From 860ddcb745ada52c98584821db4a7947aba5a020 Mon Sep 17 00:00:00 2001 From: "shuyu.li" Date: Wed, 28 Nov 2018 19:24:14 +0800 Subject: [PATCH] audio: codec: add tl1_acodec support for tl1 [1/1] PD#SWPL-1759 Problem: add tl1_acodec support Solution: add code, update xxx.dts and aml_codec_tl1_acodec.c Verify: verify by T962x2_X309 board Change-Id: Ia91e4e0f113af3d537d1828c5c4cfabc127eac8f Signed-off-by: shuyu.li --- arch/arm/boot/dts/amlogic/tl1_pxp.dts | 1 + arch/arm/boot/dts/amlogic/tl1_t962x2_skt.dts | 10 +- arch/arm/boot/dts/amlogic/tl1_t962x2_x301.dts | 15 ++- sound/soc/amlogic/auge/tdm.c | 50 +++++++- sound/soc/amlogic/auge/tdm_hw.c | 13 ++- sound/soc/amlogic/auge/tdm_hw.h | 15 ++- sound/soc/codecs/amlogic/aml_codec_tl1_acodec.c | 144 ++++++++++++++++++++---- 7 files changed, 203 insertions(+), 45 deletions(-) diff --git a/arch/arm/boot/dts/amlogic/tl1_pxp.dts b/arch/arm/boot/dts/amlogic/tl1_pxp.dts index abf96db..b688aea 100644 --- a/arch/arm/boot/dts/amlogic/tl1_pxp.dts +++ b/arch/arm/boot/dts/amlogic/tl1_pxp.dts @@ -200,6 +200,7 @@ status = "disabled"; reg = <0xff632000 0x1c>; tdmout_index = <1>; + tdmin_index = <1>; }; aml_dtv_demod { diff --git a/arch/arm/boot/dts/amlogic/tl1_t962x2_skt.dts b/arch/arm/boot/dts/amlogic/tl1_t962x2_skt.dts index 1ceb799..ab0b821 100644 --- a/arch/arm/boot/dts/amlogic/tl1_t962x2_skt.dts +++ b/arch/arm/boot/dts/amlogic/tl1_t962x2_skt.dts @@ -219,9 +219,10 @@ tl1_codec:codec { #sound-dai-cells = <0>; compatible = "amlogic, tl1_acodec"; - status = "disabled"; + status = "okay"; reg = <0xff632000 0x1c>; - tdmout_index = <1>; + tdmout_index = <0>; + tdmin_index = <0>; }; aml_dtv_demod { @@ -257,7 +258,7 @@ format = "i2s"; mclk-fs = <256>; //continuous-clock; - //bitclock-inversion; + bitclock-inversion; //frame-inversion; /* master mode */ bitclock-master = <&tdma>; @@ -280,7 +281,8 @@ system-clock-frequency = <12288000>; }; tdmacodec: codec { - sound-dai = <&dummy_codec>; + //sound-dai = <&dummy_codec>; + sound-dai = <&tl1_codec>; }; }; diff --git a/arch/arm/boot/dts/amlogic/tl1_t962x2_x301.dts b/arch/arm/boot/dts/amlogic/tl1_t962x2_x301.dts index 51d414c..7253137 100644 --- a/arch/arm/boot/dts/amlogic/tl1_t962x2_x301.dts +++ b/arch/arm/boot/dts/amlogic/tl1_t962x2_x301.dts @@ -219,9 +219,10 @@ tl1_codec:codec { #sound-dai-cells = <0>; compatible = "amlogic, tl1_acodec"; - status = "disabled"; + status = "okay"; reg = <0xff632000 0x1c>; - tdmout_index = <1>; + tdmout_index = <0>; + tdmin_index = <0>; }; aml_dtv_demod { @@ -252,6 +253,8 @@ compatible = "amlogic, tl1-sound-card"; aml-audio-card,name = "AML-AUGESOUND"; + avout_mute-gpios = <&gpio GPIODV_3 GPIO_ACTIVE_HIGH>; + aml-audio-card,dai-link@0 { format = "i2s"; mclk-fs = <256>; @@ -279,7 +282,8 @@ system-clock-frequency = <12288000>; }; tdmacodec: codec { - sound-dai = <&ad82584f>; + //sound-dai = <&dummy_codec>; + sound-dai = <&ad82584f &tl1_codec>; }; }; @@ -1213,7 +1217,7 @@ compatible = "amlogic, tl1-snd-tdma"; #sound-dai-cells = <0>; - #dai-tdm-lane-slot-mask-in = <1 0>; + dai-tdm-lane-slot-mask-in = <1 0>; dai-tdm-lane-slot-mask-out = <1 1 1 1>; dai-tdm-clk-sel = <0>; @@ -1234,6 +1238,9 @@ */ samesource_sel = <3>; + /* In for ACODEC_ADC */ + acodec_adc = <1>; + status = "okay"; }; diff --git a/sound/soc/amlogic/auge/tdm.c b/sound/soc/amlogic/auge/tdm.c index 50b0799..b62b09b 100644 --- a/sound/soc/amlogic/auge/tdm.c +++ b/sound/soc/amlogic/auge/tdm.c @@ -88,6 +88,9 @@ struct tdm_chipinfo { /* same source */ bool same_src_fn; + + /* ACODEC_ADC function */ + bool adc_fn; }; struct aml_tdm { @@ -111,6 +114,7 @@ struct aml_tdm { int samesource_sel; /* virtual link for i2s to hdmitx */ int i2s2hdmitx; + int acodec_adc; }; static const struct snd_pcm_hardware aml_tdm_hardware = { @@ -490,8 +494,15 @@ static int aml_dai_tdm_prepare(struct snd_pcm_substream *substream, if (toddr_src_get() == FRHDMIRX) { src = FRHDMIRX; - tdm_update_slot_in(p_tdm->actrl, p_tdm->id, HDMIRX_I2S); - } + aml_update_tdmin_src(p_tdm->actrl, + p_tdm->id, + HDMIRX_I2S); + } else if (p_tdm->chipinfo + && p_tdm->chipinfo->adc_fn + && p_tdm->acodec_adc) + aml_update_tdmin_src(p_tdm->actrl, + p_tdm->id, + ACODEC_ADC); pr_info("%s Expected toddr src:%s\n", __func__, @@ -783,6 +794,13 @@ static int aml_dai_set_tdm_fmt(struct snd_soc_dai *cpu_dai, unsigned int fmt) cpu_dai->capture_active, cpu_dai->playback_active); + /* update skew for ACODEC_ADC */ + if (cpu_dai->capture_active + && p_tdm->chipinfo + && p_tdm->chipinfo->adc_fn + && p_tdm->acodec_adc) + aml_update_tdmin_skew(p_tdm->actrl, p_tdm->id, 4); + return 0; } @@ -958,9 +976,17 @@ static int aml_dai_set_tdm_slot(struct snd_soc_dai *cpu_dai, out_lanes = lanes_out_cnt + lanes_oe_out_cnt; in_lanes = lanes_in_cnt + lanes_oe_in_cnt + lanes_lb_cnt; + + if (p_tdm->chipinfo + && p_tdm->chipinfo->adc_fn + && p_tdm->acodec_adc) { + in_src = ACODEC_ADC; + } + if (in_lanes >= 0 && in_lanes <= 4) aml_tdm_set_slot_in(p_tdm->actrl, p_tdm->id, in_src, slot_width); + if (out_lanes >= 0 && out_lanes <= 4) aml_tdm_set_slot_out(p_tdm->actrl, p_tdm->id, slots, slot_width, @@ -1116,6 +1142,7 @@ struct tdm_chipinfo tl1_tdma_chipinfo = { .oe_fn = true, .clk_pad_ctl = true, .same_src_fn = true, + .adc_fn = true, }; struct tdm_chipinfo tl1_tdmb_chipinfo = { @@ -1124,6 +1151,7 @@ struct tdm_chipinfo tl1_tdmb_chipinfo = { .oe_fn = true, .clk_pad_ctl = true, .same_src_fn = true, + .adc_fn = true, }; struct tdm_chipinfo tl1_tdmc_chipinfo = { @@ -1132,6 +1160,7 @@ struct tdm_chipinfo tl1_tdmc_chipinfo = { .oe_fn = true, .clk_pad_ctl = true, .same_src_fn = true, + .adc_fn = true, }; static const struct of_device_id aml_tdm_device_id[] = { @@ -1236,10 +1265,21 @@ static int aml_tdm_platform_probe(struct platform_device *pdev) "Can't retrieve samesrc_sysclk clock\n"); return PTR_ERR(p_tdm->samesrc_sysclk); } + pr_info("TDM id %d samesource_sel:%d\n", + p_tdm->id, + p_tdm->samesource_sel); } - pr_info("TDM id %d samesource_sel:%d\n", - p_tdm->id, - p_tdm->samesource_sel); + } + /* default no acodec_adc */ + if (p_tdm->chipinfo && + p_tdm->chipinfo->adc_fn) { + + ret = of_property_read_u32(node, "acodec_adc", + &p_tdm->acodec_adc); + if (ret < 0) + p_tdm->acodec_adc = 0; + else + pr_info("TDM id %d supports ACODEC_ADC\n", p_tdm->id); } ret = of_property_read_u32(node, "i2s2hdmi", diff --git a/sound/soc/amlogic/auge/tdm_hw.c b/sound/soc/amlogic/auge/tdm_hw.c index d1f23af..d76614f 100644 --- a/sound/soc/amlogic/auge/tdm_hw.c +++ b/sound/soc/amlogic/auge/tdm_hw.c @@ -403,6 +403,17 @@ void aml_tdm_set_format( } } +void aml_update_tdmin_skew(struct aml_audio_controller *actrl, + int idx, int skew) +{ + unsigned int reg_in, off_set; + + off_set = EE_AUDIO_TDMIN_B_CTRL - EE_AUDIO_TDMIN_A_CTRL; + reg_in = EE_AUDIO_TDMIN_A_CTRL + off_set * idx; + aml_audiobus_update_bits(actrl, reg_in, + 0x7 << 16, skew << 16); +} + void aml_tdm_set_slot_out( struct aml_audio_controller *actrl, int index, int slots, int slot_width, @@ -457,7 +468,7 @@ else 0xf << 20 | 0x1f, in_src << 20 | (slot_width-1)); } -void tdm_update_slot_in( +void aml_update_tdmin_src( struct aml_audio_controller *actrl, int index, int in_src) { diff --git a/sound/soc/amlogic/auge/tdm_hw.h b/sound/soc/amlogic/auge/tdm_hw.h index a7625b1..103c732 100644 --- a/sound/soc/amlogic/auge/tdm_hw.h +++ b/sound/soc/amlogic/auge/tdm_hw.h @@ -26,11 +26,11 @@ enum tdmin_src { PAD_TDMINA_DIN = 0, PAD_TDMINB_DIN = 1, PAD_TDMINC_DIN = 2, - PAD_TDMINA_D = 4, - PAD_TDMINB_D = 5, - PAD_TDMINC_D = 6, - HDMIRX_I2S = 7, - ACODEC_ADC = 8, + PAD_TDMINA_D = 3, + PAD_TDMINB_D = 4, + PAD_TDMINC_D = 5, + HDMIRX_I2S = 6, + ACODEC_ADC = 7, TDMOUTA = 13, TDMOUTB = 14, TDMOUTC = 15, @@ -88,6 +88,9 @@ extern void aml_tdm_set_format( unsigned int capture_active, unsigned int playback_active); +extern void aml_update_tdmin_skew(struct aml_audio_controller *actrl, + int idx, int skew); + extern void aml_tdm_set_slot_out( struct aml_audio_controller *actrl, int index, int slots, int slot_width, @@ -97,7 +100,7 @@ extern void aml_tdm_set_slot_in( struct aml_audio_controller *actrl, int index, int in_src, int slot_width); -extern void tdm_update_slot_in( +extern void aml_update_tdmin_src( struct aml_audio_controller *actrl, int index, int in_src); diff --git a/sound/soc/codecs/amlogic/aml_codec_tl1_acodec.c b/sound/soc/codecs/amlogic/aml_codec_tl1_acodec.c index 4869c6f..d2673b2 100644 --- a/sound/soc/codecs/amlogic/aml_codec_tl1_acodec.c +++ b/sound/soc/codecs/amlogic/aml_codec_tl1_acodec.c @@ -26,6 +26,7 @@ #include #include #include +#include #include #include #include @@ -37,21 +38,43 @@ #include #include -#include +#include "../../../soc/amlogic/auge/iomap.h" +#include "../../../soc/amlogic/auge/regs.h" #include "aml_codec_tl1_acodec.h" +struct tl1_acodec_chipinfo { + int id; + bool is_bclk_cap_inv; //default true + bool is_bclk_o_inv; //default false + bool is_lrclk_inv; //default false + bool is_dac_phase_differ_exist; + bool is_adc_phase_differ_exist; + int mclk_sel; +}; + struct tl1_acodec_priv { struct snd_soc_codec *codec; struct snd_pcm_hw_params *params; struct regmap *regmap; - + struct tl1_acodec_chipinfo *chipinfo; int tdmout_index; + int dat0_ch_sel; + int dat1_ch_sel; + + int tdmin_index; + int adc_output_sel; + //int input_data_sel; //tdmouta,tdmoutb, + //tdmouta,tdmoutb,tdmoutc,tdmina,tdminb,tdminc + //int clk_sel; + //tdmouta,tdmoutb,tdmoutc,none,tdmina,tdminb,tdminc + int dac1_input_sel; + int dac2_input_sel; }; static const struct reg_default tl1_acodec_init_list[] = { {ACODEC_0, 0x3403BFCF}, - {ACODEC_1, 0x50502929}, + {ACODEC_1, 0x50503030}, {ACODEC_2, 0xFBFB0000}, {ACODEC_3, 0x00002222}, {ACODEC_4, 0x00010000}, @@ -59,6 +82,18 @@ static const struct reg_default tl1_acodec_init_list[] = { {ACODEC_6, 0x0}, {ACODEC_7, 0x0} }; +static struct tl1_acodec_chipinfo tl1_acodec_cinfo = { + .id = 0, + .is_bclk_cap_inv = true, //default true + .is_bclk_o_inv = false, //default false + .is_lrclk_inv = false, + + .is_dac_phase_differ_exist = false, + .is_adc_phase_differ_exist = true, + //if is_adc_phase_differ=true,modified tdmin_in_rev_ws,revert ws(lrclk); + //0 :disable; 1: enable; + //.mclk_sel = 1, +}; static int tl1_acodec_reg_init(struct snd_soc_codec *codec) { @@ -115,7 +150,7 @@ static int aml_DAC_Gain_set_enum( pr_info("It has risk of distortion!\n"); } - snd_soc_write(codec, val, reg_addr); + snd_soc_write(codec, reg_addr, val); return 0; } @@ -163,7 +198,7 @@ static int aml_DAC2_Gain_set_enum( pr_info("It has risk of distortion!\n"); } - snd_soc_write(codec, val, reg_addr); + snd_soc_write(codec, reg_addr, val); return 0; } @@ -519,34 +554,34 @@ static int tl1_acodec_dai_mute_stream(struct snd_soc_dai *dai, int mute, struct tl1_acodec_priv *aml_acodec = snd_soc_codec_get_drvdata(dai->codec); u32 reg_val; + int ret; pr_debug("%s, mute:%d\n", __func__, mute); if (stream == SNDRV_PCM_STREAM_PLAYBACK) { /* DAC 1 */ - regmap_read(aml_acodec->regmap, + ret = regmap_read(aml_acodec->regmap, ACODEC_2, ®_val); if (mute) - reg_val |= DAC_SOFT_MUTE; + reg_val |= (0x1<regmap, + ret = regmap_write(aml_acodec->regmap, ACODEC_2, reg_val); - /* DAC 2 */ - regmap_read(aml_acodec->regmap, + ret = regmap_read(aml_acodec->regmap, ACODEC_6, ®_val); if (mute) - reg_val |= DAC2_SOFT_MUTE; + reg_val |= (0x1<regmap, + ret = regmap_write(aml_acodec->regmap, ACODEC_6, reg_val); } @@ -577,12 +612,9 @@ static int tl1_acodec_probe(struct snd_soc_codec *codec) tl1_acodec_start_up(codec); tl1_acodec_reg_init(codec); - if (aml_acodec) - auge_toacodec_ctrl(aml_acodec->tdmout_index); - aml_acodec->codec = codec; tl1_acodec_dai_set_bias_level(codec, SND_SOC_BIAS_STANDBY); - + pr_info("%s\n", __func__); return 0; } @@ -667,10 +699,50 @@ struct snd_soc_dai_driver aml_tl1_acodec_dai = { }, .ops = &tl1_acodec_dai_ops, }; +static int tl1_acodec_set_toacodec(struct tl1_acodec_priv *aml_acodec) +{ + int dat0_sel, dat1_sel, lrclk_sel, bclk_sel, mclk_sel; + unsigned int update_bits_msk = 0x0, update_bits = 0x0; + + update_bits_msk = 0x80FF7777; + if (aml_acodec->chipinfo->is_bclk_cap_inv == true) + update_bits |= (0x1<<9); + if (aml_acodec->chipinfo->is_bclk_o_inv == true) + update_bits |= (0x1<<8); + if (aml_acodec->chipinfo->is_lrclk_inv == true) + update_bits |= (0x1<<10); + + dat0_sel = (aml_acodec->tdmout_index<<2)+aml_acodec->dat0_ch_sel; + dat0_sel = dat0_sel<<16; + dat1_sel = (aml_acodec->tdmout_index<<2)+aml_acodec->dat1_ch_sel; + dat1_sel = dat1_sel<<20; + lrclk_sel = (aml_acodec->tdmout_index)<<12; + bclk_sel = (aml_acodec->tdmout_index)<<4; + + //mclk_sel = aml_acodec->chipinfo->mclk_sel; + mclk_sel = aml_acodec->tdmin_index; + + update_bits |= dat0_sel|dat1_sel|lrclk_sel|bclk_sel|mclk_sel; + update_bits |= 0x1<<31; + + audiobus_update_bits(EE_AUDIO_TOACODEC_CTRL0, update_bits_msk, + update_bits); + pr_info("%s, is_bclk_cap_inv %s\n", __func__, + aml_acodec->chipinfo->is_bclk_cap_inv?"true":"false"); + pr_info("%s, is_bclk_o_inv %s\n", __func__, + aml_acodec->chipinfo->is_bclk_o_inv?"true":"false"); + pr_info("%s, is_lrclk_inv %s\n", __func__, + aml_acodec->chipinfo->is_lrclk_inv?"true":"false"); + pr_info("%s read EE_AUDIO_TOACODEC_CTRL0=0x%08x\n", __func__, + audiobus_read(EE_AUDIO_TOACODEC_CTRL0)); + + return 0; +} static int aml_tl1_acodec_probe(struct platform_device *pdev) { struct tl1_acodec_priv *aml_acodec; + struct tl1_acodec_chipinfo *p_chipinfo; struct resource *res_mem; struct device_node *np; void __iomem *regs; @@ -684,6 +756,13 @@ static int aml_tl1_acodec_probe(struct platform_device *pdev) GFP_KERNEL); if (!aml_acodec) return -ENOMEM; + /* match data */ + p_chipinfo = (struct tl1_acodec_chipinfo *) + of_device_get_match_data(&pdev->dev); + if (!p_chipinfo) + dev_warn_once(&pdev->dev, "check whether to update tl1_acodec_chipinfo\n"); + + aml_acodec->chipinfo = p_chipinfo; res_mem = platform_get_resource(pdev, IORESOURCE_MEM, 0); if (!res_mem) @@ -695,24 +774,36 @@ static int aml_tl1_acodec_probe(struct platform_device *pdev) aml_acodec->regmap = devm_regmap_init_mmio(&pdev->dev, regs, &tl1_acodec_regmap_config); + if (IS_ERR(aml_acodec->regmap)) + return PTR_ERR(aml_acodec->regmap); of_property_read_u32( pdev->dev.of_node, "tdmout_index", &aml_acodec->tdmout_index); - - pr_info("aml_tl1_acodec is used by tdmout:%d\n", + pr_info("aml_tl1_acodec tdmout_index=%d\n", aml_acodec->tdmout_index); - if (IS_ERR(aml_acodec->regmap)) - return PTR_ERR(aml_acodec->regmap); + of_property_read_u32( + pdev->dev.of_node, + "tdmin_index", + &aml_acodec->tdmin_index); + pr_info("aml_tl1_acodec tdmin_index=%d\n", + aml_acodec->tdmin_index); + + tl1_acodec_set_toacodec(aml_acodec); platform_set_drvdata(pdev, aml_acodec); ret = snd_soc_register_codec(&pdev->dev, &soc_codec_dev_tl1_acodec, &aml_tl1_acodec_dai, 1); - + if (ret) + pr_info("%s call snd_soc_register_codec error\n", __func__); + else + pr_info("%s over\n", __func__); + pr_info("%s read EE_AUDIO_TOACODEC_CTRL0=0x%08x\n", __func__, + audiobus_read(EE_AUDIO_TOACODEC_CTRL0)); return ret; } @@ -735,13 +826,16 @@ static void aml_tl1_acodec_shutdown(struct platform_device *pdev) } static const struct of_device_id aml_tl1_acodec_dt_match[] = { - {.compatible = "amlogic, tl1_codec",}, + { + .compatible = "amlogic, tl1_acodec", + .data = &tl1_acodec_cinfo, + }, {}, }; static struct platform_driver aml_tl1_acodec_platform_driver = { .driver = { - .name = "tl1_codec", + .name = "tl1_acodec", .owner = THIS_MODULE, .of_match_table = aml_tl1_acodec_dt_match, }, -- 2.7.4