summaryrefslogtreecommitdiff
path: root/cs40l26/cs40l26.c
diff options
context:
space:
mode:
authorTai Kuo <taikuo@google.com>2022-06-24 16:03:34 +0800
committerTai Kuo <taikuo@google.com>2022-07-25 16:44:35 +0800
commit9b64f6ac24f3f18744a1274aef372b156335c890 (patch)
tree6e25751fbac21376c8b977e2ce5a1f89a0a97281 /cs40l26/cs40l26.c
parent23fd0fffc5ae321966831865e08e106574e11ef9 (diff)
downloadamplifiers-9b64f6ac24f3f18744a1274aef372b156335c890.tar.gz
cs40l26: merge cs40l26 v5.3.0
Branch: v5.10-cs40l26 Tag: cs40l26-v5.3.0_5.10 Files: drivers/input/misc/cs40l26-i2c.c (No changes) drivers/input/misc/cs40l26-spi.c (No changes) drivers/input/misc/cs40l26-sysfs.c (No changes) drivers/input/misc/cs40l26-tables.c (No changes) drivers/input/misc/cs40l26.c include/linux/mfd/cs40l26.h sound/soc/codecs/cs40l26.c -> cs40l26-codec.c (No changes) Features: - Support for maintenance firmware revisions dating back to Rev. 39.2.22 Bug fixes: - Disallow erase call if a haptic effect is in-flight. This allows the driver maintain correct number of loaded effects when firmware fails to delete waveform if the delete is attempted when haptics playback is active. - Minor code update to handle potential failure of memchunk read from CL DSP FW driver. Commits: 6e36db4 input: cs40l26: Rollback minimum fw revision for maintenance fw 77a5ce5 input: cs40l26: Handle memchunk read failure 20efcc3 input: cs40l26: Ensure effect to be erased is not in-flight Bug: 237047104 Test: Copy texts and adjust alarm Test: NFC, dumpstate, keyboard vibration Test: idlcli commands Test: Switch firmware continuous Test: Switch firmware and check the first tick effect Test: atest VtsHalVibratorManagerTargetTest \ VtsHalVibratorTargetTest \ android.os.cts.VibratorTest \ android.os.cts.VibratorManagerTest \ android.os.cts.VibrationEffectTest \ android.os.cts.VibrationAttributesTest \ android.os.cts.CombinedVibrationTest Signed-off-by: Tai Kuo <taikuo@google.com> Change-Id: Iad33742ad694ea9ed5987dc617e64fca0044f7c7
Diffstat (limited to 'cs40l26/cs40l26.c')
-rw-r--r--cs40l26/cs40l26.c29
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);