drm/vc4: encoder: Add finer-grained encoder callbacks 81/243881/1
authorMaxime Ripard <maxime@cerno.tech>
Mon, 24 Aug 2020 10:56:15 +0000 (19:56 +0900)
committerHoegeun Kwon <hoegeun.kwon@samsung.com>
Fri, 11 Sep 2020 01:44:50 +0000 (10:44 +0900)
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
[hoegeun.kwon: For use encoder callback, needed to troubleshoot page
flip timed out issue.]
Signed-off-by: Hoegeun Kwon <hoegeun.kwon@samsung.com>
Change-Id: I16a1a59ad753d7c4e211c24a3563a607faa03a5c

drivers/gpu/drm/vc4/vc4_crtc.c
drivers/gpu/drm/vc4/vc4_drv.h

index 7925b7d..129cf90 100644 (file)
@@ -495,6 +495,8 @@ static void vc4_crtc_atomic_disable(struct drm_crtc *crtc,
        struct vc4_crtc *vc4_crtc = to_vc4_crtc(crtc);
        struct vc4_crtc_state *vc4_crtc_state = to_vc4_crtc_state(old_state);
        u32 chan = vc4_crtc_state->assigned_channel;
+       struct drm_encoder *encoder = vc4_get_crtc_encoder(crtc);
+       struct vc4_encoder *vc4_encoder = to_vc4_encoder(encoder);
        int ret;
        require_hvs_enabled(dev);
 
@@ -506,6 +508,9 @@ 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);
 
        if (HVS_READ(SCALER_DISPCTRLX(chan)) &
@@ -531,6 +536,9 @@ static void vc4_crtc_atomic_disable(struct drm_crtc *crtc,
                      (SCALER_DISPSTATX_FULL | SCALER_DISPSTATX_EMPTY)) !=
                     SCALER_DISPSTATX_EMPTY);
 
+       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.
@@ -592,6 +600,8 @@ static void vc4_crtc_atomic_enable(struct drm_crtc *crtc,
        struct vc4_crtc_state *vc4_state = to_vc4_crtc_state(crtc->state);
        struct drm_display_mode *mode = &crtc->state->adjusted_mode;
        u32 dispctrl;
+       struct drm_encoder *encoder = vc4_get_crtc_encoder(crtc);
+       struct vc4_encoder *vc4_encoder = to_vc4_encoder(encoder);
 
        require_hvs_enabled(dev);
 
@@ -627,14 +637,23 @@ static void vc4_crtc_atomic_enable(struct drm_crtc *crtc,
                            (vc4_state->feed_txp ?
                                        SCALER5_DISPCTRLX_ONESHOT : 0);
 
+       if (vc4_encoder->pre_crtc_configure)
+               vc4_encoder->pre_crtc_configure(encoder);
+
        HVS_WRITE(SCALER_DISPCTRLX(vc4_state->assigned_channel), dispctrl);
 
+       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.
         */
        if (!vc4_state->feed_txp)
                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 afdf477..9273595 100644 (file)
@@ -440,6 +440,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 *