diff --git a/drivers/input/misc/qcom-hv-haptics.c b/drivers/input/misc/qcom-hv-haptics.c index 5239f81641b5..fdb26327f295 100644 --- a/drivers/input/misc/qcom-hv-haptics.c +++ b/drivers/input/misc/qcom-hv-haptics.c @@ -29,7 +29,9 @@ #define AUTO_RES_CAL_DONE_BIT BIT(5) #define CAL_TLRA_CL_STS_MSB_MASK GENMASK(4, 0) /* STATUS_DATA_MSB definition in V2 while MOD_STATUS_SEL is 3 */ -#define LAST_GOOD_TLRA_CL_MASK GENMASK(4, 0) +#define LAST_GOOD_TLRA_CL_MSB_MASK GENMASK(4, 0) +/* STATUS_DATA_MSB definition in V2 while MOD_STATUS_SEL is 4 */ +#define TLRA_CL_ERR_MSB_MASK GENMASK(4, 0) /* STATUS_DATA_MSB definition in V1 while MOD_STATUS_SEL is 5 */ #define FIFO_REAL_TIME_FILL_STATUS_MASK_V1 GENMASK(6, 0) /* STATUS DATA_MSB definition in V2 while MOD_STATUS_SEL is 5 */ @@ -135,6 +137,7 @@ #define HAP_CFG_MOD_STATUS_SEL_REG 0x70 #define MOD_STATUS_SEL_CAL_TLRA_CL_STS_VAL 0 #define MOD_STATUS_SEL_LAST_GOOD_TLRA_VAL 3 +#define MOD_STATUS_SEL_TLRA_CL_ERR_STS_VAL 4 #define MOD_STATUS_SEL_FIFO_FILL_STATUS_VAL 5 #define MOD_STATUS_SEL_BRAKE_CAL_RNAT_RCAL_VAL 6 @@ -145,6 +148,7 @@ #define HAP_CFG_CAL_EN_REG 0x72 #define CAL_RC_CLK_MASK GENMASK(3, 2) #define CAL_RC_CLK_SHIFT 2 +#define CAL_RC_CLK_DISABLED_VAL 0 #define CAL_RC_CLK_AUTO_VAL 1 #define CAL_RC_CLK_MANUAL_VAL 2 @@ -430,6 +434,7 @@ struct haptics_chip { struct regulator_dev *swr_slave_rdev; struct mutex irq_lock; struct nvmem_cell *cl_brake_nvmem; + struct nvmem_device *hap_cfg_nvmem; struct class hap_class; int fifo_empty_irq; u32 effects_count; @@ -756,25 +761,48 @@ static int haptics_get_closeloop_lra_period_v1( tmp = ((val[0] & CAL_TLRA_CL_STS_MSB_MASK) << 8) | val[1]; config->cl_t_lra_us = (tmp * step_ns) / 1000; - return 0; + return haptics_adjust_lra_period(chip, &config->cl_t_lra_us); } -#define CL_TLRA_STEP_NS 1666 +#define TLRA_AUTO_RES_ERR_NO_CAL_STEP_PSEC 1667000 +#define TLRA_AUTO_RES_NO_CAL_STEP_PSEC 3333000 +#define TLRA_AUTO_RES_ERR_AUTO_CAL_STEP_PSEC 1627700 +#define TLRA_AUTO_RES_AUTO_CAL_STEP_PSEC 813850 static int haptics_get_closeloop_lra_period_v2( struct haptics_chip *chip) { struct haptics_hw_config *config = &chip->config; + u16 cal_tlra_cl_sts, tlra_cl_err_sts, tlra_ol, last_good_tlra_cl_sts; + u8 val[2], rc_clk_cal; + bool auto_res_done; + u64 tmp; int rc; - u8 val[2]; - u32 tmp; - val[0] = MOD_STATUS_XT_SEL_LAST_GOOD_TLRA_VAL; - rc = haptics_write(chip, chip->cfg_addr_base, - HAP_CFG_MOD_STATUS_XT_V2_REG, val, 1); + /* read RC_CLK_CAL enabling mode */ + rc = haptics_read(chip, chip->cfg_addr_base, + HAP_CFG_CAL_EN_REG, val, 1); if (rc < 0) return rc; - val[0] = MOD_STATUS_SEL_LAST_GOOD_TLRA_VAL; + rc_clk_cal = ((val[0] & CAL_RC_CLK_MASK) >> CAL_RC_CLK_SHIFT); + /* read auto resonance calibration result */ + val[0] = MOD_STATUS_SEL_CAL_TLRA_CL_STS_VAL; + rc = haptics_write(chip, chip->cfg_addr_base, + HAP_CFG_MOD_STATUS_SEL_REG, val, 1); + if (rc < 0) + return rc; + + rc = haptics_read(chip, chip->cfg_addr_base, + HAP_CFG_STATUS_DATA_MSB_REG, val, 2); + if (rc < 0) + return rc; + + auto_res_done = !!(val[0] & AUTO_RES_CAL_DONE_BIT); + cal_tlra_cl_sts = + ((val[0] & CAL_TLRA_CL_STS_MSB_MASK) << 8) | val[1]; + + /* read auto resonance calibration error status */ + val[0] = MOD_STATUS_SEL_TLRA_CL_ERR_STS_VAL; rc = haptics_write(chip, chip->cfg_addr_base, HAP_CFG_MOD_STATUS_SEL_REG, val, 1); if (rc < 0) @@ -784,15 +812,77 @@ static int haptics_get_closeloop_lra_period_v2( HAP_CFG_STATUS_DATA_MSB_REG, val, 2); if (rc < 0) return rc; - /* - * Calculate the closed loop T_LRA with the following equations - * for PM8350B V2: - * LAST_GOOD_TLRA_CL_STS[12:0] = STATUS_DATA_MSB[4:0] | - * STATUS_DATA_LSB[7:0] - * LAST_GOOD_TLRA_CL = LAST_GOOD_TLRA_CL_STS[12:0] * 1.666 us - */ - tmp = ((val[0] & LAST_GOOD_TLRA_CL_MASK) << 8) | val[1]; - config->cl_t_lra_us = (tmp * CL_TLRA_STEP_NS) / 1000; + + tlra_cl_err_sts = + ((val[0] & TLRA_CL_ERR_MSB_MASK) << 8) | val[1]; + + dev_dbg(chip->dev, "rc_clk_cal = %u, auto_res_done = %d\n", + rc_clk_cal, auto_res_done); + + if (rc_clk_cal == CAL_RC_CLK_DISABLED_VAL && !auto_res_done) { + /* TLRA_CL_ERR(us) = TLRA_CL_ERR_STS * 1.667 us */ + tmp = tlra_cl_err_sts * TLRA_AUTO_RES_ERR_NO_CAL_STEP_PSEC; + } else if (rc_clk_cal == CAL_RC_CLK_DISABLED_VAL && auto_res_done) { + /* + * CAL_TLRA_CL_STS_NO_CAL = CAL_TLRA_CL_STS + * TLRA_AUTO_RES(us) = CAL_TLRA_CL_STS_NO_CAL * 3.333 us + */ + tmp = cal_tlra_cl_sts * TLRA_AUTO_RES_NO_CAL_STEP_PSEC; + } else if (rc_clk_cal == CAL_RC_CLK_AUTO_VAL && !auto_res_done) { + /* + * CAL_TLRA_OL = CAL_TLRA_CL_STS; + * TLRA_CL_ERR(us) = TLRA_CL_ERR_STS * + * (TLRA_OL / CAL_TLRA_OL) * 1.6277 us + */ + + /* read the TLRA_OL setting */ + rc = haptics_read(chip, chip->cfg_addr_base, + HAP_CFG_TLRA_OL_HIGH_REG, val, 2); + if (rc < 0) + return rc; + + tlra_ol = (val[0] & TLRA_OL_MSB_MASK) << 8 | val[1]; + tmp = tlra_cl_err_sts * tlra_ol; + tmp *= TLRA_AUTO_RES_ERR_AUTO_CAL_STEP_PSEC; + tmp = div_u64(tmp, cal_tlra_cl_sts); + } else if (rc_clk_cal == CAL_RC_CLK_AUTO_VAL && auto_res_done) { + /* + * CAL_TLRA_CL_STS_W_CAL = CAL_TLRA_CL_STS; + * TLRA_AUTO_RES(us) = LAST_GOOD_TLRA_CL_STS * 0.81385 us * + * (LAST_GOOD_TLRA_CL_STS / CAL_TLRA_CL_STS_AUTO_CAL) + */ + + /* read LAST_GOOD_TLRA_CL_STS */ + val[0] = MOD_STATUS_XT_SEL_LAST_GOOD_TLRA_VAL; + rc = haptics_write(chip, chip->cfg_addr_base, + HAP_CFG_MOD_STATUS_XT_V2_REG, val, 1); + if (rc < 0) + return rc; + + val[0] = MOD_STATUS_SEL_LAST_GOOD_TLRA_VAL; + rc = haptics_write(chip, chip->cfg_addr_base, + HAP_CFG_MOD_STATUS_SEL_REG, val, 1); + if (rc < 0) + return rc; + + rc = haptics_read(chip, chip->cfg_addr_base, + HAP_CFG_STATUS_DATA_MSB_REG, val, 2); + if (rc < 0) + return rc; + + last_good_tlra_cl_sts = + ((val[0] & LAST_GOOD_TLRA_CL_MSB_MASK) << 8) | val[1]; + + tmp = last_good_tlra_cl_sts * last_good_tlra_cl_sts; + tmp *= TLRA_AUTO_RES_AUTO_CAL_STEP_PSEC; + tmp = div_u64(tmp, cal_tlra_cl_sts); + } else { + dev_err(chip->dev, "Can't get close-loop LRA period in rc_clk_cal mode %u\n", + rc_clk_cal); + return -EINVAL; + } + + config->cl_t_lra_us = div_u64(tmp, 1000000); return 0; } @@ -807,17 +897,13 @@ static int haptics_get_closeloop_lra_period(struct haptics_chip *chip) rc = haptics_get_closeloop_lra_period_v2(chip); if (rc < 0) { - dev_err(chip->dev, "get close loop T LRA failed, rc=%d\n", rc); + dev_err(chip->dev, "get close loop T LRA failed, rc=%d\n", + rc); return rc; } - rc = haptics_adjust_lra_period(chip, &chip->config.cl_t_lra_us); - if (rc < 0) - return rc; - dev_dbg(chip->dev, "OL_TLRA %u us, CL_TLRA %u us\n", chip->config.t_lra_us, chip->config.cl_t_lra_us); - return 0; } @@ -892,6 +978,40 @@ static int haptics_set_direct_play(struct haptics_chip *chip, u8 amplitude) return rc; } +#define PBS_ARG_REG 0x42 +#define HAP_VREG_ON_VAL 0x1 +#define HAP_VREG_OFF_VAL 0x2 +#define PBS_TRIG_SET_REG 0xE5 +#define PBS_TRIG_SET_VAL 0x1 +static int haptics_boost_vreg_enable(struct haptics_chip *chip, bool en) +{ + int rc; + u8 val; + + if (chip->hap_cfg_nvmem == NULL) { + dev_dbg(chip->dev, "nvmem device for hap_cfg is not defined\n"); + return 0; + } + + val = en ? HAP_VREG_ON_VAL : HAP_VREG_OFF_VAL; + rc = nvmem_device_write(chip->hap_cfg_nvmem, + PBS_ARG_REG, 1, &val); + if (rc < 0) { + dev_err(chip->dev, "write SDAM %#x failed, rc=%d\n", + PBS_ARG_REG, rc); + return rc; + } + + val = PBS_TRIG_SET_VAL; + rc = nvmem_device_write(chip->hap_cfg_nvmem, + PBS_TRIG_SET_REG, 1, &val); + if (rc < 0) + dev_err(chip->dev, "Write SDAM %#x failed, rc=%d\n", + PBS_TRIG_SET_REG, rc); + + return rc; +} + static int haptics_enable_play(struct haptics_chip *chip, bool en) { struct haptics_play_info *play = &chip->play; @@ -916,8 +1036,17 @@ static int haptics_enable_play(struct haptics_chip *chip, bool en) rc = haptics_write(chip, chip->cfg_addr_base, HAP_CFG_SPMI_PLAY_REG, &val, 1); - if (rc < 0) + if (rc < 0) { dev_err(chip->dev, "Write SPMI_PLAY failed, rc=%d\n", rc); + return rc; + } + + if (play->pattern_src == FIFO) { + rc = haptics_boost_vreg_enable(chip, en); + if (rc < 0) + dev_err(chip->dev, "Notify vreg %s failed, rc=%d\n", + en ? "enabling" : "disabling", rc); + } return rc; } @@ -1874,6 +2003,7 @@ static int haptics_hw_init(struct haptics_chip *chip) struct haptics_effect *effect; int rc = 0, i; u8 val[2]; + u32 t_lra_us; /* Store CL brake settings */ rc = haptics_store_cl_brake_settings(chip); @@ -1918,12 +2048,23 @@ static int haptics_hw_init(struct haptics_chip *chip) if (config->is_erm) return 0; + /* set AUTO_mode RC CLK calibration by default */ + val[0] = CAL_RC_CLK_AUTO_VAL << CAL_RC_CLK_SHIFT; + rc = haptics_masked_write(chip, chip->cfg_addr_base, + HAP_CFG_CAL_EN_REG, CAL_RC_CLK_MASK, val[0]); + if (rc < 0) + return rc; + rc = haptics_get_closeloop_lra_period(chip); if (rc < 0) return rc; /* Config T_LRA */ - rc = haptics_config_openloop_lra_period(chip, chip->config.cl_t_lra_us); + t_lra_us = chip->config.t_lra_us; + if (chip->config.cl_t_lra_us != 0) + t_lra_us = chip->config.cl_t_lra_us; + + rc = haptics_config_openloop_lra_period(chip, t_lra_us); if (rc < 0) return rc; @@ -3069,6 +3210,18 @@ static int haptics_parse_dt(struct haptics_chip *chip) } } + if (of_find_property(node, "nvmem", NULL)) { + chip->hap_cfg_nvmem = + devm_nvmem_device_get(chip->dev, "hap_cfg_sdam"); + if (IS_ERR(chip->hap_cfg_nvmem)) { + rc = PTR_ERR(chip->hap_cfg_nvmem); + if (rc != -EPROBE_DEFER) + dev_err(chip->dev, "Failed to get nvmem device, rc=%d\n", + rc); + return rc; + } + } + addr = of_get_address(node, 0, NULL, NULL); if (!addr) { dev_err(chip->dev, "Read HAPTICS_CFG address failed\n");