1 // SPDX-License-Identifier: GPL-2.0-only
3 * leds-bd2802.c - RGB LED Driver
5 * Copyright (C) 2009 Samsung Electronics
6 * Kim Kyuwon <q1.kim@samsung.com>
8 * Datasheet: http://www.rohm.com/products/databook/driver/pdf/bd2802gu-e.pdf
11 #include <linux/module.h>
12 #include <linux/i2c.h>
13 #include <linux/gpio/consumer.h>
14 #include <linux/delay.h>
15 #include <linux/leds.h>
16 #include <linux/leds-bd2802.h>
17 #include <linux/slab.h>
20 #define LED_CTL(rgb2en, rgb1en) ((rgb2en) << 4 | ((rgb1en) << 0))
22 #define BD2802_LED_OFFSET 0xa
23 #define BD2802_COLOR_OFFSET 0x3
25 #define BD2802_REG_CLKSETUP 0x00
26 #define BD2802_REG_CONTROL 0x01
27 #define BD2802_REG_HOURSETUP 0x02
28 #define BD2802_REG_CURRENT1SETUP 0x03
29 #define BD2802_REG_CURRENT2SETUP 0x04
30 #define BD2802_REG_WAVEPATTERN 0x05
32 #define BD2802_CURRENT_032 0x10 /* 3.2mA */
33 #define BD2802_CURRENT_000 0x00 /* 0.0mA */
35 #define BD2802_PATTERN_FULL 0x07
36 #define BD2802_PATTERN_HALF 0x03
68 struct bd2802_led_platform_data
*pdata
;
69 struct i2c_client
*client
;
70 struct gpio_desc
*reset
;
71 struct rw_semaphore rwsem
;
73 struct led_state led
[2];
76 * Making led_classdev as array is not recommended, because array
77 * members prevent using 'container_of' macro. So repetitive works
80 struct led_classdev cdev_led1r
;
81 struct led_classdev cdev_led1g
;
82 struct led_classdev cdev_led1b
;
83 struct led_classdev cdev_led2r
;
84 struct led_classdev cdev_led2g
;
85 struct led_classdev cdev_led2b
;
88 * Advanced Configuration Function(ADF) mode:
89 * In ADF mode, user can set registers of BD2802GU directly,
90 * therefore BD2802GU doesn't enter reset state.
95 enum led_colors color
;
98 /* General attributes of RGB LEDs */
104 /*--------------------------------------------------------------*/
105 /* BD2802GU helper functions */
106 /*--------------------------------------------------------------*/
108 static inline int bd2802_is_rgb_off(struct bd2802_led
*led
, enum led_ids id
,
109 enum led_colors color
)
113 return !led
->led
[id
].r
;
115 return !led
->led
[id
].g
;
117 return !led
->led
[id
].b
;
119 dev_err(&led
->client
->dev
, "%s: Invalid color\n", __func__
);
124 static inline int bd2802_is_led_off(struct bd2802_led
*led
, enum led_ids id
)
126 if (led
->led
[id
].r
|| led
->led
[id
].g
|| led
->led
[id
].b
)
132 static inline int bd2802_is_all_off(struct bd2802_led
*led
)
136 for (i
= 0; i
< LED_NUM
; i
++)
137 if (!bd2802_is_led_off(led
, i
))
143 static inline u8
bd2802_get_base_offset(enum led_ids id
, enum led_colors color
)
145 return id
* BD2802_LED_OFFSET
+ color
* BD2802_COLOR_OFFSET
;
148 static inline u8
bd2802_get_reg_addr(enum led_ids id
, enum led_colors color
,
151 return reg_offset
+ bd2802_get_base_offset(id
, color
);
155 /*--------------------------------------------------------------*/
156 /* BD2802GU core functions */
157 /*--------------------------------------------------------------*/
159 static int bd2802_write_byte(struct i2c_client
*client
, u8 reg
, u8 val
)
161 int ret
= i2c_smbus_write_byte_data(client
, reg
, val
);
165 dev_err(&client
->dev
, "%s: reg 0x%x, val 0x%x, err %d\n",
166 __func__
, reg
, val
, ret
);
171 static void bd2802_update_state(struct bd2802_led
*led
, enum led_ids id
,
172 enum led_colors color
, enum led_bits led_bit
)
177 for (i
= 0; i
< LED_NUM
; i
++) {
181 led
->led
[i
].r
= led_bit
;
184 led
->led
[i
].g
= led_bit
;
187 led
->led
[i
].b
= led_bit
;
190 dev_err(&led
->client
->dev
,
191 "%s: Invalid color\n", __func__
);
197 if (led_bit
== BD2802_BLINK
|| led_bit
== BD2802_ON
)
200 if (!bd2802_is_led_off(led
, id
))
203 if (bd2802_is_all_off(led
) && !led
->adf_on
) {
204 gpiod_set_value(led
->reset
, 1);
209 * In this case, other led is turned on, and current led is turned
210 * off. So set RGB LED Control register to stop the current RGB LED
212 value
= (id
== LED1
) ? LED_CTL(1, 0) : LED_CTL(0, 1);
213 bd2802_write_byte(led
->client
, BD2802_REG_CONTROL
, value
);
216 static void bd2802_configure(struct bd2802_led
*led
)
218 struct bd2802_led_platform_data
*pdata
= led
->pdata
;
221 reg
= bd2802_get_reg_addr(LED1
, RED
, BD2802_REG_HOURSETUP
);
222 bd2802_write_byte(led
->client
, reg
, pdata
->rgb_time
);
224 reg
= bd2802_get_reg_addr(LED2
, RED
, BD2802_REG_HOURSETUP
);
225 bd2802_write_byte(led
->client
, reg
, pdata
->rgb_time
);
228 static void bd2802_reset_cancel(struct bd2802_led
*led
)
230 gpiod_set_value(led
->reset
, 0);
232 bd2802_configure(led
);
235 static void bd2802_enable(struct bd2802_led
*led
, enum led_ids id
)
237 enum led_ids other_led
= (id
== LED1
) ? LED2
: LED1
;
238 u8 value
, other_led_on
;
240 other_led_on
= !bd2802_is_led_off(led
, other_led
);
242 value
= LED_CTL(other_led_on
, 1);
244 value
= LED_CTL(1 , other_led_on
);
246 bd2802_write_byte(led
->client
, BD2802_REG_CONTROL
, value
);
249 static void bd2802_set_on(struct bd2802_led
*led
, enum led_ids id
,
250 enum led_colors color
)
254 if (bd2802_is_all_off(led
) && !led
->adf_on
)
255 bd2802_reset_cancel(led
);
257 reg
= bd2802_get_reg_addr(id
, color
, BD2802_REG_CURRENT1SETUP
);
258 bd2802_write_byte(led
->client
, reg
, led
->rgb_current
);
259 reg
= bd2802_get_reg_addr(id
, color
, BD2802_REG_CURRENT2SETUP
);
260 bd2802_write_byte(led
->client
, reg
, BD2802_CURRENT_000
);
261 reg
= bd2802_get_reg_addr(id
, color
, BD2802_REG_WAVEPATTERN
);
262 bd2802_write_byte(led
->client
, reg
, BD2802_PATTERN_FULL
);
264 bd2802_enable(led
, id
);
265 bd2802_update_state(led
, id
, color
, BD2802_ON
);
268 static void bd2802_set_blink(struct bd2802_led
*led
, enum led_ids id
,
269 enum led_colors color
)
273 if (bd2802_is_all_off(led
) && !led
->adf_on
)
274 bd2802_reset_cancel(led
);
276 reg
= bd2802_get_reg_addr(id
, color
, BD2802_REG_CURRENT1SETUP
);
277 bd2802_write_byte(led
->client
, reg
, BD2802_CURRENT_000
);
278 reg
= bd2802_get_reg_addr(id
, color
, BD2802_REG_CURRENT2SETUP
);
279 bd2802_write_byte(led
->client
, reg
, led
->rgb_current
);
280 reg
= bd2802_get_reg_addr(id
, color
, BD2802_REG_WAVEPATTERN
);
281 bd2802_write_byte(led
->client
, reg
, led
->wave_pattern
);
283 bd2802_enable(led
, id
);
284 bd2802_update_state(led
, id
, color
, BD2802_BLINK
);
287 static void bd2802_turn_on(struct bd2802_led
*led
, enum led_ids id
,
288 enum led_colors color
, enum led_bits led_bit
)
290 if (led_bit
== BD2802_OFF
) {
291 dev_err(&led
->client
->dev
,
292 "Only 'blink' and 'on' are allowed\n");
296 if (led_bit
== BD2802_BLINK
)
297 bd2802_set_blink(led
, id
, color
);
299 bd2802_set_on(led
, id
, color
);
302 static void bd2802_turn_off(struct bd2802_led
*led
, enum led_ids id
,
303 enum led_colors color
)
307 if (bd2802_is_rgb_off(led
, id
, color
))
310 reg
= bd2802_get_reg_addr(id
, color
, BD2802_REG_CURRENT1SETUP
);
311 bd2802_write_byte(led
->client
, reg
, BD2802_CURRENT_000
);
312 reg
= bd2802_get_reg_addr(id
, color
, BD2802_REG_CURRENT2SETUP
);
313 bd2802_write_byte(led
->client
, reg
, BD2802_CURRENT_000
);
315 bd2802_update_state(led
, id
, color
, BD2802_OFF
);
318 #define BD2802_SET_REGISTER(reg_addr, reg_name) \
319 static ssize_t bd2802_store_reg##reg_addr(struct device *dev, \
320 struct device_attribute *attr, const char *buf, size_t count) \
322 struct bd2802_led *led = i2c_get_clientdata(to_i2c_client(dev));\
327 ret = kstrtoul(buf, 16, &val); \
330 down_write(&led->rwsem); \
331 bd2802_write_byte(led->client, reg_addr, (u8) val); \
332 up_write(&led->rwsem); \
335 static struct device_attribute bd2802_reg##reg_addr##_attr = { \
336 .attr = {.name = reg_name, .mode = 0644}, \
337 .store = bd2802_store_reg##reg_addr, \
340 BD2802_SET_REGISTER(0x00, "0x00");
341 BD2802_SET_REGISTER(0x01, "0x01");
342 BD2802_SET_REGISTER(0x02, "0x02");
343 BD2802_SET_REGISTER(0x03, "0x03");
344 BD2802_SET_REGISTER(0x04, "0x04");
345 BD2802_SET_REGISTER(0x05, "0x05");
346 BD2802_SET_REGISTER(0x06, "0x06");
347 BD2802_SET_REGISTER(0x07, "0x07");
348 BD2802_SET_REGISTER(0x08, "0x08");
349 BD2802_SET_REGISTER(0x09, "0x09");
350 BD2802_SET_REGISTER(0x0a, "0x0a");
351 BD2802_SET_REGISTER(0x0b, "0x0b");
352 BD2802_SET_REGISTER(0x0c, "0x0c");
353 BD2802_SET_REGISTER(0x0d, "0x0d");
354 BD2802_SET_REGISTER(0x0e, "0x0e");
355 BD2802_SET_REGISTER(0x0f, "0x0f");
356 BD2802_SET_REGISTER(0x10, "0x10");
357 BD2802_SET_REGISTER(0x11, "0x11");
358 BD2802_SET_REGISTER(0x12, "0x12");
359 BD2802_SET_REGISTER(0x13, "0x13");
360 BD2802_SET_REGISTER(0x14, "0x14");
361 BD2802_SET_REGISTER(0x15, "0x15");
363 static struct device_attribute
*bd2802_addr_attributes
[] = {
364 &bd2802_reg0x00_attr
,
365 &bd2802_reg0x01_attr
,
366 &bd2802_reg0x02_attr
,
367 &bd2802_reg0x03_attr
,
368 &bd2802_reg0x04_attr
,
369 &bd2802_reg0x05_attr
,
370 &bd2802_reg0x06_attr
,
371 &bd2802_reg0x07_attr
,
372 &bd2802_reg0x08_attr
,
373 &bd2802_reg0x09_attr
,
374 &bd2802_reg0x0a_attr
,
375 &bd2802_reg0x0b_attr
,
376 &bd2802_reg0x0c_attr
,
377 &bd2802_reg0x0d_attr
,
378 &bd2802_reg0x0e_attr
,
379 &bd2802_reg0x0f_attr
,
380 &bd2802_reg0x10_attr
,
381 &bd2802_reg0x11_attr
,
382 &bd2802_reg0x12_attr
,
383 &bd2802_reg0x13_attr
,
384 &bd2802_reg0x14_attr
,
385 &bd2802_reg0x15_attr
,
388 static void bd2802_enable_adv_conf(struct bd2802_led
*led
)
392 for (i
= 0; i
< ARRAY_SIZE(bd2802_addr_attributes
); i
++) {
393 ret
= device_create_file(&led
->client
->dev
,
394 bd2802_addr_attributes
[i
]);
396 dev_err(&led
->client
->dev
, "failed: sysfs file %s\n",
397 bd2802_addr_attributes
[i
]->attr
.name
);
398 goto failed_remove_files
;
402 if (bd2802_is_all_off(led
))
403 bd2802_reset_cancel(led
);
410 for (i
--; i
>= 0; i
--)
411 device_remove_file(&led
->client
->dev
,
412 bd2802_addr_attributes
[i
]);
415 static void bd2802_disable_adv_conf(struct bd2802_led
*led
)
419 for (i
= 0; i
< ARRAY_SIZE(bd2802_addr_attributes
); i
++)
420 device_remove_file(&led
->client
->dev
,
421 bd2802_addr_attributes
[i
]);
423 if (bd2802_is_all_off(led
))
424 gpiod_set_value(led
->reset
, 1);
429 static ssize_t
bd2802_show_adv_conf(struct device
*dev
,
430 struct device_attribute
*attr
, char *buf
)
432 struct bd2802_led
*led
= i2c_get_clientdata(to_i2c_client(dev
));
435 down_read(&led
->rwsem
);
437 ret
= sprintf(buf
, "on\n");
439 ret
= sprintf(buf
, "off\n");
440 up_read(&led
->rwsem
);
445 static ssize_t
bd2802_store_adv_conf(struct device
*dev
,
446 struct device_attribute
*attr
, const char *buf
, size_t count
)
448 struct bd2802_led
*led
= i2c_get_clientdata(to_i2c_client(dev
));
453 down_write(&led
->rwsem
);
454 if (!led
->adf_on
&& !strncmp(buf
, "on", 2))
455 bd2802_enable_adv_conf(led
);
456 else if (led
->adf_on
&& !strncmp(buf
, "off", 3))
457 bd2802_disable_adv_conf(led
);
458 up_write(&led
->rwsem
);
463 static struct device_attribute bd2802_adv_conf_attr
= {
465 .name
= "advanced_configuration",
468 .show
= bd2802_show_adv_conf
,
469 .store
= bd2802_store_adv_conf
,
472 #define BD2802_CONTROL_ATTR(attr_name, name_str) \
473 static ssize_t bd2802_show_##attr_name(struct device *dev, \
474 struct device_attribute *attr, char *buf) \
476 struct bd2802_led *led = i2c_get_clientdata(to_i2c_client(dev));\
478 down_read(&led->rwsem); \
479 ret = sprintf(buf, "0x%02x\n", led->attr_name); \
480 up_read(&led->rwsem); \
483 static ssize_t bd2802_store_##attr_name(struct device *dev, \
484 struct device_attribute *attr, const char *buf, size_t count) \
486 struct bd2802_led *led = i2c_get_clientdata(to_i2c_client(dev));\
491 ret = kstrtoul(buf, 16, &val); \
494 down_write(&led->rwsem); \
495 led->attr_name = val; \
496 up_write(&led->rwsem); \
499 static struct device_attribute bd2802_##attr_name##_attr = { \
504 .show = bd2802_show_##attr_name, \
505 .store = bd2802_store_##attr_name, \
508 BD2802_CONTROL_ATTR(wave_pattern
, "wave_pattern");
509 BD2802_CONTROL_ATTR(rgb_current
, "rgb_current");
511 static struct device_attribute
*bd2802_attributes
[] = {
512 &bd2802_adv_conf_attr
,
513 &bd2802_wave_pattern_attr
,
514 &bd2802_rgb_current_attr
,
517 #define BD2802_CONTROL_RGBS(name, id, clr) \
518 static int bd2802_set_##name##_brightness(struct led_classdev *led_cdev,\
519 enum led_brightness value) \
521 struct bd2802_led *led = \
522 container_of(led_cdev, struct bd2802_led, cdev_##name); \
525 if (value == LED_OFF) { \
526 led->state = BD2802_OFF; \
527 bd2802_turn_off(led, led->led_id, led->color); \
529 led->state = BD2802_ON; \
530 bd2802_turn_on(led, led->led_id, led->color, BD2802_ON);\
534 static int bd2802_set_##name##_blink(struct led_classdev *led_cdev, \
535 unsigned long *delay_on, unsigned long *delay_off) \
537 struct bd2802_led *led = \
538 container_of(led_cdev, struct bd2802_led, cdev_##name); \
539 if (*delay_on == 0 || *delay_off == 0) \
543 led->state = BD2802_BLINK; \
544 bd2802_turn_on(led, led->led_id, led->color, BD2802_BLINK); \
548 BD2802_CONTROL_RGBS(led1r
, LED1
, RED
);
549 BD2802_CONTROL_RGBS(led1g
, LED1
, GREEN
);
550 BD2802_CONTROL_RGBS(led1b
, LED1
, BLUE
);
551 BD2802_CONTROL_RGBS(led2r
, LED2
, RED
);
552 BD2802_CONTROL_RGBS(led2g
, LED2
, GREEN
);
553 BD2802_CONTROL_RGBS(led2b
, LED2
, BLUE
);
555 static int bd2802_register_led_classdev(struct bd2802_led
*led
)
559 led
->cdev_led1r
.name
= "led1_R";
560 led
->cdev_led1r
.brightness
= LED_OFF
;
561 led
->cdev_led1r
.brightness_set_blocking
= bd2802_set_led1r_brightness
;
562 led
->cdev_led1r
.blink_set
= bd2802_set_led1r_blink
;
564 ret
= led_classdev_register(&led
->client
->dev
, &led
->cdev_led1r
);
566 dev_err(&led
->client
->dev
, "couldn't register LED %s\n",
567 led
->cdev_led1r
.name
);
568 goto failed_unregister_led1_R
;
571 led
->cdev_led1g
.name
= "led1_G";
572 led
->cdev_led1g
.brightness
= LED_OFF
;
573 led
->cdev_led1g
.brightness_set_blocking
= bd2802_set_led1g_brightness
;
574 led
->cdev_led1g
.blink_set
= bd2802_set_led1g_blink
;
576 ret
= led_classdev_register(&led
->client
->dev
, &led
->cdev_led1g
);
578 dev_err(&led
->client
->dev
, "couldn't register LED %s\n",
579 led
->cdev_led1g
.name
);
580 goto failed_unregister_led1_G
;
583 led
->cdev_led1b
.name
= "led1_B";
584 led
->cdev_led1b
.brightness
= LED_OFF
;
585 led
->cdev_led1b
.brightness_set_blocking
= bd2802_set_led1b_brightness
;
586 led
->cdev_led1b
.blink_set
= bd2802_set_led1b_blink
;
588 ret
= led_classdev_register(&led
->client
->dev
, &led
->cdev_led1b
);
590 dev_err(&led
->client
->dev
, "couldn't register LED %s\n",
591 led
->cdev_led1b
.name
);
592 goto failed_unregister_led1_B
;
595 led
->cdev_led2r
.name
= "led2_R";
596 led
->cdev_led2r
.brightness
= LED_OFF
;
597 led
->cdev_led2r
.brightness_set_blocking
= bd2802_set_led2r_brightness
;
598 led
->cdev_led2r
.blink_set
= bd2802_set_led2r_blink
;
600 ret
= led_classdev_register(&led
->client
->dev
, &led
->cdev_led2r
);
602 dev_err(&led
->client
->dev
, "couldn't register LED %s\n",
603 led
->cdev_led2r
.name
);
604 goto failed_unregister_led2_R
;
607 led
->cdev_led2g
.name
= "led2_G";
608 led
->cdev_led2g
.brightness
= LED_OFF
;
609 led
->cdev_led2g
.brightness_set_blocking
= bd2802_set_led2g_brightness
;
610 led
->cdev_led2g
.blink_set
= bd2802_set_led2g_blink
;
612 ret
= led_classdev_register(&led
->client
->dev
, &led
->cdev_led2g
);
614 dev_err(&led
->client
->dev
, "couldn't register LED %s\n",
615 led
->cdev_led2g
.name
);
616 goto failed_unregister_led2_G
;
619 led
->cdev_led2b
.name
= "led2_B";
620 led
->cdev_led2b
.brightness
= LED_OFF
;
621 led
->cdev_led2b
.brightness_set_blocking
= bd2802_set_led2b_brightness
;
622 led
->cdev_led2b
.blink_set
= bd2802_set_led2b_blink
;
623 led
->cdev_led2b
.flags
|= LED_CORE_SUSPENDRESUME
;
625 ret
= led_classdev_register(&led
->client
->dev
, &led
->cdev_led2b
);
627 dev_err(&led
->client
->dev
, "couldn't register LED %s\n",
628 led
->cdev_led2b
.name
);
629 goto failed_unregister_led2_B
;
634 failed_unregister_led2_B
:
635 led_classdev_unregister(&led
->cdev_led2g
);
636 failed_unregister_led2_G
:
637 led_classdev_unregister(&led
->cdev_led2r
);
638 failed_unregister_led2_R
:
639 led_classdev_unregister(&led
->cdev_led1b
);
640 failed_unregister_led1_B
:
641 led_classdev_unregister(&led
->cdev_led1g
);
642 failed_unregister_led1_G
:
643 led_classdev_unregister(&led
->cdev_led1r
);
644 failed_unregister_led1_R
:
649 static void bd2802_unregister_led_classdev(struct bd2802_led
*led
)
651 led_classdev_unregister(&led
->cdev_led2b
);
652 led_classdev_unregister(&led
->cdev_led2g
);
653 led_classdev_unregister(&led
->cdev_led2r
);
654 led_classdev_unregister(&led
->cdev_led1b
);
655 led_classdev_unregister(&led
->cdev_led1g
);
656 led_classdev_unregister(&led
->cdev_led1r
);
659 static int bd2802_probe(struct i2c_client
*client
,
660 const struct i2c_device_id
*id
)
662 struct bd2802_led
*led
;
665 led
= devm_kzalloc(&client
->dev
, sizeof(struct bd2802_led
), GFP_KERNEL
);
669 led
->client
= client
;
670 i2c_set_clientdata(client
, led
);
673 * Configure RESET GPIO (L: RESET, H: RESET cancel)
675 * We request the reset GPIO as OUT_LOW which means de-asserted,
676 * board files specifying this GPIO line in a machine descriptor
677 * table should take care to specify GPIO_ACTIVE_LOW for this line.
679 led
->reset
= devm_gpiod_get(&client
->dev
, "reset", GPIOD_OUT_LOW
);
680 if (IS_ERR(led
->reset
))
681 return PTR_ERR(led
->reset
);
683 /* Tacss = min 0.1ms */
686 /* Detect BD2802GU */
687 ret
= bd2802_write_byte(client
, BD2802_REG_CLKSETUP
, 0x00);
689 dev_err(&client
->dev
, "failed to detect device\n");
692 dev_info(&client
->dev
, "return 0x%02x\n", ret
);
694 /* To save the power, reset BD2802 after detecting */
695 gpiod_set_value(led
->reset
, 1);
697 /* Default attributes */
698 led
->wave_pattern
= BD2802_PATTERN_HALF
;
699 led
->rgb_current
= BD2802_CURRENT_032
;
701 init_rwsem(&led
->rwsem
);
703 for (i
= 0; i
< ARRAY_SIZE(bd2802_attributes
); i
++) {
704 ret
= device_create_file(&led
->client
->dev
,
705 bd2802_attributes
[i
]);
707 dev_err(&led
->client
->dev
, "failed: sysfs file %s\n",
708 bd2802_attributes
[i
]->attr
.name
);
709 goto failed_unregister_dev_file
;
713 ret
= bd2802_register_led_classdev(led
);
715 goto failed_unregister_dev_file
;
719 failed_unregister_dev_file
:
720 for (i
--; i
>= 0; i
--)
721 device_remove_file(&led
->client
->dev
, bd2802_attributes
[i
]);
725 static int bd2802_remove(struct i2c_client
*client
)
727 struct bd2802_led
*led
= i2c_get_clientdata(client
);
730 gpiod_set_value(led
->reset
, 1);
731 bd2802_unregister_led_classdev(led
);
733 bd2802_disable_adv_conf(led
);
734 for (i
= 0; i
< ARRAY_SIZE(bd2802_attributes
); i
++)
735 device_remove_file(&led
->client
->dev
, bd2802_attributes
[i
]);
740 #ifdef CONFIG_PM_SLEEP
741 static void bd2802_restore_state(struct bd2802_led
*led
)
745 for (i
= 0; i
< LED_NUM
; i
++) {
747 bd2802_turn_on(led
, i
, RED
, led
->led
[i
].r
);
749 bd2802_turn_on(led
, i
, GREEN
, led
->led
[i
].g
);
751 bd2802_turn_on(led
, i
, BLUE
, led
->led
[i
].b
);
755 static int bd2802_suspend(struct device
*dev
)
757 struct i2c_client
*client
= to_i2c_client(dev
);
758 struct bd2802_led
*led
= i2c_get_clientdata(client
);
760 gpiod_set_value(led
->reset
, 1);
765 static int bd2802_resume(struct device
*dev
)
767 struct i2c_client
*client
= to_i2c_client(dev
);
768 struct bd2802_led
*led
= i2c_get_clientdata(client
);
770 if (!bd2802_is_all_off(led
) || led
->adf_on
) {
771 bd2802_reset_cancel(led
);
772 bd2802_restore_state(led
);
779 static SIMPLE_DEV_PM_OPS(bd2802_pm
, bd2802_suspend
, bd2802_resume
);
781 static const struct i2c_device_id bd2802_id
[] = {
785 MODULE_DEVICE_TABLE(i2c
, bd2802_id
);
787 static struct i2c_driver bd2802_i2c_driver
= {
792 .probe
= bd2802_probe
,
793 .remove
= bd2802_remove
,
794 .id_table
= bd2802_id
,
797 module_i2c_driver(bd2802_i2c_driver
);
799 MODULE_AUTHOR("Kim Kyuwon <q1.kim@samsung.com>");
800 MODULE_DESCRIPTION("BD2802 LED driver");
801 MODULE_LICENSE("GPL v2");