summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNikesh Oswal <noswal@nvidia.com>2011-12-28 14:33:22 +0530
committerVarun Wadekar <vwadekar@nvidia.com>2011-12-30 10:48:10 +0530
commit3a73bba61fbe76853106c18820fcbb27cd8357f8 (patch)
treeb393275a5570081e516ddb8b83bacc635cae6d9d
parent440d5168436588fd72b74092cfd4aef0740c079f (diff)
asoc: tegra: max98088 machine: add support for voice call recording
Bug: 912897 Change-Id: I3bdc879d7eecea78eace7452fd9b157f68aeea48 Signed-off-by: Nikesh Oswal <noswal@nvidia.com> Reviewed-on: http://git-master/r/72355 Reviewed-by: Automatic_Commit_Validation_User Reviewed-by: Scott Peterson <speterson@nvidia.com> Reviewed-by: Sumit Bhattacharya <sumitb@nvidia.com>
-rw-r--r--sound/soc/tegra/tegra_max98088.c176
1 files changed, 133 insertions, 43 deletions
diff --git a/sound/soc/tegra/tegra_max98088.c b/sound/soc/tegra/tegra_max98088.c
index 9b2d1e9af478..9d1c8d51a0a8 100644
--- a/sound/soc/tegra/tegra_max98088.c
+++ b/sound/soc/tegra/tegra_max98088.c
@@ -172,8 +172,10 @@ struct snd_kcontrol_new tegra_call_mode_control = {
#ifndef CONFIG_ARCH_TEGRA_2x_SOC
static int tegra_max98088_set_dam_cif(int dam_ifc, int srate,
- int channels, int bit_size)
+ int channels, int bit_size, int src_on, int src_srate,
+ int src_channels, int src_bit_size)
{
+ tegra30_dam_set_gain(dam_ifc, TEGRA30_DAM_CHIN1, 0x1000);
tegra30_dam_set_samplerate(dam_ifc, TEGRA30_DAM_CHOUT,
srate);
tegra30_dam_set_samplerate(dam_ifc, TEGRA30_DAM_CHIN1,
@@ -185,6 +187,14 @@ static int tegra_max98088_set_dam_cif(int dam_ifc, int srate,
channels, bit_size, channels,
bit_size);
+ if (src_on) {
+ tegra30_dam_set_gain(dam_ifc, TEGRA30_DAM_CHIN0_SRC, 0x1000);
+ tegra30_dam_set_samplerate(dam_ifc, TEGRA30_DAM_CHIN0_SRC,
+ src_srate);
+ tegra30_dam_set_acif(dam_ifc, TEGRA30_DAM_CHIN0_SRC,
+ src_channels, src_bit_size, 1, 16);
+ }
+
return 0;
}
#endif
@@ -274,7 +284,7 @@ static int tegra_max98088_hw_params(struct snd_pcm_substream *substream,
#ifndef CONFIG_ARCH_TEGRA_2x_SOC
if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
tegra_max98088_set_dam_cif(i2s->dam_ifc, srate,
- params_channels(params), sample_size);
+ params_channels(params), sample_size, 0, 0, 0, 0);
#endif
return 0;
@@ -389,7 +399,7 @@ static int tegra_bt_hw_params(struct snd_pcm_substream *substream,
#ifndef CONFIG_ARCH_TEGRA_2x_SOC
if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
tegra_max98088_set_dam_cif(i2s->dam_ifc, params_rate(params),
- params_channels(params), sample_size);
+ params_channels(params), sample_size, 0, 0, 0, 0);
#endif
return 0;
@@ -411,35 +421,87 @@ static int tegra_max98088_startup(struct snd_pcm_substream *substream)
struct snd_soc_pcm_runtime *rtd = substream->private_data;
struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
struct tegra30_i2s *i2s = snd_soc_dai_get_drvdata(cpu_dai);
+ struct tegra_max98088 *machine = snd_soc_card_get_drvdata(rtd->card);
+ struct codec_config *codec_info;
+ struct codec_config *bb_info;
+ int codec_index;
- if ((substream->stream != SNDRV_PCM_STREAM_PLAYBACK) ||
- !(i2s->is_dam_used))
+ if (!i2s->is_dam_used)
return 0;
- /*dam configuration*/
- if (!i2s->dam_ch_refcount)
- i2s->dam_ifc = tegra30_dam_allocate_controller();
-
- tegra30_dam_allocate_channel(i2s->dam_ifc, TEGRA30_DAM_CHIN1);
- i2s->dam_ch_refcount++;
- tegra30_dam_enable_clock(i2s->dam_ifc);
- tegra30_dam_set_gain(i2s->dam_ifc, TEGRA30_DAM_CHIN1, 0x1000);
-
- tegra30_ahub_set_rx_cif_source(TEGRA30_AHUB_RXCIF_DAM0_RX1 +
- (i2s->dam_ifc*2), i2s->txcif);
-
- /*
- *make the dam tx to i2s rx connection if this is the only client
- *using i2s for playback
- */
- if (i2s->playback_ref_count == 1)
- tegra30_ahub_set_rx_cif_source(
- TEGRA30_AHUB_RXCIF_I2S0_RX0 + i2s->id,
- TEGRA30_AHUB_TXCIF_DAM0_TX0 + i2s->dam_ifc);
-
- /* enable the dam*/
- tegra30_dam_enable(i2s->dam_ifc, TEGRA30_DAM_ENABLE,
+ if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
+ /*dam configuration*/
+ if (!i2s->dam_ch_refcount)
+ i2s->dam_ifc = tegra30_dam_allocate_controller();
+
+ tegra30_dam_allocate_channel(i2s->dam_ifc, TEGRA30_DAM_CHIN1);
+ i2s->dam_ch_refcount++;
+ tegra30_dam_enable_clock(i2s->dam_ifc);
+
+ tegra30_ahub_set_rx_cif_source(TEGRA30_AHUB_RXCIF_DAM0_RX1 +
+ (i2s->dam_ifc*2), i2s->txcif);
+
+ /*
+ *make the dam tx to i2s rx connection if this is the only client
+ *using i2s for playback
+ */
+ if (i2s->playback_ref_count == 1)
+ tegra30_ahub_set_rx_cif_source(
+ TEGRA30_AHUB_RXCIF_I2S0_RX0 + i2s->id,
+ TEGRA30_AHUB_TXCIF_DAM0_TX0 + i2s->dam_ifc);
+
+ /* enable the dam*/
+ tegra30_dam_enable(i2s->dam_ifc, TEGRA30_DAM_ENABLE,
+ TEGRA30_DAM_CHIN1);
+ } else {
+
+ i2s->is_call_mode_rec = machine->is_call_mode;
+
+ if (!i2s->is_call_mode_rec)
+ return 0;
+
+ if (machine->is_device_bt)
+ codec_index = BT_SCO;
+ else
+ codec_index = HIFI_CODEC;
+
+ codec_info = &machine->codec_info[codec_index];
+ bb_info = &machine->codec_info[BASEBAND];
+
+ /* allocate a dam for voice call recording */
+
+ i2s->call_record_dam_ifc = tegra30_dam_allocate_controller();
+ tegra30_dam_allocate_channel(i2s->call_record_dam_ifc,
+ TEGRA30_DAM_CHIN0_SRC);
+ tegra30_dam_allocate_channel(i2s->call_record_dam_ifc,
TEGRA30_DAM_CHIN1);
+ tegra30_dam_enable_clock(i2s->call_record_dam_ifc);
+
+ /* configure the dam */
+ tegra_max98088_set_dam_cif(i2s->call_record_dam_ifc,
+ codec_info->rate, codec_info->channels,
+ codec_info->bitsize, 1, bb_info->rate,
+ bb_info->channels, bb_info->bitsize);
+
+ /* setup the connections for voice call record */
+
+ tegra30_ahub_unset_rx_cif_source(i2s->rxcif);
+ tegra30_ahub_set_rx_cif_source(TEGRA30_AHUB_RXCIF_DAM0_RX0 +
+ (i2s->call_record_dam_ifc*2),
+ TEGRA30_AHUB_TXCIF_I2S0_TX0 + bb_info->i2s_id);
+ tegra30_ahub_set_rx_cif_source(TEGRA30_AHUB_RXCIF_DAM0_RX1 +
+ (i2s->call_record_dam_ifc*2),
+ TEGRA30_AHUB_TXCIF_I2S0_TX0 + codec_info->i2s_id);
+ tegra30_ahub_set_rx_cif_source(i2s->rxcif,
+ TEGRA30_AHUB_TXCIF_DAM0_TX0 + i2s->call_record_dam_ifc);
+
+ /* enable the dam*/
+
+ tegra30_dam_enable(i2s->call_record_dam_ifc, TEGRA30_DAM_ENABLE,
+ TEGRA30_DAM_CHIN1);
+ tegra30_dam_enable(i2s->call_record_dam_ifc, TEGRA30_DAM_ENABLE,
+ TEGRA30_DAM_CHIN0_SRC);
+ }
return 0;
}
@@ -450,24 +512,52 @@ static void tegra_max98088_shutdown(struct snd_pcm_substream *substream)
struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
struct tegra30_i2s *i2s = snd_soc_dai_get_drvdata(cpu_dai);
- if ((substream->stream != SNDRV_PCM_STREAM_PLAYBACK) ||
- !(i2s->is_dam_used))
+ if (!i2s->is_dam_used)
return;
- /* disable the dam*/
- tegra30_dam_enable(i2s->dam_ifc, TEGRA30_DAM_DISABLE,
+ if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
+ /* disable the dam*/
+ tegra30_dam_enable(i2s->dam_ifc, TEGRA30_DAM_DISABLE,
+ TEGRA30_DAM_CHIN1);
+
+ /* disconnect the ahub connections*/
+ tegra30_ahub_unset_rx_cif_source(TEGRA30_AHUB_RXCIF_DAM0_RX1 +
+ (i2s->dam_ifc*2));
+
+ /* disable the dam and free the controller */
+ tegra30_dam_disable_clock(i2s->dam_ifc);
+ tegra30_dam_free_channel(i2s->dam_ifc, TEGRA30_DAM_CHIN1);
+ i2s->dam_ch_refcount--;
+ if (!i2s->dam_ch_refcount)
+ tegra30_dam_free_controller(i2s->dam_ifc);
+ } else {
+
+ if (!i2s->is_call_mode_rec)
+ return 0;
+
+ i2s->is_call_mode_rec = 0;
+
+ /* disable the dam*/
+ tegra30_dam_enable(i2s->call_record_dam_ifc,
+ TEGRA30_DAM_DISABLE, TEGRA30_DAM_CHIN1);
+ tegra30_dam_enable(i2s->call_record_dam_ifc,
+ TEGRA30_DAM_DISABLE, TEGRA30_DAM_CHIN0_SRC);
+
+ /* disconnect the ahub connections*/
+ tegra30_ahub_unset_rx_cif_source(i2s->rxcif);
+ tegra30_ahub_unset_rx_cif_source(TEGRA30_AHUB_RXCIF_DAM0_RX0 +
+ (i2s->call_record_dam_ifc*2));
+ tegra30_ahub_unset_rx_cif_source(TEGRA30_AHUB_RXCIF_DAM0_RX1 +
+ (i2s->call_record_dam_ifc*2));
+
+ /* free the dam channels and dam controller */
+ tegra30_dam_disable_clock(i2s->call_record_dam_ifc);
+ tegra30_dam_free_channel(i2s->call_record_dam_ifc,
TEGRA30_DAM_CHIN1);
-
- /* disconnect the ahub connections*/
- tegra30_ahub_unset_rx_cif_source(TEGRA30_AHUB_RXCIF_DAM0_RX1 +
- (i2s->dam_ifc*2));
-
- /* disable the dam and free the controller */
- tegra30_dam_disable_clock(i2s->dam_ifc);
- tegra30_dam_free_channel(i2s->dam_ifc, TEGRA30_DAM_CHIN1);
- i2s->dam_ch_refcount--;
- if (!i2s->dam_ch_refcount)
- tegra30_dam_free_controller(i2s->dam_ifc);
+ tegra30_dam_free_channel(i2s->call_record_dam_ifc,
+ TEGRA30_DAM_CHIN0_SRC);
+ tegra30_dam_free_controller(i2s->call_record_dam_ifc);
+ }
return;
}