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
46 #define VP_DEFAULT_WIN 2
48 /* The pixelformats that are natively supported by the mixer. */
49 #define MXR_FORMAT_RGB565 4
50 #define MXR_FORMAT_ARGB1555 5
51 #define MXR_FORMAT_ARGB4444 6
52 #define MXR_FORMAT_ARGB8888 7
54 struct mixer_resources {
56 void __iomem *mixer_regs;
57 void __iomem *vp_regs;
62 struct clk *sclk_mixer;
63 struct clk *sclk_hdmi;
64 struct clk *mout_mixer;
67 enum mixer_version_id {
73 enum mixer_flag_bits {
78 static const uint32_t mixer_formats[] = {
86 static const uint32_t vp_formats[] = {
91 struct mixer_context {
92 struct platform_device *pdev;
94 struct drm_device *drm_dev;
95 struct exynos_drm_crtc *crtc;
96 struct exynos_drm_plane planes[MIXER_WIN_NR];
103 struct mixer_resources mixer_res;
104 enum mixer_version_id mxr_ver;
105 wait_queue_head_t wait_vsync_queue;
106 atomic_t wait_vsync_event;
109 struct mixer_drv_data {
110 enum mixer_version_id version;
115 static const u8 filter_y_horiz_tap8[] = {
116 0, -1, -1, -1, -1, -1, -1, -1,
117 -1, -1, -1, -1, -1, 0, 0, 0,
118 0, 2, 4, 5, 6, 6, 6, 6,
119 6, 5, 5, 4, 3, 2, 1, 1,
120 0, -6, -12, -16, -18, -20, -21, -20,
121 -20, -18, -16, -13, -10, -8, -5, -2,
122 127, 126, 125, 121, 114, 107, 99, 89,
123 79, 68, 57, 46, 35, 25, 16, 8,
126 static const u8 filter_y_vert_tap4[] = {
127 0, -3, -6, -8, -8, -8, -8, -7,
128 -6, -5, -4, -3, -2, -1, -1, 0,
129 127, 126, 124, 118, 111, 102, 92, 81,
130 70, 59, 48, 37, 27, 19, 11, 5,
131 0, 5, 11, 19, 27, 37, 48, 59,
132 70, 81, 92, 102, 111, 118, 124, 126,
133 0, 0, -1, -1, -2, -3, -4, -5,
134 -6, -7, -8, -8, -8, -8, -6, -3,
137 static const u8 filter_cr_horiz_tap4[] = {
138 0, -3, -6, -8, -8, -8, -8, -7,
139 -6, -5, -4, -3, -2, -1, -1, 0,
140 127, 126, 124, 118, 111, 102, 92, 81,
141 70, 59, 48, 37, 27, 19, 11, 5,
144 static inline u32 vp_reg_read(struct mixer_resources *res, u32 reg_id)
146 return readl(res->vp_regs + reg_id);
149 static inline void vp_reg_write(struct mixer_resources *res, u32 reg_id,
152 writel(val, res->vp_regs + reg_id);
155 static inline void vp_reg_writemask(struct mixer_resources *res, u32 reg_id,
158 u32 old = vp_reg_read(res, reg_id);
160 val = (val & mask) | (old & ~mask);
161 writel(val, res->vp_regs + reg_id);
164 static inline u32 mixer_reg_read(struct mixer_resources *res, u32 reg_id)
166 return readl(res->mixer_regs + reg_id);
169 static inline void mixer_reg_write(struct mixer_resources *res, u32 reg_id,
172 writel(val, res->mixer_regs + reg_id);
175 static inline void mixer_reg_writemask(struct mixer_resources *res,
176 u32 reg_id, u32 val, u32 mask)
178 u32 old = mixer_reg_read(res, reg_id);
180 val = (val & mask) | (old & ~mask);
181 writel(val, res->mixer_regs + reg_id);
184 static void mixer_regs_dump(struct mixer_context *ctx)
186 #define DUMPREG(reg_id) \
188 DRM_DEBUG_KMS(#reg_id " = %08x\n", \
189 (u32)readl(ctx->mixer_res.mixer_regs + reg_id)); \
195 DUMPREG(MXR_INT_STATUS);
197 DUMPREG(MXR_LAYER_CFG);
198 DUMPREG(MXR_VIDEO_CFG);
200 DUMPREG(MXR_GRAPHIC0_CFG);
201 DUMPREG(MXR_GRAPHIC0_BASE);
202 DUMPREG(MXR_GRAPHIC0_SPAN);
203 DUMPREG(MXR_GRAPHIC0_WH);
204 DUMPREG(MXR_GRAPHIC0_SXY);
205 DUMPREG(MXR_GRAPHIC0_DXY);
207 DUMPREG(MXR_GRAPHIC1_CFG);
208 DUMPREG(MXR_GRAPHIC1_BASE);
209 DUMPREG(MXR_GRAPHIC1_SPAN);
210 DUMPREG(MXR_GRAPHIC1_WH);
211 DUMPREG(MXR_GRAPHIC1_SXY);
212 DUMPREG(MXR_GRAPHIC1_DXY);
216 static void vp_regs_dump(struct mixer_context *ctx)
218 #define DUMPREG(reg_id) \
220 DRM_DEBUG_KMS(#reg_id " = %08x\n", \
221 (u32) readl(ctx->mixer_res.vp_regs + reg_id)); \
226 DUMPREG(VP_SHADOW_UPDATE);
227 DUMPREG(VP_FIELD_ID);
229 DUMPREG(VP_IMG_SIZE_Y);
230 DUMPREG(VP_IMG_SIZE_C);
231 DUMPREG(VP_PER_RATE_CTRL);
232 DUMPREG(VP_TOP_Y_PTR);
233 DUMPREG(VP_BOT_Y_PTR);
234 DUMPREG(VP_TOP_C_PTR);
235 DUMPREG(VP_BOT_C_PTR);
236 DUMPREG(VP_ENDIAN_MODE);
237 DUMPREG(VP_SRC_H_POSITION);
238 DUMPREG(VP_SRC_V_POSITION);
239 DUMPREG(VP_SRC_WIDTH);
240 DUMPREG(VP_SRC_HEIGHT);
241 DUMPREG(VP_DST_H_POSITION);
242 DUMPREG(VP_DST_V_POSITION);
243 DUMPREG(VP_DST_WIDTH);
244 DUMPREG(VP_DST_HEIGHT);
251 static inline void vp_filter_set(struct mixer_resources *res,
252 int reg_id, const u8 *data, unsigned int size)
254 /* assure 4-byte align */
256 for (; size; size -= 4, reg_id += 4, data += 4) {
257 u32 val = (data[0] << 24) | (data[1] << 16) |
258 (data[2] << 8) | data[3];
259 vp_reg_write(res, reg_id, val);
263 static void vp_default_filter(struct mixer_resources *res)
265 vp_filter_set(res, VP_POLY8_Y0_LL,
266 filter_y_horiz_tap8, sizeof(filter_y_horiz_tap8));
267 vp_filter_set(res, VP_POLY4_Y0_LL,
268 filter_y_vert_tap4, sizeof(filter_y_vert_tap4));
269 vp_filter_set(res, VP_POLY4_C0_LL,
270 filter_cr_horiz_tap4, sizeof(filter_cr_horiz_tap4));
273 static void mixer_vsync_set_update(struct mixer_context *ctx, bool enable)
275 struct mixer_resources *res = &ctx->mixer_res;
277 /* block update on vsync */
278 mixer_reg_writemask(res, MXR_STATUS, enable ?
279 MXR_STATUS_SYNC_ENABLE : 0, MXR_STATUS_SYNC_ENABLE);
282 vp_reg_write(res, VP_SHADOW_UPDATE, enable ?
283 VP_SHADOW_UPDATE_ENABLE : 0);
286 static void mixer_cfg_scan(struct mixer_context *ctx, unsigned int height)
288 struct mixer_resources *res = &ctx->mixer_res;
291 /* choosing between interlace and progressive mode */
292 val = (ctx->interlace ? MXR_CFG_SCAN_INTERLACE :
293 MXR_CFG_SCAN_PROGRESSIVE);
295 if (ctx->mxr_ver != MXR_VER_128_0_0_184) {
296 /* choosing between proper HD and SD mode */
298 val |= MXR_CFG_SCAN_NTSC | MXR_CFG_SCAN_SD;
299 else if (height <= 576)
300 val |= MXR_CFG_SCAN_PAL | MXR_CFG_SCAN_SD;
301 else if (height <= 720)
302 val |= MXR_CFG_SCAN_HD_720 | MXR_CFG_SCAN_HD;
303 else if (height <= 1080)
304 val |= MXR_CFG_SCAN_HD_1080 | MXR_CFG_SCAN_HD;
306 val |= MXR_CFG_SCAN_HD_720 | MXR_CFG_SCAN_HD;
309 mixer_reg_writemask(res, MXR_CFG, val, MXR_CFG_SCAN_MASK);
312 static void mixer_cfg_rgb_fmt(struct mixer_context *ctx, unsigned int height)
314 struct mixer_resources *res = &ctx->mixer_res;
318 val = MXR_CFG_RGB601_0_255;
319 } else if (height == 576) {
320 val = MXR_CFG_RGB601_0_255;
321 } else if (height == 720) {
322 val = MXR_CFG_RGB709_16_235;
323 mixer_reg_write(res, MXR_CM_COEFF_Y,
324 (1 << 30) | (94 << 20) | (314 << 10) |
326 mixer_reg_write(res, MXR_CM_COEFF_CB,
327 (972 << 20) | (851 << 10) | (225 << 0));
328 mixer_reg_write(res, MXR_CM_COEFF_CR,
329 (225 << 20) | (820 << 10) | (1004 << 0));
330 } else if (height == 1080) {
331 val = MXR_CFG_RGB709_16_235;
332 mixer_reg_write(res, MXR_CM_COEFF_Y,
333 (1 << 30) | (94 << 20) | (314 << 10) |
335 mixer_reg_write(res, MXR_CM_COEFF_CB,
336 (972 << 20) | (851 << 10) | (225 << 0));
337 mixer_reg_write(res, MXR_CM_COEFF_CR,
338 (225 << 20) | (820 << 10) | (1004 << 0));
340 val = MXR_CFG_RGB709_16_235;
341 mixer_reg_write(res, MXR_CM_COEFF_Y,
342 (1 << 30) | (94 << 20) | (314 << 10) |
344 mixer_reg_write(res, MXR_CM_COEFF_CB,
345 (972 << 20) | (851 << 10) | (225 << 0));
346 mixer_reg_write(res, MXR_CM_COEFF_CR,
347 (225 << 20) | (820 << 10) | (1004 << 0));
350 mixer_reg_writemask(res, MXR_CFG, val, MXR_CFG_RGB_FMT_MASK);
353 static void mixer_cfg_layer(struct mixer_context *ctx, unsigned int win,
356 struct mixer_resources *res = &ctx->mixer_res;
357 u32 val = enable ? ~0 : 0;
361 mixer_reg_writemask(res, MXR_CFG, val, MXR_CFG_GRP0_ENABLE);
364 mixer_reg_writemask(res, MXR_CFG, val, MXR_CFG_GRP1_ENABLE);
367 if (ctx->vp_enabled) {
368 vp_reg_writemask(res, VP_ENABLE, val, VP_ENABLE_ON);
369 mixer_reg_writemask(res, MXR_CFG, val,
372 /* control blending of graphic layer 0 */
373 mixer_reg_writemask(res, MXR_GRAPHIC_CFG(0), val,
374 MXR_GRP_CFG_BLEND_PRE_MUL |
375 MXR_GRP_CFG_PIXEL_BLEND_EN);
381 static void mixer_run(struct mixer_context *ctx)
383 struct mixer_resources *res = &ctx->mixer_res;
385 mixer_reg_writemask(res, MXR_STATUS, ~0, MXR_STATUS_REG_RUN);
388 static void mixer_stop(struct mixer_context *ctx)
390 struct mixer_resources *res = &ctx->mixer_res;
393 mixer_reg_writemask(res, MXR_STATUS, 0, MXR_STATUS_REG_RUN);
395 while (!(mixer_reg_read(res, MXR_STATUS) & MXR_STATUS_REG_IDLE) &&
397 usleep_range(10000, 12000);
400 static void vp_video_buffer(struct mixer_context *ctx,
401 struct exynos_drm_plane *plane)
403 struct mixer_resources *res = &ctx->mixer_res;
404 struct drm_plane_state *state = plane->base.state;
405 struct drm_framebuffer *fb = state->fb;
406 struct drm_display_mode *mode = &state->crtc->mode;
408 dma_addr_t luma_addr[2], chroma_addr[2];
409 bool tiled_mode = false;
410 bool crcb_mode = false;
413 switch (fb->pixel_format) {
414 case DRM_FORMAT_NV12:
417 case DRM_FORMAT_NV21:
421 DRM_ERROR("pixel format for vp is wrong [%d].\n",
426 luma_addr[0] = plane->dma_addr[0];
427 chroma_addr[0] = plane->dma_addr[1];
429 if (mode->flags & DRM_MODE_FLAG_INTERLACE) {
430 ctx->interlace = true;
432 luma_addr[1] = luma_addr[0] + 0x40;
433 chroma_addr[1] = chroma_addr[0] + 0x40;
435 luma_addr[1] = luma_addr[0] + fb->pitches[0];
436 chroma_addr[1] = chroma_addr[0] + fb->pitches[0];
439 ctx->interlace = false;
444 spin_lock_irqsave(&res->reg_slock, flags);
445 mixer_vsync_set_update(ctx, false);
447 /* interlace or progressive scan mode */
448 val = (ctx->interlace ? ~0 : 0);
449 vp_reg_writemask(res, VP_MODE, val, VP_MODE_LINE_SKIP);
452 val = (crcb_mode ? VP_MODE_NV21 : VP_MODE_NV12);
453 val |= (tiled_mode ? VP_MODE_MEM_TILED : VP_MODE_MEM_LINEAR);
454 vp_reg_writemask(res, VP_MODE, val, VP_MODE_FMT_MASK);
456 /* setting size of input image */
457 vp_reg_write(res, VP_IMG_SIZE_Y, VP_IMG_HSIZE(fb->pitches[0]) |
458 VP_IMG_VSIZE(fb->height));
459 /* chroma height has to reduced by 2 to avoid chroma distorions */
460 vp_reg_write(res, VP_IMG_SIZE_C, VP_IMG_HSIZE(fb->pitches[0]) |
461 VP_IMG_VSIZE(fb->height / 2));
463 vp_reg_write(res, VP_SRC_WIDTH, plane->src_w);
464 vp_reg_write(res, VP_SRC_HEIGHT, plane->src_h);
465 vp_reg_write(res, VP_SRC_H_POSITION,
466 VP_SRC_H_POSITION_VAL(plane->src_x));
467 vp_reg_write(res, VP_SRC_V_POSITION, plane->src_y);
469 vp_reg_write(res, VP_DST_WIDTH, plane->crtc_w);
470 vp_reg_write(res, VP_DST_H_POSITION, plane->crtc_x);
471 if (ctx->interlace) {
472 vp_reg_write(res, VP_DST_HEIGHT, plane->crtc_h / 2);
473 vp_reg_write(res, VP_DST_V_POSITION, plane->crtc_y / 2);
475 vp_reg_write(res, VP_DST_HEIGHT, plane->crtc_h);
476 vp_reg_write(res, VP_DST_V_POSITION, plane->crtc_y);
479 vp_reg_write(res, VP_H_RATIO, plane->h_ratio);
480 vp_reg_write(res, VP_V_RATIO, plane->v_ratio);
482 vp_reg_write(res, VP_ENDIAN_MODE, VP_ENDIAN_MODE_LITTLE);
484 /* set buffer address to vp */
485 vp_reg_write(res, VP_TOP_Y_PTR, luma_addr[0]);
486 vp_reg_write(res, VP_BOT_Y_PTR, luma_addr[1]);
487 vp_reg_write(res, VP_TOP_C_PTR, chroma_addr[0]);
488 vp_reg_write(res, VP_BOT_C_PTR, chroma_addr[1]);
490 mixer_cfg_scan(ctx, mode->vdisplay);
491 mixer_cfg_rgb_fmt(ctx, mode->vdisplay);
492 mixer_cfg_layer(ctx, plane->zpos, true);
495 mixer_vsync_set_update(ctx, true);
496 spin_unlock_irqrestore(&res->reg_slock, flags);
498 mixer_regs_dump(ctx);
502 static void mixer_layer_update(struct mixer_context *ctx)
504 struct mixer_resources *res = &ctx->mixer_res;
506 mixer_reg_writemask(res, MXR_CFG, ~0, MXR_CFG_LAYER_UPDATE);
509 static int mixer_setup_scale(const struct exynos_drm_plane *plane,
510 unsigned int *x_ratio, unsigned int *y_ratio)
512 if (plane->crtc_w != plane->src_w) {
513 if (plane->crtc_w == 2 * plane->src_w)
519 if (plane->crtc_h != plane->src_h) {
520 if (plane->crtc_h == 2 * plane->src_h)
529 DRM_DEBUG_KMS("only 2x width/height scaling of plane supported\n");
533 static void mixer_graph_buffer(struct mixer_context *ctx,
534 struct exynos_drm_plane *plane)
536 struct mixer_resources *res = &ctx->mixer_res;
537 struct drm_plane_state *state = plane->base.state;
538 struct drm_framebuffer *fb = state->fb;
539 struct drm_display_mode *mode = &state->crtc->mode;
541 unsigned int win = plane->zpos;
542 unsigned int x_ratio = 0, y_ratio = 0;
543 unsigned int src_x_offset, src_y_offset, dst_x_offset, dst_y_offset;
548 switch (fb->pixel_format) {
549 case DRM_FORMAT_XRGB4444:
550 fmt = MXR_FORMAT_ARGB4444;
553 case DRM_FORMAT_XRGB1555:
554 fmt = MXR_FORMAT_ARGB1555;
557 case DRM_FORMAT_RGB565:
558 fmt = MXR_FORMAT_RGB565;
561 case DRM_FORMAT_XRGB8888:
562 case DRM_FORMAT_ARGB8888:
563 fmt = MXR_FORMAT_ARGB8888;
567 DRM_DEBUG_KMS("pixelformat unsupported by mixer\n");
571 /* check if mixer supports requested scaling setup */
572 if (mixer_setup_scale(plane, &x_ratio, &y_ratio))
575 dst_x_offset = plane->crtc_x;
576 dst_y_offset = plane->crtc_y;
578 /* converting dma address base and source offset */
579 dma_addr = plane->dma_addr[0]
580 + (plane->src_x * fb->bits_per_pixel >> 3)
581 + (plane->src_y * fb->pitches[0]);
585 if (mode->flags & DRM_MODE_FLAG_INTERLACE)
586 ctx->interlace = true;
588 ctx->interlace = false;
590 spin_lock_irqsave(&res->reg_slock, flags);
591 mixer_vsync_set_update(ctx, false);
594 mixer_reg_writemask(res, MXR_GRAPHIC_CFG(win),
595 MXR_GRP_CFG_FORMAT_VAL(fmt), MXR_GRP_CFG_FORMAT_MASK);
598 mixer_reg_write(res, MXR_GRAPHIC_SPAN(win),
599 fb->pitches[0] / (fb->bits_per_pixel >> 3));
601 /* setup display size */
602 if (ctx->mxr_ver == MXR_VER_128_0_0_184 &&
603 win == MIXER_DEFAULT_WIN) {
604 val = MXR_MXR_RES_HEIGHT(mode->vdisplay);
605 val |= MXR_MXR_RES_WIDTH(mode->hdisplay);
606 mixer_reg_write(res, MXR_RESOLUTION, val);
609 val = MXR_GRP_WH_WIDTH(plane->src_w);
610 val |= MXR_GRP_WH_HEIGHT(plane->src_h);
611 val |= MXR_GRP_WH_H_SCALE(x_ratio);
612 val |= MXR_GRP_WH_V_SCALE(y_ratio);
613 mixer_reg_write(res, MXR_GRAPHIC_WH(win), val);
615 /* setup offsets in source image */
616 val = MXR_GRP_SXY_SX(src_x_offset);
617 val |= MXR_GRP_SXY_SY(src_y_offset);
618 mixer_reg_write(res, MXR_GRAPHIC_SXY(win), val);
620 /* setup offsets in display image */
621 val = MXR_GRP_DXY_DX(dst_x_offset);
622 val |= MXR_GRP_DXY_DY(dst_y_offset);
623 mixer_reg_write(res, MXR_GRAPHIC_DXY(win), val);
625 /* set buffer address to mixer */
626 mixer_reg_write(res, MXR_GRAPHIC_BASE(win), dma_addr);
628 mixer_cfg_scan(ctx, mode->vdisplay);
629 mixer_cfg_rgb_fmt(ctx, mode->vdisplay);
630 mixer_cfg_layer(ctx, win, true);
632 /* layer update mandatory for mixer 16.0.33.0 */
633 if (ctx->mxr_ver == MXR_VER_16_0_33_0 ||
634 ctx->mxr_ver == MXR_VER_128_0_0_184)
635 mixer_layer_update(ctx);
639 mixer_vsync_set_update(ctx, true);
640 spin_unlock_irqrestore(&res->reg_slock, flags);
642 mixer_regs_dump(ctx);
645 static void vp_win_reset(struct mixer_context *ctx)
647 struct mixer_resources *res = &ctx->mixer_res;
650 vp_reg_write(res, VP_SRESET, VP_SRESET_PROCESSING);
651 for (tries = 100; tries; --tries) {
652 /* waiting until VP_SRESET_PROCESSING is 0 */
653 if (~vp_reg_read(res, VP_SRESET) & VP_SRESET_PROCESSING)
655 usleep_range(10000, 12000);
657 WARN(tries == 0, "failed to reset Video Processor\n");
660 static void mixer_win_reset(struct mixer_context *ctx)
662 struct mixer_resources *res = &ctx->mixer_res;
664 u32 val; /* value stored to register */
666 spin_lock_irqsave(&res->reg_slock, flags);
667 mixer_vsync_set_update(ctx, false);
669 mixer_reg_writemask(res, MXR_CFG, MXR_CFG_DST_HDMI, MXR_CFG_DST_MASK);
671 /* set output in RGB888 mode */
672 mixer_reg_writemask(res, MXR_CFG, MXR_CFG_OUT_RGB888, MXR_CFG_OUT_MASK);
674 /* 16 beat burst in DMA */
675 mixer_reg_writemask(res, MXR_STATUS, MXR_STATUS_16_BURST,
676 MXR_STATUS_BURST_MASK);
678 /* setting default layer priority: layer1 > layer0 > video
679 * because typical usage scenario would be
681 * layer0 - framebuffer
682 * video - video overlay
684 val = MXR_LAYER_CFG_GRP1_VAL(3);
685 val |= MXR_LAYER_CFG_GRP0_VAL(2);
687 val |= MXR_LAYER_CFG_VP_VAL(1);
688 mixer_reg_write(res, MXR_LAYER_CFG, val);
690 /* setting background color */
691 mixer_reg_write(res, MXR_BG_COLOR0, 0x008080);
692 mixer_reg_write(res, MXR_BG_COLOR1, 0x008080);
693 mixer_reg_write(res, MXR_BG_COLOR2, 0x008080);
695 /* setting graphical layers */
696 val = MXR_GRP_CFG_COLOR_KEY_DISABLE; /* no blank key */
697 val |= MXR_GRP_CFG_WIN_BLEND_EN;
698 val |= MXR_GRP_CFG_ALPHA_VAL(0xff); /* non-transparent alpha */
700 /* Don't blend layer 0 onto the mixer background */
701 mixer_reg_write(res, MXR_GRAPHIC_CFG(0), val);
703 /* Blend layer 1 into layer 0 */
704 val |= MXR_GRP_CFG_BLEND_PRE_MUL;
705 val |= MXR_GRP_CFG_PIXEL_BLEND_EN;
706 mixer_reg_write(res, MXR_GRAPHIC_CFG(1), val);
708 /* setting video layers */
709 val = MXR_GRP_CFG_ALPHA_VAL(0);
710 mixer_reg_write(res, MXR_VIDEO_CFG, val);
712 if (ctx->vp_enabled) {
713 /* configuration of Video Processor Registers */
715 vp_default_filter(res);
718 /* disable all layers */
719 mixer_reg_writemask(res, MXR_CFG, 0, MXR_CFG_GRP0_ENABLE);
720 mixer_reg_writemask(res, MXR_CFG, 0, MXR_CFG_GRP1_ENABLE);
722 mixer_reg_writemask(res, MXR_CFG, 0, MXR_CFG_VP_ENABLE);
724 mixer_vsync_set_update(ctx, true);
725 spin_unlock_irqrestore(&res->reg_slock, flags);
728 static irqreturn_t mixer_irq_handler(int irq, void *arg)
730 struct mixer_context *ctx = arg;
731 struct mixer_resources *res = &ctx->mixer_res;
732 u32 val, base, shadow;
735 spin_lock(&res->reg_slock);
737 /* read interrupt status for handling and clearing flags for VSYNC */
738 val = mixer_reg_read(res, MXR_INT_STATUS);
741 if (val & MXR_INT_STATUS_VSYNC) {
742 /* vsync interrupt use different bit for read and clear */
743 val |= MXR_INT_CLEAR_VSYNC;
744 val &= ~MXR_INT_STATUS_VSYNC;
746 /* interlace scan need to check shadow register */
747 if (ctx->interlace) {
748 base = mixer_reg_read(res, MXR_GRAPHIC_BASE(0));
749 shadow = mixer_reg_read(res, MXR_GRAPHIC_BASE_S(0));
753 base = mixer_reg_read(res, MXR_GRAPHIC_BASE(1));
754 shadow = mixer_reg_read(res, MXR_GRAPHIC_BASE_S(1));
759 drm_crtc_handle_vblank(&ctx->crtc->base);
760 for (win = 0 ; win < MIXER_WIN_NR ; win++) {
761 struct exynos_drm_plane *plane = &ctx->planes[win];
763 if (!plane->pending_fb)
766 exynos_drm_crtc_finish_update(ctx->crtc, plane);
769 /* set wait vsync event to zero and wake up queue. */
770 if (atomic_read(&ctx->wait_vsync_event)) {
771 atomic_set(&ctx->wait_vsync_event, 0);
772 wake_up(&ctx->wait_vsync_queue);
777 /* clear interrupts */
778 mixer_reg_write(res, MXR_INT_STATUS, val);
780 spin_unlock(&res->reg_slock);
785 static int mixer_resources_init(struct mixer_context *mixer_ctx)
787 struct device *dev = &mixer_ctx->pdev->dev;
788 struct mixer_resources *mixer_res = &mixer_ctx->mixer_res;
789 struct resource *res;
792 spin_lock_init(&mixer_res->reg_slock);
794 mixer_res->mixer = devm_clk_get(dev, "mixer");
795 if (IS_ERR(mixer_res->mixer)) {
796 dev_err(dev, "failed to get clock 'mixer'\n");
800 mixer_res->hdmi = devm_clk_get(dev, "hdmi");
801 if (IS_ERR(mixer_res->hdmi)) {
802 dev_err(dev, "failed to get clock 'hdmi'\n");
803 return PTR_ERR(mixer_res->hdmi);
806 mixer_res->sclk_hdmi = devm_clk_get(dev, "sclk_hdmi");
807 if (IS_ERR(mixer_res->sclk_hdmi)) {
808 dev_err(dev, "failed to get clock 'sclk_hdmi'\n");
811 res = platform_get_resource(mixer_ctx->pdev, IORESOURCE_MEM, 0);
813 dev_err(dev, "get memory resource failed.\n");
817 mixer_res->mixer_regs = devm_ioremap(dev, res->start,
819 if (mixer_res->mixer_regs == NULL) {
820 dev_err(dev, "register mapping failed.\n");
824 res = platform_get_resource(mixer_ctx->pdev, IORESOURCE_IRQ, 0);
826 dev_err(dev, "get interrupt resource failed.\n");
830 ret = devm_request_irq(dev, res->start, mixer_irq_handler,
831 0, "drm_mixer", mixer_ctx);
833 dev_err(dev, "request interrupt failed.\n");
836 mixer_res->irq = res->start;
841 static int vp_resources_init(struct mixer_context *mixer_ctx)
843 struct device *dev = &mixer_ctx->pdev->dev;
844 struct mixer_resources *mixer_res = &mixer_ctx->mixer_res;
845 struct resource *res;
847 mixer_res->vp = devm_clk_get(dev, "vp");
848 if (IS_ERR(mixer_res->vp)) {
849 dev_err(dev, "failed to get clock 'vp'\n");
853 if (mixer_ctx->has_sclk) {
854 mixer_res->sclk_mixer = devm_clk_get(dev, "sclk_mixer");
855 if (IS_ERR(mixer_res->sclk_mixer)) {
856 dev_err(dev, "failed to get clock 'sclk_mixer'\n");
859 mixer_res->mout_mixer = devm_clk_get(dev, "mout_mixer");
860 if (IS_ERR(mixer_res->mout_mixer)) {
861 dev_err(dev, "failed to get clock 'mout_mixer'\n");
865 if (mixer_res->sclk_hdmi && mixer_res->mout_mixer)
866 clk_set_parent(mixer_res->mout_mixer,
867 mixer_res->sclk_hdmi);
870 res = platform_get_resource(mixer_ctx->pdev, IORESOURCE_MEM, 1);
872 dev_err(dev, "get memory resource failed.\n");
876 mixer_res->vp_regs = devm_ioremap(dev, res->start,
878 if (mixer_res->vp_regs == NULL) {
879 dev_err(dev, "register mapping failed.\n");
886 static int mixer_initialize(struct mixer_context *mixer_ctx,
887 struct drm_device *drm_dev)
890 struct exynos_drm_private *priv;
891 priv = drm_dev->dev_private;
893 mixer_ctx->drm_dev = drm_dev;
894 mixer_ctx->pipe = priv->pipe++;
896 /* acquire resources: regs, irqs, clocks */
897 ret = mixer_resources_init(mixer_ctx);
899 DRM_ERROR("mixer_resources_init failed ret=%d\n", ret);
903 if (mixer_ctx->vp_enabled) {
904 /* acquire vp resources: regs, irqs, clocks */
905 ret = vp_resources_init(mixer_ctx);
907 DRM_ERROR("vp_resources_init failed ret=%d\n", ret);
912 ret = drm_iommu_attach_device(drm_dev, mixer_ctx->dev);
919 static void mixer_ctx_remove(struct mixer_context *mixer_ctx)
921 drm_iommu_detach_device(mixer_ctx->drm_dev, mixer_ctx->dev);
924 static int mixer_enable_vblank(struct exynos_drm_crtc *crtc)
926 struct mixer_context *mixer_ctx = crtc->ctx;
927 struct mixer_resources *res = &mixer_ctx->mixer_res;
929 __set_bit(MXR_BIT_VSYNC, &mixer_ctx->flags);
930 if (!test_bit(MXR_BIT_POWERED, &mixer_ctx->flags))
933 /* enable vsync interrupt */
934 mixer_reg_writemask(res, MXR_INT_STATUS, ~0, MXR_INT_CLEAR_VSYNC);
935 mixer_reg_writemask(res, MXR_INT_EN, ~0, MXR_INT_EN_VSYNC);
940 static void mixer_disable_vblank(struct exynos_drm_crtc *crtc)
942 struct mixer_context *mixer_ctx = crtc->ctx;
943 struct mixer_resources *res = &mixer_ctx->mixer_res;
945 __clear_bit(MXR_BIT_VSYNC, &mixer_ctx->flags);
947 if (!test_bit(MXR_BIT_POWERED, &mixer_ctx->flags))
950 /* disable vsync interrupt */
951 mixer_reg_writemask(res, MXR_INT_STATUS, ~0, MXR_INT_CLEAR_VSYNC);
952 mixer_reg_writemask(res, MXR_INT_EN, 0, MXR_INT_EN_VSYNC);
955 static void mixer_update_plane(struct exynos_drm_crtc *crtc,
956 struct exynos_drm_plane *plane)
958 struct mixer_context *mixer_ctx = crtc->ctx;
960 DRM_DEBUG_KMS("win: %d\n", plane->zpos);
962 if (!test_bit(MXR_BIT_POWERED, &mixer_ctx->flags))
965 if (plane->zpos > 1 && mixer_ctx->vp_enabled)
966 vp_video_buffer(mixer_ctx, plane);
968 mixer_graph_buffer(mixer_ctx, plane);
971 static void mixer_disable_plane(struct exynos_drm_crtc *crtc,
972 struct exynos_drm_plane *plane)
974 struct mixer_context *mixer_ctx = crtc->ctx;
975 struct mixer_resources *res = &mixer_ctx->mixer_res;
978 DRM_DEBUG_KMS("win: %d\n", plane->zpos);
980 if (!test_bit(MXR_BIT_POWERED, &mixer_ctx->flags))
983 spin_lock_irqsave(&res->reg_slock, flags);
984 mixer_vsync_set_update(mixer_ctx, false);
986 mixer_cfg_layer(mixer_ctx, plane->zpos, false);
988 mixer_vsync_set_update(mixer_ctx, true);
989 spin_unlock_irqrestore(&res->reg_slock, flags);
992 static void mixer_wait_for_vblank(struct exynos_drm_crtc *crtc)
994 struct mixer_context *mixer_ctx = crtc->ctx;
997 if (!test_bit(MXR_BIT_POWERED, &mixer_ctx->flags))
1000 err = drm_vblank_get(mixer_ctx->drm_dev, mixer_ctx->pipe);
1002 DRM_DEBUG_KMS("failed to acquire vblank counter\n");
1006 atomic_set(&mixer_ctx->wait_vsync_event, 1);
1009 * wait for MIXER to signal VSYNC interrupt or return after
1010 * timeout which is set to 50ms (refresh rate of 20).
1012 if (!wait_event_timeout(mixer_ctx->wait_vsync_queue,
1013 !atomic_read(&mixer_ctx->wait_vsync_event),
1015 DRM_DEBUG_KMS("vblank wait timed out.\n");
1017 drm_vblank_put(mixer_ctx->drm_dev, mixer_ctx->pipe);
1020 static void mixer_enable(struct exynos_drm_crtc *crtc)
1022 struct mixer_context *ctx = crtc->ctx;
1023 struct mixer_resources *res = &ctx->mixer_res;
1026 if (test_bit(MXR_BIT_POWERED, &ctx->flags))
1029 pm_runtime_get_sync(ctx->dev);
1031 ret = clk_prepare_enable(res->mixer);
1033 DRM_ERROR("Failed to prepare_enable the mixer clk [%d]\n", ret);
1036 ret = clk_prepare_enable(res->hdmi);
1038 DRM_ERROR("Failed to prepare_enable the hdmi clk [%d]\n", ret);
1041 if (ctx->vp_enabled) {
1042 ret = clk_prepare_enable(res->vp);
1044 DRM_ERROR("Failed to prepare_enable the vp clk [%d]\n",
1048 if (ctx->has_sclk) {
1049 ret = clk_prepare_enable(res->sclk_mixer);
1051 DRM_ERROR("Failed to prepare_enable the " \
1052 "sclk_mixer clk [%d]\n",
1059 set_bit(MXR_BIT_POWERED, &ctx->flags);
1061 mixer_reg_writemask(res, MXR_STATUS, ~0, MXR_STATUS_SOFT_RESET);
1063 if (test_bit(MXR_BIT_VSYNC, &ctx->flags)) {
1064 mixer_reg_writemask(res, MXR_INT_STATUS, ~0, MXR_INT_CLEAR_VSYNC);
1065 mixer_reg_writemask(res, MXR_INT_EN, ~0, MXR_INT_EN_VSYNC);
1067 mixer_win_reset(ctx);
1070 static void mixer_disable(struct exynos_drm_crtc *crtc)
1072 struct mixer_context *ctx = crtc->ctx;
1073 struct mixer_resources *res = &ctx->mixer_res;
1076 if (!test_bit(MXR_BIT_POWERED, &ctx->flags))
1080 mixer_regs_dump(ctx);
1082 for (i = 0; i < MIXER_WIN_NR; i++)
1083 mixer_disable_plane(crtc, &ctx->planes[i]);
1085 clear_bit(MXR_BIT_POWERED, &ctx->flags);
1087 clk_disable_unprepare(res->hdmi);
1088 clk_disable_unprepare(res->mixer);
1089 if (ctx->vp_enabled) {
1090 clk_disable_unprepare(res->vp);
1092 clk_disable_unprepare(res->sclk_mixer);
1095 pm_runtime_put_sync(ctx->dev);
1098 /* Only valid for Mixer version 16.0.33.0 */
1099 int mixer_check_mode(struct drm_display_mode *mode)
1106 DRM_DEBUG_KMS("xres=%d, yres=%d, refresh=%d, intl=%d\n",
1107 mode->hdisplay, mode->vdisplay, mode->vrefresh,
1108 (mode->flags & DRM_MODE_FLAG_INTERLACE) ? 1 : 0);
1110 if ((w >= 464 && w <= 720 && h >= 261 && h <= 576) ||
1111 (w >= 1024 && w <= 1280 && h >= 576 && h <= 720) ||
1112 (w >= 1664 && w <= 1920 && h >= 936 && h <= 1080))
1118 static const struct exynos_drm_crtc_ops mixer_crtc_ops = {
1119 .enable = mixer_enable,
1120 .disable = mixer_disable,
1121 .enable_vblank = mixer_enable_vblank,
1122 .disable_vblank = mixer_disable_vblank,
1123 .wait_for_vblank = mixer_wait_for_vblank,
1124 .update_plane = mixer_update_plane,
1125 .disable_plane = mixer_disable_plane,
1128 static struct mixer_drv_data exynos5420_mxr_drv_data = {
1129 .version = MXR_VER_128_0_0_184,
1133 static struct mixer_drv_data exynos5250_mxr_drv_data = {
1134 .version = MXR_VER_16_0_33_0,
1138 static struct mixer_drv_data exynos4212_mxr_drv_data = {
1139 .version = MXR_VER_0_0_0_16,
1143 static struct mixer_drv_data exynos4210_mxr_drv_data = {
1144 .version = MXR_VER_0_0_0_16,
1149 static const struct platform_device_id mixer_driver_types[] = {
1151 .name = "s5p-mixer",
1152 .driver_data = (unsigned long)&exynos4210_mxr_drv_data,
1154 .name = "exynos5-mixer",
1155 .driver_data = (unsigned long)&exynos5250_mxr_drv_data,
1161 static struct of_device_id mixer_match_types[] = {
1163 .compatible = "samsung,exynos4210-mixer",
1164 .data = &exynos4210_mxr_drv_data,
1166 .compatible = "samsung,exynos4212-mixer",
1167 .data = &exynos4212_mxr_drv_data,
1169 .compatible = "samsung,exynos5-mixer",
1170 .data = &exynos5250_mxr_drv_data,
1172 .compatible = "samsung,exynos5250-mixer",
1173 .data = &exynos5250_mxr_drv_data,
1175 .compatible = "samsung,exynos5420-mixer",
1176 .data = &exynos5420_mxr_drv_data,
1181 MODULE_DEVICE_TABLE(of, mixer_match_types);
1183 static int mixer_bind(struct device *dev, struct device *manager, void *data)
1185 struct mixer_context *ctx = dev_get_drvdata(dev);
1186 struct drm_device *drm_dev = data;
1187 struct exynos_drm_plane *exynos_plane;
1191 ret = mixer_initialize(ctx, drm_dev);
1195 for (zpos = 0; zpos < MIXER_WIN_NR; zpos++) {
1196 enum drm_plane_type type;
1197 const uint32_t *formats;
1198 unsigned int fcount;
1200 type = (zpos == MIXER_DEFAULT_WIN) ? DRM_PLANE_TYPE_PRIMARY :
1201 DRM_PLANE_TYPE_OVERLAY;
1202 if (zpos < VP_DEFAULT_WIN) {
1203 formats = mixer_formats;
1204 fcount = ARRAY_SIZE(mixer_formats);
1206 formats = vp_formats;
1207 fcount = ARRAY_SIZE(vp_formats);
1210 ret = exynos_plane_init(drm_dev, &ctx->planes[zpos],
1211 1 << ctx->pipe, type, formats, fcount,
1217 exynos_plane = &ctx->planes[MIXER_DEFAULT_WIN];
1218 ctx->crtc = exynos_drm_crtc_create(drm_dev, &exynos_plane->base,
1219 ctx->pipe, EXYNOS_DISPLAY_TYPE_HDMI,
1220 &mixer_crtc_ops, ctx);
1221 if (IS_ERR(ctx->crtc)) {
1222 mixer_ctx_remove(ctx);
1223 ret = PTR_ERR(ctx->crtc);
1230 devm_kfree(dev, ctx);
1234 static void mixer_unbind(struct device *dev, struct device *master, void *data)
1236 struct mixer_context *ctx = dev_get_drvdata(dev);
1238 mixer_ctx_remove(ctx);
1241 static const struct component_ops mixer_component_ops = {
1243 .unbind = mixer_unbind,
1246 static int mixer_probe(struct platform_device *pdev)
1248 struct device *dev = &pdev->dev;
1249 struct mixer_drv_data *drv;
1250 struct mixer_context *ctx;
1253 ctx = devm_kzalloc(&pdev->dev, sizeof(*ctx), GFP_KERNEL);
1255 DRM_ERROR("failed to alloc mixer context.\n");
1260 const struct of_device_id *match;
1262 match = of_match_node(mixer_match_types, dev->of_node);
1263 drv = (struct mixer_drv_data *)match->data;
1265 drv = (struct mixer_drv_data *)
1266 platform_get_device_id(pdev)->driver_data;
1271 ctx->vp_enabled = drv->is_vp_enabled;
1272 ctx->has_sclk = drv->has_sclk;
1273 ctx->mxr_ver = drv->version;
1274 init_waitqueue_head(&ctx->wait_vsync_queue);
1275 atomic_set(&ctx->wait_vsync_event, 0);
1277 platform_set_drvdata(pdev, ctx);
1279 ret = component_add(&pdev->dev, &mixer_component_ops);
1281 pm_runtime_enable(dev);
1286 static int mixer_remove(struct platform_device *pdev)
1288 pm_runtime_disable(&pdev->dev);
1290 component_del(&pdev->dev, &mixer_component_ops);
1295 struct platform_driver mixer_driver = {
1297 .name = "exynos-mixer",
1298 .owner = THIS_MODULE,
1299 .of_match_table = mixer_match_types,
1301 .probe = mixer_probe,
1302 .remove = mixer_remove,
1303 .id_table = mixer_driver_types,