MLK-21525 drm/imx: dpu: kms: Disallow primary plane on-the-fly disablement
authorLiu Ying <victor.liu@nxp.com>
Tue, 23 Apr 2019 11:25:24 +0000 (19:25 +0800)
committerLiu Ying <victor.liu@nxp.com>
Wed, 24 Apr 2019 06:22:30 +0000 (14:22 +0800)
The below commit introduced in v4.16 reveals the fact that the DPU KMS
driver doesn't support primary plane on-the-fly disablement.  This may
cause display issue when we restart weston with 4kp60 display for i.MX8QM.
To support this, we need considerable driver change, but doesn't make
too much sense, because disabling primary plane on an active CRTC doesn't
often happen for real graphics update.  In order not to run into this problem,
we can explicitly disallow this use case in ->atomic_check().  This rejection
makes us fall back to disable CRTC when removing the primary plane's
framebuffer according to the below commit's rationale, which is the original
behavior of atomic_remove_fb().

commit 846c7dfc1193 ("drm/atomic: Try to preserve the crtc enabled state in drm_atomic_remove_fb, v2.")

Signed-off-by: Liu Ying <victor.liu@nxp.com>
drivers/gpu/drm/imx/dpu/dpu-kms.c

index 07e68bc..f120ab7 100644 (file)
@@ -521,6 +521,40 @@ dpu_atomic_put_possible_states_per_crtc(struct drm_crtc_state *crtc_state)
        dpu_atomic_put_crtc_state(state, crtc);
 }
 
+/* primary plane on-the-fly disablement? */
+static bool
+dpu_primary_plane_is_disabling_otf_per_crtc(struct drm_crtc_state *crtc_state)
+{
+       struct drm_atomic_state *state = crtc_state->state;
+       struct drm_plane *plane;
+       struct drm_plane_state *old_plane_state, *new_plane_state;
+       int i;
+
+       if (!crtc_state->enable)
+               return false;
+
+       if (drm_atomic_crtc_needs_modeset(crtc_state))
+               return false;
+
+       for_each_oldnew_plane_in_state(state, plane, old_plane_state,
+                                      new_plane_state, i) {
+               if (plane->type != DRM_PLANE_TYPE_PRIMARY)
+                       continue;
+
+               if (!old_plane_state->crtc)
+                       continue;
+
+               if (old_plane_state->crtc != crtc_state->crtc)
+                       continue;
+
+               if (drm_atomic_plane_disabling(old_plane_state,
+                                              new_plane_state))
+                       return true;
+       }
+
+       return false;
+}
+
 static int dpu_drm_atomic_check(struct drm_device *dev,
                                struct drm_atomic_state *state)
 {
@@ -580,6 +614,10 @@ static int dpu_drm_atomic_check(struct drm_device *dev,
                imx_crtc_state = to_imx_crtc_state(crtc_state);
                dcstate = to_dpu_crtc_state(imx_crtc_state);
 
+               /* disallow primary plane on-the-fly disablement */
+               if (dpu_primary_plane_is_disabling_otf_per_crtc(crtc_state))
+                       return -EINVAL;
+
                if (crtc_state->enable) {
                        if (use_pc[dpu_crtc->crtc_grp_id])
                                return -EINVAL;