2 * Copyright (C) 2011 Samsung Electronics Co.Ltd
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/of_device.h>
35 #include <linux/component.h>
37 #include <drm/exynos_drm.h>
39 #include "exynos_drm_drv.h"
40 #include "exynos_drm_crtc.h"
41 #include "exynos_drm_fb.h"
42 #include "exynos_drm_plane.h"
43 #include "exynos_drm_iommu.h"
45 #define MIXER_WIN_NR 3
46 #define VP_DEFAULT_WIN 2
49 * Mixer color space conversion coefficient triplet.
50 * Used for CSC from RGB to YCbCr.
51 * Each coefficient is a 10-bit fixed point number with
52 * sign and no integer part, i.e.
53 * [0:8] = fractional part (representing a value y = x / 2^9)
55 * Negative values are encoded with two's complement.
57 #define MXR_CSC_C(x) ((int)((x) * 512.0) & 0x3ff)
58 #define MXR_CSC_CT(a0, a1, a2) \
59 ((MXR_CSC_C(a0) << 20) | (MXR_CSC_C(a1) << 10) | (MXR_CSC_C(a2) << 0))
61 /* YCbCr value, used for mixer background color configuration. */
62 #define MXR_YCBCR_VAL(y, cb, cr) (((y) << 16) | ((cb) << 8) | ((cr) << 0))
64 /* The pixelformats that are natively supported by the mixer. */
65 #define MXR_FORMAT_RGB565 4
66 #define MXR_FORMAT_ARGB1555 5
67 #define MXR_FORMAT_ARGB4444 6
68 #define MXR_FORMAT_ARGB8888 7
70 enum mixer_version_id {
76 enum mixer_flag_bits {
84 static const uint32_t mixer_formats[] = {
94 static const uint32_t vp_formats[] = {
99 struct mixer_context {
100 struct platform_device *pdev;
102 struct drm_device *drm_dev;
103 struct exynos_drm_crtc *crtc;
104 struct exynos_drm_plane planes[MIXER_WIN_NR];
108 void __iomem *mixer_regs;
109 void __iomem *vp_regs;
110 spinlock_t reg_slock;
114 struct clk *sclk_mixer;
115 struct clk *sclk_hdmi;
116 struct clk *mout_mixer;
117 enum mixer_version_id mxr_ver;
121 struct mixer_drv_data {
122 enum mixer_version_id version;
127 static const struct exynos_drm_plane_config plane_configs[MIXER_WIN_NR] = {
130 .type = DRM_PLANE_TYPE_PRIMARY,
131 .pixel_formats = mixer_formats,
132 .num_pixel_formats = ARRAY_SIZE(mixer_formats),
133 .capabilities = EXYNOS_DRM_PLANE_CAP_DOUBLE |
134 EXYNOS_DRM_PLANE_CAP_ZPOS,
137 .type = DRM_PLANE_TYPE_CURSOR,
138 .pixel_formats = mixer_formats,
139 .num_pixel_formats = ARRAY_SIZE(mixer_formats),
140 .capabilities = EXYNOS_DRM_PLANE_CAP_DOUBLE |
141 EXYNOS_DRM_PLANE_CAP_ZPOS,
144 .type = DRM_PLANE_TYPE_OVERLAY,
145 .pixel_formats = vp_formats,
146 .num_pixel_formats = ARRAY_SIZE(vp_formats),
147 .capabilities = EXYNOS_DRM_PLANE_CAP_SCALE |
148 EXYNOS_DRM_PLANE_CAP_ZPOS |
149 EXYNOS_DRM_PLANE_CAP_TILE,
153 static const u8 filter_y_horiz_tap8[] = {
154 0, -1, -1, -1, -1, -1, -1, -1,
155 -1, -1, -1, -1, -1, 0, 0, 0,
156 0, 2, 4, 5, 6, 6, 6, 6,
157 6, 5, 5, 4, 3, 2, 1, 1,
158 0, -6, -12, -16, -18, -20, -21, -20,
159 -20, -18, -16, -13, -10, -8, -5, -2,
160 127, 126, 125, 121, 114, 107, 99, 89,
161 79, 68, 57, 46, 35, 25, 16, 8,
164 static const u8 filter_y_vert_tap4[] = {
165 0, -3, -6, -8, -8, -8, -8, -7,
166 -6, -5, -4, -3, -2, -1, -1, 0,
167 127, 126, 124, 118, 111, 102, 92, 81,
168 70, 59, 48, 37, 27, 19, 11, 5,
169 0, 5, 11, 19, 27, 37, 48, 59,
170 70, 81, 92, 102, 111, 118, 124, 126,
171 0, 0, -1, -1, -2, -3, -4, -5,
172 -6, -7, -8, -8, -8, -8, -6, -3,
175 static const u8 filter_cr_horiz_tap4[] = {
176 0, -3, -6, -8, -8, -8, -8, -7,
177 -6, -5, -4, -3, -2, -1, -1, 0,
178 127, 126, 124, 118, 111, 102, 92, 81,
179 70, 59, 48, 37, 27, 19, 11, 5,
182 static inline u32 vp_reg_read(struct mixer_context *ctx, u32 reg_id)
184 return readl(ctx->vp_regs + reg_id);
187 static inline void vp_reg_write(struct mixer_context *ctx, u32 reg_id,
190 writel(val, ctx->vp_regs + reg_id);
193 static inline void vp_reg_writemask(struct mixer_context *ctx, u32 reg_id,
196 u32 old = vp_reg_read(ctx, reg_id);
198 val = (val & mask) | (old & ~mask);
199 writel(val, ctx->vp_regs + reg_id);
202 static inline u32 mixer_reg_read(struct mixer_context *ctx, u32 reg_id)
204 return readl(ctx->mixer_regs + reg_id);
207 static inline void mixer_reg_write(struct mixer_context *ctx, u32 reg_id,
210 writel(val, ctx->mixer_regs + reg_id);
213 static inline void mixer_reg_writemask(struct mixer_context *ctx,
214 u32 reg_id, u32 val, u32 mask)
216 u32 old = mixer_reg_read(ctx, reg_id);
218 val = (val & mask) | (old & ~mask);
219 writel(val, ctx->mixer_regs + reg_id);
222 static void mixer_regs_dump(struct mixer_context *ctx)
224 #define DUMPREG(reg_id) \
226 DRM_DEBUG_KMS(#reg_id " = %08x\n", \
227 (u32)readl(ctx->mixer_regs + reg_id)); \
233 DUMPREG(MXR_INT_STATUS);
235 DUMPREG(MXR_LAYER_CFG);
236 DUMPREG(MXR_VIDEO_CFG);
238 DUMPREG(MXR_GRAPHIC0_CFG);
239 DUMPREG(MXR_GRAPHIC0_BASE);
240 DUMPREG(MXR_GRAPHIC0_SPAN);
241 DUMPREG(MXR_GRAPHIC0_WH);
242 DUMPREG(MXR_GRAPHIC0_SXY);
243 DUMPREG(MXR_GRAPHIC0_DXY);
245 DUMPREG(MXR_GRAPHIC1_CFG);
246 DUMPREG(MXR_GRAPHIC1_BASE);
247 DUMPREG(MXR_GRAPHIC1_SPAN);
248 DUMPREG(MXR_GRAPHIC1_WH);
249 DUMPREG(MXR_GRAPHIC1_SXY);
250 DUMPREG(MXR_GRAPHIC1_DXY);
254 static void vp_regs_dump(struct mixer_context *ctx)
256 #define DUMPREG(reg_id) \
258 DRM_DEBUG_KMS(#reg_id " = %08x\n", \
259 (u32) readl(ctx->vp_regs + reg_id)); \
264 DUMPREG(VP_SHADOW_UPDATE);
265 DUMPREG(VP_FIELD_ID);
267 DUMPREG(VP_IMG_SIZE_Y);
268 DUMPREG(VP_IMG_SIZE_C);
269 DUMPREG(VP_PER_RATE_CTRL);
270 DUMPREG(VP_TOP_Y_PTR);
271 DUMPREG(VP_BOT_Y_PTR);
272 DUMPREG(VP_TOP_C_PTR);
273 DUMPREG(VP_BOT_C_PTR);
274 DUMPREG(VP_ENDIAN_MODE);
275 DUMPREG(VP_SRC_H_POSITION);
276 DUMPREG(VP_SRC_V_POSITION);
277 DUMPREG(VP_SRC_WIDTH);
278 DUMPREG(VP_SRC_HEIGHT);
279 DUMPREG(VP_DST_H_POSITION);
280 DUMPREG(VP_DST_V_POSITION);
281 DUMPREG(VP_DST_WIDTH);
282 DUMPREG(VP_DST_HEIGHT);
289 static inline void vp_filter_set(struct mixer_context *ctx,
290 int reg_id, const u8 *data, unsigned int size)
292 /* assure 4-byte align */
294 for (; size; size -= 4, reg_id += 4, data += 4) {
295 u32 val = (data[0] << 24) | (data[1] << 16) |
296 (data[2] << 8) | data[3];
297 vp_reg_write(ctx, reg_id, val);
301 static void vp_default_filter(struct mixer_context *ctx)
303 vp_filter_set(ctx, VP_POLY8_Y0_LL,
304 filter_y_horiz_tap8, sizeof(filter_y_horiz_tap8));
305 vp_filter_set(ctx, VP_POLY4_Y0_LL,
306 filter_y_vert_tap4, sizeof(filter_y_vert_tap4));
307 vp_filter_set(ctx, VP_POLY4_C0_LL,
308 filter_cr_horiz_tap4, sizeof(filter_cr_horiz_tap4));
311 static void mixer_cfg_gfx_blend(struct mixer_context *ctx, unsigned int win,
316 val = MXR_GRP_CFG_COLOR_KEY_DISABLE; /* no blank key */
318 /* blending based on pixel alpha */
319 val |= MXR_GRP_CFG_BLEND_PRE_MUL;
320 val |= MXR_GRP_CFG_PIXEL_BLEND_EN;
322 mixer_reg_writemask(ctx, MXR_GRAPHIC_CFG(win),
323 val, MXR_GRP_CFG_MISC_MASK);
326 static void mixer_cfg_vp_blend(struct mixer_context *ctx)
331 * No blending at the moment since the NV12/NV21 pixelformats don't
332 * have an alpha channel. However the mixer supports a global alpha
333 * value for a layer. Once this functionality is exposed, we can
334 * support blending of the video layer through this.
337 mixer_reg_write(ctx, MXR_VIDEO_CFG, val);
340 static void mixer_vsync_set_update(struct mixer_context *ctx, bool enable)
342 /* block update on vsync */
343 mixer_reg_writemask(ctx, MXR_STATUS, enable ?
344 MXR_STATUS_SYNC_ENABLE : 0, MXR_STATUS_SYNC_ENABLE);
346 if (test_bit(MXR_BIT_VP_ENABLED, &ctx->flags))
347 vp_reg_write(ctx, VP_SHADOW_UPDATE, enable ?
348 VP_SHADOW_UPDATE_ENABLE : 0);
351 static void mixer_cfg_scan(struct mixer_context *ctx, int width, int height)
355 /* choosing between interlace and progressive mode */
356 val = test_bit(MXR_BIT_INTERLACE, &ctx->flags) ?
357 MXR_CFG_SCAN_INTERLACE : MXR_CFG_SCAN_PROGRESSIVE;
359 if (ctx->mxr_ver == MXR_VER_128_0_0_184)
360 mixer_reg_write(ctx, MXR_RESOLUTION,
361 MXR_MXR_RES_HEIGHT(height) | MXR_MXR_RES_WIDTH(width));
363 val |= ctx->scan_value;
365 mixer_reg_writemask(ctx, MXR_CFG, val, MXR_CFG_SCAN_MASK);
368 static void mixer_cfg_rgb_fmt(struct mixer_context *ctx, unsigned int height)
375 val = MXR_CFG_RGB601_0_255;
380 val = MXR_CFG_RGB709_16_235;
381 /* Configure the BT.709 CSC matrix for full range RGB. */
382 mixer_reg_write(ctx, MXR_CM_COEFF_Y,
383 MXR_CSC_CT( 0.184, 0.614, 0.063) |
384 MXR_CM_COEFF_RGB_FULL);
385 mixer_reg_write(ctx, MXR_CM_COEFF_CB,
386 MXR_CSC_CT(-0.102, -0.338, 0.440));
387 mixer_reg_write(ctx, MXR_CM_COEFF_CR,
388 MXR_CSC_CT( 0.440, -0.399, -0.040));
392 mixer_reg_writemask(ctx, MXR_CFG, val, MXR_CFG_RGB_FMT_MASK);
395 static void mixer_cfg_layer(struct mixer_context *ctx, unsigned int win,
396 unsigned int priority, bool enable)
398 u32 val = enable ? ~0 : 0;
402 mixer_reg_writemask(ctx, MXR_CFG, val, MXR_CFG_GRP0_ENABLE);
403 mixer_reg_writemask(ctx, MXR_LAYER_CFG,
404 MXR_LAYER_CFG_GRP0_VAL(priority),
405 MXR_LAYER_CFG_GRP0_MASK);
408 mixer_reg_writemask(ctx, MXR_CFG, val, MXR_CFG_GRP1_ENABLE);
409 mixer_reg_writemask(ctx, MXR_LAYER_CFG,
410 MXR_LAYER_CFG_GRP1_VAL(priority),
411 MXR_LAYER_CFG_GRP1_MASK);
415 if (test_bit(MXR_BIT_VP_ENABLED, &ctx->flags)) {
416 vp_reg_writemask(ctx, VP_ENABLE, val, VP_ENABLE_ON);
417 mixer_reg_writemask(ctx, MXR_CFG, val,
419 mixer_reg_writemask(ctx, MXR_LAYER_CFG,
420 MXR_LAYER_CFG_VP_VAL(priority),
421 MXR_LAYER_CFG_VP_MASK);
427 static void mixer_run(struct mixer_context *ctx)
429 mixer_reg_writemask(ctx, MXR_STATUS, ~0, MXR_STATUS_REG_RUN);
432 static void mixer_stop(struct mixer_context *ctx)
436 mixer_reg_writemask(ctx, MXR_STATUS, 0, MXR_STATUS_REG_RUN);
438 while (!(mixer_reg_read(ctx, MXR_STATUS) & MXR_STATUS_REG_IDLE) &&
440 usleep_range(10000, 12000);
443 static void mixer_commit(struct mixer_context *ctx)
445 struct drm_display_mode *mode = &ctx->crtc->base.state->adjusted_mode;
447 mixer_cfg_scan(ctx, mode->hdisplay, mode->vdisplay);
448 mixer_cfg_rgb_fmt(ctx, mode->vdisplay);
452 static void vp_video_buffer(struct mixer_context *ctx,
453 struct exynos_drm_plane *plane)
455 struct exynos_drm_plane_state *state =
456 to_exynos_plane_state(plane->base.state);
457 struct drm_framebuffer *fb = state->base.fb;
458 unsigned int priority = state->base.normalized_zpos + 1;
460 dma_addr_t luma_addr[2], chroma_addr[2];
461 bool is_tiled, is_nv21;
464 is_nv21 = (fb->format->format == DRM_FORMAT_NV21);
465 is_tiled = (fb->modifier == DRM_FORMAT_MOD_SAMSUNG_64_32_TILE);
467 luma_addr[0] = exynos_drm_fb_dma_addr(fb, 0);
468 chroma_addr[0] = exynos_drm_fb_dma_addr(fb, 1);
470 if (test_bit(MXR_BIT_INTERLACE, &ctx->flags)) {
472 luma_addr[1] = luma_addr[0] + 0x40;
473 chroma_addr[1] = chroma_addr[0] + 0x40;
475 luma_addr[1] = luma_addr[0] + fb->pitches[0];
476 chroma_addr[1] = chroma_addr[0] + fb->pitches[0];
483 spin_lock_irqsave(&ctx->reg_slock, flags);
485 /* interlace or progressive scan mode */
486 val = (test_bit(MXR_BIT_INTERLACE, &ctx->flags) ? ~0 : 0);
487 vp_reg_writemask(ctx, VP_MODE, val, VP_MODE_LINE_SKIP);
490 val = (is_nv21 ? VP_MODE_NV21 : VP_MODE_NV12);
491 val |= (is_tiled ? VP_MODE_MEM_TILED : VP_MODE_MEM_LINEAR);
492 vp_reg_writemask(ctx, VP_MODE, val, VP_MODE_FMT_MASK);
494 /* setting size of input image */
495 vp_reg_write(ctx, VP_IMG_SIZE_Y, VP_IMG_HSIZE(fb->pitches[0]) |
496 VP_IMG_VSIZE(fb->height));
497 /* chroma plane for NV12/NV21 is half the height of the luma plane */
498 vp_reg_write(ctx, VP_IMG_SIZE_C, VP_IMG_HSIZE(fb->pitches[0]) |
499 VP_IMG_VSIZE(fb->height / 2));
501 vp_reg_write(ctx, VP_SRC_WIDTH, state->src.w);
502 vp_reg_write(ctx, VP_SRC_HEIGHT, state->src.h);
503 vp_reg_write(ctx, VP_SRC_H_POSITION,
504 VP_SRC_H_POSITION_VAL(state->src.x));
505 vp_reg_write(ctx, VP_SRC_V_POSITION, state->src.y);
507 vp_reg_write(ctx, VP_DST_WIDTH, state->crtc.w);
508 vp_reg_write(ctx, VP_DST_H_POSITION, state->crtc.x);
509 if (test_bit(MXR_BIT_INTERLACE, &ctx->flags)) {
510 vp_reg_write(ctx, VP_DST_HEIGHT, state->crtc.h / 2);
511 vp_reg_write(ctx, VP_DST_V_POSITION, state->crtc.y / 2);
513 vp_reg_write(ctx, VP_DST_HEIGHT, state->crtc.h);
514 vp_reg_write(ctx, VP_DST_V_POSITION, state->crtc.y);
517 vp_reg_write(ctx, VP_H_RATIO, state->h_ratio);
518 vp_reg_write(ctx, VP_V_RATIO, state->v_ratio);
520 vp_reg_write(ctx, VP_ENDIAN_MODE, VP_ENDIAN_MODE_LITTLE);
522 /* set buffer address to vp */
523 vp_reg_write(ctx, VP_TOP_Y_PTR, luma_addr[0]);
524 vp_reg_write(ctx, VP_BOT_Y_PTR, luma_addr[1]);
525 vp_reg_write(ctx, VP_TOP_C_PTR, chroma_addr[0]);
526 vp_reg_write(ctx, VP_BOT_C_PTR, chroma_addr[1]);
528 mixer_cfg_layer(ctx, plane->index, priority, true);
529 mixer_cfg_vp_blend(ctx);
531 spin_unlock_irqrestore(&ctx->reg_slock, flags);
533 mixer_regs_dump(ctx);
537 static void mixer_layer_update(struct mixer_context *ctx)
539 mixer_reg_writemask(ctx, MXR_CFG, ~0, MXR_CFG_LAYER_UPDATE);
542 static void mixer_graph_buffer(struct mixer_context *ctx,
543 struct exynos_drm_plane *plane)
545 struct exynos_drm_plane_state *state =
546 to_exynos_plane_state(plane->base.state);
547 struct drm_framebuffer *fb = state->base.fb;
548 unsigned int priority = state->base.normalized_zpos + 1;
550 unsigned int win = plane->index;
551 unsigned int x_ratio = 0, y_ratio = 0;
552 unsigned int dst_x_offset, dst_y_offset;
557 switch (fb->format->format) {
558 case DRM_FORMAT_XRGB4444:
559 case DRM_FORMAT_ARGB4444:
560 fmt = MXR_FORMAT_ARGB4444;
563 case DRM_FORMAT_XRGB1555:
564 case DRM_FORMAT_ARGB1555:
565 fmt = MXR_FORMAT_ARGB1555;
568 case DRM_FORMAT_RGB565:
569 fmt = MXR_FORMAT_RGB565;
572 case DRM_FORMAT_XRGB8888:
573 case DRM_FORMAT_ARGB8888:
575 fmt = MXR_FORMAT_ARGB8888;
579 /* ratio is already checked by common plane code */
580 x_ratio = state->h_ratio == (1 << 15);
581 y_ratio = state->v_ratio == (1 << 15);
583 dst_x_offset = state->crtc.x;
584 dst_y_offset = state->crtc.y;
586 /* translate dma address base s.t. the source image offset is zero */
587 dma_addr = exynos_drm_fb_dma_addr(fb, 0)
588 + (state->src.x * fb->format->cpp[0])
589 + (state->src.y * fb->pitches[0]);
591 spin_lock_irqsave(&ctx->reg_slock, flags);
594 mixer_reg_writemask(ctx, MXR_GRAPHIC_CFG(win),
595 MXR_GRP_CFG_FORMAT_VAL(fmt), MXR_GRP_CFG_FORMAT_MASK);
598 mixer_reg_write(ctx, MXR_GRAPHIC_SPAN(win),
599 fb->pitches[0] / fb->format->cpp[0]);
601 val = MXR_GRP_WH_WIDTH(state->src.w);
602 val |= MXR_GRP_WH_HEIGHT(state->src.h);
603 val |= MXR_GRP_WH_H_SCALE(x_ratio);
604 val |= MXR_GRP_WH_V_SCALE(y_ratio);
605 mixer_reg_write(ctx, MXR_GRAPHIC_WH(win), val);
607 /* setup offsets in display image */
608 val = MXR_GRP_DXY_DX(dst_x_offset);
609 val |= MXR_GRP_DXY_DY(dst_y_offset);
610 mixer_reg_write(ctx, MXR_GRAPHIC_DXY(win), val);
612 /* set buffer address to mixer */
613 mixer_reg_write(ctx, MXR_GRAPHIC_BASE(win), dma_addr);
615 mixer_cfg_layer(ctx, win, priority, true);
616 mixer_cfg_gfx_blend(ctx, win, fb->format->has_alpha);
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);
623 spin_unlock_irqrestore(&ctx->reg_slock, flags);
625 mixer_regs_dump(ctx);
628 static void vp_win_reset(struct mixer_context *ctx)
630 unsigned int tries = 100;
632 vp_reg_write(ctx, VP_SRESET, VP_SRESET_PROCESSING);
634 /* waiting until VP_SRESET_PROCESSING is 0 */
635 if (~vp_reg_read(ctx, VP_SRESET) & VP_SRESET_PROCESSING)
639 WARN(tries == 0, "failed to reset Video Processor\n");
642 static void mixer_win_reset(struct mixer_context *ctx)
646 spin_lock_irqsave(&ctx->reg_slock, flags);
648 mixer_reg_writemask(ctx, MXR_CFG, MXR_CFG_DST_HDMI, MXR_CFG_DST_MASK);
650 /* set output in RGB888 mode */
651 mixer_reg_writemask(ctx, MXR_CFG, MXR_CFG_OUT_RGB888, MXR_CFG_OUT_MASK);
653 /* 16 beat burst in DMA */
654 mixer_reg_writemask(ctx, MXR_STATUS, MXR_STATUS_16_BURST,
655 MXR_STATUS_BURST_MASK);
657 /* reset default layer priority */
658 mixer_reg_write(ctx, MXR_LAYER_CFG, 0);
660 /* set all background colors to RGB (0,0,0) */
661 mixer_reg_write(ctx, MXR_BG_COLOR0, MXR_YCBCR_VAL(0, 128, 128));
662 mixer_reg_write(ctx, MXR_BG_COLOR1, MXR_YCBCR_VAL(0, 128, 128));
663 mixer_reg_write(ctx, MXR_BG_COLOR2, MXR_YCBCR_VAL(0, 128, 128));
665 if (test_bit(MXR_BIT_VP_ENABLED, &ctx->flags)) {
666 /* configuration of Video Processor Registers */
668 vp_default_filter(ctx);
671 /* disable all layers */
672 mixer_reg_writemask(ctx, MXR_CFG, 0, MXR_CFG_GRP0_ENABLE);
673 mixer_reg_writemask(ctx, MXR_CFG, 0, MXR_CFG_GRP1_ENABLE);
674 if (test_bit(MXR_BIT_VP_ENABLED, &ctx->flags))
675 mixer_reg_writemask(ctx, MXR_CFG, 0, MXR_CFG_VP_ENABLE);
677 /* set all source image offsets to zero */
678 mixer_reg_write(ctx, MXR_GRAPHIC_SXY(0), 0);
679 mixer_reg_write(ctx, MXR_GRAPHIC_SXY(1), 0);
681 spin_unlock_irqrestore(&ctx->reg_slock, flags);
684 static irqreturn_t mixer_irq_handler(int irq, void *arg)
686 struct mixer_context *ctx = arg;
687 u32 val, base, shadow;
689 spin_lock(&ctx->reg_slock);
691 /* read interrupt status for handling and clearing flags for VSYNC */
692 val = mixer_reg_read(ctx, MXR_INT_STATUS);
695 if (val & MXR_INT_STATUS_VSYNC) {
696 /* vsync interrupt use different bit for read and clear */
697 val |= MXR_INT_CLEAR_VSYNC;
698 val &= ~MXR_INT_STATUS_VSYNC;
700 /* interlace scan need to check shadow register */
701 if (test_bit(MXR_BIT_INTERLACE, &ctx->flags)) {
702 base = mixer_reg_read(ctx, MXR_GRAPHIC_BASE(0));
703 shadow = mixer_reg_read(ctx, MXR_GRAPHIC_BASE_S(0));
707 base = mixer_reg_read(ctx, MXR_GRAPHIC_BASE(1));
708 shadow = mixer_reg_read(ctx, MXR_GRAPHIC_BASE_S(1));
713 drm_crtc_handle_vblank(&ctx->crtc->base);
717 /* clear interrupts */
718 mixer_reg_write(ctx, MXR_INT_STATUS, val);
720 spin_unlock(&ctx->reg_slock);
725 static int mixer_resources_init(struct mixer_context *mixer_ctx)
727 struct device *dev = &mixer_ctx->pdev->dev;
728 struct resource *res;
731 spin_lock_init(&mixer_ctx->reg_slock);
733 mixer_ctx->mixer = devm_clk_get(dev, "mixer");
734 if (IS_ERR(mixer_ctx->mixer)) {
735 dev_err(dev, "failed to get clock 'mixer'\n");
739 mixer_ctx->hdmi = devm_clk_get(dev, "hdmi");
740 if (IS_ERR(mixer_ctx->hdmi)) {
741 dev_err(dev, "failed to get clock 'hdmi'\n");
742 return PTR_ERR(mixer_ctx->hdmi);
745 mixer_ctx->sclk_hdmi = devm_clk_get(dev, "sclk_hdmi");
746 if (IS_ERR(mixer_ctx->sclk_hdmi)) {
747 dev_err(dev, "failed to get clock 'sclk_hdmi'\n");
750 res = platform_get_resource(mixer_ctx->pdev, IORESOURCE_MEM, 0);
752 dev_err(dev, "get memory resource failed.\n");
756 mixer_ctx->mixer_regs = devm_ioremap(dev, res->start,
758 if (mixer_ctx->mixer_regs == NULL) {
759 dev_err(dev, "register mapping failed.\n");
763 res = platform_get_resource(mixer_ctx->pdev, IORESOURCE_IRQ, 0);
765 dev_err(dev, "get interrupt resource failed.\n");
769 ret = devm_request_irq(dev, res->start, mixer_irq_handler,
770 0, "drm_mixer", mixer_ctx);
772 dev_err(dev, "request interrupt failed.\n");
775 mixer_ctx->irq = res->start;
780 static int vp_resources_init(struct mixer_context *mixer_ctx)
782 struct device *dev = &mixer_ctx->pdev->dev;
783 struct resource *res;
785 mixer_ctx->vp = devm_clk_get(dev, "vp");
786 if (IS_ERR(mixer_ctx->vp)) {
787 dev_err(dev, "failed to get clock 'vp'\n");
791 if (test_bit(MXR_BIT_HAS_SCLK, &mixer_ctx->flags)) {
792 mixer_ctx->sclk_mixer = devm_clk_get(dev, "sclk_mixer");
793 if (IS_ERR(mixer_ctx->sclk_mixer)) {
794 dev_err(dev, "failed to get clock 'sclk_mixer'\n");
797 mixer_ctx->mout_mixer = devm_clk_get(dev, "mout_mixer");
798 if (IS_ERR(mixer_ctx->mout_mixer)) {
799 dev_err(dev, "failed to get clock 'mout_mixer'\n");
803 if (mixer_ctx->sclk_hdmi && mixer_ctx->mout_mixer)
804 clk_set_parent(mixer_ctx->mout_mixer,
805 mixer_ctx->sclk_hdmi);
808 res = platform_get_resource(mixer_ctx->pdev, IORESOURCE_MEM, 1);
810 dev_err(dev, "get memory resource failed.\n");
814 mixer_ctx->vp_regs = devm_ioremap(dev, res->start,
816 if (mixer_ctx->vp_regs == NULL) {
817 dev_err(dev, "register mapping failed.\n");
824 static int mixer_initialize(struct mixer_context *mixer_ctx,
825 struct drm_device *drm_dev)
828 struct exynos_drm_private *priv;
829 priv = drm_dev->dev_private;
831 mixer_ctx->drm_dev = drm_dev;
833 /* acquire resources: regs, irqs, clocks */
834 ret = mixer_resources_init(mixer_ctx);
836 DRM_ERROR("mixer_resources_init failed ret=%d\n", ret);
840 if (test_bit(MXR_BIT_VP_ENABLED, &mixer_ctx->flags)) {
841 /* acquire vp resources: regs, irqs, clocks */
842 ret = vp_resources_init(mixer_ctx);
844 DRM_ERROR("vp_resources_init failed ret=%d\n", ret);
849 return drm_iommu_attach_device(drm_dev, mixer_ctx->dev);
852 static void mixer_ctx_remove(struct mixer_context *mixer_ctx)
854 drm_iommu_detach_device(mixer_ctx->drm_dev, mixer_ctx->dev);
857 static int mixer_enable_vblank(struct exynos_drm_crtc *crtc)
859 struct mixer_context *mixer_ctx = crtc->ctx;
861 __set_bit(MXR_BIT_VSYNC, &mixer_ctx->flags);
862 if (!test_bit(MXR_BIT_POWERED, &mixer_ctx->flags))
865 /* enable vsync interrupt */
866 mixer_reg_writemask(mixer_ctx, MXR_INT_STATUS, ~0, MXR_INT_CLEAR_VSYNC);
867 mixer_reg_writemask(mixer_ctx, MXR_INT_EN, ~0, MXR_INT_EN_VSYNC);
872 static void mixer_disable_vblank(struct exynos_drm_crtc *crtc)
874 struct mixer_context *mixer_ctx = crtc->ctx;
876 __clear_bit(MXR_BIT_VSYNC, &mixer_ctx->flags);
878 if (!test_bit(MXR_BIT_POWERED, &mixer_ctx->flags))
881 /* disable vsync interrupt */
882 mixer_reg_writemask(mixer_ctx, MXR_INT_STATUS, ~0, MXR_INT_CLEAR_VSYNC);
883 mixer_reg_writemask(mixer_ctx, MXR_INT_EN, 0, MXR_INT_EN_VSYNC);
886 static void mixer_atomic_begin(struct exynos_drm_crtc *crtc)
888 struct mixer_context *mixer_ctx = crtc->ctx;
890 if (!test_bit(MXR_BIT_POWERED, &mixer_ctx->flags))
893 mixer_vsync_set_update(mixer_ctx, false);
896 static void mixer_update_plane(struct exynos_drm_crtc *crtc,
897 struct exynos_drm_plane *plane)
899 struct mixer_context *mixer_ctx = crtc->ctx;
901 DRM_DEBUG_KMS("win: %d\n", plane->index);
903 if (!test_bit(MXR_BIT_POWERED, &mixer_ctx->flags))
906 if (plane->index == VP_DEFAULT_WIN)
907 vp_video_buffer(mixer_ctx, plane);
909 mixer_graph_buffer(mixer_ctx, plane);
912 static void mixer_disable_plane(struct exynos_drm_crtc *crtc,
913 struct exynos_drm_plane *plane)
915 struct mixer_context *mixer_ctx = crtc->ctx;
918 DRM_DEBUG_KMS("win: %d\n", plane->index);
920 if (!test_bit(MXR_BIT_POWERED, &mixer_ctx->flags))
923 spin_lock_irqsave(&mixer_ctx->reg_slock, flags);
924 mixer_cfg_layer(mixer_ctx, plane->index, 0, false);
925 spin_unlock_irqrestore(&mixer_ctx->reg_slock, flags);
928 static void mixer_atomic_flush(struct exynos_drm_crtc *crtc)
930 struct mixer_context *mixer_ctx = crtc->ctx;
932 if (!test_bit(MXR_BIT_POWERED, &mixer_ctx->flags))
935 mixer_vsync_set_update(mixer_ctx, true);
936 exynos_crtc_handle_event(crtc);
939 static void mixer_enable(struct exynos_drm_crtc *crtc)
941 struct mixer_context *ctx = crtc->ctx;
943 if (test_bit(MXR_BIT_POWERED, &ctx->flags))
946 pm_runtime_get_sync(ctx->dev);
948 exynos_drm_pipe_clk_enable(crtc, true);
950 mixer_vsync_set_update(ctx, false);
952 mixer_reg_writemask(ctx, MXR_STATUS, ~0, MXR_STATUS_SOFT_RESET);
954 if (test_bit(MXR_BIT_VSYNC, &ctx->flags)) {
955 mixer_reg_writemask(ctx, MXR_INT_STATUS, ~0,
956 MXR_INT_CLEAR_VSYNC);
957 mixer_reg_writemask(ctx, MXR_INT_EN, ~0, MXR_INT_EN_VSYNC);
959 mixer_win_reset(ctx);
963 mixer_vsync_set_update(ctx, true);
965 set_bit(MXR_BIT_POWERED, &ctx->flags);
968 static void mixer_disable(struct exynos_drm_crtc *crtc)
970 struct mixer_context *ctx = crtc->ctx;
973 if (!test_bit(MXR_BIT_POWERED, &ctx->flags))
977 mixer_regs_dump(ctx);
979 for (i = 0; i < MIXER_WIN_NR; i++)
980 mixer_disable_plane(crtc, &ctx->planes[i]);
982 exynos_drm_pipe_clk_enable(crtc, false);
984 pm_runtime_put(ctx->dev);
986 clear_bit(MXR_BIT_POWERED, &ctx->flags);
989 static int mixer_mode_valid(struct exynos_drm_crtc *crtc,
990 const struct drm_display_mode *mode)
992 struct mixer_context *ctx = crtc->ctx;
993 u32 w = mode->hdisplay, h = mode->vdisplay;
995 DRM_DEBUG_KMS("xres=%d, yres=%d, refresh=%d, intl=%d\n", w, h,
996 mode->vrefresh, !!(mode->flags & DRM_MODE_FLAG_INTERLACE));
998 if (ctx->mxr_ver == MXR_VER_128_0_0_184)
1001 if ((w >= 464 && w <= 720 && h >= 261 && h <= 576) ||
1002 (w >= 1024 && w <= 1280 && h >= 576 && h <= 720) ||
1003 (w >= 1664 && w <= 1920 && h >= 936 && h <= 1080))
1006 if ((w == 1024 && h == 768) ||
1007 (w == 1366 && h == 768) ||
1008 (w == 1280 && h == 1024))
1014 static bool mixer_mode_fixup(struct exynos_drm_crtc *crtc,
1015 const struct drm_display_mode *mode,
1016 struct drm_display_mode *adjusted_mode)
1018 struct mixer_context *ctx = crtc->ctx;
1019 int width = mode->hdisplay, height = mode->vdisplay, i;
1022 int hdisplay, vdisplay, htotal, vtotal, scan_val;
1023 } static const modes[] = {
1024 { 720, 480, 858, 525, MXR_CFG_SCAN_NTSC | MXR_CFG_SCAN_SD },
1025 { 720, 576, 864, 625, MXR_CFG_SCAN_PAL | MXR_CFG_SCAN_SD },
1026 { 1280, 720, 1650, 750, MXR_CFG_SCAN_HD_720 | MXR_CFG_SCAN_HD },
1027 { 1920, 1080, 2200, 1125, MXR_CFG_SCAN_HD_1080 |
1031 if (mode->flags & DRM_MODE_FLAG_INTERLACE)
1032 __set_bit(MXR_BIT_INTERLACE, &ctx->flags);
1034 __clear_bit(MXR_BIT_INTERLACE, &ctx->flags);
1036 if (ctx->mxr_ver == MXR_VER_128_0_0_184)
1039 for (i = 0; i < ARRAY_SIZE(modes); ++i)
1040 if (width <= modes[i].hdisplay && height <= modes[i].vdisplay) {
1041 ctx->scan_value = modes[i].scan_val;
1042 if (width < modes[i].hdisplay ||
1043 height < modes[i].vdisplay) {
1044 adjusted_mode->hdisplay = modes[i].hdisplay;
1045 adjusted_mode->hsync_start = modes[i].hdisplay;
1046 adjusted_mode->hsync_end = modes[i].htotal;
1047 adjusted_mode->htotal = modes[i].htotal;
1048 adjusted_mode->vdisplay = modes[i].vdisplay;
1049 adjusted_mode->vsync_start = modes[i].vdisplay;
1050 adjusted_mode->vsync_end = modes[i].vtotal;
1051 adjusted_mode->vtotal = modes[i].vtotal;
1060 static const struct exynos_drm_crtc_ops mixer_crtc_ops = {
1061 .enable = mixer_enable,
1062 .disable = mixer_disable,
1063 .enable_vblank = mixer_enable_vblank,
1064 .disable_vblank = mixer_disable_vblank,
1065 .atomic_begin = mixer_atomic_begin,
1066 .update_plane = mixer_update_plane,
1067 .disable_plane = mixer_disable_plane,
1068 .atomic_flush = mixer_atomic_flush,
1069 .mode_valid = mixer_mode_valid,
1070 .mode_fixup = mixer_mode_fixup,
1073 static const struct mixer_drv_data exynos5420_mxr_drv_data = {
1074 .version = MXR_VER_128_0_0_184,
1078 static const struct mixer_drv_data exynos5250_mxr_drv_data = {
1079 .version = MXR_VER_16_0_33_0,
1083 static const struct mixer_drv_data exynos4212_mxr_drv_data = {
1084 .version = MXR_VER_0_0_0_16,
1088 static const struct mixer_drv_data exynos4210_mxr_drv_data = {
1089 .version = MXR_VER_0_0_0_16,
1094 static const struct of_device_id mixer_match_types[] = {
1096 .compatible = "samsung,exynos4210-mixer",
1097 .data = &exynos4210_mxr_drv_data,
1099 .compatible = "samsung,exynos4212-mixer",
1100 .data = &exynos4212_mxr_drv_data,
1102 .compatible = "samsung,exynos5-mixer",
1103 .data = &exynos5250_mxr_drv_data,
1105 .compatible = "samsung,exynos5250-mixer",
1106 .data = &exynos5250_mxr_drv_data,
1108 .compatible = "samsung,exynos5420-mixer",
1109 .data = &exynos5420_mxr_drv_data,
1114 MODULE_DEVICE_TABLE(of, mixer_match_types);
1116 static int mixer_bind(struct device *dev, struct device *manager, void *data)
1118 struct mixer_context *ctx = dev_get_drvdata(dev);
1119 struct drm_device *drm_dev = data;
1120 struct exynos_drm_plane *exynos_plane;
1124 ret = mixer_initialize(ctx, drm_dev);
1128 for (i = 0; i < MIXER_WIN_NR; i++) {
1129 if (i == VP_DEFAULT_WIN && !test_bit(MXR_BIT_VP_ENABLED,
1133 ret = exynos_plane_init(drm_dev, &ctx->planes[i], i,
1139 exynos_plane = &ctx->planes[DEFAULT_WIN];
1140 ctx->crtc = exynos_drm_crtc_create(drm_dev, &exynos_plane->base,
1141 EXYNOS_DISPLAY_TYPE_HDMI, &mixer_crtc_ops, ctx);
1142 if (IS_ERR(ctx->crtc)) {
1143 mixer_ctx_remove(ctx);
1144 ret = PTR_ERR(ctx->crtc);
1151 devm_kfree(dev, ctx);
1155 static void mixer_unbind(struct device *dev, struct device *master, void *data)
1157 struct mixer_context *ctx = dev_get_drvdata(dev);
1159 mixer_ctx_remove(ctx);
1162 static const struct component_ops mixer_component_ops = {
1164 .unbind = mixer_unbind,
1167 static int mixer_probe(struct platform_device *pdev)
1169 struct device *dev = &pdev->dev;
1170 const struct mixer_drv_data *drv;
1171 struct mixer_context *ctx;
1174 ctx = devm_kzalloc(&pdev->dev, sizeof(*ctx), GFP_KERNEL);
1176 DRM_ERROR("failed to alloc mixer context.\n");
1180 drv = of_device_get_match_data(dev);
1184 ctx->mxr_ver = drv->version;
1186 if (drv->is_vp_enabled)
1187 __set_bit(MXR_BIT_VP_ENABLED, &ctx->flags);
1189 __set_bit(MXR_BIT_HAS_SCLK, &ctx->flags);
1191 platform_set_drvdata(pdev, ctx);
1193 ret = component_add(&pdev->dev, &mixer_component_ops);
1195 pm_runtime_enable(dev);
1200 static int mixer_remove(struct platform_device *pdev)
1202 pm_runtime_disable(&pdev->dev);
1204 component_del(&pdev->dev, &mixer_component_ops);
1209 static int __maybe_unused exynos_mixer_suspend(struct device *dev)
1211 struct mixer_context *ctx = dev_get_drvdata(dev);
1213 clk_disable_unprepare(ctx->hdmi);
1214 clk_disable_unprepare(ctx->mixer);
1215 if (test_bit(MXR_BIT_VP_ENABLED, &ctx->flags)) {
1216 clk_disable_unprepare(ctx->vp);
1217 if (test_bit(MXR_BIT_HAS_SCLK, &ctx->flags))
1218 clk_disable_unprepare(ctx->sclk_mixer);
1224 static int __maybe_unused exynos_mixer_resume(struct device *dev)
1226 struct mixer_context *ctx = dev_get_drvdata(dev);
1229 ret = clk_prepare_enable(ctx->mixer);
1231 DRM_ERROR("Failed to prepare_enable the mixer clk [%d]\n", ret);
1234 ret = clk_prepare_enable(ctx->hdmi);
1236 DRM_ERROR("Failed to prepare_enable the hdmi clk [%d]\n", ret);
1239 if (test_bit(MXR_BIT_VP_ENABLED, &ctx->flags)) {
1240 ret = clk_prepare_enable(ctx->vp);
1242 DRM_ERROR("Failed to prepare_enable the vp clk [%d]\n",
1246 if (test_bit(MXR_BIT_HAS_SCLK, &ctx->flags)) {
1247 ret = clk_prepare_enable(ctx->sclk_mixer);
1249 DRM_ERROR("Failed to prepare_enable the " \
1250 "sclk_mixer clk [%d]\n",
1260 static const struct dev_pm_ops exynos_mixer_pm_ops = {
1261 SET_RUNTIME_PM_OPS(exynos_mixer_suspend, exynos_mixer_resume, NULL)
1264 struct platform_driver mixer_driver = {
1266 .name = "exynos-mixer",
1267 .owner = THIS_MODULE,
1268 .pm = &exynos_mixer_pm_ops,
1269 .of_match_table = mixer_match_types,
1271 .probe = mixer_probe,
1272 .remove = mixer_remove,