2525
2626#define KTD253_T_LOW_NS (200 + 10) /* Additional 10ns as safety factor */
2727#define KTD253_T_HIGH_NS (200 + 10) /* Additional 10ns as safety factor */
28+ #define KTD253_T_OFF_CRIT_NS 100000 /* 100 us, now it doesn't look good */
2829#define KTD253_T_OFF_MS 3
2930
3031struct ktd253_backlight {
@@ -34,13 +35,50 @@ struct ktd253_backlight {
3435 u16 ratio ;
3536};
3637
38+ static void ktd253_backlight_set_max_ratio (struct ktd253_backlight * ktd253 )
39+ {
40+ gpiod_set_value_cansleep (ktd253 -> gpiod , 1 );
41+ ndelay (KTD253_T_HIGH_NS );
42+ /* We always fall back to this when we power on */
43+ }
44+
45+ static int ktd253_backlight_stepdown (struct ktd253_backlight * ktd253 )
46+ {
47+ /*
48+ * These GPIO operations absolutely can NOT sleep so no _cansleep
49+ * suffixes, and no using GPIO expanders on slow buses for this!
50+ *
51+ * The maximum number of cycles of the loop is 32 so the time taken
52+ * should nominally be:
53+ * (T_LOW_NS + T_HIGH_NS + loop_time) * 32
54+ *
55+ * Architectures do not always support ndelay() and we will get a few us
56+ * instead. If we get to a critical time limit an interrupt has likely
57+ * occured in the low part of the loop and we need to restart from the
58+ * top so we have the backlight in a known state.
59+ */
60+ u64 ns ;
61+
62+ ns = ktime_get_ns ();
63+ gpiod_set_value (ktd253 -> gpiod , 0 );
64+ ndelay (KTD253_T_LOW_NS );
65+ gpiod_set_value (ktd253 -> gpiod , 1 );
66+ ns = ktime_get_ns () - ns ;
67+ if (ns >= KTD253_T_OFF_CRIT_NS ) {
68+ dev_err (ktd253 -> dev , "PCM on backlight took too long (%llu ns)\n" , ns );
69+ return - EAGAIN ;
70+ }
71+ ndelay (KTD253_T_HIGH_NS );
72+ return 0 ;
73+ }
74+
3775static int ktd253_backlight_update_status (struct backlight_device * bl )
3876{
3977 struct ktd253_backlight * ktd253 = bl_get_data (bl );
4078 int brightness = backlight_get_brightness (bl );
4179 u16 target_ratio ;
4280 u16 current_ratio = ktd253 -> ratio ;
43- unsigned long flags ;
81+ int ret ;
4482
4583 dev_dbg (ktd253 -> dev , "new brightness/ratio: %d/32\n" , brightness );
4684
@@ -62,37 +100,34 @@ static int ktd253_backlight_update_status(struct backlight_device *bl)
62100 }
63101
64102 if (current_ratio == 0 ) {
65- gpiod_set_value_cansleep (ktd253 -> gpiod , 1 );
66- ndelay (KTD253_T_HIGH_NS );
67- /* We always fall back to this when we power on */
103+ ktd253_backlight_set_max_ratio (ktd253 );
68104 current_ratio = KTD253_MAX_RATIO ;
69105 }
70106
71- /*
72- * WARNING:
73- * The loop to set the correct current level is performed
74- * with interrupts disabled as it is timing critical.
75- * The maximum number of cycles of the loop is 32
76- * so the time taken will be (T_LOW_NS + T_HIGH_NS + loop_time) * 32,
77- */
78- local_irq_save (flags );
79107 while (current_ratio != target_ratio ) {
80108 /*
81109 * These GPIO operations absolutely can NOT sleep so no
82110 * _cansleep suffixes, and no using GPIO expanders on
83111 * slow buses for this!
84112 */
85- gpiod_set_value (ktd253 -> gpiod , 0 );
86- ndelay (KTD253_T_LOW_NS );
87- gpiod_set_value (ktd253 -> gpiod , 1 );
88- ndelay (KTD253_T_HIGH_NS );
89- /* After 1/32 we loop back to 32/32 */
90- if (current_ratio == KTD253_MIN_RATIO )
113+ ret = ktd253_backlight_stepdown (ktd253 );
114+ if (ret == - EAGAIN ) {
115+ /*
116+ * Something disturbed the backlight setting code when
117+ * running so we need to bring the PWM back to a known
118+ * state. This shouldn't happen too much.
119+ */
120+ gpiod_set_value_cansleep (ktd253 -> gpiod , 0 );
121+ msleep (KTD253_T_OFF_MS );
122+ ktd253_backlight_set_max_ratio (ktd253 );
123+ current_ratio = KTD253_MAX_RATIO ;
124+ } else if (current_ratio == KTD253_MIN_RATIO ) {
125+ /* After 1/32 we loop back to 32/32 */
91126 current_ratio = KTD253_MAX_RATIO ;
92- else
127+ } else {
93128 current_ratio -- ;
129+ }
94130 }
95- local_irq_restore (flags );
96131 ktd253 -> ratio = current_ratio ;
97132
98133 dev_dbg (ktd253 -> dev , "new ratio set to %d/32\n" , target_ratio );
0 commit comments