linux-kernel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH v4 0/2] drm: bridge: Add TI tmds181 and sn65dp159 driver
       [not found] <1b153bce-a66a-45ee-a5c6-963ea6fb1c82.949ef384-8293-46b8-903f-40a477c056ae.d6331613-729b-4f92-9c2d-d2abe6df38d5@emailsignatures365.codetwo.com>
@ 2025-09-01 14:29 ` Mike Looijmans
       [not found]   ` <1b153bce-a66a-45ee-a5c6-963ea6fb1c82.949ef384-8293-46b8-903f-40a477c056ae.edc18686-244f-441e-a6ac-0b62492b96c8@emailsignatures365.codetwo.com>
       [not found]   ` <1b153bce-a66a-45ee-a5c6-963ea6fb1c82.949ef384-8293-46b8-903f-40a477c056ae.cb04edf6-4f97-4f30-891a-5e11da8a5e1f@emailsignatures365.codetwo.com>
  0 siblings, 2 replies; 13+ messages in thread
From: Mike Looijmans @ 2025-09-01 14:29 UTC (permalink / raw)
  To: dri-devel
  Cc: Mike Looijmans, Andrzej Hajda, Conor Dooley, David Airlie,
	Jernej Skrabec, Jonas Karlman, Krzysztof Kozlowski,
	Laurent Pinchart, Maarten Lankhorst, Maxime Ripard,
	Neil Armstrong, Rob Herring, Robert Foss, Simona Vetter,
	Thomas Zimmermann, devicetree, linux-kernel


In the past I've seen (and contributed to) hacks that model the chips as
phy or even (really!) clock drivers. Since the chip usually sits between
a signal that is (almost) HDMI and a HDMI connector, I decided to stop
lying and write it as a DRM bridge driver.

Our experience with these chips is that they work best under manual control
enabling them only once the signal is active. At low resolutions (under 4k),
the optimal setting is usually to only use redriver mode. Setting the
termination to 150-300 Ohms improves EMC performance at lower resolutions,
hence the driver enables 75-150 Ohms for HDMI2 modes and defaults to
150-300 Ohm termination for other modes.


Changes in v4:
Use fallback compatible
dev_err_probe, this_module, of_match_ptr
Use fallback compatible in driver
Add vcc-supply and vdd-supply in driver

Changes in v3:
Fix duplicate links
Add vcc-supply and vdd-supply
Fix missing type for ti,slew-rate
Lower-case hex values and use defines for EYESCAN registers
Remove equalizer code (unlikely to be used)
Remove attributes (no longer useful, undocumented)
Fix build for 6.17 kernel
Use devm_drm_bridge_alloc
Sort includes and add linux/bitfield.h
Check chip type and complain on mismatch

Changes in v2:
Document driver specific bindings like slew-rate and threshold
Use atomic_enable/disable
Use #defines for bit fields in registers
Allow HDMI 2 compliance
Filter modes on clock range
Use cross-over pixel frequency instead of manual overides
Devicetree bindings according to standards

Mike Looijmans (2):
  dt-bindings: drm/bridge: ti-tmds181: Add TI TMDS181 and SN65DP159
    bindings
  drm: bridge: Add TI tmds181 and sn65dp159 driver

 .../bindings/display/bridge/ti,tmds181.yaml   | 152 +++++++
 drivers/gpu/drm/bridge/Kconfig                |  11 +
 drivers/gpu/drm/bridge/Makefile               |   1 +
 drivers/gpu/drm/bridge/ti-tmds181.c           | 401 ++++++++++++++++++
 4 files changed, 565 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/display/bridge/ti,tmds181.yaml
 create mode 100644 drivers/gpu/drm/bridge/ti-tmds181.c

-- 
2.43.0

base-commit: 53e760d8949895390e256e723e7ee46618310361
branch: drm-ti-tmds181

Met vriendelijke groet / kind regards,

Mike Looijmans
System Expert


TOPIC Embedded Products B.V.
Materiaalweg 4, 5681 RJ Best
The Netherlands

T: +31 (0) 499 33 69 69
E: mike.looijmans@topic.nl
W: www.topic.nl

Please consider the environment before printing this e-mail

^ permalink raw reply	[flat|nested] 13+ messages in thread

* [PATCH v4 1/2] dt-bindings: drm/bridge: ti-tmds181: Add TI TMDS181 and SN65DP159 bindings
       [not found]   ` <1b153bce-a66a-45ee-a5c6-963ea6fb1c82.949ef384-8293-46b8-903f-40a477c056ae.edc18686-244f-441e-a6ac-0b62492b96c8@emailsignatures365.codetwo.com>
@ 2025-09-01 14:29     ` Mike Looijmans
  2025-09-02  6:53       ` Krzysztof Kozlowski
  2025-09-02 17:29       ` Maxime Ripard
  0 siblings, 2 replies; 13+ messages in thread
From: Mike Looijmans @ 2025-09-01 14:29 UTC (permalink / raw)
  To: dri-devel
  Cc: Mike Looijmans, Andrzej Hajda, Conor Dooley, David Airlie,
	Jernej Skrabec, Jonas Karlman, Krzysztof Kozlowski,
	Laurent Pinchart, Maarten Lankhorst, Maxime Ripard,
	Neil Armstrong, Rob Herring, Robert Foss, Simona Vetter,
	Thomas Zimmermann, devicetree, linux-kernel

Add DT binding document for TI TMDS181 and SN65DP159 HDMI retimers.

The two chips have similar register maps, but different applications
(source vs. sink).

Signed-off-by: Mike Looijmans <mike.looijmans@topic.nl>

---

Changes in v4:
Use fallback compatible

Changes in v3:
Fix duplicate links
Add vcc-supply and vdd-supply
Fix missing type for ti,slew-rate

Changes in v2:
Document driver specific bindings like slew-rate and threshold

 .../bindings/display/bridge/ti,tmds181.yaml   | 152 ++++++++++++++++++
 1 file changed, 152 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/display/bridge/ti,tmds181.yaml

diff --git a/Documentation/devicetree/bindings/display/bridge/ti,tmds181.yaml b/Documentation/devicetree/bindings/display/bridge/ti,tmds181.yaml
new file mode 100644
index 000000000000..c6387c482431
--- /dev/null
+++ b/Documentation/devicetree/bindings/display/bridge/ti,tmds181.yaml
@@ -0,0 +1,152 @@
+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/display/bridge/ti,tmds181.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: TMDS181 and SN65DP159 HDMI retimer/redriver chips
+
+maintainers:
+  - Mike Looijmans <mike.looijmans@topic.nl>
+
+description: |
+  Texas Instruments TMDS181 and SN65DP159 retimer and redriver chips.
+  https://www.ti.com/product/TMDS181
+  https://www.ti.com/product/SN65DP159
+
+properties:
+  compatible:
+    oneOf:
+      - const: ti,tmds181
+      - items:
+          - const: ti,sn65dp159
+          - const: ti,tmds181
+
+  reg:
+    enum:
+      - 0x5b
+      - 0x5c
+      - 0x5d
+      - 0x5e
+
+  oe-gpios:
+    maxItems: 1
+    description: GPIO specifier for OE pin (active high).
+
+  vdd-supply:
+    description: Core power supply, 1.1V
+
+  vcc-supply:
+    description: IO power supply, 3.3V
+
+  ports:
+    $ref: /schemas/graph.yaml#/properties/ports
+
+    properties:
+      port@0:
+        $ref: /schemas/graph.yaml#/$defs/port-base
+        unevaluatedProperties: false
+        description: Video port for HDMI (ish) input
+
+        properties:
+          endpoint:
+            $ref: /schemas/media/video-interfaces.yaml#
+            unevaluatedProperties: false
+
+      port@1:
+        $ref: /schemas/graph.yaml#/$defs/port-base
+        unevaluatedProperties: false
+        description: Video port for HDMI output (panel or bridge)
+
+        properties:
+          endpoint:
+            $ref: /schemas/media/video-interfaces.yaml#
+            unevaluatedProperties: false
+
+    required:
+      - port@0
+      - port@1
+
+  ti,source-mode:
+    type: boolean
+    description:
+      Force chip to operate in "source" mode. Allows to use
+      a TMDS181 chip (which defaults to sink) as cable driver.
+
+  ti,sink-mode:
+    type: boolean
+    description:
+      Force chip to operate in "sink" mode. Allows to use
+      a DP159 chip (defaults to source) for incoming signals.
+
+  ti,retimer-threshold-hz:
+    minimum: 25000000
+    maximum: 600000000
+    default: 200000000
+    description:
+      Cross-over point. Up until this pixel clock frequency
+      the chip remains in the low-power redriver mode. Above
+      the threshold the chip should operate in retimer mode.
+
+  ti,dvi-mode:
+    type: boolean
+    description: Makes the DP159 chip operate in DVI mode.
+
+  ti,slew-rate:
+    $ref: /schemas/types.yaml#/definitions/uint32
+    minimum: 0
+    maximum: 3
+    default: 3
+    description: Set slew rate, 0 is slowest, 3 is fastest.
+
+  ti,disable-equalizer:
+    type: boolean
+    description: Disable the equalizer (to save power).
+
+  ti,adaptive-equalizer:
+    type: boolean
+    description: Set the equalizer to adaptive mode.
+
+required:
+  - compatible
+  - reg
+  - ports
+
+additionalProperties: false
+
+examples:
+  - |
+    #include <dt-bindings/gpio/gpio.h>
+
+    i2c {
+        #address-cells = <1>;
+        #size-cells = <0>;
+
+        bridge@5b {
+            compatible = "ti,sn65dp159", "ti,tmds181";
+            reg = <0x5b>;
+
+            oe-gpios = <&gpio2 1 GPIO_ACTIVE_HIGH>;
+
+            ports {
+                #address-cells = <1>;
+                #size-cells = <0>;
+
+                port@0 {
+                    reg = <0>;
+
+                    endpoint {
+                        remote-endpoint = <&encoder_out>;
+                    };
+                };
+
+                port@1 {
+                    reg = <1>;
+
+                    endpoint {
+                        remote-endpoint = <&hdmi_connector_in>;
+                    };
+                };
+            };
+        };
+    };
-- 
2.43.0


Met vriendelijke groet / kind regards,

Mike Looijmans
System Expert


TOPIC Embedded Products B.V.
Materiaalweg 4, 5681 RJ Best
The Netherlands

T: +31 (0) 499 33 69 69
E: mike.looijmans@topic.nl
W: www.topic.nl

Please consider the environment before printing this e-mail

^ permalink raw reply related	[flat|nested] 13+ messages in thread

* [PATCH v4 2/2] drm: bridge: Add TI tmds181 and sn65dp159 driver
       [not found]   ` <1b153bce-a66a-45ee-a5c6-963ea6fb1c82.949ef384-8293-46b8-903f-40a477c056ae.cb04edf6-4f97-4f30-891a-5e11da8a5e1f@emailsignatures365.codetwo.com>
@ 2025-09-01 14:29     ` Mike Looijmans
  0 siblings, 0 replies; 13+ messages in thread
From: Mike Looijmans @ 2025-09-01 14:29 UTC (permalink / raw)
  To: dri-devel
  Cc: Mike Looijmans, Andrzej Hajda, David Airlie, Jernej Skrabec,
	Jonas Karlman, Laurent Pinchart, Maarten Lankhorst, Maxime Ripard,
	Neil Armstrong, Robert Foss, Simona Vetter, Thomas Zimmermann,
	linux-kernel

The tmds181 and sn65dp159 are "retimers" and hence can be considered
HDMI-to-HDMI bridges. Typical usage is to convert the output of an
FPGA into a valid HDMI signal, and it will typically be inserted
between an encoder and hdmi-connector.

Signed-off-by: Mike Looijmans <mike.looijmans@topic.nl>
---

Changes in v4:
dev_err_probe, this_module, of_match_ptr
Use fallback compatible
Add vcc-supply and vdd-supply

Changes in v3:
Lower-case hex values and use defines for EYESCAN registers
Remove equalizer code (unlikely to be used)
Remove attributes (no longer useful, undocumented)
Fix build for 6.17 kernel
Use devm_drm_bridge_alloc
Sort includes and add linux/bitfield.h
Check chip type and complain on mismatch

Changes in v2:
Use atomic_enable/disable
Use #defines for bit fields in registers
Allow HDMI 2 compliance
Filter modes on clock range
Use cross-over pixel frequency instead of manual overides
Devicetree bindings according to standards

 drivers/gpu/drm/bridge/Kconfig      |  11 +
 drivers/gpu/drm/bridge/Makefile     |   1 +
 drivers/gpu/drm/bridge/ti-tmds181.c | 401 ++++++++++++++++++++++++++++
 3 files changed, 413 insertions(+)
 create mode 100644 drivers/gpu/drm/bridge/ti-tmds181.c

diff --git a/drivers/gpu/drm/bridge/Kconfig b/drivers/gpu/drm/bridge/Kconfig
index b9e0ca85226a..753177fc9b50 100644
--- a/drivers/gpu/drm/bridge/Kconfig
+++ b/drivers/gpu/drm/bridge/Kconfig
@@ -430,6 +430,17 @@ config DRM_TI_SN65DSI86
 	help
 	  Texas Instruments SN65DSI86 DSI to eDP Bridge driver
 
+config DRM_TI_TMDS181
+        tristate "TI TMDS181 and SN65DP159 HDMI retimer bridge driver"
+	depends on OF
+	select DRM_KMS_HELPER
+	select REGMAP_I2C
+	help
+	  Enable this to support the TI TMDS181 and SN65DP159 HDMI retimers.
+	  The SN65DP159 provides output into a cable (source) whereas the
+	  TMDS181 is meant to forward a cable signal into a PCB (sink). Either
+	  can be set up as source or sink though.
+
 config DRM_TI_TPD12S015
 	tristate "TI TPD12S015 HDMI level shifter and ESD protection"
 	depends on OF
diff --git a/drivers/gpu/drm/bridge/Makefile b/drivers/gpu/drm/bridge/Makefile
index 245e8a27e3fc..f4b5089e903c 100644
--- a/drivers/gpu/drm/bridge/Makefile
+++ b/drivers/gpu/drm/bridge/Makefile
@@ -39,6 +39,7 @@ obj-$(CONFIG_DRM_TI_SN65DSI83) += ti-sn65dsi83.o
 obj-$(CONFIG_DRM_TI_SN65DSI86) += ti-sn65dsi86.o
 obj-$(CONFIG_DRM_TI_TDP158) += ti-tdp158.o
 obj-$(CONFIG_DRM_TI_TFP410) += ti-tfp410.o
+obj-$(CONFIG_DRM_TI_TMDS181) += ti-tmds181.o
 obj-$(CONFIG_DRM_TI_TPD12S015) += ti-tpd12s015.o
 obj-$(CONFIG_DRM_NWL_MIPI_DSI) += nwl-dsi.o
 obj-$(CONFIG_DRM_ITE_IT66121) += ite-it66121.o
diff --git a/drivers/gpu/drm/bridge/ti-tmds181.c b/drivers/gpu/drm/bridge/ti-tmds181.c
new file mode 100644
index 000000000000..e7761b2f32be
--- /dev/null
+++ b/drivers/gpu/drm/bridge/ti-tmds181.c
@@ -0,0 +1,401 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * TI tmds181 and sn65dp159 HDMI redriver and retimer chips
+ *
+ * Copyright (C) 2018 - 2025 Topic Embedded Products <www.topic.nl>
+ *
+ * based on code
+ * Copyright (C) 2007 Hans Verkuil
+ * Copyright (C) 2016, 2017 Leon Woestenberg <leon@sidebranch.com>
+ */
+
+#include <linux/bitfield.h>
+#include <linux/delay.h>
+#include <linux/gpio/consumer.h>
+#include <linux/i2c.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/regmap.h>
+#include <linux/slab.h>
+
+#include <drm/drm_atomic_helper.h>
+#include <drm/drm_bridge.h>
+#include <drm/drm_crtc.h>
+#include <drm/display/drm_hdmi_helper.h>
+#include <drm/drm_print.h>
+#include <drm/drm_probe_helper.h>
+
+MODULE_DESCRIPTION("I2C device driver for DP159 and TMDS181 redriver/retimer");
+MODULE_AUTHOR("Mike Looijmans");
+MODULE_LICENSE("GPL");
+
+#define TMDS181_REG_ID		0
+#define TMDS181_REG_REV		0x8
+#define TMDS181_REG_CTRL9	0x9
+/* Registers A and B have a volatile bit, but we don't use it, so cache is ok */
+#define TMDS181_REG_CTRLA	0xa
+#define TMDS181_REG_CTRLB	0xb
+#define TMDS181_REG_CTRLC	0xc
+#define TMDS181_REG_EQUALIZER	0xd
+/* EYESCAN registers don't appear to deserve separate names */
+#define TMDS181_REG_EYESCAN_E	0xe
+#define TMDS181_REG_EYESCAN_F	0xf
+#define TMDS181_REG_EYESCAN_15	0x15
+#define TMDS181_REG_EYESCAN_17	0x17
+#define TMDS181_REG_EYESCAN_1F	0x1f
+#define TMDS181_REG_AUX		0x20
+
+
+#define TMDS181_CTRL9_SIG_EN			BIT(4)
+#define TMDS181_CTRL9_PD_EN			BIT(3)
+#define TMDS181_CTRL9_HPD_AUTO_PWRDWN_DISABLE	BIT(2)
+#define TMDS181_CTRL9_I2C_DR_CTL		GENMASK(1, 0)
+
+#define TMDS181_CTRLA_MODE_SINK			BIT(7)
+#define TMDS181_CTRLA_HPDSNK_GATE_EN		BIT(6)
+#define TMDS181_CTRLA_EQ_ADA_EN			BIT(5)
+#define TMDS181_CTRLA_EQ_EN			BIT(4)
+#define TMDS181_CTRLA_AUX_BRG_EN		BIT(3)
+#define TMDS181_CTRLA_APPLY			BIT(2)
+#define TMDS181_CTRLA_DEV_FUNC_MODE		GENMASK(1, 0)
+
+#define TMDS181_CTRLB_SLEW_CTL			GENMASK(7, 6)
+#define TMDS181_CTRLB_HDMI_SEL_DVI		BIT(5)
+#define TMDS181_CTRLB_TX_TERM_CTL		GENMASK(4, 3)
+#define TMDS181_CTRLB_DDC_DR_SEL		BIT(2)
+#define TMDS181_CTRLB_TMDS_CLOCK_RATIO_STATUS	BIT(1)
+#define TMDS181_CTRLB_DDC_TRAIN_SET		BIT(0)
+
+#define TMDS181_CTRLB_TX_TERM_150_300_OHMS	1
+#define TMDS181_CTRLB_TX_TERM_75_150_OHMS	3
+
+#define TMDS181_CTRLC_VSWING_DATA		GENMASK(7, 5)
+#define TMDS181_CTRLC_VSWING_CLK		GENMASK(4, 2)
+#define TMDS181_CTRLC_HDMI_TWPST1		GENMASK(1, 0)
+
+#define TMDS181_EQ_DATA_LANE			GENMASK(5, 3)
+#define TMDS181_EQ_CLOCK_LANE			GENMASK(2, 1)
+#define TMDS181_EQ_DIS_HDMI2_SWG		BIT(0)
+
+/* Above this data rate HDMI2 standards apply (TX termination) */
+#define HDMI2_PIXEL_RATE_KHZ	340000
+
+enum tmds181_chip {
+	tmds181,
+	dp159,
+};
+
+struct tmds181_data {
+	struct i2c_client *client;
+	struct regmap *regmap;
+	struct drm_bridge *next_bridge;
+	struct drm_bridge bridge;
+	u32 retimer_threshold_khz;
+};
+
+static inline struct tmds181_data *
+drm_bridge_to_tmds181_data(struct drm_bridge *bridge)
+{
+	return container_of(bridge, struct tmds181_data, bridge);
+}
+
+static int tmds181_attach(struct drm_bridge *bridge, struct drm_encoder *encoder,
+			  enum drm_bridge_attach_flags flags)
+{
+	struct tmds181_data *data = drm_bridge_to_tmds181_data(bridge);
+
+	return drm_bridge_attach(encoder, data->next_bridge, bridge, flags);
+}
+
+static enum drm_mode_status
+tmds181_mode_valid(struct drm_bridge *bridge, const struct drm_display_info *info,
+		   const struct drm_display_mode *mode)
+{
+	unsigned long long rate;
+
+	rate = drm_hdmi_compute_mode_clock(mode, 8, HDMI_COLORSPACE_RGB);
+
+	/* Minimum clock rate is 25MHz */
+	if (rate < 25000000)
+		return MODE_CLOCK_LOW;
+
+	/*
+	 * When in HDMI 2 mode, the clock is 1/40th of the bitrate. The limit is
+	 * then the data rate of 6Gbps, which would use a 600MHz pixel clock.
+	 */
+	if (rate > 600000000)
+		return MODE_CLOCK_HIGH;
+
+	return MODE_OK;
+}
+
+static void tmds181_enable(struct drm_bridge *bridge, struct drm_atomic_state *state)
+{
+	struct tmds181_data *data = drm_bridge_to_tmds181_data(bridge);
+	const struct drm_crtc_state *crtc_state;
+	const struct drm_display_mode *mode;
+	struct drm_connector *connector;
+	struct drm_crtc *crtc;
+	unsigned int val;
+
+	/*
+	 * Retrieve the CRTC adjusted mode. This requires a little dance to go
+	 * from the bridge to the encoder, to the connector and to the CRTC.
+	 */
+	connector = drm_atomic_get_new_connector_for_encoder(state,
+							     bridge->encoder);
+	crtc = drm_atomic_get_new_connector_state(state, connector)->crtc;
+	crtc_state = drm_atomic_get_new_crtc_state(state, crtc);
+	mode = &crtc_state->adjusted_mode;
+
+	/* Set retimer/redriver mode based on pixel clock */
+	val = mode->clock > data->retimer_threshold_khz ? TMDS181_CTRLA_DEV_FUNC_MODE : 0;
+	regmap_update_bits(data->regmap, TMDS181_REG_CTRLA,
+			   TMDS181_CTRLA_DEV_FUNC_MODE, val);
+
+	/* Configure TX termination based on pixel clock */
+	val = mode->clock > HDMI2_PIXEL_RATE_KHZ ?
+				TMDS181_CTRLB_TX_TERM_75_150_OHMS :
+				TMDS181_CTRLB_TX_TERM_150_300_OHMS;
+	regmap_update_bits(data->regmap, TMDS181_REG_CTRLB,
+			   TMDS181_CTRLB_TX_TERM_CTL,
+			   FIELD_PREP(TMDS181_CTRLB_TX_TERM_CTL, val));
+
+	regmap_update_bits(data->regmap, TMDS181_REG_CTRL9,
+			   TMDS181_CTRL9_PD_EN, 0);
+}
+
+static void tmds181_disable(struct drm_bridge *bridge, struct drm_atomic_state *state)
+{
+	struct tmds181_data *data = drm_bridge_to_tmds181_data(bridge);
+
+	/* Set the PD_EN bit */
+	regmap_update_bits(data->regmap, TMDS181_REG_CTRL9,
+			   TMDS181_CTRL9_PD_EN, TMDS181_CTRL9_PD_EN);
+}
+
+static const struct drm_bridge_funcs tmds181_bridge_funcs = {
+	.attach		= tmds181_attach,
+	.mode_valid	= tmds181_mode_valid,
+	.atomic_enable	= tmds181_enable,
+	.atomic_disable	= tmds181_disable,
+
+	.atomic_reset = drm_atomic_helper_bridge_reset,
+	.atomic_duplicate_state = drm_atomic_helper_bridge_duplicate_state,
+	.atomic_destroy_state = drm_atomic_helper_bridge_destroy_state,
+};
+
+static const u8 tmds181_id_tmds181[8] __nonstring = "TMDS181 ";
+static const u8 tmds181_id_dp159[8]   __nonstring = "DP159   ";
+
+static int tmds181_check_id(struct tmds181_data *data, enum tmds181_chip *chip)
+{
+	int ret;
+	int retry;
+	u8 buffer[8];
+
+	for (retry = 0; retry < 20; ++retry) {
+		ret = regmap_bulk_read(data->regmap, TMDS181_REG_ID, buffer,
+				       sizeof(buffer));
+		if (!ret)
+			break;
+
+		/* Compensate for very long OE power-up delays due to the cap */
+		usleep_range(5000, 10000);
+	}
+
+	if (ret) {
+		dev_err(&data->client->dev, "I2C read ID failed\n");
+		return ret;
+	}
+
+	if (memcmp(buffer, tmds181_id_tmds181, sizeof(buffer)) == 0) {
+		dev_info(&data->client->dev, "Detected: TMDS181\n");
+		*chip = tmds181;
+		return 0;
+	}
+
+	if (memcmp(buffer, tmds181_id_dp159, sizeof(buffer)) == 0) {
+		dev_info(&data->client->dev, "Detected: DP159\n");
+		*chip = dp159;
+		return 0;
+	}
+
+	dev_err(&data->client->dev, "Unknown ID: %*pE\n", (int)sizeof(buffer), buffer);
+
+	return -ENODEV;
+}
+
+static bool tmds181_regmap_is_volatile(struct device *dev, unsigned int reg)
+{
+	switch (reg) {
+	/* IBERT result and status registers, not used yet */
+	case TMDS181_REG_EYESCAN_15:
+	case TMDS181_REG_EYESCAN_17 ... TMDS181_REG_EYESCAN_1F:
+		return true;
+	default:
+		return false;
+	}
+}
+
+static const struct regmap_config tmds181_regmap_config = {
+	.reg_bits = 8,
+	.val_bits = 8,
+	.cache_type = REGCACHE_RBTREE,
+	.max_register = TMDS181_REG_AUX,
+	.volatile_reg = tmds181_regmap_is_volatile,
+};
+
+static int tmds181_probe(struct i2c_client *client)
+{
+	struct tmds181_data *data;
+	struct gpio_desc *oe_gpio;
+	enum tmds181_chip chip;
+	int ret;
+	u32 param;
+	u8 val;
+
+	/* Check if the adapter supports the needed features */
+	if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_BYTE_DATA))
+		return -EIO;
+
+	data = devm_drm_bridge_alloc(&client->dev, struct tmds181_data, bridge,
+				     &tmds181_bridge_funcs);
+	if (IS_ERR(data))
+		return PTR_ERR(data);
+
+	data->client = client;
+	i2c_set_clientdata(client, data);
+	data->regmap = devm_regmap_init_i2c(client, &tmds181_regmap_config);
+	if (IS_ERR(data->regmap))
+		return PTR_ERR(data->regmap);
+
+	/* The "OE" pin acts as a reset */
+	oe_gpio = devm_gpiod_get_optional(&client->dev, "oe", GPIOD_OUT_LOW);
+	if (IS_ERR(oe_gpio))
+		return dev_err_probe(&client->dev, PTR_ERR(oe_gpio),
+				     "failed to acquire 'oe' gpio\n");
+
+	if (oe_gpio) {
+		/* Need at least 100us reset pulse */
+		usleep_range(100, 200);
+		gpiod_set_value_cansleep(oe_gpio, 1);
+	}
+
+	/* Reading the ID also provides time for the reset */
+	ret = tmds181_check_id(data, &chip);
+	if (ret)
+		return ret;
+
+	/*
+	 * We take care of power control, so disable the chips PM functions, and
+	 * allow the DDC to run at 400kHz
+	 */
+	regmap_update_bits(data->regmap, TMDS181_REG_CTRL9,
+			TMDS181_CTRL9_SIG_EN | TMDS181_CTRL9_PD_EN |
+			TMDS181_CTRL9_HPD_AUTO_PWRDWN_DISABLE |
+			TMDS181_CTRL9_I2C_DR_CTL,
+			TMDS181_CTRL9_PD_EN |
+			TMDS181_CTRL9_HPD_AUTO_PWRDWN_DISABLE |
+			TMDS181_CTRL9_I2C_DR_CTL);
+
+	/* Apply configuration changes */
+	if (of_property_read_bool(client->dev.of_node, "ti,source-mode"))
+		regmap_update_bits(data->regmap, TMDS181_REG_CTRLA,
+				   TMDS181_CTRLA_MODE_SINK, 0);
+	if (of_property_read_bool(client->dev.of_node, "ti,sink-mode"))
+		regmap_update_bits(data->regmap, TMDS181_REG_CTRLA,
+				   TMDS181_CTRLA_MODE_SINK, TMDS181_CTRLA_MODE_SINK);
+
+	/*
+	 * Using the automatic modes of the chip uses considerable power as it
+	 * will keep the PLL running at all times. So instead, define our own
+	 * threshold for the pixel rate. This also allows to use a sane default
+	 * of 200MHz pixel rate for the redriver-retimer crossover point, as the
+	 * modes below 3k don't show any benefit from the retimer.
+	 */
+	data->retimer_threshold_khz = 200000;
+	if (!of_property_read_u32(client->dev.of_node,
+				  "ti,retimer-threshold-hz", &param))
+		data->retimer_threshold_khz = param / 1000;
+
+	/* Default to low-power redriver mode */
+	regmap_update_bits(data->regmap, TMDS181_REG_CTRLA,
+			   TMDS181_CTRLA_DEV_FUNC_MODE, 0x00);
+
+	if (of_property_read_bool(client->dev.of_node, "ti,adaptive-equalizer"))
+		regmap_update_bits(data->regmap, TMDS181_REG_CTRLA,
+				   TMDS181_CTRLA_EQ_EN | TMDS181_CTRLA_EQ_ADA_EN,
+				   TMDS181_CTRLA_EQ_EN | TMDS181_CTRLA_EQ_ADA_EN);
+	if (of_property_read_bool(client->dev.of_node, "ti,disable-equalizer"))
+		regmap_update_bits(data->regmap, TMDS181_REG_CTRLA,
+				   TMDS181_CTRLA_EQ_EN | TMDS181_CTRLA_EQ_ADA_EN,
+				   0);
+
+	switch (chip) {
+	case dp159:
+		val = 0;
+		if (!of_property_read_u32(client->dev.of_node,
+					  "ti,slew-rate", &param)) {
+			if (param > 3) {
+				dev_err(&client->dev, "invalid slew-rate\n");
+				return -EINVAL;
+			}
+			/* Implement 0 = slow, 3 = fast slew rate */
+			val = FIELD_PREP(TMDS181_CTRLB_SLEW_CTL, (3 - param));
+		}
+		if (of_property_read_bool(client->dev.of_node, "ti,dvi-mode"))
+			val |= TMDS181_CTRLB_HDMI_SEL_DVI;
+		break;
+	default:
+		val = TMDS181_CTRLB_DDC_DR_SEL;
+		break;
+	}
+
+	/* Default to low-speed termination */
+	val |= FIELD_PREP(TMDS181_CTRLB_TX_TERM_CTL, TMDS181_CTRLB_TX_TERM_150_300_OHMS);
+
+	ret = regmap_write(data->regmap, TMDS181_REG_CTRLB, val);
+	if (ret < 0) {
+		dev_err(&client->dev, "regmap_write(B) failed\n");
+		return ret;
+	}
+
+	/* Find next bridge in chain */
+	data->next_bridge = devm_drm_of_get_bridge(&client->dev, client->dev.of_node, 1, 0);
+	if (IS_ERR(data->next_bridge))
+		return dev_err_probe(&client->dev, PTR_ERR(data->next_bridge),
+				     "Failed to find next bridge\n");
+
+	/* Register the bridge. */
+	data->bridge.of_node = client->dev.of_node;
+
+	return devm_drm_bridge_add(&client->dev, &data->bridge);
+}
+
+static const struct i2c_device_id tmds181_id[] = {
+	{ "tmds181", },
+	{ "sn65dp159", },
+	{}
+};
+MODULE_DEVICE_TABLE(i2c, tmds181_id);
+
+#if IS_ENABLED(CONFIG_OF)
+static const struct of_device_id tmds181_of_match[] = {
+	{ .compatible = "ti,tmds181",  },
+	{}
+};
+MODULE_DEVICE_TABLE(of, tmds181_of_match);
+#endif
+
+static struct i2c_driver tmds181_driver = {
+	.driver = {
+		.name	= "tmds181",
+		.of_match_table = tmds181_of_match,
+	},
+	.probe		= tmds181_probe,
+	.id_table	= tmds181_id,
+};
+
+module_i2c_driver(tmds181_driver);
-- 
2.43.0


Met vriendelijke groet / kind regards,

Mike Looijmans
System Expert


TOPIC Embedded Products B.V.
Materiaalweg 4, 5681 RJ Best
The Netherlands

T: +31 (0) 499 33 69 69
E: mike.looijmans@topic.nl
W: www.topic.nl

Please consider the environment before printing this e-mail

^ permalink raw reply related	[flat|nested] 13+ messages in thread

* Re: [PATCH v4 1/2] dt-bindings: drm/bridge: ti-tmds181: Add TI TMDS181 and SN65DP159 bindings
  2025-09-01 14:29     ` [PATCH v4 1/2] dt-bindings: drm/bridge: ti-tmds181: Add TI TMDS181 and SN65DP159 bindings Mike Looijmans
@ 2025-09-02  6:53       ` Krzysztof Kozlowski
  2025-09-02  8:46         ` Mike Looijmans
  2025-09-02 17:29       ` Maxime Ripard
  1 sibling, 1 reply; 13+ messages in thread
From: Krzysztof Kozlowski @ 2025-09-02  6:53 UTC (permalink / raw)
  To: Mike Looijmans
  Cc: dri-devel, Andrzej Hajda, Conor Dooley, David Airlie,
	Jernej Skrabec, Jonas Karlman, Krzysztof Kozlowski,
	Laurent Pinchart, Maarten Lankhorst, Maxime Ripard,
	Neil Armstrong, Rob Herring, Robert Foss, Simona Vetter,
	Thomas Zimmermann, devicetree, linux-kernel

On Mon, Sep 01, 2025 at 04:29:01PM +0200, Mike Looijmans wrote:
>  .../bindings/display/bridge/ti,tmds181.yaml   | 152 ++++++++++++++++++
>  1 file changed, 152 insertions(+)
>  create mode 100644 Documentation/devicetree/bindings/display/bridge/ti,tmds181.yaml
> 
> diff --git a/Documentation/devicetree/bindings/display/bridge/ti,tmds181.yaml b/Documentation/devicetree/bindings/display/bridge/ti,tmds181.yaml
> new file mode 100644
> index 000000000000..c6387c482431
> --- /dev/null
> +++ b/Documentation/devicetree/bindings/display/bridge/ti,tmds181.yaml
> @@ -0,0 +1,152 @@
> +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
> +%YAML 1.2
> +---
> +$id: http://devicetree.org/schemas/display/bridge/ti,tmds181.yaml#
> +$schema: http://devicetree.org/meta-schemas/core.yaml#
> +
> +title: TMDS181 and SN65DP159 HDMI retimer/redriver chips
> +
> +maintainers:
> +  - Mike Looijmans <mike.looijmans@topic.nl>
> +
> +description: |
> +  Texas Instruments TMDS181 and SN65DP159 retimer and redriver chips.
> +  https://www.ti.com/product/TMDS181
> +  https://www.ti.com/product/SN65DP159
> +
> +properties:
> +  compatible:
> +    oneOf:
> +      - const: ti,tmds181
> +      - items:
> +          - const: ti,sn65dp159
> +          - const: ti,tmds181
> +
> +  reg:
> +    enum:
> +      - 0x5b
> +      - 0x5c
> +      - 0x5d
> +      - 0x5e
> +
> +  oe-gpios:
> +    maxItems: 1
> +    description: GPIO specifier for OE pin (active high).

So that's reset-gpios or powerdown-gpios (see gpio-consumer-common). At
least datasheet calls them that in one place.

> +
> +  vdd-supply:
> +    description: Core power supply, 1.1V
> +
> +  vcc-supply:
> +    description: IO power supply, 3.3V
> +
> +  ports:
> +    $ref: /schemas/graph.yaml#/properties/ports
> +
> +    properties:
> +      port@0:
> +        $ref: /schemas/graph.yaml#/$defs/port-base
> +        unevaluatedProperties: false
> +        description: Video port for HDMI (ish) input
> +
> +        properties:
> +          endpoint:
> +            $ref: /schemas/media/video-interfaces.yaml#
> +            unevaluatedProperties: false
> +
> +      port@1:
> +        $ref: /schemas/graph.yaml#/$defs/port-base
> +        unevaluatedProperties: false
> +        description: Video port for HDMI output (panel or bridge)
> +
> +        properties:
> +          endpoint:
> +            $ref: /schemas/media/video-interfaces.yaml#
> +            unevaluatedProperties: false
> +
> +    required:
> +      - port@0
> +      - port@1
> +
> +  ti,source-mode:
> +    type: boolean
> +    description:
> +      Force chip to operate in "source" mode. Allows to use
> +      a TMDS181 chip (which defaults to sink) as cable driver.
> +
> +  ti,sink-mode:

Aren't these two mutually exclusive? Can same device operate in source
and in sink mode simultaneously?


> +    type: boolean
> +    description:
> +      Force chip to operate in "sink" mode. Allows to use
> +      a DP159 chip (defaults to source) for incoming signals.
> +
> +  ti,retimer-threshold-hz:
> +    minimum: 25000000
> +    maximum: 600000000
> +    default: 200000000
> +    description:
> +      Cross-over point. Up until this pixel clock frequency
> +      the chip remains in the low-power redriver mode. Above
> +      the threshold the chip should operate in retimer mode.
> +
> +  ti,dvi-mode:
> +    type: boolean
> +    description: Makes the DP159 chip operate in DVI mode.

This suggest it is not applicable to TMDS, so you need to restrict it to
disallow it there (see example-schema).

Actually several other properties say they are applicable only to DP159.

> +
> +  ti,slew-rate:

Common property is "slew-rate" - see pincfg-node.yaml

> +    $ref: /schemas/types.yaml#/definitions/uint32
> +    minimum: 0
> +    maximum: 3
> +    default: 3
> +    description: Set slew rate, 0 is slowest, 3 is fastest.
> +
> +  ti,disable-equalizer:
> +    type: boolean
> +    description: Disable the equalizer (to save power).
> +
> +  ti,adaptive-equalizer:
> +    type: boolean
> +    description: Set the equalizer to adaptive mode.

Can equalizer be disabled and adaptive the same time?

> +
> +required:
> +  - compatible
> +  - reg
> +  - ports
> +
> +additionalProperties: false

Best regards,
Krzysztof


^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: [PATCH v4 1/2] dt-bindings: drm/bridge: ti-tmds181: Add TI TMDS181 and SN65DP159 bindings
  2025-09-02  6:53       ` Krzysztof Kozlowski
@ 2025-09-02  8:46         ` Mike Looijmans
  2025-09-02 13:46           ` Krzysztof Kozlowski
  0 siblings, 1 reply; 13+ messages in thread
From: Mike Looijmans @ 2025-09-02  8:46 UTC (permalink / raw)
  To: Krzysztof Kozlowski
  Cc: dri-devel, Andrzej Hajda, Conor Dooley, David Airlie,
	Jernej Skrabec, Jonas Karlman, Krzysztof Kozlowski,
	Laurent Pinchart, Maarten Lankhorst, Maxime Ripard,
	Neil Armstrong, Rob Herring, Robert Foss, Simona Vetter,
	Thomas Zimmermann, devicetree, linux-kernel

On 9/2/25 08:53, Krzysztof Kozlowski wrote:
> On Mon, Sep 01, 2025 at 04:29:01PM +0200, Mike Looijmans wrote:
>>   .../bindings/display/bridge/ti,tmds181.yaml   | 152 ++++++++++++++++++
>>   1 file changed, 152 insertions(+)
>>   create mode 100644 Documentation/devicetree/bindings/display/bridge/ti,tmds181.yaml
>>
>> diff --git a/Documentation/devicetree/bindings/display/bridge/ti,tmds181.yaml b/Documentation/devicetree/bindings/display/bridge/ti,tmds181.yaml
>> new file mode 100644
>> index 000000000000..c6387c482431
>> --- /dev/null
>> +++ b/Documentation/devicetree/bindings/display/bridge/ti,tmds181.yaml
>> @@ -0,0 +1,152 @@
>> +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
>> +%YAML 1.2
>> +---
>> +$id: http://devicetree.org/schemas/display/bridge/ti,tmds181.yaml#
>> +$schema: http://devicetree.org/meta-schemas/core.yaml#
>> +
>> +title: TMDS181 and SN65DP159 HDMI retimer/redriver chips
>> +
>> +maintainers:
>> +  - Mike Looijmans <mike.looijmans@topic.nl>
>> +
>> +description: |
>> +  Texas Instruments TMDS181 and SN65DP159 retimer and redriver chips.
>> +  https://www.ti.com/product/TMDS181
>> +  https://www.ti.com/product/SN65DP159
>> +
>> +properties:
>> +  compatible:
>> +    oneOf:
>> +      - const: ti,tmds181
>> +      - items:
>> +          - const: ti,sn65dp159
>> +          - const: ti,tmds181
>> +
>> +  reg:
>> +    enum:
>> +      - 0x5b
>> +      - 0x5c
>> +      - 0x5d
>> +      - 0x5e
>> +
>> +  oe-gpios:
>> +    maxItems: 1
>> +    description: GPIO specifier for OE pin (active high).
> So that's reset-gpios or powerdown-gpios (see gpio-consumer-common). At
> least datasheet calls them that in one place.

reset-gpios fits reasonably. Though the pin is labeled "OE".

(Our experience: The pin must be driven low until the power supplies are 
up. Failure to do so may put the chip in an error state, pulling the I2C 
lines low, that only a power cycle may resolve. So it's close enough to 
"reset")

>> +
>> +  vdd-supply:
>> +    description: Core power supply, 1.1V
>> +
>> +  vcc-supply:
>> +    description: IO power supply, 3.3V
>> +
>> +  ports:
>> +    $ref: /schemas/graph.yaml#/properties/ports
>> +
>> +    properties:
>> +      port@0:
>> +        $ref: /schemas/graph.yaml#/$defs/port-base
>> +        unevaluatedProperties: false
>> +        description: Video port for HDMI (ish) input
>> +
>> +        properties:
>> +          endpoint:
>> +            $ref: /schemas/media/video-interfaces.yaml#
>> +            unevaluatedProperties: false
>> +
>> +      port@1:
>> +        $ref: /schemas/graph.yaml#/$defs/port-base
>> +        unevaluatedProperties: false
>> +        description: Video port for HDMI output (panel or bridge)
>> +
>> +        properties:
>> +          endpoint:
>> +            $ref: /schemas/media/video-interfaces.yaml#
>> +            unevaluatedProperties: false
>> +
>> +    required:
>> +      - port@0
>> +      - port@1
>> +
>> +  ti,source-mode:
>> +    type: boolean
>> +    description:
>> +      Force chip to operate in "source" mode. Allows to use
>> +      a TMDS181 chip (which defaults to sink) as cable driver.
>> +
>> +  ti,sink-mode:
> Aren't these two mutually exclusive? Can same device operate in source
> and in sink mode simultaneously?

They're exclusive, yes. Will add that.


>> +    type: boolean
>> +    description:
>> +      Force chip to operate in "sink" mode. Allows to use
>> +      a DP159 chip (defaults to source) for incoming signals.
>> +
>> +  ti,retimer-threshold-hz:
>> +    minimum: 25000000
>> +    maximum: 600000000
>> +    default: 200000000
>> +    description:
>> +      Cross-over point. Up until this pixel clock frequency
>> +      the chip remains in the low-power redriver mode. Above
>> +      the threshold the chip should operate in retimer mode.
>> +
>> +  ti,dvi-mode:
>> +    type: boolean
>> +    description: Makes the DP159 chip operate in DVI mode.
> This suggest it is not applicable to TMDS, so you need to restrict it to
> disallow it there (see example-schema).
>
> Actually several other properties say they are applicable only to DP159.

Will do.


>
>> +
>> +  ti,slew-rate:
> Common property is "slew-rate" - see pincfg-node.yaml

Will change to slew-rate.


>
>> +    $ref: /schemas/types.yaml#/definitions/uint32
>> +    minimum: 0
>> +    maximum: 3
>> +    default: 3
>> +    description: Set slew rate, 0 is slowest, 3 is fastest.
>> +
>> +  ti,disable-equalizer:
>> +    type: boolean
>> +    description: Disable the equalizer (to save power).
>> +
>> +  ti,adaptive-equalizer:
>> +    type: boolean
>> +    description: Set the equalizer to adaptive mode.
> Can equalizer be disabled and adaptive the same time?

No, since "adaptive" is the default, I'll just remove that option.


>> +
>> +required:
>> +  - compatible
>> +  - reg
>> +  - ports
>> +
>> +additionalProperties: false
> Best regards,
> Krzysztof
>

-- 
Mike Looijmans



^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: [PATCH v4 1/2] dt-bindings: drm/bridge: ti-tmds181: Add TI TMDS181 and SN65DP159 bindings
  2025-09-02  8:46         ` Mike Looijmans
@ 2025-09-02 13:46           ` Krzysztof Kozlowski
  2025-09-02 14:41             ` Mike Looijmans
  0 siblings, 1 reply; 13+ messages in thread
From: Krzysztof Kozlowski @ 2025-09-02 13:46 UTC (permalink / raw)
  To: Mike Looijmans
  Cc: dri-devel, Andrzej Hajda, Conor Dooley, David Airlie,
	Jernej Skrabec, Jonas Karlman, Krzysztof Kozlowski,
	Laurent Pinchart, Maarten Lankhorst, Maxime Ripard,
	Neil Armstrong, Rob Herring, Robert Foss, Simona Vetter,
	Thomas Zimmermann, devicetree, linux-kernel

On 02/09/2025 10:46, Mike Looijmans wrote:
>>> +          endpoint:
>>> +            $ref: /schemas/media/video-interfaces.yaml#
>>> +            unevaluatedProperties: false
>>> +
>>> +      port@1:
>>> +        $ref: /schemas/graph.yaml#/$defs/port-base
>>> +        unevaluatedProperties: false
>>> +        description: Video port for HDMI output (panel or bridge)
>>> +
>>> +        properties:
>>> +          endpoint:
>>> +            $ref: /schemas/media/video-interfaces.yaml#
>>> +            unevaluatedProperties: false
>>> +
>>> +    required:
>>> +      - port@0
>>> +      - port@1
>>> +
>>> +  ti,source-mode:
>>> +    type: boolean
>>> +    description:
>>> +      Force chip to operate in "source" mode. Allows to use
>>> +      a TMDS181 chip (which defaults to sink) as cable driver.
>>> +
>>> +  ti,sink-mode:
>> Aren't these two mutually exclusive? Can same device operate in source
>> and in sink mode simultaneously?
> 
> They're exclusive, yes. Will add that.

Then either define constraints per variant in if:then: or maybe better
use string enum. Not sure what applies where, so tricky to say which
choice is better.

Best regards,
Krzysztof

^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: [PATCH v4 1/2] dt-bindings: drm/bridge: ti-tmds181: Add TI TMDS181 and SN65DP159 bindings
  2025-09-02 13:46           ` Krzysztof Kozlowski
@ 2025-09-02 14:41             ` Mike Looijmans
  2025-09-02 14:52               ` Mike Looijmans
  0 siblings, 1 reply; 13+ messages in thread
From: Mike Looijmans @ 2025-09-02 14:41 UTC (permalink / raw)
  To: Krzysztof Kozlowski
  Cc: dri-devel, Andrzej Hajda, Conor Dooley, David Airlie,
	Jernej Skrabec, Jonas Karlman, Krzysztof Kozlowski,
	Laurent Pinchart, Maarten Lankhorst, Maxime Ripard,
	Neil Armstrong, Rob Herring, Robert Foss, Simona Vetter,
	Thomas Zimmermann, devicetree, linux-kernel

On 9/2/25 15:46, Krzysztof Kozlowski wrote:
> On 02/09/2025 10:46, Mike Looijmans wrote:
>>>> +          endpoint:
>>>> +            $ref: /schemas/media/video-interfaces.yaml#
>>>> +            unevaluatedProperties: false
>>>> +
>>>> +      port@1:
>>>> +        $ref: /schemas/graph.yaml#/$defs/port-base
>>>> +        unevaluatedProperties: false
>>>> +        description: Video port for HDMI output (panel or bridge)
>>>> +
>>>> +        properties:
>>>> +          endpoint:
>>>> +            $ref: /schemas/media/video-interfaces.yaml#
>>>> +            unevaluatedProperties: false
>>>> +
>>>> +    required:
>>>> +      - port@0
>>>> +      - port@1
>>>> +
>>>> +  ti,source-mode:
>>>> +    type: boolean
>>>> +    description:
>>>> +      Force chip to operate in "source" mode. Allows to use
>>>> +      a TMDS181 chip (which defaults to sink) as cable driver.
>>>> +
>>>> +  ti,sink-mode:
>>> Aren't these two mutually exclusive? Can same device operate in source
>>> and in sink mode simultaneously?
>> They're exclusive, yes. Will add that.
> Then either define constraints per variant in if:then: or maybe better
> use string enum. Not sure what applies where, so tricky to say which
> choice is better.
>
> Best regards,
> Krzysztof

Since there's already going to be an "if" block, it simplifies parsing 
to keep the booleans. My first attempt was this, but that doesn't work 
as I'd expect. Adding "slew-rate" to the example dts results in an 
error, so apparently the "if" block doesn't do what I think it would and 
I haven't figured out yet what the correct syntax must be:

if:
   properties:
     compatible:
       contains:
         const: ti,sn65dp159
then:
   properties:
     ti,sink-mode:
       type: boolean
       description:
         Force chip to operate in "sink" mode. Allows to use
         a DP159 chip (defaults to source) for incoming signals.
     ti,dvi-mode:
       type: boolean
       description: Makes the DP159 chip operate in DVI mode.
     slew-rate:
       $ref: /schemas/types.yaml#/definitions/uint32
       minimum: 0
       maximum: 3
       default: 3
       description: Set slew rate, 0 is slowest, 3 is fastest.
else:
   properties:
     ti,source-mode:
       type: boolean
       description:
         Force chip to operate in "source" mode. Allows to use
         a TMDS181 chip (which defaults to sink) as cable driver.



-- 
Mike Looijmans
System Expert

TOPIC Embedded Products B.V.
Materiaalweg 4, 5681 RJ Best
The Netherlands

T: +31 (0) 499 33 69 69
E: mike.looijmans@topic.nl
W: www.topic.nl




^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: [PATCH v4 1/2] dt-bindings: drm/bridge: ti-tmds181: Add TI TMDS181 and SN65DP159 bindings
  2025-09-02 14:41             ` Mike Looijmans
@ 2025-09-02 14:52               ` Mike Looijmans
  2025-09-02 15:32                 ` Krzysztof Kozlowski
  0 siblings, 1 reply; 13+ messages in thread
From: Mike Looijmans @ 2025-09-02 14:52 UTC (permalink / raw)
  To: Krzysztof Kozlowski
  Cc: dri-devel, Andrzej Hajda, Conor Dooley, David Airlie,
	Jernej Skrabec, Jonas Karlman, Krzysztof Kozlowski,
	Laurent Pinchart, Maarten Lankhorst, Maxime Ripard,
	Neil Armstrong, Rob Herring, Robert Foss, Simona Vetter,
	Thomas Zimmermann, devicetree, linux-kernel

On 9/2/25 16:41, Mike Looijmans wrote:
> On 9/2/25 15:46, Krzysztof Kozlowski wrote:
>> On 02/09/2025 10:46, Mike Looijmans wrote:
>>>>> +          endpoint:
>>>>> +            $ref: /schemas/media/video-interfaces.yaml#
>>>>> +            unevaluatedProperties: false
>>>>> +
>>>>> +      port@1:
>>>>> +        $ref: /schemas/graph.yaml#/$defs/port-base
>>>>> +        unevaluatedProperties: false
>>>>> +        description: Video port for HDMI output (panel or bridge)
>>>>> +
>>>>> +        properties:
>>>>> +          endpoint:
>>>>> +            $ref: /schemas/media/video-interfaces.yaml#
>>>>> +            unevaluatedProperties: false
>>>>> +
>>>>> +    required:
>>>>> +      - port@0
>>>>> +      - port@1
>>>>> +
>>>>> +  ti,source-mode:
>>>>> +    type: boolean
>>>>> +    description:
>>>>> +      Force chip to operate in "source" mode. Allows to use
>>>>> +      a TMDS181 chip (which defaults to sink) as cable driver.
>>>>> +
>>>>> +  ti,sink-mode:
>>>> Aren't these two mutually exclusive? Can same device operate in source
>>>> and in sink mode simultaneously?
>>> They're exclusive, yes. Will add that.
>> Then either define constraints per variant in if:then: or maybe better
>> use string enum. Not sure what applies where, so tricky to say which
>> choice is better.
>>
>> Best regards,
>> Krzysztof
>
> Since there's already going to be an "if" block, it simplifies parsing 
> to keep the booleans. My first attempt was this, but that doesn't work 
> as I'd expect. Adding "slew-rate" to the example dts results in an 
> error, so apparently the "if" block doesn't do what I think it would 
> and I haven't figured out yet what the correct syntax must be:
>
> if:
>   properties:
>     compatible:
>       contains:
>         const: ti,sn65dp159
> then:
>   properties:
>     ti,sink-mode:
>       type: boolean
>       description:
>         Force chip to operate in "sink" mode. Allows to use
>         a DP159 chip (defaults to source) for incoming signals.
>     ti,dvi-mode:
>       type: boolean
>       description: Makes the DP159 chip operate in DVI mode.
>     slew-rate:
>       $ref: /schemas/types.yaml#/definitions/uint32
>       minimum: 0
>       maximum: 3
>       default: 3
>       description: Set slew rate, 0 is slowest, 3 is fastest.
> else:
>   properties:
>     ti,source-mode:
>       type: boolean
>       description:
>         Force chip to operate in "source" mode. Allows to use
>         a TMDS181 chip (which defaults to sink) as cable driver.
>
Hmm, apparently one cannot "add" properties in the "if:" block? The 
opposite approach, disallowing properties, works, e.g.:

if:
   properties:
     compatible:
       contains:
         const: ti,sn65dp159
then:
   properties:
     ti,source-mode: false
else:
   properties:
     ti,sink-mode: false
     ti,dvi-mode: false
     slew-rate: false


This produces the wanted behavior, though it looks counter-intuitive to me.


-- 
Mike Looijmans




^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: [PATCH v4 1/2] dt-bindings: drm/bridge: ti-tmds181: Add TI TMDS181 and SN65DP159 bindings
  2025-09-02 14:52               ` Mike Looijmans
@ 2025-09-02 15:32                 ` Krzysztof Kozlowski
  0 siblings, 0 replies; 13+ messages in thread
From: Krzysztof Kozlowski @ 2025-09-02 15:32 UTC (permalink / raw)
  To: Mike Looijmans
  Cc: dri-devel, Andrzej Hajda, Conor Dooley, David Airlie,
	Jernej Skrabec, Jonas Karlman, Krzysztof Kozlowski,
	Laurent Pinchart, Maarten Lankhorst, Maxime Ripard,
	Neil Armstrong, Rob Herring, Robert Foss, Simona Vetter,
	Thomas Zimmermann, devicetree, linux-kernel

On 02/09/2025 16:52, Mike Looijmans wrote:
>> if:
>>   properties:
>>     compatible:
>>       contains:
>>         const: ti,sn65dp159
>> then:
>>   properties:
>>     ti,sink-mode:
>>       type: boolean
>>       description:
>>         Force chip to operate in "sink" mode. Allows to use
>>         a DP159 chip (defaults to source) for incoming signals.
>>     ti,dvi-mode:
>>       type: boolean
>>       description: Makes the DP159 chip operate in DVI mode.
>>     slew-rate:
>>       $ref: /schemas/types.yaml#/definitions/uint32
>>       minimum: 0
>>       maximum: 3
>>       default: 3
>>       description: Set slew rate, 0 is slowest, 3 is fastest.
>> else:
>>   properties:
>>     ti,source-mode:
>>       type: boolean
>>       description:
>>         Force chip to operate in "source" mode. Allows to use
>>         a TMDS181 chip (which defaults to sink) as cable driver.
>>
> Hmm, apparently one cannot "add" properties in the "if:" block? The 

One can, but should not. Define properties in top level and disallow them.

See also example-schema.


> opposite approach, disallowing properties, works, e.g.:
> 
> if:
>    properties:
>      compatible:
>        contains:
>          const: ti,sn65dp159
> then:
>    properties:
>      ti,source-mode: false
> else:
>    properties:
>      ti,sink-mode: false
>      ti,dvi-mode: false
>      slew-rate: false


So any device can work in any mode? Then this should be just enum with
different defaults.

Best regards,
Krzysztof

^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: [PATCH v4 1/2] dt-bindings: drm/bridge: ti-tmds181: Add TI TMDS181 and SN65DP159 bindings
  2025-09-01 14:29     ` [PATCH v4 1/2] dt-bindings: drm/bridge: ti-tmds181: Add TI TMDS181 and SN65DP159 bindings Mike Looijmans
  2025-09-02  6:53       ` Krzysztof Kozlowski
@ 2025-09-02 17:29       ` Maxime Ripard
  2025-09-03  6:17         ` Mike Looijmans
  1 sibling, 1 reply; 13+ messages in thread
From: Maxime Ripard @ 2025-09-02 17:29 UTC (permalink / raw)
  To: Mike Looijmans
  Cc: dri-devel, Andrzej Hajda, Conor Dooley, David Airlie,
	Jernej Skrabec, Jonas Karlman, Krzysztof Kozlowski,
	Laurent Pinchart, Maarten Lankhorst, Neil Armstrong, Rob Herring,
	Robert Foss, Simona Vetter, Thomas Zimmermann, devicetree,
	linux-kernel

[-- Attachment #1: Type: text/plain, Size: 1150 bytes --]

On Mon, Sep 01, 2025 at 04:29:01PM +0200, Mike Looijmans wrote:
> +  ti,retimer-threshold-hz:
> +    minimum: 25000000
> +    maximum: 600000000
> +    default: 200000000
> +    description:
> +      Cross-over point. Up until this pixel clock frequency
> +      the chip remains in the low-power redriver mode. Above
> +      the threshold the chip should operate in retimer mode.

Why should anyone want to tune this at the firmware level?

> +  ti,dvi-mode:
> +    type: boolean
> +    description: Makes the DP159 chip operate in DVI mode.

Ditto. Both describe policy, not hardware.

> +  ti,slew-rate:
> +    $ref: /schemas/types.yaml#/definitions/uint32
> +    minimum: 0
> +    maximum: 3
> +    default: 3
> +    description: Set slew rate, 0 is slowest, 3 is fastest.
> +
> +  ti,disable-equalizer:
> +    type: boolean
> +    description: Disable the equalizer (to save power).

Why shouldn't we disable all the time then? Again, it looks like a
policy, and not something that should be set in stone in the firmware.

> +  ti,adaptive-equalizer:
> +    type: boolean
> +    description: Set the equalizer to adaptive mode.

Ditto.

Maxime

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 273 bytes --]

^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: [PATCH v4 1/2] dt-bindings: drm/bridge: ti-tmds181: Add TI TMDS181 and SN65DP159 bindings
  2025-09-02 17:29       ` Maxime Ripard
@ 2025-09-03  6:17         ` Mike Looijmans
  2025-09-03 11:12           ` Mike Looijmans
  2025-09-03 15:25           ` Dmitry Baryshkov
  0 siblings, 2 replies; 13+ messages in thread
From: Mike Looijmans @ 2025-09-03  6:17 UTC (permalink / raw)
  To: Maxime Ripard
  Cc: dri-devel, Andrzej Hajda, Conor Dooley, David Airlie,
	Jernej Skrabec, Jonas Karlman, Krzysztof Kozlowski,
	Laurent Pinchart, Maarten Lankhorst, Neil Armstrong, Rob Herring,
	Robert Foss, Simona Vetter, Thomas Zimmermann, devicetree,
	linux-kernel

On 02-09-2025 19:29, Maxime Ripard wrote:
> On Mon, Sep 01, 2025 at 04:29:01PM +0200, Mike Looijmans wrote:
>> +  ti,retimer-threshold-hz:
>> +    minimum: 25000000
>> +    maximum: 600000000
>> +    default: 200000000
>> +    description:
>> +      Cross-over point. Up until this pixel clock frequency
>> +      the chip remains in the low-power redriver mode. Above
>> +      the threshold the chip should operate in retimer mode.
> Why should anyone want to tune this at the firmware level?

It's a board property. You'd set this based on the hardware you've soldered 
on. If your clock and serdes are good quality, there's no need for the chip to 
be in retimer mode (it will consume more power and actually make the signal 
worse). At higher speeds, that situation may change, hence the need for a way 
to describe that. The chip has a similar function built in, but with only 2 
choices of cross-over point.

To tune these parameters (retimer, equalizer), you'll probably have to take 
your equipment to a test facility (like we did). It's not something that 
end-users would want to tune themselves.

Most of these settings can also be done using pin strapping. I guess it'd be 
helpful if I added that to the description.


>> +  ti,dvi-mode:
>> +    type: boolean
>> +    description: Makes the DP159 chip operate in DVI mode.
> Ditto. Both describe policy, not hardware.

I would set this flag if I've soldered on a DVI connector instead of a HDMI 
one. I'd consider that hardware.


>> +  ti,slew-rate:
>> +    $ref: /schemas/types.yaml#/definitions/uint32
>> +    minimum: 0
>> +    maximum: 3
>> +    default: 3
>> +    description: Set slew rate, 0 is slowest, 3 is fastest.
>> +
>> +  ti,disable-equalizer:
>> +    type: boolean
>> +    description: Disable the equalizer (to save power).
> Why shouldn't we disable all the time then? Again, it looks like a
> policy, and not something that should be set in stone in the firmware.

Again, board property. The equalizer is there to make up for things like PCB 
losses (mismatch maybe?) or serdes running at (or beyond) its maximum. Again, 
depending on your board you may need this or not. It replaces a pinstrapping 
option.


>> +  ti,adaptive-equalizer:
>> +    type: boolean
>> +    description: Set the equalizer to adaptive mode.

It's the default setting of the chip so this flag will be removed in the next 
version.


> Maxime

Mike.





^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: [PATCH v4 1/2] dt-bindings: drm/bridge: ti-tmds181: Add TI TMDS181 and SN65DP159 bindings
  2025-09-03  6:17         ` Mike Looijmans
@ 2025-09-03 11:12           ` Mike Looijmans
  2025-09-03 15:25           ` Dmitry Baryshkov
  1 sibling, 0 replies; 13+ messages in thread
From: Mike Looijmans @ 2025-09-03 11:12 UTC (permalink / raw)
  To: Maxime Ripard
  Cc: dri-devel, Andrzej Hajda, Conor Dooley, David Airlie,
	Jernej Skrabec, Jonas Karlman, Krzysztof Kozlowski,
	Laurent Pinchart, Maarten Lankhorst, Neil Armstrong, Rob Herring,
	Robert Foss, Simona Vetter, Thomas Zimmermann, devicetree,
	linux-kernel

On 03-09-2025 08:17, Mike Looijmans wrote:
> On 02-09-2025 19:29, Maxime Ripard wrote:
>> On Mon, Sep 01, 2025 at 04:29:01PM +0200, Mike Looijmans wrote:
>>> +  ti,retimer-threshold-hz:
>>> +    minimum: 25000000
>>> +    maximum: 600000000
>>> +    default: 200000000
>>> +    description:
>>> +      Cross-over point. Up until this pixel clock frequency
>>> +      the chip remains in the low-power redriver mode. Above
>>> +      the threshold the chip should operate in retimer mode.
>> Why should anyone want to tune this at the firmware level?
>
> It's a board property. You'd set this based on the hardware you've soldered 
> on. If your clock and serdes are good quality, there's no need for the chip 
> to be in retimer mode (it will consume more power and actually make the 
> signal worse). At higher speeds, that situation may change, hence the need 
> for a way to describe that. The chip has a similar function built in, but 
> with only 2 choices of cross-over point.
>
> To tune these parameters (retimer, equalizer), you'll probably have to take 
> your equipment to a test facility (like we did). It's not something that 
> end-users would want to tune themselves.
>
> Most of these settings can also be done using pin strapping. I guess it'd be 
> helpful if I added that to the description.

Looking back at the datasheet - once you enable the I2C interface of the pin, 
many of the pinstrapping options are no longer available (such as slew-rate, 
dvi/hdmi mode, equalizer and termination). The devicetree properties allow 
these settings to be applied again.

> ...
>
M.




^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: [PATCH v4 1/2] dt-bindings: drm/bridge: ti-tmds181: Add TI TMDS181 and SN65DP159 bindings
  2025-09-03  6:17         ` Mike Looijmans
  2025-09-03 11:12           ` Mike Looijmans
@ 2025-09-03 15:25           ` Dmitry Baryshkov
  1 sibling, 0 replies; 13+ messages in thread
From: Dmitry Baryshkov @ 2025-09-03 15:25 UTC (permalink / raw)
  To: Mike Looijmans
  Cc: Maxime Ripard, dri-devel, Andrzej Hajda, Conor Dooley,
	David Airlie, Jernej Skrabec, Jonas Karlman, Krzysztof Kozlowski,
	Laurent Pinchart, Maarten Lankhorst, Neil Armstrong, Rob Herring,
	Robert Foss, Simona Vetter, Thomas Zimmermann, devicetree,
	linux-kernel

On Wed, Sep 03, 2025 at 08:17:33AM +0200, Mike Looijmans wrote:
> On 02-09-2025 19:29, Maxime Ripard wrote:
> > On Mon, Sep 01, 2025 at 04:29:01PM +0200, Mike Looijmans wrote:
> > > +  ti,retimer-threshold-hz:
> > > +    minimum: 25000000
> > > +    maximum: 600000000
> > > +    default: 200000000
> > > +    description:
> > > +      Cross-over point. Up until this pixel clock frequency
> > > +      the chip remains in the low-power redriver mode. Above
> > > +      the threshold the chip should operate in retimer mode.
> > Why should anyone want to tune this at the firmware level?
> 
> It's a board property. You'd set this based on the hardware you've soldered
> on. If your clock and serdes are good quality, there's no need for the chip
> to be in retimer mode (it will consume more power and actually make the
> signal worse). At higher speeds, that situation may change, hence the need
> for a way to describe that. The chip has a similar function built in, but
> with only 2 choices of cross-over point.
> 
> To tune these parameters (retimer, equalizer), you'll probably have to take
> your equipment to a test facility (like we did). It's not something that
> end-users would want to tune themselves.
> 
> Most of these settings can also be done using pin strapping. I guess it'd be
> helpful if I added that to the description.
> 
> 
> > > +  ti,dvi-mode:
> > > +    type: boolean
> > > +    description: Makes the DP159 chip operate in DVI mode.
> > Ditto. Both describe policy, not hardware.
> 
> I would set this flag if I've soldered on a DVI connector instead of a HDMI
> one. I'd consider that hardware.

Do you need to set this if you have DVI monitor attached to the HDMI
connector via the passive cable?

As for the connector type, you can check it in the .atomic_enable by
checking drm_connector::connector_type.

-- 
With best wishes
Dmitry

^ permalink raw reply	[flat|nested] 13+ messages in thread

end of thread, other threads:[~2025-09-03 15:25 UTC | newest]

Thread overview: 13+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
     [not found] <1b153bce-a66a-45ee-a5c6-963ea6fb1c82.949ef384-8293-46b8-903f-40a477c056ae.d6331613-729b-4f92-9c2d-d2abe6df38d5@emailsignatures365.codetwo.com>
2025-09-01 14:29 ` [PATCH v4 0/2] drm: bridge: Add TI tmds181 and sn65dp159 driver Mike Looijmans
     [not found]   ` <1b153bce-a66a-45ee-a5c6-963ea6fb1c82.949ef384-8293-46b8-903f-40a477c056ae.edc18686-244f-441e-a6ac-0b62492b96c8@emailsignatures365.codetwo.com>
2025-09-01 14:29     ` [PATCH v4 1/2] dt-bindings: drm/bridge: ti-tmds181: Add TI TMDS181 and SN65DP159 bindings Mike Looijmans
2025-09-02  6:53       ` Krzysztof Kozlowski
2025-09-02  8:46         ` Mike Looijmans
2025-09-02 13:46           ` Krzysztof Kozlowski
2025-09-02 14:41             ` Mike Looijmans
2025-09-02 14:52               ` Mike Looijmans
2025-09-02 15:32                 ` Krzysztof Kozlowski
2025-09-02 17:29       ` Maxime Ripard
2025-09-03  6:17         ` Mike Looijmans
2025-09-03 11:12           ` Mike Looijmans
2025-09-03 15:25           ` Dmitry Baryshkov
     [not found]   ` <1b153bce-a66a-45ee-a5c6-963ea6fb1c82.949ef384-8293-46b8-903f-40a477c056ae.cb04edf6-4f97-4f30-891a-5e11da8a5e1f@emailsignatures365.codetwo.com>
2025-09-01 14:29     ` [PATCH v4 2/2] drm: bridge: Add TI tmds181 and sn65dp159 driver Mike Looijmans

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).