diff options
Diffstat (limited to 'cs40l26/cs40l26.c')
-rw-r--r-- | cs40l26/cs40l26.c | 29 |
1 files changed, 28 insertions, 1 deletions
diff --git a/cs40l26/cs40l26.c b/cs40l26/cs40l26.c index 93fe669..39f5253 100644 --- a/cs40l26/cs40l26.c +++ b/cs40l26/cs40l26.c @@ -708,6 +708,7 @@ static int cs40l26_handle_mbox_buffer(struct cs40l26_private *cs40l26) switch (val) { case CS40L26_DSP_MBOX_COMPLETE_MBOX: dev_dbg(dev, "Mailbox: COMPLETE_MBOX\n"); + complete_all(&cs40l26->erase_cont); cs40l26_vibe_state_update(cs40l26, CS40L26_VIBE_STATE_EVENT_MBOX_COMPLETE); break; @@ -1943,6 +1944,8 @@ static void cs40l26_vibe_start_worker(struct work_struct *work) if (!cs40l26->vibe_state_reporting) cs40l26_vibe_state_update(cs40l26, CS40L26_VIBE_STATE_EVENT_MBOX_PLAYBACK); + + reinit_completion(&cs40l26->erase_cont); err_mutex: mutex_unlock(&cs40l26->lock); pm_runtime_mark_last_busy(dev); @@ -2428,7 +2431,12 @@ static int cs40l26_refactor_owt(struct cs40l26_private *cs40l26, s16 *in_data, ch = cl_dsp_memchunk_create((void *) in_data, in_data_bytes); cl_dsp_memchunk_read(&ch, 8); /* Skip padding */ - nsections = cl_dsp_memchunk_read(&ch, 8); + ret = cl_dsp_memchunk_read(&ch, 8); + if (ret < 0) + return ret; + + nsections = ret; + global_rep = cl_dsp_memchunk_read(&ch, 8); sections = kcalloc(nsections, sizeof(struct cs40l26_owt_section), @@ -2957,6 +2965,7 @@ static void cs40l26_erase_worker(struct work_struct *work) struct cs40l26_private, erase_work); int ret = 0; int effect_id; + u16 duration; u32 index; ret = pm_runtime_get_sync(cs40l26->dev); @@ -2967,6 +2976,22 @@ static void cs40l26_erase_worker(struct work_struct *work) effect_id = cs40l26->erase_effect->id; index = cs40l26->trigger_indices[effect_id]; + duration = (cs40l26->erase_effect->replay.length == 0) ? + CS40L26_MAX_WAIT_VIBE_COMPLETE_MS : + cs40l26->erase_effect->replay.length + CS40L26_ERASE_BUFFER_MS; + + /* Check for ongoing effect playback. */ + if (cs40l26->vibe_state == CS40L26_VIBE_STATE_HAPTIC) { + /* Wait for effect to complete. */ + mutex_unlock(&cs40l26->lock); + if (!wait_for_completion_timeout(&cs40l26->erase_cont, + msecs_to_jiffies(duration))) { + ret = -ETIME; + dev_err(cs40l26->dev, "Failed to erase effect: %d", ret); + goto pm_err; + } + mutex_lock(&cs40l26->lock); + } dev_dbg(cs40l26->dev, "%s: effect ID = %d\n", __func__, effect_id); @@ -2992,6 +3017,7 @@ static void cs40l26_erase_worker(struct work_struct *work) out_mutex: mutex_unlock(&cs40l26->lock); +pm_err: pm_runtime_mark_last_busy(cs40l26->dev); pm_runtime_put_autosuspend(cs40l26->dev); @@ -4798,6 +4824,7 @@ int cs40l26_probe(struct cs40l26_private *cs40l26, cs40l26->pm_ready = false; init_completion(&cs40l26->i2s_cont); + init_completion(&cs40l26->erase_cont); if (!cs40l26->fw_defer) { ret = cs40l26_fw_upload(cs40l26); |