mirror of
https://github.com/hardkernel/linux.git
synced 2026-06-07 03:15:31 +09:00
ASoC: rockchip: i2s-tdm: Fix register write failed on QUIRKS_ALWAYS_ON
CLK_ALWAYS_ON should be placed after all registers write done,
because this situation will enable XFER bit which will make
some registers(depend on XFER) write failed.
Fixes: 3644caf8de ("ASoC: rockchip: i2s-tdm: Add support for clk always-on")
Signed-off-by: Sugar Zhang <sugar.zhang@rock-chips.com>
Change-Id: Iffcfed18d3805ee575df4e8cf267d4ef6a3fa866
This commit is contained in:
@@ -2212,6 +2212,44 @@ static irqreturn_t rockchip_i2s_tdm_isr(int irq, void *devid)
|
||||
return IRQ_HANDLED;
|
||||
}
|
||||
|
||||
static int rockchip_i2s_tdm_keep_clk_always_on(struct rk_i2s_tdm_dev *i2s_tdm)
|
||||
{
|
||||
unsigned int mclk_rate = DEFAULT_FS * DEFAULT_MCLK_FS;
|
||||
unsigned int bclk_rate = i2s_tdm->frame_width * DEFAULT_FS;
|
||||
unsigned int div_lrck = i2s_tdm->frame_width;
|
||||
unsigned int div_bclk;
|
||||
int ret;
|
||||
|
||||
div_bclk = DIV_ROUND_CLOSEST(mclk_rate, bclk_rate);
|
||||
|
||||
/* assign generic freq */
|
||||
clk_set_rate(i2s_tdm->mclk_rx, mclk_rate);
|
||||
clk_set_rate(i2s_tdm->mclk_tx, mclk_rate);
|
||||
|
||||
ret = rockchip_i2s_tdm_mclk_reparent(i2s_tdm);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
regmap_update_bits(i2s_tdm->regmap, I2S_CLKDIV,
|
||||
I2S_CLKDIV_RXM_MASK | I2S_CLKDIV_TXM_MASK,
|
||||
I2S_CLKDIV_RXM(div_bclk) | I2S_CLKDIV_TXM(div_bclk));
|
||||
regmap_update_bits(i2s_tdm->regmap, I2S_CKR,
|
||||
I2S_CKR_RSD_MASK | I2S_CKR_TSD_MASK,
|
||||
I2S_CKR_RSD(div_lrck) | I2S_CKR_TSD(div_lrck));
|
||||
|
||||
if (i2s_tdm->clk_trcm)
|
||||
rockchip_i2s_tdm_xfer_trcm_start(i2s_tdm);
|
||||
else
|
||||
rockchip_i2s_tdm_xfer_start(i2s_tdm, SNDRV_PCM_STREAM_PLAYBACK);
|
||||
|
||||
pm_runtime_forbid(i2s_tdm->dev);
|
||||
|
||||
dev_info(i2s_tdm->dev, "CLK-ALWAYS-ON: mclk: %d, bclk: %d, fsync: %d\n",
|
||||
mclk_rate, bclk_rate, DEFAULT_FS);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int rockchip_i2s_tdm_probe(struct platform_device *pdev)
|
||||
{
|
||||
struct device_node *node = pdev->dev.of_node;
|
||||
@@ -2404,36 +2442,6 @@ static int rockchip_i2s_tdm_probe(struct platform_device *pdev)
|
||||
|
||||
pm_runtime_enable(&pdev->dev);
|
||||
|
||||
if (i2s_tdm->quirks & QUIRK_ALWAYS_ON) {
|
||||
unsigned int rate = DEFAULT_FS * DEFAULT_MCLK_FS;
|
||||
unsigned int div_bclk = DEFAULT_FS * DEFAULT_MCLK_FS;
|
||||
unsigned int div_lrck = i2s_tdm->frame_width;
|
||||
|
||||
div_bclk = DIV_ROUND_CLOSEST(rate, div_lrck * DEFAULT_FS);
|
||||
|
||||
/* assign generic freq */
|
||||
clk_set_rate(i2s_tdm->mclk_rx, rate);
|
||||
clk_set_rate(i2s_tdm->mclk_tx, rate);
|
||||
|
||||
ret = rockchip_i2s_tdm_mclk_reparent(i2s_tdm);
|
||||
if (ret)
|
||||
goto err_suspend;
|
||||
|
||||
regmap_update_bits(i2s_tdm->regmap, I2S_CLKDIV,
|
||||
I2S_CLKDIV_RXM_MASK | I2S_CLKDIV_TXM_MASK,
|
||||
I2S_CLKDIV_RXM(div_bclk) | I2S_CLKDIV_TXM(div_bclk));
|
||||
regmap_update_bits(i2s_tdm->regmap, I2S_CKR,
|
||||
I2S_CKR_RSD_MASK | I2S_CKR_TSD_MASK,
|
||||
I2S_CKR_RSD(div_lrck) | I2S_CKR_TSD(div_lrck));
|
||||
|
||||
if (i2s_tdm->clk_trcm)
|
||||
rockchip_i2s_tdm_xfer_trcm_start(i2s_tdm);
|
||||
else
|
||||
rockchip_i2s_tdm_xfer_start(i2s_tdm, SNDRV_PCM_STREAM_PLAYBACK);
|
||||
|
||||
pm_runtime_forbid(&pdev->dev);
|
||||
}
|
||||
|
||||
regmap_update_bits(i2s_tdm->regmap, I2S_DMACR, I2S_DMACR_TDL_MASK,
|
||||
I2S_DMACR_TDL(16));
|
||||
regmap_update_bits(i2s_tdm->regmap, I2S_DMACR, I2S_DMACR_RDL_MASK,
|
||||
@@ -2444,6 +2452,17 @@ static int rockchip_i2s_tdm_probe(struct platform_device *pdev)
|
||||
if (i2s_tdm->soc_data && i2s_tdm->soc_data->init)
|
||||
i2s_tdm->soc_data->init(&pdev->dev, res->start);
|
||||
|
||||
/*
|
||||
* CLK_ALWAYS_ON should be placed after all registers write done,
|
||||
* because this situation will enable XFER bit which will make
|
||||
* some registers(depend on XFER) write failed.
|
||||
*/
|
||||
if (i2s_tdm->quirks & QUIRK_ALWAYS_ON) {
|
||||
ret = rockchip_i2s_tdm_keep_clk_always_on(i2s_tdm);
|
||||
if (ret)
|
||||
goto err_suspend;
|
||||
}
|
||||
|
||||
ret = devm_snd_soc_register_component(&pdev->dev,
|
||||
&rockchip_i2s_tdm_component,
|
||||
i2s_tdm->dai, 1);
|
||||
|
||||
Reference in New Issue
Block a user