GNU Linux-libre 4.19.264-gnu1
[releases.git] / drivers / video / backlight / lm3630a_bl.c
1 /*
2 * Simple driver for Texas Instruments LM3630A Backlight driver chip
3 * Copyright (C) 2012 Texas Instruments
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License version 2 as
7 * published by the Free Software Foundation.
8 *
9 */
10 #include <linux/module.h>
11 #include <linux/slab.h>
12 #include <linux/i2c.h>
13 #include <linux/backlight.h>
14 #include <linux/err.h>
15 #include <linux/delay.h>
16 #include <linux/uaccess.h>
17 #include <linux/interrupt.h>
18 #include <linux/regmap.h>
19 #include <linux/pwm.h>
20 #include <linux/platform_data/lm3630a_bl.h>
21
22 #define REG_CTRL        0x00
23 #define REG_BOOST       0x02
24 #define REG_CONFIG      0x01
25 #define REG_BRT_A       0x03
26 #define REG_BRT_B       0x04
27 #define REG_I_A         0x05
28 #define REG_I_B         0x06
29 #define REG_INT_STATUS  0x09
30 #define REG_INT_EN      0x0A
31 #define REG_FAULT       0x0B
32 #define REG_PWM_OUTLOW  0x12
33 #define REG_PWM_OUTHIGH 0x13
34 #define REG_FILTER_STRENGTH     0x50
35 #define REG_MAX         0x50
36
37 #define INT_DEBOUNCE_MSEC       10
38 struct lm3630a_chip {
39         struct device *dev;
40         struct delayed_work work;
41
42         int irq;
43         struct workqueue_struct *irqthread;
44         struct lm3630a_platform_data *pdata;
45         struct backlight_device *bleda;
46         struct backlight_device *bledb;
47         struct regmap *regmap;
48         struct pwm_device *pwmd;
49 };
50
51 /* i2c access */
52 static int lm3630a_read(struct lm3630a_chip *pchip, unsigned int reg)
53 {
54         int rval;
55         unsigned int reg_val;
56
57         rval = regmap_read(pchip->regmap, reg, &reg_val);
58         if (rval < 0)
59                 return rval;
60         return reg_val & 0xFF;
61 }
62
63 static int lm3630a_write(struct lm3630a_chip *pchip,
64                          unsigned int reg, unsigned int data)
65 {
66         return regmap_write(pchip->regmap, reg, data);
67 }
68
69 static int lm3630a_update(struct lm3630a_chip *pchip,
70                           unsigned int reg, unsigned int mask,
71                           unsigned int data)
72 {
73         return regmap_update_bits(pchip->regmap, reg, mask, data);
74 }
75
76 /* initialize chip */
77 static int lm3630a_chip_init(struct lm3630a_chip *pchip)
78 {
79         int rval;
80         struct lm3630a_platform_data *pdata = pchip->pdata;
81
82         usleep_range(1000, 2000);
83         /* set Filter Strength Register */
84         rval = lm3630a_write(pchip, REG_FILTER_STRENGTH, 0x03);
85         /* set Cofig. register */
86         rval |= lm3630a_update(pchip, REG_CONFIG, 0x07, pdata->pwm_ctrl);
87         /* set boost control */
88         rval |= lm3630a_write(pchip, REG_BOOST, 0x38);
89         /* set current A */
90         rval |= lm3630a_update(pchip, REG_I_A, 0x1F, 0x1F);
91         /* set current B */
92         rval |= lm3630a_write(pchip, REG_I_B, 0x1F);
93         /* set control */
94         rval |= lm3630a_update(pchip, REG_CTRL, 0x14, pdata->leda_ctrl);
95         rval |= lm3630a_update(pchip, REG_CTRL, 0x0B, pdata->ledb_ctrl);
96         usleep_range(1000, 2000);
97         /* set brightness A and B */
98         rval |= lm3630a_write(pchip, REG_BRT_A, pdata->leda_init_brt);
99         rval |= lm3630a_write(pchip, REG_BRT_B, pdata->ledb_init_brt);
100
101         if (rval < 0)
102                 dev_err(pchip->dev, "i2c failed to access register\n");
103         return rval;
104 }
105
106 /* interrupt handling */
107 static void lm3630a_delayed_func(struct work_struct *work)
108 {
109         int rval;
110         struct lm3630a_chip *pchip;
111
112         pchip = container_of(work, struct lm3630a_chip, work.work);
113
114         rval = lm3630a_read(pchip, REG_INT_STATUS);
115         if (rval < 0) {
116                 dev_err(pchip->dev,
117                         "i2c failed to access REG_INT_STATUS Register\n");
118                 return;
119         }
120
121         dev_info(pchip->dev, "REG_INT_STATUS Register is 0x%x\n", rval);
122 }
123
124 static irqreturn_t lm3630a_isr_func(int irq, void *chip)
125 {
126         int rval;
127         struct lm3630a_chip *pchip = chip;
128         unsigned long delay = msecs_to_jiffies(INT_DEBOUNCE_MSEC);
129
130         queue_delayed_work(pchip->irqthread, &pchip->work, delay);
131
132         rval = lm3630a_update(pchip, REG_CTRL, 0x80, 0x00);
133         if (rval < 0) {
134                 dev_err(pchip->dev, "i2c failed to access register\n");
135                 return IRQ_NONE;
136         }
137         return IRQ_HANDLED;
138 }
139
140 static int lm3630a_intr_config(struct lm3630a_chip *pchip)
141 {
142         int rval;
143
144         rval = lm3630a_write(pchip, REG_INT_EN, 0x87);
145         if (rval < 0)
146                 return rval;
147
148         INIT_DELAYED_WORK(&pchip->work, lm3630a_delayed_func);
149         pchip->irqthread = create_singlethread_workqueue("lm3630a-irqthd");
150         if (!pchip->irqthread) {
151                 dev_err(pchip->dev, "create irq thread fail\n");
152                 return -ENOMEM;
153         }
154         if (request_threaded_irq
155             (pchip->irq, NULL, lm3630a_isr_func,
156              IRQF_TRIGGER_FALLING | IRQF_ONESHOT, "lm3630a_irq", pchip)) {
157                 dev_err(pchip->dev, "request threaded irq fail\n");
158                 destroy_workqueue(pchip->irqthread);
159                 return -ENOMEM;
160         }
161         return rval;
162 }
163
164 static void lm3630a_pwm_ctrl(struct lm3630a_chip *pchip, int br, int br_max)
165 {
166         unsigned int period = pchip->pdata->pwm_period;
167         unsigned int duty = br * period / br_max;
168
169         pwm_config(pchip->pwmd, duty, period);
170         if (duty)
171                 pwm_enable(pchip->pwmd);
172         else
173                 pwm_disable(pchip->pwmd);
174 }
175
176 /* update and get brightness */
177 static int lm3630a_bank_a_update_status(struct backlight_device *bl)
178 {
179         int ret;
180         struct lm3630a_chip *pchip = bl_get_data(bl);
181         enum lm3630a_pwm_ctrl pwm_ctrl = pchip->pdata->pwm_ctrl;
182
183         /* pwm control */
184         if ((pwm_ctrl & LM3630A_PWM_BANK_A) != 0) {
185                 lm3630a_pwm_ctrl(pchip, bl->props.brightness,
186                                  bl->props.max_brightness);
187                 return 0;
188         }
189
190         /* disable sleep */
191         ret = lm3630a_update(pchip, REG_CTRL, 0x80, 0x00);
192         if (ret < 0)
193                 goto out_i2c_err;
194         usleep_range(1000, 2000);
195         /* minimum brightness is 0x04 */
196         ret = lm3630a_write(pchip, REG_BRT_A, bl->props.brightness);
197         if (bl->props.brightness < 0x4)
198                 ret |= lm3630a_update(pchip, REG_CTRL, LM3630A_LEDA_ENABLE, 0);
199         else
200                 ret |= lm3630a_update(pchip, REG_CTRL,
201                                       LM3630A_LEDA_ENABLE, LM3630A_LEDA_ENABLE);
202         if (ret < 0)
203                 goto out_i2c_err;
204         return 0;
205
206 out_i2c_err:
207         dev_err(pchip->dev, "i2c failed to access (%pe)\n", ERR_PTR(ret));
208         return ret;
209 }
210
211 static int lm3630a_bank_a_get_brightness(struct backlight_device *bl)
212 {
213         int brightness, rval;
214         struct lm3630a_chip *pchip = bl_get_data(bl);
215         enum lm3630a_pwm_ctrl pwm_ctrl = pchip->pdata->pwm_ctrl;
216
217         if ((pwm_ctrl & LM3630A_PWM_BANK_A) != 0) {
218                 rval = lm3630a_read(pchip, REG_PWM_OUTHIGH);
219                 if (rval < 0)
220                         goto out_i2c_err;
221                 brightness = (rval & 0x01) << 8;
222                 rval = lm3630a_read(pchip, REG_PWM_OUTLOW);
223                 if (rval < 0)
224                         goto out_i2c_err;
225                 brightness |= rval;
226                 goto out;
227         }
228
229         /* disable sleep */
230         rval = lm3630a_update(pchip, REG_CTRL, 0x80, 0x00);
231         if (rval < 0)
232                 goto out_i2c_err;
233         usleep_range(1000, 2000);
234         rval = lm3630a_read(pchip, REG_BRT_A);
235         if (rval < 0)
236                 goto out_i2c_err;
237         brightness = rval;
238
239 out:
240         bl->props.brightness = brightness;
241         return bl->props.brightness;
242 out_i2c_err:
243         dev_err(pchip->dev, "i2c failed to access register\n");
244         return 0;
245 }
246
247 static const struct backlight_ops lm3630a_bank_a_ops = {
248         .options = BL_CORE_SUSPENDRESUME,
249         .update_status = lm3630a_bank_a_update_status,
250         .get_brightness = lm3630a_bank_a_get_brightness,
251 };
252
253 /* update and get brightness */
254 static int lm3630a_bank_b_update_status(struct backlight_device *bl)
255 {
256         int ret;
257         struct lm3630a_chip *pchip = bl_get_data(bl);
258         enum lm3630a_pwm_ctrl pwm_ctrl = pchip->pdata->pwm_ctrl;
259
260         /* pwm control */
261         if ((pwm_ctrl & LM3630A_PWM_BANK_B) != 0) {
262                 lm3630a_pwm_ctrl(pchip, bl->props.brightness,
263                                  bl->props.max_brightness);
264                 return 0;
265         }
266
267         /* disable sleep */
268         ret = lm3630a_update(pchip, REG_CTRL, 0x80, 0x00);
269         if (ret < 0)
270                 goto out_i2c_err;
271         usleep_range(1000, 2000);
272         /* minimum brightness is 0x04 */
273         ret = lm3630a_write(pchip, REG_BRT_B, bl->props.brightness);
274         if (bl->props.brightness < 0x4)
275                 ret |= lm3630a_update(pchip, REG_CTRL, LM3630A_LEDB_ENABLE, 0);
276         else
277                 ret |= lm3630a_update(pchip, REG_CTRL,
278                                       LM3630A_LEDB_ENABLE, LM3630A_LEDB_ENABLE);
279         if (ret < 0)
280                 goto out_i2c_err;
281         return 0;
282
283 out_i2c_err:
284         dev_err(pchip->dev, "i2c failed to access (%pe)\n", ERR_PTR(ret));
285         return ret;
286 }
287
288 static int lm3630a_bank_b_get_brightness(struct backlight_device *bl)
289 {
290         int brightness, rval;
291         struct lm3630a_chip *pchip = bl_get_data(bl);
292         enum lm3630a_pwm_ctrl pwm_ctrl = pchip->pdata->pwm_ctrl;
293
294         if ((pwm_ctrl & LM3630A_PWM_BANK_B) != 0) {
295                 rval = lm3630a_read(pchip, REG_PWM_OUTHIGH);
296                 if (rval < 0)
297                         goto out_i2c_err;
298                 brightness = (rval & 0x01) << 8;
299                 rval = lm3630a_read(pchip, REG_PWM_OUTLOW);
300                 if (rval < 0)
301                         goto out_i2c_err;
302                 brightness |= rval;
303                 goto out;
304         }
305
306         /* disable sleep */
307         rval = lm3630a_update(pchip, REG_CTRL, 0x80, 0x00);
308         if (rval < 0)
309                 goto out_i2c_err;
310         usleep_range(1000, 2000);
311         rval = lm3630a_read(pchip, REG_BRT_B);
312         if (rval < 0)
313                 goto out_i2c_err;
314         brightness = rval;
315
316 out:
317         bl->props.brightness = brightness;
318         return bl->props.brightness;
319 out_i2c_err:
320         dev_err(pchip->dev, "i2c failed to access register\n");
321         return 0;
322 }
323
324 static const struct backlight_ops lm3630a_bank_b_ops = {
325         .options = BL_CORE_SUSPENDRESUME,
326         .update_status = lm3630a_bank_b_update_status,
327         .get_brightness = lm3630a_bank_b_get_brightness,
328 };
329
330 static int lm3630a_backlight_register(struct lm3630a_chip *pchip)
331 {
332         struct backlight_properties props;
333         struct lm3630a_platform_data *pdata = pchip->pdata;
334
335         props.type = BACKLIGHT_RAW;
336         if (pdata->leda_ctrl != LM3630A_LEDA_DISABLE) {
337                 props.brightness = pdata->leda_init_brt;
338                 props.max_brightness = pdata->leda_max_brt;
339                 pchip->bleda =
340                     devm_backlight_device_register(pchip->dev, "lm3630a_leda",
341                                                    pchip->dev, pchip,
342                                                    &lm3630a_bank_a_ops, &props);
343                 if (IS_ERR(pchip->bleda))
344                         return PTR_ERR(pchip->bleda);
345         }
346
347         if ((pdata->ledb_ctrl != LM3630A_LEDB_DISABLE) &&
348             (pdata->ledb_ctrl != LM3630A_LEDB_ON_A)) {
349                 props.brightness = pdata->ledb_init_brt;
350                 props.max_brightness = pdata->ledb_max_brt;
351                 pchip->bledb =
352                     devm_backlight_device_register(pchip->dev, "lm3630a_ledb",
353                                                    pchip->dev, pchip,
354                                                    &lm3630a_bank_b_ops, &props);
355                 if (IS_ERR(pchip->bledb))
356                         return PTR_ERR(pchip->bledb);
357         }
358         return 0;
359 }
360
361 static const struct regmap_config lm3630a_regmap = {
362         .reg_bits = 8,
363         .val_bits = 8,
364         .max_register = REG_MAX,
365 };
366
367 static int lm3630a_probe(struct i2c_client *client,
368                          const struct i2c_device_id *id)
369 {
370         struct lm3630a_platform_data *pdata = dev_get_platdata(&client->dev);
371         struct lm3630a_chip *pchip;
372         int rval;
373
374         if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) {
375                 dev_err(&client->dev, "fail : i2c functionality check\n");
376                 return -EOPNOTSUPP;
377         }
378
379         pchip = devm_kzalloc(&client->dev, sizeof(struct lm3630a_chip),
380                              GFP_KERNEL);
381         if (!pchip)
382                 return -ENOMEM;
383         pchip->dev = &client->dev;
384
385         pchip->regmap = devm_regmap_init_i2c(client, &lm3630a_regmap);
386         if (IS_ERR(pchip->regmap)) {
387                 rval = PTR_ERR(pchip->regmap);
388                 dev_err(&client->dev, "fail : allocate reg. map: %d\n", rval);
389                 return rval;
390         }
391
392         i2c_set_clientdata(client, pchip);
393         if (pdata == NULL) {
394                 pdata = devm_kzalloc(pchip->dev,
395                                      sizeof(struct lm3630a_platform_data),
396                                      GFP_KERNEL);
397                 if (pdata == NULL)
398                         return -ENOMEM;
399                 /* default values */
400                 pdata->leda_ctrl = LM3630A_LEDA_ENABLE;
401                 pdata->ledb_ctrl = LM3630A_LEDB_ENABLE;
402                 pdata->leda_max_brt = LM3630A_MAX_BRIGHTNESS;
403                 pdata->ledb_max_brt = LM3630A_MAX_BRIGHTNESS;
404                 pdata->leda_init_brt = LM3630A_MAX_BRIGHTNESS;
405                 pdata->ledb_init_brt = LM3630A_MAX_BRIGHTNESS;
406         }
407         pchip->pdata = pdata;
408
409         /* chip initialize */
410         rval = lm3630a_chip_init(pchip);
411         if (rval < 0) {
412                 dev_err(&client->dev, "fail : init chip\n");
413                 return rval;
414         }
415         /* backlight register */
416         rval = lm3630a_backlight_register(pchip);
417         if (rval < 0) {
418                 dev_err(&client->dev, "fail : backlight register.\n");
419                 return rval;
420         }
421         /* pwm */
422         if (pdata->pwm_ctrl != LM3630A_PWM_DISABLE) {
423                 pchip->pwmd = devm_pwm_get(pchip->dev, "lm3630a-pwm");
424                 if (IS_ERR(pchip->pwmd)) {
425                         dev_err(&client->dev, "fail : get pwm device\n");
426                         return PTR_ERR(pchip->pwmd);
427                 }
428
429                 /*
430                  * FIXME: pwm_apply_args() should be removed when switching to
431                  * the atomic PWM API.
432                  */
433                 pwm_apply_args(pchip->pwmd);
434         }
435
436         /* interrupt enable  : irq 0 is not allowed */
437         pchip->irq = client->irq;
438         if (pchip->irq) {
439                 rval = lm3630a_intr_config(pchip);
440                 if (rval < 0)
441                         return rval;
442         }
443         dev_info(&client->dev, "LM3630A backlight register OK.\n");
444         return 0;
445 }
446
447 static int lm3630a_remove(struct i2c_client *client)
448 {
449         int rval;
450         struct lm3630a_chip *pchip = i2c_get_clientdata(client);
451
452         rval = lm3630a_write(pchip, REG_BRT_A, 0);
453         if (rval < 0)
454                 dev_err(pchip->dev, "i2c failed to access register\n");
455
456         rval = lm3630a_write(pchip, REG_BRT_B, 0);
457         if (rval < 0)
458                 dev_err(pchip->dev, "i2c failed to access register\n");
459
460         if (pchip->irq) {
461                 free_irq(pchip->irq, pchip);
462                 flush_workqueue(pchip->irqthread);
463                 destroy_workqueue(pchip->irqthread);
464         }
465         return 0;
466 }
467
468 static const struct i2c_device_id lm3630a_id[] = {
469         {LM3630A_NAME, 0},
470         {}
471 };
472
473 MODULE_DEVICE_TABLE(i2c, lm3630a_id);
474
475 static struct i2c_driver lm3630a_i2c_driver = {
476         .driver = {
477                    .name = LM3630A_NAME,
478                    },
479         .probe = lm3630a_probe,
480         .remove = lm3630a_remove,
481         .id_table = lm3630a_id,
482 };
483
484 module_i2c_driver(lm3630a_i2c_driver);
485
486 MODULE_DESCRIPTION("Texas Instruments Backlight driver for LM3630A");
487 MODULE_AUTHOR("Daniel Jeong <gshark.jeong@gmail.com>");
488 MODULE_AUTHOR("LDD MLP <ldd-mlp@list.ti.com>");
489 MODULE_LICENSE("GPL v2");