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_iommu.h"
41 #include "exynos_mixer.h"
43 #define MIXER_WIN_NR 3
44 #define MIXER_DEFAULT_WIN 0
46 struct hdmi_win_data {
48 dma_addr_t chroma_dma_addr;
49 uint32_t pixel_format;
53 unsigned int crtc_width;
54 unsigned int crtc_height;
57 unsigned int fb_width;
58 unsigned int fb_height;
59 unsigned int src_width;
60 unsigned int src_height;
61 unsigned int mode_width;
62 unsigned int mode_height;
63 unsigned int scan_flags;
68 struct mixer_resources {
70 void __iomem *mixer_regs;
71 void __iomem *vp_regs;
75 struct clk *sclk_mixer;
76 struct clk *sclk_hdmi;
77 struct clk *mout_mixer;
80 enum mixer_version_id {
86 struct mixer_context {
87 struct platform_device *pdev;
89 struct drm_device *drm_dev;
90 struct exynos_drm_crtc *crtc;
98 struct mutex mixer_mutex;
99 struct mixer_resources mixer_res;
100 struct hdmi_win_data win_data[MIXER_WIN_NR];
101 enum mixer_version_id mxr_ver;
102 wait_queue_head_t wait_vsync_queue;
103 atomic_t wait_vsync_event;
106 struct mixer_drv_data {
107 enum mixer_version_id version;
112 static const u8 filter_y_horiz_tap8[] = {
113 0, -1, -1, -1, -1, -1, -1, -1,
114 -1, -1, -1, -1, -1, 0, 0, 0,
115 0, 2, 4, 5, 6, 6, 6, 6,
116 6, 5, 5, 4, 3, 2, 1, 1,
117 0, -6, -12, -16, -18, -20, -21, -20,
118 -20, -18, -16, -13, -10, -8, -5, -2,
119 127, 126, 125, 121, 114, 107, 99, 89,
120 79, 68, 57, 46, 35, 25, 16, 8,
123 static const u8 filter_y_vert_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,
128 0, 5, 11, 19, 27, 37, 48, 59,
129 70, 81, 92, 102, 111, 118, 124, 126,
130 0, 0, -1, -1, -2, -3, -4, -5,
131 -6, -7, -8, -8, -8, -8, -6, -3,
134 static const u8 filter_cr_horiz_tap4[] = {
135 0, -3, -6, -8, -8, -8, -8, -7,
136 -6, -5, -4, -3, -2, -1, -1, 0,
137 127, 126, 124, 118, 111, 102, 92, 81,
138 70, 59, 48, 37, 27, 19, 11, 5,
141 static inline u32 vp_reg_read(struct mixer_resources *res, u32 reg_id)
143 return readl(res->vp_regs + reg_id);
146 static inline void vp_reg_write(struct mixer_resources *res, u32 reg_id,
149 writel(val, res->vp_regs + reg_id);
152 static inline void vp_reg_writemask(struct mixer_resources *res, u32 reg_id,
155 u32 old = vp_reg_read(res, reg_id);
157 val = (val & mask) | (old & ~mask);
158 writel(val, res->vp_regs + reg_id);
161 static inline u32 mixer_reg_read(struct mixer_resources *res, u32 reg_id)
163 return readl(res->mixer_regs + reg_id);
166 static inline void mixer_reg_write(struct mixer_resources *res, u32 reg_id,
169 writel(val, res->mixer_regs + reg_id);
172 static inline void mixer_reg_writemask(struct mixer_resources *res,
173 u32 reg_id, u32 val, u32 mask)
175 u32 old = mixer_reg_read(res, reg_id);
177 val = (val & mask) | (old & ~mask);
178 writel(val, res->mixer_regs + reg_id);
181 static void mixer_regs_dump(struct mixer_context *ctx)
183 #define DUMPREG(reg_id) \
185 DRM_DEBUG_KMS(#reg_id " = %08x\n", \
186 (u32)readl(ctx->mixer_res.mixer_regs + reg_id)); \
192 DUMPREG(MXR_INT_STATUS);
194 DUMPREG(MXR_LAYER_CFG);
195 DUMPREG(MXR_VIDEO_CFG);
197 DUMPREG(MXR_GRAPHIC0_CFG);
198 DUMPREG(MXR_GRAPHIC0_BASE);
199 DUMPREG(MXR_GRAPHIC0_SPAN);
200 DUMPREG(MXR_GRAPHIC0_WH);
201 DUMPREG(MXR_GRAPHIC0_SXY);
202 DUMPREG(MXR_GRAPHIC0_DXY);
204 DUMPREG(MXR_GRAPHIC1_CFG);
205 DUMPREG(MXR_GRAPHIC1_BASE);
206 DUMPREG(MXR_GRAPHIC1_SPAN);
207 DUMPREG(MXR_GRAPHIC1_WH);
208 DUMPREG(MXR_GRAPHIC1_SXY);
209 DUMPREG(MXR_GRAPHIC1_DXY);
213 static void vp_regs_dump(struct mixer_context *ctx)
215 #define DUMPREG(reg_id) \
217 DRM_DEBUG_KMS(#reg_id " = %08x\n", \
218 (u32) readl(ctx->mixer_res.vp_regs + reg_id)); \
223 DUMPREG(VP_SHADOW_UPDATE);
224 DUMPREG(VP_FIELD_ID);
226 DUMPREG(VP_IMG_SIZE_Y);
227 DUMPREG(VP_IMG_SIZE_C);
228 DUMPREG(VP_PER_RATE_CTRL);
229 DUMPREG(VP_TOP_Y_PTR);
230 DUMPREG(VP_BOT_Y_PTR);
231 DUMPREG(VP_TOP_C_PTR);
232 DUMPREG(VP_BOT_C_PTR);
233 DUMPREG(VP_ENDIAN_MODE);
234 DUMPREG(VP_SRC_H_POSITION);
235 DUMPREG(VP_SRC_V_POSITION);
236 DUMPREG(VP_SRC_WIDTH);
237 DUMPREG(VP_SRC_HEIGHT);
238 DUMPREG(VP_DST_H_POSITION);
239 DUMPREG(VP_DST_V_POSITION);
240 DUMPREG(VP_DST_WIDTH);
241 DUMPREG(VP_DST_HEIGHT);
248 static inline void vp_filter_set(struct mixer_resources *res,
249 int reg_id, const u8 *data, unsigned int size)
251 /* assure 4-byte align */
253 for (; size; size -= 4, reg_id += 4, data += 4) {
254 u32 val = (data[0] << 24) | (data[1] << 16) |
255 (data[2] << 8) | data[3];
256 vp_reg_write(res, reg_id, val);
260 static void vp_default_filter(struct mixer_resources *res)
262 vp_filter_set(res, VP_POLY8_Y0_LL,
263 filter_y_horiz_tap8, sizeof(filter_y_horiz_tap8));
264 vp_filter_set(res, VP_POLY4_Y0_LL,
265 filter_y_vert_tap4, sizeof(filter_y_vert_tap4));
266 vp_filter_set(res, VP_POLY4_C0_LL,
267 filter_cr_horiz_tap4, sizeof(filter_cr_horiz_tap4));
270 static void mixer_vsync_set_update(struct mixer_context *ctx, bool enable)
272 struct mixer_resources *res = &ctx->mixer_res;
274 /* block update on vsync */
275 mixer_reg_writemask(res, MXR_STATUS, enable ?
276 MXR_STATUS_SYNC_ENABLE : 0, MXR_STATUS_SYNC_ENABLE);
279 vp_reg_write(res, VP_SHADOW_UPDATE, enable ?
280 VP_SHADOW_UPDATE_ENABLE : 0);
283 static void mixer_cfg_scan(struct mixer_context *ctx, unsigned int height)
285 struct mixer_resources *res = &ctx->mixer_res;
288 /* choosing between interlace and progressive mode */
289 val = (ctx->interlace ? MXR_CFG_SCAN_INTERLACE :
290 MXR_CFG_SCAN_PROGRASSIVE);
292 if (ctx->mxr_ver != MXR_VER_128_0_0_184) {
293 /* choosing between proper HD and SD mode */
295 val |= MXR_CFG_SCAN_NTSC | MXR_CFG_SCAN_SD;
296 else if (height <= 576)
297 val |= MXR_CFG_SCAN_PAL | MXR_CFG_SCAN_SD;
298 else if (height <= 720)
299 val |= MXR_CFG_SCAN_HD_720 | MXR_CFG_SCAN_HD;
300 else if (height <= 1080)
301 val |= MXR_CFG_SCAN_HD_1080 | MXR_CFG_SCAN_HD;
303 val |= MXR_CFG_SCAN_HD_720 | MXR_CFG_SCAN_HD;
306 mixer_reg_writemask(res, MXR_CFG, val, MXR_CFG_SCAN_MASK);
309 static void mixer_cfg_rgb_fmt(struct mixer_context *ctx, unsigned int height)
311 struct mixer_resources *res = &ctx->mixer_res;
315 val = MXR_CFG_RGB601_0_255;
316 } else if (height == 576) {
317 val = MXR_CFG_RGB601_0_255;
318 } else if (height == 720) {
319 val = MXR_CFG_RGB709_16_235;
320 mixer_reg_write(res, MXR_CM_COEFF_Y,
321 (1 << 30) | (94 << 20) | (314 << 10) |
323 mixer_reg_write(res, MXR_CM_COEFF_CB,
324 (972 << 20) | (851 << 10) | (225 << 0));
325 mixer_reg_write(res, MXR_CM_COEFF_CR,
326 (225 << 20) | (820 << 10) | (1004 << 0));
327 } else if (height == 1080) {
328 val = MXR_CFG_RGB709_16_235;
329 mixer_reg_write(res, MXR_CM_COEFF_Y,
330 (1 << 30) | (94 << 20) | (314 << 10) |
332 mixer_reg_write(res, MXR_CM_COEFF_CB,
333 (972 << 20) | (851 << 10) | (225 << 0));
334 mixer_reg_write(res, MXR_CM_COEFF_CR,
335 (225 << 20) | (820 << 10) | (1004 << 0));
337 val = MXR_CFG_RGB709_16_235;
338 mixer_reg_write(res, MXR_CM_COEFF_Y,
339 (1 << 30) | (94 << 20) | (314 << 10) |
341 mixer_reg_write(res, MXR_CM_COEFF_CB,
342 (972 << 20) | (851 << 10) | (225 << 0));
343 mixer_reg_write(res, MXR_CM_COEFF_CR,
344 (225 << 20) | (820 << 10) | (1004 << 0));
347 mixer_reg_writemask(res, MXR_CFG, val, MXR_CFG_RGB_FMT_MASK);
350 static void mixer_cfg_layer(struct mixer_context *ctx, int win, bool enable)
352 struct mixer_resources *res = &ctx->mixer_res;
353 u32 val = enable ? ~0 : 0;
357 mixer_reg_writemask(res, MXR_CFG, val, MXR_CFG_GRP0_ENABLE);
360 mixer_reg_writemask(res, MXR_CFG, val, MXR_CFG_GRP1_ENABLE);
363 if (ctx->vp_enabled) {
364 vp_reg_writemask(res, VP_ENABLE, val, VP_ENABLE_ON);
365 mixer_reg_writemask(res, MXR_CFG, val,
368 /* control blending of graphic layer 0 */
369 mixer_reg_writemask(res, MXR_GRAPHIC_CFG(0), val,
370 MXR_GRP_CFG_BLEND_PRE_MUL |
371 MXR_GRP_CFG_PIXEL_BLEND_EN);
377 static void mixer_run(struct mixer_context *ctx)
379 struct mixer_resources *res = &ctx->mixer_res;
381 mixer_reg_writemask(res, MXR_STATUS, ~0, MXR_STATUS_REG_RUN);
383 mixer_regs_dump(ctx);
386 static void mixer_stop(struct mixer_context *ctx)
388 struct mixer_resources *res = &ctx->mixer_res;
391 mixer_reg_writemask(res, MXR_STATUS, 0, MXR_STATUS_REG_RUN);
393 while (!(mixer_reg_read(res, MXR_STATUS) & MXR_STATUS_REG_IDLE) &&
395 usleep_range(10000, 12000);
397 mixer_regs_dump(ctx);
400 static void vp_video_buffer(struct mixer_context *ctx, int win)
402 struct mixer_resources *res = &ctx->mixer_res;
404 struct hdmi_win_data *win_data;
405 unsigned int x_ratio, y_ratio;
406 unsigned int buf_num = 1;
407 dma_addr_t luma_addr[2], chroma_addr[2];
408 bool tiled_mode = false;
409 bool crcb_mode = false;
412 win_data = &ctx->win_data[win];
414 switch (win_data->pixel_format) {
415 case DRM_FORMAT_NV12:
419 /* TODO: single buffer format NV12, NV21 */
421 /* ignore pixel format at disable time */
422 if (!win_data->dma_addr)
425 DRM_ERROR("pixel format for vp is wrong [%d].\n",
426 win_data->pixel_format);
430 /* scaling feature: (src << 16) / dst */
431 x_ratio = (win_data->src_width << 16) / win_data->crtc_width;
432 y_ratio = (win_data->src_height << 16) / win_data->crtc_height;
435 luma_addr[0] = win_data->dma_addr;
436 chroma_addr[0] = win_data->chroma_dma_addr;
438 luma_addr[0] = win_data->dma_addr;
439 chroma_addr[0] = win_data->dma_addr
440 + (win_data->fb_width * win_data->fb_height);
443 if (win_data->scan_flags & DRM_MODE_FLAG_INTERLACE) {
444 ctx->interlace = true;
446 luma_addr[1] = luma_addr[0] + 0x40;
447 chroma_addr[1] = chroma_addr[0] + 0x40;
449 luma_addr[1] = luma_addr[0] + win_data->fb_width;
450 chroma_addr[1] = chroma_addr[0] + win_data->fb_width;
453 ctx->interlace = false;
458 spin_lock_irqsave(&res->reg_slock, flags);
459 mixer_vsync_set_update(ctx, false);
461 /* interlace or progressive scan mode */
462 val = (ctx->interlace ? ~0 : 0);
463 vp_reg_writemask(res, VP_MODE, val, VP_MODE_LINE_SKIP);
466 val = (crcb_mode ? VP_MODE_NV21 : VP_MODE_NV12);
467 val |= (tiled_mode ? VP_MODE_MEM_TILED : VP_MODE_MEM_LINEAR);
468 vp_reg_writemask(res, VP_MODE, val, VP_MODE_FMT_MASK);
470 /* setting size of input image */
471 vp_reg_write(res, VP_IMG_SIZE_Y, VP_IMG_HSIZE(win_data->fb_width) |
472 VP_IMG_VSIZE(win_data->fb_height));
473 /* chroma height has to reduced by 2 to avoid chroma distorions */
474 vp_reg_write(res, VP_IMG_SIZE_C, VP_IMG_HSIZE(win_data->fb_width) |
475 VP_IMG_VSIZE(win_data->fb_height / 2));
477 vp_reg_write(res, VP_SRC_WIDTH, win_data->src_width);
478 vp_reg_write(res, VP_SRC_HEIGHT, win_data->src_height);
479 vp_reg_write(res, VP_SRC_H_POSITION,
480 VP_SRC_H_POSITION_VAL(win_data->fb_x));
481 vp_reg_write(res, VP_SRC_V_POSITION, win_data->fb_y);
483 vp_reg_write(res, VP_DST_WIDTH, win_data->crtc_width);
484 vp_reg_write(res, VP_DST_H_POSITION, win_data->crtc_x);
485 if (ctx->interlace) {
486 vp_reg_write(res, VP_DST_HEIGHT, win_data->crtc_height / 2);
487 vp_reg_write(res, VP_DST_V_POSITION, win_data->crtc_y / 2);
489 vp_reg_write(res, VP_DST_HEIGHT, win_data->crtc_height);
490 vp_reg_write(res, VP_DST_V_POSITION, win_data->crtc_y);
493 vp_reg_write(res, VP_H_RATIO, x_ratio);
494 vp_reg_write(res, VP_V_RATIO, y_ratio);
496 vp_reg_write(res, VP_ENDIAN_MODE, VP_ENDIAN_MODE_LITTLE);
498 /* set buffer address to vp */
499 vp_reg_write(res, VP_TOP_Y_PTR, luma_addr[0]);
500 vp_reg_write(res, VP_BOT_Y_PTR, luma_addr[1]);
501 vp_reg_write(res, VP_TOP_C_PTR, chroma_addr[0]);
502 vp_reg_write(res, VP_BOT_C_PTR, chroma_addr[1]);
504 mixer_cfg_scan(ctx, win_data->mode_height);
505 mixer_cfg_rgb_fmt(ctx, win_data->mode_height);
506 mixer_cfg_layer(ctx, win, true);
509 mixer_vsync_set_update(ctx, true);
510 spin_unlock_irqrestore(&res->reg_slock, flags);
515 static void mixer_layer_update(struct mixer_context *ctx)
517 struct mixer_resources *res = &ctx->mixer_res;
519 mixer_reg_writemask(res, MXR_CFG, ~0, MXR_CFG_LAYER_UPDATE);
522 static void mixer_graph_buffer(struct mixer_context *ctx, int win)
524 struct mixer_resources *res = &ctx->mixer_res;
526 struct hdmi_win_data *win_data;
527 unsigned int x_ratio, y_ratio;
528 unsigned int src_x_offset, src_y_offset, dst_x_offset, dst_y_offset;
533 win_data = &ctx->win_data[win];
540 switch (win_data->bpp) {
551 /* 2x scaling feature */
555 dst_x_offset = win_data->crtc_x;
556 dst_y_offset = win_data->crtc_y;
558 /* converting dma address base and source offset */
559 dma_addr = win_data->dma_addr
560 + (win_data->fb_x * win_data->bpp >> 3)
561 + (win_data->fb_y * win_data->fb_width * win_data->bpp >> 3);
565 if (win_data->scan_flags & DRM_MODE_FLAG_INTERLACE)
566 ctx->interlace = true;
568 ctx->interlace = false;
570 spin_lock_irqsave(&res->reg_slock, flags);
571 mixer_vsync_set_update(ctx, false);
574 mixer_reg_writemask(res, MXR_GRAPHIC_CFG(win),
575 MXR_GRP_CFG_FORMAT_VAL(fmt), MXR_GRP_CFG_FORMAT_MASK);
578 mixer_reg_write(res, MXR_GRAPHIC_SPAN(win), win_data->fb_width);
580 /* setup display size */
581 if (ctx->mxr_ver == MXR_VER_128_0_0_184 &&
582 win == MIXER_DEFAULT_WIN) {
583 val = MXR_MXR_RES_HEIGHT(win_data->fb_height);
584 val |= MXR_MXR_RES_WIDTH(win_data->fb_width);
585 mixer_reg_write(res, MXR_RESOLUTION, val);
588 val = MXR_GRP_WH_WIDTH(win_data->crtc_width);
589 val |= MXR_GRP_WH_HEIGHT(win_data->crtc_height);
590 val |= MXR_GRP_WH_H_SCALE(x_ratio);
591 val |= MXR_GRP_WH_V_SCALE(y_ratio);
592 mixer_reg_write(res, MXR_GRAPHIC_WH(win), val);
594 /* setup offsets in source image */
595 val = MXR_GRP_SXY_SX(src_x_offset);
596 val |= MXR_GRP_SXY_SY(src_y_offset);
597 mixer_reg_write(res, MXR_GRAPHIC_SXY(win), val);
599 /* setup offsets in display image */
600 val = MXR_GRP_DXY_DX(dst_x_offset);
601 val |= MXR_GRP_DXY_DY(dst_y_offset);
602 mixer_reg_write(res, MXR_GRAPHIC_DXY(win), val);
604 /* set buffer address to mixer */
605 mixer_reg_write(res, MXR_GRAPHIC_BASE(win), dma_addr);
607 mixer_cfg_scan(ctx, win_data->mode_height);
608 mixer_cfg_rgb_fmt(ctx, win_data->mode_height);
609 mixer_cfg_layer(ctx, win, true);
611 /* layer update mandatory for mixer 16.0.33.0 */
612 if (ctx->mxr_ver == MXR_VER_16_0_33_0 ||
613 ctx->mxr_ver == MXR_VER_128_0_0_184)
614 mixer_layer_update(ctx);
618 mixer_vsync_set_update(ctx, true);
619 spin_unlock_irqrestore(&res->reg_slock, flags);
622 static void vp_win_reset(struct mixer_context *ctx)
624 struct mixer_resources *res = &ctx->mixer_res;
627 vp_reg_write(res, VP_SRESET, VP_SRESET_PROCESSING);
628 for (tries = 100; tries; --tries) {
629 /* waiting until VP_SRESET_PROCESSING is 0 */
630 if (~vp_reg_read(res, VP_SRESET) & VP_SRESET_PROCESSING)
632 usleep_range(10000, 12000);
634 WARN(tries == 0, "failed to reset Video Processor\n");
637 static void mixer_win_reset(struct mixer_context *ctx)
639 struct mixer_resources *res = &ctx->mixer_res;
641 u32 val; /* value stored to register */
643 spin_lock_irqsave(&res->reg_slock, flags);
644 mixer_vsync_set_update(ctx, false);
646 mixer_reg_writemask(res, MXR_CFG, MXR_CFG_DST_HDMI, MXR_CFG_DST_MASK);
648 /* set output in RGB888 mode */
649 mixer_reg_writemask(res, MXR_CFG, MXR_CFG_OUT_RGB888, MXR_CFG_OUT_MASK);
651 /* 16 beat burst in DMA */
652 mixer_reg_writemask(res, MXR_STATUS, MXR_STATUS_16_BURST,
653 MXR_STATUS_BURST_MASK);
655 /* setting default layer priority: layer1 > layer0 > video
656 * because typical usage scenario would be
658 * layer0 - framebuffer
659 * video - video overlay
661 val = MXR_LAYER_CFG_GRP1_VAL(3);
662 val |= MXR_LAYER_CFG_GRP0_VAL(2);
664 val |= MXR_LAYER_CFG_VP_VAL(1);
665 mixer_reg_write(res, MXR_LAYER_CFG, val);
667 /* setting background color */
668 mixer_reg_write(res, MXR_BG_COLOR0, 0x008080);
669 mixer_reg_write(res, MXR_BG_COLOR1, 0x008080);
670 mixer_reg_write(res, MXR_BG_COLOR2, 0x008080);
672 /* setting graphical layers */
673 val = MXR_GRP_CFG_COLOR_KEY_DISABLE; /* no blank key */
674 val |= MXR_GRP_CFG_WIN_BLEND_EN;
675 val |= MXR_GRP_CFG_ALPHA_VAL(0xff); /* non-transparent alpha */
677 /* Don't blend layer 0 onto the mixer background */
678 mixer_reg_write(res, MXR_GRAPHIC_CFG(0), val);
680 /* Blend layer 1 into layer 0 */
681 val |= MXR_GRP_CFG_BLEND_PRE_MUL;
682 val |= MXR_GRP_CFG_PIXEL_BLEND_EN;
683 mixer_reg_write(res, MXR_GRAPHIC_CFG(1), val);
685 /* setting video layers */
686 val = MXR_GRP_CFG_ALPHA_VAL(0);
687 mixer_reg_write(res, MXR_VIDEO_CFG, val);
689 if (ctx->vp_enabled) {
690 /* configuration of Video Processor Registers */
692 vp_default_filter(res);
695 /* disable all layers */
696 mixer_reg_writemask(res, MXR_CFG, 0, MXR_CFG_GRP0_ENABLE);
697 mixer_reg_writemask(res, MXR_CFG, 0, MXR_CFG_GRP1_ENABLE);
699 mixer_reg_writemask(res, MXR_CFG, 0, MXR_CFG_VP_ENABLE);
701 mixer_vsync_set_update(ctx, true);
702 spin_unlock_irqrestore(&res->reg_slock, flags);
705 static irqreturn_t mixer_irq_handler(int irq, void *arg)
707 struct mixer_context *ctx = arg;
708 struct mixer_resources *res = &ctx->mixer_res;
709 u32 val, base, shadow;
711 spin_lock(&res->reg_slock);
713 /* read interrupt status for handling and clearing flags for VSYNC */
714 val = mixer_reg_read(res, MXR_INT_STATUS);
717 if (val & MXR_INT_STATUS_VSYNC) {
718 /* interlace scan need to check shadow register */
719 if (ctx->interlace) {
720 base = mixer_reg_read(res, MXR_GRAPHIC_BASE(0));
721 shadow = mixer_reg_read(res, MXR_GRAPHIC_BASE_S(0));
725 base = mixer_reg_read(res, MXR_GRAPHIC_BASE(1));
726 shadow = mixer_reg_read(res, MXR_GRAPHIC_BASE_S(1));
731 drm_handle_vblank(ctx->drm_dev, ctx->pipe);
732 exynos_drm_crtc_finish_pageflip(ctx->drm_dev, ctx->pipe);
734 /* set wait vsync event to zero and wake up queue. */
735 if (atomic_read(&ctx->wait_vsync_event)) {
736 atomic_set(&ctx->wait_vsync_event, 0);
737 wake_up(&ctx->wait_vsync_queue);
742 /* clear interrupts */
743 if (~val & MXR_INT_EN_VSYNC) {
744 /* vsync interrupt use different bit for read and clear */
745 val &= ~MXR_INT_EN_VSYNC;
746 val |= MXR_INT_CLEAR_VSYNC;
748 mixer_reg_write(res, MXR_INT_STATUS, val);
750 spin_unlock(&res->reg_slock);
755 static int mixer_resources_init(struct mixer_context *mixer_ctx)
757 struct device *dev = &mixer_ctx->pdev->dev;
758 struct mixer_resources *mixer_res = &mixer_ctx->mixer_res;
759 struct resource *res;
762 spin_lock_init(&mixer_res->reg_slock);
764 mixer_res->mixer = devm_clk_get(dev, "mixer");
765 if (IS_ERR(mixer_res->mixer)) {
766 dev_err(dev, "failed to get clock 'mixer'\n");
770 mixer_res->sclk_hdmi = devm_clk_get(dev, "sclk_hdmi");
771 if (IS_ERR(mixer_res->sclk_hdmi)) {
772 dev_err(dev, "failed to get clock 'sclk_hdmi'\n");
775 res = platform_get_resource(mixer_ctx->pdev, IORESOURCE_MEM, 0);
777 dev_err(dev, "get memory resource failed.\n");
781 mixer_res->mixer_regs = devm_ioremap(dev, res->start,
783 if (mixer_res->mixer_regs == NULL) {
784 dev_err(dev, "register mapping failed.\n");
788 res = platform_get_resource(mixer_ctx->pdev, IORESOURCE_IRQ, 0);
790 dev_err(dev, "get interrupt resource failed.\n");
794 ret = devm_request_irq(dev, res->start, mixer_irq_handler,
795 0, "drm_mixer", mixer_ctx);
797 dev_err(dev, "request interrupt failed.\n");
800 mixer_res->irq = res->start;
805 static int vp_resources_init(struct mixer_context *mixer_ctx)
807 struct device *dev = &mixer_ctx->pdev->dev;
808 struct mixer_resources *mixer_res = &mixer_ctx->mixer_res;
809 struct resource *res;
811 mixer_res->vp = devm_clk_get(dev, "vp");
812 if (IS_ERR(mixer_res->vp)) {
813 dev_err(dev, "failed to get clock 'vp'\n");
817 if (mixer_ctx->has_sclk) {
818 mixer_res->sclk_mixer = devm_clk_get(dev, "sclk_mixer");
819 if (IS_ERR(mixer_res->sclk_mixer)) {
820 dev_err(dev, "failed to get clock 'sclk_mixer'\n");
823 mixer_res->mout_mixer = devm_clk_get(dev, "mout_mixer");
824 if (IS_ERR(mixer_res->mout_mixer)) {
825 dev_err(dev, "failed to get clock 'mout_mixer'\n");
829 if (mixer_res->sclk_hdmi && mixer_res->mout_mixer)
830 clk_set_parent(mixer_res->mout_mixer,
831 mixer_res->sclk_hdmi);
834 res = platform_get_resource(mixer_ctx->pdev, IORESOURCE_MEM, 1);
836 dev_err(dev, "get memory resource failed.\n");
840 mixer_res->vp_regs = devm_ioremap(dev, res->start,
842 if (mixer_res->vp_regs == NULL) {
843 dev_err(dev, "register mapping failed.\n");
850 static int mixer_initialize(struct mixer_context *mixer_ctx,
851 struct drm_device *drm_dev)
854 struct exynos_drm_private *priv;
855 priv = drm_dev->dev_private;
857 mixer_ctx->drm_dev = drm_dev;
858 mixer_ctx->pipe = priv->pipe++;
860 /* acquire resources: regs, irqs, clocks */
861 ret = mixer_resources_init(mixer_ctx);
863 DRM_ERROR("mixer_resources_init failed ret=%d\n", ret);
867 if (mixer_ctx->vp_enabled) {
868 /* acquire vp resources: regs, irqs, clocks */
869 ret = vp_resources_init(mixer_ctx);
871 DRM_ERROR("vp_resources_init failed ret=%d\n", ret);
876 if (!is_drm_iommu_supported(mixer_ctx->drm_dev))
879 return drm_iommu_attach_device(mixer_ctx->drm_dev, mixer_ctx->dev);
882 static void mixer_ctx_remove(struct mixer_context *mixer_ctx)
884 if (is_drm_iommu_supported(mixer_ctx->drm_dev))
885 drm_iommu_detach_device(mixer_ctx->drm_dev, mixer_ctx->dev);
888 static int mixer_enable_vblank(struct exynos_drm_crtc *crtc)
890 struct mixer_context *mixer_ctx = crtc->ctx;
891 struct mixer_resources *res = &mixer_ctx->mixer_res;
893 if (!mixer_ctx->powered) {
894 mixer_ctx->int_en |= MXR_INT_EN_VSYNC;
898 /* enable vsync interrupt */
899 mixer_reg_writemask(res, MXR_INT_EN, MXR_INT_EN_VSYNC,
905 static void mixer_disable_vblank(struct exynos_drm_crtc *crtc)
907 struct mixer_context *mixer_ctx = crtc->ctx;
908 struct mixer_resources *res = &mixer_ctx->mixer_res;
910 /* disable vsync interrupt */
911 mixer_reg_writemask(res, MXR_INT_EN, 0, MXR_INT_EN_VSYNC);
914 static void mixer_win_mode_set(struct exynos_drm_crtc *crtc,
915 struct exynos_drm_plane *plane)
917 struct mixer_context *mixer_ctx = crtc->ctx;
918 struct hdmi_win_data *win_data;
922 DRM_ERROR("plane is NULL\n");
926 DRM_DEBUG_KMS("set [%d]x[%d] at (%d,%d) to [%d]x[%d] at (%d,%d)\n",
927 plane->fb_width, plane->fb_height,
928 plane->fb_x, plane->fb_y,
929 plane->crtc_width, plane->crtc_height,
930 plane->crtc_x, plane->crtc_y);
933 if (win == DEFAULT_ZPOS)
934 win = MIXER_DEFAULT_WIN;
936 if (win < 0 || win >= MIXER_WIN_NR) {
937 DRM_ERROR("mixer window[%d] is wrong\n", win);
941 win_data = &mixer_ctx->win_data[win];
943 win_data->dma_addr = plane->dma_addr[0];
944 win_data->chroma_dma_addr = plane->dma_addr[1];
945 win_data->pixel_format = plane->pixel_format;
946 win_data->bpp = plane->bpp;
948 win_data->crtc_x = plane->crtc_x;
949 win_data->crtc_y = plane->crtc_y;
950 win_data->crtc_width = plane->crtc_width;
951 win_data->crtc_height = plane->crtc_height;
953 win_data->fb_x = plane->fb_x;
954 win_data->fb_y = plane->fb_y;
955 win_data->fb_width = plane->fb_width;
956 win_data->fb_height = plane->fb_height;
957 win_data->src_width = plane->src_width;
958 win_data->src_height = plane->src_height;
960 win_data->mode_width = plane->mode_width;
961 win_data->mode_height = plane->mode_height;
963 win_data->scan_flags = plane->scan_flag;
966 static void mixer_win_commit(struct exynos_drm_crtc *crtc, int zpos)
968 struct mixer_context *mixer_ctx = crtc->ctx;
969 int win = zpos == DEFAULT_ZPOS ? MIXER_DEFAULT_WIN : zpos;
971 DRM_DEBUG_KMS("win: %d\n", win);
973 mutex_lock(&mixer_ctx->mixer_mutex);
974 if (!mixer_ctx->powered) {
975 mutex_unlock(&mixer_ctx->mixer_mutex);
978 mutex_unlock(&mixer_ctx->mixer_mutex);
980 if (win > 1 && mixer_ctx->vp_enabled)
981 vp_video_buffer(mixer_ctx, win);
983 mixer_graph_buffer(mixer_ctx, win);
985 mixer_ctx->win_data[win].enabled = true;
988 static void mixer_win_disable(struct exynos_drm_crtc *crtc, int zpos)
990 struct mixer_context *mixer_ctx = crtc->ctx;
991 struct mixer_resources *res = &mixer_ctx->mixer_res;
992 int win = zpos == DEFAULT_ZPOS ? MIXER_DEFAULT_WIN : zpos;
995 DRM_DEBUG_KMS("win: %d\n", win);
997 mutex_lock(&mixer_ctx->mixer_mutex);
998 if (!mixer_ctx->powered) {
999 mutex_unlock(&mixer_ctx->mixer_mutex);
1000 mixer_ctx->win_data[win].resume = false;
1003 mutex_unlock(&mixer_ctx->mixer_mutex);
1005 spin_lock_irqsave(&res->reg_slock, flags);
1006 mixer_vsync_set_update(mixer_ctx, false);
1008 mixer_cfg_layer(mixer_ctx, win, false);
1010 mixer_vsync_set_update(mixer_ctx, true);
1011 spin_unlock_irqrestore(&res->reg_slock, flags);
1013 mixer_ctx->win_data[win].enabled = false;
1016 static void mixer_wait_for_vblank(struct exynos_drm_crtc *crtc)
1018 struct mixer_context *mixer_ctx = crtc->ctx;
1021 mutex_lock(&mixer_ctx->mixer_mutex);
1022 if (!mixer_ctx->powered) {
1023 mutex_unlock(&mixer_ctx->mixer_mutex);
1026 mutex_unlock(&mixer_ctx->mixer_mutex);
1028 err = drm_vblank_get(mixer_ctx->drm_dev, mixer_ctx->pipe);
1030 DRM_DEBUG_KMS("failed to acquire vblank counter\n");
1034 atomic_set(&mixer_ctx->wait_vsync_event, 1);
1037 * wait for MIXER to signal VSYNC interrupt or return after
1038 * timeout which is set to 50ms (refresh rate of 20).
1040 if (!wait_event_timeout(mixer_ctx->wait_vsync_queue,
1041 !atomic_read(&mixer_ctx->wait_vsync_event),
1043 DRM_DEBUG_KMS("vblank wait timed out.\n");
1045 drm_vblank_put(mixer_ctx->drm_dev, mixer_ctx->pipe);
1048 static void mixer_window_suspend(struct exynos_drm_crtc *crtc)
1050 struct mixer_context *ctx = crtc->ctx;
1051 struct hdmi_win_data *win_data;
1054 for (i = 0; i < MIXER_WIN_NR; i++) {
1055 win_data = &ctx->win_data[i];
1056 win_data->resume = win_data->enabled;
1057 mixer_win_disable(crtc, i);
1059 mixer_wait_for_vblank(crtc);
1062 static void mixer_window_resume(struct exynos_drm_crtc *crtc)
1064 struct mixer_context *ctx = crtc->ctx;
1065 struct hdmi_win_data *win_data;
1068 for (i = 0; i < MIXER_WIN_NR; i++) {
1069 win_data = &ctx->win_data[i];
1070 win_data->enabled = win_data->resume;
1071 win_data->resume = false;
1072 if (win_data->enabled)
1073 mixer_win_commit(crtc, i);
1077 static void mixer_poweron(struct exynos_drm_crtc *crtc)
1079 struct mixer_context *ctx = crtc->ctx;
1080 struct mixer_resources *res = &ctx->mixer_res;
1082 mutex_lock(&ctx->mixer_mutex);
1084 mutex_unlock(&ctx->mixer_mutex);
1088 mutex_unlock(&ctx->mixer_mutex);
1090 pm_runtime_get_sync(ctx->dev);
1092 clk_prepare_enable(res->mixer);
1093 if (ctx->vp_enabled) {
1094 clk_prepare_enable(res->vp);
1096 clk_prepare_enable(res->sclk_mixer);
1099 mutex_lock(&ctx->mixer_mutex);
1100 ctx->powered = true;
1101 mutex_unlock(&ctx->mixer_mutex);
1103 mixer_reg_writemask(res, MXR_STATUS, ~0, MXR_STATUS_SOFT_RESET);
1105 mixer_reg_write(res, MXR_INT_EN, ctx->int_en);
1106 mixer_win_reset(ctx);
1108 mixer_window_resume(crtc);
1111 static void mixer_poweroff(struct exynos_drm_crtc *crtc)
1113 struct mixer_context *ctx = crtc->ctx;
1114 struct mixer_resources *res = &ctx->mixer_res;
1116 mutex_lock(&ctx->mixer_mutex);
1117 if (!ctx->powered) {
1118 mutex_unlock(&ctx->mixer_mutex);
1121 mutex_unlock(&ctx->mixer_mutex);
1124 mixer_window_suspend(crtc);
1126 ctx->int_en = mixer_reg_read(res, MXR_INT_EN);
1128 mutex_lock(&ctx->mixer_mutex);
1129 ctx->powered = false;
1130 mutex_unlock(&ctx->mixer_mutex);
1132 clk_disable_unprepare(res->mixer);
1133 if (ctx->vp_enabled) {
1134 clk_disable_unprepare(res->vp);
1136 clk_disable_unprepare(res->sclk_mixer);
1139 pm_runtime_put_sync(ctx->dev);
1142 static void mixer_dpms(struct exynos_drm_crtc *crtc, int mode)
1145 case DRM_MODE_DPMS_ON:
1146 mixer_poweron(crtc);
1148 case DRM_MODE_DPMS_STANDBY:
1149 case DRM_MODE_DPMS_SUSPEND:
1150 case DRM_MODE_DPMS_OFF:
1151 mixer_poweroff(crtc);
1154 DRM_DEBUG_KMS("unknown dpms mode: %d\n", mode);
1159 /* Only valid for Mixer version 16.0.33.0 */
1160 int mixer_check_mode(struct drm_display_mode *mode)
1167 DRM_DEBUG_KMS("xres=%d, yres=%d, refresh=%d, intl=%d\n",
1168 mode->hdisplay, mode->vdisplay, mode->vrefresh,
1169 (mode->flags & DRM_MODE_FLAG_INTERLACE) ? 1 : 0);
1171 if ((w >= 464 && w <= 720 && h >= 261 && h <= 576) ||
1172 (w >= 1024 && w <= 1280 && h >= 576 && h <= 720) ||
1173 (w >= 1664 && w <= 1920 && h >= 936 && h <= 1080))
1179 static struct exynos_drm_crtc_ops mixer_crtc_ops = {
1181 .enable_vblank = mixer_enable_vblank,
1182 .disable_vblank = mixer_disable_vblank,
1183 .wait_for_vblank = mixer_wait_for_vblank,
1184 .win_mode_set = mixer_win_mode_set,
1185 .win_commit = mixer_win_commit,
1186 .win_disable = mixer_win_disable,
1189 static struct mixer_drv_data exynos5420_mxr_drv_data = {
1190 .version = MXR_VER_128_0_0_184,
1194 static struct mixer_drv_data exynos5250_mxr_drv_data = {
1195 .version = MXR_VER_16_0_33_0,
1199 static struct mixer_drv_data exynos4212_mxr_drv_data = {
1200 .version = MXR_VER_0_0_0_16,
1204 static struct mixer_drv_data exynos4210_mxr_drv_data = {
1205 .version = MXR_VER_0_0_0_16,
1210 static struct platform_device_id mixer_driver_types[] = {
1212 .name = "s5p-mixer",
1213 .driver_data = (unsigned long)&exynos4210_mxr_drv_data,
1215 .name = "exynos5-mixer",
1216 .driver_data = (unsigned long)&exynos5250_mxr_drv_data,
1222 static struct of_device_id mixer_match_types[] = {
1224 .compatible = "samsung,exynos4210-mixer",
1225 .data = &exynos4210_mxr_drv_data,
1227 .compatible = "samsung,exynos4212-mixer",
1228 .data = &exynos4212_mxr_drv_data,
1230 .compatible = "samsung,exynos5-mixer",
1231 .data = &exynos5250_mxr_drv_data,
1233 .compatible = "samsung,exynos5250-mixer",
1234 .data = &exynos5250_mxr_drv_data,
1236 .compatible = "samsung,exynos5420-mixer",
1237 .data = &exynos5420_mxr_drv_data,
1242 MODULE_DEVICE_TABLE(of, mixer_match_types);
1244 static int mixer_bind(struct device *dev, struct device *manager, void *data)
1246 struct mixer_context *ctx = dev_get_drvdata(dev);
1247 struct drm_device *drm_dev = data;
1250 ctx->crtc = exynos_drm_crtc_create(drm_dev, ctx->pipe,
1251 EXYNOS_DISPLAY_TYPE_HDMI,
1252 &mixer_crtc_ops, ctx);
1253 if (IS_ERR(ctx->crtc)) {
1254 ret = PTR_ERR(ctx->crtc);
1258 ret = mixer_initialize(ctx, drm_dev);
1265 devm_kfree(dev, ctx);
1269 static void mixer_unbind(struct device *dev, struct device *master, void *data)
1271 struct mixer_context *ctx = dev_get_drvdata(dev);
1273 mixer_ctx_remove(ctx);
1276 static const struct component_ops mixer_component_ops = {
1278 .unbind = mixer_unbind,
1281 static int mixer_probe(struct platform_device *pdev)
1283 struct device *dev = &pdev->dev;
1284 struct mixer_drv_data *drv;
1285 struct mixer_context *ctx;
1288 ctx = devm_kzalloc(&pdev->dev, sizeof(*ctx), GFP_KERNEL);
1290 DRM_ERROR("failed to alloc mixer context.\n");
1294 mutex_init(&ctx->mixer_mutex);
1297 const struct of_device_id *match;
1299 match = of_match_node(mixer_match_types, dev->of_node);
1300 drv = (struct mixer_drv_data *)match->data;
1302 drv = (struct mixer_drv_data *)
1303 platform_get_device_id(pdev)->driver_data;
1308 ctx->vp_enabled = drv->is_vp_enabled;
1309 ctx->has_sclk = drv->has_sclk;
1310 ctx->mxr_ver = drv->version;
1311 init_waitqueue_head(&ctx->wait_vsync_queue);
1312 atomic_set(&ctx->wait_vsync_event, 0);
1314 platform_set_drvdata(pdev, ctx);
1316 ret = exynos_drm_component_add(&pdev->dev, EXYNOS_DEVICE_TYPE_CRTC,
1317 EXYNOS_DISPLAY_TYPE_HDMI);
1321 ret = component_add(&pdev->dev, &mixer_component_ops);
1323 exynos_drm_component_del(&pdev->dev, EXYNOS_DEVICE_TYPE_CRTC);
1327 pm_runtime_enable(dev);
1332 static int mixer_remove(struct platform_device *pdev)
1334 pm_runtime_disable(&pdev->dev);
1336 component_del(&pdev->dev, &mixer_component_ops);
1337 exynos_drm_component_del(&pdev->dev, EXYNOS_DEVICE_TYPE_CRTC);
1342 struct platform_driver mixer_driver = {
1344 .name = "exynos-mixer",
1345 .owner = THIS_MODULE,
1346 .of_match_table = mixer_match_types,
1348 .probe = mixer_probe,
1349 .remove = mixer_remove,
1350 .id_table = mixer_driver_types,