From ba9e82a1c8919340bee0dd7f7cafb8749810aabe Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Thu, 27 May 2021 11:26:12 +0900 Subject: ASoC: soc-core: add snd_soc_runtime_get_dai_fmt() ASoC is using dai_link which specify DAI format (= dai_link->dai_fmt), and it is selected by "Sound Card" driver in corrent implementation. In other words, Sound Card *needs* to setup it. But, it should be possible to automatically selected from CPU and Codec driver settings. This patch adds new .auto_selectable_formats support at snd_soc_dai_ops. By this patch, dai_fmt can be automatically selected from each driver if both CPU / Codec driver had it. Automatically selectable *field* is depends on each drivers. For example, some driver want to select format "automatically", but want to select other fields "manually", because of complex limitation. Or other example, in case of both CPU and Codec are possible to be clock provider, but the quality was different. In these case, user need/want to *manually* select each fields from Sound Card driver. This .auto_selectable_formats can set priority. For example, no limitaion format can be HI priority, supported but has picky limitation format can be next priority, etc. It uses Sound Card specified fields preferentially, and try to select non-specific fields from CPU and Codec driver automatically if all drivers have .auto_selectable_formats. In other words, we can select all dai_fmt via Sound Card driver same as before. Link: https://lore.kernel.org/r/871rb3hypy.wl-kuninori.morimoto.gx@renesas.com Link: https://lore.kernel.org/r/871racbx0w.wl-kuninori.morimoto.gx@renesas.com Signed-off-by: Kuninori Morimoto Link: https://lore.kernel.org/r/87h7ionc8s.wl-kuninori.morimoto.gx@renesas.com Signed-off-by: Mark Brown --- sound/soc/soc-dai.c | 63 +++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 63 insertions(+) (limited to 'sound/soc/soc-dai.c') diff --git a/sound/soc/soc-dai.c b/sound/soc/soc-dai.c index 4df1aae8abf3..a56dcc8d6fb7 100644 --- a/sound/soc/soc-dai.c +++ b/sound/soc/soc-dai.c @@ -134,6 +134,69 @@ int snd_soc_dai_set_bclk_ratio(struct snd_soc_dai *dai, unsigned int ratio) } EXPORT_SYMBOL_GPL(snd_soc_dai_set_bclk_ratio); +int snd_soc_dai_get_fmt_max_priority(struct snd_soc_pcm_runtime *rtd) +{ + struct snd_soc_dai *dai; + int i, max = 0; + + /* + * return max num if *ALL* DAIs have .auto_selectable_formats + */ + for_each_rtd_dais(rtd, i, dai) { + if (dai->driver->ops && + dai->driver->ops->num_auto_selectable_formats) + max = max(max, dai->driver->ops->num_auto_selectable_formats); + else + return 0; + } + + return max; +} + +/** + * snd_soc_dai_get_fmt - get supported audio format. + * @dai: DAI + * @priority: priority level of supported audio format. + * + * This should return only formats implemented with high + * quality by the DAI so that the core can configure a + * format which will work well with other devices. + * For example devices which don't support both edges of the + * LRCLK signal in I2S style formats should only list DSP + * modes. This will mean that sometimes fewer formats + * are reported here than are supported by set_fmt(). + */ +u64 snd_soc_dai_get_fmt(struct snd_soc_dai *dai, int priority) +{ + const struct snd_soc_dai_ops *ops = dai->driver->ops; + u64 fmt = 0; + int i, max = 0, until = priority; + + /* + * Collect auto_selectable_formats until priority + * + * ex) + * auto_selectable_formats[] = { A, B, C }; + * (A, B, C = SND_SOC_POSSIBLE_DAIFMT_xxx) + * + * priority = 1 : A + * priority = 2 : A | B + * priority = 3 : A | B | C + * priority = 4 : A | B | C + * ... + */ + if (ops) + max = ops->num_auto_selectable_formats; + + if (max < until) + until = max; + + for (i = 0; i < until; i++) + fmt |= ops->auto_selectable_formats[i]; + + return fmt; +} + /** * snd_soc_dai_set_fmt - configure DAI hardware audio format. * @dai: DAI -- cgit v1.2.3-70-g09d2