diff options
author | Tai Kuo <taikuo@google.com> | 2022-10-24 16:10:52 +0800 |
---|---|---|
committer | Tai Kuo <taikuo@google.com> | 2022-10-24 16:24:32 +0800 |
commit | 472e3d5906cfbf9883bebe764f8b7d31f49fb8e5 (patch) | |
tree | e1d5565811778497d83d0a8a7d7d0f1faeeeb489 | |
parent | a446aef40c377974eb834f781e1b82562d673a4f (diff) | |
download | amplifiers-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.c | 136 | ||||
-rw-r--r-- | cs40l26/cs40l26.h | 34 |
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, ®); + 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; |