xref: /linux/drivers/gpu/drm/exynos/exynos_mixer.c (revision cf8fc4f10e2c5c5b6b60d6e79d61cc58afa5967d)
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		mode_width;
58 	unsigned int		mode_height;
59 	unsigned int		scan_flags;
60 };
61 
62 struct mixer_resources {
63 	int			irq;
64 	void __iomem		*mixer_regs;
65 	void __iomem		*vp_regs;
66 	spinlock_t		reg_slock;
67 	struct clk		*mixer;
68 	struct clk		*vp;
69 	struct clk		*sclk_mixer;
70 	struct clk		*sclk_hdmi;
71 	struct clk		*sclk_dac;
72 };
73 
74 struct mixer_context {
75 	struct device		*dev;
76 	int			pipe;
77 	bool			interlace;
78 	bool			powered;
79 	u32			int_en;
80 
81 	struct mutex		mixer_mutex;
82 	struct mixer_resources	mixer_res;
83 	struct hdmi_win_data	win_data[MIXER_WIN_NR];
84 };
85 
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,
95 };
96 
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,
106 };
107 
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,
113 };
114 
115 static inline u32 vp_reg_read(struct mixer_resources *res, u32 reg_id)
116 {
117 	return readl(res->vp_regs + reg_id);
118 }
119 
120 static inline void vp_reg_write(struct mixer_resources *res, u32 reg_id,
121 				 u32 val)
122 {
123 	writel(val, res->vp_regs + reg_id);
124 }
125 
126 static inline void vp_reg_writemask(struct mixer_resources *res, u32 reg_id,
127 				 u32 val, u32 mask)
128 {
129 	u32 old = vp_reg_read(res, reg_id);
130 
131 	val = (val & mask) | (old & ~mask);
132 	writel(val, res->vp_regs + reg_id);
133 }
134 
135 static inline u32 mixer_reg_read(struct mixer_resources *res, u32 reg_id)
136 {
137 	return readl(res->mixer_regs + reg_id);
138 }
139 
140 static inline void mixer_reg_write(struct mixer_resources *res, u32 reg_id,
141 				 u32 val)
142 {
143 	writel(val, res->mixer_regs + reg_id);
144 }
145 
146 static inline void mixer_reg_writemask(struct mixer_resources *res,
147 				 u32 reg_id, u32 val, u32 mask)
148 {
149 	u32 old = mixer_reg_read(res, reg_id);
150 
151 	val = (val & mask) | (old & ~mask);
152 	writel(val, res->mixer_regs + reg_id);
153 }
154 
155 static void mixer_regs_dump(struct mixer_context *ctx)
156 {
157 #define DUMPREG(reg_id) \
158 do { \
159 	DRM_DEBUG_KMS(#reg_id " = %08x\n", \
160 		(u32)readl(ctx->mixer_res.mixer_regs + reg_id)); \
161 } while (0)
162 
163 	DUMPREG(MXR_STATUS);
164 	DUMPREG(MXR_CFG);
165 	DUMPREG(MXR_INT_EN);
166 	DUMPREG(MXR_INT_STATUS);
167 
168 	DUMPREG(MXR_LAYER_CFG);
169 	DUMPREG(MXR_VIDEO_CFG);
170 
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);
177 
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);
184 #undef DUMPREG
185 }
186 
187 static void vp_regs_dump(struct mixer_context *ctx)
188 {
189 #define DUMPREG(reg_id) \
190 do { \
191 	DRM_DEBUG_KMS(#reg_id " = %08x\n", \
192 		(u32) readl(ctx->mixer_res.vp_regs + reg_id)); \
193 } while (0)
194 
195 	DUMPREG(VP_ENABLE);
196 	DUMPREG(VP_SRESET);
197 	DUMPREG(VP_SHADOW_UPDATE);
198 	DUMPREG(VP_FIELD_ID);
199 	DUMPREG(VP_MODE);
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);
216 	DUMPREG(VP_H_RATIO);
217 	DUMPREG(VP_V_RATIO);
218 
219 #undef DUMPREG
220 }
221 
222 static inline void vp_filter_set(struct mixer_resources *res,
223 		int reg_id, const u8 *data, unsigned int size)
224 {
225 	/* assure 4-byte align */
226 	BUG_ON(size & 3);
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);
231 	}
232 }
233 
234 static void vp_default_filter(struct mixer_resources *res)
235 {
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);
242 }
243 
244 static void mixer_vsync_set_update(struct mixer_context *ctx, bool enable)
245 {
246 	struct mixer_resources *res = &ctx->mixer_res;
247 
248 	/* block update on vsync */
249 	mixer_reg_writemask(res, MXR_STATUS, enable ?
250 			MXR_STATUS_SYNC_ENABLE : 0, MXR_STATUS_SYNC_ENABLE);
251 
252 	vp_reg_write(res, VP_SHADOW_UPDATE, enable ?
253 			VP_SHADOW_UPDATE_ENABLE : 0);
254 }
255 
256 static void mixer_cfg_scan(struct mixer_context *ctx, unsigned int height)
257 {
258 	struct mixer_resources *res = &ctx->mixer_res;
259 	u32 val;
260 
261 	/* choosing between interlace and progressive mode */
262 	val = (ctx->interlace ? MXR_CFG_SCAN_INTERLACE :
263 				MXR_CFG_SCAN_PROGRASSIVE);
264 
265 	/* choosing between porper HD and SD mode */
266 	if (height == 480)
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;
274 	else
275 		val |= MXR_CFG_SCAN_HD_720 | MXR_CFG_SCAN_HD;
276 
277 	mixer_reg_writemask(res, MXR_CFG, val, MXR_CFG_SCAN_MASK);
278 }
279 
280 static void mixer_cfg_rgb_fmt(struct mixer_context *ctx, unsigned int height)
281 {
282 	struct mixer_resources *res = &ctx->mixer_res;
283 	u32 val;
284 
285 	if (height == 480) {
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) |
293 				(32 << 0));
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) |
302 				(32 << 0));
303 		mixer_reg_write(res, MXR_CM_COEFF_CB,
304 				(972 << 20) | (851 << 10) | (225 << 0));
305 		mixer_reg_write(res, MXR_CM_COEFF_CR,
306 				(225 << 20) | (820 << 10) | (1004 << 0));
307 	} else {
308 		val = MXR_CFG_RGB709_16_235;
309 		mixer_reg_write(res, MXR_CM_COEFF_Y,
310 				(1 << 30) | (94 << 20) | (314 << 10) |
311 				(32 << 0));
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));
316 	}
317 
318 	mixer_reg_writemask(res, MXR_CFG, val, MXR_CFG_RGB_FMT_MASK);
319 }
320 
321 static void mixer_cfg_layer(struct mixer_context *ctx, int win, bool enable)
322 {
323 	struct mixer_resources *res = &ctx->mixer_res;
324 	u32 val = enable ? ~0 : 0;
325 
326 	switch (win) {
327 	case 0:
328 		mixer_reg_writemask(res, MXR_CFG, val, MXR_CFG_GRP0_ENABLE);
329 		break;
330 	case 1:
331 		mixer_reg_writemask(res, MXR_CFG, val, MXR_CFG_GRP1_ENABLE);
332 		break;
333 	case 2:
334 		vp_reg_writemask(res, VP_ENABLE, val, VP_ENABLE_ON);
335 		mixer_reg_writemask(res, MXR_CFG, val, MXR_CFG_VP_ENABLE);
336 		break;
337 	}
338 }
339 
340 static void mixer_run(struct mixer_context *ctx)
341 {
342 	struct mixer_resources *res = &ctx->mixer_res;
343 
344 	mixer_reg_writemask(res, MXR_STATUS, ~0, MXR_STATUS_REG_RUN);
345 
346 	mixer_regs_dump(ctx);
347 }
348 
349 static void vp_video_buffer(struct mixer_context *ctx, int win)
350 {
351 	struct mixer_resources *res = &ctx->mixer_res;
352 	unsigned long flags;
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;
362 	u32 val;
363 
364 	win_data = &ctx->win_data[win];
365 
366 	switch (win_data->pixel_format) {
367 	case DRM_FORMAT_NV12MT:
368 		tiled_mode = true;
369 	case DRM_FORMAT_NV12M:
370 		crcb_mode = false;
371 		buf_num = 2;
372 		break;
373 	/* TODO: single buffer format NV12, NV21 */
374 	default:
375 		/* ignore pixel format at disable time */
376 		if (!win_data->dma_addr)
377 			break;
378 
379 		DRM_ERROR("pixel format for vp is wrong [%d].\n",
380 				win_data->pixel_format);
381 		return;
382 	}
383 
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;
390 
391 	/* scaling feature: (src << 16) / dst */
392 	x_ratio = (width << 16) / width;
393 	y_ratio = (height << 16) / height;
394 
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;
399 
400 	if (buf_num == 2) {
401 		luma_addr[0] = win_data->dma_addr;
402 		chroma_addr[0] = win_data->chroma_dma_addr;
403 	} else {
404 		luma_addr[0] = win_data->dma_addr;
405 		chroma_addr[0] = win_data->dma_addr
406 			+ (full_width * full_height);
407 	}
408 
409 	if (win_data->scan_flags & DRM_MODE_FLAG_INTERLACE) {
410 		ctx->interlace = true;
411 		if (tiled_mode) {
412 			luma_addr[1] = luma_addr[0] + 0x40;
413 			chroma_addr[1] = chroma_addr[0] + 0x40;
414 		} else {
415 			luma_addr[1] = luma_addr[0] + full_width;
416 			chroma_addr[1] = chroma_addr[0] + full_width;
417 		}
418 	} else {
419 		ctx->interlace = false;
420 		luma_addr[1] = 0;
421 		chroma_addr[1] = 0;
422 	}
423 
424 	spin_lock_irqsave(&res->reg_slock, flags);
425 	mixer_vsync_set_update(ctx, false);
426 
427 	/* interlace or progressive scan mode */
428 	val = (ctx->interlace ? ~0 : 0);
429 	vp_reg_writemask(res, VP_MODE, val, VP_MODE_LINE_SKIP);
430 
431 	/* setup format */
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);
435 
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));
442 
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);
448 
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);
454 	} else {
455 		vp_reg_write(res, VP_DST_HEIGHT, height);
456 		vp_reg_write(res, VP_DST_V_POSITION, dst_y_offset);
457 	}
458 
459 	vp_reg_write(res, VP_H_RATIO, x_ratio);
460 	vp_reg_write(res, VP_V_RATIO, y_ratio);
461 
462 	vp_reg_write(res, VP_ENDIAN_MODE, VP_ENDIAN_MODE_LITTLE);
463 
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]);
469 
470 	mixer_cfg_scan(ctx, mode_height);
471 	mixer_cfg_rgb_fmt(ctx, mode_height);
472 	mixer_cfg_layer(ctx, win, true);
473 	mixer_run(ctx);
474 
475 	mixer_vsync_set_update(ctx, true);
476 	spin_unlock_irqrestore(&res->reg_slock, flags);
477 
478 	vp_regs_dump(ctx);
479 }
480 
481 static void mixer_graph_buffer(struct mixer_context *ctx, int win)
482 {
483 	struct mixer_resources *res = &ctx->mixer_res;
484 	unsigned long flags;
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;
490 	dma_addr_t dma_addr;
491 	unsigned int fmt;
492 	u32 val;
493 
494 	win_data = &ctx->win_data[win];
495 
496 	#define RGB565 4
497 	#define ARGB1555 5
498 	#define ARGB4444 6
499 	#define ARGB8888 7
500 
501 	switch (win_data->bpp) {
502 	case 16:
503 		fmt = ARGB4444;
504 		break;
505 	case 32:
506 		fmt = ARGB8888;
507 		break;
508 	default:
509 		fmt = ARGB8888;
510 	}
511 
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;
518 
519 	/* 2x scaling feature */
520 	x_ratio = 0;
521 	y_ratio = 0;
522 
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;
527 
528 	/* converting dma address base and source offset */
529 	dma_addr = dma_addr
530 		+ (src_x_offset * win_data->bpp >> 3)
531 		+ (src_y_offset * full_width * win_data->bpp >> 3);
532 	src_x_offset = 0;
533 	src_y_offset = 0;
534 
535 	if (win_data->scan_flags & DRM_MODE_FLAG_INTERLACE)
536 		ctx->interlace = true;
537 	else
538 		ctx->interlace = false;
539 
540 	spin_lock_irqsave(&res->reg_slock, flags);
541 	mixer_vsync_set_update(ctx, false);
542 
543 	/* setup format */
544 	mixer_reg_writemask(res, MXR_GRAPHIC_CFG(win),
545 		MXR_GRP_CFG_FORMAT_VAL(fmt), MXR_GRP_CFG_FORMAT_MASK);
546 
547 	/* setup geometry */
548 	mixer_reg_write(res, MXR_GRAPHIC_SPAN(win), full_width);
549 
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);
555 
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);
560 
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);
565 
566 	/* set buffer address to mixer */
567 	mixer_reg_write(res, MXR_GRAPHIC_BASE(win), dma_addr);
568 
569 	mixer_cfg_scan(ctx, mode_height);
570 	mixer_cfg_rgb_fmt(ctx, mode_height);
571 	mixer_cfg_layer(ctx, win, true);
572 	mixer_run(ctx);
573 
574 	mixer_vsync_set_update(ctx, true);
575 	spin_unlock_irqrestore(&res->reg_slock, flags);
576 }
577 
578 static void vp_win_reset(struct mixer_context *ctx)
579 {
580 	struct mixer_resources *res = &ctx->mixer_res;
581 	int tries = 100;
582 
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)
587 			break;
588 		mdelay(10);
589 	}
590 	WARN(tries == 0, "failed to reset Video Processor\n");
591 }
592 
593 static void mixer_win_reset(struct mixer_context *ctx)
594 {
595 	struct mixer_resources *res = &ctx->mixer_res;
596 	unsigned long flags;
597 	u32 val; /* value stored to register */
598 
599 	spin_lock_irqsave(&res->reg_slock, flags);
600 	mixer_vsync_set_update(ctx, false);
601 
602 	mixer_reg_writemask(res, MXR_CFG, MXR_CFG_DST_HDMI, MXR_CFG_DST_MASK);
603 
604 	/* set output in RGB888 mode */
605 	mixer_reg_writemask(res, MXR_CFG, MXR_CFG_OUT_RGB888, MXR_CFG_OUT_MASK);
606 
607 	/* 16 beat burst in DMA */
608 	mixer_reg_writemask(res, MXR_STATUS, MXR_STATUS_16_BURST,
609 		MXR_STATUS_BURST_MASK);
610 
611 	/* setting default layer priority: layer1 > layer0 > video
612 	 * because typical usage scenario would be
613 	 * layer1 - OSD
614 	 * layer0 - framebuffer
615 	 * video - video overlay
616 	 */
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);
621 
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);
626 
627 	/* setting graphical layers */
628 
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 */
632 
633 	/* the same configuration for both layers */
634 	mixer_reg_write(res, MXR_GRAPHIC_CFG(0), val);
635 
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);
639 
640 	/* configuration of Video Processor Registers */
641 	vp_win_reset(ctx);
642 	vp_default_filter(res);
643 
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);
648 
649 	mixer_vsync_set_update(ctx, true);
650 	spin_unlock_irqrestore(&res->reg_slock, flags);
651 }
652 
653 static void mixer_poweron(struct mixer_context *ctx)
654 {
655 	struct mixer_resources *res = &ctx->mixer_res;
656 
657 	DRM_DEBUG_KMS("[%d] %s\n", __LINE__, __func__);
658 
659 	mutex_lock(&ctx->mixer_mutex);
660 	if (ctx->powered) {
661 		mutex_unlock(&ctx->mixer_mutex);
662 		return;
663 	}
664 	ctx->powered = true;
665 	mutex_unlock(&ctx->mixer_mutex);
666 
667 	pm_runtime_get_sync(ctx->dev);
668 
669 	clk_enable(res->mixer);
670 	clk_enable(res->vp);
671 	clk_enable(res->sclk_mixer);
672 
673 	mixer_reg_write(res, MXR_INT_EN, ctx->int_en);
674 	mixer_win_reset(ctx);
675 }
676 
677 static void mixer_poweroff(struct mixer_context *ctx)
678 {
679 	struct mixer_resources *res = &ctx->mixer_res;
680 
681 	DRM_DEBUG_KMS("[%d] %s\n", __LINE__, __func__);
682 
683 	mutex_lock(&ctx->mixer_mutex);
684 	if (!ctx->powered)
685 		goto out;
686 	mutex_unlock(&ctx->mixer_mutex);
687 
688 	ctx->int_en = mixer_reg_read(res, MXR_INT_EN);
689 
690 	clk_disable(res->mixer);
691 	clk_disable(res->vp);
692 	clk_disable(res->sclk_mixer);
693 
694 	pm_runtime_put_sync(ctx->dev);
695 
696 	mutex_lock(&ctx->mixer_mutex);
697 	ctx->powered = false;
698 
699 out:
700 	mutex_unlock(&ctx->mixer_mutex);
701 }
702 
703 static int mixer_enable_vblank(void *ctx, int pipe)
704 {
705 	struct mixer_context *mixer_ctx = ctx;
706 	struct mixer_resources *res = &mixer_ctx->mixer_res;
707 
708 	DRM_DEBUG_KMS("[%d] %s\n", __LINE__, __func__);
709 
710 	mixer_ctx->pipe = pipe;
711 
712 	/* enable vsync interrupt */
713 	mixer_reg_writemask(res, MXR_INT_EN, MXR_INT_EN_VSYNC,
714 			MXR_INT_EN_VSYNC);
715 
716 	return 0;
717 }
718 
719 static void mixer_disable_vblank(void *ctx)
720 {
721 	struct mixer_context *mixer_ctx = ctx;
722 	struct mixer_resources *res = &mixer_ctx->mixer_res;
723 
724 	DRM_DEBUG_KMS("[%d] %s\n", __LINE__, __func__);
725 
726 	/* disable vsync interrupt */
727 	mixer_reg_writemask(res, MXR_INT_EN, 0, MXR_INT_EN_VSYNC);
728 }
729 
730 static void mixer_dpms(void *ctx, int mode)
731 {
732 	struct mixer_context *mixer_ctx = ctx;
733 
734 	DRM_DEBUG_KMS("[%d] %s\n", __LINE__, __func__);
735 
736 	switch (mode) {
737 	case DRM_MODE_DPMS_ON:
738 		mixer_poweron(mixer_ctx);
739 		break;
740 	case DRM_MODE_DPMS_STANDBY:
741 	case DRM_MODE_DPMS_SUSPEND:
742 	case DRM_MODE_DPMS_OFF:
743 		mixer_poweroff(mixer_ctx);
744 		break;
745 	default:
746 		DRM_DEBUG_KMS("unknown dpms mode: %d\n", mode);
747 		break;
748 	}
749 }
750 
751 static void mixer_win_mode_set(void *ctx,
752 			      struct exynos_drm_overlay *overlay)
753 {
754 	struct mixer_context *mixer_ctx = ctx;
755 	struct hdmi_win_data *win_data;
756 	int win;
757 
758 	DRM_DEBUG_KMS("[%d] %s\n", __LINE__, __func__);
759 
760 	if (!overlay) {
761 		DRM_ERROR("overlay is NULL\n");
762 		return;
763 	}
764 
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);
770 
771 	win = overlay->zpos;
772 	if (win == DEFAULT_ZPOS)
773 		win = MIXER_DEFAULT_WIN;
774 
775 	if (win < 0 || win > MIXER_WIN_NR) {
776 		DRM_ERROR("mixer window[%d] is wrong\n", win);
777 		return;
778 	}
779 
780 	win_data = &mixer_ctx->win_data[win];
781 
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;
788 
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;
793 
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;
798 
799 	win_data->mode_width = overlay->mode_width;
800 	win_data->mode_height = overlay->mode_height;
801 
802 	win_data->scan_flags = overlay->scan_flag;
803 }
804 
805 static void mixer_win_commit(void *ctx, int win)
806 {
807 	struct mixer_context *mixer_ctx = ctx;
808 
809 	DRM_DEBUG_KMS("[%d] %s, win: %d\n", __LINE__, __func__, win);
810 
811 	if (win > 1)
812 		vp_video_buffer(mixer_ctx, win);
813 	else
814 		mixer_graph_buffer(mixer_ctx, win);
815 }
816 
817 static void mixer_win_disable(void *ctx, int win)
818 {
819 	struct mixer_context *mixer_ctx = ctx;
820 	struct mixer_resources *res = &mixer_ctx->mixer_res;
821 	unsigned long flags;
822 
823 	DRM_DEBUG_KMS("[%d] %s, win: %d\n", __LINE__, __func__, win);
824 
825 	spin_lock_irqsave(&res->reg_slock, flags);
826 	mixer_vsync_set_update(mixer_ctx, false);
827 
828 	mixer_cfg_layer(mixer_ctx, win, false);
829 
830 	mixer_vsync_set_update(mixer_ctx, true);
831 	spin_unlock_irqrestore(&res->reg_slock, flags);
832 }
833 
834 static struct exynos_mixer_ops mixer_ops = {
835 	/* manager */
836 	.enable_vblank		= mixer_enable_vblank,
837 	.disable_vblank		= mixer_disable_vblank,
838 	.dpms			= mixer_dpms,
839 
840 	/* overlay */
841 	.win_mode_set		= mixer_win_mode_set,
842 	.win_commit		= mixer_win_commit,
843 	.win_disable		= mixer_win_disable,
844 };
845 
846 /* for pageflip event */
847 static void mixer_finish_pageflip(struct drm_device *drm_dev, int crtc)
848 {
849 	struct exynos_drm_private *dev_priv = drm_dev->dev_private;
850 	struct drm_pending_vblank_event *e, *t;
851 	struct timeval now;
852 	unsigned long flags;
853 	bool is_checked = false;
854 
855 	spin_lock_irqsave(&drm_dev->event_lock, flags);
856 
857 	list_for_each_entry_safe(e, t, &dev_priv->pageflip_event_list,
858 			base.link) {
859 		/* if event's pipe isn't same as crtc then ignore it. */
860 		if (crtc != e->pipe)
861 			continue;
862 
863 		is_checked = true;
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;
868 
869 		list_move_tail(&e->base.link, &e->base.file_priv->event_list);
870 		wake_up_interruptible(&e->base.file_priv->event_wait);
871 	}
872 
873 	if (is_checked)
874 		/*
875 		 * call drm_vblank_put only in case that drm_vblank_get was
876 		 * called.
877 		 */
878 		if (atomic_read(&drm_dev->vblank_refcount[crtc]) > 0)
879 			drm_vblank_put(drm_dev, crtc);
880 
881 	spin_unlock_irqrestore(&drm_dev->event_lock, flags);
882 }
883 
884 static irqreturn_t mixer_irq_handler(int irq, void *arg)
885 {
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, val_base;
890 
891 	spin_lock(&res->reg_slock);
892 
893 	/* read interrupt status for handling and clearing flags for VSYNC */
894 	val = mixer_reg_read(res, MXR_INT_STATUS);
895 
896 	/* handling VSYNC */
897 	if (val & MXR_INT_STATUS_VSYNC) {
898 		/* interlace scan need to check shadow register */
899 		if (ctx->interlace) {
900 			val_base = mixer_reg_read(res, MXR_GRAPHIC_BASE_S(0));
901 			if (ctx->win_data[0].dma_addr != val_base)
902 				goto out;
903 
904 			val_base = mixer_reg_read(res, MXR_GRAPHIC_BASE_S(1));
905 			if (ctx->win_data[1].dma_addr != val_base)
906 				goto out;
907 		}
908 
909 		drm_handle_vblank(drm_hdmi_ctx->drm_dev, ctx->pipe);
910 		mixer_finish_pageflip(drm_hdmi_ctx->drm_dev, ctx->pipe);
911 	}
912 
913 out:
914 	/* clear interrupts */
915 	if (~val & MXR_INT_EN_VSYNC) {
916 		/* vsync interrupt use different bit for read and clear */
917 		val &= ~MXR_INT_EN_VSYNC;
918 		val |= MXR_INT_CLEAR_VSYNC;
919 	}
920 	mixer_reg_write(res, MXR_INT_STATUS, val);
921 
922 	spin_unlock(&res->reg_slock);
923 
924 	return IRQ_HANDLED;
925 }
926 
927 static int __devinit mixer_resources_init(struct exynos_drm_hdmi_context *ctx,
928 				 struct platform_device *pdev)
929 {
930 	struct mixer_context *mixer_ctx = ctx->ctx;
931 	struct device *dev = &pdev->dev;
932 	struct mixer_resources *mixer_res = &mixer_ctx->mixer_res;
933 	struct resource *res;
934 	int ret;
935 
936 	spin_lock_init(&mixer_res->reg_slock);
937 
938 	mixer_res->mixer = clk_get(dev, "mixer");
939 	if (IS_ERR_OR_NULL(mixer_res->mixer)) {
940 		dev_err(dev, "failed to get clock 'mixer'\n");
941 		ret = -ENODEV;
942 		goto fail;
943 	}
944 	mixer_res->vp = clk_get(dev, "vp");
945 	if (IS_ERR_OR_NULL(mixer_res->vp)) {
946 		dev_err(dev, "failed to get clock 'vp'\n");
947 		ret = -ENODEV;
948 		goto fail;
949 	}
950 	mixer_res->sclk_mixer = clk_get(dev, "sclk_mixer");
951 	if (IS_ERR_OR_NULL(mixer_res->sclk_mixer)) {
952 		dev_err(dev, "failed to get clock 'sclk_mixer'\n");
953 		ret = -ENODEV;
954 		goto fail;
955 	}
956 	mixer_res->sclk_hdmi = clk_get(dev, "sclk_hdmi");
957 	if (IS_ERR_OR_NULL(mixer_res->sclk_hdmi)) {
958 		dev_err(dev, "failed to get clock 'sclk_hdmi'\n");
959 		ret = -ENODEV;
960 		goto fail;
961 	}
962 	mixer_res->sclk_dac = clk_get(dev, "sclk_dac");
963 	if (IS_ERR_OR_NULL(mixer_res->sclk_dac)) {
964 		dev_err(dev, "failed to get clock 'sclk_dac'\n");
965 		ret = -ENODEV;
966 		goto fail;
967 	}
968 	res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "mxr");
969 	if (res == NULL) {
970 		dev_err(dev, "get memory resource failed.\n");
971 		ret = -ENXIO;
972 		goto fail;
973 	}
974 
975 	clk_set_parent(mixer_res->sclk_mixer, mixer_res->sclk_hdmi);
976 
977 	mixer_res->mixer_regs = ioremap(res->start, resource_size(res));
978 	if (mixer_res->mixer_regs == NULL) {
979 		dev_err(dev, "register mapping failed.\n");
980 		ret = -ENXIO;
981 		goto fail;
982 	}
983 
984 	res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "vp");
985 	if (res == NULL) {
986 		dev_err(dev, "get memory resource failed.\n");
987 		ret = -ENXIO;
988 		goto fail_mixer_regs;
989 	}
990 
991 	mixer_res->vp_regs = ioremap(res->start, resource_size(res));
992 	if (mixer_res->vp_regs == NULL) {
993 		dev_err(dev, "register mapping failed.\n");
994 		ret = -ENXIO;
995 		goto fail_mixer_regs;
996 	}
997 
998 	res = platform_get_resource_byname(pdev, IORESOURCE_IRQ, "irq");
999 	if (res == NULL) {
1000 		dev_err(dev, "get interrupt resource failed.\n");
1001 		ret = -ENXIO;
1002 		goto fail_vp_regs;
1003 	}
1004 
1005 	ret = request_irq(res->start, mixer_irq_handler, 0, "drm_mixer", ctx);
1006 	if (ret) {
1007 		dev_err(dev, "request interrupt failed.\n");
1008 		goto fail_vp_regs;
1009 	}
1010 	mixer_res->irq = res->start;
1011 
1012 	return 0;
1013 
1014 fail_vp_regs:
1015 	iounmap(mixer_res->vp_regs);
1016 
1017 fail_mixer_regs:
1018 	iounmap(mixer_res->mixer_regs);
1019 
1020 fail:
1021 	if (!IS_ERR_OR_NULL(mixer_res->sclk_dac))
1022 		clk_put(mixer_res->sclk_dac);
1023 	if (!IS_ERR_OR_NULL(mixer_res->sclk_hdmi))
1024 		clk_put(mixer_res->sclk_hdmi);
1025 	if (!IS_ERR_OR_NULL(mixer_res->sclk_mixer))
1026 		clk_put(mixer_res->sclk_mixer);
1027 	if (!IS_ERR_OR_NULL(mixer_res->vp))
1028 		clk_put(mixer_res->vp);
1029 	if (!IS_ERR_OR_NULL(mixer_res->mixer))
1030 		clk_put(mixer_res->mixer);
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 	free_irq(res->irq, ctx);
1039 
1040 	iounmap(res->vp_regs);
1041 	iounmap(res->mixer_regs);
1042 }
1043 
1044 static int __devinit mixer_probe(struct platform_device *pdev)
1045 {
1046 	struct device *dev = &pdev->dev;
1047 	struct exynos_drm_hdmi_context *drm_hdmi_ctx;
1048 	struct mixer_context *ctx;
1049 	int ret;
1050 
1051 	dev_info(dev, "probe start\n");
1052 
1053 	drm_hdmi_ctx = kzalloc(sizeof(*drm_hdmi_ctx), GFP_KERNEL);
1054 	if (!drm_hdmi_ctx) {
1055 		DRM_ERROR("failed to allocate common hdmi context.\n");
1056 		return -ENOMEM;
1057 	}
1058 
1059 	ctx = kzalloc(sizeof(*ctx), GFP_KERNEL);
1060 	if (!ctx) {
1061 		DRM_ERROR("failed to alloc mixer context.\n");
1062 		kfree(drm_hdmi_ctx);
1063 		return -ENOMEM;
1064 	}
1065 
1066 	mutex_init(&ctx->mixer_mutex);
1067 
1068 	ctx->dev = &pdev->dev;
1069 	drm_hdmi_ctx->ctx = (void *)ctx;
1070 
1071 	platform_set_drvdata(pdev, drm_hdmi_ctx);
1072 
1073 	/* acquire resources: regs, irqs, clocks */
1074 	ret = mixer_resources_init(drm_hdmi_ctx, pdev);
1075 	if (ret)
1076 		goto fail;
1077 
1078 	/* register specific callback point to common hdmi. */
1079 	exynos_mixer_ops_register(&mixer_ops);
1080 
1081 	pm_runtime_enable(dev);
1082 
1083 	return 0;
1084 
1085 
1086 fail:
1087 	dev_info(dev, "probe failed\n");
1088 	return ret;
1089 }
1090 
1091 static int mixer_remove(struct platform_device *pdev)
1092 {
1093 	struct device *dev = &pdev->dev;
1094 	struct exynos_drm_hdmi_context *drm_hdmi_ctx =
1095 					platform_get_drvdata(pdev);
1096 	struct mixer_context *ctx = drm_hdmi_ctx->ctx;
1097 
1098 	dev_info(dev, "remove successful\n");
1099 
1100 	pm_runtime_disable(&pdev->dev);
1101 
1102 	mixer_resources_cleanup(ctx);
1103 
1104 	return 0;
1105 }
1106 
1107 struct platform_driver mixer_driver = {
1108 	.driver = {
1109 		.name = "s5p-mixer",
1110 		.owner = THIS_MODULE,
1111 	},
1112 	.probe = mixer_probe,
1113 	.remove = __devexit_p(mixer_remove),
1114 };
1115