audio: auge: improve compatibility for eARC RX/TX connection [1/1]
authorXing Wang <xing.wang@amlogic.com>
Wed, 23 Oct 2019 12:19:16 +0000 (20:19 +0800)
committerTao Zeng <tao.zeng@amlogic.com>
Thu, 31 Oct 2019 07:28:53 +0000 (00:28 -0700)
PD#SWPL-15189

Problem:
1. earc rx fails to connect to a sony tv
2. earc tx fails to connect to AVR-X4500H

Solution:
1. reset earc_rx pll
2. reduce comma_th

Verify:
ab311

Change-Id: I162b9697d151b682df01093cdc086330a97f8fab
Signed-off-by: Xing Wang <xing.wang@amlogic.com>
sound/soc/amlogic/auge/earc.c
sound/soc/amlogic/auge/earc_hw.c
sound/soc/amlogic/auge/earc_hw.h
sound/soc/amlogic/auge/locker.c
sound/soc/amlogic/auge/resample.c

index 015e090..427a5ba 100644 (file)
@@ -74,8 +74,8 @@ struct earc {
        struct extcon_dev *rx_edev;
        struct extcon_dev *tx_edev;
 
-       bool tx_dmac_clk_on;
        bool rx_dmac_clk_on;
+       bool tx_dmac_clk_on;
 };
 
 static struct earc *s_earc;
@@ -150,6 +150,9 @@ static irqreturn_t earc_rx_isr(int irq, void *data)
        struct earc *p_earc = (struct earc *)data;
        unsigned int status0 = earcrx_cdmc_get_irqs(p_earc->rx_top_map);
 
+       if (status0)
+               earcrx_cdmc_clr_irqs(p_earc->rx_top_map, status0);
+
        if (status0 & INT_EARCRX_CMDC_IDLE2) {
                earcrx_update_attend_event(p_earc,
                                           false, true);
@@ -172,8 +175,10 @@ static irqreturn_t earc_rx_isr(int irq, void *data)
 
                pr_info("%s EARCRX_CMDC_EARC\n", __func__);
        }
-       if (status0 & INT_EARCRX_CMDC_HB_STATUS)
-               pr_debug("%s EARCRX_CMDC_HB_STATUS\n", __func__);
+       /*
+        * if (status0 & INT_EARCRX_CMDC_HB_STATUS)
+        *      pr_debug("%s EARCRX_CMDC_HB_STATUS\n", __func__);
+        */
        if (status0 & INT_EARCRX_CMDC_LOSTHB)
                pr_debug("%s EARCRX_CMDC_LOSTHB\n", __func__);
        if (status0 & INT_EARCRX_CMDC_TIMEOUT) {
@@ -183,12 +188,12 @@ static irqreturn_t earc_rx_isr(int irq, void *data)
                pr_debug("%s EARCRX_CMDC_TIMEOUT\n", __func__);
        }
 
-       if (status0)
-               earcrx_cdmc_clr_irqs(p_earc->rx_top_map, status0);
-
        if (p_earc->rx_dmac_clk_on) {
                unsigned int status1 = earcrx_dmac_get_irqs(p_earc->rx_top_map);
 
+               if (status1)
+                       earcrx_dmac_clr_irqs(p_earc->rx_top_map, status1);
+
                if (status1 & INT_ARCRX_BIPHASE_DECODE_C_FIND_PAPB)
                        pr_debug("%s ARCRX_C_FIND_PAPB\n", __func__);
                if (status1 & INT_ARCRX_BIPHASE_DECODE_C_VALID_CHANGE)
@@ -203,9 +208,6 @@ static irqreturn_t earc_rx_isr(int irq, void *data)
                        pr_debug("%s ARCRX_I_SAMPLE_MODE_CHANGE\n", __func__);
                if (status1 & INT_ARCRX_BIPHASE_DECODE_R_PARITY_ERR)
                        pr_debug("%s ARCRX_R_PARITY_ERR\n", __func__);
-
-               if (status1)
-                       earcrx_dmac_clr_irqs(p_earc->rx_top_map, status1);
        }
 
        return IRQ_HANDLED;
@@ -216,25 +218,25 @@ static void earctx_update_attend_event(struct earc *p_earc,
 {
        if (state) {
                if (is_earc) {
-                       extcon_set_state_sync(p_earc->rx_edev,
+                       extcon_set_state_sync(p_earc->tx_edev,
                                              EXTCON_EARCTX_ATNDTYP_ARC,
                                              false);
-                       extcon_set_state_sync(p_earc->rx_edev,
+                       extcon_set_state_sync(p_earc->tx_edev,
                                              EXTCON_EARCTX_ATNDTYP_EARC,
                                              state);
                } else {
-                       extcon_set_state_sync(p_earc->rx_edev,
+                       extcon_set_state_sync(p_earc->tx_edev,
                                              EXTCON_EARCTX_ATNDTYP_ARC,
                                              state);
-                       extcon_set_state_sync(p_earc->rx_edev,
+                       extcon_set_state_sync(p_earc->tx_edev,
                                              EXTCON_EARCTX_ATNDTYP_EARC,
                                              false);
                }
        } else {
-               extcon_set_state_sync(p_earc->rx_edev,
+               extcon_set_state_sync(p_earc->tx_edev,
                                      EXTCON_EARCTX_ATNDTYP_ARC,
                                      state);
-               extcon_set_state_sync(p_earc->rx_edev,
+               extcon_set_state_sync(p_earc->tx_edev,
                                      EXTCON_EARCTX_ATNDTYP_EARC,
                                      state);
        }
@@ -245,6 +247,9 @@ static irqreturn_t earc_tx_isr(int irq, void *data)
        struct earc *p_earc = (struct earc *)data;
        unsigned int status0 = earctx_cdmc_get_irqs(p_earc->tx_top_map);
 
+       if (status0)
+               earctx_cdmc_clr_irqs(p_earc->tx_top_map, status0);
+
        if (status0 & INT_EARCTX_CMDC_IDLE2) {
                earctx_update_attend_event(p_earc,
                                           false, true);
@@ -286,12 +291,12 @@ static irqreturn_t earc_tx_isr(int irq, void *data)
        if (status0 & INT_EARCTX_CMDC_RECV_UNEXP)
                pr_debug("%s EARCTX_CMDC_RECV_UNEXP\n", __func__);
 
-       if (status0)
-               earctx_cdmc_clr_irqs(p_earc->tx_top_map, status0);
-
        if (p_earc->tx_dmac_clk_on) {
                unsigned int status1 = earctx_dmac_get_irqs(p_earc->tx_top_map);
 
+               if (status1)
+                       earctx_dmac_clr_irqs(p_earc->tx_top_map, status1);
+
                if (status1 & INT_EARCTX_FEM_C_HOLD_CLR)
                        pr_debug("%s EARCTX_FEM_C_HOLD_CLR\n", __func__);
                if (status1 & INT_EARCTX_FEM_C_HOLD_START)
@@ -304,9 +309,6 @@ static irqreturn_t earc_tx_isr(int irq, void *data)
                                 __func__);
                if (status1 & INT_EARCTX_ERRCORR_C_FIFO_EMPTY)
                        pr_debug("%s EARCTX_ERRCORR_C_FIFO_EMPTY\n", __func__);
-
-               if (status1)
-                       earctx_dmac_clr_irqs(p_earc->tx_top_map, status1);
        }
 
        return IRQ_HANDLED;
@@ -759,6 +761,8 @@ static int earc_dai_startup(
                                goto err;
                        }
                }
+
+               earcrx_pll_refresh(p_earc->rx_top_map);
        }
 
        return 0;
@@ -885,6 +889,9 @@ static int earcrx_arc_set_enable(
        struct snd_soc_component *component = snd_kcontrol_chip(kcontrol);
        struct earc *p_earc = dev_get_drvdata(component->dev);
 
+       if (!p_earc)
+               return 0;
+
        earcrx_cmdc_arc_connect(
                p_earc->rx_cmdc_map,
                (bool)ucontrol->value.integer.value[0]);
@@ -892,6 +899,43 @@ static int earcrx_arc_set_enable(
        return 0;
 }
 
+int earctx_get_attend_type(struct snd_kcontrol *kcontrol,
+                          struct snd_ctl_elem_value *ucontrol)
+{
+       struct snd_soc_component *component = snd_kcontrol_chip(kcontrol);
+       struct earc *p_earc = dev_get_drvdata(component->dev);
+       enum attend_type type;
+
+       if (!p_earc || IS_ERR(p_earc->tx_top_map))
+               return 0;
+
+       type = earctx_cmdc_get_attended_type(p_earc->tx_cmdc_map);
+
+       ucontrol->value.integer.value[0] = type;
+
+       return 0;
+}
+
+int earctx_set_attend_type(struct snd_kcontrol *kcontrol,
+                          struct snd_ctl_elem_value *ucontrol)
+{
+       struct snd_soc_component *component = snd_kcontrol_chip(kcontrol);
+       struct earc *p_earc = dev_get_drvdata(component->dev);
+       enum cmdc_st state;
+
+       if (!p_earc || IS_ERR(p_earc->tx_top_map))
+               return 0;
+
+       state = earctx_cmdc_get_state(p_earc->tx_cmdc_map);
+
+       if (state != CMDC_ST_IDLE2)
+               return 0;
+
+       /* only support set cmdc from idle to ARC */
+
+       return 0;
+}
+
 static const struct snd_kcontrol_new earc_controls[] = {
        SOC_ENUM_EXT("eARC_RX attended type",
                     attended_type_enum,
@@ -902,6 +946,11 @@ static const struct snd_kcontrol_new earc_controls[] = {
                            0,
                            earcrx_arc_get_enable,
                            earcrx_arc_set_enable),
+
+       SOC_ENUM_EXT("eARC_TX attended type",
+                    attended_type_enum,
+                    earctx_get_attend_type,
+                    earctx_set_attend_type),
 };
 
 static const struct snd_soc_component_driver earc_component = {
@@ -966,6 +1015,8 @@ void earc_hdmitx_hpdst(bool st)
        /* ensure clock gate */
        audiobus_update_bits(EE_AUDIO_CLK_GATE_EN1, 0x1 << 6, 0x1 << 6);
 
+       earcrx_cmdc_arc_connect(p_earc->rx_cmdc_map, st);
+
        earcrx_cmdc_hpd_detect(p_earc->rx_cmdc_map, st);
 }
 
@@ -1018,7 +1069,7 @@ static int earctx_extcon_register(struct earc *p_earc)
        int ret = 0;
 
        /* earc or arc connect */
-       p_earc->tx_edev = devm_extcon_dev_allocate(p_earc->dev, earcrx_extcon);
+       p_earc->tx_edev = devm_extcon_dev_allocate(p_earc->dev, earctx_extcon);
        if (IS_ERR(p_earc->tx_edev)) {
                pr_err("failed to allocate earc extcon!!!\n");
                ret = -ENOMEM;
index 2a857e8..2028090 100644 (file)
 #include <linux/amlogic/media/sound/spdif_info.h>
 #include "earc_hw.h"
 
+void earcrx_pll_refresh(struct regmap *top_map)
+{
+       /* pll tdc mode */
+       mmio_update_bits(top_map, EARCRX_PLL_CTRL3,
+                        0x1 << 15, 0x1 << 15);
+
+       /* pll self reset */
+       mmio_update_bits(top_map, EARCRX_PLL_CTRL0,
+                        0x1 << 29, 0x1 << 29);
+       mmio_update_bits(top_map, EARCRX_PLL_CTRL0,
+                        0x1 << 29, 0x0 << 29);
+
+       mmio_update_bits(top_map, EARCRX_PLL_CTRL3,
+                        0x1 << 15, 0x0 << 15);
+}
 void earcrx_cmdc_init(struct regmap *top_map)
 {
        /* set irq mask */
@@ -98,8 +113,8 @@ void earcrx_cmdc_hpd_detect(struct regmap *cmdc_map, bool st)
                mmio_update_bits(cmdc_map,
                                 EARC_RX_CMDC_VSM_CTRL0,
                                 0x1 << 19 | 0xff << 0,
-                                0x1 << 19 | /* comma_cnt_rst */
-                                0xff << 0
+                                0x0 << 19 | /* comma_cnt_rst */
+                                0xa << 0
                                );
        } else {
                /* soft reset */
@@ -216,7 +231,8 @@ void earcrx_arc_init(struct regmap *dmac_map)
                   0x1 << 30 | /* reg_chnum_sel */
                   0x1 << 25 | /* reg_findpapb_en */
                   0x1 << 24 | /* nonpcm2pcm_th enable */
-                  0xFFF << 12   /* reg_nonpcm2pcm_th */
+                  0xFFF << 12 |  /* reg_nonpcm2pcm_th */
+                  0x1 << 2    /* reg_check_parity */
                  );
        mmio_write(dmac_map,
                   EARCRX_SPDIFIN_CTRL2,
@@ -419,17 +435,10 @@ void earctx_cmdc_hpd_detect(struct regmap *top_map,
                                 0x3 << 20 | 0x3 << 22
                                );
 
-               /* no timeout */
-               mmio_update_bits(cmdc_map,
-                                EARC_TX_CMDC_VSM_CTRL5,
-                                0x3 << 0,
-                                0x1 << 1
-                                );
-
                mmio_update_bits(cmdc_map,
                                 EARC_TX_CMDC_VSM_CTRL1,
                                 0xff << 0,
-                                0xa << 0   /* comma_cnt_th */
+                                0x4 << 0   /* comma_cnt_th */
                                );
        } else {
                /* soft reset */
@@ -524,6 +533,14 @@ void earctx_set_channel_status_info(struct regmap *dmac_map,
                   ((chsts->chstat1_r >> 8) & 0xf) << 24 | chsts->chstat0_r);
 }
 
+enum cmdc_st earctx_cmdc_get_state(struct regmap *cmdc_map)
+{
+       int val = mmio_read(cmdc_map, EARC_TX_CMDC_STATUS0);
+       enum cmdc_st state = (enum cmdc_st)(val & 0x7);
+
+       return state;
+}
+
 enum attend_type earctx_cmdc_get_attended_type(struct regmap *cmdc_map)
 {
        int val = mmio_read(cmdc_map, EARC_TX_CMDC_STATUS0);
index 6e26d32..9a01e96 100644 (file)
@@ -107,6 +107,7 @@ enum tx_hd_hdp_mux {
        GPIOW_5
 };
 
+void earcrx_pll_refresh(struct regmap *top_map);
 void earcrx_cmdc_init(struct regmap *top_map);
 void earcrx_cmdc_arc_connect(struct regmap *cmdc_map, bool init);
 void earcrx_cmdc_hpd_detect(struct regmap *cmdc_map, bool st);
@@ -132,6 +133,8 @@ void earctx_dmac_set_format(struct regmap *dmac_map,
                            int frddr_idx, int msb, int frddr_type);
 void earctx_set_channel_status_info(struct regmap *dmac_map,
                                    struct iec958_chsts *chsts);
+enum cmdc_st earctx_cmdc_get_state(struct regmap *cmdc_map);
+enum attend_type earctx_cmdc_get_attended_type(struct regmap *cmdc_map);
 void earctx_cdmc_clr_irqs(struct regmap *top_map, int clr);
 int earctx_cdmc_get_irqs(struct regmap *top_map);
 void earctx_dmac_clr_irqs(struct regmap *top_map, int clr);
index d41cc4a..6a6fa3f 100644 (file)
@@ -182,10 +182,8 @@ static DEVICE_ATTR(locker_enable, 0644,
 
 void audio_locker_set(int enable)
 {
-       if (!s_locker) {
-               pr_debug("audio locker is not init\n");
+       if (!s_locker)
                return;
-       }
 
        s_locker->enable = enable;
        audiolocker_init(s_locker);
@@ -193,10 +191,8 @@ void audio_locker_set(int enable)
 
 int audio_locker_get(void)
 {
-       if (!s_locker) {
-               pr_debug("audio locker is not init\n");
-               return -1;
-       }
+       if (!s_locker)
+               return 0;
 
        return s_locker->enable;
 }
index 41905cf..0d637ea 100644 (file)
@@ -81,10 +81,8 @@ struct audioresample *get_audioresample(enum resample_idx id)
 
        p_resample = ((id == RESAMPLE_A) ? s_resample_a : s_resample_b);
 
-       if (!p_resample) {
-               pr_debug("Not init audio resample\n");
+       if (!p_resample)
                return NULL;
-       }
 
        return p_resample;
 }