From 480eeafd459f7284d0a40043567c0d20e429569a Mon Sep 17 00:00:00 2001 From: Sugar Zhang Date: Mon, 31 May 2021 10:31:20 +0800 Subject: [PATCH] ASoC: rockchip: i2s-tdm: Delay for reset successfully This patch Adds delay after reset deassert to make sure reset done before do enabling xfer. Considering the follow situation: - i2s_mclk for 8K capture [2.048M] - i2s_hclk for i2s register access [150M] - pclk_cru for cru register access [100M] SW HW i2s reset assert [pclk_cru] | | | delay time | | i2s reset assert [i2s_mclk] i2s reset deassert [pclk_cru] | | | i2s xfer enable [i2s_hclk] | | i2s reset deassert [i2s_mclk] Obviously, pclk_cru(10ns per cycle) is much faster than i2s_mclk (500ns per cycle). so delay should be added after reset deassert to make sure hw reset done. Otherwise, the race between reset and enable xfer maybe break i2s data aligned. Fixes: A 10us delay is enough SW HW i2s reset assert [pclk_cru] | | | delay 10us | | i2s reset assert [i2s_mclk] i2s reset deassert [pclk_cru] | | | delay 10us | | i2s reset deassert [i2s_mclk] i2s xfer enable [i2s_hclk] | | | Change-Id: Id370b0aa13f771053841ce04a554b408e9e3c831 Signed-off-by: Sugar Zhang --- sound/soc/rockchip/rockchip_i2s_tdm.c | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/sound/soc/rockchip/rockchip_i2s_tdm.c b/sound/soc/rockchip/rockchip_i2s_tdm.c index 7ae188c88eab..46ec9416b44b 100644 --- a/sound/soc/rockchip/rockchip_i2s_tdm.c +++ b/sound/soc/rockchip/rockchip_i2s_tdm.c @@ -217,6 +217,8 @@ static void rockchip_snd_xfer_reset_assert(struct rk_i2s_tdm_dev *i2s_tdm, local_irq_restore(flags); break; } + /* delay for reset assert done */ + udelay(10); } static void rockchip_snd_xfer_reset_deassert(struct rk_i2s_tdm_dev *i2s_tdm, @@ -261,6 +263,8 @@ static void rockchip_snd_xfer_reset_deassert(struct rk_i2s_tdm_dev *i2s_tdm, local_irq_restore(flags); break; } + /* delay for reset deassert done */ + udelay(10); } /* @@ -290,9 +294,6 @@ static void rockchip_snd_xfer_sync_reset(struct rk_i2s_tdm_dev *i2s_tdm) rockchip_snd_xfer_reset_assert(i2s_tdm, tx_bank, tx_offset, rx_bank, rx_offset); - - udelay(150); - rockchip_snd_xfer_reset_deassert(i2s_tdm, tx_bank, tx_offset, rx_bank, rx_offset); } @@ -370,8 +371,11 @@ static void rockchip_snd_reset(struct reset_control *rc) return; reset_control_assert(rc); - udelay(1); + /* delay for reset assert done */ + udelay(10); reset_control_deassert(rc); + /* delay for reset deassert done */ + udelay(10); } static void rockchip_snd_txctrl(struct rk_i2s_tdm_dev *i2s_tdm, int on)