drm/vc4: encoder: Add finer-grained encoder callbacks
authorMaxime Ripard <maxime@cerno.tech>
Thu, 3 Sep 2020 08:01:00 +0000 (10:01 +0200)
committerMaxime Ripard <maxime@cerno.tech>
Mon, 7 Sep 2020 16:04:03 +0000 (18:04 +0200)
In the BCM2711, the setup of the HVS, pixelvalve and HDMI controller
requires very precise ordering and timing that the regular atomic callbacks
don't provide. Let's add new callbacks on top of the regular ones to be
able to split the configuration as needed.

Signed-off-by: Maxime Ripard <maxime@cerno.tech>
Tested-by: Chanwoo Choi <cw00.choi@samsung.com>
Tested-by: Hoegeun Kwon <hoegeun.kwon@samsung.com>
Tested-by: Stefan Wahren <stefan.wahren@i2se.com>
Reviewed-by: Dave Stevenson <dave.stevenson@raspberrypi.com>
Link: https://patchwork.freedesktop.org/patch/msgid/1dd78efe8f29add73c97d0148cfd4ec8e34aaf22.1599120059.git-series.maxime@cerno.tech
drivers/gpu/drm/vc4/vc4_crtc.c
drivers/gpu/drm/vc4/vc4_drv.h

index b7b0e19e2fe125598c983599f479ce29a71ba166..d0b326e1df0af119a469b43bf0c57d51542d1633 100644 (file)
@@ -389,6 +389,8 @@ static void vc4_crtc_atomic_disable(struct drm_crtc *crtc,
 {
        struct drm_device *dev = crtc->dev;
        struct vc4_crtc *vc4_crtc = to_vc4_crtc(crtc);
+       struct drm_encoder *encoder = vc4_get_crtc_encoder(crtc);
+       struct vc4_encoder *vc4_encoder = to_vc4_encoder(encoder);
        int ret;
 
        require_hvs_enabled(dev);
@@ -401,10 +403,16 @@ static void vc4_crtc_atomic_disable(struct drm_crtc *crtc,
        ret = wait_for(!(CRTC_READ(PV_V_CONTROL) & PV_VCONTROL_VIDEN), 1);
        WARN_ONCE(ret, "Timeout waiting for !PV_VCONTROL_VIDEN\n");
 
+       if (vc4_encoder->post_crtc_disable)
+               vc4_encoder->post_crtc_disable(encoder);
+
        CRTC_WRITE(PV_CONTROL, CRTC_READ(PV_CONTROL) & ~PV_CONTROL_EN);
 
        vc4_hvs_atomic_disable(crtc, old_state);
 
+       if (vc4_encoder->post_crtc_powerdown)
+               vc4_encoder->post_crtc_powerdown(encoder);
+
        /*
         * Make sure we issue a vblank event after disabling the CRTC if
         * someone was waiting it.
@@ -424,6 +432,8 @@ static void vc4_crtc_atomic_enable(struct drm_crtc *crtc,
 {
        struct drm_device *dev = crtc->dev;
        struct vc4_crtc *vc4_crtc = to_vc4_crtc(crtc);
+       struct drm_encoder *encoder = vc4_get_crtc_encoder(crtc);
+       struct vc4_encoder *vc4_encoder = to_vc4_encoder(encoder);
 
        require_hvs_enabled(dev);
 
@@ -434,15 +444,24 @@ static void vc4_crtc_atomic_enable(struct drm_crtc *crtc,
 
        vc4_hvs_atomic_enable(crtc, old_state);
 
+       if (vc4_encoder->pre_crtc_configure)
+               vc4_encoder->pre_crtc_configure(encoder);
+
        vc4_crtc_config_pv(crtc);
 
        CRTC_WRITE(PV_CONTROL, CRTC_READ(PV_CONTROL) | PV_CONTROL_EN);
 
+       if (vc4_encoder->pre_crtc_enable)
+               vc4_encoder->pre_crtc_enable(encoder);
+
        /* When feeding the transposer block the pixelvalve is unneeded and
         * should not be enabled.
         */
        CRTC_WRITE(PV_V_CONTROL,
                   CRTC_READ(PV_V_CONTROL) | PV_VCONTROL_VIDEN);
+
+       if (vc4_encoder->post_crtc_enable)
+               vc4_encoder->post_crtc_enable(encoder);
 }
 
 static enum drm_mode_status vc4_crtc_mode_valid(struct drm_crtc *crtc,
index dfcc684f5d283c5460ce77626ab387c016bde89c..251fcc35530c667d3abc1ff957ee6757370d83f8 100644 (file)
@@ -439,6 +439,13 @@ struct vc4_encoder {
        struct drm_encoder base;
        enum vc4_encoder_type type;
        u32 clock_select;
+
+       void (*pre_crtc_configure)(struct drm_encoder *encoder);
+       void (*pre_crtc_enable)(struct drm_encoder *encoder);
+       void (*post_crtc_enable)(struct drm_encoder *encoder);
+
+       void (*post_crtc_disable)(struct drm_encoder *encoder);
+       void (*post_crtc_powerdown)(struct drm_encoder *encoder);
 };
 
 static inline struct vc4_encoder *