[PATCH RFC] drm/rockchip: vop2: Add clock rate mode check
Andy Yan
andyshrk at 163.com
Thu Mar 19 18:48:01 PDT 2026
Hello Sebastian,
At 2026-02-18 00:08:45, "Sebastian Reichel" <sebastian.reichel at collabora.com> wrote:
>The display might offer modes, which exceed the maximum clock rate of a
>video output. This usually happens for displays that offer refresh rates
>above 60 Hz. This results in no picture being displayed without manual
>intervention. Fix this by teaching the driver about the maximum
>achievable clock rates.
>
>Signed-off-by: Sebastian Reichel <sebastian.reichel at collabora.com>
>---
>I've taken the max. clock rate information from the video output
>information of the RK3568/RK3588/RK3576 datasheets. The real max. clock
>rates should be above those to take blank times into account. I haven't
>found the proper information source for this. I hope Andy can help out.
>---
> drivers/gpu/drm/rockchip/rockchip_drm_vop2.c | 3 +++
> drivers/gpu/drm/rockchip/rockchip_drm_vop2.h | 1 +
> drivers/gpu/drm/rockchip/rockchip_vop2_reg.c | 10 ++++++++++
> 3 files changed, 14 insertions(+)
>
>diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_vop2.c b/drivers/gpu/drm/rockchip/rockchip_drm_vop2.c
>index ec3b4fde10db..1051418e5fff 100644
>--- a/drivers/gpu/drm/rockchip/rockchip_drm_vop2.c
>+++ b/drivers/gpu/drm/rockchip/rockchip_drm_vop2.c
>@@ -1434,6 +1434,9 @@ static enum drm_mode_status vop2_crtc_mode_valid(struct drm_crtc *crtc,
> if (mode->hdisplay > vp->data->max_output.width)
> return MODE_BAD_HVALUE;
>
>+ if (mode->clock > vp->data->max_clock_rate / 1000)
>+ return MODE_CLOCK_HIGH;
>+
> return MODE_OK;
> }
>
>diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_vop2.h b/drivers/gpu/drm/rockchip/rockchip_drm_vop2.h
>index 9124191899ba..42d70426bf08 100644
>--- a/drivers/gpu/drm/rockchip/rockchip_drm_vop2.h
>+++ b/drivers/gpu/drm/rockchip/rockchip_drm_vop2.h
>@@ -225,6 +225,7 @@ struct vop2_video_port_data {
> u16 gamma_lut_len;
> u16 cubic_lut_len;
> struct vop_rect max_output;
>+ u32 max_clock_rate;
> const u8 pre_scan_max_dly[4];
> unsigned int offset;
> /**
>diff --git a/drivers/gpu/drm/rockchip/rockchip_vop2_reg.c b/drivers/gpu/drm/rockchip/rockchip_vop2_reg.c
>index f3950e8476a7..8be2cf0c47b6 100644
>--- a/drivers/gpu/drm/rockchip/rockchip_vop2_reg.c
>+++ b/drivers/gpu/drm/rockchip/rockchip_vop2_reg.c
>@@ -559,18 +559,21 @@ static const struct vop2_video_port_data rk3568_vop_video_ports[] = {
> .gamma_lut_len = 1024,
> .cubic_lut_len = 9 * 9 * 9,
> .max_output = { 4096, 2304 },
>+ .max_clock_rate = 4096 * 2304 * 60,
600000000 MHZ
> .pre_scan_max_dly = { 69, 53, 53, 42 },
> .offset = 0xc00,
> }, {
> .id = 1,
> .gamma_lut_len = 1024,
> .max_output = { 2048, 1536 },
>+ .max_clock_rate = 2048 * 1536 * 60,
200000000 Mhz
> .pre_scan_max_dly = { 40, 40, 40, 40 },
> .offset = 0xd00,
> }, {
> .id = 2,
> .gamma_lut_len = 1024,
> .max_output = { 1920, 1080 },
>+ .max_clock_rate = 1920 * 1080 * 60,
150000000 Hz
> .pre_scan_max_dly = { 40, 40, 40, 40 },
> .offset = 0xe00,
> },
>@@ -775,6 +778,7 @@ static const struct vop2_video_port_data rk3576_vop_video_ports[] = {
> .gamma_lut_len = 1024,
> .cubic_lut_len = 9 * 9 * 9, /* 9x9x9 */
> .max_output = { 4096, 2304 },
>+ .max_clock_rate = 4096 * 2304 * 120,
600000000Mhz
> /* win layer_mix hdr */
> .pre_scan_max_dly = { 10, 8, 2, 0 },
> .offset = 0xc00,
>@@ -785,6 +789,7 @@ static const struct vop2_video_port_data rk3576_vop_video_ports[] = {
> .gamma_lut_len = 1024,
> .cubic_lut_len = 729, /* 9x9x9 */
> .max_output = { 2560, 1600 },
>+ .max_clock_rate = 2560 * 1600 * 60,
300000000 Mhz
> /* win layer_mix hdr */
> .pre_scan_max_dly = { 10, 6, 0, 0 },
> .offset = 0xd00,
>@@ -793,6 +798,7 @@ static const struct vop2_video_port_data rk3576_vop_video_ports[] = {
> .id = 2,
> .gamma_lut_len = 1024,
> .max_output = { 1920, 1080 },
>+ .max_clock_rate = 1920 * 1080 * 60,
150000000 Mhz
> /* win layer_mix hdr */
> .pre_scan_max_dly = { 10, 6, 0, 0 },
> .offset = 0xe00,
>@@ -1061,6 +1067,7 @@ static const struct vop2_video_port_data rk3588_vop_video_ports[] = {
> .gamma_lut_len = 1024,
> .cubic_lut_len = 9 * 9 * 9, /* 9x9x9 */
> .max_output = { 4096, 2304 },
>+ .max_clock_rate = 7680 * 4320 * 60,
600 000000 Mhz
For all current platforms, the maximum dclk input supported by VOP is 600 MHz.
The tricky part is that when we need to display a resolution higher than 4K at 60, even though
the required dclk exceeds 600 MHz, VOP internally processes 2 or 4 pixels per clock cycle to
output a higher resolution using a lower dclk. Therefore, even when outputting an 8K at 60 resolution,
CRU only needs to provide VOP with a dclk of 594 MHz. This is what the rk3588_calc_cru_cfg function does.
> /* hdr2sdr sdr2hdr hdr2hdr sdr2sdr */
> .pre_scan_max_dly = { 76, 65, 65, 54 },
> .offset = 0xc00,
>@@ -1070,6 +1077,7 @@ static const struct vop2_video_port_data rk3588_vop_video_ports[] = {
> .gamma_lut_len = 1024,
> .cubic_lut_len = 729, /* 9x9x9 */
> .max_output = { 4096, 2304 },
>+ .max_clock_rate = 4096 * 2304 * 60,
600 000000 Mhz
> .pre_scan_max_dly = { 76, 65, 65, 54 },
> .offset = 0xd00,
> }, {
>@@ -1078,12 +1086,14 @@ static const struct vop2_video_port_data rk3588_vop_video_ports[] = {
> .gamma_lut_len = 1024,
> .cubic_lut_len = 17 * 17 * 17, /* 17x17x17 */
> .max_output = { 4096, 2304 },
>+ .max_clock_rate = 4096 * 2304 * 60,
600 000000 Mhz
> .pre_scan_max_dly = { 52, 52, 52, 52 },
> .offset = 0xe00,
> }, {
> .id = 3,
> .gamma_lut_len = 1024,
> .max_output = { 2048, 1536 },
>+ .max_clock_rate = 1920 * 1080 * 60,
150 000000 Mhz
> .pre_scan_max_dly = { 52, 52, 52, 52 },
> .offset = 0xf00,
> },
>
>---
>base-commit: 9702969978695d9a699a1f34771580cdbb153b33
>change-id: 20260217-vop2-clk-rate-check-268269778cac
>
>Best regards,
>--
>Sebastian Reichel <sebastian.reichel at collabora.com>
More information about the Linux-rockchip
mailing list