1 /*
2  * Copyright (C) 2012 Samsung Electronics Co.Ltd
3  * Authors:
4  *	Eunchul Kim <chulspro.kim@samsung.com>
5  *	Jinyoung Jeon <jy0.jeon@samsung.com>
6  *	Sangmin Lee <lsmin.lee@samsung.com>
7  *
8  * This program is free software; you can redistribute  it and/or modify it
9  * under  the terms of  the GNU General  Public License as published by the
10  * Free Software Foundation;  either version 2 of the  License, or (at your
11  * option) any later version.
12  *
13  */
14 #include <linux/kernel.h>
15 #include <linux/module.h>
16 #include <linux/platform_device.h>
17 #include <linux/mfd/syscon.h>
18 #include <linux/regmap.h>
19 #include <linux/clk.h>
20 #include <linux/pm_runtime.h>
21 
22 #include <drm/drmP.h>
23 #include <drm/exynos_drm.h>
24 #include "regs-fimc.h"
25 #include "exynos_drm_ipp.h"
26 #include "exynos_drm_fimc.h"
27 
28 /*
29  * FIMC stands for Fully Interactive Mobile Camera and
30  * supports image scaler/rotator and input/output DMA operations.
31  * input DMA reads image data from the memory.
32  * output DMA writes image data to memory.
33  * FIMC supports image rotation and image effect functions.
34  *
35  * M2M operation : supports crop/scale/rotation/csc so on.
36  * Memory ----> FIMC H/W ----> Memory.
37  * Writeback operation : supports cloned screen with FIMD.
38  * FIMD ----> FIMC H/W ----> Memory.
39  * Output operation : supports direct display using local path.
40  * Memory ----> FIMC H/W ----> FIMD.
41  */
42 
43 /*
44  * TODO
45  * 1. check suspend/resume api if needed.
46  * 2. need to check use case platform_device_id.
47  * 3. check src/dst size with, height.
48  * 4. added check_prepare api for right register.
49  * 5. need to add supported list in prop_list.
50  * 6. check prescaler/scaler optimization.
51  */
52 
53 #define FIMC_MAX_DEVS	4
54 #define FIMC_MAX_SRC	2
55 #define FIMC_MAX_DST	32
56 #define FIMC_SHFACTOR	10
57 #define FIMC_BUF_STOP	1
58 #define FIMC_BUF_START	2
59 #define FIMC_REG_SZ		32
60 #define FIMC_WIDTH_ITU_709	1280
61 #define FIMC_REFRESH_MAX	60
62 #define FIMC_REFRESH_MIN	12
63 #define FIMC_CROP_MAX	8192
64 #define FIMC_CROP_MIN	32
65 #define FIMC_SCALE_MAX	4224
66 #define FIMC_SCALE_MIN	32
67 
68 #define get_fimc_context(dev)	platform_get_drvdata(to_platform_device(dev))
69 #define get_ctx_from_ippdrv(ippdrv)	container_of(ippdrv,\
70 					struct fimc_context, ippdrv);
71 #define fimc_read(offset)		readl(ctx->regs + (offset))
72 #define fimc_write(cfg, offset)	writel(cfg, ctx->regs + (offset))
73 
74 enum fimc_wb {
75 	FIMC_WB_NONE,
76 	FIMC_WB_A,
77 	FIMC_WB_B,
78 };
79 
80 enum {
81 	FIMC_CLK_LCLK,
82 	FIMC_CLK_GATE,
83 	FIMC_CLK_WB_A,
84 	FIMC_CLK_WB_B,
85 	FIMC_CLK_MUX,
86 	FIMC_CLK_PARENT,
87 	FIMC_CLKS_MAX
88 };
89 
90 static const char * const fimc_clock_names[] = {
91 	[FIMC_CLK_LCLK]   = "sclk_fimc",
92 	[FIMC_CLK_GATE]   = "fimc",
93 	[FIMC_CLK_WB_A]   = "pxl_async0",
94 	[FIMC_CLK_WB_B]   = "pxl_async1",
95 	[FIMC_CLK_MUX]    = "mux",
96 	[FIMC_CLK_PARENT] = "parent",
97 };
98 
99 #define FIMC_DEFAULT_LCLK_FREQUENCY 133000000UL
100 
101 /*
102  * A structure of scaler.
103  *
104  * @range: narrow, wide.
105  * @bypass: unused scaler path.
106  * @up_h: horizontal scale up.
107  * @up_v: vertical scale up.
108  * @hratio: horizontal ratio.
109  * @vratio: vertical ratio.
110  */
111 struct fimc_scaler {
112 	bool	range;
113 	bool bypass;
114 	bool up_h;
115 	bool up_v;
116 	u32 hratio;
117 	u32 vratio;
118 };
119 
120 /*
121  * A structure of scaler capability.
122  *
123  * find user manual table 43-1.
124  * @in_hori: scaler input horizontal size.
125  * @bypass: scaler bypass mode.
126  * @dst_h_wo_rot: target horizontal size without output rotation.
127  * @dst_h_rot: target horizontal size with output rotation.
128  * @rl_w_wo_rot: real width without input rotation.
129  * @rl_h_rot: real height without output rotation.
130  */
131 struct fimc_capability {
132 	/* scaler */
133 	u32	in_hori;
134 	u32	bypass;
135 	/* output rotator */
136 	u32	dst_h_wo_rot;
137 	u32	dst_h_rot;
138 	/* input rotator */
139 	u32	rl_w_wo_rot;
140 	u32	rl_h_rot;
141 };
142 
143 /*
144  * A structure of fimc context.
145  *
146  * @ippdrv: prepare initialization using ippdrv.
147  * @regs_res: register resources.
148  * @regs: memory mapped io registers.
149  * @lock: locking of operations.
150  * @clocks: fimc clocks.
151  * @clk_frequency: LCLK clock frequency.
152  * @sysreg: handle to SYSREG block regmap.
153  * @sc: scaler infomations.
154  * @pol: porarity of writeback.
155  * @id: fimc id.
156  * @irq: irq number.
157  * @suspended: qos operations.
158  */
159 struct fimc_context {
160 	struct exynos_drm_ippdrv	ippdrv;
161 	struct resource	*regs_res;
162 	void __iomem	*regs;
163 	struct mutex	lock;
164 	struct clk	*clocks[FIMC_CLKS_MAX];
165 	u32		clk_frequency;
166 	struct regmap	*sysreg;
167 	struct fimc_scaler	sc;
168 	struct exynos_drm_ipp_pol	pol;
169 	int	id;
170 	int	irq;
171 	bool	suspended;
172 };
173 
174 static void fimc_sw_reset(struct fimc_context *ctx)
175 {
176 	u32 cfg;
177 
178 	/* stop dma operation */
179 	cfg = fimc_read(EXYNOS_CISTATUS);
180 	if (EXYNOS_CISTATUS_GET_ENVID_STATUS(cfg)) {
181 		cfg = fimc_read(EXYNOS_MSCTRL);
182 		cfg &= ~EXYNOS_MSCTRL_ENVID;
183 		fimc_write(cfg, EXYNOS_MSCTRL);
184 	}
185 
186 	cfg = fimc_read(EXYNOS_CISRCFMT);
187 	cfg |= EXYNOS_CISRCFMT_ITU601_8BIT;
188 	fimc_write(cfg, EXYNOS_CISRCFMT);
189 
190 	/* disable image capture */
191 	cfg = fimc_read(EXYNOS_CIIMGCPT);
192 	cfg &= ~(EXYNOS_CIIMGCPT_IMGCPTEN_SC | EXYNOS_CIIMGCPT_IMGCPTEN);
193 	fimc_write(cfg, EXYNOS_CIIMGCPT);
194 
195 	/* s/w reset */
196 	cfg = fimc_read(EXYNOS_CIGCTRL);
197 	cfg |= (EXYNOS_CIGCTRL_SWRST);
198 	fimc_write(cfg, EXYNOS_CIGCTRL);
199 
200 	/* s/w reset complete */
201 	cfg = fimc_read(EXYNOS_CIGCTRL);
202 	cfg &= ~EXYNOS_CIGCTRL_SWRST;
203 	fimc_write(cfg, EXYNOS_CIGCTRL);
204 
205 	/* reset sequence */
206 	fimc_write(0x0, EXYNOS_CIFCNTSEQ);
207 }
208 
209 static int fimc_set_camblk_fimd0_wb(struct fimc_context *ctx)
210 {
211 	return regmap_update_bits(ctx->sysreg, SYSREG_CAMERA_BLK,
212 				  SYSREG_FIMD0WB_DEST_MASK,
213 				  ctx->id << SYSREG_FIMD0WB_DEST_SHIFT);
214 }
215 
216 static void fimc_set_type_ctrl(struct fimc_context *ctx, enum fimc_wb wb)
217 {
218 	u32 cfg;
219 
220 	DRM_DEBUG_KMS("wb[%d]\n", wb);
221 
222 	cfg = fimc_read(EXYNOS_CIGCTRL);
223 	cfg &= ~(EXYNOS_CIGCTRL_TESTPATTERN_MASK |
224 		EXYNOS_CIGCTRL_SELCAM_ITU_MASK |
225 		EXYNOS_CIGCTRL_SELCAM_MIPI_MASK |
226 		EXYNOS_CIGCTRL_SELCAM_FIMC_MASK |
227 		EXYNOS_CIGCTRL_SELWB_CAMIF_MASK |
228 		EXYNOS_CIGCTRL_SELWRITEBACK_MASK);
229 
230 	switch (wb) {
231 	case FIMC_WB_A:
232 		cfg |= (EXYNOS_CIGCTRL_SELWRITEBACK_A |
233 			EXYNOS_CIGCTRL_SELWB_CAMIF_WRITEBACK);
234 		break;
235 	case FIMC_WB_B:
236 		cfg |= (EXYNOS_CIGCTRL_SELWRITEBACK_B |
237 			EXYNOS_CIGCTRL_SELWB_CAMIF_WRITEBACK);
238 		break;
239 	case FIMC_WB_NONE:
240 	default:
241 		cfg |= (EXYNOS_CIGCTRL_SELCAM_ITU_A |
242 			EXYNOS_CIGCTRL_SELWRITEBACK_A |
243 			EXYNOS_CIGCTRL_SELCAM_MIPI_A |
244 			EXYNOS_CIGCTRL_SELCAM_FIMC_ITU);
245 		break;
246 	}
247 
248 	fimc_write(cfg, EXYNOS_CIGCTRL);
249 }
250 
251 static void fimc_set_polarity(struct fimc_context *ctx,
252 		struct exynos_drm_ipp_pol *pol)
253 {
254 	u32 cfg;
255 
256 	DRM_DEBUG_KMS("inv_pclk[%d]inv_vsync[%d]\n",
257 		pol->inv_pclk, pol->inv_vsync);
258 	DRM_DEBUG_KMS("inv_href[%d]inv_hsync[%d]\n",
259 		pol->inv_href, pol->inv_hsync);
260 
261 	cfg = fimc_read(EXYNOS_CIGCTRL);
262 	cfg &= ~(EXYNOS_CIGCTRL_INVPOLPCLK | EXYNOS_CIGCTRL_INVPOLVSYNC |
263 		 EXYNOS_CIGCTRL_INVPOLHREF | EXYNOS_CIGCTRL_INVPOLHSYNC);
264 
265 	if (pol->inv_pclk)
266 		cfg |= EXYNOS_CIGCTRL_INVPOLPCLK;
267 	if (pol->inv_vsync)
268 		cfg |= EXYNOS_CIGCTRL_INVPOLVSYNC;
269 	if (pol->inv_href)
270 		cfg |= EXYNOS_CIGCTRL_INVPOLHREF;
271 	if (pol->inv_hsync)
272 		cfg |= EXYNOS_CIGCTRL_INVPOLHSYNC;
273 
274 	fimc_write(cfg, EXYNOS_CIGCTRL);
275 }
276 
277 static void fimc_handle_jpeg(struct fimc_context *ctx, bool enable)
278 {
279 	u32 cfg;
280 
281 	DRM_DEBUG_KMS("enable[%d]\n", enable);
282 
283 	cfg = fimc_read(EXYNOS_CIGCTRL);
284 	if (enable)
285 		cfg |= EXYNOS_CIGCTRL_CAM_JPEG;
286 	else
287 		cfg &= ~EXYNOS_CIGCTRL_CAM_JPEG;
288 
289 	fimc_write(cfg, EXYNOS_CIGCTRL);
290 }
291 
292 static void fimc_handle_irq(struct fimc_context *ctx, bool enable,
293 		bool overflow, bool level)
294 {
295 	u32 cfg;
296 
297 	DRM_DEBUG_KMS("enable[%d]overflow[%d]level[%d]\n",
298 			enable, overflow, level);
299 
300 	cfg = fimc_read(EXYNOS_CIGCTRL);
301 	if (enable) {
302 		cfg &= ~(EXYNOS_CIGCTRL_IRQ_OVFEN | EXYNOS_CIGCTRL_IRQ_LEVEL);
303 		cfg |= EXYNOS_CIGCTRL_IRQ_ENABLE;
304 		if (overflow)
305 			cfg |= EXYNOS_CIGCTRL_IRQ_OVFEN;
306 		if (level)
307 			cfg |= EXYNOS_CIGCTRL_IRQ_LEVEL;
308 	} else
309 		cfg &= ~(EXYNOS_CIGCTRL_IRQ_OVFEN | EXYNOS_CIGCTRL_IRQ_ENABLE);
310 
311 	fimc_write(cfg, EXYNOS_CIGCTRL);
312 }
313 
314 static void fimc_clear_irq(struct fimc_context *ctx)
315 {
316 	u32 cfg;
317 
318 	cfg = fimc_read(EXYNOS_CIGCTRL);
319 	cfg |= EXYNOS_CIGCTRL_IRQ_CLR;
320 	fimc_write(cfg, EXYNOS_CIGCTRL);
321 }
322 
323 static bool fimc_check_ovf(struct fimc_context *ctx)
324 {
325 	struct exynos_drm_ippdrv *ippdrv = &ctx->ippdrv;
326 	u32 cfg, status, flag;
327 
328 	status = fimc_read(EXYNOS_CISTATUS);
329 	flag = EXYNOS_CISTATUS_OVFIY | EXYNOS_CISTATUS_OVFICB |
330 		EXYNOS_CISTATUS_OVFICR;
331 
332 	DRM_DEBUG_KMS("flag[0x%x]\n", flag);
333 
334 	if (status & flag) {
335 		cfg = fimc_read(EXYNOS_CIWDOFST);
336 		cfg |= (EXYNOS_CIWDOFST_CLROVFIY | EXYNOS_CIWDOFST_CLROVFICB |
337 			EXYNOS_CIWDOFST_CLROVFICR);
338 
339 		fimc_write(cfg, EXYNOS_CIWDOFST);
340 
341 		cfg = fimc_read(EXYNOS_CIWDOFST);
342 		cfg &= ~(EXYNOS_CIWDOFST_CLROVFIY | EXYNOS_CIWDOFST_CLROVFICB |
343 			EXYNOS_CIWDOFST_CLROVFICR);
344 
345 		fimc_write(cfg, EXYNOS_CIWDOFST);
346 
347 		dev_err(ippdrv->dev, "occured overflow at %d, status 0x%x.\n",
348 			ctx->id, status);
349 		return true;
350 	}
351 
352 	return false;
353 }
354 
355 static bool fimc_check_frame_end(struct fimc_context *ctx)
356 {
357 	u32 cfg;
358 
359 	cfg = fimc_read(EXYNOS_CISTATUS);
360 
361 	DRM_DEBUG_KMS("cfg[0x%x]\n", cfg);
362 
363 	if (!(cfg & EXYNOS_CISTATUS_FRAMEEND))
364 		return false;
365 
366 	cfg &= ~(EXYNOS_CISTATUS_FRAMEEND);
367 	fimc_write(cfg, EXYNOS_CISTATUS);
368 
369 	return true;
370 }
371 
372 static int fimc_get_buf_id(struct fimc_context *ctx)
373 {
374 	u32 cfg;
375 	int frame_cnt, buf_id;
376 
377 	cfg = fimc_read(EXYNOS_CISTATUS2);
378 	frame_cnt = EXYNOS_CISTATUS2_GET_FRAMECOUNT_BEFORE(cfg);
379 
380 	if (frame_cnt == 0)
381 		frame_cnt = EXYNOS_CISTATUS2_GET_FRAMECOUNT_PRESENT(cfg);
382 
383 	DRM_DEBUG_KMS("present[%d]before[%d]\n",
384 		EXYNOS_CISTATUS2_GET_FRAMECOUNT_PRESENT(cfg),
385 		EXYNOS_CISTATUS2_GET_FRAMECOUNT_BEFORE(cfg));
386 
387 	if (frame_cnt == 0) {
388 		DRM_ERROR("failed to get frame count.\n");
389 		return -EIO;
390 	}
391 
392 	buf_id = frame_cnt - 1;
393 	DRM_DEBUG_KMS("buf_id[%d]\n", buf_id);
394 
395 	return buf_id;
396 }
397 
398 static void fimc_handle_lastend(struct fimc_context *ctx, bool enable)
399 {
400 	u32 cfg;
401 
402 	DRM_DEBUG_KMS("enable[%d]\n", enable);
403 
404 	cfg = fimc_read(EXYNOS_CIOCTRL);
405 	if (enable)
406 		cfg |= EXYNOS_CIOCTRL_LASTENDEN;
407 	else
408 		cfg &= ~EXYNOS_CIOCTRL_LASTENDEN;
409 
410 	fimc_write(cfg, EXYNOS_CIOCTRL);
411 }
412 
413 
414 static int fimc_src_set_fmt_order(struct fimc_context *ctx, u32 fmt)
415 {
416 	struct exynos_drm_ippdrv *ippdrv = &ctx->ippdrv;
417 	u32 cfg;
418 
419 	DRM_DEBUG_KMS("fmt[0x%x]\n", fmt);
420 
421 	/* RGB */
422 	cfg = fimc_read(EXYNOS_CISCCTRL);
423 	cfg &= ~EXYNOS_CISCCTRL_INRGB_FMT_RGB_MASK;
424 
425 	switch (fmt) {
426 	case DRM_FORMAT_RGB565:
427 		cfg |= EXYNOS_CISCCTRL_INRGB_FMT_RGB565;
428 		fimc_write(cfg, EXYNOS_CISCCTRL);
429 		return 0;
430 	case DRM_FORMAT_RGB888:
431 	case DRM_FORMAT_XRGB8888:
432 		cfg |= EXYNOS_CISCCTRL_INRGB_FMT_RGB888;
433 		fimc_write(cfg, EXYNOS_CISCCTRL);
434 		return 0;
435 	default:
436 		/* bypass */
437 		break;
438 	}
439 
440 	/* YUV */
441 	cfg = fimc_read(EXYNOS_MSCTRL);
442 	cfg &= ~(EXYNOS_MSCTRL_ORDER2P_SHIFT_MASK |
443 		EXYNOS_MSCTRL_C_INT_IN_2PLANE |
444 		EXYNOS_MSCTRL_ORDER422_YCBYCR);
445 
446 	switch (fmt) {
447 	case DRM_FORMAT_YUYV:
448 		cfg |= EXYNOS_MSCTRL_ORDER422_YCBYCR;
449 		break;
450 	case DRM_FORMAT_YVYU:
451 		cfg |= EXYNOS_MSCTRL_ORDER422_YCRYCB;
452 		break;
453 	case DRM_FORMAT_UYVY:
454 		cfg |= EXYNOS_MSCTRL_ORDER422_CBYCRY;
455 		break;
456 	case DRM_FORMAT_VYUY:
457 	case DRM_FORMAT_YUV444:
458 		cfg |= EXYNOS_MSCTRL_ORDER422_CRYCBY;
459 		break;
460 	case DRM_FORMAT_NV21:
461 	case DRM_FORMAT_NV61:
462 		cfg |= (EXYNOS_MSCTRL_ORDER2P_LSB_CRCB |
463 			EXYNOS_MSCTRL_C_INT_IN_2PLANE);
464 		break;
465 	case DRM_FORMAT_YUV422:
466 	case DRM_FORMAT_YUV420:
467 	case DRM_FORMAT_YVU420:
468 		cfg |= EXYNOS_MSCTRL_C_INT_IN_3PLANE;
469 		break;
470 	case DRM_FORMAT_NV12:
471 	case DRM_FORMAT_NV12MT:
472 	case DRM_FORMAT_NV16:
473 		cfg |= (EXYNOS_MSCTRL_ORDER2P_LSB_CBCR |
474 			EXYNOS_MSCTRL_C_INT_IN_2PLANE);
475 		break;
476 	default:
477 		dev_err(ippdrv->dev, "inavlid source yuv order 0x%x.\n", fmt);
478 		return -EINVAL;
479 	}
480 
481 	fimc_write(cfg, EXYNOS_MSCTRL);
482 
483 	return 0;
484 }
485 
486 static int fimc_src_set_fmt(struct device *dev, u32 fmt)
487 {
488 	struct fimc_context *ctx = get_fimc_context(dev);
489 	struct exynos_drm_ippdrv *ippdrv = &ctx->ippdrv;
490 	u32 cfg;
491 
492 	DRM_DEBUG_KMS("fmt[0x%x]\n", fmt);
493 
494 	cfg = fimc_read(EXYNOS_MSCTRL);
495 	cfg &= ~EXYNOS_MSCTRL_INFORMAT_RGB;
496 
497 	switch (fmt) {
498 	case DRM_FORMAT_RGB565:
499 	case DRM_FORMAT_RGB888:
500 	case DRM_FORMAT_XRGB8888:
501 		cfg |= EXYNOS_MSCTRL_INFORMAT_RGB;
502 		break;
503 	case DRM_FORMAT_YUV444:
504 		cfg |= EXYNOS_MSCTRL_INFORMAT_YCBCR420;
505 		break;
506 	case DRM_FORMAT_YUYV:
507 	case DRM_FORMAT_YVYU:
508 	case DRM_FORMAT_UYVY:
509 	case DRM_FORMAT_VYUY:
510 		cfg |= EXYNOS_MSCTRL_INFORMAT_YCBCR422_1PLANE;
511 		break;
512 	case DRM_FORMAT_NV16:
513 	case DRM_FORMAT_NV61:
514 	case DRM_FORMAT_YUV422:
515 		cfg |= EXYNOS_MSCTRL_INFORMAT_YCBCR422;
516 		break;
517 	case DRM_FORMAT_YUV420:
518 	case DRM_FORMAT_YVU420:
519 	case DRM_FORMAT_NV12:
520 	case DRM_FORMAT_NV21:
521 	case DRM_FORMAT_NV12MT:
522 		cfg |= EXYNOS_MSCTRL_INFORMAT_YCBCR420;
523 		break;
524 	default:
525 		dev_err(ippdrv->dev, "inavlid source format 0x%x.\n", fmt);
526 		return -EINVAL;
527 	}
528 
529 	fimc_write(cfg, EXYNOS_MSCTRL);
530 
531 	cfg = fimc_read(EXYNOS_CIDMAPARAM);
532 	cfg &= ~EXYNOS_CIDMAPARAM_R_MODE_MASK;
533 
534 	if (fmt == DRM_FORMAT_NV12MT)
535 		cfg |= EXYNOS_CIDMAPARAM_R_MODE_64X32;
536 	else
537 		cfg |= EXYNOS_CIDMAPARAM_R_MODE_LINEAR;
538 
539 	fimc_write(cfg, EXYNOS_CIDMAPARAM);
540 
541 	return fimc_src_set_fmt_order(ctx, fmt);
542 }
543 
544 static int fimc_src_set_transf(struct device *dev,
545 		enum drm_exynos_degree degree,
546 		enum drm_exynos_flip flip, bool *swap)
547 {
548 	struct fimc_context *ctx = get_fimc_context(dev);
549 	struct exynos_drm_ippdrv *ippdrv = &ctx->ippdrv;
550 	u32 cfg1, cfg2;
551 
552 	DRM_DEBUG_KMS("degree[%d]flip[0x%x]\n", degree, flip);
553 
554 	cfg1 = fimc_read(EXYNOS_MSCTRL);
555 	cfg1 &= ~(EXYNOS_MSCTRL_FLIP_X_MIRROR |
556 		EXYNOS_MSCTRL_FLIP_Y_MIRROR);
557 
558 	cfg2 = fimc_read(EXYNOS_CITRGFMT);
559 	cfg2 &= ~EXYNOS_CITRGFMT_INROT90_CLOCKWISE;
560 
561 	switch (degree) {
562 	case EXYNOS_DRM_DEGREE_0:
563 		if (flip & EXYNOS_DRM_FLIP_VERTICAL)
564 			cfg1 |= EXYNOS_MSCTRL_FLIP_X_MIRROR;
565 		if (flip & EXYNOS_DRM_FLIP_HORIZONTAL)
566 			cfg1 |= EXYNOS_MSCTRL_FLIP_Y_MIRROR;
567 		break;
568 	case EXYNOS_DRM_DEGREE_90:
569 		cfg2 |= EXYNOS_CITRGFMT_INROT90_CLOCKWISE;
570 		if (flip & EXYNOS_DRM_FLIP_VERTICAL)
571 			cfg1 |= EXYNOS_MSCTRL_FLIP_X_MIRROR;
572 		if (flip & EXYNOS_DRM_FLIP_HORIZONTAL)
573 			cfg1 |= EXYNOS_MSCTRL_FLIP_Y_MIRROR;
574 		break;
575 	case EXYNOS_DRM_DEGREE_180:
576 		cfg1 |= (EXYNOS_MSCTRL_FLIP_X_MIRROR |
577 			EXYNOS_MSCTRL_FLIP_Y_MIRROR);
578 		if (flip & EXYNOS_DRM_FLIP_VERTICAL)
579 			cfg1 &= ~EXYNOS_MSCTRL_FLIP_X_MIRROR;
580 		if (flip & EXYNOS_DRM_FLIP_HORIZONTAL)
581 			cfg1 &= ~EXYNOS_MSCTRL_FLIP_Y_MIRROR;
582 		break;
583 	case EXYNOS_DRM_DEGREE_270:
584 		cfg1 |= (EXYNOS_MSCTRL_FLIP_X_MIRROR |
585 			EXYNOS_MSCTRL_FLIP_Y_MIRROR);
586 		cfg2 |= EXYNOS_CITRGFMT_INROT90_CLOCKWISE;
587 		if (flip & EXYNOS_DRM_FLIP_VERTICAL)
588 			cfg1 &= ~EXYNOS_MSCTRL_FLIP_X_MIRROR;
589 		if (flip & EXYNOS_DRM_FLIP_HORIZONTAL)
590 			cfg1 &= ~EXYNOS_MSCTRL_FLIP_Y_MIRROR;
591 		break;
592 	default:
593 		dev_err(ippdrv->dev, "inavlid degree value %d.\n", degree);
594 		return -EINVAL;
595 	}
596 
597 	fimc_write(cfg1, EXYNOS_MSCTRL);
598 	fimc_write(cfg2, EXYNOS_CITRGFMT);
599 	*swap = (cfg2 & EXYNOS_CITRGFMT_INROT90_CLOCKWISE) ? 1 : 0;
600 
601 	return 0;
602 }
603 
604 static int fimc_set_window(struct fimc_context *ctx,
605 		struct drm_exynos_pos *pos, struct drm_exynos_sz *sz)
606 {
607 	u32 cfg, h1, h2, v1, v2;
608 
609 	/* cropped image */
610 	h1 = pos->x;
611 	h2 = sz->hsize - pos->w - pos->x;
612 	v1 = pos->y;
613 	v2 = sz->vsize - pos->h - pos->y;
614 
615 	DRM_DEBUG_KMS("x[%d]y[%d]w[%d]h[%d]hsize[%d]vsize[%d]\n",
616 		pos->x, pos->y, pos->w, pos->h, sz->hsize, sz->vsize);
617 	DRM_DEBUG_KMS("h1[%d]h2[%d]v1[%d]v2[%d]\n", h1, h2, v1, v2);
618 
619 	/*
620 	 * set window offset 1, 2 size
621 	 * check figure 43-21 in user manual
622 	 */
623 	cfg = fimc_read(EXYNOS_CIWDOFST);
624 	cfg &= ~(EXYNOS_CIWDOFST_WINHOROFST_MASK |
625 		EXYNOS_CIWDOFST_WINVEROFST_MASK);
626 	cfg |= (EXYNOS_CIWDOFST_WINHOROFST(h1) |
627 		EXYNOS_CIWDOFST_WINVEROFST(v1));
628 	cfg |= EXYNOS_CIWDOFST_WINOFSEN;
629 	fimc_write(cfg, EXYNOS_CIWDOFST);
630 
631 	cfg = (EXYNOS_CIWDOFST2_WINHOROFST2(h2) |
632 		EXYNOS_CIWDOFST2_WINVEROFST2(v2));
633 	fimc_write(cfg, EXYNOS_CIWDOFST2);
634 
635 	return 0;
636 }
637 
638 static int fimc_src_set_size(struct device *dev, int swap,
639 		struct drm_exynos_pos *pos, struct drm_exynos_sz *sz)
640 {
641 	struct fimc_context *ctx = get_fimc_context(dev);
642 	struct drm_exynos_pos img_pos = *pos;
643 	struct drm_exynos_sz img_sz = *sz;
644 	u32 cfg;
645 
646 	DRM_DEBUG_KMS("swap[%d]hsize[%d]vsize[%d]\n",
647 		swap, sz->hsize, sz->vsize);
648 
649 	/* original size */
650 	cfg = (EXYNOS_ORGISIZE_HORIZONTAL(img_sz.hsize) |
651 		EXYNOS_ORGISIZE_VERTICAL(img_sz.vsize));
652 
653 	fimc_write(cfg, EXYNOS_ORGISIZE);
654 
655 	DRM_DEBUG_KMS("x[%d]y[%d]w[%d]h[%d]\n", pos->x, pos->y, pos->w, pos->h);
656 
657 	if (swap) {
658 		img_pos.w = pos->h;
659 		img_pos.h = pos->w;
660 		img_sz.hsize = sz->vsize;
661 		img_sz.vsize = sz->hsize;
662 	}
663 
664 	/* set input DMA image size */
665 	cfg = fimc_read(EXYNOS_CIREAL_ISIZE);
666 	cfg &= ~(EXYNOS_CIREAL_ISIZE_HEIGHT_MASK |
667 		EXYNOS_CIREAL_ISIZE_WIDTH_MASK);
668 	cfg |= (EXYNOS_CIREAL_ISIZE_WIDTH(img_pos.w) |
669 		EXYNOS_CIREAL_ISIZE_HEIGHT(img_pos.h));
670 	fimc_write(cfg, EXYNOS_CIREAL_ISIZE);
671 
672 	/*
673 	 * set input FIFO image size
674 	 * for now, we support only ITU601 8 bit mode
675 	 */
676 	cfg = (EXYNOS_CISRCFMT_ITU601_8BIT |
677 		EXYNOS_CISRCFMT_SOURCEHSIZE(img_sz.hsize) |
678 		EXYNOS_CISRCFMT_SOURCEVSIZE(img_sz.vsize));
679 	fimc_write(cfg, EXYNOS_CISRCFMT);
680 
681 	/* offset Y(RGB), Cb, Cr */
682 	cfg = (EXYNOS_CIIYOFF_HORIZONTAL(img_pos.x) |
683 		EXYNOS_CIIYOFF_VERTICAL(img_pos.y));
684 	fimc_write(cfg, EXYNOS_CIIYOFF);
685 	cfg = (EXYNOS_CIICBOFF_HORIZONTAL(img_pos.x) |
686 		EXYNOS_CIICBOFF_VERTICAL(img_pos.y));
687 	fimc_write(cfg, EXYNOS_CIICBOFF);
688 	cfg = (EXYNOS_CIICROFF_HORIZONTAL(img_pos.x) |
689 		EXYNOS_CIICROFF_VERTICAL(img_pos.y));
690 	fimc_write(cfg, EXYNOS_CIICROFF);
691 
692 	return fimc_set_window(ctx, &img_pos, &img_sz);
693 }
694 
695 static int fimc_src_set_addr(struct device *dev,
696 		struct drm_exynos_ipp_buf_info *buf_info, u32 buf_id,
697 		enum drm_exynos_ipp_buf_type buf_type)
698 {
699 	struct fimc_context *ctx = get_fimc_context(dev);
700 	struct exynos_drm_ippdrv *ippdrv = &ctx->ippdrv;
701 	struct drm_exynos_ipp_cmd_node *c_node = ippdrv->c_node;
702 	struct drm_exynos_ipp_property *property;
703 	struct drm_exynos_ipp_config *config;
704 
705 	if (!c_node) {
706 		DRM_ERROR("failed to get c_node.\n");
707 		return -EINVAL;
708 	}
709 
710 	property = &c_node->property;
711 
712 	DRM_DEBUG_KMS("prop_id[%d]buf_id[%d]buf_type[%d]\n",
713 		property->prop_id, buf_id, buf_type);
714 
715 	if (buf_id > FIMC_MAX_SRC) {
716 		dev_info(ippdrv->dev, "inavlid buf_id %d.\n", buf_id);
717 		return -ENOMEM;
718 	}
719 
720 	/* address register set */
721 	switch (buf_type) {
722 	case IPP_BUF_ENQUEUE:
723 		config = &property->config[EXYNOS_DRM_OPS_SRC];
724 		fimc_write(buf_info->base[EXYNOS_DRM_PLANAR_Y],
725 			EXYNOS_CIIYSA(buf_id));
726 
727 		if (config->fmt == DRM_FORMAT_YVU420) {
728 			fimc_write(buf_info->base[EXYNOS_DRM_PLANAR_CR],
729 				EXYNOS_CIICBSA(buf_id));
730 			fimc_write(buf_info->base[EXYNOS_DRM_PLANAR_CB],
731 				EXYNOS_CIICRSA(buf_id));
732 		} else {
733 			fimc_write(buf_info->base[EXYNOS_DRM_PLANAR_CB],
734 				EXYNOS_CIICBSA(buf_id));
735 			fimc_write(buf_info->base[EXYNOS_DRM_PLANAR_CR],
736 				EXYNOS_CIICRSA(buf_id));
737 		}
738 		break;
739 	case IPP_BUF_DEQUEUE:
740 		fimc_write(0x0, EXYNOS_CIIYSA(buf_id));
741 		fimc_write(0x0, EXYNOS_CIICBSA(buf_id));
742 		fimc_write(0x0, EXYNOS_CIICRSA(buf_id));
743 		break;
744 	default:
745 		/* bypass */
746 		break;
747 	}
748 
749 	return 0;
750 }
751 
752 static struct exynos_drm_ipp_ops fimc_src_ops = {
753 	.set_fmt = fimc_src_set_fmt,
754 	.set_transf = fimc_src_set_transf,
755 	.set_size = fimc_src_set_size,
756 	.set_addr = fimc_src_set_addr,
757 };
758 
759 static int fimc_dst_set_fmt_order(struct fimc_context *ctx, u32 fmt)
760 {
761 	struct exynos_drm_ippdrv *ippdrv = &ctx->ippdrv;
762 	u32 cfg;
763 
764 	DRM_DEBUG_KMS("fmt[0x%x]\n", fmt);
765 
766 	/* RGB */
767 	cfg = fimc_read(EXYNOS_CISCCTRL);
768 	cfg &= ~EXYNOS_CISCCTRL_OUTRGB_FMT_RGB_MASK;
769 
770 	switch (fmt) {
771 	case DRM_FORMAT_RGB565:
772 		cfg |= EXYNOS_CISCCTRL_OUTRGB_FMT_RGB565;
773 		fimc_write(cfg, EXYNOS_CISCCTRL);
774 		return 0;
775 	case DRM_FORMAT_RGB888:
776 		cfg |= EXYNOS_CISCCTRL_OUTRGB_FMT_RGB888;
777 		fimc_write(cfg, EXYNOS_CISCCTRL);
778 		return 0;
779 	case DRM_FORMAT_XRGB8888:
780 		cfg |= (EXYNOS_CISCCTRL_OUTRGB_FMT_RGB888 |
781 			EXYNOS_CISCCTRL_EXTRGB_EXTENSION);
782 		fimc_write(cfg, EXYNOS_CISCCTRL);
783 		break;
784 	default:
785 		/* bypass */
786 		break;
787 	}
788 
789 	/* YUV */
790 	cfg = fimc_read(EXYNOS_CIOCTRL);
791 	cfg &= ~(EXYNOS_CIOCTRL_ORDER2P_MASK |
792 		EXYNOS_CIOCTRL_ORDER422_MASK |
793 		EXYNOS_CIOCTRL_YCBCR_PLANE_MASK);
794 
795 	switch (fmt) {
796 	case DRM_FORMAT_XRGB8888:
797 		cfg |= EXYNOS_CIOCTRL_ALPHA_OUT;
798 		break;
799 	case DRM_FORMAT_YUYV:
800 		cfg |= EXYNOS_CIOCTRL_ORDER422_YCBYCR;
801 		break;
802 	case DRM_FORMAT_YVYU:
803 		cfg |= EXYNOS_CIOCTRL_ORDER422_YCRYCB;
804 		break;
805 	case DRM_FORMAT_UYVY:
806 		cfg |= EXYNOS_CIOCTRL_ORDER422_CBYCRY;
807 		break;
808 	case DRM_FORMAT_VYUY:
809 		cfg |= EXYNOS_CIOCTRL_ORDER422_CRYCBY;
810 		break;
811 	case DRM_FORMAT_NV21:
812 	case DRM_FORMAT_NV61:
813 		cfg |= EXYNOS_CIOCTRL_ORDER2P_LSB_CRCB;
814 		cfg |= EXYNOS_CIOCTRL_YCBCR_2PLANE;
815 		break;
816 	case DRM_FORMAT_YUV422:
817 	case DRM_FORMAT_YUV420:
818 	case DRM_FORMAT_YVU420:
819 		cfg |= EXYNOS_CIOCTRL_YCBCR_3PLANE;
820 		break;
821 	case DRM_FORMAT_NV12:
822 	case DRM_FORMAT_NV12MT:
823 	case DRM_FORMAT_NV16:
824 		cfg |= EXYNOS_CIOCTRL_ORDER2P_LSB_CBCR;
825 		cfg |= EXYNOS_CIOCTRL_YCBCR_2PLANE;
826 		break;
827 	default:
828 		dev_err(ippdrv->dev, "inavlid target yuv order 0x%x.\n", fmt);
829 		return -EINVAL;
830 	}
831 
832 	fimc_write(cfg, EXYNOS_CIOCTRL);
833 
834 	return 0;
835 }
836 
837 static int fimc_dst_set_fmt(struct device *dev, u32 fmt)
838 {
839 	struct fimc_context *ctx = get_fimc_context(dev);
840 	struct exynos_drm_ippdrv *ippdrv = &ctx->ippdrv;
841 	u32 cfg;
842 
843 	DRM_DEBUG_KMS("fmt[0x%x]\n", fmt);
844 
845 	cfg = fimc_read(EXYNOS_CIEXTEN);
846 
847 	if (fmt == DRM_FORMAT_AYUV) {
848 		cfg |= EXYNOS_CIEXTEN_YUV444_OUT;
849 		fimc_write(cfg, EXYNOS_CIEXTEN);
850 	} else {
851 		cfg &= ~EXYNOS_CIEXTEN_YUV444_OUT;
852 		fimc_write(cfg, EXYNOS_CIEXTEN);
853 
854 		cfg = fimc_read(EXYNOS_CITRGFMT);
855 		cfg &= ~EXYNOS_CITRGFMT_OUTFORMAT_MASK;
856 
857 		switch (fmt) {
858 		case DRM_FORMAT_RGB565:
859 		case DRM_FORMAT_RGB888:
860 		case DRM_FORMAT_XRGB8888:
861 			cfg |= EXYNOS_CITRGFMT_OUTFORMAT_RGB;
862 			break;
863 		case DRM_FORMAT_YUYV:
864 		case DRM_FORMAT_YVYU:
865 		case DRM_FORMAT_UYVY:
866 		case DRM_FORMAT_VYUY:
867 			cfg |= EXYNOS_CITRGFMT_OUTFORMAT_YCBCR422_1PLANE;
868 			break;
869 		case DRM_FORMAT_NV16:
870 		case DRM_FORMAT_NV61:
871 		case DRM_FORMAT_YUV422:
872 			cfg |= EXYNOS_CITRGFMT_OUTFORMAT_YCBCR422;
873 			break;
874 		case DRM_FORMAT_YUV420:
875 		case DRM_FORMAT_YVU420:
876 		case DRM_FORMAT_NV12:
877 		case DRM_FORMAT_NV12MT:
878 		case DRM_FORMAT_NV21:
879 			cfg |= EXYNOS_CITRGFMT_OUTFORMAT_YCBCR420;
880 			break;
881 		default:
882 			dev_err(ippdrv->dev, "inavlid target format 0x%x.\n",
883 				fmt);
884 			return -EINVAL;
885 		}
886 
887 		fimc_write(cfg, EXYNOS_CITRGFMT);
888 	}
889 
890 	cfg = fimc_read(EXYNOS_CIDMAPARAM);
891 	cfg &= ~EXYNOS_CIDMAPARAM_W_MODE_MASK;
892 
893 	if (fmt == DRM_FORMAT_NV12MT)
894 		cfg |= EXYNOS_CIDMAPARAM_W_MODE_64X32;
895 	else
896 		cfg |= EXYNOS_CIDMAPARAM_W_MODE_LINEAR;
897 
898 	fimc_write(cfg, EXYNOS_CIDMAPARAM);
899 
900 	return fimc_dst_set_fmt_order(ctx, fmt);
901 }
902 
903 static int fimc_dst_set_transf(struct device *dev,
904 		enum drm_exynos_degree degree,
905 		enum drm_exynos_flip flip, bool *swap)
906 {
907 	struct fimc_context *ctx = get_fimc_context(dev);
908 	struct exynos_drm_ippdrv *ippdrv = &ctx->ippdrv;
909 	u32 cfg;
910 
911 	DRM_DEBUG_KMS("degree[%d]flip[0x%x]\n", degree, flip);
912 
913 	cfg = fimc_read(EXYNOS_CITRGFMT);
914 	cfg &= ~EXYNOS_CITRGFMT_FLIP_MASK;
915 	cfg &= ~EXYNOS_CITRGFMT_OUTROT90_CLOCKWISE;
916 
917 	switch (degree) {
918 	case EXYNOS_DRM_DEGREE_0:
919 		if (flip & EXYNOS_DRM_FLIP_VERTICAL)
920 			cfg |= EXYNOS_CITRGFMT_FLIP_X_MIRROR;
921 		if (flip & EXYNOS_DRM_FLIP_HORIZONTAL)
922 			cfg |= EXYNOS_CITRGFMT_FLIP_Y_MIRROR;
923 		break;
924 	case EXYNOS_DRM_DEGREE_90:
925 		cfg |= EXYNOS_CITRGFMT_OUTROT90_CLOCKWISE;
926 		if (flip & EXYNOS_DRM_FLIP_VERTICAL)
927 			cfg |= EXYNOS_CITRGFMT_FLIP_X_MIRROR;
928 		if (flip & EXYNOS_DRM_FLIP_HORIZONTAL)
929 			cfg |= EXYNOS_CITRGFMT_FLIP_Y_MIRROR;
930 		break;
931 	case EXYNOS_DRM_DEGREE_180:
932 		cfg |= (EXYNOS_CITRGFMT_FLIP_X_MIRROR |
933 			EXYNOS_CITRGFMT_FLIP_Y_MIRROR);
934 		if (flip & EXYNOS_DRM_FLIP_VERTICAL)
935 			cfg &= ~EXYNOS_CITRGFMT_FLIP_X_MIRROR;
936 		if (flip & EXYNOS_DRM_FLIP_HORIZONTAL)
937 			cfg &= ~EXYNOS_CITRGFMT_FLIP_Y_MIRROR;
938 		break;
939 	case EXYNOS_DRM_DEGREE_270:
940 		cfg |= (EXYNOS_CITRGFMT_OUTROT90_CLOCKWISE |
941 			EXYNOS_CITRGFMT_FLIP_X_MIRROR |
942 			EXYNOS_CITRGFMT_FLIP_Y_MIRROR);
943 		if (flip & EXYNOS_DRM_FLIP_VERTICAL)
944 			cfg &= ~EXYNOS_CITRGFMT_FLIP_X_MIRROR;
945 		if (flip & EXYNOS_DRM_FLIP_HORIZONTAL)
946 			cfg &= ~EXYNOS_CITRGFMT_FLIP_Y_MIRROR;
947 		break;
948 	default:
949 		dev_err(ippdrv->dev, "inavlid degree value %d.\n", degree);
950 		return -EINVAL;
951 	}
952 
953 	fimc_write(cfg, EXYNOS_CITRGFMT);
954 	*swap = (cfg & EXYNOS_CITRGFMT_OUTROT90_CLOCKWISE) ? 1 : 0;
955 
956 	return 0;
957 }
958 
959 static int fimc_get_ratio_shift(u32 src, u32 dst, u32 *ratio, u32 *shift)
960 {
961 	DRM_DEBUG_KMS("src[%d]dst[%d]\n", src, dst);
962 
963 	if (src >= dst * 64) {
964 		DRM_ERROR("failed to make ratio and shift.\n");
965 		return -EINVAL;
966 	} else if (src >= dst * 32) {
967 		*ratio = 32;
968 		*shift = 5;
969 	} else if (src >= dst * 16) {
970 		*ratio = 16;
971 		*shift = 4;
972 	} else if (src >= dst * 8) {
973 		*ratio = 8;
974 		*shift = 3;
975 	} else if (src >= dst * 4) {
976 		*ratio = 4;
977 		*shift = 2;
978 	} else if (src >= dst * 2) {
979 		*ratio = 2;
980 		*shift = 1;
981 	} else {
982 		*ratio = 1;
983 		*shift = 0;
984 	}
985 
986 	return 0;
987 }
988 
989 static int fimc_set_prescaler(struct fimc_context *ctx, struct fimc_scaler *sc,
990 		struct drm_exynos_pos *src, struct drm_exynos_pos *dst)
991 {
992 	struct exynos_drm_ippdrv *ippdrv = &ctx->ippdrv;
993 	u32 cfg, cfg_ext, shfactor;
994 	u32 pre_dst_width, pre_dst_height;
995 	u32 pre_hratio, hfactor, pre_vratio, vfactor;
996 	int ret = 0;
997 	u32 src_w, src_h, dst_w, dst_h;
998 
999 	cfg_ext = fimc_read(EXYNOS_CITRGFMT);
1000 	if (cfg_ext & EXYNOS_CITRGFMT_INROT90_CLOCKWISE) {
1001 		src_w = src->h;
1002 		src_h = src->w;
1003 	} else {
1004 		src_w = src->w;
1005 		src_h = src->h;
1006 	}
1007 
1008 	if (cfg_ext & EXYNOS_CITRGFMT_OUTROT90_CLOCKWISE) {
1009 		dst_w = dst->h;
1010 		dst_h = dst->w;
1011 	} else {
1012 		dst_w = dst->w;
1013 		dst_h = dst->h;
1014 	}
1015 
1016 	ret = fimc_get_ratio_shift(src_w, dst_w, &pre_hratio, &hfactor);
1017 	if (ret) {
1018 		dev_err(ippdrv->dev, "failed to get ratio horizontal.\n");
1019 		return ret;
1020 	}
1021 
1022 	ret = fimc_get_ratio_shift(src_h, dst_h, &pre_vratio, &vfactor);
1023 	if (ret) {
1024 		dev_err(ippdrv->dev, "failed to get ratio vertical.\n");
1025 		return ret;
1026 	}
1027 
1028 	pre_dst_width = src_w / pre_hratio;
1029 	pre_dst_height = src_h / pre_vratio;
1030 	DRM_DEBUG_KMS("pre_dst_width[%d]pre_dst_height[%d]\n",
1031 		pre_dst_width, pre_dst_height);
1032 	DRM_DEBUG_KMS("pre_hratio[%d]hfactor[%d]pre_vratio[%d]vfactor[%d]\n",
1033 		pre_hratio, hfactor, pre_vratio, vfactor);
1034 
1035 	sc->hratio = (src_w << 14) / (dst_w << hfactor);
1036 	sc->vratio = (src_h << 14) / (dst_h << vfactor);
1037 	sc->up_h = (dst_w >= src_w) ? true : false;
1038 	sc->up_v = (dst_h >= src_h) ? true : false;
1039 	DRM_DEBUG_KMS("hratio[%d]vratio[%d]up_h[%d]up_v[%d]\n",
1040 		sc->hratio, sc->vratio, sc->up_h, sc->up_v);
1041 
1042 	shfactor = FIMC_SHFACTOR - (hfactor + vfactor);
1043 	DRM_DEBUG_KMS("shfactor[%d]\n", shfactor);
1044 
1045 	cfg = (EXYNOS_CISCPRERATIO_SHFACTOR(shfactor) |
1046 		EXYNOS_CISCPRERATIO_PREHORRATIO(pre_hratio) |
1047 		EXYNOS_CISCPRERATIO_PREVERRATIO(pre_vratio));
1048 	fimc_write(cfg, EXYNOS_CISCPRERATIO);
1049 
1050 	cfg = (EXYNOS_CISCPREDST_PREDSTWIDTH(pre_dst_width) |
1051 		EXYNOS_CISCPREDST_PREDSTHEIGHT(pre_dst_height));
1052 	fimc_write(cfg, EXYNOS_CISCPREDST);
1053 
1054 	return ret;
1055 }
1056 
1057 static void fimc_set_scaler(struct fimc_context *ctx, struct fimc_scaler *sc)
1058 {
1059 	u32 cfg, cfg_ext;
1060 
1061 	DRM_DEBUG_KMS("range[%d]bypass[%d]up_h[%d]up_v[%d]\n",
1062 		sc->range, sc->bypass, sc->up_h, sc->up_v);
1063 	DRM_DEBUG_KMS("hratio[%d]vratio[%d]\n",
1064 		sc->hratio, sc->vratio);
1065 
1066 	cfg = fimc_read(EXYNOS_CISCCTRL);
1067 	cfg &= ~(EXYNOS_CISCCTRL_SCALERBYPASS |
1068 		EXYNOS_CISCCTRL_SCALEUP_H | EXYNOS_CISCCTRL_SCALEUP_V |
1069 		EXYNOS_CISCCTRL_MAIN_V_RATIO_MASK |
1070 		EXYNOS_CISCCTRL_MAIN_H_RATIO_MASK |
1071 		EXYNOS_CISCCTRL_CSCR2Y_WIDE |
1072 		EXYNOS_CISCCTRL_CSCY2R_WIDE);
1073 
1074 	if (sc->range)
1075 		cfg |= (EXYNOS_CISCCTRL_CSCR2Y_WIDE |
1076 			EXYNOS_CISCCTRL_CSCY2R_WIDE);
1077 	if (sc->bypass)
1078 		cfg |= EXYNOS_CISCCTRL_SCALERBYPASS;
1079 	if (sc->up_h)
1080 		cfg |= EXYNOS_CISCCTRL_SCALEUP_H;
1081 	if (sc->up_v)
1082 		cfg |= EXYNOS_CISCCTRL_SCALEUP_V;
1083 
1084 	cfg |= (EXYNOS_CISCCTRL_MAINHORRATIO((sc->hratio >> 6)) |
1085 		EXYNOS_CISCCTRL_MAINVERRATIO((sc->vratio >> 6)));
1086 	fimc_write(cfg, EXYNOS_CISCCTRL);
1087 
1088 	cfg_ext = fimc_read(EXYNOS_CIEXTEN);
1089 	cfg_ext &= ~EXYNOS_CIEXTEN_MAINHORRATIO_EXT_MASK;
1090 	cfg_ext &= ~EXYNOS_CIEXTEN_MAINVERRATIO_EXT_MASK;
1091 	cfg_ext |= (EXYNOS_CIEXTEN_MAINHORRATIO_EXT(sc->hratio) |
1092 		EXYNOS_CIEXTEN_MAINVERRATIO_EXT(sc->vratio));
1093 	fimc_write(cfg_ext, EXYNOS_CIEXTEN);
1094 }
1095 
1096 static int fimc_dst_set_size(struct device *dev, int swap,
1097 		struct drm_exynos_pos *pos, struct drm_exynos_sz *sz)
1098 {
1099 	struct fimc_context *ctx = get_fimc_context(dev);
1100 	struct drm_exynos_pos img_pos = *pos;
1101 	struct drm_exynos_sz img_sz = *sz;
1102 	u32 cfg;
1103 
1104 	DRM_DEBUG_KMS("swap[%d]hsize[%d]vsize[%d]\n",
1105 		swap, sz->hsize, sz->vsize);
1106 
1107 	/* original size */
1108 	cfg = (EXYNOS_ORGOSIZE_HORIZONTAL(img_sz.hsize) |
1109 		EXYNOS_ORGOSIZE_VERTICAL(img_sz.vsize));
1110 
1111 	fimc_write(cfg, EXYNOS_ORGOSIZE);
1112 
1113 	DRM_DEBUG_KMS("x[%d]y[%d]w[%d]h[%d]\n", pos->x, pos->y, pos->w, pos->h);
1114 
1115 	/* CSC ITU */
1116 	cfg = fimc_read(EXYNOS_CIGCTRL);
1117 	cfg &= ~EXYNOS_CIGCTRL_CSC_MASK;
1118 
1119 	if (sz->hsize >= FIMC_WIDTH_ITU_709)
1120 		cfg |= EXYNOS_CIGCTRL_CSC_ITU709;
1121 	else
1122 		cfg |= EXYNOS_CIGCTRL_CSC_ITU601;
1123 
1124 	fimc_write(cfg, EXYNOS_CIGCTRL);
1125 
1126 	if (swap) {
1127 		img_pos.w = pos->h;
1128 		img_pos.h = pos->w;
1129 		img_sz.hsize = sz->vsize;
1130 		img_sz.vsize = sz->hsize;
1131 	}
1132 
1133 	/* target image size */
1134 	cfg = fimc_read(EXYNOS_CITRGFMT);
1135 	cfg &= ~(EXYNOS_CITRGFMT_TARGETH_MASK |
1136 		EXYNOS_CITRGFMT_TARGETV_MASK);
1137 	cfg |= (EXYNOS_CITRGFMT_TARGETHSIZE(img_pos.w) |
1138 		EXYNOS_CITRGFMT_TARGETVSIZE(img_pos.h));
1139 	fimc_write(cfg, EXYNOS_CITRGFMT);
1140 
1141 	/* target area */
1142 	cfg = EXYNOS_CITAREA_TARGET_AREA(img_pos.w * img_pos.h);
1143 	fimc_write(cfg, EXYNOS_CITAREA);
1144 
1145 	/* offset Y(RGB), Cb, Cr */
1146 	cfg = (EXYNOS_CIOYOFF_HORIZONTAL(img_pos.x) |
1147 		EXYNOS_CIOYOFF_VERTICAL(img_pos.y));
1148 	fimc_write(cfg, EXYNOS_CIOYOFF);
1149 	cfg = (EXYNOS_CIOCBOFF_HORIZONTAL(img_pos.x) |
1150 		EXYNOS_CIOCBOFF_VERTICAL(img_pos.y));
1151 	fimc_write(cfg, EXYNOS_CIOCBOFF);
1152 	cfg = (EXYNOS_CIOCROFF_HORIZONTAL(img_pos.x) |
1153 		EXYNOS_CIOCROFF_VERTICAL(img_pos.y));
1154 	fimc_write(cfg, EXYNOS_CIOCROFF);
1155 
1156 	return 0;
1157 }
1158 
1159 static int fimc_dst_get_buf_seq(struct fimc_context *ctx)
1160 {
1161 	u32 cfg, i, buf_num = 0;
1162 	u32 mask = 0x00000001;
1163 
1164 	cfg = fimc_read(EXYNOS_CIFCNTSEQ);
1165 
1166 	for (i = 0; i < FIMC_REG_SZ; i++)
1167 		if (cfg & (mask << i))
1168 			buf_num++;
1169 
1170 	DRM_DEBUG_KMS("buf_num[%d]\n", buf_num);
1171 
1172 	return buf_num;
1173 }
1174 
1175 static int fimc_dst_set_buf_seq(struct fimc_context *ctx, u32 buf_id,
1176 		enum drm_exynos_ipp_buf_type buf_type)
1177 {
1178 	struct exynos_drm_ippdrv *ippdrv = &ctx->ippdrv;
1179 	bool enable;
1180 	u32 cfg;
1181 	u32 mask = 0x00000001 << buf_id;
1182 	int ret = 0;
1183 
1184 	DRM_DEBUG_KMS("buf_id[%d]buf_type[%d]\n", buf_id, buf_type);
1185 
1186 	mutex_lock(&ctx->lock);
1187 
1188 	/* mask register set */
1189 	cfg = fimc_read(EXYNOS_CIFCNTSEQ);
1190 
1191 	switch (buf_type) {
1192 	case IPP_BUF_ENQUEUE:
1193 		enable = true;
1194 		break;
1195 	case IPP_BUF_DEQUEUE:
1196 		enable = false;
1197 		break;
1198 	default:
1199 		dev_err(ippdrv->dev, "invalid buf ctrl parameter.\n");
1200 		ret =  -EINVAL;
1201 		goto err_unlock;
1202 	}
1203 
1204 	/* sequence id */
1205 	cfg &= ~mask;
1206 	cfg |= (enable << buf_id);
1207 	fimc_write(cfg, EXYNOS_CIFCNTSEQ);
1208 
1209 	/* interrupt enable */
1210 	if (buf_type == IPP_BUF_ENQUEUE &&
1211 	    fimc_dst_get_buf_seq(ctx) >= FIMC_BUF_START)
1212 		fimc_handle_irq(ctx, true, false, true);
1213 
1214 	/* interrupt disable */
1215 	if (buf_type == IPP_BUF_DEQUEUE &&
1216 	    fimc_dst_get_buf_seq(ctx) <= FIMC_BUF_STOP)
1217 		fimc_handle_irq(ctx, false, false, true);
1218 
1219 err_unlock:
1220 	mutex_unlock(&ctx->lock);
1221 	return ret;
1222 }
1223 
1224 static int fimc_dst_set_addr(struct device *dev,
1225 		struct drm_exynos_ipp_buf_info *buf_info, u32 buf_id,
1226 		enum drm_exynos_ipp_buf_type buf_type)
1227 {
1228 	struct fimc_context *ctx = get_fimc_context(dev);
1229 	struct exynos_drm_ippdrv *ippdrv = &ctx->ippdrv;
1230 	struct drm_exynos_ipp_cmd_node *c_node = ippdrv->c_node;
1231 	struct drm_exynos_ipp_property *property;
1232 	struct drm_exynos_ipp_config *config;
1233 
1234 	if (!c_node) {
1235 		DRM_ERROR("failed to get c_node.\n");
1236 		return -EINVAL;
1237 	}
1238 
1239 	property = &c_node->property;
1240 
1241 	DRM_DEBUG_KMS("prop_id[%d]buf_id[%d]buf_type[%d]\n",
1242 		property->prop_id, buf_id, buf_type);
1243 
1244 	if (buf_id > FIMC_MAX_DST) {
1245 		dev_info(ippdrv->dev, "inavlid buf_id %d.\n", buf_id);
1246 		return -ENOMEM;
1247 	}
1248 
1249 	/* address register set */
1250 	switch (buf_type) {
1251 	case IPP_BUF_ENQUEUE:
1252 		config = &property->config[EXYNOS_DRM_OPS_DST];
1253 
1254 		fimc_write(buf_info->base[EXYNOS_DRM_PLANAR_Y],
1255 			EXYNOS_CIOYSA(buf_id));
1256 
1257 		if (config->fmt == DRM_FORMAT_YVU420) {
1258 			fimc_write(buf_info->base[EXYNOS_DRM_PLANAR_CR],
1259 				EXYNOS_CIOCBSA(buf_id));
1260 			fimc_write(buf_info->base[EXYNOS_DRM_PLANAR_CB],
1261 				EXYNOS_CIOCRSA(buf_id));
1262 		} else {
1263 			fimc_write(buf_info->base[EXYNOS_DRM_PLANAR_CB],
1264 				EXYNOS_CIOCBSA(buf_id));
1265 			fimc_write(buf_info->base[EXYNOS_DRM_PLANAR_CR],
1266 				EXYNOS_CIOCRSA(buf_id));
1267 		}
1268 		break;
1269 	case IPP_BUF_DEQUEUE:
1270 		fimc_write(0x0, EXYNOS_CIOYSA(buf_id));
1271 		fimc_write(0x0, EXYNOS_CIOCBSA(buf_id));
1272 		fimc_write(0x0, EXYNOS_CIOCRSA(buf_id));
1273 		break;
1274 	default:
1275 		/* bypass */
1276 		break;
1277 	}
1278 
1279 	return fimc_dst_set_buf_seq(ctx, buf_id, buf_type);
1280 }
1281 
1282 static struct exynos_drm_ipp_ops fimc_dst_ops = {
1283 	.set_fmt = fimc_dst_set_fmt,
1284 	.set_transf = fimc_dst_set_transf,
1285 	.set_size = fimc_dst_set_size,
1286 	.set_addr = fimc_dst_set_addr,
1287 };
1288 
1289 static int fimc_clk_ctrl(struct fimc_context *ctx, bool enable)
1290 {
1291 	DRM_DEBUG_KMS("enable[%d]\n", enable);
1292 
1293 	if (enable) {
1294 		clk_prepare_enable(ctx->clocks[FIMC_CLK_GATE]);
1295 		clk_prepare_enable(ctx->clocks[FIMC_CLK_WB_A]);
1296 		ctx->suspended = false;
1297 	} else {
1298 		clk_disable_unprepare(ctx->clocks[FIMC_CLK_GATE]);
1299 		clk_disable_unprepare(ctx->clocks[FIMC_CLK_WB_A]);
1300 		ctx->suspended = true;
1301 	}
1302 
1303 	return 0;
1304 }
1305 
1306 static irqreturn_t fimc_irq_handler(int irq, void *dev_id)
1307 {
1308 	struct fimc_context *ctx = dev_id;
1309 	struct exynos_drm_ippdrv *ippdrv = &ctx->ippdrv;
1310 	struct drm_exynos_ipp_cmd_node *c_node = ippdrv->c_node;
1311 	struct drm_exynos_ipp_event_work *event_work =
1312 		c_node->event_work;
1313 	int buf_id;
1314 
1315 	DRM_DEBUG_KMS("fimc id[%d]\n", ctx->id);
1316 
1317 	fimc_clear_irq(ctx);
1318 	if (fimc_check_ovf(ctx))
1319 		return IRQ_NONE;
1320 
1321 	if (!fimc_check_frame_end(ctx))
1322 		return IRQ_NONE;
1323 
1324 	buf_id = fimc_get_buf_id(ctx);
1325 	if (buf_id < 0)
1326 		return IRQ_HANDLED;
1327 
1328 	DRM_DEBUG_KMS("buf_id[%d]\n", buf_id);
1329 
1330 	if (fimc_dst_set_buf_seq(ctx, buf_id, IPP_BUF_DEQUEUE) < 0) {
1331 		DRM_ERROR("failed to dequeue.\n");
1332 		return IRQ_HANDLED;
1333 	}
1334 
1335 	event_work->ippdrv = ippdrv;
1336 	event_work->buf_id[EXYNOS_DRM_OPS_DST] = buf_id;
1337 	queue_work(ippdrv->event_workq, (struct work_struct *)event_work);
1338 
1339 	return IRQ_HANDLED;
1340 }
1341 
1342 static int fimc_init_prop_list(struct exynos_drm_ippdrv *ippdrv)
1343 {
1344 	struct drm_exynos_ipp_prop_list *prop_list;
1345 
1346 	prop_list = devm_kzalloc(ippdrv->dev, sizeof(*prop_list), GFP_KERNEL);
1347 	if (!prop_list) {
1348 		DRM_ERROR("failed to alloc property list.\n");
1349 		return -ENOMEM;
1350 	}
1351 
1352 	prop_list->version = 1;
1353 	prop_list->writeback = 1;
1354 	prop_list->refresh_min = FIMC_REFRESH_MIN;
1355 	prop_list->refresh_max = FIMC_REFRESH_MAX;
1356 	prop_list->flip = (1 << EXYNOS_DRM_FLIP_NONE) |
1357 				(1 << EXYNOS_DRM_FLIP_VERTICAL) |
1358 				(1 << EXYNOS_DRM_FLIP_HORIZONTAL);
1359 	prop_list->degree = (1 << EXYNOS_DRM_DEGREE_0) |
1360 				(1 << EXYNOS_DRM_DEGREE_90) |
1361 				(1 << EXYNOS_DRM_DEGREE_180) |
1362 				(1 << EXYNOS_DRM_DEGREE_270);
1363 	prop_list->csc = 1;
1364 	prop_list->crop = 1;
1365 	prop_list->crop_max.hsize = FIMC_CROP_MAX;
1366 	prop_list->crop_max.vsize = FIMC_CROP_MAX;
1367 	prop_list->crop_min.hsize = FIMC_CROP_MIN;
1368 	prop_list->crop_min.vsize = FIMC_CROP_MIN;
1369 	prop_list->scale = 1;
1370 	prop_list->scale_max.hsize = FIMC_SCALE_MAX;
1371 	prop_list->scale_max.vsize = FIMC_SCALE_MAX;
1372 	prop_list->scale_min.hsize = FIMC_SCALE_MIN;
1373 	prop_list->scale_min.vsize = FIMC_SCALE_MIN;
1374 
1375 	ippdrv->prop_list = prop_list;
1376 
1377 	return 0;
1378 }
1379 
1380 static inline bool fimc_check_drm_flip(enum drm_exynos_flip flip)
1381 {
1382 	switch (flip) {
1383 	case EXYNOS_DRM_FLIP_NONE:
1384 	case EXYNOS_DRM_FLIP_VERTICAL:
1385 	case EXYNOS_DRM_FLIP_HORIZONTAL:
1386 	case EXYNOS_DRM_FLIP_BOTH:
1387 		return true;
1388 	default:
1389 		DRM_DEBUG_KMS("invalid flip\n");
1390 		return false;
1391 	}
1392 }
1393 
1394 static int fimc_ippdrv_check_property(struct device *dev,
1395 		struct drm_exynos_ipp_property *property)
1396 {
1397 	struct fimc_context *ctx = get_fimc_context(dev);
1398 	struct exynos_drm_ippdrv *ippdrv = &ctx->ippdrv;
1399 	struct drm_exynos_ipp_prop_list *pp = ippdrv->prop_list;
1400 	struct drm_exynos_ipp_config *config;
1401 	struct drm_exynos_pos *pos;
1402 	struct drm_exynos_sz *sz;
1403 	bool swap;
1404 	int i;
1405 
1406 	for_each_ipp_ops(i) {
1407 		if ((i == EXYNOS_DRM_OPS_SRC) &&
1408 			(property->cmd == IPP_CMD_WB))
1409 			continue;
1410 
1411 		config = &property->config[i];
1412 		pos = &config->pos;
1413 		sz = &config->sz;
1414 
1415 		/* check for flip */
1416 		if (!fimc_check_drm_flip(config->flip)) {
1417 			DRM_ERROR("invalid flip.\n");
1418 			goto err_property;
1419 		}
1420 
1421 		/* check for degree */
1422 		switch (config->degree) {
1423 		case EXYNOS_DRM_DEGREE_90:
1424 		case EXYNOS_DRM_DEGREE_270:
1425 			swap = true;
1426 			break;
1427 		case EXYNOS_DRM_DEGREE_0:
1428 		case EXYNOS_DRM_DEGREE_180:
1429 			swap = false;
1430 			break;
1431 		default:
1432 			DRM_ERROR("invalid degree.\n");
1433 			goto err_property;
1434 		}
1435 
1436 		/* check for buffer bound */
1437 		if ((pos->x + pos->w > sz->hsize) ||
1438 			(pos->y + pos->h > sz->vsize)) {
1439 			DRM_ERROR("out of buf bound.\n");
1440 			goto err_property;
1441 		}
1442 
1443 		/* check for crop */
1444 		if ((i == EXYNOS_DRM_OPS_SRC) && (pp->crop)) {
1445 			if (swap) {
1446 				if ((pos->h < pp->crop_min.hsize) ||
1447 					(sz->vsize > pp->crop_max.hsize) ||
1448 					(pos->w < pp->crop_min.vsize) ||
1449 					(sz->hsize > pp->crop_max.vsize)) {
1450 					DRM_ERROR("out of crop size.\n");
1451 					goto err_property;
1452 				}
1453 			} else {
1454 				if ((pos->w < pp->crop_min.hsize) ||
1455 					(sz->hsize > pp->crop_max.hsize) ||
1456 					(pos->h < pp->crop_min.vsize) ||
1457 					(sz->vsize > pp->crop_max.vsize)) {
1458 					DRM_ERROR("out of crop size.\n");
1459 					goto err_property;
1460 				}
1461 			}
1462 		}
1463 
1464 		/* check for scale */
1465 		if ((i == EXYNOS_DRM_OPS_DST) && (pp->scale)) {
1466 			if (swap) {
1467 				if ((pos->h < pp->scale_min.hsize) ||
1468 					(sz->vsize > pp->scale_max.hsize) ||
1469 					(pos->w < pp->scale_min.vsize) ||
1470 					(sz->hsize > pp->scale_max.vsize)) {
1471 					DRM_ERROR("out of scale size.\n");
1472 					goto err_property;
1473 				}
1474 			} else {
1475 				if ((pos->w < pp->scale_min.hsize) ||
1476 					(sz->hsize > pp->scale_max.hsize) ||
1477 					(pos->h < pp->scale_min.vsize) ||
1478 					(sz->vsize > pp->scale_max.vsize)) {
1479 					DRM_ERROR("out of scale size.\n");
1480 					goto err_property;
1481 				}
1482 			}
1483 		}
1484 	}
1485 
1486 	return 0;
1487 
1488 err_property:
1489 	for_each_ipp_ops(i) {
1490 		if ((i == EXYNOS_DRM_OPS_SRC) &&
1491 			(property->cmd == IPP_CMD_WB))
1492 			continue;
1493 
1494 		config = &property->config[i];
1495 		pos = &config->pos;
1496 		sz = &config->sz;
1497 
1498 		DRM_ERROR("[%s]f[%d]r[%d]pos[%d %d %d %d]sz[%d %d]\n",
1499 			i ? "dst" : "src", config->flip, config->degree,
1500 			pos->x, pos->y, pos->w, pos->h,
1501 			sz->hsize, sz->vsize);
1502 	}
1503 
1504 	return -EINVAL;
1505 }
1506 
1507 static void fimc_clear_addr(struct fimc_context *ctx)
1508 {
1509 	int i;
1510 
1511 	for (i = 0; i < FIMC_MAX_SRC; i++) {
1512 		fimc_write(0, EXYNOS_CIIYSA(i));
1513 		fimc_write(0, EXYNOS_CIICBSA(i));
1514 		fimc_write(0, EXYNOS_CIICRSA(i));
1515 	}
1516 
1517 	for (i = 0; i < FIMC_MAX_DST; i++) {
1518 		fimc_write(0, EXYNOS_CIOYSA(i));
1519 		fimc_write(0, EXYNOS_CIOCBSA(i));
1520 		fimc_write(0, EXYNOS_CIOCRSA(i));
1521 	}
1522 }
1523 
1524 static int fimc_ippdrv_reset(struct device *dev)
1525 {
1526 	struct fimc_context *ctx = get_fimc_context(dev);
1527 
1528 	/* reset h/w block */
1529 	fimc_sw_reset(ctx);
1530 
1531 	/* reset scaler capability */
1532 	memset(&ctx->sc, 0x0, sizeof(ctx->sc));
1533 
1534 	fimc_clear_addr(ctx);
1535 
1536 	return 0;
1537 }
1538 
1539 static int fimc_ippdrv_start(struct device *dev, enum drm_exynos_ipp_cmd cmd)
1540 {
1541 	struct fimc_context *ctx = get_fimc_context(dev);
1542 	struct exynos_drm_ippdrv *ippdrv = &ctx->ippdrv;
1543 	struct drm_exynos_ipp_cmd_node *c_node = ippdrv->c_node;
1544 	struct drm_exynos_ipp_property *property;
1545 	struct drm_exynos_ipp_config *config;
1546 	struct drm_exynos_pos	img_pos[EXYNOS_DRM_OPS_MAX];
1547 	struct drm_exynos_ipp_set_wb set_wb;
1548 	int ret, i;
1549 	u32 cfg0, cfg1;
1550 
1551 	DRM_DEBUG_KMS("cmd[%d]\n", cmd);
1552 
1553 	if (!c_node) {
1554 		DRM_ERROR("failed to get c_node.\n");
1555 		return -EINVAL;
1556 	}
1557 
1558 	property = &c_node->property;
1559 
1560 	fimc_handle_irq(ctx, true, false, true);
1561 
1562 	for_each_ipp_ops(i) {
1563 		config = &property->config[i];
1564 		img_pos[i] = config->pos;
1565 	}
1566 
1567 	ret = fimc_set_prescaler(ctx, &ctx->sc,
1568 		&img_pos[EXYNOS_DRM_OPS_SRC],
1569 		&img_pos[EXYNOS_DRM_OPS_DST]);
1570 	if (ret) {
1571 		dev_err(dev, "failed to set precalser.\n");
1572 		return ret;
1573 	}
1574 
1575 	/* If set ture, we can save jpeg about screen */
1576 	fimc_handle_jpeg(ctx, false);
1577 	fimc_set_scaler(ctx, &ctx->sc);
1578 	fimc_set_polarity(ctx, &ctx->pol);
1579 
1580 	switch (cmd) {
1581 	case IPP_CMD_M2M:
1582 		fimc_set_type_ctrl(ctx, FIMC_WB_NONE);
1583 		fimc_handle_lastend(ctx, false);
1584 
1585 		/* setup dma */
1586 		cfg0 = fimc_read(EXYNOS_MSCTRL);
1587 		cfg0 &= ~EXYNOS_MSCTRL_INPUT_MASK;
1588 		cfg0 |= EXYNOS_MSCTRL_INPUT_MEMORY;
1589 		fimc_write(cfg0, EXYNOS_MSCTRL);
1590 		break;
1591 	case IPP_CMD_WB:
1592 		fimc_set_type_ctrl(ctx, FIMC_WB_A);
1593 		fimc_handle_lastend(ctx, true);
1594 
1595 		/* setup FIMD */
1596 		ret = fimc_set_camblk_fimd0_wb(ctx);
1597 		if (ret < 0) {
1598 			dev_err(dev, "camblk setup failed.\n");
1599 			return ret;
1600 		}
1601 
1602 		set_wb.enable = 1;
1603 		set_wb.refresh = property->refresh_rate;
1604 		exynos_drm_ippnb_send_event(IPP_SET_WRITEBACK, (void *)&set_wb);
1605 		break;
1606 	case IPP_CMD_OUTPUT:
1607 	default:
1608 		ret = -EINVAL;
1609 		dev_err(dev, "invalid operations.\n");
1610 		return ret;
1611 	}
1612 
1613 	/* Reset status */
1614 	fimc_write(0x0, EXYNOS_CISTATUS);
1615 
1616 	cfg0 = fimc_read(EXYNOS_CIIMGCPT);
1617 	cfg0 &= ~EXYNOS_CIIMGCPT_IMGCPTEN_SC;
1618 	cfg0 |= EXYNOS_CIIMGCPT_IMGCPTEN_SC;
1619 
1620 	/* Scaler */
1621 	cfg1 = fimc_read(EXYNOS_CISCCTRL);
1622 	cfg1 &= ~EXYNOS_CISCCTRL_SCAN_MASK;
1623 	cfg1 |= (EXYNOS_CISCCTRL_PROGRESSIVE |
1624 		EXYNOS_CISCCTRL_SCALERSTART);
1625 
1626 	fimc_write(cfg1, EXYNOS_CISCCTRL);
1627 
1628 	/* Enable image capture*/
1629 	cfg0 |= EXYNOS_CIIMGCPT_IMGCPTEN;
1630 	fimc_write(cfg0, EXYNOS_CIIMGCPT);
1631 
1632 	/* Disable frame end irq */
1633 	cfg0 = fimc_read(EXYNOS_CIGCTRL);
1634 	cfg0 &= ~EXYNOS_CIGCTRL_IRQ_END_DISABLE;
1635 	fimc_write(cfg0, EXYNOS_CIGCTRL);
1636 
1637 	cfg0 = fimc_read(EXYNOS_CIOCTRL);
1638 	cfg0 &= ~EXYNOS_CIOCTRL_WEAVE_MASK;
1639 	fimc_write(cfg0, EXYNOS_CIOCTRL);
1640 
1641 	if (cmd == IPP_CMD_M2M) {
1642 		cfg0 = fimc_read(EXYNOS_MSCTRL);
1643 		cfg0 |= EXYNOS_MSCTRL_ENVID;
1644 		fimc_write(cfg0, EXYNOS_MSCTRL);
1645 
1646 		cfg0 = fimc_read(EXYNOS_MSCTRL);
1647 		cfg0 |= EXYNOS_MSCTRL_ENVID;
1648 		fimc_write(cfg0, EXYNOS_MSCTRL);
1649 	}
1650 
1651 	return 0;
1652 }
1653 
1654 static void fimc_ippdrv_stop(struct device *dev, enum drm_exynos_ipp_cmd cmd)
1655 {
1656 	struct fimc_context *ctx = get_fimc_context(dev);
1657 	struct drm_exynos_ipp_set_wb set_wb = {0, 0};
1658 	u32 cfg;
1659 
1660 	DRM_DEBUG_KMS("cmd[%d]\n", cmd);
1661 
1662 	switch (cmd) {
1663 	case IPP_CMD_M2M:
1664 		/* Source clear */
1665 		cfg = fimc_read(EXYNOS_MSCTRL);
1666 		cfg &= ~EXYNOS_MSCTRL_INPUT_MASK;
1667 		cfg &= ~EXYNOS_MSCTRL_ENVID;
1668 		fimc_write(cfg, EXYNOS_MSCTRL);
1669 		break;
1670 	case IPP_CMD_WB:
1671 		exynos_drm_ippnb_send_event(IPP_SET_WRITEBACK, (void *)&set_wb);
1672 		break;
1673 	case IPP_CMD_OUTPUT:
1674 	default:
1675 		dev_err(dev, "invalid operations.\n");
1676 		break;
1677 	}
1678 
1679 	fimc_handle_irq(ctx, false, false, true);
1680 
1681 	/* reset sequence */
1682 	fimc_write(0x0, EXYNOS_CIFCNTSEQ);
1683 
1684 	/* Scaler disable */
1685 	cfg = fimc_read(EXYNOS_CISCCTRL);
1686 	cfg &= ~EXYNOS_CISCCTRL_SCALERSTART;
1687 	fimc_write(cfg, EXYNOS_CISCCTRL);
1688 
1689 	/* Disable image capture */
1690 	cfg = fimc_read(EXYNOS_CIIMGCPT);
1691 	cfg &= ~(EXYNOS_CIIMGCPT_IMGCPTEN_SC | EXYNOS_CIIMGCPT_IMGCPTEN);
1692 	fimc_write(cfg, EXYNOS_CIIMGCPT);
1693 
1694 	/* Enable frame end irq */
1695 	cfg = fimc_read(EXYNOS_CIGCTRL);
1696 	cfg |= EXYNOS_CIGCTRL_IRQ_END_DISABLE;
1697 	fimc_write(cfg, EXYNOS_CIGCTRL);
1698 }
1699 
1700 static void fimc_put_clocks(struct fimc_context *ctx)
1701 {
1702 	int i;
1703 
1704 	for (i = 0; i < FIMC_CLKS_MAX; i++) {
1705 		if (IS_ERR(ctx->clocks[i]))
1706 			continue;
1707 		clk_put(ctx->clocks[i]);
1708 		ctx->clocks[i] = ERR_PTR(-EINVAL);
1709 	}
1710 }
1711 
1712 static int fimc_setup_clocks(struct fimc_context *ctx)
1713 {
1714 	struct device *fimc_dev = ctx->ippdrv.dev;
1715 	struct device *dev;
1716 	int ret, i;
1717 
1718 	for (i = 0; i < FIMC_CLKS_MAX; i++)
1719 		ctx->clocks[i] = ERR_PTR(-EINVAL);
1720 
1721 	for (i = 0; i < FIMC_CLKS_MAX; i++) {
1722 		if (i == FIMC_CLK_WB_A || i == FIMC_CLK_WB_B)
1723 			dev = fimc_dev->parent;
1724 		else
1725 			dev = fimc_dev;
1726 
1727 		ctx->clocks[i] = clk_get(dev, fimc_clock_names[i]);
1728 		if (IS_ERR(ctx->clocks[i])) {
1729 			if (i >= FIMC_CLK_MUX)
1730 				break;
1731 			ret = PTR_ERR(ctx->clocks[i]);
1732 			dev_err(fimc_dev, "failed to get clock: %s\n",
1733 						fimc_clock_names[i]);
1734 			goto e_clk_free;
1735 		}
1736 	}
1737 
1738 	/* Optional FIMC LCLK parent clock setting */
1739 	if (!IS_ERR(ctx->clocks[FIMC_CLK_PARENT])) {
1740 		ret = clk_set_parent(ctx->clocks[FIMC_CLK_MUX],
1741 				     ctx->clocks[FIMC_CLK_PARENT]);
1742 		if (ret < 0) {
1743 			dev_err(fimc_dev, "failed to set parent.\n");
1744 			goto e_clk_free;
1745 		}
1746 	}
1747 
1748 	ret = clk_set_rate(ctx->clocks[FIMC_CLK_LCLK], ctx->clk_frequency);
1749 	if (ret < 0)
1750 		goto e_clk_free;
1751 
1752 	ret = clk_prepare_enable(ctx->clocks[FIMC_CLK_LCLK]);
1753 	if (!ret)
1754 		return ret;
1755 e_clk_free:
1756 	fimc_put_clocks(ctx);
1757 	return ret;
1758 }
1759 
1760 static int fimc_parse_dt(struct fimc_context *ctx)
1761 {
1762 	struct device_node *node = ctx->ippdrv.dev->of_node;
1763 
1764 	/* Handle only devices that support the LCD Writeback data path */
1765 	if (!of_property_read_bool(node, "samsung,lcd-wb"))
1766 		return -ENODEV;
1767 
1768 	if (of_property_read_u32(node, "clock-frequency",
1769 					&ctx->clk_frequency))
1770 		ctx->clk_frequency = FIMC_DEFAULT_LCLK_FREQUENCY;
1771 
1772 	ctx->id = of_alias_get_id(node, "fimc");
1773 
1774 	if (ctx->id < 0) {
1775 		dev_err(ctx->ippdrv.dev, "failed to get node alias id.\n");
1776 		return -EINVAL;
1777 	}
1778 
1779 	return 0;
1780 }
1781 
1782 static int fimc_probe(struct platform_device *pdev)
1783 {
1784 	struct device *dev = &pdev->dev;
1785 	struct fimc_context *ctx;
1786 	struct resource *res;
1787 	struct exynos_drm_ippdrv *ippdrv;
1788 	int ret;
1789 
1790 	if (!dev->of_node) {
1791 		dev_err(dev, "device tree node not found.\n");
1792 		return -ENODEV;
1793 	}
1794 
1795 	ctx = devm_kzalloc(dev, sizeof(*ctx), GFP_KERNEL);
1796 	if (!ctx)
1797 		return -ENOMEM;
1798 
1799 	ctx->ippdrv.dev = dev;
1800 
1801 	ret = fimc_parse_dt(ctx);
1802 	if (ret < 0)
1803 		return ret;
1804 
1805 	ctx->sysreg = syscon_regmap_lookup_by_phandle(dev->of_node,
1806 						"samsung,sysreg");
1807 	if (IS_ERR(ctx->sysreg)) {
1808 		dev_err(dev, "syscon regmap lookup failed.\n");
1809 		return PTR_ERR(ctx->sysreg);
1810 	}
1811 
1812 	/* resource memory */
1813 	ctx->regs_res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
1814 	ctx->regs = devm_ioremap_resource(dev, ctx->regs_res);
1815 	if (IS_ERR(ctx->regs))
1816 		return PTR_ERR(ctx->regs);
1817 
1818 	/* resource irq */
1819 	res = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
1820 	if (!res) {
1821 		dev_err(dev, "failed to request irq resource.\n");
1822 		return -ENOENT;
1823 	}
1824 
1825 	ctx->irq = res->start;
1826 	ret = devm_request_threaded_irq(dev, ctx->irq, NULL, fimc_irq_handler,
1827 		IRQF_ONESHOT, "drm_fimc", ctx);
1828 	if (ret < 0) {
1829 		dev_err(dev, "failed to request irq.\n");
1830 		return ret;
1831 	}
1832 
1833 	ret = fimc_setup_clocks(ctx);
1834 	if (ret < 0)
1835 		return ret;
1836 
1837 	ippdrv = &ctx->ippdrv;
1838 	ippdrv->ops[EXYNOS_DRM_OPS_SRC] = &fimc_src_ops;
1839 	ippdrv->ops[EXYNOS_DRM_OPS_DST] = &fimc_dst_ops;
1840 	ippdrv->check_property = fimc_ippdrv_check_property;
1841 	ippdrv->reset = fimc_ippdrv_reset;
1842 	ippdrv->start = fimc_ippdrv_start;
1843 	ippdrv->stop = fimc_ippdrv_stop;
1844 	ret = fimc_init_prop_list(ippdrv);
1845 	if (ret < 0) {
1846 		dev_err(dev, "failed to init property list.\n");
1847 		goto err_put_clk;
1848 	}
1849 
1850 	DRM_DEBUG_KMS("id[%d]ippdrv[0x%x]\n", ctx->id, (int)ippdrv);
1851 
1852 	mutex_init(&ctx->lock);
1853 	platform_set_drvdata(pdev, ctx);
1854 
1855 	pm_runtime_set_active(dev);
1856 	pm_runtime_enable(dev);
1857 
1858 	ret = exynos_drm_ippdrv_register(ippdrv);
1859 	if (ret < 0) {
1860 		dev_err(dev, "failed to register drm fimc device.\n");
1861 		goto err_pm_dis;
1862 	}
1863 
1864 	dev_info(dev, "drm fimc registered successfully.\n");
1865 
1866 	return 0;
1867 
1868 err_pm_dis:
1869 	pm_runtime_disable(dev);
1870 err_put_clk:
1871 	fimc_put_clocks(ctx);
1872 
1873 	return ret;
1874 }
1875 
1876 static int fimc_remove(struct platform_device *pdev)
1877 {
1878 	struct device *dev = &pdev->dev;
1879 	struct fimc_context *ctx = get_fimc_context(dev);
1880 	struct exynos_drm_ippdrv *ippdrv = &ctx->ippdrv;
1881 
1882 	exynos_drm_ippdrv_unregister(ippdrv);
1883 	mutex_destroy(&ctx->lock);
1884 
1885 	fimc_put_clocks(ctx);
1886 	pm_runtime_set_suspended(dev);
1887 	pm_runtime_disable(dev);
1888 
1889 	return 0;
1890 }
1891 
1892 #ifdef CONFIG_PM_SLEEP
1893 static int fimc_suspend(struct device *dev)
1894 {
1895 	struct fimc_context *ctx = get_fimc_context(dev);
1896 
1897 	DRM_DEBUG_KMS("id[%d]\n", ctx->id);
1898 
1899 	if (pm_runtime_suspended(dev))
1900 		return 0;
1901 
1902 	return fimc_clk_ctrl(ctx, false);
1903 }
1904 
1905 static int fimc_resume(struct device *dev)
1906 {
1907 	struct fimc_context *ctx = get_fimc_context(dev);
1908 
1909 	DRM_DEBUG_KMS("id[%d]\n", ctx->id);
1910 
1911 	if (!pm_runtime_suspended(dev))
1912 		return fimc_clk_ctrl(ctx, true);
1913 
1914 	return 0;
1915 }
1916 #endif
1917 
1918 #ifdef CONFIG_PM_RUNTIME
1919 static int fimc_runtime_suspend(struct device *dev)
1920 {
1921 	struct fimc_context *ctx = get_fimc_context(dev);
1922 
1923 	DRM_DEBUG_KMS("id[%d]\n", ctx->id);
1924 
1925 	return  fimc_clk_ctrl(ctx, false);
1926 }
1927 
1928 static int fimc_runtime_resume(struct device *dev)
1929 {
1930 	struct fimc_context *ctx = get_fimc_context(dev);
1931 
1932 	DRM_DEBUG_KMS("id[%d]\n", ctx->id);
1933 
1934 	return  fimc_clk_ctrl(ctx, true);
1935 }
1936 #endif
1937 
1938 static const struct dev_pm_ops fimc_pm_ops = {
1939 	SET_SYSTEM_SLEEP_PM_OPS(fimc_suspend, fimc_resume)
1940 	SET_RUNTIME_PM_OPS(fimc_runtime_suspend, fimc_runtime_resume, NULL)
1941 };
1942 
1943 static const struct of_device_id fimc_of_match[] = {
1944 	{ .compatible = "samsung,exynos4210-fimc" },
1945 	{ .compatible = "samsung,exynos4212-fimc" },
1946 	{ },
1947 };
1948 
1949 struct platform_driver fimc_driver = {
1950 	.probe		= fimc_probe,
1951 	.remove		= fimc_remove,
1952 	.driver		= {
1953 		.of_match_table = fimc_of_match,
1954 		.name	= "exynos-drm-fimc",
1955 		.owner	= THIS_MODULE,
1956 		.pm	= &fimc_pm_ops,
1957 	},
1958 };
1959 
1960