1 // SPDX-License-Identifier: GPL-2.0-only
3 * TI LP8788 MFD - keyled driver
5 * Copyright 2012 Texas Instruments
7 * Author: Milo(Woogyom) Kim <milo.kim@ti.com>
10 #include <linux/module.h>
11 #include <linux/slab.h>
12 #include <linux/err.h>
13 #include <linux/platform_device.h>
14 #include <linux/leds.h>
15 #include <linux/mutex.h>
16 #include <linux/mfd/lp8788.h>
17 #include <linux/mfd/lp8788-isink.h>
19 #define MAX_BRIGHTNESS LP8788_ISINK_MAX_PWM
20 #define DEFAULT_LED_NAME "keyboard-backlight"
25 struct led_classdev led_dev
;
26 enum lp8788_isink_number isink_num
;
30 struct lp8788_led_config
{
31 enum lp8788_isink_scale scale
;
32 enum lp8788_isink_number num
;
36 static struct lp8788_led_config default_led_config
= {
37 .scale
= LP8788_ISINK_SCALE_100mA
,
38 .num
= LP8788_ISINK_3
,
42 static int lp8788_led_init_device(struct lp8788_led
*led
,
43 struct lp8788_led_platform_data
*pdata
)
45 struct lp8788_led_config
*cfg
= &default_led_config
;
50 cfg
->scale
= pdata
->scale
;
51 cfg
->num
= pdata
->num
;
52 cfg
->iout
= pdata
->iout_code
;
55 led
->isink_num
= cfg
->num
;
57 /* scale configuration */
58 addr
= LP8788_ISINK_CTRL
;
59 mask
= 1 << (cfg
->num
+ LP8788_ISINK_SCALE_OFFSET
);
60 val
= cfg
->scale
<< (cfg
->num
+ LP8788_ISINK_SCALE_OFFSET
);
61 ret
= lp8788_update_bits(led
->lp
, addr
, mask
, val
);
65 /* current configuration */
66 addr
= lp8788_iout_addr
[cfg
->num
];
67 mask
= lp8788_iout_mask
[cfg
->num
];
70 return lp8788_update_bits(led
->lp
, addr
, mask
, val
);
73 static int lp8788_led_enable(struct lp8788_led
*led
,
74 enum lp8788_isink_number num
, int on
)
81 ret
= lp8788_update_bits(led
->lp
, LP8788_ISINK_CTRL
, mask
, val
);
88 static int lp8788_brightness_set(struct led_classdev
*led_cdev
,
89 enum led_brightness val
)
91 struct lp8788_led
*led
=
92 container_of(led_cdev
, struct lp8788_led
, led_dev
);
94 enum lp8788_isink_number num
= led
->isink_num
;
97 mutex_lock(&led
->lock
);
103 ret
= lp8788_write_byte(led
->lp
, lp8788_pwm_addr
[num
], val
);
108 mutex_unlock(&led
->lock
);
112 enable
= (val
> 0) ? 1 : 0;
113 if (enable
!= led
->on
)
114 ret
= lp8788_led_enable(led
, num
, enable
);
116 mutex_unlock(&led
->lock
);
120 static int lp8788_led_probe(struct platform_device
*pdev
)
122 struct lp8788
*lp
= dev_get_drvdata(pdev
->dev
.parent
);
123 struct lp8788_led_platform_data
*led_pdata
;
124 struct lp8788_led
*led
;
125 struct device
*dev
= &pdev
->dev
;
128 led
= devm_kzalloc(dev
, sizeof(struct lp8788_led
), GFP_KERNEL
);
133 led
->led_dev
.max_brightness
= MAX_BRIGHTNESS
;
134 led
->led_dev
.brightness_set_blocking
= lp8788_brightness_set
;
136 led_pdata
= lp
->pdata
? lp
->pdata
->led_pdata
: NULL
;
138 if (!led_pdata
|| !led_pdata
->name
)
139 led
->led_dev
.name
= DEFAULT_LED_NAME
;
141 led
->led_dev
.name
= led_pdata
->name
;
143 mutex_init(&led
->lock
);
145 ret
= lp8788_led_init_device(led
, led_pdata
);
147 dev_err(dev
, "led init device err: %d\n", ret
);
151 ret
= devm_led_classdev_register(dev
, &led
->led_dev
);
153 dev_err(dev
, "led register err: %d\n", ret
);
160 static struct platform_driver lp8788_led_driver
= {
161 .probe
= lp8788_led_probe
,
163 .name
= LP8788_DEV_KEYLED
,
166 module_platform_driver(lp8788_led_driver
);
168 MODULE_DESCRIPTION("Texas Instruments LP8788 Keyboard LED Driver");
169 MODULE_AUTHOR("Milo Kim");
170 MODULE_LICENSE("GPL");
171 MODULE_ALIAS("platform:lp8788-keyled");