backlight : add new backlight driver LM36923
[mlp-open-source/kernel.git] / drivers / video / backlight / lm36923_bl.c
1 /*
2  * Simple driver for multi-string single control backlight driver chips of
3  * Texas Instruments.
4  *
5  * Copyright (C) 2015 Texas Instruments
6  * Author: Daniel Jeong  <gshark.jeong@gmail.com>
7  *         Ldd Mlp <ldd-mlp@list.ti.com>
8  *
9  * This program is free software; you can redistribute it and/or modify
10  * it under the terms of the GNU General Public License version 2 as
11  * published by the Free Software Foundation.
12  *
13  */
14 #include <linux/backlight.h>
15 #include <linux/delay.h>
16 #include <linux/err.h>
17 #include <linux/i2c.h>
18 #include <linux/module.h>
19 #include <linux/platform_data/ti-scbl.h>
20 #include <linux/regmap.h>
21 #include <linux/slab.h>
22 #include <linux/uaccess.h>
24 #define scbl_attr(_name, _show, _store)\
25 {\
26         .attr = {\
27                 .name = _name,\
28                 .mode = S_IWUSR | S_IRUSR,\
29         },\
30         .show = _show,\
31         .store = _store,\
32 }
34 struct scbl_reg_ctrl {
35         unsigned int reg;
36         unsigned int mask;
37         unsigned int shift;
38 };
40 /*
41  *brightness control 
42  *@min : minimum brightness
43  *@max : maximum brightness
44  *@msb_shift : msb bit shfit
45  *@lsb_mask  : lsb bit mask
46  *@msb : register for the upper 8bits of the brightness code
47  *@lsb : register for the lower 8bits of the brightness code
48  */
49 struct scbl_brt_ctrl {
50         unsigned int min;
51         unsigned int max;
52         unsigned int msb_shift;
53         unsigned int lsb_mask;
54         struct scbl_reg_ctrl msb;
55         struct scbl_reg_ctrl lsb;
56 };
58 /*
59  *fault data
60  *@reg : fault register
61  *@mask: mask bit of fault
62  *@bl_fault : backlight fault mapped the bit
63  */
64 struct scbl_fault {
65         unsigned int reg;
66         unsigned int mask;
67         unsigned int bl_fault;
68 };
70 /*
71  *single control backlight data
72  *@name    : chip name
73  *@num_led : number of led string
74  *@en_chip : chip enable register
75  *@en_led  : led string enable register
76  *@brt     : brightness register
77  *@fault   : fault register
78  *@boot    : function that should be called before chip enable
79  *@init    : function that should be called after chip enable
80  *@reset   : reset function
81  *@num_devnode   : number of device node to be created
82  *@scbl_dev_attr : device node attribute
83  */
84 struct scbl_data {
85         char *name;
87         int num_led;
88         struct scbl_reg_ctrl en_chip;
89         struct scbl_reg_ctrl en_led[SCBL_LED_MAX];
91         struct scbl_brt_ctrl brt;
92         struct scbl_fault fault[SCBL_FAULT_MAX];
94         int (*boot)(struct regmap* regmap);
95         int (*init)(struct regmap* regmap);
96         int (*reset)(struct regmap* regmap);
97         
98         int num_devnode;
99         struct device_attribute *scbl_dev_attr;
100 };
102 /*
103  *chip data
104  *@dev   : device
105  *@regmap: register map
106  *@bled  : backlight device
107  *@data  : single control backlight data
108  */
109 struct scbl_chip {
110         struct device *dev;
111         struct regmap *regmap;
113         struct backlight_device *bled;
114         const struct scbl_data *data; 
115 };
117 /* chip reset */
118 static ssize_t scbl_reset_store(struct device *dev,
119                                   struct device_attribute *attr,
120                                   const char *buf, size_t size)
122         struct scbl_chip *pchip = dev_get_drvdata(dev);
123         const struct scbl_data *data = pchip->data; 
124         u8 input;
125         int ret;
127         if (kstrtou8(buf, 0, &input))
128                 return -EINVAL;
130         if (input == 1) {
131                 ret = data->reset(pchip->regmap);
132                 if (ret<0)
133                         return ret;
134         }
135         return size;
138 /* fault status */
139 static ssize_t scbl_fault_show(struct device *dev,
140                                  struct device_attribute *attr, char *buf)
142         struct scbl_chip *pchip = dev_get_drvdata(dev);
143         const struct scbl_data *data = pchip->data; 
144         unsigned int reg_val, reg = 0xfff;
145         s32 fault = 0x0000;
146         int ret, icnt;
148         for(icnt = 0; icnt < SCBL_FAULT_MAX; icnt++) {
149                 if(data->fault[icnt].mask == 0x00)
150                         continue;
151                 if(data->fault[icnt].reg != reg) {
152                         reg = data->fault[icnt].reg;
153                         ret = regmap_read(pchip->regmap, reg, &reg_val);
154                         if (ret < 0) {
155                                 dev_err(pchip->dev, 
156                                                 "fail : i2c access to register.\n");
157                                 return sprintf(buf, "%d\n", ret);
158                         }
159                 }
160                 if (reg_val & data->fault[icnt].mask)
161                         fault |= data->fault[icnt].bl_fault;            
162         }
163         return sprintf(buf, "%d\n", fault);
166 /* chip enable control */
167 static ssize_t scbl_enable_show(struct device *dev,
168                                   struct device_attribute *attr, char *buf)
170         struct scbl_chip *pchip = dev_get_drvdata(dev);
171         const struct scbl_data *data = pchip->data; 
172         unsigned int reg_val;
173         int ret;
175         ret = regmap_read(pchip->regmap, data->en_chip.reg, &reg_val);
176         if (ret <0) {           
177                 return sprintf(buf, "%d\n", -EINVAL);
178         }
179         return sprintf(buf, "%d\n",
180                         (reg_val & data->en_chip.mask) >> data->en_chip.shift);
183 static ssize_t scbl_enable_store(struct device *dev,
184                                    struct device_attribute *attr,
185                                    const char *buf, size_t size)
187         struct scbl_chip *pchip = dev_get_drvdata(dev);
188         const struct scbl_data *data = pchip->data; 
189         int ret;
190         u8 input;
192         if (kstrtou8(buf, 0, &input))
193                 return -EINVAL;
195         if (input == 0)
196                 ret = regmap_update_bits(pchip->regmap,
197                                         data->en_chip.reg, data->en_chip.mask, 0x00);
198         else
199                 ret = regmap_update_bits(pchip->regmap, data->en_chip.reg,
200                                         data->en_chip.mask, 0x01 << data->en_chip.shift);
201         if(ret <0)
202                 return ret;
204         return size;
207 /* brightness control */
208 static int scbl_update_status(struct backlight_device *bl)
210         struct scbl_chip *pchip = bl_get_data(bl);
211         const struct scbl_data *data = pchip->data; 
212         int ret = -EINVAL;
213         int msb, lsb;
215         if (bl->props.state & (BL_CORE_SUSPENDED | BL_CORE_FBBLANK))
216                 bl->props.brightness = 0;
217         
218         /* lsb write first */
219         if(data->brt.lsb_mask != 0x00) {
220                 msb = bl->props.brightness >> data->brt.msb_shift ;
221                 lsb = bl->props.brightness & data->brt.lsb_mask ;
223                 ret = regmap_update_bits(pchip->regmap, data->brt.lsb.reg,
224                                         data->brt.lsb.mask, lsb << data->brt.lsb.shift);
225         } else {
226                 msb = bl->props.brightness;
227         }
229         /* msb write */
230         ret = regmap_update_bits(pchip->regmap, data->brt.msb.reg,
231                                 data->brt.msb.mask, msb << data->brt.msb.shift);
233         if (ret < 0)
234                 dev_err(pchip->dev, "fail : i2c access to register.\n");
235         else
236                 ret = bl->props.brightness;
238         return ret;
241 static int scbl_get_brightness(struct backlight_device *bl)
243         return bl->props.brightness;
246 static const struct backlight_ops scbl_bled_ops = {
247         .options = BL_CORE_SUSPENDRESUME,
248         .update_status = scbl_update_status,
249         .get_brightness = scbl_get_brightness,
250 };
252 /*
253  * LP36923 backlight chip data
254  *  lp36923 is an ultra-compact, highly efficient, three string white-LED
255  * driver.
256  */
257 static struct device_attribute lm36923_dev_attr[] = {
258         scbl_attr("fault", scbl_fault_show, NULL),
259         scbl_attr("reset", NULL, scbl_reset_store),
260         scbl_attr("enable", scbl_enable_show, scbl_enable_store),
261 };
263 static int scbl_lm36923_reset(struct regmap *regmap)
265         return regmap_update_bits(regmap, 0x01, 0x01, 0x01);
268 static int scbl_lm36923_boot(struct regmap *regmap)
270         int rval;
272         rval = regmap_update_bits(regmap, 0x10, 0x0f, 0x00);
273         /* 
274          * For glitch free operation, the following data should
275          * only be written while chine enable bit is 0
276          */
277         /* mapping mode / brt mode / ramp / ramp rate / bl_adj polarity */
278         rval |= regmap_write(regmap, 0x11, 0x81);
279         /* pwm */
280         rval |= regmap_write(regmap, 0x12, 0x73);
281         /* auto frequency high threshold */
282         rval |= regmap_write(regmap, 0x15, 0x00);
283         /* auto frequency low threshold */
284         rval |= regmap_write(regmap, 0x16, 0x00);
285         /* backlight adjust threshold */
286         rval |= regmap_write(regmap, 0x17, 0x00);
287         /* chip and leds enable */
288         rval |= regmap_update_bits(regmap, 0x10, 0x0f, 0x0f);
289         return rval;
292 static const struct scbl_data bl_lm36923 = {
293         .name = LM36923_NAME,
294         .num_led = 3,
295         .en_chip = {.reg = 0x10, .mask = 0x01, .shift = 0},
296         .en_led = {
297                 [0] = {.reg = 0x10, .mask = 0x02, .shift = 1},
298                 [1] = {.reg = 0x10, .mask = 0x04, .shift = 2},
299                 [2] = {.reg = 0x10, .mask = 0x08, .shift = 3},
300         },
301         .brt = {
302                 .min = 0x00, .max = 0x7ff,
303                 .msb_shift = 3, .lsb_mask = 0x07,
304                 .msb = {.reg = 0x19, .mask = 0xff, .shift = 0},
305                 .lsb = {.reg = 0x18, .mask = 0x07, .shift = 0},
306         },
307         .fault = {
308                 [0] = {
309                         .reg = 0x1f, .mask = 0x01, 
310                         .bl_fault = SCBL_FAULT_OVER_VOLTAGE
311                 },      
312                 [1] = {
313                         .reg = 0x1f, .mask = 0x02,
314                         .bl_fault = SCBL_FAULT_OVER_CURRENT
315                 },      
316                 [2] = {
317                         .reg = 0x1f, .mask = 0x04,
318                         .bl_fault = SCBL_FAULT_THERMAL_SHDN
319                 },      
320                 [3] = {
321                         .reg = 0x1f, .mask = 0x08,
322                         .bl_fault = SCBL_FAULT_LED_SHORT
323                 },      
324                 [4] = {
325                         .reg = 0x1f, .mask = 0x10,
326                         .bl_fault = SCBL_FAULT_LED_OPEN
327                 },      
328         },
329         .boot = scbl_lm36923_boot,
330         .init = NULL,
331         .reset = scbl_lm36923_reset,
332         .num_devnode = 3,
333         .scbl_dev_attr = lm36923_dev_attr,
334 };
336 static const struct regmap_config scbl_regmap = {
337         .reg_bits = 8,
338         .val_bits = 8,
339         .max_register = SCBL_REG_MAX,
340 };
342 static int scbl_probe(struct i2c_client *client,
343                         const struct i2c_device_id *devid)
345         struct scbl_chip *pchip;
346         struct backlight_properties props;
347         int ret, icnt;
349         if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) {
350                 dev_err(&client->dev, "fail : i2c functionality check.\n");
351                 return -EOPNOTSUPP;
352         }
354         pchip = devm_kzalloc(&client->dev,
355                              sizeof(struct scbl_chip), GFP_KERNEL);
356         if (!pchip)
357                 return -ENOMEM;
358         pchip->dev = &client->dev;
360         pchip->regmap = devm_regmap_init_i2c(client, &scbl_regmap);
361         if (IS_ERR(pchip->regmap)) {
362                 ret = PTR_ERR(pchip->regmap);
363                 dev_err(pchip->dev, "fail : allocate i2c register map.\n");
364                 return ret;
365         }
367         pchip->data = (const struct scbl_data *)devid->driver_data;
368         i2c_set_clientdata(client, pchip);
370         props.brightness = 0;
371         props.type = BACKLIGHT_RAW;
372         props.max_brightness = pchip->data->brt.max;
373         pchip->bled = devm_backlight_device_register(pchip->dev,
374                                                      pchip->data->name,
375                                                          pchip->dev,
376                                                      pchip, &scbl_bled_ops,
377                                                      &props);
378         if (IS_ERR(pchip->bled)) {
379                 dev_err(pchip->dev, "fail : backlight register.\n");
380                 ret = PTR_ERR(pchip->bled);
381                 return ret;
382         }
384         for (icnt = 0; icnt < pchip->data->num_devnode; icnt++) {
385                 ret =
386                     device_create_file(&(pchip->bled->dev),
387                                               &(pchip->data->scbl_dev_attr)[icnt]);
388                 if (ret < 0) {
389                         dev_err(pchip->dev, "fail : node create\n");
390                         goto err_out;
391                 }
392         }
393         /* chip boot sequence before chip enable */
394         if(pchip->data->boot != NULL) {
395                 ret = pchip->data->boot(pchip->regmap);
396                 if (ret < 0)
397                         goto err_out;
398         }
399         /* chip enable */
400         ret = regmap_update_bits(pchip->regmap, pchip->data->en_chip.reg,
401                                                                         pchip->data->en_chip.mask,
402                                                                         0x01<<pchip->data->en_chip.shift);
404         /* chip init sequence after chip enable */
405         if(pchip->data->init != NULL) {
406                 ret = pchip->data->boot(pchip->regmap);
407                 if (ret < 0)
408                         goto err_out;
409         }
410         dev_info(pchip->dev, "[%s] initialized.\n",     pchip->data->name);
411         return 0;
413 err_out:
414         while (--icnt >= 0)
415                 device_remove_file(&(pchip->bled->dev),
416                                                       &(pchip->data->scbl_dev_attr)[icnt]);
417         dev_info(pchip->dev, "[%s] init failed.\n",     pchip->data->name);
418         return ret;
421 static int scbl_remove(struct i2c_client *client)
423         struct scbl_chip *pchip = i2c_get_clientdata(client);
424         int icnt;
426         for (icnt = 0; icnt < pchip->data->num_devnode; icnt++)
427                 device_remove_file(&(pchip->bled->dev),
428                                                       &(pchip->data->scbl_dev_attr)[icnt]);
429         return 0;
432 static const struct i2c_device_id scbl_id[] = {
433         {LM36923_NAME, (unsigned long)&bl_lm36923},
434         {}
435 };
437 MODULE_DEVICE_TABLE(i2c, scbl_id);
438 static struct i2c_driver scbl_i2c_driver = {
439         .driver = {
440                    .name = TI_SINGLE_CONTROL_BL_NAME,
441                    },
442         .probe = scbl_probe,
443         .remove = scbl_remove,
444         .id_table = scbl_id,
445 };
447 module_i2c_driver(scbl_i2c_driver);
449 MODULE_DESCRIPTION("Texas Instruments Single Control Backlight Driver");
450 MODULE_AUTHOR("Daniel Jeong <gshark.jeong@gmail.com>");
451 MODULE_AUTHOR("Ldd Mlp <ldd-mlp@list.ti.com>");
452 MODULE_LICENSE("GPL v2");