* [PATCH v2 0/5] High color depth support for RK3576/RK3588 HDMI output
@ 2025-08-25 10:08 Cristian Ciocaltea
2025-08-25 10:08 ` [PATCH v2 1/5] drm/rockchip: vop2: Check bpc before switching DCLK source Cristian Ciocaltea
` (5 more replies)
0 siblings, 6 replies; 8+ messages in thread
From: Cristian Ciocaltea @ 2025-08-25 10:08 UTC (permalink / raw)
To: Sandy Huang, Heiko Stübner, Andy Yan, Maarten Lankhorst,
Maxime Ripard, Thomas Zimmermann, David Airlie, Simona Vetter,
Andrzej Hajda, Neil Armstrong, Robert Foss, Laurent Pinchart,
Jonas Karlman, Jernej Skrabec
Cc: kernel, dri-devel, linux-arm-kernel, linux-rockchip, linux-kernel
Since both Rockchip RK3576 and RK3588 SoCs are capable of handling 10
bpc color depth HDMI output and we've already landed the required HDPTX
PHY driver changes to support the setup, let's add the missing bits and
pieces to VOP2, DW HDMI QP encoder and bridge library.
Please note this conflicts with the HDMI CEC series [1], hence I added
that as a b4-managed dependency.
[1] https://lore.kernel.org/all/20250825-rk3588-hdmi-cec-v3-0-95324fb22592@collabora.com/
Signed-off-by: Cristian Ciocaltea <cristian.ciocaltea@collabora.com>
---
Changes in v2:
- Replaced patch 'drm/rockchip: vop2: Add high color depth support' with
'drm/rockchip: vop2: Check bpc before switching DCLK source'
- Rebased series onto next-20250825 while adding the HDMI CEC series as
a dependency
- Link to v1: https://lore.kernel.org/r/20250721-rk3588-10bpc-v1-0-e95a4abcf482@collabora.com
---
Cristian Ciocaltea (5):
drm/rockchip: vop2: Check bpc before switching DCLK source
drm/bridge: dw-hdmi-qp: Handle platform supported formats and color depth
drm/rockchip: dw_hdmi_qp: Switch to phy_configure()
drm/rockchip: dw_hdmi_qp: Use bit macros for RK3576 regs
drm/rockchip: dw_hdmi_qp: Add high color depth support
drivers/gpu/drm/bridge/synopsys/dw-hdmi-qp.c | 11 ++-
drivers/gpu/drm/rockchip/dw_hdmi_qp-rockchip.c | 113 ++++++++++++++++++-------
drivers/gpu/drm/rockchip/rockchip_drm_vop2.c | 60 +++++++------
include/drm/bridge/dw_hdmi_qp.h | 4 +
4 files changed, 130 insertions(+), 58 deletions(-)
---
base-commit: 0c5416a62c0e4df1b3f79b5c74c03cd48df51357
change-id: 20250721-rk3588-10bpc-85ff4c228e63
prerequisite-change-id: 20250703-rk3588-hdmi-cec-cea8f523df48:v3
prerequisite-patch-id: 6d0ed574c38c15e66677e704b2d0260226430d78
prerequisite-patch-id: 014adacca1c18f77c1cd80cf6877aa5d653b8f48
prerequisite-patch-id: 79fd783c35b5979cc99f3f0420309f63ac49ad01
prerequisite-patch-id: 4e7d4735f222b9fabfff3987c578c5d954579ae5
prerequisite-patch-id: 7960aba70d8916b60e81187cfa0253025b532774
prerequisite-patch-id: 2f0338d330aee42e0acc62fb815f08a3eeef58aa
^ permalink raw reply [flat|nested] 8+ messages in thread
* [PATCH v2 1/5] drm/rockchip: vop2: Check bpc before switching DCLK source
2025-08-25 10:08 [PATCH v2 0/5] High color depth support for RK3576/RK3588 HDMI output Cristian Ciocaltea
@ 2025-08-25 10:08 ` Cristian Ciocaltea
2025-08-29 15:35 ` Daniel Stone
2025-08-25 10:08 ` [PATCH v2 2/5] drm/bridge: dw-hdmi-qp: Handle platform supported formats and color depth Cristian Ciocaltea
` (4 subsequent siblings)
5 siblings, 1 reply; 8+ messages in thread
From: Cristian Ciocaltea @ 2025-08-25 10:08 UTC (permalink / raw)
To: Sandy Huang, Heiko Stübner, Andy Yan, Maarten Lankhorst,
Maxime Ripard, Thomas Zimmermann, David Airlie, Simona Vetter,
Andrzej Hajda, Neil Armstrong, Robert Foss, Laurent Pinchart,
Jonas Karlman, Jernej Skrabec
Cc: kernel, dri-devel, linux-arm-kernel, linux-rockchip, linux-kernel
When making use of the HDMI PHY PLL as a VOP2 DCLK source, it's output
rate does normally match the mode clock. But this is only applicable
for default color depth of 8 bpc. For higher depths, the output clock
is further divided by the hardware according to the formula:
output rate = PHY PLL rate * 8 / bpc
Hence there is no need for VOP2 to compensate for bpc when adjusting
DCLK, but it is required to do so when computing its maximum operating
frequency.
Take color depth into consideration before deciding to switch DCLK
source.
Signed-off-by: Cristian Ciocaltea <cristian.ciocaltea@collabora.com>
---
drivers/gpu/drm/rockchip/rockchip_drm_vop2.c | 60 +++++++++++++++++-----------
1 file changed, 36 insertions(+), 24 deletions(-)
diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_vop2.c b/drivers/gpu/drm/rockchip/rockchip_drm_vop2.c
index b50927a824b4020a7ffd57974070ed202cd8b838..977ccbf163448bc1a0423b8af707e9b2cf9b4be6 100644
--- a/drivers/gpu/drm/rockchip/rockchip_drm_vop2.c
+++ b/drivers/gpu/drm/rockchip/rockchip_drm_vop2.c
@@ -101,7 +101,7 @@ enum vop2_afbc_format {
VOP2_AFBC_FMT_INVALID = -1,
};
-#define VOP2_MAX_DCLK_RATE 600000000
+#define VOP2_MAX_DCLK_RATE 600000000UL
/*
* bus-format types.
@@ -1737,36 +1737,48 @@ static void vop2_crtc_atomic_enable(struct drm_crtc *crtc,
* Switch to HDMI PHY PLL as DCLK source for display modes up
* to 4K@60Hz, if available, otherwise keep using the system CRU.
*/
- if ((vop2->pll_hdmiphy0 || vop2->pll_hdmiphy1) && clock <= VOP2_MAX_DCLK_RATE) {
- drm_for_each_encoder_mask(encoder, crtc->dev, crtc_state->encoder_mask) {
- struct rockchip_encoder *rkencoder = to_rockchip_encoder(encoder);
+ if (vop2->pll_hdmiphy0 || vop2->pll_hdmiphy1) {
+ unsigned long max_dclk;
- if (rkencoder->crtc_endpoint_id == ROCKCHIP_VOP2_EP_HDMI0) {
- if (!vop2->pll_hdmiphy0)
- break;
+ if (vcstate->output_bpc > 8)
+ max_dclk = DIV_ROUND_CLOSEST_ULL(VOP2_MAX_DCLK_RATE * 8,
+ vcstate->output_bpc);
+ else
+ max_dclk = VOP2_MAX_DCLK_RATE;
- if (!vp->dclk_src)
- vp->dclk_src = clk_get_parent(vp->dclk);
+ if (clock <= max_dclk) {
+ drm_for_each_encoder_mask(encoder, crtc->dev, crtc_state->encoder_mask) {
+ struct rockchip_encoder *rkencoder = to_rockchip_encoder(encoder);
- ret = clk_set_parent(vp->dclk, vop2->pll_hdmiphy0);
- if (ret < 0)
- drm_warn(vop2->drm,
- "Could not switch to HDMI0 PHY PLL: %d\n", ret);
- break;
- }
+ if (rkencoder->crtc_endpoint_id == ROCKCHIP_VOP2_EP_HDMI0) {
+ if (!vop2->pll_hdmiphy0)
+ break;
+
+ if (!vp->dclk_src)
+ vp->dclk_src = clk_get_parent(vp->dclk);
- if (rkencoder->crtc_endpoint_id == ROCKCHIP_VOP2_EP_HDMI1) {
- if (!vop2->pll_hdmiphy1)
+ ret = clk_set_parent(vp->dclk, vop2->pll_hdmiphy0);
+ if (ret < 0)
+ drm_warn(vop2->drm,
+ "Could not switch to HDMI0 PHY PLL: %d\n",
+ ret);
break;
+ }
- if (!vp->dclk_src)
- vp->dclk_src = clk_get_parent(vp->dclk);
+ if (rkencoder->crtc_endpoint_id == ROCKCHIP_VOP2_EP_HDMI1) {
+ if (!vop2->pll_hdmiphy1)
+ break;
- ret = clk_set_parent(vp->dclk, vop2->pll_hdmiphy1);
- if (ret < 0)
- drm_warn(vop2->drm,
- "Could not switch to HDMI1 PHY PLL: %d\n", ret);
- break;
+ if (!vp->dclk_src)
+ vp->dclk_src = clk_get_parent(vp->dclk);
+
+ ret = clk_set_parent(vp->dclk, vop2->pll_hdmiphy1);
+ if (ret < 0)
+ drm_warn(vop2->drm,
+ "Could not switch to HDMI1 PHY PLL: %d\n",
+ ret);
+ break;
+ }
}
}
}
--
2.50.1
^ permalink raw reply related [flat|nested] 8+ messages in thread
* [PATCH v2 2/5] drm/bridge: dw-hdmi-qp: Handle platform supported formats and color depth
2025-08-25 10:08 [PATCH v2 0/5] High color depth support for RK3576/RK3588 HDMI output Cristian Ciocaltea
2025-08-25 10:08 ` [PATCH v2 1/5] drm/rockchip: vop2: Check bpc before switching DCLK source Cristian Ciocaltea
@ 2025-08-25 10:08 ` Cristian Ciocaltea
2025-08-25 10:08 ` [PATCH v2 3/5] drm/rockchip: dw_hdmi_qp: Switch to phy_configure() Cristian Ciocaltea
` (3 subsequent siblings)
5 siblings, 0 replies; 8+ messages in thread
From: Cristian Ciocaltea @ 2025-08-25 10:08 UTC (permalink / raw)
To: Sandy Huang, Heiko Stübner, Andy Yan, Maarten Lankhorst,
Maxime Ripard, Thomas Zimmermann, David Airlie, Simona Vetter,
Andrzej Hajda, Neil Armstrong, Robert Foss, Laurent Pinchart,
Jonas Karlman, Jernej Skrabec
Cc: kernel, dri-devel, linux-arm-kernel, linux-rockchip, linux-kernel
Extend struct dw_hdmi_qp_plat_data to include the supported display
output formats and maximum bits per color channel. When provided by the
platform driver, use them to setup the HDMI bridge accordingly.
Additionally, improve debug logging in dw_hdmi_qp_bridge_atomic_enable()
to also show the current HDMI output format and bpc.
Signed-off-by: Cristian Ciocaltea <cristian.ciocaltea@collabora.com>
---
drivers/gpu/drm/bridge/synopsys/dw-hdmi-qp.c | 11 +++++++++--
include/drm/bridge/dw_hdmi_qp.h | 4 ++++
2 files changed, 13 insertions(+), 2 deletions(-)
diff --git a/drivers/gpu/drm/bridge/synopsys/dw-hdmi-qp.c b/drivers/gpu/drm/bridge/synopsys/dw-hdmi-qp.c
index 42a90e0383061dad6c8416af21b27db7a3ba6d7d..8ff8ea8e0714ed6d6fa4b7865c86d04c32565d90 100644
--- a/drivers/gpu/drm/bridge/synopsys/dw-hdmi-qp.c
+++ b/drivers/gpu/drm/bridge/synopsys/dw-hdmi-qp.c
@@ -869,8 +869,9 @@ static void dw_hdmi_qp_bridge_atomic_enable(struct drm_bridge *bridge,
return;
if (connector->display_info.is_hdmi) {
- dev_dbg(hdmi->dev, "%s mode=HDMI rate=%llu\n",
- __func__, conn_state->hdmi.tmds_char_rate);
+ dev_dbg(hdmi->dev, "%s mode=HDMI %s rate=%llu bpc=%u\n", __func__,
+ drm_hdmi_connector_get_output_format_name(conn_state->hdmi.output_format),
+ conn_state->hdmi.tmds_char_rate, conn_state->hdmi.output_bpc);
op_mode = 0;
hdmi->tmds_char_rate = conn_state->hdmi.tmds_char_rate;
} else {
@@ -1299,6 +1300,12 @@ struct dw_hdmi_qp *dw_hdmi_qp_bind(struct platform_device *pdev,
hdmi->bridge.vendor = "Synopsys";
hdmi->bridge.product = "DW HDMI QP TX";
+ if (plat_data->supported_formats)
+ hdmi->bridge.supported_formats = plat_data->supported_formats;
+
+ if (plat_data->max_bpc)
+ hdmi->bridge.max_bpc = plat_data->max_bpc;
+
hdmi->bridge.ddc = dw_hdmi_qp_i2c_adapter(hdmi);
if (IS_ERR(hdmi->bridge.ddc))
return ERR_CAST(hdmi->bridge.ddc);
diff --git a/include/drm/bridge/dw_hdmi_qp.h b/include/drm/bridge/dw_hdmi_qp.h
index 76ecf31301997718604a05f70ce9eab8695e26b5..3f461f6b9bbfbf67934bf642452d3c6f9253c4f9 100644
--- a/include/drm/bridge/dw_hdmi_qp.h
+++ b/include/drm/bridge/dw_hdmi_qp.h
@@ -25,6 +25,10 @@ struct dw_hdmi_qp_plat_data {
int main_irq;
int cec_irq;
unsigned long ref_clk_rate;
+ /* Supported output formats: bitmask of @hdmi_colorspace */
+ unsigned int supported_formats;
+ /* Maximum bits per color channel: 8, 10 or 12 */
+ unsigned int max_bpc;
};
struct dw_hdmi_qp *dw_hdmi_qp_bind(struct platform_device *pdev,
--
2.50.1
^ permalink raw reply related [flat|nested] 8+ messages in thread
* [PATCH v2 3/5] drm/rockchip: dw_hdmi_qp: Switch to phy_configure()
2025-08-25 10:08 [PATCH v2 0/5] High color depth support for RK3576/RK3588 HDMI output Cristian Ciocaltea
2025-08-25 10:08 ` [PATCH v2 1/5] drm/rockchip: vop2: Check bpc before switching DCLK source Cristian Ciocaltea
2025-08-25 10:08 ` [PATCH v2 2/5] drm/bridge: dw-hdmi-qp: Handle platform supported formats and color depth Cristian Ciocaltea
@ 2025-08-25 10:08 ` Cristian Ciocaltea
2025-08-25 10:08 ` [PATCH v2 4/5] drm/rockchip: dw_hdmi_qp: Use bit macros for RK3576 regs Cristian Ciocaltea
` (2 subsequent siblings)
5 siblings, 0 replies; 8+ messages in thread
From: Cristian Ciocaltea @ 2025-08-25 10:08 UTC (permalink / raw)
To: Sandy Huang, Heiko Stübner, Andy Yan, Maarten Lankhorst,
Maxime Ripard, Thomas Zimmermann, David Airlie, Simona Vetter,
Andrzej Hajda, Neil Armstrong, Robert Foss, Laurent Pinchart,
Jonas Karlman, Jernej Skrabec
Cc: kernel, dri-devel, linux-arm-kernel, linux-rockchip, linux-kernel
Stop relying on phy_set_bus_width() based workaround to setup the TMDS
character rate and, instead, use the recently introduced HDMI PHY
configuration API. This is also a prerequisite to enable high color
depth and FRL support.
Additionally, move the logic to ->atomic_check() callback where the
current mode rate is already provided by the connector state. As a
matter of fact this is actually necessary to ensure the link rate is
configured before VOP2 attempts to use the PHY PLL as a DCLK source in
vop2_crtc_atomic_enable(). The rationale is to restrict any changes of
the PHY rate via CCF and, instead, prefer the PHY configuration API for
this purpose.
Signed-off-by: Cristian Ciocaltea <cristian.ciocaltea@collabora.com>
---
drivers/gpu/drm/rockchip/dw_hdmi_qp-rockchip.c | 37 +++++++++++++-------------
1 file changed, 19 insertions(+), 18 deletions(-)
diff --git a/drivers/gpu/drm/rockchip/dw_hdmi_qp-rockchip.c b/drivers/gpu/drm/rockchip/dw_hdmi_qp-rockchip.c
index 5280383febe25cf579c306ec1642557600595e58..6f2006e7999b540f29841ec4ef679a3ab1e8f497 100644
--- a/drivers/gpu/drm/rockchip/dw_hdmi_qp-rockchip.c
+++ b/drivers/gpu/drm/rockchip/dw_hdmi_qp-rockchip.c
@@ -13,6 +13,7 @@
#include <linux/module.h>
#include <linux/platform_device.h>
#include <linux/phy/phy.h>
+#include <linux/phy/phy-hdmi.h>
#include <linux/regmap.h>
#include <linux/workqueue.h>
@@ -95,6 +96,7 @@ struct rockchip_hdmi_qp {
struct delayed_work hpd_work;
int port_id;
const struct rockchip_hdmi_qp_ctrl_ops *ctrl_ops;
+ unsigned long long tmds_char_rate;
};
struct rockchip_hdmi_qp_ctrl_ops {
@@ -113,24 +115,9 @@ static struct rockchip_hdmi_qp *to_rockchip_hdmi_qp(struct drm_encoder *encoder)
static void dw_hdmi_qp_rockchip_encoder_enable(struct drm_encoder *encoder)
{
struct rockchip_hdmi_qp *hdmi = to_rockchip_hdmi_qp(encoder);
- struct drm_crtc *crtc = encoder->crtc;
- unsigned long long rate;
/* Unconditionally switch to TMDS as FRL is not yet supported */
gpiod_set_value(hdmi->enable_gpio, 1);
-
- if (crtc && crtc->state) {
- rate = drm_hdmi_compute_mode_clock(&crtc->state->adjusted_mode,
- 8, HDMI_COLORSPACE_RGB);
- /*
- * FIXME: Temporary workaround to pass pixel clock rate
- * to the PHY driver until phy_configure_opts_hdmi
- * becomes available in the PHY API. See also the related
- * comment in rk_hdptx_phy_power_on() from
- * drivers/phy/rockchip/phy-rockchip-samsung-hdptx.c
- */
- phy_set_bus_width(hdmi->phy, div_u64(rate, 100));
- }
}
static int
@@ -138,12 +125,26 @@ dw_hdmi_qp_rockchip_encoder_atomic_check(struct drm_encoder *encoder,
struct drm_crtc_state *crtc_state,
struct drm_connector_state *conn_state)
{
+ struct rockchip_hdmi_qp *hdmi = to_rockchip_hdmi_qp(encoder);
struct rockchip_crtc_state *s = to_rockchip_crtc_state(crtc_state);
+ union phy_configure_opts phy_cfg = {};
+ int ret;
- s->output_mode = ROCKCHIP_OUT_MODE_AAAA;
- s->output_type = DRM_MODE_CONNECTOR_HDMIA;
+ if (hdmi->tmds_char_rate == conn_state->hdmi.tmds_char_rate)
+ return 0;
- return 0;
+ phy_cfg.hdmi.tmds_char_rate = conn_state->hdmi.tmds_char_rate;
+
+ ret = phy_configure(hdmi->phy, &phy_cfg);
+ if (!ret) {
+ hdmi->tmds_char_rate = conn_state->hdmi.tmds_char_rate;
+ s->output_mode = ROCKCHIP_OUT_MODE_AAAA;
+ s->output_type = DRM_MODE_CONNECTOR_HDMIA;
+ } else {
+ dev_err(hdmi->dev, "Failed to configure phy: %d\n", ret);
+ }
+
+ return ret;
}
static const struct
--
2.50.1
^ permalink raw reply related [flat|nested] 8+ messages in thread
* [PATCH v2 4/5] drm/rockchip: dw_hdmi_qp: Use bit macros for RK3576 regs
2025-08-25 10:08 [PATCH v2 0/5] High color depth support for RK3576/RK3588 HDMI output Cristian Ciocaltea
` (2 preceding siblings ...)
2025-08-25 10:08 ` [PATCH v2 3/5] drm/rockchip: dw_hdmi_qp: Switch to phy_configure() Cristian Ciocaltea
@ 2025-08-25 10:08 ` Cristian Ciocaltea
2025-08-25 10:08 ` [PATCH v2 5/5] drm/rockchip: dw_hdmi_qp: Add high color depth support Cristian Ciocaltea
2025-08-29 15:40 ` [PATCH v2 0/5] High color depth support for RK3576/RK3588 HDMI output Daniel Stone
5 siblings, 0 replies; 8+ messages in thread
From: Cristian Ciocaltea @ 2025-08-25 10:08 UTC (permalink / raw)
To: Sandy Huang, Heiko Stübner, Andy Yan, Maarten Lankhorst,
Maxime Ripard, Thomas Zimmermann, David Airlie, Simona Vetter,
Andrzej Hajda, Neil Armstrong, Robert Foss, Laurent Pinchart,
Jonas Karlman, Jernej Skrabec
Cc: kernel, dri-devel, linux-arm-kernel, linux-rockchip, linux-kernel
For consistency and improved readability, redefine a few RK3576 specific
register configurations by relying on GENMASK() and unshifted values for
color depth and output format. Those are not used at the moment, but
will be needed soon to support the related features.
While at it, drop a few other defines which are unlikely to be ever
required.
Signed-off-by: Cristian Ciocaltea <cristian.ciocaltea@collabora.com>
---
drivers/gpu/drm/rockchip/dw_hdmi_qp-rockchip.c | 21 ++++++++-------------
1 file changed, 8 insertions(+), 13 deletions(-)
diff --git a/drivers/gpu/drm/rockchip/dw_hdmi_qp-rockchip.c b/drivers/gpu/drm/rockchip/dw_hdmi_qp-rockchip.c
index 6f2006e7999b540f29841ec4ef679a3ab1e8f497..0f2b421134af9f935758266af45c5779407b4144 100644
--- a/drivers/gpu/drm/rockchip/dw_hdmi_qp-rockchip.c
+++ b/drivers/gpu/drm/rockchip/dw_hdmi_qp-rockchip.c
@@ -38,21 +38,16 @@
#define RK3576_HDMI_HDCP14_MEM_EN BIT(15)
#define RK3576_VO0_GRF_SOC_CON8 0x0020
-#define RK3576_COLOR_FORMAT_MASK (0xf << 4)
-#define RK3576_COLOR_DEPTH_MASK (0xf << 8)
-#define RK3576_RGB (0 << 4)
-#define RK3576_YUV422 (0x1 << 4)
-#define RK3576_YUV444 (0x2 << 4)
-#define RK3576_YUV420 (0x3 << 4)
-#define RK3576_8BPC (0x0 << 8)
-#define RK3576_10BPC (0x6 << 8)
+#define RK3576_COLOR_DEPTH_MASK GENMASK(11, 8)
+#define RK3576_8BPC 0x0
+#define RK3576_10BPC 0x6
+#define RK3576_COLOR_FORMAT_MASK GENMASK(7, 4)
+#define RK3576_RGB 0x9
+#define RK3576_YUV422 0x1
+#define RK3576_YUV444 0x2
+#define RK3576_YUV420 0x3
#define RK3576_CECIN_MASK BIT(3)
-#define RK3576_VO0_GRF_SOC_CON12 0x0030
-#define RK3576_GRF_OSDA_DLYN (0xf << 12)
-#define RK3576_GRF_OSDA_DIV (0x7f << 1)
-#define RK3576_GRF_OSDA_DLY_EN BIT(0)
-
#define RK3576_VO0_GRF_SOC_CON14 0x0038
#define RK3576_I2S_SEL_MASK BIT(0)
#define RK3576_SPDIF_SEL_MASK BIT(1)
--
2.50.1
^ permalink raw reply related [flat|nested] 8+ messages in thread
* [PATCH v2 5/5] drm/rockchip: dw_hdmi_qp: Add high color depth support
2025-08-25 10:08 [PATCH v2 0/5] High color depth support for RK3576/RK3588 HDMI output Cristian Ciocaltea
` (3 preceding siblings ...)
2025-08-25 10:08 ` [PATCH v2 4/5] drm/rockchip: dw_hdmi_qp: Use bit macros for RK3576 regs Cristian Ciocaltea
@ 2025-08-25 10:08 ` Cristian Ciocaltea
2025-08-29 15:40 ` [PATCH v2 0/5] High color depth support for RK3576/RK3588 HDMI output Daniel Stone
5 siblings, 0 replies; 8+ messages in thread
From: Cristian Ciocaltea @ 2025-08-25 10:08 UTC (permalink / raw)
To: Sandy Huang, Heiko Stübner, Andy Yan, Maarten Lankhorst,
Maxime Ripard, Thomas Zimmermann, David Airlie, Simona Vetter,
Andrzej Hajda, Neil Armstrong, Robert Foss, Laurent Pinchart,
Jonas Karlman, Jernej Skrabec
Cc: kernel, dri-devel, linux-arm-kernel, linux-rockchip, linux-kernel
Since both RK3576 and RK3588 SoCs are capable of handling 10 bpc color
depth, introduce a pair of new helpers to program the necessary
registers, as well as passing bpc at PHY configuration level.
Note max_bpc is unconditionally set to 10 before initializing the QP
bridge library, as there is no need to adjust it dynamically, i.e. per
SoC variant, for now.
While setting up .enc_init() callbacks of rockchip_hdmi_qp_ctrl_ops,
also replace the unnecessary whitespace chars before .irq_callback()
assignments.
Signed-off-by: Cristian Ciocaltea <cristian.ciocaltea@collabora.com>
---
drivers/gpu/drm/rockchip/dw_hdmi_qp-rockchip.c | 59 ++++++++++++++++++++++++--
1 file changed, 56 insertions(+), 3 deletions(-)
diff --git a/drivers/gpu/drm/rockchip/dw_hdmi_qp-rockchip.c b/drivers/gpu/drm/rockchip/dw_hdmi_qp-rockchip.c
index 0f2b421134af9f935758266af45c5779407b4144..81f106ac7b561110b4be39d58e99a225af7786f2 100644
--- a/drivers/gpu/drm/rockchip/dw_hdmi_qp-rockchip.c
+++ b/drivers/gpu/drm/rockchip/dw_hdmi_qp-rockchip.c
@@ -7,6 +7,7 @@
* Author: Cristian Ciocaltea <cristian.ciocaltea@collabora.com>
*/
+#include <linux/bitfield.h>
#include <linux/clk.h>
#include <linux/gpio/consumer.h>
#include <linux/mfd/syscon.h>
@@ -68,6 +69,12 @@
#define RK3588_HDMI1_LEVEL_INT BIT(24)
#define RK3588_GRF_VO1_CON3 0x000c
#define RK3588_GRF_VO1_CON6 0x0018
+#define RK3588_COLOR_DEPTH_MASK GENMASK(7, 4)
+#define RK3588_8BPC 0x0
+#define RK3588_10BPC 0x6
+#define RK3588_COLOR_FORMAT_MASK GENMASK(3, 0)
+#define RK3588_RGB 0x0
+#define RK3588_YUV420 0x3
#define RK3588_SCLIN_MASK BIT(9)
#define RK3588_SDAIN_MASK BIT(10)
#define RK3588_MODE_MASK BIT(11)
@@ -96,6 +103,7 @@ struct rockchip_hdmi_qp {
struct rockchip_hdmi_qp_ctrl_ops {
void (*io_init)(struct rockchip_hdmi_qp *hdmi);
+ void (*enc_init)(struct rockchip_hdmi_qp *hdmi, struct rockchip_crtc_state *state);
irqreturn_t (*irq_callback)(int irq, void *dev_id);
irqreturn_t (*hardirq_callback)(int irq, void *dev_id);
};
@@ -110,9 +118,16 @@ static struct rockchip_hdmi_qp *to_rockchip_hdmi_qp(struct drm_encoder *encoder)
static void dw_hdmi_qp_rockchip_encoder_enable(struct drm_encoder *encoder)
{
struct rockchip_hdmi_qp *hdmi = to_rockchip_hdmi_qp(encoder);
+ struct drm_crtc *crtc = encoder->crtc;
/* Unconditionally switch to TMDS as FRL is not yet supported */
gpiod_set_value(hdmi->enable_gpio, 1);
+
+ if (!crtc || !crtc->state)
+ return;
+
+ if (hdmi->ctrl_ops->enc_init)
+ hdmi->ctrl_ops->enc_init(hdmi, to_rockchip_crtc_state(crtc->state));
}
static int
@@ -125,16 +140,19 @@ dw_hdmi_qp_rockchip_encoder_atomic_check(struct drm_encoder *encoder,
union phy_configure_opts phy_cfg = {};
int ret;
- if (hdmi->tmds_char_rate == conn_state->hdmi.tmds_char_rate)
+ if (hdmi->tmds_char_rate == conn_state->hdmi.tmds_char_rate &&
+ s->output_bpc == conn_state->hdmi.output_bpc)
return 0;
phy_cfg.hdmi.tmds_char_rate = conn_state->hdmi.tmds_char_rate;
+ phy_cfg.hdmi.bpc = conn_state->hdmi.output_bpc;
ret = phy_configure(hdmi->phy, &phy_cfg);
if (!ret) {
hdmi->tmds_char_rate = conn_state->hdmi.tmds_char_rate;
s->output_mode = ROCKCHIP_OUT_MODE_AAAA;
s->output_type = DRM_MODE_CONNECTOR_HDMIA;
+ s->output_bpc = conn_state->hdmi.output_bpc;
} else {
dev_err(hdmi->dev, "Failed to configure phy: %d\n", ret);
}
@@ -373,15 +391,49 @@ static void dw_hdmi_qp_rk3588_io_init(struct rockchip_hdmi_qp *hdmi)
regmap_write(hdmi->regmap, RK3588_GRF_SOC_CON2, val);
}
+static void dw_hdmi_qp_rk3576_enc_init(struct rockchip_hdmi_qp *hdmi,
+ struct rockchip_crtc_state *state)
+{
+ u32 val;
+
+ if (state->output_bpc == 10)
+ val = HIWORD_UPDATE(FIELD_PREP(RK3576_COLOR_DEPTH_MASK, RK3576_10BPC),
+ RK3576_COLOR_DEPTH_MASK);
+ else
+ val = HIWORD_UPDATE(FIELD_PREP(RK3576_COLOR_DEPTH_MASK, RK3576_8BPC),
+ RK3576_COLOR_DEPTH_MASK);
+
+ regmap_write(hdmi->vo_regmap, RK3576_VO0_GRF_SOC_CON8, val);
+}
+
+static void dw_hdmi_qp_rk3588_enc_init(struct rockchip_hdmi_qp *hdmi,
+ struct rockchip_crtc_state *state)
+{
+ u32 val;
+
+ if (state->output_bpc == 10)
+ val = HIWORD_UPDATE(FIELD_PREP(RK3588_COLOR_DEPTH_MASK, RK3588_10BPC),
+ RK3588_COLOR_DEPTH_MASK);
+ else
+ val = HIWORD_UPDATE(FIELD_PREP(RK3588_COLOR_DEPTH_MASK, RK3588_8BPC),
+ RK3588_COLOR_DEPTH_MASK);
+
+ regmap_write(hdmi->vo_regmap,
+ hdmi->port_id ? RK3588_GRF_VO1_CON6 : RK3588_GRF_VO1_CON3,
+ val);
+}
+
static const struct rockchip_hdmi_qp_ctrl_ops rk3576_hdmi_ctrl_ops = {
.io_init = dw_hdmi_qp_rk3576_io_init,
- .irq_callback = dw_hdmi_qp_rk3576_irq,
+ .enc_init = dw_hdmi_qp_rk3576_enc_init,
+ .irq_callback = dw_hdmi_qp_rk3576_irq,
.hardirq_callback = dw_hdmi_qp_rk3576_hardirq,
};
static const struct rockchip_hdmi_qp_ctrl_ops rk3588_hdmi_ctrl_ops = {
.io_init = dw_hdmi_qp_rk3588_io_init,
- .irq_callback = dw_hdmi_qp_rk3588_irq,
+ .enc_init = dw_hdmi_qp_rk3588_enc_init,
+ .irq_callback = dw_hdmi_qp_rk3588_irq,
.hardirq_callback = dw_hdmi_qp_rk3588_hardirq,
};
@@ -474,6 +526,7 @@ static int dw_hdmi_qp_rockchip_bind(struct device *dev, struct device *master,
plat_data.phy_ops = cfg->phy_ops;
plat_data.phy_data = hdmi;
+ plat_data.max_bpc = 10;
encoder = &hdmi->encoder.encoder;
encoder->possible_crtcs = drm_of_find_possible_crtcs(drm, dev->of_node);
--
2.50.1
^ permalink raw reply related [flat|nested] 8+ messages in thread
* Re: [PATCH v2 1/5] drm/rockchip: vop2: Check bpc before switching DCLK source
2025-08-25 10:08 ` [PATCH v2 1/5] drm/rockchip: vop2: Check bpc before switching DCLK source Cristian Ciocaltea
@ 2025-08-29 15:35 ` Daniel Stone
0 siblings, 0 replies; 8+ messages in thread
From: Daniel Stone @ 2025-08-29 15:35 UTC (permalink / raw)
To: Cristian Ciocaltea
Cc: Sandy Huang, Heiko Stübner, Andy Yan, Maarten Lankhorst,
Maxime Ripard, Thomas Zimmermann, David Airlie, Simona Vetter,
Andrzej Hajda, Neil Armstrong, Robert Foss, Laurent Pinchart,
Jonas Karlman, Jernej Skrabec, kernel, dri-devel,
linux-arm-kernel, linux-rockchip, linux-kernel
Hi Cristian,
On Mon, 25 Aug 2025 at 12:08, Cristian Ciocaltea
<cristian.ciocaltea@collabora.com> wrote:
> When making use of the HDMI PHY PLL as a VOP2 DCLK source, it's output
> rate does normally match the mode clock. But this is only applicable
> for default color depth of 8 bpc. For higher depths, the output clock
> is further divided by the hardware according to the formula:
>
> output rate = PHY PLL rate * 8 / bpc
Observing that this results in phy_pll_rate * 8 / 8 == phy_pll_rate
for 8bpc, the formula does actually hold true everywhere.
> @@ -1737,36 +1737,48 @@ static void vop2_crtc_atomic_enable(struct drm_crtc *crtc,
> * Switch to HDMI PHY PLL as DCLK source for display modes up
> * to 4K@60Hz, if available, otherwise keep using the system CRU.
> */
> - if ((vop2->pll_hdmiphy0 || vop2->pll_hdmiphy1) && clock <= VOP2_MAX_DCLK_RATE) {
> - drm_for_each_encoder_mask(encoder, crtc->dev, crtc_state->encoder_mask) {
> - struct rockchip_encoder *rkencoder = to_rockchip_encoder(encoder);
> + if (vop2->pll_hdmiphy0 || vop2->pll_hdmiphy1) {
> + unsigned long max_dclk;
>
> - if (rkencoder->crtc_endpoint_id == ROCKCHIP_VOP2_EP_HDMI0) {
> - if (!vop2->pll_hdmiphy0)
> - break;
> + if (vcstate->output_bpc > 8)
> + max_dclk = DIV_ROUND_CLOSEST_ULL(VOP2_MAX_DCLK_RATE * 8,
> + vcstate->output_bpc);
> + else
> + max_dclk = VOP2_MAX_DCLK_RATE;
... so this could just be do the mul+div unconditionally.
> + if (clock <= max_dclk) {
> + drm_for_each_encoder_mask(encoder, crtc->dev, crtc_state->encoder_mask) {
> + struct rockchip_encoder *rkencoder = to_rockchip_encoder(encoder);
>
> - ret = clk_set_parent(vp->dclk, vop2->pll_hdmiphy0);
> - if (ret < 0)
> - drm_warn(vop2->drm,
> - "Could not switch to HDMI0 PHY PLL: %d\n", ret);
> - break;
> - }
> + if (rkencoder->crtc_endpoint_id == ROCKCHIP_VOP2_EP_HDMI0) {
> + if (!vop2->pll_hdmiphy0)
> + break;
> +
> + if (!vp->dclk_src)
> + vp->dclk_src = clk_get_parent(vp->dclk);
>
> - if (rkencoder->crtc_endpoint_id == ROCKCHIP_VOP2_EP_HDMI1) {
> - if (!vop2->pll_hdmiphy1)
> + ret = clk_set_parent(vp->dclk, vop2->pll_hdmiphy0);
> + if (ret < 0)
> + drm_warn(vop2->drm,
> + "Could not switch to HDMI0 PHY PLL: %d\n",
> + ret);
> break;
> + }
>
> - if (!vp->dclk_src)
> - vp->dclk_src = clk_get_parent(vp->dclk);
> + if (rkencoder->crtc_endpoint_id == ROCKCHIP_VOP2_EP_HDMI1) {
> + if (!vop2->pll_hdmiphy1)
> + break;
>
> - ret = clk_set_parent(vp->dclk, vop2->pll_hdmiphy1);
> - if (ret < 0)
> - drm_warn(vop2->drm,
> - "Could not switch to HDMI1 PHY PLL: %d\n", ret);
> - break;
> + if (!vp->dclk_src)
> + vp->dclk_src = clk_get_parent(vp->dclk);
> +
> + ret = clk_set_parent(vp->dclk, vop2->pll_hdmiphy1);
> + if (ret < 0)
> + drm_warn(vop2->drm,
> + "Could not switch to HDMI1 PHY PLL: %d\n",
> + ret);
> + break;
> + }
To be honest, this whole thing is a bit weird, and seems like it could
also be struct clk *new_dclk_parent = (rkencoder->crtc_endpoint_id ==
ROCKCHIP_VOP2_EP_HDMI0) ? vop2->pll_hdmiphy0 : vop2->pll_hdmiphy1? But
it's not your code, I know, and the rest of the clock handling is
pretty messy, so I think this is fine as is.
Reviewed-by: Daniel Stone <daniels@collabora.com>
Cheers,
Daniel
^ permalink raw reply [flat|nested] 8+ messages in thread
* Re: [PATCH v2 0/5] High color depth support for RK3576/RK3588 HDMI output
2025-08-25 10:08 [PATCH v2 0/5] High color depth support for RK3576/RK3588 HDMI output Cristian Ciocaltea
` (4 preceding siblings ...)
2025-08-25 10:08 ` [PATCH v2 5/5] drm/rockchip: dw_hdmi_qp: Add high color depth support Cristian Ciocaltea
@ 2025-08-29 15:40 ` Daniel Stone
5 siblings, 0 replies; 8+ messages in thread
From: Daniel Stone @ 2025-08-29 15:40 UTC (permalink / raw)
To: Cristian Ciocaltea
Cc: Sandy Huang, Heiko Stübner, Andy Yan, Maarten Lankhorst,
Maxime Ripard, Thomas Zimmermann, David Airlie, Simona Vetter,
Andrzej Hajda, Neil Armstrong, Robert Foss, Laurent Pinchart,
Jonas Karlman, Jernej Skrabec, kernel, dri-devel,
linux-arm-kernel, linux-rockchip, linux-kernel
Hi Cristian,
On Mon, 25 Aug 2025 at 12:08, Cristian Ciocaltea
<cristian.ciocaltea@collabora.com> wrote:
> Since both Rockchip RK3576 and RK3588 SoCs are capable of handling 10
> bpc color depth HDMI output and we've already landed the required HDPTX
> PHY driver changes to support the setup, let's add the missing bits and
> pieces to VOP2, DW HDMI QP encoder and bridge library.
>
> Please note this conflicts with the HDMI CEC series [1], hence I added
> that as a b4-managed dependency.
Thanks, no comments on this one, but having not read the PHY changes
at all, the series is:
Acked-by: Daniel Stone <daniels@collabora.com>
Cheers,
Daniel
^ permalink raw reply [flat|nested] 8+ messages in thread
end of thread, other threads:[~2025-08-29 19:36 UTC | newest]
Thread overview: 8+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2025-08-25 10:08 [PATCH v2 0/5] High color depth support for RK3576/RK3588 HDMI output Cristian Ciocaltea
2025-08-25 10:08 ` [PATCH v2 1/5] drm/rockchip: vop2: Check bpc before switching DCLK source Cristian Ciocaltea
2025-08-29 15:35 ` Daniel Stone
2025-08-25 10:08 ` [PATCH v2 2/5] drm/bridge: dw-hdmi-qp: Handle platform supported formats and color depth Cristian Ciocaltea
2025-08-25 10:08 ` [PATCH v2 3/5] drm/rockchip: dw_hdmi_qp: Switch to phy_configure() Cristian Ciocaltea
2025-08-25 10:08 ` [PATCH v2 4/5] drm/rockchip: dw_hdmi_qp: Use bit macros for RK3576 regs Cristian Ciocaltea
2025-08-25 10:08 ` [PATCH v2 5/5] drm/rockchip: dw_hdmi_qp: Add high color depth support Cristian Ciocaltea
2025-08-29 15:40 ` [PATCH v2 0/5] High color depth support for RK3576/RK3588 HDMI output Daniel Stone
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).