aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/gpu/drm/exynos/exynos5433_drm_decon.c21
-rw-r--r--drivers/gpu/drm/exynos/exynos7_drm_decon.c21
-rw-r--r--drivers/gpu/drm/exynos/exynos_drm_drv.h56
-rw-r--r--drivers/gpu/drm/exynos/exynos_drm_fimd.c33
-rw-r--r--drivers/gpu/drm/exynos/exynos_drm_plane.c125
-rw-r--r--drivers/gpu/drm/exynos/exynos_mixer.c61
6 files changed, 197 insertions, 120 deletions
diff --git a/drivers/gpu/drm/exynos/exynos5433_drm_decon.c b/drivers/gpu/drm/exynos/exynos5433_drm_decon.c
index 0ff0713d2de6..88a79ff049e0 100644
--- a/drivers/gpu/drm/exynos/exynos5433_drm_decon.c
+++ b/drivers/gpu/drm/exynos/exynos5433_drm_decon.c
@@ -260,9 +260,10 @@ static void decon_atomic_begin(struct exynos_drm_crtc *crtc,
260static void decon_update_plane(struct exynos_drm_crtc *crtc, 260static void decon_update_plane(struct exynos_drm_crtc *crtc,
261 struct exynos_drm_plane *plane) 261 struct exynos_drm_plane *plane)
262{ 262{
263 struct exynos_drm_plane_state *state =
264 to_exynos_plane_state(plane->base.state);
263 struct decon_context *ctx = crtc->ctx; 265 struct decon_context *ctx = crtc->ctx;
264 struct drm_plane_state *state = plane->base.state; 266 struct drm_framebuffer *fb = state->base.fb;
265 struct drm_framebuffer *fb = state->fb;
266 unsigned int win = plane->zpos; 267 unsigned int win = plane->zpos;
267 unsigned int bpp = fb->bits_per_pixel >> 3; 268 unsigned int bpp = fb->bits_per_pixel >> 3;
268 unsigned int pitch = fb->pitches[0]; 269 unsigned int pitch = fb->pitches[0];
@@ -272,11 +273,11 @@ static void decon_update_plane(struct exynos_drm_crtc *crtc,
272 if (test_bit(BIT_SUSPENDED, &ctx->flags)) 273 if (test_bit(BIT_SUSPENDED, &ctx->flags))
273 return; 274 return;
274 275
275 val = COORDINATE_X(plane->crtc_x) | COORDINATE_Y(plane->crtc_y); 276 val = COORDINATE_X(state->crtc.x) | COORDINATE_Y(state->crtc.y);
276 writel(val, ctx->addr + DECON_VIDOSDxA(win)); 277 writel(val, ctx->addr + DECON_VIDOSDxA(win));
277 278
278 val = COORDINATE_X(plane->crtc_x + plane->crtc_w - 1) | 279 val = COORDINATE_X(state->crtc.x + state->crtc.w - 1) |
279 COORDINATE_Y(plane->crtc_y + plane->crtc_h - 1); 280 COORDINATE_Y(state->crtc.y + state->crtc.h - 1);
280 writel(val, ctx->addr + DECON_VIDOSDxB(win)); 281 writel(val, ctx->addr + DECON_VIDOSDxB(win));
281 282
282 val = VIDOSD_Wx_ALPHA_R_F(0x0) | VIDOSD_Wx_ALPHA_G_F(0x0) | 283 val = VIDOSD_Wx_ALPHA_R_F(0x0) | VIDOSD_Wx_ALPHA_G_F(0x0) |
@@ -289,15 +290,15 @@ static void decon_update_plane(struct exynos_drm_crtc *crtc,
289 290
290 writel(dma_addr, ctx->addr + DECON_VIDW0xADD0B0(win)); 291 writel(dma_addr, ctx->addr + DECON_VIDW0xADD0B0(win));
291 292
292 val = dma_addr + pitch * plane->crtc_h; 293 val = dma_addr + pitch * state->src.h;
293 writel(val, ctx->addr + DECON_VIDW0xADD1B0(win)); 294 writel(val, ctx->addr + DECON_VIDW0xADD1B0(win));
294 295
295 if (ctx->out_type != IFTYPE_HDMI) 296 if (ctx->out_type != IFTYPE_HDMI)
296 val = BIT_VAL(pitch - plane->crtc_w * bpp, 27, 14) 297 val = BIT_VAL(pitch - state->crtc.w * bpp, 27, 14)
297 | BIT_VAL(plane->crtc_w * bpp, 13, 0); 298 | BIT_VAL(state->crtc.w * bpp, 13, 0);
298 else 299 else
299 val = BIT_VAL(pitch - plane->crtc_w * bpp, 29, 15) 300 val = BIT_VAL(pitch - state->crtc.w * bpp, 29, 15)
300 | BIT_VAL(plane->crtc_w * bpp, 14, 0); 301 | BIT_VAL(state->crtc.w * bpp, 14, 0);
301 writel(val, ctx->addr + DECON_VIDW0xADD2(win)); 302 writel(val, ctx->addr + DECON_VIDW0xADD2(win));
302 303
303 decon_win_set_pixfmt(ctx, win, fb); 304 decon_win_set_pixfmt(ctx, win, fb);
diff --git a/drivers/gpu/drm/exynos/exynos7_drm_decon.c b/drivers/gpu/drm/exynos/exynos7_drm_decon.c
index 1629732574e0..1c62de1a0839 100644
--- a/drivers/gpu/drm/exynos/exynos7_drm_decon.c
+++ b/drivers/gpu/drm/exynos/exynos7_drm_decon.c
@@ -394,9 +394,10 @@ static void decon_atomic_begin(struct exynos_drm_crtc *crtc,
394static void decon_update_plane(struct exynos_drm_crtc *crtc, 394static void decon_update_plane(struct exynos_drm_crtc *crtc,
395 struct exynos_drm_plane *plane) 395 struct exynos_drm_plane *plane)
396{ 396{
397 struct exynos_drm_plane_state *state =
398 to_exynos_plane_state(plane->base.state);
397 struct decon_context *ctx = crtc->ctx; 399 struct decon_context *ctx = crtc->ctx;
398 struct drm_plane_state *state = plane->base.state; 400 struct drm_framebuffer *fb = state->base.fb;
399 struct drm_framebuffer *fb = state->fb;
400 int padding; 401 int padding;
401 unsigned long val, alpha; 402 unsigned long val, alpha;
402 unsigned int last_x; 403 unsigned int last_x;
@@ -429,22 +430,22 @@ static void decon_update_plane(struct exynos_drm_crtc *crtc,
429 writel(fb->height, ctx->regs + VIDW_WHOLE_Y(win)); 430 writel(fb->height, ctx->regs + VIDW_WHOLE_Y(win));
430 431
431 /* offset from the start of the buffer to read */ 432 /* offset from the start of the buffer to read */
432 writel(plane->src_x, ctx->regs + VIDW_OFFSET_X(win)); 433 writel(state->src.x, ctx->regs + VIDW_OFFSET_X(win));
433 writel(plane->src_y, ctx->regs + VIDW_OFFSET_Y(win)); 434 writel(state->src.y, ctx->regs + VIDW_OFFSET_Y(win));
434 435
435 DRM_DEBUG_KMS("start addr = 0x%lx\n", 436 DRM_DEBUG_KMS("start addr = 0x%lx\n",
436 (unsigned long)val); 437 (unsigned long)val);
437 DRM_DEBUG_KMS("ovl_width = %d, ovl_height = %d\n", 438 DRM_DEBUG_KMS("ovl_width = %d, ovl_height = %d\n",
438 plane->crtc_w, plane->crtc_h); 439 state->crtc.w, state->crtc.h);
439 440
440 val = VIDOSDxA_TOPLEFT_X(plane->crtc_x) | 441 val = VIDOSDxA_TOPLEFT_X(state->crtc.x) |
441 VIDOSDxA_TOPLEFT_Y(plane->crtc_y); 442 VIDOSDxA_TOPLEFT_Y(state->crtc.y);
442 writel(val, ctx->regs + VIDOSD_A(win)); 443 writel(val, ctx->regs + VIDOSD_A(win));
443 444
444 last_x = plane->crtc_x + plane->crtc_w; 445 last_x = state->crtc.x + state->crtc.w;
445 if (last_x) 446 if (last_x)
446 last_x--; 447 last_x--;
447 last_y = plane->crtc_y + plane->crtc_h; 448 last_y = state->crtc.y + state->crtc.h;
448 if (last_y) 449 if (last_y)
449 last_y--; 450 last_y--;
450 451
@@ -453,7 +454,7 @@ static void decon_update_plane(struct exynos_drm_crtc *crtc,
453 writel(val, ctx->regs + VIDOSD_B(win)); 454 writel(val, ctx->regs + VIDOSD_B(win));
454 455
455 DRM_DEBUG_KMS("osd pos: tx = %d, ty = %d, bx = %d, by = %d\n", 456 DRM_DEBUG_KMS("osd pos: tx = %d, ty = %d, bx = %d, by = %d\n",
456 plane->crtc_x, plane->crtc_y, last_x, last_y); 457 state->crtc.x, state->crtc.y, last_x, last_y);
457 458
458 /* OSD alpha */ 459 /* OSD alpha */
459 alpha = VIDOSDxC_ALPHA0_R_F(0x0) | 460 alpha = VIDOSDxC_ALPHA0_R_F(0x0) |
diff --git a/drivers/gpu/drm/exynos/exynos_drm_drv.h b/drivers/gpu/drm/exynos/exynos_drm_drv.h
index dc41ffb26eb9..482ed2c2ed89 100644
--- a/drivers/gpu/drm/exynos/exynos_drm_drv.h
+++ b/drivers/gpu/drm/exynos/exynos_drm_drv.h
@@ -38,22 +38,44 @@ enum exynos_drm_output_type {
38 EXYNOS_DISPLAY_TYPE_VIDI, 38 EXYNOS_DISPLAY_TYPE_VIDI,
39}; 39};
40 40
41struct exynos_drm_rect {
42 unsigned int x, y;
43 unsigned int w, h;
44};
45
41/* 46/*
42 * Exynos drm common overlay structure. 47 * Exynos drm plane state structure.
43 * 48 *
44 * @base: plane object 49 * @base: plane_state object (contains drm_framebuffer pointer)
45 * @src_x: offset x on a framebuffer to be displayed. 50 * @src: rectangle of the source image data to be displayed (clipped to
46 * - the unit is screen coordinates. 51 * visible part).
47 * @src_y: offset y on a framebuffer to be displayed. 52 * @crtc: rectangle of the target image position on hardware screen
48 * - the unit is screen coordinates. 53 * (clipped to visible part).
49 * @src_w: width of a partial image to be displayed from framebuffer.
50 * @src_h: height of a partial image to be displayed from framebuffer.
51 * @crtc_x: offset x on hardware screen.
52 * @crtc_y: offset y on hardware screen.
53 * @crtc_w: window width to be displayed (hardware screen).
54 * @crtc_h: window height to be displayed (hardware screen).
55 * @h_ratio: horizontal scaling ratio, 16.16 fixed point 54 * @h_ratio: horizontal scaling ratio, 16.16 fixed point
56 * @v_ratio: vertical scaling ratio, 16.16 fixed point 55 * @v_ratio: vertical scaling ratio, 16.16 fixed point
56 *
57 * this structure consists plane state data that will be applied to hardware
58 * specific overlay info.
59 */
60
61struct exynos_drm_plane_state {
62 struct drm_plane_state base;
63 struct exynos_drm_rect crtc;
64 struct exynos_drm_rect src;
65 unsigned int h_ratio;
66 unsigned int v_ratio;
67};
68
69static inline struct exynos_drm_plane_state *
70to_exynos_plane_state(struct drm_plane_state *state)
71{
72 return container_of(state, struct exynos_drm_plane_state, base);
73}
74
75/*
76 * Exynos drm common overlay structure.
77 *
78 * @base: plane object
57 * @zpos: order of overlay layer(z position). 79 * @zpos: order of overlay layer(z position).
58 * 80 *
59 * this structure is common to exynos SoC and its contents would be copied 81 * this structure is common to exynos SoC and its contents would be copied
@@ -62,16 +84,6 @@ enum exynos_drm_output_type {
62 84
63struct exynos_drm_plane { 85struct exynos_drm_plane {
64 struct drm_plane base; 86 struct drm_plane base;
65 unsigned int src_x;
66 unsigned int src_y;
67 unsigned int src_w;
68 unsigned int src_h;
69 unsigned int crtc_x;
70 unsigned int crtc_y;
71 unsigned int crtc_w;
72 unsigned int crtc_h;
73 unsigned int h_ratio;
74 unsigned int v_ratio;
75 unsigned int zpos; 87 unsigned int zpos;
76 struct drm_framebuffer *pending_fb; 88 struct drm_framebuffer *pending_fb;
77}; 89};
diff --git a/drivers/gpu/drm/exynos/exynos_drm_fimd.c b/drivers/gpu/drm/exynos/exynos_drm_fimd.c
index ffcc498f5afe..739544871589 100644
--- a/drivers/gpu/drm/exynos/exynos_drm_fimd.c
+++ b/drivers/gpu/drm/exynos/exynos_drm_fimd.c
@@ -641,9 +641,10 @@ static void fimd_atomic_flush(struct exynos_drm_crtc *crtc,
641static void fimd_update_plane(struct exynos_drm_crtc *crtc, 641static void fimd_update_plane(struct exynos_drm_crtc *crtc,
642 struct exynos_drm_plane *plane) 642 struct exynos_drm_plane *plane)
643{ 643{
644 struct exynos_drm_plane_state *state =
645 to_exynos_plane_state(plane->base.state);
644 struct fimd_context *ctx = crtc->ctx; 646 struct fimd_context *ctx = crtc->ctx;
645 struct drm_plane_state *state = plane->base.state; 647 struct drm_framebuffer *fb = state->base.fb;
646 struct drm_framebuffer *fb = state->fb;
647 dma_addr_t dma_addr; 648 dma_addr_t dma_addr;
648 unsigned long val, size, offset; 649 unsigned long val, size, offset;
649 unsigned int last_x, last_y, buf_offsize, line_size; 650 unsigned int last_x, last_y, buf_offsize, line_size;
@@ -654,8 +655,8 @@ static void fimd_update_plane(struct exynos_drm_crtc *crtc,
654 if (ctx->suspended) 655 if (ctx->suspended)
655 return; 656 return;
656 657
657 offset = plane->src_x * bpp; 658 offset = state->src.x * bpp;
658 offset += plane->src_y * pitch; 659 offset += state->src.y * pitch;
659 660
660 /* buffer start address */ 661 /* buffer start address */
661 dma_addr = exynos_drm_fb_dma_addr(fb, 0) + offset; 662 dma_addr = exynos_drm_fb_dma_addr(fb, 0) + offset;
@@ -663,18 +664,18 @@ static void fimd_update_plane(struct exynos_drm_crtc *crtc,
663 writel(val, ctx->regs + VIDWx_BUF_START(win, 0)); 664 writel(val, ctx->regs + VIDWx_BUF_START(win, 0));
664 665
665 /* buffer end address */ 666 /* buffer end address */
666 size = pitch * plane->crtc_h; 667 size = pitch * state->crtc.h;
667 val = (unsigned long)(dma_addr + size); 668 val = (unsigned long)(dma_addr + size);
668 writel(val, ctx->regs + VIDWx_BUF_END(win, 0)); 669 writel(val, ctx->regs + VIDWx_BUF_END(win, 0));
669 670
670 DRM_DEBUG_KMS("start addr = 0x%lx, end addr = 0x%lx, size = 0x%lx\n", 671 DRM_DEBUG_KMS("start addr = 0x%lx, end addr = 0x%lx, size = 0x%lx\n",
671 (unsigned long)dma_addr, val, size); 672 (unsigned long)dma_addr, val, size);
672 DRM_DEBUG_KMS("ovl_width = %d, ovl_height = %d\n", 673 DRM_DEBUG_KMS("ovl_width = %d, ovl_height = %d\n",
673 plane->crtc_w, plane->crtc_h); 674 state->crtc.w, state->crtc.h);
674 675
675 /* buffer size */ 676 /* buffer size */
676 buf_offsize = pitch - (plane->crtc_w * bpp); 677 buf_offsize = pitch - (state->crtc.w * bpp);
677 line_size = plane->crtc_w * bpp; 678 line_size = state->crtc.w * bpp;
678 val = VIDW_BUF_SIZE_OFFSET(buf_offsize) | 679 val = VIDW_BUF_SIZE_OFFSET(buf_offsize) |
679 VIDW_BUF_SIZE_PAGEWIDTH(line_size) | 680 VIDW_BUF_SIZE_PAGEWIDTH(line_size) |
680 VIDW_BUF_SIZE_OFFSET_E(buf_offsize) | 681 VIDW_BUF_SIZE_OFFSET_E(buf_offsize) |
@@ -682,16 +683,16 @@ static void fimd_update_plane(struct exynos_drm_crtc *crtc,
682 writel(val, ctx->regs + VIDWx_BUF_SIZE(win, 0)); 683 writel(val, ctx->regs + VIDWx_BUF_SIZE(win, 0));
683 684
684 /* OSD position */ 685 /* OSD position */
685 val = VIDOSDxA_TOPLEFT_X(plane->crtc_x) | 686 val = VIDOSDxA_TOPLEFT_X(state->crtc.x) |
686 VIDOSDxA_TOPLEFT_Y(plane->crtc_y) | 687 VIDOSDxA_TOPLEFT_Y(state->crtc.y) |
687 VIDOSDxA_TOPLEFT_X_E(plane->crtc_x) | 688 VIDOSDxA_TOPLEFT_X_E(state->crtc.x) |
688 VIDOSDxA_TOPLEFT_Y_E(plane->crtc_y); 689 VIDOSDxA_TOPLEFT_Y_E(state->crtc.y);
689 writel(val, ctx->regs + VIDOSD_A(win)); 690 writel(val, ctx->regs + VIDOSD_A(win));
690 691
691 last_x = plane->crtc_x + plane->crtc_w; 692 last_x = state->crtc.x + state->crtc.w;
692 if (last_x) 693 if (last_x)
693 last_x--; 694 last_x--;
694 last_y = plane->crtc_y + plane->crtc_h; 695 last_y = state->crtc.y + state->crtc.h;
695 if (last_y) 696 if (last_y)
696 last_y--; 697 last_y--;
697 698
@@ -701,14 +702,14 @@ static void fimd_update_plane(struct exynos_drm_crtc *crtc,
701 writel(val, ctx->regs + VIDOSD_B(win)); 702 writel(val, ctx->regs + VIDOSD_B(win));
702 703
703 DRM_DEBUG_KMS("osd pos: tx = %d, ty = %d, bx = %d, by = %d\n", 704 DRM_DEBUG_KMS("osd pos: tx = %d, ty = %d, bx = %d, by = %d\n",
704 plane->crtc_x, plane->crtc_y, last_x, last_y); 705 state->crtc.x, state->crtc.y, last_x, last_y);
705 706
706 /* OSD size */ 707 /* OSD size */
707 if (win != 3 && win != 4) { 708 if (win != 3 && win != 4) {
708 u32 offset = VIDOSD_D(win); 709 u32 offset = VIDOSD_D(win);
709 if (win == 0) 710 if (win == 0)
710 offset = VIDOSD_C(win); 711 offset = VIDOSD_C(win);
711 val = plane->crtc_w * plane->crtc_h; 712 val = state->crtc.w * state->crtc.h;
712 writel(val, ctx->regs + offset); 713 writel(val, ctx->regs + offset);
713 714
714 DRM_DEBUG_KMS("osd size = 0x%x\n", (unsigned int)val); 715 DRM_DEBUG_KMS("osd size = 0x%x\n", (unsigned int)val);
diff --git a/drivers/gpu/drm/exynos/exynos_drm_plane.c b/drivers/gpu/drm/exynos/exynos_drm_plane.c
index c725409421b8..365a738042e2 100644
--- a/drivers/gpu/drm/exynos/exynos_drm_plane.c
+++ b/drivers/gpu/drm/exynos/exynos_drm_plane.c
@@ -56,19 +56,35 @@ static int exynos_plane_get_size(int start, unsigned length, unsigned last)
56 return size; 56 return size;
57} 57}
58 58
59static void exynos_plane_mode_set(struct drm_plane *plane, 59static void exynos_plane_mode_set(struct exynos_drm_plane_state *exynos_state)
60 struct drm_crtc *crtc, 60
61 struct drm_framebuffer *fb,
62 int crtc_x, int crtc_y,
63 unsigned int crtc_w, unsigned int crtc_h,
64 uint32_t src_x, uint32_t src_y,
65 uint32_t src_w, uint32_t src_h)
66{ 61{
67 struct exynos_drm_plane *exynos_plane = to_exynos_plane(plane); 62 struct drm_plane_state *state = &exynos_state->base;
63 struct drm_crtc *crtc = exynos_state->base.crtc;
68 struct drm_display_mode *mode = &crtc->state->adjusted_mode; 64 struct drm_display_mode *mode = &crtc->state->adjusted_mode;
65 int crtc_x, crtc_y;
66 unsigned int crtc_w, crtc_h;
67 unsigned int src_x, src_y;
68 unsigned int src_w, src_h;
69 unsigned int actual_w; 69 unsigned int actual_w;
70 unsigned int actual_h; 70 unsigned int actual_h;
71 71
72 /*
73 * The original src/dest coordinates are stored in exynos_state->base,
74 * but we want to keep another copy internal to our driver that we can
75 * clip/modify ourselves.
76 */
77
78 crtc_x = state->crtc_x;
79 crtc_y = state->crtc_y;
80 crtc_w = state->crtc_w;
81 crtc_h = state->crtc_h;
82
83 src_x = state->src_x >> 16;
84 src_y = state->src_y >> 16;
85 src_w = state->src_w >> 16;
86 src_h = state->src_h >> 16;
87
72 actual_w = exynos_plane_get_size(crtc_x, crtc_w, mode->hdisplay); 88 actual_w = exynos_plane_get_size(crtc_x, crtc_w, mode->hdisplay);
73 actual_h = exynos_plane_get_size(crtc_y, crtc_h, mode->vdisplay); 89 actual_h = exynos_plane_get_size(crtc_y, crtc_h, mode->vdisplay);
74 90
@@ -85,46 +101,93 @@ static void exynos_plane_mode_set(struct drm_plane *plane,
85 } 101 }
86 102
87 /* set ratio */ 103 /* set ratio */
88 exynos_plane->h_ratio = (src_w << 16) / crtc_w; 104 exynos_state->h_ratio = (src_w << 16) / crtc_w;
89 exynos_plane->v_ratio = (src_h << 16) / crtc_h; 105 exynos_state->v_ratio = (src_h << 16) / crtc_h;
90 106
91 /* set drm framebuffer data. */ 107 /* set drm framebuffer data. */
92 exynos_plane->src_x = src_x; 108 exynos_state->src.x = src_x;
93 exynos_plane->src_y = src_y; 109 exynos_state->src.y = src_y;
94 exynos_plane->src_w = (actual_w * exynos_plane->h_ratio) >> 16; 110 exynos_state->src.w = (actual_w * exynos_state->h_ratio) >> 16;
95 exynos_plane->src_h = (actual_h * exynos_plane->v_ratio) >> 16; 111 exynos_state->src.h = (actual_h * exynos_state->v_ratio) >> 16;
96 112
97 /* set plane range to be displayed. */ 113 /* set plane range to be displayed. */
98 exynos_plane->crtc_x = crtc_x; 114 exynos_state->crtc.x = crtc_x;
99 exynos_plane->crtc_y = crtc_y; 115 exynos_state->crtc.y = crtc_y;
100 exynos_plane->crtc_w = actual_w; 116 exynos_state->crtc.w = actual_w;
101 exynos_plane->crtc_h = actual_h; 117 exynos_state->crtc.h = actual_h;
102 118
103 DRM_DEBUG_KMS("plane : offset_x/y(%d,%d), width/height(%d,%d)", 119 DRM_DEBUG_KMS("plane : offset_x/y(%d,%d), width/height(%d,%d)",
104 exynos_plane->crtc_x, exynos_plane->crtc_y, 120 exynos_state->crtc.x, exynos_state->crtc.y,
105 exynos_plane->crtc_w, exynos_plane->crtc_h); 121 exynos_state->crtc.w, exynos_state->crtc.h);
122}
106 123
107 plane->crtc = crtc; 124static void exynos_drm_plane_reset(struct drm_plane *plane)
125{
126 struct exynos_drm_plane_state *exynos_state;
127
128 if (plane->state) {
129 exynos_state = to_exynos_plane_state(plane->state);
130 if (exynos_state->base.fb)
131 drm_framebuffer_unreference(exynos_state->base.fb);
132 kfree(exynos_state);
133 plane->state = NULL;
134 }
135
136 exynos_state = kzalloc(sizeof(*exynos_state), GFP_KERNEL);
137 if (exynos_state) {
138 plane->state = &exynos_state->base;
139 plane->state->plane = plane;
140 }
141}
142
143static struct drm_plane_state *
144exynos_drm_plane_duplicate_state(struct drm_plane *plane)
145{
146 struct exynos_drm_plane_state *exynos_state;
147 struct exynos_drm_plane_state *copy;
148
149 exynos_state = to_exynos_plane_state(plane->state);
150 copy = kzalloc(sizeof(*exynos_state), GFP_KERNEL);
151 if (!copy)
152 return NULL;
153
154 __drm_atomic_helper_plane_duplicate_state(plane, &copy->base);
155 return &copy->base;
156}
157
158static void exynos_drm_plane_destroy_state(struct drm_plane *plane,
159 struct drm_plane_state *old_state)
160{
161 struct exynos_drm_plane_state *old_exynos_state =
162 to_exynos_plane_state(old_state);
163 __drm_atomic_helper_plane_destroy_state(plane, old_state);
164 kfree(old_exynos_state);
108} 165}
109 166
110static struct drm_plane_funcs exynos_plane_funcs = { 167static struct drm_plane_funcs exynos_plane_funcs = {
111 .update_plane = drm_atomic_helper_update_plane, 168 .update_plane = drm_atomic_helper_update_plane,
112 .disable_plane = drm_atomic_helper_disable_plane, 169 .disable_plane = drm_atomic_helper_disable_plane,
113 .destroy = drm_plane_cleanup, 170 .destroy = drm_plane_cleanup,
114 .reset = drm_atomic_helper_plane_reset, 171 .reset = exynos_drm_plane_reset,
115 .atomic_duplicate_state = drm_atomic_helper_plane_duplicate_state, 172 .atomic_duplicate_state = exynos_drm_plane_duplicate_state,
116 .atomic_destroy_state = drm_atomic_helper_plane_destroy_state, 173 .atomic_destroy_state = exynos_drm_plane_destroy_state,
117}; 174};
118 175
119static int exynos_plane_atomic_check(struct drm_plane *plane, 176static int exynos_plane_atomic_check(struct drm_plane *plane,
120 struct drm_plane_state *state) 177 struct drm_plane_state *state)
121{ 178{
122 struct exynos_drm_plane *exynos_plane = to_exynos_plane(plane); 179 struct exynos_drm_plane *exynos_plane = to_exynos_plane(plane);
180 struct exynos_drm_plane_state *exynos_state =
181 to_exynos_plane_state(state);
182 int ret = 0;
123 183
124 if (!state->fb) 184 if (!state->crtc || !state->fb)
125 return 0; 185 return 0;
126 186
127 return 0; 187 /* translate state into exynos_state */
188 exynos_plane_mode_set(exynos_state);
189
190 return ret;
128} 191}
129 192
130static void exynos_plane_atomic_update(struct drm_plane *plane, 193static void exynos_plane_atomic_update(struct drm_plane *plane,
@@ -137,12 +200,7 @@ static void exynos_plane_atomic_update(struct drm_plane *plane,
137 if (!state->crtc) 200 if (!state->crtc)
138 return; 201 return;
139 202
140 exynos_plane_mode_set(plane, state->crtc, state->fb, 203 plane->crtc = state->crtc;
141 state->crtc_x, state->crtc_y,
142 state->crtc_w, state->crtc_h,
143 state->src_x >> 16, state->src_y >> 16,
144 state->src_w >> 16, state->src_h >> 16);
145
146 exynos_plane->pending_fb = state->fb; 204 exynos_plane->pending_fb = state->fb;
147 205
148 if (exynos_crtc->ops->update_plane) 206 if (exynos_crtc->ops->update_plane)
@@ -159,8 +217,7 @@ static void exynos_plane_atomic_disable(struct drm_plane *plane,
159 return; 217 return;
160 218
161 if (exynos_crtc->ops->disable_plane) 219 if (exynos_crtc->ops->disable_plane)
162 exynos_crtc->ops->disable_plane(exynos_crtc, 220 exynos_crtc->ops->disable_plane(exynos_crtc, exynos_plane);
163 exynos_plane);
164} 221}
165 222
166static const struct drm_plane_helper_funcs plane_helper_funcs = { 223static const struct drm_plane_helper_funcs plane_helper_funcs = {
diff --git a/drivers/gpu/drm/exynos/exynos_mixer.c b/drivers/gpu/drm/exynos/exynos_mixer.c
index f40de82848dc..154537a23c90 100644
--- a/drivers/gpu/drm/exynos/exynos_mixer.c
+++ b/drivers/gpu/drm/exynos/exynos_mixer.c
@@ -400,10 +400,11 @@ static void mixer_stop(struct mixer_context *ctx)
400static void vp_video_buffer(struct mixer_context *ctx, 400static void vp_video_buffer(struct mixer_context *ctx,
401 struct exynos_drm_plane *plane) 401 struct exynos_drm_plane *plane)
402{ 402{
403 struct exynos_drm_plane_state *state =
404 to_exynos_plane_state(plane->base.state);
403 struct mixer_resources *res = &ctx->mixer_res; 405 struct mixer_resources *res = &ctx->mixer_res;
404 struct drm_plane_state *state = plane->base.state; 406 struct drm_framebuffer *fb = state->base.fb;
405 struct drm_framebuffer *fb = state->fb; 407 struct drm_display_mode *mode = &state->base.crtc->mode;
406 struct drm_display_mode *mode = &state->crtc->mode;
407 unsigned long flags; 408 unsigned long flags;
408 dma_addr_t luma_addr[2], chroma_addr[2]; 409 dma_addr_t luma_addr[2], chroma_addr[2];
409 bool tiled_mode = false; 410 bool tiled_mode = false;
@@ -460,24 +461,24 @@ static void vp_video_buffer(struct mixer_context *ctx,
460 vp_reg_write(res, VP_IMG_SIZE_C, VP_IMG_HSIZE(fb->pitches[0]) | 461 vp_reg_write(res, VP_IMG_SIZE_C, VP_IMG_HSIZE(fb->pitches[0]) |
461 VP_IMG_VSIZE(fb->height / 2)); 462 VP_IMG_VSIZE(fb->height / 2));
462 463
463 vp_reg_write(res, VP_SRC_WIDTH, plane->src_w); 464 vp_reg_write(res, VP_SRC_WIDTH, state->src.w);
464 vp_reg_write(res, VP_SRC_HEIGHT, plane->src_h); 465 vp_reg_write(res, VP_SRC_HEIGHT, state->src.h);
465 vp_reg_write(res, VP_SRC_H_POSITION, 466 vp_reg_write(res, VP_SRC_H_POSITION,
466 VP_SRC_H_POSITION_VAL(plane->src_x)); 467 VP_SRC_H_POSITION_VAL(state->src.x));
467 vp_reg_write(res, VP_SRC_V_POSITION, plane->src_y); 468 vp_reg_write(res, VP_SRC_V_POSITION, state->src.y);
468 469
469 vp_reg_write(res, VP_DST_WIDTH, plane->crtc_w); 470 vp_reg_write(res, VP_DST_WIDTH, state->crtc.w);
470 vp_reg_write(res, VP_DST_H_POSITION, plane->crtc_x); 471 vp_reg_write(res, VP_DST_H_POSITION, state->crtc.x);
471 if (ctx->interlace) { 472 if (ctx->interlace) {
472 vp_reg_write(res, VP_DST_HEIGHT, plane->crtc_h / 2); 473 vp_reg_write(res, VP_DST_HEIGHT, state->crtc.h / 2);
473 vp_reg_write(res, VP_DST_V_POSITION, plane->crtc_y / 2); 474 vp_reg_write(res, VP_DST_V_POSITION, state->crtc.y / 2);
474 } else { 475 } else {
475 vp_reg_write(res, VP_DST_HEIGHT, plane->crtc_h); 476 vp_reg_write(res, VP_DST_HEIGHT, state->crtc.h);
476 vp_reg_write(res, VP_DST_V_POSITION, plane->crtc_y); 477 vp_reg_write(res, VP_DST_V_POSITION, state->crtc.y);
477 } 478 }
478 479
479 vp_reg_write(res, VP_H_RATIO, plane->h_ratio); 480 vp_reg_write(res, VP_H_RATIO, state->h_ratio);
480 vp_reg_write(res, VP_V_RATIO, plane->v_ratio); 481 vp_reg_write(res, VP_V_RATIO, state->v_ratio);
481 482
482 vp_reg_write(res, VP_ENDIAN_MODE, VP_ENDIAN_MODE_LITTLE); 483 vp_reg_write(res, VP_ENDIAN_MODE, VP_ENDIAN_MODE_LITTLE);
483 484
@@ -509,15 +510,18 @@ static void mixer_layer_update(struct mixer_context *ctx)
509static int mixer_setup_scale(const struct exynos_drm_plane *plane, 510static int mixer_setup_scale(const struct exynos_drm_plane *plane,
510 unsigned int *x_ratio, unsigned int *y_ratio) 511 unsigned int *x_ratio, unsigned int *y_ratio)
511{ 512{
512 if (plane->crtc_w != plane->src_w) { 513 struct exynos_drm_plane_state *state =
513 if (plane->crtc_w == 2 * plane->src_w) 514 to_exynos_plane_state(plane->base.state);
515
516 if (state->crtc.w != state->src.w) {
517 if (state->crtc.w == 2 * state->src.w)
514 *x_ratio = 1; 518 *x_ratio = 1;
515 else 519 else
516 goto fail; 520 goto fail;
517 } 521 }
518 522
519 if (plane->crtc_h != plane->src_h) { 523 if (state->crtc.h != state->src.h) {
520 if (plane->crtc_h == 2 * plane->src_h) 524 if (state->crtc.h == 2 * state->src.h)
521 *y_ratio = 1; 525 *y_ratio = 1;
522 else 526 else
523 goto fail; 527 goto fail;
@@ -533,10 +537,11 @@ fail:
533static void mixer_graph_buffer(struct mixer_context *ctx, 537static void mixer_graph_buffer(struct mixer_context *ctx,
534 struct exynos_drm_plane *plane) 538 struct exynos_drm_plane *plane)
535{ 539{
540 struct exynos_drm_plane_state *state =
541 to_exynos_plane_state(plane->base.state);
536 struct mixer_resources *res = &ctx->mixer_res; 542 struct mixer_resources *res = &ctx->mixer_res;
537 struct drm_plane_state *state = plane->base.state; 543 struct drm_framebuffer *fb = state->base.fb;
538 struct drm_framebuffer *fb = state->fb; 544 struct drm_display_mode *mode = &state->base.crtc->mode;
539 struct drm_display_mode *mode = &state->crtc->mode;
540 unsigned long flags; 545 unsigned long flags;
541 unsigned int win = plane->zpos; 546 unsigned int win = plane->zpos;
542 unsigned int x_ratio = 0, y_ratio = 0; 547 unsigned int x_ratio = 0, y_ratio = 0;
@@ -572,13 +577,13 @@ static void mixer_graph_buffer(struct mixer_context *ctx,
572 if (mixer_setup_scale(plane, &x_ratio, &y_ratio)) 577 if (mixer_setup_scale(plane, &x_ratio, &y_ratio))
573 return; 578 return;
574 579
575 dst_x_offset = plane->crtc_x; 580 dst_x_offset = state->crtc.x;
576 dst_y_offset = plane->crtc_y; 581 dst_y_offset = state->crtc.y;
577 582
578 /* converting dma address base and source offset */ 583 /* converting dma address base and source offset */
579 dma_addr = exynos_drm_fb_dma_addr(fb, 0) 584 dma_addr = exynos_drm_fb_dma_addr(fb, 0)
580 + (plane->src_x * fb->bits_per_pixel >> 3) 585 + (state->src.x * fb->bits_per_pixel >> 3)
581 + (plane->src_y * fb->pitches[0]); 586 + (state->src.y * fb->pitches[0]);
582 src_x_offset = 0; 587 src_x_offset = 0;
583 src_y_offset = 0; 588 src_y_offset = 0;
584 589
@@ -606,8 +611,8 @@ static void mixer_graph_buffer(struct mixer_context *ctx,
606 mixer_reg_write(res, MXR_RESOLUTION, val); 611 mixer_reg_write(res, MXR_RESOLUTION, val);
607 } 612 }
608 613
609 val = MXR_GRP_WH_WIDTH(plane->src_w); 614 val = MXR_GRP_WH_WIDTH(state->src.w);
610 val |= MXR_GRP_WH_HEIGHT(plane->src_h); 615 val |= MXR_GRP_WH_HEIGHT(state->src.h);
611 val |= MXR_GRP_WH_H_SCALE(x_ratio); 616 val |= MXR_GRP_WH_H_SCALE(x_ratio);
612 val |= MXR_GRP_WH_V_SCALE(y_ratio); 617 val |= MXR_GRP_WH_V_SCALE(y_ratio);
613 mixer_reg_write(res, MXR_GRAPHIC_WH(win), val); 618 mixer_reg_write(res, MXR_GRAPHIC_WH(win), val);