staging: mrst: Fix zorder handling while overlay updates are pending
authorVille Syrjälä <ville.syrjala@linux.intel.com>
Wed, 14 Dec 2011 22:12:10 +0000 (00:12 +0200)
committerMarkus Lehtonen <markus.lehtonen@linux.intel.com>
Tue, 3 Jul 2012 09:29:07 +0000 (12:29 +0300)
Configuring the Z order may potentially need to touch both overlays
simultaneosly. So ovl_wait() needs to be performed for both overlays.
Do that before touching any state to allow set_plane_opts() to fail
in a clean fashion.

Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
Acked-by: Pauli Nieminen <pauli.nieminen@linux.intel.com>
Reviewed-by: Jani Nikula <jani.nikula@intel.com>
Signed-off-by: Kirill A. Shutemov <kirill.shutemov@linux.intel.com>
drivers/staging/mrst/drv/mdfld_overlay.c

index 74a2def..bfa51cc 100644 (file)
@@ -1095,11 +1095,8 @@ static void ovl_set_dst_key(struct mfld_overlay *ovl, const struct drm_plane_opt
        ovl->dirty |= OVL_DIRTY_REGS;
 }
 
-static void ovl_set_zorder(struct mfld_overlay *ovl)
+static void ovl_set_zorder(struct drm_plane *plane_a, struct drm_plane *plane_c)
 {
-       struct drm_psb_private *dev_priv = ovl->dev->dev_private;
-       struct drm_plane *plane_a = dev_priv->overlays[0];
-       struct drm_plane *plane_c = dev_priv->overlays[1];
        struct mfld_overlay *ovl_a;
        struct mfld_overlay *ovl_c;
        struct mfld_overlay_regs *regs_a;
@@ -1130,29 +1127,37 @@ static void ovl_set_zorder(struct mfld_overlay *ovl)
 
        ovl_a->dirty |= OVL_DIRTY_REGS;
        ovl_c->dirty |= OVL_DIRTY_REGS;
-
-       /* commit the other overlay */
-       if (ovl == ovl_a)
-               ovl_commit(ovl_c);
-       else
-               ovl_commit(ovl_a);
 }
 
 static int
 mfld_overlay_set_plane_opts(struct drm_plane *plane, uint32_t flags, struct drm_plane_opts *opts)
 {
        struct mfld_overlay *ovl = to_mfld_overlay(plane);
+       struct drm_plane *other_plane = NULL;
+       struct mfld_overlay *other_ovl = NULL;
        int r;
 
        if (flags & DRM_MODE_PLANE_ZORDER) {
+               struct drm_psb_private *dev_priv = ovl->dev->dev_private;
+
                if (opts->zorder < 0)
                        return -EINVAL;
+
+               other_plane = dev_priv->overlays[!ovl->id];
+               if (other_plane)
+                       other_ovl = to_mfld_overlay(other_plane);
        }
 
        r = ovl_wait(ovl);
        if (r)
                return r;
 
+       if (other_ovl) {
+               r = ovl_wait(other_ovl);
+               if (r)
+                       return r;
+       }
+
        /* Constant alpha bits live in color key registers */
        if (flags & DRM_MODE_PLANE_CONST_ALPHA)
                flags |= DRM_MODE_PLANE_SRC_KEY | DRM_MODE_PLANE_DST_KEY;
@@ -1204,10 +1209,13 @@ mfld_overlay_set_plane_opts(struct drm_plane *plane, uint32_t flags, struct drm_
 
        if (flags & DRM_MODE_PLANE_ZORDER) {
                plane->opts.zorder = opts->zorder;
-               ovl_set_zorder(ovl);
+               ovl_set_zorder(ovl->id == 0 ? plane : other_plane,
+                              ovl->id == 0 ? other_plane : plane);
        }
 
        ovl_commit(ovl);
+       if (other_ovl)
+               ovl_commit(other_ovl);
 
        return 0;
 }