lp855x_bl.c (13607B)
1// SPDX-License-Identifier: GPL-2.0-only 2/* 3 * TI LP855x Backlight Driver 4 * 5 * Copyright (C) 2011 Texas Instruments 6 */ 7 8#include <linux/acpi.h> 9#include <linux/module.h> 10#include <linux/slab.h> 11#include <linux/i2c.h> 12#include <linux/backlight.h> 13#include <linux/delay.h> 14#include <linux/err.h> 15#include <linux/of.h> 16#include <linux/platform_data/lp855x.h> 17#include <linux/pwm.h> 18#include <linux/regulator/consumer.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/* LP8555/7 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 LP8555_EPROM_START 0x10 36#define LP8555_EPROM_END 0x7A 37#define LP8557_EPROM_START 0x10 38#define LP8557_EPROM_END 0x1E 39 40#define DEFAULT_BL_NAME "lcd-backlight" 41#define MAX_BRIGHTNESS 255 42 43enum lp855x_brightness_ctrl_mode { 44 PWM_BASED = 1, 45 REGISTER_BASED, 46}; 47 48struct lp855x; 49 50/* 51 * struct lp855x_device_config 52 * @pre_init_device: init device function call before updating the brightness 53 * @reg_brightness: register address for brigthenss control 54 * @reg_devicectrl: register address for device control 55 * @post_init_device: late init device function call 56 */ 57struct lp855x_device_config { 58 int (*pre_init_device)(struct lp855x *); 59 u8 reg_brightness; 60 u8 reg_devicectrl; 61 int (*post_init_device)(struct lp855x *); 62}; 63 64struct lp855x { 65 const char *chipname; 66 enum lp855x_chip_id chip_id; 67 enum lp855x_brightness_ctrl_mode mode; 68 struct lp855x_device_config *cfg; 69 struct i2c_client *client; 70 struct backlight_device *bl; 71 struct device *dev; 72 struct lp855x_platform_data *pdata; 73 struct pwm_device *pwm; 74 struct regulator *supply; /* regulator for VDD input */ 75 struct regulator *enable; /* regulator for EN/VDDIO input */ 76}; 77 78static int lp855x_write_byte(struct lp855x *lp, u8 reg, u8 data) 79{ 80 return i2c_smbus_write_byte_data(lp->client, reg, data); 81} 82 83static int lp855x_update_bit(struct lp855x *lp, u8 reg, u8 mask, u8 data) 84{ 85 int ret; 86 u8 tmp; 87 88 ret = i2c_smbus_read_byte_data(lp->client, reg); 89 if (ret < 0) { 90 dev_err(lp->dev, "failed to read 0x%.2x\n", reg); 91 return ret; 92 } 93 94 tmp = (u8)ret; 95 tmp &= ~mask; 96 tmp |= data & mask; 97 98 return lp855x_write_byte(lp, reg, tmp); 99} 100 101static bool lp855x_is_valid_rom_area(struct lp855x *lp, u8 addr) 102{ 103 u8 start, end; 104 105 switch (lp->chip_id) { 106 case LP8550: 107 case LP8551: 108 case LP8552: 109 case LP8553: 110 start = LP855X_EEPROM_START; 111 end = LP855X_EEPROM_END; 112 break; 113 case LP8556: 114 start = LP8556_EPROM_START; 115 end = LP8556_EPROM_END; 116 break; 117 case LP8555: 118 start = LP8555_EPROM_START; 119 end = LP8555_EPROM_END; 120 break; 121 case LP8557: 122 start = LP8557_EPROM_START; 123 end = LP8557_EPROM_END; 124 break; 125 default: 126 return false; 127 } 128 129 return addr >= start && addr <= end; 130} 131 132static int lp8557_bl_off(struct lp855x *lp) 133{ 134 /* BL_ON = 0 before updating EPROM settings */ 135 return lp855x_update_bit(lp, LP8557_BL_CMD, LP8557_BL_MASK, 136 LP8557_BL_OFF); 137} 138 139static int lp8557_bl_on(struct lp855x *lp) 140{ 141 /* BL_ON = 1 after updating EPROM settings */ 142 return lp855x_update_bit(lp, LP8557_BL_CMD, LP8557_BL_MASK, 143 LP8557_BL_ON); 144} 145 146static struct lp855x_device_config lp855x_dev_cfg = { 147 .reg_brightness = LP855X_BRIGHTNESS_CTRL, 148 .reg_devicectrl = LP855X_DEVICE_CTRL, 149}; 150 151static struct lp855x_device_config lp8557_dev_cfg = { 152 .reg_brightness = LP8557_BRIGHTNESS_CTRL, 153 .reg_devicectrl = LP8557_CONFIG, 154 .pre_init_device = lp8557_bl_off, 155 .post_init_device = lp8557_bl_on, 156}; 157 158/* 159 * Device specific configuration flow 160 * 161 * a) pre_init_device(optional) 162 * b) update the brightness register 163 * c) update device control register 164 * d) update ROM area(optional) 165 * e) post_init_device(optional) 166 * 167 */ 168static int lp855x_configure(struct lp855x *lp) 169{ 170 u8 val, addr; 171 int i, ret; 172 struct lp855x_platform_data *pd = lp->pdata; 173 174 if (lp->cfg->pre_init_device) { 175 ret = lp->cfg->pre_init_device(lp); 176 if (ret) { 177 dev_err(lp->dev, "pre init device err: %d\n", ret); 178 goto err; 179 } 180 } 181 182 val = pd->initial_brightness; 183 ret = lp855x_write_byte(lp, lp->cfg->reg_brightness, val); 184 if (ret) 185 goto err; 186 187 val = pd->device_control; 188 ret = lp855x_write_byte(lp, lp->cfg->reg_devicectrl, val); 189 if (ret) 190 goto err; 191 192 if (pd->size_program > 0) { 193 for (i = 0; i < pd->size_program; i++) { 194 addr = pd->rom_data[i].addr; 195 val = pd->rom_data[i].val; 196 if (!lp855x_is_valid_rom_area(lp, addr)) 197 continue; 198 199 ret = lp855x_write_byte(lp, addr, val); 200 if (ret) 201 goto err; 202 } 203 } 204 205 if (lp->cfg->post_init_device) { 206 ret = lp->cfg->post_init_device(lp); 207 if (ret) { 208 dev_err(lp->dev, "post init device err: %d\n", ret); 209 goto err; 210 } 211 } 212 213 return 0; 214 215err: 216 return ret; 217} 218 219static void lp855x_pwm_ctrl(struct lp855x *lp, int br, int max_br) 220{ 221 unsigned int period = lp->pdata->period_ns; 222 unsigned int duty = br * period / max_br; 223 struct pwm_device *pwm; 224 225 /* request pwm device with the consumer name */ 226 if (!lp->pwm) { 227 pwm = devm_pwm_get(lp->dev, lp->chipname); 228 if (IS_ERR(pwm)) 229 return; 230 231 lp->pwm = pwm; 232 233 /* 234 * FIXME: pwm_apply_args() should be removed when switching to 235 * the atomic PWM API. 236 */ 237 pwm_apply_args(pwm); 238 } 239 240 pwm_config(lp->pwm, duty, period); 241 if (duty) 242 pwm_enable(lp->pwm); 243 else 244 pwm_disable(lp->pwm); 245} 246 247static int lp855x_bl_update_status(struct backlight_device *bl) 248{ 249 struct lp855x *lp = bl_get_data(bl); 250 int brightness = bl->props.brightness; 251 252 if (bl->props.state & (BL_CORE_SUSPENDED | BL_CORE_FBBLANK)) 253 brightness = 0; 254 255 if (lp->mode == PWM_BASED) 256 lp855x_pwm_ctrl(lp, brightness, bl->props.max_brightness); 257 else if (lp->mode == REGISTER_BASED) 258 lp855x_write_byte(lp, lp->cfg->reg_brightness, (u8)brightness); 259 260 return 0; 261} 262 263static const struct backlight_ops lp855x_bl_ops = { 264 .options = BL_CORE_SUSPENDRESUME, 265 .update_status = lp855x_bl_update_status, 266}; 267 268static int lp855x_backlight_register(struct lp855x *lp) 269{ 270 struct backlight_device *bl; 271 struct backlight_properties props; 272 struct lp855x_platform_data *pdata = lp->pdata; 273 const char *name = pdata->name ? : DEFAULT_BL_NAME; 274 275 memset(&props, 0, sizeof(props)); 276 props.type = BACKLIGHT_PLATFORM; 277 props.max_brightness = MAX_BRIGHTNESS; 278 279 if (pdata->initial_brightness > props.max_brightness) 280 pdata->initial_brightness = props.max_brightness; 281 282 props.brightness = pdata->initial_brightness; 283 284 bl = devm_backlight_device_register(lp->dev, name, lp->dev, lp, 285 &lp855x_bl_ops, &props); 286 if (IS_ERR(bl)) 287 return PTR_ERR(bl); 288 289 lp->bl = bl; 290 291 return 0; 292} 293 294static ssize_t lp855x_get_chip_id(struct device *dev, 295 struct device_attribute *attr, char *buf) 296{ 297 struct lp855x *lp = dev_get_drvdata(dev); 298 299 return scnprintf(buf, PAGE_SIZE, "%s\n", lp->chipname); 300} 301 302static ssize_t lp855x_get_bl_ctl_mode(struct device *dev, 303 struct device_attribute *attr, char *buf) 304{ 305 struct lp855x *lp = dev_get_drvdata(dev); 306 char *strmode = NULL; 307 308 if (lp->mode == PWM_BASED) 309 strmode = "pwm based"; 310 else if (lp->mode == REGISTER_BASED) 311 strmode = "register based"; 312 313 return scnprintf(buf, PAGE_SIZE, "%s\n", strmode); 314} 315 316static DEVICE_ATTR(chip_id, S_IRUGO, lp855x_get_chip_id, NULL); 317static DEVICE_ATTR(bl_ctl_mode, S_IRUGO, lp855x_get_bl_ctl_mode, NULL); 318 319static struct attribute *lp855x_attributes[] = { 320 &dev_attr_chip_id.attr, 321 &dev_attr_bl_ctl_mode.attr, 322 NULL, 323}; 324 325static const struct attribute_group lp855x_attr_group = { 326 .attrs = lp855x_attributes, 327}; 328 329#ifdef CONFIG_OF 330static int lp855x_parse_dt(struct lp855x *lp) 331{ 332 struct device *dev = lp->dev; 333 struct device_node *node = dev->of_node; 334 struct lp855x_platform_data *pdata = lp->pdata; 335 int rom_length; 336 337 if (!node) { 338 dev_err(dev, "no platform data\n"); 339 return -EINVAL; 340 } 341 342 of_property_read_string(node, "bl-name", &pdata->name); 343 of_property_read_u8(node, "dev-ctrl", &pdata->device_control); 344 of_property_read_u8(node, "init-brt", &pdata->initial_brightness); 345 of_property_read_u32(node, "pwm-period", &pdata->period_ns); 346 347 /* Fill ROM platform data if defined */ 348 rom_length = of_get_child_count(node); 349 if (rom_length > 0) { 350 struct lp855x_rom_data *rom; 351 struct device_node *child; 352 int i = 0; 353 354 rom = devm_kcalloc(dev, rom_length, sizeof(*rom), GFP_KERNEL); 355 if (!rom) 356 return -ENOMEM; 357 358 for_each_child_of_node(node, child) { 359 of_property_read_u8(child, "rom-addr", &rom[i].addr); 360 of_property_read_u8(child, "rom-val", &rom[i].val); 361 i++; 362 } 363 364 pdata->size_program = rom_length; 365 pdata->rom_data = &rom[0]; 366 } 367 368 return 0; 369} 370#else 371static int lp855x_parse_dt(struct lp855x *lp) 372{ 373 return -EINVAL; 374} 375#endif 376 377static int lp855x_parse_acpi(struct lp855x *lp) 378{ 379 int ret; 380 381 /* 382 * On ACPI the device has already been initialized by the firmware 383 * and is in register mode, so we can read back the settings from 384 * the registers. 385 */ 386 ret = i2c_smbus_read_byte_data(lp->client, lp->cfg->reg_brightness); 387 if (ret < 0) 388 return ret; 389 390 lp->pdata->initial_brightness = ret; 391 392 ret = i2c_smbus_read_byte_data(lp->client, lp->cfg->reg_devicectrl); 393 if (ret < 0) 394 return ret; 395 396 lp->pdata->device_control = ret; 397 return 0; 398} 399 400static int lp855x_probe(struct i2c_client *cl, const struct i2c_device_id *id) 401{ 402 const struct acpi_device_id *acpi_id = NULL; 403 struct device *dev = &cl->dev; 404 struct lp855x *lp; 405 int ret; 406 407 if (!i2c_check_functionality(cl->adapter, I2C_FUNC_SMBUS_I2C_BLOCK)) 408 return -EIO; 409 410 lp = devm_kzalloc(dev, sizeof(struct lp855x), GFP_KERNEL); 411 if (!lp) 412 return -ENOMEM; 413 414 lp->client = cl; 415 lp->dev = dev; 416 lp->pdata = dev_get_platdata(dev); 417 418 if (id) { 419 lp->chipname = id->name; 420 lp->chip_id = id->driver_data; 421 } else { 422 acpi_id = acpi_match_device(dev->driver->acpi_match_table, dev); 423 if (!acpi_id) 424 return -ENODEV; 425 426 lp->chipname = acpi_id->id; 427 lp->chip_id = acpi_id->driver_data; 428 } 429 430 switch (lp->chip_id) { 431 case LP8550: 432 case LP8551: 433 case LP8552: 434 case LP8553: 435 case LP8556: 436 lp->cfg = &lp855x_dev_cfg; 437 break; 438 case LP8555: 439 case LP8557: 440 lp->cfg = &lp8557_dev_cfg; 441 break; 442 default: 443 return -EINVAL; 444 } 445 446 if (!lp->pdata) { 447 lp->pdata = devm_kzalloc(dev, sizeof(*lp->pdata), GFP_KERNEL); 448 if (!lp->pdata) 449 return -ENOMEM; 450 451 if (id) { 452 ret = lp855x_parse_dt(lp); 453 if (ret < 0) 454 return ret; 455 } else { 456 ret = lp855x_parse_acpi(lp); 457 if (ret < 0) 458 return ret; 459 } 460 } 461 462 if (lp->pdata->period_ns > 0) 463 lp->mode = PWM_BASED; 464 else 465 lp->mode = REGISTER_BASED; 466 467 lp->supply = devm_regulator_get(dev, "power"); 468 if (IS_ERR(lp->supply)) { 469 if (PTR_ERR(lp->supply) == -EPROBE_DEFER) 470 return -EPROBE_DEFER; 471 lp->supply = NULL; 472 } 473 474 lp->enable = devm_regulator_get_optional(dev, "enable"); 475 if (IS_ERR(lp->enable)) { 476 ret = PTR_ERR(lp->enable); 477 if (ret == -ENODEV) { 478 lp->enable = NULL; 479 } else { 480 return dev_err_probe(dev, ret, "getting enable regulator\n"); 481 } 482 } 483 484 if (lp->supply) { 485 ret = regulator_enable(lp->supply); 486 if (ret < 0) { 487 dev_err(dev, "failed to enable supply: %d\n", ret); 488 return ret; 489 } 490 } 491 492 if (lp->enable) { 493 ret = regulator_enable(lp->enable); 494 if (ret < 0) { 495 dev_err(dev, "failed to enable vddio: %d\n", ret); 496 goto disable_supply; 497 } 498 499 /* 500 * LP8555 datasheet says t_RESPONSE (time between VDDIO and 501 * I2C) is 1ms. 502 */ 503 usleep_range(1000, 2000); 504 } 505 506 i2c_set_clientdata(cl, lp); 507 508 ret = lp855x_configure(lp); 509 if (ret) { 510 dev_err(dev, "device config err: %d", ret); 511 goto disable_vddio; 512 } 513 514 ret = lp855x_backlight_register(lp); 515 if (ret) { 516 dev_err(dev, "failed to register backlight. err: %d\n", ret); 517 goto disable_vddio; 518 } 519 520 ret = sysfs_create_group(&dev->kobj, &lp855x_attr_group); 521 if (ret) { 522 dev_err(dev, "failed to register sysfs. err: %d\n", ret); 523 goto disable_vddio; 524 } 525 526 backlight_update_status(lp->bl); 527 528 return 0; 529 530disable_vddio: 531 if (lp->enable) 532 regulator_disable(lp->enable); 533disable_supply: 534 if (lp->supply) 535 regulator_disable(lp->supply); 536 537 return ret; 538} 539 540static int lp855x_remove(struct i2c_client *cl) 541{ 542 struct lp855x *lp = i2c_get_clientdata(cl); 543 544 lp->bl->props.brightness = 0; 545 backlight_update_status(lp->bl); 546 if (lp->enable) 547 regulator_disable(lp->enable); 548 if (lp->supply) 549 regulator_disable(lp->supply); 550 sysfs_remove_group(&lp->dev->kobj, &lp855x_attr_group); 551 552 return 0; 553} 554 555static const struct of_device_id lp855x_dt_ids[] = { 556 { .compatible = "ti,lp8550", }, 557 { .compatible = "ti,lp8551", }, 558 { .compatible = "ti,lp8552", }, 559 { .compatible = "ti,lp8553", }, 560 { .compatible = "ti,lp8555", }, 561 { .compatible = "ti,lp8556", }, 562 { .compatible = "ti,lp8557", }, 563 { } 564}; 565MODULE_DEVICE_TABLE(of, lp855x_dt_ids); 566 567static const struct i2c_device_id lp855x_ids[] = { 568 {"lp8550", LP8550}, 569 {"lp8551", LP8551}, 570 {"lp8552", LP8552}, 571 {"lp8553", LP8553}, 572 {"lp8555", LP8555}, 573 {"lp8556", LP8556}, 574 {"lp8557", LP8557}, 575 { } 576}; 577MODULE_DEVICE_TABLE(i2c, lp855x_ids); 578 579#ifdef CONFIG_ACPI 580static const struct acpi_device_id lp855x_acpi_match[] = { 581 /* Xiaomi specific HID used for the LP8556 on the Mi Pad 2 */ 582 { "XMCC0001", LP8556 }, 583 { } 584}; 585MODULE_DEVICE_TABLE(acpi, lp855x_acpi_match); 586#endif 587 588static struct i2c_driver lp855x_driver = { 589 .driver = { 590 .name = "lp855x", 591 .of_match_table = of_match_ptr(lp855x_dt_ids), 592 .acpi_match_table = ACPI_PTR(lp855x_acpi_match), 593 }, 594 .probe = lp855x_probe, 595 .remove = lp855x_remove, 596 .id_table = lp855x_ids, 597}; 598 599module_i2c_driver(lp855x_driver); 600 601MODULE_DESCRIPTION("Texas Instruments LP855x Backlight driver"); 602MODULE_AUTHOR("Milo Kim <milo.kim@ti.com>"); 603MODULE_LICENSE("GPL");