diff options
author | Marek Szyprowski <m.szyprowski@samsung.com> | 2015-11-30 08:53:22 -0500 |
---|---|---|
committer | Inki Dae <daeinki@gmail.com> | 2015-12-13 08:22:55 -0500 |
commit | 0114f404aefb767ff006b066ca2db4d43041ef0d (patch) | |
tree | 261032610dc15a487ef27bd72187c9915f657880 | |
parent | 0488f50e998dfa42a99a1e44882da408e71a09b2 (diff) |
drm/exynos: introduce exynos_drm_plane_state structure
This patch introduces exynos_drm_plane_state structure, which subclasses
drm_plane_state and holds precalculated data suitable for configuring
Exynos hardware.
Signed-off-by: Marek Szyprowski <m.szyprowski@samsung.com>
Reviewed-by: Gustavo Padovan <gustavo.padovan@collabora.co.uk>
Signed-off-by: Inki Dae <inki.dae@samsung.com>
-rw-r--r-- | drivers/gpu/drm/exynos/exynos5433_drm_decon.c | 21 | ||||
-rw-r--r-- | drivers/gpu/drm/exynos/exynos7_drm_decon.c | 21 | ||||
-rw-r--r-- | drivers/gpu/drm/exynos/exynos_drm_drv.h | 56 | ||||
-rw-r--r-- | drivers/gpu/drm/exynos/exynos_drm_fimd.c | 33 | ||||
-rw-r--r-- | drivers/gpu/drm/exynos/exynos_drm_plane.c | 125 | ||||
-rw-r--r-- | drivers/gpu/drm/exynos/exynos_mixer.c | 61 |
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, | |||
260 | static void decon_update_plane(struct exynos_drm_crtc *crtc, | 260 | static 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, | |||
394 | static void decon_update_plane(struct exynos_drm_crtc *crtc, | 394 | static 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 | ||
41 | struct 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 | |||
61 | struct 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 | |||
69 | static inline struct exynos_drm_plane_state * | ||
70 | to_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 | ||
63 | struct exynos_drm_plane { | 85 | struct 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, | |||
641 | static void fimd_update_plane(struct exynos_drm_crtc *crtc, | 641 | static 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 | ||
59 | static void exynos_plane_mode_set(struct drm_plane *plane, | 59 | static 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; | 124 | static 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 | |||
143 | static struct drm_plane_state * | ||
144 | exynos_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, ©->base); | ||
155 | return ©->base; | ||
156 | } | ||
157 | |||
158 | static 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 | ||
110 | static struct drm_plane_funcs exynos_plane_funcs = { | 167 | static 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 | ||
119 | static int exynos_plane_atomic_check(struct drm_plane *plane, | 176 | static 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 | ||
130 | static void exynos_plane_atomic_update(struct drm_plane *plane, | 193 | static 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 | ||
166 | static const struct drm_plane_helper_funcs plane_helper_funcs = { | 223 | static 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) | |||
400 | static void vp_video_buffer(struct mixer_context *ctx, | 400 | static 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) | |||
509 | static int mixer_setup_scale(const struct exynos_drm_plane *plane, | 510 | static 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: | |||
533 | static void mixer_graph_buffer(struct mixer_context *ctx, | 537 | static 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); |