diff options
-rw-r--r-- | drivers/gpu/drm/exynos/exynos_drm_crtc.c | 185 | ||||
-rw-r--r-- | drivers/gpu/drm/exynos/exynos_drm_crtc.h | 8 | ||||
-rw-r--r-- | drivers/gpu/drm/exynos/exynos_drm_drv.h | 83 | ||||
-rw-r--r-- | drivers/gpu/drm/exynos/exynos_drm_fimd.c | 196 | ||||
-rw-r--r-- | drivers/gpu/drm/exynos/exynos_drm_plane.c | 138 | ||||
-rw-r--r-- | drivers/gpu/drm/exynos/exynos_drm_plane.h | 17 | ||||
-rw-r--r-- | drivers/gpu/drm/exynos/exynos_drm_vidi.c | 135 | ||||
-rw-r--r-- | drivers/gpu/drm/exynos/exynos_mixer.c | 159 |
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 | |||
26 | enum 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 | */ | ||
46 | struct 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 | |||
56 | static void exynos_drm_crtc_dpms(struct drm_crtc *crtc, int mode) | 23 | static 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) | |||
91 | static void exynos_drm_crtc_commit(struct drm_crtc *crtc) | 57 | static 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 | ||
147 | static int exynos_drm_crtc_mode_set_commit(struct drm_crtc *crtc, int x, int y, | 115 | static 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 | |||
175 | static 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 | ||
181 | static void exynos_drm_crtc_disable(struct drm_crtc *crtc) | 136 | static 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 | ||
342 | int exynos_drm_crtc_create(struct exynos_drm_manager *manager) | 301 | struct 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 | ||
383 | err_crtc: | 347 | err_crtc: |
384 | plane->funcs->destroy(plane); | 348 | plane->funcs->destroy(plane); |
385 | err_plane: | 349 | err_plane: |
386 | kfree(exynos_crtc); | 350 | kfree(exynos_crtc); |
387 | return ret; | 351 | return ERR_PTR(ret); |
388 | } | 352 | } |
389 | 353 | ||
390 | int exynos_drm_crtc_enable_vblank(struct drm_device *dev, int pipe) | 354 | int 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 | ||
420 | void exynos_drm_crtc_finish_pageflip(struct drm_device *dev, int pipe) | 382 | void 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 | ||
446 | void 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 | |||
455 | void 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 | |||
463 | void 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 | |||
471 | void 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 | |||
479 | void exynos_drm_crtc_complete_scanout(struct drm_framebuffer *fb) | 408 | void 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 | ||
518 | void exynos_drm_crtc_te_handler(struct drm_crtc *crtc) | 447 | void 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 | ||
20 | int exynos_drm_crtc_create(struct exynos_drm_manager *manager); | 20 | struct 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); | ||
21 | int exynos_drm_crtc_enable_vblank(struct drm_device *dev, int pipe); | 25 | int exynos_drm_crtc_enable_vblank(struct drm_device *dev, int pipe); |
22 | void exynos_drm_crtc_disable_vblank(struct drm_device *dev, int pipe); | 26 | void exynos_drm_crtc_disable_vblank(struct drm_device *dev, int pipe); |
23 | void exynos_drm_crtc_finish_pageflip(struct drm_device *dev, int pipe); | 27 | void exynos_drm_crtc_finish_pageflip(struct drm_device *dev, int pipe); |
24 | void exynos_drm_crtc_complete_scanout(struct drm_framebuffer *fb); | 28 | void exynos_drm_crtc_complete_scanout(struct drm_framebuffer *fb); |
25 | 29 | ||
26 | void exynos_drm_crtc_plane_mode_set(struct drm_crtc *crtc, | 30 | void exynos_drm_crtc_plane_mode_set(struct drm_crtc *crtc, |
27 | struct exynos_drm_overlay *overlay); | 31 | struct exynos_drm_plane *plane); |
28 | void exynos_drm_crtc_plane_commit(struct drm_crtc *crtc, int zpos); | 32 | void exynos_drm_crtc_plane_commit(struct drm_crtc *crtc, int zpos); |
29 | void exynos_drm_crtc_plane_enable(struct drm_crtc *crtc, int zpos); | 33 | void exynos_drm_crtc_plane_enable(struct drm_crtc *crtc, int zpos); |
30 | void exynos_drm_crtc_plane_disable(struct drm_crtc *crtc, int zpos); | 34 | void 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. */ |
27 | enum exynos_drm_device_type { | 30 | enum 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 | */ |
80 | struct exynos_drm_overlay { | 85 | |
86 | struct 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 | */ |
175 | struct exynos_drm_manager; | 182 | struct exynos_drm_crtc; |
176 | struct exynos_drm_manager_ops { | 183 | struct 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 | |
200 | enum 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 | */ |
206 | struct exynos_drm_manager { | 222 | struct 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 | ||
215 | struct exynos_drm_g2d_private { | 234 | struct 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 | ||
159 | struct fimd_context { | 159 | struct 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 | ||
188 | static inline struct fimd_context *mgr_to_fimd(struct exynos_drm_manager *mgr) | ||
189 | { | ||
190 | return container_of(mgr, struct fimd_context, manager); | ||
191 | } | ||
192 | |||
193 | static const struct of_device_id fimd_driver_dt_match[] = { | 187 | static 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 | ||
217 | static void fimd_wait_for_vblank(struct exynos_drm_manager *mgr) | 211 | static 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 | ||
262 | static void fimd_clear_channel(struct exynos_drm_manager *mgr) | 256 | static 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 | ||
294 | static int fimd_mgr_initialize(struct exynos_drm_manager *mgr, | 288 | static 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 | ||
317 | static void fimd_mgr_remove(struct exynos_drm_manager *mgr) | 317 | static 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 | ||
346 | static bool fimd_mode_fixup(struct exynos_drm_manager *mgr, | 344 | static 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 | ||
356 | static void fimd_mode_set(struct exynos_drm_manager *mgr, | 354 | static 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 | |||
364 | static 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 | ||
464 | static int fimd_enable_vblank(struct exynos_drm_manager *mgr) | 454 | static 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 | ||
496 | static void fimd_disable_vblank(struct exynos_drm_manager *mgr) | 486 | static 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 | ||
520 | static void fimd_win_mode_set(struct exynos_drm_manager *mgr, | 510 | static 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 | ||
569 | static void fimd_win_set_pixfmt(struct fimd_context *ctx, unsigned int win) | 559 | static 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 | ||
679 | static void fimd_win_commit(struct exynos_drm_manager *mgr, int zpos) | 669 | static 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 | ||
802 | static void fimd_win_disable(struct exynos_drm_manager *mgr, int zpos) | 792 | static 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 | ||
836 | static void fimd_window_suspend(struct exynos_drm_manager *mgr) | 826 | static 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 | ||
850 | static void fimd_window_resume(struct exynos_drm_manager *mgr) | 840 | static 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 | ||
863 | static void fimd_apply(struct exynos_drm_manager *mgr) | 853 | static 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 | ||
880 | static int fimd_poweron(struct exynos_drm_manager *mgr) | 870 | static 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 | ||
928 | static int fimd_poweroff(struct exynos_drm_manager *mgr) | 918 | static 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 | ||
951 | static void fimd_dpms(struct exynos_drm_manager *mgr, int mode) | 941 | static 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 | ||
999 | static void fimd_te_handler(struct exynos_drm_manager *mgr) | 989 | static 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 | ||
1024 | static struct exynos_drm_manager_ops fimd_manager_ops = { | 1014 | static 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 | ||
1100 | static const struct component_ops fimd_component_ops = { | 1101 | static 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 | |||
23 | struct exynos_plane { | ||
24 | struct drm_plane base; | ||
25 | struct exynos_drm_overlay overlay; | ||
26 | bool enabled; | ||
27 | }; | ||
28 | |||
29 | static const uint32_t formats[] = { | 22 | static 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 | ||
72 | int exynos_plane_mode_set(struct drm_plane *plane, struct drm_crtc *crtc, | 65 | int 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 | |||
89 | void 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 | |||
149 | void 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 | ||
157 | void exynos_plane_dpms(struct drm_plane *plane, int mode) | 148 | void 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 | ||
177 | static int | 174 | int |
178 | exynos_update_plane(struct drm_plane *plane, struct drm_crtc *crtc, | 175 | exynos_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 | ||
205 | static void exynos_plane_destroy(struct drm_plane *plane) | 207 | static 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 | ||
12 | int exynos_plane_mode_set(struct drm_plane *plane, struct drm_crtc *crtc, | 12 | int exynos_check_plane(struct drm_plane *plane, struct drm_framebuffer *fb); |
13 | struct drm_framebuffer *fb, int crtc_x, int crtc_y, | 13 | void 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, |
17 | void exynos_plane_commit(struct drm_plane *plane); | 17 | uint32_t src_w, uint32_t src_h); |
18 | int 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); | ||
18 | void exynos_plane_dpms(struct drm_plane *plane, int mode); | 23 | void exynos_plane_dpms(struct drm_plane *plane, int mode); |
19 | struct drm_plane *exynos_plane_init(struct drm_device *dev, | 24 | struct 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 | ||
49 | struct vidi_context { | 49 | struct 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 | ||
71 | static inline struct vidi_context *manager_to_vidi(struct exynos_drm_manager *m) | ||
72 | { | ||
73 | return container_of(m, struct vidi_context, manager); | ||
74 | } | ||
75 | |||
76 | static inline struct vidi_context *display_to_vidi(struct exynos_drm_display *d) | 70 | static 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 | ||
106 | static void vidi_apply(struct exynos_drm_manager *mgr) | 100 | static 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 | |||
123 | static 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 | ||
131 | static int vidi_enable_vblank(struct exynos_drm_manager *mgr) | 114 | static 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 | ||
153 | static void vidi_disable_vblank(struct exynos_drm_manager *mgr) | 136 | static 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 | ||
164 | static void vidi_win_mode_set(struct exynos_drm_manager *mgr, | 147 | static 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 | ||
217 | static void vidi_win_commit(struct exynos_drm_manager *mgr, int zpos) | 200 | static 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 | ||
242 | static void vidi_win_disable(struct exynos_drm_manager *mgr, int zpos) | 225 | static 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 | ||
260 | static int vidi_power_on(struct exynos_drm_manager *mgr, bool enable) | 243 | static 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 | ||
284 | static void vidi_dpms(struct exynos_drm_manager *mgr, int mode) | 267 | static 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 | ||
309 | static int vidi_mgr_initialize(struct exynos_drm_manager *mgr, | 292 | static 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 | ||
321 | static struct exynos_drm_manager_ops vidi_manager_ops = { | 303 | static 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 | ||
86 | struct mixer_context { | 86 | struct 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 | ||
106 | static inline struct mixer_context *mgr_to_mixer(struct exynos_drm_manager *mgr) | ||
107 | { | ||
108 | return container_of(mgr, struct mixer_context, manager); | ||
109 | } | ||
110 | |||
111 | struct mixer_drv_data { | 106 | struct 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 | ||
857 | static int mixer_initialize(struct exynos_drm_manager *mgr, | 852 | static 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 | ||
890 | static void mixer_mgr_remove(struct exynos_drm_manager *mgr) | 884 | static 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 | ||
898 | static int mixer_enable_vblank(struct exynos_drm_manager *mgr) | 890 | static 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 | ||
915 | static void mixer_disable_vblank(struct exynos_drm_manager *mgr) | 907 | static 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 | ||
924 | static void mixer_win_mode_set(struct exynos_drm_manager *mgr, | 916 | static 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 | ||
976 | static void mixer_win_commit(struct exynos_drm_manager *mgr, int zpos) | 968 | static 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 | ||
998 | static void mixer_win_disable(struct exynos_drm_manager *mgr, int zpos) | 990 | static 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 | ||
1026 | static void mixer_wait_for_vblank(struct exynos_drm_manager *mgr) | 1018 | static 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 | ||
1058 | static void mixer_window_suspend(struct exynos_drm_manager *mgr) | 1050 | static 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 | ||
1072 | static void mixer_window_resume(struct exynos_drm_manager *mgr) | 1064 | static 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 | ||
1087 | static void mixer_poweron(struct exynos_drm_manager *mgr) | 1079 | static 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 | ||
1121 | static void mixer_poweroff(struct exynos_drm_manager *mgr) | 1113 | static 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 | ||
1152 | static void mixer_dpms(struct exynos_drm_manager *mgr, int mode) | 1144 | static 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 | ||
1189 | static struct exynos_drm_manager_ops mixer_manager_ops = { | 1181 | static 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 | |||
1266 | free_ctx: | ||
1267 | devm_kfree(dev, ctx); | ||
1268 | return ret; | ||
1271 | } | 1269 | } |
1272 | 1270 | ||
1273 | static void mixer_unbind(struct device *dev, struct device *master, void *data) | 1271 | static 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 | ||
1280 | static const struct component_ops mixer_component_ops = { | 1278 | static 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 | ||