From fe27c204ebfb2a545b4c2e479e4c1ed9fe773684 Mon Sep 17 00:00:00 2001 From: Sugar Zhang Date: Tue, 3 Nov 2020 15:13:56 +0800 Subject: [PATCH] ASoC: rockchip: i2s-tdm: Fix BUG scheduling while atomic BUG: scheduling while atomic: mediaserver/664/0x00000002 CPU: 0 PID: 664 Comm: mediaserver Tainted: G O 4.19.111 #36 Hardware name: Generic DT based system [] (unwind_backtrace) from [] (show_stack+0x10/0x14) [] (show_stack) from [] (dump_stack+0x90/0xa4) [] (dump_stack) from [] (_schedule_bug+0x64/0x84) [] (_schedule_bug) from [] (_schedule+0x4a4/0x580) [] (_schedule) from [] (schedule+0x50/0xb4) [] (schedule) from [] (schedule_preempt_disabled+0x28/0x40) [] (schedule_preempt_disabled) from [] (_mutex_lock.constprop.7+0x534/0x5c0) [] (_mutex_lock.constprop.7) from [] (clk_prepare_lock+0x50/0xf8) [] (clk_prepare_lock) from [] (clk_set_rate+0x18/0x88) [] (clk_set_rate) from [] (rockchip_i2s_tdm_hw_params+0x88/0x798) [] (rockchip_i2s_tdm_hw_params) from [] (soc_dai_hw_params+0x58/0xa4) [] (soc_dai_hw_params) from [] (soc_pcm_hw_params+0x170/0x55c) [] (soc_pcm_hw_params) from [] (snd_pcm_hw_params+0x124/0x3ac) [] (snd_pcm_hw_params) from [] (snd_pcm_ioctl+0x764/0xcbc) [] (snd_pcm_ioctl) from [] (do_vfs_ioctl+0xac/0x798) [] (do_vfs_ioctl) from [] (ksys_ioctl+0x34/0x58) [] (ksys_ioctl) from [] (ret_fast_syscall+0x0/0x4c) Exception stack(0xdbda3fa8 to 0xdbda3ff0) Fixes: 61559b25ba65 ("ASoC: rockchip: i2s: Set clk rate when master mode") Change-Id: I266efee0f9e5d99ff6d358c4f12e7b9dc7eb6bf8 Signed-off-by: Sugar Zhang --- sound/soc/rockchip/rockchip_i2s_tdm.c | 59 +++++++++++++-------------- 1 file changed, 28 insertions(+), 31 deletions(-) diff --git a/sound/soc/rockchip/rockchip_i2s_tdm.c b/sound/soc/rockchip/rockchip_i2s_tdm.c index 5e2c34d9df1f..090c65a6dcd4 100644 --- a/sound/soc/rockchip/rockchip_i2s_tdm.c +++ b/sound/soc/rockchip/rockchip_i2s_tdm.c @@ -751,13 +751,7 @@ static int rockchip_i2s_tdm_hw_params(struct snd_pcm_substream *substream, struct clk *mclk; int ret = 0; unsigned int val = 0; - unsigned int mclk_rate, bclk_rate, div_bclk, div_lrck; - - if (i2s_tdm->clk_trcm) { - spin_lock(&i2s_tdm->lock); - if (atomic_read(&i2s_tdm->refcount)) - rockchip_i2s_tdm_xfer_pause(substream, i2s_tdm); - } + unsigned int mclk_rate, bclk_rate, div_bclk = 4, div_lrck = 64; if (i2s_tdm->is_master_mode) { if (i2s_tdm->mclk_calibrate) @@ -776,28 +770,6 @@ static int rockchip_i2s_tdm_hw_params(struct snd_pcm_substream *substream, } div_bclk = DIV_ROUND_CLOSEST(mclk_rate, bclk_rate); div_lrck = bclk_rate / params_rate(params); - if (i2s_tdm->clk_trcm) { - regmap_update_bits(i2s_tdm->regmap, I2S_CLKDIV, - I2S_CLKDIV_TXM_MASK | I2S_CLKDIV_RXM_MASK, - I2S_CLKDIV_TXM(div_bclk) | I2S_CLKDIV_RXM(div_bclk)); - regmap_update_bits(i2s_tdm->regmap, I2S_CKR, - I2S_CKR_TSD_MASK | I2S_CKR_RSD_MASK, - I2S_CKR_TSD(div_lrck) | I2S_CKR_RSD(div_lrck)); - } else if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { - regmap_update_bits(i2s_tdm->regmap, I2S_CLKDIV, - I2S_CLKDIV_TXM_MASK, - I2S_CLKDIV_TXM(div_bclk)); - regmap_update_bits(i2s_tdm->regmap, I2S_CKR, - I2S_CKR_TSD_MASK, - I2S_CKR_TSD(div_lrck)); - } else { - regmap_update_bits(i2s_tdm->regmap, I2S_CLKDIV, - I2S_CLKDIV_RXM_MASK, - I2S_CLKDIV_RXM(div_bclk)); - regmap_update_bits(i2s_tdm->regmap, I2S_CKR, - I2S_CKR_RSD_MASK, - I2S_CKR_RSD(div_lrck)); - } } switch (params_format(params)) { @@ -841,6 +813,33 @@ static int rockchip_i2s_tdm_hw_params(struct snd_pcm_substream *substream, goto err; } + if (i2s_tdm->clk_trcm) { + spin_lock(&i2s_tdm->lock); + if (atomic_read(&i2s_tdm->refcount)) + rockchip_i2s_tdm_xfer_pause(substream, i2s_tdm); + + regmap_update_bits(i2s_tdm->regmap, I2S_CLKDIV, + I2S_CLKDIV_TXM_MASK | I2S_CLKDIV_RXM_MASK, + I2S_CLKDIV_TXM(div_bclk) | I2S_CLKDIV_RXM(div_bclk)); + regmap_update_bits(i2s_tdm->regmap, I2S_CKR, + I2S_CKR_TSD_MASK | I2S_CKR_RSD_MASK, + I2S_CKR_TSD(div_lrck) | I2S_CKR_RSD(div_lrck)); + } else if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { + regmap_update_bits(i2s_tdm->regmap, I2S_CLKDIV, + I2S_CLKDIV_TXM_MASK, + I2S_CLKDIV_TXM(div_bclk)); + regmap_update_bits(i2s_tdm->regmap, I2S_CKR, + I2S_CKR_TSD_MASK, + I2S_CKR_TSD(div_lrck)); + } else { + regmap_update_bits(i2s_tdm->regmap, I2S_CLKDIV, + I2S_CLKDIV_RXM_MASK, + I2S_CLKDIV_RXM(div_bclk)); + regmap_update_bits(i2s_tdm->regmap, I2S_CKR, + I2S_CKR_RSD_MASK, + I2S_CKR_RSD(div_lrck)); + } + if (substream->stream == SNDRV_PCM_STREAM_CAPTURE) regmap_update_bits(i2s_tdm->regmap, I2S_RXCR, I2S_RXCR_VDW_MASK | I2S_RXCR_CSR_MASK, @@ -864,8 +863,6 @@ static int rockchip_i2s_tdm_hw_params(struct snd_pcm_substream *substream, return 0; err: - if (i2s_tdm->clk_trcm) - spin_unlock(&i2s_tdm->lock); return ret; }