diff --git a/sound/soc/rockchip/rockchip_i2s.c b/sound/soc/rockchip/rockchip_i2s.c index 9bc29fdd13c5..5c85fefe81e7 100644 --- a/sound/soc/rockchip/rockchip_i2s.c +++ b/sound/soc/rockchip/rockchip_i2s.c @@ -21,6 +21,7 @@ #include #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; diff --git a/sound/soc/rockchip/rockchip_i2s.h b/sound/soc/rockchip/rockchip_i2s.h index 251851bf4f2c..bf71ea59ab0c 100644 --- a/sound/soc/rockchip/rockchip_i2s.h +++ b/sound/soc/rockchip/rockchip_i2s.h @@ -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 */