drm/vc4: hdmi: Add pixel bvb clock control 08/239608/3
authorHoegeun Kwon <hoegeun.kwon@samsung.com>
Mon, 27 Jul 2020 12:37:18 +0000 (21:37 +0900)
committerHoegeun Kwon <hoegeun.kwon@samsung.com>
Tue, 28 Jul 2020 08:01:33 +0000 (17:01 +0900)
There is a problem that the output does not work at a resolution
exceeding FHD. To solve this, we need to adjust the bvb clock at a
resolution exceeding FHD.

Change-Id: I488cbf5c9ec90e6429833edd94f8fe7e5e57bfdf
Signed-off-by: Hoegeun Kwon <hoegeun.kwon@samsung.com>
drivers/gpu/drm/vc4/vc4_hdmi.c
drivers/gpu/drm/vc4/vc4_hdmi.h

index 200f30b..da9fce5 100644 (file)
@@ -81,6 +81,7 @@
 
 #define CEC_CLOCK_FREQ 40000
 #define VC4_HSM_CLOCK 163682864
+#define VC4_HSM_MID_CLOCK 149985000
 
 static int vc4_hdmi_debugfs_regs(struct seq_file *m, void *unused)
 {
@@ -393,6 +394,7 @@ static void vc4_hdmi_encoder_disable(struct drm_encoder *encoder)
        HDMI_WRITE(HDMI_VID_CTL,
                   HDMI_READ(HDMI_VID_CTL) & ~VC4_HD_VID_CTL_ENABLE);
 
+       clk_disable_unprepare(vc4_hdmi->pixel_bvb_clock);
        clk_disable_unprepare(vc4_hdmi->hsm_clock);
        clk_disable_unprepare(vc4_hdmi->pixel_clock);
 
@@ -618,6 +620,23 @@ static void vc4_hdmi_encoder_enable(struct drm_encoder *encoder)
                return;
        }
 
+       ret = clk_set_rate(vc4_hdmi->pixel_bvb_clock,
+                       (hsm_rate > VC4_HSM_MID_CLOCK ? 150000000 : 75000000));
+       if (ret) {
+               DRM_ERROR("Failed to set pixel bvb clock rate: %d\n", ret);
+               clk_disable_unprepare(vc4_hdmi->hsm_clock);
+               clk_disable_unprepare(vc4_hdmi->pixel_clock);
+               return;
+       }
+
+       ret = clk_prepare_enable(vc4_hdmi->pixel_bvb_clock);
+       if (ret) {
+               DRM_ERROR("Failed to turn on pixel bvb clock: %d\n", ret);
+               clk_disable_unprepare(vc4_hdmi->hsm_clock);
+               clk_disable_unprepare(vc4_hdmi->pixel_clock);
+               return;
+       }
+
        if (vc4_hdmi->variant->reset)
                vc4_hdmi->variant->reset(vc4_hdmi);
 
@@ -1651,6 +1670,12 @@ static int vc5_hdmi_init_resources(struct vc4_hdmi *vc4_hdmi)
                return PTR_ERR(vc4_hdmi->reset);
        }
 
+       vc4_hdmi->pixel_bvb_clock = devm_clk_get(dev, "bvb");
+       if (IS_ERR(vc4_hdmi->pixel_bvb_clock)) {
+               DRM_ERROR("Failed to get pixel bvb clock\n");
+               return PTR_ERR(vc4_hdmi->pixel_bvb_clock);
+       }
+
        return 0;
 }
 
index c312558..9970e53 100644 (file)
@@ -160,6 +160,7 @@ struct vc4_hdmi {
 
        struct clk *pixel_clock;
        struct clk *hsm_clock;
+       struct clk *pixel_bvb_clock;
 
        struct reset_control *reset;