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/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 struct mixer_resources {
72 void __iomem *mixer_regs;
73 void __iomem *vp_regs;
78 struct clk *sclk_mixer;
79 struct clk *sclk_hdmi;
80 struct clk *mout_mixer;
83 enum mixer_version_id {
89 enum mixer_flag_bits {
97 static const uint32_t mixer_formats[] = {
107 static const uint32_t vp_formats[] = {
112 struct mixer_context {
113 struct platform_device *pdev;
115 struct drm_device *drm_dev;
116 struct exynos_drm_crtc *crtc;
117 struct exynos_drm_plane planes[MIXER_WIN_NR];
120 struct mixer_resources mixer_res;
121 enum mixer_version_id mxr_ver;
124 struct mixer_drv_data {
125 enum mixer_version_id version;
130 static const struct exynos_drm_plane_config plane_configs[MIXER_WIN_NR] = {
133 .type = DRM_PLANE_TYPE_PRIMARY,
134 .pixel_formats = mixer_formats,
135 .num_pixel_formats = ARRAY_SIZE(mixer_formats),
136 .capabilities = EXYNOS_DRM_PLANE_CAP_DOUBLE |
137 EXYNOS_DRM_PLANE_CAP_ZPOS,
140 .type = DRM_PLANE_TYPE_CURSOR,
141 .pixel_formats = mixer_formats,
142 .num_pixel_formats = ARRAY_SIZE(mixer_formats),
143 .capabilities = EXYNOS_DRM_PLANE_CAP_DOUBLE |
144 EXYNOS_DRM_PLANE_CAP_ZPOS,
147 .type = DRM_PLANE_TYPE_OVERLAY,
148 .pixel_formats = vp_formats,
149 .num_pixel_formats = ARRAY_SIZE(vp_formats),
150 .capabilities = EXYNOS_DRM_PLANE_CAP_SCALE |
151 EXYNOS_DRM_PLANE_CAP_ZPOS |
152 EXYNOS_DRM_PLANE_CAP_TILE,
156 static const u8 filter_y_horiz_tap8[] = {
157 0, -1, -1, -1, -1, -1, -1, -1,
158 -1, -1, -1, -1, -1, 0, 0, 0,
159 0, 2, 4, 5, 6, 6, 6, 6,
160 6, 5, 5, 4, 3, 2, 1, 1,
161 0, -6, -12, -16, -18, -20, -21, -20,
162 -20, -18, -16, -13, -10, -8, -5, -2,
163 127, 126, 125, 121, 114, 107, 99, 89,
164 79, 68, 57, 46, 35, 25, 16, 8,
167 static const u8 filter_y_vert_tap4[] = {
168 0, -3, -6, -8, -8, -8, -8, -7,
169 -6, -5, -4, -3, -2, -1, -1, 0,
170 127, 126, 124, 118, 111, 102, 92, 81,
171 70, 59, 48, 37, 27, 19, 11, 5,
172 0, 5, 11, 19, 27, 37, 48, 59,
173 70, 81, 92, 102, 111, 118, 124, 126,
174 0, 0, -1, -1, -2, -3, -4, -5,
175 -6, -7, -8, -8, -8, -8, -6, -3,
178 static const u8 filter_cr_horiz_tap4[] = {
179 0, -3, -6, -8, -8, -8, -8, -7,
180 -6, -5, -4, -3, -2, -1, -1, 0,
181 127, 126, 124, 118, 111, 102, 92, 81,
182 70, 59, 48, 37, 27, 19, 11, 5,
185 static inline bool is_alpha_format(unsigned int pixel_format)
187 switch (pixel_format) {
188 case DRM_FORMAT_ARGB8888:
189 case DRM_FORMAT_ARGB1555:
190 case DRM_FORMAT_ARGB4444:
197 static inline u32 vp_reg_read(struct mixer_resources *res, u32 reg_id)
199 return readl(res->vp_regs + reg_id);
202 static inline void vp_reg_write(struct mixer_resources *res, u32 reg_id,
205 writel(val, res->vp_regs + reg_id);
208 static inline void vp_reg_writemask(struct mixer_resources *res, u32 reg_id,
211 u32 old = vp_reg_read(res, reg_id);
213 val = (val & mask) | (old & ~mask);
214 writel(val, res->vp_regs + reg_id);
217 static inline u32 mixer_reg_read(struct mixer_resources *res, u32 reg_id)
219 return readl(res->mixer_regs + reg_id);
222 static inline void mixer_reg_write(struct mixer_resources *res, u32 reg_id,
225 writel(val, res->mixer_regs + reg_id);
228 static inline void mixer_reg_writemask(struct mixer_resources *res,
229 u32 reg_id, u32 val, u32 mask)
231 u32 old = mixer_reg_read(res, reg_id);
233 val = (val & mask) | (old & ~mask);
234 writel(val, res->mixer_regs + reg_id);
237 static void mixer_regs_dump(struct mixer_context *ctx)
239 #define DUMPREG(reg_id) \
241 DRM_DEBUG_KMS(#reg_id " = %08x\n", \
242 (u32)readl(ctx->mixer_res.mixer_regs + reg_id)); \
248 DUMPREG(MXR_INT_STATUS);
250 DUMPREG(MXR_LAYER_CFG);
251 DUMPREG(MXR_VIDEO_CFG);
253 DUMPREG(MXR_GRAPHIC0_CFG);
254 DUMPREG(MXR_GRAPHIC0_BASE);
255 DUMPREG(MXR_GRAPHIC0_SPAN);
256 DUMPREG(MXR_GRAPHIC0_WH);
257 DUMPREG(MXR_GRAPHIC0_SXY);
258 DUMPREG(MXR_GRAPHIC0_DXY);
260 DUMPREG(MXR_GRAPHIC1_CFG);
261 DUMPREG(MXR_GRAPHIC1_BASE);
262 DUMPREG(MXR_GRAPHIC1_SPAN);
263 DUMPREG(MXR_GRAPHIC1_WH);
264 DUMPREG(MXR_GRAPHIC1_SXY);
265 DUMPREG(MXR_GRAPHIC1_DXY);
269 static void vp_regs_dump(struct mixer_context *ctx)
271 #define DUMPREG(reg_id) \
273 DRM_DEBUG_KMS(#reg_id " = %08x\n", \
274 (u32) readl(ctx->mixer_res.vp_regs + reg_id)); \
279 DUMPREG(VP_SHADOW_UPDATE);
280 DUMPREG(VP_FIELD_ID);
282 DUMPREG(VP_IMG_SIZE_Y);
283 DUMPREG(VP_IMG_SIZE_C);
284 DUMPREG(VP_PER_RATE_CTRL);
285 DUMPREG(VP_TOP_Y_PTR);
286 DUMPREG(VP_BOT_Y_PTR);
287 DUMPREG(VP_TOP_C_PTR);
288 DUMPREG(VP_BOT_C_PTR);
289 DUMPREG(VP_ENDIAN_MODE);
290 DUMPREG(VP_SRC_H_POSITION);
291 DUMPREG(VP_SRC_V_POSITION);
292 DUMPREG(VP_SRC_WIDTH);
293 DUMPREG(VP_SRC_HEIGHT);
294 DUMPREG(VP_DST_H_POSITION);
295 DUMPREG(VP_DST_V_POSITION);
296 DUMPREG(VP_DST_WIDTH);
297 DUMPREG(VP_DST_HEIGHT);
304 static inline void vp_filter_set(struct mixer_resources *res,
305 int reg_id, const u8 *data, unsigned int size)
307 /* assure 4-byte align */
309 for (; size; size -= 4, reg_id += 4, data += 4) {
310 u32 val = (data[0] << 24) | (data[1] << 16) |
311 (data[2] << 8) | data[3];
312 vp_reg_write(res, reg_id, val);
316 static void vp_default_filter(struct mixer_resources *res)
318 vp_filter_set(res, VP_POLY8_Y0_LL,
319 filter_y_horiz_tap8, sizeof(filter_y_horiz_tap8));
320 vp_filter_set(res, VP_POLY4_Y0_LL,
321 filter_y_vert_tap4, sizeof(filter_y_vert_tap4));
322 vp_filter_set(res, VP_POLY4_C0_LL,
323 filter_cr_horiz_tap4, sizeof(filter_cr_horiz_tap4));
326 static void mixer_cfg_gfx_blend(struct mixer_context *ctx, unsigned int win,
329 struct mixer_resources *res = &ctx->mixer_res;
332 val = MXR_GRP_CFG_COLOR_KEY_DISABLE; /* no blank key */
334 /* blending based on pixel alpha */
335 val |= MXR_GRP_CFG_BLEND_PRE_MUL;
336 val |= MXR_GRP_CFG_PIXEL_BLEND_EN;
338 mixer_reg_writemask(res, MXR_GRAPHIC_CFG(win),
339 val, MXR_GRP_CFG_MISC_MASK);
342 static void mixer_cfg_vp_blend(struct mixer_context *ctx)
344 struct mixer_resources *res = &ctx->mixer_res;
348 * No blending at the moment since the NV12/NV21 pixelformats don't
349 * have an alpha channel. However the mixer supports a global alpha
350 * value for a layer. Once this functionality is exposed, we can
351 * support blending of the video layer through this.
354 mixer_reg_write(res, MXR_VIDEO_CFG, val);
357 static void mixer_vsync_set_update(struct mixer_context *ctx, bool enable)
359 struct mixer_resources *res = &ctx->mixer_res;
361 /* block update on vsync */
362 mixer_reg_writemask(res, MXR_STATUS, enable ?
363 MXR_STATUS_SYNC_ENABLE : 0, MXR_STATUS_SYNC_ENABLE);
365 if (test_bit(MXR_BIT_VP_ENABLED, &ctx->flags))
366 vp_reg_write(res, VP_SHADOW_UPDATE, enable ?
367 VP_SHADOW_UPDATE_ENABLE : 0);
370 static void mixer_cfg_scan(struct mixer_context *ctx, unsigned int height)
372 struct mixer_resources *res = &ctx->mixer_res;
375 /* choosing between interlace and progressive mode */
376 val = test_bit(MXR_BIT_INTERLACE, &ctx->flags) ?
377 MXR_CFG_SCAN_INTERLACE : MXR_CFG_SCAN_PROGRESSIVE;
379 if (ctx->mxr_ver != MXR_VER_128_0_0_184) {
380 /* choosing between proper HD and SD mode */
382 val |= MXR_CFG_SCAN_NTSC | MXR_CFG_SCAN_SD;
383 else if (height <= 576)
384 val |= MXR_CFG_SCAN_PAL | MXR_CFG_SCAN_SD;
385 else if (height <= 720)
386 val |= MXR_CFG_SCAN_HD_720 | MXR_CFG_SCAN_HD;
387 else if (height <= 1080)
388 val |= MXR_CFG_SCAN_HD_1080 | MXR_CFG_SCAN_HD;
390 val |= MXR_CFG_SCAN_HD_720 | MXR_CFG_SCAN_HD;
393 mixer_reg_writemask(res, MXR_CFG, val, MXR_CFG_SCAN_MASK);
396 static void mixer_cfg_rgb_fmt(struct mixer_context *ctx, unsigned int height)
398 struct mixer_resources *res = &ctx->mixer_res;
404 val = MXR_CFG_RGB601_0_255;
409 val = MXR_CFG_RGB709_16_235;
410 /* Configure the BT.709 CSC matrix for full range RGB. */
411 mixer_reg_write(res, MXR_CM_COEFF_Y,
412 MXR_CSC_CT( 0.184, 0.614, 0.063) |
413 MXR_CM_COEFF_RGB_FULL);
414 mixer_reg_write(res, MXR_CM_COEFF_CB,
415 MXR_CSC_CT(-0.102, -0.338, 0.440));
416 mixer_reg_write(res, MXR_CM_COEFF_CR,
417 MXR_CSC_CT( 0.440, -0.399, -0.040));
421 mixer_reg_writemask(res, MXR_CFG, val, MXR_CFG_RGB_FMT_MASK);
424 static void mixer_cfg_layer(struct mixer_context *ctx, unsigned int win,
425 unsigned int priority, bool enable)
427 struct mixer_resources *res = &ctx->mixer_res;
428 u32 val = enable ? ~0 : 0;
432 mixer_reg_writemask(res, MXR_CFG, val, MXR_CFG_GRP0_ENABLE);
433 mixer_reg_writemask(res, MXR_LAYER_CFG,
434 MXR_LAYER_CFG_GRP0_VAL(priority),
435 MXR_LAYER_CFG_GRP0_MASK);
438 mixer_reg_writemask(res, MXR_CFG, val, MXR_CFG_GRP1_ENABLE);
439 mixer_reg_writemask(res, MXR_LAYER_CFG,
440 MXR_LAYER_CFG_GRP1_VAL(priority),
441 MXR_LAYER_CFG_GRP1_MASK);
445 if (test_bit(MXR_BIT_VP_ENABLED, &ctx->flags)) {
446 vp_reg_writemask(res, VP_ENABLE, val, VP_ENABLE_ON);
447 mixer_reg_writemask(res, MXR_CFG, val,
449 mixer_reg_writemask(res, MXR_LAYER_CFG,
450 MXR_LAYER_CFG_VP_VAL(priority),
451 MXR_LAYER_CFG_VP_MASK);
457 static void mixer_run(struct mixer_context *ctx)
459 struct mixer_resources *res = &ctx->mixer_res;
461 mixer_reg_writemask(res, MXR_STATUS, ~0, MXR_STATUS_REG_RUN);
464 static void mixer_stop(struct mixer_context *ctx)
466 struct mixer_resources *res = &ctx->mixer_res;
469 mixer_reg_writemask(res, MXR_STATUS, 0, MXR_STATUS_REG_RUN);
471 while (!(mixer_reg_read(res, MXR_STATUS) & MXR_STATUS_REG_IDLE) &&
473 usleep_range(10000, 12000);
476 static void vp_video_buffer(struct mixer_context *ctx,
477 struct exynos_drm_plane *plane)
479 struct exynos_drm_plane_state *state =
480 to_exynos_plane_state(plane->base.state);
481 struct drm_display_mode *mode = &state->base.crtc->state->adjusted_mode;
482 struct mixer_resources *res = &ctx->mixer_res;
483 struct drm_framebuffer *fb = state->base.fb;
484 unsigned int priority = state->base.normalized_zpos + 1;
486 dma_addr_t luma_addr[2], chroma_addr[2];
487 bool is_tiled, is_nv21;
490 is_nv21 = (fb->format->format == DRM_FORMAT_NV21);
491 is_tiled = (fb->modifier == DRM_FORMAT_MOD_SAMSUNG_64_32_TILE);
493 luma_addr[0] = exynos_drm_fb_dma_addr(fb, 0);
494 chroma_addr[0] = exynos_drm_fb_dma_addr(fb, 1);
496 if (mode->flags & DRM_MODE_FLAG_INTERLACE) {
497 __set_bit(MXR_BIT_INTERLACE, &ctx->flags);
499 luma_addr[1] = luma_addr[0] + 0x40;
500 chroma_addr[1] = chroma_addr[0] + 0x40;
502 luma_addr[1] = luma_addr[0] + fb->pitches[0];
503 chroma_addr[1] = chroma_addr[0] + fb->pitches[0];
506 __clear_bit(MXR_BIT_INTERLACE, &ctx->flags);
511 spin_lock_irqsave(&res->reg_slock, flags);
513 /* interlace or progressive scan mode */
514 val = (test_bit(MXR_BIT_INTERLACE, &ctx->flags) ? ~0 : 0);
515 vp_reg_writemask(res, VP_MODE, val, VP_MODE_LINE_SKIP);
518 val = (is_nv21 ? VP_MODE_NV21 : VP_MODE_NV12);
519 val |= (is_tiled ? VP_MODE_MEM_TILED : VP_MODE_MEM_LINEAR);
520 vp_reg_writemask(res, VP_MODE, val, VP_MODE_FMT_MASK);
522 /* setting size of input image */
523 vp_reg_write(res, VP_IMG_SIZE_Y, VP_IMG_HSIZE(fb->pitches[0]) |
524 VP_IMG_VSIZE(fb->height));
525 /* chroma plane for NV12/NV21 is half the height of the luma plane */
526 vp_reg_write(res, VP_IMG_SIZE_C, VP_IMG_HSIZE(fb->pitches[0]) |
527 VP_IMG_VSIZE(fb->height / 2));
529 vp_reg_write(res, VP_SRC_WIDTH, state->src.w);
530 vp_reg_write(res, VP_SRC_HEIGHT, state->src.h);
531 vp_reg_write(res, VP_SRC_H_POSITION,
532 VP_SRC_H_POSITION_VAL(state->src.x));
533 vp_reg_write(res, VP_SRC_V_POSITION, state->src.y);
535 vp_reg_write(res, VP_DST_WIDTH, state->crtc.w);
536 vp_reg_write(res, VP_DST_H_POSITION, state->crtc.x);
537 if (test_bit(MXR_BIT_INTERLACE, &ctx->flags)) {
538 vp_reg_write(res, VP_DST_HEIGHT, state->crtc.h / 2);
539 vp_reg_write(res, VP_DST_V_POSITION, state->crtc.y / 2);
541 vp_reg_write(res, VP_DST_HEIGHT, state->crtc.h);
542 vp_reg_write(res, VP_DST_V_POSITION, state->crtc.y);
545 vp_reg_write(res, VP_H_RATIO, state->h_ratio);
546 vp_reg_write(res, VP_V_RATIO, state->v_ratio);
548 vp_reg_write(res, VP_ENDIAN_MODE, VP_ENDIAN_MODE_LITTLE);
550 /* set buffer address to vp */
551 vp_reg_write(res, VP_TOP_Y_PTR, luma_addr[0]);
552 vp_reg_write(res, VP_BOT_Y_PTR, luma_addr[1]);
553 vp_reg_write(res, VP_TOP_C_PTR, chroma_addr[0]);
554 vp_reg_write(res, VP_BOT_C_PTR, chroma_addr[1]);
556 mixer_cfg_scan(ctx, mode->vdisplay);
557 mixer_cfg_rgb_fmt(ctx, mode->vdisplay);
558 mixer_cfg_layer(ctx, plane->index, priority, true);
559 mixer_cfg_vp_blend(ctx);
562 spin_unlock_irqrestore(&res->reg_slock, flags);
564 mixer_regs_dump(ctx);
568 static void mixer_layer_update(struct mixer_context *ctx)
570 struct mixer_resources *res = &ctx->mixer_res;
572 mixer_reg_writemask(res, MXR_CFG, ~0, MXR_CFG_LAYER_UPDATE);
575 static void mixer_graph_buffer(struct mixer_context *ctx,
576 struct exynos_drm_plane *plane)
578 struct exynos_drm_plane_state *state =
579 to_exynos_plane_state(plane->base.state);
580 struct drm_display_mode *mode = &state->base.crtc->state->adjusted_mode;
581 struct mixer_resources *res = &ctx->mixer_res;
582 struct drm_framebuffer *fb = state->base.fb;
583 unsigned int priority = state->base.normalized_zpos + 1;
585 unsigned int win = plane->index;
586 unsigned int x_ratio = 0, y_ratio = 0;
587 unsigned int dst_x_offset, dst_y_offset;
592 switch (fb->format->format) {
593 case DRM_FORMAT_XRGB4444:
594 case DRM_FORMAT_ARGB4444:
595 fmt = MXR_FORMAT_ARGB4444;
598 case DRM_FORMAT_XRGB1555:
599 case DRM_FORMAT_ARGB1555:
600 fmt = MXR_FORMAT_ARGB1555;
603 case DRM_FORMAT_RGB565:
604 fmt = MXR_FORMAT_RGB565;
607 case DRM_FORMAT_XRGB8888:
608 case DRM_FORMAT_ARGB8888:
610 fmt = MXR_FORMAT_ARGB8888;
614 /* ratio is already checked by common plane code */
615 x_ratio = state->h_ratio == (1 << 15);
616 y_ratio = state->v_ratio == (1 << 15);
618 dst_x_offset = state->crtc.x;
619 dst_y_offset = state->crtc.y;
621 /* translate dma address base s.t. the source image offset is zero */
622 dma_addr = exynos_drm_fb_dma_addr(fb, 0)
623 + (state->src.x * fb->format->cpp[0])
624 + (state->src.y * fb->pitches[0]);
626 if (mode->flags & DRM_MODE_FLAG_INTERLACE)
627 __set_bit(MXR_BIT_INTERLACE, &ctx->flags);
629 __clear_bit(MXR_BIT_INTERLACE, &ctx->flags);
631 spin_lock_irqsave(&res->reg_slock, flags);
634 mixer_reg_writemask(res, MXR_GRAPHIC_CFG(win),
635 MXR_GRP_CFG_FORMAT_VAL(fmt), MXR_GRP_CFG_FORMAT_MASK);
638 mixer_reg_write(res, MXR_GRAPHIC_SPAN(win),
639 fb->pitches[0] / fb->format->cpp[0]);
641 /* setup display size */
642 if (ctx->mxr_ver == MXR_VER_128_0_0_184 &&
643 win == DEFAULT_WIN) {
644 val = MXR_MXR_RES_HEIGHT(mode->vdisplay);
645 val |= MXR_MXR_RES_WIDTH(mode->hdisplay);
646 mixer_reg_write(res, MXR_RESOLUTION, val);
649 val = MXR_GRP_WH_WIDTH(state->src.w);
650 val |= MXR_GRP_WH_HEIGHT(state->src.h);
651 val |= MXR_GRP_WH_H_SCALE(x_ratio);
652 val |= MXR_GRP_WH_V_SCALE(y_ratio);
653 mixer_reg_write(res, MXR_GRAPHIC_WH(win), val);
655 /* setup offsets in display image */
656 val = MXR_GRP_DXY_DX(dst_x_offset);
657 val |= MXR_GRP_DXY_DY(dst_y_offset);
658 mixer_reg_write(res, MXR_GRAPHIC_DXY(win), val);
660 /* set buffer address to mixer */
661 mixer_reg_write(res, MXR_GRAPHIC_BASE(win), dma_addr);
663 mixer_cfg_scan(ctx, mode->vdisplay);
664 mixer_cfg_rgb_fmt(ctx, mode->vdisplay);
665 mixer_cfg_layer(ctx, win, priority, true);
666 mixer_cfg_gfx_blend(ctx, win, is_alpha_format(fb->format->format));
668 /* layer update mandatory for mixer 16.0.33.0 */
669 if (ctx->mxr_ver == MXR_VER_16_0_33_0 ||
670 ctx->mxr_ver == MXR_VER_128_0_0_184)
671 mixer_layer_update(ctx);
675 spin_unlock_irqrestore(&res->reg_slock, flags);
677 mixer_regs_dump(ctx);
680 static void vp_win_reset(struct mixer_context *ctx)
682 struct mixer_resources *res = &ctx->mixer_res;
683 unsigned int tries = 100;
685 vp_reg_write(res, VP_SRESET, VP_SRESET_PROCESSING);
687 /* waiting until VP_SRESET_PROCESSING is 0 */
688 if (~vp_reg_read(res, VP_SRESET) & VP_SRESET_PROCESSING)
692 WARN(tries == 0, "failed to reset Video Processor\n");
695 static void mixer_win_reset(struct mixer_context *ctx)
697 struct mixer_resources *res = &ctx->mixer_res;
700 spin_lock_irqsave(&res->reg_slock, flags);
702 mixer_reg_writemask(res, MXR_CFG, MXR_CFG_DST_HDMI, MXR_CFG_DST_MASK);
704 /* set output in RGB888 mode */
705 mixer_reg_writemask(res, MXR_CFG, MXR_CFG_OUT_RGB888, MXR_CFG_OUT_MASK);
707 /* 16 beat burst in DMA */
708 mixer_reg_writemask(res, MXR_STATUS, MXR_STATUS_16_BURST,
709 MXR_STATUS_BURST_MASK);
711 /* reset default layer priority */
712 mixer_reg_write(res, MXR_LAYER_CFG, 0);
714 /* set all background colors to RGB (0,0,0) */
715 mixer_reg_write(res, MXR_BG_COLOR0, MXR_YCBCR_VAL(0, 128, 128));
716 mixer_reg_write(res, MXR_BG_COLOR1, MXR_YCBCR_VAL(0, 128, 128));
717 mixer_reg_write(res, MXR_BG_COLOR2, MXR_YCBCR_VAL(0, 128, 128));
719 if (test_bit(MXR_BIT_VP_ENABLED, &ctx->flags)) {
720 /* configuration of Video Processor Registers */
722 vp_default_filter(res);
725 /* disable all layers */
726 mixer_reg_writemask(res, MXR_CFG, 0, MXR_CFG_GRP0_ENABLE);
727 mixer_reg_writemask(res, MXR_CFG, 0, MXR_CFG_GRP1_ENABLE);
728 if (test_bit(MXR_BIT_VP_ENABLED, &ctx->flags))
729 mixer_reg_writemask(res, MXR_CFG, 0, MXR_CFG_VP_ENABLE);
731 /* set all source image offsets to zero */
732 mixer_reg_write(res, MXR_GRAPHIC_SXY(0), 0);
733 mixer_reg_write(res, MXR_GRAPHIC_SXY(1), 0);
735 spin_unlock_irqrestore(&res->reg_slock, flags);
738 static irqreturn_t mixer_irq_handler(int irq, void *arg)
740 struct mixer_context *ctx = arg;
741 struct mixer_resources *res = &ctx->mixer_res;
742 u32 val, base, shadow;
744 spin_lock(&res->reg_slock);
746 /* read interrupt status for handling and clearing flags for VSYNC */
747 val = mixer_reg_read(res, MXR_INT_STATUS);
750 if (val & MXR_INT_STATUS_VSYNC) {
751 /* vsync interrupt use different bit for read and clear */
752 val |= MXR_INT_CLEAR_VSYNC;
753 val &= ~MXR_INT_STATUS_VSYNC;
755 /* interlace scan need to check shadow register */
756 if (test_bit(MXR_BIT_INTERLACE, &ctx->flags)) {
757 base = mixer_reg_read(res, MXR_GRAPHIC_BASE(0));
758 shadow = mixer_reg_read(res, MXR_GRAPHIC_BASE_S(0));
762 base = mixer_reg_read(res, MXR_GRAPHIC_BASE(1));
763 shadow = mixer_reg_read(res, MXR_GRAPHIC_BASE_S(1));
768 drm_crtc_handle_vblank(&ctx->crtc->base);
772 /* clear interrupts */
773 mixer_reg_write(res, MXR_INT_STATUS, val);
775 spin_unlock(&res->reg_slock);
780 static int mixer_resources_init(struct mixer_context *mixer_ctx)
782 struct device *dev = &mixer_ctx->pdev->dev;
783 struct mixer_resources *mixer_res = &mixer_ctx->mixer_res;
784 struct resource *res;
787 spin_lock_init(&mixer_res->reg_slock);
789 mixer_res->mixer = devm_clk_get(dev, "mixer");
790 if (IS_ERR(mixer_res->mixer)) {
791 dev_err(dev, "failed to get clock 'mixer'\n");
795 mixer_res->hdmi = devm_clk_get(dev, "hdmi");
796 if (IS_ERR(mixer_res->hdmi)) {
797 dev_err(dev, "failed to get clock 'hdmi'\n");
798 return PTR_ERR(mixer_res->hdmi);
801 mixer_res->sclk_hdmi = devm_clk_get(dev, "sclk_hdmi");
802 if (IS_ERR(mixer_res->sclk_hdmi)) {
803 dev_err(dev, "failed to get clock 'sclk_hdmi'\n");
806 res = platform_get_resource(mixer_ctx->pdev, IORESOURCE_MEM, 0);
808 dev_err(dev, "get memory resource failed.\n");
812 mixer_res->mixer_regs = devm_ioremap(dev, res->start,
814 if (mixer_res->mixer_regs == NULL) {
815 dev_err(dev, "register mapping failed.\n");
819 res = platform_get_resource(mixer_ctx->pdev, IORESOURCE_IRQ, 0);
821 dev_err(dev, "get interrupt resource failed.\n");
825 ret = devm_request_irq(dev, res->start, mixer_irq_handler,
826 0, "drm_mixer", mixer_ctx);
828 dev_err(dev, "request interrupt failed.\n");
831 mixer_res->irq = res->start;
836 static int vp_resources_init(struct mixer_context *mixer_ctx)
838 struct device *dev = &mixer_ctx->pdev->dev;
839 struct mixer_resources *mixer_res = &mixer_ctx->mixer_res;
840 struct resource *res;
842 mixer_res->vp = devm_clk_get(dev, "vp");
843 if (IS_ERR(mixer_res->vp)) {
844 dev_err(dev, "failed to get clock 'vp'\n");
848 if (test_bit(MXR_BIT_HAS_SCLK, &mixer_ctx->flags)) {
849 mixer_res->sclk_mixer = devm_clk_get(dev, "sclk_mixer");
850 if (IS_ERR(mixer_res->sclk_mixer)) {
851 dev_err(dev, "failed to get clock 'sclk_mixer'\n");
854 mixer_res->mout_mixer = devm_clk_get(dev, "mout_mixer");
855 if (IS_ERR(mixer_res->mout_mixer)) {
856 dev_err(dev, "failed to get clock 'mout_mixer'\n");
860 if (mixer_res->sclk_hdmi && mixer_res->mout_mixer)
861 clk_set_parent(mixer_res->mout_mixer,
862 mixer_res->sclk_hdmi);
865 res = platform_get_resource(mixer_ctx->pdev, IORESOURCE_MEM, 1);
867 dev_err(dev, "get memory resource failed.\n");
871 mixer_res->vp_regs = devm_ioremap(dev, res->start,
873 if (mixer_res->vp_regs == NULL) {
874 dev_err(dev, "register mapping failed.\n");
881 static int mixer_initialize(struct mixer_context *mixer_ctx,
882 struct drm_device *drm_dev)
885 struct exynos_drm_private *priv;
886 priv = drm_dev->dev_private;
888 mixer_ctx->drm_dev = drm_dev;
890 /* acquire resources: regs, irqs, clocks */
891 ret = mixer_resources_init(mixer_ctx);
893 DRM_ERROR("mixer_resources_init failed ret=%d\n", ret);
897 if (test_bit(MXR_BIT_VP_ENABLED, &mixer_ctx->flags)) {
898 /* acquire vp resources: regs, irqs, clocks */
899 ret = vp_resources_init(mixer_ctx);
901 DRM_ERROR("vp_resources_init failed ret=%d\n", ret);
906 return drm_iommu_attach_device(drm_dev, mixer_ctx->dev);
909 static void mixer_ctx_remove(struct mixer_context *mixer_ctx)
911 drm_iommu_detach_device(mixer_ctx->drm_dev, mixer_ctx->dev);
914 static int mixer_enable_vblank(struct exynos_drm_crtc *crtc)
916 struct mixer_context *mixer_ctx = crtc->ctx;
917 struct mixer_resources *res = &mixer_ctx->mixer_res;
919 __set_bit(MXR_BIT_VSYNC, &mixer_ctx->flags);
920 if (!test_bit(MXR_BIT_POWERED, &mixer_ctx->flags))
923 /* enable vsync interrupt */
924 mixer_reg_writemask(res, MXR_INT_STATUS, ~0, MXR_INT_CLEAR_VSYNC);
925 mixer_reg_writemask(res, MXR_INT_EN, ~0, MXR_INT_EN_VSYNC);
930 static void mixer_disable_vblank(struct exynos_drm_crtc *crtc)
932 struct mixer_context *mixer_ctx = crtc->ctx;
933 struct mixer_resources *res = &mixer_ctx->mixer_res;
935 __clear_bit(MXR_BIT_VSYNC, &mixer_ctx->flags);
937 if (!test_bit(MXR_BIT_POWERED, &mixer_ctx->flags))
940 /* disable vsync interrupt */
941 mixer_reg_writemask(res, MXR_INT_STATUS, ~0, MXR_INT_CLEAR_VSYNC);
942 mixer_reg_writemask(res, MXR_INT_EN, 0, MXR_INT_EN_VSYNC);
945 static void mixer_atomic_begin(struct exynos_drm_crtc *crtc)
947 struct mixer_context *mixer_ctx = crtc->ctx;
949 if (!test_bit(MXR_BIT_POWERED, &mixer_ctx->flags))
952 mixer_vsync_set_update(mixer_ctx, false);
955 static void mixer_update_plane(struct exynos_drm_crtc *crtc,
956 struct exynos_drm_plane *plane)
958 struct mixer_context *mixer_ctx = crtc->ctx;
960 DRM_DEBUG_KMS("win: %d\n", plane->index);
962 if (!test_bit(MXR_BIT_POWERED, &mixer_ctx->flags))
965 if (plane->index == VP_DEFAULT_WIN)
966 vp_video_buffer(mixer_ctx, plane);
968 mixer_graph_buffer(mixer_ctx, plane);
971 static void mixer_disable_plane(struct exynos_drm_crtc *crtc,
972 struct exynos_drm_plane *plane)
974 struct mixer_context *mixer_ctx = crtc->ctx;
975 struct mixer_resources *res = &mixer_ctx->mixer_res;
978 DRM_DEBUG_KMS("win: %d\n", plane->index);
980 if (!test_bit(MXR_BIT_POWERED, &mixer_ctx->flags))
983 spin_lock_irqsave(&res->reg_slock, flags);
984 mixer_cfg_layer(mixer_ctx, plane->index, 0, false);
985 spin_unlock_irqrestore(&res->reg_slock, flags);
988 static void mixer_atomic_flush(struct exynos_drm_crtc *crtc)
990 struct mixer_context *mixer_ctx = crtc->ctx;
992 if (!test_bit(MXR_BIT_POWERED, &mixer_ctx->flags))
995 mixer_vsync_set_update(mixer_ctx, true);
996 exynos_crtc_handle_event(crtc);
999 static void mixer_enable(struct exynos_drm_crtc *crtc)
1001 struct mixer_context *ctx = crtc->ctx;
1002 struct mixer_resources *res = &ctx->mixer_res;
1004 if (test_bit(MXR_BIT_POWERED, &ctx->flags))
1007 pm_runtime_get_sync(ctx->dev);
1009 exynos_drm_pipe_clk_enable(crtc, true);
1011 mixer_vsync_set_update(ctx, false);
1013 mixer_reg_writemask(res, MXR_STATUS, ~0, MXR_STATUS_SOFT_RESET);
1015 if (test_bit(MXR_BIT_VSYNC, &ctx->flags)) {
1016 mixer_reg_writemask(res, MXR_INT_STATUS, ~0, MXR_INT_CLEAR_VSYNC);
1017 mixer_reg_writemask(res, MXR_INT_EN, ~0, MXR_INT_EN_VSYNC);
1019 mixer_win_reset(ctx);
1021 mixer_vsync_set_update(ctx, true);
1023 set_bit(MXR_BIT_POWERED, &ctx->flags);
1026 static void mixer_disable(struct exynos_drm_crtc *crtc)
1028 struct mixer_context *ctx = crtc->ctx;
1031 if (!test_bit(MXR_BIT_POWERED, &ctx->flags))
1035 mixer_regs_dump(ctx);
1037 for (i = 0; i < MIXER_WIN_NR; i++)
1038 mixer_disable_plane(crtc, &ctx->planes[i]);
1040 exynos_drm_pipe_clk_enable(crtc, false);
1042 pm_runtime_put(ctx->dev);
1044 clear_bit(MXR_BIT_POWERED, &ctx->flags);
1047 /* Only valid for Mixer version 16.0.33.0 */
1048 static int mixer_atomic_check(struct exynos_drm_crtc *crtc,
1049 struct drm_crtc_state *state)
1051 struct drm_display_mode *mode = &state->adjusted_mode;
1057 DRM_DEBUG_KMS("xres=%d, yres=%d, refresh=%d, intl=%d\n",
1058 mode->hdisplay, mode->vdisplay, mode->vrefresh,
1059 (mode->flags & DRM_MODE_FLAG_INTERLACE) ? 1 : 0);
1061 if ((w >= 464 && w <= 720 && h >= 261 && h <= 576) ||
1062 (w >= 1024 && w <= 1280 && h >= 576 && h <= 720) ||
1063 (w >= 1664 && w <= 1920 && h >= 936 && h <= 1080))
1069 static const struct exynos_drm_crtc_ops mixer_crtc_ops = {
1070 .enable = mixer_enable,
1071 .disable = mixer_disable,
1072 .enable_vblank = mixer_enable_vblank,
1073 .disable_vblank = mixer_disable_vblank,
1074 .atomic_begin = mixer_atomic_begin,
1075 .update_plane = mixer_update_plane,
1076 .disable_plane = mixer_disable_plane,
1077 .atomic_flush = mixer_atomic_flush,
1078 .atomic_check = mixer_atomic_check,
1081 static const struct mixer_drv_data exynos5420_mxr_drv_data = {
1082 .version = MXR_VER_128_0_0_184,
1086 static const struct mixer_drv_data exynos5250_mxr_drv_data = {
1087 .version = MXR_VER_16_0_33_0,
1091 static const struct mixer_drv_data exynos4212_mxr_drv_data = {
1092 .version = MXR_VER_0_0_0_16,
1096 static const struct mixer_drv_data exynos4210_mxr_drv_data = {
1097 .version = MXR_VER_0_0_0_16,
1102 static const struct of_device_id mixer_match_types[] = {
1104 .compatible = "samsung,exynos4210-mixer",
1105 .data = &exynos4210_mxr_drv_data,
1107 .compatible = "samsung,exynos4212-mixer",
1108 .data = &exynos4212_mxr_drv_data,
1110 .compatible = "samsung,exynos5-mixer",
1111 .data = &exynos5250_mxr_drv_data,
1113 .compatible = "samsung,exynos5250-mixer",
1114 .data = &exynos5250_mxr_drv_data,
1116 .compatible = "samsung,exynos5420-mixer",
1117 .data = &exynos5420_mxr_drv_data,
1122 MODULE_DEVICE_TABLE(of, mixer_match_types);
1124 static int mixer_bind(struct device *dev, struct device *manager, void *data)
1126 struct mixer_context *ctx = dev_get_drvdata(dev);
1127 struct drm_device *drm_dev = data;
1128 struct exynos_drm_plane *exynos_plane;
1132 ret = mixer_initialize(ctx, drm_dev);
1136 for (i = 0; i < MIXER_WIN_NR; i++) {
1137 if (i == VP_DEFAULT_WIN && !test_bit(MXR_BIT_VP_ENABLED,
1141 ret = exynos_plane_init(drm_dev, &ctx->planes[i], i,
1147 exynos_plane = &ctx->planes[DEFAULT_WIN];
1148 ctx->crtc = exynos_drm_crtc_create(drm_dev, &exynos_plane->base,
1149 EXYNOS_DISPLAY_TYPE_HDMI, &mixer_crtc_ops, ctx);
1150 if (IS_ERR(ctx->crtc)) {
1151 mixer_ctx_remove(ctx);
1152 ret = PTR_ERR(ctx->crtc);
1159 devm_kfree(dev, ctx);
1163 static void mixer_unbind(struct device *dev, struct device *master, void *data)
1165 struct mixer_context *ctx = dev_get_drvdata(dev);
1167 mixer_ctx_remove(ctx);
1170 static const struct component_ops mixer_component_ops = {
1172 .unbind = mixer_unbind,
1175 static int mixer_probe(struct platform_device *pdev)
1177 struct device *dev = &pdev->dev;
1178 const struct mixer_drv_data *drv;
1179 struct mixer_context *ctx;
1182 ctx = devm_kzalloc(&pdev->dev, sizeof(*ctx), GFP_KERNEL);
1184 DRM_ERROR("failed to alloc mixer context.\n");
1188 drv = of_device_get_match_data(dev);
1192 ctx->mxr_ver = drv->version;
1194 if (drv->is_vp_enabled)
1195 __set_bit(MXR_BIT_VP_ENABLED, &ctx->flags);
1197 __set_bit(MXR_BIT_HAS_SCLK, &ctx->flags);
1199 platform_set_drvdata(pdev, ctx);
1201 ret = component_add(&pdev->dev, &mixer_component_ops);
1203 pm_runtime_enable(dev);
1208 static int mixer_remove(struct platform_device *pdev)
1210 pm_runtime_disable(&pdev->dev);
1212 component_del(&pdev->dev, &mixer_component_ops);
1217 static int __maybe_unused exynos_mixer_suspend(struct device *dev)
1219 struct mixer_context *ctx = dev_get_drvdata(dev);
1220 struct mixer_resources *res = &ctx->mixer_res;
1222 clk_disable_unprepare(res->hdmi);
1223 clk_disable_unprepare(res->mixer);
1224 if (test_bit(MXR_BIT_VP_ENABLED, &ctx->flags)) {
1225 clk_disable_unprepare(res->vp);
1226 if (test_bit(MXR_BIT_HAS_SCLK, &ctx->flags))
1227 clk_disable_unprepare(res->sclk_mixer);
1233 static int __maybe_unused exynos_mixer_resume(struct device *dev)
1235 struct mixer_context *ctx = dev_get_drvdata(dev);
1236 struct mixer_resources *res = &ctx->mixer_res;
1239 ret = clk_prepare_enable(res->mixer);
1241 DRM_ERROR("Failed to prepare_enable the mixer clk [%d]\n", ret);
1244 ret = clk_prepare_enable(res->hdmi);
1246 DRM_ERROR("Failed to prepare_enable the hdmi clk [%d]\n", ret);
1249 if (test_bit(MXR_BIT_VP_ENABLED, &ctx->flags)) {
1250 ret = clk_prepare_enable(res->vp);
1252 DRM_ERROR("Failed to prepare_enable the vp clk [%d]\n",
1256 if (test_bit(MXR_BIT_HAS_SCLK, &ctx->flags)) {
1257 ret = clk_prepare_enable(res->sclk_mixer);
1259 DRM_ERROR("Failed to prepare_enable the " \
1260 "sclk_mixer clk [%d]\n",
1270 static const struct dev_pm_ops exynos_mixer_pm_ops = {
1271 SET_RUNTIME_PM_OPS(exynos_mixer_suspend, exynos_mixer_resume, NULL)
1274 struct platform_driver mixer_driver = {
1276 .name = "exynos-mixer",
1277 .owner = THIS_MODULE,
1278 .pm = &exynos_mixer_pm_ops,
1279 .of_match_table = mixer_match_types,
1281 .probe = mixer_probe,
1282 .remove = mixer_remove,