Lines Matching +full:sound +full:- +full:ak4458
1 // SPDX-License-Identifier: GPL-2.0+
2 // Copyright 2017-2021 NXP
12 #include <sound/soc.h>
13 #include <sound/pcm_params.h>
14 #include <sound/pcm.h>
15 #include <sound/soc-dapm.h>
16 #include <sound/simple_card_utils.h>
55 * struct imx_card_plat_data - specific info for codecs
89 * struct dai_link_data - specific info for dai link
104 * struct imx_card_data - platform device data
143 * Table 13 - Audio Interface Format
154 * Table 7 - mapping multiplier and speed mode
155 * Tables 8 & 9 - mapping speed mode and LRCK fs
232 if (link_data->slots > 2) in format_is_tdm()
256 struct snd_soc_pcm_runtime *rtd = substream->private_data; in akcodec_get_mclk_rate()
257 struct imx_card_data *data = snd_soc_card_get_drvdata(rtd->card); in akcodec_get_mclk_rate()
258 const struct imx_card_plat_data *plat_data = data->plat_data; in akcodec_get_mclk_rate()
259 struct dai_link_data *link_data = &data->link_data[rtd->num]; in akcodec_get_mclk_rate()
265 for (i = 0; i < plat_data->num_tdm_fs_mul; i++) { in akcodec_get_mclk_rate()
267 if (width != plat_data->tdm_fs_mul[i].min) in akcodec_get_mclk_rate()
269 return rate * plat_data->tdm_fs_mul[i].mul; in akcodec_get_mclk_rate()
272 for (i = 0; i < plat_data->num_fs_mul; i++) { in akcodec_get_mclk_rate()
273 if (rate >= plat_data->fs_mul[i].rmin && in akcodec_get_mclk_rate()
274 rate <= plat_data->fs_mul[i].rmax) { in akcodec_get_mclk_rate()
275 width = max(width, plat_data->fs_mul[i].wmin); in akcodec_get_mclk_rate()
276 width = min(width, plat_data->fs_mul[i].wmax); in akcodec_get_mclk_rate()
279 width *= link_data->one2one_ratio ? 1 : 2; in akcodec_get_mclk_rate()
293 struct snd_soc_pcm_runtime *rtd = substream->private_data; in imx_aif_hw_params()
295 struct snd_soc_card *card = rtd->card; in imx_aif_hw_params()
297 struct dai_link_data *link_data = &data->link_data[rtd->num]; in imx_aif_hw_params()
298 struct imx_card_plat_data *plat_data = data->plat_data; in imx_aif_hw_params()
299 struct device *dev = card->dev; in imx_aif_hw_params()
302 unsigned int fmt = rtd->dai_link->dai_fmt; in imx_aif_hw_params()
306 slots = link_data->slots; in imx_aif_hw_params()
307 slot_width = link_data->slot_width; in imx_aif_hw_params()
313 fmt = (rtd->dai_link->dai_fmt & ~SND_SOC_DAIFMT_FORMAT_MASK) | in imx_aif_hw_params()
318 fmt = (rtd->dai_link->dai_fmt & ~SND_SOC_DAIFMT_FORMAT_MASK) | in imx_aif_hw_params()
324 if (ret && ret != -ENOTSUPP) { in imx_aif_hw_params()
329 BIT(slots) - 1, in imx_aif_hw_params()
330 BIT(slots) - 1, in imx_aif_hw_params()
332 if (ret && ret != -ENOTSUPP) { in imx_aif_hw_params()
339 if (ret && ret != -ENOTSUPP) { in imx_aif_hw_params()
345 BIT(slots) - 1, in imx_aif_hw_params()
346 BIT(slots) - 1, in imx_aif_hw_params()
348 if (ret && ret != -ENOTSUPP) { in imx_aif_hw_params()
355 if (codec_is_akcodec(plat_data->type)) in imx_aif_hw_params()
368 ret = snd_soc_dai_set_sysclk(cpu_dai, link_data->cpu_sysclk_id, mclk_freq, in imx_aif_hw_params()
370 if (ret && ret != -ENOTSUPP) { in imx_aif_hw_params()
380 struct dai_link_data *link_data = r->private; in ak5558_hw_rule_rate()
386 fs = hw_param_interval(p, SNDRV_PCM_HW_PARAM_SAMPLE_BITS)->min; in ak5558_hw_rule_rate()
387 fs *= link_data->slots; in ak5558_hw_rule_rate()
393 mclk_freq *= link_data->one2one_ratio ? 1 : 2; in ak5558_hw_rule_rate()
403 return snd_interval_refine(hw_param_interval(p, r->var), &t); in ak5558_hw_rule_rate()
408 struct snd_pcm_runtime *runtime = substream->runtime; in imx_aif_startup()
409 struct snd_soc_pcm_runtime *rtd = substream->private_data; in imx_aif_startup()
410 struct snd_soc_card *card = rtd->card; in imx_aif_startup()
412 struct dai_link_data *link_data = &data->link_data[rtd->num]; in imx_aif_startup()
418 constraint_channels.list = data->plat_data->support_tdm_channels; in imx_aif_startup()
419 constraint_channels.count = data->plat_data->num_tdm_channels; in imx_aif_startup()
420 constraint_rates.list = data->plat_data->support_tdm_rates; in imx_aif_startup()
421 constraint_rates.count = data->plat_data->num_tdm_rates; in imx_aif_startup()
423 constraint_channels.list = data->plat_data->support_channels; in imx_aif_startup()
424 constraint_channels.count = data->plat_data->num_channels; in imx_aif_startup()
425 constraint_rates.list = data->plat_data->support_rates; in imx_aif_startup()
426 constraint_rates.count = data->plat_data->num_rates; in imx_aif_startup()
445 if (data->plat_data->type == CODEC_AK5558) in imx_aif_startup()
446 ret = snd_pcm_hw_rule_add(substream->runtime, 0, in imx_aif_startup()
449 SNDRV_PCM_HW_PARAM_SAMPLE_BITS, -1); in imx_aif_startup()
466 struct snd_soc_card *card = rtd->card; in be_hw_params_fixup()
472 rate->max = data->asrc_rate; in be_hw_params_fixup()
473 rate->min = data->asrc_rate; in be_hw_params_fixup()
477 snd_mask_set(mask, (__force unsigned int)data->asrc_format); in be_hw_params_fixup()
484 struct imx_card_plat_data *plat_data = data->plat_data; in imx_card_parse_of()
485 struct snd_soc_card *card = &data->card; in imx_card_parse_of()
491 struct device *dev = card->dev; in imx_card_parse_of()
506 if (of_property_read_bool(dev->of_node, "audio-routing")) { in imx_card_parse_of()
507 ret = snd_soc_of_parse_audio_routing(card, "audio-routing"); in imx_card_parse_of()
513 num_links = of_get_child_count(dev->of_node); in imx_card_parse_of()
516 card->dai_link = devm_kcalloc(dev, num_links, sizeof(*link), GFP_KERNEL); in imx_card_parse_of()
517 if (!card->dai_link) in imx_card_parse_of()
518 return -ENOMEM; in imx_card_parse_of()
520 data->link_data = devm_kcalloc(dev, num_links, sizeof(*link), GFP_KERNEL); in imx_card_parse_of()
521 if (!data->link_data) in imx_card_parse_of()
522 return -ENOMEM; in imx_card_parse_of()
524 card->num_links = num_links; in imx_card_parse_of()
525 link = card->dai_link; in imx_card_parse_of()
526 link_data = data->link_data; in imx_card_parse_of()
528 for_each_child_of_node(dev->of_node, np) { in imx_card_parse_of()
531 ret = -ENOMEM; in imx_card_parse_of()
535 link->cpus = &dlc[0]; in imx_card_parse_of()
536 link->platforms = &dlc[1]; in imx_card_parse_of()
538 link->num_cpus = 1; in imx_card_parse_of()
539 link->num_platforms = 1; in imx_card_parse_of()
541 ret = of_property_read_string(np, "link-name", &link->name); in imx_card_parse_of()
543 dev_err(card->dev, "error getting codec dai_link name\n"); in imx_card_parse_of()
549 dev_err(dev, "%s: Can't find cpu DT node\n", link->name); in imx_card_parse_of()
550 ret = -EINVAL; in imx_card_parse_of()
554 ret = of_parse_phandle_with_args(cpu, "sound-dai", in imx_card_parse_of()
555 "#sound-dai-cells", 0, &args); in imx_card_parse_of()
557 dev_err(card->dev, "%s: error getting cpu phandle\n", link->name); in imx_card_parse_of()
563 link_data->cpu_sysclk_id = FSL_SAI_CLK_MAST1; in imx_card_parse_of()
566 if (of_find_property(np, "fsl,mclk-equal-bclk", NULL)) { in imx_card_parse_of()
567 link_data->one2one_ratio = true; in imx_card_parse_of()
585 link->cpus->of_node = args.np; in imx_card_parse_of()
586 link->platforms->of_node = link->cpus->of_node; in imx_card_parse_of()
587 link->id = args.args[0]; in imx_card_parse_of()
589 ret = snd_soc_of_get_dai_name(cpu, &link->cpus->dai_name); in imx_card_parse_of()
591 dev_err_probe(card->dev, ret, in imx_card_parse_of()
592 "%s: error getting cpu dai name\n", link->name); in imx_card_parse_of()
601 link->name); in imx_card_parse_of()
605 plat_data->num_codecs = link->num_codecs; in imx_card_parse_of()
608 if (!strcmp(link->codecs->dai_name, "ak4458-aif")) in imx_card_parse_of()
609 plat_data->type = CODEC_AK4458; in imx_card_parse_of()
610 else if (!strcmp(link->codecs->dai_name, "ak4497-aif")) in imx_card_parse_of()
611 plat_data->type = CODEC_AK4497; in imx_card_parse_of()
612 else if (!strcmp(link->codecs->dai_name, "ak5558-aif")) in imx_card_parse_of()
613 plat_data->type = CODEC_AK5558; in imx_card_parse_of()
614 else if (!strcmp(link->codecs->dai_name, "ak5552-aif")) in imx_card_parse_of()
615 plat_data->type = CODEC_AK5552; in imx_card_parse_of()
620 ret = -ENOMEM; in imx_card_parse_of()
624 link->codecs = dlc; in imx_card_parse_of()
625 link->num_codecs = 1; in imx_card_parse_of()
627 link->codecs->dai_name = "snd-soc-dummy-dai"; in imx_card_parse_of()
628 link->codecs->name = "snd-soc-dummy"; in imx_card_parse_of()
631 if (!strncmp(link->name, "HiFi-ASRC-FE", 12)) { in imx_card_parse_of()
633 link->dynamic = 1; in imx_card_parse_of()
634 link->dpcm_merged_chan = 1; in imx_card_parse_of()
636 ret = of_property_read_u32(args.np, "fsl,asrc-rate", &data->asrc_rate); in imx_card_parse_of()
639 ret = -EINVAL; in imx_card_parse_of()
643 ret = of_property_read_u32(args.np, "fsl,asrc-format", &asrc_fmt); in imx_card_parse_of()
644 data->asrc_format = (__force snd_pcm_format_t)asrc_fmt; in imx_card_parse_of()
647 ret = of_property_read_u32(args.np, "fsl,asrc-width", &width); in imx_card_parse_of()
655 data->asrc_format = SNDRV_PCM_FORMAT_S24_LE; in imx_card_parse_of()
657 data->asrc_format = SNDRV_PCM_FORMAT_S16_LE; in imx_card_parse_of()
659 } else if (!strncmp(link->name, "HiFi-ASRC-BE", 12)) { in imx_card_parse_of()
661 link->no_pcm = 1; in imx_card_parse_of()
662 link->platforms->of_node = NULL; in imx_card_parse_of()
663 link->platforms->name = "snd-soc-dummy"; in imx_card_parse_of()
665 link->be_hw_params_fixup = be_hw_params_fixup; in imx_card_parse_of()
666 link->ops = &imx_aif_ops_be; in imx_card_parse_of()
668 link->ops = &imx_aif_ops; in imx_card_parse_of()
671 if (link->no_pcm || link->dynamic) in imx_card_parse_of()
676 NULL, &link->dai_fmt); in imx_card_parse_of()
678 link->dai_fmt = SND_SOC_DAIFMT_NB_NF | in imx_card_parse_of()
684 &link_data->slots, in imx_card_parse_of()
685 &link_data->slot_width); in imx_card_parse_of()
687 if (!link_data->slots) in imx_card_parse_of()
688 link_data->slots = 2; in imx_card_parse_of()
690 if (!link_data->slot_width) in imx_card_parse_of()
691 link_data->slot_width = 32; in imx_card_parse_of()
693 link->ignore_pmdown_time = 1; in imx_card_parse_of()
694 link->stream_name = link->name; in imx_card_parse_of()
724 data = devm_kzalloc(&pdev->dev, sizeof(*data), GFP_KERNEL); in imx_card_probe()
726 return -ENOMEM; in imx_card_probe()
728 plat_data = devm_kzalloc(&pdev->dev, sizeof(*plat_data), GFP_KERNEL); in imx_card_probe()
730 return -ENOMEM; in imx_card_probe()
732 data->plat_data = plat_data; in imx_card_probe()
733 data->card.dev = &pdev->dev; in imx_card_probe()
735 dev_set_drvdata(&pdev->dev, &data->card); in imx_card_probe()
736 snd_soc_card_set_drvdata(&data->card, data); in imx_card_probe()
741 data->num_dapm_routes = plat_data->num_codecs + 1; in imx_card_probe()
742 data->dapm_routes = devm_kcalloc(&pdev->dev, data->num_dapm_routes, in imx_card_probe()
745 if (!data->dapm_routes) in imx_card_probe()
746 return -ENOMEM; in imx_card_probe()
749 switch (plat_data->type) { in imx_card_probe()
752 if (plat_data->num_codecs == 1) { in imx_card_probe()
753 data->dapm_routes[0].sink = "Playback"; in imx_card_probe()
754 data->dapm_routes[0].source = "CPU-Playback"; in imx_card_probe()
757 for (i = 0; i < plat_data->num_codecs; i++) { in imx_card_probe()
758 data->dapm_routes[i].sink = in imx_card_probe()
759 devm_kasprintf(&pdev->dev, GFP_KERNEL, "%d %s", in imx_card_probe()
761 data->dapm_routes[i].source = "CPU-Playback"; in imx_card_probe()
764 data->dapm_routes[i].sink = "CPU-Playback"; in imx_card_probe()
765 data->dapm_routes[i].source = "ASRC-Playback"; in imx_card_probe()
769 if (plat_data->num_codecs == 1) { in imx_card_probe()
770 data->dapm_routes[0].sink = "CPU-Capture"; in imx_card_probe()
771 data->dapm_routes[0].source = "Capture"; in imx_card_probe()
774 for (i = 0; i < plat_data->num_codecs; i++) { in imx_card_probe()
775 data->dapm_routes[i].source = in imx_card_probe()
776 devm_kasprintf(&pdev->dev, GFP_KERNEL, "%d %s", in imx_card_probe()
778 data->dapm_routes[i].sink = "CPU-Capture"; in imx_card_probe()
781 data->dapm_routes[i].sink = "ASRC-Capture"; in imx_card_probe()
782 data->dapm_routes[i].source = "CPU-Capture"; in imx_card_probe()
789 if (codec_is_akcodec(plat_data->type)) { in imx_card_probe()
790 plat_data->support_rates = akcodec_rates; in imx_card_probe()
791 plat_data->num_rates = ARRAY_SIZE(akcodec_rates); in imx_card_probe()
792 plat_data->support_tdm_rates = akcodec_tdm_rates; in imx_card_probe()
793 plat_data->num_tdm_rates = ARRAY_SIZE(akcodec_tdm_rates); in imx_card_probe()
795 switch (plat_data->type) { in imx_card_probe()
797 plat_data->fs_mul = ak4458_fs_mul; in imx_card_probe()
798 plat_data->num_fs_mul = ARRAY_SIZE(ak4458_fs_mul); in imx_card_probe()
799 plat_data->tdm_fs_mul = ak4458_tdm_fs_mul; in imx_card_probe()
800 plat_data->num_tdm_fs_mul = ARRAY_SIZE(ak4458_tdm_fs_mul); in imx_card_probe()
801 plat_data->support_channels = ak4458_channels; in imx_card_probe()
802 plat_data->num_channels = ARRAY_SIZE(ak4458_channels); in imx_card_probe()
803 plat_data->support_tdm_channels = ak4458_tdm_channels; in imx_card_probe()
804 plat_data->num_tdm_channels = ARRAY_SIZE(ak4458_tdm_channels); in imx_card_probe()
807 plat_data->fs_mul = ak4497_fs_mul; in imx_card_probe()
808 plat_data->num_fs_mul = ARRAY_SIZE(ak4497_fs_mul); in imx_card_probe()
809 plat_data->support_channels = ak4458_channels; in imx_card_probe()
810 plat_data->num_channels = ARRAY_SIZE(ak4458_channels); in imx_card_probe()
814 plat_data->fs_mul = ak5558_fs_mul; in imx_card_probe()
815 plat_data->num_fs_mul = ARRAY_SIZE(ak5558_fs_mul); in imx_card_probe()
816 plat_data->tdm_fs_mul = ak5558_tdm_fs_mul; in imx_card_probe()
817 plat_data->num_tdm_fs_mul = ARRAY_SIZE(ak5558_tdm_fs_mul); in imx_card_probe()
818 plat_data->support_channels = ak5558_channels; in imx_card_probe()
819 plat_data->num_channels = ARRAY_SIZE(ak5558_channels); in imx_card_probe()
820 plat_data->support_tdm_channels = ak5558_tdm_channels; in imx_card_probe()
821 plat_data->num_tdm_channels = ARRAY_SIZE(ak5558_tdm_channels); in imx_card_probe()
829 if (data->card.num_links == 3) { in imx_card_probe()
830 data->card.dapm_routes = data->dapm_routes; in imx_card_probe()
831 data->card.num_dapm_routes = data->num_dapm_routes; in imx_card_probe()
832 for_each_card_prelinks(&data->card, i, link) { in imx_card_probe()
833 if (link->no_pcm == 1) in imx_card_probe()
836 for_each_card_prelinks(&data->card, i, link) { in imx_card_probe()
837 if (link->dynamic == 1 && link_be) { in imx_card_probe()
838 link->dpcm_playback = link_be->dpcm_playback; in imx_card_probe()
839 link->dpcm_capture = link_be->dpcm_capture; in imx_card_probe()
844 ret = devm_snd_soc_register_card(&pdev->dev, &data->card); in imx_card_probe()
846 return dev_err_probe(&pdev->dev, ret, "snd_soc_register_card failed\n"); in imx_card_probe()
852 { .compatible = "fsl,imx-audio-card", },
859 .name = "imx-card",
869 MODULE_ALIAS("platform:imx-card");