Skip to content

Commit 90d1d08

Browse files
committed
ASoC: sdw_utils: Call init callbacks on the correct codec DAI
asoc_sdw_rtd_init() needs to call the rtd_init() callbacks for each codec in a dailink. It was finding the codecs by looking for the matching DAI name in codec_info_list[] but this is broken because the DAI name isn't guaranteed to be unique. Parts using the same codec driver (so the same DAI names) might require different machine driver setup. An array of pointers to the codec_info[] entries used to construct the dailink are saved into the private data of the dailink. Then asoc_sdw_rtd_init() can then use that array to get the correct information to initialize support for that codec. The rtd_init() callbacks in the codec_info[] array take a struct snd_soc_dai, so the codec DAIs created by ASoC must be matched up with the corresponding codec_info[] entry used to create the dailink. The DAI name cannot be used for this because multiple parts in codec_info[] could have the same DAI names. Instead, the order of codec DAI entries in struct snd_soc_pcm_runtime is expected to be the same as the order of codec DAIs in struct snd_soc_dai_link->codecs. As the order of codec DAI entries in struct snd_soc_dai_link->codecs also matches the order of their corresponding codec_info[] pointers added to the dailink private data, it follows that there is a 1:1 mapping with the order of DAIs returned by for_each_rtd_codec_dais(). In other words: dailink.codec[i] was created from endpoint[i] and dailink private dai_info[i] was created from endpoint[i].codec_info so for_each_rtd_codec_dais(..., i, ...) corresponds to endpoint[i] and dai_info[i] Change-Id: Idde610bfe8909a40b884e07801f7418c57711774 Signed-off-by: Richard Fitzgerald <rf@opensource.cirrus.com>
1 parent 29d8e5b commit 90d1d08

File tree

5 files changed

+114
-54
lines changed

5 files changed

+114
-54
lines changed

include/sound/soc_sdw_utils.h

Lines changed: 20 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -106,7 +106,7 @@ struct asoc_sdw_endpoint {
106106
bool include_sidecar;
107107

108108
struct asoc_sdw_codec_info *codec_info;
109-
const struct asoc_sdw_dai_info *dai_info;
109+
struct asoc_sdw_dai_info *dai_info;
110110
};
111111

112112
struct asoc_sdw_dailink {
@@ -118,6 +118,16 @@ struct asoc_sdw_dailink {
118118
struct list_head endpoints;
119119
};
120120

121+
struct asoc_sdw_dailink_dai_info {
122+
const struct asoc_sdw_codec_info *codec_info;
123+
struct asoc_sdw_dai_info *dai_info;
124+
};
125+
126+
struct asoc_sdw_dailink_private {
127+
int num_dai_infos;
128+
struct asoc_sdw_dailink_dai_info dai_infos[] __counted_by(num_dai_infos);
129+
};
130+
121131
extern struct asoc_sdw_codec_info codec_info_list[];
122132
int asoc_sdw_get_codec_info_list_count(void);
123133

@@ -149,14 +159,15 @@ void asoc_sdw_mc_dailink_exit_loop(struct snd_soc_card *card);
149159

150160
int asoc_sdw_card_late_probe(struct snd_soc_card *card);
151161

152-
void asoc_sdw_init_dai_link(struct device *dev, struct snd_soc_dai_link *dai_links,
153-
int *be_id, char *name, int playback, int capture,
154-
struct snd_soc_dai_link_component *cpus, int cpus_num,
155-
struct snd_soc_dai_link_component *platform_component,
156-
int num_platforms, struct snd_soc_dai_link_component *codecs,
157-
int codecs_num, int no_pcm,
158-
int (*init)(struct snd_soc_pcm_runtime *rtd),
159-
const struct snd_soc_ops *ops);
162+
int asoc_sdw_init_dai_link(struct device *dev, struct snd_soc_dai_link *dai_links,
163+
struct asoc_sdw_dailink *soc_dai,
164+
int *be_id, char *name, int playback, int capture,
165+
struct snd_soc_dai_link_component *cpus, int cpus_num,
166+
struct snd_soc_dai_link_component *platform_component,
167+
int num_platforms, struct snd_soc_dai_link_component *codecs,
168+
int codecs_num, int no_pcm,
169+
int (*init)(struct snd_soc_pcm_runtime *rtd),
170+
const struct snd_soc_ops *ops);
160171

161172
int asoc_sdw_init_simple_dai_link(struct device *dev, struct snd_soc_dai_link *dai_links,
162173
int *be_id, char *name, int playback, int capture,

sound/soc/amd/acp/acp-sdw-legacy-mach.c

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -237,10 +237,14 @@ static int create_sdw_dailink(struct snd_soc_card *card,
237237
playback = (stream == SNDRV_PCM_STREAM_PLAYBACK);
238238
capture = (stream == SNDRV_PCM_STREAM_CAPTURE);
239239

240-
asoc_sdw_init_dai_link(dev, *dai_links, be_id, name, playback, capture,
241-
cpus, num_cpus, sdw_platform_component,
242-
1, codecs, num_codecs,
243-
0, asoc_sdw_rtd_init, &sdw_ops);
240+
ret = asoc_sdw_init_dai_link(dev, *dai_links, soc_dai,
241+
be_id, name, playback, capture,
242+
cpus, num_cpus, sdw_platform_component,
243+
1, codecs, num_codecs,
244+
0, asoc_sdw_rtd_init, &sdw_ops);
245+
if (ret)
246+
return ret;
247+
244248
/*
245249
* SoundWire DAILINKs use 'stream' functions and Bank Switch operations
246250
* based on wait_for_completion(), tag them as 'nonatomic'.

sound/soc/amd/acp/acp-sdw-sof-mach.c

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -193,10 +193,13 @@ static int create_sdw_dailink(struct snd_soc_card *card,
193193
playback = (stream == SNDRV_PCM_STREAM_PLAYBACK);
194194
capture = (stream == SNDRV_PCM_STREAM_CAPTURE);
195195

196-
asoc_sdw_init_dai_link(dev, *dai_links, be_id, name, playback, capture,
197-
cpus, num_cpus, platform_component,
198-
ARRAY_SIZE(platform_component), codecs, num_codecs,
199-
1, asoc_sdw_rtd_init, &sdw_ops);
196+
ret = asoc_sdw_init_dai_link(dev, *dai_links, sof_dai,
197+
be_id, name, playback, capture,
198+
cpus, num_cpus, platform_component,
199+
ARRAY_SIZE(platform_component), codecs, num_codecs,
200+
1, asoc_sdw_rtd_init, &sdw_ops);
201+
if (ret)
202+
return ret;
200203

201204
/*
202205
* SoundWire DAILINKs use 'stream' functions and Bank Switch operations

sound/soc/intel/boards/sof_sdw.c

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -998,9 +998,12 @@ static int create_sdw_dailink(struct snd_soc_card *card,
998998
playback = (stream == SNDRV_PCM_STREAM_PLAYBACK);
999999
capture = (stream == SNDRV_PCM_STREAM_CAPTURE);
10001000

1001-
asoc_sdw_init_dai_link(dev, *dai_links, be_id, name, playback, capture,
1002-
cpus, num_cpus, platform, 1, codecs, num_codecs,
1003-
1, asoc_sdw_rtd_init, &sdw_ops);
1001+
ret = asoc_sdw_init_dai_link(dev, *dai_links, sof_dai,
1002+
be_id, name, playback, capture,
1003+
cpus, num_cpus, platform, 1, codecs, num_codecs,
1004+
1, asoc_sdw_rtd_init, &sdw_ops);
1005+
if (ret)
1006+
return ret;
10041007

10051008
/*
10061009
* SoundWire DAILINKs use 'stream' functions and Bank Switch operations

sound/soc/sdw_utils/soc_sdw_utils.c

Lines changed: 73 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -837,27 +837,36 @@ EXPORT_SYMBOL_NS(asoc_sdw_find_codec_info_dai, "SND_SOC_SDW_UTILS");
837837
int asoc_sdw_rtd_init(struct snd_soc_pcm_runtime *rtd)
838838
{
839839
struct snd_soc_card *card = rtd->card;
840-
struct asoc_sdw_codec_info *codec_info;
840+
struct asoc_sdw_dailink_private *priv;
841+
const struct asoc_sdw_codec_info *codec_info;
842+
struct asoc_sdw_dai_info *dai_info;
841843
struct snd_soc_dai *dai;
842844
const char *spk_components="";
843-
int dai_index;
844845
int ret;
845846
int i;
846847

848+
priv = snd_soc_link_get_drv_data(rtd->dai_link);
849+
if (!priv)
850+
goto skip_codec_inits;
851+
847852
for_each_rtd_codec_dais(rtd, i, dai) {
848-
codec_info = asoc_sdw_find_codec_info_dai(dai->name, &dai_index);
849-
if (!codec_info)
850-
return -EINVAL;
853+
if (i >= priv->num_dai_infos)
854+
break;
855+
856+
codec_info = priv->dai_infos[i].codec_info;
857+
dai_info = priv->dai_infos[i].dai_info;
851858

852859
/*
853860
* A codec dai can be connected to different dai links for capture and playback,
854861
* but we only need to call the rtd_init function once.
855862
* The rtd_init for each codec dai is independent. So, the order of rtd_init
856863
* doesn't matter.
857864
*/
858-
if (codec_info->dais[dai_index].rtd_init_done)
865+
if (dai_info->rtd_init_done)
859866
continue;
860867

868+
dev_dbg(rtd->dev, "%#x/%s: Creating controls\n",
869+
codec_info->part_id, dai_info->dai_name);
861870
/*
862871
* Add card controls and dapm widgets for the first codec dai.
863872
* The controls and widgets will be used for all codec dais.
@@ -866,19 +875,19 @@ int asoc_sdw_rtd_init(struct snd_soc_pcm_runtime *rtd)
866875
if (i > 0)
867876
goto skip_add_controls_widgets;
868877

869-
if (codec_info->dais[dai_index].controls) {
870-
ret = snd_soc_add_card_controls(card, codec_info->dais[dai_index].controls,
871-
codec_info->dais[dai_index].num_controls);
878+
if (dai_info->controls) {
879+
ret = snd_soc_add_card_controls(card, dai_info->controls,
880+
dai_info->num_controls);
872881
if (ret) {
873882
dev_err(card->dev, "%#x controls addition failed: %d\n",
874883
codec_info->part_id, ret);
875884
return ret;
876885
}
877886
}
878-
if (codec_info->dais[dai_index].widgets) {
887+
if (dai_info->widgets) {
879888
ret = snd_soc_dapm_new_controls(&card->dapm,
880-
codec_info->dais[dai_index].widgets,
881-
codec_info->dais[dai_index].num_widgets);
889+
dai_info->widgets,
890+
dai_info->num_widgets);
882891
if (ret) {
883892
dev_err(card->dev, "%#x widgets addition failed: %d\n",
884893
codec_info->part_id, ret);
@@ -887,31 +896,34 @@ int asoc_sdw_rtd_init(struct snd_soc_pcm_runtime *rtd)
887896
}
888897

889898
skip_add_controls_widgets:
890-
if (codec_info->dais[dai_index].rtd_init) {
891-
ret = codec_info->dais[dai_index].rtd_init(rtd, dai);
899+
if (dai_info->rtd_init) {
900+
dev_dbg(rtd->dev, "%#x/%s: rtd_init for DAI %s/%s\n",
901+
codec_info->part_id, dai_info->dai_name,
902+
dai->component->name, dai->name);
903+
904+
ret = dai_info->rtd_init(rtd, dai);
892905
if (ret)
893906
return ret;
894907
}
895908

896909
/* Generate the spk component string for card->components string */
897-
if (codec_info->dais[dai_index].dai_type == SOC_SDW_DAI_TYPE_AMP &&
898-
codec_info->dais[dai_index].component_name) {
910+
if (dai_info->dai_type == SOC_SDW_DAI_TYPE_AMP && dai_info->component_name) {
899911
if (strlen (spk_components) == 0)
900912
spk_components =
901913
devm_kasprintf(card->dev, GFP_KERNEL, "%s",
902-
codec_info->dais[dai_index].component_name);
914+
dai_info->component_name);
903915
else
904916
/* Append component name to spk_components */
905917
spk_components =
906918
devm_kasprintf(card->dev, GFP_KERNEL,
907919
"%s+%s", spk_components,
908-
codec_info->dais[dai_index].component_name);
920+
dai_info->component_name);
909921
}
910922

911-
codec_info->dais[dai_index].rtd_init_done = true;
912-
923+
dai_info->rtd_init_done = true;
913924
}
914925

926+
skip_codec_inits:
915927
if (strlen (spk_components) > 0) {
916928
/* Update card components for speaker components */
917929
card->components = devm_kasprintf(card->dev, GFP_KERNEL, "%s spk:%s",
@@ -1194,15 +1206,21 @@ int asoc_sdw_card_late_probe(struct snd_soc_card *card)
11941206
}
11951207
EXPORT_SYMBOL_NS(asoc_sdw_card_late_probe, "SND_SOC_SDW_UTILS");
11961208

1197-
void asoc_sdw_init_dai_link(struct device *dev, struct snd_soc_dai_link *dai_links,
1198-
int *be_id, char *name, int playback, int capture,
1199-
struct snd_soc_dai_link_component *cpus, int cpus_num,
1200-
struct snd_soc_dai_link_component *platform_component,
1201-
int num_platforms, struct snd_soc_dai_link_component *codecs,
1202-
int codecs_num, int no_pcm,
1203-
int (*init)(struct snd_soc_pcm_runtime *rtd),
1204-
const struct snd_soc_ops *ops)
1209+
int asoc_sdw_init_dai_link(struct device *dev, struct snd_soc_dai_link *dai_links,
1210+
struct asoc_sdw_dailink *soc_dai,
1211+
int *be_id, char *name, int playback, int capture,
1212+
struct snd_soc_dai_link_component *cpus, int cpus_num,
1213+
struct snd_soc_dai_link_component *platform_component,
1214+
int num_platforms, struct snd_soc_dai_link_component *codecs,
1215+
int codecs_num, int no_pcm,
1216+
int (*init)(struct snd_soc_pcm_runtime *rtd),
1217+
const struct snd_soc_ops *ops)
12051218
{
1219+
struct asoc_sdw_dailink_private *priv;
1220+
int num_endpoints;
1221+
struct asoc_sdw_endpoint *endpoint;
1222+
int i;
1223+
12061224
dev_dbg(dev, "create dai link %s, id %d\n", name, *be_id);
12071225
dai_links->id = (*be_id)++;
12081226
dai_links->name = name;
@@ -1218,6 +1236,29 @@ void asoc_sdw_init_dai_link(struct device *dev, struct snd_soc_dai_link *dai_lin
12181236
dai_links->capture_only = !playback && capture;
12191237
dai_links->init = init;
12201238
dai_links->ops = ops;
1239+
1240+
if (!soc_dai)
1241+
return 0;
1242+
1243+
num_endpoints = list_count_nodes(&soc_dai->endpoints);
1244+
WARN_ON(num_endpoints != dai_links->num_codecs);
1245+
1246+
priv = devm_kzalloc(dev, struct_size(priv, dai_infos, num_endpoints),
1247+
GFP_KERNEL);
1248+
if (!priv)
1249+
return -ENOMEM;
1250+
1251+
priv->num_dai_infos = num_endpoints;
1252+
i = 0;
1253+
list_for_each_entry(endpoint, &soc_dai->endpoints, list) {
1254+
priv->dai_infos[i].codec_info = endpoint->codec_info;
1255+
priv->dai_infos[i].dai_info = endpoint->dai_info;
1256+
i++;
1257+
}
1258+
1259+
snd_soc_link_set_drv_data(dai_links, priv);
1260+
1261+
return 0;
12211262
}
12221263
EXPORT_SYMBOL_NS(asoc_sdw_init_dai_link, "SND_SOC_SDW_UTILS");
12231264

@@ -1241,11 +1282,9 @@ int asoc_sdw_init_simple_dai_link(struct device *dev, struct snd_soc_dai_link *d
12411282
dlc[2].name = codec_name;
12421283
dlc[2].dai_name = codec_dai_name;
12431284

1244-
asoc_sdw_init_dai_link(dev, dai_links, be_id, name, playback, capture,
1245-
&dlc[0], 1, &dlc[1], 1, &dlc[2], 1,
1246-
no_pcm, init, ops);
1247-
1248-
return 0;
1285+
return asoc_sdw_init_dai_link(dev, dai_links, NULL, be_id, name, playback, capture,
1286+
&dlc[0], 1, &dlc[1], 1, &dlc[2], 1,
1287+
no_pcm, init, ops);
12491288
}
12501289
EXPORT_SYMBOL_NS(asoc_sdw_init_simple_dai_link, "SND_SOC_SDW_UTILS");
12511290

@@ -1463,7 +1502,7 @@ int asoc_sdw_parse_sdw_endpoints(struct snd_soc_card *card,
14631502

14641503
for (j = 0; j < adr_dev->num_endpoints; j++) {
14651504
const struct snd_soc_acpi_endpoint *adr_end;
1466-
const struct asoc_sdw_dai_info *dai_info;
1505+
struct asoc_sdw_dai_info *dai_info;
14671506
struct asoc_sdw_dailink *soc_dai;
14681507
int stream;
14691508

0 commit comments

Comments
 (0)