18
18
#include <linux/backlight.h>
19
19
#include <linux/input.h>
20
20
#include <linux/input/matrix_keypad.h>
21
+ #include <linux/leds.h>
21
22
#include <linux/workqueue.h>
22
23
#include <linux/mm.h>
23
24
34
35
35
36
#define REG_DISPLAY_SETUP 0x80
36
37
#define REG_DISPLAY_SETUP_ON BIT(0)
38
+ #define REG_DISPLAY_SETUP_BLINK_OFF (0 << 1)
39
+ #define REG_DISPLAY_SETUP_BLINK_2HZ (1 << 1)
40
+ #define REG_DISPLAY_SETUP_BLINK_1HZ (2 << 1)
41
+ #define REG_DISPLAY_SETUP_BLINK_0HZ5 (3 << 1)
37
42
38
43
#define REG_ROWINT_SET 0xA0
39
44
#define REG_ROWINT_SET_INT_EN BIT(0)
@@ -94,12 +99,14 @@ struct ht16k33_seg {
94
99
struct ht16k33_priv {
95
100
struct i2c_client * client ;
96
101
struct delayed_work work ;
102
+ struct led_classdev led ;
97
103
struct ht16k33_keypad keypad ;
98
104
union {
99
105
struct ht16k33_fbdev fbdev ;
100
106
struct ht16k33_seg seg ;
101
107
};
102
108
enum display_type type ;
109
+ uint8_t blink ;
103
110
};
104
111
105
112
static const struct fb_fix_screeninfo ht16k33_fb_fix = {
@@ -158,7 +165,7 @@ static DEVICE_ATTR(map_seg14, 0644, map_seg_show, map_seg_store);
158
165
159
166
static int ht16k33_display_on (struct ht16k33_priv * priv )
160
167
{
161
- uint8_t data = REG_DISPLAY_SETUP | REG_DISPLAY_SETUP_ON ;
168
+ uint8_t data = REG_DISPLAY_SETUP | REG_DISPLAY_SETUP_ON | priv -> blink ;
162
169
163
170
return i2c_smbus_write_byte (priv -> client , data );
164
171
}
@@ -173,8 +180,10 @@ static int ht16k33_brightness_set(struct ht16k33_priv *priv,
173
180
{
174
181
int err ;
175
182
176
- if (brightness == 0 )
183
+ if (brightness == 0 ) {
184
+ priv -> blink = REG_DISPLAY_SETUP_BLINK_OFF ;
177
185
return ht16k33_display_off (priv );
186
+ }
178
187
179
188
err = ht16k33_display_on (priv );
180
189
if (err )
@@ -184,6 +193,49 @@ static int ht16k33_brightness_set(struct ht16k33_priv *priv,
184
193
REG_BRIGHTNESS | (brightness - 1 ));
185
194
}
186
195
196
+ static int ht16k33_brightness_set_blocking (struct led_classdev * led_cdev ,
197
+ enum led_brightness brightness )
198
+ {
199
+ struct ht16k33_priv * priv = container_of (led_cdev , struct ht16k33_priv ,
200
+ led );
201
+
202
+ return ht16k33_brightness_set (priv , brightness );
203
+ }
204
+
205
+ static int ht16k33_blink_set (struct led_classdev * led_cdev ,
206
+ unsigned long * delay_on , unsigned long * delay_off )
207
+ {
208
+ struct ht16k33_priv * priv = container_of (led_cdev , struct ht16k33_priv ,
209
+ led );
210
+ unsigned int delay ;
211
+ uint8_t blink ;
212
+ int err ;
213
+
214
+ if (!* delay_on && !* delay_off ) {
215
+ blink = REG_DISPLAY_SETUP_BLINK_1HZ ;
216
+ delay = 1000 ;
217
+ } else if (* delay_on <= 750 ) {
218
+ blink = REG_DISPLAY_SETUP_BLINK_2HZ ;
219
+ delay = 500 ;
220
+ } else if (* delay_on <= 1500 ) {
221
+ blink = REG_DISPLAY_SETUP_BLINK_1HZ ;
222
+ delay = 1000 ;
223
+ } else {
224
+ blink = REG_DISPLAY_SETUP_BLINK_0HZ5 ;
225
+ delay = 2000 ;
226
+ }
227
+
228
+ err = i2c_smbus_write_byte (priv -> client ,
229
+ REG_DISPLAY_SETUP | REG_DISPLAY_SETUP_ON |
230
+ blink );
231
+ if (err )
232
+ return err ;
233
+
234
+ priv -> blink = blink ;
235
+ * delay_on = * delay_off = delay ;
236
+ return 0 ;
237
+ }
238
+
187
239
static void ht16k33_fb_queue (struct ht16k33_priv * priv )
188
240
{
189
241
struct ht16k33_fbdev * fbdev = & priv -> fbdev ;
@@ -435,6 +487,35 @@ static void ht16k33_seg14_update(struct work_struct *work)
435
487
i2c_smbus_write_i2c_block_data (priv -> client , 0 , ARRAY_SIZE (buf ), buf );
436
488
}
437
489
490
+ static int ht16k33_led_probe (struct device * dev , struct led_classdev * led ,
491
+ unsigned int brightness )
492
+ {
493
+ struct led_init_data init_data = {};
494
+ struct device_node * node ;
495
+ int err ;
496
+
497
+ /* The LED is optional */
498
+ node = of_get_child_by_name (dev -> of_node , "led" );
499
+ if (!node )
500
+ return 0 ;
501
+
502
+ init_data .fwnode = of_fwnode_handle (node );
503
+ init_data .devicename = "auxdisplay" ;
504
+ init_data .devname_mandatory = true;
505
+
506
+ led -> brightness_set_blocking = ht16k33_brightness_set_blocking ;
507
+ led -> blink_set = ht16k33_blink_set ;
508
+ led -> flags = LED_CORE_SUSPENDRESUME ;
509
+ led -> brightness = brightness ;
510
+ led -> max_brightness = MAX_BRIGHTNESS ;
511
+
512
+ err = devm_led_classdev_register_ext (dev , led , & init_data );
513
+ if (err )
514
+ dev_err (dev , "Failed to register LED\n" );
515
+
516
+ return err ;
517
+ }
518
+
438
519
static int ht16k33_keypad_probe (struct i2c_client * client ,
439
520
struct ht16k33_keypad * keypad )
440
521
{
@@ -508,25 +589,33 @@ static int ht16k33_fbdev_probe(struct device *dev, struct ht16k33_priv *priv,
508
589
uint32_t brightness )
509
590
{
510
591
struct ht16k33_fbdev * fbdev = & priv -> fbdev ;
511
- struct backlight_properties bl_props ;
512
- struct backlight_device * bl ;
592
+ struct backlight_device * bl = NULL ;
513
593
int err ;
514
594
515
- /* Backlight */
516
- memset (& bl_props , 0 , sizeof (struct backlight_properties ));
517
- bl_props .type = BACKLIGHT_RAW ;
518
- bl_props .max_brightness = MAX_BRIGHTNESS ;
595
+ if (priv -> led .dev ) {
596
+ err = ht16k33_brightness_set (priv , brightness );
597
+ if (err )
598
+ return err ;
599
+ } else {
600
+ /* backwards compatibility with DT lacking an led subnode */
601
+ struct backlight_properties bl_props ;
602
+
603
+ memset (& bl_props , 0 , sizeof (struct backlight_properties ));
604
+ bl_props .type = BACKLIGHT_RAW ;
605
+ bl_props .max_brightness = MAX_BRIGHTNESS ;
606
+
607
+ bl = devm_backlight_device_register (dev , DRIVER_NAME "-bl" , dev ,
608
+ priv , & ht16k33_bl_ops ,
609
+ & bl_props );
610
+ if (IS_ERR (bl )) {
611
+ dev_err (dev , "failed to register backlight\n" );
612
+ return PTR_ERR (bl );
613
+ }
519
614
520
- bl = devm_backlight_device_register (dev , DRIVER_NAME "-bl" , dev , priv ,
521
- & ht16k33_bl_ops , & bl_props );
522
- if (IS_ERR (bl )) {
523
- dev_err (dev , "failed to register backlight\n" );
524
- return PTR_ERR (bl );
615
+ bl -> props .brightness = brightness ;
616
+ ht16k33_bl_update_status (bl );
525
617
}
526
618
527
- bl -> props .brightness = brightness ;
528
- ht16k33_bl_update_status (bl );
529
-
530
619
/* Framebuffer (2 bytes per column) */
531
620
BUILD_BUG_ON (PAGE_SIZE < HT16K33_FB_SIZE );
532
621
fbdev -> buffer = (unsigned char * ) get_zeroed_page (GFP_KERNEL );
@@ -663,6 +752,11 @@ static int ht16k33_probe(struct i2c_client *client)
663
752
dft_brightness = MAX_BRIGHTNESS ;
664
753
}
665
754
755
+ /* LED */
756
+ err = ht16k33_led_probe (dev , & priv -> led , dft_brightness );
757
+ if (err )
758
+ return err ;
759
+
666
760
/* Keypad */
667
761
if (client -> irq > 0 ) {
668
762
err = ht16k33_keypad_probe (client , & priv -> keypad );
0 commit comments