ASoC: Tegra: Add support for dual mic
Ravindra Lokhande [Fri, 3 May 2013 16:42:39 +0000 (21:42 +0530)]
To send dual mic data to modem we need to remove DAM from uplink path.

This changes removes dam from uplink path and sets codec rate to
16khz and uses dam for downlink.

Bug 1234999
Bug 1263251

Change-Id: I2ebfb206543afe352268049327a284e54e1933f8
Signed-off-by: Ravindra Lokhande <rlokhande@nvidia.com>
Reviewed-on: http://git-master/r/225300
Reviewed-by: Automatic_Commit_Validation_User
Reviewed-by: Scott Peterson <speterson@nvidia.com>

sound/soc/tegra/tegra30_dam.c
sound/soc/tegra/tegra30_dam.h
sound/soc/tegra/tegra30_i2s.c
sound/soc/tegra/tegra30_i2s.h
sound/soc/tegra/tegra_aic325x.c
sound/soc/tegra/tegra_max98090.c

index d4206a9..0f64886 100644 (file)
@@ -998,20 +998,24 @@ void tegra30_dam_enable(int ifc, int on, int chid)
        }
 }
 
-void tegra30_dam_ch0_set_datasync(struct tegra30_dam_context *dam, int datasync)
+void tegra30_dam_ch0_set_datasync(int ifc, int datasync)
 {
        u32 val;
+       struct tegra30_dam_context *dam = NULL;
 
+       dam =  dams_cont_info[ifc];
        val = tegra30_dam_readl(dam, TEGRA30_DAM_CH0_CTRL);
        val &= ~TEGRA30_DAM_CH0_CTRL_DATA_SYNC_MASK;
        val |= datasync << TEGRA30_DAM_DATA_SYNC_SHIFT;
        tegra30_dam_writel(dam, val, TEGRA30_DAM_CH0_CTRL);
 }
 
-void tegra30_dam_ch1_set_datasync(struct tegra30_dam_context *dam, int datasync)
+void tegra30_dam_ch1_set_datasync(int ifc, int datasync)
 {
        u32 val;
+       struct tegra30_dam_context *dam = NULL;
 
+       dam =  dams_cont_info[ifc];
        val = tegra30_dam_readl(dam, TEGRA30_DAM_CH1_CTRL);
        val &= ~TEGRA30_DAM_CH1_CTRL_DATA_SYNC_MASK;
        val |= datasync << TEGRA30_DAM_DATA_SYNC_SHIFT;
index df3b6e5..0e9733c 100644 (file)
@@ -190,6 +190,8 @@ int tegra30_dam_set_acif(int ifc, int chtype, unsigned int audio_channels,
        unsigned int client_bits);
 void tegra30_dam_enable(int ifc, int on, int chtype);
 int tegra30_dam_set_acif_stereo_conv(int ifc, int chtype, int conv);
+void tegra30_dam_ch0_set_datasync(int ifc, int datasync);
+void tegra30_dam_ch1_set_datasync(int ifc, int datasync);
 #ifndef CONFIG_ARCH_TEGRA_3x_SOC
 void tegra30_dam_write_coeff_ram(int ifc, int fsin, int fsout);
 void tegra30_dam_set_farrow_param(int ifc, int fsin, int fsout);
index d5815cb..0e9991e 100644 (file)
@@ -125,6 +125,7 @@ void tegra30_i2s_shutdown(struct snd_pcm_substream *substream,
 
                /* free the apbif dma channel*/
                tegra30_ahub_free_tx_fifo(i2s->playback_fifo_cif);
+               i2s->txcif = -1;
 
                /* decrement the playback ref count */
                i2s->playback_ref_count--;
@@ -965,6 +966,69 @@ static const struct regmap_config tegra30_i2s_regmap_config = {
        .cache_type = REGCACHE_RBTREE,
 };
 
+int tegra30_i2s_set_cif_channels(struct tegra30_i2s  *i2s,
+               unsigned int cif_reg,
+               unsigned int audio_ch,
+               unsigned int client_ch)
+{
+       unsigned int val;
+
+       tegra30_i2s_enable_clocks(i2s);
+
+       val = tegra30_i2s_read(i2s, cif_reg);
+       val &= ~(TEGRA30_AUDIOCIF_CTRL_AUDIO_CHANNELS_MASK |
+               TEGRA30_AUDIOCIF_CTRL_CLIENT_CHANNELS_MASK);
+       val |= ((audio_ch - 1) << TEGRA30_AUDIOCIF_CTRL_AUDIO_CHANNELS_SHIFT) |
+             ((client_ch - 1) << TEGRA30_AUDIOCIF_CTRL_CLIENT_CHANNELS_SHIFT);
+
+       tegra30_i2s_write(i2s, cif_reg, val);
+
+       tegra30_i2s_disable_clocks(i2s);
+
+       return 0;
+}
+
+int tegra30_i2s_set_cif_bits(struct tegra30_i2s  *i2s,
+               unsigned int cif_reg,
+               unsigned int audio_bits,
+               unsigned int client_bits)
+{
+       unsigned int val;
+
+       tegra30_i2s_enable_clocks(i2s);
+
+       val = tegra30_i2s_read(i2s, cif_reg);
+       val &= ~(TEGRA30_AUDIOCIF_CTRL_AUDIO_BITS_MASK |
+               TEGRA30_AUDIOCIF_CTRL_CLIENT_BITS_MASK);
+       val |= ((audio_bits) << TEGRA30_AUDIOCIF_CTRL_AUDIO_BITS_SHIFT) |
+             ((client_bits) << TEGRA30_AUDIOCIF_CTRL_CLIENT_BITS_SHIFT);
+
+       tegra30_i2s_write(i2s, cif_reg, val);
+
+       tegra30_i2s_disable_clocks(i2s);
+
+       return 0;
+}
+
+int tegra30_i2s_set_cif_stereo_conv(struct tegra30_i2s  *i2s,
+               unsigned int cif_reg,
+               int conv)
+{
+       unsigned int val;
+
+       tegra30_i2s_enable_clocks(i2s);
+
+       val = tegra30_i2s_read(i2s, cif_reg);
+       val &= ~TEGRA30_AUDIOCIF_CTRL_STEREO_CONV_MASK;
+       val |= conv;
+
+       tegra30_i2s_write(i2s, cif_reg, val);
+
+       tegra30_i2s_disable_clocks(i2s);
+
+       return 0;
+}
+
 static int configure_baseband_i2s(struct tegra30_i2s  *i2s, int is_i2smaster,
                int i2s_mode, int channels, int rate, int bitsize, int bit_clk)
 {
@@ -1150,7 +1214,7 @@ static int configure_dam(struct tegra30_i2s  *i2s, int out_channel,
 
 
 #if defined(CONFIG_ARCH_TEGRA_14x_SOC)
-int t14x_make_voice_call_connections(struct codec_config *codec_info,
+int t14x_make_bt_voice_call_connections(struct codec_config *codec_info,
                                struct ahub_bbc1_config *bb_info,
                                int uses_voice_codec)
 {
@@ -1163,63 +1227,217 @@ int t14x_make_voice_call_connections(struct codec_config *codec_info,
        codec_i2s->capture_ref_count++;
        bb_i2s->capture_ref_count++;
 
-       /*Configure codec i2s*/
+       /* Configure codec i2s */
        configure_baseband_i2s(codec_i2s, codec_info->is_i2smaster,
                codec_info->i2s_mode, codec_info->channels,
                codec_info->rate, codec_info->bitsize,
                 codec_info->bit_clk);
 
-       if (uses_voice_codec) {
-               /* The following two lines are a hack */
-               tegra30_ahub_unset_rx_cif_source(TEGRA30_AHUB_RXCIF_APBIF_RX0);
-               tegra30_ahub_unset_rx_cif_source(TEGRA30_AHUB_RXCIF_I2S0_RX0+1);
+       /* configure codec dam */
+       configure_dam(codec_i2s, codec_info->channels,
+          codec_info->rate, codec_info->bitsize, bb_info->channels,
+          bb_info->rate, bb_info->sample_size);
 
-               tegra30_ahub_set_rx_cif_source(TEGRA30_AHUB_RXCIF_I2S0_RX0 +
-                           bb_info->port_id, TEGRA30_AHUB_TXCIF_I2S0_TX0 +
-                           codec_info->i2s_id);
-               tegra30_ahub_set_rx_cif_source(TEGRA30_AHUB_RXCIF_I2S0_RX0 +
-                           codec_info->i2s_id, TEGRA30_AHUB_TXCIF_I2S0_TX0 +
-                           bb_info->port_id);
-       } else {
+       /* configure bb dam */
+       configure_dam(bb_i2s, bb_info->channels,
+               bb_info->rate, bb_info->sample_size, codec_info->channels,
+               codec_info->rate, codec_info->bitsize);
 
-               /*configure codec dam*/
-               configure_dam(codec_i2s, codec_info->channels,
-                  codec_info->rate, codec_info->bitsize, bb_info->channels,
-                  bb_info->rate, bb_info->sample_size);
+       tegra30_dam_set_acif_stereo_conv(bb_i2s->dam_ifc,
+                       TEGRA30_DAM_CHIN0_SRC,
+                       TEGRA30_CIF_STEREOCONV_AVG);
 
-               /*configure bb dam*/
-               configure_dam(bb_i2s, bb_info->channels,
-                       bb_info->rate, bb_info->sample_size, codec_info->channels,
-                       codec_info->rate, codec_info->bitsize);
+       /* make ahub connections */
 
-               tegra30_dam_set_acif_stereo_conv(bb_i2s->dam_ifc,
-                               TEGRA30_DAM_CHIN0_SRC,
-                               TEGRA30_CIF_STEREOCONV_AVG);
+       /* if this is the only user of i2s tx, make i2s rx connection */
+       if (codec_i2s->playback_ref_count == 1) {
+               tegra30_ahub_set_rx_cif_source(
+                 TEGRA30_AHUB_RXCIF_I2S0_RX0 + codec_info->i2s_id,
+                 TEGRA30_AHUB_TXCIF_DAM0_TX0 + codec_i2s->dam_ifc);
+       }
 
-               /*make ahub connections*/
+       tegra30_ahub_set_rx_cif_source(TEGRA30_AHUB_RXCIF_BBC1_RX0,
+                       TEGRA30_AHUB_TXCIF_DAM0_TX0 + bb_i2s->dam_ifc);
+       tegra30_ahub_set_rx_cif_source(TEGRA30_AHUB_RXCIF_DAM0_RX0 +
+               (codec_i2s->dam_ifc*2), TEGRA30_AHUB_TXCIF_BBC1_TX0);
+       tegra30_ahub_set_rx_cif_source(TEGRA30_AHUB_RXCIF_DAM0_RX0 +
+               (bb_i2s->dam_ifc*2), TEGRA30_AHUB_TXCIF_I2S0_TX0 +
+               codec_info->i2s_id);
 
-               /*if this is the only user of i2s tx, make i2s rx connection*/
-               if (codec_i2s->playback_ref_count == 1) {
-                       tegra30_ahub_set_rx_cif_source(
-                         TEGRA30_AHUB_RXCIF_I2S0_RX0 + codec_info->i2s_id,
-                         TEGRA30_AHUB_TXCIF_DAM0_TX0 + codec_i2s->dam_ifc);
-               }
+       /* enable dam and i2s */
+       tegra30_dam_enable(codec_i2s->dam_ifc, TEGRA30_DAM_ENABLE,
+               TEGRA30_DAM_CHIN0_SRC);
+       tegra30_dam_enable(bb_i2s->dam_ifc, TEGRA30_DAM_ENABLE,
+               TEGRA30_DAM_CHIN0_SRC);
 
-               tegra30_ahub_set_rx_cif_source(TEGRA30_AHUB_RXCIF_BBC1_RX0,
-                               TEGRA30_AHUB_TXCIF_DAM0_TX0 + bb_i2s->dam_ifc);
-               tegra30_ahub_set_rx_cif_source(TEGRA30_AHUB_RXCIF_DAM0_RX0 +
-                       (codec_i2s->dam_ifc*2), TEGRA30_AHUB_TXCIF_BBC1_TX0);
-               tegra30_ahub_set_rx_cif_source(TEGRA30_AHUB_RXCIF_DAM0_RX0 +
-                       (bb_i2s->dam_ifc*2), TEGRA30_AHUB_TXCIF_I2S0_TX0 +
-                       codec_info->i2s_id);
+       codec_i2s->reg_ctrl |= TEGRA30_I2S_CTRL_XFER_EN_TX;
+       codec_i2s->reg_ctrl |= TEGRA30_I2S_CTRL_XFER_EN_RX;
+       tegra30_i2s_write(codec_i2s, TEGRA30_I2S_CTRL,
+               codec_i2s->reg_ctrl);
 
-               /*enable dam and i2s*/
-               tegra30_dam_enable(codec_i2s->dam_ifc, TEGRA30_DAM_ENABLE,
+       return 0;
+}
+
+int t14x_break_bt_voice_call_connections(struct codec_config *codec_info,
+                               struct ahub_bbc1_config *bb_info,
+                               int uses_voice_codec)
+{
+       struct tegra30_i2s *codec_i2s = &i2scont[codec_info->i2s_id];
+       struct tegra30_i2s *bb_i2s = &bbc1cont;
+       int dcnt = 10;
+
+       /* Disable Codec I2S RX (TX to ahub) */
+       if (codec_i2s->capture_ref_count == 1)
+               codec_i2s->reg_ctrl &= ~TEGRA30_I2S_CTRL_XFER_EN_RX;
+
+       tegra30_i2s_write(codec_i2s, TEGRA30_I2S_CTRL, codec_i2s->reg_ctrl);
+
+       while (!tegra30_ahub_rx_fifo_is_empty(codec_i2s->id) && dcnt--)
+               udelay(100);
+
+       dcnt = 10;
+
+       /* Disable Codec I2S TX (RX from ahub) */
+       if (codec_i2s->playback_ref_count == 1)
+                       codec_i2s->reg_ctrl &= ~TEGRA30_I2S_CTRL_XFER_EN_TX;
+
+       tegra30_i2s_write(codec_i2s, TEGRA30_I2S_CTRL, codec_i2s->reg_ctrl);
+
+       while (!tegra30_ahub_tx_fifo_is_empty(codec_i2s->id) && dcnt--)
+               udelay(100);
+
+       dcnt = 10;
+
+       /* Disable baseband DAM */
+       tegra30_dam_enable(bb_i2s->dam_ifc, TEGRA30_DAM_DISABLE,
                        TEGRA30_DAM_CHIN0_SRC);
-               tegra30_dam_enable(bb_i2s->dam_ifc, TEGRA30_DAM_ENABLE,
+       tegra30_dam_free_channel(bb_i2s->dam_ifc,
                        TEGRA30_DAM_CHIN0_SRC);
+       bb_i2s->dam_ch_refcount--;
+       if (!bb_i2s->dam_ch_refcount)
+               tegra30_dam_free_controller(bb_i2s->dam_ifc);
+
+       /* Disable Codec DAM */
+       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);
+       codec_i2s->dam_ch_refcount--;
+       if (!codec_i2s->dam_ch_refcount)
+               tegra30_dam_free_controller(codec_i2s->dam_ifc);
+
+       /* Disconnect the ahub connections */
+       /* If this is the only user of i2s tx then break ahub
+               i2s rx connection */
+       if (codec_i2s->playback_ref_count == 1)
+               tegra30_ahub_unset_rx_cif_source(
+                  TEGRA30_AHUB_RXCIF_I2S0_RX0 + codec_info->i2s_id);
+
+       tegra30_ahub_unset_rx_cif_source(TEGRA30_AHUB_RXCIF_BBC1_RX0);
+       tegra30_ahub_unset_rx_cif_source(TEGRA30_AHUB_RXCIF_DAM0_RX0
+                               + (codec_i2s->dam_ifc*2));
+       tegra30_ahub_unset_rx_cif_source(TEGRA30_AHUB_RXCIF_DAM0_RX0
+                               + (bb_i2s->dam_ifc*2));
+
+       tegra30_dam_disable_clock(codec_i2s->dam_ifc);
+       tegra30_dam_disable_clock(bb_i2s->dam_ifc);
+
+       /* Decrement the codec and bb i2s playback ref count */
+       codec_i2s->playback_ref_count--;
+       bb_i2s->playback_ref_count--;
+       codec_i2s->capture_ref_count--;
+       bb_i2s->capture_ref_count--;
+
+       /* Soft reset */
+       tegra30_i2s_write(codec_i2s, TEGRA30_I2S_CTRL,
+               codec_i2s->reg_ctrl | TEGRA30_I2S_CTRL_SOFT_RESET);
+
+       codec_i2s->reg_ctrl &= ~TEGRA30_I2S_CTRL_TX_FLOWCTL_EN;
+       codec_i2s->reg_ctrl &= ~TEGRA30_I2S_CTRL_SOFT_RESET;
+
+       while ((tegra30_i2s_read(codec_i2s, TEGRA30_I2S_CTRL) &
+                       TEGRA30_I2S_CTRL_SOFT_RESET)  && dcnt--)
+               udelay(100);
+
+       /* Disable the clocks */
+       tegra30_i2s_disable_clocks(codec_i2s);
+
+       return 0;
+}
+
+int t14x_make_voice_call_connections(struct codec_config *codec_info,
+                               struct ahub_bbc1_config *bb_info,
+                               int uses_voice_codec)
+{
+       struct tegra30_i2s *codec_i2s = &i2scont[codec_info->i2s_id];
+       struct tegra30_i2s *bb_i2s = &bbc1cont;
+
+       /* increment the codec i2s playback ref count */
+       codec_i2s->playback_ref_count++;
+       bb_i2s->playback_ref_count++;
+       codec_i2s->capture_ref_count++;
+       bb_i2s->capture_ref_count++;
+
+       /* Configure codec i2s */
+       configure_baseband_i2s(codec_i2s, codec_info->is_i2smaster,
+               codec_info->i2s_mode, codec_info->channels,
+               codec_info->rate, codec_info->bitsize,
+               codec_info->bit_clk);
+
+       /* configure codec i2s tx cif */
+       tegra30_i2s_set_cif_channels(codec_i2s, TEGRA30_I2S_CIF_TX_CTRL,
+                       bb_info->channels, codec_info->channels);
+       tegra30_i2s_set_cif_bits(codec_i2s, TEGRA30_I2S_CIF_TX_CTRL,
+                       TEGRA30_AUDIOCIF_BITS_16, TEGRA30_AUDIOCIF_BITS_16);
+
+       if (codec_info->channels == 2 && bb_info->channels == 1) {
+               tegra30_i2s_set_cif_stereo_conv(codec_i2s,
+                               TEGRA30_I2S_CIF_TX_CTRL,
+                               TEGRA30_CIF_STEREOCONV_AVG);
        }
 
+       /* configure dam in DL path */
+       configure_dam(codec_i2s, bb_info->channels,
+          bb_info->rate, bb_info->sample_size, codec_info->channels,
+          48000, codec_info->bitsize);
+
+       tegra30_dam_allocate_channel(codec_i2s->dam_ifc, TEGRA30_DAM_CHIN1);
+       codec_i2s->dam_ch_refcount++;
+
+       tegra30_dam_set_gain(codec_i2s->dam_ifc, TEGRA30_DAM_CHIN1, 0x1000);
+       tegra30_dam_set_acif(codec_i2s->dam_ifc, TEGRA30_DAM_CHIN1, 1,
+                       codec_info->bitsize, 1, 32);
+       tegra30_dam_set_acif(codec_i2s->dam_ifc, TEGRA30_DAM_CHOUT, 2, 16,
+               1, 32);
+       tegra30_dam_ch0_set_datasync(codec_i2s->dam_ifc, 2);
+       tegra30_dam_ch1_set_datasync(codec_i2s->dam_ifc, 0);
+
+       tegra30_dam_set_acif_stereo_conv(codec_i2s->dam_ifc,
+                       TEGRA30_DAM_CHIN0_SRC,
+                       TEGRA30_CIF_STEREOCONV_AVG);
+
+       /* do routing in ahub */
+       tegra30_ahub_set_rx_cif_source(TEGRA30_AHUB_RXCIF_DAM0_RX1 +
+                       (codec_i2s->dam_ifc*2), TEGRA30_AHUB_TXCIF_BBC1_TX0);
+
+       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_BBC1_RX0,
+                       TEGRA30_AHUB_TXCIF_I2S0_TX0 + codec_info->i2s_id);
+
+       tegra30_ahub_set_rx_cif_source(TEGRA30_AHUB_RXCIF_I2S0_RX0 +
+               codec_info->i2s_id,
+               TEGRA30_AHUB_TXCIF_DAM0_TX0 + codec_i2s->dam_ifc);
+
+
+       /* enable the dam*/
+       tegra30_dam_enable(codec_i2s->dam_ifc, TEGRA30_DAM_ENABLE,
+               TEGRA30_DAM_CHIN0_SRC);
+
+       tegra30_dam_enable(codec_i2s->dam_ifc, TEGRA30_DAM_ENABLE,
+                       TEGRA30_DAM_CHIN1);
+
        codec_i2s->reg_ctrl |= TEGRA30_I2S_CTRL_XFER_EN_TX;
        codec_i2s->reg_ctrl |= TEGRA30_I2S_CTRL_XFER_EN_RX;
        tegra30_i2s_write(codec_i2s, TEGRA30_I2S_CTRL,
@@ -1236,7 +1454,7 @@ int t14x_break_voice_call_connections(struct codec_config *codec_info,
        struct tegra30_i2s *bb_i2s = &bbc1cont;
        int dcnt = 10;
 
-       /*Disable Codec I2S RX (TX to ahub)*/
+       /* Disable Codec I2S RX (TX to ahub) */
        if (codec_i2s->capture_ref_count == 1)
                codec_i2s->reg_ctrl &= ~TEGRA30_I2S_CTRL_XFER_EN_RX;
 
@@ -1247,9 +1465,9 @@ int t14x_break_voice_call_connections(struct codec_config *codec_info,
 
        dcnt = 10;
 
-       /*Disable Codec I2S TX (RX from ahub)*/
+       /* Disable Codec I2S TX (RX from ahub) */
        if (codec_i2s->playback_ref_count == 1)
-                       codec_i2s->reg_ctrl &= ~TEGRA30_I2S_CTRL_XFER_EN_TX;
+               codec_i2s->reg_ctrl &= ~TEGRA30_I2S_CTRL_XFER_EN_TX;
 
        tegra30_i2s_write(codec_i2s, TEGRA30_I2S_CTRL, codec_i2s->reg_ctrl);
 
@@ -1258,47 +1476,34 @@ int t14x_break_voice_call_connections(struct codec_config *codec_info,
 
        dcnt = 10;
 
-       if (uses_voice_codec) {
-               tegra30_ahub_unset_rx_cif_source(TEGRA30_AHUB_RXCIF_I2S0_RX0 +
-                           bb_info->port_id);
-               tegra30_ahub_unset_rx_cif_source(TEGRA30_AHUB_RXCIF_I2S0_RX0 +
-                           codec_info->i2s_id);
-       } else {
+       /* Disable DAM in DL path */
+       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);
 
-               /*Disable baseband DAM*/
-               tegra30_dam_enable(bb_i2s->dam_ifc, TEGRA30_DAM_DISABLE,
-                               TEGRA30_DAM_CHIN0_SRC);
-               tegra30_dam_free_channel(bb_i2s->dam_ifc,
-                               TEGRA30_DAM_CHIN0_SRC);
-               bb_i2s->dam_ch_refcount--;
-               if (!bb_i2s->dam_ch_refcount)
-                       tegra30_dam_free_controller(bb_i2s->dam_ifc);
+       tegra30_dam_enable(codec_i2s->dam_ifc,
+               TEGRA30_DAM_DISABLE, TEGRA30_DAM_CHIN1);
+       tegra30_dam_free_channel(codec_i2s->dam_ifc,
+               TEGRA30_DAM_CHIN1);
 
-               /*Disable Codec DAM*/
-               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);
-               codec_i2s->dam_ch_refcount--;
-               if (!codec_i2s->dam_ch_refcount)
-                       tegra30_dam_free_controller(codec_i2s->dam_ifc);
+       codec_i2s->dam_ch_refcount--;
+       if (!codec_i2s->dam_ch_refcount)
+               tegra30_dam_free_controller(codec_i2s->dam_ifc);
 
-               /* Disconnect the ahub connections */
-               /* If this is the only user of i2s tx then break ahub
-               i2s rx connection */
-               if (codec_i2s->playback_ref_count == 1)
-                       tegra30_ahub_unset_rx_cif_source(
-                          TEGRA30_AHUB_RXCIF_I2S0_RX0 + codec_info->i2s_id);
+       /* Disconnect the ahub connections */
+       tegra30_ahub_unset_rx_cif_source(TEGRA30_AHUB_RXCIF_BBC1_RX0);
 
-               tegra30_ahub_unset_rx_cif_source(TEGRA30_AHUB_RXCIF_BBC1_RX0);
-               tegra30_ahub_unset_rx_cif_source(TEGRA30_AHUB_RXCIF_DAM0_RX0
-                                       + (codec_i2s->dam_ifc*2));
-               tegra30_ahub_unset_rx_cif_source(TEGRA30_AHUB_RXCIF_DAM0_RX0
-                                       + (bb_i2s->dam_ifc*2));
+       tegra30_ahub_unset_rx_cif_source(TEGRA30_AHUB_RXCIF_I2S0_RX0 +
+                       codec_info->i2s_id);
 
-               tegra30_dam_disable_clock(codec_i2s->dam_ifc);
-               tegra30_dam_disable_clock(bb_i2s->dam_ifc);
-       }
+       tegra30_ahub_unset_rx_cif_source(TEGRA30_AHUB_RXCIF_DAM0_RX1 +
+                       (codec_i2s->dam_ifc*2));
+
+       tegra30_ahub_unset_rx_cif_source(TEGRA30_AHUB_RXCIF_DAM0_RX0 +
+               (codec_i2s->dam_ifc*2));
+
+       tegra30_dam_disable_clock(codec_i2s->dam_ifc);
 
        /* Decrement the codec and bb i2s playback ref count */
        codec_i2s->playback_ref_count--;
@@ -1316,7 +1521,6 @@ int t14x_break_voice_call_connections(struct codec_config *codec_info,
        while ((tegra30_i2s_read(codec_i2s, TEGRA30_I2S_CTRL) &
                        TEGRA30_I2S_CTRL_SOFT_RESET)  && dcnt--)
                udelay(100);
-       dcnt = 10;
 
        /* Disable the clocks */
        tegra30_i2s_disable_clocks(codec_i2s);
index a4fa22f..cbe5747 100644 (file)
@@ -304,6 +304,14 @@ int tegra30_break_voice_call_connections(struct codec_config *codec_info,
                        int uses_voice_codec);
 
 #if defined(CONFIG_ARCH_TEGRA_14x_SOC)
+int t14x_make_bt_voice_call_connections(struct codec_config *codec_info,
+                               struct ahub_bbc1_config *bb_info,
+                               int uses_voice_codec);
+
+int t14x_break_bt_voice_call_connections(struct codec_config *codec_info,
+                               struct ahub_bbc1_config *bb_info,
+                               int uses_voice_codec);
+
 int t14x_make_voice_call_connections(struct codec_config *codec_info,
                                struct ahub_bbc1_config *bb_info,
                                int uses_voice_codec);
index e31447a..be70ea3 100644 (file)
@@ -302,20 +302,32 @@ static int tegra_aic325x_call_mode_put(struct snd_kcontrol *kcontrol,
                for (i = 0; i < machine->pcard->num_links; i++)
                        machine->pcard->dai_link[i].ignore_suspend = 1;
 
-#ifdef CONFIG_ARCH_TEGRA_14x_SOC
+#if defined(CONFIG_ARCH_TEGRA_14x_SOC)
+       if (machine->is_device_bt) {
+               t14x_make_bt_voice_call_connections(
+                       &machine->codec_info[codec_index],
+                       &machine->ahub_bbc1_info, 0);
+       } else {
                t14x_make_voice_call_connections(
                        &machine->codec_info[codec_index],
                        &machine->ahub_bbc1_info, 0);
+       }
 #else
                tegra30_make_voice_call_connections(
                        &machine->codec_info[codec_index],
                        &machine->codec_info[BASEBAND], 0);
 #endif
        } else {
-#ifdef CONFIG_ARCH_TEGRA_14x_SOC
-               t14x_break_voice_call_connections(
+ #if defined(CONFIG_ARCH_TEGRA_14x_SOC)
+               if (machine->is_device_bt) {
+                       t14x_break_bt_voice_call_connections(
+                               &machine->codec_info[codec_index],
+                               &machine->ahub_bbc1_info, 0);
+               } else {
+                       t14x_break_voice_call_connections(
                        &machine->codec_info[codec_index],
                        &machine->ahub_bbc1_info, 0);
+               }
 #else
                tegra30_break_voice_call_connections(
                        &machine->codec_info[codec_index],
@@ -1140,7 +1152,8 @@ static int tegra_aic325x_init(struct snd_soc_pcm_runtime *rtd)
        struct tegra30_i2s *i2s = snd_soc_dai_get_drvdata(rtd->cpu_dai);
        int ret;
 
-       if (machine->codec_info[BASEBAND].i2s_id != -1)
+       i2s->is_dam_used = false;
+       if (i2s->id == machine->codec_info[BT_SCO].i2s_id)
                i2s->is_dam_used = true;
 
        if (machine->init_done)
index ed5709c..a3d49f7 100644 (file)
@@ -145,10 +145,16 @@ static int tegra_call_mode_put(struct snd_kcontrol *kcontrol,
                for (i = 0; i < machine->pcard->num_links; i++)
                        machine->pcard->dai_link[i].ignore_suspend = 1;
 
- #if defined(CONFIG_ARCH_TEGRA_14x_SOC)
+#if defined(CONFIG_ARCH_TEGRA_14x_SOC)
+       if (machine->is_device_bt) {
+               t14x_make_bt_voice_call_connections(
+                       &machine->codec_info[codec_index],
+                       &machine->ahub_bbc1_info, 0);
+       } else {
                t14x_make_voice_call_connections(
                        &machine->codec_info[codec_index],
                        &machine->ahub_bbc1_info, 0);
+       }
 #else
                tegra30_make_voice_call_connections(
                        &machine->codec_info[codec_index],
@@ -156,9 +162,15 @@ static int tegra_call_mode_put(struct snd_kcontrol *kcontrol,
 #endif
        } else {
  #if defined(CONFIG_ARCH_TEGRA_14x_SOC)
-               t14x_break_voice_call_connections(
+               if (machine->is_device_bt) {
+                       t14x_break_bt_voice_call_connections(
+                               &machine->codec_info[codec_index],
+                               &machine->ahub_bbc1_info, 0);
+               } else {
+                       t14x_break_voice_call_connections(
                        &machine->codec_info[codec_index],
                        &machine->ahub_bbc1_info, 0);
+               }
 #else
                tegra30_break_voice_call_connections(
                        &machine->codec_info[codec_index],
@@ -342,7 +354,7 @@ static int tegra_max98090_hw_params(struct snd_pcm_substream *substream,
                }
        }
 
-       if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
+       if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK && i2s->is_dam_used)
                tegra_max98090_set_dam_cif(i2s->dam_ifc, srate,
                        params_channels(params), sample_size, 0, 0, 0, 0);
 
@@ -432,7 +444,7 @@ static int tegra_bt_hw_params(struct snd_pcm_substream *substream,
                return err;
        }
 
-       if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
+       if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK && i2s->is_dam_used)
                tegra_max98090_set_dam_cif(i2s->dam_ifc, params_rate(params),
                        params_channels(params), sample_size, 0, 0, 0, 0);
 
@@ -980,7 +992,8 @@ static int tegra_max98090_init(struct snd_soc_pcm_runtime *rtd)
        struct tegra30_i2s *i2s = snd_soc_dai_get_drvdata(rtd->cpu_dai);
        int ret;
 
-       if (machine->codec_info[BASEBAND].i2s_id != -1)
+       i2s->is_dam_used = false;
+       if (i2s->id == machine->codec_info[BT_SCO].i2s_id)
                i2s->is_dam_used = true;
 
        if (machine->init_done)