Skip to contentSkip to conversation

drm/bridge: lt9211: Add drive-strength-microamp DT property

PATCH Superseded Boerge Struempfel 4 participants 8 messages May 12 – May 13

Subsystems (4)

v1 of 2 Superseded Latest is v2 →

lore
Share & tools
lore
#0 lore raw

cover drm/bridge: lt9211: Add drive-strength-microamp DT property

The LT9211 LVDS TX output driver current is currently hardcoded to 0x8 (~25 uA). Some board layouts require a different drive strength to meet signal integrity requirements.

This series adds support for the standard 'drive-strength-microamp' DT property, allowing board DTs to select one of sixteen discrete current levels between 12 uA and 36 uA. The default preserves the existing behaviour.

Boerge Struempfel (2):
dt-bindings: display/bridge: lt9211: Add drive-strength-microamp
property
drm/bridge: lt9211: Add drive-strength-microamp DT property

 .../display/bridge/lontium,lt9211.yaml        |  7 +++++
 drivers/gpu/drm/bridge/lontium-lt9211.c       | 28 ++++++++++++++++++-
 2 files changed, 34 insertions(+), 1 deletion(-)
Signature · 1 line
2.54.0
#1 lore raw

PATCH 1/2 dt-bindings: display/bridge: lt9211: Add drive-strength-microamp property

Add the 'drive-strength-microamp' property to allow board DTs to configure the LT9211 LVDS TX output driver current. Sixteen discrete levels are supported, ranging from 12 uA to 36 uA. Defaults to 25 uA.

---
 .../devicetree/bindings/display/bridge/lontium,lt9211.yaml | 7 +++++++
 1 file changed, 7 insertions(+)
Documentation/devicetree/bindings/display/bridge/lontium,lt9211.yaml +7 -0
index 9a6e9b25d14a..381b69c761b8 100644
@@ -31,6 +31,13 @@ properties:
   vccio-supply:
     description: Regulator for 1.8V IO power.
 
+  drive-strength-microamp:
+    description:
+      LVDS TX output driver current. Sixteen discrete levels are supported,
+      corresponding to the following nominal values in microamps.
+    enum: [12, 14, 16, 17, 19, 20, 22, 23, 25, 27, 28, 30, 31, 33, 34, 36]
+    default: 25
+
   ports:
     $ref: /schemas/graph.yaml#/properties/ports
 
Signature · 1 line
2.54.0
Acked-by on v1 1/2
#2 lore raw

Re: [PATCH 1/2] dt-bindings: display/bridge: lt9211: Add drive-strength-microamp property

Quoted 5 lines · Boerge Struempfel

Add the 'drive-strength-microamp' property to allow board DTs to configure the LT9211 LVDS TX output driver current. Sixteen discrete levels are supported, ranging from 12 uA to 36 uA. Defaults to 25 uA.

pw-bot: not-applicable

#3 lore raw

Re: [PATCH 1/2] dt-bindings: display/bridge: lt9211: Add drive-strength-microamp property

In reply to Boerge Struempfel
Thank you for your contribution! Sashiko AI review found 1 potential issue(s) to consider: - [High] The values proposed for `drive-strength-microamp` are incorrect by two orders of magnitude…

Thank you for your contribution! Sashiko AI review found 1 potential issue(s) to consider:
- [High] The values proposed for drive-strength-microamp are incorrect by two orders of magnitude, exposing an internal reference current rather than the actual pad output current and violating standard DT unit semantics. --

commit 97454d8731d851d94cc1fb58faf0cb4d4b8ca94c
Author: Boerge Struempfel <[email protected]>

dt-bindings: display/bridge: lt9211: Add drive-strength-microamp property

This commit adds the drive-strength-microamp property to allow configuring the LT9211 LVDS TX output driver current. It supports 16 discrete levels ranging from 12 to 36 microamps, and sets a default of 25 microamps.

Quoted 3 lines
Documentation/devicetree/bindings/display/bridge/lontium,lt9211.yaml +0 -0

[ ... ]

Documentation/devicetree/bindings/display/bridge/lontium,lt9211.yaml properties: · line 38

Quoted 9 lines
Documentation/devicetree/bindings/display/bridge/lontium,lt9211.yaml +5 -0
@@ -31,6 +31,13 @@ properties:
   vccio-supply:
     description: Regulator for 1.8V IO power.
 
+  drive-strength-microamp:
+    description:
+      LVDS TX output driver current. Sixteen discrete levels are supported,
+      corresponding to the following nominal values in microamps.
+    enum: [12, 14, 16, 17, 19, 20, 22, 23, 25, 27, 28, 30, 31, 33, 34, 36]

Are these values exposing an internal reference current rather than the actual pad output current?

A subsequent commit in the series mentions that the hardware supports discrete current levels starting at 12.5 microamps with a step of 1.5625 microamps.

However, standard LVDS signaling typically requires a drive current of around 3.5 mA (3500 microamps) to produce the required 350 mV voltage swing across a standard 100-ohm termination. A 25 microamp drive current would only produce a 2.5 mV swing, which appears too small for an LVDS link.

Since drive-strength-microamp is a standard property, using it to expose an internal reference scale might permanently hardcode incorrect physical units into the device tree ABI.

Should the enum instead reflect the actual multiplied pad output current, which might be closer to the range of 1250 to 3600 microamps?

Quoted 4 lines
Documentation/devicetree/bindings/display/bridge/lontium,lt9211.yaml +2 -0
+    default: 25
+
   ports:
     $ref: /schemas/graph.yaml#/properties/ports
Signature · 1 line
Sashiko AI review · https://sashiko.dev/#/patchset/[email protected]?part=1
#4 lore raw

PATCH 2/2 drm/bridge: lt9211: Add drive-strength-microamp DT property

In reply to Boerge Struempfel

The LT9211 LVDS TX output driver current (RG_MLTX_HSDRV_ISEL) was previously hardcoded to 0x8 (~25 uA), which may not be optimal for all board layouts.

The hardware supports 16 discrete current levels starting at 12.5 uA with a step of 1.5625 uA. These are exposed as rounded integer microamp values in the lookup table.

Add support for the 'drive-strength-microamp' DT property. A lookup table maps the sixteen supported microamp values (12..36 uA) to the corresponding register field. Defaults to 25 uA when the property is absent, preserving the existing behaviour.

---
 drivers/gpu/drm/bridge/lontium-lt9211.c | 28 ++++++++++++++++++++++++-
 1 file changed, 27 insertions(+), 1 deletion(-)
drivers/gpu/drm/bridge/lontium-lt9211.c +27 -1
index 03fc8fd10f20..402c639ac515 100644
@@ -40,6 +40,11 @@
 /* DSI lane count - 0 means 4 lanes ; 1, 2, 3 means 1, 2, 3 lanes. */
 #define REG_DSI_LANE_COUNT(n)			((n) & 3)
 
+/* Maps register value (index) to drive-strength-microamp DT property value */
+static const u32 lt9211_hsdrv_microamp[] = {
+	12, 14, 16, 17, 19, 20, 22, 23, 25, 27, 28, 30, 31, 33, 34, 36
+};
+
 struct lt9211 {
 	struct drm_bridge		bridge;
 	struct device			*dev;
@@ -50,6 +55,7 @@ struct lt9211 {
 	struct regulator		*vccio;
 	bool				lvds_dual_link;
 	bool				lvds_dual_link_even_odd_swap;
+	u8				lvds_hsdrv_isel;
 };
 
 static const struct regmap_range lt9211_rw_ranges[] = {
@@ -374,7 +380,8 @@ static int lt9211_configure_tx(struct lt9211 *ctx, bool jeida,
 		/* BIT(7) is LVDS dual-port */
 		{ 0x823b, 0x38 | (ctx->lvds_dual_link ? BIT(7) : 0) },
 		{ 0x823e, 0x92 },
-		{ 0x823f, 0x48 },
+		/* bits 3:0: RG_MLTX_HSDRV_ISEL, LVDS TX driver current */
+		{ 0x823f, 0x40 | ctx->lvds_hsdrv_isel },
 		{ 0x8240, 0x31 },
 		{ 0x8243, 0x80 },
 		{ 0x8244, 0x00 },
@@ -629,7 +636,9 @@ static int lt9211_parse_dt(struct lt9211 *ctx)
 	struct device *dev = ctx->dev;
 	struct drm_panel *panel;
 	int dual_link;
+	u32 microamp;
 	int ret;
+	int i;
 
 	ctx->vccio = devm_regulator_get(dev, "vccio");
 	if (IS_ERR(ctx->vccio))
@@ -666,6 +675,23 @@ static int lt9211_parse_dt(struct lt9211 *ctx)
 
 	ctx->panel_bridge = panel_bridge;
 
+	ctx->lvds_hsdrv_isel = 8; /* default: 25 uA */
+	ret = of_property_read_u32(dev->of_node, "drive-strength-microamp",
+				   &microamp);
+	if (!ret) {
+		for (i = 0; i < ARRAY_SIZE(lt9211_hsdrv_microamp); i++) {
+			if (lt9211_hsdrv_microamp[i] == microamp) {
+				ctx->lvds_hsdrv_isel = i;
+				break;
+			}
+		}
+		if (i == ARRAY_SIZE(lt9211_hsdrv_microamp)) {
+			dev_err(dev, "Invalid drive-strength-microamp value %u\n",
+				microamp);
+			return -EINVAL;
+		}
+	}
+
 	return 0;
 }
 
Signature · 1 line
2.54.0
#5 lore raw

drivers/gpu/drm/bridge/lontium-lt9211.c line 44

Quoted 2 lines · Boerge Struempfel
drivers/gpu/drm/bridge/lontium-lt9211.c +2 -0
+/* Maps register value (index) to drive-strength-microamp DT property value */
+static const u32 lt9211_hsdrv_microamp[] = {

This can be u8 .

Quoted 35 lines
drivers/gpu/drm/bridge/lontium-lt9211.c +8 -1
+	12, 14, 16, 17, 19, 20, 22, 23, 25, 27, 28, 30, 31, 33, 34, 36
+};
+
  struct lt9211 {
  	struct drm_bridge		bridge;
  	struct device			*dev;
@@ -50,6 +55,7 @@ struct lt9211 {
  	struct regulator		*vccio;
  	bool				lvds_dual_link;
  	bool				lvds_dual_link_even_odd_swap;
+	u8				lvds_hsdrv_isel;
  };
 
  static const struct regmap_range lt9211_rw_ranges[] = {
@@ -374,7 +380,8 @@ static int lt9211_configure_tx(struct lt9211 *ctx, bool jeida,
  		/* BIT(7) is LVDS dual-port */
  		{ 0x823b, 0x38 | (ctx->lvds_dual_link ? BIT(7) : 0) },
  		{ 0x823e, 0x92 },
-		{ 0x823f, 0x48 },
+		/* bits 3:0: RG_MLTX_HSDRV_ISEL, LVDS TX driver current */
+		{ 0x823f, 0x40 | ctx->lvds_hsdrv_isel },
  		{ 0x8240, 0x31 },
  		{ 0x8243, 0x80 },
  		{ 0x8244, 0x00 },
@@ -629,7 +636,9 @@ static int lt9211_parse_dt(struct lt9211 *ctx)
  	struct device *dev = ctx->dev;
  	struct drm_panel *panel;
  	int dual_link;
+	u32 microamp;
  	int ret;
+	int i;
 
  	ctx->vccio = devm_regulator_get(dev, "vccio");
  	if (IS_ERR(ctx->vccio))

drivers/gpu/drm/bridge/lontium-lt9211.c static int lt9211_parse_dt(struct lt9211 *ctx) · line 680

Quoted 6 lines
drivers/gpu/drm/bridge/lontium-lt9211.c +3 -0
@@ -666,6 +675,23 @@ static int lt9211_parse_dt(struct lt9211 *ctx)
 
  	ctx->panel_bridge = panel_bridge;
 
+	ctx->lvds_hsdrv_isel = 8; /* default: 25 uA */
+	ret = of_property_read_u32(dev->of_node, "drive-strength-microamp",
+				   &microamp);

if ret != 0 , then what happens here ?

Quoted 15 lines
drivers/gpu/drm/bridge/lontium-lt9211.c +14 -0
+	if (!ret) {
+		for (i = 0; i < ARRAY_SIZE(lt9211_hsdrv_microamp); i++) {
+			if (lt9211_hsdrv_microamp[i] == microamp) {
+				ctx->lvds_hsdrv_isel = i;
+				break;
+			}
+		}
+		if (i == ARRAY_SIZE(lt9211_hsdrv_microamp)) {
+			dev_err(dev, "Invalid drive-strength-microamp value %u\n",
+				microamp);
+			return -EINVAL;
+		}
+	}
+
  	return 0;

[...]

#6 lore raw

Hello Marek,

Thank you for your feedback,

Quoted 7 lines · Marek Vasut

drivers/gpu/drm/bridge/lontium-lt9211.c line 44

Quoted 2 lines · Boerge Struempfel
drivers/gpu/drm/bridge/lontium-lt9211.c +2 -0
+/* Maps register value (index) to drive-strength-microamp DT property value */
+static const u32 lt9211_hsdrv_microamp[] = {

This can be u8 .

you are right, I'll change that in the v2.

Quoted 36 lines
Quoted 36 lines
drivers/gpu/drm/bridge/lontium-lt9211.c +8 -1
+	12, 14, 16, 17, 19, 20, 22, 23, 25, 27, 28, 30, 31, 33, 34, 36
+};
+
  struct lt9211 {
  	struct drm_bridge		bridge;
  	struct device			*dev;
@@ -50,6 +55,7 @@ struct lt9211 {
  	struct regulator		*vccio;
  	bool				lvds_dual_link;
  	bool				lvds_dual_link_even_odd_swap;
+	u8				lvds_hsdrv_isel;
  };
 
  static const struct regmap_range lt9211_rw_ranges[] = {
@@ -374,7 +380,8 @@ static int lt9211_configure_tx(struct lt9211 *ctx, bool jeida,
  		/* BIT(7) is LVDS dual-port */
  		{ 0x823b, 0x38 | (ctx->lvds_dual_link ? BIT(7) : 0) },
  		{ 0x823e, 0x92 },
-		{ 0x823f, 0x48 },
+		/* bits 3:0: RG_MLTX_HSDRV_ISEL, LVDS TX driver current */
+		{ 0x823f, 0x40 | ctx->lvds_hsdrv_isel },
  		{ 0x8240, 0x31 },
  		{ 0x8243, 0x80 },
  		{ 0x8244, 0x00 },
@@ -629,7 +636,9 @@ static int lt9211_parse_dt(struct lt9211 *ctx)
  	struct device *dev = ctx->dev;
  	struct drm_panel *panel;
  	int dual_link;
+	u32 microamp;
  	int ret;
+	int i;
 
  	ctx->vccio = devm_regulator_get(dev, "vccio");
  	if (IS_ERR(ctx->vccio))
@@ -666,6 +675,23 @@ static int lt9211_parse_dt(struct lt9211 *ctx)
 
Quoted 8 lines

drivers/gpu/drm/bridge/lontium-lt9211.c static int lt9211_parse_dt(struct lt9211 *ctx) · line 680

Quoted 5 lines
drivers/gpu/drm/bridge/lontium-lt9211.c +3 -0
  	ctx->panel_bridge = panel_bridge;
 
+	ctx->lvds_hsdrv_isel = 8; /* default: 25 uA */
+	ret = of_property_read_u32(dev->of_node, "drive-strength-microamp",
+				   &microamp);

if ret != 0 , then what happens here ?

if ret != 0, we will keep the default value of 8 (corresponding to 25 uA as written above), which is the behavior that the driver had previously.

According to the documentation, of_property_read_u32() will return 0 on success, -EINVAL if the property does not exist, -ENODATA if property does not have a value, and -EOVERFLOW if the property data isn't large enough. I think we only would need to give a warning or similar if the -ENODATA or -EOVERFLOW cases. However, I personally do not think that is necessary, as the usage is specified unambiguously in the devicetree bindings.

If you feel like we should add a warning in those cases, I can add them however.

Quoted 17 lines
Quoted 15 lines
drivers/gpu/drm/bridge/lontium-lt9211.c +14 -0
+	if (!ret) {
+		for (i = 0; i < ARRAY_SIZE(lt9211_hsdrv_microamp); i++) {
+			if (lt9211_hsdrv_microamp[i] == microamp) {
+				ctx->lvds_hsdrv_isel = i;
+				break;
+			}
+		}
+		if (i == ARRAY_SIZE(lt9211_hsdrv_microamp)) {
+			dev_err(dev, "Invalid drive-strength-microamp value %u\n",
+				microamp);
+			return -EINVAL;
+		}
+	}
+
  	return 0;

[...]

Signature · 6 lines
Best regards,
Börge Strümpfel

DATA MODUL AG
Landsberger Str. 322
80687 München
#7 lore raw

On 5/13/26 11:02 AM, Börge Strümpfel wrote:

[...]

Quoted 10 lines
Quoted 6 lines

drivers/gpu/drm/bridge/lontium-lt9211.c static int lt9211_parse_dt(struct lt9211 *ctx) · line 680

Quoted 3 lines
drivers/gpu/drm/bridge/lontium-lt9211.c +3 -0
+	ctx->lvds_hsdrv_isel = 8; /* default: 25 uA */
+	ret = of_property_read_u32(dev->of_node, "drive-strength-microamp",
+				   &microamp);

if ret != 0 , then what happens here ?

if ret != 0, we will keep the default value of 8 (corresponding to 25 uA as written above), which is the behavior that the driver had previously.

Quoted 7 lines

According to the documentation, of_property_read_u32() will return 0 on success, -EINVAL if the property does not exist, -ENODATA if property does not have a value, and -EOVERFLOW if the property data isn't large enough. I think we only would need to give a warning or similar if the -ENODATA or -EOVERFLOW cases. However, I personally do not think that is necessary, as the usage is specified unambiguously in the devicetree bindings.

Users can pass in malformed DT, so a warning is a good idea. Thanks.