diff options
author | Kim, Milo <Milo.Kim@ti.com> | 2013-04-29 19:18:06 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2013-04-29 21:28:19 -0400 |
commit | 4add06645a0be0519030705e3076e1a5ceba7477 (patch) | |
tree | 1a1b55b7422981a0fb7b9f4ab20d3e097f64812b /drivers/video | |
parent | c365e59d47b75c5f288f7e63d95dc0c9abcfe516 (diff) |
backlight: lp855x: add a device tree structure
Enable supporting the DT structure of LP855x family devices. If the
platform data is NULL, the driver tries to parse a DT structure. Then,
the platform data is copied from the DT. Documentation is added as well.
Signed-off-by: Milo(Woogyom) Kim <milo.kim@ti.com>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Diffstat (limited to 'drivers/video')
-rw-r--r-- | drivers/video/backlight/lp855x_bl.c | 73 |
1 files changed, 71 insertions, 2 deletions
diff --git a/drivers/video/backlight/lp855x_bl.c b/drivers/video/backlight/lp855x_bl.c index f558f8f329e5..a0e1e02bdc2e 100644 --- a/drivers/video/backlight/lp855x_bl.c +++ b/drivers/video/backlight/lp855x_bl.c | |||
@@ -14,6 +14,7 @@ | |||
14 | #include <linux/i2c.h> | 14 | #include <linux/i2c.h> |
15 | #include <linux/backlight.h> | 15 | #include <linux/backlight.h> |
16 | #include <linux/err.h> | 16 | #include <linux/err.h> |
17 | #include <linux/of.h> | ||
17 | #include <linux/platform_data/lp855x.h> | 18 | #include <linux/platform_data/lp855x.h> |
18 | #include <linux/pwm.h> | 19 | #include <linux/pwm.h> |
19 | 20 | ||
@@ -338,15 +339,71 @@ static const struct attribute_group lp855x_attr_group = { | |||
338 | .attrs = lp855x_attributes, | 339 | .attrs = lp855x_attributes, |
339 | }; | 340 | }; |
340 | 341 | ||
342 | #ifdef CONFIG_OF | ||
343 | static int lp855x_parse_dt(struct device *dev, struct device_node *node) | ||
344 | { | ||
345 | struct lp855x_platform_data *pdata; | ||
346 | int rom_length; | ||
347 | |||
348 | if (!node) { | ||
349 | dev_err(dev, "no platform data\n"); | ||
350 | return -EINVAL; | ||
351 | } | ||
352 | |||
353 | pdata = devm_kzalloc(dev, sizeof(*pdata), GFP_KERNEL); | ||
354 | if (!pdata) | ||
355 | return -ENOMEM; | ||
356 | |||
357 | of_property_read_string(node, "bl-name", &pdata->name); | ||
358 | of_property_read_u8(node, "dev-ctrl", &pdata->device_control); | ||
359 | of_property_read_u8(node, "init-brt", &pdata->initial_brightness); | ||
360 | of_property_read_u32(node, "pwm-period", &pdata->period_ns); | ||
361 | |||
362 | /* Fill ROM platform data if defined */ | ||
363 | rom_length = of_get_child_count(node); | ||
364 | if (rom_length > 0) { | ||
365 | struct lp855x_rom_data *rom; | ||
366 | struct device_node *child; | ||
367 | int i = 0; | ||
368 | |||
369 | rom = devm_kzalloc(dev, sizeof(*rom) * rom_length, GFP_KERNEL); | ||
370 | if (!rom) | ||
371 | return -ENOMEM; | ||
372 | |||
373 | for_each_child_of_node(node, child) { | ||
374 | of_property_read_u8(child, "rom-addr", &rom[i].addr); | ||
375 | of_property_read_u8(child, "rom-val", &rom[i].val); | ||
376 | i++; | ||
377 | } | ||
378 | |||
379 | pdata->size_program = rom_length; | ||
380 | pdata->rom_data = &rom[0]; | ||
381 | } | ||
382 | |||
383 | dev->platform_data = pdata; | ||
384 | |||
385 | return 0; | ||
386 | } | ||
387 | #else | ||
388 | static int lp855x_parse_dt(struct device *dev, struct device_node *node) | ||
389 | { | ||
390 | return -EINVAL; | ||
391 | } | ||
392 | #endif | ||
393 | |||
341 | static int lp855x_probe(struct i2c_client *cl, const struct i2c_device_id *id) | 394 | static int lp855x_probe(struct i2c_client *cl, const struct i2c_device_id *id) |
342 | { | 395 | { |
343 | struct lp855x *lp; | 396 | struct lp855x *lp; |
344 | struct lp855x_platform_data *pdata = cl->dev.platform_data; | 397 | struct lp855x_platform_data *pdata = cl->dev.platform_data; |
398 | struct device_node *node = cl->dev.of_node; | ||
345 | int ret; | 399 | int ret; |
346 | 400 | ||
347 | if (!pdata) { | 401 | if (!pdata) { |
348 | dev_err(&cl->dev, "no platform data supplied\n"); | 402 | ret = lp855x_parse_dt(&cl->dev, node); |
349 | return -EINVAL; | 403 | if (ret < 0) |
404 | return ret; | ||
405 | |||
406 | pdata = cl->dev.platform_data; | ||
350 | } | 407 | } |
351 | 408 | ||
352 | if (!i2c_check_functionality(cl->adapter, I2C_FUNC_SMBUS_I2C_BLOCK)) | 409 | if (!i2c_check_functionality(cl->adapter, I2C_FUNC_SMBUS_I2C_BLOCK)) |
@@ -408,6 +465,17 @@ static int lp855x_remove(struct i2c_client *cl) | |||
408 | return 0; | 465 | return 0; |
409 | } | 466 | } |
410 | 467 | ||
468 | static const struct of_device_id lp855x_dt_ids[] = { | ||
469 | { .compatible = "ti,lp8550", }, | ||
470 | { .compatible = "ti,lp8551", }, | ||
471 | { .compatible = "ti,lp8552", }, | ||
472 | { .compatible = "ti,lp8553", }, | ||
473 | { .compatible = "ti,lp8556", }, | ||
474 | { .compatible = "ti,lp8557", }, | ||
475 | { } | ||
476 | }; | ||
477 | MODULE_DEVICE_TABLE(of, lp855x_dt_ids); | ||
478 | |||
411 | static const struct i2c_device_id lp855x_ids[] = { | 479 | static const struct i2c_device_id lp855x_ids[] = { |
412 | {"lp8550", LP8550}, | 480 | {"lp8550", LP8550}, |
413 | {"lp8551", LP8551}, | 481 | {"lp8551", LP8551}, |
@@ -422,6 +490,7 @@ MODULE_DEVICE_TABLE(i2c, lp855x_ids); | |||
422 | static struct i2c_driver lp855x_driver = { | 490 | static struct i2c_driver lp855x_driver = { |
423 | .driver = { | 491 | .driver = { |
424 | .name = "lp855x", | 492 | .name = "lp855x", |
493 | .of_match_table = of_match_ptr(lp855x_dt_ids), | ||
425 | }, | 494 | }, |
426 | .probe = lp855x_probe, | 495 | .probe = lp855x_probe, |
427 | .remove = lp855x_remove, | 496 | .remove = lp855x_remove, |