Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

drm/rockchip: vop2: Improve display modes handling on RK3588 HDMI1

The RK3588 specific implementation is currently quite limited in terms
of handling the full range of display modes supported by the connected
screens, e.g. 2560x1440@75Hz, 2048x1152@60Hz, 1024x768@60Hz are just a
few of them.

Additionally, it doesn't cope well with non-integer refresh rates like
59.94, 29.97, 23.98, etc.

Make use of HDMI1 PHY PLL as a more accurate DCLK source to handle
all display modes up to 4K@60Hz.

Signed-off-by: Cristian Ciocaltea <cristian.ciocaltea@collabora.com>
Signed-off-by: Heiko Stuebner <heiko@sntech.de>
Link: https://patchwork.freedesktop.org/patch/msgid/20250223-vop2-hdmi1-disp-modes-v2-1-f4cec5e06fbe@collabora.com

authored by

Cristian Ciocaltea and committed by
Heiko Stuebner
f8dd7fc9 718b3bb9

+24 -1
+24 -1
drivers/gpu/drm/rockchip/rockchip_drm_vop2.c
··· 216 216 struct clk *aclk; 217 217 struct clk *pclk; 218 218 struct clk *pll_hdmiphy0; 219 + struct clk *pll_hdmiphy1; 219 220 220 221 /* optional internal rgb encoder */ 221 222 struct rockchip_rgb *rgb; ··· 2271 2270 * Switch to HDMI PHY PLL as DCLK source for display modes up 2272 2271 * to 4K@60Hz, if available, otherwise keep using the system CRU. 2273 2272 */ 2274 - if (vop2->pll_hdmiphy0 && clock <= VOP2_MAX_DCLK_RATE) { 2273 + if ((vop2->pll_hdmiphy0 || vop2->pll_hdmiphy1) && clock <= VOP2_MAX_DCLK_RATE) { 2275 2274 drm_for_each_encoder_mask(encoder, crtc->dev, crtc_state->encoder_mask) { 2276 2275 struct rockchip_encoder *rkencoder = to_rockchip_encoder(encoder); 2277 2276 2278 2277 if (rkencoder->crtc_endpoint_id == ROCKCHIP_VOP2_EP_HDMI0) { 2278 + if (!vop2->pll_hdmiphy0) 2279 + break; 2280 + 2279 2281 if (!vp->dclk_src) 2280 2282 vp->dclk_src = clk_get_parent(vp->dclk); 2281 2283 ··· 2286 2282 if (ret < 0) 2287 2283 drm_warn(vop2->drm, 2288 2284 "Could not switch to HDMI0 PHY PLL: %d\n", ret); 2285 + break; 2286 + } 2287 + 2288 + if (rkencoder->crtc_endpoint_id == ROCKCHIP_VOP2_EP_HDMI1) { 2289 + if (!vop2->pll_hdmiphy1) 2290 + break; 2291 + 2292 + if (!vp->dclk_src) 2293 + vp->dclk_src = clk_get_parent(vp->dclk); 2294 + 2295 + ret = clk_set_parent(vp->dclk, vop2->pll_hdmiphy1); 2296 + if (ret < 0) 2297 + drm_warn(vop2->drm, 2298 + "Could not switch to HDMI1 PHY PLL: %d\n", ret); 2289 2299 break; 2290 2300 } 2291 2301 } ··· 3750 3732 drm_err(vop2->drm, "failed to get pll_hdmiphy0\n"); 3751 3733 return PTR_ERR(vop2->pll_hdmiphy0); 3752 3734 } 3735 + 3736 + vop2->pll_hdmiphy1 = devm_clk_get_optional(vop2->dev, "pll_hdmiphy1"); 3737 + if (IS_ERR(vop2->pll_hdmiphy1)) 3738 + return dev_err_probe(drm->dev, PTR_ERR(vop2->pll_hdmiphy1), 3739 + "failed to get pll_hdmiphy1\n"); 3753 3740 3754 3741 vop2->irq = platform_get_irq(pdev, 0); 3755 3742 if (vop2->irq < 0) {