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/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>
22 #include <drm/exynos_drm.h>
23 #include "regs-fimc.h"
24 #include "exynos_drm_drv.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 /* stop dma operation */
179 cfg
= fimc_read(EXYNOS_CISTATUS
);
180 if (EXYNOS_CISTATUS_GET_ENVID_STATUS(cfg
)) {
181 cfg
= fimc_read(EXYNOS_MSCTRL
);
182 cfg
&= ~EXYNOS_MSCTRL_ENVID
;
183 fimc_write(cfg
, EXYNOS_MSCTRL
);
186 cfg
= fimc_read(EXYNOS_CISRCFMT
);
187 cfg
|= EXYNOS_CISRCFMT_ITU601_8BIT
;
188 fimc_write(cfg
, EXYNOS_CISRCFMT
);
190 /* disable image capture */
191 cfg
= fimc_read(EXYNOS_CIIMGCPT
);
192 cfg
&= ~(EXYNOS_CIIMGCPT_IMGCPTEN_SC
| EXYNOS_CIIMGCPT_IMGCPTEN
);
193 fimc_write(cfg
, EXYNOS_CIIMGCPT
);
196 cfg
= fimc_read(EXYNOS_CIGCTRL
);
197 cfg
|= (EXYNOS_CIGCTRL_SWRST
);
198 fimc_write(cfg
, EXYNOS_CIGCTRL
);
200 /* s/w reset complete */
201 cfg
= fimc_read(EXYNOS_CIGCTRL
);
202 cfg
&= ~EXYNOS_CIGCTRL_SWRST
;
203 fimc_write(cfg
, EXYNOS_CIGCTRL
);
206 fimc_write(0x0, EXYNOS_CIFCNTSEQ
);
209 static int fimc_set_camblk_fimd0_wb(struct fimc_context
*ctx
)
211 return regmap_update_bits(ctx
->sysreg
, SYSREG_CAMERA_BLK
,
212 SYSREG_FIMD0WB_DEST_MASK
,
213 ctx
->id
<< SYSREG_FIMD0WB_DEST_SHIFT
);
216 static void fimc_set_type_ctrl(struct fimc_context
*ctx
, enum fimc_wb wb
)
220 DRM_DEBUG_KMS("wb[%d]\n", wb
);
222 cfg
= fimc_read(EXYNOS_CIGCTRL
);
223 cfg
&= ~(EXYNOS_CIGCTRL_TESTPATTERN_MASK
|
224 EXYNOS_CIGCTRL_SELCAM_ITU_MASK
|
225 EXYNOS_CIGCTRL_SELCAM_MIPI_MASK
|
226 EXYNOS_CIGCTRL_SELCAM_FIMC_MASK
|
227 EXYNOS_CIGCTRL_SELWB_CAMIF_MASK
|
228 EXYNOS_CIGCTRL_SELWRITEBACK_MASK
);
232 cfg
|= (EXYNOS_CIGCTRL_SELWRITEBACK_A
|
233 EXYNOS_CIGCTRL_SELWB_CAMIF_WRITEBACK
);
236 cfg
|= (EXYNOS_CIGCTRL_SELWRITEBACK_B
|
237 EXYNOS_CIGCTRL_SELWB_CAMIF_WRITEBACK
);
241 cfg
|= (EXYNOS_CIGCTRL_SELCAM_ITU_A
|
242 EXYNOS_CIGCTRL_SELWRITEBACK_A
|
243 EXYNOS_CIGCTRL_SELCAM_MIPI_A
|
244 EXYNOS_CIGCTRL_SELCAM_FIMC_ITU
);
248 fimc_write(cfg
, EXYNOS_CIGCTRL
);
251 static void fimc_set_polarity(struct fimc_context
*ctx
,
252 struct exynos_drm_ipp_pol
*pol
)
256 DRM_DEBUG_KMS("inv_pclk[%d]inv_vsync[%d]\n",
257 pol
->inv_pclk
, pol
->inv_vsync
);
258 DRM_DEBUG_KMS("inv_href[%d]inv_hsync[%d]\n",
259 pol
->inv_href
, pol
->inv_hsync
);
261 cfg
= fimc_read(EXYNOS_CIGCTRL
);
262 cfg
&= ~(EXYNOS_CIGCTRL_INVPOLPCLK
| EXYNOS_CIGCTRL_INVPOLVSYNC
|
263 EXYNOS_CIGCTRL_INVPOLHREF
| EXYNOS_CIGCTRL_INVPOLHSYNC
);
266 cfg
|= EXYNOS_CIGCTRL_INVPOLPCLK
;
268 cfg
|= EXYNOS_CIGCTRL_INVPOLVSYNC
;
270 cfg
|= EXYNOS_CIGCTRL_INVPOLHREF
;
272 cfg
|= EXYNOS_CIGCTRL_INVPOLHSYNC
;
274 fimc_write(cfg
, EXYNOS_CIGCTRL
);
277 static void fimc_handle_jpeg(struct fimc_context
*ctx
, bool enable
)
281 DRM_DEBUG_KMS("enable[%d]\n", enable
);
283 cfg
= fimc_read(EXYNOS_CIGCTRL
);
285 cfg
|= EXYNOS_CIGCTRL_CAM_JPEG
;
287 cfg
&= ~EXYNOS_CIGCTRL_CAM_JPEG
;
289 fimc_write(cfg
, EXYNOS_CIGCTRL
);
292 static void fimc_handle_irq(struct fimc_context
*ctx
, bool enable
,
293 bool overflow
, bool level
)
297 DRM_DEBUG_KMS("enable[%d]overflow[%d]level[%d]\n",
298 enable
, overflow
, level
);
300 cfg
= fimc_read(EXYNOS_CIGCTRL
);
302 cfg
&= ~(EXYNOS_CIGCTRL_IRQ_OVFEN
| EXYNOS_CIGCTRL_IRQ_LEVEL
);
303 cfg
|= EXYNOS_CIGCTRL_IRQ_ENABLE
;
305 cfg
|= EXYNOS_CIGCTRL_IRQ_OVFEN
;
307 cfg
|= EXYNOS_CIGCTRL_IRQ_LEVEL
;
309 cfg
&= ~(EXYNOS_CIGCTRL_IRQ_OVFEN
| EXYNOS_CIGCTRL_IRQ_ENABLE
);
311 fimc_write(cfg
, EXYNOS_CIGCTRL
);
314 static void fimc_clear_irq(struct fimc_context
*ctx
)
318 cfg
= fimc_read(EXYNOS_CIGCTRL
);
319 cfg
|= EXYNOS_CIGCTRL_IRQ_CLR
;
320 fimc_write(cfg
, EXYNOS_CIGCTRL
);
323 static bool fimc_check_ovf(struct fimc_context
*ctx
)
325 struct exynos_drm_ippdrv
*ippdrv
= &ctx
->ippdrv
;
326 u32 cfg
, status
, flag
;
328 status
= fimc_read(EXYNOS_CISTATUS
);
329 flag
= EXYNOS_CISTATUS_OVFIY
| EXYNOS_CISTATUS_OVFICB
|
330 EXYNOS_CISTATUS_OVFICR
;
332 DRM_DEBUG_KMS("flag[0x%x]\n", flag
);
335 cfg
= fimc_read(EXYNOS_CIWDOFST
);
336 cfg
|= (EXYNOS_CIWDOFST_CLROVFIY
| EXYNOS_CIWDOFST_CLROVFICB
|
337 EXYNOS_CIWDOFST_CLROVFICR
);
339 fimc_write(cfg
, EXYNOS_CIWDOFST
);
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 dev_err(ippdrv
->dev
, "occured overflow at %d, status 0x%x.\n",
355 static bool fimc_check_frame_end(struct fimc_context
*ctx
)
359 cfg
= fimc_read(EXYNOS_CISTATUS
);
361 DRM_DEBUG_KMS("cfg[0x%x]\n", cfg
);
363 if (!(cfg
& EXYNOS_CISTATUS_FRAMEEND
))
366 cfg
&= ~(EXYNOS_CISTATUS_FRAMEEND
);
367 fimc_write(cfg
, EXYNOS_CISTATUS
);
372 static int fimc_get_buf_id(struct fimc_context
*ctx
)
375 int frame_cnt
, buf_id
;
377 cfg
= fimc_read(EXYNOS_CISTATUS2
);
378 frame_cnt
= EXYNOS_CISTATUS2_GET_FRAMECOUNT_BEFORE(cfg
);
381 frame_cnt
= EXYNOS_CISTATUS2_GET_FRAMECOUNT_PRESENT(cfg
);
383 DRM_DEBUG_KMS("present[%d]before[%d]\n",
384 EXYNOS_CISTATUS2_GET_FRAMECOUNT_PRESENT(cfg
),
385 EXYNOS_CISTATUS2_GET_FRAMECOUNT_BEFORE(cfg
));
387 if (frame_cnt
== 0) {
388 DRM_ERROR("failed to get frame count.\n");
392 buf_id
= frame_cnt
- 1;
393 DRM_DEBUG_KMS("buf_id[%d]\n", buf_id
);
398 static void fimc_handle_lastend(struct fimc_context
*ctx
, bool enable
)
402 DRM_DEBUG_KMS("enable[%d]\n", enable
);
404 cfg
= fimc_read(EXYNOS_CIOCTRL
);
406 cfg
|= EXYNOS_CIOCTRL_LASTENDEN
;
408 cfg
&= ~EXYNOS_CIOCTRL_LASTENDEN
;
410 fimc_write(cfg
, EXYNOS_CIOCTRL
);
414 static int fimc_src_set_fmt_order(struct fimc_context
*ctx
, u32 fmt
)
416 struct exynos_drm_ippdrv
*ippdrv
= &ctx
->ippdrv
;
419 DRM_DEBUG_KMS("fmt[0x%x]\n", fmt
);
422 cfg
= fimc_read(EXYNOS_CISCCTRL
);
423 cfg
&= ~EXYNOS_CISCCTRL_INRGB_FMT_RGB_MASK
;
426 case DRM_FORMAT_RGB565
:
427 cfg
|= EXYNOS_CISCCTRL_INRGB_FMT_RGB565
;
428 fimc_write(cfg
, EXYNOS_CISCCTRL
);
430 case DRM_FORMAT_RGB888
:
431 case DRM_FORMAT_XRGB8888
:
432 cfg
|= EXYNOS_CISCCTRL_INRGB_FMT_RGB888
;
433 fimc_write(cfg
, EXYNOS_CISCCTRL
);
441 cfg
= fimc_read(EXYNOS_MSCTRL
);
442 cfg
&= ~(EXYNOS_MSCTRL_ORDER2P_SHIFT_MASK
|
443 EXYNOS_MSCTRL_C_INT_IN_2PLANE
|
444 EXYNOS_MSCTRL_ORDER422_YCBYCR
);
447 case DRM_FORMAT_YUYV
:
448 cfg
|= EXYNOS_MSCTRL_ORDER422_YCBYCR
;
450 case DRM_FORMAT_YVYU
:
451 cfg
|= EXYNOS_MSCTRL_ORDER422_YCRYCB
;
453 case DRM_FORMAT_UYVY
:
454 cfg
|= EXYNOS_MSCTRL_ORDER422_CBYCRY
;
456 case DRM_FORMAT_VYUY
:
457 case DRM_FORMAT_YUV444
:
458 cfg
|= EXYNOS_MSCTRL_ORDER422_CRYCBY
;
460 case DRM_FORMAT_NV21
:
461 case DRM_FORMAT_NV61
:
462 cfg
|= (EXYNOS_MSCTRL_ORDER2P_LSB_CRCB
|
463 EXYNOS_MSCTRL_C_INT_IN_2PLANE
);
465 case DRM_FORMAT_YUV422
:
466 case DRM_FORMAT_YUV420
:
467 case DRM_FORMAT_YVU420
:
468 cfg
|= EXYNOS_MSCTRL_C_INT_IN_3PLANE
;
470 case DRM_FORMAT_NV12
:
471 case DRM_FORMAT_NV12MT
:
472 case DRM_FORMAT_NV16
:
473 cfg
|= (EXYNOS_MSCTRL_ORDER2P_LSB_CBCR
|
474 EXYNOS_MSCTRL_C_INT_IN_2PLANE
);
477 dev_err(ippdrv
->dev
, "inavlid source yuv order 0x%x.\n", fmt
);
481 fimc_write(cfg
, EXYNOS_MSCTRL
);
486 static int fimc_src_set_fmt(struct device
*dev
, u32 fmt
)
488 struct fimc_context
*ctx
= get_fimc_context(dev
);
489 struct exynos_drm_ippdrv
*ippdrv
= &ctx
->ippdrv
;
492 DRM_DEBUG_KMS("fmt[0x%x]\n", fmt
);
494 cfg
= fimc_read(EXYNOS_MSCTRL
);
495 cfg
&= ~EXYNOS_MSCTRL_INFORMAT_RGB
;
498 case DRM_FORMAT_RGB565
:
499 case DRM_FORMAT_RGB888
:
500 case DRM_FORMAT_XRGB8888
:
501 cfg
|= EXYNOS_MSCTRL_INFORMAT_RGB
;
503 case DRM_FORMAT_YUV444
:
504 cfg
|= EXYNOS_MSCTRL_INFORMAT_YCBCR420
;
506 case DRM_FORMAT_YUYV
:
507 case DRM_FORMAT_YVYU
:
508 case DRM_FORMAT_UYVY
:
509 case DRM_FORMAT_VYUY
:
510 cfg
|= EXYNOS_MSCTRL_INFORMAT_YCBCR422_1PLANE
;
512 case DRM_FORMAT_NV16
:
513 case DRM_FORMAT_NV61
:
514 case DRM_FORMAT_YUV422
:
515 cfg
|= EXYNOS_MSCTRL_INFORMAT_YCBCR422
;
517 case DRM_FORMAT_YUV420
:
518 case DRM_FORMAT_YVU420
:
519 case DRM_FORMAT_NV12
:
520 case DRM_FORMAT_NV21
:
521 case DRM_FORMAT_NV12MT
:
522 cfg
|= EXYNOS_MSCTRL_INFORMAT_YCBCR420
;
525 dev_err(ippdrv
->dev
, "inavlid source format 0x%x.\n", fmt
);
529 fimc_write(cfg
, EXYNOS_MSCTRL
);
531 cfg
= fimc_read(EXYNOS_CIDMAPARAM
);
532 cfg
&= ~EXYNOS_CIDMAPARAM_R_MODE_MASK
;
534 if (fmt
== DRM_FORMAT_NV12MT
)
535 cfg
|= EXYNOS_CIDMAPARAM_R_MODE_64X32
;
537 cfg
|= EXYNOS_CIDMAPARAM_R_MODE_LINEAR
;
539 fimc_write(cfg
, EXYNOS_CIDMAPARAM
);
541 return fimc_src_set_fmt_order(ctx
, fmt
);
544 static int fimc_src_set_transf(struct device
*dev
,
545 enum drm_exynos_degree degree
,
546 enum drm_exynos_flip flip
, bool *swap
)
548 struct fimc_context
*ctx
= get_fimc_context(dev
);
549 struct exynos_drm_ippdrv
*ippdrv
= &ctx
->ippdrv
;
552 DRM_DEBUG_KMS("degree[%d]flip[0x%x]\n", degree
, flip
);
554 cfg1
= fimc_read(EXYNOS_MSCTRL
);
555 cfg1
&= ~(EXYNOS_MSCTRL_FLIP_X_MIRROR
|
556 EXYNOS_MSCTRL_FLIP_Y_MIRROR
);
558 cfg2
= fimc_read(EXYNOS_CITRGFMT
);
559 cfg2
&= ~EXYNOS_CITRGFMT_INROT90_CLOCKWISE
;
562 case EXYNOS_DRM_DEGREE_0
:
563 if (flip
& EXYNOS_DRM_FLIP_VERTICAL
)
564 cfg1
|= EXYNOS_MSCTRL_FLIP_X_MIRROR
;
565 if (flip
& EXYNOS_DRM_FLIP_HORIZONTAL
)
566 cfg1
|= EXYNOS_MSCTRL_FLIP_Y_MIRROR
;
568 case EXYNOS_DRM_DEGREE_90
:
569 cfg2
|= EXYNOS_CITRGFMT_INROT90_CLOCKWISE
;
570 if (flip
& EXYNOS_DRM_FLIP_VERTICAL
)
571 cfg1
|= EXYNOS_MSCTRL_FLIP_X_MIRROR
;
572 if (flip
& EXYNOS_DRM_FLIP_HORIZONTAL
)
573 cfg1
|= EXYNOS_MSCTRL_FLIP_Y_MIRROR
;
575 case EXYNOS_DRM_DEGREE_180
:
576 cfg1
|= (EXYNOS_MSCTRL_FLIP_X_MIRROR
|
577 EXYNOS_MSCTRL_FLIP_Y_MIRROR
);
578 if (flip
& EXYNOS_DRM_FLIP_VERTICAL
)
579 cfg1
&= ~EXYNOS_MSCTRL_FLIP_X_MIRROR
;
580 if (flip
& EXYNOS_DRM_FLIP_HORIZONTAL
)
581 cfg1
&= ~EXYNOS_MSCTRL_FLIP_Y_MIRROR
;
583 case EXYNOS_DRM_DEGREE_270
:
584 cfg1
|= (EXYNOS_MSCTRL_FLIP_X_MIRROR
|
585 EXYNOS_MSCTRL_FLIP_Y_MIRROR
);
586 cfg2
|= EXYNOS_CITRGFMT_INROT90_CLOCKWISE
;
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
;
593 dev_err(ippdrv
->dev
, "inavlid degree value %d.\n", degree
);
597 fimc_write(cfg1
, EXYNOS_MSCTRL
);
598 fimc_write(cfg2
, EXYNOS_CITRGFMT
);
599 *swap
= (cfg2
& EXYNOS_CITRGFMT_INROT90_CLOCKWISE
) ? 1 : 0;
604 static int fimc_set_window(struct fimc_context
*ctx
,
605 struct drm_exynos_pos
*pos
, struct drm_exynos_sz
*sz
)
607 u32 cfg
, h1
, h2
, v1
, v2
;
611 h2
= sz
->hsize
- pos
->w
- pos
->x
;
613 v2
= sz
->vsize
- pos
->h
- pos
->y
;
615 DRM_DEBUG_KMS("x[%d]y[%d]w[%d]h[%d]hsize[%d]vsize[%d]\n",
616 pos
->x
, pos
->y
, pos
->w
, pos
->h
, sz
->hsize
, sz
->vsize
);
617 DRM_DEBUG_KMS("h1[%d]h2[%d]v1[%d]v2[%d]\n", h1
, h2
, v1
, v2
);
620 * set window offset 1, 2 size
621 * check figure 43-21 in user manual
623 cfg
= fimc_read(EXYNOS_CIWDOFST
);
624 cfg
&= ~(EXYNOS_CIWDOFST_WINHOROFST_MASK
|
625 EXYNOS_CIWDOFST_WINVEROFST_MASK
);
626 cfg
|= (EXYNOS_CIWDOFST_WINHOROFST(h1
) |
627 EXYNOS_CIWDOFST_WINVEROFST(v1
));
628 cfg
|= EXYNOS_CIWDOFST_WINOFSEN
;
629 fimc_write(cfg
, EXYNOS_CIWDOFST
);
631 cfg
= (EXYNOS_CIWDOFST2_WINHOROFST2(h2
) |
632 EXYNOS_CIWDOFST2_WINVEROFST2(v2
));
633 fimc_write(cfg
, EXYNOS_CIWDOFST2
);
638 static int fimc_src_set_size(struct device
*dev
, int swap
,
639 struct drm_exynos_pos
*pos
, struct drm_exynos_sz
*sz
)
641 struct fimc_context
*ctx
= get_fimc_context(dev
);
642 struct drm_exynos_pos img_pos
= *pos
;
643 struct drm_exynos_sz img_sz
= *sz
;
646 DRM_DEBUG_KMS("swap[%d]hsize[%d]vsize[%d]\n",
647 swap
, sz
->hsize
, sz
->vsize
);
650 cfg
= (EXYNOS_ORGISIZE_HORIZONTAL(img_sz
.hsize
) |
651 EXYNOS_ORGISIZE_VERTICAL(img_sz
.vsize
));
653 fimc_write(cfg
, EXYNOS_ORGISIZE
);
655 DRM_DEBUG_KMS("x[%d]y[%d]w[%d]h[%d]\n", pos
->x
, pos
->y
, pos
->w
, pos
->h
);
660 img_sz
.hsize
= sz
->vsize
;
661 img_sz
.vsize
= sz
->hsize
;
664 /* set input DMA image size */
665 cfg
= fimc_read(EXYNOS_CIREAL_ISIZE
);
666 cfg
&= ~(EXYNOS_CIREAL_ISIZE_HEIGHT_MASK
|
667 EXYNOS_CIREAL_ISIZE_WIDTH_MASK
);
668 cfg
|= (EXYNOS_CIREAL_ISIZE_WIDTH(img_pos
.w
) |
669 EXYNOS_CIREAL_ISIZE_HEIGHT(img_pos
.h
));
670 fimc_write(cfg
, EXYNOS_CIREAL_ISIZE
);
673 * set input FIFO image size
674 * for now, we support only ITU601 8 bit mode
676 cfg
= (EXYNOS_CISRCFMT_ITU601_8BIT
|
677 EXYNOS_CISRCFMT_SOURCEHSIZE(img_sz
.hsize
) |
678 EXYNOS_CISRCFMT_SOURCEVSIZE(img_sz
.vsize
));
679 fimc_write(cfg
, EXYNOS_CISRCFMT
);
681 /* offset Y(RGB), Cb, Cr */
682 cfg
= (EXYNOS_CIIYOFF_HORIZONTAL(img_pos
.x
) |
683 EXYNOS_CIIYOFF_VERTICAL(img_pos
.y
));
684 fimc_write(cfg
, EXYNOS_CIIYOFF
);
685 cfg
= (EXYNOS_CIICBOFF_HORIZONTAL(img_pos
.x
) |
686 EXYNOS_CIICBOFF_VERTICAL(img_pos
.y
));
687 fimc_write(cfg
, EXYNOS_CIICBOFF
);
688 cfg
= (EXYNOS_CIICROFF_HORIZONTAL(img_pos
.x
) |
689 EXYNOS_CIICROFF_VERTICAL(img_pos
.y
));
690 fimc_write(cfg
, EXYNOS_CIICROFF
);
692 return fimc_set_window(ctx
, &img_pos
, &img_sz
);
695 static int fimc_src_set_addr(struct device
*dev
,
696 struct drm_exynos_ipp_buf_info
*buf_info
, u32 buf_id
,
697 enum drm_exynos_ipp_buf_type buf_type
)
699 struct fimc_context
*ctx
= get_fimc_context(dev
);
700 struct exynos_drm_ippdrv
*ippdrv
= &ctx
->ippdrv
;
701 struct drm_exynos_ipp_cmd_node
*c_node
= ippdrv
->c_node
;
702 struct drm_exynos_ipp_property
*property
;
703 struct drm_exynos_ipp_config
*config
;
706 DRM_ERROR("failed to get c_node.\n");
710 property
= &c_node
->property
;
712 DRM_DEBUG_KMS("prop_id[%d]buf_id[%d]buf_type[%d]\n",
713 property
->prop_id
, buf_id
, buf_type
);
715 if (buf_id
> FIMC_MAX_SRC
) {
716 dev_info(ippdrv
->dev
, "inavlid buf_id %d.\n", buf_id
);
720 /* address register set */
722 case IPP_BUF_ENQUEUE
:
723 config
= &property
->config
[EXYNOS_DRM_OPS_SRC
];
724 fimc_write(buf_info
->base
[EXYNOS_DRM_PLANAR_Y
],
725 EXYNOS_CIIYSA(buf_id
));
727 if (config
->fmt
== DRM_FORMAT_YVU420
) {
728 fimc_write(buf_info
->base
[EXYNOS_DRM_PLANAR_CR
],
729 EXYNOS_CIICBSA(buf_id
));
730 fimc_write(buf_info
->base
[EXYNOS_DRM_PLANAR_CB
],
731 EXYNOS_CIICRSA(buf_id
));
733 fimc_write(buf_info
->base
[EXYNOS_DRM_PLANAR_CB
],
734 EXYNOS_CIICBSA(buf_id
));
735 fimc_write(buf_info
->base
[EXYNOS_DRM_PLANAR_CR
],
736 EXYNOS_CIICRSA(buf_id
));
739 case IPP_BUF_DEQUEUE
:
740 fimc_write(0x0, EXYNOS_CIIYSA(buf_id
));
741 fimc_write(0x0, EXYNOS_CIICBSA(buf_id
));
742 fimc_write(0x0, EXYNOS_CIICRSA(buf_id
));
752 static struct exynos_drm_ipp_ops fimc_src_ops
= {
753 .set_fmt
= fimc_src_set_fmt
,
754 .set_transf
= fimc_src_set_transf
,
755 .set_size
= fimc_src_set_size
,
756 .set_addr
= fimc_src_set_addr
,
759 static int fimc_dst_set_fmt_order(struct fimc_context
*ctx
, u32 fmt
)
761 struct exynos_drm_ippdrv
*ippdrv
= &ctx
->ippdrv
;
764 DRM_DEBUG_KMS("fmt[0x%x]\n", fmt
);
767 cfg
= fimc_read(EXYNOS_CISCCTRL
);
768 cfg
&= ~EXYNOS_CISCCTRL_OUTRGB_FMT_RGB_MASK
;
771 case DRM_FORMAT_RGB565
:
772 cfg
|= EXYNOS_CISCCTRL_OUTRGB_FMT_RGB565
;
773 fimc_write(cfg
, EXYNOS_CISCCTRL
);
775 case DRM_FORMAT_RGB888
:
776 cfg
|= EXYNOS_CISCCTRL_OUTRGB_FMT_RGB888
;
777 fimc_write(cfg
, EXYNOS_CISCCTRL
);
779 case DRM_FORMAT_XRGB8888
:
780 cfg
|= (EXYNOS_CISCCTRL_OUTRGB_FMT_RGB888
|
781 EXYNOS_CISCCTRL_EXTRGB_EXTENSION
);
782 fimc_write(cfg
, EXYNOS_CISCCTRL
);
790 cfg
= fimc_read(EXYNOS_CIOCTRL
);
791 cfg
&= ~(EXYNOS_CIOCTRL_ORDER2P_MASK
|
792 EXYNOS_CIOCTRL_ORDER422_MASK
|
793 EXYNOS_CIOCTRL_YCBCR_PLANE_MASK
);
796 case DRM_FORMAT_XRGB8888
:
797 cfg
|= EXYNOS_CIOCTRL_ALPHA_OUT
;
799 case DRM_FORMAT_YUYV
:
800 cfg
|= EXYNOS_CIOCTRL_ORDER422_YCBYCR
;
802 case DRM_FORMAT_YVYU
:
803 cfg
|= EXYNOS_CIOCTRL_ORDER422_YCRYCB
;
805 case DRM_FORMAT_UYVY
:
806 cfg
|= EXYNOS_CIOCTRL_ORDER422_CBYCRY
;
808 case DRM_FORMAT_VYUY
:
809 cfg
|= EXYNOS_CIOCTRL_ORDER422_CRYCBY
;
811 case DRM_FORMAT_NV21
:
812 case DRM_FORMAT_NV61
:
813 cfg
|= EXYNOS_CIOCTRL_ORDER2P_LSB_CRCB
;
814 cfg
|= EXYNOS_CIOCTRL_YCBCR_2PLANE
;
816 case DRM_FORMAT_YUV422
:
817 case DRM_FORMAT_YUV420
:
818 case DRM_FORMAT_YVU420
:
819 cfg
|= EXYNOS_CIOCTRL_YCBCR_3PLANE
;
821 case DRM_FORMAT_NV12
:
822 case DRM_FORMAT_NV12MT
:
823 case DRM_FORMAT_NV16
:
824 cfg
|= EXYNOS_CIOCTRL_ORDER2P_LSB_CBCR
;
825 cfg
|= EXYNOS_CIOCTRL_YCBCR_2PLANE
;
828 dev_err(ippdrv
->dev
, "inavlid target yuv order 0x%x.\n", fmt
);
832 fimc_write(cfg
, EXYNOS_CIOCTRL
);
837 static int fimc_dst_set_fmt(struct device
*dev
, u32 fmt
)
839 struct fimc_context
*ctx
= get_fimc_context(dev
);
840 struct exynos_drm_ippdrv
*ippdrv
= &ctx
->ippdrv
;
843 DRM_DEBUG_KMS("fmt[0x%x]\n", fmt
);
845 cfg
= fimc_read(EXYNOS_CIEXTEN
);
847 if (fmt
== DRM_FORMAT_AYUV
) {
848 cfg
|= EXYNOS_CIEXTEN_YUV444_OUT
;
849 fimc_write(cfg
, EXYNOS_CIEXTEN
);
851 cfg
&= ~EXYNOS_CIEXTEN_YUV444_OUT
;
852 fimc_write(cfg
, EXYNOS_CIEXTEN
);
854 cfg
= fimc_read(EXYNOS_CITRGFMT
);
855 cfg
&= ~EXYNOS_CITRGFMT_OUTFORMAT_MASK
;
858 case DRM_FORMAT_RGB565
:
859 case DRM_FORMAT_RGB888
:
860 case DRM_FORMAT_XRGB8888
:
861 cfg
|= EXYNOS_CITRGFMT_OUTFORMAT_RGB
;
863 case DRM_FORMAT_YUYV
:
864 case DRM_FORMAT_YVYU
:
865 case DRM_FORMAT_UYVY
:
866 case DRM_FORMAT_VYUY
:
867 cfg
|= EXYNOS_CITRGFMT_OUTFORMAT_YCBCR422_1PLANE
;
869 case DRM_FORMAT_NV16
:
870 case DRM_FORMAT_NV61
:
871 case DRM_FORMAT_YUV422
:
872 cfg
|= EXYNOS_CITRGFMT_OUTFORMAT_YCBCR422
;
874 case DRM_FORMAT_YUV420
:
875 case DRM_FORMAT_YVU420
:
876 case DRM_FORMAT_NV12
:
877 case DRM_FORMAT_NV12MT
:
878 case DRM_FORMAT_NV21
:
879 cfg
|= EXYNOS_CITRGFMT_OUTFORMAT_YCBCR420
;
882 dev_err(ippdrv
->dev
, "inavlid target format 0x%x.\n",
887 fimc_write(cfg
, EXYNOS_CITRGFMT
);
890 cfg
= fimc_read(EXYNOS_CIDMAPARAM
);
891 cfg
&= ~EXYNOS_CIDMAPARAM_W_MODE_MASK
;
893 if (fmt
== DRM_FORMAT_NV12MT
)
894 cfg
|= EXYNOS_CIDMAPARAM_W_MODE_64X32
;
896 cfg
|= EXYNOS_CIDMAPARAM_W_MODE_LINEAR
;
898 fimc_write(cfg
, EXYNOS_CIDMAPARAM
);
900 return fimc_dst_set_fmt_order(ctx
, fmt
);
903 static int fimc_dst_set_transf(struct device
*dev
,
904 enum drm_exynos_degree degree
,
905 enum drm_exynos_flip flip
, bool *swap
)
907 struct fimc_context
*ctx
= get_fimc_context(dev
);
908 struct exynos_drm_ippdrv
*ippdrv
= &ctx
->ippdrv
;
911 DRM_DEBUG_KMS("degree[%d]flip[0x%x]\n", degree
, flip
);
913 cfg
= fimc_read(EXYNOS_CITRGFMT
);
914 cfg
&= ~EXYNOS_CITRGFMT_FLIP_MASK
;
915 cfg
&= ~EXYNOS_CITRGFMT_OUTROT90_CLOCKWISE
;
918 case EXYNOS_DRM_DEGREE_0
:
919 if (flip
& EXYNOS_DRM_FLIP_VERTICAL
)
920 cfg
|= EXYNOS_CITRGFMT_FLIP_X_MIRROR
;
921 if (flip
& EXYNOS_DRM_FLIP_HORIZONTAL
)
922 cfg
|= EXYNOS_CITRGFMT_FLIP_Y_MIRROR
;
924 case EXYNOS_DRM_DEGREE_90
:
925 cfg
|= EXYNOS_CITRGFMT_OUTROT90_CLOCKWISE
;
926 if (flip
& EXYNOS_DRM_FLIP_VERTICAL
)
927 cfg
|= EXYNOS_CITRGFMT_FLIP_X_MIRROR
;
928 if (flip
& EXYNOS_DRM_FLIP_HORIZONTAL
)
929 cfg
|= EXYNOS_CITRGFMT_FLIP_Y_MIRROR
;
931 case EXYNOS_DRM_DEGREE_180
:
932 cfg
|= (EXYNOS_CITRGFMT_FLIP_X_MIRROR
|
933 EXYNOS_CITRGFMT_FLIP_Y_MIRROR
);
934 if (flip
& EXYNOS_DRM_FLIP_VERTICAL
)
935 cfg
&= ~EXYNOS_CITRGFMT_FLIP_X_MIRROR
;
936 if (flip
& EXYNOS_DRM_FLIP_HORIZONTAL
)
937 cfg
&= ~EXYNOS_CITRGFMT_FLIP_Y_MIRROR
;
939 case EXYNOS_DRM_DEGREE_270
:
940 cfg
|= (EXYNOS_CITRGFMT_OUTROT90_CLOCKWISE
|
941 EXYNOS_CITRGFMT_FLIP_X_MIRROR
|
942 EXYNOS_CITRGFMT_FLIP_Y_MIRROR
);
943 if (flip
& EXYNOS_DRM_FLIP_VERTICAL
)
944 cfg
&= ~EXYNOS_CITRGFMT_FLIP_X_MIRROR
;
945 if (flip
& EXYNOS_DRM_FLIP_HORIZONTAL
)
946 cfg
&= ~EXYNOS_CITRGFMT_FLIP_Y_MIRROR
;
949 dev_err(ippdrv
->dev
, "inavlid degree value %d.\n", degree
);
953 fimc_write(cfg
, EXYNOS_CITRGFMT
);
954 *swap
= (cfg
& EXYNOS_CITRGFMT_OUTROT90_CLOCKWISE
) ? 1 : 0;
959 static int fimc_get_ratio_shift(u32 src
, u32 dst
, u32
*ratio
, u32
*shift
)
961 DRM_DEBUG_KMS("src[%d]dst[%d]\n", src
, dst
);
963 if (src
>= dst
* 64) {
964 DRM_ERROR("failed to make ratio and shift.\n");
966 } else if (src
>= dst
* 32) {
969 } else if (src
>= dst
* 16) {
972 } else if (src
>= dst
* 8) {
975 } else if (src
>= dst
* 4) {
978 } else if (src
>= dst
* 2) {
989 static int fimc_set_prescaler(struct fimc_context
*ctx
, struct fimc_scaler
*sc
,
990 struct drm_exynos_pos
*src
, struct drm_exynos_pos
*dst
)
992 struct exynos_drm_ippdrv
*ippdrv
= &ctx
->ippdrv
;
993 u32 cfg
, cfg_ext
, shfactor
;
994 u32 pre_dst_width
, pre_dst_height
;
995 u32 pre_hratio
, hfactor
, pre_vratio
, vfactor
;
997 u32 src_w
, src_h
, dst_w
, dst_h
;
999 cfg_ext
= fimc_read(EXYNOS_CITRGFMT
);
1000 if (cfg_ext
& EXYNOS_CITRGFMT_INROT90_CLOCKWISE
) {
1008 if (cfg_ext
& EXYNOS_CITRGFMT_OUTROT90_CLOCKWISE
) {
1016 ret
= fimc_get_ratio_shift(src_w
, dst_w
, &pre_hratio
, &hfactor
);
1018 dev_err(ippdrv
->dev
, "failed to get ratio horizontal.\n");
1022 ret
= fimc_get_ratio_shift(src_h
, dst_h
, &pre_vratio
, &vfactor
);
1024 dev_err(ippdrv
->dev
, "failed to get ratio vertical.\n");
1028 pre_dst_width
= src_w
/ pre_hratio
;
1029 pre_dst_height
= src_h
/ pre_vratio
;
1030 DRM_DEBUG_KMS("pre_dst_width[%d]pre_dst_height[%d]\n",
1031 pre_dst_width
, pre_dst_height
);
1032 DRM_DEBUG_KMS("pre_hratio[%d]hfactor[%d]pre_vratio[%d]vfactor[%d]\n",
1033 pre_hratio
, hfactor
, pre_vratio
, vfactor
);
1035 sc
->hratio
= (src_w
<< 14) / (dst_w
<< hfactor
);
1036 sc
->vratio
= (src_h
<< 14) / (dst_h
<< vfactor
);
1037 sc
->up_h
= (dst_w
>= src_w
) ? true : false;
1038 sc
->up_v
= (dst_h
>= src_h
) ? true : false;
1039 DRM_DEBUG_KMS("hratio[%d]vratio[%d]up_h[%d]up_v[%d]\n",
1040 sc
->hratio
, sc
->vratio
, sc
->up_h
, sc
->up_v
);
1042 shfactor
= FIMC_SHFACTOR
- (hfactor
+ vfactor
);
1043 DRM_DEBUG_KMS("shfactor[%d]\n", shfactor
);
1045 cfg
= (EXYNOS_CISCPRERATIO_SHFACTOR(shfactor
) |
1046 EXYNOS_CISCPRERATIO_PREHORRATIO(pre_hratio
) |
1047 EXYNOS_CISCPRERATIO_PREVERRATIO(pre_vratio
));
1048 fimc_write(cfg
, EXYNOS_CISCPRERATIO
);
1050 cfg
= (EXYNOS_CISCPREDST_PREDSTWIDTH(pre_dst_width
) |
1051 EXYNOS_CISCPREDST_PREDSTHEIGHT(pre_dst_height
));
1052 fimc_write(cfg
, EXYNOS_CISCPREDST
);
1057 static void fimc_set_scaler(struct fimc_context
*ctx
, struct fimc_scaler
*sc
)
1061 DRM_DEBUG_KMS("range[%d]bypass[%d]up_h[%d]up_v[%d]\n",
1062 sc
->range
, sc
->bypass
, sc
->up_h
, sc
->up_v
);
1063 DRM_DEBUG_KMS("hratio[%d]vratio[%d]\n",
1064 sc
->hratio
, sc
->vratio
);
1066 cfg
= fimc_read(EXYNOS_CISCCTRL
);
1067 cfg
&= ~(EXYNOS_CISCCTRL_SCALERBYPASS
|
1068 EXYNOS_CISCCTRL_SCALEUP_H
| EXYNOS_CISCCTRL_SCALEUP_V
|
1069 EXYNOS_CISCCTRL_MAIN_V_RATIO_MASK
|
1070 EXYNOS_CISCCTRL_MAIN_H_RATIO_MASK
|
1071 EXYNOS_CISCCTRL_CSCR2Y_WIDE
|
1072 EXYNOS_CISCCTRL_CSCY2R_WIDE
);
1075 cfg
|= (EXYNOS_CISCCTRL_CSCR2Y_WIDE
|
1076 EXYNOS_CISCCTRL_CSCY2R_WIDE
);
1078 cfg
|= EXYNOS_CISCCTRL_SCALERBYPASS
;
1080 cfg
|= EXYNOS_CISCCTRL_SCALEUP_H
;
1082 cfg
|= EXYNOS_CISCCTRL_SCALEUP_V
;
1084 cfg
|= (EXYNOS_CISCCTRL_MAINHORRATIO((sc
->hratio
>> 6)) |
1085 EXYNOS_CISCCTRL_MAINVERRATIO((sc
->vratio
>> 6)));
1086 fimc_write(cfg
, EXYNOS_CISCCTRL
);
1088 cfg_ext
= fimc_read(EXYNOS_CIEXTEN
);
1089 cfg_ext
&= ~EXYNOS_CIEXTEN_MAINHORRATIO_EXT_MASK
;
1090 cfg_ext
&= ~EXYNOS_CIEXTEN_MAINVERRATIO_EXT_MASK
;
1091 cfg_ext
|= (EXYNOS_CIEXTEN_MAINHORRATIO_EXT(sc
->hratio
) |
1092 EXYNOS_CIEXTEN_MAINVERRATIO_EXT(sc
->vratio
));
1093 fimc_write(cfg_ext
, EXYNOS_CIEXTEN
);
1096 static int fimc_dst_set_size(struct device
*dev
, int swap
,
1097 struct drm_exynos_pos
*pos
, struct drm_exynos_sz
*sz
)
1099 struct fimc_context
*ctx
= get_fimc_context(dev
);
1100 struct drm_exynos_pos img_pos
= *pos
;
1101 struct drm_exynos_sz img_sz
= *sz
;
1104 DRM_DEBUG_KMS("swap[%d]hsize[%d]vsize[%d]\n",
1105 swap
, sz
->hsize
, sz
->vsize
);
1108 cfg
= (EXYNOS_ORGOSIZE_HORIZONTAL(img_sz
.hsize
) |
1109 EXYNOS_ORGOSIZE_VERTICAL(img_sz
.vsize
));
1111 fimc_write(cfg
, EXYNOS_ORGOSIZE
);
1113 DRM_DEBUG_KMS("x[%d]y[%d]w[%d]h[%d]\n", pos
->x
, pos
->y
, pos
->w
, pos
->h
);
1116 cfg
= fimc_read(EXYNOS_CIGCTRL
);
1117 cfg
&= ~EXYNOS_CIGCTRL_CSC_MASK
;
1119 if (sz
->hsize
>= FIMC_WIDTH_ITU_709
)
1120 cfg
|= EXYNOS_CIGCTRL_CSC_ITU709
;
1122 cfg
|= EXYNOS_CIGCTRL_CSC_ITU601
;
1124 fimc_write(cfg
, EXYNOS_CIGCTRL
);
1129 img_sz
.hsize
= sz
->vsize
;
1130 img_sz
.vsize
= sz
->hsize
;
1133 /* target image size */
1134 cfg
= fimc_read(EXYNOS_CITRGFMT
);
1135 cfg
&= ~(EXYNOS_CITRGFMT_TARGETH_MASK
|
1136 EXYNOS_CITRGFMT_TARGETV_MASK
);
1137 cfg
|= (EXYNOS_CITRGFMT_TARGETHSIZE(img_pos
.w
) |
1138 EXYNOS_CITRGFMT_TARGETVSIZE(img_pos
.h
));
1139 fimc_write(cfg
, EXYNOS_CITRGFMT
);
1142 cfg
= EXYNOS_CITAREA_TARGET_AREA(img_pos
.w
* img_pos
.h
);
1143 fimc_write(cfg
, EXYNOS_CITAREA
);
1145 /* offset Y(RGB), Cb, Cr */
1146 cfg
= (EXYNOS_CIOYOFF_HORIZONTAL(img_pos
.x
) |
1147 EXYNOS_CIOYOFF_VERTICAL(img_pos
.y
));
1148 fimc_write(cfg
, EXYNOS_CIOYOFF
);
1149 cfg
= (EXYNOS_CIOCBOFF_HORIZONTAL(img_pos
.x
) |
1150 EXYNOS_CIOCBOFF_VERTICAL(img_pos
.y
));
1151 fimc_write(cfg
, EXYNOS_CIOCBOFF
);
1152 cfg
= (EXYNOS_CIOCROFF_HORIZONTAL(img_pos
.x
) |
1153 EXYNOS_CIOCROFF_VERTICAL(img_pos
.y
));
1154 fimc_write(cfg
, EXYNOS_CIOCROFF
);
1159 static int fimc_dst_get_buf_seq(struct fimc_context
*ctx
)
1161 u32 cfg
, i
, buf_num
= 0;
1162 u32 mask
= 0x00000001;
1164 cfg
= fimc_read(EXYNOS_CIFCNTSEQ
);
1166 for (i
= 0; i
< FIMC_REG_SZ
; i
++)
1167 if (cfg
& (mask
<< i
))
1170 DRM_DEBUG_KMS("buf_num[%d]\n", buf_num
);
1175 static int fimc_dst_set_buf_seq(struct fimc_context
*ctx
, u32 buf_id
,
1176 enum drm_exynos_ipp_buf_type buf_type
)
1178 struct exynos_drm_ippdrv
*ippdrv
= &ctx
->ippdrv
;
1181 u32 mask
= 0x00000001 << buf_id
;
1184 DRM_DEBUG_KMS("buf_id[%d]buf_type[%d]\n", buf_id
, buf_type
);
1186 mutex_lock(&ctx
->lock
);
1188 /* mask register set */
1189 cfg
= fimc_read(EXYNOS_CIFCNTSEQ
);
1192 case IPP_BUF_ENQUEUE
:
1195 case IPP_BUF_DEQUEUE
:
1199 dev_err(ippdrv
->dev
, "invalid buf ctrl parameter.\n");
1206 cfg
|= (enable
<< buf_id
);
1207 fimc_write(cfg
, EXYNOS_CIFCNTSEQ
);
1209 /* interrupt enable */
1210 if (buf_type
== IPP_BUF_ENQUEUE
&&
1211 fimc_dst_get_buf_seq(ctx
) >= FIMC_BUF_START
)
1212 fimc_handle_irq(ctx
, true, false, true);
1214 /* interrupt disable */
1215 if (buf_type
== IPP_BUF_DEQUEUE
&&
1216 fimc_dst_get_buf_seq(ctx
) <= FIMC_BUF_STOP
)
1217 fimc_handle_irq(ctx
, false, false, true);
1220 mutex_unlock(&ctx
->lock
);
1224 static int fimc_dst_set_addr(struct device
*dev
,
1225 struct drm_exynos_ipp_buf_info
*buf_info
, u32 buf_id
,
1226 enum drm_exynos_ipp_buf_type buf_type
)
1228 struct fimc_context
*ctx
= get_fimc_context(dev
);
1229 struct exynos_drm_ippdrv
*ippdrv
= &ctx
->ippdrv
;
1230 struct drm_exynos_ipp_cmd_node
*c_node
= ippdrv
->c_node
;
1231 struct drm_exynos_ipp_property
*property
;
1232 struct drm_exynos_ipp_config
*config
;
1235 DRM_ERROR("failed to get c_node.\n");
1239 property
= &c_node
->property
;
1241 DRM_DEBUG_KMS("prop_id[%d]buf_id[%d]buf_type[%d]\n",
1242 property
->prop_id
, buf_id
, buf_type
);
1244 if (buf_id
> FIMC_MAX_DST
) {
1245 dev_info(ippdrv
->dev
, "inavlid buf_id %d.\n", buf_id
);
1249 /* address register set */
1251 case IPP_BUF_ENQUEUE
:
1252 config
= &property
->config
[EXYNOS_DRM_OPS_DST
];
1254 fimc_write(buf_info
->base
[EXYNOS_DRM_PLANAR_Y
],
1255 EXYNOS_CIOYSA(buf_id
));
1257 if (config
->fmt
== DRM_FORMAT_YVU420
) {
1258 fimc_write(buf_info
->base
[EXYNOS_DRM_PLANAR_CR
],
1259 EXYNOS_CIOCBSA(buf_id
));
1260 fimc_write(buf_info
->base
[EXYNOS_DRM_PLANAR_CB
],
1261 EXYNOS_CIOCRSA(buf_id
));
1263 fimc_write(buf_info
->base
[EXYNOS_DRM_PLANAR_CB
],
1264 EXYNOS_CIOCBSA(buf_id
));
1265 fimc_write(buf_info
->base
[EXYNOS_DRM_PLANAR_CR
],
1266 EXYNOS_CIOCRSA(buf_id
));
1269 case IPP_BUF_DEQUEUE
:
1270 fimc_write(0x0, EXYNOS_CIOYSA(buf_id
));
1271 fimc_write(0x0, EXYNOS_CIOCBSA(buf_id
));
1272 fimc_write(0x0, EXYNOS_CIOCRSA(buf_id
));
1279 return fimc_dst_set_buf_seq(ctx
, buf_id
, buf_type
);
1282 static struct exynos_drm_ipp_ops fimc_dst_ops
= {
1283 .set_fmt
= fimc_dst_set_fmt
,
1284 .set_transf
= fimc_dst_set_transf
,
1285 .set_size
= fimc_dst_set_size
,
1286 .set_addr
= fimc_dst_set_addr
,
1289 static int fimc_clk_ctrl(struct fimc_context
*ctx
, bool enable
)
1291 DRM_DEBUG_KMS("enable[%d]\n", enable
);
1294 clk_prepare_enable(ctx
->clocks
[FIMC_CLK_GATE
]);
1295 clk_prepare_enable(ctx
->clocks
[FIMC_CLK_WB_A
]);
1296 ctx
->suspended
= false;
1298 clk_disable_unprepare(ctx
->clocks
[FIMC_CLK_GATE
]);
1299 clk_disable_unprepare(ctx
->clocks
[FIMC_CLK_WB_A
]);
1300 ctx
->suspended
= true;
1306 static irqreturn_t
fimc_irq_handler(int irq
, void *dev_id
)
1308 struct fimc_context
*ctx
= dev_id
;
1309 struct exynos_drm_ippdrv
*ippdrv
= &ctx
->ippdrv
;
1310 struct drm_exynos_ipp_cmd_node
*c_node
= ippdrv
->c_node
;
1311 struct drm_exynos_ipp_event_work
*event_work
=
1315 DRM_DEBUG_KMS("fimc id[%d]\n", ctx
->id
);
1317 fimc_clear_irq(ctx
);
1318 if (fimc_check_ovf(ctx
))
1321 if (!fimc_check_frame_end(ctx
))
1324 buf_id
= fimc_get_buf_id(ctx
);
1328 DRM_DEBUG_KMS("buf_id[%d]\n", buf_id
);
1330 if (fimc_dst_set_buf_seq(ctx
, buf_id
, IPP_BUF_DEQUEUE
) < 0) {
1331 DRM_ERROR("failed to dequeue.\n");
1335 event_work
->ippdrv
= ippdrv
;
1336 event_work
->buf_id
[EXYNOS_DRM_OPS_DST
] = buf_id
;
1337 queue_work(ippdrv
->event_workq
, (struct work_struct
*)event_work
);
1342 static int fimc_init_prop_list(struct exynos_drm_ippdrv
*ippdrv
)
1344 struct drm_exynos_ipp_prop_list
*prop_list
;
1346 prop_list
= devm_kzalloc(ippdrv
->dev
, sizeof(*prop_list
), GFP_KERNEL
);
1348 DRM_ERROR("failed to alloc property list.\n");
1352 prop_list
->version
= 1;
1353 prop_list
->writeback
= 1;
1354 prop_list
->refresh_min
= FIMC_REFRESH_MIN
;
1355 prop_list
->refresh_max
= FIMC_REFRESH_MAX
;
1356 prop_list
->flip
= (1 << EXYNOS_DRM_FLIP_NONE
) |
1357 (1 << EXYNOS_DRM_FLIP_VERTICAL
) |
1358 (1 << EXYNOS_DRM_FLIP_HORIZONTAL
);
1359 prop_list
->degree
= (1 << EXYNOS_DRM_DEGREE_0
) |
1360 (1 << EXYNOS_DRM_DEGREE_90
) |
1361 (1 << EXYNOS_DRM_DEGREE_180
) |
1362 (1 << EXYNOS_DRM_DEGREE_270
);
1364 prop_list
->crop
= 1;
1365 prop_list
->crop_max
.hsize
= FIMC_CROP_MAX
;
1366 prop_list
->crop_max
.vsize
= FIMC_CROP_MAX
;
1367 prop_list
->crop_min
.hsize
= FIMC_CROP_MIN
;
1368 prop_list
->crop_min
.vsize
= FIMC_CROP_MIN
;
1369 prop_list
->scale
= 1;
1370 prop_list
->scale_max
.hsize
= FIMC_SCALE_MAX
;
1371 prop_list
->scale_max
.vsize
= FIMC_SCALE_MAX
;
1372 prop_list
->scale_min
.hsize
= FIMC_SCALE_MIN
;
1373 prop_list
->scale_min
.vsize
= FIMC_SCALE_MIN
;
1375 ippdrv
->prop_list
= prop_list
;
1380 static inline bool fimc_check_drm_flip(enum drm_exynos_flip flip
)
1383 case EXYNOS_DRM_FLIP_NONE
:
1384 case EXYNOS_DRM_FLIP_VERTICAL
:
1385 case EXYNOS_DRM_FLIP_HORIZONTAL
:
1386 case EXYNOS_DRM_FLIP_BOTH
:
1389 DRM_DEBUG_KMS("invalid flip\n");
1394 static int fimc_ippdrv_check_property(struct device
*dev
,
1395 struct drm_exynos_ipp_property
*property
)
1397 struct fimc_context
*ctx
= get_fimc_context(dev
);
1398 struct exynos_drm_ippdrv
*ippdrv
= &ctx
->ippdrv
;
1399 struct drm_exynos_ipp_prop_list
*pp
= ippdrv
->prop_list
;
1400 struct drm_exynos_ipp_config
*config
;
1401 struct drm_exynos_pos
*pos
;
1402 struct drm_exynos_sz
*sz
;
1406 for_each_ipp_ops(i
) {
1407 if ((i
== EXYNOS_DRM_OPS_SRC
) &&
1408 (property
->cmd
== IPP_CMD_WB
))
1411 config
= &property
->config
[i
];
1415 /* check for flip */
1416 if (!fimc_check_drm_flip(config
->flip
)) {
1417 DRM_ERROR("invalid flip.\n");
1421 /* check for degree */
1422 switch (config
->degree
) {
1423 case EXYNOS_DRM_DEGREE_90
:
1424 case EXYNOS_DRM_DEGREE_270
:
1427 case EXYNOS_DRM_DEGREE_0
:
1428 case EXYNOS_DRM_DEGREE_180
:
1432 DRM_ERROR("invalid degree.\n");
1436 /* check for buffer bound */
1437 if ((pos
->x
+ pos
->w
> sz
->hsize
) ||
1438 (pos
->y
+ pos
->h
> sz
->vsize
)) {
1439 DRM_ERROR("out of buf bound.\n");
1443 /* check for crop */
1444 if ((i
== EXYNOS_DRM_OPS_SRC
) && (pp
->crop
)) {
1446 if ((pos
->h
< pp
->crop_min
.hsize
) ||
1447 (sz
->vsize
> pp
->crop_max
.hsize
) ||
1448 (pos
->w
< pp
->crop_min
.vsize
) ||
1449 (sz
->hsize
> pp
->crop_max
.vsize
)) {
1450 DRM_ERROR("out of crop size.\n");
1454 if ((pos
->w
< pp
->crop_min
.hsize
) ||
1455 (sz
->hsize
> pp
->crop_max
.hsize
) ||
1456 (pos
->h
< pp
->crop_min
.vsize
) ||
1457 (sz
->vsize
> pp
->crop_max
.vsize
)) {
1458 DRM_ERROR("out of crop size.\n");
1464 /* check for scale */
1465 if ((i
== EXYNOS_DRM_OPS_DST
) && (pp
->scale
)) {
1467 if ((pos
->h
< pp
->scale_min
.hsize
) ||
1468 (sz
->vsize
> pp
->scale_max
.hsize
) ||
1469 (pos
->w
< pp
->scale_min
.vsize
) ||
1470 (sz
->hsize
> pp
->scale_max
.vsize
)) {
1471 DRM_ERROR("out of scale size.\n");
1475 if ((pos
->w
< pp
->scale_min
.hsize
) ||
1476 (sz
->hsize
> pp
->scale_max
.hsize
) ||
1477 (pos
->h
< pp
->scale_min
.vsize
) ||
1478 (sz
->vsize
> pp
->scale_max
.vsize
)) {
1479 DRM_ERROR("out of scale size.\n");
1489 for_each_ipp_ops(i
) {
1490 if ((i
== EXYNOS_DRM_OPS_SRC
) &&
1491 (property
->cmd
== IPP_CMD_WB
))
1494 config
= &property
->config
[i
];
1498 DRM_ERROR("[%s]f[%d]r[%d]pos[%d %d %d %d]sz[%d %d]\n",
1499 i
? "dst" : "src", config
->flip
, config
->degree
,
1500 pos
->x
, pos
->y
, pos
->w
, pos
->h
,
1501 sz
->hsize
, sz
->vsize
);
1507 static void fimc_clear_addr(struct fimc_context
*ctx
)
1511 for (i
= 0; i
< FIMC_MAX_SRC
; i
++) {
1512 fimc_write(0, EXYNOS_CIIYSA(i
));
1513 fimc_write(0, EXYNOS_CIICBSA(i
));
1514 fimc_write(0, EXYNOS_CIICRSA(i
));
1517 for (i
= 0; i
< FIMC_MAX_DST
; i
++) {
1518 fimc_write(0, EXYNOS_CIOYSA(i
));
1519 fimc_write(0, EXYNOS_CIOCBSA(i
));
1520 fimc_write(0, EXYNOS_CIOCRSA(i
));
1524 static int fimc_ippdrv_reset(struct device
*dev
)
1526 struct fimc_context
*ctx
= get_fimc_context(dev
);
1528 /* reset h/w block */
1531 /* reset scaler capability */
1532 memset(&ctx
->sc
, 0x0, sizeof(ctx
->sc
));
1534 fimc_clear_addr(ctx
);
1539 static int fimc_ippdrv_start(struct device
*dev
, enum drm_exynos_ipp_cmd cmd
)
1541 struct fimc_context
*ctx
= get_fimc_context(dev
);
1542 struct exynos_drm_ippdrv
*ippdrv
= &ctx
->ippdrv
;
1543 struct drm_exynos_ipp_cmd_node
*c_node
= ippdrv
->c_node
;
1544 struct drm_exynos_ipp_property
*property
;
1545 struct drm_exynos_ipp_config
*config
;
1546 struct drm_exynos_pos img_pos
[EXYNOS_DRM_OPS_MAX
];
1547 struct drm_exynos_ipp_set_wb set_wb
;
1551 DRM_DEBUG_KMS("cmd[%d]\n", cmd
);
1554 DRM_ERROR("failed to get c_node.\n");
1558 property
= &c_node
->property
;
1560 fimc_handle_irq(ctx
, true, false, true);
1562 for_each_ipp_ops(i
) {
1563 config
= &property
->config
[i
];
1564 img_pos
[i
] = config
->pos
;
1567 ret
= fimc_set_prescaler(ctx
, &ctx
->sc
,
1568 &img_pos
[EXYNOS_DRM_OPS_SRC
],
1569 &img_pos
[EXYNOS_DRM_OPS_DST
]);
1571 dev_err(dev
, "failed to set precalser.\n");
1575 /* If set ture, we can save jpeg about screen */
1576 fimc_handle_jpeg(ctx
, false);
1577 fimc_set_scaler(ctx
, &ctx
->sc
);
1578 fimc_set_polarity(ctx
, &ctx
->pol
);
1582 fimc_set_type_ctrl(ctx
, FIMC_WB_NONE
);
1583 fimc_handle_lastend(ctx
, false);
1586 cfg0
= fimc_read(EXYNOS_MSCTRL
);
1587 cfg0
&= ~EXYNOS_MSCTRL_INPUT_MASK
;
1588 cfg0
|= EXYNOS_MSCTRL_INPUT_MEMORY
;
1589 fimc_write(cfg0
, EXYNOS_MSCTRL
);
1592 fimc_set_type_ctrl(ctx
, FIMC_WB_A
);
1593 fimc_handle_lastend(ctx
, true);
1596 ret
= fimc_set_camblk_fimd0_wb(ctx
);
1598 dev_err(dev
, "camblk setup failed.\n");
1603 set_wb
.refresh
= property
->refresh_rate
;
1604 exynos_drm_ippnb_send_event(IPP_SET_WRITEBACK
, (void *)&set_wb
);
1606 case IPP_CMD_OUTPUT
:
1609 dev_err(dev
, "invalid operations.\n");
1614 fimc_write(0x0, EXYNOS_CISTATUS
);
1616 cfg0
= fimc_read(EXYNOS_CIIMGCPT
);
1617 cfg0
&= ~EXYNOS_CIIMGCPT_IMGCPTEN_SC
;
1618 cfg0
|= EXYNOS_CIIMGCPT_IMGCPTEN_SC
;
1621 cfg1
= fimc_read(EXYNOS_CISCCTRL
);
1622 cfg1
&= ~EXYNOS_CISCCTRL_SCAN_MASK
;
1623 cfg1
|= (EXYNOS_CISCCTRL_PROGRESSIVE
|
1624 EXYNOS_CISCCTRL_SCALERSTART
);
1626 fimc_write(cfg1
, EXYNOS_CISCCTRL
);
1628 /* Enable image capture*/
1629 cfg0
|= EXYNOS_CIIMGCPT_IMGCPTEN
;
1630 fimc_write(cfg0
, EXYNOS_CIIMGCPT
);
1632 /* Disable frame end irq */
1633 cfg0
= fimc_read(EXYNOS_CIGCTRL
);
1634 cfg0
&= ~EXYNOS_CIGCTRL_IRQ_END_DISABLE
;
1635 fimc_write(cfg0
, EXYNOS_CIGCTRL
);
1637 cfg0
= fimc_read(EXYNOS_CIOCTRL
);
1638 cfg0
&= ~EXYNOS_CIOCTRL_WEAVE_MASK
;
1639 fimc_write(cfg0
, EXYNOS_CIOCTRL
);
1641 if (cmd
== IPP_CMD_M2M
) {
1642 cfg0
= fimc_read(EXYNOS_MSCTRL
);
1643 cfg0
|= EXYNOS_MSCTRL_ENVID
;
1644 fimc_write(cfg0
, EXYNOS_MSCTRL
);
1646 cfg0
= fimc_read(EXYNOS_MSCTRL
);
1647 cfg0
|= EXYNOS_MSCTRL_ENVID
;
1648 fimc_write(cfg0
, EXYNOS_MSCTRL
);
1654 static void fimc_ippdrv_stop(struct device
*dev
, enum drm_exynos_ipp_cmd cmd
)
1656 struct fimc_context
*ctx
= get_fimc_context(dev
);
1657 struct drm_exynos_ipp_set_wb set_wb
= {0, 0};
1660 DRM_DEBUG_KMS("cmd[%d]\n", cmd
);
1665 cfg
= fimc_read(EXYNOS_MSCTRL
);
1666 cfg
&= ~EXYNOS_MSCTRL_INPUT_MASK
;
1667 cfg
&= ~EXYNOS_MSCTRL_ENVID
;
1668 fimc_write(cfg
, EXYNOS_MSCTRL
);
1671 exynos_drm_ippnb_send_event(IPP_SET_WRITEBACK
, (void *)&set_wb
);
1673 case IPP_CMD_OUTPUT
:
1675 dev_err(dev
, "invalid operations.\n");
1679 fimc_handle_irq(ctx
, false, false, true);
1681 /* reset sequence */
1682 fimc_write(0x0, EXYNOS_CIFCNTSEQ
);
1684 /* Scaler disable */
1685 cfg
= fimc_read(EXYNOS_CISCCTRL
);
1686 cfg
&= ~EXYNOS_CISCCTRL_SCALERSTART
;
1687 fimc_write(cfg
, EXYNOS_CISCCTRL
);
1689 /* Disable image capture */
1690 cfg
= fimc_read(EXYNOS_CIIMGCPT
);
1691 cfg
&= ~(EXYNOS_CIIMGCPT_IMGCPTEN_SC
| EXYNOS_CIIMGCPT_IMGCPTEN
);
1692 fimc_write(cfg
, EXYNOS_CIIMGCPT
);
1694 /* Enable frame end irq */
1695 cfg
= fimc_read(EXYNOS_CIGCTRL
);
1696 cfg
|= EXYNOS_CIGCTRL_IRQ_END_DISABLE
;
1697 fimc_write(cfg
, EXYNOS_CIGCTRL
);
1700 static void fimc_put_clocks(struct fimc_context
*ctx
)
1704 for (i
= 0; i
< FIMC_CLKS_MAX
; i
++) {
1705 if (IS_ERR(ctx
->clocks
[i
]))
1707 clk_put(ctx
->clocks
[i
]);
1708 ctx
->clocks
[i
] = ERR_PTR(-EINVAL
);
1712 static int fimc_setup_clocks(struct fimc_context
*ctx
)
1714 struct device
*fimc_dev
= ctx
->ippdrv
.dev
;
1718 for (i
= 0; i
< FIMC_CLKS_MAX
; i
++)
1719 ctx
->clocks
[i
] = ERR_PTR(-EINVAL
);
1721 for (i
= 0; i
< FIMC_CLKS_MAX
; i
++) {
1722 if (i
== FIMC_CLK_WB_A
|| i
== FIMC_CLK_WB_B
)
1723 dev
= fimc_dev
->parent
;
1727 ctx
->clocks
[i
] = clk_get(dev
, fimc_clock_names
[i
]);
1728 if (IS_ERR(ctx
->clocks
[i
])) {
1729 if (i
>= FIMC_CLK_MUX
)
1731 ret
= PTR_ERR(ctx
->clocks
[i
]);
1732 dev_err(fimc_dev
, "failed to get clock: %s\n",
1733 fimc_clock_names
[i
]);
1738 /* Optional FIMC LCLK parent clock setting */
1739 if (!IS_ERR(ctx
->clocks
[FIMC_CLK_PARENT
])) {
1740 ret
= clk_set_parent(ctx
->clocks
[FIMC_CLK_MUX
],
1741 ctx
->clocks
[FIMC_CLK_PARENT
]);
1743 dev_err(fimc_dev
, "failed to set parent.\n");
1748 ret
= clk_set_rate(ctx
->clocks
[FIMC_CLK_LCLK
], ctx
->clk_frequency
);
1752 ret
= clk_prepare_enable(ctx
->clocks
[FIMC_CLK_LCLK
]);
1756 fimc_put_clocks(ctx
);
1760 static int fimc_parse_dt(struct fimc_context
*ctx
)
1762 struct device_node
*node
= ctx
->ippdrv
.dev
->of_node
;
1764 /* Handle only devices that support the LCD Writeback data path */
1765 if (!of_property_read_bool(node
, "samsung,lcd-wb"))
1768 if (of_property_read_u32(node
, "clock-frequency",
1769 &ctx
->clk_frequency
))
1770 ctx
->clk_frequency
= FIMC_DEFAULT_LCLK_FREQUENCY
;
1772 ctx
->id
= of_alias_get_id(node
, "fimc");
1775 dev_err(ctx
->ippdrv
.dev
, "failed to get node alias id.\n");
1782 static int fimc_probe(struct platform_device
*pdev
)
1784 struct device
*dev
= &pdev
->dev
;
1785 struct fimc_context
*ctx
;
1786 struct resource
*res
;
1787 struct exynos_drm_ippdrv
*ippdrv
;
1790 if (!dev
->of_node
) {
1791 dev_err(dev
, "device tree node not found.\n");
1795 ctx
= devm_kzalloc(dev
, sizeof(*ctx
), GFP_KERNEL
);
1799 ctx
->ippdrv
.dev
= dev
;
1801 ret
= fimc_parse_dt(ctx
);
1805 ctx
->sysreg
= syscon_regmap_lookup_by_phandle(dev
->of_node
,
1807 if (IS_ERR(ctx
->sysreg
)) {
1808 dev_err(dev
, "syscon regmap lookup failed.\n");
1809 return PTR_ERR(ctx
->sysreg
);
1812 /* resource memory */
1813 ctx
->regs_res
= platform_get_resource(pdev
, IORESOURCE_MEM
, 0);
1814 ctx
->regs
= devm_ioremap_resource(dev
, ctx
->regs_res
);
1815 if (IS_ERR(ctx
->regs
))
1816 return PTR_ERR(ctx
->regs
);
1819 res
= platform_get_resource(pdev
, IORESOURCE_IRQ
, 0);
1821 dev_err(dev
, "failed to request irq resource.\n");
1825 ctx
->irq
= res
->start
;
1826 ret
= devm_request_threaded_irq(dev
, ctx
->irq
, NULL
, fimc_irq_handler
,
1827 IRQF_ONESHOT
, "drm_fimc", ctx
);
1829 dev_err(dev
, "failed to request irq.\n");
1833 ret
= fimc_setup_clocks(ctx
);
1837 ippdrv
= &ctx
->ippdrv
;
1838 ippdrv
->ops
[EXYNOS_DRM_OPS_SRC
] = &fimc_src_ops
;
1839 ippdrv
->ops
[EXYNOS_DRM_OPS_DST
] = &fimc_dst_ops
;
1840 ippdrv
->check_property
= fimc_ippdrv_check_property
;
1841 ippdrv
->reset
= fimc_ippdrv_reset
;
1842 ippdrv
->start
= fimc_ippdrv_start
;
1843 ippdrv
->stop
= fimc_ippdrv_stop
;
1844 ret
= fimc_init_prop_list(ippdrv
);
1846 dev_err(dev
, "failed to init property list.\n");
1850 DRM_DEBUG_KMS("id[%d]ippdrv[0x%x]\n", ctx
->id
, (int)ippdrv
);
1852 mutex_init(&ctx
->lock
);
1853 platform_set_drvdata(pdev
, ctx
);
1855 pm_runtime_set_active(dev
);
1856 pm_runtime_enable(dev
);
1858 ret
= exynos_drm_ippdrv_register(ippdrv
);
1860 dev_err(dev
, "failed to register drm fimc device.\n");
1864 dev_info(dev
, "drm fimc registered successfully.\n");
1869 pm_runtime_disable(dev
);
1871 fimc_put_clocks(ctx
);
1876 static int fimc_remove(struct platform_device
*pdev
)
1878 struct device
*dev
= &pdev
->dev
;
1879 struct fimc_context
*ctx
= get_fimc_context(dev
);
1880 struct exynos_drm_ippdrv
*ippdrv
= &ctx
->ippdrv
;
1882 exynos_drm_ippdrv_unregister(ippdrv
);
1883 mutex_destroy(&ctx
->lock
);
1885 fimc_put_clocks(ctx
);
1886 pm_runtime_set_suspended(dev
);
1887 pm_runtime_disable(dev
);
1892 #ifdef CONFIG_PM_SLEEP
1893 static int fimc_suspend(struct device
*dev
)
1895 struct fimc_context
*ctx
= get_fimc_context(dev
);
1897 DRM_DEBUG_KMS("id[%d]\n", ctx
->id
);
1899 if (pm_runtime_suspended(dev
))
1902 return fimc_clk_ctrl(ctx
, false);
1905 static int fimc_resume(struct device
*dev
)
1907 struct fimc_context
*ctx
= get_fimc_context(dev
);
1909 DRM_DEBUG_KMS("id[%d]\n", ctx
->id
);
1911 if (!pm_runtime_suspended(dev
))
1912 return fimc_clk_ctrl(ctx
, true);
1918 #ifdef CONFIG_PM_RUNTIME
1919 static int fimc_runtime_suspend(struct device
*dev
)
1921 struct fimc_context
*ctx
= get_fimc_context(dev
);
1923 DRM_DEBUG_KMS("id[%d]\n", ctx
->id
);
1925 return fimc_clk_ctrl(ctx
, false);
1928 static int fimc_runtime_resume(struct device
*dev
)
1930 struct fimc_context
*ctx
= get_fimc_context(dev
);
1932 DRM_DEBUG_KMS("id[%d]\n", ctx
->id
);
1934 return fimc_clk_ctrl(ctx
, true);
1938 static const struct dev_pm_ops fimc_pm_ops
= {
1939 SET_SYSTEM_SLEEP_PM_OPS(fimc_suspend
, fimc_resume
)
1940 SET_RUNTIME_PM_OPS(fimc_runtime_suspend
, fimc_runtime_resume
, NULL
)
1943 static const struct of_device_id fimc_of_match
[] = {
1944 { .compatible
= "samsung,exynos4210-fimc" },
1945 { .compatible
= "samsung,exynos4212-fimc" },
1949 struct platform_driver fimc_driver
= {
1950 .probe
= fimc_probe
,
1951 .remove
= fimc_remove
,
1953 .of_match_table
= fimc_of_match
,
1954 .name
= "exynos-drm-fimc",
1955 .owner
= THIS_MODULE
,