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/module.h>
27 #include <linux/platform_device.h>
28 #include <linux/interrupt.h>
29 #include <linux/irq.h>
30 #include <linux/delay.h>
31 #include <linux/pm_runtime.h>
32 #include <linux/clk.h>
33 #include <linux/regulator/consumer.h>
35 #include <drm/exynos_drm.h>
37 #include "exynos_drm_drv.h"
38 #include "exynos_drm_hdmi.h"
40 #define get_mixer_context(dev) platform_get_drvdata(to_platform_device(dev))
42 struct hdmi_win_data
{
45 dma_addr_t chroma_dma_addr
;
46 void __iomem
*chroma_vaddr
;
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 mode_width
;
58 unsigned int mode_height
;
59 unsigned int scan_flags
;
62 struct mixer_resources
{
64 void __iomem
*mixer_regs
;
65 void __iomem
*vp_regs
;
69 struct clk
*sclk_mixer
;
70 struct clk
*sclk_hdmi
;
74 struct mixer_context
{
81 struct mutex mixer_mutex
;
82 struct mixer_resources mixer_res
;
83 struct hdmi_win_data win_data
[MIXER_WIN_NR
];
86 static const u8 filter_y_horiz_tap8
[] = {
87 0, -1, -1, -1, -1, -1, -1, -1,
88 -1, -1, -1, -1, -1, 0, 0, 0,
89 0, 2, 4, 5, 6, 6, 6, 6,
90 6, 5, 5, 4, 3, 2, 1, 1,
91 0, -6, -12, -16, -18, -20, -21, -20,
92 -20, -18, -16, -13, -10, -8, -5, -2,
93 127, 126, 125, 121, 114, 107, 99, 89,
94 79, 68, 57, 46, 35, 25, 16, 8,
97 static const u8 filter_y_vert_tap4
[] = {
98 0, -3, -6, -8, -8, -8, -8, -7,
99 -6, -5, -4, -3, -2, -1, -1, 0,
100 127, 126, 124, 118, 111, 102, 92, 81,
101 70, 59, 48, 37, 27, 19, 11, 5,
102 0, 5, 11, 19, 27, 37, 48, 59,
103 70, 81, 92, 102, 111, 118, 124, 126,
104 0, 0, -1, -1, -2, -3, -4, -5,
105 -6, -7, -8, -8, -8, -8, -6, -3,
108 static const u8 filter_cr_horiz_tap4
[] = {
109 0, -3, -6, -8, -8, -8, -8, -7,
110 -6, -5, -4, -3, -2, -1, -1, 0,
111 127, 126, 124, 118, 111, 102, 92, 81,
112 70, 59, 48, 37, 27, 19, 11, 5,
115 static inline u32
vp_reg_read(struct mixer_resources
*res
, u32 reg_id
)
117 return readl(res
->vp_regs
+ reg_id
);
120 static inline void vp_reg_write(struct mixer_resources
*res
, u32 reg_id
,
123 writel(val
, res
->vp_regs
+ reg_id
);
126 static inline void vp_reg_writemask(struct mixer_resources
*res
, u32 reg_id
,
129 u32 old
= vp_reg_read(res
, reg_id
);
131 val
= (val
& mask
) | (old
& ~mask
);
132 writel(val
, res
->vp_regs
+ reg_id
);
135 static inline u32
mixer_reg_read(struct mixer_resources
*res
, u32 reg_id
)
137 return readl(res
->mixer_regs
+ reg_id
);
140 static inline void mixer_reg_write(struct mixer_resources
*res
, u32 reg_id
,
143 writel(val
, res
->mixer_regs
+ reg_id
);
146 static inline void mixer_reg_writemask(struct mixer_resources
*res
,
147 u32 reg_id
, u32 val
, u32 mask
)
149 u32 old
= mixer_reg_read(res
, reg_id
);
151 val
= (val
& mask
) | (old
& ~mask
);
152 writel(val
, res
->mixer_regs
+ reg_id
);
155 static void mixer_regs_dump(struct mixer_context
*ctx
)
157 #define DUMPREG(reg_id) \
159 DRM_DEBUG_KMS(#reg_id " = %08x\n", \
160 (u32)readl(ctx->mixer_res.mixer_regs + reg_id)); \
166 DUMPREG(MXR_INT_STATUS
);
168 DUMPREG(MXR_LAYER_CFG
);
169 DUMPREG(MXR_VIDEO_CFG
);
171 DUMPREG(MXR_GRAPHIC0_CFG
);
172 DUMPREG(MXR_GRAPHIC0_BASE
);
173 DUMPREG(MXR_GRAPHIC0_SPAN
);
174 DUMPREG(MXR_GRAPHIC0_WH
);
175 DUMPREG(MXR_GRAPHIC0_SXY
);
176 DUMPREG(MXR_GRAPHIC0_DXY
);
178 DUMPREG(MXR_GRAPHIC1_CFG
);
179 DUMPREG(MXR_GRAPHIC1_BASE
);
180 DUMPREG(MXR_GRAPHIC1_SPAN
);
181 DUMPREG(MXR_GRAPHIC1_WH
);
182 DUMPREG(MXR_GRAPHIC1_SXY
);
183 DUMPREG(MXR_GRAPHIC1_DXY
);
187 static void vp_regs_dump(struct mixer_context
*ctx
)
189 #define DUMPREG(reg_id) \
191 DRM_DEBUG_KMS(#reg_id " = %08x\n", \
192 (u32) readl(ctx->mixer_res.vp_regs + reg_id)); \
197 DUMPREG(VP_SHADOW_UPDATE
);
198 DUMPREG(VP_FIELD_ID
);
200 DUMPREG(VP_IMG_SIZE_Y
);
201 DUMPREG(VP_IMG_SIZE_C
);
202 DUMPREG(VP_PER_RATE_CTRL
);
203 DUMPREG(VP_TOP_Y_PTR
);
204 DUMPREG(VP_BOT_Y_PTR
);
205 DUMPREG(VP_TOP_C_PTR
);
206 DUMPREG(VP_BOT_C_PTR
);
207 DUMPREG(VP_ENDIAN_MODE
);
208 DUMPREG(VP_SRC_H_POSITION
);
209 DUMPREG(VP_SRC_V_POSITION
);
210 DUMPREG(VP_SRC_WIDTH
);
211 DUMPREG(VP_SRC_HEIGHT
);
212 DUMPREG(VP_DST_H_POSITION
);
213 DUMPREG(VP_DST_V_POSITION
);
214 DUMPREG(VP_DST_WIDTH
);
215 DUMPREG(VP_DST_HEIGHT
);
222 static inline void vp_filter_set(struct mixer_resources
*res
,
223 int reg_id
, const u8
*data
, unsigned int size
)
225 /* assure 4-byte align */
227 for (; size
; size
-= 4, reg_id
+= 4, data
+= 4) {
228 u32 val
= (data
[0] << 24) | (data
[1] << 16) |
229 (data
[2] << 8) | data
[3];
230 vp_reg_write(res
, reg_id
, val
);
234 static void vp_default_filter(struct mixer_resources
*res
)
236 vp_filter_set(res
, VP_POLY8_Y0_LL
,
237 filter_y_horiz_tap8
, sizeof filter_y_horiz_tap8
);
238 vp_filter_set(res
, VP_POLY4_Y0_LL
,
239 filter_y_vert_tap4
, sizeof filter_y_vert_tap4
);
240 vp_filter_set(res
, VP_POLY4_C0_LL
,
241 filter_cr_horiz_tap4
, sizeof filter_cr_horiz_tap4
);
244 static void mixer_vsync_set_update(struct mixer_context
*ctx
, bool enable
)
246 struct mixer_resources
*res
= &ctx
->mixer_res
;
248 /* block update on vsync */
249 mixer_reg_writemask(res
, MXR_STATUS
, enable
?
250 MXR_STATUS_SYNC_ENABLE
: 0, MXR_STATUS_SYNC_ENABLE
);
252 vp_reg_write(res
, VP_SHADOW_UPDATE
, enable
?
253 VP_SHADOW_UPDATE_ENABLE
: 0);
256 static void mixer_cfg_scan(struct mixer_context
*ctx
, unsigned int height
)
258 struct mixer_resources
*res
= &ctx
->mixer_res
;
261 /* choosing between interlace and progressive mode */
262 val
= (ctx
->interlace
? MXR_CFG_SCAN_INTERLACE
:
263 MXR_CFG_SCAN_PROGRASSIVE
);
265 /* choosing between porper HD and SD mode */
267 val
|= MXR_CFG_SCAN_NTSC
| MXR_CFG_SCAN_SD
;
268 else if (height
== 576)
269 val
|= MXR_CFG_SCAN_PAL
| MXR_CFG_SCAN_SD
;
270 else if (height
== 720)
271 val
|= MXR_CFG_SCAN_HD_720
| MXR_CFG_SCAN_HD
;
272 else if (height
== 1080)
273 val
|= MXR_CFG_SCAN_HD_1080
| MXR_CFG_SCAN_HD
;
275 val
|= MXR_CFG_SCAN_HD_720
| MXR_CFG_SCAN_HD
;
277 mixer_reg_writemask(res
, MXR_CFG
, val
, MXR_CFG_SCAN_MASK
);
280 static void mixer_cfg_rgb_fmt(struct mixer_context
*ctx
, unsigned int height
)
282 struct mixer_resources
*res
= &ctx
->mixer_res
;
286 val
= MXR_CFG_RGB601_0_255
;
287 } else if (height
== 576) {
288 val
= MXR_CFG_RGB601_0_255
;
289 } else if (height
== 720) {
290 val
= MXR_CFG_RGB709_16_235
;
291 mixer_reg_write(res
, MXR_CM_COEFF_Y
,
292 (1 << 30) | (94 << 20) | (314 << 10) |
294 mixer_reg_write(res
, MXR_CM_COEFF_CB
,
295 (972 << 20) | (851 << 10) | (225 << 0));
296 mixer_reg_write(res
, MXR_CM_COEFF_CR
,
297 (225 << 20) | (820 << 10) | (1004 << 0));
298 } else if (height
== 1080) {
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));
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));
318 mixer_reg_writemask(res
, MXR_CFG
, val
, MXR_CFG_RGB_FMT_MASK
);
321 static void mixer_cfg_layer(struct mixer_context
*ctx
, int win
, bool enable
)
323 struct mixer_resources
*res
= &ctx
->mixer_res
;
324 u32 val
= enable
? ~0 : 0;
328 mixer_reg_writemask(res
, MXR_CFG
, val
, MXR_CFG_GRP0_ENABLE
);
331 mixer_reg_writemask(res
, MXR_CFG
, val
, MXR_CFG_GRP1_ENABLE
);
334 vp_reg_writemask(res
, VP_ENABLE
, val
, VP_ENABLE_ON
);
335 mixer_reg_writemask(res
, MXR_CFG
, val
, MXR_CFG_VP_ENABLE
);
340 static void mixer_run(struct mixer_context
*ctx
)
342 struct mixer_resources
*res
= &ctx
->mixer_res
;
344 mixer_reg_writemask(res
, MXR_STATUS
, ~0, MXR_STATUS_REG_RUN
);
346 mixer_regs_dump(ctx
);
349 static void vp_video_buffer(struct mixer_context
*ctx
, int win
)
351 struct mixer_resources
*res
= &ctx
->mixer_res
;
353 struct hdmi_win_data
*win_data
;
354 unsigned int full_width
, full_height
, width
, height
;
355 unsigned int x_ratio
, y_ratio
;
356 unsigned int src_x_offset
, src_y_offset
, dst_x_offset
, dst_y_offset
;
357 unsigned int mode_width
, mode_height
;
358 unsigned int buf_num
;
359 dma_addr_t luma_addr
[2], chroma_addr
[2];
360 bool tiled_mode
= false;
361 bool crcb_mode
= false;
364 win_data
= &ctx
->win_data
[win
];
366 switch (win_data
->pixel_format
) {
367 case DRM_FORMAT_NV12MT
:
369 case DRM_FORMAT_NV12M
:
373 /* TODO: single buffer format NV12, NV21 */
375 /* ignore pixel format at disable time */
376 if (!win_data
->dma_addr
)
379 DRM_ERROR("pixel format for vp is wrong [%d].\n",
380 win_data
->pixel_format
);
384 full_width
= win_data
->fb_width
;
385 full_height
= win_data
->fb_height
;
386 width
= win_data
->crtc_width
;
387 height
= win_data
->crtc_height
;
388 mode_width
= win_data
->mode_width
;
389 mode_height
= win_data
->mode_height
;
391 /* scaling feature: (src << 16) / dst */
392 x_ratio
= (width
<< 16) / width
;
393 y_ratio
= (height
<< 16) / height
;
395 src_x_offset
= win_data
->fb_x
;
396 src_y_offset
= win_data
->fb_y
;
397 dst_x_offset
= win_data
->crtc_x
;
398 dst_y_offset
= win_data
->crtc_y
;
401 luma_addr
[0] = win_data
->dma_addr
;
402 chroma_addr
[0] = win_data
->chroma_dma_addr
;
404 luma_addr
[0] = win_data
->dma_addr
;
405 chroma_addr
[0] = win_data
->dma_addr
406 + (full_width
* full_height
);
409 if (win_data
->scan_flags
& DRM_MODE_FLAG_INTERLACE
) {
410 ctx
->interlace
= true;
412 luma_addr
[1] = luma_addr
[0] + 0x40;
413 chroma_addr
[1] = chroma_addr
[0] + 0x40;
415 luma_addr
[1] = luma_addr
[0] + full_width
;
416 chroma_addr
[1] = chroma_addr
[0] + full_width
;
419 ctx
->interlace
= false;
424 spin_lock_irqsave(&res
->reg_slock
, flags
);
425 mixer_vsync_set_update(ctx
, false);
427 /* interlace or progressive scan mode */
428 val
= (ctx
->interlace
? ~0 : 0);
429 vp_reg_writemask(res
, VP_MODE
, val
, VP_MODE_LINE_SKIP
);
432 val
= (crcb_mode
? VP_MODE_NV21
: VP_MODE_NV12
);
433 val
|= (tiled_mode
? VP_MODE_MEM_TILED
: VP_MODE_MEM_LINEAR
);
434 vp_reg_writemask(res
, VP_MODE
, val
, VP_MODE_FMT_MASK
);
436 /* setting size of input image */
437 vp_reg_write(res
, VP_IMG_SIZE_Y
, VP_IMG_HSIZE(full_width
) |
438 VP_IMG_VSIZE(full_height
));
439 /* chroma height has to reduced by 2 to avoid chroma distorions */
440 vp_reg_write(res
, VP_IMG_SIZE_C
, VP_IMG_HSIZE(full_width
) |
441 VP_IMG_VSIZE(full_height
/ 2));
443 vp_reg_write(res
, VP_SRC_WIDTH
, width
);
444 vp_reg_write(res
, VP_SRC_HEIGHT
, height
);
445 vp_reg_write(res
, VP_SRC_H_POSITION
,
446 VP_SRC_H_POSITION_VAL(src_x_offset
));
447 vp_reg_write(res
, VP_SRC_V_POSITION
, src_y_offset
);
449 vp_reg_write(res
, VP_DST_WIDTH
, width
);
450 vp_reg_write(res
, VP_DST_H_POSITION
, dst_x_offset
);
451 if (ctx
->interlace
) {
452 vp_reg_write(res
, VP_DST_HEIGHT
, height
/ 2);
453 vp_reg_write(res
, VP_DST_V_POSITION
, dst_y_offset
/ 2);
455 vp_reg_write(res
, VP_DST_HEIGHT
, height
);
456 vp_reg_write(res
, VP_DST_V_POSITION
, dst_y_offset
);
459 vp_reg_write(res
, VP_H_RATIO
, x_ratio
);
460 vp_reg_write(res
, VP_V_RATIO
, y_ratio
);
462 vp_reg_write(res
, VP_ENDIAN_MODE
, VP_ENDIAN_MODE_LITTLE
);
464 /* set buffer address to vp */
465 vp_reg_write(res
, VP_TOP_Y_PTR
, luma_addr
[0]);
466 vp_reg_write(res
, VP_BOT_Y_PTR
, luma_addr
[1]);
467 vp_reg_write(res
, VP_TOP_C_PTR
, chroma_addr
[0]);
468 vp_reg_write(res
, VP_BOT_C_PTR
, chroma_addr
[1]);
470 mixer_cfg_scan(ctx
, mode_height
);
471 mixer_cfg_rgb_fmt(ctx
, mode_height
);
472 mixer_cfg_layer(ctx
, win
, true);
475 mixer_vsync_set_update(ctx
, true);
476 spin_unlock_irqrestore(&res
->reg_slock
, flags
);
481 static void mixer_graph_buffer(struct mixer_context
*ctx
, int win
)
483 struct mixer_resources
*res
= &ctx
->mixer_res
;
485 struct hdmi_win_data
*win_data
;
486 unsigned int full_width
, width
, height
;
487 unsigned int x_ratio
, y_ratio
;
488 unsigned int src_x_offset
, src_y_offset
, dst_x_offset
, dst_y_offset
;
489 unsigned int mode_width
, mode_height
;
494 win_data
= &ctx
->win_data
[win
];
501 switch (win_data
->bpp
) {
512 dma_addr
= win_data
->dma_addr
;
513 full_width
= win_data
->fb_width
;
514 width
= win_data
->crtc_width
;
515 height
= win_data
->crtc_height
;
516 mode_width
= win_data
->mode_width
;
517 mode_height
= win_data
->mode_height
;
519 /* 2x scaling feature */
523 src_x_offset
= win_data
->fb_x
;
524 src_y_offset
= win_data
->fb_y
;
525 dst_x_offset
= win_data
->crtc_x
;
526 dst_y_offset
= win_data
->crtc_y
;
528 /* converting dma address base and source offset */
530 + (src_x_offset
* win_data
->bpp
>> 3)
531 + (src_y_offset
* full_width
* win_data
->bpp
>> 3);
535 if (win_data
->scan_flags
& DRM_MODE_FLAG_INTERLACE
)
536 ctx
->interlace
= true;
538 ctx
->interlace
= false;
540 spin_lock_irqsave(&res
->reg_slock
, flags
);
541 mixer_vsync_set_update(ctx
, false);
544 mixer_reg_writemask(res
, MXR_GRAPHIC_CFG(win
),
545 MXR_GRP_CFG_FORMAT_VAL(fmt
), MXR_GRP_CFG_FORMAT_MASK
);
548 mixer_reg_write(res
, MXR_GRAPHIC_SPAN(win
), full_width
);
550 val
= MXR_GRP_WH_WIDTH(width
);
551 val
|= MXR_GRP_WH_HEIGHT(height
);
552 val
|= MXR_GRP_WH_H_SCALE(x_ratio
);
553 val
|= MXR_GRP_WH_V_SCALE(y_ratio
);
554 mixer_reg_write(res
, MXR_GRAPHIC_WH(win
), val
);
556 /* setup offsets in source image */
557 val
= MXR_GRP_SXY_SX(src_x_offset
);
558 val
|= MXR_GRP_SXY_SY(src_y_offset
);
559 mixer_reg_write(res
, MXR_GRAPHIC_SXY(win
), val
);
561 /* setup offsets in display image */
562 val
= MXR_GRP_DXY_DX(dst_x_offset
);
563 val
|= MXR_GRP_DXY_DY(dst_y_offset
);
564 mixer_reg_write(res
, MXR_GRAPHIC_DXY(win
), val
);
566 /* set buffer address to mixer */
567 mixer_reg_write(res
, MXR_GRAPHIC_BASE(win
), dma_addr
);
569 mixer_cfg_scan(ctx
, mode_height
);
570 mixer_cfg_rgb_fmt(ctx
, mode_height
);
571 mixer_cfg_layer(ctx
, win
, true);
574 mixer_vsync_set_update(ctx
, true);
575 spin_unlock_irqrestore(&res
->reg_slock
, flags
);
578 static void vp_win_reset(struct mixer_context
*ctx
)
580 struct mixer_resources
*res
= &ctx
->mixer_res
;
583 vp_reg_write(res
, VP_SRESET
, VP_SRESET_PROCESSING
);
584 for (tries
= 100; tries
; --tries
) {
585 /* waiting until VP_SRESET_PROCESSING is 0 */
586 if (~vp_reg_read(res
, VP_SRESET
) & VP_SRESET_PROCESSING
)
590 WARN(tries
== 0, "failed to reset Video Processor\n");
593 static void mixer_win_reset(struct mixer_context
*ctx
)
595 struct mixer_resources
*res
= &ctx
->mixer_res
;
597 u32 val
; /* value stored to register */
599 spin_lock_irqsave(&res
->reg_slock
, flags
);
600 mixer_vsync_set_update(ctx
, false);
602 mixer_reg_writemask(res
, MXR_CFG
, MXR_CFG_DST_HDMI
, MXR_CFG_DST_MASK
);
604 /* set output in RGB888 mode */
605 mixer_reg_writemask(res
, MXR_CFG
, MXR_CFG_OUT_RGB888
, MXR_CFG_OUT_MASK
);
607 /* 16 beat burst in DMA */
608 mixer_reg_writemask(res
, MXR_STATUS
, MXR_STATUS_16_BURST
,
609 MXR_STATUS_BURST_MASK
);
611 /* setting default layer priority: layer1 > layer0 > video
612 * because typical usage scenario would be
614 * layer0 - framebuffer
615 * video - video overlay
617 val
= MXR_LAYER_CFG_GRP1_VAL(3);
618 val
|= MXR_LAYER_CFG_GRP0_VAL(2);
619 val
|= MXR_LAYER_CFG_VP_VAL(1);
620 mixer_reg_write(res
, MXR_LAYER_CFG
, val
);
622 /* setting background color */
623 mixer_reg_write(res
, MXR_BG_COLOR0
, 0x008080);
624 mixer_reg_write(res
, MXR_BG_COLOR1
, 0x008080);
625 mixer_reg_write(res
, MXR_BG_COLOR2
, 0x008080);
627 /* setting graphical layers */
629 val
= MXR_GRP_CFG_COLOR_KEY_DISABLE
; /* no blank key */
630 val
|= MXR_GRP_CFG_WIN_BLEND_EN
;
631 val
|= MXR_GRP_CFG_ALPHA_VAL(0xff); /* non-transparent alpha */
633 /* the same configuration for both layers */
634 mixer_reg_write(res
, MXR_GRAPHIC_CFG(0), val
);
636 val
|= MXR_GRP_CFG_BLEND_PRE_MUL
;
637 val
|= MXR_GRP_CFG_PIXEL_BLEND_EN
;
638 mixer_reg_write(res
, MXR_GRAPHIC_CFG(1), val
);
640 /* configuration of Video Processor Registers */
642 vp_default_filter(res
);
644 /* disable all layers */
645 mixer_reg_writemask(res
, MXR_CFG
, 0, MXR_CFG_GRP0_ENABLE
);
646 mixer_reg_writemask(res
, MXR_CFG
, 0, MXR_CFG_GRP1_ENABLE
);
647 mixer_reg_writemask(res
, MXR_CFG
, 0, MXR_CFG_VP_ENABLE
);
649 mixer_vsync_set_update(ctx
, true);
650 spin_unlock_irqrestore(&res
->reg_slock
, flags
);
653 static void mixer_poweron(struct mixer_context
*ctx
)
655 struct mixer_resources
*res
= &ctx
->mixer_res
;
657 DRM_DEBUG_KMS("[%d] %s\n", __LINE__
, __func__
);
659 mutex_lock(&ctx
->mixer_mutex
);
661 mutex_unlock(&ctx
->mixer_mutex
);
665 mutex_unlock(&ctx
->mixer_mutex
);
667 pm_runtime_get_sync(ctx
->dev
);
669 clk_enable(res
->mixer
);
671 clk_enable(res
->sclk_mixer
);
673 mixer_reg_write(res
, MXR_INT_EN
, ctx
->int_en
);
674 mixer_win_reset(ctx
);
677 static void mixer_poweroff(struct mixer_context
*ctx
)
679 struct mixer_resources
*res
= &ctx
->mixer_res
;
681 DRM_DEBUG_KMS("[%d] %s\n", __LINE__
, __func__
);
683 mutex_lock(&ctx
->mixer_mutex
);
686 mutex_unlock(&ctx
->mixer_mutex
);
688 ctx
->int_en
= mixer_reg_read(res
, MXR_INT_EN
);
690 clk_disable(res
->mixer
);
691 clk_disable(res
->vp
);
692 clk_disable(res
->sclk_mixer
);
694 pm_runtime_put_sync(ctx
->dev
);
696 mutex_lock(&ctx
->mixer_mutex
);
697 ctx
->powered
= false;
700 mutex_unlock(&ctx
->mixer_mutex
);
703 static int mixer_enable_vblank(void *ctx
, int pipe
)
705 struct mixer_context
*mixer_ctx
= ctx
;
706 struct mixer_resources
*res
= &mixer_ctx
->mixer_res
;
708 DRM_DEBUG_KMS("[%d] %s\n", __LINE__
, __func__
);
710 mixer_ctx
->pipe
= pipe
;
712 /* enable vsync interrupt */
713 mixer_reg_writemask(res
, MXR_INT_EN
, MXR_INT_EN_VSYNC
,
719 static void mixer_disable_vblank(void *ctx
)
721 struct mixer_context
*mixer_ctx
= ctx
;
722 struct mixer_resources
*res
= &mixer_ctx
->mixer_res
;
724 DRM_DEBUG_KMS("[%d] %s\n", __LINE__
, __func__
);
726 /* disable vsync interrupt */
727 mixer_reg_writemask(res
, MXR_INT_EN
, 0, MXR_INT_EN_VSYNC
);
730 static void mixer_dpms(void *ctx
, int mode
)
732 struct mixer_context
*mixer_ctx
= ctx
;
734 DRM_DEBUG_KMS("[%d] %s\n", __LINE__
, __func__
);
737 case DRM_MODE_DPMS_ON
:
738 mixer_poweron(mixer_ctx
);
740 case DRM_MODE_DPMS_STANDBY
:
741 case DRM_MODE_DPMS_SUSPEND
:
742 case DRM_MODE_DPMS_OFF
:
743 mixer_poweroff(mixer_ctx
);
746 DRM_DEBUG_KMS("unknown dpms mode: %d\n", mode
);
751 static void mixer_win_mode_set(void *ctx
,
752 struct exynos_drm_overlay
*overlay
)
754 struct mixer_context
*mixer_ctx
= ctx
;
755 struct hdmi_win_data
*win_data
;
758 DRM_DEBUG_KMS("[%d] %s\n", __LINE__
, __func__
);
761 DRM_ERROR("overlay is NULL\n");
765 DRM_DEBUG_KMS("set [%d]x[%d] at (%d,%d) to [%d]x[%d] at (%d,%d)\n",
766 overlay
->fb_width
, overlay
->fb_height
,
767 overlay
->fb_x
, overlay
->fb_y
,
768 overlay
->crtc_width
, overlay
->crtc_height
,
769 overlay
->crtc_x
, overlay
->crtc_y
);
772 if (win
== DEFAULT_ZPOS
)
773 win
= MIXER_DEFAULT_WIN
;
775 if (win
< 0 || win
> MIXER_WIN_NR
) {
776 DRM_ERROR("mixer window[%d] is wrong\n", win
);
780 win_data
= &mixer_ctx
->win_data
[win
];
782 win_data
->dma_addr
= overlay
->dma_addr
[0];
783 win_data
->vaddr
= overlay
->vaddr
[0];
784 win_data
->chroma_dma_addr
= overlay
->dma_addr
[1];
785 win_data
->chroma_vaddr
= overlay
->vaddr
[1];
786 win_data
->pixel_format
= overlay
->pixel_format
;
787 win_data
->bpp
= overlay
->bpp
;
789 win_data
->crtc_x
= overlay
->crtc_x
;
790 win_data
->crtc_y
= overlay
->crtc_y
;
791 win_data
->crtc_width
= overlay
->crtc_width
;
792 win_data
->crtc_height
= overlay
->crtc_height
;
794 win_data
->fb_x
= overlay
->fb_x
;
795 win_data
->fb_y
= overlay
->fb_y
;
796 win_data
->fb_width
= overlay
->fb_width
;
797 win_data
->fb_height
= overlay
->fb_height
;
799 win_data
->mode_width
= overlay
->mode_width
;
800 win_data
->mode_height
= overlay
->mode_height
;
802 win_data
->scan_flags
= overlay
->scan_flag
;
805 static void mixer_win_commit(void *ctx
, int win
)
807 struct mixer_context
*mixer_ctx
= ctx
;
809 DRM_DEBUG_KMS("[%d] %s, win: %d\n", __LINE__
, __func__
, win
);
812 vp_video_buffer(mixer_ctx
, win
);
814 mixer_graph_buffer(mixer_ctx
, win
);
817 static void mixer_win_disable(void *ctx
, int win
)
819 struct mixer_context
*mixer_ctx
= ctx
;
820 struct mixer_resources
*res
= &mixer_ctx
->mixer_res
;
823 DRM_DEBUG_KMS("[%d] %s, win: %d\n", __LINE__
, __func__
, win
);
825 spin_lock_irqsave(&res
->reg_slock
, flags
);
826 mixer_vsync_set_update(mixer_ctx
, false);
828 mixer_cfg_layer(mixer_ctx
, win
, false);
830 mixer_vsync_set_update(mixer_ctx
, true);
831 spin_unlock_irqrestore(&res
->reg_slock
, flags
);
834 static struct exynos_mixer_ops mixer_ops
= {
836 .enable_vblank
= mixer_enable_vblank
,
837 .disable_vblank
= mixer_disable_vblank
,
841 .win_mode_set
= mixer_win_mode_set
,
842 .win_commit
= mixer_win_commit
,
843 .win_disable
= mixer_win_disable
,
846 /* for pageflip event */
847 static void mixer_finish_pageflip(struct drm_device
*drm_dev
, int crtc
)
849 struct exynos_drm_private
*dev_priv
= drm_dev
->dev_private
;
850 struct drm_pending_vblank_event
*e
, *t
;
853 bool is_checked
= false;
855 spin_lock_irqsave(&drm_dev
->event_lock
, flags
);
857 list_for_each_entry_safe(e
, t
, &dev_priv
->pageflip_event_list
,
859 /* if event's pipe isn't same as crtc then ignore it. */
864 do_gettimeofday(&now
);
865 e
->event
.sequence
= 0;
866 e
->event
.tv_sec
= now
.tv_sec
;
867 e
->event
.tv_usec
= now
.tv_usec
;
869 list_move_tail(&e
->base
.link
, &e
->base
.file_priv
->event_list
);
870 wake_up_interruptible(&e
->base
.file_priv
->event_wait
);
875 * call drm_vblank_put only in case that drm_vblank_get was
878 if (atomic_read(&drm_dev
->vblank_refcount
[crtc
]) > 0)
879 drm_vblank_put(drm_dev
, crtc
);
881 spin_unlock_irqrestore(&drm_dev
->event_lock
, flags
);
884 static irqreturn_t
mixer_irq_handler(int irq
, void *arg
)
886 struct exynos_drm_hdmi_context
*drm_hdmi_ctx
= arg
;
887 struct mixer_context
*ctx
= drm_hdmi_ctx
->ctx
;
888 struct mixer_resources
*res
= &ctx
->mixer_res
;
889 u32 val
, base
, shadow
;
891 spin_lock(&res
->reg_slock
);
893 /* read interrupt status for handling and clearing flags for VSYNC */
894 val
= mixer_reg_read(res
, MXR_INT_STATUS
);
897 if (val
& MXR_INT_STATUS_VSYNC
) {
898 /* interlace scan need to check shadow register */
899 if (ctx
->interlace
) {
900 base
= mixer_reg_read(res
, MXR_GRAPHIC_BASE(0));
901 shadow
= mixer_reg_read(res
, MXR_GRAPHIC_BASE_S(0));
905 base
= mixer_reg_read(res
, MXR_GRAPHIC_BASE(1));
906 shadow
= mixer_reg_read(res
, MXR_GRAPHIC_BASE_S(1));
911 drm_handle_vblank(drm_hdmi_ctx
->drm_dev
, ctx
->pipe
);
912 mixer_finish_pageflip(drm_hdmi_ctx
->drm_dev
, ctx
->pipe
);
916 /* clear interrupts */
917 if (~val
& MXR_INT_EN_VSYNC
) {
918 /* vsync interrupt use different bit for read and clear */
919 val
&= ~MXR_INT_EN_VSYNC
;
920 val
|= MXR_INT_CLEAR_VSYNC
;
922 mixer_reg_write(res
, MXR_INT_STATUS
, val
);
924 spin_unlock(&res
->reg_slock
);
929 static int __devinit
mixer_resources_init(struct exynos_drm_hdmi_context
*ctx
,
930 struct platform_device
*pdev
)
932 struct mixer_context
*mixer_ctx
= ctx
->ctx
;
933 struct device
*dev
= &pdev
->dev
;
934 struct mixer_resources
*mixer_res
= &mixer_ctx
->mixer_res
;
935 struct resource
*res
;
938 spin_lock_init(&mixer_res
->reg_slock
);
940 mixer_res
->mixer
= clk_get(dev
, "mixer");
941 if (IS_ERR_OR_NULL(mixer_res
->mixer
)) {
942 dev_err(dev
, "failed to get clock 'mixer'\n");
946 mixer_res
->vp
= clk_get(dev
, "vp");
947 if (IS_ERR_OR_NULL(mixer_res
->vp
)) {
948 dev_err(dev
, "failed to get clock 'vp'\n");
952 mixer_res
->sclk_mixer
= clk_get(dev
, "sclk_mixer");
953 if (IS_ERR_OR_NULL(mixer_res
->sclk_mixer
)) {
954 dev_err(dev
, "failed to get clock 'sclk_mixer'\n");
958 mixer_res
->sclk_hdmi
= clk_get(dev
, "sclk_hdmi");
959 if (IS_ERR_OR_NULL(mixer_res
->sclk_hdmi
)) {
960 dev_err(dev
, "failed to get clock 'sclk_hdmi'\n");
964 mixer_res
->sclk_dac
= clk_get(dev
, "sclk_dac");
965 if (IS_ERR_OR_NULL(mixer_res
->sclk_dac
)) {
966 dev_err(dev
, "failed to get clock 'sclk_dac'\n");
970 res
= platform_get_resource_byname(pdev
, IORESOURCE_MEM
, "mxr");
972 dev_err(dev
, "get memory resource failed.\n");
977 clk_set_parent(mixer_res
->sclk_mixer
, mixer_res
->sclk_hdmi
);
979 mixer_res
->mixer_regs
= ioremap(res
->start
, resource_size(res
));
980 if (mixer_res
->mixer_regs
== NULL
) {
981 dev_err(dev
, "register mapping failed.\n");
986 res
= platform_get_resource_byname(pdev
, IORESOURCE_MEM
, "vp");
988 dev_err(dev
, "get memory resource failed.\n");
990 goto fail_mixer_regs
;
993 mixer_res
->vp_regs
= ioremap(res
->start
, resource_size(res
));
994 if (mixer_res
->vp_regs
== NULL
) {
995 dev_err(dev
, "register mapping failed.\n");
997 goto fail_mixer_regs
;
1000 res
= platform_get_resource_byname(pdev
, IORESOURCE_IRQ
, "irq");
1002 dev_err(dev
, "get interrupt resource failed.\n");
1007 ret
= request_irq(res
->start
, mixer_irq_handler
, 0, "drm_mixer", ctx
);
1009 dev_err(dev
, "request interrupt failed.\n");
1012 mixer_res
->irq
= res
->start
;
1017 iounmap(mixer_res
->vp_regs
);
1020 iounmap(mixer_res
->mixer_regs
);
1023 if (!IS_ERR_OR_NULL(mixer_res
->sclk_dac
))
1024 clk_put(mixer_res
->sclk_dac
);
1025 if (!IS_ERR_OR_NULL(mixer_res
->sclk_hdmi
))
1026 clk_put(mixer_res
->sclk_hdmi
);
1027 if (!IS_ERR_OR_NULL(mixer_res
->sclk_mixer
))
1028 clk_put(mixer_res
->sclk_mixer
);
1029 if (!IS_ERR_OR_NULL(mixer_res
->vp
))
1030 clk_put(mixer_res
->vp
);
1031 if (!IS_ERR_OR_NULL(mixer_res
->mixer
))
1032 clk_put(mixer_res
->mixer
);
1036 static void mixer_resources_cleanup(struct mixer_context
*ctx
)
1038 struct mixer_resources
*res
= &ctx
->mixer_res
;
1040 free_irq(res
->irq
, ctx
);
1042 iounmap(res
->vp_regs
);
1043 iounmap(res
->mixer_regs
);
1046 static int __devinit
mixer_probe(struct platform_device
*pdev
)
1048 struct device
*dev
= &pdev
->dev
;
1049 struct exynos_drm_hdmi_context
*drm_hdmi_ctx
;
1050 struct mixer_context
*ctx
;
1053 dev_info(dev
, "probe start\n");
1055 drm_hdmi_ctx
= kzalloc(sizeof(*drm_hdmi_ctx
), GFP_KERNEL
);
1056 if (!drm_hdmi_ctx
) {
1057 DRM_ERROR("failed to allocate common hdmi context.\n");
1061 ctx
= kzalloc(sizeof(*ctx
), GFP_KERNEL
);
1063 DRM_ERROR("failed to alloc mixer context.\n");
1064 kfree(drm_hdmi_ctx
);
1068 mutex_init(&ctx
->mixer_mutex
);
1070 ctx
->dev
= &pdev
->dev
;
1071 drm_hdmi_ctx
->ctx
= (void *)ctx
;
1073 platform_set_drvdata(pdev
, drm_hdmi_ctx
);
1075 /* acquire resources: regs, irqs, clocks */
1076 ret
= mixer_resources_init(drm_hdmi_ctx
, pdev
);
1080 /* register specific callback point to common hdmi. */
1081 exynos_mixer_ops_register(&mixer_ops
);
1083 pm_runtime_enable(dev
);
1089 dev_info(dev
, "probe failed\n");
1093 static int mixer_remove(struct platform_device
*pdev
)
1095 struct device
*dev
= &pdev
->dev
;
1096 struct exynos_drm_hdmi_context
*drm_hdmi_ctx
=
1097 platform_get_drvdata(pdev
);
1098 struct mixer_context
*ctx
= drm_hdmi_ctx
->ctx
;
1100 dev_info(dev
, "remove successful\n");
1102 pm_runtime_disable(&pdev
->dev
);
1104 mixer_resources_cleanup(ctx
);
1109 #ifdef CONFIG_PM_SLEEP
1110 static int mixer_suspend(struct device
*dev
)
1112 struct exynos_drm_hdmi_context
*drm_hdmi_ctx
= get_mixer_context(dev
);
1113 struct mixer_context
*ctx
= drm_hdmi_ctx
->ctx
;
1115 mixer_poweroff(ctx
);
1121 static SIMPLE_DEV_PM_OPS(mixer_pm_ops
, mixer_suspend
, NULL
);
1123 struct platform_driver mixer_driver
= {
1125 .name
= "s5p-mixer",
1126 .owner
= THIS_MODULE
,
1127 .pm
= &mixer_pm_ops
,
1129 .probe
= mixer_probe
,
1130 .remove
= __devexit_p(mixer_remove
),