Skip to content

Commit f16899a

Browse files
I-n-o-kLee Jones
authored andcommitted
backlight: qcom-wled: Add callback functions
Add wled_cabc_config, wled_sync_toggle, wled_ovp_fault_status and wled_ovp_delay and wled_auto_detection_required callback functions to prepare the driver for adding WLED5 support. Signed-off-by: Kiran Gunda <[email protected]> Signed-off-by: Subbaraman Narayanamurthy <[email protected]> Reviewed-by: Daniel Thompson <[email protected]> Signed-off-by: Lee Jones <[email protected]>
1 parent e0ace1f commit f16899a

File tree

1 file changed

+141
-72
lines changed

1 file changed

+141
-72
lines changed

drivers/video/backlight/qcom-wled.c

Lines changed: 141 additions & 72 deletions
Original file line numberDiff line numberDiff line change
@@ -147,14 +147,38 @@ struct wled {
147147
u32 max_brightness;
148148
u32 short_count;
149149
u32 auto_detect_count;
150+
u32 version;
150151
bool disabled_by_short;
151152
bool has_short_detect;
152153
int short_irq;
153154
int ovp_irq;
154155

155156
struct wled_config cfg;
156157
struct delayed_work ovp_work;
158+
159+
/* Configures the brightness. Applicable for wled3, wled4 and wled5 */
157160
int (*wled_set_brightness)(struct wled *wled, u16 brightness);
161+
162+
/* Configures the cabc register. Applicable for wled4 and wled5 */
163+
int (*wled_cabc_config)(struct wled *wled, bool enable);
164+
165+
/*
166+
* Toggles the sync bit for the brightness update to take place.
167+
* Applicable for WLED3, WLED4 and WLED5.
168+
*/
169+
int (*wled_sync_toggle)(struct wled *wled);
170+
171+
/*
172+
* Time to wait before checking the OVP status after wled module enable.
173+
* Applicable for WLED4 and WLED5.
174+
*/
175+
int (*wled_ovp_delay)(struct wled *wled);
176+
177+
/*
178+
* Determines if the auto string detection is required.
179+
* Applicable for WLED4 and WLED5
180+
*/
181+
bool (*wled_auto_detection_required)(struct wled *wled);
158182
};
159183

160184
static int wled3_set_brightness(struct wled *wled, u16 brightness)
@@ -237,7 +261,7 @@ static int wled_module_enable(struct wled *wled, int val)
237261
return 0;
238262
}
239263

240-
static int wled_sync_toggle(struct wled *wled)
264+
static int wled3_sync_toggle(struct wled *wled)
241265
{
242266
int rc;
243267
unsigned int mask = GENMASK(wled->max_string_count - 1, 0);
@@ -255,6 +279,46 @@ static int wled_sync_toggle(struct wled *wled)
255279
return rc;
256280
}
257281

282+
static int wled_ovp_fault_status(struct wled *wled, bool *fault_set)
283+
{
284+
int rc;
285+
u32 int_rt_sts, fault_sts;
286+
287+
*fault_set = false;
288+
rc = regmap_read(wled->regmap,
289+
wled->ctrl_addr + WLED3_CTRL_REG_INT_RT_STS,
290+
&int_rt_sts);
291+
if (rc < 0) {
292+
dev_err(wled->dev, "Failed to read INT_RT_STS rc=%d\n", rc);
293+
return rc;
294+
}
295+
296+
rc = regmap_read(wled->regmap,
297+
wled->ctrl_addr + WLED3_CTRL_REG_FAULT_STATUS,
298+
&fault_sts);
299+
if (rc < 0) {
300+
dev_err(wled->dev, "Failed to read FAULT_STATUS rc=%d\n", rc);
301+
return rc;
302+
}
303+
304+
if (int_rt_sts & WLED3_CTRL_REG_OVP_FAULT_STATUS)
305+
*fault_set = true;
306+
307+
if (fault_sts & WLED3_CTRL_REG_OVP_FAULT_BIT)
308+
*fault_set = true;
309+
310+
if (*fault_set)
311+
dev_dbg(wled->dev, "WLED OVP fault detected, int_rt_sts=0x%x fault_sts=0x%x\n",
312+
int_rt_sts, fault_sts);
313+
314+
return rc;
315+
}
316+
317+
static int wled4_ovp_delay(struct wled *wled)
318+
{
319+
return WLED_SOFT_START_DLY_US;
320+
}
321+
258322
static int wled_update_status(struct backlight_device *bl)
259323
{
260324
struct wled *wled = bl_get_data(bl);
@@ -275,7 +339,7 @@ static int wled_update_status(struct backlight_device *bl)
275339
goto unlock_mutex;
276340
}
277341

278-
rc = wled_sync_toggle(wled);
342+
rc = wled->wled_sync_toggle(wled);
279343
if (rc < 0) {
280344
dev_err(wled->dev, "wled sync failed rc:%d\n", rc);
281345
goto unlock_mutex;
@@ -298,6 +362,25 @@ static int wled_update_status(struct backlight_device *bl)
298362
return rc;
299363
}
300364

365+
static int wled4_cabc_config(struct wled *wled, bool enable)
366+
{
367+
int i, j, rc;
368+
u8 val;
369+
370+
for (i = 0; i < wled->cfg.num_strings; i++) {
371+
j = wled->cfg.enabled_strings[i];
372+
373+
val = enable ? WLED4_SINK_REG_STR_CABC_MASK : 0;
374+
rc = regmap_update_bits(wled->regmap, wled->sink_addr +
375+
WLED4_SINK_REG_STR_CABC(j),
376+
WLED4_SINK_REG_STR_CABC_MASK, val);
377+
if (rc < 0)
378+
return rc;
379+
}
380+
381+
return 0;
382+
}
383+
301384
#define WLED_SHORT_DLY_MS 20
302385
#define WLED_SHORT_CNT_MAX 5
303386
#define WLED_SHORT_RESET_CNT_DLY_US USEC_PER_SEC
@@ -345,9 +428,10 @@ static irqreturn_t wled_short_irq_handler(int irq, void *_wled)
345428

346429
static void wled_auto_string_detection(struct wled *wled)
347430
{
348-
int rc = 0, i;
349-
u32 sink_config = 0, int_sts;
431+
int rc = 0, i, delay_time_us;
432+
u32 sink_config = 0;
350433
u8 sink_test = 0, sink_valid = 0, val;
434+
bool fault_set;
351435

352436
/* Read configured sink configuration */
353437
rc = regmap_read(wled->regmap, wled->sink_addr +
@@ -376,14 +460,9 @@ static void wled_auto_string_detection(struct wled *wled)
376460
}
377461

378462
if (wled->cfg.cabc) {
379-
for (i = 0; i < wled->cfg.num_strings; i++) {
380-
rc = regmap_update_bits(wled->regmap, wled->sink_addr +
381-
WLED4_SINK_REG_STR_CABC(i),
382-
WLED4_SINK_REG_STR_CABC_MASK,
383-
0);
384-
if (rc < 0)
385-
goto failed_detect;
386-
}
463+
rc = wled->wled_cabc_config(wled, false);
464+
if (rc < 0)
465+
goto failed_detect;
387466
}
388467

389468
/* Disable all sinks */
@@ -427,18 +506,17 @@ static void wled_auto_string_detection(struct wled *wled)
427506
goto failed_detect;
428507
}
429508

430-
usleep_range(WLED_SOFT_START_DLY_US,
431-
WLED_SOFT_START_DLY_US + 1000);
509+
delay_time_us = wled->wled_ovp_delay(wled);
510+
usleep_range(delay_time_us, delay_time_us + 1000);
432511

433-
rc = regmap_read(wled->regmap, wled->ctrl_addr +
434-
WLED3_CTRL_REG_INT_RT_STS, &int_sts);
512+
rc = wled_ovp_fault_status(wled, &fault_set);
435513
if (rc < 0) {
436-
dev_err(wled->dev, "Error in reading WLED3_CTRL_INT_RT_STS rc=%d\n",
514+
dev_err(wled->dev, "Error in getting OVP fault_sts, rc=%d\n",
437515
rc);
438516
goto failed_detect;
439517
}
440518

441-
if (int_sts & WLED3_CTRL_REG_OVP_FAULT_STATUS)
519+
if (fault_set)
442520
dev_dbg(wled->dev, "WLED OVP fault detected with SINK %d\n",
443521
i + 1);
444522
else
@@ -478,30 +556,30 @@ static void wled_auto_string_detection(struct wled *wled)
478556
}
479557

480558
/* Enable valid sinks */
481-
for (i = 0; i < wled->cfg.num_strings; i++) {
482-
if (wled->cfg.cabc) {
483-
rc = regmap_update_bits(wled->regmap, wled->sink_addr +
484-
WLED4_SINK_REG_STR_CABC(i),
485-
WLED4_SINK_REG_STR_CABC_MASK,
486-
WLED4_SINK_REG_STR_CABC_MASK);
487-
if (rc < 0)
559+
if (wled->version == 4) {
560+
for (i = 0; i < wled->cfg.num_strings; i++) {
561+
if (sink_config &
562+
BIT(WLED4_SINK_REG_CURR_SINK_SHFT + i))
563+
val = WLED4_SINK_REG_STR_MOD_MASK;
564+
else
565+
/* Disable modulator_en for unused sink */
566+
val = 0;
567+
568+
rc = regmap_write(wled->regmap, wled->sink_addr +
569+
WLED4_SINK_REG_STR_MOD_EN(i), val);
570+
if (rc < 0) {
571+
dev_err(wled->dev, "Failed to configure MODULATOR_EN rc=%d\n",
572+
rc);
488573
goto failed_detect;
489-
}
490-
491-
if (sink_config & BIT(WLED4_SINK_REG_CURR_SINK_SHFT + i))
492-
val = WLED4_SINK_REG_STR_MOD_MASK;
493-
else
494-
val = 0x0; /* Disable modulator_en for unused sink */
495-
496-
rc = regmap_write(wled->regmap, wled->sink_addr +
497-
WLED4_SINK_REG_STR_MOD_EN(i), val);
498-
if (rc < 0) {
499-
dev_err(wled->dev, "Failed to configure MODULATOR_EN rc=%d\n",
500-
rc);
501-
goto failed_detect;
574+
}
502575
}
503576
}
504577

578+
/* Enable CABC */
579+
rc = wled->wled_cabc_config(wled, true);
580+
if (rc < 0)
581+
goto failed_detect;
582+
505583
/* Restore the feedback setting */
506584
rc = regmap_write(wled->regmap,
507585
wled->ctrl_addr + WLED3_CTRL_REG_FEEDBACK_CONTROL, 0);
@@ -534,7 +612,8 @@ static void wled_auto_string_detection(struct wled *wled)
534612

535613
#define WLED_AUTO_DETECT_OVP_COUNT 5
536614
#define WLED_AUTO_DETECT_CNT_DLY_US USEC_PER_SEC
537-
static bool wled_auto_detection_required(struct wled *wled)
615+
616+
static bool wled4_auto_detection_required(struct wled *wled)
538617
{
539618
s64 elapsed_time_us;
540619

@@ -570,29 +649,19 @@ static bool wled_auto_detection_required(struct wled *wled)
570649
static int wled_auto_detection_at_init(struct wled *wled)
571650
{
572651
int rc;
573-
u32 fault_status, rt_status;
652+
bool fault_set;
574653

575654
if (!wled->cfg.auto_detection_enabled)
576655
return 0;
577656

578-
rc = regmap_read(wled->regmap,
579-
wled->ctrl_addr + WLED3_CTRL_REG_INT_RT_STS,
580-
&rt_status);
581-
if (rc < 0) {
582-
dev_err(wled->dev, "Failed to read RT status rc=%d\n", rc);
583-
return rc;
584-
}
585-
586-
rc = regmap_read(wled->regmap,
587-
wled->ctrl_addr + WLED3_CTRL_REG_FAULT_STATUS,
588-
&fault_status);
657+
rc = wled_ovp_fault_status(wled, &fault_set);
589658
if (rc < 0) {
590-
dev_err(wled->dev, "Failed to read fault status rc=%d\n", rc);
659+
dev_err(wled->dev, "Error in getting OVP fault_sts, rc=%d\n",
660+
rc);
591661
return rc;
592662
}
593663

594-
if ((rt_status & WLED3_CTRL_REG_OVP_FAULT_STATUS) ||
595-
(fault_status & WLED3_CTRL_REG_OVP_FAULT_BIT)) {
664+
if (fault_set) {
596665
mutex_lock(&wled->lock);
597666
wled_auto_string_detection(wled);
598667
mutex_unlock(&wled->lock);
@@ -629,7 +698,7 @@ static irqreturn_t wled_ovp_irq_handler(int irq, void *_wled)
629698
int_sts, fault_sts);
630699

631700
if (fault_sts & WLED3_CTRL_REG_OVP_FAULT_BIT) {
632-
if (wled_auto_detection_required(wled)) {
701+
if (wled->wled_auto_detection_required(wled)) {
633702
mutex_lock(&wled->lock);
634703
wled_auto_string_detection(wled);
635704
mutex_unlock(&wled->lock);
@@ -811,17 +880,12 @@ static int wled4_setup(struct wled *wled)
811880
wled->cfg.string_i_limit);
812881
if (rc < 0)
813882
return rc;
814-
815-
addr = wled->sink_addr +
816-
WLED4_SINK_REG_STR_CABC(j);
817-
rc = regmap_update_bits(wled->regmap, addr,
818-
WLED4_SINK_REG_STR_CABC_MASK,
819-
wled->cfg.cabc ?
820-
WLED4_SINK_REG_STR_CABC_MASK : 0);
821-
if (rc < 0)
822-
return rc;
823883
}
824884

885+
rc = wled4_cabc_config(wled, wled->cfg.cabc);
886+
if (rc < 0)
887+
return rc;
888+
825889
rc = regmap_update_bits(wled->regmap, wled->ctrl_addr +
826890
WLED3_CTRL_REG_MOD_EN,
827891
WLED3_CTRL_REG_MOD_EN_MASK,
@@ -835,7 +899,7 @@ static int wled4_setup(struct wled *wled)
835899
if (rc < 0)
836900
return rc;
837901

838-
rc = wled_sync_toggle(wled);
902+
rc = wled->wled_sync_toggle(wled);
839903
if (rc < 0) {
840904
dev_err(wled->dev, "Failed to toggle sync reg rc:%d\n", rc);
841905
return rc;
@@ -951,7 +1015,7 @@ static u32 wled_values(const struct wled_var_cfg *cfg, u32 idx)
9511015
return idx;
9521016
}
9531017

954-
static int wled_configure(struct wled *wled, int version)
1018+
static int wled_configure(struct wled *wled)
9551019
{
9561020
struct wled_config *cfg = &wled->cfg;
9571021
struct device *dev = wled->dev;
@@ -1035,12 +1099,13 @@ static int wled_configure(struct wled *wled, int version)
10351099
if (rc)
10361100
wled->name = devm_kasprintf(dev, GFP_KERNEL, "%pOFn", dev->of_node);
10371101

1038-
switch (version) {
1102+
switch (wled->version) {
10391103
case 3:
10401104
u32_opts = wled3_opts;
10411105
size = ARRAY_SIZE(wled3_opts);
10421106
*cfg = wled3_config_defaults;
10431107
wled->wled_set_brightness = wled3_set_brightness;
1108+
wled->wled_sync_toggle = wled3_sync_toggle;
10441109
wled->max_string_count = 3;
10451110
wled->sink_addr = wled->ctrl_addr;
10461111
break;
@@ -1050,6 +1115,11 @@ static int wled_configure(struct wled *wled, int version)
10501115
size = ARRAY_SIZE(wled4_opts);
10511116
*cfg = wled4_config_defaults;
10521117
wled->wled_set_brightness = wled4_set_brightness;
1118+
wled->wled_sync_toggle = wled3_sync_toggle;
1119+
wled->wled_cabc_config = wled4_cabc_config;
1120+
wled->wled_ovp_delay = wled4_ovp_delay;
1121+
wled->wled_auto_detection_required =
1122+
wled4_auto_detection_required;
10531123
wled->max_string_count = 4;
10541124

10551125
prop_addr = of_get_address(dev->of_node, 1, NULL, NULL);
@@ -1186,7 +1256,6 @@ static int wled_probe(struct platform_device *pdev)
11861256
struct backlight_device *bl;
11871257
struct wled *wled;
11881258
struct regmap *regmap;
1189-
int version;
11901259
u32 val;
11911260
int rc;
11921261

@@ -1203,18 +1272,18 @@ static int wled_probe(struct platform_device *pdev)
12031272
wled->regmap = regmap;
12041273
wled->dev = &pdev->dev;
12051274

1206-
version = (uintptr_t)of_device_get_match_data(&pdev->dev);
1207-
if (!version) {
1275+
wled->version = (uintptr_t)of_device_get_match_data(&pdev->dev);
1276+
if (!wled->version) {
12081277
dev_err(&pdev->dev, "Unknown device version\n");
12091278
return -ENODEV;
12101279
}
12111280

12121281
mutex_init(&wled->lock);
1213-
rc = wled_configure(wled, version);
1282+
rc = wled_configure(wled);
12141283
if (rc)
12151284
return rc;
12161285

1217-
switch (version) {
1286+
switch (wled->version) {
12181287
case 3:
12191288
wled->cfg.auto_detection_enabled = false;
12201289
rc = wled3_setup(wled);

0 commit comments

Comments
 (0)