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 
53 struct 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 
66 enum 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 
72 struct 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 
92 struct mixer_drv_data {
93 	enum mixer_version_id	version;
94 	bool					is_vp_enabled;
95 	bool					has_sclk;
96 };
97 
98 static 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 
109 static 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 
120 static 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 
vp_reg_read(struct mixer_resources * res,u32 reg_id)127 static inline u32 vp_reg_read(struct mixer_resources *res, u32 reg_id)
128 {
129 	return readl(res->vp_regs + reg_id);
130 }
131 
vp_reg_write(struct mixer_resources * res,u32 reg_id,u32 val)132 static 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 
vp_reg_writemask(struct mixer_resources * res,u32 reg_id,u32 val,u32 mask)138 static 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 
mixer_reg_read(struct mixer_resources * res,u32 reg_id)147 static inline u32 mixer_reg_read(struct mixer_resources *res, u32 reg_id)
148 {
149 	return readl(res->mixer_regs + reg_id);
150 }
151 
mixer_reg_write(struct mixer_resources * res,u32 reg_id,u32 val)152 static 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 
mixer_reg_writemask(struct mixer_resources * res,u32 reg_id,u32 val,u32 mask)158 static 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 
mixer_regs_dump(struct mixer_context * ctx)167 static void mixer_regs_dump(struct mixer_context *ctx)
168 {
169 #define DUMPREG(reg_id) \
170 do { \
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 
vp_regs_dump(struct mixer_context * ctx)199 static void vp_regs_dump(struct mixer_context *ctx)
200 {
201 #define DUMPREG(reg_id) \
202 do { \
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 
vp_filter_set(struct mixer_resources * res,int reg_id,const u8 * data,unsigned int size)234 static 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 
vp_default_filter(struct mixer_resources * res)246 static 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 
mixer_vsync_set_update(struct mixer_context * ctx,bool enable)256 static 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 
mixer_cfg_scan(struct mixer_context * ctx,unsigned int height)269 static 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 
mixer_cfg_rgb_fmt(struct mixer_context * ctx,unsigned int height)295 static 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 
mixer_cfg_layer(struct mixer_context * ctx,unsigned int win,bool enable)336 static 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 
mixer_run(struct mixer_context * ctx)364 static 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 
mixer_stop(struct mixer_context * ctx)371 static 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 
vp_video_buffer(struct mixer_context * ctx,unsigned int win)383 static 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 
mixer_layer_update(struct mixer_context * ctx)484 static 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 
mixer_setup_scale(const struct exynos_drm_plane * plane,unsigned int * x_ratio,unsigned int * y_ratio)491 static 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 
510 fail:
511 	DRM_DEBUG_KMS("only 2x width/height scaling of plane supported\n");
512 	return -ENOTSUPP;
513 }
514 
mixer_graph_buffer(struct mixer_context * ctx,unsigned int win)515 static 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 
vp_win_reset(struct mixer_context * ctx)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 
mixer_win_reset(struct mixer_context * ctx)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 
mixer_irq_handler(int irq,void * arg)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 
mixer_resources_init(struct mixer_context * mixer_ctx)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->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 
vp_resources_init(struct mixer_context * mixer_ctx)814 static 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 
mixer_initialize(struct mixer_context * mixer_ctx,struct drm_device * drm_dev)859 static 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 
mixer_ctx_remove(struct mixer_context * mixer_ctx)891 static 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 
mixer_enable_vblank(struct exynos_drm_crtc * crtc)897 static 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 
mixer_disable_vblank(struct exynos_drm_crtc * crtc)914 static 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 
mixer_win_commit(struct exynos_drm_crtc * crtc,unsigned int win)923 static 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 
mixer_win_disable(struct exynos_drm_crtc * crtc,unsigned int win)944 static 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 
mixer_wait_for_vblank(struct exynos_drm_crtc * crtc)971 static 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 
mixer_window_suspend(struct mixer_context * ctx)1003 static 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 
mixer_window_resume(struct mixer_context * ctx)1016 static 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 
mixer_poweron(struct mixer_context * ctx)1030 static 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 
mixer_poweroff(struct mixer_context * ctx)1064 static 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 
mixer_dpms(struct exynos_drm_crtc * crtc,int mode)1096 static 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 */
mixer_check_mode(struct drm_display_mode * mode)1114 int 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 
1133 static 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 
1142 static struct mixer_drv_data exynos5420_mxr_drv_data = {
1143 	.version = MXR_VER_128_0_0_184,
1144 	.is_vp_enabled = 0,
1145 };
1146 
1147 static struct mixer_drv_data exynos5250_mxr_drv_data = {
1148 	.version = MXR_VER_16_0_33_0,
1149 	.is_vp_enabled = 0,
1150 };
1151 
1152 static struct mixer_drv_data exynos4212_mxr_drv_data = {
1153 	.version = MXR_VER_0_0_0_16,
1154 	.is_vp_enabled = 1,
1155 };
1156 
1157 static 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 
1163 static 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 
1175 static 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 };
1195 MODULE_DEVICE_TABLE(of, mixer_match_types);
1196 
mixer_bind(struct device * dev,struct device * manager,void * data)1197 static 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 
1231 free_ctx:
1232 	devm_kfree(dev, ctx);
1233 	return ret;
1234 }
1235 
mixer_unbind(struct device * dev,struct device * master,void * data)1236 static 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 
1243 static const struct component_ops mixer_component_ops = {
1244 	.bind	= mixer_bind,
1245 	.unbind	= mixer_unbind,
1246 };
1247 
mixer_probe(struct platform_device * pdev)1248 static 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 
mixer_remove(struct platform_device * pdev)1299 static 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 
1309 struct 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