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_display.h"
41 #include "exynos_hdmi.h"
43 #include <plat/map-base.h>
44 #ifdef CONFIG_EXYNOS_IOMMU
45 #include <mach/sysmmu.h>
46 #include <linux/of_platform.h>
50 #define get_mixer_context(dev) platform_get_drvdata(to_platform_device(dev))
52 #define MIXER_WIN_NR 3
53 #define MIXER_DEFAULT_WIN 0
55 struct hdmi_win_data {
57 dma_addr_t chroma_dma_addr;
58 uint32_t pixel_format;
62 unsigned int crtc_width;
63 unsigned int crtc_height;
66 unsigned int fb_width;
67 unsigned int fb_height;
68 unsigned int mode_width;
69 unsigned int mode_height;
70 unsigned int scan_flags;
74 struct mixer_resources {
77 void __iomem *mixer_regs;
78 void __iomem *vp_regs;
80 wait_queue_head_t event_queue;
83 struct clk *sclk_mixer;
84 struct clk *sclk_hdmi;
86 unsigned int is_soc_exynos5;
89 struct mixer_context {
91 struct drm_device *drm_dev;
95 bool is_mixer_powered_on;
96 bool enabled[MIXER_WIN_NR];
98 struct mixer_resources mixer_res;
99 struct hdmi_win_data win_data[MIXER_WIN_NR];
100 unsigned long event_flags;
102 bool is_800x600_initialized;
105 /* event flags used */
106 enum mixer_status_flags {
110 static const u8 filter_y_horiz_tap8[] = {
111 0, -1, -1, -1, -1, -1, -1, -1,
112 -1, -1, -1, -1, -1, 0, 0, 0,
113 0, 2, 4, 5, 6, 6, 6, 6,
114 6, 5, 5, 4, 3, 2, 1, 1,
115 0, -6, -12, -16, -18, -20, -21, -20,
116 -20, -18, -16, -13, -10, -8, -5, -2,
117 127, 126, 125, 121, 114, 107, 99, 89,
118 79, 68, 57, 46, 35, 25, 16, 8,
121 static const u8 filter_y_vert_tap4[] = {
122 0, -3, -6, -8, -8, -8, -8, -7,
123 -6, -5, -4, -3, -2, -1, -1, 0,
124 127, 126, 124, 118, 111, 102, 92, 81,
125 70, 59, 48, 37, 27, 19, 11, 5,
126 0, 5, 11, 19, 27, 37, 48, 59,
127 70, 81, 92, 102, 111, 118, 124, 126,
128 0, 0, -1, -1, -2, -3, -4, -5,
129 -6, -7, -8, -8, -8, -8, -6, -3,
132 static const u8 filter_cr_horiz_tap4[] = {
133 0, -3, -6, -8, -8, -8, -8, -7,
134 -6, -5, -4, -3, -2, -1, -1, 0,
135 127, 126, 124, 118, 111, 102, 92, 81,
136 70, 59, 48, 37, 27, 19, 11, 5,
139 static void mixer_win_reset(struct mixer_context *mctx);
141 static inline u32 vp_reg_read(struct mixer_resources *res, u32 reg_id)
143 return readl(res->vp_regs + reg_id);
146 static inline void vp_reg_write(struct mixer_resources *res, u32 reg_id,
149 writel(val, res->vp_regs + reg_id);
152 static inline void vp_reg_writemask(struct mixer_resources *res, u32 reg_id,
155 u32 old = vp_reg_read(res, reg_id);
157 val = (val & mask) | (old & ~mask);
158 writel(val, res->vp_regs + reg_id);
161 static inline u32 mixer_reg_read(struct mixer_resources *res, u32 reg_id)
163 return readl(res->mixer_regs + reg_id);
166 static inline void mixer_reg_write(struct mixer_resources *res, u32 reg_id,
169 writel(val, res->mixer_regs + reg_id);
172 static inline void mixer_reg_writemask(struct mixer_resources *res,
173 u32 reg_id, u32 val, u32 mask)
175 u32 old = mixer_reg_read(res, reg_id);
177 val = (val & mask) | (old & ~mask);
178 writel(val, res->mixer_regs + reg_id);
181 enum exynos_mixer_mode_type exynos_mixer_get_mode_type(int width, int height)
183 if (width >= 464 && width <= 720 && height <= 480)
184 return EXYNOS_MIXER_MODE_SD_NTSC;
185 else if (width >= 464 && width <= 720 && height <= 576)
186 return EXYNOS_MIXER_MODE_SD_PAL;
187 else if (width >= 1024 && width <= 1280 && height <= 720)
188 return EXYNOS_MIXER_MODE_HD_720;
189 else if ((width == 1440 && height == 900) ||
190 (width == 800 && height == 600) ||
191 (width >= 1664 && width <= 1920 && height <= 1080))
192 return EXYNOS_MIXER_MODE_HD_1080;
194 return EXYNOS_MIXER_MODE_INVALID;
197 static void mixer_regs_dump(struct mixer_context *mctx)
199 #define DUMPREG(reg_id) \
201 DRM_DEBUG_KMS(#reg_id " = %08x\n", \
202 (u32)readl(mctx->mixer_res.mixer_regs + reg_id)); \
208 DUMPREG(MXR_INT_STATUS);
210 DUMPREG(MXR_LAYER_CFG);
211 DUMPREG(MXR_VIDEO_CFG);
213 DUMPREG(MXR_GRAPHIC0_CFG);
214 DUMPREG(MXR_GRAPHIC0_BASE);
215 DUMPREG(MXR_GRAPHIC0_SPAN);
216 DUMPREG(MXR_GRAPHIC0_WH);
217 DUMPREG(MXR_GRAPHIC0_SXY);
218 DUMPREG(MXR_GRAPHIC0_DXY);
220 DUMPREG(MXR_GRAPHIC1_CFG);
221 DUMPREG(MXR_GRAPHIC1_BASE);
222 DUMPREG(MXR_GRAPHIC1_SPAN);
223 DUMPREG(MXR_GRAPHIC1_WH);
224 DUMPREG(MXR_GRAPHIC1_SXY);
225 DUMPREG(MXR_GRAPHIC1_DXY);
229 static void vp_regs_dump(struct mixer_context *mctx)
231 #define DUMPREG(reg_id) \
233 DRM_DEBUG_KMS(#reg_id " = %08x\n", \
234 (u32) readl(mctx->mixer_res.vp_regs + reg_id)); \
239 DUMPREG(VP_SHADOW_UPDATE);
240 DUMPREG(VP_FIELD_ID);
242 DUMPREG(VP_IMG_SIZE_Y);
243 DUMPREG(VP_IMG_SIZE_C);
244 DUMPREG(VP_PER_RATE_CTRL);
245 DUMPREG(VP_TOP_Y_PTR);
246 DUMPREG(VP_BOT_Y_PTR);
247 DUMPREG(VP_TOP_C_PTR);
248 DUMPREG(VP_BOT_C_PTR);
249 DUMPREG(VP_ENDIAN_MODE);
250 DUMPREG(VP_SRC_H_POSITION);
251 DUMPREG(VP_SRC_V_POSITION);
252 DUMPREG(VP_SRC_WIDTH);
253 DUMPREG(VP_SRC_HEIGHT);
254 DUMPREG(VP_DST_H_POSITION);
255 DUMPREG(VP_DST_V_POSITION);
256 DUMPREG(VP_DST_WIDTH);
257 DUMPREG(VP_DST_HEIGHT);
264 static inline void vp_filter_set(struct mixer_resources *res,
265 int reg_id, const u8 *data, unsigned int size)
267 /* assure 4-byte align */
269 for (; size; size -= 4, reg_id += 4, data += 4) {
270 u32 val = (data[0] << 24) | (data[1] << 16) |
271 (data[2] << 8) | data[3];
272 vp_reg_write(res, reg_id, val);
276 static void vp_default_filter(struct mixer_resources *res)
278 vp_filter_set(res, VP_POLY8_Y0_LL,
279 filter_y_horiz_tap8, sizeof filter_y_horiz_tap8);
280 vp_filter_set(res, VP_POLY4_Y0_LL,
281 filter_y_vert_tap4, sizeof filter_y_vert_tap4);
282 vp_filter_set(res, VP_POLY4_C0_LL,
283 filter_cr_horiz_tap4, sizeof filter_cr_horiz_tap4);
286 static void mixer_vsync_set_update(struct mixer_context *mctx, bool enable)
288 struct mixer_resources *res = &mctx->mixer_res;
290 /* block update on vsync */
291 mixer_reg_writemask(res, MXR_STATUS, enable ?
292 MXR_STATUS_SYNC_ENABLE : 0, MXR_STATUS_SYNC_ENABLE);
294 if (!(res->is_soc_exynos5))
295 vp_reg_write(res, VP_SHADOW_UPDATE, enable ?
296 VP_SHADOW_UPDATE_ENABLE : 0);
299 static void mixer_cfg_scan(struct mixer_context *mctx, u32 width, u32 height)
301 struct mixer_resources *res = &mctx->mixer_res;
302 enum exynos_mixer_mode_type mode_type;
305 /* choosing between interlace and progressive mode */
306 val = (mctx->interlace ? MXR_CFG_SCAN_INTERLACE :
307 MXR_CFG_SCAN_PROGRASSIVE);
309 /* choosing between proper HD and SD mode */
310 mode_type = exynos_mixer_get_mode_type(width, height);
312 case EXYNOS_MIXER_MODE_SD_NTSC:
313 val |= MXR_CFG_SCAN_NTSC | MXR_CFG_SCAN_SD;
315 case EXYNOS_MIXER_MODE_SD_PAL:
316 val |= MXR_CFG_SCAN_PAL | MXR_CFG_SCAN_SD;
318 case EXYNOS_MIXER_MODE_HD_720:
319 val |= MXR_CFG_SCAN_HD_720 | MXR_CFG_SCAN_HD;
321 case EXYNOS_MIXER_MODE_HD_1080:
322 val |= MXR_CFG_SCAN_HD_1080 | MXR_CFG_SCAN_HD;
325 DRM_ERROR("Invalid mixer config %dx%d\n", width, height);
329 mixer_reg_writemask(res, MXR_CFG, val, MXR_CFG_SCAN_MASK);
332 static void mixer_set_layer_offset(struct mixer_context *mctx, u32 offset)
334 struct mixer_resources *res = &mctx->mixer_res;
335 int current_dxy = mixer_reg_read(res, MXR_GRAPHIC1_DXY);
337 if (mctx->previous_dxy != current_dxy) {
338 current_dxy += MXR_GRP_DXY_DX(offset);
339 mixer_reg_write(res, MXR_GRAPHIC1_DXY, current_dxy);
340 mctx->previous_dxy = current_dxy;
343 mixer_reg_write(res, MXR_GRAPHIC0_DXY, MXR_GRP_DXY_DX(offset));
346 static void mixer_toggle_3d_path(struct mixer_context *mctx)
348 struct mixer_resources *res = &mctx->mixer_res;
350 mixer_reg_write(res, MXR_TVOUT_CFG,
351 mctx->is_800x600_initialized ? 0x13 : 0x17);
353 mctx->is_800x600_initialized = true;
356 static void mixer_cfg_rgb_fmt(struct mixer_context *mctx, unsigned int height)
358 struct mixer_resources *res = &mctx->mixer_res;
362 val = MXR_CFG_RGB601_0_255;
363 } else if (height == 576) {
364 val = MXR_CFG_RGB601_0_255;
365 } else if (height == 720) {
366 val = MXR_CFG_RGB709_16_235;
367 mixer_reg_write(res, MXR_CM_COEFF_Y,
368 (1 << 30) | (94 << 20) | (314 << 10) |
370 mixer_reg_write(res, MXR_CM_COEFF_CB,
371 (972 << 20) | (851 << 10) | (225 << 0));
372 mixer_reg_write(res, MXR_CM_COEFF_CR,
373 (225 << 20) | (820 << 10) | (1004 << 0));
374 } else if (height == 1080) {
375 val = MXR_CFG_RGB709_16_235;
376 mixer_reg_write(res, MXR_CM_COEFF_Y,
377 (1 << 30) | (94 << 20) | (314 << 10) |
379 mixer_reg_write(res, MXR_CM_COEFF_CB,
380 (972 << 20) | (851 << 10) | (225 << 0));
381 mixer_reg_write(res, MXR_CM_COEFF_CR,
382 (225 << 20) | (820 << 10) | (1004 << 0));
384 val = MXR_CFG_RGB709_16_235;
385 mixer_reg_write(res, MXR_CM_COEFF_Y,
386 (1 << 30) | (94 << 20) | (314 << 10) |
388 mixer_reg_write(res, MXR_CM_COEFF_CB,
389 (972 << 20) | (851 << 10) | (225 << 0));
390 mixer_reg_write(res, MXR_CM_COEFF_CR,
391 (225 << 20) | (820 << 10) | (1004 << 0));
394 mixer_reg_writemask(res, MXR_CFG, val, MXR_CFG_RGB_FMT_MASK);
397 static void mixer_cfg_layer(struct mixer_context *mctx, int win, bool enable)
399 struct mixer_resources *res = &mctx->mixer_res;
400 u32 val = enable ? ~0 : 0;
404 mixer_reg_writemask(res, MXR_CFG, val, MXR_CFG_GRP0_ENABLE);
407 mixer_reg_writemask(res, MXR_CFG, val, MXR_CFG_GRP1_ENABLE);
410 vp_reg_writemask(res, VP_ENABLE, val, VP_ENABLE_ON);
411 mixer_reg_writemask(res, MXR_CFG, val, MXR_CFG_VP_ENABLE);
416 static void mixer_run(struct mixer_context *mctx)
418 struct mixer_resources *res = &mctx->mixer_res;
420 mixer_reg_writemask(res, MXR_STATUS, ~0, MXR_STATUS_REG_RUN);
422 mixer_regs_dump(mctx);
425 static int mixer_wait_for_vsync(struct mixer_context *mctx)
429 mctx->event_flags |= MXR_EVENT_VSYNC;
431 ret = wait_event_timeout(mctx->mixer_res.event_queue,
432 ((mctx->event_flags & MXR_EVENT_VSYNC) == 0), msecs_to_jiffies(1000));
439 static int mixer_get_layer_update_count(struct mixer_context *ctx)
441 struct mixer_resources *res = &ctx->mixer_res;
444 if (!res->is_soc_exynos5)
447 val = mixer_reg_read(res, MXR_CFG);
449 return (val & MXR_CFG_LAYER_UPDATE_COUNT_MASK) >>
450 MXR_CFG_LAYER_UPDATE_COUNT0;
453 static void mixer_layer_update(struct mixer_context *ctx)
455 struct mixer_resources *res = &ctx->mixer_res;
457 if (!res->is_soc_exynos5)
460 mixer_reg_writemask(res, MXR_CFG, ~0, MXR_CFG_LAYER_UPDATE);
463 static void vp_video_buffer(struct mixer_context *mctx, int win)
465 struct mixer_resources *res = &mctx->mixer_res;
467 struct hdmi_win_data *win_data;
468 unsigned int full_width, full_height, width, height;
469 unsigned int x_ratio, y_ratio;
470 unsigned int src_x_offset, src_y_offset, dst_x_offset, dst_y_offset;
471 unsigned int mode_width, mode_height;
472 unsigned int buf_num;
473 dma_addr_t luma_addr[2], chroma_addr[2];
474 bool tiled_mode = false;
475 bool crcb_mode = false;
478 win_data = &mctx->win_data[win];
480 switch (win_data->pixel_format) {
481 case DRM_FORMAT_NV12MT:
483 case DRM_FORMAT_NV12M:
487 /* TODO: single buffer format NV12, NV21 */
489 /* ignore pixel format at disable time */
490 if (!win_data->dma_addr)
493 DRM_ERROR("pixel format for vp is wrong [%d].\n",
494 win_data->pixel_format);
498 full_width = win_data->fb_width;
499 full_height = win_data->fb_height;
500 width = win_data->crtc_width;
501 height = win_data->crtc_height;
502 mode_width = win_data->mode_width;
503 mode_height = win_data->mode_height;
505 /* scaling feature: (src << 16) / dst */
506 x_ratio = (width << 16) / width;
507 y_ratio = (height << 16) / height;
509 src_x_offset = win_data->fb_x;
510 src_y_offset = win_data->fb_y;
511 dst_x_offset = win_data->crtc_x;
512 dst_y_offset = win_data->crtc_y;
515 luma_addr[0] = win_data->dma_addr;
516 chroma_addr[0] = win_data->chroma_dma_addr;
518 luma_addr[0] = win_data->dma_addr;
519 chroma_addr[0] = win_data->dma_addr
520 + (full_width * full_height);
523 if (win_data->scan_flags & DRM_MODE_FLAG_INTERLACE) {
524 mctx->interlace = true;
526 luma_addr[1] = luma_addr[0] + 0x40;
527 chroma_addr[1] = chroma_addr[0] + 0x40;
529 luma_addr[1] = luma_addr[0] + full_width;
530 chroma_addr[1] = chroma_addr[0] + full_width;
533 mctx->interlace = false;
538 spin_lock_irqsave(&res->reg_slock, flags);
539 mixer_vsync_set_update(mctx, false);
541 mctx->enabled[win] = true;
543 /* interlace or progressive scan mode */
544 val = (mctx->interlace ? ~0 : 0);
545 vp_reg_writemask(res, VP_MODE, val, VP_MODE_LINE_SKIP);
548 val = (crcb_mode ? VP_MODE_NV21 : VP_MODE_NV12);
549 val |= (tiled_mode ? VP_MODE_MEM_TILED : VP_MODE_MEM_LINEAR);
550 vp_reg_writemask(res, VP_MODE, val, VP_MODE_FMT_MASK);
552 /* setting size of input image */
553 vp_reg_write(res, VP_IMG_SIZE_Y, VP_IMG_HSIZE(full_width) |
554 VP_IMG_VSIZE(full_height));
555 /* chroma height has to reduced by 2 to avoid chroma distorions */
556 vp_reg_write(res, VP_IMG_SIZE_C, VP_IMG_HSIZE(full_width) |
557 VP_IMG_VSIZE(full_height / 2));
559 vp_reg_write(res, VP_SRC_WIDTH, width);
560 vp_reg_write(res, VP_SRC_HEIGHT, height);
561 vp_reg_write(res, VP_SRC_H_POSITION,
562 VP_SRC_H_POSITION_VAL(src_x_offset));
563 vp_reg_write(res, VP_SRC_V_POSITION, src_y_offset);
565 vp_reg_write(res, VP_DST_WIDTH, width);
566 vp_reg_write(res, VP_DST_H_POSITION, dst_x_offset);
567 if (mctx->interlace) {
568 vp_reg_write(res, VP_DST_HEIGHT, height / 2);
569 vp_reg_write(res, VP_DST_V_POSITION, dst_y_offset / 2);
571 vp_reg_write(res, VP_DST_HEIGHT, height);
572 vp_reg_write(res, VP_DST_V_POSITION, dst_y_offset);
575 vp_reg_write(res, VP_H_RATIO, x_ratio);
576 vp_reg_write(res, VP_V_RATIO, y_ratio);
578 vp_reg_write(res, VP_ENDIAN_MODE, VP_ENDIAN_MODE_LITTLE);
580 /* set buffer address to vp */
581 vp_reg_write(res, VP_TOP_Y_PTR, luma_addr[0]);
582 vp_reg_write(res, VP_BOT_Y_PTR, luma_addr[1]);
583 vp_reg_write(res, VP_TOP_C_PTR, chroma_addr[0]);
584 vp_reg_write(res, VP_BOT_C_PTR, chroma_addr[1]);
586 mixer_cfg_scan(mctx, mode_width, mode_height);
587 mixer_cfg_rgb_fmt(mctx, mode_height);
588 mixer_cfg_layer(mctx, win, true);
591 mixer_vsync_set_update(mctx, true);
592 spin_unlock_irqrestore(&res->reg_slock, flags);
597 static void mixer_graph_buffer(struct mixer_context *mctx, int win)
599 struct mixer_resources *res = &mctx->mixer_res;
601 struct hdmi_win_data *win_data;
602 unsigned int full_width, width, height;
603 unsigned int x_ratio, y_ratio;
604 unsigned int src_x_offset, src_y_offset, dst_x_offset, dst_y_offset;
605 unsigned int mode_width, mode_height;
610 win_data = &mctx->win_data[win];
617 switch (win_data->bpp) {
628 dma_addr = win_data->dma_addr;
629 full_width = win_data->fb_width;
630 width = win_data->crtc_width;
631 height = win_data->crtc_height;
632 mode_width = win_data->mode_width;
633 mode_height = win_data->mode_height;
635 /* 2x scaling feature */
639 src_x_offset = win_data->fb_x;
640 src_y_offset = win_data->fb_y;
641 dst_x_offset = win_data->crtc_x;
642 dst_y_offset = win_data->crtc_y;
644 /* converting dma address base and source offset */
646 + (src_x_offset * win_data->bpp >> 3)
647 + (src_y_offset * full_width * win_data->bpp >> 3);
651 if (win_data->scan_flags & DRM_MODE_FLAG_INTERLACE)
652 mctx->interlace = true;
654 mctx->interlace = false;
656 spin_lock_irqsave(&res->reg_slock, flags);
657 mixer_vsync_set_update(mctx, false);
659 mctx->enabled[win] = true;
662 mixer_reg_writemask(res, MXR_GRAPHIC_CFG(win),
663 MXR_GRP_CFG_FORMAT_VAL(fmt), MXR_GRP_CFG_FORMAT_MASK);
666 mixer_reg_write(res, MXR_GRAPHIC_SPAN(win), full_width);
668 val = MXR_GRP_WH_WIDTH(width);
669 val |= MXR_GRP_WH_HEIGHT(height);
670 val |= MXR_GRP_WH_H_SCALE(x_ratio);
671 val |= MXR_GRP_WH_V_SCALE(y_ratio);
672 mixer_reg_write(res, MXR_GRAPHIC_WH(win), val);
674 /* setup offsets in source image */
675 val = MXR_GRP_SXY_SX(src_x_offset);
676 val |= MXR_GRP_SXY_SY(src_y_offset);
677 mixer_reg_write(res, MXR_GRAPHIC_SXY(win), val);
679 /* setup offsets in display image */
680 val = MXR_GRP_DXY_DX(dst_x_offset);
681 val |= MXR_GRP_DXY_DY(dst_y_offset);
682 mixer_reg_write(res, MXR_GRAPHIC_DXY(win), val);
684 /* set buffer address to mixer */
685 mixer_reg_write(res, MXR_GRAPHIC_BASE(win), dma_addr);
687 mixer_cfg_scan(mctx, mode_width, mode_height);
689 if (res->is_soc_exynos5) {
690 /* Workaround 4 implementation for 1440x900 resolution support */
691 if (mode_width == 1440 && mode_height == 900)
692 mixer_set_layer_offset(mctx, 224);
694 /* Workaround 3 implementation for 800x600 resolution support */
695 if (mode_width == 800 && mode_height == 600) {
696 mixer_set_layer_offset(mctx, 32);
697 mixer_toggle_3d_path(mctx);
699 mctx->is_800x600_initialized = false;
702 mixer_cfg_rgb_fmt(mctx, mode_height);
703 mixer_cfg_layer(mctx, win, true);
704 mixer_cfg_layer(mctx, MIXER_DEFAULT_WIN, true);
706 /* Only allow one update per vsync */
707 if (!win_data->updated)
708 mixer_layer_update(mctx);
710 win_data->updated = true;
713 mixer_vsync_set_update(mctx, true);
714 spin_unlock_irqrestore(&res->reg_slock, flags);
717 static void vp_win_reset(struct mixer_context *mctx)
719 struct mixer_resources *res = &mctx->mixer_res;
722 vp_reg_write(res, VP_SRESET, VP_SRESET_PROCESSING);
723 for (tries = 100; tries; --tries) {
724 /* waiting until VP_SRESET_PROCESSING is 0 */
725 if (~vp_reg_read(res, VP_SRESET) & VP_SRESET_PROCESSING)
729 WARN(tries == 0, "failed to reset Video Processor\n");
732 static int mixer_enable_vblank(void *ctx, int pipe)
734 struct mixer_context *mctx = ctx;
735 struct mixer_resources *res = &mctx->mixer_res;
737 DRM_DEBUG_KMS("[%d] %s\n", __LINE__, __func__);
740 * TODO (seanpaul): Right now, this is an expected code path since we
741 * call enable_vblank in the poweron routine; pipe might not be
742 * initialized the first time we run it. We should refactor things such
743 * that this isn't the case and we can either BUG_ON or DRM_ERROR here.
750 /* enable vsync interrupt */
751 mixer_reg_writemask(res, MXR_INT_EN, MXR_INT_EN_VSYNC,
757 static void mixer_disable_vblank(void *ctx)
759 struct mixer_context *mctx = ctx;
760 struct mixer_resources *res = &mctx->mixer_res;
762 DRM_DEBUG_KMS("[%d] %s\n", __LINE__, __func__);
764 /* disable vsync interrupt */
765 mixer_reg_writemask(res, MXR_INT_EN, 0, MXR_INT_EN_VSYNC);
768 static void mixer_win_mode_set(void *ctx,
769 struct exynos_drm_overlay *overlay)
771 struct mixer_context *mctx = ctx;
772 struct hdmi_win_data *win_data;
775 DRM_DEBUG_KMS("[%d] %s\n", __LINE__, __func__);
778 DRM_ERROR("overlay is NULL\n");
782 DRM_DEBUG_KMS("set [%d]x[%d] at (%d,%d) to [%d]x[%d] at (%d,%d)\n",
783 overlay->fb_width, overlay->fb_height,
784 overlay->fb_x, overlay->fb_y,
785 overlay->crtc_width, overlay->crtc_height,
786 overlay->crtc_x, overlay->crtc_y);
789 if (win == DEFAULT_ZPOS)
790 win = MIXER_DEFAULT_WIN;
792 if (win < 0 || win > MIXER_WIN_NR) {
793 DRM_ERROR("overlay plane[%d] is wrong\n", win);
797 win_data = &mctx->win_data[win];
799 win_data->dma_addr = overlay->dma_addr[0];
800 win_data->chroma_dma_addr = overlay->dma_addr[1];
801 win_data->pixel_format = overlay->pixel_format;
802 win_data->bpp = overlay->bpp;
804 win_data->crtc_x = overlay->crtc_x;
805 win_data->crtc_y = overlay->crtc_y;
806 win_data->crtc_width = overlay->crtc_width;
807 win_data->crtc_height = overlay->crtc_height;
809 win_data->fb_x = overlay->fb_x;
810 win_data->fb_y = overlay->fb_y;
811 win_data->fb_width = overlay->fb_pitch / (overlay->bpp >> 3);
812 win_data->fb_height = overlay->fb_height;
814 win_data->mode_width = overlay->mode_width;
815 win_data->mode_height = overlay->mode_height;
817 win_data->scan_flags = overlay->scan_flag;
820 static void mixer_win_commit(void *ctx, int zpos)
822 struct mixer_context *mctx = ctx;
823 struct mixer_resources *res = &mctx->mixer_res;
826 DRM_DEBUG_KMS("[%d] %s, win: %d\n", __LINE__, __func__, win);
827 if (win == DEFAULT_ZPOS)
828 win = MIXER_DEFAULT_WIN;
830 if (win < 0 || win > MIXER_WIN_NR) {
831 DRM_ERROR("overlay plane[%d] is wrong\n", win);
835 if (!mctx->is_mixer_powered_on) {
836 DRM_DEBUG_KMS("[%d] %s not powered on\n", __LINE__, __func__);
840 if (!(res->is_soc_exynos5)) {
842 vp_video_buffer(mctx, win);
844 mixer_graph_buffer(mctx, win);
847 mixer_graph_buffer(mctx, win);
850 static void mixer_apply(void *ctx)
852 struct mixer_context *mctx = ctx;
855 for (i = 0; i < MIXER_WIN_NR; i++) {
856 if (!mctx->enabled[i])
859 mixer_win_commit(ctx, i);
863 static void mixer_win_disable(void *ctx, int zpos)
865 struct mixer_context *mctx = ctx;
866 struct mixer_resources *res = &mctx->mixer_res;
870 DRM_DEBUG_KMS("[%d] %s, win: %d\n", __LINE__, __func__, win);
872 if (win == DEFAULT_ZPOS)
873 win = MIXER_DEFAULT_WIN;
875 if (win < 0 || win > MIXER_WIN_NR) {
876 DRM_ERROR("overlay plane[%d] is wrong\n", win);
880 mixer_wait_for_vsync(mctx);
882 spin_lock_irqsave(&res->reg_slock, flags);
883 mixer_vsync_set_update(mctx, false);
885 mctx->enabled[win] = false;
886 mixer_cfg_layer(mctx, win, false);
888 mixer_vsync_set_update(mctx, true);
890 spin_unlock_irqrestore(&res->reg_slock, flags);
892 if (win == MIXER_DEFAULT_WIN) {
893 mixer_win_reset(mctx);
894 mixer_enable_vblank(mctx, mctx->pipe);
898 /* for pageflip event */
899 static irqreturn_t mixer_irq_handler(int irq, void *arg)
901 struct mixer_context *mctx = arg;
902 struct mixer_resources *res = &mctx->mixer_res;
903 u32 val, base, shadow;
904 bool flip_complete = false;
907 spin_lock(&res->reg_slock);
909 WARN_ON(!mctx->is_mixer_powered_on);
911 /* read interrupt status for handling and clearing flags for VSYNC */
912 val = mixer_reg_read(res, MXR_INT_STATUS);
915 if (val & MXR_INT_STATUS_VSYNC) {
916 /* interlace scan need to check shadow register */
917 if (mctx->interlace && !res->is_soc_exynos5) {
918 base = mixer_reg_read(res, MXR_GRAPHIC_BASE(0));
919 shadow = mixer_reg_read(res, MXR_GRAPHIC_BASE_S(0));
923 base = mixer_reg_read(res, MXR_GRAPHIC_BASE(1));
924 shadow = mixer_reg_read(res, MXR_GRAPHIC_BASE_S(1));
929 drm_handle_vblank(mctx->drm_dev, mctx->pipe);
931 /* Bail out if a layer update is pending */
932 if (mixer_get_layer_update_count(mctx))
935 for (i = 0; i < MIXER_WIN_NR; i++)
936 mctx->win_data[i].updated = false;
938 flip_complete = true;
940 if (mctx->event_flags & MXR_EVENT_VSYNC) {
941 DRM_DEBUG_KMS("mctx->event_flags & MXR_EVENT_VSYNC");
943 mctx->event_flags &= ~MXR_EVENT_VSYNC;
944 wake_up(&mctx->mixer_res.event_queue);
949 /* clear interrupts */
950 if (~val & MXR_INT_EN_VSYNC) {
951 /* vsync interrupt use different bit for read and clear */
952 val &= ~MXR_INT_EN_VSYNC;
953 val |= MXR_INT_CLEAR_VSYNC;
955 mixer_reg_write(res, MXR_INT_STATUS, val);
957 spin_unlock(&res->reg_slock);
960 exynos_drm_crtc_finish_pageflip(mctx->drm_dev, mctx->pipe);
965 static void mixer_win_reset(struct mixer_context *mctx)
967 struct mixer_resources *res = &mctx->mixer_res;
969 u32 val; /* value stored to register */
971 spin_lock_irqsave(&res->reg_slock, flags);
972 mixer_reg_writemask(res, MXR_STATUS, ~0, MXR_STATUS_SOFT_RESET);
973 mixer_vsync_set_update(mctx, false);
975 mixer_reg_writemask(res, MXR_CFG, MXR_CFG_DST_HDMI, MXR_CFG_DST_MASK);
977 /* set output in RGB888 mode */
978 mixer_reg_writemask(res, MXR_CFG, MXR_CFG_OUT_RGB888, MXR_CFG_OUT_MASK);
980 /* 16 beat burst in DMA */
981 mixer_reg_writemask(res, MXR_STATUS, MXR_STATUS_16_BURST,
982 MXR_STATUS_BURST_MASK);
984 /* setting default layer priority: layer1 > layer0 > video
985 * because typical usage scenario would be
987 * layer0 - framebuffer
988 * video - video overlay
990 val = MXR_LAYER_CFG_GRP1_VAL(3);
991 val |= MXR_LAYER_CFG_GRP0_VAL(2);
992 val |= MXR_LAYER_CFG_VP_VAL(1);
993 mixer_reg_write(res, MXR_LAYER_CFG, val);
995 /* setting background color */
996 mixer_reg_write(res, MXR_BG_COLOR0, 0x008080);
997 mixer_reg_write(res, MXR_BG_COLOR1, 0x008080);
998 mixer_reg_write(res, MXR_BG_COLOR2, 0x008080);
1000 /* setting graphical layers */
1002 val = MXR_GRP_CFG_COLOR_KEY_DISABLE; /* no blank key */
1003 val |= MXR_GRP_CFG_WIN_BLEND_EN;
1004 val |= MXR_GRP_CFG_ALPHA_VAL(0xff); /* non-transparent alpha */
1006 /* the same configuration for both layers */
1007 mixer_reg_write(res, MXR_GRAPHIC_CFG(0), val);
1009 val |= MXR_GRP_CFG_BLEND_PRE_MUL;
1010 val |= MXR_GRP_CFG_PIXEL_BLEND_EN;
1011 mixer_reg_write(res, MXR_GRAPHIC_CFG(1), val);
1013 if (!(res->is_soc_exynos5)) {
1014 /* configuration of Video Processor for Exynos4 soc */
1016 vp_default_filter(res);
1019 /* disable all layers */
1020 mixer_reg_writemask(res, MXR_CFG, 0, MXR_CFG_GRP0_ENABLE);
1021 mixer_reg_writemask(res, MXR_CFG, 0, MXR_CFG_GRP1_ENABLE);
1022 mixer_reg_writemask(res, MXR_CFG, 0, MXR_CFG_VP_ENABLE);
1024 mixer_vsync_set_update(mctx, true);
1025 spin_unlock_irqrestore(&res->reg_slock, flags);
1028 static void mixer_resource_poweron(struct mixer_context *mctx)
1030 struct mixer_resources *res = &mctx->mixer_res;
1032 if (mctx->is_mixer_powered_on)
1035 clk_enable(res->mixer);
1036 if (!(res->is_soc_exynos5)) {
1037 clk_enable(res->vp);
1038 clk_enable(res->sclk_mixer);
1041 mixer_win_reset(mctx);
1042 mixer_enable_vblank(mctx, mctx->pipe);
1044 mctx->is_mixer_powered_on = true;
1048 static void mixer_resource_poweroff(struct mixer_context *mctx)
1050 struct mixer_resources *res = &mctx->mixer_res;
1052 DRM_DEBUG_KMS("[%d] %s\n", __LINE__, __func__);
1053 if (!mctx->is_mixer_powered_on)
1056 clk_disable(res->mixer);
1057 if (!(res->is_soc_exynos5)) {
1058 clk_disable(res->vp);
1059 clk_disable(res->sclk_mixer);
1061 mixer_win_reset(mctx);
1062 mctx->is_mixer_powered_on = false;
1065 static int mixer_power(void *ctx, int mode)
1067 struct mixer_context *mctx = ctx;
1069 DRM_DEBUG_KMS("[%d] %s\n", __LINE__, __func__);
1072 case DRM_MODE_DPMS_ON:
1073 mixer_resource_poweron(mctx);
1075 case DRM_MODE_DPMS_STANDBY:
1076 case DRM_MODE_DPMS_SUSPEND:
1077 case DRM_MODE_DPMS_OFF:
1078 mixer_resource_poweroff(mctx);
1081 DRM_DEBUG_KMS("unknown dpms mode: %d\n", mode);
1088 static int mixer_subdrv_probe(void *ctx, struct drm_device *drm_dev)
1090 struct mixer_context *mctx = ctx;
1092 mctx->drm_dev = drm_dev;
1097 static struct exynos_controller_ops mixer_ops = {
1099 .subdrv_probe = mixer_subdrv_probe,
1100 .enable_vblank = mixer_enable_vblank,
1101 .disable_vblank = mixer_disable_vblank,
1102 .power = mixer_power,
1105 .mode_set = mixer_win_mode_set,
1106 .win_commit = mixer_win_commit,
1107 .win_disable = mixer_win_disable,
1110 #ifdef CONFIG_EXYNOS_IOMMU
1111 static int iommu_init(struct platform_device *pdev)
1113 struct platform_device *pds;
1115 pds = find_sysmmu_dt(pdev, "sysmmu");
1117 printk(KERN_ERR "No sysmmu found :\n");
1121 platform_set_sysmmu(&pds->dev, &pdev->dev);
1123 * The ordering in Makefile warrants that this is initialized after
1124 * FIMD, so only just ensure that it works as expected and we are
1125 * reusing the mapping originally created in exynos_drm_fimd.c.
1127 WARN_ON(!exynos_drm_common_mapping);
1128 exynos_drm_common_mapping = s5p_create_iommu_mapping(&pdev->dev,
1129 0, 0, 0, exynos_drm_common_mapping);
1130 if(exynos_drm_common_mapping == NULL) {
1131 printk(KERN_ERR"Failed to create iommu mapping for Mixer\n");
1138 static void iommu_deinit(struct platform_device *pdev)
1140 s5p_destroy_iommu_mapping(&pdev->dev);
1141 DRM_DEBUG("released the IOMMU mapping\n");
1145 static int __devinit mixer_resources_init_exynos(
1146 struct mixer_context *mctx,
1147 struct platform_device *pdev,
1150 struct device *dev = &pdev->dev;
1151 struct mixer_resources *mixer_res = &mctx->mixer_res;
1152 struct resource *res;
1155 DRM_DEBUG_KMS("Mixer resources init\n");
1157 mixer_res->is_soc_exynos5 = is_exynos5;
1158 mixer_res->dev = dev;
1159 spin_lock_init(&mixer_res->reg_slock);
1162 init_waitqueue_head(&mixer_res->event_queue);
1164 mixer_res->mixer = clk_get(dev, "mixer");
1165 if (IS_ERR_OR_NULL(mixer_res->mixer)) {
1166 dev_err(dev, "failed to get clock 'mixer'\n");
1171 mixer_res->vp = clk_get(dev, "vp");
1172 if (IS_ERR_OR_NULL(mixer_res->vp)) {
1173 dev_err(dev, "failed to get clock 'vp'\n");
1177 mixer_res->sclk_mixer = clk_get(dev, "sclk_mixer");
1178 if (IS_ERR_OR_NULL(mixer_res->sclk_mixer)) {
1179 dev_err(dev, "failed to get clock 'sclk_mixer'\n");
1184 mixer_res->sclk_hdmi = clk_get(dev, "sclk_hdmi");
1185 if (IS_ERR_OR_NULL(mixer_res->sclk_hdmi)) {
1186 dev_err(dev, "failed to get clock 'sclk_hdmi'\n");
1191 mixer_res->sclk_dac = clk_get(dev, "sclk_dac");
1192 if (IS_ERR_OR_NULL(mixer_res->sclk_dac)) {
1193 dev_err(dev, "failed to get clock 'sclk_dac'\n");
1197 res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "mxr");
1200 res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
1203 dev_err(dev, "get memory resource failed.\n");
1209 clk_set_parent(mixer_res->sclk_mixer, mixer_res->sclk_hdmi);
1211 mixer_res->mixer_regs = ioremap(res->start, resource_size(res));
1212 if (mixer_res->mixer_regs == NULL) {
1213 dev_err(dev, "register mapping failed.\n");
1219 res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "vp");
1221 dev_err(dev, "get memory resource failed.\n");
1226 mixer_res->vp_regs = ioremap(res->start, resource_size(res));
1227 if (mixer_res->vp_regs == NULL) {
1228 dev_err(dev, "register mapping failed.\n");
1233 res = platform_get_resource_byname(pdev, IORESOURCE_IRQ, "irq");
1235 dev_err(dev, "get interrupt resource failed.\n");
1240 res = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
1242 dev_err(dev, "get interrupt resource failed.\n");
1244 goto fail_mixer_regs;
1248 ret = request_irq(res->start, mixer_irq_handler, 0, "drm_mixer", mctx);
1250 dev_err(dev, "request interrupt failed.\n");
1251 goto fail_mixer_regs;
1253 mixer_res->irq = res->start;
1255 #ifdef CONFIG_EXYNOS_IOMMU
1256 ret = iommu_init(pdev);
1258 dev_err(dev, "iommu init failed.\n");
1259 goto fail_mixer_regs;
1265 iounmap(mixer_res->vp_regs);
1268 iounmap(mixer_res->mixer_regs);
1271 if (!IS_ERR_OR_NULL(mixer_res->sclk_dac))
1272 clk_put(mixer_res->sclk_dac);
1273 if (!IS_ERR_OR_NULL(mixer_res->sclk_hdmi))
1274 clk_put(mixer_res->sclk_hdmi);
1275 if (!IS_ERR_OR_NULL(mixer_res->sclk_mixer))
1276 clk_put(mixer_res->sclk_mixer);
1277 if (!IS_ERR_OR_NULL(mixer_res->vp))
1278 clk_put(mixer_res->vp);
1279 if (!IS_ERR_OR_NULL(mixer_res->mixer))
1280 clk_put(mixer_res->mixer);
1281 mixer_res->dev = NULL;
1285 static void mixer_resources_cleanup(struct device *dev,
1286 struct mixer_context *mctx)
1288 struct mixer_resources *res = &mctx->mixer_res;
1290 disable_irq(res->irq);
1291 free_irq(res->irq, dev);
1293 iounmap(res->vp_regs);
1294 iounmap(res->mixer_regs);
1297 static int __devinit mixer_probe(struct platform_device *pdev)
1299 struct device *dev = &pdev->dev;
1300 struct exynos_drm_hdmi_pdata *pdata;
1301 struct mixer_context *mctx;
1304 dev_info(dev, "probe start\n");
1306 mctx = kzalloc(sizeof(*mctx), GFP_KERNEL);
1308 DRM_ERROR("failed to alloc mixer context.\n");
1312 mctx->dev = &pdev->dev;
1315 platform_set_drvdata(pdev, mctx);
1317 /* Get from Platform soc deatils */
1318 pdata = pdev->dev.platform_data;
1320 /* acquire resources: regs, irqs, clocks */
1321 ret = mixer_resources_init_exynos(mctx, pdev, pdata->is_soc_exynos5);
1325 mctx->is_mixer_powered_on = false;
1326 pm_runtime_enable(dev);
1328 exynos_display_attach_controller(EXYNOS_DRM_DISPLAY_TYPE_MIXER,
1335 dev_info(dev, "probe failed\n");
1339 static int mixer_remove(struct platform_device *pdev)
1341 struct device *dev = &pdev->dev;
1342 struct mixer_context *mctx = platform_get_drvdata(pdev);
1344 dev_info(dev, "remove successful\n");
1346 mixer_resource_poweroff(mctx);
1347 mixer_resources_cleanup(dev, mctx);
1349 #ifdef CONFIG_EXYNOS_IOMMU
1358 struct platform_driver mixer_driver = {
1360 .name = "s5p-mixer",
1361 .owner = THIS_MODULE,
1363 .probe = mixer_probe,
1364 .remove = __devexit_p(mixer_remove),