Asoc: tegra: Fix audio mixing issue
Vijay Mali [Thu, 6 Mar 2014 13:15:30 +0000 (18:15 +0530)]
There is hardware issue in t114 & t124 DAM.
It does not handle mixing and down sampling
simultaneously. This a work around to use
2 DAM for doing SRC and mixing separately.

Bug 1472784

Change-Id: I67f04682b1807243800e757b548481928dd2720a
Signed-off-by: Vijay Mali <vmali@nvidia.com>
Reviewed-on: http://git-master/r/378389
Reviewed-by: Automatic_Commit_Validation_User
Reviewed-by: Lei Fan <leif@nvidia.com>
GVS: Gerrit_Virtual_Submit
Reviewed-by: Sumit Bhattacharya <sumitb@nvidia.com>
Reviewed-by: Ravindra Lokhande <rlokhande@nvidia.com>

sound/soc/tegra/tegra30_i2s.c

index ae9383e..1e7bf00 100644 (file)
@@ -1883,44 +1883,62 @@ int tegra30_make_voice_call_connections(struct codec_config *codec_info,
                        return ret;
                }
 
-               ret = tegra30_dam_allocate_channel(codec_i2s->dam_ifc,
+               /*configure codec dam*/
+               ret = configure_dam(bb_i2s,
+                                   bb_info->channels,
+                                   bb_info->rate,
+                                   bb_info->bitsize,
+                                   codec_info->channels,
+                                   codec_info->rate,
+                                   codec_info->bitsize);
+
+               if (ret) {
+                       pr_info("%s:Failed to configure dam\n", __func__);
+                       return ret;
+               }
+
+               ret = tegra30_dam_allocate_channel(bb_i2s->dam_ifc,
                                                TEGRA30_DAM_CHIN1);
                if (ret)
                        pr_info("%s:Failed to allocate dam\n", __func__);
 
-               tegra30_dam_set_gain(codec_i2s->dam_ifc,
+               tegra30_dam_set_gain(bb_i2s->dam_ifc,
                                TEGRA30_DAM_CHIN1, 0x1000);
-               tegra30_dam_set_acif(codec_i2s->dam_ifc, TEGRA30_DAM_CHIN1, 1,
+               tegra30_dam_set_acif(bb_i2s->dam_ifc, TEGRA30_DAM_CHIN1, 1,
                                bb_info->bitsize, 1, 32);
-               tegra30_dam_set_acif(codec_i2s->dam_ifc, TEGRA30_DAM_CHOUT,
+               tegra30_dam_set_acif(bb_i2s->dam_ifc, TEGRA30_DAM_CHOUT,
                                2, codec_info->bitsize, 1, 32);
-               tegra30_dam_ch0_set_datasync(codec_i2s->dam_ifc, 2);
-               tegra30_dam_ch1_set_datasync(codec_i2s->dam_ifc, 0);
+               tegra30_dam_ch0_set_datasync(bb_i2s->dam_ifc, 2);
+               tegra30_dam_ch1_set_datasync(bb_i2s->dam_ifc, 0);
 
                /* do routing in ahub */
                tegra30_ahub_set_rx_cif_source(
-                       TEGRA30_AHUB_RXCIF_DAM0_RX1 + (codec_i2s->dam_ifc*2),
-                       TEGRA30_AHUB_RXCIF_I2S0_RX0 + bb_info->i2s_id);
-
-               tegra30_ahub_set_rx_cif_source(
                        TEGRA30_AHUB_RXCIF_DAM0_RX0 + (codec_i2s->dam_ifc*2),
                        codec_i2s->txcif);
 
                tegra30_ahub_set_rx_cif_source(
-                       TEGRA30_AHUB_RXCIF_I2S0_RX0 + codec_info->i2s_id,
+                       TEGRA30_AHUB_RXCIF_DAM0_RX0 + (bb_i2s->dam_ifc*2),
                        TEGRA30_AHUB_TXCIF_DAM0_TX0 + codec_i2s->dam_ifc);
 
                tegra30_ahub_set_rx_cif_source(
+                       TEGRA30_AHUB_RXCIF_DAM0_RX1 + (bb_i2s->dam_ifc*2),
+                       TEGRA30_AHUB_TXCIF_I2S0_TX0 + bb_info->i2s_id);
+
+               tegra30_ahub_set_rx_cif_source(
+                       TEGRA30_AHUB_RXCIF_I2S0_RX0 + codec_info->i2s_id,
+                       TEGRA30_AHUB_TXCIF_DAM0_TX0 + bb_i2s->dam_ifc);
+
+               tegra30_ahub_set_rx_cif_source(
                        TEGRA30_AHUB_RXCIF_I2S0_RX0 + bb_info->i2s_id,
                        TEGRA30_AHUB_TXCIF_I2S0_TX0 + codec_info->i2s_id);
 
                /* enable the dam*/
-               tegra30_dam_enable(codec_i2s->dam_ifc, TEGRA30_DAM_ENABLE,
+               tegra30_dam_enable(bb_i2s->dam_ifc, TEGRA30_DAM_ENABLE,
                        TEGRA30_DAM_CHIN0_SRC);
-
+               tegra30_dam_enable(bb_i2s->dam_ifc, TEGRA30_DAM_ENABLE,
+                       TEGRA30_DAM_CHIN1);
                tegra30_dam_enable(codec_i2s->dam_ifc, TEGRA30_DAM_ENABLE,
-                               TEGRA30_DAM_CHIN1);
-
+                       TEGRA30_DAM_CHIN0_SRC);
        }
 #ifndef CONFIG_ARCH_TEGRA_3x_SOC
        tegra30_i2s_write(codec_i2s, TEGRA30_I2S_FLOWCTL, 0);
@@ -2033,17 +2051,27 @@ int tegra30_break_voice_call_connections(struct codec_config *codec_info,
        } else {
 
                /* Disable DAM in DL path */
-               tegra30_dam_enable(codec_i2s->dam_ifc,
+               tegra30_dam_enable(bb_i2s->dam_ifc,
                        TEGRA30_DAM_DISABLE, TEGRA30_DAM_CHIN0_SRC);
-               tegra30_dam_free_channel(codec_i2s->dam_ifc,
+               tegra30_dam_free_channel(bb_i2s->dam_ifc,
                        TEGRA30_DAM_CHIN0_SRC);
 
-               tegra30_dam_enable(codec_i2s->dam_ifc,
+               tegra30_dam_enable(bb_i2s->dam_ifc,
                        TEGRA30_DAM_DISABLE, TEGRA30_DAM_CHIN1);
-               tegra30_dam_free_channel(codec_i2s->dam_ifc,
+               tegra30_dam_free_channel(bb_i2s->dam_ifc,
                        TEGRA30_DAM_CHIN1);
 
+               tegra30_dam_enable(codec_i2s->dam_ifc,
+                       TEGRA30_DAM_DISABLE, TEGRA30_DAM_CHIN0_SRC);
+               tegra30_dam_free_channel(codec_i2s->dam_ifc,
+                       TEGRA30_DAM_CHIN0_SRC);
+
+               bb_i2s->dam_ch_refcount--;
                codec_i2s->dam_ch_refcount--;
+
+               if (!bb_i2s->dam_ch_refcount)
+                       tegra30_dam_free_controller(bb_i2s->dam_ifc);
+
                if (!codec_i2s->dam_ch_refcount)
                        tegra30_dam_free_controller(codec_i2s->dam_ifc);
 
@@ -2052,7 +2080,7 @@ int tegra30_break_voice_call_connections(struct codec_config *codec_info,
                                bb_info->i2s_id);
 
                tegra30_ahub_unset_rx_cif_source(TEGRA30_AHUB_RXCIF_DAM0_RX1 +
-                               (codec_i2s->dam_ifc*2));
+                               (bb_i2s->dam_ifc*2));
 
                tegra30_ahub_unset_rx_cif_source(TEGRA30_AHUB_RXCIF_DAM0_RX0 +
                        (codec_i2s->dam_ifc*2));
@@ -2060,9 +2088,10 @@ int tegra30_break_voice_call_connections(struct codec_config *codec_info,
                tegra30_ahub_unset_rx_cif_source(TEGRA30_AHUB_RXCIF_I2S0_RX0 +
                                codec_info->i2s_id);
 
-               tegra30_dam_ch0_set_datasync(codec_i2s->dam_ifc, 0);
-               tegra30_dam_ch1_set_datasync(codec_i2s->dam_ifc, 0);
+               tegra30_dam_ch0_set_datasync(bb_i2s->dam_ifc, 0);
+               tegra30_dam_ch1_set_datasync(bb_i2s->dam_ifc, 0);
 
+               tegra30_dam_disable_clock(bb_i2s->dam_ifc);
                tegra30_dam_disable_clock(codec_i2s->dam_ifc);
        }