aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/gpu/drm/exynos/exynos_drm_crtc.c16
-rw-r--r--drivers/gpu/drm/exynos/exynos_drm_drv.c14
-rw-r--r--drivers/gpu/drm/exynos/exynos_drm_drv.h3
-rw-r--r--drivers/gpu/drm/exynos/exynos_drm_fimd.c15
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 }
292out: 298out:
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
127static 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
127static void exynos_drm_lastclose(struct drm_device *dev) 140static 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 {
187struct exynos_drm_private { 187struct 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 */
491static void fimd_finish_pageflip(struct drm_device *drm_dev, int crtc) 490static 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}