Linux 4.18.10
[linux/fpc-iii.git] / drivers / video / backlight / lm3630a_bl.c
blob2030a6b77a09725e97bb1618b2695aea5c55f2a0
1 /*
2 * Simple driver for Texas Instruments LM3630A Backlight driver chip
3 * Copyright (C) 2012 Texas Instruments
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.
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>
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
37 #define INT_DEBOUNCE_MSEC 10
38 struct lm3630a_chip {
39 struct device *dev;
40 struct delayed_work work;
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;
51 /* i2c access */
52 static int lm3630a_read(struct lm3630a_chip *pchip, unsigned int reg)
54 int rval;
55 unsigned int reg_val;
57 rval = regmap_read(pchip->regmap, reg, &reg_val);
58 if (rval < 0)
59 return rval;
60 return reg_val & 0xFF;
63 static int lm3630a_write(struct lm3630a_chip *pchip,
64 unsigned int reg, unsigned int data)
66 return regmap_write(pchip->regmap, reg, data);
69 static int lm3630a_update(struct lm3630a_chip *pchip,
70 unsigned int reg, unsigned int mask,
71 unsigned int data)
73 return regmap_update_bits(pchip->regmap, reg, mask, data);
76 /* initialize chip */
77 static int lm3630a_chip_init(struct lm3630a_chip *pchip)
79 int rval;
80 struct lm3630a_platform_data *pdata = pchip->pdata;
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);
101 if (rval < 0)
102 dev_err(pchip->dev, "i2c failed to access register\n");
103 return rval;
106 /* interrupt handling */
107 static void lm3630a_delayed_func(struct work_struct *work)
109 int rval;
110 struct lm3630a_chip *pchip;
112 pchip = container_of(work, struct lm3630a_chip, work.work);
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;
121 dev_info(pchip->dev, "REG_INT_STATUS Register is 0x%x\n", rval);
124 static irqreturn_t lm3630a_isr_func(int irq, void *chip)
126 int rval;
127 struct lm3630a_chip *pchip = chip;
128 unsigned long delay = msecs_to_jiffies(INT_DEBOUNCE_MSEC);
130 queue_delayed_work(pchip->irqthread, &pchip->work, delay);
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;
137 return IRQ_HANDLED;
140 static int lm3630a_intr_config(struct lm3630a_chip *pchip)
142 int rval;
144 rval = lm3630a_write(pchip, REG_INT_EN, 0x87);
145 if (rval < 0)
146 return rval;
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;
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;
161 return rval;
164 static void lm3630a_pwm_ctrl(struct lm3630a_chip *pchip, int br, int br_max)
166 unsigned int period = pchip->pdata->pwm_period;
167 unsigned int duty = br * period / br_max;
169 pwm_config(pchip->pwmd, duty, period);
170 if (duty)
171 pwm_enable(pchip->pwmd);
172 else
173 pwm_disable(pchip->pwmd);
176 /* update and get brightness */
177 static int lm3630a_bank_a_update_status(struct backlight_device *bl)
179 int ret;
180 struct lm3630a_chip *pchip = bl_get_data(bl);
181 enum lm3630a_pwm_ctrl pwm_ctrl = pchip->pdata->pwm_ctrl;
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 bl->props.brightness;
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 bl->props.brightness;
206 out_i2c_err:
207 dev_err(pchip->dev, "i2c failed to access\n");
208 return bl->props.brightness;
211 static int lm3630a_bank_a_get_brightness(struct backlight_device *bl)
213 int brightness, rval;
214 struct lm3630a_chip *pchip = bl_get_data(bl);
215 enum lm3630a_pwm_ctrl pwm_ctrl = pchip->pdata->pwm_ctrl;
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;
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;
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;
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,
253 /* update and get brightness */
254 static int lm3630a_bank_b_update_status(struct backlight_device *bl)
256 int ret;
257 struct lm3630a_chip *pchip = bl_get_data(bl);
258 enum lm3630a_pwm_ctrl pwm_ctrl = pchip->pdata->pwm_ctrl;
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 bl->props.brightness;
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 bl->props.brightness;
283 out_i2c_err:
284 dev_err(pchip->dev, "i2c failed to access REG_CTRL\n");
285 return bl->props.brightness;
288 static int lm3630a_bank_b_get_brightness(struct backlight_device *bl)
290 int brightness, rval;
291 struct lm3630a_chip *pchip = bl_get_data(bl);
292 enum lm3630a_pwm_ctrl pwm_ctrl = pchip->pdata->pwm_ctrl;
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;
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;
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;
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,
330 static int lm3630a_backlight_register(struct lm3630a_chip *pchip)
332 struct backlight_properties props;
333 struct lm3630a_platform_data *pdata = pchip->pdata;
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);
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);
358 return 0;
361 static const struct regmap_config lm3630a_regmap = {
362 .reg_bits = 8,
363 .val_bits = 8,
364 .max_register = REG_MAX,
367 static int lm3630a_probe(struct i2c_client *client,
368 const struct i2c_device_id *id)
370 struct lm3630a_platform_data *pdata = dev_get_platdata(&client->dev);
371 struct lm3630a_chip *pchip;
372 int rval;
374 if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) {
375 dev_err(&client->dev, "fail : i2c functionality check\n");
376 return -EOPNOTSUPP;
379 pchip = devm_kzalloc(&client->dev, sizeof(struct lm3630a_chip),
380 GFP_KERNEL);
381 if (!pchip)
382 return -ENOMEM;
383 pchip->dev = &client->dev;
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;
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;
407 pchip->pdata = pdata;
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;
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;
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);
430 * FIXME: pwm_apply_args() should be removed when switching to
431 * the atomic PWM API.
433 pwm_apply_args(pchip->pwmd);
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;
443 dev_info(&client->dev, "LM3630A backlight register OK.\n");
444 return 0;
447 static int lm3630a_remove(struct i2c_client *client)
449 int rval;
450 struct lm3630a_chip *pchip = i2c_get_clientdata(client);
452 rval = lm3630a_write(pchip, REG_BRT_A, 0);
453 if (rval < 0)
454 dev_err(pchip->dev, "i2c failed to access register\n");
456 rval = lm3630a_write(pchip, REG_BRT_B, 0);
457 if (rval < 0)
458 dev_err(pchip->dev, "i2c failed to access register\n");
460 if (pchip->irq) {
461 free_irq(pchip->irq, pchip);
462 flush_workqueue(pchip->irqthread);
463 destroy_workqueue(pchip->irqthread);
465 return 0;
468 static const struct i2c_device_id lm3630a_id[] = {
469 {LM3630A_NAME, 0},
473 MODULE_DEVICE_TABLE(i2c, lm3630a_id);
475 static struct i2c_driver lm3630a_i2c_driver = {
476 .driver = {
477 .name = LM3630A_NAME,
479 .probe = lm3630a_probe,
480 .remove = lm3630a_remove,
481 .id_table = lm3630a_id,
484 module_i2c_driver(lm3630a_i2c_driver);
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");