From 289c29b96fcc6cbe5c966fb0cc9e1bb8efbdd9dc Mon Sep 17 00:00:00 2001 From: Dave Stevenson Date: Thu, 26 Mar 2020 15:32:19 +0000 Subject: [PATCH] drm/vc4: Kick the core clock up during a mode change Experimental commit to kick the core clock up during mode switching. This makes mode switching far more reliable, and mimics what the firmware does. Signed-off-by: Dave Stevenson --- arch/arm/boot/dts/bcm2711.dtsi | 1 + drivers/gpu/drm/vc4/vc4_drv.h | 2 ++ drivers/gpu/drm/vc4/vc4_hvs.c | 7 +++++++ drivers/gpu/drm/vc4/vc4_kms.c | 6 ++++++ 4 files changed, 16 insertions(+) --- a/arch/arm/boot/dts/bcm2711.dtsi +++ b/arch/arm/boot/dts/bcm2711.dtsi @@ -306,6 +306,7 @@ }; hvs@7e400000 { + clocks = <&firmware_clocks 4>; interrupts = ; }; --- a/drivers/gpu/drm/vc4/vc4_drv.h +++ b/drivers/gpu/drm/vc4/vc4_drv.h @@ -326,6 +326,8 @@ struct vc4_hvs { void __iomem *regs; u32 __iomem *dlist; + struct clk *core_clk; + /* Memory manager for CRTCs to allocate space in the display * list. Units are dwords. */ --- a/drivers/gpu/drm/vc4/vc4_hvs.c +++ b/drivers/gpu/drm/vc4/vc4_hvs.c @@ -19,6 +19,7 @@ * each CRTC. */ +#include #include #include @@ -239,6 +240,12 @@ static int vc4_hvs_bind(struct device *d hvs->regset.regs = hvs_regs; hvs->regset.nregs = ARRAY_SIZE(hvs_regs); + hvs->core_clk = devm_clk_get(&pdev->dev, NULL); + if (IS_ERR(hvs->core_clk)) { + dev_err(&pdev->dev, "Couldn't get core clock\n"); + return PTR_ERR(hvs->regs); + } + hvs_version = readl(hvs->regs + SCALER_DISPLSTAT) >> 24; if (hvs_version >= 0x40) hvs->hvs5 = true; --- a/drivers/gpu/drm/vc4/vc4_kms.c +++ b/drivers/gpu/drm/vc4/vc4_kms.c @@ -13,6 +13,7 @@ #include #include +#include #include #include @@ -222,6 +223,7 @@ vc4_atomic_complete_commit(struct drm_at { struct drm_device *dev = state->dev; struct vc4_dev *vc4 = to_vc4_dev(dev); + struct vc4_hvs *hvs = vc4->hvs; struct vc4_crtc *vc4_crtc; int i; @@ -237,6 +239,8 @@ vc4_atomic_complete_commit(struct drm_at vc4_hvs_mask_underrun(dev, vc4_crtc_state->assigned_channel); } + clk_set_rate(hvs->core_clk, 500000000); + drm_atomic_helper_wait_for_fences(dev, state, false); drm_atomic_helper_wait_for_dependencies(state); @@ -262,6 +266,8 @@ vc4_atomic_complete_commit(struct drm_at drm_atomic_helper_commit_cleanup_done(state); + clk_set_rate(hvs->core_clk, 200000000); + drm_atomic_state_put(state); up(&vc4->async_modeset);