mirror of
https://github.com/AuxXxilium/linux_dsm_epyc7002.git
synced 2024-12-18 04:30:08 +07:00
drm/armada: wait and cancel any pending frame work at disable
Wait for a second, and if we time out, cancel any pending work when disabling the primary plane. This ensures that any pending work is completed or cleaned up prior to the disable taking effect. Signed-off-by: Russell King <rmk+kernel@armlinux.org.uk>
This commit is contained in:
parent
2839d45c7d
commit
65724a1943
@ -273,18 +273,15 @@ void armada_drm_plane_work_cancel(struct armada_crtc *dcrtc,
|
|||||||
armada_drm_plane_work_call(dcrtc, work, work->cancel);
|
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_plane_work *work)
|
||||||
{
|
{
|
||||||
struct armada_frame_work *fwork = container_of(work, struct armada_frame_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;
|
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) {
|
if (fwork->event) {
|
||||||
|
struct drm_device *dev = dcrtc->crtc.dev;
|
||||||
|
|
||||||
spin_lock_irqsave(&dev->event_lock, flags);
|
spin_lock_irqsave(&dev->event_lock, flags);
|
||||||
drm_crtc_send_vblank_event(&dcrtc->crtc, fwork->event);
|
drm_crtc_send_vblank_event(&dcrtc->crtc, fwork->event);
|
||||||
spin_unlock_irqrestore(&dev->event_lock, flags);
|
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);
|
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 *
|
static struct armada_frame_work *
|
||||||
armada_drm_crtc_alloc_frame_work(struct drm_plane *plane)
|
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.plane = plane;
|
||||||
work->work.fn = armada_drm_crtc_complete_frame_work;
|
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);
|
armada_reg_queue_end(work->regs, i);
|
||||||
|
|
||||||
return work;
|
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,
|
void armada_drm_crtc_plane_disable(struct armada_crtc *dcrtc,
|
||||||
struct drm_plane *plane)
|
struct drm_plane *plane)
|
||||||
{
|
{
|
||||||
|
struct armada_plane *dplane = drm_to_armada_plane(plane);
|
||||||
u32 sram_para1, dma_ctrl0_mask;
|
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;
|
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);
|
spin_lock_irq(&dcrtc->irq_lock);
|
||||||
armada_updatel(0, dma_ctrl0_mask, dcrtc->base + LCD_SPU_DMA_CTRL0);
|
armada_updatel(0, dma_ctrl0_mask, dcrtc->base + LCD_SPU_DMA_CTRL0);
|
||||||
spin_unlock_irq(&dcrtc->irq_lock);
|
spin_unlock_irq(&dcrtc->irq_lock);
|
||||||
|
@ -270,8 +270,6 @@ static int armada_ovl_plane_disable(struct drm_plane *plane,
|
|||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
dcrtc = drm_to_armada_crtc(dplane->base.base.crtc);
|
dcrtc = drm_to_armada_crtc(dplane->base.base.crtc);
|
||||||
|
|
||||||
armada_drm_plane_work_cancel(dcrtc, &dplane->base);
|
|
||||||
armada_drm_crtc_plane_disable(dcrtc, plane);
|
armada_drm_crtc_plane_disable(dcrtc, plane);
|
||||||
|
|
||||||
dcrtc->plane = NULL;
|
dcrtc->plane = NULL;
|
||||||
|
Loading…
Reference in New Issue
Block a user