2 * Copyright (C) 2011 Samsung Electronics Co.Ltd
4 * Seung-Woo Kim <sw0312.kim@samsung.com>
5 * Inki Dae <inki.dae@samsung.com>
6 * Joonyoung Shim <jy0922.shim@samsung.com>
8 * Based on drivers/media/video/s5p-tv/mixer_reg.c
10 * This program is free software; you can redistribute it and/or modify it
11 * under the terms of the GNU General Public License as published by the
12 * Free Software Foundation; either version 2 of the License, or (at your
13 * option) any later version.
19 #include "regs-mixer.h"
22 #include <linux/kernel.h>
23 #include <linux/spinlock.h>
24 #include <linux/wait.h>
25 #include <linux/i2c.h>
26 #include <linux/module.h>
27 #include <linux/platform_device.h>
28 #include <linux/interrupt.h>
29 #include <linux/irq.h>
30 #include <linux/delay.h>
31 #include <linux/pm_runtime.h>
32 #include <linux/clk.h>
33 #include <linux/regulator/consumer.h>
35 #include <drm/exynos_drm.h>
37 #include "exynos_drm_drv.h"
38 #include "exynos_drm_hdmi.h"
40 #define get_mixer_context(dev) platform_get_drvdata(to_platform_device(dev))
42 struct hdmi_win_data {
45 dma_addr_t chroma_dma_addr;
46 void __iomem *chroma_vaddr;
47 uint32_t pixel_format;
51 unsigned int crtc_width;
52 unsigned int crtc_height;
55 unsigned int fb_width;
56 unsigned int fb_height;
57 unsigned int src_width;
58 unsigned int src_height;
59 unsigned int mode_width;
60 unsigned int mode_height;
61 unsigned int scan_flags;
64 struct mixer_resources {
66 void __iomem *mixer_regs;
67 void __iomem *saved_mixer_regs;
68 void __iomem *vp_regs;
69 void __iomem *saved_vp_regs;
73 struct clk *sclk_mixer;
74 struct clk *sclk_hdmi;
75 struct clk *sclk_pixel;
79 struct mixer_context {
86 struct mutex mixer_mutex;
87 struct mixer_resources mixer_res;
88 struct hdmi_win_data win_data[MIXER_WIN_NR];
91 static const u8 filter_y_horiz_tap8[] = {
92 0, -1, -1, -1, -1, -1, -1, -1,
93 -1, -1, -1, -1, -1, 0, 0, 0,
94 0, 2, 4, 5, 6, 6, 6, 6,
95 6, 5, 5, 4, 3, 2, 1, 1,
96 0, -6, -12, -16, -18, -20, -21, -20,
97 -20, -18, -16, -13, -10, -8, -5, -2,
98 127, 126, 125, 121, 114, 107, 99, 89,
99 79, 68, 57, 46, 35, 25, 16, 8,
102 static const u8 filter_y_vert_tap4[] = {
103 0, -3, -6, -8, -8, -8, -8, -7,
104 -6, -5, -4, -3, -2, -1, -1, 0,
105 127, 126, 124, 118, 111, 102, 92, 81,
106 70, 59, 48, 37, 27, 19, 11, 5,
107 0, 5, 11, 19, 27, 37, 48, 59,
108 70, 81, 92, 102, 111, 118, 124, 126,
109 0, 0, -1, -1, -2, -3, -4, -5,
110 -6, -7, -8, -8, -8, -8, -6, -3,
113 static const u8 filter_cr_horiz_tap4[] = {
114 0, -3, -6, -8, -8, -8, -8, -7,
115 -6, -5, -4, -3, -2, -1, -1, 0,
116 127, 126, 124, 118, 111, 102, 92, 81,
117 70, 59, 48, 37, 27, 19, 11, 5,
120 static inline u32 vp_reg_read(struct mixer_resources *res, u32 reg_id)
122 return readl(res->vp_regs + reg_id);
125 static inline void vp_reg_write(struct mixer_resources *res, u32 reg_id,
128 writel(val, res->vp_regs + reg_id);
131 static inline void vp_reg_writemask(struct mixer_resources *res, u32 reg_id,
134 u32 old = vp_reg_read(res, reg_id);
136 val = (val & mask) | (old & ~mask);
137 writel(val, res->vp_regs + reg_id);
140 static inline u32 mixer_reg_read(struct mixer_resources *res, u32 reg_id)
142 return readl(res->mixer_regs + reg_id);
145 static inline void mixer_reg_write(struct mixer_resources *res, u32 reg_id,
148 writel(val, res->mixer_regs + reg_id);
151 static inline void mixer_reg_writemask(struct mixer_resources *res,
152 u32 reg_id, u32 val, u32 mask)
154 u32 old = mixer_reg_read(res, reg_id);
156 val = (val & mask) | (old & ~mask);
157 writel(val, res->mixer_regs + reg_id);
160 static void mixer_regs_dump(struct mixer_context *ctx)
162 #define DUMPREG(reg_id) \
164 DRM_DEBUG_KMS(#reg_id " = %08x\n", \
165 (u32)readl(ctx->mixer_res.mixer_regs + reg_id)); \
171 DUMPREG(MXR_INT_STATUS);
173 DUMPREG(MXR_LAYER_CFG);
174 DUMPREG(MXR_VIDEO_CFG);
176 DUMPREG(MXR_GRAPHIC0_CFG);
177 DUMPREG(MXR_GRAPHIC0_BASE);
178 DUMPREG(MXR_GRAPHIC0_SPAN);
179 DUMPREG(MXR_GRAPHIC0_WH);
180 DUMPREG(MXR_GRAPHIC0_SXY);
181 DUMPREG(MXR_GRAPHIC0_DXY);
183 DUMPREG(MXR_GRAPHIC1_CFG);
184 DUMPREG(MXR_GRAPHIC1_BASE);
185 DUMPREG(MXR_GRAPHIC1_SPAN);
186 DUMPREG(MXR_GRAPHIC1_WH);
187 DUMPREG(MXR_GRAPHIC1_SXY);
188 DUMPREG(MXR_GRAPHIC1_DXY);
192 static void vp_regs_dump(struct mixer_context *ctx)
194 #define DUMPREG(reg_id) \
196 DRM_DEBUG_KMS(#reg_id " = %08x\n", \
197 (u32) readl(ctx->mixer_res.vp_regs + reg_id)); \
202 DUMPREG(VP_SHADOW_UPDATE);
203 DUMPREG(VP_FIELD_ID);
205 DUMPREG(VP_IMG_SIZE_Y);
206 DUMPREG(VP_IMG_SIZE_C);
207 DUMPREG(VP_PER_RATE_CTRL);
208 DUMPREG(VP_TOP_Y_PTR);
209 DUMPREG(VP_BOT_Y_PTR);
210 DUMPREG(VP_TOP_C_PTR);
211 DUMPREG(VP_BOT_C_PTR);
212 DUMPREG(VP_ENDIAN_MODE);
213 DUMPREG(VP_SRC_H_POSITION);
214 DUMPREG(VP_SRC_V_POSITION);
215 DUMPREG(VP_SRC_WIDTH);
216 DUMPREG(VP_SRC_HEIGHT);
217 DUMPREG(VP_DST_H_POSITION);
218 DUMPREG(VP_DST_V_POSITION);
219 DUMPREG(VP_DST_WIDTH);
220 DUMPREG(VP_DST_HEIGHT);
227 static inline void vp_filter_set(struct mixer_resources *res,
228 int reg_id, const u8 *data, unsigned int size)
230 /* assure 4-byte align */
232 for (; size; size -= 4, reg_id += 4, data += 4) {
233 u32 val = (data[0] << 24) | (data[1] << 16) |
234 (data[2] << 8) | data[3];
235 vp_reg_write(res, reg_id, val);
239 static void vp_default_filter(struct mixer_resources *res)
241 vp_filter_set(res, VP_POLY8_Y0_LL,
242 filter_y_horiz_tap8, sizeof filter_y_horiz_tap8);
243 vp_filter_set(res, VP_POLY4_Y0_LL,
244 filter_y_vert_tap4, sizeof filter_y_vert_tap4);
245 vp_filter_set(res, VP_POLY4_C0_LL,
246 filter_cr_horiz_tap4, sizeof filter_cr_horiz_tap4);
249 static void mixer_vsync_set_update(struct mixer_context *ctx, bool enable)
251 struct mixer_resources *res = &ctx->mixer_res;
253 /* block update on vsync */
254 mixer_reg_writemask(res, MXR_STATUS, enable ?
255 MXR_STATUS_SYNC_ENABLE : 0, MXR_STATUS_SYNC_ENABLE);
257 vp_reg_write(res, VP_SHADOW_UPDATE, enable ?
258 VP_SHADOW_UPDATE_ENABLE : 0);
261 static void mixer_cfg_scan(struct mixer_context *ctx, unsigned int height)
263 struct mixer_resources *res = &ctx->mixer_res;
266 /* choosing between interlace and progressive mode */
267 val = (ctx->interlace ? MXR_CFG_SCAN_INTERLACE :
268 MXR_CFG_SCAN_PROGRASSIVE);
270 /* choosing between porper HD and SD mode */
272 val |= MXR_CFG_SCAN_NTSC | MXR_CFG_SCAN_SD;
273 else if (height == 576)
274 val |= MXR_CFG_SCAN_PAL | MXR_CFG_SCAN_SD;
275 else if (height == 720)
276 val |= MXR_CFG_SCAN_HD_720 | MXR_CFG_SCAN_HD;
277 else if (height == 1080)
278 val |= MXR_CFG_SCAN_HD_1080 | MXR_CFG_SCAN_HD;
280 val |= MXR_CFG_SCAN_HD_720 | MXR_CFG_SCAN_HD;
282 mixer_reg_writemask(res, MXR_CFG, val, MXR_CFG_SCAN_MASK);
285 static void mixer_cfg_rgb_fmt(struct mixer_context *ctx, unsigned int height)
287 struct mixer_resources *res = &ctx->mixer_res;
291 val = MXR_CFG_RGB601_0_255;
292 } else if (height == 576) {
293 val = MXR_CFG_RGB601_0_255;
294 } else if (height == 720) {
295 val = MXR_CFG_RGB709_16_235;
296 mixer_reg_write(res, MXR_CM_COEFF_Y,
297 (1 << 30) | (94 << 20) | (314 << 10) |
299 mixer_reg_write(res, MXR_CM_COEFF_CB,
300 (972 << 20) | (851 << 10) | (225 << 0));
301 mixer_reg_write(res, MXR_CM_COEFF_CR,
302 (225 << 20) | (820 << 10) | (1004 << 0));
303 } else if (height == 1080) {
304 val = MXR_CFG_RGB709_16_235;
305 mixer_reg_write(res, MXR_CM_COEFF_Y,
306 (1 << 30) | (94 << 20) | (314 << 10) |
308 mixer_reg_write(res, MXR_CM_COEFF_CB,
309 (972 << 20) | (851 << 10) | (225 << 0));
310 mixer_reg_write(res, MXR_CM_COEFF_CR,
311 (225 << 20) | (820 << 10) | (1004 << 0));
313 val = MXR_CFG_RGB709_16_235;
314 mixer_reg_write(res, MXR_CM_COEFF_Y,
315 (1 << 30) | (94 << 20) | (314 << 10) |
317 mixer_reg_write(res, MXR_CM_COEFF_CB,
318 (972 << 20) | (851 << 10) | (225 << 0));
319 mixer_reg_write(res, MXR_CM_COEFF_CR,
320 (225 << 20) | (820 << 10) | (1004 << 0));
323 mixer_reg_writemask(res, MXR_CFG, val, MXR_CFG_RGB_FMT_MASK);
326 static void mixer_cfg_layer(struct mixer_context *ctx, int win, bool enable)
328 struct mixer_resources *res = &ctx->mixer_res;
329 u32 val = enable ? ~0 : 0;
333 mixer_reg_writemask(res, MXR_CFG, val, MXR_CFG_GRP0_ENABLE);
336 mixer_reg_writemask(res, MXR_CFG, val, MXR_CFG_GRP1_ENABLE);
339 vp_reg_writemask(res, VP_ENABLE, val, VP_ENABLE_ON);
340 mixer_reg_writemask(res, MXR_CFG, val, MXR_CFG_VP_ENABLE);
345 static void mixer_run(struct mixer_context *ctx)
347 struct mixer_resources *res = &ctx->mixer_res;
349 mixer_reg_writemask(res, MXR_STATUS, ~0, MXR_STATUS_REG_RUN);
351 mixer_regs_dump(ctx);
354 static void mixer_wait_for_vblank(void *ctx)
356 struct mixer_context *mixer_ctx = ctx;
357 struct mixer_resources *res = &mixer_ctx->mixer_res;
360 ret = wait_for((mixer_reg_read(res, MXR_INT_STATUS) &
361 MXR_INT_STATUS_VSYNC), 50);
363 DRM_DEBUG_KMS("vblank wait timed out.\n");
366 static void vp_video_buffer(struct mixer_context *ctx, int win)
368 struct mixer_resources *res = &ctx->mixer_res;
370 struct hdmi_win_data *win_data;
371 unsigned int x_ratio, y_ratio;
372 unsigned int buf_num;
373 dma_addr_t luma_addr[2], chroma_addr[2];
374 bool tiled_mode = false;
375 bool crcb_mode = false;
378 win_data = &ctx->win_data[win];
380 switch (win_data->pixel_format) {
381 case DRM_FORMAT_NV12MT:
383 case DRM_FORMAT_NV12:
384 case DRM_FORMAT_NV12M:
388 /* TODO: single buffer format NV12, NV21 */
390 /* ignore pixel format at disable time */
391 if (!win_data->dma_addr)
394 DRM_ERROR("pixel format for vp is wrong [%d].\n",
395 win_data->pixel_format);
399 /* scaling feature: (src << 16) / dst */
400 x_ratio = (win_data->src_width << 16) / win_data->crtc_width;
401 y_ratio = (win_data->src_height << 16) / win_data->crtc_height;
404 luma_addr[0] = win_data->dma_addr;
405 chroma_addr[0] = win_data->chroma_dma_addr;
407 luma_addr[0] = win_data->dma_addr;
408 chroma_addr[0] = win_data->dma_addr
409 + (win_data->fb_width * win_data->fb_height);
412 if (win_data->scan_flags & DRM_MODE_FLAG_INTERLACE) {
413 ctx->interlace = true;
415 luma_addr[1] = luma_addr[0] + 0x40;
416 chroma_addr[1] = chroma_addr[0] + 0x40;
418 luma_addr[1] = luma_addr[0] + win_data->fb_width;
419 chroma_addr[1] = chroma_addr[0] + win_data->fb_width;
422 ctx->interlace = false;
427 spin_lock_irqsave(&res->reg_slock, flags);
428 mixer_vsync_set_update(ctx, false);
430 /* interlace or progressive scan mode */
431 val = (ctx->interlace ? ~0 : 0);
432 vp_reg_writemask(res, VP_MODE, val, VP_MODE_LINE_SKIP);
435 val = (crcb_mode ? VP_MODE_NV21 : VP_MODE_NV12);
436 val |= (tiled_mode ? VP_MODE_MEM_TILED : VP_MODE_MEM_LINEAR);
437 vp_reg_writemask(res, VP_MODE, val, VP_MODE_FMT_MASK);
439 /* setting size of input image */
440 vp_reg_write(res, VP_IMG_SIZE_Y, VP_IMG_HSIZE(win_data->fb_width) |
441 VP_IMG_VSIZE(win_data->fb_height));
442 /* chroma height has to reduced by 2 to avoid chroma distorions */
443 vp_reg_write(res, VP_IMG_SIZE_C, VP_IMG_HSIZE(win_data->fb_width) |
444 VP_IMG_VSIZE(win_data->fb_height / 2));
446 vp_reg_write(res, VP_SRC_WIDTH, win_data->src_width);
447 vp_reg_write(res, VP_SRC_HEIGHT, win_data->src_height);
448 vp_reg_write(res, VP_SRC_H_POSITION,
449 VP_SRC_H_POSITION_VAL(win_data->fb_x));
450 vp_reg_write(res, VP_SRC_V_POSITION, win_data->fb_y);
452 vp_reg_write(res, VP_DST_WIDTH, win_data->crtc_width);
453 vp_reg_write(res, VP_DST_H_POSITION, win_data->crtc_x);
454 if (ctx->interlace) {
455 vp_reg_write(res, VP_DST_HEIGHT, win_data->crtc_height / 2);
456 vp_reg_write(res, VP_DST_V_POSITION, win_data->crtc_y / 2);
458 vp_reg_write(res, VP_DST_HEIGHT, win_data->crtc_height);
459 vp_reg_write(res, VP_DST_V_POSITION, win_data->crtc_y);
462 vp_reg_write(res, VP_H_RATIO, x_ratio);
463 vp_reg_write(res, VP_V_RATIO, y_ratio);
465 vp_reg_write(res, VP_ENDIAN_MODE, VP_ENDIAN_MODE_LITTLE);
467 /* set buffer address to vp */
468 vp_reg_write(res, VP_TOP_Y_PTR, luma_addr[0]);
469 vp_reg_write(res, VP_BOT_Y_PTR, luma_addr[1]);
470 vp_reg_write(res, VP_TOP_C_PTR, chroma_addr[0]);
471 vp_reg_write(res, VP_BOT_C_PTR, chroma_addr[1]);
473 mixer_cfg_scan(ctx, win_data->mode_height);
474 mixer_cfg_rgb_fmt(ctx, win_data->mode_height);
475 mixer_cfg_layer(ctx, win, true);
478 mixer_vsync_set_update(ctx, true);
479 spin_unlock_irqrestore(&res->reg_slock, flags);
481 mixer_wait_for_vblank(ctx);
486 static void mixer_graph_buffer(struct mixer_context *ctx, int win)
488 struct mixer_resources *res = &ctx->mixer_res;
490 struct hdmi_win_data *win_data;
491 unsigned int x_ratio, y_ratio;
492 unsigned int src_x_offset, src_y_offset, dst_x_offset, dst_y_offset;
497 win_data = &ctx->win_data[win];
504 switch (win_data->bpp) {
515 /* 2x scaling feature */
519 dst_x_offset = win_data->crtc_x;
520 dst_y_offset = win_data->crtc_y;
522 /* converting dma address base and source offset */
523 dma_addr = win_data->dma_addr
524 + (win_data->fb_x * win_data->bpp >> 3)
525 + (win_data->fb_y * win_data->fb_width * win_data->bpp >> 3);
529 if (win_data->scan_flags & DRM_MODE_FLAG_INTERLACE)
530 ctx->interlace = true;
532 ctx->interlace = false;
534 spin_lock_irqsave(&res->reg_slock, flags);
535 mixer_vsync_set_update(ctx, false);
538 mixer_reg_writemask(res, MXR_GRAPHIC_CFG(win),
539 MXR_GRP_CFG_FORMAT_VAL(fmt), MXR_GRP_CFG_FORMAT_MASK);
542 mixer_reg_write(res, MXR_GRAPHIC_SPAN(win), win_data->fb_width);
544 val = MXR_GRP_WH_WIDTH(win_data->crtc_width);
545 val |= MXR_GRP_WH_HEIGHT(win_data->crtc_height);
546 val |= MXR_GRP_WH_H_SCALE(x_ratio);
547 val |= MXR_GRP_WH_V_SCALE(y_ratio);
548 mixer_reg_write(res, MXR_GRAPHIC_WH(win), val);
550 /* setup offsets in source image */
551 val = MXR_GRP_SXY_SX(src_x_offset);
552 val |= MXR_GRP_SXY_SY(src_y_offset);
553 mixer_reg_write(res, MXR_GRAPHIC_SXY(win), val);
555 /* setup offsets in display image */
556 val = MXR_GRP_DXY_DX(dst_x_offset);
557 val |= MXR_GRP_DXY_DY(dst_y_offset);
558 mixer_reg_write(res, MXR_GRAPHIC_DXY(win), val);
560 /* set buffer address to mixer */
561 mixer_reg_write(res, MXR_GRAPHIC_BASE(win), dma_addr);
563 mixer_cfg_scan(ctx, win_data->mode_height);
564 mixer_cfg_rgb_fmt(ctx, win_data->mode_height);
565 mixer_cfg_layer(ctx, win, true);
568 mixer_vsync_set_update(ctx, true);
569 spin_unlock_irqrestore(&res->reg_slock, flags);
572 static void vp_win_reset(struct mixer_context *ctx)
574 struct mixer_resources *res = &ctx->mixer_res;
577 vp_reg_write(res, VP_SRESET, VP_SRESET_PROCESSING);
578 for (tries = 100; tries; --tries) {
579 /* waiting until VP_SRESET_PROCESSING is 0 */
580 if (~vp_reg_read(res, VP_SRESET) & VP_SRESET_PROCESSING)
584 WARN(tries == 0, "failed to reset Video Processor\n");
587 static void mixer_win_reset(struct mixer_context *ctx)
589 struct mixer_resources *res = &ctx->mixer_res;
591 u32 val; /* value stored to register */
593 spin_lock_irqsave(&res->reg_slock, flags);
594 mixer_vsync_set_update(ctx, false);
596 mixer_reg_writemask(res, MXR_CFG, MXR_CFG_DST_HDMI, MXR_CFG_DST_MASK);
598 /* set output in RGB888 mode */
599 mixer_reg_writemask(res, MXR_CFG, MXR_CFG_OUT_RGB888, MXR_CFG_OUT_MASK);
601 /* 16 beat burst in DMA */
602 mixer_reg_writemask(res, MXR_STATUS, MXR_STATUS_16_BURST,
603 MXR_STATUS_BURST_MASK);
605 /* setting default layer priority: layer1 > layer0 > video
606 * because typical usage scenario would be
608 * layer0 - framebuffer
609 * video - video overlay
611 val = MXR_LAYER_CFG_GRP1_VAL(3);
612 val |= MXR_LAYER_CFG_GRP0_VAL(2);
613 val |= MXR_LAYER_CFG_VP_VAL(1);
614 mixer_reg_write(res, MXR_LAYER_CFG, val);
616 /* setting background color */
617 mixer_reg_write(res, MXR_BG_COLOR0, 0x008080);
618 mixer_reg_write(res, MXR_BG_COLOR1, 0x008080);
619 mixer_reg_write(res, MXR_BG_COLOR2, 0x008080);
621 /* setting graphical layers */
622 val = MXR_GRP_CFG_COLOR_KEY_DISABLE; /* no blank key */
623 val |= MXR_GRP_CFG_WIN_BLEND_EN;
624 val |= MXR_GRP_CFG_BLEND_PRE_MUL;
625 val |= MXR_GRP_CFG_PIXEL_BLEND_EN;
626 val |= MXR_GRP_CFG_ALPHA_VAL(0xff); /* non-transparent alpha */
628 /* the same configuration for both layers */
629 mixer_reg_write(res, MXR_GRAPHIC_CFG(0), val);
630 mixer_reg_write(res, MXR_GRAPHIC_CFG(1), val);
632 /* setting video layers */
633 val = MXR_GRP_CFG_ALPHA_VAL(0);
634 mixer_reg_write(res, MXR_VIDEO_CFG, val);
636 /* configuration of Video Processor Registers */
638 vp_default_filter(res);
640 /* disable all layers */
641 mixer_reg_writemask(res, MXR_CFG, 0, MXR_CFG_GRP0_ENABLE);
642 mixer_reg_writemask(res, MXR_CFG, 0, MXR_CFG_GRP1_ENABLE);
643 mixer_reg_writemask(res, MXR_CFG, 0, MXR_CFG_VP_ENABLE);
645 mixer_vsync_set_update(ctx, true);
646 spin_unlock_irqrestore(&res->reg_slock, flags);
649 static void mixer_poweron(struct mixer_context *ctx)
651 struct mixer_resources *res = &ctx->mixer_res;
653 DRM_DEBUG_KMS("[%d] %s\n", __LINE__, __func__);
655 mutex_lock(&ctx->mixer_mutex);
657 mutex_unlock(&ctx->mixer_mutex);
661 mutex_unlock(&ctx->mixer_mutex);
663 res->mixer_regs = res->saved_mixer_regs;
664 res->vp_regs = res->saved_vp_regs;
666 pm_runtime_get_sync(ctx->dev);
668 clk_enable(res->mixer);
670 clk_enable(res->sclk_mixer);
672 mixer_reg_write(res, MXR_INT_EN, ctx->int_en);
673 mixer_win_reset(ctx);
676 static void vp_cleanup(struct mixer_context *ctx)
678 struct mixer_resources *res = &ctx->mixer_res;
679 int val, retries = 200;
681 DRM_DEBUG_KMS("%s\n", __func__);
683 vp_reg_writemask(res, VP_ENABLE, 0, VP_ENABLE_ON);
686 val = vp_reg_read(res, VP_ENABLE);
687 } while (!(val & VP_ENABLE_OPERATING) && retries--);
690 DRM_ERROR("vp disable failed.\n");
692 /* clean buffer address to vp */
693 vp_reg_write(res, VP_TOP_Y_PTR, 0);
694 vp_reg_write(res, VP_BOT_Y_PTR, 0);
695 vp_reg_write(res, VP_TOP_C_PTR, 0);
696 vp_reg_write(res, VP_BOT_C_PTR, 0);
699 static void mixer_cleanup(struct mixer_context *ctx)
701 struct mixer_resources *res = &ctx->mixer_res;
702 int val, retries = 200;
704 DRM_DEBUG_KMS("%s\n", __func__);
707 mixer_reg_writemask(res, MXR_INT_EN, 0, MXR_INT_EN_VSYNC);
710 mixer_reg_writemask(res, MXR_STATUS, 0, MXR_STATUS_REG_RUN);
713 val = mixer_reg_read(res, MXR_STATUS);
714 } while (!(val & MXR_STATUS_IDLE_MODE) && retries--);
717 DRM_ERROR("mixer disable failed.\n");
720 static void mixer_poweroff(struct mixer_context *ctx)
722 struct mixer_resources *res = &ctx->mixer_res;
725 DRM_DEBUG_KMS("[%d] %s\n", __LINE__, __func__);
727 mutex_lock(&ctx->mixer_mutex);
730 mutex_unlock(&ctx->mixer_mutex);
732 spin_lock_irqsave(&res->reg_slock, flags);
734 ctx->int_en = mixer_reg_read(res, MXR_INT_EN);
735 mixer_vsync_set_update(ctx, false);
740 spin_unlock_irqrestore(&res->reg_slock, flags);
742 /* HDMI changed sclk_hdmi parent clock from pixel to hdmiphy */
743 clk_set_parent(res->sclk_hdmi, res->sclk_pixel);
745 clk_disable(res->mixer);
746 clk_disable(res->vp);
747 clk_disable(res->sclk_mixer);
749 res->mixer_regs = NULL;
752 pm_runtime_put_sync(ctx->dev);
754 mutex_lock(&ctx->mixer_mutex);
755 ctx->powered = false;
758 mutex_unlock(&ctx->mixer_mutex);
761 static int mixer_enable_vblank(void *ctx, int pipe)
763 struct mixer_context *mixer_ctx = ctx;
764 struct mixer_resources *res = &mixer_ctx->mixer_res;
766 DRM_DEBUG_KMS("[%d] %s\n", __LINE__, __func__);
768 mixer_ctx->pipe = pipe;
770 /* enable vsync interrupt */
771 mixer_reg_writemask(res, MXR_INT_EN, MXR_INT_EN_VSYNC,
777 static void mixer_disable_vblank(void *ctx)
779 struct mixer_context *mixer_ctx = ctx;
780 struct mixer_resources *res = &mixer_ctx->mixer_res;
782 DRM_DEBUG_KMS("[%d] %s\n", __LINE__, __func__);
784 /* disable vsync interrupt */
785 mixer_reg_writemask(res, MXR_INT_EN, 0, MXR_INT_EN_VSYNC);
788 static void mixer_dpms(void *ctx, int mode)
790 struct mixer_context *mixer_ctx = ctx;
792 DRM_DEBUG_KMS("[%d] %s\n", __LINE__, __func__);
795 case DRM_MODE_DPMS_ON:
796 mixer_poweron(mixer_ctx);
798 case DRM_MODE_DPMS_STANDBY:
799 case DRM_MODE_DPMS_SUSPEND:
800 case DRM_MODE_DPMS_OFF:
801 mixer_poweroff(mixer_ctx);
804 DRM_DEBUG_KMS("unknown dpms mode: %d\n", mode);
809 static void mixer_win_mode_set(void *ctx,
810 struct exynos_drm_overlay *overlay)
812 struct mixer_context *mixer_ctx = ctx;
813 struct hdmi_win_data *win_data;
816 DRM_DEBUG_KMS("[%d] %s\n", __LINE__, __func__);
819 DRM_ERROR("overlay is NULL\n");
823 DRM_DEBUG_KMS("set [%d]x[%d] at (%d,%d) to [%d]x[%d] at (%d,%d)\n",
824 overlay->fb_width, overlay->fb_height,
825 overlay->fb_x, overlay->fb_y,
826 overlay->crtc_width, overlay->crtc_height,
827 overlay->crtc_x, overlay->crtc_y);
830 if (win == DEFAULT_ZPOS)
831 win = MIXER_DEFAULT_WIN;
833 if (win < 0 || win > MIXER_WIN_NR) {
834 DRM_ERROR("mixer window[%d] is wrong\n", win);
838 win_data = &mixer_ctx->win_data[win];
840 win_data->dma_addr = overlay->dma_addr[0];
841 win_data->vaddr = overlay->vaddr[0];
842 win_data->chroma_dma_addr = overlay->dma_addr[1];
843 win_data->chroma_vaddr = overlay->vaddr[1];
844 win_data->pixel_format = overlay->pixel_format;
845 win_data->bpp = overlay->bpp;
847 win_data->crtc_x = overlay->crtc_x;
848 win_data->crtc_y = overlay->crtc_y;
849 win_data->crtc_width = overlay->crtc_width;
850 win_data->crtc_height = overlay->crtc_height;
852 win_data->fb_x = overlay->fb_x;
853 win_data->fb_y = overlay->fb_y;
854 win_data->fb_width = overlay->fb_width;
855 win_data->fb_height = overlay->fb_height;
856 win_data->src_width = overlay->src_width;
857 win_data->src_height = overlay->src_height;
859 win_data->mode_width = overlay->mode_width;
860 win_data->mode_height = overlay->mode_height;
862 win_data->scan_flags = overlay->scan_flag;
865 static void mixer_win_commit(void *ctx, int win)
867 struct mixer_context *mixer_ctx = ctx;
869 DRM_DEBUG_KMS("[%d] %s, win: %d\n", __LINE__, __func__, win);
872 vp_video_buffer(mixer_ctx, win);
874 mixer_graph_buffer(mixer_ctx, win);
877 static void mixer_win_disable(void *ctx, int win)
879 struct mixer_context *mixer_ctx = ctx;
880 struct mixer_resources *res = &mixer_ctx->mixer_res;
883 DRM_DEBUG_KMS("[%d] %s, win: %d\n", __LINE__, __func__, win);
885 spin_lock_irqsave(&res->reg_slock, flags);
886 mixer_vsync_set_update(mixer_ctx, false);
888 mixer_cfg_layer(mixer_ctx, win, false);
890 mixer_vsync_set_update(mixer_ctx, true);
891 spin_unlock_irqrestore(&res->reg_slock, flags);
894 static struct exynos_mixer_ops mixer_ops = {
896 .enable_vblank = mixer_enable_vblank,
897 .disable_vblank = mixer_disable_vblank,
901 .wait_for_vblank = mixer_wait_for_vblank,
902 .win_mode_set = mixer_win_mode_set,
903 .win_commit = mixer_win_commit,
904 .win_disable = mixer_win_disable,
907 /* for pageflip event */
908 static void mixer_finish_pageflip(struct drm_device *drm_dev, int crtc)
910 struct exynos_drm_private *dev_priv = drm_dev->dev_private;
911 struct drm_pending_vblank_event *e, *t;
914 bool is_checked = false;
916 spin_lock_irqsave(&drm_dev->event_lock, flags);
918 list_for_each_entry_safe(e, t, &dev_priv->pageflip_event_list,
920 /* if event's pipe isn't same as crtc then ignore it. */
925 do_gettimeofday(&now);
926 e->event.sequence = 0;
927 e->event.tv_sec = now.tv_sec;
928 e->event.tv_usec = now.tv_usec;
930 list_move_tail(&e->base.link, &e->base.file_priv->event_list);
931 wake_up_interruptible(&e->base.file_priv->event_wait);
936 * call drm_vblank_put only in case that drm_vblank_get was
939 if (atomic_read(&drm_dev->vblank_refcount[crtc]) > 0)
940 drm_vblank_put(drm_dev, crtc);
942 spin_unlock_irqrestore(&drm_dev->event_lock, flags);
945 static irqreturn_t mixer_irq_handler(int irq, void *arg)
947 struct exynos_drm_hdmi_context *drm_hdmi_ctx = arg;
948 struct mixer_context *ctx = drm_hdmi_ctx->ctx;
949 struct mixer_resources *res = &ctx->mixer_res;
950 u32 val, base, shadow;
952 spin_lock(&res->reg_slock);
955 spin_unlock(&res->reg_slock);
959 /* read interrupt status for handling and clearing flags for VSYNC */
960 val = mixer_reg_read(res, MXR_INT_STATUS);
963 if (val & MXR_INT_STATUS_VSYNC) {
964 /* interlace scan need to check shadow register */
965 if (ctx->interlace) {
966 base = mixer_reg_read(res, MXR_GRAPHIC_BASE(0));
967 shadow = mixer_reg_read(res, MXR_GRAPHIC_BASE_S(0));
971 base = mixer_reg_read(res, MXR_GRAPHIC_BASE(1));
972 shadow = mixer_reg_read(res, MXR_GRAPHIC_BASE_S(1));
977 drm_handle_vblank(drm_hdmi_ctx->drm_dev, ctx->pipe);
978 mixer_finish_pageflip(drm_hdmi_ctx->drm_dev, ctx->pipe);
982 /* clear interrupts */
983 if (~val & MXR_INT_EN_VSYNC) {
984 /* vsync interrupt use different bit for read and clear */
985 val &= ~MXR_INT_EN_VSYNC;
986 val |= MXR_INT_CLEAR_VSYNC;
988 mixer_reg_write(res, MXR_INT_STATUS, val);
990 spin_unlock(&res->reg_slock);
995 static int __devinit mixer_resources_init(struct exynos_drm_hdmi_context *ctx,
996 struct platform_device *pdev)
998 struct mixer_context *mixer_ctx = ctx->ctx;
999 struct device *dev = &pdev->dev;
1000 struct mixer_resources *mixer_res = &mixer_ctx->mixer_res;
1001 struct resource *res;
1004 spin_lock_init(&mixer_res->reg_slock);
1006 mixer_res->mixer = clk_get(dev, "mixer");
1007 if (IS_ERR_OR_NULL(mixer_res->mixer)) {
1008 dev_err(dev, "failed to get clock 'mixer'\n");
1012 mixer_res->vp = clk_get(dev, "vp");
1013 if (IS_ERR_OR_NULL(mixer_res->vp)) {
1014 dev_err(dev, "failed to get clock 'vp'\n");
1018 mixer_res->sclk_mixer = clk_get(dev, "sclk_mixer");
1019 if (IS_ERR_OR_NULL(mixer_res->sclk_mixer)) {
1020 dev_err(dev, "failed to get clock 'sclk_mixer'\n");
1024 mixer_res->sclk_hdmi = clk_get(dev, "sclk_hdmi");
1025 if (IS_ERR_OR_NULL(mixer_res->sclk_hdmi)) {
1026 dev_err(dev, "failed to get clock 'sclk_hdmi'\n");
1030 mixer_res->sclk_pixel = clk_get(dev, "sclk_pixel");
1031 if (IS_ERR_OR_NULL(mixer_res->sclk_pixel)) {
1032 DRM_ERROR("failed to get clock 'sclk_pixel'\n");
1035 mixer_res->sclk_dac = clk_get(dev, "sclk_dac");
1036 if (IS_ERR_OR_NULL(mixer_res->sclk_dac)) {
1037 dev_err(dev, "failed to get clock 'sclk_dac'\n");
1041 res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "mxr");
1043 dev_err(dev, "get memory resource failed.\n");
1048 clk_set_parent(mixer_res->sclk_mixer, mixer_res->sclk_hdmi);
1050 mixer_res->mixer_regs = ioremap(res->start, resource_size(res));
1051 if (mixer_res->mixer_regs == NULL) {
1052 dev_err(dev, "register mapping failed.\n");
1056 mixer_res->saved_mixer_regs = mixer_res->mixer_regs;
1058 res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "vp");
1060 dev_err(dev, "get memory resource failed.\n");
1062 goto fail_mixer_regs;
1065 mixer_res->vp_regs = ioremap(res->start, resource_size(res));
1066 if (mixer_res->vp_regs == NULL) {
1067 dev_err(dev, "register mapping failed.\n");
1069 goto fail_mixer_regs;
1071 mixer_res->saved_vp_regs = mixer_res->vp_regs;
1073 res = platform_get_resource_byname(pdev, IORESOURCE_IRQ, "irq");
1075 dev_err(dev, "get interrupt resource failed.\n");
1080 ret = request_irq(res->start, mixer_irq_handler, 0, "drm_mixer", ctx);
1082 dev_err(dev, "request interrupt failed.\n");
1085 mixer_res->irq = res->start;
1090 iounmap(mixer_res->vp_regs);
1093 iounmap(mixer_res->mixer_regs);
1096 if (!IS_ERR_OR_NULL(mixer_res->sclk_dac))
1097 clk_put(mixer_res->sclk_dac);
1098 if (!IS_ERR_OR_NULL(mixer_res->sclk_hdmi))
1099 clk_put(mixer_res->sclk_hdmi);
1100 if (!IS_ERR_OR_NULL(mixer_res->sclk_pixel))
1101 clk_put(mixer_res->sclk_pixel);
1102 if (!IS_ERR_OR_NULL(mixer_res->sclk_mixer))
1103 clk_put(mixer_res->sclk_mixer);
1104 if (!IS_ERR_OR_NULL(mixer_res->vp))
1105 clk_put(mixer_res->vp);
1106 if (!IS_ERR_OR_NULL(mixer_res->mixer))
1107 clk_put(mixer_res->mixer);
1111 static void mixer_resources_cleanup(struct mixer_context *ctx)
1113 struct mixer_resources *res = &ctx->mixer_res;
1115 free_irq(res->irq, ctx);
1117 if (!IS_ERR_OR_NULL(res->sclk_dac))
1118 clk_put(res->sclk_dac);
1119 if (!IS_ERR_OR_NULL(res->sclk_hdmi))
1120 clk_put(res->sclk_hdmi);
1121 if (!IS_ERR_OR_NULL(res->sclk_pixel))
1122 clk_put(res->sclk_pixel);
1123 if (!IS_ERR_OR_NULL(res->sclk_mixer))
1124 clk_put(res->sclk_mixer);
1125 if (!IS_ERR_OR_NULL(res->vp))
1127 if (!IS_ERR_OR_NULL(res->mixer))
1128 clk_put(res->mixer);
1130 iounmap(res->vp_regs);
1131 iounmap(res->mixer_regs);
1134 static int __devinit mixer_probe(struct platform_device *pdev)
1136 struct device *dev = &pdev->dev;
1137 struct exynos_drm_hdmi_context *drm_hdmi_ctx;
1138 struct mixer_context *ctx;
1141 dev_info(dev, "probe start\n");
1143 drm_hdmi_ctx = kzalloc(sizeof(*drm_hdmi_ctx), GFP_KERNEL);
1144 if (!drm_hdmi_ctx) {
1145 DRM_ERROR("failed to allocate common hdmi context.\n");
1149 ctx = kzalloc(sizeof(*ctx), GFP_KERNEL);
1151 DRM_ERROR("failed to alloc mixer context.\n");
1152 kfree(drm_hdmi_ctx);
1156 mutex_init(&ctx->mixer_mutex);
1158 ctx->dev = &pdev->dev;
1159 drm_hdmi_ctx->ctx = (void *)ctx;
1161 platform_set_drvdata(pdev, drm_hdmi_ctx);
1163 /* acquire resources: regs, irqs, clocks */
1164 ret = mixer_resources_init(drm_hdmi_ctx, pdev);
1168 /* register specific callback point to common hdmi. */
1169 exynos_mixer_ops_register(&mixer_ops);
1171 pm_runtime_enable(dev);
1177 dev_info(dev, "probe failed\n");
1181 static int mixer_remove(struct platform_device *pdev)
1183 struct device *dev = &pdev->dev;
1184 struct exynos_drm_hdmi_context *drm_hdmi_ctx =
1185 platform_get_drvdata(pdev);
1186 struct mixer_context *ctx = drm_hdmi_ctx->ctx;
1188 dev_info(dev, "remove successful\n");
1190 pm_runtime_disable(&pdev->dev);
1192 mixer_resources_cleanup(ctx);
1197 #ifdef CONFIG_PM_SLEEP
1198 static int mixer_suspend(struct device *dev)
1200 struct exynos_drm_hdmi_context *drm_hdmi_ctx = get_mixer_context(dev);
1201 struct mixer_context *ctx = drm_hdmi_ctx->ctx;
1203 mixer_poweroff(ctx);
1209 static SIMPLE_DEV_PM_OPS(mixer_pm_ops, mixer_suspend, NULL);
1211 struct platform_driver mixer_driver = {
1213 .name = "s5p-mixer",
1214 .owner = THIS_MODULE,
1215 .pm = &mixer_pm_ops,
1217 .probe = mixer_probe,
1218 .remove = __devexit_p(mixer_remove),