2 * TI LP8788 MFD - keyled driver
4 * Copyright 2012 Texas Instruments
6 * Author: Milo(Woogyom) Kim <milo.kim@ti.com>
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License version 2 as
10 * published by the Free Software Foundation.
14 #include <linux/module.h>
15 #include <linux/slab.h>
16 #include <linux/err.h>
17 #include <linux/platform_device.h>
18 #include <linux/leds.h>
19 #include <linux/mutex.h>
20 #include <linux/mfd/lp8788.h>
21 #include <linux/mfd/lp8788-isink.h>
23 #define MAX_BRIGHTNESS LP8788_ISINK_MAX_PWM
24 #define DEFAULT_LED_NAME "keyboard-backlight"
29 struct led_classdev led_dev
;
30 enum lp8788_isink_number isink_num
;
34 struct lp8788_led_config
{
35 enum lp8788_isink_scale scale
;
36 enum lp8788_isink_number num
;
40 static struct lp8788_led_config default_led_config
= {
41 .scale
= LP8788_ISINK_SCALE_100mA
,
42 .num
= LP8788_ISINK_3
,
46 static int lp8788_led_init_device(struct lp8788_led
*led
,
47 struct lp8788_led_platform_data
*pdata
)
49 struct lp8788_led_config
*cfg
= &default_led_config
;
54 cfg
->scale
= pdata
->scale
;
55 cfg
->num
= pdata
->num
;
56 cfg
->iout
= pdata
->iout_code
;
59 led
->isink_num
= cfg
->num
;
61 /* scale configuration */
62 addr
= LP8788_ISINK_CTRL
;
63 mask
= 1 << (cfg
->num
+ LP8788_ISINK_SCALE_OFFSET
);
64 val
= cfg
->scale
<< (cfg
->num
+ LP8788_ISINK_SCALE_OFFSET
);
65 ret
= lp8788_update_bits(led
->lp
, addr
, mask
, val
);
69 /* current configuration */
70 addr
= lp8788_iout_addr
[cfg
->num
];
71 mask
= lp8788_iout_mask
[cfg
->num
];
74 return lp8788_update_bits(led
->lp
, addr
, mask
, val
);
77 static int lp8788_led_enable(struct lp8788_led
*led
,
78 enum lp8788_isink_number num
, int on
)
85 ret
= lp8788_update_bits(led
->lp
, LP8788_ISINK_CTRL
, mask
, val
);
92 static int lp8788_brightness_set(struct led_classdev
*led_cdev
,
93 enum led_brightness val
)
95 struct lp8788_led
*led
=
96 container_of(led_cdev
, struct lp8788_led
, led_dev
);
98 enum lp8788_isink_number num
= led
->isink_num
;
101 mutex_lock(&led
->lock
);
107 ret
= lp8788_write_byte(led
->lp
, lp8788_pwm_addr
[num
], val
);
112 mutex_unlock(&led
->lock
);
116 enable
= (val
> 0) ? 1 : 0;
117 if (enable
!= led
->on
)
118 ret
= lp8788_led_enable(led
, num
, enable
);
120 mutex_unlock(&led
->lock
);
124 static int lp8788_led_probe(struct platform_device
*pdev
)
126 struct lp8788
*lp
= dev_get_drvdata(pdev
->dev
.parent
);
127 struct lp8788_led_platform_data
*led_pdata
;
128 struct lp8788_led
*led
;
129 struct device
*dev
= &pdev
->dev
;
132 led
= devm_kzalloc(dev
, sizeof(struct lp8788_led
), GFP_KERNEL
);
137 led
->led_dev
.max_brightness
= MAX_BRIGHTNESS
;
138 led
->led_dev
.brightness_set_blocking
= lp8788_brightness_set
;
140 led_pdata
= lp
->pdata
? lp
->pdata
->led_pdata
: NULL
;
142 if (!led_pdata
|| !led_pdata
->name
)
143 led
->led_dev
.name
= DEFAULT_LED_NAME
;
145 led
->led_dev
.name
= led_pdata
->name
;
147 mutex_init(&led
->lock
);
149 platform_set_drvdata(pdev
, led
);
151 ret
= lp8788_led_init_device(led
, led_pdata
);
153 dev_err(dev
, "led init device err: %d\n", ret
);
157 ret
= led_classdev_register(dev
, &led
->led_dev
);
159 dev_err(dev
, "led register err: %d\n", ret
);
166 static int lp8788_led_remove(struct platform_device
*pdev
)
168 struct lp8788_led
*led
= platform_get_drvdata(pdev
);
170 led_classdev_unregister(&led
->led_dev
);
175 static struct platform_driver lp8788_led_driver
= {
176 .probe
= lp8788_led_probe
,
177 .remove
= lp8788_led_remove
,
179 .name
= LP8788_DEV_KEYLED
,
182 module_platform_driver(lp8788_led_driver
);
184 MODULE_DESCRIPTION("Texas Instruments LP8788 Keyboard LED Driver");
185 MODULE_AUTHOR("Milo Kim");
186 MODULE_LICENSE("GPL");
187 MODULE_ALIAS("platform:lp8788-keyled");