aboutsummaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
authorDave Airlie <airlied@redhat.com>2016-01-13 16:59:21 -0500
committerDave Airlie <airlied@redhat.com>2016-01-13 16:59:21 -0500
commitd6f7a18c8adcb77ca9bfff2d7fb152ac685b73fd (patch)
tree62602e618371b8b64795d030debfa643626fbd6b /drivers
parent06249e69324209b41ba017f476764eba347b1127 (diff)
parentc74d8eb5649386c2cfcd65cc960fd283ba876877 (diff)
Merge branch 'exynos-drm-next' of git://git.kernel.org/pub/scm/linux/kernel/git/daeinki/drm-exynos into drm-next
This 2nd pull request includes the following, - add configurable plane support and relevant cleanups. - fixup kernel panic issue at drm releasing. - remove unnecessary codes. This has been delayed to resolve a critical issue - which incurrs a kernel panic when driver is released - and review it. * 'exynos-drm-next' of git://git.kernel.org/pub/scm/linux/kernel/git/daeinki/drm-exynos: drm/exynos: fix kernel panic issue at drm releasing drm/exynos: crtc: do not wait for the scanout completion drm/exynos: mixer: properly update all planes on the same vblank event drm/exynos: crtc: rework atomic_{begin,flush} drm/exynos: mixer: unify a check for video-processor window drm/exynos: mixer: also allow ARGB1555 and ARGB4444 drm/exynos: mixer: refactor layer setup drm/exynos: mixer: remove all static blending setup drm/exynos: mixer: set window priority based on zpos drm/exynos: make zpos property configurable drm/exynos: rename zpos to index
Diffstat (limited to 'drivers')
-rw-r--r--drivers/gpu/drm/exynos/exynos5433_drm_decon.c20
-rw-r--r--drivers/gpu/drm/exynos/exynos7_drm_decon.c20
-rw-r--r--drivers/gpu/drm/exynos/exynos_drm_crtc.c69
-rw-r--r--drivers/gpu/drm/exynos/exynos_drm_crtc.h5
-rw-r--r--drivers/gpu/drm/exynos/exynos_drm_drv.c5
-rw-r--r--drivers/gpu/drm/exynos/exynos_drm_drv.h18
-rw-r--r--drivers/gpu/drm/exynos/exynos_drm_fb.c3
-rw-r--r--drivers/gpu/drm/exynos/exynos_drm_fimd.c20
-rw-r--r--drivers/gpu/drm/exynos/exynos_drm_plane.c55
-rw-r--r--drivers/gpu/drm/exynos/exynos_drm_plane.h2
-rw-r--r--drivers/gpu/drm/exynos/exynos_drm_vidi.c2
-rw-r--r--drivers/gpu/drm/exynos/exynos_mixer.c155
-rw-r--r--drivers/gpu/drm/exynos/regs-mixer.h4
13 files changed, 235 insertions, 143 deletions
diff --git a/drivers/gpu/drm/exynos/exynos5433_drm_decon.c b/drivers/gpu/drm/exynos/exynos5433_drm_decon.c
index c7362b99ce28..1bf6a21130c7 100644
--- a/drivers/gpu/drm/exynos/exynos5433_drm_decon.c
+++ b/drivers/gpu/drm/exynos/exynos5433_drm_decon.c
@@ -248,15 +248,16 @@ static void decon_shadow_protect_win(struct decon_context *ctx, int win,
248 protect ? ~0 : 0); 248 protect ? ~0 : 0);
249} 249}
250 250
251static void decon_atomic_begin(struct exynos_drm_crtc *crtc, 251static void decon_atomic_begin(struct exynos_drm_crtc *crtc)
252 struct exynos_drm_plane *plane)
253{ 252{
254 struct decon_context *ctx = crtc->ctx; 253 struct decon_context *ctx = crtc->ctx;
254 int i;
255 255
256 if (test_bit(BIT_SUSPENDED, &ctx->flags)) 256 if (test_bit(BIT_SUSPENDED, &ctx->flags))
257 return; 257 return;
258 258
259 decon_shadow_protect_win(ctx, plane->zpos, true); 259 for (i = ctx->first_win; i < WINDOWS_NR; i++)
260 decon_shadow_protect_win(ctx, i, true);
260} 261}
261 262
262#define BIT_VAL(x, e, s) (((x) & ((1 << ((e) - (s) + 1)) - 1)) << (s)) 263#define BIT_VAL(x, e, s) (((x) & ((1 << ((e) - (s) + 1)) - 1)) << (s))
@@ -270,7 +271,7 @@ static void decon_update_plane(struct exynos_drm_crtc *crtc,
270 to_exynos_plane_state(plane->base.state); 271 to_exynos_plane_state(plane->base.state);
271 struct decon_context *ctx = crtc->ctx; 272 struct decon_context *ctx = crtc->ctx;
272 struct drm_framebuffer *fb = state->base.fb; 273 struct drm_framebuffer *fb = state->base.fb;
273 unsigned int win = plane->zpos; 274 unsigned int win = plane->index;
274 unsigned int bpp = fb->bits_per_pixel >> 3; 275 unsigned int bpp = fb->bits_per_pixel >> 3;
275 unsigned int pitch = fb->pitches[0]; 276 unsigned int pitch = fb->pitches[0];
276 dma_addr_t dma_addr = exynos_drm_fb_dma_addr(fb, 0); 277 dma_addr_t dma_addr = exynos_drm_fb_dma_addr(fb, 0);
@@ -320,7 +321,7 @@ static void decon_disable_plane(struct exynos_drm_crtc *crtc,
320 struct exynos_drm_plane *plane) 321 struct exynos_drm_plane *plane)
321{ 322{
322 struct decon_context *ctx = crtc->ctx; 323 struct decon_context *ctx = crtc->ctx;
323 unsigned int win = plane->zpos; 324 unsigned int win = plane->index;
324 325
325 if (test_bit(BIT_SUSPENDED, &ctx->flags)) 326 if (test_bit(BIT_SUSPENDED, &ctx->flags))
326 return; 327 return;
@@ -336,15 +337,16 @@ static void decon_disable_plane(struct exynos_drm_crtc *crtc,
336 decon_set_bits(ctx, DECON_UPDATE, STANDALONE_UPDATE_F, ~0); 337 decon_set_bits(ctx, DECON_UPDATE, STANDALONE_UPDATE_F, ~0);
337} 338}
338 339
339static void decon_atomic_flush(struct exynos_drm_crtc *crtc, 340static void decon_atomic_flush(struct exynos_drm_crtc *crtc)
340 struct exynos_drm_plane *plane)
341{ 341{
342 struct decon_context *ctx = crtc->ctx; 342 struct decon_context *ctx = crtc->ctx;
343 int i;
343 344
344 if (test_bit(BIT_SUSPENDED, &ctx->flags)) 345 if (test_bit(BIT_SUSPENDED, &ctx->flags))
345 return; 346 return;
346 347
347 decon_shadow_protect_win(ctx, plane->zpos, false); 348 for (i = ctx->first_win; i < WINDOWS_NR; i++)
349 decon_shadow_protect_win(ctx, i, false);
348 350
349 if (ctx->out_type == IFTYPE_I80) 351 if (ctx->out_type == IFTYPE_I80)
350 set_bit(BIT_WIN_UPDATED, &ctx->flags); 352 set_bit(BIT_WIN_UPDATED, &ctx->flags);
@@ -502,7 +504,7 @@ static int decon_bind(struct device *dev, struct device *master, void *data)
502 ctx->configs[win].zpos = win; 504 ctx->configs[win].zpos = win;
503 ctx->configs[win].type = decon_win_types[tmp]; 505 ctx->configs[win].type = decon_win_types[tmp];
504 506
505 ret = exynos_plane_init(drm_dev, &ctx->planes[win], 507 ret = exynos_plane_init(drm_dev, &ctx->planes[win], win,
506 1 << ctx->pipe, &ctx->configs[win]); 508 1 << ctx->pipe, &ctx->configs[win]);
507 if (ret) 509 if (ret)
508 return ret; 510 return ret;
diff --git a/drivers/gpu/drm/exynos/exynos7_drm_decon.c b/drivers/gpu/drm/exynos/exynos7_drm_decon.c
index c47f9af8170b..52bda3b42fe0 100644
--- a/drivers/gpu/drm/exynos/exynos7_drm_decon.c
+++ b/drivers/gpu/drm/exynos/exynos7_drm_decon.c
@@ -385,15 +385,16 @@ static void decon_shadow_protect_win(struct decon_context *ctx,
385 writel(val, ctx->regs + SHADOWCON); 385 writel(val, ctx->regs + SHADOWCON);
386} 386}
387 387
388static void decon_atomic_begin(struct exynos_drm_crtc *crtc, 388static void decon_atomic_begin(struct exynos_drm_crtc *crtc)
389 struct exynos_drm_plane *plane)
390{ 389{
391 struct decon_context *ctx = crtc->ctx; 390 struct decon_context *ctx = crtc->ctx;
391 int i;
392 392
393 if (ctx->suspended) 393 if (ctx->suspended)
394 return; 394 return;
395 395
396 decon_shadow_protect_win(ctx, plane->zpos, true); 396 for (i = 0; i < WINDOWS_NR; i++)
397 decon_shadow_protect_win(ctx, i, true);
397} 398}
398 399
399static void decon_update_plane(struct exynos_drm_crtc *crtc, 400static void decon_update_plane(struct exynos_drm_crtc *crtc,
@@ -407,7 +408,7 @@ static void decon_update_plane(struct exynos_drm_crtc *crtc,
407 unsigned long val, alpha; 408 unsigned long val, alpha;
408 unsigned int last_x; 409 unsigned int last_x;
409 unsigned int last_y; 410 unsigned int last_y;
410 unsigned int win = plane->zpos; 411 unsigned int win = plane->index;
411 unsigned int bpp = fb->bits_per_pixel >> 3; 412 unsigned int bpp = fb->bits_per_pixel >> 3;
412 unsigned int pitch = fb->pitches[0]; 413 unsigned int pitch = fb->pitches[0];
413 414
@@ -498,7 +499,7 @@ static void decon_disable_plane(struct exynos_drm_crtc *crtc,
498 struct exynos_drm_plane *plane) 499 struct exynos_drm_plane *plane)
499{ 500{
500 struct decon_context *ctx = crtc->ctx; 501 struct decon_context *ctx = crtc->ctx;
501 unsigned int win = plane->zpos; 502 unsigned int win = plane->index;
502 u32 val; 503 u32 val;
503 504
504 if (ctx->suspended) 505 if (ctx->suspended)
@@ -517,15 +518,16 @@ static void decon_disable_plane(struct exynos_drm_crtc *crtc,
517 writel(val, ctx->regs + DECON_UPDATE); 518 writel(val, ctx->regs + DECON_UPDATE);
518} 519}
519 520
520static void decon_atomic_flush(struct exynos_drm_crtc *crtc, 521static void decon_atomic_flush(struct exynos_drm_crtc *crtc)
521 struct exynos_drm_plane *plane)
522{ 522{
523 struct decon_context *ctx = crtc->ctx; 523 struct decon_context *ctx = crtc->ctx;
524 int i;
524 525
525 if (ctx->suspended) 526 if (ctx->suspended)
526 return; 527 return;
527 528
528 decon_shadow_protect_win(ctx, plane->zpos, false); 529 for (i = 0; i < WINDOWS_NR; i++)
530 decon_shadow_protect_win(ctx, i, false);
529} 531}
530 532
531static void decon_init(struct decon_context *ctx) 533static void decon_init(struct decon_context *ctx)
@@ -657,7 +659,7 @@ static int decon_bind(struct device *dev, struct device *master, void *data)
657 ctx->configs[i].zpos = i; 659 ctx->configs[i].zpos = i;
658 ctx->configs[i].type = decon_win_types[i]; 660 ctx->configs[i].type = decon_win_types[i];
659 661
660 ret = exynos_plane_init(drm_dev, &ctx->planes[i], 662 ret = exynos_plane_init(drm_dev, &ctx->planes[i], i,
661 1 << ctx->pipe, &ctx->configs[i]); 663 1 << ctx->pipe, &ctx->configs[i]);
662 if (ret) 664 if (ret)
663 return ret; 665 return ret;
diff --git a/drivers/gpu/drm/exynos/exynos_drm_crtc.c b/drivers/gpu/drm/exynos/exynos_drm_crtc.c
index 8f5ac535d809..e36579c1c025 100644
--- a/drivers/gpu/drm/exynos/exynos_drm_crtc.c
+++ b/drivers/gpu/drm/exynos/exynos_drm_crtc.c
@@ -68,32 +68,20 @@ static void exynos_crtc_atomic_begin(struct drm_crtc *crtc,
68 struct drm_crtc_state *old_crtc_state) 68 struct drm_crtc_state *old_crtc_state)
69{ 69{
70 struct exynos_drm_crtc *exynos_crtc = to_exynos_crtc(crtc); 70 struct exynos_drm_crtc *exynos_crtc = to_exynos_crtc(crtc);
71 struct drm_plane *plane;
72 71
73 exynos_crtc->event = crtc->state->event; 72 exynos_crtc->event = crtc->state->event;
74 73
75 drm_atomic_crtc_for_each_plane(plane, crtc) { 74 if (exynos_crtc->ops->atomic_begin)
76 struct exynos_drm_plane *exynos_plane = to_exynos_plane(plane); 75 exynos_crtc->ops->atomic_begin(exynos_crtc);
77
78 if (exynos_crtc->ops->atomic_begin)
79 exynos_crtc->ops->atomic_begin(exynos_crtc,
80 exynos_plane);
81 }
82} 76}
83 77
84static void exynos_crtc_atomic_flush(struct drm_crtc *crtc, 78static void exynos_crtc_atomic_flush(struct drm_crtc *crtc,
85 struct drm_crtc_state *old_crtc_state) 79 struct drm_crtc_state *old_crtc_state)
86{ 80{
87 struct exynos_drm_crtc *exynos_crtc = to_exynos_crtc(crtc); 81 struct exynos_drm_crtc *exynos_crtc = to_exynos_crtc(crtc);
88 struct drm_plane *plane;
89 82
90 drm_atomic_crtc_for_each_plane(plane, crtc) { 83 if (exynos_crtc->ops->atomic_flush)
91 struct exynos_drm_plane *exynos_plane = to_exynos_plane(plane); 84 exynos_crtc->ops->atomic_flush(exynos_crtc);
92
93 if (exynos_crtc->ops->atomic_flush)
94 exynos_crtc->ops->atomic_flush(exynos_crtc,
95 exynos_plane);
96 }
97} 85}
98 86
99static const struct drm_crtc_helper_funcs exynos_crtc_helper_funcs = { 87static const struct drm_crtc_helper_funcs exynos_crtc_helper_funcs = {
@@ -215,29 +203,6 @@ void exynos_drm_crtc_finish_update(struct exynos_drm_crtc *exynos_crtc,
215 spin_unlock_irqrestore(&crtc->dev->event_lock, flags); 203 spin_unlock_irqrestore(&crtc->dev->event_lock, flags);
216} 204}
217 205
218void exynos_drm_crtc_complete_scanout(struct drm_framebuffer *fb)
219{
220 struct exynos_drm_crtc *exynos_crtc;
221 struct drm_device *dev = fb->dev;
222 struct drm_crtc *crtc;
223
224 /*
225 * make sure that overlay data are updated to real hardware
226 * for all encoders.
227 */
228 list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) {
229 exynos_crtc = to_exynos_crtc(crtc);
230
231 /*
232 * wait for vblank interrupt
233 * - this makes sure that overlay data are updated to
234 * real hardware.
235 */
236 if (exynos_crtc->ops->wait_for_vblank)
237 exynos_crtc->ops->wait_for_vblank(exynos_crtc);
238 }
239}
240
241int exynos_drm_crtc_get_pipe_from_type(struct drm_device *drm_dev, 206int exynos_drm_crtc_get_pipe_from_type(struct drm_device *drm_dev,
242 enum exynos_drm_output_type out_type) 207 enum exynos_drm_output_type out_type)
243{ 208{
@@ -261,3 +226,29 @@ void exynos_drm_crtc_te_handler(struct drm_crtc *crtc)
261 if (exynos_crtc->ops->te_handler) 226 if (exynos_crtc->ops->te_handler)
262 exynos_crtc->ops->te_handler(exynos_crtc); 227 exynos_crtc->ops->te_handler(exynos_crtc);
263} 228}
229
230void exynos_drm_crtc_cancel_page_flip(struct drm_crtc *crtc,
231 struct drm_file *file)
232{
233 struct exynos_drm_crtc *exynos_crtc = to_exynos_crtc(crtc);
234 struct drm_pending_vblank_event *e;
235 unsigned long flags;
236
237 spin_lock_irqsave(&crtc->dev->event_lock, flags);
238 e = exynos_crtc->event;
239 if (e && e->base.file_priv == file) {
240 exynos_crtc->event = NULL;
241 /*
242 * event will be destroyed by core part
243 * so below line should be removed later with core changes
244 */
245 e->base.destroy(&e->base);
246 /*
247 * event_space will be increased by core part
248 * so below line should be removed later with core changes.
249 */
250 file->event_space += sizeof(e->event);
251 atomic_dec(&exynos_crtc->pending_update);
252 }
253 spin_unlock_irqrestore(&crtc->dev->event_lock, flags);
254}
diff --git a/drivers/gpu/drm/exynos/exynos_drm_crtc.h b/drivers/gpu/drm/exynos/exynos_drm_crtc.h
index f9f365bd0257..cfdcf3e4eb1b 100644
--- a/drivers/gpu/drm/exynos/exynos_drm_crtc.h
+++ b/drivers/gpu/drm/exynos/exynos_drm_crtc.h
@@ -28,7 +28,6 @@ void exynos_drm_crtc_disable_vblank(struct drm_device *dev, unsigned int pipe);
28void exynos_drm_crtc_wait_pending_update(struct exynos_drm_crtc *exynos_crtc); 28void exynos_drm_crtc_wait_pending_update(struct exynos_drm_crtc *exynos_crtc);
29void exynos_drm_crtc_finish_update(struct exynos_drm_crtc *exynos_crtc, 29void exynos_drm_crtc_finish_update(struct exynos_drm_crtc *exynos_crtc,
30 struct exynos_drm_plane *exynos_plane); 30 struct exynos_drm_plane *exynos_plane);
31void exynos_drm_crtc_complete_scanout(struct drm_framebuffer *fb);
32 31
33/* This function gets pipe value to crtc device matched with out_type. */ 32/* This function gets pipe value to crtc device matched with out_type. */
34int exynos_drm_crtc_get_pipe_from_type(struct drm_device *drm_dev, 33int exynos_drm_crtc_get_pipe_from_type(struct drm_device *drm_dev,
@@ -41,4 +40,8 @@ int exynos_drm_crtc_get_pipe_from_type(struct drm_device *drm_dev,
41 */ 40 */
42void exynos_drm_crtc_te_handler(struct drm_crtc *crtc); 41void exynos_drm_crtc_te_handler(struct drm_crtc *crtc);
43 42
43/* This function cancels a page flip request. */
44void exynos_drm_crtc_cancel_page_flip(struct drm_crtc *crtc,
45 struct drm_file *file);
46
44#endif 47#endif
diff --git a/drivers/gpu/drm/exynos/exynos_drm_drv.c b/drivers/gpu/drm/exynos/exynos_drm_drv.c
index 9756797a15a5..68f0f36f6e7e 100644
--- a/drivers/gpu/drm/exynos/exynos_drm_drv.c
+++ b/drivers/gpu/drm/exynos/exynos_drm_drv.c
@@ -330,7 +330,12 @@ err_file_priv_free:
330static void exynos_drm_preclose(struct drm_device *dev, 330static void exynos_drm_preclose(struct drm_device *dev,
331 struct drm_file *file) 331 struct drm_file *file)
332{ 332{
333 struct drm_crtc *crtc;
334
333 exynos_drm_subdrv_close(dev, file); 335 exynos_drm_subdrv_close(dev, file);
336
337 list_for_each_entry(crtc, &dev->mode_config.crtc_list, head)
338 exynos_drm_crtc_cancel_page_flip(crtc, file);
334} 339}
335 340
336static void exynos_drm_postclose(struct drm_device *dev, struct drm_file *file) 341static void exynos_drm_postclose(struct drm_device *dev, struct drm_file *file)
diff --git a/drivers/gpu/drm/exynos/exynos_drm_drv.h b/drivers/gpu/drm/exynos/exynos_drm_drv.h
index 82bbd7f4b316..17b5ded72ff1 100644
--- a/drivers/gpu/drm/exynos/exynos_drm_drv.h
+++ b/drivers/gpu/drm/exynos/exynos_drm_drv.h
@@ -64,6 +64,7 @@ struct exynos_drm_plane_state {
64 struct exynos_drm_rect src; 64 struct exynos_drm_rect src;
65 unsigned int h_ratio; 65 unsigned int h_ratio;
66 unsigned int v_ratio; 66 unsigned int v_ratio;
67 unsigned int zpos;
67}; 68};
68 69
69static inline struct exynos_drm_plane_state * 70static inline struct exynos_drm_plane_state *
@@ -76,7 +77,7 @@ to_exynos_plane_state(struct drm_plane_state *state)
76 * Exynos drm common overlay structure. 77 * Exynos drm common overlay structure.
77 * 78 *
78 * @base: plane object 79 * @base: plane object
79 * @zpos: order of overlay layer(z position). 80 * @index: hardware index of the overlay layer
80 * 81 *
81 * this structure is common to exynos SoC and its contents would be copied 82 * this structure is common to exynos SoC and its contents would be copied
82 * to hardware specific overlay info. 83 * to hardware specific overlay info.
@@ -85,17 +86,18 @@ to_exynos_plane_state(struct drm_plane_state *state)
85struct exynos_drm_plane { 86struct exynos_drm_plane {
86 struct drm_plane base; 87 struct drm_plane base;
87 const struct exynos_drm_plane_config *config; 88 const struct exynos_drm_plane_config *config;
88 unsigned int zpos; 89 unsigned int index;
89 struct drm_framebuffer *pending_fb; 90 struct drm_framebuffer *pending_fb;
90}; 91};
91 92
92#define EXYNOS_DRM_PLANE_CAP_DOUBLE (1 << 0) 93#define EXYNOS_DRM_PLANE_CAP_DOUBLE (1 << 0)
93#define EXYNOS_DRM_PLANE_CAP_SCALE (1 << 1) 94#define EXYNOS_DRM_PLANE_CAP_SCALE (1 << 1)
95#define EXYNOS_DRM_PLANE_CAP_ZPOS (1 << 2)
94 96
95/* 97/*
96 * Exynos DRM plane configuration structure. 98 * Exynos DRM plane configuration structure.
97 * 99 *
98 * @zpos: z-position of the plane. 100 * @zpos: initial z-position of the plane.
99 * @type: type of the plane (primary, cursor or overlay). 101 * @type: type of the plane (primary, cursor or overlay).
100 * @pixel_formats: supported pixel formats. 102 * @pixel_formats: supported pixel formats.
101 * @num_pixel_formats: number of elements in 'pixel_formats'. 103 * @num_pixel_formats: number of elements in 'pixel_formats'.
@@ -121,8 +123,8 @@ struct exynos_drm_plane_config {
121 * @wait_for_vblank: wait for vblank interrupt to make sure that 123 * @wait_for_vblank: wait for vblank interrupt to make sure that
122 * hardware overlay is updated. 124 * hardware overlay is updated.
123 * @atomic_check: validate state 125 * @atomic_check: validate state
124 * @atomic_begin: prepare a window to receive a update 126 * @atomic_begin: prepare device to receive an update
125 * @atomic_flush: mark the end of a window update 127 * @atomic_flush: mark the end of device update
126 * @update_plane: apply hardware specific overlay data to registers. 128 * @update_plane: apply hardware specific overlay data to registers.
127 * @disable_plane: disable hardware specific overlay. 129 * @disable_plane: disable hardware specific overlay.
128 * @te_handler: trigger to transfer video image at the tearing effect 130 * @te_handler: trigger to transfer video image at the tearing effect
@@ -142,14 +144,12 @@ struct exynos_drm_crtc_ops {
142 void (*wait_for_vblank)(struct exynos_drm_crtc *crtc); 144 void (*wait_for_vblank)(struct exynos_drm_crtc *crtc);
143 int (*atomic_check)(struct exynos_drm_crtc *crtc, 145 int (*atomic_check)(struct exynos_drm_crtc *crtc,
144 struct drm_crtc_state *state); 146 struct drm_crtc_state *state);
145 void (*atomic_begin)(struct exynos_drm_crtc *crtc, 147 void (*atomic_begin)(struct exynos_drm_crtc *crtc);
146 struct exynos_drm_plane *plane);
147 void (*update_plane)(struct exynos_drm_crtc *crtc, 148 void (*update_plane)(struct exynos_drm_crtc *crtc,
148 struct exynos_drm_plane *plane); 149 struct exynos_drm_plane *plane);
149 void (*disable_plane)(struct exynos_drm_crtc *crtc, 150 void (*disable_plane)(struct exynos_drm_crtc *crtc,
150 struct exynos_drm_plane *plane); 151 struct exynos_drm_plane *plane);
151 void (*atomic_flush)(struct exynos_drm_crtc *crtc, 152 void (*atomic_flush)(struct exynos_drm_crtc *crtc);
152 struct exynos_drm_plane *plane);
153 void (*te_handler)(struct exynos_drm_crtc *crtc); 153 void (*te_handler)(struct exynos_drm_crtc *crtc);
154 void (*clock_enable)(struct exynos_drm_crtc *crtc, bool enable); 154 void (*clock_enable)(struct exynos_drm_crtc *crtc, bool enable);
155}; 155};
diff --git a/drivers/gpu/drm/exynos/exynos_drm_fb.c b/drivers/gpu/drm/exynos/exynos_drm_fb.c
index cbbb1a86e70a..d614194644c8 100644
--- a/drivers/gpu/drm/exynos/exynos_drm_fb.c
+++ b/drivers/gpu/drm/exynos/exynos_drm_fb.c
@@ -71,9 +71,6 @@ static void exynos_drm_fb_destroy(struct drm_framebuffer *fb)
71 struct exynos_drm_fb *exynos_fb = to_exynos_fb(fb); 71 struct exynos_drm_fb *exynos_fb = to_exynos_fb(fb);
72 unsigned int i; 72 unsigned int i;
73 73
74 /* make sure that overlay data are updated before relesing fb. */
75 exynos_drm_crtc_complete_scanout(fb);
76
77 drm_framebuffer_cleanup(fb); 74 drm_framebuffer_cleanup(fb);
78 75
79 for (i = 0; i < ARRAY_SIZE(exynos_fb->exynos_gem); i++) { 76 for (i = 0; i < ARRAY_SIZE(exynos_fb->exynos_gem); i++) {
diff --git a/drivers/gpu/drm/exynos/exynos_drm_fimd.c b/drivers/gpu/drm/exynos/exynos_drm_fimd.c
index 2e2247126581..70194d0e4fe4 100644
--- a/drivers/gpu/drm/exynos/exynos_drm_fimd.c
+++ b/drivers/gpu/drm/exynos/exynos_drm_fimd.c
@@ -622,26 +622,28 @@ static void fimd_shadow_protect_win(struct fimd_context *ctx,
622 writel(val, ctx->regs + reg); 622 writel(val, ctx->regs + reg);
623} 623}
624 624
625static void fimd_atomic_begin(struct exynos_drm_crtc *crtc, 625static void fimd_atomic_begin(struct exynos_drm_crtc *crtc)
626 struct exynos_drm_plane *plane)
627{ 626{
628 struct fimd_context *ctx = crtc->ctx; 627 struct fimd_context *ctx = crtc->ctx;
628 int i;
629 629
630 if (ctx->suspended) 630 if (ctx->suspended)
631 return; 631 return;
632 632
633 fimd_shadow_protect_win(ctx, plane->zpos, true); 633 for (i = 0; i < WINDOWS_NR; i++)
634 fimd_shadow_protect_win(ctx, i, true);
634} 635}
635 636
636static void fimd_atomic_flush(struct exynos_drm_crtc *crtc, 637static void fimd_atomic_flush(struct exynos_drm_crtc *crtc)
637 struct exynos_drm_plane *plane)
638{ 638{
639 struct fimd_context *ctx = crtc->ctx; 639 struct fimd_context *ctx = crtc->ctx;
640 int i;
640 641
641 if (ctx->suspended) 642 if (ctx->suspended)
642 return; 643 return;
643 644
644 fimd_shadow_protect_win(ctx, plane->zpos, false); 645 for (i = 0; i < WINDOWS_NR; i++)
646 fimd_shadow_protect_win(ctx, i, false);
645} 647}
646 648
647static void fimd_update_plane(struct exynos_drm_crtc *crtc, 649static void fimd_update_plane(struct exynos_drm_crtc *crtc,
@@ -654,7 +656,7 @@ static void fimd_update_plane(struct exynos_drm_crtc *crtc,
654 dma_addr_t dma_addr; 656 dma_addr_t dma_addr;
655 unsigned long val, size, offset; 657 unsigned long val, size, offset;
656 unsigned int last_x, last_y, buf_offsize, line_size; 658 unsigned int last_x, last_y, buf_offsize, line_size;
657 unsigned int win = plane->zpos; 659 unsigned int win = plane->index;
658 unsigned int bpp = fb->bits_per_pixel >> 3; 660 unsigned int bpp = fb->bits_per_pixel >> 3;
659 unsigned int pitch = fb->pitches[0]; 661 unsigned int pitch = fb->pitches[0];
660 662
@@ -740,7 +742,7 @@ static void fimd_disable_plane(struct exynos_drm_crtc *crtc,
740 struct exynos_drm_plane *plane) 742 struct exynos_drm_plane *plane)
741{ 743{
742 struct fimd_context *ctx = crtc->ctx; 744 struct fimd_context *ctx = crtc->ctx;
743 unsigned int win = plane->zpos; 745 unsigned int win = plane->index;
744 746
745 if (ctx->suspended) 747 if (ctx->suspended)
746 return; 748 return;
@@ -944,7 +946,7 @@ static int fimd_bind(struct device *dev, struct device *master, void *data)
944 ctx->configs[i].num_pixel_formats = ARRAY_SIZE(fimd_formats); 946 ctx->configs[i].num_pixel_formats = ARRAY_SIZE(fimd_formats);
945 ctx->configs[i].zpos = i; 947 ctx->configs[i].zpos = i;
946 ctx->configs[i].type = fimd_win_types[i]; 948 ctx->configs[i].type = fimd_win_types[i];
947 ret = exynos_plane_init(drm_dev, &ctx->planes[i], 949 ret = exynos_plane_init(drm_dev, &ctx->planes[i], i,
948 1 << ctx->pipe, &ctx->configs[i]); 950 1 << ctx->pipe, &ctx->configs[i]);
949 if (ret) 951 if (ret)
950 return ret; 952 return ret;
diff --git a/drivers/gpu/drm/exynos/exynos_drm_plane.c b/drivers/gpu/drm/exynos/exynos_drm_plane.c
index e668fcdbcafc..d86227236f55 100644
--- a/drivers/gpu/drm/exynos/exynos_drm_plane.c
+++ b/drivers/gpu/drm/exynos/exynos_drm_plane.c
@@ -124,6 +124,7 @@ static void exynos_plane_mode_set(struct exynos_drm_plane_state *exynos_state)
124 124
125static void exynos_drm_plane_reset(struct drm_plane *plane) 125static void exynos_drm_plane_reset(struct drm_plane *plane)
126{ 126{
127 struct exynos_drm_plane *exynos_plane = to_exynos_plane(plane);
127 struct exynos_drm_plane_state *exynos_state; 128 struct exynos_drm_plane_state *exynos_state;
128 129
129 if (plane->state) { 130 if (plane->state) {
@@ -136,6 +137,7 @@ static void exynos_drm_plane_reset(struct drm_plane *plane)
136 137
137 exynos_state = kzalloc(sizeof(*exynos_state), GFP_KERNEL); 138 exynos_state = kzalloc(sizeof(*exynos_state), GFP_KERNEL);
138 if (exynos_state) { 139 if (exynos_state) {
140 exynos_state->zpos = exynos_plane->config->zpos;
139 plane->state = &exynos_state->base; 141 plane->state = &exynos_state->base;
140 plane->state->plane = plane; 142 plane->state->plane = plane;
141 } 143 }
@@ -153,6 +155,7 @@ exynos_drm_plane_duplicate_state(struct drm_plane *plane)
153 return NULL; 155 return NULL;
154 156
155 __drm_atomic_helper_plane_duplicate_state(plane, &copy->base); 157 __drm_atomic_helper_plane_duplicate_state(plane, &copy->base);
158 copy->zpos = exynos_state->zpos;
156 return &copy->base; 159 return &copy->base;
157} 160}
158 161
@@ -165,13 +168,53 @@ static void exynos_drm_plane_destroy_state(struct drm_plane *plane,
165 kfree(old_exynos_state); 168 kfree(old_exynos_state);
166} 169}
167 170
171static int exynos_drm_plane_atomic_set_property(struct drm_plane *plane,
172 struct drm_plane_state *state,
173 struct drm_property *property,
174 uint64_t val)
175{
176 struct exynos_drm_plane *exynos_plane = to_exynos_plane(plane);
177 struct exynos_drm_plane_state *exynos_state =
178 to_exynos_plane_state(state);
179 struct exynos_drm_private *dev_priv = plane->dev->dev_private;
180 const struct exynos_drm_plane_config *config = exynos_plane->config;
181
182 if (property == dev_priv->plane_zpos_property &&
183 (config->capabilities & EXYNOS_DRM_PLANE_CAP_ZPOS))
184 exynos_state->zpos = val;
185 else
186 return -EINVAL;
187
188 return 0;
189}
190
191static int exynos_drm_plane_atomic_get_property(struct drm_plane *plane,
192 const struct drm_plane_state *state,
193 struct drm_property *property,
194 uint64_t *val)
195{
196 const struct exynos_drm_plane_state *exynos_state =
197 container_of(state, const struct exynos_drm_plane_state, base);
198 struct exynos_drm_private *dev_priv = plane->dev->dev_private;
199
200 if (property == dev_priv->plane_zpos_property)
201 *val = exynos_state->zpos;
202 else
203 return -EINVAL;
204
205 return 0;
206}
207
168static struct drm_plane_funcs exynos_plane_funcs = { 208static struct drm_plane_funcs exynos_plane_funcs = {
169 .update_plane = drm_atomic_helper_update_plane, 209 .update_plane = drm_atomic_helper_update_plane,
170 .disable_plane = drm_atomic_helper_disable_plane, 210 .disable_plane = drm_atomic_helper_disable_plane,
171 .destroy = drm_plane_cleanup, 211 .destroy = drm_plane_cleanup,
212 .set_property = drm_atomic_helper_plane_set_property,
172 .reset = exynos_drm_plane_reset, 213 .reset = exynos_drm_plane_reset,
173 .atomic_duplicate_state = exynos_drm_plane_duplicate_state, 214 .atomic_duplicate_state = exynos_drm_plane_duplicate_state,
174 .atomic_destroy_state = exynos_drm_plane_destroy_state, 215 .atomic_destroy_state = exynos_drm_plane_destroy_state,
216 .atomic_set_property = exynos_drm_plane_atomic_set_property,
217 .atomic_get_property = exynos_drm_plane_atomic_get_property,
175}; 218};
176 219
177static int 220static int
@@ -267,8 +310,8 @@ static void exynos_plane_attach_zpos_property(struct drm_plane *plane,
267 310
268 prop = dev_priv->plane_zpos_property; 311 prop = dev_priv->plane_zpos_property;
269 if (!prop) { 312 if (!prop) {
270 prop = drm_property_create_range(dev, DRM_MODE_PROP_IMMUTABLE, 313 prop = drm_property_create_range(dev, 0, "zpos",
271 "zpos", 0, MAX_PLANE - 1); 314 0, MAX_PLANE - 1);
272 if (!prop) 315 if (!prop)
273 return; 316 return;
274 317
@@ -280,7 +323,7 @@ static void exynos_plane_attach_zpos_property(struct drm_plane *plane,
280 323
281int exynos_plane_init(struct drm_device *dev, 324int exynos_plane_init(struct drm_device *dev,
282 struct exynos_drm_plane *exynos_plane, 325 struct exynos_drm_plane *exynos_plane,
283 unsigned long possible_crtcs, 326 unsigned int index, unsigned long possible_crtcs,
284 const struct exynos_drm_plane_config *config) 327 const struct exynos_drm_plane_config *config)
285{ 328{
286 int err; 329 int err;
@@ -298,12 +341,10 @@ int exynos_plane_init(struct drm_device *dev,
298 341
299 drm_plane_helper_add(&exynos_plane->base, &plane_helper_funcs); 342 drm_plane_helper_add(&exynos_plane->base, &plane_helper_funcs);
300 343
301 exynos_plane->zpos = config->zpos; 344 exynos_plane->index = index;
302 exynos_plane->config = config; 345 exynos_plane->config = config;
303 346
304 if (config->type == DRM_PLANE_TYPE_OVERLAY) 347 exynos_plane_attach_zpos_property(&exynos_plane->base, config->zpos);
305 exynos_plane_attach_zpos_property(&exynos_plane->base,
306 config->zpos);
307 348
308 return 0; 349 return 0;
309} 350}
diff --git a/drivers/gpu/drm/exynos/exynos_drm_plane.h b/drivers/gpu/drm/exynos/exynos_drm_plane.h
index 0dd096548284..9aafad164cdf 100644
--- a/drivers/gpu/drm/exynos/exynos_drm_plane.h
+++ b/drivers/gpu/drm/exynos/exynos_drm_plane.h
@@ -10,6 +10,6 @@
10 */ 10 */
11 11
12int exynos_plane_init(struct drm_device *dev, 12int exynos_plane_init(struct drm_device *dev,
13 struct exynos_drm_plane *exynos_plane, 13 struct exynos_drm_plane *exynos_plane, unsigned int index,
14 unsigned long possible_crtcs, 14 unsigned long possible_crtcs,
15 const struct exynos_drm_plane_config *config); 15 const struct exynos_drm_plane_config *config);
diff --git a/drivers/gpu/drm/exynos/exynos_drm_vidi.c b/drivers/gpu/drm/exynos/exynos_drm_vidi.c
index 0be29c1b2c05..62ac4e5fa51d 100644
--- a/drivers/gpu/drm/exynos/exynos_drm_vidi.c
+++ b/drivers/gpu/drm/exynos/exynos_drm_vidi.c
@@ -461,7 +461,7 @@ static int vidi_bind(struct device *dev, struct device *master, void *data)
461 plane_config.zpos = i; 461 plane_config.zpos = i;
462 plane_config.type = vidi_win_types[i]; 462 plane_config.type = vidi_win_types[i];
463 463
464 ret = exynos_plane_init(drm_dev, &ctx->planes[i], 464 ret = exynos_plane_init(drm_dev, &ctx->planes[i], i,
465 1 << ctx->pipe, &plane_config); 465 1 << ctx->pipe, &plane_config);
466 if (ret) 466 if (ret)
467 return ret; 467 return ret;
diff --git a/drivers/gpu/drm/exynos/exynos_mixer.c b/drivers/gpu/drm/exynos/exynos_mixer.c
index dfb35e2da4db..b5fbc1cbf024 100644
--- a/drivers/gpu/drm/exynos/exynos_mixer.c
+++ b/drivers/gpu/drm/exynos/exynos_mixer.c
@@ -76,7 +76,9 @@ enum mixer_flag_bits {
76 76
77static const uint32_t mixer_formats[] = { 77static const uint32_t mixer_formats[] = {
78 DRM_FORMAT_XRGB4444, 78 DRM_FORMAT_XRGB4444,
79 DRM_FORMAT_ARGB4444,
79 DRM_FORMAT_XRGB1555, 80 DRM_FORMAT_XRGB1555,
81 DRM_FORMAT_ARGB1555,
80 DRM_FORMAT_RGB565, 82 DRM_FORMAT_RGB565,
81 DRM_FORMAT_XRGB8888, 83 DRM_FORMAT_XRGB8888,
82 DRM_FORMAT_ARGB8888, 84 DRM_FORMAT_ARGB8888,
@@ -117,19 +119,22 @@ static const struct exynos_drm_plane_config plane_configs[MIXER_WIN_NR] = {
117 .type = DRM_PLANE_TYPE_PRIMARY, 119 .type = DRM_PLANE_TYPE_PRIMARY,
118 .pixel_formats = mixer_formats, 120 .pixel_formats = mixer_formats,
119 .num_pixel_formats = ARRAY_SIZE(mixer_formats), 121 .num_pixel_formats = ARRAY_SIZE(mixer_formats),
120 .capabilities = EXYNOS_DRM_PLANE_CAP_DOUBLE, 122 .capabilities = EXYNOS_DRM_PLANE_CAP_DOUBLE |
123 EXYNOS_DRM_PLANE_CAP_ZPOS,
121 }, { 124 }, {
122 .zpos = 1, 125 .zpos = 1,
123 .type = DRM_PLANE_TYPE_CURSOR, 126 .type = DRM_PLANE_TYPE_CURSOR,
124 .pixel_formats = mixer_formats, 127 .pixel_formats = mixer_formats,
125 .num_pixel_formats = ARRAY_SIZE(mixer_formats), 128 .num_pixel_formats = ARRAY_SIZE(mixer_formats),
126 .capabilities = EXYNOS_DRM_PLANE_CAP_DOUBLE, 129 .capabilities = EXYNOS_DRM_PLANE_CAP_DOUBLE |
130 EXYNOS_DRM_PLANE_CAP_ZPOS,
127 }, { 131 }, {
128 .zpos = 2, 132 .zpos = 2,
129 .type = DRM_PLANE_TYPE_OVERLAY, 133 .type = DRM_PLANE_TYPE_OVERLAY,
130 .pixel_formats = vp_formats, 134 .pixel_formats = vp_formats,
131 .num_pixel_formats = ARRAY_SIZE(vp_formats), 135 .num_pixel_formats = ARRAY_SIZE(vp_formats),
132 .capabilities = EXYNOS_DRM_PLANE_CAP_SCALE, 136 .capabilities = EXYNOS_DRM_PLANE_CAP_SCALE |
137 EXYNOS_DRM_PLANE_CAP_ZPOS,
133 }, 138 },
134}; 139};
135 140
@@ -162,6 +167,18 @@ static const u8 filter_cr_horiz_tap4[] = {
162 70, 59, 48, 37, 27, 19, 11, 5, 167 70, 59, 48, 37, 27, 19, 11, 5,
163}; 168};
164 169
170static inline bool is_alpha_format(unsigned int pixel_format)
171{
172 switch (pixel_format) {
173 case DRM_FORMAT_ARGB8888:
174 case DRM_FORMAT_ARGB1555:
175 case DRM_FORMAT_ARGB4444:
176 return true;
177 default:
178 return false;
179 }
180}
181
165static inline u32 vp_reg_read(struct mixer_resources *res, u32 reg_id) 182static inline u32 vp_reg_read(struct mixer_resources *res, u32 reg_id)
166{ 183{
167 return readl(res->vp_regs + reg_id); 184 return readl(res->vp_regs + reg_id);
@@ -291,6 +308,37 @@ static void vp_default_filter(struct mixer_resources *res)
291 filter_cr_horiz_tap4, sizeof(filter_cr_horiz_tap4)); 308 filter_cr_horiz_tap4, sizeof(filter_cr_horiz_tap4));
292} 309}
293 310
311static void mixer_cfg_gfx_blend(struct mixer_context *ctx, unsigned int win,
312 bool alpha)
313{
314 struct mixer_resources *res = &ctx->mixer_res;
315 u32 val;
316
317 val = MXR_GRP_CFG_COLOR_KEY_DISABLE; /* no blank key */
318 if (alpha) {
319 /* blending based on pixel alpha */
320 val |= MXR_GRP_CFG_BLEND_PRE_MUL;
321 val |= MXR_GRP_CFG_PIXEL_BLEND_EN;
322 }
323 mixer_reg_writemask(res, MXR_GRAPHIC_CFG(win),
324 val, MXR_GRP_CFG_MISC_MASK);
325}
326
327static void mixer_cfg_vp_blend(struct mixer_context *ctx)
328{
329 struct mixer_resources *res = &ctx->mixer_res;
330 u32 val;
331
332 /*
333 * No blending at the moment since the NV12/NV21 pixelformats don't
334 * have an alpha channel. However the mixer supports a global alpha
335 * value for a layer. Once this functionality is exposed, we can
336 * support blending of the video layer through this.
337 */
338 val = 0;
339 mixer_reg_write(res, MXR_VIDEO_CFG, val);
340}
341
294static void mixer_vsync_set_update(struct mixer_context *ctx, bool enable) 342static void mixer_vsync_set_update(struct mixer_context *ctx, bool enable)
295{ 343{
296 struct mixer_resources *res = &ctx->mixer_res; 344 struct mixer_resources *res = &ctx->mixer_res;
@@ -372,7 +420,7 @@ static void mixer_cfg_rgb_fmt(struct mixer_context *ctx, unsigned int height)
372} 420}
373 421
374static void mixer_cfg_layer(struct mixer_context *ctx, unsigned int win, 422static void mixer_cfg_layer(struct mixer_context *ctx, unsigned int win,
375 bool enable) 423 unsigned int priority, bool enable)
376{ 424{
377 struct mixer_resources *res = &ctx->mixer_res; 425 struct mixer_resources *res = &ctx->mixer_res;
378 u32 val = enable ? ~0 : 0; 426 u32 val = enable ? ~0 : 0;
@@ -380,20 +428,24 @@ static void mixer_cfg_layer(struct mixer_context *ctx, unsigned int win,
380 switch (win) { 428 switch (win) {
381 case 0: 429 case 0:
382 mixer_reg_writemask(res, MXR_CFG, val, MXR_CFG_GRP0_ENABLE); 430 mixer_reg_writemask(res, MXR_CFG, val, MXR_CFG_GRP0_ENABLE);
431 mixer_reg_writemask(res, MXR_LAYER_CFG,
432 MXR_LAYER_CFG_GRP0_VAL(priority),
433 MXR_LAYER_CFG_GRP0_MASK);
383 break; 434 break;
384 case 1: 435 case 1:
385 mixer_reg_writemask(res, MXR_CFG, val, MXR_CFG_GRP1_ENABLE); 436 mixer_reg_writemask(res, MXR_CFG, val, MXR_CFG_GRP1_ENABLE);
437 mixer_reg_writemask(res, MXR_LAYER_CFG,
438 MXR_LAYER_CFG_GRP1_VAL(priority),
439 MXR_LAYER_CFG_GRP1_MASK);
386 break; 440 break;
387 case 2: 441 case VP_DEFAULT_WIN:
388 if (ctx->vp_enabled) { 442 if (ctx->vp_enabled) {
389 vp_reg_writemask(res, VP_ENABLE, val, VP_ENABLE_ON); 443 vp_reg_writemask(res, VP_ENABLE, val, VP_ENABLE_ON);
390 mixer_reg_writemask(res, MXR_CFG, val, 444 mixer_reg_writemask(res, MXR_CFG, val,
391 MXR_CFG_VP_ENABLE); 445 MXR_CFG_VP_ENABLE);
392 446 mixer_reg_writemask(res, MXR_LAYER_CFG,
393 /* control blending of graphic layer 0 */ 447 MXR_LAYER_CFG_VP_VAL(priority),
394 mixer_reg_writemask(res, MXR_GRAPHIC_CFG(0), val, 448 MXR_LAYER_CFG_VP_MASK);
395 MXR_GRP_CFG_BLEND_PRE_MUL |
396 MXR_GRP_CFG_PIXEL_BLEND_EN);
397 } 449 }
398 break; 450 break;
399 } 451 }
@@ -464,7 +516,6 @@ static void vp_video_buffer(struct mixer_context *ctx,
464 } 516 }
465 517
466 spin_lock_irqsave(&res->reg_slock, flags); 518 spin_lock_irqsave(&res->reg_slock, flags);
467 mixer_vsync_set_update(ctx, false);
468 519
469 /* interlace or progressive scan mode */ 520 /* interlace or progressive scan mode */
470 val = (ctx->interlace ? ~0 : 0); 521 val = (ctx->interlace ? ~0 : 0);
@@ -511,10 +562,10 @@ static void vp_video_buffer(struct mixer_context *ctx,
511 562
512 mixer_cfg_scan(ctx, mode->vdisplay); 563 mixer_cfg_scan(ctx, mode->vdisplay);
513 mixer_cfg_rgb_fmt(ctx, mode->vdisplay); 564 mixer_cfg_rgb_fmt(ctx, mode->vdisplay);
514 mixer_cfg_layer(ctx, plane->zpos, true); 565 mixer_cfg_layer(ctx, plane->index, state->zpos + 1, true);
566 mixer_cfg_vp_blend(ctx);
515 mixer_run(ctx); 567 mixer_run(ctx);
516 568
517 mixer_vsync_set_update(ctx, true);
518 spin_unlock_irqrestore(&res->reg_slock, flags); 569 spin_unlock_irqrestore(&res->reg_slock, flags);
519 570
520 mixer_regs_dump(ctx); 571 mixer_regs_dump(ctx);
@@ -537,7 +588,7 @@ static void mixer_graph_buffer(struct mixer_context *ctx,
537 struct mixer_resources *res = &ctx->mixer_res; 588 struct mixer_resources *res = &ctx->mixer_res;
538 struct drm_framebuffer *fb = state->base.fb; 589 struct drm_framebuffer *fb = state->base.fb;
539 unsigned long flags; 590 unsigned long flags;
540 unsigned int win = plane->zpos; 591 unsigned int win = plane->index;
541 unsigned int x_ratio = 0, y_ratio = 0; 592 unsigned int x_ratio = 0, y_ratio = 0;
542 unsigned int src_x_offset, src_y_offset, dst_x_offset, dst_y_offset; 593 unsigned int src_x_offset, src_y_offset, dst_x_offset, dst_y_offset;
543 dma_addr_t dma_addr; 594 dma_addr_t dma_addr;
@@ -546,10 +597,12 @@ static void mixer_graph_buffer(struct mixer_context *ctx,
546 597
547 switch (fb->pixel_format) { 598 switch (fb->pixel_format) {
548 case DRM_FORMAT_XRGB4444: 599 case DRM_FORMAT_XRGB4444:
600 case DRM_FORMAT_ARGB4444:
549 fmt = MXR_FORMAT_ARGB4444; 601 fmt = MXR_FORMAT_ARGB4444;
550 break; 602 break;
551 603
552 case DRM_FORMAT_XRGB1555: 604 case DRM_FORMAT_XRGB1555:
605 case DRM_FORMAT_ARGB1555:
553 fmt = MXR_FORMAT_ARGB1555; 606 fmt = MXR_FORMAT_ARGB1555;
554 break; 607 break;
555 608
@@ -587,7 +640,6 @@ static void mixer_graph_buffer(struct mixer_context *ctx,
587 ctx->interlace = false; 640 ctx->interlace = false;
588 641
589 spin_lock_irqsave(&res->reg_slock, flags); 642 spin_lock_irqsave(&res->reg_slock, flags);
590 mixer_vsync_set_update(ctx, false);
591 643
592 /* setup format */ 644 /* setup format */
593 mixer_reg_writemask(res, MXR_GRAPHIC_CFG(win), 645 mixer_reg_writemask(res, MXR_GRAPHIC_CFG(win),
@@ -626,7 +678,8 @@ static void mixer_graph_buffer(struct mixer_context *ctx,
626 678
627 mixer_cfg_scan(ctx, mode->vdisplay); 679 mixer_cfg_scan(ctx, mode->vdisplay);
628 mixer_cfg_rgb_fmt(ctx, mode->vdisplay); 680 mixer_cfg_rgb_fmt(ctx, mode->vdisplay);
629 mixer_cfg_layer(ctx, win, true); 681 mixer_cfg_layer(ctx, win, state->zpos + 1, true);
682 mixer_cfg_gfx_blend(ctx, win, is_alpha_format(fb->pixel_format));
630 683
631 /* layer update mandatory for mixer 16.0.33.0 */ 684 /* layer update mandatory for mixer 16.0.33.0 */
632 if (ctx->mxr_ver == MXR_VER_16_0_33_0 || 685 if (ctx->mxr_ver == MXR_VER_16_0_33_0 ||
@@ -635,7 +688,6 @@ static void mixer_graph_buffer(struct mixer_context *ctx,
635 688
636 mixer_run(ctx); 689 mixer_run(ctx);
637 690
638 mixer_vsync_set_update(ctx, true);
639 spin_unlock_irqrestore(&res->reg_slock, flags); 691 spin_unlock_irqrestore(&res->reg_slock, flags);
640 692
641 mixer_regs_dump(ctx); 693 mixer_regs_dump(ctx);
@@ -660,10 +712,8 @@ static void mixer_win_reset(struct mixer_context *ctx)
660{ 712{
661 struct mixer_resources *res = &ctx->mixer_res; 713 struct mixer_resources *res = &ctx->mixer_res;
662 unsigned long flags; 714 unsigned long flags;
663 u32 val; /* value stored to register */
664 715
665 spin_lock_irqsave(&res->reg_slock, flags); 716 spin_lock_irqsave(&res->reg_slock, flags);
666 mixer_vsync_set_update(ctx, false);
667 717
668 mixer_reg_writemask(res, MXR_CFG, MXR_CFG_DST_HDMI, MXR_CFG_DST_MASK); 718 mixer_reg_writemask(res, MXR_CFG, MXR_CFG_DST_HDMI, MXR_CFG_DST_MASK);
669 719
@@ -674,40 +724,14 @@ static void mixer_win_reset(struct mixer_context *ctx)
674 mixer_reg_writemask(res, MXR_STATUS, MXR_STATUS_16_BURST, 724 mixer_reg_writemask(res, MXR_STATUS, MXR_STATUS_16_BURST,
675 MXR_STATUS_BURST_MASK); 725 MXR_STATUS_BURST_MASK);
676 726
677 /* setting default layer priority: layer1 > layer0 > video 727 /* reset default layer priority */
678 * because typical usage scenario would be 728 mixer_reg_write(res, MXR_LAYER_CFG, 0);
679 * layer1 - OSD
680 * layer0 - framebuffer
681 * video - video overlay
682 */
683 val = MXR_LAYER_CFG_GRP1_VAL(3);
684 val |= MXR_LAYER_CFG_GRP0_VAL(2);
685 if (ctx->vp_enabled)
686 val |= MXR_LAYER_CFG_VP_VAL(1);
687 mixer_reg_write(res, MXR_LAYER_CFG, val);
688 729
689 /* setting background color */ 730 /* setting background color */
690 mixer_reg_write(res, MXR_BG_COLOR0, 0x008080); 731 mixer_reg_write(res, MXR_BG_COLOR0, 0x008080);
691 mixer_reg_write(res, MXR_BG_COLOR1, 0x008080); 732 mixer_reg_write(res, MXR_BG_COLOR1, 0x008080);
692 mixer_reg_write(res, MXR_BG_COLOR2, 0x008080); 733 mixer_reg_write(res, MXR_BG_COLOR2, 0x008080);
693 734
694 /* setting graphical layers */
695 val = MXR_GRP_CFG_COLOR_KEY_DISABLE; /* no blank key */
696 val |= MXR_GRP_CFG_WIN_BLEND_EN;
697 val |= MXR_GRP_CFG_ALPHA_VAL(0xff); /* non-transparent alpha */
698
699 /* Don't blend layer 0 onto the mixer background */
700 mixer_reg_write(res, MXR_GRAPHIC_CFG(0), val);
701
702 /* Blend layer 1 into layer 0 */
703 val |= MXR_GRP_CFG_BLEND_PRE_MUL;
704 val |= MXR_GRP_CFG_PIXEL_BLEND_EN;
705 mixer_reg_write(res, MXR_GRAPHIC_CFG(1), val);
706
707 /* setting video layers */
708 val = MXR_GRP_CFG_ALPHA_VAL(0);
709 mixer_reg_write(res, MXR_VIDEO_CFG, val);
710
711 if (ctx->vp_enabled) { 735 if (ctx->vp_enabled) {
712 /* configuration of Video Processor Registers */ 736 /* configuration of Video Processor Registers */
713 vp_win_reset(ctx); 737 vp_win_reset(ctx);
@@ -720,7 +744,6 @@ static void mixer_win_reset(struct mixer_context *ctx)
720 if (ctx->vp_enabled) 744 if (ctx->vp_enabled)
721 mixer_reg_writemask(res, MXR_CFG, 0, MXR_CFG_VP_ENABLE); 745 mixer_reg_writemask(res, MXR_CFG, 0, MXR_CFG_VP_ENABLE);
722 746
723 mixer_vsync_set_update(ctx, true);
724 spin_unlock_irqrestore(&res->reg_slock, flags); 747 spin_unlock_irqrestore(&res->reg_slock, flags);
725} 748}
726 749
@@ -951,17 +974,27 @@ static void mixer_disable_vblank(struct exynos_drm_crtc *crtc)
951 mixer_reg_writemask(res, MXR_INT_EN, 0, MXR_INT_EN_VSYNC); 974 mixer_reg_writemask(res, MXR_INT_EN, 0, MXR_INT_EN_VSYNC);
952} 975}
953 976
977static void mixer_atomic_begin(struct exynos_drm_crtc *crtc)
978{
979 struct mixer_context *mixer_ctx = crtc->ctx;
980
981 if (!test_bit(MXR_BIT_POWERED, &mixer_ctx->flags))
982 return;
983
984 mixer_vsync_set_update(mixer_ctx, false);
985}
986
954static void mixer_update_plane(struct exynos_drm_crtc *crtc, 987static void mixer_update_plane(struct exynos_drm_crtc *crtc,
955 struct exynos_drm_plane *plane) 988 struct exynos_drm_plane *plane)
956{ 989{
957 struct mixer_context *mixer_ctx = crtc->ctx; 990 struct mixer_context *mixer_ctx = crtc->ctx;
958 991
959 DRM_DEBUG_KMS("win: %d\n", plane->zpos); 992 DRM_DEBUG_KMS("win: %d\n", plane->index);
960 993
961 if (!test_bit(MXR_BIT_POWERED, &mixer_ctx->flags)) 994 if (!test_bit(MXR_BIT_POWERED, &mixer_ctx->flags))
962 return; 995 return;
963 996
964 if (plane->zpos > 1 && mixer_ctx->vp_enabled) 997 if (plane->index == VP_DEFAULT_WIN)
965 vp_video_buffer(mixer_ctx, plane); 998 vp_video_buffer(mixer_ctx, plane);
966 else 999 else
967 mixer_graph_buffer(mixer_ctx, plane); 1000 mixer_graph_buffer(mixer_ctx, plane);
@@ -974,18 +1007,24 @@ static void mixer_disable_plane(struct exynos_drm_crtc *crtc,
974 struct mixer_resources *res = &mixer_ctx->mixer_res; 1007 struct mixer_resources *res = &mixer_ctx->mixer_res;
975 unsigned long flags; 1008 unsigned long flags;
976 1009
977 DRM_DEBUG_KMS("win: %d\n", plane->zpos); 1010 DRM_DEBUG_KMS("win: %d\n", plane->index);
978 1011
979 if (!test_bit(MXR_BIT_POWERED, &mixer_ctx->flags)) 1012 if (!test_bit(MXR_BIT_POWERED, &mixer_ctx->flags))
980 return; 1013 return;
981 1014
982 spin_lock_irqsave(&res->reg_slock, flags); 1015 spin_lock_irqsave(&res->reg_slock, flags);
983 mixer_vsync_set_update(mixer_ctx, false); 1016 mixer_cfg_layer(mixer_ctx, plane->index, 0, false);
1017 spin_unlock_irqrestore(&res->reg_slock, flags);
1018}
984 1019
985 mixer_cfg_layer(mixer_ctx, plane->zpos, false); 1020static void mixer_atomic_flush(struct exynos_drm_crtc *crtc)
1021{
1022 struct mixer_context *mixer_ctx = crtc->ctx;
1023
1024 if (!test_bit(MXR_BIT_POWERED, &mixer_ctx->flags))
1025 return;
986 1026
987 mixer_vsync_set_update(mixer_ctx, true); 1027 mixer_vsync_set_update(mixer_ctx, true);
988 spin_unlock_irqrestore(&res->reg_slock, flags);
989} 1028}
990 1029
991static void mixer_wait_for_vblank(struct exynos_drm_crtc *crtc) 1030static void mixer_wait_for_vblank(struct exynos_drm_crtc *crtc)
@@ -1026,6 +1065,8 @@ static void mixer_enable(struct exynos_drm_crtc *crtc)
1026 1065
1027 pm_runtime_get_sync(ctx->dev); 1066 pm_runtime_get_sync(ctx->dev);
1028 1067
1068 mixer_vsync_set_update(ctx, false);
1069
1029 mixer_reg_writemask(res, MXR_STATUS, ~0, MXR_STATUS_SOFT_RESET); 1070 mixer_reg_writemask(res, MXR_STATUS, ~0, MXR_STATUS_SOFT_RESET);
1030 1071
1031 if (test_bit(MXR_BIT_VSYNC, &ctx->flags)) { 1072 if (test_bit(MXR_BIT_VSYNC, &ctx->flags)) {
@@ -1034,6 +1075,8 @@ static void mixer_enable(struct exynos_drm_crtc *crtc)
1034 } 1075 }
1035 mixer_win_reset(ctx); 1076 mixer_win_reset(ctx);
1036 1077
1078 mixer_vsync_set_update(ctx, true);
1079
1037 set_bit(MXR_BIT_POWERED, &ctx->flags); 1080 set_bit(MXR_BIT_POWERED, &ctx->flags);
1038} 1081}
1039 1082
@@ -1084,8 +1127,10 @@ static const struct exynos_drm_crtc_ops mixer_crtc_ops = {
1084 .enable_vblank = mixer_enable_vblank, 1127 .enable_vblank = mixer_enable_vblank,
1085 .disable_vblank = mixer_disable_vblank, 1128 .disable_vblank = mixer_disable_vblank,
1086 .wait_for_vblank = mixer_wait_for_vblank, 1129 .wait_for_vblank = mixer_wait_for_vblank,
1130 .atomic_begin = mixer_atomic_begin,
1087 .update_plane = mixer_update_plane, 1131 .update_plane = mixer_update_plane,
1088 .disable_plane = mixer_disable_plane, 1132 .disable_plane = mixer_disable_plane,
1133 .atomic_flush = mixer_atomic_flush,
1089 .atomic_check = mixer_atomic_check, 1134 .atomic_check = mixer_atomic_check,
1090}; 1135};
1091 1136
@@ -1160,7 +1205,7 @@ static int mixer_bind(struct device *dev, struct device *manager, void *data)
1160 if (i == VP_DEFAULT_WIN && !ctx->vp_enabled) 1205 if (i == VP_DEFAULT_WIN && !ctx->vp_enabled)
1161 continue; 1206 continue;
1162 1207
1163 ret = exynos_plane_init(drm_dev, &ctx->planes[i], 1208 ret = exynos_plane_init(drm_dev, &ctx->planes[i], i,
1164 1 << ctx->pipe, &plane_configs[i]); 1209 1 << ctx->pipe, &plane_configs[i]);
1165 if (ret) 1210 if (ret)
1166 return ret; 1211 return ret;
diff --git a/drivers/gpu/drm/exynos/regs-mixer.h b/drivers/gpu/drm/exynos/regs-mixer.h
index ac60260c2389..7f22df5bf707 100644
--- a/drivers/gpu/drm/exynos/regs-mixer.h
+++ b/drivers/gpu/drm/exynos/regs-mixer.h
@@ -113,6 +113,7 @@
113#define MXR_GRP_CFG_BLEND_PRE_MUL (1 << 20) 113#define MXR_GRP_CFG_BLEND_PRE_MUL (1 << 20)
114#define MXR_GRP_CFG_WIN_BLEND_EN (1 << 17) 114#define MXR_GRP_CFG_WIN_BLEND_EN (1 << 17)
115#define MXR_GRP_CFG_PIXEL_BLEND_EN (1 << 16) 115#define MXR_GRP_CFG_PIXEL_BLEND_EN (1 << 16)
116#define MXR_GRP_CFG_MISC_MASK ((3 << 16) | (3 << 20))
116#define MXR_GRP_CFG_FORMAT_VAL(x) MXR_MASK_VAL(x, 11, 8) 117#define MXR_GRP_CFG_FORMAT_VAL(x) MXR_MASK_VAL(x, 11, 8)
117#define MXR_GRP_CFG_FORMAT_MASK MXR_GRP_CFG_FORMAT_VAL(~0) 118#define MXR_GRP_CFG_FORMAT_MASK MXR_GRP_CFG_FORMAT_VAL(~0)
118#define MXR_GRP_CFG_ALPHA_VAL(x) MXR_MASK_VAL(x, 7, 0) 119#define MXR_GRP_CFG_ALPHA_VAL(x) MXR_MASK_VAL(x, 7, 0)
@@ -145,8 +146,11 @@
145 146
146/* bit for MXR_LAYER_CFG */ 147/* bit for MXR_LAYER_CFG */
147#define MXR_LAYER_CFG_GRP1_VAL(x) MXR_MASK_VAL(x, 11, 8) 148#define MXR_LAYER_CFG_GRP1_VAL(x) MXR_MASK_VAL(x, 11, 8)
149#define MXR_LAYER_CFG_GRP1_MASK MXR_LAYER_CFG_GRP1_VAL(~0)
148#define MXR_LAYER_CFG_GRP0_VAL(x) MXR_MASK_VAL(x, 7, 4) 150#define MXR_LAYER_CFG_GRP0_VAL(x) MXR_MASK_VAL(x, 7, 4)
151#define MXR_LAYER_CFG_GRP0_MASK MXR_LAYER_CFG_GRP0_VAL(~0)
149#define MXR_LAYER_CFG_VP_VAL(x) MXR_MASK_VAL(x, 3, 0) 152#define MXR_LAYER_CFG_VP_VAL(x) MXR_MASK_VAL(x, 3, 0)
153#define MXR_LAYER_CFG_VP_MASK MXR_LAYER_CFG_VP_VAL(~0)
150 154
151#endif /* SAMSUNG_REGS_MIXER_H */ 155#endif /* SAMSUNG_REGS_MIXER_H */
152 156