diff options
| -rw-r--r-- | drivers/video/backlight/lm3630a_bl.c | 149 | ||||
| -rw-r--r-- | include/linux/platform_data/lm3630a_bl.h | 4 |
2 files changed, 148 insertions, 5 deletions
diff --git a/drivers/video/backlight/lm3630a_bl.c b/drivers/video/backlight/lm3630a_bl.c index ef2553f452ca..75d996490cf0 100644 --- a/drivers/video/backlight/lm3630a_bl.c +++ b/drivers/video/backlight/lm3630a_bl.c | |||
| @@ -35,6 +35,14 @@ | |||
| 35 | #define REG_MAX 0x50 | 35 | #define REG_MAX 0x50 |
| 36 | 36 | ||
| 37 | #define INT_DEBOUNCE_MSEC 10 | 37 | #define INT_DEBOUNCE_MSEC 10 |
| 38 | |||
| 39 | #define LM3630A_BANK_0 0 | ||
| 40 | #define LM3630A_BANK_1 1 | ||
| 41 | |||
| 42 | #define LM3630A_NUM_SINKS 2 | ||
| 43 | #define LM3630A_SINK_0 0 | ||
| 44 | #define LM3630A_SINK_1 1 | ||
| 45 | |||
| 38 | struct lm3630a_chip { | 46 | struct lm3630a_chip { |
| 39 | struct device *dev; | 47 | struct device *dev; |
| 40 | struct delayed_work work; | 48 | struct delayed_work work; |
| @@ -329,15 +337,17 @@ static const struct backlight_ops lm3630a_bank_b_ops = { | |||
| 329 | 337 | ||
| 330 | static int lm3630a_backlight_register(struct lm3630a_chip *pchip) | 338 | static int lm3630a_backlight_register(struct lm3630a_chip *pchip) |
| 331 | { | 339 | { |
| 332 | struct backlight_properties props; | ||
| 333 | struct lm3630a_platform_data *pdata = pchip->pdata; | 340 | struct lm3630a_platform_data *pdata = pchip->pdata; |
| 341 | struct backlight_properties props; | ||
| 342 | const char *label; | ||
| 334 | 343 | ||
| 335 | props.type = BACKLIGHT_RAW; | 344 | props.type = BACKLIGHT_RAW; |
| 336 | if (pdata->leda_ctrl != LM3630A_LEDA_DISABLE) { | 345 | if (pdata->leda_ctrl != LM3630A_LEDA_DISABLE) { |
| 337 | props.brightness = pdata->leda_init_brt; | 346 | props.brightness = pdata->leda_init_brt; |
| 338 | props.max_brightness = pdata->leda_max_brt; | 347 | props.max_brightness = pdata->leda_max_brt; |
| 348 | label = pdata->leda_label ? pdata->leda_label : "lm3630a_leda"; | ||
| 339 | pchip->bleda = | 349 | pchip->bleda = |
| 340 | devm_backlight_device_register(pchip->dev, "lm3630a_leda", | 350 | devm_backlight_device_register(pchip->dev, label, |
| 341 | pchip->dev, pchip, | 351 | pchip->dev, pchip, |
| 342 | &lm3630a_bank_a_ops, &props); | 352 | &lm3630a_bank_a_ops, &props); |
| 343 | if (IS_ERR(pchip->bleda)) | 353 | if (IS_ERR(pchip->bleda)) |
| @@ -348,8 +358,9 @@ static int lm3630a_backlight_register(struct lm3630a_chip *pchip) | |||
| 348 | (pdata->ledb_ctrl != LM3630A_LEDB_ON_A)) { | 358 | (pdata->ledb_ctrl != LM3630A_LEDB_ON_A)) { |
| 349 | props.brightness = pdata->ledb_init_brt; | 359 | props.brightness = pdata->ledb_init_brt; |
| 350 | props.max_brightness = pdata->ledb_max_brt; | 360 | props.max_brightness = pdata->ledb_max_brt; |
| 361 | label = pdata->ledb_label ? pdata->ledb_label : "lm3630a_ledb"; | ||
| 351 | pchip->bledb = | 362 | pchip->bledb = |
| 352 | devm_backlight_device_register(pchip->dev, "lm3630a_ledb", | 363 | devm_backlight_device_register(pchip->dev, label, |
| 353 | pchip->dev, pchip, | 364 | pchip->dev, pchip, |
| 354 | &lm3630a_bank_b_ops, &props); | 365 | &lm3630a_bank_b_ops, &props); |
| 355 | if (IS_ERR(pchip->bledb)) | 366 | if (IS_ERR(pchip->bledb)) |
| @@ -364,6 +375,123 @@ static const struct regmap_config lm3630a_regmap = { | |||
| 364 | .max_register = REG_MAX, | 375 | .max_register = REG_MAX, |
| 365 | }; | 376 | }; |
| 366 | 377 | ||
| 378 | static int lm3630a_parse_led_sources(struct fwnode_handle *node, | ||
| 379 | int default_led_sources) | ||
| 380 | { | ||
| 381 | u32 sources[LM3630A_NUM_SINKS]; | ||
| 382 | int ret, num_sources, i; | ||
| 383 | |||
| 384 | num_sources = fwnode_property_read_u32_array(node, "led-sources", NULL, | ||
| 385 | 0); | ||
| 386 | if (num_sources < 0) | ||
| 387 | return default_led_sources; | ||
| 388 | else if (num_sources > ARRAY_SIZE(sources)) | ||
| 389 | return -EINVAL; | ||
| 390 | |||
| 391 | ret = fwnode_property_read_u32_array(node, "led-sources", sources, | ||
| 392 | num_sources); | ||
| 393 | if (ret) | ||
| 394 | return ret; | ||
| 395 | |||
| 396 | for (i = 0; i < num_sources; i++) { | ||
| 397 | if (sources[i] < LM3630A_SINK_0 || sources[i] > LM3630A_SINK_1) | ||
| 398 | return -EINVAL; | ||
| 399 | |||
| 400 | ret |= BIT(sources[i]); | ||
| 401 | } | ||
| 402 | |||
| 403 | return ret; | ||
| 404 | } | ||
| 405 | |||
| 406 | static int lm3630a_parse_bank(struct lm3630a_platform_data *pdata, | ||
| 407 | struct fwnode_handle *node, int *seen_led_sources) | ||
| 408 | { | ||
| 409 | int led_sources, ret; | ||
| 410 | const char *label; | ||
| 411 | u32 bank, val; | ||
| 412 | bool linear; | ||
| 413 | |||
| 414 | ret = fwnode_property_read_u32(node, "reg", &bank); | ||
| 415 | if (ret) | ||
| 416 | return ret; | ||
| 417 | |||
| 418 | if (bank < LM3630A_BANK_0 || bank > LM3630A_BANK_1) | ||
| 419 | return -EINVAL; | ||
| 420 | |||
| 421 | led_sources = lm3630a_parse_led_sources(node, BIT(bank)); | ||
| 422 | if (led_sources < 0) | ||
| 423 | return led_sources; | ||
| 424 | |||
| 425 | if (*seen_led_sources & led_sources) | ||
| 426 | return -EINVAL; | ||
| 427 | |||
| 428 | *seen_led_sources |= led_sources; | ||
| 429 | |||
| 430 | linear = fwnode_property_read_bool(node, | ||
| 431 | "ti,linear-mapping-mode"); | ||
| 432 | if (bank) { | ||
| 433 | if (led_sources & BIT(LM3630A_SINK_0) || | ||
| 434 | !(led_sources & BIT(LM3630A_SINK_1))) | ||
| 435 | return -EINVAL; | ||
| 436 | |||
| 437 | pdata->ledb_ctrl = linear ? | ||
| 438 | LM3630A_LEDB_ENABLE_LINEAR : | ||
| 439 | LM3630A_LEDB_ENABLE; | ||
| 440 | } else { | ||
| 441 | if (!(led_sources & BIT(LM3630A_SINK_0))) | ||
| 442 | return -EINVAL; | ||
| 443 | |||
| 444 | pdata->leda_ctrl = linear ? | ||
| 445 | LM3630A_LEDA_ENABLE_LINEAR : | ||
| 446 | LM3630A_LEDA_ENABLE; | ||
| 447 | |||
| 448 | if (led_sources & BIT(LM3630A_SINK_1)) | ||
| 449 | pdata->ledb_ctrl = LM3630A_LEDB_ON_A; | ||
| 450 | } | ||
| 451 | |||
| 452 | ret = fwnode_property_read_string(node, "label", &label); | ||
| 453 | if (!ret) { | ||
| 454 | if (bank) | ||
| 455 | pdata->ledb_label = label; | ||
| 456 | else | ||
| 457 | pdata->leda_label = label; | ||
| 458 | } | ||
| 459 | |||
| 460 | ret = fwnode_property_read_u32(node, "default-brightness", | ||
| 461 | &val); | ||
| 462 | if (!ret) { | ||
| 463 | if (bank) | ||
| 464 | pdata->ledb_init_brt = val; | ||
| 465 | else | ||
| 466 | pdata->leda_init_brt = val; | ||
| 467 | } | ||
| 468 | |||
| 469 | ret = fwnode_property_read_u32(node, "max-brightness", &val); | ||
| 470 | if (!ret) { | ||
| 471 | if (bank) | ||
| 472 | pdata->ledb_max_brt = val; | ||
| 473 | else | ||
| 474 | pdata->leda_max_brt = val; | ||
| 475 | } | ||
| 476 | |||
| 477 | return 0; | ||
| 478 | } | ||
| 479 | |||
| 480 | static int lm3630a_parse_node(struct lm3630a_chip *pchip, | ||
| 481 | struct lm3630a_platform_data *pdata) | ||
| 482 | { | ||
| 483 | int ret = -ENODEV, seen_led_sources = 0; | ||
| 484 | struct fwnode_handle *node; | ||
| 485 | |||
| 486 | device_for_each_child_node(pchip->dev, node) { | ||
| 487 | ret = lm3630a_parse_bank(pdata, node, &seen_led_sources); | ||
| 488 | if (ret) | ||
| 489 | return ret; | ||
| 490 | } | ||
| 491 | |||
| 492 | return ret; | ||
| 493 | } | ||
| 494 | |||
| 367 | static int lm3630a_probe(struct i2c_client *client, | 495 | static int lm3630a_probe(struct i2c_client *client, |
| 368 | const struct i2c_device_id *id) | 496 | const struct i2c_device_id *id) |
| 369 | { | 497 | { |
| @@ -396,13 +524,18 @@ static int lm3630a_probe(struct i2c_client *client, | |||
| 396 | GFP_KERNEL); | 524 | GFP_KERNEL); |
| 397 | if (pdata == NULL) | 525 | if (pdata == NULL) |
| 398 | return -ENOMEM; | 526 | return -ENOMEM; |
| 527 | |||
| 399 | /* default values */ | 528 | /* default values */ |
| 400 | pdata->leda_ctrl = LM3630A_LEDA_ENABLE; | ||
| 401 | pdata->ledb_ctrl = LM3630A_LEDB_ENABLE; | ||
| 402 | pdata->leda_max_brt = LM3630A_MAX_BRIGHTNESS; | 529 | pdata->leda_max_brt = LM3630A_MAX_BRIGHTNESS; |
| 403 | pdata->ledb_max_brt = LM3630A_MAX_BRIGHTNESS; | 530 | pdata->ledb_max_brt = LM3630A_MAX_BRIGHTNESS; |
| 404 | pdata->leda_init_brt = LM3630A_MAX_BRIGHTNESS; | 531 | pdata->leda_init_brt = LM3630A_MAX_BRIGHTNESS; |
| 405 | pdata->ledb_init_brt = LM3630A_MAX_BRIGHTNESS; | 532 | pdata->ledb_init_brt = LM3630A_MAX_BRIGHTNESS; |
| 533 | |||
| 534 | rval = lm3630a_parse_node(pchip, pdata); | ||
| 535 | if (rval) { | ||
| 536 | dev_err(&client->dev, "fail : parse node\n"); | ||
| 537 | return rval; | ||
| 538 | } | ||
| 406 | } | 539 | } |
| 407 | pchip->pdata = pdata; | 540 | pchip->pdata = pdata; |
| 408 | 541 | ||
| @@ -470,11 +603,17 @@ static const struct i2c_device_id lm3630a_id[] = { | |||
| 470 | {} | 603 | {} |
| 471 | }; | 604 | }; |
| 472 | 605 | ||
| 606 | static const struct of_device_id lm3630a_match_table[] = { | ||
| 607 | { .compatible = "ti,lm3630a", }, | ||
| 608 | { }, | ||
| 609 | }; | ||
| 610 | |||
| 473 | MODULE_DEVICE_TABLE(i2c, lm3630a_id); | 611 | MODULE_DEVICE_TABLE(i2c, lm3630a_id); |
| 474 | 612 | ||
| 475 | static struct i2c_driver lm3630a_i2c_driver = { | 613 | static struct i2c_driver lm3630a_i2c_driver = { |
| 476 | .driver = { | 614 | .driver = { |
| 477 | .name = LM3630A_NAME, | 615 | .name = LM3630A_NAME, |
| 616 | .of_match_table = lm3630a_match_table, | ||
| 478 | }, | 617 | }, |
| 479 | .probe = lm3630a_probe, | 618 | .probe = lm3630a_probe, |
| 480 | .remove = lm3630a_remove, | 619 | .remove = lm3630a_remove, |
diff --git a/include/linux/platform_data/lm3630a_bl.h b/include/linux/platform_data/lm3630a_bl.h index 7538e38e270b..762e68956f31 100644 --- a/include/linux/platform_data/lm3630a_bl.h +++ b/include/linux/platform_data/lm3630a_bl.h | |||
| @@ -38,9 +38,11 @@ enum lm3630a_ledb_ctrl { | |||
| 38 | 38 | ||
| 39 | #define LM3630A_MAX_BRIGHTNESS 255 | 39 | #define LM3630A_MAX_BRIGHTNESS 255 |
| 40 | /* | 40 | /* |
| 41 | *@leda_label : optional led a label. | ||
| 41 | *@leda_init_brt : led a init brightness. 4~255 | 42 | *@leda_init_brt : led a init brightness. 4~255 |
| 42 | *@leda_max_brt : led a max brightness. 4~255 | 43 | *@leda_max_brt : led a max brightness. 4~255 |
| 43 | *@leda_ctrl : led a disable, enable linear, enable exponential | 44 | *@leda_ctrl : led a disable, enable linear, enable exponential |
| 45 | *@ledb_label : optional led b label. | ||
| 44 | *@ledb_init_brt : led b init brightness. 4~255 | 46 | *@ledb_init_brt : led b init brightness. 4~255 |
| 45 | *@ledb_max_brt : led b max brightness. 4~255 | 47 | *@ledb_max_brt : led b max brightness. 4~255 |
| 46 | *@ledb_ctrl : led b disable, enable linear, enable exponential | 48 | *@ledb_ctrl : led b disable, enable linear, enable exponential |
| @@ -50,10 +52,12 @@ enum lm3630a_ledb_ctrl { | |||
| 50 | struct lm3630a_platform_data { | 52 | struct lm3630a_platform_data { |
| 51 | 53 | ||
| 52 | /* led a config. */ | 54 | /* led a config. */ |
| 55 | const char *leda_label; | ||
| 53 | int leda_init_brt; | 56 | int leda_init_brt; |
| 54 | int leda_max_brt; | 57 | int leda_max_brt; |
| 55 | enum lm3630a_leda_ctrl leda_ctrl; | 58 | enum lm3630a_leda_ctrl leda_ctrl; |
| 56 | /* led b config. */ | 59 | /* led b config. */ |
| 60 | const char *ledb_label; | ||
| 57 | int ledb_init_brt; | 61 | int ledb_init_brt; |
| 58 | int ledb_max_brt; | 62 | int ledb_max_brt; |
| 59 | enum lm3630a_ledb_ctrl ledb_ctrl; | 63 | enum lm3630a_ledb_ctrl ledb_ctrl; |
