Lines Matching +full:aux +full:- +full:devs
1 // SPDX-License-Identifier: (GPL-2.0 OR MIT)
9 #include <sound/soc-dai.h>
11 #include "axg-tdm.h"
40 links = krealloc(priv->card.dai_link, in axg_card_reallocate_links()
41 num_links * sizeof(*priv->card.dai_link), in axg_card_reallocate_links()
43 ldata = krealloc(priv->link_data, in axg_card_reallocate_links()
44 num_links * sizeof(*priv->link_data), in axg_card_reallocate_links()
48 dev_err(priv->card.dev, "failed to allocate links\n"); in axg_card_reallocate_links()
49 return -ENOMEM; in axg_card_reallocate_links()
52 priv->card.dai_link = links; in axg_card_reallocate_links()
53 priv->link_data = ldata; in axg_card_reallocate_links()
54 priv->card.num_links = num_links; in axg_card_reallocate_links()
67 return -EINVAL; in axg_card_parse_dai()
69 ret = of_parse_phandle_with_args(node, "sound-dai", in axg_card_parse_dai()
70 "#sound-dai-cells", 0, &args); in axg_card_parse_dai()
72 if (ret != -EPROBE_DEFER) in axg_card_parse_dai()
73 dev_err(card->dev, "can't parse dai %d\n", ret); in axg_card_parse_dai()
85 char *name = devm_kasprintf(card->dev, GFP_KERNEL, "%s.%s", in axg_card_set_link_name()
86 prefix, link->cpu_of_node->full_name); in axg_card_set_link_name()
88 return -ENOMEM; in axg_card_set_link_name()
90 link->name = name; in axg_card_set_link_name()
91 link->stream_name = name; in axg_card_set_link_name()
98 struct snd_soc_card *card = &priv->card; in axg_card_clean_references()
102 if (card->dai_link) { in axg_card_clean_references()
103 for (i = 0; i < card->num_links; i++) { in axg_card_clean_references()
104 link = &card->dai_link[i]; in axg_card_clean_references()
105 of_node_put(link->cpu_of_node); in axg_card_clean_references()
106 for (j = 0; j < link->num_codecs; j++) in axg_card_clean_references()
107 of_node_put(link->codecs[j].of_node); in axg_card_clean_references()
111 if (card->aux_dev) { in axg_card_clean_references()
112 for (i = 0; i < card->num_aux_devs; i++) in axg_card_clean_references()
113 of_node_put(card->aux_dev[i].codec_of_node); in axg_card_clean_references()
116 kfree(card->dai_link); in axg_card_clean_references()
117 kfree(priv->link_data); in axg_card_clean_references()
122 struct device_node *node = card->dev->of_node; in axg_card_add_aux_devices()
123 struct snd_soc_aux_dev *aux; in axg_card_add_aux_devices() local
126 num = of_count_phandle_with_args(node, "audio-aux-devs", NULL); in axg_card_add_aux_devices()
127 if (num == -ENOENT) { in axg_card_add_aux_devices()
132 dev_warn(card->dev, "card has no auxiliary devices\n"); in axg_card_add_aux_devices()
135 dev_err(card->dev, "error getting auxiliary devices: %d\n", in axg_card_add_aux_devices()
140 aux = devm_kcalloc(card->dev, num, sizeof(*aux), GFP_KERNEL); in axg_card_add_aux_devices()
141 if (!aux) in axg_card_add_aux_devices()
142 return -ENOMEM; in axg_card_add_aux_devices()
143 card->aux_dev = aux; in axg_card_add_aux_devices()
144 card->num_aux_devs = num; in axg_card_add_aux_devices()
146 for (i = 0; i < card->num_aux_devs; i++, aux++) { in axg_card_add_aux_devices()
147 aux->codec_of_node = in axg_card_add_aux_devices()
148 of_parse_phandle(node, "audio-aux-devs", i); in axg_card_add_aux_devices()
149 if (!aux->codec_of_node) in axg_card_add_aux_devices()
150 return -EINVAL; in axg_card_add_aux_devices()
159 struct snd_soc_pcm_runtime *rtd = substream->private_data; in axg_card_tdm_be_hw_params()
160 struct axg_card *priv = snd_soc_card_get_drvdata(rtd->card); in axg_card_tdm_be_hw_params()
162 (struct axg_dai_link_tdm_data *)priv->link_data[rtd->num]; in axg_card_tdm_be_hw_params()
167 if (be->mclk_fs) { in axg_card_tdm_be_hw_params()
168 mclk = params_rate(params) * be->mclk_fs; in axg_card_tdm_be_hw_params()
170 for (i = 0; i < rtd->num_codecs; i++) { in axg_card_tdm_be_hw_params()
171 codec_dai = rtd->codec_dais[i]; in axg_card_tdm_be_hw_params()
174 if (ret && ret != -ENOTSUPP) in axg_card_tdm_be_hw_params()
178 ret = snd_soc_dai_set_sysclk(rtd->cpu_dai, 0, mclk, in axg_card_tdm_be_hw_params()
180 if (ret && ret != -ENOTSUPP) in axg_card_tdm_be_hw_params()
193 struct axg_card *priv = snd_soc_card_get_drvdata(rtd->card); in axg_card_tdm_dai_init()
195 (struct axg_dai_link_tdm_data *)priv->link_data[rtd->num]; in axg_card_tdm_dai_init()
199 for (i = 0; i < rtd->num_codecs; i++) { in axg_card_tdm_dai_init()
200 codec_dai = rtd->codec_dais[i]; in axg_card_tdm_dai_init()
202 be->codec_masks[i].tx, in axg_card_tdm_dai_init()
203 be->codec_masks[i].rx, in axg_card_tdm_dai_init()
204 be->slots, be->slot_width); in axg_card_tdm_dai_init()
205 if (ret && ret != -ENOTSUPP) { in axg_card_tdm_dai_init()
206 dev_err(codec_dai->dev, in axg_card_tdm_dai_init()
212 ret = axg_tdm_set_tdm_slots(rtd->cpu_dai, be->tx_mask, be->rx_mask, in axg_card_tdm_dai_init()
213 be->slots, be->slot_width); in axg_card_tdm_dai_init()
215 dev_err(rtd->cpu_dai->dev, "setting tdm link slots failed\n"); in axg_card_tdm_dai_init()
224 struct axg_card *priv = snd_soc_card_get_drvdata(rtd->card); in axg_card_tdm_dai_lb_init()
226 (struct axg_dai_link_tdm_data *)priv->link_data[rtd->num]; in axg_card_tdm_dai_lb_init()
230 ret = axg_tdm_set_tdm_slots(rtd->cpu_dai, NULL, be->tx_mask, in axg_card_tdm_dai_lb_init()
231 be->slots, be->slot_width); in axg_card_tdm_dai_lb_init()
233 dev_err(rtd->cpu_dai->dev, "setting tdm link slots failed\n"); in axg_card_tdm_dai_lb_init()
244 struct snd_soc_dai_link *pad = &card->dai_link[*index]; in axg_card_add_tdm_loopback()
249 ret = axg_card_reallocate_links(priv, card->num_links + 1); in axg_card_add_tdm_loopback()
253 lb = &card->dai_link[*index + 1]; in axg_card_add_tdm_loopback()
255 lb->name = kasprintf(GFP_KERNEL, "%s-lb", pad->name); in axg_card_add_tdm_loopback()
256 if (!lb->name) in axg_card_add_tdm_loopback()
257 return -ENOMEM; in axg_card_add_tdm_loopback()
259 lb->stream_name = lb->name; in axg_card_add_tdm_loopback()
260 lb->cpu_of_node = pad->cpu_of_node; in axg_card_add_tdm_loopback()
261 lb->cpu_dai_name = "TDM Loopback"; in axg_card_add_tdm_loopback()
262 lb->codec_name = "snd-soc-dummy"; in axg_card_add_tdm_loopback()
263 lb->codec_dai_name = "snd-soc-dummy-dai"; in axg_card_add_tdm_loopback()
264 lb->dpcm_capture = 1; in axg_card_add_tdm_loopback()
265 lb->no_pcm = 1; in axg_card_add_tdm_loopback()
266 lb->ops = &axg_card_tdm_be_ops; in axg_card_add_tdm_loopback()
267 lb->init = axg_card_tdm_dai_lb_init; in axg_card_add_tdm_loopback()
270 priv->link_data[*index + 1] = priv->link_data[*index]; in axg_card_add_tdm_loopback()
276 of_node_get(lb->cpu_of_node); in axg_card_add_tdm_loopback()
319 be->tx_mask = devm_kcalloc(card->dev, AXG_TDM_NUM_LANES, in axg_card_parse_cpu_tdm_slots()
320 sizeof(*be->tx_mask), GFP_KERNEL); in axg_card_parse_cpu_tdm_slots()
321 be->rx_mask = devm_kcalloc(card->dev, AXG_TDM_NUM_LANES, in axg_card_parse_cpu_tdm_slots()
322 sizeof(*be->rx_mask), GFP_KERNEL); in axg_card_parse_cpu_tdm_slots()
323 if (!be->tx_mask || !be->rx_mask) in axg_card_parse_cpu_tdm_slots()
324 return -ENOMEM; in axg_card_parse_cpu_tdm_slots()
327 snprintf(propname, 32, "dai-tdm-slot-tx-mask-%d", i); in axg_card_parse_cpu_tdm_slots()
328 snd_soc_of_get_slot_mask(node, propname, &be->tx_mask[i]); in axg_card_parse_cpu_tdm_slots()
329 tx = max(tx, be->tx_mask[i]); in axg_card_parse_cpu_tdm_slots()
334 link->dpcm_playback = 0; in axg_card_parse_cpu_tdm_slots()
337 snprintf(propname, 32, "dai-tdm-slot-rx-mask-%d", i); in axg_card_parse_cpu_tdm_slots()
338 snd_soc_of_get_slot_mask(node, propname, &be->rx_mask[i]); in axg_card_parse_cpu_tdm_slots()
339 rx = max(rx, be->rx_mask[i]); in axg_card_parse_cpu_tdm_slots()
344 link->dpcm_capture = 0; in axg_card_parse_cpu_tdm_slots()
348 dev_err(card->dev, "tdm link has no cpu slots\n"); in axg_card_parse_cpu_tdm_slots()
349 return -EINVAL; in axg_card_parse_cpu_tdm_slots()
352 of_property_read_u32(node, "dai-tdm-slot-num", &be->slots); in axg_card_parse_cpu_tdm_slots()
353 if (!be->slots) { in axg_card_parse_cpu_tdm_slots()
358 be->slots = fls(max(tx, rx)); in axg_card_parse_cpu_tdm_slots()
359 } else if (be->slots < fls(max(tx, rx)) || be->slots > 32) { in axg_card_parse_cpu_tdm_slots()
364 dev_err(card->dev, "bad slot number\n"); in axg_card_parse_cpu_tdm_slots()
365 return -EINVAL; in axg_card_parse_cpu_tdm_slots()
368 of_property_read_u32(node, "dai-tdm-slot-width", &be->slot_width); in axg_card_parse_cpu_tdm_slots()
381 codec_mask = devm_kcalloc(card->dev, link->num_codecs, in axg_card_parse_codecs_masks()
384 return -ENOMEM; in axg_card_parse_codecs_masks()
386 be->codec_masks = codec_mask; in axg_card_parse_codecs_masks()
389 snd_soc_of_get_slot_mask(np, "dai-tdm-slot-rx-mask", in axg_card_parse_codecs_masks()
390 &codec_mask->rx); in axg_card_parse_codecs_masks()
391 snd_soc_of_get_slot_mask(np, "dai-tdm-slot-tx-mask", in axg_card_parse_codecs_masks()
392 &codec_mask->tx); in axg_card_parse_codecs_masks()
405 struct snd_soc_dai_link *link = &card->dai_link[*index]; in axg_card_parse_tdm()
410 be = devm_kzalloc(card->dev, sizeof(*be), GFP_KERNEL); in axg_card_parse_tdm()
412 return -ENOMEM; in axg_card_parse_tdm()
413 priv->link_data[*index] = be; in axg_card_parse_tdm()
416 link->ops = &axg_card_tdm_be_ops; in axg_card_parse_tdm()
417 link->init = axg_card_tdm_dai_init; in axg_card_parse_tdm()
418 link->dai_fmt = axg_card_parse_daifmt(node, link->cpu_of_node); in axg_card_parse_tdm()
420 of_property_read_u32(node, "mclk-fs", &be->mclk_fs); in axg_card_parse_tdm()
424 dev_err(card->dev, "error parsing tdm link slots\n"); in axg_card_parse_tdm()
433 if (link->dpcm_playback) { in axg_card_parse_tdm()
450 link->no_pcm = 1; in axg_card_set_be_link()
451 link->dpcm_playback = 1; in axg_card_set_be_link()
452 link->dpcm_capture = 1; in axg_card_set_be_link()
456 dev_err(card->dev, "be link %s has no codec\n", in axg_card_set_be_link()
457 node->full_name); in axg_card_set_be_link()
458 return -EINVAL; in axg_card_set_be_link()
461 codec = devm_kcalloc(card->dev, num_codecs, sizeof(*codec), GFP_KERNEL); in axg_card_set_be_link()
463 return -ENOMEM; in axg_card_set_be_link()
465 link->codecs = codec; in axg_card_set_be_link()
466 link->num_codecs = num_codecs; in axg_card_set_be_link()
469 ret = axg_card_parse_dai(card, np, &codec->of_node, in axg_card_set_be_link()
470 &codec->dai_name); in axg_card_set_be_link()
481 dev_err(card->dev, "error setting %s link name\n", np->name); in axg_card_set_be_link()
490 link->dynamic = 1; in axg_card_set_fe_link()
491 link->dpcm_merged_format = 1; in axg_card_set_fe_link()
492 link->dpcm_merged_chan = 1; in axg_card_set_fe_link()
493 link->dpcm_merged_rate = 1; in axg_card_set_fe_link()
494 link->codec_dai_name = "snd-soc-dummy-dai"; in axg_card_set_fe_link()
495 link->codec_name = "snd-soc-dummy"; in axg_card_set_fe_link()
498 link->dpcm_playback = 1; in axg_card_set_fe_link()
500 link->dpcm_capture = 1; in axg_card_set_fe_link()
507 return of_device_is_compatible(np, PREFIX "axg-toddr"); in axg_card_cpu_is_capture_fe()
512 return of_device_is_compatible(np, PREFIX "axg-frddr"); in axg_card_cpu_is_playback_fe()
517 return of_device_is_compatible(np, PREFIX "axg-tdm-iface"); in axg_card_cpu_is_tdm_iface()
523 struct snd_soc_dai_link *dai_link = &card->dai_link[*index]; in axg_card_add_link()
526 ret = axg_card_parse_dai(card, np, &dai_link->cpu_of_node, in axg_card_add_link()
527 &dai_link->cpu_dai_name); in axg_card_add_link()
531 if (axg_card_cpu_is_playback_fe(dai_link->cpu_of_node)) in axg_card_add_link()
533 else if (axg_card_cpu_is_capture_fe(dai_link->cpu_of_node)) in axg_card_add_link()
541 if (axg_card_cpu_is_tdm_iface(dai_link->cpu_of_node)) in axg_card_add_link()
550 struct device_node *node = card->dev->of_node; in axg_card_add_links()
556 dev_err(card->dev, "card has no links\n"); in axg_card_add_links()
557 return -EINVAL; in axg_card_add_links()
584 if (!of_property_read_bool(card->dev->of_node, propname)) in axg_card_parse_of_optional()
592 { .compatible = "amlogic,axg-sound-card", },
599 struct device *dev = &pdev->dev; in axg_card_probe()
605 return -ENOMEM; in axg_card_probe()
608 snd_soc_card_set_drvdata(&priv->card, priv); in axg_card_probe()
610 priv->card.owner = THIS_MODULE; in axg_card_probe()
611 priv->card.dev = dev; in axg_card_probe()
613 ret = snd_soc_of_parse_card_name(&priv->card, "model"); in axg_card_probe()
617 ret = axg_card_parse_of_optional(&priv->card, "audio-routing", in axg_card_probe()
624 ret = axg_card_parse_of_optional(&priv->card, "audio-widgets", in axg_card_probe()
631 ret = axg_card_add_links(&priv->card); in axg_card_probe()
635 ret = axg_card_add_aux_devices(&priv->card); in axg_card_probe()
639 ret = devm_snd_soc_register_card(dev, &priv->card); in axg_card_probe()
663 .name = "axg-sound-card",