Loading drivers/input/misc/qcom-hv-haptics.c +254 −29 Original line number Diff line number Diff line Loading @@ -142,6 +142,9 @@ #define VMAX_HDRM_STEP_MV 50 #define VMAX_HDRM_MAX_MV 6350 #define HAP_CFG_VSET_CFG_REG 0x68 #define FORCE_VREG_RDY_BIT BIT(0) #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 Loading Loading @@ -249,6 +252,7 @@ #define CHAR_BRAKE_MODE 24 #define HW_BRAKE_CYCLES 5 #define F_LRA_VARIATION_HZ 5 #define NON_HBOOST_MAX_VMAX_MV 4000 #define MAX_FIFO_SAMPLES(chip) \ ((chip)->ptn_revision == HAP_PTN_V1 ? 104 : 640) Loading Loading @@ -427,6 +431,7 @@ struct haptics_hw_config { u32 cl_t_lra_us; u32 lra_min_mohms; u32 lra_max_mohms; u32 lra_open_mohms; u32 preload_effect; u32 fifo_empty_thresh; u16 rc_clk_cal_count; Loading Loading @@ -456,7 +461,9 @@ struct haptics_chip { struct nvmem_device *hap_cfg_nvmem; struct device_node *pbs_node; struct class hap_class; struct regulator *hpwr_vreg; int fifo_empty_irq; u32 hpwr_voltage_mv; u32 effects_count; u32 cfg_addr_base; u32 ptn_addr_base; Loading @@ -467,6 +474,7 @@ struct haptics_chip { bool fifo_empty_irq_en; bool swr_slave_enabled; bool clamp_at_5v; bool hpwr_vreg_enabled; }; struct haptics_reg_info { Loading Loading @@ -1055,6 +1063,23 @@ static int haptics_set_vmax_headroom_mv(struct haptics_chip *chip, u32 hdrm_mv) return rc; } static int haptics_get_vmax_headroom_mv(struct haptics_chip *chip, u32 *hdrm_mv) { int rc; u8 val; rc = haptics_read(chip, chip->cfg_addr_base, HAP_CFG_VMAX_HDRM_REG, &val, 1); if (rc < 0) { dev_err(chip->dev, "Get Vmax HDRM failed, rc=%d\n", rc); return rc; } *hdrm_mv = (val & VMAX_HDRM_MASK) * VMAX_HDRM_STEP_MV; return 0; } static int haptics_enable_autores(struct haptics_chip *chip, bool en) { int rc; Loading Loading @@ -1134,32 +1159,73 @@ static bool is_boost_vreg_enabled_in_open_loop(struct haptics_chip *chip) return false; } static int haptics_enable_play(struct haptics_chip *chip, bool en) static int haptics_enable_hpwr_vreg(struct haptics_chip *chip, bool en) { struct haptics_play_info *play = &chip->play; int rc; u8 val; if (chip->hpwr_vreg == NULL || chip->hpwr_vreg_enabled == en) return 0; if (en) { val = SC_CLR_BIT | AUTO_RES_ERR_CLR_BIT | HPWR_RDY_FAULT_CLR_BIT; rc = haptics_write(chip, chip->cfg_addr_base, HAP_CFG_FAULT_CLR_REG, &val, 1); rc = regulator_set_voltage(chip->hpwr_vreg, chip->hpwr_voltage_mv * 1000, INT_MAX); if (rc < 0) { dev_err(chip->dev, "Set hpwr voltage failed, rc=%d\n", rc); return rc; } rc = regulator_enable(chip->hpwr_vreg); if (rc < 0) { dev_err(chip->dev, "Enable hpwr failed, rc=%d\n", rc); regulator_set_voltage(chip->hpwr_vreg, 0, INT_MAX); return rc; } } else { rc = regulator_disable(chip->hpwr_vreg); if (rc < 0) { dev_err(chip->dev, "Disable hpwr failed, rc=%d\n", rc); return rc; } rc = regulator_set_voltage(chip->hpwr_vreg, 0, INT_MAX); if (rc < 0) { dev_err(chip->dev, "Set hpwr voltage failed, rc=%d\n", rc); return rc; } } dev_dbg(chip->dev, "%s hpwr vreg\n", en ? "enabled" : "disabled"); chip->hpwr_vreg_enabled = en; return 0; } static int haptics_open_loop_drive_config(struct haptics_chip *chip, bool en) { int rc; u8 val; if ((is_boost_vreg_enabled_in_open_loop(chip) || chip->hpwr_vreg != NULL) && en) { /* Force VREG_RDY */ val = FORCE_VREG_RDY_BIT; rc = haptics_masked_write(chip, chip->cfg_addr_base, HAP_CFG_VSET_CFG_REG, FORCE_VREG_RDY_BIT, FORCE_VREG_RDY_BIT); if (rc < 0) return rc; /* * Toggle RC_CLK_CAL_EN if it's in auto mode and * haptics boost is working in open loop */ /* Toggle RC_CLK_CAL_EN if it's in auto mode */ rc = haptics_read(chip, chip->cfg_addr_base, HAP_CFG_CAL_EN_REG, &val, 1); if (rc < 0) return rc; if (((val & CAL_RC_CLK_MASK) == CAL_RC_CLK_AUTO_VAL << CAL_RC_CLK_SHIFT) && is_boost_vreg_enabled_in_open_loop(chip)) { if ((val & CAL_RC_CLK_MASK) == CAL_RC_CLK_AUTO_VAL << CAL_RC_CLK_SHIFT) { val = CAL_RC_CLK_DISABLED_VAL << CAL_RC_CLK_SHIFT; rc = haptics_masked_write(chip, chip->cfg_addr_base, HAP_CFG_CAL_EN_REG, CAL_RC_CLK_MASK, Loading @@ -1176,8 +1242,35 @@ static int haptics_enable_play(struct haptics_chip *chip, bool en) dev_dbg(chip->dev, "Toggle CAL_EN in open-loop-VREG playing\n"); } } else { val = en ? FORCE_VREG_RDY_BIT : 0; rc = haptics_masked_write(chip, chip->cfg_addr_base, HAP_CFG_VSET_CFG_REG, FORCE_VREG_RDY_BIT, val); } return rc; } static int haptics_enable_play(struct haptics_chip *chip, bool en) { struct haptics_play_info *play = &chip->play; int rc; u8 val; if (en) { val = SC_CLR_BIT | AUTO_RES_ERR_CLR_BIT | HPWR_RDY_FAULT_CLR_BIT; rc = haptics_write(chip, chip->cfg_addr_base, HAP_CFG_FAULT_CLR_REG, &val, 1); if (rc < 0) return rc; } rc = haptics_open_loop_drive_config(chip, en); if (rc < 0) return rc; val = play->pattern_src; if (play->brake && !play->brake->disabled) val |= BRAKE_EN_BIT; Loading Loading @@ -1576,6 +1669,7 @@ static int haptics_set_fifo(struct haptics_chip *chip, struct fifo_cfg *fifo) static int haptics_load_constant_effect(struct haptics_chip *chip, u8 amplitude) { struct haptics_play_info *play = &chip->play; u32 hdrm_mv, vmax_mv = chip->config.vmax_mv; int rc = 0; mutex_lock(&chip->play.lock); Loading @@ -1588,8 +1682,17 @@ static int haptics_load_constant_effect(struct haptics_chip *chip, u8 amplitude) /* No effect data when playing constant waveform */ play->effect = NULL; /* Fix Vmax to (hpwr_vreg_mv - hdrm_mv) in non-HBOOST regulator case */ if (chip->hpwr_vreg) { rc = haptics_get_vmax_headroom_mv(chip, &hdrm_mv); if (rc < 0) goto unlock; vmax_mv = chip->hpwr_voltage_mv - hdrm_mv; } /* configure VMAX in case it was changed in previous effect playing */ rc = haptics_set_vmax_mv(chip, chip->config.vmax_mv); rc = haptics_set_vmax_mv(chip, vmax_mv); if (rc < 0) goto unlock; Loading Loading @@ -1899,6 +2002,26 @@ static int haptics_load_periodic_effect(struct haptics_chip *chip, return rc; } static u8 get_direct_play_max_amplitude(struct haptics_chip *chip) { u32 amplitude = DIRECT_PLAY_MAX_AMPLITUDE, hdrm_mv; int rc; if (chip->hpwr_vreg) { rc = haptics_get_vmax_headroom_mv(chip, &hdrm_mv); if (rc < 0) return 0; amplitude *= chip->config.vmax_mv; amplitude /= (chip->hpwr_voltage_mv - hdrm_mv); if (amplitude > DIRECT_PLAY_MAX_AMPLITUDE) amplitude = DIRECT_PLAY_MAX_AMPLITUDE; } dev_dbg(chip->dev, "max amplitude for direct play: %#x\n", amplitude); return (u8)amplitude; } static int haptics_upload_effect(struct input_dev *dev, struct ff_effect *effect, struct ff_effect *old) { Loading @@ -1912,9 +2035,10 @@ static int haptics_upload_effect(struct input_dev *dev, case FF_CONSTANT: length_us = effect->replay.length * USEC_PER_MSEC; level = effect->u.constant.level; tmp = level * DIRECT_PLAY_MAX_AMPLITUDE; tmp = get_direct_play_max_amplitude(chip); tmp *= level; amplitude = tmp / 0x7fff; dev_dbg(chip->dev, "upload constant effect, length = %dus, amplitude = %d\n", dev_dbg(chip->dev, "upload constant effect, length = %dus, amplitude = %#x\n", length_us, amplitude); haptics_load_constant_effect(chip, amplitude); if (rc < 0) { Loading Loading @@ -1961,7 +2085,11 @@ static int haptics_upload_effect(struct input_dev *dev, return -EINVAL; } return 0; rc = haptics_enable_hpwr_vreg(chip, true); if (rc < 0) dev_err(chip->dev, "enable hpwr_vreg failed, rc=%d\n"); return rc; } static void haptics_fifo_empty_irq_config(struct haptics_chip *chip, Loading Loading @@ -2065,7 +2193,11 @@ static int haptics_erase(struct input_dev *dev, int effect_id) } } return 0; rc = haptics_enable_hpwr_vreg(chip, false); if (rc < 0) dev_err(chip->dev, "disable hpwr_vreg failed, rc=%d\n"); return rc; } static void haptics_set_gain(struct input_dev *dev, u16 gain) Loading @@ -2073,7 +2205,7 @@ static void haptics_set_gain(struct input_dev *dev, u16 gain) struct haptics_chip *chip = input_get_drvdata(dev); struct haptics_hw_config *config = &chip->config; struct haptics_play_info *play = &chip->play; u32 vmax_mv; u32 vmax_mv, amplitude; if (gain == 0) return; Loading @@ -2081,6 +2213,20 @@ static void haptics_set_gain(struct input_dev *dev, u16 gain) if (gain > 0x7fff) gain = 0x7fff; dev_dbg(chip->dev, "Set gain: %#x\n", gain); /* scale amplitude when playing in DIRECT_PLAY mode */ if (chip->play.pattern_src == DIRECT_PLAY) { amplitude = get_direct_play_max_amplitude(chip); amplitude *= gain; amplitude /= 0x7fff; dev_dbg(chip->dev, "Set amplitude: %#x\n", amplitude); haptics_set_direct_play(chip, (u8)amplitude); return; } /* scale Vmax when playing in other modes */ vmax_mv = config->vmax_mv; if (play->effect) vmax_mv = play->effect->vmax_mv; Loading Loading @@ -3347,6 +3493,38 @@ static int haptics_get_revision(struct haptics_chip *chip) return 0; } static int haptics_parse_hpwr_vreg_dt(struct haptics_chip *chip) { struct device_node *node = chip->dev->of_node; int rc; if (!of_find_property(node, "qcom,hpwr-supply", NULL)) return 0; chip->hpwr_vreg = devm_regulator_get(chip->dev, "qcom,hpwr"); if (IS_ERR(chip->hpwr_vreg)) { rc = PTR_ERR(chip->hpwr_vreg); if (rc != -EPROBE_DEFER) dev_err(chip->dev, "Failed to get qcom,hpwr-supply, rc=%d\n", rc); return rc; } rc = of_property_read_u32(node, "qcom,hpwr-voltage-mv", &chip->hpwr_voltage_mv); if (rc < 0) { dev_err(chip->dev, "Failed to read qcom,hpwr-voltage-mv, rc=%d\n", rc); return rc; } if (chip->hpwr_voltage_mv == 0 || chip->hpwr_voltage_mv > NON_HBOOST_MAX_VMAX_MV) return -EINVAL; return 0; } static int haptics_parse_dt(struct haptics_chip *chip) { struct haptics_hw_config *config = &chip->config; Loading @@ -3355,6 +3533,10 @@ static int haptics_parse_dt(struct haptics_chip *chip) const __be32 *addr; int rc = 0, tmp; rc = haptics_parse_hpwr_vreg_dt(chip); if (rc < 0) return rc; if (of_find_property(node, "nvmem-cells", NULL)) { chip->cl_brake_nvmem = devm_nvmem_cell_get(chip->dev, "hap_cl_brake"); Loading Loading @@ -3619,9 +3801,24 @@ static int haptics_pbs_trigger_isc_config(struct haptics_chip *chip) #define MAX_SWEEP_STEPS 5 #define MAX_IMPEDANCE_MOHM 40000 #define MIN_ISC_MA 250 #define MIN_DUTY_MILLI_PCT 0 #define MAX_DUTY_MILLI_PCT 100000 #define LRA_CONFIG_REGS 3 static u32 get_lra_impedance_capable_max(struct haptics_chip *chip) { u32 mohms = MAX_IMPEDANCE_MOHM; if (chip->clamp_at_5v) mohms = MAX_IMPEDANCE_MOHM / 2; if (chip->hpwr_vreg) mohms = (chip->hpwr_voltage_mv * 1000) / MIN_ISC_MA; dev_dbg(chip->dev, "LRA impedance capable max: %u mohms\n", mohms); return mohms; } static int haptics_detect_lra_impedance(struct haptics_chip *chip) { int rc, i; Loading @@ -3633,7 +3830,7 @@ static int haptics_detect_lra_impedance(struct haptics_chip *chip) struct haptics_reg_info backup[LRA_CONFIG_REGS]; u8 val; u32 duty_milli_pct, low_milli_pct, high_milli_pct; u32 amplitude, lra_min_mohms, lra_max_mohms; u32 amplitude, lra_min_mohms, lra_max_mohms, capability_mohms; if (chip->cfg_revision == HAP_CFG_V1) { dev_dbg(chip->dev, "HAP_CFG V1.0 doesn't support impedance detection\n"); Loading Loading @@ -3662,6 +3859,10 @@ static int haptics_detect_lra_impedance(struct haptics_chip *chip) goto restore; } rc = haptics_enable_hpwr_vreg(chip, true); if (rc < 0) goto restore; low_milli_pct = MIN_DUTY_MILLI_PCT; high_milli_pct = MAX_DUTY_MILLI_PCT; /* Sweep duty cycle using binary approach */ Loading Loading @@ -3704,11 +3905,12 @@ static int haptics_detect_lra_impedance(struct haptics_chip *chip) usleep_range(4000, 5000); } lra_min_mohms = low_milli_pct * MAX_IMPEDANCE_MOHM / 100000; lra_max_mohms = high_milli_pct * MAX_IMPEDANCE_MOHM / 100000; capability_mohms = get_lra_impedance_capable_max(chip); lra_min_mohms = low_milli_pct * capability_mohms / 100000; lra_max_mohms = high_milli_pct * capability_mohms / 100000; if (lra_min_mohms == 0) dev_warn(chip->dev, "Short circuit detected!\n"); else if (lra_max_mohms == MAX_IMPEDANCE_MOHM) else if (lra_max_mohms >= capability_mohms) dev_warn(chip->dev, "Open circuit detected!\n"); else dev_dbg(chip->dev, "LRA impedance is between %u - %u mohms\n", Loading @@ -3716,9 +3918,14 @@ static int haptics_detect_lra_impedance(struct haptics_chip *chip) chip->config.lra_min_mohms = lra_min_mohms; chip->config.lra_max_mohms = lra_max_mohms; chip->config.lra_open_mohms = capability_mohms; restore: /* Disable play in case it's not been disabled */ haptics_enable_play(chip, false); rc = haptics_enable_hpwr_vreg(chip, false); if (rc < 0) return rc; /* Trigger PBS to restore 1500mA ISC setting */ rc = haptics_pbs_trigger_isc_config(chip); if (rc < 0) Loading @@ -3739,7 +3946,8 @@ static int haptics_detect_lra_impedance(struct haptics_chip *chip) static int haptics_detect_lra_frequency(struct haptics_chip *chip) { int rc; u8 autores_cfg; u8 autores_cfg, amplitude; u32 vmax_mv = chip->config.vmax_mv; rc = haptics_read(chip, chip->cfg_addr_base, HAP_CFG_AUTORES_CFG_REG, &autores_cfg, 1); Loading @@ -3760,15 +3968,24 @@ static int haptics_detect_lra_frequency(struct haptics_chip *chip) if (rc < 0) goto restore; rc = haptics_set_vmax_mv(chip, chip->config.vmax_mv); rc = haptics_set_vmax_headroom_mv(chip, LRA_CALIBRATION_VMAX_HDRM_MV); if (rc < 0) goto restore; rc = haptics_set_vmax_headroom_mv(chip, LRA_CALIBRATION_VMAX_HDRM_MV); /* Fix Vmax to (hpwr_vreg_mv - hdrm_mv) in non-HBOOST regulator case */ if (chip->hpwr_vreg) vmax_mv = chip->hpwr_voltage_mv - LRA_CALIBRATION_VMAX_HDRM_MV; rc = haptics_set_vmax_mv(chip, vmax_mv); if (rc < 0) goto restore; rc = haptics_set_direct_play(chip, DIRECT_PLAY_MAX_AMPLITUDE); amplitude = get_direct_play_max_amplitude(chip); rc = haptics_set_direct_play(chip, amplitude); if (rc < 0) goto restore; rc = haptics_enable_hpwr_vreg(chip, true); if (rc < 0) goto restore; Loading @@ -3793,6 +4010,10 @@ static int haptics_detect_lra_frequency(struct haptics_chip *chip) restore: /* Disable play in case it's not been disabled */ haptics_enable_play(chip, false); rc = haptics_enable_hpwr_vreg(chip, false); if (rc < 0) return rc; rc = haptics_write(chip, chip->cfg_addr_base, HAP_CFG_AUTORES_CFG_REG, &autores_cfg, 1); Loading Loading @@ -3889,7 +4110,7 @@ static ssize_t lra_impedance_show(struct class *c, return -EINVAL; else if (chip->config.lra_min_mohms == 0) return scnprintf(buf, PAGE_SIZE, "%s\n", "Short circuit"); else if (chip->config.lra_max_mohms == MAX_IMPEDANCE_MOHM) else if (chip->config.lra_max_mohms >= chip->config.lra_open_mohms) return scnprintf(buf, PAGE_SIZE, "%s\n", "Open circuit"); else return scnprintf(buf, PAGE_SIZE, "%u ~ %u mohms\n", Loading Loading @@ -4071,6 +4292,10 @@ static int haptics_suspend(struct device *dev) return rc; } rc = haptics_enable_hpwr_vreg(chip, false); if (rc < 0) return rc; return haptics_write(chip, chip->cfg_addr_base, HAP_CFG_EN_CTL_REG, &val, 1); } Loading Loading
drivers/input/misc/qcom-hv-haptics.c +254 −29 Original line number Diff line number Diff line Loading @@ -142,6 +142,9 @@ #define VMAX_HDRM_STEP_MV 50 #define VMAX_HDRM_MAX_MV 6350 #define HAP_CFG_VSET_CFG_REG 0x68 #define FORCE_VREG_RDY_BIT BIT(0) #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 Loading Loading @@ -249,6 +252,7 @@ #define CHAR_BRAKE_MODE 24 #define HW_BRAKE_CYCLES 5 #define F_LRA_VARIATION_HZ 5 #define NON_HBOOST_MAX_VMAX_MV 4000 #define MAX_FIFO_SAMPLES(chip) \ ((chip)->ptn_revision == HAP_PTN_V1 ? 104 : 640) Loading Loading @@ -427,6 +431,7 @@ struct haptics_hw_config { u32 cl_t_lra_us; u32 lra_min_mohms; u32 lra_max_mohms; u32 lra_open_mohms; u32 preload_effect; u32 fifo_empty_thresh; u16 rc_clk_cal_count; Loading Loading @@ -456,7 +461,9 @@ struct haptics_chip { struct nvmem_device *hap_cfg_nvmem; struct device_node *pbs_node; struct class hap_class; struct regulator *hpwr_vreg; int fifo_empty_irq; u32 hpwr_voltage_mv; u32 effects_count; u32 cfg_addr_base; u32 ptn_addr_base; Loading @@ -467,6 +474,7 @@ struct haptics_chip { bool fifo_empty_irq_en; bool swr_slave_enabled; bool clamp_at_5v; bool hpwr_vreg_enabled; }; struct haptics_reg_info { Loading Loading @@ -1055,6 +1063,23 @@ static int haptics_set_vmax_headroom_mv(struct haptics_chip *chip, u32 hdrm_mv) return rc; } static int haptics_get_vmax_headroom_mv(struct haptics_chip *chip, u32 *hdrm_mv) { int rc; u8 val; rc = haptics_read(chip, chip->cfg_addr_base, HAP_CFG_VMAX_HDRM_REG, &val, 1); if (rc < 0) { dev_err(chip->dev, "Get Vmax HDRM failed, rc=%d\n", rc); return rc; } *hdrm_mv = (val & VMAX_HDRM_MASK) * VMAX_HDRM_STEP_MV; return 0; } static int haptics_enable_autores(struct haptics_chip *chip, bool en) { int rc; Loading Loading @@ -1134,32 +1159,73 @@ static bool is_boost_vreg_enabled_in_open_loop(struct haptics_chip *chip) return false; } static int haptics_enable_play(struct haptics_chip *chip, bool en) static int haptics_enable_hpwr_vreg(struct haptics_chip *chip, bool en) { struct haptics_play_info *play = &chip->play; int rc; u8 val; if (chip->hpwr_vreg == NULL || chip->hpwr_vreg_enabled == en) return 0; if (en) { val = SC_CLR_BIT | AUTO_RES_ERR_CLR_BIT | HPWR_RDY_FAULT_CLR_BIT; rc = haptics_write(chip, chip->cfg_addr_base, HAP_CFG_FAULT_CLR_REG, &val, 1); rc = regulator_set_voltage(chip->hpwr_vreg, chip->hpwr_voltage_mv * 1000, INT_MAX); if (rc < 0) { dev_err(chip->dev, "Set hpwr voltage failed, rc=%d\n", rc); return rc; } rc = regulator_enable(chip->hpwr_vreg); if (rc < 0) { dev_err(chip->dev, "Enable hpwr failed, rc=%d\n", rc); regulator_set_voltage(chip->hpwr_vreg, 0, INT_MAX); return rc; } } else { rc = regulator_disable(chip->hpwr_vreg); if (rc < 0) { dev_err(chip->dev, "Disable hpwr failed, rc=%d\n", rc); return rc; } rc = regulator_set_voltage(chip->hpwr_vreg, 0, INT_MAX); if (rc < 0) { dev_err(chip->dev, "Set hpwr voltage failed, rc=%d\n", rc); return rc; } } dev_dbg(chip->dev, "%s hpwr vreg\n", en ? "enabled" : "disabled"); chip->hpwr_vreg_enabled = en; return 0; } static int haptics_open_loop_drive_config(struct haptics_chip *chip, bool en) { int rc; u8 val; if ((is_boost_vreg_enabled_in_open_loop(chip) || chip->hpwr_vreg != NULL) && en) { /* Force VREG_RDY */ val = FORCE_VREG_RDY_BIT; rc = haptics_masked_write(chip, chip->cfg_addr_base, HAP_CFG_VSET_CFG_REG, FORCE_VREG_RDY_BIT, FORCE_VREG_RDY_BIT); if (rc < 0) return rc; /* * Toggle RC_CLK_CAL_EN if it's in auto mode and * haptics boost is working in open loop */ /* Toggle RC_CLK_CAL_EN if it's in auto mode */ rc = haptics_read(chip, chip->cfg_addr_base, HAP_CFG_CAL_EN_REG, &val, 1); if (rc < 0) return rc; if (((val & CAL_RC_CLK_MASK) == CAL_RC_CLK_AUTO_VAL << CAL_RC_CLK_SHIFT) && is_boost_vreg_enabled_in_open_loop(chip)) { if ((val & CAL_RC_CLK_MASK) == CAL_RC_CLK_AUTO_VAL << CAL_RC_CLK_SHIFT) { val = CAL_RC_CLK_DISABLED_VAL << CAL_RC_CLK_SHIFT; rc = haptics_masked_write(chip, chip->cfg_addr_base, HAP_CFG_CAL_EN_REG, CAL_RC_CLK_MASK, Loading @@ -1176,8 +1242,35 @@ static int haptics_enable_play(struct haptics_chip *chip, bool en) dev_dbg(chip->dev, "Toggle CAL_EN in open-loop-VREG playing\n"); } } else { val = en ? FORCE_VREG_RDY_BIT : 0; rc = haptics_masked_write(chip, chip->cfg_addr_base, HAP_CFG_VSET_CFG_REG, FORCE_VREG_RDY_BIT, val); } return rc; } static int haptics_enable_play(struct haptics_chip *chip, bool en) { struct haptics_play_info *play = &chip->play; int rc; u8 val; if (en) { val = SC_CLR_BIT | AUTO_RES_ERR_CLR_BIT | HPWR_RDY_FAULT_CLR_BIT; rc = haptics_write(chip, chip->cfg_addr_base, HAP_CFG_FAULT_CLR_REG, &val, 1); if (rc < 0) return rc; } rc = haptics_open_loop_drive_config(chip, en); if (rc < 0) return rc; val = play->pattern_src; if (play->brake && !play->brake->disabled) val |= BRAKE_EN_BIT; Loading Loading @@ -1576,6 +1669,7 @@ static int haptics_set_fifo(struct haptics_chip *chip, struct fifo_cfg *fifo) static int haptics_load_constant_effect(struct haptics_chip *chip, u8 amplitude) { struct haptics_play_info *play = &chip->play; u32 hdrm_mv, vmax_mv = chip->config.vmax_mv; int rc = 0; mutex_lock(&chip->play.lock); Loading @@ -1588,8 +1682,17 @@ static int haptics_load_constant_effect(struct haptics_chip *chip, u8 amplitude) /* No effect data when playing constant waveform */ play->effect = NULL; /* Fix Vmax to (hpwr_vreg_mv - hdrm_mv) in non-HBOOST regulator case */ if (chip->hpwr_vreg) { rc = haptics_get_vmax_headroom_mv(chip, &hdrm_mv); if (rc < 0) goto unlock; vmax_mv = chip->hpwr_voltage_mv - hdrm_mv; } /* configure VMAX in case it was changed in previous effect playing */ rc = haptics_set_vmax_mv(chip, chip->config.vmax_mv); rc = haptics_set_vmax_mv(chip, vmax_mv); if (rc < 0) goto unlock; Loading Loading @@ -1899,6 +2002,26 @@ static int haptics_load_periodic_effect(struct haptics_chip *chip, return rc; } static u8 get_direct_play_max_amplitude(struct haptics_chip *chip) { u32 amplitude = DIRECT_PLAY_MAX_AMPLITUDE, hdrm_mv; int rc; if (chip->hpwr_vreg) { rc = haptics_get_vmax_headroom_mv(chip, &hdrm_mv); if (rc < 0) return 0; amplitude *= chip->config.vmax_mv; amplitude /= (chip->hpwr_voltage_mv - hdrm_mv); if (amplitude > DIRECT_PLAY_MAX_AMPLITUDE) amplitude = DIRECT_PLAY_MAX_AMPLITUDE; } dev_dbg(chip->dev, "max amplitude for direct play: %#x\n", amplitude); return (u8)amplitude; } static int haptics_upload_effect(struct input_dev *dev, struct ff_effect *effect, struct ff_effect *old) { Loading @@ -1912,9 +2035,10 @@ static int haptics_upload_effect(struct input_dev *dev, case FF_CONSTANT: length_us = effect->replay.length * USEC_PER_MSEC; level = effect->u.constant.level; tmp = level * DIRECT_PLAY_MAX_AMPLITUDE; tmp = get_direct_play_max_amplitude(chip); tmp *= level; amplitude = tmp / 0x7fff; dev_dbg(chip->dev, "upload constant effect, length = %dus, amplitude = %d\n", dev_dbg(chip->dev, "upload constant effect, length = %dus, amplitude = %#x\n", length_us, amplitude); haptics_load_constant_effect(chip, amplitude); if (rc < 0) { Loading Loading @@ -1961,7 +2085,11 @@ static int haptics_upload_effect(struct input_dev *dev, return -EINVAL; } return 0; rc = haptics_enable_hpwr_vreg(chip, true); if (rc < 0) dev_err(chip->dev, "enable hpwr_vreg failed, rc=%d\n"); return rc; } static void haptics_fifo_empty_irq_config(struct haptics_chip *chip, Loading Loading @@ -2065,7 +2193,11 @@ static int haptics_erase(struct input_dev *dev, int effect_id) } } return 0; rc = haptics_enable_hpwr_vreg(chip, false); if (rc < 0) dev_err(chip->dev, "disable hpwr_vreg failed, rc=%d\n"); return rc; } static void haptics_set_gain(struct input_dev *dev, u16 gain) Loading @@ -2073,7 +2205,7 @@ static void haptics_set_gain(struct input_dev *dev, u16 gain) struct haptics_chip *chip = input_get_drvdata(dev); struct haptics_hw_config *config = &chip->config; struct haptics_play_info *play = &chip->play; u32 vmax_mv; u32 vmax_mv, amplitude; if (gain == 0) return; Loading @@ -2081,6 +2213,20 @@ static void haptics_set_gain(struct input_dev *dev, u16 gain) if (gain > 0x7fff) gain = 0x7fff; dev_dbg(chip->dev, "Set gain: %#x\n", gain); /* scale amplitude when playing in DIRECT_PLAY mode */ if (chip->play.pattern_src == DIRECT_PLAY) { amplitude = get_direct_play_max_amplitude(chip); amplitude *= gain; amplitude /= 0x7fff; dev_dbg(chip->dev, "Set amplitude: %#x\n", amplitude); haptics_set_direct_play(chip, (u8)amplitude); return; } /* scale Vmax when playing in other modes */ vmax_mv = config->vmax_mv; if (play->effect) vmax_mv = play->effect->vmax_mv; Loading Loading @@ -3347,6 +3493,38 @@ static int haptics_get_revision(struct haptics_chip *chip) return 0; } static int haptics_parse_hpwr_vreg_dt(struct haptics_chip *chip) { struct device_node *node = chip->dev->of_node; int rc; if (!of_find_property(node, "qcom,hpwr-supply", NULL)) return 0; chip->hpwr_vreg = devm_regulator_get(chip->dev, "qcom,hpwr"); if (IS_ERR(chip->hpwr_vreg)) { rc = PTR_ERR(chip->hpwr_vreg); if (rc != -EPROBE_DEFER) dev_err(chip->dev, "Failed to get qcom,hpwr-supply, rc=%d\n", rc); return rc; } rc = of_property_read_u32(node, "qcom,hpwr-voltage-mv", &chip->hpwr_voltage_mv); if (rc < 0) { dev_err(chip->dev, "Failed to read qcom,hpwr-voltage-mv, rc=%d\n", rc); return rc; } if (chip->hpwr_voltage_mv == 0 || chip->hpwr_voltage_mv > NON_HBOOST_MAX_VMAX_MV) return -EINVAL; return 0; } static int haptics_parse_dt(struct haptics_chip *chip) { struct haptics_hw_config *config = &chip->config; Loading @@ -3355,6 +3533,10 @@ static int haptics_parse_dt(struct haptics_chip *chip) const __be32 *addr; int rc = 0, tmp; rc = haptics_parse_hpwr_vreg_dt(chip); if (rc < 0) return rc; if (of_find_property(node, "nvmem-cells", NULL)) { chip->cl_brake_nvmem = devm_nvmem_cell_get(chip->dev, "hap_cl_brake"); Loading Loading @@ -3619,9 +3801,24 @@ static int haptics_pbs_trigger_isc_config(struct haptics_chip *chip) #define MAX_SWEEP_STEPS 5 #define MAX_IMPEDANCE_MOHM 40000 #define MIN_ISC_MA 250 #define MIN_DUTY_MILLI_PCT 0 #define MAX_DUTY_MILLI_PCT 100000 #define LRA_CONFIG_REGS 3 static u32 get_lra_impedance_capable_max(struct haptics_chip *chip) { u32 mohms = MAX_IMPEDANCE_MOHM; if (chip->clamp_at_5v) mohms = MAX_IMPEDANCE_MOHM / 2; if (chip->hpwr_vreg) mohms = (chip->hpwr_voltage_mv * 1000) / MIN_ISC_MA; dev_dbg(chip->dev, "LRA impedance capable max: %u mohms\n", mohms); return mohms; } static int haptics_detect_lra_impedance(struct haptics_chip *chip) { int rc, i; Loading @@ -3633,7 +3830,7 @@ static int haptics_detect_lra_impedance(struct haptics_chip *chip) struct haptics_reg_info backup[LRA_CONFIG_REGS]; u8 val; u32 duty_milli_pct, low_milli_pct, high_milli_pct; u32 amplitude, lra_min_mohms, lra_max_mohms; u32 amplitude, lra_min_mohms, lra_max_mohms, capability_mohms; if (chip->cfg_revision == HAP_CFG_V1) { dev_dbg(chip->dev, "HAP_CFG V1.0 doesn't support impedance detection\n"); Loading Loading @@ -3662,6 +3859,10 @@ static int haptics_detect_lra_impedance(struct haptics_chip *chip) goto restore; } rc = haptics_enable_hpwr_vreg(chip, true); if (rc < 0) goto restore; low_milli_pct = MIN_DUTY_MILLI_PCT; high_milli_pct = MAX_DUTY_MILLI_PCT; /* Sweep duty cycle using binary approach */ Loading Loading @@ -3704,11 +3905,12 @@ static int haptics_detect_lra_impedance(struct haptics_chip *chip) usleep_range(4000, 5000); } lra_min_mohms = low_milli_pct * MAX_IMPEDANCE_MOHM / 100000; lra_max_mohms = high_milli_pct * MAX_IMPEDANCE_MOHM / 100000; capability_mohms = get_lra_impedance_capable_max(chip); lra_min_mohms = low_milli_pct * capability_mohms / 100000; lra_max_mohms = high_milli_pct * capability_mohms / 100000; if (lra_min_mohms == 0) dev_warn(chip->dev, "Short circuit detected!\n"); else if (lra_max_mohms == MAX_IMPEDANCE_MOHM) else if (lra_max_mohms >= capability_mohms) dev_warn(chip->dev, "Open circuit detected!\n"); else dev_dbg(chip->dev, "LRA impedance is between %u - %u mohms\n", Loading @@ -3716,9 +3918,14 @@ static int haptics_detect_lra_impedance(struct haptics_chip *chip) chip->config.lra_min_mohms = lra_min_mohms; chip->config.lra_max_mohms = lra_max_mohms; chip->config.lra_open_mohms = capability_mohms; restore: /* Disable play in case it's not been disabled */ haptics_enable_play(chip, false); rc = haptics_enable_hpwr_vreg(chip, false); if (rc < 0) return rc; /* Trigger PBS to restore 1500mA ISC setting */ rc = haptics_pbs_trigger_isc_config(chip); if (rc < 0) Loading @@ -3739,7 +3946,8 @@ static int haptics_detect_lra_impedance(struct haptics_chip *chip) static int haptics_detect_lra_frequency(struct haptics_chip *chip) { int rc; u8 autores_cfg; u8 autores_cfg, amplitude; u32 vmax_mv = chip->config.vmax_mv; rc = haptics_read(chip, chip->cfg_addr_base, HAP_CFG_AUTORES_CFG_REG, &autores_cfg, 1); Loading @@ -3760,15 +3968,24 @@ static int haptics_detect_lra_frequency(struct haptics_chip *chip) if (rc < 0) goto restore; rc = haptics_set_vmax_mv(chip, chip->config.vmax_mv); rc = haptics_set_vmax_headroom_mv(chip, LRA_CALIBRATION_VMAX_HDRM_MV); if (rc < 0) goto restore; rc = haptics_set_vmax_headroom_mv(chip, LRA_CALIBRATION_VMAX_HDRM_MV); /* Fix Vmax to (hpwr_vreg_mv - hdrm_mv) in non-HBOOST regulator case */ if (chip->hpwr_vreg) vmax_mv = chip->hpwr_voltage_mv - LRA_CALIBRATION_VMAX_HDRM_MV; rc = haptics_set_vmax_mv(chip, vmax_mv); if (rc < 0) goto restore; rc = haptics_set_direct_play(chip, DIRECT_PLAY_MAX_AMPLITUDE); amplitude = get_direct_play_max_amplitude(chip); rc = haptics_set_direct_play(chip, amplitude); if (rc < 0) goto restore; rc = haptics_enable_hpwr_vreg(chip, true); if (rc < 0) goto restore; Loading @@ -3793,6 +4010,10 @@ static int haptics_detect_lra_frequency(struct haptics_chip *chip) restore: /* Disable play in case it's not been disabled */ haptics_enable_play(chip, false); rc = haptics_enable_hpwr_vreg(chip, false); if (rc < 0) return rc; rc = haptics_write(chip, chip->cfg_addr_base, HAP_CFG_AUTORES_CFG_REG, &autores_cfg, 1); Loading Loading @@ -3889,7 +4110,7 @@ static ssize_t lra_impedance_show(struct class *c, return -EINVAL; else if (chip->config.lra_min_mohms == 0) return scnprintf(buf, PAGE_SIZE, "%s\n", "Short circuit"); else if (chip->config.lra_max_mohms == MAX_IMPEDANCE_MOHM) else if (chip->config.lra_max_mohms >= chip->config.lra_open_mohms) return scnprintf(buf, PAGE_SIZE, "%s\n", "Open circuit"); else return scnprintf(buf, PAGE_SIZE, "%u ~ %u mohms\n", Loading Loading @@ -4071,6 +4292,10 @@ static int haptics_suspend(struct device *dev) return rc; } rc = haptics_enable_hpwr_vreg(chip, false); if (rc < 0) return rc; return haptics_write(chip, chip->cfg_addr_base, HAP_CFG_EN_CTL_REG, &val, 1); } Loading