Some DAIs have multiple system clock sources, which can be chosen using the "clk_id" argument to snd_soc_dai_set_sysclk(). Currently this is hardcoded to 0 when using simple cards, but that choice is not always suitable.
Add the "system-clock-id" property to allow selecting a different clock ID on a per-DAI basis.
To simplify the logic on DPCM cards, add a dummy "asoc_simple_dai" instance and use that for the dummy components on DPCM links. This ensures that when we're iterating over DAIs in the PCM runtime there is always a matching "asoc_simple_dai" we can dereference.
Signed-off-by: Aidan MacDonald aidanmacdonald.0x0@gmail.com --- include/sound/simple_card_utils.h | 2 ++ sound/soc/generic/simple-card-utils.c | 26 ++++++++++++++++++++------ 2 files changed, 22 insertions(+), 6 deletions(-)
diff --git a/include/sound/simple_card_utils.h b/include/sound/simple_card_utils.h index a0b827f0c2f6..9f9a72299637 100644 --- a/include/sound/simple_card_utils.h +++ b/include/sound/simple_card_utils.h @@ -26,6 +26,7 @@ struct asoc_simple_dai { const char *name; unsigned int sysclk; int clk_direction; + int sysclk_id; int slots; int slot_width; unsigned int tx_slot_mask; @@ -67,6 +68,7 @@ struct asoc_simple_priv { struct prop_nums num; unsigned int mclk_fs; } *dai_props; + struct asoc_simple_dai dummy_dai; struct asoc_simple_jack hp_jack; struct asoc_simple_jack mic_jack; struct snd_soc_dai_link *dai_link; diff --git a/sound/soc/generic/simple-card-utils.c b/sound/soc/generic/simple-card-utils.c index bef16833c487..d4d898e06e76 100644 --- a/sound/soc/generic/simple-card-utils.c +++ b/sound/soc/generic/simple-card-utils.c @@ -262,6 +262,9 @@ int asoc_simple_parse_clk(struct device *dev, if (of_property_read_bool(node, "system-clock-direction-out")) simple_dai->clk_direction = SND_SOC_CLOCK_OUT;
+ if (!of_property_read_u32(node, "system-clock-id", &val)) + simple_dai->sysclk_id = val; + return 0; } EXPORT_SYMBOL_GPL(asoc_simple_parse_clk); @@ -355,7 +358,7 @@ void asoc_simple_shutdown(struct snd_pcm_substream *substream)
if (props->mclk_fs && !dai->clk_fixed && !snd_soc_dai_active(cpu_dai)) snd_soc_dai_set_sysclk(cpu_dai, - 0, 0, SND_SOC_CLOCK_OUT); + dai->sysclk_id, 0, SND_SOC_CLOCK_OUT);
asoc_simple_clk_disable(dai); } @@ -364,7 +367,7 @@ void asoc_simple_shutdown(struct snd_pcm_substream *substream)
if (props->mclk_fs && !dai->clk_fixed && !snd_soc_dai_active(codec_dai)) snd_soc_dai_set_sysclk(codec_dai, - 0, 0, SND_SOC_CLOCK_IN); + dai->sysclk_id, 0, SND_SOC_CLOCK_IN);
asoc_simple_clk_disable(dai); } @@ -439,7 +442,7 @@ int asoc_simple_hw_params(struct snd_pcm_substream *substream, struct asoc_simple_priv *priv = snd_soc_card_get_drvdata(rtd->card); struct simple_dai_props *props = simple_priv_to_props(priv, rtd->num); unsigned int mclk, mclk_fs = 0; - int i, ret; + int i, ret, sysclk_id;
if (props->mclk_fs) mclk_fs = props->mclk_fs; @@ -472,13 +475,21 @@ int asoc_simple_hw_params(struct snd_pcm_substream *substream, }
for_each_rtd_codec_dais(rtd, i, sdai) { - ret = snd_soc_dai_set_sysclk(sdai, 0, mclk, SND_SOC_CLOCK_IN); + pdai = simple_props_to_dai_codec(props, i); + sysclk_id = pdai->sysclk_id; + + ret = snd_soc_dai_set_sysclk(sdai, sysclk_id, mclk, + SND_SOC_CLOCK_IN); if (ret && ret != -ENOTSUPP) return ret; }
for_each_rtd_cpu_dais(rtd, i, sdai) { - ret = snd_soc_dai_set_sysclk(sdai, 0, mclk, SND_SOC_CLOCK_OUT); + pdai = simple_props_to_dai_cpu(props, i); + sysclk_id = pdai->sysclk_id; + + ret = snd_soc_dai_set_sysclk(sdai, pdai->sysclk_id, mclk, + SND_SOC_CLOCK_OUT); if (ret && ret != -ENOTSUPP) return ret; } @@ -523,7 +534,8 @@ static int asoc_simple_init_dai(struct snd_soc_dai *dai, return 0;
if (simple_dai->sysclk) { - ret = snd_soc_dai_set_sysclk(dai, 0, simple_dai->sysclk, + ret = snd_soc_dai_set_sysclk(dai, simple_dai->sysclk_id, + simple_dai->sysclk, simple_dai->clk_direction); if (ret && ret != -ENOTSUPP) { dev_err(dai->dev, "simple-card: set_sysclk error\n"); @@ -858,6 +870,7 @@ int asoc_simple_init_priv(struct asoc_simple_priv *priv, dai_link[i].cpus = &priv->dummy; dai_props[i].num.cpus = dai_link[i].num_cpus = 1; + dai_props[i].cpu_dai = &priv->dummy_dai; }
if (li->num[i].codecs) { @@ -882,6 +895,7 @@ int asoc_simple_init_priv(struct asoc_simple_priv *priv, dai_link[i].codecs = &priv->dummy; dai_props[i].num.codecs = dai_link[i].num_codecs = 1; + dai_props[i].codec_dai = &priv->dummy_dai; }
if (li->num[i].platforms) {