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 get_mixer_manager(dev) platform_get_drvdata(to_platform_device(dev))
45 #define MIXER_WIN_NR 3
46 #define MIXER_DEFAULT_WIN 0
48 struct hdmi_win_data {
50 dma_addr_t chroma_dma_addr;
51 uint32_t pixel_format;
55 unsigned int crtc_width;
56 unsigned int crtc_height;
59 unsigned int fb_width;
60 unsigned int fb_height;
61 unsigned int src_width;
62 unsigned int src_height;
63 unsigned int mode_width;
64 unsigned int mode_height;
65 unsigned int scan_flags;
70 struct mixer_resources {
72 void __iomem *mixer_regs;
73 void __iomem *vp_regs;
77 struct clk *sclk_mixer;
78 struct clk *sclk_hdmi;
79 struct clk *mout_mixer;
82 enum mixer_version_id {
88 struct mixer_context {
89 struct platform_device *pdev;
91 struct drm_device *drm_dev;
99 struct mutex mixer_mutex;
100 struct mixer_resources mixer_res;
101 struct hdmi_win_data win_data[MIXER_WIN_NR];
102 enum mixer_version_id mxr_ver;
103 wait_queue_head_t wait_vsync_queue;
104 atomic_t wait_vsync_event;
107 struct mixer_drv_data {
108 enum mixer_version_id version;
113 static const u8 filter_y_horiz_tap8[] = {
114 0, -1, -1, -1, -1, -1, -1, -1,
115 -1, -1, -1, -1, -1, 0, 0, 0,
116 0, 2, 4, 5, 6, 6, 6, 6,
117 6, 5, 5, 4, 3, 2, 1, 1,
118 0, -6, -12, -16, -18, -20, -21, -20,
119 -20, -18, -16, -13, -10, -8, -5, -2,
120 127, 126, 125, 121, 114, 107, 99, 89,
121 79, 68, 57, 46, 35, 25, 16, 8,
124 static const u8 filter_y_vert_tap4[] = {
125 0, -3, -6, -8, -8, -8, -8, -7,
126 -6, -5, -4, -3, -2, -1, -1, 0,
127 127, 126, 124, 118, 111, 102, 92, 81,
128 70, 59, 48, 37, 27, 19, 11, 5,
129 0, 5, 11, 19, 27, 37, 48, 59,
130 70, 81, 92, 102, 111, 118, 124, 126,
131 0, 0, -1, -1, -2, -3, -4, -5,
132 -6, -7, -8, -8, -8, -8, -6, -3,
135 static const u8 filter_cr_horiz_tap4[] = {
136 0, -3, -6, -8, -8, -8, -8, -7,
137 -6, -5, -4, -3, -2, -1, -1, 0,
138 127, 126, 124, 118, 111, 102, 92, 81,
139 70, 59, 48, 37, 27, 19, 11, 5,
142 static inline u32 vp_reg_read(struct mixer_resources *res, u32 reg_id)
144 return readl(res->vp_regs + reg_id);
147 static inline void vp_reg_write(struct mixer_resources *res, u32 reg_id,
150 writel(val, res->vp_regs + reg_id);
153 static inline void vp_reg_writemask(struct mixer_resources *res, u32 reg_id,
156 u32 old = vp_reg_read(res, reg_id);
158 val = (val & mask) | (old & ~mask);
159 writel(val, res->vp_regs + reg_id);
162 static inline u32 mixer_reg_read(struct mixer_resources *res, u32 reg_id)
164 return readl(res->mixer_regs + reg_id);
167 static inline void mixer_reg_write(struct mixer_resources *res, u32 reg_id,
170 writel(val, res->mixer_regs + reg_id);
173 static inline void mixer_reg_writemask(struct mixer_resources *res,
174 u32 reg_id, u32 val, u32 mask)
176 u32 old = mixer_reg_read(res, reg_id);
178 val = (val & mask) | (old & ~mask);
179 writel(val, res->mixer_regs + reg_id);
182 static void mixer_regs_dump(struct mixer_context *ctx)
184 #define DUMPREG(reg_id) \
186 DRM_DEBUG_KMS(#reg_id " = %08x\n", \
187 (u32)readl(ctx->mixer_res.mixer_regs + reg_id)); \
193 DUMPREG(MXR_INT_STATUS);
195 DUMPREG(MXR_LAYER_CFG);
196 DUMPREG(MXR_VIDEO_CFG);
198 DUMPREG(MXR_GRAPHIC0_CFG);
199 DUMPREG(MXR_GRAPHIC0_BASE);
200 DUMPREG(MXR_GRAPHIC0_SPAN);
201 DUMPREG(MXR_GRAPHIC0_WH);
202 DUMPREG(MXR_GRAPHIC0_SXY);
203 DUMPREG(MXR_GRAPHIC0_DXY);
205 DUMPREG(MXR_GRAPHIC1_CFG);
206 DUMPREG(MXR_GRAPHIC1_BASE);
207 DUMPREG(MXR_GRAPHIC1_SPAN);
208 DUMPREG(MXR_GRAPHIC1_WH);
209 DUMPREG(MXR_GRAPHIC1_SXY);
210 DUMPREG(MXR_GRAPHIC1_DXY);
214 static void vp_regs_dump(struct mixer_context *ctx)
216 #define DUMPREG(reg_id) \
218 DRM_DEBUG_KMS(#reg_id " = %08x\n", \
219 (u32) readl(ctx->mixer_res.vp_regs + reg_id)); \
224 DUMPREG(VP_SHADOW_UPDATE);
225 DUMPREG(VP_FIELD_ID);
227 DUMPREG(VP_IMG_SIZE_Y);
228 DUMPREG(VP_IMG_SIZE_C);
229 DUMPREG(VP_PER_RATE_CTRL);
230 DUMPREG(VP_TOP_Y_PTR);
231 DUMPREG(VP_BOT_Y_PTR);
232 DUMPREG(VP_TOP_C_PTR);
233 DUMPREG(VP_BOT_C_PTR);
234 DUMPREG(VP_ENDIAN_MODE);
235 DUMPREG(VP_SRC_H_POSITION);
236 DUMPREG(VP_SRC_V_POSITION);
237 DUMPREG(VP_SRC_WIDTH);
238 DUMPREG(VP_SRC_HEIGHT);
239 DUMPREG(VP_DST_H_POSITION);
240 DUMPREG(VP_DST_V_POSITION);
241 DUMPREG(VP_DST_WIDTH);
242 DUMPREG(VP_DST_HEIGHT);
249 static inline void vp_filter_set(struct mixer_resources *res,
250 int reg_id, const u8 *data, unsigned int size)
252 /* assure 4-byte align */
254 for (; size; size -= 4, reg_id += 4, data += 4) {
255 u32 val = (data[0] << 24) | (data[1] << 16) |
256 (data[2] << 8) | data[3];
257 vp_reg_write(res, reg_id, val);
261 static void vp_default_filter(struct mixer_resources *res)
263 vp_filter_set(res, VP_POLY8_Y0_LL,
264 filter_y_horiz_tap8, sizeof(filter_y_horiz_tap8));
265 vp_filter_set(res, VP_POLY4_Y0_LL,
266 filter_y_vert_tap4, sizeof(filter_y_vert_tap4));
267 vp_filter_set(res, VP_POLY4_C0_LL,
268 filter_cr_horiz_tap4, sizeof(filter_cr_horiz_tap4));
271 static void mixer_vsync_set_update(struct mixer_context *ctx, bool enable)
273 struct mixer_resources *res = &ctx->mixer_res;
275 /* block update on vsync */
276 mixer_reg_writemask(res, MXR_STATUS, enable ?
277 MXR_STATUS_SYNC_ENABLE : 0, MXR_STATUS_SYNC_ENABLE);
280 vp_reg_write(res, VP_SHADOW_UPDATE, enable ?
281 VP_SHADOW_UPDATE_ENABLE : 0);
284 static void mixer_cfg_scan(struct mixer_context *ctx, unsigned int height)
286 struct mixer_resources *res = &ctx->mixer_res;
289 /* choosing between interlace and progressive mode */
290 val = (ctx->interlace ? MXR_CFG_SCAN_INTERLACE :
291 MXR_CFG_SCAN_PROGRASSIVE);
293 if (ctx->mxr_ver != MXR_VER_128_0_0_184) {
294 /* choosing between proper HD and SD mode */
296 val |= MXR_CFG_SCAN_NTSC | MXR_CFG_SCAN_SD;
297 else if (height <= 576)
298 val |= MXR_CFG_SCAN_PAL | MXR_CFG_SCAN_SD;
299 else if (height <= 720)
300 val |= MXR_CFG_SCAN_HD_720 | MXR_CFG_SCAN_HD;
301 else if (height <= 1080)
302 val |= MXR_CFG_SCAN_HD_1080 | MXR_CFG_SCAN_HD;
304 val |= MXR_CFG_SCAN_HD_720 | MXR_CFG_SCAN_HD;
307 mixer_reg_writemask(res, MXR_CFG, val, MXR_CFG_SCAN_MASK);
310 static void mixer_cfg_rgb_fmt(struct mixer_context *ctx, unsigned int height)
312 struct mixer_resources *res = &ctx->mixer_res;
316 val = MXR_CFG_RGB601_0_255;
317 } else if (height == 576) {
318 val = MXR_CFG_RGB601_0_255;
319 } else if (height == 720) {
320 val = MXR_CFG_RGB709_16_235;
321 mixer_reg_write(res, MXR_CM_COEFF_Y,
322 (1 << 30) | (94 << 20) | (314 << 10) |
324 mixer_reg_write(res, MXR_CM_COEFF_CB,
325 (972 << 20) | (851 << 10) | (225 << 0));
326 mixer_reg_write(res, MXR_CM_COEFF_CR,
327 (225 << 20) | (820 << 10) | (1004 << 0));
328 } else if (height == 1080) {
329 val = MXR_CFG_RGB709_16_235;
330 mixer_reg_write(res, MXR_CM_COEFF_Y,
331 (1 << 30) | (94 << 20) | (314 << 10) |
333 mixer_reg_write(res, MXR_CM_COEFF_CB,
334 (972 << 20) | (851 << 10) | (225 << 0));
335 mixer_reg_write(res, MXR_CM_COEFF_CR,
336 (225 << 20) | (820 << 10) | (1004 << 0));
338 val = MXR_CFG_RGB709_16_235;
339 mixer_reg_write(res, MXR_CM_COEFF_Y,
340 (1 << 30) | (94 << 20) | (314 << 10) |
342 mixer_reg_write(res, MXR_CM_COEFF_CB,
343 (972 << 20) | (851 << 10) | (225 << 0));
344 mixer_reg_write(res, MXR_CM_COEFF_CR,
345 (225 << 20) | (820 << 10) | (1004 << 0));
348 mixer_reg_writemask(res, MXR_CFG, val, MXR_CFG_RGB_FMT_MASK);
351 static void mixer_cfg_layer(struct mixer_context *ctx, int win, bool enable)
353 struct mixer_resources *res = &ctx->mixer_res;
354 u32 val = enable ? ~0 : 0;
358 mixer_reg_writemask(res, MXR_CFG, val, MXR_CFG_GRP0_ENABLE);
361 mixer_reg_writemask(res, MXR_CFG, val, MXR_CFG_GRP1_ENABLE);
364 if (ctx->vp_enabled) {
365 vp_reg_writemask(res, VP_ENABLE, val, VP_ENABLE_ON);
366 mixer_reg_writemask(res, MXR_CFG, val,
373 static void mixer_run(struct mixer_context *ctx)
375 struct mixer_resources *res = &ctx->mixer_res;
377 mixer_reg_writemask(res, MXR_STATUS, ~0, MXR_STATUS_REG_RUN);
379 mixer_regs_dump(ctx);
382 static void mixer_stop(struct mixer_context *ctx)
384 struct mixer_resources *res = &ctx->mixer_res;
387 mixer_reg_writemask(res, MXR_STATUS, 0, MXR_STATUS_REG_RUN);
389 while (!(mixer_reg_read(res, MXR_STATUS) & MXR_STATUS_REG_IDLE) &&
391 usleep_range(10000, 12000);
393 mixer_regs_dump(ctx);
396 static void vp_video_buffer(struct mixer_context *ctx, int win)
398 struct mixer_resources *res = &ctx->mixer_res;
400 struct hdmi_win_data *win_data;
401 unsigned int x_ratio, y_ratio;
402 unsigned int buf_num = 1;
403 dma_addr_t luma_addr[2], chroma_addr[2];
404 bool tiled_mode = false;
405 bool crcb_mode = false;
408 win_data = &ctx->win_data[win];
410 switch (win_data->pixel_format) {
411 case DRM_FORMAT_NV12MT:
413 case DRM_FORMAT_NV12:
417 /* TODO: single buffer format NV12, NV21 */
419 /* ignore pixel format at disable time */
420 if (!win_data->dma_addr)
423 DRM_ERROR("pixel format for vp is wrong [%d].\n",
424 win_data->pixel_format);
428 /* scaling feature: (src << 16) / dst */
429 x_ratio = (win_data->src_width << 16) / win_data->crtc_width;
430 y_ratio = (win_data->src_height << 16) / win_data->crtc_height;
433 luma_addr[0] = win_data->dma_addr;
434 chroma_addr[0] = win_data->chroma_dma_addr;
436 luma_addr[0] = win_data->dma_addr;
437 chroma_addr[0] = win_data->dma_addr
438 + (win_data->fb_width * win_data->fb_height);
441 if (win_data->scan_flags & DRM_MODE_FLAG_INTERLACE) {
442 ctx->interlace = true;
444 luma_addr[1] = luma_addr[0] + 0x40;
445 chroma_addr[1] = chroma_addr[0] + 0x40;
447 luma_addr[1] = luma_addr[0] + win_data->fb_width;
448 chroma_addr[1] = chroma_addr[0] + win_data->fb_width;
451 ctx->interlace = false;
456 spin_lock_irqsave(&res->reg_slock, flags);
457 mixer_vsync_set_update(ctx, false);
459 /* interlace or progressive scan mode */
460 val = (ctx->interlace ? ~0 : 0);
461 vp_reg_writemask(res, VP_MODE, val, VP_MODE_LINE_SKIP);
464 val = (crcb_mode ? VP_MODE_NV21 : VP_MODE_NV12);
465 val |= (tiled_mode ? VP_MODE_MEM_TILED : VP_MODE_MEM_LINEAR);
466 vp_reg_writemask(res, VP_MODE, val, VP_MODE_FMT_MASK);
468 /* setting size of input image */
469 vp_reg_write(res, VP_IMG_SIZE_Y, VP_IMG_HSIZE(win_data->fb_width) |
470 VP_IMG_VSIZE(win_data->fb_height));
471 /* chroma height has to reduced by 2 to avoid chroma distorions */
472 vp_reg_write(res, VP_IMG_SIZE_C, VP_IMG_HSIZE(win_data->fb_width) |
473 VP_IMG_VSIZE(win_data->fb_height / 2));
475 vp_reg_write(res, VP_SRC_WIDTH, win_data->src_width);
476 vp_reg_write(res, VP_SRC_HEIGHT, win_data->src_height);
477 vp_reg_write(res, VP_SRC_H_POSITION,
478 VP_SRC_H_POSITION_VAL(win_data->fb_x));
479 vp_reg_write(res, VP_SRC_V_POSITION, win_data->fb_y);
481 vp_reg_write(res, VP_DST_WIDTH, win_data->crtc_width);
482 vp_reg_write(res, VP_DST_H_POSITION, win_data->crtc_x);
483 if (ctx->interlace) {
484 vp_reg_write(res, VP_DST_HEIGHT, win_data->crtc_height / 2);
485 vp_reg_write(res, VP_DST_V_POSITION, win_data->crtc_y / 2);
487 vp_reg_write(res, VP_DST_HEIGHT, win_data->crtc_height);
488 vp_reg_write(res, VP_DST_V_POSITION, win_data->crtc_y);
491 vp_reg_write(res, VP_H_RATIO, x_ratio);
492 vp_reg_write(res, VP_V_RATIO, y_ratio);
494 vp_reg_write(res, VP_ENDIAN_MODE, VP_ENDIAN_MODE_LITTLE);
496 /* set buffer address to vp */
497 vp_reg_write(res, VP_TOP_Y_PTR, luma_addr[0]);
498 vp_reg_write(res, VP_BOT_Y_PTR, luma_addr[1]);
499 vp_reg_write(res, VP_TOP_C_PTR, chroma_addr[0]);
500 vp_reg_write(res, VP_BOT_C_PTR, chroma_addr[1]);
502 mixer_cfg_scan(ctx, win_data->mode_height);
503 mixer_cfg_rgb_fmt(ctx, win_data->mode_height);
504 mixer_cfg_layer(ctx, win, true);
507 mixer_vsync_set_update(ctx, true);
508 spin_unlock_irqrestore(&res->reg_slock, flags);
513 static void mixer_layer_update(struct mixer_context *ctx)
515 struct mixer_resources *res = &ctx->mixer_res;
517 mixer_reg_writemask(res, MXR_CFG, ~0, MXR_CFG_LAYER_UPDATE);
520 static void mixer_graph_buffer(struct mixer_context *ctx, int win)
522 struct mixer_resources *res = &ctx->mixer_res;
524 struct hdmi_win_data *win_data;
525 unsigned int x_ratio, y_ratio;
526 unsigned int src_x_offset, src_y_offset, dst_x_offset, dst_y_offset;
531 win_data = &ctx->win_data[win];
538 switch (win_data->bpp) {
549 /* 2x scaling feature */
553 dst_x_offset = win_data->crtc_x;
554 dst_y_offset = win_data->crtc_y;
556 /* converting dma address base and source offset */
557 dma_addr = win_data->dma_addr
558 + (win_data->fb_x * win_data->bpp >> 3)
559 + (win_data->fb_y * win_data->fb_width * win_data->bpp >> 3);
563 if (win_data->scan_flags & DRM_MODE_FLAG_INTERLACE)
564 ctx->interlace = true;
566 ctx->interlace = false;
568 spin_lock_irqsave(&res->reg_slock, flags);
569 mixer_vsync_set_update(ctx, false);
572 mixer_reg_writemask(res, MXR_GRAPHIC_CFG(win),
573 MXR_GRP_CFG_FORMAT_VAL(fmt), MXR_GRP_CFG_FORMAT_MASK);
576 mixer_reg_write(res, MXR_GRAPHIC_SPAN(win), win_data->fb_width);
578 /* setup display size */
579 if (ctx->mxr_ver == MXR_VER_128_0_0_184 &&
580 win == MIXER_DEFAULT_WIN) {
581 val = MXR_MXR_RES_HEIGHT(win_data->fb_height);
582 val |= MXR_MXR_RES_WIDTH(win_data->fb_width);
583 mixer_reg_write(res, MXR_RESOLUTION, val);
586 val = MXR_GRP_WH_WIDTH(win_data->crtc_width);
587 val |= MXR_GRP_WH_HEIGHT(win_data->crtc_height);
588 val |= MXR_GRP_WH_H_SCALE(x_ratio);
589 val |= MXR_GRP_WH_V_SCALE(y_ratio);
590 mixer_reg_write(res, MXR_GRAPHIC_WH(win), val);
592 /* setup offsets in source image */
593 val = MXR_GRP_SXY_SX(src_x_offset);
594 val |= MXR_GRP_SXY_SY(src_y_offset);
595 mixer_reg_write(res, MXR_GRAPHIC_SXY(win), val);
597 /* setup offsets in display image */
598 val = MXR_GRP_DXY_DX(dst_x_offset);
599 val |= MXR_GRP_DXY_DY(dst_y_offset);
600 mixer_reg_write(res, MXR_GRAPHIC_DXY(win), val);
602 /* set buffer address to mixer */
603 mixer_reg_write(res, MXR_GRAPHIC_BASE(win), dma_addr);
605 mixer_cfg_scan(ctx, win_data->mode_height);
606 mixer_cfg_rgb_fmt(ctx, win_data->mode_height);
607 mixer_cfg_layer(ctx, win, true);
609 /* layer update mandatory for mixer 16.0.33.0 */
610 if (ctx->mxr_ver == MXR_VER_16_0_33_0 ||
611 ctx->mxr_ver == MXR_VER_128_0_0_184)
612 mixer_layer_update(ctx);
616 mixer_vsync_set_update(ctx, true);
617 spin_unlock_irqrestore(&res->reg_slock, flags);
620 static void vp_win_reset(struct mixer_context *ctx)
622 struct mixer_resources *res = &ctx->mixer_res;
625 vp_reg_write(res, VP_SRESET, VP_SRESET_PROCESSING);
626 for (tries = 100; tries; --tries) {
627 /* waiting until VP_SRESET_PROCESSING is 0 */
628 if (~vp_reg_read(res, VP_SRESET) & VP_SRESET_PROCESSING)
630 usleep_range(10000, 12000);
632 WARN(tries == 0, "failed to reset Video Processor\n");
635 static void mixer_win_reset(struct mixer_context *ctx)
637 struct mixer_resources *res = &ctx->mixer_res;
639 u32 val; /* value stored to register */
641 spin_lock_irqsave(&res->reg_slock, flags);
642 mixer_vsync_set_update(ctx, false);
644 mixer_reg_writemask(res, MXR_CFG, MXR_CFG_DST_HDMI, MXR_CFG_DST_MASK);
646 /* set output in RGB888 mode */
647 mixer_reg_writemask(res, MXR_CFG, MXR_CFG_OUT_RGB888, MXR_CFG_OUT_MASK);
649 /* 16 beat burst in DMA */
650 mixer_reg_writemask(res, MXR_STATUS, MXR_STATUS_16_BURST,
651 MXR_STATUS_BURST_MASK);
653 /* setting default layer priority: layer1 > layer0 > video
654 * because typical usage scenario would be
656 * layer0 - framebuffer
657 * video - video overlay
659 val = MXR_LAYER_CFG_GRP1_VAL(3);
660 val |= MXR_LAYER_CFG_GRP0_VAL(2);
662 val |= MXR_LAYER_CFG_VP_VAL(1);
663 mixer_reg_write(res, MXR_LAYER_CFG, val);
665 /* setting background color */
666 mixer_reg_write(res, MXR_BG_COLOR0, 0x008080);
667 mixer_reg_write(res, MXR_BG_COLOR1, 0x008080);
668 mixer_reg_write(res, MXR_BG_COLOR2, 0x008080);
670 /* setting graphical layers */
671 val = MXR_GRP_CFG_COLOR_KEY_DISABLE; /* no blank key */
672 val |= MXR_GRP_CFG_WIN_BLEND_EN;
673 val |= MXR_GRP_CFG_ALPHA_VAL(0xff); /* non-transparent alpha */
675 /* Don't blend layer 0 onto the mixer background */
676 mixer_reg_write(res, MXR_GRAPHIC_CFG(0), val);
678 /* Blend layer 1 into layer 0 */
679 val |= MXR_GRP_CFG_BLEND_PRE_MUL;
680 val |= MXR_GRP_CFG_PIXEL_BLEND_EN;
681 mixer_reg_write(res, MXR_GRAPHIC_CFG(1), val);
683 /* setting video layers */
684 val = MXR_GRP_CFG_ALPHA_VAL(0);
685 mixer_reg_write(res, MXR_VIDEO_CFG, val);
687 if (ctx->vp_enabled) {
688 /* configuration of Video Processor Registers */
690 vp_default_filter(res);
693 /* disable all layers */
694 mixer_reg_writemask(res, MXR_CFG, 0, MXR_CFG_GRP0_ENABLE);
695 mixer_reg_writemask(res, MXR_CFG, 0, MXR_CFG_GRP1_ENABLE);
697 mixer_reg_writemask(res, MXR_CFG, 0, MXR_CFG_VP_ENABLE);
699 mixer_vsync_set_update(ctx, true);
700 spin_unlock_irqrestore(&res->reg_slock, flags);
703 static irqreturn_t mixer_irq_handler(int irq, void *arg)
705 struct mixer_context *ctx = arg;
706 struct mixer_resources *res = &ctx->mixer_res;
707 u32 val, base, shadow;
709 spin_lock(&res->reg_slock);
711 /* read interrupt status for handling and clearing flags for VSYNC */
712 val = mixer_reg_read(res, MXR_INT_STATUS);
715 if (val & MXR_INT_STATUS_VSYNC) {
716 /* interlace scan need to check shadow register */
717 if (ctx->interlace) {
718 base = mixer_reg_read(res, MXR_GRAPHIC_BASE(0));
719 shadow = mixer_reg_read(res, MXR_GRAPHIC_BASE_S(0));
723 base = mixer_reg_read(res, MXR_GRAPHIC_BASE(1));
724 shadow = mixer_reg_read(res, MXR_GRAPHIC_BASE_S(1));
729 drm_handle_vblank(ctx->drm_dev, ctx->pipe);
730 exynos_drm_crtc_finish_pageflip(ctx->drm_dev, ctx->pipe);
732 /* set wait vsync event to zero and wake up queue. */
733 if (atomic_read(&ctx->wait_vsync_event)) {
734 atomic_set(&ctx->wait_vsync_event, 0);
735 wake_up(&ctx->wait_vsync_queue);
740 /* clear interrupts */
741 if (~val & MXR_INT_EN_VSYNC) {
742 /* vsync interrupt use different bit for read and clear */
743 val &= ~MXR_INT_EN_VSYNC;
744 val |= MXR_INT_CLEAR_VSYNC;
746 mixer_reg_write(res, MXR_INT_STATUS, val);
748 spin_unlock(&res->reg_slock);
753 static int mixer_resources_init(struct mixer_context *mixer_ctx)
755 struct device *dev = &mixer_ctx->pdev->dev;
756 struct mixer_resources *mixer_res = &mixer_ctx->mixer_res;
757 struct resource *res;
760 spin_lock_init(&mixer_res->reg_slock);
762 mixer_res->mixer = devm_clk_get(dev, "mixer");
763 if (IS_ERR(mixer_res->mixer)) {
764 dev_err(dev, "failed to get clock 'mixer'\n");
768 mixer_res->sclk_hdmi = devm_clk_get(dev, "sclk_hdmi");
769 if (IS_ERR(mixer_res->sclk_hdmi)) {
770 dev_err(dev, "failed to get clock 'sclk_hdmi'\n");
773 res = platform_get_resource(mixer_ctx->pdev, IORESOURCE_MEM, 0);
775 dev_err(dev, "get memory resource failed.\n");
779 mixer_res->mixer_regs = devm_ioremap(dev, res->start,
781 if (mixer_res->mixer_regs == NULL) {
782 dev_err(dev, "register mapping failed.\n");
786 res = platform_get_resource(mixer_ctx->pdev, IORESOURCE_IRQ, 0);
788 dev_err(dev, "get interrupt resource failed.\n");
792 ret = devm_request_irq(dev, res->start, mixer_irq_handler,
793 0, "drm_mixer", mixer_ctx);
795 dev_err(dev, "request interrupt failed.\n");
798 mixer_res->irq = res->start;
803 static int vp_resources_init(struct mixer_context *mixer_ctx)
805 struct device *dev = &mixer_ctx->pdev->dev;
806 struct mixer_resources *mixer_res = &mixer_ctx->mixer_res;
807 struct resource *res;
809 mixer_res->vp = devm_clk_get(dev, "vp");
810 if (IS_ERR(mixer_res->vp)) {
811 dev_err(dev, "failed to get clock 'vp'\n");
815 if (mixer_ctx->has_sclk) {
816 mixer_res->sclk_mixer = devm_clk_get(dev, "sclk_mixer");
817 if (IS_ERR(mixer_res->sclk_mixer)) {
818 dev_err(dev, "failed to get clock 'sclk_mixer'\n");
821 mixer_res->mout_mixer = devm_clk_get(dev, "mout_mixer");
822 if (IS_ERR(mixer_res->mout_mixer)) {
823 dev_err(dev, "failed to get clock 'mout_mixer'\n");
827 if (mixer_res->sclk_hdmi && mixer_res->mout_mixer)
828 clk_set_parent(mixer_res->mout_mixer,
829 mixer_res->sclk_hdmi);
832 res = platform_get_resource(mixer_ctx->pdev, IORESOURCE_MEM, 1);
834 dev_err(dev, "get memory resource failed.\n");
838 mixer_res->vp_regs = devm_ioremap(dev, res->start,
840 if (mixer_res->vp_regs == NULL) {
841 dev_err(dev, "register mapping failed.\n");
848 static int mixer_initialize(struct exynos_drm_manager *mgr,
849 struct drm_device *drm_dev)
852 struct mixer_context *mixer_ctx = mgr->ctx;
853 struct exynos_drm_private *priv;
854 priv = drm_dev->dev_private;
856 mgr->drm_dev = mixer_ctx->drm_dev = drm_dev;
857 mgr->pipe = mixer_ctx->pipe = priv->pipe++;
859 /* acquire resources: regs, irqs, clocks */
860 ret = mixer_resources_init(mixer_ctx);
862 DRM_ERROR("mixer_resources_init failed ret=%d\n", ret);
866 if (mixer_ctx->vp_enabled) {
867 /* acquire vp resources: regs, irqs, clocks */
868 ret = vp_resources_init(mixer_ctx);
870 DRM_ERROR("vp_resources_init failed ret=%d\n", ret);
875 if (!is_drm_iommu_supported(mixer_ctx->drm_dev))
878 return drm_iommu_attach_device(mixer_ctx->drm_dev, mixer_ctx->dev);
881 static void mixer_mgr_remove(struct exynos_drm_manager *mgr)
883 struct mixer_context *mixer_ctx = mgr->ctx;
885 if (is_drm_iommu_supported(mixer_ctx->drm_dev))
886 drm_iommu_detach_device(mixer_ctx->drm_dev, mixer_ctx->dev);
889 static int mixer_enable_vblank(struct exynos_drm_manager *mgr)
891 struct mixer_context *mixer_ctx = mgr->ctx;
892 struct mixer_resources *res = &mixer_ctx->mixer_res;
894 if (!mixer_ctx->powered) {
895 mixer_ctx->int_en |= MXR_INT_EN_VSYNC;
899 /* enable vsync interrupt */
900 mixer_reg_writemask(res, MXR_INT_EN, MXR_INT_EN_VSYNC,
906 static void mixer_disable_vblank(struct exynos_drm_manager *mgr)
908 struct mixer_context *mixer_ctx = mgr->ctx;
909 struct mixer_resources *res = &mixer_ctx->mixer_res;
911 /* disable vsync interrupt */
912 mixer_reg_writemask(res, MXR_INT_EN, 0, MXR_INT_EN_VSYNC);
915 static void mixer_win_mode_set(struct exynos_drm_manager *mgr,
916 struct exynos_drm_overlay *overlay)
918 struct mixer_context *mixer_ctx = mgr->ctx;
919 struct hdmi_win_data *win_data;
923 DRM_ERROR("overlay is NULL\n");
927 DRM_DEBUG_KMS("set [%d]x[%d] at (%d,%d) to [%d]x[%d] at (%d,%d)\n",
928 overlay->fb_width, overlay->fb_height,
929 overlay->fb_x, overlay->fb_y,
930 overlay->crtc_width, overlay->crtc_height,
931 overlay->crtc_x, overlay->crtc_y);
934 if (win == DEFAULT_ZPOS)
935 win = MIXER_DEFAULT_WIN;
937 if (win < 0 || win >= MIXER_WIN_NR) {
938 DRM_ERROR("mixer window[%d] is wrong\n", win);
942 win_data = &mixer_ctx->win_data[win];
944 win_data->dma_addr = overlay->dma_addr[0];
945 win_data->chroma_dma_addr = overlay->dma_addr[1];
946 win_data->pixel_format = overlay->pixel_format;
947 win_data->bpp = overlay->bpp;
949 win_data->crtc_x = overlay->crtc_x;
950 win_data->crtc_y = overlay->crtc_y;
951 win_data->crtc_width = overlay->crtc_width;
952 win_data->crtc_height = overlay->crtc_height;
954 win_data->fb_x = overlay->fb_x;
955 win_data->fb_y = overlay->fb_y;
956 win_data->fb_width = overlay->fb_width;
957 win_data->fb_height = overlay->fb_height;
958 win_data->src_width = overlay->src_width;
959 win_data->src_height = overlay->src_height;
961 win_data->mode_width = overlay->mode_width;
962 win_data->mode_height = overlay->mode_height;
964 win_data->scan_flags = overlay->scan_flag;
967 static void mixer_win_commit(struct exynos_drm_manager *mgr, int zpos)
969 struct mixer_context *mixer_ctx = mgr->ctx;
970 int win = zpos == DEFAULT_ZPOS ? MIXER_DEFAULT_WIN : zpos;
972 DRM_DEBUG_KMS("win: %d\n", win);
974 mutex_lock(&mixer_ctx->mixer_mutex);
975 if (!mixer_ctx->powered) {
976 mutex_unlock(&mixer_ctx->mixer_mutex);
979 mutex_unlock(&mixer_ctx->mixer_mutex);
981 if (win > 1 && mixer_ctx->vp_enabled)
982 vp_video_buffer(mixer_ctx, win);
984 mixer_graph_buffer(mixer_ctx, win);
986 mixer_ctx->win_data[win].enabled = true;
989 static void mixer_win_disable(struct exynos_drm_manager *mgr, int zpos)
991 struct mixer_context *mixer_ctx = mgr->ctx;
992 struct mixer_resources *res = &mixer_ctx->mixer_res;
993 int win = zpos == DEFAULT_ZPOS ? MIXER_DEFAULT_WIN : zpos;
996 DRM_DEBUG_KMS("win: %d\n", win);
998 mutex_lock(&mixer_ctx->mixer_mutex);
999 if (!mixer_ctx->powered) {
1000 mutex_unlock(&mixer_ctx->mixer_mutex);
1001 mixer_ctx->win_data[win].resume = false;
1004 mutex_unlock(&mixer_ctx->mixer_mutex);
1006 spin_lock_irqsave(&res->reg_slock, flags);
1007 mixer_vsync_set_update(mixer_ctx, false);
1009 mixer_cfg_layer(mixer_ctx, win, false);
1011 mixer_vsync_set_update(mixer_ctx, true);
1012 spin_unlock_irqrestore(&res->reg_slock, flags);
1014 mixer_ctx->win_data[win].enabled = false;
1017 static void mixer_wait_for_vblank(struct exynos_drm_manager *mgr)
1019 struct mixer_context *mixer_ctx = mgr->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 drm_vblank_get(mgr->crtc->dev, mixer_ctx->pipe);
1030 atomic_set(&mixer_ctx->wait_vsync_event, 1);
1033 * wait for MIXER to signal VSYNC interrupt or return after
1034 * timeout which is set to 50ms (refresh rate of 20).
1036 if (!wait_event_timeout(mixer_ctx->wait_vsync_queue,
1037 !atomic_read(&mixer_ctx->wait_vsync_event),
1039 DRM_DEBUG_KMS("vblank wait timed out.\n");
1041 drm_vblank_put(mgr->crtc->dev, mixer_ctx->pipe);
1044 static void mixer_window_suspend(struct exynos_drm_manager *mgr)
1046 struct mixer_context *ctx = mgr->ctx;
1047 struct hdmi_win_data *win_data;
1050 for (i = 0; i < MIXER_WIN_NR; i++) {
1051 win_data = &ctx->win_data[i];
1052 win_data->resume = win_data->enabled;
1053 mixer_win_disable(mgr, i);
1055 mixer_wait_for_vblank(mgr);
1058 static void mixer_window_resume(struct exynos_drm_manager *mgr)
1060 struct mixer_context *ctx = mgr->ctx;
1061 struct hdmi_win_data *win_data;
1064 for (i = 0; i < MIXER_WIN_NR; i++) {
1065 win_data = &ctx->win_data[i];
1066 win_data->enabled = win_data->resume;
1067 win_data->resume = false;
1068 if (win_data->enabled)
1069 mixer_win_commit(mgr, i);
1073 static void mixer_poweron(struct exynos_drm_manager *mgr)
1075 struct mixer_context *ctx = mgr->ctx;
1076 struct mixer_resources *res = &ctx->mixer_res;
1078 mutex_lock(&ctx->mixer_mutex);
1080 mutex_unlock(&ctx->mixer_mutex);
1084 mutex_unlock(&ctx->mixer_mutex);
1086 pm_runtime_get_sync(ctx->dev);
1088 clk_prepare_enable(res->mixer);
1089 if (ctx->vp_enabled) {
1090 clk_prepare_enable(res->vp);
1092 clk_prepare_enable(res->sclk_mixer);
1095 mutex_lock(&ctx->mixer_mutex);
1096 ctx->powered = true;
1097 mutex_unlock(&ctx->mixer_mutex);
1099 mixer_reg_writemask(res, MXR_STATUS, ~0, MXR_STATUS_SOFT_RESET);
1101 mixer_reg_write(res, MXR_INT_EN, ctx->int_en);
1102 mixer_win_reset(ctx);
1104 mixer_window_resume(mgr);
1107 static void mixer_poweroff(struct exynos_drm_manager *mgr)
1109 struct mixer_context *ctx = mgr->ctx;
1110 struct mixer_resources *res = &ctx->mixer_res;
1112 mutex_lock(&ctx->mixer_mutex);
1113 if (!ctx->powered) {
1114 mutex_unlock(&ctx->mixer_mutex);
1117 mutex_unlock(&ctx->mixer_mutex);
1120 mixer_window_suspend(mgr);
1122 ctx->int_en = mixer_reg_read(res, MXR_INT_EN);
1124 mutex_lock(&ctx->mixer_mutex);
1125 ctx->powered = false;
1126 mutex_unlock(&ctx->mixer_mutex);
1128 clk_disable_unprepare(res->mixer);
1129 if (ctx->vp_enabled) {
1130 clk_disable_unprepare(res->vp);
1132 clk_disable_unprepare(res->sclk_mixer);
1135 pm_runtime_put_sync(ctx->dev);
1138 static void mixer_dpms(struct exynos_drm_manager *mgr, int mode)
1141 case DRM_MODE_DPMS_ON:
1144 case DRM_MODE_DPMS_STANDBY:
1145 case DRM_MODE_DPMS_SUSPEND:
1146 case DRM_MODE_DPMS_OFF:
1147 mixer_poweroff(mgr);
1150 DRM_DEBUG_KMS("unknown dpms mode: %d\n", mode);
1155 /* Only valid for Mixer version 16.0.33.0 */
1156 int mixer_check_mode(struct drm_display_mode *mode)
1163 DRM_DEBUG_KMS("xres=%d, yres=%d, refresh=%d, intl=%d\n",
1164 mode->hdisplay, mode->vdisplay, mode->vrefresh,
1165 (mode->flags & DRM_MODE_FLAG_INTERLACE) ? 1 : 0);
1167 if ((w >= 464 && w <= 720 && h >= 261 && h <= 576) ||
1168 (w >= 1024 && w <= 1280 && h >= 576 && h <= 720) ||
1169 (w >= 1664 && w <= 1920 && h >= 936 && h <= 1080))
1175 static struct exynos_drm_manager_ops mixer_manager_ops = {
1177 .enable_vblank = mixer_enable_vblank,
1178 .disable_vblank = mixer_disable_vblank,
1179 .wait_for_vblank = mixer_wait_for_vblank,
1180 .win_mode_set = mixer_win_mode_set,
1181 .win_commit = mixer_win_commit,
1182 .win_disable = mixer_win_disable,
1185 static struct exynos_drm_manager mixer_manager = {
1186 .type = EXYNOS_DISPLAY_TYPE_HDMI,
1187 .ops = &mixer_manager_ops,
1190 static struct mixer_drv_data exynos5420_mxr_drv_data = {
1191 .version = MXR_VER_128_0_0_184,
1195 static struct mixer_drv_data exynos5250_mxr_drv_data = {
1196 .version = MXR_VER_16_0_33_0,
1200 static struct mixer_drv_data exynos4212_mxr_drv_data = {
1201 .version = MXR_VER_0_0_0_16,
1205 static struct mixer_drv_data exynos4210_mxr_drv_data = {
1206 .version = MXR_VER_0_0_0_16,
1211 static struct platform_device_id mixer_driver_types[] = {
1213 .name = "s5p-mixer",
1214 .driver_data = (unsigned long)&exynos4210_mxr_drv_data,
1216 .name = "exynos5-mixer",
1217 .driver_data = (unsigned long)&exynos5250_mxr_drv_data,
1223 static struct of_device_id mixer_match_types[] = {
1225 .compatible = "samsung,exynos4210-mixer",
1226 .data = &exynos4210_mxr_drv_data,
1228 .compatible = "samsung,exynos4212-mixer",
1229 .data = &exynos4212_mxr_drv_data,
1231 .compatible = "samsung,exynos5-mixer",
1232 .data = &exynos5250_mxr_drv_data,
1234 .compatible = "samsung,exynos5250-mixer",
1235 .data = &exynos5250_mxr_drv_data,
1237 .compatible = "samsung,exynos5420-mixer",
1238 .data = &exynos5420_mxr_drv_data,
1243 MODULE_DEVICE_TABLE(of, mixer_match_types);
1245 static int mixer_bind(struct device *dev, struct device *manager, void *data)
1247 struct platform_device *pdev = to_platform_device(dev);
1248 struct drm_device *drm_dev = data;
1249 struct mixer_context *ctx;
1250 struct mixer_drv_data *drv;
1253 dev_info(dev, "probe start\n");
1255 ctx = devm_kzalloc(&pdev->dev, sizeof(*ctx), GFP_KERNEL);
1257 DRM_ERROR("failed to alloc mixer context.\n");
1261 mutex_init(&ctx->mixer_mutex);
1264 const struct of_device_id *match;
1265 match = of_match_node(mixer_match_types, dev->of_node);
1266 drv = (struct mixer_drv_data *)match->data;
1268 drv = (struct mixer_drv_data *)
1269 platform_get_device_id(pdev)->driver_data;
1274 ctx->vp_enabled = drv->is_vp_enabled;
1275 ctx->has_sclk = drv->has_sclk;
1276 ctx->mxr_ver = drv->version;
1277 init_waitqueue_head(&ctx->wait_vsync_queue);
1278 atomic_set(&ctx->wait_vsync_event, 0);
1280 mixer_manager.ctx = ctx;
1281 ret = mixer_initialize(&mixer_manager, drm_dev);
1285 platform_set_drvdata(pdev, &mixer_manager);
1286 ret = exynos_drm_crtc_create(&mixer_manager);
1288 mixer_mgr_remove(&mixer_manager);
1292 pm_runtime_enable(dev);
1297 static void mixer_unbind(struct device *dev, struct device *master, void *data)
1299 struct exynos_drm_manager *mgr = dev_get_drvdata(dev);
1300 struct drm_crtc *crtc = mgr->crtc;
1302 dev_info(dev, "remove successful\n");
1304 mixer_mgr_remove(mgr);
1306 pm_runtime_disable(dev);
1308 crtc->funcs->destroy(crtc);
1311 static const struct component_ops mixer_component_ops = {
1313 .unbind = mixer_unbind,
1316 static int mixer_probe(struct platform_device *pdev)
1320 ret = exynos_drm_component_add(&pdev->dev, EXYNOS_DEVICE_TYPE_CRTC,
1321 mixer_manager.type);
1325 ret = component_add(&pdev->dev, &mixer_component_ops);
1327 exynos_drm_component_del(&pdev->dev, EXYNOS_DEVICE_TYPE_CRTC);
1332 static int mixer_remove(struct platform_device *pdev)
1334 component_del(&pdev->dev, &mixer_component_ops);
1335 exynos_drm_component_del(&pdev->dev, EXYNOS_DEVICE_TYPE_CRTC);
1340 struct platform_driver mixer_driver = {
1342 .name = "exynos-mixer",
1343 .owner = THIS_MODULE,
1344 .of_match_table = mixer_match_types,
1346 .probe = mixer_probe,
1347 .remove = mixer_remove,
1348 .id_table = mixer_driver_types,