aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/gpu/drm/exynos
diff options
context:
space:
mode:
authorGustavo Padovan <gustavo.padovan@collabora.co.uk>2015-04-03 08:03:40 -0400
committerInki Dae <inki.dae@samsung.com>2015-04-12 22:39:39 -0400
commit7ee14cdcbc4f813b9c5875d6e8e3daef71c366b3 (patch)
tree2c65b033db13c2ed7175f511fc773dfa6a5ee812 /drivers/gpu/drm/exynos
parent1be4b7ee800a57ca613131304e01cd91ec8bca2a (diff)
drm/exynos: remove struct *_win_data abstraction on planes
struct {fimd,mixer,vidi}_win_data was just keeping the same data as struct exynos_drm_plane thus get ride of it and use exynos_drm_plane directly. It changes how planes are created and remove .win_mode_set() callback that was only filling all *_win_data structs. v2: check for return of exynos_plane_init() Signed-off-by: Gustavo Padovan <gustavo.padovan@collabora.co.uk> Signed-off-by: Inki Dae <inki.dae@samsung.com>
Diffstat (limited to 'drivers/gpu/drm/exynos')
-rw-r--r--drivers/gpu/drm/exynos/exynos7_drm_decon.c166
-rw-r--r--drivers/gpu/drm/exynos/exynos_drm_crtc.c9
-rw-r--r--drivers/gpu/drm/exynos/exynos_drm_crtc.h1
-rw-r--r--drivers/gpu/drm/exynos/exynos_drm_drv.c14
-rw-r--r--drivers/gpu/drm/exynos/exynos_drm_drv.h5
-rw-r--r--drivers/gpu/drm/exynos/exynos_drm_fimd.c186
-rw-r--r--drivers/gpu/drm/exynos/exynos_drm_plane.c23
-rw-r--r--drivers/gpu/drm/exynos/exynos_drm_plane.h6
-rw-r--r--drivers/gpu/drm/exynos/exynos_drm_vidi.c125
-rw-r--r--drivers/gpu/drm/exynos/exynos_mixer.c216
10 files changed, 250 insertions, 501 deletions
diff --git a/drivers/gpu/drm/exynos/exynos7_drm_decon.c b/drivers/gpu/drm/exynos/exynos7_drm_decon.c
index 970046199608..c5dfd99653d8 100644
--- a/drivers/gpu/drm/exynos/exynos7_drm_decon.c
+++ b/drivers/gpu/drm/exynos/exynos7_drm_decon.c
@@ -28,6 +28,7 @@
28#include <video/exynos7_decon.h> 28#include <video/exynos7_decon.h>
29 29
30#include "exynos_drm_crtc.h" 30#include "exynos_drm_crtc.h"
31#include "exynos_drm_plane.h"
31#include "exynos_drm_drv.h" 32#include "exynos_drm_drv.h"
32#include "exynos_drm_fbdev.h" 33#include "exynos_drm_fbdev.h"
33#include "exynos_drm_iommu.h" 34#include "exynos_drm_iommu.h"
@@ -41,32 +42,16 @@
41 42
42#define WINDOWS_NR 2 43#define WINDOWS_NR 2
43 44
44struct decon_win_data {
45 unsigned int ovl_x;
46 unsigned int ovl_y;
47 unsigned int offset_x;
48 unsigned int offset_y;
49 unsigned int ovl_width;
50 unsigned int ovl_height;
51 unsigned int fb_width;
52 unsigned int fb_height;
53 unsigned int bpp;
54 unsigned int pixel_format;
55 dma_addr_t dma_addr;
56 bool enabled;
57 bool resume;
58};
59
60struct decon_context { 45struct decon_context {
61 struct device *dev; 46 struct device *dev;
62 struct drm_device *drm_dev; 47 struct drm_device *drm_dev;
63 struct exynos_drm_crtc *crtc; 48 struct exynos_drm_crtc *crtc;
49 struct exynos_drm_plane planes[WINDOWS_NR];
64 struct clk *pclk; 50 struct clk *pclk;
65 struct clk *aclk; 51 struct clk *aclk;
66 struct clk *eclk; 52 struct clk *eclk;
67 struct clk *vclk; 53 struct clk *vclk;
68 void __iomem *regs; 54 void __iomem *regs;
69 struct decon_win_data win_data[WINDOWS_NR];
70 unsigned int default_win; 55 unsigned int default_win;
71 unsigned long irq_flags; 56 unsigned long irq_flags;
72 bool i80_if; 57 bool i80_if;
@@ -296,59 +281,16 @@ static void decon_disable_vblank(struct exynos_drm_crtc *crtc)
296 } 281 }
297} 282}
298 283
299static void decon_win_mode_set(struct exynos_drm_crtc *crtc,
300 struct exynos_drm_plane *plane)
301{
302 struct decon_context *ctx = crtc->ctx;
303 struct decon_win_data *win_data;
304 int win, padding;
305
306 if (!plane) {
307 DRM_ERROR("plane is NULL\n");
308 return;
309 }
310
311 win = plane->zpos;
312 if (win == DEFAULT_ZPOS)
313 win = ctx->default_win;
314
315 if (win < 0 || win >= WINDOWS_NR)
316 return;
317
318
319 win_data = &ctx->win_data[win];
320
321 padding = (plane->pitch / (plane->bpp >> 3)) - plane->fb_width;
322 win_data->offset_x = plane->fb_x;
323 win_data->offset_y = plane->fb_y;
324 win_data->fb_width = plane->fb_width + padding;
325 win_data->fb_height = plane->fb_height;
326 win_data->ovl_x = plane->crtc_x;
327 win_data->ovl_y = plane->crtc_y;
328 win_data->ovl_width = plane->crtc_width;
329 win_data->ovl_height = plane->crtc_height;
330 win_data->dma_addr = plane->dma_addr[0];
331 win_data->bpp = plane->bpp;
332 win_data->pixel_format = plane->pixel_format;
333
334 DRM_DEBUG_KMS("offset_x = %d, offset_y = %d\n",
335 win_data->offset_x, win_data->offset_y);
336 DRM_DEBUG_KMS("ovl_width = %d, ovl_height = %d\n",
337 win_data->ovl_width, win_data->ovl_height);
338 DRM_DEBUG_KMS("paddr = 0x%lx\n", (unsigned long)win_data->dma_addr);
339 DRM_DEBUG_KMS("fb_width = %d, crtc_width = %d\n",
340 plane->fb_width, plane->crtc_width);
341}
342
343static void decon_win_set_pixfmt(struct decon_context *ctx, unsigned int win) 284static void decon_win_set_pixfmt(struct decon_context *ctx, unsigned int win)
344{ 285{
345 struct decon_win_data *win_data = &ctx->win_data[win]; 286 struct exynos_drm_plane *plane = &ctx->planes[win];
346 unsigned long val; 287 unsigned long val;
288 int padding;
347 289
348 val = readl(ctx->regs + WINCON(win)); 290 val = readl(ctx->regs + WINCON(win));
349 val &= ~WINCONx_BPPMODE_MASK; 291 val &= ~WINCONx_BPPMODE_MASK;
350 292
351 switch (win_data->pixel_format) { 293 switch (plane->pixel_format) {
352 case DRM_FORMAT_RGB565: 294 case DRM_FORMAT_RGB565:
353 val |= WINCONx_BPPMODE_16BPP_565; 295 val |= WINCONx_BPPMODE_16BPP_565;
354 val |= WINCONx_BURSTLEN_16WORD; 296 val |= WINCONx_BURSTLEN_16WORD;
@@ -397,7 +339,7 @@ static void decon_win_set_pixfmt(struct decon_context *ctx, unsigned int win)
397 break; 339 break;
398 } 340 }
399 341
400 DRM_DEBUG_KMS("bpp = %d\n", win_data->bpp); 342 DRM_DEBUG_KMS("bpp = %d\n", plane->bpp);
401 343
402 /* 344 /*
403 * In case of exynos, setting dma-burst to 16Word causes permanent 345 * In case of exynos, setting dma-burst to 16Word causes permanent
@@ -407,7 +349,8 @@ static void decon_win_set_pixfmt(struct decon_context *ctx, unsigned int win)
407 * movement causes unstable DMA which results into iommu crash/tear. 349 * movement causes unstable DMA which results into iommu crash/tear.
408 */ 350 */
409 351
410 if (win_data->fb_width < MIN_FB_WIDTH_FOR_16WORD_BURST) { 352 padding = (plane->pitch / (plane->bpp >> 3)) - plane->fb_width;
353 if (plane->fb_width + padding < MIN_FB_WIDTH_FOR_16WORD_BURST) {
411 val &= ~WINCONx_BURSTLEN_MASK; 354 val &= ~WINCONx_BURSTLEN_MASK;
412 val |= WINCONx_BURSTLEN_8WORD; 355 val |= WINCONx_BURSTLEN_8WORD;
413 } 356 }
@@ -453,8 +396,8 @@ static void decon_win_commit(struct exynos_drm_crtc *crtc, int zpos)
453{ 396{
454 struct decon_context *ctx = crtc->ctx; 397 struct decon_context *ctx = crtc->ctx;
455 struct drm_display_mode *mode = &crtc->base.mode; 398 struct drm_display_mode *mode = &crtc->base.mode;
456 struct decon_win_data *win_data; 399 struct exynos_drm_plane *plane;
457 int win = zpos; 400 int padding, win = zpos;
458 unsigned long val, alpha; 401 unsigned long val, alpha;
459 unsigned int last_x; 402 unsigned int last_x;
460 unsigned int last_y; 403 unsigned int last_y;
@@ -468,11 +411,11 @@ static void decon_win_commit(struct exynos_drm_crtc *crtc, int zpos)
468 if (win < 0 || win >= WINDOWS_NR) 411 if (win < 0 || win >= WINDOWS_NR)
469 return; 412 return;
470 413
471 win_data = &ctx->win_data[win]; 414 plane = &ctx->planes[win];
472 415
473 /* If suspended, enable this on resume */ 416 /* If suspended, enable this on resume */
474 if (ctx->suspended) { 417 if (ctx->suspended) {
475 win_data->resume = true; 418 plane->resume = true;
476 return; 419 return;
477 } 420 }
478 421
@@ -490,39 +433,41 @@ static void decon_win_commit(struct exynos_drm_crtc *crtc, int zpos)
490 decon_shadow_protect_win(ctx, win, true); 433 decon_shadow_protect_win(ctx, win, true);
491 434
492 /* buffer start address */ 435 /* buffer start address */
493 val = (unsigned long)win_data->dma_addr; 436 val = (unsigned long)plane->dma_addr[0];
494 writel(val, ctx->regs + VIDW_BUF_START(win)); 437 writel(val, ctx->regs + VIDW_BUF_START(win));
495 438
439 padding = (plane->pitch / (plane->bpp >> 3)) - plane->fb_width;
440
496 /* buffer size */ 441 /* buffer size */
497 writel(win_data->fb_width, ctx->regs + VIDW_WHOLE_X(win)); 442 writel(plane->fb_width + padding, ctx->regs + VIDW_WHOLE_X(win));
498 writel(win_data->fb_height, ctx->regs + VIDW_WHOLE_Y(win)); 443 writel(plane->fb_height, ctx->regs + VIDW_WHOLE_Y(win));
499 444
500 /* offset from the start of the buffer to read */ 445 /* offset from the start of the buffer to read */
501 writel(win_data->offset_x, ctx->regs + VIDW_OFFSET_X(win)); 446 writel(plane->fb_x, ctx->regs + VIDW_OFFSET_X(win));
502 writel(win_data->offset_y, ctx->regs + VIDW_OFFSET_Y(win)); 447 writel(plane->fb_y, ctx->regs + VIDW_OFFSET_Y(win));
503 448
504 DRM_DEBUG_KMS("start addr = 0x%lx\n", 449 DRM_DEBUG_KMS("start addr = 0x%lx\n",
505 (unsigned long)win_data->dma_addr); 450 (unsigned long)val);
506 DRM_DEBUG_KMS("ovl_width = %d, ovl_height = %d\n", 451 DRM_DEBUG_KMS("ovl_width = %d, ovl_height = %d\n",
507 win_data->ovl_width, win_data->ovl_height); 452 plane->crtc_width, plane->crtc_height);
508 453
509 /* 454 /*
510 * OSD position. 455 * OSD position.
511 * In case the window layout goes of LCD layout, DECON fails. 456 * In case the window layout goes of LCD layout, DECON fails.
512 */ 457 */
513 if ((win_data->ovl_x + win_data->ovl_width) > mode->hdisplay) 458 if ((plane->crtc_x + plane->crtc_width) > mode->hdisplay)
514 win_data->ovl_x = mode->hdisplay - win_data->ovl_width; 459 plane->crtc_x = mode->hdisplay - plane->crtc_width;
515 if ((win_data->ovl_y + win_data->ovl_height) > mode->vdisplay) 460 if ((plane->crtc_y + plane->crtc_height) > mode->vdisplay)
516 win_data->ovl_y = mode->vdisplay - win_data->ovl_height; 461 plane->crtc_y = mode->vdisplay - plane->crtc_height;
517 462
518 val = VIDOSDxA_TOPLEFT_X(win_data->ovl_x) | 463 val = VIDOSDxA_TOPLEFT_X(plane->crtc_x) |
519 VIDOSDxA_TOPLEFT_Y(win_data->ovl_y); 464 VIDOSDxA_TOPLEFT_Y(plane->crtc_y);
520 writel(val, ctx->regs + VIDOSD_A(win)); 465 writel(val, ctx->regs + VIDOSD_A(win));
521 466
522 last_x = win_data->ovl_x + win_data->ovl_width; 467 last_x = plane->crtc_x + plane->crtc_width;
523 if (last_x) 468 if (last_x)
524 last_x--; 469 last_x--;
525 last_y = win_data->ovl_y + win_data->ovl_height; 470 last_y = plane->crtc_y + plane->crtc_height;
526 if (last_y) 471 if (last_y)
527 last_y--; 472 last_y--;
528 473
@@ -531,7 +476,7 @@ static void decon_win_commit(struct exynos_drm_crtc *crtc, int zpos)
531 writel(val, ctx->regs + VIDOSD_B(win)); 476 writel(val, ctx->regs + VIDOSD_B(win));
532 477
533 DRM_DEBUG_KMS("osd pos: tx = %d, ty = %d, bx = %d, by = %d\n", 478 DRM_DEBUG_KMS("osd pos: tx = %d, ty = %d, bx = %d, by = %d\n",
534 win_data->ovl_x, win_data->ovl_y, last_x, last_y); 479 plane->crtc_x, plane->crtc_y, last_x, last_y);
535 480
536 /* OSD alpha */ 481 /* OSD alpha */
537 alpha = VIDOSDxC_ALPHA0_R_F(0x0) | 482 alpha = VIDOSDxC_ALPHA0_R_F(0x0) |
@@ -565,13 +510,13 @@ static void decon_win_commit(struct exynos_drm_crtc *crtc, int zpos)
565 val |= DECON_UPDATE_STANDALONE_F; 510 val |= DECON_UPDATE_STANDALONE_F;
566 writel(val, ctx->regs + DECON_UPDATE); 511 writel(val, ctx->regs + DECON_UPDATE);
567 512
568 win_data->enabled = true; 513 plane->enabled = true;
569} 514}
570 515
571static void decon_win_disable(struct exynos_drm_crtc *crtc, int zpos) 516static void decon_win_disable(struct exynos_drm_crtc *crtc, int zpos)
572{ 517{
573 struct decon_context *ctx = crtc->ctx; 518 struct decon_context *ctx = crtc->ctx;
574 struct decon_win_data *win_data; 519 struct exynos_drm_plane *plane;
575 int win = zpos; 520 int win = zpos;
576 u32 val; 521 u32 val;
577 522
@@ -581,11 +526,11 @@ static void decon_win_disable(struct exynos_drm_crtc *crtc, int zpos)
581 if (win < 0 || win >= WINDOWS_NR) 526 if (win < 0 || win >= WINDOWS_NR)
582 return; 527 return;
583 528
584 win_data = &ctx->win_data[win]; 529 plane = &ctx->planes[win];
585 530
586 if (ctx->suspended) { 531 if (ctx->suspended) {
587 /* do not resume this window*/ 532 /* do not resume this window*/
588 win_data->resume = false; 533 plane->resume = false;
589 return; 534 return;
590 } 535 }
591 536
@@ -604,42 +549,42 @@ static void decon_win_disable(struct exynos_drm_crtc *crtc, int zpos)
604 val |= DECON_UPDATE_STANDALONE_F; 549 val |= DECON_UPDATE_STANDALONE_F;
605 writel(val, ctx->regs + DECON_UPDATE); 550 writel(val, ctx->regs + DECON_UPDATE);
606 551
607 win_data->enabled = false; 552 plane->enabled = false;
608} 553}
609 554
610static void decon_window_suspend(struct decon_context *ctx) 555static void decon_window_suspend(struct decon_context *ctx)
611{ 556{
612 struct decon_win_data *win_data; 557 struct exynos_drm_plane *plane;
613 int i; 558 int i;
614 559
615 for (i = 0; i < WINDOWS_NR; i++) { 560 for (i = 0; i < WINDOWS_NR; i++) {
616 win_data = &ctx->win_data[i]; 561 plane = &ctx->planes[i];
617 win_data->resume = win_data->enabled; 562 plane->resume = plane->enabled;
618 if (win_data->enabled) 563 if (plane->enabled)
619 decon_win_disable(ctx->crtc, i); 564 decon_win_disable(ctx->crtc, i);
620 } 565 }
621} 566}
622 567
623static void decon_window_resume(struct decon_context *ctx) 568static void decon_window_resume(struct decon_context *ctx)
624{ 569{
625 struct decon_win_data *win_data; 570 struct exynos_drm_plane *plane;
626 int i; 571 int i;
627 572
628 for (i = 0; i < WINDOWS_NR; i++) { 573 for (i = 0; i < WINDOWS_NR; i++) {
629 win_data = &ctx->win_data[i]; 574 plane = &ctx->planes[i];
630 win_data->enabled = win_data->resume; 575 plane->enabled = plane->resume;
631 win_data->resume = false; 576 plane->resume = false;
632 } 577 }
633} 578}
634 579
635static void decon_apply(struct decon_context *ctx) 580static void decon_apply(struct decon_context *ctx)
636{ 581{
637 struct decon_win_data *win_data; 582 struct exynos_drm_plane *plane;
638 int i; 583 int i;
639 584
640 for (i = 0; i < WINDOWS_NR; i++) { 585 for (i = 0; i < WINDOWS_NR; i++) {
641 win_data = &ctx->win_data[i]; 586 plane = &ctx->planes[i];
642 if (win_data->enabled) 587 if (plane->enabled)
643 decon_win_commit(ctx->crtc, i); 588 decon_win_commit(ctx->crtc, i);
644 else 589 else
645 decon_win_disable(ctx->crtc, i); 590 decon_win_disable(ctx->crtc, i);
@@ -779,7 +724,6 @@ static struct exynos_drm_crtc_ops decon_crtc_ops = {
779 .enable_vblank = decon_enable_vblank, 724 .enable_vblank = decon_enable_vblank,
780 .disable_vblank = decon_disable_vblank, 725 .disable_vblank = decon_disable_vblank,
781 .wait_for_vblank = decon_wait_for_vblank, 726 .wait_for_vblank = decon_wait_for_vblank,
782 .win_mode_set = decon_win_mode_set,
783 .win_commit = decon_win_commit, 727 .win_commit = decon_win_commit,
784 .win_disable = decon_win_disable, 728 .win_disable = decon_win_disable,
785}; 729};
@@ -818,7 +762,9 @@ static int decon_bind(struct device *dev, struct device *master, void *data)
818{ 762{
819 struct decon_context *ctx = dev_get_drvdata(dev); 763 struct decon_context *ctx = dev_get_drvdata(dev);
820 struct drm_device *drm_dev = data; 764 struct drm_device *drm_dev = data;
821 int ret; 765 struct exynos_drm_plane *exynos_plane;
766 enum drm_plane_type type;
767 int zpos, ret;
822 768
823 ret = decon_ctx_initialize(ctx, drm_dev); 769 ret = decon_ctx_initialize(ctx, drm_dev);
824 if (ret) { 770 if (ret) {
@@ -826,8 +772,18 @@ static int decon_bind(struct device *dev, struct device *master, void *data)
826 return ret; 772 return ret;
827 } 773 }
828 774
829 ctx->crtc = exynos_drm_crtc_create(drm_dev, ctx->pipe, 775 for (zpos = 0; zpos < WINDOWS_NR; zpos++) {
830 EXYNOS_DISPLAY_TYPE_LCD, 776 type = (zpos == ctx->default_win) ? DRM_PLANE_TYPE_PRIMARY :
777 DRM_PLANE_TYPE_OVERLAY;
778 ret = exynos_plane_init(drm_dev, &ctx->planes[zpos],
779 1 << ctx->pipe, type);
780 if (ret)
781 return ret;
782 }
783
784 exynos_plane = &ctx->planes[ctx->default_win];
785 ctx->crtc = exynos_drm_crtc_create(drm_dev, &exynos_plane->base,
786 ctx->pipe, EXYNOS_DISPLAY_TYPE_LCD,
831 &decon_crtc_ops, ctx); 787 &decon_crtc_ops, ctx);
832 if (IS_ERR(ctx->crtc)) { 788 if (IS_ERR(ctx->crtc)) {
833 decon_ctx_remove(ctx); 789 decon_ctx_remove(ctx);
diff --git a/drivers/gpu/drm/exynos/exynos_drm_crtc.c b/drivers/gpu/drm/exynos/exynos_drm_crtc.c
index 48ccab7fdf63..47dd2b0f4aa5 100644
--- a/drivers/gpu/drm/exynos/exynos_drm_crtc.c
+++ b/drivers/gpu/drm/exynos/exynos_drm_crtc.c
@@ -239,13 +239,13 @@ static struct drm_crtc_funcs exynos_crtc_funcs = {
239}; 239};
240 240
241struct exynos_drm_crtc *exynos_drm_crtc_create(struct drm_device *drm_dev, 241struct exynos_drm_crtc *exynos_drm_crtc_create(struct drm_device *drm_dev,
242 struct drm_plane *plane,
242 int pipe, 243 int pipe,
243 enum exynos_drm_output_type type, 244 enum exynos_drm_output_type type,
244 struct exynos_drm_crtc_ops *ops, 245 struct exynos_drm_crtc_ops *ops,
245 void *ctx) 246 void *ctx)
246{ 247{
247 struct exynos_drm_crtc *exynos_crtc; 248 struct exynos_drm_crtc *exynos_crtc;
248 struct drm_plane *plane;
249 struct exynos_drm_private *private = drm_dev->dev_private; 249 struct exynos_drm_private *private = drm_dev->dev_private;
250 struct drm_crtc *crtc; 250 struct drm_crtc *crtc;
251 int ret; 251 int ret;
@@ -262,12 +262,6 @@ struct exynos_drm_crtc *exynos_drm_crtc_create(struct drm_device *drm_dev,
262 exynos_crtc->type = type; 262 exynos_crtc->type = type;
263 exynos_crtc->ops = ops; 263 exynos_crtc->ops = ops;
264 exynos_crtc->ctx = ctx; 264 exynos_crtc->ctx = ctx;
265 plane = exynos_plane_init(drm_dev, 1 << pipe,
266 DRM_PLANE_TYPE_PRIMARY);
267 if (IS_ERR(plane)) {
268 ret = PTR_ERR(plane);
269 goto err_plane;
270 }
271 265
272 crtc = &exynos_crtc->base; 266 crtc = &exynos_crtc->base;
273 267
@@ -284,7 +278,6 @@ struct exynos_drm_crtc *exynos_drm_crtc_create(struct drm_device *drm_dev,
284 278
285err_crtc: 279err_crtc:
286 plane->funcs->destroy(plane); 280 plane->funcs->destroy(plane);
287err_plane:
288 kfree(exynos_crtc); 281 kfree(exynos_crtc);
289 return ERR_PTR(ret); 282 return ERR_PTR(ret);
290} 283}
diff --git a/drivers/gpu/drm/exynos/exynos_drm_crtc.h b/drivers/gpu/drm/exynos/exynos_drm_crtc.h
index 6258b800aab8..e1fd2efc88ff 100644
--- a/drivers/gpu/drm/exynos/exynos_drm_crtc.h
+++ b/drivers/gpu/drm/exynos/exynos_drm_crtc.h
@@ -18,6 +18,7 @@
18#include "exynos_drm_drv.h" 18#include "exynos_drm_drv.h"
19 19
20struct exynos_drm_crtc *exynos_drm_crtc_create(struct drm_device *drm_dev, 20struct exynos_drm_crtc *exynos_drm_crtc_create(struct drm_device *drm_dev,
21 struct drm_plane *plane,
21 int pipe, 22 int pipe,
22 enum exynos_drm_output_type type, 23 enum exynos_drm_output_type type,
23 struct exynos_drm_crtc_ops *ops, 24 struct exynos_drm_crtc_ops *ops,
diff --git a/drivers/gpu/drm/exynos/exynos_drm_drv.c b/drivers/gpu/drm/exynos/exynos_drm_drv.c
index 90168d7cf66a..bb6e7f72f9e0 100644
--- a/drivers/gpu/drm/exynos/exynos_drm_drv.c
+++ b/drivers/gpu/drm/exynos/exynos_drm_drv.c
@@ -55,7 +55,6 @@ static int exynos_drm_load(struct drm_device *dev, unsigned long flags)
55{ 55{
56 struct exynos_drm_private *private; 56 struct exynos_drm_private *private;
57 int ret; 57 int ret;
58 int nr;
59 58
60 private = kzalloc(sizeof(struct exynos_drm_private), GFP_KERNEL); 59 private = kzalloc(sizeof(struct exynos_drm_private), GFP_KERNEL);
61 if (!private) 60 if (!private)
@@ -81,19 +80,6 @@ static int exynos_drm_load(struct drm_device *dev, unsigned long flags)
81 80
82 exynos_drm_mode_config_init(dev); 81 exynos_drm_mode_config_init(dev);
83 82
84 for (nr = 0; nr < MAX_PLANE; nr++) {
85 struct drm_plane *plane;
86 unsigned long possible_crtcs = (1 << MAX_CRTC) - 1;
87
88 plane = exynos_plane_init(dev, possible_crtcs,
89 DRM_PLANE_TYPE_OVERLAY);
90 if (!IS_ERR(plane))
91 continue;
92
93 ret = PTR_ERR(plane);
94 goto err_mode_config_cleanup;
95 }
96
97 /* setup possible_clones. */ 83 /* setup possible_clones. */
98 exynos_drm_encoder_setup(dev); 84 exynos_drm_encoder_setup(dev);
99 85
diff --git a/drivers/gpu/drm/exynos/exynos_drm_drv.h b/drivers/gpu/drm/exynos/exynos_drm_drv.h
index 4e8f0b04fff5..8a2f9430969d 100644
--- a/drivers/gpu/drm/exynos/exynos_drm_drv.h
+++ b/drivers/gpu/drm/exynos/exynos_drm_drv.h
@@ -78,6 +78,7 @@ enum exynos_drm_output_type {
78 * @transparency: transparency on or off. 78 * @transparency: transparency on or off.
79 * @activated: activated or not. 79 * @activated: activated or not.
80 * @enabled: enabled or not. 80 * @enabled: enabled or not.
81 * @resume: to resume or not.
81 * 82 *
82 * this structure is common to exynos SoC and its contents would be copied 83 * this structure is common to exynos SoC and its contents would be copied
83 * to hardware specific overlay info. 84 * to hardware specific overlay info.
@@ -112,6 +113,7 @@ struct exynos_drm_plane {
112 bool transparency:1; 113 bool transparency:1;
113 bool activated:1; 114 bool activated:1;
114 bool enabled:1; 115 bool enabled:1;
116 bool resume:1;
115}; 117};
116 118
117/* 119/*
@@ -172,7 +174,6 @@ struct exynos_drm_display {
172 * @disable_vblank: specific driver callback for disabling vblank interrupt. 174 * @disable_vblank: specific driver callback for disabling vblank interrupt.
173 * @wait_for_vblank: wait for vblank interrupt to make sure that 175 * @wait_for_vblank: wait for vblank interrupt to make sure that
174 * hardware overlay is updated. 176 * hardware overlay is updated.
175 * @win_mode_set: copy drm overlay info to hw specific overlay info.
176 * @win_commit: apply hardware specific overlay data to registers. 177 * @win_commit: apply hardware specific overlay data to registers.
177 * @win_disable: disable hardware specific overlay. 178 * @win_disable: disable hardware specific overlay.
178 * @te_handler: trigger to transfer video image at the tearing effect 179 * @te_handler: trigger to transfer video image at the tearing effect
@@ -188,8 +189,6 @@ struct exynos_drm_crtc_ops {
188 int (*enable_vblank)(struct exynos_drm_crtc *crtc); 189 int (*enable_vblank)(struct exynos_drm_crtc *crtc);
189 void (*disable_vblank)(struct exynos_drm_crtc *crtc); 190 void (*disable_vblank)(struct exynos_drm_crtc *crtc);
190 void (*wait_for_vblank)(struct exynos_drm_crtc *crtc); 191 void (*wait_for_vblank)(struct exynos_drm_crtc *crtc);
191 void (*win_mode_set)(struct exynos_drm_crtc *crtc,
192 struct exynos_drm_plane *plane);
193 void (*win_commit)(struct exynos_drm_crtc *crtc, int zpos); 192 void (*win_commit)(struct exynos_drm_crtc *crtc, int zpos);
194 void (*win_disable)(struct exynos_drm_crtc *crtc, int zpos); 193 void (*win_disable)(struct exynos_drm_crtc *crtc, int zpos);
195 void (*te_handler)(struct exynos_drm_crtc *crtc); 194 void (*te_handler)(struct exynos_drm_crtc *crtc);
diff --git a/drivers/gpu/drm/exynos/exynos_drm_fimd.c b/drivers/gpu/drm/exynos/exynos_drm_fimd.c
index 6f51d3d7ef6f..ab97162dd76c 100644
--- a/drivers/gpu/drm/exynos/exynos_drm_fimd.c
+++ b/drivers/gpu/drm/exynos/exynos_drm_fimd.c
@@ -31,6 +31,7 @@
31#include "exynos_drm_drv.h" 31#include "exynos_drm_drv.h"
32#include "exynos_drm_fbdev.h" 32#include "exynos_drm_fbdev.h"
33#include "exynos_drm_crtc.h" 33#include "exynos_drm_crtc.h"
34#include "exynos_drm_plane.h"
34#include "exynos_drm_iommu.h" 35#include "exynos_drm_iommu.h"
35 36
36/* 37/*
@@ -143,32 +144,15 @@ static struct fimd_driver_data exynos5_fimd_driver_data = {
143 .has_vtsel = 1, 144 .has_vtsel = 1,
144}; 145};
145 146
146struct fimd_win_data {
147 unsigned int offset_x;
148 unsigned int offset_y;
149 unsigned int ovl_width;
150 unsigned int ovl_height;
151 unsigned int fb_width;
152 unsigned int fb_height;
153 unsigned int fb_pitch;
154 unsigned int bpp;
155 unsigned int pixel_format;
156 dma_addr_t dma_addr;
157 unsigned int buf_offsize;
158 unsigned int line_size; /* bytes */
159 bool enabled;
160 bool resume;
161};
162
163struct fimd_context { 147struct fimd_context {
164 struct device *dev; 148 struct device *dev;
165 struct drm_device *drm_dev; 149 struct drm_device *drm_dev;
166 struct exynos_drm_crtc *crtc; 150 struct exynos_drm_crtc *crtc;
151 struct exynos_drm_plane planes[WINDOWS_NR];
167 struct clk *bus_clk; 152 struct clk *bus_clk;
168 struct clk *lcd_clk; 153 struct clk *lcd_clk;
169 void __iomem *regs; 154 void __iomem *regs;
170 struct regmap *sysreg; 155 struct regmap *sysreg;
171 struct fimd_win_data win_data[WINDOWS_NR];
172 unsigned int default_win; 156 unsigned int default_win;
173 unsigned long irq_flags; 157 unsigned long irq_flags;
174 u32 vidcon0; 158 u32 vidcon0;
@@ -505,59 +489,9 @@ static void fimd_disable_vblank(struct exynos_drm_crtc *crtc)
505 } 489 }
506} 490}
507 491
508static void fimd_win_mode_set(struct exynos_drm_crtc *crtc,
509 struct exynos_drm_plane *plane)
510{
511 struct fimd_context *ctx = crtc->ctx;
512 struct fimd_win_data *win_data;
513 int win;
514 unsigned long offset;
515
516 if (!plane) {
517 DRM_ERROR("plane is NULL\n");
518 return;
519 }
520
521 win = plane->zpos;
522 if (win == DEFAULT_ZPOS)
523 win = ctx->default_win;
524
525 if (win < 0 || win >= WINDOWS_NR)
526 return;
527
528 offset = plane->fb_x * (plane->bpp >> 3);
529 offset += plane->fb_y * plane->pitch;
530
531 DRM_DEBUG_KMS("offset = 0x%lx, pitch = %x\n", offset, plane->pitch);
532
533 win_data = &ctx->win_data[win];
534
535 win_data->offset_x = plane->crtc_x;
536 win_data->offset_y = plane->crtc_y;
537 win_data->ovl_width = plane->crtc_width;
538 win_data->ovl_height = plane->crtc_height;
539 win_data->fb_pitch = plane->pitch;
540 win_data->fb_width = plane->fb_width;
541 win_data->fb_height = plane->fb_height;
542 win_data->dma_addr = plane->dma_addr[0] + offset;
543 win_data->bpp = plane->bpp;
544 win_data->pixel_format = plane->pixel_format;
545 win_data->buf_offsize =
546 plane->pitch - (plane->crtc_width * (plane->bpp >> 3));
547 win_data->line_size = plane->crtc_width * (plane->bpp >> 3);
548
549 DRM_DEBUG_KMS("offset_x = %d, offset_y = %d\n",
550 win_data->offset_x, win_data->offset_y);
551 DRM_DEBUG_KMS("ovl_width = %d, ovl_height = %d\n",
552 win_data->ovl_width, win_data->ovl_height);
553 DRM_DEBUG_KMS("paddr = 0x%lx\n", (unsigned long)win_data->dma_addr);
554 DRM_DEBUG_KMS("fb_width = %d, crtc_width = %d\n",
555 plane->fb_width, plane->crtc_width);
556}
557
558static void fimd_win_set_pixfmt(struct fimd_context *ctx, unsigned int win) 492static void fimd_win_set_pixfmt(struct fimd_context *ctx, unsigned int win)
559{ 493{
560 struct fimd_win_data *win_data = &ctx->win_data[win]; 494 struct exynos_drm_plane *plane = &ctx->planes[win];
561 unsigned long val; 495 unsigned long val;
562 496
563 val = WINCONx_ENWIN; 497 val = WINCONx_ENWIN;
@@ -567,11 +501,11 @@ static void fimd_win_set_pixfmt(struct fimd_context *ctx, unsigned int win)
567 * So the request format is ARGB8888 then change it to XRGB8888. 501 * So the request format is ARGB8888 then change it to XRGB8888.
568 */ 502 */
569 if (ctx->driver_data->has_limited_fmt && !win) { 503 if (ctx->driver_data->has_limited_fmt && !win) {
570 if (win_data->pixel_format == DRM_FORMAT_ARGB8888) 504 if (plane->pixel_format == DRM_FORMAT_ARGB8888)
571 win_data->pixel_format = DRM_FORMAT_XRGB8888; 505 plane->pixel_format = DRM_FORMAT_XRGB8888;
572 } 506 }
573 507
574 switch (win_data->pixel_format) { 508 switch (plane->pixel_format) {
575 case DRM_FORMAT_C8: 509 case DRM_FORMAT_C8:
576 val |= WINCON0_BPPMODE_8BPP_PALETTE; 510 val |= WINCON0_BPPMODE_8BPP_PALETTE;
577 val |= WINCONx_BURSTLEN_8WORD; 511 val |= WINCONx_BURSTLEN_8WORD;
@@ -607,7 +541,7 @@ static void fimd_win_set_pixfmt(struct fimd_context *ctx, unsigned int win)
607 break; 541 break;
608 } 542 }
609 543
610 DRM_DEBUG_KMS("bpp = %d\n", win_data->bpp); 544 DRM_DEBUG_KMS("bpp = %d\n", plane->bpp);
611 545
612 /* 546 /*
613 * In case of exynos, setting dma-burst to 16Word causes permanent 547 * In case of exynos, setting dma-burst to 16Word causes permanent
@@ -617,7 +551,7 @@ static void fimd_win_set_pixfmt(struct fimd_context *ctx, unsigned int win)
617 * movement causes unstable DMA which results into iommu crash/tear. 551 * movement causes unstable DMA which results into iommu crash/tear.
618 */ 552 */
619 553
620 if (win_data->fb_width < MIN_FB_WIDTH_FOR_16WORD_BURST) { 554 if (plane->fb_width < MIN_FB_WIDTH_FOR_16WORD_BURST) {
621 val &= ~WINCONx_BURSTLEN_MASK; 555 val &= ~WINCONx_BURSTLEN_MASK;
622 val |= WINCONx_BURSTLEN_4WORD; 556 val |= WINCONx_BURSTLEN_4WORD;
623 } 557 }
@@ -686,11 +620,11 @@ static void fimd_shadow_protect_win(struct fimd_context *ctx,
686static void fimd_win_commit(struct exynos_drm_crtc *crtc, int zpos) 620static void fimd_win_commit(struct exynos_drm_crtc *crtc, int zpos)
687{ 621{
688 struct fimd_context *ctx = crtc->ctx; 622 struct fimd_context *ctx = crtc->ctx;
689 struct fimd_win_data *win_data; 623 struct exynos_drm_plane *plane;
690 int win = zpos; 624 int win = zpos;
691 unsigned long val, size; 625 dma_addr_t dma_addr;
692 unsigned int last_x; 626 unsigned long val, size, offset;
693 unsigned int last_y; 627 unsigned int last_x, last_y, buf_offsize, line_size;
694 628
695 if (ctx->suspended) 629 if (ctx->suspended)
696 return; 630 return;
@@ -701,11 +635,11 @@ static void fimd_win_commit(struct exynos_drm_crtc *crtc, int zpos)
701 if (win < 0 || win >= WINDOWS_NR) 635 if (win < 0 || win >= WINDOWS_NR)
702 return; 636 return;
703 637
704 win_data = &ctx->win_data[win]; 638 plane = &ctx->planes[win];
705 639
706 /* If suspended, enable this on resume */ 640 /* If suspended, enable this on resume */
707 if (ctx->suspended) { 641 if (ctx->suspended) {
708 win_data->resume = true; 642 plane->resume = true;
709 return; 643 return;
710 } 644 }
711 645
@@ -722,38 +656,45 @@ static void fimd_win_commit(struct exynos_drm_crtc *crtc, int zpos)
722 /* protect windows */ 656 /* protect windows */
723 fimd_shadow_protect_win(ctx, win, true); 657 fimd_shadow_protect_win(ctx, win, true);
724 658
659
660 offset = plane->fb_x * (plane->bpp >> 3);
661 offset += plane->fb_y * plane->pitch;
662
725 /* buffer start address */ 663 /* buffer start address */
726 val = (unsigned long)win_data->dma_addr; 664 dma_addr = plane->dma_addr[0] + offset;
665 val = (unsigned long)dma_addr;
727 writel(val, ctx->regs + VIDWx_BUF_START(win, 0)); 666 writel(val, ctx->regs + VIDWx_BUF_START(win, 0));
728 667
729 /* buffer end address */ 668 /* buffer end address */
730 size = win_data->fb_pitch * win_data->ovl_height * (win_data->bpp >> 3); 669 size = plane->pitch * plane->crtc_height * (plane->bpp >> 3);
731 val = (unsigned long)(win_data->dma_addr + size); 670 val = (unsigned long)(dma_addr + size);
732 writel(val, ctx->regs + VIDWx_BUF_END(win, 0)); 671 writel(val, ctx->regs + VIDWx_BUF_END(win, 0));
733 672
734 DRM_DEBUG_KMS("start addr = 0x%lx, end addr = 0x%lx, size = 0x%lx\n", 673 DRM_DEBUG_KMS("start addr = 0x%lx, end addr = 0x%lx, size = 0x%lx\n",
735 (unsigned long)win_data->dma_addr, val, size); 674 (unsigned long)dma_addr, val, size);
736 DRM_DEBUG_KMS("ovl_width = %d, ovl_height = %d\n", 675 DRM_DEBUG_KMS("ovl_width = %d, ovl_height = %d\n",
737 win_data->ovl_width, win_data->ovl_height); 676 plane->crtc_width, plane->crtc_height);
738 677
739 /* buffer size */ 678 /* buffer size */
740 val = VIDW_BUF_SIZE_OFFSET(win_data->buf_offsize) | 679 buf_offsize = (plane->fb_width - plane->crtc_width) * (plane->bpp >> 3);
741 VIDW_BUF_SIZE_PAGEWIDTH(win_data->line_size) | 680 line_size = plane->crtc_width * (plane->bpp >> 3);
742 VIDW_BUF_SIZE_OFFSET_E(win_data->buf_offsize) | 681 val = VIDW_BUF_SIZE_OFFSET(buf_offsize) |
743 VIDW_BUF_SIZE_PAGEWIDTH_E(win_data->line_size); 682 VIDW_BUF_SIZE_PAGEWIDTH(line_size) |
683 VIDW_BUF_SIZE_OFFSET_E(buf_offsize) |
684 VIDW_BUF_SIZE_PAGEWIDTH_E(line_size);
744 writel(val, ctx->regs + VIDWx_BUF_SIZE(win, 0)); 685 writel(val, ctx->regs + VIDWx_BUF_SIZE(win, 0));
745 686
746 /* OSD position */ 687 /* OSD position */
747 val = VIDOSDxA_TOPLEFT_X(win_data->offset_x) | 688 val = VIDOSDxA_TOPLEFT_X(plane->crtc_x) |
748 VIDOSDxA_TOPLEFT_Y(win_data->offset_y) | 689 VIDOSDxA_TOPLEFT_Y(plane->crtc_y) |
749 VIDOSDxA_TOPLEFT_X_E(win_data->offset_x) | 690 VIDOSDxA_TOPLEFT_X_E(plane->crtc_x) |
750 VIDOSDxA_TOPLEFT_Y_E(win_data->offset_y); 691 VIDOSDxA_TOPLEFT_Y_E(plane->crtc_y);
751 writel(val, ctx->regs + VIDOSD_A(win)); 692 writel(val, ctx->regs + VIDOSD_A(win));
752 693
753 last_x = win_data->offset_x + win_data->ovl_width; 694 last_x = plane->crtc_x + plane->crtc_width;
754 if (last_x) 695 if (last_x)
755 last_x--; 696 last_x--;
756 last_y = win_data->offset_y + win_data->ovl_height; 697 last_y = plane->crtc_y + plane->crtc_height;
757 if (last_y) 698 if (last_y)
758 last_y--; 699 last_y--;
759 700
@@ -763,14 +704,14 @@ static void fimd_win_commit(struct exynos_drm_crtc *crtc, int zpos)
763 writel(val, ctx->regs + VIDOSD_B(win)); 704 writel(val, ctx->regs + VIDOSD_B(win));
764 705
765 DRM_DEBUG_KMS("osd pos: tx = %d, ty = %d, bx = %d, by = %d\n", 706 DRM_DEBUG_KMS("osd pos: tx = %d, ty = %d, bx = %d, by = %d\n",
766 win_data->offset_x, win_data->offset_y, last_x, last_y); 707 plane->crtc_x, plane->crtc_y, last_x, last_y);
767 708
768 /* OSD size */ 709 /* OSD size */
769 if (win != 3 && win != 4) { 710 if (win != 3 && win != 4) {
770 u32 offset = VIDOSD_D(win); 711 u32 offset = VIDOSD_D(win);
771 if (win == 0) 712 if (win == 0)
772 offset = VIDOSD_C(win); 713 offset = VIDOSD_C(win);
773 val = win_data->ovl_width * win_data->ovl_height; 714 val = plane->crtc_width * plane->crtc_height;
774 writel(val, ctx->regs + offset); 715 writel(val, ctx->regs + offset);
775 716
776 DRM_DEBUG_KMS("osd size = 0x%x\n", (unsigned int)val); 717 DRM_DEBUG_KMS("osd size = 0x%x\n", (unsigned int)val);
@@ -790,7 +731,7 @@ static void fimd_win_commit(struct exynos_drm_crtc *crtc, int zpos)
790 /* Enable DMA channel and unprotect windows */ 731 /* Enable DMA channel and unprotect windows */
791 fimd_shadow_protect_win(ctx, win, false); 732 fimd_shadow_protect_win(ctx, win, false);
792 733
793 win_data->enabled = true; 734 plane->enabled = true;
794 735
795 if (ctx->i80_if) 736 if (ctx->i80_if)
796 atomic_set(&ctx->win_updated, 1); 737 atomic_set(&ctx->win_updated, 1);
@@ -799,7 +740,7 @@ static void fimd_win_commit(struct exynos_drm_crtc *crtc, int zpos)
799static void fimd_win_disable(struct exynos_drm_crtc *crtc, int zpos) 740static void fimd_win_disable(struct exynos_drm_crtc *crtc, int zpos)
800{ 741{
801 struct fimd_context *ctx = crtc->ctx; 742 struct fimd_context *ctx = crtc->ctx;
802 struct fimd_win_data *win_data; 743 struct exynos_drm_plane *plane;
803 int win = zpos; 744 int win = zpos;
804 745
805 if (win == DEFAULT_ZPOS) 746 if (win == DEFAULT_ZPOS)
@@ -808,11 +749,11 @@ static void fimd_win_disable(struct exynos_drm_crtc *crtc, int zpos)
808 if (win < 0 || win >= WINDOWS_NR) 749 if (win < 0 || win >= WINDOWS_NR)
809 return; 750 return;
810 751
811 win_data = &ctx->win_data[win]; 752 plane = &ctx->planes[win];
812 753
813 if (ctx->suspended) { 754 if (ctx->suspended) {
814 /* do not resume this window*/ 755 /* do not resume this window*/
815 win_data->resume = false; 756 plane->resume = false;
816 return; 757 return;
817 } 758 }
818 759
@@ -827,42 +768,42 @@ static void fimd_win_disable(struct exynos_drm_crtc *crtc, int zpos)
827 /* unprotect windows */ 768 /* unprotect windows */
828 fimd_shadow_protect_win(ctx, win, false); 769 fimd_shadow_protect_win(ctx, win, false);
829 770
830 win_data->enabled = false; 771 plane->enabled = false;
831} 772}
832 773
833static void fimd_window_suspend(struct fimd_context *ctx) 774static void fimd_window_suspend(struct fimd_context *ctx)
834{ 775{
835 struct fimd_win_data *win_data; 776 struct exynos_drm_plane *plane;
836 int i; 777 int i;
837 778
838 for (i = 0; i < WINDOWS_NR; i++) { 779 for (i = 0; i < WINDOWS_NR; i++) {
839 win_data = &ctx->win_data[i]; 780 plane = &ctx->planes[i];
840 win_data->resume = win_data->enabled; 781 plane->resume = plane->enabled;
841 if (win_data->enabled) 782 if (plane->enabled)
842 fimd_win_disable(ctx->crtc, i); 783 fimd_win_disable(ctx->crtc, i);
843 } 784 }
844} 785}
845 786
846static void fimd_window_resume(struct fimd_context *ctx) 787static void fimd_window_resume(struct fimd_context *ctx)
847{ 788{
848 struct fimd_win_data *win_data; 789 struct exynos_drm_plane *plane;
849 int i; 790 int i;
850 791
851 for (i = 0; i < WINDOWS_NR; i++) { 792 for (i = 0; i < WINDOWS_NR; i++) {
852 win_data = &ctx->win_data[i]; 793 plane = &ctx->planes[i];
853 win_data->enabled = win_data->resume; 794 plane->enabled = plane->resume;
854 win_data->resume = false; 795 plane->resume = false;
855 } 796 }
856} 797}
857 798
858static void fimd_apply(struct fimd_context *ctx) 799static void fimd_apply(struct fimd_context *ctx)
859{ 800{
860 struct fimd_win_data *win_data; 801 struct exynos_drm_plane *plane;
861 int i; 802 int i;
862 803
863 for (i = 0; i < WINDOWS_NR; i++) { 804 for (i = 0; i < WINDOWS_NR; i++) {
864 win_data = &ctx->win_data[i]; 805 plane = &ctx->planes[i];
865 if (win_data->enabled) 806 if (plane->enabled)
866 fimd_win_commit(ctx->crtc, i); 807 fimd_win_commit(ctx->crtc, i);
867 else 808 else
868 fimd_win_disable(ctx->crtc, i); 809 fimd_win_disable(ctx->crtc, i);
@@ -1019,7 +960,6 @@ static struct exynos_drm_crtc_ops fimd_crtc_ops = {
1019 .enable_vblank = fimd_enable_vblank, 960 .enable_vblank = fimd_enable_vblank,
1020 .disable_vblank = fimd_disable_vblank, 961 .disable_vblank = fimd_disable_vblank,
1021 .wait_for_vblank = fimd_wait_for_vblank, 962 .wait_for_vblank = fimd_wait_for_vblank,
1022 .win_mode_set = fimd_win_mode_set,
1023 .win_commit = fimd_win_commit, 963 .win_commit = fimd_win_commit,
1024 .win_disable = fimd_win_disable, 964 .win_disable = fimd_win_disable,
1025 .te_handler = fimd_te_handler, 965 .te_handler = fimd_te_handler,
@@ -1065,13 +1005,25 @@ static int fimd_bind(struct device *dev, struct device *master, void *data)
1065 struct fimd_context *ctx = dev_get_drvdata(dev); 1005 struct fimd_context *ctx = dev_get_drvdata(dev);
1066 struct drm_device *drm_dev = data; 1006 struct drm_device *drm_dev = data;
1067 struct exynos_drm_private *priv = drm_dev->dev_private; 1007 struct exynos_drm_private *priv = drm_dev->dev_private;
1068 int ret; 1008 struct exynos_drm_plane *exynos_plane;
1009 enum drm_plane_type type;
1010 int zpos, ret;
1069 1011
1070 ctx->drm_dev = drm_dev; 1012 ctx->drm_dev = drm_dev;
1071 ctx->pipe = priv->pipe++; 1013 ctx->pipe = priv->pipe++;
1072 1014
1073 ctx->crtc = exynos_drm_crtc_create(drm_dev, ctx->pipe, 1015 for (zpos = 0; zpos < WINDOWS_NR; zpos++) {
1074 EXYNOS_DISPLAY_TYPE_LCD, 1016 type = (zpos == ctx->default_win) ? DRM_PLANE_TYPE_PRIMARY :
1017 DRM_PLANE_TYPE_OVERLAY;
1018 ret = exynos_plane_init(drm_dev, &ctx->planes[zpos],
1019 1 << ctx->pipe, type);
1020 if (ret)
1021 return ret;
1022 }
1023
1024 exynos_plane = &ctx->planes[ctx->default_win];
1025 ctx->crtc = exynos_drm_crtc_create(drm_dev, &exynos_plane->base,
1026 ctx->pipe, EXYNOS_DISPLAY_TYPE_LCD,
1075 &fimd_crtc_ops, ctx); 1027 &fimd_crtc_ops, ctx);
1076 1028
1077 if (ctx->display) 1029 if (ctx->display)
diff --git a/drivers/gpu/drm/exynos/exynos_drm_plane.c b/drivers/gpu/drm/exynos/exynos_drm_plane.c
index 8ad5b7294eb4..4014c746a534 100644
--- a/drivers/gpu/drm/exynos/exynos_drm_plane.c
+++ b/drivers/gpu/drm/exynos/exynos_drm_plane.c
@@ -92,7 +92,6 @@ void exynos_plane_mode_set(struct drm_plane *plane, struct drm_crtc *crtc,
92 uint32_t src_w, uint32_t src_h) 92 uint32_t src_w, uint32_t src_h)
93{ 93{
94 struct exynos_drm_plane *exynos_plane = to_exynos_plane(plane); 94 struct exynos_drm_plane *exynos_plane = to_exynos_plane(plane);
95 struct exynos_drm_crtc *exynos_crtc = to_exynos_crtc(crtc);
96 unsigned int actual_w; 95 unsigned int actual_w;
97 unsigned int actual_h; 96 unsigned int actual_h;
98 97
@@ -139,9 +138,6 @@ void exynos_plane_mode_set(struct drm_plane *plane, struct drm_crtc *crtc,
139 exynos_plane->crtc_width, exynos_plane->crtc_height); 138 exynos_plane->crtc_width, exynos_plane->crtc_height);
140 139
141 plane->crtc = crtc; 140 plane->crtc = crtc;
142
143 if (exynos_crtc->ops->win_mode_set)
144 exynos_crtc->ops->win_mode_set(exynos_crtc, exynos_plane);
145} 141}
146 142
147int 143int
@@ -184,11 +180,8 @@ static int exynos_disable_plane(struct drm_plane *plane)
184 180
185static void exynos_plane_destroy(struct drm_plane *plane) 181static void exynos_plane_destroy(struct drm_plane *plane)
186{ 182{
187 struct exynos_drm_plane *exynos_plane = to_exynos_plane(plane);
188
189 exynos_disable_plane(plane); 183 exynos_disable_plane(plane);
190 drm_plane_cleanup(plane); 184 drm_plane_cleanup(plane);
191 kfree(exynos_plane);
192} 185}
193 186
194static int exynos_plane_set_property(struct drm_plane *plane, 187static int exynos_plane_set_property(struct drm_plane *plane,
@@ -233,24 +226,18 @@ static void exynos_plane_attach_zpos_property(struct drm_plane *plane)
233 drm_object_attach_property(&plane->base, prop, 0); 226 drm_object_attach_property(&plane->base, prop, 0);
234} 227}
235 228
236struct drm_plane *exynos_plane_init(struct drm_device *dev, 229int exynos_plane_init(struct drm_device *dev,
237 unsigned long possible_crtcs, 230 struct exynos_drm_plane *exynos_plane,
238 enum drm_plane_type type) 231 unsigned long possible_crtcs, enum drm_plane_type type)
239{ 232{
240 struct exynos_drm_plane *exynos_plane;
241 int err; 233 int err;
242 234
243 exynos_plane = kzalloc(sizeof(struct exynos_drm_plane), GFP_KERNEL);
244 if (!exynos_plane)
245 return ERR_PTR(-ENOMEM);
246
247 err = drm_universal_plane_init(dev, &exynos_plane->base, possible_crtcs, 235 err = drm_universal_plane_init(dev, &exynos_plane->base, possible_crtcs,
248 &exynos_plane_funcs, formats, 236 &exynos_plane_funcs, formats,
249 ARRAY_SIZE(formats), type); 237 ARRAY_SIZE(formats), type);
250 if (err) { 238 if (err) {
251 DRM_ERROR("failed to initialize plane\n"); 239 DRM_ERROR("failed to initialize plane\n");
252 kfree(exynos_plane); 240 return err;
253 return ERR_PTR(err);
254 } 241 }
255 242
256 if (type == DRM_PLANE_TYPE_PRIMARY) 243 if (type == DRM_PLANE_TYPE_PRIMARY)
@@ -258,5 +245,5 @@ struct drm_plane *exynos_plane_init(struct drm_device *dev,
258 else 245 else
259 exynos_plane_attach_zpos_property(&exynos_plane->base); 246 exynos_plane_attach_zpos_property(&exynos_plane->base);
260 247
261 return &exynos_plane->base; 248 return 0;
262} 249}
diff --git a/drivers/gpu/drm/exynos/exynos_drm_plane.h b/drivers/gpu/drm/exynos/exynos_drm_plane.h
index 9d3c374e7b3e..d8a349491c68 100644
--- a/drivers/gpu/drm/exynos/exynos_drm_plane.h
+++ b/drivers/gpu/drm/exynos/exynos_drm_plane.h
@@ -20,6 +20,6 @@ int exynos_update_plane(struct drm_plane *plane, struct drm_crtc *crtc,
20 unsigned int crtc_w, unsigned int crtc_h, 20 unsigned int crtc_w, unsigned int crtc_h,
21 uint32_t src_x, uint32_t src_y, 21 uint32_t src_x, uint32_t src_y,
22 uint32_t src_w, uint32_t src_h); 22 uint32_t src_w, uint32_t src_h);
23struct drm_plane *exynos_plane_init(struct drm_device *dev, 23int exynos_plane_init(struct drm_device *dev,
24 unsigned long possible_crtcs, 24 struct exynos_drm_plane *exynos_plane,
25 enum drm_plane_type type); 25 unsigned long possible_crtcs, enum drm_plane_type type);
diff --git a/drivers/gpu/drm/exynos/exynos_drm_vidi.c b/drivers/gpu/drm/exynos/exynos_drm_vidi.c
index b886972b5888..da5ee15f6136 100644
--- a/drivers/gpu/drm/exynos/exynos_drm_vidi.c
+++ b/drivers/gpu/drm/exynos/exynos_drm_vidi.c
@@ -23,6 +23,7 @@
23 23
24#include "exynos_drm_drv.h" 24#include "exynos_drm_drv.h"
25#include "exynos_drm_crtc.h" 25#include "exynos_drm_crtc.h"
26#include "exynos_drm_plane.h"
26#include "exynos_drm_encoder.h" 27#include "exynos_drm_encoder.h"
27#include "exynos_drm_vidi.h" 28#include "exynos_drm_vidi.h"
28 29
@@ -32,20 +33,6 @@
32#define ctx_from_connector(c) container_of(c, struct vidi_context, \ 33#define ctx_from_connector(c) container_of(c, struct vidi_context, \
33 connector) 34 connector)
34 35
35struct vidi_win_data {
36 unsigned int offset_x;
37 unsigned int offset_y;
38 unsigned int ovl_width;
39 unsigned int ovl_height;
40 unsigned int fb_width;
41 unsigned int fb_height;
42 unsigned int bpp;
43 dma_addr_t dma_addr;
44 unsigned int buf_offsize;
45 unsigned int line_size; /* bytes */
46 bool enabled;
47};
48
49struct vidi_context { 36struct vidi_context {
50 struct exynos_drm_display display; 37 struct exynos_drm_display display;
51 struct platform_device *pdev; 38 struct platform_device *pdev;
@@ -53,7 +40,7 @@ struct vidi_context {
53 struct exynos_drm_crtc *crtc; 40 struct exynos_drm_crtc *crtc;
54 struct drm_encoder *encoder; 41 struct drm_encoder *encoder;
55 struct drm_connector connector; 42 struct drm_connector connector;
56 struct vidi_win_data win_data[WINDOWS_NR]; 43 struct exynos_drm_plane planes[WINDOWS_NR];
57 struct edid *raw_edid; 44 struct edid *raw_edid;
58 unsigned int clkdiv; 45 unsigned int clkdiv;
59 unsigned int default_win; 46 unsigned int default_win;
@@ -97,19 +84,6 @@ static const char fake_edid_info[] = {
97 0x00, 0x00, 0x00, 0x06 84 0x00, 0x00, 0x00, 0x06
98}; 85};
99 86
100static void vidi_apply(struct vidi_context *ctx)
101{
102 struct exynos_drm_crtc_ops *crtc_ops = ctx->crtc->ops;
103 struct vidi_win_data *win_data;
104 int i;
105
106 for (i = 0; i < WINDOWS_NR; i++) {
107 win_data = &ctx->win_data[i];
108 if (win_data->enabled && (crtc_ops && crtc_ops->win_commit))
109 crtc_ops->win_commit(ctx->crtc, i);
110 }
111}
112
113static int vidi_enable_vblank(struct exynos_drm_crtc *crtc) 87static int vidi_enable_vblank(struct exynos_drm_crtc *crtc)
114{ 88{
115 struct vidi_context *ctx = crtc->ctx; 89 struct vidi_context *ctx = crtc->ctx;
@@ -143,63 +117,10 @@ static void vidi_disable_vblank(struct exynos_drm_crtc *crtc)
143 ctx->vblank_on = false; 117 ctx->vblank_on = false;
144} 118}
145 119
146static void vidi_win_mode_set(struct exynos_drm_crtc *crtc,
147 struct exynos_drm_plane *plane)
148{
149 struct vidi_context *ctx = crtc->ctx;
150 struct vidi_win_data *win_data;
151 int win;
152 unsigned long offset;
153
154 if (!plane) {
155 DRM_ERROR("plane is NULL\n");
156 return;
157 }
158
159 win = plane->zpos;
160 if (win == DEFAULT_ZPOS)
161 win = ctx->default_win;
162
163 if (win < 0 || win >= WINDOWS_NR)
164 return;
165
166 offset = plane->fb_x * (plane->bpp >> 3);
167 offset += plane->fb_y * plane->pitch;
168
169 DRM_DEBUG_KMS("offset = 0x%lx, pitch = %x\n", offset, plane->pitch);
170
171 win_data = &ctx->win_data[win];
172
173 win_data->offset_x = plane->crtc_x;
174 win_data->offset_y = plane->crtc_y;
175 win_data->ovl_width = plane->crtc_width;
176 win_data->ovl_height = plane->crtc_height;
177 win_data->fb_width = plane->fb_width;
178 win_data->fb_height = plane->fb_height;
179 win_data->dma_addr = plane->dma_addr[0] + offset;
180 win_data->bpp = plane->bpp;
181 win_data->buf_offsize = (plane->fb_width - plane->crtc_width) *
182 (plane->bpp >> 3);
183 win_data->line_size = plane->crtc_width * (plane->bpp >> 3);
184
185 /*
186 * some parts of win_data should be transferred to user side
187 * through specific ioctl.
188 */
189
190 DRM_DEBUG_KMS("offset_x = %d, offset_y = %d\n",
191 win_data->offset_x, win_data->offset_y);
192 DRM_DEBUG_KMS("ovl_width = %d, ovl_height = %d\n",
193 win_data->ovl_width, win_data->ovl_height);
194 DRM_DEBUG_KMS("paddr = 0x%lx\n", (unsigned long)win_data->dma_addr);
195 DRM_DEBUG_KMS("fb_width = %d, crtc_width = %d\n",
196 plane->fb_width, plane->crtc_width);
197}
198
199static void vidi_win_commit(struct exynos_drm_crtc *crtc, int zpos) 120static void vidi_win_commit(struct exynos_drm_crtc *crtc, int zpos)
200{ 121{
201 struct vidi_context *ctx = crtc->ctx; 122 struct vidi_context *ctx = crtc->ctx;
202 struct vidi_win_data *win_data; 123 struct exynos_drm_plane *plane;
203 int win = zpos; 124 int win = zpos;
204 125
205 if (ctx->suspended) 126 if (ctx->suspended)
@@ -211,11 +132,11 @@ static void vidi_win_commit(struct exynos_drm_crtc *crtc, int zpos)
211 if (win < 0 || win >= WINDOWS_NR) 132 if (win < 0 || win >= WINDOWS_NR)
212 return; 133 return;
213 134
214 win_data = &ctx->win_data[win]; 135 plane = &ctx->planes[win];
215 136
216 win_data->enabled = true; 137 plane->enabled = true;
217 138
218 DRM_DEBUG_KMS("dma_addr = %pad\n", &win_data->dma_addr); 139 DRM_DEBUG_KMS("dma_addr = %pad\n", plane->dma_addr);
219 140
220 if (ctx->vblank_on) 141 if (ctx->vblank_on)
221 schedule_work(&ctx->work); 142 schedule_work(&ctx->work);
@@ -224,7 +145,7 @@ static void vidi_win_commit(struct exynos_drm_crtc *crtc, int zpos)
224static void vidi_win_disable(struct exynos_drm_crtc *crtc, int zpos) 145static void vidi_win_disable(struct exynos_drm_crtc *crtc, int zpos)
225{ 146{
226 struct vidi_context *ctx = crtc->ctx; 147 struct vidi_context *ctx = crtc->ctx;
227 struct vidi_win_data *win_data; 148 struct exynos_drm_plane *plane;
228 int win = zpos; 149 int win = zpos;
229 150
230 if (win == DEFAULT_ZPOS) 151 if (win == DEFAULT_ZPOS)
@@ -233,14 +154,17 @@ static void vidi_win_disable(struct exynos_drm_crtc *crtc, int zpos)
233 if (win < 0 || win >= WINDOWS_NR) 154 if (win < 0 || win >= WINDOWS_NR)
234 return; 155 return;
235 156
236 win_data = &ctx->win_data[win]; 157 plane = &ctx->planes[win];
237 win_data->enabled = false; 158 plane->enabled = false;
238 159
239 /* TODO. */ 160 /* TODO. */
240} 161}
241 162
242static int vidi_power_on(struct vidi_context *ctx, bool enable) 163static int vidi_power_on(struct vidi_context *ctx, bool enable)
243{ 164{
165 struct exynos_drm_plane *plane;
166 int i;
167
244 DRM_DEBUG_KMS("%s\n", __FILE__); 168 DRM_DEBUG_KMS("%s\n", __FILE__);
245 169
246 if (enable != false && enable != true) 170 if (enable != false && enable != true)
@@ -253,7 +177,11 @@ static int vidi_power_on(struct vidi_context *ctx, bool enable)
253 if (test_and_clear_bit(0, &ctx->irq_flags)) 177 if (test_and_clear_bit(0, &ctx->irq_flags))
254 vidi_enable_vblank(ctx->crtc); 178 vidi_enable_vblank(ctx->crtc);
255 179
256 vidi_apply(ctx); 180 for (i = 0; i < WINDOWS_NR; i++) {
181 plane = &ctx->planes[i];
182 if (plane->enabled)
183 vidi_win_commit(ctx->crtc, i);
184 }
257 } else { 185 } else {
258 ctx->suspended = true; 186 ctx->suspended = true;
259 } 187 }
@@ -301,7 +229,6 @@ static struct exynos_drm_crtc_ops vidi_crtc_ops = {
301 .dpms = vidi_dpms, 229 .dpms = vidi_dpms,
302 .enable_vblank = vidi_enable_vblank, 230 .enable_vblank = vidi_enable_vblank,
303 .disable_vblank = vidi_disable_vblank, 231 .disable_vblank = vidi_disable_vblank,
304 .win_mode_set = vidi_win_mode_set,
305 .win_commit = vidi_win_commit, 232 .win_commit = vidi_win_commit,
306 .win_disable = vidi_win_disable, 233 .win_disable = vidi_win_disable,
307}; 234};
@@ -543,12 +470,24 @@ static int vidi_bind(struct device *dev, struct device *master, void *data)
543{ 470{
544 struct vidi_context *ctx = dev_get_drvdata(dev); 471 struct vidi_context *ctx = dev_get_drvdata(dev);
545 struct drm_device *drm_dev = data; 472 struct drm_device *drm_dev = data;
546 int ret; 473 struct exynos_drm_plane *exynos_plane;
474 enum drm_plane_type type;
475 int zpos, ret;
547 476
548 vidi_ctx_initialize(ctx, drm_dev); 477 vidi_ctx_initialize(ctx, drm_dev);
549 478
550 ctx->crtc = exynos_drm_crtc_create(drm_dev, ctx->pipe, 479 for (zpos = 0; zpos < WINDOWS_NR; zpos++) {
551 EXYNOS_DISPLAY_TYPE_VIDI, 480 type = (zpos == ctx->default_win) ? DRM_PLANE_TYPE_PRIMARY :
481 DRM_PLANE_TYPE_OVERLAY;
482 ret = exynos_plane_init(drm_dev, &ctx->planes[zpos],
483 1 << ctx->pipe, type);
484 if (ret)
485 return ret;
486 }
487
488 exynos_plane = &ctx->planes[ctx->default_win];
489 ctx->crtc = exynos_drm_crtc_create(drm_dev, &exynos_plane->base,
490 ctx->pipe, EXYNOS_DISPLAY_TYPE_VIDI,
552 &vidi_crtc_ops, ctx); 491 &vidi_crtc_ops, ctx);
553 if (IS_ERR(ctx->crtc)) { 492 if (IS_ERR(ctx->crtc)) {
554 DRM_ERROR("failed to create crtc.\n"); 493 DRM_ERROR("failed to create crtc.\n");
diff --git a/drivers/gpu/drm/exynos/exynos_mixer.c b/drivers/gpu/drm/exynos/exynos_mixer.c
index 2e3bc57ea50e..d181cb1ce71a 100644
--- a/drivers/gpu/drm/exynos/exynos_mixer.c
+++ b/drivers/gpu/drm/exynos/exynos_mixer.c
@@ -37,35 +37,13 @@
37 37
38#include "exynos_drm_drv.h" 38#include "exynos_drm_drv.h"
39#include "exynos_drm_crtc.h" 39#include "exynos_drm_crtc.h"
40#include "exynos_drm_plane.h"
40#include "exynos_drm_iommu.h" 41#include "exynos_drm_iommu.h"
41#include "exynos_mixer.h" 42#include "exynos_mixer.h"
42 43
43#define MIXER_WIN_NR 3 44#define MIXER_WIN_NR 3
44#define MIXER_DEFAULT_WIN 0 45#define MIXER_DEFAULT_WIN 0
45 46
46struct hdmi_win_data {
47 dma_addr_t dma_addr;
48 dma_addr_t chroma_dma_addr;
49 uint32_t pixel_format;
50 unsigned int bpp;
51 unsigned int crtc_x;
52 unsigned int crtc_y;
53 unsigned int crtc_width;
54 unsigned int crtc_height;
55 unsigned int fb_x;
56 unsigned int fb_y;
57 unsigned int fb_width;
58 unsigned int fb_pitch;
59 unsigned int fb_height;
60 unsigned int src_width;
61 unsigned int src_height;
62 unsigned int mode_width;
63 unsigned int mode_height;
64 unsigned int scan_flags;
65 bool enabled;
66 bool resume;
67};
68
69struct mixer_resources { 47struct mixer_resources {
70 int irq; 48 int irq;
71 void __iomem *mixer_regs; 49 void __iomem *mixer_regs;
@@ -90,6 +68,7 @@ struct mixer_context {
90 struct device *dev; 68 struct device *dev;
91 struct drm_device *drm_dev; 69 struct drm_device *drm_dev;
92 struct exynos_drm_crtc *crtc; 70 struct exynos_drm_crtc *crtc;
71 struct exynos_drm_plane planes[MIXER_WIN_NR];
93 int pipe; 72 int pipe;
94 bool interlace; 73 bool interlace;
95 bool powered; 74 bool powered;
@@ -99,7 +78,6 @@ struct mixer_context {
99 78
100 struct mutex mixer_mutex; 79 struct mutex mixer_mutex;
101 struct mixer_resources mixer_res; 80 struct mixer_resources mixer_res;
102 struct hdmi_win_data win_data[MIXER_WIN_NR];
103 enum mixer_version_id mxr_ver; 81 enum mixer_version_id mxr_ver;
104 wait_queue_head_t wait_vsync_queue; 82 wait_queue_head_t wait_vsync_queue;
105 atomic_t wait_vsync_event; 83 atomic_t wait_vsync_event;
@@ -403,7 +381,7 @@ static void vp_video_buffer(struct mixer_context *ctx, int win)
403{ 381{
404 struct mixer_resources *res = &ctx->mixer_res; 382 struct mixer_resources *res = &ctx->mixer_res;
405 unsigned long flags; 383 unsigned long flags;
406 struct hdmi_win_data *win_data; 384 struct exynos_drm_plane *plane;
407 unsigned int x_ratio, y_ratio; 385 unsigned int x_ratio, y_ratio;
408 unsigned int buf_num = 1; 386 unsigned int buf_num = 1;
409 dma_addr_t luma_addr[2], chroma_addr[2]; 387 dma_addr_t luma_addr[2], chroma_addr[2];
@@ -411,9 +389,9 @@ static void vp_video_buffer(struct mixer_context *ctx, int win)
411 bool crcb_mode = false; 389 bool crcb_mode = false;
412 u32 val; 390 u32 val;
413 391
414 win_data = &ctx->win_data[win]; 392 plane = &ctx->planes[win];
415 393
416 switch (win_data->pixel_format) { 394 switch (plane->pixel_format) {
417 case DRM_FORMAT_NV12: 395 case DRM_FORMAT_NV12:
418 crcb_mode = false; 396 crcb_mode = false;
419 buf_num = 2; 397 buf_num = 2;
@@ -421,35 +399,35 @@ static void vp_video_buffer(struct mixer_context *ctx, int win)
421 /* TODO: single buffer format NV12, NV21 */ 399 /* TODO: single buffer format NV12, NV21 */
422 default: 400 default:
423 /* ignore pixel format at disable time */ 401 /* ignore pixel format at disable time */
424 if (!win_data->dma_addr) 402 if (!plane->dma_addr[0])
425 break; 403 break;
426 404
427 DRM_ERROR("pixel format for vp is wrong [%d].\n", 405 DRM_ERROR("pixel format for vp is wrong [%d].\n",
428 win_data->pixel_format); 406 plane->pixel_format);
429 return; 407 return;
430 } 408 }
431 409
432 /* scaling feature: (src << 16) / dst */ 410 /* scaling feature: (src << 16) / dst */
433 x_ratio = (win_data->src_width << 16) / win_data->crtc_width; 411 x_ratio = (plane->src_width << 16) / plane->crtc_width;
434 y_ratio = (win_data->src_height << 16) / win_data->crtc_height; 412 y_ratio = (plane->src_height << 16) / plane->crtc_height;
435 413
436 if (buf_num == 2) { 414 if (buf_num == 2) {
437 luma_addr[0] = win_data->dma_addr; 415 luma_addr[0] = plane->dma_addr[0];
438 chroma_addr[0] = win_data->chroma_dma_addr; 416 chroma_addr[0] = plane->dma_addr[1];
439 } else { 417 } else {
440 luma_addr[0] = win_data->dma_addr; 418 luma_addr[0] = plane->dma_addr[0];
441 chroma_addr[0] = win_data->dma_addr 419 chroma_addr[0] = plane->dma_addr[0]
442 + (win_data->fb_pitch * win_data->fb_height); 420 + (plane->pitch * plane->fb_height);
443 } 421 }
444 422
445 if (win_data->scan_flags & DRM_MODE_FLAG_INTERLACE) { 423 if (plane->scan_flag & DRM_MODE_FLAG_INTERLACE) {
446 ctx->interlace = true; 424 ctx->interlace = true;
447 if (tiled_mode) { 425 if (tiled_mode) {
448 luma_addr[1] = luma_addr[0] + 0x40; 426 luma_addr[1] = luma_addr[0] + 0x40;
449 chroma_addr[1] = chroma_addr[0] + 0x40; 427 chroma_addr[1] = chroma_addr[0] + 0x40;
450 } else { 428 } else {
451 luma_addr[1] = luma_addr[0] + win_data->fb_pitch; 429 luma_addr[1] = luma_addr[0] + plane->pitch;
452 chroma_addr[1] = chroma_addr[0] + win_data->fb_pitch; 430 chroma_addr[1] = chroma_addr[0] + plane->pitch;
453 } 431 }
454 } else { 432 } else {
455 ctx->interlace = false; 433 ctx->interlace = false;
@@ -470,26 +448,26 @@ static void vp_video_buffer(struct mixer_context *ctx, int win)
470 vp_reg_writemask(res, VP_MODE, val, VP_MODE_FMT_MASK); 448 vp_reg_writemask(res, VP_MODE, val, VP_MODE_FMT_MASK);
471 449
472 /* setting size of input image */ 450 /* setting size of input image */
473 vp_reg_write(res, VP_IMG_SIZE_Y, VP_IMG_HSIZE(win_data->fb_pitch) | 451 vp_reg_write(res, VP_IMG_SIZE_Y, VP_IMG_HSIZE(plane->pitch) |
474 VP_IMG_VSIZE(win_data->fb_height)); 452 VP_IMG_VSIZE(plane->fb_height));
475 /* chroma height has to reduced by 2 to avoid chroma distorions */ 453 /* chroma height has to reduced by 2 to avoid chroma distorions */
476 vp_reg_write(res, VP_IMG_SIZE_C, VP_IMG_HSIZE(win_data->fb_pitch) | 454 vp_reg_write(res, VP_IMG_SIZE_C, VP_IMG_HSIZE(plane->pitch) |
477 VP_IMG_VSIZE(win_data->fb_height / 2)); 455 VP_IMG_VSIZE(plane->fb_height / 2));
478 456
479 vp_reg_write(res, VP_SRC_WIDTH, win_data->src_width); 457 vp_reg_write(res, VP_SRC_WIDTH, plane->src_width);
480 vp_reg_write(res, VP_SRC_HEIGHT, win_data->src_height); 458 vp_reg_write(res, VP_SRC_HEIGHT, plane->src_height);
481 vp_reg_write(res, VP_SRC_H_POSITION, 459 vp_reg_write(res, VP_SRC_H_POSITION,
482 VP_SRC_H_POSITION_VAL(win_data->fb_x)); 460 VP_SRC_H_POSITION_VAL(plane->fb_x));
483 vp_reg_write(res, VP_SRC_V_POSITION, win_data->fb_y); 461 vp_reg_write(res, VP_SRC_V_POSITION, plane->fb_y);
484 462
485 vp_reg_write(res, VP_DST_WIDTH, win_data->crtc_width); 463 vp_reg_write(res, VP_DST_WIDTH, plane->crtc_width);
486 vp_reg_write(res, VP_DST_H_POSITION, win_data->crtc_x); 464 vp_reg_write(res, VP_DST_H_POSITION, plane->crtc_x);
487 if (ctx->interlace) { 465 if (ctx->interlace) {
488 vp_reg_write(res, VP_DST_HEIGHT, win_data->crtc_height / 2); 466 vp_reg_write(res, VP_DST_HEIGHT, plane->crtc_height / 2);
489 vp_reg_write(res, VP_DST_V_POSITION, win_data->crtc_y / 2); 467 vp_reg_write(res, VP_DST_V_POSITION, plane->crtc_y / 2);
490 } else { 468 } else {
491 vp_reg_write(res, VP_DST_HEIGHT, win_data->crtc_height); 469 vp_reg_write(res, VP_DST_HEIGHT, plane->crtc_height);
492 vp_reg_write(res, VP_DST_V_POSITION, win_data->crtc_y); 470 vp_reg_write(res, VP_DST_V_POSITION, plane->crtc_y);
493 } 471 }
494 472
495 vp_reg_write(res, VP_H_RATIO, x_ratio); 473 vp_reg_write(res, VP_H_RATIO, x_ratio);
@@ -503,8 +481,8 @@ static void vp_video_buffer(struct mixer_context *ctx, int win)
503 vp_reg_write(res, VP_TOP_C_PTR, chroma_addr[0]); 481 vp_reg_write(res, VP_TOP_C_PTR, chroma_addr[0]);
504 vp_reg_write(res, VP_BOT_C_PTR, chroma_addr[1]); 482 vp_reg_write(res, VP_BOT_C_PTR, chroma_addr[1]);
505 483
506 mixer_cfg_scan(ctx, win_data->mode_height); 484 mixer_cfg_scan(ctx, plane->mode_height);
507 mixer_cfg_rgb_fmt(ctx, win_data->mode_height); 485 mixer_cfg_rgb_fmt(ctx, plane->mode_height);
508 mixer_cfg_layer(ctx, win, true); 486 mixer_cfg_layer(ctx, win, true);
509 mixer_run(ctx); 487 mixer_run(ctx);
510 488
@@ -525,21 +503,21 @@ static void mixer_graph_buffer(struct mixer_context *ctx, int win)
525{ 503{
526 struct mixer_resources *res = &ctx->mixer_res; 504 struct mixer_resources *res = &ctx->mixer_res;
527 unsigned long flags; 505 unsigned long flags;
528 struct hdmi_win_data *win_data; 506 struct exynos_drm_plane *plane;
529 unsigned int x_ratio, y_ratio; 507 unsigned int x_ratio, y_ratio;
530 unsigned int src_x_offset, src_y_offset, dst_x_offset, dst_y_offset; 508 unsigned int src_x_offset, src_y_offset, dst_x_offset, dst_y_offset;
531 dma_addr_t dma_addr; 509 dma_addr_t dma_addr;
532 unsigned int fmt; 510 unsigned int fmt;
533 u32 val; 511 u32 val;
534 512
535 win_data = &ctx->win_data[win]; 513 plane = &ctx->planes[win];
536 514
537 #define RGB565 4 515 #define RGB565 4
538 #define ARGB1555 5 516 #define ARGB1555 5
539 #define ARGB4444 6 517 #define ARGB4444 6
540 #define ARGB8888 7 518 #define ARGB8888 7
541 519
542 switch (win_data->bpp) { 520 switch (plane->bpp) {
543 case 16: 521 case 16:
544 fmt = ARGB4444; 522 fmt = ARGB4444;
545 break; 523 break;
@@ -554,17 +532,17 @@ static void mixer_graph_buffer(struct mixer_context *ctx, int win)
554 x_ratio = 0; 532 x_ratio = 0;
555 y_ratio = 0; 533 y_ratio = 0;
556 534
557 dst_x_offset = win_data->crtc_x; 535 dst_x_offset = plane->crtc_x;
558 dst_y_offset = win_data->crtc_y; 536 dst_y_offset = plane->crtc_y;
559 537
560 /* converting dma address base and source offset */ 538 /* converting dma address base and source offset */
561 dma_addr = win_data->dma_addr 539 dma_addr = plane->dma_addr[0]
562 + (win_data->fb_x * win_data->bpp >> 3) 540 + (plane->fb_x * plane->bpp >> 3)
563 + (win_data->fb_y * win_data->fb_pitch); 541 + (plane->fb_y * plane->pitch);
564 src_x_offset = 0; 542 src_x_offset = 0;
565 src_y_offset = 0; 543 src_y_offset = 0;
566 544
567 if (win_data->scan_flags & DRM_MODE_FLAG_INTERLACE) 545 if (plane->scan_flag & DRM_MODE_FLAG_INTERLACE)
568 ctx->interlace = true; 546 ctx->interlace = true;
569 else 547 else
570 ctx->interlace = false; 548 ctx->interlace = false;
@@ -578,18 +556,18 @@ static void mixer_graph_buffer(struct mixer_context *ctx, int win)
578 556
579 /* setup geometry */ 557 /* setup geometry */
580 mixer_reg_write(res, MXR_GRAPHIC_SPAN(win), 558 mixer_reg_write(res, MXR_GRAPHIC_SPAN(win),
581 win_data->fb_pitch / (win_data->bpp >> 3)); 559 plane->pitch / (plane->bpp >> 3));
582 560
583 /* setup display size */ 561 /* setup display size */
584 if (ctx->mxr_ver == MXR_VER_128_0_0_184 && 562 if (ctx->mxr_ver == MXR_VER_128_0_0_184 &&
585 win == MIXER_DEFAULT_WIN) { 563 win == MIXER_DEFAULT_WIN) {
586 val = MXR_MXR_RES_HEIGHT(win_data->mode_height); 564 val = MXR_MXR_RES_HEIGHT(plane->mode_height);
587 val |= MXR_MXR_RES_WIDTH(win_data->mode_width); 565 val |= MXR_MXR_RES_WIDTH(plane->mode_width);
588 mixer_reg_write(res, MXR_RESOLUTION, val); 566 mixer_reg_write(res, MXR_RESOLUTION, val);
589 } 567 }
590 568
591 val = MXR_GRP_WH_WIDTH(win_data->crtc_width); 569 val = MXR_GRP_WH_WIDTH(plane->crtc_width);
592 val |= MXR_GRP_WH_HEIGHT(win_data->crtc_height); 570 val |= MXR_GRP_WH_HEIGHT(plane->crtc_height);
593 val |= MXR_GRP_WH_H_SCALE(x_ratio); 571 val |= MXR_GRP_WH_H_SCALE(x_ratio);
594 val |= MXR_GRP_WH_V_SCALE(y_ratio); 572 val |= MXR_GRP_WH_V_SCALE(y_ratio);
595 mixer_reg_write(res, MXR_GRAPHIC_WH(win), val); 573 mixer_reg_write(res, MXR_GRAPHIC_WH(win), val);
@@ -607,8 +585,8 @@ static void mixer_graph_buffer(struct mixer_context *ctx, int win)
607 /* set buffer address to mixer */ 585 /* set buffer address to mixer */
608 mixer_reg_write(res, MXR_GRAPHIC_BASE(win), dma_addr); 586 mixer_reg_write(res, MXR_GRAPHIC_BASE(win), dma_addr);
609 587
610 mixer_cfg_scan(ctx, win_data->mode_height); 588 mixer_cfg_scan(ctx, plane->mode_height);
611 mixer_cfg_rgb_fmt(ctx, win_data->mode_height); 589 mixer_cfg_rgb_fmt(ctx, plane->mode_height);
612 mixer_cfg_layer(ctx, win, true); 590 mixer_cfg_layer(ctx, win, true);
613 591
614 /* layer update mandatory for mixer 16.0.33.0 */ 592 /* layer update mandatory for mixer 16.0.33.0 */
@@ -920,59 +898,6 @@ static void mixer_disable_vblank(struct exynos_drm_crtc *crtc)
920 mixer_reg_writemask(res, MXR_INT_EN, 0, MXR_INT_EN_VSYNC); 898 mixer_reg_writemask(res, MXR_INT_EN, 0, MXR_INT_EN_VSYNC);
921} 899}
922 900
923static void mixer_win_mode_set(struct exynos_drm_crtc *crtc,
924 struct exynos_drm_plane *plane)
925{
926 struct mixer_context *mixer_ctx = crtc->ctx;
927 struct hdmi_win_data *win_data;
928 int win;
929
930 if (!plane) {
931 DRM_ERROR("plane is NULL\n");
932 return;
933 }
934
935 DRM_DEBUG_KMS("set [%d]x[%d] at (%d,%d) to [%d]x[%d] at (%d,%d)\n",
936 plane->fb_width, plane->fb_height,
937 plane->fb_x, plane->fb_y,
938 plane->crtc_width, plane->crtc_height,
939 plane->crtc_x, plane->crtc_y);
940
941 win = plane->zpos;
942 if (win == DEFAULT_ZPOS)
943 win = MIXER_DEFAULT_WIN;
944
945 if (win < 0 || win >= MIXER_WIN_NR) {
946 DRM_ERROR("mixer window[%d] is wrong\n", win);
947 return;
948 }
949
950 win_data = &mixer_ctx->win_data[win];
951
952 win_data->dma_addr = plane->dma_addr[0];
953 win_data->chroma_dma_addr = plane->dma_addr[1];
954 win_data->pixel_format = plane->pixel_format;
955 win_data->bpp = plane->bpp;
956
957 win_data->crtc_x = plane->crtc_x;
958 win_data->crtc_y = plane->crtc_y;
959 win_data->crtc_width = plane->crtc_width;
960 win_data->crtc_height = plane->crtc_height;
961
962 win_data->fb_x = plane->fb_x;
963 win_data->fb_y = plane->fb_y;
964 win_data->fb_width = plane->fb_width;
965 win_data->fb_height = plane->fb_height;
966 win_data->fb_pitch = plane->pitch;
967 win_data->src_width = plane->src_width;
968 win_data->src_height = plane->src_height;
969
970 win_data->mode_width = plane->mode_width;
971 win_data->mode_height = plane->mode_height;
972
973 win_data->scan_flags = plane->scan_flag;
974}
975
976static void mixer_win_commit(struct exynos_drm_crtc *crtc, int zpos) 901static void mixer_win_commit(struct exynos_drm_crtc *crtc, int zpos)
977{ 902{
978 struct mixer_context *mixer_ctx = crtc->ctx; 903 struct mixer_context *mixer_ctx = crtc->ctx;
@@ -992,7 +917,7 @@ static void mixer_win_commit(struct exynos_drm_crtc *crtc, int zpos)
992 else 917 else
993 mixer_graph_buffer(mixer_ctx, win); 918 mixer_graph_buffer(mixer_ctx, win);
994 919
995 mixer_ctx->win_data[win].enabled = true; 920 mixer_ctx->planes[win].enabled = true;
996} 921}
997 922
998static void mixer_win_disable(struct exynos_drm_crtc *crtc, int zpos) 923static void mixer_win_disable(struct exynos_drm_crtc *crtc, int zpos)
@@ -1007,7 +932,7 @@ static void mixer_win_disable(struct exynos_drm_crtc *crtc, int zpos)
1007 mutex_lock(&mixer_ctx->mixer_mutex); 932 mutex_lock(&mixer_ctx->mixer_mutex);
1008 if (!mixer_ctx->powered) { 933 if (!mixer_ctx->powered) {
1009 mutex_unlock(&mixer_ctx->mixer_mutex); 934 mutex_unlock(&mixer_ctx->mixer_mutex);
1010 mixer_ctx->win_data[win].resume = false; 935 mixer_ctx->planes[win].resume = false;
1011 return; 936 return;
1012 } 937 }
1013 mutex_unlock(&mixer_ctx->mixer_mutex); 938 mutex_unlock(&mixer_ctx->mixer_mutex);
@@ -1020,7 +945,7 @@ static void mixer_win_disable(struct exynos_drm_crtc *crtc, int zpos)
1020 mixer_vsync_set_update(mixer_ctx, true); 945 mixer_vsync_set_update(mixer_ctx, true);
1021 spin_unlock_irqrestore(&res->reg_slock, flags); 946 spin_unlock_irqrestore(&res->reg_slock, flags);
1022 947
1023 mixer_ctx->win_data[win].enabled = false; 948 mixer_ctx->planes[win].enabled = false;
1024} 949}
1025 950
1026static void mixer_wait_for_vblank(struct exynos_drm_crtc *crtc) 951static void mixer_wait_for_vblank(struct exynos_drm_crtc *crtc)
@@ -1057,12 +982,12 @@ static void mixer_wait_for_vblank(struct exynos_drm_crtc *crtc)
1057 982
1058static void mixer_window_suspend(struct mixer_context *ctx) 983static void mixer_window_suspend(struct mixer_context *ctx)
1059{ 984{
1060 struct hdmi_win_data *win_data; 985 struct exynos_drm_plane *plane;
1061 int i; 986 int i;
1062 987
1063 for (i = 0; i < MIXER_WIN_NR; i++) { 988 for (i = 0; i < MIXER_WIN_NR; i++) {
1064 win_data = &ctx->win_data[i]; 989 plane = &ctx->planes[i];
1065 win_data->resume = win_data->enabled; 990 plane->resume = plane->enabled;
1066 mixer_win_disable(ctx->crtc, i); 991 mixer_win_disable(ctx->crtc, i);
1067 } 992 }
1068 mixer_wait_for_vblank(ctx->crtc); 993 mixer_wait_for_vblank(ctx->crtc);
@@ -1070,14 +995,14 @@ static void mixer_window_suspend(struct mixer_context *ctx)
1070 995
1071static void mixer_window_resume(struct mixer_context *ctx) 996static void mixer_window_resume(struct mixer_context *ctx)
1072{ 997{
1073 struct hdmi_win_data *win_data; 998 struct exynos_drm_plane *plane;
1074 int i; 999 int i;
1075 1000
1076 for (i = 0; i < MIXER_WIN_NR; i++) { 1001 for (i = 0; i < MIXER_WIN_NR; i++) {
1077 win_data = &ctx->win_data[i]; 1002 plane = &ctx->planes[i];
1078 win_data->enabled = win_data->resume; 1003 plane->enabled = plane->resume;
1079 win_data->resume = false; 1004 plane->resume = false;
1080 if (win_data->enabled) 1005 if (plane->enabled)
1081 mixer_win_commit(ctx->crtc, i); 1006 mixer_win_commit(ctx->crtc, i);
1082 } 1007 }
1083} 1008}
@@ -1189,7 +1114,6 @@ static struct exynos_drm_crtc_ops mixer_crtc_ops = {
1189 .enable_vblank = mixer_enable_vblank, 1114 .enable_vblank = mixer_enable_vblank,
1190 .disable_vblank = mixer_disable_vblank, 1115 .disable_vblank = mixer_disable_vblank,
1191 .wait_for_vblank = mixer_wait_for_vblank, 1116 .wait_for_vblank = mixer_wait_for_vblank,
1192 .win_mode_set = mixer_win_mode_set,
1193 .win_commit = mixer_win_commit, 1117 .win_commit = mixer_win_commit,
1194 .win_disable = mixer_win_disable, 1118 .win_disable = mixer_win_disable,
1195}; 1119};
@@ -1253,15 +1177,27 @@ static int mixer_bind(struct device *dev, struct device *manager, void *data)
1253{ 1177{
1254 struct mixer_context *ctx = dev_get_drvdata(dev); 1178 struct mixer_context *ctx = dev_get_drvdata(dev);
1255 struct drm_device *drm_dev = data; 1179 struct drm_device *drm_dev = data;
1256 int ret; 1180 struct exynos_drm_plane *exynos_plane;
1181 enum drm_plane_type type;
1182 int zpos, ret;
1257 1183
1258 ret = mixer_initialize(ctx, drm_dev); 1184 ret = mixer_initialize(ctx, drm_dev);
1259 if (ret) 1185 if (ret)
1260 return ret; 1186 return ret;
1261 1187
1262 ctx->crtc = exynos_drm_crtc_create(drm_dev, ctx->pipe, 1188 for (zpos = 0; zpos < MIXER_WIN_NR; zpos++) {
1263 EXYNOS_DISPLAY_TYPE_HDMI, 1189 type = (zpos == MIXER_DEFAULT_WIN) ? DRM_PLANE_TYPE_PRIMARY :
1264 &mixer_crtc_ops, ctx); 1190 DRM_PLANE_TYPE_OVERLAY;
1191 ret = exynos_plane_init(drm_dev, &ctx->planes[zpos],
1192 1 << ctx->pipe, type);
1193 if (ret)
1194 return ret;
1195 }
1196
1197 exynos_plane = &ctx->planes[MIXER_DEFAULT_WIN];
1198 ctx->crtc = exynos_drm_crtc_create(drm_dev, &exynos_plane->base,
1199 ctx->pipe, EXYNOS_DISPLAY_TYPE_HDMI,
1200 &mixer_crtc_ops, ctx);
1265 if (IS_ERR(ctx->crtc)) { 1201 if (IS_ERR(ctx->crtc)) {
1266 mixer_ctx_remove(ctx); 1202 mixer_ctx_remove(ctx);
1267 ret = PTR_ERR(ctx->crtc); 1203 ret = PTR_ERR(ctx->crtc);