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>
47 #define MIXER_WIN_NR 3
48 #define MIXER_DEFAULT_WIN 0
50 #define get_mixer_context(dev) platform_get_drvdata(to_platform_device(dev))
52 struct hdmi_win_data {
55 dma_addr_t chroma_dma_addr;
56 void __iomem *chroma_vaddr;
57 uint32_t pixel_format;
61 unsigned int crtc_width;
62 unsigned int crtc_height;
65 unsigned int fb_width;
66 unsigned int fb_height;
67 unsigned int mode_width;
68 unsigned int mode_height;
69 unsigned int scan_flags;
73 struct mixer_resources {
76 void __iomem *mixer_regs;
77 void __iomem *vp_regs;
79 wait_queue_head_t event_queue;
82 struct clk *sclk_mixer;
83 struct clk *sclk_hdmi;
85 unsigned int is_soc_exynos5;
88 struct mixer_context {
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 *ctx);
134 static inline u32 vp_reg_read(struct mixer_resources *res, u32 reg_id)
136 return readl(res->vp_regs + reg_id);
139 static inline void vp_reg_write(struct mixer_resources *res, u32 reg_id,
142 writel(val, res->vp_regs + reg_id);
145 static inline void vp_reg_writemask(struct mixer_resources *res, u32 reg_id,
148 u32 old = vp_reg_read(res, reg_id);
150 val = (val & mask) | (old & ~mask);
151 writel(val, res->vp_regs + reg_id);
154 static inline u32 mixer_reg_read(struct mixer_resources *res, u32 reg_id)
156 return readl(res->mixer_regs + reg_id);
159 static inline void mixer_reg_write(struct mixer_resources *res, u32 reg_id,
162 writel(val, res->mixer_regs + reg_id);
165 static inline void mixer_reg_writemask(struct mixer_resources *res,
166 u32 reg_id, u32 val, u32 mask)
168 u32 old = mixer_reg_read(res, reg_id);
170 val = (val & mask) | (old & ~mask);
171 writel(val, res->mixer_regs + reg_id);
174 static void mixer_regs_dump(struct mixer_context *ctx)
176 #define DUMPREG(reg_id) \
178 DRM_DEBUG_KMS(#reg_id " = %08x\n", \
179 (u32)readl(ctx->mixer_res.mixer_regs + reg_id)); \
185 DUMPREG(MXR_INT_STATUS);
187 DUMPREG(MXR_LAYER_CFG);
188 DUMPREG(MXR_VIDEO_CFG);
190 DUMPREG(MXR_GRAPHIC0_CFG);
191 DUMPREG(MXR_GRAPHIC0_BASE);
192 DUMPREG(MXR_GRAPHIC0_SPAN);
193 DUMPREG(MXR_GRAPHIC0_WH);
194 DUMPREG(MXR_GRAPHIC0_SXY);
195 DUMPREG(MXR_GRAPHIC0_DXY);
197 DUMPREG(MXR_GRAPHIC1_CFG);
198 DUMPREG(MXR_GRAPHIC1_BASE);
199 DUMPREG(MXR_GRAPHIC1_SPAN);
200 DUMPREG(MXR_GRAPHIC1_WH);
201 DUMPREG(MXR_GRAPHIC1_SXY);
202 DUMPREG(MXR_GRAPHIC1_DXY);
206 static void vp_regs_dump(struct mixer_context *ctx)
208 #define DUMPREG(reg_id) \
210 DRM_DEBUG_KMS(#reg_id " = %08x\n", \
211 (u32) readl(ctx->mixer_res.vp_regs + reg_id)); \
216 DUMPREG(VP_SHADOW_UPDATE);
217 DUMPREG(VP_FIELD_ID);
219 DUMPREG(VP_IMG_SIZE_Y);
220 DUMPREG(VP_IMG_SIZE_C);
221 DUMPREG(VP_PER_RATE_CTRL);
222 DUMPREG(VP_TOP_Y_PTR);
223 DUMPREG(VP_BOT_Y_PTR);
224 DUMPREG(VP_TOP_C_PTR);
225 DUMPREG(VP_BOT_C_PTR);
226 DUMPREG(VP_ENDIAN_MODE);
227 DUMPREG(VP_SRC_H_POSITION);
228 DUMPREG(VP_SRC_V_POSITION);
229 DUMPREG(VP_SRC_WIDTH);
230 DUMPREG(VP_SRC_HEIGHT);
231 DUMPREG(VP_DST_H_POSITION);
232 DUMPREG(VP_DST_V_POSITION);
233 DUMPREG(VP_DST_WIDTH);
234 DUMPREG(VP_DST_HEIGHT);
241 static inline void vp_filter_set(struct mixer_resources *res,
242 int reg_id, const u8 *data, unsigned int size)
244 /* assure 4-byte align */
246 for (; size; size -= 4, reg_id += 4, data += 4) {
247 u32 val = (data[0] << 24) | (data[1] << 16) |
248 (data[2] << 8) | data[3];
249 vp_reg_write(res, reg_id, val);
253 static void vp_default_filter(struct mixer_resources *res)
255 vp_filter_set(res, VP_POLY8_Y0_LL,
256 filter_y_horiz_tap8, sizeof filter_y_horiz_tap8);
257 vp_filter_set(res, VP_POLY4_Y0_LL,
258 filter_y_vert_tap4, sizeof filter_y_vert_tap4);
259 vp_filter_set(res, VP_POLY4_C0_LL,
260 filter_cr_horiz_tap4, sizeof filter_cr_horiz_tap4);
263 static void mixer_vsync_set_update(struct mixer_context *ctx, bool enable)
265 struct mixer_resources *res = &ctx->mixer_res;
267 /* block update on vsync */
268 mixer_reg_writemask(res, MXR_STATUS, enable ?
269 MXR_STATUS_SYNC_ENABLE : 0, MXR_STATUS_SYNC_ENABLE);
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 *ctx, unsigned int height)
278 struct mixer_resources *res = &ctx->mixer_res;
281 /* choosing between interlace and progressive mode */
282 val = (ctx->interlace ? MXR_CFG_SCAN_INTERLACE :
283 MXR_CFG_SCAN_PROGRASSIVE);
285 /* choosing between porper HD and SD mode */
287 val |= MXR_CFG_SCAN_NTSC | MXR_CFG_SCAN_SD;
288 else if (height == 576)
289 val |= MXR_CFG_SCAN_PAL | MXR_CFG_SCAN_SD;
290 else if (height == 720)
291 val |= MXR_CFG_SCAN_HD_720 | MXR_CFG_SCAN_HD;
292 else if (height == 1080)
293 val |= MXR_CFG_SCAN_HD_1080 | MXR_CFG_SCAN_HD;
295 val |= MXR_CFG_SCAN_HD_720 | MXR_CFG_SCAN_HD;
297 mixer_reg_writemask(res, MXR_CFG, val, MXR_CFG_SCAN_MASK);
300 static void mixer_cfg_rgb_fmt(struct mixer_context *ctx, unsigned int height)
302 struct mixer_resources *res = &ctx->mixer_res;
306 val = MXR_CFG_RGB601_0_255;
307 } else if (height == 576) {
308 val = MXR_CFG_RGB601_0_255;
309 } else if (height == 720) {
310 val = MXR_CFG_RGB709_16_235;
311 mixer_reg_write(res, MXR_CM_COEFF_Y,
312 (1 << 30) | (94 << 20) | (314 << 10) |
314 mixer_reg_write(res, MXR_CM_COEFF_CB,
315 (972 << 20) | (851 << 10) | (225 << 0));
316 mixer_reg_write(res, MXR_CM_COEFF_CR,
317 (225 << 20) | (820 << 10) | (1004 << 0));
318 } else if (height == 1080) {
319 val = MXR_CFG_RGB709_16_235;
320 mixer_reg_write(res, MXR_CM_COEFF_Y,
321 (1 << 30) | (94 << 20) | (314 << 10) |
323 mixer_reg_write(res, MXR_CM_COEFF_CB,
324 (972 << 20) | (851 << 10) | (225 << 0));
325 mixer_reg_write(res, MXR_CM_COEFF_CR,
326 (225 << 20) | (820 << 10) | (1004 << 0));
328 val = MXR_CFG_RGB709_16_235;
329 mixer_reg_write(res, MXR_CM_COEFF_Y,
330 (1 << 30) | (94 << 20) | (314 << 10) |
332 mixer_reg_write(res, MXR_CM_COEFF_CB,
333 (972 << 20) | (851 << 10) | (225 << 0));
334 mixer_reg_write(res, MXR_CM_COEFF_CR,
335 (225 << 20) | (820 << 10) | (1004 << 0));
338 mixer_reg_writemask(res, MXR_CFG, val, MXR_CFG_RGB_FMT_MASK);
341 static void mixer_cfg_layer(struct mixer_context *ctx, int win, bool enable)
343 struct mixer_resources *res = &ctx->mixer_res;
344 u32 val = enable ? ~0 : 0;
348 mixer_reg_writemask(res, MXR_CFG, val, MXR_CFG_GRP0_ENABLE);
351 mixer_reg_writemask(res, MXR_CFG, val, MXR_CFG_GRP1_ENABLE);
354 vp_reg_writemask(res, VP_ENABLE, val, VP_ENABLE_ON);
355 mixer_reg_writemask(res, MXR_CFG, val, MXR_CFG_VP_ENABLE);
360 static void mixer_run(struct mixer_context *ctx)
362 struct mixer_resources *res = &ctx->mixer_res;
364 mixer_reg_writemask(res, MXR_STATUS, ~0, MXR_STATUS_REG_RUN);
366 mixer_regs_dump(ctx);
369 static int mixer_wait_for_vsync(struct mixer_context *ctx)
373 ctx->event_flags |= MXR_EVENT_VSYNC;
375 ret = wait_event_timeout(ctx->mixer_res.event_queue,
376 ((ctx->event_flags & MXR_EVENT_VSYNC) == 0), msecs_to_jiffies(1000));
383 static int mixer_get_layer_update_count(struct mixer_context *ctx)
385 struct mixer_resources *res = &ctx->mixer_res;
388 if (!res->is_soc_exynos5)
391 val = mixer_reg_read(res, MXR_CFG);
393 return (val & MXR_CFG_LAYER_UPDATE_COUNT_MASK) >>
394 MXR_CFG_LAYER_UPDATE_COUNT0;
397 static void mixer_layer_update(struct mixer_context *ctx)
399 struct mixer_resources *res = &ctx->mixer_res;
401 if (!res->is_soc_exynos5)
404 mixer_reg_writemask(res, MXR_CFG, ~0, MXR_CFG_LAYER_UPDATE);
407 static void vp_video_buffer(struct mixer_context *ctx, int win)
409 struct mixer_resources *res = &ctx->mixer_res;
411 struct hdmi_win_data *win_data;
412 unsigned int full_width, full_height, width, height;
413 unsigned int x_ratio, y_ratio;
414 unsigned int src_x_offset, src_y_offset, dst_x_offset, dst_y_offset;
415 unsigned int mode_width, mode_height;
416 unsigned int buf_num;
417 dma_addr_t luma_addr[2], chroma_addr[2];
418 bool tiled_mode = false;
419 bool crcb_mode = false;
422 win_data = &ctx->win_data[win];
424 switch (win_data->pixel_format) {
425 case DRM_FORMAT_NV12MT:
427 case DRM_FORMAT_NV12M:
431 /* TODO: single buffer format NV12, NV21 */
433 /* ignore pixel format at disable time */
434 if (!win_data->dma_addr)
437 DRM_ERROR("pixel format for vp is wrong [%d].\n",
438 win_data->pixel_format);
442 full_width = win_data->fb_width;
443 full_height = win_data->fb_height;
444 width = win_data->crtc_width;
445 height = win_data->crtc_height;
446 mode_width = win_data->mode_width;
447 mode_height = win_data->mode_height;
449 /* scaling feature: (src << 16) / dst */
450 x_ratio = (width << 16) / width;
451 y_ratio = (height << 16) / height;
453 src_x_offset = win_data->fb_x;
454 src_y_offset = win_data->fb_y;
455 dst_x_offset = win_data->crtc_x;
456 dst_y_offset = win_data->crtc_y;
459 luma_addr[0] = win_data->dma_addr;
460 chroma_addr[0] = win_data->chroma_dma_addr;
462 luma_addr[0] = win_data->dma_addr;
463 chroma_addr[0] = win_data->dma_addr
464 + (full_width * full_height);
467 if (win_data->scan_flags & DRM_MODE_FLAG_INTERLACE) {
468 ctx->interlace = true;
470 luma_addr[1] = luma_addr[0] + 0x40;
471 chroma_addr[1] = chroma_addr[0] + 0x40;
473 luma_addr[1] = luma_addr[0] + full_width;
474 chroma_addr[1] = chroma_addr[0] + full_width;
477 ctx->interlace = false;
482 spin_lock_irqsave(&res->reg_slock, flags);
483 mixer_vsync_set_update(ctx, false);
485 /* interlace or progressive scan mode */
486 val = (ctx->interlace ? ~0 : 0);
487 vp_reg_writemask(res, VP_MODE, val, VP_MODE_LINE_SKIP);
490 val = (crcb_mode ? VP_MODE_NV21 : VP_MODE_NV12);
491 val |= (tiled_mode ? VP_MODE_MEM_TILED : VP_MODE_MEM_LINEAR);
492 vp_reg_writemask(res, VP_MODE, val, VP_MODE_FMT_MASK);
494 /* setting size of input image */
495 vp_reg_write(res, VP_IMG_SIZE_Y, VP_IMG_HSIZE(full_width) |
496 VP_IMG_VSIZE(full_height));
497 /* chroma height has to reduced by 2 to avoid chroma distorions */
498 vp_reg_write(res, VP_IMG_SIZE_C, VP_IMG_HSIZE(full_width) |
499 VP_IMG_VSIZE(full_height / 2));
501 vp_reg_write(res, VP_SRC_WIDTH, width);
502 vp_reg_write(res, VP_SRC_HEIGHT, height);
503 vp_reg_write(res, VP_SRC_H_POSITION,
504 VP_SRC_H_POSITION_VAL(src_x_offset));
505 vp_reg_write(res, VP_SRC_V_POSITION, src_y_offset);
507 vp_reg_write(res, VP_DST_WIDTH, width);
508 vp_reg_write(res, VP_DST_H_POSITION, dst_x_offset);
509 if (ctx->interlace) {
510 vp_reg_write(res, VP_DST_HEIGHT, height / 2);
511 vp_reg_write(res, VP_DST_V_POSITION, dst_y_offset / 2);
513 vp_reg_write(res, VP_DST_HEIGHT, height);
514 vp_reg_write(res, VP_DST_V_POSITION, dst_y_offset);
517 vp_reg_write(res, VP_H_RATIO, x_ratio);
518 vp_reg_write(res, VP_V_RATIO, y_ratio);
520 vp_reg_write(res, VP_ENDIAN_MODE, VP_ENDIAN_MODE_LITTLE);
522 /* set buffer address to vp */
523 vp_reg_write(res, VP_TOP_Y_PTR, luma_addr[0]);
524 vp_reg_write(res, VP_BOT_Y_PTR, luma_addr[1]);
525 vp_reg_write(res, VP_TOP_C_PTR, chroma_addr[0]);
526 vp_reg_write(res, VP_BOT_C_PTR, chroma_addr[1]);
528 mixer_cfg_scan(ctx, mode_height);
529 mixer_cfg_rgb_fmt(ctx, mode_height);
530 mixer_cfg_layer(ctx, win, true);
533 mixer_vsync_set_update(ctx, true);
534 spin_unlock_irqrestore(&res->reg_slock, flags);
539 static void mixer_graph_buffer(struct mixer_context *ctx, int win)
541 struct mixer_resources *res = &ctx->mixer_res;
543 struct hdmi_win_data *win_data;
544 unsigned int full_width, width, height;
545 unsigned int x_ratio, y_ratio;
546 unsigned int src_x_offset, src_y_offset, dst_x_offset, dst_y_offset;
547 unsigned int mode_width, mode_height;
552 win_data = &ctx->win_data[win];
559 switch (win_data->bpp) {
570 dma_addr = win_data->dma_addr;
571 full_width = win_data->fb_width;
572 width = win_data->crtc_width;
573 height = win_data->crtc_height;
574 mode_width = win_data->mode_width;
575 mode_height = win_data->mode_height;
577 /* 2x scaling feature */
581 src_x_offset = win_data->fb_x;
582 src_y_offset = win_data->fb_y;
583 dst_x_offset = win_data->crtc_x;
584 dst_y_offset = win_data->crtc_y;
586 /* converting dma address base and source offset */
588 + (src_x_offset * win_data->bpp >> 3)
589 + (src_y_offset * full_width * win_data->bpp >> 3);
593 if (win_data->scan_flags & DRM_MODE_FLAG_INTERLACE)
594 ctx->interlace = true;
596 ctx->interlace = false;
598 spin_lock_irqsave(&res->reg_slock, flags);
599 mixer_vsync_set_update(ctx, false);
602 mixer_reg_writemask(res, MXR_GRAPHIC_CFG(win),
603 MXR_GRP_CFG_FORMAT_VAL(fmt), MXR_GRP_CFG_FORMAT_MASK);
606 mixer_reg_write(res, MXR_GRAPHIC_SPAN(win), full_width);
608 val = MXR_GRP_WH_WIDTH(width);
609 val |= MXR_GRP_WH_HEIGHT(height);
610 val |= MXR_GRP_WH_H_SCALE(x_ratio);
611 val |= MXR_GRP_WH_V_SCALE(y_ratio);
612 mixer_reg_write(res, MXR_GRAPHIC_WH(win), val);
614 /* setup offsets in source image */
615 val = MXR_GRP_SXY_SX(src_x_offset);
616 val |= MXR_GRP_SXY_SY(src_y_offset);
617 mixer_reg_write(res, MXR_GRAPHIC_SXY(win), val);
619 /* setup offsets in display image */
620 val = MXR_GRP_DXY_DX(dst_x_offset);
621 val |= MXR_GRP_DXY_DY(dst_y_offset);
622 mixer_reg_write(res, MXR_GRAPHIC_DXY(win), val);
624 /* set buffer address to mixer */
625 mixer_reg_write(res, MXR_GRAPHIC_BASE(win), dma_addr);
627 mixer_cfg_scan(ctx, mode_height);
628 mixer_cfg_rgb_fmt(ctx, mode_height);
629 mixer_cfg_layer(ctx, win, true);
630 mixer_cfg_layer(ctx, MIXER_DEFAULT_WIN, true);
632 /* Only allow one update per vsync */
633 if (!win_data->updated)
634 mixer_layer_update(ctx);
636 win_data->updated = true;
640 mixer_vsync_set_update(ctx, true);
641 spin_unlock_irqrestore(&res->reg_slock, flags);
644 static void vp_win_reset(struct mixer_context *ctx)
646 struct mixer_resources *res = &ctx->mixer_res;
649 vp_reg_write(res, VP_SRESET, VP_SRESET_PROCESSING);
650 for (tries = 100; tries; --tries) {
651 /* waiting until VP_SRESET_PROCESSING is 0 */
652 if (~vp_reg_read(res, VP_SRESET) & VP_SRESET_PROCESSING)
656 WARN(tries == 0, "failed to reset Video Processor\n");
659 static int mixer_enable_vblank(void *ctx, int pipe)
661 struct mixer_context *mixer_ctx = ctx;
662 struct mixer_resources *res = &mixer_ctx->mixer_res;
664 DRM_DEBUG_KMS("[%d] %s\n", __LINE__, __func__);
666 mixer_ctx->pipe = pipe;
668 /* enable vsync interrupt */
669 mixer_reg_writemask(res, MXR_INT_EN, MXR_INT_EN_VSYNC,
675 static void mixer_disable_vblank(void *ctx)
677 struct mixer_context *mixer_ctx = ctx;
678 struct mixer_resources *res = &mixer_ctx->mixer_res;
680 DRM_DEBUG_KMS("[%d] %s\n", __LINE__, __func__);
682 /* disable vsync interrupt */
683 mixer_reg_writemask(res, MXR_INT_EN, 0, MXR_INT_EN_VSYNC);
686 static void mixer_win_mode_set(void *ctx,
687 struct exynos_drm_overlay *overlay)
689 struct mixer_context *mixer_ctx = ctx;
690 struct hdmi_win_data *win_data;
693 DRM_DEBUG_KMS("[%d] %s\n", __LINE__, __func__);
696 DRM_ERROR("overlay is NULL\n");
700 DRM_DEBUG_KMS("set [%d]x[%d] at (%d,%d) to [%d]x[%d] at (%d,%d)\n",
701 overlay->fb_width, overlay->fb_height,
702 overlay->fb_x, overlay->fb_y,
703 overlay->crtc_width, overlay->crtc_height,
704 overlay->crtc_x, overlay->crtc_y);
707 if (win == DEFAULT_ZPOS)
708 win = MIXER_DEFAULT_WIN;
710 if (win < 0 || win > MIXER_WIN_NR) {
711 DRM_ERROR("overlay plane[%d] is wrong\n", win);
715 win_data = &mixer_ctx->win_data[win];
717 win_data->dma_addr = overlay->dma_addr[0];
718 win_data->vaddr = overlay->vaddr[0];
719 win_data->chroma_dma_addr = overlay->dma_addr[1];
720 win_data->chroma_vaddr = overlay->vaddr[1];
721 win_data->pixel_format = overlay->pixel_format;
722 win_data->bpp = overlay->bpp;
724 win_data->crtc_x = overlay->crtc_x;
725 win_data->crtc_y = overlay->crtc_y;
726 win_data->crtc_width = overlay->crtc_width;
727 win_data->crtc_height = overlay->crtc_height;
729 win_data->fb_x = overlay->fb_x;
730 win_data->fb_y = overlay->fb_y;
731 win_data->fb_width = overlay->fb_pitch / (overlay->bpp >> 3);
732 win_data->fb_height = overlay->fb_height;
734 win_data->mode_width = overlay->mode_width;
735 win_data->mode_height = overlay->mode_height;
737 win_data->scan_flags = overlay->scan_flag;
740 static void mixer_win_commit(void *ctx, int zpos)
742 struct mixer_context *mixer_ctx = ctx;
743 struct mixer_resources *res = &mixer_ctx->mixer_res;
746 DRM_DEBUG_KMS("[%d] %s, win: %d\n", __LINE__, __func__, win);
748 if (win == DEFAULT_ZPOS)
749 win = MIXER_DEFAULT_WIN;
751 if (win < 0 || win > MIXER_WIN_NR) {
752 DRM_ERROR("overlay plane[%d] is wrong\n", win);
756 if (!(res->is_soc_exynos5)) {
758 vp_video_buffer(mixer_ctx, win);
760 mixer_graph_buffer(mixer_ctx, win);
763 mixer_graph_buffer(mixer_ctx, win);
766 static void mixer_win_disable(void *ctx, int zpos)
768 struct mixer_context *mixer_ctx = ctx;
769 struct mixer_resources *res = &mixer_ctx->mixer_res;
773 DRM_DEBUG_KMS("[%d] %s, win: %d\n", __LINE__, __func__, win);
775 if (win == DEFAULT_ZPOS)
776 win = MIXER_DEFAULT_WIN;
778 if (win < 0 || win > MIXER_WIN_NR) {
779 DRM_ERROR("overlay plane[%d] is wrong\n", win);
783 mixer_wait_for_vsync(mixer_ctx);
785 spin_lock_irqsave(&res->reg_slock, flags);
786 mixer_vsync_set_update(mixer_ctx, false);
788 mixer_cfg_layer(mixer_ctx, win, false);
790 mixer_vsync_set_update(mixer_ctx, true);
792 spin_unlock_irqrestore(&res->reg_slock, flags);
794 if (win == MIXER_DEFAULT_WIN) {
795 mixer_win_reset(ctx);
796 mixer_enable_vblank(ctx, mixer_ctx->pipe);
800 static struct exynos_mixer_ops mixer_ops = {
802 .enable_vblank = mixer_enable_vblank,
803 .disable_vblank = mixer_disable_vblank,
806 .win_mode_set = mixer_win_mode_set,
807 .win_commit = mixer_win_commit,
808 .win_disable = mixer_win_disable,
811 /* for pageflip event */
812 static irqreturn_t mixer_irq_handler(int irq, void *arg)
814 struct exynos_drm_hdmi_context *drm_hdmi_ctx = arg;
815 struct mixer_context *ctx = drm_hdmi_ctx->ctx;
816 struct mixer_resources *res = &ctx->mixer_res;
817 u32 val, base, shadow;
820 spin_lock(&res->reg_slock);
822 /* read interrupt status for handling and clearing flags for VSYNC */
823 val = mixer_reg_read(res, MXR_INT_STATUS);
826 if (val & MXR_INT_STATUS_VSYNC) {
828 if (ctx->event_flags & MXR_EVENT_VSYNC) {
829 DRM_DEBUG_KMS("ctx->event_flags & MXR_EVENT_VSYNC");
832 mixer_reg_write(res, MXR_GRAPHIC_WH(1), 0);
833 mixer_reg_write(res, MXR_GRAPHIC_SPAN(1), 0);
834 mixer_reg_write(res, MXR_GRAPHIC_SXY(1), 0);
835 mixer_reg_write(res, MXR_GRAPHIC_DXY(1), 0);
837 ctx->event_flags &= ~MXR_EVENT_VSYNC;
838 wake_up(&ctx->mixer_res.event_queue);
842 /* interlace scan need to check shadow register */
843 if (ctx->interlace) {
844 base = mixer_reg_read(res, MXR_GRAPHIC_BASE(0));
845 shadow = mixer_reg_read(res, MXR_GRAPHIC_BASE_S(0));
849 base = mixer_reg_read(res, MXR_GRAPHIC_BASE(1));
850 shadow = mixer_reg_read(res, MXR_GRAPHIC_BASE_S(1));
855 drm_handle_vblank(drm_hdmi_ctx->drm_dev, ctx->pipe);
857 /* Bail out if a layer update is pending */
858 if (mixer_get_layer_update_count(ctx))
861 for (i = 0; i < MIXER_WIN_NR; i++)
862 ctx->win_data[i].updated = false;
864 exynos_drm_crtc_finish_pageflip(drm_hdmi_ctx->drm_dev,
869 /* clear interrupts */
870 if (~val & MXR_INT_EN_VSYNC) {
871 /* vsync interrupt use different bit for read and clear */
872 val &= ~MXR_INT_EN_VSYNC;
873 val |= MXR_INT_CLEAR_VSYNC;
875 mixer_reg_write(res, MXR_INT_STATUS, val);
877 spin_unlock(&res->reg_slock);
882 static void mixer_win_reset(struct mixer_context *ctx)
884 struct mixer_resources *res = &ctx->mixer_res;
886 u32 val; /* value stored to register */
888 spin_lock_irqsave(&res->reg_slock, flags);
889 mixer_reg_writemask(res, MXR_STATUS, ~0, MXR_STATUS_SOFT_RESET);
890 mixer_vsync_set_update(ctx, false);
892 mixer_reg_writemask(res, MXR_CFG, MXR_CFG_DST_HDMI, MXR_CFG_DST_MASK);
894 /* set output in RGB888 mode */
895 mixer_reg_writemask(res, MXR_CFG, MXR_CFG_OUT_RGB888, MXR_CFG_OUT_MASK);
897 /* 16 beat burst in DMA */
898 mixer_reg_writemask(res, MXR_STATUS, MXR_STATUS_16_BURST,
899 MXR_STATUS_BURST_MASK);
901 /* setting default layer priority: layer1 > layer0 > video
902 * because typical usage scenario would be
904 * layer0 - framebuffer
905 * video - video overlay
907 val = MXR_LAYER_CFG_GRP1_VAL(3);
908 val |= MXR_LAYER_CFG_GRP0_VAL(2);
909 val |= MXR_LAYER_CFG_VP_VAL(1);
910 mixer_reg_write(res, MXR_LAYER_CFG, val);
912 /* setting background color */
913 mixer_reg_write(res, MXR_BG_COLOR0, 0x008080);
914 mixer_reg_write(res, MXR_BG_COLOR1, 0x008080);
915 mixer_reg_write(res, MXR_BG_COLOR2, 0x008080);
917 /* setting graphical layers */
919 val = MXR_GRP_CFG_COLOR_KEY_DISABLE; /* no blank key */
920 val |= MXR_GRP_CFG_WIN_BLEND_EN;
921 val |= MXR_GRP_CFG_ALPHA_VAL(0xff); /* non-transparent alpha */
923 /* the same configuration for both layers */
924 mixer_reg_write(res, MXR_GRAPHIC_CFG(0), val);
926 val |= MXR_GRP_CFG_BLEND_PRE_MUL;
927 val |= MXR_GRP_CFG_PIXEL_BLEND_EN;
928 mixer_reg_write(res, MXR_GRAPHIC_CFG(1), val);
930 if (!(res->is_soc_exynos5)) {
931 /* configuration of Video Processor for Exynos4 soc */
933 vp_default_filter(res);
936 /* disable all layers */
937 mixer_reg_writemask(res, MXR_CFG, 0, MXR_CFG_GRP0_ENABLE);
938 mixer_reg_writemask(res, MXR_CFG, 0, MXR_CFG_GRP1_ENABLE);
939 mixer_reg_writemask(res, MXR_CFG, 0, MXR_CFG_VP_ENABLE);
941 mixer_reg_writemask(res, MXR_INT_EN, ~0, MXR_INT_EN_ALL);
943 mixer_vsync_set_update(ctx, true);
944 spin_unlock_irqrestore(&res->reg_slock, flags);
947 static void mixer_resource_poweron(struct mixer_context *ctx)
949 struct mixer_resources *res = &ctx->mixer_res;
951 DRM_DEBUG_KMS("[%d] %s\n", __LINE__, __func__);
953 clk_enable(res->mixer);
954 if (!(res->is_soc_exynos5)) {
956 clk_enable(res->sclk_mixer);
959 mixer_win_reset(ctx);
962 static void mixer_resource_poweroff(struct mixer_context *ctx)
964 struct mixer_resources *res = &ctx->mixer_res;
966 DRM_DEBUG_KMS("[%d] %s\n", __LINE__, __func__);
968 clk_disable(res->mixer);
969 if (!(res->is_soc_exynos5)) {
970 clk_disable(res->vp);
971 clk_disable(res->sclk_mixer);
975 static int mixer_runtime_resume(struct device *dev)
977 struct exynos_drm_hdmi_context *ctx = get_mixer_context(dev);
979 DRM_DEBUG_KMS("resume - start\n");
981 mixer_resource_poweron(ctx->ctx);
986 static int mixer_runtime_suspend(struct device *dev)
988 struct exynos_drm_hdmi_context *ctx = get_mixer_context(dev);
990 DRM_DEBUG_KMS("suspend - start\n");
992 mixer_resource_poweroff(ctx->ctx);
997 static const struct dev_pm_ops mixer_pm_ops = {
998 .runtime_suspend = mixer_runtime_suspend,
999 .runtime_resume = mixer_runtime_resume,
1002 #ifdef CONFIG_EXYNOS_IOMMU
1003 static int iommu_init(struct platform_device *pdev)
1005 struct platform_device *pds;
1007 pds = find_sysmmu_dt(pdev, "sysmmu");
1009 printk(KERN_ERR "No sysmmu found :\n");
1013 platform_set_sysmmu(&pds->dev, &pdev->dev);
1015 * The ordering in Makefile warrants that this is initialized after
1016 * FIMD, so only just ensure that it works as expected and we are
1017 * reusing the mapping originally created in exynos_drm_fimd.c.
1019 WARN_ON(!exynos_drm_common_mapping);
1020 exynos_drm_common_mapping = s5p_create_iommu_mapping(&pdev->dev,
1021 0, 0, 0, exynos_drm_common_mapping);
1022 if(exynos_drm_common_mapping == NULL) {
1023 printk(KERN_ERR"Failed to create iommu mapping for Mixer\n");
1031 static int __devinit mixer_resources_init_exynos(
1032 struct exynos_drm_hdmi_context *ctx,
1033 struct platform_device *pdev,
1036 struct mixer_context *mixer_ctx = ctx->ctx;
1037 struct device *dev = &pdev->dev;
1038 struct mixer_resources *mixer_res = &mixer_ctx->mixer_res;
1039 struct resource *res;
1042 DRM_DEBUG_KMS("Mixer resources init\n");
1044 mixer_res->is_soc_exynos5 = is_exynos5;
1045 mixer_res->dev = dev;
1046 spin_lock_init(&mixer_res->reg_slock);
1049 init_waitqueue_head(&mixer_res->event_queue);
1051 mixer_res->mixer = clk_get(dev, "mixer");
1052 if (IS_ERR_OR_NULL(mixer_res->mixer)) {
1053 dev_err(dev, "failed to get clock 'mixer'\n");
1058 mixer_res->vp = clk_get(dev, "vp");
1059 if (IS_ERR_OR_NULL(mixer_res->vp)) {
1060 dev_err(dev, "failed to get clock 'vp'\n");
1064 mixer_res->sclk_mixer = clk_get(dev, "sclk_mixer");
1065 if (IS_ERR_OR_NULL(mixer_res->sclk_mixer)) {
1066 dev_err(dev, "failed to get clock 'sclk_mixer'\n");
1071 mixer_res->sclk_hdmi = clk_get(dev, "sclk_hdmi");
1072 if (IS_ERR_OR_NULL(mixer_res->sclk_hdmi)) {
1073 dev_err(dev, "failed to get clock 'sclk_hdmi'\n");
1078 mixer_res->sclk_dac = clk_get(dev, "sclk_dac");
1079 if (IS_ERR_OR_NULL(mixer_res->sclk_dac)) {
1080 dev_err(dev, "failed to get clock 'sclk_dac'\n");
1084 res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "mxr");
1087 res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
1090 dev_err(dev, "get memory resource failed.\n");
1096 clk_set_parent(mixer_res->sclk_mixer, mixer_res->sclk_hdmi);
1098 mixer_res->mixer_regs = ioremap(res->start, resource_size(res));
1099 if (mixer_res->mixer_regs == NULL) {
1100 dev_err(dev, "register mapping failed.\n");
1106 res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "vp");
1108 dev_err(dev, "get memory resource failed.\n");
1113 mixer_res->vp_regs = ioremap(res->start, resource_size(res));
1114 if (mixer_res->vp_regs == NULL) {
1115 dev_err(dev, "register mapping failed.\n");
1120 res = platform_get_resource_byname(pdev, IORESOURCE_IRQ, "irq");
1122 dev_err(dev, "get interrupt resource failed.\n");
1127 res = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
1129 dev_err(dev, "get interrupt resource failed.\n");
1131 goto fail_mixer_regs;
1135 ret = request_irq(res->start, mixer_irq_handler, 0, "drm_mixer", ctx);
1137 dev_err(dev, "request interrupt failed.\n");
1138 goto fail_mixer_regs;
1140 mixer_res->irq = res->start;
1142 #ifdef CONFIG_EXYNOS_IOMMU
1143 ret = iommu_init(pdev);
1145 dev_err(dev, "iommu init failed.\n");
1146 goto fail_mixer_regs;
1152 iounmap(mixer_res->vp_regs);
1155 iounmap(mixer_res->mixer_regs);
1158 if (!IS_ERR_OR_NULL(mixer_res->sclk_dac))
1159 clk_put(mixer_res->sclk_dac);
1160 if (!IS_ERR_OR_NULL(mixer_res->sclk_hdmi))
1161 clk_put(mixer_res->sclk_hdmi);
1162 if (!IS_ERR_OR_NULL(mixer_res->sclk_mixer))
1163 clk_put(mixer_res->sclk_mixer);
1164 if (!IS_ERR_OR_NULL(mixer_res->vp))
1165 clk_put(mixer_res->vp);
1166 if (!IS_ERR_OR_NULL(mixer_res->mixer))
1167 clk_put(mixer_res->mixer);
1168 mixer_res->dev = NULL;
1172 static void mixer_resources_cleanup(struct mixer_context *ctx)
1174 struct mixer_resources *res = &ctx->mixer_res;
1176 disable_irq(res->irq);
1177 free_irq(res->irq, ctx);
1179 iounmap(res->vp_regs);
1180 iounmap(res->mixer_regs);
1183 static int __devinit mixer_probe(struct platform_device *pdev)
1185 struct device *dev = &pdev->dev;
1186 struct exynos_drm_hdmi_context *drm_hdmi_ctx;
1187 struct exynos_drm_hdmi_pdata *pdata;
1188 struct mixer_context *ctx;
1191 dev_info(dev, "probe start\n");
1193 drm_hdmi_ctx = kzalloc(sizeof(*drm_hdmi_ctx), GFP_KERNEL);
1194 if (!drm_hdmi_ctx) {
1195 DRM_ERROR("failed to allocate common hdmi context.\n");
1199 ctx = kzalloc(sizeof(*ctx), GFP_KERNEL);
1201 DRM_ERROR("failed to alloc mixer context.\n");
1202 kfree(drm_hdmi_ctx);
1206 drm_hdmi_ctx->ctx = (void *)ctx;
1208 platform_set_drvdata(pdev, drm_hdmi_ctx);
1210 /* Get from Platform soc deatils */
1211 pdata = pdev->dev.platform_data;
1213 /* acquire resources: regs, irqs, clocks */
1214 ret = mixer_resources_init_exynos(drm_hdmi_ctx, pdev,pdata->is_soc_exynos5);
1218 /* attach mixer driver to common hdmi. */
1219 exynos_mixer_drv_attach(drm_hdmi_ctx);
1221 /* register specific callback point to common hdmi. */
1222 exynos_mixer_ops_register(&mixer_ops);
1224 mixer_resource_poweron(ctx);
1230 dev_info(dev, "probe failed\n");
1234 static int mixer_remove(struct platform_device *pdev)
1236 struct device *dev = &pdev->dev;
1237 struct exynos_drm_hdmi_context *drm_hdmi_ctx =
1238 platform_get_drvdata(pdev);
1239 struct mixer_context *ctx = drm_hdmi_ctx->ctx;
1241 dev_info(dev, "remove successful\n");
1243 mixer_resource_poweroff(ctx);
1244 mixer_resources_cleanup(ctx);
1249 struct platform_driver mixer_driver = {
1251 .name = "s5p-mixer",
1252 .owner = THIS_MODULE,
1253 .pm = &mixer_pm_ops,
1255 .probe = mixer_probe,
1256 .remove = __devexit_p(mixer_remove),