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/module.h>
27 #include <linux/platform_device.h>
28 #include <linux/interrupt.h>
29 #include <linux/irq.h>
30 #include <linux/delay.h>
31 #include <linux/pm_runtime.h>
32 #include <linux/clk.h>
33 #include <linux/regulator/consumer.h>
35 #include <drm/exynos_drm.h>
37 #include "exynos_drm_drv.h"
38 #include "exynos_drm_hdmi.h"
39 #include "exynos_drm_iommu.h"
41 #define get_mixer_context(dev) platform_get_drvdata(to_platform_device(dev))
43 struct hdmi_win_data {
46 dma_addr_t chroma_dma_addr;
47 void __iomem *chroma_vaddr;
48 uint32_t pixel_format;
52 unsigned int crtc_width;
53 unsigned int crtc_height;
56 unsigned int fb_width;
57 unsigned int fb_height;
58 unsigned int src_width;
59 unsigned int src_height;
60 unsigned int mode_width;
61 unsigned int mode_height;
62 unsigned int scan_flags;
67 struct mixer_resources {
69 void __iomem *mixer_regs;
70 void __iomem *vp_regs;
74 struct clk *sclk_mixer;
75 struct clk *sclk_hdmi;
79 enum mixer_version_id {
84 struct mixer_context {
86 struct drm_device *drm_dev;
93 struct mutex mixer_mutex;
94 struct mixer_resources mixer_res;
95 struct hdmi_win_data win_data[MIXER_WIN_NR];
96 enum mixer_version_id mxr_ver;
98 wait_queue_head_t wait_vsync_queue;
99 atomic_t wait_vsync_event;
102 struct mixer_drv_data {
103 enum mixer_version_id version;
107 static const u8 filter_y_horiz_tap8[] = {
108 0, -1, -1, -1, -1, -1, -1, -1,
109 -1, -1, -1, -1, -1, 0, 0, 0,
110 0, 2, 4, 5, 6, 6, 6, 6,
111 6, 5, 5, 4, 3, 2, 1, 1,
112 0, -6, -12, -16, -18, -20, -21, -20,
113 -20, -18, -16, -13, -10, -8, -5, -2,
114 127, 126, 125, 121, 114, 107, 99, 89,
115 79, 68, 57, 46, 35, 25, 16, 8,
118 static const u8 filter_y_vert_tap4[] = {
119 0, -3, -6, -8, -8, -8, -8, -7,
120 -6, -5, -4, -3, -2, -1, -1, 0,
121 127, 126, 124, 118, 111, 102, 92, 81,
122 70, 59, 48, 37, 27, 19, 11, 5,
123 0, 5, 11, 19, 27, 37, 48, 59,
124 70, 81, 92, 102, 111, 118, 124, 126,
125 0, 0, -1, -1, -2, -3, -4, -5,
126 -6, -7, -8, -8, -8, -8, -6, -3,
129 static const u8 filter_cr_horiz_tap4[] = {
130 0, -3, -6, -8, -8, -8, -8, -7,
131 -6, -5, -4, -3, -2, -1, -1, 0,
132 127, 126, 124, 118, 111, 102, 92, 81,
133 70, 59, 48, 37, 27, 19, 11, 5,
136 static inline u32 vp_reg_read(struct mixer_resources *res, u32 reg_id)
138 return readl(res->vp_regs + reg_id);
141 static inline void vp_reg_write(struct mixer_resources *res, u32 reg_id,
144 writel(val, res->vp_regs + reg_id);
147 static inline void vp_reg_writemask(struct mixer_resources *res, u32 reg_id,
150 u32 old = vp_reg_read(res, reg_id);
152 val = (val & mask) | (old & ~mask);
153 writel(val, res->vp_regs + reg_id);
156 static inline u32 mixer_reg_read(struct mixer_resources *res, u32 reg_id)
158 return readl(res->mixer_regs + reg_id);
161 static inline void mixer_reg_write(struct mixer_resources *res, u32 reg_id,
164 writel(val, res->mixer_regs + reg_id);
167 static inline void mixer_reg_writemask(struct mixer_resources *res,
168 u32 reg_id, u32 val, u32 mask)
170 u32 old = mixer_reg_read(res, reg_id);
172 val = (val & mask) | (old & ~mask);
173 writel(val, res->mixer_regs + reg_id);
176 static void mixer_regs_dump(struct mixer_context *ctx)
178 #define DUMPREG(reg_id) \
180 DRM_DEBUG_KMS(#reg_id " = %08x\n", \
181 (u32)readl(ctx->mixer_res.mixer_regs + reg_id)); \
187 DUMPREG(MXR_INT_STATUS);
189 DUMPREG(MXR_LAYER_CFG);
190 DUMPREG(MXR_VIDEO_CFG);
192 DUMPREG(MXR_GRAPHIC0_CFG);
193 DUMPREG(MXR_GRAPHIC0_BASE);
194 DUMPREG(MXR_GRAPHIC0_SPAN);
195 DUMPREG(MXR_GRAPHIC0_WH);
196 DUMPREG(MXR_GRAPHIC0_SXY);
197 DUMPREG(MXR_GRAPHIC0_DXY);
199 DUMPREG(MXR_GRAPHIC1_CFG);
200 DUMPREG(MXR_GRAPHIC1_BASE);
201 DUMPREG(MXR_GRAPHIC1_SPAN);
202 DUMPREG(MXR_GRAPHIC1_WH);
203 DUMPREG(MXR_GRAPHIC1_SXY);
204 DUMPREG(MXR_GRAPHIC1_DXY);
208 static void vp_regs_dump(struct mixer_context *ctx)
210 #define DUMPREG(reg_id) \
212 DRM_DEBUG_KMS(#reg_id " = %08x\n", \
213 (u32) readl(ctx->mixer_res.vp_regs + reg_id)); \
218 DUMPREG(VP_SHADOW_UPDATE);
219 DUMPREG(VP_FIELD_ID);
221 DUMPREG(VP_IMG_SIZE_Y);
222 DUMPREG(VP_IMG_SIZE_C);
223 DUMPREG(VP_PER_RATE_CTRL);
224 DUMPREG(VP_TOP_Y_PTR);
225 DUMPREG(VP_BOT_Y_PTR);
226 DUMPREG(VP_TOP_C_PTR);
227 DUMPREG(VP_BOT_C_PTR);
228 DUMPREG(VP_ENDIAN_MODE);
229 DUMPREG(VP_SRC_H_POSITION);
230 DUMPREG(VP_SRC_V_POSITION);
231 DUMPREG(VP_SRC_WIDTH);
232 DUMPREG(VP_SRC_HEIGHT);
233 DUMPREG(VP_DST_H_POSITION);
234 DUMPREG(VP_DST_V_POSITION);
235 DUMPREG(VP_DST_WIDTH);
236 DUMPREG(VP_DST_HEIGHT);
243 static inline void vp_filter_set(struct mixer_resources *res,
244 int reg_id, const u8 *data, unsigned int size)
246 /* assure 4-byte align */
248 for (; size; size -= 4, reg_id += 4, data += 4) {
249 u32 val = (data[0] << 24) | (data[1] << 16) |
250 (data[2] << 8) | data[3];
251 vp_reg_write(res, reg_id, val);
255 static void vp_default_filter(struct mixer_resources *res)
257 vp_filter_set(res, VP_POLY8_Y0_LL,
258 filter_y_horiz_tap8, sizeof(filter_y_horiz_tap8));
259 vp_filter_set(res, VP_POLY4_Y0_LL,
260 filter_y_vert_tap4, sizeof(filter_y_vert_tap4));
261 vp_filter_set(res, VP_POLY4_C0_LL,
262 filter_cr_horiz_tap4, sizeof(filter_cr_horiz_tap4));
265 static void mixer_vsync_set_update(struct mixer_context *ctx, bool enable)
267 struct mixer_resources *res = &ctx->mixer_res;
269 /* block update on vsync */
270 mixer_reg_writemask(res, MXR_STATUS, enable ?
271 MXR_STATUS_SYNC_ENABLE : 0, MXR_STATUS_SYNC_ENABLE);
274 vp_reg_write(res, VP_SHADOW_UPDATE, enable ?
275 VP_SHADOW_UPDATE_ENABLE : 0);
278 static void mixer_cfg_scan(struct mixer_context *ctx, unsigned int height)
280 struct mixer_resources *res = &ctx->mixer_res;
283 /* choosing between interlace and progressive mode */
284 val = (ctx->interlace ? MXR_CFG_SCAN_INTERLACE :
285 MXR_CFG_SCAN_PROGRASSIVE);
287 /* choosing between porper HD and SD mode */
289 val |= MXR_CFG_SCAN_NTSC | MXR_CFG_SCAN_SD;
290 else if (height == 576)
291 val |= MXR_CFG_SCAN_PAL | MXR_CFG_SCAN_SD;
292 else if (height == 720)
293 val |= MXR_CFG_SCAN_HD_720 | MXR_CFG_SCAN_HD;
294 else if (height == 1080)
295 val |= MXR_CFG_SCAN_HD_1080 | MXR_CFG_SCAN_HD;
297 val |= MXR_CFG_SCAN_HD_720 | MXR_CFG_SCAN_HD;
299 mixer_reg_writemask(res, MXR_CFG, val, MXR_CFG_SCAN_MASK);
302 static void mixer_cfg_rgb_fmt(struct mixer_context *ctx, unsigned int height)
304 struct mixer_resources *res = &ctx->mixer_res;
308 val = MXR_CFG_RGB601_0_255;
309 } else if (height == 576) {
310 val = MXR_CFG_RGB601_0_255;
311 } else if (height == 720) {
312 val = MXR_CFG_RGB709_16_235;
313 mixer_reg_write(res, MXR_CM_COEFF_Y,
314 (1 << 30) | (94 << 20) | (314 << 10) |
316 mixer_reg_write(res, MXR_CM_COEFF_CB,
317 (972 << 20) | (851 << 10) | (225 << 0));
318 mixer_reg_write(res, MXR_CM_COEFF_CR,
319 (225 << 20) | (820 << 10) | (1004 << 0));
320 } else if (height == 1080) {
321 val = MXR_CFG_RGB709_16_235;
322 mixer_reg_write(res, MXR_CM_COEFF_Y,
323 (1 << 30) | (94 << 20) | (314 << 10) |
325 mixer_reg_write(res, MXR_CM_COEFF_CB,
326 (972 << 20) | (851 << 10) | (225 << 0));
327 mixer_reg_write(res, MXR_CM_COEFF_CR,
328 (225 << 20) | (820 << 10) | (1004 << 0));
330 val = MXR_CFG_RGB709_16_235;
331 mixer_reg_write(res, MXR_CM_COEFF_Y,
332 (1 << 30) | (94 << 20) | (314 << 10) |
334 mixer_reg_write(res, MXR_CM_COEFF_CB,
335 (972 << 20) | (851 << 10) | (225 << 0));
336 mixer_reg_write(res, MXR_CM_COEFF_CR,
337 (225 << 20) | (820 << 10) | (1004 << 0));
340 mixer_reg_writemask(res, MXR_CFG, val, MXR_CFG_RGB_FMT_MASK);
343 static void mixer_cfg_layer(struct mixer_context *ctx, int win, bool enable)
345 struct mixer_resources *res = &ctx->mixer_res;
346 u32 val = enable ? ~0 : 0;
350 mixer_reg_writemask(res, MXR_CFG, val, MXR_CFG_GRP0_ENABLE);
353 mixer_reg_writemask(res, MXR_CFG, val, MXR_CFG_GRP1_ENABLE);
356 if (ctx->vp_enabled) {
357 vp_reg_writemask(res, VP_ENABLE, val, VP_ENABLE_ON);
358 mixer_reg_writemask(res, MXR_CFG, val,
365 static void mixer_run(struct mixer_context *ctx)
367 struct mixer_resources *res = &ctx->mixer_res;
369 mixer_reg_writemask(res, MXR_STATUS, ~0, MXR_STATUS_REG_RUN);
371 mixer_regs_dump(ctx);
374 static void vp_video_buffer(struct mixer_context *ctx, int win)
376 struct mixer_resources *res = &ctx->mixer_res;
378 struct hdmi_win_data *win_data;
379 unsigned int x_ratio, y_ratio;
380 unsigned int buf_num;
381 dma_addr_t luma_addr[2], chroma_addr[2];
382 bool tiled_mode = false;
383 bool crcb_mode = false;
386 win_data = &ctx->win_data[win];
388 switch (win_data->pixel_format) {
389 case DRM_FORMAT_NV12MT:
391 case DRM_FORMAT_NV12:
395 /* TODO: single buffer format NV12, NV21 */
397 /* ignore pixel format at disable time */
398 if (!win_data->dma_addr)
401 DRM_ERROR("pixel format for vp is wrong [%d].\n",
402 win_data->pixel_format);
406 /* scaling feature: (src << 16) / dst */
407 x_ratio = (win_data->src_width << 16) / win_data->crtc_width;
408 y_ratio = (win_data->src_height << 16) / win_data->crtc_height;
411 luma_addr[0] = win_data->dma_addr;
412 chroma_addr[0] = win_data->chroma_dma_addr;
414 luma_addr[0] = win_data->dma_addr;
415 chroma_addr[0] = win_data->dma_addr
416 + (win_data->fb_width * win_data->fb_height);
419 if (win_data->scan_flags & DRM_MODE_FLAG_INTERLACE) {
420 ctx->interlace = true;
422 luma_addr[1] = luma_addr[0] + 0x40;
423 chroma_addr[1] = chroma_addr[0] + 0x40;
425 luma_addr[1] = luma_addr[0] + win_data->fb_width;
426 chroma_addr[1] = chroma_addr[0] + win_data->fb_width;
429 ctx->interlace = false;
434 spin_lock_irqsave(&res->reg_slock, flags);
435 mixer_vsync_set_update(ctx, false);
437 /* interlace or progressive scan mode */
438 val = (ctx->interlace ? ~0 : 0);
439 vp_reg_writemask(res, VP_MODE, val, VP_MODE_LINE_SKIP);
442 val = (crcb_mode ? VP_MODE_NV21 : VP_MODE_NV12);
443 val |= (tiled_mode ? VP_MODE_MEM_TILED : VP_MODE_MEM_LINEAR);
444 vp_reg_writemask(res, VP_MODE, val, VP_MODE_FMT_MASK);
446 /* setting size of input image */
447 vp_reg_write(res, VP_IMG_SIZE_Y, VP_IMG_HSIZE(win_data->fb_width) |
448 VP_IMG_VSIZE(win_data->fb_height));
449 /* chroma height has to reduced by 2 to avoid chroma distorions */
450 vp_reg_write(res, VP_IMG_SIZE_C, VP_IMG_HSIZE(win_data->fb_width) |
451 VP_IMG_VSIZE(win_data->fb_height / 2));
453 vp_reg_write(res, VP_SRC_WIDTH, win_data->src_width);
454 vp_reg_write(res, VP_SRC_HEIGHT, win_data->src_height);
455 vp_reg_write(res, VP_SRC_H_POSITION,
456 VP_SRC_H_POSITION_VAL(win_data->fb_x));
457 vp_reg_write(res, VP_SRC_V_POSITION, win_data->fb_y);
459 vp_reg_write(res, VP_DST_WIDTH, win_data->crtc_width);
460 vp_reg_write(res, VP_DST_H_POSITION, win_data->crtc_x);
461 if (ctx->interlace) {
462 vp_reg_write(res, VP_DST_HEIGHT, win_data->crtc_height / 2);
463 vp_reg_write(res, VP_DST_V_POSITION, win_data->crtc_y / 2);
465 vp_reg_write(res, VP_DST_HEIGHT, win_data->crtc_height);
466 vp_reg_write(res, VP_DST_V_POSITION, win_data->crtc_y);
469 vp_reg_write(res, VP_H_RATIO, x_ratio);
470 vp_reg_write(res, VP_V_RATIO, y_ratio);
472 vp_reg_write(res, VP_ENDIAN_MODE, VP_ENDIAN_MODE_LITTLE);
474 /* set buffer address to vp */
475 vp_reg_write(res, VP_TOP_Y_PTR, luma_addr[0]);
476 vp_reg_write(res, VP_BOT_Y_PTR, luma_addr[1]);
477 vp_reg_write(res, VP_TOP_C_PTR, chroma_addr[0]);
478 vp_reg_write(res, VP_BOT_C_PTR, chroma_addr[1]);
480 mixer_cfg_scan(ctx, win_data->mode_height);
481 mixer_cfg_rgb_fmt(ctx, win_data->mode_height);
482 mixer_cfg_layer(ctx, win, true);
485 mixer_vsync_set_update(ctx, true);
486 spin_unlock_irqrestore(&res->reg_slock, flags);
491 static void mixer_layer_update(struct mixer_context *ctx)
493 struct mixer_resources *res = &ctx->mixer_res;
496 val = mixer_reg_read(res, MXR_CFG);
498 /* allow one update per vsync only */
499 if (!(val & MXR_CFG_LAYER_UPDATE_COUNT_MASK))
500 mixer_reg_writemask(res, MXR_CFG, ~0, MXR_CFG_LAYER_UPDATE);
503 static void mixer_graph_buffer(struct mixer_context *ctx, int win)
505 struct mixer_resources *res = &ctx->mixer_res;
507 struct hdmi_win_data *win_data;
508 unsigned int x_ratio, y_ratio;
509 unsigned int src_x_offset, src_y_offset, dst_x_offset, dst_y_offset;
514 win_data = &ctx->win_data[win];
521 switch (win_data->bpp) {
532 /* 2x scaling feature */
536 dst_x_offset = win_data->crtc_x;
537 dst_y_offset = win_data->crtc_y;
539 /* converting dma address base and source offset */
540 dma_addr = win_data->dma_addr
541 + (win_data->fb_x * win_data->bpp >> 3)
542 + (win_data->fb_y * win_data->fb_width * win_data->bpp >> 3);
546 if (win_data->scan_flags & DRM_MODE_FLAG_INTERLACE)
547 ctx->interlace = true;
549 ctx->interlace = false;
551 spin_lock_irqsave(&res->reg_slock, flags);
552 mixer_vsync_set_update(ctx, false);
555 mixer_reg_writemask(res, MXR_GRAPHIC_CFG(win),
556 MXR_GRP_CFG_FORMAT_VAL(fmt), MXR_GRP_CFG_FORMAT_MASK);
559 mixer_reg_write(res, MXR_GRAPHIC_SPAN(win), win_data->fb_width);
561 val = MXR_GRP_WH_WIDTH(win_data->crtc_width);
562 val |= MXR_GRP_WH_HEIGHT(win_data->crtc_height);
563 val |= MXR_GRP_WH_H_SCALE(x_ratio);
564 val |= MXR_GRP_WH_V_SCALE(y_ratio);
565 mixer_reg_write(res, MXR_GRAPHIC_WH(win), val);
567 /* setup offsets in source image */
568 val = MXR_GRP_SXY_SX(src_x_offset);
569 val |= MXR_GRP_SXY_SY(src_y_offset);
570 mixer_reg_write(res, MXR_GRAPHIC_SXY(win), val);
572 /* setup offsets in display image */
573 val = MXR_GRP_DXY_DX(dst_x_offset);
574 val |= MXR_GRP_DXY_DY(dst_y_offset);
575 mixer_reg_write(res, MXR_GRAPHIC_DXY(win), val);
577 /* set buffer address to mixer */
578 mixer_reg_write(res, MXR_GRAPHIC_BASE(win), dma_addr);
580 mixer_cfg_scan(ctx, win_data->mode_height);
581 mixer_cfg_rgb_fmt(ctx, win_data->mode_height);
582 mixer_cfg_layer(ctx, win, true);
584 /* layer update mandatory for mixer 16.0.33.0 */
585 if (ctx->mxr_ver == MXR_VER_16_0_33_0)
586 mixer_layer_update(ctx);
590 mixer_vsync_set_update(ctx, true);
591 spin_unlock_irqrestore(&res->reg_slock, flags);
594 static void vp_win_reset(struct mixer_context *ctx)
596 struct mixer_resources *res = &ctx->mixer_res;
599 vp_reg_write(res, VP_SRESET, VP_SRESET_PROCESSING);
600 for (tries = 100; tries; --tries) {
601 /* waiting until VP_SRESET_PROCESSING is 0 */
602 if (~vp_reg_read(res, VP_SRESET) & VP_SRESET_PROCESSING)
606 WARN(tries == 0, "failed to reset Video Processor\n");
609 static void mixer_win_reset(struct mixer_context *ctx)
611 struct mixer_resources *res = &ctx->mixer_res;
613 u32 val; /* value stored to register */
615 spin_lock_irqsave(&res->reg_slock, flags);
616 mixer_vsync_set_update(ctx, false);
618 mixer_reg_writemask(res, MXR_CFG, MXR_CFG_DST_HDMI, MXR_CFG_DST_MASK);
620 /* set output in RGB888 mode */
621 mixer_reg_writemask(res, MXR_CFG, MXR_CFG_OUT_RGB888, MXR_CFG_OUT_MASK);
623 /* 16 beat burst in DMA */
624 mixer_reg_writemask(res, MXR_STATUS, MXR_STATUS_16_BURST,
625 MXR_STATUS_BURST_MASK);
627 /* setting default layer priority: layer1 > layer0 > video
628 * because typical usage scenario would be
630 * layer0 - framebuffer
631 * video - video overlay
633 val = MXR_LAYER_CFG_GRP1_VAL(3);
634 val |= MXR_LAYER_CFG_GRP0_VAL(2);
636 val |= MXR_LAYER_CFG_VP_VAL(1);
637 mixer_reg_write(res, MXR_LAYER_CFG, val);
639 /* setting background color */
640 mixer_reg_write(res, MXR_BG_COLOR0, 0x008080);
641 mixer_reg_write(res, MXR_BG_COLOR1, 0x008080);
642 mixer_reg_write(res, MXR_BG_COLOR2, 0x008080);
644 /* setting graphical layers */
645 val = MXR_GRP_CFG_COLOR_KEY_DISABLE; /* no blank key */
646 val |= MXR_GRP_CFG_WIN_BLEND_EN;
647 val |= MXR_GRP_CFG_BLEND_PRE_MUL;
648 val |= MXR_GRP_CFG_PIXEL_BLEND_EN;
649 val |= MXR_GRP_CFG_ALPHA_VAL(0xff); /* non-transparent alpha */
651 /* the same configuration for both layers */
652 mixer_reg_write(res, MXR_GRAPHIC_CFG(0), val);
653 mixer_reg_write(res, MXR_GRAPHIC_CFG(1), val);
655 /* setting video layers */
656 val = MXR_GRP_CFG_ALPHA_VAL(0);
657 mixer_reg_write(res, MXR_VIDEO_CFG, val);
659 if (ctx->vp_enabled) {
660 /* configuration of Video Processor Registers */
662 vp_default_filter(res);
665 /* disable all layers */
666 mixer_reg_writemask(res, MXR_CFG, 0, MXR_CFG_GRP0_ENABLE);
667 mixer_reg_writemask(res, MXR_CFG, 0, MXR_CFG_GRP1_ENABLE);
669 mixer_reg_writemask(res, MXR_CFG, 0, MXR_CFG_VP_ENABLE);
671 mixer_vsync_set_update(ctx, true);
672 spin_unlock_irqrestore(&res->reg_slock, flags);
675 static int mixer_iommu_on(void *ctx, bool enable)
677 struct exynos_drm_hdmi_context *drm_hdmi_ctx;
678 struct mixer_context *mdata = ctx;
679 struct drm_device *drm_dev;
681 drm_hdmi_ctx = mdata->parent_ctx;
682 drm_dev = drm_hdmi_ctx->drm_dev;
684 if (is_drm_iommu_supported(drm_dev)) {
686 return drm_iommu_attach_device(drm_dev, mdata->dev);
688 drm_iommu_detach_device(drm_dev, mdata->dev);
693 static int mixer_enable_vblank(void *ctx, int pipe)
695 struct mixer_context *mixer_ctx = ctx;
696 struct mixer_resources *res = &mixer_ctx->mixer_res;
698 DRM_DEBUG_KMS("[%d] %s\n", __LINE__, __func__);
700 mixer_ctx->pipe = pipe;
702 /* enable vsync interrupt */
703 mixer_reg_writemask(res, MXR_INT_EN, MXR_INT_EN_VSYNC,
709 static void mixer_disable_vblank(void *ctx)
711 struct mixer_context *mixer_ctx = ctx;
712 struct mixer_resources *res = &mixer_ctx->mixer_res;
714 DRM_DEBUG_KMS("[%d] %s\n", __LINE__, __func__);
716 /* disable vsync interrupt */
717 mixer_reg_writemask(res, MXR_INT_EN, 0, MXR_INT_EN_VSYNC);
720 static void mixer_win_mode_set(void *ctx,
721 struct exynos_drm_overlay *overlay)
723 struct mixer_context *mixer_ctx = ctx;
724 struct hdmi_win_data *win_data;
727 DRM_DEBUG_KMS("[%d] %s\n", __LINE__, __func__);
730 DRM_ERROR("overlay is NULL\n");
734 DRM_DEBUG_KMS("set [%d]x[%d] at (%d,%d) to [%d]x[%d] at (%d,%d)\n",
735 overlay->fb_width, overlay->fb_height,
736 overlay->fb_x, overlay->fb_y,
737 overlay->crtc_width, overlay->crtc_height,
738 overlay->crtc_x, overlay->crtc_y);
741 if (win == DEFAULT_ZPOS)
742 win = MIXER_DEFAULT_WIN;
744 if (win < 0 || win > MIXER_WIN_NR) {
745 DRM_ERROR("mixer window[%d] is wrong\n", win);
749 win_data = &mixer_ctx->win_data[win];
751 win_data->dma_addr = overlay->dma_addr[0];
752 win_data->vaddr = overlay->vaddr[0];
753 win_data->chroma_dma_addr = overlay->dma_addr[1];
754 win_data->chroma_vaddr = overlay->vaddr[1];
755 win_data->pixel_format = overlay->pixel_format;
756 win_data->bpp = overlay->bpp;
758 win_data->crtc_x = overlay->crtc_x;
759 win_data->crtc_y = overlay->crtc_y;
760 win_data->crtc_width = overlay->crtc_width;
761 win_data->crtc_height = overlay->crtc_height;
763 win_data->fb_x = overlay->fb_x;
764 win_data->fb_y = overlay->fb_y;
765 win_data->fb_width = overlay->fb_width;
766 win_data->fb_height = overlay->fb_height;
767 win_data->src_width = overlay->src_width;
768 win_data->src_height = overlay->src_height;
770 win_data->mode_width = overlay->mode_width;
771 win_data->mode_height = overlay->mode_height;
773 win_data->scan_flags = overlay->scan_flag;
776 static void mixer_win_commit(void *ctx, int win)
778 struct mixer_context *mixer_ctx = ctx;
780 DRM_DEBUG_KMS("[%d] %s, win: %d\n", __LINE__, __func__, win);
782 if (win > 1 && mixer_ctx->vp_enabled)
783 vp_video_buffer(mixer_ctx, win);
785 mixer_graph_buffer(mixer_ctx, win);
787 mixer_ctx->win_data[win].enabled = true;
790 static void mixer_win_disable(void *ctx, int win)
792 struct mixer_context *mixer_ctx = ctx;
793 struct mixer_resources *res = &mixer_ctx->mixer_res;
796 DRM_DEBUG_KMS("[%d] %s, win: %d\n", __LINE__, __func__, win);
798 mutex_lock(&mixer_ctx->mixer_mutex);
799 if (!mixer_ctx->powered) {
800 mutex_unlock(&mixer_ctx->mixer_mutex);
801 mixer_ctx->win_data[win].resume = false;
804 mutex_unlock(&mixer_ctx->mixer_mutex);
806 spin_lock_irqsave(&res->reg_slock, flags);
807 mixer_vsync_set_update(mixer_ctx, false);
809 mixer_cfg_layer(mixer_ctx, win, false);
811 mixer_vsync_set_update(mixer_ctx, true);
812 spin_unlock_irqrestore(&res->reg_slock, flags);
814 mixer_ctx->win_data[win].enabled = false;
817 static void mixer_wait_for_vblank(void *ctx)
819 struct mixer_context *mixer_ctx = ctx;
821 mutex_lock(&mixer_ctx->mixer_mutex);
822 if (!mixer_ctx->powered) {
823 mutex_unlock(&mixer_ctx->mixer_mutex);
826 mutex_unlock(&mixer_ctx->mixer_mutex);
828 atomic_set(&mixer_ctx->wait_vsync_event, 1);
831 * wait for MIXER to signal VSYNC interrupt or return after
832 * timeout which is set to 50ms (refresh rate of 20).
834 if (!wait_event_timeout(mixer_ctx->wait_vsync_queue,
835 !atomic_read(&mixer_ctx->wait_vsync_event),
837 DRM_DEBUG_KMS("vblank wait timed out.\n");
840 static void mixer_window_suspend(struct mixer_context *ctx)
842 struct hdmi_win_data *win_data;
845 for (i = 0; i < MIXER_WIN_NR; i++) {
846 win_data = &ctx->win_data[i];
847 win_data->resume = win_data->enabled;
848 mixer_win_disable(ctx, i);
850 mixer_wait_for_vblank(ctx);
853 static void mixer_window_resume(struct mixer_context *ctx)
855 struct hdmi_win_data *win_data;
858 for (i = 0; i < MIXER_WIN_NR; i++) {
859 win_data = &ctx->win_data[i];
860 win_data->enabled = win_data->resume;
861 win_data->resume = false;
865 static void mixer_poweron(struct mixer_context *ctx)
867 struct mixer_resources *res = &ctx->mixer_res;
869 DRM_DEBUG_KMS("[%d] %s\n", __LINE__, __func__);
871 mutex_lock(&ctx->mixer_mutex);
873 mutex_unlock(&ctx->mixer_mutex);
877 mutex_unlock(&ctx->mixer_mutex);
879 pm_runtime_get_sync(ctx->dev);
881 clk_enable(res->mixer);
882 if (ctx->vp_enabled) {
884 clk_enable(res->sclk_mixer);
887 mixer_reg_write(res, MXR_INT_EN, ctx->int_en);
888 mixer_win_reset(ctx);
890 mixer_window_resume(ctx);
893 static void mixer_poweroff(struct mixer_context *ctx)
895 struct mixer_resources *res = &ctx->mixer_res;
897 DRM_DEBUG_KMS("[%d] %s\n", __LINE__, __func__);
899 mutex_lock(&ctx->mixer_mutex);
902 mutex_unlock(&ctx->mixer_mutex);
904 mixer_window_suspend(ctx);
906 ctx->int_en = mixer_reg_read(res, MXR_INT_EN);
908 clk_disable(res->mixer);
909 if (ctx->vp_enabled) {
910 clk_disable(res->vp);
911 clk_disable(res->sclk_mixer);
914 pm_runtime_put_sync(ctx->dev);
916 mutex_lock(&ctx->mixer_mutex);
917 ctx->powered = false;
920 mutex_unlock(&ctx->mixer_mutex);
923 static void mixer_dpms(void *ctx, int mode)
925 struct mixer_context *mixer_ctx = ctx;
927 DRM_DEBUG_KMS("[%d] %s\n", __LINE__, __func__);
930 case DRM_MODE_DPMS_ON:
931 mixer_poweron(mixer_ctx);
933 case DRM_MODE_DPMS_STANDBY:
934 case DRM_MODE_DPMS_SUSPEND:
935 case DRM_MODE_DPMS_OFF:
936 mixer_poweroff(mixer_ctx);
939 DRM_DEBUG_KMS("unknown dpms mode: %d\n", mode);
944 static struct exynos_mixer_ops mixer_ops = {
946 .iommu_on = mixer_iommu_on,
947 .enable_vblank = mixer_enable_vblank,
948 .disable_vblank = mixer_disable_vblank,
949 .wait_for_vblank = mixer_wait_for_vblank,
953 .win_mode_set = mixer_win_mode_set,
954 .win_commit = mixer_win_commit,
955 .win_disable = mixer_win_disable,
958 /* for pageflip event */
959 static void mixer_finish_pageflip(struct drm_device *drm_dev, int crtc)
961 struct exynos_drm_private *dev_priv = drm_dev->dev_private;
962 struct drm_pending_vblank_event *e, *t;
966 spin_lock_irqsave(&drm_dev->event_lock, flags);
968 list_for_each_entry_safe(e, t, &dev_priv->pageflip_event_list,
970 /* if event's pipe isn't same as crtc then ignore it. */
974 do_gettimeofday(&now);
975 e->event.sequence = 0;
976 e->event.tv_sec = now.tv_sec;
977 e->event.tv_usec = now.tv_usec;
979 list_move_tail(&e->base.link, &e->base.file_priv->event_list);
980 wake_up_interruptible(&e->base.file_priv->event_wait);
981 drm_vblank_put(drm_dev, crtc);
984 spin_unlock_irqrestore(&drm_dev->event_lock, flags);
987 static irqreturn_t mixer_irq_handler(int irq, void *arg)
989 struct exynos_drm_hdmi_context *drm_hdmi_ctx = arg;
990 struct mixer_context *ctx = drm_hdmi_ctx->ctx;
991 struct mixer_resources *res = &ctx->mixer_res;
992 u32 val, base, shadow;
994 spin_lock(&res->reg_slock);
996 /* read interrupt status for handling and clearing flags for VSYNC */
997 val = mixer_reg_read(res, MXR_INT_STATUS);
1000 if (val & MXR_INT_STATUS_VSYNC) {
1001 /* interlace scan need to check shadow register */
1002 if (ctx->interlace) {
1003 base = mixer_reg_read(res, MXR_GRAPHIC_BASE(0));
1004 shadow = mixer_reg_read(res, MXR_GRAPHIC_BASE_S(0));
1008 base = mixer_reg_read(res, MXR_GRAPHIC_BASE(1));
1009 shadow = mixer_reg_read(res, MXR_GRAPHIC_BASE_S(1));
1014 drm_handle_vblank(drm_hdmi_ctx->drm_dev, ctx->pipe);
1015 mixer_finish_pageflip(drm_hdmi_ctx->drm_dev, ctx->pipe);
1017 /* set wait vsync event to zero and wake up queue. */
1018 if (atomic_read(&ctx->wait_vsync_event)) {
1019 atomic_set(&ctx->wait_vsync_event, 0);
1020 DRM_WAKEUP(&ctx->wait_vsync_queue);
1025 /* clear interrupts */
1026 if (~val & MXR_INT_EN_VSYNC) {
1027 /* vsync interrupt use different bit for read and clear */
1028 val &= ~MXR_INT_EN_VSYNC;
1029 val |= MXR_INT_CLEAR_VSYNC;
1031 mixer_reg_write(res, MXR_INT_STATUS, val);
1033 spin_unlock(&res->reg_slock);
1038 static int __devinit mixer_resources_init(struct exynos_drm_hdmi_context *ctx,
1039 struct platform_device *pdev)
1041 struct mixer_context *mixer_ctx = ctx->ctx;
1042 struct device *dev = &pdev->dev;
1043 struct mixer_resources *mixer_res = &mixer_ctx->mixer_res;
1044 struct resource *res;
1047 spin_lock_init(&mixer_res->reg_slock);
1049 mixer_res->mixer = devm_clk_get(dev, "mixer");
1050 if (IS_ERR_OR_NULL(mixer_res->mixer)) {
1051 dev_err(dev, "failed to get clock 'mixer'\n");
1055 mixer_res->sclk_hdmi = devm_clk_get(dev, "sclk_hdmi");
1056 if (IS_ERR_OR_NULL(mixer_res->sclk_hdmi)) {
1057 dev_err(dev, "failed to get clock 'sclk_hdmi'\n");
1060 res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
1062 dev_err(dev, "get memory resource failed.\n");
1066 mixer_res->mixer_regs = devm_ioremap(&pdev->dev, res->start,
1067 resource_size(res));
1068 if (mixer_res->mixer_regs == NULL) {
1069 dev_err(dev, "register mapping failed.\n");
1073 res = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
1075 dev_err(dev, "get interrupt resource failed.\n");
1079 ret = devm_request_irq(&pdev->dev, res->start, mixer_irq_handler,
1080 0, "drm_mixer", ctx);
1082 dev_err(dev, "request interrupt failed.\n");
1085 mixer_res->irq = res->start;
1090 static int __devinit vp_resources_init(struct exynos_drm_hdmi_context *ctx,
1091 struct platform_device *pdev)
1093 struct mixer_context *mixer_ctx = ctx->ctx;
1094 struct device *dev = &pdev->dev;
1095 struct mixer_resources *mixer_res = &mixer_ctx->mixer_res;
1096 struct resource *res;
1098 mixer_res->vp = devm_clk_get(dev, "vp");
1099 if (IS_ERR_OR_NULL(mixer_res->vp)) {
1100 dev_err(dev, "failed to get clock 'vp'\n");
1103 mixer_res->sclk_mixer = devm_clk_get(dev, "sclk_mixer");
1104 if (IS_ERR_OR_NULL(mixer_res->sclk_mixer)) {
1105 dev_err(dev, "failed to get clock 'sclk_mixer'\n");
1108 mixer_res->sclk_dac = devm_clk_get(dev, "sclk_dac");
1109 if (IS_ERR_OR_NULL(mixer_res->sclk_dac)) {
1110 dev_err(dev, "failed to get clock 'sclk_dac'\n");
1114 if (mixer_res->sclk_hdmi)
1115 clk_set_parent(mixer_res->sclk_mixer, mixer_res->sclk_hdmi);
1117 res = platform_get_resource(pdev, IORESOURCE_MEM, 1);
1119 dev_err(dev, "get memory resource failed.\n");
1123 mixer_res->vp_regs = devm_ioremap(&pdev->dev, res->start,
1124 resource_size(res));
1125 if (mixer_res->vp_regs == NULL) {
1126 dev_err(dev, "register mapping failed.\n");
1133 static struct mixer_drv_data exynos5_mxr_drv_data = {
1134 .version = MXR_VER_16_0_33_0,
1138 static struct mixer_drv_data exynos4_mxr_drv_data = {
1139 .version = MXR_VER_0_0_0_16,
1143 static struct platform_device_id mixer_driver_types[] = {
1145 .name = "s5p-mixer",
1146 .driver_data = (unsigned long)&exynos4_mxr_drv_data,
1148 .name = "exynos5-mixer",
1149 .driver_data = (unsigned long)&exynos5_mxr_drv_data,
1155 static struct of_device_id mixer_match_types[] = {
1157 .compatible = "samsung,exynos5-mixer",
1158 .data = &exynos5_mxr_drv_data,
1164 static int __devinit mixer_probe(struct platform_device *pdev)
1166 struct device *dev = &pdev->dev;
1167 struct exynos_drm_hdmi_context *drm_hdmi_ctx;
1168 struct mixer_context *ctx;
1169 struct mixer_drv_data *drv;
1172 dev_info(dev, "probe start\n");
1174 drm_hdmi_ctx = devm_kzalloc(&pdev->dev, sizeof(*drm_hdmi_ctx),
1176 if (!drm_hdmi_ctx) {
1177 DRM_ERROR("failed to allocate common hdmi context.\n");
1181 ctx = devm_kzalloc(&pdev->dev, sizeof(*ctx), GFP_KERNEL);
1183 DRM_ERROR("failed to alloc mixer context.\n");
1187 mutex_init(&ctx->mixer_mutex);
1190 const struct of_device_id *match;
1191 match = of_match_node(of_match_ptr(mixer_match_types),
1193 drv = (struct mixer_drv_data *)match->data;
1195 drv = (struct mixer_drv_data *)
1196 platform_get_device_id(pdev)->driver_data;
1199 ctx->dev = &pdev->dev;
1200 ctx->parent_ctx = (void *)drm_hdmi_ctx;
1201 drm_hdmi_ctx->ctx = (void *)ctx;
1202 ctx->vp_enabled = drv->is_vp_enabled;
1203 ctx->mxr_ver = drv->version;
1204 DRM_INIT_WAITQUEUE(&ctx->wait_vsync_queue);
1205 atomic_set(&ctx->wait_vsync_event, 0);
1207 platform_set_drvdata(pdev, drm_hdmi_ctx);
1209 /* acquire resources: regs, irqs, clocks */
1210 ret = mixer_resources_init(drm_hdmi_ctx, pdev);
1212 DRM_ERROR("mixer_resources_init failed\n");
1216 if (ctx->vp_enabled) {
1217 /* acquire vp resources: regs, irqs, clocks */
1218 ret = vp_resources_init(drm_hdmi_ctx, pdev);
1220 DRM_ERROR("vp_resources_init failed\n");
1225 /* attach mixer driver to common hdmi. */
1226 exynos_mixer_drv_attach(drm_hdmi_ctx);
1228 /* register specific callback point to common hdmi. */
1229 exynos_mixer_ops_register(&mixer_ops);
1231 pm_runtime_enable(dev);
1237 dev_info(dev, "probe failed\n");
1241 static int mixer_remove(struct platform_device *pdev)
1243 dev_info(&pdev->dev, "remove successful\n");
1245 pm_runtime_disable(&pdev->dev);
1250 #ifdef CONFIG_PM_SLEEP
1251 static int mixer_suspend(struct device *dev)
1253 struct exynos_drm_hdmi_context *drm_hdmi_ctx = get_mixer_context(dev);
1254 struct mixer_context *ctx = drm_hdmi_ctx->ctx;
1256 mixer_poweroff(ctx);
1262 static SIMPLE_DEV_PM_OPS(mixer_pm_ops, mixer_suspend, NULL);
1264 struct platform_driver mixer_driver = {
1266 .name = "exynos-mixer",
1267 .owner = THIS_MODULE,
1268 .pm = &mixer_pm_ops,
1269 .of_match_table = mixer_match_types,
1271 .probe = mixer_probe,
1272 .remove = __devexit_p(mixer_remove),
1273 .id_table = mixer_driver_types,