Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

input: pm8xxx-vibrator: add new SPMI vibrator support

Add support for a new SPMI vibrator module which is very similar
to the vibrator module inside PM8916 but has a finer drive voltage
step and different output voltage range, its drive level control
is expanded across 2 registers. The vibrator module can be found
in following Qualcomm PMICs: PMI632, PM7250B, PM7325B, PM7550BA.

Signed-off-by: Fenglin Wu <quic_fenglinw@quicinc.com>
Reviewed-by: Dmitry Baryshkov <dmitry.baryshkov@linaro.org>
Reviewed-by: Konrad Dybcio <konrad.dybcio@linaro.org>
Link: https://lore.kernel.org/r/20240416-pm8xxx-vibrator-new-design-v11-3-7b1c951e1515@quicinc.com
Signed-off-by: Dmitry Torokhov <dmitry.torokhov@gmail.com>

authored by

Fenglin Wu and committed by
Dmitry Torokhov
9e063169 ca7755ad

+43 -9
+43 -9
drivers/input/misc/pm8xxx-vibrator.c
··· 11 11 #include <linux/regmap.h> 12 12 #include <linux/slab.h> 13 13 14 - #define VIB_MAX_LEVEL_mV (3100) 15 - #define VIB_MIN_LEVEL_mV (1200) 16 - #define VIB_PER_STEP_mV (100) 17 - #define VIB_MAX_LEVELS (VIB_MAX_LEVEL_mV - VIB_MIN_LEVEL_mV + VIB_PER_STEP_mV) 14 + #define VIB_MAX_LEVEL_mV(vib) (vib->drv2_addr ? 3544 : 3100) 15 + #define VIB_MIN_LEVEL_mV(vib) (vib->drv2_addr ? 1504 : 1200) 16 + #define VIB_PER_STEP_mV(vib) (vib->drv2_addr ? 8 : 100) 17 + #define VIB_MAX_LEVELS(vib) \ 18 + (VIB_MAX_LEVEL_mV(vib) - VIB_MIN_LEVEL_mV(vib) + VIB_PER_STEP_mV(vib)) 18 19 19 20 #define MAX_FF_SPEED 0xff 20 21 ··· 26 25 unsigned int drv_offset; 27 26 unsigned int drv_mask; 28 27 unsigned int drv_shift; 28 + unsigned int drv2_offset; 29 + unsigned int drv2_mask; 30 + unsigned int drv2_shift; 29 31 unsigned int drv_en_manual_mask; 32 + bool drv_in_step; 30 33 }; 31 34 32 35 static const struct pm8xxx_regs pm8058_regs = { ··· 38 33 .drv_mask = GENMASK(7, 3), 39 34 .drv_shift = 3, 40 35 .drv_en_manual_mask = 0xfc, 36 + .drv_in_step = true, 41 37 }; 42 38 43 39 static struct pm8xxx_regs pm8916_regs = { ··· 48 42 .drv_mask = GENMASK(4, 0), 49 43 .drv_shift = 0, 50 44 .drv_en_manual_mask = 0, 45 + .drv_in_step = true, 46 + }; 47 + 48 + static struct pm8xxx_regs pmi632_regs = { 49 + .enable_offset = 0x46, 50 + .enable_mask = BIT(7), 51 + .drv_offset = 0x40, 52 + .drv_mask = GENMASK(7, 0), 53 + .drv_shift = 0, 54 + .drv2_offset = 0x41, 55 + .drv2_mask = GENMASK(3, 0), 56 + .drv2_shift = 8, 57 + .drv_en_manual_mask = 0, 58 + .drv_in_step = false, 51 59 }; 52 60 53 61 /** ··· 72 52 * @regs: registers' info 73 53 * @enable_addr: vibrator enable register 74 54 * @drv_addr: vibrator drive strength register 55 + * @drv2_addr: vibrator drive strength upper byte register 75 56 * @speed: speed of vibration set from userland 76 57 * @active: state of vibrator 77 58 * @level: level of vibration to set in the chip ··· 85 64 const struct pm8xxx_regs *regs; 86 65 unsigned int enable_addr; 87 66 unsigned int drv_addr; 67 + unsigned int drv2_addr; 88 68 int speed; 89 69 int level; 90 70 bool active; ··· 103 81 unsigned int val = vib->reg_vib_drv; 104 82 const struct pm8xxx_regs *regs = vib->regs; 105 83 84 + if (regs->drv_in_step) 85 + vib->level /= VIB_PER_STEP_mV(vib); 86 + 106 87 if (on) 107 88 val |= (vib->level << regs->drv_shift) & regs->drv_mask; 108 89 else ··· 116 91 return rc; 117 92 118 93 vib->reg_vib_drv = val; 94 + 95 + if (regs->drv2_mask) { 96 + val = vib->level << regs->drv2_shift; 97 + rc = regmap_write_bits(vib->regmap, vib->drv2_addr, 98 + regs->drv2_mask, on ? val : 0); 99 + if (rc < 0) 100 + return rc; 101 + } 119 102 120 103 if (regs->enable_mask) 121 104 rc = regmap_update_bits(vib->regmap, vib->enable_addr, ··· 147 114 return; 148 115 149 116 /* 150 - * pmic vibrator supports voltage ranges from 1.2 to 3.1V, so 117 + * pmic vibrator supports voltage ranges from MIN_LEVEL to MAX_LEVEL, so 151 118 * scale the level to fit into these ranges. 152 119 */ 153 120 if (vib->speed) { 154 121 vib->active = true; 155 - vib->level = ((VIB_MAX_LEVELS * vib->speed) / MAX_FF_SPEED) + 156 - VIB_MIN_LEVEL_mV; 157 - vib->level /= VIB_PER_STEP_mV; 122 + vib->level = VIB_MIN_LEVEL_mV(vib); 123 + vib->level += mult_frac(VIB_MAX_LEVELS(vib), vib->speed, MAX_FF_SPEED); 158 124 } else { 159 125 vib->active = false; 160 - vib->level = VIB_MIN_LEVEL_mV / VIB_PER_STEP_mV; 126 + vib->level = VIB_MIN_LEVEL_mV(vib); 161 127 } 162 128 163 129 pm8xxx_vib_set(vib, vib->active); ··· 229 197 regs = of_device_get_match_data(&pdev->dev); 230 198 vib->enable_addr = reg_base + regs->enable_offset; 231 199 vib->drv_addr = reg_base + regs->drv_offset; 200 + vib->drv2_addr = reg_base + regs->drv2_offset; 232 201 233 202 /* operate in manual mode */ 234 203 error = regmap_read(vib->regmap, vib->drv_addr, &val); ··· 284 251 { .compatible = "qcom,pm8058-vib", .data = &pm8058_regs }, 285 252 { .compatible = "qcom,pm8921-vib", .data = &pm8058_regs }, 286 253 { .compatible = "qcom,pm8916-vib", .data = &pm8916_regs }, 254 + { .compatible = "qcom,pmi632-vib", .data = &pmi632_regs }, 287 255 { } 288 256 }; 289 257 MODULE_DEVICE_TABLE(of, pm8xxx_vib_id_table);