summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTai Kuo <taikuo@google.com>2022-10-24 16:10:52 +0800
committerTai Kuo <taikuo@google.com>2022-10-24 16:24:32 +0800
commit472e3d5906cfbf9883bebe764f8b7d31f49fb8e5 (patch)
treee1d5565811778497d83d0a8a7d7d0f1faeeeb489
parenta446aef40c377974eb834f781e1b82562d673a4f (diff)
downloadamplifiers-472e3d5906cfbf9883bebe764f8b7d31f49fb8e5.tar.gz
cs40l26: merge cs40l26 v5.6.3 for firmware RAM18
Merge Cirrus kernel driver (tag cs40l26 v5.6.3) for firmware RAM18 (v7.2.42 (runtime) & v1.1.34 (calib)) Branch: v5.15-cirrus-dsp-fw and v5.15-cs40l26 Tag: cs40l26-v5.6.3_5.15 Files: drivers/firmware/cirrus/cl_dsp.c (No changes) include/linux/firmware/cirrus/cl_dsp.h (No changes) 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: - Set GPI trigger duration during mapping Bug fixes: - Remapped GPI not working Commits: 498efc6 input: cs40l26: Modify handling of GPI mapping c8e0e13 input: cs40l26: Set duration for GPI triggered events Bug: 254810265 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 PtsVibratorHalTestSuite \ PtsHapticsTestCases \ VibratorHalCs40l26TestSuite \ 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: I4e21ceae7ba76559cc4416502e5485fc8fd4509d
-rw-r--r--cs40l26/cs40l26.c136
-rw-r--r--cs40l26/cs40l26.h34
2 files changed, 100 insertions, 70 deletions
diff --git a/cs40l26/cs40l26.c b/cs40l26/cs40l26.c
index 0cbb8e3..86a15d9 100644
--- a/cs40l26/cs40l26.c
+++ b/cs40l26/cs40l26.c
@@ -1709,11 +1709,12 @@ static int cs40l26_buzzgen_set(struct cs40l26_private *cs40l26, u16 freq,
static int cs40l26_map_gpi_to_haptic(struct cs40l26_private *cs40l26,
u32 index, u8 bank, struct ff_effect *effect)
{
- int ret;
- bool edge, ev_handler_bank_ram, owt;
- u32 reg, write_val;
u16 button = effect->trigger.button;
u8 gpio = (button & CS40L26_BTN_NUM_MASK) >> CS40L26_BTN_NUM_SHIFT;
+ bool edge, ev_handler_bank_ram, owt, use_timeout;
+ unsigned int fw_rev;
+ u32 reg, write_val;
+ int ret;
edge = (button & CS40L26_BTN_EDGE_MASK) >> CS40L26_BTN_EDGE_SHIFT;
@@ -1752,9 +1753,38 @@ static int cs40l26_map_gpi_to_haptic(struct cs40l26_private *cs40l26,
return ret;
ret = regmap_write(cs40l26->regmap, reg, write_val);
- if (ret)
+ if (ret) {
dev_err(cs40l26->dev, "Failed to update event map\n");
+ goto pm_exit;
+ }
+
+ ret = cl_dsp_fw_rev_get(cs40l26->dsp, &fw_rev);
+ if (ret)
+ goto pm_exit;
+
+ use_timeout = (!cs40l26->calib_fw &&
+ fw_rev >= CS40L26_FW_GPI_TIMEOUT_MIN_REV) ||
+ (cs40l26->calib_fw && fw_rev >=
+ CS40L26_FW_GPI_TIMEOUT_CALIB_MIN_REV);
+
+ if (use_timeout) {
+ ret = cl_dsp_get_reg(cs40l26->dsp, "TIMEOUT_GPI_MS",
+ CL_DSP_XM_UNPACKED_TYPE,
+ CS40L26_VIBEGEN_ALGO_ID, &reg);
+ if (ret)
+ goto pm_exit;
+
+ ret = regmap_write(cs40l26->regmap, reg, effect->replay.length);
+ if (ret)
+ dev_err(cs40l26->dev, "Failed to set GPI timeout\n");
+ }
+
+ if (edge)
+ cs40l26->gpi_ids[CS40L26_GPIO_MAP_A_PRESS] = effect->id;
+ else
+ cs40l26->gpi_ids[CS40L26_GPIO_MAP_A_RELEASE] = effect->id;
+pm_exit:
cs40l26_pm_exit(cs40l26->dev);
return ret;
@@ -2906,51 +2936,44 @@ const struct attribute_group *cs40l26_dev_attr_groups[] = {
};
#endif
-static int cs40l26_clear_gpi_event_reg(struct cs40l26_private *cs40l26, u32 reg)
+static enum cs40l26_gpio_map cs40l26_map_get(struct cs40l26_private *cs40l26,
+ int effect_id)
{
- struct regmap *regmap = cs40l26->regmap;
- int ret;
-
- ret = regmap_write(regmap, reg, CS40L26_EVENT_MAP_GPI_EVENT_DISABLE);
- if (ret)
- dev_err(cs40l26->dev, "Failed to clear gpi reg: %08X", reg);
+ if (cs40l26->gpi_ids[CS40L26_GPIO_MAP_A_PRESS] == effect_id)
+ return CS40L26_GPIO_MAP_A_PRESS;
+ else if (cs40l26->gpi_ids[CS40L26_GPIO_MAP_A_RELEASE] == effect_id)
+ return CS40L26_GPIO_MAP_A_RELEASE;
- return ret;
+ return CS40L26_GPIO_MAP_INVALID;
}
static int cs40l26_erase_gpi_mapping(struct cs40l26_private *cs40l26,
- int effect_id)
+ enum cs40l26_gpio_map mapping)
{
- struct device *dev = cs40l26->dev;
- u32 index = cs40l26->trigger_indices[effect_id];
- u8 trigger_index, gpi_index;
- u32 reg, val;
- int i, ret;
+ int ret = 0;
+ u32 reg;
+
+ if (mapping == CS40L26_GPIO_MAP_A_PRESS)
+ reg = CS40L26_A1_EVENT_MAP_1;
+ else if (mapping == CS40L26_GPIO_MAP_A_RELEASE)
+ reg = CS40L26_A1_EVENT_MAP_2;
+ else
+ ret = -EINVAL;
- trigger_index = index & 0xFF;
+ if (ret) {
+ dev_err(cs40l26->dev, "Invalid GPI mapping %u\n", mapping);
+ return ret;
+ }
- for (i = 0; i < CS40L26_EVENT_MAP_NUM_GPI_REGS; i++) {
- reg = cs40l26->event_map_base + (i * 4);
- ret = regmap_read(cs40l26->regmap, reg, &val);
- if (ret) {
- dev_err(dev, "Failed to read gpi event reg: 0x%08X",
- reg);
- return ret;
- }
- gpi_index = val & 0xFF;
-
- if (is_buzz(index) ||
- (is_owt(index) && val & CS40L26_BTN_OWT_MASK) ||
- (is_ram(index) && val & CS40L26_BTN_BANK_MASK) ||
- (is_rom(index) && ~val & CS40L26_BTN_BANK_MASK)) {
- if (trigger_index == gpi_index) {
- ret = cs40l26_clear_gpi_event_reg(cs40l26, reg);
- if (ret)
- return ret;
- }
- }
+ ret = regmap_write(cs40l26->regmap, reg, CS40L26_EVENT_MAP_GPI_DISABLE);
+ if (ret) {
+ dev_err(cs40l26->dev, "Failed to clear GPI mapping %u\n",
+ mapping);
+ return ret;
}
+ cs40l26->gpi_ids[mapping] = -1;
+
return 0;
}
@@ -3002,6 +3025,7 @@ static void cs40l26_erase_worker(struct work_struct *work)
struct cs40l26_private *cs40l26 = container_of(work,
struct cs40l26_private, erase_work);
int ret = 0;
+ enum cs40l26_gpio_map mapping;
int effect_id;
u16 duration;
u32 index;
@@ -3025,7 +3049,8 @@ static void cs40l26_erase_worker(struct work_struct *work)
if (!wait_for_completion_timeout(&cs40l26->erase_cont,
msecs_to_jiffies(duration))) {
ret = -ETIME;
- dev_err(cs40l26->dev, "Failed to erase effect: %d", ret);
+ dev_err(cs40l26->dev, "Failed to erase effect: %d",
+ ret);
goto pm_err;
}
mutex_lock(&cs40l26->lock);
@@ -3033,25 +3058,20 @@ static void cs40l26_erase_worker(struct work_struct *work)
dev_dbg(cs40l26->dev, "%s: effect ID = %d\n", __func__, effect_id);
- if (is_owt(index)) {
- ret = cs40l26_erase_owt(cs40l26, effect_id);
+ mapping = cs40l26_map_get(cs40l26, effect_id);
+ if (mapping != CS40L26_GPIO_MAP_INVALID) {
+ ret = cs40l26_erase_gpi_mapping(cs40l26, mapping);
if (ret)
- dev_err(cs40l26->dev, "Failed to erase OWT effect: %d",
- ret);
- goto out_mutex;
+ goto out_mutex;
}
- if (is_buzz(index)) {
+ if (is_owt(index))
+ ret = cs40l26_erase_owt(cs40l26, effect_id);
+ else if (is_buzz(index))
ret = cs40l26_erase_buzz(cs40l26, effect_id);
- if (ret)
- dev_err(cs40l26->dev, "Failed to erase buzz effect: %d",
- ret);
- goto out_mutex;
- }
- ret = cs40l26_erase_gpi_mapping(cs40l26, effect_id);
if (ret)
- dev_err(cs40l26->dev, "Failed to erase gpi mapping: %d", ret);
+ dev_err(cs40l26->dev, "Failed to erase effect: %d", ret);
out_mutex:
mutex_unlock(&cs40l26->lock);
@@ -4826,15 +4846,15 @@ int cs40l26_probe(struct cs40l26_private *cs40l26,
ret = cs40l26_set_pll_loop(cs40l26, CS40L26_PLL_REFCLK_SET_OPEN_LOOP);
if (ret)
- return ret;
+ goto err;
- ret = cs40l26_clear_gpi_event_reg(cs40l26, CS40L26_A1_EVENT_MAP_1);
+ ret = cs40l26_erase_gpi_mapping(cs40l26, CS40L26_GPIO_MAP_A_PRESS);
if (ret)
- return ret;
+ goto err;
- ret = cs40l26_clear_gpi_event_reg(cs40l26, CS40L26_A1_EVENT_MAP_2);
+ ret = cs40l26_erase_gpi_mapping(cs40l26, CS40L26_GPIO_MAP_A_RELEASE);
if (ret)
- return ret;
+ goto err;
ret = cs40l26_part_num_resolve(cs40l26);
if (ret)
diff --git a/cs40l26/cs40l26.h b/cs40l26/cs40l26.h
index 17e675f..359abe1 100644
--- a/cs40l26/cs40l26.h
+++ b/cs40l26/cs40l26.h
@@ -856,17 +856,19 @@
#define CS40L26_SVC_LE_MAX_ATTEMPTS 2
#define CS40L26_SVC_DT_PREFIX "svc-le"
-#define CS40L26_FW_ID 0x1800D4
-#define CS40L26_FW_MIN_REV 0x07021C
-#define CS40L26_FW_BRANCH 0x07
-#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 0x270216
-#define CS40L26_FW_MAINT_BRANCH 0x27
-#define CS40L26_FW_MAINT_CALIB_MIN_REV 0x21010D
-#define CS40L26_FW_MAINT_CALIB_BRANCH 0x21
-#define CS40L26_FW_BRANCH_MASK GENMASK(23, 21)
+#define CS40L26_FW_ID 0x1800D4
+#define CS40L26_FW_MIN_REV 0x07021C
+#define CS40L26_FW_BRANCH 0x07
+#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 0x270216
+#define CS40L26_FW_MAINT_BRANCH 0x27
+#define CS40L26_FW_MAINT_CALIB_MIN_REV 0x21010D
+#define CS40L26_FW_MAINT_CALIB_BRANCH 0x21
+#define CS40L26_FW_GPI_TIMEOUT_MIN_REV 0x07022A
+#define CS40L26_FW_GPI_TIMEOUT_CALIB_MIN_REV 0x010122
+#define CS40L26_FW_BRANCH_MASK GENMASK(23, 21)
#define CS40L26_CCM_CORE_RESET 0x00000200
#define CS40L26_CCM_CORE_ENABLE 0x00000281
@@ -938,7 +940,7 @@
#define CS40L26_GPIO1 1
#define CS40L26_EVENT_MAP_INDEX_MASK GENMASK(8, 0)
#define CS40L26_EVENT_MAP_NUM_GPI_REGS 4
-#define CS40L26_EVENT_MAP_GPI_EVENT_DISABLE 0x1FF
+#define CS40L26_EVENT_MAP_GPI_DISABLE 0x1FF
#define CS40L26_BTN_INDEX_MASK GENMASK(7, 0)
#define CS40L26_BTN_BUZZ_MASK BIT(7)
@@ -1290,6 +1292,13 @@
#define CS40L26_SAMPS_TO_MS(n) ((n) / 8)
/* enums */
+enum cs40l26_gpio_map {
+ CS40L26_GPIO_MAP_A_PRESS,
+ CS40L26_GPIO_MAP_A_RELEASE,
+ CS40L26_GPIO_MAP_NUM_AVAILABLE,
+ CS40L26_GPIO_MAP_INVALID,
+};
+
enum cs40l26_dbc {
CS40L26_DBC_ENV_REL_COEF, /* 0 */
CS40L26_DBC_RISE_HEADROOM,
@@ -1473,6 +1482,7 @@ struct cs40l26_private {
struct input_dev *input;
struct cl_dsp *dsp;
unsigned int trigger_indices[FF_MAX_EFFECTS];
+ int gpi_ids[CS40L26_GPIO_MAP_NUM_AVAILABLE];
struct ff_effect *trigger_effect;
struct ff_effect upload_effect;
struct ff_effect *erase_effect;