LP8758 - consolidated version
[mlp-open-source/kernel.git] / drivers / video / backlight / lm3632_bl.c
1 /*
2  * TI LM3632 Backlight Driver
3  *
4  * Copyright 2015 Texas Instruments
5  *
6  * Author: Milo Kim <milo.kim@ti.com>
7  *
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.
11  *
12  */
14 #include <linux/backlight.h>
15 #include <linux/delay.h>
16 #include <linux/err.h>
17 #include <linux/mfd/lm3632.h>
18 #include <linux/module.h>
19 #include <linux/of.h>
20 #include <linux/platform_device.h>
21 #include <linux/pwm.h>
22 #include <linux/slab.h>
24 #define LM3632_MAX_BRIGHTNESS           2047
26 #define DEFAULT_BL_NAME                 "lcd-backlight"
28 enum lm3632_bl_ctrl_mode {
29         LMU_BL_I2C,
30         LMU_BL_PWM,
31 };
33 struct lm3632_bl {
34         struct device *dev;
35         struct backlight_device *bl_dev;
37         struct lm3632 *lm3632;
38         struct lm3632_backlight_platform_data *pdata;
39         enum lm3632_bl_ctrl_mode mode;
41         struct pwm_device *pwm;
42 };
44 static int lm3632_bl_string_configure(struct lm3632_bl *lm3632_bl, int enable)
45 {
46         u8 val;
48         if (enable) {
49                 if (lm3632_bl->pdata->is_full_strings)
50                         val = LM3632_BL_TWO_STRINGS;
51                 else
52                         val = LM3632_BL_ONE_STRING;
53         } else {
54                 val = 0;
55         }
57         return lm3632_update_bits(lm3632_bl->lm3632, LM3632_REG_ENABLE,
58                                   LM3632_BL_STRING_MASK, val);
59 }
61 static int lm3632_bl_enable(struct lm3632_bl *lm3632_bl, int enable)
62 {
63         int ret;
65         ret = lm3632_bl_string_configure(lm3632_bl, enable);
66         if (ret) {
67                 dev_err(lm3632_bl->dev,
68                         "Backlight string config error: %d\n", ret);
69                 return ret;
70         }
72         return lm3632_update_bits(lm3632_bl->lm3632, LM3632_REG_ENABLE,
73                         LM3632_BL_EN_MASK, enable << LM3632_BL_EN_SHIFT);
74 }
76 static void lm3632_bl_pwm_ctrl(struct lm3632_bl *lm3632_bl, int br, int max_br)
77 {
78         unsigned int period;
79         unsigned int duty;
80         struct pwm_device *pwm;
82         if (!lm3632_bl->pdata)
83                 return;
85         period = lm3632_bl->pdata->pwm_period;
86         duty = br * period / max_br;
88         /* Request a PWM device with the consumer name */
89         if (!lm3632_bl->pwm) {
90                 pwm = devm_pwm_get(lm3632_bl->dev, "lm3632-backlight");
91                 if (IS_ERR(pwm)) {
92                         dev_err(lm3632_bl->dev, "can not get PWM device\n");
93                         return;
94                 }
95                 lm3632_bl->pwm = pwm;
96         }
98         pwm_config(lm3632_bl->pwm, duty, period);
99         if (duty)
100                 pwm_enable(lm3632_bl->pwm);
101         else
102                 pwm_disable(lm3632_bl->pwm);
105 static int lm3632_bl_set_brightness(struct lm3632_bl *lm3632_bl, int val)
107         u8 data;
108         int ret;
111         data = val & LM3632_BRT_LSB_MASK;
112         ret = lm3632_update_bits(lm3632_bl->lm3632, LM3632_REG_BRT_LSB,
113                                  LM3632_BRT_LSB_MASK, data);
114         if (ret)
115                 return ret;
117         data = (val >> LM3632_BRT_MSB_SHIFT) & 0xFF;
119         return lm3632_write_byte(lm3632_bl->lm3632, LM3632_REG_BRT_MSB,
120                                  data);
123 static int lm3632_bl_update_status(struct backlight_device *bl_dev)
125         struct lm3632_bl *lm3632_bl = bl_get_data(bl_dev);
126         int brt;
127         int ret;
129         if (bl_dev->props.state & BL_CORE_SUSPENDED)
130                 bl_dev->props.brightness = 0;
132         brt = bl_dev->props.brightness;
134         if (brt > 0)
135                 ret = lm3632_bl_enable(lm3632_bl, 1);
136         else
137                 ret = lm3632_bl_enable(lm3632_bl, 0);
139         if (ret)
140                 return ret;
142         if (lm3632_bl->mode == LMU_BL_PWM)
143                 lm3632_bl_pwm_ctrl(lm3632_bl, brt,
144                                    bl_dev->props.max_brightness);
145         else
146                 ret = lm3632_bl_set_brightness(lm3632_bl, brt);
148         return ret;
151 static int lm3632_bl_get_brightness(struct backlight_device *bl_dev)
153         return bl_dev->props.brightness;
156 static const struct backlight_ops lm3632_bl_ops = {
157         .options = BL_CORE_SUSPENDRESUME,
158         .update_status = lm3632_bl_update_status,
159         .get_brightness = lm3632_bl_get_brightness,
160 };
162 static int lm3632_bl_register(struct lm3632_bl *lm3632_bl)
164         struct backlight_device *bl_dev;
165         struct backlight_properties props;
166         struct lm3632_backlight_platform_data *pdata = lm3632_bl->pdata;
167         char name[20];
169         props.type = BACKLIGHT_PLATFORM;
170         props.brightness = 0;
171         props.max_brightness = LM3632_MAX_BRIGHTNESS;
173         if (!pdata || !pdata->name)
174                 snprintf(name, sizeof(name), "%s", DEFAULT_BL_NAME);
175         else
176                 snprintf(name, sizeof(name), "%s", pdata->name);
178         bl_dev = backlight_device_register(name, lm3632_bl->dev, lm3632_bl,
179                                            &lm3632_bl_ops, &props);
180         if (IS_ERR(bl_dev))
181                 return PTR_ERR(bl_dev);
183         lm3632_bl->bl_dev = bl_dev;
185         return 0;
188 static void lm3632_bl_unregister(struct lm3632_bl *lm3632_bl)
190         if (lm3632_bl->bl_dev)
191                 backlight_device_unregister(lm3632_bl->bl_dev);
194 static int lm3632_bl_set_ovp(struct lm3632_bl *lm3632_bl)
196         return lm3632_update_bits(lm3632_bl->lm3632, LM3632_REG_CONFIG1,
197                                   LM3632_OVP_MASK, LM3632_OVP_25V);
200 static int lm3632_bl_set_swfreq(struct lm3632_bl *lm3632_bl)
202         return lm3632_update_bits(lm3632_bl->lm3632, LM3632_REG_CONFIG2,
203                                   LM3632_SWFREQ_MASK, LM3632_SWFREQ_1MHZ);
206 static int lm3632_bl_set_ctrl_mode(struct lm3632_bl *lm3632_bl)
208         struct lm3632_backlight_platform_data *pdata = lm3632_bl->pdata;
210         if (pdata->pwm_period > 0)
211                 lm3632_bl->mode = LMU_BL_PWM;
212         else
213                 lm3632_bl->mode = LMU_BL_I2C;
215         return lm3632_update_bits(lm3632_bl->lm3632, LM3632_REG_IO_CTRL,
216                                   LM3632_PWM_MASK,
217                                   lm3632_bl->mode << LM3632_PWM_SHIFT);
220 static int lm3632_bl_configure(struct lm3632_bl *lm3632_bl)
222         int ret;
224         /* Select OVP level */
225         ret = lm3632_bl_set_ovp(lm3632_bl);
226         if (ret)
227                 return ret;
229         /* Select switch frequency */
230         ret = lm3632_bl_set_swfreq(lm3632_bl);
231         if (ret)
232                 return ret;
234         /* Backlight control mode - PWM or I2C */
235         return lm3632_bl_set_ctrl_mode(lm3632_bl);
238 static int lm3632_bl_parse_dt(struct device *dev, struct lm3632_bl *lm3632_bl)
240         struct device_node *node = dev->of_node;
241         struct lm3632_backlight_platform_data *pdata;
242         int brightness = 0;
243         int ret;
245         pdata = devm_kzalloc(dev, sizeof(*pdata), GFP_KERNEL);
246         if (!pdata)
247                 return -ENOMEM;
249         /* Channel name */
250         of_property_read_string(node, "bl-name", &pdata->name);
252         /* String configuration */
253         if (of_find_property(node, "full-strings-used", NULL))
254                 pdata->is_full_strings = true;
256         /* PWM mode */
257         of_property_read_u32(node, "pwm-period", &pdata->pwm_period);
258         of_property_read_u32(node, "pwm-max-brightness", &brightness);
260         if (pdata->pwm_period > 0) {
261                 if (brightness == 0) {
262                         dev_err(lm3632_bl->dev,
263                         "PWM max brightness should be greater than 0\n");
264                         return -EINVAL;
265                 }
267                 ret = lm3632_bl_set_brightness(lm3632_bl, brightness);
268                 if (ret) {
269                         dev_err(lm3632_bl->dev,
270                                 "PWM max brightness set error: %d\n", ret);
271                         return ret;
272                 }
273         }
275         lm3632_bl->pdata = pdata;
277         return 0;
280 static int lm3632_bl_probe(struct platform_device *pdev)
282         struct lm3632 *lm3632 = dev_get_drvdata(pdev->dev.parent);
283         struct lm3632_backlight_platform_data *pdata = lm3632->pdata->bl_pdata;
284         struct lm3632_bl *lm3632_bl;
285         int ret;
287         lm3632_bl = devm_kzalloc(&pdev->dev, sizeof(*lm3632_bl), GFP_KERNEL);
288         if (!lm3632_bl)
289                 return -ENOMEM;
291         lm3632_bl->dev = &pdev->dev;
292         lm3632_bl->lm3632 = lm3632;
293         lm3632_bl->pdata = pdata;
295         if (!lm3632_bl->pdata) {
296                 if (IS_ENABLED(CONFIG_OF))
297                         ret = lm3632_bl_parse_dt(&pdev->dev, lm3632_bl);
298                 else
299                         return -ENODEV;
301                 if (ret)
302                         return ret;
303         }
305         platform_set_drvdata(pdev, lm3632_bl);
307         /* Backlight configuration */
308         ret = lm3632_bl_configure(lm3632_bl);
309         if (ret) {
310                 dev_err(&pdev->dev, "backlight config err: %d\n", ret);
311                 return ret;
312         }
314         /* Register backlight subsystem */
315         ret = lm3632_bl_register(lm3632_bl);
316         if (ret) {
317                 dev_err(&pdev->dev, "register backlight err: %d\n", ret);
318                 return ret;
319         }
321         backlight_update_status(lm3632_bl->bl_dev);
323         return 0;
326 static int lm3632_bl_remove(struct platform_device *pdev)
328         struct lm3632_bl *lm3632_bl = platform_get_drvdata(pdev);
329         struct backlight_device *bl_dev = lm3632_bl->bl_dev;
331         bl_dev->props.brightness = 0;
332         backlight_update_status(bl_dev);
333         lm3632_bl_unregister(lm3632_bl);
335         return 0;
338 #ifdef CONFIG_OF
339 static const struct of_device_id lm3632_bl_of_match[] = {
340         { .compatible = "ti,lm3632-backlight", },
341         { }
342 };
343 MODULE_DEVICE_TABLE(of, lm3632_bl_of_match);
344 #endif
346 static struct platform_driver lm3632_bl_driver = {
347         .probe = lm3632_bl_probe,
348         .remove = lm3632_bl_remove,
349         .driver = {
350                 .name = "lm3632-backlight",
351                 .owner = THIS_MODULE,
352                 .of_match_table = of_match_ptr(lm3632_bl_of_match),
353         },
354 };
355 module_platform_driver(lm3632_bl_driver);
357 MODULE_DESCRIPTION("TI LM3632 Backlight Driver");
358 MODULE_AUTHOR("Milo Kim");
359 MODULE_LICENSE("GPL");
360 MODULE_ALIAS("platform:lm3632-backlight");