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 {
45 dma_addr_t chroma_dma_addr;
46 uint32_t pixel_format;
50 unsigned int crtc_width;
51 unsigned int crtc_height;
54 unsigned int fb_width;
55 unsigned int fb_height;
56 unsigned int src_width;
57 unsigned int src_height;
58 unsigned int mode_width;
59 unsigned int mode_height;
60 unsigned int scan_flags;
65 struct mixer_resources {
67 void __iomem *mixer_regs;
68 void __iomem *vp_regs;
72 struct clk *sclk_mixer;
73 struct clk *sclk_hdmi;
77 enum mixer_version_id {
82 struct mixer_context {
84 struct drm_device *drm_dev;
91 struct mutex mixer_mutex;
92 struct mixer_resources mixer_res;
93 struct hdmi_win_data win_data[MIXER_WIN_NR];
94 enum mixer_version_id mxr_ver;
96 wait_queue_head_t wait_vsync_queue;
97 atomic_t wait_vsync_event;
100 struct mixer_drv_data {
101 enum mixer_version_id version;
105 static const u8 filter_y_horiz_tap8[] = {
106 0, -1, -1, -1, -1, -1, -1, -1,
107 -1, -1, -1, -1, -1, 0, 0, 0,
108 0, 2, 4, 5, 6, 6, 6, 6,
109 6, 5, 5, 4, 3, 2, 1, 1,
110 0, -6, -12, -16, -18, -20, -21, -20,
111 -20, -18, -16, -13, -10, -8, -5, -2,
112 127, 126, 125, 121, 114, 107, 99, 89,
113 79, 68, 57, 46, 35, 25, 16, 8,
116 static const u8 filter_y_vert_tap4[] = {
117 0, -3, -6, -8, -8, -8, -8, -7,
118 -6, -5, -4, -3, -2, -1, -1, 0,
119 127, 126, 124, 118, 111, 102, 92, 81,
120 70, 59, 48, 37, 27, 19, 11, 5,
121 0, 5, 11, 19, 27, 37, 48, 59,
122 70, 81, 92, 102, 111, 118, 124, 126,
123 0, 0, -1, -1, -2, -3, -4, -5,
124 -6, -7, -8, -8, -8, -8, -6, -3,
127 static const u8 filter_cr_horiz_tap4[] = {
128 0, -3, -6, -8, -8, -8, -8, -7,
129 -6, -5, -4, -3, -2, -1, -1, 0,
130 127, 126, 124, 118, 111, 102, 92, 81,
131 70, 59, 48, 37, 27, 19, 11, 5,
134 static inline u32 vp_reg_read(struct mixer_resources *res, u32 reg_id)
136 return readl(res->vp_regs + reg_id);
139 static inline void vp_reg_write(struct mixer_resources *res, u32 reg_id,
142 writel(val, res->vp_regs + reg_id);
145 static inline void vp_reg_writemask(struct mixer_resources *res, u32 reg_id,
148 u32 old = vp_reg_read(res, reg_id);
150 val = (val & mask) | (old & ~mask);
151 writel(val, res->vp_regs + reg_id);
154 static inline u32 mixer_reg_read(struct mixer_resources *res, u32 reg_id)
156 return readl(res->mixer_regs + reg_id);
159 static inline void mixer_reg_write(struct mixer_resources *res, u32 reg_id,
162 writel(val, res->mixer_regs + reg_id);
165 static inline void mixer_reg_writemask(struct mixer_resources *res,
166 u32 reg_id, u32 val, u32 mask)
168 u32 old = mixer_reg_read(res, reg_id);
170 val = (val & mask) | (old & ~mask);
171 writel(val, res->mixer_regs + reg_id);
174 static void mixer_regs_dump(struct mixer_context *ctx)
176 #define DUMPREG(reg_id) \
178 DRM_DEBUG_KMS(#reg_id " = %08x\n", \
179 (u32)readl(ctx->mixer_res.mixer_regs + reg_id)); \
185 DUMPREG(MXR_INT_STATUS);
187 DUMPREG(MXR_LAYER_CFG);
188 DUMPREG(MXR_VIDEO_CFG);
190 DUMPREG(MXR_GRAPHIC0_CFG);
191 DUMPREG(MXR_GRAPHIC0_BASE);
192 DUMPREG(MXR_GRAPHIC0_SPAN);
193 DUMPREG(MXR_GRAPHIC0_WH);
194 DUMPREG(MXR_GRAPHIC0_SXY);
195 DUMPREG(MXR_GRAPHIC0_DXY);
197 DUMPREG(MXR_GRAPHIC1_CFG);
198 DUMPREG(MXR_GRAPHIC1_BASE);
199 DUMPREG(MXR_GRAPHIC1_SPAN);
200 DUMPREG(MXR_GRAPHIC1_WH);
201 DUMPREG(MXR_GRAPHIC1_SXY);
202 DUMPREG(MXR_GRAPHIC1_DXY);
206 static void vp_regs_dump(struct mixer_context *ctx)
208 #define DUMPREG(reg_id) \
210 DRM_DEBUG_KMS(#reg_id " = %08x\n", \
211 (u32) readl(ctx->mixer_res.vp_regs + reg_id)); \
216 DUMPREG(VP_SHADOW_UPDATE);
217 DUMPREG(VP_FIELD_ID);
219 DUMPREG(VP_IMG_SIZE_Y);
220 DUMPREG(VP_IMG_SIZE_C);
221 DUMPREG(VP_PER_RATE_CTRL);
222 DUMPREG(VP_TOP_Y_PTR);
223 DUMPREG(VP_BOT_Y_PTR);
224 DUMPREG(VP_TOP_C_PTR);
225 DUMPREG(VP_BOT_C_PTR);
226 DUMPREG(VP_ENDIAN_MODE);
227 DUMPREG(VP_SRC_H_POSITION);
228 DUMPREG(VP_SRC_V_POSITION);
229 DUMPREG(VP_SRC_WIDTH);
230 DUMPREG(VP_SRC_HEIGHT);
231 DUMPREG(VP_DST_H_POSITION);
232 DUMPREG(VP_DST_V_POSITION);
233 DUMPREG(VP_DST_WIDTH);
234 DUMPREG(VP_DST_HEIGHT);
241 static inline void vp_filter_set(struct mixer_resources *res,
242 int reg_id, const u8 *data, unsigned int size)
244 /* assure 4-byte align */
246 for (; size; size -= 4, reg_id += 4, data += 4) {
247 u32 val = (data[0] << 24) | (data[1] << 16) |
248 (data[2] << 8) | data[3];
249 vp_reg_write(res, reg_id, val);
253 static void vp_default_filter(struct mixer_resources *res)
255 vp_filter_set(res, VP_POLY8_Y0_LL,
256 filter_y_horiz_tap8, sizeof(filter_y_horiz_tap8));
257 vp_filter_set(res, VP_POLY4_Y0_LL,
258 filter_y_vert_tap4, sizeof(filter_y_vert_tap4));
259 vp_filter_set(res, VP_POLY4_C0_LL,
260 filter_cr_horiz_tap4, sizeof(filter_cr_horiz_tap4));
263 static void mixer_vsync_set_update(struct mixer_context *ctx, bool enable)
265 struct mixer_resources *res = &ctx->mixer_res;
267 /* block update on vsync */
268 mixer_reg_writemask(res, MXR_STATUS, enable ?
269 MXR_STATUS_SYNC_ENABLE : 0, MXR_STATUS_SYNC_ENABLE);
272 vp_reg_write(res, VP_SHADOW_UPDATE, enable ?
273 VP_SHADOW_UPDATE_ENABLE : 0);
276 static void mixer_cfg_scan(struct mixer_context *ctx, unsigned int height)
278 struct mixer_resources *res = &ctx->mixer_res;
281 /* choosing between interlace and progressive mode */
282 val = (ctx->interlace ? MXR_CFG_SCAN_INTERLACE :
283 MXR_CFG_SCAN_PROGRASSIVE);
285 /* choosing between porper HD and SD mode */
287 val |= MXR_CFG_SCAN_NTSC | MXR_CFG_SCAN_SD;
288 else if (height == 576)
289 val |= MXR_CFG_SCAN_PAL | MXR_CFG_SCAN_SD;
290 else if (height == 720)
291 val |= MXR_CFG_SCAN_HD_720 | MXR_CFG_SCAN_HD;
292 else if (height == 1080)
293 val |= MXR_CFG_SCAN_HD_1080 | MXR_CFG_SCAN_HD;
295 val |= MXR_CFG_SCAN_HD_720 | MXR_CFG_SCAN_HD;
297 mixer_reg_writemask(res, MXR_CFG, val, MXR_CFG_SCAN_MASK);
300 static void mixer_cfg_rgb_fmt(struct mixer_context *ctx, unsigned int height)
302 struct mixer_resources *res = &ctx->mixer_res;
306 val = MXR_CFG_RGB601_0_255;
307 } else if (height == 576) {
308 val = MXR_CFG_RGB601_0_255;
309 } else if (height == 720) {
310 val = MXR_CFG_RGB709_16_235;
311 mixer_reg_write(res, MXR_CM_COEFF_Y,
312 (1 << 30) | (94 << 20) | (314 << 10) |
314 mixer_reg_write(res, MXR_CM_COEFF_CB,
315 (972 << 20) | (851 << 10) | (225 << 0));
316 mixer_reg_write(res, MXR_CM_COEFF_CR,
317 (225 << 20) | (820 << 10) | (1004 << 0));
318 } else if (height == 1080) {
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));
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));
338 mixer_reg_writemask(res, MXR_CFG, val, MXR_CFG_RGB_FMT_MASK);
341 static void mixer_cfg_layer(struct mixer_context *ctx, int win, bool enable)
343 struct mixer_resources *res = &ctx->mixer_res;
344 u32 val = enable ? ~0 : 0;
348 mixer_reg_writemask(res, MXR_CFG, val, MXR_CFG_GRP0_ENABLE);
351 mixer_reg_writemask(res, MXR_CFG, val, MXR_CFG_GRP1_ENABLE);
354 if (ctx->vp_enabled) {
355 vp_reg_writemask(res, VP_ENABLE, val, VP_ENABLE_ON);
356 mixer_reg_writemask(res, MXR_CFG, val,
363 static void mixer_run(struct mixer_context *ctx)
365 struct mixer_resources *res = &ctx->mixer_res;
367 mixer_reg_writemask(res, MXR_STATUS, ~0, MXR_STATUS_REG_RUN);
369 mixer_regs_dump(ctx);
372 static void vp_video_buffer(struct mixer_context *ctx, int win)
374 struct mixer_resources *res = &ctx->mixer_res;
376 struct hdmi_win_data *win_data;
377 unsigned int x_ratio, y_ratio;
378 unsigned int buf_num;
379 dma_addr_t luma_addr[2], chroma_addr[2];
380 bool tiled_mode = false;
381 bool crcb_mode = false;
384 win_data = &ctx->win_data[win];
386 switch (win_data->pixel_format) {
387 case DRM_FORMAT_NV12MT:
389 case DRM_FORMAT_NV12:
393 /* TODO: single buffer format NV12, NV21 */
395 /* ignore pixel format at disable time */
396 if (!win_data->dma_addr)
399 DRM_ERROR("pixel format for vp is wrong [%d].\n",
400 win_data->pixel_format);
404 /* scaling feature: (src << 16) / dst */
405 x_ratio = (win_data->src_width << 16) / win_data->crtc_width;
406 y_ratio = (win_data->src_height << 16) / win_data->crtc_height;
409 luma_addr[0] = win_data->dma_addr;
410 chroma_addr[0] = win_data->chroma_dma_addr;
412 luma_addr[0] = win_data->dma_addr;
413 chroma_addr[0] = win_data->dma_addr
414 + (win_data->fb_width * win_data->fb_height);
417 if (win_data->scan_flags & DRM_MODE_FLAG_INTERLACE) {
418 ctx->interlace = true;
420 luma_addr[1] = luma_addr[0] + 0x40;
421 chroma_addr[1] = chroma_addr[0] + 0x40;
423 luma_addr[1] = luma_addr[0] + win_data->fb_width;
424 chroma_addr[1] = chroma_addr[0] + win_data->fb_width;
427 ctx->interlace = false;
432 spin_lock_irqsave(&res->reg_slock, flags);
433 mixer_vsync_set_update(ctx, false);
435 /* interlace or progressive scan mode */
436 val = (ctx->interlace ? ~0 : 0);
437 vp_reg_writemask(res, VP_MODE, val, VP_MODE_LINE_SKIP);
440 val = (crcb_mode ? VP_MODE_NV21 : VP_MODE_NV12);
441 val |= (tiled_mode ? VP_MODE_MEM_TILED : VP_MODE_MEM_LINEAR);
442 vp_reg_writemask(res, VP_MODE, val, VP_MODE_FMT_MASK);
444 /* setting size of input image */
445 vp_reg_write(res, VP_IMG_SIZE_Y, VP_IMG_HSIZE(win_data->fb_width) |
446 VP_IMG_VSIZE(win_data->fb_height));
447 /* chroma height has to reduced by 2 to avoid chroma distorions */
448 vp_reg_write(res, VP_IMG_SIZE_C, VP_IMG_HSIZE(win_data->fb_width) |
449 VP_IMG_VSIZE(win_data->fb_height / 2));
451 vp_reg_write(res, VP_SRC_WIDTH, win_data->src_width);
452 vp_reg_write(res, VP_SRC_HEIGHT, win_data->src_height);
453 vp_reg_write(res, VP_SRC_H_POSITION,
454 VP_SRC_H_POSITION_VAL(win_data->fb_x));
455 vp_reg_write(res, VP_SRC_V_POSITION, win_data->fb_y);
457 vp_reg_write(res, VP_DST_WIDTH, win_data->crtc_width);
458 vp_reg_write(res, VP_DST_H_POSITION, win_data->crtc_x);
459 if (ctx->interlace) {
460 vp_reg_write(res, VP_DST_HEIGHT, win_data->crtc_height / 2);
461 vp_reg_write(res, VP_DST_V_POSITION, win_data->crtc_y / 2);
463 vp_reg_write(res, VP_DST_HEIGHT, win_data->crtc_height);
464 vp_reg_write(res, VP_DST_V_POSITION, win_data->crtc_y);
467 vp_reg_write(res, VP_H_RATIO, x_ratio);
468 vp_reg_write(res, VP_V_RATIO, y_ratio);
470 vp_reg_write(res, VP_ENDIAN_MODE, VP_ENDIAN_MODE_LITTLE);
472 /* set buffer address to vp */
473 vp_reg_write(res, VP_TOP_Y_PTR, luma_addr[0]);
474 vp_reg_write(res, VP_BOT_Y_PTR, luma_addr[1]);
475 vp_reg_write(res, VP_TOP_C_PTR, chroma_addr[0]);
476 vp_reg_write(res, VP_BOT_C_PTR, chroma_addr[1]);
478 mixer_cfg_scan(ctx, win_data->mode_height);
479 mixer_cfg_rgb_fmt(ctx, win_data->mode_height);
480 mixer_cfg_layer(ctx, win, true);
483 mixer_vsync_set_update(ctx, true);
484 spin_unlock_irqrestore(&res->reg_slock, flags);
489 static void mixer_layer_update(struct mixer_context *ctx)
491 struct mixer_resources *res = &ctx->mixer_res;
494 val = mixer_reg_read(res, MXR_CFG);
496 /* allow one update per vsync only */
497 if (!(val & MXR_CFG_LAYER_UPDATE_COUNT_MASK))
498 mixer_reg_writemask(res, MXR_CFG, ~0, MXR_CFG_LAYER_UPDATE);
501 static void mixer_graph_buffer(struct mixer_context *ctx, int win)
503 struct mixer_resources *res = &ctx->mixer_res;
505 struct hdmi_win_data *win_data;
506 unsigned int x_ratio, y_ratio;
507 unsigned int src_x_offset, src_y_offset, dst_x_offset, dst_y_offset;
512 win_data = &ctx->win_data[win];
519 switch (win_data->bpp) {
530 /* 2x scaling feature */
534 dst_x_offset = win_data->crtc_x;
535 dst_y_offset = win_data->crtc_y;
537 /* converting dma address base and source offset */
538 dma_addr = win_data->dma_addr
539 + (win_data->fb_x * win_data->bpp >> 3)
540 + (win_data->fb_y * win_data->fb_width * win_data->bpp >> 3);
544 if (win_data->scan_flags & DRM_MODE_FLAG_INTERLACE)
545 ctx->interlace = true;
547 ctx->interlace = false;
549 spin_lock_irqsave(&res->reg_slock, flags);
550 mixer_vsync_set_update(ctx, false);
553 mixer_reg_writemask(res, MXR_GRAPHIC_CFG(win),
554 MXR_GRP_CFG_FORMAT_VAL(fmt), MXR_GRP_CFG_FORMAT_MASK);
557 mixer_reg_write(res, MXR_GRAPHIC_SPAN(win), win_data->fb_width);
559 val = MXR_GRP_WH_WIDTH(win_data->crtc_width);
560 val |= MXR_GRP_WH_HEIGHT(win_data->crtc_height);
561 val |= MXR_GRP_WH_H_SCALE(x_ratio);
562 val |= MXR_GRP_WH_V_SCALE(y_ratio);
563 mixer_reg_write(res, MXR_GRAPHIC_WH(win), val);
565 /* setup offsets in source image */
566 val = MXR_GRP_SXY_SX(src_x_offset);
567 val |= MXR_GRP_SXY_SY(src_y_offset);
568 mixer_reg_write(res, MXR_GRAPHIC_SXY(win), val);
570 /* setup offsets in display image */
571 val = MXR_GRP_DXY_DX(dst_x_offset);
572 val |= MXR_GRP_DXY_DY(dst_y_offset);
573 mixer_reg_write(res, MXR_GRAPHIC_DXY(win), val);
575 /* set buffer address to mixer */
576 mixer_reg_write(res, MXR_GRAPHIC_BASE(win), dma_addr);
578 mixer_cfg_scan(ctx, win_data->mode_height);
579 mixer_cfg_rgb_fmt(ctx, win_data->mode_height);
580 mixer_cfg_layer(ctx, win, true);
582 /* layer update mandatory for mixer 16.0.33.0 */
583 if (ctx->mxr_ver == MXR_VER_16_0_33_0)
584 mixer_layer_update(ctx);
588 mixer_vsync_set_update(ctx, true);
589 spin_unlock_irqrestore(&res->reg_slock, flags);
592 static void vp_win_reset(struct mixer_context *ctx)
594 struct mixer_resources *res = &ctx->mixer_res;
597 vp_reg_write(res, VP_SRESET, VP_SRESET_PROCESSING);
598 for (tries = 100; tries; --tries) {
599 /* waiting until VP_SRESET_PROCESSING is 0 */
600 if (~vp_reg_read(res, VP_SRESET) & VP_SRESET_PROCESSING)
604 WARN(tries == 0, "failed to reset Video Processor\n");
607 static void mixer_win_reset(struct mixer_context *ctx)
609 struct mixer_resources *res = &ctx->mixer_res;
611 u32 val; /* value stored to register */
613 spin_lock_irqsave(&res->reg_slock, flags);
614 mixer_vsync_set_update(ctx, false);
616 mixer_reg_writemask(res, MXR_CFG, MXR_CFG_DST_HDMI, MXR_CFG_DST_MASK);
618 /* set output in RGB888 mode */
619 mixer_reg_writemask(res, MXR_CFG, MXR_CFG_OUT_RGB888, MXR_CFG_OUT_MASK);
621 /* 16 beat burst in DMA */
622 mixer_reg_writemask(res, MXR_STATUS, MXR_STATUS_16_BURST,
623 MXR_STATUS_BURST_MASK);
625 /* setting default layer priority: layer1 > layer0 > video
626 * because typical usage scenario would be
628 * layer0 - framebuffer
629 * video - video overlay
631 val = MXR_LAYER_CFG_GRP1_VAL(3);
632 val |= MXR_LAYER_CFG_GRP0_VAL(2);
634 val |= MXR_LAYER_CFG_VP_VAL(1);
635 mixer_reg_write(res, MXR_LAYER_CFG, val);
637 /* setting background color */
638 mixer_reg_write(res, MXR_BG_COLOR0, 0x008080);
639 mixer_reg_write(res, MXR_BG_COLOR1, 0x008080);
640 mixer_reg_write(res, MXR_BG_COLOR2, 0x008080);
642 /* setting graphical layers */
643 val = MXR_GRP_CFG_COLOR_KEY_DISABLE; /* no blank key */
644 val |= MXR_GRP_CFG_WIN_BLEND_EN;
645 val |= MXR_GRP_CFG_BLEND_PRE_MUL;
646 val |= MXR_GRP_CFG_PIXEL_BLEND_EN;
647 val |= MXR_GRP_CFG_ALPHA_VAL(0xff); /* non-transparent alpha */
649 /* the same configuration for both layers */
650 mixer_reg_write(res, MXR_GRAPHIC_CFG(0), val);
651 mixer_reg_write(res, MXR_GRAPHIC_CFG(1), val);
653 /* setting video layers */
654 val = MXR_GRP_CFG_ALPHA_VAL(0);
655 mixer_reg_write(res, MXR_VIDEO_CFG, val);
657 if (ctx->vp_enabled) {
658 /* configuration of Video Processor Registers */
660 vp_default_filter(res);
663 /* disable all layers */
664 mixer_reg_writemask(res, MXR_CFG, 0, MXR_CFG_GRP0_ENABLE);
665 mixer_reg_writemask(res, MXR_CFG, 0, MXR_CFG_GRP1_ENABLE);
667 mixer_reg_writemask(res, MXR_CFG, 0, MXR_CFG_VP_ENABLE);
669 mixer_vsync_set_update(ctx, true);
670 spin_unlock_irqrestore(&res->reg_slock, flags);
673 static int mixer_iommu_on(void *ctx, bool enable)
675 struct exynos_drm_hdmi_context *drm_hdmi_ctx;
676 struct mixer_context *mdata = ctx;
677 struct drm_device *drm_dev;
679 drm_hdmi_ctx = mdata->parent_ctx;
680 drm_dev = drm_hdmi_ctx->drm_dev;
682 if (is_drm_iommu_supported(drm_dev)) {
684 return drm_iommu_attach_device(drm_dev, mdata->dev);
686 drm_iommu_detach_device(drm_dev, mdata->dev);
691 static int mixer_enable_vblank(void *ctx, int pipe)
693 struct mixer_context *mixer_ctx = ctx;
694 struct mixer_resources *res = &mixer_ctx->mixer_res;
696 DRM_DEBUG_KMS("[%d] %s\n", __LINE__, __func__);
698 mixer_ctx->pipe = pipe;
700 /* enable vsync interrupt */
701 mixer_reg_writemask(res, MXR_INT_EN, MXR_INT_EN_VSYNC,
707 static void mixer_disable_vblank(void *ctx)
709 struct mixer_context *mixer_ctx = ctx;
710 struct mixer_resources *res = &mixer_ctx->mixer_res;
712 DRM_DEBUG_KMS("[%d] %s\n", __LINE__, __func__);
714 /* disable vsync interrupt */
715 mixer_reg_writemask(res, MXR_INT_EN, 0, MXR_INT_EN_VSYNC);
718 static void mixer_win_mode_set(void *ctx,
719 struct exynos_drm_overlay *overlay)
721 struct mixer_context *mixer_ctx = ctx;
722 struct hdmi_win_data *win_data;
725 DRM_DEBUG_KMS("[%d] %s\n", __LINE__, __func__);
728 DRM_ERROR("overlay is NULL\n");
732 DRM_DEBUG_KMS("set [%d]x[%d] at (%d,%d) to [%d]x[%d] at (%d,%d)\n",
733 overlay->fb_width, overlay->fb_height,
734 overlay->fb_x, overlay->fb_y,
735 overlay->crtc_width, overlay->crtc_height,
736 overlay->crtc_x, overlay->crtc_y);
739 if (win == DEFAULT_ZPOS)
740 win = MIXER_DEFAULT_WIN;
742 if (win < 0 || win > MIXER_WIN_NR) {
743 DRM_ERROR("mixer window[%d] is wrong\n", win);
747 win_data = &mixer_ctx->win_data[win];
749 win_data->dma_addr = overlay->dma_addr[0];
750 win_data->chroma_dma_addr = overlay->dma_addr[1];
751 win_data->pixel_format = overlay->pixel_format;
752 win_data->bpp = overlay->bpp;
754 win_data->crtc_x = overlay->crtc_x;
755 win_data->crtc_y = overlay->crtc_y;
756 win_data->crtc_width = overlay->crtc_width;
757 win_data->crtc_height = overlay->crtc_height;
759 win_data->fb_x = overlay->fb_x;
760 win_data->fb_y = overlay->fb_y;
761 win_data->fb_width = overlay->fb_width;
762 win_data->fb_height = overlay->fb_height;
763 win_data->src_width = overlay->src_width;
764 win_data->src_height = overlay->src_height;
766 win_data->mode_width = overlay->mode_width;
767 win_data->mode_height = overlay->mode_height;
769 win_data->scan_flags = overlay->scan_flag;
772 static void mixer_win_commit(void *ctx, int win)
774 struct mixer_context *mixer_ctx = ctx;
776 DRM_DEBUG_KMS("[%d] %s, win: %d\n", __LINE__, __func__, win);
778 if (win > 1 && mixer_ctx->vp_enabled)
779 vp_video_buffer(mixer_ctx, win);
781 mixer_graph_buffer(mixer_ctx, win);
783 mixer_ctx->win_data[win].enabled = true;
786 static void mixer_win_disable(void *ctx, int win)
788 struct mixer_context *mixer_ctx = ctx;
789 struct mixer_resources *res = &mixer_ctx->mixer_res;
792 DRM_DEBUG_KMS("[%d] %s, win: %d\n", __LINE__, __func__, win);
794 mutex_lock(&mixer_ctx->mixer_mutex);
795 if (!mixer_ctx->powered) {
796 mutex_unlock(&mixer_ctx->mixer_mutex);
797 mixer_ctx->win_data[win].resume = false;
800 mutex_unlock(&mixer_ctx->mixer_mutex);
802 spin_lock_irqsave(&res->reg_slock, flags);
803 mixer_vsync_set_update(mixer_ctx, false);
805 mixer_cfg_layer(mixer_ctx, win, false);
807 mixer_vsync_set_update(mixer_ctx, true);
808 spin_unlock_irqrestore(&res->reg_slock, flags);
810 mixer_ctx->win_data[win].enabled = false;
813 static void mixer_wait_for_vblank(void *ctx)
815 struct mixer_context *mixer_ctx = ctx;
817 mutex_lock(&mixer_ctx->mixer_mutex);
818 if (!mixer_ctx->powered) {
819 mutex_unlock(&mixer_ctx->mixer_mutex);
822 mutex_unlock(&mixer_ctx->mixer_mutex);
824 atomic_set(&mixer_ctx->wait_vsync_event, 1);
827 * wait for MIXER to signal VSYNC interrupt or return after
828 * timeout which is set to 50ms (refresh rate of 20).
830 if (!wait_event_timeout(mixer_ctx->wait_vsync_queue,
831 !atomic_read(&mixer_ctx->wait_vsync_event),
833 DRM_DEBUG_KMS("vblank wait timed out.\n");
836 static void mixer_window_suspend(struct mixer_context *ctx)
838 struct hdmi_win_data *win_data;
841 for (i = 0; i < MIXER_WIN_NR; i++) {
842 win_data = &ctx->win_data[i];
843 win_data->resume = win_data->enabled;
844 mixer_win_disable(ctx, i);
846 mixer_wait_for_vblank(ctx);
849 static void mixer_window_resume(struct mixer_context *ctx)
851 struct hdmi_win_data *win_data;
854 for (i = 0; i < MIXER_WIN_NR; i++) {
855 win_data = &ctx->win_data[i];
856 win_data->enabled = win_data->resume;
857 win_data->resume = false;
861 static void mixer_poweron(struct mixer_context *ctx)
863 struct mixer_resources *res = &ctx->mixer_res;
865 DRM_DEBUG_KMS("[%d] %s\n", __LINE__, __func__);
867 mutex_lock(&ctx->mixer_mutex);
869 mutex_unlock(&ctx->mixer_mutex);
873 mutex_unlock(&ctx->mixer_mutex);
875 pm_runtime_get_sync(ctx->dev);
877 clk_enable(res->mixer);
878 if (ctx->vp_enabled) {
880 clk_enable(res->sclk_mixer);
883 mixer_reg_write(res, MXR_INT_EN, ctx->int_en);
884 mixer_win_reset(ctx);
886 mixer_window_resume(ctx);
889 static void mixer_poweroff(struct mixer_context *ctx)
891 struct mixer_resources *res = &ctx->mixer_res;
893 DRM_DEBUG_KMS("[%d] %s\n", __LINE__, __func__);
895 mutex_lock(&ctx->mixer_mutex);
898 mutex_unlock(&ctx->mixer_mutex);
900 mixer_window_suspend(ctx);
902 ctx->int_en = mixer_reg_read(res, MXR_INT_EN);
904 clk_disable(res->mixer);
905 if (ctx->vp_enabled) {
906 clk_disable(res->vp);
907 clk_disable(res->sclk_mixer);
910 pm_runtime_put_sync(ctx->dev);
912 mutex_lock(&ctx->mixer_mutex);
913 ctx->powered = false;
916 mutex_unlock(&ctx->mixer_mutex);
919 static void mixer_dpms(void *ctx, int mode)
921 struct mixer_context *mixer_ctx = ctx;
923 DRM_DEBUG_KMS("[%d] %s\n", __LINE__, __func__);
926 case DRM_MODE_DPMS_ON:
927 mixer_poweron(mixer_ctx);
929 case DRM_MODE_DPMS_STANDBY:
930 case DRM_MODE_DPMS_SUSPEND:
931 case DRM_MODE_DPMS_OFF:
932 mixer_poweroff(mixer_ctx);
935 DRM_DEBUG_KMS("unknown dpms mode: %d\n", mode);
940 static struct exynos_mixer_ops mixer_ops = {
942 .iommu_on = mixer_iommu_on,
943 .enable_vblank = mixer_enable_vblank,
944 .disable_vblank = mixer_disable_vblank,
945 .wait_for_vblank = mixer_wait_for_vblank,
949 .win_mode_set = mixer_win_mode_set,
950 .win_commit = mixer_win_commit,
951 .win_disable = mixer_win_disable,
954 /* for pageflip event */
955 static void mixer_finish_pageflip(struct drm_device *drm_dev, int crtc)
957 struct exynos_drm_private *dev_priv = drm_dev->dev_private;
958 struct drm_pending_vblank_event *e, *t;
962 spin_lock_irqsave(&drm_dev->event_lock, flags);
964 list_for_each_entry_safe(e, t, &dev_priv->pageflip_event_list,
966 /* if event's pipe isn't same as crtc then ignore it. */
970 do_gettimeofday(&now);
971 e->event.sequence = 0;
972 e->event.tv_sec = now.tv_sec;
973 e->event.tv_usec = now.tv_usec;
975 list_move_tail(&e->base.link, &e->base.file_priv->event_list);
976 wake_up_interruptible(&e->base.file_priv->event_wait);
977 drm_vblank_put(drm_dev, crtc);
980 spin_unlock_irqrestore(&drm_dev->event_lock, flags);
983 static irqreturn_t mixer_irq_handler(int irq, void *arg)
985 struct exynos_drm_hdmi_context *drm_hdmi_ctx = arg;
986 struct mixer_context *ctx = drm_hdmi_ctx->ctx;
987 struct mixer_resources *res = &ctx->mixer_res;
988 u32 val, base, shadow;
990 spin_lock(&res->reg_slock);
992 /* read interrupt status for handling and clearing flags for VSYNC */
993 val = mixer_reg_read(res, MXR_INT_STATUS);
996 if (val & MXR_INT_STATUS_VSYNC) {
997 /* interlace scan need to check shadow register */
998 if (ctx->interlace) {
999 base = mixer_reg_read(res, MXR_GRAPHIC_BASE(0));
1000 shadow = mixer_reg_read(res, MXR_GRAPHIC_BASE_S(0));
1004 base = mixer_reg_read(res, MXR_GRAPHIC_BASE(1));
1005 shadow = mixer_reg_read(res, MXR_GRAPHIC_BASE_S(1));
1010 drm_handle_vblank(drm_hdmi_ctx->drm_dev, ctx->pipe);
1011 mixer_finish_pageflip(drm_hdmi_ctx->drm_dev, ctx->pipe);
1013 /* set wait vsync event to zero and wake up queue. */
1014 if (atomic_read(&ctx->wait_vsync_event)) {
1015 atomic_set(&ctx->wait_vsync_event, 0);
1016 DRM_WAKEUP(&ctx->wait_vsync_queue);
1021 /* clear interrupts */
1022 if (~val & MXR_INT_EN_VSYNC) {
1023 /* vsync interrupt use different bit for read and clear */
1024 val &= ~MXR_INT_EN_VSYNC;
1025 val |= MXR_INT_CLEAR_VSYNC;
1027 mixer_reg_write(res, MXR_INT_STATUS, val);
1029 spin_unlock(&res->reg_slock);
1034 static int __devinit mixer_resources_init(struct exynos_drm_hdmi_context *ctx,
1035 struct platform_device *pdev)
1037 struct mixer_context *mixer_ctx = ctx->ctx;
1038 struct device *dev = &pdev->dev;
1039 struct mixer_resources *mixer_res = &mixer_ctx->mixer_res;
1040 struct resource *res;
1043 spin_lock_init(&mixer_res->reg_slock);
1045 mixer_res->mixer = devm_clk_get(dev, "mixer");
1046 if (IS_ERR_OR_NULL(mixer_res->mixer)) {
1047 dev_err(dev, "failed to get clock 'mixer'\n");
1051 mixer_res->sclk_hdmi = devm_clk_get(dev, "sclk_hdmi");
1052 if (IS_ERR_OR_NULL(mixer_res->sclk_hdmi)) {
1053 dev_err(dev, "failed to get clock 'sclk_hdmi'\n");
1056 res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
1058 dev_err(dev, "get memory resource failed.\n");
1062 mixer_res->mixer_regs = devm_ioremap(&pdev->dev, res->start,
1063 resource_size(res));
1064 if (mixer_res->mixer_regs == NULL) {
1065 dev_err(dev, "register mapping failed.\n");
1069 res = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
1071 dev_err(dev, "get interrupt resource failed.\n");
1075 ret = devm_request_irq(&pdev->dev, res->start, mixer_irq_handler,
1076 0, "drm_mixer", ctx);
1078 dev_err(dev, "request interrupt failed.\n");
1081 mixer_res->irq = res->start;
1086 static int __devinit vp_resources_init(struct exynos_drm_hdmi_context *ctx,
1087 struct platform_device *pdev)
1089 struct mixer_context *mixer_ctx = ctx->ctx;
1090 struct device *dev = &pdev->dev;
1091 struct mixer_resources *mixer_res = &mixer_ctx->mixer_res;
1092 struct resource *res;
1094 mixer_res->vp = devm_clk_get(dev, "vp");
1095 if (IS_ERR_OR_NULL(mixer_res->vp)) {
1096 dev_err(dev, "failed to get clock 'vp'\n");
1099 mixer_res->sclk_mixer = devm_clk_get(dev, "sclk_mixer");
1100 if (IS_ERR_OR_NULL(mixer_res->sclk_mixer)) {
1101 dev_err(dev, "failed to get clock 'sclk_mixer'\n");
1104 mixer_res->sclk_dac = devm_clk_get(dev, "sclk_dac");
1105 if (IS_ERR_OR_NULL(mixer_res->sclk_dac)) {
1106 dev_err(dev, "failed to get clock 'sclk_dac'\n");
1110 if (mixer_res->sclk_hdmi)
1111 clk_set_parent(mixer_res->sclk_mixer, mixer_res->sclk_hdmi);
1113 res = platform_get_resource(pdev, IORESOURCE_MEM, 1);
1115 dev_err(dev, "get memory resource failed.\n");
1119 mixer_res->vp_regs = devm_ioremap(&pdev->dev, res->start,
1120 resource_size(res));
1121 if (mixer_res->vp_regs == NULL) {
1122 dev_err(dev, "register mapping failed.\n");
1129 static struct mixer_drv_data exynos5_mxr_drv_data = {
1130 .version = MXR_VER_16_0_33_0,
1134 static struct mixer_drv_data exynos4_mxr_drv_data = {
1135 .version = MXR_VER_0_0_0_16,
1139 static struct platform_device_id mixer_driver_types[] = {
1141 .name = "s5p-mixer",
1142 .driver_data = (unsigned long)&exynos4_mxr_drv_data,
1144 .name = "exynos5-mixer",
1145 .driver_data = (unsigned long)&exynos5_mxr_drv_data,
1151 static struct of_device_id mixer_match_types[] = {
1153 .compatible = "samsung,exynos5-mixer",
1154 .data = &exynos5_mxr_drv_data,
1160 static int __devinit mixer_probe(struct platform_device *pdev)
1162 struct device *dev = &pdev->dev;
1163 struct exynos_drm_hdmi_context *drm_hdmi_ctx;
1164 struct mixer_context *ctx;
1165 struct mixer_drv_data *drv;
1168 dev_info(dev, "probe start\n");
1170 drm_hdmi_ctx = devm_kzalloc(&pdev->dev, sizeof(*drm_hdmi_ctx),
1172 if (!drm_hdmi_ctx) {
1173 DRM_ERROR("failed to allocate common hdmi context.\n");
1177 ctx = devm_kzalloc(&pdev->dev, sizeof(*ctx), GFP_KERNEL);
1179 DRM_ERROR("failed to alloc mixer context.\n");
1183 mutex_init(&ctx->mixer_mutex);
1186 const struct of_device_id *match;
1187 match = of_match_node(of_match_ptr(mixer_match_types),
1189 drv = (struct mixer_drv_data *)match->data;
1191 drv = (struct mixer_drv_data *)
1192 platform_get_device_id(pdev)->driver_data;
1195 ctx->dev = &pdev->dev;
1196 ctx->parent_ctx = (void *)drm_hdmi_ctx;
1197 drm_hdmi_ctx->ctx = (void *)ctx;
1198 ctx->vp_enabled = drv->is_vp_enabled;
1199 ctx->mxr_ver = drv->version;
1200 DRM_INIT_WAITQUEUE(&ctx->wait_vsync_queue);
1201 atomic_set(&ctx->wait_vsync_event, 0);
1203 platform_set_drvdata(pdev, drm_hdmi_ctx);
1205 /* acquire resources: regs, irqs, clocks */
1206 ret = mixer_resources_init(drm_hdmi_ctx, pdev);
1208 DRM_ERROR("mixer_resources_init failed\n");
1212 if (ctx->vp_enabled) {
1213 /* acquire vp resources: regs, irqs, clocks */
1214 ret = vp_resources_init(drm_hdmi_ctx, pdev);
1216 DRM_ERROR("vp_resources_init failed\n");
1221 /* attach mixer driver to common hdmi. */
1222 exynos_mixer_drv_attach(drm_hdmi_ctx);
1224 /* register specific callback point to common hdmi. */
1225 exynos_mixer_ops_register(&mixer_ops);
1227 pm_runtime_enable(dev);
1233 dev_info(dev, "probe failed\n");
1237 static int mixer_remove(struct platform_device *pdev)
1239 dev_info(&pdev->dev, "remove successful\n");
1241 pm_runtime_disable(&pdev->dev);
1246 #ifdef CONFIG_PM_SLEEP
1247 static int mixer_suspend(struct device *dev)
1249 struct exynos_drm_hdmi_context *drm_hdmi_ctx = get_mixer_context(dev);
1250 struct mixer_context *ctx = drm_hdmi_ctx->ctx;
1252 mixer_poweroff(ctx);
1258 static SIMPLE_DEV_PM_OPS(mixer_pm_ops, mixer_suspend, NULL);
1260 struct platform_driver mixer_driver = {
1262 .name = "exynos-mixer",
1263 .owner = THIS_MODULE,
1264 .pm = &mixer_pm_ops,
1265 .of_match_table = mixer_match_types,
1267 .probe = mixer_probe,
1268 .remove = __devexit_p(mixer_remove),
1269 .id_table = mixer_driver_types,