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, ®_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 bl->props.brightness; 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 bl->props.brightness; 205 206 out_i2c_err: 207 dev_err(pchip->dev, "i2c failed to access\n"); 208 return bl->props.brightness; 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 bl->props.brightness; 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 bl->props.brightness; 282 283 out_i2c_err: 284 dev_err(pchip->dev, "i2c failed to access REG_CTRL\n"); 285 return bl->props.brightness; 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"); 490