blob: 357fcd59aa484d4e4f181569968440c3a212f4eb [file] [log] [blame]
Inki Dae1c248b72011-10-04 19:19:01 +09001/* exynos_drm_crtc.c
2 *
3 * Copyright (c) 2011 Samsung Electronics Co., Ltd.
4 * Authors:
5 * Inki Dae <inki.dae@samsung.com>
6 * Joonyoung Shim <jy0922.shim@samsung.com>
7 * Seung-Woo Kim <sw0312.kim@samsung.com>
8 *
Inki Daed81aecb2012-12-18 02:30:17 +09009 * This program is free software; you can redistribute it and/or modify it
10 * under the terms of the GNU General Public License as published by the
11 * Free Software Foundation; either version 2 of the License, or (at your
12 * option) any later version.
Inki Dae1c248b72011-10-04 19:19:01 +090013 */
14
David Howells760285e2012-10-02 18:01:07 +010015#include <drm/drmP.h>
16#include <drm/drm_crtc_helper.h>
Inki Dae1c248b72011-10-04 19:19:01 +090017
Mark Browne30655d2013-08-13 00:46:40 +010018#include "exynos_drm_crtc.h"
Inki Dae1c248b72011-10-04 19:19:01 +090019#include "exynos_drm_drv.h"
Inki Dae1c248b72011-10-04 19:19:01 +090020#include "exynos_drm_encoder.h"
Joonyoung Shimb5d2eb32012-06-27 14:27:04 +090021#include "exynos_drm_plane.h"
Inki Dae1c248b72011-10-04 19:19:01 +090022
Inki Dae1c248b72011-10-04 19:19:01 +090023static void exynos_drm_crtc_dpms(struct drm_crtc *crtc, int mode)
24{
Joonyoung Shimd2716c82011-11-04 17:04:45 +090025 struct exynos_drm_crtc *exynos_crtc = to_exynos_crtc(crtc);
Inki Dae1c248b72011-10-04 19:19:01 +090026
Joonyoung Shimd2716c82011-11-04 17:04:45 +090027 DRM_DEBUG_KMS("crtc[%d] mode[%d]\n", crtc->base.id, mode);
28
Inki Daeec05da92011-12-06 11:06:54 +090029 if (exynos_crtc->dpms == mode) {
30 DRM_DEBUG_KMS("desired dpms mode is same as previous one.\n");
31 return;
32 }
33
Inki Dae20cd2642013-05-21 16:55:58 +090034 if (mode > DRM_MODE_DPMS_ON) {
35 /* wait for the completion of page flip. */
YoungJun Choe35d7222014-07-17 18:01:17 +090036 if (!wait_event_timeout(exynos_crtc->pending_flip_queue,
37 !atomic_read(&exynos_crtc->pending_flip),
38 HZ/20))
39 atomic_set(&exynos_crtc->pending_flip, 0);
Andrzej Hajdad6948b22014-10-10 14:31:55 +020040 drm_crtc_vblank_off(crtc);
Inki Dae20cd2642013-05-21 16:55:58 +090041 }
42
Gustavo Padovan93bca242015-01-18 18:16:23 +090043 if (exynos_crtc->ops->dpms)
44 exynos_crtc->ops->dpms(exynos_crtc, mode);
Sean Paul080be03d2014-02-19 21:02:55 +090045
Joonyoung Shimcf5188a2012-06-27 14:27:09 +090046 exynos_crtc->dpms = mode;
Andrzej Hajdad6948b22014-10-10 14:31:55 +020047
48 if (mode == DRM_MODE_DPMS_ON)
49 drm_crtc_vblank_on(crtc);
Inki Dae1c248b72011-10-04 19:19:01 +090050}
51
52static void exynos_drm_crtc_prepare(struct drm_crtc *crtc)
53{
Inki Dae1c248b72011-10-04 19:19:01 +090054 /* drm framework doesn't check NULL. */
55}
56
57static void exynos_drm_crtc_commit(struct drm_crtc *crtc)
58{
Joonyoung Shimd2716c82011-11-04 17:04:45 +090059 struct exynos_drm_crtc *exynos_crtc = to_exynos_crtc(crtc);
Gustavo Padovan9d5310c2014-11-13 22:17:46 -020060 struct exynos_drm_plane *exynos_plane = to_exynos_plane(crtc->primary);
Joonyoung Shimd2716c82011-11-04 17:04:45 +090061
Inki Dae50caf252012-08-20 21:29:25 +090062 exynos_drm_crtc_dpms(crtc, DRM_MODE_DPMS_ON);
Sean Paul080be03d2014-02-19 21:02:55 +090063
Gustavo Padovan93bca242015-01-18 18:16:23 +090064 if (exynos_crtc->ops->win_commit)
65 exynos_crtc->ops->win_commit(exynos_crtc, exynos_plane->zpos);
Sean Paul080be03d2014-02-19 21:02:55 +090066
Gustavo Padovan93bca242015-01-18 18:16:23 +090067 if (exynos_crtc->ops->commit)
68 exynos_crtc->ops->commit(exynos_crtc);
Sean Paul080be03d2014-02-19 21:02:55 +090069
Andrzej Hajda72ed6cc2014-09-19 14:58:53 +020070 exynos_plane_dpms(crtc->primary, DRM_MODE_DPMS_ON);
Inki Dae1c248b72011-10-04 19:19:01 +090071}
72
73static bool
74exynos_drm_crtc_mode_fixup(struct drm_crtc *crtc,
Laurent Pincharte811f5a2012-07-17 17:56:50 +020075 const struct drm_display_mode *mode,
Inki Dae1c248b72011-10-04 19:19:01 +090076 struct drm_display_mode *adjusted_mode)
77{
Sean Paul4b405262014-01-30 16:19:19 -050078 struct exynos_drm_crtc *exynos_crtc = to_exynos_crtc(crtc);
Sean Paul4b405262014-01-30 16:19:19 -050079
Gustavo Padovan93bca242015-01-18 18:16:23 +090080 if (exynos_crtc->ops->mode_fixup)
81 return exynos_crtc->ops->mode_fixup(exynos_crtc, mode,
82 adjusted_mode);
Sean Paul4b405262014-01-30 16:19:19 -050083
Inki Dae1c248b72011-10-04 19:19:01 +090084 return true;
85}
86
87static int
88exynos_drm_crtc_mode_set(struct drm_crtc *crtc, struct drm_display_mode *mode,
89 struct drm_display_mode *adjusted_mode, int x, int y,
90 struct drm_framebuffer *old_fb)
91{
Andrzej Hajda72ed6cc2014-09-19 14:58:53 +020092 struct drm_framebuffer *fb = crtc->primary->fb;
Joonyoung Shim4070d212012-06-27 14:27:05 +090093 unsigned int crtc_w;
94 unsigned int crtc_h;
Joonyoung Shimaeb29222012-06-27 14:27:01 +090095
Inki Dae1de425b2012-03-16 18:47:04 +090096 /*
97 * copy the mode data adjusted by mode_fixup() into crtc->mode
98 * so that hardware can be seet to proper mode.
99 */
100 memcpy(&crtc->mode, adjusted_mode, sizeof(*adjusted_mode));
Inki Dae1c248b72011-10-04 19:19:01 +0900101
Andrzej Hajda72ed6cc2014-09-19 14:58:53 +0200102 crtc_w = fb->width - x;
103 crtc_h = fb->height - y;
Andrzej Hajda72ed6cc2014-09-19 14:58:53 +0200104 return exynos_plane_mode_set(crtc->primary, crtc, fb, 0, 0,
105 crtc_w, crtc_h, x, y, crtc_w, crtc_h);
Inki Dae1c248b72011-10-04 19:19:01 +0900106}
107
Gustavo Padovanfd092d72014-11-13 22:30:00 -0200108static int exynos_drm_crtc_mode_set_base(struct drm_crtc *crtc, int x, int y,
Inki Dae1c248b72011-10-04 19:19:01 +0900109 struct drm_framebuffer *old_fb)
110{
Joonyoung Shim4070d212012-06-27 14:27:05 +0900111 struct exynos_drm_crtc *exynos_crtc = to_exynos_crtc(crtc);
Andrzej Hajda72ed6cc2014-09-19 14:58:53 +0200112 struct drm_framebuffer *fb = crtc->primary->fb;
Joonyoung Shim4070d212012-06-27 14:27:05 +0900113 unsigned int crtc_w;
114 unsigned int crtc_h;
Inki Dae1c248b72011-10-04 19:19:01 +0900115
Inki Dae32aeab12012-09-14 13:29:47 +0900116 /* when framebuffer changing is requested, crtc's dpms should be on */
117 if (exynos_crtc->dpms > DRM_MODE_DPMS_ON) {
118 DRM_ERROR("failed framebuffer changing request.\n");
119 return -EPERM;
120 }
121
Andrzej Hajda72ed6cc2014-09-19 14:58:53 +0200122 crtc_w = fb->width - x;
123 crtc_h = fb->height - y;
Joonyoung Shim4070d212012-06-27 14:27:05 +0900124
Gustavo Padovan0e0a6492014-11-25 11:21:17 -0200125 return exynos_update_plane(crtc->primary, crtc, fb, 0, 0,
126 crtc_w, crtc_h, x, y, crtc_w, crtc_h);
Inki Dae1c248b72011-10-04 19:19:01 +0900127}
128
Joonyoung Shima365d9e2012-06-27 14:27:10 +0900129static void exynos_drm_crtc_disable(struct drm_crtc *crtc)
130{
Sean Paula9c4cd22014-01-30 16:19:17 -0500131 struct drm_plane *plane;
132 int ret;
Joonyoung Shima365d9e2012-06-27 14:27:10 +0900133
Joonyoung Shima365d9e2012-06-27 14:27:10 +0900134 exynos_drm_crtc_dpms(crtc, DRM_MODE_DPMS_OFF);
Sean Paula9c4cd22014-01-30 16:19:17 -0500135
Matt Roper08863272014-04-01 15:22:31 -0700136 drm_for_each_legacy_plane(plane, &crtc->dev->mode_config.plane_list) {
Sean Paula9c4cd22014-01-30 16:19:17 -0500137 if (plane->crtc != crtc)
138 continue;
139
140 ret = plane->funcs->disable_plane(plane);
141 if (ret)
142 DRM_ERROR("Failed to disable plane %d\n", ret);
143 }
Joonyoung Shima365d9e2012-06-27 14:27:10 +0900144}
145
Inki Dae1c248b72011-10-04 19:19:01 +0900146static struct drm_crtc_helper_funcs exynos_crtc_helper_funcs = {
147 .dpms = exynos_drm_crtc_dpms,
148 .prepare = exynos_drm_crtc_prepare,
149 .commit = exynos_drm_crtc_commit,
150 .mode_fixup = exynos_drm_crtc_mode_fixup,
151 .mode_set = exynos_drm_crtc_mode_set,
152 .mode_set_base = exynos_drm_crtc_mode_set_base,
Joonyoung Shima365d9e2012-06-27 14:27:10 +0900153 .disable = exynos_drm_crtc_disable,
Inki Dae1c248b72011-10-04 19:19:01 +0900154};
155
156static int exynos_drm_crtc_page_flip(struct drm_crtc *crtc,
Keith Packarded8d1972013-07-22 18:49:58 -0700157 struct drm_framebuffer *fb,
158 struct drm_pending_vblank_event *event,
159 uint32_t page_flip_flags)
Inki Dae1c248b72011-10-04 19:19:01 +0900160{
161 struct drm_device *dev = crtc->dev;
162 struct exynos_drm_private *dev_priv = dev->dev_private;
163 struct exynos_drm_crtc *exynos_crtc = to_exynos_crtc(crtc);
Matt Roperf4510a22014-04-01 15:22:40 -0700164 struct drm_framebuffer *old_fb = crtc->primary->fb;
Gustavo Padovan8b9c4502014-11-25 16:18:34 -0200165 unsigned int crtc_w, crtc_h;
Inki Dae1c248b72011-10-04 19:19:01 +0900166 int ret = -EINVAL;
167
Inki Daeef6223d2012-09-11 18:25:21 +0900168 /* when the page flip is requested, crtc's dpms should be on */
169 if (exynos_crtc->dpms > DRM_MODE_DPMS_ON) {
170 DRM_ERROR("failed page flip request.\n");
171 return -EINVAL;
172 }
173
Inki Dae1c248b72011-10-04 19:19:01 +0900174 mutex_lock(&dev->struct_mutex);
175
Inki Daeccf4d882011-10-14 13:29:51 +0900176 if (event) {
177 /*
178 * the pipe from user always is 0 so we can set pipe number
179 * of current owner to event.
180 */
181 event->pipe = exynos_crtc->pipe;
182
Inki Dae1c248b72011-10-04 19:19:01 +0900183 ret = drm_vblank_get(dev, exynos_crtc->pipe);
184 if (ret) {
185 DRM_DEBUG("failed to acquire vblank counter\n");
Inki Daeccf4d882011-10-14 13:29:51 +0900186
Inki Dae1c248b72011-10-04 19:19:01 +0900187 goto out;
188 }
189
Imre Deak85473322012-11-02 13:30:47 +0200190 spin_lock_irq(&dev->event_lock);
Inki Daec5614ae2012-02-15 11:25:20 +0900191 list_add_tail(&event->base.link,
192 &dev_priv->pageflip_event_list);
Inki Dae20cd2642013-05-21 16:55:58 +0900193 atomic_set(&exynos_crtc->pending_flip, 1);
Imre Deak85473322012-11-02 13:30:47 +0200194 spin_unlock_irq(&dev->event_lock);
Inki Daec5614ae2012-02-15 11:25:20 +0900195
Matt Roperf4510a22014-04-01 15:22:40 -0700196 crtc->primary->fb = fb;
Gustavo Padovan8b9c4502014-11-25 16:18:34 -0200197 crtc_w = fb->width - crtc->x;
198 crtc_h = fb->height - crtc->y;
199 ret = exynos_update_plane(crtc->primary, crtc, fb, 0, 0,
200 crtc_w, crtc_h, crtc->x, crtc->y,
201 crtc_w, crtc_h);
Inki Dae1c248b72011-10-04 19:19:01 +0900202 if (ret) {
Matt Roperf4510a22014-04-01 15:22:40 -0700203 crtc->primary->fb = old_fb;
Imre Deak85473322012-11-02 13:30:47 +0200204
205 spin_lock_irq(&dev->event_lock);
Inki Dae1c248b72011-10-04 19:19:01 +0900206 drm_vblank_put(dev, exynos_crtc->pipe);
Inki Daeccf4d882011-10-14 13:29:51 +0900207 list_del(&event->base.link);
YoungJun Choe35d7222014-07-17 18:01:17 +0900208 atomic_set(&exynos_crtc->pending_flip, 0);
Imre Deak85473322012-11-02 13:30:47 +0200209 spin_unlock_irq(&dev->event_lock);
Inki Dae1c248b72011-10-04 19:19:01 +0900210
211 goto out;
212 }
Inki Dae1c248b72011-10-04 19:19:01 +0900213 }
214out:
215 mutex_unlock(&dev->struct_mutex);
216 return ret;
217}
218
219static void exynos_drm_crtc_destroy(struct drm_crtc *crtc)
220{
221 struct exynos_drm_crtc *exynos_crtc = to_exynos_crtc(crtc);
222 struct exynos_drm_private *private = crtc->dev->dev_private;
223
Inki Dae1c248b72011-10-04 19:19:01 +0900224 private->crtc[exynos_crtc->pipe] = NULL;
225
226 drm_crtc_cleanup(crtc);
227 kfree(exynos_crtc);
228}
229
Joonyoung Shim3b8d1cf2012-06-27 14:27:11 +0900230static int exynos_drm_crtc_set_property(struct drm_crtc *crtc,
231 struct drm_property *property,
232 uint64_t val)
233{
234 struct drm_device *dev = crtc->dev;
235 struct exynos_drm_private *dev_priv = dev->dev_private;
236 struct exynos_drm_crtc *exynos_crtc = to_exynos_crtc(crtc);
237
Joonyoung Shim3b8d1cf2012-06-27 14:27:11 +0900238 if (property == dev_priv->crtc_mode_property) {
239 enum exynos_crtc_mode mode = val;
240
241 if (mode == exynos_crtc->mode)
242 return 0;
243
244 exynos_crtc->mode = mode;
245
246 switch (mode) {
247 case CRTC_MODE_NORMAL:
248 exynos_drm_crtc_commit(crtc);
249 break;
250 case CRTC_MODE_BLANK:
Andrzej Hajda72ed6cc2014-09-19 14:58:53 +0200251 exynos_plane_dpms(crtc->primary, DRM_MODE_DPMS_OFF);
Joonyoung Shim3b8d1cf2012-06-27 14:27:11 +0900252 break;
253 default:
254 break;
255 }
256
257 return 0;
258 }
259
260 return -EINVAL;
261}
262
Inki Dae1c248b72011-10-04 19:19:01 +0900263static struct drm_crtc_funcs exynos_crtc_funcs = {
264 .set_config = drm_crtc_helper_set_config,
265 .page_flip = exynos_drm_crtc_page_flip,
266 .destroy = exynos_drm_crtc_destroy,
Joonyoung Shim3b8d1cf2012-06-27 14:27:11 +0900267 .set_property = exynos_drm_crtc_set_property,
Inki Dae1c248b72011-10-04 19:19:01 +0900268};
269
Joonyoung Shim3b8d1cf2012-06-27 14:27:11 +0900270static const struct drm_prop_enum_list mode_names[] = {
271 { CRTC_MODE_NORMAL, "normal" },
272 { CRTC_MODE_BLANK, "blank" },
273};
274
275static void exynos_drm_crtc_attach_mode_property(struct drm_crtc *crtc)
276{
277 struct drm_device *dev = crtc->dev;
278 struct exynos_drm_private *dev_priv = dev->dev_private;
279 struct drm_property *prop;
280
Joonyoung Shim3b8d1cf2012-06-27 14:27:11 +0900281 prop = dev_priv->crtc_mode_property;
282 if (!prop) {
283 prop = drm_property_create_enum(dev, 0, "mode", mode_names,
284 ARRAY_SIZE(mode_names));
285 if (!prop)
286 return;
287
288 dev_priv->crtc_mode_property = prop;
289 }
290
291 drm_object_attach_property(&crtc->base, prop, 0);
292}
293
Gustavo Padovan93bca242015-01-18 18:16:23 +0900294struct exynos_drm_crtc *exynos_drm_crtc_create(struct drm_device *drm_dev,
295 int pipe,
296 enum exynos_drm_output_type type,
297 struct exynos_drm_crtc_ops *ops,
298 void *ctx)
Inki Dae1c248b72011-10-04 19:19:01 +0900299{
300 struct exynos_drm_crtc *exynos_crtc;
Andrzej Hajda72ed6cc2014-09-19 14:58:53 +0200301 struct drm_plane *plane;
Gustavo Padovaneb88e422014-11-26 16:43:27 -0200302 struct exynos_drm_private *private = drm_dev->dev_private;
Inki Dae1c248b72011-10-04 19:19:01 +0900303 struct drm_crtc *crtc;
Andrzej Hajda72ed6cc2014-09-19 14:58:53 +0200304 int ret;
Inki Dae1c248b72011-10-04 19:19:01 +0900305
Inki Dae1c248b72011-10-04 19:19:01 +0900306 exynos_crtc = kzalloc(sizeof(*exynos_crtc), GFP_KERNEL);
Sachin Kamat38bb5252013-08-19 19:04:55 +0900307 if (!exynos_crtc)
Gustavo Padovan93bca242015-01-18 18:16:23 +0900308 return ERR_PTR(-ENOMEM);
Inki Dae1c248b72011-10-04 19:19:01 +0900309
Inki Dae20cd2642013-05-21 16:55:58 +0900310 init_waitqueue_head(&exynos_crtc->pending_flip_queue);
311 atomic_set(&exynos_crtc->pending_flip, 0);
Sean Paul080be03d2014-02-19 21:02:55 +0900312
313 exynos_crtc->dpms = DRM_MODE_DPMS_OFF;
Gustavo Padovane09f2b02014-11-04 18:25:27 -0200314 exynos_crtc->pipe = pipe;
Gustavo Padovan5d1741a2014-11-05 19:51:35 -0200315 exynos_crtc->type = type;
Gustavo Padovan93bca242015-01-18 18:16:23 +0900316 exynos_crtc->ops = ops;
317 exynos_crtc->ctx = ctx;
Gustavo Padovaneb88e422014-11-26 16:43:27 -0200318 plane = exynos_plane_init(drm_dev, 1 << pipe,
Andrzej Hajda72ed6cc2014-09-19 14:58:53 +0200319 DRM_PLANE_TYPE_PRIMARY);
320 if (IS_ERR(plane)) {
321 ret = PTR_ERR(plane);
322 goto err_plane;
Joonyoung Shimb5d2eb32012-06-27 14:27:04 +0900323 }
324
Gustavo Padovan357193c2014-11-03 18:20:29 -0200325 crtc = &exynos_crtc->base;
Inki Dae1c248b72011-10-04 19:19:01 +0900326
Gustavo Padovane09f2b02014-11-04 18:25:27 -0200327 private->crtc[pipe] = crtc;
Inki Dae1c248b72011-10-04 19:19:01 +0900328
Gustavo Padovaneb88e422014-11-26 16:43:27 -0200329 ret = drm_crtc_init_with_planes(drm_dev, crtc, plane, NULL,
Andrzej Hajda72ed6cc2014-09-19 14:58:53 +0200330 &exynos_crtc_funcs);
331 if (ret < 0)
332 goto err_crtc;
333
Inki Dae1c248b72011-10-04 19:19:01 +0900334 drm_crtc_helper_add(crtc, &exynos_crtc_helper_funcs);
335
Joonyoung Shim3b8d1cf2012-06-27 14:27:11 +0900336 exynos_drm_crtc_attach_mode_property(crtc);
337
Gustavo Padovan93bca242015-01-18 18:16:23 +0900338 return exynos_crtc;
Andrzej Hajda72ed6cc2014-09-19 14:58:53 +0200339
340err_crtc:
341 plane->funcs->destroy(plane);
342err_plane:
343 kfree(exynos_crtc);
Gustavo Padovan93bca242015-01-18 18:16:23 +0900344 return ERR_PTR(ret);
Inki Dae1c248b72011-10-04 19:19:01 +0900345}
346
Sean Paul080be03d2014-02-19 21:02:55 +0900347int exynos_drm_crtc_enable_vblank(struct drm_device *dev, int pipe)
Inki Dae1c248b72011-10-04 19:19:01 +0900348{
349 struct exynos_drm_private *private = dev->dev_private;
Inki Daeec05da92011-12-06 11:06:54 +0900350 struct exynos_drm_crtc *exynos_crtc =
Sean Paul080be03d2014-02-19 21:02:55 +0900351 to_exynos_crtc(private->crtc[pipe]);
Inki Dae1c248b72011-10-04 19:19:01 +0900352
Inki Daeec05da92011-12-06 11:06:54 +0900353 if (exynos_crtc->dpms != DRM_MODE_DPMS_ON)
354 return -EPERM;
355
Gustavo Padovan93bca242015-01-18 18:16:23 +0900356 if (exynos_crtc->ops->enable_vblank)
357 exynos_crtc->ops->enable_vblank(exynos_crtc);
Inki Dae1c248b72011-10-04 19:19:01 +0900358
359 return 0;
360}
361
Sean Paul080be03d2014-02-19 21:02:55 +0900362void exynos_drm_crtc_disable_vblank(struct drm_device *dev, int pipe)
Inki Dae1c248b72011-10-04 19:19:01 +0900363{
364 struct exynos_drm_private *private = dev->dev_private;
Inki Daeec05da92011-12-06 11:06:54 +0900365 struct exynos_drm_crtc *exynos_crtc =
Sean Paul080be03d2014-02-19 21:02:55 +0900366 to_exynos_crtc(private->crtc[pipe]);
Inki Dae1c248b72011-10-04 19:19:01 +0900367
Inki Daeec05da92011-12-06 11:06:54 +0900368 if (exynos_crtc->dpms != DRM_MODE_DPMS_ON)
369 return;
370
Gustavo Padovan93bca242015-01-18 18:16:23 +0900371 if (exynos_crtc->ops->disable_vblank)
372 exynos_crtc->ops->disable_vblank(exynos_crtc);
Inki Dae1c248b72011-10-04 19:19:01 +0900373}
Rahul Sharma663d8762013-01-03 05:44:04 -0500374
Sean Paul080be03d2014-02-19 21:02:55 +0900375void exynos_drm_crtc_finish_pageflip(struct drm_device *dev, int pipe)
Rahul Sharma663d8762013-01-03 05:44:04 -0500376{
377 struct exynos_drm_private *dev_priv = dev->dev_private;
378 struct drm_pending_vblank_event *e, *t;
Sean Paul080be03d2014-02-19 21:02:55 +0900379 struct drm_crtc *drm_crtc = dev_priv->crtc[pipe];
Inki Dae20cd2642013-05-21 16:55:58 +0900380 struct exynos_drm_crtc *exynos_crtc = to_exynos_crtc(drm_crtc);
Rahul Sharma663d8762013-01-03 05:44:04 -0500381 unsigned long flags;
382
Rahul Sharma663d8762013-01-03 05:44:04 -0500383 spin_lock_irqsave(&dev->event_lock, flags);
384
385 list_for_each_entry_safe(e, t, &dev_priv->pageflip_event_list,
386 base.link) {
387 /* if event's pipe isn't same as crtc then ignore it. */
Sean Paul080be03d2014-02-19 21:02:55 +0900388 if (pipe != e->pipe)
Rahul Sharma663d8762013-01-03 05:44:04 -0500389 continue;
390
Rob Clarkc5cca972013-05-22 11:48:40 +0900391 list_del(&e->base.link);
392 drm_send_vblank_event(dev, -1, e);
Sean Paul080be03d2014-02-19 21:02:55 +0900393 drm_vblank_put(dev, pipe);
Inki Dae20cd2642013-05-21 16:55:58 +0900394 atomic_set(&exynos_crtc->pending_flip, 0);
395 wake_up(&exynos_crtc->pending_flip_queue);
Rahul Sharma663d8762013-01-03 05:44:04 -0500396 }
397
398 spin_unlock_irqrestore(&dev->event_lock, flags);
399}
Sean Paul080be03d2014-02-19 21:02:55 +0900400
Sean Paul080be03d2014-02-19 21:02:55 +0900401void exynos_drm_crtc_complete_scanout(struct drm_framebuffer *fb)
402{
Gustavo Padovan93bca242015-01-18 18:16:23 +0900403 struct exynos_drm_crtc *exynos_crtc;
Sean Paul080be03d2014-02-19 21:02:55 +0900404 struct drm_device *dev = fb->dev;
405 struct drm_crtc *crtc;
406
407 /*
408 * make sure that overlay data are updated to real hardware
409 * for all encoders.
410 */
411 list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) {
Gustavo Padovan93bca242015-01-18 18:16:23 +0900412 exynos_crtc = to_exynos_crtc(crtc);
Sean Paul080be03d2014-02-19 21:02:55 +0900413
414 /*
415 * wait for vblank interrupt
416 * - this makes sure that overlay data are updated to
417 * real hardware.
418 */
Gustavo Padovan93bca242015-01-18 18:16:23 +0900419 if (exynos_crtc->ops->wait_for_vblank)
420 exynos_crtc->ops->wait_for_vblank(exynos_crtc);
Sean Paul080be03d2014-02-19 21:02:55 +0900421 }
422}
Inki Daef37cd5e2014-05-09 14:25:20 +0900423
424int exynos_drm_crtc_get_pipe_from_type(struct drm_device *drm_dev,
425 unsigned int out_type)
426{
427 struct drm_crtc *crtc;
428
429 list_for_each_entry(crtc, &drm_dev->mode_config.crtc_list, head) {
430 struct exynos_drm_crtc *exynos_crtc;
431
432 exynos_crtc = to_exynos_crtc(crtc);
Gustavo Padovan5d1741a2014-11-05 19:51:35 -0200433 if (exynos_crtc->type == out_type)
Gustavo Padovan8a326ed2014-11-04 18:44:47 -0200434 return exynos_crtc->pipe;
Inki Daef37cd5e2014-05-09 14:25:20 +0900435 }
436
437 return -EPERM;
438}
YoungJun Cho5595d4d2014-07-17 18:01:19 +0900439
440void exynos_drm_crtc_te_handler(struct drm_crtc *crtc)
441{
Gustavo Padovan93bca242015-01-18 18:16:23 +0900442 struct exynos_drm_crtc *exynos_crtc = to_exynos_crtc(crtc);
YoungJun Cho5595d4d2014-07-17 18:01:19 +0900443
Gustavo Padovan93bca242015-01-18 18:16:23 +0900444 if (exynos_crtc->ops->te_handler)
445 exynos_crtc->ops->te_handler(exynos_crtc);
YoungJun Cho5595d4d2014-07-17 18:01:19 +0900446}