@@ -213,13 +213,24 @@ static void imx_drm_disable_vblank(struct drm_device *drm, int pipe)
static void imx_drm_driver_preclose(struct drm_device *drm,
struct drm_file *file)
{
+ struct imx_drm_device *imxdrm = drm->dev_private;
+ struct imx_drm_crtc_helper_funcs *helpers;
+ struct imx_drm_crtc *imx_drm_crtc;
int pipe;
if (!file->is_master)
return;
- for (pipe = 0; pipe < MAX_PIPES; pipe++)
- imx_drm_disable_vblank(drm, pipe);
+ for (pipe = 0; pipe < MAX_PIPES; pipe++) {
+ imx_drm_crtc = imxdrm->crtc[pipe_to_crtc_id(pipe)];
+ if (!imx_drm_crtc)
+ continue;
+ helpers = &imx_drm_crtc->imx_drm_helper_funcs;
+ if (!helpers->cancel_page_flip)
+ continue;
+
+ helpers->cancel_page_flip(imx_drm_crtc->crtc, file, pipe);
+ }
}
static const struct file_operations imx_drm_driver_fops = {
@@ -21,6 +21,8 @@ int imx_drm_overlay_plane_pipe(struct imx_drm_crtc *crtc);
struct imx_drm_crtc_helper_funcs {
int (*enable_vblank)(struct drm_crtc *crtc, int pipe);
void (*disable_vblank)(struct drm_crtc *crtc, int pipe);
+ void (*cancel_page_flip)(struct drm_crtc *crtc, struct drm_file *file,
+ int pipe);
int (*set_interface_pix_fmt)(struct drm_crtc *crtc, u32 encoder_type,
u32 pix_fmt, struct ipu_dc_if_map *pix_map,
int hsync_pin, int vsync_pin);
@@ -398,6 +398,18 @@ static void ipu_disable_vblank(struct drm_crtc *crtc, int pipe)
ipu_plane_disable_vblank(ipu_plane);
}
+static void ipu_cancel_page_flip(struct drm_crtc *crtc, struct drm_file *file,
+ int pipe)
+{
+ struct ipu_crtc *ipu_crtc = to_ipu_crtc(crtc);
+ struct ipu_plane *ipu_plane = pipe_to_plane(ipu_crtc, pipe);
+
+ if (!ipu_plane)
+ return;
+
+ ipu_plane_cancel_page_flip(ipu_plane, file);
+}
+
static int ipu_set_interface_pix_fmt(struct drm_crtc *crtc, u32 encoder_type,
u32 pixfmt, struct ipu_dc_if_map *pixmap,
int hsync_pin, int vsync_pin)
@@ -435,6 +447,7 @@ static int ipu_gamma_set(struct drm_crtc *crtc, bool enable, u32 *m, u32 *b)
static const struct imx_drm_crtc_helper_funcs ipu_crtc_helper_funcs = {
.enable_vblank = ipu_enable_vblank,
.disable_vblank = ipu_disable_vblank,
+ .cancel_page_flip = ipu_cancel_page_flip,
.set_interface_pix_fmt = ipu_set_interface_pix_fmt,
.gamma_set = ipu_gamma_set,
.crtc_funcs = &ipu_crtc_funcs,
@@ -150,6 +150,28 @@ void ipu_plane_disable_vblank(struct ipu_plane *ipu_plane)
ipu_plane->newfb = NULL;
}
+void ipu_plane_cancel_page_flip(struct ipu_plane *ipu_plane,
+ struct drm_file *file)
+{
+ struct drm_device *drm = ipu_plane->base.dev;
+ struct drm_pending_vblank_event *event;
+ unsigned long flags;
+
+ /*
+ * Destroy the pending vertical blanking event associated with the
+ * pending page flip, if any, and disable vertical blanking interrupts.
+ */
+ spin_lock_irqsave(&drm->event_lock, flags);
+ event = ipu_plane->page_flip_event;
+ if (event && event->base.file_priv == file) {
+ ipu_plane->page_flip_event = NULL;
+ ipu_plane->newfb = NULL;
+ event->base.destroy(&event->base);
+ drm_vblank_put(drm, ipu_plane->pipe);
+ }
+ spin_unlock_irqrestore(&drm->event_lock, flags);
+}
+
int ipu_plane_mode_set(struct ipu_plane *ipu_plane, struct drm_crtc *crtc,
struct drm_display_mode *mode,
struct drm_framebuffer *fb, int crtc_x, int crtc_y,
@@ -63,6 +63,8 @@ int ipu_plane_page_flip(struct drm_plane *plane,
int ipu_plane_enable_vblank(struct ipu_plane *ipu_plane);
void ipu_plane_disable_vblank(struct ipu_plane *ipu_plane);
+void ipu_plane_cancel_page_flip(struct ipu_plane *ipu_plane,
+ struct drm_file *file);
void ipu_plane_enable(struct ipu_plane *plane);
void ipu_plane_disable(struct ipu_plane *plane);
At preclose, destroy page flip events that are pending on every plane. Signed-off-by: Steve Longerbeam <steve_longerbeam@mentor.com> --- drivers/staging/imx-drm/imx-drm-core.c | 15 +++++++++++++-- drivers/staging/imx-drm/imx-drm.h | 2 ++ drivers/staging/imx-drm/ipuv3-crtc.c | 13 +++++++++++++ drivers/staging/imx-drm/ipuv3-plane.c | 22 ++++++++++++++++++++++ drivers/staging/imx-drm/ipuv3-plane.h | 2 ++ 5 files changed, 52 insertions(+), 2 deletions(-)