1 // SPDX-License-Identifier: GPL-2.0-or-later
3 * Copyright (C) 2012 Samsung Electronics Co.Ltd
5 * Eunchul Kim <chulspro.kim@samsung.com>
6 * Jinyoung Jeon <jy0.jeon@samsung.com>
7 * Sangmin Lee <lsmin.lee@samsung.com>
10 #include <linux/clk.h>
11 #include <linux/component.h>
12 #include <linux/kernel.h>
13 #include <linux/mfd/syscon.h>
15 #include <linux/platform_device.h>
16 #include <linux/pm_runtime.h>
17 #include <linux/regmap.h>
18 #include <linux/spinlock.h>
20 #include <drm/drm_fourcc.h>
21 #include <drm/drm_print.h>
22 #include <drm/exynos_drm.h>
24 #include "exynos_drm_drv.h"
25 #include "exynos_drm_ipp.h"
26 #include "regs-fimc.h"
29 * FIMC stands for Fully Interactive Mobile Camera and
30 * supports image scaler/rotator and input/output DMA operations.
31 * input DMA reads image data from the memory.
32 * output DMA writes image data to memory.
33 * FIMC supports image rotation and image effect functions.
36 #define FIMC_MAX_DEVS 4
37 #define FIMC_MAX_SRC 2
38 #define FIMC_MAX_DST 32
39 #define FIMC_SHFACTOR 10
40 #define FIMC_BUF_STOP 1
41 #define FIMC_BUF_START 2
42 #define FIMC_WIDTH_ITU_709 1280
43 #define FIMC_AUTOSUSPEND_DELAY 2000
45 static unsigned int fimc_mask
= 0xc;
46 module_param_named(fimc_devs
, fimc_mask
, uint
, 0644);
47 MODULE_PARM_DESC(fimc_devs
, "Alias mask for assigning FIMC devices to Exynos DRM");
49 #define get_fimc_context(dev) dev_get_drvdata(dev)
59 static const char * const fimc_clock_names
[] = {
60 [FIMC_CLK_LCLK
] = "sclk_fimc",
61 [FIMC_CLK_GATE
] = "fimc",
62 [FIMC_CLK_WB_A
] = "pxl_async0",
63 [FIMC_CLK_WB_B
] = "pxl_async1",
67 * A structure of scaler.
69 * @range: narrow, wide.
70 * @bypass: unused scaler path.
71 * @up_h: horizontal scale up.
72 * @up_v: vertical scale up.
73 * @hratio: horizontal ratio.
74 * @vratio: vertical ratio.
86 * A structure of fimc context.
88 * @regs: memory mapped io registers.
89 * @lock: locking of operations.
90 * @clocks: fimc clocks.
91 * @sc: scaler infomations.
92 * @pol: porarity of writeback.
97 struct exynos_drm_ipp ipp
;
98 struct drm_device
*drm_dev
;
101 struct exynos_drm_ipp_task
*task
;
102 struct exynos_drm_ipp_formats
*formats
;
103 unsigned int num_formats
;
107 struct clk
*clocks
[FIMC_CLKS_MAX
];
108 struct fimc_scaler sc
;
113 static u32
fimc_read(struct fimc_context
*ctx
, u32 reg
)
115 return readl(ctx
->regs
+ reg
);
118 static void fimc_write(struct fimc_context
*ctx
, u32 val
, u32 reg
)
120 writel(val
, ctx
->regs
+ reg
);
123 static void fimc_set_bits(struct fimc_context
*ctx
, u32 reg
, u32 bits
)
125 void __iomem
*r
= ctx
->regs
+ reg
;
127 writel(readl(r
) | bits
, r
);
130 static void fimc_clear_bits(struct fimc_context
*ctx
, u32 reg
, u32 bits
)
132 void __iomem
*r
= ctx
->regs
+ reg
;
134 writel(readl(r
) & ~bits
, r
);
137 static void fimc_sw_reset(struct fimc_context
*ctx
)
141 /* stop dma operation */
142 cfg
= fimc_read(ctx
, EXYNOS_CISTATUS
);
143 if (EXYNOS_CISTATUS_GET_ENVID_STATUS(cfg
))
144 fimc_clear_bits(ctx
, EXYNOS_MSCTRL
, EXYNOS_MSCTRL_ENVID
);
146 fimc_set_bits(ctx
, EXYNOS_CISRCFMT
, EXYNOS_CISRCFMT_ITU601_8BIT
);
148 /* disable image capture */
149 fimc_clear_bits(ctx
, EXYNOS_CIIMGCPT
,
150 EXYNOS_CIIMGCPT_IMGCPTEN_SC
| EXYNOS_CIIMGCPT_IMGCPTEN
);
153 fimc_set_bits(ctx
, EXYNOS_CIGCTRL
, EXYNOS_CIGCTRL_SWRST
);
155 /* s/w reset complete */
156 fimc_clear_bits(ctx
, EXYNOS_CIGCTRL
, EXYNOS_CIGCTRL_SWRST
);
159 fimc_write(ctx
, 0x0, EXYNOS_CIFCNTSEQ
);
162 static void fimc_set_type_ctrl(struct fimc_context
*ctx
)
166 cfg
= fimc_read(ctx
, EXYNOS_CIGCTRL
);
167 cfg
&= ~(EXYNOS_CIGCTRL_TESTPATTERN_MASK
|
168 EXYNOS_CIGCTRL_SELCAM_ITU_MASK
|
169 EXYNOS_CIGCTRL_SELCAM_MIPI_MASK
|
170 EXYNOS_CIGCTRL_SELCAM_FIMC_MASK
|
171 EXYNOS_CIGCTRL_SELWB_CAMIF_MASK
|
172 EXYNOS_CIGCTRL_SELWRITEBACK_MASK
);
174 cfg
|= (EXYNOS_CIGCTRL_SELCAM_ITU_A
|
175 EXYNOS_CIGCTRL_SELWRITEBACK_A
|
176 EXYNOS_CIGCTRL_SELCAM_MIPI_A
|
177 EXYNOS_CIGCTRL_SELCAM_FIMC_ITU
);
179 fimc_write(ctx
, cfg
, EXYNOS_CIGCTRL
);
182 static void fimc_handle_jpeg(struct fimc_context
*ctx
, bool enable
)
186 DRM_DEV_DEBUG_KMS(ctx
->dev
, "enable[%d]\n", enable
);
188 cfg
= fimc_read(ctx
, EXYNOS_CIGCTRL
);
190 cfg
|= EXYNOS_CIGCTRL_CAM_JPEG
;
192 cfg
&= ~EXYNOS_CIGCTRL_CAM_JPEG
;
194 fimc_write(ctx
, cfg
, EXYNOS_CIGCTRL
);
197 static void fimc_mask_irq(struct fimc_context
*ctx
, bool enable
)
201 DRM_DEV_DEBUG_KMS(ctx
->dev
, "enable[%d]\n", enable
);
203 cfg
= fimc_read(ctx
, EXYNOS_CIGCTRL
);
205 cfg
&= ~EXYNOS_CIGCTRL_IRQ_OVFEN
;
206 cfg
|= EXYNOS_CIGCTRL_IRQ_ENABLE
| EXYNOS_CIGCTRL_IRQ_LEVEL
;
208 cfg
&= ~EXYNOS_CIGCTRL_IRQ_ENABLE
;
209 fimc_write(ctx
, cfg
, EXYNOS_CIGCTRL
);
212 static void fimc_clear_irq(struct fimc_context
*ctx
)
214 fimc_set_bits(ctx
, EXYNOS_CIGCTRL
, EXYNOS_CIGCTRL_IRQ_CLR
);
217 static bool fimc_check_ovf(struct fimc_context
*ctx
)
221 status
= fimc_read(ctx
, EXYNOS_CISTATUS
);
222 flag
= EXYNOS_CISTATUS_OVFIY
| EXYNOS_CISTATUS_OVFICB
|
223 EXYNOS_CISTATUS_OVFICR
;
225 DRM_DEV_DEBUG_KMS(ctx
->dev
, "flag[0x%x]\n", flag
);
228 fimc_set_bits(ctx
, EXYNOS_CIWDOFST
,
229 EXYNOS_CIWDOFST_CLROVFIY
| EXYNOS_CIWDOFST_CLROVFICB
|
230 EXYNOS_CIWDOFST_CLROVFICR
);
232 DRM_DEV_ERROR(ctx
->dev
,
233 "occurred overflow at %d, status 0x%x.\n",
241 static bool fimc_check_frame_end(struct fimc_context
*ctx
)
245 cfg
= fimc_read(ctx
, EXYNOS_CISTATUS
);
247 DRM_DEV_DEBUG_KMS(ctx
->dev
, "cfg[0x%x]\n", cfg
);
249 if (!(cfg
& EXYNOS_CISTATUS_FRAMEEND
))
252 cfg
&= ~(EXYNOS_CISTATUS_FRAMEEND
);
253 fimc_write(ctx
, cfg
, EXYNOS_CISTATUS
);
258 static int fimc_get_buf_id(struct fimc_context
*ctx
)
261 int frame_cnt
, buf_id
;
263 cfg
= fimc_read(ctx
, EXYNOS_CISTATUS2
);
264 frame_cnt
= EXYNOS_CISTATUS2_GET_FRAMECOUNT_BEFORE(cfg
);
267 frame_cnt
= EXYNOS_CISTATUS2_GET_FRAMECOUNT_PRESENT(cfg
);
269 DRM_DEV_DEBUG_KMS(ctx
->dev
, "present[%d]before[%d]\n",
270 EXYNOS_CISTATUS2_GET_FRAMECOUNT_PRESENT(cfg
),
271 EXYNOS_CISTATUS2_GET_FRAMECOUNT_BEFORE(cfg
));
273 if (frame_cnt
== 0) {
274 DRM_DEV_ERROR(ctx
->dev
, "failed to get frame count.\n");
278 buf_id
= frame_cnt
- 1;
279 DRM_DEV_DEBUG_KMS(ctx
->dev
, "buf_id[%d]\n", buf_id
);
284 static void fimc_handle_lastend(struct fimc_context
*ctx
, bool enable
)
288 DRM_DEV_DEBUG_KMS(ctx
->dev
, "enable[%d]\n", enable
);
290 cfg
= fimc_read(ctx
, EXYNOS_CIOCTRL
);
292 cfg
|= EXYNOS_CIOCTRL_LASTENDEN
;
294 cfg
&= ~EXYNOS_CIOCTRL_LASTENDEN
;
296 fimc_write(ctx
, cfg
, EXYNOS_CIOCTRL
);
299 static void fimc_src_set_fmt_order(struct fimc_context
*ctx
, u32 fmt
)
303 DRM_DEV_DEBUG_KMS(ctx
->dev
, "fmt[0x%x]\n", fmt
);
306 cfg
= fimc_read(ctx
, EXYNOS_CISCCTRL
);
307 cfg
&= ~EXYNOS_CISCCTRL_INRGB_FMT_RGB_MASK
;
310 case DRM_FORMAT_RGB565
:
311 cfg
|= EXYNOS_CISCCTRL_INRGB_FMT_RGB565
;
312 fimc_write(ctx
, cfg
, EXYNOS_CISCCTRL
);
314 case DRM_FORMAT_RGB888
:
315 case DRM_FORMAT_XRGB8888
:
316 cfg
|= EXYNOS_CISCCTRL_INRGB_FMT_RGB888
;
317 fimc_write(ctx
, cfg
, EXYNOS_CISCCTRL
);
325 cfg
= fimc_read(ctx
, EXYNOS_MSCTRL
);
326 cfg
&= ~(EXYNOS_MSCTRL_ORDER2P_SHIFT_MASK
|
327 EXYNOS_MSCTRL_C_INT_IN_2PLANE
|
328 EXYNOS_MSCTRL_ORDER422_YCBYCR
);
331 case DRM_FORMAT_YUYV
:
332 cfg
|= EXYNOS_MSCTRL_ORDER422_YCBYCR
;
334 case DRM_FORMAT_YVYU
:
335 cfg
|= EXYNOS_MSCTRL_ORDER422_YCRYCB
;
337 case DRM_FORMAT_UYVY
:
338 cfg
|= EXYNOS_MSCTRL_ORDER422_CBYCRY
;
340 case DRM_FORMAT_VYUY
:
341 case DRM_FORMAT_YUV444
:
342 cfg
|= EXYNOS_MSCTRL_ORDER422_CRYCBY
;
344 case DRM_FORMAT_NV21
:
345 case DRM_FORMAT_NV61
:
346 cfg
|= (EXYNOS_MSCTRL_ORDER2P_LSB_CRCB
|
347 EXYNOS_MSCTRL_C_INT_IN_2PLANE
);
349 case DRM_FORMAT_YUV422
:
350 case DRM_FORMAT_YUV420
:
351 case DRM_FORMAT_YVU420
:
352 cfg
|= EXYNOS_MSCTRL_C_INT_IN_3PLANE
;
354 case DRM_FORMAT_NV12
:
355 case DRM_FORMAT_NV16
:
356 cfg
|= (EXYNOS_MSCTRL_ORDER2P_LSB_CBCR
|
357 EXYNOS_MSCTRL_C_INT_IN_2PLANE
);
361 fimc_write(ctx
, cfg
, EXYNOS_MSCTRL
);
364 static void fimc_src_set_fmt(struct fimc_context
*ctx
, u32 fmt
, bool tiled
)
368 DRM_DEV_DEBUG_KMS(ctx
->dev
, "fmt[0x%x]\n", fmt
);
370 cfg
= fimc_read(ctx
, EXYNOS_MSCTRL
);
371 cfg
&= ~EXYNOS_MSCTRL_INFORMAT_RGB
;
374 case DRM_FORMAT_RGB565
:
375 case DRM_FORMAT_RGB888
:
376 case DRM_FORMAT_XRGB8888
:
377 cfg
|= EXYNOS_MSCTRL_INFORMAT_RGB
;
379 case DRM_FORMAT_YUV444
:
380 cfg
|= EXYNOS_MSCTRL_INFORMAT_YCBCR420
;
382 case DRM_FORMAT_YUYV
:
383 case DRM_FORMAT_YVYU
:
384 case DRM_FORMAT_UYVY
:
385 case DRM_FORMAT_VYUY
:
386 cfg
|= EXYNOS_MSCTRL_INFORMAT_YCBCR422_1PLANE
;
388 case DRM_FORMAT_NV16
:
389 case DRM_FORMAT_NV61
:
390 case DRM_FORMAT_YUV422
:
391 cfg
|= EXYNOS_MSCTRL_INFORMAT_YCBCR422
;
393 case DRM_FORMAT_YUV420
:
394 case DRM_FORMAT_YVU420
:
395 case DRM_FORMAT_NV12
:
396 case DRM_FORMAT_NV21
:
397 cfg
|= EXYNOS_MSCTRL_INFORMAT_YCBCR420
;
401 fimc_write(ctx
, cfg
, EXYNOS_MSCTRL
);
403 cfg
= fimc_read(ctx
, EXYNOS_CIDMAPARAM
);
404 cfg
&= ~EXYNOS_CIDMAPARAM_R_MODE_MASK
;
407 cfg
|= EXYNOS_CIDMAPARAM_R_MODE_64X32
;
409 cfg
|= EXYNOS_CIDMAPARAM_R_MODE_LINEAR
;
411 fimc_write(ctx
, cfg
, EXYNOS_CIDMAPARAM
);
413 fimc_src_set_fmt_order(ctx
, fmt
);
416 static void fimc_src_set_transf(struct fimc_context
*ctx
, unsigned int rotation
)
418 unsigned int degree
= rotation
& DRM_MODE_ROTATE_MASK
;
421 DRM_DEV_DEBUG_KMS(ctx
->dev
, "rotation[%x]\n", rotation
);
423 cfg1
= fimc_read(ctx
, EXYNOS_MSCTRL
);
424 cfg1
&= ~(EXYNOS_MSCTRL_FLIP_X_MIRROR
|
425 EXYNOS_MSCTRL_FLIP_Y_MIRROR
);
427 cfg2
= fimc_read(ctx
, EXYNOS_CITRGFMT
);
428 cfg2
&= ~EXYNOS_CITRGFMT_INROT90_CLOCKWISE
;
431 case DRM_MODE_ROTATE_0
:
432 if (rotation
& DRM_MODE_REFLECT_X
)
433 cfg1
|= EXYNOS_MSCTRL_FLIP_X_MIRROR
;
434 if (rotation
& DRM_MODE_REFLECT_Y
)
435 cfg1
|= EXYNOS_MSCTRL_FLIP_Y_MIRROR
;
437 case DRM_MODE_ROTATE_90
:
438 cfg2
|= EXYNOS_CITRGFMT_INROT90_CLOCKWISE
;
439 if (rotation
& DRM_MODE_REFLECT_X
)
440 cfg1
|= EXYNOS_MSCTRL_FLIP_X_MIRROR
;
441 if (rotation
& DRM_MODE_REFLECT_Y
)
442 cfg1
|= EXYNOS_MSCTRL_FLIP_Y_MIRROR
;
444 case DRM_MODE_ROTATE_180
:
445 cfg1
|= (EXYNOS_MSCTRL_FLIP_X_MIRROR
|
446 EXYNOS_MSCTRL_FLIP_Y_MIRROR
);
447 if (rotation
& DRM_MODE_REFLECT_X
)
448 cfg1
&= ~EXYNOS_MSCTRL_FLIP_X_MIRROR
;
449 if (rotation
& DRM_MODE_REFLECT_Y
)
450 cfg1
&= ~EXYNOS_MSCTRL_FLIP_Y_MIRROR
;
452 case DRM_MODE_ROTATE_270
:
453 cfg1
|= (EXYNOS_MSCTRL_FLIP_X_MIRROR
|
454 EXYNOS_MSCTRL_FLIP_Y_MIRROR
);
455 cfg2
|= EXYNOS_CITRGFMT_INROT90_CLOCKWISE
;
456 if (rotation
& DRM_MODE_REFLECT_X
)
457 cfg1
&= ~EXYNOS_MSCTRL_FLIP_X_MIRROR
;
458 if (rotation
& DRM_MODE_REFLECT_Y
)
459 cfg1
&= ~EXYNOS_MSCTRL_FLIP_Y_MIRROR
;
463 fimc_write(ctx
, cfg1
, EXYNOS_MSCTRL
);
464 fimc_write(ctx
, cfg2
, EXYNOS_CITRGFMT
);
467 static void fimc_set_window(struct fimc_context
*ctx
,
468 struct exynos_drm_ipp_buffer
*buf
)
470 unsigned int real_width
= buf
->buf
.pitch
[0] / buf
->format
->cpp
[0];
471 u32 cfg
, h1
, h2
, v1
, v2
;
475 h2
= real_width
- buf
->rect
.w
- buf
->rect
.x
;
477 v2
= buf
->buf
.height
- buf
->rect
.h
- buf
->rect
.y
;
479 DRM_DEV_DEBUG_KMS(ctx
->dev
, "x[%d]y[%d]w[%d]h[%d]hsize[%d]vsize[%d]\n",
480 buf
->rect
.x
, buf
->rect
.y
, buf
->rect
.w
, buf
->rect
.h
,
481 real_width
, buf
->buf
.height
);
482 DRM_DEV_DEBUG_KMS(ctx
->dev
, "h1[%d]h2[%d]v1[%d]v2[%d]\n", h1
, h2
, v1
,
486 * set window offset 1, 2 size
487 * check figure 43-21 in user manual
489 cfg
= fimc_read(ctx
, EXYNOS_CIWDOFST
);
490 cfg
&= ~(EXYNOS_CIWDOFST_WINHOROFST_MASK
|
491 EXYNOS_CIWDOFST_WINVEROFST_MASK
);
492 cfg
|= (EXYNOS_CIWDOFST_WINHOROFST(h1
) |
493 EXYNOS_CIWDOFST_WINVEROFST(v1
));
494 cfg
|= EXYNOS_CIWDOFST_WINOFSEN
;
495 fimc_write(ctx
, cfg
, EXYNOS_CIWDOFST
);
497 cfg
= (EXYNOS_CIWDOFST2_WINHOROFST2(h2
) |
498 EXYNOS_CIWDOFST2_WINVEROFST2(v2
));
499 fimc_write(ctx
, cfg
, EXYNOS_CIWDOFST2
);
502 static void fimc_src_set_size(struct fimc_context
*ctx
,
503 struct exynos_drm_ipp_buffer
*buf
)
505 unsigned int real_width
= buf
->buf
.pitch
[0] / buf
->format
->cpp
[0];
508 DRM_DEV_DEBUG_KMS(ctx
->dev
, "hsize[%d]vsize[%d]\n", real_width
,
512 cfg
= (EXYNOS_ORGISIZE_HORIZONTAL(real_width
) |
513 EXYNOS_ORGISIZE_VERTICAL(buf
->buf
.height
));
515 fimc_write(ctx
, cfg
, EXYNOS_ORGISIZE
);
517 DRM_DEV_DEBUG_KMS(ctx
->dev
, "x[%d]y[%d]w[%d]h[%d]\n", buf
->rect
.x
,
518 buf
->rect
.y
, buf
->rect
.w
, buf
->rect
.h
);
520 /* set input DMA image size */
521 cfg
= fimc_read(ctx
, EXYNOS_CIREAL_ISIZE
);
522 cfg
&= ~(EXYNOS_CIREAL_ISIZE_HEIGHT_MASK
|
523 EXYNOS_CIREAL_ISIZE_WIDTH_MASK
);
524 cfg
|= (EXYNOS_CIREAL_ISIZE_WIDTH(buf
->rect
.w
) |
525 EXYNOS_CIREAL_ISIZE_HEIGHT(buf
->rect
.h
));
526 fimc_write(ctx
, cfg
, EXYNOS_CIREAL_ISIZE
);
529 * set input FIFO image size
530 * for now, we support only ITU601 8 bit mode
532 cfg
= (EXYNOS_CISRCFMT_ITU601_8BIT
|
533 EXYNOS_CISRCFMT_SOURCEHSIZE(real_width
) |
534 EXYNOS_CISRCFMT_SOURCEVSIZE(buf
->buf
.height
));
535 fimc_write(ctx
, cfg
, EXYNOS_CISRCFMT
);
537 /* offset Y(RGB), Cb, Cr */
538 cfg
= (EXYNOS_CIIYOFF_HORIZONTAL(buf
->rect
.x
) |
539 EXYNOS_CIIYOFF_VERTICAL(buf
->rect
.y
));
540 fimc_write(ctx
, cfg
, EXYNOS_CIIYOFF
);
541 cfg
= (EXYNOS_CIICBOFF_HORIZONTAL(buf
->rect
.x
) |
542 EXYNOS_CIICBOFF_VERTICAL(buf
->rect
.y
));
543 fimc_write(ctx
, cfg
, EXYNOS_CIICBOFF
);
544 cfg
= (EXYNOS_CIICROFF_HORIZONTAL(buf
->rect
.x
) |
545 EXYNOS_CIICROFF_VERTICAL(buf
->rect
.y
));
546 fimc_write(ctx
, cfg
, EXYNOS_CIICROFF
);
548 fimc_set_window(ctx
, buf
);
551 static void fimc_src_set_addr(struct fimc_context
*ctx
,
552 struct exynos_drm_ipp_buffer
*buf
)
554 fimc_write(ctx
, buf
->dma_addr
[0], EXYNOS_CIIYSA(0));
555 fimc_write(ctx
, buf
->dma_addr
[1], EXYNOS_CIICBSA(0));
556 fimc_write(ctx
, buf
->dma_addr
[2], EXYNOS_CIICRSA(0));
559 static void fimc_dst_set_fmt_order(struct fimc_context
*ctx
, u32 fmt
)
563 DRM_DEV_DEBUG_KMS(ctx
->dev
, "fmt[0x%x]\n", fmt
);
566 cfg
= fimc_read(ctx
, EXYNOS_CISCCTRL
);
567 cfg
&= ~EXYNOS_CISCCTRL_OUTRGB_FMT_RGB_MASK
;
570 case DRM_FORMAT_RGB565
:
571 cfg
|= EXYNOS_CISCCTRL_OUTRGB_FMT_RGB565
;
572 fimc_write(ctx
, cfg
, EXYNOS_CISCCTRL
);
574 case DRM_FORMAT_RGB888
:
575 cfg
|= EXYNOS_CISCCTRL_OUTRGB_FMT_RGB888
;
576 fimc_write(ctx
, cfg
, EXYNOS_CISCCTRL
);
578 case DRM_FORMAT_XRGB8888
:
579 cfg
|= (EXYNOS_CISCCTRL_OUTRGB_FMT_RGB888
|
580 EXYNOS_CISCCTRL_EXTRGB_EXTENSION
);
581 fimc_write(ctx
, cfg
, EXYNOS_CISCCTRL
);
589 cfg
= fimc_read(ctx
, EXYNOS_CIOCTRL
);
590 cfg
&= ~(EXYNOS_CIOCTRL_ORDER2P_MASK
|
591 EXYNOS_CIOCTRL_ORDER422_MASK
|
592 EXYNOS_CIOCTRL_YCBCR_PLANE_MASK
);
595 case DRM_FORMAT_XRGB8888
:
596 cfg
|= EXYNOS_CIOCTRL_ALPHA_OUT
;
598 case DRM_FORMAT_YUYV
:
599 cfg
|= EXYNOS_CIOCTRL_ORDER422_YCBYCR
;
601 case DRM_FORMAT_YVYU
:
602 cfg
|= EXYNOS_CIOCTRL_ORDER422_YCRYCB
;
604 case DRM_FORMAT_UYVY
:
605 cfg
|= EXYNOS_CIOCTRL_ORDER422_CBYCRY
;
607 case DRM_FORMAT_VYUY
:
608 cfg
|= EXYNOS_CIOCTRL_ORDER422_CRYCBY
;
610 case DRM_FORMAT_NV21
:
611 case DRM_FORMAT_NV61
:
612 cfg
|= EXYNOS_CIOCTRL_ORDER2P_LSB_CRCB
;
613 cfg
|= EXYNOS_CIOCTRL_YCBCR_2PLANE
;
615 case DRM_FORMAT_YUV422
:
616 case DRM_FORMAT_YUV420
:
617 case DRM_FORMAT_YVU420
:
618 cfg
|= EXYNOS_CIOCTRL_YCBCR_3PLANE
;
620 case DRM_FORMAT_NV12
:
621 case DRM_FORMAT_NV16
:
622 cfg
|= EXYNOS_CIOCTRL_ORDER2P_LSB_CBCR
;
623 cfg
|= EXYNOS_CIOCTRL_YCBCR_2PLANE
;
627 fimc_write(ctx
, cfg
, EXYNOS_CIOCTRL
);
630 static void fimc_dst_set_fmt(struct fimc_context
*ctx
, u32 fmt
, bool tiled
)
634 DRM_DEV_DEBUG_KMS(ctx
->dev
, "fmt[0x%x]\n", fmt
);
636 cfg
= fimc_read(ctx
, EXYNOS_CIEXTEN
);
638 if (fmt
== DRM_FORMAT_AYUV
) {
639 cfg
|= EXYNOS_CIEXTEN_YUV444_OUT
;
640 fimc_write(ctx
, cfg
, EXYNOS_CIEXTEN
);
642 cfg
&= ~EXYNOS_CIEXTEN_YUV444_OUT
;
643 fimc_write(ctx
, cfg
, EXYNOS_CIEXTEN
);
645 cfg
= fimc_read(ctx
, EXYNOS_CITRGFMT
);
646 cfg
&= ~EXYNOS_CITRGFMT_OUTFORMAT_MASK
;
649 case DRM_FORMAT_RGB565
:
650 case DRM_FORMAT_RGB888
:
651 case DRM_FORMAT_XRGB8888
:
652 cfg
|= EXYNOS_CITRGFMT_OUTFORMAT_RGB
;
654 case DRM_FORMAT_YUYV
:
655 case DRM_FORMAT_YVYU
:
656 case DRM_FORMAT_UYVY
:
657 case DRM_FORMAT_VYUY
:
658 cfg
|= EXYNOS_CITRGFMT_OUTFORMAT_YCBCR422_1PLANE
;
660 case DRM_FORMAT_NV16
:
661 case DRM_FORMAT_NV61
:
662 case DRM_FORMAT_YUV422
:
663 cfg
|= EXYNOS_CITRGFMT_OUTFORMAT_YCBCR422
;
665 case DRM_FORMAT_YUV420
:
666 case DRM_FORMAT_YVU420
:
667 case DRM_FORMAT_NV12
:
668 case DRM_FORMAT_NV21
:
669 cfg
|= EXYNOS_CITRGFMT_OUTFORMAT_YCBCR420
;
673 fimc_write(ctx
, cfg
, EXYNOS_CITRGFMT
);
676 cfg
= fimc_read(ctx
, EXYNOS_CIDMAPARAM
);
677 cfg
&= ~EXYNOS_CIDMAPARAM_W_MODE_MASK
;
680 cfg
|= EXYNOS_CIDMAPARAM_W_MODE_64X32
;
682 cfg
|= EXYNOS_CIDMAPARAM_W_MODE_LINEAR
;
684 fimc_write(ctx
, cfg
, EXYNOS_CIDMAPARAM
);
686 fimc_dst_set_fmt_order(ctx
, fmt
);
689 static void fimc_dst_set_transf(struct fimc_context
*ctx
, unsigned int rotation
)
691 unsigned int degree
= rotation
& DRM_MODE_ROTATE_MASK
;
694 DRM_DEV_DEBUG_KMS(ctx
->dev
, "rotation[0x%x]\n", rotation
);
696 cfg
= fimc_read(ctx
, EXYNOS_CITRGFMT
);
697 cfg
&= ~EXYNOS_CITRGFMT_FLIP_MASK
;
698 cfg
&= ~EXYNOS_CITRGFMT_OUTROT90_CLOCKWISE
;
701 case DRM_MODE_ROTATE_0
:
702 if (rotation
& DRM_MODE_REFLECT_X
)
703 cfg
|= EXYNOS_CITRGFMT_FLIP_X_MIRROR
;
704 if (rotation
& DRM_MODE_REFLECT_Y
)
705 cfg
|= EXYNOS_CITRGFMT_FLIP_Y_MIRROR
;
707 case DRM_MODE_ROTATE_90
:
708 cfg
|= EXYNOS_CITRGFMT_OUTROT90_CLOCKWISE
;
709 if (rotation
& DRM_MODE_REFLECT_X
)
710 cfg
|= EXYNOS_CITRGFMT_FLIP_X_MIRROR
;
711 if (rotation
& DRM_MODE_REFLECT_Y
)
712 cfg
|= EXYNOS_CITRGFMT_FLIP_Y_MIRROR
;
714 case DRM_MODE_ROTATE_180
:
715 cfg
|= (EXYNOS_CITRGFMT_FLIP_X_MIRROR
|
716 EXYNOS_CITRGFMT_FLIP_Y_MIRROR
);
717 if (rotation
& DRM_MODE_REFLECT_X
)
718 cfg
&= ~EXYNOS_CITRGFMT_FLIP_X_MIRROR
;
719 if (rotation
& DRM_MODE_REFLECT_Y
)
720 cfg
&= ~EXYNOS_CITRGFMT_FLIP_Y_MIRROR
;
722 case DRM_MODE_ROTATE_270
:
723 cfg
|= (EXYNOS_CITRGFMT_OUTROT90_CLOCKWISE
|
724 EXYNOS_CITRGFMT_FLIP_X_MIRROR
|
725 EXYNOS_CITRGFMT_FLIP_Y_MIRROR
);
726 if (rotation
& DRM_MODE_REFLECT_X
)
727 cfg
&= ~EXYNOS_CITRGFMT_FLIP_X_MIRROR
;
728 if (rotation
& DRM_MODE_REFLECT_Y
)
729 cfg
&= ~EXYNOS_CITRGFMT_FLIP_Y_MIRROR
;
733 fimc_write(ctx
, cfg
, EXYNOS_CITRGFMT
);
736 static int fimc_set_prescaler(struct fimc_context
*ctx
, struct fimc_scaler
*sc
,
737 struct drm_exynos_ipp_task_rect
*src
,
738 struct drm_exynos_ipp_task_rect
*dst
)
740 u32 cfg
, cfg_ext
, shfactor
;
741 u32 pre_dst_width
, pre_dst_height
;
742 u32 hfactor
, vfactor
;
744 u32 src_w
, src_h
, dst_w
, dst_h
;
746 cfg_ext
= fimc_read(ctx
, EXYNOS_CITRGFMT
);
747 if (cfg_ext
& EXYNOS_CITRGFMT_INROT90_CLOCKWISE
) {
755 if (cfg_ext
& EXYNOS_CITRGFMT_OUTROT90_CLOCKWISE
) {
763 /* fimc_ippdrv_check_property assures that dividers are not null */
764 hfactor
= fls(src_w
/ dst_w
/ 2);
765 if (hfactor
> FIMC_SHFACTOR
/ 2) {
766 dev_err(ctx
->dev
, "failed to get ratio horizontal.\n");
770 vfactor
= fls(src_h
/ dst_h
/ 2);
771 if (vfactor
> FIMC_SHFACTOR
/ 2) {
772 dev_err(ctx
->dev
, "failed to get ratio vertical.\n");
776 pre_dst_width
= src_w
>> hfactor
;
777 pre_dst_height
= src_h
>> vfactor
;
778 DRM_DEV_DEBUG_KMS(ctx
->dev
, "pre_dst_width[%d]pre_dst_height[%d]\n",
779 pre_dst_width
, pre_dst_height
);
780 DRM_DEV_DEBUG_KMS(ctx
->dev
, "hfactor[%d]vfactor[%d]\n", hfactor
,
783 sc
->hratio
= (src_w
<< 14) / (dst_w
<< hfactor
);
784 sc
->vratio
= (src_h
<< 14) / (dst_h
<< vfactor
);
785 sc
->up_h
= (dst_w
>= src_w
);
786 sc
->up_v
= (dst_h
>= src_h
);
787 DRM_DEV_DEBUG_KMS(ctx
->dev
, "hratio[%d]vratio[%d]up_h[%d]up_v[%d]\n",
788 sc
->hratio
, sc
->vratio
, sc
->up_h
, sc
->up_v
);
790 shfactor
= FIMC_SHFACTOR
- (hfactor
+ vfactor
);
791 DRM_DEV_DEBUG_KMS(ctx
->dev
, "shfactor[%d]\n", shfactor
);
793 cfg
= (EXYNOS_CISCPRERATIO_SHFACTOR(shfactor
) |
794 EXYNOS_CISCPRERATIO_PREHORRATIO(1 << hfactor
) |
795 EXYNOS_CISCPRERATIO_PREVERRATIO(1 << vfactor
));
796 fimc_write(ctx
, cfg
, EXYNOS_CISCPRERATIO
);
798 cfg
= (EXYNOS_CISCPREDST_PREDSTWIDTH(pre_dst_width
) |
799 EXYNOS_CISCPREDST_PREDSTHEIGHT(pre_dst_height
));
800 fimc_write(ctx
, cfg
, EXYNOS_CISCPREDST
);
805 static void fimc_set_scaler(struct fimc_context
*ctx
, struct fimc_scaler
*sc
)
809 DRM_DEV_DEBUG_KMS(ctx
->dev
, "range[%d]bypass[%d]up_h[%d]up_v[%d]\n",
810 sc
->range
, sc
->bypass
, sc
->up_h
, sc
->up_v
);
811 DRM_DEV_DEBUG_KMS(ctx
->dev
, "hratio[%d]vratio[%d]\n",
812 sc
->hratio
, sc
->vratio
);
814 cfg
= fimc_read(ctx
, EXYNOS_CISCCTRL
);
815 cfg
&= ~(EXYNOS_CISCCTRL_SCALERBYPASS
|
816 EXYNOS_CISCCTRL_SCALEUP_H
| EXYNOS_CISCCTRL_SCALEUP_V
|
817 EXYNOS_CISCCTRL_MAIN_V_RATIO_MASK
|
818 EXYNOS_CISCCTRL_MAIN_H_RATIO_MASK
|
819 EXYNOS_CISCCTRL_CSCR2Y_WIDE
|
820 EXYNOS_CISCCTRL_CSCY2R_WIDE
);
823 cfg
|= (EXYNOS_CISCCTRL_CSCR2Y_WIDE
|
824 EXYNOS_CISCCTRL_CSCY2R_WIDE
);
826 cfg
|= EXYNOS_CISCCTRL_SCALERBYPASS
;
828 cfg
|= EXYNOS_CISCCTRL_SCALEUP_H
;
830 cfg
|= EXYNOS_CISCCTRL_SCALEUP_V
;
832 cfg
|= (EXYNOS_CISCCTRL_MAINHORRATIO((sc
->hratio
>> 6)) |
833 EXYNOS_CISCCTRL_MAINVERRATIO((sc
->vratio
>> 6)));
834 fimc_write(ctx
, cfg
, EXYNOS_CISCCTRL
);
836 cfg_ext
= fimc_read(ctx
, EXYNOS_CIEXTEN
);
837 cfg_ext
&= ~EXYNOS_CIEXTEN_MAINHORRATIO_EXT_MASK
;
838 cfg_ext
&= ~EXYNOS_CIEXTEN_MAINVERRATIO_EXT_MASK
;
839 cfg_ext
|= (EXYNOS_CIEXTEN_MAINHORRATIO_EXT(sc
->hratio
) |
840 EXYNOS_CIEXTEN_MAINVERRATIO_EXT(sc
->vratio
));
841 fimc_write(ctx
, cfg_ext
, EXYNOS_CIEXTEN
);
844 static void fimc_dst_set_size(struct fimc_context
*ctx
,
845 struct exynos_drm_ipp_buffer
*buf
)
847 unsigned int real_width
= buf
->buf
.pitch
[0] / buf
->format
->cpp
[0];
850 DRM_DEV_DEBUG_KMS(ctx
->dev
, "hsize[%d]vsize[%d]\n", real_width
,
854 cfg
= (EXYNOS_ORGOSIZE_HORIZONTAL(real_width
) |
855 EXYNOS_ORGOSIZE_VERTICAL(buf
->buf
.height
));
857 fimc_write(ctx
, cfg
, EXYNOS_ORGOSIZE
);
859 DRM_DEV_DEBUG_KMS(ctx
->dev
, "x[%d]y[%d]w[%d]h[%d]\n", buf
->rect
.x
,
861 buf
->rect
.w
, buf
->rect
.h
);
864 cfg
= fimc_read(ctx
, EXYNOS_CIGCTRL
);
865 cfg
&= ~EXYNOS_CIGCTRL_CSC_MASK
;
867 if (buf
->buf
.width
>= FIMC_WIDTH_ITU_709
)
868 cfg
|= EXYNOS_CIGCTRL_CSC_ITU709
;
870 cfg
|= EXYNOS_CIGCTRL_CSC_ITU601
;
872 fimc_write(ctx
, cfg
, EXYNOS_CIGCTRL
);
874 cfg_ext
= fimc_read(ctx
, EXYNOS_CITRGFMT
);
876 /* target image size */
877 cfg
= fimc_read(ctx
, EXYNOS_CITRGFMT
);
878 cfg
&= ~(EXYNOS_CITRGFMT_TARGETH_MASK
|
879 EXYNOS_CITRGFMT_TARGETV_MASK
);
880 if (cfg_ext
& EXYNOS_CITRGFMT_OUTROT90_CLOCKWISE
)
881 cfg
|= (EXYNOS_CITRGFMT_TARGETHSIZE(buf
->rect
.h
) |
882 EXYNOS_CITRGFMT_TARGETVSIZE(buf
->rect
.w
));
884 cfg
|= (EXYNOS_CITRGFMT_TARGETHSIZE(buf
->rect
.w
) |
885 EXYNOS_CITRGFMT_TARGETVSIZE(buf
->rect
.h
));
886 fimc_write(ctx
, cfg
, EXYNOS_CITRGFMT
);
889 cfg
= EXYNOS_CITAREA_TARGET_AREA(buf
->rect
.w
* buf
->rect
.h
);
890 fimc_write(ctx
, cfg
, EXYNOS_CITAREA
);
892 /* offset Y(RGB), Cb, Cr */
893 cfg
= (EXYNOS_CIOYOFF_HORIZONTAL(buf
->rect
.x
) |
894 EXYNOS_CIOYOFF_VERTICAL(buf
->rect
.y
));
895 fimc_write(ctx
, cfg
, EXYNOS_CIOYOFF
);
896 cfg
= (EXYNOS_CIOCBOFF_HORIZONTAL(buf
->rect
.x
) |
897 EXYNOS_CIOCBOFF_VERTICAL(buf
->rect
.y
));
898 fimc_write(ctx
, cfg
, EXYNOS_CIOCBOFF
);
899 cfg
= (EXYNOS_CIOCROFF_HORIZONTAL(buf
->rect
.x
) |
900 EXYNOS_CIOCROFF_VERTICAL(buf
->rect
.y
));
901 fimc_write(ctx
, cfg
, EXYNOS_CIOCROFF
);
904 static void fimc_dst_set_buf_seq(struct fimc_context
*ctx
, u32 buf_id
,
911 DRM_DEV_DEBUG_KMS(ctx
->dev
, "buf_id[%d]enqueu[%d]\n", buf_id
, enqueue
);
913 spin_lock_irqsave(&ctx
->lock
, flags
);
915 cfg
= fimc_read(ctx
, EXYNOS_CIFCNTSEQ
);
918 cfg
|= (1 << buf_id
);
920 cfg
&= ~(1 << buf_id
);
922 fimc_write(ctx
, cfg
, EXYNOS_CIFCNTSEQ
);
924 buf_num
= hweight32(cfg
);
926 if (enqueue
&& buf_num
>= FIMC_BUF_START
)
927 fimc_mask_irq(ctx
, true);
928 else if (!enqueue
&& buf_num
<= FIMC_BUF_STOP
)
929 fimc_mask_irq(ctx
, false);
931 spin_unlock_irqrestore(&ctx
->lock
, flags
);
934 static void fimc_dst_set_addr(struct fimc_context
*ctx
,
935 struct exynos_drm_ipp_buffer
*buf
)
937 fimc_write(ctx
, buf
->dma_addr
[0], EXYNOS_CIOYSA(0));
938 fimc_write(ctx
, buf
->dma_addr
[1], EXYNOS_CIOCBSA(0));
939 fimc_write(ctx
, buf
->dma_addr
[2], EXYNOS_CIOCRSA(0));
941 fimc_dst_set_buf_seq(ctx
, 0, true);
944 static void fimc_stop(struct fimc_context
*ctx
);
946 static irqreturn_t
fimc_irq_handler(int irq
, void *dev_id
)
948 struct fimc_context
*ctx
= dev_id
;
951 DRM_DEV_DEBUG_KMS(ctx
->dev
, "fimc id[%d]\n", ctx
->id
);
954 if (fimc_check_ovf(ctx
))
957 if (!fimc_check_frame_end(ctx
))
960 buf_id
= fimc_get_buf_id(ctx
);
964 DRM_DEV_DEBUG_KMS(ctx
->dev
, "buf_id[%d]\n", buf_id
);
967 struct exynos_drm_ipp_task
*task
= ctx
->task
;
970 pm_runtime_mark_last_busy(ctx
->dev
);
971 pm_runtime_put_autosuspend(ctx
->dev
);
972 exynos_drm_ipp_task_done(task
, 0);
975 fimc_dst_set_buf_seq(ctx
, buf_id
, false);
981 static void fimc_clear_addr(struct fimc_context
*ctx
)
985 for (i
= 0; i
< FIMC_MAX_SRC
; i
++) {
986 fimc_write(ctx
, 0, EXYNOS_CIIYSA(i
));
987 fimc_write(ctx
, 0, EXYNOS_CIICBSA(i
));
988 fimc_write(ctx
, 0, EXYNOS_CIICRSA(i
));
991 for (i
= 0; i
< FIMC_MAX_DST
; i
++) {
992 fimc_write(ctx
, 0, EXYNOS_CIOYSA(i
));
993 fimc_write(ctx
, 0, EXYNOS_CIOCBSA(i
));
994 fimc_write(ctx
, 0, EXYNOS_CIOCRSA(i
));
998 static void fimc_reset(struct fimc_context
*ctx
)
1000 /* reset h/w block */
1003 /* reset scaler capability */
1004 memset(&ctx
->sc
, 0x0, sizeof(ctx
->sc
));
1006 fimc_clear_addr(ctx
);
1009 static void fimc_start(struct fimc_context
*ctx
)
1013 fimc_mask_irq(ctx
, true);
1015 /* If set true, we can save jpeg about screen */
1016 fimc_handle_jpeg(ctx
, false);
1017 fimc_set_scaler(ctx
, &ctx
->sc
);
1019 fimc_set_type_ctrl(ctx
);
1020 fimc_handle_lastend(ctx
, false);
1023 cfg0
= fimc_read(ctx
, EXYNOS_MSCTRL
);
1024 cfg0
&= ~EXYNOS_MSCTRL_INPUT_MASK
;
1025 cfg0
|= EXYNOS_MSCTRL_INPUT_MEMORY
;
1026 fimc_write(ctx
, cfg0
, EXYNOS_MSCTRL
);
1029 fimc_write(ctx
, 0x0, EXYNOS_CISTATUS
);
1031 cfg0
= fimc_read(ctx
, EXYNOS_CIIMGCPT
);
1032 cfg0
&= ~EXYNOS_CIIMGCPT_IMGCPTEN_SC
;
1033 cfg0
|= EXYNOS_CIIMGCPT_IMGCPTEN_SC
;
1036 cfg1
= fimc_read(ctx
, EXYNOS_CISCCTRL
);
1037 cfg1
&= ~EXYNOS_CISCCTRL_SCAN_MASK
;
1038 cfg1
|= (EXYNOS_CISCCTRL_PROGRESSIVE
|
1039 EXYNOS_CISCCTRL_SCALERSTART
);
1041 fimc_write(ctx
, cfg1
, EXYNOS_CISCCTRL
);
1043 /* Enable image capture*/
1044 cfg0
|= EXYNOS_CIIMGCPT_IMGCPTEN
;
1045 fimc_write(ctx
, cfg0
, EXYNOS_CIIMGCPT
);
1047 /* Disable frame end irq */
1048 fimc_clear_bits(ctx
, EXYNOS_CIGCTRL
, EXYNOS_CIGCTRL_IRQ_END_DISABLE
);
1050 fimc_clear_bits(ctx
, EXYNOS_CIOCTRL
, EXYNOS_CIOCTRL_WEAVE_MASK
);
1052 fimc_set_bits(ctx
, EXYNOS_MSCTRL
, EXYNOS_MSCTRL_ENVID
);
1055 static void fimc_stop(struct fimc_context
*ctx
)
1060 cfg
= fimc_read(ctx
, EXYNOS_MSCTRL
);
1061 cfg
&= ~EXYNOS_MSCTRL_INPUT_MASK
;
1062 cfg
&= ~EXYNOS_MSCTRL_ENVID
;
1063 fimc_write(ctx
, cfg
, EXYNOS_MSCTRL
);
1065 fimc_mask_irq(ctx
, false);
1067 /* reset sequence */
1068 fimc_write(ctx
, 0x0, EXYNOS_CIFCNTSEQ
);
1070 /* Scaler disable */
1071 fimc_clear_bits(ctx
, EXYNOS_CISCCTRL
, EXYNOS_CISCCTRL_SCALERSTART
);
1073 /* Disable image capture */
1074 fimc_clear_bits(ctx
, EXYNOS_CIIMGCPT
,
1075 EXYNOS_CIIMGCPT_IMGCPTEN_SC
| EXYNOS_CIIMGCPT_IMGCPTEN
);
1077 /* Enable frame end irq */
1078 fimc_set_bits(ctx
, EXYNOS_CIGCTRL
, EXYNOS_CIGCTRL_IRQ_END_DISABLE
);
1081 static int fimc_commit(struct exynos_drm_ipp
*ipp
,
1082 struct exynos_drm_ipp_task
*task
)
1084 struct fimc_context
*ctx
=
1085 container_of(ipp
, struct fimc_context
, ipp
);
1088 ret
= pm_runtime_resume_and_get(ctx
->dev
);
1090 dev_err(ctx
->dev
, "failed to enable FIMC device.\n");
1096 fimc_src_set_fmt(ctx
, task
->src
.buf
.fourcc
, task
->src
.buf
.modifier
);
1097 fimc_src_set_size(ctx
, &task
->src
);
1098 fimc_src_set_transf(ctx
, DRM_MODE_ROTATE_0
);
1099 fimc_src_set_addr(ctx
, &task
->src
);
1100 fimc_dst_set_fmt(ctx
, task
->dst
.buf
.fourcc
, task
->dst
.buf
.modifier
);
1101 fimc_dst_set_transf(ctx
, task
->transform
.rotation
);
1102 fimc_dst_set_size(ctx
, &task
->dst
);
1103 fimc_dst_set_addr(ctx
, &task
->dst
);
1104 fimc_set_prescaler(ctx
, &ctx
->sc
, &task
->src
.rect
, &task
->dst
.rect
);
1110 static void fimc_abort(struct exynos_drm_ipp
*ipp
,
1111 struct exynos_drm_ipp_task
*task
)
1113 struct fimc_context
*ctx
=
1114 container_of(ipp
, struct fimc_context
, ipp
);
1119 struct exynos_drm_ipp_task
*task
= ctx
->task
;
1122 pm_runtime_mark_last_busy(ctx
->dev
);
1123 pm_runtime_put_autosuspend(ctx
->dev
);
1124 exynos_drm_ipp_task_done(task
, -EIO
);
1128 static const struct exynos_drm_ipp_funcs ipp_funcs
= {
1129 .commit
= fimc_commit
,
1130 .abort
= fimc_abort
,
1133 static int fimc_bind(struct device
*dev
, struct device
*master
, void *data
)
1135 struct fimc_context
*ctx
= dev_get_drvdata(dev
);
1136 struct drm_device
*drm_dev
= data
;
1137 struct exynos_drm_ipp
*ipp
= &ctx
->ipp
;
1139 ctx
->drm_dev
= drm_dev
;
1140 ipp
->drm_dev
= drm_dev
;
1141 exynos_drm_register_dma(drm_dev
, dev
, &ctx
->dma_priv
);
1143 exynos_drm_ipp_register(dev
, ipp
, &ipp_funcs
,
1144 DRM_EXYNOS_IPP_CAP_CROP
| DRM_EXYNOS_IPP_CAP_ROTATE
|
1145 DRM_EXYNOS_IPP_CAP_SCALE
| DRM_EXYNOS_IPP_CAP_CONVERT
,
1146 ctx
->formats
, ctx
->num_formats
, "fimc");
1148 dev_info(dev
, "The exynos fimc has been probed successfully\n");
1153 static void fimc_unbind(struct device
*dev
, struct device
*master
,
1156 struct fimc_context
*ctx
= dev_get_drvdata(dev
);
1157 struct drm_device
*drm_dev
= data
;
1158 struct exynos_drm_ipp
*ipp
= &ctx
->ipp
;
1160 exynos_drm_ipp_unregister(dev
, ipp
);
1161 exynos_drm_unregister_dma(drm_dev
, dev
, &ctx
->dma_priv
);
1164 static const struct component_ops fimc_component_ops
= {
1166 .unbind
= fimc_unbind
,
1169 static void fimc_put_clocks(struct fimc_context
*ctx
)
1173 for (i
= 0; i
< FIMC_CLKS_MAX
; i
++) {
1174 if (IS_ERR(ctx
->clocks
[i
]))
1176 clk_put(ctx
->clocks
[i
]);
1177 ctx
->clocks
[i
] = ERR_PTR(-EINVAL
);
1181 static int fimc_setup_clocks(struct fimc_context
*ctx
)
1183 struct device
*fimc_dev
= ctx
->dev
;
1187 for (i
= 0; i
< FIMC_CLKS_MAX
; i
++)
1188 ctx
->clocks
[i
] = ERR_PTR(-EINVAL
);
1190 for (i
= 0; i
< FIMC_CLKS_MAX
; i
++) {
1191 if (i
== FIMC_CLK_WB_A
|| i
== FIMC_CLK_WB_B
)
1192 dev
= fimc_dev
->parent
;
1196 ctx
->clocks
[i
] = clk_get(dev
, fimc_clock_names
[i
]);
1197 if (IS_ERR(ctx
->clocks
[i
])) {
1198 ret
= PTR_ERR(ctx
->clocks
[i
]);
1199 dev_err(fimc_dev
, "failed to get clock: %s\n",
1200 fimc_clock_names
[i
]);
1205 ret
= clk_prepare_enable(ctx
->clocks
[FIMC_CLK_LCLK
]);
1209 fimc_put_clocks(ctx
);
1213 int exynos_drm_check_fimc_device(struct device
*dev
)
1215 int id
= of_alias_get_id(dev
->of_node
, "fimc");
1217 if (id
>= 0 && (BIT(id
) & fimc_mask
))
1222 static const unsigned int fimc_formats
[] = {
1223 DRM_FORMAT_XRGB8888
, DRM_FORMAT_RGB565
,
1224 DRM_FORMAT_NV12
, DRM_FORMAT_NV16
, DRM_FORMAT_NV21
, DRM_FORMAT_NV61
,
1225 DRM_FORMAT_UYVY
, DRM_FORMAT_VYUY
, DRM_FORMAT_YUYV
, DRM_FORMAT_YVYU
,
1226 DRM_FORMAT_YUV420
, DRM_FORMAT_YVU420
, DRM_FORMAT_YUV422
,
1230 static const unsigned int fimc_tiled_formats
[] = {
1231 DRM_FORMAT_NV12
, DRM_FORMAT_NV21
,
1234 static const struct drm_exynos_ipp_limit fimc_4210_limits_v1
[] = {
1235 { IPP_SIZE_LIMIT(BUFFER
, .h
= { 16, 8192, 8 }, .v
= { 16, 8192, 2 }) },
1236 { IPP_SIZE_LIMIT(AREA
, .h
= { 16, 4224, 2 }, .v
= { 16, 0, 2 }) },
1237 { IPP_SIZE_LIMIT(ROTATED
, .h
= { 128, 1920 }, .v
= { 128, 0 }) },
1238 { IPP_SCALE_LIMIT(.h
= { (1 << 16) / 64, (1 << 16) * 64 },
1239 .v
= { (1 << 16) / 64, (1 << 16) * 64 }) },
1242 static const struct drm_exynos_ipp_limit fimc_4210_limits_v2
[] = {
1243 { IPP_SIZE_LIMIT(BUFFER
, .h
= { 16, 8192, 8 }, .v
= { 16, 8192, 2 }) },
1244 { IPP_SIZE_LIMIT(AREA
, .h
= { 16, 1920, 2 }, .v
= { 16, 0, 2 }) },
1245 { IPP_SIZE_LIMIT(ROTATED
, .h
= { 128, 1366 }, .v
= { 128, 0 }) },
1246 { IPP_SCALE_LIMIT(.h
= { (1 << 16) / 64, (1 << 16) * 64 },
1247 .v
= { (1 << 16) / 64, (1 << 16) * 64 }) },
1250 static const struct drm_exynos_ipp_limit fimc_4210_limits_tiled_v1
[] = {
1251 { IPP_SIZE_LIMIT(BUFFER
, .h
= { 128, 1920, 128 }, .v
= { 32, 1920, 32 }) },
1252 { IPP_SIZE_LIMIT(AREA
, .h
= { 128, 1920, 2 }, .v
= { 128, 0, 2 }) },
1253 { IPP_SCALE_LIMIT(.h
= { (1 << 16) / 64, (1 << 16) * 64 },
1254 .v
= { (1 << 16) / 64, (1 << 16) * 64 }) },
1257 static const struct drm_exynos_ipp_limit fimc_4210_limits_tiled_v2
[] = {
1258 { IPP_SIZE_LIMIT(BUFFER
, .h
= { 128, 1920, 128 }, .v
= { 32, 1920, 32 }) },
1259 { IPP_SIZE_LIMIT(AREA
, .h
= { 128, 1366, 2 }, .v
= { 128, 0, 2 }) },
1260 { IPP_SCALE_LIMIT(.h
= { (1 << 16) / 64, (1 << 16) * 64 },
1261 .v
= { (1 << 16) / 64, (1 << 16) * 64 }) },
1264 static int fimc_probe(struct platform_device
*pdev
)
1266 const struct drm_exynos_ipp_limit
*limits
;
1267 struct exynos_drm_ipp_formats
*formats
;
1268 struct device
*dev
= &pdev
->dev
;
1269 struct fimc_context
*ctx
;
1271 int i
, j
, num_limits
, num_formats
;
1273 if (exynos_drm_check_fimc_device(dev
) != 0)
1276 ctx
= devm_kzalloc(dev
, sizeof(*ctx
), GFP_KERNEL
);
1281 ctx
->id
= of_alias_get_id(dev
->of_node
, "fimc");
1283 /* construct formats/limits array */
1284 num_formats
= ARRAY_SIZE(fimc_formats
) + ARRAY_SIZE(fimc_tiled_formats
);
1285 formats
= devm_kcalloc(dev
, num_formats
, sizeof(*formats
),
1290 /* linear formats */
1292 limits
= fimc_4210_limits_v1
;
1293 num_limits
= ARRAY_SIZE(fimc_4210_limits_v1
);
1295 limits
= fimc_4210_limits_v2
;
1296 num_limits
= ARRAY_SIZE(fimc_4210_limits_v2
);
1298 for (i
= 0; i
< ARRAY_SIZE(fimc_formats
); i
++) {
1299 formats
[i
].fourcc
= fimc_formats
[i
];
1300 formats
[i
].type
= DRM_EXYNOS_IPP_FORMAT_SOURCE
|
1301 DRM_EXYNOS_IPP_FORMAT_DESTINATION
;
1302 formats
[i
].limits
= limits
;
1303 formats
[i
].num_limits
= num_limits
;
1308 limits
= fimc_4210_limits_tiled_v1
;
1309 num_limits
= ARRAY_SIZE(fimc_4210_limits_tiled_v1
);
1311 limits
= fimc_4210_limits_tiled_v2
;
1312 num_limits
= ARRAY_SIZE(fimc_4210_limits_tiled_v2
);
1314 for (j
= i
, i
= 0; i
< ARRAY_SIZE(fimc_tiled_formats
); j
++, i
++) {
1315 formats
[j
].fourcc
= fimc_tiled_formats
[i
];
1316 formats
[j
].modifier
= DRM_FORMAT_MOD_SAMSUNG_64_32_TILE
;
1317 formats
[j
].type
= DRM_EXYNOS_IPP_FORMAT_SOURCE
|
1318 DRM_EXYNOS_IPP_FORMAT_DESTINATION
;
1319 formats
[j
].limits
= limits
;
1320 formats
[j
].num_limits
= num_limits
;
1323 ctx
->formats
= formats
;
1324 ctx
->num_formats
= num_formats
;
1326 /* resource memory */
1327 ctx
->regs
= devm_platform_ioremap_resource(pdev
, 0);
1328 if (IS_ERR(ctx
->regs
))
1329 return PTR_ERR(ctx
->regs
);
1332 ret
= platform_get_irq(pdev
, 0);
1336 ret
= devm_request_irq(dev
, ret
, fimc_irq_handler
,
1337 0, dev_name(dev
), ctx
);
1339 dev_err(dev
, "failed to request irq.\n");
1343 ret
= fimc_setup_clocks(ctx
);
1347 spin_lock_init(&ctx
->lock
);
1348 platform_set_drvdata(pdev
, ctx
);
1350 pm_runtime_use_autosuspend(dev
);
1351 pm_runtime_set_autosuspend_delay(dev
, FIMC_AUTOSUSPEND_DELAY
);
1352 pm_runtime_enable(dev
);
1354 ret
= component_add(dev
, &fimc_component_ops
);
1358 dev_info(dev
, "drm fimc registered successfully.\n");
1363 pm_runtime_dont_use_autosuspend(dev
);
1364 pm_runtime_disable(dev
);
1365 fimc_put_clocks(ctx
);
1370 static void fimc_remove(struct platform_device
*pdev
)
1372 struct device
*dev
= &pdev
->dev
;
1373 struct fimc_context
*ctx
= get_fimc_context(dev
);
1375 component_del(dev
, &fimc_component_ops
);
1376 pm_runtime_dont_use_autosuspend(dev
);
1377 pm_runtime_disable(dev
);
1379 fimc_put_clocks(ctx
);
1382 static int fimc_runtime_suspend(struct device
*dev
)
1384 struct fimc_context
*ctx
= get_fimc_context(dev
);
1386 DRM_DEV_DEBUG_KMS(dev
, "id[%d]\n", ctx
->id
);
1387 clk_disable_unprepare(ctx
->clocks
[FIMC_CLK_GATE
]);
1391 static int fimc_runtime_resume(struct device
*dev
)
1393 struct fimc_context
*ctx
= get_fimc_context(dev
);
1395 DRM_DEV_DEBUG_KMS(dev
, "id[%d]\n", ctx
->id
);
1396 return clk_prepare_enable(ctx
->clocks
[FIMC_CLK_GATE
]);
1399 static DEFINE_RUNTIME_DEV_PM_OPS(fimc_pm_ops
, fimc_runtime_suspend
,
1400 fimc_runtime_resume
, NULL
);
1402 static const struct of_device_id fimc_of_match
[] = {
1403 { .compatible
= "samsung,exynos4210-fimc" },
1404 { .compatible
= "samsung,exynos4212-fimc" },
1407 MODULE_DEVICE_TABLE(of
, fimc_of_match
);
1409 struct platform_driver fimc_driver
= {
1410 .probe
= fimc_probe
,
1411 .remove
= fimc_remove
,
1413 .of_match_table
= fimc_of_match
,
1414 .name
= "exynos-drm-fimc",
1415 .pm
= pm_ptr(&fimc_pm_ops
),