Add Control Bank to HVLED/LVLED muxing support based on the led-sources
defined in the device tree.

Signed-off-by: Svyatoslav Ryhel <[email protected]>
---
 drivers/leds/leds-lm3533.c          | 55 +++++++++++++++++++++++++++--
 drivers/video/backlight/lm3533_bl.c | 39 +++++++++++++++++++-
 2 files changed, 91 insertions(+), 3 deletions(-)

diff --git a/drivers/leds/leds-lm3533.c b/drivers/leds/leds-lm3533.c
index f6345bc1f443..c4eaf30880a1 100644
--- a/drivers/leds/leds-lm3533.c
+++ b/drivers/leds/leds-lm3533.c
@@ -7,6 +7,7 @@
  * Author: Johan Hovold <[email protected]>
  */
 
+#include <linux/bits.h>
 #include <linux/module.h>
 #include <linux/leds.h>
 #include <linux/mfd/core.h>
@@ -26,6 +27,12 @@
 #define LM3533_ALS_CHANNEL_LV_MIN      1
 #define LM3533_ALS_CHANNEL_LV_MAX      2
 
+#define LM3533_REG_OUTPUT_CONF1                        0x10
+#define   OUTPUT_CONF1_MASK                    GENMASK(7, 2)
+#define   OUTPUT_CONF1_SHIFT                   2
+#define LM3533_REG_OUTPUT_CONF2                        0x11
+#define   OUTPUT_CONF2_MASK                    GENMASK(3, 0)
+#define   OUTPUT_CONF2_SHIFT                   6
 #define LM3533_REG_CTRLBANK_BCONF_BASE         0x1b
 #define LM3533_REG_PATTERN_ENABLE              0x28
 #define LM3533_REG_PATTERN_LOW_TIME_BASE       0x71
@@ -40,7 +47,7 @@
 #define LM3533_REG_CTRLBANK_BCONF_ALS_CHANNEL_MASK     0x01
 
 #define LM3533_LED_FLAG_PATTERN_ENABLE         1
-
+#define LM3533_MAX_LEDS                                5
 
 struct lm3533_led {
        struct lm3533 *lm3533;
@@ -53,6 +60,9 @@ struct lm3533_led {
 
        u32 max_current;
        u32 pwm;
+
+       u32 num_leds;
+       u32 leds[LM3533_MAX_LEDS];
 };
 
 
@@ -639,7 +649,30 @@ static const struct attribute_group 
*lm3533_led_attribute_groups[] = {
 
 static int lm3533_led_setup(struct lm3533_led *led)
 {
-       int ret;
+       u32 output_cfg_shift = 0;
+       u32 output_cfg_val = 0;
+       int ret, i;
+
+       if (led->num_leds) {
+               for (i = 0; i < led->num_leds; i++) {
+                       output_cfg_shift = led->leds[i] * 2;
+                       output_cfg_val |= led->id << output_cfg_shift;
+               }
+
+               /* LVLED1, LVLED2 and LVLED3 */
+               ret = lm3533_update(led->lm3533, LM3533_REG_OUTPUT_CONF1,
+                                   output_cfg_val << OUTPUT_CONF1_SHIFT,
+                                   OUTPUT_CONF1_MASK);
+               if (ret)
+                       return ret;
+
+               /* LVLED4 and LVLED5 */
+               ret = lm3533_update(led->lm3533, LM3533_REG_OUTPUT_CONF1,
+                                   output_cfg_val >> OUTPUT_CONF2_SHIFT,
+                                   OUTPUT_CONF2_MASK);
+               if (ret)
+                       return ret;
+       }
 
        ret = lm3533_ctrlbank_set_max_current(&led->cb, led->max_current);
        if (ret)
@@ -713,6 +746,24 @@ static int lm3533_led_probe(struct platform_device *pdev)
        led->pwm = 0;
        device_property_read_u32(&pdev->dev, "ti,pwm-config-mask", &led->pwm);
 
+       led->num_leds = device_property_count_u32(&pdev->dev, "led-sources");
+
+       /*
+        * If led-sources property is not set then either this Control Bank uses
+        * its default LVLED or is not linked to any LVLED at all.
+        */
+       if (led->num_leds <= 0 || led->num_leds > LM3533_MAX_LEDS)
+               led->num_leds = 0;
+
+       if (led->num_leds > 0 && led->num_leds < LM3533_MAX_LEDS) {
+               ret = device_property_read_u32_array(&pdev->dev, "led-sources",
+                                                    led->leds, led->num_leds);
+               if (ret) {
+                       dev_err(&pdev->dev, "failed to get led-sources\n");
+                       goto err_deregister;
+               }
+       }
+
        ret = lm3533_led_setup(led);
        if (ret)
                goto err_deregister;
diff --git a/drivers/video/backlight/lm3533_bl.c 
b/drivers/video/backlight/lm3533_bl.c
index be9114b7e0ad..2898cb229643 100644
--- a/drivers/video/backlight/lm3533_bl.c
+++ b/drivers/video/backlight/lm3533_bl.c
@@ -7,6 +7,7 @@
  * Author: Johan Hovold <[email protected]>
  */
 
+#include <linux/bits.h>
 #include <linux/module.h>
 #include <linux/init.h>
 #include <linux/mod_devicetable.h>
@@ -21,9 +22,12 @@
 #define LM3533_HVCTRLBANK_COUNT                2
 #define LM3533_BL_MAX_BRIGHTNESS       255
 
+#define LM3533_REG_OUTPUT_CONF1                0x10
+#define   OUTPUT_CONF1_MASK            GENMASK(1, 0)
 #define LM3533_REG_CTRLBANK_AB_BCONF   0x1a
 #define   CTRLBANK_AB_BCONF_MODE(n)    BIT(2 * (n) + 1)
 
+#define LM3533_MAX_LED_STRINGS         2
 
 struct lm3533_bl {
        struct lm3533 *lm3533;
@@ -34,6 +38,9 @@ struct lm3533_bl {
        u32 max_current;
        u32 pwm;
        bool linear;
+
+       u32 num_leds;
+       u32 led_strings[LM3533_MAX_LED_STRINGS];
 };
 
 
@@ -248,7 +255,8 @@ static struct attribute_group lm3533_bl_attribute_group = {
 static int lm3533_bl_setup(struct lm3533_bl *bl)
 {
        int id = lm3533_bl_get_ctrlbank_id(bl);
-       int ret;
+       u32 output_cfg_val = 0;
+       int ret, i;
 
        ret = lm3533_update(bl->lm3533, LM3533_REG_CTRLBANK_AB_BCONF,
                            bl->linear ? CTRLBANK_AB_BCONF_MODE(id) : 0,
@@ -256,6 +264,16 @@ static int lm3533_bl_setup(struct lm3533_bl *bl)
        if (ret)
                return ret;
 
+       if (bl->num_leds) {
+               for (i = 0; i < bl->num_leds; i++)
+                       output_cfg_val |= id << bl->led_strings[i];
+
+               ret = lm3533_update(bl->lm3533, LM3533_REG_OUTPUT_CONF1,
+                                   output_cfg_val, OUTPUT_CONF1_MASK);
+               if (ret)
+                       return ret;
+       }
+
        ret = lm3533_ctrlbank_set_max_current(&bl->cb, bl->max_current);
        if (ret)
                return ret;
@@ -337,6 +355,25 @@ static int lm3533_bl_probe(struct platform_device *pdev)
        bl->linear = device_property_read_bool(&pdev->dev,
                                               "ti,linear-mapping-mode");
 
+       bl->num_leds = device_property_count_u32(&pdev->dev, "led-sources");
+
+       /*
+        * If led-sources property is not set then either this Control Bank uses
+        * its default HVLED or is not linked to any HVLED at all.
+        */
+       if (bl->num_leds <= 0 || bl->num_leds > LM3533_MAX_LED_STRINGS)
+               bl->num_leds = 0;
+
+       if (bl->num_leds > 0 && bl->num_leds < LM3533_MAX_LED_STRINGS) {
+               ret = device_property_read_u32_array(&pdev->dev, "led-sources",
+                                                    bl->led_strings,
+                                                    bl->num_leds);
+               if (ret) {
+                       dev_err(&pdev->dev, "failed to get led-sources\n");
+                       goto err_sysfs_remove;
+               }
+       }
+
        ret = lm3533_bl_setup(bl);
        if (ret)
                goto err_sysfs_remove;
-- 
2.51.0

Reply via email to