import PULS_20160108
[GitHub/mt8127/android_kernel_alcatel_ttab.git] / drivers / misc / mediatek / leds / leds_drv.c
1 /*
2 * drivers/leds/leds-mt65xx.c
3 *
4 * This file is subject to the terms and conditions of the GNU General Public
5 * License. See the file COPYING in the main directory of this archive for
6 * more details.
7 *
8 * mt65xx leds driver
9 *
10 */
11
12 #include <linux/module.h>
13 #include <linux/platform_device.h>
14 #include <linux/delay.h>
15 #include <linux/string.h>
16 #include <linux/ctype.h>
17 #include <linux/leds.h>
18 #include <linux/leds-mt65xx.h>
19 #include <linux/workqueue.h>
20 #include <linux/wakelock.h>
21 #include <linux/slab.h>
22 #include <linux/spinlock.h>
23 /* #include <cust_leds.h> */
24 /* #include <cust_leds_def.h> */
25 #include <mach/mt_pwm.h>
26 /* #include <mach/mt_pwm_hal.h> */
27 /* #include <mach/mt_gpio.h> */
28 #include <mach/upmu_common_sw.h>
29 #include <mach/upmu_hw.h>
30 /* #include <mach/mt_pmic_feature_api.h> */
31 /* #include <mach/mt_boot.h> */
32 #include <leds_hal.h>
33 /* #include <linux/leds_hal.h> */
34 #include "leds_drv.h"
35
36
37
38 /****************************************************************************
39 * variables
40 ***************************************************************************/
41 struct cust_mt65xx_led *bl_setting = NULL;
42 /*[PLATFORM]-ADD-BEIGIN by falin.luo 2015.4.17*/
43 /*hall sensor use bl brighrness to detect system status*/
44 #ifdef CONFIG_MTK_HALL
45 unsigned int bl_brightness = 102;
46 #else
47 static unsigned int bl_brightness = 102;
48 #endif
49 /*[PLATFORM]-ADD-END by falin.luo 2015.4.17*/
50 static unsigned int bl_duty = 21;
51 static unsigned int bl_div = CLK_DIV1;
52 static unsigned int bl_frequency = 32000;
53 static unsigned int div_array[PWM_DIV_NUM];
54 struct mt65xx_led_data *g_leds_data[MT65XX_LED_TYPE_TOTAL];
55
56
57 /****************************************************************************
58 * DEBUG MACROS
59 ***************************************************************************/
60 static int debug_enable_led = 1;
61 #define LEDS_DRV_DEBUG(format, args...) do { \
62 if (debug_enable_led) \
63 {\
64 printk(KERN_WARNING format, ##args);\
65 } \
66 } while (0)
67
68 /****************************************************************************
69 * function prototypes
70 ***************************************************************************/
71 #ifndef CONTROL_BL_TEMPERATURE
72 #define CONTROL_BL_TEMPERATURE
73 #endif
74
75 #define MT_LED_INTERNAL_LEVEL_BIT_CNT 10
76
77 #ifdef CONTROL_BL_TEMPERATURE
78 int setMaxbrightness(int max_level, int enable);
79
80 #endif
81
82 /******************************************************************************
83 for DISP backlight High resolution
84 ******************************************************************************/
85 #ifdef LED_INCREASE_LED_LEVEL_MTKPATCH
86 #define LED_INTERNAL_LEVEL_BIT_CNT 10
87 #endif
88
89
90 static int mt65xx_led_set_cust(struct cust_mt65xx_led *cust, int level);
91
92 /****************************************************************************
93 * add API for temperature control
94 ***************************************************************************/
95
96 #ifdef CONTROL_BL_TEMPERATURE
97
98 /* define int limit for brightness limitation */
99 static unsigned int limit = 255;
100 static unsigned int limit_flag;
101 static unsigned int last_level;
102 static unsigned int current_level;
103 static DEFINE_MUTEX(bl_level_limit_mutex);
104 extern int disp_bls_set_max_backlight(unsigned int level);
105
106
107 /* this API add for control the power and temperature */
108 /* if enabe=1, the value of brightness will smaller than max_level, whatever lightservice transfers to driver */
109 int setMaxbrightness(int max_level, int enable)
110 {
111 #if !defined(CONFIG_MTK_AAL_SUPPORT)
112 struct cust_mt65xx_led *cust_led_list = mt_get_cust_led_list();
113 mutex_lock(&bl_level_limit_mutex);
114 if (1 == enable) {
115 limit_flag = 1;
116 limit = max_level;
117 mutex_unlock(&bl_level_limit_mutex);
118 /* LEDS_DRV_DEBUG("[LED] setMaxbrightness limit happen and release lock!!\n"); */
119 /* LEDS_DRV_DEBUG("setMaxbrightness enable:last_level=%d, current_level=%d\n", last_level, current_level); */
120 /* if (limit < last_level){ */
121 if (0 != current_level) {
122 if (limit < last_level) {
123 LEDS_DRV_DEBUG
124 ("mt65xx_leds_set_cust in setMaxbrightness:value control start! limit=%d\n",
125 limit);
126 mt65xx_led_set_cust(&cust_led_list[MT65XX_LED_TYPE_LCD], limit);
127 } else {
128 /* LEDS_DRV_DEBUG("mt65xx_leds_set_cust in setMaxbrightness:value control start! last_level=%d\n", last_level); */
129 mt65xx_led_set_cust(&cust_led_list[MT65XX_LED_TYPE_LCD],
130 last_level);
131 }
132 }
133 } else {
134 limit_flag = 0;
135 limit = 255;
136 mutex_unlock(&bl_level_limit_mutex);
137 /* LEDS_DRV_DEBUG("[LED] setMaxbrightness limit closed and and release lock!!\n"); */
138 /* LEDS_DRV_DEBUG("setMaxbrightness disable:last_level=%d, current_level=%d\n", last_level, current_level); */
139
140 /* if (last_level != 0){ */
141 if (0 != current_level) {
142 LEDS_DRV_DEBUG("control temperature close:limit=%d\n", limit);
143 mt65xx_led_set_cust(&cust_led_list[MT65XX_LED_TYPE_LCD], last_level);
144
145 /* printk("mt65xx_leds_set_cust in setMaxbrightness:value control close!\n"); */
146 }
147 }
148
149 /* LEDS_DRV_DEBUG("[LED] setMaxbrightness limit_flag = %d, limit=%d, current_level=%d\n",limit_flag, limit, current_level); */
150
151 #else
152 LEDS_DRV_DEBUG("setMaxbrightness go through AAL\n");
153 disp_bls_set_max_backlight(max_level);
154 #endif /* endif CONFIG_MTK_AAL_SUPPORT */
155 return 0;
156
157 }
158 #endif
159 /****************************************************************************
160 * internal functions
161 ***************************************************************************/
162 static void get_div_array(void)
163 {
164 int i = 0;
165 unsigned int *temp = mt_get_div_array();
166 while (i < PWM_DIV_NUM) {
167 div_array[i] = *temp++;
168 LEDS_DRV_DEBUG("get_div_array: div_array=%d\n", div_array[i]);
169 i++;
170 }
171 }
172
173 static int led_set_pwm(int pwm_num, struct nled_setting *led)
174 {
175
176 mt_led_set_pwm(pwm_num, led);
177 return 0;
178 }
179
180 static int brightness_set_pmic(enum mt65xx_led_pmic pmic_type, u32 level, u32 div)
181 {
182 mt_brightness_set_pmic(pmic_type, level, div);
183 return -1;
184
185 }
186
187 static int mt65xx_led_set_cust(struct cust_mt65xx_led *cust, int level)
188 {
189 #ifdef CONTROL_BL_TEMPERATURE
190 mutex_lock(&bl_level_limit_mutex);
191 current_level = level;
192 /* LEDS_DRV_DEBUG("brightness_set_cust:current_level=%d\n", current_level); */
193 if (0 == limit_flag) {
194 last_level = level;
195 /* LEDS_DRV_DEBUG("brightness_set_cust:last_level=%d\n", last_level); */
196 } else {
197 if (limit < current_level) {
198 level = limit;
199 /* LEDS_DRV_DEBUG("backlight_set_cust: control level=%d\n", level); */
200 }
201 }
202 mutex_unlock(&bl_level_limit_mutex);
203 #endif
204 #ifdef LED_INCREASE_LED_LEVEL_MTKPATCH
205 if (MT65XX_LED_MODE_CUST_BLS_PWM == cust->mode) {
206 mt_mt65xx_led_set_cust(cust,
207 ((((1 << LED_INTERNAL_LEVEL_BIT_CNT) - 1) * level +
208 127) / 255));
209 } else {
210 mt_mt65xx_led_set_cust(cust, level);
211 }
212 #else
213 mt_mt65xx_led_set_cust(cust, level);
214 #endif
215 return -1;
216 }
217
218
219 static void mt65xx_led_set(struct led_classdev *led_cdev, enum led_brightness level)
220 {
221 struct mt65xx_led_data *led_data = container_of(led_cdev, struct mt65xx_led_data, cdev);
222 if (strcmp(led_data->cust.name, "lcd-backlight") == 0) {
223 #ifdef CONTROL_BL_TEMPERATURE
224 mutex_lock(&bl_level_limit_mutex);
225 current_level = level;
226 /* LEDS_DRV_DEBUG("brightness_set_cust:current_level=%d\n", current_level); */
227 if (0 == limit_flag) {
228 last_level = level;
229 /* LEDS_DRV_DEBUG("brightness_set_cust:last_level=%d\n", last_level); */
230 } else {
231 if (limit < current_level) {
232 level = limit;
233 LEDS_DRV_DEBUG("backlight_set_cust: control level=%d\n", level);
234 }
235 }
236 mutex_unlock(&bl_level_limit_mutex);
237 #endif
238 }
239 mt_mt65xx_led_set(led_cdev, level);
240 }
241
242 static int mt65xx_blink_set(struct led_classdev *led_cdev,
243 unsigned long *delay_on, unsigned long *delay_off)
244 {
245 if (mt_mt65xx_blink_set(led_cdev, delay_on, delay_off)) {
246 return -1;
247 } else {
248 return 0;
249 }
250 }
251
252 /****************************************************************************
253 * external functions
254 ***************************************************************************/
255 int mt65xx_leds_brightness_set(enum mt65xx_led_type type, enum led_brightness level)
256 {
257 struct cust_mt65xx_led *cust_led_list = mt_get_cust_led_list();
258
259 LEDS_DRV_DEBUG("[LED]#%d:%d\n", type, level);
260
261 if (type < 0 || type >= MT65XX_LED_TYPE_TOTAL)
262 return -1;
263
264 if (level > LED_FULL)
265 level = LED_FULL;
266 else if (level < 0)
267 level = 0;
268
269 return mt65xx_led_set_cust(&cust_led_list[type], level);
270
271 }
272 EXPORT_SYMBOL(mt65xx_leds_brightness_set);
273
274
275 /****************************************************************************
276 * external functions
277 ***************************************************************************/
278 int backlight_brightness_set(int level)
279 {
280 struct cust_mt65xx_led *cust_led_list = mt_get_cust_led_list();
281
282 if (level > ((1 << MT_LED_INTERNAL_LEVEL_BIT_CNT) - 1) )
283 level = ((1 << MT_LED_INTERNAL_LEVEL_BIT_CNT) - 1);
284 else if (level < 0)
285 level = 0;
286
287 if(MT65XX_LED_MODE_CUST_BLS_PWM == cust_led_list[MT65XX_LED_TYPE_LCD].mode)
288 {
289 #ifdef CONTROL_BL_TEMPERATURE
290 mutex_lock(&bl_level_limit_mutex);
291 current_level = (level >> (MT_LED_INTERNAL_LEVEL_BIT_CNT - 8)); // 8 bits
292 if(0 == limit_flag){
293 last_level = current_level;
294 }else {
295 if(limit < current_level){
296 // extend 8-bit limit to 10 bits
297 level = (limit << (MT_LED_INTERNAL_LEVEL_BIT_CNT - 8)) | (limit >> (16 - MT_LED_INTERNAL_LEVEL_BIT_CNT));
298 }
299 }
300 mutex_unlock(&bl_level_limit_mutex);
301 #endif
302
303 return mt_mt65xx_led_set_cust(&cust_led_list[MT65XX_LED_TYPE_LCD], level);
304 }
305 else
306 {
307 return mt65xx_led_set_cust(&cust_led_list[MT65XX_LED_TYPE_LCD],( level >> (MT_LED_INTERNAL_LEVEL_BIT_CNT - 8)) );
308 }
309
310 }
311
312 EXPORT_SYMBOL(backlight_brightness_set);
313
314
315 static ssize_t show_duty(struct device *dev, struct device_attribute *attr, char *buf)
316 {
317 LEDS_DRV_DEBUG("[LED]get backlight duty value is:%d\n", bl_duty);
318 return sprintf(buf, "%u\n", bl_duty);
319 }
320
321 static ssize_t store_duty(struct device *dev, struct device_attribute *attr, const char *buf,
322 size_t size)
323 {
324 char *pvalue = NULL;
325 unsigned int level = 0;
326 size_t count = 0;
327 bl_div = mt_get_bl_div();
328 LEDS_DRV_DEBUG("set backlight duty start\n");
329 level = simple_strtoul(buf, &pvalue, 10);
330 count = pvalue - buf;
331 if (*pvalue && isspace(*pvalue))
332 count++;
333
334 if (count == size) {
335
336 if (bl_setting->mode == MT65XX_LED_MODE_PMIC) {
337 /* duty:0-16 */
338 if ((level >= 0) && (level <= 15)) {
339 mt_brightness_set_pmic_duty_store((level * 17), bl_div);
340 } else {
341 LEDS_DRV_DEBUG
342 ("duty value is error, please select vaule from [0-15]!\n");
343 }
344
345 }
346
347 else if (bl_setting->mode == MT65XX_LED_MODE_PWM) {
348 if (level == 0) {
349 mt_led_pwm_disable(bl_setting->data);
350 } else if (level <= 64) {
351 mt_backlight_set_pwm_duty(bl_setting->data, level, bl_div,
352 &bl_setting->config_data);
353 }
354 }
355
356 mt_set_bl_duty(level);
357
358 }
359
360 return size;
361 }
362
363
364 static DEVICE_ATTR(duty, 0664, show_duty, store_duty);
365
366
367 static ssize_t show_div(struct device *dev, struct device_attribute *attr, char *buf)
368 {
369 bl_div = mt_get_bl_div();
370 LEDS_DRV_DEBUG("get backlight div value is:%d\n", bl_div);
371 return sprintf(buf, "%u\n", bl_div);
372 }
373
374 static ssize_t store_div(struct device *dev, struct device_attribute *attr, const char *buf,
375 size_t size)
376 {
377 char *pvalue = NULL;
378 unsigned int div = 0;
379 size_t count = 0;
380
381 bl_duty = mt_get_bl_duty();
382 LEDS_DRV_DEBUG("set backlight div start\n");
383 div = simple_strtoul(buf, &pvalue, 10);
384 count = pvalue - buf;
385
386 if (*pvalue && isspace(*pvalue))
387 count++;
388
389 if (count == size) {
390 if (div < 0 || (div > 7)) {
391 LEDS_DRV_DEBUG("set backlight div parameter error: %d[div:0~7]\n", div);
392 return 0;
393 }
394
395 if (bl_setting->mode == MT65XX_LED_MODE_PWM) {
396 LEDS_DRV_DEBUG("set PWM backlight div OK: div=%d, duty=%d\n", div, bl_duty);
397 mt_backlight_set_pwm_div(bl_setting->data, bl_duty, div,
398 &bl_setting->config_data);
399 }
400
401 else if (bl_setting->mode == MT65XX_LED_MODE_CUST_LCM) {
402 bl_brightness = mt_get_bl_brightness();
403 LEDS_DRV_DEBUG("set cust backlight div OK: div=%d, brightness=%d\n", div,
404 bl_brightness);
405 ((cust_brightness_set) (bl_setting->data)) (bl_brightness, div);
406 }
407 mt_set_bl_div(div);
408
409 }
410
411 return size;
412 }
413
414 static DEVICE_ATTR(div, 0664, show_div, store_div);
415
416
417 static ssize_t show_frequency(struct device *dev, struct device_attribute *attr, char *buf)
418 {
419 bl_div = mt_get_bl_div();
420 bl_frequency = mt_get_bl_frequency();
421
422 if (bl_setting->mode == MT65XX_LED_MODE_PWM) {
423 mt_set_bl_frequency(32000 / div_array[bl_div]);
424 } else if (bl_setting->mode == MT65XX_LED_MODE_CUST_LCM) {
425 /* mtkfb_get_backlight_pwm(bl_div, &bl_frequency); */
426 mt_backlight_get_pwm_fsel(bl_div, &bl_frequency);
427 }
428
429 LEDS_DRV_DEBUG("[LED]get backlight PWM frequency value is:%d\n", bl_frequency);
430
431 return sprintf(buf, "%u\n", bl_frequency);
432 }
433
434 static DEVICE_ATTR(frequency, 0444, show_frequency, NULL);
435
436
437
438 static ssize_t store_pwm_register(struct device *dev, struct device_attribute *attr,
439 const char *buf, size_t size)
440 {
441 char *pvalue = NULL;
442 unsigned int reg_value = 0;
443 unsigned int reg_address = 0;
444 if (buf != NULL && size != 0) {
445 //LEDS_DRV_DEBUG("store_pwm_register: size:%d,address:0x%s\n", size, buf);
446 reg_address = simple_strtoul(buf, &pvalue, 16);
447
448 if (*pvalue && (*pvalue == '#')) {
449 reg_value = simple_strtoul((pvalue + 1), NULL, 16);
450 LEDS_DRV_DEBUG("set pwm register:[0x%x]= 0x%x\n", reg_address, reg_value);
451 /* OUTREG32(reg_address,reg_value); */
452 mt_store_pwm_register(reg_address, reg_value);
453
454 } else if (*pvalue && (*pvalue == '@')) {
455 LEDS_DRV_DEBUG("get pwm register:[0x%x]=0x%x\n", reg_address,
456 mt_show_pwm_register(reg_address));
457 }
458 }
459
460 return size;
461 }
462
463 static ssize_t show_pwm_register(struct device *dev, struct device_attribute *attr, char *buf)
464 {
465 return 0;
466 }
467
468 static DEVICE_ATTR(pwm_register, 0664, show_pwm_register, store_pwm_register);
469
470
471 /****************************************************************************
472 * driver functions
473 ***************************************************************************/
474 static int __init mt65xx_leds_probe(struct platform_device *pdev)
475 {
476 int i;
477 int ret, rc;
478 struct cust_mt65xx_led *cust_led_list = mt_get_cust_led_list();
479 LEDS_DRV_DEBUG("[LED]%s\n", __func__);
480 get_div_array();
481 for (i = 0; i < MT65XX_LED_TYPE_TOTAL; i++) {
482 if (cust_led_list[i].mode == MT65XX_LED_MODE_NONE) {
483 g_leds_data[i] = NULL;
484 continue;
485 }
486
487 g_leds_data[i] = kzalloc(sizeof(struct mt65xx_led_data), GFP_KERNEL);
488 if (!g_leds_data[i]) {
489 ret = -ENOMEM;
490 goto err;
491 }
492
493 g_leds_data[i]->cust.mode = cust_led_list[i].mode;
494 g_leds_data[i]->cust.data = cust_led_list[i].data;
495 g_leds_data[i]->cust.name = cust_led_list[i].name;
496
497 g_leds_data[i]->cdev.name = cust_led_list[i].name;
498 g_leds_data[i]->cust.config_data = cust_led_list[i].config_data; /* bei add */
499
500 g_leds_data[i]->cdev.brightness_set = mt65xx_led_set;
501 g_leds_data[i]->cdev.blink_set = mt65xx_blink_set;
502
503 INIT_WORK(&g_leds_data[i]->work, mt_mt65xx_led_work);
504
505 ret = led_classdev_register(&pdev->dev, &g_leds_data[i]->cdev);
506
507 if (strcmp(g_leds_data[i]->cdev.name, "lcd-backlight") == 0) {
508 rc = device_create_file(g_leds_data[i]->cdev.dev, &dev_attr_duty);
509 if (rc) {
510 LEDS_DRV_DEBUG("[LED]device_create_file duty fail!\n");
511 }
512
513 rc = device_create_file(g_leds_data[i]->cdev.dev, &dev_attr_div);
514 if (rc) {
515 LEDS_DRV_DEBUG("[LED]device_create_file duty fail!\n");
516 }
517
518 rc = device_create_file(g_leds_data[i]->cdev.dev, &dev_attr_frequency);
519 if (rc) {
520 LEDS_DRV_DEBUG("[LED]device_create_file duty fail!\n");
521 }
522
523 rc = device_create_file(g_leds_data[i]->cdev.dev, &dev_attr_pwm_register);
524 if (rc) {
525 LEDS_DRV_DEBUG("[LED]device_create_file duty fail!\n");
526 }
527 bl_setting = &g_leds_data[i]->cust;
528 }
529
530 if (ret)
531 goto err;
532
533 }
534 #ifdef CONTROL_BL_TEMPERATURE
535
536 last_level = 0;
537 limit = 255;
538 limit_flag = 0;
539 current_level = 0;
540 LEDS_DRV_DEBUG
541 ("[LED]led probe last_level = %d, limit = %d, limit_flag = %d, current_level = %d\n",
542 last_level, limit, limit_flag, current_level);
543 #endif
544
545
546 return 0;
547
548 err:
549 if (i) {
550 for (i = i - 1; i >= 0; i--) {
551 if (!g_leds_data[i])
552 continue;
553 led_classdev_unregister(&g_leds_data[i]->cdev);
554 cancel_work_sync(&g_leds_data[i]->work);
555 kfree(g_leds_data[i]);
556 g_leds_data[i] = NULL;
557 }
558 }
559
560 return ret;
561 }
562
563 static int mt65xx_leds_remove(struct platform_device *pdev)
564 {
565 int i;
566 for (i = 0; i < MT65XX_LED_TYPE_TOTAL; i++) {
567 if (!g_leds_data[i])
568 continue;
569 led_classdev_unregister(&g_leds_data[i]->cdev);
570 cancel_work_sync(&g_leds_data[i]->work);
571 kfree(g_leds_data[i]);
572 g_leds_data[i] = NULL;
573 }
574
575 return 0;
576 }
577
578 /*
579 static int mt65xx_leds_suspend(struct platform_device *pdev, pm_message_t state)
580 {
581 return 0;
582 }
583 */
584
585 static void mt65xx_leds_shutdown(struct platform_device *pdev)
586 {
587 int i;
588 struct nled_setting led_tmp_setting = { NLED_OFF, 0, 0 };
589
590 LEDS_DRV_DEBUG("[LED]%s\n", __func__);
591 LEDS_DRV_DEBUG("[LED]mt65xx_leds_shutdown: turn off backlight\n");
592
593 for (i = 0; i < MT65XX_LED_TYPE_TOTAL; i++) {
594 if (!g_leds_data[i])
595 continue;
596 switch (g_leds_data[i]->cust.mode) {
597
598 case MT65XX_LED_MODE_PWM:
599 if (strcmp(g_leds_data[i]->cust.name, "lcd-backlight") == 0) {
600 /* mt_set_pwm_disable(g_leds_data[i]->cust.data); */
601 /* mt_pwm_power_off (g_leds_data[i]->cust.data); */
602 mt_led_pwm_disable(g_leds_data[i]->cust.data);
603 } else {
604 led_set_pwm(g_leds_data[i]->cust.data, &led_tmp_setting);
605 }
606 break;
607
608 /* case MT65XX_LED_MODE_GPIO: */
609 /* brightness_set_gpio(g_leds_data[i]->cust.data, 0); */
610 /* break; */
611
612 case MT65XX_LED_MODE_PMIC:
613 brightness_set_pmic(g_leds_data[i]->cust.data, 0, 0);
614 break;
615 case MT65XX_LED_MODE_CUST_LCM:
616 LEDS_DRV_DEBUG("[LED]backlight control through LCM!!1\n");
617 ((cust_brightness_set) (g_leds_data[i]->cust.data)) (0, bl_div);
618 break;
619 case MT65XX_LED_MODE_CUST_BLS_PWM:
620 LEDS_DRV_DEBUG("[LED]backlight control through BLS!!1\n");
621 ((cust_set_brightness) (g_leds_data[i]->cust.data)) (0);
622 break;
623 case MT65XX_LED_MODE_NONE:
624 default:
625 break;
626 }
627 }
628
629 }
630
631 static struct platform_driver mt65xx_leds_driver = {
632 .driver = {
633 .name = "leds-mt65xx",
634 .owner = THIS_MODULE,
635 },
636 .probe = mt65xx_leds_probe,
637 .remove = mt65xx_leds_remove,
638 /* .suspend = mt65xx_leds_suspend, */
639 .shutdown = mt65xx_leds_shutdown,
640 };
641
642 #ifdef CONFIG_OF
643 static struct platform_device mt65xx_leds_device = {
644 .name = "leds-mt65xx",
645 .id = -1
646 };
647
648 #endif
649
650 static int __init mt65xx_leds_init(void)
651 {
652 int ret;
653
654 LEDS_DRV_DEBUG("[LED]%s\n", __func__);
655
656 #ifdef CONFIG_OF
657 ret = platform_device_register(&mt65xx_leds_device);
658 if (ret)
659 printk("[LED]mt65xx_leds_init:dev:E%d\n", ret);
660 #endif
661 ret = platform_driver_register(&mt65xx_leds_driver);
662
663 if (ret) {
664 LEDS_DRV_DEBUG("[LED]mt65xx_leds_init:drv:E%d\n", ret);
665 /* platform_device_unregister(&mt65xx_leds_device); */
666 return ret;
667 }
668
669 mt_leds_wake_lock_init();
670
671 return ret;
672 }
673
674 static void __exit mt65xx_leds_exit(void)
675 {
676 platform_driver_unregister(&mt65xx_leds_driver);
677 /* platform_device_unregister(&mt65xx_leds_device); */
678 }
679
680 module_param(debug_enable_led, int, 0644);
681
682 module_init(mt65xx_leds_init);
683 module_exit(mt65xx_leds_exit);
684
685 MODULE_AUTHOR("MediaTek Inc.");
686 MODULE_DESCRIPTION("LED driver for MediaTek MT65xx chip");
687 MODULE_LICENSE("GPL");
688 MODULE_ALIAS("leds-mt65xx");