@@ -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
160184static 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+
258322static 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
346429static 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)
570649static 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