mirror of
git://nv-tegra.nvidia.com/linux-nv-oot.git
synced 2025-12-22 09:11:26 +03:00
ASoC: allow switch to set source before playback
For switch currently we rely on setting switch source after playback has started in null-sink mode. However this will leads to missing few frames of intial data. Thus change adds support to allow setting source to switch before playback is started. Jira EMA-528 Change-Id: I2301da6d8b256bb188a8c442058bd87cac5a48ca Signed-off-by: Dipesh Gandhi <dipeshg@nvidia.com> Reviewed-on: https://git-master.nvidia.com/r/1517265 Signed-off-by: Sameer Pujar <spujar@nvidia.com> (cherry picked from commit 313c392daeeb84a12a01b1befc47ab1826c2126e) Reviewed-on: https://git-master.nvidia.com/r/1533084 Reviewed-by: mobile promotions <svcmobile_promotions@nvidia.com> Tested-by: mobile promotions <svcmobile_promotions@nvidia.com>
This commit is contained in:
committed by
Sameer Pujar
parent
d772f9ce82
commit
a22ea5aac7
@@ -185,6 +185,7 @@ struct tegra210_adsp {
|
||||
struct nvaudio_ivc_ctxt *hivc_client;
|
||||
uint32_t fe_to_admaif_map[ADSP_FE_END - ADSP_FE_START + 1][2];
|
||||
struct tegra210_adsp_switch switches[MAX_ADSP_SWITCHES];
|
||||
bool is_fe_set[ADSP_FE_COUNT];
|
||||
spinlock_t switch_lock;
|
||||
#endif
|
||||
};
|
||||
@@ -2332,7 +2333,26 @@ static int tegra210_adsp_fe_hw_params(struct snd_pcm_substream *substream,
|
||||
|
||||
return 0;
|
||||
}
|
||||
#ifdef CONFIG_SND_SOC_TEGRA_VIRT_IVC_COMM
|
||||
static int tegra210_adsp_switch_active_fe(struct tegra210_adsp *adsp,
|
||||
int32_t be_reg)
|
||||
{
|
||||
int ret, i;
|
||||
struct tegra210_adsp_switch *sch = &adsp->switches[0];
|
||||
|
||||
ret = tegra_adsp_get_connected_fe(adsp, be_reg,
|
||||
SNDRV_PCM_STREAM_PLAYBACK);
|
||||
if (ret != ADSP_FE_COUNT) {
|
||||
for (i = 0; i < MAX_ADSP_SWITCHES; i++) {
|
||||
if (sch->active_fe == ret)
|
||||
return sch->admaif_id;
|
||||
sch = &adsp->switches[i+1];
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
|
||||
}
|
||||
#endif
|
||||
static int tegra210_adsp_null_sink_hw_params(struct snd_soc_dapm_widget *w,
|
||||
struct snd_kcontrol *kcontrol, int event) {
|
||||
|
||||
@@ -2343,7 +2363,7 @@ static int tegra210_adsp_null_sink_hw_params(struct snd_soc_dapm_widget *w,
|
||||
struct tegra210_adsp_pcm_rtd *prtd = NULL;
|
||||
struct snd_pcm_runtime *runtime = NULL;
|
||||
uint32_t channels = 2, format = SNDRV_PCM_FORMAT_S16_LE, rate = 48000;
|
||||
int32_t source, be_reg = w->reg, apm_in_reg;
|
||||
int32_t source, be_reg = w->reg, apm_in_reg, ahub_chan = 0;
|
||||
int ret, num_params;
|
||||
apm_msg_t apm_msg;
|
||||
#ifdef CONFIG_SND_SOC_TEGRA_VIRT_IVC_COMM
|
||||
@@ -2357,7 +2377,6 @@ static int tegra210_adsp_null_sink_hw_params(struct snd_soc_dapm_widget *w,
|
||||
|
||||
memset(&adma_params, 0, sizeof(adma_params));
|
||||
adma_params.mode = ADMA_MODE_CONTINUOUS;
|
||||
adma_params.ahub_channel = 0;
|
||||
adma_params.periods = 4;
|
||||
adma_params.adma_ch_page = adsp->adma_ch_page;
|
||||
|
||||
@@ -2432,6 +2451,10 @@ static int tegra210_adsp_null_sink_hw_params(struct snd_soc_dapm_widget *w,
|
||||
|
||||
apm_msg.msg.fx_set_param_params.params[1] =
|
||||
nvfx_adma_set_null_sink_mode;
|
||||
#ifdef CONFIG_SND_SOC_TEGRA_VIRT_IVC_COMM
|
||||
ahub_chan = tegra210_adsp_switch_active_fe(adsp, be_reg);
|
||||
#endif
|
||||
adma_params.ahub_channel = ahub_chan;
|
||||
|
||||
if (event == SND_SOC_DAPM_POST_PMD) {
|
||||
#ifdef CONFIG_SND_SOC_TEGRA_VIRT_IVC_COMM
|
||||
@@ -2441,8 +2464,9 @@ static int tegra210_adsp_null_sink_hw_params(struct snd_soc_dapm_widget *w,
|
||||
admaif_id = adsp->fe_to_admaif_map[ret - 1]
|
||||
[SNDRV_PCM_STREAM_PLAYBACK];
|
||||
if (admaif_id) {
|
||||
tegra_adsp_set_admaif_id(adsp, 0, be_reg,
|
||||
tegra_adsp_set_admaif_id(adsp, admaif_id, be_reg,
|
||||
SNDRV_PCM_STREAM_CAPTURE);
|
||||
adsp->is_fe_set[ret - 1] = false;
|
||||
spin_unlock_irqrestore(&adsp->switch_lock, flags);
|
||||
tegra_ivc_stop_playback(adsp, admaif_id - 1, true);
|
||||
return 0;
|
||||
@@ -2453,7 +2477,7 @@ static int tegra210_adsp_null_sink_hw_params(struct snd_soc_dapm_widget *w,
|
||||
apm_msg.msg.fx_set_param_params.params[2] = 0;
|
||||
} else
|
||||
/* set adma in drain mode */
|
||||
apm_msg.msg.fx_set_param_params.params[2] = 1;
|
||||
apm_msg.msg.fx_set_param_params.params[2] = ahub_chan ? 0 : 1;
|
||||
|
||||
ret = pm_runtime_get_sync(adsp->dev);
|
||||
if (ret < 0) {
|
||||
@@ -2461,10 +2485,20 @@ static int tegra210_adsp_null_sink_hw_params(struct snd_soc_dapm_widget *w,
|
||||
__func__, ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_SND_SOC_TEGRA_VIRT_IVC_COMM
|
||||
if (ahub_chan) {
|
||||
tegra210_adsp_admaif_hv_hw_params(adsp, NULL, ahub_chan,
|
||||
be_reg, &adma_params, SNDRV_PCM_STREAM_CAPTURE);
|
||||
ret = tegra_adsp_get_connected_fe(adsp, be_reg,
|
||||
SNDRV_PCM_STREAM_PLAYBACK);
|
||||
if (!adsp->is_fe_set[ret - 1]) {
|
||||
tegra_ivc_start_playback(adsp, ahub_chan - 1, true);
|
||||
adsp->is_fe_set[ret - 1] = true;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
ret = tegra210_adsp_send_msg(app, &apm_msg,
|
||||
TEGRA210_ADSP_MSG_FLAG_SEND |
|
||||
TEGRA210_ADSP_MSG_FLAG_NEED_ACK);
|
||||
TEGRA210_ADSP_MSG_FLAG_SEND);
|
||||
|
||||
if (ret < 0) {
|
||||
dev_vdbg(adsp->dev, "apm null-sink msg failed.%d\n", ret);
|
||||
@@ -2487,7 +2521,8 @@ static int tegra210_adsp_null_sink_hw_params(struct snd_soc_dapm_widget *w,
|
||||
pm_runtime_put(adsp->dev);
|
||||
|
||||
#ifdef CONFIG_SND_SOC_TEGRA_VIRT_IVC_COMM
|
||||
tegra_adsp_set_admaif_id(adsp, 0, be_reg, SNDRV_PCM_STREAM_CAPTURE);
|
||||
tegra_adsp_set_admaif_id(adsp, ahub_chan, be_reg,
|
||||
SNDRV_PCM_STREAM_CAPTURE);
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
@@ -4111,7 +4146,10 @@ stop_playback:
|
||||
/* skip if fe is active but playback has finished */
|
||||
spin_lock_irqsave(&adsp->switch_lock, flags);
|
||||
if ((adsp->fe_to_admaif_map[sch->active_fe - 1]
|
||||
[SNDRV_PCM_STREAM_PLAYBACK]) == 0) {
|
||||
[SNDRV_PCM_STREAM_PLAYBACK]) == 0 ||
|
||||
!adsp->is_fe_set[sch->active_fe - 1]) {
|
||||
tegra_adsp_set_admaif_id(adsp,
|
||||
0, active_be_reg, SNDRV_PCM_STREAM_CAPTURE);
|
||||
spin_unlock_irqrestore(&adsp->switch_lock, flags);
|
||||
goto start_playback;
|
||||
}
|
||||
@@ -4122,6 +4160,7 @@ stop_playback:
|
||||
spin_unlock_irqrestore(&adsp->switch_lock, flags);
|
||||
|
||||
tegra_ivc_stop_playback(adsp, admaif_id - 1, true);
|
||||
adsp->is_fe_set[sch->active_fe - 1] = false;
|
||||
curr_adma_id = tegra_adsp_get_connected_adma(adsp,
|
||||
sch->active_fe);
|
||||
app_curr = &adsp->apps[curr_adma_id];
|
||||
@@ -4190,7 +4229,7 @@ start_playback:
|
||||
TEGRA210_ADSP_MSG_FLAG_SEND | TEGRA210_ADSP_MSG_FLAG_NEED_ACK);
|
||||
pm_runtime_put(adsp->dev);
|
||||
sch->active_fe = fe_reg;
|
||||
|
||||
adsp->is_fe_set[sch->active_fe - 1] = true;
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
Reference in New Issue
Block a user