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/platform_device.h>
27 #include <linux/interrupt.h>
28 #include <linux/irq.h>
29 #include <linux/delay.h>
30 #include <linux/pm_runtime.h>
31 #include <linux/clk.h>
32 #include <linux/regulator/consumer.h>
34 #include <linux/component.h>
36 #include <drm/exynos_drm.h>
38 #include "exynos_drm_drv.h"
39 #include "exynos_drm_crtc.h"
40 #include "exynos_drm_plane.h"
41 #include "exynos_drm_iommu.h"
42 #include "exynos_mixer.h"
44 #define MIXER_WIN_NR 3
45 #define MIXER_DEFAULT_WIN 0
47 struct mixer_resources {
49 void __iomem *mixer_regs;
50 void __iomem *vp_regs;
55 struct clk *sclk_mixer;
56 struct clk *sclk_hdmi;
57 struct clk *mout_mixer;
60 enum mixer_version_id {
66 struct mixer_context {
67 struct platform_device *pdev;
69 struct drm_device *drm_dev;
70 struct exynos_drm_crtc *crtc;
71 struct exynos_drm_plane planes[MIXER_WIN_NR];
79 struct mutex mixer_mutex;
80 struct mixer_resources mixer_res;
81 enum mixer_version_id mxr_ver;
82 wait_queue_head_t wait_vsync_queue;
83 atomic_t wait_vsync_event;
86 struct mixer_drv_data {
87 enum mixer_version_id version;
92 static const u8 filter_y_horiz_tap8[] = {
93 0, -1, -1, -1, -1, -1, -1, -1,
94 -1, -1, -1, -1, -1, 0, 0, 0,
95 0, 2, 4, 5, 6, 6, 6, 6,
96 6, 5, 5, 4, 3, 2, 1, 1,
97 0, -6, -12, -16, -18, -20, -21, -20,
98 -20, -18, -16, -13, -10, -8, -5, -2,
99 127, 126, 125, 121, 114, 107, 99, 89,
100 79, 68, 57, 46, 35, 25, 16, 8,
103 static const u8 filter_y_vert_tap4[] = {
104 0, -3, -6, -8, -8, -8, -8, -7,
105 -6, -5, -4, -3, -2, -1, -1, 0,
106 127, 126, 124, 118, 111, 102, 92, 81,
107 70, 59, 48, 37, 27, 19, 11, 5,
108 0, 5, 11, 19, 27, 37, 48, 59,
109 70, 81, 92, 102, 111, 118, 124, 126,
110 0, 0, -1, -1, -2, -3, -4, -5,
111 -6, -7, -8, -8, -8, -8, -6, -3,
114 static const u8 filter_cr_horiz_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,
121 static inline u32 vp_reg_read(struct mixer_resources *res, u32 reg_id)
123 return readl(res->vp_regs + reg_id);
126 static inline void vp_reg_write(struct mixer_resources *res, u32 reg_id,
129 writel(val, res->vp_regs + reg_id);
132 static inline void vp_reg_writemask(struct mixer_resources *res, u32 reg_id,
135 u32 old = vp_reg_read(res, reg_id);
137 val = (val & mask) | (old & ~mask);
138 writel(val, res->vp_regs + reg_id);
141 static inline u32 mixer_reg_read(struct mixer_resources *res, u32 reg_id)
143 return readl(res->mixer_regs + reg_id);
146 static inline void mixer_reg_write(struct mixer_resources *res, u32 reg_id,
149 writel(val, res->mixer_regs + reg_id);
152 static inline void mixer_reg_writemask(struct mixer_resources *res,
153 u32 reg_id, u32 val, u32 mask)
155 u32 old = mixer_reg_read(res, reg_id);
157 val = (val & mask) | (old & ~mask);
158 writel(val, res->mixer_regs + reg_id);
161 static void mixer_regs_dump(struct mixer_context *ctx)
163 #define DUMPREG(reg_id) \
165 DRM_DEBUG_KMS(#reg_id " = %08x\n", \
166 (u32)readl(ctx->mixer_res.mixer_regs + reg_id)); \
172 DUMPREG(MXR_INT_STATUS);
174 DUMPREG(MXR_LAYER_CFG);
175 DUMPREG(MXR_VIDEO_CFG);
177 DUMPREG(MXR_GRAPHIC0_CFG);
178 DUMPREG(MXR_GRAPHIC0_BASE);
179 DUMPREG(MXR_GRAPHIC0_SPAN);
180 DUMPREG(MXR_GRAPHIC0_WH);
181 DUMPREG(MXR_GRAPHIC0_SXY);
182 DUMPREG(MXR_GRAPHIC0_DXY);
184 DUMPREG(MXR_GRAPHIC1_CFG);
185 DUMPREG(MXR_GRAPHIC1_BASE);
186 DUMPREG(MXR_GRAPHIC1_SPAN);
187 DUMPREG(MXR_GRAPHIC1_WH);
188 DUMPREG(MXR_GRAPHIC1_SXY);
189 DUMPREG(MXR_GRAPHIC1_DXY);
193 static void vp_regs_dump(struct mixer_context *ctx)
195 #define DUMPREG(reg_id) \
197 DRM_DEBUG_KMS(#reg_id " = %08x\n", \
198 (u32) readl(ctx->mixer_res.vp_regs + reg_id)); \
203 DUMPREG(VP_SHADOW_UPDATE);
204 DUMPREG(VP_FIELD_ID);
206 DUMPREG(VP_IMG_SIZE_Y);
207 DUMPREG(VP_IMG_SIZE_C);
208 DUMPREG(VP_PER_RATE_CTRL);
209 DUMPREG(VP_TOP_Y_PTR);
210 DUMPREG(VP_BOT_Y_PTR);
211 DUMPREG(VP_TOP_C_PTR);
212 DUMPREG(VP_BOT_C_PTR);
213 DUMPREG(VP_ENDIAN_MODE);
214 DUMPREG(VP_SRC_H_POSITION);
215 DUMPREG(VP_SRC_V_POSITION);
216 DUMPREG(VP_SRC_WIDTH);
217 DUMPREG(VP_SRC_HEIGHT);
218 DUMPREG(VP_DST_H_POSITION);
219 DUMPREG(VP_DST_V_POSITION);
220 DUMPREG(VP_DST_WIDTH);
221 DUMPREG(VP_DST_HEIGHT);
228 static inline void vp_filter_set(struct mixer_resources *res,
229 int reg_id, const u8 *data, unsigned int size)
231 /* assure 4-byte align */
233 for (; size; size -= 4, reg_id += 4, data += 4) {
234 u32 val = (data[0] << 24) | (data[1] << 16) |
235 (data[2] << 8) | data[3];
236 vp_reg_write(res, reg_id, val);
240 static void vp_default_filter(struct mixer_resources *res)
242 vp_filter_set(res, VP_POLY8_Y0_LL,
243 filter_y_horiz_tap8, sizeof(filter_y_horiz_tap8));
244 vp_filter_set(res, VP_POLY4_Y0_LL,
245 filter_y_vert_tap4, sizeof(filter_y_vert_tap4));
246 vp_filter_set(res, VP_POLY4_C0_LL,
247 filter_cr_horiz_tap4, sizeof(filter_cr_horiz_tap4));
250 static void mixer_vsync_set_update(struct mixer_context *ctx, bool enable)
252 struct mixer_resources *res = &ctx->mixer_res;
254 /* block update on vsync */
255 mixer_reg_writemask(res, MXR_STATUS, enable ?
256 MXR_STATUS_SYNC_ENABLE : 0, MXR_STATUS_SYNC_ENABLE);
259 vp_reg_write(res, VP_SHADOW_UPDATE, enable ?
260 VP_SHADOW_UPDATE_ENABLE : 0);
263 static void mixer_cfg_scan(struct mixer_context *ctx, unsigned int height)
265 struct mixer_resources *res = &ctx->mixer_res;
268 /* choosing between interlace and progressive mode */
269 val = (ctx->interlace ? MXR_CFG_SCAN_INTERLACE :
270 MXR_CFG_SCAN_PROGRESSIVE);
272 if (ctx->mxr_ver != MXR_VER_128_0_0_184) {
273 /* choosing between proper HD and SD mode */
275 val |= MXR_CFG_SCAN_NTSC | MXR_CFG_SCAN_SD;
276 else if (height <= 576)
277 val |= MXR_CFG_SCAN_PAL | MXR_CFG_SCAN_SD;
278 else if (height <= 720)
279 val |= MXR_CFG_SCAN_HD_720 | MXR_CFG_SCAN_HD;
280 else if (height <= 1080)
281 val |= MXR_CFG_SCAN_HD_1080 | MXR_CFG_SCAN_HD;
283 val |= MXR_CFG_SCAN_HD_720 | MXR_CFG_SCAN_HD;
286 mixer_reg_writemask(res, MXR_CFG, val, MXR_CFG_SCAN_MASK);
289 static void mixer_cfg_rgb_fmt(struct mixer_context *ctx, unsigned int height)
291 struct mixer_resources *res = &ctx->mixer_res;
295 val = MXR_CFG_RGB601_0_255;
296 } else if (height == 576) {
297 val = MXR_CFG_RGB601_0_255;
298 } else if (height == 720) {
299 val = MXR_CFG_RGB709_16_235;
300 mixer_reg_write(res, MXR_CM_COEFF_Y,
301 (1 << 30) | (94 << 20) | (314 << 10) |
303 mixer_reg_write(res, MXR_CM_COEFF_CB,
304 (972 << 20) | (851 << 10) | (225 << 0));
305 mixer_reg_write(res, MXR_CM_COEFF_CR,
306 (225 << 20) | (820 << 10) | (1004 << 0));
307 } else if (height == 1080) {
308 val = MXR_CFG_RGB709_16_235;
309 mixer_reg_write(res, MXR_CM_COEFF_Y,
310 (1 << 30) | (94 << 20) | (314 << 10) |
312 mixer_reg_write(res, MXR_CM_COEFF_CB,
313 (972 << 20) | (851 << 10) | (225 << 0));
314 mixer_reg_write(res, MXR_CM_COEFF_CR,
315 (225 << 20) | (820 << 10) | (1004 << 0));
317 val = MXR_CFG_RGB709_16_235;
318 mixer_reg_write(res, MXR_CM_COEFF_Y,
319 (1 << 30) | (94 << 20) | (314 << 10) |
321 mixer_reg_write(res, MXR_CM_COEFF_CB,
322 (972 << 20) | (851 << 10) | (225 << 0));
323 mixer_reg_write(res, MXR_CM_COEFF_CR,
324 (225 << 20) | (820 << 10) | (1004 << 0));
327 mixer_reg_writemask(res, MXR_CFG, val, MXR_CFG_RGB_FMT_MASK);
330 static void mixer_cfg_layer(struct mixer_context *ctx, int win, bool enable)
332 struct mixer_resources *res = &ctx->mixer_res;
333 u32 val = enable ? ~0 : 0;
337 mixer_reg_writemask(res, MXR_CFG, val, MXR_CFG_GRP0_ENABLE);
340 mixer_reg_writemask(res, MXR_CFG, val, MXR_CFG_GRP1_ENABLE);
343 if (ctx->vp_enabled) {
344 vp_reg_writemask(res, VP_ENABLE, val, VP_ENABLE_ON);
345 mixer_reg_writemask(res, MXR_CFG, val,
348 /* control blending of graphic layer 0 */
349 mixer_reg_writemask(res, MXR_GRAPHIC_CFG(0), val,
350 MXR_GRP_CFG_BLEND_PRE_MUL |
351 MXR_GRP_CFG_PIXEL_BLEND_EN);
357 static void mixer_run(struct mixer_context *ctx)
359 struct mixer_resources *res = &ctx->mixer_res;
361 mixer_reg_writemask(res, MXR_STATUS, ~0, MXR_STATUS_REG_RUN);
363 mixer_regs_dump(ctx);
366 static void mixer_stop(struct mixer_context *ctx)
368 struct mixer_resources *res = &ctx->mixer_res;
371 mixer_reg_writemask(res, MXR_STATUS, 0, MXR_STATUS_REG_RUN);
373 while (!(mixer_reg_read(res, MXR_STATUS) & MXR_STATUS_REG_IDLE) &&
375 usleep_range(10000, 12000);
377 mixer_regs_dump(ctx);
380 static void vp_video_buffer(struct mixer_context *ctx, int win)
382 struct mixer_resources *res = &ctx->mixer_res;
384 struct exynos_drm_plane *plane;
385 unsigned int buf_num = 1;
386 dma_addr_t luma_addr[2], chroma_addr[2];
387 bool tiled_mode = false;
388 bool crcb_mode = false;
391 plane = &ctx->planes[win];
393 switch (plane->pixel_format) {
394 case DRM_FORMAT_NV12:
398 /* TODO: single buffer format NV12, NV21 */
400 /* ignore pixel format at disable time */
401 if (!plane->dma_addr[0])
404 DRM_ERROR("pixel format for vp is wrong [%d].\n",
405 plane->pixel_format);
410 luma_addr[0] = plane->dma_addr[0];
411 chroma_addr[0] = plane->dma_addr[1];
413 luma_addr[0] = plane->dma_addr[0];
414 chroma_addr[0] = plane->dma_addr[0]
415 + (plane->pitch * plane->fb_height);
418 if (plane->scan_flag & DRM_MODE_FLAG_INTERLACE) {
419 ctx->interlace = true;
421 luma_addr[1] = luma_addr[0] + 0x40;
422 chroma_addr[1] = chroma_addr[0] + 0x40;
424 luma_addr[1] = luma_addr[0] + plane->pitch;
425 chroma_addr[1] = chroma_addr[0] + plane->pitch;
428 ctx->interlace = false;
433 spin_lock_irqsave(&res->reg_slock, flags);
434 mixer_vsync_set_update(ctx, false);
436 /* interlace or progressive scan mode */
437 val = (ctx->interlace ? ~0 : 0);
438 vp_reg_writemask(res, VP_MODE, val, VP_MODE_LINE_SKIP);
441 val = (crcb_mode ? VP_MODE_NV21 : VP_MODE_NV12);
442 val |= (tiled_mode ? VP_MODE_MEM_TILED : VP_MODE_MEM_LINEAR);
443 vp_reg_writemask(res, VP_MODE, val, VP_MODE_FMT_MASK);
445 /* setting size of input image */
446 vp_reg_write(res, VP_IMG_SIZE_Y, VP_IMG_HSIZE(plane->pitch) |
447 VP_IMG_VSIZE(plane->fb_height));
448 /* chroma height has to reduced by 2 to avoid chroma distorions */
449 vp_reg_write(res, VP_IMG_SIZE_C, VP_IMG_HSIZE(plane->pitch) |
450 VP_IMG_VSIZE(plane->fb_height / 2));
452 vp_reg_write(res, VP_SRC_WIDTH, plane->src_width);
453 vp_reg_write(res, VP_SRC_HEIGHT, plane->src_height);
454 vp_reg_write(res, VP_SRC_H_POSITION,
455 VP_SRC_H_POSITION_VAL(plane->src_x));
456 vp_reg_write(res, VP_SRC_V_POSITION, plane->src_y);
458 vp_reg_write(res, VP_DST_WIDTH, plane->crtc_width);
459 vp_reg_write(res, VP_DST_H_POSITION, plane->crtc_x);
460 if (ctx->interlace) {
461 vp_reg_write(res, VP_DST_HEIGHT, plane->crtc_height / 2);
462 vp_reg_write(res, VP_DST_V_POSITION, plane->crtc_y / 2);
464 vp_reg_write(res, VP_DST_HEIGHT, plane->crtc_height);
465 vp_reg_write(res, VP_DST_V_POSITION, plane->crtc_y);
468 vp_reg_write(res, VP_H_RATIO, plane->h_ratio);
469 vp_reg_write(res, VP_V_RATIO, plane->v_ratio);
471 vp_reg_write(res, VP_ENDIAN_MODE, VP_ENDIAN_MODE_LITTLE);
473 /* set buffer address to vp */
474 vp_reg_write(res, VP_TOP_Y_PTR, luma_addr[0]);
475 vp_reg_write(res, VP_BOT_Y_PTR, luma_addr[1]);
476 vp_reg_write(res, VP_TOP_C_PTR, chroma_addr[0]);
477 vp_reg_write(res, VP_BOT_C_PTR, chroma_addr[1]);
479 mixer_cfg_scan(ctx, plane->mode_height);
480 mixer_cfg_rgb_fmt(ctx, plane->mode_height);
481 mixer_cfg_layer(ctx, win, true);
484 mixer_vsync_set_update(ctx, true);
485 spin_unlock_irqrestore(&res->reg_slock, flags);
490 static void mixer_layer_update(struct mixer_context *ctx)
492 struct mixer_resources *res = &ctx->mixer_res;
494 mixer_reg_writemask(res, MXR_CFG, ~0, MXR_CFG_LAYER_UPDATE);
497 static int mixer_setup_scale(const struct exynos_drm_plane *plane,
498 unsigned int *x_ratio, unsigned int *y_ratio)
500 if (plane->crtc_width != plane->src_width) {
501 if (plane->crtc_width == 2 * plane->src_width)
507 if (plane->crtc_height != plane->src_height) {
508 if (plane->crtc_height == 2 * plane->src_height)
517 DRM_DEBUG_KMS("only 2x width/height scaling of plane supported\n");
521 static void mixer_graph_buffer(struct mixer_context *ctx, int win)
523 struct mixer_resources *res = &ctx->mixer_res;
525 struct exynos_drm_plane *plane;
526 unsigned int x_ratio = 0, y_ratio = 0;
527 unsigned int src_x_offset, src_y_offset, dst_x_offset, dst_y_offset;
532 plane = &ctx->planes[win];
539 switch (plane->bpp) {
550 /* check if mixer supports requested scaling setup */
551 if (mixer_setup_scale(plane, &x_ratio, &y_ratio))
554 dst_x_offset = plane->crtc_x;
555 dst_y_offset = plane->crtc_y;
557 /* converting dma address base and source offset */
558 dma_addr = plane->dma_addr[0]
559 + (plane->src_x * plane->bpp >> 3)
560 + (plane->src_y * plane->pitch);
564 if (plane->scan_flag & DRM_MODE_FLAG_INTERLACE)
565 ctx->interlace = true;
567 ctx->interlace = false;
569 spin_lock_irqsave(&res->reg_slock, flags);
570 mixer_vsync_set_update(ctx, false);
573 mixer_reg_writemask(res, MXR_GRAPHIC_CFG(win),
574 MXR_GRP_CFG_FORMAT_VAL(fmt), MXR_GRP_CFG_FORMAT_MASK);
577 mixer_reg_write(res, MXR_GRAPHIC_SPAN(win),
578 plane->pitch / (plane->bpp >> 3));
580 /* setup display size */
581 if (ctx->mxr_ver == MXR_VER_128_0_0_184 &&
582 win == MIXER_DEFAULT_WIN) {
583 val = MXR_MXR_RES_HEIGHT(plane->mode_height);
584 val |= MXR_MXR_RES_WIDTH(plane->mode_width);
585 mixer_reg_write(res, MXR_RESOLUTION, val);
588 val = MXR_GRP_WH_WIDTH(plane->src_width);
589 val |= MXR_GRP_WH_HEIGHT(plane->src_height);
590 val |= MXR_GRP_WH_H_SCALE(x_ratio);
591 val |= MXR_GRP_WH_V_SCALE(y_ratio);
592 mixer_reg_write(res, MXR_GRAPHIC_WH(win), val);
594 /* setup offsets in source image */
595 val = MXR_GRP_SXY_SX(src_x_offset);
596 val |= MXR_GRP_SXY_SY(src_y_offset);
597 mixer_reg_write(res, MXR_GRAPHIC_SXY(win), val);
599 /* setup offsets in display image */
600 val = MXR_GRP_DXY_DX(dst_x_offset);
601 val |= MXR_GRP_DXY_DY(dst_y_offset);
602 mixer_reg_write(res, MXR_GRAPHIC_DXY(win), val);
604 /* set buffer address to mixer */
605 mixer_reg_write(res, MXR_GRAPHIC_BASE(win), dma_addr);
607 mixer_cfg_scan(ctx, plane->mode_height);
608 mixer_cfg_rgb_fmt(ctx, plane->mode_height);
609 mixer_cfg_layer(ctx, win, true);
611 /* layer update mandatory for mixer 16.0.33.0 */
612 if (ctx->mxr_ver == MXR_VER_16_0_33_0 ||
613 ctx->mxr_ver == MXR_VER_128_0_0_184)
614 mixer_layer_update(ctx);
618 mixer_vsync_set_update(ctx, true);
619 spin_unlock_irqrestore(&res->reg_slock, flags);
622 static void vp_win_reset(struct mixer_context *ctx)
624 struct mixer_resources *res = &ctx->mixer_res;
627 vp_reg_write(res, VP_SRESET, VP_SRESET_PROCESSING);
628 for (tries = 100; tries; --tries) {
629 /* waiting until VP_SRESET_PROCESSING is 0 */
630 if (~vp_reg_read(res, VP_SRESET) & VP_SRESET_PROCESSING)
632 usleep_range(10000, 12000);
634 WARN(tries == 0, "failed to reset Video Processor\n");
637 static void mixer_win_reset(struct mixer_context *ctx)
639 struct mixer_resources *res = &ctx->mixer_res;
641 u32 val; /* value stored to register */
643 spin_lock_irqsave(&res->reg_slock, flags);
644 mixer_vsync_set_update(ctx, false);
646 mixer_reg_writemask(res, MXR_CFG, MXR_CFG_DST_HDMI, MXR_CFG_DST_MASK);
648 /* set output in RGB888 mode */
649 mixer_reg_writemask(res, MXR_CFG, MXR_CFG_OUT_RGB888, MXR_CFG_OUT_MASK);
651 /* 16 beat burst in DMA */
652 mixer_reg_writemask(res, MXR_STATUS, MXR_STATUS_16_BURST,
653 MXR_STATUS_BURST_MASK);
655 /* setting default layer priority: layer1 > layer0 > video
656 * because typical usage scenario would be
658 * layer0 - framebuffer
659 * video - video overlay
661 val = MXR_LAYER_CFG_GRP1_VAL(3);
662 val |= MXR_LAYER_CFG_GRP0_VAL(2);
664 val |= MXR_LAYER_CFG_VP_VAL(1);
665 mixer_reg_write(res, MXR_LAYER_CFG, val);
667 /* setting background color */
668 mixer_reg_write(res, MXR_BG_COLOR0, 0x008080);
669 mixer_reg_write(res, MXR_BG_COLOR1, 0x008080);
670 mixer_reg_write(res, MXR_BG_COLOR2, 0x008080);
672 /* setting graphical layers */
673 val = MXR_GRP_CFG_COLOR_KEY_DISABLE; /* no blank key */
674 val |= MXR_GRP_CFG_WIN_BLEND_EN;
675 val |= MXR_GRP_CFG_ALPHA_VAL(0xff); /* non-transparent alpha */
677 /* Don't blend layer 0 onto the mixer background */
678 mixer_reg_write(res, MXR_GRAPHIC_CFG(0), val);
680 /* Blend layer 1 into layer 0 */
681 val |= MXR_GRP_CFG_BLEND_PRE_MUL;
682 val |= MXR_GRP_CFG_PIXEL_BLEND_EN;
683 mixer_reg_write(res, MXR_GRAPHIC_CFG(1), val);
685 /* setting video layers */
686 val = MXR_GRP_CFG_ALPHA_VAL(0);
687 mixer_reg_write(res, MXR_VIDEO_CFG, val);
689 if (ctx->vp_enabled) {
690 /* configuration of Video Processor Registers */
692 vp_default_filter(res);
695 /* disable all layers */
696 mixer_reg_writemask(res, MXR_CFG, 0, MXR_CFG_GRP0_ENABLE);
697 mixer_reg_writemask(res, MXR_CFG, 0, MXR_CFG_GRP1_ENABLE);
699 mixer_reg_writemask(res, MXR_CFG, 0, MXR_CFG_VP_ENABLE);
701 mixer_vsync_set_update(ctx, true);
702 spin_unlock_irqrestore(&res->reg_slock, flags);
705 static irqreturn_t mixer_irq_handler(int irq, void *arg)
707 struct mixer_context *ctx = arg;
708 struct mixer_resources *res = &ctx->mixer_res;
709 u32 val, base, shadow;
711 spin_lock(&res->reg_slock);
713 /* read interrupt status for handling and clearing flags for VSYNC */
714 val = mixer_reg_read(res, MXR_INT_STATUS);
717 if (val & MXR_INT_STATUS_VSYNC) {
718 /* interlace scan need to check shadow register */
719 if (ctx->interlace) {
720 base = mixer_reg_read(res, MXR_GRAPHIC_BASE(0));
721 shadow = mixer_reg_read(res, MXR_GRAPHIC_BASE_S(0));
725 base = mixer_reg_read(res, MXR_GRAPHIC_BASE(1));
726 shadow = mixer_reg_read(res, MXR_GRAPHIC_BASE_S(1));
731 drm_handle_vblank(ctx->drm_dev, ctx->pipe);
732 exynos_drm_crtc_finish_pageflip(ctx->drm_dev, ctx->pipe);
734 /* set wait vsync event to zero and wake up queue. */
735 if (atomic_read(&ctx->wait_vsync_event)) {
736 atomic_set(&ctx->wait_vsync_event, 0);
737 wake_up(&ctx->wait_vsync_queue);
742 /* clear interrupts */
743 if (~val & MXR_INT_EN_VSYNC) {
744 /* vsync interrupt use different bit for read and clear */
745 val &= ~MXR_INT_EN_VSYNC;
746 val |= MXR_INT_CLEAR_VSYNC;
748 mixer_reg_write(res, MXR_INT_STATUS, val);
750 spin_unlock(&res->reg_slock);
755 static int mixer_resources_init(struct mixer_context *mixer_ctx)
757 struct device *dev = &mixer_ctx->pdev->dev;
758 struct mixer_resources *mixer_res = &mixer_ctx->mixer_res;
759 struct resource *res;
762 spin_lock_init(&mixer_res->reg_slock);
764 mixer_res->mixer = devm_clk_get(dev, "mixer");
765 if (IS_ERR(mixer_res->mixer)) {
766 dev_err(dev, "failed to get clock 'mixer'\n");
770 mixer_res->hdmi = devm_clk_get(dev, "hdmi");
771 if (IS_ERR(mixer_res->hdmi)) {
772 dev_err(dev, "failed to get clock 'hdmi'\n");
773 return PTR_ERR(mixer_res->hdmi);
776 mixer_res->sclk_hdmi = devm_clk_get(dev, "sclk_hdmi");
777 if (IS_ERR(mixer_res->sclk_hdmi)) {
778 dev_err(dev, "failed to get clock 'sclk_hdmi'\n");
781 res = platform_get_resource(mixer_ctx->pdev, IORESOURCE_MEM, 0);
783 dev_err(dev, "get memory resource failed.\n");
787 mixer_res->mixer_regs = devm_ioremap(dev, res->start,
789 if (mixer_res->mixer_regs == NULL) {
790 dev_err(dev, "register mapping failed.\n");
794 res = platform_get_resource(mixer_ctx->pdev, IORESOURCE_IRQ, 0);
796 dev_err(dev, "get interrupt resource failed.\n");
800 ret = devm_request_irq(dev, res->start, mixer_irq_handler,
801 0, "drm_mixer", mixer_ctx);
803 dev_err(dev, "request interrupt failed.\n");
806 mixer_res->irq = res->start;
811 static int vp_resources_init(struct mixer_context *mixer_ctx)
813 struct device *dev = &mixer_ctx->pdev->dev;
814 struct mixer_resources *mixer_res = &mixer_ctx->mixer_res;
815 struct resource *res;
817 mixer_res->vp = devm_clk_get(dev, "vp");
818 if (IS_ERR(mixer_res->vp)) {
819 dev_err(dev, "failed to get clock 'vp'\n");
823 if (mixer_ctx->has_sclk) {
824 mixer_res->sclk_mixer = devm_clk_get(dev, "sclk_mixer");
825 if (IS_ERR(mixer_res->sclk_mixer)) {
826 dev_err(dev, "failed to get clock 'sclk_mixer'\n");
829 mixer_res->mout_mixer = devm_clk_get(dev, "mout_mixer");
830 if (IS_ERR(mixer_res->mout_mixer)) {
831 dev_err(dev, "failed to get clock 'mout_mixer'\n");
835 if (mixer_res->sclk_hdmi && mixer_res->mout_mixer)
836 clk_set_parent(mixer_res->mout_mixer,
837 mixer_res->sclk_hdmi);
840 res = platform_get_resource(mixer_ctx->pdev, IORESOURCE_MEM, 1);
842 dev_err(dev, "get memory resource failed.\n");
846 mixer_res->vp_regs = devm_ioremap(dev, res->start,
848 if (mixer_res->vp_regs == NULL) {
849 dev_err(dev, "register mapping failed.\n");
856 static int mixer_initialize(struct mixer_context *mixer_ctx,
857 struct drm_device *drm_dev)
860 struct exynos_drm_private *priv;
861 priv = drm_dev->dev_private;
863 mixer_ctx->drm_dev = drm_dev;
864 mixer_ctx->pipe = priv->pipe++;
866 /* acquire resources: regs, irqs, clocks */
867 ret = mixer_resources_init(mixer_ctx);
869 DRM_ERROR("mixer_resources_init failed ret=%d\n", ret);
873 if (mixer_ctx->vp_enabled) {
874 /* acquire vp resources: regs, irqs, clocks */
875 ret = vp_resources_init(mixer_ctx);
877 DRM_ERROR("vp_resources_init failed ret=%d\n", ret);
882 if (!is_drm_iommu_supported(mixer_ctx->drm_dev))
885 return drm_iommu_attach_device(mixer_ctx->drm_dev, mixer_ctx->dev);
888 static void mixer_ctx_remove(struct mixer_context *mixer_ctx)
890 if (is_drm_iommu_supported(mixer_ctx->drm_dev))
891 drm_iommu_detach_device(mixer_ctx->drm_dev, mixer_ctx->dev);
894 static int mixer_enable_vblank(struct exynos_drm_crtc *crtc)
896 struct mixer_context *mixer_ctx = crtc->ctx;
897 struct mixer_resources *res = &mixer_ctx->mixer_res;
899 if (!mixer_ctx->powered) {
900 mixer_ctx->int_en |= MXR_INT_EN_VSYNC;
904 /* enable vsync interrupt */
905 mixer_reg_writemask(res, MXR_INT_EN, MXR_INT_EN_VSYNC,
911 static void mixer_disable_vblank(struct exynos_drm_crtc *crtc)
913 struct mixer_context *mixer_ctx = crtc->ctx;
914 struct mixer_resources *res = &mixer_ctx->mixer_res;
916 /* disable vsync interrupt */
917 mixer_reg_writemask(res, MXR_INT_EN, 0, MXR_INT_EN_VSYNC);
920 static void mixer_win_commit(struct exynos_drm_crtc *crtc, unsigned int win)
922 struct mixer_context *mixer_ctx = crtc->ctx;
924 DRM_DEBUG_KMS("win: %d\n", win);
926 mutex_lock(&mixer_ctx->mixer_mutex);
927 if (!mixer_ctx->powered) {
928 mutex_unlock(&mixer_ctx->mixer_mutex);
931 mutex_unlock(&mixer_ctx->mixer_mutex);
933 if (win > 1 && mixer_ctx->vp_enabled)
934 vp_video_buffer(mixer_ctx, win);
936 mixer_graph_buffer(mixer_ctx, win);
938 mixer_ctx->planes[win].enabled = true;
941 static void mixer_win_disable(struct exynos_drm_crtc *crtc, unsigned int win)
943 struct mixer_context *mixer_ctx = crtc->ctx;
944 struct mixer_resources *res = &mixer_ctx->mixer_res;
947 DRM_DEBUG_KMS("win: %d\n", win);
949 mutex_lock(&mixer_ctx->mixer_mutex);
950 if (!mixer_ctx->powered) {
951 mutex_unlock(&mixer_ctx->mixer_mutex);
952 mixer_ctx->planes[win].resume = false;
955 mutex_unlock(&mixer_ctx->mixer_mutex);
957 spin_lock_irqsave(&res->reg_slock, flags);
958 mixer_vsync_set_update(mixer_ctx, false);
960 mixer_cfg_layer(mixer_ctx, win, false);
962 mixer_vsync_set_update(mixer_ctx, true);
963 spin_unlock_irqrestore(&res->reg_slock, flags);
965 mixer_ctx->planes[win].enabled = false;
968 static void mixer_wait_for_vblank(struct exynos_drm_crtc *crtc)
970 struct mixer_context *mixer_ctx = crtc->ctx;
973 mutex_lock(&mixer_ctx->mixer_mutex);
974 if (!mixer_ctx->powered) {
975 mutex_unlock(&mixer_ctx->mixer_mutex);
978 mutex_unlock(&mixer_ctx->mixer_mutex);
980 err = drm_vblank_get(mixer_ctx->drm_dev, mixer_ctx->pipe);
982 DRM_DEBUG_KMS("failed to acquire vblank counter\n");
986 atomic_set(&mixer_ctx->wait_vsync_event, 1);
989 * wait for MIXER to signal VSYNC interrupt or return after
990 * timeout which is set to 50ms (refresh rate of 20).
992 if (!wait_event_timeout(mixer_ctx->wait_vsync_queue,
993 !atomic_read(&mixer_ctx->wait_vsync_event),
995 DRM_DEBUG_KMS("vblank wait timed out.\n");
997 drm_vblank_put(mixer_ctx->drm_dev, mixer_ctx->pipe);
1000 static void mixer_window_suspend(struct mixer_context *ctx)
1002 struct exynos_drm_plane *plane;
1005 for (i = 0; i < MIXER_WIN_NR; i++) {
1006 plane = &ctx->planes[i];
1007 plane->resume = plane->enabled;
1008 mixer_win_disable(ctx->crtc, i);
1010 mixer_wait_for_vblank(ctx->crtc);
1013 static void mixer_window_resume(struct mixer_context *ctx)
1015 struct exynos_drm_plane *plane;
1018 for (i = 0; i < MIXER_WIN_NR; i++) {
1019 plane = &ctx->planes[i];
1020 plane->enabled = plane->resume;
1021 plane->resume = false;
1023 mixer_win_commit(ctx->crtc, i);
1027 static void mixer_poweron(struct mixer_context *ctx)
1029 struct mixer_resources *res = &ctx->mixer_res;
1031 mutex_lock(&ctx->mixer_mutex);
1033 mutex_unlock(&ctx->mixer_mutex);
1037 mutex_unlock(&ctx->mixer_mutex);
1039 pm_runtime_get_sync(ctx->dev);
1041 clk_prepare_enable(res->mixer);
1042 clk_prepare_enable(res->hdmi);
1043 if (ctx->vp_enabled) {
1044 clk_prepare_enable(res->vp);
1046 clk_prepare_enable(res->sclk_mixer);
1049 mutex_lock(&ctx->mixer_mutex);
1050 ctx->powered = true;
1051 mutex_unlock(&ctx->mixer_mutex);
1053 mixer_reg_writemask(res, MXR_STATUS, ~0, MXR_STATUS_SOFT_RESET);
1055 mixer_reg_write(res, MXR_INT_EN, ctx->int_en);
1056 mixer_win_reset(ctx);
1058 mixer_window_resume(ctx);
1061 static void mixer_poweroff(struct mixer_context *ctx)
1063 struct mixer_resources *res = &ctx->mixer_res;
1065 mutex_lock(&ctx->mixer_mutex);
1066 if (!ctx->powered) {
1067 mutex_unlock(&ctx->mixer_mutex);
1070 mutex_unlock(&ctx->mixer_mutex);
1073 mixer_window_suspend(ctx);
1075 ctx->int_en = mixer_reg_read(res, MXR_INT_EN);
1077 mutex_lock(&ctx->mixer_mutex);
1078 ctx->powered = false;
1079 mutex_unlock(&ctx->mixer_mutex);
1081 clk_disable_unprepare(res->hdmi);
1082 clk_disable_unprepare(res->mixer);
1083 if (ctx->vp_enabled) {
1084 clk_disable_unprepare(res->vp);
1086 clk_disable_unprepare(res->sclk_mixer);
1089 pm_runtime_put_sync(ctx->dev);
1092 static void mixer_dpms(struct exynos_drm_crtc *crtc, int mode)
1095 case DRM_MODE_DPMS_ON:
1096 mixer_poweron(crtc->ctx);
1098 case DRM_MODE_DPMS_STANDBY:
1099 case DRM_MODE_DPMS_SUSPEND:
1100 case DRM_MODE_DPMS_OFF:
1101 mixer_poweroff(crtc->ctx);
1104 DRM_DEBUG_KMS("unknown dpms mode: %d\n", mode);
1109 /* Only valid for Mixer version 16.0.33.0 */
1110 int mixer_check_mode(struct drm_display_mode *mode)
1117 DRM_DEBUG_KMS("xres=%d, yres=%d, refresh=%d, intl=%d\n",
1118 mode->hdisplay, mode->vdisplay, mode->vrefresh,
1119 (mode->flags & DRM_MODE_FLAG_INTERLACE) ? 1 : 0);
1121 if ((w >= 464 && w <= 720 && h >= 261 && h <= 576) ||
1122 (w >= 1024 && w <= 1280 && h >= 576 && h <= 720) ||
1123 (w >= 1664 && w <= 1920 && h >= 936 && h <= 1080))
1129 static struct exynos_drm_crtc_ops mixer_crtc_ops = {
1131 .enable_vblank = mixer_enable_vblank,
1132 .disable_vblank = mixer_disable_vblank,
1133 .wait_for_vblank = mixer_wait_for_vblank,
1134 .win_commit = mixer_win_commit,
1135 .win_disable = mixer_win_disable,
1138 static struct mixer_drv_data exynos5420_mxr_drv_data = {
1139 .version = MXR_VER_128_0_0_184,
1143 static struct mixer_drv_data exynos5250_mxr_drv_data = {
1144 .version = MXR_VER_16_0_33_0,
1148 static struct mixer_drv_data exynos4212_mxr_drv_data = {
1149 .version = MXR_VER_0_0_0_16,
1153 static struct mixer_drv_data exynos4210_mxr_drv_data = {
1154 .version = MXR_VER_0_0_0_16,
1159 static struct platform_device_id mixer_driver_types[] = {
1161 .name = "s5p-mixer",
1162 .driver_data = (unsigned long)&exynos4210_mxr_drv_data,
1164 .name = "exynos5-mixer",
1165 .driver_data = (unsigned long)&exynos5250_mxr_drv_data,
1171 static struct of_device_id mixer_match_types[] = {
1173 .compatible = "samsung,exynos4210-mixer",
1174 .data = &exynos4210_mxr_drv_data,
1176 .compatible = "samsung,exynos4212-mixer",
1177 .data = &exynos4212_mxr_drv_data,
1179 .compatible = "samsung,exynos5-mixer",
1180 .data = &exynos5250_mxr_drv_data,
1182 .compatible = "samsung,exynos5250-mixer",
1183 .data = &exynos5250_mxr_drv_data,
1185 .compatible = "samsung,exynos5420-mixer",
1186 .data = &exynos5420_mxr_drv_data,
1191 MODULE_DEVICE_TABLE(of, mixer_match_types);
1193 static int mixer_bind(struct device *dev, struct device *manager, void *data)
1195 struct mixer_context *ctx = dev_get_drvdata(dev);
1196 struct drm_device *drm_dev = data;
1197 struct exynos_drm_plane *exynos_plane;
1198 enum drm_plane_type type;
1202 ret = mixer_initialize(ctx, drm_dev);
1206 for (zpos = 0; zpos < MIXER_WIN_NR; zpos++) {
1207 type = (zpos == MIXER_DEFAULT_WIN) ? DRM_PLANE_TYPE_PRIMARY :
1208 DRM_PLANE_TYPE_OVERLAY;
1209 ret = exynos_plane_init(drm_dev, &ctx->planes[zpos],
1210 1 << ctx->pipe, type, zpos);
1215 exynos_plane = &ctx->planes[MIXER_DEFAULT_WIN];
1216 ctx->crtc = exynos_drm_crtc_create(drm_dev, &exynos_plane->base,
1217 ctx->pipe, EXYNOS_DISPLAY_TYPE_HDMI,
1218 &mixer_crtc_ops, ctx);
1219 if (IS_ERR(ctx->crtc)) {
1220 mixer_ctx_remove(ctx);
1221 ret = PTR_ERR(ctx->crtc);
1228 devm_kfree(dev, ctx);
1232 static void mixer_unbind(struct device *dev, struct device *master, void *data)
1234 struct mixer_context *ctx = dev_get_drvdata(dev);
1236 mixer_ctx_remove(ctx);
1239 static const struct component_ops mixer_component_ops = {
1241 .unbind = mixer_unbind,
1244 static int mixer_probe(struct platform_device *pdev)
1246 struct device *dev = &pdev->dev;
1247 struct mixer_drv_data *drv;
1248 struct mixer_context *ctx;
1251 ctx = devm_kzalloc(&pdev->dev, sizeof(*ctx), GFP_KERNEL);
1253 DRM_ERROR("failed to alloc mixer context.\n");
1257 mutex_init(&ctx->mixer_mutex);
1260 const struct of_device_id *match;
1262 match = of_match_node(mixer_match_types, dev->of_node);
1263 drv = (struct mixer_drv_data *)match->data;
1265 drv = (struct mixer_drv_data *)
1266 platform_get_device_id(pdev)->driver_data;
1271 ctx->vp_enabled = drv->is_vp_enabled;
1272 ctx->has_sclk = drv->has_sclk;
1273 ctx->mxr_ver = drv->version;
1274 init_waitqueue_head(&ctx->wait_vsync_queue);
1275 atomic_set(&ctx->wait_vsync_event, 0);
1277 platform_set_drvdata(pdev, ctx);
1279 ret = exynos_drm_component_add(&pdev->dev, EXYNOS_DEVICE_TYPE_CRTC,
1280 EXYNOS_DISPLAY_TYPE_HDMI);
1284 ret = component_add(&pdev->dev, &mixer_component_ops);
1286 exynos_drm_component_del(&pdev->dev, EXYNOS_DEVICE_TYPE_CRTC);
1290 pm_runtime_enable(dev);
1295 static int mixer_remove(struct platform_device *pdev)
1297 pm_runtime_disable(&pdev->dev);
1299 component_del(&pdev->dev, &mixer_component_ops);
1300 exynos_drm_component_del(&pdev->dev, EXYNOS_DEVICE_TYPE_CRTC);
1305 struct platform_driver mixer_driver = {
1307 .name = "exynos-mixer",
1308 .owner = THIS_MODULE,
1309 .of_match_table = mixer_match_types,
1311 .probe = mixer_probe,
1312 .remove = mixer_remove,
1313 .id_table = mixer_driver_types,