2 * Copyright (C) 2011 Samsung Electronics Co.Ltd
4 * Seung-Woo Kim <sw0312.kim@samsung.com>
5 * Inki Dae <inki.dae@samsung.com>
6 * Joonyoung Shim <jy0922.shim@samsung.com>
8 * Based on drivers/media/video/s5p-tv/mixer_reg.c
10 * This program is free software; you can redistribute it and/or modify it
11 * under the terms of the GNU General Public License as published by the
12 * Free Software Foundation; either version 2 of the License, or (at your
13 * option) any later version.
19 #include "regs-mixer.h"
22 #include <linux/kernel.h>
23 #include <linux/spinlock.h>
24 #include <linux/wait.h>
25 #include <linux/i2c.h>
26 #include <linux/platform_device.h>
27 #include <linux/interrupt.h>
28 #include <linux/irq.h>
29 #include <linux/delay.h>
30 #include <linux/pm_runtime.h>
31 #include <linux/clk.h>
32 #include <linux/regulator/consumer.h>
34 #include <linux/component.h>
36 #include <drm/exynos_drm.h>
38 #include "exynos_drm_drv.h"
39 #include "exynos_drm_crtc.h"
40 #include "exynos_drm_plane.h"
41 #include "exynos_drm_iommu.h"
42 #include "exynos_mixer.h"
44 #define MIXER_WIN_NR 3
45 #define MIXER_DEFAULT_WIN 0
47 /* The pixelformats that are natively supported by the mixer. */
48 #define MXR_FORMAT_RGB565 4
49 #define MXR_FORMAT_ARGB1555 5
50 #define MXR_FORMAT_ARGB4444 6
51 #define MXR_FORMAT_ARGB8888 7
53 struct mixer_resources {
55 void __iomem *mixer_regs;
56 void __iomem *vp_regs;
61 struct clk *sclk_mixer;
62 struct clk *sclk_hdmi;
63 struct clk *mout_mixer;
66 enum mixer_version_id {
72 enum mixer_flag_bits {
77 struct mixer_context {
78 struct platform_device *pdev;
80 struct drm_device *drm_dev;
81 struct exynos_drm_crtc *crtc;
82 struct exynos_drm_plane planes[MIXER_WIN_NR];
89 struct mixer_resources mixer_res;
90 enum mixer_version_id mxr_ver;
91 wait_queue_head_t wait_vsync_queue;
92 atomic_t wait_vsync_event;
95 struct mixer_drv_data {
96 enum mixer_version_id version;
101 static const u8 filter_y_horiz_tap8[] = {
102 0, -1, -1, -1, -1, -1, -1, -1,
103 -1, -1, -1, -1, -1, 0, 0, 0,
104 0, 2, 4, 5, 6, 6, 6, 6,
105 6, 5, 5, 4, 3, 2, 1, 1,
106 0, -6, -12, -16, -18, -20, -21, -20,
107 -20, -18, -16, -13, -10, -8, -5, -2,
108 127, 126, 125, 121, 114, 107, 99, 89,
109 79, 68, 57, 46, 35, 25, 16, 8,
112 static const u8 filter_y_vert_tap4[] = {
113 0, -3, -6, -8, -8, -8, -8, -7,
114 -6, -5, -4, -3, -2, -1, -1, 0,
115 127, 126, 124, 118, 111, 102, 92, 81,
116 70, 59, 48, 37, 27, 19, 11, 5,
117 0, 5, 11, 19, 27, 37, 48, 59,
118 70, 81, 92, 102, 111, 118, 124, 126,
119 0, 0, -1, -1, -2, -3, -4, -5,
120 -6, -7, -8, -8, -8, -8, -6, -3,
123 static const u8 filter_cr_horiz_tap4[] = {
124 0, -3, -6, -8, -8, -8, -8, -7,
125 -6, -5, -4, -3, -2, -1, -1, 0,
126 127, 126, 124, 118, 111, 102, 92, 81,
127 70, 59, 48, 37, 27, 19, 11, 5,
130 static inline u32 vp_reg_read(struct mixer_resources *res, u32 reg_id)
132 return readl(res->vp_regs + reg_id);
135 static inline void vp_reg_write(struct mixer_resources *res, u32 reg_id,
138 writel(val, res->vp_regs + reg_id);
141 static inline void vp_reg_writemask(struct mixer_resources *res, u32 reg_id,
144 u32 old = vp_reg_read(res, reg_id);
146 val = (val & mask) | (old & ~mask);
147 writel(val, res->vp_regs + reg_id);
150 static inline u32 mixer_reg_read(struct mixer_resources *res, u32 reg_id)
152 return readl(res->mixer_regs + reg_id);
155 static inline void mixer_reg_write(struct mixer_resources *res, u32 reg_id,
158 writel(val, res->mixer_regs + reg_id);
161 static inline void mixer_reg_writemask(struct mixer_resources *res,
162 u32 reg_id, u32 val, u32 mask)
164 u32 old = mixer_reg_read(res, reg_id);
166 val = (val & mask) | (old & ~mask);
167 writel(val, res->mixer_regs + reg_id);
170 static void mixer_regs_dump(struct mixer_context *ctx)
172 #define DUMPREG(reg_id) \
174 DRM_DEBUG_KMS(#reg_id " = %08x\n", \
175 (u32)readl(ctx->mixer_res.mixer_regs + reg_id)); \
181 DUMPREG(MXR_INT_STATUS);
183 DUMPREG(MXR_LAYER_CFG);
184 DUMPREG(MXR_VIDEO_CFG);
186 DUMPREG(MXR_GRAPHIC0_CFG);
187 DUMPREG(MXR_GRAPHIC0_BASE);
188 DUMPREG(MXR_GRAPHIC0_SPAN);
189 DUMPREG(MXR_GRAPHIC0_WH);
190 DUMPREG(MXR_GRAPHIC0_SXY);
191 DUMPREG(MXR_GRAPHIC0_DXY);
193 DUMPREG(MXR_GRAPHIC1_CFG);
194 DUMPREG(MXR_GRAPHIC1_BASE);
195 DUMPREG(MXR_GRAPHIC1_SPAN);
196 DUMPREG(MXR_GRAPHIC1_WH);
197 DUMPREG(MXR_GRAPHIC1_SXY);
198 DUMPREG(MXR_GRAPHIC1_DXY);
202 static void vp_regs_dump(struct mixer_context *ctx)
204 #define DUMPREG(reg_id) \
206 DRM_DEBUG_KMS(#reg_id " = %08x\n", \
207 (u32) readl(ctx->mixer_res.vp_regs + reg_id)); \
212 DUMPREG(VP_SHADOW_UPDATE);
213 DUMPREG(VP_FIELD_ID);
215 DUMPREG(VP_IMG_SIZE_Y);
216 DUMPREG(VP_IMG_SIZE_C);
217 DUMPREG(VP_PER_RATE_CTRL);
218 DUMPREG(VP_TOP_Y_PTR);
219 DUMPREG(VP_BOT_Y_PTR);
220 DUMPREG(VP_TOP_C_PTR);
221 DUMPREG(VP_BOT_C_PTR);
222 DUMPREG(VP_ENDIAN_MODE);
223 DUMPREG(VP_SRC_H_POSITION);
224 DUMPREG(VP_SRC_V_POSITION);
225 DUMPREG(VP_SRC_WIDTH);
226 DUMPREG(VP_SRC_HEIGHT);
227 DUMPREG(VP_DST_H_POSITION);
228 DUMPREG(VP_DST_V_POSITION);
229 DUMPREG(VP_DST_WIDTH);
230 DUMPREG(VP_DST_HEIGHT);
237 static inline void vp_filter_set(struct mixer_resources *res,
238 int reg_id, const u8 *data, unsigned int size)
240 /* assure 4-byte align */
242 for (; size; size -= 4, reg_id += 4, data += 4) {
243 u32 val = (data[0] << 24) | (data[1] << 16) |
244 (data[2] << 8) | data[3];
245 vp_reg_write(res, reg_id, val);
249 static void vp_default_filter(struct mixer_resources *res)
251 vp_filter_set(res, VP_POLY8_Y0_LL,
252 filter_y_horiz_tap8, sizeof(filter_y_horiz_tap8));
253 vp_filter_set(res, VP_POLY4_Y0_LL,
254 filter_y_vert_tap4, sizeof(filter_y_vert_tap4));
255 vp_filter_set(res, VP_POLY4_C0_LL,
256 filter_cr_horiz_tap4, sizeof(filter_cr_horiz_tap4));
259 static void mixer_vsync_set_update(struct mixer_context *ctx, bool enable)
261 struct mixer_resources *res = &ctx->mixer_res;
263 /* block update on vsync */
264 mixer_reg_writemask(res, MXR_STATUS, enable ?
265 MXR_STATUS_SYNC_ENABLE : 0, MXR_STATUS_SYNC_ENABLE);
268 vp_reg_write(res, VP_SHADOW_UPDATE, enable ?
269 VP_SHADOW_UPDATE_ENABLE : 0);
272 static void mixer_cfg_scan(struct mixer_context *ctx, unsigned int height)
274 struct mixer_resources *res = &ctx->mixer_res;
277 /* choosing between interlace and progressive mode */
278 val = (ctx->interlace ? MXR_CFG_SCAN_INTERLACE :
279 MXR_CFG_SCAN_PROGRESSIVE);
281 if (ctx->mxr_ver != MXR_VER_128_0_0_184) {
282 /* choosing between proper HD and SD mode */
284 val |= MXR_CFG_SCAN_NTSC | MXR_CFG_SCAN_SD;
285 else if (height <= 576)
286 val |= MXR_CFG_SCAN_PAL | MXR_CFG_SCAN_SD;
287 else if (height <= 720)
288 val |= MXR_CFG_SCAN_HD_720 | MXR_CFG_SCAN_HD;
289 else if (height <= 1080)
290 val |= MXR_CFG_SCAN_HD_1080 | MXR_CFG_SCAN_HD;
292 val |= MXR_CFG_SCAN_HD_720 | MXR_CFG_SCAN_HD;
295 mixer_reg_writemask(res, MXR_CFG, val, MXR_CFG_SCAN_MASK);
298 static void mixer_cfg_rgb_fmt(struct mixer_context *ctx, unsigned int height)
300 struct mixer_resources *res = &ctx->mixer_res;
304 val = MXR_CFG_RGB601_0_255;
305 } else if (height == 576) {
306 val = MXR_CFG_RGB601_0_255;
307 } else if (height == 720) {
308 val = MXR_CFG_RGB709_16_235;
309 mixer_reg_write(res, MXR_CM_COEFF_Y,
310 (1 << 30) | (94 << 20) | (314 << 10) |
312 mixer_reg_write(res, MXR_CM_COEFF_CB,
313 (972 << 20) | (851 << 10) | (225 << 0));
314 mixer_reg_write(res, MXR_CM_COEFF_CR,
315 (225 << 20) | (820 << 10) | (1004 << 0));
316 } else if (height == 1080) {
317 val = MXR_CFG_RGB709_16_235;
318 mixer_reg_write(res, MXR_CM_COEFF_Y,
319 (1 << 30) | (94 << 20) | (314 << 10) |
321 mixer_reg_write(res, MXR_CM_COEFF_CB,
322 (972 << 20) | (851 << 10) | (225 << 0));
323 mixer_reg_write(res, MXR_CM_COEFF_CR,
324 (225 << 20) | (820 << 10) | (1004 << 0));
326 val = MXR_CFG_RGB709_16_235;
327 mixer_reg_write(res, MXR_CM_COEFF_Y,
328 (1 << 30) | (94 << 20) | (314 << 10) |
330 mixer_reg_write(res, MXR_CM_COEFF_CB,
331 (972 << 20) | (851 << 10) | (225 << 0));
332 mixer_reg_write(res, MXR_CM_COEFF_CR,
333 (225 << 20) | (820 << 10) | (1004 << 0));
336 mixer_reg_writemask(res, MXR_CFG, val, MXR_CFG_RGB_FMT_MASK);
339 static void mixer_cfg_layer(struct mixer_context *ctx, unsigned int win,
342 struct mixer_resources *res = &ctx->mixer_res;
343 u32 val = enable ? ~0 : 0;
347 mixer_reg_writemask(res, MXR_CFG, val, MXR_CFG_GRP0_ENABLE);
350 mixer_reg_writemask(res, MXR_CFG, val, MXR_CFG_GRP1_ENABLE);
353 if (ctx->vp_enabled) {
354 vp_reg_writemask(res, VP_ENABLE, val, VP_ENABLE_ON);
355 mixer_reg_writemask(res, MXR_CFG, val,
358 /* control blending of graphic layer 0 */
359 mixer_reg_writemask(res, MXR_GRAPHIC_CFG(0), val,
360 MXR_GRP_CFG_BLEND_PRE_MUL |
361 MXR_GRP_CFG_PIXEL_BLEND_EN);
367 static void mixer_run(struct mixer_context *ctx)
369 struct mixer_resources *res = &ctx->mixer_res;
371 mixer_reg_writemask(res, MXR_STATUS, ~0, MXR_STATUS_REG_RUN);
374 static void mixer_stop(struct mixer_context *ctx)
376 struct mixer_resources *res = &ctx->mixer_res;
379 mixer_reg_writemask(res, MXR_STATUS, 0, MXR_STATUS_REG_RUN);
381 while (!(mixer_reg_read(res, MXR_STATUS) & MXR_STATUS_REG_IDLE) &&
383 usleep_range(10000, 12000);
386 static void vp_video_buffer(struct mixer_context *ctx,
387 struct exynos_drm_plane *plane)
389 struct mixer_resources *res = &ctx->mixer_res;
390 struct drm_plane_state *state = plane->base.state;
391 struct drm_framebuffer *fb = state->fb;
392 struct drm_display_mode *mode = &state->crtc->mode;
394 dma_addr_t luma_addr[2], chroma_addr[2];
395 bool tiled_mode = false;
396 bool crcb_mode = false;
399 switch (fb->pixel_format) {
400 case DRM_FORMAT_NV12:
403 case DRM_FORMAT_NV21:
407 DRM_ERROR("pixel format for vp is wrong [%d].\n",
412 luma_addr[0] = plane->dma_addr[0];
413 chroma_addr[0] = plane->dma_addr[1];
415 if (mode->flags & DRM_MODE_FLAG_INTERLACE) {
416 ctx->interlace = true;
418 luma_addr[1] = luma_addr[0] + 0x40;
419 chroma_addr[1] = chroma_addr[0] + 0x40;
421 luma_addr[1] = luma_addr[0] + fb->pitches[0];
422 chroma_addr[1] = chroma_addr[0] + fb->pitches[0];
425 ctx->interlace = false;
430 spin_lock_irqsave(&res->reg_slock, flags);
431 mixer_vsync_set_update(ctx, false);
433 /* interlace or progressive scan mode */
434 val = (ctx->interlace ? ~0 : 0);
435 vp_reg_writemask(res, VP_MODE, val, VP_MODE_LINE_SKIP);
438 val = (crcb_mode ? VP_MODE_NV21 : VP_MODE_NV12);
439 val |= (tiled_mode ? VP_MODE_MEM_TILED : VP_MODE_MEM_LINEAR);
440 vp_reg_writemask(res, VP_MODE, val, VP_MODE_FMT_MASK);
442 /* setting size of input image */
443 vp_reg_write(res, VP_IMG_SIZE_Y, VP_IMG_HSIZE(fb->pitches[0]) |
444 VP_IMG_VSIZE(fb->height));
445 /* chroma height has to reduced by 2 to avoid chroma distorions */
446 vp_reg_write(res, VP_IMG_SIZE_C, VP_IMG_HSIZE(fb->pitches[0]) |
447 VP_IMG_VSIZE(fb->height / 2));
449 vp_reg_write(res, VP_SRC_WIDTH, plane->src_width);
450 vp_reg_write(res, VP_SRC_HEIGHT, plane->src_height);
451 vp_reg_write(res, VP_SRC_H_POSITION,
452 VP_SRC_H_POSITION_VAL(plane->src_x));
453 vp_reg_write(res, VP_SRC_V_POSITION, plane->src_y);
455 vp_reg_write(res, VP_DST_WIDTH, plane->crtc_width);
456 vp_reg_write(res, VP_DST_H_POSITION, plane->crtc_x);
457 if (ctx->interlace) {
458 vp_reg_write(res, VP_DST_HEIGHT, plane->crtc_height / 2);
459 vp_reg_write(res, VP_DST_V_POSITION, plane->crtc_y / 2);
461 vp_reg_write(res, VP_DST_HEIGHT, plane->crtc_height);
462 vp_reg_write(res, VP_DST_V_POSITION, plane->crtc_y);
465 vp_reg_write(res, VP_H_RATIO, plane->h_ratio);
466 vp_reg_write(res, VP_V_RATIO, plane->v_ratio);
468 vp_reg_write(res, VP_ENDIAN_MODE, VP_ENDIAN_MODE_LITTLE);
470 /* set buffer address to vp */
471 vp_reg_write(res, VP_TOP_Y_PTR, luma_addr[0]);
472 vp_reg_write(res, VP_BOT_Y_PTR, luma_addr[1]);
473 vp_reg_write(res, VP_TOP_C_PTR, chroma_addr[0]);
474 vp_reg_write(res, VP_BOT_C_PTR, chroma_addr[1]);
476 mixer_cfg_scan(ctx, mode->vdisplay);
477 mixer_cfg_rgb_fmt(ctx, mode->vdisplay);
478 mixer_cfg_layer(ctx, plane->zpos, true);
481 mixer_vsync_set_update(ctx, true);
482 spin_unlock_irqrestore(&res->reg_slock, flags);
484 mixer_regs_dump(ctx);
488 static void mixer_layer_update(struct mixer_context *ctx)
490 struct mixer_resources *res = &ctx->mixer_res;
492 mixer_reg_writemask(res, MXR_CFG, ~0, MXR_CFG_LAYER_UPDATE);
495 static int mixer_setup_scale(const struct exynos_drm_plane *plane,
496 unsigned int *x_ratio, unsigned int *y_ratio)
498 if (plane->crtc_width != plane->src_width) {
499 if (plane->crtc_width == 2 * plane->src_width)
505 if (plane->crtc_height != plane->src_height) {
506 if (plane->crtc_height == 2 * plane->src_height)
515 DRM_DEBUG_KMS("only 2x width/height scaling of plane supported\n");
519 static void mixer_graph_buffer(struct mixer_context *ctx,
520 struct exynos_drm_plane *plane)
522 struct mixer_resources *res = &ctx->mixer_res;
523 struct drm_plane_state *state = plane->base.state;
524 struct drm_framebuffer *fb = state->fb;
525 struct drm_display_mode *mode = &state->crtc->mode;
527 unsigned int win = plane->zpos;
528 unsigned int x_ratio = 0, y_ratio = 0;
529 unsigned int src_x_offset, src_y_offset, dst_x_offset, dst_y_offset;
534 switch (fb->pixel_format) {
535 case DRM_FORMAT_XRGB4444:
536 fmt = MXR_FORMAT_ARGB4444;
539 case DRM_FORMAT_XRGB1555:
540 fmt = MXR_FORMAT_ARGB1555;
543 case DRM_FORMAT_RGB565:
544 fmt = MXR_FORMAT_RGB565;
547 case DRM_FORMAT_XRGB8888:
548 case DRM_FORMAT_ARGB8888:
549 fmt = MXR_FORMAT_ARGB8888;
553 DRM_DEBUG_KMS("pixelformat unsupported by mixer\n");
557 /* check if mixer supports requested scaling setup */
558 if (mixer_setup_scale(plane, &x_ratio, &y_ratio))
561 dst_x_offset = plane->crtc_x;
562 dst_y_offset = plane->crtc_y;
564 /* converting dma address base and source offset */
565 dma_addr = plane->dma_addr[0]
566 + (plane->src_x * fb->bits_per_pixel >> 3)
567 + (plane->src_y * fb->pitches[0]);
571 if (mode->flags & DRM_MODE_FLAG_INTERLACE)
572 ctx->interlace = true;
574 ctx->interlace = false;
576 spin_lock_irqsave(&res->reg_slock, flags);
577 mixer_vsync_set_update(ctx, false);
580 mixer_reg_writemask(res, MXR_GRAPHIC_CFG(win),
581 MXR_GRP_CFG_FORMAT_VAL(fmt), MXR_GRP_CFG_FORMAT_MASK);
584 mixer_reg_write(res, MXR_GRAPHIC_SPAN(win),
585 fb->pitches[0] / (fb->bits_per_pixel >> 3));
587 /* setup display size */
588 if (ctx->mxr_ver == MXR_VER_128_0_0_184 &&
589 win == MIXER_DEFAULT_WIN) {
590 val = MXR_MXR_RES_HEIGHT(mode->vdisplay);
591 val |= MXR_MXR_RES_WIDTH(mode->hdisplay);
592 mixer_reg_write(res, MXR_RESOLUTION, val);
595 val = MXR_GRP_WH_WIDTH(plane->src_width);
596 val |= MXR_GRP_WH_HEIGHT(plane->src_height);
597 val |= MXR_GRP_WH_H_SCALE(x_ratio);
598 val |= MXR_GRP_WH_V_SCALE(y_ratio);
599 mixer_reg_write(res, MXR_GRAPHIC_WH(win), val);
601 /* setup offsets in source image */
602 val = MXR_GRP_SXY_SX(src_x_offset);
603 val |= MXR_GRP_SXY_SY(src_y_offset);
604 mixer_reg_write(res, MXR_GRAPHIC_SXY(win), val);
606 /* setup offsets in display image */
607 val = MXR_GRP_DXY_DX(dst_x_offset);
608 val |= MXR_GRP_DXY_DY(dst_y_offset);
609 mixer_reg_write(res, MXR_GRAPHIC_DXY(win), val);
611 /* set buffer address to mixer */
612 mixer_reg_write(res, MXR_GRAPHIC_BASE(win), dma_addr);
614 mixer_cfg_scan(ctx, mode->vdisplay);
615 mixer_cfg_rgb_fmt(ctx, mode->vdisplay);
616 mixer_cfg_layer(ctx, win, true);
618 /* layer update mandatory for mixer 16.0.33.0 */
619 if (ctx->mxr_ver == MXR_VER_16_0_33_0 ||
620 ctx->mxr_ver == MXR_VER_128_0_0_184)
621 mixer_layer_update(ctx);
625 mixer_vsync_set_update(ctx, true);
626 spin_unlock_irqrestore(&res->reg_slock, flags);
628 mixer_regs_dump(ctx);
631 static void vp_win_reset(struct mixer_context *ctx)
633 struct mixer_resources *res = &ctx->mixer_res;
636 vp_reg_write(res, VP_SRESET, VP_SRESET_PROCESSING);
637 for (tries = 100; tries; --tries) {
638 /* waiting until VP_SRESET_PROCESSING is 0 */
639 if (~vp_reg_read(res, VP_SRESET) & VP_SRESET_PROCESSING)
641 usleep_range(10000, 12000);
643 WARN(tries == 0, "failed to reset Video Processor\n");
646 static void mixer_win_reset(struct mixer_context *ctx)
648 struct mixer_resources *res = &ctx->mixer_res;
650 u32 val; /* value stored to register */
652 spin_lock_irqsave(&res->reg_slock, flags);
653 mixer_vsync_set_update(ctx, false);
655 mixer_reg_writemask(res, MXR_CFG, MXR_CFG_DST_HDMI, MXR_CFG_DST_MASK);
657 /* set output in RGB888 mode */
658 mixer_reg_writemask(res, MXR_CFG, MXR_CFG_OUT_RGB888, MXR_CFG_OUT_MASK);
660 /* 16 beat burst in DMA */
661 mixer_reg_writemask(res, MXR_STATUS, MXR_STATUS_16_BURST,
662 MXR_STATUS_BURST_MASK);
664 /* setting default layer priority: layer1 > layer0 > video
665 * because typical usage scenario would be
667 * layer0 - framebuffer
668 * video - video overlay
670 val = MXR_LAYER_CFG_GRP1_VAL(3);
671 val |= MXR_LAYER_CFG_GRP0_VAL(2);
673 val |= MXR_LAYER_CFG_VP_VAL(1);
674 mixer_reg_write(res, MXR_LAYER_CFG, val);
676 /* setting background color */
677 mixer_reg_write(res, MXR_BG_COLOR0, 0x008080);
678 mixer_reg_write(res, MXR_BG_COLOR1, 0x008080);
679 mixer_reg_write(res, MXR_BG_COLOR2, 0x008080);
681 /* setting graphical layers */
682 val = MXR_GRP_CFG_COLOR_KEY_DISABLE; /* no blank key */
683 val |= MXR_GRP_CFG_WIN_BLEND_EN;
684 val |= MXR_GRP_CFG_ALPHA_VAL(0xff); /* non-transparent alpha */
686 /* Don't blend layer 0 onto the mixer background */
687 mixer_reg_write(res, MXR_GRAPHIC_CFG(0), val);
689 /* Blend layer 1 into layer 0 */
690 val |= MXR_GRP_CFG_BLEND_PRE_MUL;
691 val |= MXR_GRP_CFG_PIXEL_BLEND_EN;
692 mixer_reg_write(res, MXR_GRAPHIC_CFG(1), val);
694 /* setting video layers */
695 val = MXR_GRP_CFG_ALPHA_VAL(0);
696 mixer_reg_write(res, MXR_VIDEO_CFG, val);
698 if (ctx->vp_enabled) {
699 /* configuration of Video Processor Registers */
701 vp_default_filter(res);
704 /* disable all layers */
705 mixer_reg_writemask(res, MXR_CFG, 0, MXR_CFG_GRP0_ENABLE);
706 mixer_reg_writemask(res, MXR_CFG, 0, MXR_CFG_GRP1_ENABLE);
708 mixer_reg_writemask(res, MXR_CFG, 0, MXR_CFG_VP_ENABLE);
710 mixer_vsync_set_update(ctx, true);
711 spin_unlock_irqrestore(&res->reg_slock, flags);
714 static irqreturn_t mixer_irq_handler(int irq, void *arg)
716 struct mixer_context *ctx = arg;
717 struct mixer_resources *res = &ctx->mixer_res;
718 u32 val, base, shadow;
720 spin_lock(&res->reg_slock);
722 /* read interrupt status for handling and clearing flags for VSYNC */
723 val = mixer_reg_read(res, MXR_INT_STATUS);
726 if (val & MXR_INT_STATUS_VSYNC) {
727 /* vsync interrupt use different bit for read and clear */
728 val |= MXR_INT_CLEAR_VSYNC;
729 val &= ~MXR_INT_STATUS_VSYNC;
731 /* interlace scan need to check shadow register */
732 if (ctx->interlace) {
733 base = mixer_reg_read(res, MXR_GRAPHIC_BASE(0));
734 shadow = mixer_reg_read(res, MXR_GRAPHIC_BASE_S(0));
738 base = mixer_reg_read(res, MXR_GRAPHIC_BASE(1));
739 shadow = mixer_reg_read(res, MXR_GRAPHIC_BASE_S(1));
744 drm_crtc_handle_vblank(&ctx->crtc->base);
745 exynos_drm_crtc_finish_pageflip(ctx->crtc);
747 /* set wait vsync event to zero and wake up queue. */
748 if (atomic_read(&ctx->wait_vsync_event)) {
749 atomic_set(&ctx->wait_vsync_event, 0);
750 wake_up(&ctx->wait_vsync_queue);
755 /* clear interrupts */
756 mixer_reg_write(res, MXR_INT_STATUS, val);
758 spin_unlock(&res->reg_slock);
763 static int mixer_resources_init(struct mixer_context *mixer_ctx)
765 struct device *dev = &mixer_ctx->pdev->dev;
766 struct mixer_resources *mixer_res = &mixer_ctx->mixer_res;
767 struct resource *res;
770 spin_lock_init(&mixer_res->reg_slock);
772 mixer_res->mixer = devm_clk_get(dev, "mixer");
773 if (IS_ERR(mixer_res->mixer)) {
774 dev_err(dev, "failed to get clock 'mixer'\n");
778 mixer_res->hdmi = devm_clk_get(dev, "hdmi");
779 if (IS_ERR(mixer_res->hdmi)) {
780 dev_err(dev, "failed to get clock 'hdmi'\n");
781 return PTR_ERR(mixer_res->hdmi);
784 mixer_res->sclk_hdmi = devm_clk_get(dev, "sclk_hdmi");
785 if (IS_ERR(mixer_res->sclk_hdmi)) {
786 dev_err(dev, "failed to get clock 'sclk_hdmi'\n");
789 res = platform_get_resource(mixer_ctx->pdev, IORESOURCE_MEM, 0);
791 dev_err(dev, "get memory resource failed.\n");
795 mixer_res->mixer_regs = devm_ioremap(dev, res->start,
797 if (mixer_res->mixer_regs == NULL) {
798 dev_err(dev, "register mapping failed.\n");
802 res = platform_get_resource(mixer_ctx->pdev, IORESOURCE_IRQ, 0);
804 dev_err(dev, "get interrupt resource failed.\n");
808 ret = devm_request_irq(dev, res->start, mixer_irq_handler,
809 0, "drm_mixer", mixer_ctx);
811 dev_err(dev, "request interrupt failed.\n");
814 mixer_res->irq = res->start;
819 static int vp_resources_init(struct mixer_context *mixer_ctx)
821 struct device *dev = &mixer_ctx->pdev->dev;
822 struct mixer_resources *mixer_res = &mixer_ctx->mixer_res;
823 struct resource *res;
825 mixer_res->vp = devm_clk_get(dev, "vp");
826 if (IS_ERR(mixer_res->vp)) {
827 dev_err(dev, "failed to get clock 'vp'\n");
831 if (mixer_ctx->has_sclk) {
832 mixer_res->sclk_mixer = devm_clk_get(dev, "sclk_mixer");
833 if (IS_ERR(mixer_res->sclk_mixer)) {
834 dev_err(dev, "failed to get clock 'sclk_mixer'\n");
837 mixer_res->mout_mixer = devm_clk_get(dev, "mout_mixer");
838 if (IS_ERR(mixer_res->mout_mixer)) {
839 dev_err(dev, "failed to get clock 'mout_mixer'\n");
843 if (mixer_res->sclk_hdmi && mixer_res->mout_mixer)
844 clk_set_parent(mixer_res->mout_mixer,
845 mixer_res->sclk_hdmi);
848 res = platform_get_resource(mixer_ctx->pdev, IORESOURCE_MEM, 1);
850 dev_err(dev, "get memory resource failed.\n");
854 mixer_res->vp_regs = devm_ioremap(dev, res->start,
856 if (mixer_res->vp_regs == NULL) {
857 dev_err(dev, "register mapping failed.\n");
864 static int mixer_initialize(struct mixer_context *mixer_ctx,
865 struct drm_device *drm_dev)
868 struct exynos_drm_private *priv;
869 priv = drm_dev->dev_private;
871 mixer_ctx->drm_dev = drm_dev;
872 mixer_ctx->pipe = priv->pipe++;
874 /* acquire resources: regs, irqs, clocks */
875 ret = mixer_resources_init(mixer_ctx);
877 DRM_ERROR("mixer_resources_init failed ret=%d\n", ret);
881 if (mixer_ctx->vp_enabled) {
882 /* acquire vp resources: regs, irqs, clocks */
883 ret = vp_resources_init(mixer_ctx);
885 DRM_ERROR("vp_resources_init failed ret=%d\n", ret);
890 ret = drm_iommu_attach_device(drm_dev, mixer_ctx->dev);
897 static void mixer_ctx_remove(struct mixer_context *mixer_ctx)
899 drm_iommu_detach_device(mixer_ctx->drm_dev, mixer_ctx->dev);
902 static int mixer_enable_vblank(struct exynos_drm_crtc *crtc)
904 struct mixer_context *mixer_ctx = crtc->ctx;
905 struct mixer_resources *res = &mixer_ctx->mixer_res;
907 __set_bit(MXR_BIT_VSYNC, &mixer_ctx->flags);
908 if (!test_bit(MXR_BIT_POWERED, &mixer_ctx->flags))
911 /* enable vsync interrupt */
912 mixer_reg_writemask(res, MXR_INT_STATUS, ~0, MXR_INT_CLEAR_VSYNC);
913 mixer_reg_writemask(res, MXR_INT_EN, ~0, MXR_INT_EN_VSYNC);
918 static void mixer_disable_vblank(struct exynos_drm_crtc *crtc)
920 struct mixer_context *mixer_ctx = crtc->ctx;
921 struct mixer_resources *res = &mixer_ctx->mixer_res;
923 __clear_bit(MXR_BIT_VSYNC, &mixer_ctx->flags);
925 if (!test_bit(MXR_BIT_POWERED, &mixer_ctx->flags))
928 /* disable vsync interrupt */
929 mixer_reg_writemask(res, MXR_INT_STATUS, ~0, MXR_INT_CLEAR_VSYNC);
930 mixer_reg_writemask(res, MXR_INT_EN, 0, MXR_INT_EN_VSYNC);
933 static void mixer_update_plane(struct exynos_drm_crtc *crtc,
934 struct exynos_drm_plane *plane)
936 struct mixer_context *mixer_ctx = crtc->ctx;
938 DRM_DEBUG_KMS("win: %d\n", plane->zpos);
940 if (!test_bit(MXR_BIT_POWERED, &mixer_ctx->flags))
943 if (plane->zpos > 1 && mixer_ctx->vp_enabled)
944 vp_video_buffer(mixer_ctx, plane);
946 mixer_graph_buffer(mixer_ctx, plane);
949 static void mixer_disable_plane(struct exynos_drm_crtc *crtc,
950 struct exynos_drm_plane *plane)
952 struct mixer_context *mixer_ctx = crtc->ctx;
953 struct mixer_resources *res = &mixer_ctx->mixer_res;
956 DRM_DEBUG_KMS("win: %d\n", plane->zpos);
958 if (!test_bit(MXR_BIT_POWERED, &mixer_ctx->flags))
961 spin_lock_irqsave(&res->reg_slock, flags);
962 mixer_vsync_set_update(mixer_ctx, false);
964 mixer_cfg_layer(mixer_ctx, plane->zpos, false);
966 mixer_vsync_set_update(mixer_ctx, true);
967 spin_unlock_irqrestore(&res->reg_slock, flags);
970 static void mixer_wait_for_vblank(struct exynos_drm_crtc *crtc)
972 struct mixer_context *mixer_ctx = crtc->ctx;
975 if (!test_bit(MXR_BIT_POWERED, &mixer_ctx->flags))
978 err = drm_vblank_get(mixer_ctx->drm_dev, mixer_ctx->pipe);
980 DRM_DEBUG_KMS("failed to acquire vblank counter\n");
984 atomic_set(&mixer_ctx->wait_vsync_event, 1);
987 * wait for MIXER to signal VSYNC interrupt or return after
988 * timeout which is set to 50ms (refresh rate of 20).
990 if (!wait_event_timeout(mixer_ctx->wait_vsync_queue,
991 !atomic_read(&mixer_ctx->wait_vsync_event),
993 DRM_DEBUG_KMS("vblank wait timed out.\n");
995 drm_vblank_put(mixer_ctx->drm_dev, mixer_ctx->pipe);
998 static void mixer_enable(struct exynos_drm_crtc *crtc)
1000 struct mixer_context *ctx = crtc->ctx;
1001 struct mixer_resources *res = &ctx->mixer_res;
1004 if (test_bit(MXR_BIT_POWERED, &ctx->flags))
1007 pm_runtime_get_sync(ctx->dev);
1009 ret = clk_prepare_enable(res->mixer);
1011 DRM_ERROR("Failed to prepare_enable the mixer clk [%d]\n", ret);
1014 ret = clk_prepare_enable(res->hdmi);
1016 DRM_ERROR("Failed to prepare_enable the hdmi clk [%d]\n", ret);
1019 if (ctx->vp_enabled) {
1020 ret = clk_prepare_enable(res->vp);
1022 DRM_ERROR("Failed to prepare_enable the vp clk [%d]\n",
1026 if (ctx->has_sclk) {
1027 ret = clk_prepare_enable(res->sclk_mixer);
1029 DRM_ERROR("Failed to prepare_enable the " \
1030 "sclk_mixer clk [%d]\n",
1037 set_bit(MXR_BIT_POWERED, &ctx->flags);
1039 mixer_reg_writemask(res, MXR_STATUS, ~0, MXR_STATUS_SOFT_RESET);
1041 if (test_bit(MXR_BIT_VSYNC, &ctx->flags)) {
1042 mixer_reg_writemask(res, MXR_INT_STATUS, ~0, MXR_INT_CLEAR_VSYNC);
1043 mixer_reg_writemask(res, MXR_INT_EN, ~0, MXR_INT_EN_VSYNC);
1045 mixer_win_reset(ctx);
1048 static void mixer_disable(struct exynos_drm_crtc *crtc)
1050 struct mixer_context *ctx = crtc->ctx;
1051 struct mixer_resources *res = &ctx->mixer_res;
1054 if (!test_bit(MXR_BIT_POWERED, &ctx->flags))
1058 mixer_regs_dump(ctx);
1060 for (i = 0; i < MIXER_WIN_NR; i++)
1061 mixer_disable_plane(crtc, &ctx->planes[i]);
1063 clear_bit(MXR_BIT_POWERED, &ctx->flags);
1065 clk_disable_unprepare(res->hdmi);
1066 clk_disable_unprepare(res->mixer);
1067 if (ctx->vp_enabled) {
1068 clk_disable_unprepare(res->vp);
1070 clk_disable_unprepare(res->sclk_mixer);
1073 pm_runtime_put_sync(ctx->dev);
1076 /* Only valid for Mixer version 16.0.33.0 */
1077 int mixer_check_mode(struct drm_display_mode *mode)
1084 DRM_DEBUG_KMS("xres=%d, yres=%d, refresh=%d, intl=%d\n",
1085 mode->hdisplay, mode->vdisplay, mode->vrefresh,
1086 (mode->flags & DRM_MODE_FLAG_INTERLACE) ? 1 : 0);
1088 if ((w >= 464 && w <= 720 && h >= 261 && h <= 576) ||
1089 (w >= 1024 && w <= 1280 && h >= 576 && h <= 720) ||
1090 (w >= 1664 && w <= 1920 && h >= 936 && h <= 1080))
1096 static const struct exynos_drm_crtc_ops mixer_crtc_ops = {
1097 .enable = mixer_enable,
1098 .disable = mixer_disable,
1099 .enable_vblank = mixer_enable_vblank,
1100 .disable_vblank = mixer_disable_vblank,
1101 .wait_for_vblank = mixer_wait_for_vblank,
1102 .update_plane = mixer_update_plane,
1103 .disable_plane = mixer_disable_plane,
1106 static struct mixer_drv_data exynos5420_mxr_drv_data = {
1107 .version = MXR_VER_128_0_0_184,
1111 static struct mixer_drv_data exynos5250_mxr_drv_data = {
1112 .version = MXR_VER_16_0_33_0,
1116 static struct mixer_drv_data exynos4212_mxr_drv_data = {
1117 .version = MXR_VER_0_0_0_16,
1121 static struct mixer_drv_data exynos4210_mxr_drv_data = {
1122 .version = MXR_VER_0_0_0_16,
1127 static const struct platform_device_id mixer_driver_types[] = {
1129 .name = "s5p-mixer",
1130 .driver_data = (unsigned long)&exynos4210_mxr_drv_data,
1132 .name = "exynos5-mixer",
1133 .driver_data = (unsigned long)&exynos5250_mxr_drv_data,
1139 static struct of_device_id mixer_match_types[] = {
1141 .compatible = "samsung,exynos4210-mixer",
1142 .data = &exynos4210_mxr_drv_data,
1144 .compatible = "samsung,exynos4212-mixer",
1145 .data = &exynos4212_mxr_drv_data,
1147 .compatible = "samsung,exynos5-mixer",
1148 .data = &exynos5250_mxr_drv_data,
1150 .compatible = "samsung,exynos5250-mixer",
1151 .data = &exynos5250_mxr_drv_data,
1153 .compatible = "samsung,exynos5420-mixer",
1154 .data = &exynos5420_mxr_drv_data,
1159 MODULE_DEVICE_TABLE(of, mixer_match_types);
1161 static int mixer_bind(struct device *dev, struct device *manager, void *data)
1163 struct mixer_context *ctx = dev_get_drvdata(dev);
1164 struct drm_device *drm_dev = data;
1165 struct exynos_drm_plane *exynos_plane;
1166 enum drm_plane_type type;
1170 ret = mixer_initialize(ctx, drm_dev);
1174 for (zpos = 0; zpos < MIXER_WIN_NR; zpos++) {
1175 type = (zpos == MIXER_DEFAULT_WIN) ? DRM_PLANE_TYPE_PRIMARY :
1176 DRM_PLANE_TYPE_OVERLAY;
1177 ret = exynos_plane_init(drm_dev, &ctx->planes[zpos],
1178 1 << ctx->pipe, type, zpos);
1183 exynos_plane = &ctx->planes[MIXER_DEFAULT_WIN];
1184 ctx->crtc = exynos_drm_crtc_create(drm_dev, &exynos_plane->base,
1185 ctx->pipe, EXYNOS_DISPLAY_TYPE_HDMI,
1186 &mixer_crtc_ops, ctx);
1187 if (IS_ERR(ctx->crtc)) {
1188 mixer_ctx_remove(ctx);
1189 ret = PTR_ERR(ctx->crtc);
1196 devm_kfree(dev, ctx);
1200 static void mixer_unbind(struct device *dev, struct device *master, void *data)
1202 struct mixer_context *ctx = dev_get_drvdata(dev);
1204 mixer_ctx_remove(ctx);
1207 static const struct component_ops mixer_component_ops = {
1209 .unbind = mixer_unbind,
1212 static int mixer_probe(struct platform_device *pdev)
1214 struct device *dev = &pdev->dev;
1215 struct mixer_drv_data *drv;
1216 struct mixer_context *ctx;
1219 ctx = devm_kzalloc(&pdev->dev, sizeof(*ctx), GFP_KERNEL);
1221 DRM_ERROR("failed to alloc mixer context.\n");
1226 const struct of_device_id *match;
1228 match = of_match_node(mixer_match_types, dev->of_node);
1229 drv = (struct mixer_drv_data *)match->data;
1231 drv = (struct mixer_drv_data *)
1232 platform_get_device_id(pdev)->driver_data;
1237 ctx->vp_enabled = drv->is_vp_enabled;
1238 ctx->has_sclk = drv->has_sclk;
1239 ctx->mxr_ver = drv->version;
1240 init_waitqueue_head(&ctx->wait_vsync_queue);
1241 atomic_set(&ctx->wait_vsync_event, 0);
1243 platform_set_drvdata(pdev, ctx);
1245 ret = component_add(&pdev->dev, &mixer_component_ops);
1247 pm_runtime_enable(dev);
1252 static int mixer_remove(struct platform_device *pdev)
1254 pm_runtime_disable(&pdev->dev);
1256 component_del(&pdev->dev, &mixer_component_ops);
1261 struct platform_driver mixer_driver = {
1263 .name = "exynos-mixer",
1264 .owner = THIS_MODULE,
1265 .of_match_table = mixer_match_types,
1267 .probe = mixer_probe,
1268 .remove = mixer_remove,
1269 .id_table = mixer_driver_types,