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