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_crtc.h"
39 #include "exynos_drm_hdmi.h"
41 #include <plat/map-base.h>
42 #ifdef CONFIG_EXYNOS_IOMMU
43 #include <mach/sysmmu.h>
44 #include <linux/of_platform.h>
48 #define get_mixer_context(dev) platform_get_drvdata(to_platform_device(dev))
50 struct hdmi_win_data {
53 dma_addr_t chroma_dma_addr;
54 void __iomem *chroma_vaddr;
55 uint32_t pixel_format;
59 unsigned int crtc_width;
60 unsigned int crtc_height;
63 unsigned int fb_width;
64 unsigned int fb_height;
65 unsigned int mode_width;
66 unsigned int mode_height;
67 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 bool is_mixer_powered_on;
93 struct mixer_resources mixer_res;
94 struct hdmi_win_data win_data[MIXER_WIN_NR];
95 unsigned long event_flags;
98 /* event flags used */
99 enum mixer_status_flags {
103 static const u8 filter_y_horiz_tap8[] = {
104 0, -1, -1, -1, -1, -1, -1, -1,
105 -1, -1, -1, -1, -1, 0, 0, 0,
106 0, 2, 4, 5, 6, 6, 6, 6,
107 6, 5, 5, 4, 3, 2, 1, 1,
108 0, -6, -12, -16, -18, -20, -21, -20,
109 -20, -18, -16, -13, -10, -8, -5, -2,
110 127, 126, 125, 121, 114, 107, 99, 89,
111 79, 68, 57, 46, 35, 25, 16, 8,
114 static const u8 filter_y_vert_tap4[] = {
115 0, -3, -6, -8, -8, -8, -8, -7,
116 -6, -5, -4, -3, -2, -1, -1, 0,
117 127, 126, 124, 118, 111, 102, 92, 81,
118 70, 59, 48, 37, 27, 19, 11, 5,
119 0, 5, 11, 19, 27, 37, 48, 59,
120 70, 81, 92, 102, 111, 118, 124, 126,
121 0, 0, -1, -1, -2, -3, -4, -5,
122 -6, -7, -8, -8, -8, -8, -6, -3,
125 static const u8 filter_cr_horiz_tap4[] = {
126 0, -3, -6, -8, -8, -8, -8, -7,
127 -6, -5, -4, -3, -2, -1, -1, 0,
128 127, 126, 124, 118, 111, 102, 92, 81,
129 70, 59, 48, 37, 27, 19, 11, 5,
132 static void mixer_win_reset(struct mixer_context *mctx);
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 *mctx)
176 #define DUMPREG(reg_id) \
178 DRM_DEBUG_KMS(#reg_id " = %08x\n", \
179 (u32)readl(mctx->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 *mctx)
208 #define DUMPREG(reg_id) \
210 DRM_DEBUG_KMS(#reg_id " = %08x\n", \
211 (u32) readl(mctx->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 *mctx, bool enable)
265 struct mixer_resources *res = &mctx->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);
271 if (!(res->is_soc_exynos5))
272 vp_reg_write(res, VP_SHADOW_UPDATE, enable ?
273 VP_SHADOW_UPDATE_ENABLE : 0);
276 static void mixer_cfg_scan(struct mixer_context *mctx, u32 width, u32 height)
278 struct mixer_resources *res = &mctx->mixer_res;
279 enum exynos_mixer_mode_type mode_type;
282 /* choosing between interlace and progressive mode */
283 val = (mctx->interlace ? MXR_CFG_SCAN_INTERLACE :
284 MXR_CFG_SCAN_PROGRASSIVE);
286 /* choosing between proper HD and SD mode */
287 mode_type = exynos_mixer_get_mode_type(width, height);
289 case EXYNOS_MIXER_MODE_SD_NTSC:
290 val |= MXR_CFG_SCAN_NTSC | MXR_CFG_SCAN_SD;
292 case EXYNOS_MIXER_MODE_SD_PAL:
293 val |= MXR_CFG_SCAN_PAL | MXR_CFG_SCAN_SD;
295 case EXYNOS_MIXER_MODE_HD_720:
296 val |= MXR_CFG_SCAN_HD_720 | MXR_CFG_SCAN_HD;
298 case EXYNOS_MIXER_MODE_HD_1080:
299 val |= MXR_CFG_SCAN_HD_1080 | MXR_CFG_SCAN_HD;
302 DRM_ERROR("Invalid mixer config %dx%d\n", width, height);
306 mixer_reg_writemask(res, MXR_CFG, val, MXR_CFG_SCAN_MASK);
309 static void mixer_cfg_rgb_fmt(struct mixer_context *mctx, unsigned int height)
311 struct mixer_resources *res = &mctx->mixer_res;
315 val = MXR_CFG_RGB601_0_255;
316 } else if (height == 576) {
317 val = MXR_CFG_RGB601_0_255;
318 } else if (height == 720) {
319 val = MXR_CFG_RGB709_16_235;
320 mixer_reg_write(res, MXR_CM_COEFF_Y,
321 (1 << 30) | (94 << 20) | (314 << 10) |
323 mixer_reg_write(res, MXR_CM_COEFF_CB,
324 (972 << 20) | (851 << 10) | (225 << 0));
325 mixer_reg_write(res, MXR_CM_COEFF_CR,
326 (225 << 20) | (820 << 10) | (1004 << 0));
327 } else if (height == 1080) {
328 val = MXR_CFG_RGB709_16_235;
329 mixer_reg_write(res, MXR_CM_COEFF_Y,
330 (1 << 30) | (94 << 20) | (314 << 10) |
332 mixer_reg_write(res, MXR_CM_COEFF_CB,
333 (972 << 20) | (851 << 10) | (225 << 0));
334 mixer_reg_write(res, MXR_CM_COEFF_CR,
335 (225 << 20) | (820 << 10) | (1004 << 0));
337 val = MXR_CFG_RGB709_16_235;
338 mixer_reg_write(res, MXR_CM_COEFF_Y,
339 (1 << 30) | (94 << 20) | (314 << 10) |
341 mixer_reg_write(res, MXR_CM_COEFF_CB,
342 (972 << 20) | (851 << 10) | (225 << 0));
343 mixer_reg_write(res, MXR_CM_COEFF_CR,
344 (225 << 20) | (820 << 10) | (1004 << 0));
347 mixer_reg_writemask(res, MXR_CFG, val, MXR_CFG_RGB_FMT_MASK);
350 static void mixer_cfg_layer(struct mixer_context *mctx, int win, bool enable)
352 struct mixer_resources *res = &mctx->mixer_res;
353 u32 val = enable ? ~0 : 0;
357 mixer_reg_writemask(res, MXR_CFG, val, MXR_CFG_GRP0_ENABLE);
360 mixer_reg_writemask(res, MXR_CFG, val, MXR_CFG_GRP1_ENABLE);
363 vp_reg_writemask(res, VP_ENABLE, val, VP_ENABLE_ON);
364 mixer_reg_writemask(res, MXR_CFG, val, MXR_CFG_VP_ENABLE);
369 static void mixer_run(struct mixer_context *mctx)
371 struct mixer_resources *res = &mctx->mixer_res;
373 mixer_reg_writemask(res, MXR_STATUS, ~0, MXR_STATUS_REG_RUN);
375 mixer_regs_dump(mctx);
378 static int mixer_wait_for_vsync(struct mixer_context *mctx)
382 mctx->event_flags |= MXR_EVENT_VSYNC;
384 ret = wait_event_timeout(mctx->mixer_res.event_queue,
385 ((mctx->event_flags & MXR_EVENT_VSYNC) == 0), msecs_to_jiffies(1000));
392 static int mixer_get_layer_update_count(struct mixer_context *ctx)
394 struct mixer_resources *res = &ctx->mixer_res;
397 if (!res->is_soc_exynos5)
400 val = mixer_reg_read(res, MXR_CFG);
402 return (val & MXR_CFG_LAYER_UPDATE_COUNT_MASK) >>
403 MXR_CFG_LAYER_UPDATE_COUNT0;
406 static void mixer_layer_update(struct mixer_context *ctx)
408 struct mixer_resources *res = &ctx->mixer_res;
410 if (!res->is_soc_exynos5)
413 mixer_reg_writemask(res, MXR_CFG, ~0, MXR_CFG_LAYER_UPDATE);
416 static void vp_video_buffer(struct mixer_context *mctx, int win)
418 struct mixer_resources *res = &mctx->mixer_res;
420 struct hdmi_win_data *win_data;
421 unsigned int full_width, full_height, width, height;
422 unsigned int x_ratio, y_ratio;
423 unsigned int src_x_offset, src_y_offset, dst_x_offset, dst_y_offset;
424 unsigned int mode_width, mode_height;
425 unsigned int buf_num;
426 dma_addr_t luma_addr[2], chroma_addr[2];
427 bool tiled_mode = false;
428 bool crcb_mode = false;
431 win_data = &mctx->win_data[win];
433 switch (win_data->pixel_format) {
434 case DRM_FORMAT_NV12MT:
436 case DRM_FORMAT_NV12M:
440 /* TODO: single buffer format NV12, NV21 */
442 /* ignore pixel format at disable time */
443 if (!win_data->dma_addr)
446 DRM_ERROR("pixel format for vp is wrong [%d].\n",
447 win_data->pixel_format);
451 full_width = win_data->fb_width;
452 full_height = win_data->fb_height;
453 width = win_data->crtc_width;
454 height = win_data->crtc_height;
455 mode_width = win_data->mode_width;
456 mode_height = win_data->mode_height;
458 /* scaling feature: (src << 16) / dst */
459 x_ratio = (width << 16) / width;
460 y_ratio = (height << 16) / height;
462 src_x_offset = win_data->fb_x;
463 src_y_offset = win_data->fb_y;
464 dst_x_offset = win_data->crtc_x;
465 dst_y_offset = win_data->crtc_y;
468 luma_addr[0] = win_data->dma_addr;
469 chroma_addr[0] = win_data->chroma_dma_addr;
471 luma_addr[0] = win_data->dma_addr;
472 chroma_addr[0] = win_data->dma_addr
473 + (full_width * full_height);
476 if (win_data->scan_flags & DRM_MODE_FLAG_INTERLACE) {
477 mctx->interlace = true;
479 luma_addr[1] = luma_addr[0] + 0x40;
480 chroma_addr[1] = chroma_addr[0] + 0x40;
482 luma_addr[1] = luma_addr[0] + full_width;
483 chroma_addr[1] = chroma_addr[0] + full_width;
486 mctx->interlace = false;
491 spin_lock_irqsave(&res->reg_slock, flags);
492 mixer_vsync_set_update(mctx, false);
494 /* interlace or progressive scan mode */
495 val = (mctx->interlace ? ~0 : 0);
496 vp_reg_writemask(res, VP_MODE, val, VP_MODE_LINE_SKIP);
499 val = (crcb_mode ? VP_MODE_NV21 : VP_MODE_NV12);
500 val |= (tiled_mode ? VP_MODE_MEM_TILED : VP_MODE_MEM_LINEAR);
501 vp_reg_writemask(res, VP_MODE, val, VP_MODE_FMT_MASK);
503 /* setting size of input image */
504 vp_reg_write(res, VP_IMG_SIZE_Y, VP_IMG_HSIZE(full_width) |
505 VP_IMG_VSIZE(full_height));
506 /* chroma height has to reduced by 2 to avoid chroma distorions */
507 vp_reg_write(res, VP_IMG_SIZE_C, VP_IMG_HSIZE(full_width) |
508 VP_IMG_VSIZE(full_height / 2));
510 vp_reg_write(res, VP_SRC_WIDTH, width);
511 vp_reg_write(res, VP_SRC_HEIGHT, height);
512 vp_reg_write(res, VP_SRC_H_POSITION,
513 VP_SRC_H_POSITION_VAL(src_x_offset));
514 vp_reg_write(res, VP_SRC_V_POSITION, src_y_offset);
516 vp_reg_write(res, VP_DST_WIDTH, width);
517 vp_reg_write(res, VP_DST_H_POSITION, dst_x_offset);
518 if (mctx->interlace) {
519 vp_reg_write(res, VP_DST_HEIGHT, height / 2);
520 vp_reg_write(res, VP_DST_V_POSITION, dst_y_offset / 2);
522 vp_reg_write(res, VP_DST_HEIGHT, height);
523 vp_reg_write(res, VP_DST_V_POSITION, dst_y_offset);
526 vp_reg_write(res, VP_H_RATIO, x_ratio);
527 vp_reg_write(res, VP_V_RATIO, y_ratio);
529 vp_reg_write(res, VP_ENDIAN_MODE, VP_ENDIAN_MODE_LITTLE);
531 /* set buffer address to vp */
532 vp_reg_write(res, VP_TOP_Y_PTR, luma_addr[0]);
533 vp_reg_write(res, VP_BOT_Y_PTR, luma_addr[1]);
534 vp_reg_write(res, VP_TOP_C_PTR, chroma_addr[0]);
535 vp_reg_write(res, VP_BOT_C_PTR, chroma_addr[1]);
537 mixer_cfg_scan(mctx, mode_width, mode_height);
538 mixer_cfg_rgb_fmt(mctx, mode_height);
539 mixer_cfg_layer(mctx, win, true);
542 mixer_vsync_set_update(mctx, true);
543 spin_unlock_irqrestore(&res->reg_slock, flags);
548 static void mixer_graph_buffer(struct mixer_context *mctx, int win)
550 struct mixer_resources *res = &mctx->mixer_res;
552 struct hdmi_win_data *win_data;
553 unsigned int full_width, width, height;
554 unsigned int x_ratio, y_ratio;
555 unsigned int src_x_offset, src_y_offset, dst_x_offset, dst_y_offset;
556 unsigned int mode_width, mode_height;
561 win_data = &mctx->win_data[win];
568 switch (win_data->bpp) {
579 dma_addr = win_data->dma_addr;
580 full_width = win_data->fb_width;
581 width = win_data->crtc_width;
582 height = win_data->crtc_height;
583 mode_width = win_data->mode_width;
584 mode_height = win_data->mode_height;
586 /* 2x scaling feature */
590 src_x_offset = win_data->fb_x;
591 src_y_offset = win_data->fb_y;
592 dst_x_offset = win_data->crtc_x;
593 dst_y_offset = win_data->crtc_y;
595 /* converting dma address base and source offset */
597 + (src_x_offset * win_data->bpp >> 3)
598 + (src_y_offset * full_width * win_data->bpp >> 3);
602 if (win_data->scan_flags & DRM_MODE_FLAG_INTERLACE)
603 mctx->interlace = true;
605 mctx->interlace = false;
607 spin_lock_irqsave(&res->reg_slock, flags);
608 mixer_vsync_set_update(mctx, false);
611 mixer_reg_writemask(res, MXR_GRAPHIC_CFG(win),
612 MXR_GRP_CFG_FORMAT_VAL(fmt), MXR_GRP_CFG_FORMAT_MASK);
615 mixer_reg_write(res, MXR_GRAPHIC_SPAN(win), full_width);
617 val = MXR_GRP_WH_WIDTH(width);
618 val |= MXR_GRP_WH_HEIGHT(height);
619 val |= MXR_GRP_WH_H_SCALE(x_ratio);
620 val |= MXR_GRP_WH_V_SCALE(y_ratio);
621 mixer_reg_write(res, MXR_GRAPHIC_WH(win), val);
623 /* setup offsets in source image */
624 val = MXR_GRP_SXY_SX(src_x_offset);
625 val |= MXR_GRP_SXY_SY(src_y_offset);
626 mixer_reg_write(res, MXR_GRAPHIC_SXY(win), val);
628 /* setup offsets in display image */
629 val = MXR_GRP_DXY_DX(dst_x_offset);
630 val |= MXR_GRP_DXY_DY(dst_y_offset);
631 mixer_reg_write(res, MXR_GRAPHIC_DXY(win), val);
633 /* set buffer address to mixer */
634 mixer_reg_write(res, MXR_GRAPHIC_BASE(win), dma_addr);
636 mixer_cfg_scan(mctx, mode_width, mode_height);
637 mixer_cfg_rgb_fmt(mctx, mode_height);
638 mixer_cfg_layer(mctx, win, true);
639 mixer_cfg_layer(mctx, MIXER_DEFAULT_WIN, true);
641 /* Only allow one update per vsync */
642 if (!win_data->updated)
643 mixer_layer_update(mctx);
645 win_data->updated = true;
648 mixer_vsync_set_update(mctx, true);
649 spin_unlock_irqrestore(&res->reg_slock, flags);
652 static void vp_win_reset(struct mixer_context *mctx)
654 struct mixer_resources *res = &mctx->mixer_res;
657 vp_reg_write(res, VP_SRESET, VP_SRESET_PROCESSING);
658 for (tries = 100; tries; --tries) {
659 /* waiting until VP_SRESET_PROCESSING is 0 */
660 if (~vp_reg_read(res, VP_SRESET) & VP_SRESET_PROCESSING)
664 WARN(tries == 0, "failed to reset Video Processor\n");
667 static int mixer_enable_vblank(void *ctx, int pipe)
669 struct mixer_context *mctx = ctx;
670 struct mixer_resources *res = &mctx->mixer_res;
672 DRM_DEBUG_KMS("[%d] %s\n", __LINE__, __func__);
676 /* enable vsync interrupt */
677 mixer_reg_writemask(res, MXR_INT_EN, MXR_INT_EN_VSYNC,
683 static void mixer_disable_vblank(void *ctx)
685 struct mixer_context *mctx = ctx;
686 struct mixer_resources *res = &mctx->mixer_res;
688 DRM_DEBUG_KMS("[%d] %s\n", __LINE__, __func__);
690 /* disable vsync interrupt */
691 mixer_reg_writemask(res, MXR_INT_EN, 0, MXR_INT_EN_VSYNC);
694 static void mixer_win_mode_set(void *ctx,
695 struct exynos_drm_overlay *overlay)
697 struct mixer_context *mctx = ctx;
698 struct hdmi_win_data *win_data;
701 DRM_DEBUG_KMS("[%d] %s\n", __LINE__, __func__);
704 DRM_ERROR("overlay is NULL\n");
708 DRM_DEBUG_KMS("set [%d]x[%d] at (%d,%d) to [%d]x[%d] at (%d,%d)\n",
709 overlay->fb_width, overlay->fb_height,
710 overlay->fb_x, overlay->fb_y,
711 overlay->crtc_width, overlay->crtc_height,
712 overlay->crtc_x, overlay->crtc_y);
715 if (win == DEFAULT_ZPOS)
716 win = MIXER_DEFAULT_WIN;
718 if (win < 0 || win > MIXER_WIN_NR) {
719 DRM_ERROR("overlay plane[%d] is wrong\n", win);
723 win_data = &mctx->win_data[win];
725 win_data->dma_addr = overlay->dma_addr[0];
726 win_data->vaddr = overlay->vaddr[0];
727 win_data->chroma_dma_addr = overlay->dma_addr[1];
728 win_data->chroma_vaddr = overlay->vaddr[1];
729 win_data->pixel_format = overlay->pixel_format;
730 win_data->bpp = overlay->bpp;
732 win_data->crtc_x = overlay->crtc_x;
733 win_data->crtc_y = overlay->crtc_y;
734 win_data->crtc_width = overlay->crtc_width;
735 win_data->crtc_height = overlay->crtc_height;
737 win_data->fb_x = overlay->fb_x;
738 win_data->fb_y = overlay->fb_y;
739 win_data->fb_width = overlay->fb_pitch / (overlay->bpp >> 3);
740 win_data->fb_height = overlay->fb_height;
742 win_data->mode_width = overlay->mode_width;
743 win_data->mode_height = overlay->mode_height;
745 win_data->scan_flags = overlay->scan_flag;
748 static void mixer_win_page_flip(void *ctx,
749 struct exynos_drm_overlay *overlay)
751 struct mixer_context *mixer_ctx = ctx;
752 struct hdmi_win_data *win_data;
753 int win = overlay->zpos;
755 if (win == DEFAULT_ZPOS)
756 win = MIXER_DEFAULT_WIN;
758 if (win < 0 || win > MIXER_WIN_NR) {
759 DRM_ERROR("overlay plane[%d] is wrong\n", win);
763 win_data = &mixer_ctx->win_data[win];
765 win_data->dma_addr = overlay->dma_addr[0];
766 win_data->vaddr = overlay->vaddr[0];
767 win_data->chroma_dma_addr = overlay->dma_addr[1];
768 win_data->chroma_vaddr = overlay->vaddr[1];
771 static void mixer_win_commit(void *ctx, int zpos)
773 struct mixer_context *mctx = ctx;
774 struct mixer_resources *res = &mctx->mixer_res;
777 DRM_DEBUG_KMS("[%d] %s, win: %d\n", __LINE__, __func__, win);
778 if (win == DEFAULT_ZPOS)
779 win = MIXER_DEFAULT_WIN;
781 if (win < 0 || win > MIXER_WIN_NR) {
782 DRM_ERROR("overlay plane[%d] is wrong\n", win);
786 if (!mctx->is_mixer_powered_on) {
787 DRM_DEBUG_KMS("[%d] %s not powered on\n", __LINE__, __func__);
791 if (!(res->is_soc_exynos5)) {
793 vp_video_buffer(mctx, win);
795 mixer_graph_buffer(mctx, win);
798 mixer_graph_buffer(mctx, win);
801 static void mixer_win_disable(void *ctx, int zpos)
803 struct mixer_context *mctx = ctx;
804 struct mixer_resources *res = &mctx->mixer_res;
808 DRM_DEBUG_KMS("[%d] %s, win: %d\n", __LINE__, __func__, win);
810 if (win == DEFAULT_ZPOS)
811 win = MIXER_DEFAULT_WIN;
813 if (win < 0 || win > MIXER_WIN_NR) {
814 DRM_ERROR("overlay plane[%d] is wrong\n", win);
818 mixer_wait_for_vsync(mctx);
820 spin_lock_irqsave(&res->reg_slock, flags);
821 mixer_vsync_set_update(mctx, false);
823 mixer_cfg_layer(mctx, win, false);
825 mixer_vsync_set_update(mctx, true);
827 spin_unlock_irqrestore(&res->reg_slock, flags);
829 if (win == MIXER_DEFAULT_WIN) {
830 mixer_win_reset(mctx);
831 mixer_enable_vblank(mctx, mctx->pipe);
835 /* for pageflip event */
836 static irqreturn_t mixer_irq_handler(int irq, void *arg)
838 struct exynos_drm_hdmi_context *drm_hdmi_ctx = arg;
839 struct mixer_context *mctx = drm_hdmi_ctx->ctx;
840 struct mixer_resources *res = &mctx->mixer_res;
841 u32 val, base, shadow;
844 spin_lock(&res->reg_slock);
846 /* read interrupt status for handling and clearing flags for VSYNC */
847 val = mixer_reg_read(res, MXR_INT_STATUS);
850 if (val & MXR_INT_STATUS_VSYNC) {
852 if (mctx->event_flags & MXR_EVENT_VSYNC) {
853 DRM_DEBUG_KMS("mctx->event_flags & MXR_EVENT_VSYNC");
856 mixer_reg_write(res, MXR_GRAPHIC_WH(1), 0);
857 mixer_reg_write(res, MXR_GRAPHIC_SPAN(1), 0);
858 mixer_reg_write(res, MXR_GRAPHIC_SXY(1), 0);
859 mixer_reg_write(res, MXR_GRAPHIC_DXY(1), 0);
861 mctx->event_flags &= ~MXR_EVENT_VSYNC;
862 wake_up(&mctx->mixer_res.event_queue);
866 /* interlace scan need to check shadow register */
867 if (mctx->interlace) {
868 base = mixer_reg_read(res, MXR_GRAPHIC_BASE(0));
869 shadow = mixer_reg_read(res, MXR_GRAPHIC_BASE_S(0));
873 base = mixer_reg_read(res, MXR_GRAPHIC_BASE(1));
874 shadow = mixer_reg_read(res, MXR_GRAPHIC_BASE_S(1));
879 drm_handle_vblank(drm_hdmi_ctx->drm_dev, mctx->pipe);
881 /* Bail out if a layer update is pending */
882 if (mixer_get_layer_update_count(mctx))
885 for (i = 0; i < MIXER_WIN_NR; i++)
886 mctx->win_data[i].updated = false;
887 exynos_drm_crtc_finish_pageflip(drm_hdmi_ctx->drm_dev,
892 /* clear interrupts */
893 if (~val & MXR_INT_EN_VSYNC) {
894 /* vsync interrupt use different bit for read and clear */
895 val &= ~MXR_INT_EN_VSYNC;
896 val |= MXR_INT_CLEAR_VSYNC;
898 mixer_reg_write(res, MXR_INT_STATUS, val);
900 spin_unlock(&res->reg_slock);
905 static void mixer_win_reset(struct mixer_context *mctx)
907 struct mixer_resources *res = &mctx->mixer_res;
909 u32 val; /* value stored to register */
911 spin_lock_irqsave(&res->reg_slock, flags);
912 mixer_reg_writemask(res, MXR_STATUS, ~0, MXR_STATUS_SOFT_RESET);
913 mixer_vsync_set_update(mctx, false);
915 mixer_reg_writemask(res, MXR_CFG, MXR_CFG_DST_HDMI, MXR_CFG_DST_MASK);
917 /* set output in RGB888 mode */
918 mixer_reg_writemask(res, MXR_CFG, MXR_CFG_OUT_RGB888, MXR_CFG_OUT_MASK);
920 /* 16 beat burst in DMA */
921 mixer_reg_writemask(res, MXR_STATUS, MXR_STATUS_16_BURST,
922 MXR_STATUS_BURST_MASK);
924 /* setting default layer priority: layer1 > layer0 > video
925 * because typical usage scenario would be
927 * layer0 - framebuffer
928 * video - video overlay
930 val = MXR_LAYER_CFG_GRP1_VAL(3);
931 val |= MXR_LAYER_CFG_GRP0_VAL(2);
932 val |= MXR_LAYER_CFG_VP_VAL(1);
933 mixer_reg_write(res, MXR_LAYER_CFG, val);
935 /* setting background color */
936 mixer_reg_write(res, MXR_BG_COLOR0, 0x008080);
937 mixer_reg_write(res, MXR_BG_COLOR1, 0x008080);
938 mixer_reg_write(res, MXR_BG_COLOR2, 0x008080);
940 /* setting graphical layers */
942 val = MXR_GRP_CFG_COLOR_KEY_DISABLE; /* no blank key */
943 val |= MXR_GRP_CFG_WIN_BLEND_EN;
944 val |= MXR_GRP_CFG_ALPHA_VAL(0xff); /* non-transparent alpha */
946 /* the same configuration for both layers */
947 mixer_reg_write(res, MXR_GRAPHIC_CFG(0), val);
949 val |= MXR_GRP_CFG_BLEND_PRE_MUL;
950 val |= MXR_GRP_CFG_PIXEL_BLEND_EN;
951 mixer_reg_write(res, MXR_GRAPHIC_CFG(1), val);
953 if (!(res->is_soc_exynos5)) {
954 /* configuration of Video Processor for Exynos4 soc */
956 vp_default_filter(res);
959 /* disable all layers */
960 mixer_reg_writemask(res, MXR_CFG, 0, MXR_CFG_GRP0_ENABLE);
961 mixer_reg_writemask(res, MXR_CFG, 0, MXR_CFG_GRP1_ENABLE);
962 mixer_reg_writemask(res, MXR_CFG, 0, MXR_CFG_VP_ENABLE);
964 mixer_reg_writemask(res, MXR_INT_EN, ~0, MXR_INT_EN_ALL);
966 mixer_vsync_set_update(mctx, true);
967 spin_unlock_irqrestore(&res->reg_slock, flags);
970 static void mixer_resource_poweron(struct mixer_context *mctx)
972 struct mixer_resources *res = &mctx->mixer_res;
974 if (mctx->is_mixer_powered_on)
977 clk_enable(res->mixer);
978 if (!(res->is_soc_exynos5)) {
980 clk_enable(res->sclk_mixer);
983 mixer_win_reset(mctx);
984 mctx->is_mixer_powered_on = true;
987 static void mixer_resource_poweroff(struct mixer_context *mctx)
989 struct mixer_resources *res = &mctx->mixer_res;
991 DRM_DEBUG_KMS("[%d] %s\n", __LINE__, __func__);
992 if (!mctx->is_mixer_powered_on)
995 clk_disable(res->mixer);
996 if (!(res->is_soc_exynos5)) {
997 clk_disable(res->vp);
998 clk_disable(res->sclk_mixer);
1000 mctx->is_mixer_powered_on = false;
1003 #ifdef CONFIG_PM_SLEEP
1004 static int mixer_resume(struct device *dev)
1006 struct exynos_drm_hdmi_context *ctx = get_mixer_context(dev);
1007 struct mixer_context *mctx = ctx->ctx;
1009 DRM_DEBUG_KMS("[mixer] sleep resume - start\n");
1011 if (!pm_runtime_suspended(dev)) {
1012 DRM_DEBUG_KMS("[mixer] sleep resume - end\n");
1013 mixer_resource_poweron(mctx);
1014 mixer_win_commit(mctx, 0);
1016 DRM_DEBUG_KMS("[mixer] sleep resume - not done\n");
1020 static int mixer_suspend(struct device *dev)
1022 struct exynos_drm_hdmi_context *ctx = get_mixer_context(dev);
1023 struct mixer_context *mctx = ctx->ctx;
1025 DRM_DEBUG_KMS("[mixer] suspend - start\n");
1026 if (pm_runtime_suspended(dev)) {
1027 DRM_DEBUG_KMS("[mixer] suspend - already suspended\n");
1031 mixer_resource_poweroff(mctx);
1032 DRM_DEBUG_KMS("[mixer] suspend - end\n");
1036 #ifdef CONFIG_PM_RUNTIME
1037 static int mixer_runtime_resume(struct device *dev)
1039 struct exynos_drm_hdmi_context *ctx = get_mixer_context(dev);
1040 struct mixer_context *mctx = ctx->ctx;
1042 DRM_DEBUG_KMS("[mixer] runtime resume - start\n");
1044 mixer_resource_poweron(mctx);
1045 DRM_DEBUG_KMS("[mixer] runtime resume - end\n");
1050 static int mixer_runtime_suspend(struct device *dev)
1052 struct exynos_drm_hdmi_context *ctx = get_mixer_context(dev);
1053 struct mixer_context *mctx = ctx->ctx;
1055 DRM_DEBUG_KMS("[mixer] runtime suspend - start\n");
1057 mixer_resource_poweroff(mctx);
1058 DRM_DEBUG_KMS("[mixer] runtime suspend - end\n");
1064 static int mixer_power_on(void *ctx, int mode)
1066 struct mixer_context *mctx = ctx;
1068 DRM_DEBUG_KMS("[%d] %s\n", __LINE__, __func__);
1071 case DRM_MODE_DPMS_ON:
1072 if (mctx->is_mixer_powered_on) {
1073 DRM_DEBUG_KMS("[%d] %s returning\n", __LINE__, __func__);
1076 pm_runtime_get_sync(mctx->dev);
1078 case DRM_MODE_DPMS_STANDBY:
1079 case DRM_MODE_DPMS_SUSPEND:
1080 case DRM_MODE_DPMS_OFF:
1081 if (!mctx->is_mixer_powered_on) {
1082 DRM_DEBUG_KMS("[%d] %s returning\n", __LINE__, __func__);
1085 pm_runtime_put_sync(mctx->dev);
1088 DRM_DEBUG_KMS("unknown dpms mode: %d\n", mode);
1095 static struct exynos_mixer_ops mixer_ops = {
1097 .enable_vblank = mixer_enable_vblank,
1098 .disable_vblank = mixer_disable_vblank,
1099 .power_on = mixer_power_on,
1102 .win_mode_set = mixer_win_mode_set,
1103 .win_page_flip = mixer_win_page_flip,
1104 .win_commit = mixer_win_commit,
1105 .win_disable = mixer_win_disable,
1108 static const struct dev_pm_ops mixer_pm_ops = {
1109 SET_SYSTEM_SLEEP_PM_OPS(mixer_suspend, mixer_resume)
1110 SET_RUNTIME_PM_OPS(mixer_runtime_suspend, mixer_runtime_resume, NULL)
1113 #ifdef CONFIG_EXYNOS_IOMMU
1114 static int iommu_init(struct platform_device *pdev)
1116 struct platform_device *pds;
1118 pds = find_sysmmu_dt(pdev, "sysmmu");
1120 printk(KERN_ERR "No sysmmu found :\n");
1124 platform_set_sysmmu(&pds->dev, &pdev->dev);
1126 * The ordering in Makefile warrants that this is initialized after
1127 * FIMD, so only just ensure that it works as expected and we are
1128 * reusing the mapping originally created in exynos_drm_fimd.c.
1130 WARN_ON(!exynos_drm_common_mapping);
1131 exynos_drm_common_mapping = s5p_create_iommu_mapping(&pdev->dev,
1132 0, 0, 0, exynos_drm_common_mapping);
1133 if(exynos_drm_common_mapping == NULL) {
1134 printk(KERN_ERR"Failed to create iommu mapping for Mixer\n");
1142 static int __devinit mixer_resources_init_exynos(
1143 struct exynos_drm_hdmi_context *ctx,
1144 struct platform_device *pdev,
1147 struct mixer_context *mctx = ctx->ctx;
1148 struct device *dev = &pdev->dev;
1149 struct mixer_resources *mixer_res = &mctx->mixer_res;
1150 struct resource *res;
1153 DRM_DEBUG_KMS("Mixer resources init\n");
1155 mixer_res->is_soc_exynos5 = is_exynos5;
1156 mixer_res->dev = dev;
1157 spin_lock_init(&mixer_res->reg_slock);
1160 init_waitqueue_head(&mixer_res->event_queue);
1162 mixer_res->mixer = clk_get(dev, "mixer");
1163 if (IS_ERR_OR_NULL(mixer_res->mixer)) {
1164 dev_err(dev, "failed to get clock 'mixer'\n");
1169 mixer_res->vp = clk_get(dev, "vp");
1170 if (IS_ERR_OR_NULL(mixer_res->vp)) {
1171 dev_err(dev, "failed to get clock 'vp'\n");
1175 mixer_res->sclk_mixer = clk_get(dev, "sclk_mixer");
1176 if (IS_ERR_OR_NULL(mixer_res->sclk_mixer)) {
1177 dev_err(dev, "failed to get clock 'sclk_mixer'\n");
1182 mixer_res->sclk_hdmi = clk_get(dev, "sclk_hdmi");
1183 if (IS_ERR_OR_NULL(mixer_res->sclk_hdmi)) {
1184 dev_err(dev, "failed to get clock 'sclk_hdmi'\n");
1189 mixer_res->sclk_dac = clk_get(dev, "sclk_dac");
1190 if (IS_ERR_OR_NULL(mixer_res->sclk_dac)) {
1191 dev_err(dev, "failed to get clock 'sclk_dac'\n");
1195 res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "mxr");
1198 res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
1201 dev_err(dev, "get memory resource failed.\n");
1207 clk_set_parent(mixer_res->sclk_mixer, mixer_res->sclk_hdmi);
1209 mixer_res->mixer_regs = ioremap(res->start, resource_size(res));
1210 if (mixer_res->mixer_regs == NULL) {
1211 dev_err(dev, "register mapping failed.\n");
1217 res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "vp");
1219 dev_err(dev, "get memory resource failed.\n");
1224 mixer_res->vp_regs = ioremap(res->start, resource_size(res));
1225 if (mixer_res->vp_regs == NULL) {
1226 dev_err(dev, "register mapping failed.\n");
1231 res = platform_get_resource_byname(pdev, IORESOURCE_IRQ, "irq");
1233 dev_err(dev, "get interrupt resource failed.\n");
1238 res = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
1240 dev_err(dev, "get interrupt resource failed.\n");
1242 goto fail_mixer_regs;
1246 ret = request_irq(res->start, mixer_irq_handler, 0, "drm_mixer", ctx);
1248 dev_err(dev, "request interrupt failed.\n");
1249 goto fail_mixer_regs;
1251 mixer_res->irq = res->start;
1253 #ifdef CONFIG_EXYNOS_IOMMU
1254 ret = iommu_init(pdev);
1256 dev_err(dev, "iommu init failed.\n");
1257 goto fail_mixer_regs;
1263 iounmap(mixer_res->vp_regs);
1266 iounmap(mixer_res->mixer_regs);
1269 if (!IS_ERR_OR_NULL(mixer_res->sclk_dac))
1270 clk_put(mixer_res->sclk_dac);
1271 if (!IS_ERR_OR_NULL(mixer_res->sclk_hdmi))
1272 clk_put(mixer_res->sclk_hdmi);
1273 if (!IS_ERR_OR_NULL(mixer_res->sclk_mixer))
1274 clk_put(mixer_res->sclk_mixer);
1275 if (!IS_ERR_OR_NULL(mixer_res->vp))
1276 clk_put(mixer_res->vp);
1277 if (!IS_ERR_OR_NULL(mixer_res->mixer))
1278 clk_put(mixer_res->mixer);
1279 mixer_res->dev = NULL;
1283 static void mixer_resources_cleanup(struct mixer_context *mctx)
1285 struct mixer_resources *res = &mctx->mixer_res;
1287 disable_irq(res->irq);
1288 free_irq(res->irq, mctx);
1290 iounmap(res->vp_regs);
1291 iounmap(res->mixer_regs);
1294 static int __devinit mixer_probe(struct platform_device *pdev)
1296 struct device *dev = &pdev->dev;
1297 struct exynos_drm_hdmi_context *drm_hdmi_ctx;
1298 struct exynos_drm_hdmi_pdata *pdata;
1299 struct mixer_context *mctx;
1302 dev_info(dev, "probe start\n");
1304 drm_hdmi_ctx = kzalloc(sizeof(*drm_hdmi_ctx), GFP_KERNEL);
1305 if (!drm_hdmi_ctx) {
1306 DRM_ERROR("failed to allocate common hdmi context.\n");
1310 mctx = kzalloc(sizeof(*mctx), GFP_KERNEL);
1312 DRM_ERROR("failed to alloc mixer context.\n");
1313 kfree(drm_hdmi_ctx);
1318 mctx->dev = &pdev->dev;
1319 drm_hdmi_ctx->ctx = (void *)mctx;
1321 platform_set_drvdata(pdev, drm_hdmi_ctx);
1323 /* Get from Platform soc deatils */
1324 pdata = pdev->dev.platform_data;
1326 /* acquire resources: regs, irqs, clocks */
1327 ret = mixer_resources_init_exynos(drm_hdmi_ctx, pdev,pdata->is_soc_exynos5);
1331 /* attach mixer driver to common hdmi. */
1332 exynos_mixer_drv_attach(drm_hdmi_ctx);
1334 /* register specific callback point to common hdmi. */
1335 exynos_mixer_ops_register(&mixer_ops);
1336 mctx->is_mixer_powered_on = false;
1337 pm_runtime_enable(dev);
1343 dev_info(dev, "probe failed\n");
1347 static int mixer_remove(struct platform_device *pdev)
1349 struct device *dev = &pdev->dev;
1350 struct exynos_drm_hdmi_context *drm_hdmi_ctx =
1351 platform_get_drvdata(pdev);
1352 struct mixer_context *mctx = drm_hdmi_ctx->ctx;
1354 dev_info(dev, "remove successful\n");
1356 mixer_resource_poweroff(mctx);
1357 mixer_resources_cleanup(mctx);
1360 kfree(drm_hdmi_ctx);
1365 struct platform_driver mixer_driver = {
1367 .name = "s5p-mixer",
1368 .owner = THIS_MODULE,
1369 .pm = &mixer_pm_ops,
1371 .probe = mixer_probe,
1372 .remove = __devexit_p(mixer_remove),