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_iommu.h"
41 #include "exynos_mixer.h"
43 #define MIXER_WIN_NR 3
44 #define MIXER_DEFAULT_WIN 0
46 struct hdmi_win_data {
48 dma_addr_t chroma_dma_addr;
49 uint32_t pixel_format;
53 unsigned int crtc_width;
54 unsigned int crtc_height;
57 unsigned int fb_width;
58 unsigned int fb_height;
59 unsigned int src_width;
60 unsigned int src_height;
61 unsigned int mode_width;
62 unsigned int mode_height;
63 unsigned int scan_flags;
68 struct mixer_resources {
70 void __iomem *mixer_regs;
71 void __iomem *vp_regs;
75 struct clk *sclk_mixer;
76 struct clk *sclk_hdmi;
77 struct clk *mout_mixer;
80 enum mixer_version_id {
86 struct mixer_context {
87 struct exynos_drm_manager manager;
88 struct platform_device *pdev;
90 struct drm_device *drm_dev;
98 struct mutex mixer_mutex;
99 struct mixer_resources mixer_res;
100 struct hdmi_win_data win_data[MIXER_WIN_NR];
101 enum mixer_version_id mxr_ver;
102 wait_queue_head_t wait_vsync_queue;
103 atomic_t wait_vsync_event;
106 static inline struct mixer_context *mgr_to_mixer(struct exynos_drm_manager *mgr)
108 return container_of(mgr, struct mixer_context, manager);
111 struct mixer_drv_data {
112 enum mixer_version_id version;
117 static const u8 filter_y_horiz_tap8[] = {
118 0, -1, -1, -1, -1, -1, -1, -1,
119 -1, -1, -1, -1, -1, 0, 0, 0,
120 0, 2, 4, 5, 6, 6, 6, 6,
121 6, 5, 5, 4, 3, 2, 1, 1,
122 0, -6, -12, -16, -18, -20, -21, -20,
123 -20, -18, -16, -13, -10, -8, -5, -2,
124 127, 126, 125, 121, 114, 107, 99, 89,
125 79, 68, 57, 46, 35, 25, 16, 8,
128 static const u8 filter_y_vert_tap4[] = {
129 0, -3, -6, -8, -8, -8, -8, -7,
130 -6, -5, -4, -3, -2, -1, -1, 0,
131 127, 126, 124, 118, 111, 102, 92, 81,
132 70, 59, 48, 37, 27, 19, 11, 5,
133 0, 5, 11, 19, 27, 37, 48, 59,
134 70, 81, 92, 102, 111, 118, 124, 126,
135 0, 0, -1, -1, -2, -3, -4, -5,
136 -6, -7, -8, -8, -8, -8, -6, -3,
139 static const u8 filter_cr_horiz_tap4[] = {
140 0, -3, -6, -8, -8, -8, -8, -7,
141 -6, -5, -4, -3, -2, -1, -1, 0,
142 127, 126, 124, 118, 111, 102, 92, 81,
143 70, 59, 48, 37, 27, 19, 11, 5,
146 static inline u32 vp_reg_read(struct mixer_resources *res, u32 reg_id)
148 return readl(res->vp_regs + reg_id);
151 static inline void vp_reg_write(struct mixer_resources *res, u32 reg_id,
154 writel(val, res->vp_regs + reg_id);
157 static inline void vp_reg_writemask(struct mixer_resources *res, u32 reg_id,
160 u32 old = vp_reg_read(res, reg_id);
162 val = (val & mask) | (old & ~mask);
163 writel(val, res->vp_regs + reg_id);
166 static inline u32 mixer_reg_read(struct mixer_resources *res, u32 reg_id)
168 return readl(res->mixer_regs + reg_id);
171 static inline void mixer_reg_write(struct mixer_resources *res, u32 reg_id,
174 writel(val, res->mixer_regs + reg_id);
177 static inline void mixer_reg_writemask(struct mixer_resources *res,
178 u32 reg_id, u32 val, u32 mask)
180 u32 old = mixer_reg_read(res, reg_id);
182 val = (val & mask) | (old & ~mask);
183 writel(val, res->mixer_regs + reg_id);
186 static void mixer_regs_dump(struct mixer_context *ctx)
188 #define DUMPREG(reg_id) \
190 DRM_DEBUG_KMS(#reg_id " = %08x\n", \
191 (u32)readl(ctx->mixer_res.mixer_regs + reg_id)); \
197 DUMPREG(MXR_INT_STATUS);
199 DUMPREG(MXR_LAYER_CFG);
200 DUMPREG(MXR_VIDEO_CFG);
202 DUMPREG(MXR_GRAPHIC0_CFG);
203 DUMPREG(MXR_GRAPHIC0_BASE);
204 DUMPREG(MXR_GRAPHIC0_SPAN);
205 DUMPREG(MXR_GRAPHIC0_WH);
206 DUMPREG(MXR_GRAPHIC0_SXY);
207 DUMPREG(MXR_GRAPHIC0_DXY);
209 DUMPREG(MXR_GRAPHIC1_CFG);
210 DUMPREG(MXR_GRAPHIC1_BASE);
211 DUMPREG(MXR_GRAPHIC1_SPAN);
212 DUMPREG(MXR_GRAPHIC1_WH);
213 DUMPREG(MXR_GRAPHIC1_SXY);
214 DUMPREG(MXR_GRAPHIC1_DXY);
218 static void vp_regs_dump(struct mixer_context *ctx)
220 #define DUMPREG(reg_id) \
222 DRM_DEBUG_KMS(#reg_id " = %08x\n", \
223 (u32) readl(ctx->mixer_res.vp_regs + reg_id)); \
228 DUMPREG(VP_SHADOW_UPDATE);
229 DUMPREG(VP_FIELD_ID);
231 DUMPREG(VP_IMG_SIZE_Y);
232 DUMPREG(VP_IMG_SIZE_C);
233 DUMPREG(VP_PER_RATE_CTRL);
234 DUMPREG(VP_TOP_Y_PTR);
235 DUMPREG(VP_BOT_Y_PTR);
236 DUMPREG(VP_TOP_C_PTR);
237 DUMPREG(VP_BOT_C_PTR);
238 DUMPREG(VP_ENDIAN_MODE);
239 DUMPREG(VP_SRC_H_POSITION);
240 DUMPREG(VP_SRC_V_POSITION);
241 DUMPREG(VP_SRC_WIDTH);
242 DUMPREG(VP_SRC_HEIGHT);
243 DUMPREG(VP_DST_H_POSITION);
244 DUMPREG(VP_DST_V_POSITION);
245 DUMPREG(VP_DST_WIDTH);
246 DUMPREG(VP_DST_HEIGHT);
253 static inline void vp_filter_set(struct mixer_resources *res,
254 int reg_id, const u8 *data, unsigned int size)
256 /* assure 4-byte align */
258 for (; size; size -= 4, reg_id += 4, data += 4) {
259 u32 val = (data[0] << 24) | (data[1] << 16) |
260 (data[2] << 8) | data[3];
261 vp_reg_write(res, reg_id, val);
265 static void vp_default_filter(struct mixer_resources *res)
267 vp_filter_set(res, VP_POLY8_Y0_LL,
268 filter_y_horiz_tap8, sizeof(filter_y_horiz_tap8));
269 vp_filter_set(res, VP_POLY4_Y0_LL,
270 filter_y_vert_tap4, sizeof(filter_y_vert_tap4));
271 vp_filter_set(res, VP_POLY4_C0_LL,
272 filter_cr_horiz_tap4, sizeof(filter_cr_horiz_tap4));
275 static void mixer_vsync_set_update(struct mixer_context *ctx, bool enable)
277 struct mixer_resources *res = &ctx->mixer_res;
279 /* block update on vsync */
280 mixer_reg_writemask(res, MXR_STATUS, enable ?
281 MXR_STATUS_SYNC_ENABLE : 0, MXR_STATUS_SYNC_ENABLE);
284 vp_reg_write(res, VP_SHADOW_UPDATE, enable ?
285 VP_SHADOW_UPDATE_ENABLE : 0);
288 static void mixer_cfg_scan(struct mixer_context *ctx, unsigned int height)
290 struct mixer_resources *res = &ctx->mixer_res;
293 /* choosing between interlace and progressive mode */
294 val = (ctx->interlace ? MXR_CFG_SCAN_INTERLACE :
295 MXR_CFG_SCAN_PROGRASSIVE);
297 if (ctx->mxr_ver != MXR_VER_128_0_0_184) {
298 /* choosing between proper HD and SD mode */
300 val |= MXR_CFG_SCAN_NTSC | MXR_CFG_SCAN_SD;
301 else if (height <= 576)
302 val |= MXR_CFG_SCAN_PAL | MXR_CFG_SCAN_SD;
303 else if (height <= 720)
304 val |= MXR_CFG_SCAN_HD_720 | MXR_CFG_SCAN_HD;
305 else if (height <= 1080)
306 val |= MXR_CFG_SCAN_HD_1080 | MXR_CFG_SCAN_HD;
308 val |= MXR_CFG_SCAN_HD_720 | MXR_CFG_SCAN_HD;
311 mixer_reg_writemask(res, MXR_CFG, val, MXR_CFG_SCAN_MASK);
314 static void mixer_cfg_rgb_fmt(struct mixer_context *ctx, unsigned int height)
316 struct mixer_resources *res = &ctx->mixer_res;
320 val = MXR_CFG_RGB601_0_255;
321 } else if (height == 576) {
322 val = MXR_CFG_RGB601_0_255;
323 } else if (height == 720) {
324 val = MXR_CFG_RGB709_16_235;
325 mixer_reg_write(res, MXR_CM_COEFF_Y,
326 (1 << 30) | (94 << 20) | (314 << 10) |
328 mixer_reg_write(res, MXR_CM_COEFF_CB,
329 (972 << 20) | (851 << 10) | (225 << 0));
330 mixer_reg_write(res, MXR_CM_COEFF_CR,
331 (225 << 20) | (820 << 10) | (1004 << 0));
332 } else if (height == 1080) {
333 val = MXR_CFG_RGB709_16_235;
334 mixer_reg_write(res, MXR_CM_COEFF_Y,
335 (1 << 30) | (94 << 20) | (314 << 10) |
337 mixer_reg_write(res, MXR_CM_COEFF_CB,
338 (972 << 20) | (851 << 10) | (225 << 0));
339 mixer_reg_write(res, MXR_CM_COEFF_CR,
340 (225 << 20) | (820 << 10) | (1004 << 0));
342 val = MXR_CFG_RGB709_16_235;
343 mixer_reg_write(res, MXR_CM_COEFF_Y,
344 (1 << 30) | (94 << 20) | (314 << 10) |
346 mixer_reg_write(res, MXR_CM_COEFF_CB,
347 (972 << 20) | (851 << 10) | (225 << 0));
348 mixer_reg_write(res, MXR_CM_COEFF_CR,
349 (225 << 20) | (820 << 10) | (1004 << 0));
352 mixer_reg_writemask(res, MXR_CFG, val, MXR_CFG_RGB_FMT_MASK);
355 static void mixer_cfg_layer(struct mixer_context *ctx, int win, bool enable)
357 struct mixer_resources *res = &ctx->mixer_res;
358 u32 val = enable ? ~0 : 0;
362 mixer_reg_writemask(res, MXR_CFG, val, MXR_CFG_GRP0_ENABLE);
365 mixer_reg_writemask(res, MXR_CFG, val, MXR_CFG_GRP1_ENABLE);
368 if (ctx->vp_enabled) {
369 vp_reg_writemask(res, VP_ENABLE, val, VP_ENABLE_ON);
370 mixer_reg_writemask(res, MXR_CFG, val,
373 /* control blending of graphic layer 0 */
374 mixer_reg_writemask(res, MXR_GRAPHIC_CFG(0), val,
375 MXR_GRP_CFG_BLEND_PRE_MUL |
376 MXR_GRP_CFG_PIXEL_BLEND_EN);
382 static void mixer_run(struct mixer_context *ctx)
384 struct mixer_resources *res = &ctx->mixer_res;
386 mixer_reg_writemask(res, MXR_STATUS, ~0, MXR_STATUS_REG_RUN);
388 mixer_regs_dump(ctx);
391 static void mixer_stop(struct mixer_context *ctx)
393 struct mixer_resources *res = &ctx->mixer_res;
396 mixer_reg_writemask(res, MXR_STATUS, 0, MXR_STATUS_REG_RUN);
398 while (!(mixer_reg_read(res, MXR_STATUS) & MXR_STATUS_REG_IDLE) &&
400 usleep_range(10000, 12000);
402 mixer_regs_dump(ctx);
405 static void vp_video_buffer(struct mixer_context *ctx, int win)
407 struct mixer_resources *res = &ctx->mixer_res;
409 struct hdmi_win_data *win_data;
410 unsigned int x_ratio, y_ratio;
411 unsigned int buf_num = 1;
412 dma_addr_t luma_addr[2], chroma_addr[2];
413 bool tiled_mode = false;
414 bool crcb_mode = false;
417 win_data = &ctx->win_data[win];
419 switch (win_data->pixel_format) {
420 case DRM_FORMAT_NV12MT:
422 case DRM_FORMAT_NV12:
426 /* TODO: single buffer format NV12, NV21 */
428 /* ignore pixel format at disable time */
429 if (!win_data->dma_addr)
432 DRM_ERROR("pixel format for vp is wrong [%d].\n",
433 win_data->pixel_format);
437 /* scaling feature: (src << 16) / dst */
438 x_ratio = (win_data->src_width << 16) / win_data->crtc_width;
439 y_ratio = (win_data->src_height << 16) / win_data->crtc_height;
442 luma_addr[0] = win_data->dma_addr;
443 chroma_addr[0] = win_data->chroma_dma_addr;
445 luma_addr[0] = win_data->dma_addr;
446 chroma_addr[0] = win_data->dma_addr
447 + (win_data->fb_width * win_data->fb_height);
450 if (win_data->scan_flags & DRM_MODE_FLAG_INTERLACE) {
451 ctx->interlace = true;
453 luma_addr[1] = luma_addr[0] + 0x40;
454 chroma_addr[1] = chroma_addr[0] + 0x40;
456 luma_addr[1] = luma_addr[0] + win_data->fb_width;
457 chroma_addr[1] = chroma_addr[0] + win_data->fb_width;
460 ctx->interlace = false;
465 spin_lock_irqsave(&res->reg_slock, flags);
466 mixer_vsync_set_update(ctx, false);
468 /* interlace or progressive scan mode */
469 val = (ctx->interlace ? ~0 : 0);
470 vp_reg_writemask(res, VP_MODE, val, VP_MODE_LINE_SKIP);
473 val = (crcb_mode ? VP_MODE_NV21 : VP_MODE_NV12);
474 val |= (tiled_mode ? VP_MODE_MEM_TILED : VP_MODE_MEM_LINEAR);
475 vp_reg_writemask(res, VP_MODE, val, VP_MODE_FMT_MASK);
477 /* setting size of input image */
478 vp_reg_write(res, VP_IMG_SIZE_Y, VP_IMG_HSIZE(win_data->fb_width) |
479 VP_IMG_VSIZE(win_data->fb_height));
480 /* chroma height has to reduced by 2 to avoid chroma distorions */
481 vp_reg_write(res, VP_IMG_SIZE_C, VP_IMG_HSIZE(win_data->fb_width) |
482 VP_IMG_VSIZE(win_data->fb_height / 2));
484 vp_reg_write(res, VP_SRC_WIDTH, win_data->src_width);
485 vp_reg_write(res, VP_SRC_HEIGHT, win_data->src_height);
486 vp_reg_write(res, VP_SRC_H_POSITION,
487 VP_SRC_H_POSITION_VAL(win_data->fb_x));
488 vp_reg_write(res, VP_SRC_V_POSITION, win_data->fb_y);
490 vp_reg_write(res, VP_DST_WIDTH, win_data->crtc_width);
491 vp_reg_write(res, VP_DST_H_POSITION, win_data->crtc_x);
492 if (ctx->interlace) {
493 vp_reg_write(res, VP_DST_HEIGHT, win_data->crtc_height / 2);
494 vp_reg_write(res, VP_DST_V_POSITION, win_data->crtc_y / 2);
496 vp_reg_write(res, VP_DST_HEIGHT, win_data->crtc_height);
497 vp_reg_write(res, VP_DST_V_POSITION, win_data->crtc_y);
500 vp_reg_write(res, VP_H_RATIO, x_ratio);
501 vp_reg_write(res, VP_V_RATIO, y_ratio);
503 vp_reg_write(res, VP_ENDIAN_MODE, VP_ENDIAN_MODE_LITTLE);
505 /* set buffer address to vp */
506 vp_reg_write(res, VP_TOP_Y_PTR, luma_addr[0]);
507 vp_reg_write(res, VP_BOT_Y_PTR, luma_addr[1]);
508 vp_reg_write(res, VP_TOP_C_PTR, chroma_addr[0]);
509 vp_reg_write(res, VP_BOT_C_PTR, chroma_addr[1]);
511 mixer_cfg_scan(ctx, win_data->mode_height);
512 mixer_cfg_rgb_fmt(ctx, win_data->mode_height);
513 mixer_cfg_layer(ctx, win, true);
516 mixer_vsync_set_update(ctx, true);
517 spin_unlock_irqrestore(&res->reg_slock, flags);
522 static void mixer_layer_update(struct mixer_context *ctx)
524 struct mixer_resources *res = &ctx->mixer_res;
526 mixer_reg_writemask(res, MXR_CFG, ~0, MXR_CFG_LAYER_UPDATE);
529 static void mixer_graph_buffer(struct mixer_context *ctx, int win)
531 struct mixer_resources *res = &ctx->mixer_res;
533 struct hdmi_win_data *win_data;
534 unsigned int x_ratio, y_ratio;
535 unsigned int src_x_offset, src_y_offset, dst_x_offset, dst_y_offset;
540 win_data = &ctx->win_data[win];
547 switch (win_data->bpp) {
558 /* 2x scaling feature */
562 dst_x_offset = win_data->crtc_x;
563 dst_y_offset = win_data->crtc_y;
565 /* converting dma address base and source offset */
566 dma_addr = win_data->dma_addr
567 + (win_data->fb_x * win_data->bpp >> 3)
568 + (win_data->fb_y * win_data->fb_width * win_data->bpp >> 3);
572 if (win_data->scan_flags & DRM_MODE_FLAG_INTERLACE)
573 ctx->interlace = true;
575 ctx->interlace = false;
577 spin_lock_irqsave(&res->reg_slock, flags);
578 mixer_vsync_set_update(ctx, false);
581 mixer_reg_writemask(res, MXR_GRAPHIC_CFG(win),
582 MXR_GRP_CFG_FORMAT_VAL(fmt), MXR_GRP_CFG_FORMAT_MASK);
585 mixer_reg_write(res, MXR_GRAPHIC_SPAN(win), win_data->fb_width);
587 /* setup display size */
588 if (ctx->mxr_ver == MXR_VER_128_0_0_184 &&
589 win == MIXER_DEFAULT_WIN) {
590 val = MXR_MXR_RES_HEIGHT(win_data->fb_height);
591 val |= MXR_MXR_RES_WIDTH(win_data->fb_width);
592 mixer_reg_write(res, MXR_RESOLUTION, val);
595 val = MXR_GRP_WH_WIDTH(win_data->crtc_width);
596 val |= MXR_GRP_WH_HEIGHT(win_data->crtc_height);
597 val |= MXR_GRP_WH_H_SCALE(x_ratio);
598 val |= MXR_GRP_WH_V_SCALE(y_ratio);
599 mixer_reg_write(res, MXR_GRAPHIC_WH(win), val);
601 /* setup offsets in source image */
602 val = MXR_GRP_SXY_SX(src_x_offset);
603 val |= MXR_GRP_SXY_SY(src_y_offset);
604 mixer_reg_write(res, MXR_GRAPHIC_SXY(win), val);
606 /* setup offsets in display image */
607 val = MXR_GRP_DXY_DX(dst_x_offset);
608 val |= MXR_GRP_DXY_DY(dst_y_offset);
609 mixer_reg_write(res, MXR_GRAPHIC_DXY(win), val);
611 /* set buffer address to mixer */
612 mixer_reg_write(res, MXR_GRAPHIC_BASE(win), dma_addr);
614 mixer_cfg_scan(ctx, win_data->mode_height);
615 mixer_cfg_rgb_fmt(ctx, win_data->mode_height);
616 mixer_cfg_layer(ctx, win, true);
618 /* layer update mandatory for mixer 16.0.33.0 */
619 if (ctx->mxr_ver == MXR_VER_16_0_33_0 ||
620 ctx->mxr_ver == MXR_VER_128_0_0_184)
621 mixer_layer_update(ctx);
625 mixer_vsync_set_update(ctx, true);
626 spin_unlock_irqrestore(&res->reg_slock, flags);
629 static void vp_win_reset(struct mixer_context *ctx)
631 struct mixer_resources *res = &ctx->mixer_res;
634 vp_reg_write(res, VP_SRESET, VP_SRESET_PROCESSING);
635 for (tries = 100; tries; --tries) {
636 /* waiting until VP_SRESET_PROCESSING is 0 */
637 if (~vp_reg_read(res, VP_SRESET) & VP_SRESET_PROCESSING)
639 usleep_range(10000, 12000);
641 WARN(tries == 0, "failed to reset Video Processor\n");
644 static void mixer_win_reset(struct mixer_context *ctx)
646 struct mixer_resources *res = &ctx->mixer_res;
648 u32 val; /* value stored to register */
650 spin_lock_irqsave(&res->reg_slock, flags);
651 mixer_vsync_set_update(ctx, false);
653 mixer_reg_writemask(res, MXR_CFG, MXR_CFG_DST_HDMI, MXR_CFG_DST_MASK);
655 /* set output in RGB888 mode */
656 mixer_reg_writemask(res, MXR_CFG, MXR_CFG_OUT_RGB888, MXR_CFG_OUT_MASK);
658 /* 16 beat burst in DMA */
659 mixer_reg_writemask(res, MXR_STATUS, MXR_STATUS_16_BURST,
660 MXR_STATUS_BURST_MASK);
662 /* setting default layer priority: layer1 > layer0 > video
663 * because typical usage scenario would be
665 * layer0 - framebuffer
666 * video - video overlay
668 val = MXR_LAYER_CFG_GRP1_VAL(3);
669 val |= MXR_LAYER_CFG_GRP0_VAL(2);
671 val |= MXR_LAYER_CFG_VP_VAL(1);
672 mixer_reg_write(res, MXR_LAYER_CFG, val);
674 /* setting background color */
675 mixer_reg_write(res, MXR_BG_COLOR0, 0x008080);
676 mixer_reg_write(res, MXR_BG_COLOR1, 0x008080);
677 mixer_reg_write(res, MXR_BG_COLOR2, 0x008080);
679 /* setting graphical layers */
680 val = MXR_GRP_CFG_COLOR_KEY_DISABLE; /* no blank key */
681 val |= MXR_GRP_CFG_WIN_BLEND_EN;
682 val |= MXR_GRP_CFG_ALPHA_VAL(0xff); /* non-transparent alpha */
684 /* Don't blend layer 0 onto the mixer background */
685 mixer_reg_write(res, MXR_GRAPHIC_CFG(0), val);
687 /* Blend layer 1 into layer 0 */
688 val |= MXR_GRP_CFG_BLEND_PRE_MUL;
689 val |= MXR_GRP_CFG_PIXEL_BLEND_EN;
690 mixer_reg_write(res, MXR_GRAPHIC_CFG(1), val);
692 /* setting video layers */
693 val = MXR_GRP_CFG_ALPHA_VAL(0);
694 mixer_reg_write(res, MXR_VIDEO_CFG, val);
696 if (ctx->vp_enabled) {
697 /* configuration of Video Processor Registers */
699 vp_default_filter(res);
702 /* disable all layers */
703 mixer_reg_writemask(res, MXR_CFG, 0, MXR_CFG_GRP0_ENABLE);
704 mixer_reg_writemask(res, MXR_CFG, 0, MXR_CFG_GRP1_ENABLE);
706 mixer_reg_writemask(res, MXR_CFG, 0, MXR_CFG_VP_ENABLE);
708 mixer_vsync_set_update(ctx, true);
709 spin_unlock_irqrestore(&res->reg_slock, flags);
712 static irqreturn_t mixer_irq_handler(int irq, void *arg)
714 struct mixer_context *ctx = arg;
715 struct mixer_resources *res = &ctx->mixer_res;
716 u32 val, base, shadow;
718 spin_lock(&res->reg_slock);
720 /* read interrupt status for handling and clearing flags for VSYNC */
721 val = mixer_reg_read(res, MXR_INT_STATUS);
724 if (val & MXR_INT_STATUS_VSYNC) {
725 /* interlace scan need to check shadow register */
726 if (ctx->interlace) {
727 base = mixer_reg_read(res, MXR_GRAPHIC_BASE(0));
728 shadow = mixer_reg_read(res, MXR_GRAPHIC_BASE_S(0));
732 base = mixer_reg_read(res, MXR_GRAPHIC_BASE(1));
733 shadow = mixer_reg_read(res, MXR_GRAPHIC_BASE_S(1));
738 drm_handle_vblank(ctx->drm_dev, ctx->pipe);
739 exynos_drm_crtc_finish_pageflip(ctx->drm_dev, ctx->pipe);
741 /* set wait vsync event to zero and wake up queue. */
742 if (atomic_read(&ctx->wait_vsync_event)) {
743 atomic_set(&ctx->wait_vsync_event, 0);
744 wake_up(&ctx->wait_vsync_queue);
749 /* clear interrupts */
750 if (~val & MXR_INT_EN_VSYNC) {
751 /* vsync interrupt use different bit for read and clear */
752 val &= ~MXR_INT_EN_VSYNC;
753 val |= MXR_INT_CLEAR_VSYNC;
755 mixer_reg_write(res, MXR_INT_STATUS, val);
757 spin_unlock(&res->reg_slock);
762 static int mixer_resources_init(struct mixer_context *mixer_ctx)
764 struct device *dev = &mixer_ctx->pdev->dev;
765 struct mixer_resources *mixer_res = &mixer_ctx->mixer_res;
766 struct resource *res;
769 spin_lock_init(&mixer_res->reg_slock);
771 mixer_res->mixer = devm_clk_get(dev, "mixer");
772 if (IS_ERR(mixer_res->mixer)) {
773 dev_err(dev, "failed to get clock 'mixer'\n");
777 mixer_res->sclk_hdmi = devm_clk_get(dev, "sclk_hdmi");
778 if (IS_ERR(mixer_res->sclk_hdmi)) {
779 dev_err(dev, "failed to get clock 'sclk_hdmi'\n");
782 res = platform_get_resource(mixer_ctx->pdev, IORESOURCE_MEM, 0);
784 dev_err(dev, "get memory resource failed.\n");
788 mixer_res->mixer_regs = devm_ioremap(dev, res->start,
790 if (mixer_res->mixer_regs == NULL) {
791 dev_err(dev, "register mapping failed.\n");
795 res = platform_get_resource(mixer_ctx->pdev, IORESOURCE_IRQ, 0);
797 dev_err(dev, "get interrupt resource failed.\n");
801 ret = devm_request_irq(dev, res->start, mixer_irq_handler,
802 0, "drm_mixer", mixer_ctx);
804 dev_err(dev, "request interrupt failed.\n");
807 mixer_res->irq = res->start;
812 static int vp_resources_init(struct mixer_context *mixer_ctx)
814 struct device *dev = &mixer_ctx->pdev->dev;
815 struct mixer_resources *mixer_res = &mixer_ctx->mixer_res;
816 struct resource *res;
818 mixer_res->vp = devm_clk_get(dev, "vp");
819 if (IS_ERR(mixer_res->vp)) {
820 dev_err(dev, "failed to get clock 'vp'\n");
824 if (mixer_ctx->has_sclk) {
825 mixer_res->sclk_mixer = devm_clk_get(dev, "sclk_mixer");
826 if (IS_ERR(mixer_res->sclk_mixer)) {
827 dev_err(dev, "failed to get clock 'sclk_mixer'\n");
830 mixer_res->mout_mixer = devm_clk_get(dev, "mout_mixer");
831 if (IS_ERR(mixer_res->mout_mixer)) {
832 dev_err(dev, "failed to get clock 'mout_mixer'\n");
836 if (mixer_res->sclk_hdmi && mixer_res->mout_mixer)
837 clk_set_parent(mixer_res->mout_mixer,
838 mixer_res->sclk_hdmi);
841 res = platform_get_resource(mixer_ctx->pdev, IORESOURCE_MEM, 1);
843 dev_err(dev, "get memory resource failed.\n");
847 mixer_res->vp_regs = devm_ioremap(dev, res->start,
849 if (mixer_res->vp_regs == NULL) {
850 dev_err(dev, "register mapping failed.\n");
857 static int mixer_initialize(struct exynos_drm_manager *mgr,
858 struct drm_device *drm_dev)
861 struct mixer_context *mixer_ctx = mgr_to_mixer(mgr);
862 struct exynos_drm_private *priv;
863 priv = drm_dev->dev_private;
865 mgr->drm_dev = mixer_ctx->drm_dev = drm_dev;
866 mgr->pipe = mixer_ctx->pipe = priv->pipe++;
868 /* acquire resources: regs, irqs, clocks */
869 ret = mixer_resources_init(mixer_ctx);
871 DRM_ERROR("mixer_resources_init failed ret=%d\n", ret);
875 if (mixer_ctx->vp_enabled) {
876 /* acquire vp resources: regs, irqs, clocks */
877 ret = vp_resources_init(mixer_ctx);
879 DRM_ERROR("vp_resources_init failed ret=%d\n", ret);
884 if (!is_drm_iommu_supported(mixer_ctx->drm_dev))
887 return drm_iommu_attach_device(mixer_ctx->drm_dev, mixer_ctx->dev);
890 static void mixer_mgr_remove(struct exynos_drm_manager *mgr)
892 struct mixer_context *mixer_ctx = mgr_to_mixer(mgr);
894 if (is_drm_iommu_supported(mixer_ctx->drm_dev))
895 drm_iommu_detach_device(mixer_ctx->drm_dev, mixer_ctx->dev);
898 static int mixer_enable_vblank(struct exynos_drm_manager *mgr)
900 struct mixer_context *mixer_ctx = mgr_to_mixer(mgr);
901 struct mixer_resources *res = &mixer_ctx->mixer_res;
903 if (!mixer_ctx->powered) {
904 mixer_ctx->int_en |= MXR_INT_EN_VSYNC;
908 /* enable vsync interrupt */
909 mixer_reg_writemask(res, MXR_INT_EN, MXR_INT_EN_VSYNC,
915 static void mixer_disable_vblank(struct exynos_drm_manager *mgr)
917 struct mixer_context *mixer_ctx = mgr_to_mixer(mgr);
918 struct mixer_resources *res = &mixer_ctx->mixer_res;
920 /* disable vsync interrupt */
921 mixer_reg_writemask(res, MXR_INT_EN, 0, MXR_INT_EN_VSYNC);
924 static void mixer_win_mode_set(struct exynos_drm_manager *mgr,
925 struct exynos_drm_overlay *overlay)
927 struct mixer_context *mixer_ctx = mgr_to_mixer(mgr);
928 struct hdmi_win_data *win_data;
932 DRM_ERROR("overlay is NULL\n");
936 DRM_DEBUG_KMS("set [%d]x[%d] at (%d,%d) to [%d]x[%d] at (%d,%d)\n",
937 overlay->fb_width, overlay->fb_height,
938 overlay->fb_x, overlay->fb_y,
939 overlay->crtc_width, overlay->crtc_height,
940 overlay->crtc_x, overlay->crtc_y);
943 if (win == DEFAULT_ZPOS)
944 win = MIXER_DEFAULT_WIN;
946 if (win < 0 || win >= MIXER_WIN_NR) {
947 DRM_ERROR("mixer window[%d] is wrong\n", win);
951 win_data = &mixer_ctx->win_data[win];
953 win_data->dma_addr = overlay->dma_addr[0];
954 win_data->chroma_dma_addr = overlay->dma_addr[1];
955 win_data->pixel_format = overlay->pixel_format;
956 win_data->bpp = overlay->bpp;
958 win_data->crtc_x = overlay->crtc_x;
959 win_data->crtc_y = overlay->crtc_y;
960 win_data->crtc_width = overlay->crtc_width;
961 win_data->crtc_height = overlay->crtc_height;
963 win_data->fb_x = overlay->fb_x;
964 win_data->fb_y = overlay->fb_y;
965 win_data->fb_width = overlay->fb_width;
966 win_data->fb_height = overlay->fb_height;
967 win_data->src_width = overlay->src_width;
968 win_data->src_height = overlay->src_height;
970 win_data->mode_width = overlay->mode_width;
971 win_data->mode_height = overlay->mode_height;
973 win_data->scan_flags = overlay->scan_flag;
976 static void mixer_win_commit(struct exynos_drm_manager *mgr, int zpos)
978 struct mixer_context *mixer_ctx = mgr_to_mixer(mgr);
979 int win = zpos == DEFAULT_ZPOS ? MIXER_DEFAULT_WIN : zpos;
981 DRM_DEBUG_KMS("win: %d\n", win);
983 mutex_lock(&mixer_ctx->mixer_mutex);
984 if (!mixer_ctx->powered) {
985 mutex_unlock(&mixer_ctx->mixer_mutex);
988 mutex_unlock(&mixer_ctx->mixer_mutex);
990 if (win > 1 && mixer_ctx->vp_enabled)
991 vp_video_buffer(mixer_ctx, win);
993 mixer_graph_buffer(mixer_ctx, win);
995 mixer_ctx->win_data[win].enabled = true;
998 static void mixer_win_disable(struct exynos_drm_manager *mgr, int zpos)
1000 struct mixer_context *mixer_ctx = mgr_to_mixer(mgr);
1001 struct mixer_resources *res = &mixer_ctx->mixer_res;
1002 int win = zpos == DEFAULT_ZPOS ? MIXER_DEFAULT_WIN : zpos;
1003 unsigned long flags;
1005 DRM_DEBUG_KMS("win: %d\n", win);
1007 mutex_lock(&mixer_ctx->mixer_mutex);
1008 if (!mixer_ctx->powered) {
1009 mutex_unlock(&mixer_ctx->mixer_mutex);
1010 mixer_ctx->win_data[win].resume = false;
1013 mutex_unlock(&mixer_ctx->mixer_mutex);
1015 spin_lock_irqsave(&res->reg_slock, flags);
1016 mixer_vsync_set_update(mixer_ctx, false);
1018 mixer_cfg_layer(mixer_ctx, win, false);
1020 mixer_vsync_set_update(mixer_ctx, true);
1021 spin_unlock_irqrestore(&res->reg_slock, flags);
1023 mixer_ctx->win_data[win].enabled = false;
1026 static void mixer_wait_for_vblank(struct exynos_drm_manager *mgr)
1028 struct mixer_context *mixer_ctx = mgr_to_mixer(mgr);
1031 mutex_lock(&mixer_ctx->mixer_mutex);
1032 if (!mixer_ctx->powered) {
1033 mutex_unlock(&mixer_ctx->mixer_mutex);
1036 mutex_unlock(&mixer_ctx->mixer_mutex);
1038 err = drm_vblank_get(mgr->crtc->dev, mixer_ctx->pipe);
1040 DRM_DEBUG_KMS("failed to acquire vblank counter\n");
1044 atomic_set(&mixer_ctx->wait_vsync_event, 1);
1047 * wait for MIXER to signal VSYNC interrupt or return after
1048 * timeout which is set to 50ms (refresh rate of 20).
1050 if (!wait_event_timeout(mixer_ctx->wait_vsync_queue,
1051 !atomic_read(&mixer_ctx->wait_vsync_event),
1053 DRM_DEBUG_KMS("vblank wait timed out.\n");
1055 drm_vblank_put(mgr->crtc->dev, mixer_ctx->pipe);
1058 static void mixer_window_suspend(struct exynos_drm_manager *mgr)
1060 struct mixer_context *ctx = mgr_to_mixer(mgr);
1061 struct hdmi_win_data *win_data;
1064 for (i = 0; i < MIXER_WIN_NR; i++) {
1065 win_data = &ctx->win_data[i];
1066 win_data->resume = win_data->enabled;
1067 mixer_win_disable(mgr, i);
1069 mixer_wait_for_vblank(mgr);
1072 static void mixer_window_resume(struct exynos_drm_manager *mgr)
1074 struct mixer_context *ctx = mgr_to_mixer(mgr);
1075 struct hdmi_win_data *win_data;
1078 for (i = 0; i < MIXER_WIN_NR; i++) {
1079 win_data = &ctx->win_data[i];
1080 win_data->enabled = win_data->resume;
1081 win_data->resume = false;
1082 if (win_data->enabled)
1083 mixer_win_commit(mgr, i);
1087 static void mixer_poweron(struct exynos_drm_manager *mgr)
1089 struct mixer_context *ctx = mgr_to_mixer(mgr);
1090 struct mixer_resources *res = &ctx->mixer_res;
1092 mutex_lock(&ctx->mixer_mutex);
1094 mutex_unlock(&ctx->mixer_mutex);
1098 mutex_unlock(&ctx->mixer_mutex);
1100 pm_runtime_get_sync(ctx->dev);
1102 clk_prepare_enable(res->mixer);
1103 if (ctx->vp_enabled) {
1104 clk_prepare_enable(res->vp);
1106 clk_prepare_enable(res->sclk_mixer);
1109 mutex_lock(&ctx->mixer_mutex);
1110 ctx->powered = true;
1111 mutex_unlock(&ctx->mixer_mutex);
1113 mixer_reg_writemask(res, MXR_STATUS, ~0, MXR_STATUS_SOFT_RESET);
1115 mixer_reg_write(res, MXR_INT_EN, ctx->int_en);
1116 mixer_win_reset(ctx);
1118 mixer_window_resume(mgr);
1121 static void mixer_poweroff(struct exynos_drm_manager *mgr)
1123 struct mixer_context *ctx = mgr_to_mixer(mgr);
1124 struct mixer_resources *res = &ctx->mixer_res;
1126 mutex_lock(&ctx->mixer_mutex);
1127 if (!ctx->powered) {
1128 mutex_unlock(&ctx->mixer_mutex);
1131 mutex_unlock(&ctx->mixer_mutex);
1134 mixer_window_suspend(mgr);
1136 ctx->int_en = mixer_reg_read(res, MXR_INT_EN);
1138 mutex_lock(&ctx->mixer_mutex);
1139 ctx->powered = false;
1140 mutex_unlock(&ctx->mixer_mutex);
1142 clk_disable_unprepare(res->mixer);
1143 if (ctx->vp_enabled) {
1144 clk_disable_unprepare(res->vp);
1146 clk_disable_unprepare(res->sclk_mixer);
1149 pm_runtime_put_sync(ctx->dev);
1152 static void mixer_dpms(struct exynos_drm_manager *mgr, int mode)
1155 case DRM_MODE_DPMS_ON:
1158 case DRM_MODE_DPMS_STANDBY:
1159 case DRM_MODE_DPMS_SUSPEND:
1160 case DRM_MODE_DPMS_OFF:
1161 mixer_poweroff(mgr);
1164 DRM_DEBUG_KMS("unknown dpms mode: %d\n", mode);
1169 /* Only valid for Mixer version 16.0.33.0 */
1170 int mixer_check_mode(struct drm_display_mode *mode)
1177 DRM_DEBUG_KMS("xres=%d, yres=%d, refresh=%d, intl=%d\n",
1178 mode->hdisplay, mode->vdisplay, mode->vrefresh,
1179 (mode->flags & DRM_MODE_FLAG_INTERLACE) ? 1 : 0);
1181 if ((w >= 464 && w <= 720 && h >= 261 && h <= 576) ||
1182 (w >= 1024 && w <= 1280 && h >= 576 && h <= 720) ||
1183 (w >= 1664 && w <= 1920 && h >= 936 && h <= 1080))
1189 static struct exynos_drm_manager_ops mixer_manager_ops = {
1191 .enable_vblank = mixer_enable_vblank,
1192 .disable_vblank = mixer_disable_vblank,
1193 .wait_for_vblank = mixer_wait_for_vblank,
1194 .win_mode_set = mixer_win_mode_set,
1195 .win_commit = mixer_win_commit,
1196 .win_disable = mixer_win_disable,
1199 static struct mixer_drv_data exynos5420_mxr_drv_data = {
1200 .version = MXR_VER_128_0_0_184,
1204 static struct mixer_drv_data exynos5250_mxr_drv_data = {
1205 .version = MXR_VER_16_0_33_0,
1209 static struct mixer_drv_data exynos4212_mxr_drv_data = {
1210 .version = MXR_VER_0_0_0_16,
1214 static struct mixer_drv_data exynos4210_mxr_drv_data = {
1215 .version = MXR_VER_0_0_0_16,
1220 static struct platform_device_id mixer_driver_types[] = {
1222 .name = "s5p-mixer",
1223 .driver_data = (unsigned long)&exynos4210_mxr_drv_data,
1225 .name = "exynos5-mixer",
1226 .driver_data = (unsigned long)&exynos5250_mxr_drv_data,
1232 static struct of_device_id mixer_match_types[] = {
1234 .compatible = "samsung,exynos4210-mixer",
1235 .data = &exynos4210_mxr_drv_data,
1237 .compatible = "samsung,exynos4212-mixer",
1238 .data = &exynos4212_mxr_drv_data,
1240 .compatible = "samsung,exynos5-mixer",
1241 .data = &exynos5250_mxr_drv_data,
1243 .compatible = "samsung,exynos5250-mixer",
1244 .data = &exynos5250_mxr_drv_data,
1246 .compatible = "samsung,exynos5420-mixer",
1247 .data = &exynos5420_mxr_drv_data,
1252 MODULE_DEVICE_TABLE(of, mixer_match_types);
1254 static int mixer_bind(struct device *dev, struct device *manager, void *data)
1256 struct mixer_context *ctx = dev_get_drvdata(dev);
1257 struct drm_device *drm_dev = data;
1260 ret = mixer_initialize(&ctx->manager, drm_dev);
1264 ret = exynos_drm_crtc_create(&ctx->manager);
1266 mixer_mgr_remove(&ctx->manager);
1273 static void mixer_unbind(struct device *dev, struct device *master, void *data)
1275 struct mixer_context *ctx = dev_get_drvdata(dev);
1277 mixer_mgr_remove(&ctx->manager);
1280 static const struct component_ops mixer_component_ops = {
1282 .unbind = mixer_unbind,
1285 static int mixer_probe(struct platform_device *pdev)
1287 struct device *dev = &pdev->dev;
1288 struct mixer_drv_data *drv;
1289 struct mixer_context *ctx;
1292 ctx = devm_kzalloc(&pdev->dev, sizeof(*ctx), GFP_KERNEL);
1294 DRM_ERROR("failed to alloc mixer context.\n");
1298 mutex_init(&ctx->mixer_mutex);
1300 ctx->manager.type = EXYNOS_DISPLAY_TYPE_HDMI;
1301 ctx->manager.ops = &mixer_manager_ops;
1304 const struct of_device_id *match;
1306 match = of_match_node(mixer_match_types, dev->of_node);
1307 drv = (struct mixer_drv_data *)match->data;
1309 drv = (struct mixer_drv_data *)
1310 platform_get_device_id(pdev)->driver_data;
1315 ctx->vp_enabled = drv->is_vp_enabled;
1316 ctx->has_sclk = drv->has_sclk;
1317 ctx->mxr_ver = drv->version;
1318 init_waitqueue_head(&ctx->wait_vsync_queue);
1319 atomic_set(&ctx->wait_vsync_event, 0);
1321 platform_set_drvdata(pdev, ctx);
1323 ret = exynos_drm_component_add(&pdev->dev, EXYNOS_DEVICE_TYPE_CRTC,
1328 ret = component_add(&pdev->dev, &mixer_component_ops);
1330 exynos_drm_component_del(&pdev->dev, EXYNOS_DEVICE_TYPE_CRTC);
1334 pm_runtime_enable(dev);
1339 static int mixer_remove(struct platform_device *pdev)
1341 pm_runtime_disable(&pdev->dev);
1343 component_del(&pdev->dev, &mixer_component_ops);
1344 exynos_drm_component_del(&pdev->dev, EXYNOS_DEVICE_TYPE_CRTC);
1349 struct platform_driver mixer_driver = {
1351 .name = "exynos-mixer",
1352 .owner = THIS_MODULE,
1353 .of_match_table = mixer_match_types,
1355 .probe = mixer_probe,
1356 .remove = mixer_remove,
1357 .id_table = mixer_driver_types,