Lines Matching +full:audio +full:- +full:graph +full:- +full:card
1 // SPDX-License-Identifier: GPL-2.0
3 // ASoC audio graph sound card support
8 // based on ${LINUX}/sound/soc/generic/simple-card.c
25 #define PREFIX "audio-graph-card,"
31 struct snd_soc_dapm_context *dapm = w->dapm; in graph_outdrv_event()
32 struct asoc_simple_priv *priv = snd_soc_card_get_drvdata(dapm->card); in graph_outdrv_event()
36 gpiod_set_value_cansleep(priv->pa_gpio, 1); in graph_outdrv_event()
39 gpiod_set_value_cansleep(priv->pa_gpio, 0); in graph_outdrv_event()
42 return -EINVAL; in graph_outdrv_event()
71 if (ret != -ENOTSUPP) in graph_get_dai_id()
99 id = -1; in graph_get_dai_id()
109 return -ENODEV; in graph_get_dai_id()
127 /* Get dai->name */ in asoc_simple_parse_dai()
135 * Here, dlc->dai_name is pointer to CPU/Codec DAI name. in asoc_simple_parse_dai()
136 * If user unbinded CPU or Codec driver, but not for Sound Card, in asoc_simple_parse_dai()
137 * dlc->dai_name is keeping unbinded CPU or Codec in asoc_simple_parse_dai()
140 * If user re-bind CPU or Codec driver again, ALSA SoC will try in asoc_simple_parse_dai()
141 * to rebind Card via snd_soc_try_rebind_card(), but because of in asoc_simple_parse_dai()
142 * above reason, it might can't bind Sound Card. in asoc_simple_parse_dai()
143 * Because Sound Card is pointing to released dai_name pointer. in asoc_simple_parse_dai()
145 * To avoid this rebind Card issue, in asoc_simple_parse_dai()
148 * 2) user need to rebind Sound Card everytime in asoc_simple_parse_dai()
151 ret = snd_soc_get_dai_name(&args, &dlc->dai_name); in asoc_simple_parse_dai()
157 dlc->of_node = node; in asoc_simple_parse_dai()
169 struct device_node *top = dev->of_node; in graph_parse_convert()
193 of_property_read_u32(top, "mclk-fs", &props->mclk_fs); in graph_parse_mclk_fs()
194 of_property_read_u32(ports, "mclk-fs", &props->mclk_fs); in graph_parse_mclk_fs()
195 of_property_read_u32(port, "mclk-fs", &props->mclk_fs); in graph_parse_mclk_fs()
196 of_property_read_u32(ep, "mclk-fs", &props->mclk_fs); in graph_parse_mclk_fs()
210 struct snd_soc_dai_link *dai_link = simple_priv_to_link(priv, li->link); in graph_dai_link_of_dpcm()
211 struct simple_dai_props *dai_props = simple_priv_to_props(priv, li->link); in graph_dai_link_of_dpcm()
212 struct device_node *top = dev->of_node; in graph_dai_link_of_dpcm()
213 struct device_node *ep = li->cpu ? cpu_ep : codec_ep; in graph_dai_link_of_dpcm()
218 struct snd_soc_dai_link_component *cpus = dai_link->cpus; in graph_dai_link_of_dpcm()
219 struct snd_soc_dai_link_component *codecs = dai_link->codecs; in graph_dai_link_of_dpcm()
223 if (!li->cpu && dup_codec) in graph_dai_link_of_dpcm()
230 li->link++; in graph_dai_link_of_dpcm()
234 if (li->cpu) { in graph_dai_link_of_dpcm()
238 codecs->of_node = NULL; in graph_dai_link_of_dpcm()
239 codecs->dai_name = "snd-soc-dummy-dai"; in graph_dai_link_of_dpcm()
240 codecs->name = "snd-soc-dummy"; in graph_dai_link_of_dpcm()
243 dai_link->dynamic = 1; in graph_dai_link_of_dpcm()
244 dai_link->dpcm_merged_format = 1; in graph_dai_link_of_dpcm()
247 dai_props->cpu_dai = &priv->dais[li->dais++]; in graph_dai_link_of_dpcm()
259 cpus->dai_name); in graph_dai_link_of_dpcm()
263 /* card->num_links includes Codec */ in graph_dai_link_of_dpcm()
269 cpus->of_node = NULL; in graph_dai_link_of_dpcm()
270 cpus->dai_name = "snd-soc-dummy-dai"; in graph_dai_link_of_dpcm()
271 cpus->name = "snd-soc-dummy"; in graph_dai_link_of_dpcm()
274 dai_link->no_pcm = 1; in graph_dai_link_of_dpcm()
275 dai_link->be_hw_params_fixup = asoc_simple_be_hw_params_fixup; in graph_dai_link_of_dpcm()
278 dai_props->codec_dai = &priv->dais[li->dais++]; in graph_dai_link_of_dpcm()
281 dai_props->codec_conf = &priv->codec_conf[li->conf++]; in graph_dai_link_of_dpcm()
293 codecs->dai_name); in graph_dai_link_of_dpcm()
298 snd_soc_of_parse_node_prefix(top, cconf, codecs->of_node, in graph_dai_link_of_dpcm()
300 snd_soc_of_parse_node_prefix(node, cconf, codecs->of_node, in graph_dai_link_of_dpcm()
302 snd_soc_of_parse_node_prefix(ports, cconf, codecs->of_node, in graph_dai_link_of_dpcm()
304 snd_soc_of_parse_node_prefix(port, cconf, codecs->of_node, in graph_dai_link_of_dpcm()
308 graph_parse_convert(dev, ep, &dai_props->adata); in graph_dai_link_of_dpcm()
318 NULL, &dai_link->dai_fmt); in graph_dai_link_of_dpcm()
324 dai_link->ops = &graph_ops; in graph_dai_link_of_dpcm()
325 dai_link->init = asoc_simple_dai_init; in graph_dai_link_of_dpcm()
340 struct snd_soc_dai_link *dai_link = simple_priv_to_link(priv, li->link); in graph_dai_link_of()
341 struct simple_dai_props *dai_props = simple_priv_to_props(priv, li->link); in graph_dai_link_of()
342 struct device_node *top = dev->of_node; in graph_dai_link_of()
348 if (!li->cpu) in graph_dai_link_of()
353 li->link++; in graph_dai_link_of()
356 dai_props->cpu_dai = &priv->dais[li->dais++]; in graph_dai_link_of()
358 dai_props->codec_dai = &priv->dais[li->dais++]; in graph_dai_link_of()
365 NULL, &dai_link->dai_fmt); in graph_dai_link_of()
394 "%s-%s", in graph_dai_link_of()
395 dai_link->cpus->dai_name, in graph_dai_link_of()
396 dai_link->codecs->dai_name); in graph_dai_link_of()
400 dai_link->ops = &graph_ops; in graph_dai_link_of()
401 dai_link->init = asoc_simple_dai_init; in graph_dai_link_of()
422 struct device_node *node = dev->of_node; in graph_for_each_link()
447 /* get convert-xxx property */ in graph_for_each_link()
455 * or has convert-xxx property in graph_for_each_link()
483 struct snd_soc_card *card = simple_priv_to_card(priv); in graph_parse_of() local
487 ret = asoc_simple_parse_widgets(card, NULL); in graph_parse_of()
491 ret = asoc_simple_parse_routing(card, NULL); in graph_parse_of()
496 for (li.cpu = 1; li.cpu >= 0; li.cpu--) { in graph_parse_of()
501 * as "CPU-Codec". in graph_parse_of()
504 * all CPUs are detected as "CPU-dummy", and in graph_parse_of()
505 * all Codecs are detected as "dummy-Codec". in graph_parse_of()
506 * To avoid random sub-device numbering, in graph_parse_of()
507 * detect "dummy-Codec" in last; in graph_parse_of()
516 return asoc_simple_parse_card_name(card, NULL); in graph_parse_of()
526 li->link += 1; /* 1xCPU-Codec */ in graph_count_noml()
527 li->dais += 2; /* 1xCPU + 1xCodec */ in graph_count_noml()
542 li->link++; /* 1xCPU-dummy */ in graph_count_dpcm()
543 li->dais++; /* 1xCPU */ in graph_count_dpcm()
546 li->link++; /* 1xdummy-Codec */ in graph_count_dpcm()
547 li->conf++; /* 1xdummy-Codec */ in graph_count_dpcm()
548 li->dais++; /* 1xCodec */ in graph_count_dpcm()
563 * CPU-Codec / CPU-dummy / dummy-Codec in graph_get_dais_count()
566 * same number for "dummy-Codec" in graph_get_dais_count()
569 * CPU0 --- Codec0 link : 5 in graph_get_dais_count()
570 * CPU1 --- Codec1 dais : 7 in graph_get_dais_count()
571 * CPU2 -/ ccnf : 1 in graph_get_dais_count()
572 * CPU3 --- Codec2 in graph_get_dais_count()
574 * => 5 links = 2xCPU-Codec + 2xCPU-dummy + 1xdummy-Codec in graph_get_dais_count()
576 * => 1 ccnf = 1xdummy-Codec in graph_get_dais_count()
579 * CPU0 --- Codec0 link : 5 in graph_get_dais_count()
580 * CPU1 --- Codec1 dais : 6 in graph_get_dais_count()
581 * CPU2 -/ ccnf : 1 in graph_get_dais_count()
582 * CPU3 -/ in graph_get_dais_count()
584 * => 5 links = 1xCPU-Codec + 3xCPU-dummy + 1xdummy-Codec in graph_get_dais_count()
586 * => 1 ccnf = 1xdummy-Codec in graph_get_dais_count()
589 * CPU0 --- Codec0 link : 6 in graph_get_dais_count()
590 * CPU1 -/ dais : 6 in graph_get_dais_count()
591 * CPU2 --- Codec1 ccnf : 2 in graph_get_dais_count()
592 * CPU3 -/ in graph_get_dais_count()
594 * => 6 links = 0xCPU-Codec + 4xCPU-dummy + 2xdummy-Codec in graph_get_dais_count()
596 * => 2 ccnf = 2xdummy-Codec in graph_get_dais_count()
599 * CPU0 --- Codec0 (convert-rate) link : 3 in graph_get_dais_count()
600 * CPU1 --- Codec1 dais : 4 in graph_get_dais_count()
603 * => 3 links = 1xCPU-Codec + 1xCPU-dummy + 1xdummy-Codec in graph_get_dais_count()
605 * => 1 ccnf = 1xdummy-Codec in graph_get_dais_count()
611 li->link, li->dais, li->conf); in graph_get_dais_count()
614 static int graph_card_probe(struct snd_soc_card *card) in graph_card_probe() argument
616 struct asoc_simple_priv *priv = snd_soc_card_get_drvdata(card); in graph_card_probe()
619 ret = asoc_simple_init_hp(card, &priv->hp_jack, NULL); in graph_card_probe()
623 ret = asoc_simple_init_mic(card, &priv->mic_jack, NULL); in graph_card_probe()
633 struct device *dev = &pdev->dev; in graph_probe()
634 struct snd_soc_card *card; in graph_probe() local
641 return -ENOMEM; in graph_probe()
643 card = simple_priv_to_card(priv); in graph_probe()
644 card->owner = THIS_MODULE; in graph_probe()
645 card->dev = dev; in graph_probe()
646 card->dapm_widgets = graph_dapm_widgets; in graph_probe()
647 card->num_dapm_widgets = ARRAY_SIZE(graph_dapm_widgets); in graph_probe()
648 card->probe = graph_card_probe; in graph_probe()
653 return -EINVAL; in graph_probe()
659 priv->pa_gpio = devm_gpiod_get_optional(dev, "pa", GPIOD_OUT_LOW); in graph_probe()
660 if (IS_ERR(priv->pa_gpio)) { in graph_probe()
661 ret = PTR_ERR(priv->pa_gpio); in graph_probe()
668 if (ret != -EPROBE_DEFER) in graph_probe()
673 snd_soc_card_set_drvdata(card, priv); in graph_probe()
677 ret = devm_snd_soc_register_card(dev, card); in graph_probe()
683 asoc_simple_clean_reference(card); in graph_probe()
690 struct snd_soc_card *card = platform_get_drvdata(pdev); in graph_remove() local
692 return asoc_simple_clean_reference(card); in graph_remove()
696 { .compatible = "audio-graph-card", },
697 { .compatible = "audio-graph-scu-card",
705 .name = "asoc-audio-graph-card",
714 MODULE_ALIAS("platform:asoc-audio-graph-card");
716 MODULE_DESCRIPTION("ASoC Audio Graph Sound Card");