Unverified Commit bb29a33c authored by Pierre-Louis Bossart's avatar Pierre-Louis Bossart Committed by Mark Brown
Browse files

ASoC: soc-acpi: move link_slaves_found()



Move existing function in common library to make sure the code can be
reused by other SoC vendors.

No functionality change outside of the move and added prefix.

Signed-off-by: default avatarPierre-Louis Bossart <pierre-louis.bossart@linux.intel.com>
Reviewed-by: default avatarRander Wang <rander.wang@intel.com>
Reviewed-by: default avatarBard Liao <yung-chuan.liao@linux.intel.com>
Link: https://lore.kernel.org/r/20230731213242.434594-3-pierre-louis.bossart@linux.intel.com


Signed-off-by: default avatarMark Brown <broonie@kernel.org>
parent 799d9933
Loading
Loading
Loading
Loading
+5 −0
Original line number Diff line number Diff line
@@ -482,6 +482,11 @@ struct sdw_slave_id {
	__u8 sdw_version:4;
};

struct sdw_extended_slave_id {
	int link_id;
	struct sdw_slave_id id;
};

/*
 * Helper macros to extract the MIPI-defined IDs
 *
+1 −6
Original line number Diff line number Diff line
@@ -264,11 +264,6 @@ struct sdw_intel_link_dev;
 */
#define SDW_INTEL_CLK_STOP_BUS_RESET		BIT(3)

struct sdw_intel_slave_id {
	int link_id;
	struct sdw_slave_id id;
};

struct hdac_bus;

/**
@@ -298,7 +293,7 @@ struct sdw_intel_ctx {
	int num_slaves;
	acpi_handle handle;
	struct sdw_intel_link_dev **ldev;
	struct sdw_intel_slave_id *ids;
	struct sdw_extended_slave_id *ids;
	struct list_head link_list;
	struct mutex shim_lock; /* lock for access to shared SHIM registers */
	u32 shim_mask;
+6 −0
Original line number Diff line number Diff line
@@ -9,6 +9,7 @@
#include <linux/stddef.h>
#include <linux/acpi.h>
#include <linux/mod_devicetable.h>
#include <linux/soundwire/sdw.h>

struct snd_soc_acpi_package_context {
	char *name;           /* package name */
@@ -208,4 +209,9 @@ static inline bool snd_soc_acpi_sof_parent(struct device *dev)
		!strncmp(dev->parent->driver->name, "sof-audio-acpi", strlen("sof-audio-acpi"));
}

bool snd_soc_acpi_sdw_link_slaves_found(struct device *dev,
					const struct snd_soc_acpi_link_adr *link,
					struct sdw_extended_slave_id *ids,
					int num_slaves);

#endif
+73 −0
Original line number Diff line number Diff line
@@ -125,5 +125,78 @@ struct snd_soc_acpi_mach *snd_soc_acpi_codec_list(void *arg)
}
EXPORT_SYMBOL_GPL(snd_soc_acpi_codec_list);

#define SDW_CODEC_ADR_MASK(_adr) ((_adr) & (SDW_DISCO_LINK_ID_MASK | SDW_VERSION_MASK | \
				  SDW_MFG_ID_MASK | SDW_PART_ID_MASK))

/* Check if all Slaves defined on the link can be found */
bool snd_soc_acpi_sdw_link_slaves_found(struct device *dev,
					const struct snd_soc_acpi_link_adr *link,
					struct sdw_extended_slave_id *ids,
					int num_slaves)
{
	unsigned int part_id, link_id, unique_id, mfg_id, version;
	int i, j, k;

	for (i = 0; i < link->num_adr; i++) {
		u64 adr = link->adr_d[i].adr;
		int reported_part_count = 0;

		mfg_id = SDW_MFG_ID(adr);
		part_id = SDW_PART_ID(adr);
		link_id = SDW_DISCO_LINK_ID(adr);
		version = SDW_VERSION(adr);

		for (j = 0; j < num_slaves; j++) {
			/* find out how many identical parts were reported on that link */
			if (ids[j].link_id == link_id &&
			    ids[j].id.part_id == part_id &&
			    ids[j].id.mfg_id == mfg_id &&
			    ids[j].id.sdw_version == version)
				reported_part_count++;
		}

		for (j = 0; j < num_slaves; j++) {
			int expected_part_count = 0;

			if (ids[j].link_id != link_id ||
			    ids[j].id.part_id != part_id ||
			    ids[j].id.mfg_id != mfg_id ||
			    ids[j].id.sdw_version != version)
				continue;

			/* find out how many identical parts are expected */
			for (k = 0; k < link->num_adr; k++) {
				u64 adr2 = link->adr_d[k].adr;

				if (SDW_CODEC_ADR_MASK(adr2) == SDW_CODEC_ADR_MASK(adr))
					expected_part_count++;
			}

			if (reported_part_count == expected_part_count) {
				/*
				 * we have to check unique id
				 * if there is more than one
				 * Slave on the link
				 */
				unique_id = SDW_UNIQUE_ID(adr);
				if (reported_part_count == 1 ||
				    ids[j].id.unique_id == unique_id) {
					dev_dbg(dev, "found %x at link %d\n", part_id, link_id);
					break;
				}
			} else {
				dev_dbg(dev, "part %x reported %d expected %d on link %d, skipping\n",
					part_id, reported_part_count, expected_part_count, link_id);
			}
		}
		if (j == num_slaves) {
			dev_dbg(dev, "Slave %x not found\n", part_id);
			return false;
		}
	}
	return true;
}
EXPORT_SYMBOL_GPL(snd_soc_acpi_sdw_link_slaves_found);

MODULE_LICENSE("GPL v2");
MODULE_DESCRIPTION("ALSA SoC ACPI module");
+3 −73
Original line number Diff line number Diff line
@@ -1429,78 +1429,6 @@ static void hda_generic_machine_select(struct snd_sof_dev *sdev,

#if IS_ENABLED(CONFIG_SND_SOC_SOF_INTEL_SOUNDWIRE)

#define SDW_CODEC_ADR_MASK(_adr) ((_adr) & (SDW_DISCO_LINK_ID_MASK | SDW_VERSION_MASK | \
				  SDW_MFG_ID_MASK | SDW_PART_ID_MASK))

/* Check if all Slaves defined on the link can be found */
static bool link_slaves_found(struct device *dev,
			      const struct snd_soc_acpi_link_adr *link,
			      struct sdw_intel_slave_id *ids,
			      int num_slaves)
{
	unsigned int part_id, link_id, unique_id, mfg_id, version;
	int i, j, k;

	for (i = 0; i < link->num_adr; i++) {
		u64 adr = link->adr_d[i].adr;
		int reported_part_count = 0;

		mfg_id = SDW_MFG_ID(adr);
		part_id = SDW_PART_ID(adr);
		link_id = SDW_DISCO_LINK_ID(adr);
		version = SDW_VERSION(adr);

		for (j = 0; j < num_slaves; j++) {
			/* find out how many identical parts were reported on that link */
			if (ids[j].link_id == link_id &&
			    ids[j].id.part_id == part_id &&
			    ids[j].id.mfg_id == mfg_id &&
			    ids[j].id.sdw_version == version)
				reported_part_count++;
		}

		for (j = 0; j < num_slaves; j++) {
			int expected_part_count = 0;

			if (ids[j].link_id != link_id ||
			    ids[j].id.part_id != part_id ||
			    ids[j].id.mfg_id != mfg_id ||
			    ids[j].id.sdw_version != version)
				continue;

			/* find out how many identical parts are expected */
			for (k = 0; k < link->num_adr; k++) {
				u64 adr2 = link->adr_d[k].adr;

				if (SDW_CODEC_ADR_MASK(adr2) == SDW_CODEC_ADR_MASK(adr))
					expected_part_count++;
			}

			if (reported_part_count == expected_part_count) {
				/*
				 * we have to check unique id
				 * if there is more than one
				 * Slave on the link
				 */
				unique_id = SDW_UNIQUE_ID(adr);
				if (reported_part_count == 1 ||
				    ids[j].id.unique_id == unique_id) {
					dev_dbg(dev, "found %x at link %d\n", part_id, link_id);
					break;
				}
			} else {
				dev_dbg(dev, "part %x reported %d expected %d on link %d, skipping\n",
					part_id, reported_part_count, expected_part_count, link_id);
			}
		}
		if (j == num_slaves) {
			dev_dbg(dev, "Slave %x not found\n", part_id);
			return false;
		}
	}
	return true;
}

static struct snd_soc_acpi_mach *hda_sdw_machine_select(struct snd_sof_dev *sdev)
{
	struct snd_sof_pdata *pdata = sdev->pdata;
@@ -1544,7 +1472,9 @@ static struct snd_soc_acpi_mach *hda_sdw_machine_select(struct snd_sof_dev *sdev
				 * Try next machine if any expected Slaves
				 * are not found on this link.
				 */
				if (!link_slaves_found(sdev->dev, link, hdev->sdw->ids, hdev->sdw->num_slaves))
				if (!snd_soc_acpi_sdw_link_slaves_found(sdev->dev, link,
									hdev->sdw->ids,
									hdev->sdw->num_slaves))
					break;
			}
			/* Found if all Slaves are checked */