xref: /linux/drivers/gpu/drm/exynos/exynos_mixer.c (revision 8f949b9a7e0bac3a9c3c29dc27c476a87e21db3e)
1 /*
2  * Copyright (C) 2011 Samsung Electronics Co.Ltd
3  * Authors:
4  * Seung-Woo Kim <sw0312.kim@samsung.com>
5  *	Inki Dae <inki.dae@samsung.com>
6  *	Joonyoung Shim <jy0922.shim@samsung.com>
7  *
8  * Based on drivers/media/video/s5p-tv/mixer_reg.c
9  *
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.
14  *
15  */
16 
17 #include "drmP.h"
18 
19 #include "regs-mixer.h"
20 #include "regs-vp.h"
21 
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>
34 
35 #include <drm/exynos_drm.h>
36 
37 #include "exynos_drm_drv.h"
38 #include "exynos_drm_hdmi.h"
39 
40 #define get_mixer_context(dev)	platform_get_drvdata(to_platform_device(dev))
41 
42 struct hdmi_win_data {
43 	dma_addr_t		dma_addr;
44 	void __iomem		*vaddr;
45 	dma_addr_t		chroma_dma_addr;
46 	void __iomem		*chroma_vaddr;
47 	uint32_t		pixel_format;
48 	unsigned int		bpp;
49 	unsigned int		crtc_x;
50 	unsigned int		crtc_y;
51 	unsigned int		crtc_width;
52 	unsigned int		crtc_height;
53 	unsigned int		fb_x;
54 	unsigned int		fb_y;
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;
62 };
63 
64 struct mixer_resources {
65 	int			irq;
66 	void __iomem		*mixer_regs;
67 	void __iomem		*vp_regs;
68 	spinlock_t		reg_slock;
69 	struct clk		*mixer;
70 	struct clk		*vp;
71 	struct clk		*sclk_mixer;
72 	struct clk		*sclk_hdmi;
73 	struct clk		*sclk_dac;
74 };
75 
76 struct mixer_context {
77 	struct device		*dev;
78 	int			pipe;
79 	bool			interlace;
80 	bool			powered;
81 	u32			int_en;
82 
83 	struct mutex		mixer_mutex;
84 	struct mixer_resources	mixer_res;
85 	struct hdmi_win_data	win_data[MIXER_WIN_NR];
86 };
87 
88 static const u8 filter_y_horiz_tap8[] = {
89 	0,	-1,	-1,	-1,	-1,	-1,	-1,	-1,
90 	-1,	-1,	-1,	-1,	-1,	0,	0,	0,
91 	0,	2,	4,	5,	6,	6,	6,	6,
92 	6,	5,	5,	4,	3,	2,	1,	1,
93 	0,	-6,	-12,	-16,	-18,	-20,	-21,	-20,
94 	-20,	-18,	-16,	-13,	-10,	-8,	-5,	-2,
95 	127,	126,	125,	121,	114,	107,	99,	89,
96 	79,	68,	57,	46,	35,	25,	16,	8,
97 };
98 
99 static const u8 filter_y_vert_tap4[] = {
100 	0,	-3,	-6,	-8,	-8,	-8,	-8,	-7,
101 	-6,	-5,	-4,	-3,	-2,	-1,	-1,	0,
102 	127,	126,	124,	118,	111,	102,	92,	81,
103 	70,	59,	48,	37,	27,	19,	11,	5,
104 	0,	5,	11,	19,	27,	37,	48,	59,
105 	70,	81,	92,	102,	111,	118,	124,	126,
106 	0,	0,	-1,	-1,	-2,	-3,	-4,	-5,
107 	-6,	-7,	-8,	-8,	-8,	-8,	-6,	-3,
108 };
109 
110 static const u8 filter_cr_horiz_tap4[] = {
111 	0,	-3,	-6,	-8,	-8,	-8,	-8,	-7,
112 	-6,	-5,	-4,	-3,	-2,	-1,	-1,	0,
113 	127,	126,	124,	118,	111,	102,	92,	81,
114 	70,	59,	48,	37,	27,	19,	11,	5,
115 };
116 
117 static inline u32 vp_reg_read(struct mixer_resources *res, u32 reg_id)
118 {
119 	return readl(res->vp_regs + reg_id);
120 }
121 
122 static inline void vp_reg_write(struct mixer_resources *res, u32 reg_id,
123 				 u32 val)
124 {
125 	writel(val, res->vp_regs + reg_id);
126 }
127 
128 static inline void vp_reg_writemask(struct mixer_resources *res, u32 reg_id,
129 				 u32 val, u32 mask)
130 {
131 	u32 old = vp_reg_read(res, reg_id);
132 
133 	val = (val & mask) | (old & ~mask);
134 	writel(val, res->vp_regs + reg_id);
135 }
136 
137 static inline u32 mixer_reg_read(struct mixer_resources *res, u32 reg_id)
138 {
139 	return readl(res->mixer_regs + reg_id);
140 }
141 
142 static inline void mixer_reg_write(struct mixer_resources *res, u32 reg_id,
143 				 u32 val)
144 {
145 	writel(val, res->mixer_regs + reg_id);
146 }
147 
148 static inline void mixer_reg_writemask(struct mixer_resources *res,
149 				 u32 reg_id, u32 val, u32 mask)
150 {
151 	u32 old = mixer_reg_read(res, reg_id);
152 
153 	val = (val & mask) | (old & ~mask);
154 	writel(val, res->mixer_regs + reg_id);
155 }
156 
157 static void mixer_regs_dump(struct mixer_context *ctx)
158 {
159 #define DUMPREG(reg_id) \
160 do { \
161 	DRM_DEBUG_KMS(#reg_id " = %08x\n", \
162 		(u32)readl(ctx->mixer_res.mixer_regs + reg_id)); \
163 } while (0)
164 
165 	DUMPREG(MXR_STATUS);
166 	DUMPREG(MXR_CFG);
167 	DUMPREG(MXR_INT_EN);
168 	DUMPREG(MXR_INT_STATUS);
169 
170 	DUMPREG(MXR_LAYER_CFG);
171 	DUMPREG(MXR_VIDEO_CFG);
172 
173 	DUMPREG(MXR_GRAPHIC0_CFG);
174 	DUMPREG(MXR_GRAPHIC0_BASE);
175 	DUMPREG(MXR_GRAPHIC0_SPAN);
176 	DUMPREG(MXR_GRAPHIC0_WH);
177 	DUMPREG(MXR_GRAPHIC0_SXY);
178 	DUMPREG(MXR_GRAPHIC0_DXY);
179 
180 	DUMPREG(MXR_GRAPHIC1_CFG);
181 	DUMPREG(MXR_GRAPHIC1_BASE);
182 	DUMPREG(MXR_GRAPHIC1_SPAN);
183 	DUMPREG(MXR_GRAPHIC1_WH);
184 	DUMPREG(MXR_GRAPHIC1_SXY);
185 	DUMPREG(MXR_GRAPHIC1_DXY);
186 #undef DUMPREG
187 }
188 
189 static void vp_regs_dump(struct mixer_context *ctx)
190 {
191 #define DUMPREG(reg_id) \
192 do { \
193 	DRM_DEBUG_KMS(#reg_id " = %08x\n", \
194 		(u32) readl(ctx->mixer_res.vp_regs + reg_id)); \
195 } while (0)
196 
197 	DUMPREG(VP_ENABLE);
198 	DUMPREG(VP_SRESET);
199 	DUMPREG(VP_SHADOW_UPDATE);
200 	DUMPREG(VP_FIELD_ID);
201 	DUMPREG(VP_MODE);
202 	DUMPREG(VP_IMG_SIZE_Y);
203 	DUMPREG(VP_IMG_SIZE_C);
204 	DUMPREG(VP_PER_RATE_CTRL);
205 	DUMPREG(VP_TOP_Y_PTR);
206 	DUMPREG(VP_BOT_Y_PTR);
207 	DUMPREG(VP_TOP_C_PTR);
208 	DUMPREG(VP_BOT_C_PTR);
209 	DUMPREG(VP_ENDIAN_MODE);
210 	DUMPREG(VP_SRC_H_POSITION);
211 	DUMPREG(VP_SRC_V_POSITION);
212 	DUMPREG(VP_SRC_WIDTH);
213 	DUMPREG(VP_SRC_HEIGHT);
214 	DUMPREG(VP_DST_H_POSITION);
215 	DUMPREG(VP_DST_V_POSITION);
216 	DUMPREG(VP_DST_WIDTH);
217 	DUMPREG(VP_DST_HEIGHT);
218 	DUMPREG(VP_H_RATIO);
219 	DUMPREG(VP_V_RATIO);
220 
221 #undef DUMPREG
222 }
223 
224 static inline void vp_filter_set(struct mixer_resources *res,
225 		int reg_id, const u8 *data, unsigned int size)
226 {
227 	/* assure 4-byte align */
228 	BUG_ON(size & 3);
229 	for (; size; size -= 4, reg_id += 4, data += 4) {
230 		u32 val = (data[0] << 24) |  (data[1] << 16) |
231 			(data[2] << 8) | data[3];
232 		vp_reg_write(res, reg_id, val);
233 	}
234 }
235 
236 static void vp_default_filter(struct mixer_resources *res)
237 {
238 	vp_filter_set(res, VP_POLY8_Y0_LL,
239 		filter_y_horiz_tap8, sizeof(filter_y_horiz_tap8));
240 	vp_filter_set(res, VP_POLY4_Y0_LL,
241 		filter_y_vert_tap4, sizeof(filter_y_vert_tap4));
242 	vp_filter_set(res, VP_POLY4_C0_LL,
243 		filter_cr_horiz_tap4, sizeof(filter_cr_horiz_tap4));
244 }
245 
246 static void mixer_vsync_set_update(struct mixer_context *ctx, bool enable)
247 {
248 	struct mixer_resources *res = &ctx->mixer_res;
249 
250 	/* block update on vsync */
251 	mixer_reg_writemask(res, MXR_STATUS, enable ?
252 			MXR_STATUS_SYNC_ENABLE : 0, MXR_STATUS_SYNC_ENABLE);
253 
254 	vp_reg_write(res, VP_SHADOW_UPDATE, enable ?
255 			VP_SHADOW_UPDATE_ENABLE : 0);
256 }
257 
258 static void mixer_cfg_scan(struct mixer_context *ctx, unsigned int height)
259 {
260 	struct mixer_resources *res = &ctx->mixer_res;
261 	u32 val;
262 
263 	/* choosing between interlace and progressive mode */
264 	val = (ctx->interlace ? MXR_CFG_SCAN_INTERLACE :
265 				MXR_CFG_SCAN_PROGRASSIVE);
266 
267 	/* choosing between porper HD and SD mode */
268 	if (height == 480)
269 		val |= MXR_CFG_SCAN_NTSC | MXR_CFG_SCAN_SD;
270 	else if (height == 576)
271 		val |= MXR_CFG_SCAN_PAL | MXR_CFG_SCAN_SD;
272 	else if (height == 720)
273 		val |= MXR_CFG_SCAN_HD_720 | MXR_CFG_SCAN_HD;
274 	else if (height == 1080)
275 		val |= MXR_CFG_SCAN_HD_1080 | MXR_CFG_SCAN_HD;
276 	else
277 		val |= MXR_CFG_SCAN_HD_720 | MXR_CFG_SCAN_HD;
278 
279 	mixer_reg_writemask(res, MXR_CFG, val, MXR_CFG_SCAN_MASK);
280 }
281 
282 static void mixer_cfg_rgb_fmt(struct mixer_context *ctx, unsigned int height)
283 {
284 	struct mixer_resources *res = &ctx->mixer_res;
285 	u32 val;
286 
287 	if (height == 480) {
288 		val = MXR_CFG_RGB601_0_255;
289 	} else if (height == 576) {
290 		val = MXR_CFG_RGB601_0_255;
291 	} else if (height == 720) {
292 		val = MXR_CFG_RGB709_16_235;
293 		mixer_reg_write(res, MXR_CM_COEFF_Y,
294 				(1 << 30) | (94 << 20) | (314 << 10) |
295 				(32 << 0));
296 		mixer_reg_write(res, MXR_CM_COEFF_CB,
297 				(972 << 20) | (851 << 10) | (225 << 0));
298 		mixer_reg_write(res, MXR_CM_COEFF_CR,
299 				(225 << 20) | (820 << 10) | (1004 << 0));
300 	} else if (height == 1080) {
301 		val = MXR_CFG_RGB709_16_235;
302 		mixer_reg_write(res, MXR_CM_COEFF_Y,
303 				(1 << 30) | (94 << 20) | (314 << 10) |
304 				(32 << 0));
305 		mixer_reg_write(res, MXR_CM_COEFF_CB,
306 				(972 << 20) | (851 << 10) | (225 << 0));
307 		mixer_reg_write(res, MXR_CM_COEFF_CR,
308 				(225 << 20) | (820 << 10) | (1004 << 0));
309 	} else {
310 		val = MXR_CFG_RGB709_16_235;
311 		mixer_reg_write(res, MXR_CM_COEFF_Y,
312 				(1 << 30) | (94 << 20) | (314 << 10) |
313 				(32 << 0));
314 		mixer_reg_write(res, MXR_CM_COEFF_CB,
315 				(972 << 20) | (851 << 10) | (225 << 0));
316 		mixer_reg_write(res, MXR_CM_COEFF_CR,
317 				(225 << 20) | (820 << 10) | (1004 << 0));
318 	}
319 
320 	mixer_reg_writemask(res, MXR_CFG, val, MXR_CFG_RGB_FMT_MASK);
321 }
322 
323 static void mixer_cfg_layer(struct mixer_context *ctx, int win, bool enable)
324 {
325 	struct mixer_resources *res = &ctx->mixer_res;
326 	u32 val = enable ? ~0 : 0;
327 
328 	switch (win) {
329 	case 0:
330 		mixer_reg_writemask(res, MXR_CFG, val, MXR_CFG_GRP0_ENABLE);
331 		break;
332 	case 1:
333 		mixer_reg_writemask(res, MXR_CFG, val, MXR_CFG_GRP1_ENABLE);
334 		break;
335 	case 2:
336 		vp_reg_writemask(res, VP_ENABLE, val, VP_ENABLE_ON);
337 		mixer_reg_writemask(res, MXR_CFG, val, MXR_CFG_VP_ENABLE);
338 		break;
339 	}
340 }
341 
342 static void mixer_run(struct mixer_context *ctx)
343 {
344 	struct mixer_resources *res = &ctx->mixer_res;
345 
346 	mixer_reg_writemask(res, MXR_STATUS, ~0, MXR_STATUS_REG_RUN);
347 
348 	mixer_regs_dump(ctx);
349 }
350 
351 static void vp_video_buffer(struct mixer_context *ctx, int win)
352 {
353 	struct mixer_resources *res = &ctx->mixer_res;
354 	unsigned long flags;
355 	struct hdmi_win_data *win_data;
356 	unsigned int x_ratio, y_ratio;
357 	unsigned int buf_num;
358 	dma_addr_t luma_addr[2], chroma_addr[2];
359 	bool tiled_mode = false;
360 	bool crcb_mode = false;
361 	u32 val;
362 
363 	win_data = &ctx->win_data[win];
364 
365 	switch (win_data->pixel_format) {
366 	case DRM_FORMAT_NV12MT:
367 		tiled_mode = true;
368 	case DRM_FORMAT_NV12:
369 		crcb_mode = false;
370 		buf_num = 2;
371 		break;
372 	/* TODO: single buffer format NV12, NV21 */
373 	default:
374 		/* ignore pixel format at disable time */
375 		if (!win_data->dma_addr)
376 			break;
377 
378 		DRM_ERROR("pixel format for vp is wrong [%d].\n",
379 				win_data->pixel_format);
380 		return;
381 	}
382 
383 	/* scaling feature: (src << 16) / dst */
384 	x_ratio = (win_data->src_width << 16) / win_data->crtc_width;
385 	y_ratio = (win_data->src_height << 16) / win_data->crtc_height;
386 
387 	if (buf_num == 2) {
388 		luma_addr[0] = win_data->dma_addr;
389 		chroma_addr[0] = win_data->chroma_dma_addr;
390 	} else {
391 		luma_addr[0] = win_data->dma_addr;
392 		chroma_addr[0] = win_data->dma_addr
393 			+ (win_data->fb_width * win_data->fb_height);
394 	}
395 
396 	if (win_data->scan_flags & DRM_MODE_FLAG_INTERLACE) {
397 		ctx->interlace = true;
398 		if (tiled_mode) {
399 			luma_addr[1] = luma_addr[0] + 0x40;
400 			chroma_addr[1] = chroma_addr[0] + 0x40;
401 		} else {
402 			luma_addr[1] = luma_addr[0] + win_data->fb_width;
403 			chroma_addr[1] = chroma_addr[0] + win_data->fb_width;
404 		}
405 	} else {
406 		ctx->interlace = false;
407 		luma_addr[1] = 0;
408 		chroma_addr[1] = 0;
409 	}
410 
411 	spin_lock_irqsave(&res->reg_slock, flags);
412 	mixer_vsync_set_update(ctx, false);
413 
414 	/* interlace or progressive scan mode */
415 	val = (ctx->interlace ? ~0 : 0);
416 	vp_reg_writemask(res, VP_MODE, val, VP_MODE_LINE_SKIP);
417 
418 	/* setup format */
419 	val = (crcb_mode ? VP_MODE_NV21 : VP_MODE_NV12);
420 	val |= (tiled_mode ? VP_MODE_MEM_TILED : VP_MODE_MEM_LINEAR);
421 	vp_reg_writemask(res, VP_MODE, val, VP_MODE_FMT_MASK);
422 
423 	/* setting size of input image */
424 	vp_reg_write(res, VP_IMG_SIZE_Y, VP_IMG_HSIZE(win_data->fb_width) |
425 		VP_IMG_VSIZE(win_data->fb_height));
426 	/* chroma height has to reduced by 2 to avoid chroma distorions */
427 	vp_reg_write(res, VP_IMG_SIZE_C, VP_IMG_HSIZE(win_data->fb_width) |
428 		VP_IMG_VSIZE(win_data->fb_height / 2));
429 
430 	vp_reg_write(res, VP_SRC_WIDTH, win_data->src_width);
431 	vp_reg_write(res, VP_SRC_HEIGHT, win_data->src_height);
432 	vp_reg_write(res, VP_SRC_H_POSITION,
433 			VP_SRC_H_POSITION_VAL(win_data->fb_x));
434 	vp_reg_write(res, VP_SRC_V_POSITION, win_data->fb_y);
435 
436 	vp_reg_write(res, VP_DST_WIDTH, win_data->crtc_width);
437 	vp_reg_write(res, VP_DST_H_POSITION, win_data->crtc_x);
438 	if (ctx->interlace) {
439 		vp_reg_write(res, VP_DST_HEIGHT, win_data->crtc_height / 2);
440 		vp_reg_write(res, VP_DST_V_POSITION, win_data->crtc_y / 2);
441 	} else {
442 		vp_reg_write(res, VP_DST_HEIGHT, win_data->crtc_height);
443 		vp_reg_write(res, VP_DST_V_POSITION, win_data->crtc_y);
444 	}
445 
446 	vp_reg_write(res, VP_H_RATIO, x_ratio);
447 	vp_reg_write(res, VP_V_RATIO, y_ratio);
448 
449 	vp_reg_write(res, VP_ENDIAN_MODE, VP_ENDIAN_MODE_LITTLE);
450 
451 	/* set buffer address to vp */
452 	vp_reg_write(res, VP_TOP_Y_PTR, luma_addr[0]);
453 	vp_reg_write(res, VP_BOT_Y_PTR, luma_addr[1]);
454 	vp_reg_write(res, VP_TOP_C_PTR, chroma_addr[0]);
455 	vp_reg_write(res, VP_BOT_C_PTR, chroma_addr[1]);
456 
457 	mixer_cfg_scan(ctx, win_data->mode_height);
458 	mixer_cfg_rgb_fmt(ctx, win_data->mode_height);
459 	mixer_cfg_layer(ctx, win, true);
460 	mixer_run(ctx);
461 
462 	mixer_vsync_set_update(ctx, true);
463 	spin_unlock_irqrestore(&res->reg_slock, flags);
464 
465 	vp_regs_dump(ctx);
466 }
467 
468 static void mixer_graph_buffer(struct mixer_context *ctx, int win)
469 {
470 	struct mixer_resources *res = &ctx->mixer_res;
471 	unsigned long flags;
472 	struct hdmi_win_data *win_data;
473 	unsigned int x_ratio, y_ratio;
474 	unsigned int src_x_offset, src_y_offset, dst_x_offset, dst_y_offset;
475 	dma_addr_t dma_addr;
476 	unsigned int fmt;
477 	u32 val;
478 
479 	win_data = &ctx->win_data[win];
480 
481 	#define RGB565 4
482 	#define ARGB1555 5
483 	#define ARGB4444 6
484 	#define ARGB8888 7
485 
486 	switch (win_data->bpp) {
487 	case 16:
488 		fmt = ARGB4444;
489 		break;
490 	case 32:
491 		fmt = ARGB8888;
492 		break;
493 	default:
494 		fmt = ARGB8888;
495 	}
496 
497 	/* 2x scaling feature */
498 	x_ratio = 0;
499 	y_ratio = 0;
500 
501 	dst_x_offset = win_data->crtc_x;
502 	dst_y_offset = win_data->crtc_y;
503 
504 	/* converting dma address base and source offset */
505 	dma_addr = win_data->dma_addr
506 		+ (win_data->fb_x * win_data->bpp >> 3)
507 		+ (win_data->fb_y * win_data->fb_width * win_data->bpp >> 3);
508 	src_x_offset = 0;
509 	src_y_offset = 0;
510 
511 	if (win_data->scan_flags & DRM_MODE_FLAG_INTERLACE)
512 		ctx->interlace = true;
513 	else
514 		ctx->interlace = false;
515 
516 	spin_lock_irqsave(&res->reg_slock, flags);
517 	mixer_vsync_set_update(ctx, false);
518 
519 	/* setup format */
520 	mixer_reg_writemask(res, MXR_GRAPHIC_CFG(win),
521 		MXR_GRP_CFG_FORMAT_VAL(fmt), MXR_GRP_CFG_FORMAT_MASK);
522 
523 	/* setup geometry */
524 	mixer_reg_write(res, MXR_GRAPHIC_SPAN(win), win_data->fb_width);
525 
526 	val  = MXR_GRP_WH_WIDTH(win_data->crtc_width);
527 	val |= MXR_GRP_WH_HEIGHT(win_data->crtc_height);
528 	val |= MXR_GRP_WH_H_SCALE(x_ratio);
529 	val |= MXR_GRP_WH_V_SCALE(y_ratio);
530 	mixer_reg_write(res, MXR_GRAPHIC_WH(win), val);
531 
532 	/* setup offsets in source image */
533 	val  = MXR_GRP_SXY_SX(src_x_offset);
534 	val |= MXR_GRP_SXY_SY(src_y_offset);
535 	mixer_reg_write(res, MXR_GRAPHIC_SXY(win), val);
536 
537 	/* setup offsets in display image */
538 	val  = MXR_GRP_DXY_DX(dst_x_offset);
539 	val |= MXR_GRP_DXY_DY(dst_y_offset);
540 	mixer_reg_write(res, MXR_GRAPHIC_DXY(win), val);
541 
542 	/* set buffer address to mixer */
543 	mixer_reg_write(res, MXR_GRAPHIC_BASE(win), dma_addr);
544 
545 	mixer_cfg_scan(ctx, win_data->mode_height);
546 	mixer_cfg_rgb_fmt(ctx, win_data->mode_height);
547 	mixer_cfg_layer(ctx, win, true);
548 	mixer_run(ctx);
549 
550 	mixer_vsync_set_update(ctx, true);
551 	spin_unlock_irqrestore(&res->reg_slock, flags);
552 }
553 
554 static void vp_win_reset(struct mixer_context *ctx)
555 {
556 	struct mixer_resources *res = &ctx->mixer_res;
557 	int tries = 100;
558 
559 	vp_reg_write(res, VP_SRESET, VP_SRESET_PROCESSING);
560 	for (tries = 100; tries; --tries) {
561 		/* waiting until VP_SRESET_PROCESSING is 0 */
562 		if (~vp_reg_read(res, VP_SRESET) & VP_SRESET_PROCESSING)
563 			break;
564 		mdelay(10);
565 	}
566 	WARN(tries == 0, "failed to reset Video Processor\n");
567 }
568 
569 static void mixer_win_reset(struct mixer_context *ctx)
570 {
571 	struct mixer_resources *res = &ctx->mixer_res;
572 	unsigned long flags;
573 	u32 val; /* value stored to register */
574 
575 	spin_lock_irqsave(&res->reg_slock, flags);
576 	mixer_vsync_set_update(ctx, false);
577 
578 	mixer_reg_writemask(res, MXR_CFG, MXR_CFG_DST_HDMI, MXR_CFG_DST_MASK);
579 
580 	/* set output in RGB888 mode */
581 	mixer_reg_writemask(res, MXR_CFG, MXR_CFG_OUT_RGB888, MXR_CFG_OUT_MASK);
582 
583 	/* 16 beat burst in DMA */
584 	mixer_reg_writemask(res, MXR_STATUS, MXR_STATUS_16_BURST,
585 		MXR_STATUS_BURST_MASK);
586 
587 	/* setting default layer priority: layer1 > layer0 > video
588 	 * because typical usage scenario would be
589 	 * layer1 - OSD
590 	 * layer0 - framebuffer
591 	 * video - video overlay
592 	 */
593 	val = MXR_LAYER_CFG_GRP1_VAL(3);
594 	val |= MXR_LAYER_CFG_GRP0_VAL(2);
595 	val |= MXR_LAYER_CFG_VP_VAL(1);
596 	mixer_reg_write(res, MXR_LAYER_CFG, val);
597 
598 	/* setting background color */
599 	mixer_reg_write(res, MXR_BG_COLOR0, 0x008080);
600 	mixer_reg_write(res, MXR_BG_COLOR1, 0x008080);
601 	mixer_reg_write(res, MXR_BG_COLOR2, 0x008080);
602 
603 	/* setting graphical layers */
604 	val  = MXR_GRP_CFG_COLOR_KEY_DISABLE; /* no blank key */
605 	val |= MXR_GRP_CFG_WIN_BLEND_EN;
606 	val |= MXR_GRP_CFG_BLEND_PRE_MUL;
607 	val |= MXR_GRP_CFG_PIXEL_BLEND_EN;
608 	val |= MXR_GRP_CFG_ALPHA_VAL(0xff); /* non-transparent alpha */
609 
610 	/* the same configuration for both layers */
611 	mixer_reg_write(res, MXR_GRAPHIC_CFG(0), val);
612 	mixer_reg_write(res, MXR_GRAPHIC_CFG(1), val);
613 
614 	/* setting video layers */
615 	val = MXR_GRP_CFG_ALPHA_VAL(0);
616 	mixer_reg_write(res, MXR_VIDEO_CFG, val);
617 
618 	/* configuration of Video Processor Registers */
619 	vp_win_reset(ctx);
620 	vp_default_filter(res);
621 
622 	/* disable all layers */
623 	mixer_reg_writemask(res, MXR_CFG, 0, MXR_CFG_GRP0_ENABLE);
624 	mixer_reg_writemask(res, MXR_CFG, 0, MXR_CFG_GRP1_ENABLE);
625 	mixer_reg_writemask(res, MXR_CFG, 0, MXR_CFG_VP_ENABLE);
626 
627 	mixer_vsync_set_update(ctx, true);
628 	spin_unlock_irqrestore(&res->reg_slock, flags);
629 }
630 
631 static void mixer_poweron(struct mixer_context *ctx)
632 {
633 	struct mixer_resources *res = &ctx->mixer_res;
634 
635 	DRM_DEBUG_KMS("[%d] %s\n", __LINE__, __func__);
636 
637 	mutex_lock(&ctx->mixer_mutex);
638 	if (ctx->powered) {
639 		mutex_unlock(&ctx->mixer_mutex);
640 		return;
641 	}
642 	ctx->powered = true;
643 	mutex_unlock(&ctx->mixer_mutex);
644 
645 	pm_runtime_get_sync(ctx->dev);
646 
647 	clk_enable(res->mixer);
648 	clk_enable(res->vp);
649 	clk_enable(res->sclk_mixer);
650 
651 	mixer_reg_write(res, MXR_INT_EN, ctx->int_en);
652 	mixer_win_reset(ctx);
653 }
654 
655 static void mixer_poweroff(struct mixer_context *ctx)
656 {
657 	struct mixer_resources *res = &ctx->mixer_res;
658 
659 	DRM_DEBUG_KMS("[%d] %s\n", __LINE__, __func__);
660 
661 	mutex_lock(&ctx->mixer_mutex);
662 	if (!ctx->powered)
663 		goto out;
664 	mutex_unlock(&ctx->mixer_mutex);
665 
666 	ctx->int_en = mixer_reg_read(res, MXR_INT_EN);
667 
668 	clk_disable(res->mixer);
669 	clk_disable(res->vp);
670 	clk_disable(res->sclk_mixer);
671 
672 	pm_runtime_put_sync(ctx->dev);
673 
674 	mutex_lock(&ctx->mixer_mutex);
675 	ctx->powered = false;
676 
677 out:
678 	mutex_unlock(&ctx->mixer_mutex);
679 }
680 
681 static int mixer_enable_vblank(void *ctx, int pipe)
682 {
683 	struct mixer_context *mixer_ctx = ctx;
684 	struct mixer_resources *res = &mixer_ctx->mixer_res;
685 
686 	DRM_DEBUG_KMS("[%d] %s\n", __LINE__, __func__);
687 
688 	mixer_ctx->pipe = pipe;
689 
690 	/* enable vsync interrupt */
691 	mixer_reg_writemask(res, MXR_INT_EN, MXR_INT_EN_VSYNC,
692 			MXR_INT_EN_VSYNC);
693 
694 	return 0;
695 }
696 
697 static void mixer_disable_vblank(void *ctx)
698 {
699 	struct mixer_context *mixer_ctx = ctx;
700 	struct mixer_resources *res = &mixer_ctx->mixer_res;
701 
702 	DRM_DEBUG_KMS("[%d] %s\n", __LINE__, __func__);
703 
704 	/* disable vsync interrupt */
705 	mixer_reg_writemask(res, MXR_INT_EN, 0, MXR_INT_EN_VSYNC);
706 }
707 
708 static void mixer_dpms(void *ctx, int mode)
709 {
710 	struct mixer_context *mixer_ctx = ctx;
711 
712 	DRM_DEBUG_KMS("[%d] %s\n", __LINE__, __func__);
713 
714 	switch (mode) {
715 	case DRM_MODE_DPMS_ON:
716 		mixer_poweron(mixer_ctx);
717 		break;
718 	case DRM_MODE_DPMS_STANDBY:
719 	case DRM_MODE_DPMS_SUSPEND:
720 	case DRM_MODE_DPMS_OFF:
721 		mixer_poweroff(mixer_ctx);
722 		break;
723 	default:
724 		DRM_DEBUG_KMS("unknown dpms mode: %d\n", mode);
725 		break;
726 	}
727 }
728 
729 static void mixer_win_mode_set(void *ctx,
730 			      struct exynos_drm_overlay *overlay)
731 {
732 	struct mixer_context *mixer_ctx = ctx;
733 	struct hdmi_win_data *win_data;
734 	int win;
735 
736 	DRM_DEBUG_KMS("[%d] %s\n", __LINE__, __func__);
737 
738 	if (!overlay) {
739 		DRM_ERROR("overlay is NULL\n");
740 		return;
741 	}
742 
743 	DRM_DEBUG_KMS("set [%d]x[%d] at (%d,%d) to [%d]x[%d] at (%d,%d)\n",
744 				 overlay->fb_width, overlay->fb_height,
745 				 overlay->fb_x, overlay->fb_y,
746 				 overlay->crtc_width, overlay->crtc_height,
747 				 overlay->crtc_x, overlay->crtc_y);
748 
749 	win = overlay->zpos;
750 	if (win == DEFAULT_ZPOS)
751 		win = MIXER_DEFAULT_WIN;
752 
753 	if (win < 0 || win > MIXER_WIN_NR) {
754 		DRM_ERROR("mixer window[%d] is wrong\n", win);
755 		return;
756 	}
757 
758 	win_data = &mixer_ctx->win_data[win];
759 
760 	win_data->dma_addr = overlay->dma_addr[0];
761 	win_data->vaddr = overlay->vaddr[0];
762 	win_data->chroma_dma_addr = overlay->dma_addr[1];
763 	win_data->chroma_vaddr = overlay->vaddr[1];
764 	win_data->pixel_format = overlay->pixel_format;
765 	win_data->bpp = overlay->bpp;
766 
767 	win_data->crtc_x = overlay->crtc_x;
768 	win_data->crtc_y = overlay->crtc_y;
769 	win_data->crtc_width = overlay->crtc_width;
770 	win_data->crtc_height = overlay->crtc_height;
771 
772 	win_data->fb_x = overlay->fb_x;
773 	win_data->fb_y = overlay->fb_y;
774 	win_data->fb_width = overlay->fb_width;
775 	win_data->fb_height = overlay->fb_height;
776 	win_data->src_width = overlay->src_width;
777 	win_data->src_height = overlay->src_height;
778 
779 	win_data->mode_width = overlay->mode_width;
780 	win_data->mode_height = overlay->mode_height;
781 
782 	win_data->scan_flags = overlay->scan_flag;
783 }
784 
785 static void mixer_win_commit(void *ctx, int win)
786 {
787 	struct mixer_context *mixer_ctx = ctx;
788 
789 	DRM_DEBUG_KMS("[%d] %s, win: %d\n", __LINE__, __func__, win);
790 
791 	if (win > 1)
792 		vp_video_buffer(mixer_ctx, win);
793 	else
794 		mixer_graph_buffer(mixer_ctx, win);
795 }
796 
797 static void mixer_win_disable(void *ctx, int win)
798 {
799 	struct mixer_context *mixer_ctx = ctx;
800 	struct mixer_resources *res = &mixer_ctx->mixer_res;
801 	unsigned long flags;
802 
803 	DRM_DEBUG_KMS("[%d] %s, win: %d\n", __LINE__, __func__, win);
804 
805 	spin_lock_irqsave(&res->reg_slock, flags);
806 	mixer_vsync_set_update(mixer_ctx, false);
807 
808 	mixer_cfg_layer(mixer_ctx, win, false);
809 
810 	mixer_vsync_set_update(mixer_ctx, true);
811 	spin_unlock_irqrestore(&res->reg_slock, flags);
812 }
813 
814 static struct exynos_mixer_ops mixer_ops = {
815 	/* manager */
816 	.enable_vblank		= mixer_enable_vblank,
817 	.disable_vblank		= mixer_disable_vblank,
818 	.dpms			= mixer_dpms,
819 
820 	/* overlay */
821 	.win_mode_set		= mixer_win_mode_set,
822 	.win_commit		= mixer_win_commit,
823 	.win_disable		= mixer_win_disable,
824 };
825 
826 /* for pageflip event */
827 static void mixer_finish_pageflip(struct drm_device *drm_dev, int crtc)
828 {
829 	struct exynos_drm_private *dev_priv = drm_dev->dev_private;
830 	struct drm_pending_vblank_event *e, *t;
831 	struct timeval now;
832 	unsigned long flags;
833 	bool is_checked = false;
834 
835 	spin_lock_irqsave(&drm_dev->event_lock, flags);
836 
837 	list_for_each_entry_safe(e, t, &dev_priv->pageflip_event_list,
838 			base.link) {
839 		/* if event's pipe isn't same as crtc then ignore it. */
840 		if (crtc != e->pipe)
841 			continue;
842 
843 		is_checked = true;
844 		do_gettimeofday(&now);
845 		e->event.sequence = 0;
846 		e->event.tv_sec = now.tv_sec;
847 		e->event.tv_usec = now.tv_usec;
848 
849 		list_move_tail(&e->base.link, &e->base.file_priv->event_list);
850 		wake_up_interruptible(&e->base.file_priv->event_wait);
851 	}
852 
853 	if (is_checked)
854 		/*
855 		 * call drm_vblank_put only in case that drm_vblank_get was
856 		 * called.
857 		 */
858 		if (atomic_read(&drm_dev->vblank_refcount[crtc]) > 0)
859 			drm_vblank_put(drm_dev, crtc);
860 
861 	spin_unlock_irqrestore(&drm_dev->event_lock, flags);
862 }
863 
864 static irqreturn_t mixer_irq_handler(int irq, void *arg)
865 {
866 	struct exynos_drm_hdmi_context *drm_hdmi_ctx = arg;
867 	struct mixer_context *ctx = drm_hdmi_ctx->ctx;
868 	struct mixer_resources *res = &ctx->mixer_res;
869 	u32 val, base, shadow;
870 
871 	spin_lock(&res->reg_slock);
872 
873 	/* read interrupt status for handling and clearing flags for VSYNC */
874 	val = mixer_reg_read(res, MXR_INT_STATUS);
875 
876 	/* handling VSYNC */
877 	if (val & MXR_INT_STATUS_VSYNC) {
878 		/* interlace scan need to check shadow register */
879 		if (ctx->interlace) {
880 			base = mixer_reg_read(res, MXR_GRAPHIC_BASE(0));
881 			shadow = mixer_reg_read(res, MXR_GRAPHIC_BASE_S(0));
882 			if (base != shadow)
883 				goto out;
884 
885 			base = mixer_reg_read(res, MXR_GRAPHIC_BASE(1));
886 			shadow = mixer_reg_read(res, MXR_GRAPHIC_BASE_S(1));
887 			if (base != shadow)
888 				goto out;
889 		}
890 
891 		drm_handle_vblank(drm_hdmi_ctx->drm_dev, ctx->pipe);
892 		mixer_finish_pageflip(drm_hdmi_ctx->drm_dev, ctx->pipe);
893 	}
894 
895 out:
896 	/* clear interrupts */
897 	if (~val & MXR_INT_EN_VSYNC) {
898 		/* vsync interrupt use different bit for read and clear */
899 		val &= ~MXR_INT_EN_VSYNC;
900 		val |= MXR_INT_CLEAR_VSYNC;
901 	}
902 	mixer_reg_write(res, MXR_INT_STATUS, val);
903 
904 	spin_unlock(&res->reg_slock);
905 
906 	return IRQ_HANDLED;
907 }
908 
909 static int __devinit mixer_resources_init(struct exynos_drm_hdmi_context *ctx,
910 				 struct platform_device *pdev)
911 {
912 	struct mixer_context *mixer_ctx = ctx->ctx;
913 	struct device *dev = &pdev->dev;
914 	struct mixer_resources *mixer_res = &mixer_ctx->mixer_res;
915 	struct resource *res;
916 	int ret;
917 
918 	spin_lock_init(&mixer_res->reg_slock);
919 
920 	mixer_res->mixer = clk_get(dev, "mixer");
921 	if (IS_ERR_OR_NULL(mixer_res->mixer)) {
922 		dev_err(dev, "failed to get clock 'mixer'\n");
923 		ret = -ENODEV;
924 		goto fail;
925 	}
926 	mixer_res->vp = clk_get(dev, "vp");
927 	if (IS_ERR_OR_NULL(mixer_res->vp)) {
928 		dev_err(dev, "failed to get clock 'vp'\n");
929 		ret = -ENODEV;
930 		goto fail;
931 	}
932 	mixer_res->sclk_mixer = clk_get(dev, "sclk_mixer");
933 	if (IS_ERR_OR_NULL(mixer_res->sclk_mixer)) {
934 		dev_err(dev, "failed to get clock 'sclk_mixer'\n");
935 		ret = -ENODEV;
936 		goto fail;
937 	}
938 	mixer_res->sclk_hdmi = clk_get(dev, "sclk_hdmi");
939 	if (IS_ERR_OR_NULL(mixer_res->sclk_hdmi)) {
940 		dev_err(dev, "failed to get clock 'sclk_hdmi'\n");
941 		ret = -ENODEV;
942 		goto fail;
943 	}
944 	mixer_res->sclk_dac = clk_get(dev, "sclk_dac");
945 	if (IS_ERR_OR_NULL(mixer_res->sclk_dac)) {
946 		dev_err(dev, "failed to get clock 'sclk_dac'\n");
947 		ret = -ENODEV;
948 		goto fail;
949 	}
950 	res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "mxr");
951 	if (res == NULL) {
952 		dev_err(dev, "get memory resource failed.\n");
953 		ret = -ENXIO;
954 		goto fail;
955 	}
956 
957 	clk_set_parent(mixer_res->sclk_mixer, mixer_res->sclk_hdmi);
958 
959 	mixer_res->mixer_regs = devm_ioremap(&pdev->dev, res->start,
960 							resource_size(res));
961 	if (mixer_res->mixer_regs == NULL) {
962 		dev_err(dev, "register mapping failed.\n");
963 		ret = -ENXIO;
964 		goto fail;
965 	}
966 
967 	res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "vp");
968 	if (res == NULL) {
969 		dev_err(dev, "get memory resource failed.\n");
970 		ret = -ENXIO;
971 		goto fail;
972 	}
973 
974 	mixer_res->vp_regs = devm_ioremap(&pdev->dev, res->start,
975 							resource_size(res));
976 	if (mixer_res->vp_regs == NULL) {
977 		dev_err(dev, "register mapping failed.\n");
978 		ret = -ENXIO;
979 		goto fail;
980 	}
981 
982 	res = platform_get_resource_byname(pdev, IORESOURCE_IRQ, "irq");
983 	if (res == NULL) {
984 		dev_err(dev, "get interrupt resource failed.\n");
985 		ret = -ENXIO;
986 		goto fail;
987 	}
988 
989 	ret = devm_request_irq(&pdev->dev, res->start, mixer_irq_handler,
990 							0, "drm_mixer", ctx);
991 	if (ret) {
992 		dev_err(dev, "request interrupt failed.\n");
993 		goto fail;
994 	}
995 	mixer_res->irq = res->start;
996 
997 	return 0;
998 
999 fail:
1000 	if (!IS_ERR_OR_NULL(mixer_res->sclk_dac))
1001 		clk_put(mixer_res->sclk_dac);
1002 	if (!IS_ERR_OR_NULL(mixer_res->sclk_hdmi))
1003 		clk_put(mixer_res->sclk_hdmi);
1004 	if (!IS_ERR_OR_NULL(mixer_res->sclk_mixer))
1005 		clk_put(mixer_res->sclk_mixer);
1006 	if (!IS_ERR_OR_NULL(mixer_res->vp))
1007 		clk_put(mixer_res->vp);
1008 	if (!IS_ERR_OR_NULL(mixer_res->mixer))
1009 		clk_put(mixer_res->mixer);
1010 	return ret;
1011 }
1012 
1013 static int __devinit mixer_probe(struct platform_device *pdev)
1014 {
1015 	struct device *dev = &pdev->dev;
1016 	struct exynos_drm_hdmi_context *drm_hdmi_ctx;
1017 	struct mixer_context *ctx;
1018 	int ret;
1019 
1020 	dev_info(dev, "probe start\n");
1021 
1022 	drm_hdmi_ctx = devm_kzalloc(&pdev->dev, sizeof(*drm_hdmi_ctx),
1023 								GFP_KERNEL);
1024 	if (!drm_hdmi_ctx) {
1025 		DRM_ERROR("failed to allocate common hdmi context.\n");
1026 		return -ENOMEM;
1027 	}
1028 
1029 	ctx = devm_kzalloc(&pdev->dev, sizeof(*ctx), GFP_KERNEL);
1030 	if (!ctx) {
1031 		DRM_ERROR("failed to alloc mixer context.\n");
1032 		return -ENOMEM;
1033 	}
1034 
1035 	mutex_init(&ctx->mixer_mutex);
1036 
1037 	ctx->dev = &pdev->dev;
1038 	drm_hdmi_ctx->ctx = (void *)ctx;
1039 
1040 	platform_set_drvdata(pdev, drm_hdmi_ctx);
1041 
1042 	/* acquire resources: regs, irqs, clocks */
1043 	ret = mixer_resources_init(drm_hdmi_ctx, pdev);
1044 	if (ret)
1045 		goto fail;
1046 
1047 	/* register specific callback point to common hdmi. */
1048 	exynos_mixer_ops_register(&mixer_ops);
1049 
1050 	pm_runtime_enable(dev);
1051 
1052 	return 0;
1053 
1054 
1055 fail:
1056 	dev_info(dev, "probe failed\n");
1057 	return ret;
1058 }
1059 
1060 static int mixer_remove(struct platform_device *pdev)
1061 {
1062 	dev_info(&pdev->dev, "remove successful\n");
1063 
1064 	pm_runtime_disable(&pdev->dev);
1065 
1066 	return 0;
1067 }
1068 
1069 #ifdef CONFIG_PM_SLEEP
1070 static int mixer_suspend(struct device *dev)
1071 {
1072 	struct exynos_drm_hdmi_context *drm_hdmi_ctx = get_mixer_context(dev);
1073 	struct mixer_context *ctx = drm_hdmi_ctx->ctx;
1074 
1075 	mixer_poweroff(ctx);
1076 
1077 	return 0;
1078 }
1079 #endif
1080 
1081 static SIMPLE_DEV_PM_OPS(mixer_pm_ops, mixer_suspend, NULL);
1082 
1083 struct platform_driver mixer_driver = {
1084 	.driver = {
1085 		.name = "s5p-mixer",
1086 		.owner = THIS_MODULE,
1087 		.pm = &mixer_pm_ops,
1088 	},
1089 	.probe = mixer_probe,
1090 	.remove = __devexit_p(mixer_remove),
1091 };
1092