xref: /linux/drivers/gpu/drm/exynos/exynos_mixer.c (revision 3932b9ca55b0be314a36d3e84faff3e823c081f5)
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 <drm/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/platform_device.h>
27 #include <linux/interrupt.h>
28 #include <linux/irq.h>
29 #include <linux/delay.h>
30 #include <linux/pm_runtime.h>
31 #include <linux/clk.h>
32 #include <linux/regulator/consumer.h>
33 #include <linux/of.h>
34 #include <linux/component.h>
35 
36 #include <drm/exynos_drm.h>
37 
38 #include "exynos_drm_drv.h"
39 #include "exynos_drm_crtc.h"
40 #include "exynos_drm_iommu.h"
41 #include "exynos_mixer.h"
42 
43 #define get_mixer_manager(dev)	platform_get_drvdata(to_platform_device(dev))
44 
45 #define MIXER_WIN_NR		3
46 #define MIXER_DEFAULT_WIN	0
47 
48 struct hdmi_win_data {
49 	dma_addr_t		dma_addr;
50 	dma_addr_t		chroma_dma_addr;
51 	uint32_t		pixel_format;
52 	unsigned int		bpp;
53 	unsigned int		crtc_x;
54 	unsigned int		crtc_y;
55 	unsigned int		crtc_width;
56 	unsigned int		crtc_height;
57 	unsigned int		fb_x;
58 	unsigned int		fb_y;
59 	unsigned int		fb_width;
60 	unsigned int		fb_height;
61 	unsigned int		src_width;
62 	unsigned int		src_height;
63 	unsigned int		mode_width;
64 	unsigned int		mode_height;
65 	unsigned int		scan_flags;
66 	bool			enabled;
67 	bool			resume;
68 };
69 
70 struct mixer_resources {
71 	int			irq;
72 	void __iomem		*mixer_regs;
73 	void __iomem		*vp_regs;
74 	spinlock_t		reg_slock;
75 	struct clk		*mixer;
76 	struct clk		*vp;
77 	struct clk		*sclk_mixer;
78 	struct clk		*sclk_hdmi;
79 	struct clk		*mout_mixer;
80 };
81 
82 enum mixer_version_id {
83 	MXR_VER_0_0_0_16,
84 	MXR_VER_16_0_33_0,
85 	MXR_VER_128_0_0_184,
86 };
87 
88 struct mixer_context {
89 	struct platform_device *pdev;
90 	struct device		*dev;
91 	struct drm_device	*drm_dev;
92 	int			pipe;
93 	bool			interlace;
94 	bool			powered;
95 	bool			vp_enabled;
96 	bool			has_sclk;
97 	u32			int_en;
98 
99 	struct mutex		mixer_mutex;
100 	struct mixer_resources	mixer_res;
101 	struct hdmi_win_data	win_data[MIXER_WIN_NR];
102 	enum mixer_version_id	mxr_ver;
103 	wait_queue_head_t	wait_vsync_queue;
104 	atomic_t		wait_vsync_event;
105 };
106 
107 struct mixer_drv_data {
108 	enum mixer_version_id	version;
109 	bool					is_vp_enabled;
110 	bool					has_sclk;
111 };
112 
113 static const u8 filter_y_horiz_tap8[] = {
114 	0,	-1,	-1,	-1,	-1,	-1,	-1,	-1,
115 	-1,	-1,	-1,	-1,	-1,	0,	0,	0,
116 	0,	2,	4,	5,	6,	6,	6,	6,
117 	6,	5,	5,	4,	3,	2,	1,	1,
118 	0,	-6,	-12,	-16,	-18,	-20,	-21,	-20,
119 	-20,	-18,	-16,	-13,	-10,	-8,	-5,	-2,
120 	127,	126,	125,	121,	114,	107,	99,	89,
121 	79,	68,	57,	46,	35,	25,	16,	8,
122 };
123 
124 static const u8 filter_y_vert_tap4[] = {
125 	0,	-3,	-6,	-8,	-8,	-8,	-8,	-7,
126 	-6,	-5,	-4,	-3,	-2,	-1,	-1,	0,
127 	127,	126,	124,	118,	111,	102,	92,	81,
128 	70,	59,	48,	37,	27,	19,	11,	5,
129 	0,	5,	11,	19,	27,	37,	48,	59,
130 	70,	81,	92,	102,	111,	118,	124,	126,
131 	0,	0,	-1,	-1,	-2,	-3,	-4,	-5,
132 	-6,	-7,	-8,	-8,	-8,	-8,	-6,	-3,
133 };
134 
135 static const u8 filter_cr_horiz_tap4[] = {
136 	0,	-3,	-6,	-8,	-8,	-8,	-8,	-7,
137 	-6,	-5,	-4,	-3,	-2,	-1,	-1,	0,
138 	127,	126,	124,	118,	111,	102,	92,	81,
139 	70,	59,	48,	37,	27,	19,	11,	5,
140 };
141 
142 static inline u32 vp_reg_read(struct mixer_resources *res, u32 reg_id)
143 {
144 	return readl(res->vp_regs + reg_id);
145 }
146 
147 static inline void vp_reg_write(struct mixer_resources *res, u32 reg_id,
148 				 u32 val)
149 {
150 	writel(val, res->vp_regs + reg_id);
151 }
152 
153 static inline void vp_reg_writemask(struct mixer_resources *res, u32 reg_id,
154 				 u32 val, u32 mask)
155 {
156 	u32 old = vp_reg_read(res, reg_id);
157 
158 	val = (val & mask) | (old & ~mask);
159 	writel(val, res->vp_regs + reg_id);
160 }
161 
162 static inline u32 mixer_reg_read(struct mixer_resources *res, u32 reg_id)
163 {
164 	return readl(res->mixer_regs + reg_id);
165 }
166 
167 static inline void mixer_reg_write(struct mixer_resources *res, u32 reg_id,
168 				 u32 val)
169 {
170 	writel(val, res->mixer_regs + reg_id);
171 }
172 
173 static inline void mixer_reg_writemask(struct mixer_resources *res,
174 				 u32 reg_id, u32 val, u32 mask)
175 {
176 	u32 old = mixer_reg_read(res, reg_id);
177 
178 	val = (val & mask) | (old & ~mask);
179 	writel(val, res->mixer_regs + reg_id);
180 }
181 
182 static void mixer_regs_dump(struct mixer_context *ctx)
183 {
184 #define DUMPREG(reg_id) \
185 do { \
186 	DRM_DEBUG_KMS(#reg_id " = %08x\n", \
187 		(u32)readl(ctx->mixer_res.mixer_regs + reg_id)); \
188 } while (0)
189 
190 	DUMPREG(MXR_STATUS);
191 	DUMPREG(MXR_CFG);
192 	DUMPREG(MXR_INT_EN);
193 	DUMPREG(MXR_INT_STATUS);
194 
195 	DUMPREG(MXR_LAYER_CFG);
196 	DUMPREG(MXR_VIDEO_CFG);
197 
198 	DUMPREG(MXR_GRAPHIC0_CFG);
199 	DUMPREG(MXR_GRAPHIC0_BASE);
200 	DUMPREG(MXR_GRAPHIC0_SPAN);
201 	DUMPREG(MXR_GRAPHIC0_WH);
202 	DUMPREG(MXR_GRAPHIC0_SXY);
203 	DUMPREG(MXR_GRAPHIC0_DXY);
204 
205 	DUMPREG(MXR_GRAPHIC1_CFG);
206 	DUMPREG(MXR_GRAPHIC1_BASE);
207 	DUMPREG(MXR_GRAPHIC1_SPAN);
208 	DUMPREG(MXR_GRAPHIC1_WH);
209 	DUMPREG(MXR_GRAPHIC1_SXY);
210 	DUMPREG(MXR_GRAPHIC1_DXY);
211 #undef DUMPREG
212 }
213 
214 static void vp_regs_dump(struct mixer_context *ctx)
215 {
216 #define DUMPREG(reg_id) \
217 do { \
218 	DRM_DEBUG_KMS(#reg_id " = %08x\n", \
219 		(u32) readl(ctx->mixer_res.vp_regs + reg_id)); \
220 } while (0)
221 
222 	DUMPREG(VP_ENABLE);
223 	DUMPREG(VP_SRESET);
224 	DUMPREG(VP_SHADOW_UPDATE);
225 	DUMPREG(VP_FIELD_ID);
226 	DUMPREG(VP_MODE);
227 	DUMPREG(VP_IMG_SIZE_Y);
228 	DUMPREG(VP_IMG_SIZE_C);
229 	DUMPREG(VP_PER_RATE_CTRL);
230 	DUMPREG(VP_TOP_Y_PTR);
231 	DUMPREG(VP_BOT_Y_PTR);
232 	DUMPREG(VP_TOP_C_PTR);
233 	DUMPREG(VP_BOT_C_PTR);
234 	DUMPREG(VP_ENDIAN_MODE);
235 	DUMPREG(VP_SRC_H_POSITION);
236 	DUMPREG(VP_SRC_V_POSITION);
237 	DUMPREG(VP_SRC_WIDTH);
238 	DUMPREG(VP_SRC_HEIGHT);
239 	DUMPREG(VP_DST_H_POSITION);
240 	DUMPREG(VP_DST_V_POSITION);
241 	DUMPREG(VP_DST_WIDTH);
242 	DUMPREG(VP_DST_HEIGHT);
243 	DUMPREG(VP_H_RATIO);
244 	DUMPREG(VP_V_RATIO);
245 
246 #undef DUMPREG
247 }
248 
249 static inline void vp_filter_set(struct mixer_resources *res,
250 		int reg_id, const u8 *data, unsigned int size)
251 {
252 	/* assure 4-byte align */
253 	BUG_ON(size & 3);
254 	for (; size; size -= 4, reg_id += 4, data += 4) {
255 		u32 val = (data[0] << 24) |  (data[1] << 16) |
256 			(data[2] << 8) | data[3];
257 		vp_reg_write(res, reg_id, val);
258 	}
259 }
260 
261 static void vp_default_filter(struct mixer_resources *res)
262 {
263 	vp_filter_set(res, VP_POLY8_Y0_LL,
264 		filter_y_horiz_tap8, sizeof(filter_y_horiz_tap8));
265 	vp_filter_set(res, VP_POLY4_Y0_LL,
266 		filter_y_vert_tap4, sizeof(filter_y_vert_tap4));
267 	vp_filter_set(res, VP_POLY4_C0_LL,
268 		filter_cr_horiz_tap4, sizeof(filter_cr_horiz_tap4));
269 }
270 
271 static void mixer_vsync_set_update(struct mixer_context *ctx, bool enable)
272 {
273 	struct mixer_resources *res = &ctx->mixer_res;
274 
275 	/* block update on vsync */
276 	mixer_reg_writemask(res, MXR_STATUS, enable ?
277 			MXR_STATUS_SYNC_ENABLE : 0, MXR_STATUS_SYNC_ENABLE);
278 
279 	if (ctx->vp_enabled)
280 		vp_reg_write(res, VP_SHADOW_UPDATE, enable ?
281 			VP_SHADOW_UPDATE_ENABLE : 0);
282 }
283 
284 static void mixer_cfg_scan(struct mixer_context *ctx, unsigned int height)
285 {
286 	struct mixer_resources *res = &ctx->mixer_res;
287 	u32 val;
288 
289 	/* choosing between interlace and progressive mode */
290 	val = (ctx->interlace ? MXR_CFG_SCAN_INTERLACE :
291 				MXR_CFG_SCAN_PROGRASSIVE);
292 
293 	if (ctx->mxr_ver != MXR_VER_128_0_0_184) {
294 		/* choosing between proper HD and SD mode */
295 		if (height <= 480)
296 			val |= MXR_CFG_SCAN_NTSC | MXR_CFG_SCAN_SD;
297 		else if (height <= 576)
298 			val |= MXR_CFG_SCAN_PAL | MXR_CFG_SCAN_SD;
299 		else if (height <= 720)
300 			val |= MXR_CFG_SCAN_HD_720 | MXR_CFG_SCAN_HD;
301 		else if (height <= 1080)
302 			val |= MXR_CFG_SCAN_HD_1080 | MXR_CFG_SCAN_HD;
303 		else
304 			val |= MXR_CFG_SCAN_HD_720 | MXR_CFG_SCAN_HD;
305 	}
306 
307 	mixer_reg_writemask(res, MXR_CFG, val, MXR_CFG_SCAN_MASK);
308 }
309 
310 static void mixer_cfg_rgb_fmt(struct mixer_context *ctx, unsigned int height)
311 {
312 	struct mixer_resources *res = &ctx->mixer_res;
313 	u32 val;
314 
315 	if (height == 480) {
316 		val = MXR_CFG_RGB601_0_255;
317 	} else if (height == 576) {
318 		val = MXR_CFG_RGB601_0_255;
319 	} else if (height == 720) {
320 		val = MXR_CFG_RGB709_16_235;
321 		mixer_reg_write(res, MXR_CM_COEFF_Y,
322 				(1 << 30) | (94 << 20) | (314 << 10) |
323 				(32 << 0));
324 		mixer_reg_write(res, MXR_CM_COEFF_CB,
325 				(972 << 20) | (851 << 10) | (225 << 0));
326 		mixer_reg_write(res, MXR_CM_COEFF_CR,
327 				(225 << 20) | (820 << 10) | (1004 << 0));
328 	} else if (height == 1080) {
329 		val = MXR_CFG_RGB709_16_235;
330 		mixer_reg_write(res, MXR_CM_COEFF_Y,
331 				(1 << 30) | (94 << 20) | (314 << 10) |
332 				(32 << 0));
333 		mixer_reg_write(res, MXR_CM_COEFF_CB,
334 				(972 << 20) | (851 << 10) | (225 << 0));
335 		mixer_reg_write(res, MXR_CM_COEFF_CR,
336 				(225 << 20) | (820 << 10) | (1004 << 0));
337 	} else {
338 		val = MXR_CFG_RGB709_16_235;
339 		mixer_reg_write(res, MXR_CM_COEFF_Y,
340 				(1 << 30) | (94 << 20) | (314 << 10) |
341 				(32 << 0));
342 		mixer_reg_write(res, MXR_CM_COEFF_CB,
343 				(972 << 20) | (851 << 10) | (225 << 0));
344 		mixer_reg_write(res, MXR_CM_COEFF_CR,
345 				(225 << 20) | (820 << 10) | (1004 << 0));
346 	}
347 
348 	mixer_reg_writemask(res, MXR_CFG, val, MXR_CFG_RGB_FMT_MASK);
349 }
350 
351 static void mixer_cfg_layer(struct mixer_context *ctx, int win, bool enable)
352 {
353 	struct mixer_resources *res = &ctx->mixer_res;
354 	u32 val = enable ? ~0 : 0;
355 
356 	switch (win) {
357 	case 0:
358 		mixer_reg_writemask(res, MXR_CFG, val, MXR_CFG_GRP0_ENABLE);
359 		break;
360 	case 1:
361 		mixer_reg_writemask(res, MXR_CFG, val, MXR_CFG_GRP1_ENABLE);
362 		break;
363 	case 2:
364 		if (ctx->vp_enabled) {
365 			vp_reg_writemask(res, VP_ENABLE, val, VP_ENABLE_ON);
366 			mixer_reg_writemask(res, MXR_CFG, val,
367 				MXR_CFG_VP_ENABLE);
368 
369 			/* control blending of graphic layer 0 */
370 			mixer_reg_writemask(res, MXR_GRAPHIC_CFG(0), val,
371 					MXR_GRP_CFG_BLEND_PRE_MUL |
372 					MXR_GRP_CFG_PIXEL_BLEND_EN);
373 		}
374 		break;
375 	}
376 }
377 
378 static void mixer_run(struct mixer_context *ctx)
379 {
380 	struct mixer_resources *res = &ctx->mixer_res;
381 
382 	mixer_reg_writemask(res, MXR_STATUS, ~0, MXR_STATUS_REG_RUN);
383 
384 	mixer_regs_dump(ctx);
385 }
386 
387 static void mixer_stop(struct mixer_context *ctx)
388 {
389 	struct mixer_resources *res = &ctx->mixer_res;
390 	int timeout = 20;
391 
392 	mixer_reg_writemask(res, MXR_STATUS, 0, MXR_STATUS_REG_RUN);
393 
394 	while (!(mixer_reg_read(res, MXR_STATUS) & MXR_STATUS_REG_IDLE) &&
395 			--timeout)
396 		usleep_range(10000, 12000);
397 
398 	mixer_regs_dump(ctx);
399 }
400 
401 static void vp_video_buffer(struct mixer_context *ctx, int win)
402 {
403 	struct mixer_resources *res = &ctx->mixer_res;
404 	unsigned long flags;
405 	struct hdmi_win_data *win_data;
406 	unsigned int x_ratio, y_ratio;
407 	unsigned int buf_num = 1;
408 	dma_addr_t luma_addr[2], chroma_addr[2];
409 	bool tiled_mode = false;
410 	bool crcb_mode = false;
411 	u32 val;
412 
413 	win_data = &ctx->win_data[win];
414 
415 	switch (win_data->pixel_format) {
416 	case DRM_FORMAT_NV12MT:
417 		tiled_mode = true;
418 	case DRM_FORMAT_NV12:
419 		crcb_mode = false;
420 		buf_num = 2;
421 		break;
422 	/* TODO: single buffer format NV12, NV21 */
423 	default:
424 		/* ignore pixel format at disable time */
425 		if (!win_data->dma_addr)
426 			break;
427 
428 		DRM_ERROR("pixel format for vp is wrong [%d].\n",
429 				win_data->pixel_format);
430 		return;
431 	}
432 
433 	/* scaling feature: (src << 16) / dst */
434 	x_ratio = (win_data->src_width << 16) / win_data->crtc_width;
435 	y_ratio = (win_data->src_height << 16) / win_data->crtc_height;
436 
437 	if (buf_num == 2) {
438 		luma_addr[0] = win_data->dma_addr;
439 		chroma_addr[0] = win_data->chroma_dma_addr;
440 	} else {
441 		luma_addr[0] = win_data->dma_addr;
442 		chroma_addr[0] = win_data->dma_addr
443 			+ (win_data->fb_width * win_data->fb_height);
444 	}
445 
446 	if (win_data->scan_flags & DRM_MODE_FLAG_INTERLACE) {
447 		ctx->interlace = true;
448 		if (tiled_mode) {
449 			luma_addr[1] = luma_addr[0] + 0x40;
450 			chroma_addr[1] = chroma_addr[0] + 0x40;
451 		} else {
452 			luma_addr[1] = luma_addr[0] + win_data->fb_width;
453 			chroma_addr[1] = chroma_addr[0] + win_data->fb_width;
454 		}
455 	} else {
456 		ctx->interlace = false;
457 		luma_addr[1] = 0;
458 		chroma_addr[1] = 0;
459 	}
460 
461 	spin_lock_irqsave(&res->reg_slock, flags);
462 	mixer_vsync_set_update(ctx, false);
463 
464 	/* interlace or progressive scan mode */
465 	val = (ctx->interlace ? ~0 : 0);
466 	vp_reg_writemask(res, VP_MODE, val, VP_MODE_LINE_SKIP);
467 
468 	/* setup format */
469 	val = (crcb_mode ? VP_MODE_NV21 : VP_MODE_NV12);
470 	val |= (tiled_mode ? VP_MODE_MEM_TILED : VP_MODE_MEM_LINEAR);
471 	vp_reg_writemask(res, VP_MODE, val, VP_MODE_FMT_MASK);
472 
473 	/* setting size of input image */
474 	vp_reg_write(res, VP_IMG_SIZE_Y, VP_IMG_HSIZE(win_data->fb_width) |
475 		VP_IMG_VSIZE(win_data->fb_height));
476 	/* chroma height has to reduced by 2 to avoid chroma distorions */
477 	vp_reg_write(res, VP_IMG_SIZE_C, VP_IMG_HSIZE(win_data->fb_width) |
478 		VP_IMG_VSIZE(win_data->fb_height / 2));
479 
480 	vp_reg_write(res, VP_SRC_WIDTH, win_data->src_width);
481 	vp_reg_write(res, VP_SRC_HEIGHT, win_data->src_height);
482 	vp_reg_write(res, VP_SRC_H_POSITION,
483 			VP_SRC_H_POSITION_VAL(win_data->fb_x));
484 	vp_reg_write(res, VP_SRC_V_POSITION, win_data->fb_y);
485 
486 	vp_reg_write(res, VP_DST_WIDTH, win_data->crtc_width);
487 	vp_reg_write(res, VP_DST_H_POSITION, win_data->crtc_x);
488 	if (ctx->interlace) {
489 		vp_reg_write(res, VP_DST_HEIGHT, win_data->crtc_height / 2);
490 		vp_reg_write(res, VP_DST_V_POSITION, win_data->crtc_y / 2);
491 	} else {
492 		vp_reg_write(res, VP_DST_HEIGHT, win_data->crtc_height);
493 		vp_reg_write(res, VP_DST_V_POSITION, win_data->crtc_y);
494 	}
495 
496 	vp_reg_write(res, VP_H_RATIO, x_ratio);
497 	vp_reg_write(res, VP_V_RATIO, y_ratio);
498 
499 	vp_reg_write(res, VP_ENDIAN_MODE, VP_ENDIAN_MODE_LITTLE);
500 
501 	/* set buffer address to vp */
502 	vp_reg_write(res, VP_TOP_Y_PTR, luma_addr[0]);
503 	vp_reg_write(res, VP_BOT_Y_PTR, luma_addr[1]);
504 	vp_reg_write(res, VP_TOP_C_PTR, chroma_addr[0]);
505 	vp_reg_write(res, VP_BOT_C_PTR, chroma_addr[1]);
506 
507 	mixer_cfg_scan(ctx, win_data->mode_height);
508 	mixer_cfg_rgb_fmt(ctx, win_data->mode_height);
509 	mixer_cfg_layer(ctx, win, true);
510 	mixer_run(ctx);
511 
512 	mixer_vsync_set_update(ctx, true);
513 	spin_unlock_irqrestore(&res->reg_slock, flags);
514 
515 	vp_regs_dump(ctx);
516 }
517 
518 static void mixer_layer_update(struct mixer_context *ctx)
519 {
520 	struct mixer_resources *res = &ctx->mixer_res;
521 
522 	mixer_reg_writemask(res, MXR_CFG, ~0, MXR_CFG_LAYER_UPDATE);
523 }
524 
525 static void mixer_graph_buffer(struct mixer_context *ctx, int win)
526 {
527 	struct mixer_resources *res = &ctx->mixer_res;
528 	unsigned long flags;
529 	struct hdmi_win_data *win_data;
530 	unsigned int x_ratio, y_ratio;
531 	unsigned int src_x_offset, src_y_offset, dst_x_offset, dst_y_offset;
532 	dma_addr_t dma_addr;
533 	unsigned int fmt;
534 	u32 val;
535 
536 	win_data = &ctx->win_data[win];
537 
538 	#define RGB565 4
539 	#define ARGB1555 5
540 	#define ARGB4444 6
541 	#define ARGB8888 7
542 
543 	switch (win_data->bpp) {
544 	case 16:
545 		fmt = ARGB4444;
546 		break;
547 	case 32:
548 		fmt = ARGB8888;
549 		break;
550 	default:
551 		fmt = ARGB8888;
552 	}
553 
554 	/* 2x scaling feature */
555 	x_ratio = 0;
556 	y_ratio = 0;
557 
558 	dst_x_offset = win_data->crtc_x;
559 	dst_y_offset = win_data->crtc_y;
560 
561 	/* converting dma address base and source offset */
562 	dma_addr = win_data->dma_addr
563 		+ (win_data->fb_x * win_data->bpp >> 3)
564 		+ (win_data->fb_y * win_data->fb_width * win_data->bpp >> 3);
565 	src_x_offset = 0;
566 	src_y_offset = 0;
567 
568 	if (win_data->scan_flags & DRM_MODE_FLAG_INTERLACE)
569 		ctx->interlace = true;
570 	else
571 		ctx->interlace = false;
572 
573 	spin_lock_irqsave(&res->reg_slock, flags);
574 	mixer_vsync_set_update(ctx, false);
575 
576 	/* setup format */
577 	mixer_reg_writemask(res, MXR_GRAPHIC_CFG(win),
578 		MXR_GRP_CFG_FORMAT_VAL(fmt), MXR_GRP_CFG_FORMAT_MASK);
579 
580 	/* setup geometry */
581 	mixer_reg_write(res, MXR_GRAPHIC_SPAN(win), win_data->fb_width);
582 
583 	/* setup display size */
584 	if (ctx->mxr_ver == MXR_VER_128_0_0_184 &&
585 		win == MIXER_DEFAULT_WIN) {
586 		val  = MXR_MXR_RES_HEIGHT(win_data->fb_height);
587 		val |= MXR_MXR_RES_WIDTH(win_data->fb_width);
588 		mixer_reg_write(res, MXR_RESOLUTION, val);
589 	}
590 
591 	val  = MXR_GRP_WH_WIDTH(win_data->crtc_width);
592 	val |= MXR_GRP_WH_HEIGHT(win_data->crtc_height);
593 	val |= MXR_GRP_WH_H_SCALE(x_ratio);
594 	val |= MXR_GRP_WH_V_SCALE(y_ratio);
595 	mixer_reg_write(res, MXR_GRAPHIC_WH(win), val);
596 
597 	/* setup offsets in source image */
598 	val  = MXR_GRP_SXY_SX(src_x_offset);
599 	val |= MXR_GRP_SXY_SY(src_y_offset);
600 	mixer_reg_write(res, MXR_GRAPHIC_SXY(win), val);
601 
602 	/* setup offsets in display image */
603 	val  = MXR_GRP_DXY_DX(dst_x_offset);
604 	val |= MXR_GRP_DXY_DY(dst_y_offset);
605 	mixer_reg_write(res, MXR_GRAPHIC_DXY(win), val);
606 
607 	/* set buffer address to mixer */
608 	mixer_reg_write(res, MXR_GRAPHIC_BASE(win), dma_addr);
609 
610 	mixer_cfg_scan(ctx, win_data->mode_height);
611 	mixer_cfg_rgb_fmt(ctx, win_data->mode_height);
612 	mixer_cfg_layer(ctx, win, true);
613 
614 	/* layer update mandatory for mixer 16.0.33.0 */
615 	if (ctx->mxr_ver == MXR_VER_16_0_33_0 ||
616 		ctx->mxr_ver == MXR_VER_128_0_0_184)
617 		mixer_layer_update(ctx);
618 
619 	mixer_run(ctx);
620 
621 	mixer_vsync_set_update(ctx, true);
622 	spin_unlock_irqrestore(&res->reg_slock, flags);
623 }
624 
625 static void vp_win_reset(struct mixer_context *ctx)
626 {
627 	struct mixer_resources *res = &ctx->mixer_res;
628 	int tries = 100;
629 
630 	vp_reg_write(res, VP_SRESET, VP_SRESET_PROCESSING);
631 	for (tries = 100; tries; --tries) {
632 		/* waiting until VP_SRESET_PROCESSING is 0 */
633 		if (~vp_reg_read(res, VP_SRESET) & VP_SRESET_PROCESSING)
634 			break;
635 		usleep_range(10000, 12000);
636 	}
637 	WARN(tries == 0, "failed to reset Video Processor\n");
638 }
639 
640 static void mixer_win_reset(struct mixer_context *ctx)
641 {
642 	struct mixer_resources *res = &ctx->mixer_res;
643 	unsigned long flags;
644 	u32 val; /* value stored to register */
645 
646 	spin_lock_irqsave(&res->reg_slock, flags);
647 	mixer_vsync_set_update(ctx, false);
648 
649 	mixer_reg_writemask(res, MXR_CFG, MXR_CFG_DST_HDMI, MXR_CFG_DST_MASK);
650 
651 	/* set output in RGB888 mode */
652 	mixer_reg_writemask(res, MXR_CFG, MXR_CFG_OUT_RGB888, MXR_CFG_OUT_MASK);
653 
654 	/* 16 beat burst in DMA */
655 	mixer_reg_writemask(res, MXR_STATUS, MXR_STATUS_16_BURST,
656 		MXR_STATUS_BURST_MASK);
657 
658 	/* setting default layer priority: layer1 > layer0 > video
659 	 * because typical usage scenario would be
660 	 * layer1 - OSD
661 	 * layer0 - framebuffer
662 	 * video - video overlay
663 	 */
664 	val = MXR_LAYER_CFG_GRP1_VAL(3);
665 	val |= MXR_LAYER_CFG_GRP0_VAL(2);
666 	if (ctx->vp_enabled)
667 		val |= MXR_LAYER_CFG_VP_VAL(1);
668 	mixer_reg_write(res, MXR_LAYER_CFG, val);
669 
670 	/* setting background color */
671 	mixer_reg_write(res, MXR_BG_COLOR0, 0x008080);
672 	mixer_reg_write(res, MXR_BG_COLOR1, 0x008080);
673 	mixer_reg_write(res, MXR_BG_COLOR2, 0x008080);
674 
675 	/* setting graphical layers */
676 	val  = MXR_GRP_CFG_COLOR_KEY_DISABLE; /* no blank key */
677 	val |= MXR_GRP_CFG_WIN_BLEND_EN;
678 	val |= MXR_GRP_CFG_ALPHA_VAL(0xff); /* non-transparent alpha */
679 
680 	/* Don't blend layer 0 onto the mixer background */
681 	mixer_reg_write(res, MXR_GRAPHIC_CFG(0), val);
682 
683 	/* Blend layer 1 into layer 0 */
684 	val |= MXR_GRP_CFG_BLEND_PRE_MUL;
685 	val |= MXR_GRP_CFG_PIXEL_BLEND_EN;
686 	mixer_reg_write(res, MXR_GRAPHIC_CFG(1), val);
687 
688 	/* setting video layers */
689 	val = MXR_GRP_CFG_ALPHA_VAL(0);
690 	mixer_reg_write(res, MXR_VIDEO_CFG, val);
691 
692 	if (ctx->vp_enabled) {
693 		/* configuration of Video Processor Registers */
694 		vp_win_reset(ctx);
695 		vp_default_filter(res);
696 	}
697 
698 	/* disable all layers */
699 	mixer_reg_writemask(res, MXR_CFG, 0, MXR_CFG_GRP0_ENABLE);
700 	mixer_reg_writemask(res, MXR_CFG, 0, MXR_CFG_GRP1_ENABLE);
701 	if (ctx->vp_enabled)
702 		mixer_reg_writemask(res, MXR_CFG, 0, MXR_CFG_VP_ENABLE);
703 
704 	mixer_vsync_set_update(ctx, true);
705 	spin_unlock_irqrestore(&res->reg_slock, flags);
706 }
707 
708 static irqreturn_t mixer_irq_handler(int irq, void *arg)
709 {
710 	struct mixer_context *ctx = arg;
711 	struct mixer_resources *res = &ctx->mixer_res;
712 	u32 val, base, shadow;
713 
714 	spin_lock(&res->reg_slock);
715 
716 	/* read interrupt status for handling and clearing flags for VSYNC */
717 	val = mixer_reg_read(res, MXR_INT_STATUS);
718 
719 	/* handling VSYNC */
720 	if (val & MXR_INT_STATUS_VSYNC) {
721 		/* interlace scan need to check shadow register */
722 		if (ctx->interlace) {
723 			base = mixer_reg_read(res, MXR_GRAPHIC_BASE(0));
724 			shadow = mixer_reg_read(res, MXR_GRAPHIC_BASE_S(0));
725 			if (base != shadow)
726 				goto out;
727 
728 			base = mixer_reg_read(res, MXR_GRAPHIC_BASE(1));
729 			shadow = mixer_reg_read(res, MXR_GRAPHIC_BASE_S(1));
730 			if (base != shadow)
731 				goto out;
732 		}
733 
734 		drm_handle_vblank(ctx->drm_dev, ctx->pipe);
735 		exynos_drm_crtc_finish_pageflip(ctx->drm_dev, ctx->pipe);
736 
737 		/* set wait vsync event to zero and wake up queue. */
738 		if (atomic_read(&ctx->wait_vsync_event)) {
739 			atomic_set(&ctx->wait_vsync_event, 0);
740 			wake_up(&ctx->wait_vsync_queue);
741 		}
742 	}
743 
744 out:
745 	/* clear interrupts */
746 	if (~val & MXR_INT_EN_VSYNC) {
747 		/* vsync interrupt use different bit for read and clear */
748 		val &= ~MXR_INT_EN_VSYNC;
749 		val |= MXR_INT_CLEAR_VSYNC;
750 	}
751 	mixer_reg_write(res, MXR_INT_STATUS, val);
752 
753 	spin_unlock(&res->reg_slock);
754 
755 	return IRQ_HANDLED;
756 }
757 
758 static int mixer_resources_init(struct mixer_context *mixer_ctx)
759 {
760 	struct device *dev = &mixer_ctx->pdev->dev;
761 	struct mixer_resources *mixer_res = &mixer_ctx->mixer_res;
762 	struct resource *res;
763 	int ret;
764 
765 	spin_lock_init(&mixer_res->reg_slock);
766 
767 	mixer_res->mixer = devm_clk_get(dev, "mixer");
768 	if (IS_ERR(mixer_res->mixer)) {
769 		dev_err(dev, "failed to get clock 'mixer'\n");
770 		return -ENODEV;
771 	}
772 
773 	mixer_res->sclk_hdmi = devm_clk_get(dev, "sclk_hdmi");
774 	if (IS_ERR(mixer_res->sclk_hdmi)) {
775 		dev_err(dev, "failed to get clock 'sclk_hdmi'\n");
776 		return -ENODEV;
777 	}
778 	res = platform_get_resource(mixer_ctx->pdev, IORESOURCE_MEM, 0);
779 	if (res == NULL) {
780 		dev_err(dev, "get memory resource failed.\n");
781 		return -ENXIO;
782 	}
783 
784 	mixer_res->mixer_regs = devm_ioremap(dev, res->start,
785 							resource_size(res));
786 	if (mixer_res->mixer_regs == NULL) {
787 		dev_err(dev, "register mapping failed.\n");
788 		return -ENXIO;
789 	}
790 
791 	res = platform_get_resource(mixer_ctx->pdev, IORESOURCE_IRQ, 0);
792 	if (res == NULL) {
793 		dev_err(dev, "get interrupt resource failed.\n");
794 		return -ENXIO;
795 	}
796 
797 	ret = devm_request_irq(dev, res->start, mixer_irq_handler,
798 						0, "drm_mixer", mixer_ctx);
799 	if (ret) {
800 		dev_err(dev, "request interrupt failed.\n");
801 		return ret;
802 	}
803 	mixer_res->irq = res->start;
804 
805 	return 0;
806 }
807 
808 static int vp_resources_init(struct mixer_context *mixer_ctx)
809 {
810 	struct device *dev = &mixer_ctx->pdev->dev;
811 	struct mixer_resources *mixer_res = &mixer_ctx->mixer_res;
812 	struct resource *res;
813 
814 	mixer_res->vp = devm_clk_get(dev, "vp");
815 	if (IS_ERR(mixer_res->vp)) {
816 		dev_err(dev, "failed to get clock 'vp'\n");
817 		return -ENODEV;
818 	}
819 
820 	if (mixer_ctx->has_sclk) {
821 		mixer_res->sclk_mixer = devm_clk_get(dev, "sclk_mixer");
822 		if (IS_ERR(mixer_res->sclk_mixer)) {
823 			dev_err(dev, "failed to get clock 'sclk_mixer'\n");
824 			return -ENODEV;
825 		}
826 		mixer_res->mout_mixer = devm_clk_get(dev, "mout_mixer");
827 		if (IS_ERR(mixer_res->mout_mixer)) {
828 			dev_err(dev, "failed to get clock 'mout_mixer'\n");
829 			return -ENODEV;
830 		}
831 
832 		if (mixer_res->sclk_hdmi && mixer_res->mout_mixer)
833 			clk_set_parent(mixer_res->mout_mixer,
834 				       mixer_res->sclk_hdmi);
835 	}
836 
837 	res = platform_get_resource(mixer_ctx->pdev, IORESOURCE_MEM, 1);
838 	if (res == NULL) {
839 		dev_err(dev, "get memory resource failed.\n");
840 		return -ENXIO;
841 	}
842 
843 	mixer_res->vp_regs = devm_ioremap(dev, res->start,
844 							resource_size(res));
845 	if (mixer_res->vp_regs == NULL) {
846 		dev_err(dev, "register mapping failed.\n");
847 		return -ENXIO;
848 	}
849 
850 	return 0;
851 }
852 
853 static int mixer_initialize(struct exynos_drm_manager *mgr,
854 			struct drm_device *drm_dev)
855 {
856 	int ret;
857 	struct mixer_context *mixer_ctx = mgr->ctx;
858 	struct exynos_drm_private *priv;
859 	priv = drm_dev->dev_private;
860 
861 	mgr->drm_dev = mixer_ctx->drm_dev = drm_dev;
862 	mgr->pipe = mixer_ctx->pipe = priv->pipe++;
863 
864 	/* acquire resources: regs, irqs, clocks */
865 	ret = mixer_resources_init(mixer_ctx);
866 	if (ret) {
867 		DRM_ERROR("mixer_resources_init failed ret=%d\n", ret);
868 		return ret;
869 	}
870 
871 	if (mixer_ctx->vp_enabled) {
872 		/* acquire vp resources: regs, irqs, clocks */
873 		ret = vp_resources_init(mixer_ctx);
874 		if (ret) {
875 			DRM_ERROR("vp_resources_init failed ret=%d\n", ret);
876 			return ret;
877 		}
878 	}
879 
880 	if (!is_drm_iommu_supported(mixer_ctx->drm_dev))
881 		return 0;
882 
883 	return drm_iommu_attach_device(mixer_ctx->drm_dev, mixer_ctx->dev);
884 }
885 
886 static void mixer_mgr_remove(struct exynos_drm_manager *mgr)
887 {
888 	struct mixer_context *mixer_ctx = mgr->ctx;
889 
890 	if (is_drm_iommu_supported(mixer_ctx->drm_dev))
891 		drm_iommu_detach_device(mixer_ctx->drm_dev, mixer_ctx->dev);
892 }
893 
894 static int mixer_enable_vblank(struct exynos_drm_manager *mgr)
895 {
896 	struct mixer_context *mixer_ctx = mgr->ctx;
897 	struct mixer_resources *res = &mixer_ctx->mixer_res;
898 
899 	if (!mixer_ctx->powered) {
900 		mixer_ctx->int_en |= MXR_INT_EN_VSYNC;
901 		return 0;
902 	}
903 
904 	/* enable vsync interrupt */
905 	mixer_reg_writemask(res, MXR_INT_EN, MXR_INT_EN_VSYNC,
906 			MXR_INT_EN_VSYNC);
907 
908 	return 0;
909 }
910 
911 static void mixer_disable_vblank(struct exynos_drm_manager *mgr)
912 {
913 	struct mixer_context *mixer_ctx = mgr->ctx;
914 	struct mixer_resources *res = &mixer_ctx->mixer_res;
915 
916 	/* disable vsync interrupt */
917 	mixer_reg_writemask(res, MXR_INT_EN, 0, MXR_INT_EN_VSYNC);
918 }
919 
920 static void mixer_win_mode_set(struct exynos_drm_manager *mgr,
921 			struct exynos_drm_overlay *overlay)
922 {
923 	struct mixer_context *mixer_ctx = mgr->ctx;
924 	struct hdmi_win_data *win_data;
925 	int win;
926 
927 	if (!overlay) {
928 		DRM_ERROR("overlay is NULL\n");
929 		return;
930 	}
931 
932 	DRM_DEBUG_KMS("set [%d]x[%d] at (%d,%d) to [%d]x[%d] at (%d,%d)\n",
933 				 overlay->fb_width, overlay->fb_height,
934 				 overlay->fb_x, overlay->fb_y,
935 				 overlay->crtc_width, overlay->crtc_height,
936 				 overlay->crtc_x, overlay->crtc_y);
937 
938 	win = overlay->zpos;
939 	if (win == DEFAULT_ZPOS)
940 		win = MIXER_DEFAULT_WIN;
941 
942 	if (win < 0 || win >= MIXER_WIN_NR) {
943 		DRM_ERROR("mixer window[%d] is wrong\n", win);
944 		return;
945 	}
946 
947 	win_data = &mixer_ctx->win_data[win];
948 
949 	win_data->dma_addr = overlay->dma_addr[0];
950 	win_data->chroma_dma_addr = overlay->dma_addr[1];
951 	win_data->pixel_format = overlay->pixel_format;
952 	win_data->bpp = overlay->bpp;
953 
954 	win_data->crtc_x = overlay->crtc_x;
955 	win_data->crtc_y = overlay->crtc_y;
956 	win_data->crtc_width = overlay->crtc_width;
957 	win_data->crtc_height = overlay->crtc_height;
958 
959 	win_data->fb_x = overlay->fb_x;
960 	win_data->fb_y = overlay->fb_y;
961 	win_data->fb_width = overlay->fb_width;
962 	win_data->fb_height = overlay->fb_height;
963 	win_data->src_width = overlay->src_width;
964 	win_data->src_height = overlay->src_height;
965 
966 	win_data->mode_width = overlay->mode_width;
967 	win_data->mode_height = overlay->mode_height;
968 
969 	win_data->scan_flags = overlay->scan_flag;
970 }
971 
972 static void mixer_win_commit(struct exynos_drm_manager *mgr, int zpos)
973 {
974 	struct mixer_context *mixer_ctx = mgr->ctx;
975 	int win = zpos == DEFAULT_ZPOS ? MIXER_DEFAULT_WIN : zpos;
976 
977 	DRM_DEBUG_KMS("win: %d\n", win);
978 
979 	mutex_lock(&mixer_ctx->mixer_mutex);
980 	if (!mixer_ctx->powered) {
981 		mutex_unlock(&mixer_ctx->mixer_mutex);
982 		return;
983 	}
984 	mutex_unlock(&mixer_ctx->mixer_mutex);
985 
986 	if (win > 1 && mixer_ctx->vp_enabled)
987 		vp_video_buffer(mixer_ctx, win);
988 	else
989 		mixer_graph_buffer(mixer_ctx, win);
990 
991 	mixer_ctx->win_data[win].enabled = true;
992 }
993 
994 static void mixer_win_disable(struct exynos_drm_manager *mgr, int zpos)
995 {
996 	struct mixer_context *mixer_ctx = mgr->ctx;
997 	struct mixer_resources *res = &mixer_ctx->mixer_res;
998 	int win = zpos == DEFAULT_ZPOS ? MIXER_DEFAULT_WIN : zpos;
999 	unsigned long flags;
1000 
1001 	DRM_DEBUG_KMS("win: %d\n", win);
1002 
1003 	mutex_lock(&mixer_ctx->mixer_mutex);
1004 	if (!mixer_ctx->powered) {
1005 		mutex_unlock(&mixer_ctx->mixer_mutex);
1006 		mixer_ctx->win_data[win].resume = false;
1007 		return;
1008 	}
1009 	mutex_unlock(&mixer_ctx->mixer_mutex);
1010 
1011 	spin_lock_irqsave(&res->reg_slock, flags);
1012 	mixer_vsync_set_update(mixer_ctx, false);
1013 
1014 	mixer_cfg_layer(mixer_ctx, win, false);
1015 
1016 	mixer_vsync_set_update(mixer_ctx, true);
1017 	spin_unlock_irqrestore(&res->reg_slock, flags);
1018 
1019 	mixer_ctx->win_data[win].enabled = false;
1020 }
1021 
1022 static void mixer_wait_for_vblank(struct exynos_drm_manager *mgr)
1023 {
1024 	struct mixer_context *mixer_ctx = mgr->ctx;
1025 
1026 	mutex_lock(&mixer_ctx->mixer_mutex);
1027 	if (!mixer_ctx->powered) {
1028 		mutex_unlock(&mixer_ctx->mixer_mutex);
1029 		return;
1030 	}
1031 	mutex_unlock(&mixer_ctx->mixer_mutex);
1032 
1033 	drm_vblank_get(mgr->crtc->dev, mixer_ctx->pipe);
1034 
1035 	atomic_set(&mixer_ctx->wait_vsync_event, 1);
1036 
1037 	/*
1038 	 * wait for MIXER to signal VSYNC interrupt or return after
1039 	 * timeout which is set to 50ms (refresh rate of 20).
1040 	 */
1041 	if (!wait_event_timeout(mixer_ctx->wait_vsync_queue,
1042 				!atomic_read(&mixer_ctx->wait_vsync_event),
1043 				HZ/20))
1044 		DRM_DEBUG_KMS("vblank wait timed out.\n");
1045 
1046 	drm_vblank_put(mgr->crtc->dev, mixer_ctx->pipe);
1047 }
1048 
1049 static void mixer_window_suspend(struct exynos_drm_manager *mgr)
1050 {
1051 	struct mixer_context *ctx = mgr->ctx;
1052 	struct hdmi_win_data *win_data;
1053 	int i;
1054 
1055 	for (i = 0; i < MIXER_WIN_NR; i++) {
1056 		win_data = &ctx->win_data[i];
1057 		win_data->resume = win_data->enabled;
1058 		mixer_win_disable(mgr, i);
1059 	}
1060 	mixer_wait_for_vblank(mgr);
1061 }
1062 
1063 static void mixer_window_resume(struct exynos_drm_manager *mgr)
1064 {
1065 	struct mixer_context *ctx = mgr->ctx;
1066 	struct hdmi_win_data *win_data;
1067 	int i;
1068 
1069 	for (i = 0; i < MIXER_WIN_NR; i++) {
1070 		win_data = &ctx->win_data[i];
1071 		win_data->enabled = win_data->resume;
1072 		win_data->resume = false;
1073 		if (win_data->enabled)
1074 			mixer_win_commit(mgr, i);
1075 	}
1076 }
1077 
1078 static void mixer_poweron(struct exynos_drm_manager *mgr)
1079 {
1080 	struct mixer_context *ctx = mgr->ctx;
1081 	struct mixer_resources *res = &ctx->mixer_res;
1082 
1083 	mutex_lock(&ctx->mixer_mutex);
1084 	if (ctx->powered) {
1085 		mutex_unlock(&ctx->mixer_mutex);
1086 		return;
1087 	}
1088 
1089 	mutex_unlock(&ctx->mixer_mutex);
1090 
1091 	pm_runtime_get_sync(ctx->dev);
1092 
1093 	clk_prepare_enable(res->mixer);
1094 	if (ctx->vp_enabled) {
1095 		clk_prepare_enable(res->vp);
1096 		if (ctx->has_sclk)
1097 			clk_prepare_enable(res->sclk_mixer);
1098 	}
1099 
1100 	mutex_lock(&ctx->mixer_mutex);
1101 	ctx->powered = true;
1102 	mutex_unlock(&ctx->mixer_mutex);
1103 
1104 	mixer_reg_writemask(res, MXR_STATUS, ~0, MXR_STATUS_SOFT_RESET);
1105 
1106 	mixer_reg_write(res, MXR_INT_EN, ctx->int_en);
1107 	mixer_win_reset(ctx);
1108 
1109 	mixer_window_resume(mgr);
1110 }
1111 
1112 static void mixer_poweroff(struct exynos_drm_manager *mgr)
1113 {
1114 	struct mixer_context *ctx = mgr->ctx;
1115 	struct mixer_resources *res = &ctx->mixer_res;
1116 
1117 	mutex_lock(&ctx->mixer_mutex);
1118 	if (!ctx->powered) {
1119 		mutex_unlock(&ctx->mixer_mutex);
1120 		return;
1121 	}
1122 	mutex_unlock(&ctx->mixer_mutex);
1123 
1124 	mixer_stop(ctx);
1125 	mixer_window_suspend(mgr);
1126 
1127 	ctx->int_en = mixer_reg_read(res, MXR_INT_EN);
1128 
1129 	mutex_lock(&ctx->mixer_mutex);
1130 	ctx->powered = false;
1131 	mutex_unlock(&ctx->mixer_mutex);
1132 
1133 	clk_disable_unprepare(res->mixer);
1134 	if (ctx->vp_enabled) {
1135 		clk_disable_unprepare(res->vp);
1136 		if (ctx->has_sclk)
1137 			clk_disable_unprepare(res->sclk_mixer);
1138 	}
1139 
1140 	pm_runtime_put_sync(ctx->dev);
1141 }
1142 
1143 static void mixer_dpms(struct exynos_drm_manager *mgr, int mode)
1144 {
1145 	switch (mode) {
1146 	case DRM_MODE_DPMS_ON:
1147 		mixer_poweron(mgr);
1148 		break;
1149 	case DRM_MODE_DPMS_STANDBY:
1150 	case DRM_MODE_DPMS_SUSPEND:
1151 	case DRM_MODE_DPMS_OFF:
1152 		mixer_poweroff(mgr);
1153 		break;
1154 	default:
1155 		DRM_DEBUG_KMS("unknown dpms mode: %d\n", mode);
1156 		break;
1157 	}
1158 }
1159 
1160 /* Only valid for Mixer version 16.0.33.0 */
1161 int mixer_check_mode(struct drm_display_mode *mode)
1162 {
1163 	u32 w, h;
1164 
1165 	w = mode->hdisplay;
1166 	h = mode->vdisplay;
1167 
1168 	DRM_DEBUG_KMS("xres=%d, yres=%d, refresh=%d, intl=%d\n",
1169 		mode->hdisplay, mode->vdisplay, mode->vrefresh,
1170 		(mode->flags & DRM_MODE_FLAG_INTERLACE) ? 1 : 0);
1171 
1172 	if ((w >= 464 && w <= 720 && h >= 261 && h <= 576) ||
1173 		(w >= 1024 && w <= 1280 && h >= 576 && h <= 720) ||
1174 		(w >= 1664 && w <= 1920 && h >= 936 && h <= 1080))
1175 		return 0;
1176 
1177 	return -EINVAL;
1178 }
1179 
1180 static struct exynos_drm_manager_ops mixer_manager_ops = {
1181 	.dpms			= mixer_dpms,
1182 	.enable_vblank		= mixer_enable_vblank,
1183 	.disable_vblank		= mixer_disable_vblank,
1184 	.wait_for_vblank	= mixer_wait_for_vblank,
1185 	.win_mode_set		= mixer_win_mode_set,
1186 	.win_commit		= mixer_win_commit,
1187 	.win_disable		= mixer_win_disable,
1188 };
1189 
1190 static struct exynos_drm_manager mixer_manager = {
1191 	.type			= EXYNOS_DISPLAY_TYPE_HDMI,
1192 	.ops			= &mixer_manager_ops,
1193 };
1194 
1195 static struct mixer_drv_data exynos5420_mxr_drv_data = {
1196 	.version = MXR_VER_128_0_0_184,
1197 	.is_vp_enabled = 0,
1198 };
1199 
1200 static struct mixer_drv_data exynos5250_mxr_drv_data = {
1201 	.version = MXR_VER_16_0_33_0,
1202 	.is_vp_enabled = 0,
1203 };
1204 
1205 static struct mixer_drv_data exynos4212_mxr_drv_data = {
1206 	.version = MXR_VER_0_0_0_16,
1207 	.is_vp_enabled = 1,
1208 };
1209 
1210 static struct mixer_drv_data exynos4210_mxr_drv_data = {
1211 	.version = MXR_VER_0_0_0_16,
1212 	.is_vp_enabled = 1,
1213 	.has_sclk = 1,
1214 };
1215 
1216 static struct platform_device_id mixer_driver_types[] = {
1217 	{
1218 		.name		= "s5p-mixer",
1219 		.driver_data	= (unsigned long)&exynos4210_mxr_drv_data,
1220 	}, {
1221 		.name		= "exynos5-mixer",
1222 		.driver_data	= (unsigned long)&exynos5250_mxr_drv_data,
1223 	}, {
1224 		/* end node */
1225 	}
1226 };
1227 
1228 static struct of_device_id mixer_match_types[] = {
1229 	{
1230 		.compatible = "samsung,exynos4210-mixer",
1231 		.data	= &exynos4210_mxr_drv_data,
1232 	}, {
1233 		.compatible = "samsung,exynos4212-mixer",
1234 		.data	= &exynos4212_mxr_drv_data,
1235 	}, {
1236 		.compatible = "samsung,exynos5-mixer",
1237 		.data	= &exynos5250_mxr_drv_data,
1238 	}, {
1239 		.compatible = "samsung,exynos5250-mixer",
1240 		.data	= &exynos5250_mxr_drv_data,
1241 	}, {
1242 		.compatible = "samsung,exynos5420-mixer",
1243 		.data	= &exynos5420_mxr_drv_data,
1244 	}, {
1245 		/* end node */
1246 	}
1247 };
1248 MODULE_DEVICE_TABLE(of, mixer_match_types);
1249 
1250 static int mixer_bind(struct device *dev, struct device *manager, void *data)
1251 {
1252 	struct platform_device *pdev = to_platform_device(dev);
1253 	struct drm_device *drm_dev = data;
1254 	struct mixer_context *ctx;
1255 	struct mixer_drv_data *drv;
1256 	int ret;
1257 
1258 	dev_info(dev, "probe start\n");
1259 
1260 	ctx = devm_kzalloc(&pdev->dev, sizeof(*ctx), GFP_KERNEL);
1261 	if (!ctx) {
1262 		DRM_ERROR("failed to alloc mixer context.\n");
1263 		return -ENOMEM;
1264 	}
1265 
1266 	mutex_init(&ctx->mixer_mutex);
1267 
1268 	if (dev->of_node) {
1269 		const struct of_device_id *match;
1270 		match = of_match_node(mixer_match_types, dev->of_node);
1271 		drv = (struct mixer_drv_data *)match->data;
1272 	} else {
1273 		drv = (struct mixer_drv_data *)
1274 			platform_get_device_id(pdev)->driver_data;
1275 	}
1276 
1277 	ctx->pdev = pdev;
1278 	ctx->dev = dev;
1279 	ctx->vp_enabled = drv->is_vp_enabled;
1280 	ctx->has_sclk = drv->has_sclk;
1281 	ctx->mxr_ver = drv->version;
1282 	init_waitqueue_head(&ctx->wait_vsync_queue);
1283 	atomic_set(&ctx->wait_vsync_event, 0);
1284 
1285 	mixer_manager.ctx = ctx;
1286 	ret = mixer_initialize(&mixer_manager, drm_dev);
1287 	if (ret)
1288 		return ret;
1289 
1290 	platform_set_drvdata(pdev, &mixer_manager);
1291 	ret = exynos_drm_crtc_create(&mixer_manager);
1292 	if (ret) {
1293 		mixer_mgr_remove(&mixer_manager);
1294 		return ret;
1295 	}
1296 
1297 	pm_runtime_enable(dev);
1298 
1299 	return 0;
1300 }
1301 
1302 static void mixer_unbind(struct device *dev, struct device *master, void *data)
1303 {
1304 	struct exynos_drm_manager *mgr = dev_get_drvdata(dev);
1305 	struct drm_crtc *crtc = mgr->crtc;
1306 
1307 	dev_info(dev, "remove successful\n");
1308 
1309 	mixer_mgr_remove(mgr);
1310 
1311 	pm_runtime_disable(dev);
1312 
1313 	crtc->funcs->destroy(crtc);
1314 }
1315 
1316 static const struct component_ops mixer_component_ops = {
1317 	.bind	= mixer_bind,
1318 	.unbind	= mixer_unbind,
1319 };
1320 
1321 static int mixer_probe(struct platform_device *pdev)
1322 {
1323 	int ret;
1324 
1325 	ret = exynos_drm_component_add(&pdev->dev, EXYNOS_DEVICE_TYPE_CRTC,
1326 					mixer_manager.type);
1327 	if (ret)
1328 		return ret;
1329 
1330 	ret = component_add(&pdev->dev, &mixer_component_ops);
1331 	if (ret)
1332 		exynos_drm_component_del(&pdev->dev, EXYNOS_DEVICE_TYPE_CRTC);
1333 
1334 	return ret;
1335 }
1336 
1337 static int mixer_remove(struct platform_device *pdev)
1338 {
1339 	component_del(&pdev->dev, &mixer_component_ops);
1340 	exynos_drm_component_del(&pdev->dev, EXYNOS_DEVICE_TYPE_CRTC);
1341 
1342 	return 0;
1343 }
1344 
1345 struct platform_driver mixer_driver = {
1346 	.driver = {
1347 		.name = "exynos-mixer",
1348 		.owner = THIS_MODULE,
1349 		.of_match_table = mixer_match_types,
1350 	},
1351 	.probe = mixer_probe,
1352 	.remove = mixer_remove,
1353 	.id_table	= mixer_driver_types,
1354 };
1355