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