History

backlight: lm3630a: Add firmware node support

Add fwnode support to the lm3630a driver and optionally allow configuring the label, default brightness level, and maximum brightness level. The two outputs can be controlled by bank A and B independently or bank A can control both outputs. If the platform data was not configured, then the driver defaults to enabling both banks. This patch changes the default value to disable both banks before parsing the firmware node so that just a single bank can be enabled if desired. There are no in-tree users of this driver. Driver was tested on a LG Nexus 5 (hammerhead) phone.

Brian Masney committed 7 years ago

Commit 8fbce8e1 parent 32fcb752 files · +148 −5Browse files

Unified · Split

2 files
  1. drivers/video/backlight/lm3630a_bl.c +144 −5
  2. include/linux/platform_data/lm3630a_bl.h +4 −0
drivers/video/backlight/lm3630a_bl.c+144−5
@@ -35,6 +35,14 @@ · 34 unmodified lines
3535 #define REG_MAX 0x50
3636
3737 #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+
3846 struct lm3630a_chip {
3947 struct device *dev;
4048 struct delayed_work work;
@@ -329,15 +337,17 @@ static const struct backlight_ops lm3630a_bank_b_ops = { · 288 unmodified lines
329337
330338 static int lm3630a_backlight_register(struct lm3630a_chip *pchip)
331339 {
332− struct backlight_properties props;
333340 struct lm3630a_platform_data *pdata = pchip->pdata;
341+ struct backlight_properties props;
342+ const char *label;
334343
335344 props.type = BACKLIGHT_RAW;
336345 if (pdata->leda_ctrl != LM3630A_LEDA_DISABLE) {
337346 props.brightness = pdata->leda_init_brt;
338347 props.max_brightness = pdata->leda_max_brt;
348+ label = pdata->leda_label ? pdata->leda_label : "lm3630a_leda";
339349 pchip->bleda =
340− devm_backlight_device_register(pchip->dev, "lm3630a_leda",
350+ devm_backlight_device_register(pchip->dev, label,
341351 pchip->dev, pchip,
342352 &lm3630a_bank_a_ops, &props);
343353 if (IS_ERR(pchip->bleda))
@@ -348,8 +358,9 @@ static int lm3630a_backlight_register(struct lm3630a_chip *pchip) · 4 unmodified lines
348358 (pdata->ledb_ctrl != LM3630A_LEDB_ON_A)) {
349359 props.brightness = pdata->ledb_init_brt;
350360 props.max_brightness = pdata->ledb_max_brt;
361+ label = pdata->ledb_label ? pdata->ledb_label : "lm3630a_ledb";
351362 pchip->bledb =
352− devm_backlight_device_register(pchip->dev, "lm3630a_ledb",
363+ devm_backlight_device_register(pchip->dev, label,
353364 pchip->dev, pchip,
354365 &lm3630a_bank_b_ops, &props);
355366 if (IS_ERR(pchip->bledb))
@@ -364,6 +375,123 @@ static const struct regmap_config lm3630a_regmap = { · 8 unmodified lines
364375 .max_register = REG_MAX,
365376 };
366377
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+
367495 static int lm3630a_probe(struct i2c_client *client,
368496 const struct i2c_device_id *id)
369497 {
@@ -396,13 +524,18 @@ static int lm3630a_probe(struct i2c_client *client, · 26 unmodified lines
396524 GFP_KERNEL);
397525 if (pdata == NULL)
398526 return -ENOMEM;
527+
399528 /* default values */
400− pdata->leda_ctrl = LM3630A_LEDA_ENABLE;
401− pdata->ledb_ctrl = LM3630A_LEDB_ENABLE;
402529 pdata->leda_max_brt = LM3630A_MAX_BRIGHTNESS;
403530 pdata->ledb_max_brt = LM3630A_MAX_BRIGHTNESS;
404531 pdata->leda_init_brt = LM3630A_MAX_BRIGHTNESS;
405532 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+ }
406539 }
407540 pchip->pdata = pdata;
408541
@@ -470,11 +603,17 @@ static const struct i2c_device_id lm3630a_id[] = { · 61 unmodified lines
470603 {}
471604 };
472605
606+static const struct of_device_id lm3630a_match_table[] = {
607+ { .compatible = "ti,lm3630a", },
608+ { },
609+};
610+
473611 MODULE_DEVICE_TABLE(i2c, lm3630a_id);
474612
475613 static struct i2c_driver lm3630a_i2c_driver = {
476614 .driver = {
477615 .name = LM3630A_NAME,
616+ .of_match_table = lm3630a_match_table,
478617 },
479618 .probe = lm3630a_probe,
480619 .remove = lm3630a_remove,
include/linux/platform_data/lm3630a_bl.h+4−0
@@ -38,9 +38,11 @@ enum lm3630a_ledb_ctrl { · 37 unmodified lines
3838
3939 #define LM3630A_MAX_BRIGHTNESS 255
4040 /*
41+ *@leda_label : optional led a label.
4142 *@leda_init_brt : led a init brightness. 4~255
4243 *@leda_max_brt : led a max brightness. 4~255
4344 *@leda_ctrl : led a disable, enable linear, enable exponential
45+ *@ledb_label : optional led b label.
4446 *@ledb_init_brt : led b init brightness. 4~255
4547 *@ledb_max_brt : led b max brightness. 4~255
4648 *@ledb_ctrl : led b disable, enable linear, enable exponential
@@ -50,10 +52,12 @@ enum lm3630a_ledb_ctrl { · 3 unmodified lines
5052 struct lm3630a_platform_data {
5153
5254 /* led a config. */
55+ const char *leda_label;
5356 int leda_init_brt;
5457 int leda_max_brt;
5558 enum lm3630a_leda_ctrl leda_ctrl;
5659 /* led b config. */
60+ const char *ledb_label;
5761 int ledb_init_brt;
5862 int ledb_max_brt;
5963 enum lm3630a_ledb_ctrl ledb_ctrl;

Keyboard shortcuts

General

Show keyboard shortcuts
?
Focus the current search
/

Issues and pull requests

Open filters
f

Issues, pull requests and Inbox

Select next item
j↓
Select previous item
k↑
Open selected item
Enter
Dismiss filters or clear selection
Esc

Repository code

Go to file
t