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