summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorCristian Ciocaltea <cristian.ciocaltea@collabora.com>2025-02-23 11:31:37 +0200
committerHeiko Stuebner <heiko@sntech.de>2025-02-27 11:51:21 +0100
commitf8dd7fc9ba88bc4a6ea85269287a51fb756440e2 (patch)
tree2c5d4563ce810fdfb08c20b688bc164366190b81
parent718b3bb9c0ab87bc90914799e6999bf4b1ecc67b (diff)
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
-rw-r--r--drivers/gpu/drm/rockchip/rockchip_drm_vop2.c25
1 files changed, 24 insertions, 1 deletions
diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_vop2.c b/drivers/gpu/drm/rockchip/rockchip_drm_vop2.c
index afc946ead870..14e039e9143a 100644
--- a/drivers/gpu/drm/rockchip/rockchip_drm_vop2.c
+++ b/drivers/gpu/drm/rockchip/rockchip_drm_vop2.c
@@ -216,6 +216,7 @@ struct vop2 {
struct clk *aclk;
struct clk *pclk;
struct clk *pll_hdmiphy0;
+ struct clk *pll_hdmiphy1;
/* optional internal rgb encoder */
struct rockchip_rgb *rgb;
@@ -2270,11 +2271,14 @@ 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 && clock <= VOP2_MAX_DCLK_RATE) {
+ 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 (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);
@@ -2284,6 +2288,20 @@ static void vop2_crtc_atomic_enable(struct drm_crtc *crtc,
"Could not switch to HDMI0 PHY PLL: %d\n", ret);
break;
}
+
+ if (rkencoder->crtc_endpoint_id == ROCKCHIP_VOP2_EP_HDMI1) {
+ if (!vop2->pll_hdmiphy1)
+ 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;
+ }
}
}
@@ -3733,6 +3751,11 @@ static int vop2_bind(struct device *dev, struct device *master, void *data)
return PTR_ERR(vop2->pll_hdmiphy0);
}
+ vop2->pll_hdmiphy1 = devm_clk_get_optional(vop2->dev, "pll_hdmiphy1");
+ if (IS_ERR(vop2->pll_hdmiphy1))
+ return dev_err_probe(drm->dev, PTR_ERR(vop2->pll_hdmiphy1),
+ "failed to get pll_hdmiphy1\n");
+
vop2->irq = platform_get_irq(pdev, 0);
if (vop2->irq < 0) {
drm_err(vop2->drm, "cannot find irq for vop2\n");