summaryrefslogtreecommitdiff
path: root/sound
diff options
context:
space:
mode:
authorBard Liao <yung-chuan.liao@linux.intel.com>2023-04-19 14:55:23 -0500
committerMark Brown <broonie@kernel.org>2023-04-20 12:51:53 +0100
commitc8db7b50128b8cc61a5ca6e4717cf8158fca302a (patch)
treeb00dd6ac172724c54eca72b08e5a0b9b07f95d7d /sound
parent16373f30777f45823fa68e850b230fa2ef9d7e92 (diff)
downloadlinux-c8db7b50128b8cc61a5ca6e4717cf8158fca302a.tar.gz
ASoC: Intel: sof_sdw: support different devices on the same sdw link
The existing code assumes all devices on the same soundwire link are the same devices. eg. all rt1316. This commit removes the assumption and supports different devices on the same soundwire link. Signed-off-by: Bard Liao <yung-chuan.liao@linux.intel.com> Signed-off-by: Pierre-Louis Bossart <pierre-louis.bossart@linux.intel.com> Reviewed-by: Rander Wang <rander.wang@intel.com> Link: https://lore.kernel.org/r/20230419195524.46995-7-pierre-louis.bossart@linux.intel.com Signed-off-by: Mark Brown <broonie@kernel.org>
Diffstat (limited to 'sound')
-rw-r--r--sound/soc/intel/boards/sof_sdw.c130
1 files changed, 77 insertions, 53 deletions
diff --git a/sound/soc/intel/boards/sof_sdw.c b/sound/soc/intel/boards/sof_sdw.c
index e5729df4fd44..6a6c81df72bd 100644
--- a/sound/soc/intel/boards/sof_sdw.c
+++ b/sound/soc/intel/boards/sof_sdw.c
@@ -732,34 +732,36 @@ static int get_sdw_dailink_info(struct device *dev, const struct snd_soc_acpi_li
int stream;
u64 adr;
- adr = link->adr_d->adr;
- codec_index = find_codec_info_part(adr);
- if (codec_index < 0)
- return codec_index;
+ for (i = 0; i < link->num_adr; i++) {
+ adr = link->adr_d[i].adr;
+ codec_index = find_codec_info_part(adr);
+ if (codec_index < 0)
+ return codec_index;
- if (codec_info_list[codec_index].codec_type < _codec_type)
- dev_warn(dev,
- "Unexpected address table ordering. Expected order: jack -> amp -> mic\n");
+ if (codec_info_list[codec_index].codec_type < _codec_type)
+ dev_warn(dev,
+ "Unexpected address table ordering. Expected order: jack -> amp -> mic\n");
- _codec_type = codec_info_list[codec_index].codec_type;
+ _codec_type = codec_info_list[codec_index].codec_type;
- endpoint = link->adr_d->endpoints;
+ endpoint = link->adr_d[i].endpoints;
- /* count DAI number for playback and capture */
- for_each_pcm_streams(stream) {
- if (!codec_info_list[codec_index].direction[stream])
- continue;
+ /* count DAI number for playback and capture */
+ for_each_pcm_streams(stream) {
+ if (!codec_info_list[codec_index].direction[stream])
+ continue;
- (*sdw_cpu_dai_num)++;
+ (*sdw_cpu_dai_num)++;
- /* count BE for each non-aggregated slave or group */
- if (!endpoint->aggregated || no_aggregation ||
- !group_visited[endpoint->group_id])
- (*sdw_be_num)++;
- }
+ /* count BE for each non-aggregated slave or group */
+ if (!endpoint->aggregated || no_aggregation ||
+ !group_visited[endpoint->group_id])
+ (*sdw_be_num)++;
+ }
- if (endpoint->aggregated)
- group_visited[endpoint->group_id] = true;
+ if (endpoint->aggregated)
+ group_visited[endpoint->group_id] = true;
+ }
}
return 0;
@@ -829,17 +831,19 @@ static int create_codec_dai_name(struct device *dev,
int offset,
struct snd_soc_codec_conf *codec_conf,
int codec_count,
- int *codec_conf_index)
+ int *codec_conf_index,
+ int adr_index)
{
+ int _codec_index = -1;
int i;
/* sanity check */
- if (*codec_conf_index + link->num_adr > codec_count) {
+ if (*codec_conf_index + link->num_adr - adr_index > codec_count) {
dev_err(dev, "codec_conf: out-of-bounds access requested\n");
return -EINVAL;
}
- for (i = 0; i < link->num_adr; i++) {
+ for (i = adr_index; i < link->num_adr; i++) {
unsigned int sdw_version, unique_id, mfg_id;
unsigned int link_id, part_id, class_id;
int codec_index, comp_index;
@@ -855,7 +859,7 @@ static int create_codec_dai_name(struct device *dev,
part_id = SDW_PART_ID(adr);
class_id = SDW_CLASS_ID(adr);
- comp_index = i + offset;
+ comp_index = i - adr_index + offset;
if (is_unique_device(link, sdw_version, mfg_id, part_id,
class_id, i)) {
codec_str = "sdw:%01x:%04x:%04x:%02x";
@@ -877,6 +881,11 @@ static int create_codec_dai_name(struct device *dev,
codec_index = find_codec_info_part(adr);
if (codec_index < 0)
return codec_index;
+ if (_codec_index != -1 && codec_index != _codec_index) {
+ dev_dbg(dev, "Different devices on the same sdw link\n");
+ break;
+ }
+ _codec_index = codec_index;
codec[comp_index].dai_name =
codec_info_list[codec_index].dai_name;
@@ -943,16 +952,16 @@ static int set_codec_init_func(struct snd_soc_card *card,
static int get_slave_info(const struct snd_soc_acpi_link_adr *adr_link,
struct device *dev, int *cpu_dai_id, int *cpu_dai_num,
int *codec_num, unsigned int *group_id,
- bool *group_generated)
+ bool *group_generated, int adr_index)
{
const struct snd_soc_acpi_adr_device *adr_d;
const struct snd_soc_acpi_link_adr *adr_next;
bool no_aggregation;
int index = 0;
+ int i;
no_aggregation = sof_sdw_quirk & SOF_SDW_NO_AGGREGATION;
- *codec_num = adr_link->num_adr;
- adr_d = adr_link->adr_d;
+ adr_d = &adr_link->adr_d[adr_index];
/* make sure the link mask has a single bit set */
if (!is_power_of_2(adr_link->mask))
@@ -968,6 +977,14 @@ static int get_slave_info(const struct snd_soc_acpi_link_adr *adr_link,
*group_id = adr_d->endpoints->group_id;
+ /* Count endpoints with the same group_id in the adr_link */
+ *codec_num = 0;
+ for (i = 0; i < adr_link->num_adr; i++) {
+ if (adr_link->adr_d[i].endpoints->aggregated &&
+ adr_link->adr_d[i].endpoints->group_id == *group_id)
+ (*codec_num)++;
+ }
+
/* gather other link ID of slaves in the same group */
for (adr_next = adr_link + 1; adr_next && adr_next->num_adr;
adr_next++) {
@@ -988,7 +1005,11 @@ static int get_slave_info(const struct snd_soc_acpi_link_adr *adr_link,
}
cpu_dai_id[index++] = ffs(adr_next->mask) - 1;
- *codec_num += adr_next->num_adr;
+ for (i = 0; i < adr_next->num_adr; i++) {
+ if (adr_next->adr_d[i].endpoints->aggregated &&
+ adr_next->adr_d[i].endpoints->group_id == *group_id)
+ (*codec_num)++;
+ }
}
/*
@@ -1011,7 +1032,8 @@ static int create_sdw_dailink(struct snd_soc_card *card,
struct snd_soc_codec_conf *codec_conf,
int codec_count, int *link_id,
int *codec_conf_index,
- bool *ignore_pch_dmic)
+ bool *ignore_pch_dmic,
+ int adr_index)
{
const struct snd_soc_acpi_link_adr *link_next;
struct snd_soc_dai_link_component *codecs;
@@ -1027,7 +1049,7 @@ static int create_sdw_dailink(struct snd_soc_card *card,
int k;
ret = get_slave_info(link, dev, cpu_dai_id, &cpu_dai_num, &codec_num,
- &group_id, group_generated);
+ &group_id, group_generated, adr_index);
if (ret)
return ret;
@@ -1050,7 +1072,7 @@ static int create_sdw_dailink(struct snd_soc_card *card,
continue;
ret = create_codec_dai_name(dev, link_next, codecs, codec_idx,
- codec_conf, codec_count, codec_conf_index);
+ codec_conf, codec_count, codec_conf_index, adr_index);
if (ret < 0)
return ret;
@@ -1060,7 +1082,7 @@ static int create_sdw_dailink(struct snd_soc_card *card,
}
/* find codec info to create BE DAI */
- codec_index = find_codec_info_part(link->adr_d[0].adr);
+ codec_index = find_codec_info_part(link->adr_d[adr_index].adr);
if (codec_index < 0)
return codec_index;
@@ -1303,29 +1325,31 @@ static int sof_card_dai_links_create(struct device *dev,
/* generate DAI links by each sdw link */
for (; adr_link->num_adr; adr_link++) {
- const struct snd_soc_acpi_endpoint *endpoint;
+ for (i = 0; i < adr_link->num_adr; i++) {
+ const struct snd_soc_acpi_endpoint *endpoint;
- endpoint = adr_link->adr_d->endpoints;
- if (endpoint->aggregated && !endpoint->group_id) {
- dev_err(dev, "invalid group id on link %x",
- adr_link->mask);
- continue;
- }
+ endpoint = adr_link->adr_d[i].endpoints;
+ if (endpoint->aggregated && !endpoint->group_id) {
+ dev_err(dev, "invalid group id on link %x",
+ adr_link->mask);
+ continue;
+ }
- /* this group has been generated */
- if (endpoint->aggregated &&
- group_generated[endpoint->group_id])
- continue;
+ /* this group has been generated */
+ if (endpoint->aggregated &&
+ group_generated[endpoint->group_id])
+ continue;
- ret = create_sdw_dailink(card, dev, &link_index, links, sdw_be_num,
- sdw_cpu_dai_num, cpus, adr_link,
- &cpu_id, group_generated,
- codec_conf, codec_conf_count,
- &be_id, &codec_conf_index,
- &ignore_pch_dmic);
- if (ret < 0) {
- dev_err(dev, "failed to create dai link %d", link_index);
- return ret;
+ ret = create_sdw_dailink(card, dev, &link_index, links, sdw_be_num,
+ sdw_cpu_dai_num, cpus, adr_link,
+ &cpu_id, group_generated,
+ codec_conf, codec_conf_count,
+ &be_id, &codec_conf_index,
+ &ignore_pch_dmic, i);
+ if (ret < 0) {
+ dev_err(dev, "failed to create dai link %d", link_index);
+ return ret;
+ }
}
}