From 4455f26a551c86e31c7d27495903a11c3d660034 Mon Sep 17 00:00:00 2001 From: Sugar Zhang Date: Thu, 26 Aug 2021 12:02:37 +0800 Subject: ASoC: rockchip: i2s: Make playback/capture optional There are some controllers which support playback only or capture only. so, make it optional. and initial capability by 'dma-names' of DT. Signed-off-by: Sugar Zhang Link: https://lore.kernel.org/r/1629950562-14281-4-git-send-email-sugar.zhang@rock-chips.com Signed-off-by: Mark Brown --- sound/soc/rockchip/rockchip_i2s.c | 129 +++++++++++++++++++++++--------------- 1 file changed, 79 insertions(+), 50 deletions(-) (limited to 'sound') diff --git a/sound/soc/rockchip/rockchip_i2s.c b/sound/soc/rockchip/rockchip_i2s.c index ef9d1db4df48..f955a06fe194 100644 --- a/sound/soc/rockchip/rockchip_i2s.c +++ b/sound/soc/rockchip/rockchip_i2s.c @@ -40,6 +40,9 @@ struct rk_i2s_dev { struct regmap *regmap; struct regmap *grf; + bool has_capture; + bool has_playback; + /* * Used to indicate the tx/rx status. * I2S controller hopes to start the tx and rx together, @@ -453,8 +456,9 @@ static int rockchip_i2s_dai_probe(struct snd_soc_dai *dai) { struct rk_i2s_dev *i2s = snd_soc_dai_get_drvdata(dai); - dai->capture_dma_data = &i2s->capture_dma_data; - dai->playback_dma_data = &i2s->playback_dma_data; + snd_soc_dai_init_dma_data(dai, + i2s->has_playback ? &i2s->playback_dma_data : NULL, + i2s->has_capture ? &i2s->capture_dma_data : NULL); return 0; } @@ -469,28 +473,6 @@ static const struct snd_soc_dai_ops rockchip_i2s_dai_ops = { static struct snd_soc_dai_driver rockchip_i2s_dai = { .probe = rockchip_i2s_dai_probe, - .playback = { - .stream_name = "Playback", - .channels_min = 2, - .channels_max = 8, - .rates = SNDRV_PCM_RATE_8000_192000, - .formats = (SNDRV_PCM_FMTBIT_S8 | - SNDRV_PCM_FMTBIT_S16_LE | - SNDRV_PCM_FMTBIT_S20_3LE | - SNDRV_PCM_FMTBIT_S24_LE | - SNDRV_PCM_FMTBIT_S32_LE), - }, - .capture = { - .stream_name = "Capture", - .channels_min = 2, - .channels_max = 2, - .rates = SNDRV_PCM_RATE_8000_192000, - .formats = (SNDRV_PCM_FMTBIT_S8 | - SNDRV_PCM_FMTBIT_S16_LE | - SNDRV_PCM_FMTBIT_S20_3LE | - SNDRV_PCM_FMTBIT_S24_LE | - SNDRV_PCM_FMTBIT_S32_LE), - }, .ops = &rockchip_i2s_dai_ops, .symmetric_rate = 1, }; @@ -595,16 +577,84 @@ static const struct of_device_id rockchip_i2s_match[] __maybe_unused = { {}, }; +static int rockchip_i2s_init_dai(struct rk_i2s_dev *i2s, struct resource *res, + struct snd_soc_dai_driver **dp) +{ + struct device_node *node = i2s->dev->of_node; + struct snd_soc_dai_driver *dai; + struct property *dma_names; + const char *dma_name; + unsigned int val; + + of_property_for_each_string(node, "dma-names", dma_names, dma_name) { + if (!strcmp(dma_name, "tx")) + i2s->has_playback = true; + if (!strcmp(dma_name, "rx")) + i2s->has_capture = true; + } + + dai = devm_kmemdup(i2s->dev, &rockchip_i2s_dai, + sizeof(*dai), GFP_KERNEL); + if (!dai) + return -ENOMEM; + + if (i2s->has_playback) { + dai->playback.stream_name = "Playback"; + dai->playback.channels_min = 2; + dai->playback.channels_max = 8; + dai->playback.rates = SNDRV_PCM_RATE_8000_192000; + dai->playback.formats = SNDRV_PCM_FMTBIT_S8 | + SNDRV_PCM_FMTBIT_S16_LE | + SNDRV_PCM_FMTBIT_S20_3LE | + SNDRV_PCM_FMTBIT_S24_LE | + SNDRV_PCM_FMTBIT_S32_LE; + + i2s->playback_dma_data.addr = res->start + I2S_TXDR; + i2s->playback_dma_data.addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES; + i2s->playback_dma_data.maxburst = 8; + + if (!of_property_read_u32(node, "rockchip,playback-channels", &val)) { + if (val >= 2 && val <= 8) + dai->playback.channels_max = val; + } + } + + if (i2s->has_capture) { + dai->capture.stream_name = "Capture"; + dai->capture.channels_min = 2; + dai->capture.channels_max = 8; + dai->capture.rates = SNDRV_PCM_RATE_8000_192000; + dai->capture.formats = SNDRV_PCM_FMTBIT_S8 | + SNDRV_PCM_FMTBIT_S16_LE | + SNDRV_PCM_FMTBIT_S20_3LE | + SNDRV_PCM_FMTBIT_S24_LE | + SNDRV_PCM_FMTBIT_S32_LE; + + i2s->capture_dma_data.addr = res->start + I2S_RXDR; + i2s->capture_dma_data.addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES; + i2s->capture_dma_data.maxburst = 8; + + if (!of_property_read_u32(node, "rockchip,capture-channels", &val)) { + if (val >= 2 && val <= 8) + dai->capture.channels_max = val; + } + } + + if (dp) + *dp = dai; + + return 0; +} + static int rockchip_i2s_probe(struct platform_device *pdev) { struct device_node *node = pdev->dev.of_node; const struct of_device_id *of_id; struct rk_i2s_dev *i2s; - struct snd_soc_dai_driver *soc_dai; + struct snd_soc_dai_driver *dai; struct resource *res; void __iomem *regs; int ret; - int val; i2s = devm_kzalloc(&pdev->dev, sizeof(*i2s), GFP_KERNEL); if (!i2s) @@ -651,14 +701,6 @@ static int rockchip_i2s_probe(struct platform_device *pdev) return PTR_ERR(i2s->regmap); } - i2s->playback_dma_data.addr = res->start + I2S_TXDR; - i2s->playback_dma_data.addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES; - i2s->playback_dma_data.maxburst = 8; - - i2s->capture_dma_data.addr = res->start + I2S_RXDR; - i2s->capture_dma_data.addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES; - i2s->capture_dma_data.maxburst = 8; - i2s->bclk_ratio = 64; dev_set_drvdata(&pdev->dev, i2s); @@ -670,26 +712,13 @@ static int rockchip_i2s_probe(struct platform_device *pdev) goto err_pm_disable; } - soc_dai = devm_kmemdup(&pdev->dev, &rockchip_i2s_dai, - sizeof(*soc_dai), GFP_KERNEL); - if (!soc_dai) { - ret = -ENOMEM; + ret = rockchip_i2s_init_dai(i2s, res, &dai); + if (ret) goto err_pm_disable; - } - - if (!of_property_read_u32(node, "rockchip,playback-channels", &val)) { - if (val >= 2 && val <= 8) - soc_dai->playback.channels_max = val; - } - - if (!of_property_read_u32(node, "rockchip,capture-channels", &val)) { - if (val >= 2 && val <= 8) - soc_dai->capture.channels_max = val; - } ret = devm_snd_soc_register_component(&pdev->dev, &rockchip_i2s_component, - soc_dai, 1); + dai, 1); if (ret) { dev_err(&pdev->dev, "Could not register DAI\n"); -- cgit v1.2.3-59-g8ed1b