2 * Copyright (C) 2012 Samsung Electronics Co.Ltd
4 * Eunchul Kim <chulspro.kim@samsung.com>
5 * Jinyoung Jeon <jy0.jeon@samsung.com>
6 * Sangmin Lee <lsmin.lee@samsung.com>
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.
14 #include <linux/kernel.h>
15 #include <linux/module.h>
16 #include <linux/platform_device.h>
17 #include <linux/mfd/syscon.h>
18 #include <linux/regmap.h>
19 #include <linux/clk.h>
20 #include <linux/pm_runtime.h>
23 #include <drm/exynos_drm.h>
24 #include "regs-fimc.h"
25 #include "exynos_drm_ipp.h"
26 #include "exynos_drm_fimc.h"
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.
35 * M2M operation : supports crop/scale/rotation/csc so on.
36 * Memory ----> FIMC H/W ----> Memory.
37 * Writeback operation : supports cloned screen with FIMD.
38 * FIMD ----> FIMC H/W ----> Memory.
39 * Output operation : supports direct display using local path.
40 * Memory ----> FIMC H/W ----> FIMD.
45 * 1. check suspend/resume api if needed.
46 * 2. need to check use case platform_device_id.
47 * 3. check src/dst size with, height.
48 * 4. added check_prepare api for right register.
49 * 5. need to add supported list in prop_list.
50 * 6. check prescaler/scaler optimization.
53 #define FIMC_MAX_DEVS 4
54 #define FIMC_MAX_SRC 2
55 #define FIMC_MAX_DST 32
56 #define FIMC_SHFACTOR 10
57 #define FIMC_BUF_STOP 1
58 #define FIMC_BUF_START 2
59 #define FIMC_REG_SZ 32
60 #define FIMC_WIDTH_ITU_709 1280
61 #define FIMC_REFRESH_MAX 60
62 #define FIMC_REFRESH_MIN 12
63 #define FIMC_CROP_MAX 8192
64 #define FIMC_CROP_MIN 32
65 #define FIMC_SCALE_MAX 4224
66 #define FIMC_SCALE_MIN 32
68 #define get_fimc_context(dev) platform_get_drvdata(to_platform_device(dev))
69 #define get_ctx_from_ippdrv(ippdrv) container_of(ippdrv,\
70 struct fimc_context, ippdrv);
71 #define fimc_read(offset) readl(ctx->regs + (offset))
72 #define fimc_write(cfg, offset) writel(cfg, ctx->regs + (offset))
90 static const char * const fimc_clock_names
[] = {
91 [FIMC_CLK_LCLK
] = "sclk_fimc",
92 [FIMC_CLK_GATE
] = "fimc",
93 [FIMC_CLK_WB_A
] = "pxl_async0",
94 [FIMC_CLK_WB_B
] = "pxl_async1",
95 [FIMC_CLK_MUX
] = "mux",
96 [FIMC_CLK_PARENT
] = "parent",
99 #define FIMC_DEFAULT_LCLK_FREQUENCY 133000000UL
102 * A structure of scaler.
104 * @range: narrow, wide.
105 * @bypass: unused scaler path.
106 * @up_h: horizontal scale up.
107 * @up_v: vertical scale up.
108 * @hratio: horizontal ratio.
109 * @vratio: vertical ratio.
121 * A structure of scaler capability.
123 * find user manual table 43-1.
124 * @in_hori: scaler input horizontal size.
125 * @bypass: scaler bypass mode.
126 * @dst_h_wo_rot: target horizontal size without output rotation.
127 * @dst_h_rot: target horizontal size with output rotation.
128 * @rl_w_wo_rot: real width without input rotation.
129 * @rl_h_rot: real height without output rotation.
131 struct fimc_capability
{
144 * A structure of fimc context.
146 * @ippdrv: prepare initialization using ippdrv.
147 * @regs_res: register resources.
148 * @regs: memory mapped io registers.
149 * @lock: locking of operations.
150 * @clocks: fimc clocks.
151 * @clk_frequency: LCLK clock frequency.
152 * @sysreg: handle to SYSREG block regmap.
153 * @sc: scaler infomations.
154 * @pol: porarity of writeback.
157 * @suspended: qos operations.
159 struct fimc_context
{
160 struct exynos_drm_ippdrv ippdrv
;
161 struct resource
*regs_res
;
164 struct clk
*clocks
[FIMC_CLKS_MAX
];
166 struct regmap
*sysreg
;
167 struct fimc_scaler sc
;
168 struct exynos_drm_ipp_pol pol
;
174 static void fimc_sw_reset(struct fimc_context
*ctx
)
178 DRM_DEBUG_KMS("%s\n", __func__
);
180 /* stop dma operation */
181 cfg
= fimc_read(EXYNOS_CISTATUS
);
182 if (EXYNOS_CISTATUS_GET_ENVID_STATUS(cfg
)) {
183 cfg
= fimc_read(EXYNOS_MSCTRL
);
184 cfg
&= ~EXYNOS_MSCTRL_ENVID
;
185 fimc_write(cfg
, EXYNOS_MSCTRL
);
188 cfg
= fimc_read(EXYNOS_CISRCFMT
);
189 cfg
|= EXYNOS_CISRCFMT_ITU601_8BIT
;
190 fimc_write(cfg
, EXYNOS_CISRCFMT
);
192 /* disable image capture */
193 cfg
= fimc_read(EXYNOS_CIIMGCPT
);
194 cfg
&= ~(EXYNOS_CIIMGCPT_IMGCPTEN_SC
| EXYNOS_CIIMGCPT_IMGCPTEN
);
195 fimc_write(cfg
, EXYNOS_CIIMGCPT
);
198 cfg
= fimc_read(EXYNOS_CIGCTRL
);
199 cfg
|= (EXYNOS_CIGCTRL_SWRST
);
200 fimc_write(cfg
, EXYNOS_CIGCTRL
);
202 /* s/w reset complete */
203 cfg
= fimc_read(EXYNOS_CIGCTRL
);
204 cfg
&= ~EXYNOS_CIGCTRL_SWRST
;
205 fimc_write(cfg
, EXYNOS_CIGCTRL
);
208 fimc_write(0x0, EXYNOS_CIFCNTSEQ
);
211 static int fimc_set_camblk_fimd0_wb(struct fimc_context
*ctx
)
213 DRM_DEBUG_KMS("%s\n", __func__
);
215 return regmap_update_bits(ctx
->sysreg
, SYSREG_CAMERA_BLK
,
216 SYSREG_FIMD0WB_DEST_MASK
,
217 ctx
->id
<< SYSREG_FIMD0WB_DEST_SHIFT
);
220 static void fimc_set_type_ctrl(struct fimc_context
*ctx
, enum fimc_wb wb
)
224 DRM_DEBUG_KMS("%s:wb[%d]\n", __func__
, wb
);
226 cfg
= fimc_read(EXYNOS_CIGCTRL
);
227 cfg
&= ~(EXYNOS_CIGCTRL_TESTPATTERN_MASK
|
228 EXYNOS_CIGCTRL_SELCAM_ITU_MASK
|
229 EXYNOS_CIGCTRL_SELCAM_MIPI_MASK
|
230 EXYNOS_CIGCTRL_SELCAM_FIMC_MASK
|
231 EXYNOS_CIGCTRL_SELWB_CAMIF_MASK
|
232 EXYNOS_CIGCTRL_SELWRITEBACK_MASK
);
236 cfg
|= (EXYNOS_CIGCTRL_SELWRITEBACK_A
|
237 EXYNOS_CIGCTRL_SELWB_CAMIF_WRITEBACK
);
240 cfg
|= (EXYNOS_CIGCTRL_SELWRITEBACK_B
|
241 EXYNOS_CIGCTRL_SELWB_CAMIF_WRITEBACK
);
245 cfg
|= (EXYNOS_CIGCTRL_SELCAM_ITU_A
|
246 EXYNOS_CIGCTRL_SELWRITEBACK_A
|
247 EXYNOS_CIGCTRL_SELCAM_MIPI_A
|
248 EXYNOS_CIGCTRL_SELCAM_FIMC_ITU
);
252 fimc_write(cfg
, EXYNOS_CIGCTRL
);
255 static void fimc_set_polarity(struct fimc_context
*ctx
,
256 struct exynos_drm_ipp_pol
*pol
)
260 DRM_DEBUG_KMS("%s:inv_pclk[%d]inv_vsync[%d]\n",
261 __func__
, pol
->inv_pclk
, pol
->inv_vsync
);
262 DRM_DEBUG_KMS("%s:inv_href[%d]inv_hsync[%d]\n",
263 __func__
, pol
->inv_href
, pol
->inv_hsync
);
265 cfg
= fimc_read(EXYNOS_CIGCTRL
);
266 cfg
&= ~(EXYNOS_CIGCTRL_INVPOLPCLK
| EXYNOS_CIGCTRL_INVPOLVSYNC
|
267 EXYNOS_CIGCTRL_INVPOLHREF
| EXYNOS_CIGCTRL_INVPOLHSYNC
);
270 cfg
|= EXYNOS_CIGCTRL_INVPOLPCLK
;
272 cfg
|= EXYNOS_CIGCTRL_INVPOLVSYNC
;
274 cfg
|= EXYNOS_CIGCTRL_INVPOLHREF
;
276 cfg
|= EXYNOS_CIGCTRL_INVPOLHSYNC
;
278 fimc_write(cfg
, EXYNOS_CIGCTRL
);
281 static void fimc_handle_jpeg(struct fimc_context
*ctx
, bool enable
)
285 DRM_DEBUG_KMS("%s:enable[%d]\n", __func__
, enable
);
287 cfg
= fimc_read(EXYNOS_CIGCTRL
);
289 cfg
|= EXYNOS_CIGCTRL_CAM_JPEG
;
291 cfg
&= ~EXYNOS_CIGCTRL_CAM_JPEG
;
293 fimc_write(cfg
, EXYNOS_CIGCTRL
);
296 static void fimc_handle_irq(struct fimc_context
*ctx
, bool enable
,
297 bool overflow
, bool level
)
301 DRM_DEBUG_KMS("%s:enable[%d]overflow[%d]level[%d]\n", __func__
,
302 enable
, overflow
, level
);
304 cfg
= fimc_read(EXYNOS_CIGCTRL
);
306 cfg
&= ~(EXYNOS_CIGCTRL_IRQ_OVFEN
| EXYNOS_CIGCTRL_IRQ_LEVEL
);
307 cfg
|= EXYNOS_CIGCTRL_IRQ_ENABLE
;
309 cfg
|= EXYNOS_CIGCTRL_IRQ_OVFEN
;
311 cfg
|= EXYNOS_CIGCTRL_IRQ_LEVEL
;
313 cfg
&= ~(EXYNOS_CIGCTRL_IRQ_OVFEN
| EXYNOS_CIGCTRL_IRQ_ENABLE
);
315 fimc_write(cfg
, EXYNOS_CIGCTRL
);
318 static void fimc_clear_irq(struct fimc_context
*ctx
)
322 DRM_DEBUG_KMS("%s\n", __func__
);
324 cfg
= fimc_read(EXYNOS_CIGCTRL
);
325 cfg
|= EXYNOS_CIGCTRL_IRQ_CLR
;
326 fimc_write(cfg
, EXYNOS_CIGCTRL
);
329 static bool fimc_check_ovf(struct fimc_context
*ctx
)
331 struct exynos_drm_ippdrv
*ippdrv
= &ctx
->ippdrv
;
332 u32 cfg
, status
, flag
;
334 status
= fimc_read(EXYNOS_CISTATUS
);
335 flag
= EXYNOS_CISTATUS_OVFIY
| EXYNOS_CISTATUS_OVFICB
|
336 EXYNOS_CISTATUS_OVFICR
;
338 DRM_DEBUG_KMS("%s:flag[0x%x]\n", __func__
, flag
);
341 cfg
= fimc_read(EXYNOS_CIWDOFST
);
342 cfg
|= (EXYNOS_CIWDOFST_CLROVFIY
| EXYNOS_CIWDOFST_CLROVFICB
|
343 EXYNOS_CIWDOFST_CLROVFICR
);
345 fimc_write(cfg
, EXYNOS_CIWDOFST
);
347 cfg
= fimc_read(EXYNOS_CIWDOFST
);
348 cfg
&= ~(EXYNOS_CIWDOFST_CLROVFIY
| EXYNOS_CIWDOFST_CLROVFICB
|
349 EXYNOS_CIWDOFST_CLROVFICR
);
351 fimc_write(cfg
, EXYNOS_CIWDOFST
);
353 dev_err(ippdrv
->dev
, "occured overflow at %d, status 0x%x.\n",
361 static bool fimc_check_frame_end(struct fimc_context
*ctx
)
365 cfg
= fimc_read(EXYNOS_CISTATUS
);
367 DRM_DEBUG_KMS("%s:cfg[0x%x]\n", __func__
, cfg
);
369 if (!(cfg
& EXYNOS_CISTATUS_FRAMEEND
))
372 cfg
&= ~(EXYNOS_CISTATUS_FRAMEEND
);
373 fimc_write(cfg
, EXYNOS_CISTATUS
);
378 static int fimc_get_buf_id(struct fimc_context
*ctx
)
381 int frame_cnt
, buf_id
;
383 DRM_DEBUG_KMS("%s\n", __func__
);
385 cfg
= fimc_read(EXYNOS_CISTATUS2
);
386 frame_cnt
= EXYNOS_CISTATUS2_GET_FRAMECOUNT_BEFORE(cfg
);
389 frame_cnt
= EXYNOS_CISTATUS2_GET_FRAMECOUNT_PRESENT(cfg
);
391 DRM_DEBUG_KMS("%s:present[%d]before[%d]\n", __func__
,
392 EXYNOS_CISTATUS2_GET_FRAMECOUNT_PRESENT(cfg
),
393 EXYNOS_CISTATUS2_GET_FRAMECOUNT_BEFORE(cfg
));
395 if (frame_cnt
== 0) {
396 DRM_ERROR("failed to get frame count.\n");
400 buf_id
= frame_cnt
- 1;
401 DRM_DEBUG_KMS("%s:buf_id[%d]\n", __func__
, buf_id
);
406 static void fimc_handle_lastend(struct fimc_context
*ctx
, bool enable
)
410 DRM_DEBUG_KMS("%s:enable[%d]\n", __func__
, enable
);
412 cfg
= fimc_read(EXYNOS_CIOCTRL
);
414 cfg
|= EXYNOS_CIOCTRL_LASTENDEN
;
416 cfg
&= ~EXYNOS_CIOCTRL_LASTENDEN
;
418 fimc_write(cfg
, EXYNOS_CIOCTRL
);
422 static int fimc_src_set_fmt_order(struct fimc_context
*ctx
, u32 fmt
)
424 struct exynos_drm_ippdrv
*ippdrv
= &ctx
->ippdrv
;
427 DRM_DEBUG_KMS("%s:fmt[0x%x]\n", __func__
, fmt
);
430 cfg
= fimc_read(EXYNOS_CISCCTRL
);
431 cfg
&= ~EXYNOS_CISCCTRL_INRGB_FMT_RGB_MASK
;
434 case DRM_FORMAT_RGB565
:
435 cfg
|= EXYNOS_CISCCTRL_INRGB_FMT_RGB565
;
436 fimc_write(cfg
, EXYNOS_CISCCTRL
);
438 case DRM_FORMAT_RGB888
:
439 case DRM_FORMAT_XRGB8888
:
440 cfg
|= EXYNOS_CISCCTRL_INRGB_FMT_RGB888
;
441 fimc_write(cfg
, EXYNOS_CISCCTRL
);
449 cfg
= fimc_read(EXYNOS_MSCTRL
);
450 cfg
&= ~(EXYNOS_MSCTRL_ORDER2P_SHIFT_MASK
|
451 EXYNOS_MSCTRL_C_INT_IN_2PLANE
|
452 EXYNOS_MSCTRL_ORDER422_YCBYCR
);
455 case DRM_FORMAT_YUYV
:
456 cfg
|= EXYNOS_MSCTRL_ORDER422_YCBYCR
;
458 case DRM_FORMAT_YVYU
:
459 cfg
|= EXYNOS_MSCTRL_ORDER422_YCRYCB
;
461 case DRM_FORMAT_UYVY
:
462 cfg
|= EXYNOS_MSCTRL_ORDER422_CBYCRY
;
464 case DRM_FORMAT_VYUY
:
465 case DRM_FORMAT_YUV444
:
466 cfg
|= EXYNOS_MSCTRL_ORDER422_CRYCBY
;
468 case DRM_FORMAT_NV21
:
469 case DRM_FORMAT_NV61
:
470 cfg
|= (EXYNOS_MSCTRL_ORDER2P_LSB_CRCB
|
471 EXYNOS_MSCTRL_C_INT_IN_2PLANE
);
473 case DRM_FORMAT_YUV422
:
474 case DRM_FORMAT_YUV420
:
475 case DRM_FORMAT_YVU420
:
476 cfg
|= EXYNOS_MSCTRL_C_INT_IN_3PLANE
;
478 case DRM_FORMAT_NV12
:
479 case DRM_FORMAT_NV12MT
:
480 case DRM_FORMAT_NV16
:
481 cfg
|= (EXYNOS_MSCTRL_ORDER2P_LSB_CBCR
|
482 EXYNOS_MSCTRL_C_INT_IN_2PLANE
);
485 dev_err(ippdrv
->dev
, "inavlid source yuv order 0x%x.\n", fmt
);
489 fimc_write(cfg
, EXYNOS_MSCTRL
);
494 static int fimc_src_set_fmt(struct device
*dev
, u32 fmt
)
496 struct fimc_context
*ctx
= get_fimc_context(dev
);
497 struct exynos_drm_ippdrv
*ippdrv
= &ctx
->ippdrv
;
500 DRM_DEBUG_KMS("%s:fmt[0x%x]\n", __func__
, fmt
);
502 cfg
= fimc_read(EXYNOS_MSCTRL
);
503 cfg
&= ~EXYNOS_MSCTRL_INFORMAT_RGB
;
506 case DRM_FORMAT_RGB565
:
507 case DRM_FORMAT_RGB888
:
508 case DRM_FORMAT_XRGB8888
:
509 cfg
|= EXYNOS_MSCTRL_INFORMAT_RGB
;
511 case DRM_FORMAT_YUV444
:
512 cfg
|= EXYNOS_MSCTRL_INFORMAT_YCBCR420
;
514 case DRM_FORMAT_YUYV
:
515 case DRM_FORMAT_YVYU
:
516 case DRM_FORMAT_UYVY
:
517 case DRM_FORMAT_VYUY
:
518 cfg
|= EXYNOS_MSCTRL_INFORMAT_YCBCR422_1PLANE
;
520 case DRM_FORMAT_NV16
:
521 case DRM_FORMAT_NV61
:
522 case DRM_FORMAT_YUV422
:
523 cfg
|= EXYNOS_MSCTRL_INFORMAT_YCBCR422
;
525 case DRM_FORMAT_YUV420
:
526 case DRM_FORMAT_YVU420
:
527 case DRM_FORMAT_NV12
:
528 case DRM_FORMAT_NV21
:
529 case DRM_FORMAT_NV12MT
:
530 cfg
|= EXYNOS_MSCTRL_INFORMAT_YCBCR420
;
533 dev_err(ippdrv
->dev
, "inavlid source format 0x%x.\n", fmt
);
537 fimc_write(cfg
, EXYNOS_MSCTRL
);
539 cfg
= fimc_read(EXYNOS_CIDMAPARAM
);
540 cfg
&= ~EXYNOS_CIDMAPARAM_R_MODE_MASK
;
542 if (fmt
== DRM_FORMAT_NV12MT
)
543 cfg
|= EXYNOS_CIDMAPARAM_R_MODE_64X32
;
545 cfg
|= EXYNOS_CIDMAPARAM_R_MODE_LINEAR
;
547 fimc_write(cfg
, EXYNOS_CIDMAPARAM
);
549 return fimc_src_set_fmt_order(ctx
, fmt
);
552 static int fimc_src_set_transf(struct device
*dev
,
553 enum drm_exynos_degree degree
,
554 enum drm_exynos_flip flip
, bool *swap
)
556 struct fimc_context
*ctx
= get_fimc_context(dev
);
557 struct exynos_drm_ippdrv
*ippdrv
= &ctx
->ippdrv
;
560 DRM_DEBUG_KMS("%s:degree[%d]flip[0x%x]\n", __func__
,
563 cfg1
= fimc_read(EXYNOS_MSCTRL
);
564 cfg1
&= ~(EXYNOS_MSCTRL_FLIP_X_MIRROR
|
565 EXYNOS_MSCTRL_FLIP_Y_MIRROR
);
567 cfg2
= fimc_read(EXYNOS_CITRGFMT
);
568 cfg2
&= ~EXYNOS_CITRGFMT_INROT90_CLOCKWISE
;
571 case EXYNOS_DRM_DEGREE_0
:
572 if (flip
& EXYNOS_DRM_FLIP_VERTICAL
)
573 cfg1
|= EXYNOS_MSCTRL_FLIP_X_MIRROR
;
574 if (flip
& EXYNOS_DRM_FLIP_HORIZONTAL
)
575 cfg1
|= EXYNOS_MSCTRL_FLIP_Y_MIRROR
;
577 case EXYNOS_DRM_DEGREE_90
:
578 cfg2
|= EXYNOS_CITRGFMT_INROT90_CLOCKWISE
;
579 if (flip
& EXYNOS_DRM_FLIP_VERTICAL
)
580 cfg1
|= EXYNOS_MSCTRL_FLIP_X_MIRROR
;
581 if (flip
& EXYNOS_DRM_FLIP_HORIZONTAL
)
582 cfg1
|= EXYNOS_MSCTRL_FLIP_Y_MIRROR
;
584 case EXYNOS_DRM_DEGREE_180
:
585 cfg1
|= (EXYNOS_MSCTRL_FLIP_X_MIRROR
|
586 EXYNOS_MSCTRL_FLIP_Y_MIRROR
);
587 if (flip
& EXYNOS_DRM_FLIP_VERTICAL
)
588 cfg1
&= ~EXYNOS_MSCTRL_FLIP_X_MIRROR
;
589 if (flip
& EXYNOS_DRM_FLIP_HORIZONTAL
)
590 cfg1
&= ~EXYNOS_MSCTRL_FLIP_Y_MIRROR
;
592 case EXYNOS_DRM_DEGREE_270
:
593 cfg1
|= (EXYNOS_MSCTRL_FLIP_X_MIRROR
|
594 EXYNOS_MSCTRL_FLIP_Y_MIRROR
);
595 cfg2
|= EXYNOS_CITRGFMT_INROT90_CLOCKWISE
;
596 if (flip
& EXYNOS_DRM_FLIP_VERTICAL
)
597 cfg1
&= ~EXYNOS_MSCTRL_FLIP_X_MIRROR
;
598 if (flip
& EXYNOS_DRM_FLIP_HORIZONTAL
)
599 cfg1
&= ~EXYNOS_MSCTRL_FLIP_Y_MIRROR
;
602 dev_err(ippdrv
->dev
, "inavlid degree value %d.\n", degree
);
606 fimc_write(cfg1
, EXYNOS_MSCTRL
);
607 fimc_write(cfg2
, EXYNOS_CITRGFMT
);
608 *swap
= (cfg2
& EXYNOS_CITRGFMT_INROT90_CLOCKWISE
) ? 1 : 0;
613 static int fimc_set_window(struct fimc_context
*ctx
,
614 struct drm_exynos_pos
*pos
, struct drm_exynos_sz
*sz
)
616 u32 cfg
, h1
, h2
, v1
, v2
;
620 h2
= sz
->hsize
- pos
->w
- pos
->x
;
622 v2
= sz
->vsize
- pos
->h
- pos
->y
;
624 DRM_DEBUG_KMS("%s:x[%d]y[%d]w[%d]h[%d]hsize[%d]vsize[%d]\n",
625 __func__
, pos
->x
, pos
->y
, pos
->w
, pos
->h
, sz
->hsize
, sz
->vsize
);
626 DRM_DEBUG_KMS("%s:h1[%d]h2[%d]v1[%d]v2[%d]\n", __func__
,
630 * set window offset 1, 2 size
631 * check figure 43-21 in user manual
633 cfg
= fimc_read(EXYNOS_CIWDOFST
);
634 cfg
&= ~(EXYNOS_CIWDOFST_WINHOROFST_MASK
|
635 EXYNOS_CIWDOFST_WINVEROFST_MASK
);
636 cfg
|= (EXYNOS_CIWDOFST_WINHOROFST(h1
) |
637 EXYNOS_CIWDOFST_WINVEROFST(v1
));
638 cfg
|= EXYNOS_CIWDOFST_WINOFSEN
;
639 fimc_write(cfg
, EXYNOS_CIWDOFST
);
641 cfg
= (EXYNOS_CIWDOFST2_WINHOROFST2(h2
) |
642 EXYNOS_CIWDOFST2_WINVEROFST2(v2
));
643 fimc_write(cfg
, EXYNOS_CIWDOFST2
);
648 static int fimc_src_set_size(struct device
*dev
, int swap
,
649 struct drm_exynos_pos
*pos
, struct drm_exynos_sz
*sz
)
651 struct fimc_context
*ctx
= get_fimc_context(dev
);
652 struct drm_exynos_pos img_pos
= *pos
;
653 struct drm_exynos_sz img_sz
= *sz
;
656 DRM_DEBUG_KMS("%s:swap[%d]hsize[%d]vsize[%d]\n",
657 __func__
, swap
, sz
->hsize
, sz
->vsize
);
660 cfg
= (EXYNOS_ORGISIZE_HORIZONTAL(img_sz
.hsize
) |
661 EXYNOS_ORGISIZE_VERTICAL(img_sz
.vsize
));
663 fimc_write(cfg
, EXYNOS_ORGISIZE
);
665 DRM_DEBUG_KMS("%s:x[%d]y[%d]w[%d]h[%d]\n", __func__
,
666 pos
->x
, pos
->y
, pos
->w
, pos
->h
);
671 img_sz
.hsize
= sz
->vsize
;
672 img_sz
.vsize
= sz
->hsize
;
675 /* set input DMA image size */
676 cfg
= fimc_read(EXYNOS_CIREAL_ISIZE
);
677 cfg
&= ~(EXYNOS_CIREAL_ISIZE_HEIGHT_MASK
|
678 EXYNOS_CIREAL_ISIZE_WIDTH_MASK
);
679 cfg
|= (EXYNOS_CIREAL_ISIZE_WIDTH(img_pos
.w
) |
680 EXYNOS_CIREAL_ISIZE_HEIGHT(img_pos
.h
));
681 fimc_write(cfg
, EXYNOS_CIREAL_ISIZE
);
684 * set input FIFO image size
685 * for now, we support only ITU601 8 bit mode
687 cfg
= (EXYNOS_CISRCFMT_ITU601_8BIT
|
688 EXYNOS_CISRCFMT_SOURCEHSIZE(img_sz
.hsize
) |
689 EXYNOS_CISRCFMT_SOURCEVSIZE(img_sz
.vsize
));
690 fimc_write(cfg
, EXYNOS_CISRCFMT
);
692 /* offset Y(RGB), Cb, Cr */
693 cfg
= (EXYNOS_CIIYOFF_HORIZONTAL(img_pos
.x
) |
694 EXYNOS_CIIYOFF_VERTICAL(img_pos
.y
));
695 fimc_write(cfg
, EXYNOS_CIIYOFF
);
696 cfg
= (EXYNOS_CIICBOFF_HORIZONTAL(img_pos
.x
) |
697 EXYNOS_CIICBOFF_VERTICAL(img_pos
.y
));
698 fimc_write(cfg
, EXYNOS_CIICBOFF
);
699 cfg
= (EXYNOS_CIICROFF_HORIZONTAL(img_pos
.x
) |
700 EXYNOS_CIICROFF_VERTICAL(img_pos
.y
));
701 fimc_write(cfg
, EXYNOS_CIICROFF
);
703 return fimc_set_window(ctx
, &img_pos
, &img_sz
);
706 static int fimc_src_set_addr(struct device
*dev
,
707 struct drm_exynos_ipp_buf_info
*buf_info
, u32 buf_id
,
708 enum drm_exynos_ipp_buf_type buf_type
)
710 struct fimc_context
*ctx
= get_fimc_context(dev
);
711 struct exynos_drm_ippdrv
*ippdrv
= &ctx
->ippdrv
;
712 struct drm_exynos_ipp_cmd_node
*c_node
= ippdrv
->c_node
;
713 struct drm_exynos_ipp_property
*property
;
714 struct drm_exynos_ipp_config
*config
;
717 DRM_ERROR("failed to get c_node.\n");
721 property
= &c_node
->property
;
723 DRM_DEBUG_KMS("%s:prop_id[%d]buf_id[%d]buf_type[%d]\n", __func__
,
724 property
->prop_id
, buf_id
, buf_type
);
726 if (buf_id
> FIMC_MAX_SRC
) {
727 dev_info(ippdrv
->dev
, "inavlid buf_id %d.\n", buf_id
);
731 /* address register set */
733 case IPP_BUF_ENQUEUE
:
734 config
= &property
->config
[EXYNOS_DRM_OPS_SRC
];
735 fimc_write(buf_info
->base
[EXYNOS_DRM_PLANAR_Y
],
736 EXYNOS_CIIYSA(buf_id
));
738 if (config
->fmt
== DRM_FORMAT_YVU420
) {
739 fimc_write(buf_info
->base
[EXYNOS_DRM_PLANAR_CR
],
740 EXYNOS_CIICBSA(buf_id
));
741 fimc_write(buf_info
->base
[EXYNOS_DRM_PLANAR_CB
],
742 EXYNOS_CIICRSA(buf_id
));
744 fimc_write(buf_info
->base
[EXYNOS_DRM_PLANAR_CB
],
745 EXYNOS_CIICBSA(buf_id
));
746 fimc_write(buf_info
->base
[EXYNOS_DRM_PLANAR_CR
],
747 EXYNOS_CIICRSA(buf_id
));
750 case IPP_BUF_DEQUEUE
:
751 fimc_write(0x0, EXYNOS_CIIYSA(buf_id
));
752 fimc_write(0x0, EXYNOS_CIICBSA(buf_id
));
753 fimc_write(0x0, EXYNOS_CIICRSA(buf_id
));
763 static struct exynos_drm_ipp_ops fimc_src_ops
= {
764 .set_fmt
= fimc_src_set_fmt
,
765 .set_transf
= fimc_src_set_transf
,
766 .set_size
= fimc_src_set_size
,
767 .set_addr
= fimc_src_set_addr
,
770 static int fimc_dst_set_fmt_order(struct fimc_context
*ctx
, u32 fmt
)
772 struct exynos_drm_ippdrv
*ippdrv
= &ctx
->ippdrv
;
775 DRM_DEBUG_KMS("%s:fmt[0x%x]\n", __func__
, fmt
);
778 cfg
= fimc_read(EXYNOS_CISCCTRL
);
779 cfg
&= ~EXYNOS_CISCCTRL_OUTRGB_FMT_RGB_MASK
;
782 case DRM_FORMAT_RGB565
:
783 cfg
|= EXYNOS_CISCCTRL_OUTRGB_FMT_RGB565
;
784 fimc_write(cfg
, EXYNOS_CISCCTRL
);
786 case DRM_FORMAT_RGB888
:
787 cfg
|= EXYNOS_CISCCTRL_OUTRGB_FMT_RGB888
;
788 fimc_write(cfg
, EXYNOS_CISCCTRL
);
790 case DRM_FORMAT_XRGB8888
:
791 cfg
|= (EXYNOS_CISCCTRL_OUTRGB_FMT_RGB888
|
792 EXYNOS_CISCCTRL_EXTRGB_EXTENSION
);
793 fimc_write(cfg
, EXYNOS_CISCCTRL
);
801 cfg
= fimc_read(EXYNOS_CIOCTRL
);
802 cfg
&= ~(EXYNOS_CIOCTRL_ORDER2P_MASK
|
803 EXYNOS_CIOCTRL_ORDER422_MASK
|
804 EXYNOS_CIOCTRL_YCBCR_PLANE_MASK
);
807 case DRM_FORMAT_XRGB8888
:
808 cfg
|= EXYNOS_CIOCTRL_ALPHA_OUT
;
810 case DRM_FORMAT_YUYV
:
811 cfg
|= EXYNOS_CIOCTRL_ORDER422_YCBYCR
;
813 case DRM_FORMAT_YVYU
:
814 cfg
|= EXYNOS_CIOCTRL_ORDER422_YCRYCB
;
816 case DRM_FORMAT_UYVY
:
817 cfg
|= EXYNOS_CIOCTRL_ORDER422_CBYCRY
;
819 case DRM_FORMAT_VYUY
:
820 cfg
|= EXYNOS_CIOCTRL_ORDER422_CRYCBY
;
822 case DRM_FORMAT_NV21
:
823 case DRM_FORMAT_NV61
:
824 cfg
|= EXYNOS_CIOCTRL_ORDER2P_LSB_CRCB
;
825 cfg
|= EXYNOS_CIOCTRL_YCBCR_2PLANE
;
827 case DRM_FORMAT_YUV422
:
828 case DRM_FORMAT_YUV420
:
829 case DRM_FORMAT_YVU420
:
830 cfg
|= EXYNOS_CIOCTRL_YCBCR_3PLANE
;
832 case DRM_FORMAT_NV12
:
833 case DRM_FORMAT_NV12MT
:
834 case DRM_FORMAT_NV16
:
835 cfg
|= EXYNOS_CIOCTRL_ORDER2P_LSB_CBCR
;
836 cfg
|= EXYNOS_CIOCTRL_YCBCR_2PLANE
;
839 dev_err(ippdrv
->dev
, "inavlid target yuv order 0x%x.\n", fmt
);
843 fimc_write(cfg
, EXYNOS_CIOCTRL
);
848 static int fimc_dst_set_fmt(struct device
*dev
, u32 fmt
)
850 struct fimc_context
*ctx
= get_fimc_context(dev
);
851 struct exynos_drm_ippdrv
*ippdrv
= &ctx
->ippdrv
;
854 DRM_DEBUG_KMS("%s:fmt[0x%x]\n", __func__
, fmt
);
856 cfg
= fimc_read(EXYNOS_CIEXTEN
);
858 if (fmt
== DRM_FORMAT_AYUV
) {
859 cfg
|= EXYNOS_CIEXTEN_YUV444_OUT
;
860 fimc_write(cfg
, EXYNOS_CIEXTEN
);
862 cfg
&= ~EXYNOS_CIEXTEN_YUV444_OUT
;
863 fimc_write(cfg
, EXYNOS_CIEXTEN
);
865 cfg
= fimc_read(EXYNOS_CITRGFMT
);
866 cfg
&= ~EXYNOS_CITRGFMT_OUTFORMAT_MASK
;
869 case DRM_FORMAT_RGB565
:
870 case DRM_FORMAT_RGB888
:
871 case DRM_FORMAT_XRGB8888
:
872 cfg
|= EXYNOS_CITRGFMT_OUTFORMAT_RGB
;
874 case DRM_FORMAT_YUYV
:
875 case DRM_FORMAT_YVYU
:
876 case DRM_FORMAT_UYVY
:
877 case DRM_FORMAT_VYUY
:
878 cfg
|= EXYNOS_CITRGFMT_OUTFORMAT_YCBCR422_1PLANE
;
880 case DRM_FORMAT_NV16
:
881 case DRM_FORMAT_NV61
:
882 case DRM_FORMAT_YUV422
:
883 cfg
|= EXYNOS_CITRGFMT_OUTFORMAT_YCBCR422
;
885 case DRM_FORMAT_YUV420
:
886 case DRM_FORMAT_YVU420
:
887 case DRM_FORMAT_NV12
:
888 case DRM_FORMAT_NV12MT
:
889 case DRM_FORMAT_NV21
:
890 cfg
|= EXYNOS_CITRGFMT_OUTFORMAT_YCBCR420
;
893 dev_err(ippdrv
->dev
, "inavlid target format 0x%x.\n",
898 fimc_write(cfg
, EXYNOS_CITRGFMT
);
901 cfg
= fimc_read(EXYNOS_CIDMAPARAM
);
902 cfg
&= ~EXYNOS_CIDMAPARAM_W_MODE_MASK
;
904 if (fmt
== DRM_FORMAT_NV12MT
)
905 cfg
|= EXYNOS_CIDMAPARAM_W_MODE_64X32
;
907 cfg
|= EXYNOS_CIDMAPARAM_W_MODE_LINEAR
;
909 fimc_write(cfg
, EXYNOS_CIDMAPARAM
);
911 return fimc_dst_set_fmt_order(ctx
, fmt
);
914 static int fimc_dst_set_transf(struct device
*dev
,
915 enum drm_exynos_degree degree
,
916 enum drm_exynos_flip flip
, bool *swap
)
918 struct fimc_context
*ctx
= get_fimc_context(dev
);
919 struct exynos_drm_ippdrv
*ippdrv
= &ctx
->ippdrv
;
922 DRM_DEBUG_KMS("%s:degree[%d]flip[0x%x]\n", __func__
,
925 cfg
= fimc_read(EXYNOS_CITRGFMT
);
926 cfg
&= ~EXYNOS_CITRGFMT_FLIP_MASK
;
927 cfg
&= ~EXYNOS_CITRGFMT_OUTROT90_CLOCKWISE
;
930 case EXYNOS_DRM_DEGREE_0
:
931 if (flip
& EXYNOS_DRM_FLIP_VERTICAL
)
932 cfg
|= EXYNOS_CITRGFMT_FLIP_X_MIRROR
;
933 if (flip
& EXYNOS_DRM_FLIP_HORIZONTAL
)
934 cfg
|= EXYNOS_CITRGFMT_FLIP_Y_MIRROR
;
936 case EXYNOS_DRM_DEGREE_90
:
937 cfg
|= EXYNOS_CITRGFMT_OUTROT90_CLOCKWISE
;
938 if (flip
& EXYNOS_DRM_FLIP_VERTICAL
)
939 cfg
|= EXYNOS_CITRGFMT_FLIP_X_MIRROR
;
940 if (flip
& EXYNOS_DRM_FLIP_HORIZONTAL
)
941 cfg
|= EXYNOS_CITRGFMT_FLIP_Y_MIRROR
;
943 case EXYNOS_DRM_DEGREE_180
:
944 cfg
|= (EXYNOS_CITRGFMT_FLIP_X_MIRROR
|
945 EXYNOS_CITRGFMT_FLIP_Y_MIRROR
);
946 if (flip
& EXYNOS_DRM_FLIP_VERTICAL
)
947 cfg
&= ~EXYNOS_CITRGFMT_FLIP_X_MIRROR
;
948 if (flip
& EXYNOS_DRM_FLIP_HORIZONTAL
)
949 cfg
&= ~EXYNOS_CITRGFMT_FLIP_Y_MIRROR
;
951 case EXYNOS_DRM_DEGREE_270
:
952 cfg
|= (EXYNOS_CITRGFMT_OUTROT90_CLOCKWISE
|
953 EXYNOS_CITRGFMT_FLIP_X_MIRROR
|
954 EXYNOS_CITRGFMT_FLIP_Y_MIRROR
);
955 if (flip
& EXYNOS_DRM_FLIP_VERTICAL
)
956 cfg
&= ~EXYNOS_CITRGFMT_FLIP_X_MIRROR
;
957 if (flip
& EXYNOS_DRM_FLIP_HORIZONTAL
)
958 cfg
&= ~EXYNOS_CITRGFMT_FLIP_Y_MIRROR
;
961 dev_err(ippdrv
->dev
, "inavlid degree value %d.\n", degree
);
965 fimc_write(cfg
, EXYNOS_CITRGFMT
);
966 *swap
= (cfg
& EXYNOS_CITRGFMT_OUTROT90_CLOCKWISE
) ? 1 : 0;
971 static int fimc_get_ratio_shift(u32 src
, u32 dst
, u32
*ratio
, u32
*shift
)
973 DRM_DEBUG_KMS("%s:src[%d]dst[%d]\n", __func__
, src
, dst
);
975 if (src
>= dst
* 64) {
976 DRM_ERROR("failed to make ratio and shift.\n");
978 } else if (src
>= dst
* 32) {
981 } else if (src
>= dst
* 16) {
984 } else if (src
>= dst
* 8) {
987 } else if (src
>= dst
* 4) {
990 } else if (src
>= dst
* 2) {
1001 static int fimc_set_prescaler(struct fimc_context
*ctx
, struct fimc_scaler
*sc
,
1002 struct drm_exynos_pos
*src
, struct drm_exynos_pos
*dst
)
1004 struct exynos_drm_ippdrv
*ippdrv
= &ctx
->ippdrv
;
1005 u32 cfg
, cfg_ext
, shfactor
;
1006 u32 pre_dst_width
, pre_dst_height
;
1007 u32 pre_hratio
, hfactor
, pre_vratio
, vfactor
;
1009 u32 src_w
, src_h
, dst_w
, dst_h
;
1011 cfg_ext
= fimc_read(EXYNOS_CITRGFMT
);
1012 if (cfg_ext
& EXYNOS_CITRGFMT_INROT90_CLOCKWISE
) {
1020 if (cfg_ext
& EXYNOS_CITRGFMT_OUTROT90_CLOCKWISE
) {
1028 ret
= fimc_get_ratio_shift(src_w
, dst_w
, &pre_hratio
, &hfactor
);
1030 dev_err(ippdrv
->dev
, "failed to get ratio horizontal.\n");
1034 ret
= fimc_get_ratio_shift(src_h
, dst_h
, &pre_vratio
, &vfactor
);
1036 dev_err(ippdrv
->dev
, "failed to get ratio vertical.\n");
1040 pre_dst_width
= src_w
/ pre_hratio
;
1041 pre_dst_height
= src_h
/ pre_vratio
;
1042 DRM_DEBUG_KMS("%s:pre_dst_width[%d]pre_dst_height[%d]\n", __func__
,
1043 pre_dst_width
, pre_dst_height
);
1044 DRM_DEBUG_KMS("%s:pre_hratio[%d]hfactor[%d]pre_vratio[%d]vfactor[%d]\n",
1045 __func__
, pre_hratio
, hfactor
, pre_vratio
, vfactor
);
1047 sc
->hratio
= (src_w
<< 14) / (dst_w
<< hfactor
);
1048 sc
->vratio
= (src_h
<< 14) / (dst_h
<< vfactor
);
1049 sc
->up_h
= (dst_w
>= src_w
) ? true : false;
1050 sc
->up_v
= (dst_h
>= src_h
) ? true : false;
1051 DRM_DEBUG_KMS("%s:hratio[%d]vratio[%d]up_h[%d]up_v[%d]\n",
1052 __func__
, sc
->hratio
, sc
->vratio
, sc
->up_h
, sc
->up_v
);
1054 shfactor
= FIMC_SHFACTOR
- (hfactor
+ vfactor
);
1055 DRM_DEBUG_KMS("%s:shfactor[%d]\n", __func__
, shfactor
);
1057 cfg
= (EXYNOS_CISCPRERATIO_SHFACTOR(shfactor
) |
1058 EXYNOS_CISCPRERATIO_PREHORRATIO(pre_hratio
) |
1059 EXYNOS_CISCPRERATIO_PREVERRATIO(pre_vratio
));
1060 fimc_write(cfg
, EXYNOS_CISCPRERATIO
);
1062 cfg
= (EXYNOS_CISCPREDST_PREDSTWIDTH(pre_dst_width
) |
1063 EXYNOS_CISCPREDST_PREDSTHEIGHT(pre_dst_height
));
1064 fimc_write(cfg
, EXYNOS_CISCPREDST
);
1069 static void fimc_set_scaler(struct fimc_context
*ctx
, struct fimc_scaler
*sc
)
1073 DRM_DEBUG_KMS("%s:range[%d]bypass[%d]up_h[%d]up_v[%d]\n",
1074 __func__
, sc
->range
, sc
->bypass
, sc
->up_h
, sc
->up_v
);
1075 DRM_DEBUG_KMS("%s:hratio[%d]vratio[%d]\n",
1076 __func__
, sc
->hratio
, sc
->vratio
);
1078 cfg
= fimc_read(EXYNOS_CISCCTRL
);
1079 cfg
&= ~(EXYNOS_CISCCTRL_SCALERBYPASS
|
1080 EXYNOS_CISCCTRL_SCALEUP_H
| EXYNOS_CISCCTRL_SCALEUP_V
|
1081 EXYNOS_CISCCTRL_MAIN_V_RATIO_MASK
|
1082 EXYNOS_CISCCTRL_MAIN_H_RATIO_MASK
|
1083 EXYNOS_CISCCTRL_CSCR2Y_WIDE
|
1084 EXYNOS_CISCCTRL_CSCY2R_WIDE
);
1087 cfg
|= (EXYNOS_CISCCTRL_CSCR2Y_WIDE
|
1088 EXYNOS_CISCCTRL_CSCY2R_WIDE
);
1090 cfg
|= EXYNOS_CISCCTRL_SCALERBYPASS
;
1092 cfg
|= EXYNOS_CISCCTRL_SCALEUP_H
;
1094 cfg
|= EXYNOS_CISCCTRL_SCALEUP_V
;
1096 cfg
|= (EXYNOS_CISCCTRL_MAINHORRATIO((sc
->hratio
>> 6)) |
1097 EXYNOS_CISCCTRL_MAINVERRATIO((sc
->vratio
>> 6)));
1098 fimc_write(cfg
, EXYNOS_CISCCTRL
);
1100 cfg_ext
= fimc_read(EXYNOS_CIEXTEN
);
1101 cfg_ext
&= ~EXYNOS_CIEXTEN_MAINHORRATIO_EXT_MASK
;
1102 cfg_ext
&= ~EXYNOS_CIEXTEN_MAINVERRATIO_EXT_MASK
;
1103 cfg_ext
|= (EXYNOS_CIEXTEN_MAINHORRATIO_EXT(sc
->hratio
) |
1104 EXYNOS_CIEXTEN_MAINVERRATIO_EXT(sc
->vratio
));
1105 fimc_write(cfg_ext
, EXYNOS_CIEXTEN
);
1108 static int fimc_dst_set_size(struct device
*dev
, int swap
,
1109 struct drm_exynos_pos
*pos
, struct drm_exynos_sz
*sz
)
1111 struct fimc_context
*ctx
= get_fimc_context(dev
);
1112 struct drm_exynos_pos img_pos
= *pos
;
1113 struct drm_exynos_sz img_sz
= *sz
;
1116 DRM_DEBUG_KMS("%s:swap[%d]hsize[%d]vsize[%d]\n",
1117 __func__
, swap
, sz
->hsize
, sz
->vsize
);
1120 cfg
= (EXYNOS_ORGOSIZE_HORIZONTAL(img_sz
.hsize
) |
1121 EXYNOS_ORGOSIZE_VERTICAL(img_sz
.vsize
));
1123 fimc_write(cfg
, EXYNOS_ORGOSIZE
);
1125 DRM_DEBUG_KMS("%s:x[%d]y[%d]w[%d]h[%d]\n",
1126 __func__
, pos
->x
, pos
->y
, pos
->w
, pos
->h
);
1129 cfg
= fimc_read(EXYNOS_CIGCTRL
);
1130 cfg
&= ~EXYNOS_CIGCTRL_CSC_MASK
;
1132 if (sz
->hsize
>= FIMC_WIDTH_ITU_709
)
1133 cfg
|= EXYNOS_CIGCTRL_CSC_ITU709
;
1135 cfg
|= EXYNOS_CIGCTRL_CSC_ITU601
;
1137 fimc_write(cfg
, EXYNOS_CIGCTRL
);
1142 img_sz
.hsize
= sz
->vsize
;
1143 img_sz
.vsize
= sz
->hsize
;
1146 /* target image size */
1147 cfg
= fimc_read(EXYNOS_CITRGFMT
);
1148 cfg
&= ~(EXYNOS_CITRGFMT_TARGETH_MASK
|
1149 EXYNOS_CITRGFMT_TARGETV_MASK
);
1150 cfg
|= (EXYNOS_CITRGFMT_TARGETHSIZE(img_pos
.w
) |
1151 EXYNOS_CITRGFMT_TARGETVSIZE(img_pos
.h
));
1152 fimc_write(cfg
, EXYNOS_CITRGFMT
);
1155 cfg
= EXYNOS_CITAREA_TARGET_AREA(img_pos
.w
* img_pos
.h
);
1156 fimc_write(cfg
, EXYNOS_CITAREA
);
1158 /* offset Y(RGB), Cb, Cr */
1159 cfg
= (EXYNOS_CIOYOFF_HORIZONTAL(img_pos
.x
) |
1160 EXYNOS_CIOYOFF_VERTICAL(img_pos
.y
));
1161 fimc_write(cfg
, EXYNOS_CIOYOFF
);
1162 cfg
= (EXYNOS_CIOCBOFF_HORIZONTAL(img_pos
.x
) |
1163 EXYNOS_CIOCBOFF_VERTICAL(img_pos
.y
));
1164 fimc_write(cfg
, EXYNOS_CIOCBOFF
);
1165 cfg
= (EXYNOS_CIOCROFF_HORIZONTAL(img_pos
.x
) |
1166 EXYNOS_CIOCROFF_VERTICAL(img_pos
.y
));
1167 fimc_write(cfg
, EXYNOS_CIOCROFF
);
1172 static int fimc_dst_get_buf_seq(struct fimc_context
*ctx
)
1174 u32 cfg
, i
, buf_num
= 0;
1175 u32 mask
= 0x00000001;
1177 cfg
= fimc_read(EXYNOS_CIFCNTSEQ
);
1179 for (i
= 0; i
< FIMC_REG_SZ
; i
++)
1180 if (cfg
& (mask
<< i
))
1183 DRM_DEBUG_KMS("%s:buf_num[%d]\n", __func__
, buf_num
);
1188 static int fimc_dst_set_buf_seq(struct fimc_context
*ctx
, u32 buf_id
,
1189 enum drm_exynos_ipp_buf_type buf_type
)
1191 struct exynos_drm_ippdrv
*ippdrv
= &ctx
->ippdrv
;
1194 u32 mask
= 0x00000001 << buf_id
;
1197 DRM_DEBUG_KMS("%s:buf_id[%d]buf_type[%d]\n", __func__
,
1200 mutex_lock(&ctx
->lock
);
1202 /* mask register set */
1203 cfg
= fimc_read(EXYNOS_CIFCNTSEQ
);
1206 case IPP_BUF_ENQUEUE
:
1209 case IPP_BUF_DEQUEUE
:
1213 dev_err(ippdrv
->dev
, "invalid buf ctrl parameter.\n");
1220 cfg
|= (enable
<< buf_id
);
1221 fimc_write(cfg
, EXYNOS_CIFCNTSEQ
);
1223 /* interrupt enable */
1224 if (buf_type
== IPP_BUF_ENQUEUE
&&
1225 fimc_dst_get_buf_seq(ctx
) >= FIMC_BUF_START
)
1226 fimc_handle_irq(ctx
, true, false, true);
1228 /* interrupt disable */
1229 if (buf_type
== IPP_BUF_DEQUEUE
&&
1230 fimc_dst_get_buf_seq(ctx
) <= FIMC_BUF_STOP
)
1231 fimc_handle_irq(ctx
, false, false, true);
1234 mutex_unlock(&ctx
->lock
);
1238 static int fimc_dst_set_addr(struct device
*dev
,
1239 struct drm_exynos_ipp_buf_info
*buf_info
, u32 buf_id
,
1240 enum drm_exynos_ipp_buf_type buf_type
)
1242 struct fimc_context
*ctx
= get_fimc_context(dev
);
1243 struct exynos_drm_ippdrv
*ippdrv
= &ctx
->ippdrv
;
1244 struct drm_exynos_ipp_cmd_node
*c_node
= ippdrv
->c_node
;
1245 struct drm_exynos_ipp_property
*property
;
1246 struct drm_exynos_ipp_config
*config
;
1249 DRM_ERROR("failed to get c_node.\n");
1253 property
= &c_node
->property
;
1255 DRM_DEBUG_KMS("%s:prop_id[%d]buf_id[%d]buf_type[%d]\n", __func__
,
1256 property
->prop_id
, buf_id
, buf_type
);
1258 if (buf_id
> FIMC_MAX_DST
) {
1259 dev_info(ippdrv
->dev
, "inavlid buf_id %d.\n", buf_id
);
1263 /* address register set */
1265 case IPP_BUF_ENQUEUE
:
1266 config
= &property
->config
[EXYNOS_DRM_OPS_DST
];
1268 fimc_write(buf_info
->base
[EXYNOS_DRM_PLANAR_Y
],
1269 EXYNOS_CIOYSA(buf_id
));
1271 if (config
->fmt
== DRM_FORMAT_YVU420
) {
1272 fimc_write(buf_info
->base
[EXYNOS_DRM_PLANAR_CR
],
1273 EXYNOS_CIOCBSA(buf_id
));
1274 fimc_write(buf_info
->base
[EXYNOS_DRM_PLANAR_CB
],
1275 EXYNOS_CIOCRSA(buf_id
));
1277 fimc_write(buf_info
->base
[EXYNOS_DRM_PLANAR_CB
],
1278 EXYNOS_CIOCBSA(buf_id
));
1279 fimc_write(buf_info
->base
[EXYNOS_DRM_PLANAR_CR
],
1280 EXYNOS_CIOCRSA(buf_id
));
1283 case IPP_BUF_DEQUEUE
:
1284 fimc_write(0x0, EXYNOS_CIOYSA(buf_id
));
1285 fimc_write(0x0, EXYNOS_CIOCBSA(buf_id
));
1286 fimc_write(0x0, EXYNOS_CIOCRSA(buf_id
));
1293 return fimc_dst_set_buf_seq(ctx
, buf_id
, buf_type
);
1296 static struct exynos_drm_ipp_ops fimc_dst_ops
= {
1297 .set_fmt
= fimc_dst_set_fmt
,
1298 .set_transf
= fimc_dst_set_transf
,
1299 .set_size
= fimc_dst_set_size
,
1300 .set_addr
= fimc_dst_set_addr
,
1303 static int fimc_clk_ctrl(struct fimc_context
*ctx
, bool enable
)
1305 DRM_DEBUG_KMS("%s:enable[%d]\n", __func__
, enable
);
1308 clk_prepare_enable(ctx
->clocks
[FIMC_CLK_GATE
]);
1309 clk_prepare_enable(ctx
->clocks
[FIMC_CLK_WB_A
]);
1310 ctx
->suspended
= false;
1312 clk_disable_unprepare(ctx
->clocks
[FIMC_CLK_GATE
]);
1313 clk_disable_unprepare(ctx
->clocks
[FIMC_CLK_WB_A
]);
1314 ctx
->suspended
= true;
1320 static irqreturn_t
fimc_irq_handler(int irq
, void *dev_id
)
1322 struct fimc_context
*ctx
= dev_id
;
1323 struct exynos_drm_ippdrv
*ippdrv
= &ctx
->ippdrv
;
1324 struct drm_exynos_ipp_cmd_node
*c_node
= ippdrv
->c_node
;
1325 struct drm_exynos_ipp_event_work
*event_work
=
1329 DRM_DEBUG_KMS("%s:fimc id[%d]\n", __func__
, ctx
->id
);
1331 fimc_clear_irq(ctx
);
1332 if (fimc_check_ovf(ctx
))
1335 if (!fimc_check_frame_end(ctx
))
1338 buf_id
= fimc_get_buf_id(ctx
);
1342 DRM_DEBUG_KMS("%s:buf_id[%d]\n", __func__
, buf_id
);
1344 if (fimc_dst_set_buf_seq(ctx
, buf_id
, IPP_BUF_DEQUEUE
) < 0) {
1345 DRM_ERROR("failed to dequeue.\n");
1349 event_work
->ippdrv
= ippdrv
;
1350 event_work
->buf_id
[EXYNOS_DRM_OPS_DST
] = buf_id
;
1351 queue_work(ippdrv
->event_workq
, (struct work_struct
*)event_work
);
1356 static int fimc_init_prop_list(struct exynos_drm_ippdrv
*ippdrv
)
1358 struct drm_exynos_ipp_prop_list
*prop_list
;
1360 DRM_DEBUG_KMS("%s\n", __func__
);
1362 prop_list
= devm_kzalloc(ippdrv
->dev
, sizeof(*prop_list
), GFP_KERNEL
);
1364 DRM_ERROR("failed to alloc property list.\n");
1368 prop_list
->version
= 1;
1369 prop_list
->writeback
= 1;
1370 prop_list
->refresh_min
= FIMC_REFRESH_MIN
;
1371 prop_list
->refresh_max
= FIMC_REFRESH_MAX
;
1372 prop_list
->flip
= (1 << EXYNOS_DRM_FLIP_NONE
) |
1373 (1 << EXYNOS_DRM_FLIP_VERTICAL
) |
1374 (1 << EXYNOS_DRM_FLIP_HORIZONTAL
);
1375 prop_list
->degree
= (1 << EXYNOS_DRM_DEGREE_0
) |
1376 (1 << EXYNOS_DRM_DEGREE_90
) |
1377 (1 << EXYNOS_DRM_DEGREE_180
) |
1378 (1 << EXYNOS_DRM_DEGREE_270
);
1380 prop_list
->crop
= 1;
1381 prop_list
->crop_max
.hsize
= FIMC_CROP_MAX
;
1382 prop_list
->crop_max
.vsize
= FIMC_CROP_MAX
;
1383 prop_list
->crop_min
.hsize
= FIMC_CROP_MIN
;
1384 prop_list
->crop_min
.vsize
= FIMC_CROP_MIN
;
1385 prop_list
->scale
= 1;
1386 prop_list
->scale_max
.hsize
= FIMC_SCALE_MAX
;
1387 prop_list
->scale_max
.vsize
= FIMC_SCALE_MAX
;
1388 prop_list
->scale_min
.hsize
= FIMC_SCALE_MIN
;
1389 prop_list
->scale_min
.vsize
= FIMC_SCALE_MIN
;
1391 ippdrv
->prop_list
= prop_list
;
1396 static inline bool fimc_check_drm_flip(enum drm_exynos_flip flip
)
1399 case EXYNOS_DRM_FLIP_NONE
:
1400 case EXYNOS_DRM_FLIP_VERTICAL
:
1401 case EXYNOS_DRM_FLIP_HORIZONTAL
:
1402 case EXYNOS_DRM_FLIP_BOTH
:
1405 DRM_DEBUG_KMS("%s:invalid flip\n", __func__
);
1410 static int fimc_ippdrv_check_property(struct device
*dev
,
1411 struct drm_exynos_ipp_property
*property
)
1413 struct fimc_context
*ctx
= get_fimc_context(dev
);
1414 struct exynos_drm_ippdrv
*ippdrv
= &ctx
->ippdrv
;
1415 struct drm_exynos_ipp_prop_list
*pp
= ippdrv
->prop_list
;
1416 struct drm_exynos_ipp_config
*config
;
1417 struct drm_exynos_pos
*pos
;
1418 struct drm_exynos_sz
*sz
;
1422 DRM_DEBUG_KMS("%s\n", __func__
);
1424 for_each_ipp_ops(i
) {
1425 if ((i
== EXYNOS_DRM_OPS_SRC
) &&
1426 (property
->cmd
== IPP_CMD_WB
))
1429 config
= &property
->config
[i
];
1433 /* check for flip */
1434 if (!fimc_check_drm_flip(config
->flip
)) {
1435 DRM_ERROR("invalid flip.\n");
1439 /* check for degree */
1440 switch (config
->degree
) {
1441 case EXYNOS_DRM_DEGREE_90
:
1442 case EXYNOS_DRM_DEGREE_270
:
1445 case EXYNOS_DRM_DEGREE_0
:
1446 case EXYNOS_DRM_DEGREE_180
:
1450 DRM_ERROR("invalid degree.\n");
1454 /* check for buffer bound */
1455 if ((pos
->x
+ pos
->w
> sz
->hsize
) ||
1456 (pos
->y
+ pos
->h
> sz
->vsize
)) {
1457 DRM_ERROR("out of buf bound.\n");
1461 /* check for crop */
1462 if ((i
== EXYNOS_DRM_OPS_SRC
) && (pp
->crop
)) {
1464 if ((pos
->h
< pp
->crop_min
.hsize
) ||
1465 (sz
->vsize
> pp
->crop_max
.hsize
) ||
1466 (pos
->w
< pp
->crop_min
.vsize
) ||
1467 (sz
->hsize
> pp
->crop_max
.vsize
)) {
1468 DRM_ERROR("out of crop size.\n");
1472 if ((pos
->w
< pp
->crop_min
.hsize
) ||
1473 (sz
->hsize
> pp
->crop_max
.hsize
) ||
1474 (pos
->h
< pp
->crop_min
.vsize
) ||
1475 (sz
->vsize
> pp
->crop_max
.vsize
)) {
1476 DRM_ERROR("out of crop size.\n");
1482 /* check for scale */
1483 if ((i
== EXYNOS_DRM_OPS_DST
) && (pp
->scale
)) {
1485 if ((pos
->h
< pp
->scale_min
.hsize
) ||
1486 (sz
->vsize
> pp
->scale_max
.hsize
) ||
1487 (pos
->w
< pp
->scale_min
.vsize
) ||
1488 (sz
->hsize
> pp
->scale_max
.vsize
)) {
1489 DRM_ERROR("out of scale size.\n");
1493 if ((pos
->w
< pp
->scale_min
.hsize
) ||
1494 (sz
->hsize
> pp
->scale_max
.hsize
) ||
1495 (pos
->h
< pp
->scale_min
.vsize
) ||
1496 (sz
->vsize
> pp
->scale_max
.vsize
)) {
1497 DRM_ERROR("out of scale size.\n");
1507 for_each_ipp_ops(i
) {
1508 if ((i
== EXYNOS_DRM_OPS_SRC
) &&
1509 (property
->cmd
== IPP_CMD_WB
))
1512 config
= &property
->config
[i
];
1516 DRM_ERROR("[%s]f[%d]r[%d]pos[%d %d %d %d]sz[%d %d]\n",
1517 i
? "dst" : "src", config
->flip
, config
->degree
,
1518 pos
->x
, pos
->y
, pos
->w
, pos
->h
,
1519 sz
->hsize
, sz
->vsize
);
1525 static void fimc_clear_addr(struct fimc_context
*ctx
)
1529 DRM_DEBUG_KMS("%s:\n", __func__
);
1531 for (i
= 0; i
< FIMC_MAX_SRC
; i
++) {
1532 fimc_write(0, EXYNOS_CIIYSA(i
));
1533 fimc_write(0, EXYNOS_CIICBSA(i
));
1534 fimc_write(0, EXYNOS_CIICRSA(i
));
1537 for (i
= 0; i
< FIMC_MAX_DST
; i
++) {
1538 fimc_write(0, EXYNOS_CIOYSA(i
));
1539 fimc_write(0, EXYNOS_CIOCBSA(i
));
1540 fimc_write(0, EXYNOS_CIOCRSA(i
));
1544 static int fimc_ippdrv_reset(struct device
*dev
)
1546 struct fimc_context
*ctx
= get_fimc_context(dev
);
1548 DRM_DEBUG_KMS("%s\n", __func__
);
1550 /* reset h/w block */
1553 /* reset scaler capability */
1554 memset(&ctx
->sc
, 0x0, sizeof(ctx
->sc
));
1556 fimc_clear_addr(ctx
);
1561 static int fimc_ippdrv_start(struct device
*dev
, enum drm_exynos_ipp_cmd cmd
)
1563 struct fimc_context
*ctx
= get_fimc_context(dev
);
1564 struct exynos_drm_ippdrv
*ippdrv
= &ctx
->ippdrv
;
1565 struct drm_exynos_ipp_cmd_node
*c_node
= ippdrv
->c_node
;
1566 struct drm_exynos_ipp_property
*property
;
1567 struct drm_exynos_ipp_config
*config
;
1568 struct drm_exynos_pos img_pos
[EXYNOS_DRM_OPS_MAX
];
1569 struct drm_exynos_ipp_set_wb set_wb
;
1573 DRM_DEBUG_KMS("%s:cmd[%d]\n", __func__
, cmd
);
1576 DRM_ERROR("failed to get c_node.\n");
1580 property
= &c_node
->property
;
1582 fimc_handle_irq(ctx
, true, false, true);
1584 for_each_ipp_ops(i
) {
1585 config
= &property
->config
[i
];
1586 img_pos
[i
] = config
->pos
;
1589 ret
= fimc_set_prescaler(ctx
, &ctx
->sc
,
1590 &img_pos
[EXYNOS_DRM_OPS_SRC
],
1591 &img_pos
[EXYNOS_DRM_OPS_DST
]);
1593 dev_err(dev
, "failed to set precalser.\n");
1597 /* If set ture, we can save jpeg about screen */
1598 fimc_handle_jpeg(ctx
, false);
1599 fimc_set_scaler(ctx
, &ctx
->sc
);
1600 fimc_set_polarity(ctx
, &ctx
->pol
);
1604 fimc_set_type_ctrl(ctx
, FIMC_WB_NONE
);
1605 fimc_handle_lastend(ctx
, false);
1608 cfg0
= fimc_read(EXYNOS_MSCTRL
);
1609 cfg0
&= ~EXYNOS_MSCTRL_INPUT_MASK
;
1610 cfg0
|= EXYNOS_MSCTRL_INPUT_MEMORY
;
1611 fimc_write(cfg0
, EXYNOS_MSCTRL
);
1614 fimc_set_type_ctrl(ctx
, FIMC_WB_A
);
1615 fimc_handle_lastend(ctx
, true);
1618 ret
= fimc_set_camblk_fimd0_wb(ctx
);
1620 dev_err(dev
, "camblk setup failed.\n");
1625 set_wb
.refresh
= property
->refresh_rate
;
1626 exynos_drm_ippnb_send_event(IPP_SET_WRITEBACK
, (void *)&set_wb
);
1628 case IPP_CMD_OUTPUT
:
1631 dev_err(dev
, "invalid operations.\n");
1636 fimc_write(0x0, EXYNOS_CISTATUS
);
1638 cfg0
= fimc_read(EXYNOS_CIIMGCPT
);
1639 cfg0
&= ~EXYNOS_CIIMGCPT_IMGCPTEN_SC
;
1640 cfg0
|= EXYNOS_CIIMGCPT_IMGCPTEN_SC
;
1643 cfg1
= fimc_read(EXYNOS_CISCCTRL
);
1644 cfg1
&= ~EXYNOS_CISCCTRL_SCAN_MASK
;
1645 cfg1
|= (EXYNOS_CISCCTRL_PROGRESSIVE
|
1646 EXYNOS_CISCCTRL_SCALERSTART
);
1648 fimc_write(cfg1
, EXYNOS_CISCCTRL
);
1650 /* Enable image capture*/
1651 cfg0
|= EXYNOS_CIIMGCPT_IMGCPTEN
;
1652 fimc_write(cfg0
, EXYNOS_CIIMGCPT
);
1654 /* Disable frame end irq */
1655 cfg0
= fimc_read(EXYNOS_CIGCTRL
);
1656 cfg0
&= ~EXYNOS_CIGCTRL_IRQ_END_DISABLE
;
1657 fimc_write(cfg0
, EXYNOS_CIGCTRL
);
1659 cfg0
= fimc_read(EXYNOS_CIOCTRL
);
1660 cfg0
&= ~EXYNOS_CIOCTRL_WEAVE_MASK
;
1661 fimc_write(cfg0
, EXYNOS_CIOCTRL
);
1663 if (cmd
== IPP_CMD_M2M
) {
1664 cfg0
= fimc_read(EXYNOS_MSCTRL
);
1665 cfg0
|= EXYNOS_MSCTRL_ENVID
;
1666 fimc_write(cfg0
, EXYNOS_MSCTRL
);
1668 cfg0
= fimc_read(EXYNOS_MSCTRL
);
1669 cfg0
|= EXYNOS_MSCTRL_ENVID
;
1670 fimc_write(cfg0
, EXYNOS_MSCTRL
);
1676 static void fimc_ippdrv_stop(struct device
*dev
, enum drm_exynos_ipp_cmd cmd
)
1678 struct fimc_context
*ctx
= get_fimc_context(dev
);
1679 struct drm_exynos_ipp_set_wb set_wb
= {0, 0};
1682 DRM_DEBUG_KMS("%s:cmd[%d]\n", __func__
, cmd
);
1687 cfg
= fimc_read(EXYNOS_MSCTRL
);
1688 cfg
&= ~EXYNOS_MSCTRL_INPUT_MASK
;
1689 cfg
&= ~EXYNOS_MSCTRL_ENVID
;
1690 fimc_write(cfg
, EXYNOS_MSCTRL
);
1693 exynos_drm_ippnb_send_event(IPP_SET_WRITEBACK
, (void *)&set_wb
);
1695 case IPP_CMD_OUTPUT
:
1697 dev_err(dev
, "invalid operations.\n");
1701 fimc_handle_irq(ctx
, false, false, true);
1703 /* reset sequence */
1704 fimc_write(0x0, EXYNOS_CIFCNTSEQ
);
1706 /* Scaler disable */
1707 cfg
= fimc_read(EXYNOS_CISCCTRL
);
1708 cfg
&= ~EXYNOS_CISCCTRL_SCALERSTART
;
1709 fimc_write(cfg
, EXYNOS_CISCCTRL
);
1711 /* Disable image capture */
1712 cfg
= fimc_read(EXYNOS_CIIMGCPT
);
1713 cfg
&= ~(EXYNOS_CIIMGCPT_IMGCPTEN_SC
| EXYNOS_CIIMGCPT_IMGCPTEN
);
1714 fimc_write(cfg
, EXYNOS_CIIMGCPT
);
1716 /* Enable frame end irq */
1717 cfg
= fimc_read(EXYNOS_CIGCTRL
);
1718 cfg
|= EXYNOS_CIGCTRL_IRQ_END_DISABLE
;
1719 fimc_write(cfg
, EXYNOS_CIGCTRL
);
1722 static void fimc_put_clocks(struct fimc_context
*ctx
)
1726 for (i
= 0; i
< FIMC_CLKS_MAX
; i
++) {
1727 if (IS_ERR(ctx
->clocks
[i
]))
1729 clk_put(ctx
->clocks
[i
]);
1730 ctx
->clocks
[i
] = ERR_PTR(-EINVAL
);
1734 static int fimc_setup_clocks(struct fimc_context
*ctx
)
1736 struct device
*fimc_dev
= ctx
->ippdrv
.dev
;
1740 for (i
= 0; i
< FIMC_CLKS_MAX
; i
++)
1741 ctx
->clocks
[i
] = ERR_PTR(-EINVAL
);
1743 for (i
= 0; i
< FIMC_CLKS_MAX
; i
++) {
1744 if (i
== FIMC_CLK_WB_A
|| i
== FIMC_CLK_WB_B
)
1745 dev
= fimc_dev
->parent
;
1749 ctx
->clocks
[i
] = clk_get(dev
, fimc_clock_names
[i
]);
1750 if (IS_ERR(ctx
->clocks
[i
])) {
1751 if (i
>= FIMC_CLK_MUX
)
1753 ret
= PTR_ERR(ctx
->clocks
[i
]);
1754 dev_err(fimc_dev
, "failed to get clock: %s\n",
1755 fimc_clock_names
[i
]);
1760 /* Optional FIMC LCLK parent clock setting */
1761 if (!IS_ERR(ctx
->clocks
[FIMC_CLK_PARENT
])) {
1762 ret
= clk_set_parent(ctx
->clocks
[FIMC_CLK_MUX
],
1763 ctx
->clocks
[FIMC_CLK_PARENT
]);
1765 dev_err(fimc_dev
, "failed to set parent.\n");
1770 ret
= clk_set_rate(ctx
->clocks
[FIMC_CLK_LCLK
], ctx
->clk_frequency
);
1774 ret
= clk_prepare_enable(ctx
->clocks
[FIMC_CLK_LCLK
]);
1778 fimc_put_clocks(ctx
);
1782 static int fimc_parse_dt(struct fimc_context
*ctx
)
1784 struct device_node
*node
= ctx
->ippdrv
.dev
->of_node
;
1786 /* Handle only devices that support the LCD Writeback data path */
1787 if (!of_property_read_bool(node
, "samsung,lcd-wb"))
1790 if (of_property_read_u32(node
, "clock-frequency",
1791 &ctx
->clk_frequency
))
1792 ctx
->clk_frequency
= FIMC_DEFAULT_LCLK_FREQUENCY
;
1794 ctx
->id
= of_alias_get_id(node
, "fimc");
1797 dev_err(ctx
->ippdrv
.dev
, "failed to get node alias id.\n");
1804 static int fimc_probe(struct platform_device
*pdev
)
1806 struct device
*dev
= &pdev
->dev
;
1807 struct fimc_context
*ctx
;
1808 struct resource
*res
;
1809 struct exynos_drm_ippdrv
*ippdrv
;
1812 if (!dev
->of_node
) {
1813 dev_err(dev
, "device tree node not found.\n");
1817 ctx
= devm_kzalloc(dev
, sizeof(*ctx
), GFP_KERNEL
);
1821 ctx
->ippdrv
.dev
= dev
;
1823 ret
= fimc_parse_dt(ctx
);
1827 ctx
->sysreg
= syscon_regmap_lookup_by_phandle(dev
->of_node
,
1829 if (IS_ERR(ctx
->sysreg
)) {
1830 dev_err(dev
, "syscon regmap lookup failed.\n");
1831 return PTR_ERR(ctx
->sysreg
);
1834 /* resource memory */
1835 ctx
->regs_res
= platform_get_resource(pdev
, IORESOURCE_MEM
, 0);
1836 ctx
->regs
= devm_ioremap_resource(dev
, ctx
->regs_res
);
1837 if (IS_ERR(ctx
->regs
))
1838 return PTR_ERR(ctx
->regs
);
1841 res
= platform_get_resource(pdev
, IORESOURCE_IRQ
, 0);
1843 dev_err(dev
, "failed to request irq resource.\n");
1847 ctx
->irq
= res
->start
;
1848 ret
= devm_request_threaded_irq(dev
, ctx
->irq
, NULL
, fimc_irq_handler
,
1849 IRQF_ONESHOT
, "drm_fimc", ctx
);
1851 dev_err(dev
, "failed to request irq.\n");
1855 ret
= fimc_setup_clocks(ctx
);
1859 ippdrv
= &ctx
->ippdrv
;
1860 ippdrv
->ops
[EXYNOS_DRM_OPS_SRC
] = &fimc_src_ops
;
1861 ippdrv
->ops
[EXYNOS_DRM_OPS_DST
] = &fimc_dst_ops
;
1862 ippdrv
->check_property
= fimc_ippdrv_check_property
;
1863 ippdrv
->reset
= fimc_ippdrv_reset
;
1864 ippdrv
->start
= fimc_ippdrv_start
;
1865 ippdrv
->stop
= fimc_ippdrv_stop
;
1866 ret
= fimc_init_prop_list(ippdrv
);
1868 dev_err(dev
, "failed to init property list.\n");
1872 DRM_DEBUG_KMS("%s:id[%d]ippdrv[0x%x]\n", __func__
, ctx
->id
,
1875 mutex_init(&ctx
->lock
);
1876 platform_set_drvdata(pdev
, ctx
);
1878 pm_runtime_set_active(dev
);
1879 pm_runtime_enable(dev
);
1881 ret
= exynos_drm_ippdrv_register(ippdrv
);
1883 dev_err(dev
, "failed to register drm fimc device.\n");
1887 dev_info(dev
, "drm fimc registered successfully.\n");
1892 pm_runtime_disable(dev
);
1894 fimc_put_clocks(ctx
);
1899 static int fimc_remove(struct platform_device
*pdev
)
1901 struct device
*dev
= &pdev
->dev
;
1902 struct fimc_context
*ctx
= get_fimc_context(dev
);
1903 struct exynos_drm_ippdrv
*ippdrv
= &ctx
->ippdrv
;
1905 exynos_drm_ippdrv_unregister(ippdrv
);
1906 mutex_destroy(&ctx
->lock
);
1908 fimc_put_clocks(ctx
);
1909 pm_runtime_set_suspended(dev
);
1910 pm_runtime_disable(dev
);
1915 #ifdef CONFIG_PM_SLEEP
1916 static int fimc_suspend(struct device
*dev
)
1918 struct fimc_context
*ctx
= get_fimc_context(dev
);
1920 DRM_DEBUG_KMS("%s:id[%d]\n", __func__
, ctx
->id
);
1922 if (pm_runtime_suspended(dev
))
1925 return fimc_clk_ctrl(ctx
, false);
1928 static int fimc_resume(struct device
*dev
)
1930 struct fimc_context
*ctx
= get_fimc_context(dev
);
1932 DRM_DEBUG_KMS("%s:id[%d]\n", __func__
, ctx
->id
);
1934 if (!pm_runtime_suspended(dev
))
1935 return fimc_clk_ctrl(ctx
, true);
1941 #ifdef CONFIG_PM_RUNTIME
1942 static int fimc_runtime_suspend(struct device
*dev
)
1944 struct fimc_context
*ctx
= get_fimc_context(dev
);
1946 DRM_DEBUG_KMS("%s:id[%d]\n", __func__
, ctx
->id
);
1948 return fimc_clk_ctrl(ctx
, false);
1951 static int fimc_runtime_resume(struct device
*dev
)
1953 struct fimc_context
*ctx
= get_fimc_context(dev
);
1955 DRM_DEBUG_KMS("%s:id[%d]\n", __func__
, ctx
->id
);
1957 return fimc_clk_ctrl(ctx
, true);
1961 static const struct dev_pm_ops fimc_pm_ops
= {
1962 SET_SYSTEM_SLEEP_PM_OPS(fimc_suspend
, fimc_resume
)
1963 SET_RUNTIME_PM_OPS(fimc_runtime_suspend
, fimc_runtime_resume
, NULL
)
1966 static const struct of_device_id fimc_of_match
[] = {
1967 { .compatible
= "samsung,exynos4210-fimc" },
1968 { .compatible
= "samsung,exynos4212-fimc" },
1972 struct platform_driver fimc_driver
= {
1973 .probe
= fimc_probe
,
1974 .remove
= fimc_remove
,
1976 .of_match_table
= fimc_of_match
,
1977 .name
= "exynos-drm-fimc",
1978 .owner
= THIS_MODULE
,