diff --git a/arch/arm64/boot/dts/freescale/Makefile b/arch/arm64/boot/dts/freescale/Makefile index 542a4f9b959f9..50356e38faa48 100644 --- a/arch/arm64/boot/dts/freescale/Makefile +++ b/arch/arm64/boot/dts/freescale/Makefile @@ -183,6 +183,7 @@ dtb-$(CONFIG_ARCH_MXC) += imx8mp-evk.dtb imx8mp-evk-rm67191.dtb imx8mp-evk-it626 imx8mp-evk-hifiberry-dac2.dtb imx8mp-evk-hifiberry-dacplusadc.dtb \ imx8mp-evk-usdhc1-m2.dtb imx8mp-evk-rm67199.dtb \ imx8mp-evk-dpdk.dtb imx8mp-evk-8mic-swpdm.dtb imx8mp-evk-revA3-8mic-revE.dtb +dtb-$(CONFIG_ARCH_MXC) += imx8mp-evk-sof-nocodec.dtb dtb-$(CONFIG_ARCH_MXC) += imx8mp-navqp.dtb dtb-$(CONFIG_ARCH_MXC) += imx8mp-ab2.dtb dtb-$(CONFIG_ARCH_MXC) += imx8mp-navq.dtb imx8mp-navq-ov5640-ov5645.dtb imx8mp-navq-ov5647-ov5640.dtb diff --git a/arch/arm64/boot/dts/freescale/imx8mp-evk-sof-nocodec.dts b/arch/arm64/boot/dts/freescale/imx8mp-evk-sof-nocodec.dts new file mode 100644 index 0000000000000..da81454303e3f --- /dev/null +++ b/arch/arm64/boot/dts/freescale/imx8mp-evk-sof-nocodec.dts @@ -0,0 +1,89 @@ +// SPDX-License-Identifier: GPL-2.0+ +// Copyright NXP 2020 + +#include "imx8mp-evk.dts" + +/delete-node/ &dsp_reserved_heap; +/delete-node/ &dsp_vdev0vring0; +/delete-node/ &dsp_vdev0vring1; +/delete-node/ &dsp_vdev0buffer; + +/ { + compatible = "fsl,imx8mp-evk-nocodec", "fsl,imx8mp-evk", "fsl,imx8mp"; + + reserved-memory { + dsp_reserved: dsp@92400000 { + reg = <0 0x92400000 0 0x2000000>; + }; + }; + + sound-wm8960 { + status = "disabled"; + }; + + sound-micfil { + status = "disabled"; + }; + + sof-nocodec { + compatible = "sof-audio-nocodec"; + status = "okay"; + + sof,num-dai-drivers = <1>; + sof,dai-driver-names = "sai3"; + sof,dai-playback-channels = <32>; + sof,dai-capture-channels = <32>; + }; + +}; + +&dsp { + compatible = "fsl,imx8mp-dsp"; + + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_sai3>; + + power-domains = <&audiomix_pd>; + + clocks = <&audio_blk_ctrl IMX8MP_CLK_AUDIOMIX_OCRAMA_IPG>, + <&audio_blk_ctrl IMX8MP_CLK_AUDIOMIX_DSP_ROOT>, + <&audio_blk_ctrl IMX8MP_CLK_AUDIOMIX_DSPDBG_ROOT>, + <&audio_blk_ctrl IMX8MP_CLK_AUDIOMIX_SAI3_IPG>, + <&audio_blk_ctrl IMX8MP_CLK_AUDIOMIX_SDMA3_ROOT>; + + clock-names = "ipg", "ocram", "core", + "sai3_bus", "sdma3_root"; + + mbox-names = "txdb0", "txdb1", "rxdb0", "rxdb1"; + mboxes = <&mu2 2 0>, <&mu2 2 1>, + <&mu2 3 0>, <&mu2 3 1>; + memory-region = <&dsp_reserved>; + /delete-property/ firmware-name; + + tplg-name = "sof-imx8-nocodec.tplg"; + machine-drv-name = "sof-nocodec"; + status = "okay"; + + ports { + #address-cells = <1>; + #size-cells = <0>; + + port@0 { reg = <0>; endpoint { /* not used */ }; }; + }; +}; + +&wm8960 { + status = "disabled"; +}; + +&sai3 { + status = "disabled"; +}; + +&sdma3 { + status = "disabled"; +}; + +&easrc { + status = "disabled"; +}; diff --git a/sound/soc/sof/imx/imx8m.c b/sound/soc/sof/imx/imx8m.c index f4fed8c2189fd..e0d7621bcb45f 100644 --- a/sound/soc/sof/imx/imx8m.c +++ b/sound/soc/sof/imx/imx8m.c @@ -476,6 +476,11 @@ static struct snd_sof_of_mach sof_imx8mp_machs[] = { .sof_tplg_filename = "sof-imx8mp-wm8962.tplg", .drv_name = "asoc-audio-graph-card2", }, + { + .compatible = "fsl,imx8mp-evk-nocodec", + .sof_tplg_filename = "sof-imx8-nocodec.tplg", + .drv_name = "sof-nocodec", + }, { .compatible = "fsl,imx8mp-evk", .sof_tplg_filename = "sof-imx8mp-wm8960.tplg", diff --git a/sound/soc/sof/nocodec.c b/sound/soc/sof/nocodec.c index b12b3d865ae30..d1641250c88cb 100644 --- a/sound/soc/sof/nocodec.c +++ b/sound/soc/sof/nocodec.c @@ -54,7 +54,15 @@ static int sof_nocodec_bes_setup(struct device *dev, links[i].id = i; links[i].no_pcm = 1; links[i].cpus->dai_name = drv[i].name; - links[i].platforms->name = dev_name(dev->parent); + + if (!dev->of_node) { + links[i].platforms->name = dev_name(dev->parent); + links[i].platforms->of_node = NULL; + } else { + links[i].platforms->of_node = dev->of_node; + links[i].platforms->name = NULL; + } + if (drv[i].playback.channels_min) links[i].dpcm_playback = 1; if (drv[i].capture.channels_min) @@ -75,6 +83,11 @@ static int sof_nocodec_setup(struct device *dev, { struct snd_soc_dai_link *links; + if (!dai_drivers) { + dev_err(dev, "ERROR: dai_drivers is NULL\n"); + return -EINVAL; + } + /* create dummy BE dai_links */ links = devm_kcalloc(dev, num_dai_drivers, sizeof(struct snd_soc_dai_link), GFP_KERNEL); if (!links) @@ -83,29 +96,107 @@ static int sof_nocodec_setup(struct device *dev, return sof_nocodec_bes_setup(dev, dai_drivers, links, num_dai_drivers, &sof_nocodec_card); } +static int sof_nocodec_parse_dt_dai_info(struct device *dev, + u32 *num_dai_drivers, + struct snd_soc_dai_driver **dai_drivers) +{ + struct device_node *np = dev->of_node; + const char *dai_name; + int playback_channels, capture_channels; + int ret, i; + + ret = of_property_read_u32(np, "sof,num-dai-drivers", num_dai_drivers); + if (ret) + return ret; + + *dai_drivers = devm_kcalloc(dev, *num_dai_drivers, + sizeof(struct snd_soc_dai_driver), GFP_KERNEL); + if (!*dai_drivers) + return -ENOMEM; + + for (i = 0; i < *num_dai_drivers; i++) { + + ret = of_property_read_string_index(np, "sof,dai-driver-names", i, &dai_name); + if (ret) + return ret; + + ret = of_property_read_u32_index(np, "sof,dai-playback-channels", i, &playback_channels); + if (ret) + playback_channels = 0; + + ret = of_property_read_u32_index(np, "sof,dai-capture-channels", i, &capture_channels); + if (ret) + capture_channels = 0; + + (*dai_drivers)[i].name = devm_kstrdup(dev, dai_name, GFP_KERNEL); + if (!(*dai_drivers)[i].name) + return -ENOMEM; + + (*dai_drivers)[i].id = i; + + if (playback_channels > 0) { + (*dai_drivers)[i].playback.channels_min = 1; + (*dai_drivers)[i].playback.channels_max = 32; + } + + if (capture_channels > 0) { + (*dai_drivers)[i].capture.channels_min = 1; + (*dai_drivers)[i].capture.channels_max = 32; + } + + } + + return 0; +} + static int sof_nocodec_probe(struct platform_device *pdev) { + struct device *dev = &pdev->dev; struct snd_soc_card *card = &sof_nocodec_card; struct snd_soc_acpi_mach *mach; int ret; - card->dev = &pdev->dev; + card->dev = dev; card->topology_shortname_created = true; - mach = pdev->dev.platform_data; - ret = sof_nocodec_setup(card->dev, mach->mach_params.num_dai_drivers, - mach->mach_params.dai_drivers); + if (dev->of_node) { + u32 num_dai_drivers = 0; + struct snd_soc_dai_driver *dai_drivers = NULL; + + ret = sof_nocodec_parse_dt_dai_info(dev, &num_dai_drivers, &dai_drivers); + + if (ret) { + dev_err(dev, "Failed to parse DT info: %d\n", ret); + return ret; + } + + ret = sof_nocodec_setup(dev, num_dai_drivers, dai_drivers); + } else { + mach = dev->platform_data; + + ret = sof_nocodec_setup(dev, + mach->mach_params.num_dai_drivers, + mach->mach_params.dai_drivers); + } + if (ret < 0) return ret; - return devm_snd_soc_register_card(&pdev->dev, card); + return devm_snd_soc_register_card(dev, card); } +static const struct of_device_id sof_nocodec_of_match[] = { + { .compatible = "sof-audio-nocodec", }, + { }, +}; +MODULE_DEVICE_TABLE(of, sof_nocodec_of_match); + static struct platform_driver sof_nocodec_audio = { .probe = sof_nocodec_probe, .driver = { .name = "sof-nocodec", .pm = &snd_soc_pm_ops, + .of_match_table = sof_nocodec_of_match, }, }; module_platform_driver(sof_nocodec_audio)