2 * leds-bd2802.c - RGB LED Driver
4 * Copyright (C) 2009 Samsung Electronics
5 * Kim Kyuwon <q1.kim@samsung.com>
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License version 2 as
9 * published by the Free Software Foundation.
11 * Datasheet: http://www.rohm.com/products/databook/driver/pdf/bd2802gu-e.pdf
15 #include <linux/module.h>
16 #include <linux/i2c.h>
17 #include <linux/gpio.h>
18 #include <linux/delay.h>
19 #include <linux/leds.h>
20 #include <linux/leds-bd2802.h>
21 #include <linux/slab.h>
24 #define LED_CTL(rgb2en, rgb1en) ((rgb2en) << 4 | ((rgb1en) << 0))
26 #define BD2802_LED_OFFSET 0xa
27 #define BD2802_COLOR_OFFSET 0x3
29 #define BD2802_REG_CLKSETUP 0x00
30 #define BD2802_REG_CONTROL 0x01
31 #define BD2802_REG_HOURSETUP 0x02
32 #define BD2802_REG_CURRENT1SETUP 0x03
33 #define BD2802_REG_CURRENT2SETUP 0x04
34 #define BD2802_REG_WAVEPATTERN 0x05
36 #define BD2802_CURRENT_032 0x10 /* 3.2mA */
37 #define BD2802_CURRENT_000 0x00 /* 0.0mA */
39 #define BD2802_PATTERN_FULL 0x07
40 #define BD2802_PATTERN_HALF 0x03
72 struct bd2802_led_platform_data
*pdata
;
73 struct i2c_client
*client
;
74 struct rw_semaphore rwsem
;
75 struct work_struct work
;
77 struct led_state led
[2];
80 * Making led_classdev as array is not recommended, because array
81 * members prevent using 'container_of' macro. So repetitive works
84 struct led_classdev cdev_led1r
;
85 struct led_classdev cdev_led1g
;
86 struct led_classdev cdev_led1b
;
87 struct led_classdev cdev_led2r
;
88 struct led_classdev cdev_led2g
;
89 struct led_classdev cdev_led2b
;
92 * Advanced Configuration Function(ADF) mode:
93 * In ADF mode, user can set registers of BD2802GU directly,
94 * therefore BD2802GU doesn't enter reset state.
99 enum led_colors color
;
102 /* General attributes of RGB LEDs */
108 /*--------------------------------------------------------------*/
109 /* BD2802GU helper functions */
110 /*--------------------------------------------------------------*/
112 static inline int bd2802_is_rgb_off(struct bd2802_led
*led
, enum led_ids id
,
113 enum led_colors color
)
117 return !led
->led
[id
].r
;
119 return !led
->led
[id
].g
;
121 return !led
->led
[id
].b
;
123 dev_err(&led
->client
->dev
, "%s: Invalid color\n", __func__
);
128 static inline int bd2802_is_led_off(struct bd2802_led
*led
, enum led_ids id
)
130 if (led
->led
[id
].r
|| led
->led
[id
].g
|| led
->led
[id
].b
)
136 static inline int bd2802_is_all_off(struct bd2802_led
*led
)
140 for (i
= 0; i
< LED_NUM
; i
++)
141 if (!bd2802_is_led_off(led
, i
))
147 static inline u8
bd2802_get_base_offset(enum led_ids id
, enum led_colors color
)
149 return id
* BD2802_LED_OFFSET
+ color
* BD2802_COLOR_OFFSET
;
152 static inline u8
bd2802_get_reg_addr(enum led_ids id
, enum led_colors color
,
155 return reg_offset
+ bd2802_get_base_offset(id
, color
);
159 /*--------------------------------------------------------------*/
160 /* BD2802GU core functions */
161 /*--------------------------------------------------------------*/
163 static int bd2802_write_byte(struct i2c_client
*client
, u8 reg
, u8 val
)
165 int ret
= i2c_smbus_write_byte_data(client
, reg
, val
);
169 dev_err(&client
->dev
, "%s: reg 0x%x, val 0x%x, err %d\n",
170 __func__
, reg
, val
, ret
);
175 static void bd2802_update_state(struct bd2802_led
*led
, enum led_ids id
,
176 enum led_colors color
, enum led_bits led_bit
)
181 for (i
= 0; i
< LED_NUM
; i
++) {
185 led
->led
[i
].r
= led_bit
;
188 led
->led
[i
].g
= led_bit
;
191 led
->led
[i
].b
= led_bit
;
194 dev_err(&led
->client
->dev
,
195 "%s: Invalid color\n", __func__
);
201 if (led_bit
== BD2802_BLINK
|| led_bit
== BD2802_ON
)
204 if (!bd2802_is_led_off(led
, id
))
207 if (bd2802_is_all_off(led
) && !led
->adf_on
) {
208 gpio_set_value(led
->pdata
->reset_gpio
, 0);
213 * In this case, other led is turned on, and current led is turned
214 * off. So set RGB LED Control register to stop the current RGB LED
216 value
= (id
== LED1
) ? LED_CTL(1, 0) : LED_CTL(0, 1);
217 bd2802_write_byte(led
->client
, BD2802_REG_CONTROL
, value
);
220 static void bd2802_configure(struct bd2802_led
*led
)
222 struct bd2802_led_platform_data
*pdata
= led
->pdata
;
225 reg
= bd2802_get_reg_addr(LED1
, RED
, BD2802_REG_HOURSETUP
);
226 bd2802_write_byte(led
->client
, reg
, pdata
->rgb_time
);
228 reg
= bd2802_get_reg_addr(LED2
, RED
, BD2802_REG_HOURSETUP
);
229 bd2802_write_byte(led
->client
, reg
, pdata
->rgb_time
);
232 static void bd2802_reset_cancel(struct bd2802_led
*led
)
234 gpio_set_value(led
->pdata
->reset_gpio
, 1);
236 bd2802_configure(led
);
239 static void bd2802_enable(struct bd2802_led
*led
, enum led_ids id
)
241 enum led_ids other_led
= (id
== LED1
) ? LED2
: LED1
;
242 u8 value
, other_led_on
;
244 other_led_on
= !bd2802_is_led_off(led
, other_led
);
246 value
= LED_CTL(other_led_on
, 1);
248 value
= LED_CTL(1 , other_led_on
);
250 bd2802_write_byte(led
->client
, BD2802_REG_CONTROL
, value
);
253 static void bd2802_set_on(struct bd2802_led
*led
, enum led_ids id
,
254 enum led_colors color
)
258 if (bd2802_is_all_off(led
) && !led
->adf_on
)
259 bd2802_reset_cancel(led
);
261 reg
= bd2802_get_reg_addr(id
, color
, BD2802_REG_CURRENT1SETUP
);
262 bd2802_write_byte(led
->client
, reg
, led
->rgb_current
);
263 reg
= bd2802_get_reg_addr(id
, color
, BD2802_REG_CURRENT2SETUP
);
264 bd2802_write_byte(led
->client
, reg
, BD2802_CURRENT_000
);
265 reg
= bd2802_get_reg_addr(id
, color
, BD2802_REG_WAVEPATTERN
);
266 bd2802_write_byte(led
->client
, reg
, BD2802_PATTERN_FULL
);
268 bd2802_enable(led
, id
);
269 bd2802_update_state(led
, id
, color
, BD2802_ON
);
272 static void bd2802_set_blink(struct bd2802_led
*led
, enum led_ids id
,
273 enum led_colors color
)
277 if (bd2802_is_all_off(led
) && !led
->adf_on
)
278 bd2802_reset_cancel(led
);
280 reg
= bd2802_get_reg_addr(id
, color
, BD2802_REG_CURRENT1SETUP
);
281 bd2802_write_byte(led
->client
, reg
, BD2802_CURRENT_000
);
282 reg
= bd2802_get_reg_addr(id
, color
, BD2802_REG_CURRENT2SETUP
);
283 bd2802_write_byte(led
->client
, reg
, led
->rgb_current
);
284 reg
= bd2802_get_reg_addr(id
, color
, BD2802_REG_WAVEPATTERN
);
285 bd2802_write_byte(led
->client
, reg
, led
->wave_pattern
);
287 bd2802_enable(led
, id
);
288 bd2802_update_state(led
, id
, color
, BD2802_BLINK
);
291 static void bd2802_turn_on(struct bd2802_led
*led
, enum led_ids id
,
292 enum led_colors color
, enum led_bits led_bit
)
294 if (led_bit
== BD2802_OFF
) {
295 dev_err(&led
->client
->dev
,
296 "Only 'blink' and 'on' are allowed\n");
300 if (led_bit
== BD2802_BLINK
)
301 bd2802_set_blink(led
, id
, color
);
303 bd2802_set_on(led
, id
, color
);
306 static void bd2802_turn_off(struct bd2802_led
*led
, enum led_ids id
,
307 enum led_colors color
)
311 if (bd2802_is_rgb_off(led
, id
, color
))
314 reg
= bd2802_get_reg_addr(id
, color
, BD2802_REG_CURRENT1SETUP
);
315 bd2802_write_byte(led
->client
, reg
, BD2802_CURRENT_000
);
316 reg
= bd2802_get_reg_addr(id
, color
, BD2802_REG_CURRENT2SETUP
);
317 bd2802_write_byte(led
->client
, reg
, BD2802_CURRENT_000
);
319 bd2802_update_state(led
, id
, color
, BD2802_OFF
);
322 static void bd2802_restore_state(struct bd2802_led
*led
)
326 for (i
= 0; i
< LED_NUM
; i
++) {
328 bd2802_turn_on(led
, i
, RED
, led
->led
[i
].r
);
330 bd2802_turn_on(led
, i
, GREEN
, led
->led
[i
].g
);
332 bd2802_turn_on(led
, i
, BLUE
, led
->led
[i
].b
);
336 #define BD2802_SET_REGISTER(reg_addr, reg_name) \
337 static ssize_t bd2802_store_reg##reg_addr(struct device *dev, \
338 struct device_attribute *attr, const char *buf, size_t count) \
340 struct bd2802_led *led = i2c_get_clientdata(to_i2c_client(dev));\
345 ret = strict_strtoul(buf, 16, &val); \
348 down_write(&led->rwsem); \
349 bd2802_write_byte(led->client, reg_addr, (u8) val); \
350 up_write(&led->rwsem); \
353 static struct device_attribute bd2802_reg##reg_addr##_attr = { \
354 .attr = {.name = reg_name, .mode = 0644, .owner = THIS_MODULE}, \
355 .store = bd2802_store_reg##reg_addr, \
358 BD2802_SET_REGISTER(0x00, "0x00");
359 BD2802_SET_REGISTER(0x01, "0x01");
360 BD2802_SET_REGISTER(0x02, "0x02");
361 BD2802_SET_REGISTER(0x03, "0x03");
362 BD2802_SET_REGISTER(0x04, "0x04");
363 BD2802_SET_REGISTER(0x05, "0x05");
364 BD2802_SET_REGISTER(0x06, "0x06");
365 BD2802_SET_REGISTER(0x07, "0x07");
366 BD2802_SET_REGISTER(0x08, "0x08");
367 BD2802_SET_REGISTER(0x09, "0x09");
368 BD2802_SET_REGISTER(0x0a, "0x0a");
369 BD2802_SET_REGISTER(0x0b, "0x0b");
370 BD2802_SET_REGISTER(0x0c, "0x0c");
371 BD2802_SET_REGISTER(0x0d, "0x0d");
372 BD2802_SET_REGISTER(0x0e, "0x0e");
373 BD2802_SET_REGISTER(0x0f, "0x0f");
374 BD2802_SET_REGISTER(0x10, "0x10");
375 BD2802_SET_REGISTER(0x11, "0x11");
376 BD2802_SET_REGISTER(0x12, "0x12");
377 BD2802_SET_REGISTER(0x13, "0x13");
378 BD2802_SET_REGISTER(0x14, "0x14");
379 BD2802_SET_REGISTER(0x15, "0x15");
381 static struct device_attribute
*bd2802_addr_attributes
[] = {
382 &bd2802_reg0x00_attr
,
383 &bd2802_reg0x01_attr
,
384 &bd2802_reg0x02_attr
,
385 &bd2802_reg0x03_attr
,
386 &bd2802_reg0x04_attr
,
387 &bd2802_reg0x05_attr
,
388 &bd2802_reg0x06_attr
,
389 &bd2802_reg0x07_attr
,
390 &bd2802_reg0x08_attr
,
391 &bd2802_reg0x09_attr
,
392 &bd2802_reg0x0a_attr
,
393 &bd2802_reg0x0b_attr
,
394 &bd2802_reg0x0c_attr
,
395 &bd2802_reg0x0d_attr
,
396 &bd2802_reg0x0e_attr
,
397 &bd2802_reg0x0f_attr
,
398 &bd2802_reg0x10_attr
,
399 &bd2802_reg0x11_attr
,
400 &bd2802_reg0x12_attr
,
401 &bd2802_reg0x13_attr
,
402 &bd2802_reg0x14_attr
,
403 &bd2802_reg0x15_attr
,
406 static void bd2802_enable_adv_conf(struct bd2802_led
*led
)
410 for (i
= 0; i
< ARRAY_SIZE(bd2802_addr_attributes
); i
++) {
411 ret
= device_create_file(&led
->client
->dev
,
412 bd2802_addr_attributes
[i
]);
414 dev_err(&led
->client
->dev
, "failed: sysfs file %s\n",
415 bd2802_addr_attributes
[i
]->attr
.name
);
416 goto failed_remove_files
;
420 if (bd2802_is_all_off(led
))
421 bd2802_reset_cancel(led
);
428 for (i
--; i
>= 0; i
--)
429 device_remove_file(&led
->client
->dev
,
430 bd2802_addr_attributes
[i
]);
433 static void bd2802_disable_adv_conf(struct bd2802_led
*led
)
437 for (i
= 0; i
< ARRAY_SIZE(bd2802_addr_attributes
); i
++)
438 device_remove_file(&led
->client
->dev
,
439 bd2802_addr_attributes
[i
]);
441 if (bd2802_is_all_off(led
))
442 gpio_set_value(led
->pdata
->reset_gpio
, 0);
447 static ssize_t
bd2802_show_adv_conf(struct device
*dev
,
448 struct device_attribute
*attr
, char *buf
)
450 struct bd2802_led
*led
= i2c_get_clientdata(to_i2c_client(dev
));
453 down_read(&led
->rwsem
);
455 ret
= sprintf(buf
, "on\n");
457 ret
= sprintf(buf
, "off\n");
458 up_read(&led
->rwsem
);
463 static ssize_t
bd2802_store_adv_conf(struct device
*dev
,
464 struct device_attribute
*attr
, const char *buf
, size_t count
)
466 struct bd2802_led
*led
= i2c_get_clientdata(to_i2c_client(dev
));
471 down_write(&led
->rwsem
);
472 if (!led
->adf_on
&& !strncmp(buf
, "on", 2))
473 bd2802_enable_adv_conf(led
);
474 else if (led
->adf_on
&& !strncmp(buf
, "off", 3))
475 bd2802_disable_adv_conf(led
);
476 up_write(&led
->rwsem
);
481 static struct device_attribute bd2802_adv_conf_attr
= {
483 .name
= "advanced_configuration",
487 .show
= bd2802_show_adv_conf
,
488 .store
= bd2802_store_adv_conf
,
491 #define BD2802_CONTROL_ATTR(attr_name, name_str) \
492 static ssize_t bd2802_show_##attr_name(struct device *dev, \
493 struct device_attribute *attr, char *buf) \
495 struct bd2802_led *led = i2c_get_clientdata(to_i2c_client(dev));\
497 down_read(&led->rwsem); \
498 ret = sprintf(buf, "0x%02x\n", led->attr_name); \
499 up_read(&led->rwsem); \
502 static ssize_t bd2802_store_##attr_name(struct device *dev, \
503 struct device_attribute *attr, const char *buf, size_t count) \
505 struct bd2802_led *led = i2c_get_clientdata(to_i2c_client(dev));\
510 ret = strict_strtoul(buf, 16, &val); \
513 down_write(&led->rwsem); \
514 led->attr_name = val; \
515 up_write(&led->rwsem); \
518 static struct device_attribute bd2802_##attr_name##_attr = { \
522 .owner = THIS_MODULE \
524 .show = bd2802_show_##attr_name, \
525 .store = bd2802_store_##attr_name, \
528 BD2802_CONTROL_ATTR(wave_pattern
, "wave_pattern");
529 BD2802_CONTROL_ATTR(rgb_current
, "rgb_current");
531 static struct device_attribute
*bd2802_attributes
[] = {
532 &bd2802_adv_conf_attr
,
533 &bd2802_wave_pattern_attr
,
534 &bd2802_rgb_current_attr
,
537 static void bd2802_led_work(struct work_struct
*work
)
539 struct bd2802_led
*led
= container_of(work
, struct bd2802_led
, work
);
542 bd2802_turn_on(led
, led
->led_id
, led
->color
, led
->state
);
544 bd2802_turn_off(led
, led
->led_id
, led
->color
);
547 #define BD2802_CONTROL_RGBS(name, id, clr) \
548 static void bd2802_set_##name##_brightness(struct led_classdev *led_cdev,\
549 enum led_brightness value) \
551 struct bd2802_led *led = \
552 container_of(led_cdev, struct bd2802_led, cdev_##name); \
555 if (value == LED_OFF) \
556 led->state = BD2802_OFF; \
558 led->state = BD2802_ON; \
559 schedule_work(&led->work); \
561 static int bd2802_set_##name##_blink(struct led_classdev *led_cdev, \
562 unsigned long *delay_on, unsigned long *delay_off) \
564 struct bd2802_led *led = \
565 container_of(led_cdev, struct bd2802_led, cdev_##name); \
566 if (*delay_on == 0 || *delay_off == 0) \
570 led->state = BD2802_BLINK; \
571 schedule_work(&led->work); \
575 BD2802_CONTROL_RGBS(led1r
, LED1
, RED
);
576 BD2802_CONTROL_RGBS(led1g
, LED1
, GREEN
);
577 BD2802_CONTROL_RGBS(led1b
, LED1
, BLUE
);
578 BD2802_CONTROL_RGBS(led2r
, LED2
, RED
);
579 BD2802_CONTROL_RGBS(led2g
, LED2
, GREEN
);
580 BD2802_CONTROL_RGBS(led2b
, LED2
, BLUE
);
582 static int bd2802_register_led_classdev(struct bd2802_led
*led
)
586 INIT_WORK(&led
->work
, bd2802_led_work
);
588 led
->cdev_led1r
.name
= "led1_R";
589 led
->cdev_led1r
.brightness
= LED_OFF
;
590 led
->cdev_led1r
.brightness_set
= bd2802_set_led1r_brightness
;
591 led
->cdev_led1r
.blink_set
= bd2802_set_led1r_blink
;
593 ret
= led_classdev_register(&led
->client
->dev
, &led
->cdev_led1r
);
595 dev_err(&led
->client
->dev
, "couldn't register LED %s\n",
596 led
->cdev_led1r
.name
);
597 goto failed_unregister_led1_R
;
600 led
->cdev_led1g
.name
= "led1_G";
601 led
->cdev_led1g
.brightness
= LED_OFF
;
602 led
->cdev_led1g
.brightness_set
= bd2802_set_led1g_brightness
;
603 led
->cdev_led1g
.blink_set
= bd2802_set_led1g_blink
;
605 ret
= led_classdev_register(&led
->client
->dev
, &led
->cdev_led1g
);
607 dev_err(&led
->client
->dev
, "couldn't register LED %s\n",
608 led
->cdev_led1g
.name
);
609 goto failed_unregister_led1_G
;
612 led
->cdev_led1b
.name
= "led1_B";
613 led
->cdev_led1b
.brightness
= LED_OFF
;
614 led
->cdev_led1b
.brightness_set
= bd2802_set_led1b_brightness
;
615 led
->cdev_led1b
.blink_set
= bd2802_set_led1b_blink
;
617 ret
= led_classdev_register(&led
->client
->dev
, &led
->cdev_led1b
);
619 dev_err(&led
->client
->dev
, "couldn't register LED %s\n",
620 led
->cdev_led1b
.name
);
621 goto failed_unregister_led1_B
;
624 led
->cdev_led2r
.name
= "led2_R";
625 led
->cdev_led2r
.brightness
= LED_OFF
;
626 led
->cdev_led2r
.brightness_set
= bd2802_set_led2r_brightness
;
627 led
->cdev_led2r
.blink_set
= bd2802_set_led2r_blink
;
629 ret
= led_classdev_register(&led
->client
->dev
, &led
->cdev_led2r
);
631 dev_err(&led
->client
->dev
, "couldn't register LED %s\n",
632 led
->cdev_led2r
.name
);
633 goto failed_unregister_led2_R
;
636 led
->cdev_led2g
.name
= "led2_G";
637 led
->cdev_led2g
.brightness
= LED_OFF
;
638 led
->cdev_led2g
.brightness_set
= bd2802_set_led2g_brightness
;
639 led
->cdev_led2g
.blink_set
= bd2802_set_led2g_blink
;
641 ret
= led_classdev_register(&led
->client
->dev
, &led
->cdev_led2g
);
643 dev_err(&led
->client
->dev
, "couldn't register LED %s\n",
644 led
->cdev_led2g
.name
);
645 goto failed_unregister_led2_G
;
648 led
->cdev_led2b
.name
= "led2_B";
649 led
->cdev_led2b
.brightness
= LED_OFF
;
650 led
->cdev_led2b
.brightness_set
= bd2802_set_led2b_brightness
;
651 led
->cdev_led2b
.blink_set
= bd2802_set_led2b_blink
;
652 led
->cdev_led2b
.flags
|= LED_CORE_SUSPENDRESUME
;
654 ret
= led_classdev_register(&led
->client
->dev
, &led
->cdev_led2b
);
656 dev_err(&led
->client
->dev
, "couldn't register LED %s\n",
657 led
->cdev_led2b
.name
);
658 goto failed_unregister_led2_B
;
663 failed_unregister_led2_B
:
664 led_classdev_unregister(&led
->cdev_led2g
);
665 failed_unregister_led2_G
:
666 led_classdev_unregister(&led
->cdev_led2r
);
667 failed_unregister_led2_R
:
668 led_classdev_unregister(&led
->cdev_led1b
);
669 failed_unregister_led1_B
:
670 led_classdev_unregister(&led
->cdev_led1g
);
671 failed_unregister_led1_G
:
672 led_classdev_unregister(&led
->cdev_led1r
);
673 failed_unregister_led1_R
:
678 static void bd2802_unregister_led_classdev(struct bd2802_led
*led
)
680 cancel_work_sync(&led
->work
);
681 led_classdev_unregister(&led
->cdev_led1r
);
684 static int __devinit
bd2802_probe(struct i2c_client
*client
,
685 const struct i2c_device_id
*id
)
687 struct bd2802_led
*led
;
688 struct bd2802_led_platform_data
*pdata
;
691 led
= kzalloc(sizeof(struct bd2802_led
), GFP_KERNEL
);
693 dev_err(&client
->dev
, "failed to allocate driver data\n");
697 led
->client
= client
;
698 pdata
= led
->pdata
= client
->dev
.platform_data
;
699 i2c_set_clientdata(client
, led
);
701 /* Configure RESET GPIO (L: RESET, H: RESET cancel) */
702 gpio_request(pdata
->reset_gpio
, "RGB_RESETB");
703 gpio_direction_output(pdata
->reset_gpio
, 1);
705 /* Tacss = min 0.1ms */
708 /* Detect BD2802GU */
709 ret
= bd2802_write_byte(client
, BD2802_REG_CLKSETUP
, 0x00);
711 dev_err(&client
->dev
, "failed to detect device\n");
714 dev_info(&client
->dev
, "return 0x%02x\n", ret
);
716 /* To save the power, reset BD2802 after detecting */
717 gpio_set_value(led
->pdata
->reset_gpio
, 0);
719 /* Default attributes */
720 led
->wave_pattern
= BD2802_PATTERN_HALF
;
721 led
->rgb_current
= BD2802_CURRENT_032
;
723 init_rwsem(&led
->rwsem
);
725 for (i
= 0; i
< ARRAY_SIZE(bd2802_attributes
); i
++) {
726 ret
= device_create_file(&led
->client
->dev
,
727 bd2802_attributes
[i
]);
729 dev_err(&led
->client
->dev
, "failed: sysfs file %s\n",
730 bd2802_attributes
[i
]->attr
.name
);
731 goto failed_unregister_dev_file
;
735 ret
= bd2802_register_led_classdev(led
);
737 goto failed_unregister_dev_file
;
741 failed_unregister_dev_file
:
742 for (i
--; i
>= 0; i
--)
743 device_remove_file(&led
->client
->dev
, bd2802_attributes
[i
]);
745 i2c_set_clientdata(client
, NULL
);
751 static int __exit
bd2802_remove(struct i2c_client
*client
)
753 struct bd2802_led
*led
= i2c_get_clientdata(client
);
756 gpio_set_value(led
->pdata
->reset_gpio
, 0);
757 bd2802_unregister_led_classdev(led
);
759 bd2802_disable_adv_conf(led
);
760 for (i
= 0; i
< ARRAY_SIZE(bd2802_attributes
); i
++)
761 device_remove_file(&led
->client
->dev
, bd2802_attributes
[i
]);
762 i2c_set_clientdata(client
, NULL
);
768 static int bd2802_suspend(struct i2c_client
*client
, pm_message_t mesg
)
770 struct bd2802_led
*led
= i2c_get_clientdata(client
);
772 gpio_set_value(led
->pdata
->reset_gpio
, 0);
777 static int bd2802_resume(struct i2c_client
*client
)
779 struct bd2802_led
*led
= i2c_get_clientdata(client
);
781 if (!bd2802_is_all_off(led
) || led
->adf_on
) {
782 bd2802_reset_cancel(led
);
783 bd2802_restore_state(led
);
789 static const struct i2c_device_id bd2802_id
[] = {
793 MODULE_DEVICE_TABLE(i2c
, bd2802_id
);
795 static struct i2c_driver bd2802_i2c_driver
= {
799 .probe
= bd2802_probe
,
800 .remove
= __exit_p(bd2802_remove
),
801 .suspend
= bd2802_suspend
,
802 .resume
= bd2802_resume
,
803 .id_table
= bd2802_id
,
806 static int __init
bd2802_init(void)
808 return i2c_add_driver(&bd2802_i2c_driver
);
810 module_init(bd2802_init
);
812 static void __exit
bd2802_exit(void)
814 i2c_del_driver(&bd2802_i2c_driver
);
816 module_exit(bd2802_exit
);
818 MODULE_AUTHOR("Kim Kyuwon <q1.kim@samsung.com>");
819 MODULE_DESCRIPTION("BD2802 LED driver");
820 MODULE_LICENSE("GPL v2");