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"
40 #include <plat/map-base.h>
41 #ifdef CONFIG_EXYNOS_IOMMU
42 #include <mach/sysmmu.h>
43 #include <linux/of_platform.h>
46 #define MIXER_WIN_NR 3
47 #define MIXER_DEFAULT_WIN 0
49 #define get_mixer_context(dev) platform_get_drvdata(to_platform_device(dev))
51 struct hdmi_win_data {
54 dma_addr_t chroma_dma_addr;
55 void __iomem *chroma_vaddr;
56 uint32_t pixel_format;
60 unsigned int crtc_width;
61 unsigned int crtc_height;
64 unsigned int fb_width;
65 unsigned int fb_height;
66 unsigned int mode_width;
67 unsigned int mode_height;
68 unsigned int scan_flags;
71 struct mixer_resources {
74 void __iomem *mixer_regs;
75 void __iomem *vp_regs;
77 wait_queue_head_t event_queue;
80 struct clk *sclk_mixer;
81 struct clk *sclk_hdmi;
83 unsigned int is_soc_exynos5;
86 struct mixer_context {
91 struct mixer_resources mixer_res;
92 struct hdmi_win_data win_data[MIXER_WIN_NR];
93 unsigned long event_flags;
96 /* event flags used */
97 enum mixer_status_flags {
101 static const u8 filter_y_horiz_tap8[] = {
102 0, -1, -1, -1, -1, -1, -1, -1,
103 -1, -1, -1, -1, -1, 0, 0, 0,
104 0, 2, 4, 5, 6, 6, 6, 6,
105 6, 5, 5, 4, 3, 2, 1, 1,
106 0, -6, -12, -16, -18, -20, -21, -20,
107 -20, -18, -16, -13, -10, -8, -5, -2,
108 127, 126, 125, 121, 114, 107, 99, 89,
109 79, 68, 57, 46, 35, 25, 16, 8,
112 static const u8 filter_y_vert_tap4[] = {
113 0, -3, -6, -8, -8, -8, -8, -7,
114 -6, -5, -4, -3, -2, -1, -1, 0,
115 127, 126, 124, 118, 111, 102, 92, 81,
116 70, 59, 48, 37, 27, 19, 11, 5,
117 0, 5, 11, 19, 27, 37, 48, 59,
118 70, 81, 92, 102, 111, 118, 124, 126,
119 0, 0, -1, -1, -2, -3, -4, -5,
120 -6, -7, -8, -8, -8, -8, -6, -3,
123 static const u8 filter_cr_horiz_tap4[] = {
124 0, -3, -6, -8, -8, -8, -8, -7,
125 -6, -5, -4, -3, -2, -1, -1, 0,
126 127, 126, 124, 118, 111, 102, 92, 81,
127 70, 59, 48, 37, 27, 19, 11, 5,
130 static void mixer_win_reset(struct mixer_context *ctx);
132 static inline u32 vp_reg_read(struct mixer_resources *res, u32 reg_id)
134 return readl(res->vp_regs + reg_id);
137 static inline void vp_reg_write(struct mixer_resources *res, u32 reg_id,
140 writel(val, res->vp_regs + reg_id);
143 static inline void vp_reg_writemask(struct mixer_resources *res, u32 reg_id,
146 u32 old = vp_reg_read(res, reg_id);
148 val = (val & mask) | (old & ~mask);
149 writel(val, res->vp_regs + reg_id);
152 static inline u32 mixer_reg_read(struct mixer_resources *res, u32 reg_id)
154 return readl(res->mixer_regs + reg_id);
157 static inline void mixer_reg_write(struct mixer_resources *res, u32 reg_id,
160 writel(val, res->mixer_regs + reg_id);
163 static inline void mixer_reg_writemask(struct mixer_resources *res,
164 u32 reg_id, u32 val, u32 mask)
166 u32 old = mixer_reg_read(res, reg_id);
168 val = (val & mask) | (old & ~mask);
169 writel(val, res->mixer_regs + reg_id);
172 static void mixer_regs_dump(struct mixer_context *ctx)
174 #define DUMPREG(reg_id) \
176 DRM_DEBUG_KMS(#reg_id " = %08x\n", \
177 (u32)readl(ctx->mixer_res.mixer_regs + reg_id)); \
183 DUMPREG(MXR_INT_STATUS);
185 DUMPREG(MXR_LAYER_CFG);
186 DUMPREG(MXR_VIDEO_CFG);
188 DUMPREG(MXR_GRAPHIC0_CFG);
189 DUMPREG(MXR_GRAPHIC0_BASE);
190 DUMPREG(MXR_GRAPHIC0_SPAN);
191 DUMPREG(MXR_GRAPHIC0_WH);
192 DUMPREG(MXR_GRAPHIC0_SXY);
193 DUMPREG(MXR_GRAPHIC0_DXY);
195 DUMPREG(MXR_GRAPHIC1_CFG);
196 DUMPREG(MXR_GRAPHIC1_BASE);
197 DUMPREG(MXR_GRAPHIC1_SPAN);
198 DUMPREG(MXR_GRAPHIC1_WH);
199 DUMPREG(MXR_GRAPHIC1_SXY);
200 DUMPREG(MXR_GRAPHIC1_DXY);
204 static void vp_regs_dump(struct mixer_context *ctx)
206 #define DUMPREG(reg_id) \
208 DRM_DEBUG_KMS(#reg_id " = %08x\n", \
209 (u32) readl(ctx->mixer_res.vp_regs + reg_id)); \
214 DUMPREG(VP_SHADOW_UPDATE);
215 DUMPREG(VP_FIELD_ID);
217 DUMPREG(VP_IMG_SIZE_Y);
218 DUMPREG(VP_IMG_SIZE_C);
219 DUMPREG(VP_PER_RATE_CTRL);
220 DUMPREG(VP_TOP_Y_PTR);
221 DUMPREG(VP_BOT_Y_PTR);
222 DUMPREG(VP_TOP_C_PTR);
223 DUMPREG(VP_BOT_C_PTR);
224 DUMPREG(VP_ENDIAN_MODE);
225 DUMPREG(VP_SRC_H_POSITION);
226 DUMPREG(VP_SRC_V_POSITION);
227 DUMPREG(VP_SRC_WIDTH);
228 DUMPREG(VP_SRC_HEIGHT);
229 DUMPREG(VP_DST_H_POSITION);
230 DUMPREG(VP_DST_V_POSITION);
231 DUMPREG(VP_DST_WIDTH);
232 DUMPREG(VP_DST_HEIGHT);
239 static inline void vp_filter_set(struct mixer_resources *res,
240 int reg_id, const u8 *data, unsigned int size)
242 /* assure 4-byte align */
244 for (; size; size -= 4, reg_id += 4, data += 4) {
245 u32 val = (data[0] << 24) | (data[1] << 16) |
246 (data[2] << 8) | data[3];
247 vp_reg_write(res, reg_id, val);
251 static void vp_default_filter(struct mixer_resources *res)
253 vp_filter_set(res, VP_POLY8_Y0_LL,
254 filter_y_horiz_tap8, sizeof filter_y_horiz_tap8);
255 vp_filter_set(res, VP_POLY4_Y0_LL,
256 filter_y_vert_tap4, sizeof filter_y_vert_tap4);
257 vp_filter_set(res, VP_POLY4_C0_LL,
258 filter_cr_horiz_tap4, sizeof filter_cr_horiz_tap4);
261 static void mixer_vsync_set_update(struct mixer_context *ctx, bool enable)
263 struct mixer_resources *res = &ctx->mixer_res;
265 /* block update on vsync */
266 mixer_reg_writemask(res, MXR_STATUS, enable ?
267 MXR_STATUS_SYNC_ENABLE : 0, MXR_STATUS_SYNC_ENABLE);
269 if (!(res->is_soc_exynos5))
270 vp_reg_write(res, VP_SHADOW_UPDATE, enable ?
271 VP_SHADOW_UPDATE_ENABLE : 0);
274 static void mixer_cfg_scan(struct mixer_context *ctx, unsigned int height)
276 struct mixer_resources *res = &ctx->mixer_res;
279 /* choosing between interlace and progressive mode */
280 val = (ctx->interlace ? MXR_CFG_SCAN_INTERLACE :
281 MXR_CFG_SCAN_PROGRASSIVE);
283 /* choosing between porper HD and SD mode */
285 val |= MXR_CFG_SCAN_NTSC | MXR_CFG_SCAN_SD;
286 else if (height == 576)
287 val |= MXR_CFG_SCAN_PAL | MXR_CFG_SCAN_SD;
288 else if (height == 720)
289 val |= MXR_CFG_SCAN_HD_720 | MXR_CFG_SCAN_HD;
290 else if (height == 1080)
291 val |= MXR_CFG_SCAN_HD_1080 | MXR_CFG_SCAN_HD;
293 val |= MXR_CFG_SCAN_HD_720 | MXR_CFG_SCAN_HD;
295 mixer_reg_writemask(res, MXR_CFG, val, MXR_CFG_SCAN_MASK);
298 static void mixer_cfg_rgb_fmt(struct mixer_context *ctx, unsigned int height)
300 struct mixer_resources *res = &ctx->mixer_res;
304 val = MXR_CFG_RGB601_0_255;
305 } else if (height == 576) {
306 val = MXR_CFG_RGB601_0_255;
307 } else if (height == 720) {
308 val = MXR_CFG_RGB709_16_235;
309 mixer_reg_write(res, MXR_CM_COEFF_Y,
310 (1 << 30) | (94 << 20) | (314 << 10) |
312 mixer_reg_write(res, MXR_CM_COEFF_CB,
313 (972 << 20) | (851 << 10) | (225 << 0));
314 mixer_reg_write(res, MXR_CM_COEFF_CR,
315 (225 << 20) | (820 << 10) | (1004 << 0));
316 } else if (height == 1080) {
317 val = MXR_CFG_RGB709_16_235;
318 mixer_reg_write(res, MXR_CM_COEFF_Y,
319 (1 << 30) | (94 << 20) | (314 << 10) |
321 mixer_reg_write(res, MXR_CM_COEFF_CB,
322 (972 << 20) | (851 << 10) | (225 << 0));
323 mixer_reg_write(res, MXR_CM_COEFF_CR,
324 (225 << 20) | (820 << 10) | (1004 << 0));
326 val = MXR_CFG_RGB709_16_235;
327 mixer_reg_write(res, MXR_CM_COEFF_Y,
328 (1 << 30) | (94 << 20) | (314 << 10) |
330 mixer_reg_write(res, MXR_CM_COEFF_CB,
331 (972 << 20) | (851 << 10) | (225 << 0));
332 mixer_reg_write(res, MXR_CM_COEFF_CR,
333 (225 << 20) | (820 << 10) | (1004 << 0));
336 mixer_reg_writemask(res, MXR_CFG, val, MXR_CFG_RGB_FMT_MASK);
339 static void mixer_cfg_layer(struct mixer_context *ctx, int win, bool enable)
341 struct mixer_resources *res = &ctx->mixer_res;
342 u32 val = enable ? ~0 : 0;
346 mixer_reg_writemask(res, MXR_CFG, val, MXR_CFG_GRP0_ENABLE);
349 mixer_reg_writemask(res, MXR_CFG, val, MXR_CFG_GRP1_ENABLE);
352 vp_reg_writemask(res, VP_ENABLE, val, VP_ENABLE_ON);
353 mixer_reg_writemask(res, MXR_CFG, val, MXR_CFG_VP_ENABLE);
358 static void mixer_run(struct mixer_context *ctx)
360 struct mixer_resources *res = &ctx->mixer_res;
362 mixer_reg_writemask(res, MXR_STATUS, ~0, MXR_STATUS_REG_RUN);
364 mixer_regs_dump(ctx);
367 static int mixer_wait_for_vsync(struct mixer_context *ctx)
371 ctx->event_flags |= MXR_EVENT_VSYNC;
373 ret = wait_event_timeout(ctx->mixer_res.event_queue,
374 ((ctx->event_flags & MXR_EVENT_VSYNC) == 0), msecs_to_jiffies(1000));
381 static void vp_video_buffer(struct mixer_context *ctx, int win)
383 struct mixer_resources *res = &ctx->mixer_res;
385 struct hdmi_win_data *win_data;
386 unsigned int full_width, full_height, width, height;
387 unsigned int x_ratio, y_ratio;
388 unsigned int src_x_offset, src_y_offset, dst_x_offset, dst_y_offset;
389 unsigned int mode_width, mode_height;
390 unsigned int buf_num;
391 dma_addr_t luma_addr[2], chroma_addr[2];
392 bool tiled_mode = false;
393 bool crcb_mode = false;
396 win_data = &ctx->win_data[win];
398 switch (win_data->pixel_format) {
399 case DRM_FORMAT_NV12MT:
401 case DRM_FORMAT_NV12M:
405 /* TODO: single buffer format NV12, NV21 */
407 /* ignore pixel format at disable time */
408 if (!win_data->dma_addr)
411 DRM_ERROR("pixel format for vp is wrong [%d].\n",
412 win_data->pixel_format);
416 full_width = win_data->fb_width;
417 full_height = win_data->fb_height;
418 width = win_data->crtc_width;
419 height = win_data->crtc_height;
420 mode_width = win_data->mode_width;
421 mode_height = win_data->mode_height;
423 /* scaling feature: (src << 16) / dst */
424 x_ratio = (width << 16) / width;
425 y_ratio = (height << 16) / height;
427 src_x_offset = win_data->fb_x;
428 src_y_offset = win_data->fb_y;
429 dst_x_offset = win_data->crtc_x;
430 dst_y_offset = win_data->crtc_y;
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 + (full_width * full_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] + full_width;
448 chroma_addr[1] = chroma_addr[0] + full_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(full_width) |
470 VP_IMG_VSIZE(full_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(full_width) |
473 VP_IMG_VSIZE(full_height / 2));
475 vp_reg_write(res, VP_SRC_WIDTH, width);
476 vp_reg_write(res, VP_SRC_HEIGHT, height);
477 vp_reg_write(res, VP_SRC_H_POSITION,
478 VP_SRC_H_POSITION_VAL(src_x_offset));
479 vp_reg_write(res, VP_SRC_V_POSITION, src_y_offset);
481 vp_reg_write(res, VP_DST_WIDTH, width);
482 vp_reg_write(res, VP_DST_H_POSITION, dst_x_offset);
483 if (ctx->interlace) {
484 vp_reg_write(res, VP_DST_HEIGHT, height / 2);
485 vp_reg_write(res, VP_DST_V_POSITION, dst_y_offset / 2);
487 vp_reg_write(res, VP_DST_HEIGHT, height);
488 vp_reg_write(res, VP_DST_V_POSITION, dst_y_offset);
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, mode_height);
503 mixer_cfg_rgb_fmt(ctx, 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_graph_buffer(struct mixer_context *ctx, int win)
515 struct mixer_resources *res = &ctx->mixer_res;
517 struct hdmi_win_data *win_data;
518 unsigned int full_width, width, height;
519 unsigned int x_ratio, y_ratio;
520 unsigned int src_x_offset, src_y_offset, dst_x_offset, dst_y_offset;
521 unsigned int mode_width, mode_height;
526 win_data = &ctx->win_data[win];
533 switch (win_data->bpp) {
544 dma_addr = win_data->dma_addr;
545 full_width = win_data->fb_width;
546 width = win_data->crtc_width;
547 height = win_data->crtc_height;
548 mode_width = win_data->mode_width;
549 mode_height = win_data->mode_height;
551 /* 2x scaling feature */
555 src_x_offset = win_data->fb_x;
556 src_y_offset = win_data->fb_y;
557 dst_x_offset = win_data->crtc_x;
558 dst_y_offset = win_data->crtc_y;
560 /* converting dma address base and source offset */
562 + (src_x_offset * win_data->bpp >> 3)
563 + (src_y_offset * full_width * win_data->bpp >> 3);
567 if (win_data->scan_flags & DRM_MODE_FLAG_INTERLACE)
568 ctx->interlace = true;
570 ctx->interlace = false;
572 spin_lock_irqsave(&res->reg_slock, flags);
573 mixer_vsync_set_update(ctx, false);
576 mixer_reg_writemask(res, MXR_GRAPHIC_CFG(win),
577 MXR_GRP_CFG_FORMAT_VAL(fmt), MXR_GRP_CFG_FORMAT_MASK);
580 mixer_reg_write(res, MXR_GRAPHIC_SPAN(win), full_width);
582 val = MXR_GRP_WH_WIDTH(width);
583 val |= MXR_GRP_WH_HEIGHT(height);
584 val |= MXR_GRP_WH_H_SCALE(x_ratio);
585 val |= MXR_GRP_WH_V_SCALE(y_ratio);
586 mixer_reg_write(res, MXR_GRAPHIC_WH(win), val);
588 /* setup offsets in source image */
589 val = MXR_GRP_SXY_SX(src_x_offset);
590 val |= MXR_GRP_SXY_SY(src_y_offset);
591 mixer_reg_write(res, MXR_GRAPHIC_SXY(win), val);
593 /* setup offsets in display image */
594 val = MXR_GRP_DXY_DX(dst_x_offset);
595 val |= MXR_GRP_DXY_DY(dst_y_offset);
596 mixer_reg_write(res, MXR_GRAPHIC_DXY(win), val);
598 /* set buffer address to mixer */
599 mixer_reg_write(res, MXR_GRAPHIC_BASE(win), dma_addr);
601 mixer_cfg_scan(ctx, mode_height);
602 mixer_cfg_rgb_fmt(ctx, mode_height);
603 mixer_cfg_layer(ctx, win, true);
604 mixer_cfg_layer(ctx, MIXER_DEFAULT_WIN, true);
607 mixer_vsync_set_update(ctx, true);
608 spin_unlock_irqrestore(&res->reg_slock, flags);
611 static void vp_win_reset(struct mixer_context *ctx)
613 struct mixer_resources *res = &ctx->mixer_res;
616 vp_reg_write(res, VP_SRESET, VP_SRESET_PROCESSING);
617 for (tries = 100; tries; --tries) {
618 /* waiting until VP_SRESET_PROCESSING is 0 */
619 if (~vp_reg_read(res, VP_SRESET) & VP_SRESET_PROCESSING)
623 WARN(tries == 0, "failed to reset Video Processor\n");
626 static int mixer_enable_vblank(void *ctx, int pipe)
628 struct mixer_context *mixer_ctx = ctx;
629 struct mixer_resources *res = &mixer_ctx->mixer_res;
631 DRM_DEBUG_KMS("[%d] %s\n", __LINE__, __func__);
633 /* enable vsync interrupt */
634 mixer_reg_writemask(res, MXR_INT_EN, MXR_INT_EN_VSYNC,
640 static void mixer_disable_vblank(void *ctx)
642 struct mixer_context *mixer_ctx = ctx;
643 struct mixer_resources *res = &mixer_ctx->mixer_res;
645 DRM_DEBUG_KMS("[%d] %s\n", __LINE__, __func__);
647 /* disable vsync interrupt */
648 mixer_reg_writemask(res, MXR_INT_EN, 0, MXR_INT_EN_VSYNC);
651 static void mixer_win_mode_set(void *ctx,
652 struct exynos_drm_overlay *overlay)
654 struct mixer_context *mixer_ctx = ctx;
655 struct hdmi_win_data *win_data;
658 DRM_DEBUG_KMS("[%d] %s\n", __LINE__, __func__);
661 DRM_ERROR("overlay is NULL\n");
665 DRM_DEBUG_KMS("set [%d]x[%d] at (%d,%d) to [%d]x[%d] at (%d,%d)\n",
666 overlay->fb_width, overlay->fb_height,
667 overlay->fb_x, overlay->fb_y,
668 overlay->crtc_width, overlay->crtc_height,
669 overlay->crtc_x, overlay->crtc_y);
672 if (win == DEFAULT_ZPOS)
673 win = MIXER_DEFAULT_WIN;
675 if (win < 0 || win > MIXER_WIN_NR) {
676 DRM_ERROR("overlay plane[%d] is wrong\n", win);
680 win_data = &mixer_ctx->win_data[win];
682 win_data->dma_addr = overlay->dma_addr[0];
683 win_data->vaddr = overlay->vaddr[0];
684 win_data->chroma_dma_addr = overlay->dma_addr[1];
685 win_data->chroma_vaddr = overlay->vaddr[1];
686 win_data->pixel_format = overlay->pixel_format;
687 win_data->bpp = overlay->bpp;
689 win_data->crtc_x = overlay->crtc_x;
690 win_data->crtc_y = overlay->crtc_y;
691 win_data->crtc_width = overlay->crtc_width;
692 win_data->crtc_height = overlay->crtc_height;
694 win_data->fb_x = overlay->fb_x;
695 win_data->fb_y = overlay->fb_y;
696 win_data->fb_width = overlay->fb_width;
697 win_data->fb_height = overlay->fb_height;
699 win_data->mode_width = overlay->mode_width;
700 win_data->mode_height = overlay->mode_height;
702 win_data->scan_flags = overlay->scan_flag;
705 static void mixer_win_commit(void *ctx, int zpos)
707 struct mixer_context *mixer_ctx = ctx;
708 struct mixer_resources *res = &mixer_ctx->mixer_res;
711 DRM_DEBUG_KMS("[%d] %s, win: %d\n", __LINE__, __func__, win);
713 if (win == DEFAULT_ZPOS)
714 win = MIXER_DEFAULT_WIN;
716 if (win < 0 || win > MIXER_WIN_NR) {
717 DRM_ERROR("overlay plane[%d] is wrong\n", win);
721 if (!(res->is_soc_exynos5)) {
723 vp_video_buffer(mixer_ctx, win);
725 mixer_graph_buffer(mixer_ctx, win);
728 mixer_graph_buffer(mixer_ctx, win);
731 static void mixer_win_disable(void *ctx, int zpos)
733 struct mixer_context *mixer_ctx = ctx;
734 struct mixer_resources *res = &mixer_ctx->mixer_res;
738 DRM_DEBUG_KMS("[%d] %s, win: %d\n", __LINE__, __func__, win);
740 if (win == DEFAULT_ZPOS)
741 win = MIXER_DEFAULT_WIN;
743 if (win < 0 || win > MIXER_WIN_NR) {
744 DRM_ERROR("overlay plane[%d] is wrong\n", win);
748 mixer_wait_for_vsync(mixer_ctx);
750 spin_lock_irqsave(&res->reg_slock, flags);
751 mixer_vsync_set_update(mixer_ctx, false);
753 mixer_cfg_layer(mixer_ctx, win, false);
755 mixer_vsync_set_update(mixer_ctx, true);
757 spin_unlock_irqrestore(&res->reg_slock, flags);
759 if (win == MIXER_DEFAULT_WIN) {
760 mixer_win_reset(ctx);
761 mixer_enable_vblank(ctx, 0);
765 static struct exynos_mixer_ops mixer_ops = {
767 .enable_vblank = mixer_enable_vblank,
768 .disable_vblank = mixer_disable_vblank,
771 .win_mode_set = mixer_win_mode_set,
772 .win_commit = mixer_win_commit,
773 .win_disable = mixer_win_disable,
776 /* for pageflip event */
777 static void mixer_finish_pageflip(struct drm_device *drm_dev, int crtc)
779 struct exynos_drm_private *dev_priv = drm_dev->dev_private;
780 struct drm_pending_vblank_event *e, *t;
783 bool is_checked = false;
785 spin_lock_irqsave(&drm_dev->event_lock, flags);
787 list_for_each_entry_safe(e, t, &dev_priv->pageflip_event_list,
789 /* if event's pipe isn't same as crtc then ignore it. */
794 do_gettimeofday(&now);
795 e->event.sequence = 0;
796 e->event.tv_sec = now.tv_sec;
797 e->event.tv_usec = now.tv_usec;
799 list_move_tail(&e->base.link, &e->base.file_priv->event_list);
800 wake_up_interruptible(&e->base.file_priv->event_wait);
805 * call drm_vblank_put only in case that drm_vblank_get was
808 if (atomic_read(&drm_dev->vblank_refcount[crtc]) > 0)
809 drm_vblank_put(drm_dev, crtc);
811 spin_unlock_irqrestore(&drm_dev->event_lock, flags);
814 static irqreturn_t mixer_irq_handler(int irq, void *arg)
816 struct exynos_drm_hdmi_context *drm_hdmi_ctx = arg;
817 struct mixer_context *ctx = drm_hdmi_ctx->ctx;
818 struct mixer_resources *res = &ctx->mixer_res;
821 spin_lock(&res->reg_slock);
823 /* read interrupt status for handling and clearing flags for VSYNC */
824 val = mixer_reg_read(res, MXR_INT_STATUS);
827 if (val & MXR_INT_STATUS_VSYNC) {
829 if (ctx->event_flags & MXR_EVENT_VSYNC) {
830 DRM_DEBUG_KMS("ctx->event_flags & MXR_EVENT_VSYNC");
833 mixer_reg_write(res, MXR_GRAPHIC_WH(1), 0);
834 mixer_reg_write(res, MXR_GRAPHIC_SPAN(1), 0);
835 mixer_reg_write(res, MXR_GRAPHIC_SXY(1), 0);
836 mixer_reg_write(res, MXR_GRAPHIC_DXY(1), 0);
838 ctx->event_flags &= ~MXR_EVENT_VSYNC;
839 wake_up(&ctx->mixer_res.event_queue);
844 /* interlace scan need to check shadow register */
845 if (ctx->interlace) {
846 val_base = mixer_reg_read(res, MXR_GRAPHIC_BASE_S(0));
847 if (ctx->win_data[0].dma_addr != val_base)
850 val_base = mixer_reg_read(res, MXR_GRAPHIC_BASE_S(1));
851 if (ctx->win_data[1].dma_addr != val_base)
855 drm_handle_vblank(drm_hdmi_ctx->drm_dev, ctx->pipe);
856 mixer_finish_pageflip(drm_hdmi_ctx->drm_dev, ctx->pipe);
858 /* layer update mandatory for exynos5 soc,and not present
860 if (res->is_soc_exynos5)
861 mixer_reg_writemask(res, MXR_CFG, ~0, MXR_CFG_LAYER_UPDATE);
865 /* clear interrupts */
866 if (~val & MXR_INT_EN_VSYNC) {
867 /* vsync interrupt use different bit for read and clear */
868 val &= ~MXR_INT_EN_VSYNC;
869 val |= MXR_INT_CLEAR_VSYNC;
871 mixer_reg_write(res, MXR_INT_STATUS, val);
873 spin_unlock(&res->reg_slock);
878 static void mixer_win_reset(struct mixer_context *ctx)
880 struct mixer_resources *res = &ctx->mixer_res;
882 u32 val; /* value stored to register */
884 spin_lock_irqsave(&res->reg_slock, flags);
885 mixer_reg_writemask(res, MXR_STATUS, ~0, MXR_STATUS_SOFT_RESET);
886 mixer_vsync_set_update(ctx, false);
888 mixer_reg_writemask(res, MXR_CFG, MXR_CFG_DST_HDMI, MXR_CFG_DST_MASK);
890 /* set output in RGB888 mode */
891 mixer_reg_writemask(res, MXR_CFG, MXR_CFG_OUT_RGB888, MXR_CFG_OUT_MASK);
893 /* 16 beat burst in DMA */
894 mixer_reg_writemask(res, MXR_STATUS, MXR_STATUS_16_BURST,
895 MXR_STATUS_BURST_MASK);
897 /* setting default layer priority: layer1 > layer0 > video
898 * because typical usage scenario would be
900 * layer0 - framebuffer
901 * video - video overlay
903 val = MXR_LAYER_CFG_GRP1_VAL(3);
904 val |= MXR_LAYER_CFG_GRP0_VAL(2);
905 val |= MXR_LAYER_CFG_VP_VAL(1);
906 mixer_reg_write(res, MXR_LAYER_CFG, val);
908 /* setting background color */
909 mixer_reg_write(res, MXR_BG_COLOR0, 0x008080);
910 mixer_reg_write(res, MXR_BG_COLOR1, 0x008080);
911 mixer_reg_write(res, MXR_BG_COLOR2, 0x008080);
913 /* setting graphical layers */
915 val = MXR_GRP_CFG_COLOR_KEY_DISABLE; /* no blank key */
916 val |= MXR_GRP_CFG_WIN_BLEND_EN;
917 val |= MXR_GRP_CFG_ALPHA_VAL(0xff); /* non-transparent alpha */
919 /* the same configuration for both layers */
920 mixer_reg_write(res, MXR_GRAPHIC_CFG(0), val);
922 val |= MXR_GRP_CFG_BLEND_PRE_MUL;
923 val |= MXR_GRP_CFG_PIXEL_BLEND_EN;
924 mixer_reg_write(res, MXR_GRAPHIC_CFG(1), val);
926 if (!(res->is_soc_exynos5)) {
927 /* configuration of Video Processor for Exynos4 soc */
929 vp_default_filter(res);
932 /* disable all layers */
933 mixer_reg_writemask(res, MXR_CFG, 0, MXR_CFG_GRP0_ENABLE);
934 mixer_reg_writemask(res, MXR_CFG, 0, MXR_CFG_GRP1_ENABLE);
935 mixer_reg_writemask(res, MXR_CFG, 0, MXR_CFG_VP_ENABLE);
937 mixer_reg_writemask(res, MXR_INT_EN, ~0, MXR_INT_EN_ALL);
939 mixer_vsync_set_update(ctx, true);
940 spin_unlock_irqrestore(&res->reg_slock, flags);
943 static void mixer_resource_poweron(struct mixer_context *ctx)
945 struct mixer_resources *res = &ctx->mixer_res;
947 DRM_DEBUG_KMS("[%d] %s\n", __LINE__, __func__);
949 clk_enable(res->mixer);
950 if (!(res->is_soc_exynos5)) {
952 clk_enable(res->sclk_mixer);
955 mixer_win_reset(ctx);
958 static void mixer_resource_poweroff(struct mixer_context *ctx)
960 struct mixer_resources *res = &ctx->mixer_res;
962 DRM_DEBUG_KMS("[%d] %s\n", __LINE__, __func__);
964 clk_disable(res->mixer);
965 if (!(res->is_soc_exynos5)) {
966 clk_disable(res->vp);
967 clk_disable(res->sclk_mixer);
971 static int mixer_runtime_resume(struct device *dev)
973 struct exynos_drm_hdmi_context *ctx = get_mixer_context(dev);
975 DRM_DEBUG_KMS("resume - start\n");
977 mixer_resource_poweron(ctx->ctx);
982 static int mixer_runtime_suspend(struct device *dev)
984 struct exynos_drm_hdmi_context *ctx = get_mixer_context(dev);
986 DRM_DEBUG_KMS("suspend - start\n");
988 mixer_resource_poweroff(ctx->ctx);
993 static const struct dev_pm_ops mixer_pm_ops = {
994 .runtime_suspend = mixer_runtime_suspend,
995 .runtime_resume = mixer_runtime_resume,
998 #ifdef CONFIG_EXYNOS_IOMMU
999 static int iommu_init(struct platform_device *pdev)
1001 struct platform_device *pds;
1003 pds = find_sysmmu_dt(pdev, "sysmmu");
1005 printk(KERN_ERR "No sysmmu found :\n");
1009 platform_set_sysmmu(&pds->dev, &pdev->dev);
1010 exynos_drm_common_mapping = s5p_create_iommu_mapping(&pdev->dev,
1011 0x20000000, SZ_128M, 4, exynos_drm_common_mapping);
1012 if(exynos_drm_common_mapping == NULL) {
1013 printk(KERN_ERR"Failed to create iommu mapping for Mixer\n");
1021 static int __devinit mixer_resources_init_exynos(
1022 struct exynos_drm_hdmi_context *ctx,
1023 struct platform_device *pdev,
1026 struct mixer_context *mixer_ctx = ctx->ctx;
1027 struct device *dev = &pdev->dev;
1028 struct mixer_resources *mixer_res = &mixer_ctx->mixer_res;
1029 struct resource *res;
1032 DRM_DEBUG_KMS("Mixer resources init\n");
1034 mixer_res->is_soc_exynos5 = is_exynos5;
1035 mixer_res->dev = dev;
1036 spin_lock_init(&mixer_res->reg_slock);
1039 init_waitqueue_head(&mixer_res->event_queue);
1041 mixer_res->mixer = clk_get(dev, "mixer");
1042 if (IS_ERR_OR_NULL(mixer_res->mixer)) {
1043 dev_err(dev, "failed to get clock 'mixer'\n");
1048 mixer_res->vp = clk_get(dev, "vp");
1049 if (IS_ERR_OR_NULL(mixer_res->vp)) {
1050 dev_err(dev, "failed to get clock 'vp'\n");
1054 mixer_res->sclk_mixer = clk_get(dev, "sclk_mixer");
1055 if (IS_ERR_OR_NULL(mixer_res->sclk_mixer)) {
1056 dev_err(dev, "failed to get clock 'sclk_mixer'\n");
1061 mixer_res->sclk_hdmi = clk_get(dev, "sclk_hdmi");
1062 if (IS_ERR_OR_NULL(mixer_res->sclk_hdmi)) {
1063 dev_err(dev, "failed to get clock 'sclk_hdmi'\n");
1068 mixer_res->sclk_dac = clk_get(dev, "sclk_dac");
1069 if (IS_ERR_OR_NULL(mixer_res->sclk_dac)) {
1070 dev_err(dev, "failed to get clock 'sclk_dac'\n");
1074 res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "mxr");
1077 res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
1080 dev_err(dev, "get memory resource failed.\n");
1086 clk_set_parent(mixer_res->sclk_mixer, mixer_res->sclk_hdmi);
1088 mixer_res->mixer_regs = ioremap(res->start, resource_size(res));
1089 if (mixer_res->mixer_regs == NULL) {
1090 dev_err(dev, "register mapping failed.\n");
1096 res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "vp");
1098 dev_err(dev, "get memory resource failed.\n");
1103 mixer_res->vp_regs = ioremap(res->start, resource_size(res));
1104 if (mixer_res->vp_regs == NULL) {
1105 dev_err(dev, "register mapping failed.\n");
1110 res = platform_get_resource_byname(pdev, IORESOURCE_IRQ, "irq");
1112 dev_err(dev, "get interrupt resource failed.\n");
1117 res = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
1119 dev_err(dev, "get interrupt resource failed.\n");
1121 goto fail_mixer_regs;
1125 ret = request_irq(res->start, mixer_irq_handler, 0, "drm_mixer", ctx);
1127 dev_err(dev, "request interrupt failed.\n");
1128 goto fail_mixer_regs;
1130 mixer_res->irq = res->start;
1132 #ifdef CONFIG_EXYNOS_IOMMU
1133 ret = iommu_init(pdev);
1135 dev_err(dev, "iommu init failed.\n");
1136 goto fail_mixer_regs;
1142 iounmap(mixer_res->vp_regs);
1145 iounmap(mixer_res->mixer_regs);
1148 if (!IS_ERR_OR_NULL(mixer_res->sclk_dac))
1149 clk_put(mixer_res->sclk_dac);
1150 if (!IS_ERR_OR_NULL(mixer_res->sclk_hdmi))
1151 clk_put(mixer_res->sclk_hdmi);
1152 if (!IS_ERR_OR_NULL(mixer_res->sclk_mixer))
1153 clk_put(mixer_res->sclk_mixer);
1154 if (!IS_ERR_OR_NULL(mixer_res->vp))
1155 clk_put(mixer_res->vp);
1156 if (!IS_ERR_OR_NULL(mixer_res->mixer))
1157 clk_put(mixer_res->mixer);
1158 mixer_res->dev = NULL;
1162 static void mixer_resources_cleanup(struct mixer_context *ctx)
1164 struct mixer_resources *res = &ctx->mixer_res;
1166 disable_irq(res->irq);
1167 free_irq(res->irq, ctx);
1169 iounmap(res->vp_regs);
1170 iounmap(res->mixer_regs);
1173 static int __devinit mixer_probe(struct platform_device *pdev)
1175 struct device *dev = &pdev->dev;
1176 struct exynos_drm_hdmi_context *drm_hdmi_ctx;
1177 struct exynos_drm_hdmi_pdata *pdata;
1178 struct mixer_context *ctx;
1181 dev_info(dev, "probe start\n");
1183 drm_hdmi_ctx = kzalloc(sizeof(*drm_hdmi_ctx), GFP_KERNEL);
1184 if (!drm_hdmi_ctx) {
1185 DRM_ERROR("failed to allocate common hdmi context.\n");
1189 ctx = kzalloc(sizeof(*ctx), GFP_KERNEL);
1191 DRM_ERROR("failed to alloc mixer context.\n");
1192 kfree(drm_hdmi_ctx);
1196 drm_hdmi_ctx->ctx = (void *)ctx;
1198 platform_set_drvdata(pdev, drm_hdmi_ctx);
1200 /* Get from Platform soc deatils */
1201 pdata = pdev->dev.platform_data;
1203 /* acquire resources: regs, irqs, clocks */
1204 ret = mixer_resources_init_exynos(drm_hdmi_ctx, pdev,pdata->is_soc_exynos5);
1208 /* attach mixer driver to common hdmi. */
1209 exynos_mixer_drv_attach(drm_hdmi_ctx);
1211 /* register specific callback point to common hdmi. */
1212 exynos_mixer_ops_register(&mixer_ops);
1214 mixer_resource_poweron(ctx);
1220 dev_info(dev, "probe failed\n");
1224 static int mixer_remove(struct platform_device *pdev)
1226 struct device *dev = &pdev->dev;
1227 struct exynos_drm_hdmi_context *drm_hdmi_ctx =
1228 platform_get_drvdata(pdev);
1229 struct mixer_context *ctx = drm_hdmi_ctx->ctx;
1231 dev_info(dev, "remove successful\n");
1233 mixer_resource_poweroff(ctx);
1234 mixer_resources_cleanup(ctx);
1239 struct platform_driver mixer_driver = {
1241 .name = "s5p-mixer",
1242 .owner = THIS_MODULE,
1243 .pm = &mixer_pm_ops,
1245 .probe = mixer_probe,
1246 .remove = __devexit_p(mixer_remove),