]> Gitweb @ Texas Instruments - Open Source Git Repositories - git.TI.com/gitweb - mlp-open-source/kernel.git/blob - drivers/video/backlight/lm3585_bl.c
Add LM3585 Device driver -v0 based on LK3.8
[mlp-open-source/kernel.git] / drivers / video / backlight / lm3585_bl.c
1 /*
2  * Simple driver for Texas Instruments lm3585 Backlight driver chip
3  *
4  * Copyright (C) 2014 Texas Instruments
5  * Author: Daniel Jeong  <gshark.jeong@gmail.com>
6  *                Ldd Mlp <ldd-mlp@list.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  */
13 #include <linux/backlight.h>
14 #include <linux/delay.h>
15 #include <linux/err.h>
16 #include <linux/i2c.h>
17 #include <linux/module.h>
18 #include <linux/platform_data/lm3585_bl.h>
19 #include <linux/regmap.h>
20 #include <linux/slab.h>
21 #include <linux/uaccess.h>
23 #define REG_CTRL                                0x00
24 #define REG_ENABLE                              0x01
25 #define REG_LED_EN_LO                   0x02
26 #define REG_LED_EN_HI                   0x03
27 #define REG_FAULT                               0x04
28 #define REG_BBOOST_MODE                 0x06
29 #define REG_BBOOST_OUTV                 0x07
30 #define REG_BBOOST_CTRL                 0x08
31 #define REG_BOOSTV                              0x0a
32 #define REG_RAMP_DURATION               0x0f
33 #define REG_RAMP_TAR_LO                 0x10
34 #define REG_RAMP_TAR_HI                 0x11
35 #define REG_RAMP_TAR_CTRL               0x12
36 #define REG_READ_RAMP_LO                0x14
37 #define REG_READ_RAMP_HI                0x15
38 #define REG_READ_CABC_PWM_LO    0x16
39 #define REG_READ_CABC_PWM_HI    0x17
40 #define REG_READ_LED_DC_LO              0x18
41 #define REG_READ_LED_DC_HI              0x19
42 #define REG_REVISION                    0x1f
43 #define REG_BBOOST_TRIM                 0x25
44 #define REG_MAX 0xff
46 #define LM3585_ENABLED 1
47 #define LM3585_DISABLED 0
49 struct lm3585_chip {
50         struct device *dev;
51         struct lm3585_platform_data *pdata;
52         struct backlight_device *bled;
53         struct regmap *regmap;
54         int is_enabled;
55 };
57 static int lm3585_startup(struct lm3585_chip *pchip)
58 {
59         unsigned int rev1, rev2;
60         int ret;
62         /* POR wait */
63         msleep(1);
64         /* sw reset */
65         ret = regmap_write(pchip->regmap, REG_CTRL, 0x01);
66         msleep(1);
67         /* LED enable */
68         ret |= regmap_write(pchip->regmap,
69                             REG_LED_EN_LO, pchip->pdata->led_enable);
70         ret |= regmap_update_bits(pchip->regmap,
71                                   REG_LED_EN_HI, 0x03,
72                                   pchip->pdata->led_enable >> 8);
74         /* Vpos 5.1V */
75         ret |= regmap_write(pchip->regmap, REG_BOOSTV, 0x07);
77         /*
78          * revision info and set buck/boost current limit
79          * A0 - 0x00
80          * A1 - 0x01
81          * B0 - 0x04 & R25[1:0] : 11b
82          * B1 - 0x04 & R25[1:0] : 10b
83          * B2 - 0x05
84          */
85         ret |= regmap_read(pchip->regmap, REG_REVISION, &rev1);
86         switch (rev1) {
87         case 0x00:
88         case 0x01:
89                 ret |= regmap_write(pchip->regmap, REG_BBOOST_CTRL, 0x4A);
90                 break;
91         case 0x04:
92                 ret |= regmap_read(pchip->regmap, REG_BBOOST_TRIM, &rev2);
93                 switch (rev2 & 0x03) {
94                 case 0x2:
95                         ret |=
96                             regmap_write(pchip->regmap, REG_BBOOST_CTRL, 0x4A);
97                         break;
98                 case 0x3:
99                         ret |=
100                             regmap_write(pchip->regmap, REG_BBOOST_CTRL, 0x0A);
101                         break;
102                 }
103                 break;
104         case 0x05:
105                 ret |= regmap_write(pchip->regmap, REG_BBOOST_CTRL, 0x0A);
106                 break;
107         }
108         /* enable buck boost & wait soft start time */
109         ret |= regmap_write(pchip->regmap, REG_ENABLE, 0x01);
110         msleep(10);
111         /* enable charge pump discharge */
112         ret |= regmap_write(pchip->regmap, REG_ENABLE, 0x09);
113         msleep(100);
114         /* enable boost converter */
115         ret |= regmap_write(pchip->regmap, REG_ENABLE, 0x0b);
116         msleep(1);
117         /* enable charge pump Vneg */
118         ret |= regmap_write(pchip->regmap, REG_ENABLE, 0x0f);
119         /* enable global led */
120         ret |= regmap_write(pchip->regmap, REG_ENABLE, 0x2f);
121         /* enable cabc pwm input control */
122         if (pchip->pdata->cabc_input != 0)
123                 ret |= regmap_write(pchip->regmap, REG_ENABLE, 0x3f);
125         /* set LED current to 0 initially */
126         ret |= regmap_write(pchip->regmap, REG_RAMP_TAR_LO, 0x00);
127         ret |= regmap_update_bits(pchip->regmap, REG_RAMP_TAR_HI,
128                                   0xcf, (pchip->pdata->ctype << 6) | 0x00);
129         /* ramp duration */
130         ret |= regmap_write(pchip->regmap,
131                             REG_RAMP_DURATION, pchip->pdata->ramp_time);
132         /* adgo */
133         ret |= regmap_write(pchip->regmap, REG_RAMP_TAR_CTRL, 0x01);
135         if (ret == 0)
136                 pchip->is_enabled = LM3585_ENABLED;
137         return ret;
140 static ssize_t lm3585_reset_store(struct device *dev,
141                                   struct device_attribute *attr,
142                                   const char *buf, size_t size)
144         struct lm3585_chip *pchip = dev_get_drvdata(dev);
145         u8 input;
146         int ret;
148         if (kstrtou8(buf, 0, &input))
149                 return -EINVAL;
151         if (input == 1) {
152                 ret = lm3585_startup(pchip);
153                 if (ret < 0)
154                         return ret;
155         }
156         return size;
159 static ssize_t lm3585_fault_show(struct device *dev,
160                                  struct device_attribute *attr, char *buf)
162         struct lm3585_chip *pchip = dev_get_drvdata(dev);
163         unsigned int fault;
164         int ret;
166         ret = regmap_read(pchip->regmap, REG_FAULT, &fault);
167         if (ret < 0) {
168                 dev_err(pchip->dev, "fail : i2c access to register.\n");
169                 return sprintf(buf, "%d\n", ret);
170         }
172         if (fault & 0x1)
173                 dev_err(pchip->dev, "LM3585 Temperature Fault.\n");
174         if (fault & 0x2)
175                 dev_err(pchip->dev, "LM3585 Boost Over Voltage Fault.\n");
176         if (fault & 0x4)
177                 dev_err(pchip->dev, "LM3585 LED Short Fault.\n");
178         if (fault & 0x8)
179                 dev_err(pchip->dev, "LM3585 LED Open Fault.\n");
181         return sprintf(buf, "%d\n", fault);
184 static ssize_t lm3585_enable_show(struct device *dev,
185                                   struct device_attribute *attr, char *buf)
187         struct lm3585_chip *pchip = dev_get_drvdata(dev);
189         return sprintf(buf, "%d\n", pchip->is_enabled);
192 static ssize_t lm3585_enable_store(struct device *dev,
193                                    struct device_attribute *attr,
194                                    const char *buf, size_t size)
196         struct lm3585_chip *pchip = dev_get_drvdata(dev);
197         u8 input;
198         int ret;
200         if (kstrtou8(buf, 0, &input))
201                 return -EINVAL;
203         if (input == LM3585_DISABLED) {
204                 /* turn off backlight */
205                 ret = regmap_write(pchip->regmap, REG_ENABLE, 0x0f);
206                 /* turn off charge pump */
207                 ret |= regmap_write(pchip->regmap, REG_ENABLE, 0x0b);
208                 /* turn off boost */
209                 ret |= regmap_write(pchip->regmap, REG_ENABLE, 0x09);
210                 msleep(100);
211                 /* turn off charge pump discharge */
212                 ret |= regmap_write(pchip->regmap, REG_ENABLE, 0x01);
213                 /* turn off buck boost */
214                 ret |= regmap_write(pchip->regmap, REG_ENABLE, 0x00);
215         } else {
216                 /* turn on Vout */
217                 ret = regmap_write(pchip->regmap, REG_ENABLE, 0x01);
218                 /* turn on the Vpos */
219                 ret |= regmap_write(pchip->regmap, REG_ENABLE, 0x03);
220                 /* enable charger pump */
221                 ret |= regmap_write(pchip->regmap, REG_ENABLE, 0x0F);
222                 /* turn on backlight */
223                 ret |= regmap_write(pchip->regmap, REG_ENABLE, 0x2F);
224                 /* enable cabc pwm control */
225                 if (pchip->pdata->cabc_input != 0)
226                         ret |= regmap_write(pchip->regmap, REG_ENABLE, 0x3F);
227         }
228         if (ret < 0)
229                 return ret;
230         pchip->is_enabled = input;
232         return size;
235 #define LM3585_DVNODE_MAX 3
236 #define lm3585_attr(_name, _show, _store)\
237 {\
238         .attr = {\
239                 .name = _name,\
240                 .mode = S_IWUSR | S_IRUSR,\
241         },\
242         .show = _show,\
243         .store = _store,\
246 static struct device_attribute lm3585_dev_attr[] = {
247         lm3585_attr("fault", lm3585_fault_show, NULL),
248         lm3585_attr("enable", lm3585_enable_show, lm3585_enable_store),
249         lm3585_attr("reset", NULL, lm3585_reset_store),
250 };
252 /* brightness control */
253 static int lm3585_update_status(struct backlight_device *bl)
255         int ret = -EINVAL;
256         struct lm3585_chip *pchip = bl_get_data(bl);
258         if (bl->props.state & (BL_CORE_SUSPENDED | BL_CORE_FBBLANK))
259                 bl->props.brightness = 0;
261         /* adstop */
262         ret = regmap_write(pchip->regmap, REG_RAMP_TAR_CTRL, 0x02);
263         /* set target iled low */
264         ret |= regmap_write(pchip->regmap,
265                             REG_RAMP_TAR_LO, bl->props.brightness & 0xff);
266         /* set target iled high */
267         ret |= regmap_update_bits(pchip->regmap,
268                                   REG_RAMP_TAR_HI, 0x0f,
269                                   bl->props.brightness >> 8);
270         /* ramp duration */
271         ret |= regmap_write(pchip->regmap,
272                             REG_RAMP_DURATION, pchip->pdata->ramp_time);
273         /* adgo */
274         ret |= regmap_write(pchip->regmap, REG_RAMP_TAR_CTRL, 0x01);
276         if (ret < 0)
277                 dev_err(pchip->dev, "fail : i2c access to register.\n");
278         else
279                 ret = bl->props.brightness;
281         return ret;
284 static int lm3585_get_brightness(struct backlight_device *bl)
286         return bl->props.brightness;
289 static const struct backlight_ops lm3585_bled_ops = {
290         .options = BL_CORE_SUSPENDRESUME,
291         .update_status = lm3585_update_status,
292         .get_brightness = lm3585_get_brightness,
293 };
295 static const struct regmap_config lm3585_regmap = {
296         .reg_bits = 8,
297         .val_bits = 8,
298         .max_register = REG_MAX,
299 };
301 #ifdef CONFIG_OF
302 static struct lm3585_platform_data *lm3585_parse_dt(struct i2c_client *client)
304         struct device_node *node = client->dev.of_node;
305         struct lm3585_platform_data *pdata = NULL;
306         u32 rdata;
308         if (!node) {
309                 dev_err(&client->dev, "can't find data in device tree\n");
310                 return pdata;
311         }
313         pdata = devm_kzalloc(&client->dev,
314                              sizeof(struct lm3585_platform_data), GFP_KERNEL);
315         if (pdata == NULL)
316                 return pdata;
318         of_property_read_u32(node, "led_enable", &rdata);
319         pdata->led_enable = (enum lm3585_leds_enable)rdata;
320         of_property_read_u32(node, "ctype", &rdata);
321         pdata->ctype = (enum lm3585_curve_type)rdata;
322         of_property_read_u32(node, "cabc_input", &rdata);
323         pdata->cabc_input = (enum lm3585_cabc_input)rdata;
324         of_property_read_u32(node, "ramp_time", &rdata);
325         pdata->ramp_time = rdata;
327         return pdata;
330 static const struct of_device_id of_lm3585_bl_match[] = {
331         {.compatible = "ti,lm3585",},
332         {},
333 };
335 #else
336 static struct lm3585_platform_data *lm3585_parse_dt(struct i2c_client *client)
338         return NULL;
340 #endif
342 static int lm3585_probe(struct i2c_client *client,
343                         const struct i2c_device_id *id)
345         struct lm3585_chip *pchip;
346         struct lm3585_platform_data *pdata = dev_get_platdata(&client->dev);
347         struct backlight_properties props;
348         int ret, icnt;
350         if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) {
351                 dev_err(&client->dev, "fail : i2c functionality check.\n");
352                 return -EOPNOTSUPP;
353         }
355         pchip = devm_kzalloc(&client->dev,
356                              sizeof(struct lm3585_chip), GFP_KERNEL);
357         if (!pchip)
358                 return -ENOMEM;
359         pchip->dev = &client->dev;
361         pchip->regmap = devm_regmap_init_i2c(client, &lm3585_regmap);
362         if (IS_ERR(pchip->regmap)) {
363                 ret = PTR_ERR(pchip->regmap);
364                 dev_err(pchip->dev, "fail : allocate i2c register map.\n");
365                 return ret;
366         }
368         if (pdata == NULL) {
369                 pdata = lm3585_parse_dt(client);
370                 if (pdata == NULL) {
371                         pdata = devm_kzalloc(pchip->dev,
372                                              sizeof(struct
373                                                     lm3585_platform_data),
374                                              GFP_KERNEL);
375                         if (pdata == NULL) {
376                                 dev_err(pchip->dev, "fail to get memory\n");
377                                 return -ENOMEM;
378                         }
379                         pdata->ramp_time = 0;
380                         pdata->ctype = LM3585_CURVE_LINEAR;
381                         pdata->led_enable = LM3585_LED_ALL_ON;
382                         pdata->cabc_input = LM3585_CABC_INPUT_DISABLE;
383                 }
384         }
385         pchip->pdata = pdata;
387         i2c_set_clientdata(client, pchip);
389         ret = lm3585_startup(pchip);
390         if (ret < 0) {
391                 dev_err(pchip->dev, "fail : start up.\n");
392                 return ret;
393         }
395         props.brightness = 0;
396         props.type = BACKLIGHT_RAW;
397         props.max_brightness = LM3585_BR_MAX;
398         pchip->bled = devm_backlight_device_register(pchip->dev,
399                                                      LM3585_NAME, pchip->dev,
400                                                      pchip, &lm3585_bled_ops,
401                                                      &props);
402         if (IS_ERR(pchip->bled)) {
403                 dev_err(pchip->dev, "fail : backlight register.\n");
404                 ret = PTR_ERR(pchip->bled);
405                 return ret;
406         }
408         for (icnt = 0; icnt < LM3585_DVNODE_MAX; icnt++) {
409                 ret =
410                     device_create_file(&(pchip->bled->dev),
411                                        &lm3585_dev_attr[icnt]);
412                 if (ret < 0) {
413                         dev_err(pchip->dev, "fail : node create\n");
414                         goto err_dn_out;
415                 }
416         }
418         dev_info(pchip->dev, "LM3585 backlight Initialized.\n");
419         return 0;
421 err_dn_out:
422         while (--icnt >= 0)
423                 device_remove_file(&(pchip->bled->dev), &lm3585_dev_attr[icnt]);
425         return ret;
428 static int lm3585_remove(struct i2c_client *client)
430         struct lm3585_chip *pchip = i2c_get_clientdata(client);
431         int icnt;
433         for (icnt = 0; icnt < LM3585_DVNODE_MAX; icnt++)
434                 device_remove_file(&(pchip->bled->dev), &lm3585_dev_attr[icnt]);
435         return 0;
438 static const struct i2c_device_id lm3585_id[] = {
439         {LM3585_NAME, 0},
440         {}
441 };
443 MODULE_DEVICE_TABLE(i2c, lm3585_id);
444 static struct i2c_driver lm3585_i2c_driver = {
445         .driver = {
446                    .name = LM3585_NAME,
447                    },
448         .probe = lm3585_probe,
449         .remove = lm3585_remove,
450         .id_table = lm3585_id,
451 };
453 module_i2c_driver(lm3585_i2c_driver);
455 MODULE_DESCRIPTION("Texas Instruments LM3585 Backlight Driver");
456 MODULE_AUTHOR("Daniel Jeong <gshark.jeong@gmail.com>");
457 MODULE_AUTHOR("Ldd Mlp <ldd-mlp@list.ti.com>");
458 MODULE_LICENSE("GPL v2");