diff options
author | Ravindra Lokhande <rlokhande@nvidia.com> | 2013-05-03 22:12:39 +0530 |
---|---|---|
committer | Dan Willemsen <dwillemsen@nvidia.com> | 2013-09-14 13:16:22 -0700 |
commit | ec72dba22c55458339f50bd38288149a20b3b73b (patch) | |
tree | 531a77a0fdf693164a1a4ee2c1e63ea2a588b48d /sound | |
parent | 0045ca2e46cad7e3d7979ac434836e3db58c584a (diff) |
ASoC: Tegra: Add support for dual mic
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>
Diffstat (limited to 'sound')
-rw-r--r-- | sound/soc/tegra/tegra30_dam.c | 8 | ||||
-rw-r--r-- | sound/soc/tegra/tegra30_dam.h | 2 | ||||
-rw-r--r-- | sound/soc/tegra/tegra30_i2s.c | 366 | ||||
-rw-r--r-- | sound/soc/tegra/tegra30_i2s.h | 8 | ||||
-rw-r--r-- | sound/soc/tegra/tegra_aic325x.c | 21 | ||||
-rw-r--r-- | sound/soc/tegra/tegra_max98090.c | 23 |
6 files changed, 336 insertions, 92 deletions
diff --git a/sound/soc/tegra/tegra30_dam.c b/sound/soc/tegra/tegra30_dam.c index d4206a99dd7d..0f64886945fb 100644 --- a/sound/soc/tegra/tegra30_dam.c +++ b/sound/soc/tegra/tegra30_dam.c @@ -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; diff --git a/sound/soc/tegra/tegra30_dam.h b/sound/soc/tegra/tegra30_dam.h index df3b6e5d6bcf..0e9733c413c7 100644 --- a/sound/soc/tegra/tegra30_dam.h +++ b/sound/soc/tegra/tegra30_dam.h @@ -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); diff --git a/sound/soc/tegra/tegra30_i2s.c b/sound/soc/tegra/tegra30_i2s.c index d5815cb80e8d..0e9991e7237e 100644 --- a/sound/soc/tegra/tegra30_i2s.c +++ b/sound/soc/tegra/tegra30_i2s.c @@ -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); diff --git a/sound/soc/tegra/tegra30_i2s.h b/sound/soc/tegra/tegra30_i2s.h index a4fa22fb7e56..cbe57475b232 100644 --- a/sound/soc/tegra/tegra30_i2s.h +++ b/sound/soc/tegra/tegra30_i2s.h @@ -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); diff --git a/sound/soc/tegra/tegra_aic325x.c b/sound/soc/tegra/tegra_aic325x.c index e31447a1bc97..be70ea3524ee 100644 --- a/sound/soc/tegra/tegra_aic325x.c +++ b/sound/soc/tegra/tegra_aic325x.c @@ -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) diff --git a/sound/soc/tegra/tegra_max98090.c b/sound/soc/tegra/tegra_max98090.c index ed5709c754a4..a3d49f76a14c 100644 --- a/sound/soc/tegra/tegra_max98090.c +++ b/sound/soc/tegra/tegra_max98090.c @@ -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) |