From e3e12f52b214121840b44c91de5b3e5af5d3eb84 Mon Sep 17 00:00:00 2001 From: hc <hc@nodka.com> Date: Mon, 06 Nov 2023 03:04:41 +0000 Subject: [PATCH] rk3568 rt init --- kernel/sound/soc/rockchip/rockchip_i2s.c | 120 +++++++++++++++++++++++++++++++++--------------------------- 1 files changed, 66 insertions(+), 54 deletions(-) diff --git a/kernel/sound/soc/rockchip/rockchip_i2s.c b/kernel/sound/soc/rockchip/rockchip_i2s.c index 262a954..5af12e4 100644 --- a/kernel/sound/soc/rockchip/rockchip_i2s.c +++ b/kernel/sound/soc/rockchip/rockchip_i2s.c @@ -61,6 +61,7 @@ bool is_master_mode; const struct rk_i2s_pins *pins; unsigned int bclk_fs; + spinlock_t lock; /* tx/rx lock */ unsigned int clk_trcm; unsigned int mclk_root_rate; @@ -69,9 +70,6 @@ bool mclk_calibrate; }; - -/* txctrl/rxctrl lock */ -static DEFINE_SPINLOCK(lock); static int i2s_runtime_suspend(struct device *dev) { @@ -124,12 +122,51 @@ regcache_sync(i2s->regmap); } +static int rockchip_i2s_clear(struct rk_i2s_dev *i2s) +{ + unsigned int clr = I2S_CLR_TXC | I2S_CLR_RXC; + unsigned int val = 0; + int ret; + + /* + * 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->is_master_mode) + regmap_update_bits(i2s->regmap, I2S_CKR, + I2S_CKR_MSS_MASK, I2S_CKR_MSS_MASTER); + regmap_update_bits(i2s->regmap, I2S_CLR, clr, clr); + + ret = regmap_read_poll_timeout_atomic(i2s->regmap, I2S_CLR, val, + !(val & clr), 10, 100); + if (!i2s->is_master_mode) + regmap_update_bits(i2s->regmap, I2S_CKR, + I2S_CKR_MSS_MASK, I2S_CKR_MSS_SLAVE); + if (ret < 0) { + dev_warn(i2s->dev, "failed to clear fifo on %s mode\n", + i2s->is_master_mode ? "master" : "slave"); + goto reset; + } + + return 0; + +reset: + rockchip_i2s_reset(i2s); + + return ret; +} + static void rockchip_snd_txctrl(struct rk_i2s_dev *i2s, int on) { - unsigned int val = 0; - int retry = 10; - - spin_lock(&lock); + spin_lock(&i2s->lock); if (on) { regmap_update_bits(i2s->regmap, I2S_DMACR, I2S_DMACR_TDE_ENABLE, I2S_DMACR_TDE_ENABLE); @@ -153,33 +190,15 @@ I2S_XFER_RXS_STOP); udelay(150); - regmap_update_bits(i2s->regmap, I2S_CLR, - I2S_CLR_TXC | I2S_CLR_RXC, - I2S_CLR_TXC | I2S_CLR_RXC); - - regmap_read(i2s->regmap, I2S_CLR, &val); - - /* Should wait for clear operation to finish */ - while (val) { - regmap_read(i2s->regmap, I2S_CLR, &val); - retry--; - if (!retry) { - dev_warn(i2s->dev, "reset\n"); - rockchip_i2s_reset(i2s); - break; - } - } + rockchip_i2s_clear(i2s); } } - spin_unlock(&lock); + spin_unlock(&i2s->lock); } static void rockchip_snd_rxctrl(struct rk_i2s_dev *i2s, int on) { - unsigned int val = 0; - int retry = 10; - - spin_lock(&lock); + spin_lock(&i2s->lock); if (on) { regmap_update_bits(i2s->regmap, I2S_DMACR, I2S_DMACR_RDE_ENABLE, I2S_DMACR_RDE_ENABLE); @@ -203,25 +222,10 @@ I2S_XFER_RXS_STOP); udelay(150); - regmap_update_bits(i2s->regmap, I2S_CLR, - I2S_CLR_TXC | I2S_CLR_RXC, - I2S_CLR_TXC | I2S_CLR_RXC); - - regmap_read(i2s->regmap, I2S_CLR, &val); - - /* Should wait for clear operation to finish */ - while (val) { - regmap_read(i2s->regmap, I2S_CLR, &val); - retry--; - if (!retry) { - dev_warn(i2s->dev, "reset\n"); - rockchip_i2s_reset(i2s); - break; - } - } + rockchip_i2s_clear(i2s); } } - spin_unlock(&lock); + spin_unlock(&i2s->lock); } static int rockchip_i2s_set_fmt(struct snd_soc_dai *cpu_dai, @@ -779,6 +783,7 @@ if (!i2s) return -ENOMEM; + spin_lock_init(&i2s->lock); i2s->dev = &pdev->dev; i2s->grf = syscon_regmap_lookup_by_phandle(node, "rockchip,grf"); @@ -819,20 +824,23 @@ i2s->mclk = devm_clk_get(&pdev->dev, "i2s_clk"); if (IS_ERR(i2s->mclk)) { dev_err(&pdev->dev, "Can't retrieve i2s master clock\n"); - return PTR_ERR(i2s->mclk); + ret = PTR_ERR(i2s->mclk); + goto err_clk; } - res = platform_get_resource(pdev, IORESOURCE_MEM, 0); - regs = devm_ioremap_resource(&pdev->dev, res); - if (IS_ERR(regs)) - return PTR_ERR(regs); + regs = devm_platform_get_and_ioremap_resource(pdev, 0, &res); + if (IS_ERR(regs)) { + ret = PTR_ERR(regs); + goto err_clk; + } i2s->regmap = devm_regmap_init_mmio(&pdev->dev, regs, &rockchip_i2s_regmap_config); if (IS_ERR(i2s->regmap)) { dev_err(&pdev->dev, "Failed to initialise managed register map\n"); - return PTR_ERR(i2s->regmap); + ret = PTR_ERR(i2s->regmap); + goto err_clk; } i2s->playback_dma_data.addr = res->start + I2S_TXDR; @@ -901,8 +909,11 @@ goto err_suspend; } - if (of_property_read_bool(node, "rockchip,no-dmaengine")) - return ret; + if (of_property_read_bool(node, "rockchip,no-dmaengine")) { + dev_info(&pdev->dev, "Used for Multi-DAI\n"); + return 0; + } + ret = devm_snd_dmaengine_pcm_register(&pdev->dev, NULL, 0); if (ret) { dev_err(&pdev->dev, "Could not register PCM\n"); @@ -916,7 +927,8 @@ i2s_runtime_suspend(&pdev->dev); err_pm_disable: pm_runtime_disable(&pdev->dev); - +err_clk: + clk_disable_unprepare(i2s->hclk); return ret; } -- Gitblit v1.6.2