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