From 1f93a7dfd1f8d5ff7a5c53246c7534fe2332d6f4 Mon Sep 17 00:00:00 2001 From: hc <hc@nodka.com> Date: Mon, 11 Dec 2023 02:46:07 +0000 Subject: [PATCH] add audio --- kernel/sound/soc/adi/axi-i2s.c | 71 ++++++++++++++++++++++++----------- 1 files changed, 49 insertions(+), 22 deletions(-) diff --git a/kernel/sound/soc/adi/axi-i2s.c b/kernel/sound/soc/adi/axi-i2s.c index 4c23381..8c4dc82 100644 --- a/kernel/sound/soc/adi/axi-i2s.c +++ b/kernel/sound/soc/adi/axi-i2s.c @@ -1,8 +1,7 @@ +// SPDX-License-Identifier: GPL-2.0-only /* * Copyright (C) 2012-2013, Analog Devices Inc. * Author: Lars-Peter Clausen <lars@metafoo.de> - * - * Licensed under the GPL-2. */ #include <linux/clk.h> @@ -42,6 +41,9 @@ struct regmap *regmap; struct clk *clk; struct clk *clk_ref; + + bool has_capture; + bool has_playback; struct snd_soc_dai_driver dai_driver; @@ -136,8 +138,10 @@ { 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 +155,6 @@ 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 +170,19 @@ .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; @@ -190,6 +195,8 @@ return -ENOMEM; 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); @@ -213,13 +220,29 @@ 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->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->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->ratnum.num = clk_get_rate(i2s->clk_ref) / 2 / AXI_I2S_BITS_PER_FRAME; i2s->ratnum.den_step = 1; @@ -240,6 +263,10 @@ 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: -- Gitblit v1.6.2