aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorEunchul Kim <chulspro.kim@samsung.com>2012-12-14 03:58:55 -0500
committerInki Dae <daeinki@gmail.com>2012-12-14 12:38:53 -0500
commit16102edb49b6cc7fbb68b10c04a42b78fbceb3ed (patch)
tree97c4c28c5fb058bb94b304eae3be0efa1decdc46
parentc12e2617b25535014a766a0bc3e05134ef817b82 (diff)
drm/exynos: add fimc ipp driver
FIMC is stand for Fully Interfactive Mobile Camera and supports image scaler/rotator/crop/flip/csc and input/output DMA operations and also supports writeback and display output operations. This driver is registered to IPP subsystem framework to be used by user side and user can control the FIMC hardware through some interfaces of IPP subsystem framework. Changelog v6: - fix build warning. Changelog v1 ~ v5: - add comments, code fixups and cleanups. Signed-off-by: Eunchul Kim <chulspro.kim@samsung.com> Signed-off-by: Jinyoung Jeon <jy0.jeon@samsung.com> Signed-off-by: Inki Dae <inki.dae@samsung.com> Signed-off-by: Kyungmin Park <kyungmin.park@samsung.com>
-rw-r--r--drivers/gpu/drm/exynos/Kconfig6
-rw-r--r--drivers/gpu/drm/exynos/Makefile1
-rw-r--r--drivers/gpu/drm/exynos/exynos_drm_drv.c15
-rw-r--r--drivers/gpu/drm/exynos/exynos_drm_drv.h1
-rw-r--r--drivers/gpu/drm/exynos/exynos_drm_fimc.c2001
-rw-r--r--drivers/gpu/drm/exynos/exynos_drm_fimc.h37
-rw-r--r--drivers/gpu/drm/exynos/regs-fimc.h669
-rw-r--r--include/drm/exynos_drm.h26
8 files changed, 2756 insertions, 0 deletions
diff --git a/drivers/gpu/drm/exynos/Kconfig b/drivers/gpu/drm/exynos/Kconfig
index 80ab242e2739..66c02df360e7 100644
--- a/drivers/gpu/drm/exynos/Kconfig
+++ b/drivers/gpu/drm/exynos/Kconfig
@@ -51,3 +51,9 @@ config DRM_EXYNOS_IPP
51 depends on DRM_EXYNOS 51 depends on DRM_EXYNOS
52 help 52 help
53 Choose this option if you want to use IPP feature for DRM. 53 Choose this option if you want to use IPP feature for DRM.
54
55config DRM_EXYNOS_FIMC
56 bool "Exynos DRM FIMC"
57 depends on DRM_EXYNOS_IPP
58 help
59 Choose this option if you want to use Exynos FIMC for DRM.
diff --git a/drivers/gpu/drm/exynos/Makefile b/drivers/gpu/drm/exynos/Makefile
index 6c536ce4d95b..9710024ed000 100644
--- a/drivers/gpu/drm/exynos/Makefile
+++ b/drivers/gpu/drm/exynos/Makefile
@@ -17,5 +17,6 @@ exynosdrm-$(CONFIG_DRM_EXYNOS_HDMI) += exynos_hdmi.o exynos_mixer.o \
17exynosdrm-$(CONFIG_DRM_EXYNOS_VIDI) += exynos_drm_vidi.o 17exynosdrm-$(CONFIG_DRM_EXYNOS_VIDI) += exynos_drm_vidi.o
18exynosdrm-$(CONFIG_DRM_EXYNOS_G2D) += exynos_drm_g2d.o 18exynosdrm-$(CONFIG_DRM_EXYNOS_G2D) += exynos_drm_g2d.o
19exynosdrm-$(CONFIG_DRM_EXYNOS_IPP) += exynos_drm_ipp.o 19exynosdrm-$(CONFIG_DRM_EXYNOS_IPP) += exynos_drm_ipp.o
20exynosdrm-$(CONFIG_DRM_EXYNOS_FIMC) += exynos_drm_fimc.o
20 21
21obj-$(CONFIG_DRM_EXYNOS) += exynosdrm.o 22obj-$(CONFIG_DRM_EXYNOS) += exynosdrm.o
diff --git a/drivers/gpu/drm/exynos/exynos_drm_drv.c b/drivers/gpu/drm/exynos/exynos_drm_drv.c
index 0eb8a972e21c..73f02ac53bad 100644
--- a/drivers/gpu/drm/exynos/exynos_drm_drv.c
+++ b/drivers/gpu/drm/exynos/exynos_drm_drv.c
@@ -372,6 +372,12 @@ static int __init exynos_drm_init(void)
372 goto out_g2d; 372 goto out_g2d;
373#endif 373#endif
374 374
375#ifdef CONFIG_DRM_EXYNOS_FIMC
376 ret = platform_driver_register(&fimc_driver);
377 if (ret < 0)
378 goto out_fimc;
379#endif
380
375#ifdef CONFIG_DRM_EXYNOS_IPP 381#ifdef CONFIG_DRM_EXYNOS_IPP
376 ret = platform_driver_register(&ipp_driver); 382 ret = platform_driver_register(&ipp_driver);
377 if (ret < 0) 383 if (ret < 0)
@@ -400,6 +406,11 @@ out_drm:
400out_ipp: 406out_ipp:
401#endif 407#endif
402 408
409#ifdef CONFIG_DRM_EXYNOS_FIMC
410 platform_driver_unregister(&fimc_driver);
411out_fimc:
412#endif
413
403#ifdef CONFIG_DRM_EXYNOS_G2D 414#ifdef CONFIG_DRM_EXYNOS_G2D
404 platform_driver_unregister(&g2d_driver); 415 platform_driver_unregister(&g2d_driver);
405out_g2d: 416out_g2d:
@@ -440,6 +451,10 @@ static void __exit exynos_drm_exit(void)
440 platform_driver_unregister(&ipp_driver); 451 platform_driver_unregister(&ipp_driver);
441#endif 452#endif
442 453
454#ifdef CONFIG_DRM_EXYNOS_FIMC
455 platform_driver_unregister(&fimc_driver);
456#endif
457
443#ifdef CONFIG_DRM_EXYNOS_G2D 458#ifdef CONFIG_DRM_EXYNOS_G2D
444 platform_driver_unregister(&g2d_driver); 459 platform_driver_unregister(&g2d_driver);
445#endif 460#endif
diff --git a/drivers/gpu/drm/exynos/exynos_drm_drv.h b/drivers/gpu/drm/exynos/exynos_drm_drv.h
index 44ab3c7b6a90..63803508e4df 100644
--- a/drivers/gpu/drm/exynos/exynos_drm_drv.h
+++ b/drivers/gpu/drm/exynos/exynos_drm_drv.h
@@ -349,5 +349,6 @@ extern struct platform_driver mixer_driver;
349extern struct platform_driver exynos_drm_common_hdmi_driver; 349extern struct platform_driver exynos_drm_common_hdmi_driver;
350extern struct platform_driver vidi_driver; 350extern struct platform_driver vidi_driver;
351extern struct platform_driver g2d_driver; 351extern struct platform_driver g2d_driver;
352extern struct platform_driver fimc_driver;
352extern struct platform_driver ipp_driver; 353extern struct platform_driver ipp_driver;
353#endif 354#endif
diff --git a/drivers/gpu/drm/exynos/exynos_drm_fimc.c b/drivers/gpu/drm/exynos/exynos_drm_fimc.c
new file mode 100644
index 000000000000..61ea24296b52
--- /dev/null
+++ b/drivers/gpu/drm/exynos/exynos_drm_fimc.c
@@ -0,0 +1,2001 @@
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/clk.h>
18#include <linux/pm_runtime.h>
19#include <plat/map-base.h>
20
21#include <drm/drmP.h>
22#include <drm/exynos_drm.h>
23#include "regs-fimc.h"
24#include "exynos_drm_ipp.h"
25#include "exynos_drm_fimc.h"
26
27/*
28 * FIMC is stand for Fully Interactive Mobile Camera and
29 * supports image scaler/rotator and input/output DMA operations.
30 * input DMA reads image data from the memory.
31 * output DMA writes image data to memory.
32 * FIMC supports image rotation and image effect functions.
33 *
34 * M2M operation : supports crop/scale/rotation/csc so on.
35 * Memory ----> FIMC H/W ----> Memory.
36 * Writeback operation : supports cloned screen with FIMD.
37 * FIMD ----> FIMC H/W ----> Memory.
38 * Output operation : supports direct display using local path.
39 * Memory ----> FIMC H/W ----> FIMD.
40 */
41
42/*
43 * TODO
44 * 1. check suspend/resume api if needed.
45 * 2. need to check use case platform_device_id.
46 * 3. check src/dst size with, height.
47 * 4. added check_prepare api for right register.
48 * 5. need to add supported list in prop_list.
49 * 6. check prescaler/scaler optimization.
50 */
51
52#define FIMC_MAX_DEVS 4
53#define FIMC_MAX_SRC 2
54#define FIMC_MAX_DST 32
55#define FIMC_SHFACTOR 10
56#define FIMC_BUF_STOP 1
57#define FIMC_BUF_START 2
58#define FIMC_REG_SZ 32
59#define FIMC_WIDTH_ITU_709 1280
60#define FIMC_REFRESH_MAX 60
61#define FIMC_REFRESH_MIN 12
62#define FIMC_CROP_MAX 8192
63#define FIMC_CROP_MIN 32
64#define FIMC_SCALE_MAX 4224
65#define FIMC_SCALE_MIN 32
66
67#define get_fimc_context(dev) platform_get_drvdata(to_platform_device(dev))
68#define get_ctx_from_ippdrv(ippdrv) container_of(ippdrv,\
69 struct fimc_context, ippdrv);
70#define fimc_read(offset) readl(ctx->regs + (offset))
71#define fimc_write(cfg, offset) writel(cfg, ctx->regs + (offset))
72
73enum fimc_wb {
74 FIMC_WB_NONE,
75 FIMC_WB_A,
76 FIMC_WB_B,
77};
78
79/*
80 * A structure of scaler.
81 *
82 * @range: narrow, wide.
83 * @bypass: unused scaler path.
84 * @up_h: horizontal scale up.
85 * @up_v: vertical scale up.
86 * @hratio: horizontal ratio.
87 * @vratio: vertical ratio.
88 */
89struct fimc_scaler {
90 bool range;
91 bool bypass;
92 bool up_h;
93 bool up_v;
94 u32 hratio;
95 u32 vratio;
96};
97
98/*
99 * A structure of scaler capability.
100 *
101 * find user manual table 43-1.
102 * @in_hori: scaler input horizontal size.
103 * @bypass: scaler bypass mode.
104 * @dst_h_wo_rot: target horizontal size without output rotation.
105 * @dst_h_rot: target horizontal size with output rotation.
106 * @rl_w_wo_rot: real width without input rotation.
107 * @rl_h_rot: real height without output rotation.
108 */
109struct fimc_capability {
110 /* scaler */
111 u32 in_hori;
112 u32 bypass;
113 /* output rotator */
114 u32 dst_h_wo_rot;
115 u32 dst_h_rot;
116 /* input rotator */
117 u32 rl_w_wo_rot;
118 u32 rl_h_rot;
119};
120
121/*
122 * A structure of fimc driver data.
123 *
124 * @parent_clk: name of parent clock.
125 */
126struct fimc_driverdata {
127 char *parent_clk;
128};
129
130/*
131 * A structure of fimc context.
132 *
133 * @ippdrv: prepare initialization using ippdrv.
134 * @regs_res: register resources.
135 * @regs: memory mapped io registers.
136 * @lock: locking of operations.
137 * @sclk_fimc_clk: fimc source clock.
138 * @fimc_clk: fimc clock.
139 * @wb_clk: writeback a clock.
140 * @wb_b_clk: writeback b clock.
141 * @sc: scaler infomations.
142 * @odr: ordering of YUV.
143 * @ver: fimc version.
144 * @pol: porarity of writeback.
145 * @id: fimc id.
146 * @irq: irq number.
147 * @suspended: qos operations.
148 */
149struct fimc_context {
150 struct exynos_drm_ippdrv ippdrv;
151 struct resource *regs_res;
152 void __iomem *regs;
153 struct mutex lock;
154 struct clk *sclk_fimc_clk;
155 struct clk *fimc_clk;
156 struct clk *wb_clk;
157 struct clk *wb_b_clk;
158 struct fimc_scaler sc;
159 struct fimc_driverdata *ddata;
160 struct exynos_drm_ipp_pol pol;
161 int id;
162 int irq;
163 bool suspended;
164};
165
166static void fimc_sw_reset(struct fimc_context *ctx, bool pattern)
167{
168 u32 cfg;
169
170 DRM_DEBUG_KMS("%s:pattern[%d]\n", __func__, pattern);
171
172 cfg = fimc_read(EXYNOS_CISRCFMT);
173 cfg |= EXYNOS_CISRCFMT_ITU601_8BIT;
174 if (pattern)
175 cfg |= EXYNOS_CIGCTRL_TESTPATTERN_COLOR_BAR;
176
177 fimc_write(cfg, EXYNOS_CISRCFMT);
178
179 /* s/w reset */
180 cfg = fimc_read(EXYNOS_CIGCTRL);
181 cfg |= (EXYNOS_CIGCTRL_SWRST);
182 fimc_write(cfg, EXYNOS_CIGCTRL);
183
184 /* s/w reset complete */
185 cfg = fimc_read(EXYNOS_CIGCTRL);
186 cfg &= ~EXYNOS_CIGCTRL_SWRST;
187 fimc_write(cfg, EXYNOS_CIGCTRL);
188
189 /* reset sequence */
190 fimc_write(0x0, EXYNOS_CIFCNTSEQ);
191}
192
193static void fimc_set_camblk_fimd0_wb(struct fimc_context *ctx)
194{
195 u32 camblk_cfg;
196
197 DRM_DEBUG_KMS("%s\n", __func__);
198
199 camblk_cfg = readl(SYSREG_CAMERA_BLK);
200 camblk_cfg &= ~(SYSREG_FIMD0WB_DEST_MASK);
201 camblk_cfg |= ctx->id << (SYSREG_FIMD0WB_DEST_SHIFT);
202
203 writel(camblk_cfg, SYSREG_CAMERA_BLK);
204}
205
206static void fimc_set_type_ctrl(struct fimc_context *ctx, enum fimc_wb wb)
207{
208 u32 cfg;
209
210 DRM_DEBUG_KMS("%s:wb[%d]\n", __func__, wb);
211
212 cfg = fimc_read(EXYNOS_CIGCTRL);
213 cfg &= ~(EXYNOS_CIGCTRL_TESTPATTERN_MASK |
214 EXYNOS_CIGCTRL_SELCAM_ITU_MASK |
215 EXYNOS_CIGCTRL_SELCAM_MIPI_MASK |
216 EXYNOS_CIGCTRL_SELCAM_FIMC_MASK |
217 EXYNOS_CIGCTRL_SELWB_CAMIF_MASK |
218 EXYNOS_CIGCTRL_SELWRITEBACK_MASK);
219
220 switch (wb) {
221 case FIMC_WB_A:
222 cfg |= (EXYNOS_CIGCTRL_SELWRITEBACK_A |
223 EXYNOS_CIGCTRL_SELWB_CAMIF_WRITEBACK);
224 break;
225 case FIMC_WB_B:
226 cfg |= (EXYNOS_CIGCTRL_SELWRITEBACK_B |
227 EXYNOS_CIGCTRL_SELWB_CAMIF_WRITEBACK);
228 break;
229 case FIMC_WB_NONE:
230 default:
231 cfg |= (EXYNOS_CIGCTRL_SELCAM_ITU_A |
232 EXYNOS_CIGCTRL_SELWRITEBACK_A |
233 EXYNOS_CIGCTRL_SELCAM_MIPI_A |
234 EXYNOS_CIGCTRL_SELCAM_FIMC_ITU);
235 break;
236 }
237
238 fimc_write(cfg, EXYNOS_CIGCTRL);
239}
240
241static void fimc_set_polarity(struct fimc_context *ctx,
242 struct exynos_drm_ipp_pol *pol)
243{
244 u32 cfg;
245
246 DRM_DEBUG_KMS("%s:inv_pclk[%d]inv_vsync[%d]\n",
247 __func__, pol->inv_pclk, pol->inv_vsync);
248 DRM_DEBUG_KMS("%s:inv_href[%d]inv_hsync[%d]\n",
249 __func__, pol->inv_href, pol->inv_hsync);
250
251 cfg = fimc_read(EXYNOS_CIGCTRL);
252 cfg &= ~(EXYNOS_CIGCTRL_INVPOLPCLK | EXYNOS_CIGCTRL_INVPOLVSYNC |
253 EXYNOS_CIGCTRL_INVPOLHREF | EXYNOS_CIGCTRL_INVPOLHSYNC);
254
255 if (pol->inv_pclk)
256 cfg |= EXYNOS_CIGCTRL_INVPOLPCLK;
257 if (pol->inv_vsync)
258 cfg |= EXYNOS_CIGCTRL_INVPOLVSYNC;
259 if (pol->inv_href)
260 cfg |= EXYNOS_CIGCTRL_INVPOLHREF;
261 if (pol->inv_hsync)
262 cfg |= EXYNOS_CIGCTRL_INVPOLHSYNC;
263
264 fimc_write(cfg, EXYNOS_CIGCTRL);
265}
266
267static void fimc_handle_jpeg(struct fimc_context *ctx, bool enable)
268{
269 u32 cfg;
270
271 DRM_DEBUG_KMS("%s:enable[%d]\n", __func__, enable);
272
273 cfg = fimc_read(EXYNOS_CIGCTRL);
274 if (enable)
275 cfg |= EXYNOS_CIGCTRL_CAM_JPEG;
276 else
277 cfg &= ~EXYNOS_CIGCTRL_CAM_JPEG;
278
279 fimc_write(cfg, EXYNOS_CIGCTRL);
280}
281
282static void fimc_handle_irq(struct fimc_context *ctx, bool enable,
283 bool overflow, bool level)
284{
285 u32 cfg;
286
287 DRM_DEBUG_KMS("%s:enable[%d]overflow[%d]level[%d]\n", __func__,
288 enable, overflow, level);
289
290 cfg = fimc_read(EXYNOS_CIGCTRL);
291 if (enable) {
292 cfg &= ~(EXYNOS_CIGCTRL_IRQ_OVFEN | EXYNOS_CIGCTRL_IRQ_LEVEL);
293 cfg |= EXYNOS_CIGCTRL_IRQ_ENABLE;
294 if (overflow)
295 cfg |= EXYNOS_CIGCTRL_IRQ_OVFEN;
296 if (level)
297 cfg |= EXYNOS_CIGCTRL_IRQ_LEVEL;
298 } else
299 cfg &= ~(EXYNOS_CIGCTRL_IRQ_OVFEN | EXYNOS_CIGCTRL_IRQ_ENABLE);
300
301 fimc_write(cfg, EXYNOS_CIGCTRL);
302}
303
304static void fimc_clear_irq(struct fimc_context *ctx)
305{
306 u32 cfg;
307
308 DRM_DEBUG_KMS("%s\n", __func__);
309
310 cfg = fimc_read(EXYNOS_CIGCTRL);
311 cfg |= EXYNOS_CIGCTRL_IRQ_CLR;
312 fimc_write(cfg, EXYNOS_CIGCTRL);
313}
314
315static bool fimc_check_ovf(struct fimc_context *ctx)
316{
317 struct exynos_drm_ippdrv *ippdrv = &ctx->ippdrv;
318 u32 cfg, status, flag;
319
320 status = fimc_read(EXYNOS_CISTATUS);
321 flag = EXYNOS_CISTATUS_OVFIY | EXYNOS_CISTATUS_OVFICB |
322 EXYNOS_CISTATUS_OVFICR;
323
324 DRM_DEBUG_KMS("%s:flag[0x%x]\n", __func__, flag);
325
326 if (status & flag) {
327 cfg = fimc_read(EXYNOS_CIWDOFST);
328 cfg |= (EXYNOS_CIWDOFST_CLROVFIY | EXYNOS_CIWDOFST_CLROVFICB |
329 EXYNOS_CIWDOFST_CLROVFICR);
330
331 fimc_write(cfg, EXYNOS_CIWDOFST);
332
333 cfg = fimc_read(EXYNOS_CIWDOFST);
334 cfg &= ~(EXYNOS_CIWDOFST_CLROVFIY | EXYNOS_CIWDOFST_CLROVFICB |
335 EXYNOS_CIWDOFST_CLROVFICR);
336
337 fimc_write(cfg, EXYNOS_CIWDOFST);
338
339 dev_err(ippdrv->dev, "occured overflow at %d, status 0x%x.\n",
340 ctx->id, status);
341 return true;
342 }
343
344 return false;
345}
346
347static bool fimc_check_frame_end(struct fimc_context *ctx)
348{
349 u32 cfg;
350
351 cfg = fimc_read(EXYNOS_CISTATUS);
352
353 DRM_DEBUG_KMS("%s:cfg[0x%x]\n", __func__, cfg);
354
355 if (!(cfg & EXYNOS_CISTATUS_FRAMEEND))
356 return false;
357
358 cfg &= ~(EXYNOS_CISTATUS_FRAMEEND);
359 fimc_write(cfg, EXYNOS_CISTATUS);
360
361 return true;
362}
363
364static int fimc_get_buf_id(struct fimc_context *ctx)
365{
366 u32 cfg;
367 int frame_cnt, buf_id;
368
369 DRM_DEBUG_KMS("%s\n", __func__);
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("%s:present[%d]before[%d]\n", __func__,
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("%s:buf_id[%d]\n", __func__, buf_id);
388
389 return buf_id;
390}
391
392static void fimc_handle_lastend(struct fimc_context *ctx, bool enable)
393{
394 u32 cfg;
395
396 DRM_DEBUG_KMS("%s:enable[%d]\n", __func__, 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
408static 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("%s:fmt[0x%x]\n", __func__, 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
480static 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("%s:fmt[0x%x]\n", __func__, 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
538static 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("%s:degree[%d]flip[0x%x]\n", __func__,
547 degree, flip);
548
549 cfg1 = fimc_read(EXYNOS_MSCTRL);
550 cfg1 &= ~(EXYNOS_MSCTRL_FLIP_X_MIRROR |
551 EXYNOS_MSCTRL_FLIP_Y_MIRROR);
552
553 cfg2 = fimc_read(EXYNOS_CITRGFMT);
554 cfg2 &= ~EXYNOS_CITRGFMT_INROT90_CLOCKWISE;
555
556 switch (degree) {
557 case EXYNOS_DRM_DEGREE_0:
558 if (flip & EXYNOS_DRM_FLIP_VERTICAL)
559 cfg1 |= EXYNOS_MSCTRL_FLIP_X_MIRROR;
560 if (flip & EXYNOS_DRM_FLIP_HORIZONTAL)
561 cfg1 |= EXYNOS_MSCTRL_FLIP_Y_MIRROR;
562 break;
563 case EXYNOS_DRM_DEGREE_90:
564 cfg2 |= EXYNOS_CITRGFMT_INROT90_CLOCKWISE;
565 if (flip & EXYNOS_DRM_FLIP_VERTICAL)
566 cfg1 |= EXYNOS_MSCTRL_FLIP_X_MIRROR;
567 if (flip & EXYNOS_DRM_FLIP_HORIZONTAL)
568 cfg1 |= EXYNOS_MSCTRL_FLIP_Y_MIRROR;
569 break;
570 case EXYNOS_DRM_DEGREE_180:
571 cfg1 |= (EXYNOS_MSCTRL_FLIP_X_MIRROR |
572 EXYNOS_MSCTRL_FLIP_Y_MIRROR);
573 if (flip & EXYNOS_DRM_FLIP_VERTICAL)
574 cfg1 &= ~EXYNOS_MSCTRL_FLIP_X_MIRROR;
575 if (flip & EXYNOS_DRM_FLIP_HORIZONTAL)
576 cfg1 &= ~EXYNOS_MSCTRL_FLIP_Y_MIRROR;
577 break;
578 case EXYNOS_DRM_DEGREE_270:
579 cfg1 |= (EXYNOS_MSCTRL_FLIP_X_MIRROR |
580 EXYNOS_MSCTRL_FLIP_Y_MIRROR);
581 cfg2 |= EXYNOS_CITRGFMT_INROT90_CLOCKWISE;
582 if (flip & EXYNOS_DRM_FLIP_VERTICAL)
583 cfg1 &= ~EXYNOS_MSCTRL_FLIP_X_MIRROR;
584 if (flip & EXYNOS_DRM_FLIP_HORIZONTAL)
585 cfg1 &= ~EXYNOS_MSCTRL_FLIP_Y_MIRROR;
586 break;
587 default:
588 dev_err(ippdrv->dev, "inavlid degree value %d.\n", degree);
589 return -EINVAL;
590 }
591
592 fimc_write(cfg1, EXYNOS_MSCTRL);
593 fimc_write(cfg2, EXYNOS_CITRGFMT);
594 *swap = (cfg2 & EXYNOS_CITRGFMT_INROT90_CLOCKWISE) ? 1 : 0;
595
596 return 0;
597}
598
599static int fimc_set_window(struct fimc_context *ctx,
600 struct drm_exynos_pos *pos, struct drm_exynos_sz *sz)
601{
602 u32 cfg, h1, h2, v1, v2;
603
604 /* cropped image */
605 h1 = pos->x;
606 h2 = sz->hsize - pos->w - pos->x;
607 v1 = pos->y;
608 v2 = sz->vsize - pos->h - pos->y;
609
610 DRM_DEBUG_KMS("%s:x[%d]y[%d]w[%d]h[%d]hsize[%d]vsize[%d]\n",
611 __func__, pos->x, pos->y, pos->w, pos->h, sz->hsize, sz->vsize);
612 DRM_DEBUG_KMS("%s:h1[%d]h2[%d]v1[%d]v2[%d]\n", __func__,
613 h1, h2, v1, v2);
614
615 /*
616 * set window offset 1, 2 size
617 * check figure 43-21 in user manual
618 */
619 cfg = fimc_read(EXYNOS_CIWDOFST);
620 cfg &= ~(EXYNOS_CIWDOFST_WINHOROFST_MASK |
621 EXYNOS_CIWDOFST_WINVEROFST_MASK);
622 cfg |= (EXYNOS_CIWDOFST_WINHOROFST(h1) |
623 EXYNOS_CIWDOFST_WINVEROFST(v1));
624 cfg |= EXYNOS_CIWDOFST_WINOFSEN;
625 fimc_write(cfg, EXYNOS_CIWDOFST);
626
627 cfg = (EXYNOS_CIWDOFST2_WINHOROFST2(h2) |
628 EXYNOS_CIWDOFST2_WINVEROFST2(v2));
629 fimc_write(cfg, EXYNOS_CIWDOFST2);
630
631 return 0;
632}
633
634static int fimc_src_set_size(struct device *dev, int swap,
635 struct drm_exynos_pos *pos, struct drm_exynos_sz *sz)
636{
637 struct fimc_context *ctx = get_fimc_context(dev);
638 struct drm_exynos_pos img_pos = *pos;
639 struct drm_exynos_sz img_sz = *sz;
640 u32 cfg;
641
642 DRM_DEBUG_KMS("%s:swap[%d]hsize[%d]vsize[%d]\n",
643 __func__, swap, sz->hsize, sz->vsize);
644
645 /* original size */
646 cfg = (EXYNOS_ORGISIZE_HORIZONTAL(img_sz.hsize) |
647 EXYNOS_ORGISIZE_VERTICAL(img_sz.vsize));
648
649 fimc_write(cfg, EXYNOS_ORGISIZE);
650
651 DRM_DEBUG_KMS("%s:x[%d]y[%d]w[%d]h[%d]\n", __func__,
652 pos->x, pos->y, pos->w, pos->h);
653
654 if (swap) {
655 img_pos.w = pos->h;
656 img_pos.h = pos->w;
657 img_sz.hsize = sz->vsize;
658 img_sz.vsize = sz->hsize;
659 }
660
661 /* set input DMA image size */
662 cfg = fimc_read(EXYNOS_CIREAL_ISIZE);
663 cfg &= ~(EXYNOS_CIREAL_ISIZE_HEIGHT_MASK |
664 EXYNOS_CIREAL_ISIZE_WIDTH_MASK);
665 cfg |= (EXYNOS_CIREAL_ISIZE_WIDTH(img_pos.w) |
666 EXYNOS_CIREAL_ISIZE_HEIGHT(img_pos.h));
667 fimc_write(cfg, EXYNOS_CIREAL_ISIZE);
668
669 /*
670 * set input FIFO image size
671 * for now, we support only ITU601 8 bit mode
672 */
673 cfg = (EXYNOS_CISRCFMT_ITU601_8BIT |
674 EXYNOS_CISRCFMT_SOURCEHSIZE(img_sz.hsize) |
675 EXYNOS_CISRCFMT_SOURCEVSIZE(img_sz.vsize));
676 fimc_write(cfg, EXYNOS_CISRCFMT);
677
678 /* offset Y(RGB), Cb, Cr */
679 cfg = (EXYNOS_CIIYOFF_HORIZONTAL(img_pos.x) |
680 EXYNOS_CIIYOFF_VERTICAL(img_pos.y));
681 fimc_write(cfg, EXYNOS_CIIYOFF);
682 cfg = (EXYNOS_CIICBOFF_HORIZONTAL(img_pos.x) |
683 EXYNOS_CIICBOFF_VERTICAL(img_pos.y));
684 fimc_write(cfg, EXYNOS_CIICBOFF);
685 cfg = (EXYNOS_CIICROFF_HORIZONTAL(img_pos.x) |
686 EXYNOS_CIICROFF_VERTICAL(img_pos.y));
687 fimc_write(cfg, EXYNOS_CIICROFF);
688
689 return fimc_set_window(ctx, &img_pos, &img_sz);
690}
691
692static int fimc_src_set_addr(struct device *dev,
693 struct drm_exynos_ipp_buf_info *buf_info, u32 buf_id,
694 enum drm_exynos_ipp_buf_type buf_type)
695{
696 struct fimc_context *ctx = get_fimc_context(dev);
697 struct exynos_drm_ippdrv *ippdrv = &ctx->ippdrv;
698 struct drm_exynos_ipp_cmd_node *c_node = ippdrv->cmd;
699 struct drm_exynos_ipp_property *property;
700 struct drm_exynos_ipp_config *config;
701
702 if (!c_node) {
703 DRM_ERROR("failed to get c_node.\n");
704 return -EINVAL;
705 }
706
707 property = &c_node->property;
708 if (!property) {
709 DRM_ERROR("failed to get property.\n");
710 return -EINVAL;
711 }
712
713 DRM_DEBUG_KMS("%s:prop_id[%d]buf_id[%d]buf_type[%d]\n", __func__,
714 property->prop_id, buf_id, buf_type);
715
716 if (buf_id > FIMC_MAX_SRC) {
717 dev_info(ippdrv->dev, "inavlid buf_id %d.\n", buf_id);
718 return -ENOMEM;
719 }
720
721 /* address register set */
722 switch (buf_type) {
723 case IPP_BUF_ENQUEUE:
724 config = &property->config[EXYNOS_DRM_OPS_SRC];
725 fimc_write(buf_info->base[EXYNOS_DRM_PLANAR_Y],
726 EXYNOS_CIIYSA(buf_id));
727
728 if (config->fmt == DRM_FORMAT_YVU420) {
729 fimc_write(buf_info->base[EXYNOS_DRM_PLANAR_CR],
730 EXYNOS_CIICBSA(buf_id));
731 fimc_write(buf_info->base[EXYNOS_DRM_PLANAR_CB],
732 EXYNOS_CIICRSA(buf_id));
733 } else {
734 fimc_write(buf_info->base[EXYNOS_DRM_PLANAR_CB],
735 EXYNOS_CIICBSA(buf_id));
736 fimc_write(buf_info->base[EXYNOS_DRM_PLANAR_CR],
737 EXYNOS_CIICRSA(buf_id));
738 }
739 break;
740 case IPP_BUF_DEQUEUE:
741 fimc_write(0x0, EXYNOS_CIIYSA(buf_id));
742 fimc_write(0x0, EXYNOS_CIICBSA(buf_id));
743 fimc_write(0x0, EXYNOS_CIICRSA(buf_id));
744 break;
745 default:
746 /* bypass */
747 break;
748 }
749
750 return 0;
751}
752
753static struct exynos_drm_ipp_ops fimc_src_ops = {
754 .set_fmt = fimc_src_set_fmt,
755 .set_transf = fimc_src_set_transf,
756 .set_size = fimc_src_set_size,
757 .set_addr = fimc_src_set_addr,
758};
759
760static int fimc_dst_set_fmt_order(struct fimc_context *ctx, u32 fmt)
761{
762 struct exynos_drm_ippdrv *ippdrv = &ctx->ippdrv;
763 u32 cfg;
764
765 DRM_DEBUG_KMS("%s:fmt[0x%x]\n", __func__, fmt);
766
767 /* RGB */
768 cfg = fimc_read(EXYNOS_CISCCTRL);
769 cfg &= ~EXYNOS_CISCCTRL_OUTRGB_FMT_RGB_MASK;
770
771 switch (fmt) {
772 case DRM_FORMAT_RGB565:
773 cfg |= EXYNOS_CISCCTRL_OUTRGB_FMT_RGB565;
774 fimc_write(cfg, EXYNOS_CISCCTRL);
775 return 0;
776 case DRM_FORMAT_RGB888:
777 cfg |= EXYNOS_CISCCTRL_OUTRGB_FMT_RGB888;
778 fimc_write(cfg, EXYNOS_CISCCTRL);
779 return 0;
780 case DRM_FORMAT_XRGB8888:
781 cfg |= (EXYNOS_CISCCTRL_OUTRGB_FMT_RGB888 |
782 EXYNOS_CISCCTRL_EXTRGB_EXTENSION);
783 fimc_write(cfg, EXYNOS_CISCCTRL);
784 break;
785 default:
786 /* bypass */
787 break;
788 }
789
790 /* YUV */
791 cfg = fimc_read(EXYNOS_CIOCTRL);
792 cfg &= ~(EXYNOS_CIOCTRL_ORDER2P_MASK |
793 EXYNOS_CIOCTRL_ORDER422_MASK |
794 EXYNOS_CIOCTRL_YCBCR_PLANE_MASK);
795
796 switch (fmt) {
797 case DRM_FORMAT_XRGB8888:
798 cfg |= EXYNOS_CIOCTRL_ALPHA_OUT;
799 break;
800 case DRM_FORMAT_YUYV:
801 cfg |= EXYNOS_CIOCTRL_ORDER422_YCBYCR;
802 break;
803 case DRM_FORMAT_YVYU:
804 cfg |= EXYNOS_CIOCTRL_ORDER422_YCRYCB;
805 break;
806 case DRM_FORMAT_UYVY:
807 cfg |= EXYNOS_CIOCTRL_ORDER422_CBYCRY;
808 break;
809 case DRM_FORMAT_VYUY:
810 cfg |= EXYNOS_CIOCTRL_ORDER422_CRYCBY;
811 break;
812 case DRM_FORMAT_NV21:
813 case DRM_FORMAT_NV61:
814 cfg |= EXYNOS_CIOCTRL_ORDER2P_LSB_CRCB;
815 cfg |= EXYNOS_CIOCTRL_YCBCR_2PLANE;
816 break;
817 case DRM_FORMAT_YUV422:
818 case DRM_FORMAT_YUV420:
819 case DRM_FORMAT_YVU420:
820 cfg |= EXYNOS_CIOCTRL_YCBCR_3PLANE;
821 break;
822 case DRM_FORMAT_NV12:
823 case DRM_FORMAT_NV12MT:
824 case DRM_FORMAT_NV16:
825 cfg |= EXYNOS_CIOCTRL_ORDER2P_LSB_CBCR;
826 cfg |= EXYNOS_CIOCTRL_YCBCR_2PLANE;
827 break;
828 default:
829 dev_err(ippdrv->dev, "inavlid target yuv order 0x%x.\n", fmt);
830 return -EINVAL;
831 }
832
833 fimc_write(cfg, EXYNOS_CIOCTRL);
834
835 return 0;
836}
837
838static int fimc_dst_set_fmt(struct device *dev, u32 fmt)
839{
840 struct fimc_context *ctx = get_fimc_context(dev);
841 struct exynos_drm_ippdrv *ippdrv = &ctx->ippdrv;
842 u32 cfg;
843
844 DRM_DEBUG_KMS("%s:fmt[0x%x]\n", __func__, fmt);
845
846 cfg = fimc_read(EXYNOS_CIEXTEN);
847
848 if (fmt == DRM_FORMAT_AYUV) {
849 cfg |= EXYNOS_CIEXTEN_YUV444_OUT;
850 fimc_write(cfg, EXYNOS_CIEXTEN);
851 } else {
852 cfg &= ~EXYNOS_CIEXTEN_YUV444_OUT;
853 fimc_write(cfg, EXYNOS_CIEXTEN);
854
855 cfg = fimc_read(EXYNOS_CITRGFMT);
856 cfg &= ~EXYNOS_CITRGFMT_OUTFORMAT_MASK;
857
858 switch (fmt) {
859 case DRM_FORMAT_RGB565:
860 case DRM_FORMAT_RGB888:
861 case DRM_FORMAT_XRGB8888:
862 cfg |= EXYNOS_CITRGFMT_OUTFORMAT_RGB;
863 break;
864 case DRM_FORMAT_YUYV:
865 case DRM_FORMAT_YVYU:
866 case DRM_FORMAT_UYVY:
867 case DRM_FORMAT_VYUY:
868 cfg |= EXYNOS_CITRGFMT_OUTFORMAT_YCBCR422_1PLANE;
869 break;
870 case DRM_FORMAT_NV16:
871 case DRM_FORMAT_NV61:
872 case DRM_FORMAT_YUV422:
873 cfg |= EXYNOS_CITRGFMT_OUTFORMAT_YCBCR422;
874 break;
875 case DRM_FORMAT_YUV420:
876 case DRM_FORMAT_YVU420:
877 case DRM_FORMAT_NV12:
878 case DRM_FORMAT_NV12MT:
879 case DRM_FORMAT_NV21:
880 cfg |= EXYNOS_CITRGFMT_OUTFORMAT_YCBCR420;
881 break;
882 default:
883 dev_err(ippdrv->dev, "inavlid target format 0x%x.\n",
884 fmt);
885 return -EINVAL;
886 }
887
888 fimc_write(cfg, EXYNOS_CITRGFMT);
889 }
890
891 cfg = fimc_read(EXYNOS_CIDMAPARAM);
892 cfg &= ~EXYNOS_CIDMAPARAM_W_MODE_MASK;
893
894 if (fmt == DRM_FORMAT_NV12MT)
895 cfg |= EXYNOS_CIDMAPARAM_W_MODE_64X32;
896 else
897 cfg |= EXYNOS_CIDMAPARAM_W_MODE_LINEAR;
898
899 fimc_write(cfg, EXYNOS_CIDMAPARAM);
900
901 return fimc_dst_set_fmt_order(ctx, fmt);
902}
903
904static int fimc_dst_set_transf(struct device *dev,
905 enum drm_exynos_degree degree,
906 enum drm_exynos_flip flip, bool *swap)
907{
908 struct fimc_context *ctx = get_fimc_context(dev);
909 struct exynos_drm_ippdrv *ippdrv = &ctx->ippdrv;
910 u32 cfg;
911
912 DRM_DEBUG_KMS("%s:degree[%d]flip[0x%x]\n", __func__,
913 degree, flip);
914
915 cfg = fimc_read(EXYNOS_CITRGFMT);
916 cfg &= ~EXYNOS_CITRGFMT_FLIP_MASK;
917 cfg &= ~EXYNOS_CITRGFMT_OUTROT90_CLOCKWISE;
918
919 switch (degree) {
920 case EXYNOS_DRM_DEGREE_0:
921 if (flip & EXYNOS_DRM_FLIP_VERTICAL)
922 cfg |= EXYNOS_CITRGFMT_FLIP_X_MIRROR;
923 if (flip & EXYNOS_DRM_FLIP_HORIZONTAL)
924 cfg |= EXYNOS_CITRGFMT_FLIP_Y_MIRROR;
925 break;
926 case EXYNOS_DRM_DEGREE_90:
927 cfg |= EXYNOS_CITRGFMT_OUTROT90_CLOCKWISE;
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_180:
934 cfg |= (EXYNOS_CITRGFMT_FLIP_X_MIRROR |
935 EXYNOS_CITRGFMT_FLIP_Y_MIRROR);
936 if (flip & EXYNOS_DRM_FLIP_VERTICAL)
937 cfg &= ~EXYNOS_CITRGFMT_FLIP_X_MIRROR;
938 if (flip & EXYNOS_DRM_FLIP_HORIZONTAL)
939 cfg &= ~EXYNOS_CITRGFMT_FLIP_Y_MIRROR;
940 break;
941 case EXYNOS_DRM_DEGREE_270:
942 cfg |= (EXYNOS_CITRGFMT_OUTROT90_CLOCKWISE |
943 EXYNOS_CITRGFMT_FLIP_X_MIRROR |
944 EXYNOS_CITRGFMT_FLIP_Y_MIRROR);
945 if (flip & EXYNOS_DRM_FLIP_VERTICAL)
946 cfg &= ~EXYNOS_CITRGFMT_FLIP_X_MIRROR;
947 if (flip & EXYNOS_DRM_FLIP_HORIZONTAL)
948 cfg &= ~EXYNOS_CITRGFMT_FLIP_Y_MIRROR;
949 break;
950 default:
951 dev_err(ippdrv->dev, "inavlid degree value %d.\n", degree);
952 return -EINVAL;
953 }
954
955 fimc_write(cfg, EXYNOS_CITRGFMT);
956 *swap = (cfg & EXYNOS_CITRGFMT_OUTROT90_CLOCKWISE) ? 1 : 0;
957
958 return 0;
959}
960
961static int fimc_get_ratio_shift(u32 src, u32 dst, u32 *ratio, u32 *shift)
962{
963 DRM_DEBUG_KMS("%s:src[%d]dst[%d]\n", __func__, src, dst);
964
965 if (src >= dst * 64) {
966 DRM_ERROR("failed to make ratio and shift.\n");
967 return -EINVAL;
968 } else if (src >= dst * 32) {
969 *ratio = 32;
970 *shift = 5;
971 } else if (src >= dst * 16) {
972 *ratio = 16;
973 *shift = 4;
974 } else if (src >= dst * 8) {
975 *ratio = 8;
976 *shift = 3;
977 } else if (src >= dst * 4) {
978 *ratio = 4;
979 *shift = 2;
980 } else if (src >= dst * 2) {
981 *ratio = 2;
982 *shift = 1;
983 } else {
984 *ratio = 1;
985 *shift = 0;
986 }
987
988 return 0;
989}
990
991static int fimc_set_prescaler(struct fimc_context *ctx, struct fimc_scaler *sc,
992 struct drm_exynos_pos *src, struct drm_exynos_pos *dst)
993{
994 struct exynos_drm_ippdrv *ippdrv = &ctx->ippdrv;
995 u32 cfg, cfg_ext, shfactor;
996 u32 pre_dst_width, pre_dst_height;
997 u32 pre_hratio, hfactor, pre_vratio, vfactor;
998 int ret = 0;
999 u32 src_w, src_h, dst_w, dst_h;
1000
1001 cfg_ext = fimc_read(EXYNOS_CITRGFMT);
1002 if (cfg_ext & EXYNOS_CITRGFMT_INROT90_CLOCKWISE) {
1003 src_w = src->h;
1004 src_h = src->w;
1005 } else {
1006 src_w = src->w;
1007 src_h = src->h;
1008 }
1009
1010 if (cfg_ext & EXYNOS_CITRGFMT_OUTROT90_CLOCKWISE) {
1011 dst_w = dst->h;
1012 dst_h = dst->w;
1013 } else {
1014 dst_w = dst->w;
1015 dst_h = dst->h;
1016 }
1017
1018 ret = fimc_get_ratio_shift(src_w, dst_w, &pre_hratio, &hfactor);
1019 if (ret) {
1020 dev_err(ippdrv->dev, "failed to get ratio horizontal.\n");
1021 return ret;
1022 }
1023
1024 ret = fimc_get_ratio_shift(src_h, dst_h, &pre_vratio, &vfactor);
1025 if (ret) {
1026 dev_err(ippdrv->dev, "failed to get ratio vertical.\n");
1027 return ret;
1028 }
1029
1030 pre_dst_width = src_w / pre_hratio;
1031 pre_dst_height = src_h / pre_vratio;
1032 DRM_DEBUG_KMS("%s:pre_dst_width[%d]pre_dst_height[%d]\n", __func__,
1033 pre_dst_width, pre_dst_height);
1034 DRM_DEBUG_KMS("%s:pre_hratio[%d]hfactor[%d]pre_vratio[%d]vfactor[%d]\n",
1035 __func__, pre_hratio, hfactor, pre_vratio, vfactor);
1036
1037 sc->hratio = (src_w << 14) / (dst_w << hfactor);
1038 sc->vratio = (src_h << 14) / (dst_h << vfactor);
1039 sc->up_h = (dst_w >= src_w) ? true : false;
1040 sc->up_v = (dst_h >= src_h) ? true : false;
1041 DRM_DEBUG_KMS("%s:hratio[%d]vratio[%d]up_h[%d]up_v[%d]\n",
1042 __func__, sc->hratio, sc->vratio, sc->up_h, sc->up_v);
1043
1044 shfactor = FIMC_SHFACTOR - (hfactor + vfactor);
1045 DRM_DEBUG_KMS("%s:shfactor[%d]\n", __func__, shfactor);
1046
1047 cfg = (EXYNOS_CISCPRERATIO_SHFACTOR(shfactor) |
1048 EXYNOS_CISCPRERATIO_PREHORRATIO(pre_hratio) |
1049 EXYNOS_CISCPRERATIO_PREVERRATIO(pre_vratio));
1050 fimc_write(cfg, EXYNOS_CISCPRERATIO);
1051
1052 cfg = (EXYNOS_CISCPREDST_PREDSTWIDTH(pre_dst_width) |
1053 EXYNOS_CISCPREDST_PREDSTHEIGHT(pre_dst_height));
1054 fimc_write(cfg, EXYNOS_CISCPREDST);
1055
1056 return ret;
1057}
1058
1059static void fimc_set_scaler(struct fimc_context *ctx, struct fimc_scaler *sc)
1060{
1061 u32 cfg, cfg_ext;
1062
1063 DRM_DEBUG_KMS("%s:range[%d]bypass[%d]up_h[%d]up_v[%d]\n",
1064 __func__, sc->range, sc->bypass, sc->up_h, sc->up_v);
1065 DRM_DEBUG_KMS("%s:hratio[%d]vratio[%d]\n",
1066 __func__, sc->hratio, sc->vratio);
1067
1068 cfg = fimc_read(EXYNOS_CISCCTRL);
1069 cfg &= ~(EXYNOS_CISCCTRL_SCALERBYPASS |
1070 EXYNOS_CISCCTRL_SCALEUP_H | EXYNOS_CISCCTRL_SCALEUP_V |
1071 EXYNOS_CISCCTRL_MAIN_V_RATIO_MASK |
1072 EXYNOS_CISCCTRL_MAIN_H_RATIO_MASK |
1073 EXYNOS_CISCCTRL_CSCR2Y_WIDE |
1074 EXYNOS_CISCCTRL_CSCY2R_WIDE);
1075
1076 if (sc->range)
1077 cfg |= (EXYNOS_CISCCTRL_CSCR2Y_WIDE |
1078 EXYNOS_CISCCTRL_CSCY2R_WIDE);
1079 if (sc->bypass)
1080 cfg |= EXYNOS_CISCCTRL_SCALERBYPASS;
1081 if (sc->up_h)
1082 cfg |= EXYNOS_CISCCTRL_SCALEUP_H;
1083 if (sc->up_v)
1084 cfg |= EXYNOS_CISCCTRL_SCALEUP_V;
1085
1086 cfg |= (EXYNOS_CISCCTRL_MAINHORRATIO((sc->hratio >> 6)) |
1087 EXYNOS_CISCCTRL_MAINVERRATIO((sc->vratio >> 6)));
1088 fimc_write(cfg, EXYNOS_CISCCTRL);
1089
1090 cfg_ext = fimc_read(EXYNOS_CIEXTEN);
1091 cfg_ext &= ~EXYNOS_CIEXTEN_MAINHORRATIO_EXT_MASK;
1092 cfg_ext &= ~EXYNOS_CIEXTEN_MAINVERRATIO_EXT_MASK;
1093 cfg_ext |= (EXYNOS_CIEXTEN_MAINHORRATIO_EXT(sc->hratio) |
1094 EXYNOS_CIEXTEN_MAINVERRATIO_EXT(sc->vratio));
1095 fimc_write(cfg_ext, EXYNOS_CIEXTEN);
1096}
1097
1098static int fimc_dst_set_size(struct device *dev, int swap,
1099 struct drm_exynos_pos *pos, struct drm_exynos_sz *sz)
1100{
1101 struct fimc_context *ctx = get_fimc_context(dev);
1102 struct drm_exynos_pos img_pos = *pos;
1103 struct drm_exynos_sz img_sz = *sz;
1104 u32 cfg;
1105
1106 DRM_DEBUG_KMS("%s:swap[%d]hsize[%d]vsize[%d]\n",
1107 __func__, swap, sz->hsize, sz->vsize);
1108
1109 /* original size */
1110 cfg = (EXYNOS_ORGOSIZE_HORIZONTAL(img_sz.hsize) |
1111 EXYNOS_ORGOSIZE_VERTICAL(img_sz.vsize));
1112
1113 fimc_write(cfg, EXYNOS_ORGOSIZE);
1114
1115 DRM_DEBUG_KMS("%s:x[%d]y[%d]w[%d]h[%d]\n",
1116 __func__, pos->x, pos->y, pos->w, pos->h);
1117
1118 /* CSC ITU */
1119 cfg = fimc_read(EXYNOS_CIGCTRL);
1120 cfg &= ~EXYNOS_CIGCTRL_CSC_MASK;
1121
1122 if (sz->hsize >= FIMC_WIDTH_ITU_709)
1123 cfg |= EXYNOS_CIGCTRL_CSC_ITU709;
1124 else
1125 cfg |= EXYNOS_CIGCTRL_CSC_ITU601;
1126
1127 fimc_write(cfg, EXYNOS_CIGCTRL);
1128
1129 if (swap) {
1130 img_pos.w = pos->h;
1131 img_pos.h = pos->w;
1132 img_sz.hsize = sz->vsize;
1133 img_sz.vsize = sz->hsize;
1134 }
1135
1136 /* target image size */
1137 cfg = fimc_read(EXYNOS_CITRGFMT);
1138 cfg &= ~(EXYNOS_CITRGFMT_TARGETH_MASK |
1139 EXYNOS_CITRGFMT_TARGETV_MASK);
1140 cfg |= (EXYNOS_CITRGFMT_TARGETHSIZE(img_pos.w) |
1141 EXYNOS_CITRGFMT_TARGETVSIZE(img_pos.h));
1142 fimc_write(cfg, EXYNOS_CITRGFMT);
1143
1144 /* target area */
1145 cfg = EXYNOS_CITAREA_TARGET_AREA(img_pos.w * img_pos.h);
1146 fimc_write(cfg, EXYNOS_CITAREA);
1147
1148 /* offset Y(RGB), Cb, Cr */
1149 cfg = (EXYNOS_CIOYOFF_HORIZONTAL(img_pos.x) |
1150 EXYNOS_CIOYOFF_VERTICAL(img_pos.y));
1151 fimc_write(cfg, EXYNOS_CIOYOFF);
1152 cfg = (EXYNOS_CIOCBOFF_HORIZONTAL(img_pos.x) |
1153 EXYNOS_CIOCBOFF_VERTICAL(img_pos.y));
1154 fimc_write(cfg, EXYNOS_CIOCBOFF);
1155 cfg = (EXYNOS_CIOCROFF_HORIZONTAL(img_pos.x) |
1156 EXYNOS_CIOCROFF_VERTICAL(img_pos.y));
1157 fimc_write(cfg, EXYNOS_CIOCROFF);
1158
1159 return 0;
1160}
1161
1162static int fimc_dst_get_buf_seq(struct fimc_context *ctx)
1163{
1164 u32 cfg, i, buf_num = 0;
1165 u32 mask = 0x00000001;
1166
1167 cfg = fimc_read(EXYNOS_CIFCNTSEQ);
1168
1169 for (i = 0; i < FIMC_REG_SZ; i++)
1170 if (cfg & (mask << i))
1171 buf_num++;
1172
1173 DRM_DEBUG_KMS("%s:buf_num[%d]\n", __func__, buf_num);
1174
1175 return buf_num;
1176}
1177
1178static int fimc_dst_set_buf_seq(struct fimc_context *ctx, u32 buf_id,
1179 enum drm_exynos_ipp_buf_type buf_type)
1180{
1181 struct exynos_drm_ippdrv *ippdrv = &ctx->ippdrv;
1182 bool enable;
1183 u32 cfg;
1184 u32 mask = 0x00000001 << buf_id;
1185 int ret = 0;
1186
1187 DRM_DEBUG_KMS("%s:buf_id[%d]buf_type[%d]\n", __func__,
1188 buf_id, buf_type);
1189
1190 mutex_lock(&ctx->lock);
1191
1192 /* mask register set */
1193 cfg = fimc_read(EXYNOS_CIFCNTSEQ);
1194
1195 switch (buf_type) {
1196 case IPP_BUF_ENQUEUE:
1197 enable = true;
1198 break;
1199 case IPP_BUF_DEQUEUE:
1200 enable = false;
1201 break;
1202 default:
1203 dev_err(ippdrv->dev, "invalid buf ctrl parameter.\n");
1204 ret = -EINVAL;
1205 goto err_unlock;
1206 }
1207
1208 /* sequence id */
1209 cfg &= (~mask);
1210 cfg |= (enable << buf_id);
1211 fimc_write(cfg, EXYNOS_CIFCNTSEQ);
1212
1213 /* interrupt enable */
1214 if (buf_type == IPP_BUF_ENQUEUE &&
1215 fimc_dst_get_buf_seq(ctx) >= FIMC_BUF_START)
1216 fimc_handle_irq(ctx, true, false, true);
1217
1218 /* interrupt disable */
1219 if (buf_type == IPP_BUF_DEQUEUE &&
1220 fimc_dst_get_buf_seq(ctx) <= FIMC_BUF_STOP)
1221 fimc_handle_irq(ctx, false, false, true);
1222
1223err_unlock:
1224 mutex_unlock(&ctx->lock);
1225 return ret;
1226}
1227
1228static int fimc_dst_set_addr(struct device *dev,
1229 struct drm_exynos_ipp_buf_info *buf_info, u32 buf_id,
1230 enum drm_exynos_ipp_buf_type buf_type)
1231{
1232 struct fimc_context *ctx = get_fimc_context(dev);
1233 struct exynos_drm_ippdrv *ippdrv = &ctx->ippdrv;
1234 struct drm_exynos_ipp_cmd_node *c_node = ippdrv->cmd;
1235 struct drm_exynos_ipp_property *property;
1236 struct drm_exynos_ipp_config *config;
1237
1238 if (!c_node) {
1239 DRM_ERROR("failed to get c_node.\n");
1240 return -EINVAL;
1241 }
1242
1243 property = &c_node->property;
1244 if (!property) {
1245 DRM_ERROR("failed to get property.\n");
1246 return -EINVAL;
1247 }
1248
1249 DRM_DEBUG_KMS("%s:prop_id[%d]buf_id[%d]buf_type[%d]\n", __func__,
1250 property->prop_id, buf_id, buf_type);
1251
1252 if (buf_id > FIMC_MAX_DST) {
1253 dev_info(ippdrv->dev, "inavlid buf_id %d.\n", buf_id);
1254 return -ENOMEM;
1255 }
1256
1257 /* address register set */
1258 switch (buf_type) {
1259 case IPP_BUF_ENQUEUE:
1260 config = &property->config[EXYNOS_DRM_OPS_DST];
1261
1262 fimc_write(buf_info->base[EXYNOS_DRM_PLANAR_Y],
1263 EXYNOS_CIOYSA(buf_id));
1264
1265 if (config->fmt == DRM_FORMAT_YVU420) {
1266 fimc_write(buf_info->base[EXYNOS_DRM_PLANAR_CR],
1267 EXYNOS_CIOCBSA(buf_id));
1268 fimc_write(buf_info->base[EXYNOS_DRM_PLANAR_CB],
1269 EXYNOS_CIOCRSA(buf_id));
1270 } else {
1271 fimc_write(buf_info->base[EXYNOS_DRM_PLANAR_CB],
1272 EXYNOS_CIOCBSA(buf_id));
1273 fimc_write(buf_info->base[EXYNOS_DRM_PLANAR_CR],
1274 EXYNOS_CIOCRSA(buf_id));
1275 }
1276 break;
1277 case IPP_BUF_DEQUEUE:
1278 fimc_write(0x0, EXYNOS_CIOYSA(buf_id));
1279 fimc_write(0x0, EXYNOS_CIOCBSA(buf_id));
1280 fimc_write(0x0, EXYNOS_CIOCRSA(buf_id));
1281 break;
1282 default:
1283 /* bypass */
1284 break;
1285 }
1286
1287 return fimc_dst_set_buf_seq(ctx, buf_id, buf_type);
1288}
1289
1290static struct exynos_drm_ipp_ops fimc_dst_ops = {
1291 .set_fmt = fimc_dst_set_fmt,
1292 .set_transf = fimc_dst_set_transf,
1293 .set_size = fimc_dst_set_size,
1294 .set_addr = fimc_dst_set_addr,
1295};
1296
1297static int fimc_clk_ctrl(struct fimc_context *ctx, bool enable)
1298{
1299 DRM_DEBUG_KMS("%s:enable[%d]\n", __func__, enable);
1300
1301 if (enable) {
1302 clk_enable(ctx->sclk_fimc_clk);
1303 clk_enable(ctx->fimc_clk);
1304 clk_enable(ctx->wb_clk);
1305 ctx->suspended = false;
1306 } else {
1307 clk_disable(ctx->sclk_fimc_clk);
1308 clk_disable(ctx->fimc_clk);
1309 clk_disable(ctx->wb_clk);
1310 ctx->suspended = true;
1311 }
1312
1313 return 0;
1314}
1315
1316static irqreturn_t fimc_irq_handler(int irq, void *dev_id)
1317{
1318 struct fimc_context *ctx = dev_id;
1319 struct exynos_drm_ippdrv *ippdrv = &ctx->ippdrv;
1320 struct drm_exynos_ipp_cmd_node *c_node = ippdrv->cmd;
1321 struct drm_exynos_ipp_event_work *event_work =
1322 c_node->event_work;
1323 int buf_id;
1324
1325 DRM_DEBUG_KMS("%s:fimc id[%d]\n", __func__, ctx->id);
1326
1327 fimc_clear_irq(ctx);
1328 if (fimc_check_ovf(ctx))
1329 return IRQ_NONE;
1330
1331 if (!fimc_check_frame_end(ctx))
1332 return IRQ_NONE;
1333
1334 buf_id = fimc_get_buf_id(ctx);
1335 if (buf_id < 0)
1336 return IRQ_HANDLED;
1337
1338 DRM_DEBUG_KMS("%s:buf_id[%d]\n", __func__, buf_id);
1339
1340 if (fimc_dst_set_buf_seq(ctx, buf_id, IPP_BUF_DEQUEUE) < 0) {
1341 DRM_ERROR("failed to dequeue.\n");
1342 return IRQ_HANDLED;
1343 }
1344
1345 event_work->ippdrv = ippdrv;
1346 event_work->buf_id[EXYNOS_DRM_OPS_DST] = buf_id;
1347 queue_work(ippdrv->event_workq, (struct work_struct *)event_work);
1348
1349 return IRQ_HANDLED;
1350}
1351
1352static int fimc_init_prop_list(struct exynos_drm_ippdrv *ippdrv)
1353{
1354 struct drm_exynos_ipp_prop_list *prop_list;
1355
1356 DRM_DEBUG_KMS("%s\n", __func__);
1357
1358 prop_list = devm_kzalloc(ippdrv->dev, sizeof(*prop_list), GFP_KERNEL);
1359 if (!prop_list) {
1360 DRM_ERROR("failed to alloc property list.\n");
1361 return -ENOMEM;
1362 }
1363
1364 prop_list->version = 1;
1365 prop_list->writeback = 1;
1366 prop_list->refresh_min = FIMC_REFRESH_MIN;
1367 prop_list->refresh_max = FIMC_REFRESH_MAX;
1368 prop_list->flip = (1 << EXYNOS_DRM_FLIP_NONE) |
1369 (1 << EXYNOS_DRM_FLIP_VERTICAL) |
1370 (1 << EXYNOS_DRM_FLIP_HORIZONTAL);
1371 prop_list->degree = (1 << EXYNOS_DRM_DEGREE_0) |
1372 (1 << EXYNOS_DRM_DEGREE_90) |
1373 (1 << EXYNOS_DRM_DEGREE_180) |
1374 (1 << EXYNOS_DRM_DEGREE_270);
1375 prop_list->csc = 1;
1376 prop_list->crop = 1;
1377 prop_list->crop_max.hsize = FIMC_CROP_MAX;
1378 prop_list->crop_max.vsize = FIMC_CROP_MAX;
1379 prop_list->crop_min.hsize = FIMC_CROP_MIN;
1380 prop_list->crop_min.vsize = FIMC_CROP_MIN;
1381 prop_list->scale = 1;
1382 prop_list->scale_max.hsize = FIMC_SCALE_MAX;
1383 prop_list->scale_max.vsize = FIMC_SCALE_MAX;
1384 prop_list->scale_min.hsize = FIMC_SCALE_MIN;
1385 prop_list->scale_min.vsize = FIMC_SCALE_MIN;
1386
1387 ippdrv->prop_list = prop_list;
1388
1389 return 0;
1390}
1391
1392static inline bool fimc_check_drm_flip(enum drm_exynos_flip flip)
1393{
1394 switch (flip) {
1395 case EXYNOS_DRM_FLIP_NONE:
1396 case EXYNOS_DRM_FLIP_VERTICAL:
1397 case EXYNOS_DRM_FLIP_HORIZONTAL:
1398 return true;
1399 default:
1400 DRM_DEBUG_KMS("%s:invalid flip\n", __func__);
1401 return false;
1402 }
1403}
1404
1405static int fimc_ippdrv_check_property(struct device *dev,
1406 struct drm_exynos_ipp_property *property)
1407{
1408 struct fimc_context *ctx = get_fimc_context(dev);
1409 struct exynos_drm_ippdrv *ippdrv = &ctx->ippdrv;
1410 struct drm_exynos_ipp_prop_list *pp = ippdrv->prop_list;
1411 struct drm_exynos_ipp_config *config;
1412 struct drm_exynos_pos *pos;
1413 struct drm_exynos_sz *sz;
1414 bool swap;
1415 int i;
1416
1417 DRM_DEBUG_KMS("%s\n", __func__);
1418
1419 for_each_ipp_ops(i) {
1420 if ((i == EXYNOS_DRM_OPS_SRC) &&
1421 (property->cmd == IPP_CMD_WB))
1422 continue;
1423
1424 config = &property->config[i];
1425 pos = &config->pos;
1426 sz = &config->sz;
1427
1428 /* check for flip */
1429 if (!fimc_check_drm_flip(config->flip)) {
1430 DRM_ERROR("invalid flip.\n");
1431 goto err_property;
1432 }
1433
1434 /* check for degree */
1435 switch (config->degree) {
1436 case EXYNOS_DRM_DEGREE_90:
1437 case EXYNOS_DRM_DEGREE_270:
1438 swap = true;
1439 break;
1440 case EXYNOS_DRM_DEGREE_0:
1441 case EXYNOS_DRM_DEGREE_180:
1442 swap = false;
1443 break;
1444 default:
1445 DRM_ERROR("invalid degree.\n");
1446 goto err_property;
1447 }
1448
1449 /* check for buffer bound */
1450 if ((pos->x + pos->w > sz->hsize) ||
1451 (pos->y + pos->h > sz->vsize)) {
1452 DRM_ERROR("out of buf bound.\n");
1453 goto err_property;
1454 }
1455
1456 /* check for crop */
1457 if ((i == EXYNOS_DRM_OPS_SRC) && (pp->crop)) {
1458 if (swap) {
1459 if ((pos->h < pp->crop_min.hsize) ||
1460 (sz->vsize > pp->crop_max.hsize) ||
1461 (pos->w < pp->crop_min.vsize) ||
1462 (sz->hsize > pp->crop_max.vsize)) {
1463 DRM_ERROR("out of crop size.\n");
1464 goto err_property;
1465 }
1466 } else {
1467 if ((pos->w < pp->crop_min.hsize) ||
1468 (sz->hsize > pp->crop_max.hsize) ||
1469 (pos->h < pp->crop_min.vsize) ||
1470 (sz->vsize > pp->crop_max.vsize)) {
1471 DRM_ERROR("out of crop size.\n");
1472 goto err_property;
1473 }
1474 }
1475 }
1476
1477 /* check for scale */
1478 if ((i == EXYNOS_DRM_OPS_DST) && (pp->scale)) {
1479 if (swap) {
1480 if ((pos->h < pp->scale_min.hsize) ||
1481 (sz->vsize > pp->scale_max.hsize) ||
1482 (pos->w < pp->scale_min.vsize) ||
1483 (sz->hsize > pp->scale_max.vsize)) {
1484 DRM_ERROR("out of scale size.\n");
1485 goto err_property;
1486 }
1487 } else {
1488 if ((pos->w < pp->scale_min.hsize) ||
1489 (sz->hsize > pp->scale_max.hsize) ||
1490 (pos->h < pp->scale_min.vsize) ||
1491 (sz->vsize > pp->scale_max.vsize)) {
1492 DRM_ERROR("out of scale size.\n");
1493 goto err_property;
1494 }
1495 }
1496 }
1497 }
1498
1499 return 0;
1500
1501err_property:
1502 for_each_ipp_ops(i) {
1503 if ((i == EXYNOS_DRM_OPS_SRC) &&
1504 (property->cmd == IPP_CMD_WB))
1505 continue;
1506
1507 config = &property->config[i];
1508 pos = &config->pos;
1509 sz = &config->sz;
1510
1511 DRM_ERROR("[%s]f[%d]r[%d]pos[%d %d %d %d]sz[%d %d]\n",
1512 i ? "dst" : "src", config->flip, config->degree,
1513 pos->x, pos->y, pos->w, pos->h,
1514 sz->hsize, sz->vsize);
1515 }
1516
1517 return -EINVAL;
1518}
1519
1520static void fimc_clear_addr(struct fimc_context *ctx)
1521{
1522 int i;
1523
1524 DRM_DEBUG_KMS("%s:\n", __func__);
1525
1526 for (i = 0; i < FIMC_MAX_SRC; i++) {
1527 fimc_write(0, EXYNOS_CIIYSA(i));
1528 fimc_write(0, EXYNOS_CIICBSA(i));
1529 fimc_write(0, EXYNOS_CIICRSA(i));
1530 }
1531
1532 for (i = 0; i < FIMC_MAX_DST; i++) {
1533 fimc_write(0, EXYNOS_CIOYSA(i));
1534 fimc_write(0, EXYNOS_CIOCBSA(i));
1535 fimc_write(0, EXYNOS_CIOCRSA(i));
1536 }
1537}
1538
1539static int fimc_ippdrv_reset(struct device *dev)
1540{
1541 struct fimc_context *ctx = get_fimc_context(dev);
1542
1543 DRM_DEBUG_KMS("%s\n", __func__);
1544
1545 /* reset h/w block */
1546 fimc_sw_reset(ctx, false);
1547
1548 /* reset scaler capability */
1549 memset(&ctx->sc, 0x0, sizeof(ctx->sc));
1550
1551 fimc_clear_addr(ctx);
1552
1553 return 0;
1554}
1555
1556static int fimc_ippdrv_start(struct device *dev, enum drm_exynos_ipp_cmd cmd)
1557{
1558 struct fimc_context *ctx = get_fimc_context(dev);
1559 struct exynos_drm_ippdrv *ippdrv = &ctx->ippdrv;
1560 struct drm_exynos_ipp_cmd_node *c_node = ippdrv->cmd;
1561 struct drm_exynos_ipp_property *property;
1562 struct drm_exynos_ipp_config *config;
1563 struct drm_exynos_pos img_pos[EXYNOS_DRM_OPS_MAX];
1564 struct drm_exynos_ipp_set_wb set_wb;
1565 int ret, i;
1566 u32 cfg0, cfg1;
1567
1568 DRM_DEBUG_KMS("%s:cmd[%d]\n", __func__, cmd);
1569
1570 if (!c_node) {
1571 DRM_ERROR("failed to get c_node.\n");
1572 return -EINVAL;
1573 }
1574
1575 property = &c_node->property;
1576 if (!property) {
1577 DRM_ERROR("failed to get property.\n");
1578 return -EINVAL;
1579 }
1580
1581 fimc_handle_irq(ctx, true, false, true);
1582
1583 for_each_ipp_ops(i) {
1584 config = &property->config[i];
1585 img_pos[i] = config->pos;
1586 }
1587
1588 ret = fimc_set_prescaler(ctx, &ctx->sc,
1589 &img_pos[EXYNOS_DRM_OPS_SRC],
1590 &img_pos[EXYNOS_DRM_OPS_DST]);
1591 if (ret) {
1592 dev_err(dev, "failed to set precalser.\n");
1593 return ret;
1594 }
1595
1596 /* If set ture, we can save jpeg about screen */
1597 fimc_handle_jpeg(ctx, false);
1598 fimc_set_scaler(ctx, &ctx->sc);
1599 fimc_set_polarity(ctx, &ctx->pol);
1600
1601 switch (cmd) {
1602 case IPP_CMD_M2M:
1603 fimc_set_type_ctrl(ctx, FIMC_WB_NONE);
1604 fimc_handle_lastend(ctx, false);
1605
1606 /* setup dma */
1607 cfg0 = fimc_read(EXYNOS_MSCTRL);
1608 cfg0 &= ~EXYNOS_MSCTRL_INPUT_MASK;
1609 cfg0 |= EXYNOS_MSCTRL_INPUT_MEMORY;
1610 fimc_write(cfg0, EXYNOS_MSCTRL);
1611 break;
1612 case IPP_CMD_WB:
1613 fimc_set_type_ctrl(ctx, FIMC_WB_A);
1614 fimc_handle_lastend(ctx, true);
1615
1616 /* setup FIMD */
1617 fimc_set_camblk_fimd0_wb(ctx);
1618
1619 set_wb.enable = 1;
1620 set_wb.refresh = property->refresh_rate;
1621 exynos_drm_ippnb_send_event(IPP_SET_WRITEBACK, (void *)&set_wb);
1622 break;
1623 case IPP_CMD_OUTPUT:
1624 default:
1625 ret = -EINVAL;
1626 dev_err(dev, "invalid operations.\n");
1627 return ret;
1628 }
1629
1630 /* Reset status */
1631 fimc_write(0x0, EXYNOS_CISTATUS);
1632
1633 cfg0 = fimc_read(EXYNOS_CIIMGCPT);
1634 cfg0 &= ~EXYNOS_CIIMGCPT_IMGCPTEN_SC;
1635 cfg0 |= EXYNOS_CIIMGCPT_IMGCPTEN_SC;
1636
1637 /* Scaler */
1638 cfg1 = fimc_read(EXYNOS_CISCCTRL);
1639 cfg1 &= ~EXYNOS_CISCCTRL_SCAN_MASK;
1640 cfg1 |= (EXYNOS_CISCCTRL_PROGRESSIVE |
1641 EXYNOS_CISCCTRL_SCALERSTART);
1642
1643 fimc_write(cfg1, EXYNOS_CISCCTRL);
1644
1645 /* Enable image capture*/
1646 cfg0 |= EXYNOS_CIIMGCPT_IMGCPTEN;
1647 fimc_write(cfg0, EXYNOS_CIIMGCPT);
1648
1649 /* Disable frame end irq */
1650 cfg0 = fimc_read(EXYNOS_CIGCTRL);
1651 cfg0 &= ~EXYNOS_CIGCTRL_IRQ_END_DISABLE;
1652 fimc_write(cfg0, EXYNOS_CIGCTRL);
1653
1654 cfg0 = fimc_read(EXYNOS_CIOCTRL);
1655 cfg0 &= ~EXYNOS_CIOCTRL_WEAVE_MASK;
1656 fimc_write(cfg0, EXYNOS_CIOCTRL);
1657
1658 if (cmd == IPP_CMD_M2M) {
1659 cfg0 = fimc_read(EXYNOS_MSCTRL);
1660 cfg0 |= EXYNOS_MSCTRL_ENVID;
1661 fimc_write(cfg0, EXYNOS_MSCTRL);
1662
1663 cfg0 = fimc_read(EXYNOS_MSCTRL);
1664 cfg0 |= EXYNOS_MSCTRL_ENVID;
1665 fimc_write(cfg0, EXYNOS_MSCTRL);
1666 }
1667
1668 return 0;
1669}
1670
1671static void fimc_ippdrv_stop(struct device *dev, enum drm_exynos_ipp_cmd cmd)
1672{
1673 struct fimc_context *ctx = get_fimc_context(dev);
1674 struct drm_exynos_ipp_set_wb set_wb = {0, 0};
1675 u32 cfg;
1676
1677 DRM_DEBUG_KMS("%s:cmd[%d]\n", __func__, cmd);
1678
1679 switch (cmd) {
1680 case IPP_CMD_M2M:
1681 /* Source clear */
1682 cfg = fimc_read(EXYNOS_MSCTRL);
1683 cfg &= ~EXYNOS_MSCTRL_INPUT_MASK;
1684 cfg &= ~EXYNOS_MSCTRL_ENVID;
1685 fimc_write(cfg, EXYNOS_MSCTRL);
1686 break;
1687 case IPP_CMD_WB:
1688 exynos_drm_ippnb_send_event(IPP_SET_WRITEBACK, (void *)&set_wb);
1689 break;
1690 case IPP_CMD_OUTPUT:
1691 default:
1692 dev_err(dev, "invalid operations.\n");
1693 break;
1694 }
1695
1696 fimc_handle_irq(ctx, false, false, true);
1697
1698 /* reset sequence */
1699 fimc_write(0x0, EXYNOS_CIFCNTSEQ);
1700
1701 /* Scaler disable */
1702 cfg = fimc_read(EXYNOS_CISCCTRL);
1703 cfg &= ~EXYNOS_CISCCTRL_SCALERSTART;
1704 fimc_write(cfg, EXYNOS_CISCCTRL);
1705
1706 /* Disable image capture */
1707 cfg = fimc_read(EXYNOS_CIIMGCPT);
1708 cfg &= ~(EXYNOS_CIIMGCPT_IMGCPTEN_SC | EXYNOS_CIIMGCPT_IMGCPTEN);
1709 fimc_write(cfg, EXYNOS_CIIMGCPT);
1710
1711 /* Enable frame end irq */
1712 cfg = fimc_read(EXYNOS_CIGCTRL);
1713 cfg |= EXYNOS_CIGCTRL_IRQ_END_DISABLE;
1714 fimc_write(cfg, EXYNOS_CIGCTRL);
1715}
1716
1717static int __devinit fimc_probe(struct platform_device *pdev)
1718{
1719 struct device *dev = &pdev->dev;
1720 struct fimc_context *ctx;
1721 struct clk *parent_clk;
1722 struct resource *res;
1723 struct exynos_drm_ippdrv *ippdrv;
1724 struct exynos_drm_fimc_pdata *pdata;
1725 struct fimc_driverdata *ddata;
1726 int ret;
1727
1728 pdata = pdev->dev.platform_data;
1729 if (!pdata) {
1730 dev_err(dev, "no platform data specified.\n");
1731 return -EINVAL;
1732 }
1733
1734 ctx = devm_kzalloc(dev, sizeof(*ctx), GFP_KERNEL);
1735 if (!ctx)
1736 return -ENOMEM;
1737
1738 ddata = (struct fimc_driverdata *)
1739 platform_get_device_id(pdev)->driver_data;
1740
1741 /* clock control */
1742 ctx->sclk_fimc_clk = clk_get(dev, "sclk_fimc");
1743 if (IS_ERR(ctx->sclk_fimc_clk)) {
1744 dev_err(dev, "failed to get src fimc clock.\n");
1745 ret = PTR_ERR(ctx->sclk_fimc_clk);
1746 goto err_ctx;
1747 }
1748 clk_enable(ctx->sclk_fimc_clk);
1749
1750 ctx->fimc_clk = clk_get(dev, "fimc");
1751 if (IS_ERR(ctx->fimc_clk)) {
1752 dev_err(dev, "failed to get fimc clock.\n");
1753 ret = PTR_ERR(ctx->fimc_clk);
1754 clk_disable(ctx->sclk_fimc_clk);
1755 clk_put(ctx->sclk_fimc_clk);
1756 goto err_ctx;
1757 }
1758
1759 ctx->wb_clk = clk_get(dev, "pxl_async0");
1760 if (IS_ERR(ctx->wb_clk)) {
1761 dev_err(dev, "failed to get writeback a clock.\n");
1762 ret = PTR_ERR(ctx->wb_clk);
1763 clk_disable(ctx->sclk_fimc_clk);
1764 clk_put(ctx->sclk_fimc_clk);
1765 clk_put(ctx->fimc_clk);
1766 goto err_ctx;
1767 }
1768
1769 ctx->wb_b_clk = clk_get(dev, "pxl_async1");
1770 if (IS_ERR(ctx->wb_b_clk)) {
1771 dev_err(dev, "failed to get writeback b clock.\n");
1772 ret = PTR_ERR(ctx->wb_b_clk);
1773 clk_disable(ctx->sclk_fimc_clk);
1774 clk_put(ctx->sclk_fimc_clk);
1775 clk_put(ctx->fimc_clk);
1776 clk_put(ctx->wb_clk);
1777 goto err_ctx;
1778 }
1779
1780 parent_clk = clk_get(dev, ddata->parent_clk);
1781
1782 if (IS_ERR(parent_clk)) {
1783 dev_err(dev, "failed to get parent clock.\n");
1784 ret = PTR_ERR(parent_clk);
1785 clk_disable(ctx->sclk_fimc_clk);
1786 clk_put(ctx->sclk_fimc_clk);
1787 clk_put(ctx->fimc_clk);
1788 clk_put(ctx->wb_clk);
1789 clk_put(ctx->wb_b_clk);
1790 goto err_ctx;
1791 }
1792
1793 if (clk_set_parent(ctx->sclk_fimc_clk, parent_clk)) {
1794 dev_err(dev, "failed to set parent.\n");
1795 ret = -EINVAL;
1796 clk_put(parent_clk);
1797 clk_disable(ctx->sclk_fimc_clk);
1798 clk_put(ctx->sclk_fimc_clk);
1799 clk_put(ctx->fimc_clk);
1800 clk_put(ctx->wb_clk);
1801 clk_put(ctx->wb_b_clk);
1802 goto err_ctx;
1803 }
1804
1805 clk_put(parent_clk);
1806 clk_set_rate(ctx->sclk_fimc_clk, pdata->clk_rate);
1807
1808 /* resource memory */
1809 ctx->regs_res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
1810 if (!ctx->regs_res) {
1811 dev_err(dev, "failed to find registers.\n");
1812 ret = -ENOENT;
1813 goto err_clk;
1814 }
1815
1816 ctx->regs = devm_request_and_ioremap(dev, ctx->regs_res);
1817 if (!ctx->regs) {
1818 dev_err(dev, "failed to map registers.\n");
1819 ret = -ENXIO;
1820 goto err_clk;
1821 }
1822
1823 /* resource irq */
1824 res = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
1825 if (!res) {
1826 dev_err(dev, "failed to request irq resource.\n");
1827 ret = -ENOENT;
1828 goto err_get_regs;
1829 }
1830
1831 ctx->irq = res->start;
1832 ret = request_threaded_irq(ctx->irq, NULL, fimc_irq_handler,
1833 IRQF_ONESHOT, "drm_fimc", ctx);
1834 if (ret < 0) {
1835 dev_err(dev, "failed to request irq.\n");
1836 goto err_get_regs;
1837 }
1838
1839 /* context initailization */
1840 ctx->id = pdev->id;
1841 ctx->pol = pdata->pol;
1842 ctx->ddata = ddata;
1843
1844 ippdrv = &ctx->ippdrv;
1845 ippdrv->dev = dev;
1846 ippdrv->ops[EXYNOS_DRM_OPS_SRC] = &fimc_src_ops;
1847 ippdrv->ops[EXYNOS_DRM_OPS_DST] = &fimc_dst_ops;
1848 ippdrv->check_property = fimc_ippdrv_check_property;
1849 ippdrv->reset = fimc_ippdrv_reset;
1850 ippdrv->start = fimc_ippdrv_start;
1851 ippdrv->stop = fimc_ippdrv_stop;
1852 ret = fimc_init_prop_list(ippdrv);
1853 if (ret < 0) {
1854 dev_err(dev, "failed to init property list.\n");
1855 goto err_get_irq;
1856 }
1857
1858 DRM_DEBUG_KMS("%s:id[%d]ippdrv[0x%x]\n", __func__, ctx->id,
1859 (int)ippdrv);
1860
1861 mutex_init(&ctx->lock);
1862 platform_set_drvdata(pdev, ctx);
1863
1864 pm_runtime_set_active(dev);
1865 pm_runtime_enable(dev);
1866
1867 ret = exynos_drm_ippdrv_register(ippdrv);
1868 if (ret < 0) {
1869 dev_err(dev, "failed to register drm fimc device.\n");
1870 goto err_ippdrv_register;
1871 }
1872
1873 dev_info(&pdev->dev, "drm fimc registered successfully.\n");
1874
1875 return 0;
1876
1877err_ippdrv_register:
1878 devm_kfree(dev, ippdrv->prop_list);
1879 pm_runtime_disable(dev);
1880err_get_irq:
1881 free_irq(ctx->irq, ctx);
1882err_get_regs:
1883 devm_iounmap(dev, ctx->regs);
1884err_clk:
1885 clk_put(ctx->sclk_fimc_clk);
1886 clk_put(ctx->fimc_clk);
1887 clk_put(ctx->wb_clk);
1888 clk_put(ctx->wb_b_clk);
1889err_ctx:
1890 devm_kfree(dev, ctx);
1891 return ret;
1892}
1893
1894static int __devexit fimc_remove(struct platform_device *pdev)
1895{
1896 struct device *dev = &pdev->dev;
1897 struct fimc_context *ctx = get_fimc_context(dev);
1898 struct exynos_drm_ippdrv *ippdrv = &ctx->ippdrv;
1899
1900 devm_kfree(dev, ippdrv->prop_list);
1901 exynos_drm_ippdrv_unregister(ippdrv);
1902 mutex_destroy(&ctx->lock);
1903
1904 pm_runtime_set_suspended(dev);
1905 pm_runtime_disable(dev);
1906
1907 free_irq(ctx->irq, ctx);
1908 devm_iounmap(dev, ctx->regs);
1909
1910 clk_put(ctx->sclk_fimc_clk);
1911 clk_put(ctx->fimc_clk);
1912 clk_put(ctx->wb_clk);
1913 clk_put(ctx->wb_b_clk);
1914
1915 devm_kfree(dev, ctx);
1916
1917 return 0;
1918}
1919
1920#ifdef CONFIG_PM_SLEEP
1921static int fimc_suspend(struct device *dev)
1922{
1923 struct fimc_context *ctx = get_fimc_context(dev);
1924
1925 DRM_DEBUG_KMS("%s:id[%d]\n", __func__, ctx->id);
1926
1927 if (pm_runtime_suspended(dev))
1928 return 0;
1929
1930 return fimc_clk_ctrl(ctx, false);
1931}
1932
1933static int fimc_resume(struct device *dev)
1934{
1935 struct fimc_context *ctx = get_fimc_context(dev);
1936
1937 DRM_DEBUG_KMS("%s:id[%d]\n", __func__, ctx->id);
1938
1939 if (!pm_runtime_suspended(dev))
1940 return fimc_clk_ctrl(ctx, true);
1941
1942 return 0;
1943}
1944#endif
1945
1946#ifdef CONFIG_PM_RUNTIME
1947static int fimc_runtime_suspend(struct device *dev)
1948{
1949 struct fimc_context *ctx = get_fimc_context(dev);
1950
1951 DRM_DEBUG_KMS("%s:id[%d]\n", __func__, ctx->id);
1952
1953 return fimc_clk_ctrl(ctx, false);
1954}
1955
1956static int fimc_runtime_resume(struct device *dev)
1957{
1958 struct fimc_context *ctx = get_fimc_context(dev);
1959
1960 DRM_DEBUG_KMS("%s:id[%d]\n", __func__, ctx->id);
1961
1962 return fimc_clk_ctrl(ctx, true);
1963}
1964#endif
1965
1966static struct fimc_driverdata exynos4210_fimc_data = {
1967 .parent_clk = "mout_mpll",
1968};
1969
1970static struct fimc_driverdata exynos4410_fimc_data = {
1971 .parent_clk = "mout_mpll_user",
1972};
1973
1974static struct platform_device_id fimc_driver_ids[] = {
1975 {
1976 .name = "exynos4210-fimc",
1977 .driver_data = (unsigned long)&exynos4210_fimc_data,
1978 }, {
1979 .name = "exynos4412-fimc",
1980 .driver_data = (unsigned long)&exynos4410_fimc_data,
1981 },
1982 {},
1983};
1984MODULE_DEVICE_TABLE(platform, fimc_driver_ids);
1985
1986static const struct dev_pm_ops fimc_pm_ops = {
1987 SET_SYSTEM_SLEEP_PM_OPS(fimc_suspend, fimc_resume)
1988 SET_RUNTIME_PM_OPS(fimc_runtime_suspend, fimc_runtime_resume, NULL)
1989};
1990
1991struct platform_driver fimc_driver = {
1992 .probe = fimc_probe,
1993 .remove = __devexit_p(fimc_remove),
1994 .id_table = fimc_driver_ids,
1995 .driver = {
1996 .name = "exynos-drm-fimc",
1997 .owner = THIS_MODULE,
1998 .pm = &fimc_pm_ops,
1999 },
2000};
2001
diff --git a/drivers/gpu/drm/exynos/exynos_drm_fimc.h b/drivers/gpu/drm/exynos/exynos_drm_fimc.h
new file mode 100644
index 000000000000..dc970fa0d888
--- /dev/null
+++ b/drivers/gpu/drm/exynos/exynos_drm_fimc.h
@@ -0,0 +1,37 @@
1/*
2 * Copyright (c) 2012 Samsung Electronics Co., Ltd.
3 *
4 * Authors:
5 * Eunchul Kim <chulspro.kim@samsung.com>
6 * Jinyoung Jeon <jy0.jeon@samsung.com>
7 * Sangmin Lee <lsmin.lee@samsung.com>
8 *
9 * Permission is hereby granted, free of charge, to any person obtaining a
10 * copy of this software and associated documentation files (the "Software"),
11 * to deal in the Software without restriction, including without limitation
12 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
13 * and/or sell copies of the Software, and to permit persons to whom the
14 * Software is furnished to do so, subject to the following conditions:
15 *
16 * The above copyright notice and this permission notice (including the next
17 * paragraph) shall be included in all copies or substantial portions of the
18 * Software.
19 *
20 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
21 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
22 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
23 * VA LINUX SYSTEMS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
24 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
25 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
26 * OTHER DEALINGS IN THE SOFTWARE.
27 */
28
29#ifndef _EXYNOS_DRM_FIMC_H_
30#define _EXYNOS_DRM_FIMC_H_
31
32/*
33 * TODO
34 * FIMD output interface notifier callback.
35 */
36
37#endif /* _EXYNOS_DRM_FIMC_H_ */
diff --git a/drivers/gpu/drm/exynos/regs-fimc.h b/drivers/gpu/drm/exynos/regs-fimc.h
new file mode 100644
index 000000000000..b4f9ca1fd851
--- /dev/null
+++ b/drivers/gpu/drm/exynos/regs-fimc.h
@@ -0,0 +1,669 @@
1/* drivers/gpu/drm/exynos/regs-fimc.h
2 *
3 * Copyright (c) 2012 Samsung Electronics Co., Ltd.
4 * http://www.samsung.com/
5 *
6 * Register definition file for Samsung Camera Interface (FIMC) driver
7 *
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License version 2 as
10 * published by the Free Software Foundation.
11*/
12
13#ifndef EXYNOS_REGS_FIMC_H
14#define EXYNOS_REGS_FIMC_H
15
16/*
17 * Register part
18*/
19/* Input source format */
20#define EXYNOS_CISRCFMT (0x00)
21/* Window offset */
22#define EXYNOS_CIWDOFST (0x04)
23/* Global control */
24#define EXYNOS_CIGCTRL (0x08)
25/* Window offset 2 */
26#define EXYNOS_CIWDOFST2 (0x14)
27/* Y 1st frame start address for output DMA */
28#define EXYNOS_CIOYSA1 (0x18)
29/* Y 2nd frame start address for output DMA */
30#define EXYNOS_CIOYSA2 (0x1c)
31/* Y 3rd frame start address for output DMA */
32#define EXYNOS_CIOYSA3 (0x20)
33/* Y 4th frame start address for output DMA */
34#define EXYNOS_CIOYSA4 (0x24)
35/* Cb 1st frame start address for output DMA */
36#define EXYNOS_CIOCBSA1 (0x28)
37/* Cb 2nd frame start address for output DMA */
38#define EXYNOS_CIOCBSA2 (0x2c)
39/* Cb 3rd frame start address for output DMA */
40#define EXYNOS_CIOCBSA3 (0x30)
41/* Cb 4th frame start address for output DMA */
42#define EXYNOS_CIOCBSA4 (0x34)
43/* Cr 1st frame start address for output DMA */
44#define EXYNOS_CIOCRSA1 (0x38)
45/* Cr 2nd frame start address for output DMA */
46#define EXYNOS_CIOCRSA2 (0x3c)
47/* Cr 3rd frame start address for output DMA */
48#define EXYNOS_CIOCRSA3 (0x40)
49/* Cr 4th frame start address for output DMA */
50#define EXYNOS_CIOCRSA4 (0x44)
51/* Target image format */
52#define EXYNOS_CITRGFMT (0x48)
53/* Output DMA control */
54#define EXYNOS_CIOCTRL (0x4c)
55/* Pre-scaler control 1 */
56#define EXYNOS_CISCPRERATIO (0x50)
57/* Pre-scaler control 2 */
58#define EXYNOS_CISCPREDST (0x54)
59/* Main scaler control */
60#define EXYNOS_CISCCTRL (0x58)
61/* Target area */
62#define EXYNOS_CITAREA (0x5c)
63/* Status */
64#define EXYNOS_CISTATUS (0x64)
65/* Status2 */
66#define EXYNOS_CISTATUS2 (0x68)
67/* Image capture enable command */
68#define EXYNOS_CIIMGCPT (0xc0)
69/* Capture sequence */
70#define EXYNOS_CICPTSEQ (0xc4)
71/* Image effects */
72#define EXYNOS_CIIMGEFF (0xd0)
73/* Y frame start address for input DMA */
74#define EXYNOS_CIIYSA0 (0xd4)
75/* Cb frame start address for input DMA */
76#define EXYNOS_CIICBSA0 (0xd8)
77/* Cr frame start address for input DMA */
78#define EXYNOS_CIICRSA0 (0xdc)
79/* Input DMA Y Line Skip */
80#define EXYNOS_CIILINESKIP_Y (0xec)
81/* Input DMA Cb Line Skip */
82#define EXYNOS_CIILINESKIP_CB (0xf0)
83/* Input DMA Cr Line Skip */
84#define EXYNOS_CIILINESKIP_CR (0xf4)
85/* Real input DMA image size */
86#define EXYNOS_CIREAL_ISIZE (0xf8)
87/* Input DMA control */
88#define EXYNOS_MSCTRL (0xfc)
89/* Y frame start address for input DMA */
90#define EXYNOS_CIIYSA1 (0x144)
91/* Cb frame start address for input DMA */
92#define EXYNOS_CIICBSA1 (0x148)
93/* Cr frame start address for input DMA */
94#define EXYNOS_CIICRSA1 (0x14c)
95/* Output DMA Y offset */
96#define EXYNOS_CIOYOFF (0x168)
97/* Output DMA CB offset */
98#define EXYNOS_CIOCBOFF (0x16c)
99/* Output DMA CR offset */
100#define EXYNOS_CIOCROFF (0x170)
101/* Input DMA Y offset */
102#define EXYNOS_CIIYOFF (0x174)
103/* Input DMA CB offset */
104#define EXYNOS_CIICBOFF (0x178)
105/* Input DMA CR offset */
106#define EXYNOS_CIICROFF (0x17c)
107/* Input DMA original image size */
108#define EXYNOS_ORGISIZE (0x180)
109/* Output DMA original image size */
110#define EXYNOS_ORGOSIZE (0x184)
111/* Real output DMA image size */
112#define EXYNOS_CIEXTEN (0x188)
113/* DMA parameter */
114#define EXYNOS_CIDMAPARAM (0x18c)
115/* MIPI CSI image format */
116#define EXYNOS_CSIIMGFMT (0x194)
117/* FIMC Clock Source Select */
118#define EXYNOS_MISC_FIMC (0x198)
119
120/* Add for FIMC v5.1 */
121/* Output Frame Buffer Sequence */
122#define EXYNOS_CIFCNTSEQ (0x1fc)
123/* Y 5th frame start address for output DMA */
124#define EXYNOS_CIOYSA5 (0x200)
125/* Y 6th frame start address for output DMA */
126#define EXYNOS_CIOYSA6 (0x204)
127/* Y 7th frame start address for output DMA */
128#define EXYNOS_CIOYSA7 (0x208)
129/* Y 8th frame start address for output DMA */
130#define EXYNOS_CIOYSA8 (0x20c)
131/* Y 9th frame start address for output DMA */
132#define EXYNOS_CIOYSA9 (0x210)
133/* Y 10th frame start address for output DMA */
134#define EXYNOS_CIOYSA10 (0x214)
135/* Y 11th frame start address for output DMA */
136#define EXYNOS_CIOYSA11 (0x218)
137/* Y 12th frame start address for output DMA */
138#define EXYNOS_CIOYSA12 (0x21c)
139/* Y 13th frame start address for output DMA */
140#define EXYNOS_CIOYSA13 (0x220)
141/* Y 14th frame start address for output DMA */
142#define EXYNOS_CIOYSA14 (0x224)
143/* Y 15th frame start address for output DMA */
144#define EXYNOS_CIOYSA15 (0x228)
145/* Y 16th frame start address for output DMA */
146#define EXYNOS_CIOYSA16 (0x22c)
147/* Y 17th frame start address for output DMA */
148#define EXYNOS_CIOYSA17 (0x230)
149/* Y 18th frame start address for output DMA */
150#define EXYNOS_CIOYSA18 (0x234)
151/* Y 19th frame start address for output DMA */
152#define EXYNOS_CIOYSA19 (0x238)
153/* Y 20th frame start address for output DMA */
154#define EXYNOS_CIOYSA20 (0x23c)
155/* Y 21th frame start address for output DMA */
156#define EXYNOS_CIOYSA21 (0x240)
157/* Y 22th frame start address for output DMA */
158#define EXYNOS_CIOYSA22 (0x244)
159/* Y 23th frame start address for output DMA */
160#define EXYNOS_CIOYSA23 (0x248)
161/* Y 24th frame start address for output DMA */
162#define EXYNOS_CIOYSA24 (0x24c)
163/* Y 25th frame start address for output DMA */
164#define EXYNOS_CIOYSA25 (0x250)
165/* Y 26th frame start address for output DMA */
166#define EXYNOS_CIOYSA26 (0x254)
167/* Y 27th frame start address for output DMA */
168#define EXYNOS_CIOYSA27 (0x258)
169/* Y 28th frame start address for output DMA */
170#define EXYNOS_CIOYSA28 (0x25c)
171/* Y 29th frame start address for output DMA */
172#define EXYNOS_CIOYSA29 (0x260)
173/* Y 30th frame start address for output DMA */
174#define EXYNOS_CIOYSA30 (0x264)
175/* Y 31th frame start address for output DMA */
176#define EXYNOS_CIOYSA31 (0x268)
177/* Y 32th frame start address for output DMA */
178#define EXYNOS_CIOYSA32 (0x26c)
179
180/* CB 5th frame start address for output DMA */
181#define EXYNOS_CIOCBSA5 (0x270)
182/* CB 6th frame start address for output DMA */
183#define EXYNOS_CIOCBSA6 (0x274)
184/* CB 7th frame start address for output DMA */
185#define EXYNOS_CIOCBSA7 (0x278)
186/* CB 8th frame start address for output DMA */
187#define EXYNOS_CIOCBSA8 (0x27c)
188/* CB 9th frame start address for output DMA */
189#define EXYNOS_CIOCBSA9 (0x280)
190/* CB 10th frame start address for output DMA */
191#define EXYNOS_CIOCBSA10 (0x284)
192/* CB 11th frame start address for output DMA */
193#define EXYNOS_CIOCBSA11 (0x288)
194/* CB 12th frame start address for output DMA */
195#define EXYNOS_CIOCBSA12 (0x28c)
196/* CB 13th frame start address for output DMA */
197#define EXYNOS_CIOCBSA13 (0x290)
198/* CB 14th frame start address for output DMA */
199#define EXYNOS_CIOCBSA14 (0x294)
200/* CB 15th frame start address for output DMA */
201#define EXYNOS_CIOCBSA15 (0x298)
202/* CB 16th frame start address for output DMA */
203#define EXYNOS_CIOCBSA16 (0x29c)
204/* CB 17th frame start address for output DMA */
205#define EXYNOS_CIOCBSA17 (0x2a0)
206/* CB 18th frame start address for output DMA */
207#define EXYNOS_CIOCBSA18 (0x2a4)
208/* CB 19th frame start address for output DMA */
209#define EXYNOS_CIOCBSA19 (0x2a8)
210/* CB 20th frame start address for output DMA */
211#define EXYNOS_CIOCBSA20 (0x2ac)
212/* CB 21th frame start address for output DMA */
213#define EXYNOS_CIOCBSA21 (0x2b0)
214/* CB 22th frame start address for output DMA */
215#define EXYNOS_CIOCBSA22 (0x2b4)
216/* CB 23th frame start address for output DMA */
217#define EXYNOS_CIOCBSA23 (0x2b8)
218/* CB 24th frame start address for output DMA */
219#define EXYNOS_CIOCBSA24 (0x2bc)
220/* CB 25th frame start address for output DMA */
221#define EXYNOS_CIOCBSA25 (0x2c0)
222/* CB 26th frame start address for output DMA */
223#define EXYNOS_CIOCBSA26 (0x2c4)
224/* CB 27th frame start address for output DMA */
225#define EXYNOS_CIOCBSA27 (0x2c8)
226/* CB 28th frame start address for output DMA */
227#define EXYNOS_CIOCBSA28 (0x2cc)
228/* CB 29th frame start address for output DMA */
229#define EXYNOS_CIOCBSA29 (0x2d0)
230/* CB 30th frame start address for output DMA */
231#define EXYNOS_CIOCBSA30 (0x2d4)
232/* CB 31th frame start address for output DMA */
233#define EXYNOS_CIOCBSA31 (0x2d8)
234/* CB 32th frame start address for output DMA */
235#define EXYNOS_CIOCBSA32 (0x2dc)
236
237/* CR 5th frame start address for output DMA */
238#define EXYNOS_CIOCRSA5 (0x2e0)
239/* CR 6th frame start address for output DMA */
240#define EXYNOS_CIOCRSA6 (0x2e4)
241/* CR 7th frame start address for output DMA */
242#define EXYNOS_CIOCRSA7 (0x2e8)
243/* CR 8th frame start address for output DMA */
244#define EXYNOS_CIOCRSA8 (0x2ec)
245/* CR 9th frame start address for output DMA */
246#define EXYNOS_CIOCRSA9 (0x2f0)
247/* CR 10th frame start address for output DMA */
248#define EXYNOS_CIOCRSA10 (0x2f4)
249/* CR 11th frame start address for output DMA */
250#define EXYNOS_CIOCRSA11 (0x2f8)
251/* CR 12th frame start address for output DMA */
252#define EXYNOS_CIOCRSA12 (0x2fc)
253/* CR 13th frame start address for output DMA */
254#define EXYNOS_CIOCRSA13 (0x300)
255/* CR 14th frame start address for output DMA */
256#define EXYNOS_CIOCRSA14 (0x304)
257/* CR 15th frame start address for output DMA */
258#define EXYNOS_CIOCRSA15 (0x308)
259/* CR 16th frame start address for output DMA */
260#define EXYNOS_CIOCRSA16 (0x30c)
261/* CR 17th frame start address for output DMA */
262#define EXYNOS_CIOCRSA17 (0x310)
263/* CR 18th frame start address for output DMA */
264#define EXYNOS_CIOCRSA18 (0x314)
265/* CR 19th frame start address for output DMA */
266#define EXYNOS_CIOCRSA19 (0x318)
267/* CR 20th frame start address for output DMA */
268#define EXYNOS_CIOCRSA20 (0x31c)
269/* CR 21th frame start address for output DMA */
270#define EXYNOS_CIOCRSA21 (0x320)
271/* CR 22th frame start address for output DMA */
272#define EXYNOS_CIOCRSA22 (0x324)
273/* CR 23th frame start address for output DMA */
274#define EXYNOS_CIOCRSA23 (0x328)
275/* CR 24th frame start address for output DMA */
276#define EXYNOS_CIOCRSA24 (0x32c)
277/* CR 25th frame start address for output DMA */
278#define EXYNOS_CIOCRSA25 (0x330)
279/* CR 26th frame start address for output DMA */
280#define EXYNOS_CIOCRSA26 (0x334)
281/* CR 27th frame start address for output DMA */
282#define EXYNOS_CIOCRSA27 (0x338)
283/* CR 28th frame start address for output DMA */
284#define EXYNOS_CIOCRSA28 (0x33c)
285/* CR 29th frame start address for output DMA */
286#define EXYNOS_CIOCRSA29 (0x340)
287/* CR 30th frame start address for output DMA */
288#define EXYNOS_CIOCRSA30 (0x344)
289/* CR 31th frame start address for output DMA */
290#define EXYNOS_CIOCRSA31 (0x348)
291/* CR 32th frame start address for output DMA */
292#define EXYNOS_CIOCRSA32 (0x34c)
293
294/*
295 * Macro part
296*/
297/* frame start address 1 ~ 4, 5 ~ 32 */
298/* Number of Default PingPong Memory */
299#define DEF_PP 4
300#define EXYNOS_CIOYSA(__x) \
301 (((__x) < DEF_PP) ? \
302 (EXYNOS_CIOYSA1 + (__x) * 4) : \
303 (EXYNOS_CIOYSA5 + ((__x) - DEF_PP) * 4))
304#define EXYNOS_CIOCBSA(__x) \
305 (((__x) < DEF_PP) ? \
306 (EXYNOS_CIOCBSA1 + (__x) * 4) : \
307 (EXYNOS_CIOCBSA5 + ((__x) - DEF_PP) * 4))
308#define EXYNOS_CIOCRSA(__x) \
309 (((__x) < DEF_PP) ? \
310 (EXYNOS_CIOCRSA1 + (__x) * 4) : \
311 (EXYNOS_CIOCRSA5 + ((__x) - DEF_PP) * 4))
312/* Number of Default PingPong Memory */
313#define DEF_IPP 1
314#define EXYNOS_CIIYSA(__x) \
315 (((__x) < DEF_IPP) ? \
316 (EXYNOS_CIIYSA0) : (EXYNOS_CIIYSA1))
317#define EXYNOS_CIICBSA(__x) \
318 (((__x) < DEF_IPP) ? \
319 (EXYNOS_CIICBSA0) : (EXYNOS_CIICBSA1))
320#define EXYNOS_CIICRSA(__x) \
321 (((__x) < DEF_IPP) ? \
322 (EXYNOS_CIICRSA0) : (EXYNOS_CIICRSA1))
323
324#define EXYNOS_CISRCFMT_SOURCEHSIZE(x) ((x) << 16)
325#define EXYNOS_CISRCFMT_SOURCEVSIZE(x) ((x) << 0)
326
327#define EXYNOS_CIWDOFST_WINHOROFST(x) ((x) << 16)
328#define EXYNOS_CIWDOFST_WINVEROFST(x) ((x) << 0)
329
330#define EXYNOS_CIWDOFST2_WINHOROFST2(x) ((x) << 16)
331#define EXYNOS_CIWDOFST2_WINVEROFST2(x) ((x) << 0)
332
333#define EXYNOS_CITRGFMT_TARGETHSIZE(x) (((x) & 0x1fff) << 16)
334#define EXYNOS_CITRGFMT_TARGETVSIZE(x) (((x) & 0x1fff) << 0)
335
336#define EXYNOS_CISCPRERATIO_SHFACTOR(x) ((x) << 28)
337#define EXYNOS_CISCPRERATIO_PREHORRATIO(x) ((x) << 16)
338#define EXYNOS_CISCPRERATIO_PREVERRATIO(x) ((x) << 0)
339
340#define EXYNOS_CISCPREDST_PREDSTWIDTH(x) ((x) << 16)
341#define EXYNOS_CISCPREDST_PREDSTHEIGHT(x) ((x) << 0)
342
343#define EXYNOS_CISCCTRL_MAINHORRATIO(x) ((x) << 16)
344#define EXYNOS_CISCCTRL_MAINVERRATIO(x) ((x) << 0)
345
346#define EXYNOS_CITAREA_TARGET_AREA(x) ((x) << 0)
347
348#define EXYNOS_CISTATUS_GET_FRAME_COUNT(x) (((x) >> 26) & 0x3)
349#define EXYNOS_CISTATUS_GET_FRAME_END(x) (((x) >> 17) & 0x1)
350#define EXYNOS_CISTATUS_GET_LAST_CAPTURE_END(x) (((x) >> 16) & 0x1)
351#define EXYNOS_CISTATUS_GET_LCD_STATUS(x) (((x) >> 9) & 0x1)
352#define EXYNOS_CISTATUS_GET_ENVID_STATUS(x) (((x) >> 8) & 0x1)
353
354#define EXYNOS_CISTATUS2_GET_FRAMECOUNT_BEFORE(x) (((x) >> 7) & 0x3f)
355#define EXYNOS_CISTATUS2_GET_FRAMECOUNT_PRESENT(x) ((x) & 0x3f)
356
357#define EXYNOS_CIIMGEFF_FIN(x) ((x & 0x7) << 26)
358#define EXYNOS_CIIMGEFF_PAT_CB(x) ((x) << 13)
359#define EXYNOS_CIIMGEFF_PAT_CR(x) ((x) << 0)
360
361#define EXYNOS_CIILINESKIP(x) (((x) & 0xf) << 24)
362
363#define EXYNOS_CIREAL_ISIZE_HEIGHT(x) ((x) << 16)
364#define EXYNOS_CIREAL_ISIZE_WIDTH(x) ((x) << 0)
365
366#define EXYNOS_MSCTRL_SUCCESSIVE_COUNT(x) ((x) << 24)
367#define EXYNOS_MSCTRL_GET_INDMA_STATUS(x) ((x) & 0x1)
368
369#define EXYNOS_CIOYOFF_VERTICAL(x) ((x) << 16)
370#define EXYNOS_CIOYOFF_HORIZONTAL(x) ((x) << 0)
371
372#define EXYNOS_CIOCBOFF_VERTICAL(x) ((x) << 16)
373#define EXYNOS_CIOCBOFF_HORIZONTAL(x) ((x) << 0)
374
375#define EXYNOS_CIOCROFF_VERTICAL(x) ((x) << 16)
376#define EXYNOS_CIOCROFF_HORIZONTAL(x) ((x) << 0)
377
378#define EXYNOS_CIIYOFF_VERTICAL(x) ((x) << 16)
379#define EXYNOS_CIIYOFF_HORIZONTAL(x) ((x) << 0)
380
381#define EXYNOS_CIICBOFF_VERTICAL(x) ((x) << 16)
382#define EXYNOS_CIICBOFF_HORIZONTAL(x) ((x) << 0)
383
384#define EXYNOS_CIICROFF_VERTICAL(x) ((x) << 16)
385#define EXYNOS_CIICROFF_HORIZONTAL(x) ((x) << 0)
386
387#define EXYNOS_ORGISIZE_VERTICAL(x) ((x) << 16)
388#define EXYNOS_ORGISIZE_HORIZONTAL(x) ((x) << 0)
389
390#define EXYNOS_ORGOSIZE_VERTICAL(x) ((x) << 16)
391#define EXYNOS_ORGOSIZE_HORIZONTAL(x) ((x) << 0)
392
393#define EXYNOS_CIEXTEN_TARGETH_EXT(x) ((((x) & 0x2000) >> 13) << 26)
394#define EXYNOS_CIEXTEN_TARGETV_EXT(x) ((((x) & 0x2000) >> 13) << 24)
395#define EXYNOS_CIEXTEN_MAINHORRATIO_EXT(x) (((x) & 0x3F) << 10)
396#define EXYNOS_CIEXTEN_MAINVERRATIO_EXT(x) ((x) & 0x3F)
397
398/*
399 * Bit definition part
400*/
401/* Source format register */
402#define EXYNOS_CISRCFMT_ITU601_8BIT (1 << 31)
403#define EXYNOS_CISRCFMT_ITU656_8BIT (0 << 31)
404#define EXYNOS_CISRCFMT_ITU601_16BIT (1 << 29)
405#define EXYNOS_CISRCFMT_ORDER422_YCBYCR (0 << 14)
406#define EXYNOS_CISRCFMT_ORDER422_YCRYCB (1 << 14)
407#define EXYNOS_CISRCFMT_ORDER422_CBYCRY (2 << 14)
408#define EXYNOS_CISRCFMT_ORDER422_CRYCBY (3 << 14)
409/* ITU601 16bit only */
410#define EXYNOS_CISRCFMT_ORDER422_Y4CBCRCBCR (0 << 14)
411/* ITU601 16bit only */
412#define EXYNOS_CISRCFMT_ORDER422_Y4CRCBCRCB (1 << 14)
413
414/* Window offset register */
415#define EXYNOS_CIWDOFST_WINOFSEN (1 << 31)
416#define EXYNOS_CIWDOFST_CLROVFIY (1 << 30)
417#define EXYNOS_CIWDOFST_CLROVRLB (1 << 29)
418#define EXYNOS_CIWDOFST_WINHOROFST_MASK (0x7ff << 16)
419#define EXYNOS_CIWDOFST_CLROVFICB (1 << 15)
420#define EXYNOS_CIWDOFST_CLROVFICR (1 << 14)
421#define EXYNOS_CIWDOFST_WINVEROFST_MASK (0xfff << 0)
422
423/* Global control register */
424#define EXYNOS_CIGCTRL_SWRST (1 << 31)
425#define EXYNOS_CIGCTRL_CAMRST_A (1 << 30)
426#define EXYNOS_CIGCTRL_SELCAM_ITU_B (0 << 29)
427#define EXYNOS_CIGCTRL_SELCAM_ITU_A (1 << 29)
428#define EXYNOS_CIGCTRL_SELCAM_ITU_MASK (1 << 29)
429#define EXYNOS_CIGCTRL_TESTPATTERN_NORMAL (0 << 27)
430#define EXYNOS_CIGCTRL_TESTPATTERN_COLOR_BAR (1 << 27)
431#define EXYNOS_CIGCTRL_TESTPATTERN_HOR_INC (2 << 27)
432#define EXYNOS_CIGCTRL_TESTPATTERN_VER_INC (3 << 27)
433#define EXYNOS_CIGCTRL_TESTPATTERN_MASK (3 << 27)
434#define EXYNOS_CIGCTRL_TESTPATTERN_SHIFT (27)
435#define EXYNOS_CIGCTRL_INVPOLPCLK (1 << 26)
436#define EXYNOS_CIGCTRL_INVPOLVSYNC (1 << 25)
437#define EXYNOS_CIGCTRL_INVPOLHREF (1 << 24)
438#define EXYNOS_CIGCTRL_IRQ_OVFEN (1 << 22)
439#define EXYNOS_CIGCTRL_HREF_MASK (1 << 21)
440#define EXYNOS_CIGCTRL_IRQ_EDGE (0 << 20)
441#define EXYNOS_CIGCTRL_IRQ_LEVEL (1 << 20)
442#define EXYNOS_CIGCTRL_IRQ_CLR (1 << 19)
443#define EXYNOS_CIGCTRL_IRQ_END_DISABLE (1 << 18)
444#define EXYNOS_CIGCTRL_IRQ_DISABLE (0 << 16)
445#define EXYNOS_CIGCTRL_IRQ_ENABLE (1 << 16)
446#define EXYNOS_CIGCTRL_SHADOW_DISABLE (1 << 12)
447#define EXYNOS_CIGCTRL_CAM_JPEG (1 << 8)
448#define EXYNOS_CIGCTRL_SELCAM_MIPI_B (0 << 7)
449#define EXYNOS_CIGCTRL_SELCAM_MIPI_A (1 << 7)
450#define EXYNOS_CIGCTRL_SELCAM_MIPI_MASK (1 << 7)
451#define EXYNOS_CIGCTRL_SELWB_CAMIF_CAMERA (0 << 6)
452#define EXYNOS_CIGCTRL_SELWB_CAMIF_WRITEBACK (1 << 6)
453#define EXYNOS_CIGCTRL_SELWRITEBACK_MASK (1 << 10)
454#define EXYNOS_CIGCTRL_SELWRITEBACK_A (1 << 10)
455#define EXYNOS_CIGCTRL_SELWRITEBACK_B (0 << 10)
456#define EXYNOS_CIGCTRL_SELWB_CAMIF_MASK (1 << 6)
457#define EXYNOS_CIGCTRL_CSC_ITU601 (0 << 5)
458#define EXYNOS_CIGCTRL_CSC_ITU709 (1 << 5)
459#define EXYNOS_CIGCTRL_CSC_MASK (1 << 5)
460#define EXYNOS_CIGCTRL_INVPOLHSYNC (1 << 4)
461#define EXYNOS_CIGCTRL_SELCAM_FIMC_ITU (0 << 3)
462#define EXYNOS_CIGCTRL_SELCAM_FIMC_MIPI (1 << 3)
463#define EXYNOS_CIGCTRL_SELCAM_FIMC_MASK (1 << 3)
464#define EXYNOS_CIGCTRL_PROGRESSIVE (0 << 0)
465#define EXYNOS_CIGCTRL_INTERLACE (1 << 0)
466
467/* Window offset2 register */
468#define EXYNOS_CIWDOFST_WINHOROFST2_MASK (0xfff << 16)
469#define EXYNOS_CIWDOFST_WINVEROFST2_MASK (0xfff << 16)
470
471/* Target format register */
472#define EXYNOS_CITRGFMT_INROT90_CLOCKWISE (1 << 31)
473#define EXYNOS_CITRGFMT_OUTFORMAT_YCBCR420 (0 << 29)
474#define EXYNOS_CITRGFMT_OUTFORMAT_YCBCR422 (1 << 29)
475#define EXYNOS_CITRGFMT_OUTFORMAT_YCBCR422_1PLANE (2 << 29)
476#define EXYNOS_CITRGFMT_OUTFORMAT_RGB (3 << 29)
477#define EXYNOS_CITRGFMT_OUTFORMAT_MASK (3 << 29)
478#define EXYNOS_CITRGFMT_FLIP_SHIFT (14)
479#define EXYNOS_CITRGFMT_FLIP_NORMAL (0 << 14)
480#define EXYNOS_CITRGFMT_FLIP_X_MIRROR (1 << 14)
481#define EXYNOS_CITRGFMT_FLIP_Y_MIRROR (2 << 14)
482#define EXYNOS_CITRGFMT_FLIP_180 (3 << 14)
483#define EXYNOS_CITRGFMT_FLIP_MASK (3 << 14)
484#define EXYNOS_CITRGFMT_OUTROT90_CLOCKWISE (1 << 13)
485#define EXYNOS_CITRGFMT_TARGETV_MASK (0x1fff << 0)
486#define EXYNOS_CITRGFMT_TARGETH_MASK (0x1fff << 16)
487
488/* Output DMA control register */
489#define EXYNOS_CIOCTRL_WEAVE_OUT (1 << 31)
490#define EXYNOS_CIOCTRL_WEAVE_MASK (1 << 31)
491#define EXYNOS_CIOCTRL_LASTENDEN (1 << 30)
492#define EXYNOS_CIOCTRL_ORDER2P_LSB_CBCR (0 << 24)
493#define EXYNOS_CIOCTRL_ORDER2P_LSB_CRCB (1 << 24)
494#define EXYNOS_CIOCTRL_ORDER2P_MSB_CRCB (2 << 24)
495#define EXYNOS_CIOCTRL_ORDER2P_MSB_CBCR (3 << 24)
496#define EXYNOS_CIOCTRL_ORDER2P_SHIFT (24)
497#define EXYNOS_CIOCTRL_ORDER2P_MASK (3 << 24)
498#define EXYNOS_CIOCTRL_YCBCR_3PLANE (0 << 3)
499#define EXYNOS_CIOCTRL_YCBCR_2PLANE (1 << 3)
500#define EXYNOS_CIOCTRL_YCBCR_PLANE_MASK (1 << 3)
501#define EXYNOS_CIOCTRL_LASTIRQ_ENABLE (1 << 2)
502#define EXYNOS_CIOCTRL_ALPHA_OUT (0xff << 4)
503#define EXYNOS_CIOCTRL_ORDER422_YCBYCR (0 << 0)
504#define EXYNOS_CIOCTRL_ORDER422_YCRYCB (1 << 0)
505#define EXYNOS_CIOCTRL_ORDER422_CBYCRY (2 << 0)
506#define EXYNOS_CIOCTRL_ORDER422_CRYCBY (3 << 0)
507#define EXYNOS_CIOCTRL_ORDER422_MASK (3 << 0)
508
509/* Main scaler control register */
510#define EXYNOS_CISCCTRL_SCALERBYPASS (1 << 31)
511#define EXYNOS_CISCCTRL_SCALEUP_H (1 << 30)
512#define EXYNOS_CISCCTRL_SCALEUP_V (1 << 29)
513#define EXYNOS_CISCCTRL_CSCR2Y_NARROW (0 << 28)
514#define EXYNOS_CISCCTRL_CSCR2Y_WIDE (1 << 28)
515#define EXYNOS_CISCCTRL_CSCY2R_NARROW (0 << 27)
516#define EXYNOS_CISCCTRL_CSCY2R_WIDE (1 << 27)
517#define EXYNOS_CISCCTRL_LCDPATHEN_FIFO (1 << 26)
518#define EXYNOS_CISCCTRL_PROGRESSIVE (0 << 25)
519#define EXYNOS_CISCCTRL_INTERLACE (1 << 25)
520#define EXYNOS_CISCCTRL_SCAN_MASK (1 << 25)
521#define EXYNOS_CISCCTRL_SCALERSTART (1 << 15)
522#define EXYNOS_CISCCTRL_INRGB_FMT_RGB565 (0 << 13)
523#define EXYNOS_CISCCTRL_INRGB_FMT_RGB666 (1 << 13)
524#define EXYNOS_CISCCTRL_INRGB_FMT_RGB888 (2 << 13)
525#define EXYNOS_CISCCTRL_INRGB_FMT_RGB_MASK (3 << 13)
526#define EXYNOS_CISCCTRL_OUTRGB_FMT_RGB565 (0 << 11)
527#define EXYNOS_CISCCTRL_OUTRGB_FMT_RGB666 (1 << 11)
528#define EXYNOS_CISCCTRL_OUTRGB_FMT_RGB888 (2 << 11)
529#define EXYNOS_CISCCTRL_OUTRGB_FMT_RGB_MASK (3 << 11)
530#define EXYNOS_CISCCTRL_EXTRGB_NORMAL (0 << 10)
531#define EXYNOS_CISCCTRL_EXTRGB_EXTENSION (1 << 10)
532#define EXYNOS_CISCCTRL_ONE2ONE (1 << 9)
533#define EXYNOS_CISCCTRL_MAIN_V_RATIO_MASK (0x1ff << 0)
534#define EXYNOS_CISCCTRL_MAIN_H_RATIO_MASK (0x1ff << 16)
535
536/* Status register */
537#define EXYNOS_CISTATUS_OVFIY (1 << 31)
538#define EXYNOS_CISTATUS_OVFICB (1 << 30)
539#define EXYNOS_CISTATUS_OVFICR (1 << 29)
540#define EXYNOS_CISTATUS_VSYNC (1 << 28)
541#define EXYNOS_CISTATUS_SCALERSTART (1 << 26)
542#define EXYNOS_CISTATUS_WINOFSTEN (1 << 25)
543#define EXYNOS_CISTATUS_IMGCPTEN (1 << 22)
544#define EXYNOS_CISTATUS_IMGCPTENSC (1 << 21)
545#define EXYNOS_CISTATUS_VSYNC_A (1 << 20)
546#define EXYNOS_CISTATUS_VSYNC_B (1 << 19)
547#define EXYNOS_CISTATUS_OVRLB (1 << 18)
548#define EXYNOS_CISTATUS_FRAMEEND (1 << 17)
549#define EXYNOS_CISTATUS_LASTCAPTUREEND (1 << 16)
550#define EXYNOS_CISTATUS_VVALID_A (1 << 15)
551#define EXYNOS_CISTATUS_VVALID_B (1 << 14)
552
553/* Image capture enable register */
554#define EXYNOS_CIIMGCPT_IMGCPTEN (1 << 31)
555#define EXYNOS_CIIMGCPT_IMGCPTEN_SC (1 << 30)
556#define EXYNOS_CIIMGCPT_CPT_FREN_ENABLE (1 << 25)
557#define EXYNOS_CIIMGCPT_CPT_FRMOD_EN (0 << 18)
558#define EXYNOS_CIIMGCPT_CPT_FRMOD_CNT (1 << 18)
559
560/* Image effects register */
561#define EXYNOS_CIIMGEFF_IE_DISABLE (0 << 30)
562#define EXYNOS_CIIMGEFF_IE_ENABLE (1 << 30)
563#define EXYNOS_CIIMGEFF_IE_SC_BEFORE (0 << 29)
564#define EXYNOS_CIIMGEFF_IE_SC_AFTER (1 << 29)
565#define EXYNOS_CIIMGEFF_FIN_BYPASS (0 << 26)
566#define EXYNOS_CIIMGEFF_FIN_ARBITRARY (1 << 26)
567#define EXYNOS_CIIMGEFF_FIN_NEGATIVE (2 << 26)
568#define EXYNOS_CIIMGEFF_FIN_ARTFREEZE (3 << 26)
569#define EXYNOS_CIIMGEFF_FIN_EMBOSSING (4 << 26)
570#define EXYNOS_CIIMGEFF_FIN_SILHOUETTE (5 << 26)
571#define EXYNOS_CIIMGEFF_FIN_MASK (7 << 26)
572#define EXYNOS_CIIMGEFF_PAT_CBCR_MASK ((0xff < 13) | (0xff < 0))
573
574/* Real input DMA size register */
575#define EXYNOS_CIREAL_ISIZE_AUTOLOAD_ENABLE (1 << 31)
576#define EXYNOS_CIREAL_ISIZE_ADDR_CH_DISABLE (1 << 30)
577#define EXYNOS_CIREAL_ISIZE_HEIGHT_MASK (0x3FFF << 16)
578#define EXYNOS_CIREAL_ISIZE_WIDTH_MASK (0x3FFF << 0)
579
580/* Input DMA control register */
581#define EXYNOS_MSCTRL_FIELD_MASK (1 << 31)
582#define EXYNOS_MSCTRL_FIELD_WEAVE (1 << 31)
583#define EXYNOS_MSCTRL_FIELD_NORMAL (0 << 31)
584#define EXYNOS_MSCTRL_BURST_CNT (24)
585#define EXYNOS_MSCTRL_BURST_CNT_MASK (0xf << 24)
586#define EXYNOS_MSCTRL_ORDER2P_LSB_CBCR (0 << 16)
587#define EXYNOS_MSCTRL_ORDER2P_LSB_CRCB (1 << 16)
588#define EXYNOS_MSCTRL_ORDER2P_MSB_CRCB (2 << 16)
589#define EXYNOS_MSCTRL_ORDER2P_MSB_CBCR (3 << 16)
590#define EXYNOS_MSCTRL_ORDER2P_SHIFT (16)
591#define EXYNOS_MSCTRL_ORDER2P_SHIFT_MASK (0x3 << 16)
592#define EXYNOS_MSCTRL_C_INT_IN_3PLANE (0 << 15)
593#define EXYNOS_MSCTRL_C_INT_IN_2PLANE (1 << 15)
594#define EXYNOS_MSCTRL_FLIP_SHIFT (13)
595#define EXYNOS_MSCTRL_FLIP_NORMAL (0 << 13)
596#define EXYNOS_MSCTRL_FLIP_X_MIRROR (1 << 13)
597#define EXYNOS_MSCTRL_FLIP_Y_MIRROR (2 << 13)
598#define EXYNOS_MSCTRL_FLIP_180 (3 << 13)
599#define EXYNOS_MSCTRL_FLIP_MASK (3 << 13)
600#define EXYNOS_MSCTRL_ORDER422_CRYCBY (0 << 4)
601#define EXYNOS_MSCTRL_ORDER422_YCRYCB (1 << 4)
602#define EXYNOS_MSCTRL_ORDER422_CBYCRY (2 << 4)
603#define EXYNOS_MSCTRL_ORDER422_YCBYCR (3 << 4)
604#define EXYNOS_MSCTRL_INPUT_EXTCAM (0 << 3)
605#define EXYNOS_MSCTRL_INPUT_MEMORY (1 << 3)
606#define EXYNOS_MSCTRL_INPUT_MASK (1 << 3)
607#define EXYNOS_MSCTRL_INFORMAT_YCBCR420 (0 << 1)
608#define EXYNOS_MSCTRL_INFORMAT_YCBCR422 (1 << 1)
609#define EXYNOS_MSCTRL_INFORMAT_YCBCR422_1PLANE (2 << 1)
610#define EXYNOS_MSCTRL_INFORMAT_RGB (3 << 1)
611#define EXYNOS_MSCTRL_ENVID (1 << 0)
612
613/* DMA parameter register */
614#define EXYNOS_CIDMAPARAM_R_MODE_LINEAR (0 << 29)
615#define EXYNOS_CIDMAPARAM_R_MODE_CONFTILE (1 << 29)
616#define EXYNOS_CIDMAPARAM_R_MODE_16X16 (2 << 29)
617#define EXYNOS_CIDMAPARAM_R_MODE_64X32 (3 << 29)
618#define EXYNOS_CIDMAPARAM_R_MODE_MASK (3 << 29)
619#define EXYNOS_CIDMAPARAM_R_TILE_HSIZE_64 (0 << 24)
620#define EXYNOS_CIDMAPARAM_R_TILE_HSIZE_128 (1 << 24)
621#define EXYNOS_CIDMAPARAM_R_TILE_HSIZE_256 (2 << 24)
622#define EXYNOS_CIDMAPARAM_R_TILE_HSIZE_512 (3 << 24)
623#define EXYNOS_CIDMAPARAM_R_TILE_HSIZE_1024 (4 << 24)
624#define EXYNOS_CIDMAPARAM_R_TILE_HSIZE_2048 (5 << 24)
625#define EXYNOS_CIDMAPARAM_R_TILE_HSIZE_4096 (6 << 24)
626#define EXYNOS_CIDMAPARAM_R_TILE_VSIZE_1 (0 << 20)
627#define EXYNOS_CIDMAPARAM_R_TILE_VSIZE_2 (1 << 20)
628#define EXYNOS_CIDMAPARAM_R_TILE_VSIZE_4 (2 << 20)
629#define EXYNOS_CIDMAPARAM_R_TILE_VSIZE_8 (3 << 20)
630#define EXYNOS_CIDMAPARAM_R_TILE_VSIZE_16 (4 << 20)
631#define EXYNOS_CIDMAPARAM_R_TILE_VSIZE_32 (5 << 20)
632#define EXYNOS_CIDMAPARAM_W_MODE_LINEAR (0 << 13)
633#define EXYNOS_CIDMAPARAM_W_MODE_CONFTILE (1 << 13)
634#define EXYNOS_CIDMAPARAM_W_MODE_16X16 (2 << 13)
635#define EXYNOS_CIDMAPARAM_W_MODE_64X32 (3 << 13)
636#define EXYNOS_CIDMAPARAM_W_MODE_MASK (3 << 13)
637#define EXYNOS_CIDMAPARAM_W_TILE_HSIZE_64 (0 << 8)
638#define EXYNOS_CIDMAPARAM_W_TILE_HSIZE_128 (1 << 8)
639#define EXYNOS_CIDMAPARAM_W_TILE_HSIZE_256 (2 << 8)
640#define EXYNOS_CIDMAPARAM_W_TILE_HSIZE_512 (3 << 8)
641#define EXYNOS_CIDMAPARAM_W_TILE_HSIZE_1024 (4 << 8)
642#define EXYNOS_CIDMAPARAM_W_TILE_HSIZE_2048 (5 << 8)
643#define EXYNOS_CIDMAPARAM_W_TILE_HSIZE_4096 (6 << 8)
644#define EXYNOS_CIDMAPARAM_W_TILE_VSIZE_1 (0 << 4)
645#define EXYNOS_CIDMAPARAM_W_TILE_VSIZE_2 (1 << 4)
646#define EXYNOS_CIDMAPARAM_W_TILE_VSIZE_4 (2 << 4)
647#define EXYNOS_CIDMAPARAM_W_TILE_VSIZE_8 (3 << 4)
648#define EXYNOS_CIDMAPARAM_W_TILE_VSIZE_16 (4 << 4)
649#define EXYNOS_CIDMAPARAM_W_TILE_VSIZE_32 (5 << 4)
650
651/* Gathering Extension register */
652#define EXYNOS_CIEXTEN_TARGETH_EXT_MASK (1 << 26)
653#define EXYNOS_CIEXTEN_TARGETV_EXT_MASK (1 << 24)
654#define EXYNOS_CIEXTEN_MAINHORRATIO_EXT_MASK (0x3F << 10)
655#define EXYNOS_CIEXTEN_MAINVERRATIO_EXT_MASK (0x3F)
656#define EXYNOS_CIEXTEN_YUV444_OUT (1 << 22)
657
658/* FIMC Clock Source Select register */
659#define EXYNOS_CLKSRC_HCLK (0 << 1)
660#define EXYNOS_CLKSRC_HCLK_MASK (1 << 1)
661#define EXYNOS_CLKSRC_SCLK (1 << 1)
662
663/* SYSREG for FIMC writeback */
664#define SYSREG_CAMERA_BLK (S3C_VA_SYS + 0x0218)
665#define SYSREG_ISP_BLK (S3C_VA_SYS + 0x020c)
666#define SYSREG_FIMD0WB_DEST_MASK (0x3 << 23)
667#define SYSREG_FIMD0WB_DEST_SHIFT 23
668
669#endif /* EXYNOS_REGS_FIMC_H */
diff --git a/include/drm/exynos_drm.h b/include/drm/exynos_drm.h
index 3c13a3a4b158..808dad29607a 100644
--- a/include/drm/exynos_drm.h
+++ b/include/drm/exynos_drm.h
@@ -85,4 +85,30 @@ struct exynos_drm_hdmi_pdata {
85 int (*get_hpd)(void); 85 int (*get_hpd)(void);
86}; 86};
87 87
88/**
89 * Platform Specific Structure for DRM based IPP.
90 *
91 * @inv_pclk: if set 1. invert pixel clock
92 * @inv_vsync: if set 1. invert vsync signal for wb
93 * @inv_href: if set 1. invert href signal
94 * @inv_hsync: if set 1. invert hsync signal for wb
95 */
96struct exynos_drm_ipp_pol {
97 unsigned int inv_pclk;
98 unsigned int inv_vsync;
99 unsigned int inv_href;
100 unsigned int inv_hsync;
101};
102
103/**
104 * Platform Specific Structure for DRM based FIMC.
105 *
106 * @pol: current hardware block polarity settings.
107 * @clk_rate: current hardware clock rate.
108 */
109struct exynos_drm_fimc_pdata {
110 struct exynos_drm_ipp_pol pol;
111 int clk_rate;
112};
113
88#endif /* _EXYNOS_DRM_H_ */ 114#endif /* _EXYNOS_DRM_H_ */