summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--drivers/gpu/drm/armada/armada_crtc.c28
-rw-r--r--drivers/gpu/drm/armada/armada_overlay.c2
2 files changed, 22 insertions, 8 deletions
diff --git a/drivers/gpu/drm/armada/armada_crtc.c b/drivers/gpu/drm/armada/armada_crtc.c
index f10ab0275ce7..328f030ffbdc 100644
--- a/drivers/gpu/drm/armada/armada_crtc.c
+++ b/drivers/gpu/drm/armada/armada_crtc.c
@@ -273,18 +273,15 @@ void armada_drm_plane_work_cancel(struct armada_crtc *dcrtc,
armada_drm_plane_work_call(dcrtc, work, work->cancel);
}
-static void armada_drm_crtc_complete_frame_work(struct armada_crtc *dcrtc,
+static void armada_drm_crtc_finish_frame_work(struct armada_crtc *dcrtc,
struct armada_plane_work *work)
{
struct armada_frame_work *fwork = container_of(work, struct armada_frame_work, work);
- struct drm_device *dev = dcrtc->crtc.dev;
unsigned long flags;
- spin_lock_irqsave(&dcrtc->irq_lock, flags);
- armada_drm_crtc_update_regs(dcrtc, fwork->regs);
- spin_unlock_irqrestore(&dcrtc->irq_lock, flags);
-
if (fwork->event) {
+ struct drm_device *dev = dcrtc->crtc.dev;
+
spin_lock_irqsave(&dev->event_lock, flags);
drm_crtc_send_vblank_event(&dcrtc->crtc, fwork->event);
spin_unlock_irqrestore(&dev->event_lock, flags);
@@ -295,6 +292,19 @@ static void armada_drm_crtc_complete_frame_work(struct armada_crtc *dcrtc,
kfree(fwork);
}
+static void armada_drm_crtc_complete_frame_work(struct armada_crtc *dcrtc,
+ struct armada_plane_work *work)
+{
+ struct armada_frame_work *fwork = container_of(work, struct armada_frame_work, work);
+ unsigned long flags;
+
+ spin_lock_irqsave(&dcrtc->irq_lock, flags);
+ armada_drm_crtc_update_regs(dcrtc, fwork->regs);
+ spin_unlock_irqrestore(&dcrtc->irq_lock, flags);
+
+ armada_drm_crtc_finish_frame_work(dcrtc, work);
+}
+
static struct armada_frame_work *
armada_drm_crtc_alloc_frame_work(struct drm_plane *plane)
{
@@ -307,6 +317,7 @@ armada_drm_crtc_alloc_frame_work(struct drm_plane *plane)
work->work.plane = plane;
work->work.fn = armada_drm_crtc_complete_frame_work;
+ work->work.cancel = armada_drm_crtc_finish_frame_work;
armada_reg_queue_end(work->regs, i);
return work;
@@ -752,6 +763,7 @@ static int armada_drm_crtc_mode_set_base(struct drm_crtc *crtc, int x, int y,
void armada_drm_crtc_plane_disable(struct armada_crtc *dcrtc,
struct drm_plane *plane)
{
+ struct armada_plane *dplane = drm_to_armada_plane(plane);
u32 sram_para1, dma_ctrl0_mask;
/*
@@ -775,6 +787,10 @@ void armada_drm_crtc_plane_disable(struct armada_crtc *dcrtc,
dma_ctrl0_mask = CFG_DMA_ENA;
}
+ /* Wait for any preceding work to complete, but don't wedge */
+ if (WARN_ON(!armada_drm_plane_work_wait(dplane, HZ)))
+ armada_drm_plane_work_cancel(dcrtc, dplane);
+
spin_lock_irq(&dcrtc->irq_lock);
armada_updatel(0, dma_ctrl0_mask, dcrtc->base + LCD_SPU_DMA_CTRL0);
spin_unlock_irq(&dcrtc->irq_lock);
diff --git a/drivers/gpu/drm/armada/armada_overlay.c b/drivers/gpu/drm/armada/armada_overlay.c
index 1fa8ea8cb2de..cf8442583bfc 100644
--- a/drivers/gpu/drm/armada/armada_overlay.c
+++ b/drivers/gpu/drm/armada/armada_overlay.c
@@ -270,8 +270,6 @@ static int armada_ovl_plane_disable(struct drm_plane *plane,
return 0;
dcrtc = drm_to_armada_crtc(dplane->base.base.crtc);
-
- armada_drm_plane_work_cancel(dcrtc, &dplane->base);
armada_drm_crtc_plane_disable(dcrtc, plane);
dcrtc->plane = NULL;