Merge tag 'late-omap' of git://git.kernel.org/pub/scm/linux/kernel/git/arm/arm-soc
[platform/kernel/linux-rpi.git] / drivers / video / backlight / lp855x_bl.c
1 /*
2  * TI LP855x Backlight Driver
3  *
4  *                      Copyright (C) 2011 Texas Instruments
5  *
6  * This program is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License version 2 as
8  * published by the Free Software Foundation.
9  *
10  */
11
12 #include <linux/module.h>
13 #include <linux/slab.h>
14 #include <linux/i2c.h>
15 #include <linux/backlight.h>
16 #include <linux/err.h>
17 #include <linux/platform_data/lp855x.h>
18 #include <linux/pwm.h>
19
20 /* LP8550/1/2/3/6 Registers */
21 #define LP855X_BRIGHTNESS_CTRL          0x00
22 #define LP855X_DEVICE_CTRL              0x01
23 #define LP855X_EEPROM_START             0xA0
24 #define LP855X_EEPROM_END               0xA7
25 #define LP8556_EPROM_START              0xA0
26 #define LP8556_EPROM_END                0xAF
27
28 /* LP8557 Registers */
29 #define LP8557_BL_CMD                   0x00
30 #define LP8557_BL_MASK                  0x01
31 #define LP8557_BL_ON                    0x01
32 #define LP8557_BL_OFF                   0x00
33 #define LP8557_BRIGHTNESS_CTRL          0x04
34 #define LP8557_CONFIG                   0x10
35 #define LP8557_EPROM_START              0x10
36 #define LP8557_EPROM_END                0x1E
37
38 #define BUF_SIZE                20
39 #define DEFAULT_BL_NAME         "lcd-backlight"
40 #define MAX_BRIGHTNESS          255
41
42 struct lp855x;
43
44 /*
45  * struct lp855x_device_config
46  * @pre_init_device: init device function call before updating the brightness
47  * @reg_brightness: register address for brigthenss control
48  * @reg_devicectrl: register address for device control
49  * @post_init_device: late init device function call
50  */
51 struct lp855x_device_config {
52         int (*pre_init_device)(struct lp855x *);
53         u8 reg_brightness;
54         u8 reg_devicectrl;
55         int (*post_init_device)(struct lp855x *);
56 };
57
58 struct lp855x {
59         const char *chipname;
60         enum lp855x_chip_id chip_id;
61         struct lp855x_device_config *cfg;
62         struct i2c_client *client;
63         struct backlight_device *bl;
64         struct device *dev;
65         struct lp855x_platform_data *pdata;
66         struct pwm_device *pwm;
67 };
68
69 static int lp855x_write_byte(struct lp855x *lp, u8 reg, u8 data)
70 {
71         return i2c_smbus_write_byte_data(lp->client, reg, data);
72 }
73
74 static int lp855x_update_bit(struct lp855x *lp, u8 reg, u8 mask, u8 data)
75 {
76         int ret;
77         u8 tmp;
78
79         ret = i2c_smbus_read_byte_data(lp->client, reg);
80         if (ret < 0) {
81                 dev_err(lp->dev, "failed to read 0x%.2x\n", reg);
82                 return ret;
83         }
84
85         tmp = (u8)ret;
86         tmp &= ~mask;
87         tmp |= data & mask;
88
89         return lp855x_write_byte(lp, reg, tmp);
90 }
91
92 static bool lp855x_is_valid_rom_area(struct lp855x *lp, u8 addr)
93 {
94         u8 start, end;
95
96         switch (lp->chip_id) {
97         case LP8550:
98         case LP8551:
99         case LP8552:
100         case LP8553:
101                 start = LP855X_EEPROM_START;
102                 end = LP855X_EEPROM_END;
103                 break;
104         case LP8556:
105                 start = LP8556_EPROM_START;
106                 end = LP8556_EPROM_END;
107                 break;
108         case LP8557:
109                 start = LP8557_EPROM_START;
110                 end = LP8557_EPROM_END;
111                 break;
112         default:
113                 return false;
114         }
115
116         return (addr >= start && addr <= end);
117 }
118
119 static int lp8557_bl_off(struct lp855x *lp)
120 {
121         /* BL_ON = 0 before updating EPROM settings */
122         return lp855x_update_bit(lp, LP8557_BL_CMD, LP8557_BL_MASK,
123                                 LP8557_BL_OFF);
124 }
125
126 static int lp8557_bl_on(struct lp855x *lp)
127 {
128         /* BL_ON = 1 after updating EPROM settings */
129         return lp855x_update_bit(lp, LP8557_BL_CMD, LP8557_BL_MASK,
130                                 LP8557_BL_ON);
131 }
132
133 static struct lp855x_device_config lp855x_dev_cfg = {
134         .reg_brightness = LP855X_BRIGHTNESS_CTRL,
135         .reg_devicectrl = LP855X_DEVICE_CTRL,
136 };
137
138 static struct lp855x_device_config lp8557_dev_cfg = {
139         .reg_brightness = LP8557_BRIGHTNESS_CTRL,
140         .reg_devicectrl = LP8557_CONFIG,
141         .pre_init_device = lp8557_bl_off,
142         .post_init_device = lp8557_bl_on,
143 };
144
145 /*
146  * Device specific configuration flow
147  *
148  *    a) pre_init_device(optional)
149  *    b) update the brightness register
150  *    c) update device control register
151  *    d) update ROM area(optional)
152  *    e) post_init_device(optional)
153  *
154  */
155 static int lp855x_configure(struct lp855x *lp)
156 {
157         u8 val, addr;
158         int i, ret;
159         struct lp855x_platform_data *pd = lp->pdata;
160
161         switch (lp->chip_id) {
162         case LP8550 ... LP8556:
163                 lp->cfg = &lp855x_dev_cfg;
164                 break;
165         case LP8557:
166                 lp->cfg = &lp8557_dev_cfg;
167                 break;
168         default:
169                 return -EINVAL;
170         }
171
172         if (lp->cfg->pre_init_device) {
173                 ret = lp->cfg->pre_init_device(lp);
174                 if (ret) {
175                         dev_err(lp->dev, "pre init device err: %d\n", ret);
176                         goto err;
177                 }
178         }
179
180         val = pd->initial_brightness;
181         ret = lp855x_write_byte(lp, lp->cfg->reg_brightness, val);
182         if (ret)
183                 goto err;
184
185         val = pd->device_control;
186         ret = lp855x_write_byte(lp, lp->cfg->reg_devicectrl, val);
187         if (ret)
188                 goto err;
189
190         if (pd->load_new_rom_data && pd->size_program) {
191                 for (i = 0; i < pd->size_program; i++) {
192                         addr = pd->rom_data[i].addr;
193                         val = pd->rom_data[i].val;
194                         if (!lp855x_is_valid_rom_area(lp, addr))
195                                 continue;
196
197                         ret = lp855x_write_byte(lp, addr, val);
198                         if (ret)
199                                 goto err;
200                 }
201         }
202
203         if (lp->cfg->post_init_device) {
204                 ret = lp->cfg->post_init_device(lp);
205                 if (ret) {
206                         dev_err(lp->dev, "post init device err: %d\n", ret);
207                         goto err;
208                 }
209         }
210
211         return 0;
212
213 err:
214         return ret;
215 }
216
217 static void lp855x_pwm_ctrl(struct lp855x *lp, int br, int max_br)
218 {
219         unsigned int period = lp->pdata->period_ns;
220         unsigned int duty = br * period / max_br;
221         struct pwm_device *pwm;
222
223         /* request pwm device with the consumer name */
224         if (!lp->pwm) {
225                 pwm = devm_pwm_get(lp->dev, lp->chipname);
226                 if (IS_ERR(pwm))
227                         return;
228
229                 lp->pwm = pwm;
230         }
231
232         pwm_config(lp->pwm, duty, period);
233         if (duty)
234                 pwm_enable(lp->pwm);
235         else
236                 pwm_disable(lp->pwm);
237 }
238
239 static int lp855x_bl_update_status(struct backlight_device *bl)
240 {
241         struct lp855x *lp = bl_get_data(bl);
242         enum lp855x_brightness_ctrl_mode mode = lp->pdata->mode;
243
244         if (bl->props.state & BL_CORE_SUSPENDED)
245                 bl->props.brightness = 0;
246
247         if (mode == PWM_BASED) {
248                 int br = bl->props.brightness;
249                 int max_br = bl->props.max_brightness;
250
251                 lp855x_pwm_ctrl(lp, br, max_br);
252
253         } else if (mode == REGISTER_BASED) {
254                 u8 val = bl->props.brightness;
255                 lp855x_write_byte(lp, lp->cfg->reg_brightness, val);
256         }
257
258         return 0;
259 }
260
261 static int lp855x_bl_get_brightness(struct backlight_device *bl)
262 {
263         return bl->props.brightness;
264 }
265
266 static const struct backlight_ops lp855x_bl_ops = {
267         .options = BL_CORE_SUSPENDRESUME,
268         .update_status = lp855x_bl_update_status,
269         .get_brightness = lp855x_bl_get_brightness,
270 };
271
272 static int lp855x_backlight_register(struct lp855x *lp)
273 {
274         struct backlight_device *bl;
275         struct backlight_properties props;
276         struct lp855x_platform_data *pdata = lp->pdata;
277         char *name = pdata->name ? : DEFAULT_BL_NAME;
278
279         props.type = BACKLIGHT_PLATFORM;
280         props.max_brightness = MAX_BRIGHTNESS;
281
282         if (pdata->initial_brightness > props.max_brightness)
283                 pdata->initial_brightness = props.max_brightness;
284
285         props.brightness = pdata->initial_brightness;
286
287         bl = backlight_device_register(name, lp->dev, lp,
288                                        &lp855x_bl_ops, &props);
289         if (IS_ERR(bl))
290                 return PTR_ERR(bl);
291
292         lp->bl = bl;
293
294         return 0;
295 }
296
297 static void lp855x_backlight_unregister(struct lp855x *lp)
298 {
299         if (lp->bl)
300                 backlight_device_unregister(lp->bl);
301 }
302
303 static ssize_t lp855x_get_chip_id(struct device *dev,
304                                 struct device_attribute *attr, char *buf)
305 {
306         struct lp855x *lp = dev_get_drvdata(dev);
307         return scnprintf(buf, BUF_SIZE, "%s\n", lp->chipname);
308 }
309
310 static ssize_t lp855x_get_bl_ctl_mode(struct device *dev,
311                                      struct device_attribute *attr, char *buf)
312 {
313         struct lp855x *lp = dev_get_drvdata(dev);
314         enum lp855x_brightness_ctrl_mode mode = lp->pdata->mode;
315         char *strmode = NULL;
316
317         if (mode == PWM_BASED)
318                 strmode = "pwm based";
319         else if (mode == REGISTER_BASED)
320                 strmode = "register based";
321
322         return scnprintf(buf, BUF_SIZE, "%s\n", strmode);
323 }
324
325 static DEVICE_ATTR(chip_id, S_IRUGO, lp855x_get_chip_id, NULL);
326 static DEVICE_ATTR(bl_ctl_mode, S_IRUGO, lp855x_get_bl_ctl_mode, NULL);
327
328 static struct attribute *lp855x_attributes[] = {
329         &dev_attr_chip_id.attr,
330         &dev_attr_bl_ctl_mode.attr,
331         NULL,
332 };
333
334 static const struct attribute_group lp855x_attr_group = {
335         .attrs = lp855x_attributes,
336 };
337
338 static int lp855x_probe(struct i2c_client *cl, const struct i2c_device_id *id)
339 {
340         struct lp855x *lp;
341         struct lp855x_platform_data *pdata = cl->dev.platform_data;
342         enum lp855x_brightness_ctrl_mode mode;
343         int ret;
344
345         if (!pdata) {
346                 dev_err(&cl->dev, "no platform data supplied\n");
347                 return -EINVAL;
348         }
349
350         if (!i2c_check_functionality(cl->adapter, I2C_FUNC_SMBUS_I2C_BLOCK))
351                 return -EIO;
352
353         lp = devm_kzalloc(&cl->dev, sizeof(struct lp855x), GFP_KERNEL);
354         if (!lp)
355                 return -ENOMEM;
356
357         mode = pdata->mode;
358         lp->client = cl;
359         lp->dev = &cl->dev;
360         lp->pdata = pdata;
361         lp->chipname = id->name;
362         lp->chip_id = id->driver_data;
363         i2c_set_clientdata(cl, lp);
364
365         ret = lp855x_configure(lp);
366         if (ret) {
367                 dev_err(lp->dev, "device config err: %d", ret);
368                 goto err_dev;
369         }
370
371         ret = lp855x_backlight_register(lp);
372         if (ret) {
373                 dev_err(lp->dev,
374                         "failed to register backlight. err: %d\n", ret);
375                 goto err_dev;
376         }
377
378         ret = sysfs_create_group(&lp->dev->kobj, &lp855x_attr_group);
379         if (ret) {
380                 dev_err(lp->dev, "failed to register sysfs. err: %d\n", ret);
381                 goto err_sysfs;
382         }
383
384         backlight_update_status(lp->bl);
385         return 0;
386
387 err_sysfs:
388         lp855x_backlight_unregister(lp);
389 err_dev:
390         return ret;
391 }
392
393 static int lp855x_remove(struct i2c_client *cl)
394 {
395         struct lp855x *lp = i2c_get_clientdata(cl);
396
397         lp->bl->props.brightness = 0;
398         backlight_update_status(lp->bl);
399         sysfs_remove_group(&lp->dev->kobj, &lp855x_attr_group);
400         lp855x_backlight_unregister(lp);
401
402         return 0;
403 }
404
405 static const struct i2c_device_id lp855x_ids[] = {
406         {"lp8550", LP8550},
407         {"lp8551", LP8551},
408         {"lp8552", LP8552},
409         {"lp8553", LP8553},
410         {"lp8556", LP8556},
411         {"lp8557", LP8557},
412         { }
413 };
414 MODULE_DEVICE_TABLE(i2c, lp855x_ids);
415
416 static struct i2c_driver lp855x_driver = {
417         .driver = {
418                    .name = "lp855x",
419                    },
420         .probe = lp855x_probe,
421         .remove = lp855x_remove,
422         .id_table = lp855x_ids,
423 };
424
425 module_i2c_driver(lp855x_driver);
426
427 MODULE_DESCRIPTION("Texas Instruments LP855x Backlight driver");
428 MODULE_AUTHOR("Milo Kim <milo.kim@ti.com>");
429 MODULE_LICENSE("GPL");