^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1) // SPDX-License-Identifier: GPL-2.0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2) //
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3) // simple-card-utils.c
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4) //
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5) // Copyright (c) 2016 Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7) #include <linux/clk.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8) #include <linux/gpio.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9) #include <linux/gpio/consumer.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10) #include <linux/module.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11) #include <linux/of.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12) #include <linux/of_gpio.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13) #include <linux/of_graph.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14) #include <sound/jack.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15) #include <sound/simple_card_utils.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17) void asoc_simple_convert_fixup(struct asoc_simple_data *data,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18) struct snd_pcm_hw_params *params)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20) struct snd_interval *rate = hw_param_interval(params,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21) SNDRV_PCM_HW_PARAM_RATE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22) struct snd_interval *channels = hw_param_interval(params,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23) SNDRV_PCM_HW_PARAM_CHANNELS);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25) if (data->convert_rate)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26) rate->min =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27) rate->max = data->convert_rate;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29) if (data->convert_channels)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30) channels->min =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31) channels->max = data->convert_channels;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33) EXPORT_SYMBOL_GPL(asoc_simple_convert_fixup);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35) void asoc_simple_parse_convert(struct device *dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36) struct device_node *np,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37) char *prefix,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38) struct asoc_simple_data *data)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40) char prop[128];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42) if (!prefix)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43) prefix = "";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45) /* sampling rate convert */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46) snprintf(prop, sizeof(prop), "%s%s", prefix, "convert-rate");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47) of_property_read_u32(np, prop, &data->convert_rate);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49) /* channels transfer */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50) snprintf(prop, sizeof(prop), "%s%s", prefix, "convert-channels");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51) of_property_read_u32(np, prop, &data->convert_channels);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53) EXPORT_SYMBOL_GPL(asoc_simple_parse_convert);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55) int asoc_simple_parse_daifmt(struct device *dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56) struct device_node *node,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57) struct device_node *codec,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58) char *prefix,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59) unsigned int *retfmt)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61) struct device_node *bitclkmaster = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62) struct device_node *framemaster = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63) unsigned int daifmt;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65) daifmt = snd_soc_of_parse_daifmt(node, prefix,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66) &bitclkmaster, &framemaster);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67) daifmt &= ~SND_SOC_DAIFMT_MASTER_MASK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69) if (!bitclkmaster && !framemaster) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71) * No dai-link level and master setting was not found from
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72) * sound node level, revert back to legacy DT parsing and
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73) * take the settings from codec node.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75) dev_dbg(dev, "Revert to legacy daifmt parsing\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77) daifmt = snd_soc_of_parse_daifmt(codec, NULL, NULL, NULL) |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78) (daifmt & ~SND_SOC_DAIFMT_CLOCK_MASK);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80) if (codec == bitclkmaster)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81) daifmt |= (codec == framemaster) ?
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82) SND_SOC_DAIFMT_CBM_CFM : SND_SOC_DAIFMT_CBM_CFS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84) daifmt |= (codec == framemaster) ?
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85) SND_SOC_DAIFMT_CBS_CFM : SND_SOC_DAIFMT_CBS_CFS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88) of_node_put(bitclkmaster);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89) of_node_put(framemaster);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91) *retfmt = daifmt;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95) EXPORT_SYMBOL_GPL(asoc_simple_parse_daifmt);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97) int asoc_simple_set_dailink_name(struct device *dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98) struct snd_soc_dai_link *dai_link,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99) const char *fmt, ...)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) va_list ap;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) char *name = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) int ret = -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) va_start(ap, fmt);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) name = devm_kvasprintf(dev, GFP_KERNEL, fmt, ap);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) va_end(ap);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) if (name) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) ret = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) dai_link->name = name;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) dai_link->stream_name = name;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) EXPORT_SYMBOL_GPL(asoc_simple_set_dailink_name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) int asoc_simple_parse_card_name(struct snd_soc_card *card,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) char *prefix)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) if (!prefix)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) prefix = "";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) /* Parse the card name from DT */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) ret = snd_soc_of_parse_card_name(card, "label");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130) if (ret < 0 || !card->name) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) char prop[128];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) snprintf(prop, sizeof(prop), "%sname", prefix);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) ret = snd_soc_of_parse_card_name(card, prop);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135) if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139) if (!card->name && card->dai_link)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140) card->name = card->dai_link->name;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144) EXPORT_SYMBOL_GPL(asoc_simple_parse_card_name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146) static int asoc_simple_clk_enable(struct asoc_simple_dai *dai)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148) if (dai)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149) return clk_prepare_enable(dai->clk);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154) static void asoc_simple_clk_disable(struct asoc_simple_dai *dai)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156) if (dai)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157) clk_disable_unprepare(dai->clk);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160) int asoc_simple_parse_clk(struct device *dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161) struct device_node *node,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162) struct asoc_simple_dai *simple_dai,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163) struct snd_soc_dai_link_component *dlc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165) struct clk *clk;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166) u32 val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169) * Parse dai->sysclk come from "clocks = <&xxx>"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170) * (if system has common clock)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171) * or "system-clock-frequency = <xxx>"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172) * or device's module clock.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174) clk = devm_get_clk_from_child(dev, node, NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175) if (!IS_ERR(clk)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176) simple_dai->sysclk = clk_get_rate(clk);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178) simple_dai->clk = clk;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179) } else if (!of_property_read_u32(node, "system-clock-frequency", &val)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180) simple_dai->sysclk = val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 181) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 182) clk = devm_get_clk_from_child(dev, dlc->of_node, NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 183) if (!IS_ERR(clk))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 184) simple_dai->sysclk = clk_get_rate(clk);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 185) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 186)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 187) if (of_property_read_bool(node, "system-clock-direction-out"))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 188) simple_dai->clk_direction = SND_SOC_CLOCK_OUT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 189)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 190) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 191) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 192) EXPORT_SYMBOL_GPL(asoc_simple_parse_clk);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 193)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 194) int asoc_simple_startup(struct snd_pcm_substream *substream)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 195) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 196) struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 197) struct asoc_simple_priv *priv = snd_soc_card_get_drvdata(rtd->card);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 198) struct simple_dai_props *dai_props = simple_priv_to_props(priv, rtd->num);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 199) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 200)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 201) ret = asoc_simple_clk_enable(dai_props->cpu_dai);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 202) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 203) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 204)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 205) ret = asoc_simple_clk_enable(dai_props->codec_dai);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 206) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 207) asoc_simple_clk_disable(dai_props->cpu_dai);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 208)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 209) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 210) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 211) EXPORT_SYMBOL_GPL(asoc_simple_startup);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 212)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 213) void asoc_simple_shutdown(struct snd_pcm_substream *substream)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 214) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 215) struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 216) struct snd_soc_dai *codec_dai = asoc_rtd_to_codec(rtd, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 217) struct snd_soc_dai *cpu_dai = asoc_rtd_to_cpu(rtd, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 218) struct asoc_simple_priv *priv = snd_soc_card_get_drvdata(rtd->card);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 219) struct simple_dai_props *dai_props =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 220) simple_priv_to_props(priv, rtd->num);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 221)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 222) if (dai_props->mclk_fs) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 223) snd_soc_dai_set_sysclk(codec_dai, 0, 0, SND_SOC_CLOCK_IN);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 224) snd_soc_dai_set_sysclk(cpu_dai, 0, 0, SND_SOC_CLOCK_OUT);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 225) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 226)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 227) asoc_simple_clk_disable(dai_props->cpu_dai);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 228)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 229) asoc_simple_clk_disable(dai_props->codec_dai);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 230) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 231) EXPORT_SYMBOL_GPL(asoc_simple_shutdown);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 232)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 233) static int asoc_simple_set_clk_rate(struct asoc_simple_dai *simple_dai,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 234) unsigned long rate)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 235) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 236) if (!simple_dai)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 237) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 238)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 239) if (!simple_dai->clk)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 240) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 241)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 242) if (clk_get_rate(simple_dai->clk) == rate)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 243) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 244)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 245) return clk_set_rate(simple_dai->clk, rate);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 246) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 247)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 248) int asoc_simple_hw_params(struct snd_pcm_substream *substream,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 249) struct snd_pcm_hw_params *params)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 250) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 251) struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 252) struct snd_soc_dai *codec_dai = asoc_rtd_to_codec(rtd, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 253) struct snd_soc_dai *cpu_dai = asoc_rtd_to_cpu(rtd, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 254) struct asoc_simple_priv *priv = snd_soc_card_get_drvdata(rtd->card);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 255) struct simple_dai_props *dai_props =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 256) simple_priv_to_props(priv, rtd->num);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 257) unsigned int mclk, mclk_fs = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 258) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 259)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 260) if (dai_props->mclk_fs)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 261) mclk_fs = dai_props->mclk_fs;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 262)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 263) if (mclk_fs) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 264) mclk = params_rate(params) * mclk_fs;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 265)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 266) ret = asoc_simple_set_clk_rate(dai_props->codec_dai, mclk);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 267) if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 268) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 269)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 270) ret = asoc_simple_set_clk_rate(dai_props->cpu_dai, mclk);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 271) if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 272) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 273)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 274) ret = snd_soc_dai_set_sysclk(codec_dai, 0, mclk,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 275) SND_SOC_CLOCK_IN);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 276) if (ret && ret != -ENOTSUPP)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 277) goto err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 278)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 279) ret = snd_soc_dai_set_sysclk(cpu_dai, 0, mclk,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 280) SND_SOC_CLOCK_OUT);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 281) if (ret && ret != -ENOTSUPP)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 282) goto err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 283) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 284) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 285) err:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 286) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 287) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 288) EXPORT_SYMBOL_GPL(asoc_simple_hw_params);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 289)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 290) int asoc_simple_be_hw_params_fixup(struct snd_soc_pcm_runtime *rtd,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 291) struct snd_pcm_hw_params *params)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 292) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 293) struct asoc_simple_priv *priv = snd_soc_card_get_drvdata(rtd->card);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 294) struct simple_dai_props *dai_props = simple_priv_to_props(priv, rtd->num);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 295)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 296) asoc_simple_convert_fixup(&dai_props->adata, params);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 297)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 298) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 299) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 300) EXPORT_SYMBOL_GPL(asoc_simple_be_hw_params_fixup);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 301)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 302) static int asoc_simple_init_dai(struct snd_soc_dai *dai,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 303) struct asoc_simple_dai *simple_dai)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 304) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 305) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 306)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 307) if (!simple_dai)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 308) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 309)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 310) if (simple_dai->sysclk) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 311) ret = snd_soc_dai_set_sysclk(dai, 0, simple_dai->sysclk,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 312) simple_dai->clk_direction);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 313) if (ret && ret != -ENOTSUPP) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 314) dev_err(dai->dev, "simple-card: set_sysclk error\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 315) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 316) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 317) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 318)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 319) if (simple_dai->slots) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 320) ret = snd_soc_dai_set_tdm_slot(dai,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 321) simple_dai->tx_slot_mask,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 322) simple_dai->rx_slot_mask,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 323) simple_dai->slots,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 324) simple_dai->slot_width);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 325) if (ret && ret != -ENOTSUPP) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 326) dev_err(dai->dev, "simple-card: set_tdm_slot error\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 327) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 328) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 329) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 330)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 331) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 332) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 333)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 334) static int asoc_simple_init_dai_link_params(struct snd_soc_pcm_runtime *rtd,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 335) struct simple_dai_props *dai_props)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 336) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 337) struct snd_soc_dai_link *dai_link = rtd->dai_link;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 338) struct snd_soc_component *component;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 339) struct snd_soc_pcm_stream *params;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 340) struct snd_pcm_hardware hw;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 341) int i, ret, stream;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 342)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 343) /* Only codecs should have non_legacy_dai_naming set. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 344) for_each_rtd_components(rtd, i, component) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 345) if (!component->driver->non_legacy_dai_naming)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 346) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 347) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 348)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 349) /* Assumes the capabilities are the same for all supported streams */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 350) for_each_pcm_streams(stream) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 351) ret = snd_soc_runtime_calc_hw(rtd, &hw, stream);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 352) if (ret == 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 353) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 354) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 355)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 356) if (ret < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 357) dev_err(rtd->dev, "simple-card: no valid dai_link params\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 358) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 359) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 360)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 361) params = devm_kzalloc(rtd->dev, sizeof(*params), GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 362) if (!params)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 363) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 364)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 365) params->formats = hw.formats;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 366) params->rates = hw.rates;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 367) params->rate_min = hw.rate_min;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 368) params->rate_max = hw.rate_max;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 369) params->channels_min = hw.channels_min;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 370) params->channels_max = hw.channels_max;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 371)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 372) dai_link->params = params;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 373) dai_link->num_params = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 374)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 375) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 376) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 377)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 378) int asoc_simple_dai_init(struct snd_soc_pcm_runtime *rtd)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 379) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 380) struct asoc_simple_priv *priv = snd_soc_card_get_drvdata(rtd->card);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 381) struct simple_dai_props *dai_props = simple_priv_to_props(priv, rtd->num);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 382) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 383)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 384) ret = asoc_simple_init_dai(asoc_rtd_to_codec(rtd, 0),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 385) dai_props->codec_dai);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 386) if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 387) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 388)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 389) ret = asoc_simple_init_dai(asoc_rtd_to_cpu(rtd, 0),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 390) dai_props->cpu_dai);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 391) if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 392) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 393)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 394) ret = asoc_simple_init_dai_link_params(rtd, dai_props);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 395) if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 396) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 397)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 398) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 399) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 400) EXPORT_SYMBOL_GPL(asoc_simple_dai_init);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 401)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 402) void asoc_simple_canonicalize_platform(struct snd_soc_dai_link *dai_link)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 403) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 404) /* Assumes platform == cpu */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 405) if (!dai_link->platforms->of_node)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 406) dai_link->platforms->of_node = dai_link->cpus->of_node;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 407)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 408) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 409) * DPCM BE can be no platform.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 410) * Alloced memory will be waste, but not leak.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 411) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 412) if (!dai_link->platforms->of_node)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 413) dai_link->num_platforms = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 414) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 415) EXPORT_SYMBOL_GPL(asoc_simple_canonicalize_platform);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 416)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 417) void asoc_simple_canonicalize_cpu(struct snd_soc_dai_link *dai_link,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 418) int is_single_links)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 419) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 420) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 421) * In soc_bind_dai_link() will check cpu name after
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 422) * of_node matching if dai_link has cpu_dai_name.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 423) * but, it will never match if name was created by
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 424) * fmt_single_name() remove cpu_dai_name if cpu_args
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 425) * was 0. See:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 426) * fmt_single_name()
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 427) * fmt_multiple_name()
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 428) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 429) if (is_single_links)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 430) dai_link->cpus->dai_name = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 431) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 432) EXPORT_SYMBOL_GPL(asoc_simple_canonicalize_cpu);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 433)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 434) int asoc_simple_clean_reference(struct snd_soc_card *card)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 435) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 436) struct snd_soc_dai_link *dai_link;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 437) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 438)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 439) for_each_card_prelinks(card, i, dai_link) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 440) of_node_put(dai_link->cpus->of_node);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 441) of_node_put(dai_link->codecs->of_node);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 442) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 443) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 444) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 445) EXPORT_SYMBOL_GPL(asoc_simple_clean_reference);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 446)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 447) int asoc_simple_parse_routing(struct snd_soc_card *card,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 448) char *prefix)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 449) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 450) struct device_node *node = card->dev->of_node;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 451) char prop[128];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 452)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 453) if (!prefix)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 454) prefix = "";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 455)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 456) snprintf(prop, sizeof(prop), "%s%s", prefix, "routing");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 457)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 458) if (!of_property_read_bool(node, prop))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 459) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 460)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 461) return snd_soc_of_parse_audio_routing(card, prop);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 462) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 463) EXPORT_SYMBOL_GPL(asoc_simple_parse_routing);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 464)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 465) int asoc_simple_parse_widgets(struct snd_soc_card *card,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 466) char *prefix)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 467) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 468) struct device_node *node = card->dev->of_node;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 469) char prop[128];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 470)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 471) if (!prefix)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 472) prefix = "";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 473)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 474) snprintf(prop, sizeof(prop), "%s%s", prefix, "widgets");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 475)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 476) if (of_property_read_bool(node, prop))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 477) return snd_soc_of_parse_audio_simple_widgets(card, prop);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 478)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 479) /* no widgets is not error */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 480) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 481) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 482) EXPORT_SYMBOL_GPL(asoc_simple_parse_widgets);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 483)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 484) int asoc_simple_parse_pin_switches(struct snd_soc_card *card,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 485) char *prefix)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 486) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 487) const unsigned int nb_controls_max = 16;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 488) const char **strings, *control_name;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 489) struct snd_kcontrol_new *controls;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 490) struct device *dev = card->dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 491) unsigned int i, nb_controls;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 492) char prop[128];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 493) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 494)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 495) if (!prefix)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 496) prefix = "";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 497)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 498) snprintf(prop, sizeof(prop), "%s%s", prefix, "pin-switches");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 499)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 500) if (!of_property_read_bool(dev->of_node, prop))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 501) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 502)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 503) strings = devm_kcalloc(dev, nb_controls_max,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 504) sizeof(*strings), GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 505) if (!strings)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 506) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 507)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 508) ret = of_property_read_string_array(dev->of_node, prop,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 509) strings, nb_controls_max);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 510) if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 511) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 512)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 513) nb_controls = (unsigned int)ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 514)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 515) controls = devm_kcalloc(dev, nb_controls,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 516) sizeof(*controls), GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 517) if (!controls)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 518) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 519)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 520) for (i = 0; i < nb_controls; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 521) control_name = devm_kasprintf(dev, GFP_KERNEL,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 522) "%s Switch", strings[i]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 523) if (!control_name)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 524) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 525)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 526) controls[i].iface = SNDRV_CTL_ELEM_IFACE_MIXER;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 527) controls[i].name = control_name;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 528) controls[i].info = snd_soc_dapm_info_pin_switch;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 529) controls[i].get = snd_soc_dapm_get_pin_switch;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 530) controls[i].put = snd_soc_dapm_put_pin_switch;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 531) controls[i].private_value = (unsigned long)strings[i];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 532) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 533)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 534) card->controls = controls;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 535) card->num_controls = nb_controls;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 536)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 537) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 538) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 539) EXPORT_SYMBOL_GPL(asoc_simple_parse_pin_switches);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 540)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 541) int asoc_simple_init_jack(struct snd_soc_card *card,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 542) struct asoc_simple_jack *sjack,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 543) int is_hp, char *prefix,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 544) char *pin)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 545) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 546) struct device *dev = card->dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 547) enum of_gpio_flags flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 548) char prop[128];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 549) char *pin_name;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 550) char *gpio_name;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 551) int mask;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 552) int det;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 553)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 554) if (!prefix)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 555) prefix = "";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 556)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 557) sjack->gpio.gpio = -ENOENT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 558)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 559) if (is_hp) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 560) snprintf(prop, sizeof(prop), "%shp-det-gpio", prefix);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 561) pin_name = pin ? pin : "Headphones";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 562) gpio_name = "Headphone detection";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 563) mask = SND_JACK_HEADPHONE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 564) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 565) snprintf(prop, sizeof(prop), "%smic-det-gpio", prefix);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 566) pin_name = pin ? pin : "Mic Jack";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 567) gpio_name = "Mic detection";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 568) mask = SND_JACK_MICROPHONE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 569) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 570)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 571) det = of_get_named_gpio_flags(dev->of_node, prop, 0, &flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 572) if (det == -EPROBE_DEFER)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 573) return -EPROBE_DEFER;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 574)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 575) if (gpio_is_valid(det)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 576) sjack->pin.pin = pin_name;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 577) sjack->pin.mask = mask;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 578)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 579) sjack->gpio.name = gpio_name;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 580) sjack->gpio.report = mask;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 581) sjack->gpio.gpio = det;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 582) sjack->gpio.invert = !!(flags & OF_GPIO_ACTIVE_LOW);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 583) sjack->gpio.debounce_time = 150;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 584)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 585) snd_soc_card_jack_new(card, pin_name, mask,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 586) &sjack->jack,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 587) &sjack->pin, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 588)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 589) snd_soc_jack_add_gpios(&sjack->jack, 1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 590) &sjack->gpio);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 591) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 592)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 593) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 594) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 595) EXPORT_SYMBOL_GPL(asoc_simple_init_jack);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 596)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 597) int asoc_simple_init_priv(struct asoc_simple_priv *priv,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 598) struct link_info *li)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 599) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 600) struct snd_soc_card *card = simple_priv_to_card(priv);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 601) struct device *dev = simple_priv_to_dev(priv);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 602) struct snd_soc_dai_link *dai_link;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 603) struct simple_dai_props *dai_props;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 604) struct asoc_simple_dai *dais;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 605) struct snd_soc_codec_conf *cconf = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 606) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 607)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 608) dai_props = devm_kcalloc(dev, li->link, sizeof(*dai_props), GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 609) dai_link = devm_kcalloc(dev, li->link, sizeof(*dai_link), GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 610) dais = devm_kcalloc(dev, li->dais, sizeof(*dais), GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 611) if (!dai_props || !dai_link || !dais)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 612) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 613)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 614) if (li->conf) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 615) cconf = devm_kcalloc(dev, li->conf, sizeof(*cconf), GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 616) if (!cconf)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 617) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 618) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 619)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 620) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 621) * Use snd_soc_dai_link_component instead of legacy style
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 622) * It is codec only. but cpu/platform will be supported in the future.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 623) * see
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 624) * soc-core.c :: snd_soc_init_multicodec()
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 625) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 626) * "platform" might be removed
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 627) * see
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 628) * simple-card-utils.c :: asoc_simple_canonicalize_platform()
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 629) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 630) for (i = 0; i < li->link; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 631) dai_link[i].cpus = &dai_props[i].cpus;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 632) dai_link[i].num_cpus = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 633) dai_link[i].codecs = &dai_props[i].codecs;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 634) dai_link[i].num_codecs = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 635) dai_link[i].platforms = &dai_props[i].platforms;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 636) dai_link[i].num_platforms = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 637) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 638)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 639) priv->dai_props = dai_props;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 640) priv->dai_link = dai_link;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 641) priv->dais = dais;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 642) priv->codec_conf = cconf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 643)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 644) card->dai_link = priv->dai_link;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 645) card->num_links = li->link;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 646) card->codec_conf = cconf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 647) card->num_configs = li->conf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 648)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 649) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 650) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 651) EXPORT_SYMBOL_GPL(asoc_simple_init_priv);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 652)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 653) /* Module information */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 654) MODULE_AUTHOR("Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 655) MODULE_DESCRIPTION("ALSA SoC Simple Card Utils");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 656) MODULE_LICENSE("GPL v2");