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>
23 #include <drm/exynos_drm.h>
24 #include "regs-fimc.h"
25 #include "exynos_drm_drv.h"
26 #include "exynos_drm_ipp.h"
27 #include "exynos_drm_fimc.h"
30 * FIMC stands for Fully Interactive Mobile Camera and
31 * supports image scaler/rotator and input/output DMA operations.
32 * input DMA reads image data from the memory.
33 * output DMA writes image data to memory.
34 * FIMC supports image rotation and image effect functions.
36 * M2M operation : supports crop/scale/rotation/csc so on.
37 * Memory ----> FIMC H/W ----> Memory.
38 * Writeback operation : supports cloned screen with FIMD.
39 * FIMD ----> FIMC H/W ----> Memory.
40 * Output operation : supports direct display using local path.
41 * Memory ----> FIMC H/W ----> FIMD.
46 * 1. check suspend/resume api if needed.
47 * 2. need to check use case platform_device_id.
48 * 3. check src/dst size with, height.
49 * 4. added check_prepare api for right register.
50 * 5. need to add supported list in prop_list.
51 * 6. check prescaler/scaler optimization.
54 #define FIMC_MAX_DEVS 4
55 #define FIMC_MAX_SRC 2
56 #define FIMC_MAX_DST 32
57 #define FIMC_SHFACTOR 10
58 #define FIMC_BUF_STOP 1
59 #define FIMC_BUF_START 2
60 #define FIMC_REG_SZ 32
61 #define FIMC_WIDTH_ITU_709 1280
62 #define FIMC_REFRESH_MAX 60
63 #define FIMC_REFRESH_MIN 12
64 #define FIMC_CROP_MAX 8192
65 #define FIMC_CROP_MIN 32
66 #define FIMC_SCALE_MAX 4224
67 #define FIMC_SCALE_MIN 32
69 #define get_fimc_context(dev) platform_get_drvdata(to_platform_device(dev))
70 #define get_ctx_from_ippdrv(ippdrv) container_of(ippdrv,\
71 struct fimc_context, ippdrv);
72 #define fimc_read(offset) readl(ctx->regs + (offset))
73 #define fimc_write(cfg, offset) writel(cfg, ctx->regs + (offset))
91 static const char * const fimc_clock_names
[] = {
92 [FIMC_CLK_LCLK
] = "sclk_fimc",
93 [FIMC_CLK_GATE
] = "fimc",
94 [FIMC_CLK_WB_A
] = "pxl_async0",
95 [FIMC_CLK_WB_B
] = "pxl_async1",
96 [FIMC_CLK_MUX
] = "mux",
97 [FIMC_CLK_PARENT
] = "parent",
100 #define FIMC_DEFAULT_LCLK_FREQUENCY 133000000UL
103 * A structure of scaler.
105 * @range: narrow, wide.
106 * @bypass: unused scaler path.
107 * @up_h: horizontal scale up.
108 * @up_v: vertical scale up.
109 * @hratio: horizontal ratio.
110 * @vratio: vertical ratio.
122 * A structure of scaler capability.
124 * find user manual table 43-1.
125 * @in_hori: scaler input horizontal size.
126 * @bypass: scaler bypass mode.
127 * @dst_h_wo_rot: target horizontal size without output rotation.
128 * @dst_h_rot: target horizontal size with output rotation.
129 * @rl_w_wo_rot: real width without input rotation.
130 * @rl_h_rot: real height without output rotation.
132 struct fimc_capability
{
145 * A structure of fimc context.
147 * @ippdrv: prepare initialization using ippdrv.
148 * @regs_res: register resources.
149 * @regs: memory mapped io registers.
150 * @lock: locking of operations.
151 * @clocks: fimc clocks.
152 * @clk_frequency: LCLK clock frequency.
153 * @sysreg: handle to SYSREG block regmap.
154 * @sc: scaler infomations.
155 * @pol: porarity of writeback.
158 * @suspended: qos operations.
160 struct fimc_context
{
161 struct exynos_drm_ippdrv ippdrv
;
162 struct resource
*regs_res
;
165 struct clk
*clocks
[FIMC_CLKS_MAX
];
167 struct regmap
*sysreg
;
168 struct fimc_scaler sc
;
169 struct exynos_drm_ipp_pol pol
;
175 static void fimc_sw_reset(struct fimc_context
*ctx
)
179 /* stop dma operation */
180 cfg
= fimc_read(EXYNOS_CISTATUS
);
181 if (EXYNOS_CISTATUS_GET_ENVID_STATUS(cfg
)) {
182 cfg
= fimc_read(EXYNOS_MSCTRL
);
183 cfg
&= ~EXYNOS_MSCTRL_ENVID
;
184 fimc_write(cfg
, EXYNOS_MSCTRL
);
187 cfg
= fimc_read(EXYNOS_CISRCFMT
);
188 cfg
|= EXYNOS_CISRCFMT_ITU601_8BIT
;
189 fimc_write(cfg
, EXYNOS_CISRCFMT
);
191 /* disable image capture */
192 cfg
= fimc_read(EXYNOS_CIIMGCPT
);
193 cfg
&= ~(EXYNOS_CIIMGCPT_IMGCPTEN_SC
| EXYNOS_CIIMGCPT_IMGCPTEN
);
194 fimc_write(cfg
, EXYNOS_CIIMGCPT
);
197 cfg
= fimc_read(EXYNOS_CIGCTRL
);
198 cfg
|= (EXYNOS_CIGCTRL_SWRST
);
199 fimc_write(cfg
, EXYNOS_CIGCTRL
);
201 /* s/w reset complete */
202 cfg
= fimc_read(EXYNOS_CIGCTRL
);
203 cfg
&= ~EXYNOS_CIGCTRL_SWRST
;
204 fimc_write(cfg
, EXYNOS_CIGCTRL
);
207 fimc_write(0x0, EXYNOS_CIFCNTSEQ
);
210 static int fimc_set_camblk_fimd0_wb(struct fimc_context
*ctx
)
212 return regmap_update_bits(ctx
->sysreg
, SYSREG_CAMERA_BLK
,
213 SYSREG_FIMD0WB_DEST_MASK
,
214 ctx
->id
<< SYSREG_FIMD0WB_DEST_SHIFT
);
217 static void fimc_set_type_ctrl(struct fimc_context
*ctx
, enum fimc_wb wb
)
221 DRM_DEBUG_KMS("wb[%d]\n", wb
);
223 cfg
= fimc_read(EXYNOS_CIGCTRL
);
224 cfg
&= ~(EXYNOS_CIGCTRL_TESTPATTERN_MASK
|
225 EXYNOS_CIGCTRL_SELCAM_ITU_MASK
|
226 EXYNOS_CIGCTRL_SELCAM_MIPI_MASK
|
227 EXYNOS_CIGCTRL_SELCAM_FIMC_MASK
|
228 EXYNOS_CIGCTRL_SELWB_CAMIF_MASK
|
229 EXYNOS_CIGCTRL_SELWRITEBACK_MASK
);
233 cfg
|= (EXYNOS_CIGCTRL_SELWRITEBACK_A
|
234 EXYNOS_CIGCTRL_SELWB_CAMIF_WRITEBACK
);
237 cfg
|= (EXYNOS_CIGCTRL_SELWRITEBACK_B
|
238 EXYNOS_CIGCTRL_SELWB_CAMIF_WRITEBACK
);
242 cfg
|= (EXYNOS_CIGCTRL_SELCAM_ITU_A
|
243 EXYNOS_CIGCTRL_SELWRITEBACK_A
|
244 EXYNOS_CIGCTRL_SELCAM_MIPI_A
|
245 EXYNOS_CIGCTRL_SELCAM_FIMC_ITU
);
249 fimc_write(cfg
, EXYNOS_CIGCTRL
);
252 static void fimc_set_polarity(struct fimc_context
*ctx
,
253 struct exynos_drm_ipp_pol
*pol
)
257 DRM_DEBUG_KMS("inv_pclk[%d]inv_vsync[%d]\n",
258 pol
->inv_pclk
, pol
->inv_vsync
);
259 DRM_DEBUG_KMS("inv_href[%d]inv_hsync[%d]\n",
260 pol
->inv_href
, pol
->inv_hsync
);
262 cfg
= fimc_read(EXYNOS_CIGCTRL
);
263 cfg
&= ~(EXYNOS_CIGCTRL_INVPOLPCLK
| EXYNOS_CIGCTRL_INVPOLVSYNC
|
264 EXYNOS_CIGCTRL_INVPOLHREF
| EXYNOS_CIGCTRL_INVPOLHSYNC
);
267 cfg
|= EXYNOS_CIGCTRL_INVPOLPCLK
;
269 cfg
|= EXYNOS_CIGCTRL_INVPOLVSYNC
;
271 cfg
|= EXYNOS_CIGCTRL_INVPOLHREF
;
273 cfg
|= EXYNOS_CIGCTRL_INVPOLHSYNC
;
275 fimc_write(cfg
, EXYNOS_CIGCTRL
);
278 static void fimc_handle_jpeg(struct fimc_context
*ctx
, bool enable
)
282 DRM_DEBUG_KMS("enable[%d]\n", enable
);
284 cfg
= fimc_read(EXYNOS_CIGCTRL
);
286 cfg
|= EXYNOS_CIGCTRL_CAM_JPEG
;
288 cfg
&= ~EXYNOS_CIGCTRL_CAM_JPEG
;
290 fimc_write(cfg
, EXYNOS_CIGCTRL
);
293 static void fimc_handle_irq(struct fimc_context
*ctx
, bool enable
,
294 bool overflow
, bool level
)
298 DRM_DEBUG_KMS("enable[%d]overflow[%d]level[%d]\n",
299 enable
, overflow
, level
);
301 cfg
= fimc_read(EXYNOS_CIGCTRL
);
303 cfg
&= ~(EXYNOS_CIGCTRL_IRQ_OVFEN
| EXYNOS_CIGCTRL_IRQ_LEVEL
);
304 cfg
|= EXYNOS_CIGCTRL_IRQ_ENABLE
;
306 cfg
|= EXYNOS_CIGCTRL_IRQ_OVFEN
;
308 cfg
|= EXYNOS_CIGCTRL_IRQ_LEVEL
;
310 cfg
&= ~(EXYNOS_CIGCTRL_IRQ_OVFEN
| EXYNOS_CIGCTRL_IRQ_ENABLE
);
312 fimc_write(cfg
, EXYNOS_CIGCTRL
);
315 static void fimc_clear_irq(struct fimc_context
*ctx
)
319 cfg
= fimc_read(EXYNOS_CIGCTRL
);
320 cfg
|= EXYNOS_CIGCTRL_IRQ_CLR
;
321 fimc_write(cfg
, EXYNOS_CIGCTRL
);
324 static bool fimc_check_ovf(struct fimc_context
*ctx
)
326 struct exynos_drm_ippdrv
*ippdrv
= &ctx
->ippdrv
;
327 u32 cfg
, status
, flag
;
329 status
= fimc_read(EXYNOS_CISTATUS
);
330 flag
= EXYNOS_CISTATUS_OVFIY
| EXYNOS_CISTATUS_OVFICB
|
331 EXYNOS_CISTATUS_OVFICR
;
333 DRM_DEBUG_KMS("flag[0x%x]\n", flag
);
336 cfg
= fimc_read(EXYNOS_CIWDOFST
);
337 cfg
|= (EXYNOS_CIWDOFST_CLROVFIY
| EXYNOS_CIWDOFST_CLROVFICB
|
338 EXYNOS_CIWDOFST_CLROVFICR
);
340 fimc_write(cfg
, EXYNOS_CIWDOFST
);
342 cfg
= fimc_read(EXYNOS_CIWDOFST
);
343 cfg
&= ~(EXYNOS_CIWDOFST_CLROVFIY
| EXYNOS_CIWDOFST_CLROVFICB
|
344 EXYNOS_CIWDOFST_CLROVFICR
);
346 fimc_write(cfg
, EXYNOS_CIWDOFST
);
348 dev_err(ippdrv
->dev
, "occured overflow at %d, status 0x%x.\n",
356 static bool fimc_check_frame_end(struct fimc_context
*ctx
)
360 cfg
= fimc_read(EXYNOS_CISTATUS
);
362 DRM_DEBUG_KMS("cfg[0x%x]\n", cfg
);
364 if (!(cfg
& EXYNOS_CISTATUS_FRAMEEND
))
367 cfg
&= ~(EXYNOS_CISTATUS_FRAMEEND
);
368 fimc_write(cfg
, EXYNOS_CISTATUS
);
373 static int fimc_get_buf_id(struct fimc_context
*ctx
)
376 int frame_cnt
, buf_id
;
378 cfg
= fimc_read(EXYNOS_CISTATUS2
);
379 frame_cnt
= EXYNOS_CISTATUS2_GET_FRAMECOUNT_BEFORE(cfg
);
382 frame_cnt
= EXYNOS_CISTATUS2_GET_FRAMECOUNT_PRESENT(cfg
);
384 DRM_DEBUG_KMS("present[%d]before[%d]\n",
385 EXYNOS_CISTATUS2_GET_FRAMECOUNT_PRESENT(cfg
),
386 EXYNOS_CISTATUS2_GET_FRAMECOUNT_BEFORE(cfg
));
388 if (frame_cnt
== 0) {
389 DRM_ERROR("failed to get frame count.\n");
393 buf_id
= frame_cnt
- 1;
394 DRM_DEBUG_KMS("buf_id[%d]\n", buf_id
);
399 static void fimc_handle_lastend(struct fimc_context
*ctx
, bool enable
)
403 DRM_DEBUG_KMS("enable[%d]\n", enable
);
405 cfg
= fimc_read(EXYNOS_CIOCTRL
);
407 cfg
|= EXYNOS_CIOCTRL_LASTENDEN
;
409 cfg
&= ~EXYNOS_CIOCTRL_LASTENDEN
;
411 fimc_write(cfg
, EXYNOS_CIOCTRL
);
415 static int fimc_src_set_fmt_order(struct fimc_context
*ctx
, u32 fmt
)
417 struct exynos_drm_ippdrv
*ippdrv
= &ctx
->ippdrv
;
420 DRM_DEBUG_KMS("fmt[0x%x]\n", fmt
);
423 cfg
= fimc_read(EXYNOS_CISCCTRL
);
424 cfg
&= ~EXYNOS_CISCCTRL_INRGB_FMT_RGB_MASK
;
427 case DRM_FORMAT_RGB565
:
428 cfg
|= EXYNOS_CISCCTRL_INRGB_FMT_RGB565
;
429 fimc_write(cfg
, EXYNOS_CISCCTRL
);
431 case DRM_FORMAT_RGB888
:
432 case DRM_FORMAT_XRGB8888
:
433 cfg
|= EXYNOS_CISCCTRL_INRGB_FMT_RGB888
;
434 fimc_write(cfg
, EXYNOS_CISCCTRL
);
442 cfg
= fimc_read(EXYNOS_MSCTRL
);
443 cfg
&= ~(EXYNOS_MSCTRL_ORDER2P_SHIFT_MASK
|
444 EXYNOS_MSCTRL_C_INT_IN_2PLANE
|
445 EXYNOS_MSCTRL_ORDER422_YCBYCR
);
448 case DRM_FORMAT_YUYV
:
449 cfg
|= EXYNOS_MSCTRL_ORDER422_YCBYCR
;
451 case DRM_FORMAT_YVYU
:
452 cfg
|= EXYNOS_MSCTRL_ORDER422_YCRYCB
;
454 case DRM_FORMAT_UYVY
:
455 cfg
|= EXYNOS_MSCTRL_ORDER422_CBYCRY
;
457 case DRM_FORMAT_VYUY
:
458 case DRM_FORMAT_YUV444
:
459 cfg
|= EXYNOS_MSCTRL_ORDER422_CRYCBY
;
461 case DRM_FORMAT_NV21
:
462 case DRM_FORMAT_NV61
:
463 cfg
|= (EXYNOS_MSCTRL_ORDER2P_LSB_CRCB
|
464 EXYNOS_MSCTRL_C_INT_IN_2PLANE
);
466 case DRM_FORMAT_YUV422
:
467 case DRM_FORMAT_YUV420
:
468 case DRM_FORMAT_YVU420
:
469 cfg
|= EXYNOS_MSCTRL_C_INT_IN_3PLANE
;
471 case DRM_FORMAT_NV12
:
472 case DRM_FORMAT_NV12MT
:
473 case DRM_FORMAT_NV16
:
474 cfg
|= (EXYNOS_MSCTRL_ORDER2P_LSB_CBCR
|
475 EXYNOS_MSCTRL_C_INT_IN_2PLANE
);
478 dev_err(ippdrv
->dev
, "inavlid source yuv order 0x%x.\n", fmt
);
482 fimc_write(cfg
, EXYNOS_MSCTRL
);
487 static int fimc_src_set_fmt(struct device
*dev
, u32 fmt
)
489 struct fimc_context
*ctx
= get_fimc_context(dev
);
490 struct exynos_drm_ippdrv
*ippdrv
= &ctx
->ippdrv
;
493 DRM_DEBUG_KMS("fmt[0x%x]\n", fmt
);
495 cfg
= fimc_read(EXYNOS_MSCTRL
);
496 cfg
&= ~EXYNOS_MSCTRL_INFORMAT_RGB
;
499 case DRM_FORMAT_RGB565
:
500 case DRM_FORMAT_RGB888
:
501 case DRM_FORMAT_XRGB8888
:
502 cfg
|= EXYNOS_MSCTRL_INFORMAT_RGB
;
504 case DRM_FORMAT_YUV444
:
505 cfg
|= EXYNOS_MSCTRL_INFORMAT_YCBCR420
;
507 case DRM_FORMAT_YUYV
:
508 case DRM_FORMAT_YVYU
:
509 case DRM_FORMAT_UYVY
:
510 case DRM_FORMAT_VYUY
:
511 cfg
|= EXYNOS_MSCTRL_INFORMAT_YCBCR422_1PLANE
;
513 case DRM_FORMAT_NV16
:
514 case DRM_FORMAT_NV61
:
515 case DRM_FORMAT_YUV422
:
516 cfg
|= EXYNOS_MSCTRL_INFORMAT_YCBCR422
;
518 case DRM_FORMAT_YUV420
:
519 case DRM_FORMAT_YVU420
:
520 case DRM_FORMAT_NV12
:
521 case DRM_FORMAT_NV21
:
522 case DRM_FORMAT_NV12MT
:
523 cfg
|= EXYNOS_MSCTRL_INFORMAT_YCBCR420
;
526 dev_err(ippdrv
->dev
, "inavlid source format 0x%x.\n", fmt
);
530 fimc_write(cfg
, EXYNOS_MSCTRL
);
532 cfg
= fimc_read(EXYNOS_CIDMAPARAM
);
533 cfg
&= ~EXYNOS_CIDMAPARAM_R_MODE_MASK
;
535 if (fmt
== DRM_FORMAT_NV12MT
)
536 cfg
|= EXYNOS_CIDMAPARAM_R_MODE_64X32
;
538 cfg
|= EXYNOS_CIDMAPARAM_R_MODE_LINEAR
;
540 fimc_write(cfg
, EXYNOS_CIDMAPARAM
);
542 return fimc_src_set_fmt_order(ctx
, fmt
);
545 static int fimc_src_set_transf(struct device
*dev
,
546 enum drm_exynos_degree degree
,
547 enum drm_exynos_flip flip
, bool *swap
)
549 struct fimc_context
*ctx
= get_fimc_context(dev
);
550 struct exynos_drm_ippdrv
*ippdrv
= &ctx
->ippdrv
;
553 DRM_DEBUG_KMS("degree[%d]flip[0x%x]\n", degree
, flip
);
555 cfg1
= fimc_read(EXYNOS_MSCTRL
);
556 cfg1
&= ~(EXYNOS_MSCTRL_FLIP_X_MIRROR
|
557 EXYNOS_MSCTRL_FLIP_Y_MIRROR
);
559 cfg2
= fimc_read(EXYNOS_CITRGFMT
);
560 cfg2
&= ~EXYNOS_CITRGFMT_INROT90_CLOCKWISE
;
563 case EXYNOS_DRM_DEGREE_0
:
564 if (flip
& EXYNOS_DRM_FLIP_VERTICAL
)
565 cfg1
|= EXYNOS_MSCTRL_FLIP_X_MIRROR
;
566 if (flip
& EXYNOS_DRM_FLIP_HORIZONTAL
)
567 cfg1
|= EXYNOS_MSCTRL_FLIP_Y_MIRROR
;
569 case EXYNOS_DRM_DEGREE_90
:
570 cfg2
|= EXYNOS_CITRGFMT_INROT90_CLOCKWISE
;
571 if (flip
& EXYNOS_DRM_FLIP_VERTICAL
)
572 cfg1
|= EXYNOS_MSCTRL_FLIP_X_MIRROR
;
573 if (flip
& EXYNOS_DRM_FLIP_HORIZONTAL
)
574 cfg1
|= EXYNOS_MSCTRL_FLIP_Y_MIRROR
;
576 case EXYNOS_DRM_DEGREE_180
:
577 cfg1
|= (EXYNOS_MSCTRL_FLIP_X_MIRROR
|
578 EXYNOS_MSCTRL_FLIP_Y_MIRROR
);
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_270
:
585 cfg1
|= (EXYNOS_MSCTRL_FLIP_X_MIRROR
|
586 EXYNOS_MSCTRL_FLIP_Y_MIRROR
);
587 cfg2
|= EXYNOS_CITRGFMT_INROT90_CLOCKWISE
;
588 if (flip
& EXYNOS_DRM_FLIP_VERTICAL
)
589 cfg1
&= ~EXYNOS_MSCTRL_FLIP_X_MIRROR
;
590 if (flip
& EXYNOS_DRM_FLIP_HORIZONTAL
)
591 cfg1
&= ~EXYNOS_MSCTRL_FLIP_Y_MIRROR
;
594 dev_err(ippdrv
->dev
, "inavlid degree value %d.\n", degree
);
598 fimc_write(cfg1
, EXYNOS_MSCTRL
);
599 fimc_write(cfg2
, EXYNOS_CITRGFMT
);
600 *swap
= (cfg2
& EXYNOS_CITRGFMT_INROT90_CLOCKWISE
) ? 1 : 0;
605 static int fimc_set_window(struct fimc_context
*ctx
,
606 struct drm_exynos_pos
*pos
, struct drm_exynos_sz
*sz
)
608 u32 cfg
, h1
, h2
, v1
, v2
;
612 h2
= sz
->hsize
- pos
->w
- pos
->x
;
614 v2
= sz
->vsize
- pos
->h
- pos
->y
;
616 DRM_DEBUG_KMS("x[%d]y[%d]w[%d]h[%d]hsize[%d]vsize[%d]\n",
617 pos
->x
, pos
->y
, pos
->w
, pos
->h
, sz
->hsize
, sz
->vsize
);
618 DRM_DEBUG_KMS("h1[%d]h2[%d]v1[%d]v2[%d]\n", h1
, h2
, v1
, v2
);
621 * set window offset 1, 2 size
622 * check figure 43-21 in user manual
624 cfg
= fimc_read(EXYNOS_CIWDOFST
);
625 cfg
&= ~(EXYNOS_CIWDOFST_WINHOROFST_MASK
|
626 EXYNOS_CIWDOFST_WINVEROFST_MASK
);
627 cfg
|= (EXYNOS_CIWDOFST_WINHOROFST(h1
) |
628 EXYNOS_CIWDOFST_WINVEROFST(v1
));
629 cfg
|= EXYNOS_CIWDOFST_WINOFSEN
;
630 fimc_write(cfg
, EXYNOS_CIWDOFST
);
632 cfg
= (EXYNOS_CIWDOFST2_WINHOROFST2(h2
) |
633 EXYNOS_CIWDOFST2_WINVEROFST2(v2
));
634 fimc_write(cfg
, EXYNOS_CIWDOFST2
);
639 static int fimc_src_set_size(struct device
*dev
, int swap
,
640 struct drm_exynos_pos
*pos
, struct drm_exynos_sz
*sz
)
642 struct fimc_context
*ctx
= get_fimc_context(dev
);
643 struct drm_exynos_pos img_pos
= *pos
;
644 struct drm_exynos_sz img_sz
= *sz
;
647 DRM_DEBUG_KMS("swap[%d]hsize[%d]vsize[%d]\n",
648 swap
, sz
->hsize
, sz
->vsize
);
651 cfg
= (EXYNOS_ORGISIZE_HORIZONTAL(img_sz
.hsize
) |
652 EXYNOS_ORGISIZE_VERTICAL(img_sz
.vsize
));
654 fimc_write(cfg
, EXYNOS_ORGISIZE
);
656 DRM_DEBUG_KMS("x[%d]y[%d]w[%d]h[%d]\n", pos
->x
, pos
->y
, pos
->w
, pos
->h
);
661 img_sz
.hsize
= sz
->vsize
;
662 img_sz
.vsize
= sz
->hsize
;
665 /* set input DMA image size */
666 cfg
= fimc_read(EXYNOS_CIREAL_ISIZE
);
667 cfg
&= ~(EXYNOS_CIREAL_ISIZE_HEIGHT_MASK
|
668 EXYNOS_CIREAL_ISIZE_WIDTH_MASK
);
669 cfg
|= (EXYNOS_CIREAL_ISIZE_WIDTH(img_pos
.w
) |
670 EXYNOS_CIREAL_ISIZE_HEIGHT(img_pos
.h
));
671 fimc_write(cfg
, EXYNOS_CIREAL_ISIZE
);
674 * set input FIFO image size
675 * for now, we support only ITU601 8 bit mode
677 cfg
= (EXYNOS_CISRCFMT_ITU601_8BIT
|
678 EXYNOS_CISRCFMT_SOURCEHSIZE(img_sz
.hsize
) |
679 EXYNOS_CISRCFMT_SOURCEVSIZE(img_sz
.vsize
));
680 fimc_write(cfg
, EXYNOS_CISRCFMT
);
682 /* offset Y(RGB), Cb, Cr */
683 cfg
= (EXYNOS_CIIYOFF_HORIZONTAL(img_pos
.x
) |
684 EXYNOS_CIIYOFF_VERTICAL(img_pos
.y
));
685 fimc_write(cfg
, EXYNOS_CIIYOFF
);
686 cfg
= (EXYNOS_CIICBOFF_HORIZONTAL(img_pos
.x
) |
687 EXYNOS_CIICBOFF_VERTICAL(img_pos
.y
));
688 fimc_write(cfg
, EXYNOS_CIICBOFF
);
689 cfg
= (EXYNOS_CIICROFF_HORIZONTAL(img_pos
.x
) |
690 EXYNOS_CIICROFF_VERTICAL(img_pos
.y
));
691 fimc_write(cfg
, EXYNOS_CIICROFF
);
693 return fimc_set_window(ctx
, &img_pos
, &img_sz
);
696 static int fimc_src_set_addr(struct device
*dev
,
697 struct drm_exynos_ipp_buf_info
*buf_info
, u32 buf_id
,
698 enum drm_exynos_ipp_buf_type buf_type
)
700 struct fimc_context
*ctx
= get_fimc_context(dev
);
701 struct exynos_drm_ippdrv
*ippdrv
= &ctx
->ippdrv
;
702 struct drm_exynos_ipp_cmd_node
*c_node
= ippdrv
->c_node
;
703 struct drm_exynos_ipp_property
*property
;
704 struct drm_exynos_ipp_config
*config
;
707 DRM_ERROR("failed to get c_node.\n");
711 property
= &c_node
->property
;
713 DRM_DEBUG_KMS("prop_id[%d]buf_id[%d]buf_type[%d]\n",
714 property
->prop_id
, buf_id
, buf_type
);
716 if (buf_id
> FIMC_MAX_SRC
) {
717 dev_info(ippdrv
->dev
, "inavlid buf_id %d.\n", buf_id
);
721 /* address register set */
723 case IPP_BUF_ENQUEUE
:
724 config
= &property
->config
[EXYNOS_DRM_OPS_SRC
];
725 fimc_write(buf_info
->base
[EXYNOS_DRM_PLANAR_Y
],
726 EXYNOS_CIIYSA(buf_id
));
728 if (config
->fmt
== DRM_FORMAT_YVU420
) {
729 fimc_write(buf_info
->base
[EXYNOS_DRM_PLANAR_CR
],
730 EXYNOS_CIICBSA(buf_id
));
731 fimc_write(buf_info
->base
[EXYNOS_DRM_PLANAR_CB
],
732 EXYNOS_CIICRSA(buf_id
));
734 fimc_write(buf_info
->base
[EXYNOS_DRM_PLANAR_CB
],
735 EXYNOS_CIICBSA(buf_id
));
736 fimc_write(buf_info
->base
[EXYNOS_DRM_PLANAR_CR
],
737 EXYNOS_CIICRSA(buf_id
));
740 case IPP_BUF_DEQUEUE
:
741 fimc_write(0x0, EXYNOS_CIIYSA(buf_id
));
742 fimc_write(0x0, EXYNOS_CIICBSA(buf_id
));
743 fimc_write(0x0, EXYNOS_CIICRSA(buf_id
));
753 static struct exynos_drm_ipp_ops fimc_src_ops
= {
754 .set_fmt
= fimc_src_set_fmt
,
755 .set_transf
= fimc_src_set_transf
,
756 .set_size
= fimc_src_set_size
,
757 .set_addr
= fimc_src_set_addr
,
760 static int fimc_dst_set_fmt_order(struct fimc_context
*ctx
, u32 fmt
)
762 struct exynos_drm_ippdrv
*ippdrv
= &ctx
->ippdrv
;
765 DRM_DEBUG_KMS("fmt[0x%x]\n", fmt
);
768 cfg
= fimc_read(EXYNOS_CISCCTRL
);
769 cfg
&= ~EXYNOS_CISCCTRL_OUTRGB_FMT_RGB_MASK
;
772 case DRM_FORMAT_RGB565
:
773 cfg
|= EXYNOS_CISCCTRL_OUTRGB_FMT_RGB565
;
774 fimc_write(cfg
, EXYNOS_CISCCTRL
);
776 case DRM_FORMAT_RGB888
:
777 cfg
|= EXYNOS_CISCCTRL_OUTRGB_FMT_RGB888
;
778 fimc_write(cfg
, EXYNOS_CISCCTRL
);
780 case DRM_FORMAT_XRGB8888
:
781 cfg
|= (EXYNOS_CISCCTRL_OUTRGB_FMT_RGB888
|
782 EXYNOS_CISCCTRL_EXTRGB_EXTENSION
);
783 fimc_write(cfg
, EXYNOS_CISCCTRL
);
791 cfg
= fimc_read(EXYNOS_CIOCTRL
);
792 cfg
&= ~(EXYNOS_CIOCTRL_ORDER2P_MASK
|
793 EXYNOS_CIOCTRL_ORDER422_MASK
|
794 EXYNOS_CIOCTRL_YCBCR_PLANE_MASK
);
797 case DRM_FORMAT_XRGB8888
:
798 cfg
|= EXYNOS_CIOCTRL_ALPHA_OUT
;
800 case DRM_FORMAT_YUYV
:
801 cfg
|= EXYNOS_CIOCTRL_ORDER422_YCBYCR
;
803 case DRM_FORMAT_YVYU
:
804 cfg
|= EXYNOS_CIOCTRL_ORDER422_YCRYCB
;
806 case DRM_FORMAT_UYVY
:
807 cfg
|= EXYNOS_CIOCTRL_ORDER422_CBYCRY
;
809 case DRM_FORMAT_VYUY
:
810 cfg
|= EXYNOS_CIOCTRL_ORDER422_CRYCBY
;
812 case DRM_FORMAT_NV21
:
813 case DRM_FORMAT_NV61
:
814 cfg
|= EXYNOS_CIOCTRL_ORDER2P_LSB_CRCB
;
815 cfg
|= EXYNOS_CIOCTRL_YCBCR_2PLANE
;
817 case DRM_FORMAT_YUV422
:
818 case DRM_FORMAT_YUV420
:
819 case DRM_FORMAT_YVU420
:
820 cfg
|= EXYNOS_CIOCTRL_YCBCR_3PLANE
;
822 case DRM_FORMAT_NV12
:
823 case DRM_FORMAT_NV12MT
:
824 case DRM_FORMAT_NV16
:
825 cfg
|= EXYNOS_CIOCTRL_ORDER2P_LSB_CBCR
;
826 cfg
|= EXYNOS_CIOCTRL_YCBCR_2PLANE
;
829 dev_err(ippdrv
->dev
, "inavlid target yuv order 0x%x.\n", fmt
);
833 fimc_write(cfg
, EXYNOS_CIOCTRL
);
838 static int fimc_dst_set_fmt(struct device
*dev
, u32 fmt
)
840 struct fimc_context
*ctx
= get_fimc_context(dev
);
841 struct exynos_drm_ippdrv
*ippdrv
= &ctx
->ippdrv
;
844 DRM_DEBUG_KMS("fmt[0x%x]\n", fmt
);
846 cfg
= fimc_read(EXYNOS_CIEXTEN
);
848 if (fmt
== DRM_FORMAT_AYUV
) {
849 cfg
|= EXYNOS_CIEXTEN_YUV444_OUT
;
850 fimc_write(cfg
, EXYNOS_CIEXTEN
);
852 cfg
&= ~EXYNOS_CIEXTEN_YUV444_OUT
;
853 fimc_write(cfg
, EXYNOS_CIEXTEN
);
855 cfg
= fimc_read(EXYNOS_CITRGFMT
);
856 cfg
&= ~EXYNOS_CITRGFMT_OUTFORMAT_MASK
;
859 case DRM_FORMAT_RGB565
:
860 case DRM_FORMAT_RGB888
:
861 case DRM_FORMAT_XRGB8888
:
862 cfg
|= EXYNOS_CITRGFMT_OUTFORMAT_RGB
;
864 case DRM_FORMAT_YUYV
:
865 case DRM_FORMAT_YVYU
:
866 case DRM_FORMAT_UYVY
:
867 case DRM_FORMAT_VYUY
:
868 cfg
|= EXYNOS_CITRGFMT_OUTFORMAT_YCBCR422_1PLANE
;
870 case DRM_FORMAT_NV16
:
871 case DRM_FORMAT_NV61
:
872 case DRM_FORMAT_YUV422
:
873 cfg
|= EXYNOS_CITRGFMT_OUTFORMAT_YCBCR422
;
875 case DRM_FORMAT_YUV420
:
876 case DRM_FORMAT_YVU420
:
877 case DRM_FORMAT_NV12
:
878 case DRM_FORMAT_NV12MT
:
879 case DRM_FORMAT_NV21
:
880 cfg
|= EXYNOS_CITRGFMT_OUTFORMAT_YCBCR420
;
883 dev_err(ippdrv
->dev
, "inavlid target format 0x%x.\n",
888 fimc_write(cfg
, EXYNOS_CITRGFMT
);
891 cfg
= fimc_read(EXYNOS_CIDMAPARAM
);
892 cfg
&= ~EXYNOS_CIDMAPARAM_W_MODE_MASK
;
894 if (fmt
== DRM_FORMAT_NV12MT
)
895 cfg
|= EXYNOS_CIDMAPARAM_W_MODE_64X32
;
897 cfg
|= EXYNOS_CIDMAPARAM_W_MODE_LINEAR
;
899 fimc_write(cfg
, EXYNOS_CIDMAPARAM
);
901 return fimc_dst_set_fmt_order(ctx
, fmt
);
904 static int fimc_dst_set_transf(struct device
*dev
,
905 enum drm_exynos_degree degree
,
906 enum drm_exynos_flip flip
, bool *swap
)
908 struct fimc_context
*ctx
= get_fimc_context(dev
);
909 struct exynos_drm_ippdrv
*ippdrv
= &ctx
->ippdrv
;
912 DRM_DEBUG_KMS("degree[%d]flip[0x%x]\n", degree
, flip
);
914 cfg
= fimc_read(EXYNOS_CITRGFMT
);
915 cfg
&= ~EXYNOS_CITRGFMT_FLIP_MASK
;
916 cfg
&= ~EXYNOS_CITRGFMT_OUTROT90_CLOCKWISE
;
919 case EXYNOS_DRM_DEGREE_0
:
920 if (flip
& EXYNOS_DRM_FLIP_VERTICAL
)
921 cfg
|= EXYNOS_CITRGFMT_FLIP_X_MIRROR
;
922 if (flip
& EXYNOS_DRM_FLIP_HORIZONTAL
)
923 cfg
|= EXYNOS_CITRGFMT_FLIP_Y_MIRROR
;
925 case EXYNOS_DRM_DEGREE_90
:
926 cfg
|= EXYNOS_CITRGFMT_OUTROT90_CLOCKWISE
;
927 if (flip
& EXYNOS_DRM_FLIP_VERTICAL
)
928 cfg
|= EXYNOS_CITRGFMT_FLIP_X_MIRROR
;
929 if (flip
& EXYNOS_DRM_FLIP_HORIZONTAL
)
930 cfg
|= EXYNOS_CITRGFMT_FLIP_Y_MIRROR
;
932 case EXYNOS_DRM_DEGREE_180
:
933 cfg
|= (EXYNOS_CITRGFMT_FLIP_X_MIRROR
|
934 EXYNOS_CITRGFMT_FLIP_Y_MIRROR
);
935 if (flip
& EXYNOS_DRM_FLIP_VERTICAL
)
936 cfg
&= ~EXYNOS_CITRGFMT_FLIP_X_MIRROR
;
937 if (flip
& EXYNOS_DRM_FLIP_HORIZONTAL
)
938 cfg
&= ~EXYNOS_CITRGFMT_FLIP_Y_MIRROR
;
940 case EXYNOS_DRM_DEGREE_270
:
941 cfg
|= (EXYNOS_CITRGFMT_OUTROT90_CLOCKWISE
|
942 EXYNOS_CITRGFMT_FLIP_X_MIRROR
|
943 EXYNOS_CITRGFMT_FLIP_Y_MIRROR
);
944 if (flip
& EXYNOS_DRM_FLIP_VERTICAL
)
945 cfg
&= ~EXYNOS_CITRGFMT_FLIP_X_MIRROR
;
946 if (flip
& EXYNOS_DRM_FLIP_HORIZONTAL
)
947 cfg
&= ~EXYNOS_CITRGFMT_FLIP_Y_MIRROR
;
950 dev_err(ippdrv
->dev
, "inavlid degree value %d.\n", degree
);
954 fimc_write(cfg
, EXYNOS_CITRGFMT
);
955 *swap
= (cfg
& EXYNOS_CITRGFMT_OUTROT90_CLOCKWISE
) ? 1 : 0;
960 static int fimc_get_ratio_shift(u32 src
, u32 dst
, u32
*ratio
, u32
*shift
)
962 DRM_DEBUG_KMS("src[%d]dst[%d]\n", src
, dst
);
964 if (src
>= dst
* 64) {
965 DRM_ERROR("failed to make ratio and shift.\n");
967 } else if (src
>= dst
* 32) {
970 } else if (src
>= dst
* 16) {
973 } else if (src
>= dst
* 8) {
976 } else if (src
>= dst
* 4) {
979 } else if (src
>= dst
* 2) {
990 static int fimc_set_prescaler(struct fimc_context
*ctx
, struct fimc_scaler
*sc
,
991 struct drm_exynos_pos
*src
, struct drm_exynos_pos
*dst
)
993 struct exynos_drm_ippdrv
*ippdrv
= &ctx
->ippdrv
;
994 u32 cfg
, cfg_ext
, shfactor
;
995 u32 pre_dst_width
, pre_dst_height
;
996 u32 pre_hratio
, hfactor
, pre_vratio
, vfactor
;
998 u32 src_w
, src_h
, dst_w
, dst_h
;
1000 cfg_ext
= fimc_read(EXYNOS_CITRGFMT
);
1001 if (cfg_ext
& EXYNOS_CITRGFMT_INROT90_CLOCKWISE
) {
1009 if (cfg_ext
& EXYNOS_CITRGFMT_OUTROT90_CLOCKWISE
) {
1017 ret
= fimc_get_ratio_shift(src_w
, dst_w
, &pre_hratio
, &hfactor
);
1019 dev_err(ippdrv
->dev
, "failed to get ratio horizontal.\n");
1023 ret
= fimc_get_ratio_shift(src_h
, dst_h
, &pre_vratio
, &vfactor
);
1025 dev_err(ippdrv
->dev
, "failed to get ratio vertical.\n");
1029 pre_dst_width
= src_w
/ pre_hratio
;
1030 pre_dst_height
= src_h
/ pre_vratio
;
1031 DRM_DEBUG_KMS("pre_dst_width[%d]pre_dst_height[%d]\n",
1032 pre_dst_width
, pre_dst_height
);
1033 DRM_DEBUG_KMS("pre_hratio[%d]hfactor[%d]pre_vratio[%d]vfactor[%d]\n",
1034 pre_hratio
, hfactor
, pre_vratio
, vfactor
);
1036 sc
->hratio
= (src_w
<< 14) / (dst_w
<< hfactor
);
1037 sc
->vratio
= (src_h
<< 14) / (dst_h
<< vfactor
);
1038 sc
->up_h
= (dst_w
>= src_w
) ? true : false;
1039 sc
->up_v
= (dst_h
>= src_h
) ? true : false;
1040 DRM_DEBUG_KMS("hratio[%d]vratio[%d]up_h[%d]up_v[%d]\n",
1041 sc
->hratio
, sc
->vratio
, sc
->up_h
, sc
->up_v
);
1043 shfactor
= FIMC_SHFACTOR
- (hfactor
+ vfactor
);
1044 DRM_DEBUG_KMS("shfactor[%d]\n", shfactor
);
1046 cfg
= (EXYNOS_CISCPRERATIO_SHFACTOR(shfactor
) |
1047 EXYNOS_CISCPRERATIO_PREHORRATIO(pre_hratio
) |
1048 EXYNOS_CISCPRERATIO_PREVERRATIO(pre_vratio
));
1049 fimc_write(cfg
, EXYNOS_CISCPRERATIO
);
1051 cfg
= (EXYNOS_CISCPREDST_PREDSTWIDTH(pre_dst_width
) |
1052 EXYNOS_CISCPREDST_PREDSTHEIGHT(pre_dst_height
));
1053 fimc_write(cfg
, EXYNOS_CISCPREDST
);
1058 static void fimc_set_scaler(struct fimc_context
*ctx
, struct fimc_scaler
*sc
)
1062 DRM_DEBUG_KMS("range[%d]bypass[%d]up_h[%d]up_v[%d]\n",
1063 sc
->range
, sc
->bypass
, sc
->up_h
, sc
->up_v
);
1064 DRM_DEBUG_KMS("hratio[%d]vratio[%d]\n",
1065 sc
->hratio
, sc
->vratio
);
1067 cfg
= fimc_read(EXYNOS_CISCCTRL
);
1068 cfg
&= ~(EXYNOS_CISCCTRL_SCALERBYPASS
|
1069 EXYNOS_CISCCTRL_SCALEUP_H
| EXYNOS_CISCCTRL_SCALEUP_V
|
1070 EXYNOS_CISCCTRL_MAIN_V_RATIO_MASK
|
1071 EXYNOS_CISCCTRL_MAIN_H_RATIO_MASK
|
1072 EXYNOS_CISCCTRL_CSCR2Y_WIDE
|
1073 EXYNOS_CISCCTRL_CSCY2R_WIDE
);
1076 cfg
|= (EXYNOS_CISCCTRL_CSCR2Y_WIDE
|
1077 EXYNOS_CISCCTRL_CSCY2R_WIDE
);
1079 cfg
|= EXYNOS_CISCCTRL_SCALERBYPASS
;
1081 cfg
|= EXYNOS_CISCCTRL_SCALEUP_H
;
1083 cfg
|= EXYNOS_CISCCTRL_SCALEUP_V
;
1085 cfg
|= (EXYNOS_CISCCTRL_MAINHORRATIO((sc
->hratio
>> 6)) |
1086 EXYNOS_CISCCTRL_MAINVERRATIO((sc
->vratio
>> 6)));
1087 fimc_write(cfg
, EXYNOS_CISCCTRL
);
1089 cfg_ext
= fimc_read(EXYNOS_CIEXTEN
);
1090 cfg_ext
&= ~EXYNOS_CIEXTEN_MAINHORRATIO_EXT_MASK
;
1091 cfg_ext
&= ~EXYNOS_CIEXTEN_MAINVERRATIO_EXT_MASK
;
1092 cfg_ext
|= (EXYNOS_CIEXTEN_MAINHORRATIO_EXT(sc
->hratio
) |
1093 EXYNOS_CIEXTEN_MAINVERRATIO_EXT(sc
->vratio
));
1094 fimc_write(cfg_ext
, EXYNOS_CIEXTEN
);
1097 static int fimc_dst_set_size(struct device
*dev
, int swap
,
1098 struct drm_exynos_pos
*pos
, struct drm_exynos_sz
*sz
)
1100 struct fimc_context
*ctx
= get_fimc_context(dev
);
1101 struct drm_exynos_pos img_pos
= *pos
;
1102 struct drm_exynos_sz img_sz
= *sz
;
1105 DRM_DEBUG_KMS("swap[%d]hsize[%d]vsize[%d]\n",
1106 swap
, sz
->hsize
, sz
->vsize
);
1109 cfg
= (EXYNOS_ORGOSIZE_HORIZONTAL(img_sz
.hsize
) |
1110 EXYNOS_ORGOSIZE_VERTICAL(img_sz
.vsize
));
1112 fimc_write(cfg
, EXYNOS_ORGOSIZE
);
1114 DRM_DEBUG_KMS("x[%d]y[%d]w[%d]h[%d]\n", pos
->x
, pos
->y
, pos
->w
, pos
->h
);
1117 cfg
= fimc_read(EXYNOS_CIGCTRL
);
1118 cfg
&= ~EXYNOS_CIGCTRL_CSC_MASK
;
1120 if (sz
->hsize
>= FIMC_WIDTH_ITU_709
)
1121 cfg
|= EXYNOS_CIGCTRL_CSC_ITU709
;
1123 cfg
|= EXYNOS_CIGCTRL_CSC_ITU601
;
1125 fimc_write(cfg
, EXYNOS_CIGCTRL
);
1130 img_sz
.hsize
= sz
->vsize
;
1131 img_sz
.vsize
= sz
->hsize
;
1134 /* target image size */
1135 cfg
= fimc_read(EXYNOS_CITRGFMT
);
1136 cfg
&= ~(EXYNOS_CITRGFMT_TARGETH_MASK
|
1137 EXYNOS_CITRGFMT_TARGETV_MASK
);
1138 cfg
|= (EXYNOS_CITRGFMT_TARGETHSIZE(img_pos
.w
) |
1139 EXYNOS_CITRGFMT_TARGETVSIZE(img_pos
.h
));
1140 fimc_write(cfg
, EXYNOS_CITRGFMT
);
1143 cfg
= EXYNOS_CITAREA_TARGET_AREA(img_pos
.w
* img_pos
.h
);
1144 fimc_write(cfg
, EXYNOS_CITAREA
);
1146 /* offset Y(RGB), Cb, Cr */
1147 cfg
= (EXYNOS_CIOYOFF_HORIZONTAL(img_pos
.x
) |
1148 EXYNOS_CIOYOFF_VERTICAL(img_pos
.y
));
1149 fimc_write(cfg
, EXYNOS_CIOYOFF
);
1150 cfg
= (EXYNOS_CIOCBOFF_HORIZONTAL(img_pos
.x
) |
1151 EXYNOS_CIOCBOFF_VERTICAL(img_pos
.y
));
1152 fimc_write(cfg
, EXYNOS_CIOCBOFF
);
1153 cfg
= (EXYNOS_CIOCROFF_HORIZONTAL(img_pos
.x
) |
1154 EXYNOS_CIOCROFF_VERTICAL(img_pos
.y
));
1155 fimc_write(cfg
, EXYNOS_CIOCROFF
);
1160 static int fimc_dst_get_buf_seq(struct fimc_context
*ctx
)
1162 u32 cfg
, i
, buf_num
= 0;
1163 u32 mask
= 0x00000001;
1165 cfg
= fimc_read(EXYNOS_CIFCNTSEQ
);
1167 for (i
= 0; i
< FIMC_REG_SZ
; i
++)
1168 if (cfg
& (mask
<< i
))
1171 DRM_DEBUG_KMS("buf_num[%d]\n", buf_num
);
1176 static int fimc_dst_set_buf_seq(struct fimc_context
*ctx
, u32 buf_id
,
1177 enum drm_exynos_ipp_buf_type buf_type
)
1179 struct exynos_drm_ippdrv
*ippdrv
= &ctx
->ippdrv
;
1182 u32 mask
= 0x00000001 << buf_id
;
1185 DRM_DEBUG_KMS("buf_id[%d]buf_type[%d]\n", buf_id
, buf_type
);
1187 mutex_lock(&ctx
->lock
);
1189 /* mask register set */
1190 cfg
= fimc_read(EXYNOS_CIFCNTSEQ
);
1193 case IPP_BUF_ENQUEUE
:
1196 case IPP_BUF_DEQUEUE
:
1200 dev_err(ippdrv
->dev
, "invalid buf ctrl parameter.\n");
1207 cfg
|= (enable
<< buf_id
);
1208 fimc_write(cfg
, EXYNOS_CIFCNTSEQ
);
1210 /* interrupt enable */
1211 if (buf_type
== IPP_BUF_ENQUEUE
&&
1212 fimc_dst_get_buf_seq(ctx
) >= FIMC_BUF_START
)
1213 fimc_handle_irq(ctx
, true, false, true);
1215 /* interrupt disable */
1216 if (buf_type
== IPP_BUF_DEQUEUE
&&
1217 fimc_dst_get_buf_seq(ctx
) <= FIMC_BUF_STOP
)
1218 fimc_handle_irq(ctx
, false, false, true);
1221 mutex_unlock(&ctx
->lock
);
1225 static int fimc_dst_set_addr(struct device
*dev
,
1226 struct drm_exynos_ipp_buf_info
*buf_info
, u32 buf_id
,
1227 enum drm_exynos_ipp_buf_type buf_type
)
1229 struct fimc_context
*ctx
= get_fimc_context(dev
);
1230 struct exynos_drm_ippdrv
*ippdrv
= &ctx
->ippdrv
;
1231 struct drm_exynos_ipp_cmd_node
*c_node
= ippdrv
->c_node
;
1232 struct drm_exynos_ipp_property
*property
;
1233 struct drm_exynos_ipp_config
*config
;
1236 DRM_ERROR("failed to get c_node.\n");
1240 property
= &c_node
->property
;
1242 DRM_DEBUG_KMS("prop_id[%d]buf_id[%d]buf_type[%d]\n",
1243 property
->prop_id
, buf_id
, buf_type
);
1245 if (buf_id
> FIMC_MAX_DST
) {
1246 dev_info(ippdrv
->dev
, "inavlid buf_id %d.\n", buf_id
);
1250 /* address register set */
1252 case IPP_BUF_ENQUEUE
:
1253 config
= &property
->config
[EXYNOS_DRM_OPS_DST
];
1255 fimc_write(buf_info
->base
[EXYNOS_DRM_PLANAR_Y
],
1256 EXYNOS_CIOYSA(buf_id
));
1258 if (config
->fmt
== DRM_FORMAT_YVU420
) {
1259 fimc_write(buf_info
->base
[EXYNOS_DRM_PLANAR_CR
],
1260 EXYNOS_CIOCBSA(buf_id
));
1261 fimc_write(buf_info
->base
[EXYNOS_DRM_PLANAR_CB
],
1262 EXYNOS_CIOCRSA(buf_id
));
1264 fimc_write(buf_info
->base
[EXYNOS_DRM_PLANAR_CB
],
1265 EXYNOS_CIOCBSA(buf_id
));
1266 fimc_write(buf_info
->base
[EXYNOS_DRM_PLANAR_CR
],
1267 EXYNOS_CIOCRSA(buf_id
));
1270 case IPP_BUF_DEQUEUE
:
1271 fimc_write(0x0, EXYNOS_CIOYSA(buf_id
));
1272 fimc_write(0x0, EXYNOS_CIOCBSA(buf_id
));
1273 fimc_write(0x0, EXYNOS_CIOCRSA(buf_id
));
1280 return fimc_dst_set_buf_seq(ctx
, buf_id
, buf_type
);
1283 static struct exynos_drm_ipp_ops fimc_dst_ops
= {
1284 .set_fmt
= fimc_dst_set_fmt
,
1285 .set_transf
= fimc_dst_set_transf
,
1286 .set_size
= fimc_dst_set_size
,
1287 .set_addr
= fimc_dst_set_addr
,
1290 static int fimc_clk_ctrl(struct fimc_context
*ctx
, bool enable
)
1292 DRM_DEBUG_KMS("enable[%d]\n", enable
);
1295 clk_prepare_enable(ctx
->clocks
[FIMC_CLK_GATE
]);
1296 clk_prepare_enable(ctx
->clocks
[FIMC_CLK_WB_A
]);
1297 ctx
->suspended
= false;
1299 clk_disable_unprepare(ctx
->clocks
[FIMC_CLK_GATE
]);
1300 clk_disable_unprepare(ctx
->clocks
[FIMC_CLK_WB_A
]);
1301 ctx
->suspended
= true;
1307 static irqreturn_t
fimc_irq_handler(int irq
, void *dev_id
)
1309 struct fimc_context
*ctx
= dev_id
;
1310 struct exynos_drm_ippdrv
*ippdrv
= &ctx
->ippdrv
;
1311 struct drm_exynos_ipp_cmd_node
*c_node
= ippdrv
->c_node
;
1312 struct drm_exynos_ipp_event_work
*event_work
=
1316 DRM_DEBUG_KMS("fimc id[%d]\n", ctx
->id
);
1318 fimc_clear_irq(ctx
);
1319 if (fimc_check_ovf(ctx
))
1322 if (!fimc_check_frame_end(ctx
))
1325 buf_id
= fimc_get_buf_id(ctx
);
1329 DRM_DEBUG_KMS("buf_id[%d]\n", buf_id
);
1331 if (fimc_dst_set_buf_seq(ctx
, buf_id
, IPP_BUF_DEQUEUE
) < 0) {
1332 DRM_ERROR("failed to dequeue.\n");
1336 event_work
->ippdrv
= ippdrv
;
1337 event_work
->buf_id
[EXYNOS_DRM_OPS_DST
] = buf_id
;
1338 queue_work(ippdrv
->event_workq
, (struct work_struct
*)event_work
);
1343 static int fimc_init_prop_list(struct exynos_drm_ippdrv
*ippdrv
)
1345 struct drm_exynos_ipp_prop_list
*prop_list
;
1347 prop_list
= devm_kzalloc(ippdrv
->dev
, sizeof(*prop_list
), GFP_KERNEL
);
1351 prop_list
->version
= 1;
1352 prop_list
->writeback
= 1;
1353 prop_list
->refresh_min
= FIMC_REFRESH_MIN
;
1354 prop_list
->refresh_max
= FIMC_REFRESH_MAX
;
1355 prop_list
->flip
= (1 << EXYNOS_DRM_FLIP_NONE
) |
1356 (1 << EXYNOS_DRM_FLIP_VERTICAL
) |
1357 (1 << EXYNOS_DRM_FLIP_HORIZONTAL
);
1358 prop_list
->degree
= (1 << EXYNOS_DRM_DEGREE_0
) |
1359 (1 << EXYNOS_DRM_DEGREE_90
) |
1360 (1 << EXYNOS_DRM_DEGREE_180
) |
1361 (1 << EXYNOS_DRM_DEGREE_270
);
1363 prop_list
->crop
= 1;
1364 prop_list
->crop_max
.hsize
= FIMC_CROP_MAX
;
1365 prop_list
->crop_max
.vsize
= FIMC_CROP_MAX
;
1366 prop_list
->crop_min
.hsize
= FIMC_CROP_MIN
;
1367 prop_list
->crop_min
.vsize
= FIMC_CROP_MIN
;
1368 prop_list
->scale
= 1;
1369 prop_list
->scale_max
.hsize
= FIMC_SCALE_MAX
;
1370 prop_list
->scale_max
.vsize
= FIMC_SCALE_MAX
;
1371 prop_list
->scale_min
.hsize
= FIMC_SCALE_MIN
;
1372 prop_list
->scale_min
.vsize
= FIMC_SCALE_MIN
;
1374 ippdrv
->prop_list
= prop_list
;
1379 static inline bool fimc_check_drm_flip(enum drm_exynos_flip flip
)
1382 case EXYNOS_DRM_FLIP_NONE
:
1383 case EXYNOS_DRM_FLIP_VERTICAL
:
1384 case EXYNOS_DRM_FLIP_HORIZONTAL
:
1385 case EXYNOS_DRM_FLIP_BOTH
:
1388 DRM_DEBUG_KMS("invalid flip\n");
1393 static int fimc_ippdrv_check_property(struct device
*dev
,
1394 struct drm_exynos_ipp_property
*property
)
1396 struct fimc_context
*ctx
= get_fimc_context(dev
);
1397 struct exynos_drm_ippdrv
*ippdrv
= &ctx
->ippdrv
;
1398 struct drm_exynos_ipp_prop_list
*pp
= ippdrv
->prop_list
;
1399 struct drm_exynos_ipp_config
*config
;
1400 struct drm_exynos_pos
*pos
;
1401 struct drm_exynos_sz
*sz
;
1405 for_each_ipp_ops(i
) {
1406 if ((i
== EXYNOS_DRM_OPS_SRC
) &&
1407 (property
->cmd
== IPP_CMD_WB
))
1410 config
= &property
->config
[i
];
1414 /* check for flip */
1415 if (!fimc_check_drm_flip(config
->flip
)) {
1416 DRM_ERROR("invalid flip.\n");
1420 /* check for degree */
1421 switch (config
->degree
) {
1422 case EXYNOS_DRM_DEGREE_90
:
1423 case EXYNOS_DRM_DEGREE_270
:
1426 case EXYNOS_DRM_DEGREE_0
:
1427 case EXYNOS_DRM_DEGREE_180
:
1431 DRM_ERROR("invalid degree.\n");
1435 /* check for buffer bound */
1436 if ((pos
->x
+ pos
->w
> sz
->hsize
) ||
1437 (pos
->y
+ pos
->h
> sz
->vsize
)) {
1438 DRM_ERROR("out of buf bound.\n");
1442 /* check for crop */
1443 if ((i
== EXYNOS_DRM_OPS_SRC
) && (pp
->crop
)) {
1445 if ((pos
->h
< pp
->crop_min
.hsize
) ||
1446 (sz
->vsize
> pp
->crop_max
.hsize
) ||
1447 (pos
->w
< pp
->crop_min
.vsize
) ||
1448 (sz
->hsize
> pp
->crop_max
.vsize
)) {
1449 DRM_ERROR("out of crop size.\n");
1453 if ((pos
->w
< pp
->crop_min
.hsize
) ||
1454 (sz
->hsize
> pp
->crop_max
.hsize
) ||
1455 (pos
->h
< pp
->crop_min
.vsize
) ||
1456 (sz
->vsize
> pp
->crop_max
.vsize
)) {
1457 DRM_ERROR("out of crop size.\n");
1463 /* check for scale */
1464 if ((i
== EXYNOS_DRM_OPS_DST
) && (pp
->scale
)) {
1466 if ((pos
->h
< pp
->scale_min
.hsize
) ||
1467 (sz
->vsize
> pp
->scale_max
.hsize
) ||
1468 (pos
->w
< pp
->scale_min
.vsize
) ||
1469 (sz
->hsize
> pp
->scale_max
.vsize
)) {
1470 DRM_ERROR("out of scale size.\n");
1474 if ((pos
->w
< pp
->scale_min
.hsize
) ||
1475 (sz
->hsize
> pp
->scale_max
.hsize
) ||
1476 (pos
->h
< pp
->scale_min
.vsize
) ||
1477 (sz
->vsize
> pp
->scale_max
.vsize
)) {
1478 DRM_ERROR("out of scale size.\n");
1488 for_each_ipp_ops(i
) {
1489 if ((i
== EXYNOS_DRM_OPS_SRC
) &&
1490 (property
->cmd
== IPP_CMD_WB
))
1493 config
= &property
->config
[i
];
1497 DRM_ERROR("[%s]f[%d]r[%d]pos[%d %d %d %d]sz[%d %d]\n",
1498 i
? "dst" : "src", config
->flip
, config
->degree
,
1499 pos
->x
, pos
->y
, pos
->w
, pos
->h
,
1500 sz
->hsize
, sz
->vsize
);
1506 static void fimc_clear_addr(struct fimc_context
*ctx
)
1510 for (i
= 0; i
< FIMC_MAX_SRC
; i
++) {
1511 fimc_write(0, EXYNOS_CIIYSA(i
));
1512 fimc_write(0, EXYNOS_CIICBSA(i
));
1513 fimc_write(0, EXYNOS_CIICRSA(i
));
1516 for (i
= 0; i
< FIMC_MAX_DST
; i
++) {
1517 fimc_write(0, EXYNOS_CIOYSA(i
));
1518 fimc_write(0, EXYNOS_CIOCBSA(i
));
1519 fimc_write(0, EXYNOS_CIOCRSA(i
));
1523 static int fimc_ippdrv_reset(struct device
*dev
)
1525 struct fimc_context
*ctx
= get_fimc_context(dev
);
1527 /* reset h/w block */
1530 /* reset scaler capability */
1531 memset(&ctx
->sc
, 0x0, sizeof(ctx
->sc
));
1533 fimc_clear_addr(ctx
);
1538 static int fimc_ippdrv_start(struct device
*dev
, enum drm_exynos_ipp_cmd cmd
)
1540 struct fimc_context
*ctx
= get_fimc_context(dev
);
1541 struct exynos_drm_ippdrv
*ippdrv
= &ctx
->ippdrv
;
1542 struct drm_exynos_ipp_cmd_node
*c_node
= ippdrv
->c_node
;
1543 struct drm_exynos_ipp_property
*property
;
1544 struct drm_exynos_ipp_config
*config
;
1545 struct drm_exynos_pos img_pos
[EXYNOS_DRM_OPS_MAX
];
1546 struct drm_exynos_ipp_set_wb set_wb
;
1550 DRM_DEBUG_KMS("cmd[%d]\n", cmd
);
1553 DRM_ERROR("failed to get c_node.\n");
1557 property
= &c_node
->property
;
1559 fimc_handle_irq(ctx
, true, false, true);
1561 for_each_ipp_ops(i
) {
1562 config
= &property
->config
[i
];
1563 img_pos
[i
] = config
->pos
;
1566 ret
= fimc_set_prescaler(ctx
, &ctx
->sc
,
1567 &img_pos
[EXYNOS_DRM_OPS_SRC
],
1568 &img_pos
[EXYNOS_DRM_OPS_DST
]);
1570 dev_err(dev
, "failed to set precalser.\n");
1574 /* If set ture, we can save jpeg about screen */
1575 fimc_handle_jpeg(ctx
, false);
1576 fimc_set_scaler(ctx
, &ctx
->sc
);
1577 fimc_set_polarity(ctx
, &ctx
->pol
);
1581 fimc_set_type_ctrl(ctx
, FIMC_WB_NONE
);
1582 fimc_handle_lastend(ctx
, false);
1585 cfg0
= fimc_read(EXYNOS_MSCTRL
);
1586 cfg0
&= ~EXYNOS_MSCTRL_INPUT_MASK
;
1587 cfg0
|= EXYNOS_MSCTRL_INPUT_MEMORY
;
1588 fimc_write(cfg0
, EXYNOS_MSCTRL
);
1591 fimc_set_type_ctrl(ctx
, FIMC_WB_A
);
1592 fimc_handle_lastend(ctx
, true);
1595 ret
= fimc_set_camblk_fimd0_wb(ctx
);
1597 dev_err(dev
, "camblk setup failed.\n");
1602 set_wb
.refresh
= property
->refresh_rate
;
1603 exynos_drm_ippnb_send_event(IPP_SET_WRITEBACK
, (void *)&set_wb
);
1605 case IPP_CMD_OUTPUT
:
1608 dev_err(dev
, "invalid operations.\n");
1613 fimc_write(0x0, EXYNOS_CISTATUS
);
1615 cfg0
= fimc_read(EXYNOS_CIIMGCPT
);
1616 cfg0
&= ~EXYNOS_CIIMGCPT_IMGCPTEN_SC
;
1617 cfg0
|= EXYNOS_CIIMGCPT_IMGCPTEN_SC
;
1620 cfg1
= fimc_read(EXYNOS_CISCCTRL
);
1621 cfg1
&= ~EXYNOS_CISCCTRL_SCAN_MASK
;
1622 cfg1
|= (EXYNOS_CISCCTRL_PROGRESSIVE
|
1623 EXYNOS_CISCCTRL_SCALERSTART
);
1625 fimc_write(cfg1
, EXYNOS_CISCCTRL
);
1627 /* Enable image capture*/
1628 cfg0
|= EXYNOS_CIIMGCPT_IMGCPTEN
;
1629 fimc_write(cfg0
, EXYNOS_CIIMGCPT
);
1631 /* Disable frame end irq */
1632 cfg0
= fimc_read(EXYNOS_CIGCTRL
);
1633 cfg0
&= ~EXYNOS_CIGCTRL_IRQ_END_DISABLE
;
1634 fimc_write(cfg0
, EXYNOS_CIGCTRL
);
1636 cfg0
= fimc_read(EXYNOS_CIOCTRL
);
1637 cfg0
&= ~EXYNOS_CIOCTRL_WEAVE_MASK
;
1638 fimc_write(cfg0
, EXYNOS_CIOCTRL
);
1640 if (cmd
== IPP_CMD_M2M
) {
1641 cfg0
= fimc_read(EXYNOS_MSCTRL
);
1642 cfg0
|= EXYNOS_MSCTRL_ENVID
;
1643 fimc_write(cfg0
, EXYNOS_MSCTRL
);
1645 cfg0
= fimc_read(EXYNOS_MSCTRL
);
1646 cfg0
|= EXYNOS_MSCTRL_ENVID
;
1647 fimc_write(cfg0
, EXYNOS_MSCTRL
);
1653 static void fimc_ippdrv_stop(struct device
*dev
, enum drm_exynos_ipp_cmd cmd
)
1655 struct fimc_context
*ctx
= get_fimc_context(dev
);
1656 struct drm_exynos_ipp_set_wb set_wb
= {0, 0};
1659 DRM_DEBUG_KMS("cmd[%d]\n", cmd
);
1664 cfg
= fimc_read(EXYNOS_MSCTRL
);
1665 cfg
&= ~EXYNOS_MSCTRL_INPUT_MASK
;
1666 cfg
&= ~EXYNOS_MSCTRL_ENVID
;
1667 fimc_write(cfg
, EXYNOS_MSCTRL
);
1670 exynos_drm_ippnb_send_event(IPP_SET_WRITEBACK
, (void *)&set_wb
);
1672 case IPP_CMD_OUTPUT
:
1674 dev_err(dev
, "invalid operations.\n");
1678 fimc_handle_irq(ctx
, false, false, true);
1680 /* reset sequence */
1681 fimc_write(0x0, EXYNOS_CIFCNTSEQ
);
1683 /* Scaler disable */
1684 cfg
= fimc_read(EXYNOS_CISCCTRL
);
1685 cfg
&= ~EXYNOS_CISCCTRL_SCALERSTART
;
1686 fimc_write(cfg
, EXYNOS_CISCCTRL
);
1688 /* Disable image capture */
1689 cfg
= fimc_read(EXYNOS_CIIMGCPT
);
1690 cfg
&= ~(EXYNOS_CIIMGCPT_IMGCPTEN_SC
| EXYNOS_CIIMGCPT_IMGCPTEN
);
1691 fimc_write(cfg
, EXYNOS_CIIMGCPT
);
1693 /* Enable frame end irq */
1694 cfg
= fimc_read(EXYNOS_CIGCTRL
);
1695 cfg
|= EXYNOS_CIGCTRL_IRQ_END_DISABLE
;
1696 fimc_write(cfg
, EXYNOS_CIGCTRL
);
1699 static void fimc_put_clocks(struct fimc_context
*ctx
)
1703 for (i
= 0; i
< FIMC_CLKS_MAX
; i
++) {
1704 if (IS_ERR(ctx
->clocks
[i
]))
1706 clk_put(ctx
->clocks
[i
]);
1707 ctx
->clocks
[i
] = ERR_PTR(-EINVAL
);
1711 static int fimc_setup_clocks(struct fimc_context
*ctx
)
1713 struct device
*fimc_dev
= ctx
->ippdrv
.dev
;
1717 for (i
= 0; i
< FIMC_CLKS_MAX
; i
++)
1718 ctx
->clocks
[i
] = ERR_PTR(-EINVAL
);
1720 for (i
= 0; i
< FIMC_CLKS_MAX
; i
++) {
1721 if (i
== FIMC_CLK_WB_A
|| i
== FIMC_CLK_WB_B
)
1722 dev
= fimc_dev
->parent
;
1726 ctx
->clocks
[i
] = clk_get(dev
, fimc_clock_names
[i
]);
1727 if (IS_ERR(ctx
->clocks
[i
])) {
1728 if (i
>= FIMC_CLK_MUX
)
1730 ret
= PTR_ERR(ctx
->clocks
[i
]);
1731 dev_err(fimc_dev
, "failed to get clock: %s\n",
1732 fimc_clock_names
[i
]);
1737 /* Optional FIMC LCLK parent clock setting */
1738 if (!IS_ERR(ctx
->clocks
[FIMC_CLK_PARENT
])) {
1739 ret
= clk_set_parent(ctx
->clocks
[FIMC_CLK_MUX
],
1740 ctx
->clocks
[FIMC_CLK_PARENT
]);
1742 dev_err(fimc_dev
, "failed to set parent.\n");
1747 ret
= clk_set_rate(ctx
->clocks
[FIMC_CLK_LCLK
], ctx
->clk_frequency
);
1751 ret
= clk_prepare_enable(ctx
->clocks
[FIMC_CLK_LCLK
]);
1755 fimc_put_clocks(ctx
);
1759 static int fimc_parse_dt(struct fimc_context
*ctx
)
1761 struct device_node
*node
= ctx
->ippdrv
.dev
->of_node
;
1763 /* Handle only devices that support the LCD Writeback data path */
1764 if (!of_property_read_bool(node
, "samsung,lcd-wb"))
1767 if (of_property_read_u32(node
, "clock-frequency",
1768 &ctx
->clk_frequency
))
1769 ctx
->clk_frequency
= FIMC_DEFAULT_LCLK_FREQUENCY
;
1771 ctx
->id
= of_alias_get_id(node
, "fimc");
1774 dev_err(ctx
->ippdrv
.dev
, "failed to get node alias id.\n");
1781 static int fimc_probe(struct platform_device
*pdev
)
1783 struct device
*dev
= &pdev
->dev
;
1784 struct fimc_context
*ctx
;
1785 struct resource
*res
;
1786 struct exynos_drm_ippdrv
*ippdrv
;
1789 if (!dev
->of_node
) {
1790 dev_err(dev
, "device tree node not found.\n");
1794 ctx
= devm_kzalloc(dev
, sizeof(*ctx
), GFP_KERNEL
);
1798 ctx
->ippdrv
.dev
= dev
;
1800 ret
= fimc_parse_dt(ctx
);
1804 ctx
->sysreg
= syscon_regmap_lookup_by_phandle(dev
->of_node
,
1806 if (IS_ERR(ctx
->sysreg
)) {
1807 dev_err(dev
, "syscon regmap lookup failed.\n");
1808 return PTR_ERR(ctx
->sysreg
);
1811 /* resource memory */
1812 ctx
->regs_res
= platform_get_resource(pdev
, IORESOURCE_MEM
, 0);
1813 ctx
->regs
= devm_ioremap_resource(dev
, ctx
->regs_res
);
1814 if (IS_ERR(ctx
->regs
))
1815 return PTR_ERR(ctx
->regs
);
1818 res
= platform_get_resource(pdev
, IORESOURCE_IRQ
, 0);
1820 dev_err(dev
, "failed to request irq resource.\n");
1824 ctx
->irq
= res
->start
;
1825 ret
= devm_request_threaded_irq(dev
, ctx
->irq
, NULL
, fimc_irq_handler
,
1826 IRQF_ONESHOT
, "drm_fimc", ctx
);
1828 dev_err(dev
, "failed to request irq.\n");
1832 ret
= fimc_setup_clocks(ctx
);
1836 ippdrv
= &ctx
->ippdrv
;
1837 ippdrv
->ops
[EXYNOS_DRM_OPS_SRC
] = &fimc_src_ops
;
1838 ippdrv
->ops
[EXYNOS_DRM_OPS_DST
] = &fimc_dst_ops
;
1839 ippdrv
->check_property
= fimc_ippdrv_check_property
;
1840 ippdrv
->reset
= fimc_ippdrv_reset
;
1841 ippdrv
->start
= fimc_ippdrv_start
;
1842 ippdrv
->stop
= fimc_ippdrv_stop
;
1843 ret
= fimc_init_prop_list(ippdrv
);
1845 dev_err(dev
, "failed to init property list.\n");
1849 DRM_DEBUG_KMS("id[%d]ippdrv[0x%x]\n", ctx
->id
, (int)ippdrv
);
1851 mutex_init(&ctx
->lock
);
1852 platform_set_drvdata(pdev
, ctx
);
1854 pm_runtime_set_active(dev
);
1855 pm_runtime_enable(dev
);
1857 ret
= exynos_drm_ippdrv_register(ippdrv
);
1859 dev_err(dev
, "failed to register drm fimc device.\n");
1863 dev_info(dev
, "drm fimc registered successfully.\n");
1868 pm_runtime_disable(dev
);
1870 fimc_put_clocks(ctx
);
1875 static int fimc_remove(struct platform_device
*pdev
)
1877 struct device
*dev
= &pdev
->dev
;
1878 struct fimc_context
*ctx
= get_fimc_context(dev
);
1879 struct exynos_drm_ippdrv
*ippdrv
= &ctx
->ippdrv
;
1881 exynos_drm_ippdrv_unregister(ippdrv
);
1882 mutex_destroy(&ctx
->lock
);
1884 fimc_put_clocks(ctx
);
1885 pm_runtime_set_suspended(dev
);
1886 pm_runtime_disable(dev
);
1891 #ifdef CONFIG_PM_SLEEP
1892 static int fimc_suspend(struct device
*dev
)
1894 struct fimc_context
*ctx
= get_fimc_context(dev
);
1896 DRM_DEBUG_KMS("id[%d]\n", ctx
->id
);
1898 if (pm_runtime_suspended(dev
))
1901 return fimc_clk_ctrl(ctx
, false);
1904 static int fimc_resume(struct device
*dev
)
1906 struct fimc_context
*ctx
= get_fimc_context(dev
);
1908 DRM_DEBUG_KMS("id[%d]\n", ctx
->id
);
1910 if (!pm_runtime_suspended(dev
))
1911 return fimc_clk_ctrl(ctx
, true);
1917 #ifdef CONFIG_PM_RUNTIME
1918 static int fimc_runtime_suspend(struct device
*dev
)
1920 struct fimc_context
*ctx
= get_fimc_context(dev
);
1922 DRM_DEBUG_KMS("id[%d]\n", ctx
->id
);
1924 return fimc_clk_ctrl(ctx
, false);
1927 static int fimc_runtime_resume(struct device
*dev
)
1929 struct fimc_context
*ctx
= get_fimc_context(dev
);
1931 DRM_DEBUG_KMS("id[%d]\n", ctx
->id
);
1933 return fimc_clk_ctrl(ctx
, true);
1937 static const struct dev_pm_ops fimc_pm_ops
= {
1938 SET_SYSTEM_SLEEP_PM_OPS(fimc_suspend
, fimc_resume
)
1939 SET_RUNTIME_PM_OPS(fimc_runtime_suspend
, fimc_runtime_resume
, NULL
)
1942 static const struct of_device_id fimc_of_match
[] = {
1943 { .compatible
= "samsung,exynos4210-fimc" },
1944 { .compatible
= "samsung,exynos4212-fimc" },
1948 struct platform_driver fimc_driver
= {
1949 .probe
= fimc_probe
,
1950 .remove
= fimc_remove
,
1952 .of_match_table
= fimc_of_match
,
1953 .name
= "exynos-drm-fimc",
1954 .owner
= THIS_MODULE
,