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;
|
struct nvaudio_ivc_ctxt *hivc_client;
|
||||||
uint32_t fe_to_admaif_map[ADSP_FE_END - ADSP_FE_START + 1][2];
|
uint32_t fe_to_admaif_map[ADSP_FE_END - ADSP_FE_START + 1][2];
|
||||||
struct tegra210_adsp_switch switches[MAX_ADSP_SWITCHES];
|
struct tegra210_adsp_switch switches[MAX_ADSP_SWITCHES];
|
||||||
|
bool is_fe_set[ADSP_FE_COUNT];
|
||||||
spinlock_t switch_lock;
|
spinlock_t switch_lock;
|
||||||
#endif
|
#endif
|
||||||
};
|
};
|
||||||
@@ -2332,7 +2333,26 @@ static int tegra210_adsp_fe_hw_params(struct snd_pcm_substream *substream,
|
|||||||
|
|
||||||
return 0;
|
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,
|
static int tegra210_adsp_null_sink_hw_params(struct snd_soc_dapm_widget *w,
|
||||||
struct snd_kcontrol *kcontrol, int event) {
|
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 tegra210_adsp_pcm_rtd *prtd = NULL;
|
||||||
struct snd_pcm_runtime *runtime = NULL;
|
struct snd_pcm_runtime *runtime = NULL;
|
||||||
uint32_t channels = 2, format = SNDRV_PCM_FORMAT_S16_LE, rate = 48000;
|
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;
|
int ret, num_params;
|
||||||
apm_msg_t apm_msg;
|
apm_msg_t apm_msg;
|
||||||
#ifdef CONFIG_SND_SOC_TEGRA_VIRT_IVC_COMM
|
#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));
|
memset(&adma_params, 0, sizeof(adma_params));
|
||||||
adma_params.mode = ADMA_MODE_CONTINUOUS;
|
adma_params.mode = ADMA_MODE_CONTINUOUS;
|
||||||
adma_params.ahub_channel = 0;
|
|
||||||
adma_params.periods = 4;
|
adma_params.periods = 4;
|
||||||
adma_params.adma_ch_page = adsp->adma_ch_page;
|
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] =
|
apm_msg.msg.fx_set_param_params.params[1] =
|
||||||
nvfx_adma_set_null_sink_mode;
|
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) {
|
if (event == SND_SOC_DAPM_POST_PMD) {
|
||||||
#ifdef CONFIG_SND_SOC_TEGRA_VIRT_IVC_COMM
|
#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]
|
admaif_id = adsp->fe_to_admaif_map[ret - 1]
|
||||||
[SNDRV_PCM_STREAM_PLAYBACK];
|
[SNDRV_PCM_STREAM_PLAYBACK];
|
||||||
if (admaif_id) {
|
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);
|
SNDRV_PCM_STREAM_CAPTURE);
|
||||||
|
adsp->is_fe_set[ret - 1] = false;
|
||||||
spin_unlock_irqrestore(&adsp->switch_lock, flags);
|
spin_unlock_irqrestore(&adsp->switch_lock, flags);
|
||||||
tegra_ivc_stop_playback(adsp, admaif_id - 1, true);
|
tegra_ivc_stop_playback(adsp, admaif_id - 1, true);
|
||||||
return 0;
|
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;
|
apm_msg.msg.fx_set_param_params.params[2] = 0;
|
||||||
} else
|
} else
|
||||||
/* set adma in drain mode */
|
/* 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);
|
ret = pm_runtime_get_sync(adsp->dev);
|
||||||
if (ret < 0) {
|
if (ret < 0) {
|
||||||
@@ -2461,10 +2485,20 @@ static int tegra210_adsp_null_sink_hw_params(struct snd_soc_dapm_widget *w,
|
|||||||
__func__, ret);
|
__func__, ret);
|
||||||
return 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,
|
ret = tegra210_adsp_send_msg(app, &apm_msg,
|
||||||
TEGRA210_ADSP_MSG_FLAG_SEND |
|
TEGRA210_ADSP_MSG_FLAG_SEND);
|
||||||
TEGRA210_ADSP_MSG_FLAG_NEED_ACK);
|
|
||||||
|
|
||||||
if (ret < 0) {
|
if (ret < 0) {
|
||||||
dev_vdbg(adsp->dev, "apm null-sink msg failed.%d\n", ret);
|
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);
|
pm_runtime_put(adsp->dev);
|
||||||
|
|
||||||
#ifdef CONFIG_SND_SOC_TEGRA_VIRT_IVC_COMM
|
#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
|
#endif
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@@ -4111,7 +4146,10 @@ stop_playback:
|
|||||||
/* skip if fe is active but playback has finished */
|
/* skip if fe is active but playback has finished */
|
||||||
spin_lock_irqsave(&adsp->switch_lock, flags);
|
spin_lock_irqsave(&adsp->switch_lock, flags);
|
||||||
if ((adsp->fe_to_admaif_map[sch->active_fe - 1]
|
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);
|
spin_unlock_irqrestore(&adsp->switch_lock, flags);
|
||||||
goto start_playback;
|
goto start_playback;
|
||||||
}
|
}
|
||||||
@@ -4122,6 +4160,7 @@ stop_playback:
|
|||||||
spin_unlock_irqrestore(&adsp->switch_lock, flags);
|
spin_unlock_irqrestore(&adsp->switch_lock, flags);
|
||||||
|
|
||||||
tegra_ivc_stop_playback(adsp, admaif_id - 1, true);
|
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,
|
curr_adma_id = tegra_adsp_get_connected_adma(adsp,
|
||||||
sch->active_fe);
|
sch->active_fe);
|
||||||
app_curr = &adsp->apps[curr_adma_id];
|
app_curr = &adsp->apps[curr_adma_id];
|
||||||
@@ -4190,7 +4229,7 @@ start_playback:
|
|||||||
TEGRA210_ADSP_MSG_FLAG_SEND | TEGRA210_ADSP_MSG_FLAG_NEED_ACK);
|
TEGRA210_ADSP_MSG_FLAG_SEND | TEGRA210_ADSP_MSG_FLAG_NEED_ACK);
|
||||||
pm_runtime_put(adsp->dev);
|
pm_runtime_put(adsp->dev);
|
||||||
sch->active_fe = fe_reg;
|
sch->active_fe = fe_reg;
|
||||||
|
adsp->is_fe_set[sch->active_fe - 1] = true;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
Reference in New Issue
Block a user