audio: set audio path from frhdmirx through spdifin mode [1/2]
authorZhe Wang <Zhe.Wang@amlogic.com>
Tue, 9 Jul 2019 09:07:20 +0000 (17:07 +0800)
committerTao Zeng <tao.zeng@amlogic.com>
Thu, 17 Oct 2019 04:46:25 +0000 (21:46 -0700)
PD#SWPL-11054

Problem:
hdmiin source, audio input is randomly LR invert

Solution:
set audio path from frhdmirx through spdifin mode

Verify:
Verified on X301

Change-Id: Ib40d30b8b6d8bc28da69bf9b4f37ae2ef9228761
Signed-off-by: Zhe Wang <Zhe.Wang@amlogic.com>
drivers/amlogic/media/vin/tvin/hdmirx/hdmi_rx_hw.c
sound/soc/amlogic/auge/ddr_mngr.c
sound/soc/amlogic/auge/extn.c
sound/soc/amlogic/auge/frhdmirx_hw.c
sound/soc/amlogic/auge/frhdmirx_hw.h
sound/soc/amlogic/auge/resample.c
sound/soc/amlogic/auge/resample_hw.c

index f48b2fb..cb31828 100644 (file)
@@ -86,7 +86,7 @@ MODULE_PARM_DESC(hdcp22_on, "\n hdcp22_on\n");
 module_param(hdcp22_on, int, 0664);
 
 /* test for HBR CTS, audio module can set it to force 8ch */
-int hbr_force_8ch = 1;
+int hbr_force_8ch;
 /*
  * hdcp14_key_mode:hdcp1.4 key handle method select
  * NORMAL_MODE:systemcontrol path
@@ -2140,7 +2140,7 @@ int hdmirx_audio_init(void)
        hdmirx_wr_dwc(DWC_PDEC_ACRM_CTRL, data32);
 
        /* unsupport HBR serial mode. invalid bit */
-       /* hdmirx_wr_bits_dwc(DWC_AUD_CTRL, DWC_AUD_HBR_ENABLE, 1); */
+       hdmirx_wr_bits_dwc(DWC_AUD_CTRL, DWC_AUD_HBR_ENABLE, 1);
 
        /* SAO cfg, disable I2S output, no use */
        data32 = 0;
index 1fa7282..fce113b 100644 (file)
@@ -441,8 +441,8 @@ void aml_toddr_set_format(struct toddr *to, struct toddr_fmt *fmt)
 
        reg = calc_toddr_address(EE_AUDIO_TODDR_A_CTRL0, reg_base);
        aml_audiobus_update_bits(actrl, reg,
-               0x7 << 24 | 0x1fff << 3,
-               fmt->endian << 24 | fmt->type << 13 |
+               0x1 << 27 | 0x7 << 24 | 0x1fff << 3,
+               0x1 << 27 | fmt->endian << 24 | fmt->type << 13 |
                fmt->msb << 8 | fmt->lsb << 3);
 }
 
@@ -695,15 +695,15 @@ static void aml_resample_enable(
                        resample_src_select(to->fifo_id);
        }
 
-       /* resample enable or not */
-       resample_enable(p_attach_resample->id, enable);
-
        /* select reample data */
        if (to->chipinfo
                        && to->chipinfo->asrc_src_sel_ctrl)
                aml_toddr_set_resample_ab(to, p_attach_resample->id, enable);
        else
                aml_toddr_set_resample(to, enable);
+
+       /* resample enable or disable */
+       resample_enable(p_attach_resample->id, enable);
 }
 
 void aml_set_resample(enum resample_idx id,
@@ -711,7 +711,6 @@ void aml_set_resample(enum resample_idx id,
 {
        struct toddr_attach *p_attach_resample;
        struct toddr *to;
-       bool update_running = false;
 
        if (id == RESAMPLE_A)
                p_attach_resample = &attach_resample_a;
@@ -730,26 +729,7 @@ void aml_set_resample(enum resample_idx id,
                goto exit;
        }
 
-       if (enable) {
-               if ((p_attach_resample->status == DISABLED)
-                       || (p_attach_resample->status == READY)) {
-
-                       if (!to) {
-                               p_attach_resample->status = READY;
-                       } else {
-                               p_attach_resample->status = RUNNING;
-                               update_running = true;
-                               pr_info("Capture with resample\n");
-                       }
-               }
-       } else {
-               if (p_attach_resample->status == RUNNING)
-                       update_running = true;
-
-               p_attach_resample->status = DISABLED;
-       }
-
-       if (update_running && to)
+       if (p_attach_resample->status == RUNNING)
                aml_resample_enable(to, p_attach_resample, enable);
 
 exit:
@@ -770,18 +750,19 @@ static void aml_check_resample(struct toddr *to, bool enable)
 
 start_check:
        is_module_resample = false;
-       if (p_attach_resample->enable
-               && (to->src == p_attach_resample->attach_module))
+       if (to->src == p_attach_resample->attach_module)
                is_module_resample = true;
 
-       /* resample in enable */
        if (is_module_resample) {
+               /* save toddr status */
                if (enable)
                        p_attach_resample->status = RUNNING;
                else
                        p_attach_resample->status = DISABLED;
 
-               aml_resample_enable(to, p_attach_resample, enable);
+               /*if disable toddr, disable attached resampler*/
+               if (p_attach_resample->enable)
+                       aml_resample_enable(to, p_attach_resample, enable);
        }
 
        if ((!resample_b_check)
index f95afa5..97f7cc8 100644 (file)
 
 #define DYNC_KCNTL_CNT 2
 
+enum {
+       HDMIRX_MODE_SPDIFIN = 0,
+       HDMIRX_MODE_PAO = 1,
+};
+
 struct extn_chipinfo {
        /* try to check papb before fetch pcpd
         * no nonpcm2pcm irq for tl1
@@ -147,27 +152,24 @@ static irqreturn_t extn_ddr_isr(int irq, void *devid)
        struct snd_soc_pcm_runtime *rtd = substream->private_data;
        struct device *dev = rtd->platform->dev;
        struct extn *p_extn = (struct extn *)dev_get_drvdata(dev);
-       int timeout_thres = 5;
-
-#ifdef CONFIG_AMLOGIC_MEDIA_TVIN_HDMI
-       int sample_rate_index = get_hdmi_sample_rate_index();
-
-       /*192K audio*/
-       if (sample_rate_index == 7)
-               timeout_thres = 10;
-       else
-               timeout_thres = 5;
-#endif
 
        if (!snd_pcm_running(substream))
                return IRQ_HANDLED;
 
        snd_pcm_period_elapsed(substream);
 
-       /* check pcm or nonpcm */
-       if (p_extn &&
-               p_extn->chipinfo &&
-               p_extn->chipinfo->no_nonpcm2pcm_clr) {
+       /* check pcm or nonpcm for PAO*/
+       if (p_extn->hdmirx_mode == HDMIRX_MODE_PAO) {
+               int timeout_thres = 5;
+#ifdef CONFIG_AMLOGIC_MEDIA_TVIN_HDMI
+               int sample_rate_index = get_hdmi_sample_rate_index();
+
+               /*192K audio*/
+               if (sample_rate_index == 7)
+                       timeout_thres = 10;
+               else
+                       timeout_thres = 5;
+#endif
                if (p_extn->frhdmirx_last_cnt == p_extn->frhdmirx_cnt) {
 
                        p_extn->frhdmirx_same_cnt++;
@@ -183,6 +185,8 @@ static irqreturn_t extn_ddr_isr(int irq, void *devid)
                        p_extn->nonpcm_flag = true;
                        frhdmirx_clr_PAO_irq_bits();
                }
+       } else {
+           frhdmirx_clr_SPDIF_irq_bits();
        }
 
        return IRQ_HANDLED;
@@ -260,8 +264,7 @@ static int extn_close(struct snd_pcm_substream *substream)
 
                if (toddr_src_get() == FRHDMIRX) {
                        frhdmirx_nonpcm2pcm_clr_reset(p_extn);
-                       if (p_extn->hdmirx_mode == 1)
-                               frhdmirx_clr_PAO_irq_bits();
+                       frhdmirx_clr_all_irq_bits();
                        free_irq(p_extn->irq_frhdmirx, p_extn);
                }
        }
@@ -496,20 +499,26 @@ static int extn_dai_prepare(
                         */
                        /* fratv_src_select(1); */
                } else if (src == FRHDMIRX) {
-                       if (p_extn->hdmirx_mode) { /* PAO */
 
-                               if (bit_depth == 32)
-                                       toddr_type = 3;
-                               else if (bit_depth == 24)
-                                       toddr_type = 4;
-                               else
-                                       toddr_type = 0;
+                       if (bit_depth == 32)
+                               toddr_type = 3;
+                       else if (bit_depth == 24)
+                               toddr_type = 4;
+                       else
+                               toddr_type = 0;
 
+                       if (p_extn->hdmirx_mode == HDMIRX_MODE_PAO) { /* PAO */
                                msb = 28 - 1 - 4;
                                if (bit_depth == 16)
                                        lsb = 24 - bit_depth;
                                else
                                        lsb = 4;
+                       } else { /* SPDIFIN */
+                               msb = 28 - 1;
+                               if (bit_depth <= 24)
+                                       lsb = 28 - bit_depth;
+                               else
+                                       lsb = 4;
                        }
 
                        frhdmirx_ctrl(runtime->channels, p_extn->hdmirx_mode);
@@ -812,7 +821,7 @@ static int hdmiin_check_audio_type(struct extn *p_extn)
        int audio_type = 0;
        int i;
 
-       if (!p_extn->nonpcm_flag)
+       if (!p_extn->nonpcm_flag && p_extn->hdmirx_mode)
                return audio_type;
 
        for (i = 0; i < total_num; i++) {
@@ -935,9 +944,9 @@ static const struct snd_kcontrol_new extn_controls[] = {
                aml_set_atmos_audio_edid),
 
        SOC_ENUM_EXT("HDMIIN Audio Type",
-                        hdmirx_audio_type_enum,
-                        hdmirx_audio_type_get_enum,
-                        NULL),
+               hdmirx_audio_type_enum,
+               hdmirx_audio_type_get_enum,
+               NULL),
 #endif
 
 };
@@ -1014,8 +1023,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: SPDIFIN mode */
+       p_extn->hdmirx_mode = HDMIRX_MODE_SPDIFIN;
 
        ret = devm_snd_soc_register_component(&pdev->dev,
                                              &extn_component,
index 1dd0593..6f2846b 100644 (file)
@@ -51,12 +51,7 @@ void frhdmirx_src_select(int src)
 
 static void frhdmirx_enable_irq_bits(int channels, int src)
 {
-       int lane, int_bits = 0, i;
-
-       if (channels % 2)
-               lane = channels / 2 + 1;
-       else
-               lane = channels / 2;
+       unsigned int int_bits = 0;
 
        /* interrupt bits */
        if (src) { /* PAO mode */
@@ -66,78 +61,59 @@ static void frhdmirx_enable_irq_bits(int channels, int src)
                        );
        } else { /* SPDIF Lane */
                int lane_irq_bits = (0x1 << 7 | /* lane: find papb */
-                       0x1 << 6 | /* lane: find papb */
+                       0x1 << 6 | /* lane: find valid changed */
                        0x1 << 5 | /* lane: find nonpcm to pcm */
                        0x1 << 4 | /* lane: find pcpd changed */
                        0x1 << 3 | /* lane: find ch status changed */
                        0x1 << 1 /* lane: find parity error */
                        );
 
+               int lane, i;
+
+               lane = (channels % 2) ? (channels / 2 + 1) : (channels / 2);
                for (i = 0; i < lane; i++)
-                       int_bits |= (lane_irq_bits << i);
+                       int_bits |= (lane_irq_bits << 8 * i);
        }
+
+       int_bits |= audiobus_read(EE_AUDIO_FRHDMIRX_CTRL2);
        audiobus_write(EE_AUDIO_FRHDMIRX_CTRL2, int_bits);
 }
 
-void frhdmirx_clr_irq_bits(int channels, int src)
+void frhdmirx_clr_all_irq_bits(void)
 {
-       int lane, int_clr_mask = 0, i;
-
-       if (channels % 2)
-               lane = channels / 2 + 1;
-       else
-               lane = channels / 2;
-
-       /* interrupt bits */
-       if (src) { /* PAO mode */
-               int_clr_mask = (
-                       0x1 << INT_PAO_PAPB_MASK | /* find papb */
-                       0x1 << INT_PAO_PCPD_MASK   /* find pcpd changed */
-                       );
-       } else { /* SPDIF Lane */
-               int lane_irq_bits = (0x1 << 7 | /* lane: find papb */
-                       0x1 << 6 | /* lane: find valid changed; */
-                       0x1 << 5 | /* lane: find nonpcm to pcm */
-                       0x1 << 4 | /* lane: find pcpd changed */
-                       0x1 << 3 | /* lane: find ch status changed */
-                       0x1 << 1 /* lane: find parity error */
-                       );
-
-               for (i = 0; i < lane; i++)
-                       int_clr_mask |= (lane_irq_bits << i);
-       }
-       audiobus_write(EE_AUDIO_FRHDMIRX_CTRL3, ~int_clr_mask);
-       audiobus_write(EE_AUDIO_FRHDMIRX_CTRL3, int_clr_mask);
-       audiobus_write(EE_AUDIO_FRHDMIRX_CTRL4, ~int_clr_mask);
-       audiobus_write(EE_AUDIO_FRHDMIRX_CTRL4, int_clr_mask);
+       audiobus_write(EE_AUDIO_FRHDMIRX_CTRL3, 0xffffffff);
+       audiobus_write(EE_AUDIO_FRHDMIRX_CTRL3, 0x0);
+       audiobus_write(EE_AUDIO_FRHDMIRX_CTRL4, 0xffffffff);
+       audiobus_write(EE_AUDIO_FRHDMIRX_CTRL4, 0x0);
 }
 
 void frhdmirx_ctrl(int channels, int src)
 {
-       int lane, lane_mask = 0, i;
-
        /* PAO mode */
        if (src) {
                audiobus_write(EE_AUDIO_FRHDMIRX_CTRL0,
                        0x1 << 22 | /* capture input by fall edge*/
                        0x1 << 8  | /* start detect PAPB */
+                       0x1 << 7  | /* add channel num */
                        0x4 << 4    /* chan status sel: pao pc/pd value */
                        );
        } else {
-               if (channels % 2)
-                       lane = channels / 2 + 1;
-               else
-                       lane = channels / 2;
+               int lane, lane_mask = 0, i;
 
+               lane = (channels % 2) ? (channels / 2 + 1) : (channels / 2);
                for (i = 0; i < lane; i++)
                        lane_mask |= (1 << i);
 
                audiobus_update_bits(EE_AUDIO_FRHDMIRX_CTRL0,
-                       0x1 << 30 | 0xf << 24 | 0x1 << 22 | 0x3 << 11,
+                       0x1 << 30 | 0xf << 24 | 0x1 << 22 |
+                       0x3 << 11 | 0x1 << 8 | 0x1 << 7 | 0x7 << 0,
                        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 */
+                       0x1 << 8  | /* start detect PAPB */
+                       0x1 << 7  | /* add channel num*/
+                       0x6 << 0    /* channel status*/
                        );
        }
        /* nonpcm2pcm_th */
@@ -158,6 +134,35 @@ void frhdmirx_clr_PAO_irq_bits(void)
                0x0 << INT_PAO_PAPB_MASK | 0x0 << INT_PAO_PCPD_MASK);
 }
 
+void frhdmirx_clr_SPDIF_irq_bits(void)
+{
+       unsigned int value = audiobus_read(EE_AUDIO_FRHDMIRX_STAT0);
+       unsigned int clr_mask = audiobus_read(EE_AUDIO_FRHDMIRX_CTRL4);
+       unsigned int reg = 0;
+       int i;
+
+       reg = clr_mask | value;
+       audiobus_write(EE_AUDIO_FRHDMIRX_CTRL4, reg);
+
+       reg = clr_mask & (~value);
+       audiobus_write(EE_AUDIO_FRHDMIRX_CTRL4, reg);
+
+       /*compressed audio only transfer through lane0*/
+       for (i = 0; i < 1; i++) {
+               /*nonpcm2pcm irq, clear papb/pcpd/nonpcm*/
+               if (value & (0x20 << 8 * i)) {
+                       audiobus_update_bits(
+                               EE_AUDIO_FRHDMIRX_CTRL3,
+                               0xf << 8 * i, 0xf << 8 * i);
+                       audiobus_update_bits(
+                               EE_AUDIO_FRHDMIRX_CTRL3,
+                               0xf << 8 * i, 0x0 << 8 * i);
+                       pr_info("raw to pcm change: irq status:%x, lane: %d\n",
+                               value, i);
+               }
+       }
+}
+
 unsigned int frhdmirx_get_ch_status0to31(void)
 {
        return (unsigned int)audiobus_read(EE_AUDIO_FRHDMIRX_STAT0);
@@ -170,3 +175,4 @@ unsigned int frhdmirx_get_chan_status_pc(void)
        val = audiobus_read(EE_AUDIO_FRHDMIRX_STAT1);
        return (val >> 16) & 0xff;
 }
+
index 7c83dd0..6b336cd 100644 (file)
 #define INT_PAO_PAPB_MASK    24
 #define INT_PAO_PCPD_MASK    16
 
-extern void frhdmirx_enable(bool enable);
-extern void frhdmirx_src_select(int src);
-extern void frhdmirx_ctrl(int channels, int src);
-extern void frhdmirx_clr_PAO_irq_bits(void);
-extern unsigned int frhdmirx_get_ch_status0to31(void);
-extern unsigned int frhdmirx_get_chan_status_pc(void);
+void frhdmirx_enable(bool enable);
+void frhdmirx_src_select(int src);
+void frhdmirx_ctrl(int channels, int src);
+void frhdmirx_clr_PAO_irq_bits(void);
+void frhdmirx_clr_SPDIF_irq_bits(void);
+unsigned int frhdmirx_get_ch_status0to31(void);
+unsigned int frhdmirx_get_chan_status_pc(void);
+void frhdmirx_clr_all_irq_bits(void);
+
 #endif
index c4cd6c1..41905cf 100644 (file)
@@ -143,12 +143,6 @@ static int resample_clk_set(struct audioresample *p_resample)
        return ret;
 }
 
-static void audio_resample_init(struct audioresample *p_resample)
-{
-       aml_set_resample(p_resample->id, p_resample->enable,
-               p_resample->resample_module);
-}
-
 static int audio_resample_set(
        struct audioresample *p_resample,
        bool enable, int rate)
@@ -158,7 +152,9 @@ static int audio_resample_set(
 
        p_resample->enable = enable;
        p_resample->out_rate = rate;
-       audio_resample_init(p_resample);
+       aml_set_resample(
+               p_resample->id, p_resample->enable,
+               p_resample->resample_module);
 
        return 0;
 }
index f5d4d43..0ebbece 100644 (file)
@@ -45,6 +45,11 @@ void resample_enable(enum resample_idx id, bool enable)
        int offset = EE_AUDIO_RESAMPLEB_CTRL0 - EE_AUDIO_RESAMPLEA_CTRL0;
        int reg = EE_AUDIO_RESAMPLEA_CTRL0 + offset * id;
 
+       /*don't change this flow*/
+       audiobus_update_bits(
+               reg, 0x1 << 31 | 0x1 << 28,
+               0 << 31 | 0x0 << 28);
+
        audiobus_update_bits(reg,
                0x1 << 31,
                1 << 31);
@@ -90,7 +95,7 @@ int resample_disable(enum resample_idx id)
        int offset = EE_AUDIO_RESAMPLEB_CTRL0 - EE_AUDIO_RESAMPLEA_CTRL0;
        int reg = EE_AUDIO_RESAMPLEA_CTRL0 + offset * id;
 
-       audiobus_write(reg, 0);
+       audiobus_update_bits(reg, 0x1 << 28, 0 << 28);
 
        return 0;
 }
@@ -116,7 +121,7 @@ int resample_set_hw_param(enum resample_idx id,
        offset = EE_AUDIO_RESAMPLEB_CTRL2 - EE_AUDIO_RESAMPLEA_CTRL2;
        reg = EE_AUDIO_RESAMPLEA_CTRL2 + offset * id;
 
-       audiobus_update_bits(reg, 1 << 25, 1 << 25);
+       audiobus_update_bits(reg, 3 << 26 | 1 << 25, 3 << 26 | 1 << 25);
        resample_set_hw_pause_thd(id, 128);
 
        return 0;