ASoC: msm: qdsp6v2: Fix gapless session open fail
During gapless playback, next track open write command is triggered to DSP. At the same time, for current track, volume change or some PP command is triggered to DSP. Due to race condition, the track open write fails since the second command is triggered asynchronously. Use separate cmd state for PP command to handle this. CRs-Fixed: 1080766 Change-Id: Ia80766394e4933800b72be2bf3296cd5de4e3159 Signed-off-by: Laxminath Kasam <lkasam@codeaurora.org>
This commit is contained in:
parent
6137652043
commit
671fae0fce
2 changed files with 71 additions and 53 deletions
|
@ -209,6 +209,7 @@ struct audio_client {
|
|||
int session;
|
||||
app_cb cb;
|
||||
atomic_t cmd_state;
|
||||
atomic_t cmd_state_pp;
|
||||
/* Relative or absolute TS */
|
||||
atomic_t time_flag;
|
||||
atomic_t nowait_cmd_cnt;
|
||||
|
|
|
@ -1167,6 +1167,7 @@ struct audio_client *q6asm_audio_client_alloc(app_cb cb, void *priv)
|
|||
spin_lock_init(&ac->port[lcnt].dsp_lock);
|
||||
}
|
||||
atomic_set(&ac->cmd_state, 0);
|
||||
atomic_set(&ac->cmd_state_pp, 0);
|
||||
atomic_set(&ac->mem_state, 0);
|
||||
|
||||
rc = send_asm_custom_topology(ac);
|
||||
|
@ -1659,6 +1660,7 @@ static int32_t q6asm_callback(struct apr_client_data *data, void *priv)
|
|||
atomic_set(&ac->time_flag, 0);
|
||||
atomic_set(&ac->cmd_state, 0);
|
||||
atomic_set(&ac->mem_state, 0);
|
||||
atomic_set(&ac->cmd_state_pp, 0);
|
||||
wake_up(&ac->time_wait);
|
||||
wake_up(&ac->cmd_wait);
|
||||
wake_up(&ac->mem_wait);
|
||||
|
@ -1725,14 +1727,29 @@ static int32_t q6asm_callback(struct apr_client_data *data, void *priv)
|
|||
pr_err("%s: cmd = 0x%x returned error = 0x%x\n",
|
||||
__func__, payload[0], payload[1]);
|
||||
if (wakeup_flag) {
|
||||
atomic_set(&ac->cmd_state, payload[1]);
|
||||
if (payload[0] ==
|
||||
ASM_STREAM_CMD_SET_PP_PARAMS_V2)
|
||||
atomic_set(&ac->cmd_state_pp,
|
||||
payload[1]);
|
||||
else
|
||||
atomic_set(&ac->cmd_state,
|
||||
payload[1]);
|
||||
wake_up(&ac->cmd_wait);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
if (atomic_read(&ac->cmd_state) && wakeup_flag) {
|
||||
atomic_set(&ac->cmd_state, 0);
|
||||
wake_up(&ac->cmd_wait);
|
||||
if (payload[0] == ASM_STREAM_CMD_SET_PP_PARAMS_V2) {
|
||||
if (atomic_read(&ac->cmd_state_pp) &&
|
||||
wakeup_flag) {
|
||||
atomic_set(&ac->cmd_state_pp, 0);
|
||||
wake_up(&ac->cmd_wait);
|
||||
}
|
||||
} else {
|
||||
if (atomic_read(&ac->cmd_state) &&
|
||||
wakeup_flag) {
|
||||
atomic_set(&ac->cmd_state, 0);
|
||||
wake_up(&ac->cmd_wait);
|
||||
}
|
||||
}
|
||||
if (ac->cb)
|
||||
ac->cb(data->opcode, data->token,
|
||||
|
@ -6239,7 +6256,7 @@ int q6asm_set_lrgain(struct audio_client *ac, int left_gain, int right_gain)
|
|||
memset(&multi_ch_gain, 0, sizeof(multi_ch_gain));
|
||||
sz = sizeof(struct asm_volume_ctrl_multichannel_gain);
|
||||
q6asm_add_hdr_async(ac, &multi_ch_gain.hdr, sz, TRUE);
|
||||
atomic_set(&ac->cmd_state, -1);
|
||||
atomic_set(&ac->cmd_state_pp, -1);
|
||||
multi_ch_gain.hdr.opcode = ASM_STREAM_CMD_SET_PP_PARAMS_V2;
|
||||
multi_ch_gain.param.data_payload_addr_lsw = 0;
|
||||
multi_ch_gain.param.data_payload_addr_msw = 0;
|
||||
|
@ -6265,20 +6282,20 @@ int q6asm_set_lrgain(struct audio_client *ac, int left_gain, int right_gain)
|
|||
}
|
||||
|
||||
rc = wait_event_timeout(ac->cmd_wait,
|
||||
(atomic_read(&ac->cmd_state) >= 0), 5*HZ);
|
||||
(atomic_read(&ac->cmd_state_pp) >= 0), 5*HZ);
|
||||
if (!rc) {
|
||||
pr_err("%s: timeout, set-params paramid[0x%x]\n", __func__,
|
||||
multi_ch_gain.data.param_id);
|
||||
rc = -ETIMEDOUT;
|
||||
goto fail_cmd;
|
||||
}
|
||||
if (atomic_read(&ac->cmd_state) > 0) {
|
||||
if (atomic_read(&ac->cmd_state_pp) > 0) {
|
||||
pr_err("%s: DSP returned error[%s] , set-params paramid[0x%x]\n",
|
||||
__func__, adsp_err_get_err_str(
|
||||
atomic_read(&ac->cmd_state)),
|
||||
atomic_read(&ac->cmd_state_pp)),
|
||||
multi_ch_gain.data.param_id);
|
||||
rc = adsp_err_get_lnx_err_code(
|
||||
atomic_read(&ac->cmd_state));
|
||||
atomic_read(&ac->cmd_state_pp));
|
||||
goto fail_cmd;
|
||||
}
|
||||
rc = 0;
|
||||
|
@ -6333,7 +6350,7 @@ int q6asm_set_multich_gain(struct audio_client *ac, uint32_t channels,
|
|||
memset(&multich_gain, 0, sizeof(multich_gain));
|
||||
sz = sizeof(struct asm_volume_ctrl_multichannel_gain);
|
||||
q6asm_add_hdr_async(ac, &multich_gain.hdr, sz, TRUE);
|
||||
atomic_set(&ac->cmd_state, 1);
|
||||
atomic_set(&ac->cmd_state_pp, -1);
|
||||
multich_gain.hdr.opcode = ASM_STREAM_CMD_SET_PP_PARAMS_V2;
|
||||
multich_gain.param.data_payload_addr_lsw = 0;
|
||||
multich_gain.param.data_payload_addr_msw = 0;
|
||||
|
@ -6371,17 +6388,17 @@ int q6asm_set_multich_gain(struct audio_client *ac, uint32_t channels,
|
|||
}
|
||||
|
||||
rc = wait_event_timeout(ac->cmd_wait,
|
||||
(atomic_read(&ac->cmd_state) <= 0), 5*HZ);
|
||||
(atomic_read(&ac->cmd_state_pp) >= 0), 5*HZ);
|
||||
if (!rc) {
|
||||
pr_err("%s: timeout, set-params paramid[0x%x]\n", __func__,
|
||||
multich_gain.data.param_id);
|
||||
rc = -EINVAL;
|
||||
goto done;
|
||||
}
|
||||
if (atomic_read(&ac->cmd_state) < 0) {
|
||||
if (atomic_read(&ac->cmd_state_pp) > 0) {
|
||||
pr_err("%s: DSP returned error[%d] , set-params paramid[0x%x]\n",
|
||||
__func__, atomic_read(&ac->cmd_state),
|
||||
multich_gain.data.param_id);
|
||||
__func__, atomic_read(&ac->cmd_state_pp),
|
||||
multich_gain.data.param_id);
|
||||
rc = -EINVAL;
|
||||
goto done;
|
||||
}
|
||||
|
@ -6409,7 +6426,7 @@ int q6asm_set_mute(struct audio_client *ac, int muteflag)
|
|||
|
||||
sz = sizeof(struct asm_volume_ctrl_mute_config);
|
||||
q6asm_add_hdr_async(ac, &mute.hdr, sz, TRUE);
|
||||
atomic_set(&ac->cmd_state, -1);
|
||||
atomic_set(&ac->cmd_state_pp, -1);
|
||||
mute.hdr.opcode = ASM_STREAM_CMD_SET_PP_PARAMS_V2;
|
||||
mute.param.data_payload_addr_lsw = 0;
|
||||
mute.param.data_payload_addr_msw = 0;
|
||||
|
@ -6431,20 +6448,20 @@ int q6asm_set_mute(struct audio_client *ac, int muteflag)
|
|||
}
|
||||
|
||||
rc = wait_event_timeout(ac->cmd_wait,
|
||||
(atomic_read(&ac->cmd_state) >= 0), 5*HZ);
|
||||
(atomic_read(&ac->cmd_state_pp) >= 0), 5*HZ);
|
||||
if (!rc) {
|
||||
pr_err("%s: timeout, set-params paramid[0x%x]\n", __func__,
|
||||
mute.data.param_id);
|
||||
rc = -ETIMEDOUT;
|
||||
goto fail_cmd;
|
||||
}
|
||||
if (atomic_read(&ac->cmd_state) > 0) {
|
||||
if (atomic_read(&ac->cmd_state_pp) > 0) {
|
||||
pr_err("%s: DSP returned error[%s] set-params paramid[0x%x]\n",
|
||||
__func__, adsp_err_get_err_str(
|
||||
atomic_read(&ac->cmd_state)),
|
||||
atomic_read(&ac->cmd_state_pp)),
|
||||
mute.data.param_id);
|
||||
rc = adsp_err_get_lnx_err_code(
|
||||
atomic_read(&ac->cmd_state));
|
||||
atomic_read(&ac->cmd_state_pp));
|
||||
goto fail_cmd;
|
||||
}
|
||||
rc = 0;
|
||||
|
@ -6485,7 +6502,7 @@ int q6asm_dts_eagle_set(struct audio_client *ac, int param_id, uint32_t size,
|
|||
ad->data.param_id = param_id;
|
||||
ad->data.param_size = size;
|
||||
ad->data.reserved = 0;
|
||||
atomic_set(&ac->cmd_state, -1);
|
||||
atomic_set(&ac->cmd_state_pp, -1);
|
||||
|
||||
if (po) {
|
||||
struct list_head *ptr, *next;
|
||||
|
@ -6536,7 +6553,7 @@ int q6asm_dts_eagle_set(struct audio_client *ac, int param_id, uint32_t size,
|
|||
}
|
||||
|
||||
rc = wait_event_timeout(ac->cmd_wait,
|
||||
(atomic_read(&ac->cmd_state) >= 0), 1*HZ);
|
||||
(atomic_read(&ac->cmd_state_pp) >= 0), 1*HZ);
|
||||
if (!rc) {
|
||||
pr_err("DTS_EAGLE_ASM - %s: timeout, set-params paramid[0x%x]\n",
|
||||
__func__, ad->data.param_id);
|
||||
|
@ -6544,12 +6561,12 @@ int q6asm_dts_eagle_set(struct audio_client *ac, int param_id, uint32_t size,
|
|||
goto fail_cmd;
|
||||
}
|
||||
|
||||
if (atomic_read(&ac->cmd_state) > 0) {
|
||||
if (atomic_read(&ac->cmd_state_pp) > 0) {
|
||||
pr_err("%s: DSP returned error[%s]\n",
|
||||
__func__, adsp_err_get_err_str(
|
||||
atomic_read(&ac->cmd_state)));
|
||||
atomic_read(&ac->cmd_state_pp)));
|
||||
rc = adsp_err_get_lnx_err_code(
|
||||
atomic_read(&ac->cmd_state));
|
||||
atomic_read(&ac->cmd_state_pp));
|
||||
goto fail_cmd;
|
||||
}
|
||||
rc = 0;
|
||||
|
@ -6709,7 +6726,7 @@ static int __q6asm_set_volume(struct audio_client *ac, int volume, int instance)
|
|||
|
||||
sz = sizeof(struct asm_volume_ctrl_master_gain);
|
||||
q6asm_add_hdr_async(ac, &vol.hdr, sz, TRUE);
|
||||
atomic_set(&ac->cmd_state, -1);
|
||||
atomic_set(&ac->cmd_state_pp, -1);
|
||||
vol.hdr.opcode = ASM_STREAM_CMD_SET_PP_PARAMS_V2;
|
||||
vol.param.data_payload_addr_lsw = 0;
|
||||
vol.param.data_payload_addr_msw = 0;
|
||||
|
@ -6731,20 +6748,20 @@ static int __q6asm_set_volume(struct audio_client *ac, int volume, int instance)
|
|||
}
|
||||
|
||||
rc = wait_event_timeout(ac->cmd_wait,
|
||||
(atomic_read(&ac->cmd_state) >= 0), 5*HZ);
|
||||
(atomic_read(&ac->cmd_state_pp) >= 0), 5*HZ);
|
||||
if (!rc) {
|
||||
pr_err("%s: timeout, set-params paramid[0x%x]\n", __func__,
|
||||
vol.data.param_id);
|
||||
rc = -ETIMEDOUT;
|
||||
goto fail_cmd;
|
||||
}
|
||||
if (atomic_read(&ac->cmd_state) > 0) {
|
||||
if (atomic_read(&ac->cmd_state_pp) > 0) {
|
||||
pr_err("%s: DSP returned error[%s] set-params paramid[0x%x]\n",
|
||||
__func__, adsp_err_get_err_str(
|
||||
atomic_read(&ac->cmd_state)),
|
||||
atomic_read(&ac->cmd_state_pp)),
|
||||
vol.data.param_id);
|
||||
rc = adsp_err_get_lnx_err_code(
|
||||
atomic_read(&ac->cmd_state));
|
||||
atomic_read(&ac->cmd_state_pp));
|
||||
goto fail_cmd;
|
||||
}
|
||||
|
||||
|
@ -6783,7 +6800,7 @@ int q6asm_set_softpause(struct audio_client *ac,
|
|||
|
||||
sz = sizeof(struct asm_soft_pause_params);
|
||||
q6asm_add_hdr_async(ac, &softpause.hdr, sz, TRUE);
|
||||
atomic_set(&ac->cmd_state, -1);
|
||||
atomic_set(&ac->cmd_state_pp, -1);
|
||||
softpause.hdr.opcode = ASM_STREAM_CMD_SET_PP_PARAMS_V2;
|
||||
|
||||
softpause.param.data_payload_addr_lsw = 0;
|
||||
|
@ -6810,20 +6827,20 @@ int q6asm_set_softpause(struct audio_client *ac,
|
|||
}
|
||||
|
||||
rc = wait_event_timeout(ac->cmd_wait,
|
||||
(atomic_read(&ac->cmd_state) >= 0), 5*HZ);
|
||||
(atomic_read(&ac->cmd_state_pp) >= 0), 5*HZ);
|
||||
if (!rc) {
|
||||
pr_err("%s: timeout, set-params paramid[0x%x]\n", __func__,
|
||||
softpause.data.param_id);
|
||||
rc = -ETIMEDOUT;
|
||||
goto fail_cmd;
|
||||
}
|
||||
if (atomic_read(&ac->cmd_state) > 0) {
|
||||
if (atomic_read(&ac->cmd_state_pp) > 0) {
|
||||
pr_err("%s: DSP returned error[%s] set-params paramid[0x%x]\n",
|
||||
__func__, adsp_err_get_err_str(
|
||||
atomic_read(&ac->cmd_state)),
|
||||
atomic_read(&ac->cmd_state_pp)),
|
||||
softpause.data.param_id);
|
||||
rc = adsp_err_get_lnx_err_code(
|
||||
atomic_read(&ac->cmd_state));
|
||||
atomic_read(&ac->cmd_state_pp));
|
||||
goto fail_cmd;
|
||||
}
|
||||
rc = 0;
|
||||
|
@ -6863,7 +6880,7 @@ static int __q6asm_set_softvolume(struct audio_client *ac,
|
|||
|
||||
sz = sizeof(struct asm_soft_step_volume_params);
|
||||
q6asm_add_hdr_async(ac, &softvol.hdr, sz, TRUE);
|
||||
atomic_set(&ac->cmd_state, -1);
|
||||
atomic_set(&ac->cmd_state_pp, -1);
|
||||
softvol.hdr.opcode = ASM_STREAM_CMD_SET_PP_PARAMS_V2;
|
||||
softvol.param.data_payload_addr_lsw = 0;
|
||||
softvol.param.data_payload_addr_msw = 0;
|
||||
|
@ -6888,20 +6905,20 @@ static int __q6asm_set_softvolume(struct audio_client *ac,
|
|||
}
|
||||
|
||||
rc = wait_event_timeout(ac->cmd_wait,
|
||||
(atomic_read(&ac->cmd_state) >= 0), 5*HZ);
|
||||
(atomic_read(&ac->cmd_state_pp) >= 0), 5*HZ);
|
||||
if (!rc) {
|
||||
pr_err("%s: timeout, set-params paramid[0x%x]\n", __func__,
|
||||
softvol.data.param_id);
|
||||
rc = -ETIMEDOUT;
|
||||
goto fail_cmd;
|
||||
}
|
||||
if (atomic_read(&ac->cmd_state) > 0) {
|
||||
if (atomic_read(&ac->cmd_state_pp) > 0) {
|
||||
pr_err("%s: DSP returned error[%s] set-params paramid[0x%x]\n",
|
||||
__func__, adsp_err_get_err_str(
|
||||
atomic_read(&ac->cmd_state)),
|
||||
atomic_read(&ac->cmd_state_pp)),
|
||||
softvol.data.param_id);
|
||||
rc = adsp_err_get_lnx_err_code(
|
||||
atomic_read(&ac->cmd_state));
|
||||
atomic_read(&ac->cmd_state_pp));
|
||||
goto fail_cmd;
|
||||
}
|
||||
rc = 0;
|
||||
|
@ -6950,7 +6967,7 @@ int q6asm_equalizer(struct audio_client *ac, void *eq_p)
|
|||
sz = sizeof(struct asm_eq_params);
|
||||
eq_params = (struct msm_audio_eq_stream_config *) eq_p;
|
||||
q6asm_add_hdr(ac, &eq.hdr, sz, TRUE);
|
||||
atomic_set(&ac->cmd_state, -1);
|
||||
atomic_set(&ac->cmd_state_pp, -1);
|
||||
|
||||
eq.hdr.opcode = ASM_STREAM_CMD_SET_PP_PARAMS_V2;
|
||||
eq.param.data_payload_addr_lsw = 0;
|
||||
|
@ -6995,20 +7012,20 @@ int q6asm_equalizer(struct audio_client *ac, void *eq_p)
|
|||
}
|
||||
|
||||
rc = wait_event_timeout(ac->cmd_wait,
|
||||
(atomic_read(&ac->cmd_state) >= 0), 5*HZ);
|
||||
(atomic_read(&ac->cmd_state_pp) >= 0), 5*HZ);
|
||||
if (!rc) {
|
||||
pr_err("%s: timeout, set-params paramid[0x%x]\n", __func__,
|
||||
eq.data.param_id);
|
||||
rc = -ETIMEDOUT;
|
||||
goto fail_cmd;
|
||||
}
|
||||
if (atomic_read(&ac->cmd_state) > 0) {
|
||||
if (atomic_read(&ac->cmd_state_pp) > 0) {
|
||||
pr_err("%s: DSP returned error[%s] set-params paramid[0x%x]\n",
|
||||
__func__, adsp_err_get_err_str(
|
||||
atomic_read(&ac->cmd_state)),
|
||||
atomic_read(&ac->cmd_state_pp)),
|
||||
eq.data.param_id);
|
||||
rc = adsp_err_get_lnx_err_code(
|
||||
atomic_read(&ac->cmd_state));
|
||||
atomic_read(&ac->cmd_state_pp));
|
||||
goto fail_cmd;
|
||||
}
|
||||
rc = 0;
|
||||
|
@ -7622,7 +7639,7 @@ int q6asm_send_audio_effects_params(struct audio_client *ac, char *params,
|
|||
q6asm_add_hdr_async(ac, &hdr, (sizeof(struct apr_hdr) +
|
||||
sizeof(struct asm_stream_cmd_set_pp_params_v2) +
|
||||
params_length), TRUE);
|
||||
atomic_set(&ac->cmd_state, -1);
|
||||
atomic_set(&ac->cmd_state_pp, -1);
|
||||
hdr.opcode = ASM_STREAM_CMD_SET_PP_PARAMS_V2;
|
||||
payload_params.data_payload_addr_lsw = 0;
|
||||
payload_params.data_payload_addr_msw = 0;
|
||||
|
@ -7641,18 +7658,18 @@ int q6asm_send_audio_effects_params(struct audio_client *ac, char *params,
|
|||
goto fail_send_param;
|
||||
}
|
||||
rc = wait_event_timeout(ac->cmd_wait,
|
||||
(atomic_read(&ac->cmd_state) >= 0), 1*HZ);
|
||||
(atomic_read(&ac->cmd_state_pp) >= 0), 1*HZ);
|
||||
if (!rc) {
|
||||
pr_err("%s: timeout, audio effects set-params\n", __func__);
|
||||
rc = -ETIMEDOUT;
|
||||
goto fail_send_param;
|
||||
}
|
||||
if (atomic_read(&ac->cmd_state) > 0) {
|
||||
if (atomic_read(&ac->cmd_state_pp) > 0) {
|
||||
pr_err("%s: DSP returned error[%s] set-params\n",
|
||||
__func__, adsp_err_get_err_str(
|
||||
atomic_read(&ac->cmd_state)));
|
||||
atomic_read(&ac->cmd_state_pp)));
|
||||
rc = adsp_err_get_lnx_err_code(
|
||||
atomic_read(&ac->cmd_state));
|
||||
atomic_read(&ac->cmd_state_pp));
|
||||
goto fail_send_param;
|
||||
}
|
||||
|
||||
|
@ -8326,7 +8343,7 @@ int q6asm_send_cal(struct audio_client *ac)
|
|||
q6asm_add_hdr_async(ac, &hdr, (sizeof(struct apr_hdr) +
|
||||
sizeof(struct asm_stream_cmd_set_pp_params_v2)), TRUE);
|
||||
|
||||
atomic_set(&ac->cmd_state, -1);
|
||||
atomic_set(&ac->cmd_state_pp, -1);
|
||||
hdr.opcode = ASM_STREAM_CMD_SET_PP_PARAMS_V2;
|
||||
payload_params.data_payload_addr_lsw =
|
||||
lower_32_bits(cal_block->cal_data.paddr);
|
||||
|
@ -8352,15 +8369,15 @@ int q6asm_send_cal(struct audio_client *ac)
|
|||
goto free;
|
||||
}
|
||||
rc = wait_event_timeout(ac->cmd_wait,
|
||||
(atomic_read(&ac->cmd_state) >= 0), 5 * HZ);
|
||||
(atomic_read(&ac->cmd_state_pp) >= 0), 5 * HZ);
|
||||
if (!rc) {
|
||||
pr_err("%s: timeout, audio audstrm cal send\n", __func__);
|
||||
rc = -ETIMEDOUT;
|
||||
goto free;
|
||||
}
|
||||
if (atomic_read(&ac->cmd_state) > 0) {
|
||||
if (atomic_read(&ac->cmd_state_pp) > 0) {
|
||||
pr_err("%s: DSP returned error[%d] audio audstrm cal send\n",
|
||||
__func__, atomic_read(&ac->cmd_state));
|
||||
__func__, atomic_read(&ac->cmd_state_pp));
|
||||
rc = -EINVAL;
|
||||
goto free;
|
||||
}
|
||||
|
|
Loading…
Add table
Reference in a new issue