2 * Copyright (C) 2012 Samsung Electronics Co.Ltd
4 * Eunchul Kim <chulspro.kim@samsung.com>
5 * Jinyoung Jeon <jy0.jeon@samsung.com>
6 * Sangmin Lee <lsmin.lee@samsung.com>
8 * This program is free software; you can redistribute it and/or modify it
9 * under the terms of the GNU General Public License as published by the
10 * Free Software Foundation; either version 2 of the License, or (at your
11 * option) any later version.
14 #include <linux/kernel.h>
15 #include <linux/module.h>
16 #include <linux/platform_device.h>
17 #include <linux/clk.h>
18 #include <linux/pm_runtime.h>
19 #include <plat/map-base.h>
22 #include <drm/exynos_drm.h>
23 #include "regs-fimc.h"
24 #include "exynos_drm_ipp.h"
25 #include "exynos_drm_fimc.h"
28 * FIMC is stand for Fully Interactive Mobile Camera and
29 * supports image scaler/rotator and input/output DMA operations.
30 * input DMA reads image data from the memory.
31 * output DMA writes image data to memory.
32 * FIMC supports image rotation and image effect functions.
34 * M2M operation : supports crop/scale/rotation/csc so on.
35 * Memory ----> FIMC H/W ----> Memory.
36 * Writeback operation : supports cloned screen with FIMD.
37 * FIMD ----> FIMC H/W ----> Memory.
38 * Output operation : supports direct display using local path.
39 * Memory ----> FIMC H/W ----> FIMD.
44 * 1. check suspend/resume api if needed.
45 * 2. need to check use case platform_device_id.
46 * 3. check src/dst size with, height.
47 * 4. added check_prepare api for right register.
48 * 5. need to add supported list in prop_list.
49 * 6. check prescaler/scaler optimization.
52 #define FIMC_MAX_DEVS 4
53 #define FIMC_MAX_SRC 2
54 #define FIMC_MAX_DST 32
55 #define FIMC_SHFACTOR 10
56 #define FIMC_BUF_STOP 1
57 #define FIMC_BUF_START 2
58 #define FIMC_REG_SZ 32
59 #define FIMC_WIDTH_ITU_709 1280
60 #define FIMC_REFRESH_MAX 60
61 #define FIMC_REFRESH_MIN 12
62 #define FIMC_CROP_MAX 8192
63 #define FIMC_CROP_MIN 32
64 #define FIMC_SCALE_MAX 4224
65 #define FIMC_SCALE_MIN 32
67 #define get_fimc_context(dev) platform_get_drvdata(to_platform_device(dev))
68 #define get_ctx_from_ippdrv(ippdrv) container_of(ippdrv,\
69 struct fimc_context, ippdrv);
70 #define fimc_read(offset) readl(ctx->regs + (offset))
71 #define fimc_write(cfg, offset) writel(cfg, ctx->regs + (offset))
80 * A structure of scaler.
82 * @range: narrow, wide.
83 * @bypass: unused scaler path.
84 * @up_h: horizontal scale up.
85 * @up_v: vertical scale up.
86 * @hratio: horizontal ratio.
87 * @vratio: vertical ratio.
99 * A structure of scaler capability.
101 * find user manual table 43-1.
102 * @in_hori: scaler input horizontal size.
103 * @bypass: scaler bypass mode.
104 * @dst_h_wo_rot: target horizontal size without output rotation.
105 * @dst_h_rot: target horizontal size with output rotation.
106 * @rl_w_wo_rot: real width without input rotation.
107 * @rl_h_rot: real height without output rotation.
109 struct fimc_capability
{
122 * A structure of fimc driver data.
124 * @parent_clk: name of parent clock.
126 struct fimc_driverdata
{
131 * A structure of fimc context.
133 * @ippdrv: prepare initialization using ippdrv.
134 * @regs_res: register resources.
135 * @regs: memory mapped io registers.
136 * @lock: locking of operations.
137 * @sclk_fimc_clk: fimc source clock.
138 * @fimc_clk: fimc clock.
139 * @wb_clk: writeback a clock.
140 * @wb_b_clk: writeback b clock.
141 * @sc: scaler infomations.
142 * @odr: ordering of YUV.
143 * @ver: fimc version.
144 * @pol: porarity of writeback.
147 * @suspended: qos operations.
149 struct fimc_context
{
150 struct exynos_drm_ippdrv ippdrv
;
151 struct resource
*regs_res
;
154 struct clk
*sclk_fimc_clk
;
155 struct clk
*fimc_clk
;
157 struct clk
*wb_b_clk
;
158 struct fimc_scaler sc
;
159 struct fimc_driverdata
*ddata
;
160 struct exynos_drm_ipp_pol pol
;
166 static void fimc_sw_reset(struct fimc_context
*ctx
, bool pattern
)
170 DRM_DEBUG_KMS("%s:pattern[%d]\n", __func__
, pattern
);
172 cfg
= fimc_read(EXYNOS_CISRCFMT
);
173 cfg
|= EXYNOS_CISRCFMT_ITU601_8BIT
;
175 cfg
|= EXYNOS_CIGCTRL_TESTPATTERN_COLOR_BAR
;
177 fimc_write(cfg
, EXYNOS_CISRCFMT
);
180 cfg
= fimc_read(EXYNOS_CIGCTRL
);
181 cfg
|= (EXYNOS_CIGCTRL_SWRST
);
182 fimc_write(cfg
, EXYNOS_CIGCTRL
);
184 /* s/w reset complete */
185 cfg
= fimc_read(EXYNOS_CIGCTRL
);
186 cfg
&= ~EXYNOS_CIGCTRL_SWRST
;
187 fimc_write(cfg
, EXYNOS_CIGCTRL
);
190 fimc_write(0x0, EXYNOS_CIFCNTSEQ
);
193 static void fimc_set_camblk_fimd0_wb(struct fimc_context
*ctx
)
197 DRM_DEBUG_KMS("%s\n", __func__
);
199 camblk_cfg
= readl(SYSREG_CAMERA_BLK
);
200 camblk_cfg
&= ~(SYSREG_FIMD0WB_DEST_MASK
);
201 camblk_cfg
|= ctx
->id
<< (SYSREG_FIMD0WB_DEST_SHIFT
);
203 writel(camblk_cfg
, SYSREG_CAMERA_BLK
);
206 static void fimc_set_type_ctrl(struct fimc_context
*ctx
, enum fimc_wb wb
)
210 DRM_DEBUG_KMS("%s:wb[%d]\n", __func__
, wb
);
212 cfg
= fimc_read(EXYNOS_CIGCTRL
);
213 cfg
&= ~(EXYNOS_CIGCTRL_TESTPATTERN_MASK
|
214 EXYNOS_CIGCTRL_SELCAM_ITU_MASK
|
215 EXYNOS_CIGCTRL_SELCAM_MIPI_MASK
|
216 EXYNOS_CIGCTRL_SELCAM_FIMC_MASK
|
217 EXYNOS_CIGCTRL_SELWB_CAMIF_MASK
|
218 EXYNOS_CIGCTRL_SELWRITEBACK_MASK
);
222 cfg
|= (EXYNOS_CIGCTRL_SELWRITEBACK_A
|
223 EXYNOS_CIGCTRL_SELWB_CAMIF_WRITEBACK
);
226 cfg
|= (EXYNOS_CIGCTRL_SELWRITEBACK_B
|
227 EXYNOS_CIGCTRL_SELWB_CAMIF_WRITEBACK
);
231 cfg
|= (EXYNOS_CIGCTRL_SELCAM_ITU_A
|
232 EXYNOS_CIGCTRL_SELWRITEBACK_A
|
233 EXYNOS_CIGCTRL_SELCAM_MIPI_A
|
234 EXYNOS_CIGCTRL_SELCAM_FIMC_ITU
);
238 fimc_write(cfg
, EXYNOS_CIGCTRL
);
241 static void fimc_set_polarity(struct fimc_context
*ctx
,
242 struct exynos_drm_ipp_pol
*pol
)
246 DRM_DEBUG_KMS("%s:inv_pclk[%d]inv_vsync[%d]\n",
247 __func__
, pol
->inv_pclk
, pol
->inv_vsync
);
248 DRM_DEBUG_KMS("%s:inv_href[%d]inv_hsync[%d]\n",
249 __func__
, pol
->inv_href
, pol
->inv_hsync
);
251 cfg
= fimc_read(EXYNOS_CIGCTRL
);
252 cfg
&= ~(EXYNOS_CIGCTRL_INVPOLPCLK
| EXYNOS_CIGCTRL_INVPOLVSYNC
|
253 EXYNOS_CIGCTRL_INVPOLHREF
| EXYNOS_CIGCTRL_INVPOLHSYNC
);
256 cfg
|= EXYNOS_CIGCTRL_INVPOLPCLK
;
258 cfg
|= EXYNOS_CIGCTRL_INVPOLVSYNC
;
260 cfg
|= EXYNOS_CIGCTRL_INVPOLHREF
;
262 cfg
|= EXYNOS_CIGCTRL_INVPOLHSYNC
;
264 fimc_write(cfg
, EXYNOS_CIGCTRL
);
267 static void fimc_handle_jpeg(struct fimc_context
*ctx
, bool enable
)
271 DRM_DEBUG_KMS("%s:enable[%d]\n", __func__
, enable
);
273 cfg
= fimc_read(EXYNOS_CIGCTRL
);
275 cfg
|= EXYNOS_CIGCTRL_CAM_JPEG
;
277 cfg
&= ~EXYNOS_CIGCTRL_CAM_JPEG
;
279 fimc_write(cfg
, EXYNOS_CIGCTRL
);
282 static void fimc_handle_irq(struct fimc_context
*ctx
, bool enable
,
283 bool overflow
, bool level
)
287 DRM_DEBUG_KMS("%s:enable[%d]overflow[%d]level[%d]\n", __func__
,
288 enable
, overflow
, level
);
290 cfg
= fimc_read(EXYNOS_CIGCTRL
);
292 cfg
&= ~(EXYNOS_CIGCTRL_IRQ_OVFEN
| EXYNOS_CIGCTRL_IRQ_LEVEL
);
293 cfg
|= EXYNOS_CIGCTRL_IRQ_ENABLE
;
295 cfg
|= EXYNOS_CIGCTRL_IRQ_OVFEN
;
297 cfg
|= EXYNOS_CIGCTRL_IRQ_LEVEL
;
299 cfg
&= ~(EXYNOS_CIGCTRL_IRQ_OVFEN
| EXYNOS_CIGCTRL_IRQ_ENABLE
);
301 fimc_write(cfg
, EXYNOS_CIGCTRL
);
304 static void fimc_clear_irq(struct fimc_context
*ctx
)
308 DRM_DEBUG_KMS("%s\n", __func__
);
310 cfg
= fimc_read(EXYNOS_CIGCTRL
);
311 cfg
|= EXYNOS_CIGCTRL_IRQ_CLR
;
312 fimc_write(cfg
, EXYNOS_CIGCTRL
);
315 static bool fimc_check_ovf(struct fimc_context
*ctx
)
317 struct exynos_drm_ippdrv
*ippdrv
= &ctx
->ippdrv
;
318 u32 cfg
, status
, flag
;
320 status
= fimc_read(EXYNOS_CISTATUS
);
321 flag
= EXYNOS_CISTATUS_OVFIY
| EXYNOS_CISTATUS_OVFICB
|
322 EXYNOS_CISTATUS_OVFICR
;
324 DRM_DEBUG_KMS("%s:flag[0x%x]\n", __func__
, flag
);
327 cfg
= fimc_read(EXYNOS_CIWDOFST
);
328 cfg
|= (EXYNOS_CIWDOFST_CLROVFIY
| EXYNOS_CIWDOFST_CLROVFICB
|
329 EXYNOS_CIWDOFST_CLROVFICR
);
331 fimc_write(cfg
, EXYNOS_CIWDOFST
);
333 cfg
= fimc_read(EXYNOS_CIWDOFST
);
334 cfg
&= ~(EXYNOS_CIWDOFST_CLROVFIY
| EXYNOS_CIWDOFST_CLROVFICB
|
335 EXYNOS_CIWDOFST_CLROVFICR
);
337 fimc_write(cfg
, EXYNOS_CIWDOFST
);
339 dev_err(ippdrv
->dev
, "occured overflow at %d, status 0x%x.\n",
347 static bool fimc_check_frame_end(struct fimc_context
*ctx
)
351 cfg
= fimc_read(EXYNOS_CISTATUS
);
353 DRM_DEBUG_KMS("%s:cfg[0x%x]\n", __func__
, cfg
);
355 if (!(cfg
& EXYNOS_CISTATUS_FRAMEEND
))
358 cfg
&= ~(EXYNOS_CISTATUS_FRAMEEND
);
359 fimc_write(cfg
, EXYNOS_CISTATUS
);
364 static int fimc_get_buf_id(struct fimc_context
*ctx
)
367 int frame_cnt
, buf_id
;
369 DRM_DEBUG_KMS("%s\n", __func__
);
371 cfg
= fimc_read(EXYNOS_CISTATUS2
);
372 frame_cnt
= EXYNOS_CISTATUS2_GET_FRAMECOUNT_BEFORE(cfg
);
375 frame_cnt
= EXYNOS_CISTATUS2_GET_FRAMECOUNT_PRESENT(cfg
);
377 DRM_DEBUG_KMS("%s:present[%d]before[%d]\n", __func__
,
378 EXYNOS_CISTATUS2_GET_FRAMECOUNT_PRESENT(cfg
),
379 EXYNOS_CISTATUS2_GET_FRAMECOUNT_BEFORE(cfg
));
381 if (frame_cnt
== 0) {
382 DRM_ERROR("failed to get frame count.\n");
386 buf_id
= frame_cnt
- 1;
387 DRM_DEBUG_KMS("%s:buf_id[%d]\n", __func__
, buf_id
);
392 static void fimc_handle_lastend(struct fimc_context
*ctx
, bool enable
)
396 DRM_DEBUG_KMS("%s:enable[%d]\n", __func__
, enable
);
398 cfg
= fimc_read(EXYNOS_CIOCTRL
);
400 cfg
|= EXYNOS_CIOCTRL_LASTENDEN
;
402 cfg
&= ~EXYNOS_CIOCTRL_LASTENDEN
;
404 fimc_write(cfg
, EXYNOS_CIOCTRL
);
408 static int fimc_src_set_fmt_order(struct fimc_context
*ctx
, u32 fmt
)
410 struct exynos_drm_ippdrv
*ippdrv
= &ctx
->ippdrv
;
413 DRM_DEBUG_KMS("%s:fmt[0x%x]\n", __func__
, fmt
);
416 cfg
= fimc_read(EXYNOS_CISCCTRL
);
417 cfg
&= ~EXYNOS_CISCCTRL_INRGB_FMT_RGB_MASK
;
420 case DRM_FORMAT_RGB565
:
421 cfg
|= EXYNOS_CISCCTRL_INRGB_FMT_RGB565
;
422 fimc_write(cfg
, EXYNOS_CISCCTRL
);
424 case DRM_FORMAT_RGB888
:
425 case DRM_FORMAT_XRGB8888
:
426 cfg
|= EXYNOS_CISCCTRL_INRGB_FMT_RGB888
;
427 fimc_write(cfg
, EXYNOS_CISCCTRL
);
435 cfg
= fimc_read(EXYNOS_MSCTRL
);
436 cfg
&= ~(EXYNOS_MSCTRL_ORDER2P_SHIFT_MASK
|
437 EXYNOS_MSCTRL_C_INT_IN_2PLANE
|
438 EXYNOS_MSCTRL_ORDER422_YCBYCR
);
441 case DRM_FORMAT_YUYV
:
442 cfg
|= EXYNOS_MSCTRL_ORDER422_YCBYCR
;
444 case DRM_FORMAT_YVYU
:
445 cfg
|= EXYNOS_MSCTRL_ORDER422_YCRYCB
;
447 case DRM_FORMAT_UYVY
:
448 cfg
|= EXYNOS_MSCTRL_ORDER422_CBYCRY
;
450 case DRM_FORMAT_VYUY
:
451 case DRM_FORMAT_YUV444
:
452 cfg
|= EXYNOS_MSCTRL_ORDER422_CRYCBY
;
454 case DRM_FORMAT_NV21
:
455 case DRM_FORMAT_NV61
:
456 cfg
|= (EXYNOS_MSCTRL_ORDER2P_LSB_CRCB
|
457 EXYNOS_MSCTRL_C_INT_IN_2PLANE
);
459 case DRM_FORMAT_YUV422
:
460 case DRM_FORMAT_YUV420
:
461 case DRM_FORMAT_YVU420
:
462 cfg
|= EXYNOS_MSCTRL_C_INT_IN_3PLANE
;
464 case DRM_FORMAT_NV12
:
465 case DRM_FORMAT_NV12MT
:
466 case DRM_FORMAT_NV16
:
467 cfg
|= (EXYNOS_MSCTRL_ORDER2P_LSB_CBCR
|
468 EXYNOS_MSCTRL_C_INT_IN_2PLANE
);
471 dev_err(ippdrv
->dev
, "inavlid source yuv order 0x%x.\n", fmt
);
475 fimc_write(cfg
, EXYNOS_MSCTRL
);
480 static int fimc_src_set_fmt(struct device
*dev
, u32 fmt
)
482 struct fimc_context
*ctx
= get_fimc_context(dev
);
483 struct exynos_drm_ippdrv
*ippdrv
= &ctx
->ippdrv
;
486 DRM_DEBUG_KMS("%s:fmt[0x%x]\n", __func__
, fmt
);
488 cfg
= fimc_read(EXYNOS_MSCTRL
);
489 cfg
&= ~EXYNOS_MSCTRL_INFORMAT_RGB
;
492 case DRM_FORMAT_RGB565
:
493 case DRM_FORMAT_RGB888
:
494 case DRM_FORMAT_XRGB8888
:
495 cfg
|= EXYNOS_MSCTRL_INFORMAT_RGB
;
497 case DRM_FORMAT_YUV444
:
498 cfg
|= EXYNOS_MSCTRL_INFORMAT_YCBCR420
;
500 case DRM_FORMAT_YUYV
:
501 case DRM_FORMAT_YVYU
:
502 case DRM_FORMAT_UYVY
:
503 case DRM_FORMAT_VYUY
:
504 cfg
|= EXYNOS_MSCTRL_INFORMAT_YCBCR422_1PLANE
;
506 case DRM_FORMAT_NV16
:
507 case DRM_FORMAT_NV61
:
508 case DRM_FORMAT_YUV422
:
509 cfg
|= EXYNOS_MSCTRL_INFORMAT_YCBCR422
;
511 case DRM_FORMAT_YUV420
:
512 case DRM_FORMAT_YVU420
:
513 case DRM_FORMAT_NV12
:
514 case DRM_FORMAT_NV21
:
515 case DRM_FORMAT_NV12MT
:
516 cfg
|= EXYNOS_MSCTRL_INFORMAT_YCBCR420
;
519 dev_err(ippdrv
->dev
, "inavlid source format 0x%x.\n", fmt
);
523 fimc_write(cfg
, EXYNOS_MSCTRL
);
525 cfg
= fimc_read(EXYNOS_CIDMAPARAM
);
526 cfg
&= ~EXYNOS_CIDMAPARAM_R_MODE_MASK
;
528 if (fmt
== DRM_FORMAT_NV12MT
)
529 cfg
|= EXYNOS_CIDMAPARAM_R_MODE_64X32
;
531 cfg
|= EXYNOS_CIDMAPARAM_R_MODE_LINEAR
;
533 fimc_write(cfg
, EXYNOS_CIDMAPARAM
);
535 return fimc_src_set_fmt_order(ctx
, fmt
);
538 static int fimc_src_set_transf(struct device
*dev
,
539 enum drm_exynos_degree degree
,
540 enum drm_exynos_flip flip
, bool *swap
)
542 struct fimc_context
*ctx
= get_fimc_context(dev
);
543 struct exynos_drm_ippdrv
*ippdrv
= &ctx
->ippdrv
;
546 DRM_DEBUG_KMS("%s:degree[%d]flip[0x%x]\n", __func__
,
549 cfg1
= fimc_read(EXYNOS_MSCTRL
);
550 cfg1
&= ~(EXYNOS_MSCTRL_FLIP_X_MIRROR
|
551 EXYNOS_MSCTRL_FLIP_Y_MIRROR
);
553 cfg2
= fimc_read(EXYNOS_CITRGFMT
);
554 cfg2
&= ~EXYNOS_CITRGFMT_INROT90_CLOCKWISE
;
557 case EXYNOS_DRM_DEGREE_0
:
558 if (flip
& EXYNOS_DRM_FLIP_VERTICAL
)
559 cfg1
|= EXYNOS_MSCTRL_FLIP_X_MIRROR
;
560 if (flip
& EXYNOS_DRM_FLIP_HORIZONTAL
)
561 cfg1
|= EXYNOS_MSCTRL_FLIP_Y_MIRROR
;
563 case EXYNOS_DRM_DEGREE_90
:
564 cfg2
|= EXYNOS_CITRGFMT_INROT90_CLOCKWISE
;
565 if (flip
& EXYNOS_DRM_FLIP_VERTICAL
)
566 cfg1
|= EXYNOS_MSCTRL_FLIP_X_MIRROR
;
567 if (flip
& EXYNOS_DRM_FLIP_HORIZONTAL
)
568 cfg1
|= EXYNOS_MSCTRL_FLIP_Y_MIRROR
;
570 case EXYNOS_DRM_DEGREE_180
:
571 cfg1
|= (EXYNOS_MSCTRL_FLIP_X_MIRROR
|
572 EXYNOS_MSCTRL_FLIP_Y_MIRROR
);
573 if (flip
& EXYNOS_DRM_FLIP_VERTICAL
)
574 cfg1
&= ~EXYNOS_MSCTRL_FLIP_X_MIRROR
;
575 if (flip
& EXYNOS_DRM_FLIP_HORIZONTAL
)
576 cfg1
&= ~EXYNOS_MSCTRL_FLIP_Y_MIRROR
;
578 case EXYNOS_DRM_DEGREE_270
:
579 cfg1
|= (EXYNOS_MSCTRL_FLIP_X_MIRROR
|
580 EXYNOS_MSCTRL_FLIP_Y_MIRROR
);
581 cfg2
|= EXYNOS_CITRGFMT_INROT90_CLOCKWISE
;
582 if (flip
& EXYNOS_DRM_FLIP_VERTICAL
)
583 cfg1
&= ~EXYNOS_MSCTRL_FLIP_X_MIRROR
;
584 if (flip
& EXYNOS_DRM_FLIP_HORIZONTAL
)
585 cfg1
&= ~EXYNOS_MSCTRL_FLIP_Y_MIRROR
;
588 dev_err(ippdrv
->dev
, "inavlid degree value %d.\n", degree
);
592 fimc_write(cfg1
, EXYNOS_MSCTRL
);
593 fimc_write(cfg2
, EXYNOS_CITRGFMT
);
594 *swap
= (cfg2
& EXYNOS_CITRGFMT_INROT90_CLOCKWISE
) ? 1 : 0;
599 static int fimc_set_window(struct fimc_context
*ctx
,
600 struct drm_exynos_pos
*pos
, struct drm_exynos_sz
*sz
)
602 u32 cfg
, h1
, h2
, v1
, v2
;
606 h2
= sz
->hsize
- pos
->w
- pos
->x
;
608 v2
= sz
->vsize
- pos
->h
- pos
->y
;
610 DRM_DEBUG_KMS("%s:x[%d]y[%d]w[%d]h[%d]hsize[%d]vsize[%d]\n",
611 __func__
, pos
->x
, pos
->y
, pos
->w
, pos
->h
, sz
->hsize
, sz
->vsize
);
612 DRM_DEBUG_KMS("%s:h1[%d]h2[%d]v1[%d]v2[%d]\n", __func__
,
616 * set window offset 1, 2 size
617 * check figure 43-21 in user manual
619 cfg
= fimc_read(EXYNOS_CIWDOFST
);
620 cfg
&= ~(EXYNOS_CIWDOFST_WINHOROFST_MASK
|
621 EXYNOS_CIWDOFST_WINVEROFST_MASK
);
622 cfg
|= (EXYNOS_CIWDOFST_WINHOROFST(h1
) |
623 EXYNOS_CIWDOFST_WINVEROFST(v1
));
624 cfg
|= EXYNOS_CIWDOFST_WINOFSEN
;
625 fimc_write(cfg
, EXYNOS_CIWDOFST
);
627 cfg
= (EXYNOS_CIWDOFST2_WINHOROFST2(h2
) |
628 EXYNOS_CIWDOFST2_WINVEROFST2(v2
));
629 fimc_write(cfg
, EXYNOS_CIWDOFST2
);
634 static int fimc_src_set_size(struct device
*dev
, int swap
,
635 struct drm_exynos_pos
*pos
, struct drm_exynos_sz
*sz
)
637 struct fimc_context
*ctx
= get_fimc_context(dev
);
638 struct drm_exynos_pos img_pos
= *pos
;
639 struct drm_exynos_sz img_sz
= *sz
;
642 DRM_DEBUG_KMS("%s:swap[%d]hsize[%d]vsize[%d]\n",
643 __func__
, swap
, sz
->hsize
, sz
->vsize
);
646 cfg
= (EXYNOS_ORGISIZE_HORIZONTAL(img_sz
.hsize
) |
647 EXYNOS_ORGISIZE_VERTICAL(img_sz
.vsize
));
649 fimc_write(cfg
, EXYNOS_ORGISIZE
);
651 DRM_DEBUG_KMS("%s:x[%d]y[%d]w[%d]h[%d]\n", __func__
,
652 pos
->x
, pos
->y
, pos
->w
, pos
->h
);
657 img_sz
.hsize
= sz
->vsize
;
658 img_sz
.vsize
= sz
->hsize
;
661 /* set input DMA image size */
662 cfg
= fimc_read(EXYNOS_CIREAL_ISIZE
);
663 cfg
&= ~(EXYNOS_CIREAL_ISIZE_HEIGHT_MASK
|
664 EXYNOS_CIREAL_ISIZE_WIDTH_MASK
);
665 cfg
|= (EXYNOS_CIREAL_ISIZE_WIDTH(img_pos
.w
) |
666 EXYNOS_CIREAL_ISIZE_HEIGHT(img_pos
.h
));
667 fimc_write(cfg
, EXYNOS_CIREAL_ISIZE
);
670 * set input FIFO image size
671 * for now, we support only ITU601 8 bit mode
673 cfg
= (EXYNOS_CISRCFMT_ITU601_8BIT
|
674 EXYNOS_CISRCFMT_SOURCEHSIZE(img_sz
.hsize
) |
675 EXYNOS_CISRCFMT_SOURCEVSIZE(img_sz
.vsize
));
676 fimc_write(cfg
, EXYNOS_CISRCFMT
);
678 /* offset Y(RGB), Cb, Cr */
679 cfg
= (EXYNOS_CIIYOFF_HORIZONTAL(img_pos
.x
) |
680 EXYNOS_CIIYOFF_VERTICAL(img_pos
.y
));
681 fimc_write(cfg
, EXYNOS_CIIYOFF
);
682 cfg
= (EXYNOS_CIICBOFF_HORIZONTAL(img_pos
.x
) |
683 EXYNOS_CIICBOFF_VERTICAL(img_pos
.y
));
684 fimc_write(cfg
, EXYNOS_CIICBOFF
);
685 cfg
= (EXYNOS_CIICROFF_HORIZONTAL(img_pos
.x
) |
686 EXYNOS_CIICROFF_VERTICAL(img_pos
.y
));
687 fimc_write(cfg
, EXYNOS_CIICROFF
);
689 return fimc_set_window(ctx
, &img_pos
, &img_sz
);
692 static int fimc_src_set_addr(struct device
*dev
,
693 struct drm_exynos_ipp_buf_info
*buf_info
, u32 buf_id
,
694 enum drm_exynos_ipp_buf_type buf_type
)
696 struct fimc_context
*ctx
= get_fimc_context(dev
);
697 struct exynos_drm_ippdrv
*ippdrv
= &ctx
->ippdrv
;
698 struct drm_exynos_ipp_cmd_node
*c_node
= ippdrv
->cmd
;
699 struct drm_exynos_ipp_property
*property
;
700 struct drm_exynos_ipp_config
*config
;
703 DRM_ERROR("failed to get c_node.\n");
707 property
= &c_node
->property
;
709 DRM_ERROR("failed to get property.\n");
713 DRM_DEBUG_KMS("%s:prop_id[%d]buf_id[%d]buf_type[%d]\n", __func__
,
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("%s:fmt[0x%x]\n", __func__
, 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("%s:fmt[0x%x]\n", __func__
, 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("%s:degree[%d]flip[0x%x]\n", __func__
,
915 cfg
= fimc_read(EXYNOS_CITRGFMT
);
916 cfg
&= ~EXYNOS_CITRGFMT_FLIP_MASK
;
917 cfg
&= ~EXYNOS_CITRGFMT_OUTROT90_CLOCKWISE
;
920 case EXYNOS_DRM_DEGREE_0
:
921 if (flip
& EXYNOS_DRM_FLIP_VERTICAL
)
922 cfg
|= EXYNOS_CITRGFMT_FLIP_X_MIRROR
;
923 if (flip
& EXYNOS_DRM_FLIP_HORIZONTAL
)
924 cfg
|= EXYNOS_CITRGFMT_FLIP_Y_MIRROR
;
926 case EXYNOS_DRM_DEGREE_90
:
927 cfg
|= EXYNOS_CITRGFMT_OUTROT90_CLOCKWISE
;
928 if (flip
& EXYNOS_DRM_FLIP_VERTICAL
)
929 cfg
|= EXYNOS_CITRGFMT_FLIP_X_MIRROR
;
930 if (flip
& EXYNOS_DRM_FLIP_HORIZONTAL
)
931 cfg
|= EXYNOS_CITRGFMT_FLIP_Y_MIRROR
;
933 case EXYNOS_DRM_DEGREE_180
:
934 cfg
|= (EXYNOS_CITRGFMT_FLIP_X_MIRROR
|
935 EXYNOS_CITRGFMT_FLIP_Y_MIRROR
);
936 if (flip
& EXYNOS_DRM_FLIP_VERTICAL
)
937 cfg
&= ~EXYNOS_CITRGFMT_FLIP_X_MIRROR
;
938 if (flip
& EXYNOS_DRM_FLIP_HORIZONTAL
)
939 cfg
&= ~EXYNOS_CITRGFMT_FLIP_Y_MIRROR
;
941 case EXYNOS_DRM_DEGREE_270
:
942 cfg
|= (EXYNOS_CITRGFMT_OUTROT90_CLOCKWISE
|
943 EXYNOS_CITRGFMT_FLIP_X_MIRROR
|
944 EXYNOS_CITRGFMT_FLIP_Y_MIRROR
);
945 if (flip
& EXYNOS_DRM_FLIP_VERTICAL
)
946 cfg
&= ~EXYNOS_CITRGFMT_FLIP_X_MIRROR
;
947 if (flip
& EXYNOS_DRM_FLIP_HORIZONTAL
)
948 cfg
&= ~EXYNOS_CITRGFMT_FLIP_Y_MIRROR
;
951 dev_err(ippdrv
->dev
, "inavlid degree value %d.\n", degree
);
955 fimc_write(cfg
, EXYNOS_CITRGFMT
);
956 *swap
= (cfg
& EXYNOS_CITRGFMT_OUTROT90_CLOCKWISE
) ? 1 : 0;
961 static int fimc_get_ratio_shift(u32 src
, u32 dst
, u32
*ratio
, u32
*shift
)
963 DRM_DEBUG_KMS("%s:src[%d]dst[%d]\n", __func__
, src
, dst
);
965 if (src
>= dst
* 64) {
966 DRM_ERROR("failed to make ratio and shift.\n");
968 } else if (src
>= dst
* 32) {
971 } else if (src
>= dst
* 16) {
974 } else if (src
>= dst
* 8) {
977 } else if (src
>= dst
* 4) {
980 } else if (src
>= dst
* 2) {
991 static int fimc_set_prescaler(struct fimc_context
*ctx
, struct fimc_scaler
*sc
,
992 struct drm_exynos_pos
*src
, struct drm_exynos_pos
*dst
)
994 struct exynos_drm_ippdrv
*ippdrv
= &ctx
->ippdrv
;
995 u32 cfg
, cfg_ext
, shfactor
;
996 u32 pre_dst_width
, pre_dst_height
;
997 u32 pre_hratio
, hfactor
, pre_vratio
, vfactor
;
999 u32 src_w
, src_h
, dst_w
, dst_h
;
1001 cfg_ext
= fimc_read(EXYNOS_CITRGFMT
);
1002 if (cfg_ext
& EXYNOS_CITRGFMT_INROT90_CLOCKWISE
) {
1010 if (cfg_ext
& EXYNOS_CITRGFMT_OUTROT90_CLOCKWISE
) {
1018 ret
= fimc_get_ratio_shift(src_w
, dst_w
, &pre_hratio
, &hfactor
);
1020 dev_err(ippdrv
->dev
, "failed to get ratio horizontal.\n");
1024 ret
= fimc_get_ratio_shift(src_h
, dst_h
, &pre_vratio
, &vfactor
);
1026 dev_err(ippdrv
->dev
, "failed to get ratio vertical.\n");
1030 pre_dst_width
= src_w
/ pre_hratio
;
1031 pre_dst_height
= src_h
/ pre_vratio
;
1032 DRM_DEBUG_KMS("%s:pre_dst_width[%d]pre_dst_height[%d]\n", __func__
,
1033 pre_dst_width
, pre_dst_height
);
1034 DRM_DEBUG_KMS("%s:pre_hratio[%d]hfactor[%d]pre_vratio[%d]vfactor[%d]\n",
1035 __func__
, pre_hratio
, hfactor
, pre_vratio
, vfactor
);
1037 sc
->hratio
= (src_w
<< 14) / (dst_w
<< hfactor
);
1038 sc
->vratio
= (src_h
<< 14) / (dst_h
<< vfactor
);
1039 sc
->up_h
= (dst_w
>= src_w
) ? true : false;
1040 sc
->up_v
= (dst_h
>= src_h
) ? true : false;
1041 DRM_DEBUG_KMS("%s:hratio[%d]vratio[%d]up_h[%d]up_v[%d]\n",
1042 __func__
, sc
->hratio
, sc
->vratio
, sc
->up_h
, sc
->up_v
);
1044 shfactor
= FIMC_SHFACTOR
- (hfactor
+ vfactor
);
1045 DRM_DEBUG_KMS("%s:shfactor[%d]\n", __func__
, shfactor
);
1047 cfg
= (EXYNOS_CISCPRERATIO_SHFACTOR(shfactor
) |
1048 EXYNOS_CISCPRERATIO_PREHORRATIO(pre_hratio
) |
1049 EXYNOS_CISCPRERATIO_PREVERRATIO(pre_vratio
));
1050 fimc_write(cfg
, EXYNOS_CISCPRERATIO
);
1052 cfg
= (EXYNOS_CISCPREDST_PREDSTWIDTH(pre_dst_width
) |
1053 EXYNOS_CISCPREDST_PREDSTHEIGHT(pre_dst_height
));
1054 fimc_write(cfg
, EXYNOS_CISCPREDST
);
1059 static void fimc_set_scaler(struct fimc_context
*ctx
, struct fimc_scaler
*sc
)
1063 DRM_DEBUG_KMS("%s:range[%d]bypass[%d]up_h[%d]up_v[%d]\n",
1064 __func__
, sc
->range
, sc
->bypass
, sc
->up_h
, sc
->up_v
);
1065 DRM_DEBUG_KMS("%s:hratio[%d]vratio[%d]\n",
1066 __func__
, sc
->hratio
, sc
->vratio
);
1068 cfg
= fimc_read(EXYNOS_CISCCTRL
);
1069 cfg
&= ~(EXYNOS_CISCCTRL_SCALERBYPASS
|
1070 EXYNOS_CISCCTRL_SCALEUP_H
| EXYNOS_CISCCTRL_SCALEUP_V
|
1071 EXYNOS_CISCCTRL_MAIN_V_RATIO_MASK
|
1072 EXYNOS_CISCCTRL_MAIN_H_RATIO_MASK
|
1073 EXYNOS_CISCCTRL_CSCR2Y_WIDE
|
1074 EXYNOS_CISCCTRL_CSCY2R_WIDE
);
1077 cfg
|= (EXYNOS_CISCCTRL_CSCR2Y_WIDE
|
1078 EXYNOS_CISCCTRL_CSCY2R_WIDE
);
1080 cfg
|= EXYNOS_CISCCTRL_SCALERBYPASS
;
1082 cfg
|= EXYNOS_CISCCTRL_SCALEUP_H
;
1084 cfg
|= EXYNOS_CISCCTRL_SCALEUP_V
;
1086 cfg
|= (EXYNOS_CISCCTRL_MAINHORRATIO((sc
->hratio
>> 6)) |
1087 EXYNOS_CISCCTRL_MAINVERRATIO((sc
->vratio
>> 6)));
1088 fimc_write(cfg
, EXYNOS_CISCCTRL
);
1090 cfg_ext
= fimc_read(EXYNOS_CIEXTEN
);
1091 cfg_ext
&= ~EXYNOS_CIEXTEN_MAINHORRATIO_EXT_MASK
;
1092 cfg_ext
&= ~EXYNOS_CIEXTEN_MAINVERRATIO_EXT_MASK
;
1093 cfg_ext
|= (EXYNOS_CIEXTEN_MAINHORRATIO_EXT(sc
->hratio
) |
1094 EXYNOS_CIEXTEN_MAINVERRATIO_EXT(sc
->vratio
));
1095 fimc_write(cfg_ext
, EXYNOS_CIEXTEN
);
1098 static int fimc_dst_set_size(struct device
*dev
, int swap
,
1099 struct drm_exynos_pos
*pos
, struct drm_exynos_sz
*sz
)
1101 struct fimc_context
*ctx
= get_fimc_context(dev
);
1102 struct drm_exynos_pos img_pos
= *pos
;
1103 struct drm_exynos_sz img_sz
= *sz
;
1106 DRM_DEBUG_KMS("%s:swap[%d]hsize[%d]vsize[%d]\n",
1107 __func__
, swap
, sz
->hsize
, sz
->vsize
);
1110 cfg
= (EXYNOS_ORGOSIZE_HORIZONTAL(img_sz
.hsize
) |
1111 EXYNOS_ORGOSIZE_VERTICAL(img_sz
.vsize
));
1113 fimc_write(cfg
, EXYNOS_ORGOSIZE
);
1115 DRM_DEBUG_KMS("%s:x[%d]y[%d]w[%d]h[%d]\n",
1116 __func__
, pos
->x
, pos
->y
, pos
->w
, pos
->h
);
1119 cfg
= fimc_read(EXYNOS_CIGCTRL
);
1120 cfg
&= ~EXYNOS_CIGCTRL_CSC_MASK
;
1122 if (sz
->hsize
>= FIMC_WIDTH_ITU_709
)
1123 cfg
|= EXYNOS_CIGCTRL_CSC_ITU709
;
1125 cfg
|= EXYNOS_CIGCTRL_CSC_ITU601
;
1127 fimc_write(cfg
, EXYNOS_CIGCTRL
);
1132 img_sz
.hsize
= sz
->vsize
;
1133 img_sz
.vsize
= sz
->hsize
;
1136 /* target image size */
1137 cfg
= fimc_read(EXYNOS_CITRGFMT
);
1138 cfg
&= ~(EXYNOS_CITRGFMT_TARGETH_MASK
|
1139 EXYNOS_CITRGFMT_TARGETV_MASK
);
1140 cfg
|= (EXYNOS_CITRGFMT_TARGETHSIZE(img_pos
.w
) |
1141 EXYNOS_CITRGFMT_TARGETVSIZE(img_pos
.h
));
1142 fimc_write(cfg
, EXYNOS_CITRGFMT
);
1145 cfg
= EXYNOS_CITAREA_TARGET_AREA(img_pos
.w
* img_pos
.h
);
1146 fimc_write(cfg
, EXYNOS_CITAREA
);
1148 /* offset Y(RGB), Cb, Cr */
1149 cfg
= (EXYNOS_CIOYOFF_HORIZONTAL(img_pos
.x
) |
1150 EXYNOS_CIOYOFF_VERTICAL(img_pos
.y
));
1151 fimc_write(cfg
, EXYNOS_CIOYOFF
);
1152 cfg
= (EXYNOS_CIOCBOFF_HORIZONTAL(img_pos
.x
) |
1153 EXYNOS_CIOCBOFF_VERTICAL(img_pos
.y
));
1154 fimc_write(cfg
, EXYNOS_CIOCBOFF
);
1155 cfg
= (EXYNOS_CIOCROFF_HORIZONTAL(img_pos
.x
) |
1156 EXYNOS_CIOCROFF_VERTICAL(img_pos
.y
));
1157 fimc_write(cfg
, EXYNOS_CIOCROFF
);
1162 static int fimc_dst_get_buf_seq(struct fimc_context
*ctx
)
1164 u32 cfg
, i
, buf_num
= 0;
1165 u32 mask
= 0x00000001;
1167 cfg
= fimc_read(EXYNOS_CIFCNTSEQ
);
1169 for (i
= 0; i
< FIMC_REG_SZ
; i
++)
1170 if (cfg
& (mask
<< i
))
1173 DRM_DEBUG_KMS("%s:buf_num[%d]\n", __func__
, buf_num
);
1178 static int fimc_dst_set_buf_seq(struct fimc_context
*ctx
, u32 buf_id
,
1179 enum drm_exynos_ipp_buf_type buf_type
)
1181 struct exynos_drm_ippdrv
*ippdrv
= &ctx
->ippdrv
;
1184 u32 mask
= 0x00000001 << buf_id
;
1187 DRM_DEBUG_KMS("%s:buf_id[%d]buf_type[%d]\n", __func__
,
1190 mutex_lock(&ctx
->lock
);
1192 /* mask register set */
1193 cfg
= fimc_read(EXYNOS_CIFCNTSEQ
);
1196 case IPP_BUF_ENQUEUE
:
1199 case IPP_BUF_DEQUEUE
:
1203 dev_err(ippdrv
->dev
, "invalid buf ctrl parameter.\n");
1210 cfg
|= (enable
<< buf_id
);
1211 fimc_write(cfg
, EXYNOS_CIFCNTSEQ
);
1213 /* interrupt enable */
1214 if (buf_type
== IPP_BUF_ENQUEUE
&&
1215 fimc_dst_get_buf_seq(ctx
) >= FIMC_BUF_START
)
1216 fimc_handle_irq(ctx
, true, false, true);
1218 /* interrupt disable */
1219 if (buf_type
== IPP_BUF_DEQUEUE
&&
1220 fimc_dst_get_buf_seq(ctx
) <= FIMC_BUF_STOP
)
1221 fimc_handle_irq(ctx
, false, false, true);
1224 mutex_unlock(&ctx
->lock
);
1228 static int fimc_dst_set_addr(struct device
*dev
,
1229 struct drm_exynos_ipp_buf_info
*buf_info
, u32 buf_id
,
1230 enum drm_exynos_ipp_buf_type buf_type
)
1232 struct fimc_context
*ctx
= get_fimc_context(dev
);
1233 struct exynos_drm_ippdrv
*ippdrv
= &ctx
->ippdrv
;
1234 struct drm_exynos_ipp_cmd_node
*c_node
= ippdrv
->cmd
;
1235 struct drm_exynos_ipp_property
*property
;
1236 struct drm_exynos_ipp_config
*config
;
1239 DRM_ERROR("failed to get c_node.\n");
1243 property
= &c_node
->property
;
1245 DRM_ERROR("failed to get property.\n");
1249 DRM_DEBUG_KMS("%s:prop_id[%d]buf_id[%d]buf_type[%d]\n", __func__
,
1250 property
->prop_id
, buf_id
, buf_type
);
1252 if (buf_id
> FIMC_MAX_DST
) {
1253 dev_info(ippdrv
->dev
, "inavlid buf_id %d.\n", buf_id
);
1257 /* address register set */
1259 case IPP_BUF_ENQUEUE
:
1260 config
= &property
->config
[EXYNOS_DRM_OPS_DST
];
1262 fimc_write(buf_info
->base
[EXYNOS_DRM_PLANAR_Y
],
1263 EXYNOS_CIOYSA(buf_id
));
1265 if (config
->fmt
== DRM_FORMAT_YVU420
) {
1266 fimc_write(buf_info
->base
[EXYNOS_DRM_PLANAR_CR
],
1267 EXYNOS_CIOCBSA(buf_id
));
1268 fimc_write(buf_info
->base
[EXYNOS_DRM_PLANAR_CB
],
1269 EXYNOS_CIOCRSA(buf_id
));
1271 fimc_write(buf_info
->base
[EXYNOS_DRM_PLANAR_CB
],
1272 EXYNOS_CIOCBSA(buf_id
));
1273 fimc_write(buf_info
->base
[EXYNOS_DRM_PLANAR_CR
],
1274 EXYNOS_CIOCRSA(buf_id
));
1277 case IPP_BUF_DEQUEUE
:
1278 fimc_write(0x0, EXYNOS_CIOYSA(buf_id
));
1279 fimc_write(0x0, EXYNOS_CIOCBSA(buf_id
));
1280 fimc_write(0x0, EXYNOS_CIOCRSA(buf_id
));
1287 return fimc_dst_set_buf_seq(ctx
, buf_id
, buf_type
);
1290 static struct exynos_drm_ipp_ops fimc_dst_ops
= {
1291 .set_fmt
= fimc_dst_set_fmt
,
1292 .set_transf
= fimc_dst_set_transf
,
1293 .set_size
= fimc_dst_set_size
,
1294 .set_addr
= fimc_dst_set_addr
,
1297 static int fimc_clk_ctrl(struct fimc_context
*ctx
, bool enable
)
1299 DRM_DEBUG_KMS("%s:enable[%d]\n", __func__
, enable
);
1302 clk_enable(ctx
->sclk_fimc_clk
);
1303 clk_enable(ctx
->fimc_clk
);
1304 clk_enable(ctx
->wb_clk
);
1305 ctx
->suspended
= false;
1307 clk_disable(ctx
->sclk_fimc_clk
);
1308 clk_disable(ctx
->fimc_clk
);
1309 clk_disable(ctx
->wb_clk
);
1310 ctx
->suspended
= true;
1316 static irqreturn_t
fimc_irq_handler(int irq
, void *dev_id
)
1318 struct fimc_context
*ctx
= dev_id
;
1319 struct exynos_drm_ippdrv
*ippdrv
= &ctx
->ippdrv
;
1320 struct drm_exynos_ipp_cmd_node
*c_node
= ippdrv
->cmd
;
1321 struct drm_exynos_ipp_event_work
*event_work
=
1325 DRM_DEBUG_KMS("%s:fimc id[%d]\n", __func__
, ctx
->id
);
1327 fimc_clear_irq(ctx
);
1328 if (fimc_check_ovf(ctx
))
1331 if (!fimc_check_frame_end(ctx
))
1334 buf_id
= fimc_get_buf_id(ctx
);
1338 DRM_DEBUG_KMS("%s:buf_id[%d]\n", __func__
, buf_id
);
1340 if (fimc_dst_set_buf_seq(ctx
, buf_id
, IPP_BUF_DEQUEUE
) < 0) {
1341 DRM_ERROR("failed to dequeue.\n");
1345 event_work
->ippdrv
= ippdrv
;
1346 event_work
->buf_id
[EXYNOS_DRM_OPS_DST
] = buf_id
;
1347 queue_work(ippdrv
->event_workq
, (struct work_struct
*)event_work
);
1352 static int fimc_init_prop_list(struct exynos_drm_ippdrv
*ippdrv
)
1354 struct drm_exynos_ipp_prop_list
*prop_list
;
1356 DRM_DEBUG_KMS("%s\n", __func__
);
1358 prop_list
= devm_kzalloc(ippdrv
->dev
, sizeof(*prop_list
), GFP_KERNEL
);
1360 DRM_ERROR("failed to alloc property list.\n");
1364 prop_list
->version
= 1;
1365 prop_list
->writeback
= 1;
1366 prop_list
->refresh_min
= FIMC_REFRESH_MIN
;
1367 prop_list
->refresh_max
= FIMC_REFRESH_MAX
;
1368 prop_list
->flip
= (1 << EXYNOS_DRM_FLIP_NONE
) |
1369 (1 << EXYNOS_DRM_FLIP_VERTICAL
) |
1370 (1 << EXYNOS_DRM_FLIP_HORIZONTAL
);
1371 prop_list
->degree
= (1 << EXYNOS_DRM_DEGREE_0
) |
1372 (1 << EXYNOS_DRM_DEGREE_90
) |
1373 (1 << EXYNOS_DRM_DEGREE_180
) |
1374 (1 << EXYNOS_DRM_DEGREE_270
);
1376 prop_list
->crop
= 1;
1377 prop_list
->crop_max
.hsize
= FIMC_CROP_MAX
;
1378 prop_list
->crop_max
.vsize
= FIMC_CROP_MAX
;
1379 prop_list
->crop_min
.hsize
= FIMC_CROP_MIN
;
1380 prop_list
->crop_min
.vsize
= FIMC_CROP_MIN
;
1381 prop_list
->scale
= 1;
1382 prop_list
->scale_max
.hsize
= FIMC_SCALE_MAX
;
1383 prop_list
->scale_max
.vsize
= FIMC_SCALE_MAX
;
1384 prop_list
->scale_min
.hsize
= FIMC_SCALE_MIN
;
1385 prop_list
->scale_min
.vsize
= FIMC_SCALE_MIN
;
1387 ippdrv
->prop_list
= prop_list
;
1392 static inline bool fimc_check_drm_flip(enum drm_exynos_flip flip
)
1395 case EXYNOS_DRM_FLIP_NONE
:
1396 case EXYNOS_DRM_FLIP_VERTICAL
:
1397 case EXYNOS_DRM_FLIP_HORIZONTAL
:
1400 DRM_DEBUG_KMS("%s:invalid flip\n", __func__
);
1405 static int fimc_ippdrv_check_property(struct device
*dev
,
1406 struct drm_exynos_ipp_property
*property
)
1408 struct fimc_context
*ctx
= get_fimc_context(dev
);
1409 struct exynos_drm_ippdrv
*ippdrv
= &ctx
->ippdrv
;
1410 struct drm_exynos_ipp_prop_list
*pp
= ippdrv
->prop_list
;
1411 struct drm_exynos_ipp_config
*config
;
1412 struct drm_exynos_pos
*pos
;
1413 struct drm_exynos_sz
*sz
;
1417 DRM_DEBUG_KMS("%s\n", __func__
);
1419 for_each_ipp_ops(i
) {
1420 if ((i
== EXYNOS_DRM_OPS_SRC
) &&
1421 (property
->cmd
== IPP_CMD_WB
))
1424 config
= &property
->config
[i
];
1428 /* check for flip */
1429 if (!fimc_check_drm_flip(config
->flip
)) {
1430 DRM_ERROR("invalid flip.\n");
1434 /* check for degree */
1435 switch (config
->degree
) {
1436 case EXYNOS_DRM_DEGREE_90
:
1437 case EXYNOS_DRM_DEGREE_270
:
1440 case EXYNOS_DRM_DEGREE_0
:
1441 case EXYNOS_DRM_DEGREE_180
:
1445 DRM_ERROR("invalid degree.\n");
1449 /* check for buffer bound */
1450 if ((pos
->x
+ pos
->w
> sz
->hsize
) ||
1451 (pos
->y
+ pos
->h
> sz
->vsize
)) {
1452 DRM_ERROR("out of buf bound.\n");
1456 /* check for crop */
1457 if ((i
== EXYNOS_DRM_OPS_SRC
) && (pp
->crop
)) {
1459 if ((pos
->h
< pp
->crop_min
.hsize
) ||
1460 (sz
->vsize
> pp
->crop_max
.hsize
) ||
1461 (pos
->w
< pp
->crop_min
.vsize
) ||
1462 (sz
->hsize
> pp
->crop_max
.vsize
)) {
1463 DRM_ERROR("out of crop size.\n");
1467 if ((pos
->w
< pp
->crop_min
.hsize
) ||
1468 (sz
->hsize
> pp
->crop_max
.hsize
) ||
1469 (pos
->h
< pp
->crop_min
.vsize
) ||
1470 (sz
->vsize
> pp
->crop_max
.vsize
)) {
1471 DRM_ERROR("out of crop size.\n");
1477 /* check for scale */
1478 if ((i
== EXYNOS_DRM_OPS_DST
) && (pp
->scale
)) {
1480 if ((pos
->h
< pp
->scale_min
.hsize
) ||
1481 (sz
->vsize
> pp
->scale_max
.hsize
) ||
1482 (pos
->w
< pp
->scale_min
.vsize
) ||
1483 (sz
->hsize
> pp
->scale_max
.vsize
)) {
1484 DRM_ERROR("out of scale size.\n");
1488 if ((pos
->w
< pp
->scale_min
.hsize
) ||
1489 (sz
->hsize
> pp
->scale_max
.hsize
) ||
1490 (pos
->h
< pp
->scale_min
.vsize
) ||
1491 (sz
->vsize
> pp
->scale_max
.vsize
)) {
1492 DRM_ERROR("out of scale size.\n");
1502 for_each_ipp_ops(i
) {
1503 if ((i
== EXYNOS_DRM_OPS_SRC
) &&
1504 (property
->cmd
== IPP_CMD_WB
))
1507 config
= &property
->config
[i
];
1511 DRM_ERROR("[%s]f[%d]r[%d]pos[%d %d %d %d]sz[%d %d]\n",
1512 i
? "dst" : "src", config
->flip
, config
->degree
,
1513 pos
->x
, pos
->y
, pos
->w
, pos
->h
,
1514 sz
->hsize
, sz
->vsize
);
1520 static void fimc_clear_addr(struct fimc_context
*ctx
)
1524 DRM_DEBUG_KMS("%s:\n", __func__
);
1526 for (i
= 0; i
< FIMC_MAX_SRC
; i
++) {
1527 fimc_write(0, EXYNOS_CIIYSA(i
));
1528 fimc_write(0, EXYNOS_CIICBSA(i
));
1529 fimc_write(0, EXYNOS_CIICRSA(i
));
1532 for (i
= 0; i
< FIMC_MAX_DST
; i
++) {
1533 fimc_write(0, EXYNOS_CIOYSA(i
));
1534 fimc_write(0, EXYNOS_CIOCBSA(i
));
1535 fimc_write(0, EXYNOS_CIOCRSA(i
));
1539 static int fimc_ippdrv_reset(struct device
*dev
)
1541 struct fimc_context
*ctx
= get_fimc_context(dev
);
1543 DRM_DEBUG_KMS("%s\n", __func__
);
1545 /* reset h/w block */
1546 fimc_sw_reset(ctx
, false);
1548 /* reset scaler capability */
1549 memset(&ctx
->sc
, 0x0, sizeof(ctx
->sc
));
1551 fimc_clear_addr(ctx
);
1556 static int fimc_ippdrv_start(struct device
*dev
, enum drm_exynos_ipp_cmd cmd
)
1558 struct fimc_context
*ctx
= get_fimc_context(dev
);
1559 struct exynos_drm_ippdrv
*ippdrv
= &ctx
->ippdrv
;
1560 struct drm_exynos_ipp_cmd_node
*c_node
= ippdrv
->cmd
;
1561 struct drm_exynos_ipp_property
*property
;
1562 struct drm_exynos_ipp_config
*config
;
1563 struct drm_exynos_pos img_pos
[EXYNOS_DRM_OPS_MAX
];
1564 struct drm_exynos_ipp_set_wb set_wb
;
1568 DRM_DEBUG_KMS("%s:cmd[%d]\n", __func__
, cmd
);
1571 DRM_ERROR("failed to get c_node.\n");
1575 property
= &c_node
->property
;
1577 DRM_ERROR("failed to get property.\n");
1581 fimc_handle_irq(ctx
, true, false, true);
1583 for_each_ipp_ops(i
) {
1584 config
= &property
->config
[i
];
1585 img_pos
[i
] = config
->pos
;
1588 ret
= fimc_set_prescaler(ctx
, &ctx
->sc
,
1589 &img_pos
[EXYNOS_DRM_OPS_SRC
],
1590 &img_pos
[EXYNOS_DRM_OPS_DST
]);
1592 dev_err(dev
, "failed to set precalser.\n");
1596 /* If set ture, we can save jpeg about screen */
1597 fimc_handle_jpeg(ctx
, false);
1598 fimc_set_scaler(ctx
, &ctx
->sc
);
1599 fimc_set_polarity(ctx
, &ctx
->pol
);
1603 fimc_set_type_ctrl(ctx
, FIMC_WB_NONE
);
1604 fimc_handle_lastend(ctx
, false);
1607 cfg0
= fimc_read(EXYNOS_MSCTRL
);
1608 cfg0
&= ~EXYNOS_MSCTRL_INPUT_MASK
;
1609 cfg0
|= EXYNOS_MSCTRL_INPUT_MEMORY
;
1610 fimc_write(cfg0
, EXYNOS_MSCTRL
);
1613 fimc_set_type_ctrl(ctx
, FIMC_WB_A
);
1614 fimc_handle_lastend(ctx
, true);
1617 fimc_set_camblk_fimd0_wb(ctx
);
1620 set_wb
.refresh
= property
->refresh_rate
;
1621 exynos_drm_ippnb_send_event(IPP_SET_WRITEBACK
, (void *)&set_wb
);
1623 case IPP_CMD_OUTPUT
:
1626 dev_err(dev
, "invalid operations.\n");
1631 fimc_write(0x0, EXYNOS_CISTATUS
);
1633 cfg0
= fimc_read(EXYNOS_CIIMGCPT
);
1634 cfg0
&= ~EXYNOS_CIIMGCPT_IMGCPTEN_SC
;
1635 cfg0
|= EXYNOS_CIIMGCPT_IMGCPTEN_SC
;
1638 cfg1
= fimc_read(EXYNOS_CISCCTRL
);
1639 cfg1
&= ~EXYNOS_CISCCTRL_SCAN_MASK
;
1640 cfg1
|= (EXYNOS_CISCCTRL_PROGRESSIVE
|
1641 EXYNOS_CISCCTRL_SCALERSTART
);
1643 fimc_write(cfg1
, EXYNOS_CISCCTRL
);
1645 /* Enable image capture*/
1646 cfg0
|= EXYNOS_CIIMGCPT_IMGCPTEN
;
1647 fimc_write(cfg0
, EXYNOS_CIIMGCPT
);
1649 /* Disable frame end irq */
1650 cfg0
= fimc_read(EXYNOS_CIGCTRL
);
1651 cfg0
&= ~EXYNOS_CIGCTRL_IRQ_END_DISABLE
;
1652 fimc_write(cfg0
, EXYNOS_CIGCTRL
);
1654 cfg0
= fimc_read(EXYNOS_CIOCTRL
);
1655 cfg0
&= ~EXYNOS_CIOCTRL_WEAVE_MASK
;
1656 fimc_write(cfg0
, EXYNOS_CIOCTRL
);
1658 if (cmd
== IPP_CMD_M2M
) {
1659 cfg0
= fimc_read(EXYNOS_MSCTRL
);
1660 cfg0
|= EXYNOS_MSCTRL_ENVID
;
1661 fimc_write(cfg0
, EXYNOS_MSCTRL
);
1663 cfg0
= fimc_read(EXYNOS_MSCTRL
);
1664 cfg0
|= EXYNOS_MSCTRL_ENVID
;
1665 fimc_write(cfg0
, EXYNOS_MSCTRL
);
1671 static void fimc_ippdrv_stop(struct device
*dev
, enum drm_exynos_ipp_cmd cmd
)
1673 struct fimc_context
*ctx
= get_fimc_context(dev
);
1674 struct drm_exynos_ipp_set_wb set_wb
= {0, 0};
1677 DRM_DEBUG_KMS("%s:cmd[%d]\n", __func__
, cmd
);
1682 cfg
= fimc_read(EXYNOS_MSCTRL
);
1683 cfg
&= ~EXYNOS_MSCTRL_INPUT_MASK
;
1684 cfg
&= ~EXYNOS_MSCTRL_ENVID
;
1685 fimc_write(cfg
, EXYNOS_MSCTRL
);
1688 exynos_drm_ippnb_send_event(IPP_SET_WRITEBACK
, (void *)&set_wb
);
1690 case IPP_CMD_OUTPUT
:
1692 dev_err(dev
, "invalid operations.\n");
1696 fimc_handle_irq(ctx
, false, false, true);
1698 /* reset sequence */
1699 fimc_write(0x0, EXYNOS_CIFCNTSEQ
);
1701 /* Scaler disable */
1702 cfg
= fimc_read(EXYNOS_CISCCTRL
);
1703 cfg
&= ~EXYNOS_CISCCTRL_SCALERSTART
;
1704 fimc_write(cfg
, EXYNOS_CISCCTRL
);
1706 /* Disable image capture */
1707 cfg
= fimc_read(EXYNOS_CIIMGCPT
);
1708 cfg
&= ~(EXYNOS_CIIMGCPT_IMGCPTEN_SC
| EXYNOS_CIIMGCPT_IMGCPTEN
);
1709 fimc_write(cfg
, EXYNOS_CIIMGCPT
);
1711 /* Enable frame end irq */
1712 cfg
= fimc_read(EXYNOS_CIGCTRL
);
1713 cfg
|= EXYNOS_CIGCTRL_IRQ_END_DISABLE
;
1714 fimc_write(cfg
, EXYNOS_CIGCTRL
);
1717 static int __devinit
fimc_probe(struct platform_device
*pdev
)
1719 struct device
*dev
= &pdev
->dev
;
1720 struct fimc_context
*ctx
;
1721 struct clk
*parent_clk
;
1722 struct resource
*res
;
1723 struct exynos_drm_ippdrv
*ippdrv
;
1724 struct exynos_drm_fimc_pdata
*pdata
;
1725 struct fimc_driverdata
*ddata
;
1728 pdata
= pdev
->dev
.platform_data
;
1730 dev_err(dev
, "no platform data specified.\n");
1734 ctx
= devm_kzalloc(dev
, sizeof(*ctx
), GFP_KERNEL
);
1738 ddata
= (struct fimc_driverdata
*)
1739 platform_get_device_id(pdev
)->driver_data
;
1742 ctx
->sclk_fimc_clk
= clk_get(dev
, "sclk_fimc");
1743 if (IS_ERR(ctx
->sclk_fimc_clk
)) {
1744 dev_err(dev
, "failed to get src fimc clock.\n");
1745 ret
= PTR_ERR(ctx
->sclk_fimc_clk
);
1748 clk_enable(ctx
->sclk_fimc_clk
);
1750 ctx
->fimc_clk
= clk_get(dev
, "fimc");
1751 if (IS_ERR(ctx
->fimc_clk
)) {
1752 dev_err(dev
, "failed to get fimc clock.\n");
1753 ret
= PTR_ERR(ctx
->fimc_clk
);
1754 clk_disable(ctx
->sclk_fimc_clk
);
1755 clk_put(ctx
->sclk_fimc_clk
);
1759 ctx
->wb_clk
= clk_get(dev
, "pxl_async0");
1760 if (IS_ERR(ctx
->wb_clk
)) {
1761 dev_err(dev
, "failed to get writeback a clock.\n");
1762 ret
= PTR_ERR(ctx
->wb_clk
);
1763 clk_disable(ctx
->sclk_fimc_clk
);
1764 clk_put(ctx
->sclk_fimc_clk
);
1765 clk_put(ctx
->fimc_clk
);
1769 ctx
->wb_b_clk
= clk_get(dev
, "pxl_async1");
1770 if (IS_ERR(ctx
->wb_b_clk
)) {
1771 dev_err(dev
, "failed to get writeback b clock.\n");
1772 ret
= PTR_ERR(ctx
->wb_b_clk
);
1773 clk_disable(ctx
->sclk_fimc_clk
);
1774 clk_put(ctx
->sclk_fimc_clk
);
1775 clk_put(ctx
->fimc_clk
);
1776 clk_put(ctx
->wb_clk
);
1780 parent_clk
= clk_get(dev
, ddata
->parent_clk
);
1782 if (IS_ERR(parent_clk
)) {
1783 dev_err(dev
, "failed to get parent clock.\n");
1784 ret
= PTR_ERR(parent_clk
);
1785 clk_disable(ctx
->sclk_fimc_clk
);
1786 clk_put(ctx
->sclk_fimc_clk
);
1787 clk_put(ctx
->fimc_clk
);
1788 clk_put(ctx
->wb_clk
);
1789 clk_put(ctx
->wb_b_clk
);
1793 if (clk_set_parent(ctx
->sclk_fimc_clk
, parent_clk
)) {
1794 dev_err(dev
, "failed to set parent.\n");
1796 clk_put(parent_clk
);
1797 clk_disable(ctx
->sclk_fimc_clk
);
1798 clk_put(ctx
->sclk_fimc_clk
);
1799 clk_put(ctx
->fimc_clk
);
1800 clk_put(ctx
->wb_clk
);
1801 clk_put(ctx
->wb_b_clk
);
1805 clk_put(parent_clk
);
1806 clk_set_rate(ctx
->sclk_fimc_clk
, pdata
->clk_rate
);
1808 /* resource memory */
1809 ctx
->regs_res
= platform_get_resource(pdev
, IORESOURCE_MEM
, 0);
1810 if (!ctx
->regs_res
) {
1811 dev_err(dev
, "failed to find registers.\n");
1816 ctx
->regs
= devm_request_and_ioremap(dev
, ctx
->regs_res
);
1818 dev_err(dev
, "failed to map registers.\n");
1824 res
= platform_get_resource(pdev
, IORESOURCE_IRQ
, 0);
1826 dev_err(dev
, "failed to request irq resource.\n");
1831 ctx
->irq
= res
->start
;
1832 ret
= request_threaded_irq(ctx
->irq
, NULL
, fimc_irq_handler
,
1833 IRQF_ONESHOT
, "drm_fimc", ctx
);
1835 dev_err(dev
, "failed to request irq.\n");
1839 /* context initailization */
1841 ctx
->pol
= pdata
->pol
;
1844 ippdrv
= &ctx
->ippdrv
;
1846 ippdrv
->ops
[EXYNOS_DRM_OPS_SRC
] = &fimc_src_ops
;
1847 ippdrv
->ops
[EXYNOS_DRM_OPS_DST
] = &fimc_dst_ops
;
1848 ippdrv
->check_property
= fimc_ippdrv_check_property
;
1849 ippdrv
->reset
= fimc_ippdrv_reset
;
1850 ippdrv
->start
= fimc_ippdrv_start
;
1851 ippdrv
->stop
= fimc_ippdrv_stop
;
1852 ret
= fimc_init_prop_list(ippdrv
);
1854 dev_err(dev
, "failed to init property list.\n");
1858 DRM_DEBUG_KMS("%s:id[%d]ippdrv[0x%x]\n", __func__
, ctx
->id
,
1861 mutex_init(&ctx
->lock
);
1862 platform_set_drvdata(pdev
, ctx
);
1864 pm_runtime_set_active(dev
);
1865 pm_runtime_enable(dev
);
1867 ret
= exynos_drm_ippdrv_register(ippdrv
);
1869 dev_err(dev
, "failed to register drm fimc device.\n");
1870 goto err_ippdrv_register
;
1873 dev_info(&pdev
->dev
, "drm fimc registered successfully.\n");
1877 err_ippdrv_register
:
1878 devm_kfree(dev
, ippdrv
->prop_list
);
1879 pm_runtime_disable(dev
);
1881 free_irq(ctx
->irq
, ctx
);
1883 devm_iounmap(dev
, ctx
->regs
);
1885 clk_put(ctx
->sclk_fimc_clk
);
1886 clk_put(ctx
->fimc_clk
);
1887 clk_put(ctx
->wb_clk
);
1888 clk_put(ctx
->wb_b_clk
);
1890 devm_kfree(dev
, ctx
);
1894 static int __devexit
fimc_remove(struct platform_device
*pdev
)
1896 struct device
*dev
= &pdev
->dev
;
1897 struct fimc_context
*ctx
= get_fimc_context(dev
);
1898 struct exynos_drm_ippdrv
*ippdrv
= &ctx
->ippdrv
;
1900 devm_kfree(dev
, ippdrv
->prop_list
);
1901 exynos_drm_ippdrv_unregister(ippdrv
);
1902 mutex_destroy(&ctx
->lock
);
1904 pm_runtime_set_suspended(dev
);
1905 pm_runtime_disable(dev
);
1907 free_irq(ctx
->irq
, ctx
);
1908 devm_iounmap(dev
, ctx
->regs
);
1910 clk_put(ctx
->sclk_fimc_clk
);
1911 clk_put(ctx
->fimc_clk
);
1912 clk_put(ctx
->wb_clk
);
1913 clk_put(ctx
->wb_b_clk
);
1915 devm_kfree(dev
, ctx
);
1920 #ifdef CONFIG_PM_SLEEP
1921 static int fimc_suspend(struct device
*dev
)
1923 struct fimc_context
*ctx
= get_fimc_context(dev
);
1925 DRM_DEBUG_KMS("%s:id[%d]\n", __func__
, ctx
->id
);
1927 if (pm_runtime_suspended(dev
))
1930 return fimc_clk_ctrl(ctx
, false);
1933 static int fimc_resume(struct device
*dev
)
1935 struct fimc_context
*ctx
= get_fimc_context(dev
);
1937 DRM_DEBUG_KMS("%s:id[%d]\n", __func__
, ctx
->id
);
1939 if (!pm_runtime_suspended(dev
))
1940 return fimc_clk_ctrl(ctx
, true);
1946 #ifdef CONFIG_PM_RUNTIME
1947 static int fimc_runtime_suspend(struct device
*dev
)
1949 struct fimc_context
*ctx
= get_fimc_context(dev
);
1951 DRM_DEBUG_KMS("%s:id[%d]\n", __func__
, ctx
->id
);
1953 return fimc_clk_ctrl(ctx
, false);
1956 static int fimc_runtime_resume(struct device
*dev
)
1958 struct fimc_context
*ctx
= get_fimc_context(dev
);
1960 DRM_DEBUG_KMS("%s:id[%d]\n", __func__
, ctx
->id
);
1962 return fimc_clk_ctrl(ctx
, true);
1966 static struct fimc_driverdata exynos4210_fimc_data
= {
1967 .parent_clk
= "mout_mpll",
1970 static struct fimc_driverdata exynos4410_fimc_data
= {
1971 .parent_clk
= "mout_mpll_user",
1974 static struct platform_device_id fimc_driver_ids
[] = {
1976 .name
= "exynos4210-fimc",
1977 .driver_data
= (unsigned long)&exynos4210_fimc_data
,
1979 .name
= "exynos4412-fimc",
1980 .driver_data
= (unsigned long)&exynos4410_fimc_data
,
1984 MODULE_DEVICE_TABLE(platform
, fimc_driver_ids
);
1986 static const struct dev_pm_ops fimc_pm_ops
= {
1987 SET_SYSTEM_SLEEP_PM_OPS(fimc_suspend
, fimc_resume
)
1988 SET_RUNTIME_PM_OPS(fimc_runtime_suspend
, fimc_runtime_resume
, NULL
)
1991 struct platform_driver fimc_driver
= {
1992 .probe
= fimc_probe
,
1993 .remove
= __devexit_p(fimc_remove
),
1994 .id_table
= fimc_driver_ids
,
1996 .name
= "exynos-drm-fimc",
1997 .owner
= THIS_MODULE
,