diff options
author | Eric Anholt <eric@anholt.net> | 2015-06-29 18:49:26 -0700 |
---|---|---|
committer | Eric Anholt <eric@anholt.net> | 2015-06-29 18:59:07 -0700 |
commit | 3c84e9023b144abfb2626fe5fe37a6e42dc3205a (patch) | |
tree | 85d1423482197a3642f1daaf785634ae6ec02d07 | |
parent | f51aff90487c13d99c213f5ce47fbf55fa55658e (diff) | |
download | linux-3c84e9023b144abfb2626fe5fe37a6e42dc3205a.tar.gz |
drm/vc4: When asked for a page flip event, send it at vblank time.
Signed-off-by: Eric Anholt <eric@anholt.net>
-rw-r--r-- | drivers/gpu/drm/vc4/vc4_crtc.c | 49 | ||||
-rw-r--r-- | drivers/gpu/drm/vc4/vc4_drv.c | 10 | ||||
-rw-r--r-- | drivers/gpu/drm/vc4/vc4_drv.h | 3 |
3 files changed, 62 insertions, 0 deletions
diff --git a/drivers/gpu/drm/vc4/vc4_crtc.c b/drivers/gpu/drm/vc4/vc4_crtc.c index 9ddaffe49832..f9960ac34fd7 100644 --- a/drivers/gpu/drm/vc4/vc4_crtc.c +++ b/drivers/gpu/drm/vc4/vc4_crtc.c @@ -265,6 +265,19 @@ static void vc4_crtc_atomic_flush(struct drm_crtc *crtc) DRM_INFO("CRTC %d HVS after:\n", drm_crtc_index(crtc)); vc4_hvs_dump_state(dev); } + + if (crtc->state->event) { + unsigned long flags; + + crtc->state->event->pipe = drm_crtc_index(crtc); + + WARN_ON(drm_crtc_vblank_get(crtc) != 0); + + spin_lock_irqsave(&dev->event_lock, flags); + vc4_crtc->event = crtc->state->event; + spin_unlock_irqrestore(&dev->event_lock, flags); + crtc->state->event = NULL; + } } int vc4_enable_vblank(struct drm_device *dev, int crtc_id) @@ -285,6 +298,21 @@ void vc4_disable_vblank(struct drm_device *dev, int crtc_id) CRTC_WRITE(PV_INTEN, 0); } +static void +vc4_crtc_handle_page_flip(struct vc4_crtc *vc4_crtc) +{ + struct drm_crtc *crtc = &vc4_crtc->base; + struct drm_device *dev = crtc->dev; + unsigned long flags; + + spin_lock_irqsave(&dev->event_lock, flags); + if (vc4_crtc->event) { + drm_crtc_send_vblank_event(crtc, vc4_crtc->event); + vc4_crtc->event = NULL; + } + spin_unlock_irqrestore(&dev->event_lock, flags); +} + static irqreturn_t vc4_crtc_irq_handler(int irq, void *data) { struct vc4_crtc *vc4_crtc = data; @@ -294,6 +322,7 @@ static irqreturn_t vc4_crtc_irq_handler(int irq, void *data) if (stat & PV_INT_VFP_START) { CRTC_WRITE(PV_INTSTAT, PV_INT_VFP_START); drm_crtc_handle_vblank(&vc4_crtc->base); + vc4_crtc_handle_page_flip(vc4_crtc); ret = IRQ_HANDLED; } @@ -322,6 +351,26 @@ static const struct drm_crtc_helper_funcs vc4_crtc_helper_funcs = { .atomic_flush = vc4_crtc_atomic_flush, }; +/* Frees the page flip event when the DRM device is closed with the + * event still outstanding. + */ +void vc4_cancel_page_flip(struct drm_crtc *crtc, struct drm_file *file) +{ + struct vc4_crtc *vc4_crtc = to_vc4_crtc(crtc); + struct drm_device *dev = crtc->dev; + unsigned long flags; + + spin_lock_irqsave(&dev->event_lock, flags); + + if (vc4_crtc->event && vc4_crtc->event->base.file_priv == file) { + vc4_crtc->event->base.destroy(&vc4_crtc->event->base); + drm_crtc_vblank_put(crtc); + vc4_crtc->event = NULL; + } + + spin_unlock_irqrestore(&dev->event_lock, flags); +} + static int vc4_crtc_bind(struct device *dev, struct device *master, void *data) { struct platform_device *pdev = to_platform_device(dev); diff --git a/drivers/gpu/drm/vc4/vc4_drv.c b/drivers/gpu/drm/vc4/vc4_drv.c index 2ea207562310..64fea2618084 100644 --- a/drivers/gpu/drm/vc4/vc4_drv.c +++ b/drivers/gpu/drm/vc4/vc4_drv.c @@ -85,6 +85,15 @@ static int vc4_drm_unload(struct drm_device *dev) return 0; } +static void vc4_drm_preclose(struct drm_device *dev, struct drm_file *file) +{ + struct vc4_dev *vc4 = to_vc4_dev(dev); + struct drm_crtc *crtc; + + list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) + vc4_cancel_page_flip(crtc, file); +} + static const struct file_operations vc4_drm_fops = { .owner = THIS_MODULE, .open = drm_open, @@ -116,6 +125,7 @@ static struct drm_driver vc4_drm_driver = { .load = vc4_drm_load, .unload = vc4_drm_unload, .set_busid = drm_platform_set_busid, + .preclose = vc4_drm_preclose, .irq_handler = vc4_irq, .irq_preinstall = vc4_irq_preinstall, diff --git a/drivers/gpu/drm/vc4/vc4_drv.h b/drivers/gpu/drm/vc4/vc4_drv.h index 5b4227f41015..ed3f48212e00 100644 --- a/drivers/gpu/drm/vc4/vc4_drv.h +++ b/drivers/gpu/drm/vc4/vc4_drv.h @@ -138,6 +138,8 @@ struct vc4_crtc { u32 __iomem *dlist; u32 dlist_size; /* in dwords */ + + struct drm_pending_vblank_event *event; }; static inline struct vc4_crtc * @@ -315,6 +317,7 @@ void vc4_crtc_register(void); void vc4_crtc_unregister(void); int vc4_enable_vblank(struct drm_device *dev, int crtc_id); void vc4_disable_vblank(struct drm_device *dev, int crtc_id); +void vc4_cancel_page_flip(struct drm_crtc *crtc, struct drm_file *file); /** * _wait_for - magic (register) wait macro |