2 * Copyright (C) 2011 Samsung Electronics Co.Ltd
4 * Seung-Woo Kim <sw0312.kim@samsung.com>
5 * Inki Dae <inki.dae@samsung.com>
6 * Joonyoung Shim <jy0922.shim@samsung.com>
8 * Based on drivers/media/video/s5p-tv/mixer_reg.c
10 * This program is free software; you can redistribute it and/or modify it
11 * under the terms of the GNU General Public License as published by the
12 * Free Software Foundation; either version 2 of the License, or (at your
13 * option) any later version.
19 #include "regs-mixer.h"
22 #include <linux/kernel.h>
23 #include <linux/spinlock.h>
24 #include <linux/wait.h>
25 #include <linux/i2c.h>
26 #include <linux/platform_device.h>
27 #include <linux/interrupt.h>
28 #include <linux/irq.h>
29 #include <linux/delay.h>
30 #include <linux/pm_runtime.h>
31 #include <linux/clk.h>
32 #include <linux/regulator/consumer.h>
34 #include <linux/component.h>
36 #include <drm/exynos_drm.h>
38 #include "exynos_drm_drv.h"
39 #include "exynos_drm_crtc.h"
40 #include "exynos_drm_plane.h"
41 #include "exynos_drm_iommu.h"
42 #include "exynos_mixer.h"
44 #define MIXER_WIN_NR 3
45 #define MIXER_DEFAULT_WIN 0
47 struct mixer_resources
{
49 void __iomem
*mixer_regs
;
50 void __iomem
*vp_regs
;
55 struct clk
*sclk_mixer
;
56 struct clk
*sclk_hdmi
;
57 struct clk
*mout_mixer
;
60 enum mixer_version_id
{
66 struct mixer_context
{
67 struct platform_device
*pdev
;
69 struct drm_device
*drm_dev
;
70 struct exynos_drm_crtc
*crtc
;
71 struct exynos_drm_plane planes
[MIXER_WIN_NR
];
79 struct mutex mixer_mutex
;
80 struct mixer_resources mixer_res
;
81 enum mixer_version_id mxr_ver
;
82 wait_queue_head_t wait_vsync_queue
;
83 atomic_t wait_vsync_event
;
86 struct mixer_drv_data
{
87 enum mixer_version_id version
;
92 static const u8 filter_y_horiz_tap8
[] = {
93 0, -1, -1, -1, -1, -1, -1, -1,
94 -1, -1, -1, -1, -1, 0, 0, 0,
95 0, 2, 4, 5, 6, 6, 6, 6,
96 6, 5, 5, 4, 3, 2, 1, 1,
97 0, -6, -12, -16, -18, -20, -21, -20,
98 -20, -18, -16, -13, -10, -8, -5, -2,
99 127, 126, 125, 121, 114, 107, 99, 89,
100 79, 68, 57, 46, 35, 25, 16, 8,
103 static const u8 filter_y_vert_tap4
[] = {
104 0, -3, -6, -8, -8, -8, -8, -7,
105 -6, -5, -4, -3, -2, -1, -1, 0,
106 127, 126, 124, 118, 111, 102, 92, 81,
107 70, 59, 48, 37, 27, 19, 11, 5,
108 0, 5, 11, 19, 27, 37, 48, 59,
109 70, 81, 92, 102, 111, 118, 124, 126,
110 0, 0, -1, -1, -2, -3, -4, -5,
111 -6, -7, -8, -8, -8, -8, -6, -3,
114 static const u8 filter_cr_horiz_tap4
[] = {
115 0, -3, -6, -8, -8, -8, -8, -7,
116 -6, -5, -4, -3, -2, -1, -1, 0,
117 127, 126, 124, 118, 111, 102, 92, 81,
118 70, 59, 48, 37, 27, 19, 11, 5,
121 static inline u32
vp_reg_read(struct mixer_resources
*res
, u32 reg_id
)
123 return readl(res
->vp_regs
+ reg_id
);
126 static inline void vp_reg_write(struct mixer_resources
*res
, u32 reg_id
,
129 writel(val
, res
->vp_regs
+ reg_id
);
132 static inline void vp_reg_writemask(struct mixer_resources
*res
, u32 reg_id
,
135 u32 old
= vp_reg_read(res
, reg_id
);
137 val
= (val
& mask
) | (old
& ~mask
);
138 writel(val
, res
->vp_regs
+ reg_id
);
141 static inline u32
mixer_reg_read(struct mixer_resources
*res
, u32 reg_id
)
143 return readl(res
->mixer_regs
+ reg_id
);
146 static inline void mixer_reg_write(struct mixer_resources
*res
, u32 reg_id
,
149 writel(val
, res
->mixer_regs
+ reg_id
);
152 static inline void mixer_reg_writemask(struct mixer_resources
*res
,
153 u32 reg_id
, u32 val
, u32 mask
)
155 u32 old
= mixer_reg_read(res
, reg_id
);
157 val
= (val
& mask
) | (old
& ~mask
);
158 writel(val
, res
->mixer_regs
+ reg_id
);
161 static void mixer_regs_dump(struct mixer_context
*ctx
)
163 #define DUMPREG(reg_id) \
165 DRM_DEBUG_KMS(#reg_id " = %08x\n", \
166 (u32)readl(ctx->mixer_res.mixer_regs + reg_id)); \
172 DUMPREG(MXR_INT_STATUS
);
174 DUMPREG(MXR_LAYER_CFG
);
175 DUMPREG(MXR_VIDEO_CFG
);
177 DUMPREG(MXR_GRAPHIC0_CFG
);
178 DUMPREG(MXR_GRAPHIC0_BASE
);
179 DUMPREG(MXR_GRAPHIC0_SPAN
);
180 DUMPREG(MXR_GRAPHIC0_WH
);
181 DUMPREG(MXR_GRAPHIC0_SXY
);
182 DUMPREG(MXR_GRAPHIC0_DXY
);
184 DUMPREG(MXR_GRAPHIC1_CFG
);
185 DUMPREG(MXR_GRAPHIC1_BASE
);
186 DUMPREG(MXR_GRAPHIC1_SPAN
);
187 DUMPREG(MXR_GRAPHIC1_WH
);
188 DUMPREG(MXR_GRAPHIC1_SXY
);
189 DUMPREG(MXR_GRAPHIC1_DXY
);
193 static void vp_regs_dump(struct mixer_context
*ctx
)
195 #define DUMPREG(reg_id) \
197 DRM_DEBUG_KMS(#reg_id " = %08x\n", \
198 (u32) readl(ctx->mixer_res.vp_regs + reg_id)); \
203 DUMPREG(VP_SHADOW_UPDATE
);
204 DUMPREG(VP_FIELD_ID
);
206 DUMPREG(VP_IMG_SIZE_Y
);
207 DUMPREG(VP_IMG_SIZE_C
);
208 DUMPREG(VP_PER_RATE_CTRL
);
209 DUMPREG(VP_TOP_Y_PTR
);
210 DUMPREG(VP_BOT_Y_PTR
);
211 DUMPREG(VP_TOP_C_PTR
);
212 DUMPREG(VP_BOT_C_PTR
);
213 DUMPREG(VP_ENDIAN_MODE
);
214 DUMPREG(VP_SRC_H_POSITION
);
215 DUMPREG(VP_SRC_V_POSITION
);
216 DUMPREG(VP_SRC_WIDTH
);
217 DUMPREG(VP_SRC_HEIGHT
);
218 DUMPREG(VP_DST_H_POSITION
);
219 DUMPREG(VP_DST_V_POSITION
);
220 DUMPREG(VP_DST_WIDTH
);
221 DUMPREG(VP_DST_HEIGHT
);
228 static inline void vp_filter_set(struct mixer_resources
*res
,
229 int reg_id
, const u8
*data
, unsigned int size
)
231 /* assure 4-byte align */
233 for (; size
; size
-= 4, reg_id
+= 4, data
+= 4) {
234 u32 val
= (data
[0] << 24) | (data
[1] << 16) |
235 (data
[2] << 8) | data
[3];
236 vp_reg_write(res
, reg_id
, val
);
240 static void vp_default_filter(struct mixer_resources
*res
)
242 vp_filter_set(res
, VP_POLY8_Y0_LL
,
243 filter_y_horiz_tap8
, sizeof(filter_y_horiz_tap8
));
244 vp_filter_set(res
, VP_POLY4_Y0_LL
,
245 filter_y_vert_tap4
, sizeof(filter_y_vert_tap4
));
246 vp_filter_set(res
, VP_POLY4_C0_LL
,
247 filter_cr_horiz_tap4
, sizeof(filter_cr_horiz_tap4
));
250 static void mixer_vsync_set_update(struct mixer_context
*ctx
, bool enable
)
252 struct mixer_resources
*res
= &ctx
->mixer_res
;
254 /* block update on vsync */
255 mixer_reg_writemask(res
, MXR_STATUS
, enable
?
256 MXR_STATUS_SYNC_ENABLE
: 0, MXR_STATUS_SYNC_ENABLE
);
259 vp_reg_write(res
, VP_SHADOW_UPDATE
, enable
?
260 VP_SHADOW_UPDATE_ENABLE
: 0);
263 static void mixer_cfg_scan(struct mixer_context
*ctx
, unsigned int height
)
265 struct mixer_resources
*res
= &ctx
->mixer_res
;
268 /* choosing between interlace and progressive mode */
269 val
= (ctx
->interlace
? MXR_CFG_SCAN_INTERLACE
:
270 MXR_CFG_SCAN_PROGRESSIVE
);
272 if (ctx
->mxr_ver
!= MXR_VER_128_0_0_184
) {
273 /* choosing between proper HD and SD mode */
275 val
|= MXR_CFG_SCAN_NTSC
| MXR_CFG_SCAN_SD
;
276 else if (height
<= 576)
277 val
|= MXR_CFG_SCAN_PAL
| MXR_CFG_SCAN_SD
;
278 else if (height
<= 720)
279 val
|= MXR_CFG_SCAN_HD_720
| MXR_CFG_SCAN_HD
;
280 else if (height
<= 1080)
281 val
|= MXR_CFG_SCAN_HD_1080
| MXR_CFG_SCAN_HD
;
283 val
|= MXR_CFG_SCAN_HD_720
| MXR_CFG_SCAN_HD
;
286 mixer_reg_writemask(res
, MXR_CFG
, val
, MXR_CFG_SCAN_MASK
);
289 static void mixer_cfg_rgb_fmt(struct mixer_context
*ctx
, unsigned int height
)
291 struct mixer_resources
*res
= &ctx
->mixer_res
;
295 val
= MXR_CFG_RGB601_0_255
;
296 } else if (height
== 576) {
297 val
= MXR_CFG_RGB601_0_255
;
298 } else if (height
== 720) {
299 val
= MXR_CFG_RGB709_16_235
;
300 mixer_reg_write(res
, MXR_CM_COEFF_Y
,
301 (1 << 30) | (94 << 20) | (314 << 10) |
303 mixer_reg_write(res
, MXR_CM_COEFF_CB
,
304 (972 << 20) | (851 << 10) | (225 << 0));
305 mixer_reg_write(res
, MXR_CM_COEFF_CR
,
306 (225 << 20) | (820 << 10) | (1004 << 0));
307 } else if (height
== 1080) {
308 val
= MXR_CFG_RGB709_16_235
;
309 mixer_reg_write(res
, MXR_CM_COEFF_Y
,
310 (1 << 30) | (94 << 20) | (314 << 10) |
312 mixer_reg_write(res
, MXR_CM_COEFF_CB
,
313 (972 << 20) | (851 << 10) | (225 << 0));
314 mixer_reg_write(res
, MXR_CM_COEFF_CR
,
315 (225 << 20) | (820 << 10) | (1004 << 0));
317 val
= MXR_CFG_RGB709_16_235
;
318 mixer_reg_write(res
, MXR_CM_COEFF_Y
,
319 (1 << 30) | (94 << 20) | (314 << 10) |
321 mixer_reg_write(res
, MXR_CM_COEFF_CB
,
322 (972 << 20) | (851 << 10) | (225 << 0));
323 mixer_reg_write(res
, MXR_CM_COEFF_CR
,
324 (225 << 20) | (820 << 10) | (1004 << 0));
327 mixer_reg_writemask(res
, MXR_CFG
, val
, MXR_CFG_RGB_FMT_MASK
);
330 static void mixer_cfg_layer(struct mixer_context
*ctx
, int win
, bool enable
)
332 struct mixer_resources
*res
= &ctx
->mixer_res
;
333 u32 val
= enable
? ~0 : 0;
337 mixer_reg_writemask(res
, MXR_CFG
, val
, MXR_CFG_GRP0_ENABLE
);
340 mixer_reg_writemask(res
, MXR_CFG
, val
, MXR_CFG_GRP1_ENABLE
);
343 if (ctx
->vp_enabled
) {
344 vp_reg_writemask(res
, VP_ENABLE
, val
, VP_ENABLE_ON
);
345 mixer_reg_writemask(res
, MXR_CFG
, val
,
348 /* control blending of graphic layer 0 */
349 mixer_reg_writemask(res
, MXR_GRAPHIC_CFG(0), val
,
350 MXR_GRP_CFG_BLEND_PRE_MUL
|
351 MXR_GRP_CFG_PIXEL_BLEND_EN
);
357 static void mixer_run(struct mixer_context
*ctx
)
359 struct mixer_resources
*res
= &ctx
->mixer_res
;
361 mixer_reg_writemask(res
, MXR_STATUS
, ~0, MXR_STATUS_REG_RUN
);
363 mixer_regs_dump(ctx
);
366 static void mixer_stop(struct mixer_context
*ctx
)
368 struct mixer_resources
*res
= &ctx
->mixer_res
;
371 mixer_reg_writemask(res
, MXR_STATUS
, 0, MXR_STATUS_REG_RUN
);
373 while (!(mixer_reg_read(res
, MXR_STATUS
) & MXR_STATUS_REG_IDLE
) &&
375 usleep_range(10000, 12000);
377 mixer_regs_dump(ctx
);
380 static void vp_video_buffer(struct mixer_context
*ctx
, int win
)
382 struct mixer_resources
*res
= &ctx
->mixer_res
;
384 struct exynos_drm_plane
*plane
;
385 unsigned int x_ratio
, y_ratio
;
386 unsigned int buf_num
= 1;
387 dma_addr_t luma_addr
[2], chroma_addr
[2];
388 bool tiled_mode
= false;
389 bool crcb_mode
= false;
392 plane
= &ctx
->planes
[win
];
394 switch (plane
->pixel_format
) {
395 case DRM_FORMAT_NV12
:
399 /* TODO: single buffer format NV12, NV21 */
401 /* ignore pixel format at disable time */
402 if (!plane
->dma_addr
[0])
405 DRM_ERROR("pixel format for vp is wrong [%d].\n",
406 plane
->pixel_format
);
410 /* scaling feature: (src << 16) / dst */
411 x_ratio
= (plane
->src_width
<< 16) / plane
->crtc_width
;
412 y_ratio
= (plane
->src_height
<< 16) / plane
->crtc_height
;
415 luma_addr
[0] = plane
->dma_addr
[0];
416 chroma_addr
[0] = plane
->dma_addr
[1];
418 luma_addr
[0] = plane
->dma_addr
[0];
419 chroma_addr
[0] = plane
->dma_addr
[0]
420 + (plane
->pitch
* plane
->fb_height
);
423 if (plane
->scan_flag
& DRM_MODE_FLAG_INTERLACE
) {
424 ctx
->interlace
= true;
426 luma_addr
[1] = luma_addr
[0] + 0x40;
427 chroma_addr
[1] = chroma_addr
[0] + 0x40;
429 luma_addr
[1] = luma_addr
[0] + plane
->pitch
;
430 chroma_addr
[1] = chroma_addr
[0] + plane
->pitch
;
433 ctx
->interlace
= false;
438 spin_lock_irqsave(&res
->reg_slock
, flags
);
439 mixer_vsync_set_update(ctx
, false);
441 /* interlace or progressive scan mode */
442 val
= (ctx
->interlace
? ~0 : 0);
443 vp_reg_writemask(res
, VP_MODE
, val
, VP_MODE_LINE_SKIP
);
446 val
= (crcb_mode
? VP_MODE_NV21
: VP_MODE_NV12
);
447 val
|= (tiled_mode
? VP_MODE_MEM_TILED
: VP_MODE_MEM_LINEAR
);
448 vp_reg_writemask(res
, VP_MODE
, val
, VP_MODE_FMT_MASK
);
450 /* setting size of input image */
451 vp_reg_write(res
, VP_IMG_SIZE_Y
, VP_IMG_HSIZE(plane
->pitch
) |
452 VP_IMG_VSIZE(plane
->fb_height
));
453 /* chroma height has to reduced by 2 to avoid chroma distorions */
454 vp_reg_write(res
, VP_IMG_SIZE_C
, VP_IMG_HSIZE(plane
->pitch
) |
455 VP_IMG_VSIZE(plane
->fb_height
/ 2));
457 vp_reg_write(res
, VP_SRC_WIDTH
, plane
->src_width
);
458 vp_reg_write(res
, VP_SRC_HEIGHT
, plane
->src_height
);
459 vp_reg_write(res
, VP_SRC_H_POSITION
,
460 VP_SRC_H_POSITION_VAL(plane
->fb_x
));
461 vp_reg_write(res
, VP_SRC_V_POSITION
, plane
->fb_y
);
463 vp_reg_write(res
, VP_DST_WIDTH
, plane
->crtc_width
);
464 vp_reg_write(res
, VP_DST_H_POSITION
, plane
->crtc_x
);
465 if (ctx
->interlace
) {
466 vp_reg_write(res
, VP_DST_HEIGHT
, plane
->crtc_height
/ 2);
467 vp_reg_write(res
, VP_DST_V_POSITION
, plane
->crtc_y
/ 2);
469 vp_reg_write(res
, VP_DST_HEIGHT
, plane
->crtc_height
);
470 vp_reg_write(res
, VP_DST_V_POSITION
, plane
->crtc_y
);
473 vp_reg_write(res
, VP_H_RATIO
, x_ratio
);
474 vp_reg_write(res
, VP_V_RATIO
, y_ratio
);
476 vp_reg_write(res
, VP_ENDIAN_MODE
, VP_ENDIAN_MODE_LITTLE
);
478 /* set buffer address to vp */
479 vp_reg_write(res
, VP_TOP_Y_PTR
, luma_addr
[0]);
480 vp_reg_write(res
, VP_BOT_Y_PTR
, luma_addr
[1]);
481 vp_reg_write(res
, VP_TOP_C_PTR
, chroma_addr
[0]);
482 vp_reg_write(res
, VP_BOT_C_PTR
, chroma_addr
[1]);
484 mixer_cfg_scan(ctx
, plane
->mode_height
);
485 mixer_cfg_rgb_fmt(ctx
, plane
->mode_height
);
486 mixer_cfg_layer(ctx
, win
, true);
489 mixer_vsync_set_update(ctx
, true);
490 spin_unlock_irqrestore(&res
->reg_slock
, flags
);
495 static void mixer_layer_update(struct mixer_context
*ctx
)
497 struct mixer_resources
*res
= &ctx
->mixer_res
;
499 mixer_reg_writemask(res
, MXR_CFG
, ~0, MXR_CFG_LAYER_UPDATE
);
502 static int mixer_setup_scale(const struct exynos_drm_plane
*plane
,
503 unsigned int *x_ratio
, unsigned int *y_ratio
)
505 if (plane
->crtc_width
!= plane
->src_width
) {
506 if (plane
->crtc_width
== 2 * plane
->src_width
)
512 if (plane
->crtc_height
!= plane
->src_height
) {
513 if (plane
->crtc_height
== 2 * plane
->src_height
)
522 DRM_DEBUG_KMS("only 2x width/height scaling of plane supported\n");
526 static void mixer_graph_buffer(struct mixer_context
*ctx
, int win
)
528 struct mixer_resources
*res
= &ctx
->mixer_res
;
530 struct exynos_drm_plane
*plane
;
531 unsigned int x_ratio
= 0, y_ratio
= 0;
532 unsigned int src_x_offset
, src_y_offset
, dst_x_offset
, dst_y_offset
;
537 plane
= &ctx
->planes
[win
];
544 switch (plane
->bpp
) {
555 /* check if mixer supports requested scaling setup */
556 if (mixer_setup_scale(plane
, &x_ratio
, &y_ratio
))
559 dst_x_offset
= plane
->crtc_x
;
560 dst_y_offset
= plane
->crtc_y
;
562 /* converting dma address base and source offset */
563 dma_addr
= plane
->dma_addr
[0]
564 + (plane
->fb_x
* plane
->bpp
>> 3)
565 + (plane
->fb_y
* plane
->pitch
);
569 if (plane
->scan_flag
& DRM_MODE_FLAG_INTERLACE
)
570 ctx
->interlace
= true;
572 ctx
->interlace
= false;
574 spin_lock_irqsave(&res
->reg_slock
, flags
);
575 mixer_vsync_set_update(ctx
, false);
578 mixer_reg_writemask(res
, MXR_GRAPHIC_CFG(win
),
579 MXR_GRP_CFG_FORMAT_VAL(fmt
), MXR_GRP_CFG_FORMAT_MASK
);
582 mixer_reg_write(res
, MXR_GRAPHIC_SPAN(win
),
583 plane
->pitch
/ (plane
->bpp
>> 3));
585 /* setup display size */
586 if (ctx
->mxr_ver
== MXR_VER_128_0_0_184
&&
587 win
== MIXER_DEFAULT_WIN
) {
588 val
= MXR_MXR_RES_HEIGHT(plane
->mode_height
);
589 val
|= MXR_MXR_RES_WIDTH(plane
->mode_width
);
590 mixer_reg_write(res
, MXR_RESOLUTION
, val
);
593 val
= MXR_GRP_WH_WIDTH(plane
->src_width
);
594 val
|= MXR_GRP_WH_HEIGHT(plane
->src_height
);
595 val
|= MXR_GRP_WH_H_SCALE(x_ratio
);
596 val
|= MXR_GRP_WH_V_SCALE(y_ratio
);
597 mixer_reg_write(res
, MXR_GRAPHIC_WH(win
), val
);
599 /* setup offsets in source image */
600 val
= MXR_GRP_SXY_SX(src_x_offset
);
601 val
|= MXR_GRP_SXY_SY(src_y_offset
);
602 mixer_reg_write(res
, MXR_GRAPHIC_SXY(win
), val
);
604 /* setup offsets in display image */
605 val
= MXR_GRP_DXY_DX(dst_x_offset
);
606 val
|= MXR_GRP_DXY_DY(dst_y_offset
);
607 mixer_reg_write(res
, MXR_GRAPHIC_DXY(win
), val
);
609 /* set buffer address to mixer */
610 mixer_reg_write(res
, MXR_GRAPHIC_BASE(win
), dma_addr
);
612 mixer_cfg_scan(ctx
, plane
->mode_height
);
613 mixer_cfg_rgb_fmt(ctx
, plane
->mode_height
);
614 mixer_cfg_layer(ctx
, win
, true);
616 /* layer update mandatory for mixer 16.0.33.0 */
617 if (ctx
->mxr_ver
== MXR_VER_16_0_33_0
||
618 ctx
->mxr_ver
== MXR_VER_128_0_0_184
)
619 mixer_layer_update(ctx
);
623 mixer_vsync_set_update(ctx
, true);
624 spin_unlock_irqrestore(&res
->reg_slock
, flags
);
627 static void vp_win_reset(struct mixer_context
*ctx
)
629 struct mixer_resources
*res
= &ctx
->mixer_res
;
632 vp_reg_write(res
, VP_SRESET
, VP_SRESET_PROCESSING
);
633 for (tries
= 100; tries
; --tries
) {
634 /* waiting until VP_SRESET_PROCESSING is 0 */
635 if (~vp_reg_read(res
, VP_SRESET
) & VP_SRESET_PROCESSING
)
637 usleep_range(10000, 12000);
639 WARN(tries
== 0, "failed to reset Video Processor\n");
642 static void mixer_win_reset(struct mixer_context
*ctx
)
644 struct mixer_resources
*res
= &ctx
->mixer_res
;
646 u32 val
; /* value stored to register */
648 spin_lock_irqsave(&res
->reg_slock
, flags
);
649 mixer_vsync_set_update(ctx
, false);
651 mixer_reg_writemask(res
, MXR_CFG
, MXR_CFG_DST_HDMI
, MXR_CFG_DST_MASK
);
653 /* set output in RGB888 mode */
654 mixer_reg_writemask(res
, MXR_CFG
, MXR_CFG_OUT_RGB888
, MXR_CFG_OUT_MASK
);
656 /* 16 beat burst in DMA */
657 mixer_reg_writemask(res
, MXR_STATUS
, MXR_STATUS_16_BURST
,
658 MXR_STATUS_BURST_MASK
);
660 /* setting default layer priority: layer1 > layer0 > video
661 * because typical usage scenario would be
663 * layer0 - framebuffer
664 * video - video overlay
666 val
= MXR_LAYER_CFG_GRP1_VAL(3);
667 val
|= MXR_LAYER_CFG_GRP0_VAL(2);
669 val
|= MXR_LAYER_CFG_VP_VAL(1);
670 mixer_reg_write(res
, MXR_LAYER_CFG
, val
);
672 /* setting background color */
673 mixer_reg_write(res
, MXR_BG_COLOR0
, 0x008080);
674 mixer_reg_write(res
, MXR_BG_COLOR1
, 0x008080);
675 mixer_reg_write(res
, MXR_BG_COLOR2
, 0x008080);
677 /* setting graphical layers */
678 val
= MXR_GRP_CFG_COLOR_KEY_DISABLE
; /* no blank key */
679 val
|= MXR_GRP_CFG_WIN_BLEND_EN
;
680 val
|= MXR_GRP_CFG_ALPHA_VAL(0xff); /* non-transparent alpha */
682 /* Don't blend layer 0 onto the mixer background */
683 mixer_reg_write(res
, MXR_GRAPHIC_CFG(0), val
);
685 /* Blend layer 1 into layer 0 */
686 val
|= MXR_GRP_CFG_BLEND_PRE_MUL
;
687 val
|= MXR_GRP_CFG_PIXEL_BLEND_EN
;
688 mixer_reg_write(res
, MXR_GRAPHIC_CFG(1), val
);
690 /* setting video layers */
691 val
= MXR_GRP_CFG_ALPHA_VAL(0);
692 mixer_reg_write(res
, MXR_VIDEO_CFG
, val
);
694 if (ctx
->vp_enabled
) {
695 /* configuration of Video Processor Registers */
697 vp_default_filter(res
);
700 /* disable all layers */
701 mixer_reg_writemask(res
, MXR_CFG
, 0, MXR_CFG_GRP0_ENABLE
);
702 mixer_reg_writemask(res
, MXR_CFG
, 0, MXR_CFG_GRP1_ENABLE
);
704 mixer_reg_writemask(res
, MXR_CFG
, 0, MXR_CFG_VP_ENABLE
);
706 mixer_vsync_set_update(ctx
, true);
707 spin_unlock_irqrestore(&res
->reg_slock
, flags
);
710 static irqreturn_t
mixer_irq_handler(int irq
, void *arg
)
712 struct mixer_context
*ctx
= arg
;
713 struct mixer_resources
*res
= &ctx
->mixer_res
;
714 u32 val
, base
, shadow
;
716 spin_lock(&res
->reg_slock
);
718 /* read interrupt status for handling and clearing flags for VSYNC */
719 val
= mixer_reg_read(res
, MXR_INT_STATUS
);
722 if (val
& MXR_INT_STATUS_VSYNC
) {
723 /* interlace scan need to check shadow register */
724 if (ctx
->interlace
) {
725 base
= mixer_reg_read(res
, MXR_GRAPHIC_BASE(0));
726 shadow
= mixer_reg_read(res
, MXR_GRAPHIC_BASE_S(0));
730 base
= mixer_reg_read(res
, MXR_GRAPHIC_BASE(1));
731 shadow
= mixer_reg_read(res
, MXR_GRAPHIC_BASE_S(1));
736 drm_handle_vblank(ctx
->drm_dev
, ctx
->pipe
);
737 exynos_drm_crtc_finish_pageflip(ctx
->drm_dev
, ctx
->pipe
);
739 /* set wait vsync event to zero and wake up queue. */
740 if (atomic_read(&ctx
->wait_vsync_event
)) {
741 atomic_set(&ctx
->wait_vsync_event
, 0);
742 wake_up(&ctx
->wait_vsync_queue
);
747 /* clear interrupts */
748 if (~val
& MXR_INT_EN_VSYNC
) {
749 /* vsync interrupt use different bit for read and clear */
750 val
&= ~MXR_INT_EN_VSYNC
;
751 val
|= MXR_INT_CLEAR_VSYNC
;
753 mixer_reg_write(res
, MXR_INT_STATUS
, val
);
755 spin_unlock(&res
->reg_slock
);
760 static int mixer_resources_init(struct mixer_context
*mixer_ctx
)
762 struct device
*dev
= &mixer_ctx
->pdev
->dev
;
763 struct mixer_resources
*mixer_res
= &mixer_ctx
->mixer_res
;
764 struct resource
*res
;
767 spin_lock_init(&mixer_res
->reg_slock
);
769 mixer_res
->mixer
= devm_clk_get(dev
, "mixer");
770 if (IS_ERR(mixer_res
->mixer
)) {
771 dev_err(dev
, "failed to get clock 'mixer'\n");
775 mixer_res
->hdmi
= devm_clk_get(dev
, "hdmi");
776 if (IS_ERR(mixer_res
->hdmi
)) {
777 dev_err(dev
, "failed to get clock 'hdmi'\n");
778 return PTR_ERR(mixer_res
->hdmi
);
781 mixer_res
->sclk_hdmi
= devm_clk_get(dev
, "sclk_hdmi");
782 if (IS_ERR(mixer_res
->sclk_hdmi
)) {
783 dev_err(dev
, "failed to get clock 'sclk_hdmi'\n");
786 res
= platform_get_resource(mixer_ctx
->pdev
, IORESOURCE_MEM
, 0);
788 dev_err(dev
, "get memory resource failed.\n");
792 mixer_res
->mixer_regs
= devm_ioremap(dev
, res
->start
,
794 if (mixer_res
->mixer_regs
== NULL
) {
795 dev_err(dev
, "register mapping failed.\n");
799 res
= platform_get_resource(mixer_ctx
->pdev
, IORESOURCE_IRQ
, 0);
801 dev_err(dev
, "get interrupt resource failed.\n");
805 ret
= devm_request_irq(dev
, res
->start
, mixer_irq_handler
,
806 0, "drm_mixer", mixer_ctx
);
808 dev_err(dev
, "request interrupt failed.\n");
811 mixer_res
->irq
= res
->start
;
816 static int vp_resources_init(struct mixer_context
*mixer_ctx
)
818 struct device
*dev
= &mixer_ctx
->pdev
->dev
;
819 struct mixer_resources
*mixer_res
= &mixer_ctx
->mixer_res
;
820 struct resource
*res
;
822 mixer_res
->vp
= devm_clk_get(dev
, "vp");
823 if (IS_ERR(mixer_res
->vp
)) {
824 dev_err(dev
, "failed to get clock 'vp'\n");
828 if (mixer_ctx
->has_sclk
) {
829 mixer_res
->sclk_mixer
= devm_clk_get(dev
, "sclk_mixer");
830 if (IS_ERR(mixer_res
->sclk_mixer
)) {
831 dev_err(dev
, "failed to get clock 'sclk_mixer'\n");
834 mixer_res
->mout_mixer
= devm_clk_get(dev
, "mout_mixer");
835 if (IS_ERR(mixer_res
->mout_mixer
)) {
836 dev_err(dev
, "failed to get clock 'mout_mixer'\n");
840 if (mixer_res
->sclk_hdmi
&& mixer_res
->mout_mixer
)
841 clk_set_parent(mixer_res
->mout_mixer
,
842 mixer_res
->sclk_hdmi
);
845 res
= platform_get_resource(mixer_ctx
->pdev
, IORESOURCE_MEM
, 1);
847 dev_err(dev
, "get memory resource failed.\n");
851 mixer_res
->vp_regs
= devm_ioremap(dev
, res
->start
,
853 if (mixer_res
->vp_regs
== NULL
) {
854 dev_err(dev
, "register mapping failed.\n");
861 static int mixer_initialize(struct mixer_context
*mixer_ctx
,
862 struct drm_device
*drm_dev
)
865 struct exynos_drm_private
*priv
;
866 priv
= drm_dev
->dev_private
;
868 mixer_ctx
->drm_dev
= drm_dev
;
869 mixer_ctx
->pipe
= priv
->pipe
++;
871 /* acquire resources: regs, irqs, clocks */
872 ret
= mixer_resources_init(mixer_ctx
);
874 DRM_ERROR("mixer_resources_init failed ret=%d\n", ret
);
878 if (mixer_ctx
->vp_enabled
) {
879 /* acquire vp resources: regs, irqs, clocks */
880 ret
= vp_resources_init(mixer_ctx
);
882 DRM_ERROR("vp_resources_init failed ret=%d\n", ret
);
887 if (!is_drm_iommu_supported(mixer_ctx
->drm_dev
))
890 return drm_iommu_attach_device(mixer_ctx
->drm_dev
, mixer_ctx
->dev
);
893 static void mixer_ctx_remove(struct mixer_context
*mixer_ctx
)
895 if (is_drm_iommu_supported(mixer_ctx
->drm_dev
))
896 drm_iommu_detach_device(mixer_ctx
->drm_dev
, mixer_ctx
->dev
);
899 static int mixer_enable_vblank(struct exynos_drm_crtc
*crtc
)
901 struct mixer_context
*mixer_ctx
= crtc
->ctx
;
902 struct mixer_resources
*res
= &mixer_ctx
->mixer_res
;
904 if (!mixer_ctx
->powered
) {
905 mixer_ctx
->int_en
|= MXR_INT_EN_VSYNC
;
909 /* enable vsync interrupt */
910 mixer_reg_writemask(res
, MXR_INT_EN
, MXR_INT_EN_VSYNC
,
916 static void mixer_disable_vblank(struct exynos_drm_crtc
*crtc
)
918 struct mixer_context
*mixer_ctx
= crtc
->ctx
;
919 struct mixer_resources
*res
= &mixer_ctx
->mixer_res
;
921 /* disable vsync interrupt */
922 mixer_reg_writemask(res
, MXR_INT_EN
, 0, MXR_INT_EN_VSYNC
);
925 static void mixer_win_commit(struct exynos_drm_crtc
*crtc
, unsigned int win
)
927 struct mixer_context
*mixer_ctx
= crtc
->ctx
;
929 DRM_DEBUG_KMS("win: %d\n", win
);
931 mutex_lock(&mixer_ctx
->mixer_mutex
);
932 if (!mixer_ctx
->powered
) {
933 mutex_unlock(&mixer_ctx
->mixer_mutex
);
936 mutex_unlock(&mixer_ctx
->mixer_mutex
);
938 if (win
> 1 && mixer_ctx
->vp_enabled
)
939 vp_video_buffer(mixer_ctx
, win
);
941 mixer_graph_buffer(mixer_ctx
, win
);
943 mixer_ctx
->planes
[win
].enabled
= true;
946 static void mixer_win_disable(struct exynos_drm_crtc
*crtc
, unsigned int win
)
948 struct mixer_context
*mixer_ctx
= crtc
->ctx
;
949 struct mixer_resources
*res
= &mixer_ctx
->mixer_res
;
952 DRM_DEBUG_KMS("win: %d\n", win
);
954 mutex_lock(&mixer_ctx
->mixer_mutex
);
955 if (!mixer_ctx
->powered
) {
956 mutex_unlock(&mixer_ctx
->mixer_mutex
);
957 mixer_ctx
->planes
[win
].resume
= false;
960 mutex_unlock(&mixer_ctx
->mixer_mutex
);
962 spin_lock_irqsave(&res
->reg_slock
, flags
);
963 mixer_vsync_set_update(mixer_ctx
, false);
965 mixer_cfg_layer(mixer_ctx
, win
, false);
967 mixer_vsync_set_update(mixer_ctx
, true);
968 spin_unlock_irqrestore(&res
->reg_slock
, flags
);
970 mixer_ctx
->planes
[win
].enabled
= false;
973 static void mixer_wait_for_vblank(struct exynos_drm_crtc
*crtc
)
975 struct mixer_context
*mixer_ctx
= crtc
->ctx
;
978 mutex_lock(&mixer_ctx
->mixer_mutex
);
979 if (!mixer_ctx
->powered
) {
980 mutex_unlock(&mixer_ctx
->mixer_mutex
);
983 mutex_unlock(&mixer_ctx
->mixer_mutex
);
985 err
= drm_vblank_get(mixer_ctx
->drm_dev
, mixer_ctx
->pipe
);
987 DRM_DEBUG_KMS("failed to acquire vblank counter\n");
991 atomic_set(&mixer_ctx
->wait_vsync_event
, 1);
994 * wait for MIXER to signal VSYNC interrupt or return after
995 * timeout which is set to 50ms (refresh rate of 20).
997 if (!wait_event_timeout(mixer_ctx
->wait_vsync_queue
,
998 !atomic_read(&mixer_ctx
->wait_vsync_event
),
1000 DRM_DEBUG_KMS("vblank wait timed out.\n");
1002 drm_vblank_put(mixer_ctx
->drm_dev
, mixer_ctx
->pipe
);
1005 static void mixer_window_suspend(struct mixer_context
*ctx
)
1007 struct exynos_drm_plane
*plane
;
1010 for (i
= 0; i
< MIXER_WIN_NR
; i
++) {
1011 plane
= &ctx
->planes
[i
];
1012 plane
->resume
= plane
->enabled
;
1013 mixer_win_disable(ctx
->crtc
, i
);
1015 mixer_wait_for_vblank(ctx
->crtc
);
1018 static void mixer_window_resume(struct mixer_context
*ctx
)
1020 struct exynos_drm_plane
*plane
;
1023 for (i
= 0; i
< MIXER_WIN_NR
; i
++) {
1024 plane
= &ctx
->planes
[i
];
1025 plane
->enabled
= plane
->resume
;
1026 plane
->resume
= false;
1028 mixer_win_commit(ctx
->crtc
, i
);
1032 static void mixer_poweron(struct mixer_context
*ctx
)
1034 struct mixer_resources
*res
= &ctx
->mixer_res
;
1036 mutex_lock(&ctx
->mixer_mutex
);
1038 mutex_unlock(&ctx
->mixer_mutex
);
1042 mutex_unlock(&ctx
->mixer_mutex
);
1044 pm_runtime_get_sync(ctx
->dev
);
1046 clk_prepare_enable(res
->mixer
);
1047 clk_prepare_enable(res
->hdmi
);
1048 if (ctx
->vp_enabled
) {
1049 clk_prepare_enable(res
->vp
);
1051 clk_prepare_enable(res
->sclk_mixer
);
1054 mutex_lock(&ctx
->mixer_mutex
);
1055 ctx
->powered
= true;
1056 mutex_unlock(&ctx
->mixer_mutex
);
1058 mixer_reg_writemask(res
, MXR_STATUS
, ~0, MXR_STATUS_SOFT_RESET
);
1060 mixer_reg_write(res
, MXR_INT_EN
, ctx
->int_en
);
1061 mixer_win_reset(ctx
);
1063 mixer_window_resume(ctx
);
1066 static void mixer_poweroff(struct mixer_context
*ctx
)
1068 struct mixer_resources
*res
= &ctx
->mixer_res
;
1070 mutex_lock(&ctx
->mixer_mutex
);
1071 if (!ctx
->powered
) {
1072 mutex_unlock(&ctx
->mixer_mutex
);
1075 mutex_unlock(&ctx
->mixer_mutex
);
1078 mixer_window_suspend(ctx
);
1080 ctx
->int_en
= mixer_reg_read(res
, MXR_INT_EN
);
1082 mutex_lock(&ctx
->mixer_mutex
);
1083 ctx
->powered
= false;
1084 mutex_unlock(&ctx
->mixer_mutex
);
1086 clk_disable_unprepare(res
->hdmi
);
1087 clk_disable_unprepare(res
->mixer
);
1088 if (ctx
->vp_enabled
) {
1089 clk_disable_unprepare(res
->vp
);
1091 clk_disable_unprepare(res
->sclk_mixer
);
1094 pm_runtime_put_sync(ctx
->dev
);
1097 static void mixer_dpms(struct exynos_drm_crtc
*crtc
, int mode
)
1100 case DRM_MODE_DPMS_ON
:
1101 mixer_poweron(crtc
->ctx
);
1103 case DRM_MODE_DPMS_STANDBY
:
1104 case DRM_MODE_DPMS_SUSPEND
:
1105 case DRM_MODE_DPMS_OFF
:
1106 mixer_poweroff(crtc
->ctx
);
1109 DRM_DEBUG_KMS("unknown dpms mode: %d\n", mode
);
1114 /* Only valid for Mixer version 16.0.33.0 */
1115 int mixer_check_mode(struct drm_display_mode
*mode
)
1122 DRM_DEBUG_KMS("xres=%d, yres=%d, refresh=%d, intl=%d\n",
1123 mode
->hdisplay
, mode
->vdisplay
, mode
->vrefresh
,
1124 (mode
->flags
& DRM_MODE_FLAG_INTERLACE
) ? 1 : 0);
1126 if ((w
>= 464 && w
<= 720 && h
>= 261 && h
<= 576) ||
1127 (w
>= 1024 && w
<= 1280 && h
>= 576 && h
<= 720) ||
1128 (w
>= 1664 && w
<= 1920 && h
>= 936 && h
<= 1080))
1134 static struct exynos_drm_crtc_ops mixer_crtc_ops
= {
1136 .enable_vblank
= mixer_enable_vblank
,
1137 .disable_vblank
= mixer_disable_vblank
,
1138 .wait_for_vblank
= mixer_wait_for_vblank
,
1139 .win_commit
= mixer_win_commit
,
1140 .win_disable
= mixer_win_disable
,
1143 static struct mixer_drv_data exynos5420_mxr_drv_data
= {
1144 .version
= MXR_VER_128_0_0_184
,
1148 static struct mixer_drv_data exynos5250_mxr_drv_data
= {
1149 .version
= MXR_VER_16_0_33_0
,
1153 static struct mixer_drv_data exynos4212_mxr_drv_data
= {
1154 .version
= MXR_VER_0_0_0_16
,
1158 static struct mixer_drv_data exynos4210_mxr_drv_data
= {
1159 .version
= MXR_VER_0_0_0_16
,
1164 static struct platform_device_id mixer_driver_types
[] = {
1166 .name
= "s5p-mixer",
1167 .driver_data
= (unsigned long)&exynos4210_mxr_drv_data
,
1169 .name
= "exynos5-mixer",
1170 .driver_data
= (unsigned long)&exynos5250_mxr_drv_data
,
1176 static struct of_device_id mixer_match_types
[] = {
1178 .compatible
= "samsung,exynos4210-mixer",
1179 .data
= &exynos4210_mxr_drv_data
,
1181 .compatible
= "samsung,exynos4212-mixer",
1182 .data
= &exynos4212_mxr_drv_data
,
1184 .compatible
= "samsung,exynos5-mixer",
1185 .data
= &exynos5250_mxr_drv_data
,
1187 .compatible
= "samsung,exynos5250-mixer",
1188 .data
= &exynos5250_mxr_drv_data
,
1190 .compatible
= "samsung,exynos5420-mixer",
1191 .data
= &exynos5420_mxr_drv_data
,
1196 MODULE_DEVICE_TABLE(of
, mixer_match_types
);
1198 static int mixer_bind(struct device
*dev
, struct device
*manager
, void *data
)
1200 struct mixer_context
*ctx
= dev_get_drvdata(dev
);
1201 struct drm_device
*drm_dev
= data
;
1202 struct exynos_drm_plane
*exynos_plane
;
1203 enum drm_plane_type type
;
1207 ret
= mixer_initialize(ctx
, drm_dev
);
1211 for (zpos
= 0; zpos
< MIXER_WIN_NR
; zpos
++) {
1212 type
= (zpos
== MIXER_DEFAULT_WIN
) ? DRM_PLANE_TYPE_PRIMARY
:
1213 DRM_PLANE_TYPE_OVERLAY
;
1214 ret
= exynos_plane_init(drm_dev
, &ctx
->planes
[zpos
],
1215 1 << ctx
->pipe
, type
, zpos
);
1220 exynos_plane
= &ctx
->planes
[MIXER_DEFAULT_WIN
];
1221 ctx
->crtc
= exynos_drm_crtc_create(drm_dev
, &exynos_plane
->base
,
1222 ctx
->pipe
, EXYNOS_DISPLAY_TYPE_HDMI
,
1223 &mixer_crtc_ops
, ctx
);
1224 if (IS_ERR(ctx
->crtc
)) {
1225 mixer_ctx_remove(ctx
);
1226 ret
= PTR_ERR(ctx
->crtc
);
1233 devm_kfree(dev
, ctx
);
1237 static void mixer_unbind(struct device
*dev
, struct device
*master
, void *data
)
1239 struct mixer_context
*ctx
= dev_get_drvdata(dev
);
1241 mixer_ctx_remove(ctx
);
1244 static const struct component_ops mixer_component_ops
= {
1246 .unbind
= mixer_unbind
,
1249 static int mixer_probe(struct platform_device
*pdev
)
1251 struct device
*dev
= &pdev
->dev
;
1252 struct mixer_drv_data
*drv
;
1253 struct mixer_context
*ctx
;
1256 ctx
= devm_kzalloc(&pdev
->dev
, sizeof(*ctx
), GFP_KERNEL
);
1258 DRM_ERROR("failed to alloc mixer context.\n");
1262 mutex_init(&ctx
->mixer_mutex
);
1265 const struct of_device_id
*match
;
1267 match
= of_match_node(mixer_match_types
, dev
->of_node
);
1268 drv
= (struct mixer_drv_data
*)match
->data
;
1270 drv
= (struct mixer_drv_data
*)
1271 platform_get_device_id(pdev
)->driver_data
;
1276 ctx
->vp_enabled
= drv
->is_vp_enabled
;
1277 ctx
->has_sclk
= drv
->has_sclk
;
1278 ctx
->mxr_ver
= drv
->version
;
1279 init_waitqueue_head(&ctx
->wait_vsync_queue
);
1280 atomic_set(&ctx
->wait_vsync_event
, 0);
1282 platform_set_drvdata(pdev
, ctx
);
1284 ret
= exynos_drm_component_add(&pdev
->dev
, EXYNOS_DEVICE_TYPE_CRTC
,
1285 EXYNOS_DISPLAY_TYPE_HDMI
);
1289 ret
= component_add(&pdev
->dev
, &mixer_component_ops
);
1291 exynos_drm_component_del(&pdev
->dev
, EXYNOS_DEVICE_TYPE_CRTC
);
1295 pm_runtime_enable(dev
);
1300 static int mixer_remove(struct platform_device
*pdev
)
1302 pm_runtime_disable(&pdev
->dev
);
1304 component_del(&pdev
->dev
, &mixer_component_ops
);
1305 exynos_drm_component_del(&pdev
->dev
, EXYNOS_DEVICE_TYPE_CRTC
);
1310 struct platform_driver mixer_driver
= {
1312 .name
= "exynos-mixer",
1313 .owner
= THIS_MODULE
,
1314 .of_match_table
= mixer_match_types
,
1316 .probe
= mixer_probe
,
1317 .remove
= mixer_remove
,
1318 .id_table
= mixer_driver_types
,