xref: /linux/drivers/gpu/drm/exynos/exynos_mixer.c (revision e269f90f3d3f7c70cf661c660bf445597261f54a)
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_NV12M:
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 
605 	val  = MXR_GRP_CFG_COLOR_KEY_DISABLE; /* no blank key */
606 	val |= MXR_GRP_CFG_WIN_BLEND_EN;
607 	val |= MXR_GRP_CFG_ALPHA_VAL(0xff); /* non-transparent alpha */
608 
609 	/* the same configuration for both layers */
610 	mixer_reg_write(res, MXR_GRAPHIC_CFG(0), val);
611 
612 	val |= MXR_GRP_CFG_BLEND_PRE_MUL;
613 	val |= MXR_GRP_CFG_PIXEL_BLEND_EN;
614 	mixer_reg_write(res, MXR_GRAPHIC_CFG(1), val);
615 
616 	/* configuration of Video Processor Registers */
617 	vp_win_reset(ctx);
618 	vp_default_filter(res);
619 
620 	/* disable all layers */
621 	mixer_reg_writemask(res, MXR_CFG, 0, MXR_CFG_GRP0_ENABLE);
622 	mixer_reg_writemask(res, MXR_CFG, 0, MXR_CFG_GRP1_ENABLE);
623 	mixer_reg_writemask(res, MXR_CFG, 0, MXR_CFG_VP_ENABLE);
624 
625 	mixer_vsync_set_update(ctx, true);
626 	spin_unlock_irqrestore(&res->reg_slock, flags);
627 }
628 
629 static void mixer_poweron(struct mixer_context *ctx)
630 {
631 	struct mixer_resources *res = &ctx->mixer_res;
632 
633 	DRM_DEBUG_KMS("[%d] %s\n", __LINE__, __func__);
634 
635 	mutex_lock(&ctx->mixer_mutex);
636 	if (ctx->powered) {
637 		mutex_unlock(&ctx->mixer_mutex);
638 		return;
639 	}
640 	ctx->powered = true;
641 	mutex_unlock(&ctx->mixer_mutex);
642 
643 	pm_runtime_get_sync(ctx->dev);
644 
645 	clk_enable(res->mixer);
646 	clk_enable(res->vp);
647 	clk_enable(res->sclk_mixer);
648 
649 	mixer_reg_write(res, MXR_INT_EN, ctx->int_en);
650 	mixer_win_reset(ctx);
651 }
652 
653 static void mixer_poweroff(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 		goto out;
662 	mutex_unlock(&ctx->mixer_mutex);
663 
664 	ctx->int_en = mixer_reg_read(res, MXR_INT_EN);
665 
666 	clk_disable(res->mixer);
667 	clk_disable(res->vp);
668 	clk_disable(res->sclk_mixer);
669 
670 	pm_runtime_put_sync(ctx->dev);
671 
672 	mutex_lock(&ctx->mixer_mutex);
673 	ctx->powered = false;
674 
675 out:
676 	mutex_unlock(&ctx->mixer_mutex);
677 }
678 
679 static int mixer_enable_vblank(void *ctx, int pipe)
680 {
681 	struct mixer_context *mixer_ctx = ctx;
682 	struct mixer_resources *res = &mixer_ctx->mixer_res;
683 
684 	DRM_DEBUG_KMS("[%d] %s\n", __LINE__, __func__);
685 
686 	mixer_ctx->pipe = pipe;
687 
688 	/* enable vsync interrupt */
689 	mixer_reg_writemask(res, MXR_INT_EN, MXR_INT_EN_VSYNC,
690 			MXR_INT_EN_VSYNC);
691 
692 	return 0;
693 }
694 
695 static void mixer_disable_vblank(void *ctx)
696 {
697 	struct mixer_context *mixer_ctx = ctx;
698 	struct mixer_resources *res = &mixer_ctx->mixer_res;
699 
700 	DRM_DEBUG_KMS("[%d] %s\n", __LINE__, __func__);
701 
702 	/* disable vsync interrupt */
703 	mixer_reg_writemask(res, MXR_INT_EN, 0, MXR_INT_EN_VSYNC);
704 }
705 
706 static void mixer_dpms(void *ctx, int mode)
707 {
708 	struct mixer_context *mixer_ctx = ctx;
709 
710 	DRM_DEBUG_KMS("[%d] %s\n", __LINE__, __func__);
711 
712 	switch (mode) {
713 	case DRM_MODE_DPMS_ON:
714 		mixer_poweron(mixer_ctx);
715 		break;
716 	case DRM_MODE_DPMS_STANDBY:
717 	case DRM_MODE_DPMS_SUSPEND:
718 	case DRM_MODE_DPMS_OFF:
719 		mixer_poweroff(mixer_ctx);
720 		break;
721 	default:
722 		DRM_DEBUG_KMS("unknown dpms mode: %d\n", mode);
723 		break;
724 	}
725 }
726 
727 static void mixer_win_mode_set(void *ctx,
728 			      struct exynos_drm_overlay *overlay)
729 {
730 	struct mixer_context *mixer_ctx = ctx;
731 	struct hdmi_win_data *win_data;
732 	int win;
733 
734 	DRM_DEBUG_KMS("[%d] %s\n", __LINE__, __func__);
735 
736 	if (!overlay) {
737 		DRM_ERROR("overlay is NULL\n");
738 		return;
739 	}
740 
741 	DRM_DEBUG_KMS("set [%d]x[%d] at (%d,%d) to [%d]x[%d] at (%d,%d)\n",
742 				 overlay->fb_width, overlay->fb_height,
743 				 overlay->fb_x, overlay->fb_y,
744 				 overlay->crtc_width, overlay->crtc_height,
745 				 overlay->crtc_x, overlay->crtc_y);
746 
747 	win = overlay->zpos;
748 	if (win == DEFAULT_ZPOS)
749 		win = MIXER_DEFAULT_WIN;
750 
751 	if (win < 0 || win > MIXER_WIN_NR) {
752 		DRM_ERROR("mixer window[%d] is wrong\n", win);
753 		return;
754 	}
755 
756 	win_data = &mixer_ctx->win_data[win];
757 
758 	win_data->dma_addr = overlay->dma_addr[0];
759 	win_data->vaddr = overlay->vaddr[0];
760 	win_data->chroma_dma_addr = overlay->dma_addr[1];
761 	win_data->chroma_vaddr = overlay->vaddr[1];
762 	win_data->pixel_format = overlay->pixel_format;
763 	win_data->bpp = overlay->bpp;
764 
765 	win_data->crtc_x = overlay->crtc_x;
766 	win_data->crtc_y = overlay->crtc_y;
767 	win_data->crtc_width = overlay->crtc_width;
768 	win_data->crtc_height = overlay->crtc_height;
769 
770 	win_data->fb_x = overlay->fb_x;
771 	win_data->fb_y = overlay->fb_y;
772 	win_data->fb_width = overlay->fb_width;
773 	win_data->fb_height = overlay->fb_height;
774 	win_data->src_width = overlay->src_width;
775 	win_data->src_height = overlay->src_height;
776 
777 	win_data->mode_width = overlay->mode_width;
778 	win_data->mode_height = overlay->mode_height;
779 
780 	win_data->scan_flags = overlay->scan_flag;
781 }
782 
783 static void mixer_win_commit(void *ctx, int win)
784 {
785 	struct mixer_context *mixer_ctx = ctx;
786 
787 	DRM_DEBUG_KMS("[%d] %s, win: %d\n", __LINE__, __func__, win);
788 
789 	if (win > 1)
790 		vp_video_buffer(mixer_ctx, win);
791 	else
792 		mixer_graph_buffer(mixer_ctx, win);
793 }
794 
795 static void mixer_win_disable(void *ctx, int win)
796 {
797 	struct mixer_context *mixer_ctx = ctx;
798 	struct mixer_resources *res = &mixer_ctx->mixer_res;
799 	unsigned long flags;
800 
801 	DRM_DEBUG_KMS("[%d] %s, win: %d\n", __LINE__, __func__, win);
802 
803 	spin_lock_irqsave(&res->reg_slock, flags);
804 	mixer_vsync_set_update(mixer_ctx, false);
805 
806 	mixer_cfg_layer(mixer_ctx, win, false);
807 
808 	mixer_vsync_set_update(mixer_ctx, true);
809 	spin_unlock_irqrestore(&res->reg_slock, flags);
810 }
811 
812 static struct exynos_mixer_ops mixer_ops = {
813 	/* manager */
814 	.enable_vblank		= mixer_enable_vblank,
815 	.disable_vblank		= mixer_disable_vblank,
816 	.dpms			= mixer_dpms,
817 
818 	/* overlay */
819 	.win_mode_set		= mixer_win_mode_set,
820 	.win_commit		= mixer_win_commit,
821 	.win_disable		= mixer_win_disable,
822 };
823 
824 /* for pageflip event */
825 static void mixer_finish_pageflip(struct drm_device *drm_dev, int crtc)
826 {
827 	struct exynos_drm_private *dev_priv = drm_dev->dev_private;
828 	struct drm_pending_vblank_event *e, *t;
829 	struct timeval now;
830 	unsigned long flags;
831 	bool is_checked = false;
832 
833 	spin_lock_irqsave(&drm_dev->event_lock, flags);
834 
835 	list_for_each_entry_safe(e, t, &dev_priv->pageflip_event_list,
836 			base.link) {
837 		/* if event's pipe isn't same as crtc then ignore it. */
838 		if (crtc != e->pipe)
839 			continue;
840 
841 		is_checked = true;
842 		do_gettimeofday(&now);
843 		e->event.sequence = 0;
844 		e->event.tv_sec = now.tv_sec;
845 		e->event.tv_usec = now.tv_usec;
846 
847 		list_move_tail(&e->base.link, &e->base.file_priv->event_list);
848 		wake_up_interruptible(&e->base.file_priv->event_wait);
849 	}
850 
851 	if (is_checked)
852 		/*
853 		 * call drm_vblank_put only in case that drm_vblank_get was
854 		 * called.
855 		 */
856 		if (atomic_read(&drm_dev->vblank_refcount[crtc]) > 0)
857 			drm_vblank_put(drm_dev, crtc);
858 
859 	spin_unlock_irqrestore(&drm_dev->event_lock, flags);
860 }
861 
862 static irqreturn_t mixer_irq_handler(int irq, void *arg)
863 {
864 	struct exynos_drm_hdmi_context *drm_hdmi_ctx = arg;
865 	struct mixer_context *ctx = drm_hdmi_ctx->ctx;
866 	struct mixer_resources *res = &ctx->mixer_res;
867 	u32 val, base, shadow;
868 
869 	spin_lock(&res->reg_slock);
870 
871 	/* read interrupt status for handling and clearing flags for VSYNC */
872 	val = mixer_reg_read(res, MXR_INT_STATUS);
873 
874 	/* handling VSYNC */
875 	if (val & MXR_INT_STATUS_VSYNC) {
876 		/* interlace scan need to check shadow register */
877 		if (ctx->interlace) {
878 			base = mixer_reg_read(res, MXR_GRAPHIC_BASE(0));
879 			shadow = mixer_reg_read(res, MXR_GRAPHIC_BASE_S(0));
880 			if (base != shadow)
881 				goto out;
882 
883 			base = mixer_reg_read(res, MXR_GRAPHIC_BASE(1));
884 			shadow = mixer_reg_read(res, MXR_GRAPHIC_BASE_S(1));
885 			if (base != shadow)
886 				goto out;
887 		}
888 
889 		drm_handle_vblank(drm_hdmi_ctx->drm_dev, ctx->pipe);
890 		mixer_finish_pageflip(drm_hdmi_ctx->drm_dev, ctx->pipe);
891 	}
892 
893 out:
894 	/* clear interrupts */
895 	if (~val & MXR_INT_EN_VSYNC) {
896 		/* vsync interrupt use different bit for read and clear */
897 		val &= ~MXR_INT_EN_VSYNC;
898 		val |= MXR_INT_CLEAR_VSYNC;
899 	}
900 	mixer_reg_write(res, MXR_INT_STATUS, val);
901 
902 	spin_unlock(&res->reg_slock);
903 
904 	return IRQ_HANDLED;
905 }
906 
907 static int __devinit mixer_resources_init(struct exynos_drm_hdmi_context *ctx,
908 				 struct platform_device *pdev)
909 {
910 	struct mixer_context *mixer_ctx = ctx->ctx;
911 	struct device *dev = &pdev->dev;
912 	struct mixer_resources *mixer_res = &mixer_ctx->mixer_res;
913 	struct resource *res;
914 	int ret;
915 
916 	spin_lock_init(&mixer_res->reg_slock);
917 
918 	mixer_res->mixer = clk_get(dev, "mixer");
919 	if (IS_ERR_OR_NULL(mixer_res->mixer)) {
920 		dev_err(dev, "failed to get clock 'mixer'\n");
921 		ret = -ENODEV;
922 		goto fail;
923 	}
924 	mixer_res->vp = clk_get(dev, "vp");
925 	if (IS_ERR_OR_NULL(mixer_res->vp)) {
926 		dev_err(dev, "failed to get clock 'vp'\n");
927 		ret = -ENODEV;
928 		goto fail;
929 	}
930 	mixer_res->sclk_mixer = clk_get(dev, "sclk_mixer");
931 	if (IS_ERR_OR_NULL(mixer_res->sclk_mixer)) {
932 		dev_err(dev, "failed to get clock 'sclk_mixer'\n");
933 		ret = -ENODEV;
934 		goto fail;
935 	}
936 	mixer_res->sclk_hdmi = clk_get(dev, "sclk_hdmi");
937 	if (IS_ERR_OR_NULL(mixer_res->sclk_hdmi)) {
938 		dev_err(dev, "failed to get clock 'sclk_hdmi'\n");
939 		ret = -ENODEV;
940 		goto fail;
941 	}
942 	mixer_res->sclk_dac = clk_get(dev, "sclk_dac");
943 	if (IS_ERR_OR_NULL(mixer_res->sclk_dac)) {
944 		dev_err(dev, "failed to get clock 'sclk_dac'\n");
945 		ret = -ENODEV;
946 		goto fail;
947 	}
948 	res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "mxr");
949 	if (res == NULL) {
950 		dev_err(dev, "get memory resource failed.\n");
951 		ret = -ENXIO;
952 		goto fail;
953 	}
954 
955 	clk_set_parent(mixer_res->sclk_mixer, mixer_res->sclk_hdmi);
956 
957 	mixer_res->mixer_regs = ioremap(res->start, resource_size(res));
958 	if (mixer_res->mixer_regs == NULL) {
959 		dev_err(dev, "register mapping failed.\n");
960 		ret = -ENXIO;
961 		goto fail;
962 	}
963 
964 	res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "vp");
965 	if (res == NULL) {
966 		dev_err(dev, "get memory resource failed.\n");
967 		ret = -ENXIO;
968 		goto fail_mixer_regs;
969 	}
970 
971 	mixer_res->vp_regs = ioremap(res->start, resource_size(res));
972 	if (mixer_res->vp_regs == NULL) {
973 		dev_err(dev, "register mapping failed.\n");
974 		ret = -ENXIO;
975 		goto fail_mixer_regs;
976 	}
977 
978 	res = platform_get_resource_byname(pdev, IORESOURCE_IRQ, "irq");
979 	if (res == NULL) {
980 		dev_err(dev, "get interrupt resource failed.\n");
981 		ret = -ENXIO;
982 		goto fail_vp_regs;
983 	}
984 
985 	ret = request_irq(res->start, mixer_irq_handler, 0, "drm_mixer", ctx);
986 	if (ret) {
987 		dev_err(dev, "request interrupt failed.\n");
988 		goto fail_vp_regs;
989 	}
990 	mixer_res->irq = res->start;
991 
992 	return 0;
993 
994 fail_vp_regs:
995 	iounmap(mixer_res->vp_regs);
996 
997 fail_mixer_regs:
998 	iounmap(mixer_res->mixer_regs);
999 
1000 fail:
1001 	if (!IS_ERR_OR_NULL(mixer_res->sclk_dac))
1002 		clk_put(mixer_res->sclk_dac);
1003 	if (!IS_ERR_OR_NULL(mixer_res->sclk_hdmi))
1004 		clk_put(mixer_res->sclk_hdmi);
1005 	if (!IS_ERR_OR_NULL(mixer_res->sclk_mixer))
1006 		clk_put(mixer_res->sclk_mixer);
1007 	if (!IS_ERR_OR_NULL(mixer_res->vp))
1008 		clk_put(mixer_res->vp);
1009 	if (!IS_ERR_OR_NULL(mixer_res->mixer))
1010 		clk_put(mixer_res->mixer);
1011 	return ret;
1012 }
1013 
1014 static void mixer_resources_cleanup(struct mixer_context *ctx)
1015 {
1016 	struct mixer_resources *res = &ctx->mixer_res;
1017 
1018 	free_irq(res->irq, ctx);
1019 
1020 	iounmap(res->vp_regs);
1021 	iounmap(res->mixer_regs);
1022 }
1023 
1024 static int __devinit mixer_probe(struct platform_device *pdev)
1025 {
1026 	struct device *dev = &pdev->dev;
1027 	struct exynos_drm_hdmi_context *drm_hdmi_ctx;
1028 	struct mixer_context *ctx;
1029 	int ret;
1030 
1031 	dev_info(dev, "probe start\n");
1032 
1033 	drm_hdmi_ctx = kzalloc(sizeof(*drm_hdmi_ctx), GFP_KERNEL);
1034 	if (!drm_hdmi_ctx) {
1035 		DRM_ERROR("failed to allocate common hdmi context.\n");
1036 		return -ENOMEM;
1037 	}
1038 
1039 	ctx = kzalloc(sizeof(*ctx), GFP_KERNEL);
1040 	if (!ctx) {
1041 		DRM_ERROR("failed to alloc mixer context.\n");
1042 		kfree(drm_hdmi_ctx);
1043 		return -ENOMEM;
1044 	}
1045 
1046 	mutex_init(&ctx->mixer_mutex);
1047 
1048 	ctx->dev = &pdev->dev;
1049 	drm_hdmi_ctx->ctx = (void *)ctx;
1050 
1051 	platform_set_drvdata(pdev, drm_hdmi_ctx);
1052 
1053 	/* acquire resources: regs, irqs, clocks */
1054 	ret = mixer_resources_init(drm_hdmi_ctx, pdev);
1055 	if (ret)
1056 		goto fail;
1057 
1058 	/* register specific callback point to common hdmi. */
1059 	exynos_mixer_ops_register(&mixer_ops);
1060 
1061 	pm_runtime_enable(dev);
1062 
1063 	return 0;
1064 
1065 
1066 fail:
1067 	dev_info(dev, "probe failed\n");
1068 	return ret;
1069 }
1070 
1071 static int mixer_remove(struct platform_device *pdev)
1072 {
1073 	struct device *dev = &pdev->dev;
1074 	struct exynos_drm_hdmi_context *drm_hdmi_ctx =
1075 					platform_get_drvdata(pdev);
1076 	struct mixer_context *ctx = drm_hdmi_ctx->ctx;
1077 
1078 	dev_info(dev, "remove successful\n");
1079 
1080 	pm_runtime_disable(&pdev->dev);
1081 
1082 	mixer_resources_cleanup(ctx);
1083 
1084 	return 0;
1085 }
1086 
1087 #ifdef CONFIG_PM_SLEEP
1088 static int mixer_suspend(struct device *dev)
1089 {
1090 	struct exynos_drm_hdmi_context *drm_hdmi_ctx = get_mixer_context(dev);
1091 	struct mixer_context *ctx = drm_hdmi_ctx->ctx;
1092 
1093 	mixer_poweroff(ctx);
1094 
1095 	return 0;
1096 }
1097 #endif
1098 
1099 static SIMPLE_DEV_PM_OPS(mixer_pm_ops, mixer_suspend, NULL);
1100 
1101 struct platform_driver mixer_driver = {
1102 	.driver = {
1103 		.name = "s5p-mixer",
1104 		.owner = THIS_MODULE,
1105 		.pm = &mixer_pm_ops,
1106 	},
1107 	.probe = mixer_probe,
1108 	.remove = __devexit_p(mixer_remove),
1109 };
1110