summaryrefslogtreecommitdiff
path: root/sound
diff options
context:
space:
mode:
authorSugar Zhang <sugar.zhang@rock-chips.com>2018-11-29 13:05:12 +0800
committerTao Huang <huangtao@rock-chips.com>2018-12-05 18:16:28 +0800
commit5af049f8ebb49b5d6bc288688f66543a62e95c9c (patch)
tree64633020b7d892b803a41a4708a5843ce0328183 /sound
parentd83ced5248207b94078289de1125389fd2b60b9e (diff)
ASoC: rockchip: i2s_tdm: Correct some regmap config
When restoring registers during runtime resume, we must not write to I2S_TXDR which is the transmit FIFO as this queues up a sample to be output and pushes all of the output channels down by one. This can be demonstrated with the speaker-test utility: for i in a b c; do speaker-test -c 2 -s 1; done which should play a test with through the left speaker three times but if the I2S hardware starts runtime suspended the first sample will be played through the right speaker. Fix this by marking I2S_TXDR as volatile (which also requires marking it as readable, even though it technically isn't). This seems to be the most robust fix, the alternative of giving I2S_TXDR a default value is more fragile since it does not prevent regcache writing to the register in all circumstances. While here, also fix the configuration of I2S_RXDR and I2S_FIFOLR; these are not writable so they do not suffer from the same problem as I2S_TXDR but reading from I2S_RXDR does suffer from a similar problem. Change-Id: Id91d3f54f3fda0e9140c9da162b0dff2c3df067b Signed-off-by: Sugar Zhang <sugar.zhang@rock-chips.com>
Diffstat (limited to 'sound')
-rw-r--r--sound/soc/rockchip/rockchip_i2s_tdm.c10
-rw-r--r--sound/soc/rockchip/rockchip_i2s_tdm.h3
2 files changed, 11 insertions, 2 deletions
diff --git a/sound/soc/rockchip/rockchip_i2s_tdm.c b/sound/soc/rockchip/rockchip_i2s_tdm.c
index 35199e843dac..694440cc8309 100644
--- a/sound/soc/rockchip/rockchip_i2s_tdm.c
+++ b/sound/soc/rockchip/rockchip_i2s_tdm.c
@@ -983,9 +983,11 @@ static bool rockchip_i2s_tdm_rd_reg(struct device *dev, unsigned int reg)
case I2S_INTCR:
case I2S_XFER:
case I2S_CLR:
+ case I2S_TXDR:
case I2S_RXDR:
- case I2S_FIFOLR:
+ case I2S_TXFIFOLR:
case I2S_INTSR:
+ case I2S_RXFIFOLR:
case I2S_TDM_TXCR:
case I2S_TDM_RXCR:
case I2S_CLKDIV:
@@ -998,8 +1000,12 @@ static bool rockchip_i2s_tdm_rd_reg(struct device *dev, unsigned int reg)
static bool rockchip_i2s_tdm_volatile_reg(struct device *dev, unsigned int reg)
{
switch (reg) {
+ case I2S_TXFIFOLR:
case I2S_INTSR:
case I2S_CLR:
+ case I2S_TXDR:
+ case I2S_RXDR:
+ case I2S_RXFIFOLR:
return true;
default:
return false;
@@ -1009,6 +1015,8 @@ static bool rockchip_i2s_tdm_volatile_reg(struct device *dev, unsigned int reg)
static bool rockchip_i2s_tdm_precious_reg(struct device *dev, unsigned int reg)
{
switch (reg) {
+ case I2S_RXDR:
+ return true;
default:
return false;
}
diff --git a/sound/soc/rockchip/rockchip_i2s_tdm.h b/sound/soc/rockchip/rockchip_i2s_tdm.h
index eb1f5405b9cc..9f6086feba8c 100644
--- a/sound/soc/rockchip/rockchip_i2s_tdm.h
+++ b/sound/soc/rockchip/rockchip_i2s_tdm.h
@@ -267,7 +267,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)
@@ -275,6 +275,7 @@ enum {
#define I2S_CLR (0x0020)
#define I2S_TXDR (0x0024)
#define I2S_RXDR (0x0028)
+#define I2S_RXFIFOLR (0x002c)
#define I2S_TDM_TXCR (0x0030)
#define I2S_TDM_RXCR (0x0034)
#define I2S_CLKDIV (0x0038)