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, unsigned int height)
278 struct mixer_resources *res = &mctx->mixer_res;
281 /* choosing between interlace and progressive mode */
282 val = (mctx->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 *mctx, unsigned int height)
302 struct mixer_resources *res = &mctx->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 *mctx, int win, bool enable)
343 struct mixer_resources *res = &mctx->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 *mctx)
362 struct mixer_resources *res = &mctx->mixer_res;
364 mixer_reg_writemask(res, MXR_STATUS, ~0, MXR_STATUS_REG_RUN);
366 mixer_regs_dump(mctx);
369 static int mixer_wait_for_vsync(struct mixer_context *mctx)
373 mctx->event_flags |= MXR_EVENT_VSYNC;
375 ret = wait_event_timeout(mctx->mixer_res.event_queue,
376 ((mctx->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 *mctx, int win)
409 struct mixer_resources *res = &mctx->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 = &mctx->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 mctx->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 mctx->interlace = false;
482 spin_lock_irqsave(&res->reg_slock, flags);
483 mixer_vsync_set_update(mctx, false);
485 /* interlace or progressive scan mode */
486 val = (mctx->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 (mctx->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(mctx, mode_height);
529 mixer_cfg_rgb_fmt(mctx, mode_height);
530 mixer_cfg_layer(mctx, win, true);
533 mixer_vsync_set_update(mctx, true);
534 spin_unlock_irqrestore(&res->reg_slock, flags);
539 static void mixer_graph_buffer(struct mixer_context *mctx, int win)
541 struct mixer_resources *res = &mctx->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 = &mctx->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 mctx->interlace = true;
596 mctx->interlace = false;
598 spin_lock_irqsave(&res->reg_slock, flags);
599 mixer_vsync_set_update(mctx, 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(mctx, mode_height);
628 mixer_cfg_rgb_fmt(mctx, mode_height);
629 mixer_cfg_layer(mctx, win, true);
630 mixer_cfg_layer(mctx, MIXER_DEFAULT_WIN, true);
632 /* Only allow one update per vsync */
633 if (!win_data->updated)
634 mixer_layer_update(mctx);
636 win_data->updated = true;
639 mixer_vsync_set_update(mctx, true);
640 spin_unlock_irqrestore(&res->reg_slock, flags);
643 static void vp_win_reset(struct mixer_context *mctx)
645 struct mixer_resources *res = &mctx->mixer_res;
648 vp_reg_write(res, VP_SRESET, VP_SRESET_PROCESSING);
649 for (tries = 100; tries; --tries) {
650 /* waiting until VP_SRESET_PROCESSING is 0 */
651 if (~vp_reg_read(res, VP_SRESET) & VP_SRESET_PROCESSING)
655 WARN(tries == 0, "failed to reset Video Processor\n");
658 static int mixer_enable_vblank(void *ctx, int pipe)
660 struct mixer_context *mctx = ctx;
661 struct mixer_resources *res = &mctx->mixer_res;
663 DRM_DEBUG_KMS("[%d] %s\n", __LINE__, __func__);
667 /* enable vsync interrupt */
668 mixer_reg_writemask(res, MXR_INT_EN, MXR_INT_EN_VSYNC,
674 static void mixer_disable_vblank(void *ctx)
676 struct mixer_context *mctx = ctx;
677 struct mixer_resources *res = &mctx->mixer_res;
679 DRM_DEBUG_KMS("[%d] %s\n", __LINE__, __func__);
681 /* disable vsync interrupt */
682 mixer_reg_writemask(res, MXR_INT_EN, 0, MXR_INT_EN_VSYNC);
685 static void mixer_win_mode_set(void *ctx,
686 struct exynos_drm_overlay *overlay)
688 struct mixer_context *mctx = ctx;
689 struct hdmi_win_data *win_data;
692 DRM_DEBUG_KMS("[%d] %s\n", __LINE__, __func__);
695 DRM_ERROR("overlay is NULL\n");
699 DRM_DEBUG_KMS("set [%d]x[%d] at (%d,%d) to [%d]x[%d] at (%d,%d)\n",
700 overlay->fb_width, overlay->fb_height,
701 overlay->fb_x, overlay->fb_y,
702 overlay->crtc_width, overlay->crtc_height,
703 overlay->crtc_x, overlay->crtc_y);
706 if (win == DEFAULT_ZPOS)
707 win = MIXER_DEFAULT_WIN;
709 if (win < 0 || win > MIXER_WIN_NR) {
710 DRM_ERROR("overlay plane[%d] is wrong\n", win);
714 win_data = &mctx->win_data[win];
716 win_data->dma_addr = overlay->dma_addr[0];
717 win_data->vaddr = overlay->vaddr[0];
718 win_data->chroma_dma_addr = overlay->dma_addr[1];
719 win_data->chroma_vaddr = overlay->vaddr[1];
720 win_data->pixel_format = overlay->pixel_format;
721 win_data->bpp = overlay->bpp;
723 win_data->crtc_x = overlay->crtc_x;
724 win_data->crtc_y = overlay->crtc_y;
725 win_data->crtc_width = overlay->crtc_width;
726 win_data->crtc_height = overlay->crtc_height;
728 win_data->fb_x = overlay->fb_x;
729 win_data->fb_y = overlay->fb_y;
730 win_data->fb_width = overlay->fb_pitch / (overlay->bpp >> 3);
731 win_data->fb_height = overlay->fb_height;
733 win_data->mode_width = overlay->mode_width;
734 win_data->mode_height = overlay->mode_height;
736 win_data->scan_flags = overlay->scan_flag;
739 static void mixer_win_commit(void *ctx, int zpos)
741 struct mixer_context *mctx = ctx;
742 struct mixer_resources *res = &mctx->mixer_res;
745 DRM_DEBUG_KMS("[%d] %s, win: %d\n", __LINE__, __func__, win);
746 if (win == DEFAULT_ZPOS)
747 win = MIXER_DEFAULT_WIN;
749 if (win < 0 || win > MIXER_WIN_NR) {
750 DRM_ERROR("overlay plane[%d] is wrong\n", win);
754 if (!mctx->is_mixer_powered_on) {
755 DRM_DEBUG_KMS("[%d] %s not powered on\n", __LINE__, __func__);
759 if (!(res->is_soc_exynos5)) {
761 vp_video_buffer(mctx, win);
763 mixer_graph_buffer(mctx, win);
766 mixer_graph_buffer(mctx, win);
769 static void mixer_win_disable(void *ctx, int zpos)
771 struct mixer_context *mctx = ctx;
772 struct mixer_resources *res = &mctx->mixer_res;
776 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 mixer_wait_for_vsync(mctx);
788 spin_lock_irqsave(&res->reg_slock, flags);
789 mixer_vsync_set_update(mctx, false);
791 mixer_cfg_layer(mctx, win, false);
793 mixer_vsync_set_update(mctx, true);
795 spin_unlock_irqrestore(&res->reg_slock, flags);
797 if (win == MIXER_DEFAULT_WIN) {
798 mixer_win_reset(mctx);
799 mixer_enable_vblank(mctx, mctx->pipe);
803 /* for pageflip event */
804 static irqreturn_t mixer_irq_handler(int irq, void *arg)
806 struct exynos_drm_hdmi_context *drm_hdmi_ctx = arg;
807 struct mixer_context *mctx = drm_hdmi_ctx->ctx;
808 struct mixer_resources *res = &mctx->mixer_res;
809 u32 val, base, shadow;
812 spin_lock(&res->reg_slock);
814 /* read interrupt status for handling and clearing flags for VSYNC */
815 val = mixer_reg_read(res, MXR_INT_STATUS);
818 if (val & MXR_INT_STATUS_VSYNC) {
820 if (mctx->event_flags & MXR_EVENT_VSYNC) {
821 DRM_DEBUG_KMS("mctx->event_flags & MXR_EVENT_VSYNC");
824 mixer_reg_write(res, MXR_GRAPHIC_WH(1), 0);
825 mixer_reg_write(res, MXR_GRAPHIC_SPAN(1), 0);
826 mixer_reg_write(res, MXR_GRAPHIC_SXY(1), 0);
827 mixer_reg_write(res, MXR_GRAPHIC_DXY(1), 0);
829 mctx->event_flags &= ~MXR_EVENT_VSYNC;
830 wake_up(&mctx->mixer_res.event_queue);
834 /* interlace scan need to check shadow register */
835 if (mctx->interlace) {
836 base = mixer_reg_read(res, MXR_GRAPHIC_BASE(0));
837 shadow = mixer_reg_read(res, MXR_GRAPHIC_BASE_S(0));
841 base = mixer_reg_read(res, MXR_GRAPHIC_BASE(1));
842 shadow = mixer_reg_read(res, MXR_GRAPHIC_BASE_S(1));
847 drm_handle_vblank(drm_hdmi_ctx->drm_dev, mctx->pipe);
849 /* Bail out if a layer update is pending */
850 if (mixer_get_layer_update_count(mctx))
853 for (i = 0; i < MIXER_WIN_NR; i++)
854 mctx->win_data[i].updated = false;
855 exynos_drm_crtc_finish_pageflip(drm_hdmi_ctx->drm_dev,
860 /* clear interrupts */
861 if (~val & MXR_INT_EN_VSYNC) {
862 /* vsync interrupt use different bit for read and clear */
863 val &= ~MXR_INT_EN_VSYNC;
864 val |= MXR_INT_CLEAR_VSYNC;
866 mixer_reg_write(res, MXR_INT_STATUS, val);
868 spin_unlock(&res->reg_slock);
873 static void mixer_win_reset(struct mixer_context *mctx)
875 struct mixer_resources *res = &mctx->mixer_res;
877 u32 val; /* value stored to register */
879 spin_lock_irqsave(&res->reg_slock, flags);
880 mixer_reg_writemask(res, MXR_STATUS, ~0, MXR_STATUS_SOFT_RESET);
881 mixer_vsync_set_update(mctx, false);
883 mixer_reg_writemask(res, MXR_CFG, MXR_CFG_DST_HDMI, MXR_CFG_DST_MASK);
885 /* set output in RGB888 mode */
886 mixer_reg_writemask(res, MXR_CFG, MXR_CFG_OUT_RGB888, MXR_CFG_OUT_MASK);
888 /* 16 beat burst in DMA */
889 mixer_reg_writemask(res, MXR_STATUS, MXR_STATUS_16_BURST,
890 MXR_STATUS_BURST_MASK);
892 /* setting default layer priority: layer1 > layer0 > video
893 * because typical usage scenario would be
895 * layer0 - framebuffer
896 * video - video overlay
898 val = MXR_LAYER_CFG_GRP1_VAL(3);
899 val |= MXR_LAYER_CFG_GRP0_VAL(2);
900 val |= MXR_LAYER_CFG_VP_VAL(1);
901 mixer_reg_write(res, MXR_LAYER_CFG, val);
903 /* setting background color */
904 mixer_reg_write(res, MXR_BG_COLOR0, 0x008080);
905 mixer_reg_write(res, MXR_BG_COLOR1, 0x008080);
906 mixer_reg_write(res, MXR_BG_COLOR2, 0x008080);
908 /* setting graphical layers */
910 val = MXR_GRP_CFG_COLOR_KEY_DISABLE; /* no blank key */
911 val |= MXR_GRP_CFG_WIN_BLEND_EN;
912 val |= MXR_GRP_CFG_ALPHA_VAL(0xff); /* non-transparent alpha */
914 /* the same configuration for both layers */
915 mixer_reg_write(res, MXR_GRAPHIC_CFG(0), val);
917 val |= MXR_GRP_CFG_BLEND_PRE_MUL;
918 val |= MXR_GRP_CFG_PIXEL_BLEND_EN;
919 mixer_reg_write(res, MXR_GRAPHIC_CFG(1), val);
921 if (!(res->is_soc_exynos5)) {
922 /* configuration of Video Processor for Exynos4 soc */
924 vp_default_filter(res);
927 /* disable all layers */
928 mixer_reg_writemask(res, MXR_CFG, 0, MXR_CFG_GRP0_ENABLE);
929 mixer_reg_writemask(res, MXR_CFG, 0, MXR_CFG_GRP1_ENABLE);
930 mixer_reg_writemask(res, MXR_CFG, 0, MXR_CFG_VP_ENABLE);
932 mixer_reg_writemask(res, MXR_INT_EN, ~0, MXR_INT_EN_ALL);
934 mixer_vsync_set_update(mctx, true);
935 spin_unlock_irqrestore(&res->reg_slock, flags);
938 static void mixer_resource_poweron(struct mixer_context *mctx)
940 struct mixer_resources *res = &mctx->mixer_res;
942 if (mctx->is_mixer_powered_on)
945 clk_enable(res->mixer);
946 if (!(res->is_soc_exynos5)) {
948 clk_enable(res->sclk_mixer);
951 mixer_win_reset(mctx);
952 mctx->is_mixer_powered_on = true;
955 static void mixer_resource_poweroff(struct mixer_context *mctx)
957 struct mixer_resources *res = &mctx->mixer_res;
959 DRM_DEBUG_KMS("[%d] %s\n", __LINE__, __func__);
960 if (!mctx->is_mixer_powered_on)
963 clk_disable(res->mixer);
964 if (!(res->is_soc_exynos5)) {
965 clk_disable(res->vp);
966 clk_disable(res->sclk_mixer);
968 mctx->is_mixer_powered_on = false;
971 #ifdef CONFIG_PM_SLEEP
972 static int mixer_resume(struct device *dev)
974 struct exynos_drm_hdmi_context *ctx = get_mixer_context(dev);
975 struct mixer_context *mctx = ctx->ctx;
977 DRM_DEBUG_KMS("[mixer] sleep resume - start\n");
979 if (!pm_runtime_suspended(dev)) {
980 DRM_DEBUG_KMS("[mixer] sleep resume - end\n");
981 mixer_resource_poweron(mctx);
982 mixer_win_commit(mctx, 0);
984 DRM_DEBUG_KMS("[mixer] sleep resume - not done\n");
988 static int mixer_suspend(struct device *dev)
990 struct exynos_drm_hdmi_context *ctx = get_mixer_context(dev);
991 struct mixer_context *mctx = ctx->ctx;
993 DRM_DEBUG_KMS("[mixer] suspend - start\n");
994 if (pm_runtime_suspended(dev)) {
995 DRM_DEBUG_KMS("[mixer] suspend - already suspended\n");
999 mixer_resource_poweroff(mctx);
1000 DRM_DEBUG_KMS("[mixer] suspend - end\n");
1004 #ifdef CONFIG_PM_RUNTIME
1005 static int mixer_runtime_resume(struct device *dev)
1007 struct exynos_drm_hdmi_context *ctx = get_mixer_context(dev);
1008 struct mixer_context *mctx = ctx->ctx;
1010 DRM_DEBUG_KMS("[mixer] runtime resume - start\n");
1012 mixer_resource_poweron(mctx);
1013 DRM_DEBUG_KMS("[mixer] runtime resume - end\n");
1018 static int mixer_runtime_suspend(struct device *dev)
1020 struct exynos_drm_hdmi_context *ctx = get_mixer_context(dev);
1021 struct mixer_context *mctx = ctx->ctx;
1023 DRM_DEBUG_KMS("[mixer] runtime suspend - start\n");
1025 mixer_resource_poweroff(mctx);
1026 DRM_DEBUG_KMS("[mixer] runtime suspend - end\n");
1032 static int mixer_power_on(void *ctx, int mode)
1034 struct mixer_context *mctx = ctx;
1036 DRM_DEBUG_KMS("[%d] %s\n", __LINE__, __func__);
1039 case DRM_MODE_DPMS_ON:
1040 if (mctx->is_mixer_powered_on) {
1041 DRM_DEBUG_KMS("[%d] %s returning\n", __LINE__, __func__);
1044 pm_runtime_get_sync(mctx->dev);
1046 case DRM_MODE_DPMS_STANDBY:
1047 case DRM_MODE_DPMS_SUSPEND:
1048 case DRM_MODE_DPMS_OFF:
1049 if (!mctx->is_mixer_powered_on) {
1050 DRM_DEBUG_KMS("[%d] %s returning\n", __LINE__, __func__);
1053 pm_runtime_put_sync(mctx->dev);
1056 DRM_DEBUG_KMS("unknown dpms mode: %d\n", mode);
1063 static struct exynos_mixer_ops mixer_ops = {
1065 .enable_vblank = mixer_enable_vblank,
1066 .disable_vblank = mixer_disable_vblank,
1067 .power_on = mixer_power_on,
1070 .win_mode_set = mixer_win_mode_set,
1071 .win_commit = mixer_win_commit,
1072 .win_disable = mixer_win_disable,
1075 static const struct dev_pm_ops mixer_pm_ops = {
1076 SET_SYSTEM_SLEEP_PM_OPS(mixer_suspend, mixer_resume)
1077 SET_RUNTIME_PM_OPS(mixer_runtime_suspend, mixer_runtime_resume, NULL)
1080 #ifdef CONFIG_EXYNOS_IOMMU
1081 static int iommu_init(struct platform_device *pdev)
1083 struct platform_device *pds;
1085 pds = find_sysmmu_dt(pdev, "sysmmu");
1087 printk(KERN_ERR "No sysmmu found :\n");
1091 platform_set_sysmmu(&pds->dev, &pdev->dev);
1093 * The ordering in Makefile warrants that this is initialized after
1094 * FIMD, so only just ensure that it works as expected and we are
1095 * reusing the mapping originally created in exynos_drm_fimd.c.
1097 WARN_ON(!exynos_drm_common_mapping);
1098 exynos_drm_common_mapping = s5p_create_iommu_mapping(&pdev->dev,
1099 0, 0, 0, exynos_drm_common_mapping);
1100 if(exynos_drm_common_mapping == NULL) {
1101 printk(KERN_ERR"Failed to create iommu mapping for Mixer\n");
1109 static int __devinit mixer_resources_init_exynos(
1110 struct exynos_drm_hdmi_context *ctx,
1111 struct platform_device *pdev,
1114 struct mixer_context *mctx = ctx->ctx;
1115 struct device *dev = &pdev->dev;
1116 struct mixer_resources *mixer_res = &mctx->mixer_res;
1117 struct resource *res;
1120 DRM_DEBUG_KMS("Mixer resources init\n");
1122 mixer_res->is_soc_exynos5 = is_exynos5;
1123 mixer_res->dev = dev;
1124 spin_lock_init(&mixer_res->reg_slock);
1127 init_waitqueue_head(&mixer_res->event_queue);
1129 mixer_res->mixer = clk_get(dev, "mixer");
1130 if (IS_ERR_OR_NULL(mixer_res->mixer)) {
1131 dev_err(dev, "failed to get clock 'mixer'\n");
1136 mixer_res->vp = clk_get(dev, "vp");
1137 if (IS_ERR_OR_NULL(mixer_res->vp)) {
1138 dev_err(dev, "failed to get clock 'vp'\n");
1142 mixer_res->sclk_mixer = clk_get(dev, "sclk_mixer");
1143 if (IS_ERR_OR_NULL(mixer_res->sclk_mixer)) {
1144 dev_err(dev, "failed to get clock 'sclk_mixer'\n");
1149 mixer_res->sclk_hdmi = clk_get(dev, "sclk_hdmi");
1150 if (IS_ERR_OR_NULL(mixer_res->sclk_hdmi)) {
1151 dev_err(dev, "failed to get clock 'sclk_hdmi'\n");
1156 mixer_res->sclk_dac = clk_get(dev, "sclk_dac");
1157 if (IS_ERR_OR_NULL(mixer_res->sclk_dac)) {
1158 dev_err(dev, "failed to get clock 'sclk_dac'\n");
1162 res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "mxr");
1165 res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
1168 dev_err(dev, "get memory resource failed.\n");
1174 clk_set_parent(mixer_res->sclk_mixer, mixer_res->sclk_hdmi);
1176 mixer_res->mixer_regs = ioremap(res->start, resource_size(res));
1177 if (mixer_res->mixer_regs == NULL) {
1178 dev_err(dev, "register mapping failed.\n");
1184 res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "vp");
1186 dev_err(dev, "get memory resource failed.\n");
1191 mixer_res->vp_regs = ioremap(res->start, resource_size(res));
1192 if (mixer_res->vp_regs == NULL) {
1193 dev_err(dev, "register mapping failed.\n");
1198 res = platform_get_resource_byname(pdev, IORESOURCE_IRQ, "irq");
1200 dev_err(dev, "get interrupt resource failed.\n");
1205 res = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
1207 dev_err(dev, "get interrupt resource failed.\n");
1209 goto fail_mixer_regs;
1213 ret = request_irq(res->start, mixer_irq_handler, 0, "drm_mixer", ctx);
1215 dev_err(dev, "request interrupt failed.\n");
1216 goto fail_mixer_regs;
1218 mixer_res->irq = res->start;
1220 #ifdef CONFIG_EXYNOS_IOMMU
1221 ret = iommu_init(pdev);
1223 dev_err(dev, "iommu init failed.\n");
1224 goto fail_mixer_regs;
1230 iounmap(mixer_res->vp_regs);
1233 iounmap(mixer_res->mixer_regs);
1236 if (!IS_ERR_OR_NULL(mixer_res->sclk_dac))
1237 clk_put(mixer_res->sclk_dac);
1238 if (!IS_ERR_OR_NULL(mixer_res->sclk_hdmi))
1239 clk_put(mixer_res->sclk_hdmi);
1240 if (!IS_ERR_OR_NULL(mixer_res->sclk_mixer))
1241 clk_put(mixer_res->sclk_mixer);
1242 if (!IS_ERR_OR_NULL(mixer_res->vp))
1243 clk_put(mixer_res->vp);
1244 if (!IS_ERR_OR_NULL(mixer_res->mixer))
1245 clk_put(mixer_res->mixer);
1246 mixer_res->dev = NULL;
1250 static void mixer_resources_cleanup(struct mixer_context *mctx)
1252 struct mixer_resources *res = &mctx->mixer_res;
1254 disable_irq(res->irq);
1255 free_irq(res->irq, mctx);
1257 iounmap(res->vp_regs);
1258 iounmap(res->mixer_regs);
1261 static int __devinit mixer_probe(struct platform_device *pdev)
1263 struct device *dev = &pdev->dev;
1264 struct exynos_drm_hdmi_context *drm_hdmi_ctx;
1265 struct exynos_drm_hdmi_pdata *pdata;
1266 struct mixer_context *mctx;
1269 dev_info(dev, "probe start\n");
1271 drm_hdmi_ctx = kzalloc(sizeof(*drm_hdmi_ctx), GFP_KERNEL);
1272 if (!drm_hdmi_ctx) {
1273 DRM_ERROR("failed to allocate common hdmi context.\n");
1277 mctx = kzalloc(sizeof(*mctx), GFP_KERNEL);
1279 DRM_ERROR("failed to alloc mixer context.\n");
1280 kfree(drm_hdmi_ctx);
1285 mctx->dev = &pdev->dev;
1286 drm_hdmi_ctx->ctx = (void *)mctx;
1288 platform_set_drvdata(pdev, drm_hdmi_ctx);
1290 /* Get from Platform soc deatils */
1291 pdata = pdev->dev.platform_data;
1293 /* acquire resources: regs, irqs, clocks */
1294 ret = mixer_resources_init_exynos(drm_hdmi_ctx, pdev,pdata->is_soc_exynos5);
1298 /* attach mixer driver to common hdmi. */
1299 exynos_mixer_drv_attach(drm_hdmi_ctx);
1301 /* register specific callback point to common hdmi. */
1302 exynos_mixer_ops_register(&mixer_ops);
1303 mctx->is_mixer_powered_on = false;
1304 pm_runtime_enable(dev);
1310 dev_info(dev, "probe failed\n");
1314 static int mixer_remove(struct platform_device *pdev)
1316 struct device *dev = &pdev->dev;
1317 struct exynos_drm_hdmi_context *drm_hdmi_ctx =
1318 platform_get_drvdata(pdev);
1319 struct mixer_context *mctx = drm_hdmi_ctx->ctx;
1321 dev_info(dev, "remove successful\n");
1323 mixer_resource_poweroff(mctx);
1324 mixer_resources_cleanup(mctx);
1329 struct platform_driver mixer_driver = {
1331 .name = "s5p-mixer",
1332 .owner = THIS_MODULE,
1333 .pm = &mixer_pm_ops,
1335 .probe = mixer_probe,
1336 .remove = __devexit_p(mixer_remove),