Thomas Zimmermann 9612dd
From ec961cf3241153e0f27d850f1bf0f172e7d27a21 Mon Sep 17 00:00:00 2001
Thomas Zimmermann 9612dd
From: Marijn Suijten <marijn.suijten@somainline.org>
Thomas Zimmermann 9612dd
Date: Mon, 15 Nov 2021 21:34:59 +0100
Thomas Zimmermann 9612dd
Subject: backlight: qcom-wled: Respect enabled-strings in set_brightness
Thomas Zimmermann 9612dd
Git-commit: ec961cf3241153e0f27d850f1bf0f172e7d27a21
Thomas Zimmermann 9612dd
Patch-mainline: v5.17-rc1
Thomas Zimmermann 9612dd
References: bsc#1152489
Thomas Zimmermann 9612dd
Thomas Zimmermann 9612dd
The hardware is capable of controlling any non-contiguous sequence of
Thomas Zimmermann 9612dd
LEDs specified in the DT using qcom,enabled-strings as u32
Thomas Zimmermann 9612dd
array, and this also follows from the DT-bindings documentation.  The
Thomas Zimmermann 9612dd
numbers specified in this array represent indices of the LED strings
Thomas Zimmermann 9612dd
that are to be enabled and disabled.
Thomas Zimmermann 9612dd
Thomas Zimmermann 9612dd
Its value is appropriately used to setup and enable string modules, but
Thomas Zimmermann 9612dd
completely disregarded in the set_brightness paths which only iterate
Thomas Zimmermann 9612dd
over the number of strings linearly.
Thomas Zimmermann 9612dd
Take an example where only string 2 is enabled with
Thomas Zimmermann 9612dd
qcom,enabled_strings=<2>: this string is appropriately enabled but
Thomas Zimmermann 9612dd
subsequent brightness changes would have only touched the zero'th
Thomas Zimmermann 9612dd
brightness register because num_strings is 1 here.  This is simply
Thomas Zimmermann 9612dd
addressed by looking up the string for this index in the enabled_strings
Thomas Zimmermann 9612dd
array just like the other codepaths that iterate over num_strings.
Thomas Zimmermann 9612dd
Thomas Zimmermann 9612dd
Likewise enabled_strings is now also used in the autodetection path for
Thomas Zimmermann 9612dd
consistent behaviour: when a list of strings is specified in DT only
Thomas Zimmermann 9612dd
those strings will be probed for autodetection, analogous to how the
Thomas Zimmermann 9612dd
number of strings that need to be probed is already bound by
Thomas Zimmermann 9612dd
qcom,num-strings.  After all autodetection uses the set_brightness
Thomas Zimmermann 9612dd
helpers to set an initial value, which could otherwise end up changing
Thomas Zimmermann 9612dd
brightness on a different set of strings.
Thomas Zimmermann 9612dd
Thomas Zimmermann 9612dd
Fixes: 775d2ffb4af6 ("backlight: qcom-wled: Restructure the driver for WLED3")
Thomas Zimmermann 9612dd
Fixes: 03b2b5e86986 ("backlight: qcom-wled: Add support for WLED4 peripheral")
Thomas Zimmermann 9612dd
Signed-off-by: Marijn Suijten <marijn.suijten@somainline.org>
Thomas Zimmermann 9612dd
Reviewed-by: AngeloGioacchino Del Regno <angelogioacchino.delregno@somainline.org>
Thomas Zimmermann 9612dd
Reviewed-by: Daniel Thompson <daniel.thompson@linaro.org>
Thomas Zimmermann 9612dd
Signed-off-by: Lee Jones <lee.jones@linaro.org>
Thomas Zimmermann 9612dd
Link: https://lore.kernel.org/r/20211115203459.1634079-10-marijn.suijten@somainline.org
Thomas Zimmermann 9612dd
Acked-by: Thomas Zimmermann <tzimmermann@suse.de>
Thomas Zimmermann 9612dd
---
Thomas Zimmermann 9612dd
 drivers/video/backlight/qcom-wled.c |   24 ++++++++++++++----------
Thomas Zimmermann 9612dd
 1 file changed, 14 insertions(+), 10 deletions(-)
Thomas Zimmermann 9612dd
Thomas Zimmermann 9612dd
--- a/drivers/video/backlight/qcom-wled.c
Thomas Zimmermann 9612dd
+++ b/drivers/video/backlight/qcom-wled.c
Thomas Zimmermann 9612dd
@@ -238,7 +238,8 @@ static int wled3_set_brightness(struct w
Thomas Zimmermann 9612dd
 
Thomas Zimmermann 9612dd
 	for (i = 0;  i < wled->cfg.num_strings; ++i) {
Thomas Zimmermann 9612dd
 		rc = regmap_bulk_write(wled->regmap, wled->ctrl_addr +
Thomas Zimmermann 9612dd
-				       WLED3_SINK_REG_BRIGHT(i), v, 2);
Thomas Zimmermann 9612dd
+				       WLED3_SINK_REG_BRIGHT(wled->cfg.enabled_strings[i]),
Thomas Zimmermann 9612dd
+				       v, 2);
Thomas Zimmermann 9612dd
 		if (rc < 0)
Thomas Zimmermann 9612dd
 			return rc;
Thomas Zimmermann 9612dd
 	}
Thomas Zimmermann 9612dd
@@ -261,7 +262,8 @@ static int wled4_set_brightness(struct w
Thomas Zimmermann 9612dd
 
Thomas Zimmermann 9612dd
 	for (i = 0;  i < wled->cfg.num_strings; ++i) {
Thomas Zimmermann 9612dd
 		rc = regmap_bulk_write(wled->regmap, wled->sink_addr +
Thomas Zimmermann 9612dd
-				       WLED4_SINK_REG_BRIGHT(i), v, 2);
Thomas Zimmermann 9612dd
+				       WLED4_SINK_REG_BRIGHT(wled->cfg.enabled_strings[i]),
Thomas Zimmermann 9612dd
+				       v, 2);
Thomas Zimmermann 9612dd
 		if (rc < 0)
Thomas Zimmermann 9612dd
 			return rc;
Thomas Zimmermann 9612dd
 	}
Thomas Zimmermann 9612dd
@@ -559,7 +561,7 @@ unlock_mutex:
Thomas Zimmermann 9612dd
 
Thomas Zimmermann 9612dd
 static void wled_auto_string_detection(struct wled *wled)
Thomas Zimmermann 9612dd
 {
Thomas Zimmermann 9612dd
-	int rc = 0, i, delay_time_us;
Thomas Zimmermann 9612dd
+	int rc = 0, i, j, delay_time_us;
Thomas Zimmermann 9612dd
 	u32 sink_config = 0;
Thomas Zimmermann 9612dd
 	u8 sink_test = 0, sink_valid = 0, val;
Thomas Zimmermann 9612dd
 	bool fault_set;
Thomas Zimmermann 9612dd
@@ -606,14 +608,15 @@ static void wled_auto_string_detection(s
Thomas Zimmermann 9612dd
 
Thomas Zimmermann 9612dd
 	/* Iterate through the strings one by one */
Thomas Zimmermann 9612dd
 	for (i = 0; i < wled->cfg.num_strings; i++) {
Thomas Zimmermann 9612dd
-		sink_test = BIT((WLED4_SINK_REG_CURR_SINK_SHFT + i));
Thomas Zimmermann 9612dd
+		j = wled->cfg.enabled_strings[i];
Thomas Zimmermann 9612dd
+		sink_test = BIT((WLED4_SINK_REG_CURR_SINK_SHFT + j));
Thomas Zimmermann 9612dd
 
Thomas Zimmermann 9612dd
 		/* Enable feedback control */
Thomas Zimmermann 9612dd
 		rc = regmap_write(wled->regmap, wled->ctrl_addr +
Thomas Zimmermann 9612dd
-				  WLED3_CTRL_REG_FEEDBACK_CONTROL, i + 1);
Thomas Zimmermann 9612dd
+				  WLED3_CTRL_REG_FEEDBACK_CONTROL, j + 1);
Thomas Zimmermann 9612dd
 		if (rc < 0) {
Thomas Zimmermann 9612dd
 			dev_err(wled->dev, "Failed to enable feedback for SINK %d rc = %d\n",
Thomas Zimmermann 9612dd
-				i + 1, rc);
Thomas Zimmermann 9612dd
+				j + 1, rc);
Thomas Zimmermann 9612dd
 			goto failed_detect;
Thomas Zimmermann 9612dd
 		}
Thomas Zimmermann 9612dd
 
Thomas Zimmermann 9612dd
@@ -622,7 +625,7 @@ static void wled_auto_string_detection(s
Thomas Zimmermann 9612dd
 				  WLED4_SINK_REG_CURR_SINK, sink_test);
Thomas Zimmermann 9612dd
 		if (rc < 0) {
Thomas Zimmermann 9612dd
 			dev_err(wled->dev, "Failed to configure SINK %d rc=%d\n",
Thomas Zimmermann 9612dd
-				i + 1, rc);
Thomas Zimmermann 9612dd
+				j + 1, rc);
Thomas Zimmermann 9612dd
 			goto failed_detect;
Thomas Zimmermann 9612dd
 		}
Thomas Zimmermann 9612dd
 
Thomas Zimmermann 9612dd
@@ -649,7 +652,7 @@ static void wled_auto_string_detection(s
Thomas Zimmermann 9612dd
 
Thomas Zimmermann 9612dd
 		if (fault_set)
Thomas Zimmermann 9612dd
 			dev_dbg(wled->dev, "WLED OVP fault detected with SINK %d\n",
Thomas Zimmermann 9612dd
-				i + 1);
Thomas Zimmermann 9612dd
+				j + 1);
Thomas Zimmermann 9612dd
 		else
Thomas Zimmermann 9612dd
 			sink_valid |= sink_test;
Thomas Zimmermann 9612dd
 
Thomas Zimmermann 9612dd
@@ -689,15 +692,16 @@ static void wled_auto_string_detection(s
Thomas Zimmermann 9612dd
 	/* Enable valid sinks */
Thomas Zimmermann 9612dd
 	if (wled->version == 4) {
Thomas Zimmermann 9612dd
 		for (i = 0; i < wled->cfg.num_strings; i++) {
Thomas Zimmermann 9612dd
+			j = wled->cfg.enabled_strings[i];
Thomas Zimmermann 9612dd
 			if (sink_config &
Thomas Zimmermann 9612dd
-			    BIT(WLED4_SINK_REG_CURR_SINK_SHFT + i))
Thomas Zimmermann 9612dd
+			    BIT(WLED4_SINK_REG_CURR_SINK_SHFT + j))
Thomas Zimmermann 9612dd
 				val = WLED4_SINK_REG_STR_MOD_MASK;
Thomas Zimmermann 9612dd
 			else
Thomas Zimmermann 9612dd
 				/* Disable modulator_en for unused sink */
Thomas Zimmermann 9612dd
 				val = 0;
Thomas Zimmermann 9612dd
 
Thomas Zimmermann 9612dd
 			rc = regmap_write(wled->regmap, wled->sink_addr +
Thomas Zimmermann 9612dd
-					  WLED4_SINK_REG_STR_MOD_EN(i), val);
Thomas Zimmermann 9612dd
+					  WLED4_SINK_REG_STR_MOD_EN(j), val);
Thomas Zimmermann 9612dd
 			if (rc < 0) {
Thomas Zimmermann 9612dd
 				dev_err(wled->dev, "Failed to configure MODULATOR_EN rc=%d\n",
Thomas Zimmermann 9612dd
 					rc);