[PATCH 1/5] drm/bridge: dw-hdmi-qp: Provide HDMI Vendor Specific InfoFrame

Cristian Ciocaltea posted 5 patches 2 weeks, 1 day ago
There is a newer version of this series
[PATCH 1/5] drm/bridge: dw-hdmi-qp: Provide HDMI Vendor Specific InfoFrame
Posted by Cristian Ciocaltea 2 weeks, 1 day ago
Since commit b626b1a1c9cc ("drm/bridge: refactor HDMI InfoFrame
callbacks"), the following warning is generated:

  [   13.654149] rockchip-drm display-subsystem: [drm] HDMI VSI not supported

Add the missing support for sending HDMI Vendor-Specific Infoframes.

Additionally, introduce the dw_hdmi_qp_write_pkt() utility function, as
a prerequisite to rework the *_write_*_infoframe() callbacks and get rid
of some boilerplate code.

Signed-off-by: Cristian Ciocaltea <cristian.ciocaltea@collabora.com>
---
 drivers/gpu/drm/bridge/synopsys/dw-hdmi-qp.c | 32 +++++++++++++++++++++++++---
 drivers/gpu/drm/bridge/synopsys/dw-hdmi-qp.h |  2 ++
 2 files changed, 31 insertions(+), 3 deletions(-)

diff --git a/drivers/gpu/drm/bridge/synopsys/dw-hdmi-qp.c b/drivers/gpu/drm/bridge/synopsys/dw-hdmi-qp.c
index 036316e2b60d..b37af6a7e194 100644
--- a/drivers/gpu/drm/bridge/synopsys/dw-hdmi-qp.c
+++ b/drivers/gpu/drm/bridge/synopsys/dw-hdmi-qp.c
@@ -11,6 +11,7 @@
 #include <linux/export.h>
 #include <linux/i2c.h>
 #include <linux/irq.h>
+#include <linux/minmax.h>
 #include <linux/module.h>
 #include <linux/mutex.h>
 #include <linux/of.h>
@@ -969,9 +970,9 @@ static int dw_hdmi_qp_bridge_clear_avi_infoframe(struct drm_bridge *bridge)
 
 static int dw_hdmi_qp_bridge_clear_hdmi_infoframe(struct drm_bridge *bridge)
 {
-	/* FIXME: add support for this InfoFrame */
+	struct dw_hdmi_qp *hdmi = bridge->driver_private;
 
-	drm_warn_once(bridge->encoder->dev, "HDMI VSI not supported\n");
+	dw_hdmi_qp_mod(hdmi, 0, PKTSCHED_VSI_TX_EN, PKTSCHED_PKT_EN);
 
 	return 0;
 }
@@ -998,6 +999,18 @@ static int dw_hdmi_qp_bridge_clear_audio_infoframe(struct drm_bridge *bridge)
 	return 0;
 }
 
+static void dw_hdmi_qp_write_pkt(struct dw_hdmi_qp *hdmi, const u8 *buffer,
+				 size_t start, size_t len, unsigned int reg)
+{
+	u32 val = 0;
+	size_t i;
+
+	for (i = start; i < start + len; i++)
+		val |= buffer[i] << ((i % 4) * 8);
+
+	dw_hdmi_qp_write(hdmi, val, reg);
+}
+
 static int dw_hdmi_qp_bridge_write_avi_infoframe(struct drm_bridge *bridge,
 						 const u8 *buffer, size_t len)
 {
@@ -1011,9 +1024,22 @@ static int dw_hdmi_qp_bridge_write_avi_infoframe(struct drm_bridge *bridge,
 static int dw_hdmi_qp_bridge_write_hdmi_infoframe(struct drm_bridge *bridge,
 						  const u8 *buffer, size_t len)
 {
+	struct dw_hdmi_qp *hdmi = bridge->driver_private;
+	size_t i;
+
 	dw_hdmi_qp_bridge_clear_hdmi_infoframe(bridge);
 
-	/* FIXME: add support for the HDMI VSI */
+	/* VSI packet header */
+	dw_hdmi_qp_write_pkt(hdmi, buffer, 1, 2, PKT_VSI_CONTENTS0);
+
+	/* VSI packet body */
+	for (i = 0; i < len - 3; i += 4)
+		dw_hdmi_qp_write_pkt(hdmi, buffer + 3, i, min(len - i - 3, 4),
+				     PKT_VSI_CONTENTS1 + i);
+
+	dw_hdmi_qp_mod(hdmi, 0, PKTSCHED_VSI_FIELDRATE, PKTSCHED_PKT_CONFIG1);
+	dw_hdmi_qp_mod(hdmi, PKTSCHED_VSI_TX_EN, PKTSCHED_VSI_TX_EN,
+		       PKTSCHED_PKT_EN);
 
 	return 0;
 }
diff --git a/drivers/gpu/drm/bridge/synopsys/dw-hdmi-qp.h b/drivers/gpu/drm/bridge/synopsys/dw-hdmi-qp.h
index 91a15f82e32a..53688eae8dba 100644
--- a/drivers/gpu/drm/bridge/synopsys/dw-hdmi-qp.h
+++ b/drivers/gpu/drm/bridge/synopsys/dw-hdmi-qp.h
@@ -198,6 +198,7 @@
 #define PKTSCHED_PRQUEUE2_CONFIG2			0xa94
 #define PKTSCHED_PKT_CONFIG0				0xa98
 #define PKTSCHED_PKT_CONFIG1				0xa9c
+#define PKTSCHED_VSI_FIELDRATE				BIT(14)
 #define PKTSCHED_DRMI_FIELDRATE				BIT(13)
 #define PKTSCHED_AVI_FIELDRATE				BIT(12)
 #define PKTSCHED_PKT_CONFIG2				0xaa0
@@ -206,6 +207,7 @@
 #define PKTSCHED_DRMI_TX_EN				BIT(17)
 #define PKTSCHED_AUDI_TX_EN				BIT(15)
 #define PKTSCHED_AVI_TX_EN				BIT(13)
+#define PKTSCHED_VSI_TX_EN				BIT(12)
 #define PKTSCHED_EMP_CVTEM_TX_EN			BIT(10)
 #define PKTSCHED_AMD_TX_EN				BIT(8)
 #define PKTSCHED_GCP_TX_EN				BIT(3)

-- 
2.52.0
Re: [PATCH 1/5] drm/bridge: dw-hdmi-qp: Provide HDMI Vendor Specific InfoFrame
Posted by Daniel Stone 1 week, 4 days ago
Hi Cristian,

On Sun, 25 Jan 2026 at 00:23, Cristian Ciocaltea
<cristian.ciocaltea@collabora.com> wrote:
> +       /* VSI packet body */
> +       for (i = 0; i < len - 3; i += 4)
> +               dw_hdmi_qp_write_pkt(hdmi, buffer + 3, i, min(len - i - 3, 4),
> +                                    PKT_VSI_CONTENTS1 + i);

Given that this for loop occurs in all the users (other than when len
< 4 where it's not required), why not move it into the
dw_hdmi_qp_write_pkt() helper itself, such that the calls for each
infoframe could be dw_hdmi_qp_write_pkt(hdmi, buffer + 3, len,
PKT_VSI_CONTENTS1 /* base reg, incremented by helper */)?

Cheers,
Daniel
Re: [PATCH 1/5] drm/bridge: dw-hdmi-qp: Provide HDMI Vendor Specific InfoFrame
Posted by Cristian Ciocaltea 1 week, 4 days ago
Hi Daniel,

On 1/28/26 2:11 PM, Daniel Stone wrote:
> Hi Cristian,
> 
> On Sun, 25 Jan 2026 at 00:23, Cristian Ciocaltea
> <cristian.ciocaltea@collabora.com> wrote:
>> +       /* VSI packet body */
>> +       for (i = 0; i < len - 3; i += 4)
>> +               dw_hdmi_qp_write_pkt(hdmi, buffer + 3, i, min(len - i - 3, 4),
>> +                                    PKT_VSI_CONTENTS1 + i);
> 
> Given that this for loop occurs in all the users (other than when len
> < 4 where it's not required), why not move it into the
> dw_hdmi_qp_write_pkt() helper itself, such that the calls for each
> infoframe could be dw_hdmi_qp_write_pkt(hdmi, buffer + 3, len,
> PKT_VSI_CONTENTS1 /* base reg, incremented by helper */)?

Yeah, initially planned to keep the helper simple and allow more flexibility in
the callbacks.  Probably now it makes sense to also write the packet header via
the helper, not just the body, since this is also handled similarly in all
cases.

Thanks,
Cristian