audio: auge: add HDMIRX SPDIF in support [1/2]
authorJian Xu <jian.xu@amlogic.com>
Wed, 19 Dec 2018 03:19:51 +0000 (11:19 +0800)
committerJianxin Pan <jianxin.pan@amlogic.com>
Wed, 19 Dec 2018 10:47:18 +0000 (02:47 -0800)
PD#SWPL-2956

Problem:
HDMI in DTS/Dolby input has noise when treated to LPCM

Solution:
By default,we are using PAO mode for HDMIRX,but we have not
enabled the PaPb search for 61937 raw data input, after add
that, we can detect the raw data, but it can not by clear when
switch from NONE-LPCM to NONE-LPCM, need add IRQ function to
clear that by sw.we enabled spdif in from HDMIRX, which is  the same
design as txl/txlx.we can get the Pc information now.
also we add a new interface to set spdif in source when hdmirx input.

Verify:
x301

Change-Id: I3c4e8b387308ef862a069c29d15b8b5a9e865564
Signed-off-by: Jian Xu <jian.xu@amlogic.com>
sound/soc/amlogic/auge/extn.c
sound/soc/amlogic/auge/frhdmirx_hw.c
sound/soc/amlogic/auge/frhdmirx_hw.h
sound/soc/amlogic/auge/spdif.c
sound/soc/amlogic/auge/spdif_hw.c
sound/soc/amlogic/auge/spdif_hw.h
sound/soc/amlogic/auge/tdm.c

index c0fe616..55d3e46 100644 (file)
@@ -613,6 +613,72 @@ static int frhdmirx_set_mode(
 
        return 0;
 }
+#ifdef CONFIG_AMLOGIC_MEDIA_TVIN_HDMI
+/* spdif in audio format detect: LPCM or NONE-LPCM */
+struct sppdif_audio_info {
+       unsigned char aud_type;
+       /*IEC61937 package presamble Pc value*/
+       short pc;
+       char *aud_type_str;
+};
+
+static const char *const spdif_audio_type_texts[] = {
+       "LPCM",
+       "AC3",
+       "EAC3",
+       "DTS",
+       "DTS-HD",
+       "TRUEHD",
+       "PAUSE"
+};
+
+static const struct sppdif_audio_info type_texts[] = {
+       {0, 0, "LPCM"},
+       {1, 0x1, "AC3"},
+       {2, 0x15, "EAC3"},
+       {3, 0xb, "DTS-I"},
+       {3, 0x0c, "DTS-II"},
+       {3, 0x0d, "DTS-III"},
+       {3, 0x11, "DTS-IV"},
+       {4, 0, "DTS-HD"},
+       {5, 0x16, "TRUEHD"},
+       {6, 0x103, "PAUSE"},
+       {6, 0x003, "PAUSE"},
+       {6, 0x100, "PAUSE"},
+};
+
+static const struct soc_enum hdmirx_audio_type_enum =
+       SOC_ENUM_SINGLE(SND_SOC_NOPM, 0, ARRAY_SIZE(spdif_audio_type_texts),
+                       spdif_audio_type_texts);
+
+static int hdmiin_check_audio_type(void)
+{
+       int total_num = sizeof(type_texts)/sizeof(struct sppdif_audio_info);
+       int pc = frhdmirx_get_chan_status_pc();
+       int audio_type = 0;
+       int i;
+
+       for (i = 0; i < total_num; i++) {
+               if (pc == type_texts[i].pc) {
+                       audio_type = type_texts[i].aud_type;
+                       break;
+               }
+       }
+
+       pr_debug("%s audio type:%d\n", __func__, audio_type);
+
+       return audio_type;
+}
+
+static int hdmirx_audio_type_get_enum(
+       struct snd_kcontrol *kcontrol,
+       struct snd_ctl_elem_value *ucontrol)
+{
+       ucontrol->value.enumerated.item[0] =
+               hdmiin_check_audio_type();
+       return 0;
+}
+#endif
 
 static const struct snd_kcontrol_new extn_controls[] = {
        /* Out */
@@ -664,6 +730,10 @@ static const struct snd_kcontrol_new extn_controls[] = {
                0,
                aml_get_atmos_audio_edid,
                aml_set_atmos_audio_edid),
+       SOC_ENUM_EXT("HDMIIN Audio Type",
+                        hdmirx_audio_type_enum,
+                        hdmirx_audio_type_get_enum,
+                        NULL),
 #endif
 
 };
@@ -723,8 +793,8 @@ static int extn_platform_probe(struct platform_device *pdev)
        /* Default ARC SRC */
        p_extn->arc_src = 1;
 
-       /* Default: PAO mode */
-       p_extn->hdmirx_mode = 1;
+       /* Default: SPDIF in mode */
+       p_extn->hdmirx_mode = 0;
 
        ret = snd_soc_register_component(&pdev->dev,
                                &extn_component,
index c46f6df..19c55f4 100644 (file)
@@ -84,7 +84,11 @@ void frhdmirx_ctrl(int channels, int src)
        /* PAO mode */
        if (src) {
                audiobus_write(EE_AUDIO_FRHDMIRX_CTRL0,
-                       0x1 << 23 | 0x1 << 22 | 0x1 << 7);
+                       0x1 << 23 | /* slect pao mode */
+                       0x1 << 22 | /* capture input by fall edge*/
+                       0x1 << 7  | /* start sending ch num info out */
+                       0x1 << 8  | /* start detect PAPB */
+                       0x1 << 6    /* chan status sel: pao pc/pd value */);
                return;
        }
 
@@ -101,7 +105,7 @@ void frhdmirx_ctrl(int channels, int src)
                0x1 << 30 | /* chnum_sel */
                lane_mask << 24 | /* chnum_sel */
                0x1 << 22 | /* clk_inv */
-               0x0 << 11 /* req_sel, Sync 4 spdifin by which */
+               0x0 << 11  /* req_sel, Sync 4 spdifin by which */
                );
 
        /* nonpcm2pcm_th */
@@ -110,3 +114,14 @@ void frhdmirx_ctrl(int channels, int src)
        /* enable irq bits */
        frhdmirx_enable_irq_bits(channels, src);
 }
+
+unsigned int frhdmirx_get_chan_status_pc(void)
+{
+       unsigned int val;
+
+       val = audiobus_read(EE_AUDIO_FRHDMIRX_STAT1);
+       return (val >> 16) & 0xff;
+}
+
+
+
index ce51e13..e0ebfe4 100644 (file)
@@ -20,5 +20,5 @@
 extern void frhdmirx_enable(bool enable);
 extern void frhdmirx_src_select(int src);
 extern void frhdmirx_ctrl(int channels, int src);
-
+extern unsigned int frhdmirx_get_chan_status_pc(void);
 #endif
index ce5a88b..ce37b25 100644 (file)
@@ -253,6 +253,7 @@ static int spdifin_audio_type_get_enum(
 
 /* For fake */
 static bool is_mute;
+static int  spdifin_src;
 static int aml_audio_set_spdif_mute(struct snd_kcontrol *kcontrol,
                                        struct snd_ctl_elem_value *ucontrol)
 {
@@ -268,6 +269,36 @@ static int aml_audio_get_spdif_mute(struct snd_kcontrol *kcontrol,
 
        return 0;
 }
+static const char *const spdifin_src_texts[] = {
+       "spdifin pad", "spdifout", "N/A", "HDMIRX"
+};
+
+const struct soc_enum spdifin_src_enum =
+       SOC_ENUM_SINGLE(SND_SOC_NOPM, 0, ARRAY_SIZE(spdifin_src_texts),
+       spdifin_src_texts);
+
+int spdifin_source_get_enum(
+       struct snd_kcontrol *kcontrol,
+       struct snd_ctl_elem_value *ucontrol)
+{
+       ucontrol->value.enumerated.item[0] = spdifin_src;
+       return 0;
+}
+
+int spdifin_source_set_enum(
+       struct snd_kcontrol *kcontrol,
+       struct snd_ctl_elem_value *ucontrol)
+{
+       int src = ucontrol->value.enumerated.item[0];
+
+       if (src > 3) {
+               pr_err("bad parameter for spdifin src set\n");
+               return -1;
+       }
+       spdifin_set_src(src);
+       spdifin_src = src;
+       return 0;
+}
 
 static const struct snd_kcontrol_new snd_spdif_controls[] = {
 
@@ -288,6 +319,10 @@ static const struct snd_kcontrol_new snd_spdif_controls[] = {
        SOC_SINGLE_BOOL_EXT("Audio spdif mute",
                                0, aml_audio_get_spdif_mute,
                                aml_audio_set_spdif_mute),
+       SOC_ENUM_EXT("Audio spdifin source",
+                               spdifin_src_enum,
+                               spdifin_source_get_enum,
+                               spdifin_source_set_enum),
 
 };
 
@@ -556,7 +591,7 @@ static void spdifin_status_event(struct aml_spdif *p_spdif)
                        pr_info("Pd changed\n");
        } else {
                if (intrpt_status & 0x8)
-                       pr_info("CH status changed\n");
+                       pr_debug("CH status changed\n");
 
                if (intrpt_status & 0x10) {
                        int val = spdifin_get_ch_status0to31();
index 496036d..51503dd 100644 (file)
@@ -528,6 +528,11 @@ int spdifin_get_audio_type(void)
        return (val >> 16) & 0xff;
 }
 
+void spdifin_set_src(int src)
+{
+       audiobus_update_bits(EE_AUDIO_SPDIFIN_CTRL0, 0x3 << 4, src << 4);
+}
+
 void spdif_set_channel_status_info(
        struct iec958_chsts *chsts, int spdif_id)
 {
index 51d5e0b..9d25eaa 100644 (file)
@@ -88,4 +88,5 @@ extern void spdif_set_channel_status_info(
 
 extern void spdifout_play_with_zerodata(unsigned int spdif_id);
 extern void spdifout_play_with_zerodata_free(unsigned int spdif_id);
+extern void spdifin_set_src(int src);
 #endif
index 60703fa..4d3b36f 100644 (file)
@@ -55,22 +55,22 @@ static void dump_pcm_setting(struct pcm_setting *setting)
        if (setting == NULL)
                return;
 
-       pr_info("dump_pcm_setting(%p)\n", setting);
-       pr_info("\tpcm_mode(%d)\n", setting->pcm_mode);
-       pr_info("\tsysclk(%d)\n", setting->sysclk);
-       pr_info("\tsysclk_bclk_ratio(%d)\n", setting->sysclk_bclk_ratio);
-       pr_info("\tbclk(%d)\n", setting->bclk);
-       pr_info("\tbclk_lrclk_ratio(%d)\n", setting->bclk_lrclk_ratio);
-       pr_info("\tlrclk(%d)\n", setting->lrclk);
-       pr_info("\ttx_mask(%#x)\n", setting->tx_mask);
-       pr_info("\trx_mask(%#x)\n", setting->rx_mask);
-       pr_info("\tslots(%d)\n", setting->slots);
-       pr_info("\tslot_width(%d)\n", setting->slot_width);
-       pr_info("\tlane_mask_in(%#x)\n", setting->lane_mask_in);
-       pr_info("\tlane_mask_out(%#x)\n", setting->lane_mask_out);
-       pr_info("\tlane_oe_mask_in(%#x)\n", setting->lane_oe_mask_in);
-       pr_info("\tlane_oe_mask_out(%#x)\n", setting->lane_oe_mask_out);
-       pr_info("\tlane_lb_mask_in(%#x)\n", setting->lane_lb_mask_in);
+       pr_debug("dump_pcm_setting(%p)\n", setting);
+       pr_debug("\tpcm_mode(%d)\n", setting->pcm_mode);
+       pr_debug("\tsysclk(%d)\n", setting->sysclk);
+       pr_debug("\tsysclk_bclk_ratio(%d)\n", setting->sysclk_bclk_ratio);
+       pr_debug("\tbclk(%d)\n", setting->bclk);
+       pr_debug("\tbclk_lrclk_ratio(%d)\n", setting->bclk_lrclk_ratio);
+       pr_debug("\tlrclk(%d)\n", setting->lrclk);
+       pr_debug("\ttx_mask(%#x)\n", setting->tx_mask);
+       pr_debug("\trx_mask(%#x)\n", setting->rx_mask);
+       pr_debug("\tslots(%d)\n", setting->slots);
+       pr_debug("\tslot_width(%d)\n", setting->slot_width);
+       pr_debug("\tlane_mask_in(%#x)\n", setting->lane_mask_in);
+       pr_debug("\tlane_mask_out(%#x)\n", setting->lane_mask_out);
+       pr_debug("\tlane_oe_mask_in(%#x)\n", setting->lane_oe_mask_in);
+       pr_debug("\tlane_oe_mask_out(%#x)\n", setting->lane_oe_mask_out);
+       pr_debug("\tlane_lb_mask_in(%#x)\n", setting->lane_lb_mask_in);
 }
 
 struct tdm_chipinfo {
@@ -844,7 +844,7 @@ static int aml_dai_set_tdm_sysclk(struct snd_soc_dai *cpu_dai,
        clk_set_rate(p_tdm->clk, freq * ratio);
        clk_set_rate(p_tdm->mclk, freq);
 
-       pr_info("set mclk:%d, mpll:%d, get mclk:%lu, mpll:%lu\n",
+       pr_debug("set mclk:%d, mpll:%d, get mclk:%lu, mpll:%lu\n",
                freq,
                freq * ratio,
                clk_get_rate(p_tdm->mclk),