]> Gentwo Git Trees - linux/.git/commitdiff
drm/rockchip: vop2: Check bpc before switching DCLK source
authorCristian Ciocaltea <cristian.ciocaltea@collabora.com>
Tue, 21 Oct 2025 10:19:14 +0000 (13:19 +0300)
committerHeiko Stuebner <heiko@sntech.de>
Fri, 14 Nov 2025 22:10:33 +0000 (23:10 +0100)
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.

Reviewed-by: Daniel Stone <daniels@collabora.com>
Signed-off-by: Cristian Ciocaltea <cristian.ciocaltea@collabora.com>
Signed-off-by: Heiko Stuebner <heiko@sntech.de>
Link: https://lore.kernel.org/r/20251021-rk3588-10bpc-v3-1-3d3eed00a6db@collabora.com
drivers/gpu/drm/rockchip/rockchip_drm_vop2.c

index e979d5e02ff491d56640b0a300ff5c092cce240b..498df0ce4680cbdddeb71c4fa499b2a9ed2d63d8 100644 (file)
@@ -102,7 +102,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.
@@ -1743,36 +1743,42 @@ 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 (rkencoder->crtc_endpoint_id == ROCKCHIP_VOP2_EP_HDMI0) {
-                               if (!vop2->pll_hdmiphy0)
+       if (vop2->pll_hdmiphy0 || vop2->pll_hdmiphy1) {
+               unsigned long max_dclk = DIV_ROUND_CLOSEST_ULL(VOP2_MAX_DCLK_RATE * 8,
+                                                              vcstate->output_bpc);
+               if (clock <= max_dclk) {
+                       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);
+
+                                       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_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)
+                                       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;
+                               }
                        }
                }
        }