[PATCH v2 12/27] drm/rockchip: dw_hdmi_qp: Add VRR support

From: Nicolas Frattaroli

Date: Thu Nov 05 2026 - 11:19:57 EST


Register the vrr_capable property on the connector for RK3588, where VRR
is implemented, as well as the other VRR connector properties.

In the encoder's atomic_check callback, the vrr_capable property, if
present, is then set to true if the sink supports VRR. The display limit
properties are also updated accordingly there, using the helper.

Signed-off-by: Nicolas Frattaroli <nicolas.frattaroli@xxxxxxxxxxxxx>
---
drivers/gpu/drm/rockchip/dw_hdmi_qp-rockchip.c | 30 ++++++++++++++++++++++++++
1 file changed, 30 insertions(+)

diff --git a/drivers/gpu/drm/rockchip/dw_hdmi_qp-rockchip.c b/drivers/gpu/drm/rockchip/dw_hdmi_qp-rockchip.c
index f2a1ea8dfefa..dcde50bca36b 100644
--- a/drivers/gpu/drm/rockchip/dw_hdmi_qp-rockchip.c
+++ b/drivers/gpu/drm/rockchip/dw_hdmi_qp-rockchip.c
@@ -89,6 +89,9 @@
#define RK_COLOR_FMT_YUV444 0x2
#define RK_COLOR_FMT_YUV420 0x3

+#define RK_VRR_DISPLAY_MODES (BIT(VRR_DISPLAY_MODE_GAME) | \
+ BIT(VRR_DISPLAY_MODE_OFF))
+
struct rockchip_hdmi_qp {
struct device *dev;
struct regmap *regmap;
@@ -195,6 +198,7 @@ dw_hdmi_qp_rockchip_encoder_atomic_check(struct drm_encoder *encoder,
struct drm_crtc_state *crtc_state,
struct drm_connector_state *conn_state)
{
+ struct drm_connector *connector = conn_state->connector;
struct rockchip_crtc_state *s = to_rockchip_crtc_state(crtc_state);
struct rockchip_hdmi_qp *hdmi = to_rockchip_hdmi_qp(encoder);
union phy_configure_opts phy_cfg = {};
@@ -205,6 +209,12 @@ dw_hdmi_qp_rockchip_encoder_atomic_check(struct drm_encoder *encoder,
if (ingest_fmt < 0)
return -EINVAL;

+ if (connector->vrr_capable_property) {
+ drm_connector_set_vrr_capable_property(connector,
+ drm_display_info_is_vrr_capable(&connector->display_info));
+ drm_connector_hdmi_update_vrr_limits(connector, &crtc_state->mode);
+ }
+
if (hdmi->tmds_char_rate == conn_state->hdmi.tmds_char_rate &&
s->output_bpc == conn_state->hdmi.output_bpc &&
s->bus_format == ingest_fmt)
@@ -552,6 +562,7 @@ struct rockchip_hdmi_qp_cfg {
unsigned int port_ids[MAX_HDMI_PORT_NUM];
const struct rockchip_hdmi_qp_ctrl_ops *ctrl_ops;
const struct dw_hdmi_qp_phy_ops *phy_ops;
+ bool supports_vrr;
};

static const struct rockchip_hdmi_qp_cfg rk3576_hdmi_cfg = {
@@ -571,6 +582,7 @@ static const struct rockchip_hdmi_qp_cfg rk3588_hdmi_cfg = {
},
.ctrl_ops = &rk3588_hdmi_ctrl_ops,
.phy_ops = &rk3588_hdmi_phy_ops,
+ .supports_vrr = true,
};

static const struct of_device_id dw_hdmi_qp_rockchip_dt_ids[] = {
@@ -729,6 +741,24 @@ static int dw_hdmi_qp_rockchip_bind(struct device *dev, struct device *master,
return dev_err_probe(dev, PTR_ERR(connector),
"Failed to init bridge connector\n");

+ if (cfg->supports_vrr) {
+ ret = drm_connector_attach_vrr_capable_property(connector);
+ if (ret)
+ return dev_err_probe(hdmi->dev, ret,
+ "Failed to attach 'vrr_capable' property\n");
+
+ ret = drm_connector_attach_vrr_display_mode_property(connector,
+ RK_VRR_DISPLAY_MODES);
+ if (ret)
+ return dev_err_probe(hdmi->dev, ret,
+ "Failed to attach 'vrr_display_mode' property\n");
+
+ ret = drm_connector_attach_vrr_display_limits_properties(connector);
+ if (ret)
+ return dev_err_probe(hdmi->dev, ret,
+ "Failed to attach VRR display limits properties\n");
+ }
+
platform_set_drvdata(pdev, hdmi);

return 0;

--
2.56.0