drm/vc4: Add support for setting DPMS in firmwarekms.
authorEric Anholt <eric@anholt.net>
Thu, 6 Jul 2017 18:45:48 +0000 (11:45 -0700)
committerpopcornmix <popcornmix@gmail.com>
Wed, 1 Jul 2020 15:32:43 +0000 (16:32 +0100)
This ensures that the screen goes blank during DPMS (screensaver),
including the cursor.  Planes don't necessarily get disabled during
CRTC disable, so we need to be careful to not leave them on or turn
them back on early.

Signed-off-by: Eric Anholt <eric@anholt.net>
drivers/gpu/drm/vc4/vc4_firmware_kms.c

index 4d7b7f2..809437c 100644 (file)
@@ -36,6 +36,8 @@ struct vc4_crtc {
        struct drm_crtc base;
        struct drm_encoder *encoder;
        struct drm_connector *connector;
+       struct drm_plane *primary;
+       struct drm_plane *cursor;
        void __iomem *regs;
 
        struct drm_pending_vblank_event *event;
@@ -123,8 +125,6 @@ static void vc4_primary_plane_atomic_update(struct drm_plane *plane,
        u32 bpp = 32;
        int ret;
 
-       vc4_plane_set_primary_blank(plane, false);
-
        fbinfo->xres = state->crtc_w;
        fbinfo->yres = state->crtc_h;
        fbinfo->xres_virtual = state->crtc_w;
@@ -168,6 +168,12 @@ static void vc4_primary_plane_atomic_update(struct drm_plane *plane,
                                       vc4_plane->fbinfo_bus_addr);
        WARN_ON_ONCE(fbinfo->pitch != fb->pitches[0]);
        WARN_ON_ONCE(fbinfo->base != bo->paddr + fb->offsets[0]);
+
+       /* If the CRTC is on (or going to be on) and we're enabled,
+        * then unblank.  Otherwise, stay blank until CRTC enable.
+       */
+       if (state->crtc->state->active)
+               vc4_plane_set_primary_blank(plane, false);
 }
 
 static void vc4_primary_plane_atomic_disable(struct drm_plane *plane,
@@ -184,7 +190,12 @@ static void vc4_cursor_plane_atomic_update(struct drm_plane *plane,
        struct drm_framebuffer *fb = state->fb;
        struct drm_gem_cma_object *bo = drm_fb_cma_get_gem_obj(fb, 0);
        int ret;
-       u32 packet_state[] = { true, state->crtc_x, state->crtc_y, 0 };
+       u32 packet_state[] = {
+               state->crtc->state->active,
+               state->crtc_x,
+               state->crtc_y,
+               0
+       };
        u32 packet_info[] = { state->crtc_w, state->crtc_h,
                              0, /* unused */
                              bo->paddr + fb->offsets[0],
@@ -321,10 +332,30 @@ static void vc4_crtc_mode_set_nofb(struct drm_crtc *crtc)
 
 static void vc4_crtc_disable(struct drm_crtc *crtc, struct drm_crtc_state *old_state)
 {
+       struct vc4_crtc *vc4_crtc = to_vc4_crtc(crtc);
+
+       /* Always turn the planes off on CRTC disable. In DRM, planes
+        * are enabled/disabled through the update/disable hooks
+        * above, and the CRTC enable/disable independently controls
+        * whether anything scans out at all, but the firmware doesn't
+        * give us a CRTC-level control for that.
+        */
+       vc4_cursor_plane_atomic_disable(vc4_crtc->cursor,
+                                       vc4_crtc->cursor->state);
+       vc4_plane_set_primary_blank(vc4_crtc->primary, true);
 }
 
 static void vc4_crtc_enable(struct drm_crtc *crtc, struct drm_crtc_state *old_state)
 {
+       struct vc4_crtc *vc4_crtc = to_vc4_crtc(crtc);
+
+       /* Unblank the planes (if they're supposed to be displayed). */
+       if (vc4_crtc->primary->state->fb)
+               vc4_plane_set_primary_blank(vc4_crtc->primary, false);
+       if (vc4_crtc->cursor->state->fb) {
+               vc4_cursor_plane_atomic_update(vc4_crtc->cursor,
+                                              vc4_crtc->cursor->state);
+       }
 }
 
 static int vc4_crtc_atomic_check(struct drm_crtc *crtc,
@@ -618,6 +649,9 @@ static int vc4_fkms_bind(struct device *dev, struct device *master, void *data)
        primary_plane->crtc = crtc;
        cursor_plane->crtc = crtc;
 
+       vc4_crtc->primary = primary_plane;
+       vc4_crtc->cursor = cursor_plane;
+
        vc4_encoder = devm_kzalloc(dev, sizeof(*vc4_encoder), GFP_KERNEL);
        if (!vc4_encoder)
                return -ENOMEM;