Lines Matching +full:tdm +full:- +full:slots

1 // SPDX-License-Identifier: GPL-2.0+
2 // Copyright 2017-2021 NXP
14 #include <sound/soc-dapm.h>
46 * Mapping TDM mode and frame width
55 * struct imx_card_plat_data - specific info for codecs
58 * @tdm_fs_mul: ratio of mclk/fs for tdm mode
60 * @support_tdm_rates: supported sample rate for tdm mode
62 * @support_tdm_channels: supported channels for tdm mode
89 * struct dai_link_data - specific info for dai link
91 * @slots: slot number
97 unsigned int slots;
104 * struct imx_card_data - platform device data
143 * Table 13 - Audio Interface Format
144 * For TDM mode, MCLK should is set to
145 * obtained from 2 * slots * slot_width
154 * Table 7 - mapping multiplier and speed mode
155 * Tables 8 & 9 - mapping speed mode and LRCK fs
179 * MCLK and BCLK selection based on TDM mode
250 if (link_data->slots > 2)
273 int slots, int slot_width)
276 struct imx_card_data *data = snd_soc_card_get_drvdata(rtd->card);
277 const struct imx_card_plat_data *plat_data = data->plat_data;
278 struct dai_link_data *link_data = &data->link_data[rtd->id];
279 unsigned int width = slots * slot_width;
284 for (i = 0; i < plat_data->num_tdm_fs_mul; i++) {
285 /* min = max = slots * slots_width */
286 if (width != plat_data->tdm_fs_mul[i].min)
288 return rate * plat_data->tdm_fs_mul[i].mul;
291 for (i = 0; i < plat_data->num_fs_mul; i++) {
292 if (rate >= plat_data->fs_mul[i].rmin &&
293 rate <= plat_data->fs_mul[i].rmax) {
294 width = max(width, plat_data->fs_mul[i].wmin);
295 width = min(width, plat_data->fs_mul[i].wmax);
298 width *= link_data->one2one_ratio ? 1 : 2;
314 struct snd_soc_card *card = rtd->card;
316 struct dai_link_data *link_data = &data->link_data[rtd->id];
317 struct imx_card_plat_data *plat_data = data->plat_data;
318 struct device *dev = card->dev;
321 unsigned int fmt = rtd->dai_link->dai_fmt;
322 unsigned int slots, slot_width;
325 slots = link_data->slots;
326 slot_width = link_data->slot_width;
330 slots = 1;
332 fmt = (rtd->dai_link->dai_fmt & ~SND_SOC_DAIFMT_FORMAT_MASK) |
335 slots = 2;
337 fmt = (rtd->dai_link->dai_fmt & ~SND_SOC_DAIFMT_FORMAT_MASK) |
343 if (ret && ret != -ENOTSUPP) {
348 BIT(slots) - 1,
349 BIT(slots) - 1,
350 slots, slot_width);
351 if (ret && ret != -ENOTSUPP) {
352 dev_err(dev, "failed to set cpu dai tdm slot: %d\n", ret);
358 if (ret && ret != -ENOTSUPP) {
365 BIT(slots) - 1,
366 BIT(slots) - 1,
367 slots, slot_width);
368 if (ret && ret != -ENOTSUPP) {
369 dev_err(dev, "failed to set codec dai[%d] tdm slot: %d\n", i, ret);
376 if (codec_is_akcodec(plat_data->type))
377 mclk_freq = akcodec_get_mclk_rate(substream, params, slots, slot_width);
379 mclk_freq = params_rate(params) * slots * slot_width;
389 ret = snd_soc_dai_set_sysclk(cpu_dai, link_data->cpu_sysclk_id, mclk_freq,
391 if (ret && ret != -ENOTSUPP) {
396 if (ret && ret != -ENOTSUPP) {
406 struct dai_link_data *link_data = r->private;
412 fs = hw_param_interval(p, SNDRV_PCM_HW_PARAM_SAMPLE_BITS)->min;
413 fs *= link_data->slots;
419 mclk_freq *= link_data->one2one_ratio ? 1 : 2;
429 return snd_interval_refine(hw_param_interval(p, r->var), &t);
434 struct snd_pcm_runtime *runtime = substream->runtime;
436 struct snd_soc_card *card = rtd->card;
438 struct dai_link_data *link_data = &data->link_data[rtd->id];
444 constraint_channels.list = data->plat_data->support_tdm_channels;
445 constraint_channels.count = data->plat_data->num_tdm_channels;
446 constraint_rates.list = data->plat_data->support_tdm_rates;
447 constraint_rates.count = data->plat_data->num_tdm_rates;
449 constraint_channels.list = data->plat_data->support_channels;
450 constraint_channels.count = data->plat_data->num_channels;
451 constraint_rates.list = data->plat_data->support_rates;
452 constraint_rates.count = data->plat_data->num_rates;
471 if (data->plat_data->type == CODEC_AK5558)
472 ret = snd_pcm_hw_rule_add(substream->runtime, 0,
475 SNDRV_PCM_HW_PARAM_SAMPLE_BITS, -1);
492 struct snd_soc_card *card = rtd->card;
498 rate->max = data->asrc_rate;
499 rate->min = data->asrc_rate;
503 snd_mask_set(mask, (__force unsigned int)data->asrc_format);
510 struct imx_card_plat_data *plat_data = data->plat_data;
511 struct snd_soc_card *card = &data->card;
517 struct device *dev = card->dev;
532 if (of_property_present(dev->of_node, "audio-routing")) {
533 ret = snd_soc_of_parse_audio_routing(card, "audio-routing");
539 num_links = of_get_child_count(dev->of_node);
542 card->dai_link = devm_kcalloc(dev, num_links, sizeof(*link), GFP_KERNEL);
543 if (!card->dai_link)
544 return -ENOMEM;
546 data->link_data = devm_kcalloc(dev, num_links, sizeof(*link), GFP_KERNEL);
547 if (!data->link_data)
548 return -ENOMEM;
550 card->num_links = num_links;
551 link = card->dai_link;
552 link_data = data->link_data;
554 for_each_child_of_node(dev->of_node, np) {
557 ret = -ENOMEM;
561 link->cpus = &dlc[0];
562 link->platforms = &dlc[1];
564 link->num_cpus = 1;
565 link->num_platforms = 1;
567 ret = of_property_read_string(np, "link-name", &link->name);
569 dev_err(card->dev, "error getting codec dai_link name\n");
575 dev_err(dev, "%s: Can't find cpu DT node\n", link->name);
576 ret = -EINVAL;
580 ret = snd_soc_of_get_dlc(cpu, &args, link->cpus, 0);
582 dev_err_probe(card->dev, ret,
583 "%s: error getting cpu dai info\n", link->name);
589 link_data->cpu_sysclk_id = FSL_SAI_CLK_MAST1;
592 if (of_property_read_bool(np, "fsl,mclk-equal-bclk")) {
593 link_data->one2one_ratio = true;
611 link->platforms->of_node = link->cpus->of_node;
612 link->id = args.args[0];
619 link->name);
623 plat_data->num_codecs = link->num_codecs;
626 if (!strcmp(link->codecs->dai_name, "ak4458-aif"))
627 plat_data->type = CODEC_AK4458;
628 else if (!strcmp(link->codecs->dai_name, "ak4497-aif"))
629 plat_data->type = CODEC_AK4497;
630 else if (!strcmp(link->codecs->dai_name, "ak5558-aif"))
631 plat_data->type = CODEC_AK5558;
632 else if (!strcmp(link->codecs->dai_name, "ak5552-aif"))
633 plat_data->type = CODEC_AK5552;
634 else if (!strcmp(link->codecs->dai_name, "cs42888"))
635 plat_data->type = CODEC_CS42888;
638 link->codecs = &snd_soc_dummy_dlc;
639 link->num_codecs = 1;
642 if (!strncmp(link->name, "HiFi-ASRC-FE", 12)) {
644 link->dynamic = 1;
645 link->dpcm_merged_chan = 1;
647 ret = of_property_read_u32(args.np, "fsl,asrc-rate", &data->asrc_rate);
650 ret = -EINVAL;
654 ret = of_property_read_u32(args.np, "fsl,asrc-format", &asrc_fmt);
655 data->asrc_format = (__force snd_pcm_format_t)asrc_fmt;
658 ret = of_property_read_u32(args.np, "fsl,asrc-width", &width);
666 data->asrc_format = SNDRV_PCM_FORMAT_S24_LE;
668 data->asrc_format = SNDRV_PCM_FORMAT_S16_LE;
670 } else if (!strncmp(link->name, "HiFi-ASRC-BE", 12)) {
672 link->no_pcm = 1;
673 link->platforms->of_node = NULL;
674 link->platforms->name = "snd-soc-dummy";
676 link->be_hw_params_fixup = be_hw_params_fixup;
677 link->ops = &imx_aif_ops_be;
679 link->ops = &imx_aif_ops;
684 NULL, &link->dai_fmt);
686 link->dai_fmt = SND_SOC_DAIFMT_NB_NF |
690 /* Get tdm slot */
692 &link_data->slots,
693 &link_data->slot_width);
695 if (!link_data->slots)
696 link_data->slots = 2;
698 if (!link_data->slot_width)
699 link_data->slot_width = 32;
701 link->ignore_pmdown_time = 1;
702 link->stream_name = link->name;
732 data = devm_kzalloc(&pdev->dev, sizeof(*data), GFP_KERNEL);
734 return -ENOMEM;
736 plat_data = devm_kzalloc(&pdev->dev, sizeof(*plat_data), GFP_KERNEL);
738 return -ENOMEM;
740 data->plat_data = plat_data;
741 data->card.dev = &pdev->dev;
742 data->card.owner = THIS_MODULE;
744 dev_set_drvdata(&pdev->dev, &data->card);
745 snd_soc_card_set_drvdata(&data->card, data);
750 data->num_dapm_routes = plat_data->num_codecs + 1;
751 data->dapm_routes = devm_kcalloc(&pdev->dev, data->num_dapm_routes,
754 if (!data->dapm_routes)
755 return -ENOMEM;
758 switch (plat_data->type) {
761 if (plat_data->num_codecs == 1) {
762 data->dapm_routes[0].sink = "Playback";
763 data->dapm_routes[0].source = "CPU-Playback";
766 for (i = 0; i < plat_data->num_codecs; i++) {
767 data->dapm_routes[i].sink =
768 devm_kasprintf(&pdev->dev, GFP_KERNEL, "%d %s",
770 data->dapm_routes[i].source = "CPU-Playback";
773 data->dapm_routes[i].sink = "CPU-Playback";
774 data->dapm_routes[i].source = "ASRC-Playback";
778 if (plat_data->num_codecs == 1) {
779 data->dapm_routes[0].sink = "CPU-Capture";
780 data->dapm_routes[0].source = "Capture";
783 for (i = 0; i < plat_data->num_codecs; i++) {
784 data->dapm_routes[i].source =
785 devm_kasprintf(&pdev->dev, GFP_KERNEL, "%d %s",
787 data->dapm_routes[i].sink = "CPU-Capture";
790 data->dapm_routes[i].sink = "ASRC-Capture";
791 data->dapm_routes[i].source = "CPU-Capture";
794 data->dapm_routes[0].sink = "Playback";
795 data->dapm_routes[0].source = "CPU-Playback";
796 data->dapm_routes[1].sink = "CPU-Capture";
797 data->dapm_routes[1].source = "Capture";
804 if (codec_is_akcodec(plat_data->type)) {
805 plat_data->support_rates = akcodec_rates;
806 plat_data->num_rates = ARRAY_SIZE(akcodec_rates);
807 plat_data->support_tdm_rates = akcodec_tdm_rates;
808 plat_data->num_tdm_rates = ARRAY_SIZE(akcodec_tdm_rates);
810 switch (plat_data->type) {
812 plat_data->fs_mul = ak4458_fs_mul;
813 plat_data->num_fs_mul = ARRAY_SIZE(ak4458_fs_mul);
814 plat_data->tdm_fs_mul = ak4458_tdm_fs_mul;
815 plat_data->num_tdm_fs_mul = ARRAY_SIZE(ak4458_tdm_fs_mul);
816 plat_data->support_channels = ak4458_channels;
817 plat_data->num_channels = ARRAY_SIZE(ak4458_channels);
818 plat_data->support_tdm_channels = ak4458_tdm_channels;
819 plat_data->num_tdm_channels = ARRAY_SIZE(ak4458_tdm_channels);
822 plat_data->fs_mul = ak4497_fs_mul;
823 plat_data->num_fs_mul = ARRAY_SIZE(ak4497_fs_mul);
824 plat_data->support_channels = ak4458_channels;
825 plat_data->num_channels = ARRAY_SIZE(ak4458_channels);
829 plat_data->fs_mul = ak5558_fs_mul;
830 plat_data->num_fs_mul = ARRAY_SIZE(ak5558_fs_mul);
831 plat_data->tdm_fs_mul = ak5558_tdm_fs_mul;
832 plat_data->num_tdm_fs_mul = ARRAY_SIZE(ak5558_tdm_fs_mul);
833 plat_data->support_channels = ak5558_channels;
834 plat_data->num_channels = ARRAY_SIZE(ak5558_channels);
835 plat_data->support_tdm_channels = ak5558_tdm_channels;
836 plat_data->num_tdm_channels = ARRAY_SIZE(ak5558_tdm_channels);
839 plat_data->fs_mul = cs42888_fs_mul;
840 plat_data->num_fs_mul = ARRAY_SIZE(cs42888_fs_mul);
841 plat_data->tdm_fs_mul = cs42888_tdm_fs_mul;
842 plat_data->num_tdm_fs_mul = ARRAY_SIZE(cs42888_tdm_fs_mul);
843 plat_data->support_channels = cs42888_channels;
844 plat_data->num_channels = ARRAY_SIZE(cs42888_channels);
845 plat_data->support_tdm_channels = cs42888_tdm_channels;
846 plat_data->num_tdm_channels = ARRAY_SIZE(cs42888_tdm_channels);
854 if (data->card.num_links == 3) {
855 data->card.dapm_routes = data->dapm_routes;
856 data->card.num_dapm_routes = data->num_dapm_routes;
857 for_each_card_prelinks(&data->card, i, link) {
858 if (link->no_pcm == 1)
861 for_each_card_prelinks(&data->card, i, link) {
862 if (link->dynamic == 1 && link_be) {
863 link->playback_only = link_be->playback_only;
864 link->capture_only = link_be->capture_only;
869 ret = devm_snd_soc_register_card(&pdev->dev, &data->card);
871 return dev_err_probe(&pdev->dev, ret, "snd_soc_register_card failed\n");
877 { .compatible = "fsl,imx-audio-card", },
884 .name = "imx-card",
894 MODULE_ALIAS("platform:imx-card");