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);