aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/gpu/drm/exynos/Kconfig2
-rw-r--r--drivers/gpu/drm/exynos/exynos_drm_drv.c8
-rw-r--r--drivers/gpu/drm/exynos/exynos_drm_drv.h9
-rw-r--r--drivers/gpu/drm/exynos/exynos_drm_fimc.c1080
-rw-r--r--drivers/gpu/drm/exynos/exynos_drm_fimc.h23
5 files changed, 366 insertions, 756 deletions
diff --git a/drivers/gpu/drm/exynos/Kconfig b/drivers/gpu/drm/exynos/Kconfig
index 5c216548ea18..54f5703b37e8 100644
--- a/drivers/gpu/drm/exynos/Kconfig
+++ b/drivers/gpu/drm/exynos/Kconfig
@@ -100,7 +100,7 @@ config DRM_EXYNOS_IPP
100 100
101config DRM_EXYNOS_FIMC 101config DRM_EXYNOS_FIMC
102 bool "FIMC" 102 bool "FIMC"
103 depends on BROKEN && MFD_SYSCON 103 select DRM_EXYNOS_IPP
104 help 104 help
105 Choose this option if you want to use Exynos FIMC for DRM. 105 Choose this option if you want to use Exynos FIMC for DRM.
106 106
diff --git a/drivers/gpu/drm/exynos/exynos_drm_drv.c b/drivers/gpu/drm/exynos/exynos_drm_drv.c
index 2dcb94034716..7ba13c122d14 100644
--- a/drivers/gpu/drm/exynos/exynos_drm_drv.c
+++ b/drivers/gpu/drm/exynos/exynos_drm_drv.c
@@ -222,6 +222,7 @@ struct exynos_drm_driver_info {
222#define DRM_COMPONENT_DRIVER BIT(0) /* supports component framework */ 222#define DRM_COMPONENT_DRIVER BIT(0) /* supports component framework */
223#define DRM_VIRTUAL_DEVICE BIT(1) /* create virtual platform device */ 223#define DRM_VIRTUAL_DEVICE BIT(1) /* create virtual platform device */
224#define DRM_DMA_DEVICE BIT(2) /* can be used for dma allocations */ 224#define DRM_DMA_DEVICE BIT(2) /* can be used for dma allocations */
225#define DRM_FIMC_DEVICE BIT(3) /* devices shared with V4L2 subsystem */
225 226
226#define DRV_PTR(drv, cond) (IS_ENABLED(cond) ? &drv : NULL) 227#define DRV_PTR(drv, cond) (IS_ENABLED(cond) ? &drv : NULL)
227 228
@@ -261,6 +262,7 @@ static struct exynos_drm_driver_info exynos_drm_drivers[] = {
261 DRV_PTR(g2d_driver, CONFIG_DRM_EXYNOS_G2D), 262 DRV_PTR(g2d_driver, CONFIG_DRM_EXYNOS_G2D),
262 }, { 263 }, {
263 DRV_PTR(fimc_driver, CONFIG_DRM_EXYNOS_FIMC), 264 DRV_PTR(fimc_driver, CONFIG_DRM_EXYNOS_FIMC),
265 DRM_COMPONENT_DRIVER | DRM_FIMC_DEVICE,
264 }, { 266 }, {
265 DRV_PTR(rotator_driver, CONFIG_DRM_EXYNOS_ROTATOR), 267 DRV_PTR(rotator_driver, CONFIG_DRM_EXYNOS_ROTATOR),
266 DRM_COMPONENT_DRIVER 268 DRM_COMPONENT_DRIVER
@@ -294,7 +296,11 @@ static struct component_match *exynos_drm_match_add(struct device *dev)
294 &info->driver->driver, 296 &info->driver->driver,
295 (void *)platform_bus_type.match))) { 297 (void *)platform_bus_type.match))) {
296 put_device(p); 298 put_device(p);
297 component_match_add(dev, &match, compare_dev, d); 299
300 if (!(info->flags & DRM_FIMC_DEVICE) ||
301 exynos_drm_check_fimc_device(d) == 0)
302 component_match_add(dev, &match,
303 compare_dev, d);
298 p = d; 304 p = d;
299 } 305 }
300 put_device(p); 306 put_device(p);
diff --git a/drivers/gpu/drm/exynos/exynos_drm_drv.h b/drivers/gpu/drm/exynos/exynos_drm_drv.h
index df2262f70d91..0834e7e28c99 100644
--- a/drivers/gpu/drm/exynos/exynos_drm_drv.h
+++ b/drivers/gpu/drm/exynos/exynos_drm_drv.h
@@ -273,6 +273,15 @@ static inline int exynos_dpi_bind(struct drm_device *dev,
273} 273}
274#endif 274#endif
275 275
276#ifdef CONFIG_DRM_EXYNOS_FIMC
277int exynos_drm_check_fimc_device(struct device *dev);
278#else
279static inline int exynos_drm_check_fimc_device(struct device *dev)
280{
281 return 0;
282}
283#endif
284
276int exynos_atomic_commit(struct drm_device *dev, struct drm_atomic_state *state, 285int exynos_atomic_commit(struct drm_device *dev, struct drm_atomic_state *state,
277 bool nonblock); 286 bool nonblock);
278int exynos_atomic_check(struct drm_device *dev, struct drm_atomic_state *state); 287int exynos_atomic_check(struct drm_device *dev, struct drm_atomic_state *state);
diff --git a/drivers/gpu/drm/exynos/exynos_drm_fimc.c b/drivers/gpu/drm/exynos/exynos_drm_fimc.c
index 5b18b5c5fdf2..4dfbfc7f3b84 100644
--- a/drivers/gpu/drm/exynos/exynos_drm_fimc.c
+++ b/drivers/gpu/drm/exynos/exynos_drm_fimc.c
@@ -12,6 +12,7 @@
12 * 12 *
13 */ 13 */
14#include <linux/kernel.h> 14#include <linux/kernel.h>
15#include <linux/component.h>
15#include <linux/platform_device.h> 16#include <linux/platform_device.h>
16#include <linux/mfd/syscon.h> 17#include <linux/mfd/syscon.h>
17#include <linux/regmap.h> 18#include <linux/regmap.h>
@@ -24,8 +25,8 @@
24#include <drm/exynos_drm.h> 25#include <drm/exynos_drm.h>
25#include "regs-fimc.h" 26#include "regs-fimc.h"
26#include "exynos_drm_drv.h" 27#include "exynos_drm_drv.h"
28#include "exynos_drm_iommu.h"
27#include "exynos_drm_ipp.h" 29#include "exynos_drm_ipp.h"
28#include "exynos_drm_fimc.h"
29 30
30/* 31/*
31 * FIMC stands for Fully Interactive Mobile Camera and 32 * FIMC stands for Fully Interactive Mobile Camera and
@@ -33,23 +34,6 @@
33 * input DMA reads image data from the memory. 34 * input DMA reads image data from the memory.
34 * output DMA writes image data to memory. 35 * output DMA writes image data to memory.
35 * FIMC supports image rotation and image effect functions. 36 * FIMC supports image rotation and image effect functions.
36 *
37 * M2M operation : supports crop/scale/rotation/csc so on.
38 * Memory ----> FIMC H/W ----> Memory.
39 * Writeback operation : supports cloned screen with FIMD.
40 * FIMD ----> FIMC H/W ----> Memory.
41 * Output operation : supports direct display using local path.
42 * Memory ----> FIMC H/W ----> FIMD.
43 */
44
45/*
46 * TODO
47 * 1. check suspend/resume api if needed.
48 * 2. need to check use case platform_device_id.
49 * 3. check src/dst size with, height.
50 * 4. added check_prepare api for right register.
51 * 5. need to add supported list in prop_list.
52 * 6. check prescaler/scaler optimization.
53 */ 37 */
54 38
55#define FIMC_MAX_DEVS 4 39#define FIMC_MAX_DEVS 4
@@ -59,29 +43,19 @@
59#define FIMC_BUF_STOP 1 43#define FIMC_BUF_STOP 1
60#define FIMC_BUF_START 2 44#define FIMC_BUF_START 2
61#define FIMC_WIDTH_ITU_709 1280 45#define FIMC_WIDTH_ITU_709 1280
62#define FIMC_REFRESH_MAX 60 46#define FIMC_AUTOSUSPEND_DELAY 2000
63#define FIMC_REFRESH_MIN 12 47
64#define FIMC_CROP_MAX 8192 48static unsigned int fimc_mask = 0xc;
65#define FIMC_CROP_MIN 32 49module_param_named(fimc_devs, fimc_mask, uint, 0644);
66#define FIMC_SCALE_MAX 4224 50MODULE_PARM_DESC(fimc_devs, "Alias mask for assigning FIMC devices to Exynos DRM");
67#define FIMC_SCALE_MIN 32
68 51
69#define get_fimc_context(dev) platform_get_drvdata(to_platform_device(dev)) 52#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);
72enum fimc_wb {
73 FIMC_WB_NONE,
74 FIMC_WB_A,
75 FIMC_WB_B,
76};
77 53
78enum { 54enum {
79 FIMC_CLK_LCLK, 55 FIMC_CLK_LCLK,
80 FIMC_CLK_GATE, 56 FIMC_CLK_GATE,
81 FIMC_CLK_WB_A, 57 FIMC_CLK_WB_A,
82 FIMC_CLK_WB_B, 58 FIMC_CLK_WB_B,
83 FIMC_CLK_MUX,
84 FIMC_CLK_PARENT,
85 FIMC_CLKS_MAX 59 FIMC_CLKS_MAX
86}; 60};
87 61
@@ -90,12 +64,8 @@ static const char * const fimc_clock_names[] = {
90 [FIMC_CLK_GATE] = "fimc", 64 [FIMC_CLK_GATE] = "fimc",
91 [FIMC_CLK_WB_A] = "pxl_async0", 65 [FIMC_CLK_WB_A] = "pxl_async0",
92 [FIMC_CLK_WB_B] = "pxl_async1", 66 [FIMC_CLK_WB_B] = "pxl_async1",
93 [FIMC_CLK_MUX] = "mux",
94 [FIMC_CLK_PARENT] = "parent",
95}; 67};
96 68
97#define FIMC_DEFAULT_LCLK_FREQUENCY 133000000UL
98
99/* 69/*
100 * A structure of scaler. 70 * A structure of scaler.
101 * 71 *
@@ -107,7 +77,7 @@ static const char * const fimc_clock_names[] = {
107 * @vratio: vertical ratio. 77 * @vratio: vertical ratio.
108 */ 78 */
109struct fimc_scaler { 79struct fimc_scaler {
110 bool range; 80 bool range;
111 bool bypass; 81 bool bypass;
112 bool up_h; 82 bool up_h;
113 bool up_v; 83 bool up_v;
@@ -116,56 +86,32 @@ struct fimc_scaler {
116}; 86};
117 87
118/* 88/*
119 * A structure of scaler capability.
120 *
121 * find user manual table 43-1.
122 * @in_hori: scaler input horizontal size.
123 * @bypass: scaler bypass mode.
124 * @dst_h_wo_rot: target horizontal size without output rotation.
125 * @dst_h_rot: target horizontal size with output rotation.
126 * @rl_w_wo_rot: real width without input rotation.
127 * @rl_h_rot: real height without output rotation.
128 */
129struct fimc_capability {
130 /* scaler */
131 u32 in_hori;
132 u32 bypass;
133 /* output rotator */
134 u32 dst_h_wo_rot;
135 u32 dst_h_rot;
136 /* input rotator */
137 u32 rl_w_wo_rot;
138 u32 rl_h_rot;
139};
140
141/*
142 * A structure of fimc context. 89 * A structure of fimc context.
143 * 90 *
144 * @ippdrv: prepare initialization using ippdrv.
145 * @regs_res: register resources. 91 * @regs_res: register resources.
146 * @regs: memory mapped io registers. 92 * @regs: memory mapped io registers.
147 * @lock: locking of operations. 93 * @lock: locking of operations.
148 * @clocks: fimc clocks. 94 * @clocks: fimc clocks.
149 * @clk_frequency: LCLK clock frequency.
150 * @sysreg: handle to SYSREG block regmap.
151 * @sc: scaler infomations. 95 * @sc: scaler infomations.
152 * @pol: porarity of writeback. 96 * @pol: porarity of writeback.
153 * @id: fimc id. 97 * @id: fimc id.
154 * @irq: irq number. 98 * @irq: irq number.
155 * @suspended: qos operations.
156 */ 99 */
157struct fimc_context { 100struct fimc_context {
158 struct exynos_drm_ippdrv ippdrv; 101 struct exynos_drm_ipp ipp;
102 struct drm_device *drm_dev;
103 struct device *dev;
104 struct exynos_drm_ipp_task *task;
105 struct exynos_drm_ipp_formats *formats;
106 unsigned int num_formats;
107
159 struct resource *regs_res; 108 struct resource *regs_res;
160 void __iomem *regs; 109 void __iomem *regs;
161 spinlock_t lock; 110 spinlock_t lock;
162 struct clk *clocks[FIMC_CLKS_MAX]; 111 struct clk *clocks[FIMC_CLKS_MAX];
163 u32 clk_frequency;
164 struct regmap *sysreg;
165 struct fimc_scaler sc; 112 struct fimc_scaler sc;
166 int id; 113 int id;
167 int irq; 114 int irq;
168 bool suspended;
169}; 115};
170 116
171static u32 fimc_read(struct fimc_context *ctx, u32 reg) 117static u32 fimc_read(struct fimc_context *ctx, u32 reg)
@@ -217,19 +163,10 @@ static void fimc_sw_reset(struct fimc_context *ctx)
217 fimc_write(ctx, 0x0, EXYNOS_CIFCNTSEQ); 163 fimc_write(ctx, 0x0, EXYNOS_CIFCNTSEQ);
218} 164}
219 165
220static int fimc_set_camblk_fimd0_wb(struct fimc_context *ctx) 166static void fimc_set_type_ctrl(struct fimc_context *ctx)
221{
222 return regmap_update_bits(ctx->sysreg, SYSREG_CAMERA_BLK,
223 SYSREG_FIMD0WB_DEST_MASK,
224 ctx->id << SYSREG_FIMD0WB_DEST_SHIFT);
225}
226
227static void fimc_set_type_ctrl(struct fimc_context *ctx, enum fimc_wb wb)
228{ 167{
229 u32 cfg; 168 u32 cfg;
230 169
231 DRM_DEBUG_KMS("wb[%d]\n", wb);
232
233 cfg = fimc_read(ctx, EXYNOS_CIGCTRL); 170 cfg = fimc_read(ctx, EXYNOS_CIGCTRL);
234 cfg &= ~(EXYNOS_CIGCTRL_TESTPATTERN_MASK | 171 cfg &= ~(EXYNOS_CIGCTRL_TESTPATTERN_MASK |
235 EXYNOS_CIGCTRL_SELCAM_ITU_MASK | 172 EXYNOS_CIGCTRL_SELCAM_ITU_MASK |
@@ -238,23 +175,10 @@ static void fimc_set_type_ctrl(struct fimc_context *ctx, enum fimc_wb wb)
238 EXYNOS_CIGCTRL_SELWB_CAMIF_MASK | 175 EXYNOS_CIGCTRL_SELWB_CAMIF_MASK |
239 EXYNOS_CIGCTRL_SELWRITEBACK_MASK); 176 EXYNOS_CIGCTRL_SELWRITEBACK_MASK);
240 177
241 switch (wb) { 178 cfg |= (EXYNOS_CIGCTRL_SELCAM_ITU_A |
242 case FIMC_WB_A: 179 EXYNOS_CIGCTRL_SELWRITEBACK_A |
243 cfg |= (EXYNOS_CIGCTRL_SELWRITEBACK_A | 180 EXYNOS_CIGCTRL_SELCAM_MIPI_A |
244 EXYNOS_CIGCTRL_SELWB_CAMIF_WRITEBACK); 181 EXYNOS_CIGCTRL_SELCAM_FIMC_ITU);
245 break;
246 case FIMC_WB_B:
247 cfg |= (EXYNOS_CIGCTRL_SELWRITEBACK_B |
248 EXYNOS_CIGCTRL_SELWB_CAMIF_WRITEBACK);
249 break;
250 case FIMC_WB_NONE:
251 default:
252 cfg |= (EXYNOS_CIGCTRL_SELCAM_ITU_A |
253 EXYNOS_CIGCTRL_SELWRITEBACK_A |
254 EXYNOS_CIGCTRL_SELCAM_MIPI_A |
255 EXYNOS_CIGCTRL_SELCAM_FIMC_ITU);
256 break;
257 }
258 182
259 fimc_write(ctx, cfg, EXYNOS_CIGCTRL); 183 fimc_write(ctx, cfg, EXYNOS_CIGCTRL);
260} 184}
@@ -296,7 +220,6 @@ static void fimc_clear_irq(struct fimc_context *ctx)
296 220
297static bool fimc_check_ovf(struct fimc_context *ctx) 221static bool fimc_check_ovf(struct fimc_context *ctx)
298{ 222{
299 struct exynos_drm_ippdrv *ippdrv = &ctx->ippdrv;
300 u32 status, flag; 223 u32 status, flag;
301 224
302 status = fimc_read(ctx, EXYNOS_CISTATUS); 225 status = fimc_read(ctx, EXYNOS_CISTATUS);
@@ -310,7 +233,7 @@ static bool fimc_check_ovf(struct fimc_context *ctx)
310 EXYNOS_CIWDOFST_CLROVFIY | EXYNOS_CIWDOFST_CLROVFICB | 233 EXYNOS_CIWDOFST_CLROVFIY | EXYNOS_CIWDOFST_CLROVFICB |
311 EXYNOS_CIWDOFST_CLROVFICR); 234 EXYNOS_CIWDOFST_CLROVFICR);
312 235
313 dev_err(ippdrv->dev, "occurred overflow at %d, status 0x%x.\n", 236 dev_err(ctx->dev, "occurred overflow at %d, status 0x%x.\n",
314 ctx->id, status); 237 ctx->id, status);
315 return true; 238 return true;
316 } 239 }
@@ -376,10 +299,8 @@ static void fimc_handle_lastend(struct fimc_context *ctx, bool enable)
376 fimc_write(ctx, cfg, EXYNOS_CIOCTRL); 299 fimc_write(ctx, cfg, EXYNOS_CIOCTRL);
377} 300}
378 301
379 302static void fimc_src_set_fmt_order(struct fimc_context *ctx, u32 fmt)
380static int fimc_src_set_fmt_order(struct fimc_context *ctx, u32 fmt)
381{ 303{
382 struct exynos_drm_ippdrv *ippdrv = &ctx->ippdrv;
383 u32 cfg; 304 u32 cfg;
384 305
385 DRM_DEBUG_KMS("fmt[0x%x]\n", fmt); 306 DRM_DEBUG_KMS("fmt[0x%x]\n", fmt);
@@ -392,12 +313,12 @@ static int fimc_src_set_fmt_order(struct fimc_context *ctx, u32 fmt)
392 case DRM_FORMAT_RGB565: 313 case DRM_FORMAT_RGB565:
393 cfg |= EXYNOS_CISCCTRL_INRGB_FMT_RGB565; 314 cfg |= EXYNOS_CISCCTRL_INRGB_FMT_RGB565;
394 fimc_write(ctx, cfg, EXYNOS_CISCCTRL); 315 fimc_write(ctx, cfg, EXYNOS_CISCCTRL);
395 return 0; 316 return;
396 case DRM_FORMAT_RGB888: 317 case DRM_FORMAT_RGB888:
397 case DRM_FORMAT_XRGB8888: 318 case DRM_FORMAT_XRGB8888:
398 cfg |= EXYNOS_CISCCTRL_INRGB_FMT_RGB888; 319 cfg |= EXYNOS_CISCCTRL_INRGB_FMT_RGB888;
399 fimc_write(ctx, cfg, EXYNOS_CISCCTRL); 320 fimc_write(ctx, cfg, EXYNOS_CISCCTRL);
400 return 0; 321 return;
401 default: 322 default:
402 /* bypass */ 323 /* bypass */
403 break; 324 break;
@@ -438,20 +359,13 @@ static int fimc_src_set_fmt_order(struct fimc_context *ctx, u32 fmt)
438 cfg |= (EXYNOS_MSCTRL_ORDER2P_LSB_CBCR | 359 cfg |= (EXYNOS_MSCTRL_ORDER2P_LSB_CBCR |
439 EXYNOS_MSCTRL_C_INT_IN_2PLANE); 360 EXYNOS_MSCTRL_C_INT_IN_2PLANE);
440 break; 361 break;
441 default:
442 dev_err(ippdrv->dev, "invalid source yuv order 0x%x.\n", fmt);
443 return -EINVAL;
444 } 362 }
445 363
446 fimc_write(ctx, cfg, EXYNOS_MSCTRL); 364 fimc_write(ctx, cfg, EXYNOS_MSCTRL);
447
448 return 0;
449} 365}
450 366
451static int fimc_src_set_fmt(struct device *dev, u32 fmt) 367static void fimc_src_set_fmt(struct fimc_context *ctx, u32 fmt, bool tiled)
452{ 368{
453 struct fimc_context *ctx = get_fimc_context(dev);
454 struct exynos_drm_ippdrv *ippdrv = &ctx->ippdrv;
455 u32 cfg; 369 u32 cfg;
456 370
457 DRM_DEBUG_KMS("fmt[0x%x]\n", fmt); 371 DRM_DEBUG_KMS("fmt[0x%x]\n", fmt);
@@ -485,9 +399,6 @@ static int fimc_src_set_fmt(struct device *dev, u32 fmt)
485 case DRM_FORMAT_NV21: 399 case DRM_FORMAT_NV21:
486 cfg |= EXYNOS_MSCTRL_INFORMAT_YCBCR420; 400 cfg |= EXYNOS_MSCTRL_INFORMAT_YCBCR420;
487 break; 401 break;
488 default:
489 dev_err(ippdrv->dev, "invalid source format 0x%x.\n", fmt);
490 return -EINVAL;
491 } 402 }
492 403
493 fimc_write(ctx, cfg, EXYNOS_MSCTRL); 404 fimc_write(ctx, cfg, EXYNOS_MSCTRL);
@@ -495,22 +406,22 @@ static int fimc_src_set_fmt(struct device *dev, u32 fmt)
495 cfg = fimc_read(ctx, EXYNOS_CIDMAPARAM); 406 cfg = fimc_read(ctx, EXYNOS_CIDMAPARAM);
496 cfg &= ~EXYNOS_CIDMAPARAM_R_MODE_MASK; 407 cfg &= ~EXYNOS_CIDMAPARAM_R_MODE_MASK;
497 408
498 cfg |= EXYNOS_CIDMAPARAM_R_MODE_LINEAR; 409 if (tiled)
410 cfg |= EXYNOS_CIDMAPARAM_R_MODE_64X32;
411 else
412 cfg |= EXYNOS_CIDMAPARAM_R_MODE_LINEAR;
499 413
500 fimc_write(ctx, cfg, EXYNOS_CIDMAPARAM); 414 fimc_write(ctx, cfg, EXYNOS_CIDMAPARAM);
501 415
502 return fimc_src_set_fmt_order(ctx, fmt); 416 fimc_src_set_fmt_order(ctx, fmt);
503} 417}
504 418
505static int fimc_src_set_transf(struct device *dev, 419static void fimc_src_set_transf(struct fimc_context *ctx, unsigned int rotation)
506 enum drm_exynos_degree degree,
507 enum drm_exynos_flip flip, bool *swap)
508{ 420{
509 struct fimc_context *ctx = get_fimc_context(dev); 421 unsigned int degree = rotation & DRM_MODE_ROTATE_MASK;
510 struct exynos_drm_ippdrv *ippdrv = &ctx->ippdrv;
511 u32 cfg1, cfg2; 422 u32 cfg1, cfg2;
512 423
513 DRM_DEBUG_KMS("degree[%d]flip[0x%x]\n", degree, flip); 424 DRM_DEBUG_KMS("rotation[%x]\n", rotation);
514 425
515 cfg1 = fimc_read(ctx, EXYNOS_MSCTRL); 426 cfg1 = fimc_read(ctx, EXYNOS_MSCTRL);
516 cfg1 &= ~(EXYNOS_MSCTRL_FLIP_X_MIRROR | 427 cfg1 &= ~(EXYNOS_MSCTRL_FLIP_X_MIRROR |
@@ -520,61 +431,56 @@ static int fimc_src_set_transf(struct device *dev,
520 cfg2 &= ~EXYNOS_CITRGFMT_INROT90_CLOCKWISE; 431 cfg2 &= ~EXYNOS_CITRGFMT_INROT90_CLOCKWISE;
521 432
522 switch (degree) { 433 switch (degree) {
523 case EXYNOS_DRM_DEGREE_0: 434 case DRM_MODE_ROTATE_0:
524 if (flip & EXYNOS_DRM_FLIP_VERTICAL) 435 if (rotation & DRM_MODE_REFLECT_X)
525 cfg1 |= EXYNOS_MSCTRL_FLIP_X_MIRROR; 436 cfg1 |= EXYNOS_MSCTRL_FLIP_X_MIRROR;
526 if (flip & EXYNOS_DRM_FLIP_HORIZONTAL) 437 if (rotation & DRM_MODE_REFLECT_Y)
527 cfg1 |= EXYNOS_MSCTRL_FLIP_Y_MIRROR; 438 cfg1 |= EXYNOS_MSCTRL_FLIP_Y_MIRROR;
528 break; 439 break;
529 case EXYNOS_DRM_DEGREE_90: 440 case DRM_MODE_ROTATE_90:
530 cfg2 |= EXYNOS_CITRGFMT_INROT90_CLOCKWISE; 441 cfg2 |= EXYNOS_CITRGFMT_INROT90_CLOCKWISE;
531 if (flip & EXYNOS_DRM_FLIP_VERTICAL) 442 if (rotation & DRM_MODE_REFLECT_X)
532 cfg1 |= EXYNOS_MSCTRL_FLIP_X_MIRROR; 443 cfg1 |= EXYNOS_MSCTRL_FLIP_X_MIRROR;
533 if (flip & EXYNOS_DRM_FLIP_HORIZONTAL) 444 if (rotation & DRM_MODE_REFLECT_Y)
534 cfg1 |= EXYNOS_MSCTRL_FLIP_Y_MIRROR; 445 cfg1 |= EXYNOS_MSCTRL_FLIP_Y_MIRROR;
535 break; 446 break;
536 case EXYNOS_DRM_DEGREE_180: 447 case DRM_MODE_ROTATE_180:
537 cfg1 |= (EXYNOS_MSCTRL_FLIP_X_MIRROR | 448 cfg1 |= (EXYNOS_MSCTRL_FLIP_X_MIRROR |
538 EXYNOS_MSCTRL_FLIP_Y_MIRROR); 449 EXYNOS_MSCTRL_FLIP_Y_MIRROR);
539 if (flip & EXYNOS_DRM_FLIP_VERTICAL) 450 if (rotation & DRM_MODE_REFLECT_X)
540 cfg1 &= ~EXYNOS_MSCTRL_FLIP_X_MIRROR; 451 cfg1 &= ~EXYNOS_MSCTRL_FLIP_X_MIRROR;
541 if (flip & EXYNOS_DRM_FLIP_HORIZONTAL) 452 if (rotation & DRM_MODE_REFLECT_Y)
542 cfg1 &= ~EXYNOS_MSCTRL_FLIP_Y_MIRROR; 453 cfg1 &= ~EXYNOS_MSCTRL_FLIP_Y_MIRROR;
543 break; 454 break;
544 case EXYNOS_DRM_DEGREE_270: 455 case DRM_MODE_ROTATE_270:
545 cfg1 |= (EXYNOS_MSCTRL_FLIP_X_MIRROR | 456 cfg1 |= (EXYNOS_MSCTRL_FLIP_X_MIRROR |
546 EXYNOS_MSCTRL_FLIP_Y_MIRROR); 457 EXYNOS_MSCTRL_FLIP_Y_MIRROR);
547 cfg2 |= EXYNOS_CITRGFMT_INROT90_CLOCKWISE; 458 cfg2 |= EXYNOS_CITRGFMT_INROT90_CLOCKWISE;
548 if (flip & EXYNOS_DRM_FLIP_VERTICAL) 459 if (rotation & DRM_MODE_REFLECT_X)
549 cfg1 &= ~EXYNOS_MSCTRL_FLIP_X_MIRROR; 460 cfg1 &= ~EXYNOS_MSCTRL_FLIP_X_MIRROR;
550 if (flip & EXYNOS_DRM_FLIP_HORIZONTAL) 461 if (rotation & DRM_MODE_REFLECT_Y)
551 cfg1 &= ~EXYNOS_MSCTRL_FLIP_Y_MIRROR; 462 cfg1 &= ~EXYNOS_MSCTRL_FLIP_Y_MIRROR;
552 break; 463 break;
553 default:
554 dev_err(ippdrv->dev, "invalid degree value %d.\n", degree);
555 return -EINVAL;
556 } 464 }
557 465
558 fimc_write(ctx, cfg1, EXYNOS_MSCTRL); 466 fimc_write(ctx, cfg1, EXYNOS_MSCTRL);
559 fimc_write(ctx, cfg2, EXYNOS_CITRGFMT); 467 fimc_write(ctx, cfg2, EXYNOS_CITRGFMT);
560 *swap = (cfg2 & EXYNOS_CITRGFMT_INROT90_CLOCKWISE) ? 1 : 0;
561
562 return 0;
563} 468}
564 469
565static int fimc_set_window(struct fimc_context *ctx, 470static void fimc_set_window(struct fimc_context *ctx,
566 struct drm_exynos_pos *pos, struct drm_exynos_sz *sz) 471 struct exynos_drm_ipp_buffer *buf)
567{ 472{
568 u32 cfg, h1, h2, v1, v2; 473 u32 cfg, h1, h2, v1, v2;
569 474
570 /* cropped image */ 475 /* cropped image */
571 h1 = pos->x; 476 h1 = buf->rect.x;
572 h2 = sz->hsize - pos->w - pos->x; 477 h2 = buf->buf.width - buf->rect.w - buf->rect.x;
573 v1 = pos->y; 478 v1 = buf->rect.y;
574 v2 = sz->vsize - pos->h - pos->y; 479 v2 = buf->buf.height - buf->rect.h - buf->rect.y;
575 480
576 DRM_DEBUG_KMS("x[%d]y[%d]w[%d]h[%d]hsize[%d]vsize[%d]\n", 481 DRM_DEBUG_KMS("x[%d]y[%d]w[%d]h[%d]hsize[%d]vsize[%d]\n",
577 pos->x, pos->y, pos->w, pos->h, sz->hsize, sz->vsize); 482 buf->rect.x, buf->rect.y, buf->rect.w, buf->rect.h,
483 buf->buf.width, buf->buf.height);
578 DRM_DEBUG_KMS("h1[%d]h2[%d]v1[%d]v2[%d]\n", h1, h2, v1, v2); 484 DRM_DEBUG_KMS("h1[%d]h2[%d]v1[%d]v2[%d]\n", h1, h2, v1, v2);
579 485
580 /* 486 /*
@@ -592,42 +498,30 @@ static int fimc_set_window(struct fimc_context *ctx,
592 cfg = (EXYNOS_CIWDOFST2_WINHOROFST2(h2) | 498 cfg = (EXYNOS_CIWDOFST2_WINHOROFST2(h2) |
593 EXYNOS_CIWDOFST2_WINVEROFST2(v2)); 499 EXYNOS_CIWDOFST2_WINVEROFST2(v2));
594 fimc_write(ctx, cfg, EXYNOS_CIWDOFST2); 500 fimc_write(ctx, cfg, EXYNOS_CIWDOFST2);
595
596 return 0;
597} 501}
598 502
599static int fimc_src_set_size(struct device *dev, int swap, 503static void fimc_src_set_size(struct fimc_context *ctx,
600 struct drm_exynos_pos *pos, struct drm_exynos_sz *sz) 504 struct exynos_drm_ipp_buffer *buf)
601{ 505{
602 struct fimc_context *ctx = get_fimc_context(dev);
603 struct drm_exynos_pos img_pos = *pos;
604 struct drm_exynos_sz img_sz = *sz;
605 u32 cfg; 506 u32 cfg;
606 507
607 DRM_DEBUG_KMS("swap[%d]hsize[%d]vsize[%d]\n", 508 DRM_DEBUG_KMS("hsize[%d]vsize[%d]\n", buf->buf.width, buf->buf.height);
608 swap, sz->hsize, sz->vsize);
609 509
610 /* original size */ 510 /* original size */
611 cfg = (EXYNOS_ORGISIZE_HORIZONTAL(img_sz.hsize) | 511 cfg = (EXYNOS_ORGISIZE_HORIZONTAL(buf->buf.width) |
612 EXYNOS_ORGISIZE_VERTICAL(img_sz.vsize)); 512 EXYNOS_ORGISIZE_VERTICAL(buf->buf.height));
613 513
614 fimc_write(ctx, cfg, EXYNOS_ORGISIZE); 514 fimc_write(ctx, cfg, EXYNOS_ORGISIZE);
615 515
616 DRM_DEBUG_KMS("x[%d]y[%d]w[%d]h[%d]\n", pos->x, pos->y, pos->w, pos->h); 516 DRM_DEBUG_KMS("x[%d]y[%d]w[%d]h[%d]\n", buf->rect.x, buf->rect.y,
617 517 buf->rect.w, buf->rect.h);
618 if (swap) {
619 img_pos.w = pos->h;
620 img_pos.h = pos->w;
621 img_sz.hsize = sz->vsize;
622 img_sz.vsize = sz->hsize;
623 }
624 518
625 /* set input DMA image size */ 519 /* set input DMA image size */
626 cfg = fimc_read(ctx, EXYNOS_CIREAL_ISIZE); 520 cfg = fimc_read(ctx, EXYNOS_CIREAL_ISIZE);
627 cfg &= ~(EXYNOS_CIREAL_ISIZE_HEIGHT_MASK | 521 cfg &= ~(EXYNOS_CIREAL_ISIZE_HEIGHT_MASK |
628 EXYNOS_CIREAL_ISIZE_WIDTH_MASK); 522 EXYNOS_CIREAL_ISIZE_WIDTH_MASK);
629 cfg |= (EXYNOS_CIREAL_ISIZE_WIDTH(img_pos.w) | 523 cfg |= (EXYNOS_CIREAL_ISIZE_WIDTH(buf->rect.w) |
630 EXYNOS_CIREAL_ISIZE_HEIGHT(img_pos.h)); 524 EXYNOS_CIREAL_ISIZE_HEIGHT(buf->rect.h));
631 fimc_write(ctx, cfg, EXYNOS_CIREAL_ISIZE); 525 fimc_write(ctx, cfg, EXYNOS_CIREAL_ISIZE);
632 526
633 /* 527 /*
@@ -635,91 +529,34 @@ static int fimc_src_set_size(struct device *dev, int swap,
635 * for now, we support only ITU601 8 bit mode 529 * for now, we support only ITU601 8 bit mode
636 */ 530 */
637 cfg = (EXYNOS_CISRCFMT_ITU601_8BIT | 531 cfg = (EXYNOS_CISRCFMT_ITU601_8BIT |
638 EXYNOS_CISRCFMT_SOURCEHSIZE(img_sz.hsize) | 532 EXYNOS_CISRCFMT_SOURCEHSIZE(buf->buf.width) |
639 EXYNOS_CISRCFMT_SOURCEVSIZE(img_sz.vsize)); 533 EXYNOS_CISRCFMT_SOURCEVSIZE(buf->buf.height));
640 fimc_write(ctx, cfg, EXYNOS_CISRCFMT); 534 fimc_write(ctx, cfg, EXYNOS_CISRCFMT);
641 535
642 /* offset Y(RGB), Cb, Cr */ 536 /* offset Y(RGB), Cb, Cr */
643 cfg = (EXYNOS_CIIYOFF_HORIZONTAL(img_pos.x) | 537 cfg = (EXYNOS_CIIYOFF_HORIZONTAL(buf->rect.x) |
644 EXYNOS_CIIYOFF_VERTICAL(img_pos.y)); 538 EXYNOS_CIIYOFF_VERTICAL(buf->rect.y));
645 fimc_write(ctx, cfg, EXYNOS_CIIYOFF); 539 fimc_write(ctx, cfg, EXYNOS_CIIYOFF);
646 cfg = (EXYNOS_CIICBOFF_HORIZONTAL(img_pos.x) | 540 cfg = (EXYNOS_CIICBOFF_HORIZONTAL(buf->rect.x) |
647 EXYNOS_CIICBOFF_VERTICAL(img_pos.y)); 541 EXYNOS_CIICBOFF_VERTICAL(buf->rect.y));
648 fimc_write(ctx, cfg, EXYNOS_CIICBOFF); 542 fimc_write(ctx, cfg, EXYNOS_CIICBOFF);
649 cfg = (EXYNOS_CIICROFF_HORIZONTAL(img_pos.x) | 543 cfg = (EXYNOS_CIICROFF_HORIZONTAL(buf->rect.x) |
650 EXYNOS_CIICROFF_VERTICAL(img_pos.y)); 544 EXYNOS_CIICROFF_VERTICAL(buf->rect.y));
651 fimc_write(ctx, cfg, EXYNOS_CIICROFF); 545 fimc_write(ctx, cfg, EXYNOS_CIICROFF);
652 546
653 return fimc_set_window(ctx, &img_pos, &img_sz); 547 fimc_set_window(ctx, buf);
654} 548}
655 549
656static int fimc_src_set_addr(struct device *dev, 550static void fimc_src_set_addr(struct fimc_context *ctx,
657 struct drm_exynos_ipp_buf_info *buf_info, u32 buf_id, 551 struct exynos_drm_ipp_buffer *buf)
658 enum drm_exynos_ipp_buf_type buf_type)
659{ 552{
660 struct fimc_context *ctx = get_fimc_context(dev); 553 fimc_write(ctx, buf->dma_addr[0], EXYNOS_CIIYSA(0));
661 struct exynos_drm_ippdrv *ippdrv = &ctx->ippdrv; 554 fimc_write(ctx, buf->dma_addr[1], EXYNOS_CIICBSA(0));
662 struct drm_exynos_ipp_cmd_node *c_node = ippdrv->c_node; 555 fimc_write(ctx, buf->dma_addr[2], EXYNOS_CIICRSA(0));
663 struct drm_exynos_ipp_property *property;
664 struct drm_exynos_ipp_config *config;
665
666 if (!c_node) {
667 DRM_ERROR("failed to get c_node.\n");
668 return -EINVAL;
669 }
670
671 property = &c_node->property;
672
673 DRM_DEBUG_KMS("prop_id[%d]buf_id[%d]buf_type[%d]\n",
674 property->prop_id, buf_id, buf_type);
675
676 if (buf_id > FIMC_MAX_SRC) {
677 dev_info(ippdrv->dev, "invalid buf_id %d.\n", buf_id);
678 return -ENOMEM;
679 }
680
681 /* address register set */
682 switch (buf_type) {
683 case IPP_BUF_ENQUEUE:
684 config = &property->config[EXYNOS_DRM_OPS_SRC];
685 fimc_write(ctx, buf_info->base[EXYNOS_DRM_PLANAR_Y],
686 EXYNOS_CIIYSA0);
687
688 if (config->fmt == DRM_FORMAT_YVU420) {
689 fimc_write(ctx, buf_info->base[EXYNOS_DRM_PLANAR_CR],
690 EXYNOS_CIICBSA0);
691 fimc_write(ctx, buf_info->base[EXYNOS_DRM_PLANAR_CB],
692 EXYNOS_CIICRSA0);
693 } else {
694 fimc_write(ctx, buf_info->base[EXYNOS_DRM_PLANAR_CB],
695 EXYNOS_CIICBSA0);
696 fimc_write(ctx, buf_info->base[EXYNOS_DRM_PLANAR_CR],
697 EXYNOS_CIICRSA0);
698 }
699 break;
700 case IPP_BUF_DEQUEUE:
701 fimc_write(ctx, 0x0, EXYNOS_CIIYSA0);
702 fimc_write(ctx, 0x0, EXYNOS_CIICBSA0);
703 fimc_write(ctx, 0x0, EXYNOS_CIICRSA0);
704 break;
705 default:
706 /* bypass */
707 break;
708 }
709
710 return 0;
711} 556}
712 557
713static struct exynos_drm_ipp_ops fimc_src_ops = { 558static void fimc_dst_set_fmt_order(struct fimc_context *ctx, u32 fmt)
714 .set_fmt = fimc_src_set_fmt,
715 .set_transf = fimc_src_set_transf,
716 .set_size = fimc_src_set_size,
717 .set_addr = fimc_src_set_addr,
718};
719
720static int fimc_dst_set_fmt_order(struct fimc_context *ctx, u32 fmt)
721{ 559{
722 struct exynos_drm_ippdrv *ippdrv = &ctx->ippdrv;
723 u32 cfg; 560 u32 cfg;
724 561
725 DRM_DEBUG_KMS("fmt[0x%x]\n", fmt); 562 DRM_DEBUG_KMS("fmt[0x%x]\n", fmt);
@@ -732,11 +569,11 @@ static int fimc_dst_set_fmt_order(struct fimc_context *ctx, u32 fmt)
732 case DRM_FORMAT_RGB565: 569 case DRM_FORMAT_RGB565:
733 cfg |= EXYNOS_CISCCTRL_OUTRGB_FMT_RGB565; 570 cfg |= EXYNOS_CISCCTRL_OUTRGB_FMT_RGB565;
734 fimc_write(ctx, cfg, EXYNOS_CISCCTRL); 571 fimc_write(ctx, cfg, EXYNOS_CISCCTRL);
735 return 0; 572 return;
736 case DRM_FORMAT_RGB888: 573 case DRM_FORMAT_RGB888:
737 cfg |= EXYNOS_CISCCTRL_OUTRGB_FMT_RGB888; 574 cfg |= EXYNOS_CISCCTRL_OUTRGB_FMT_RGB888;
738 fimc_write(ctx, cfg, EXYNOS_CISCCTRL); 575 fimc_write(ctx, cfg, EXYNOS_CISCCTRL);
739 return 0; 576 return;
740 case DRM_FORMAT_XRGB8888: 577 case DRM_FORMAT_XRGB8888:
741 cfg |= (EXYNOS_CISCCTRL_OUTRGB_FMT_RGB888 | 578 cfg |= (EXYNOS_CISCCTRL_OUTRGB_FMT_RGB888 |
742 EXYNOS_CISCCTRL_EXTRGB_EXTENSION); 579 EXYNOS_CISCCTRL_EXTRGB_EXTENSION);
@@ -784,20 +621,13 @@ static int fimc_dst_set_fmt_order(struct fimc_context *ctx, u32 fmt)
784 cfg |= EXYNOS_CIOCTRL_ORDER2P_LSB_CBCR; 621 cfg |= EXYNOS_CIOCTRL_ORDER2P_LSB_CBCR;
785 cfg |= EXYNOS_CIOCTRL_YCBCR_2PLANE; 622 cfg |= EXYNOS_CIOCTRL_YCBCR_2PLANE;
786 break; 623 break;
787 default:
788 dev_err(ippdrv->dev, "invalid target yuv order 0x%x.\n", fmt);
789 return -EINVAL;
790 } 624 }
791 625
792 fimc_write(ctx, cfg, EXYNOS_CIOCTRL); 626 fimc_write(ctx, cfg, EXYNOS_CIOCTRL);
793
794 return 0;
795} 627}
796 628
797static int fimc_dst_set_fmt(struct device *dev, u32 fmt) 629static void fimc_dst_set_fmt(struct fimc_context *ctx, u32 fmt, bool tiled)
798{ 630{
799 struct fimc_context *ctx = get_fimc_context(dev);
800 struct exynos_drm_ippdrv *ippdrv = &ctx->ippdrv;
801 u32 cfg; 631 u32 cfg;
802 632
803 DRM_DEBUG_KMS("fmt[0x%x]\n", fmt); 633 DRM_DEBUG_KMS("fmt[0x%x]\n", fmt);
@@ -837,10 +667,6 @@ static int fimc_dst_set_fmt(struct device *dev, u32 fmt)
837 case DRM_FORMAT_NV21: 667 case DRM_FORMAT_NV21:
838 cfg |= EXYNOS_CITRGFMT_OUTFORMAT_YCBCR420; 668 cfg |= EXYNOS_CITRGFMT_OUTFORMAT_YCBCR420;
839 break; 669 break;
840 default:
841 dev_err(ippdrv->dev, "invalid target format 0x%x.\n",
842 fmt);
843 return -EINVAL;
844 } 670 }
845 671
846 fimc_write(ctx, cfg, EXYNOS_CITRGFMT); 672 fimc_write(ctx, cfg, EXYNOS_CITRGFMT);
@@ -849,73 +675,67 @@ static int fimc_dst_set_fmt(struct device *dev, u32 fmt)
849 cfg = fimc_read(ctx, EXYNOS_CIDMAPARAM); 675 cfg = fimc_read(ctx, EXYNOS_CIDMAPARAM);
850 cfg &= ~EXYNOS_CIDMAPARAM_W_MODE_MASK; 676 cfg &= ~EXYNOS_CIDMAPARAM_W_MODE_MASK;
851 677
852 cfg |= EXYNOS_CIDMAPARAM_W_MODE_LINEAR; 678 if (tiled)
679 cfg |= EXYNOS_CIDMAPARAM_W_MODE_64X32;
680 else
681 cfg |= EXYNOS_CIDMAPARAM_W_MODE_LINEAR;
853 682
854 fimc_write(ctx, cfg, EXYNOS_CIDMAPARAM); 683 fimc_write(ctx, cfg, EXYNOS_CIDMAPARAM);
855 684
856 return fimc_dst_set_fmt_order(ctx, fmt); 685 fimc_dst_set_fmt_order(ctx, fmt);
857} 686}
858 687
859static int fimc_dst_set_transf(struct device *dev, 688static void fimc_dst_set_transf(struct fimc_context *ctx, unsigned int rotation)
860 enum drm_exynos_degree degree,
861 enum drm_exynos_flip flip, bool *swap)
862{ 689{
863 struct fimc_context *ctx = get_fimc_context(dev); 690 unsigned int degree = rotation & DRM_MODE_ROTATE_MASK;
864 struct exynos_drm_ippdrv *ippdrv = &ctx->ippdrv;
865 u32 cfg; 691 u32 cfg;
866 692
867 DRM_DEBUG_KMS("degree[%d]flip[0x%x]\n", degree, flip); 693 DRM_DEBUG_KMS("rotation[0x%x]\n", rotation);
868 694
869 cfg = fimc_read(ctx, EXYNOS_CITRGFMT); 695 cfg = fimc_read(ctx, EXYNOS_CITRGFMT);
870 cfg &= ~EXYNOS_CITRGFMT_FLIP_MASK; 696 cfg &= ~EXYNOS_CITRGFMT_FLIP_MASK;
871 cfg &= ~EXYNOS_CITRGFMT_OUTROT90_CLOCKWISE; 697 cfg &= ~EXYNOS_CITRGFMT_OUTROT90_CLOCKWISE;
872 698
873 switch (degree) { 699 switch (degree) {
874 case EXYNOS_DRM_DEGREE_0: 700 case DRM_MODE_ROTATE_0:
875 if (flip & EXYNOS_DRM_FLIP_VERTICAL) 701 if (rotation & DRM_MODE_REFLECT_X)
876 cfg |= EXYNOS_CITRGFMT_FLIP_X_MIRROR; 702 cfg |= EXYNOS_CITRGFMT_FLIP_X_MIRROR;
877 if (flip & EXYNOS_DRM_FLIP_HORIZONTAL) 703 if (rotation & DRM_MODE_REFLECT_Y)
878 cfg |= EXYNOS_CITRGFMT_FLIP_Y_MIRROR; 704 cfg |= EXYNOS_CITRGFMT_FLIP_Y_MIRROR;
879 break; 705 break;
880 case EXYNOS_DRM_DEGREE_90: 706 case DRM_MODE_ROTATE_90:
881 cfg |= EXYNOS_CITRGFMT_OUTROT90_CLOCKWISE; 707 cfg |= EXYNOS_CITRGFMT_OUTROT90_CLOCKWISE;
882 if (flip & EXYNOS_DRM_FLIP_VERTICAL) 708 if (rotation & DRM_MODE_REFLECT_X)
883 cfg |= EXYNOS_CITRGFMT_FLIP_X_MIRROR; 709 cfg |= EXYNOS_CITRGFMT_FLIP_X_MIRROR;
884 if (flip & EXYNOS_DRM_FLIP_HORIZONTAL) 710 if (rotation & DRM_MODE_REFLECT_Y)
885 cfg |= EXYNOS_CITRGFMT_FLIP_Y_MIRROR; 711 cfg |= EXYNOS_CITRGFMT_FLIP_Y_MIRROR;
886 break; 712 break;
887 case EXYNOS_DRM_DEGREE_180: 713 case DRM_MODE_ROTATE_180:
888 cfg |= (EXYNOS_CITRGFMT_FLIP_X_MIRROR | 714 cfg |= (EXYNOS_CITRGFMT_FLIP_X_MIRROR |
889 EXYNOS_CITRGFMT_FLIP_Y_MIRROR); 715 EXYNOS_CITRGFMT_FLIP_Y_MIRROR);
890 if (flip & EXYNOS_DRM_FLIP_VERTICAL) 716 if (rotation & DRM_MODE_REFLECT_X)
891 cfg &= ~EXYNOS_CITRGFMT_FLIP_X_MIRROR; 717 cfg &= ~EXYNOS_CITRGFMT_FLIP_X_MIRROR;
892 if (flip & EXYNOS_DRM_FLIP_HORIZONTAL) 718 if (rotation & DRM_MODE_REFLECT_Y)
893 cfg &= ~EXYNOS_CITRGFMT_FLIP_Y_MIRROR; 719 cfg &= ~EXYNOS_CITRGFMT_FLIP_Y_MIRROR;
894 break; 720 break;
895 case EXYNOS_DRM_DEGREE_270: 721 case DRM_MODE_ROTATE_270:
896 cfg |= (EXYNOS_CITRGFMT_OUTROT90_CLOCKWISE | 722 cfg |= (EXYNOS_CITRGFMT_OUTROT90_CLOCKWISE |
897 EXYNOS_CITRGFMT_FLIP_X_MIRROR | 723 EXYNOS_CITRGFMT_FLIP_X_MIRROR |
898 EXYNOS_CITRGFMT_FLIP_Y_MIRROR); 724 EXYNOS_CITRGFMT_FLIP_Y_MIRROR);
899 if (flip & EXYNOS_DRM_FLIP_VERTICAL) 725 if (rotation & DRM_MODE_REFLECT_X)
900 cfg &= ~EXYNOS_CITRGFMT_FLIP_X_MIRROR; 726 cfg &= ~EXYNOS_CITRGFMT_FLIP_X_MIRROR;
901 if (flip & EXYNOS_DRM_FLIP_HORIZONTAL) 727 if (rotation & DRM_MODE_REFLECT_Y)
902 cfg &= ~EXYNOS_CITRGFMT_FLIP_Y_MIRROR; 728 cfg &= ~EXYNOS_CITRGFMT_FLIP_Y_MIRROR;
903 break; 729 break;
904 default:
905 dev_err(ippdrv->dev, "invalid degree value %d.\n", degree);
906 return -EINVAL;
907 } 730 }
908 731
909 fimc_write(ctx, cfg, EXYNOS_CITRGFMT); 732 fimc_write(ctx, cfg, EXYNOS_CITRGFMT);
910 *swap = (cfg & EXYNOS_CITRGFMT_OUTROT90_CLOCKWISE) ? 1 : 0;
911
912 return 0;
913} 733}
914 734
915static int fimc_set_prescaler(struct fimc_context *ctx, struct fimc_scaler *sc, 735static int fimc_set_prescaler(struct fimc_context *ctx, struct fimc_scaler *sc,
916 struct drm_exynos_pos *src, struct drm_exynos_pos *dst) 736 struct drm_exynos_ipp_task_rect *src,
737 struct drm_exynos_ipp_task_rect *dst)
917{ 738{
918 struct exynos_drm_ippdrv *ippdrv = &ctx->ippdrv;
919 u32 cfg, cfg_ext, shfactor; 739 u32 cfg, cfg_ext, shfactor;
920 u32 pre_dst_width, pre_dst_height; 740 u32 pre_dst_width, pre_dst_height;
921 u32 hfactor, vfactor; 741 u32 hfactor, vfactor;
@@ -942,13 +762,13 @@ static int fimc_set_prescaler(struct fimc_context *ctx, struct fimc_scaler *sc,
942 /* fimc_ippdrv_check_property assures that dividers are not null */ 762 /* fimc_ippdrv_check_property assures that dividers are not null */
943 hfactor = fls(src_w / dst_w / 2); 763 hfactor = fls(src_w / dst_w / 2);
944 if (hfactor > FIMC_SHFACTOR / 2) { 764 if (hfactor > FIMC_SHFACTOR / 2) {
945 dev_err(ippdrv->dev, "failed to get ratio horizontal.\n"); 765 dev_err(ctx->dev, "failed to get ratio horizontal.\n");
946 return -EINVAL; 766 return -EINVAL;
947 } 767 }
948 768
949 vfactor = fls(src_h / dst_h / 2); 769 vfactor = fls(src_h / dst_h / 2);
950 if (vfactor > FIMC_SHFACTOR / 2) { 770 if (vfactor > FIMC_SHFACTOR / 2) {
951 dev_err(ippdrv->dev, "failed to get ratio vertical.\n"); 771 dev_err(ctx->dev, "failed to get ratio vertical.\n");
952 return -EINVAL; 772 return -EINVAL;
953 } 773 }
954 774
@@ -1019,83 +839,77 @@ static void fimc_set_scaler(struct fimc_context *ctx, struct fimc_scaler *sc)
1019 fimc_write(ctx, cfg_ext, EXYNOS_CIEXTEN); 839 fimc_write(ctx, cfg_ext, EXYNOS_CIEXTEN);
1020} 840}
1021 841
1022static int fimc_dst_set_size(struct device *dev, int swap, 842static void fimc_dst_set_size(struct fimc_context *ctx,
1023 struct drm_exynos_pos *pos, struct drm_exynos_sz *sz) 843 struct exynos_drm_ipp_buffer *buf)
1024{ 844{
1025 struct fimc_context *ctx = get_fimc_context(dev); 845 u32 cfg, cfg_ext;
1026 struct drm_exynos_pos img_pos = *pos;
1027 struct drm_exynos_sz img_sz = *sz;
1028 u32 cfg;
1029 846
1030 DRM_DEBUG_KMS("swap[%d]hsize[%d]vsize[%d]\n", 847 DRM_DEBUG_KMS("hsize[%d]vsize[%d]\n", buf->buf.width, buf->buf.height);
1031 swap, sz->hsize, sz->vsize);
1032 848
1033 /* original size */ 849 /* original size */
1034 cfg = (EXYNOS_ORGOSIZE_HORIZONTAL(img_sz.hsize) | 850 cfg = (EXYNOS_ORGOSIZE_HORIZONTAL(buf->buf.width) |
1035 EXYNOS_ORGOSIZE_VERTICAL(img_sz.vsize)); 851 EXYNOS_ORGOSIZE_VERTICAL(buf->buf.height));
1036 852
1037 fimc_write(ctx, cfg, EXYNOS_ORGOSIZE); 853 fimc_write(ctx, cfg, EXYNOS_ORGOSIZE);
1038 854
1039 DRM_DEBUG_KMS("x[%d]y[%d]w[%d]h[%d]\n", pos->x, pos->y, pos->w, pos->h); 855 DRM_DEBUG_KMS("x[%d]y[%d]w[%d]h[%d]\n", buf->rect.x, buf->rect.y,
856 buf->rect.w, buf->rect.h);
1040 857
1041 /* CSC ITU */ 858 /* CSC ITU */
1042 cfg = fimc_read(ctx, EXYNOS_CIGCTRL); 859 cfg = fimc_read(ctx, EXYNOS_CIGCTRL);
1043 cfg &= ~EXYNOS_CIGCTRL_CSC_MASK; 860 cfg &= ~EXYNOS_CIGCTRL_CSC_MASK;
1044 861
1045 if (sz->hsize >= FIMC_WIDTH_ITU_709) 862 if (buf->buf.width >= FIMC_WIDTH_ITU_709)
1046 cfg |= EXYNOS_CIGCTRL_CSC_ITU709; 863 cfg |= EXYNOS_CIGCTRL_CSC_ITU709;
1047 else 864 else
1048 cfg |= EXYNOS_CIGCTRL_CSC_ITU601; 865 cfg |= EXYNOS_CIGCTRL_CSC_ITU601;
1049 866
1050 fimc_write(ctx, cfg, EXYNOS_CIGCTRL); 867 fimc_write(ctx, cfg, EXYNOS_CIGCTRL);
1051 868
1052 if (swap) { 869 cfg_ext = fimc_read(ctx, EXYNOS_CITRGFMT);
1053 img_pos.w = pos->h;
1054 img_pos.h = pos->w;
1055 img_sz.hsize = sz->vsize;
1056 img_sz.vsize = sz->hsize;
1057 }
1058 870
1059 /* target image size */ 871 /* target image size */
1060 cfg = fimc_read(ctx, EXYNOS_CITRGFMT); 872 cfg = fimc_read(ctx, EXYNOS_CITRGFMT);
1061 cfg &= ~(EXYNOS_CITRGFMT_TARGETH_MASK | 873 cfg &= ~(EXYNOS_CITRGFMT_TARGETH_MASK |
1062 EXYNOS_CITRGFMT_TARGETV_MASK); 874 EXYNOS_CITRGFMT_TARGETV_MASK);
1063 cfg |= (EXYNOS_CITRGFMT_TARGETHSIZE(img_pos.w) | 875 if (cfg_ext & EXYNOS_CITRGFMT_OUTROT90_CLOCKWISE)
1064 EXYNOS_CITRGFMT_TARGETVSIZE(img_pos.h)); 876 cfg |= (EXYNOS_CITRGFMT_TARGETHSIZE(buf->rect.h) |
877 EXYNOS_CITRGFMT_TARGETVSIZE(buf->rect.w));
878 else
879 cfg |= (EXYNOS_CITRGFMT_TARGETHSIZE(buf->rect.w) |
880 EXYNOS_CITRGFMT_TARGETVSIZE(buf->rect.h));
1065 fimc_write(ctx, cfg, EXYNOS_CITRGFMT); 881 fimc_write(ctx, cfg, EXYNOS_CITRGFMT);
1066 882
1067 /* target area */ 883 /* target area */
1068 cfg = EXYNOS_CITAREA_TARGET_AREA(img_pos.w * img_pos.h); 884 cfg = EXYNOS_CITAREA_TARGET_AREA(buf->rect.w * buf->rect.h);
1069 fimc_write(ctx, cfg, EXYNOS_CITAREA); 885 fimc_write(ctx, cfg, EXYNOS_CITAREA);
1070 886
1071 /* offset Y(RGB), Cb, Cr */ 887 /* offset Y(RGB), Cb, Cr */
1072 cfg = (EXYNOS_CIOYOFF_HORIZONTAL(img_pos.x) | 888 cfg = (EXYNOS_CIOYOFF_HORIZONTAL(buf->rect.x) |
1073 EXYNOS_CIOYOFF_VERTICAL(img_pos.y)); 889 EXYNOS_CIOYOFF_VERTICAL(buf->rect.y));
1074 fimc_write(ctx, cfg, EXYNOS_CIOYOFF); 890 fimc_write(ctx, cfg, EXYNOS_CIOYOFF);
1075 cfg = (EXYNOS_CIOCBOFF_HORIZONTAL(img_pos.x) | 891 cfg = (EXYNOS_CIOCBOFF_HORIZONTAL(buf->rect.x) |
1076 EXYNOS_CIOCBOFF_VERTICAL(img_pos.y)); 892 EXYNOS_CIOCBOFF_VERTICAL(buf->rect.y));
1077 fimc_write(ctx, cfg, EXYNOS_CIOCBOFF); 893 fimc_write(ctx, cfg, EXYNOS_CIOCBOFF);
1078 cfg = (EXYNOS_CIOCROFF_HORIZONTAL(img_pos.x) | 894 cfg = (EXYNOS_CIOCROFF_HORIZONTAL(buf->rect.x) |
1079 EXYNOS_CIOCROFF_VERTICAL(img_pos.y)); 895 EXYNOS_CIOCROFF_VERTICAL(buf->rect.y));
1080 fimc_write(ctx, cfg, EXYNOS_CIOCROFF); 896 fimc_write(ctx, cfg, EXYNOS_CIOCROFF);
1081
1082 return 0;
1083} 897}
1084 898
1085static void fimc_dst_set_buf_seq(struct fimc_context *ctx, u32 buf_id, 899static void fimc_dst_set_buf_seq(struct fimc_context *ctx, u32 buf_id,
1086 enum drm_exynos_ipp_buf_type buf_type) 900 bool enqueue)
1087{ 901{
1088 unsigned long flags; 902 unsigned long flags;
1089 u32 buf_num; 903 u32 buf_num;
1090 u32 cfg; 904 u32 cfg;
1091 905
1092 DRM_DEBUG_KMS("buf_id[%d]buf_type[%d]\n", buf_id, buf_type); 906 DRM_DEBUG_KMS("buf_id[%d]enqueu[%d]\n", buf_id, enqueue);
1093 907
1094 spin_lock_irqsave(&ctx->lock, flags); 908 spin_lock_irqsave(&ctx->lock, flags);
1095 909
1096 cfg = fimc_read(ctx, EXYNOS_CIFCNTSEQ); 910 cfg = fimc_read(ctx, EXYNOS_CIFCNTSEQ);
1097 911
1098 if (buf_type == IPP_BUF_ENQUEUE) 912 if (enqueue)
1099 cfg |= (1 << buf_id); 913 cfg |= (1 << buf_id);
1100 else 914 else
1101 cfg &= ~(1 << buf_id); 915 cfg &= ~(1 << buf_id);
@@ -1104,88 +918,29 @@ static void fimc_dst_set_buf_seq(struct fimc_context *ctx, u32 buf_id,
1104 918
1105 buf_num = hweight32(cfg); 919 buf_num = hweight32(cfg);
1106 920
1107 if (buf_type == IPP_BUF_ENQUEUE && buf_num >= FIMC_BUF_START) 921 if (enqueue && buf_num >= FIMC_BUF_START)
1108 fimc_mask_irq(ctx, true); 922 fimc_mask_irq(ctx, true);
1109 else if (buf_type == IPP_BUF_DEQUEUE && buf_num <= FIMC_BUF_STOP) 923 else if (!enqueue && buf_num <= FIMC_BUF_STOP)
1110 fimc_mask_irq(ctx, false); 924 fimc_mask_irq(ctx, false);
1111 925
1112 spin_unlock_irqrestore(&ctx->lock, flags); 926 spin_unlock_irqrestore(&ctx->lock, flags);
1113} 927}
1114 928
1115static int fimc_dst_set_addr(struct device *dev, 929static void fimc_dst_set_addr(struct fimc_context *ctx,
1116 struct drm_exynos_ipp_buf_info *buf_info, u32 buf_id, 930 struct exynos_drm_ipp_buffer *buf)
1117 enum drm_exynos_ipp_buf_type buf_type)
1118{ 931{
1119 struct fimc_context *ctx = get_fimc_context(dev); 932 fimc_write(ctx, buf->dma_addr[0], EXYNOS_CIOYSA(0));
1120 struct exynos_drm_ippdrv *ippdrv = &ctx->ippdrv; 933 fimc_write(ctx, buf->dma_addr[1], EXYNOS_CIOCBSA(0));
1121 struct drm_exynos_ipp_cmd_node *c_node = ippdrv->c_node; 934 fimc_write(ctx, buf->dma_addr[2], EXYNOS_CIOCRSA(0));
1122 struct drm_exynos_ipp_property *property;
1123 struct drm_exynos_ipp_config *config;
1124
1125 if (!c_node) {
1126 DRM_ERROR("failed to get c_node.\n");
1127 return -EINVAL;
1128 }
1129
1130 property = &c_node->property;
1131
1132 DRM_DEBUG_KMS("prop_id[%d]buf_id[%d]buf_type[%d]\n",
1133 property->prop_id, buf_id, buf_type);
1134 935
1135 if (buf_id > FIMC_MAX_DST) { 936 fimc_dst_set_buf_seq(ctx, 0, true);
1136 dev_info(ippdrv->dev, "invalid buf_id %d.\n", buf_id);
1137 return -ENOMEM;
1138 }
1139
1140 /* address register set */
1141 switch (buf_type) {
1142 case IPP_BUF_ENQUEUE:
1143 config = &property->config[EXYNOS_DRM_OPS_DST];
1144
1145 fimc_write(ctx, buf_info->base[EXYNOS_DRM_PLANAR_Y],
1146 EXYNOS_CIOYSA(buf_id));
1147
1148 if (config->fmt == DRM_FORMAT_YVU420) {
1149 fimc_write(ctx, buf_info->base[EXYNOS_DRM_PLANAR_CR],
1150 EXYNOS_CIOCBSA(buf_id));
1151 fimc_write(ctx, buf_info->base[EXYNOS_DRM_PLANAR_CB],
1152 EXYNOS_CIOCRSA(buf_id));
1153 } else {
1154 fimc_write(ctx, buf_info->base[EXYNOS_DRM_PLANAR_CB],
1155 EXYNOS_CIOCBSA(buf_id));
1156 fimc_write(ctx, buf_info->base[EXYNOS_DRM_PLANAR_CR],
1157 EXYNOS_CIOCRSA(buf_id));
1158 }
1159 break;
1160 case IPP_BUF_DEQUEUE:
1161 fimc_write(ctx, 0x0, EXYNOS_CIOYSA(buf_id));
1162 fimc_write(ctx, 0x0, EXYNOS_CIOCBSA(buf_id));
1163 fimc_write(ctx, 0x0, EXYNOS_CIOCRSA(buf_id));
1164 break;
1165 default:
1166 /* bypass */
1167 break;
1168 }
1169
1170 fimc_dst_set_buf_seq(ctx, buf_id, buf_type);
1171
1172 return 0;
1173} 937}
1174 938
1175static struct exynos_drm_ipp_ops fimc_dst_ops = { 939static void fimc_stop(struct fimc_context *ctx);
1176 .set_fmt = fimc_dst_set_fmt,
1177 .set_transf = fimc_dst_set_transf,
1178 .set_size = fimc_dst_set_size,
1179 .set_addr = fimc_dst_set_addr,
1180};
1181 940
1182static irqreturn_t fimc_irq_handler(int irq, void *dev_id) 941static irqreturn_t fimc_irq_handler(int irq, void *dev_id)
1183{ 942{
1184 struct fimc_context *ctx = dev_id; 943 struct fimc_context *ctx = dev_id;
1185 struct exynos_drm_ippdrv *ippdrv = &ctx->ippdrv;
1186 struct drm_exynos_ipp_cmd_node *c_node = ippdrv->c_node;
1187 struct drm_exynos_ipp_event_work *event_work =
1188 c_node->event_work;
1189 int buf_id; 944 int buf_id;
1190 945
1191 DRM_DEBUG_KMS("fimc id[%d]\n", ctx->id); 946 DRM_DEBUG_KMS("fimc id[%d]\n", ctx->id);
@@ -1203,170 +958,19 @@ static irqreturn_t fimc_irq_handler(int irq, void *dev_id)
1203 958
1204 DRM_DEBUG_KMS("buf_id[%d]\n", buf_id); 959 DRM_DEBUG_KMS("buf_id[%d]\n", buf_id);
1205 960
1206 fimc_dst_set_buf_seq(ctx, buf_id, IPP_BUF_DEQUEUE); 961 if (ctx->task) {
1207 962 struct exynos_drm_ipp_task *task = ctx->task;
1208 event_work->ippdrv = ippdrv;
1209 event_work->buf_id[EXYNOS_DRM_OPS_DST] = buf_id;
1210 queue_work(ippdrv->event_workq, &event_work->work);
1211
1212 return IRQ_HANDLED;
1213}
1214
1215static int fimc_init_prop_list(struct exynos_drm_ippdrv *ippdrv)
1216{
1217 struct drm_exynos_ipp_prop_list *prop_list = &ippdrv->prop_list;
1218
1219 prop_list->version = 1;
1220 prop_list->writeback = 1;
1221 prop_list->refresh_min = FIMC_REFRESH_MIN;
1222 prop_list->refresh_max = FIMC_REFRESH_MAX;
1223 prop_list->flip = (1 << EXYNOS_DRM_FLIP_NONE) |
1224 (1 << EXYNOS_DRM_FLIP_VERTICAL) |
1225 (1 << EXYNOS_DRM_FLIP_HORIZONTAL);
1226 prop_list->degree = (1 << EXYNOS_DRM_DEGREE_0) |
1227 (1 << EXYNOS_DRM_DEGREE_90) |
1228 (1 << EXYNOS_DRM_DEGREE_180) |
1229 (1 << EXYNOS_DRM_DEGREE_270);
1230 prop_list->csc = 1;
1231 prop_list->crop = 1;
1232 prop_list->crop_max.hsize = FIMC_CROP_MAX;
1233 prop_list->crop_max.vsize = FIMC_CROP_MAX;
1234 prop_list->crop_min.hsize = FIMC_CROP_MIN;
1235 prop_list->crop_min.vsize = FIMC_CROP_MIN;
1236 prop_list->scale = 1;
1237 prop_list->scale_max.hsize = FIMC_SCALE_MAX;
1238 prop_list->scale_max.vsize = FIMC_SCALE_MAX;
1239 prop_list->scale_min.hsize = FIMC_SCALE_MIN;
1240 prop_list->scale_min.vsize = FIMC_SCALE_MIN;
1241
1242 return 0;
1243}
1244
1245static inline bool fimc_check_drm_flip(enum drm_exynos_flip flip)
1246{
1247 switch (flip) {
1248 case EXYNOS_DRM_FLIP_NONE:
1249 case EXYNOS_DRM_FLIP_VERTICAL:
1250 case EXYNOS_DRM_FLIP_HORIZONTAL:
1251 case EXYNOS_DRM_FLIP_BOTH:
1252 return true;
1253 default:
1254 DRM_DEBUG_KMS("invalid flip\n");
1255 return false;
1256 }
1257}
1258
1259static int fimc_ippdrv_check_property(struct device *dev,
1260 struct drm_exynos_ipp_property *property)
1261{
1262 struct fimc_context *ctx = get_fimc_context(dev);
1263 struct exynos_drm_ippdrv *ippdrv = &ctx->ippdrv;
1264 struct drm_exynos_ipp_prop_list *pp = &ippdrv->prop_list;
1265 struct drm_exynos_ipp_config *config;
1266 struct drm_exynos_pos *pos;
1267 struct drm_exynos_sz *sz;
1268 bool swap;
1269 int i;
1270
1271 for_each_ipp_ops(i) {
1272 if ((i == EXYNOS_DRM_OPS_SRC) &&
1273 (property->cmd == IPP_CMD_WB))
1274 continue;
1275
1276 config = &property->config[i];
1277 pos = &config->pos;
1278 sz = &config->sz;
1279
1280 /* check for flip */
1281 if (!fimc_check_drm_flip(config->flip)) {
1282 DRM_ERROR("invalid flip.\n");
1283 goto err_property;
1284 }
1285
1286 /* check for degree */
1287 switch (config->degree) {
1288 case EXYNOS_DRM_DEGREE_90:
1289 case EXYNOS_DRM_DEGREE_270:
1290 swap = true;
1291 break;
1292 case EXYNOS_DRM_DEGREE_0:
1293 case EXYNOS_DRM_DEGREE_180:
1294 swap = false;
1295 break;
1296 default:
1297 DRM_ERROR("invalid degree.\n");
1298 goto err_property;
1299 }
1300
1301 /* check for buffer bound */
1302 if ((pos->x + pos->w > sz->hsize) ||
1303 (pos->y + pos->h > sz->vsize)) {
1304 DRM_ERROR("out of buf bound.\n");
1305 goto err_property;
1306 }
1307 963
1308 /* check for crop */ 964 ctx->task = NULL;
1309 if ((i == EXYNOS_DRM_OPS_SRC) && (pp->crop)) { 965 pm_runtime_mark_last_busy(ctx->dev);
1310 if (swap) { 966 pm_runtime_put_autosuspend(ctx->dev);
1311 if ((pos->h < pp->crop_min.hsize) || 967 exynos_drm_ipp_task_done(task, 0);
1312 (sz->vsize > pp->crop_max.hsize) ||
1313 (pos->w < pp->crop_min.vsize) ||
1314 (sz->hsize > pp->crop_max.vsize)) {
1315 DRM_ERROR("out of crop size.\n");
1316 goto err_property;
1317 }
1318 } else {
1319 if ((pos->w < pp->crop_min.hsize) ||
1320 (sz->hsize > pp->crop_max.hsize) ||
1321 (pos->h < pp->crop_min.vsize) ||
1322 (sz->vsize > pp->crop_max.vsize)) {
1323 DRM_ERROR("out of crop size.\n");
1324 goto err_property;
1325 }
1326 }
1327 }
1328
1329 /* check for scale */
1330 if ((i == EXYNOS_DRM_OPS_DST) && (pp->scale)) {
1331 if (swap) {
1332 if ((pos->h < pp->scale_min.hsize) ||
1333 (sz->vsize > pp->scale_max.hsize) ||
1334 (pos->w < pp->scale_min.vsize) ||
1335 (sz->hsize > pp->scale_max.vsize)) {
1336 DRM_ERROR("out of scale size.\n");
1337 goto err_property;
1338 }
1339 } else {
1340 if ((pos->w < pp->scale_min.hsize) ||
1341 (sz->hsize > pp->scale_max.hsize) ||
1342 (pos->h < pp->scale_min.vsize) ||
1343 (sz->vsize > pp->scale_max.vsize)) {
1344 DRM_ERROR("out of scale size.\n");
1345 goto err_property;
1346 }
1347 }
1348 }
1349 } 968 }
1350 969
1351 return 0; 970 fimc_dst_set_buf_seq(ctx, buf_id, false);
971 fimc_stop(ctx);
1352 972
1353err_property: 973 return IRQ_HANDLED;
1354 for_each_ipp_ops(i) {
1355 if ((i == EXYNOS_DRM_OPS_SRC) &&
1356 (property->cmd == IPP_CMD_WB))
1357 continue;
1358
1359 config = &property->config[i];
1360 pos = &config->pos;
1361 sz = &config->sz;
1362
1363 DRM_ERROR("[%s]f[%d]r[%d]pos[%d %d %d %d]sz[%d %d]\n",
1364 i ? "dst" : "src", config->flip, config->degree,
1365 pos->x, pos->y, pos->w, pos->h,
1366 sz->hsize, sz->vsize);
1367 }
1368
1369 return -EINVAL;
1370} 974}
1371 975
1372static void fimc_clear_addr(struct fimc_context *ctx) 976static void fimc_clear_addr(struct fimc_context *ctx)
@@ -1386,10 +990,8 @@ static void fimc_clear_addr(struct fimc_context *ctx)
1386 } 990 }
1387} 991}
1388 992
1389static int fimc_ippdrv_reset(struct device *dev) 993static void fimc_reset(struct fimc_context *ctx)
1390{ 994{
1391 struct fimc_context *ctx = get_fimc_context(dev);
1392
1393 /* reset h/w block */ 995 /* reset h/w block */
1394 fimc_sw_reset(ctx); 996 fimc_sw_reset(ctx);
1395 997
@@ -1397,82 +999,26 @@ static int fimc_ippdrv_reset(struct device *dev)
1397 memset(&ctx->sc, 0x0, sizeof(ctx->sc)); 999 memset(&ctx->sc, 0x0, sizeof(ctx->sc));
1398 1000
1399 fimc_clear_addr(ctx); 1001 fimc_clear_addr(ctx);
1400
1401 return 0;
1402} 1002}
1403 1003
1404static int fimc_ippdrv_start(struct device *dev, enum drm_exynos_ipp_cmd cmd) 1004static void fimc_start(struct fimc_context *ctx)
1405{ 1005{
1406 struct fimc_context *ctx = get_fimc_context(dev);
1407 struct exynos_drm_ippdrv *ippdrv = &ctx->ippdrv;
1408 struct drm_exynos_ipp_cmd_node *c_node = ippdrv->c_node;
1409 struct drm_exynos_ipp_property *property;
1410 struct drm_exynos_ipp_config *config;
1411 struct drm_exynos_pos img_pos[EXYNOS_DRM_OPS_MAX];
1412 struct drm_exynos_ipp_set_wb set_wb;
1413 int ret, i;
1414 u32 cfg0, cfg1; 1006 u32 cfg0, cfg1;
1415 1007
1416 DRM_DEBUG_KMS("cmd[%d]\n", cmd);
1417
1418 if (!c_node) {
1419 DRM_ERROR("failed to get c_node.\n");
1420 return -EINVAL;
1421 }
1422
1423 property = &c_node->property;
1424
1425 fimc_mask_irq(ctx, true); 1008 fimc_mask_irq(ctx, true);
1426 1009
1427 for_each_ipp_ops(i) { 1010 /* If set true, we can save jpeg about screen */
1428 config = &property->config[i];
1429 img_pos[i] = config->pos;
1430 }
1431
1432 ret = fimc_set_prescaler(ctx, &ctx->sc,
1433 &img_pos[EXYNOS_DRM_OPS_SRC],
1434 &img_pos[EXYNOS_DRM_OPS_DST]);
1435 if (ret) {
1436 dev_err(dev, "failed to set prescaler.\n");
1437 return ret;
1438 }
1439
1440 /* If set ture, we can save jpeg about screen */
1441 fimc_handle_jpeg(ctx, false); 1011 fimc_handle_jpeg(ctx, false);
1442 fimc_set_scaler(ctx, &ctx->sc); 1012 fimc_set_scaler(ctx, &ctx->sc);
1443 1013
1444 switch (cmd) { 1014 fimc_set_type_ctrl(ctx);
1445 case IPP_CMD_M2M: 1015 fimc_handle_lastend(ctx, false);
1446 fimc_set_type_ctrl(ctx, FIMC_WB_NONE);
1447 fimc_handle_lastend(ctx, false);
1448
1449 /* setup dma */
1450 cfg0 = fimc_read(ctx, EXYNOS_MSCTRL);
1451 cfg0 &= ~EXYNOS_MSCTRL_INPUT_MASK;
1452 cfg0 |= EXYNOS_MSCTRL_INPUT_MEMORY;
1453 fimc_write(ctx, cfg0, EXYNOS_MSCTRL);
1454 break;
1455 case IPP_CMD_WB:
1456 fimc_set_type_ctrl(ctx, FIMC_WB_A);
1457 fimc_handle_lastend(ctx, true);
1458
1459 /* setup FIMD */
1460 ret = fimc_set_camblk_fimd0_wb(ctx);
1461 if (ret < 0) {
1462 dev_err(dev, "camblk setup failed.\n");
1463 return ret;
1464 }
1465 1016
1466 set_wb.enable = 1; 1017 /* setup dma */
1467 set_wb.refresh = property->refresh_rate; 1018 cfg0 = fimc_read(ctx, EXYNOS_MSCTRL);
1468 exynos_drm_ippnb_send_event(IPP_SET_WRITEBACK, (void *)&set_wb); 1019 cfg0 &= ~EXYNOS_MSCTRL_INPUT_MASK;
1469 break; 1020 cfg0 |= EXYNOS_MSCTRL_INPUT_MEMORY;
1470 case IPP_CMD_OUTPUT: 1021 fimc_write(ctx, cfg0, EXYNOS_MSCTRL);
1471 default:
1472 ret = -EINVAL;
1473 dev_err(dev, "invalid operations.\n");
1474 return ret;
1475 }
1476 1022
1477 /* Reset status */ 1023 /* Reset status */
1478 fimc_write(ctx, 0x0, EXYNOS_CISTATUS); 1024 fimc_write(ctx, 0x0, EXYNOS_CISTATUS);
@@ -1498,36 +1044,18 @@ static int fimc_ippdrv_start(struct device *dev, enum drm_exynos_ipp_cmd cmd)
1498 1044
1499 fimc_clear_bits(ctx, EXYNOS_CIOCTRL, EXYNOS_CIOCTRL_WEAVE_MASK); 1045 fimc_clear_bits(ctx, EXYNOS_CIOCTRL, EXYNOS_CIOCTRL_WEAVE_MASK);
1500 1046
1501 if (cmd == IPP_CMD_M2M) 1047 fimc_set_bits(ctx, EXYNOS_MSCTRL, EXYNOS_MSCTRL_ENVID);
1502 fimc_set_bits(ctx, EXYNOS_MSCTRL, EXYNOS_MSCTRL_ENVID);
1503
1504 return 0;
1505} 1048}
1506 1049
1507static void fimc_ippdrv_stop(struct device *dev, enum drm_exynos_ipp_cmd cmd) 1050static void fimc_stop(struct fimc_context *ctx)
1508{ 1051{
1509 struct fimc_context *ctx = get_fimc_context(dev);
1510 struct drm_exynos_ipp_set_wb set_wb = {0, 0};
1511 u32 cfg; 1052 u32 cfg;
1512 1053
1513 DRM_DEBUG_KMS("cmd[%d]\n", cmd); 1054 /* Source clear */
1514 1055 cfg = fimc_read(ctx, EXYNOS_MSCTRL);
1515 switch (cmd) { 1056 cfg &= ~EXYNOS_MSCTRL_INPUT_MASK;
1516 case IPP_CMD_M2M: 1057 cfg &= ~EXYNOS_MSCTRL_ENVID;
1517 /* Source clear */ 1058 fimc_write(ctx, cfg, EXYNOS_MSCTRL);
1518 cfg = fimc_read(ctx, EXYNOS_MSCTRL);
1519 cfg &= ~EXYNOS_MSCTRL_INPUT_MASK;
1520 cfg &= ~EXYNOS_MSCTRL_ENVID;
1521 fimc_write(ctx, cfg, EXYNOS_MSCTRL);
1522 break;
1523 case IPP_CMD_WB:
1524 exynos_drm_ippnb_send_event(IPP_SET_WRITEBACK, (void *)&set_wb);
1525 break;
1526 case IPP_CMD_OUTPUT:
1527 default:
1528 dev_err(dev, "invalid operations.\n");
1529 break;
1530 }
1531 1059
1532 fimc_mask_irq(ctx, false); 1060 fimc_mask_irq(ctx, false);
1533 1061
@@ -1545,6 +1073,87 @@ static void fimc_ippdrv_stop(struct device *dev, enum drm_exynos_ipp_cmd cmd)
1545 fimc_set_bits(ctx, EXYNOS_CIGCTRL, EXYNOS_CIGCTRL_IRQ_END_DISABLE); 1073 fimc_set_bits(ctx, EXYNOS_CIGCTRL, EXYNOS_CIGCTRL_IRQ_END_DISABLE);
1546} 1074}
1547 1075
1076static int fimc_commit(struct exynos_drm_ipp *ipp,
1077 struct exynos_drm_ipp_task *task)
1078{
1079 struct fimc_context *ctx =
1080 container_of(ipp, struct fimc_context, ipp);
1081
1082 pm_runtime_get_sync(ctx->dev);
1083 ctx->task = task;
1084
1085 fimc_src_set_fmt(ctx, task->src.buf.fourcc, task->src.buf.modifier);
1086 fimc_src_set_size(ctx, &task->src);
1087 fimc_src_set_transf(ctx, DRM_MODE_ROTATE_0);
1088 fimc_src_set_addr(ctx, &task->src);
1089 fimc_dst_set_fmt(ctx, task->dst.buf.fourcc, task->dst.buf.modifier);
1090 fimc_dst_set_transf(ctx, task->transform.rotation);
1091 fimc_dst_set_size(ctx, &task->dst);
1092 fimc_dst_set_addr(ctx, &task->dst);
1093 fimc_set_prescaler(ctx, &ctx->sc, &task->src.rect, &task->dst.rect);
1094 fimc_start(ctx);
1095
1096 return 0;
1097}
1098
1099static void fimc_abort(struct exynos_drm_ipp *ipp,
1100 struct exynos_drm_ipp_task *task)
1101{
1102 struct fimc_context *ctx =
1103 container_of(ipp, struct fimc_context, ipp);
1104
1105 fimc_reset(ctx);
1106
1107 if (ctx->task) {
1108 struct exynos_drm_ipp_task *task = ctx->task;
1109
1110 ctx->task = NULL;
1111 pm_runtime_mark_last_busy(ctx->dev);
1112 pm_runtime_put_autosuspend(ctx->dev);
1113 exynos_drm_ipp_task_done(task, -EIO);
1114 }
1115}
1116
1117static struct exynos_drm_ipp_funcs ipp_funcs = {
1118 .commit = fimc_commit,
1119 .abort = fimc_abort,
1120};
1121
1122static int fimc_bind(struct device *dev, struct device *master, void *data)
1123{
1124 struct fimc_context *ctx = dev_get_drvdata(dev);
1125 struct drm_device *drm_dev = data;
1126 struct exynos_drm_ipp *ipp = &ctx->ipp;
1127
1128 ctx->drm_dev = drm_dev;
1129 drm_iommu_attach_device(drm_dev, dev);
1130
1131 exynos_drm_ipp_register(drm_dev, ipp, &ipp_funcs,
1132 DRM_EXYNOS_IPP_CAP_CROP | DRM_EXYNOS_IPP_CAP_ROTATE |
1133 DRM_EXYNOS_IPP_CAP_SCALE | DRM_EXYNOS_IPP_CAP_CONVERT,
1134 ctx->formats, ctx->num_formats, "fimc");
1135
1136 dev_info(dev, "The exynos fimc has been probed successfully\n");
1137
1138 return 0;
1139}
1140
1141static void fimc_unbind(struct device *dev, struct device *master,
1142 void *data)
1143{
1144 struct fimc_context *ctx = dev_get_drvdata(dev);
1145 struct drm_device *drm_dev = data;
1146 struct exynos_drm_ipp *ipp = &ctx->ipp;
1147
1148 exynos_drm_ipp_unregister(drm_dev, ipp);
1149 drm_iommu_detach_device(drm_dev, dev);
1150}
1151
1152static const struct component_ops fimc_component_ops = {
1153 .bind = fimc_bind,
1154 .unbind = fimc_unbind,
1155};
1156
1548static void fimc_put_clocks(struct fimc_context *ctx) 1157static void fimc_put_clocks(struct fimc_context *ctx)
1549{ 1158{
1550 int i; 1159 int i;
@@ -1559,7 +1168,7 @@ static void fimc_put_clocks(struct fimc_context *ctx)
1559 1168
1560static int fimc_setup_clocks(struct fimc_context *ctx) 1169static int fimc_setup_clocks(struct fimc_context *ctx)
1561{ 1170{
1562 struct device *fimc_dev = ctx->ippdrv.dev; 1171 struct device *fimc_dev = ctx->dev;
1563 struct device *dev; 1172 struct device *dev;
1564 int ret, i; 1173 int ret, i;
1565 1174
@@ -1574,8 +1183,6 @@ static int fimc_setup_clocks(struct fimc_context *ctx)
1574 1183
1575 ctx->clocks[i] = clk_get(dev, fimc_clock_names[i]); 1184 ctx->clocks[i] = clk_get(dev, fimc_clock_names[i]);
1576 if (IS_ERR(ctx->clocks[i])) { 1185 if (IS_ERR(ctx->clocks[i])) {
1577 if (i >= FIMC_CLK_MUX)
1578 break;
1579 ret = PTR_ERR(ctx->clocks[i]); 1186 ret = PTR_ERR(ctx->clocks[i]);
1580 dev_err(fimc_dev, "failed to get clock: %s\n", 1187 dev_err(fimc_dev, "failed to get clock: %s\n",
1581 fimc_clock_names[i]); 1188 fimc_clock_names[i]);
@@ -1583,20 +1190,6 @@ static int fimc_setup_clocks(struct fimc_context *ctx)
1583 } 1190 }
1584 } 1191 }
1585 1192
1586 /* Optional FIMC LCLK parent clock setting */
1587 if (!IS_ERR(ctx->clocks[FIMC_CLK_PARENT])) {
1588 ret = clk_set_parent(ctx->clocks[FIMC_CLK_MUX],
1589 ctx->clocks[FIMC_CLK_PARENT]);
1590 if (ret < 0) {
1591 dev_err(fimc_dev, "failed to set parent.\n");
1592 goto e_clk_free;
1593 }
1594 }
1595
1596 ret = clk_set_rate(ctx->clocks[FIMC_CLK_LCLK], ctx->clk_frequency);
1597 if (ret < 0)
1598 goto e_clk_free;
1599
1600 ret = clk_prepare_enable(ctx->clocks[FIMC_CLK_LCLK]); 1193 ret = clk_prepare_enable(ctx->clocks[FIMC_CLK_LCLK]);
1601 if (!ret) 1194 if (!ret)
1602 return ret; 1195 return ret;
@@ -1605,57 +1198,118 @@ e_clk_free:
1605 return ret; 1198 return ret;
1606} 1199}
1607 1200
1608static int fimc_parse_dt(struct fimc_context *ctx) 1201int exynos_drm_check_fimc_device(struct device *dev)
1609{ 1202{
1610 struct device_node *node = ctx->ippdrv.dev->of_node; 1203 unsigned int id = of_alias_get_id(dev->of_node, "fimc");
1611 1204
1612 /* Handle only devices that support the LCD Writeback data path */ 1205 if (id >= 0 && (BIT(id) & fimc_mask))
1613 if (!of_property_read_bool(node, "samsung,lcd-wb")) 1206 return 0;
1614 return -ENODEV; 1207 return -ENODEV;
1208}
1615 1209
1616 if (of_property_read_u32(node, "clock-frequency", 1210static const unsigned int fimc_formats[] = {
1617 &ctx->clk_frequency)) 1211 DRM_FORMAT_XRGB8888, DRM_FORMAT_RGB565,
1618 ctx->clk_frequency = FIMC_DEFAULT_LCLK_FREQUENCY; 1212 DRM_FORMAT_NV12, DRM_FORMAT_NV16, DRM_FORMAT_NV21, DRM_FORMAT_NV61,
1213 DRM_FORMAT_UYVY, DRM_FORMAT_VYUY, DRM_FORMAT_YUYV, DRM_FORMAT_YVYU,
1214 DRM_FORMAT_YUV420, DRM_FORMAT_YVU420, DRM_FORMAT_YUV422,
1215 DRM_FORMAT_YUV444,
1216};
1619 1217
1620 ctx->id = of_alias_get_id(node, "fimc"); 1218static const unsigned int fimc_tiled_formats[] = {
1219 DRM_FORMAT_NV12, DRM_FORMAT_NV21,
1220};
1621 1221
1622 if (ctx->id < 0) { 1222static const struct drm_exynos_ipp_limit fimc_4210_limits_v1[] = {
1623 dev_err(ctx->ippdrv.dev, "failed to get node alias id.\n"); 1223 { IPP_SIZE_LIMIT(BUFFER, .h = { 16, 8192, 8 }, .v = { 16, 8192, 2 }) },
1624 return -EINVAL; 1224 { IPP_SIZE_LIMIT(AREA, .h = { 16, 4224, 2 }, .v = { 16, 0, 2 }) },
1625 } 1225 { IPP_SIZE_LIMIT(ROTATED, .h = { 128, 1920 }, .v = { 128, 0 }) },
1226 { IPP_SCALE_LIMIT(.h = { (1 << 16) / 64, (1 << 16) * 64 },
1227 .v = { (1 << 16) / 64, (1 << 16) * 64 }) },
1228};
1626 1229
1627 return 0; 1230static const struct drm_exynos_ipp_limit fimc_4210_limits_v2[] = {
1628} 1231 { IPP_SIZE_LIMIT(BUFFER, .h = { 16, 8192, 8 }, .v = { 16, 8192, 2 }) },
1232 { IPP_SIZE_LIMIT(AREA, .h = { 16, 1920, 2 }, .v = { 16, 0, 2 }) },
1233 { IPP_SIZE_LIMIT(ROTATED, .h = { 128, 1366 }, .v = { 128, 0 }) },
1234 { IPP_SCALE_LIMIT(.h = { (1 << 16) / 64, (1 << 16) * 64 },
1235 .v = { (1 << 16) / 64, (1 << 16) * 64 }) },
1236};
1237
1238static const struct drm_exynos_ipp_limit fimc_4210_limits_tiled_v1[] = {
1239 { IPP_SIZE_LIMIT(BUFFER, .h = { 128, 1920, 128 }, .v = { 32, 1920, 32 }) },
1240 { IPP_SIZE_LIMIT(AREA, .h = { 128, 1920, 2 }, .v = { 128, 0, 2 }) },
1241 { IPP_SCALE_LIMIT(.h = { (1 << 16) / 64, (1 << 16) * 64 },
1242 .v = { (1 << 16) / 64, (1 << 16) * 64 }) },
1243};
1244
1245static const struct drm_exynos_ipp_limit fimc_4210_limits_tiled_v2[] = {
1246 { IPP_SIZE_LIMIT(BUFFER, .h = { 128, 1920, 128 }, .v = { 32, 1920, 32 }) },
1247 { IPP_SIZE_LIMIT(AREA, .h = { 128, 1366, 2 }, .v = { 128, 0, 2 }) },
1248 { IPP_SCALE_LIMIT(.h = { (1 << 16) / 64, (1 << 16) * 64 },
1249 .v = { (1 << 16) / 64, (1 << 16) * 64 }) },
1250};
1629 1251
1630static int fimc_probe(struct platform_device *pdev) 1252static int fimc_probe(struct platform_device *pdev)
1631{ 1253{
1254 const struct drm_exynos_ipp_limit *limits;
1255 struct exynos_drm_ipp_formats *formats;
1632 struct device *dev = &pdev->dev; 1256 struct device *dev = &pdev->dev;
1633 struct fimc_context *ctx; 1257 struct fimc_context *ctx;
1634 struct resource *res; 1258 struct resource *res;
1635 struct exynos_drm_ippdrv *ippdrv;
1636 int ret; 1259 int ret;
1260 int i, j, num_limits, num_formats;
1637 1261
1638 if (!dev->of_node) { 1262 if (exynos_drm_check_fimc_device(dev) != 0)
1639 dev_err(dev, "device tree node not found.\n");
1640 return -ENODEV; 1263 return -ENODEV;
1641 }
1642 1264
1643 ctx = devm_kzalloc(dev, sizeof(*ctx), GFP_KERNEL); 1265 ctx = devm_kzalloc(dev, sizeof(*ctx), GFP_KERNEL);
1644 if (!ctx) 1266 if (!ctx)
1645 return -ENOMEM; 1267 return -ENOMEM;
1646 1268
1647 ctx->ippdrv.dev = dev; 1269 ctx->dev = dev;
1270 ctx->id = of_alias_get_id(dev->of_node, "fimc");
1648 1271
1649 ret = fimc_parse_dt(ctx); 1272 /* construct formats/limits array */
1650 if (ret < 0) 1273 num_formats = ARRAY_SIZE(fimc_formats) + ARRAY_SIZE(fimc_tiled_formats);
1651 return ret; 1274 formats = devm_kzalloc(dev, sizeof(*formats) * num_formats, GFP_KERNEL);
1275 if (!formats)
1276 return -ENOMEM;
1277
1278 /* linear formats */
1279 if (ctx->id < 3) {
1280 limits = fimc_4210_limits_v1;
1281 num_limits = ARRAY_SIZE(fimc_4210_limits_v1);
1282 } else {
1283 limits = fimc_4210_limits_v2;
1284 num_limits = ARRAY_SIZE(fimc_4210_limits_v2);
1285 }
1286 for (i = 0; i < ARRAY_SIZE(fimc_formats); i++) {
1287 formats[i].fourcc = fimc_formats[i];
1288 formats[i].type = DRM_EXYNOS_IPP_FORMAT_SOURCE |
1289 DRM_EXYNOS_IPP_FORMAT_DESTINATION;
1290 formats[i].limits = limits;
1291 formats[i].num_limits = num_limits;
1292 }
1652 1293
1653 ctx->sysreg = syscon_regmap_lookup_by_phandle(dev->of_node, 1294 /* tiled formats */
1654 "samsung,sysreg"); 1295 if (ctx->id < 3) {
1655 if (IS_ERR(ctx->sysreg)) { 1296 limits = fimc_4210_limits_tiled_v1;
1656 dev_err(dev, "syscon regmap lookup failed.\n"); 1297 num_limits = ARRAY_SIZE(fimc_4210_limits_tiled_v1);
1657 return PTR_ERR(ctx->sysreg); 1298 } else {
1299 limits = fimc_4210_limits_tiled_v2;
1300 num_limits = ARRAY_SIZE(fimc_4210_limits_tiled_v2);
1658 } 1301 }
1302 for (j = i, i = 0; i < ARRAY_SIZE(fimc_tiled_formats); j++, i++) {
1303 formats[j].fourcc = fimc_tiled_formats[i];
1304 formats[j].modifier = DRM_FORMAT_MOD_SAMSUNG_64_32_TILE;
1305 formats[j].type = DRM_EXYNOS_IPP_FORMAT_SOURCE |
1306 DRM_EXYNOS_IPP_FORMAT_DESTINATION;
1307 formats[j].limits = limits;
1308 formats[j].num_limits = num_limits;
1309 }
1310
1311 ctx->formats = formats;
1312 ctx->num_formats = num_formats;
1659 1313
1660 /* resource memory */ 1314 /* resource memory */
1661 ctx->regs_res = platform_get_resource(pdev, IORESOURCE_MEM, 0); 1315 ctx->regs_res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
@@ -1670,9 +1324,8 @@ static int fimc_probe(struct platform_device *pdev)
1670 return -ENOENT; 1324 return -ENOENT;
1671 } 1325 }
1672 1326
1673 ctx->irq = res->start; 1327 ret = devm_request_irq(dev, res->start, fimc_irq_handler,
1674 ret = devm_request_threaded_irq(dev, ctx->irq, NULL, fimc_irq_handler, 1328 0, dev_name(dev), ctx);
1675 IRQF_ONESHOT, "drm_fimc", ctx);
1676 if (ret < 0) { 1329 if (ret < 0) {
1677 dev_err(dev, "failed to request irq.\n"); 1330 dev_err(dev, "failed to request irq.\n");
1678 return ret; 1331 return ret;
@@ -1682,39 +1335,24 @@ static int fimc_probe(struct platform_device *pdev)
1682 if (ret < 0) 1335 if (ret < 0)
1683 return ret; 1336 return ret;
1684 1337
1685 ippdrv = &ctx->ippdrv;
1686 ippdrv->ops[EXYNOS_DRM_OPS_SRC] = &fimc_src_ops;
1687 ippdrv->ops[EXYNOS_DRM_OPS_DST] = &fimc_dst_ops;
1688 ippdrv->check_property = fimc_ippdrv_check_property;
1689 ippdrv->reset = fimc_ippdrv_reset;
1690 ippdrv->start = fimc_ippdrv_start;
1691 ippdrv->stop = fimc_ippdrv_stop;
1692 ret = fimc_init_prop_list(ippdrv);
1693 if (ret < 0) {
1694 dev_err(dev, "failed to init property list.\n");
1695 goto err_put_clk;
1696 }
1697
1698 DRM_DEBUG_KMS("id[%d]ippdrv[%pK]\n", ctx->id, ippdrv);
1699
1700 spin_lock_init(&ctx->lock); 1338 spin_lock_init(&ctx->lock);
1701 platform_set_drvdata(pdev, ctx); 1339 platform_set_drvdata(pdev, ctx);
1702 1340
1341 pm_runtime_use_autosuspend(dev);
1342 pm_runtime_set_autosuspend_delay(dev, FIMC_AUTOSUSPEND_DELAY);
1703 pm_runtime_enable(dev); 1343 pm_runtime_enable(dev);
1704 1344
1705 ret = exynos_drm_ippdrv_register(ippdrv); 1345 ret = component_add(dev, &fimc_component_ops);
1706 if (ret < 0) { 1346 if (ret)
1707 dev_err(dev, "failed to register drm fimc device.\n");
1708 goto err_pm_dis; 1347 goto err_pm_dis;
1709 }
1710 1348
1711 dev_info(dev, "drm fimc registered successfully.\n"); 1349 dev_info(dev, "drm fimc registered successfully.\n");
1712 1350
1713 return 0; 1351 return 0;
1714 1352
1715err_pm_dis: 1353err_pm_dis:
1354 pm_runtime_dont_use_autosuspend(dev);
1716 pm_runtime_disable(dev); 1355 pm_runtime_disable(dev);
1717err_put_clk:
1718 fimc_put_clocks(ctx); 1356 fimc_put_clocks(ctx);
1719 1357
1720 return ret; 1358 return ret;
@@ -1724,42 +1362,24 @@ static int fimc_remove(struct platform_device *pdev)
1724{ 1362{
1725 struct device *dev = &pdev->dev; 1363 struct device *dev = &pdev->dev;
1726 struct fimc_context *ctx = get_fimc_context(dev); 1364 struct fimc_context *ctx = get_fimc_context(dev);
1727 struct exynos_drm_ippdrv *ippdrv = &ctx->ippdrv;
1728 1365
1729 exynos_drm_ippdrv_unregister(ippdrv); 1366 component_del(dev, &fimc_component_ops);
1367 pm_runtime_dont_use_autosuspend(dev);
1368 pm_runtime_disable(dev);
1730 1369
1731 fimc_put_clocks(ctx); 1370 fimc_put_clocks(ctx);
1732 pm_runtime_set_suspended(dev);
1733 pm_runtime_disable(dev);
1734 1371
1735 return 0; 1372 return 0;
1736} 1373}
1737 1374
1738#ifdef CONFIG_PM 1375#ifdef CONFIG_PM
1739static int fimc_clk_ctrl(struct fimc_context *ctx, bool enable)
1740{
1741 DRM_DEBUG_KMS("enable[%d]\n", enable);
1742
1743 if (enable) {
1744 clk_prepare_enable(ctx->clocks[FIMC_CLK_GATE]);
1745 clk_prepare_enable(ctx->clocks[FIMC_CLK_WB_A]);
1746 ctx->suspended = false;
1747 } else {
1748 clk_disable_unprepare(ctx->clocks[FIMC_CLK_GATE]);
1749 clk_disable_unprepare(ctx->clocks[FIMC_CLK_WB_A]);
1750 ctx->suspended = true;
1751 }
1752
1753 return 0;
1754}
1755
1756static int fimc_runtime_suspend(struct device *dev) 1376static int fimc_runtime_suspend(struct device *dev)
1757{ 1377{
1758 struct fimc_context *ctx = get_fimc_context(dev); 1378 struct fimc_context *ctx = get_fimc_context(dev);
1759 1379
1760 DRM_DEBUG_KMS("id[%d]\n", ctx->id); 1380 DRM_DEBUG_KMS("id[%d]\n", ctx->id);
1761 1381 clk_disable_unprepare(ctx->clocks[FIMC_CLK_GATE]);
1762 return fimc_clk_ctrl(ctx, false); 1382 return 0;
1763} 1383}
1764 1384
1765static int fimc_runtime_resume(struct device *dev) 1385static int fimc_runtime_resume(struct device *dev)
@@ -1767,8 +1387,7 @@ static int fimc_runtime_resume(struct device *dev)
1767 struct fimc_context *ctx = get_fimc_context(dev); 1387 struct fimc_context *ctx = get_fimc_context(dev);
1768 1388
1769 DRM_DEBUG_KMS("id[%d]\n", ctx->id); 1389 DRM_DEBUG_KMS("id[%d]\n", ctx->id);
1770 1390 return clk_prepare_enable(ctx->clocks[FIMC_CLK_GATE]);
1771 return fimc_clk_ctrl(ctx, true);
1772} 1391}
1773#endif 1392#endif
1774 1393
@@ -1795,4 +1414,3 @@ struct platform_driver fimc_driver = {
1795 .pm = &fimc_pm_ops, 1414 .pm = &fimc_pm_ops,
1796 }, 1415 },
1797}; 1416};
1798
diff --git a/drivers/gpu/drm/exynos/exynos_drm_fimc.h b/drivers/gpu/drm/exynos/exynos_drm_fimc.h
deleted file mode 100644
index 127a424c5fdf..000000000000
--- a/drivers/gpu/drm/exynos/exynos_drm_fimc.h
+++ /dev/null
@@ -1,23 +0,0 @@
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 * This program is free software; you can redistribute it and/or modify it
10 * under the terms of the GNU General Public License as published by the
11 * Free Software Foundation; either version 2 of the License, or (at your
12 * option) any later version.
13 */
14
15#ifndef _EXYNOS_DRM_FIMC_H_
16#define _EXYNOS_DRM_FIMC_H_
17
18/*
19 * TODO
20 * FIMD output interface notifier callback.
21 */
22
23#endif /* _EXYNOS_DRM_FIMC_H_ */