summaryrefslogtreecommitdiff
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
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
-rw-r--r--cs40l26/cs40l26.c29
-rw-r--r--cs40l26/cs40l26.h8
2 files changed, 34 insertions, 3 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);
diff --git a/cs40l26/cs40l26.h b/cs40l26/cs40l26.h
index 639c309..d7be94f 100644
--- a/cs40l26/cs40l26.h
+++ b/cs40l26/cs40l26.h
@@ -858,9 +858,9 @@
#define CS40L26_FW_CALIB_ID 0x1800DA
#define CS40L26_FW_CALIB_MIN_REV 0x010014
#define CS40L26_FW_CALIB_BRANCH 0x01
-#define CS40L26_FW_MAINT_MIN_REV 0x27021A
+#define CS40L26_FW_MAINT_MIN_REV 0x270216
#define CS40L26_FW_MAINT_BRANCH 0x27
-#define CS40L26_FW_MAINT_CALIB_MIN_REV 0x210112
+#define CS40L26_FW_MAINT_CALIB_MIN_REV 0x21010D
#define CS40L26_FW_MAINT_CALIB_BRANCH 0x21
#define CS40L26_FW_BRANCH_MASK GENMASK(23, 21)
@@ -927,6 +927,9 @@
#define CS40L26_AMP_VOL_PCM_MAX 0x07FF
+#define CS40L26_ERASE_BUFFER_MS 500
+#define CS40L26_MAX_WAIT_VIBE_COMPLETE_MS 10000
+
/* GPI Triggering */
#define CS40L26_GPIO1 1
#define CS40L26_EVENT_MAP_INDEX_MASK GENMASK(8, 0)
@@ -1513,6 +1516,7 @@ struct cs40l26_private {
bool comp_enable_redc;
bool comp_enable_f0;
struct completion i2s_cont;
+ struct completion erase_cont;
u8 vpbr_thld;
};