Lines Matching +full:dai +full:- +full:tdm +full:- +full:slot +full:- +full:width +full:- +full:map

1 // SPDX-License-Identifier: GPL-2.0
3 // simple-card-utils.c
35 if (!strcmp(data->convert_sample_format, in asoc_simple_fixup_sample_fmt()
54 snprintf(prop, sizeof(prop), "%s%s", prefix, "convert-rate"); in asoc_simple_parse_convert()
55 of_property_read_u32(np, prop, &data->convert_rate); in asoc_simple_parse_convert()
58 snprintf(prop, sizeof(prop), "%s%s", prefix, "convert-channels"); in asoc_simple_parse_convert()
59 of_property_read_u32(np, prop, &data->convert_channels); in asoc_simple_parse_convert()
62 snprintf(prop, sizeof(prop), "%s%s", prefix, "convert-sample-format"); in asoc_simple_parse_convert()
63 of_property_read_string(np, prop, &data->convert_sample_format); in asoc_simple_parse_convert()
68 * asoc_simple_is_convert_required() - Query if HW param conversion was requested
71 * Returns true if any HW param conversion was requested for this DAI link with
72 * any "convert-xxx" properties.
76 return data->convert_rate || in asoc_simple_is_convert_required()
77 data->convert_channels || in asoc_simple_is_convert_required()
78 data->convert_sample_format; in asoc_simple_is_convert_required()
97 * No dai-link level and master setting was not found from in asoc_simple_parse_daifmt()
119 struct asoc_simple_dai *dai) in asoc_simple_parse_tdm_width_map() argument
124 if (!of_property_read_bool(np, "dai-tdm-slot-width-map")) in asoc_simple_parse_tdm_width_map()
127 n = of_property_count_elems_of_size(np, "dai-tdm-slot-width-map", sizeof(u32)); in asoc_simple_parse_tdm_width_map()
129 dev_err(dev, "Invalid number of cells for dai-tdm-slot-width-map\n"); in asoc_simple_parse_tdm_width_map()
130 return -EINVAL; in asoc_simple_parse_tdm_width_map()
133 dai->tdm_width_map = devm_kcalloc(dev, n, sizeof(*dai->tdm_width_map), GFP_KERNEL); in asoc_simple_parse_tdm_width_map()
134 if (!dai->tdm_width_map) in asoc_simple_parse_tdm_width_map()
135 return -ENOMEM; in asoc_simple_parse_tdm_width_map()
139 return -ENOMEM; in asoc_simple_parse_tdm_width_map()
141 ret = of_property_read_u32_array(np, "dai-tdm-slot-width-map", array_values, n); in asoc_simple_parse_tdm_width_map()
143 dev_err(dev, "Could not read dai-tdm-slot-width-map: %d\n", ret); in asoc_simple_parse_tdm_width_map()
149 dai->tdm_width_map[i].sample_bits = *p++; in asoc_simple_parse_tdm_width_map()
150 dai->tdm_width_map[i].slot_width = *p++; in asoc_simple_parse_tdm_width_map()
151 dai->tdm_width_map[i].slot_count = *p++; in asoc_simple_parse_tdm_width_map()
154 dai->n_tdm_widths = i; in asoc_simple_parse_tdm_width_map()
169 int ret = -ENOMEM; in asoc_simple_set_dailink_name()
178 dai_link->name = name; in asoc_simple_set_dailink_name()
179 dai_link->stream_name = name; in asoc_simple_set_dailink_name()
196 if (ret < 0 || !card->name) { in asoc_simple_parse_card_name()
205 if (!card->name && card->dai_link) in asoc_simple_parse_card_name()
206 card->name = card->dai_link->name; in asoc_simple_parse_card_name()
212 static int asoc_simple_clk_enable(struct asoc_simple_dai *dai) in asoc_simple_clk_enable() argument
214 if (dai) in asoc_simple_clk_enable()
215 return clk_prepare_enable(dai->clk); in asoc_simple_clk_enable()
220 static void asoc_simple_clk_disable(struct asoc_simple_dai *dai) in asoc_simple_clk_disable() argument
222 if (dai) in asoc_simple_clk_disable()
223 clk_disable_unprepare(dai->clk); in asoc_simple_clk_disable()
235 * Parse dai->sysclk come from "clocks = <&xxx>" in asoc_simple_parse_clk()
237 * or "system-clock-frequency = <xxx>" in asoc_simple_parse_clk()
241 simple_dai->clk_fixed = of_property_read_bool( in asoc_simple_parse_clk()
242 node, "system-clock-fixed"); in asoc_simple_parse_clk()
244 simple_dai->sysclk = clk_get_rate(clk); in asoc_simple_parse_clk()
246 simple_dai->clk = clk; in asoc_simple_parse_clk()
247 } else if (!of_property_read_u32(node, "system-clock-frequency", &val)) { in asoc_simple_parse_clk()
248 simple_dai->sysclk = val; in asoc_simple_parse_clk()
249 simple_dai->clk_fixed = true; in asoc_simple_parse_clk()
251 clk = devm_get_clk_from_child(dev, dlc->of_node, NULL); in asoc_simple_parse_clk()
253 simple_dai->sysclk = clk_get_rate(clk); in asoc_simple_parse_clk()
256 if (of_property_read_bool(node, "system-clock-direction-out")) in asoc_simple_parse_clk()
257 simple_dai->clk_direction = SND_SOC_CLOCK_OUT; in asoc_simple_parse_clk()
264 struct asoc_simple_dai *dai, in asoc_simple_check_fixed_sysclk() argument
267 if (dai->clk_fixed) { in asoc_simple_check_fixed_sysclk()
268 if (*fixed_sysclk && *fixed_sysclk != dai->sysclk) { in asoc_simple_check_fixed_sysclk()
270 *fixed_sysclk, dai->sysclk); in asoc_simple_check_fixed_sysclk()
271 return -EINVAL; in asoc_simple_check_fixed_sysclk()
273 *fixed_sysclk = dai->sysclk; in asoc_simple_check_fixed_sysclk()
282 struct asoc_simple_priv *priv = snd_soc_card_get_drvdata(rtd->card); in asoc_simple_startup()
283 struct simple_dai_props *props = simple_priv_to_props(priv, rtd->num); in asoc_simple_startup()
284 struct asoc_simple_dai *dai; in asoc_simple_startup() local
289 for_each_prop_dai_cpu(props, i1, dai) { in asoc_simple_startup()
290 ret = asoc_simple_clk_enable(dai); in asoc_simple_startup()
293 ret = asoc_simple_check_fixed_sysclk(rtd->dev, dai, &fixed_sysclk); in asoc_simple_startup()
298 for_each_prop_dai_codec(props, i2, dai) { in asoc_simple_startup()
299 ret = asoc_simple_clk_enable(dai); in asoc_simple_startup()
302 ret = asoc_simple_check_fixed_sysclk(rtd->dev, dai, &fixed_sysclk); in asoc_simple_startup()
307 if (fixed_sysclk && props->mclk_fs) { in asoc_simple_startup()
308 unsigned int fixed_rate = fixed_sysclk / props->mclk_fs; in asoc_simple_startup()
310 if (fixed_sysclk % props->mclk_fs) { in asoc_simple_startup()
311 dev_err(rtd->dev, "fixed sysclk %u not divisible by mclk_fs %u\n", in asoc_simple_startup()
312 fixed_sysclk, props->mclk_fs); in asoc_simple_startup()
313 ret = -EINVAL; in asoc_simple_startup()
316 ret = snd_pcm_hw_constraint_minmax(substream->runtime, SNDRV_PCM_HW_PARAM_RATE, in asoc_simple_startup()
325 for_each_prop_dai_codec(props, i, dai) { in asoc_simple_startup()
328 asoc_simple_clk_disable(dai); in asoc_simple_startup()
331 for_each_prop_dai_cpu(props, i, dai) { in asoc_simple_startup()
334 asoc_simple_clk_disable(dai); in asoc_simple_startup()
343 struct asoc_simple_priv *priv = snd_soc_card_get_drvdata(rtd->card); in asoc_simple_shutdown()
344 struct simple_dai_props *props = simple_priv_to_props(priv, rtd->num); in asoc_simple_shutdown()
345 struct asoc_simple_dai *dai; in asoc_simple_shutdown() local
348 for_each_prop_dai_cpu(props, i, dai) { in asoc_simple_shutdown()
351 if (props->mclk_fs && !dai->clk_fixed && !snd_soc_dai_active(cpu_dai)) in asoc_simple_shutdown()
355 asoc_simple_clk_disable(dai); in asoc_simple_shutdown()
357 for_each_prop_dai_codec(props, i, dai) { in asoc_simple_shutdown()
360 if (props->mclk_fs && !dai->clk_fixed && !snd_soc_dai_active(codec_dai)) in asoc_simple_shutdown()
364 asoc_simple_clk_disable(dai); in asoc_simple_shutdown()
376 if (simple_dai->clk_fixed && rate != simple_dai->sysclk) { in asoc_simple_set_clk_rate()
377 dev_err(dev, "dai %s invalid clock rate %lu\n", simple_dai->name, rate); in asoc_simple_set_clk_rate()
378 return -EINVAL; in asoc_simple_set_clk_rate()
381 if (!simple_dai->clk) in asoc_simple_set_clk_rate()
384 if (clk_get_rate(simple_dai->clk) == rate) in asoc_simple_set_clk_rate()
387 return clk_set_rate(simple_dai->clk, rate); in asoc_simple_set_clk_rate()
390 static int asoc_simple_set_tdm(struct snd_soc_dai *dai, in asoc_simple_set_tdm() argument
398 if (!simple_dai || !simple_dai->tdm_width_map) in asoc_simple_set_tdm()
401 slot_width = simple_dai->slot_width; in asoc_simple_set_tdm()
402 slot_count = simple_dai->slots; in asoc_simple_set_tdm()
407 for (i = 0; i < simple_dai->n_tdm_widths; ++i) { in asoc_simple_set_tdm()
408 if (simple_dai->tdm_width_map[i].sample_bits == sample_bits) { in asoc_simple_set_tdm()
409 slot_width = simple_dai->tdm_width_map[i].slot_width; in asoc_simple_set_tdm()
410 slot_count = simple_dai->tdm_width_map[i].slot_count; in asoc_simple_set_tdm()
415 ret = snd_soc_dai_set_tdm_slot(dai, in asoc_simple_set_tdm()
416 simple_dai->tx_slot_mask, in asoc_simple_set_tdm()
417 simple_dai->rx_slot_mask, in asoc_simple_set_tdm()
420 if (ret && ret != -ENOTSUPP) { in asoc_simple_set_tdm()
421 dev_err(dai->dev, "simple-card: set_tdm_slot error: %d\n", ret); in asoc_simple_set_tdm()
434 struct asoc_simple_priv *priv = snd_soc_card_get_drvdata(rtd->card); in asoc_simple_hw_params()
435 struct simple_dai_props *props = simple_priv_to_props(priv, rtd->num); in asoc_simple_hw_params()
439 if (props->mclk_fs) in asoc_simple_hw_params()
440 mclk_fs = props->mclk_fs; in asoc_simple_hw_params()
447 ret = asoc_simple_set_clk_rate(rtd->dev, pdai, mclk); in asoc_simple_hw_params()
453 ret = asoc_simple_set_clk_rate(rtd->dev, pdai, mclk); in asoc_simple_hw_params()
465 if (ret && ret != -ENOTSUPP) in asoc_simple_hw_params()
471 if (ret && ret != -ENOTSUPP) in asoc_simple_hw_params()
477 if (ret && ret != -ENOTSUPP) in asoc_simple_hw_params()
503 struct asoc_simple_priv *priv = snd_soc_card_get_drvdata(rtd->card); in asoc_simple_be_hw_params_fixup()
504 struct simple_dai_props *dai_props = simple_priv_to_props(priv, rtd->num); in asoc_simple_be_hw_params_fixup()
505 struct asoc_simple_data *data = &dai_props->adata; in asoc_simple_be_hw_params_fixup()
509 if (data->convert_rate) in asoc_simple_be_hw_params_fixup()
510 rate->min = in asoc_simple_be_hw_params_fixup()
511 rate->max = data->convert_rate; in asoc_simple_be_hw_params_fixup()
513 if (data->convert_channels) in asoc_simple_be_hw_params_fixup()
514 channels->min = in asoc_simple_be_hw_params_fixup()
515 channels->max = data->convert_channels; in asoc_simple_be_hw_params_fixup()
517 if (data->convert_sample_format) in asoc_simple_be_hw_params_fixup()
524 static int asoc_simple_init_dai(struct snd_soc_dai *dai, in asoc_simple_init_dai() argument
532 if (simple_dai->sysclk) { in asoc_simple_init_dai()
533 ret = snd_soc_dai_set_sysclk(dai, 0, simple_dai->sysclk, in asoc_simple_init_dai()
534 simple_dai->clk_direction); in asoc_simple_init_dai()
535 if (ret && ret != -ENOTSUPP) { in asoc_simple_init_dai()
536 dev_err(dai->dev, "simple-card: set_sysclk error\n"); in asoc_simple_init_dai()
541 if (simple_dai->slots) { in asoc_simple_init_dai()
542 ret = snd_soc_dai_set_tdm_slot(dai, in asoc_simple_init_dai()
543 simple_dai->tx_slot_mask, in asoc_simple_init_dai()
544 simple_dai->rx_slot_mask, in asoc_simple_init_dai()
545 simple_dai->slots, in asoc_simple_init_dai()
546 simple_dai->slot_width); in asoc_simple_init_dai()
547 if (ret && ret != -ENOTSUPP) { in asoc_simple_init_dai()
548 dev_err(dai->dev, "simple-card: set_tdm_slot error\n"); in asoc_simple_init_dai()
558 return component->driver->endianness; in asoc_simple_component_is_codec()
564 struct snd_soc_dai_link *dai_link = rtd->dai_link; in asoc_simple_init_for_codec2codec()
571 if (dai_link->c2c_params) in asoc_simple_init_for_codec2codec()
575 if (dai_link->no_pcm) in asoc_simple_init_for_codec2codec()
592 dev_err(rtd->dev, "simple-card: no valid dai_link params\n"); in asoc_simple_init_for_codec2codec()
596 c2c_params = devm_kzalloc(rtd->dev, sizeof(*c2c_params), GFP_KERNEL); in asoc_simple_init_for_codec2codec()
598 return -ENOMEM; in asoc_simple_init_for_codec2codec()
600 c2c_params->formats = hw.formats; in asoc_simple_init_for_codec2codec()
601 c2c_params->rates = hw.rates; in asoc_simple_init_for_codec2codec()
602 c2c_params->rate_min = hw.rate_min; in asoc_simple_init_for_codec2codec()
603 c2c_params->rate_max = hw.rate_max; in asoc_simple_init_for_codec2codec()
604 c2c_params->channels_min = hw.channels_min; in asoc_simple_init_for_codec2codec()
605 c2c_params->channels_max = hw.channels_max; in asoc_simple_init_for_codec2codec()
607 dai_link->c2c_params = c2c_params; in asoc_simple_init_for_codec2codec()
608 dai_link->num_c2c_params = 1; in asoc_simple_init_for_codec2codec()
615 struct asoc_simple_priv *priv = snd_soc_card_get_drvdata(rtd->card); in asoc_simple_dai_init()
616 struct simple_dai_props *props = simple_priv_to_props(priv, rtd->num); in asoc_simple_dai_init()
617 struct asoc_simple_dai *dai; in asoc_simple_dai_init() local
620 for_each_prop_dai_codec(props, i, dai) { in asoc_simple_dai_init()
621 ret = asoc_simple_init_dai(asoc_rtd_to_codec(rtd, i), dai); in asoc_simple_dai_init()
625 for_each_prop_dai_cpu(props, i, dai) { in asoc_simple_dai_init()
626 ret = asoc_simple_init_dai(asoc_rtd_to_cpu(rtd, i), dai); in asoc_simple_dai_init()
645 * Some CPU might be using soc-generic-dmaengine-pcm. This means CPU and Platform in asoc_simple_canonicalize_platform()
646 * are different Component, but are sharing same component->dev. in asoc_simple_canonicalize_platform()
650 * simple-card.c :: simple_count_noml() in asoc_simple_canonicalize_platform()
652 if (!platforms->of_node) in asoc_simple_canonicalize_platform()
670 cpus->dai_name = NULL; in asoc_simple_canonicalize_cpu()
683 of_node_put(cpu->of_node); in asoc_simple_clean_reference()
685 of_node_put(codec->of_node); in asoc_simple_clean_reference()
693 struct device_node *node = card->dev->of_node; in asoc_simple_parse_routing()
711 struct device_node *node = card->dev->of_node; in asoc_simple_parse_widgets()
735 snprintf(prop, sizeof(prop), "%s%s", prefix, "pin-switches"); in asoc_simple_parse_pin_switches()
746 struct device *dev = card->dev; in asoc_simple_init_jack()
757 sjack->gpio.gpio = -ENOENT; in asoc_simple_init_jack()
760 snprintf(prop, sizeof(prop), "%shp-det", prefix); in asoc_simple_init_jack()
765 snprintf(prop, sizeof(prop), "%smic-det", prefix); in asoc_simple_init_jack()
781 sjack->pin.pin = pin_name; in asoc_simple_init_jack()
782 sjack->pin.mask = mask; in asoc_simple_init_jack()
784 sjack->gpio.name = gpio_name; in asoc_simple_init_jack()
785 sjack->gpio.report = mask; in asoc_simple_init_jack()
786 sjack->gpio.desc = desc; in asoc_simple_init_jack()
787 sjack->gpio.debounce_time = 150; in asoc_simple_init_jack()
789 snd_soc_card_jack_new_pins(card, pin_name, mask, &sjack->jack, in asoc_simple_init_jack()
790 &sjack->pin, 1); in asoc_simple_init_jack()
792 snd_soc_jack_add_gpios(&sjack->jack, 1, &sjack->gpio); in asoc_simple_init_jack()
808 if (priv->aux_jacks) in asoc_simple_init_aux_jacks()
819 priv->aux_jacks = devm_kcalloc(card->dev, num, in asoc_simple_init_aux_jacks()
821 if (!priv->aux_jacks) in asoc_simple_init_aux_jacks()
822 return -ENOMEM; in asoc_simple_init_aux_jacks()
836 jack = &(priv->aux_jacks[found_jack_index++]); in asoc_simple_init_aux_jacks()
837 snprintf(id, sizeof(id), "%s-jack", component->name); in asoc_simple_init_aux_jacks()
860 dai_props = devm_kcalloc(dev, li->link, sizeof(*dai_props), GFP_KERNEL); in asoc_simple_init_priv()
861 dai_link = devm_kcalloc(dev, li->link, sizeof(*dai_link), GFP_KERNEL); in asoc_simple_init_priv()
863 return -ENOMEM; in asoc_simple_init_priv()
869 for (i = 0; i < li->link; i++) { in asoc_simple_init_priv()
870 int cc = li->num[i].cpus + li->num[i].codecs; in asoc_simple_init_priv()
873 dlc_num += cc + li->num[i].platforms; in asoc_simple_init_priv()
875 if (!li->num[i].cpus) in asoc_simple_init_priv()
876 cnf_num += li->num[i].codecs; in asoc_simple_init_priv()
882 return -ENOMEM; in asoc_simple_init_priv()
887 return -ENOMEM; in asoc_simple_init_priv()
891 li->link, dai_num, cnf_num); in asoc_simple_init_priv()
893 priv->dai_props = dai_props; in asoc_simple_init_priv()
894 priv->dai_link = dai_link; in asoc_simple_init_priv()
895 priv->dais = dais; in asoc_simple_init_priv()
896 priv->dlcs = dlcs; in asoc_simple_init_priv()
897 priv->codec_conf = cconf; in asoc_simple_init_priv()
899 card->dai_link = priv->dai_link; in asoc_simple_init_priv()
900 card->num_links = li->link; in asoc_simple_init_priv()
901 card->codec_conf = cconf; in asoc_simple_init_priv()
902 card->num_configs = cnf_num; in asoc_simple_init_priv()
904 for (i = 0; i < li->link; i++) { in asoc_simple_init_priv()
905 if (li->num[i].cpus) { in asoc_simple_init_priv()
909 dai_link[i].num_cpus = li->num[i].cpus; in asoc_simple_init_priv()
912 dlcs += li->num[i].cpus; in asoc_simple_init_priv()
913 dais += li->num[i].cpus; in asoc_simple_init_priv()
921 if (li->num[i].codecs) { in asoc_simple_init_priv()
925 dai_link[i].num_codecs = li->num[i].codecs; in asoc_simple_init_priv()
928 dlcs += li->num[i].codecs; in asoc_simple_init_priv()
929 dais += li->num[i].codecs; in asoc_simple_init_priv()
931 if (!li->num[i].cpus) { in asoc_simple_init_priv()
934 cconf += li->num[i].codecs; in asoc_simple_init_priv()
943 if (li->num[i].platforms) { in asoc_simple_init_priv()
947 dai_link[i].num_platforms = li->num[i].platforms; in asoc_simple_init_priv()
949 dlcs += li->num[i].platforms; in asoc_simple_init_priv()
977 ret = asoc_simple_init_hp(card, &priv->hp_jack, NULL); in asoc_graph_card_probe()
981 ret = asoc_simple_init_mic(card, &priv->mic_jack, NULL); in asoc_graph_card_probe()
1025 /* use driver specified DAI ID if exist */ in graph_get_dai_id()
1027 if (ret != -ENOTSUPP) in graph_get_dai_id()
1055 id = -1; in graph_get_dai_id()
1065 return -ENODEV; in graph_get_dai_id()
1075 struct snd_soc_dai *dai; in asoc_graph_parse_dai() local
1084 * Try to find from DAI node in asoc_graph_parse_dai()
1087 dai = snd_soc_get_dai_via_args(&args); in asoc_graph_parse_dai()
1088 if (dai) { in asoc_graph_parse_dai()
1089 dlc->dai_name = snd_soc_dai_name_get(dai); in asoc_graph_parse_dai()
1090 dlc->dai_args = snd_soc_copy_dai_args(dev, &args); in asoc_graph_parse_dai()
1091 if (!dlc->dai_args) in asoc_graph_parse_dai()
1092 return -ENOMEM; in asoc_graph_parse_dai()
1097 /* Get dai->name */ in asoc_graph_parse_dai()
1105 * Here, dlc->dai_name is pointer to CPU/Codec DAI name. in asoc_graph_parse_dai()
1107 * dlc->dai_name is keeping unbinded CPU or Codec in asoc_graph_parse_dai()
1110 * If user re-bind CPU or Codec driver again, ALSA SoC will try in asoc_graph_parse_dai()