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;
138 }
140 static ssize_t lm3585_reset_store(struct device *dev,
141 struct device_attribute *attr,
142 const char *buf, size_t size)
143 {
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;
157 }
159 static ssize_t lm3585_fault_show(struct device *dev,
160 struct device_attribute *attr, char *buf)
161 {
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);
182 }
184 static ssize_t lm3585_enable_show(struct device *dev,
185 struct device_attribute *attr, char *buf)
186 {
187 struct lm3585_chip *pchip = dev_get_drvdata(dev);
189 return sprintf(buf, "%d\n", pchip->is_enabled);
190 }
192 static ssize_t lm3585_enable_store(struct device *dev,
193 struct device_attribute *attr,
194 const char *buf, size_t size)
195 {
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;
233 }
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,\
244 }
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)
254 {
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;
282 }
284 static int lm3585_get_brightness(struct backlight_device *bl)
285 {
286 return bl->props.brightness;
287 }
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)
303 {
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;
328 }
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)
337 {
338 return NULL;
339 }
340 #endif
342 static int lm3585_probe(struct i2c_client *client,
343 const struct i2c_device_id *id)
344 {
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;
426 }
428 static int lm3585_remove(struct i2c_client *client)
429 {
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;
436 }
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");