ASoC: rockchip: i2s: Add support for DLP

This patch add support DMA-based digital loopback for I2S.

Ref: commit 9975bc50f3 ("ASoC: rockchip: Add support for Digital Loopback")

Signed-off-by: Sugar Zhang <sugar.zhang@rock-chips.com>
Change-Id: I8a0ea59b216e18ed8c9758f529ef600a333913d7
This commit is contained in:
Sugar Zhang
2023-10-09 23:25:48 +08:00
committed by Tao Huang
parent db8f1a338e
commit 336c6579db
2 changed files with 49 additions and 4 deletions

View File

@@ -21,6 +21,7 @@
#include <sound/dmaengine_pcm.h>
#include "rockchip_i2s.h"
#include "rockchip_dlp_pcm.h"
#define DRV_NAME "rockchip-i2s"
@@ -798,7 +799,8 @@ static bool rockchip_i2s_rd_reg(struct device *dev, unsigned int reg)
case I2S_CLR:
case I2S_TXDR:
case I2S_RXDR:
case I2S_FIFOLR:
case I2S_TXFIFOLR:
case I2S_RXFIFOLR:
case I2S_INTSR:
return true;
default:
@@ -811,7 +813,8 @@ static bool rockchip_i2s_volatile_reg(struct device *dev, unsigned int reg)
switch (reg) {
case I2S_INTSR:
case I2S_CLR:
case I2S_FIFOLR:
case I2S_TXFIFOLR:
case I2S_RXFIFOLR:
case I2S_TXDR:
case I2S_RXDR:
return true;
@@ -1016,6 +1019,36 @@ static int rockchip_i2s_keep_clk_always_on(struct rk_i2s_dev *i2s)
return 0;
}
static int rockchip_i2s_get_fifo_count(struct device *dev,
struct snd_pcm_substream *substream)
{
struct rk_i2s_dev *i2s = dev_get_drvdata(dev);
unsigned int tx, rx;
int val = 0;
regmap_read(i2s->regmap, I2S_TXFIFOLR, &tx);
regmap_read(i2s->regmap, I2S_RXFIFOLR, &rx);
if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
val = I2S_FIFOLR_XFL3(tx) +
I2S_FIFOLR_XFL2(tx) +
I2S_FIFOLR_XFL1(tx) +
I2S_FIFOLR_XFL0(tx);
else
/* XFL4 is compatible for old version */
val = I2S_FIFOLR_XFL4(tx) +
I2S_FIFOLR_XFL3(rx) +
I2S_FIFOLR_XFL2(rx) +
I2S_FIFOLR_XFL1(rx) +
I2S_FIFOLR_XFL0(rx);
return val;
}
static const struct snd_dlp_config dconfig = {
.get_fifo_count = rockchip_i2s_get_fifo_count,
};
static int rockchip_i2s_probe(struct platform_device *pdev)
{
struct device_node *node = pdev->dev.of_node;
@@ -1141,7 +1174,11 @@ static int rockchip_i2s_probe(struct platform_device *pdev)
return 0;
}
ret = devm_snd_dmaengine_pcm_register(&pdev->dev, NULL, 0);
if (device_property_read_bool(&pdev->dev, "rockchip,digital-loopback"))
ret = devm_snd_dmaengine_dlp_register(&pdev->dev, &dconfig);
else
ret = devm_snd_dmaengine_pcm_register(&pdev->dev, NULL, 0);
if (ret) {
dev_err(&pdev->dev, "Could not register PCM\n");
goto err_suspend;

View File

@@ -229,7 +229,7 @@ enum {
#define I2S_TXCR (0x0000)
#define I2S_RXCR (0x0004)
#define I2S_CKR (0x0008)
#define I2S_FIFOLR (0x000c)
#define I2S_TXFIFOLR (0x000c)
#define I2S_DMACR (0x0010)
#define I2S_INTCR (0x0014)
#define I2S_INTSR (0x0018)
@@ -237,6 +237,7 @@ enum {
#define I2S_CLR (0x0020)
#define I2S_TXDR (0x0024)
#define I2S_RXDR (0x0028)
#define I2S_RXFIFOLR (0x002c)
/* io direction cfg register */
#define I2S_IO_DIRECTION_MASK (7)
@@ -245,4 +246,11 @@ enum {
#define I2S_IO_4CH_OUT_6CH_IN (6)
#define I2S_IO_2CH_OUT_8CH_IN (7)
/* XFL4 is compatible for old version */
#define I2S_FIFOLR_XFL4(v) (((v) & GENMASK(29, 24)) >> 24)
#define I2S_FIFOLR_XFL3(v) (((v) & GENMASK(23, 18)) >> 18)
#define I2S_FIFOLR_XFL2(v) (((v) & GENMASK(17, 12)) >> 12)
#define I2S_FIFOLR_XFL1(v) (((v) & GENMASK(11, 6)) >> 6)
#define I2S_FIFOLR_XFL0(v) (((v) & GENMASK(5, 0)) >> 0)
#endif /* _ROCKCHIP_IIS_H */