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 {
76 struct mixer_context {
77 struct platform_device *pdev;
79 struct drm_device *drm_dev;
80 struct exynos_drm_crtc *crtc;
81 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, unsigned int win)
388 struct mixer_resources *res = &ctx->mixer_res;
390 struct exynos_drm_plane *plane;
391 dma_addr_t luma_addr[2], chroma_addr[2];
392 bool tiled_mode = false;
393 bool crcb_mode = false;
396 plane = &ctx->planes[win];
398 switch (plane->pixel_format) {
399 case DRM_FORMAT_NV12:
402 case DRM_FORMAT_NV21:
406 DRM_ERROR("pixel format for vp is wrong [%d].\n",
407 plane->pixel_format);
411 luma_addr[0] = plane->dma_addr[0];
412 chroma_addr[0] = plane->dma_addr[1];
414 if (plane->scan_flag & DRM_MODE_FLAG_INTERLACE) {
415 ctx->interlace = true;
417 luma_addr[1] = luma_addr[0] + 0x40;
418 chroma_addr[1] = chroma_addr[0] + 0x40;
420 luma_addr[1] = luma_addr[0] + plane->pitch;
421 chroma_addr[1] = chroma_addr[0] + plane->pitch;
424 ctx->interlace = false;
429 spin_lock_irqsave(&res->reg_slock, flags);
430 mixer_vsync_set_update(ctx, false);
432 /* interlace or progressive scan mode */
433 val = (ctx->interlace ? ~0 : 0);
434 vp_reg_writemask(res, VP_MODE, val, VP_MODE_LINE_SKIP);
437 val = (crcb_mode ? VP_MODE_NV21 : VP_MODE_NV12);
438 val |= (tiled_mode ? VP_MODE_MEM_TILED : VP_MODE_MEM_LINEAR);
439 vp_reg_writemask(res, VP_MODE, val, VP_MODE_FMT_MASK);
441 /* setting size of input image */
442 vp_reg_write(res, VP_IMG_SIZE_Y, VP_IMG_HSIZE(plane->pitch) |
443 VP_IMG_VSIZE(plane->fb_height));
444 /* chroma height has to reduced by 2 to avoid chroma distorions */
445 vp_reg_write(res, VP_IMG_SIZE_C, VP_IMG_HSIZE(plane->pitch) |
446 VP_IMG_VSIZE(plane->fb_height / 2));
448 vp_reg_write(res, VP_SRC_WIDTH, plane->src_width);
449 vp_reg_write(res, VP_SRC_HEIGHT, plane->src_height);
450 vp_reg_write(res, VP_SRC_H_POSITION,
451 VP_SRC_H_POSITION_VAL(plane->src_x));
452 vp_reg_write(res, VP_SRC_V_POSITION, plane->src_y);
454 vp_reg_write(res, VP_DST_WIDTH, plane->crtc_width);
455 vp_reg_write(res, VP_DST_H_POSITION, plane->crtc_x);
456 if (ctx->interlace) {
457 vp_reg_write(res, VP_DST_HEIGHT, plane->crtc_height / 2);
458 vp_reg_write(res, VP_DST_V_POSITION, plane->crtc_y / 2);
460 vp_reg_write(res, VP_DST_HEIGHT, plane->crtc_height);
461 vp_reg_write(res, VP_DST_V_POSITION, plane->crtc_y);
464 vp_reg_write(res, VP_H_RATIO, plane->h_ratio);
465 vp_reg_write(res, VP_V_RATIO, plane->v_ratio);
467 vp_reg_write(res, VP_ENDIAN_MODE, VP_ENDIAN_MODE_LITTLE);
469 /* set buffer address to vp */
470 vp_reg_write(res, VP_TOP_Y_PTR, luma_addr[0]);
471 vp_reg_write(res, VP_BOT_Y_PTR, luma_addr[1]);
472 vp_reg_write(res, VP_TOP_C_PTR, chroma_addr[0]);
473 vp_reg_write(res, VP_BOT_C_PTR, chroma_addr[1]);
475 mixer_cfg_scan(ctx, plane->mode_height);
476 mixer_cfg_rgb_fmt(ctx, plane->mode_height);
477 mixer_cfg_layer(ctx, win, true);
480 mixer_vsync_set_update(ctx, true);
481 spin_unlock_irqrestore(&res->reg_slock, flags);
483 mixer_regs_dump(ctx);
487 static void mixer_layer_update(struct mixer_context *ctx)
489 struct mixer_resources *res = &ctx->mixer_res;
491 mixer_reg_writemask(res, MXR_CFG, ~0, MXR_CFG_LAYER_UPDATE);
494 static int mixer_setup_scale(const struct exynos_drm_plane *plane,
495 unsigned int *x_ratio, unsigned int *y_ratio)
497 if (plane->crtc_width != plane->src_width) {
498 if (plane->crtc_width == 2 * plane->src_width)
504 if (plane->crtc_height != plane->src_height) {
505 if (plane->crtc_height == 2 * plane->src_height)
514 DRM_DEBUG_KMS("only 2x width/height scaling of plane supported\n");
518 static void mixer_graph_buffer(struct mixer_context *ctx, unsigned int win)
520 struct mixer_resources *res = &ctx->mixer_res;
522 struct exynos_drm_plane *plane;
523 unsigned int x_ratio = 0, y_ratio = 0;
524 unsigned int src_x_offset, src_y_offset, dst_x_offset, dst_y_offset;
529 plane = &ctx->planes[win];
531 switch (plane->pixel_format) {
532 case DRM_FORMAT_XRGB4444:
533 fmt = MXR_FORMAT_ARGB4444;
536 case DRM_FORMAT_XRGB1555:
537 fmt = MXR_FORMAT_ARGB1555;
540 case DRM_FORMAT_RGB565:
541 fmt = MXR_FORMAT_RGB565;
544 case DRM_FORMAT_XRGB8888:
545 case DRM_FORMAT_ARGB8888:
546 fmt = MXR_FORMAT_ARGB8888;
550 DRM_DEBUG_KMS("pixelformat unsupported by mixer\n");
554 /* check if mixer supports requested scaling setup */
555 if (mixer_setup_scale(plane, &x_ratio, &y_ratio))
558 dst_x_offset = plane->crtc_x;
559 dst_y_offset = plane->crtc_y;
561 /* converting dma address base and source offset */
562 dma_addr = plane->dma_addr[0]
563 + (plane->src_x * plane->bpp >> 3)
564 + (plane->src_y * plane->pitch);
568 if (plane->scan_flag & DRM_MODE_FLAG_INTERLACE)
569 ctx->interlace = true;
571 ctx->interlace = false;
573 spin_lock_irqsave(&res->reg_slock, flags);
574 mixer_vsync_set_update(ctx, false);
577 mixer_reg_writemask(res, MXR_GRAPHIC_CFG(win),
578 MXR_GRP_CFG_FORMAT_VAL(fmt), MXR_GRP_CFG_FORMAT_MASK);
581 mixer_reg_write(res, MXR_GRAPHIC_SPAN(win),
582 plane->pitch / (plane->bpp >> 3));
584 /* setup display size */
585 if (ctx->mxr_ver == MXR_VER_128_0_0_184 &&
586 win == MIXER_DEFAULT_WIN) {
587 val = MXR_MXR_RES_HEIGHT(plane->mode_height);
588 val |= MXR_MXR_RES_WIDTH(plane->mode_width);
589 mixer_reg_write(res, MXR_RESOLUTION, val);
592 val = MXR_GRP_WH_WIDTH(plane->src_width);
593 val |= MXR_GRP_WH_HEIGHT(plane->src_height);
594 val |= MXR_GRP_WH_H_SCALE(x_ratio);
595 val |= MXR_GRP_WH_V_SCALE(y_ratio);
596 mixer_reg_write(res, MXR_GRAPHIC_WH(win), val);
598 /* setup offsets in source image */
599 val = MXR_GRP_SXY_SX(src_x_offset);
600 val |= MXR_GRP_SXY_SY(src_y_offset);
601 mixer_reg_write(res, MXR_GRAPHIC_SXY(win), val);
603 /* setup offsets in display image */
604 val = MXR_GRP_DXY_DX(dst_x_offset);
605 val |= MXR_GRP_DXY_DY(dst_y_offset);
606 mixer_reg_write(res, MXR_GRAPHIC_DXY(win), val);
608 /* set buffer address to mixer */
609 mixer_reg_write(res, MXR_GRAPHIC_BASE(win), dma_addr);
611 mixer_cfg_scan(ctx, plane->mode_height);
612 mixer_cfg_rgb_fmt(ctx, plane->mode_height);
613 mixer_cfg_layer(ctx, win, true);
615 /* layer update mandatory for mixer 16.0.33.0 */
616 if (ctx->mxr_ver == MXR_VER_16_0_33_0 ||
617 ctx->mxr_ver == MXR_VER_128_0_0_184)
618 mixer_layer_update(ctx);
622 mixer_vsync_set_update(ctx, true);
623 spin_unlock_irqrestore(&res->reg_slock, flags);
625 mixer_regs_dump(ctx);
628 static void vp_win_reset(struct mixer_context *ctx)
630 struct mixer_resources *res = &ctx->mixer_res;
633 vp_reg_write(res, VP_SRESET, VP_SRESET_PROCESSING);
634 for (tries = 100; tries; --tries) {
635 /* waiting until VP_SRESET_PROCESSING is 0 */
636 if (~vp_reg_read(res, VP_SRESET) & VP_SRESET_PROCESSING)
638 usleep_range(10000, 12000);
640 WARN(tries == 0, "failed to reset Video Processor\n");
643 static void mixer_win_reset(struct mixer_context *ctx)
645 struct mixer_resources *res = &ctx->mixer_res;
647 u32 val; /* value stored to register */
649 spin_lock_irqsave(&res->reg_slock, flags);
650 mixer_vsync_set_update(ctx, false);
652 mixer_reg_writemask(res, MXR_CFG, MXR_CFG_DST_HDMI, MXR_CFG_DST_MASK);
654 /* set output in RGB888 mode */
655 mixer_reg_writemask(res, MXR_CFG, MXR_CFG_OUT_RGB888, MXR_CFG_OUT_MASK);
657 /* 16 beat burst in DMA */
658 mixer_reg_writemask(res, MXR_STATUS, MXR_STATUS_16_BURST,
659 MXR_STATUS_BURST_MASK);
661 /* setting default layer priority: layer1 > layer0 > video
662 * because typical usage scenario would be
664 * layer0 - framebuffer
665 * video - video overlay
667 val = MXR_LAYER_CFG_GRP1_VAL(3);
668 val |= MXR_LAYER_CFG_GRP0_VAL(2);
670 val |= MXR_LAYER_CFG_VP_VAL(1);
671 mixer_reg_write(res, MXR_LAYER_CFG, val);
673 /* setting background color */
674 mixer_reg_write(res, MXR_BG_COLOR0, 0x008080);
675 mixer_reg_write(res, MXR_BG_COLOR1, 0x008080);
676 mixer_reg_write(res, MXR_BG_COLOR2, 0x008080);
678 /* setting graphical layers */
679 val = MXR_GRP_CFG_COLOR_KEY_DISABLE; /* no blank key */
680 val |= MXR_GRP_CFG_WIN_BLEND_EN;
681 val |= MXR_GRP_CFG_ALPHA_VAL(0xff); /* non-transparent alpha */
683 /* Don't blend layer 0 onto the mixer background */
684 mixer_reg_write(res, MXR_GRAPHIC_CFG(0), val);
686 /* Blend layer 1 into layer 0 */
687 val |= MXR_GRP_CFG_BLEND_PRE_MUL;
688 val |= MXR_GRP_CFG_PIXEL_BLEND_EN;
689 mixer_reg_write(res, MXR_GRAPHIC_CFG(1), val);
691 /* setting video layers */
692 val = MXR_GRP_CFG_ALPHA_VAL(0);
693 mixer_reg_write(res, MXR_VIDEO_CFG, val);
695 if (ctx->vp_enabled) {
696 /* configuration of Video Processor Registers */
698 vp_default_filter(res);
701 /* disable all layers */
702 mixer_reg_writemask(res, MXR_CFG, 0, MXR_CFG_GRP0_ENABLE);
703 mixer_reg_writemask(res, MXR_CFG, 0, MXR_CFG_GRP1_ENABLE);
705 mixer_reg_writemask(res, MXR_CFG, 0, MXR_CFG_VP_ENABLE);
707 mixer_vsync_set_update(ctx, true);
708 spin_unlock_irqrestore(&res->reg_slock, flags);
711 static irqreturn_t mixer_irq_handler(int irq, void *arg)
713 struct mixer_context *ctx = arg;
714 struct mixer_resources *res = &ctx->mixer_res;
715 u32 val, base, shadow;
717 spin_lock(&res->reg_slock);
719 /* read interrupt status for handling and clearing flags for VSYNC */
720 val = mixer_reg_read(res, MXR_INT_STATUS);
723 if (val & MXR_INT_STATUS_VSYNC) {
724 /* vsync interrupt use different bit for read and clear */
725 val |= MXR_INT_CLEAR_VSYNC;
726 val &= ~MXR_INT_STATUS_VSYNC;
728 /* interlace scan need to check shadow register */
729 if (ctx->interlace) {
730 base = mixer_reg_read(res, MXR_GRAPHIC_BASE(0));
731 shadow = mixer_reg_read(res, MXR_GRAPHIC_BASE_S(0));
735 base = mixer_reg_read(res, MXR_GRAPHIC_BASE(1));
736 shadow = mixer_reg_read(res, MXR_GRAPHIC_BASE_S(1));
741 drm_handle_vblank(ctx->drm_dev, ctx->pipe);
742 exynos_drm_crtc_finish_pageflip(ctx->drm_dev, ctx->pipe);
744 /* set wait vsync event to zero and wake up queue. */
745 if (atomic_read(&ctx->wait_vsync_event)) {
746 atomic_set(&ctx->wait_vsync_event, 0);
747 wake_up(&ctx->wait_vsync_queue);
752 /* clear interrupts */
753 mixer_reg_write(res, MXR_INT_STATUS, val);
755 spin_unlock(&res->reg_slock);
760 static int mixer_resources_init(struct mixer_context *mixer_ctx)
762 struct device *dev = &mixer_ctx->pdev->dev;
763 struct mixer_resources *mixer_res = &mixer_ctx->mixer_res;
764 struct resource *res;
767 spin_lock_init(&mixer_res->reg_slock);
769 mixer_res->mixer = devm_clk_get(dev, "mixer");
770 if (IS_ERR(mixer_res->mixer)) {
771 dev_err(dev, "failed to get clock 'mixer'\n");
775 mixer_res->hdmi = devm_clk_get(dev, "hdmi");
776 if (IS_ERR(mixer_res->hdmi)) {
777 dev_err(dev, "failed to get clock 'hdmi'\n");
778 return PTR_ERR(mixer_res->hdmi);
781 mixer_res->sclk_hdmi = devm_clk_get(dev, "sclk_hdmi");
782 if (IS_ERR(mixer_res->sclk_hdmi)) {
783 dev_err(dev, "failed to get clock 'sclk_hdmi'\n");
786 res = platform_get_resource(mixer_ctx->pdev, IORESOURCE_MEM, 0);
788 dev_err(dev, "get memory resource failed.\n");
792 mixer_res->mixer_regs = devm_ioremap(dev, res->start,
794 if (mixer_res->mixer_regs == NULL) {
795 dev_err(dev, "register mapping failed.\n");
799 res = platform_get_resource(mixer_ctx->pdev, IORESOURCE_IRQ, 0);
801 dev_err(dev, "get interrupt resource failed.\n");
805 ret = devm_request_irq(dev, res->start, mixer_irq_handler,
806 0, "drm_mixer", mixer_ctx);
808 dev_err(dev, "request interrupt failed.\n");
811 mixer_res->irq = res->start;
816 static int vp_resources_init(struct mixer_context *mixer_ctx)
818 struct device *dev = &mixer_ctx->pdev->dev;
819 struct mixer_resources *mixer_res = &mixer_ctx->mixer_res;
820 struct resource *res;
822 mixer_res->vp = devm_clk_get(dev, "vp");
823 if (IS_ERR(mixer_res->vp)) {
824 dev_err(dev, "failed to get clock 'vp'\n");
828 if (mixer_ctx->has_sclk) {
829 mixer_res->sclk_mixer = devm_clk_get(dev, "sclk_mixer");
830 if (IS_ERR(mixer_res->sclk_mixer)) {
831 dev_err(dev, "failed to get clock 'sclk_mixer'\n");
834 mixer_res->mout_mixer = devm_clk_get(dev, "mout_mixer");
835 if (IS_ERR(mixer_res->mout_mixer)) {
836 dev_err(dev, "failed to get clock 'mout_mixer'\n");
840 if (mixer_res->sclk_hdmi && mixer_res->mout_mixer)
841 clk_set_parent(mixer_res->mout_mixer,
842 mixer_res->sclk_hdmi);
845 res = platform_get_resource(mixer_ctx->pdev, IORESOURCE_MEM, 1);
847 dev_err(dev, "get memory resource failed.\n");
851 mixer_res->vp_regs = devm_ioremap(dev, res->start,
853 if (mixer_res->vp_regs == NULL) {
854 dev_err(dev, "register mapping failed.\n");
861 static int mixer_initialize(struct mixer_context *mixer_ctx,
862 struct drm_device *drm_dev)
865 struct exynos_drm_private *priv;
866 priv = drm_dev->dev_private;
868 mixer_ctx->drm_dev = drm_dev;
869 mixer_ctx->pipe = priv->pipe++;
871 /* acquire resources: regs, irqs, clocks */
872 ret = mixer_resources_init(mixer_ctx);
874 DRM_ERROR("mixer_resources_init failed ret=%d\n", ret);
878 if (mixer_ctx->vp_enabled) {
879 /* acquire vp resources: regs, irqs, clocks */
880 ret = vp_resources_init(mixer_ctx);
882 DRM_ERROR("vp_resources_init failed ret=%d\n", ret);
887 ret = drm_iommu_attach_device_if_possible(mixer_ctx->crtc, drm_dev,
895 static void mixer_ctx_remove(struct mixer_context *mixer_ctx)
897 drm_iommu_detach_device(mixer_ctx->drm_dev, mixer_ctx->dev);
900 static int mixer_enable_vblank(struct exynos_drm_crtc *crtc)
902 struct mixer_context *mixer_ctx = crtc->ctx;
903 struct mixer_resources *res = &mixer_ctx->mixer_res;
905 if (!test_bit(MXR_BIT_POWERED, &mixer_ctx->flags)) {
906 mixer_ctx->int_en |= MXR_INT_EN_VSYNC;
910 /* enable vsync interrupt */
911 mixer_reg_writemask(res, MXR_INT_STATUS, ~0, MXR_INT_CLEAR_VSYNC);
912 mixer_reg_writemask(res, MXR_INT_EN, ~0, MXR_INT_EN_VSYNC);
917 static void mixer_disable_vblank(struct exynos_drm_crtc *crtc)
919 struct mixer_context *mixer_ctx = crtc->ctx;
920 struct mixer_resources *res = &mixer_ctx->mixer_res;
922 if (!test_bit(MXR_BIT_POWERED, &mixer_ctx->flags)) {
923 mixer_ctx->int_en &= MXR_INT_EN_VSYNC;
927 /* disable vsync interrupt */
928 mixer_reg_writemask(res, MXR_INT_STATUS, ~0, MXR_INT_CLEAR_VSYNC);
929 mixer_reg_writemask(res, MXR_INT_EN, 0, MXR_INT_EN_VSYNC);
932 static void mixer_win_commit(struct exynos_drm_crtc *crtc, unsigned int win)
934 struct mixer_context *mixer_ctx = crtc->ctx;
936 DRM_DEBUG_KMS("win: %d\n", win);
938 if (!test_bit(MXR_BIT_POWERED, &mixer_ctx->flags))
941 if (win > 1 && mixer_ctx->vp_enabled)
942 vp_video_buffer(mixer_ctx, win);
944 mixer_graph_buffer(mixer_ctx, win);
947 static void mixer_win_disable(struct exynos_drm_crtc *crtc, unsigned int win)
949 struct mixer_context *mixer_ctx = crtc->ctx;
950 struct mixer_resources *res = &mixer_ctx->mixer_res;
953 DRM_DEBUG_KMS("win: %d\n", win);
955 if (!test_bit(MXR_BIT_POWERED, &mixer_ctx->flags))
958 spin_lock_irqsave(&res->reg_slock, flags);
959 mixer_vsync_set_update(mixer_ctx, false);
961 mixer_cfg_layer(mixer_ctx, win, false);
963 mixer_vsync_set_update(mixer_ctx, true);
964 spin_unlock_irqrestore(&res->reg_slock, flags);
967 static void mixer_wait_for_vblank(struct exynos_drm_crtc *crtc)
969 struct mixer_context *mixer_ctx = crtc->ctx;
972 if (!test_bit(MXR_BIT_POWERED, &mixer_ctx->flags))
975 err = drm_vblank_get(mixer_ctx->drm_dev, mixer_ctx->pipe);
977 DRM_DEBUG_KMS("failed to acquire vblank counter\n");
981 atomic_set(&mixer_ctx->wait_vsync_event, 1);
984 * wait for MIXER to signal VSYNC interrupt or return after
985 * timeout which is set to 50ms (refresh rate of 20).
987 if (!wait_event_timeout(mixer_ctx->wait_vsync_queue,
988 !atomic_read(&mixer_ctx->wait_vsync_event),
990 DRM_DEBUG_KMS("vblank wait timed out.\n");
992 drm_vblank_put(mixer_ctx->drm_dev, mixer_ctx->pipe);
995 static void mixer_enable(struct exynos_drm_crtc *crtc)
997 struct mixer_context *ctx = crtc->ctx;
998 struct mixer_resources *res = &ctx->mixer_res;
1001 if (test_bit(MXR_BIT_POWERED, &ctx->flags))
1004 pm_runtime_get_sync(ctx->dev);
1006 ret = clk_prepare_enable(res->mixer);
1008 DRM_ERROR("Failed to prepare_enable the mixer clk [%d]\n", ret);
1011 ret = clk_prepare_enable(res->hdmi);
1013 DRM_ERROR("Failed to prepare_enable the hdmi clk [%d]\n", ret);
1016 if (ctx->vp_enabled) {
1017 ret = clk_prepare_enable(res->vp);
1019 DRM_ERROR("Failed to prepare_enable the vp clk [%d]\n",
1023 if (ctx->has_sclk) {
1024 ret = clk_prepare_enable(res->sclk_mixer);
1026 DRM_ERROR("Failed to prepare_enable the " \
1027 "sclk_mixer clk [%d]\n",
1034 set_bit(MXR_BIT_POWERED, &ctx->flags);
1036 mixer_reg_writemask(res, MXR_STATUS, ~0, MXR_STATUS_SOFT_RESET);
1038 if (ctx->int_en & MXR_INT_EN_VSYNC)
1039 mixer_reg_writemask(res, MXR_INT_STATUS, ~0, MXR_INT_CLEAR_VSYNC);
1040 mixer_reg_write(res, MXR_INT_EN, ctx->int_en);
1041 mixer_win_reset(ctx);
1044 static void mixer_disable(struct exynos_drm_crtc *crtc)
1046 struct mixer_context *ctx = crtc->ctx;
1047 struct mixer_resources *res = &ctx->mixer_res;
1050 if (!test_bit(MXR_BIT_POWERED, &ctx->flags))
1054 mixer_regs_dump(ctx);
1056 for (i = 0; i < MIXER_WIN_NR; i++)
1057 mixer_win_disable(crtc, i);
1059 ctx->int_en = mixer_reg_read(res, MXR_INT_EN);
1061 clear_bit(MXR_BIT_POWERED, &ctx->flags);
1063 clk_disable_unprepare(res->hdmi);
1064 clk_disable_unprepare(res->mixer);
1065 if (ctx->vp_enabled) {
1066 clk_disable_unprepare(res->vp);
1068 clk_disable_unprepare(res->sclk_mixer);
1071 pm_runtime_put_sync(ctx->dev);
1074 /* Only valid for Mixer version 16.0.33.0 */
1075 int mixer_check_mode(struct drm_display_mode *mode)
1082 DRM_DEBUG_KMS("xres=%d, yres=%d, refresh=%d, intl=%d\n",
1083 mode->hdisplay, mode->vdisplay, mode->vrefresh,
1084 (mode->flags & DRM_MODE_FLAG_INTERLACE) ? 1 : 0);
1086 if ((w >= 464 && w <= 720 && h >= 261 && h <= 576) ||
1087 (w >= 1024 && w <= 1280 && h >= 576 && h <= 720) ||
1088 (w >= 1664 && w <= 1920 && h >= 936 && h <= 1080))
1094 static const struct exynos_drm_crtc_ops mixer_crtc_ops = {
1095 .enable = mixer_enable,
1096 .disable = mixer_disable,
1097 .enable_vblank = mixer_enable_vblank,
1098 .disable_vblank = mixer_disable_vblank,
1099 .wait_for_vblank = mixer_wait_for_vblank,
1100 .win_commit = mixer_win_commit,
1101 .win_disable = mixer_win_disable,
1104 static struct mixer_drv_data exynos5420_mxr_drv_data = {
1105 .version = MXR_VER_128_0_0_184,
1109 static struct mixer_drv_data exynos5250_mxr_drv_data = {
1110 .version = MXR_VER_16_0_33_0,
1114 static struct mixer_drv_data exynos4212_mxr_drv_data = {
1115 .version = MXR_VER_0_0_0_16,
1119 static struct mixer_drv_data exynos4210_mxr_drv_data = {
1120 .version = MXR_VER_0_0_0_16,
1125 static const struct platform_device_id mixer_driver_types[] = {
1127 .name = "s5p-mixer",
1128 .driver_data = (unsigned long)&exynos4210_mxr_drv_data,
1130 .name = "exynos5-mixer",
1131 .driver_data = (unsigned long)&exynos5250_mxr_drv_data,
1137 static struct of_device_id mixer_match_types[] = {
1139 .compatible = "samsung,exynos4210-mixer",
1140 .data = &exynos4210_mxr_drv_data,
1142 .compatible = "samsung,exynos4212-mixer",
1143 .data = &exynos4212_mxr_drv_data,
1145 .compatible = "samsung,exynos5-mixer",
1146 .data = &exynos5250_mxr_drv_data,
1148 .compatible = "samsung,exynos5250-mixer",
1149 .data = &exynos5250_mxr_drv_data,
1151 .compatible = "samsung,exynos5420-mixer",
1152 .data = &exynos5420_mxr_drv_data,
1157 MODULE_DEVICE_TABLE(of, mixer_match_types);
1159 static int mixer_bind(struct device *dev, struct device *manager, void *data)
1161 struct mixer_context *ctx = dev_get_drvdata(dev);
1162 struct drm_device *drm_dev = data;
1163 struct exynos_drm_plane *exynos_plane;
1164 enum drm_plane_type type;
1168 ret = mixer_initialize(ctx, drm_dev);
1172 for (zpos = 0; zpos < MIXER_WIN_NR; zpos++) {
1173 type = (zpos == MIXER_DEFAULT_WIN) ? DRM_PLANE_TYPE_PRIMARY :
1174 DRM_PLANE_TYPE_OVERLAY;
1175 ret = exynos_plane_init(drm_dev, &ctx->planes[zpos],
1176 1 << ctx->pipe, type, zpos);
1181 exynos_plane = &ctx->planes[MIXER_DEFAULT_WIN];
1182 ctx->crtc = exynos_drm_crtc_create(drm_dev, &exynos_plane->base,
1183 ctx->pipe, EXYNOS_DISPLAY_TYPE_HDMI,
1184 &mixer_crtc_ops, ctx);
1185 if (IS_ERR(ctx->crtc)) {
1186 mixer_ctx_remove(ctx);
1187 ret = PTR_ERR(ctx->crtc);
1194 devm_kfree(dev, ctx);
1198 static void mixer_unbind(struct device *dev, struct device *master, void *data)
1200 struct mixer_context *ctx = dev_get_drvdata(dev);
1202 mixer_ctx_remove(ctx);
1205 static const struct component_ops mixer_component_ops = {
1207 .unbind = mixer_unbind,
1210 static int mixer_probe(struct platform_device *pdev)
1212 struct device *dev = &pdev->dev;
1213 struct mixer_drv_data *drv;
1214 struct mixer_context *ctx;
1217 ctx = devm_kzalloc(&pdev->dev, sizeof(*ctx), GFP_KERNEL);
1219 DRM_ERROR("failed to alloc mixer context.\n");
1224 const struct of_device_id *match;
1226 match = of_match_node(mixer_match_types, dev->of_node);
1227 drv = (struct mixer_drv_data *)match->data;
1229 drv = (struct mixer_drv_data *)
1230 platform_get_device_id(pdev)->driver_data;
1235 ctx->vp_enabled = drv->is_vp_enabled;
1236 ctx->has_sclk = drv->has_sclk;
1237 ctx->mxr_ver = drv->version;
1238 init_waitqueue_head(&ctx->wait_vsync_queue);
1239 atomic_set(&ctx->wait_vsync_event, 0);
1241 platform_set_drvdata(pdev, ctx);
1243 ret = component_add(&pdev->dev, &mixer_component_ops);
1245 pm_runtime_enable(dev);
1250 static int mixer_remove(struct platform_device *pdev)
1252 pm_runtime_disable(&pdev->dev);
1254 component_del(&pdev->dev, &mixer_component_ops);
1259 struct platform_driver mixer_driver = {
1261 .name = "exynos-mixer",
1262 .owner = THIS_MODULE,
1263 .of_match_table = mixer_match_types,
1265 .probe = mixer_probe,
1266 .remove = mixer_remove,
1267 .id_table = mixer_driver_types,