300字范文,内容丰富有趣,生活中的好帮手!
300字范文 > [RK3399][Android7.1] 调试笔记 --- Audio codec时钟源从BCLK1获取

[RK3399][Android7.1] 调试笔记 --- Audio codec时钟源从BCLK1获取

时间:2021-11-24 22:31:00

相关推荐

[RK3399][Android7.1] 调试笔记 --- Audio codec时钟源从BCLK1获取

Platform: RK3399

OS: Android 7.1

Kernel: v4.4.83

需求:

默认codec的clock source是从I2S1的mclk获取,由于I2S0和I2S1的mclk是共用同一个,

而且同一时刻只有一个I2S模块才能使用,而I2S0需要接麦克阵列,因此I2S1接的RT5640 Codec的时钟源改从BCLK1来获取。

信号源选择方法:

参考RT5640 codec的数据手册中的图,clock source可以从MCLK也可以从PLL获取。

原理图:

5640和cpu的接法如下:

修改:

移除之前对I2S1修改的patch以及添加对5640 clock source的控制。

diff --git a/arch/arm64/boot/dts/rockchip/rk3399-vop-clk-set.dtsi b/arch/arm64/boot/dts/rockchip/rk3399-vop-clk-set.dtsiindex 8a98bbc..0546ed2 100644--- a/arch/arm64/boot/dts/rockchip/rk3399-vop-clk-set.dtsi+++ b/arch/arm64/boot/dts/rockchip/rk3399-vop-clk-set.dtsi@@ -89,12 +89,12 @@assigned-clock-parents = <&cru PLL_GPLL>;};-/* Kris,180906, Fix playback noise issue.+&i2s1 {assigned-clocks = <&cru SCLK_I2S1_DIV>;assigned-clock-parents = <&cru PLL_GPLL>;};-*/+&i2s2 {assigned-clocks = <&cru SCLK_I2S2_DIV>;diff --git a/arch/arm64/boot/dts/rockchip/rk3399.dtsi b/arch/arm64/boot/dts/rockchip/rk3399.dtsiindex 5bf6cb9..109d8ce 100644--- a/arch/arm64/boot/dts/rockchip/rk3399.dtsi+++ b/arch/arm64/boot/dts/rockchip/rk3399.dtsi@@ -1693,9 +1693,6 @@dma-names = "tx", "rx";clock-names = "i2s_clk", "i2s_hclk";clocks = <&cru SCLK_I2S1_8CH>, <&cru HCLK_I2S1_8CH>;-//Kris,180706, porting rt5640 on i2s1.-assigned-clocks = <&cru SCLK_I2S_8CH>;-assigned-clock-parents = <&cru SCLK_I2S1_8CH>;pinctrl-names = "default";pinctrl-0 = <&i2s1_2ch_bus>;power-domains = <&power RK3399_PD_SDIOAUDIO>;diff --git a/drivers/clk/rockchip/clk-rk3399.c b/drivers/clk/rockchip/clk-rk3399.cindex e2d872f..cd7b268 100644--- a/drivers/clk/rockchip/clk-rk3399.c+++ b/drivers/clk/rockchip/clk-rk3399.c@@ -711,9 +711,7 @@ static struct rockchip_clk_branch rk3399_clk_branches[] __initdata = {&rk3399_i2s2_fracmux),GATE(SCLK_I2S2_8CH, "clk_i2s2", "clk_i2s2_mux", CLK_SET_RATE_PARENT,RK3399_CLKGATE_CON(8), 11, GFLAGS),-//Kris,180706, porting rt5640 on i2s1.-//MUX(0, "clk_i2sout_src", mux_i2sch_p, CLK_SET_RATE_PARENT,-MUX(SCLK_I2S_8CH, "clk_i2sout_src", mux_i2sch_p, CLK_SET_RATE_PARENT,+MUX(0, "clk_i2sout_src", mux_i2sch_p, CLK_SET_RATE_PARENT,RK3399_CLKSEL_CON(31), 0, 2, MFLAGS),COMPOSITE_NODIV(SCLK_I2S_8CH_OUT, "clk_i2sout", mux_i2sout_p, CLK_SET_RATE_PARENT,RK3399_CLKSEL_CON(30), 8, 2, MFLAGS,diff --git a/drivers/dma/pl330.c b/drivers/dma/pl330.cindex 08179f5..1e5c79b 100644--- a/drivers/dma/pl330.c+++ b/drivers/dma/pl330.c@@ -1169,16 +1169,6 @@ static inline int _ldst_devtomem(struct pl330_dmac *pl330, unsigned dry_run,off += _emit_WFP(dry_run, &buf[off], cond, pxs->desc->peri);off += _emit_LDP(dry_run, &buf[off], cond, pxs->desc->peri);off += _emit_ST(dry_run, &buf[off], ALWAYS);-#ifdef CONFIG_ARCH_ROCKCHIP-/*- * Make suree dma has finish transmission, or later flush may- * cause dma second transmission,and fifo is overrun.- */-off += _emit_WMB(dry_run, &buf[off]);-off += _emit_NOP(dry_run, &buf[off]);-off += _emit_WMB(dry_run, &buf[off]);-off += _emit_NOP(dry_run, &buf[off]);-#endifif (!(pl330->quirks & PL330_QUIRK_BROKEN_NO_FLUSHP))off += _emit_FLUSHP(dry_run, &buf[off],@@ -1199,16 +1189,6 @@ static inline int _ldst_memtodev(struct pl330_dmac *pl330,off += _emit_WFP(dry_run, &buf[off], cond, pxs->desc->peri);off += _emit_LD(dry_run, &buf[off], ALWAYS);off += _emit_STP(dry_run, &buf[off], cond, pxs->desc->peri);-#ifdef CONFIG_ARCH_ROCKCHIP-/*- * Make suree dma has finish transmission, or later flush may- * cause dma second transmission,and fifo is overrun.- */-off += _emit_WMB(dry_run, &buf[off]);-off += _emit_NOP(dry_run, &buf[off]);-off += _emit_WMB(dry_run, &buf[off]);-off += _emit_NOP(dry_run, &buf[off]);-#endifif (!(pl330->quirks & PL330_QUIRK_BROKEN_NO_FLUSHP))off += _emit_FLUSHP(dry_run, &buf[off],@@ -1347,11 +1327,7 @@ static inline int _loop_cyclic(struct pl330_dmac *pl330, unsigned dry_run,/* forever loop */off += _emit_MOV(dry_run, &buf[off], SAR, x->src_addr);off += _emit_MOV(dry_run, &buf[off], DAR, x->dst_addr);-#ifdef CONFIG_ARCH_ROCKCHIP-if (!(pl330->quirks & PL330_QUIRK_BROKEN_NO_FLUSHP))-off += _emit_FLUSHP(dry_run, &buf[off],-pxs->desc->peri);-#endif+/* loop0 */off += _emit_LP(dry_run, &buf[off], 0, lcnt0);ljmp0 = off;@@ -1390,7 +1366,7 @@ static inline int _loop_cyclic(struct pl330_dmac *pl330, unsigned dry_run,ccr &= ~(0xf << CC_SRCBRSTLEN_SHFT);ccr &= ~(0xf << CC_DSTBRSTLEN_SHFT);off += _emit_MOV(dry_run, &buf[off], CCR, ccr);-off += _emit_LP(dry_run, &buf[off], 1, c);+off += _emit_LP(dry_run, &buf[off], 1, c - 1);ljmp1 = off;off += _bursts(pl330, dry_run, &buf[off], pxs, 1);lpend.cond = ALWAYS;@@ -1427,11 +1403,7 @@ static inline int _setup_loops(struct pl330_dmac *pl330,u32 ccr = pxs->ccr;unsigned long c, bursts = BYTE_TO_BURST(x->bytes, ccr);int off = 0;-#ifdef CONFIG_ARCH_ROCKCHIP-if (!(pl330->quirks & PL330_QUIRK_BROKEN_NO_FLUSHP))-off += _emit_FLUSHP(dry_run, &buf[off],-pxs->desc->peri);-#endif+while (bursts) {c = bursts;off += _loop(pl330, dry_run, &buf[off], &c, pxs);@@ -1785,17 +1757,16 @@ static int pl330_update(struct pl330_dmac *pl330)/* Detach the req */descdone = thrd->req[active].desc;-if (descdone) {-if (!descdone->cyclic) {-thrd->req[active].desc = NULL;-thrd->req_running = -1;-/* Get going again ASAP */-_start(thrd);-}-/* For now, just make a list of callbacks to be done */-list_add_tail(&descdone->rqd, &pl330->req_done);+if (!descdone->cyclic) {+thrd->req[active].desc = NULL;+thrd->req_running = -1;+/* Get going again ASAP */+_start(thrd);}++/* For now, just make a list of callbacks to be done */+list_add_tail(&descdone->rqd, &pl330->req_done);}}@@ -1846,6 +1817,7 @@ static bool _chan_ns(const struct pl330_dmac *pl330, int i)static struct pl330_thread *pl330_request_channel(struct pl330_dmac *pl330){struct pl330_thread *thrd = NULL;+unsigned long flags;int chans, i;if (pl330->state == DYING)@@ -1853,6 +1825,8 @@ static struct pl330_thread *pl330_request_channel(struct pl330_dmac *pl330)chans = pl330->pcfg.num_chan;+spin_lock_irqsave(&pl330->lock, flags);+for (i = 0; i < chans; i++) {thrd = &pl330->channels[i];if ((thrd->free) && (!_manager_ns(thrd) ||@@ -1870,6 +1844,8 @@ static struct pl330_thread *pl330_request_channel(struct pl330_dmac *pl330)thrd = NULL;}+spin_unlock_irqrestore(&pl330->lock, flags);+return thrd;}@@ -1887,6 +1863,7 @@ static inline void _free_event(struct pl330_thread *thrd, int ev)static void pl330_release_channel(struct pl330_thread *thrd){struct pl330_dmac *pl330;+unsigned long flags;if (!thrd || thrd->free)return;@@ -1898,8 +1875,10 @@ static void pl330_release_channel(struct pl330_thread *thrd)pl330 = thrd->dmac;+spin_lock_irqsave(&pl330->lock, flags);_free_event(thrd, thrd->ev);thrd->free = true;+spin_unlock_irqrestore(&pl330->lock, flags);}/* Initialize the structure for PL330 configuration, that can be used@@ -2269,19 +2248,19 @@ static int pl330_alloc_chan_resources(struct dma_chan *chan)struct pl330_dmac *pl330 = pch->dmac;unsigned long flags;-spin_lock_irqsave(&pl330->lock, flags);+spin_lock_irqsave(&pch->lock, flags);dma_cookie_init(chan);pch->thread = pl330_request_channel(pl330);if (!pch->thread) {-spin_unlock_irqrestore(&pl330->lock, flags);+spin_unlock_irqrestore(&pch->lock, flags);return -ENOMEM;}tasklet_init(&pch->task, pl330_tasklet, (unsigned long) pch);-spin_unlock_irqrestore(&pl330->lock, flags);+spin_unlock_irqrestore(&pch->lock, flags);return 1;}@@ -2384,20 +2363,19 @@ static int pl330_pause(struct dma_chan *chan)static void pl330_free_chan_resources(struct dma_chan *chan){struct dma_pl330_chan *pch = to_pchan(chan);-struct pl330_dmac *pl330 = pch->dmac;unsigned long flags;tasklet_kill(&pch->task);pm_runtime_get_sync(pch->dmac->ddma.dev);-spin_lock_irqsave(&pl330->lock, flags);+spin_lock_irqsave(&pch->lock, flags);pl330_release_channel(pch->thread);pch->thread = NULL;list_splice_tail_init(&pch->work_list, &pch->dmac->desc_pool);-spin_unlock_irqrestore(&pl330->lock, flags);+spin_unlock_irqrestore(&pch->lock, flags);pm_runtime_mark_last_busy(pch->dmac->ddma.dev);pm_runtime_put_autosuspend(pch->dmac->ddma.dev);}diff --git a/sound/soc/codecs/rt5640.c b/sound/soc/codecs/rt5640.cindex ee9d1ba..985f9ee 100644--- a/sound/soc/codecs/rt5640.c+++ b/sound/soc/codecs/rt5640.c@@ -1797,6 +1797,10 @@ static int rt5640_hw_params(struct snd_pcm_substream *substream,snd_soc_update_bits(codec, RT5640_ADDA_CLK1, mask_clk, val_clk);}//理论上,PLL的计算是动态自适应的,可能驱动有问题导致计算不对。//后来是找realtek FAE拿的参数数据+/*Kris, 181128, Use BCLK1 as clock source. {*/+snd_soc_update_bits(codec, RT5640_ADDA_CLK1, 0xffff, 0000);+/*Kris, 181128, Use BCLK1 as clock source. }*/+return 0;}@@ -1969,12 +1973,22 @@ static int rt5640_set_dai_pll(struct snd_soc_dai *dai, int pll_id, int source,pll_code.m_bp, (pll_code.m_bp ? 0 : pll_code.m_code),pll_code.n_code, pll_code.k_code);//理论上,PLL的计算是动态自适应的,可能驱动有问题导致计算不对。//后来是找realtek FAE拿的参数数据+/*Kris, 181128, Use BCLK1 as clock source. {*/+#if 0snd_soc_write(codec, RT5640_PLL_CTRL1,pll_code.n_code << RT5640_PLL_N_SFT | pll_code.k_code);snd_soc_write(codec, RT5640_PLL_CTRL2,(pll_code.m_bp ? 0 : pll_code.m_code) << RT5640_PLL_M_SFT |pll_code.m_bp << RT5640_PLL_M_BP_SFT);+#else+snd_soc_write(codec, RT5640_GLB_CLK, 0x5000);+snd_soc_write(codec, RT5640_PLL_CTRL1, 0x0f06);+snd_soc_write(codec, RT5640_PLL_CTRL2, 0x0800);+#endif+/*Kris, 181128, Use BCLK1 as clock source. }*/++rt5640->pll_in = freq_in;rt5640->pll_out = freq_out;rt5640->pll_src = source;diff --git a/sound/soc/generic/simple-card.c b/sound/soc/generic/simple-card.cindex dc971a0..d84eefc 100644--- a/sound/soc/generic/simple-card.c+++ b/sound/soc/generic/simple-card.c@@ -21,6 +21,11 @@#include <sound/soc-dai.h>#include <sound/soc.h>+#include "../codecs/rt5640.h"++++struct simple_card_data {struct snd_soc_card snd_card;struct simple_dai_props {@@ -90,8 +95,25 @@ static int asoc_simple_card_hw_params(struct snd_pcm_substream *substream,if (mclk_fs) {mclk = params_rate(params) * mclk_fs;-ret = snd_soc_dai_set_sysclk(codec_dai, 0, mclk,-SND_SOC_CLOCK_IN);++/*Kris, 181128, Use BCLK1 as clock source. {*///修改对应的时钟源+#if 0+ ret = snd_soc_dai_set_sysclk(codec_dai, 0, mclk, SND_SOC_CLOCK_IN);+#else+ret = snd_soc_dai_set_sysclk(codec_dai, RT5640_SCLK_S_PLL1, mclk * 2, SND_SOC_CLOCK_IN);+if (ret < 0) {+dev_err(codec_dai->dev, "codec_dai sys clock not set\n");+return ret;+}++ret = snd_soc_dai_set_pll(codec_dai, 0, RT5640_PLL1_S_BCLK1, mclk, mclk *2);+if (ret < 0) {+dev_err(codec_dai->dev, "codec_dai pll clock not set\n");+return ret;+}+#endif+/*Kris, 181128, Use BCLK1 as clock source. }*/+if (ret && ret != -ENOTSUPP)goto err;

遗留问题:

RT5640 codec中的BLKC1是指pin脚,那么80h寄存器选的是BCLK2,为什么还能工作?

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。