gfx: drv: Clear all pending flips when a pipe is being disabled
authorVille Syrjälä <ville.syrjala@linux.intel.com>
Thu, 29 Mar 2012 18:14:16 +0000 (21:14 +0300)
committerMarkus Lehtonen <markus.lehtonen@linux.intel.com>
Tue, 3 Jul 2012 09:30:50 +0000 (12:30 +0300)
When a pipe is disabled, no vblank interrupt will be generated, and thus
any pending flip will not complete on its own. Complete all pending
flips when the associated pipe is being disabled.

The drm_flip_driver initialization must be performed earlier since the
DPMS hooks get called during modeset init. Also fix the crtc/plane vs.
drm_flip_helper vs. drm_flip_driver cleanup order.

Issue: ANDROID-2302
Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
Signed-off-by: Artem Bityutskiy <artem.bityutskiy@linux.intel.com>
drivers/staging/mrst/drv/drm_flip.c
drivers/staging/mrst/drv/drm_flip.h
drivers/staging/mrst/drv/mdfld_dsi_dpi.c
drivers/staging/mrst/drv/mdfld_overlay.c
drivers/staging/mrst/drv/psb_drv.c
drivers/staging/mrst/drv/psb_fb.c
drivers/staging/mrst/drv/psb_intel_display.c
drivers/staging/mrst/drv/psb_intel_drv.h

index aa1f3ad..064f44d 100644 (file)
@@ -142,7 +142,7 @@ void drm_flip_helper_init(struct drm_flip_helper *helper,
        helper->funcs = funcs;
 }
 
-void drm_flip_helper_fini(struct drm_flip_helper *helper)
+void drm_flip_helper_clear(struct drm_flip_helper *helper)
 {
        unsigned long flags;
        struct drm_flip_driver *driver = helper->driver;
@@ -175,6 +175,16 @@ void drm_flip_helper_fini(struct drm_flip_helper *helper)
                queue_work(driver->wq, &driver->cleanup_work);
 }
 
+void drm_flip_helper_fini(struct drm_flip_helper *helper)
+{
+       struct drm_flip_driver *driver = helper->driver;
+
+       drm_flip_helper_clear(helper);
+
+       flush_work_sync(&driver->finish_work);
+       flush_work_sync(&driver->cleanup_work);
+}
+
 void drm_flip_helper_vblank(struct drm_flip_helper *helper)
 {
        struct drm_flip_driver *driver = helper->driver;
@@ -230,9 +240,6 @@ void drm_flip_driver_init(struct drm_flip_driver *driver,
 
 void drm_flip_driver_fini(struct drm_flip_driver *driver)
 {
-       flush_work_sync(&driver->finish_work);
-       flush_work_sync(&driver->cleanup_work);
-
        destroy_workqueue(driver->wq);
 
        /* All the scheduled flips should be cleaned up by now. */
index 8e70a88..4172d6e 100644 (file)
@@ -182,9 +182,16 @@ void drm_flip_helper_init(struct drm_flip_helper *helper,
                          const struct drm_flip_helper_funcs *funcs);
 
 /*
- * Finalize flip helper. This will forcefully complete the
+ * Clear flip helper state. This will forcefully complete the
  * helper's pending flip (if any).
  */
+void drm_flip_helper_clear(struct drm_flip_helper *helper);
+
+/*
+ * Finalize the flip helper. This will forcefully complete the
+ * helper's pending flip (if any), and wait for the finish and
+ * cleanup works to finish.
+ */
 void drm_flip_helper_fini(struct drm_flip_helper *helper);
 
 /*
index f8c19d5..e146e8b 100644 (file)
@@ -196,6 +196,8 @@ static void mdfld_dsi_configure_down(struct mdfld_dsi_encoder * dsi_encoder, int
        mdfld_dsi_dpi_shut_down(dpi_output, pipe);  //Send shut down command
 
        dsi_set_device_ready_state(dev, 0, pipe);  //Clear device ready state
+
+       mdfld_pipe_disabled(dev, pipe);
 }
 
 static void mdfld_dsi_configure_up(struct mdfld_dsi_encoder * dsi_encoder, int pipe)
index 40d233a..a3e5423 100644 (file)
@@ -1923,3 +1923,13 @@ struct drm_flip *mdfld_overlay_atomic_flip(struct drm_plane *plane, int pipe)
 
        return &oflip->base;
 }
+
+void mdfld_overlay_pipe_disabled(struct drm_plane *plane, int pipe)
+{
+       struct mfld_overlay *ovl = to_mfld_overlay(plane);
+
+       if (ovl->pipe != pipe)
+               return;
+
+       drm_flip_helper_clear(&ovl->flip_helper);
+}
index a65ff77..16fa440 100644 (file)
@@ -61,7 +61,6 @@
 #include "bufferclass_video_linux.h"
 
 #include "android_hdmi.h"
-#include "psb_page_flip.h"
 
 int drm_psb_debug;
 /*EXPORT_SYMBOL(drm_psb_debug); */
@@ -946,8 +945,6 @@ static int psb_driver_unload(struct drm_device *dev)
        struct drm_psb_private *dev_priv =
                (struct drm_psb_private *) dev->dev_private;
 
-       psb_page_flip_fini(dev);
-
        /*Fristly, unload pvr driver*/
        PVRSRVDrmUnload(dev);
 
@@ -1298,8 +1295,6 @@ static int psb_driver_load(struct drm_device *dev, unsigned long chipset)
        gl3_enable();
 #endif
 
-       psb_page_flip_init(dev);
-
        /*Intel drm driver load is done, continue doing pvr load*/
        DRM_DEBUG("Pvr driver load\n");
 
index 036e60b..2f7574d 100644 (file)
@@ -39,6 +39,7 @@
 #include "psb_ttm_userobj_api.h"
 #include "psb_fb.h"
 #include "psb_pvr_glue.h"
+#include "psb_page_flip.h"
 
 #include "mdfld_dsi_dbi.h"
 #include "mdfld_dsi_output.h"
@@ -783,6 +784,8 @@ void psb_modeset_init(struct drm_device *dev)
        mode_dev->bo_pin_for_scanout = psb_bo_pin_for_scanout;
        mode_dev->bo_unpin_for_scanout = psb_bo_unpin_for_scanout;
 
+       psb_page_flip_init(dev);
+
        drm_mode_config_init(dev);
 
        dev->mode_config.min_width = 0;
@@ -818,6 +821,8 @@ void psb_modeset_cleanup(struct drm_device *dev)
        
        drm_mode_config_cleanup(dev);
 
+       psb_page_flip_fini(dev);
+
        mutex_unlock(&dev->struct_mutex);
 }
 
index e2e4a56..d06aa1c 100644 (file)
@@ -1054,6 +1054,28 @@ void mdfld_disable_crtc (struct drm_device *dev, int pipe)
 
 }
 
+void mdfld_pipe_disabled(struct drm_device *dev, int pipe)
+{
+       struct drm_psb_private *dev_priv = dev->dev_private;
+       struct drm_crtc *crtc;
+       int i;
+
+       list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) {
+               struct psb_intel_crtc *psb_intel_crtc = to_psb_intel_crtc(crtc);
+
+               if (psb_intel_crtc->pipe == pipe) {
+                       drm_flip_helper_clear(&psb_intel_crtc->flip_helper);
+                       break;
+               }
+       }
+
+       for (i = 0; i < ARRAY_SIZE(dev_priv->overlays); i++) {
+               if (!dev_priv->overlays[i])
+                       continue;
+               mdfld_overlay_pipe_disabled(dev_priv->overlays[i], pipe);
+       }
+}
+
 /**
  * Sets the power management mode of the pipe and plane.
  *
@@ -1276,6 +1298,8 @@ static void mdfld_crtc_dpms(struct drm_crtc *crtc, int mode)
 #endif  /* MDFLD_PO_JLIU7 */   
                        }
                }
+
+               mdfld_pipe_disabled(dev, pipe);
                break;
        }
 
index 7cadf0f..4316182 100644 (file)
@@ -241,6 +241,7 @@ extern int intelfb_probe(struct drm_device *dev);
 extern int intelfb_remove(struct drm_device *dev,
                          struct drm_framebuffer *fb);
 extern void mdfld_disable_crtc (struct drm_device *dev, int pipe);
+extern void mdfld_pipe_disabled(struct drm_device *dev, int pipe);
 
 extern void mdfld_dbi_update_fb (struct drm_device *dev, int pipe);
 extern void mdfld_dbi_enter_dsr (struct drm_device *dev);
@@ -257,5 +258,6 @@ extern void mdfld_overlay_suspend(struct drm_plane *plane);
 extern void mdfld_overlay_resume(struct drm_plane *plane);
 extern struct drm_flip *mdfld_overlay_atomic_flip(struct drm_plane *plane, int pipe);
 extern void mdfld_overlay_process_vblank(struct drm_plane *plane, int pipe);
+extern void mdfld_overlay_pipe_disabled(struct drm_plane *plane, int pipe);
 
 #endif                         /* __INTEL_DRV_H__ */