diff options
-rw-r--r-- | drivers/gpu/drm/exynos/exynos_drm_crtc.c | 16 | ||||
-rw-r--r-- | drivers/gpu/drm/exynos/exynos_drm_drv.c | 14 | ||||
-rw-r--r-- | drivers/gpu/drm/exynos/exynos_drm_drv.h | 3 | ||||
-rw-r--r-- | drivers/gpu/drm/exynos/exynos_drm_fimd.c | 15 |
4 files changed, 35 insertions, 13 deletions
diff --git a/drivers/gpu/drm/exynos/exynos_drm_crtc.c b/drivers/gpu/drm/exynos/exynos_drm_crtc.c index 8cd9d8eec46e..9337e5e2dbb6 100644 --- a/drivers/gpu/drm/exynos/exynos_drm_crtc.c +++ b/drivers/gpu/drm/exynos/exynos_drm_crtc.c | |||
@@ -259,13 +259,21 @@ static int exynos_drm_crtc_page_flip(struct drm_crtc *crtc, | |||
259 | 259 | ||
260 | mutex_lock(&dev->struct_mutex); | 260 | mutex_lock(&dev->struct_mutex); |
261 | 261 | ||
262 | if (event && !dev_priv->pageflip_event) { | 262 | if (event) { |
263 | /* | ||
264 | * the pipe from user always is 0 so we can set pipe number | ||
265 | * of current owner to event. | ||
266 | */ | ||
267 | event->pipe = exynos_crtc->pipe; | ||
268 | |||
263 | list_add_tail(&event->base.link, | 269 | list_add_tail(&event->base.link, |
264 | &dev_priv->pageflip_event_list); | 270 | &dev_priv->pageflip_event_list); |
265 | 271 | ||
266 | ret = drm_vblank_get(dev, exynos_crtc->pipe); | 272 | ret = drm_vblank_get(dev, exynos_crtc->pipe); |
267 | if (ret) { | 273 | if (ret) { |
268 | DRM_DEBUG("failed to acquire vblank counter\n"); | 274 | DRM_DEBUG("failed to acquire vblank counter\n"); |
275 | list_del(&event->base.link); | ||
276 | |||
269 | goto out; | 277 | goto out; |
270 | } | 278 | } |
271 | 279 | ||
@@ -274,7 +282,7 @@ static int exynos_drm_crtc_page_flip(struct drm_crtc *crtc, | |||
274 | if (ret) { | 282 | if (ret) { |
275 | crtc->fb = old_fb; | 283 | crtc->fb = old_fb; |
276 | drm_vblank_put(dev, exynos_crtc->pipe); | 284 | drm_vblank_put(dev, exynos_crtc->pipe); |
277 | dev_priv->pageflip_event = false; | 285 | list_del(&event->base.link); |
278 | 286 | ||
279 | goto out; | 287 | goto out; |
280 | } | 288 | } |
@@ -282,12 +290,10 @@ static int exynos_drm_crtc_page_flip(struct drm_crtc *crtc, | |||
282 | /* | 290 | /* |
283 | * the values related to a buffer of the drm framebuffer | 291 | * the values related to a buffer of the drm framebuffer |
284 | * to be applied should be set at here. because these values | 292 | * to be applied should be set at here. because these values |
285 | * first, is set to shadow registers and then to | 293 | * first, are set to shadow registers and then to |
286 | * real registers at vsync front porch period. | 294 | * real registers at vsync front porch period. |
287 | */ | 295 | */ |
288 | exynos_drm_crtc_apply(crtc); | 296 | exynos_drm_crtc_apply(crtc); |
289 | |||
290 | dev_priv->pageflip_event = true; | ||
291 | } | 297 | } |
292 | out: | 298 | out: |
293 | mutex_unlock(&dev->struct_mutex); | 299 | mutex_unlock(&dev->struct_mutex); |
diff --git a/drivers/gpu/drm/exynos/exynos_drm_drv.c b/drivers/gpu/drm/exynos/exynos_drm_drv.c index a190348ed9bd..83810cbe3c17 100644 --- a/drivers/gpu/drm/exynos/exynos_drm_drv.c +++ b/drivers/gpu/drm/exynos/exynos_drm_drv.c | |||
@@ -124,6 +124,19 @@ static int exynos_drm_unload(struct drm_device *dev) | |||
124 | return 0; | 124 | return 0; |
125 | } | 125 | } |
126 | 126 | ||
127 | static void exynos_drm_preclose(struct drm_device *dev, | ||
128 | struct drm_file *file_priv) | ||
129 | { | ||
130 | struct exynos_drm_private *dev_priv = dev->dev_private; | ||
131 | |||
132 | /* | ||
133 | * drm framework frees all events at release time, | ||
134 | * so private event list should be cleared. | ||
135 | */ | ||
136 | if (!list_empty(&dev_priv->pageflip_event_list)) | ||
137 | INIT_LIST_HEAD(&dev_priv->pageflip_event_list); | ||
138 | } | ||
139 | |||
127 | static void exynos_drm_lastclose(struct drm_device *dev) | 140 | static void exynos_drm_lastclose(struct drm_device *dev) |
128 | { | 141 | { |
129 | DRM_DEBUG_DRIVER("%s\n", __FILE__); | 142 | DRM_DEBUG_DRIVER("%s\n", __FILE__); |
@@ -152,6 +165,7 @@ static struct drm_driver exynos_drm_driver = { | |||
152 | DRIVER_MODESET | DRIVER_GEM, | 165 | DRIVER_MODESET | DRIVER_GEM, |
153 | .load = exynos_drm_load, | 166 | .load = exynos_drm_load, |
154 | .unload = exynos_drm_unload, | 167 | .unload = exynos_drm_unload, |
168 | .preclose = exynos_drm_preclose, | ||
155 | .lastclose = exynos_drm_lastclose, | 169 | .lastclose = exynos_drm_lastclose, |
156 | .get_vblank_counter = drm_vblank_count, | 170 | .get_vblank_counter = drm_vblank_count, |
157 | .enable_vblank = exynos_drm_crtc_enable_vblank, | 171 | .enable_vblank = exynos_drm_crtc_enable_vblank, |
diff --git a/drivers/gpu/drm/exynos/exynos_drm_drv.h b/drivers/gpu/drm/exynos/exynos_drm_drv.h index 63c1422403d8..915f5cd4d109 100644 --- a/drivers/gpu/drm/exynos/exynos_drm_drv.h +++ b/drivers/gpu/drm/exynos/exynos_drm_drv.h | |||
@@ -187,9 +187,8 @@ struct exynos_drm_manager { | |||
187 | struct exynos_drm_private { | 187 | struct exynos_drm_private { |
188 | struct drm_fb_helper *fb_helper; | 188 | struct drm_fb_helper *fb_helper; |
189 | 189 | ||
190 | /* for pageflip */ | 190 | /* list head for new event to be added. */ |
191 | struct list_head pageflip_event_list; | 191 | struct list_head pageflip_event_list; |
192 | bool pageflip_event; | ||
193 | 192 | ||
194 | /* | 193 | /* |
195 | * created crtc object would be contained at this array and | 194 | * created crtc object would be contained at this array and |
diff --git a/drivers/gpu/drm/exynos/exynos_drm_fimd.c b/drivers/gpu/drm/exynos/exynos_drm_fimd.c index b0afa8493230..68446b3bd8f0 100644 --- a/drivers/gpu/drm/exynos/exynos_drm_fimd.c +++ b/drivers/gpu/drm/exynos/exynos_drm_fimd.c | |||
@@ -487,21 +487,24 @@ static struct exynos_drm_overlay_ops fimd_overlay_ops = { | |||
487 | .disable = fimd_win_disable, | 487 | .disable = fimd_win_disable, |
488 | }; | 488 | }; |
489 | 489 | ||
490 | /* for pageflip event */ | ||
491 | static void fimd_finish_pageflip(struct drm_device *drm_dev, int crtc) | 490 | static void fimd_finish_pageflip(struct drm_device *drm_dev, int crtc) |
492 | { | 491 | { |
493 | struct exynos_drm_private *dev_priv = drm_dev->dev_private; | 492 | struct exynos_drm_private *dev_priv = drm_dev->dev_private; |
494 | struct drm_pending_vblank_event *e, *t; | 493 | struct drm_pending_vblank_event *e, *t; |
495 | struct timeval now; | 494 | struct timeval now; |
496 | unsigned long flags; | 495 | unsigned long flags; |
497 | 496 | bool is_checked = false; | |
498 | if (!dev_priv->pageflip_event) | ||
499 | return; | ||
500 | 497 | ||
501 | spin_lock_irqsave(&drm_dev->event_lock, flags); | 498 | spin_lock_irqsave(&drm_dev->event_lock, flags); |
502 | 499 | ||
503 | list_for_each_entry_safe(e, t, &dev_priv->pageflip_event_list, | 500 | list_for_each_entry_safe(e, t, &dev_priv->pageflip_event_list, |
504 | base.link) { | 501 | base.link) { |
502 | /* if event's pipe isn't same as crtc then ignor it. */ | ||
503 | if (crtc != e->pipe) | ||
504 | continue; | ||
505 | |||
506 | is_checked = true; | ||
507 | |||
505 | do_gettimeofday(&now); | 508 | do_gettimeofday(&now); |
506 | e->event.sequence = 0; | 509 | e->event.sequence = 0; |
507 | e->event.tv_sec = now.tv_sec; | 510 | e->event.tv_sec = now.tv_sec; |
@@ -511,8 +514,8 @@ static void fimd_finish_pageflip(struct drm_device *drm_dev, int crtc) | |||
511 | wake_up_interruptible(&e->base.file_priv->event_wait); | 514 | wake_up_interruptible(&e->base.file_priv->event_wait); |
512 | } | 515 | } |
513 | 516 | ||
514 | drm_vblank_put(drm_dev, crtc); | 517 | if (is_checked) |
515 | dev_priv->pageflip_event = false; | 518 | drm_vblank_put(drm_dev, crtc); |
516 | 519 | ||
517 | spin_unlock_irqrestore(&drm_dev->event_lock, flags); | 520 | spin_unlock_irqrestore(&drm_dev->event_lock, flags); |
518 | } | 521 | } |