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>
35 #include <drm/exynos_drm.h>
37 #include "exynos_drm_drv.h"
38 #include "exynos_drm_crtc.h"
39 #include "exynos_drm_hdmi.h"
40 #include "exynos_drm_iommu.h"
42 #define get_mixer_context(dev) platform_get_drvdata(to_platform_device(dev))
44 struct hdmi_win_data
{
46 dma_addr_t chroma_dma_addr
;
47 uint32_t pixel_format
;
51 unsigned int crtc_width
;
52 unsigned int crtc_height
;
55 unsigned int fb_width
;
56 unsigned int fb_height
;
57 unsigned int src_width
;
58 unsigned int src_height
;
59 unsigned int mode_width
;
60 unsigned int mode_height
;
61 unsigned int scan_flags
;
66 struct mixer_resources
{
68 void __iomem
*mixer_regs
;
69 void __iomem
*vp_regs
;
73 struct clk
*sclk_mixer
;
74 struct clk
*sclk_hdmi
;
78 enum mixer_version_id
{
84 struct mixer_context
{
86 struct drm_device
*drm_dev
;
93 struct mutex mixer_mutex
;
94 struct mixer_resources mixer_res
;
95 struct hdmi_win_data win_data
[MIXER_WIN_NR
];
96 enum mixer_version_id mxr_ver
;
98 wait_queue_head_t wait_vsync_queue
;
99 atomic_t wait_vsync_event
;
102 struct mixer_drv_data
{
103 enum mixer_version_id version
;
107 static const u8 filter_y_horiz_tap8
[] = {
108 0, -1, -1, -1, -1, -1, -1, -1,
109 -1, -1, -1, -1, -1, 0, 0, 0,
110 0, 2, 4, 5, 6, 6, 6, 6,
111 6, 5, 5, 4, 3, 2, 1, 1,
112 0, -6, -12, -16, -18, -20, -21, -20,
113 -20, -18, -16, -13, -10, -8, -5, -2,
114 127, 126, 125, 121, 114, 107, 99, 89,
115 79, 68, 57, 46, 35, 25, 16, 8,
118 static const u8 filter_y_vert_tap4
[] = {
119 0, -3, -6, -8, -8, -8, -8, -7,
120 -6, -5, -4, -3, -2, -1, -1, 0,
121 127, 126, 124, 118, 111, 102, 92, 81,
122 70, 59, 48, 37, 27, 19, 11, 5,
123 0, 5, 11, 19, 27, 37, 48, 59,
124 70, 81, 92, 102, 111, 118, 124, 126,
125 0, 0, -1, -1, -2, -3, -4, -5,
126 -6, -7, -8, -8, -8, -8, -6, -3,
129 static const u8 filter_cr_horiz_tap4
[] = {
130 0, -3, -6, -8, -8, -8, -8, -7,
131 -6, -5, -4, -3, -2, -1, -1, 0,
132 127, 126, 124, 118, 111, 102, 92, 81,
133 70, 59, 48, 37, 27, 19, 11, 5,
136 static inline u32
vp_reg_read(struct mixer_resources
*res
, u32 reg_id
)
138 return readl(res
->vp_regs
+ reg_id
);
141 static inline void vp_reg_write(struct mixer_resources
*res
, u32 reg_id
,
144 writel(val
, res
->vp_regs
+ reg_id
);
147 static inline void vp_reg_writemask(struct mixer_resources
*res
, u32 reg_id
,
150 u32 old
= vp_reg_read(res
, reg_id
);
152 val
= (val
& mask
) | (old
& ~mask
);
153 writel(val
, res
->vp_regs
+ reg_id
);
156 static inline u32
mixer_reg_read(struct mixer_resources
*res
, u32 reg_id
)
158 return readl(res
->mixer_regs
+ reg_id
);
161 static inline void mixer_reg_write(struct mixer_resources
*res
, u32 reg_id
,
164 writel(val
, res
->mixer_regs
+ reg_id
);
167 static inline void mixer_reg_writemask(struct mixer_resources
*res
,
168 u32 reg_id
, u32 val
, u32 mask
)
170 u32 old
= mixer_reg_read(res
, reg_id
);
172 val
= (val
& mask
) | (old
& ~mask
);
173 writel(val
, res
->mixer_regs
+ reg_id
);
176 static void mixer_regs_dump(struct mixer_context
*ctx
)
178 #define DUMPREG(reg_id) \
180 DRM_DEBUG_KMS(#reg_id " = %08x\n", \
181 (u32)readl(ctx->mixer_res.mixer_regs + reg_id)); \
187 DUMPREG(MXR_INT_STATUS
);
189 DUMPREG(MXR_LAYER_CFG
);
190 DUMPREG(MXR_VIDEO_CFG
);
192 DUMPREG(MXR_GRAPHIC0_CFG
);
193 DUMPREG(MXR_GRAPHIC0_BASE
);
194 DUMPREG(MXR_GRAPHIC0_SPAN
);
195 DUMPREG(MXR_GRAPHIC0_WH
);
196 DUMPREG(MXR_GRAPHIC0_SXY
);
197 DUMPREG(MXR_GRAPHIC0_DXY
);
199 DUMPREG(MXR_GRAPHIC1_CFG
);
200 DUMPREG(MXR_GRAPHIC1_BASE
);
201 DUMPREG(MXR_GRAPHIC1_SPAN
);
202 DUMPREG(MXR_GRAPHIC1_WH
);
203 DUMPREG(MXR_GRAPHIC1_SXY
);
204 DUMPREG(MXR_GRAPHIC1_DXY
);
208 static void vp_regs_dump(struct mixer_context
*ctx
)
210 #define DUMPREG(reg_id) \
212 DRM_DEBUG_KMS(#reg_id " = %08x\n", \
213 (u32) readl(ctx->mixer_res.vp_regs + reg_id)); \
218 DUMPREG(VP_SHADOW_UPDATE
);
219 DUMPREG(VP_FIELD_ID
);
221 DUMPREG(VP_IMG_SIZE_Y
);
222 DUMPREG(VP_IMG_SIZE_C
);
223 DUMPREG(VP_PER_RATE_CTRL
);
224 DUMPREG(VP_TOP_Y_PTR
);
225 DUMPREG(VP_BOT_Y_PTR
);
226 DUMPREG(VP_TOP_C_PTR
);
227 DUMPREG(VP_BOT_C_PTR
);
228 DUMPREG(VP_ENDIAN_MODE
);
229 DUMPREG(VP_SRC_H_POSITION
);
230 DUMPREG(VP_SRC_V_POSITION
);
231 DUMPREG(VP_SRC_WIDTH
);
232 DUMPREG(VP_SRC_HEIGHT
);
233 DUMPREG(VP_DST_H_POSITION
);
234 DUMPREG(VP_DST_V_POSITION
);
235 DUMPREG(VP_DST_WIDTH
);
236 DUMPREG(VP_DST_HEIGHT
);
243 static inline void vp_filter_set(struct mixer_resources
*res
,
244 int reg_id
, const u8
*data
, unsigned int size
)
246 /* assure 4-byte align */
248 for (; size
; size
-= 4, reg_id
+= 4, data
+= 4) {
249 u32 val
= (data
[0] << 24) | (data
[1] << 16) |
250 (data
[2] << 8) | data
[3];
251 vp_reg_write(res
, reg_id
, val
);
255 static void vp_default_filter(struct mixer_resources
*res
)
257 vp_filter_set(res
, VP_POLY8_Y0_LL
,
258 filter_y_horiz_tap8
, sizeof(filter_y_horiz_tap8
));
259 vp_filter_set(res
, VP_POLY4_Y0_LL
,
260 filter_y_vert_tap4
, sizeof(filter_y_vert_tap4
));
261 vp_filter_set(res
, VP_POLY4_C0_LL
,
262 filter_cr_horiz_tap4
, sizeof(filter_cr_horiz_tap4
));
265 static void mixer_vsync_set_update(struct mixer_context
*ctx
, bool enable
)
267 struct mixer_resources
*res
= &ctx
->mixer_res
;
269 /* block update on vsync */
270 mixer_reg_writemask(res
, MXR_STATUS
, enable
?
271 MXR_STATUS_SYNC_ENABLE
: 0, MXR_STATUS_SYNC_ENABLE
);
274 vp_reg_write(res
, VP_SHADOW_UPDATE
, enable
?
275 VP_SHADOW_UPDATE_ENABLE
: 0);
278 static void mixer_cfg_scan(struct mixer_context
*ctx
, unsigned int height
)
280 struct mixer_resources
*res
= &ctx
->mixer_res
;
283 /* choosing between interlace and progressive mode */
284 val
= (ctx
->interlace
? MXR_CFG_SCAN_INTERLACE
:
285 MXR_CFG_SCAN_PROGRASSIVE
);
287 if (ctx
->mxr_ver
!= MXR_VER_128_0_0_184
) {
288 /* choosing between proper HD and SD mode */
290 val
|= MXR_CFG_SCAN_NTSC
| MXR_CFG_SCAN_SD
;
291 else if (height
<= 576)
292 val
|= MXR_CFG_SCAN_PAL
| MXR_CFG_SCAN_SD
;
293 else if (height
<= 720)
294 val
|= MXR_CFG_SCAN_HD_720
| MXR_CFG_SCAN_HD
;
295 else if (height
<= 1080)
296 val
|= MXR_CFG_SCAN_HD_1080
| MXR_CFG_SCAN_HD
;
298 val
|= MXR_CFG_SCAN_HD_720
| MXR_CFG_SCAN_HD
;
301 mixer_reg_writemask(res
, MXR_CFG
, val
, MXR_CFG_SCAN_MASK
);
304 static void mixer_cfg_rgb_fmt(struct mixer_context
*ctx
, unsigned int height
)
306 struct mixer_resources
*res
= &ctx
->mixer_res
;
310 val
= MXR_CFG_RGB601_0_255
;
311 } else if (height
== 576) {
312 val
= MXR_CFG_RGB601_0_255
;
313 } else if (height
== 720) {
314 val
= MXR_CFG_RGB709_16_235
;
315 mixer_reg_write(res
, MXR_CM_COEFF_Y
,
316 (1 << 30) | (94 << 20) | (314 << 10) |
318 mixer_reg_write(res
, MXR_CM_COEFF_CB
,
319 (972 << 20) | (851 << 10) | (225 << 0));
320 mixer_reg_write(res
, MXR_CM_COEFF_CR
,
321 (225 << 20) | (820 << 10) | (1004 << 0));
322 } else if (height
== 1080) {
323 val
= MXR_CFG_RGB709_16_235
;
324 mixer_reg_write(res
, MXR_CM_COEFF_Y
,
325 (1 << 30) | (94 << 20) | (314 << 10) |
327 mixer_reg_write(res
, MXR_CM_COEFF_CB
,
328 (972 << 20) | (851 << 10) | (225 << 0));
329 mixer_reg_write(res
, MXR_CM_COEFF_CR
,
330 (225 << 20) | (820 << 10) | (1004 << 0));
332 val
= MXR_CFG_RGB709_16_235
;
333 mixer_reg_write(res
, MXR_CM_COEFF_Y
,
334 (1 << 30) | (94 << 20) | (314 << 10) |
336 mixer_reg_write(res
, MXR_CM_COEFF_CB
,
337 (972 << 20) | (851 << 10) | (225 << 0));
338 mixer_reg_write(res
, MXR_CM_COEFF_CR
,
339 (225 << 20) | (820 << 10) | (1004 << 0));
342 mixer_reg_writemask(res
, MXR_CFG
, val
, MXR_CFG_RGB_FMT_MASK
);
345 static void mixer_cfg_layer(struct mixer_context
*ctx
, int win
, bool enable
)
347 struct mixer_resources
*res
= &ctx
->mixer_res
;
348 u32 val
= enable
? ~0 : 0;
352 mixer_reg_writemask(res
, MXR_CFG
, val
, MXR_CFG_GRP0_ENABLE
);
355 mixer_reg_writemask(res
, MXR_CFG
, val
, MXR_CFG_GRP1_ENABLE
);
358 if (ctx
->vp_enabled
) {
359 vp_reg_writemask(res
, VP_ENABLE
, val
, VP_ENABLE_ON
);
360 mixer_reg_writemask(res
, MXR_CFG
, val
,
367 static void mixer_run(struct mixer_context
*ctx
)
369 struct mixer_resources
*res
= &ctx
->mixer_res
;
371 mixer_reg_writemask(res
, MXR_STATUS
, ~0, MXR_STATUS_REG_RUN
);
373 mixer_regs_dump(ctx
);
376 static void vp_video_buffer(struct mixer_context
*ctx
, int win
)
378 struct mixer_resources
*res
= &ctx
->mixer_res
;
380 struct hdmi_win_data
*win_data
;
381 unsigned int x_ratio
, y_ratio
;
382 unsigned int buf_num
= 1;
383 dma_addr_t luma_addr
[2], chroma_addr
[2];
384 bool tiled_mode
= false;
385 bool crcb_mode
= false;
388 win_data
= &ctx
->win_data
[win
];
390 switch (win_data
->pixel_format
) {
391 case DRM_FORMAT_NV12MT
:
393 case DRM_FORMAT_NV12
:
397 /* TODO: single buffer format NV12, NV21 */
399 /* ignore pixel format at disable time */
400 if (!win_data
->dma_addr
)
403 DRM_ERROR("pixel format for vp is wrong [%d].\n",
404 win_data
->pixel_format
);
408 /* scaling feature: (src << 16) / dst */
409 x_ratio
= (win_data
->src_width
<< 16) / win_data
->crtc_width
;
410 y_ratio
= (win_data
->src_height
<< 16) / win_data
->crtc_height
;
413 luma_addr
[0] = win_data
->dma_addr
;
414 chroma_addr
[0] = win_data
->chroma_dma_addr
;
416 luma_addr
[0] = win_data
->dma_addr
;
417 chroma_addr
[0] = win_data
->dma_addr
418 + (win_data
->fb_width
* win_data
->fb_height
);
421 if (win_data
->scan_flags
& DRM_MODE_FLAG_INTERLACE
) {
422 ctx
->interlace
= true;
424 luma_addr
[1] = luma_addr
[0] + 0x40;
425 chroma_addr
[1] = chroma_addr
[0] + 0x40;
427 luma_addr
[1] = luma_addr
[0] + win_data
->fb_width
;
428 chroma_addr
[1] = chroma_addr
[0] + win_data
->fb_width
;
431 ctx
->interlace
= false;
436 spin_lock_irqsave(&res
->reg_slock
, flags
);
437 mixer_vsync_set_update(ctx
, false);
439 /* interlace or progressive scan mode */
440 val
= (ctx
->interlace
? ~0 : 0);
441 vp_reg_writemask(res
, VP_MODE
, val
, VP_MODE_LINE_SKIP
);
444 val
= (crcb_mode
? VP_MODE_NV21
: VP_MODE_NV12
);
445 val
|= (tiled_mode
? VP_MODE_MEM_TILED
: VP_MODE_MEM_LINEAR
);
446 vp_reg_writemask(res
, VP_MODE
, val
, VP_MODE_FMT_MASK
);
448 /* setting size of input image */
449 vp_reg_write(res
, VP_IMG_SIZE_Y
, VP_IMG_HSIZE(win_data
->fb_width
) |
450 VP_IMG_VSIZE(win_data
->fb_height
));
451 /* chroma height has to reduced by 2 to avoid chroma distorions */
452 vp_reg_write(res
, VP_IMG_SIZE_C
, VP_IMG_HSIZE(win_data
->fb_width
) |
453 VP_IMG_VSIZE(win_data
->fb_height
/ 2));
455 vp_reg_write(res
, VP_SRC_WIDTH
, win_data
->src_width
);
456 vp_reg_write(res
, VP_SRC_HEIGHT
, win_data
->src_height
);
457 vp_reg_write(res
, VP_SRC_H_POSITION
,
458 VP_SRC_H_POSITION_VAL(win_data
->fb_x
));
459 vp_reg_write(res
, VP_SRC_V_POSITION
, win_data
->fb_y
);
461 vp_reg_write(res
, VP_DST_WIDTH
, win_data
->crtc_width
);
462 vp_reg_write(res
, VP_DST_H_POSITION
, win_data
->crtc_x
);
463 if (ctx
->interlace
) {
464 vp_reg_write(res
, VP_DST_HEIGHT
, win_data
->crtc_height
/ 2);
465 vp_reg_write(res
, VP_DST_V_POSITION
, win_data
->crtc_y
/ 2);
467 vp_reg_write(res
, VP_DST_HEIGHT
, win_data
->crtc_height
);
468 vp_reg_write(res
, VP_DST_V_POSITION
, win_data
->crtc_y
);
471 vp_reg_write(res
, VP_H_RATIO
, x_ratio
);
472 vp_reg_write(res
, VP_V_RATIO
, y_ratio
);
474 vp_reg_write(res
, VP_ENDIAN_MODE
, VP_ENDIAN_MODE_LITTLE
);
476 /* set buffer address to vp */
477 vp_reg_write(res
, VP_TOP_Y_PTR
, luma_addr
[0]);
478 vp_reg_write(res
, VP_BOT_Y_PTR
, luma_addr
[1]);
479 vp_reg_write(res
, VP_TOP_C_PTR
, chroma_addr
[0]);
480 vp_reg_write(res
, VP_BOT_C_PTR
, chroma_addr
[1]);
482 mixer_cfg_scan(ctx
, win_data
->mode_height
);
483 mixer_cfg_rgb_fmt(ctx
, win_data
->mode_height
);
484 mixer_cfg_layer(ctx
, win
, true);
487 mixer_vsync_set_update(ctx
, true);
488 spin_unlock_irqrestore(&res
->reg_slock
, flags
);
493 static void mixer_layer_update(struct mixer_context
*ctx
)
495 struct mixer_resources
*res
= &ctx
->mixer_res
;
498 val
= mixer_reg_read(res
, MXR_CFG
);
500 /* allow one update per vsync only */
501 if (!(val
& MXR_CFG_LAYER_UPDATE_COUNT_MASK
))
502 mixer_reg_writemask(res
, MXR_CFG
, ~0, MXR_CFG_LAYER_UPDATE
);
505 static void mixer_graph_buffer(struct mixer_context
*ctx
, int win
)
507 struct mixer_resources
*res
= &ctx
->mixer_res
;
509 struct hdmi_win_data
*win_data
;
510 unsigned int x_ratio
, y_ratio
;
511 unsigned int src_x_offset
, src_y_offset
, dst_x_offset
, dst_y_offset
;
516 win_data
= &ctx
->win_data
[win
];
523 switch (win_data
->bpp
) {
534 /* 2x scaling feature */
538 dst_x_offset
= win_data
->crtc_x
;
539 dst_y_offset
= win_data
->crtc_y
;
541 /* converting dma address base and source offset */
542 dma_addr
= win_data
->dma_addr
543 + (win_data
->fb_x
* win_data
->bpp
>> 3)
544 + (win_data
->fb_y
* win_data
->fb_width
* win_data
->bpp
>> 3);
548 if (win_data
->scan_flags
& DRM_MODE_FLAG_INTERLACE
)
549 ctx
->interlace
= true;
551 ctx
->interlace
= false;
553 spin_lock_irqsave(&res
->reg_slock
, flags
);
554 mixer_vsync_set_update(ctx
, false);
557 mixer_reg_writemask(res
, MXR_GRAPHIC_CFG(win
),
558 MXR_GRP_CFG_FORMAT_VAL(fmt
), MXR_GRP_CFG_FORMAT_MASK
);
561 mixer_reg_write(res
, MXR_GRAPHIC_SPAN(win
), win_data
->fb_width
);
563 /* setup display size */
564 if (ctx
->mxr_ver
== MXR_VER_128_0_0_184
&&
565 win
== MIXER_DEFAULT_WIN
) {
566 val
= MXR_MXR_RES_HEIGHT(win_data
->fb_height
);
567 val
|= MXR_MXR_RES_WIDTH(win_data
->fb_width
);
568 mixer_reg_write(res
, MXR_RESOLUTION
, val
);
571 val
= MXR_GRP_WH_WIDTH(win_data
->crtc_width
);
572 val
|= MXR_GRP_WH_HEIGHT(win_data
->crtc_height
);
573 val
|= MXR_GRP_WH_H_SCALE(x_ratio
);
574 val
|= MXR_GRP_WH_V_SCALE(y_ratio
);
575 mixer_reg_write(res
, MXR_GRAPHIC_WH(win
), val
);
577 /* setup offsets in source image */
578 val
= MXR_GRP_SXY_SX(src_x_offset
);
579 val
|= MXR_GRP_SXY_SY(src_y_offset
);
580 mixer_reg_write(res
, MXR_GRAPHIC_SXY(win
), val
);
582 /* setup offsets in display image */
583 val
= MXR_GRP_DXY_DX(dst_x_offset
);
584 val
|= MXR_GRP_DXY_DY(dst_y_offset
);
585 mixer_reg_write(res
, MXR_GRAPHIC_DXY(win
), val
);
587 /* set buffer address to mixer */
588 mixer_reg_write(res
, MXR_GRAPHIC_BASE(win
), dma_addr
);
590 mixer_cfg_scan(ctx
, win_data
->mode_height
);
591 mixer_cfg_rgb_fmt(ctx
, win_data
->mode_height
);
592 mixer_cfg_layer(ctx
, win
, true);
594 /* layer update mandatory for mixer 16.0.33.0 */
595 if (ctx
->mxr_ver
== MXR_VER_16_0_33_0
||
596 ctx
->mxr_ver
== MXR_VER_128_0_0_184
)
597 mixer_layer_update(ctx
);
601 mixer_vsync_set_update(ctx
, true);
602 spin_unlock_irqrestore(&res
->reg_slock
, flags
);
605 static void vp_win_reset(struct mixer_context
*ctx
)
607 struct mixer_resources
*res
= &ctx
->mixer_res
;
610 vp_reg_write(res
, VP_SRESET
, VP_SRESET_PROCESSING
);
611 for (tries
= 100; tries
; --tries
) {
612 /* waiting until VP_SRESET_PROCESSING is 0 */
613 if (~vp_reg_read(res
, VP_SRESET
) & VP_SRESET_PROCESSING
)
615 usleep_range(10000, 12000);
617 WARN(tries
== 0, "failed to reset Video Processor\n");
620 static void mixer_win_reset(struct mixer_context
*ctx
)
622 struct mixer_resources
*res
= &ctx
->mixer_res
;
624 u32 val
; /* value stored to register */
626 spin_lock_irqsave(&res
->reg_slock
, flags
);
627 mixer_vsync_set_update(ctx
, false);
629 mixer_reg_writemask(res
, MXR_CFG
, MXR_CFG_DST_HDMI
, MXR_CFG_DST_MASK
);
631 /* set output in RGB888 mode */
632 mixer_reg_writemask(res
, MXR_CFG
, MXR_CFG_OUT_RGB888
, MXR_CFG_OUT_MASK
);
634 /* 16 beat burst in DMA */
635 mixer_reg_writemask(res
, MXR_STATUS
, MXR_STATUS_16_BURST
,
636 MXR_STATUS_BURST_MASK
);
638 /* setting default layer priority: layer1 > layer0 > video
639 * because typical usage scenario would be
641 * layer0 - framebuffer
642 * video - video overlay
644 val
= MXR_LAYER_CFG_GRP1_VAL(3);
645 val
|= MXR_LAYER_CFG_GRP0_VAL(2);
647 val
|= MXR_LAYER_CFG_VP_VAL(1);
648 mixer_reg_write(res
, MXR_LAYER_CFG
, val
);
650 /* setting background color */
651 mixer_reg_write(res
, MXR_BG_COLOR0
, 0x008080);
652 mixer_reg_write(res
, MXR_BG_COLOR1
, 0x008080);
653 mixer_reg_write(res
, MXR_BG_COLOR2
, 0x008080);
655 /* setting graphical layers */
656 val
= MXR_GRP_CFG_COLOR_KEY_DISABLE
; /* no blank key */
657 val
|= MXR_GRP_CFG_WIN_BLEND_EN
;
658 val
|= MXR_GRP_CFG_ALPHA_VAL(0xff); /* non-transparent alpha */
660 /* Don't blend layer 0 onto the mixer background */
661 mixer_reg_write(res
, MXR_GRAPHIC_CFG(0), val
);
663 /* Blend layer 1 into layer 0 */
664 val
|= MXR_GRP_CFG_BLEND_PRE_MUL
;
665 val
|= MXR_GRP_CFG_PIXEL_BLEND_EN
;
666 mixer_reg_write(res
, MXR_GRAPHIC_CFG(1), val
);
668 /* setting video layers */
669 val
= MXR_GRP_CFG_ALPHA_VAL(0);
670 mixer_reg_write(res
, MXR_VIDEO_CFG
, val
);
672 if (ctx
->vp_enabled
) {
673 /* configuration of Video Processor Registers */
675 vp_default_filter(res
);
678 /* disable all layers */
679 mixer_reg_writemask(res
, MXR_CFG
, 0, MXR_CFG_GRP0_ENABLE
);
680 mixer_reg_writemask(res
, MXR_CFG
, 0, MXR_CFG_GRP1_ENABLE
);
682 mixer_reg_writemask(res
, MXR_CFG
, 0, MXR_CFG_VP_ENABLE
);
684 mixer_vsync_set_update(ctx
, true);
685 spin_unlock_irqrestore(&res
->reg_slock
, flags
);
688 static int mixer_iommu_on(void *ctx
, bool enable
)
690 struct exynos_drm_hdmi_context
*drm_hdmi_ctx
;
691 struct mixer_context
*mdata
= ctx
;
692 struct drm_device
*drm_dev
;
694 drm_hdmi_ctx
= mdata
->parent_ctx
;
695 drm_dev
= drm_hdmi_ctx
->drm_dev
;
697 if (is_drm_iommu_supported(drm_dev
)) {
699 return drm_iommu_attach_device(drm_dev
, mdata
->dev
);
701 drm_iommu_detach_device(drm_dev
, mdata
->dev
);
706 static int mixer_enable_vblank(void *ctx
, int pipe
)
708 struct mixer_context
*mixer_ctx
= ctx
;
709 struct mixer_resources
*res
= &mixer_ctx
->mixer_res
;
711 mixer_ctx
->pipe
= pipe
;
713 /* enable vsync interrupt */
714 mixer_reg_writemask(res
, MXR_INT_EN
, MXR_INT_EN_VSYNC
,
720 static void mixer_disable_vblank(void *ctx
)
722 struct mixer_context
*mixer_ctx
= ctx
;
723 struct mixer_resources
*res
= &mixer_ctx
->mixer_res
;
725 /* disable vsync interrupt */
726 mixer_reg_writemask(res
, MXR_INT_EN
, 0, MXR_INT_EN_VSYNC
);
729 static void mixer_win_mode_set(void *ctx
,
730 struct exynos_drm_overlay
*overlay
)
732 struct mixer_context
*mixer_ctx
= ctx
;
733 struct hdmi_win_data
*win_data
;
737 DRM_ERROR("overlay is NULL\n");
741 DRM_DEBUG_KMS("set [%d]x[%d] at (%d,%d) to [%d]x[%d] at (%d,%d)\n",
742 overlay
->fb_width
, overlay
->fb_height
,
743 overlay
->fb_x
, overlay
->fb_y
,
744 overlay
->crtc_width
, overlay
->crtc_height
,
745 overlay
->crtc_x
, overlay
->crtc_y
);
748 if (win
== DEFAULT_ZPOS
)
749 win
= MIXER_DEFAULT_WIN
;
751 if (win
< 0 || win
>= MIXER_WIN_NR
) {
752 DRM_ERROR("mixer window[%d] is wrong\n", win
);
756 win_data
= &mixer_ctx
->win_data
[win
];
758 win_data
->dma_addr
= overlay
->dma_addr
[0];
759 win_data
->chroma_dma_addr
= overlay
->dma_addr
[1];
760 win_data
->pixel_format
= overlay
->pixel_format
;
761 win_data
->bpp
= overlay
->bpp
;
763 win_data
->crtc_x
= overlay
->crtc_x
;
764 win_data
->crtc_y
= overlay
->crtc_y
;
765 win_data
->crtc_width
= overlay
->crtc_width
;
766 win_data
->crtc_height
= overlay
->crtc_height
;
768 win_data
->fb_x
= overlay
->fb_x
;
769 win_data
->fb_y
= overlay
->fb_y
;
770 win_data
->fb_width
= overlay
->fb_width
;
771 win_data
->fb_height
= overlay
->fb_height
;
772 win_data
->src_width
= overlay
->src_width
;
773 win_data
->src_height
= overlay
->src_height
;
775 win_data
->mode_width
= overlay
->mode_width
;
776 win_data
->mode_height
= overlay
->mode_height
;
778 win_data
->scan_flags
= overlay
->scan_flag
;
781 static void mixer_win_commit(void *ctx
, int win
)
783 struct mixer_context
*mixer_ctx
= ctx
;
785 DRM_DEBUG_KMS("win: %d\n", win
);
787 mutex_lock(&mixer_ctx
->mixer_mutex
);
788 if (!mixer_ctx
->powered
) {
789 mutex_unlock(&mixer_ctx
->mixer_mutex
);
792 mutex_unlock(&mixer_ctx
->mixer_mutex
);
794 if (win
> 1 && mixer_ctx
->vp_enabled
)
795 vp_video_buffer(mixer_ctx
, win
);
797 mixer_graph_buffer(mixer_ctx
, win
);
799 mixer_ctx
->win_data
[win
].enabled
= true;
802 static void mixer_win_disable(void *ctx
, int win
)
804 struct mixer_context
*mixer_ctx
= ctx
;
805 struct mixer_resources
*res
= &mixer_ctx
->mixer_res
;
808 DRM_DEBUG_KMS("win: %d\n", win
);
810 mutex_lock(&mixer_ctx
->mixer_mutex
);
811 if (!mixer_ctx
->powered
) {
812 mutex_unlock(&mixer_ctx
->mixer_mutex
);
813 mixer_ctx
->win_data
[win
].resume
= false;
816 mutex_unlock(&mixer_ctx
->mixer_mutex
);
818 spin_lock_irqsave(&res
->reg_slock
, flags
);
819 mixer_vsync_set_update(mixer_ctx
, false);
821 mixer_cfg_layer(mixer_ctx
, win
, false);
823 mixer_vsync_set_update(mixer_ctx
, true);
824 spin_unlock_irqrestore(&res
->reg_slock
, flags
);
826 mixer_ctx
->win_data
[win
].enabled
= false;
829 static int mixer_check_mode(void *ctx
, struct drm_display_mode
*mode
)
831 struct mixer_context
*mixer_ctx
= ctx
;
837 DRM_DEBUG_KMS("xres=%d, yres=%d, refresh=%d, intl=%d\n",
838 mode
->hdisplay
, mode
->vdisplay
, mode
->vrefresh
,
839 (mode
->flags
& DRM_MODE_FLAG_INTERLACE
) ? 1 : 0);
841 if (mixer_ctx
->mxr_ver
== MXR_VER_0_0_0_16
||
842 mixer_ctx
->mxr_ver
== MXR_VER_128_0_0_184
)
845 if ((w
>= 464 && w
<= 720 && h
>= 261 && h
<= 576) ||
846 (w
>= 1024 && w
<= 1280 && h
>= 576 && h
<= 720) ||
847 (w
>= 1664 && w
<= 1920 && h
>= 936 && h
<= 1080))
852 static void mixer_wait_for_vblank(void *ctx
)
854 struct mixer_context
*mixer_ctx
= ctx
;
856 mutex_lock(&mixer_ctx
->mixer_mutex
);
857 if (!mixer_ctx
->powered
) {
858 mutex_unlock(&mixer_ctx
->mixer_mutex
);
861 mutex_unlock(&mixer_ctx
->mixer_mutex
);
863 atomic_set(&mixer_ctx
->wait_vsync_event
, 1);
866 * wait for MIXER to signal VSYNC interrupt or return after
867 * timeout which is set to 50ms (refresh rate of 20).
869 if (!wait_event_timeout(mixer_ctx
->wait_vsync_queue
,
870 !atomic_read(&mixer_ctx
->wait_vsync_event
),
872 DRM_DEBUG_KMS("vblank wait timed out.\n");
875 static void mixer_window_suspend(struct mixer_context
*ctx
)
877 struct hdmi_win_data
*win_data
;
880 for (i
= 0; i
< MIXER_WIN_NR
; i
++) {
881 win_data
= &ctx
->win_data
[i
];
882 win_data
->resume
= win_data
->enabled
;
883 mixer_win_disable(ctx
, i
);
885 mixer_wait_for_vblank(ctx
);
888 static void mixer_window_resume(struct mixer_context
*ctx
)
890 struct hdmi_win_data
*win_data
;
893 for (i
= 0; i
< MIXER_WIN_NR
; i
++) {
894 win_data
= &ctx
->win_data
[i
];
895 win_data
->enabled
= win_data
->resume
;
896 win_data
->resume
= false;
900 static void mixer_poweron(struct mixer_context
*ctx
)
902 struct mixer_resources
*res
= &ctx
->mixer_res
;
904 mutex_lock(&ctx
->mixer_mutex
);
906 mutex_unlock(&ctx
->mixer_mutex
);
910 mutex_unlock(&ctx
->mixer_mutex
);
912 clk_prepare_enable(res
->mixer
);
913 if (ctx
->vp_enabled
) {
914 clk_prepare_enable(res
->vp
);
915 clk_prepare_enable(res
->sclk_mixer
);
918 mixer_reg_write(res
, MXR_INT_EN
, ctx
->int_en
);
919 mixer_win_reset(ctx
);
921 mixer_window_resume(ctx
);
924 static void mixer_poweroff(struct mixer_context
*ctx
)
926 struct mixer_resources
*res
= &ctx
->mixer_res
;
928 mutex_lock(&ctx
->mixer_mutex
);
931 mutex_unlock(&ctx
->mixer_mutex
);
933 mixer_window_suspend(ctx
);
935 ctx
->int_en
= mixer_reg_read(res
, MXR_INT_EN
);
937 clk_disable_unprepare(res
->mixer
);
938 if (ctx
->vp_enabled
) {
939 clk_disable_unprepare(res
->vp
);
940 clk_disable_unprepare(res
->sclk_mixer
);
943 mutex_lock(&ctx
->mixer_mutex
);
944 ctx
->powered
= false;
947 mutex_unlock(&ctx
->mixer_mutex
);
950 static void mixer_dpms(void *ctx
, int mode
)
952 struct mixer_context
*mixer_ctx
= ctx
;
955 case DRM_MODE_DPMS_ON
:
956 if (pm_runtime_suspended(mixer_ctx
->dev
))
957 pm_runtime_get_sync(mixer_ctx
->dev
);
959 case DRM_MODE_DPMS_STANDBY
:
960 case DRM_MODE_DPMS_SUSPEND
:
961 case DRM_MODE_DPMS_OFF
:
962 if (!pm_runtime_suspended(mixer_ctx
->dev
))
963 pm_runtime_put_sync(mixer_ctx
->dev
);
966 DRM_DEBUG_KMS("unknown dpms mode: %d\n", mode
);
971 static struct exynos_mixer_ops mixer_ops
= {
973 .iommu_on
= mixer_iommu_on
,
974 .enable_vblank
= mixer_enable_vblank
,
975 .disable_vblank
= mixer_disable_vblank
,
976 .wait_for_vblank
= mixer_wait_for_vblank
,
980 .win_mode_set
= mixer_win_mode_set
,
981 .win_commit
= mixer_win_commit
,
982 .win_disable
= mixer_win_disable
,
985 .check_mode
= mixer_check_mode
,
988 static irqreturn_t
mixer_irq_handler(int irq
, void *arg
)
990 struct exynos_drm_hdmi_context
*drm_hdmi_ctx
= arg
;
991 struct mixer_context
*ctx
= drm_hdmi_ctx
->ctx
;
992 struct mixer_resources
*res
= &ctx
->mixer_res
;
993 u32 val
, base
, shadow
;
995 spin_lock(&res
->reg_slock
);
997 /* read interrupt status for handling and clearing flags for VSYNC */
998 val
= mixer_reg_read(res
, MXR_INT_STATUS
);
1000 /* handling VSYNC */
1001 if (val
& MXR_INT_STATUS_VSYNC
) {
1002 /* interlace scan need to check shadow register */
1003 if (ctx
->interlace
) {
1004 base
= mixer_reg_read(res
, MXR_GRAPHIC_BASE(0));
1005 shadow
= mixer_reg_read(res
, MXR_GRAPHIC_BASE_S(0));
1009 base
= mixer_reg_read(res
, MXR_GRAPHIC_BASE(1));
1010 shadow
= mixer_reg_read(res
, MXR_GRAPHIC_BASE_S(1));
1015 drm_handle_vblank(drm_hdmi_ctx
->drm_dev
, ctx
->pipe
);
1016 exynos_drm_crtc_finish_pageflip(drm_hdmi_ctx
->drm_dev
,
1019 /* set wait vsync event to zero and wake up queue. */
1020 if (atomic_read(&ctx
->wait_vsync_event
)) {
1021 atomic_set(&ctx
->wait_vsync_event
, 0);
1022 DRM_WAKEUP(&ctx
->wait_vsync_queue
);
1027 /* clear interrupts */
1028 if (~val
& MXR_INT_EN_VSYNC
) {
1029 /* vsync interrupt use different bit for read and clear */
1030 val
&= ~MXR_INT_EN_VSYNC
;
1031 val
|= MXR_INT_CLEAR_VSYNC
;
1033 mixer_reg_write(res
, MXR_INT_STATUS
, val
);
1035 spin_unlock(&res
->reg_slock
);
1040 static int mixer_resources_init(struct exynos_drm_hdmi_context
*ctx
,
1041 struct platform_device
*pdev
)
1043 struct mixer_context
*mixer_ctx
= ctx
->ctx
;
1044 struct device
*dev
= &pdev
->dev
;
1045 struct mixer_resources
*mixer_res
= &mixer_ctx
->mixer_res
;
1046 struct resource
*res
;
1049 spin_lock_init(&mixer_res
->reg_slock
);
1051 mixer_res
->mixer
= devm_clk_get(dev
, "mixer");
1052 if (IS_ERR(mixer_res
->mixer
)) {
1053 dev_err(dev
, "failed to get clock 'mixer'\n");
1057 mixer_res
->sclk_hdmi
= devm_clk_get(dev
, "sclk_hdmi");
1058 if (IS_ERR(mixer_res
->sclk_hdmi
)) {
1059 dev_err(dev
, "failed to get clock 'sclk_hdmi'\n");
1062 res
= platform_get_resource(pdev
, IORESOURCE_MEM
, 0);
1064 dev_err(dev
, "get memory resource failed.\n");
1068 mixer_res
->mixer_regs
= devm_ioremap(dev
, res
->start
,
1069 resource_size(res
));
1070 if (mixer_res
->mixer_regs
== NULL
) {
1071 dev_err(dev
, "register mapping failed.\n");
1075 res
= platform_get_resource(pdev
, IORESOURCE_IRQ
, 0);
1077 dev_err(dev
, "get interrupt resource failed.\n");
1081 ret
= devm_request_irq(dev
, res
->start
, mixer_irq_handler
,
1082 0, "drm_mixer", ctx
);
1084 dev_err(dev
, "request interrupt failed.\n");
1087 mixer_res
->irq
= res
->start
;
1092 static int vp_resources_init(struct exynos_drm_hdmi_context
*ctx
,
1093 struct platform_device
*pdev
)
1095 struct mixer_context
*mixer_ctx
= ctx
->ctx
;
1096 struct device
*dev
= &pdev
->dev
;
1097 struct mixer_resources
*mixer_res
= &mixer_ctx
->mixer_res
;
1098 struct resource
*res
;
1100 mixer_res
->vp
= devm_clk_get(dev
, "vp");
1101 if (IS_ERR(mixer_res
->vp
)) {
1102 dev_err(dev
, "failed to get clock 'vp'\n");
1105 mixer_res
->sclk_mixer
= devm_clk_get(dev
, "sclk_mixer");
1106 if (IS_ERR(mixer_res
->sclk_mixer
)) {
1107 dev_err(dev
, "failed to get clock 'sclk_mixer'\n");
1110 mixer_res
->sclk_dac
= devm_clk_get(dev
, "sclk_dac");
1111 if (IS_ERR(mixer_res
->sclk_dac
)) {
1112 dev_err(dev
, "failed to get clock 'sclk_dac'\n");
1116 if (mixer_res
->sclk_hdmi
)
1117 clk_set_parent(mixer_res
->sclk_mixer
, mixer_res
->sclk_hdmi
);
1119 res
= platform_get_resource(pdev
, IORESOURCE_MEM
, 1);
1121 dev_err(dev
, "get memory resource failed.\n");
1125 mixer_res
->vp_regs
= devm_ioremap(dev
, res
->start
,
1126 resource_size(res
));
1127 if (mixer_res
->vp_regs
== NULL
) {
1128 dev_err(dev
, "register mapping failed.\n");
1135 static struct mixer_drv_data exynos5420_mxr_drv_data
= {
1136 .version
= MXR_VER_128_0_0_184
,
1140 static struct mixer_drv_data exynos5250_mxr_drv_data
= {
1141 .version
= MXR_VER_16_0_33_0
,
1145 static struct mixer_drv_data exynos4210_mxr_drv_data
= {
1146 .version
= MXR_VER_0_0_0_16
,
1150 static struct platform_device_id mixer_driver_types
[] = {
1152 .name
= "s5p-mixer",
1153 .driver_data
= (unsigned long)&exynos4210_mxr_drv_data
,
1155 .name
= "exynos5-mixer",
1156 .driver_data
= (unsigned long)&exynos5250_mxr_drv_data
,
1162 static struct of_device_id mixer_match_types
[] = {
1164 .compatible
= "samsung,exynos5-mixer",
1165 .data
= &exynos5250_mxr_drv_data
,
1167 .compatible
= "samsung,exynos5250-mixer",
1168 .data
= &exynos5250_mxr_drv_data
,
1170 .compatible
= "samsung,exynos5420-mixer",
1171 .data
= &exynos5420_mxr_drv_data
,
1177 static int mixer_probe(struct platform_device
*pdev
)
1179 struct device
*dev
= &pdev
->dev
;
1180 struct exynos_drm_hdmi_context
*drm_hdmi_ctx
;
1181 struct mixer_context
*ctx
;
1182 struct mixer_drv_data
*drv
;
1185 dev_info(dev
, "probe start\n");
1187 drm_hdmi_ctx
= devm_kzalloc(dev
, sizeof(*drm_hdmi_ctx
),
1192 ctx
= devm_kzalloc(dev
, sizeof(*ctx
), GFP_KERNEL
);
1196 mutex_init(&ctx
->mixer_mutex
);
1199 const struct of_device_id
*match
;
1200 match
= of_match_node(mixer_match_types
, dev
->of_node
);
1201 drv
= (struct mixer_drv_data
*)match
->data
;
1203 drv
= (struct mixer_drv_data
*)
1204 platform_get_device_id(pdev
)->driver_data
;
1208 ctx
->parent_ctx
= (void *)drm_hdmi_ctx
;
1209 drm_hdmi_ctx
->ctx
= (void *)ctx
;
1210 ctx
->vp_enabled
= drv
->is_vp_enabled
;
1211 ctx
->mxr_ver
= drv
->version
;
1212 DRM_INIT_WAITQUEUE(&ctx
->wait_vsync_queue
);
1213 atomic_set(&ctx
->wait_vsync_event
, 0);
1215 platform_set_drvdata(pdev
, drm_hdmi_ctx
);
1217 /* acquire resources: regs, irqs, clocks */
1218 ret
= mixer_resources_init(drm_hdmi_ctx
, pdev
);
1220 DRM_ERROR("mixer_resources_init failed\n");
1224 if (ctx
->vp_enabled
) {
1225 /* acquire vp resources: regs, irqs, clocks */
1226 ret
= vp_resources_init(drm_hdmi_ctx
, pdev
);
1228 DRM_ERROR("vp_resources_init failed\n");
1233 /* attach mixer driver to common hdmi. */
1234 exynos_mixer_drv_attach(drm_hdmi_ctx
);
1236 /* register specific callback point to common hdmi. */
1237 exynos_mixer_ops_register(&mixer_ops
);
1239 pm_runtime_enable(dev
);
1245 dev_info(dev
, "probe failed\n");
1249 static int mixer_remove(struct platform_device
*pdev
)
1251 dev_info(&pdev
->dev
, "remove successful\n");
1253 pm_runtime_disable(&pdev
->dev
);
1258 #ifdef CONFIG_PM_SLEEP
1259 static int mixer_suspend(struct device
*dev
)
1261 struct exynos_drm_hdmi_context
*drm_hdmi_ctx
= get_mixer_context(dev
);
1262 struct mixer_context
*ctx
= drm_hdmi_ctx
->ctx
;
1264 if (pm_runtime_suspended(dev
)) {
1265 DRM_DEBUG_KMS("Already suspended\n");
1269 mixer_poweroff(ctx
);
1274 static int mixer_resume(struct device
*dev
)
1276 struct exynos_drm_hdmi_context
*drm_hdmi_ctx
= get_mixer_context(dev
);
1277 struct mixer_context
*ctx
= drm_hdmi_ctx
->ctx
;
1279 if (!pm_runtime_suspended(dev
)) {
1280 DRM_DEBUG_KMS("Already resumed\n");
1290 #ifdef CONFIG_PM_RUNTIME
1291 static int mixer_runtime_suspend(struct device
*dev
)
1293 struct exynos_drm_hdmi_context
*drm_hdmi_ctx
= get_mixer_context(dev
);
1294 struct mixer_context
*ctx
= drm_hdmi_ctx
->ctx
;
1296 mixer_poweroff(ctx
);
1301 static int mixer_runtime_resume(struct device
*dev
)
1303 struct exynos_drm_hdmi_context
*drm_hdmi_ctx
= get_mixer_context(dev
);
1304 struct mixer_context
*ctx
= drm_hdmi_ctx
->ctx
;
1312 static const struct dev_pm_ops mixer_pm_ops
= {
1313 SET_SYSTEM_SLEEP_PM_OPS(mixer_suspend
, mixer_resume
)
1314 SET_RUNTIME_PM_OPS(mixer_runtime_suspend
, mixer_runtime_resume
, NULL
)
1317 struct platform_driver mixer_driver
= {
1319 .name
= "exynos-mixer",
1320 .owner
= THIS_MODULE
,
1321 .pm
= &mixer_pm_ops
,
1322 .of_match_table
= mixer_match_types
,
1324 .probe
= mixer_probe
,
1325 .remove
= mixer_remove
,
1326 .id_table
= mixer_driver_types
,