diff options
author | Luca Ceresoli <luca@lucaceresoli.net> | 2019-03-07 22:44:55 +0100 |
---|---|---|
committer | Mark Brown <broonie@kernel.org> | 2019-03-11 17:17:38 +0000 |
commit | 7bf7d0554890c53478ec04d3d4bfced0c881f6c8 (patch) | |
tree | e84d69196cd95b5518dfc56d73ed5ec0f4c3a3f3 /sound/soc/adi | |
parent | 7d7b25d05ef1c5a1a9320190e1eeb55534847558 (diff) |
ASoC: axi-i2s: let both capture and playback be optional
Both the capture and playback channels are optional in the axi_i2s IP
block. Reflect this in the driver by enabling only the channel(s) that
have a DMA.
Signed-off-by: Luca Ceresoli <luca@lucaceresoli.net>
Signed-off-by: Mark Brown <broonie@kernel.org>
Diffstat (limited to 'sound/soc/adi')
-rw-r--r-- | sound/soc/adi/axi-i2s.c | 68 |
1 files changed, 48 insertions, 20 deletions
diff --git a/sound/soc/adi/axi-i2s.c b/sound/soc/adi/axi-i2s.c index 4c23381727a1..273c543e8ff3 100644 --- a/sound/soc/adi/axi-i2s.c +++ b/sound/soc/adi/axi-i2s.c @@ -43,6 +43,9 @@ struct axi_i2s { struct clk *clk; struct clk *clk_ref; + bool has_capture; + bool has_playback; + struct snd_soc_dai_driver dai_driver; struct snd_dmaengine_dai_dma_data capture_dma_data; @@ -136,8 +139,10 @@ static int axi_i2s_dai_probe(struct snd_soc_dai *dai) { struct axi_i2s *i2s = snd_soc_dai_get_drvdata(dai); - snd_soc_dai_init_dma_data(dai, &i2s->playback_dma_data, - &i2s->capture_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; } @@ -151,18 +156,6 @@ static const struct snd_soc_dai_ops axi_i2s_dai_ops = { static struct snd_soc_dai_driver axi_i2s_dai = { .probe = axi_i2s_dai_probe, - .playback = { - .channels_min = 2, - .channels_max = 2, - .rates = SNDRV_PCM_RATE_KNOT, - .formats = SNDRV_PCM_FMTBIT_S32_LE | SNDRV_PCM_FMTBIT_U32_LE, - }, - .capture = { - .channels_min = 2, - .channels_max = 2, - .rates = SNDRV_PCM_RATE_KNOT, - .formats = SNDRV_PCM_FMTBIT_S32_LE | SNDRV_PCM_FMTBIT_U32_LE, - }, .ops = &axi_i2s_dai_ops, .symmetric_rates = 1, }; @@ -178,6 +171,19 @@ static const struct regmap_config axi_i2s_regmap_config = { .max_register = AXI_I2S_REG_STATUS, }; +static void axi_i2s_parse_of(struct axi_i2s *i2s, const struct device_node *np) +{ + struct property *dma_names; + const char *dma_name; + + of_property_for_each_string(np, "dma-names", dma_names, dma_name) { + if (strcmp(dma_name, "rx") == 0) + i2s->has_capture = true; + if (strcmp(dma_name, "tx") == 0) + i2s->has_playback = true; + } +} + static int axi_i2s_probe(struct platform_device *pdev) { struct resource *res; @@ -191,6 +197,8 @@ static int axi_i2s_probe(struct platform_device *pdev) platform_set_drvdata(pdev, i2s); + axi_i2s_parse_of(i2s, pdev->dev.of_node); + res = platform_get_resource(pdev, IORESOURCE_MEM, 0); base = devm_ioremap_resource(&pdev->dev, res); if (IS_ERR(base)) @@ -213,13 +221,29 @@ static int axi_i2s_probe(struct platform_device *pdev) if (ret) return ret; - i2s->playback_dma_data.addr = res->start + AXI_I2S_REG_TX_FIFO; - i2s->playback_dma_data.addr_width = 4; - i2s->playback_dma_data.maxburst = 1; + if (i2s->has_playback) { + axi_i2s_dai.playback.channels_min = 2; + axi_i2s_dai.playback.channels_max = 2; + axi_i2s_dai.playback.rates = SNDRV_PCM_RATE_KNOT; + axi_i2s_dai.playback.formats = + SNDRV_PCM_FMTBIT_S32_LE | SNDRV_PCM_FMTBIT_U32_LE; + + i2s->playback_dma_data.addr = res->start + AXI_I2S_REG_TX_FIFO; + i2s->playback_dma_data.addr_width = 4; + i2s->playback_dma_data.maxburst = 1; + } + + if (i2s->has_capture) { + axi_i2s_dai.capture.channels_min = 2; + axi_i2s_dai.capture.channels_max = 2; + axi_i2s_dai.capture.rates = SNDRV_PCM_RATE_KNOT; + axi_i2s_dai.capture.formats = + SNDRV_PCM_FMTBIT_S32_LE | SNDRV_PCM_FMTBIT_U32_LE; - i2s->capture_dma_data.addr = res->start + AXI_I2S_REG_RX_FIFO; - i2s->capture_dma_data.addr_width = 4; - i2s->capture_dma_data.maxburst = 1; + i2s->capture_dma_data.addr = res->start + AXI_I2S_REG_RX_FIFO; + i2s->capture_dma_data.addr_width = 4; + i2s->capture_dma_data.maxburst = 1; + } i2s->ratnum.num = clk_get_rate(i2s->clk_ref) / 2 / AXI_I2S_BITS_PER_FRAME; i2s->ratnum.den_step = 1; @@ -240,6 +264,10 @@ static int axi_i2s_probe(struct platform_device *pdev) if (ret) goto err_clk_disable; + dev_info(&pdev->dev, "probed, capture %s, playback %s\n", + i2s->has_capture ? "enabled" : "disabled", + i2s->has_playback ? "enabled" : "disabled"); + return 0; err_clk_disable: |