From d4a03cf620c06f6d876a62f24e102ae0ca9a1c04 Mon Sep 17 00:00:00 2001 From: Jason Zhu Date: Wed, 19 Jun 2024 17:30:06 +0800 Subject: [PATCH] ASoC: rockchip: multicodecs: support DPCM Change-Id: I1e856b305bb949791962a1c157bae8981b2663f9 Signed-off-by: Jason Zhu --- sound/soc/rockchip/rockchip_multicodecs.c | 117 +++++++++++++++------- 1 file changed, 81 insertions(+), 36 deletions(-) diff --git a/sound/soc/rockchip/rockchip_multicodecs.c b/sound/soc/rockchip/rockchip_multicodecs.c index 658b2856a92b..15f486749788 100644 --- a/sound/soc/rockchip/rockchip_multicodecs.c +++ b/sound/soc/rockchip/rockchip_multicodecs.c @@ -41,6 +41,7 @@ #define DRV_NAME "rk-multicodecs" #define WAIT_CARDS (SNDRV_CARDS - 1) #define DEFAULT_MCLK_FS 256 +#define DAI_FMT_BASE (SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF) struct adc_keys_button { u32 voltage; @@ -57,7 +58,7 @@ struct input_dev_poller { struct multicodecs_data { struct snd_soc_card snd_card; - struct snd_soc_dai_link dai_link; + struct snd_soc_dai_link dai_link[3]; struct snd_soc_jack *jack_headset; struct gpio_desc *hp_ctl_gpio; struct gpio_desc *spk_ctl_gpio; @@ -312,7 +313,6 @@ static int mc_spk_event(struct snd_soc_dapm_widget *w, break; default: return 0; - } return 0; @@ -321,6 +321,8 @@ static int mc_spk_event(struct snd_soc_dapm_widget *w, static const struct snd_soc_dapm_widget mc_dapm_widgets[] = { SND_SOC_DAPM_HP("Headphone", mc_hp_event), SND_SOC_DAPM_SPK("Speaker", mc_spk_event), + SND_SOC_DAPM_LINE("Line Out Jack", NULL), + SND_SOC_DAPM_LINE("Line In Jack", NULL), SND_SOC_DAPM_MIC("Main Mic", NULL), SND_SOC_DAPM_MIC("Headset Mic", NULL), SND_SOC_DAPM_SUPPLY("Speaker Power", SND_SOC_NOPM, 0, 0, NULL, 0), @@ -492,7 +494,7 @@ static int rk_multicodecs_parse_daifmt(struct device_node *node, struct multicodecs_data *mc_data, const char *prefix) { - struct snd_soc_dai_link *dai_link = &mc_data->dai_link; + struct snd_soc_dai_link *dai_link = &mc_data->dai_link[0]; struct device_node *bitclkmaster = NULL; struct device_node *framemaster = NULL; unsigned int daifmt; @@ -592,17 +594,56 @@ static struct snd_soc_ops rk_ops = { .hw_params = rk_multicodecs_hw_params, }; +SND_SOC_DAILINK_DEFS(hifi, + DAILINK_COMP_ARRAY(COMP_EMPTY()), + DAILINK_COMP_ARRAY(COMP_EMPTY()), + DAILINK_COMP_ARRAY(COMP_EMPTY())); + +SND_SOC_DAILINK_DEFS(hifi_fe, + DAILINK_COMP_ARRAY(COMP_EMPTY()), + DAILINK_COMP_ARRAY(COMP_DUMMY()), + DAILINK_COMP_ARRAY(COMP_EMPTY())); + +SND_SOC_DAILINK_DEFS(hifi_be, + DAILINK_COMP_ARRAY(COMP_EMPTY()), + DAILINK_COMP_ARRAY(COMP_EMPTY()), + DAILINK_COMP_ARRAY(COMP_DUMMY())); + +static const struct snd_soc_dai_link rk_multicodecs_card_dai[] = { + /* Default ASoC DAI Link*/ + { + .name = "HiFi", + .stream_name = "HiFi", + .ops = &rk_ops, + SND_SOC_DAILINK_REG(hifi), + }, + /* DPCM Link between Front-End and Back-End (Optional) */ + { + .name = "HiFi-ASRC-FE", + .stream_name = "HiFi-ASRC-FE", + .dpcm_playback = 1, + .dpcm_capture = 1, + .dynamic = 1, + SND_SOC_DAILINK_REG(hifi_fe), + }, + { + .name = "HiFi-ASRC-BE", + .stream_name = "HiFi-ASRC-BE", + .ops = &rk_ops, + .dpcm_playback = 1, + .dpcm_capture = 1, + .no_pcm = 1, + SND_SOC_DAILINK_REG(hifi_be), + }, +}; + static int rk_multicodecs_probe(struct platform_device *pdev) { struct snd_soc_card *card; - struct device_node *np = pdev->dev.of_node; - struct snd_soc_dai_link *link; - struct snd_soc_dai_link_component *cpus; - struct snd_soc_dai_link_component *platforms; + struct device_node *np = pdev->dev.of_node, *node, *asrc_np; struct snd_soc_dai_link_component *codecs; struct multicodecs_data *mc_data; struct of_phandle_args args; - struct device_node *node; struct input_dev *input; u32 val; int count, value, irq; @@ -619,13 +660,7 @@ static int rk_multicodecs_probe(struct platform_device *pdev) if (!mc_data) return -ENOMEM; - cpus = devm_kzalloc(&pdev->dev, sizeof(*cpus), GFP_KERNEL); - if (!cpus) - return -ENOMEM; - - platforms = devm_kzalloc(&pdev->dev, sizeof(*platforms), GFP_KERNEL); - if (!platforms) - return -ENOMEM; + memcpy(mc_data->dai_link, rk_multicodecs_card_dai, sizeof(mc_data->dai_link)); card = &mc_data->snd_card; card->dev = &pdev->dev; @@ -635,18 +670,15 @@ static int rk_multicodecs_probe(struct platform_device *pdev) if (ret < 0) return ret; - link = &mc_data->dai_link; - link->name = "dailink-multicodecs"; - link->stream_name = link->name; - link->init = rk_dailink_init; - link->ops = &rk_ops; - link->cpus = cpus; - link->platforms = platforms; - link->num_cpus = 1; - link->num_platforms = 1; - link->ignore_pmdown_time = 1; + mc_data->dai_link[0].name = "dailink-multicodecs"; + mc_data->dai_link[0].stream_name = mc_data->dai_link[0].name; + mc_data->dai_link[0].init = rk_dailink_init; + mc_data->dai_link[0].ops = &rk_ops; + mc_data->dai_link[0].num_cpus = 1; + mc_data->dai_link[0].num_platforms = 1; + mc_data->dai_link[0].ignore_pmdown_time = 1; - card->dai_link = link; + card->dai_link = mc_data->dai_link; card->num_links = 1; card->dapm_widgets = mc_dapm_widgets; card->num_dapm_widgets = ARRAY_SIZE(mc_dapm_widgets); @@ -675,8 +707,8 @@ static int rk_multicodecs_probe(struct platform_device *pdev) if (!codecs) return -ENOMEM; - link->codecs = codecs; - link->num_codecs = idx; + mc_data->dai_link[0].codecs = codecs; + mc_data->dai_link[0].num_codecs = idx; idx = 0; for (i = 0; i < count; i++) { node = of_parse_phandle(np, "rockchip,codec", i); @@ -700,11 +732,26 @@ static int rk_multicodecs_probe(struct platform_device *pdev) /* Only reference the codecs[0].of_node which maybe as master. */ rk_multicodecs_parse_daifmt(np, codecs[0].of_node, mc_data, prefix); - link->cpus->of_node = of_parse_phandle(np, "rockchip,cpu", 0); - if (!link->cpus->of_node) + mc_data->dai_link[0].cpus->of_node = of_parse_phandle(np, "rockchip,cpu", 0); + if (!mc_data->dai_link[0].cpus->of_node) return -ENODEV; - link->platforms->of_node = link->cpus->of_node; + mc_data->dai_link[0].platforms->of_node = mc_data->dai_link[0].cpus->of_node; + + asrc_np = of_parse_phandle(np, "rockchip,asrc", 0); + if (asrc_np) { + mc_data->dai_link[1].cpus->of_node = asrc_np; + mc_data->dai_link[1].platforms->of_node = asrc_np; + mc_data->dai_link[1].num_cpus = 1; + mc_data->dai_link[1].num_platforms = 1; + + /* Support multicodec in future */ + mc_data->dai_link[2].codecs->dai_name = "dummy_codec"; + mc_data->dai_link[2].codecs->of_node = of_parse_phandle(np, "rockchip,codec", 0); + mc_data->dai_link[2].cpus->of_node = mc_data->dai_link[0].cpus->of_node; + + card->num_links = 3; + } mc_data->mclk_fs = DEFAULT_MCLK_FS; if (!of_property_read_u32(np, "rockchip,mclk-fs", &val)) @@ -814,7 +861,7 @@ static int rk_multicodecs_probe(struct platform_device *pdev) snd_soc_of_parse_audio_routing(card, "rockchip,audio-routing"); snd_soc_card_set_drvdata(card, mc_data); - platform_set_drvdata(pdev, card); + platform_set_drvdata(pdev, mc_data); ret = devm_snd_soc_register_card(&pdev->dev, card); if (ret) { @@ -832,8 +879,7 @@ static int rk_multicodecs_probe(struct platform_device *pdev) static int rk_multicodec_remove(struct platform_device *pdev) { - struct snd_soc_card *card = platform_get_drvdata(pdev); - struct multicodecs_data *mc_data = snd_soc_card_get_drvdata(card); + struct multicodecs_data *mc_data = platform_get_drvdata(pdev); cancel_delayed_work_sync(&mc_data->handler); @@ -842,8 +888,7 @@ static int rk_multicodec_remove(struct platform_device *pdev) static void rk_multicodec_shutdown(struct platform_device *pdev) { - struct snd_soc_card *card = platform_get_drvdata(pdev); - struct multicodecs_data *mc_data = snd_soc_card_get_drvdata(card); + struct multicodecs_data *mc_data = platform_get_drvdata(pdev); cancel_delayed_work_sync(&mc_data->handler); }