From 6df60b00fe5241eb5dcfbd832f3d9caf88578544 Mon Sep 17 00:00:00 2001 From: Xing Wang Date: Fri, 21 Jul 2017 16:12:36 +0800 Subject: [PATCH] audio: fix tdm audio format PD#146334: audio: fix tdm bclk and fclk revert and skew issue Change-Id: I1dcb6f8559b3c04a2ddbb7c13a6115001c249c18 Signed-off-by: Xing Wang --- arch/arm64/boot/dts/amlogic/axg_a113d_skt.dts | 17 +-- arch/arm64/boot/dts/amlogic/axg_s400.dts | 8 +- arch/arm64/boot/dts/amlogic/axg_s420.dts | 6 +- sound/soc/amlogic/auge/tdm.c | 6 +- sound/soc/amlogic/auge/tdm_hw.c | 157 +++++++++++++++++--------- sound/soc/amlogic/auge/tdm_hw.h | 4 +- 6 files changed, 121 insertions(+), 77 deletions(-) diff --git a/arch/arm64/boot/dts/amlogic/axg_a113d_skt.dts b/arch/arm64/boot/dts/amlogic/axg_a113d_skt.dts index cd01809..232c6f1 100644 --- a/arch/arm64/boot/dts/amlogic/axg_a113d_skt.dts +++ b/arch/arm64/boot/dts/amlogic/axg_a113d_skt.dts @@ -440,8 +440,8 @@ format = "i2s"; mclk-fs = <256>; continuous-clock; - bitclock-inversion; - frame-inversion; + //bitclock-inversion; + //frame-inversion; //bitclock-master = <&aml_tdmb>; //frame-master = <&aml_tdmb>; cpu { @@ -461,8 +461,8 @@ format = "i2s"; mclk-fs = <256>; continuous-clock; - bitclock-inversion; - frame-inversion; + //bitclock-inversion; + //frame-inversion; //bitclock-master = <&aml_tdmc>; //frame-master = <&aml_tdmc>; cpu { @@ -479,13 +479,7 @@ }; aml-audio-card,dai-link@3 { - format = "i2s"; mclk-fs = <256>; - continuous-clock; - //bitclock-inversion; - //frame-inversion; - bitclock-master = <&aml_pdm>; - frame-master = <&aml_pdm>; cpu { sound-dai = <&aml_pdm>; }; @@ -495,12 +489,9 @@ }; aml-audio-card,dai-link@4 { - //format = "i2s"; mclk-fs = <128>; - continuous-clock; cpu { sound-dai = <&aml_spdif>; - system-clock-frequency = <12288000>; }; codec { sound-dai = <&dummy_codec>; diff --git a/arch/arm64/boot/dts/amlogic/axg_s400.dts b/arch/arm64/boot/dts/amlogic/axg_s400.dts index c6f55dd..fd66b34 100644 --- a/arch/arm64/boot/dts/amlogic/axg_s400.dts +++ b/arch/arm64/boot/dts/amlogic/axg_s400.dts @@ -480,7 +480,7 @@ mclk-fs = <256>; continuous-clock; //bitclock-inversion; - frame-inversion; + //frame-inversion; bitclock-master = <&aml_tdmb>; frame-master = <&aml_tdmb>; cpu { @@ -506,7 +506,7 @@ mclk-fs = <256>; continuous-clock; //bitclock-inversion; - frame-inversion; + //frame-inversion; //bitclock-master = <&aml_tdmc>; //frame-master = <&aml_tdmc>; cpu { @@ -912,8 +912,8 @@ aml_tdma: tdma { compatible = "amlogic, snd-tdma"; #sound-dai-cells = <0>; - dai-tdm-lane-slot-mask-in = <1>; - dai-tdm-lane-slot-mask-out = <1>; + dai-tdm-lane-slot-mask-in = <1 0>; + dai-tdm-lane-slot-mask-out = <0 1>; dai-tdm-clk-sel = <0>; tdm_from_ddr = <0>; tdm_to_ddr = <0>; diff --git a/arch/arm64/boot/dts/amlogic/axg_s420.dts b/arch/arm64/boot/dts/amlogic/axg_s420.dts index ac0b8a7..6f87f8b 100644 --- a/arch/arm64/boot/dts/amlogic/axg_s420.dts +++ b/arch/arm64/boot/dts/amlogic/axg_s420.dts @@ -367,7 +367,7 @@ mclk-fs = <256>; continuous-clock; //bitclock-inversion; - frame-inversion; + //frame-inversion; bitclock-master = <&aml_tdmb>; frame-master = <&aml_tdmb>; cpu { @@ -388,7 +388,7 @@ continuous-clock; /* tdmb clk using tdmc so no bclk-inv */ //bitclock-inversion; - frame-inversion; + //frame-inversion; bitclock-master = <&aml_tdmc>; frame-master = <&aml_tdmc>; cpu { @@ -762,7 +762,7 @@ dai-tdm-clk-sel = <0>; tdm_from_ddr = <0>; tdm_to_ddr = <0>; - clocks = <&clkc CLKID_MPLL2>; + clocks = <&clkc CLKID_MPLL0>; //&clkaudio CLKID_AUDIO_TDMOUTA //&clkaudio CLKID_AUDIO_MCLK_A>; clock-names = "mpll0", "gate", "mclk"; diff --git a/sound/soc/amlogic/auge/tdm.c b/sound/soc/amlogic/auge/tdm.c index 9e5d337..6dbd44a 100644 --- a/sound/soc/amlogic/auge/tdm.c +++ b/sound/soc/amlogic/auge/tdm.c @@ -336,8 +336,6 @@ static int aml_dai_tdm_startup(struct snd_pcm_substream *substream, struct aml_tdm *p_tdm = snd_soc_dai_get_drvdata(cpu_dai); int ret; - aml_tdm_fifo_reset(p_tdm->actrl, substream->stream, p_tdm->id); - ret = clk_prepare_enable(p_tdm->clk); if (ret) { pr_err("Can't enable mpll clock: %d\n", ret); @@ -624,7 +622,9 @@ static int aml_dai_set_tdm_fmt(struct snd_soc_dai *cpu_dai, unsigned int fmt) fmt, p_tdm, p_tdm->id, p_tdm->clk_sel); aml_tdm_set_format(p_tdm->actrl, - &(p_tdm->setting), p_tdm->clk_sel, p_tdm->id, fmt); + &(p_tdm->setting), p_tdm->clk_sel, p_tdm->id, fmt, + cpu_dai->capture_active, + cpu_dai->playback_active); return 0; } diff --git a/sound/soc/amlogic/auge/tdm_hw.c b/sound/soc/amlogic/auge/tdm_hw.c index 06af3d7..95279c4 100644 --- a/sound/soc/amlogic/auge/tdm_hw.c +++ b/sound/soc/amlogic/auge/tdm_hw.c @@ -18,6 +18,13 @@ #include "tdm_hw.h" +#define MST_CLK_INVERT_PH0_PAD_BCLK (1 << 0) +#define MST_CLK_INVERT_PH0_PAD_FCLK (1 << 1) +#define MST_CLK_INVERT_PH1_TDMIN_BCLK (1 << 2) +#define MST_CLK_INVERT_PH1_TDMIN_FCLK (1 << 3) +#define MST_CLK_INVERT_PH2_TDMOUT_BCLK (1 << 4) +#define MST_CLK_INVERT_PH2_TDMOUT_FCLK (1 << 5) + void aml_tdm_enable( struct aml_audio_controller *actrl, int stream, int index, @@ -80,22 +87,19 @@ void aml_tdm_fifo_ctrl( int bitwidth, int stream, int index) { - unsigned int frddr_type, toddr_type; + unsigned int frddr_type; unsigned int reg, offset; switch (bitwidth) { case 8: frddr_type = 0; - toddr_type = 0; break; case 16: frddr_type = 2; - toddr_type = 2; break; case 24: case 32: frddr_type = 4; - toddr_type = 4; break; default: pr_err("invalid bit_depth: %d\n", @@ -123,20 +127,26 @@ void aml_tdm_set_format( struct pcm_setting *p_config, unsigned int clk_sel, unsigned int index, - unsigned int fmt) + unsigned int fmt, + unsigned int capture_active, + unsigned int playback_active) { unsigned int binv, finv, id; unsigned int valb, valf; unsigned int reg_in, reg_out, off_set; int bclkin_skew, bclkout_skew; int master_mode; + unsigned int clkctl = 0; id = index; + binv = 0; + finv = 0; + switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) { case SND_SOC_DAIFMT_CBM_CFM: valb = SLAVE_A + id; - valf = SLAVE_A; + valf = SLAVE_A + id; master_mode = 0; break; case SND_SOC_DAIFMT_CBS_CFS: @@ -162,28 +172,47 @@ void aml_tdm_set_format( switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) { case SND_SOC_DAIFMT_I2S: + bclkout_skew = 1; + bclkin_skew = 3; + + clkctl |= MST_CLK_INVERT_PH0_PAD_FCLK; + if (!master_mode) + finv = 1; + if (master_mode) { - bclkout_skew = 1; - bclkin_skew = 3; + clkctl |= MST_CLK_INVERT_PH0_PAD_BCLK; + if (capture_active) + binv |= 1; } else { - bclkout_skew = 2; - bclkin_skew = 3; + if (playback_active) + binv |= 1; } + break; case SND_SOC_DAIFMT_DSP_A: - if (master_mode) { - bclkout_skew = 1; - bclkin_skew = 4; - } else { - bclkout_skew = 2; - bclkin_skew = 3; - } + /* + * Frame high, 1clk before data, one bit for frame sync, + * frame sync starts one serial clock cycle earlier, + * that is, together with the last bit of the previous + * data word. + */ + bclkout_skew = 1; + bclkin_skew = 3; + + if (capture_active) + binv |= 1; break; case SND_SOC_DAIFMT_LEFT_J: case SND_SOC_DAIFMT_DSP_B: - //TODO: need test + /* + * Frame high, one bit for frame sync, + * frame sync asserts with the first bit of the frame. + */ bclkout_skew = 2; bclkin_skew = 2; + + if (capture_active) + binv |= 1; break; default: return; @@ -191,69 +220,91 @@ void aml_tdm_set_format( p_config->pcm_mode = fmt & SND_SOC_DAIFMT_FORMAT_MASK; + pr_info("pad clk ctl value:%x\n", clkctl); /* set lrclk/bclk invertion */ switch (fmt & SND_SOC_DAIFMT_INV_MASK) { case SND_SOC_DAIFMT_IB_IF: /* Invert both clocks */ - binv = 1; - finv = 1; + if (!master_mode) + binv ^= 1; + + finv |= 1; + clkctl ^= MST_CLK_INVERT_PH0_PAD_BCLK; + clkctl ^= MST_CLK_INVERT_PH0_PAD_FCLK; break; case SND_SOC_DAIFMT_IB_NF: /* Invert bit clock */ - binv = 1; - finv = 0; + if (!master_mode) + binv ^= 1; + clkctl ^= MST_CLK_INVERT_PH0_PAD_BCLK; break; case SND_SOC_DAIFMT_NB_IF: /* Invert frame clock */ - binv = 0; - finv = 1; + finv ^= 1; + clkctl ^= MST_CLK_INVERT_PH0_PAD_FCLK; break; case SND_SOC_DAIFMT_NB_NF: /* normal cases */ - binv = 0; - finv = 0; break; default: return; } + pr_info("sclk_ph0 (pad) clk ctl set:%x\n", clkctl); + /* clk ctrl: delay line and invert clk */ + /*clkctl |= 0x88880000;*/ + if (master_mode) { + off_set = EE_AUDIO_MST_B_SCLK_CTRL1 - EE_AUDIO_MST_A_SCLK_CTRL1; + reg_out = EE_AUDIO_MST_A_SCLK_CTRL1 + off_set * id; + + aml_audiobus_update_bits(actrl, reg_out, 0x3f, clkctl); + } pr_info("master_mode(%d), binv(%d), finv(%d) out_skew(%d), in_skew(%d)\n", master_mode, binv, finv, bclkout_skew, bclkin_skew); /* TDM out */ - reg_out = EE_AUDIO_CLK_TDMOUT_A_CTRL + id; - aml_audiobus_update_bits(actrl, reg_out, - 0x3<<30|0x1<<29, 0x3<<30/*|binv<<29*/); - // sclk_ph0 (pad) invert - off_set = EE_AUDIO_MST_B_SCLK_CTRL1 - EE_AUDIO_MST_A_SCLK_CTRL1; - reg_out = EE_AUDIO_MST_A_SCLK_CTRL1 + off_set * id; - aml_audiobus_update_bits(actrl, reg_out, 0x3f, !binv); - if (!binv) - bclkin_skew = 4; - - off_set = EE_AUDIO_TDMOUT_B_CTRL0 - EE_AUDIO_TDMOUT_A_CTRL0; - reg_out = EE_AUDIO_TDMOUT_A_CTRL0 + off_set * id; - aml_audiobus_update_bits(actrl, reg_out, 0x1f<<15, bclkout_skew<<15); - - off_set = EE_AUDIO_TDMOUT_B_CTRL1 - EE_AUDIO_TDMOUT_A_CTRL1; - reg_out = EE_AUDIO_TDMOUT_A_CTRL1 + off_set * id; - aml_audiobus_update_bits(actrl, reg_out, 0x1<<28, finv<<28); + if (playback_active) { - /* TDM in */ - reg_in = EE_AUDIO_CLK_TDMIN_A_CTRL + id; - aml_audiobus_update_bits(actrl, reg_in, - 0x3<<30|0x1<<29, 0x3<<30|binv<<29); + reg_out = EE_AUDIO_CLK_TDMOUT_A_CTRL + id; + aml_audiobus_update_bits(actrl, reg_out, + 0x3<<30, 0x3<<30); + + aml_audiobus_update_bits(actrl, reg_out, + 0x1<<29, binv<<29); + + off_set = EE_AUDIO_TDMOUT_B_CTRL1 - EE_AUDIO_TDMOUT_A_CTRL1; + reg_out = EE_AUDIO_TDMOUT_A_CTRL1 + off_set * id; + aml_audiobus_update_bits(actrl, reg_out, 0x1<<28, finv<<28); + + off_set = EE_AUDIO_TDMOUT_B_CTRL0 - EE_AUDIO_TDMOUT_A_CTRL0; + reg_out = EE_AUDIO_TDMOUT_A_CTRL0 + off_set * id; + aml_audiobus_update_bits(actrl, reg_out, + 0x1f<<15, bclkout_skew<<15); + } - off_set = EE_AUDIO_TDMIN_B_CTRL - EE_AUDIO_TDMIN_A_CTRL; - reg_in = EE_AUDIO_TDMIN_A_CTRL + off_set * id; - if (p_config->pcm_mode == SND_SOC_DAIFMT_I2S) + /* TDM in */ + if (capture_active) { + reg_in = EE_AUDIO_CLK_TDMIN_A_CTRL + id; aml_audiobus_update_bits(actrl, reg_in, - 1<<30|3<<26|0x1<<25|0x7<<16, - 1<<30|3<<26|1<<25|bclkin_skew<<16); - else + 0x3<<30, 0x3<<30); + + if (master_mode) + aml_audiobus_update_bits(actrl, reg_in, + 0x1<<29, binv<<29); + + off_set = EE_AUDIO_TDMIN_B_CTRL - EE_AUDIO_TDMIN_A_CTRL; + reg_in = EE_AUDIO_TDMIN_A_CTRL + off_set * id; aml_audiobus_update_bits(actrl, reg_in, 3<<26|0x7<<16, 3<<26|bclkin_skew<<16); + aml_audiobus_update_bits(actrl, reg_in, + 0x1<<25, finv<<25); + + if (p_config->pcm_mode == SND_SOC_DAIFMT_I2S) + aml_audiobus_update_bits(actrl, reg_in, + 1<<30, + 1<<30); + } } void aml_tdm_set_slot( diff --git a/sound/soc/amlogic/auge/tdm_hw.h b/sound/soc/amlogic/auge/tdm_hw.h index b093b6d..966cf16 100644 --- a/sound/soc/amlogic/auge/tdm_hw.h +++ b/sound/soc/amlogic/auge/tdm_hw.h @@ -59,7 +59,9 @@ extern void aml_tdm_set_format( struct pcm_setting *p_config, unsigned int clk_sel, unsigned int index, - unsigned int fmt); + unsigned int fmt, + unsigned int capture_active, + unsigned int playback_active); extern void aml_tdm_set_slot( struct aml_audio_controller *actrl, -- 2.7.4