aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/gpu/drm/exynos
diff options
context:
space:
mode:
authorDave Airlie <airlied@redhat.com>2015-01-26 18:38:29 -0500
committerDave Airlie <airlied@redhat.com>2015-01-26 18:38:29 -0500
commit923e0575a94589d56c0d6b65bd4af599b7422bcc (patch)
tree4332625078941e5ba360eecf586fa0c3ad0a83ec /drivers/gpu/drm/exynos
parentf43dff0ee00a259f524ce17ba4f8030553c66590 (diff)
parentefa75bcdad59fc796152a4c73bb65ae2ab7ce035 (diff)
Merge branch 'exynos-drm-next' of git://git.kernel.org/pub/scm/linux/kernel/git/daeinki/drm-exynos into drm-next
This pull request includes some code refactoring which removes Exynos specific structure names and uses generic structure names instead, and makes all plane updating to be done by only exynos_update_plane function. And also it includes some cleanup and fixup patches. * 'exynos-drm-next' of git://git.kernel.org/pub/scm/linux/kernel/git/daeinki/drm-exynos: (22 commits) drm/exynos: fimd: check error status for drm_iommu_attach_device drm/exynos: create exynos_check_plane() drm/exynos: remove mode_set() ops from exynos_crtc drm/exynos: don't duplicate drm_display_mode in fimd context drm/exynos: remove struct exynos_drm_manager drm/exynos: remove drm_dev from struct exynos_drm_manager drm/exynos: move 'type' from manager to crtc struct drm/exynos: remove pipe member of struct exynos_drm_manager drm/exynos: add pipe param to exynos_drm_crtc_create() drm/exynos: rename base object of struct exynos_drm_crtc to 'base' drm/exynos: remove exynos_drm_crtc_mode_set_commit() drm/exynos: call exynos_update_plane() directly on page flips drm/exynos: unify plane update on exynos_update_plane() drm/exynos: remove exynos_plane_commit() wrapper drm/exynos: don't do any DPMS operation while updating planes drm/exynos: Don't touch DPMS when updating overlay planes drm/exynos/vidi: remove useless ops->commit() drm/exynos/fimd: don't initialize 'ret' variable in fimd_probe() drm/exynos: remove struct exynos_drm_overlay drm/exynos: remove exynos_drm_crtc_plane_* wrappers ...
Diffstat (limited to 'drivers/gpu/drm/exynos')
-rw-r--r--drivers/gpu/drm/exynos/exynos_drm_crtc.c185
-rw-r--r--drivers/gpu/drm/exynos/exynos_drm_crtc.h8
-rw-r--r--drivers/gpu/drm/exynos/exynos_drm_drv.h83
-rw-r--r--drivers/gpu/drm/exynos/exynos_drm_fimd.c196
-rw-r--r--drivers/gpu/drm/exynos/exynos_drm_plane.c138
-rw-r--r--drivers/gpu/drm/exynos/exynos_drm_plane.h17
-rw-r--r--drivers/gpu/drm/exynos/exynos_drm_vidi.c135
-rw-r--r--drivers/gpu/drm/exynos/exynos_mixer.c159
8 files changed, 426 insertions, 495 deletions
diff --git a/drivers/gpu/drm/exynos/exynos_drm_crtc.c b/drivers/gpu/drm/exynos/exynos_drm_crtc.c
index 45026e693225..a85c451ba392 100644
--- a/drivers/gpu/drm/exynos/exynos_drm_crtc.c
+++ b/drivers/gpu/drm/exynos/exynos_drm_crtc.c
@@ -20,43 +20,9 @@
20#include "exynos_drm_encoder.h" 20#include "exynos_drm_encoder.h"
21#include "exynos_drm_plane.h" 21#include "exynos_drm_plane.h"
22 22
23#define to_exynos_crtc(x) container_of(x, struct exynos_drm_crtc,\
24 drm_crtc)
25
26enum exynos_crtc_mode {
27 CRTC_MODE_NORMAL, /* normal mode */
28 CRTC_MODE_BLANK, /* The private plane of crtc is blank */
29};
30
31/*
32 * Exynos specific crtc structure.
33 *
34 * @drm_crtc: crtc object.
35 * @manager: the manager associated with this crtc
36 * @pipe: a crtc index created at load() with a new crtc object creation
37 * and the crtc object would be set to private->crtc array
38 * to get a crtc object corresponding to this pipe from private->crtc
39 * array when irq interrupt occurred. the reason of using this pipe is that
40 * drm framework doesn't support multiple irq yet.
41 * we can refer to the crtc to current hardware interrupt occurred through
42 * this pipe value.
43 * @dpms: store the crtc dpms value
44 * @mode: store the crtc mode value
45 */
46struct exynos_drm_crtc {
47 struct drm_crtc drm_crtc;
48 struct exynos_drm_manager *manager;
49 unsigned int pipe;
50 unsigned int dpms;
51 enum exynos_crtc_mode mode;
52 wait_queue_head_t pending_flip_queue;
53 atomic_t pending_flip;
54};
55
56static void exynos_drm_crtc_dpms(struct drm_crtc *crtc, int mode) 23static void exynos_drm_crtc_dpms(struct drm_crtc *crtc, int mode)
57{ 24{
58 struct exynos_drm_crtc *exynos_crtc = to_exynos_crtc(crtc); 25 struct exynos_drm_crtc *exynos_crtc = to_exynos_crtc(crtc);
59 struct exynos_drm_manager *manager = exynos_crtc->manager;
60 26
61 DRM_DEBUG_KMS("crtc[%d] mode[%d]\n", crtc->base.id, mode); 27 DRM_DEBUG_KMS("crtc[%d] mode[%d]\n", crtc->base.id, mode);
62 28
@@ -74,8 +40,8 @@ static void exynos_drm_crtc_dpms(struct drm_crtc *crtc, int mode)
74 drm_crtc_vblank_off(crtc); 40 drm_crtc_vblank_off(crtc);
75 } 41 }
76 42
77 if (manager->ops->dpms) 43 if (exynos_crtc->ops->dpms)
78 manager->ops->dpms(manager, mode); 44 exynos_crtc->ops->dpms(exynos_crtc, mode);
79 45
80 exynos_crtc->dpms = mode; 46 exynos_crtc->dpms = mode;
81 47
@@ -91,14 +57,15 @@ static void exynos_drm_crtc_prepare(struct drm_crtc *crtc)
91static void exynos_drm_crtc_commit(struct drm_crtc *crtc) 57static void exynos_drm_crtc_commit(struct drm_crtc *crtc)
92{ 58{
93 struct exynos_drm_crtc *exynos_crtc = to_exynos_crtc(crtc); 59 struct exynos_drm_crtc *exynos_crtc = to_exynos_crtc(crtc);
94 struct exynos_drm_manager *manager = exynos_crtc->manager; 60 struct exynos_drm_plane *exynos_plane = to_exynos_plane(crtc->primary);
95 61
96 exynos_drm_crtc_dpms(crtc, DRM_MODE_DPMS_ON); 62 exynos_drm_crtc_dpms(crtc, DRM_MODE_DPMS_ON);
97 63
98 exynos_plane_commit(crtc->primary); 64 if (exynos_crtc->ops->win_commit)
65 exynos_crtc->ops->win_commit(exynos_crtc, exynos_plane->zpos);
99 66
100 if (manager->ops->commit) 67 if (exynos_crtc->ops->commit)
101 manager->ops->commit(manager); 68 exynos_crtc->ops->commit(exynos_crtc);
102 69
103 exynos_plane_dpms(crtc->primary, DRM_MODE_DPMS_ON); 70 exynos_plane_dpms(crtc->primary, DRM_MODE_DPMS_ON);
104} 71}
@@ -109,10 +76,10 @@ exynos_drm_crtc_mode_fixup(struct drm_crtc *crtc,
109 struct drm_display_mode *adjusted_mode) 76 struct drm_display_mode *adjusted_mode)
110{ 77{
111 struct exynos_drm_crtc *exynos_crtc = to_exynos_crtc(crtc); 78 struct exynos_drm_crtc *exynos_crtc = to_exynos_crtc(crtc);
112 struct exynos_drm_manager *manager = exynos_crtc->manager;
113 79
114 if (manager->ops->mode_fixup) 80 if (exynos_crtc->ops->mode_fixup)
115 return manager->ops->mode_fixup(manager, mode, adjusted_mode); 81 return exynos_crtc->ops->mode_fixup(exynos_crtc, mode,
82 adjusted_mode);
116 83
117 return true; 84 return true;
118} 85}
@@ -122,11 +89,10 @@ exynos_drm_crtc_mode_set(struct drm_crtc *crtc, struct drm_display_mode *mode,
122 struct drm_display_mode *adjusted_mode, int x, int y, 89 struct drm_display_mode *adjusted_mode, int x, int y,
123 struct drm_framebuffer *old_fb) 90 struct drm_framebuffer *old_fb)
124{ 91{
125 struct exynos_drm_crtc *exynos_crtc = to_exynos_crtc(crtc);
126 struct exynos_drm_manager *manager = exynos_crtc->manager;
127 struct drm_framebuffer *fb = crtc->primary->fb; 92 struct drm_framebuffer *fb = crtc->primary->fb;
128 unsigned int crtc_w; 93 unsigned int crtc_w;
129 unsigned int crtc_h; 94 unsigned int crtc_h;
95 int ret;
130 96
131 /* 97 /*
132 * copy the mode data adjusted by mode_fixup() into crtc->mode 98 * copy the mode data adjusted by mode_fixup() into crtc->mode
@@ -134,24 +100,25 @@ exynos_drm_crtc_mode_set(struct drm_crtc *crtc, struct drm_display_mode *mode,
134 */ 100 */
135 memcpy(&crtc->mode, adjusted_mode, sizeof(*adjusted_mode)); 101 memcpy(&crtc->mode, adjusted_mode, sizeof(*adjusted_mode));
136 102
103 ret = exynos_check_plane(crtc->primary, fb);
104 if (ret < 0)
105 return ret;
106
137 crtc_w = fb->width - x; 107 crtc_w = fb->width - x;
138 crtc_h = fb->height - y; 108 crtc_h = fb->height - y;
109 exynos_plane_mode_set(crtc->primary, crtc, fb, 0, 0,
110 crtc_w, crtc_h, x, y, crtc_w, crtc_h);
139 111
140 if (manager->ops->mode_set) 112 return 0;
141 manager->ops->mode_set(manager, &crtc->mode);
142
143 return exynos_plane_mode_set(crtc->primary, crtc, fb, 0, 0,
144 crtc_w, crtc_h, x, y, crtc_w, crtc_h);
145} 113}
146 114
147static int exynos_drm_crtc_mode_set_commit(struct drm_crtc *crtc, int x, int y, 115static int exynos_drm_crtc_mode_set_base(struct drm_crtc *crtc, int x, int y,
148 struct drm_framebuffer *old_fb) 116 struct drm_framebuffer *old_fb)
149{ 117{
150 struct exynos_drm_crtc *exynos_crtc = to_exynos_crtc(crtc); 118 struct exynos_drm_crtc *exynos_crtc = to_exynos_crtc(crtc);
151 struct drm_framebuffer *fb = crtc->primary->fb; 119 struct drm_framebuffer *fb = crtc->primary->fb;
152 unsigned int crtc_w; 120 unsigned int crtc_w;
153 unsigned int crtc_h; 121 unsigned int crtc_h;
154 int ret;
155 122
156 /* when framebuffer changing is requested, crtc's dpms should be on */ 123 /* when framebuffer changing is requested, crtc's dpms should be on */
157 if (exynos_crtc->dpms > DRM_MODE_DPMS_ON) { 124 if (exynos_crtc->dpms > DRM_MODE_DPMS_ON) {
@@ -162,20 +129,8 @@ static int exynos_drm_crtc_mode_set_commit(struct drm_crtc *crtc, int x, int y,
162 crtc_w = fb->width - x; 129 crtc_w = fb->width - x;
163 crtc_h = fb->height - y; 130 crtc_h = fb->height - y;
164 131
165 ret = exynos_plane_mode_set(crtc->primary, crtc, fb, 0, 0, 132 return exynos_update_plane(crtc->primary, crtc, fb, 0, 0,
166 crtc_w, crtc_h, x, y, crtc_w, crtc_h); 133 crtc_w, crtc_h, x, y, crtc_w, crtc_h);
167 if (ret)
168 return ret;
169
170 exynos_drm_crtc_commit(crtc);
171
172 return 0;
173}
174
175static int exynos_drm_crtc_mode_set_base(struct drm_crtc *crtc, int x, int y,
176 struct drm_framebuffer *old_fb)
177{
178 return exynos_drm_crtc_mode_set_commit(crtc, x, y, old_fb);
179} 134}
180 135
181static void exynos_drm_crtc_disable(struct drm_crtc *crtc) 136static void exynos_drm_crtc_disable(struct drm_crtc *crtc)
@@ -214,6 +169,7 @@ static int exynos_drm_crtc_page_flip(struct drm_crtc *crtc,
214 struct exynos_drm_private *dev_priv = dev->dev_private; 169 struct exynos_drm_private *dev_priv = dev->dev_private;
215 struct exynos_drm_crtc *exynos_crtc = to_exynos_crtc(crtc); 170 struct exynos_drm_crtc *exynos_crtc = to_exynos_crtc(crtc);
216 struct drm_framebuffer *old_fb = crtc->primary->fb; 171 struct drm_framebuffer *old_fb = crtc->primary->fb;
172 unsigned int crtc_w, crtc_h;
217 int ret = -EINVAL; 173 int ret = -EINVAL;
218 174
219 /* when the page flip is requested, crtc's dpms should be on */ 175 /* when the page flip is requested, crtc's dpms should be on */
@@ -245,8 +201,11 @@ static int exynos_drm_crtc_page_flip(struct drm_crtc *crtc,
245 spin_unlock_irq(&dev->event_lock); 201 spin_unlock_irq(&dev->event_lock);
246 202
247 crtc->primary->fb = fb; 203 crtc->primary->fb = fb;
248 ret = exynos_drm_crtc_mode_set_commit(crtc, crtc->x, crtc->y, 204 crtc_w = fb->width - crtc->x;
249 NULL); 205 crtc_h = fb->height - crtc->y;
206 ret = exynos_update_plane(crtc->primary, crtc, fb, 0, 0,
207 crtc_w, crtc_h, crtc->x, crtc->y,
208 crtc_w, crtc_h);
250 if (ret) { 209 if (ret) {
251 crtc->primary->fb = old_fb; 210 crtc->primary->fb = old_fb;
252 211
@@ -339,37 +298,42 @@ static void exynos_drm_crtc_attach_mode_property(struct drm_crtc *crtc)
339 drm_object_attach_property(&crtc->base, prop, 0); 298 drm_object_attach_property(&crtc->base, prop, 0);
340} 299}
341 300
342int exynos_drm_crtc_create(struct exynos_drm_manager *manager) 301struct exynos_drm_crtc *exynos_drm_crtc_create(struct drm_device *drm_dev,
302 int pipe,
303 enum exynos_drm_output_type type,
304 struct exynos_drm_crtc_ops *ops,
305 void *ctx)
343{ 306{
344 struct exynos_drm_crtc *exynos_crtc; 307 struct exynos_drm_crtc *exynos_crtc;
345 struct drm_plane *plane; 308 struct drm_plane *plane;
346 struct exynos_drm_private *private = manager->drm_dev->dev_private; 309 struct exynos_drm_private *private = drm_dev->dev_private;
347 struct drm_crtc *crtc; 310 struct drm_crtc *crtc;
348 int ret; 311 int ret;
349 312
350 exynos_crtc = kzalloc(sizeof(*exynos_crtc), GFP_KERNEL); 313 exynos_crtc = kzalloc(sizeof(*exynos_crtc), GFP_KERNEL);
351 if (!exynos_crtc) 314 if (!exynos_crtc)
352 return -ENOMEM; 315 return ERR_PTR(-ENOMEM);
353 316
354 init_waitqueue_head(&exynos_crtc->pending_flip_queue); 317 init_waitqueue_head(&exynos_crtc->pending_flip_queue);
355 atomic_set(&exynos_crtc->pending_flip, 0); 318 atomic_set(&exynos_crtc->pending_flip, 0);
356 319
357 exynos_crtc->dpms = DRM_MODE_DPMS_OFF; 320 exynos_crtc->dpms = DRM_MODE_DPMS_OFF;
358 exynos_crtc->manager = manager; 321 exynos_crtc->pipe = pipe;
359 exynos_crtc->pipe = manager->pipe; 322 exynos_crtc->type = type;
360 plane = exynos_plane_init(manager->drm_dev, 1 << manager->pipe, 323 exynos_crtc->ops = ops;
324 exynos_crtc->ctx = ctx;
325 plane = exynos_plane_init(drm_dev, 1 << pipe,
361 DRM_PLANE_TYPE_PRIMARY); 326 DRM_PLANE_TYPE_PRIMARY);
362 if (IS_ERR(plane)) { 327 if (IS_ERR(plane)) {
363 ret = PTR_ERR(plane); 328 ret = PTR_ERR(plane);
364 goto err_plane; 329 goto err_plane;
365 } 330 }
366 331
367 manager->crtc = &exynos_crtc->drm_crtc; 332 crtc = &exynos_crtc->base;
368 crtc = &exynos_crtc->drm_crtc;
369 333
370 private->crtc[manager->pipe] = crtc; 334 private->crtc[pipe] = crtc;
371 335
372 ret = drm_crtc_init_with_planes(manager->drm_dev, crtc, plane, NULL, 336 ret = drm_crtc_init_with_planes(drm_dev, crtc, plane, NULL,
373 &exynos_crtc_funcs); 337 &exynos_crtc_funcs);
374 if (ret < 0) 338 if (ret < 0)
375 goto err_crtc; 339 goto err_crtc;
@@ -378,13 +342,13 @@ int exynos_drm_crtc_create(struct exynos_drm_manager *manager)
378 342
379 exynos_drm_crtc_attach_mode_property(crtc); 343 exynos_drm_crtc_attach_mode_property(crtc);
380 344
381 return 0; 345 return exynos_crtc;
382 346
383err_crtc: 347err_crtc:
384 plane->funcs->destroy(plane); 348 plane->funcs->destroy(plane);
385err_plane: 349err_plane:
386 kfree(exynos_crtc); 350 kfree(exynos_crtc);
387 return ret; 351 return ERR_PTR(ret);
388} 352}
389 353
390int exynos_drm_crtc_enable_vblank(struct drm_device *dev, int pipe) 354int exynos_drm_crtc_enable_vblank(struct drm_device *dev, int pipe)
@@ -392,13 +356,12 @@ int exynos_drm_crtc_enable_vblank(struct drm_device *dev, int pipe)
392 struct exynos_drm_private *private = dev->dev_private; 356 struct exynos_drm_private *private = dev->dev_private;
393 struct exynos_drm_crtc *exynos_crtc = 357 struct exynos_drm_crtc *exynos_crtc =
394 to_exynos_crtc(private->crtc[pipe]); 358 to_exynos_crtc(private->crtc[pipe]);
395 struct exynos_drm_manager *manager = exynos_crtc->manager;
396 359
397 if (exynos_crtc->dpms != DRM_MODE_DPMS_ON) 360 if (exynos_crtc->dpms != DRM_MODE_DPMS_ON)
398 return -EPERM; 361 return -EPERM;
399 362
400 if (manager->ops->enable_vblank) 363 if (exynos_crtc->ops->enable_vblank)
401 manager->ops->enable_vblank(manager); 364 exynos_crtc->ops->enable_vblank(exynos_crtc);
402 365
403 return 0; 366 return 0;
404} 367}
@@ -408,13 +371,12 @@ void exynos_drm_crtc_disable_vblank(struct drm_device *dev, int pipe)
408 struct exynos_drm_private *private = dev->dev_private; 371 struct exynos_drm_private *private = dev->dev_private;
409 struct exynos_drm_crtc *exynos_crtc = 372 struct exynos_drm_crtc *exynos_crtc =
410 to_exynos_crtc(private->crtc[pipe]); 373 to_exynos_crtc(private->crtc[pipe]);
411 struct exynos_drm_manager *manager = exynos_crtc->manager;
412 374
413 if (exynos_crtc->dpms != DRM_MODE_DPMS_ON) 375 if (exynos_crtc->dpms != DRM_MODE_DPMS_ON)
414 return; 376 return;
415 377
416 if (manager->ops->disable_vblank) 378 if (exynos_crtc->ops->disable_vblank)
417 manager->ops->disable_vblank(manager); 379 exynos_crtc->ops->disable_vblank(exynos_crtc);
418} 380}
419 381
420void exynos_drm_crtc_finish_pageflip(struct drm_device *dev, int pipe) 382void exynos_drm_crtc_finish_pageflip(struct drm_device *dev, int pipe)
@@ -443,42 +405,9 @@ void exynos_drm_crtc_finish_pageflip(struct drm_device *dev, int pipe)
443 spin_unlock_irqrestore(&dev->event_lock, flags); 405 spin_unlock_irqrestore(&dev->event_lock, flags);
444} 406}
445 407
446void exynos_drm_crtc_plane_mode_set(struct drm_crtc *crtc,
447 struct exynos_drm_overlay *overlay)
448{
449 struct exynos_drm_manager *manager = to_exynos_crtc(crtc)->manager;
450
451 if (manager->ops->win_mode_set)
452 manager->ops->win_mode_set(manager, overlay);
453}
454
455void exynos_drm_crtc_plane_commit(struct drm_crtc *crtc, int zpos)
456{
457 struct exynos_drm_manager *manager = to_exynos_crtc(crtc)->manager;
458
459 if (manager->ops->win_commit)
460 manager->ops->win_commit(manager, zpos);
461}
462
463void exynos_drm_crtc_plane_enable(struct drm_crtc *crtc, int zpos)
464{
465 struct exynos_drm_manager *manager = to_exynos_crtc(crtc)->manager;
466
467 if (manager->ops->win_enable)
468 manager->ops->win_enable(manager, zpos);
469}
470
471void exynos_drm_crtc_plane_disable(struct drm_crtc *crtc, int zpos)
472{
473 struct exynos_drm_manager *manager = to_exynos_crtc(crtc)->manager;
474
475 if (manager->ops->win_disable)
476 manager->ops->win_disable(manager, zpos);
477}
478
479void exynos_drm_crtc_complete_scanout(struct drm_framebuffer *fb) 408void exynos_drm_crtc_complete_scanout(struct drm_framebuffer *fb)
480{ 409{
481 struct exynos_drm_manager *manager; 410 struct exynos_drm_crtc *exynos_crtc;
482 struct drm_device *dev = fb->dev; 411 struct drm_device *dev = fb->dev;
483 struct drm_crtc *crtc; 412 struct drm_crtc *crtc;
484 413
@@ -487,15 +416,15 @@ void exynos_drm_crtc_complete_scanout(struct drm_framebuffer *fb)
487 * for all encoders. 416 * for all encoders.
488 */ 417 */
489 list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) { 418 list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) {
490 manager = to_exynos_crtc(crtc)->manager; 419 exynos_crtc = to_exynos_crtc(crtc);
491 420
492 /* 421 /*
493 * wait for vblank interrupt 422 * wait for vblank interrupt
494 * - this makes sure that overlay data are updated to 423 * - this makes sure that overlay data are updated to
495 * real hardware. 424 * real hardware.
496 */ 425 */
497 if (manager->ops->wait_for_vblank) 426 if (exynos_crtc->ops->wait_for_vblank)
498 manager->ops->wait_for_vblank(manager); 427 exynos_crtc->ops->wait_for_vblank(exynos_crtc);
499 } 428 }
500} 429}
501 430
@@ -508,8 +437,8 @@ int exynos_drm_crtc_get_pipe_from_type(struct drm_device *drm_dev,
508 struct exynos_drm_crtc *exynos_crtc; 437 struct exynos_drm_crtc *exynos_crtc;
509 438
510 exynos_crtc = to_exynos_crtc(crtc); 439 exynos_crtc = to_exynos_crtc(crtc);
511 if (exynos_crtc->manager->type == out_type) 440 if (exynos_crtc->type == out_type)
512 return exynos_crtc->manager->pipe; 441 return exynos_crtc->pipe;
513 } 442 }
514 443
515 return -EPERM; 444 return -EPERM;
@@ -517,8 +446,8 @@ int exynos_drm_crtc_get_pipe_from_type(struct drm_device *drm_dev,
517 446
518void exynos_drm_crtc_te_handler(struct drm_crtc *crtc) 447void exynos_drm_crtc_te_handler(struct drm_crtc *crtc)
519{ 448{
520 struct exynos_drm_manager *manager = to_exynos_crtc(crtc)->manager; 449 struct exynos_drm_crtc *exynos_crtc = to_exynos_crtc(crtc);
521 450
522 if (manager->ops->te_handler) 451 if (exynos_crtc->ops->te_handler)
523 manager->ops->te_handler(manager); 452 exynos_crtc->ops->te_handler(exynos_crtc);
524} 453}
diff --git a/drivers/gpu/drm/exynos/exynos_drm_crtc.h b/drivers/gpu/drm/exynos/exynos_drm_crtc.h
index e353d353836f..6258b800aab8 100644
--- a/drivers/gpu/drm/exynos/exynos_drm_crtc.h
+++ b/drivers/gpu/drm/exynos/exynos_drm_crtc.h
@@ -17,14 +17,18 @@
17 17
18#include "exynos_drm_drv.h" 18#include "exynos_drm_drv.h"
19 19
20int exynos_drm_crtc_create(struct exynos_drm_manager *manager); 20struct exynos_drm_crtc *exynos_drm_crtc_create(struct drm_device *drm_dev,
21 int pipe,
22 enum exynos_drm_output_type type,
23 struct exynos_drm_crtc_ops *ops,
24 void *context);
21int exynos_drm_crtc_enable_vblank(struct drm_device *dev, int pipe); 25int exynos_drm_crtc_enable_vblank(struct drm_device *dev, int pipe);
22void exynos_drm_crtc_disable_vblank(struct drm_device *dev, int pipe); 26void exynos_drm_crtc_disable_vblank(struct drm_device *dev, int pipe);
23void exynos_drm_crtc_finish_pageflip(struct drm_device *dev, int pipe); 27void exynos_drm_crtc_finish_pageflip(struct drm_device *dev, int pipe);
24void exynos_drm_crtc_complete_scanout(struct drm_framebuffer *fb); 28void exynos_drm_crtc_complete_scanout(struct drm_framebuffer *fb);
25 29
26void exynos_drm_crtc_plane_mode_set(struct drm_crtc *crtc, 30void exynos_drm_crtc_plane_mode_set(struct drm_crtc *crtc,
27 struct exynos_drm_overlay *overlay); 31 struct exynos_drm_plane *plane);
28void exynos_drm_crtc_plane_commit(struct drm_crtc *crtc, int zpos); 32void exynos_drm_crtc_plane_commit(struct drm_crtc *crtc, int zpos);
29void exynos_drm_crtc_plane_enable(struct drm_crtc *crtc, int zpos); 33void exynos_drm_crtc_plane_enable(struct drm_crtc *crtc, int zpos);
30void exynos_drm_crtc_plane_disable(struct drm_crtc *crtc, int zpos); 34void exynos_drm_crtc_plane_disable(struct drm_crtc *crtc, int zpos);
diff --git a/drivers/gpu/drm/exynos/exynos_drm_drv.h b/drivers/gpu/drm/exynos/exynos_drm_drv.h
index 2e5063488c50..d490b49f71c9 100644
--- a/drivers/gpu/drm/exynos/exynos_drm_drv.h
+++ b/drivers/gpu/drm/exynos/exynos_drm_drv.h
@@ -23,6 +23,9 @@
23#define MAX_FB_BUFFER 4 23#define MAX_FB_BUFFER 4
24#define DEFAULT_ZPOS -1 24#define DEFAULT_ZPOS -1
25 25
26#define to_exynos_crtc(x) container_of(x, struct exynos_drm_crtc, base)
27#define to_exynos_plane(x) container_of(x, struct exynos_drm_plane, base)
28
26/* This enumerates device type. */ 29/* This enumerates device type. */
27enum exynos_drm_device_type { 30enum exynos_drm_device_type {
28 EXYNOS_DEVICE_TYPE_NONE, 31 EXYNOS_DEVICE_TYPE_NONE,
@@ -44,6 +47,7 @@ enum exynos_drm_output_type {
44/* 47/*
45 * Exynos drm common overlay structure. 48 * Exynos drm common overlay structure.
46 * 49 *
50 * @base: plane object
47 * @fb_x: offset x on a framebuffer to be displayed. 51 * @fb_x: offset x on a framebuffer to be displayed.
48 * - the unit is screen coordinates. 52 * - the unit is screen coordinates.
49 * @fb_y: offset y on a framebuffer to be displayed. 53 * @fb_y: offset y on a framebuffer to be displayed.
@@ -73,11 +77,14 @@ enum exynos_drm_output_type {
73 * @local_path: in case of lcd type, local path mode on or off. 77 * @local_path: in case of lcd type, local path mode on or off.
74 * @transparency: transparency on or off. 78 * @transparency: transparency on or off.
75 * @activated: activated or not. 79 * @activated: activated or not.
80 * @enabled: enabled or not.
76 * 81 *
77 * this structure is common to exynos SoC and its contents would be copied 82 * this structure is common to exynos SoC and its contents would be copied
78 * to hardware specific overlay info. 83 * to hardware specific overlay info.
79 */ 84 */
80struct exynos_drm_overlay { 85
86struct exynos_drm_plane {
87 struct drm_plane base;
81 unsigned int fb_x; 88 unsigned int fb_x;
82 unsigned int fb_y; 89 unsigned int fb_y;
83 unsigned int fb_width; 90 unsigned int fb_width;
@@ -104,6 +111,7 @@ struct exynos_drm_overlay {
104 bool local_path:1; 111 bool local_path:1;
105 bool transparency:1; 112 bool transparency:1;
106 bool activated:1; 113 bool activated:1;
114 bool enabled:1;
107}; 115};
108 116
109/* 117/*
@@ -155,11 +163,10 @@ struct exynos_drm_display {
155}; 163};
156 164
157/* 165/*
158 * Exynos drm manager ops 166 * Exynos drm crtc ops
159 * 167 *
160 * @dpms: control device power. 168 * @dpms: control device power.
161 * @mode_fixup: fix mode data before applying it 169 * @mode_fixup: fix mode data before applying it
162 * @mode_set: set the given mode to the manager
163 * @commit: set current hw specific display mode to hw. 170 * @commit: set current hw specific display mode to hw.
164 * @enable_vblank: specific driver callback for enabling vblank interrupt. 171 * @enable_vblank: specific driver callback for enabling vblank interrupt.
165 * @disable_vblank: specific driver callback for disabling vblank interrupt. 172 * @disable_vblank: specific driver callback for disabling vblank interrupt.
@@ -172,44 +179,56 @@ struct exynos_drm_display {
172 * @te_handler: trigger to transfer video image at the tearing effect 179 * @te_handler: trigger to transfer video image at the tearing effect
173 * synchronization signal if there is a page flip request. 180 * synchronization signal if there is a page flip request.
174 */ 181 */
175struct exynos_drm_manager; 182struct exynos_drm_crtc;
176struct exynos_drm_manager_ops { 183struct exynos_drm_crtc_ops {
177 void (*dpms)(struct exynos_drm_manager *mgr, int mode); 184 void (*dpms)(struct exynos_drm_crtc *crtc, int mode);
178 bool (*mode_fixup)(struct exynos_drm_manager *mgr, 185 bool (*mode_fixup)(struct exynos_drm_crtc *crtc,
179 const struct drm_display_mode *mode, 186 const struct drm_display_mode *mode,
180 struct drm_display_mode *adjusted_mode); 187 struct drm_display_mode *adjusted_mode);
181 void (*mode_set)(struct exynos_drm_manager *mgr, 188 void (*commit)(struct exynos_drm_crtc *crtc);
182 const struct drm_display_mode *mode); 189 int (*enable_vblank)(struct exynos_drm_crtc *crtc);
183 void (*commit)(struct exynos_drm_manager *mgr); 190 void (*disable_vblank)(struct exynos_drm_crtc *crtc);
184 int (*enable_vblank)(struct exynos_drm_manager *mgr); 191 void (*wait_for_vblank)(struct exynos_drm_crtc *crtc);
185 void (*disable_vblank)(struct exynos_drm_manager *mgr); 192 void (*win_mode_set)(struct exynos_drm_crtc *crtc,
186 void (*wait_for_vblank)(struct exynos_drm_manager *mgr); 193 struct exynos_drm_plane *plane);
187 void (*win_mode_set)(struct exynos_drm_manager *mgr, 194 void (*win_commit)(struct exynos_drm_crtc *crtc, int zpos);
188 struct exynos_drm_overlay *overlay); 195 void (*win_enable)(struct exynos_drm_crtc *crtc, int zpos);
189 void (*win_commit)(struct exynos_drm_manager *mgr, int zpos); 196 void (*win_disable)(struct exynos_drm_crtc *crtc, int zpos);
190 void (*win_enable)(struct exynos_drm_manager *mgr, int zpos); 197 void (*te_handler)(struct exynos_drm_crtc *crtc);
191 void (*win_disable)(struct exynos_drm_manager *mgr, int zpos); 198};
192 void (*te_handler)(struct exynos_drm_manager *mgr); 199
200enum exynos_crtc_mode {
201 CRTC_MODE_NORMAL, /* normal mode */
202 CRTC_MODE_BLANK, /* The private plane of crtc is blank */
193}; 203};
194 204
195/* 205/*
196 * Exynos drm common manager structure, maps 1:1 with a crtc 206 * Exynos specific crtc structure.
197 * 207 *
198 * @list: the list entry for this manager 208 * @base: crtc object.
199 * @type: one of EXYNOS_DISPLAY_TYPE_LCD and HDMI. 209 * @type: one of EXYNOS_DISPLAY_TYPE_LCD and HDMI.
200 * @drm_dev: pointer to the drm device 210 * @pipe: a crtc index created at load() with a new crtc object creation
201 * @crtc: crtc object. 211 * and the crtc object would be set to private->crtc array
202 * @pipe: the pipe number for this crtc/manager 212 * to get a crtc object corresponding to this pipe from private->crtc
213 * array when irq interrupt occurred. the reason of using this pipe is that
214 * drm framework doesn't support multiple irq yet.
215 * we can refer to the crtc to current hardware interrupt occurred through
216 * this pipe value.
217 * @dpms: store the crtc dpms value
218 * @mode: store the crtc mode value
203 * @ops: pointer to callbacks for exynos drm specific functionality 219 * @ops: pointer to callbacks for exynos drm specific functionality
204 * @ctx: A pointer to the manager's implementation specific context 220 * @ctx: A pointer to the crtc's implementation specific context
205 */ 221 */
206struct exynos_drm_manager { 222struct exynos_drm_crtc {
207 struct list_head list; 223 struct drm_crtc base;
208 enum exynos_drm_output_type type; 224 enum exynos_drm_output_type type;
209 struct drm_device *drm_dev; 225 unsigned int pipe;
210 struct drm_crtc *crtc; 226 unsigned int dpms;
211 int pipe; 227 enum exynos_crtc_mode mode;
212 struct exynos_drm_manager_ops *ops; 228 wait_queue_head_t pending_flip_queue;
229 atomic_t pending_flip;
230 struct exynos_drm_crtc_ops *ops;
231 void *ctx;
213}; 232};
214 233
215struct exynos_drm_g2d_private { 234struct exynos_drm_g2d_private {
diff --git a/drivers/gpu/drm/exynos/exynos_drm_fimd.c b/drivers/gpu/drm/exynos/exynos_drm_fimd.c
index e5810d13bf9c..682806ef4d33 100644
--- a/drivers/gpu/drm/exynos/exynos_drm_fimd.c
+++ b/drivers/gpu/drm/exynos/exynos_drm_fimd.c
@@ -157,14 +157,13 @@ struct fimd_win_data {
157}; 157};
158 158
159struct fimd_context { 159struct fimd_context {
160 struct exynos_drm_manager manager;
161 struct device *dev; 160 struct device *dev;
162 struct drm_device *drm_dev; 161 struct drm_device *drm_dev;
162 struct exynos_drm_crtc *crtc;
163 struct clk *bus_clk; 163 struct clk *bus_clk;
164 struct clk *lcd_clk; 164 struct clk *lcd_clk;
165 void __iomem *regs; 165 void __iomem *regs;
166 struct regmap *sysreg; 166 struct regmap *sysreg;
167 struct drm_display_mode mode;
168 struct fimd_win_data win_data[WINDOWS_NR]; 167 struct fimd_win_data win_data[WINDOWS_NR];
169 unsigned int default_win; 168 unsigned int default_win;
170 unsigned long irq_flags; 169 unsigned long irq_flags;
@@ -185,11 +184,6 @@ struct fimd_context {
185 struct exynos_drm_display *display; 184 struct exynos_drm_display *display;
186}; 185};
187 186
188static inline struct fimd_context *mgr_to_fimd(struct exynos_drm_manager *mgr)
189{
190 return container_of(mgr, struct fimd_context, manager);
191}
192
193static const struct of_device_id fimd_driver_dt_match[] = { 187static const struct of_device_id fimd_driver_dt_match[] = {
194 { .compatible = "samsung,s3c6400-fimd", 188 { .compatible = "samsung,s3c6400-fimd",
195 .data = &s3c64xx_fimd_driver_data }, 189 .data = &s3c64xx_fimd_driver_data },
@@ -214,9 +208,9 @@ static inline struct fimd_driver_data *drm_fimd_get_driver_data(
214 return (struct fimd_driver_data *)of_id->data; 208 return (struct fimd_driver_data *)of_id->data;
215} 209}
216 210
217static void fimd_wait_for_vblank(struct exynos_drm_manager *mgr) 211static void fimd_wait_for_vblank(struct exynos_drm_crtc *crtc)
218{ 212{
219 struct fimd_context *ctx = mgr_to_fimd(mgr); 213 struct fimd_context *ctx = crtc->ctx;
220 214
221 if (ctx->suspended) 215 if (ctx->suspended)
222 return; 216 return;
@@ -259,9 +253,9 @@ static void fimd_enable_shadow_channel_path(struct fimd_context *ctx, int win,
259 writel(val, ctx->regs + SHADOWCON); 253 writel(val, ctx->regs + SHADOWCON);
260} 254}
261 255
262static void fimd_clear_channel(struct exynos_drm_manager *mgr) 256static void fimd_clear_channel(struct exynos_drm_crtc *crtc)
263{ 257{
264 struct fimd_context *ctx = mgr_to_fimd(mgr); 258 struct fimd_context *ctx = crtc->ctx;
265 int win, ch_enabled = 0; 259 int win, ch_enabled = 0;
266 260
267 DRM_DEBUG_KMS("%s\n", __FILE__); 261 DRM_DEBUG_KMS("%s\n", __FILE__);
@@ -286,38 +280,42 @@ static void fimd_clear_channel(struct exynos_drm_manager *mgr)
286 unsigned int state = ctx->suspended; 280 unsigned int state = ctx->suspended;
287 281
288 ctx->suspended = 0; 282 ctx->suspended = 0;
289 fimd_wait_for_vblank(mgr); 283 fimd_wait_for_vblank(crtc);
290 ctx->suspended = state; 284 ctx->suspended = state;
291 } 285 }
292} 286}
293 287
294static int fimd_mgr_initialize(struct exynos_drm_manager *mgr, 288static int fimd_ctx_initialize(struct fimd_context *ctx,
295 struct drm_device *drm_dev) 289 struct drm_device *drm_dev)
296{ 290{
297 struct fimd_context *ctx = mgr_to_fimd(mgr);
298 struct exynos_drm_private *priv; 291 struct exynos_drm_private *priv;
299 priv = drm_dev->dev_private; 292 priv = drm_dev->dev_private;
300 293
301 mgr->drm_dev = ctx->drm_dev = drm_dev; 294 ctx->drm_dev = drm_dev;
302 mgr->pipe = ctx->pipe = priv->pipe++; 295 ctx->pipe = priv->pipe++;
303 296
304 /* attach this sub driver to iommu mapping if supported. */ 297 /* attach this sub driver to iommu mapping if supported. */
305 if (is_drm_iommu_supported(ctx->drm_dev)) { 298 if (is_drm_iommu_supported(ctx->drm_dev)) {
299 int ret;
300
306 /* 301 /*
307 * If any channel is already active, iommu will throw 302 * If any channel is already active, iommu will throw
308 * a PAGE FAULT when enabled. So clear any channel if enabled. 303 * a PAGE FAULT when enabled. So clear any channel if enabled.
309 */ 304 */
310 fimd_clear_channel(mgr); 305 fimd_clear_channel(ctx->crtc);
311 drm_iommu_attach_device(ctx->drm_dev, ctx->dev); 306 ret = drm_iommu_attach_device(ctx->drm_dev, ctx->dev);
307 if (ret) {
308 DRM_ERROR("drm_iommu_attach failed.\n");
309 return ret;
310 }
311
312 } 312 }
313 313
314 return 0; 314 return 0;
315} 315}
316 316
317static void fimd_mgr_remove(struct exynos_drm_manager *mgr) 317static void fimd_ctx_remove(struct fimd_context *ctx)
318{ 318{
319 struct fimd_context *ctx = mgr_to_fimd(mgr);
320
321 /* detach this sub driver from iommu mapping if supported. */ 319 /* detach this sub driver from iommu mapping if supported. */
322 if (is_drm_iommu_supported(ctx->drm_dev)) 320 if (is_drm_iommu_supported(ctx->drm_dev))
323 drm_iommu_detach_device(ctx->drm_dev, ctx->dev); 321 drm_iommu_detach_device(ctx->drm_dev, ctx->dev);
@@ -343,7 +341,7 @@ static u32 fimd_calc_clkdiv(struct fimd_context *ctx,
343 return (clkdiv < 0x100) ? clkdiv : 0xff; 341 return (clkdiv < 0x100) ? clkdiv : 0xff;
344} 342}
345 343
346static bool fimd_mode_fixup(struct exynos_drm_manager *mgr, 344static bool fimd_mode_fixup(struct exynos_drm_crtc *crtc,
347 const struct drm_display_mode *mode, 345 const struct drm_display_mode *mode,
348 struct drm_display_mode *adjusted_mode) 346 struct drm_display_mode *adjusted_mode)
349{ 347{
@@ -353,18 +351,10 @@ static bool fimd_mode_fixup(struct exynos_drm_manager *mgr,
353 return true; 351 return true;
354} 352}
355 353
356static void fimd_mode_set(struct exynos_drm_manager *mgr, 354static void fimd_commit(struct exynos_drm_crtc *crtc)
357 const struct drm_display_mode *in_mode)
358{ 355{
359 struct fimd_context *ctx = mgr_to_fimd(mgr); 356 struct fimd_context *ctx = crtc->ctx;
360 357 struct drm_display_mode *mode = &crtc->base.mode;
361 drm_mode_copy(&ctx->mode, in_mode);
362}
363
364static void fimd_commit(struct exynos_drm_manager *mgr)
365{
366 struct fimd_context *ctx = mgr_to_fimd(mgr);
367 struct drm_display_mode *mode = &ctx->mode;
368 struct fimd_driver_data *driver_data = ctx->driver_data; 358 struct fimd_driver_data *driver_data = ctx->driver_data;
369 void *timing_base = ctx->regs + driver_data->timing_base; 359 void *timing_base = ctx->regs + driver_data->timing_base;
370 u32 val, clkdiv; 360 u32 val, clkdiv;
@@ -461,9 +451,9 @@ static void fimd_commit(struct exynos_drm_manager *mgr)
461 writel(val, ctx->regs + VIDCON0); 451 writel(val, ctx->regs + VIDCON0);
462} 452}
463 453
464static int fimd_enable_vblank(struct exynos_drm_manager *mgr) 454static int fimd_enable_vblank(struct exynos_drm_crtc *crtc)
465{ 455{
466 struct fimd_context *ctx = mgr_to_fimd(mgr); 456 struct fimd_context *ctx = crtc->ctx;
467 u32 val; 457 u32 val;
468 458
469 if (ctx->suspended) 459 if (ctx->suspended)
@@ -493,9 +483,9 @@ static int fimd_enable_vblank(struct exynos_drm_manager *mgr)
493 return 0; 483 return 0;
494} 484}
495 485
496static void fimd_disable_vblank(struct exynos_drm_manager *mgr) 486static void fimd_disable_vblank(struct exynos_drm_crtc *crtc)
497{ 487{
498 struct fimd_context *ctx = mgr_to_fimd(mgr); 488 struct fimd_context *ctx = crtc->ctx;
499 u32 val; 489 u32 val;
500 490
501 if (ctx->suspended) 491 if (ctx->suspended)
@@ -517,45 +507,45 @@ static void fimd_disable_vblank(struct exynos_drm_manager *mgr)
517 } 507 }
518} 508}
519 509
520static void fimd_win_mode_set(struct exynos_drm_manager *mgr, 510static void fimd_win_mode_set(struct exynos_drm_crtc *crtc,
521 struct exynos_drm_overlay *overlay) 511 struct exynos_drm_plane *plane)
522{ 512{
523 struct fimd_context *ctx = mgr_to_fimd(mgr); 513 struct fimd_context *ctx = crtc->ctx;
524 struct fimd_win_data *win_data; 514 struct fimd_win_data *win_data;
525 int win; 515 int win;
526 unsigned long offset; 516 unsigned long offset;
527 517
528 if (!overlay) { 518 if (!plane) {
529 DRM_ERROR("overlay is NULL\n"); 519 DRM_ERROR("plane is NULL\n");
530 return; 520 return;
531 } 521 }
532 522
533 win = overlay->zpos; 523 win = plane->zpos;
534 if (win == DEFAULT_ZPOS) 524 if (win == DEFAULT_ZPOS)
535 win = ctx->default_win; 525 win = ctx->default_win;
536 526
537 if (win < 0 || win >= WINDOWS_NR) 527 if (win < 0 || win >= WINDOWS_NR)
538 return; 528 return;
539 529
540 offset = overlay->fb_x * (overlay->bpp >> 3); 530 offset = plane->fb_x * (plane->bpp >> 3);
541 offset += overlay->fb_y * overlay->pitch; 531 offset += plane->fb_y * plane->pitch;
542 532
543 DRM_DEBUG_KMS("offset = 0x%lx, pitch = %x\n", offset, overlay->pitch); 533 DRM_DEBUG_KMS("offset = 0x%lx, pitch = %x\n", offset, plane->pitch);
544 534
545 win_data = &ctx->win_data[win]; 535 win_data = &ctx->win_data[win];
546 536
547 win_data->offset_x = overlay->crtc_x; 537 win_data->offset_x = plane->crtc_x;
548 win_data->offset_y = overlay->crtc_y; 538 win_data->offset_y = plane->crtc_y;
549 win_data->ovl_width = overlay->crtc_width; 539 win_data->ovl_width = plane->crtc_width;
550 win_data->ovl_height = overlay->crtc_height; 540 win_data->ovl_height = plane->crtc_height;
551 win_data->fb_width = overlay->fb_width; 541 win_data->fb_width = plane->fb_width;
552 win_data->fb_height = overlay->fb_height; 542 win_data->fb_height = plane->fb_height;
553 win_data->dma_addr = overlay->dma_addr[0] + offset; 543 win_data->dma_addr = plane->dma_addr[0] + offset;
554 win_data->bpp = overlay->bpp; 544 win_data->bpp = plane->bpp;
555 win_data->pixel_format = overlay->pixel_format; 545 win_data->pixel_format = plane->pixel_format;
556 win_data->buf_offsize = (overlay->fb_width - overlay->crtc_width) * 546 win_data->buf_offsize = (plane->fb_width - plane->crtc_width) *
557 (overlay->bpp >> 3); 547 (plane->bpp >> 3);
558 win_data->line_size = overlay->crtc_width * (overlay->bpp >> 3); 548 win_data->line_size = plane->crtc_width * (plane->bpp >> 3);
559 549
560 DRM_DEBUG_KMS("offset_x = %d, offset_y = %d\n", 550 DRM_DEBUG_KMS("offset_x = %d, offset_y = %d\n",
561 win_data->offset_x, win_data->offset_y); 551 win_data->offset_x, win_data->offset_y);
@@ -563,7 +553,7 @@ static void fimd_win_mode_set(struct exynos_drm_manager *mgr,
563 win_data->ovl_width, win_data->ovl_height); 553 win_data->ovl_width, win_data->ovl_height);
564 DRM_DEBUG_KMS("paddr = 0x%lx\n", (unsigned long)win_data->dma_addr); 554 DRM_DEBUG_KMS("paddr = 0x%lx\n", (unsigned long)win_data->dma_addr);
565 DRM_DEBUG_KMS("fb_width = %d, crtc_width = %d\n", 555 DRM_DEBUG_KMS("fb_width = %d, crtc_width = %d\n",
566 overlay->fb_width, overlay->crtc_width); 556 plane->fb_width, plane->crtc_width);
567} 557}
568 558
569static void fimd_win_set_pixfmt(struct fimd_context *ctx, unsigned int win) 559static void fimd_win_set_pixfmt(struct fimd_context *ctx, unsigned int win)
@@ -623,8 +613,8 @@ static void fimd_win_set_pixfmt(struct fimd_context *ctx, unsigned int win)
623 /* 613 /*
624 * In case of exynos, setting dma-burst to 16Word causes permanent 614 * In case of exynos, setting dma-burst to 16Word causes permanent
625 * tearing for very small buffers, e.g. cursor buffer. Burst Mode 615 * tearing for very small buffers, e.g. cursor buffer. Burst Mode
626 * switching which is based on overlay size is not recommended as 616 * switching which is based on plane size is not recommended as
627 * overlay size varies alot towards the end of the screen and rapid 617 * plane size varies alot towards the end of the screen and rapid
628 * movement causes unstable DMA which results into iommu crash/tear. 618 * movement causes unstable DMA which results into iommu crash/tear.
629 */ 619 */
630 620
@@ -676,9 +666,9 @@ static void fimd_shadow_protect_win(struct fimd_context *ctx,
676 writel(val, ctx->regs + reg); 666 writel(val, ctx->regs + reg);
677} 667}
678 668
679static void fimd_win_commit(struct exynos_drm_manager *mgr, int zpos) 669static void fimd_win_commit(struct exynos_drm_crtc *crtc, int zpos)
680{ 670{
681 struct fimd_context *ctx = mgr_to_fimd(mgr); 671 struct fimd_context *ctx = crtc->ctx;
682 struct fimd_win_data *win_data; 672 struct fimd_win_data *win_data;
683 int win = zpos; 673 int win = zpos;
684 unsigned long val, alpha, size; 674 unsigned long val, alpha, size;
@@ -799,9 +789,9 @@ static void fimd_win_commit(struct exynos_drm_manager *mgr, int zpos)
799 atomic_set(&ctx->win_updated, 1); 789 atomic_set(&ctx->win_updated, 1);
800} 790}
801 791
802static void fimd_win_disable(struct exynos_drm_manager *mgr, int zpos) 792static void fimd_win_disable(struct exynos_drm_crtc *crtc, int zpos)
803{ 793{
804 struct fimd_context *ctx = mgr_to_fimd(mgr); 794 struct fimd_context *ctx = crtc->ctx;
805 struct fimd_win_data *win_data; 795 struct fimd_win_data *win_data;
806 int win = zpos; 796 int win = zpos;
807 797
@@ -833,9 +823,9 @@ static void fimd_win_disable(struct exynos_drm_manager *mgr, int zpos)
833 win_data->enabled = false; 823 win_data->enabled = false;
834} 824}
835 825
836static void fimd_window_suspend(struct exynos_drm_manager *mgr) 826static void fimd_window_suspend(struct exynos_drm_crtc *crtc)
837{ 827{
838 struct fimd_context *ctx = mgr_to_fimd(mgr); 828 struct fimd_context *ctx = crtc->ctx;
839 struct fimd_win_data *win_data; 829 struct fimd_win_data *win_data;
840 int i; 830 int i;
841 831
@@ -843,13 +833,13 @@ static void fimd_window_suspend(struct exynos_drm_manager *mgr)
843 win_data = &ctx->win_data[i]; 833 win_data = &ctx->win_data[i];
844 win_data->resume = win_data->enabled; 834 win_data->resume = win_data->enabled;
845 if (win_data->enabled) 835 if (win_data->enabled)
846 fimd_win_disable(mgr, i); 836 fimd_win_disable(crtc, i);
847 } 837 }
848} 838}
849 839
850static void fimd_window_resume(struct exynos_drm_manager *mgr) 840static void fimd_window_resume(struct exynos_drm_crtc *crtc)
851{ 841{
852 struct fimd_context *ctx = mgr_to_fimd(mgr); 842 struct fimd_context *ctx = crtc->ctx;
853 struct fimd_win_data *win_data; 843 struct fimd_win_data *win_data;
854 int i; 844 int i;
855 845
@@ -860,26 +850,26 @@ static void fimd_window_resume(struct exynos_drm_manager *mgr)
860 } 850 }
861} 851}
862 852
863static void fimd_apply(struct exynos_drm_manager *mgr) 853static void fimd_apply(struct exynos_drm_crtc *crtc)
864{ 854{
865 struct fimd_context *ctx = mgr_to_fimd(mgr); 855 struct fimd_context *ctx = crtc->ctx;
866 struct fimd_win_data *win_data; 856 struct fimd_win_data *win_data;
867 int i; 857 int i;
868 858
869 for (i = 0; i < WINDOWS_NR; i++) { 859 for (i = 0; i < WINDOWS_NR; i++) {
870 win_data = &ctx->win_data[i]; 860 win_data = &ctx->win_data[i];
871 if (win_data->enabled) 861 if (win_data->enabled)
872 fimd_win_commit(mgr, i); 862 fimd_win_commit(crtc, i);
873 else 863 else
874 fimd_win_disable(mgr, i); 864 fimd_win_disable(crtc, i);
875 } 865 }
876 866
877 fimd_commit(mgr); 867 fimd_commit(crtc);
878} 868}
879 869
880static int fimd_poweron(struct exynos_drm_manager *mgr) 870static int fimd_poweron(struct exynos_drm_crtc *crtc)
881{ 871{
882 struct fimd_context *ctx = mgr_to_fimd(mgr); 872 struct fimd_context *ctx = crtc->ctx;
883 int ret; 873 int ret;
884 874
885 if (!ctx->suspended) 875 if (!ctx->suspended)
@@ -903,16 +893,16 @@ static int fimd_poweron(struct exynos_drm_manager *mgr)
903 893
904 /* if vblank was enabled status, enable it again. */ 894 /* if vblank was enabled status, enable it again. */
905 if (test_and_clear_bit(0, &ctx->irq_flags)) { 895 if (test_and_clear_bit(0, &ctx->irq_flags)) {
906 ret = fimd_enable_vblank(mgr); 896 ret = fimd_enable_vblank(crtc);
907 if (ret) { 897 if (ret) {
908 DRM_ERROR("Failed to re-enable vblank [%d]\n", ret); 898 DRM_ERROR("Failed to re-enable vblank [%d]\n", ret);
909 goto enable_vblank_err; 899 goto enable_vblank_err;
910 } 900 }
911 } 901 }
912 902
913 fimd_window_resume(mgr); 903 fimd_window_resume(crtc);
914 904
915 fimd_apply(mgr); 905 fimd_apply(crtc);
916 906
917 return 0; 907 return 0;
918 908
@@ -925,9 +915,9 @@ bus_clk_err:
925 return ret; 915 return ret;
926} 916}
927 917
928static int fimd_poweroff(struct exynos_drm_manager *mgr) 918static int fimd_poweroff(struct exynos_drm_crtc *crtc)
929{ 919{
930 struct fimd_context *ctx = mgr_to_fimd(mgr); 920 struct fimd_context *ctx = crtc->ctx;
931 921
932 if (ctx->suspended) 922 if (ctx->suspended)
933 return 0; 923 return 0;
@@ -937,7 +927,7 @@ static int fimd_poweroff(struct exynos_drm_manager *mgr)
937 * suspend that connector. Otherwise we might try to scan from 927 * suspend that connector. Otherwise we might try to scan from
938 * a destroyed buffer later. 928 * a destroyed buffer later.
939 */ 929 */
940 fimd_window_suspend(mgr); 930 fimd_window_suspend(crtc);
941 931
942 clk_disable_unprepare(ctx->lcd_clk); 932 clk_disable_unprepare(ctx->lcd_clk);
943 clk_disable_unprepare(ctx->bus_clk); 933 clk_disable_unprepare(ctx->bus_clk);
@@ -948,18 +938,18 @@ static int fimd_poweroff(struct exynos_drm_manager *mgr)
948 return 0; 938 return 0;
949} 939}
950 940
951static void fimd_dpms(struct exynos_drm_manager *mgr, int mode) 941static void fimd_dpms(struct exynos_drm_crtc *crtc, int mode)
952{ 942{
953 DRM_DEBUG_KMS("%s, %d\n", __FILE__, mode); 943 DRM_DEBUG_KMS("%s, %d\n", __FILE__, mode);
954 944
955 switch (mode) { 945 switch (mode) {
956 case DRM_MODE_DPMS_ON: 946 case DRM_MODE_DPMS_ON:
957 fimd_poweron(mgr); 947 fimd_poweron(crtc);
958 break; 948 break;
959 case DRM_MODE_DPMS_STANDBY: 949 case DRM_MODE_DPMS_STANDBY:
960 case DRM_MODE_DPMS_SUSPEND: 950 case DRM_MODE_DPMS_SUSPEND:
961 case DRM_MODE_DPMS_OFF: 951 case DRM_MODE_DPMS_OFF:
962 fimd_poweroff(mgr); 952 fimd_poweroff(crtc);
963 break; 953 break;
964 default: 954 default:
965 DRM_DEBUG_KMS("unspecified mode %d\n", mode); 955 DRM_DEBUG_KMS("unspecified mode %d\n", mode);
@@ -996,9 +986,9 @@ static void fimd_trigger(struct device *dev)
996 atomic_set(&ctx->triggering, 0); 986 atomic_set(&ctx->triggering, 0);
997} 987}
998 988
999static void fimd_te_handler(struct exynos_drm_manager *mgr) 989static void fimd_te_handler(struct exynos_drm_crtc *crtc)
1000{ 990{
1001 struct fimd_context *ctx = mgr_to_fimd(mgr); 991 struct fimd_context *ctx = crtc->ctx;
1002 992
1003 /* Checks the crtc is detached already from encoder */ 993 /* Checks the crtc is detached already from encoder */
1004 if (ctx->pipe < 0 || !ctx->drm_dev) 994 if (ctx->pipe < 0 || !ctx->drm_dev)
@@ -1021,10 +1011,9 @@ static void fimd_te_handler(struct exynos_drm_manager *mgr)
1021 drm_handle_vblank(ctx->drm_dev, ctx->pipe); 1011 drm_handle_vblank(ctx->drm_dev, ctx->pipe);
1022} 1012}
1023 1013
1024static struct exynos_drm_manager_ops fimd_manager_ops = { 1014static struct exynos_drm_crtc_ops fimd_crtc_ops = {
1025 .dpms = fimd_dpms, 1015 .dpms = fimd_dpms,
1026 .mode_fixup = fimd_mode_fixup, 1016 .mode_fixup = fimd_mode_fixup,
1027 .mode_set = fimd_mode_set,
1028 .commit = fimd_commit, 1017 .commit = fimd_commit,
1029 .enable_vblank = fimd_enable_vblank, 1018 .enable_vblank = fimd_enable_vblank,
1030 .disable_vblank = fimd_disable_vblank, 1019 .disable_vblank = fimd_disable_vblank,
@@ -1074,9 +1063,21 @@ static int fimd_bind(struct device *dev, struct device *master, void *data)
1074{ 1063{
1075 struct fimd_context *ctx = dev_get_drvdata(dev); 1064 struct fimd_context *ctx = dev_get_drvdata(dev);
1076 struct drm_device *drm_dev = data; 1065 struct drm_device *drm_dev = data;
1066 int ret;
1067
1068 ctx->crtc = exynos_drm_crtc_create(drm_dev, ctx->pipe,
1069 EXYNOS_DISPLAY_TYPE_LCD,
1070 &fimd_crtc_ops, ctx);
1071 if (IS_ERR(ctx->crtc))
1072 return PTR_ERR(ctx->crtc);
1073
1074 ret = fimd_ctx_initialize(ctx, drm_dev);
1075 if (ret) {
1076 DRM_ERROR("fimd_ctx_initialize failed.\n");
1077 return ret;
1078 }
1079
1077 1080
1078 fimd_mgr_initialize(&ctx->manager, drm_dev);
1079 exynos_drm_crtc_create(&ctx->manager);
1080 if (ctx->display) 1081 if (ctx->display)
1081 exynos_drm_create_enc_conn(drm_dev, ctx->display); 1082 exynos_drm_create_enc_conn(drm_dev, ctx->display);
1082 1083
@@ -1089,12 +1090,12 @@ static void fimd_unbind(struct device *dev, struct device *master,
1089{ 1090{
1090 struct fimd_context *ctx = dev_get_drvdata(dev); 1091 struct fimd_context *ctx = dev_get_drvdata(dev);
1091 1092
1092 fimd_dpms(&ctx->manager, DRM_MODE_DPMS_OFF); 1093 fimd_dpms(ctx->crtc, DRM_MODE_DPMS_OFF);
1093 1094
1094 if (ctx->display) 1095 if (ctx->display)
1095 exynos_dpi_remove(ctx->display); 1096 exynos_dpi_remove(ctx->display);
1096 1097
1097 fimd_mgr_remove(&ctx->manager); 1098 fimd_ctx_remove(ctx);
1098} 1099}
1099 1100
1100static const struct component_ops fimd_component_ops = { 1101static const struct component_ops fimd_component_ops = {
@@ -1108,7 +1109,7 @@ static int fimd_probe(struct platform_device *pdev)
1108 struct fimd_context *ctx; 1109 struct fimd_context *ctx;
1109 struct device_node *i80_if_timings; 1110 struct device_node *i80_if_timings;
1110 struct resource *res; 1111 struct resource *res;
1111 int ret = -EINVAL; 1112 int ret;
1112 1113
1113 if (!dev->of_node) 1114 if (!dev->of_node)
1114 return -ENODEV; 1115 return -ENODEV;
@@ -1117,11 +1118,8 @@ static int fimd_probe(struct platform_device *pdev)
1117 if (!ctx) 1118 if (!ctx)
1118 return -ENOMEM; 1119 return -ENOMEM;
1119 1120
1120 ctx->manager.type = EXYNOS_DISPLAY_TYPE_LCD;
1121 ctx->manager.ops = &fimd_manager_ops;
1122
1123 ret = exynos_drm_component_add(dev, EXYNOS_DEVICE_TYPE_CRTC, 1121 ret = exynos_drm_component_add(dev, EXYNOS_DEVICE_TYPE_CRTC,
1124 ctx->manager.type); 1122 EXYNOS_DISPLAY_TYPE_LCD);
1125 if (ret) 1123 if (ret)
1126 return ret; 1124 return ret;
1127 1125
diff --git a/drivers/gpu/drm/exynos/exynos_drm_plane.c b/drivers/gpu/drm/exynos/exynos_drm_plane.c
index c7045a663763..358cff67e5ce 100644
--- a/drivers/gpu/drm/exynos/exynos_drm_plane.c
+++ b/drivers/gpu/drm/exynos/exynos_drm_plane.c
@@ -12,20 +12,13 @@
12#include <drm/drmP.h> 12#include <drm/drmP.h>
13 13
14#include <drm/exynos_drm.h> 14#include <drm/exynos_drm.h>
15#include <drm/drm_plane_helper.h>
15#include "exynos_drm_drv.h" 16#include "exynos_drm_drv.h"
16#include "exynos_drm_crtc.h" 17#include "exynos_drm_crtc.h"
17#include "exynos_drm_fb.h" 18#include "exynos_drm_fb.h"
18#include "exynos_drm_gem.h" 19#include "exynos_drm_gem.h"
19#include "exynos_drm_plane.h" 20#include "exynos_drm_plane.h"
20 21
21#define to_exynos_plane(x) container_of(x, struct exynos_plane, base)
22
23struct exynos_plane {
24 struct drm_plane base;
25 struct exynos_drm_overlay overlay;
26 bool enabled;
27};
28
29static const uint32_t formats[] = { 22static const uint32_t formats[] = {
30 DRM_FORMAT_XRGB8888, 23 DRM_FORMAT_XRGB8888,
31 DRM_FORMAT_ARGB8888, 24 DRM_FORMAT_ARGB8888,
@@ -69,16 +62,9 @@ static int exynos_plane_get_size(int start, unsigned length, unsigned last)
69 return size; 62 return size;
70} 63}
71 64
72int exynos_plane_mode_set(struct drm_plane *plane, struct drm_crtc *crtc, 65int exynos_check_plane(struct drm_plane *plane, struct drm_framebuffer *fb)
73 struct drm_framebuffer *fb, int crtc_x, int crtc_y,
74 unsigned int crtc_w, unsigned int crtc_h,
75 uint32_t src_x, uint32_t src_y,
76 uint32_t src_w, uint32_t src_h)
77{ 66{
78 struct exynos_plane *exynos_plane = to_exynos_plane(plane); 67 struct exynos_drm_plane *exynos_plane = to_exynos_plane(plane);
79 struct exynos_drm_overlay *overlay = &exynos_plane->overlay;
80 unsigned int actual_w;
81 unsigned int actual_h;
82 int nr; 68 int nr;
83 int i; 69 int i;
84 70
@@ -91,12 +77,26 @@ int exynos_plane_mode_set(struct drm_plane *plane, struct drm_crtc *crtc,
91 return -EFAULT; 77 return -EFAULT;
92 } 78 }
93 79
94 overlay->dma_addr[i] = buffer->dma_addr; 80 exynos_plane->dma_addr[i] = buffer->dma_addr;
95 81
96 DRM_DEBUG_KMS("buffer: %d, dma_addr = 0x%lx\n", 82 DRM_DEBUG_KMS("buffer: %d, dma_addr = 0x%lx\n",
97 i, (unsigned long)overlay->dma_addr[i]); 83 i, (unsigned long)exynos_plane->dma_addr[i]);
98 } 84 }
99 85
86 return 0;
87}
88
89void exynos_plane_mode_set(struct drm_plane *plane, struct drm_crtc *crtc,
90 struct drm_framebuffer *fb, int crtc_x, int crtc_y,
91 unsigned int crtc_w, unsigned int crtc_h,
92 uint32_t src_x, uint32_t src_y,
93 uint32_t src_w, uint32_t src_h)
94{
95 struct exynos_drm_plane *exynos_plane = to_exynos_plane(plane);
96 struct exynos_drm_crtc *exynos_crtc = to_exynos_crtc(crtc);
97 unsigned int actual_w;
98 unsigned int actual_h;
99
100 actual_w = exynos_plane_get_size(crtc_x, crtc_w, crtc->mode.hdisplay); 100 actual_w = exynos_plane_get_size(crtc_x, crtc_w, crtc->mode.hdisplay);
101 actual_h = exynos_plane_get_size(crtc_y, crtc_h, crtc->mode.vdisplay); 101 actual_h = exynos_plane_get_size(crtc_y, crtc_h, crtc->mode.vdisplay);
102 102
@@ -113,84 +113,86 @@ int exynos_plane_mode_set(struct drm_plane *plane, struct drm_crtc *crtc,
113 } 113 }
114 114
115 /* set drm framebuffer data. */ 115 /* set drm framebuffer data. */
116 overlay->fb_x = src_x; 116 exynos_plane->fb_x = src_x;
117 overlay->fb_y = src_y; 117 exynos_plane->fb_y = src_y;
118 overlay->fb_width = fb->width; 118 exynos_plane->fb_width = fb->width;
119 overlay->fb_height = fb->height; 119 exynos_plane->fb_height = fb->height;
120 overlay->src_width = src_w; 120 exynos_plane->src_width = src_w;
121 overlay->src_height = src_h; 121 exynos_plane->src_height = src_h;
122 overlay->bpp = fb->bits_per_pixel; 122 exynos_plane->bpp = fb->bits_per_pixel;
123 overlay->pitch = fb->pitches[0]; 123 exynos_plane->pitch = fb->pitches[0];
124 overlay->pixel_format = fb->pixel_format; 124 exynos_plane->pixel_format = fb->pixel_format;
125 125
126 /* set overlay range to be displayed. */ 126 /* set plane range to be displayed. */
127 overlay->crtc_x = crtc_x; 127 exynos_plane->crtc_x = crtc_x;
128 overlay->crtc_y = crtc_y; 128 exynos_plane->crtc_y = crtc_y;
129 overlay->crtc_width = actual_w; 129 exynos_plane->crtc_width = actual_w;
130 overlay->crtc_height = actual_h; 130 exynos_plane->crtc_height = actual_h;
131 131
132 /* set drm mode data. */ 132 /* set drm mode data. */
133 overlay->mode_width = crtc->mode.hdisplay; 133 exynos_plane->mode_width = crtc->mode.hdisplay;
134 overlay->mode_height = crtc->mode.vdisplay; 134 exynos_plane->mode_height = crtc->mode.vdisplay;
135 overlay->refresh = crtc->mode.vrefresh; 135 exynos_plane->refresh = crtc->mode.vrefresh;
136 overlay->scan_flag = crtc->mode.flags; 136 exynos_plane->scan_flag = crtc->mode.flags;
137 137
138 DRM_DEBUG_KMS("overlay : offset_x/y(%d,%d), width/height(%d,%d)", 138 DRM_DEBUG_KMS("plane : offset_x/y(%d,%d), width/height(%d,%d)",
139 overlay->crtc_x, overlay->crtc_y, 139 exynos_plane->crtc_x, exynos_plane->crtc_y,
140 overlay->crtc_width, overlay->crtc_height); 140 exynos_plane->crtc_width, exynos_plane->crtc_height);
141 141
142 plane->crtc = crtc; 142 plane->crtc = crtc;
143 143
144 exynos_drm_crtc_plane_mode_set(crtc, overlay); 144 if (exynos_crtc->ops->win_mode_set)
145 145 exynos_crtc->ops->win_mode_set(exynos_crtc, exynos_plane);
146 return 0;
147}
148
149void exynos_plane_commit(struct drm_plane *plane)
150{
151 struct exynos_plane *exynos_plane = to_exynos_plane(plane);
152 struct exynos_drm_overlay *overlay = &exynos_plane->overlay;
153
154 exynos_drm_crtc_plane_commit(plane->crtc, overlay->zpos);
155} 146}
156 147
157void exynos_plane_dpms(struct drm_plane *plane, int mode) 148void exynos_plane_dpms(struct drm_plane *plane, int mode)
158{ 149{
159 struct exynos_plane *exynos_plane = to_exynos_plane(plane); 150 struct exynos_drm_plane *exynos_plane = to_exynos_plane(plane);
160 struct exynos_drm_overlay *overlay = &exynos_plane->overlay; 151 struct exynos_drm_crtc *exynos_crtc = to_exynos_crtc(plane->crtc);
161 152
162 if (mode == DRM_MODE_DPMS_ON) { 153 if (mode == DRM_MODE_DPMS_ON) {
163 if (exynos_plane->enabled) 154 if (exynos_plane->enabled)
164 return; 155 return;
165 156
166 exynos_drm_crtc_plane_enable(plane->crtc, overlay->zpos); 157 if (exynos_crtc->ops->win_enable)
158 exynos_crtc->ops->win_enable(exynos_crtc,
159 exynos_plane->zpos);
160
167 exynos_plane->enabled = true; 161 exynos_plane->enabled = true;
168 } else { 162 } else {
169 if (!exynos_plane->enabled) 163 if (!exynos_plane->enabled)
170 return; 164 return;
171 165
172 exynos_drm_crtc_plane_disable(plane->crtc, overlay->zpos); 166 if (exynos_crtc->ops->win_disable)
167 exynos_crtc->ops->win_disable(exynos_crtc,
168 exynos_plane->zpos);
169
173 exynos_plane->enabled = false; 170 exynos_plane->enabled = false;
174 } 171 }
175} 172}
176 173
177static int 174int
178exynos_update_plane(struct drm_plane *plane, struct drm_crtc *crtc, 175exynos_update_plane(struct drm_plane *plane, struct drm_crtc *crtc,
179 struct drm_framebuffer *fb, int crtc_x, int crtc_y, 176 struct drm_framebuffer *fb, int crtc_x, int crtc_y,
180 unsigned int crtc_w, unsigned int crtc_h, 177 unsigned int crtc_w, unsigned int crtc_h,
181 uint32_t src_x, uint32_t src_y, 178 uint32_t src_x, uint32_t src_y,
182 uint32_t src_w, uint32_t src_h) 179 uint32_t src_w, uint32_t src_h)
183{ 180{
181
182 struct exynos_drm_crtc *exynos_crtc = to_exynos_crtc(crtc);
183 struct exynos_drm_plane *exynos_plane = to_exynos_plane(plane);
184 int ret; 184 int ret;
185 185
186 ret = exynos_plane_mode_set(plane, crtc, fb, crtc_x, crtc_y, 186 ret = exynos_check_plane(plane, fb);
187 crtc_w, crtc_h, src_x >> 16, src_y >> 16,
188 src_w >> 16, src_h >> 16);
189 if (ret < 0) 187 if (ret < 0)
190 return ret; 188 return ret;
191 189
192 exynos_plane_commit(plane); 190 exynos_plane_mode_set(plane, crtc, fb, crtc_x, crtc_y,
193 exynos_plane_dpms(plane, DRM_MODE_DPMS_ON); 191 crtc_w, crtc_h, src_x >> 16, src_y >> 16,
192 src_w >> 16, src_h >> 16);
193
194 if (exynos_crtc->ops->win_commit)
195 exynos_crtc->ops->win_commit(exynos_crtc, exynos_plane->zpos);
194 196
195 return 0; 197 return 0;
196} 198}
@@ -204,7 +206,7 @@ static int exynos_disable_plane(struct drm_plane *plane)
204 206
205static void exynos_plane_destroy(struct drm_plane *plane) 207static void exynos_plane_destroy(struct drm_plane *plane)
206{ 208{
207 struct exynos_plane *exynos_plane = to_exynos_plane(plane); 209 struct exynos_drm_plane *exynos_plane = to_exynos_plane(plane);
208 210
209 exynos_disable_plane(plane); 211 exynos_disable_plane(plane);
210 drm_plane_cleanup(plane); 212 drm_plane_cleanup(plane);
@@ -216,11 +218,11 @@ static int exynos_plane_set_property(struct drm_plane *plane,
216 uint64_t val) 218 uint64_t val)
217{ 219{
218 struct drm_device *dev = plane->dev; 220 struct drm_device *dev = plane->dev;
219 struct exynos_plane *exynos_plane = to_exynos_plane(plane); 221 struct exynos_drm_plane *exynos_plane = to_exynos_plane(plane);
220 struct exynos_drm_private *dev_priv = dev->dev_private; 222 struct exynos_drm_private *dev_priv = dev->dev_private;
221 223
222 if (property == dev_priv->plane_zpos_property) { 224 if (property == dev_priv->plane_zpos_property) {
223 exynos_plane->overlay.zpos = val; 225 exynos_plane->zpos = val;
224 return 0; 226 return 0;
225 } 227 }
226 228
@@ -257,10 +259,10 @@ struct drm_plane *exynos_plane_init(struct drm_device *dev,
257 unsigned long possible_crtcs, 259 unsigned long possible_crtcs,
258 enum drm_plane_type type) 260 enum drm_plane_type type)
259{ 261{
260 struct exynos_plane *exynos_plane; 262 struct exynos_drm_plane *exynos_plane;
261 int err; 263 int err;
262 264
263 exynos_plane = kzalloc(sizeof(struct exynos_plane), GFP_KERNEL); 265 exynos_plane = kzalloc(sizeof(struct exynos_drm_plane), GFP_KERNEL);
264 if (!exynos_plane) 266 if (!exynos_plane)
265 return ERR_PTR(-ENOMEM); 267 return ERR_PTR(-ENOMEM);
266 268
@@ -274,7 +276,7 @@ struct drm_plane *exynos_plane_init(struct drm_device *dev,
274 } 276 }
275 277
276 if (type == DRM_PLANE_TYPE_PRIMARY) 278 if (type == DRM_PLANE_TYPE_PRIMARY)
277 exynos_plane->overlay.zpos = DEFAULT_ZPOS; 279 exynos_plane->zpos = DEFAULT_ZPOS;
278 else 280 else
279 exynos_plane_attach_zpos_property(&exynos_plane->base); 281 exynos_plane_attach_zpos_property(&exynos_plane->base);
280 282
diff --git a/drivers/gpu/drm/exynos/exynos_drm_plane.h b/drivers/gpu/drm/exynos/exynos_drm_plane.h
index 0d1986b115f8..59d40755095b 100644
--- a/drivers/gpu/drm/exynos/exynos_drm_plane.h
+++ b/drivers/gpu/drm/exynos/exynos_drm_plane.h
@@ -9,12 +9,17 @@
9 * 9 *
10 */ 10 */
11 11
12int exynos_plane_mode_set(struct drm_plane *plane, struct drm_crtc *crtc, 12int exynos_check_plane(struct drm_plane *plane, struct drm_framebuffer *fb);
13 struct drm_framebuffer *fb, int crtc_x, int crtc_y, 13void exynos_plane_mode_set(struct drm_plane *plane, struct drm_crtc *crtc,
14 unsigned int crtc_w, unsigned int crtc_h, 14 struct drm_framebuffer *fb, int crtc_x, int crtc_y,
15 uint32_t src_x, uint32_t src_y, 15 unsigned int crtc_w, unsigned int crtc_h,
16 uint32_t src_w, uint32_t src_h); 16 uint32_t src_x, uint32_t src_y,
17void exynos_plane_commit(struct drm_plane *plane); 17 uint32_t src_w, uint32_t src_h);
18int exynos_update_plane(struct drm_plane *plane, struct drm_crtc *crtc,
19 struct drm_framebuffer *fb, int crtc_x, int crtc_y,
20 unsigned int crtc_w, unsigned int crtc_h,
21 uint32_t src_x, uint32_t src_y,
22 uint32_t src_w, uint32_t src_h);
18void exynos_plane_dpms(struct drm_plane *plane, int mode); 23void exynos_plane_dpms(struct drm_plane *plane, int mode);
19struct drm_plane *exynos_plane_init(struct drm_device *dev, 24struct drm_plane *exynos_plane_init(struct drm_device *dev,
20 unsigned long possible_crtcs, 25 unsigned long possible_crtcs,
diff --git a/drivers/gpu/drm/exynos/exynos_drm_vidi.c b/drivers/gpu/drm/exynos/exynos_drm_vidi.c
index 45899fb63272..9c8300edd348 100644
--- a/drivers/gpu/drm/exynos/exynos_drm_vidi.c
+++ b/drivers/gpu/drm/exynos/exynos_drm_vidi.c
@@ -47,11 +47,10 @@ struct vidi_win_data {
47}; 47};
48 48
49struct vidi_context { 49struct vidi_context {
50 struct exynos_drm_manager manager;
51 struct exynos_drm_display display; 50 struct exynos_drm_display display;
52 struct platform_device *pdev; 51 struct platform_device *pdev;
53 struct drm_device *drm_dev; 52 struct drm_device *drm_dev;
54 struct drm_crtc *crtc; 53 struct exynos_drm_crtc *crtc;
55 struct drm_encoder *encoder; 54 struct drm_encoder *encoder;
56 struct drm_connector connector; 55 struct drm_connector connector;
57 struct vidi_win_data win_data[WINDOWS_NR]; 56 struct vidi_win_data win_data[WINDOWS_NR];
@@ -68,11 +67,6 @@ struct vidi_context {
68 int pipe; 67 int pipe;
69}; 68};
70 69
71static inline struct vidi_context *manager_to_vidi(struct exynos_drm_manager *m)
72{
73 return container_of(m, struct vidi_context, manager);
74}
75
76static inline struct vidi_context *display_to_vidi(struct exynos_drm_display *d) 70static inline struct vidi_context *display_to_vidi(struct exynos_drm_display *d)
77{ 71{
78 return container_of(d, struct vidi_context, display); 72 return container_of(d, struct vidi_context, display);
@@ -103,34 +97,23 @@ static const char fake_edid_info[] = {
103 0x00, 0x00, 0x00, 0x06 97 0x00, 0x00, 0x00, 0x06
104}; 98};
105 99
106static void vidi_apply(struct exynos_drm_manager *mgr) 100static void vidi_apply(struct exynos_drm_crtc *crtc)
107{ 101{
108 struct vidi_context *ctx = manager_to_vidi(mgr); 102 struct vidi_context *ctx = crtc->ctx;
109 struct exynos_drm_manager_ops *mgr_ops = mgr->ops; 103 struct exynos_drm_crtc_ops *crtc_ops = crtc->ops;
110 struct vidi_win_data *win_data; 104 struct vidi_win_data *win_data;
111 int i; 105 int i;
112 106
113 for (i = 0; i < WINDOWS_NR; i++) { 107 for (i = 0; i < WINDOWS_NR; i++) {
114 win_data = &ctx->win_data[i]; 108 win_data = &ctx->win_data[i];
115 if (win_data->enabled && (mgr_ops && mgr_ops->win_commit)) 109 if (win_data->enabled && (crtc_ops && crtc_ops->win_commit))
116 mgr_ops->win_commit(mgr, i); 110 crtc_ops->win_commit(crtc, i);
117 } 111 }
118
119 if (mgr_ops && mgr_ops->commit)
120 mgr_ops->commit(mgr);
121}
122
123static void vidi_commit(struct exynos_drm_manager *mgr)
124{
125 struct vidi_context *ctx = manager_to_vidi(mgr);
126
127 if (ctx->suspended)
128 return;
129} 112}
130 113
131static int vidi_enable_vblank(struct exynos_drm_manager *mgr) 114static int vidi_enable_vblank(struct exynos_drm_crtc *crtc)
132{ 115{
133 struct vidi_context *ctx = manager_to_vidi(mgr); 116 struct vidi_context *ctx = crtc->ctx;
134 117
135 if (ctx->suspended) 118 if (ctx->suspended)
136 return -EPERM; 119 return -EPERM;
@@ -143,16 +126,16 @@ static int vidi_enable_vblank(struct exynos_drm_manager *mgr)
143 /* 126 /*
144 * in case of page flip request, vidi_finish_pageflip function 127 * in case of page flip request, vidi_finish_pageflip function
145 * will not be called because direct_vblank is true and then 128 * will not be called because direct_vblank is true and then
146 * that function will be called by manager_ops->win_commit callback 129 * that function will be called by crtc_ops->win_commit callback
147 */ 130 */
148 schedule_work(&ctx->work); 131 schedule_work(&ctx->work);
149 132
150 return 0; 133 return 0;
151} 134}
152 135
153static void vidi_disable_vblank(struct exynos_drm_manager *mgr) 136static void vidi_disable_vblank(struct exynos_drm_crtc *crtc)
154{ 137{
155 struct vidi_context *ctx = manager_to_vidi(mgr); 138 struct vidi_context *ctx = crtc->ctx;
156 139
157 if (ctx->suspended) 140 if (ctx->suspended)
158 return; 141 return;
@@ -161,44 +144,44 @@ static void vidi_disable_vblank(struct exynos_drm_manager *mgr)
161 ctx->vblank_on = false; 144 ctx->vblank_on = false;
162} 145}
163 146
164static void vidi_win_mode_set(struct exynos_drm_manager *mgr, 147static void vidi_win_mode_set(struct exynos_drm_crtc *crtc,
165 struct exynos_drm_overlay *overlay) 148 struct exynos_drm_plane *plane)
166{ 149{
167 struct vidi_context *ctx = manager_to_vidi(mgr); 150 struct vidi_context *ctx = crtc->ctx;
168 struct vidi_win_data *win_data; 151 struct vidi_win_data *win_data;
169 int win; 152 int win;
170 unsigned long offset; 153 unsigned long offset;
171 154
172 if (!overlay) { 155 if (!plane) {
173 DRM_ERROR("overlay is NULL\n"); 156 DRM_ERROR("plane is NULL\n");
174 return; 157 return;
175 } 158 }
176 159
177 win = overlay->zpos; 160 win = plane->zpos;
178 if (win == DEFAULT_ZPOS) 161 if (win == DEFAULT_ZPOS)
179 win = ctx->default_win; 162 win = ctx->default_win;
180 163
181 if (win < 0 || win >= WINDOWS_NR) 164 if (win < 0 || win >= WINDOWS_NR)
182 return; 165 return;
183 166
184 offset = overlay->fb_x * (overlay->bpp >> 3); 167 offset = plane->fb_x * (plane->bpp >> 3);
185 offset += overlay->fb_y * overlay->pitch; 168 offset += plane->fb_y * plane->pitch;
186 169
187 DRM_DEBUG_KMS("offset = 0x%lx, pitch = %x\n", offset, overlay->pitch); 170 DRM_DEBUG_KMS("offset = 0x%lx, pitch = %x\n", offset, plane->pitch);
188 171
189 win_data = &ctx->win_data[win]; 172 win_data = &ctx->win_data[win];
190 173
191 win_data->offset_x = overlay->crtc_x; 174 win_data->offset_x = plane->crtc_x;
192 win_data->offset_y = overlay->crtc_y; 175 win_data->offset_y = plane->crtc_y;
193 win_data->ovl_width = overlay->crtc_width; 176 win_data->ovl_width = plane->crtc_width;
194 win_data->ovl_height = overlay->crtc_height; 177 win_data->ovl_height = plane->crtc_height;
195 win_data->fb_width = overlay->fb_width; 178 win_data->fb_width = plane->fb_width;
196 win_data->fb_height = overlay->fb_height; 179 win_data->fb_height = plane->fb_height;
197 win_data->dma_addr = overlay->dma_addr[0] + offset; 180 win_data->dma_addr = plane->dma_addr[0] + offset;
198 win_data->bpp = overlay->bpp; 181 win_data->bpp = plane->bpp;
199 win_data->buf_offsize = (overlay->fb_width - overlay->crtc_width) * 182 win_data->buf_offsize = (plane->fb_width - plane->crtc_width) *
200 (overlay->bpp >> 3); 183 (plane->bpp >> 3);
201 win_data->line_size = overlay->crtc_width * (overlay->bpp >> 3); 184 win_data->line_size = plane->crtc_width * (plane->bpp >> 3);
202 185
203 /* 186 /*
204 * some parts of win_data should be transferred to user side 187 * some parts of win_data should be transferred to user side
@@ -211,12 +194,12 @@ static void vidi_win_mode_set(struct exynos_drm_manager *mgr,
211 win_data->ovl_width, win_data->ovl_height); 194 win_data->ovl_width, win_data->ovl_height);
212 DRM_DEBUG_KMS("paddr = 0x%lx\n", (unsigned long)win_data->dma_addr); 195 DRM_DEBUG_KMS("paddr = 0x%lx\n", (unsigned long)win_data->dma_addr);
213 DRM_DEBUG_KMS("fb_width = %d, crtc_width = %d\n", 196 DRM_DEBUG_KMS("fb_width = %d, crtc_width = %d\n",
214 overlay->fb_width, overlay->crtc_width); 197 plane->fb_width, plane->crtc_width);
215} 198}
216 199
217static void vidi_win_commit(struct exynos_drm_manager *mgr, int zpos) 200static void vidi_win_commit(struct exynos_drm_crtc *crtc, int zpos)
218{ 201{
219 struct vidi_context *ctx = manager_to_vidi(mgr); 202 struct vidi_context *ctx = crtc->ctx;
220 struct vidi_win_data *win_data; 203 struct vidi_win_data *win_data;
221 int win = zpos; 204 int win = zpos;
222 205
@@ -239,9 +222,9 @@ static void vidi_win_commit(struct exynos_drm_manager *mgr, int zpos)
239 schedule_work(&ctx->work); 222 schedule_work(&ctx->work);
240} 223}
241 224
242static void vidi_win_disable(struct exynos_drm_manager *mgr, int zpos) 225static void vidi_win_disable(struct exynos_drm_crtc *crtc, int zpos)
243{ 226{
244 struct vidi_context *ctx = manager_to_vidi(mgr); 227 struct vidi_context *ctx = crtc->ctx;
245 struct vidi_win_data *win_data; 228 struct vidi_win_data *win_data;
246 int win = zpos; 229 int win = zpos;
247 230
@@ -257,9 +240,9 @@ static void vidi_win_disable(struct exynos_drm_manager *mgr, int zpos)
257 /* TODO. */ 240 /* TODO. */
258} 241}
259 242
260static int vidi_power_on(struct exynos_drm_manager *mgr, bool enable) 243static int vidi_power_on(struct exynos_drm_crtc *crtc, bool enable)
261{ 244{
262 struct vidi_context *ctx = manager_to_vidi(mgr); 245 struct vidi_context *ctx = crtc->ctx;
263 246
264 DRM_DEBUG_KMS("%s\n", __FILE__); 247 DRM_DEBUG_KMS("%s\n", __FILE__);
265 248
@@ -271,9 +254,9 @@ static int vidi_power_on(struct exynos_drm_manager *mgr, bool enable)
271 254
272 /* if vblank was enabled status, enable it again. */ 255 /* if vblank was enabled status, enable it again. */
273 if (test_and_clear_bit(0, &ctx->irq_flags)) 256 if (test_and_clear_bit(0, &ctx->irq_flags))
274 vidi_enable_vblank(mgr); 257 vidi_enable_vblank(crtc);
275 258
276 vidi_apply(mgr); 259 vidi_apply(crtc);
277 } else { 260 } else {
278 ctx->suspended = true; 261 ctx->suspended = true;
279 } 262 }
@@ -281,9 +264,9 @@ static int vidi_power_on(struct exynos_drm_manager *mgr, bool enable)
281 return 0; 264 return 0;
282} 265}
283 266
284static void vidi_dpms(struct exynos_drm_manager *mgr, int mode) 267static void vidi_dpms(struct exynos_drm_crtc *crtc, int mode)
285{ 268{
286 struct vidi_context *ctx = manager_to_vidi(mgr); 269 struct vidi_context *ctx = crtc->ctx;
287 270
288 DRM_DEBUG_KMS("%d\n", mode); 271 DRM_DEBUG_KMS("%d\n", mode);
289 272
@@ -291,12 +274,12 @@ static void vidi_dpms(struct exynos_drm_manager *mgr, int mode)
291 274
292 switch (mode) { 275 switch (mode) {
293 case DRM_MODE_DPMS_ON: 276 case DRM_MODE_DPMS_ON:
294 vidi_power_on(mgr, true); 277 vidi_power_on(crtc, true);
295 break; 278 break;
296 case DRM_MODE_DPMS_STANDBY: 279 case DRM_MODE_DPMS_STANDBY:
297 case DRM_MODE_DPMS_SUSPEND: 280 case DRM_MODE_DPMS_SUSPEND:
298 case DRM_MODE_DPMS_OFF: 281 case DRM_MODE_DPMS_OFF:
299 vidi_power_on(mgr, false); 282 vidi_power_on(crtc, false);
300 break; 283 break;
301 default: 284 default:
302 DRM_DEBUG_KMS("unspecified mode %d\n", mode); 285 DRM_DEBUG_KMS("unspecified mode %d\n", mode);
@@ -306,21 +289,19 @@ static void vidi_dpms(struct exynos_drm_manager *mgr, int mode)
306 mutex_unlock(&ctx->lock); 289 mutex_unlock(&ctx->lock);
307} 290}
308 291
309static int vidi_mgr_initialize(struct exynos_drm_manager *mgr, 292static int vidi_ctx_initialize(struct vidi_context *ctx,
310 struct drm_device *drm_dev) 293 struct drm_device *drm_dev)
311{ 294{
312 struct vidi_context *ctx = manager_to_vidi(mgr);
313 struct exynos_drm_private *priv = drm_dev->dev_private; 295 struct exynos_drm_private *priv = drm_dev->dev_private;
314 296
315 mgr->drm_dev = ctx->drm_dev = drm_dev; 297 ctx->drm_dev = drm_dev;
316 mgr->pipe = ctx->pipe = priv->pipe++; 298 ctx->pipe = priv->pipe++;
317 299
318 return 0; 300 return 0;
319} 301}
320 302
321static struct exynos_drm_manager_ops vidi_manager_ops = { 303static struct exynos_drm_crtc_ops vidi_crtc_ops = {
322 .dpms = vidi_dpms, 304 .dpms = vidi_dpms,
323 .commit = vidi_commit,
324 .enable_vblank = vidi_enable_vblank, 305 .enable_vblank = vidi_enable_vblank,
325 .disable_vblank = vidi_disable_vblank, 306 .disable_vblank = vidi_disable_vblank,
326 .win_mode_set = vidi_win_mode_set, 307 .win_mode_set = vidi_win_mode_set,
@@ -565,21 +546,21 @@ static int vidi_bind(struct device *dev, struct device *master, void *data)
565{ 546{
566 struct vidi_context *ctx = dev_get_drvdata(dev); 547 struct vidi_context *ctx = dev_get_drvdata(dev);
567 struct drm_device *drm_dev = data; 548 struct drm_device *drm_dev = data;
568 struct drm_crtc *crtc = ctx->crtc;
569 int ret; 549 int ret;
570 550
571 vidi_mgr_initialize(&ctx->manager, drm_dev); 551 ctx->crtc = exynos_drm_crtc_create(drm_dev, ctx->pipe,
572 552 EXYNOS_DISPLAY_TYPE_VIDI,
573 ret = exynos_drm_crtc_create(&ctx->manager); 553 &vidi_crtc_ops, ctx);
574 if (ret) { 554 if (IS_ERR(ctx->crtc)) {
575 DRM_ERROR("failed to create crtc.\n"); 555 DRM_ERROR("failed to create crtc.\n");
576 return ret; 556 return PTR_ERR(ctx->crtc);
577 } 557 }
578 558
559 vidi_ctx_initialize(ctx, drm_dev);
560
579 ret = exynos_drm_create_enc_conn(drm_dev, &ctx->display); 561 ret = exynos_drm_create_enc_conn(drm_dev, &ctx->display);
580 if (ret) { 562 if (ret) {
581 crtc->funcs->destroy(crtc); 563 ctx->crtc->base.funcs->destroy(&ctx->crtc->base);
582 DRM_ERROR("failed to create encoder and connector.\n");
583 return ret; 564 return ret;
584 } 565 }
585 566
@@ -605,15 +586,13 @@ static int vidi_probe(struct platform_device *pdev)
605 if (!ctx) 586 if (!ctx)
606 return -ENOMEM; 587 return -ENOMEM;
607 588
608 ctx->manager.type = EXYNOS_DISPLAY_TYPE_VIDI;
609 ctx->manager.ops = &vidi_manager_ops;
610 ctx->display.type = EXYNOS_DISPLAY_TYPE_VIDI; 589 ctx->display.type = EXYNOS_DISPLAY_TYPE_VIDI;
611 ctx->display.ops = &vidi_display_ops; 590 ctx->display.ops = &vidi_display_ops;
612 ctx->default_win = 0; 591 ctx->default_win = 0;
613 ctx->pdev = pdev; 592 ctx->pdev = pdev;
614 593
615 ret = exynos_drm_component_add(&pdev->dev, EXYNOS_DEVICE_TYPE_CRTC, 594 ret = exynos_drm_component_add(&pdev->dev, EXYNOS_DEVICE_TYPE_CRTC,
616 ctx->manager.type); 595 EXYNOS_DISPLAY_TYPE_VIDI);
617 if (ret) 596 if (ret)
618 return ret; 597 return ret;
619 598
diff --git a/drivers/gpu/drm/exynos/exynos_mixer.c b/drivers/gpu/drm/exynos/exynos_mixer.c
index 064ed6597def..ed44cd4f01f7 100644
--- a/drivers/gpu/drm/exynos/exynos_mixer.c
+++ b/drivers/gpu/drm/exynos/exynos_mixer.c
@@ -84,10 +84,10 @@ enum mixer_version_id {
84}; 84};
85 85
86struct mixer_context { 86struct mixer_context {
87 struct exynos_drm_manager manager;
88 struct platform_device *pdev; 87 struct platform_device *pdev;
89 struct device *dev; 88 struct device *dev;
90 struct drm_device *drm_dev; 89 struct drm_device *drm_dev;
90 struct exynos_drm_crtc *crtc;
91 int pipe; 91 int pipe;
92 bool interlace; 92 bool interlace;
93 bool powered; 93 bool powered;
@@ -103,11 +103,6 @@ struct mixer_context {
103 atomic_t wait_vsync_event; 103 atomic_t wait_vsync_event;
104}; 104};
105 105
106static inline struct mixer_context *mgr_to_mixer(struct exynos_drm_manager *mgr)
107{
108 return container_of(mgr, struct mixer_context, manager);
109}
110
111struct mixer_drv_data { 106struct mixer_drv_data {
112 enum mixer_version_id version; 107 enum mixer_version_id version;
113 bool is_vp_enabled; 108 bool is_vp_enabled;
@@ -854,16 +849,15 @@ static int vp_resources_init(struct mixer_context *mixer_ctx)
854 return 0; 849 return 0;
855} 850}
856 851
857static int mixer_initialize(struct exynos_drm_manager *mgr, 852static int mixer_initialize(struct mixer_context *mixer_ctx,
858 struct drm_device *drm_dev) 853 struct drm_device *drm_dev)
859{ 854{
860 int ret; 855 int ret;
861 struct mixer_context *mixer_ctx = mgr_to_mixer(mgr);
862 struct exynos_drm_private *priv; 856 struct exynos_drm_private *priv;
863 priv = drm_dev->dev_private; 857 priv = drm_dev->dev_private;
864 858
865 mgr->drm_dev = mixer_ctx->drm_dev = drm_dev; 859 mixer_ctx->drm_dev = drm_dev;
866 mgr->pipe = mixer_ctx->pipe = priv->pipe++; 860 mixer_ctx->pipe = priv->pipe++;
867 861
868 /* acquire resources: regs, irqs, clocks */ 862 /* acquire resources: regs, irqs, clocks */
869 ret = mixer_resources_init(mixer_ctx); 863 ret = mixer_resources_init(mixer_ctx);
@@ -887,17 +881,15 @@ static int mixer_initialize(struct exynos_drm_manager *mgr,
887 return drm_iommu_attach_device(mixer_ctx->drm_dev, mixer_ctx->dev); 881 return drm_iommu_attach_device(mixer_ctx->drm_dev, mixer_ctx->dev);
888} 882}
889 883
890static void mixer_mgr_remove(struct exynos_drm_manager *mgr) 884static void mixer_ctx_remove(struct mixer_context *mixer_ctx)
891{ 885{
892 struct mixer_context *mixer_ctx = mgr_to_mixer(mgr);
893
894 if (is_drm_iommu_supported(mixer_ctx->drm_dev)) 886 if (is_drm_iommu_supported(mixer_ctx->drm_dev))
895 drm_iommu_detach_device(mixer_ctx->drm_dev, mixer_ctx->dev); 887 drm_iommu_detach_device(mixer_ctx->drm_dev, mixer_ctx->dev);
896} 888}
897 889
898static int mixer_enable_vblank(struct exynos_drm_manager *mgr) 890static int mixer_enable_vblank(struct exynos_drm_crtc *crtc)
899{ 891{
900 struct mixer_context *mixer_ctx = mgr_to_mixer(mgr); 892 struct mixer_context *mixer_ctx = crtc->ctx;
901 struct mixer_resources *res = &mixer_ctx->mixer_res; 893 struct mixer_resources *res = &mixer_ctx->mixer_res;
902 894
903 if (!mixer_ctx->powered) { 895 if (!mixer_ctx->powered) {
@@ -912,34 +904,34 @@ static int mixer_enable_vblank(struct exynos_drm_manager *mgr)
912 return 0; 904 return 0;
913} 905}
914 906
915static void mixer_disable_vblank(struct exynos_drm_manager *mgr) 907static void mixer_disable_vblank(struct exynos_drm_crtc *crtc)
916{ 908{
917 struct mixer_context *mixer_ctx = mgr_to_mixer(mgr); 909 struct mixer_context *mixer_ctx = crtc->ctx;
918 struct mixer_resources *res = &mixer_ctx->mixer_res; 910 struct mixer_resources *res = &mixer_ctx->mixer_res;
919 911
920 /* disable vsync interrupt */ 912 /* disable vsync interrupt */
921 mixer_reg_writemask(res, MXR_INT_EN, 0, MXR_INT_EN_VSYNC); 913 mixer_reg_writemask(res, MXR_INT_EN, 0, MXR_INT_EN_VSYNC);
922} 914}
923 915
924static void mixer_win_mode_set(struct exynos_drm_manager *mgr, 916static void mixer_win_mode_set(struct exynos_drm_crtc *crtc,
925 struct exynos_drm_overlay *overlay) 917 struct exynos_drm_plane *plane)
926{ 918{
927 struct mixer_context *mixer_ctx = mgr_to_mixer(mgr); 919 struct mixer_context *mixer_ctx = crtc->ctx;
928 struct hdmi_win_data *win_data; 920 struct hdmi_win_data *win_data;
929 int win; 921 int win;
930 922
931 if (!overlay) { 923 if (!plane) {
932 DRM_ERROR("overlay is NULL\n"); 924 DRM_ERROR("plane is NULL\n");
933 return; 925 return;
934 } 926 }
935 927
936 DRM_DEBUG_KMS("set [%d]x[%d] at (%d,%d) to [%d]x[%d] at (%d,%d)\n", 928 DRM_DEBUG_KMS("set [%d]x[%d] at (%d,%d) to [%d]x[%d] at (%d,%d)\n",
937 overlay->fb_width, overlay->fb_height, 929 plane->fb_width, plane->fb_height,
938 overlay->fb_x, overlay->fb_y, 930 plane->fb_x, plane->fb_y,
939 overlay->crtc_width, overlay->crtc_height, 931 plane->crtc_width, plane->crtc_height,
940 overlay->crtc_x, overlay->crtc_y); 932 plane->crtc_x, plane->crtc_y);
941 933
942 win = overlay->zpos; 934 win = plane->zpos;
943 if (win == DEFAULT_ZPOS) 935 if (win == DEFAULT_ZPOS)
944 win = MIXER_DEFAULT_WIN; 936 win = MIXER_DEFAULT_WIN;
945 937
@@ -950,32 +942,32 @@ static void mixer_win_mode_set(struct exynos_drm_manager *mgr,
950 942
951 win_data = &mixer_ctx->win_data[win]; 943 win_data = &mixer_ctx->win_data[win];
952 944
953 win_data->dma_addr = overlay->dma_addr[0]; 945 win_data->dma_addr = plane->dma_addr[0];
954 win_data->chroma_dma_addr = overlay->dma_addr[1]; 946 win_data->chroma_dma_addr = plane->dma_addr[1];
955 win_data->pixel_format = overlay->pixel_format; 947 win_data->pixel_format = plane->pixel_format;
956 win_data->bpp = overlay->bpp; 948 win_data->bpp = plane->bpp;
957 949
958 win_data->crtc_x = overlay->crtc_x; 950 win_data->crtc_x = plane->crtc_x;
959 win_data->crtc_y = overlay->crtc_y; 951 win_data->crtc_y = plane->crtc_y;
960 win_data->crtc_width = overlay->crtc_width; 952 win_data->crtc_width = plane->crtc_width;
961 win_data->crtc_height = overlay->crtc_height; 953 win_data->crtc_height = plane->crtc_height;
962 954
963 win_data->fb_x = overlay->fb_x; 955 win_data->fb_x = plane->fb_x;
964 win_data->fb_y = overlay->fb_y; 956 win_data->fb_y = plane->fb_y;
965 win_data->fb_width = overlay->fb_width; 957 win_data->fb_width = plane->fb_width;
966 win_data->fb_height = overlay->fb_height; 958 win_data->fb_height = plane->fb_height;
967 win_data->src_width = overlay->src_width; 959 win_data->src_width = plane->src_width;
968 win_data->src_height = overlay->src_height; 960 win_data->src_height = plane->src_height;
969 961
970 win_data->mode_width = overlay->mode_width; 962 win_data->mode_width = plane->mode_width;
971 win_data->mode_height = overlay->mode_height; 963 win_data->mode_height = plane->mode_height;
972 964
973 win_data->scan_flags = overlay->scan_flag; 965 win_data->scan_flags = plane->scan_flag;
974} 966}
975 967
976static void mixer_win_commit(struct exynos_drm_manager *mgr, int zpos) 968static void mixer_win_commit(struct exynos_drm_crtc *crtc, int zpos)
977{ 969{
978 struct mixer_context *mixer_ctx = mgr_to_mixer(mgr); 970 struct mixer_context *mixer_ctx = crtc->ctx;
979 int win = zpos == DEFAULT_ZPOS ? MIXER_DEFAULT_WIN : zpos; 971 int win = zpos == DEFAULT_ZPOS ? MIXER_DEFAULT_WIN : zpos;
980 972
981 DRM_DEBUG_KMS("win: %d\n", win); 973 DRM_DEBUG_KMS("win: %d\n", win);
@@ -995,9 +987,9 @@ static void mixer_win_commit(struct exynos_drm_manager *mgr, int zpos)
995 mixer_ctx->win_data[win].enabled = true; 987 mixer_ctx->win_data[win].enabled = true;
996} 988}
997 989
998static void mixer_win_disable(struct exynos_drm_manager *mgr, int zpos) 990static void mixer_win_disable(struct exynos_drm_crtc *crtc, int zpos)
999{ 991{
1000 struct mixer_context *mixer_ctx = mgr_to_mixer(mgr); 992 struct mixer_context *mixer_ctx = crtc->ctx;
1001 struct mixer_resources *res = &mixer_ctx->mixer_res; 993 struct mixer_resources *res = &mixer_ctx->mixer_res;
1002 int win = zpos == DEFAULT_ZPOS ? MIXER_DEFAULT_WIN : zpos; 994 int win = zpos == DEFAULT_ZPOS ? MIXER_DEFAULT_WIN : zpos;
1003 unsigned long flags; 995 unsigned long flags;
@@ -1023,9 +1015,9 @@ static void mixer_win_disable(struct exynos_drm_manager *mgr, int zpos)
1023 mixer_ctx->win_data[win].enabled = false; 1015 mixer_ctx->win_data[win].enabled = false;
1024} 1016}
1025 1017
1026static void mixer_wait_for_vblank(struct exynos_drm_manager *mgr) 1018static void mixer_wait_for_vblank(struct exynos_drm_crtc *crtc)
1027{ 1019{
1028 struct mixer_context *mixer_ctx = mgr_to_mixer(mgr); 1020 struct mixer_context *mixer_ctx = crtc->ctx;
1029 int err; 1021 int err;
1030 1022
1031 mutex_lock(&mixer_ctx->mixer_mutex); 1023 mutex_lock(&mixer_ctx->mixer_mutex);
@@ -1035,7 +1027,7 @@ static void mixer_wait_for_vblank(struct exynos_drm_manager *mgr)
1035 } 1027 }
1036 mutex_unlock(&mixer_ctx->mixer_mutex); 1028 mutex_unlock(&mixer_ctx->mixer_mutex);
1037 1029
1038 err = drm_vblank_get(mgr->crtc->dev, mixer_ctx->pipe); 1030 err = drm_vblank_get(mixer_ctx->drm_dev, mixer_ctx->pipe);
1039 if (err < 0) { 1031 if (err < 0) {
1040 DRM_DEBUG_KMS("failed to acquire vblank counter\n"); 1032 DRM_DEBUG_KMS("failed to acquire vblank counter\n");
1041 return; 1033 return;
@@ -1052,26 +1044,26 @@ static void mixer_wait_for_vblank(struct exynos_drm_manager *mgr)
1052 HZ/20)) 1044 HZ/20))
1053 DRM_DEBUG_KMS("vblank wait timed out.\n"); 1045 DRM_DEBUG_KMS("vblank wait timed out.\n");
1054 1046
1055 drm_vblank_put(mgr->crtc->dev, mixer_ctx->pipe); 1047 drm_vblank_put(mixer_ctx->drm_dev, mixer_ctx->pipe);
1056} 1048}
1057 1049
1058static void mixer_window_suspend(struct exynos_drm_manager *mgr) 1050static void mixer_window_suspend(struct exynos_drm_crtc *crtc)
1059{ 1051{
1060 struct mixer_context *ctx = mgr_to_mixer(mgr); 1052 struct mixer_context *ctx = crtc->ctx;
1061 struct hdmi_win_data *win_data; 1053 struct hdmi_win_data *win_data;
1062 int i; 1054 int i;
1063 1055
1064 for (i = 0; i < MIXER_WIN_NR; i++) { 1056 for (i = 0; i < MIXER_WIN_NR; i++) {
1065 win_data = &ctx->win_data[i]; 1057 win_data = &ctx->win_data[i];
1066 win_data->resume = win_data->enabled; 1058 win_data->resume = win_data->enabled;
1067 mixer_win_disable(mgr, i); 1059 mixer_win_disable(crtc, i);
1068 } 1060 }
1069 mixer_wait_for_vblank(mgr); 1061 mixer_wait_for_vblank(crtc);
1070} 1062}
1071 1063
1072static void mixer_window_resume(struct exynos_drm_manager *mgr) 1064static void mixer_window_resume(struct exynos_drm_crtc *crtc)
1073{ 1065{
1074 struct mixer_context *ctx = mgr_to_mixer(mgr); 1066 struct mixer_context *ctx = crtc->ctx;
1075 struct hdmi_win_data *win_data; 1067 struct hdmi_win_data *win_data;
1076 int i; 1068 int i;
1077 1069
@@ -1080,13 +1072,13 @@ static void mixer_window_resume(struct exynos_drm_manager *mgr)
1080 win_data->enabled = win_data->resume; 1072 win_data->enabled = win_data->resume;
1081 win_data->resume = false; 1073 win_data->resume = false;
1082 if (win_data->enabled) 1074 if (win_data->enabled)
1083 mixer_win_commit(mgr, i); 1075 mixer_win_commit(crtc, i);
1084 } 1076 }
1085} 1077}
1086 1078
1087static void mixer_poweron(struct exynos_drm_manager *mgr) 1079static void mixer_poweron(struct exynos_drm_crtc *crtc)
1088{ 1080{
1089 struct mixer_context *ctx = mgr_to_mixer(mgr); 1081 struct mixer_context *ctx = crtc->ctx;
1090 struct mixer_resources *res = &ctx->mixer_res; 1082 struct mixer_resources *res = &ctx->mixer_res;
1091 1083
1092 mutex_lock(&ctx->mixer_mutex); 1084 mutex_lock(&ctx->mixer_mutex);
@@ -1115,12 +1107,12 @@ static void mixer_poweron(struct exynos_drm_manager *mgr)
1115 mixer_reg_write(res, MXR_INT_EN, ctx->int_en); 1107 mixer_reg_write(res, MXR_INT_EN, ctx->int_en);
1116 mixer_win_reset(ctx); 1108 mixer_win_reset(ctx);
1117 1109
1118 mixer_window_resume(mgr); 1110 mixer_window_resume(crtc);
1119} 1111}
1120 1112
1121static void mixer_poweroff(struct exynos_drm_manager *mgr) 1113static void mixer_poweroff(struct exynos_drm_crtc *crtc)
1122{ 1114{
1123 struct mixer_context *ctx = mgr_to_mixer(mgr); 1115 struct mixer_context *ctx = crtc->ctx;
1124 struct mixer_resources *res = &ctx->mixer_res; 1116 struct mixer_resources *res = &ctx->mixer_res;
1125 1117
1126 mutex_lock(&ctx->mixer_mutex); 1118 mutex_lock(&ctx->mixer_mutex);
@@ -1131,7 +1123,7 @@ static void mixer_poweroff(struct exynos_drm_manager *mgr)
1131 mutex_unlock(&ctx->mixer_mutex); 1123 mutex_unlock(&ctx->mixer_mutex);
1132 1124
1133 mixer_stop(ctx); 1125 mixer_stop(ctx);
1134 mixer_window_suspend(mgr); 1126 mixer_window_suspend(crtc);
1135 1127
1136 ctx->int_en = mixer_reg_read(res, MXR_INT_EN); 1128 ctx->int_en = mixer_reg_read(res, MXR_INT_EN);
1137 1129
@@ -1149,16 +1141,16 @@ static void mixer_poweroff(struct exynos_drm_manager *mgr)
1149 pm_runtime_put_sync(ctx->dev); 1141 pm_runtime_put_sync(ctx->dev);
1150} 1142}
1151 1143
1152static void mixer_dpms(struct exynos_drm_manager *mgr, int mode) 1144static void mixer_dpms(struct exynos_drm_crtc *crtc, int mode)
1153{ 1145{
1154 switch (mode) { 1146 switch (mode) {
1155 case DRM_MODE_DPMS_ON: 1147 case DRM_MODE_DPMS_ON:
1156 mixer_poweron(mgr); 1148 mixer_poweron(crtc);
1157 break; 1149 break;
1158 case DRM_MODE_DPMS_STANDBY: 1150 case DRM_MODE_DPMS_STANDBY:
1159 case DRM_MODE_DPMS_SUSPEND: 1151 case DRM_MODE_DPMS_SUSPEND:
1160 case DRM_MODE_DPMS_OFF: 1152 case DRM_MODE_DPMS_OFF:
1161 mixer_poweroff(mgr); 1153 mixer_poweroff(crtc);
1162 break; 1154 break;
1163 default: 1155 default:
1164 DRM_DEBUG_KMS("unknown dpms mode: %d\n", mode); 1156 DRM_DEBUG_KMS("unknown dpms mode: %d\n", mode);
@@ -1186,7 +1178,7 @@ int mixer_check_mode(struct drm_display_mode *mode)
1186 return -EINVAL; 1178 return -EINVAL;
1187} 1179}
1188 1180
1189static struct exynos_drm_manager_ops mixer_manager_ops = { 1181static struct exynos_drm_crtc_ops mixer_crtc_ops = {
1190 .dpms = mixer_dpms, 1182 .dpms = mixer_dpms,
1191 .enable_vblank = mixer_enable_vblank, 1183 .enable_vblank = mixer_enable_vblank,
1192 .disable_vblank = mixer_disable_vblank, 1184 .disable_vblank = mixer_disable_vblank,
@@ -1257,24 +1249,30 @@ static int mixer_bind(struct device *dev, struct device *manager, void *data)
1257 struct drm_device *drm_dev = data; 1249 struct drm_device *drm_dev = data;
1258 int ret; 1250 int ret;
1259 1251
1260 ret = mixer_initialize(&ctx->manager, drm_dev); 1252 ctx->crtc = exynos_drm_crtc_create(drm_dev, ctx->pipe,
1261 if (ret) 1253 EXYNOS_DISPLAY_TYPE_HDMI,
1262 return ret; 1254 &mixer_crtc_ops, ctx);
1263 1255 if (IS_ERR(ctx->crtc)) {
1264 ret = exynos_drm_crtc_create(&ctx->manager); 1256 ret = PTR_ERR(ctx->crtc);
1265 if (ret) { 1257 goto free_ctx;
1266 mixer_mgr_remove(&ctx->manager);
1267 return ret;
1268 } 1258 }
1269 1259
1260 ret = mixer_initialize(ctx, drm_dev);
1261 if (ret)
1262 goto free_ctx;
1263
1270 return 0; 1264 return 0;
1265
1266free_ctx:
1267 devm_kfree(dev, ctx);
1268 return ret;
1271} 1269}
1272 1270
1273static void mixer_unbind(struct device *dev, struct device *master, void *data) 1271static void mixer_unbind(struct device *dev, struct device *master, void *data)
1274{ 1272{
1275 struct mixer_context *ctx = dev_get_drvdata(dev); 1273 struct mixer_context *ctx = dev_get_drvdata(dev);
1276 1274
1277 mixer_mgr_remove(&ctx->manager); 1275 mixer_ctx_remove(ctx);
1278} 1276}
1279 1277
1280static const struct component_ops mixer_component_ops = { 1278static const struct component_ops mixer_component_ops = {
@@ -1297,9 +1295,6 @@ static int mixer_probe(struct platform_device *pdev)
1297 1295
1298 mutex_init(&ctx->mixer_mutex); 1296 mutex_init(&ctx->mixer_mutex);
1299 1297
1300 ctx->manager.type = EXYNOS_DISPLAY_TYPE_HDMI;
1301 ctx->manager.ops = &mixer_manager_ops;
1302
1303 if (dev->of_node) { 1298 if (dev->of_node) {
1304 const struct of_device_id *match; 1299 const struct of_device_id *match;
1305 1300
@@ -1321,7 +1316,7 @@ static int mixer_probe(struct platform_device *pdev)
1321 platform_set_drvdata(pdev, ctx); 1316 platform_set_drvdata(pdev, ctx);
1322 1317
1323 ret = exynos_drm_component_add(&pdev->dev, EXYNOS_DEVICE_TYPE_CRTC, 1318 ret = exynos_drm_component_add(&pdev->dev, EXYNOS_DEVICE_TYPE_CRTC,
1324 ctx->manager.type); 1319 EXYNOS_DISPLAY_TYPE_HDMI);
1325 if (ret) 1320 if (ret)
1326 return ret; 1321 return ret;
1327 1322