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:
Laxminath Kasam 2016-10-24 16:38:56 +05:30
parent 6137652043
commit 671fae0fce
2 changed files with 71 additions and 53 deletions

View file

@ -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;

View file

@ -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;
}