audio: codec: add tl1_acodec support for tl1 [1/1]
authorshuyu.li <shuyu.li@amlogic.com>
Wed, 28 Nov 2018 11:24:14 +0000 (19:24 +0800)
committerBo Yang <bo.yang@amlogic.com>
Tue, 4 Dec 2018 08:43:54 +0000 (00:43 -0800)
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 <shuyu.li@amlogic.com>
arch/arm/boot/dts/amlogic/tl1_pxp.dts
arch/arm/boot/dts/amlogic/tl1_t962x2_skt.dts
arch/arm/boot/dts/amlogic/tl1_t962x2_x301.dts
sound/soc/amlogic/auge/tdm.c
sound/soc/amlogic/auge/tdm_hw.c
sound/soc/amlogic/auge/tdm_hw.h
sound/soc/codecs/amlogic/aml_codec_tl1_acodec.c

index abf96db..b688aea 100644 (file)
                status = "disabled";
                reg = <0xff632000 0x1c>;
                tdmout_index = <1>;
+               tdmin_index = <1>;
        };
 
        aml_dtv_demod {
index 1ceb799..ab0b821 100644 (file)
        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 {
                        format = "i2s";
                        mclk-fs = <256>;
                        //continuous-clock;
-                       //bitclock-inversion;
+                       bitclock-inversion;
                        //frame-inversion;
                        /* master mode */
                        bitclock-master = <&tdma>;
                                system-clock-frequency = <12288000>;
                        };
                        tdmacodec: codec {
-                               sound-dai = <&dummy_codec>;
+                               //sound-dai = <&dummy_codec>;
+                               sound-dai = <&tl1_codec>;
                        };
                };
 
index 51d414c..7253137 100644 (file)
        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 {
                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>;
                                system-clock-frequency = <12288000>;
                        };
                        tdmacodec: codec {
-                               sound-dai = <&ad82584f>;
+                               //sound-dai = <&dummy_codec>;
+                               sound-dai = <&ad82584f &tl1_codec>;
                        };
                };
 
                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>;
 
                 */
                samesource_sel = <3>;
 
+               /* In for ACODEC_ADC */
+               acodec_adc = <1>;
+
                status = "okay";
        };
 
index 50b0799..b62b09b 100644 (file)
@@ -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",
index d1f23af..d76614f 100644 (file)
@@ -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)
 {
index a7625b1..103c732 100644 (file)
@@ -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);
 
index 4869c6f..d2673b2 100644 (file)
@@ -26,6 +26,7 @@
 #include <linux/mutex.h>
 #include <linux/io.h>
 #include <linux/of.h>
+#include <linux/of_device.h>
 #include <sound/core.h>
 #include <sound/pcm.h>
 #include <sound/pcm_params.h>
 
 #include <linux/amlogic/iomap.h>
 #include <linux/amlogic/media/sound/auge_utils.h>
-#include <linux/amlogic/media/sound/aiu_regs.h>
 
+#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,
                                        &reg_val);
                if (mute)
-                       reg_val |= DAC_SOFT_MUTE;
+                       reg_val |= (0x1<<DAC_SOFT_MUTE);
                else
-                       reg_val &= ~DAC_SOFT_MUTE;
+                       reg_val &= ~(0x1<<DAC_SOFT_MUTE);
 
-               regmap_write(aml_acodec->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,
                                        &reg_val);
                if (mute)
-                       reg_val |= DAC2_SOFT_MUTE;
+                       reg_val |= (0x1<<DAC2_SOFT_MUTE);
                else
-                       reg_val &= ~DAC2_SOFT_MUTE;
+                       reg_val &= ~(0x1<<DAC2_SOFT_MUTE);
 
-               regmap_write(aml_acodec->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,
                   },