From fbe34611ee41cb0690da989a32c64a09be0cb7f7 Mon Sep 17 00:00:00 2001 From: Fenglin Wu Date: Thu, 18 Mar 2021 17:52:22 +0800 Subject: [PATCH] input: qcom-hv-haptics: reset haptics module if it's stuck in SWR mode The haptics module would get stuck in SWR mode if SWR port is disconnected during SWR play, and this can happen if ADSP SSR (subsystem reset) is triggered when playing in SWR mode. This stuck condition can be detected by checking if haptics module has already been in SWR mode when swr-haptics driver requests to enable SWR haptics. When it's detected, ignore SWR mode temporarily and toggle HAPTICS_EN for a HW reset. When SWR play is attempted again i.e. when swr_haptics driver request to turn on SWR slave device, SWR mode would get re-enabled. Change-Id: Ie55d331e3c689972b42dd9688f0d2b182b3fd282 Signed-off-by: Fenglin Wu --- drivers/input/misc/qcom-hv-haptics.c | 30 ++++++++++++++++++++++++++++ 1 file changed, 30 insertions(+) diff --git a/drivers/input/misc/qcom-hv-haptics.c b/drivers/input/misc/qcom-hv-haptics.c index 16a8f0751014..5a1fd8a5ae68 100644 --- a/drivers/input/misc/qcom-hv-haptics.c +++ b/drivers/input/misc/qcom-hv-haptics.c @@ -79,7 +79,9 @@ #define DRV_WF_SEL_MASK GENMASK(1, 0) #define HAP_CFG_AUTO_SHUTDOWN_CFG_REG 0x4A + #define HAP_CFG_TRIG_PRIORITY_REG 0x4B +#define SWR_IGNORE_BIT BIT(4) #define HAP_CFG_SPMI_PLAY_REG 0x4C #define PLAY_EN_BIT BIT(7) @@ -3902,6 +3904,34 @@ static int swr_slave_reg_enable(struct regulator_dev *rdev) return rc; } + /* + * If haptics has already been in SWR mode when enabling the SWR + * slave, it means that the haptics module was stuck in prevous + * SWR play. Then toggle HAPTICS_EN to reset haptics module and + * ignore SWR mode until next SWR slave enable request is coming. + */ + if (is_swr_play_enabled(chip)) { + rc = haptics_masked_write(chip, chip->cfg_addr_base, + HAP_CFG_TRIG_PRIORITY_REG, + SWR_IGNORE_BIT, SWR_IGNORE_BIT); + if (rc < 0) { + dev_err(chip->dev, "Failed to enable SWR_IGNORE, rc=%d\n", rc); + return rc; + } + + rc = haptics_toggle_module_enable(chip); + if (rc < 0) + return rc; + } else { + rc = haptics_masked_write(chip, chip->cfg_addr_base, + HAP_CFG_TRIG_PRIORITY_REG, + SWR_IGNORE_BIT, 0); + if (rc < 0) { + dev_err(chip->dev, "Failed to disable SWR_IGNORE, rc=%d\n", rc); + return rc; + } + } + chip->swr_slave_enabled = true; return 0; }