From a7691a0f8e3c10caa366d40b08432bb5e27bee89 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 1ead64e0c110..e363aff6c515 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; }