1 /* Copyright (c) 2014-2017, The Linux Foundation. All rights reserved.
2 * Copyright (C) 2018 XiaoMi, Inc.
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License version 2 and
6 * only version 2 as published by the Free Software Foundation.
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
14 #include <linux/module.h>
15 #include <linux/init.h>
16 #include <linux/kernel.h>
17 #include <linux/regmap.h>
18 #include <linux/errno.h>
19 #include <linux/leds.h>
20 #include <linux/slab.h>
21 #include <linux/of_device.h>
22 #include <linux/of_address.h>
23 #include <linux/spmi.h>
24 #include <linux/platform_device.h>
25 #include <linux/interrupt.h>
26 #include <linux/err.h>
27 #include <linux/delay.h>
28 #include <linux/leds-qpnp-wled.h>
29 #include <linux/qpnp/qpnp-revid.h>
32 #define QPNP_WLED_CTRL_BASE "qpnp-wled-ctrl-base"
33 #define QPNP_WLED_SINK_BASE "qpnp-wled-sink-base"
36 #define QPNP_WLED_FAULT_STATUS(b) (b + 0x08)
37 #define QPNP_WLED_INT_RT_STS(b) (b + 0x10)
38 #define QPNP_WLED_EN_REG(b) (b + 0x46)
39 #define QPNP_WLED_FDBK_OP_REG(b) (b + 0x48)
40 #define QPNP_WLED_VREF_REG(b) (b + 0x49)
41 #define QPNP_WLED_BOOST_DUTY_REG(b) (b + 0x4B)
42 #define QPNP_WLED_SWITCH_FREQ_REG(b) (b + 0x4C)
43 #define QPNP_WLED_OVP_REG(b) (b + 0x4D)
44 #define QPNP_WLED_ILIM_REG(b) (b + 0x4E)
45 #define QPNP_WLED_AMOLED_VOUT_REG(b) (b + 0x4F)
46 #define QPNP_WLED_SOFTSTART_RAMP_DLY(b) (b + 0x53)
47 #define QPNP_WLED_VLOOP_COMP_RES_REG(b) (b + 0x55)
48 #define QPNP_WLED_VLOOP_COMP_GM_REG(b) (b + 0x56)
49 #define QPNP_WLED_EN_PSM_REG(b) (b + 0x5A)
50 #define QPNP_WLED_PSM_CTRL_REG(b) (b + 0x5B)
51 #define QPNP_WLED_LCD_AUTO_PFM_REG(b) (b + 0x5C)
52 #define QPNP_WLED_SC_PRO_REG(b) (b + 0x5E)
53 #define QPNP_WLED_SWIRE_AVDD_REG(b) (b + 0x5F)
54 #define QPNP_WLED_CTRL_SPARE_REG(b) (b + 0xDF)
55 #define QPNP_WLED_TEST1_REG(b) (b + 0xE2)
56 #define QPNP_WLED_TEST4_REG(b) (b + 0xE5)
57 #define QPNP_WLED_REF_7P7_TRIM_REG(b) (b + 0xF2)
59 #define QPNP_WLED_7P7_TRIM_MASK GENMASK(3, 0)
60 #define QPNP_WLED_EN_MASK 0x7F
61 #define QPNP_WLED_EN_SHIFT 7
62 #define QPNP_WLED_FDBK_OP_MASK 0xF8
63 #define QPNP_WLED_VREF_MASK GENMASK(3, 0)
65 #define QPNP_WLED_VLOOP_COMP_RES_MASK 0xF0
66 #define QPNP_WLED_VLOOP_COMP_RES_OVERWRITE 0x80
67 #define QPNP_WLED_LOOP_COMP_RES_STEP_KOHM 20
68 #define QPNP_WLED_LOOP_COMP_RES_MIN_KOHM 20
69 #define QPNP_WLED_LOOP_COMP_RES_MAX_KOHM 320
70 #define QPNP_WLED_VLOOP_COMP_GM_MASK GENMASK(3, 0)
71 #define QPNP_WLED_VLOOP_COMP_GM_OVERWRITE 0x80
72 #define QPNP_WLED_VLOOP_COMP_AUTO_GM_EN BIT(6)
73 #define QPNP_WLED_VLOOP_COMP_AUTO_GM_THRESH_MASK GENMASK(5, 4)
74 #define QPNP_WLED_VLOOP_COMP_AUTO_GM_THRESH_SHIFT 4
75 #define QPNP_WLED_LOOP_EA_GM_DFLT_AMOLED_PMI8994 0x03
76 #define QPNP_WLED_LOOP_GM_DFLT_AMOLED_PMI8998 0x09
77 #define QPNP_WLED_LOOP_GM_DFLT_WLED 0x09
78 #define QPNP_WLED_LOOP_EA_GM_MIN 0x0
79 #define QPNP_WLED_LOOP_EA_GM_MAX 0xF
80 #define QPNP_WLED_LOOP_AUTO_GM_THRESH_MAX 3
81 #define QPNP_WLED_LOOP_AUTO_GM_DFLT_THRESH 1
82 #define QPNP_WLED_VREF_PSM_MASK 0xF8
83 #define QPNP_WLED_VREF_PSM_STEP_MV 50
84 #define QPNP_WLED_VREF_PSM_MIN_MV 400
85 #define QPNP_WLED_VREF_PSM_MAX_MV 750
86 #define QPNP_WLED_VREF_PSM_DFLT_AMOLED_MV 450
87 #define QPNP_WLED_PSM_OVERWRITE_BIT BIT(7)
88 #define QPNP_WLED_LCD_AUTO_PFM_DFLT_THRESH 1
89 #define QPNP_WLED_LCD_AUTO_PFM_THRESH_MAX 0xF
90 #define QPNP_WLED_LCD_AUTO_PFM_EN_SHIFT 7
91 #define QPNP_WLED_LCD_AUTO_PFM_EN_BIT BIT(7)
92 #define QPNP_WLED_LCD_AUTO_PFM_THRESH_MASK GENMASK(3, 0)
93 #define QPNP_WLED_EN_PSM_BIT BIT(7)
95 #define QPNP_WLED_ILIM_MASK GENMASK(2, 0)
96 #define QPNP_WLED_ILIM_OVERWRITE BIT(7)
97 #define PMI8994_WLED_ILIM_MIN_MA 105
98 #define PMI8994_WLED_ILIM_MAX_MA 1980
99 #define PMI8994_WLED_DFLT_ILIM_MA 980
100 #define PMI8994_AMOLED_DFLT_ILIM_MA 385
101 #define PMI8998_WLED_ILIM_MAX_MA 1500
102 #define PMI8998_WLED_DFLT_ILIM_MA 970
103 #define PMI8998_AMOLED_DFLT_ILIM_MA 620
104 #define QPNP_WLED_BOOST_DUTY_MASK 0xFC
105 #define QPNP_WLED_BOOST_DUTY_STEP_NS 52
106 #define QPNP_WLED_BOOST_DUTY_MIN_NS 26
107 #define QPNP_WLED_BOOST_DUTY_MAX_NS 156
108 #define QPNP_WLED_DEF_BOOST_DUTY_NS 104
109 #define QPNP_WLED_SWITCH_FREQ_MASK GENMASK(3, 0)
110 #define QPNP_WLED_SWITCH_FREQ_OVERWRITE BIT(7)
111 #define QPNP_WLED_OVP_MASK GENMASK(1, 0)
112 #define QPNP_WLED_TEST4_EN_DEB_BYPASS_ILIM_BIT BIT(6)
113 #define QPNP_WLED_TEST4_EN_SH_FOR_SS_BIT BIT(5)
114 #define QPNP_WLED_TEST4_EN_CLAMP_BIT BIT(4)
115 #define QPNP_WLED_TEST4_EN_SOFT_START_BIT BIT(1)
116 #define QPNP_WLED_TEST4_EN_VREF_UP \
117 (QPNP_WLED_TEST4_EN_SH_FOR_SS_BIT | \
118 QPNP_WLED_TEST4_EN_CLAMP_BIT | \
119 QPNP_WLED_TEST4_EN_SOFT_START_BIT)
120 #define QPNP_WLED_TEST4_EN_IIND_UP 0x1
121 #define QPNP_WLED_ILIM_FAULT_BIT BIT(0)
122 #define QPNP_WLED_OVP_FAULT_BIT BIT(1)
123 #define QPNP_WLED_SC_FAULT_BIT BIT(2)
124 #define QPNP_WLED_OVP_FLT_RT_STS_BIT BIT(1)
126 /* QPNP_WLED_SOFTSTART_RAMP_DLY */
127 #define SOFTSTART_OVERWRITE_BIT BIT(7)
128 #define SOFTSTART_RAMP_DELAY_MASK GENMASK(2, 0)
131 #define QPNP_WLED_CURR_SINK_REG(b) (b + 0x46)
132 #define QPNP_WLED_SYNC_REG(b) (b + 0x47)
133 #define QPNP_WLED_MOD_REG(b) (b + 0x4A)
134 #define QPNP_WLED_HYB_THRES_REG(b) (b + 0x4B)
135 #define QPNP_WLED_MOD_EN_REG(b, n) (b + 0x50 + (n * 0x10))
136 #define QPNP_WLED_SYNC_DLY_REG(b, n) (QPNP_WLED_MOD_EN_REG(b, n) + 0x01)
137 #define QPNP_WLED_FS_CURR_REG(b, n) (QPNP_WLED_MOD_EN_REG(b, n) + 0x02)
138 #define QPNP_WLED_CABC_REG(b, n) (QPNP_WLED_MOD_EN_REG(b, n) + 0x06)
139 #define QPNP_WLED_BRIGHT_LSB_REG(b, n) (QPNP_WLED_MOD_EN_REG(b, n) + 0x07)
140 #define QPNP_WLED_BRIGHT_MSB_REG(b, n) (QPNP_WLED_MOD_EN_REG(b, n) + 0x08)
141 #define QPNP_WLED_SINK_TEST5_REG(b) (b + 0xE6)
143 #define QPNP_WLED_MOD_FREQ_1200_KHZ 1200
144 #define QPNP_WLED_MOD_FREQ_2400_KHZ 2400
145 #define QPNP_WLED_MOD_FREQ_9600_KHZ 9600
146 #define QPNP_WLED_MOD_FREQ_19200_KHZ 19200
147 #define QPNP_WLED_MOD_FREQ_MASK 0x3F
148 #define QPNP_WLED_MOD_FREQ_SHIFT 6
149 #define QPNP_WLED_ACC_CLK_FREQ_MASK 0xE7
150 #define QPNP_WLED_ACC_CLK_FREQ_SHIFT 3
151 #define QPNP_WLED_PHASE_STAG_MASK 0xDF
152 #define QPNP_WLED_PHASE_STAG_SHIFT 5
153 #define QPNP_WLED_DIM_RES_MASK 0xFD
154 #define QPNP_WLED_DIM_RES_SHIFT 1
155 #define QPNP_WLED_DIM_HYB_MASK 0xFB
156 #define QPNP_WLED_DIM_HYB_SHIFT 2
157 #define QPNP_WLED_DIM_ANA_MASK 0xFE
158 #define QPNP_WLED_HYB_THRES_MASK 0xF8
159 #define QPNP_WLED_HYB_THRES_MIN 78
160 #define QPNP_WLED_DEF_HYB_THRES 625
161 #define QPNP_WLED_HYB_THRES_MAX 10000
162 #define QPNP_WLED_MOD_EN_MASK 0x7F
163 #define QPNP_WLED_MOD_EN_SHFT 7
164 #define QPNP_WLED_MOD_EN 1
165 #define QPNP_WLED_GATE_DRV_MASK 0xFE
166 #define QPNP_WLED_SYNC_DLY_MASK GENMASK(2, 0)
167 #define QPNP_WLED_SYNC_DLY_MIN_US 0
168 #define QPNP_WLED_SYNC_DLY_MAX_US 1400
169 #define QPNP_WLED_SYNC_DLY_STEP_US 200
170 #define QPNP_WLED_DEF_SYNC_DLY_US 400
171 #define QPNP_WLED_FS_CURR_MASK GENMASK(3, 0)
172 #define QPNP_WLED_FS_CURR_MIN_UA 0
173 #define QPNP_WLED_FS_CURR_MAX_UA 30000
174 #define QPNP_WLED_FS_CURR_STEP_UA 2500
175 #define QPNP_WLED_CABC_MASK 0x80
176 #define QPNP_WLED_CABC_SHIFT 7
177 #define QPNP_WLED_CURR_SINK_SHIFT 4
178 #define QPNP_WLED_CURR_SINK_MASK GENMASK(7, 4)
179 #define QPNP_WLED_BRIGHT_LSB_MASK 0xFF
180 #define QPNP_WLED_BRIGHT_MSB_SHIFT 8
181 #define QPNP_WLED_BRIGHT_MSB_MASK 0x0F
182 #define QPNP_WLED_SYNC 0x0F
183 #define QPNP_WLED_SYNC_RESET 0x00
185 #define QPNP_WLED_SINK_TEST5_HYB 0x14
186 #define QPNP_WLED_SINK_TEST5_DIG 0x1E
187 #define QPNP_WLED_SINK_TEST5_HVG_PULL_STR_BIT BIT(3)
189 #define QPNP_WLED_SWITCH_FREQ_600_KHZ_CODE 0x0F
190 #define QPNP_WLED_SWITCH_FREQ_800_KHZ_CODE 0x0B
191 #define QPNP_WLED_SWITCH_FREQ_1600_KHZ_CODE 0x05
193 #define QPNP_WLED_DISP_SEL_REG(b) (b + 0x44)
194 #define QPNP_WLED_MODULE_RDY_REG(b) (b + 0x45)
195 #define QPNP_WLED_MODULE_EN_REG(b) (b + 0x46)
196 #define QPNP_WLED_MODULE_RDY_MASK 0x7F
197 #define QPNP_WLED_MODULE_RDY_SHIFT 7
198 #define QPNP_WLED_MODULE_EN_MASK BIT(7)
199 #define QPNP_WLED_MODULE_EN_SHIFT 7
200 #define QPNP_WLED_DISP_SEL_MASK 0x7F
201 #define QPNP_WLED_DISP_SEL_SHIFT 7
202 #define QPNP_WLED_EN_SC_DEB_CYCLES_MASK 0x79
203 #define QPNP_WLED_EN_DEB_CYCLES_MASK 0xF9
204 #define QPNP_WLED_EN_SC_SHIFT 7
205 #define QPNP_WLED_SC_PRO_EN_DSCHGR 0x8
206 #define QPNP_WLED_SC_DEB_CYCLES_MIN 2
207 #define QPNP_WLED_SC_DEB_CYCLES_MAX 16
208 #define QPNP_WLED_SC_DEB_CYCLES_SUB 2
209 #define QPNP_WLED_SC_DEB_CYCLES_DFLT 4
210 #define QPNP_WLED_EXT_FET_DTEST2 0x09
212 #define QPNP_WLED_SEC_ACCESS_REG(b) (b + 0xD0)
213 #define QPNP_WLED_SEC_UNLOCK 0xA5
215 #define NUM_DDIC_CODES 256
216 #define QPNP_WLED_MAX_STRINGS 4
217 #define QPNP_PM660_WLED_MAX_STRINGS 3
218 #define WLED_MAX_LEVEL_4095 4095
219 #define QPNP_WLED_RAMP_DLY_MS 20
220 #define QPNP_WLED_TRIGGER_NONE "none"
221 #define QPNP_WLED_STR_SIZE 20
222 #define QPNP_WLED_MIN_MSLEEP 20
223 #define QPNP_WLED_SC_DLY_MS 20
224 #define QPNP_WLED_SOFT_START_DLY_US 10000
226 #define NUM_SUPPORTED_AVDD_VOLTAGES 6
227 #define QPNP_WLED_DFLT_AVDD_MV 7600
228 #define QPNP_WLED_AVDD_MIN_MV 5650
229 #define QPNP_WLED_AVDD_MAX_MV 7900
230 #define QPNP_WLED_AVDD_STEP_MV 150
231 #define QPNP_WLED_AVDD_MIN_TRIM_VAL 0x0
232 #define QPNP_WLED_AVDD_MAX_TRIM_VAL 0xF
233 #define QPNP_WLED_AVDD_SEL_SPMI_BIT BIT(7)
234 #define QPNP_WLED_AVDD_SET_BIT BIT(4)
236 #define NUM_SUPPORTED_OVP_THRESHOLDS 4
237 #define NUM_SUPPORTED_ILIM_THRESHOLDS 8
239 #define QPNP_WLED_AVDD_MV_TO_REG(val) \
240 ((val - QPNP_WLED_AVDD_MIN_MV) / QPNP_WLED_AVDD_STEP_MV)
242 /* output feedback mode */
243 enum qpnp_wled_fdbk_op {
245 QPNP_WLED_FDBK_WLED1,
246 QPNP_WLED_FDBK_WLED2,
247 QPNP_WLED_FDBK_WLED3,
248 QPNP_WLED_FDBK_WLED4,
252 enum qpnp_wled_dim_mode {
253 QPNP_WLED_DIM_ANALOG,
254 QPNP_WLED_DIM_DIGITAL,
255 QPNP_WLED_DIM_HYBRID,
258 /* wled ctrl debug registers */
259 static u8 qpnp_wled_ctrl_dbg_regs[] = {
260 0x44, 0x46, 0x48, 0x49, 0x4b, 0x4c, 0x4d, 0x4e, 0x50, 0x51, 0x52, 0x53,
261 0x54, 0x55, 0x56, 0x57, 0x58, 0x5a, 0x5b, 0x5d, 0x5e, 0xe2
264 /* wled sink debug registers */
265 static u8 qpnp_wled_sink_dbg_regs[] = {
266 0x46, 0x47, 0x48, 0x4a, 0x4b,
267 0x50, 0x51, 0x52, 0x53, 0x56, 0x57, 0x58,
268 0x60, 0x61, 0x62, 0x63, 0x66, 0x67, 0x68,
269 0x70, 0x71, 0x72, 0x73, 0x76, 0x77, 0x78,
270 0x80, 0x81, 0x82, 0x83, 0x86, 0x87, 0x88,
274 static int qpnp_wled_avdd_target_voltages[NUM_SUPPORTED_AVDD_VOLTAGES] = {
275 7900, 7600, 7300, 6400, 6100, 5800,
278 static u8 qpnp_wled_ovp_reg_settings[NUM_SUPPORTED_AVDD_VOLTAGES] = {
279 0x0, 0x0, 0x1, 0x2, 0x2, 0x3,
282 static int qpnp_wled_avdd_trim_adjustments[NUM_SUPPORTED_AVDD_VOLTAGES] = {
286 static int qpnp_wled_ovp_thresholds_pmi8994[NUM_SUPPORTED_OVP_THRESHOLDS] = {
287 31000, 29500, 19400, 17800,
290 static int qpnp_wled_ovp_thresholds_pmi8998[NUM_SUPPORTED_OVP_THRESHOLDS] = {
291 31100, 29600, 19600, 18100,
294 static int qpnp_wled_ilim_settings_pmi8994[NUM_SUPPORTED_ILIM_THRESHOLDS] = {
295 105, 385, 660, 980, 1150, 1420, 1700, 1980,
298 static int qpnp_wled_ilim_settings_pmi8998[NUM_SUPPORTED_ILIM_THRESHOLDS] = {
299 105, 280, 450, 620, 970, 1150, 1300, 1500,
302 struct wled_vref_setting {
309 static struct wled_vref_setting vref_setting_pmi8994 = {
310 300000, 675000, 25000, 350000,
312 static struct wled_vref_setting vref_setting_pmi8998 = {
313 60000, 397500, 22500, 127500,
317 * qpnp_wled - wed data structure
318 * @ cdev - led class device
319 * @ pdev - platform device
320 * @ work - worker for led operation
321 * @ wq - workqueue for setting brightness level
322 * @ lock - mutex lock for exclusive access
323 * @ fdbk_op - output feedback mode
324 * @ dim_mode - dimming mode
325 * @ ovp_irq - over voltage protection irq
326 * @ sc_irq - short circuit irq
327 * @ sc_cnt - short circuit irq count
328 * @ avdd_target_voltage_mv - target voltage for AVDD module in mV
329 * @ ctrl_base - base address for wled ctrl
330 * @ sink_base - base address for wled sink
331 * @ mod_freq_khz - modulator frequency in KHZ
332 * @ hyb_thres - threshold for hybrid dimming
333 * @ sync_dly_us - sync delay in us
334 * @ vref_uv - ref voltage in uv
335 * @ vref_psm_mv - ref psm voltage in mv
336 * @ loop_comp_res_kohm - control to select the compensation resistor
337 * @ loop_ea_gm - control to select the gm for the gm stage in control loop
338 * @ sc_deb_cycles - debounce time for short circuit detection
339 * @ switch_freq_khz - switching frequency in KHZ
340 * @ ovp_mv - over voltage protection in mv
341 * @ ilim_ma - current limiter in ma
342 * @ boost_duty_ns - boost duty cycle in ns
343 * @ fs_curr_ua - full scale current in ua
344 * @ ramp_ms - delay between ramp steps in ms
345 * @ ramp_step - ramp step size
346 * @ cons_sync_write_delay_us - delay between two consecutive writes to SYNC
347 * @ auto_calibration_ovp_count - OVP fault irq count to run auto calibration
348 * @ max_strings - Number of strings supported in WLED peripheral
349 * @ prev_level - Previous brightness level
350 * @ brt_map_table - Brightness map table
351 * @ strings - supported list of strings
352 * @ num_strings - number of strings
353 * @ loop_auto_gm_thresh - the clamping level for auto gm
354 * @ lcd_auto_pfm_thresh - the threshold for lcd auto pfm mode
355 * @ loop_auto_gm_en - select if auto gm is enabled
356 * @ lcd_auto_pfm_en - select if auto pfm is enabled in lcd mode
357 * @ lcd_psm_ctrl - select if psm needs to be controlled in lcd mode
358 * @ avdd_mode_spmi - enable avdd programming via spmi
359 * @ en_9b_dim_res - enable or disable 9bit dimming
360 * @ en_phase_stag - enable or disable phase staggering
361 * @ en_cabc - enable or disable cabc
362 * @ disp_type_amoled - type of display: LCD/AMOLED
363 * @ en_ext_pfet_sc_pro - enable sc protection on external pfet
364 * @ prev_state - previous state of WLED
365 * @ stepper_en - Flag to enable stepper algorithm
366 * @ ovp_irq_disabled - OVP interrupt disable status
367 * @ auto_calib_enabled - Flag to enable auto calibration feature
368 * @ auto_calib_done - Flag to indicate auto calibration is done
369 * @ module_dis_perm - Flat to keep module permanently disabled
370 * @ start_ovp_fault_time - Time when the OVP fault first occurred
373 struct led_classdev cdev;
374 struct platform_device *pdev;
375 struct regmap *regmap;
376 struct pmic_revid_data *pmic_rev_id;
377 struct work_struct work;
378 struct workqueue_struct *wq;
380 struct mutex bus_lock;
381 enum qpnp_wled_fdbk_op fdbk_op;
382 enum qpnp_wled_dim_mode dim_mode;
386 u32 avdd_target_voltage_mv;
394 u16 loop_comp_res_kohm;
404 u16 cons_sync_write_delay_us;
405 u16 auto_calibration_ovp_count;
409 u8 strings[QPNP_WLED_MAX_STRINGS];
411 u8 loop_auto_gm_thresh;
412 u8 lcd_auto_pfm_thresh;
413 bool loop_auto_gm_en;
414 bool lcd_auto_pfm_en;
420 bool disp_type_amoled;
421 bool en_ext_pfet_sc_pro;
424 bool ovp_irq_disabled;
425 bool auto_calib_enabled;
426 bool auto_calib_done;
427 bool module_dis_perm;
428 ktime_t start_ovp_fault_time;
431 static int qpnp_wled_step_delay_us = 52000;
433 total_step_delay_us, qpnp_wled_step_delay_us, int, 0600
436 static int qpnp_wled_step_size_threshold = 3;
438 step_size_threshold, qpnp_wled_step_size_threshold, int, 0600
441 static int qpnp_wled_step_delay_gain = 2;
443 step_delay_gain, qpnp_wled_step_delay_gain, int, 0600
446 /* helper to read a pmic register */
447 static int qpnp_wled_read_reg(struct qpnp_wled *wled, u16 addr, u8 *data)
452 rc = regmap_read(wled->regmap, addr, &val);
454 dev_err(&wled->pdev->dev,
455 "Error reading address: %x(%d)\n", addr, rc);
463 /* helper to write a pmic register */
464 static int qpnp_wled_write_reg(struct qpnp_wled *wled, u16 addr, u8 data)
468 mutex_lock(&wled->bus_lock);
469 rc = regmap_write(wled->regmap, addr, data);
471 dev_err(&wled->pdev->dev, "Error writing address: %x(%d)\n",
476 dev_dbg(&wled->pdev->dev, "wrote: WLED_0x%x = 0x%x\n", addr, data);
478 mutex_unlock(&wled->bus_lock);
482 static int qpnp_wled_masked_write_reg(struct qpnp_wled *wled, u16 addr,
487 mutex_lock(&wled->bus_lock);
488 rc = regmap_update_bits(wled->regmap, addr, mask, data);
490 dev_err(&wled->pdev->dev, "Error writing address: %x(%d)\n",
495 dev_dbg(&wled->pdev->dev, "wrote: WLED_0x%x = 0x%x\n", addr, data);
497 mutex_unlock(&wled->bus_lock);
501 static int qpnp_wled_sec_write_reg(struct qpnp_wled *wled, u16 addr, u8 data)
504 u8 reg = QPNP_WLED_SEC_UNLOCK;
505 u16 base_addr = addr & 0xFF00;
507 mutex_lock(&wled->bus_lock);
508 rc = regmap_write(wled->regmap, QPNP_WLED_SEC_ACCESS_REG(base_addr),
511 dev_err(&wled->pdev->dev, "Error writing address: %x(%d)\n",
512 QPNP_WLED_SEC_ACCESS_REG(base_addr), rc);
516 rc = regmap_write(wled->regmap, addr, data);
518 dev_err(&wled->pdev->dev, "Error writing address: %x(%d)\n",
523 dev_dbg(&wled->pdev->dev, "wrote: WLED_0x%x = 0x%x\n", addr, data);
525 mutex_unlock(&wled->bus_lock);
529 static int qpnp_wled_swire_avdd_config(struct qpnp_wled *wled)
534 if (wled->pmic_rev_id->pmic_subtype != PMI8998_SUBTYPE &&
535 wled->pmic_rev_id->pmic_subtype != PM660L_SUBTYPE)
538 if (!wled->disp_type_amoled || wled->avdd_mode_spmi)
541 val = QPNP_WLED_AVDD_MV_TO_REG(wled->avdd_target_voltage_mv);
542 rc = qpnp_wled_write_reg(wled,
543 QPNP_WLED_SWIRE_AVDD_REG(wled->ctrl_base), val);
547 static int qpnp_wled_sync_reg_toggle(struct qpnp_wled *wled)
553 reg = QPNP_WLED_SYNC;
554 rc = qpnp_wled_write_reg(wled, QPNP_WLED_SYNC_REG(wled->sink_base),
559 if (wled->cons_sync_write_delay_us)
560 usleep_range(wled->cons_sync_write_delay_us,
561 wled->cons_sync_write_delay_us + 1);
563 reg = QPNP_WLED_SYNC_RESET;
564 rc = qpnp_wled_write_reg(wled, QPNP_WLED_SYNC_REG(wled->sink_base),
572 /* set wled to a level of brightness */
573 static int qpnp_wled_set_level(struct qpnp_wled *wled, int level)
577 u16 low_limit = WLED_MAX_LEVEL_4095 * 4 / 1000;
579 /* WLED's lower limit of operation is 0.4% */
580 if (level > 0 && level < low_limit)
583 /* set brightness registers */
584 for (i = 0; i < wled->max_strings; i++) {
585 reg = level & QPNP_WLED_BRIGHT_LSB_MASK;
586 rc = qpnp_wled_write_reg(wled,
587 QPNP_WLED_BRIGHT_LSB_REG(wled->sink_base,
588 wled->strings[i]), reg);
592 reg = level >> QPNP_WLED_BRIGHT_MSB_SHIFT;
593 reg = reg & QPNP_WLED_BRIGHT_MSB_MASK;
594 rc = qpnp_wled_write_reg(wled,
595 QPNP_WLED_BRIGHT_MSB_REG(wled->sink_base,
596 wled->strings[i]), reg);
601 rc = qpnp_wled_sync_reg_toggle(wled);
603 dev_err(&wled->pdev->dev, "Failed to toggle sync reg %d\n", rc);
607 pr_debug("level:%d\n", level);
611 static int qpnp_wled_set_map_level(struct qpnp_wled *wled, int level)
615 if (level < wled->prev_level) {
616 for (i = wled->prev_level; i >= level; i--) {
617 rc = qpnp_wled_set_level(wled, wled->brt_map_table[i]);
619 pr_err("set brightness level failed, rc:%d\n",
624 } else if (level > wled->prev_level) {
625 for (i = wled->prev_level; i <= level; i++) {
626 rc = qpnp_wled_set_level(wled, wled->brt_map_table[i]);
628 pr_err("set brightness level failed, rc:%d\n",
638 static int qpnp_wled_set_step_level(struct qpnp_wled *wled, int new_level)
640 int rc, i, num_steps, delay_us;
641 u16 level, start_level, end_level, step_size;
642 bool level_inc = false;
644 level = wled->prev_level;
645 start_level = wled->brt_map_table[level];
646 end_level = wled->brt_map_table[new_level];
647 level_inc = (new_level > level);
649 num_steps = abs(start_level - end_level);
653 delay_us = qpnp_wled_step_delay_us / num_steps;
654 pr_debug("level goes from [%d %d] num_steps: %d, delay: %d\n",
655 start_level, end_level, num_steps, delay_us);
657 if (delay_us < 500) {
658 step_size = 1000 / delay_us;
659 num_steps = num_steps / step_size;
662 if (num_steps < qpnp_wled_step_size_threshold)
663 delay_us *= qpnp_wled_step_delay_gain;
669 while (num_steps--) {
675 rc = qpnp_wled_set_level(wled, i);
680 if (delay_us < 20000)
681 usleep_range(delay_us, delay_us + 1);
683 msleep(delay_us / USEC_PER_MSEC);
687 if (i != end_level) {
689 rc = qpnp_wled_set_level(wled, i);
697 static int qpnp_wled_psm_config(struct qpnp_wled *wled, bool enable)
701 if (!wled->lcd_psm_ctrl)
704 rc = qpnp_wled_masked_write_reg(wled,
705 QPNP_WLED_EN_PSM_REG(wled->ctrl_base),
706 QPNP_WLED_EN_PSM_BIT,
707 enable ? QPNP_WLED_EN_PSM_BIT : 0);
711 rc = qpnp_wled_masked_write_reg(wled,
712 QPNP_WLED_PSM_CTRL_REG(wled->ctrl_base),
713 QPNP_WLED_PSM_OVERWRITE_BIT,
714 enable ? QPNP_WLED_PSM_OVERWRITE_BIT : 0);
721 static int qpnp_wled_module_en(struct qpnp_wled *wled,
722 u16 base_addr, bool state)
726 if (wled->module_dis_perm)
729 rc = qpnp_wled_masked_write_reg(wled,
730 QPNP_WLED_MODULE_EN_REG(base_addr),
731 QPNP_WLED_MODULE_EN_MASK,
732 state << QPNP_WLED_MODULE_EN_SHIFT);
737 * Wait for at least 10ms before enabling OVP fault interrupt after
738 * enabling the module so that soft start is completed. Also, this
739 * delay can be used to control PSM during enable when required. Keep
740 * OVP interrupt disabled when the module is disabled.
743 usleep_range(QPNP_WLED_SOFT_START_DLY_US,
744 QPNP_WLED_SOFT_START_DLY_US + 1000);
745 rc = qpnp_wled_psm_config(wled, false);
749 if (wled->ovp_irq > 0 && wled->ovp_irq_disabled) {
750 enable_irq(wled->ovp_irq);
751 wled->ovp_irq_disabled = false;
754 if (wled->ovp_irq > 0 && !wled->ovp_irq_disabled) {
755 disable_irq(wled->ovp_irq);
756 wled->ovp_irq_disabled = true;
759 rc = qpnp_wled_psm_config(wled, true);
767 /* sysfs store function for ramp */
768 static ssize_t qpnp_wled_ramp_store(struct device *dev,
769 struct device_attribute *attr, const char *buf, size_t count)
771 struct qpnp_wled *wled = dev_get_drvdata(dev);
774 mutex_lock(&wled->lock);
776 if (!wled->cdev.brightness) {
777 rc = qpnp_wled_module_en(wled, wled->ctrl_base, true);
779 dev_err(&wled->pdev->dev, "wled enable failed\n");
785 for (i = 0; i <= wled->cdev.max_brightness;) {
786 rc = qpnp_wled_set_level(wled, i);
788 dev_err(&wled->pdev->dev, "wled set level failed\n");
789 goto restore_brightness;
792 if (wled->ramp_ms < QPNP_WLED_MIN_MSLEEP)
793 usleep_range(wled->ramp_ms * USEC_PER_MSEC,
794 wled->ramp_ms * USEC_PER_MSEC);
796 msleep(wled->ramp_ms);
798 if (i == wled->cdev.max_brightness)
801 i += wled->ramp_step;
802 if (i > wled->cdev.max_brightness)
803 i = wled->cdev.max_brightness;
807 for (i = wled->cdev.max_brightness; i >= 0;) {
808 rc = qpnp_wled_set_level(wled, i);
810 dev_err(&wled->pdev->dev, "wled set level failed\n");
811 goto restore_brightness;
814 if (wled->ramp_ms < QPNP_WLED_MIN_MSLEEP)
815 usleep_range(wled->ramp_ms * USEC_PER_MSEC,
816 wled->ramp_ms * USEC_PER_MSEC);
818 msleep(wled->ramp_ms);
823 i -= wled->ramp_step;
828 dev_info(&wled->pdev->dev, "wled ramp complete\n");
831 /* restore the old brightness */
832 qpnp_wled_set_level(wled, wled->cdev.brightness);
833 if (!wled->cdev.brightness) {
834 rc = qpnp_wled_module_en(wled, wled->ctrl_base, false);
836 dev_err(&wled->pdev->dev, "wled enable failed\n");
839 mutex_unlock(&wled->lock);
844 static int qpnp_wled_dump_regs(struct qpnp_wled *wled, u16 base_addr,
845 u8 dbg_regs[], u8 size, char *label,
846 int count, char *buf)
851 for (i = 0; i < size; i++) {
852 rc = qpnp_wled_read_reg(wled, base_addr + dbg_regs[i], ®);
856 count += snprintf(buf + count, PAGE_SIZE - count,
857 "%s: REG_0x%x = 0x%x\n", label,
858 base_addr + dbg_regs[i], reg);
860 if (count >= PAGE_SIZE)
861 return PAGE_SIZE - 1;
867 /* sysfs show function for debug registers */
868 static ssize_t qpnp_wled_dump_regs_show(struct device *dev,
869 struct device_attribute *attr, char *buf)
871 struct qpnp_wled *wled = dev_get_drvdata(dev);
874 count = qpnp_wled_dump_regs(wled, wled->ctrl_base,
875 qpnp_wled_ctrl_dbg_regs,
876 ARRAY_SIZE(qpnp_wled_ctrl_dbg_regs),
877 "wled_ctrl", count, buf);
879 if (count < 0 || count == PAGE_SIZE - 1)
882 count = qpnp_wled_dump_regs(wled, wled->sink_base,
883 qpnp_wled_sink_dbg_regs,
884 ARRAY_SIZE(qpnp_wled_sink_dbg_regs),
885 "wled_sink", count, buf);
887 if (count < 0 || count == PAGE_SIZE - 1)
893 /* sysfs show function for ramp delay in each step */
894 static ssize_t qpnp_wled_ramp_ms_show(struct device *dev,
895 struct device_attribute *attr, char *buf)
897 struct qpnp_wled *wled = dev_get_drvdata(dev);
899 return snprintf(buf, PAGE_SIZE, "%d\n", wled->ramp_ms);
902 /* sysfs store function for ramp delay in each step */
903 static ssize_t qpnp_wled_ramp_ms_store(struct device *dev,
904 struct device_attribute *attr, const char *buf, size_t count)
906 struct qpnp_wled *wled = dev_get_drvdata(dev);
909 rc = kstrtoint(buf, 10, &data);
913 wled->ramp_ms = data;
917 /* sysfs show function for ramp step */
918 static ssize_t qpnp_wled_ramp_step_show(struct device *dev,
919 struct device_attribute *attr, char *buf)
921 struct qpnp_wled *wled = dev_get_drvdata(dev);
923 return snprintf(buf, PAGE_SIZE, "%d\n", wled->ramp_step);
926 /* sysfs store function for ramp step */
927 static ssize_t qpnp_wled_ramp_step_store(struct device *dev,
928 struct device_attribute *attr, const char *buf, size_t count)
930 struct qpnp_wled *wled = dev_get_drvdata(dev);
933 rc = kstrtoint(buf, 10, &data);
937 wled->ramp_step = data;
941 /* sysfs show function for dim mode */
942 static ssize_t qpnp_wled_dim_mode_show(struct device *dev,
943 struct device_attribute *attr, char *buf)
945 struct qpnp_wled *wled = dev_get_drvdata(dev);
948 if (wled->dim_mode == QPNP_WLED_DIM_ANALOG)
950 else if (wled->dim_mode == QPNP_WLED_DIM_DIGITAL)
955 return snprintf(buf, PAGE_SIZE, "%s\n", str);
958 /* sysfs store function for dim mode*/
959 static ssize_t qpnp_wled_dim_mode_store(struct device *dev,
960 struct device_attribute *attr, const char *buf, size_t count)
962 struct qpnp_wled *wled = dev_get_drvdata(dev);
963 char str[QPNP_WLED_STR_SIZE + 1];
967 if (snprintf(str, QPNP_WLED_STR_SIZE, "%s", buf) > QPNP_WLED_STR_SIZE)
970 if (strcmp(str, "analog") == 0)
971 temp = QPNP_WLED_DIM_ANALOG;
972 else if (strcmp(str, "digital") == 0)
973 temp = QPNP_WLED_DIM_DIGITAL;
975 temp = QPNP_WLED_DIM_HYBRID;
977 if (temp == wled->dim_mode)
980 rc = qpnp_wled_read_reg(wled, QPNP_WLED_MOD_REG(wled->sink_base), ®);
984 if (temp == QPNP_WLED_DIM_HYBRID) {
985 reg &= QPNP_WLED_DIM_HYB_MASK;
986 reg |= (1 << QPNP_WLED_DIM_HYB_SHIFT);
988 reg &= QPNP_WLED_DIM_HYB_MASK;
989 reg |= (0 << QPNP_WLED_DIM_HYB_SHIFT);
990 reg &= QPNP_WLED_DIM_ANA_MASK;
994 rc = qpnp_wled_write_reg(wled, QPNP_WLED_MOD_REG(wled->sink_base), reg);
998 wled->dim_mode = temp;
1003 /* sysfs show function for full scale current in ua*/
1004 static ssize_t qpnp_wled_fs_curr_ua_show(struct device *dev,
1005 struct device_attribute *attr, char *buf)
1007 struct qpnp_wled *wled = dev_get_drvdata(dev);
1009 return snprintf(buf, PAGE_SIZE, "%d\n", wled->fs_curr_ua);
1012 /* sysfs store function for full scale current in ua*/
1013 static ssize_t qpnp_wled_fs_curr_ua_store(struct device *dev,
1014 struct device_attribute *attr, const char *buf, size_t count)
1016 struct qpnp_wled *wled = dev_get_drvdata(dev);
1020 rc = kstrtoint(buf, 10, &data);
1024 for (i = 0; i < wled->max_strings; i++) {
1025 if (data < QPNP_WLED_FS_CURR_MIN_UA)
1026 data = QPNP_WLED_FS_CURR_MIN_UA;
1027 else if (data > QPNP_WLED_FS_CURR_MAX_UA)
1028 data = QPNP_WLED_FS_CURR_MAX_UA;
1030 reg = data / QPNP_WLED_FS_CURR_STEP_UA;
1031 rc = qpnp_wled_masked_write_reg(wled,
1032 QPNP_WLED_FS_CURR_REG(wled->sink_base, i),
1033 QPNP_WLED_FS_CURR_MASK, reg);
1038 wled->fs_curr_ua = data;
1040 rc = qpnp_wled_sync_reg_toggle(wled);
1042 dev_err(&wled->pdev->dev, "Failed to toggle sync reg %d\n", rc);
1049 /* sysfs attributes exported by wled */
1050 static struct device_attribute qpnp_wled_attrs[] = {
1051 __ATTR(dump_regs, 0664, qpnp_wled_dump_regs_show, NULL),
1052 __ATTR(dim_mode, 0664, qpnp_wled_dim_mode_show,
1053 qpnp_wled_dim_mode_store),
1054 __ATTR(fs_curr_ua, 0664, qpnp_wled_fs_curr_ua_show,
1055 qpnp_wled_fs_curr_ua_store),
1056 __ATTR(start_ramp, 0664, NULL, qpnp_wled_ramp_store),
1057 __ATTR(ramp_ms, 0664, qpnp_wled_ramp_ms_show, qpnp_wled_ramp_ms_store),
1058 __ATTR(ramp_step, 0664, qpnp_wled_ramp_step_show,
1059 qpnp_wled_ramp_step_store),
1062 /* worker for setting wled brightness */
1063 static void qpnp_wled_work(struct work_struct *work)
1065 struct qpnp_wled *wled;
1066 int level, level_255, rc;
1068 wled = container_of(work, struct qpnp_wled, work);
1070 mutex_lock(&wled->lock);
1071 level = wled->cdev.brightness;
1073 if (wled->brt_map_table) {
1075 * Change the 12 bit level to 8 bit level and use the mapped
1076 * values for 12 bit level from brightness map table.
1078 level_255 = DIV_ROUND_CLOSEST(level, 16);
1079 if (level_255 > 255)
1082 pr_debug("level: %d level_255: %d\n", level, level_255);
1083 if (wled->stepper_en)
1084 rc = qpnp_wled_set_step_level(wled, level_255);
1086 rc = qpnp_wled_set_map_level(wled, level_255);
1088 dev_err(&wled->pdev->dev, "wled set level failed\n");
1091 wled->prev_level = level_255;
1093 rc = qpnp_wled_set_level(wled, level);
1095 dev_err(&wled->pdev->dev, "wled set level failed\n");
1100 if (!!level != wled->prev_state) {
1103 * For AMOLED display in pmi8998, SWIRE_AVDD_DEFAULT has
1104 * to be reconfigured every time the module is enabled.
1106 rc = qpnp_wled_swire_avdd_config(wled);
1108 pr_err("Write to SWIRE_AVDD_DEFAULT register failed rc:%d\n",
1114 rc = qpnp_wled_module_en(wled, wled->ctrl_base, !!level);
1116 dev_err(&wled->pdev->dev, "wled %sable failed\n",
1117 level ? "en" : "dis");
1122 wled->prev_state = !!level;
1124 mutex_unlock(&wled->lock);
1127 /* get api registered with led classdev for wled brightness */
1128 static enum led_brightness qpnp_wled_get(struct led_classdev *led_cdev)
1130 struct qpnp_wled *wled;
1132 wled = container_of(led_cdev, struct qpnp_wled, cdev);
1134 return wled->cdev.brightness;
1137 /* set api registered with led classdev for wled brightness */
1138 static void qpnp_wled_set(struct led_classdev *led_cdev,
1139 enum led_brightness level)
1141 struct qpnp_wled *wled;
1143 wled = container_of(led_cdev, struct qpnp_wled, cdev);
1145 if (level < LED_OFF)
1147 else if (level > wled->cdev.max_brightness)
1148 level = wled->cdev.max_brightness;
1150 wled->cdev.brightness = level;
1151 queue_work(wled->wq, &wled->work);
1154 static int qpnp_wled_set_disp(struct qpnp_wled *wled, u16 base_addr)
1160 rc = qpnp_wled_read_reg(wled, QPNP_WLED_DISP_SEL_REG(base_addr), ®);
1164 reg &= QPNP_WLED_DISP_SEL_MASK;
1165 reg |= (wled->disp_type_amoled << QPNP_WLED_DISP_SEL_SHIFT);
1167 rc = qpnp_wled_sec_write_reg(wled, QPNP_WLED_DISP_SEL_REG(base_addr),
1172 if (wled->disp_type_amoled) {
1173 /* Configure the PSM CTRL register for AMOLED */
1174 if (wled->vref_psm_mv < QPNP_WLED_VREF_PSM_MIN_MV)
1175 wled->vref_psm_mv = QPNP_WLED_VREF_PSM_MIN_MV;
1176 else if (wled->vref_psm_mv > QPNP_WLED_VREF_PSM_MAX_MV)
1177 wled->vref_psm_mv = QPNP_WLED_VREF_PSM_MAX_MV;
1179 rc = qpnp_wled_read_reg(wled,
1180 QPNP_WLED_PSM_CTRL_REG(wled->ctrl_base), ®);
1184 reg &= QPNP_WLED_VREF_PSM_MASK;
1185 reg |= ((wled->vref_psm_mv - QPNP_WLED_VREF_PSM_MIN_MV)/
1186 QPNP_WLED_VREF_PSM_STEP_MV);
1187 reg |= QPNP_WLED_PSM_OVERWRITE_BIT;
1188 rc = qpnp_wled_write_reg(wled,
1189 QPNP_WLED_PSM_CTRL_REG(wled->ctrl_base), reg);
1193 /* Configure the VLOOP COMP RES register for AMOLED */
1194 if (wled->loop_comp_res_kohm < QPNP_WLED_LOOP_COMP_RES_MIN_KOHM)
1195 wled->loop_comp_res_kohm =
1196 QPNP_WLED_LOOP_COMP_RES_MIN_KOHM;
1197 else if (wled->loop_comp_res_kohm >
1198 QPNP_WLED_LOOP_COMP_RES_MAX_KOHM)
1199 wled->loop_comp_res_kohm =
1200 QPNP_WLED_LOOP_COMP_RES_MAX_KOHM;
1202 rc = qpnp_wled_read_reg(wled,
1203 QPNP_WLED_VLOOP_COMP_RES_REG(wled->ctrl_base),
1208 reg &= QPNP_WLED_VLOOP_COMP_RES_MASK;
1209 reg |= ((wled->loop_comp_res_kohm -
1210 QPNP_WLED_LOOP_COMP_RES_MIN_KOHM)/
1211 QPNP_WLED_LOOP_COMP_RES_STEP_KOHM);
1212 reg |= QPNP_WLED_VLOOP_COMP_RES_OVERWRITE;
1213 rc = qpnp_wled_write_reg(wled,
1214 QPNP_WLED_VLOOP_COMP_RES_REG(wled->ctrl_base),
1219 /* Configure the CTRL TEST4 register for AMOLED */
1220 rc = qpnp_wled_read_reg(wled,
1221 QPNP_WLED_TEST4_REG(wled->ctrl_base), ®);
1225 reg |= QPNP_WLED_TEST4_EN_IIND_UP;
1226 rc = qpnp_wled_sec_write_reg(wled,
1227 QPNP_WLED_TEST4_REG(base_addr), reg);
1232 * enable VREF_UP to avoid false ovp on low brightness for LCD
1234 reg = QPNP_WLED_TEST4_EN_VREF_UP
1235 | QPNP_WLED_TEST4_EN_DEB_BYPASS_ILIM_BIT;
1236 rc = qpnp_wled_sec_write_reg(wled,
1237 QPNP_WLED_TEST4_REG(base_addr), reg);
1245 #define AUTO_CALIB_BRIGHTNESS 200
1246 static int wled_auto_calibrate(struct qpnp_wled *wled)
1249 u8 reg = 0, sink_config = 0, sink_test = 0, sink_valid = 0, int_sts;
1251 /* read configured sink configuration */
1252 rc = qpnp_wled_read_reg(wled,
1253 QPNP_WLED_CURR_SINK_REG(wled->sink_base), &sink_config);
1255 pr_err("Failed to read SINK configuration rc=%d\n", rc);
1259 /* disable the module before starting calibration */
1260 rc = qpnp_wled_masked_write_reg(wled,
1261 QPNP_WLED_MODULE_EN_REG(wled->ctrl_base),
1262 QPNP_WLED_MODULE_EN_MASK, 0);
1264 pr_err("Failed to disable WLED module rc=%d\n", rc);
1268 /* set low brightness across all sinks */
1269 rc = qpnp_wled_set_level(wled, AUTO_CALIB_BRIGHTNESS);
1271 pr_err("Failed to set brightness for calibration rc=%d\n", rc);
1275 if (wled->en_cabc) {
1276 for (i = 0; i < wled->max_strings; i++) {
1278 rc = qpnp_wled_masked_write_reg(wled,
1279 QPNP_WLED_CABC_REG(wled->sink_base, i),
1280 QPNP_WLED_CABC_MASK, reg);
1286 /* disable all sinks */
1287 rc = qpnp_wled_write_reg(wled,
1288 QPNP_WLED_CURR_SINK_REG(wled->sink_base), 0);
1290 pr_err("Failed to disable all sinks rc=%d\n", rc);
1294 /* iterate through the strings one by one */
1295 for (i = 0; i < wled->max_strings; i++) {
1296 sink_test = 1 << (QPNP_WLED_CURR_SINK_SHIFT + i);
1298 /* Enable feedback control */
1299 rc = qpnp_wled_write_reg(wled,
1300 QPNP_WLED_FDBK_OP_REG(wled->ctrl_base),
1303 pr_err("Failed to enable feedback for SINK %d rc = %d\n",
1308 /* enable the sink */
1309 rc = qpnp_wled_write_reg(wled,
1310 QPNP_WLED_CURR_SINK_REG(wled->sink_base), sink_test);
1312 pr_err("Failed to configure SINK %d rc=%d\n",
1317 /* Enable the module */
1318 rc = qpnp_wled_masked_write_reg(wled,
1319 QPNP_WLED_MODULE_EN_REG(wled->ctrl_base),
1320 QPNP_WLED_MODULE_EN_MASK, QPNP_WLED_MODULE_EN_MASK);
1322 pr_err("Failed to enable WLED module rc=%d\n", rc);
1326 /* delay for WLED soft-start */
1327 usleep_range(QPNP_WLED_SOFT_START_DLY_US,
1328 QPNP_WLED_SOFT_START_DLY_US + 1000);
1330 rc = qpnp_wled_read_reg(wled,
1331 QPNP_WLED_INT_RT_STS(wled->ctrl_base), &int_sts);
1333 pr_err("Error in reading WLED_INT_RT_STS rc=%d\n", rc);
1337 if (int_sts & QPNP_WLED_OVP_FAULT_BIT)
1338 pr_debug("WLED OVP fault detected with SINK %d\n",
1341 sink_valid |= sink_test;
1343 /* Disable the module */
1344 rc = qpnp_wled_masked_write_reg(wled,
1345 QPNP_WLED_MODULE_EN_REG(wled->ctrl_base),
1346 QPNP_WLED_MODULE_EN_MASK, 0);
1348 pr_err("Failed to disable WLED module rc=%d\n", rc);
1353 if (sink_valid == sink_config) {
1354 pr_debug("WLED auto-calibration complete, default sink-config=%x OK!\n",
1357 pr_warn("Invalid WLED default sink config=%x changing it to=%x\n",
1358 sink_config, sink_valid);
1359 sink_config = sink_valid;
1363 pr_warn("No valid WLED sinks found\n");
1364 wled->module_dis_perm = true;
1368 /* write the new sink configuration */
1369 rc = qpnp_wled_write_reg(wled,
1370 QPNP_WLED_CURR_SINK_REG(wled->sink_base), sink_config);
1372 pr_err("Failed to reconfigure the default sink rc=%d\n", rc);
1376 /* MODULATOR_EN setting for valid sinks */
1377 for (i = 0; i < wled->max_strings; i++) {
1378 if (wled->en_cabc) {
1379 reg = 1 << QPNP_WLED_CABC_SHIFT;
1380 rc = qpnp_wled_masked_write_reg(wled,
1381 QPNP_WLED_CABC_REG(wled->sink_base, i),
1382 QPNP_WLED_CABC_MASK, reg);
1387 if (sink_config & (1 << (QPNP_WLED_CURR_SINK_SHIFT + i)))
1388 reg = (QPNP_WLED_MOD_EN << QPNP_WLED_MOD_EN_SHFT);
1390 reg = 0x0; /* disable modulator_en for unused sink */
1392 if (wled->dim_mode == QPNP_WLED_DIM_HYBRID)
1393 reg &= QPNP_WLED_GATE_DRV_MASK;
1395 reg |= ~QPNP_WLED_GATE_DRV_MASK;
1397 rc = qpnp_wled_write_reg(wled,
1398 QPNP_WLED_MOD_EN_REG(wled->sink_base, i), reg);
1400 pr_err("Failed to configure MODULATOR_EN rc=%d\n", rc);
1405 /* restore the feedback setting */
1406 rc = qpnp_wled_write_reg(wled,
1407 QPNP_WLED_FDBK_OP_REG(wled->ctrl_base),
1410 pr_err("Failed to restore feedback setting rc=%d\n", rc);
1414 /* restore brightness */
1415 rc = qpnp_wled_set_level(wled, !wled->cdev.brightness ?
1416 AUTO_CALIB_BRIGHTNESS : wled->cdev.brightness);
1418 pr_err("Failed to set brightness after calibration rc=%d\n",
1423 rc = qpnp_wled_masked_write_reg(wled,
1424 QPNP_WLED_MODULE_EN_REG(wled->ctrl_base),
1425 QPNP_WLED_MODULE_EN_MASK,
1426 QPNP_WLED_MODULE_EN_MASK);
1428 pr_err("Failed to enable WLED module rc=%d\n", rc);
1432 /* delay for WLED soft-start */
1433 usleep_range(QPNP_WLED_SOFT_START_DLY_US,
1434 QPNP_WLED_SOFT_START_DLY_US + 1000);
1440 #define WLED_AUTO_CAL_OVP_COUNT 5
1441 #define WLED_AUTO_CAL_CNT_DLY_US 1000000 /* 1 second */
1442 static bool qpnp_wled_auto_cal_required(struct qpnp_wled *wled)
1444 s64 elapsed_time_us;
1447 * Check if the OVP fault was an occasional one
1448 * or if its firing continuously, the latter qualifies
1449 * for an auto-calibration check.
1451 if (!wled->auto_calibration_ovp_count) {
1452 wled->start_ovp_fault_time = ktime_get();
1453 wled->auto_calibration_ovp_count++;
1455 elapsed_time_us = ktime_us_delta(ktime_get(),
1456 wled->start_ovp_fault_time);
1457 if (elapsed_time_us > WLED_AUTO_CAL_CNT_DLY_US)
1458 wled->auto_calibration_ovp_count = 0;
1460 wled->auto_calibration_ovp_count++;
1462 if (wled->auto_calibration_ovp_count >=
1463 WLED_AUTO_CAL_OVP_COUNT) {
1464 wled->auto_calibration_ovp_count = 0;
1472 static int qpnp_wled_auto_calibrate_at_init(struct qpnp_wled *wled)
1475 u8 fault_status = 0, rt_status = 0;
1477 if (!wled->auto_calib_enabled)
1480 rc = qpnp_wled_read_reg(wled,
1481 QPNP_WLED_INT_RT_STS(wled->ctrl_base), &rt_status);
1483 pr_err("Failed to read RT status rc=%d\n", rc);
1485 rc = qpnp_wled_read_reg(wled,
1486 QPNP_WLED_FAULT_STATUS(wled->ctrl_base), &fault_status);
1488 pr_err("Failed to read fault status rc=%d\n", rc);
1490 if ((rt_status & QPNP_WLED_OVP_FLT_RT_STS_BIT) ||
1491 (fault_status & QPNP_WLED_OVP_FAULT_BIT)) {
1492 mutex_lock(&wled->lock);
1493 rc = wled_auto_calibrate(wled);
1495 pr_err("Failed auto-calibration rc=%d\n", rc);
1497 wled->auto_calib_done = true;
1498 mutex_unlock(&wled->lock);
1504 /* ovp irq handler */
1505 static irqreturn_t qpnp_wled_ovp_irq_handler(int irq, void *_wled)
1507 struct qpnp_wled *wled = _wled;
1509 u8 fault_sts, int_sts;
1511 rc = qpnp_wled_read_reg(wled,
1512 QPNP_WLED_INT_RT_STS(wled->ctrl_base), &int_sts);
1514 pr_err("Error in reading WLED_INT_RT_STS rc=%d\n", rc);
1518 rc = qpnp_wled_read_reg(wled,
1519 QPNP_WLED_FAULT_STATUS(wled->ctrl_base), &fault_sts);
1521 pr_err("Error in reading WLED_FAULT_STATUS rc=%d\n", rc);
1525 if (fault_sts & (QPNP_WLED_OVP_FAULT_BIT | QPNP_WLED_ILIM_FAULT_BIT))
1526 pr_err("WLED OVP fault detected, int_sts=%x fault_sts= %x\n",
1527 int_sts, fault_sts);
1529 if (fault_sts & QPNP_WLED_OVP_FAULT_BIT) {
1530 if (wled->auto_calib_enabled && !wled->auto_calib_done) {
1531 if (qpnp_wled_auto_cal_required(wled)) {
1532 mutex_lock(&wled->lock);
1533 if (wled->ovp_irq > 0 &&
1534 !wled->ovp_irq_disabled) {
1535 disable_irq_nosync(wled->ovp_irq);
1536 wled->ovp_irq_disabled = true;
1539 rc = wled_auto_calibrate(wled);
1541 pr_err("Failed auto-calibration rc=%d\n",
1544 wled->auto_calib_done = true;
1546 if (wled->ovp_irq > 0 &&
1547 wled->ovp_irq_disabled) {
1548 enable_irq(wled->ovp_irq);
1549 wled->ovp_irq_disabled = false;
1551 mutex_unlock(&wled->lock);
1557 disable_irq_nosync(wled->ovp_irq);
1558 wled->ovp_irq_disabled = true;
1562 /* short circuit irq handler */
1563 static irqreturn_t qpnp_wled_sc_irq_handler(int irq, void *_wled)
1565 struct qpnp_wled *wled = _wled;
1569 rc = qpnp_wled_read_reg(wled,
1570 QPNP_WLED_FAULT_STATUS(wled->ctrl_base), &val);
1572 pr_err("Error in reading WLED_FAULT_STATUS rc=%d\n", rc);
1576 pr_err("WLED short circuit detected %d times fault_status=%x\n",
1577 ++wled->sc_cnt, val);
1578 mutex_lock(&wled->lock);
1579 qpnp_wled_module_en(wled, wled->ctrl_base, false);
1580 msleep(QPNP_WLED_SC_DLY_MS);
1581 qpnp_wled_module_en(wled, wled->ctrl_base, true);
1582 mutex_unlock(&wled->lock);
1587 static bool is_avdd_trim_adjustment_required(struct qpnp_wled *wled)
1593 * AVDD trim adjustment is not required for pmi8998/pm660l and not
1594 * supported for pmi8994.
1596 if (wled->pmic_rev_id->pmic_subtype == PMI8998_SUBTYPE ||
1597 wled->pmic_rev_id->pmic_subtype == PM660L_SUBTYPE ||
1598 wled->pmic_rev_id->pmic_subtype == PMI8994_SUBTYPE)
1602 * Configure TRIM_REG only if disp_type_amoled and it has
1603 * not already been programmed by bootloader.
1605 if (!wled->disp_type_amoled)
1608 rc = qpnp_wled_read_reg(wled,
1609 QPNP_WLED_CTRL_SPARE_REG(wled->ctrl_base), ®);
1613 return !(reg & QPNP_WLED_AVDD_SET_BIT);
1616 static int qpnp_wled_gm_config(struct qpnp_wled *wled)
1619 u8 mask = 0, reg = 0;
1621 /* Configure the LOOP COMP GM register */
1622 if ((wled->pmic_rev_id->pmic_subtype == PMI8998_SUBTYPE ||
1623 wled->pmic_rev_id->pmic_subtype == PM660L_SUBTYPE)) {
1624 if (wled->disp_type_amoled) {
1626 mask |= QPNP_WLED_VLOOP_COMP_AUTO_GM_EN |
1627 QPNP_WLED_VLOOP_COMP_AUTO_GM_THRESH_MASK;
1629 if (wled->loop_auto_gm_en)
1630 reg |= QPNP_WLED_VLOOP_COMP_AUTO_GM_EN;
1632 if (wled->loop_auto_gm_thresh >
1633 QPNP_WLED_LOOP_AUTO_GM_THRESH_MAX)
1634 wled->loop_auto_gm_thresh =
1635 QPNP_WLED_LOOP_AUTO_GM_THRESH_MAX;
1637 reg |= wled->loop_auto_gm_thresh <<
1638 QPNP_WLED_VLOOP_COMP_AUTO_GM_THRESH_SHIFT;
1639 mask |= QPNP_WLED_VLOOP_COMP_AUTO_GM_EN |
1640 QPNP_WLED_VLOOP_COMP_AUTO_GM_THRESH_MASK;
1644 if (wled->loop_ea_gm < QPNP_WLED_LOOP_EA_GM_MIN)
1645 wled->loop_ea_gm = QPNP_WLED_LOOP_EA_GM_MIN;
1646 else if (wled->loop_ea_gm > QPNP_WLED_LOOP_EA_GM_MAX)
1647 wled->loop_ea_gm = QPNP_WLED_LOOP_EA_GM_MAX;
1649 reg |= wled->loop_ea_gm | QPNP_WLED_VLOOP_COMP_GM_OVERWRITE;
1650 mask |= QPNP_WLED_VLOOP_COMP_GM_MASK |
1651 QPNP_WLED_VLOOP_COMP_GM_OVERWRITE;
1653 rc = qpnp_wled_masked_write_reg(wled,
1654 QPNP_WLED_VLOOP_COMP_GM_REG(wled->ctrl_base), mask,
1657 pr_err("write VLOOP_COMP_GM_REG failed, rc=%d]\n", rc);
1662 static int qpnp_wled_ovp_config(struct qpnp_wled *wled)
1664 int rc, i, *ovp_table;
1668 * Configure the OVP register based on ovp_mv only if display type is
1671 if (wled->disp_type_amoled)
1674 if (wled->pmic_rev_id->pmic_subtype == PMI8998_SUBTYPE ||
1675 wled->pmic_rev_id->pmic_subtype == PM660L_SUBTYPE)
1676 ovp_table = qpnp_wled_ovp_thresholds_pmi8998;
1678 ovp_table = qpnp_wled_ovp_thresholds_pmi8994;
1680 for (i = 0; i < NUM_SUPPORTED_OVP_THRESHOLDS; i++) {
1681 if (wled->ovp_mv == ovp_table[i])
1685 if (i == NUM_SUPPORTED_OVP_THRESHOLDS) {
1686 dev_err(&wled->pdev->dev,
1687 "Invalid ovp threshold specified in device tree\n");
1691 reg = i & QPNP_WLED_OVP_MASK;
1692 rc = qpnp_wled_masked_write_reg(wled,
1693 QPNP_WLED_OVP_REG(wled->ctrl_base),
1694 QPNP_WLED_OVP_MASK, reg);
1701 static int qpnp_wled_avdd_trim_config(struct qpnp_wled *wled)
1706 for (i = 0; i < NUM_SUPPORTED_AVDD_VOLTAGES; i++) {
1707 if (wled->avdd_target_voltage_mv ==
1708 qpnp_wled_avdd_target_voltages[i])
1712 if (i == NUM_SUPPORTED_AVDD_VOLTAGES) {
1713 dev_err(&wled->pdev->dev,
1714 "Invalid avdd target voltage specified in device tree\n");
1718 /* Update WLED_OVP register based on desired target voltage */
1719 reg = qpnp_wled_ovp_reg_settings[i];
1720 rc = qpnp_wled_masked_write_reg(wled,
1721 QPNP_WLED_OVP_REG(wled->ctrl_base),
1722 QPNP_WLED_OVP_MASK, reg);
1726 /* Update WLED_TRIM register based on desired target voltage */
1727 rc = qpnp_wled_read_reg(wled,
1728 QPNP_WLED_REF_7P7_TRIM_REG(wled->ctrl_base), ®);
1732 reg += qpnp_wled_avdd_trim_adjustments[i];
1733 if ((s8)reg < QPNP_WLED_AVDD_MIN_TRIM_VAL ||
1734 (s8)reg > QPNP_WLED_AVDD_MAX_TRIM_VAL) {
1735 dev_dbg(&wled->pdev->dev,
1736 "adjusted trim %d is not within range, capping it\n",
1738 if ((s8)reg < QPNP_WLED_AVDD_MIN_TRIM_VAL)
1739 reg = QPNP_WLED_AVDD_MIN_TRIM_VAL;
1741 reg = QPNP_WLED_AVDD_MAX_TRIM_VAL;
1744 reg &= QPNP_WLED_7P7_TRIM_MASK;
1745 rc = qpnp_wled_sec_write_reg(wled,
1746 QPNP_WLED_REF_7P7_TRIM_REG(wled->ctrl_base), reg);
1748 dev_err(&wled->pdev->dev, "Write to 7P7_TRIM register failed, rc=%d\n",
1753 static int qpnp_wled_avdd_mode_config(struct qpnp_wled *wled)
1759 * At present, configuring the mode to SPMI/SWIRE for controlling
1760 * AVDD voltage is available only in pmi8998/pm660l.
1762 if (wled->pmic_rev_id->pmic_subtype != PMI8998_SUBTYPE &&
1763 wled->pmic_rev_id->pmic_subtype != PM660L_SUBTYPE)
1766 /* AMOLED_VOUT should be configured for AMOLED */
1767 if (!wled->disp_type_amoled)
1770 /* Configure avdd register */
1771 if (wled->avdd_target_voltage_mv > QPNP_WLED_AVDD_MAX_MV) {
1772 dev_dbg(&wled->pdev->dev, "Capping avdd target voltage to %d\n",
1773 QPNP_WLED_AVDD_MAX_MV);
1774 wled->avdd_target_voltage_mv = QPNP_WLED_AVDD_MAX_MV;
1775 } else if (wled->avdd_target_voltage_mv < QPNP_WLED_AVDD_MIN_MV) {
1776 dev_info(&wled->pdev->dev, "Capping avdd target voltage to %d\n",
1777 QPNP_WLED_AVDD_MIN_MV);
1778 wled->avdd_target_voltage_mv = QPNP_WLED_AVDD_MIN_MV;
1781 if (wled->avdd_mode_spmi) {
1782 reg = QPNP_WLED_AVDD_MV_TO_REG(wled->avdd_target_voltage_mv);
1783 reg |= QPNP_WLED_AVDD_SEL_SPMI_BIT;
1784 rc = qpnp_wled_write_reg(wled,
1785 QPNP_WLED_AMOLED_VOUT_REG(wled->ctrl_base),
1788 pr_err("Write to AMOLED_VOUT register failed, rc=%d\n",
1791 rc = qpnp_wled_swire_avdd_config(wled);
1793 pr_err("Write to SWIRE_AVDD_DEFAULT register failed rc:%d\n",
1800 static int qpnp_wled_ilim_config(struct qpnp_wled *wled)
1802 int rc, i, *ilim_table;
1805 if (wled->ilim_ma < PMI8994_WLED_ILIM_MIN_MA)
1806 wled->ilim_ma = PMI8994_WLED_ILIM_MIN_MA;
1808 if (wled->pmic_rev_id->pmic_subtype == PMI8998_SUBTYPE ||
1809 wled->pmic_rev_id->pmic_subtype == PM660L_SUBTYPE) {
1810 ilim_table = qpnp_wled_ilim_settings_pmi8998;
1811 if (wled->ilim_ma > PMI8998_WLED_ILIM_MAX_MA)
1812 wled->ilim_ma = PMI8998_WLED_ILIM_MAX_MA;
1814 ilim_table = qpnp_wled_ilim_settings_pmi8994;
1815 if (wled->ilim_ma > PMI8994_WLED_ILIM_MAX_MA)
1816 wled->ilim_ma = PMI8994_WLED_ILIM_MAX_MA;
1819 for (i = 0; i < NUM_SUPPORTED_ILIM_THRESHOLDS; i++) {
1820 if (wled->ilim_ma == ilim_table[i])
1824 if (i == NUM_SUPPORTED_ILIM_THRESHOLDS) {
1825 dev_err(&wled->pdev->dev,
1826 "Invalid ilim threshold specified in device tree\n");
1830 reg = (i & QPNP_WLED_ILIM_MASK) | QPNP_WLED_ILIM_OVERWRITE;
1831 rc = qpnp_wled_masked_write_reg(wled,
1832 QPNP_WLED_ILIM_REG(wled->ctrl_base),
1833 QPNP_WLED_ILIM_MASK | QPNP_WLED_ILIM_OVERWRITE, reg);
1835 dev_err(&wled->pdev->dev, "Write to ILIM register failed, rc=%d\n",
1840 static int qpnp_wled_vref_config(struct qpnp_wled *wled)
1843 struct wled_vref_setting vref_setting;
1847 if (wled->pmic_rev_id->pmic_subtype == PMI8998_SUBTYPE ||
1848 wled->pmic_rev_id->pmic_subtype == PM660L_SUBTYPE)
1849 vref_setting = vref_setting_pmi8998;
1851 vref_setting = vref_setting_pmi8994;
1853 if (wled->vref_uv < vref_setting.min_uv)
1854 wled->vref_uv = vref_setting.min_uv;
1855 else if (wled->vref_uv > vref_setting.max_uv)
1856 wled->vref_uv = vref_setting.max_uv;
1858 reg |= DIV_ROUND_CLOSEST(wled->vref_uv - vref_setting.min_uv,
1859 vref_setting.step_uv);
1861 rc = qpnp_wled_masked_write_reg(wled,
1862 QPNP_WLED_VREF_REG(wled->ctrl_base),
1863 QPNP_WLED_VREF_MASK, reg);
1865 pr_err("Write VREF_REG failed, rc=%d\n", rc);
1870 /* Configure WLED registers */
1871 static int qpnp_wled_config(struct qpnp_wled *wled)
1874 u8 reg = 0, sink_en = 0, mask;
1876 /* Configure display type */
1877 rc = qpnp_wled_set_disp(wled, wled->ctrl_base);
1881 /* Configure the FEEDBACK OUTPUT register */
1882 rc = qpnp_wled_read_reg(wled, QPNP_WLED_FDBK_OP_REG(wled->ctrl_base),
1886 reg &= QPNP_WLED_FDBK_OP_MASK;
1887 reg |= wled->fdbk_op;
1888 rc = qpnp_wled_write_reg(wled, QPNP_WLED_FDBK_OP_REG(wled->ctrl_base),
1893 /* Configure the VREF register */
1894 rc = qpnp_wled_vref_config(wled);
1896 pr_err("Error in configuring wled vref, rc=%d\n", rc);
1900 /* Configure VLOOP_COMP_GM register */
1901 rc = qpnp_wled_gm_config(wled);
1903 pr_err("Error in configureing wled gm, rc=%d\n", rc);
1907 /* Configure the ILIM register */
1908 rc = qpnp_wled_ilim_config(wled);
1910 pr_err("Error in configuring wled ilim, rc=%d\n", rc);
1914 /* Configure auto PFM mode for LCD mode only */
1915 if ((wled->pmic_rev_id->pmic_subtype == PMI8998_SUBTYPE ||
1916 wled->pmic_rev_id->pmic_subtype == PM660L_SUBTYPE)
1917 && !wled->disp_type_amoled) {
1919 reg |= wled->lcd_auto_pfm_thresh;
1920 reg |= wled->lcd_auto_pfm_en <<
1921 QPNP_WLED_LCD_AUTO_PFM_EN_SHIFT;
1922 rc = qpnp_wled_masked_write_reg(wled,
1923 QPNP_WLED_LCD_AUTO_PFM_REG(wled->ctrl_base),
1924 QPNP_WLED_LCD_AUTO_PFM_EN_BIT |
1925 QPNP_WLED_LCD_AUTO_PFM_THRESH_MASK, reg);
1927 pr_err("Write LCD_AUTO_PFM failed, rc=%d\n", rc);
1932 /* Configure the Soft start Ramp delay: for AMOLED - 0,for LCD - 2 */
1933 reg = (wled->disp_type_amoled) ? 0 : 2;
1934 mask = SOFTSTART_RAMP_DELAY_MASK;
1935 if ((wled->pmic_rev_id->pmic_subtype == PMI8998_SUBTYPE ||
1936 wled->pmic_rev_id->pmic_subtype == PM660L_SUBTYPE)
1937 && wled->disp_type_amoled) {
1938 reg |= SOFTSTART_OVERWRITE_BIT;
1939 mask |= SOFTSTART_OVERWRITE_BIT;
1942 rc = qpnp_wled_masked_write_reg(wled,
1943 QPNP_WLED_SOFTSTART_RAMP_DLY(wled->ctrl_base),
1948 /* Configure the MAX BOOST DUTY register */
1949 if (wled->boost_duty_ns < QPNP_WLED_BOOST_DUTY_MIN_NS)
1950 wled->boost_duty_ns = QPNP_WLED_BOOST_DUTY_MIN_NS;
1951 else if (wled->boost_duty_ns > QPNP_WLED_BOOST_DUTY_MAX_NS)
1952 wled->boost_duty_ns = QPNP_WLED_BOOST_DUTY_MAX_NS;
1954 rc = qpnp_wled_read_reg(wled, QPNP_WLED_BOOST_DUTY_REG(wled->ctrl_base),
1958 reg &= QPNP_WLED_BOOST_DUTY_MASK;
1959 reg |= (wled->boost_duty_ns / QPNP_WLED_BOOST_DUTY_STEP_NS);
1960 rc = qpnp_wled_write_reg(wled,
1961 QPNP_WLED_BOOST_DUTY_REG(wled->ctrl_base), reg);
1965 /* Configure the SWITCHING FREQ register */
1966 if (wled->switch_freq_khz == 1600)
1967 reg = QPNP_WLED_SWITCH_FREQ_1600_KHZ_CODE;
1968 else if (wled->switch_freq_khz == 600)
1969 reg = QPNP_WLED_SWITCH_FREQ_600_KHZ_CODE;
1971 reg = QPNP_WLED_SWITCH_FREQ_800_KHZ_CODE;
1974 * Do not set the overwrite bit when switching frequency is selected
1975 * for AMOLED. This register is in logic reset block which can cause
1976 * the value to be overwritten during module enable/disable.
1978 mask = QPNP_WLED_SWITCH_FREQ_MASK | QPNP_WLED_SWITCH_FREQ_OVERWRITE;
1979 if (!wled->disp_type_amoled)
1980 reg |= QPNP_WLED_SWITCH_FREQ_OVERWRITE;
1982 rc = qpnp_wled_masked_write_reg(wled,
1983 QPNP_WLED_SWITCH_FREQ_REG(wled->ctrl_base), mask, reg);
1987 rc = qpnp_wled_ovp_config(wled);
1989 pr_err("Error in configuring OVP threshold, rc=%d\n", rc);
1993 if (is_avdd_trim_adjustment_required(wled)) {
1994 rc = qpnp_wled_avdd_trim_config(wled);
1999 rc = qpnp_wled_avdd_mode_config(wled);
2003 /* Configure the MODULATION register */
2004 if (wled->mod_freq_khz <= QPNP_WLED_MOD_FREQ_1200_KHZ) {
2005 wled->mod_freq_khz = QPNP_WLED_MOD_FREQ_1200_KHZ;
2007 } else if (wled->mod_freq_khz <= QPNP_WLED_MOD_FREQ_2400_KHZ) {
2008 wled->mod_freq_khz = QPNP_WLED_MOD_FREQ_2400_KHZ;
2010 } else if (wled->mod_freq_khz <= QPNP_WLED_MOD_FREQ_9600_KHZ) {
2011 wled->mod_freq_khz = QPNP_WLED_MOD_FREQ_9600_KHZ;
2013 } else if (wled->mod_freq_khz <= QPNP_WLED_MOD_FREQ_19200_KHZ) {
2014 wled->mod_freq_khz = QPNP_WLED_MOD_FREQ_19200_KHZ;
2017 wled->mod_freq_khz = QPNP_WLED_MOD_FREQ_9600_KHZ;
2021 rc = qpnp_wled_read_reg(wled, QPNP_WLED_MOD_REG(wled->sink_base), ®);
2024 reg &= QPNP_WLED_MOD_FREQ_MASK;
2025 reg |= (temp << QPNP_WLED_MOD_FREQ_SHIFT);
2027 reg &= QPNP_WLED_PHASE_STAG_MASK;
2028 reg |= (wled->en_phase_stag << QPNP_WLED_PHASE_STAG_SHIFT);
2030 reg &= QPNP_WLED_ACC_CLK_FREQ_MASK;
2031 reg |= (temp << QPNP_WLED_ACC_CLK_FREQ_SHIFT);
2033 reg &= QPNP_WLED_DIM_RES_MASK;
2034 reg |= (wled->en_9b_dim_res << QPNP_WLED_DIM_RES_SHIFT);
2036 if (wled->dim_mode == QPNP_WLED_DIM_HYBRID) {
2037 reg &= QPNP_WLED_DIM_HYB_MASK;
2038 reg |= (1 << QPNP_WLED_DIM_HYB_SHIFT);
2040 reg &= QPNP_WLED_DIM_HYB_MASK;
2041 reg |= (0 << QPNP_WLED_DIM_HYB_SHIFT);
2042 reg &= QPNP_WLED_DIM_ANA_MASK;
2043 reg |= wled->dim_mode;
2046 rc = qpnp_wled_write_reg(wled, QPNP_WLED_MOD_REG(wled->sink_base), reg);
2050 /* Configure the HYBRID THRESHOLD register */
2051 if (wled->hyb_thres < QPNP_WLED_HYB_THRES_MIN)
2052 wled->hyb_thres = QPNP_WLED_HYB_THRES_MIN;
2053 else if (wled->hyb_thres > QPNP_WLED_HYB_THRES_MAX)
2054 wled->hyb_thres = QPNP_WLED_HYB_THRES_MAX;
2056 rc = qpnp_wled_read_reg(wled, QPNP_WLED_HYB_THRES_REG(wled->sink_base),
2060 reg &= QPNP_WLED_HYB_THRES_MASK;
2061 temp = fls(wled->hyb_thres / QPNP_WLED_HYB_THRES_MIN) - 1;
2063 rc = qpnp_wled_write_reg(wled, QPNP_WLED_HYB_THRES_REG(wled->sink_base),
2068 /* Configure TEST5 register */
2069 if (wled->dim_mode == QPNP_WLED_DIM_DIGITAL) {
2070 reg = QPNP_WLED_SINK_TEST5_DIG;
2072 reg = QPNP_WLED_SINK_TEST5_HYB;
2073 if (wled->pmic_rev_id->pmic_subtype == PM660L_SUBTYPE)
2074 reg |= QPNP_WLED_SINK_TEST5_HVG_PULL_STR_BIT;
2077 rc = qpnp_wled_sec_write_reg(wled,
2078 QPNP_WLED_SINK_TEST5_REG(wled->sink_base), reg);
2082 /* disable all current sinks and enable selected strings */
2084 rc = qpnp_wled_write_reg(wled, QPNP_WLED_CURR_SINK_REG(wled->sink_base),
2087 for (i = 0; i < wled->max_strings; i++) {
2089 if (wled->sync_dly_us > QPNP_WLED_SYNC_DLY_MAX_US)
2090 wled->sync_dly_us = QPNP_WLED_SYNC_DLY_MAX_US;
2092 reg = wled->sync_dly_us / QPNP_WLED_SYNC_DLY_STEP_US;
2093 mask = QPNP_WLED_SYNC_DLY_MASK;
2094 rc = qpnp_wled_masked_write_reg(wled,
2095 QPNP_WLED_SYNC_DLY_REG(wled->sink_base, i),
2100 /* FULL SCALE CURRENT */
2101 if (wled->fs_curr_ua > QPNP_WLED_FS_CURR_MAX_UA)
2102 wled->fs_curr_ua = QPNP_WLED_FS_CURR_MAX_UA;
2104 reg = wled->fs_curr_ua / QPNP_WLED_FS_CURR_STEP_UA;
2105 mask = QPNP_WLED_FS_CURR_MASK;
2106 rc = qpnp_wled_masked_write_reg(wled,
2107 QPNP_WLED_FS_CURR_REG(wled->sink_base, i),
2113 reg = wled->en_cabc ? (1 << QPNP_WLED_CABC_SHIFT) : 0;
2114 mask = QPNP_WLED_CABC_MASK;
2115 rc = qpnp_wled_masked_write_reg(wled,
2116 QPNP_WLED_CABC_REG(wled->sink_base, i),
2122 /* Settings specific to valid sinks */
2123 for (i = 0; i < wled->num_strings; i++) {
2124 if (wled->strings[i] >= wled->max_strings) {
2125 dev_err(&wled->pdev->dev, "Invalid string number\n");
2129 rc = qpnp_wled_read_reg(wled,
2130 QPNP_WLED_MOD_EN_REG(wled->sink_base, i), ®);
2133 reg &= QPNP_WLED_MOD_EN_MASK;
2134 reg |= (QPNP_WLED_MOD_EN << QPNP_WLED_MOD_EN_SHFT);
2136 if (wled->dim_mode == QPNP_WLED_DIM_HYBRID)
2137 reg &= QPNP_WLED_GATE_DRV_MASK;
2139 reg |= ~QPNP_WLED_GATE_DRV_MASK;
2141 rc = qpnp_wled_write_reg(wled,
2142 QPNP_WLED_MOD_EN_REG(wled->sink_base, i), reg);
2147 temp = wled->strings[i] + QPNP_WLED_CURR_SINK_SHIFT;
2148 sink_en |= (1 << temp);
2150 mask = QPNP_WLED_CURR_SINK_MASK;
2151 rc = qpnp_wled_masked_write_reg(wled,
2152 QPNP_WLED_CURR_SINK_REG(wled->sink_base),
2155 dev_err(&wled->pdev->dev,
2156 "Failed to enable WLED sink config rc = %d\n", rc);
2160 rc = qpnp_wled_sync_reg_toggle(wled);
2162 dev_err(&wled->pdev->dev, "Failed to toggle sync reg %d\n", rc);
2166 rc = qpnp_wled_auto_calibrate_at_init(wled);
2168 pr_err("Failed to auto-calibrate at init rc=%d\n", rc);
2170 /* setup ovp and sc irqs */
2171 if (wled->ovp_irq >= 0) {
2172 rc = devm_request_threaded_irq(&wled->pdev->dev, wled->ovp_irq,
2173 NULL, qpnp_wled_ovp_irq_handler, IRQF_ONESHOT,
2174 "qpnp_wled_ovp_irq", wled);
2176 dev_err(&wled->pdev->dev,
2177 "Unable to request ovp(%d) IRQ(err:%d)\n",
2181 rc = qpnp_wled_read_reg(wled,
2182 QPNP_WLED_MODULE_EN_REG(wled->ctrl_base), ®);
2183 /* disable the OVP irq only if the module is not enabled */
2184 if (!rc && !(reg & QPNP_WLED_MODULE_EN_MASK)) {
2185 disable_irq(wled->ovp_irq);
2186 wled->ovp_irq_disabled = true;
2190 if (wled->sc_irq >= 0) {
2192 rc = devm_request_threaded_irq(&wled->pdev->dev, wled->sc_irq,
2193 NULL, qpnp_wled_sc_irq_handler, IRQF_ONESHOT,
2194 "qpnp_wled_sc_irq", wled);
2196 dev_err(&wled->pdev->dev,
2197 "Unable to request sc(%d) IRQ(err:%d)\n",
2202 rc = qpnp_wled_read_reg(wled,
2203 QPNP_WLED_SC_PRO_REG(wled->ctrl_base), ®);
2206 reg &= QPNP_WLED_EN_SC_DEB_CYCLES_MASK;
2207 reg |= 1 << QPNP_WLED_EN_SC_SHIFT;
2209 if (wled->sc_deb_cycles < QPNP_WLED_SC_DEB_CYCLES_MIN)
2210 wled->sc_deb_cycles = QPNP_WLED_SC_DEB_CYCLES_MIN;
2211 else if (wled->sc_deb_cycles > QPNP_WLED_SC_DEB_CYCLES_MAX)
2212 wled->sc_deb_cycles = QPNP_WLED_SC_DEB_CYCLES_MAX;
2213 temp = fls(wled->sc_deb_cycles) - QPNP_WLED_SC_DEB_CYCLES_SUB;
2216 if (wled->disp_type_amoled)
2217 reg |= QPNP_WLED_SC_PRO_EN_DSCHGR;
2219 rc = qpnp_wled_write_reg(wled,
2220 QPNP_WLED_SC_PRO_REG(wled->ctrl_base), reg);
2224 if (wled->en_ext_pfet_sc_pro) {
2225 reg = QPNP_WLED_EXT_FET_DTEST2;
2226 rc = qpnp_wled_sec_write_reg(wled,
2227 QPNP_WLED_TEST1_REG(wled->ctrl_base),
2233 rc = qpnp_wled_read_reg(wled,
2234 QPNP_WLED_SC_PRO_REG(wled->ctrl_base), ®);
2237 reg &= QPNP_WLED_EN_DEB_CYCLES_MASK;
2239 if (wled->sc_deb_cycles < QPNP_WLED_SC_DEB_CYCLES_MIN)
2240 wled->sc_deb_cycles = QPNP_WLED_SC_DEB_CYCLES_MIN;
2241 else if (wled->sc_deb_cycles > QPNP_WLED_SC_DEB_CYCLES_MAX)
2242 wled->sc_deb_cycles = QPNP_WLED_SC_DEB_CYCLES_MAX;
2243 temp = fls(wled->sc_deb_cycles) - QPNP_WLED_SC_DEB_CYCLES_SUB;
2246 rc = qpnp_wled_write_reg(wled,
2247 QPNP_WLED_SC_PRO_REG(wled->ctrl_base), reg);
2255 int qpnp_wled_cabc(struct led_classdev *led_cdev, bool enable)
2257 struct qpnp_wled *wled;
2261 wled = container_of(led_cdev, struct qpnp_wled, cdev);
2263 pr_err("wled is null\n");
2266 wled->en_cabc = enable;
2267 for (i = 0; i < wled->num_strings; i++) {
2269 rc = qpnp_wled_read_reg(wled,
2270 QPNP_WLED_CABC_REG(wled->sink_base,
2271 wled->strings[i]), ®);
2274 reg &= QPNP_WLED_CABC_MASK;
2275 reg |= (wled->en_cabc << QPNP_WLED_CABC_SHIFT);
2276 rc = qpnp_wled_write_reg(wled,
2277 QPNP_WLED_CABC_REG(wled->sink_base,
2278 wled->strings[i]), reg);
2281 pr_debug("%d en_cabc %d\n", i, wled->en_cabc);
2286 EXPORT_SYMBOL_GPL(qpnp_wled_cabc);
2288 /* parse wled dtsi parameters */
2289 static int qpnp_wled_parse_dt(struct qpnp_wled *wled)
2291 struct platform_device *pdev = wled->pdev;
2292 struct property *prop;
2293 const char *temp_str;
2298 wled->cdev.name = "wled";
2299 rc = of_property_read_string(pdev->dev.of_node,
2300 "linux,name", &wled->cdev.name);
2301 if (rc && (rc != -EINVAL)) {
2302 dev_err(&pdev->dev, "Unable to read led name\n");
2306 wled->cdev.default_trigger = QPNP_WLED_TRIGGER_NONE;
2307 rc = of_property_read_string(pdev->dev.of_node, "linux,default-trigger",
2308 &wled->cdev.default_trigger);
2309 if (rc && (rc != -EINVAL)) {
2310 dev_err(&pdev->dev, "Unable to read led trigger\n");
2314 if (of_find_property(pdev->dev.of_node, "qcom,wled-brightness-map",
2316 size = of_property_count_elems_of_size(pdev->dev.of_node,
2317 "qcom,wled-brightness-map", sizeof(u16));
2318 if (size != NUM_DDIC_CODES) {
2319 pr_err("Invalid WLED brightness map size:%d\n", size);
2323 wled->brt_map_table = devm_kcalloc(&pdev->dev, NUM_DDIC_CODES,
2324 sizeof(u16), GFP_KERNEL);
2325 if (!wled->brt_map_table)
2328 rc = of_property_read_u16_array(pdev->dev.of_node,
2329 "qcom,wled-brightness-map", wled->brt_map_table,
2332 pr_err("Error in reading WLED brightness map, rc=%d\n",
2337 for (i = 0; i < NUM_DDIC_CODES; i++) {
2338 if (wled->brt_map_table[i] > WLED_MAX_LEVEL_4095) {
2339 pr_err("WLED brightness map not in range\n");
2343 if ((i > 1) && wled->brt_map_table[i]
2344 < wled->brt_map_table[i - 1]) {
2345 pr_err("WLED brightness map not in ascending order?\n");
2351 wled->stepper_en = of_property_read_bool(pdev->dev.of_node,
2352 "qcom,wled-stepper-en");
2353 wled->disp_type_amoled = of_property_read_bool(pdev->dev.of_node,
2354 "qcom,disp-type-amoled");
2355 if (wled->disp_type_amoled) {
2356 wled->vref_psm_mv = QPNP_WLED_VREF_PSM_DFLT_AMOLED_MV;
2357 rc = of_property_read_u32(pdev->dev.of_node,
2358 "qcom,vref-psm-mv", &temp_val);
2360 wled->vref_psm_mv = temp_val;
2361 } else if (rc != -EINVAL) {
2362 dev_err(&pdev->dev, "Unable to read vref-psm\n");
2366 wled->loop_comp_res_kohm = 320;
2367 if (wled->pmic_rev_id->pmic_subtype == PMI8998_SUBTYPE ||
2368 wled->pmic_rev_id->pmic_subtype == PM660L_SUBTYPE)
2369 wled->loop_comp_res_kohm = 300;
2371 rc = of_property_read_u32(pdev->dev.of_node,
2372 "qcom,loop-comp-res-kohm", &temp_val);
2374 wled->loop_comp_res_kohm = temp_val;
2375 } else if (rc != -EINVAL) {
2376 dev_err(&pdev->dev, "Unable to read loop-comp-res-kohm\n");
2380 wled->avdd_mode_spmi = of_property_read_bool(pdev->dev.of_node,
2381 "qcom,avdd-mode-spmi");
2383 wled->avdd_target_voltage_mv = QPNP_WLED_DFLT_AVDD_MV;
2384 rc = of_property_read_u32(pdev->dev.of_node,
2385 "qcom,avdd-target-voltage-mv", &temp_val);
2387 wled->avdd_target_voltage_mv = temp_val;
2388 } else if (rc != -EINVAL) {
2389 dev_err(&pdev->dev, "Unable to read avdd target voltage\n");
2394 if (wled->disp_type_amoled) {
2395 if (wled->pmic_rev_id->pmic_subtype == PMI8998_SUBTYPE ||
2396 wled->pmic_rev_id->pmic_subtype == PM660L_SUBTYPE)
2398 QPNP_WLED_LOOP_GM_DFLT_AMOLED_PMI8998;
2401 QPNP_WLED_LOOP_EA_GM_DFLT_AMOLED_PMI8994;
2403 wled->loop_ea_gm = QPNP_WLED_LOOP_GM_DFLT_WLED;
2406 rc = of_property_read_u32(pdev->dev.of_node,
2407 "qcom,loop-ea-gm", &temp_val);
2409 wled->loop_ea_gm = temp_val;
2410 } else if (rc != -EINVAL) {
2411 dev_err(&pdev->dev, "Unable to read loop-ea-gm\n");
2415 if (wled->pmic_rev_id->pmic_subtype == PMI8998_SUBTYPE ||
2416 wled->pmic_rev_id->pmic_subtype == PM660L_SUBTYPE) {
2417 wled->loop_auto_gm_en =
2418 of_property_read_bool(pdev->dev.of_node,
2419 "qcom,loop-auto-gm-en");
2420 wled->loop_auto_gm_thresh = QPNP_WLED_LOOP_AUTO_GM_DFLT_THRESH;
2421 rc = of_property_read_u8(pdev->dev.of_node,
2422 "qcom,loop-auto-gm-thresh",
2423 &wled->loop_auto_gm_thresh);
2424 if (rc && rc != -EINVAL) {
2426 "Unable to read loop-auto-gm-thresh\n");
2431 if (wled->pmic_rev_id->pmic_subtype == PMI8998_SUBTYPE ||
2432 wled->pmic_rev_id->pmic_subtype == PM660L_SUBTYPE) {
2434 if (wled->pmic_rev_id->pmic_subtype == PMI8998_SUBTYPE &&
2435 wled->pmic_rev_id->rev4 == PMI8998_V2P0_REV4)
2436 wled->lcd_auto_pfm_en = false;
2438 wled->lcd_auto_pfm_en = true;
2440 wled->lcd_auto_pfm_thresh = QPNP_WLED_LCD_AUTO_PFM_DFLT_THRESH;
2441 rc = of_property_read_u8(pdev->dev.of_node,
2442 "qcom,lcd-auto-pfm-thresh",
2443 &wled->lcd_auto_pfm_thresh);
2444 if (rc && rc != -EINVAL) {
2446 "Unable to read lcd-auto-pfm-thresh\n");
2450 if (wled->lcd_auto_pfm_thresh >
2451 QPNP_WLED_LCD_AUTO_PFM_THRESH_MAX)
2452 wled->lcd_auto_pfm_thresh =
2453 QPNP_WLED_LCD_AUTO_PFM_THRESH_MAX;
2456 wled->sc_deb_cycles = QPNP_WLED_SC_DEB_CYCLES_DFLT;
2457 rc = of_property_read_u32(pdev->dev.of_node,
2458 "qcom,sc-deb-cycles", &temp_val);
2460 wled->sc_deb_cycles = temp_val;
2461 } else if (rc != -EINVAL) {
2462 dev_err(&pdev->dev, "Unable to read sc debounce cycles\n");
2466 wled->fdbk_op = QPNP_WLED_FDBK_AUTO;
2467 rc = of_property_read_string(pdev->dev.of_node,
2468 "qcom,fdbk-output", &temp_str);
2470 if (strcmp(temp_str, "wled1") == 0)
2471 wled->fdbk_op = QPNP_WLED_FDBK_WLED1;
2472 else if (strcmp(temp_str, "wled2") == 0)
2473 wled->fdbk_op = QPNP_WLED_FDBK_WLED2;
2474 else if (strcmp(temp_str, "wled3") == 0)
2475 wled->fdbk_op = QPNP_WLED_FDBK_WLED3;
2476 else if (strcmp(temp_str, "wled4") == 0)
2477 wled->fdbk_op = QPNP_WLED_FDBK_WLED4;
2479 wled->fdbk_op = QPNP_WLED_FDBK_AUTO;
2480 } else if (rc != -EINVAL) {
2481 dev_err(&pdev->dev, "Unable to read feedback output\n");
2485 if (wled->pmic_rev_id->pmic_subtype == PMI8998_SUBTYPE ||
2486 wled->pmic_rev_id->pmic_subtype == PM660L_SUBTYPE)
2487 wled->vref_uv = vref_setting_pmi8998.default_uv;
2489 wled->vref_uv = vref_setting_pmi8994.default_uv;
2490 rc = of_property_read_u32(pdev->dev.of_node,
2491 "qcom,vref-uv", &temp_val);
2493 wled->vref_uv = temp_val;
2494 } else if (rc != -EINVAL) {
2495 dev_err(&pdev->dev, "Unable to read vref\n");
2499 wled->switch_freq_khz = wled->disp_type_amoled ? 1600 : 800;
2500 rc = of_property_read_u32(pdev->dev.of_node,
2501 "qcom,switch-freq-khz", &temp_val);
2503 wled->switch_freq_khz = temp_val;
2504 } else if (rc != -EINVAL) {
2505 dev_err(&pdev->dev, "Unable to read switch freq\n");
2509 if (wled->pmic_rev_id->pmic_subtype == PMI8998_SUBTYPE ||
2510 wled->pmic_rev_id->pmic_subtype == PM660L_SUBTYPE)
2511 wled->ovp_mv = 29600;
2513 wled->ovp_mv = 29500;
2514 rc = of_property_read_u32(pdev->dev.of_node,
2515 "qcom,ovp-mv", &temp_val);
2517 wled->ovp_mv = temp_val;
2518 } else if (rc != -EINVAL) {
2519 dev_err(&pdev->dev, "Unable to read ovp\n");
2523 if (wled->pmic_rev_id->pmic_subtype == PMI8998_SUBTYPE ||
2524 wled->pmic_rev_id->pmic_subtype == PM660L_SUBTYPE) {
2525 if (wled->disp_type_amoled)
2526 wled->ilim_ma = PMI8998_AMOLED_DFLT_ILIM_MA;
2528 wled->ilim_ma = PMI8998_WLED_DFLT_ILIM_MA;
2530 if (wled->disp_type_amoled)
2531 wled->ilim_ma = PMI8994_AMOLED_DFLT_ILIM_MA;
2533 wled->ilim_ma = PMI8994_WLED_DFLT_ILIM_MA;
2536 rc = of_property_read_u32(pdev->dev.of_node,
2537 "qcom,ilim-ma", &temp_val);
2539 wled->ilim_ma = temp_val;
2540 } else if (rc != -EINVAL) {
2541 dev_err(&pdev->dev, "Unable to read ilim\n");
2545 wled->boost_duty_ns = QPNP_WLED_DEF_BOOST_DUTY_NS;
2546 rc = of_property_read_u32(pdev->dev.of_node,
2547 "qcom,boost-duty-ns", &temp_val);
2549 wled->boost_duty_ns = temp_val;
2550 } else if (rc != -EINVAL) {
2551 dev_err(&pdev->dev, "Unable to read boost duty\n");
2555 wled->mod_freq_khz = QPNP_WLED_MOD_FREQ_9600_KHZ;
2556 rc = of_property_read_u32(pdev->dev.of_node,
2557 "qcom,mod-freq-khz", &temp_val);
2559 wled->mod_freq_khz = temp_val;
2560 } else if (rc != -EINVAL) {
2561 dev_err(&pdev->dev, "Unable to read modulation freq\n");
2565 wled->dim_mode = QPNP_WLED_DIM_HYBRID;
2566 rc = of_property_read_string(pdev->dev.of_node,
2567 "qcom,dim-mode", &temp_str);
2569 if (strcmp(temp_str, "analog") == 0)
2570 wled->dim_mode = QPNP_WLED_DIM_ANALOG;
2571 else if (strcmp(temp_str, "digital") == 0)
2572 wled->dim_mode = QPNP_WLED_DIM_DIGITAL;
2574 wled->dim_mode = QPNP_WLED_DIM_HYBRID;
2575 } else if (rc != -EINVAL) {
2576 dev_err(&pdev->dev, "Unable to read dim mode\n");
2580 if (wled->dim_mode == QPNP_WLED_DIM_HYBRID) {
2581 wled->hyb_thres = QPNP_WLED_DEF_HYB_THRES;
2582 rc = of_property_read_u32(pdev->dev.of_node,
2583 "qcom,hyb-thres", &temp_val);
2585 wled->hyb_thres = temp_val;
2586 } else if (rc != -EINVAL) {
2587 dev_err(&pdev->dev, "Unable to read hyb threshold\n");
2592 wled->sync_dly_us = QPNP_WLED_DEF_SYNC_DLY_US;
2593 rc = of_property_read_u32(pdev->dev.of_node,
2594 "qcom,sync-dly-us", &temp_val);
2596 wled->sync_dly_us = temp_val;
2597 } else if (rc != -EINVAL) {
2598 dev_err(&pdev->dev, "Unable to read sync delay\n");
2602 wled->fs_curr_ua = QPNP_WLED_FS_CURR_MAX_UA;
2603 rc = of_property_read_u32(pdev->dev.of_node,
2604 "qcom,fs-curr-ua", &temp_val);
2606 wled->fs_curr_ua = temp_val;
2607 } else if (rc != -EINVAL) {
2608 dev_err(&pdev->dev, "Unable to read full scale current\n");
2612 wled->cons_sync_write_delay_us = 0;
2613 rc = of_property_read_u32(pdev->dev.of_node,
2614 "qcom,cons-sync-write-delay-us", &temp_val);
2616 wled->cons_sync_write_delay_us = temp_val;
2618 wled->en_9b_dim_res = of_property_read_bool(pdev->dev.of_node,
2619 "qcom,en-9b-dim-res");
2620 wled->en_phase_stag = of_property_read_bool(pdev->dev.of_node,
2621 "qcom,en-phase-stag");
2622 wled->en_cabc = of_property_read_bool(pdev->dev.of_node,
2625 if (wled->pmic_rev_id->pmic_subtype == PM660L_SUBTYPE)
2626 wled->max_strings = QPNP_PM660_WLED_MAX_STRINGS;
2628 wled->max_strings = QPNP_WLED_MAX_STRINGS;
2630 prop = of_find_property(pdev->dev.of_node,
2631 "qcom,led-strings-list", &temp_val);
2632 if (!prop || !temp_val || temp_val > QPNP_WLED_MAX_STRINGS) {
2633 dev_err(&pdev->dev, "Invalid strings info, use default");
2634 wled->num_strings = wled->max_strings;
2635 for (i = 0; i < wled->num_strings; i++)
2636 wled->strings[i] = i;
2638 wled->num_strings = temp_val;
2639 strings = prop->value;
2640 for (i = 0; i < wled->num_strings; ++i)
2641 wled->strings[i] = strings[i];
2644 wled->ovp_irq = platform_get_irq_byname(pdev, "ovp-irq");
2645 if (wled->ovp_irq < 0)
2646 dev_dbg(&pdev->dev, "ovp irq is not used\n");
2648 wled->sc_irq = platform_get_irq_byname(pdev, "sc-irq");
2649 if (wled->sc_irq < 0)
2650 dev_dbg(&pdev->dev, "sc irq is not used\n");
2652 wled->en_ext_pfet_sc_pro = of_property_read_bool(pdev->dev.of_node,
2653 "qcom,en-ext-pfet-sc-pro");
2655 wled->lcd_psm_ctrl = of_property_read_bool(pdev->dev.of_node,
2656 "qcom,lcd-psm-ctrl");
2658 wled->auto_calib_enabled = of_property_read_bool(pdev->dev.of_node,
2659 "qcom,auto-calibration-enable");
2663 static int qpnp_wled_probe(struct platform_device *pdev)
2665 struct qpnp_wled *wled;
2666 struct device_node *revid_node;
2670 wled = devm_kzalloc(&pdev->dev, sizeof(*wled), GFP_KERNEL);
2674 wled->regmap = dev_get_regmap(pdev->dev.parent, NULL);
2675 if (!wled->regmap) {
2676 dev_err(&pdev->dev, "Couldn't get parent's regmap\n");
2682 revid_node = of_parse_phandle(pdev->dev.of_node, "qcom,pmic-revid", 0);
2684 pr_err("Missing qcom,pmic-revid property - driver failed\n");
2688 wled->pmic_rev_id = get_revid_data(revid_node);
2689 of_node_put(revid_node);
2690 if (IS_ERR_OR_NULL(wled->pmic_rev_id)) {
2691 pr_err("Unable to get pmic_revid rc=%ld\n",
2692 PTR_ERR(wled->pmic_rev_id));
2694 * the revid peripheral must be registered, any failure
2695 * here only indicates that the rev-id module has not
2698 return -EPROBE_DEFER;
2701 pr_debug("PMIC subtype %d Digital major %d\n",
2702 wled->pmic_rev_id->pmic_subtype, wled->pmic_rev_id->rev4);
2704 wled->wq = alloc_ordered_workqueue("qpnp_wled_wq", WQ_HIGHPRI);
2706 pr_err("Unable to alloc workqueue for WLED\n");
2710 prop = of_get_address_by_name(pdev->dev.of_node, QPNP_WLED_SINK_BASE,
2713 dev_err(&pdev->dev, "Couldnt find sink's addr rc %d\n", rc);
2716 wled->sink_base = be32_to_cpu(*prop);
2718 prop = of_get_address_by_name(pdev->dev.of_node, QPNP_WLED_CTRL_BASE,
2721 dev_err(&pdev->dev, "Couldnt find ctrl's addr rc = %d\n", rc);
2724 wled->ctrl_base = be32_to_cpu(*prop);
2726 dev_set_drvdata(&pdev->dev, wled);
2728 rc = qpnp_wled_parse_dt(wled);
2730 dev_err(&pdev->dev, "DT parsing failed\n");
2734 mutex_init(&wled->bus_lock);
2735 mutex_init(&wled->lock);
2736 rc = qpnp_wled_config(wled);
2738 dev_err(&pdev->dev, "wled config failed\n");
2742 INIT_WORK(&wled->work, qpnp_wled_work);
2743 wled->ramp_ms = QPNP_WLED_RAMP_DLY_MS;
2744 wled->ramp_step = 1;
2746 wled->cdev.brightness_set = qpnp_wled_set;
2747 wled->cdev.brightness_get = qpnp_wled_get;
2749 wled->cdev.max_brightness = WLED_MAX_LEVEL_4095;
2751 rc = led_classdev_register(&pdev->dev, &wled->cdev);
2753 dev_err(&pdev->dev, "wled registration failed(%d)\n", rc);
2754 goto wled_register_fail;
2757 for (i = 0; i < ARRAY_SIZE(qpnp_wled_attrs); i++) {
2758 rc = sysfs_create_file(&wled->cdev.dev->kobj,
2759 &qpnp_wled_attrs[i].attr);
2761 dev_err(&pdev->dev, "sysfs creation failed\n");
2769 for (i--; i >= 0; i--)
2770 sysfs_remove_file(&wled->cdev.dev->kobj,
2771 &qpnp_wled_attrs[i].attr);
2772 led_classdev_unregister(&wled->cdev);
2774 cancel_work_sync(&wled->work);
2775 destroy_workqueue(wled->wq);
2776 mutex_destroy(&wled->lock);
2780 static int qpnp_wled_remove(struct platform_device *pdev)
2782 struct qpnp_wled *wled = dev_get_drvdata(&pdev->dev);
2785 for (i = 0; i < ARRAY_SIZE(qpnp_wled_attrs); i++)
2786 sysfs_remove_file(&wled->cdev.dev->kobj,
2787 &qpnp_wled_attrs[i].attr);
2789 led_classdev_unregister(&wled->cdev);
2790 cancel_work_sync(&wled->work);
2791 destroy_workqueue(wled->wq);
2792 mutex_destroy(&wled->lock);
2797 static const struct of_device_id spmi_match_table[] = {
2798 { .compatible = "qcom,qpnp-wled",},
2802 static struct platform_driver qpnp_wled_driver = {
2804 .name = "qcom,qpnp-wled",
2805 .of_match_table = spmi_match_table,
2807 .probe = qpnp_wled_probe,
2808 .remove = qpnp_wled_remove,
2811 static int __init qpnp_wled_init(void)
2813 return platform_driver_register(&qpnp_wled_driver);
2815 module_init(qpnp_wled_init);
2817 static void __exit qpnp_wled_exit(void)
2819 platform_driver_unregister(&qpnp_wled_driver);
2821 module_exit(qpnp_wled_exit);
2823 MODULE_DESCRIPTION("QPNP WLED driver");
2824 MODULE_LICENSE("GPL v2");
2825 MODULE_ALIAS("leds:leds-qpnp-wled");