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

时间:2024-03-15 21:31:56

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获取。
[RK3399][Android7.1] 调试笔记 --- Audio codec时钟源从BCLK1获取


原理图:

5640和cpu的接法如下:
[RK3399][Android7.1] 调试笔记 --- Audio codec时钟源从BCLK1获取


修改:

移除之前对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.dtsi
index 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.dtsi
index 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.c
index 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.c
index 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]);
-#endif
 
 		if (!(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]);
-#endif
 
 		if (!(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.c
index 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 0
 	snd_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.c
index 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,为什么还能工作?