summaryrefslogtreecommitdiff
path: root/sound
diff options
context:
space:
mode:
Diffstat (limited to 'sound')
-rw-r--r--sound/soc/tegra/tegra30_i2s.h1
-rw-r--r--sound/soc/tegra/tegra_aic326x.c109
2 files changed, 73 insertions, 37 deletions
diff --git a/sound/soc/tegra/tegra30_i2s.h b/sound/soc/tegra/tegra30_i2s.h
index ef0aded64b86..562bf53d40c2 100644
--- a/sound/soc/tegra/tegra30_i2s.h
+++ b/sound/soc/tegra/tegra30_i2s.h
@@ -277,6 +277,7 @@ struct tegra30_i2s {
#endif
#endif
int call_record_dam_ifc;
+ int call_record_dam_ifc2;
int is_call_mode_rec;
struct dsp_config_t dsp_config;
diff --git a/sound/soc/tegra/tegra_aic326x.c b/sound/soc/tegra/tegra_aic326x.c
index 215f6e2df750..d5fcd99fbc1b 100644
--- a/sound/soc/tegra/tegra_aic326x.c
+++ b/sound/soc/tegra/tegra_aic326x.c
@@ -529,40 +529,26 @@ static int tegra_aic326x_startup(struct snd_pcm_substream *substream)
struct tegra_aic326x *machine = snd_soc_card_get_drvdata(rtd->card);
struct codec_config *codec_info;
struct codec_config *bb_info;
+ struct codec_config *hifi_info;
int codec_index;
if (!i2s->is_dam_used)
return 0;
if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
- /*dam configuration*/
- if (!i2s->dam_ch_refcount)
- i2s->dam_ifc = tegra30_dam_allocate_controller();
- if (i2s->dam_ifc < 0)
- return i2s->dam_ifc;
- 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
+ *make apbif tx to i2s rx connection if this is the only client
*using i2s for playback
*/
- if (i2s->playback_ref_count == 1)
+ 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);
+ i2s->txcif);
+ tegra30_ahub_enable_clocks();
+ }
- /* 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;
@@ -573,8 +559,9 @@ static int tegra_aic326x_startup(struct snd_pcm_substream *substream)
codec_info = &machine->codec_info[codec_index];
bb_info = &machine->codec_info[BASEBAND];
+ hifi_info = &machine->codec_info[HIFI_CODEC];
- /* allocate a dam for voice call recording */
+ /* allocate a dams for voice call recording */
i2s->call_record_dam_ifc = tegra30_dam_allocate_controller();
@@ -587,30 +574,69 @@ static int tegra_aic326x_startup(struct snd_pcm_substream *substream)
TEGRA30_DAM_CHIN1);
tegra30_dam_enable_clock(i2s->call_record_dam_ifc);
- /* configure the dam */
+ i2s->call_record_dam_ifc2 = tegra30_dam_allocate_controller();
+
+ if (i2s->call_record_dam_ifc2 < 0)
+ return i2s->call_record_dam_ifc2;
+
+ tegra30_dam_allocate_channel(i2s->call_record_dam_ifc2,
+ TEGRA30_DAM_CHIN0_SRC);
+ tegra30_dam_allocate_channel(i2s->call_record_dam_ifc2,
+ TEGRA30_DAM_CHIN1);
+ tegra30_dam_enable_clock(i2s->call_record_dam_ifc2);
+
+ /* configure the dams */
+ /* DAM0 SRC bb rate to hifi rate */
tegra_aic326x_set_dam_cif(i2s->call_record_dam_ifc,
codec_info->rate, codec_info->channels,
+ codec_info->bitsize, 1, hifi_info->rate,
+ hifi_info->channels, hifi_info->bitsize);
+ /* DAM1 UL + DL Mix */
+ tegra_aic326x_set_dam_cif(i2s->call_record_dam_ifc2,
+ 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),
+ (i2s->call_record_dam_ifc2*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),
+ (i2s->call_record_dam_ifc2*2),
TEGRA30_AHUB_TXCIF_I2S0_TX0 + codec_info->i2s_id);
+ tegra30_ahub_set_rx_cif_source(TEGRA30_AHUB_RXCIF_DAM0_RX0 +
+ (i2s->call_record_dam_ifc*2),
+ TEGRA30_AHUB_TXCIF_DAM0_TX0 +
+ i2s->call_record_dam_ifc2);
tegra30_ahub_set_rx_cif_source(i2s->rxcif,
TEGRA30_AHUB_TXCIF_DAM0_TX0 + i2s->call_record_dam_ifc);
- /* enable the dam*/
+ /* Configure DAM0 for SRC */
+ if (bb_info->rate != hifi_info->rate) {
+ tegra30_dam_write_coeff_ram(i2s->call_record_dam_ifc,
+ bb_info->rate, hifi_info->rate);
+ tegra30_dam_set_farrow_param(i2s->call_record_dam_ifc,
+ bb_info->rate, hifi_info->rate);
+ tegra30_dam_set_biquad_fixed_coef(
+ i2s->call_record_dam_ifc);
+ tegra30_dam_enable_coeff_ram(i2s->call_record_dam_ifc);
+ tegra30_dam_set_filter_stages(i2s->call_record_dam_ifc,
+ bb_info->rate,
+ hifi_info->rate);
+ }
+ /* 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);
+ tegra30_dam_enable(i2s->call_record_dam_ifc2,
+ TEGRA30_DAM_ENABLE,
+ TEGRA30_DAM_CHIN1);
+ tegra30_dam_enable(i2s->call_record_dam_ifc2,
+ TEGRA30_DAM_ENABLE,
+ TEGRA30_DAM_CHIN0_SRC);
}
return 0;
@@ -647,26 +673,39 @@ static void tegra_aic326x_shutdown(struct snd_pcm_substream *substream)
i2s->is_call_mode_rec = 0;
- /* disable the dam*/
+ /* disable the dams*/
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);
+ tegra30_dam_enable(i2s->call_record_dam_ifc2,
+ TEGRA30_DAM_DISABLE, TEGRA30_DAM_CHIN1);
+ tegra30_dam_enable(i2s->call_record_dam_ifc2,
+ 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));
+ (i2s->call_record_dam_ifc2*2));
tegra30_ahub_unset_rx_cif_source(TEGRA30_AHUB_RXCIF_DAM0_RX1 +
- (i2s->call_record_dam_ifc*2));
+ (i2s->call_record_dam_ifc2*2));
+ tegra30_ahub_unset_rx_cif_source(TEGRA30_AHUB_RXCIF_DAM0_RX0 +
+ (i2s->call_record_dam_ifc*2));
+ tegra30_ahub_unset_rx_cif_source(i2s->rxcif);
- /* free the dam channels and dam controller */
+ /* free the dam channels and dam controllers */
tegra30_dam_disable_clock(i2s->call_record_dam_ifc);
tegra30_dam_free_channel(i2s->call_record_dam_ifc,
- TEGRA30_DAM_CHIN1);
+ TEGRA30_DAM_CHIN1);
tegra30_dam_free_channel(i2s->call_record_dam_ifc,
- TEGRA30_DAM_CHIN0_SRC);
+ TEGRA30_DAM_CHIN0_SRC);
tegra30_dam_free_controller(i2s->call_record_dam_ifc);
+
+ tegra30_dam_disable_clock(i2s->call_record_dam_ifc2);
+ tegra30_dam_free_channel(i2s->call_record_dam_ifc2,
+ TEGRA30_DAM_CHIN1);
+ tegra30_dam_free_channel(i2s->call_record_dam_ifc2,
+ TEGRA30_DAM_CHIN0_SRC);
+ tegra30_dam_free_controller(i2s->call_record_dam_ifc2);
}
return;
@@ -1067,10 +1106,6 @@ static int tegra_aic326x_init(struct snd_soc_pcm_runtime *rtd)
i2s->is_dam_used = true;
#endif
- if ((i2s->id == machine->codec_info[HIFI_CODEC].i2s_id) &&
- (i2s->id != machine->codec_info[VOICE_CODEC].i2s_id))
- i2s->is_dam_used = false;
-
if (machine->init_done)
return 0;