From 0a0a0b76064c2ad6285525af0b2731769a1d8795 Mon Sep 17 00:00:00 2001 From: Sugar Zhang Date: Sun, 9 Oct 2022 14:31:32 +0800 Subject: [PATCH] ASoC: rockchip: i2s-tdm: Fix FIFO clear error on SLAVE mode Workaround for FIFO clear on SLAVE mode: A Suggest to do reset hclk domain and then do mclk domain, especially for SLAVE mode without CLK in. at last, recovery regmap config. B Suggest to switch to MASTER, and then do FIFO clr, at last, bring back to SLAVE. Now we choose plan B here. Signed-off-by: Sugar Zhang Change-Id: Iac775ff092c6d16e0240459e60fc8112b54f61c6 --- sound/soc/rockchip/rockchip_i2s_tdm.c | 36 ++++++++++++++++++++++++--- 1 file changed, 32 insertions(+), 4 deletions(-) diff --git a/sound/soc/rockchip/rockchip_i2s_tdm.c b/sound/soc/rockchip/rockchip_i2s_tdm.c index de31da12f611..ea886a876fe4 100644 --- a/sound/soc/rockchip/rockchip_i2s_tdm.c +++ b/sound/soc/rockchip/rockchip_i2s_tdm.c @@ -384,9 +384,6 @@ static int rockchip_i2s_tdm_clear(struct rk_i2s_tdm_dev *i2s_tdm, unsigned int val = 0; int ret = 0; - if (!i2s_tdm->is_master_mode) - goto reset; - switch (clr) { case I2S_CLR_TXC: rst = i2s_tdm->tx_reset; @@ -405,11 +402,42 @@ static int rockchip_i2s_tdm_clear(struct rk_i2s_tdm_dev *i2s_tdm, !(val & clr), 10, 100); if (ret < 0) { dev_warn(i2s_tdm->dev, "failed to clear %u\n", clr); - goto reset; + goto clear2; } return 0; +clear2: + /* + * Workaround for FIFO clear on SLAVE mode: + * + * A Suggest to do reset hclk domain and then do mclk + * domain, especially for SLAVE mode without CLK in. + * at last, recovery regmap config. + * + * B Suggest to switch to MASTER, and then do FIFO clr, + * at last, bring back to SLAVE. + * + * Now we choose plan B here. + */ + if (!i2s_tdm->is_master_mode) { + regmap_update_bits(i2s_tdm->regmap, I2S_CKR, + I2S_CKR_MSS_MASK, I2S_CKR_MSS_MASTER); + + ret = regmap_read_poll_timeout_atomic(i2s_tdm->regmap, I2S_CLR, val, + !(val & clr), 10, 100); + + regmap_update_bits(i2s_tdm->regmap, I2S_CKR, + I2S_CKR_MSS_MASK, I2S_CKR_MSS_SLAVE); + + if (ret < 0) { + dev_warn(i2s_tdm->dev, "failed to clear on slave mode %u\n", clr); + goto reset; + } + + return 0; + } + reset: if (i2s_tdm->clk_trcm) rockchip_i2s_tdm_sync_reset(i2s_tdm);