Message ID | 87r0rep4we.wl-kuninori.morimoto.gx@renesas.com |
---|---|
State | New |
Headers | show |
Series | ASoC: replace dpcm_playback/capture to playback/capture_only | expand |
On 5/18/2023 7:47 AM, Kuninori Morimoto wrote: > Current soc_get_playback_capture() (A) is checking playback/capture > availability for DPCM (X) / Normal (Y) / Codec2Codec (Z) connections. > > (A) static int soc_get_playback_capture(...) > { > ... > ^ if (dai_link->dynamic || dai_link->no_pcm) { > | ... > |(a) if (dai_link->dpcm_playback) { > | ... > | ^ for_each_rtd_cpu_dais(rtd, i, cpu_dai) { > |(*) ... > | v } > | ... > (X) } > |(b) if (dai_link->dpcm_capture) { > | ... > | ^ for_each_rtd_cpu_dais(rtd, i, cpu_dai) { > |(*) ... > | v } > | ... > v } > } else { > ^ ^ /* Adapt stream for codec2codec links */ > |(Z) int cpu_capture = ... > | v int cpu_playback = ... > (Y) > | ^ for_each_rtd_codec_dais(rtd, i, codec_dai) { > |(*) ... > v v } > } > ... > } > > (*) part is checking each DAI's availability. > > At first, (X) part is for DPCM, and it checks playback/capture > availability if dai_link has dpcm_playback/capture flag (a)(b). > But we are already using playback/capture_only flag. > for Normal (Y) and Codec2Codec (Z). We can use this flags for DPCM too. > > Before After > dpcm_playback = 1; => /* no flags */ > dpcm_capture = 1; > > dpcm_playback = 1; => playback_only = 1; > > dpcm_capture = 1; => capture_only = 1; > > This patch enables both flags case, but dpcm_playback/capture flags > will be removed if all driver were switched to new playback/capture_only > flags. > > Here, CPU <-> Codec relationship is like this > > DPCM > [CPU/dummy]-[dummy/Codec] > ^^^^^^^^^^^ > Normal > [CPU/Codec] > ^^^^^^^^^^^ > > (X) part is checking only CPU DAI, and > (Y) part is checking both CPU/Codec DAI > > This means (X)/(Y) are checking same position. > Because dammy DAI is always available, > we can share same code for all cases (= X/Y/Z). > > This patch merge these. > > Signed-off-by: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com> > --- Reviewed-by: Amadeusz Sławiński <amadeuszx.slawinski@linux.intel.com>
On 5/18/2023 7:47 AM, Kuninori Morimoto wrote: > Current soc_get_playback_capture() (A) is checking playback/capture > availability for DPCM (X) / Normal (Y) / Codec2Codec (Z) connections. > > (A) static int soc_get_playback_capture(...) > { > ... > ^ if (dai_link->dynamic || dai_link->no_pcm) { > | ... > |(a) if (dai_link->dpcm_playback) { > | ... > | ^ for_each_rtd_cpu_dais(rtd, i, cpu_dai) { > |(*) ... > | v } > | ... > (X) } > |(b) if (dai_link->dpcm_capture) { > | ... > | ^ for_each_rtd_cpu_dais(rtd, i, cpu_dai) { > |(*) ... > | v } > | ... > v } > } else { > ^ ^ /* Adapt stream for codec2codec links */ > |(Z) int cpu_capture = ... > | v int cpu_playback = ... > (Y) > | ^ for_each_rtd_codec_dais(rtd, i, codec_dai) { > |(*) ... > v v } > } > ... > } > > (*) part is checking each DAI's availability. > > At first, (X) part is for DPCM, and it checks playback/capture > availability if dai_link has dpcm_playback/capture flag (a)(b). > But we are already using playback/capture_only flag. > for Normal (Y) and Codec2Codec (Z). We can use this flags for DPCM too. > > Before After > dpcm_playback = 1; => /* no flags */ > dpcm_capture = 1; > > dpcm_playback = 1; => playback_only = 1; > > dpcm_capture = 1; => capture_only = 1; > > This patch enables both flags case, but dpcm_playback/capture flags > will be removed if all driver were switched to new playback/capture_only > flags. > > Here, CPU <-> Codec relationship is like this > > DPCM > [CPU/dummy]-[dummy/Codec] > ^^^^^^^^^^^ > Normal > [CPU/Codec] > ^^^^^^^^^^^ > > (X) part is checking only CPU DAI, and > (Y) part is checking both CPU/Codec DAI > > This means (X)/(Y) are checking same position. > Because dammy DAI is always available, > we can share same code for all cases (= X/Y/Z). > > This patch merge these. > > Signed-off-by: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com> > --- > sound/soc/soc-pcm.c | 75 +++++++++++++-------------------------------- > 1 file changed, 22 insertions(+), 53 deletions(-) > > diff --git a/sound/soc/soc-pcm.c b/sound/soc/soc-pcm.c > index af5d4e1effdf..f47ddf660c57 100644 > --- a/sound/soc/soc-pcm.c > +++ b/sound/soc/soc-pcm.c > @@ -2732,7 +2732,10 @@ static int soc_get_playback_capture(struct snd_soc_pcm_runtime *rtd, > int *playback, int *capture) > { > struct snd_soc_dai_link *dai_link = rtd->dai_link; > + struct snd_soc_dai *codec_dai; > struct snd_soc_dai *cpu_dai; > + int cpu_capture = SNDRV_PCM_STREAM_CAPTURE; > + int cpu_playback = SNDRV_PCM_STREAM_PLAYBACK; > int tmp_playback = 0; > int tmp_capture = 0; > int i; > @@ -2748,61 +2751,27 @@ static int soc_get_playback_capture(struct snd_soc_pcm_runtime *rtd, > return -EINVAL; > } > > - if (dai_link->dynamic || dai_link->no_pcm) { > - int stream; > - > - if (dai_link->dpcm_playback) { > - stream = SNDRV_PCM_STREAM_PLAYBACK; > + /* Adapt stream for codec2codec links */ > + if (dai_link->c2c_params) { > + cpu_capture = SNDRV_PCM_STREAM_PLAYBACK; > + cpu_playback = SNDRV_PCM_STREAM_CAPTURE; > + } > > - for_each_rtd_cpu_dais(rtd, i, cpu_dai) { > - if (snd_soc_dai_stream_valid(cpu_dai, stream)) { > - tmp_playback = 1; > - break; > - } > - } > - if (!tmp_playback) { > - dev_err(rtd->card->dev, > - "No CPU DAIs support playback for stream %s\n", > - dai_link->stream_name); > - return -EINVAL; > - } > - } > - if (dai_link->dpcm_capture) { > - stream = SNDRV_PCM_STREAM_CAPTURE; > + /* REMOVE ME */ > + if (dai_link->dpcm_playback && !dai_link->dpcm_capture) > + dai_link->playback_only = 1; > + if (!dai_link->dpcm_playback && dai_link->dpcm_capture) > + dai_link->capture_only = 1; > > - for_each_rtd_cpu_dais(rtd, i, cpu_dai) { > - if (snd_soc_dai_stream_valid(cpu_dai, stream)) { > - tmp_capture = 1; > - break; > - } > - } > - > - if (!tmp_capture) { > - dev_err(rtd->card->dev, > - "No CPU DAIs support capture for stream %s\n", > - dai_link->stream_name); > - return -EINVAL; > - } > - } > - } else { > - struct snd_soc_dai *codec_dai; > - > - /* Adapt stream for codec2codec links */ > - int cpu_capture = dai_link->c2c_params ? > - SNDRV_PCM_STREAM_PLAYBACK : SNDRV_PCM_STREAM_CAPTURE; > - int cpu_playback = dai_link->c2c_params ? > - SNDRV_PCM_STREAM_CAPTURE : SNDRV_PCM_STREAM_PLAYBACK; > - > - for_each_rtd_codec_dais(rtd, i, codec_dai) { > - cpu_dai = asoc_rtd_to_cpu(rtd, i); > - > - if (snd_soc_dai_stream_valid(codec_dai, SNDRV_PCM_STREAM_PLAYBACK) && > - snd_soc_dai_stream_valid(cpu_dai, cpu_playback)) > - tmp_playback = 1; > - if (snd_soc_dai_stream_valid(codec_dai, SNDRV_PCM_STREAM_CAPTURE) && > - snd_soc_dai_stream_valid(cpu_dai, cpu_capture)) > - tmp_capture = 1; > - } > + for_each_rtd_cpu_dais(rtd, i, cpu_dai) { > + codec_dai = asoc_rtd_to_codec(rtd, i); /* get paired codec */ > + > + if (snd_soc_dai_stream_valid(codec_dai, SNDRV_PCM_STREAM_PLAYBACK) && > + snd_soc_dai_stream_valid(cpu_dai, cpu_playback)) > + tmp_playback = 1; > + if (snd_soc_dai_stream_valid(codec_dai, SNDRV_PCM_STREAM_CAPTURE) && > + snd_soc_dai_stream_valid(cpu_dai, cpu_capture)) > + tmp_capture = 1; > } > > if (dai_link->playback_only) I put the patchset to test and it fails to enumerate devices on our platforms. Bisect leads me to this patch, here is dmesg fragment: [ 34.609909] snd_soc_avs:avs_component_probe: avs_hdaudio avs_hdaudio.2: probing hdaudioB0D2-platform card hdaudioB0D2 [ 34.612274] snd_soc_core:soc_tplg_load_header: avs_hdaudio avs_hdaudio.2: ASoC: Got 0x490 bytes of type 8 version 0 vendor 0 at pass 0 [ 34.612456] snd_soc_core:soc_tplg_load_header: avs_hdaudio avs_hdaudio.2: ASoC: Got 0x7ec bytes of type 5 version 0 vendor 0 at pass 3 [ 34.612477] snd_soc_core:soc_tplg_dapm_widget_elems_load: avs_hdaudio avs_hdaudio.2: ASoC: adding 6 DAPM widgets [ 34.612493] snd_soc_core:soc_tplg_dapm_widget_create: avs_hdaudio avs_hdaudio.2: ASoC: creating DAPM widget hdmi1_fe id 17 [ 34.612774] snd_soc_core:soc_tplg_dapm_widget_create: avs_hdaudio avs_hdaudio.2: ASoC: creating DAPM widget hdmi1_be id 17 [ 34.613025] snd_soc_core:soc_tplg_dapm_widget_create: avs_hdaudio avs_hdaudio.2: ASoC: creating DAPM widget hdmi2_fe id 17 [ 34.613297] snd_soc_core:soc_tplg_dapm_widget_create: avs_hdaudio avs_hdaudio.2: ASoC: creating DAPM widget hdmi2_be id 17 [ 34.613552] snd_soc_core:soc_tplg_dapm_widget_create: avs_hdaudio avs_hdaudio.2: ASoC: creating DAPM widget hdmi3_fe id 17 [ 34.613823] snd_soc_core:soc_tplg_dapm_widget_create: avs_hdaudio avs_hdaudio.2: ASoC: creating DAPM widget hdmi3_be id 17 [ 34.614077] snd_soc_core:soc_tplg_load_header: avs_hdaudio avs_hdaudio.2: ASoC: Got 0xab0 bytes of type 7 version 0 vendor 0 at pass 4 [ 34.614272] snd_soc_core:snd_soc_register_dai: snd_soc_avs 0000:00:0e.0: ASoC: Registered DAI 'HDMI1-dai' [ 34.614290] snd_soc_core:snd_soc_dapm_new_dai_widgets: snd_soc_avs 0000:00:0e.0: ASoC: adding HDMI1-playback widget [ 34.614453] snd_soc_core:snd_soc_add_pcm_runtime: avs_hdaudio avs_hdaudio.2: ASoC: binding HDMI1 [ 34.615192] snd_soc_core:snd_soc_register_dai: snd_soc_avs 0000:00:0e.0: ASoC: Registered DAI 'HDMI2-dai' [ 34.615210] snd_soc_core:snd_soc_dapm_new_dai_widgets: snd_soc_avs 0000:00:0e.0: ASoC: adding HDMI2-playback widget [ 34.615371] snd_soc_core:snd_soc_add_pcm_runtime: avs_hdaudio avs_hdaudio.2: ASoC: binding HDMI2 [ 34.616060] snd_soc_core:snd_soc_register_dai: snd_soc_avs 0000:00:0e.0: ASoC: Registered DAI 'HDMI3-dai' [ 34.616077] snd_soc_core:snd_soc_dapm_new_dai_widgets: snd_soc_avs 0000:00:0e.0: ASoC: adding HDMI3-playback widget [ 34.616235] snd_soc_core:snd_soc_add_pcm_runtime: avs_hdaudio avs_hdaudio.2: ASoC: binding HDMI3 [ 34.616858] snd_soc_core:soc_tplg_pcm_elems_load: avs_hdaudio avs_hdaudio.2: ASoC: adding 3 PCM DAIs [ 34.616876] snd_soc_core:soc_tplg_load_header: avs_hdaudio avs_hdaudio.2: ASoC: Got 0x4a4 bytes of type 4 version 0 vendor 0 at pass 5 [ 34.616895] snd_soc_core:soc_tplg_dapm_graph_elems_load: avs_hdaudio avs_hdaudio.2: ASoC: adding 9 DAPM routes for index 0 [ 34.617601] avs_hdaudio avs_hdaudio.2: ASoC: Parent card not yet available, widget card binding deferred [ 34.618153] snd_soc_core:snd_soc_add_pcm_runtime: avs_hdaudio avs_hdaudio.2: ASoC: binding hdaudioB0D2 link0 [ 34.618724] snd_soc_core:snd_soc_add_pcm_runtime: avs_hdaudio avs_hdaudio.2: ASoC: binding hdaudioB0D2 link1 [ 34.619221] snd_soc_core:snd_soc_add_pcm_runtime: avs_hdaudio avs_hdaudio.2: ASoC: binding hdaudioB0D2 link2 [ 34.619973] probing-LINK: substream (null) has no playback, no capture [ 34.620016] avs_hdaudio avs_hdaudio.2: ASoC: can't create pcm (null) :-22 [ 34.620196] snd_soc_core:snd_soc_unregister_dai: snd_soc_avs 0000:00:0e.0: ASoC: Unregistered DAI 'hdaudioB0D2-cpu0' [ 34.620309] snd_soc_core:snd_soc_unregister_dai: snd_soc_avs 0000:00:0e.0: ASoC: Unregistered DAI 'hdaudioB0D2-cpu1' [ 34.620419] snd_soc_core:snd_soc_unregister_dai: snd_soc_avs 0000:00:0e.0: ASoC: Unregistered DAI 'hdaudioB0D2-cpu2' [ 34.621254] snd_soc_core:snd_soc_unregister_dai: snd_soc_avs 0000:00:0e.0: ASoC: Unregistered DAI 'HDMI3-dai' [ 34.621837] snd_soc_core:snd_soc_unregister_dai: snd_soc_avs 0000:00:0e.0: ASoC: Unregistered DAI 'HDMI2-dai' [ 34.622704] snd_soc_core:snd_soc_unregister_dai: snd_soc_avs 0000:00:0e.0: ASoC: Unregistered DAI 'HDMI1-dai' [ 34.623620] snd_soc_core:snd_soc_unregister_dai: snd_hda_codec_hdmi hdaudioB0D2: ASoC: Unregistered DAI 'HDMI 0' [ 34.623695] snd_soc_core:snd_soc_unregister_dai: snd_hda_codec_hdmi hdaudioB0D2: ASoC: Unregistered DAI 'HDMI 1' [ 34.623769] snd_soc_core:snd_soc_unregister_dai: snd_hda_codec_hdmi hdaudioB0D2: ASoC: Unregistered DAI 'HDMI 2' [ 34.624779] snd_hda_core:snd_hdac_display_power: snd_soc_avs 0000:00:0e.0: display power disable [ 34.628057] avs_hdaudio: probe of avs_hdaudio.2 failed with error -22
Hi Amadeusz Thank you for testing > I put the patchset to test and it fails to enumerate devices on our > platforms. > > Bisect leads me to this patch, here is dmesg fragment: (snip) > [ 34.617601] avs_hdaudio avs_hdaudio.2: ASoC: Parent card not yet > available, widget card binding deferred (snip) > [ 34.619973] probing-LINK: substream (null) has no playback, no capture Hmm.. I tested it on my many type of connections, but couldn't reproduce the error... It seems you got [01/20] patch error = no playback, no capture. This means has_playback/capture both flags are 0. It seems you are using soc-topology. Is it topology specific something ? But hmm.. ? static int soc_get_playback_capture(...) { ... (A) if (dai_link->dynamic || dai_link->no_pcm) { ... if (dai_link->dpcm_playback) { ... (B) for_each_rtd_cpu_dais(rtd, i, cpu_dai) { ... } ... } if (dai_link->dpcm_capture) { ... (B) for_each_rtd_cpu_dais(rtd, i, cpu_dai) { ... } } ... } } It checks CPU (B) when no_pcm (A) on original. But I think "no_pcm - CPU" is dummy DAI -> above check is no meaning. After the patch, it checks both CPU/Codec. I wonder is your Codec which is connected to no_pcm DAI valid ? Thank you for your help !! Best regards --- Kuninori Morimoto
On 5/22/2023 6:35 AM, Kuninori Morimoto wrote: > > Hi Amadeusz > > Thank you for testing > >> I put the patchset to test and it fails to enumerate devices on our >> platforms. >> >> Bisect leads me to this patch, here is dmesg fragment: > (snip) >> [ 34.617601] avs_hdaudio avs_hdaudio.2: ASoC: Parent card not yet >> available, widget card binding deferred > (snip) >> [ 34.619973] probing-LINK: substream (null) has no playback, no capture > > Hmm.. I tested it on my many type of connections, > but couldn't reproduce the error... > > It seems you got [01/20] patch error = no playback, no capture. > This means has_playback/capture both flags are 0. > > It seems you are using soc-topology. > Is it topology specific something ? > > But hmm.. ? > > static int soc_get_playback_capture(...) > { > ... > (A) if (dai_link->dynamic || dai_link->no_pcm) { > ... > if (dai_link->dpcm_playback) { > ... > (B) for_each_rtd_cpu_dais(rtd, i, cpu_dai) { > ... > } > ... > } > if (dai_link->dpcm_capture) { > ... > (B) for_each_rtd_cpu_dais(rtd, i, cpu_dai) { > ... > } > } > ... > } > } > > It checks CPU (B) when no_pcm (A) on original. > But I think "no_pcm - CPU" is dummy DAI -> above check is no meaning. > After the patch, it checks both CPU/Codec. no_pcm means that we are describing Back End, if you check any file in sound/soc/intel/avs/boards, they set link->no_pcm to 1 - those files describe card and BE (codec) configuration. Topology in case of our driver describe Front Ends (what is visible when you do "aplay -l"), as well as DSP path. Topology sets link->dynamic to 1 in soc_tplg_fe_link_create(). Do note that card and topology are loaded separately hence the "card binding deferred" message in dmesg above. > I wonder is your Codec which is connected to no_pcm DAI valid ? > I'm not sure what do you mean, if it is valid? It works fine before this patch ;)
Hi Amadeusz > > static int soc_get_playback_capture(...) > > { > > ... > > (A) if (dai_link->dynamic || dai_link->no_pcm) { > > ... > > if (dai_link->dpcm_playback) { > > ... > > (B) for_each_rtd_cpu_dais(rtd, i, cpu_dai) { > > ... > > } > > ... > > } > > if (dai_link->dpcm_capture) { > > ... > > (B) for_each_rtd_cpu_dais(rtd, i, cpu_dai) { > > ... > > } > > } > > ... > > } > > } > > > > It checks CPU (B) when no_pcm (A) on original. > > But I think "no_pcm - CPU" is dummy DAI -> above check is no meaning. > > After the patch, it checks both CPU/Codec. (snip) > > I wonder is your Codec which is connected to no_pcm DAI valid ? > > I'm not sure what do you mean, if it is valid? It works fine before this > patch ;) Ah, sorry, let me explain detail. static int soc_get_playback_capture(...) { ... (A) if (dai_link->dynamic || dai_link->no_pcm) { int stream; if (dai_link->dpcm_playback) { stream = SNDRV_PCM_STREAM_PLAYBACK; (B) for_each_rtd_cpu_dais(rtd, i, cpu_dai) { (C) if (snd_soc_dai_stream_valid(cpu_dai, stream)) { has_playback = 1; break; } } ... } Before appling the patch, in DPCM case (A), it checks CPU valid only (B)/(C). In many case, DPCM is like this dynamic no_pcm [CPU/dummy-Codec] - [dummy-CPU/Codec] I noticed that before the patch, it checks dummy DAI only for no_pcm case. But after appling the patch, it will check both CPU and Codec valid (X)/(Y)/(Z). I think this was changed after patch. So, my question was what happen for snd_soc_dai_stream_valid() on your Codec. # I notcied that avs_create_dai_links() is not using dummy CPU on no_pcm case... static int soc_get_playback_capture(...) { ... (X) for_each_rtd_cpu_dais(rtd, i, cpu_dai) { (Y) codec_dai = asoc_rtd_to_codec(rtd, i); /* get paired codec */ (Z) if (snd_soc_dai_stream_valid(codec_dai, SNDRV_PCM_STREAM_PLAYBACK) && (Z) snd_soc_dai_stream_valid(cpu_dai, cpu_playback)) has_playback = 1; (Z) if (snd_soc_dai_stream_valid(codec_dai, SNDRV_PCM_STREAM_CAPTURE) && (Z) snd_soc_dai_stream_valid(cpu_dai, cpu_capture)) has_capture = 1; } ... } Thank you for your help !! Best regards --- Kuninori Morimoto
Hi Amadeusz Cc Mark Thank you for debuging/checking. > > I noticed that before the patch, it checks dummy DAI only for no_pcm case. > > But after appling the patch, it will check both CPU and Codec > > valid (X)/(Y)/(Z). (snip) > sorry for small delay, I've debugged the issue. Seems like one less > critical problem is in ASoC HDA codec, which blocks HDA and HDMI probing > altogether in our driver, something like this should fix this: (snip) > @@ -341,6 +341,8 @@ static const struct snd_soc_dapm_widget > hda_dapm_widgets[] = { > static struct snd_soc_dai_driver card_binder_dai = { > .id = -1, > .name = "codec-probing-DAI", > + .capture.channels_min = 1, > + .playback.channels_min = 1, > }; (snip) > and it works for testing purposes, but as commented in code, those > fields are initialized later (in hdmi_pcm_open()), which apparently in > case of ASoC binding is too late. Likely those assignments need to be > moved earlier. > > Another thing that should probably be done is some kind of look through > ASoC codec files to make sure that they all define channels_min > properly, otherwise there may be more unexpected failures. Hmm... >From logic point of view, I think we need to check all validation. But from compatible point of view, we want to skip validation check for BE Codec... Especially, quick hack solution (= adding channels_min in many place) might case other bug I guess. OK, let's skip BE Codec in v2 for now. Thank you for your help !! Best regards --- Kuninori Morimoto
diff --git a/sound/soc/soc-pcm.c b/sound/soc/soc-pcm.c index af5d4e1effdf..f47ddf660c57 100644 --- a/sound/soc/soc-pcm.c +++ b/sound/soc/soc-pcm.c @@ -2732,7 +2732,10 @@ static int soc_get_playback_capture(struct snd_soc_pcm_runtime *rtd, int *playback, int *capture) { struct snd_soc_dai_link *dai_link = rtd->dai_link; + struct snd_soc_dai *codec_dai; struct snd_soc_dai *cpu_dai; + int cpu_capture = SNDRV_PCM_STREAM_CAPTURE; + int cpu_playback = SNDRV_PCM_STREAM_PLAYBACK; int tmp_playback = 0; int tmp_capture = 0; int i; @@ -2748,61 +2751,27 @@ static int soc_get_playback_capture(struct snd_soc_pcm_runtime *rtd, return -EINVAL; } - if (dai_link->dynamic || dai_link->no_pcm) { - int stream; - - if (dai_link->dpcm_playback) { - stream = SNDRV_PCM_STREAM_PLAYBACK; + /* Adapt stream for codec2codec links */ + if (dai_link->c2c_params) { + cpu_capture = SNDRV_PCM_STREAM_PLAYBACK; + cpu_playback = SNDRV_PCM_STREAM_CAPTURE; + } - for_each_rtd_cpu_dais(rtd, i, cpu_dai) { - if (snd_soc_dai_stream_valid(cpu_dai, stream)) { - tmp_playback = 1; - break; - } - } - if (!tmp_playback) { - dev_err(rtd->card->dev, - "No CPU DAIs support playback for stream %s\n", - dai_link->stream_name); - return -EINVAL; - } - } - if (dai_link->dpcm_capture) { - stream = SNDRV_PCM_STREAM_CAPTURE; + /* REMOVE ME */ + if (dai_link->dpcm_playback && !dai_link->dpcm_capture) + dai_link->playback_only = 1; + if (!dai_link->dpcm_playback && dai_link->dpcm_capture) + dai_link->capture_only = 1; - for_each_rtd_cpu_dais(rtd, i, cpu_dai) { - if (snd_soc_dai_stream_valid(cpu_dai, stream)) { - tmp_capture = 1; - break; - } - } - - if (!tmp_capture) { - dev_err(rtd->card->dev, - "No CPU DAIs support capture for stream %s\n", - dai_link->stream_name); - return -EINVAL; - } - } - } else { - struct snd_soc_dai *codec_dai; - - /* Adapt stream for codec2codec links */ - int cpu_capture = dai_link->c2c_params ? - SNDRV_PCM_STREAM_PLAYBACK : SNDRV_PCM_STREAM_CAPTURE; - int cpu_playback = dai_link->c2c_params ? - SNDRV_PCM_STREAM_CAPTURE : SNDRV_PCM_STREAM_PLAYBACK; - - for_each_rtd_codec_dais(rtd, i, codec_dai) { - cpu_dai = asoc_rtd_to_cpu(rtd, i); - - if (snd_soc_dai_stream_valid(codec_dai, SNDRV_PCM_STREAM_PLAYBACK) && - snd_soc_dai_stream_valid(cpu_dai, cpu_playback)) - tmp_playback = 1; - if (snd_soc_dai_stream_valid(codec_dai, SNDRV_PCM_STREAM_CAPTURE) && - snd_soc_dai_stream_valid(cpu_dai, cpu_capture)) - tmp_capture = 1; - } + for_each_rtd_cpu_dais(rtd, i, cpu_dai) { + codec_dai = asoc_rtd_to_codec(rtd, i); /* get paired codec */ + + if (snd_soc_dai_stream_valid(codec_dai, SNDRV_PCM_STREAM_PLAYBACK) && + snd_soc_dai_stream_valid(cpu_dai, cpu_playback)) + tmp_playback = 1; + if (snd_soc_dai_stream_valid(codec_dai, SNDRV_PCM_STREAM_CAPTURE) && + snd_soc_dai_stream_valid(cpu_dai, cpu_capture)) + tmp_capture = 1; } if (dai_link->playback_only)
Current soc_get_playback_capture() (A) is checking playback/capture availability for DPCM (X) / Normal (Y) / Codec2Codec (Z) connections. (A) static int soc_get_playback_capture(...) { ... ^ if (dai_link->dynamic || dai_link->no_pcm) { | ... |(a) if (dai_link->dpcm_playback) { | ... | ^ for_each_rtd_cpu_dais(rtd, i, cpu_dai) { |(*) ... | v } | ... (X) } |(b) if (dai_link->dpcm_capture) { | ... | ^ for_each_rtd_cpu_dais(rtd, i, cpu_dai) { |(*) ... | v } | ... v } } else { ^ ^ /* Adapt stream for codec2codec links */ |(Z) int cpu_capture = ... | v int cpu_playback = ... (Y) | ^ for_each_rtd_codec_dais(rtd, i, codec_dai) { |(*) ... v v } } ... } (*) part is checking each DAI's availability. At first, (X) part is for DPCM, and it checks playback/capture availability if dai_link has dpcm_playback/capture flag (a)(b). But we are already using playback/capture_only flag. for Normal (Y) and Codec2Codec (Z). We can use this flags for DPCM too. Before After dpcm_playback = 1; => /* no flags */ dpcm_capture = 1; dpcm_playback = 1; => playback_only = 1; dpcm_capture = 1; => capture_only = 1; This patch enables both flags case, but dpcm_playback/capture flags will be removed if all driver were switched to new playback/capture_only flags. Here, CPU <-> Codec relationship is like this DPCM [CPU/dummy]-[dummy/Codec] ^^^^^^^^^^^ Normal [CPU/Codec] ^^^^^^^^^^^ (X) part is checking only CPU DAI, and (Y) part is checking both CPU/Codec DAI This means (X)/(Y) are checking same position. Because dammy DAI is always available, we can share same code for all cases (= X/Y/Z). This patch merge these. Signed-off-by: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com> --- sound/soc/soc-pcm.c | 75 +++++++++++++-------------------------------- 1 file changed, 22 insertions(+), 53 deletions(-)