OSDN Git Service

drivers: leds: Import Xiaomi changes
[sagit-ice-cold/kernel_xiaomi_msm8998.git] / drivers / leds / leds-qpnp-wled.c
1 /* Copyright (c) 2014-2017, The Linux Foundation. All rights reserved.
2  * Copyright (C) 2018 XiaoMi, Inc.
3  *
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.
7  *
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.
12  */
13
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>
30
31 /* base addresses */
32 #define QPNP_WLED_CTRL_BASE             "qpnp-wled-ctrl-base"
33 #define QPNP_WLED_SINK_BASE             "qpnp-wled-sink-base"
34
35 /* ctrl registers */
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)
58
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)
64
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)
94
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)
125
126 /* QPNP_WLED_SOFTSTART_RAMP_DLY */
127 #define SOFTSTART_OVERWRITE_BIT         BIT(7)
128 #define SOFTSTART_RAMP_DELAY_MASK       GENMASK(2, 0)
129
130 /* sink registers */
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)
142
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
184
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)
188
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
192
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
211
212 #define QPNP_WLED_SEC_ACCESS_REG(b)    (b + 0xD0)
213 #define QPNP_WLED_SEC_UNLOCK           0xA5
214
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
225
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)
235
236 #define NUM_SUPPORTED_OVP_THRESHOLDS    4
237 #define NUM_SUPPORTED_ILIM_THRESHOLDS   8
238
239 #define QPNP_WLED_AVDD_MV_TO_REG(val) \
240                 ((val - QPNP_WLED_AVDD_MIN_MV) / QPNP_WLED_AVDD_STEP_MV)
241
242 /* output feedback mode */
243 enum qpnp_wled_fdbk_op {
244         QPNP_WLED_FDBK_AUTO,
245         QPNP_WLED_FDBK_WLED1,
246         QPNP_WLED_FDBK_WLED2,
247         QPNP_WLED_FDBK_WLED3,
248         QPNP_WLED_FDBK_WLED4,
249 };
250
251 /* dimming modes */
252 enum qpnp_wled_dim_mode {
253         QPNP_WLED_DIM_ANALOG,
254         QPNP_WLED_DIM_DIGITAL,
255         QPNP_WLED_DIM_HYBRID,
256 };
257
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
262 };
263
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,
271         0xe6,
272 };
273
274 static int qpnp_wled_avdd_target_voltages[NUM_SUPPORTED_AVDD_VOLTAGES] = {
275         7900, 7600, 7300, 6400, 6100, 5800,
276 };
277
278 static u8 qpnp_wled_ovp_reg_settings[NUM_SUPPORTED_AVDD_VOLTAGES] = {
279         0x0, 0x0, 0x1, 0x2, 0x2, 0x3,
280 };
281
282 static int qpnp_wled_avdd_trim_adjustments[NUM_SUPPORTED_AVDD_VOLTAGES] = {
283         3, 0, -2, 7, 3, 3,
284 };
285
286 static int qpnp_wled_ovp_thresholds_pmi8994[NUM_SUPPORTED_OVP_THRESHOLDS] = {
287         31000, 29500, 19400, 17800,
288 };
289
290 static int qpnp_wled_ovp_thresholds_pmi8998[NUM_SUPPORTED_OVP_THRESHOLDS] = {
291         31100, 29600, 19600, 18100,
292 };
293
294 static int qpnp_wled_ilim_settings_pmi8994[NUM_SUPPORTED_ILIM_THRESHOLDS] = {
295         105, 385, 660, 980, 1150, 1420, 1700, 1980,
296 };
297
298 static int qpnp_wled_ilim_settings_pmi8998[NUM_SUPPORTED_ILIM_THRESHOLDS] = {
299         105, 280, 450, 620, 970, 1150, 1300, 1500,
300 };
301
302 struct wled_vref_setting {
303         u32 min_uv;
304         u32 max_uv;
305         u32 step_uv;
306         u32 default_uv;
307 };
308
309 static struct wled_vref_setting vref_setting_pmi8994 = {
310         300000, 675000, 25000, 350000,
311 };
312 static struct wled_vref_setting vref_setting_pmi8998 = {
313         60000, 397500, 22500, 127500,
314 };
315
316 /**
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
371  */
372 struct qpnp_wled {
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;
379         struct mutex            lock;
380         struct mutex            bus_lock;
381         enum qpnp_wled_fdbk_op  fdbk_op;
382         enum qpnp_wled_dim_mode dim_mode;
383         int                     ovp_irq;
384         int                     sc_irq;
385         u32                     sc_cnt;
386         u32                     avdd_target_voltage_mv;
387         u16                     ctrl_base;
388         u16                     sink_base;
389         u16                     mod_freq_khz;
390         u16                     hyb_thres;
391         u16                     sync_dly_us;
392         u32                     vref_uv;
393         u16                     vref_psm_mv;
394         u16                     loop_comp_res_kohm;
395         u16                     loop_ea_gm;
396         u16                     sc_deb_cycles;
397         u16                     switch_freq_khz;
398         u16                     ovp_mv;
399         u16                     ilim_ma;
400         u16                     boost_duty_ns;
401         u16                     fs_curr_ua;
402         u16                     ramp_ms;
403         u16                     ramp_step;
404         u16                     cons_sync_write_delay_us;
405         u16                     auto_calibration_ovp_count;
406         u16                     max_strings;
407         u16                     prev_level;
408         u16                     *brt_map_table;
409         u8                      strings[QPNP_WLED_MAX_STRINGS];
410         u8                      num_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;
415         bool                    lcd_psm_ctrl;
416         bool                    avdd_mode_spmi;
417         bool                    en_9b_dim_res;
418         bool                    en_phase_stag;
419         bool                    en_cabc;
420         bool                    disp_type_amoled;
421         bool                    en_ext_pfet_sc_pro;
422         bool                    prev_state;
423         bool                    stepper_en;
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;
429 };
430
431 static int qpnp_wled_step_delay_us = 52000;
432 module_param_named(
433         total_step_delay_us, qpnp_wled_step_delay_us, int, 0600
434 );
435
436 static int qpnp_wled_step_size_threshold = 3;
437 module_param_named(
438         step_size_threshold, qpnp_wled_step_size_threshold, int, 0600
439 );
440
441 static int qpnp_wled_step_delay_gain = 2;
442 module_param_named(
443         step_delay_gain, qpnp_wled_step_delay_gain, int, 0600
444 );
445
446 /* helper to read a pmic register */
447 static int qpnp_wled_read_reg(struct qpnp_wled *wled, u16 addr, u8 *data)
448 {
449         int rc;
450         uint val;
451
452         rc = regmap_read(wled->regmap, addr, &val);
453         if (rc < 0) {
454                 dev_err(&wled->pdev->dev,
455                         "Error reading address: %x(%d)\n", addr, rc);
456                 return rc;
457         }
458
459         *data = (u8)val;
460         return 0;
461 }
462
463 /* helper to write a pmic register */
464 static int qpnp_wled_write_reg(struct qpnp_wled *wled, u16 addr, u8 data)
465 {
466         int rc;
467
468         mutex_lock(&wled->bus_lock);
469         rc = regmap_write(wled->regmap, addr, data);
470         if (rc < 0) {
471                 dev_err(&wled->pdev->dev, "Error writing address: %x(%d)\n",
472                         addr, rc);
473                 goto out;
474         }
475
476         dev_dbg(&wled->pdev->dev, "wrote: WLED_0x%x = 0x%x\n", addr, data);
477 out:
478         mutex_unlock(&wled->bus_lock);
479         return rc;
480 }
481
482 static int qpnp_wled_masked_write_reg(struct qpnp_wled *wled, u16 addr,
483                                         u8 mask, u8 data)
484 {
485         int rc;
486
487         mutex_lock(&wled->bus_lock);
488         rc = regmap_update_bits(wled->regmap, addr, mask, data);
489         if (rc < 0) {
490                 dev_err(&wled->pdev->dev, "Error writing address: %x(%d)\n",
491                         addr, rc);
492                 goto out;
493         }
494
495         dev_dbg(&wled->pdev->dev, "wrote: WLED_0x%x = 0x%x\n", addr, data);
496 out:
497         mutex_unlock(&wled->bus_lock);
498         return rc;
499 }
500
501 static int qpnp_wled_sec_write_reg(struct qpnp_wled *wled, u16 addr, u8 data)
502 {
503         int rc;
504         u8 reg = QPNP_WLED_SEC_UNLOCK;
505         u16 base_addr = addr & 0xFF00;
506
507         mutex_lock(&wled->bus_lock);
508         rc = regmap_write(wled->regmap, QPNP_WLED_SEC_ACCESS_REG(base_addr),
509                         reg);
510         if (rc < 0) {
511                 dev_err(&wled->pdev->dev, "Error writing address: %x(%d)\n",
512                         QPNP_WLED_SEC_ACCESS_REG(base_addr), rc);
513                 goto out;
514         }
515
516         rc = regmap_write(wled->regmap, addr, data);
517         if (rc < 0) {
518                 dev_err(&wled->pdev->dev, "Error writing address: %x(%d)\n",
519                         addr, rc);
520                 goto out;
521         }
522
523         dev_dbg(&wled->pdev->dev, "wrote: WLED_0x%x = 0x%x\n", addr, data);
524 out:
525         mutex_unlock(&wled->bus_lock);
526         return rc;
527 }
528
529 static int qpnp_wled_swire_avdd_config(struct qpnp_wled *wled)
530 {
531         int rc;
532         u8 val;
533
534         if (wled->pmic_rev_id->pmic_subtype != PMI8998_SUBTYPE &&
535                 wled->pmic_rev_id->pmic_subtype != PM660L_SUBTYPE)
536                 return 0;
537
538         if (!wled->disp_type_amoled || wled->avdd_mode_spmi)
539                 return 0;
540
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);
544         return rc;
545 }
546
547 static int qpnp_wled_sync_reg_toggle(struct qpnp_wled *wled)
548 {
549         int rc;
550         u8 reg;
551
552         /* sync */
553         reg = QPNP_WLED_SYNC;
554         rc = qpnp_wled_write_reg(wled, QPNP_WLED_SYNC_REG(wled->sink_base),
555                         reg);
556         if (rc < 0)
557                 return rc;
558
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);
562
563         reg = QPNP_WLED_SYNC_RESET;
564         rc = qpnp_wled_write_reg(wled, QPNP_WLED_SYNC_REG(wled->sink_base),
565                         reg);
566         if (rc < 0)
567                 return rc;
568
569         return 0;
570 }
571
572 /* set wled to a level of brightness */
573 static int qpnp_wled_set_level(struct qpnp_wled *wled, int level)
574 {
575         int i, rc;
576         u8 reg;
577         u16 low_limit = WLED_MAX_LEVEL_4095 * 4 / 1000;
578
579         /* WLED's lower limit of operation is 0.4% */
580         if (level > 0 && level < low_limit)
581                 level = low_limit;
582
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);
589                 if (rc < 0)
590                         return rc;
591
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);
597                 if (rc < 0)
598                         return rc;
599         }
600
601         rc = qpnp_wled_sync_reg_toggle(wled);
602         if (rc < 0) {
603                 dev_err(&wled->pdev->dev, "Failed to toggle sync reg %d\n", rc);
604                 return rc;
605         }
606
607         pr_debug("level:%d\n", level);
608         return 0;
609 }
610
611 static int qpnp_wled_set_map_level(struct qpnp_wled *wled, int level)
612 {
613         int rc, i;
614
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]);
618                         if (rc < 0) {
619                                 pr_err("set brightness level failed, rc:%d\n",
620                                         rc);
621                                 return rc;
622                         }
623                 }
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]);
627                         if (rc < 0) {
628                                 pr_err("set brightness level failed, rc:%d\n",
629                                         rc);
630                                 return rc;
631                         }
632                 }
633         }
634
635         return 0;
636 }
637
638 static int qpnp_wled_set_step_level(struct qpnp_wled *wled, int new_level)
639 {
640         int rc, i, num_steps, delay_us;
641         u16 level, start_level, end_level, step_size;
642         bool level_inc = false;
643
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);
648
649         num_steps = abs(start_level - end_level);
650         if (!num_steps)
651                 return 0;
652
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);
656
657         if (delay_us < 500) {
658                 step_size = 1000 / delay_us;
659                 num_steps = num_steps / step_size;
660                 delay_us = 1000;
661         } else {
662                 if (num_steps < qpnp_wled_step_size_threshold)
663                         delay_us *= qpnp_wled_step_delay_gain;
664
665                 step_size = 1;
666         }
667
668         i = start_level;
669         while (num_steps--) {
670                 if (level_inc)
671                         i += step_size;
672                 else
673                         i -= step_size;
674
675                 rc = qpnp_wled_set_level(wled, i);
676                 if (rc < 0)
677                         return rc;
678
679                 if (delay_us > 0) {
680                         if (delay_us < 20000)
681                                 usleep_range(delay_us, delay_us + 1);
682                         else
683                                 msleep(delay_us / USEC_PER_MSEC);
684                 }
685         }
686
687         if (i != end_level) {
688                 i = end_level;
689                 rc = qpnp_wled_set_level(wled, i);
690                 if (rc < 0)
691                         return rc;
692         }
693
694         return 0;
695 }
696
697 static int qpnp_wled_psm_config(struct qpnp_wled *wled, bool enable)
698 {
699         int rc;
700
701         if (!wled->lcd_psm_ctrl)
702                 return 0;
703
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);
708         if (rc < 0)
709                 return rc;
710
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);
715         if (rc < 0)
716                 return rc;
717
718         return 0;
719 }
720
721 static int qpnp_wled_module_en(struct qpnp_wled *wled,
722                                 u16 base_addr, bool state)
723 {
724         int rc;
725
726         if (wled->module_dis_perm)
727                 return 0;
728
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);
733         if (rc < 0)
734                 return rc;
735
736         /*
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.
741          */
742         if (state) {
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);
746                 if (rc < 0)
747                         return rc;
748
749                 if (wled->ovp_irq > 0 && wled->ovp_irq_disabled) {
750                         enable_irq(wled->ovp_irq);
751                         wled->ovp_irq_disabled = false;
752                 }
753         } else {
754                 if (wled->ovp_irq > 0 && !wled->ovp_irq_disabled) {
755                         disable_irq(wled->ovp_irq);
756                         wled->ovp_irq_disabled = true;
757                 }
758
759                 rc = qpnp_wled_psm_config(wled, true);
760                 if (rc < 0)
761                         return rc;
762         }
763
764         return 0;
765 }
766
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)
770 {
771         struct qpnp_wled *wled = dev_get_drvdata(dev);
772         int i, rc;
773
774         mutex_lock(&wled->lock);
775
776         if (!wled->cdev.brightness) {
777                 rc = qpnp_wled_module_en(wled, wled->ctrl_base, true);
778                 if (rc) {
779                         dev_err(&wled->pdev->dev, "wled enable failed\n");
780                         goto unlock_mutex;
781                 }
782         }
783
784         /* ramp up */
785         for (i = 0; i <= wled->cdev.max_brightness;) {
786                 rc = qpnp_wled_set_level(wled, i);
787                 if (rc) {
788                         dev_err(&wled->pdev->dev, "wled set level failed\n");
789                         goto restore_brightness;
790                 }
791
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);
795                 else
796                         msleep(wled->ramp_ms);
797
798                 if (i == wled->cdev.max_brightness)
799                         break;
800
801                 i += wled->ramp_step;
802                 if (i > wled->cdev.max_brightness)
803                         i = wled->cdev.max_brightness;
804         }
805
806         /* ramp down */
807         for (i = wled->cdev.max_brightness; i >= 0;) {
808                 rc = qpnp_wled_set_level(wled, i);
809                 if (rc) {
810                         dev_err(&wled->pdev->dev, "wled set level failed\n");
811                         goto restore_brightness;
812                 }
813
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);
817                 else
818                         msleep(wled->ramp_ms);
819
820                 if (i == 0)
821                         break;
822
823                 i -= wled->ramp_step;
824                 if (i < 0)
825                         i = 0;
826         }
827
828         dev_info(&wled->pdev->dev, "wled ramp complete\n");
829
830 restore_brightness:
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);
835                 if (rc)
836                         dev_err(&wled->pdev->dev, "wled enable failed\n");
837         }
838 unlock_mutex:
839         mutex_unlock(&wled->lock);
840
841         return count;
842 }
843
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)
847 {
848         int i, rc;
849         u8 reg;
850
851         for (i = 0; i < size; i++) {
852                 rc = qpnp_wled_read_reg(wled, base_addr + dbg_regs[i], &reg);
853                 if (rc < 0)
854                         return rc;
855
856                 count += snprintf(buf + count, PAGE_SIZE - count,
857                                 "%s: REG_0x%x = 0x%x\n", label,
858                                 base_addr + dbg_regs[i], reg);
859
860                 if (count >= PAGE_SIZE)
861                         return PAGE_SIZE - 1;
862         }
863
864         return count;
865 }
866
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)
870 {
871         struct qpnp_wled *wled = dev_get_drvdata(dev);
872         int count = 0;
873
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);
878
879         if (count < 0 || count == PAGE_SIZE - 1)
880                 return count;
881
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);
886
887         if (count < 0 || count == PAGE_SIZE - 1)
888                 return count;
889
890         return count;
891 }
892
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)
896 {
897         struct qpnp_wled *wled = dev_get_drvdata(dev);
898
899         return snprintf(buf, PAGE_SIZE, "%d\n", wled->ramp_ms);
900 }
901
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)
905 {
906         struct qpnp_wled *wled = dev_get_drvdata(dev);
907         int data, rc;
908
909         rc = kstrtoint(buf, 10, &data);
910         if (rc)
911                 return rc;
912
913         wled->ramp_ms = data;
914         return count;
915 }
916
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)
920 {
921         struct qpnp_wled *wled = dev_get_drvdata(dev);
922
923         return snprintf(buf, PAGE_SIZE, "%d\n", wled->ramp_step);
924 }
925
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)
929 {
930         struct qpnp_wled *wled = dev_get_drvdata(dev);
931         int data, rc;
932
933         rc = kstrtoint(buf, 10, &data);
934         if (rc)
935                 return rc;
936
937         wled->ramp_step = data;
938         return count;
939 }
940
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)
944 {
945         struct qpnp_wled *wled = dev_get_drvdata(dev);
946         char *str;
947
948         if (wled->dim_mode == QPNP_WLED_DIM_ANALOG)
949                 str = "analog";
950         else if (wled->dim_mode == QPNP_WLED_DIM_DIGITAL)
951                 str = "digital";
952         else
953                 str = "hybrid";
954
955         return snprintf(buf, PAGE_SIZE, "%s\n", str);
956 }
957
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)
961 {
962         struct qpnp_wled *wled = dev_get_drvdata(dev);
963         char str[QPNP_WLED_STR_SIZE + 1];
964         int rc, temp;
965         u8 reg;
966
967         if (snprintf(str, QPNP_WLED_STR_SIZE, "%s", buf) > QPNP_WLED_STR_SIZE)
968                 return -EINVAL;
969
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;
974         else
975                 temp = QPNP_WLED_DIM_HYBRID;
976
977         if (temp == wled->dim_mode)
978                 return count;
979
980         rc = qpnp_wled_read_reg(wled, QPNP_WLED_MOD_REG(wled->sink_base), &reg);
981         if (rc < 0)
982                 return rc;
983
984         if (temp == QPNP_WLED_DIM_HYBRID) {
985                 reg &= QPNP_WLED_DIM_HYB_MASK;
986                 reg |= (1 << QPNP_WLED_DIM_HYB_SHIFT);
987         } else {
988                 reg &= QPNP_WLED_DIM_HYB_MASK;
989                 reg |= (0 << QPNP_WLED_DIM_HYB_SHIFT);
990                 reg &= QPNP_WLED_DIM_ANA_MASK;
991                 reg |= temp;
992         }
993
994         rc = qpnp_wled_write_reg(wled, QPNP_WLED_MOD_REG(wled->sink_base), reg);
995         if (rc)
996                 return rc;
997
998         wled->dim_mode = temp;
999
1000         return count;
1001 }
1002
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)
1006 {
1007         struct qpnp_wled *wled = dev_get_drvdata(dev);
1008
1009         return snprintf(buf, PAGE_SIZE, "%d\n", wled->fs_curr_ua);
1010 }
1011
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)
1015 {
1016         struct qpnp_wled *wled = dev_get_drvdata(dev);
1017         int data, i, rc;
1018         u8 reg;
1019
1020         rc = kstrtoint(buf, 10, &data);
1021         if (rc)
1022                 return rc;
1023
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;
1029
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);
1034                 if (rc < 0)
1035                         return rc;
1036         }
1037
1038         wled->fs_curr_ua = data;
1039
1040         rc = qpnp_wled_sync_reg_toggle(wled);
1041         if (rc < 0) {
1042                 dev_err(&wled->pdev->dev, "Failed to toggle sync reg %d\n", rc);
1043                 return rc;
1044         }
1045
1046         return count;
1047 }
1048
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),
1060 };
1061
1062 /* worker for setting wled brightness */
1063 static void qpnp_wled_work(struct work_struct *work)
1064 {
1065         struct qpnp_wled *wled;
1066         int level, level_255, rc;
1067
1068         wled = container_of(work, struct qpnp_wled, work);
1069
1070         mutex_lock(&wled->lock);
1071         level = wled->cdev.brightness;
1072
1073         if (wled->brt_map_table) {
1074                 /*
1075                  * Change the 12 bit level to 8 bit level and use the mapped
1076                  * values for 12 bit level from brightness map table.
1077                  */
1078                 level_255 = DIV_ROUND_CLOSEST(level, 16);
1079                 if (level_255 > 255)
1080                         level_255 = 255;
1081
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);
1085                 else
1086                         rc = qpnp_wled_set_map_level(wled, level_255);
1087                 if (rc) {
1088                         dev_err(&wled->pdev->dev, "wled set level failed\n");
1089                         goto unlock_mutex;
1090                 }
1091                 wled->prev_level = level_255;
1092         } else if (level) {
1093                 rc = qpnp_wled_set_level(wled, level);
1094                 if (rc) {
1095                         dev_err(&wled->pdev->dev, "wled set level failed\n");
1096                         goto unlock_mutex;
1097                 }
1098         }
1099
1100         if (!!level != wled->prev_state) {
1101                 if (!!level) {
1102                         /*
1103                          * For AMOLED display in pmi8998, SWIRE_AVDD_DEFAULT has
1104                          * to be reconfigured every time the module is enabled.
1105                          */
1106                         rc = qpnp_wled_swire_avdd_config(wled);
1107                         if (rc < 0) {
1108                                 pr_err("Write to SWIRE_AVDD_DEFAULT register failed rc:%d\n",
1109                                         rc);
1110                                 goto unlock_mutex;
1111                         }
1112                 }
1113
1114                 rc = qpnp_wled_module_en(wled, wled->ctrl_base, !!level);
1115                 if (rc) {
1116                         dev_err(&wled->pdev->dev, "wled %sable failed\n",
1117                                                 level ? "en" : "dis");
1118                         goto unlock_mutex;
1119                 }
1120         }
1121
1122         wled->prev_state = !!level;
1123 unlock_mutex:
1124         mutex_unlock(&wled->lock);
1125 }
1126
1127 /* get api registered with led classdev for wled brightness */
1128 static enum led_brightness qpnp_wled_get(struct led_classdev *led_cdev)
1129 {
1130         struct qpnp_wled *wled;
1131
1132         wled = container_of(led_cdev, struct qpnp_wled, cdev);
1133
1134         return wled->cdev.brightness;
1135 }
1136
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)
1140 {
1141         struct qpnp_wled *wled;
1142
1143         wled = container_of(led_cdev, struct qpnp_wled, cdev);
1144
1145         if (level < LED_OFF)
1146                 level = LED_OFF;
1147         else if (level > wled->cdev.max_brightness)
1148                 level = wled->cdev.max_brightness;
1149
1150         wled->cdev.brightness = level;
1151         queue_work(wled->wq, &wled->work);
1152 }
1153
1154 static int qpnp_wled_set_disp(struct qpnp_wled *wled, u16 base_addr)
1155 {
1156         int rc;
1157         u8 reg;
1158
1159         /* display type */
1160         rc = qpnp_wled_read_reg(wled, QPNP_WLED_DISP_SEL_REG(base_addr), &reg);
1161         if (rc < 0)
1162                 return rc;
1163
1164         reg &= QPNP_WLED_DISP_SEL_MASK;
1165         reg |= (wled->disp_type_amoled << QPNP_WLED_DISP_SEL_SHIFT);
1166
1167         rc = qpnp_wled_sec_write_reg(wled, QPNP_WLED_DISP_SEL_REG(base_addr),
1168                         reg);
1169         if (rc)
1170                 return rc;
1171
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;
1178
1179                 rc = qpnp_wled_read_reg(wled,
1180                                 QPNP_WLED_PSM_CTRL_REG(wled->ctrl_base), &reg);
1181                 if (rc < 0)
1182                         return rc;
1183
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);
1190                 if (rc)
1191                         return rc;
1192
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;
1201
1202                 rc = qpnp_wled_read_reg(wled,
1203                                 QPNP_WLED_VLOOP_COMP_RES_REG(wled->ctrl_base),
1204                                 &reg);
1205                 if (rc < 0)
1206                         return rc;
1207
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),
1215                                 reg);
1216                 if (rc)
1217                         return rc;
1218
1219                 /* Configure the CTRL TEST4 register for AMOLED */
1220                 rc = qpnp_wled_read_reg(wled,
1221                                 QPNP_WLED_TEST4_REG(wled->ctrl_base), &reg);
1222                 if (rc < 0)
1223                         return rc;
1224
1225                 reg |= QPNP_WLED_TEST4_EN_IIND_UP;
1226                 rc = qpnp_wled_sec_write_reg(wled,
1227                                 QPNP_WLED_TEST4_REG(base_addr), reg);
1228                 if (rc)
1229                         return rc;
1230         } else {
1231                 /*
1232                  * enable VREF_UP to avoid false ovp on low brightness for LCD
1233                  */
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);
1238                 if (rc)
1239                         return rc;
1240         }
1241
1242         return 0;
1243 }
1244
1245 #define AUTO_CALIB_BRIGHTNESS           200
1246 static int wled_auto_calibrate(struct qpnp_wled *wled)
1247 {
1248         int rc = 0, i;
1249         u8 reg = 0, sink_config = 0, sink_test = 0, sink_valid = 0, int_sts;
1250
1251         /* read configured sink configuration */
1252         rc = qpnp_wled_read_reg(wled,
1253                 QPNP_WLED_CURR_SINK_REG(wled->sink_base), &sink_config);
1254         if (rc < 0) {
1255                 pr_err("Failed to read SINK configuration rc=%d\n", rc);
1256                 goto failed_calib;
1257         }
1258
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);
1263         if (rc < 0) {
1264                 pr_err("Failed to disable WLED module rc=%d\n", rc);
1265                 goto failed_calib;
1266         }
1267
1268         /* set low brightness across all sinks */
1269         rc = qpnp_wled_set_level(wled, AUTO_CALIB_BRIGHTNESS);
1270         if (rc < 0) {
1271                 pr_err("Failed to set brightness for calibration rc=%d\n", rc);
1272                 goto failed_calib;
1273         }
1274
1275         if (wled->en_cabc) {
1276                 for (i = 0; i < wled->max_strings; i++) {
1277                         reg = 0;
1278                         rc = qpnp_wled_masked_write_reg(wled,
1279                                 QPNP_WLED_CABC_REG(wled->sink_base, i),
1280                                 QPNP_WLED_CABC_MASK, reg);
1281                         if (rc < 0)
1282                                 goto failed_calib;
1283                 }
1284         }
1285
1286         /* disable all sinks */
1287         rc = qpnp_wled_write_reg(wled,
1288                  QPNP_WLED_CURR_SINK_REG(wled->sink_base), 0);
1289         if (rc < 0) {
1290                 pr_err("Failed to disable all sinks rc=%d\n", rc);
1291                 goto failed_calib;
1292         }
1293
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);
1297
1298                 /* Enable feedback control */
1299                 rc = qpnp_wled_write_reg(wled,
1300                         QPNP_WLED_FDBK_OP_REG(wled->ctrl_base),
1301                         i + 1);
1302                 if (rc < 0) {
1303                         pr_err("Failed to enable feedback for SINK %d rc = %d\n",
1304                                                 i + 1, rc);
1305                         goto failed_calib;
1306                 }
1307
1308                 /* enable the sink */
1309                 rc = qpnp_wled_write_reg(wled,
1310                         QPNP_WLED_CURR_SINK_REG(wled->sink_base), sink_test);
1311                 if (rc < 0) {
1312                         pr_err("Failed to configure SINK %d rc=%d\n",
1313                                                 i + 1, rc);
1314                         goto failed_calib;
1315                 }
1316
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);
1321                 if (rc < 0) {
1322                         pr_err("Failed to enable WLED module rc=%d\n", rc);
1323                         goto failed_calib;
1324                 }
1325
1326                 /* delay for WLED soft-start */
1327                 usleep_range(QPNP_WLED_SOFT_START_DLY_US,
1328                                 QPNP_WLED_SOFT_START_DLY_US + 1000);
1329
1330                 rc = qpnp_wled_read_reg(wled,
1331                         QPNP_WLED_INT_RT_STS(wled->ctrl_base), &int_sts);
1332                 if (rc < 0) {
1333                         pr_err("Error in reading WLED_INT_RT_STS rc=%d\n", rc);
1334                         goto failed_calib;
1335                 }
1336
1337                 if (int_sts & QPNP_WLED_OVP_FAULT_BIT)
1338                         pr_debug("WLED OVP fault detected with SINK %d\n",
1339                                                 i + 1);
1340                 else
1341                         sink_valid |= sink_test;
1342
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);
1347                 if (rc < 0) {
1348                         pr_err("Failed to disable WLED module rc=%d\n", rc);
1349                         goto failed_calib;
1350                 }
1351         }
1352
1353         if (sink_valid == sink_config) {
1354                 pr_debug("WLED auto-calibration complete, default sink-config=%x OK!\n",
1355                                                 sink_config);
1356         } else {
1357                 pr_warn("Invalid WLED default sink config=%x changing it to=%x\n",
1358                                                 sink_config, sink_valid);
1359                 sink_config = sink_valid;
1360         }
1361
1362         if (!sink_config) {
1363                 pr_warn("No valid WLED sinks found\n");
1364                 wled->module_dis_perm = true;
1365                 goto failed_calib;
1366         }
1367
1368         /* write the new sink configuration */
1369         rc = qpnp_wled_write_reg(wled,
1370                         QPNP_WLED_CURR_SINK_REG(wled->sink_base), sink_config);
1371         if (rc < 0) {
1372                 pr_err("Failed to reconfigure the default sink rc=%d\n", rc);
1373                 goto failed_calib;
1374         }
1375
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);
1383                         if (rc < 0)
1384                                 goto failed_calib;
1385                 }
1386
1387                 if (sink_config & (1 << (QPNP_WLED_CURR_SINK_SHIFT + i)))
1388                         reg = (QPNP_WLED_MOD_EN << QPNP_WLED_MOD_EN_SHFT);
1389                 else
1390                         reg = 0x0; /* disable modulator_en for unused sink */
1391
1392                 if (wled->dim_mode == QPNP_WLED_DIM_HYBRID)
1393                         reg &= QPNP_WLED_GATE_DRV_MASK;
1394                 else
1395                         reg |= ~QPNP_WLED_GATE_DRV_MASK;
1396
1397                 rc = qpnp_wled_write_reg(wled,
1398                         QPNP_WLED_MOD_EN_REG(wled->sink_base, i), reg);
1399                 if (rc < 0) {
1400                         pr_err("Failed to configure MODULATOR_EN rc=%d\n", rc);
1401                         goto failed_calib;
1402                 }
1403         }
1404
1405         /* restore the feedback setting */
1406         rc = qpnp_wled_write_reg(wled,
1407                         QPNP_WLED_FDBK_OP_REG(wled->ctrl_base),
1408                         wled->fdbk_op);
1409         if (rc < 0) {
1410                 pr_err("Failed to restore feedback setting rc=%d\n", rc);
1411                 goto failed_calib;
1412         }
1413
1414         /* restore  brightness */
1415         rc = qpnp_wled_set_level(wled, !wled->cdev.brightness ?
1416                         AUTO_CALIB_BRIGHTNESS : wled->cdev.brightness);
1417         if (rc < 0) {
1418                 pr_err("Failed to set brightness after calibration rc=%d\n",
1419                                                 rc);
1420                 goto failed_calib;
1421         }
1422
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);
1427         if (rc < 0) {
1428                 pr_err("Failed to enable WLED module rc=%d\n", rc);
1429                 goto failed_calib;
1430         }
1431
1432         /* delay for WLED soft-start */
1433         usleep_range(QPNP_WLED_SOFT_START_DLY_US,
1434                         QPNP_WLED_SOFT_START_DLY_US + 1000);
1435
1436 failed_calib:
1437         return rc;
1438 }
1439
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)
1443 {
1444         s64 elapsed_time_us;
1445
1446         /*
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.
1450          */
1451         if (!wled->auto_calibration_ovp_count) {
1452                 wled->start_ovp_fault_time = ktime_get();
1453                 wled->auto_calibration_ovp_count++;
1454         } else {
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;
1459                 else
1460                         wled->auto_calibration_ovp_count++;
1461
1462                 if (wled->auto_calibration_ovp_count >=
1463                                 WLED_AUTO_CAL_OVP_COUNT) {
1464                         wled->auto_calibration_ovp_count = 0;
1465                         return true;
1466                 }
1467         }
1468
1469         return false;
1470 }
1471
1472 static int qpnp_wled_auto_calibrate_at_init(struct qpnp_wled *wled)
1473 {
1474         int rc;
1475         u8 fault_status = 0, rt_status = 0;
1476
1477         if (!wled->auto_calib_enabled)
1478                 return 0;
1479
1480         rc = qpnp_wled_read_reg(wled,
1481                         QPNP_WLED_INT_RT_STS(wled->ctrl_base), &rt_status);
1482         if (rc < 0)
1483                 pr_err("Failed to read RT status rc=%d\n", rc);
1484
1485         rc = qpnp_wled_read_reg(wled,
1486                         QPNP_WLED_FAULT_STATUS(wled->ctrl_base), &fault_status);
1487         if (rc < 0)
1488                 pr_err("Failed to read fault status rc=%d\n", rc);
1489
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);
1494                 if (rc < 0)
1495                         pr_err("Failed auto-calibration rc=%d\n", rc);
1496                 else
1497                         wled->auto_calib_done = true;
1498                 mutex_unlock(&wled->lock);
1499         }
1500
1501         return rc;
1502 }
1503
1504 /* ovp irq handler */
1505 static irqreturn_t qpnp_wled_ovp_irq_handler(int irq, void *_wled)
1506 {
1507         struct qpnp_wled *wled = _wled;
1508         int rc;
1509         u8 fault_sts, int_sts;
1510
1511         rc = qpnp_wled_read_reg(wled,
1512                         QPNP_WLED_INT_RT_STS(wled->ctrl_base), &int_sts);
1513         if (rc < 0) {
1514                 pr_err("Error in reading WLED_INT_RT_STS rc=%d\n", rc);
1515                 return IRQ_HANDLED;
1516         }
1517
1518         rc = qpnp_wled_read_reg(wled,
1519                         QPNP_WLED_FAULT_STATUS(wled->ctrl_base), &fault_sts);
1520         if (rc < 0) {
1521                 pr_err("Error in reading WLED_FAULT_STATUS rc=%d\n", rc);
1522                 goto end;
1523         }
1524
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);
1528
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;
1537                                 }
1538
1539                                 rc = wled_auto_calibrate(wled);
1540                                 if (rc < 0)
1541                                         pr_err("Failed auto-calibration rc=%d\n",
1542                                                                 rc);
1543                                 else
1544                                         wled->auto_calib_done = true;
1545
1546                                 if (wled->ovp_irq > 0 &&
1547                                                 wled->ovp_irq_disabled) {
1548                                         enable_irq(wled->ovp_irq);
1549                                         wled->ovp_irq_disabled = false;
1550                                 }
1551                                 mutex_unlock(&wled->lock);
1552                         }
1553                 }
1554         }
1555
1556 end:
1557         disable_irq_nosync(wled->ovp_irq);
1558         wled->ovp_irq_disabled = true;
1559         return IRQ_HANDLED;
1560 }
1561
1562 /* short circuit irq handler */
1563 static irqreturn_t qpnp_wled_sc_irq_handler(int irq, void *_wled)
1564 {
1565         struct qpnp_wled *wled = _wled;
1566         int rc;
1567         u8 val;
1568
1569         rc = qpnp_wled_read_reg(wled,
1570                         QPNP_WLED_FAULT_STATUS(wled->ctrl_base), &val);
1571         if (rc < 0) {
1572                 pr_err("Error in reading WLED_FAULT_STATUS rc=%d\n", rc);
1573                 return IRQ_HANDLED;
1574         }
1575
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);
1583
1584         return IRQ_HANDLED;
1585 }
1586
1587 static bool is_avdd_trim_adjustment_required(struct qpnp_wled *wled)
1588 {
1589         int rc;
1590         u8 reg = 0;
1591
1592         /*
1593          * AVDD trim adjustment is not required for pmi8998/pm660l and not
1594          * supported for pmi8994.
1595          */
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)
1599                 return false;
1600
1601         /*
1602          * Configure TRIM_REG only if disp_type_amoled and it has
1603          * not already been programmed by bootloader.
1604          */
1605         if (!wled->disp_type_amoled)
1606                 return false;
1607
1608         rc = qpnp_wled_read_reg(wled,
1609                         QPNP_WLED_CTRL_SPARE_REG(wled->ctrl_base), &reg);
1610         if (rc < 0)
1611                 return false;
1612
1613         return !(reg & QPNP_WLED_AVDD_SET_BIT);
1614 }
1615
1616 static int qpnp_wled_gm_config(struct qpnp_wled *wled)
1617 {
1618         int rc;
1619         u8 mask = 0, reg = 0;
1620
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) {
1625                         reg = 0;
1626                         mask |= QPNP_WLED_VLOOP_COMP_AUTO_GM_EN |
1627                                 QPNP_WLED_VLOOP_COMP_AUTO_GM_THRESH_MASK;
1628                 } else {
1629                         if (wled->loop_auto_gm_en)
1630                                 reg |= QPNP_WLED_VLOOP_COMP_AUTO_GM_EN;
1631
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;
1636
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;
1641                 }
1642         }
1643
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;
1648
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;
1652
1653         rc = qpnp_wled_masked_write_reg(wled,
1654                         QPNP_WLED_VLOOP_COMP_GM_REG(wled->ctrl_base), mask,
1655                         reg);
1656         if (rc)
1657                 pr_err("write VLOOP_COMP_GM_REG failed, rc=%d]\n", rc);
1658
1659         return rc;
1660 }
1661
1662 static int qpnp_wled_ovp_config(struct qpnp_wled *wled)
1663 {
1664         int rc, i, *ovp_table;
1665         u8 reg;
1666
1667         /*
1668          * Configure the OVP register based on ovp_mv only if display type is
1669          * not AMOLED.
1670          */
1671         if (wled->disp_type_amoled)
1672                 return 0;
1673
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;
1677         else
1678                 ovp_table = qpnp_wled_ovp_thresholds_pmi8994;
1679
1680         for (i = 0; i < NUM_SUPPORTED_OVP_THRESHOLDS; i++) {
1681                 if (wled->ovp_mv == ovp_table[i])
1682                         break;
1683         }
1684
1685         if (i == NUM_SUPPORTED_OVP_THRESHOLDS) {
1686                 dev_err(&wled->pdev->dev,
1687                         "Invalid ovp threshold specified in device tree\n");
1688                 return -EINVAL;
1689         }
1690
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);
1695         if (rc)
1696                 return rc;
1697
1698         return 0;
1699 }
1700
1701 static int qpnp_wled_avdd_trim_config(struct qpnp_wled *wled)
1702 {
1703         int rc, i;
1704         u8 reg;
1705
1706         for (i = 0; i < NUM_SUPPORTED_AVDD_VOLTAGES; i++) {
1707                 if (wled->avdd_target_voltage_mv ==
1708                                 qpnp_wled_avdd_target_voltages[i])
1709                         break;
1710         }
1711
1712         if (i == NUM_SUPPORTED_AVDD_VOLTAGES) {
1713                 dev_err(&wled->pdev->dev,
1714                         "Invalid avdd target voltage specified in device tree\n");
1715                 return -EINVAL;
1716         }
1717
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);
1723         if (rc)
1724                 return rc;
1725
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), &reg);
1729         if (rc)
1730                 return rc;
1731
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",
1737                          (s8)reg);
1738                 if ((s8)reg < QPNP_WLED_AVDD_MIN_TRIM_VAL)
1739                         reg = QPNP_WLED_AVDD_MIN_TRIM_VAL;
1740                 else
1741                         reg = QPNP_WLED_AVDD_MAX_TRIM_VAL;
1742         }
1743
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);
1747         if (rc < 0)
1748                 dev_err(&wled->pdev->dev, "Write to 7P7_TRIM register failed, rc=%d\n",
1749                         rc);
1750         return rc;
1751 }
1752
1753 static int qpnp_wled_avdd_mode_config(struct qpnp_wled *wled)
1754 {
1755         int rc;
1756         u8 reg = 0;
1757
1758         /*
1759          * At present, configuring the mode to SPMI/SWIRE for controlling
1760          * AVDD voltage is available only in pmi8998/pm660l.
1761          */
1762         if (wled->pmic_rev_id->pmic_subtype != PMI8998_SUBTYPE &&
1763                 wled->pmic_rev_id->pmic_subtype != PM660L_SUBTYPE)
1764                 return 0;
1765
1766         /* AMOLED_VOUT should be configured for AMOLED */
1767         if (!wled->disp_type_amoled)
1768                 return 0;
1769
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;
1779         }
1780
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),
1786                                 reg);
1787                 if (rc < 0)
1788                         pr_err("Write to AMOLED_VOUT register failed, rc=%d\n",
1789                                 rc);
1790         } else {
1791                 rc = qpnp_wled_swire_avdd_config(wled);
1792                 if (rc < 0)
1793                         pr_err("Write to SWIRE_AVDD_DEFAULT register failed rc:%d\n",
1794                                 rc);
1795         }
1796
1797         return rc;
1798 }
1799
1800 static int qpnp_wled_ilim_config(struct qpnp_wled *wled)
1801 {
1802         int rc, i, *ilim_table;
1803         u8 reg;
1804
1805         if (wled->ilim_ma < PMI8994_WLED_ILIM_MIN_MA)
1806                 wled->ilim_ma = PMI8994_WLED_ILIM_MIN_MA;
1807
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;
1813         } else {
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;
1817         }
1818
1819         for (i = 0; i < NUM_SUPPORTED_ILIM_THRESHOLDS; i++) {
1820                 if (wled->ilim_ma == ilim_table[i])
1821                         break;
1822         }
1823
1824         if (i == NUM_SUPPORTED_ILIM_THRESHOLDS) {
1825                 dev_err(&wled->pdev->dev,
1826                         "Invalid ilim threshold specified in device tree\n");
1827                 return -EINVAL;
1828         }
1829
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);
1834         if (rc < 0)
1835                 dev_err(&wled->pdev->dev, "Write to ILIM register failed, rc=%d\n",
1836                         rc);
1837         return rc;
1838 }
1839
1840 static int qpnp_wled_vref_config(struct qpnp_wled *wled)
1841 {
1842
1843         struct wled_vref_setting vref_setting;
1844         int rc;
1845         u8 reg = 0;
1846
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;
1850         else
1851                 vref_setting = vref_setting_pmi8994;
1852
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;
1857
1858         reg |= DIV_ROUND_CLOSEST(wled->vref_uv - vref_setting.min_uv,
1859                                         vref_setting.step_uv);
1860
1861         rc = qpnp_wled_masked_write_reg(wled,
1862                         QPNP_WLED_VREF_REG(wled->ctrl_base),
1863                         QPNP_WLED_VREF_MASK, reg);
1864         if (rc)
1865                 pr_err("Write VREF_REG failed, rc=%d\n", rc);
1866
1867         return rc;
1868 }
1869
1870 /* Configure WLED registers */
1871 static int qpnp_wled_config(struct qpnp_wled *wled)
1872 {
1873         int rc, i, temp;
1874         u8 reg = 0, sink_en = 0, mask;
1875
1876         /* Configure display type */
1877         rc = qpnp_wled_set_disp(wled, wled->ctrl_base);
1878         if (rc < 0)
1879                 return rc;
1880
1881         /* Configure the FEEDBACK OUTPUT register */
1882         rc = qpnp_wled_read_reg(wled, QPNP_WLED_FDBK_OP_REG(wled->ctrl_base),
1883                         &reg);
1884         if (rc < 0)
1885                 return rc;
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),
1889                         reg);
1890         if (rc)
1891                 return rc;
1892
1893         /* Configure the VREF register */
1894         rc = qpnp_wled_vref_config(wled);
1895         if (rc < 0) {
1896                 pr_err("Error in configuring wled vref, rc=%d\n", rc);
1897                 return rc;
1898         }
1899
1900         /* Configure VLOOP_COMP_GM register */
1901         rc = qpnp_wled_gm_config(wled);
1902         if (rc < 0) {
1903                 pr_err("Error in configureing wled gm, rc=%d\n", rc);
1904                 return rc;
1905         }
1906
1907         /* Configure the ILIM register */
1908         rc = qpnp_wled_ilim_config(wled);
1909         if (rc < 0) {
1910                 pr_err("Error in configuring wled ilim, rc=%d\n", rc);
1911                 return rc;
1912         }
1913
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) {
1918                 reg = 0;
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);
1926                 if (rc < 0) {
1927                         pr_err("Write LCD_AUTO_PFM failed, rc=%d\n", rc);
1928                         return rc;
1929                 }
1930         }
1931
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;
1940         }
1941
1942         rc = qpnp_wled_masked_write_reg(wled,
1943                         QPNP_WLED_SOFTSTART_RAMP_DLY(wled->ctrl_base),
1944                         mask, reg);
1945         if (rc)
1946                 return rc;
1947
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;
1953
1954         rc = qpnp_wled_read_reg(wled, QPNP_WLED_BOOST_DUTY_REG(wled->ctrl_base),
1955                         &reg);
1956         if (rc < 0)
1957                 return rc;
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);
1962         if (rc)
1963                 return rc;
1964
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;
1970         else
1971                 reg = QPNP_WLED_SWITCH_FREQ_800_KHZ_CODE;
1972
1973         /*
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.
1977          */
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;
1981
1982         rc = qpnp_wled_masked_write_reg(wled,
1983                         QPNP_WLED_SWITCH_FREQ_REG(wled->ctrl_base), mask, reg);
1984         if (rc < 0)
1985                 return rc;
1986
1987         rc = qpnp_wled_ovp_config(wled);
1988         if (rc < 0) {
1989                 pr_err("Error in configuring OVP threshold, rc=%d\n", rc);
1990                 return rc;
1991         }
1992
1993         if (is_avdd_trim_adjustment_required(wled)) {
1994                 rc = qpnp_wled_avdd_trim_config(wled);
1995                 if (rc < 0)
1996                         return rc;
1997         }
1998
1999         rc = qpnp_wled_avdd_mode_config(wled);
2000         if (rc < 0)
2001                 return rc;
2002
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;
2006                 temp = 3;
2007         } else if (wled->mod_freq_khz <= QPNP_WLED_MOD_FREQ_2400_KHZ) {
2008                 wled->mod_freq_khz = QPNP_WLED_MOD_FREQ_2400_KHZ;
2009                 temp = 2;
2010         } else if (wled->mod_freq_khz <= QPNP_WLED_MOD_FREQ_9600_KHZ) {
2011                 wled->mod_freq_khz = QPNP_WLED_MOD_FREQ_9600_KHZ;
2012                 temp = 1;
2013         } else if (wled->mod_freq_khz <= QPNP_WLED_MOD_FREQ_19200_KHZ) {
2014                 wled->mod_freq_khz = QPNP_WLED_MOD_FREQ_19200_KHZ;
2015                 temp = 0;
2016         } else {
2017                 wled->mod_freq_khz = QPNP_WLED_MOD_FREQ_9600_KHZ;
2018                 temp = 1;
2019         }
2020
2021         rc = qpnp_wled_read_reg(wled, QPNP_WLED_MOD_REG(wled->sink_base), &reg);
2022         if (rc < 0)
2023                 return rc;
2024         reg &= QPNP_WLED_MOD_FREQ_MASK;
2025         reg |= (temp << QPNP_WLED_MOD_FREQ_SHIFT);
2026
2027         reg &= QPNP_WLED_PHASE_STAG_MASK;
2028         reg |= (wled->en_phase_stag << QPNP_WLED_PHASE_STAG_SHIFT);
2029
2030         reg &= QPNP_WLED_ACC_CLK_FREQ_MASK;
2031         reg |= (temp << QPNP_WLED_ACC_CLK_FREQ_SHIFT);
2032
2033         reg &= QPNP_WLED_DIM_RES_MASK;
2034         reg |= (wled->en_9b_dim_res << QPNP_WLED_DIM_RES_SHIFT);
2035
2036         if (wled->dim_mode == QPNP_WLED_DIM_HYBRID) {
2037                 reg &= QPNP_WLED_DIM_HYB_MASK;
2038                 reg |= (1 << QPNP_WLED_DIM_HYB_SHIFT);
2039         } else {
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;
2044         }
2045
2046         rc = qpnp_wled_write_reg(wled, QPNP_WLED_MOD_REG(wled->sink_base), reg);
2047         if (rc)
2048                 return rc;
2049
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;
2055
2056         rc = qpnp_wled_read_reg(wled, QPNP_WLED_HYB_THRES_REG(wled->sink_base),
2057                         &reg);
2058         if (rc < 0)
2059                 return rc;
2060         reg &= QPNP_WLED_HYB_THRES_MASK;
2061         temp = fls(wled->hyb_thres / QPNP_WLED_HYB_THRES_MIN) - 1;
2062         reg |= temp;
2063         rc = qpnp_wled_write_reg(wled, QPNP_WLED_HYB_THRES_REG(wled->sink_base),
2064                         reg);
2065         if (rc)
2066                 return rc;
2067
2068         /* Configure TEST5 register */
2069         if (wled->dim_mode == QPNP_WLED_DIM_DIGITAL) {
2070                 reg = QPNP_WLED_SINK_TEST5_DIG;
2071         } else {
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;
2075         }
2076
2077         rc = qpnp_wled_sec_write_reg(wled,
2078                         QPNP_WLED_SINK_TEST5_REG(wled->sink_base), reg);
2079         if (rc)
2080                 return rc;
2081
2082         /* disable all current sinks and enable selected strings */
2083         reg = 0x00;
2084         rc = qpnp_wled_write_reg(wled, QPNP_WLED_CURR_SINK_REG(wled->sink_base),
2085                         reg);
2086
2087         for (i = 0; i < wled->max_strings; i++) {
2088                 /* SYNC DELAY */
2089                 if (wled->sync_dly_us > QPNP_WLED_SYNC_DLY_MAX_US)
2090                         wled->sync_dly_us = QPNP_WLED_SYNC_DLY_MAX_US;
2091
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),
2096                         mask, reg);
2097                 if (rc < 0)
2098                         return rc;
2099
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;
2103
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),
2108                         mask, reg);
2109                 if (rc < 0)
2110                         return rc;
2111
2112                 /* CABC */
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),
2117                         mask, reg);
2118                 if (rc < 0)
2119                         return rc;
2120         }
2121
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");
2126                         return -EINVAL;
2127                 }
2128                 /* MODULATOR */
2129                 rc = qpnp_wled_read_reg(wled,
2130                         QPNP_WLED_MOD_EN_REG(wled->sink_base, i), &reg);
2131                 if (rc < 0)
2132                         return rc;
2133                 reg &= QPNP_WLED_MOD_EN_MASK;
2134                 reg |= (QPNP_WLED_MOD_EN << QPNP_WLED_MOD_EN_SHFT);
2135
2136                 if (wled->dim_mode == QPNP_WLED_DIM_HYBRID)
2137                         reg &= QPNP_WLED_GATE_DRV_MASK;
2138                 else
2139                         reg |= ~QPNP_WLED_GATE_DRV_MASK;
2140
2141                 rc = qpnp_wled_write_reg(wled,
2142                         QPNP_WLED_MOD_EN_REG(wled->sink_base, i), reg);
2143                 if (rc)
2144                         return rc;
2145
2146                 /* SINK EN */
2147                 temp = wled->strings[i] + QPNP_WLED_CURR_SINK_SHIFT;
2148                 sink_en |= (1 << temp);
2149         }
2150         mask = QPNP_WLED_CURR_SINK_MASK;
2151         rc = qpnp_wled_masked_write_reg(wled,
2152                 QPNP_WLED_CURR_SINK_REG(wled->sink_base),
2153                 mask, sink_en);
2154         if (rc < 0) {
2155                 dev_err(&wled->pdev->dev,
2156                         "Failed to enable WLED sink config rc = %d\n", rc);
2157                 return rc;
2158         }
2159
2160         rc = qpnp_wled_sync_reg_toggle(wled);
2161         if (rc < 0) {
2162                 dev_err(&wled->pdev->dev, "Failed to toggle sync reg %d\n", rc);
2163                 return rc;
2164         }
2165
2166         rc = qpnp_wled_auto_calibrate_at_init(wled);
2167         if (rc < 0)
2168                 pr_err("Failed to auto-calibrate at init rc=%d\n", rc);
2169
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);
2175                 if (rc < 0) {
2176                         dev_err(&wled->pdev->dev,
2177                                 "Unable to request ovp(%d) IRQ(err:%d)\n",
2178                                 wled->ovp_irq, rc);
2179                         return rc;
2180                 }
2181                 rc = qpnp_wled_read_reg(wled,
2182                                 QPNP_WLED_MODULE_EN_REG(wled->ctrl_base), &reg);
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;
2187                 }
2188         }
2189
2190         if (wled->sc_irq >= 0) {
2191                 wled->sc_cnt = 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);
2195                 if (rc < 0) {
2196                         dev_err(&wled->pdev->dev,
2197                                 "Unable to request sc(%d) IRQ(err:%d)\n",
2198                                 wled->sc_irq, rc);
2199                         return rc;
2200                 }
2201
2202                 rc = qpnp_wled_read_reg(wled,
2203                                 QPNP_WLED_SC_PRO_REG(wled->ctrl_base), &reg);
2204                 if (rc < 0)
2205                         return rc;
2206                 reg &= QPNP_WLED_EN_SC_DEB_CYCLES_MASK;
2207                 reg |= 1 << QPNP_WLED_EN_SC_SHIFT;
2208
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;
2214                 reg |= (temp << 1);
2215
2216                 if (wled->disp_type_amoled)
2217                         reg |= QPNP_WLED_SC_PRO_EN_DSCHGR;
2218
2219                 rc = qpnp_wled_write_reg(wled,
2220                                 QPNP_WLED_SC_PRO_REG(wled->ctrl_base), reg);
2221                 if (rc)
2222                         return rc;
2223
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),
2228                                         reg);
2229                         if (rc)
2230                                 return rc;
2231                 }
2232         } else {
2233                 rc = qpnp_wled_read_reg(wled,
2234                                 QPNP_WLED_SC_PRO_REG(wled->ctrl_base), &reg);
2235                 if (rc < 0)
2236                         return rc;
2237                 reg &= QPNP_WLED_EN_DEB_CYCLES_MASK;
2238
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;
2244                 reg |= (temp << 1);
2245
2246                 rc = qpnp_wled_write_reg(wled,
2247                                 QPNP_WLED_SC_PRO_REG(wled->ctrl_base), reg);
2248                 if (rc)
2249                         return rc;
2250         }
2251
2252         return 0;
2253 }
2254
2255 int qpnp_wled_cabc(struct led_classdev *led_cdev, bool enable)
2256 {
2257         struct qpnp_wled *wled;
2258         int rc = 0, i;
2259         u8 reg = 0;
2260
2261         wled = container_of(led_cdev, struct qpnp_wled, cdev);
2262         if (wled == NULL) {
2263                 pr_err("wled is null\n");
2264                 return -EPERM;
2265         }
2266         wled->en_cabc = enable;
2267         for (i = 0; i < wled->num_strings; i++) {
2268                 /* CABC */
2269                 rc = qpnp_wled_read_reg(wled,
2270                                 QPNP_WLED_CABC_REG(wled->sink_base,
2271                                         wled->strings[i]), &reg);
2272                 if (rc < 0)
2273                         return rc;
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);
2279                 if (rc)
2280                         return rc;
2281                 pr_debug("%d en_cabc %d\n", i, wled->en_cabc);
2282         }
2283         return rc;
2284 }
2285
2286 EXPORT_SYMBOL_GPL(qpnp_wled_cabc);
2287
2288 /* parse wled dtsi parameters */
2289 static int qpnp_wled_parse_dt(struct qpnp_wled *wled)
2290 {
2291         struct platform_device *pdev = wled->pdev;
2292         struct property *prop;
2293         const char *temp_str;
2294         u32 temp_val;
2295         int rc, i, size;
2296         u8 *strings;
2297
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");
2303                 return rc;
2304         }
2305
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");
2311                 return rc;
2312         }
2313
2314         if (of_find_property(pdev->dev.of_node, "qcom,wled-brightness-map",
2315                         NULL)) {
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);
2320                         return rc;
2321                 }
2322
2323                 wled->brt_map_table = devm_kcalloc(&pdev->dev, NUM_DDIC_CODES,
2324                                                 sizeof(u16), GFP_KERNEL);
2325                 if (!wled->brt_map_table)
2326                         return -ENOMEM;
2327
2328                 rc = of_property_read_u16_array(pdev->dev.of_node,
2329                         "qcom,wled-brightness-map", wled->brt_map_table,
2330                         NUM_DDIC_CODES);
2331                 if (rc < 0) {
2332                         pr_err("Error in reading WLED brightness map, rc=%d\n",
2333                                 rc);
2334                         return rc;
2335                 }
2336
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");
2340                                 return -EDOM;
2341                         }
2342
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");
2346                                 return -EDOM;
2347                         }
2348                 }
2349         }
2350
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);
2359                 if (!rc) {
2360                         wled->vref_psm_mv = temp_val;
2361                 } else if (rc != -EINVAL) {
2362                         dev_err(&pdev->dev, "Unable to read vref-psm\n");
2363                         return rc;
2364                 }
2365
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;
2370
2371                 rc = of_property_read_u32(pdev->dev.of_node,
2372                                 "qcom,loop-comp-res-kohm", &temp_val);
2373                 if (!rc) {
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");
2377                         return rc;
2378                 }
2379
2380                 wled->avdd_mode_spmi = of_property_read_bool(pdev->dev.of_node,
2381                                 "qcom,avdd-mode-spmi");
2382
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);
2386                 if (!rc) {
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");
2390                         return rc;
2391                 }
2392         }
2393
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)
2397                         wled->loop_ea_gm =
2398                                 QPNP_WLED_LOOP_GM_DFLT_AMOLED_PMI8998;
2399                 else
2400                         wled->loop_ea_gm =
2401                                 QPNP_WLED_LOOP_EA_GM_DFLT_AMOLED_PMI8994;
2402         } else {
2403                 wled->loop_ea_gm = QPNP_WLED_LOOP_GM_DFLT_WLED;
2404         }
2405
2406         rc = of_property_read_u32(pdev->dev.of_node,
2407                         "qcom,loop-ea-gm", &temp_val);
2408         if (!rc) {
2409                 wled->loop_ea_gm = temp_val;
2410         } else if (rc != -EINVAL) {
2411                 dev_err(&pdev->dev, "Unable to read loop-ea-gm\n");
2412                 return rc;
2413         }
2414
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) {
2425                         dev_err(&pdev->dev,
2426                                 "Unable to read loop-auto-gm-thresh\n");
2427                         return rc;
2428                 }
2429         }
2430
2431         if (wled->pmic_rev_id->pmic_subtype == PMI8998_SUBTYPE ||
2432                 wled->pmic_rev_id->pmic_subtype == PM660L_SUBTYPE) {
2433
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;
2437                 else
2438                         wled->lcd_auto_pfm_en = true;
2439
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) {
2445                         dev_err(&pdev->dev,
2446                                 "Unable to read lcd-auto-pfm-thresh\n");
2447                         return rc;
2448                 }
2449
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;
2454         }
2455
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);
2459         if (!rc) {
2460                 wled->sc_deb_cycles = temp_val;
2461         } else if (rc != -EINVAL) {
2462                 dev_err(&pdev->dev, "Unable to read sc debounce cycles\n");
2463                 return rc;
2464         }
2465
2466         wled->fdbk_op = QPNP_WLED_FDBK_AUTO;
2467         rc = of_property_read_string(pdev->dev.of_node,
2468                         "qcom,fdbk-output", &temp_str);
2469         if (!rc) {
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;
2478                 else
2479                         wled->fdbk_op = QPNP_WLED_FDBK_AUTO;
2480         } else if (rc != -EINVAL) {
2481                 dev_err(&pdev->dev, "Unable to read feedback output\n");
2482                 return rc;
2483         }
2484
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;
2488         else
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);
2492         if (!rc) {
2493                 wled->vref_uv = temp_val;
2494         } else if (rc != -EINVAL) {
2495                 dev_err(&pdev->dev, "Unable to read vref\n");
2496                 return rc;
2497         }
2498
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);
2502         if (!rc) {
2503                 wled->switch_freq_khz = temp_val;
2504         } else if (rc != -EINVAL) {
2505                 dev_err(&pdev->dev, "Unable to read switch freq\n");
2506                 return rc;
2507         }
2508
2509         if (wled->pmic_rev_id->pmic_subtype == PMI8998_SUBTYPE ||
2510                 wled->pmic_rev_id->pmic_subtype == PM660L_SUBTYPE)
2511                 wled->ovp_mv = 29600;
2512         else
2513                 wled->ovp_mv = 29500;
2514         rc = of_property_read_u32(pdev->dev.of_node,
2515                         "qcom,ovp-mv", &temp_val);
2516         if (!rc) {
2517                 wled->ovp_mv = temp_val;
2518         } else if (rc != -EINVAL) {
2519                 dev_err(&pdev->dev, "Unable to read ovp\n");
2520                 return rc;
2521         }
2522
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;
2527                 else
2528                         wled->ilim_ma = PMI8998_WLED_DFLT_ILIM_MA;
2529         } else {
2530                 if (wled->disp_type_amoled)
2531                         wled->ilim_ma = PMI8994_AMOLED_DFLT_ILIM_MA;
2532                 else
2533                         wled->ilim_ma = PMI8994_WLED_DFLT_ILIM_MA;
2534         }
2535
2536         rc = of_property_read_u32(pdev->dev.of_node,
2537                         "qcom,ilim-ma", &temp_val);
2538         if (!rc) {
2539                 wled->ilim_ma = temp_val;
2540         } else if (rc != -EINVAL) {
2541                 dev_err(&pdev->dev, "Unable to read ilim\n");
2542                 return rc;
2543         }
2544
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);
2548         if (!rc) {
2549                 wled->boost_duty_ns = temp_val;
2550         } else if (rc != -EINVAL) {
2551                 dev_err(&pdev->dev, "Unable to read boost duty\n");
2552                 return rc;
2553         }
2554
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);
2558         if (!rc) {
2559                 wled->mod_freq_khz = temp_val;
2560         } else if (rc != -EINVAL) {
2561                 dev_err(&pdev->dev, "Unable to read modulation freq\n");
2562                 return rc;
2563         }
2564
2565         wled->dim_mode = QPNP_WLED_DIM_HYBRID;
2566         rc = of_property_read_string(pdev->dev.of_node,
2567                         "qcom,dim-mode", &temp_str);
2568         if (!rc) {
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;
2573                 else
2574                         wled->dim_mode = QPNP_WLED_DIM_HYBRID;
2575         } else if (rc != -EINVAL) {
2576                 dev_err(&pdev->dev, "Unable to read dim mode\n");
2577                 return rc;
2578         }
2579
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);
2584                 if (!rc) {
2585                         wled->hyb_thres = temp_val;
2586                 } else if (rc != -EINVAL) {
2587                         dev_err(&pdev->dev, "Unable to read hyb threshold\n");
2588                         return rc;
2589                 }
2590         }
2591
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);
2595         if (!rc) {
2596                 wled->sync_dly_us = temp_val;
2597         } else if (rc != -EINVAL) {
2598                 dev_err(&pdev->dev, "Unable to read sync delay\n");
2599                 return rc;
2600         }
2601
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);
2605         if (!rc) {
2606                 wled->fs_curr_ua = temp_val;
2607         } else if (rc != -EINVAL) {
2608                 dev_err(&pdev->dev, "Unable to read full scale current\n");
2609                 return rc;
2610         }
2611
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);
2615         if (!rc)
2616                 wled->cons_sync_write_delay_us = temp_val;
2617
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,
2623                         "qcom,en-cabc");
2624
2625         if (wled->pmic_rev_id->pmic_subtype == PM660L_SUBTYPE)
2626                 wled->max_strings = QPNP_PM660_WLED_MAX_STRINGS;
2627         else
2628                 wled->max_strings = QPNP_WLED_MAX_STRINGS;
2629
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;
2637         } else {
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];
2642         }
2643
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");
2647
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");
2651
2652         wled->en_ext_pfet_sc_pro = of_property_read_bool(pdev->dev.of_node,
2653                                         "qcom,en-ext-pfet-sc-pro");
2654
2655         wled->lcd_psm_ctrl = of_property_read_bool(pdev->dev.of_node,
2656                                 "qcom,lcd-psm-ctrl");
2657
2658         wled->auto_calib_enabled = of_property_read_bool(pdev->dev.of_node,
2659                                         "qcom,auto-calibration-enable");
2660         return 0;
2661 }
2662
2663 static int qpnp_wled_probe(struct platform_device *pdev)
2664 {
2665         struct qpnp_wled *wled;
2666         struct device_node *revid_node;
2667         int rc = 0, i;
2668         const __be32 *prop;
2669
2670         wled = devm_kzalloc(&pdev->dev, sizeof(*wled), GFP_KERNEL);
2671         if (!wled)
2672                 return -ENOMEM;
2673
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");
2677                 return -EINVAL;
2678         }
2679
2680         wled->pdev = pdev;
2681
2682         revid_node = of_parse_phandle(pdev->dev.of_node, "qcom,pmic-revid", 0);
2683         if (!revid_node) {
2684                 pr_err("Missing qcom,pmic-revid property - driver failed\n");
2685                 return -EINVAL;
2686         }
2687
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));
2693                 /*
2694                  * the revid peripheral must be registered, any failure
2695                  * here only indicates that the rev-id module has not
2696                  * probed yet.
2697                  */
2698                 return -EPROBE_DEFER;
2699         }
2700
2701         pr_debug("PMIC subtype %d Digital major %d\n",
2702                 wled->pmic_rev_id->pmic_subtype, wled->pmic_rev_id->rev4);
2703
2704         wled->wq = alloc_ordered_workqueue("qpnp_wled_wq", WQ_HIGHPRI);
2705         if (!wled->wq) {
2706                 pr_err("Unable to alloc workqueue for WLED\n");
2707                 return -ENOMEM;
2708         }
2709
2710         prop = of_get_address_by_name(pdev->dev.of_node, QPNP_WLED_SINK_BASE,
2711                         NULL, NULL);
2712         if (!prop) {
2713                 dev_err(&pdev->dev, "Couldnt find sink's addr rc %d\n", rc);
2714                 return rc;
2715         }
2716         wled->sink_base = be32_to_cpu(*prop);
2717
2718         prop = of_get_address_by_name(pdev->dev.of_node, QPNP_WLED_CTRL_BASE,
2719                         NULL, NULL);
2720         if (!prop) {
2721                 dev_err(&pdev->dev, "Couldnt find ctrl's addr rc = %d\n", rc);
2722                 return rc;
2723         }
2724         wled->ctrl_base = be32_to_cpu(*prop);
2725
2726         dev_set_drvdata(&pdev->dev, wled);
2727
2728         rc = qpnp_wled_parse_dt(wled);
2729         if (rc) {
2730                 dev_err(&pdev->dev, "DT parsing failed\n");
2731                 return rc;
2732         }
2733
2734         mutex_init(&wled->bus_lock);
2735         mutex_init(&wled->lock);
2736         rc = qpnp_wled_config(wled);
2737         if (rc) {
2738                 dev_err(&pdev->dev, "wled config failed\n");
2739                 return rc;
2740         }
2741
2742         INIT_WORK(&wled->work, qpnp_wled_work);
2743         wled->ramp_ms = QPNP_WLED_RAMP_DLY_MS;
2744         wled->ramp_step = 1;
2745
2746         wled->cdev.brightness_set = qpnp_wled_set;
2747         wled->cdev.brightness_get = qpnp_wled_get;
2748
2749         wled->cdev.max_brightness = WLED_MAX_LEVEL_4095;
2750
2751         rc = led_classdev_register(&pdev->dev, &wled->cdev);
2752         if (rc) {
2753                 dev_err(&pdev->dev, "wled registration failed(%d)\n", rc);
2754                 goto wled_register_fail;
2755         }
2756
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);
2760                 if (rc < 0) {
2761                         dev_err(&pdev->dev, "sysfs creation failed\n");
2762                         goto sysfs_fail;
2763                 }
2764         }
2765
2766         return 0;
2767
2768 sysfs_fail:
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);
2773 wled_register_fail:
2774         cancel_work_sync(&wled->work);
2775         destroy_workqueue(wled->wq);
2776         mutex_destroy(&wled->lock);
2777         return rc;
2778 }
2779
2780 static int qpnp_wled_remove(struct platform_device *pdev)
2781 {
2782         struct qpnp_wled *wled = dev_get_drvdata(&pdev->dev);
2783         int i;
2784
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);
2788
2789         led_classdev_unregister(&wled->cdev);
2790         cancel_work_sync(&wled->work);
2791         destroy_workqueue(wled->wq);
2792         mutex_destroy(&wled->lock);
2793
2794         return 0;
2795 }
2796
2797 static const struct of_device_id spmi_match_table[] = {
2798         { .compatible = "qcom,qpnp-wled",},
2799         { },
2800 };
2801
2802 static struct platform_driver qpnp_wled_driver = {
2803         .driver         = {
2804                 .name           = "qcom,qpnp-wled",
2805                 .of_match_table = spmi_match_table,
2806         },
2807         .probe          = qpnp_wled_probe,
2808         .remove         = qpnp_wled_remove,
2809 };
2810
2811 static int __init qpnp_wled_init(void)
2812 {
2813         return platform_driver_register(&qpnp_wled_driver);
2814 }
2815 module_init(qpnp_wled_init);
2816
2817 static void __exit qpnp_wled_exit(void)
2818 {
2819         platform_driver_unregister(&qpnp_wled_driver);
2820 }
2821 module_exit(qpnp_wled_exit);
2822
2823 MODULE_DESCRIPTION("QPNP WLED driver");
2824 MODULE_LICENSE("GPL v2");
2825 MODULE_ALIAS("leds:leds-qpnp-wled");