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>
9 #include <linux/kernel.h>
10 #include <linux/component.h>
11 #include <linux/platform_device.h>
12 #include <linux/mfd/syscon.h>
13 #include <linux/regmap.h>
14 #include <linux/clk.h>
15 #include <linux/pm_runtime.h>
17 #include <linux/spinlock.h>
20 #include <drm/exynos_drm.h>
21 #include "regs-fimc.h"
22 #include "exynos_drm_drv.h"
23 #include "exynos_drm_ipp.h"
26 * FIMC stands for Fully Interactive Mobile Camera and
27 * supports image scaler/rotator and input/output DMA operations.
28 * input DMA reads image data from the memory.
29 * output DMA writes image data to memory.
30 * FIMC supports image rotation and image effect functions.
33 #define FIMC_MAX_DEVS 4
34 #define FIMC_MAX_SRC 2
35 #define FIMC_MAX_DST 32
36 #define FIMC_SHFACTOR 10
37 #define FIMC_BUF_STOP 1
38 #define FIMC_BUF_START 2
39 #define FIMC_WIDTH_ITU_709 1280
40 #define FIMC_AUTOSUSPEND_DELAY 2000
42 static unsigned int fimc_mask
= 0xc;
43 module_param_named(fimc_devs
, fimc_mask
, uint
, 0644);
44 MODULE_PARM_DESC(fimc_devs
, "Alias mask for assigning FIMC devices to Exynos DRM");
46 #define get_fimc_context(dev) platform_get_drvdata(to_platform_device(dev))
56 static const char * const fimc_clock_names
[] = {
57 [FIMC_CLK_LCLK
] = "sclk_fimc",
58 [FIMC_CLK_GATE
] = "fimc",
59 [FIMC_CLK_WB_A
] = "pxl_async0",
60 [FIMC_CLK_WB_B
] = "pxl_async1",
64 * A structure of scaler.
66 * @range: narrow, wide.
67 * @bypass: unused scaler path.
68 * @up_h: horizontal scale up.
69 * @up_v: vertical scale up.
70 * @hratio: horizontal ratio.
71 * @vratio: vertical ratio.
83 * A structure of fimc context.
85 * @regs_res: register resources.
86 * @regs: memory mapped io registers.
87 * @lock: locking of operations.
88 * @clocks: fimc clocks.
89 * @sc: scaler infomations.
90 * @pol: porarity of writeback.
95 struct exynos_drm_ipp ipp
;
96 struct drm_device
*drm_dev
;
98 struct exynos_drm_ipp_task
*task
;
99 struct exynos_drm_ipp_formats
*formats
;
100 unsigned int num_formats
;
102 struct resource
*regs_res
;
105 struct clk
*clocks
[FIMC_CLKS_MAX
];
106 struct fimc_scaler sc
;
111 static u32
fimc_read(struct fimc_context
*ctx
, u32 reg
)
113 return readl(ctx
->regs
+ reg
);
116 static void fimc_write(struct fimc_context
*ctx
, u32 val
, u32 reg
)
118 writel(val
, ctx
->regs
+ reg
);
121 static void fimc_set_bits(struct fimc_context
*ctx
, u32 reg
, u32 bits
)
123 void __iomem
*r
= ctx
->regs
+ reg
;
125 writel(readl(r
) | bits
, r
);
128 static void fimc_clear_bits(struct fimc_context
*ctx
, u32 reg
, u32 bits
)
130 void __iomem
*r
= ctx
->regs
+ reg
;
132 writel(readl(r
) & ~bits
, r
);
135 static void fimc_sw_reset(struct fimc_context
*ctx
)
139 /* stop dma operation */
140 cfg
= fimc_read(ctx
, EXYNOS_CISTATUS
);
141 if (EXYNOS_CISTATUS_GET_ENVID_STATUS(cfg
))
142 fimc_clear_bits(ctx
, EXYNOS_MSCTRL
, EXYNOS_MSCTRL_ENVID
);
144 fimc_set_bits(ctx
, EXYNOS_CISRCFMT
, EXYNOS_CISRCFMT_ITU601_8BIT
);
146 /* disable image capture */
147 fimc_clear_bits(ctx
, EXYNOS_CIIMGCPT
,
148 EXYNOS_CIIMGCPT_IMGCPTEN_SC
| EXYNOS_CIIMGCPT_IMGCPTEN
);
151 fimc_set_bits(ctx
, EXYNOS_CIGCTRL
, EXYNOS_CIGCTRL_SWRST
);
153 /* s/w reset complete */
154 fimc_clear_bits(ctx
, EXYNOS_CIGCTRL
, EXYNOS_CIGCTRL_SWRST
);
157 fimc_write(ctx
, 0x0, EXYNOS_CIFCNTSEQ
);
160 static void fimc_set_type_ctrl(struct fimc_context
*ctx
)
164 cfg
= fimc_read(ctx
, EXYNOS_CIGCTRL
);
165 cfg
&= ~(EXYNOS_CIGCTRL_TESTPATTERN_MASK
|
166 EXYNOS_CIGCTRL_SELCAM_ITU_MASK
|
167 EXYNOS_CIGCTRL_SELCAM_MIPI_MASK
|
168 EXYNOS_CIGCTRL_SELCAM_FIMC_MASK
|
169 EXYNOS_CIGCTRL_SELWB_CAMIF_MASK
|
170 EXYNOS_CIGCTRL_SELWRITEBACK_MASK
);
172 cfg
|= (EXYNOS_CIGCTRL_SELCAM_ITU_A
|
173 EXYNOS_CIGCTRL_SELWRITEBACK_A
|
174 EXYNOS_CIGCTRL_SELCAM_MIPI_A
|
175 EXYNOS_CIGCTRL_SELCAM_FIMC_ITU
);
177 fimc_write(ctx
, cfg
, EXYNOS_CIGCTRL
);
180 static void fimc_handle_jpeg(struct fimc_context
*ctx
, bool enable
)
184 DRM_DEV_DEBUG_KMS(ctx
->dev
, "enable[%d]\n", enable
);
186 cfg
= fimc_read(ctx
, EXYNOS_CIGCTRL
);
188 cfg
|= EXYNOS_CIGCTRL_CAM_JPEG
;
190 cfg
&= ~EXYNOS_CIGCTRL_CAM_JPEG
;
192 fimc_write(ctx
, cfg
, EXYNOS_CIGCTRL
);
195 static void fimc_mask_irq(struct fimc_context
*ctx
, bool enable
)
199 DRM_DEV_DEBUG_KMS(ctx
->dev
, "enable[%d]\n", enable
);
201 cfg
= fimc_read(ctx
, EXYNOS_CIGCTRL
);
203 cfg
&= ~EXYNOS_CIGCTRL_IRQ_OVFEN
;
204 cfg
|= EXYNOS_CIGCTRL_IRQ_ENABLE
| EXYNOS_CIGCTRL_IRQ_LEVEL
;
206 cfg
&= ~EXYNOS_CIGCTRL_IRQ_ENABLE
;
207 fimc_write(ctx
, cfg
, EXYNOS_CIGCTRL
);
210 static void fimc_clear_irq(struct fimc_context
*ctx
)
212 fimc_set_bits(ctx
, EXYNOS_CIGCTRL
, EXYNOS_CIGCTRL_IRQ_CLR
);
215 static bool fimc_check_ovf(struct fimc_context
*ctx
)
219 status
= fimc_read(ctx
, EXYNOS_CISTATUS
);
220 flag
= EXYNOS_CISTATUS_OVFIY
| EXYNOS_CISTATUS_OVFICB
|
221 EXYNOS_CISTATUS_OVFICR
;
223 DRM_DEV_DEBUG_KMS(ctx
->dev
, "flag[0x%x]\n", flag
);
226 fimc_set_bits(ctx
, EXYNOS_CIWDOFST
,
227 EXYNOS_CIWDOFST_CLROVFIY
| EXYNOS_CIWDOFST_CLROVFICB
|
228 EXYNOS_CIWDOFST_CLROVFICR
);
230 DRM_DEV_ERROR(ctx
->dev
,
231 "occurred overflow at %d, status 0x%x.\n",
239 static bool fimc_check_frame_end(struct fimc_context
*ctx
)
243 cfg
= fimc_read(ctx
, EXYNOS_CISTATUS
);
245 DRM_DEV_DEBUG_KMS(ctx
->dev
, "cfg[0x%x]\n", cfg
);
247 if (!(cfg
& EXYNOS_CISTATUS_FRAMEEND
))
250 cfg
&= ~(EXYNOS_CISTATUS_FRAMEEND
);
251 fimc_write(ctx
, cfg
, EXYNOS_CISTATUS
);
256 static int fimc_get_buf_id(struct fimc_context
*ctx
)
259 int frame_cnt
, buf_id
;
261 cfg
= fimc_read(ctx
, EXYNOS_CISTATUS2
);
262 frame_cnt
= EXYNOS_CISTATUS2_GET_FRAMECOUNT_BEFORE(cfg
);
265 frame_cnt
= EXYNOS_CISTATUS2_GET_FRAMECOUNT_PRESENT(cfg
);
267 DRM_DEV_DEBUG_KMS(ctx
->dev
, "present[%d]before[%d]\n",
268 EXYNOS_CISTATUS2_GET_FRAMECOUNT_PRESENT(cfg
),
269 EXYNOS_CISTATUS2_GET_FRAMECOUNT_BEFORE(cfg
));
271 if (frame_cnt
== 0) {
272 DRM_DEV_ERROR(ctx
->dev
, "failed to get frame count.\n");
276 buf_id
= frame_cnt
- 1;
277 DRM_DEV_DEBUG_KMS(ctx
->dev
, "buf_id[%d]\n", buf_id
);
282 static void fimc_handle_lastend(struct fimc_context
*ctx
, bool enable
)
286 DRM_DEV_DEBUG_KMS(ctx
->dev
, "enable[%d]\n", enable
);
288 cfg
= fimc_read(ctx
, EXYNOS_CIOCTRL
);
290 cfg
|= EXYNOS_CIOCTRL_LASTENDEN
;
292 cfg
&= ~EXYNOS_CIOCTRL_LASTENDEN
;
294 fimc_write(ctx
, cfg
, EXYNOS_CIOCTRL
);
297 static void fimc_src_set_fmt_order(struct fimc_context
*ctx
, u32 fmt
)
301 DRM_DEV_DEBUG_KMS(ctx
->dev
, "fmt[0x%x]\n", fmt
);
304 cfg
= fimc_read(ctx
, EXYNOS_CISCCTRL
);
305 cfg
&= ~EXYNOS_CISCCTRL_INRGB_FMT_RGB_MASK
;
308 case DRM_FORMAT_RGB565
:
309 cfg
|= EXYNOS_CISCCTRL_INRGB_FMT_RGB565
;
310 fimc_write(ctx
, cfg
, EXYNOS_CISCCTRL
);
312 case DRM_FORMAT_RGB888
:
313 case DRM_FORMAT_XRGB8888
:
314 cfg
|= EXYNOS_CISCCTRL_INRGB_FMT_RGB888
;
315 fimc_write(ctx
, cfg
, EXYNOS_CISCCTRL
);
323 cfg
= fimc_read(ctx
, EXYNOS_MSCTRL
);
324 cfg
&= ~(EXYNOS_MSCTRL_ORDER2P_SHIFT_MASK
|
325 EXYNOS_MSCTRL_C_INT_IN_2PLANE
|
326 EXYNOS_MSCTRL_ORDER422_YCBYCR
);
329 case DRM_FORMAT_YUYV
:
330 cfg
|= EXYNOS_MSCTRL_ORDER422_YCBYCR
;
332 case DRM_FORMAT_YVYU
:
333 cfg
|= EXYNOS_MSCTRL_ORDER422_YCRYCB
;
335 case DRM_FORMAT_UYVY
:
336 cfg
|= EXYNOS_MSCTRL_ORDER422_CBYCRY
;
338 case DRM_FORMAT_VYUY
:
339 case DRM_FORMAT_YUV444
:
340 cfg
|= EXYNOS_MSCTRL_ORDER422_CRYCBY
;
342 case DRM_FORMAT_NV21
:
343 case DRM_FORMAT_NV61
:
344 cfg
|= (EXYNOS_MSCTRL_ORDER2P_LSB_CRCB
|
345 EXYNOS_MSCTRL_C_INT_IN_2PLANE
);
347 case DRM_FORMAT_YUV422
:
348 case DRM_FORMAT_YUV420
:
349 case DRM_FORMAT_YVU420
:
350 cfg
|= EXYNOS_MSCTRL_C_INT_IN_3PLANE
;
352 case DRM_FORMAT_NV12
:
353 case DRM_FORMAT_NV16
:
354 cfg
|= (EXYNOS_MSCTRL_ORDER2P_LSB_CBCR
|
355 EXYNOS_MSCTRL_C_INT_IN_2PLANE
);
359 fimc_write(ctx
, cfg
, EXYNOS_MSCTRL
);
362 static void fimc_src_set_fmt(struct fimc_context
*ctx
, u32 fmt
, bool tiled
)
366 DRM_DEV_DEBUG_KMS(ctx
->dev
, "fmt[0x%x]\n", fmt
);
368 cfg
= fimc_read(ctx
, EXYNOS_MSCTRL
);
369 cfg
&= ~EXYNOS_MSCTRL_INFORMAT_RGB
;
372 case DRM_FORMAT_RGB565
:
373 case DRM_FORMAT_RGB888
:
374 case DRM_FORMAT_XRGB8888
:
375 cfg
|= EXYNOS_MSCTRL_INFORMAT_RGB
;
377 case DRM_FORMAT_YUV444
:
378 cfg
|= EXYNOS_MSCTRL_INFORMAT_YCBCR420
;
380 case DRM_FORMAT_YUYV
:
381 case DRM_FORMAT_YVYU
:
382 case DRM_FORMAT_UYVY
:
383 case DRM_FORMAT_VYUY
:
384 cfg
|= EXYNOS_MSCTRL_INFORMAT_YCBCR422_1PLANE
;
386 case DRM_FORMAT_NV16
:
387 case DRM_FORMAT_NV61
:
388 case DRM_FORMAT_YUV422
:
389 cfg
|= EXYNOS_MSCTRL_INFORMAT_YCBCR422
;
391 case DRM_FORMAT_YUV420
:
392 case DRM_FORMAT_YVU420
:
393 case DRM_FORMAT_NV12
:
394 case DRM_FORMAT_NV21
:
395 cfg
|= EXYNOS_MSCTRL_INFORMAT_YCBCR420
;
399 fimc_write(ctx
, cfg
, EXYNOS_MSCTRL
);
401 cfg
= fimc_read(ctx
, EXYNOS_CIDMAPARAM
);
402 cfg
&= ~EXYNOS_CIDMAPARAM_R_MODE_MASK
;
405 cfg
|= EXYNOS_CIDMAPARAM_R_MODE_64X32
;
407 cfg
|= EXYNOS_CIDMAPARAM_R_MODE_LINEAR
;
409 fimc_write(ctx
, cfg
, EXYNOS_CIDMAPARAM
);
411 fimc_src_set_fmt_order(ctx
, fmt
);
414 static void fimc_src_set_transf(struct fimc_context
*ctx
, unsigned int rotation
)
416 unsigned int degree
= rotation
& DRM_MODE_ROTATE_MASK
;
419 DRM_DEV_DEBUG_KMS(ctx
->dev
, "rotation[%x]\n", rotation
);
421 cfg1
= fimc_read(ctx
, EXYNOS_MSCTRL
);
422 cfg1
&= ~(EXYNOS_MSCTRL_FLIP_X_MIRROR
|
423 EXYNOS_MSCTRL_FLIP_Y_MIRROR
);
425 cfg2
= fimc_read(ctx
, EXYNOS_CITRGFMT
);
426 cfg2
&= ~EXYNOS_CITRGFMT_INROT90_CLOCKWISE
;
429 case DRM_MODE_ROTATE_0
:
430 if (rotation
& DRM_MODE_REFLECT_X
)
431 cfg1
|= EXYNOS_MSCTRL_FLIP_X_MIRROR
;
432 if (rotation
& DRM_MODE_REFLECT_Y
)
433 cfg1
|= EXYNOS_MSCTRL_FLIP_Y_MIRROR
;
435 case DRM_MODE_ROTATE_90
:
436 cfg2
|= EXYNOS_CITRGFMT_INROT90_CLOCKWISE
;
437 if (rotation
& DRM_MODE_REFLECT_X
)
438 cfg1
|= EXYNOS_MSCTRL_FLIP_X_MIRROR
;
439 if (rotation
& DRM_MODE_REFLECT_Y
)
440 cfg1
|= EXYNOS_MSCTRL_FLIP_Y_MIRROR
;
442 case DRM_MODE_ROTATE_180
:
443 cfg1
|= (EXYNOS_MSCTRL_FLIP_X_MIRROR
|
444 EXYNOS_MSCTRL_FLIP_Y_MIRROR
);
445 if (rotation
& DRM_MODE_REFLECT_X
)
446 cfg1
&= ~EXYNOS_MSCTRL_FLIP_X_MIRROR
;
447 if (rotation
& DRM_MODE_REFLECT_Y
)
448 cfg1
&= ~EXYNOS_MSCTRL_FLIP_Y_MIRROR
;
450 case DRM_MODE_ROTATE_270
:
451 cfg1
|= (EXYNOS_MSCTRL_FLIP_X_MIRROR
|
452 EXYNOS_MSCTRL_FLIP_Y_MIRROR
);
453 cfg2
|= EXYNOS_CITRGFMT_INROT90_CLOCKWISE
;
454 if (rotation
& DRM_MODE_REFLECT_X
)
455 cfg1
&= ~EXYNOS_MSCTRL_FLIP_X_MIRROR
;
456 if (rotation
& DRM_MODE_REFLECT_Y
)
457 cfg1
&= ~EXYNOS_MSCTRL_FLIP_Y_MIRROR
;
461 fimc_write(ctx
, cfg1
, EXYNOS_MSCTRL
);
462 fimc_write(ctx
, cfg2
, EXYNOS_CITRGFMT
);
465 static void fimc_set_window(struct fimc_context
*ctx
,
466 struct exynos_drm_ipp_buffer
*buf
)
468 unsigned int real_width
= buf
->buf
.pitch
[0] / buf
->format
->cpp
[0];
469 u32 cfg
, h1
, h2
, v1
, v2
;
473 h2
= real_width
- buf
->rect
.w
- buf
->rect
.x
;
475 v2
= buf
->buf
.height
- buf
->rect
.h
- buf
->rect
.y
;
477 DRM_DEV_DEBUG_KMS(ctx
->dev
, "x[%d]y[%d]w[%d]h[%d]hsize[%d]vsize[%d]\n",
478 buf
->rect
.x
, buf
->rect
.y
, buf
->rect
.w
, buf
->rect
.h
,
479 real_width
, buf
->buf
.height
);
480 DRM_DEV_DEBUG_KMS(ctx
->dev
, "h1[%d]h2[%d]v1[%d]v2[%d]\n", h1
, h2
, v1
,
484 * set window offset 1, 2 size
485 * check figure 43-21 in user manual
487 cfg
= fimc_read(ctx
, EXYNOS_CIWDOFST
);
488 cfg
&= ~(EXYNOS_CIWDOFST_WINHOROFST_MASK
|
489 EXYNOS_CIWDOFST_WINVEROFST_MASK
);
490 cfg
|= (EXYNOS_CIWDOFST_WINHOROFST(h1
) |
491 EXYNOS_CIWDOFST_WINVEROFST(v1
));
492 cfg
|= EXYNOS_CIWDOFST_WINOFSEN
;
493 fimc_write(ctx
, cfg
, EXYNOS_CIWDOFST
);
495 cfg
= (EXYNOS_CIWDOFST2_WINHOROFST2(h2
) |
496 EXYNOS_CIWDOFST2_WINVEROFST2(v2
));
497 fimc_write(ctx
, cfg
, EXYNOS_CIWDOFST2
);
500 static void fimc_src_set_size(struct fimc_context
*ctx
,
501 struct exynos_drm_ipp_buffer
*buf
)
503 unsigned int real_width
= buf
->buf
.pitch
[0] / buf
->format
->cpp
[0];
506 DRM_DEV_DEBUG_KMS(ctx
->dev
, "hsize[%d]vsize[%d]\n", real_width
,
510 cfg
= (EXYNOS_ORGISIZE_HORIZONTAL(real_width
) |
511 EXYNOS_ORGISIZE_VERTICAL(buf
->buf
.height
));
513 fimc_write(ctx
, cfg
, EXYNOS_ORGISIZE
);
515 DRM_DEV_DEBUG_KMS(ctx
->dev
, "x[%d]y[%d]w[%d]h[%d]\n", buf
->rect
.x
,
516 buf
->rect
.y
, buf
->rect
.w
, buf
->rect
.h
);
518 /* set input DMA image size */
519 cfg
= fimc_read(ctx
, EXYNOS_CIREAL_ISIZE
);
520 cfg
&= ~(EXYNOS_CIREAL_ISIZE_HEIGHT_MASK
|
521 EXYNOS_CIREAL_ISIZE_WIDTH_MASK
);
522 cfg
|= (EXYNOS_CIREAL_ISIZE_WIDTH(buf
->rect
.w
) |
523 EXYNOS_CIREAL_ISIZE_HEIGHT(buf
->rect
.h
));
524 fimc_write(ctx
, cfg
, EXYNOS_CIREAL_ISIZE
);
527 * set input FIFO image size
528 * for now, we support only ITU601 8 bit mode
530 cfg
= (EXYNOS_CISRCFMT_ITU601_8BIT
|
531 EXYNOS_CISRCFMT_SOURCEHSIZE(real_width
) |
532 EXYNOS_CISRCFMT_SOURCEVSIZE(buf
->buf
.height
));
533 fimc_write(ctx
, cfg
, EXYNOS_CISRCFMT
);
535 /* offset Y(RGB), Cb, Cr */
536 cfg
= (EXYNOS_CIIYOFF_HORIZONTAL(buf
->rect
.x
) |
537 EXYNOS_CIIYOFF_VERTICAL(buf
->rect
.y
));
538 fimc_write(ctx
, cfg
, EXYNOS_CIIYOFF
);
539 cfg
= (EXYNOS_CIICBOFF_HORIZONTAL(buf
->rect
.x
) |
540 EXYNOS_CIICBOFF_VERTICAL(buf
->rect
.y
));
541 fimc_write(ctx
, cfg
, EXYNOS_CIICBOFF
);
542 cfg
= (EXYNOS_CIICROFF_HORIZONTAL(buf
->rect
.x
) |
543 EXYNOS_CIICROFF_VERTICAL(buf
->rect
.y
));
544 fimc_write(ctx
, cfg
, EXYNOS_CIICROFF
);
546 fimc_set_window(ctx
, buf
);
549 static void fimc_src_set_addr(struct fimc_context
*ctx
,
550 struct exynos_drm_ipp_buffer
*buf
)
552 fimc_write(ctx
, buf
->dma_addr
[0], EXYNOS_CIIYSA(0));
553 fimc_write(ctx
, buf
->dma_addr
[1], EXYNOS_CIICBSA(0));
554 fimc_write(ctx
, buf
->dma_addr
[2], EXYNOS_CIICRSA(0));
557 static void fimc_dst_set_fmt_order(struct fimc_context
*ctx
, u32 fmt
)
561 DRM_DEV_DEBUG_KMS(ctx
->dev
, "fmt[0x%x]\n", fmt
);
564 cfg
= fimc_read(ctx
, EXYNOS_CISCCTRL
);
565 cfg
&= ~EXYNOS_CISCCTRL_OUTRGB_FMT_RGB_MASK
;
568 case DRM_FORMAT_RGB565
:
569 cfg
|= EXYNOS_CISCCTRL_OUTRGB_FMT_RGB565
;
570 fimc_write(ctx
, cfg
, EXYNOS_CISCCTRL
);
572 case DRM_FORMAT_RGB888
:
573 cfg
|= EXYNOS_CISCCTRL_OUTRGB_FMT_RGB888
;
574 fimc_write(ctx
, cfg
, EXYNOS_CISCCTRL
);
576 case DRM_FORMAT_XRGB8888
:
577 cfg
|= (EXYNOS_CISCCTRL_OUTRGB_FMT_RGB888
|
578 EXYNOS_CISCCTRL_EXTRGB_EXTENSION
);
579 fimc_write(ctx
, cfg
, EXYNOS_CISCCTRL
);
587 cfg
= fimc_read(ctx
, EXYNOS_CIOCTRL
);
588 cfg
&= ~(EXYNOS_CIOCTRL_ORDER2P_MASK
|
589 EXYNOS_CIOCTRL_ORDER422_MASK
|
590 EXYNOS_CIOCTRL_YCBCR_PLANE_MASK
);
593 case DRM_FORMAT_XRGB8888
:
594 cfg
|= EXYNOS_CIOCTRL_ALPHA_OUT
;
596 case DRM_FORMAT_YUYV
:
597 cfg
|= EXYNOS_CIOCTRL_ORDER422_YCBYCR
;
599 case DRM_FORMAT_YVYU
:
600 cfg
|= EXYNOS_CIOCTRL_ORDER422_YCRYCB
;
602 case DRM_FORMAT_UYVY
:
603 cfg
|= EXYNOS_CIOCTRL_ORDER422_CBYCRY
;
605 case DRM_FORMAT_VYUY
:
606 cfg
|= EXYNOS_CIOCTRL_ORDER422_CRYCBY
;
608 case DRM_FORMAT_NV21
:
609 case DRM_FORMAT_NV61
:
610 cfg
|= EXYNOS_CIOCTRL_ORDER2P_LSB_CRCB
;
611 cfg
|= EXYNOS_CIOCTRL_YCBCR_2PLANE
;
613 case DRM_FORMAT_YUV422
:
614 case DRM_FORMAT_YUV420
:
615 case DRM_FORMAT_YVU420
:
616 cfg
|= EXYNOS_CIOCTRL_YCBCR_3PLANE
;
618 case DRM_FORMAT_NV12
:
619 case DRM_FORMAT_NV16
:
620 cfg
|= EXYNOS_CIOCTRL_ORDER2P_LSB_CBCR
;
621 cfg
|= EXYNOS_CIOCTRL_YCBCR_2PLANE
;
625 fimc_write(ctx
, cfg
, EXYNOS_CIOCTRL
);
628 static void fimc_dst_set_fmt(struct fimc_context
*ctx
, u32 fmt
, bool tiled
)
632 DRM_DEV_DEBUG_KMS(ctx
->dev
, "fmt[0x%x]\n", fmt
);
634 cfg
= fimc_read(ctx
, EXYNOS_CIEXTEN
);
636 if (fmt
== DRM_FORMAT_AYUV
) {
637 cfg
|= EXYNOS_CIEXTEN_YUV444_OUT
;
638 fimc_write(ctx
, cfg
, EXYNOS_CIEXTEN
);
640 cfg
&= ~EXYNOS_CIEXTEN_YUV444_OUT
;
641 fimc_write(ctx
, cfg
, EXYNOS_CIEXTEN
);
643 cfg
= fimc_read(ctx
, EXYNOS_CITRGFMT
);
644 cfg
&= ~EXYNOS_CITRGFMT_OUTFORMAT_MASK
;
647 case DRM_FORMAT_RGB565
:
648 case DRM_FORMAT_RGB888
:
649 case DRM_FORMAT_XRGB8888
:
650 cfg
|= EXYNOS_CITRGFMT_OUTFORMAT_RGB
;
652 case DRM_FORMAT_YUYV
:
653 case DRM_FORMAT_YVYU
:
654 case DRM_FORMAT_UYVY
:
655 case DRM_FORMAT_VYUY
:
656 cfg
|= EXYNOS_CITRGFMT_OUTFORMAT_YCBCR422_1PLANE
;
658 case DRM_FORMAT_NV16
:
659 case DRM_FORMAT_NV61
:
660 case DRM_FORMAT_YUV422
:
661 cfg
|= EXYNOS_CITRGFMT_OUTFORMAT_YCBCR422
;
663 case DRM_FORMAT_YUV420
:
664 case DRM_FORMAT_YVU420
:
665 case DRM_FORMAT_NV12
:
666 case DRM_FORMAT_NV21
:
667 cfg
|= EXYNOS_CITRGFMT_OUTFORMAT_YCBCR420
;
671 fimc_write(ctx
, cfg
, EXYNOS_CITRGFMT
);
674 cfg
= fimc_read(ctx
, EXYNOS_CIDMAPARAM
);
675 cfg
&= ~EXYNOS_CIDMAPARAM_W_MODE_MASK
;
678 cfg
|= EXYNOS_CIDMAPARAM_W_MODE_64X32
;
680 cfg
|= EXYNOS_CIDMAPARAM_W_MODE_LINEAR
;
682 fimc_write(ctx
, cfg
, EXYNOS_CIDMAPARAM
);
684 fimc_dst_set_fmt_order(ctx
, fmt
);
687 static void fimc_dst_set_transf(struct fimc_context
*ctx
, unsigned int rotation
)
689 unsigned int degree
= rotation
& DRM_MODE_ROTATE_MASK
;
692 DRM_DEV_DEBUG_KMS(ctx
->dev
, "rotation[0x%x]\n", rotation
);
694 cfg
= fimc_read(ctx
, EXYNOS_CITRGFMT
);
695 cfg
&= ~EXYNOS_CITRGFMT_FLIP_MASK
;
696 cfg
&= ~EXYNOS_CITRGFMT_OUTROT90_CLOCKWISE
;
699 case DRM_MODE_ROTATE_0
:
700 if (rotation
& DRM_MODE_REFLECT_X
)
701 cfg
|= EXYNOS_CITRGFMT_FLIP_X_MIRROR
;
702 if (rotation
& DRM_MODE_REFLECT_Y
)
703 cfg
|= EXYNOS_CITRGFMT_FLIP_Y_MIRROR
;
705 case DRM_MODE_ROTATE_90
:
706 cfg
|= EXYNOS_CITRGFMT_OUTROT90_CLOCKWISE
;
707 if (rotation
& DRM_MODE_REFLECT_X
)
708 cfg
|= EXYNOS_CITRGFMT_FLIP_X_MIRROR
;
709 if (rotation
& DRM_MODE_REFLECT_Y
)
710 cfg
|= EXYNOS_CITRGFMT_FLIP_Y_MIRROR
;
712 case DRM_MODE_ROTATE_180
:
713 cfg
|= (EXYNOS_CITRGFMT_FLIP_X_MIRROR
|
714 EXYNOS_CITRGFMT_FLIP_Y_MIRROR
);
715 if (rotation
& DRM_MODE_REFLECT_X
)
716 cfg
&= ~EXYNOS_CITRGFMT_FLIP_X_MIRROR
;
717 if (rotation
& DRM_MODE_REFLECT_Y
)
718 cfg
&= ~EXYNOS_CITRGFMT_FLIP_Y_MIRROR
;
720 case DRM_MODE_ROTATE_270
:
721 cfg
|= (EXYNOS_CITRGFMT_OUTROT90_CLOCKWISE
|
722 EXYNOS_CITRGFMT_FLIP_X_MIRROR
|
723 EXYNOS_CITRGFMT_FLIP_Y_MIRROR
);
724 if (rotation
& DRM_MODE_REFLECT_X
)
725 cfg
&= ~EXYNOS_CITRGFMT_FLIP_X_MIRROR
;
726 if (rotation
& DRM_MODE_REFLECT_Y
)
727 cfg
&= ~EXYNOS_CITRGFMT_FLIP_Y_MIRROR
;
731 fimc_write(ctx
, cfg
, EXYNOS_CITRGFMT
);
734 static int fimc_set_prescaler(struct fimc_context
*ctx
, struct fimc_scaler
*sc
,
735 struct drm_exynos_ipp_task_rect
*src
,
736 struct drm_exynos_ipp_task_rect
*dst
)
738 u32 cfg
, cfg_ext
, shfactor
;
739 u32 pre_dst_width
, pre_dst_height
;
740 u32 hfactor
, vfactor
;
742 u32 src_w
, src_h
, dst_w
, dst_h
;
744 cfg_ext
= fimc_read(ctx
, EXYNOS_CITRGFMT
);
745 if (cfg_ext
& EXYNOS_CITRGFMT_INROT90_CLOCKWISE
) {
753 if (cfg_ext
& EXYNOS_CITRGFMT_OUTROT90_CLOCKWISE
) {
761 /* fimc_ippdrv_check_property assures that dividers are not null */
762 hfactor
= fls(src_w
/ dst_w
/ 2);
763 if (hfactor
> FIMC_SHFACTOR
/ 2) {
764 dev_err(ctx
->dev
, "failed to get ratio horizontal.\n");
768 vfactor
= fls(src_h
/ dst_h
/ 2);
769 if (vfactor
> FIMC_SHFACTOR
/ 2) {
770 dev_err(ctx
->dev
, "failed to get ratio vertical.\n");
774 pre_dst_width
= src_w
>> hfactor
;
775 pre_dst_height
= src_h
>> vfactor
;
776 DRM_DEV_DEBUG_KMS(ctx
->dev
, "pre_dst_width[%d]pre_dst_height[%d]\n",
777 pre_dst_width
, pre_dst_height
);
778 DRM_DEV_DEBUG_KMS(ctx
->dev
, "hfactor[%d]vfactor[%d]\n", hfactor
,
781 sc
->hratio
= (src_w
<< 14) / (dst_w
<< hfactor
);
782 sc
->vratio
= (src_h
<< 14) / (dst_h
<< vfactor
);
783 sc
->up_h
= (dst_w
>= src_w
) ? true : false;
784 sc
->up_v
= (dst_h
>= src_h
) ? true : false;
785 DRM_DEV_DEBUG_KMS(ctx
->dev
, "hratio[%d]vratio[%d]up_h[%d]up_v[%d]\n",
786 sc
->hratio
, sc
->vratio
, sc
->up_h
, sc
->up_v
);
788 shfactor
= FIMC_SHFACTOR
- (hfactor
+ vfactor
);
789 DRM_DEV_DEBUG_KMS(ctx
->dev
, "shfactor[%d]\n", shfactor
);
791 cfg
= (EXYNOS_CISCPRERATIO_SHFACTOR(shfactor
) |
792 EXYNOS_CISCPRERATIO_PREHORRATIO(1 << hfactor
) |
793 EXYNOS_CISCPRERATIO_PREVERRATIO(1 << vfactor
));
794 fimc_write(ctx
, cfg
, EXYNOS_CISCPRERATIO
);
796 cfg
= (EXYNOS_CISCPREDST_PREDSTWIDTH(pre_dst_width
) |
797 EXYNOS_CISCPREDST_PREDSTHEIGHT(pre_dst_height
));
798 fimc_write(ctx
, cfg
, EXYNOS_CISCPREDST
);
803 static void fimc_set_scaler(struct fimc_context
*ctx
, struct fimc_scaler
*sc
)
807 DRM_DEV_DEBUG_KMS(ctx
->dev
, "range[%d]bypass[%d]up_h[%d]up_v[%d]\n",
808 sc
->range
, sc
->bypass
, sc
->up_h
, sc
->up_v
);
809 DRM_DEV_DEBUG_KMS(ctx
->dev
, "hratio[%d]vratio[%d]\n",
810 sc
->hratio
, sc
->vratio
);
812 cfg
= fimc_read(ctx
, EXYNOS_CISCCTRL
);
813 cfg
&= ~(EXYNOS_CISCCTRL_SCALERBYPASS
|
814 EXYNOS_CISCCTRL_SCALEUP_H
| EXYNOS_CISCCTRL_SCALEUP_V
|
815 EXYNOS_CISCCTRL_MAIN_V_RATIO_MASK
|
816 EXYNOS_CISCCTRL_MAIN_H_RATIO_MASK
|
817 EXYNOS_CISCCTRL_CSCR2Y_WIDE
|
818 EXYNOS_CISCCTRL_CSCY2R_WIDE
);
821 cfg
|= (EXYNOS_CISCCTRL_CSCR2Y_WIDE
|
822 EXYNOS_CISCCTRL_CSCY2R_WIDE
);
824 cfg
|= EXYNOS_CISCCTRL_SCALERBYPASS
;
826 cfg
|= EXYNOS_CISCCTRL_SCALEUP_H
;
828 cfg
|= EXYNOS_CISCCTRL_SCALEUP_V
;
830 cfg
|= (EXYNOS_CISCCTRL_MAINHORRATIO((sc
->hratio
>> 6)) |
831 EXYNOS_CISCCTRL_MAINVERRATIO((sc
->vratio
>> 6)));
832 fimc_write(ctx
, cfg
, EXYNOS_CISCCTRL
);
834 cfg_ext
= fimc_read(ctx
, EXYNOS_CIEXTEN
);
835 cfg_ext
&= ~EXYNOS_CIEXTEN_MAINHORRATIO_EXT_MASK
;
836 cfg_ext
&= ~EXYNOS_CIEXTEN_MAINVERRATIO_EXT_MASK
;
837 cfg_ext
|= (EXYNOS_CIEXTEN_MAINHORRATIO_EXT(sc
->hratio
) |
838 EXYNOS_CIEXTEN_MAINVERRATIO_EXT(sc
->vratio
));
839 fimc_write(ctx
, cfg_ext
, EXYNOS_CIEXTEN
);
842 static void fimc_dst_set_size(struct fimc_context
*ctx
,
843 struct exynos_drm_ipp_buffer
*buf
)
845 unsigned int real_width
= buf
->buf
.pitch
[0] / buf
->format
->cpp
[0];
848 DRM_DEV_DEBUG_KMS(ctx
->dev
, "hsize[%d]vsize[%d]\n", real_width
,
852 cfg
= (EXYNOS_ORGOSIZE_HORIZONTAL(real_width
) |
853 EXYNOS_ORGOSIZE_VERTICAL(buf
->buf
.height
));
855 fimc_write(ctx
, cfg
, EXYNOS_ORGOSIZE
);
857 DRM_DEV_DEBUG_KMS(ctx
->dev
, "x[%d]y[%d]w[%d]h[%d]\n", buf
->rect
.x
,
859 buf
->rect
.w
, buf
->rect
.h
);
862 cfg
= fimc_read(ctx
, EXYNOS_CIGCTRL
);
863 cfg
&= ~EXYNOS_CIGCTRL_CSC_MASK
;
865 if (buf
->buf
.width
>= FIMC_WIDTH_ITU_709
)
866 cfg
|= EXYNOS_CIGCTRL_CSC_ITU709
;
868 cfg
|= EXYNOS_CIGCTRL_CSC_ITU601
;
870 fimc_write(ctx
, cfg
, EXYNOS_CIGCTRL
);
872 cfg_ext
= fimc_read(ctx
, EXYNOS_CITRGFMT
);
874 /* target image size */
875 cfg
= fimc_read(ctx
, EXYNOS_CITRGFMT
);
876 cfg
&= ~(EXYNOS_CITRGFMT_TARGETH_MASK
|
877 EXYNOS_CITRGFMT_TARGETV_MASK
);
878 if (cfg_ext
& EXYNOS_CITRGFMT_OUTROT90_CLOCKWISE
)
879 cfg
|= (EXYNOS_CITRGFMT_TARGETHSIZE(buf
->rect
.h
) |
880 EXYNOS_CITRGFMT_TARGETVSIZE(buf
->rect
.w
));
882 cfg
|= (EXYNOS_CITRGFMT_TARGETHSIZE(buf
->rect
.w
) |
883 EXYNOS_CITRGFMT_TARGETVSIZE(buf
->rect
.h
));
884 fimc_write(ctx
, cfg
, EXYNOS_CITRGFMT
);
887 cfg
= EXYNOS_CITAREA_TARGET_AREA(buf
->rect
.w
* buf
->rect
.h
);
888 fimc_write(ctx
, cfg
, EXYNOS_CITAREA
);
890 /* offset Y(RGB), Cb, Cr */
891 cfg
= (EXYNOS_CIOYOFF_HORIZONTAL(buf
->rect
.x
) |
892 EXYNOS_CIOYOFF_VERTICAL(buf
->rect
.y
));
893 fimc_write(ctx
, cfg
, EXYNOS_CIOYOFF
);
894 cfg
= (EXYNOS_CIOCBOFF_HORIZONTAL(buf
->rect
.x
) |
895 EXYNOS_CIOCBOFF_VERTICAL(buf
->rect
.y
));
896 fimc_write(ctx
, cfg
, EXYNOS_CIOCBOFF
);
897 cfg
= (EXYNOS_CIOCROFF_HORIZONTAL(buf
->rect
.x
) |
898 EXYNOS_CIOCROFF_VERTICAL(buf
->rect
.y
));
899 fimc_write(ctx
, cfg
, EXYNOS_CIOCROFF
);
902 static void fimc_dst_set_buf_seq(struct fimc_context
*ctx
, u32 buf_id
,
909 DRM_DEV_DEBUG_KMS(ctx
->dev
, "buf_id[%d]enqueu[%d]\n", buf_id
, enqueue
);
911 spin_lock_irqsave(&ctx
->lock
, flags
);
913 cfg
= fimc_read(ctx
, EXYNOS_CIFCNTSEQ
);
916 cfg
|= (1 << buf_id
);
918 cfg
&= ~(1 << buf_id
);
920 fimc_write(ctx
, cfg
, EXYNOS_CIFCNTSEQ
);
922 buf_num
= hweight32(cfg
);
924 if (enqueue
&& buf_num
>= FIMC_BUF_START
)
925 fimc_mask_irq(ctx
, true);
926 else if (!enqueue
&& buf_num
<= FIMC_BUF_STOP
)
927 fimc_mask_irq(ctx
, false);
929 spin_unlock_irqrestore(&ctx
->lock
, flags
);
932 static void fimc_dst_set_addr(struct fimc_context
*ctx
,
933 struct exynos_drm_ipp_buffer
*buf
)
935 fimc_write(ctx
, buf
->dma_addr
[0], EXYNOS_CIOYSA(0));
936 fimc_write(ctx
, buf
->dma_addr
[1], EXYNOS_CIOCBSA(0));
937 fimc_write(ctx
, buf
->dma_addr
[2], EXYNOS_CIOCRSA(0));
939 fimc_dst_set_buf_seq(ctx
, 0, true);
942 static void fimc_stop(struct fimc_context
*ctx
);
944 static irqreturn_t
fimc_irq_handler(int irq
, void *dev_id
)
946 struct fimc_context
*ctx
= dev_id
;
949 DRM_DEV_DEBUG_KMS(ctx
->dev
, "fimc id[%d]\n", ctx
->id
);
952 if (fimc_check_ovf(ctx
))
955 if (!fimc_check_frame_end(ctx
))
958 buf_id
= fimc_get_buf_id(ctx
);
962 DRM_DEV_DEBUG_KMS(ctx
->dev
, "buf_id[%d]\n", buf_id
);
965 struct exynos_drm_ipp_task
*task
= ctx
->task
;
968 pm_runtime_mark_last_busy(ctx
->dev
);
969 pm_runtime_put_autosuspend(ctx
->dev
);
970 exynos_drm_ipp_task_done(task
, 0);
973 fimc_dst_set_buf_seq(ctx
, buf_id
, false);
979 static void fimc_clear_addr(struct fimc_context
*ctx
)
983 for (i
= 0; i
< FIMC_MAX_SRC
; i
++) {
984 fimc_write(ctx
, 0, EXYNOS_CIIYSA(i
));
985 fimc_write(ctx
, 0, EXYNOS_CIICBSA(i
));
986 fimc_write(ctx
, 0, EXYNOS_CIICRSA(i
));
989 for (i
= 0; i
< FIMC_MAX_DST
; i
++) {
990 fimc_write(ctx
, 0, EXYNOS_CIOYSA(i
));
991 fimc_write(ctx
, 0, EXYNOS_CIOCBSA(i
));
992 fimc_write(ctx
, 0, EXYNOS_CIOCRSA(i
));
996 static void fimc_reset(struct fimc_context
*ctx
)
998 /* reset h/w block */
1001 /* reset scaler capability */
1002 memset(&ctx
->sc
, 0x0, sizeof(ctx
->sc
));
1004 fimc_clear_addr(ctx
);
1007 static void fimc_start(struct fimc_context
*ctx
)
1011 fimc_mask_irq(ctx
, true);
1013 /* If set true, we can save jpeg about screen */
1014 fimc_handle_jpeg(ctx
, false);
1015 fimc_set_scaler(ctx
, &ctx
->sc
);
1017 fimc_set_type_ctrl(ctx
);
1018 fimc_handle_lastend(ctx
, false);
1021 cfg0
= fimc_read(ctx
, EXYNOS_MSCTRL
);
1022 cfg0
&= ~EXYNOS_MSCTRL_INPUT_MASK
;
1023 cfg0
|= EXYNOS_MSCTRL_INPUT_MEMORY
;
1024 fimc_write(ctx
, cfg0
, EXYNOS_MSCTRL
);
1027 fimc_write(ctx
, 0x0, EXYNOS_CISTATUS
);
1029 cfg0
= fimc_read(ctx
, EXYNOS_CIIMGCPT
);
1030 cfg0
&= ~EXYNOS_CIIMGCPT_IMGCPTEN_SC
;
1031 cfg0
|= EXYNOS_CIIMGCPT_IMGCPTEN_SC
;
1034 cfg1
= fimc_read(ctx
, EXYNOS_CISCCTRL
);
1035 cfg1
&= ~EXYNOS_CISCCTRL_SCAN_MASK
;
1036 cfg1
|= (EXYNOS_CISCCTRL_PROGRESSIVE
|
1037 EXYNOS_CISCCTRL_SCALERSTART
);
1039 fimc_write(ctx
, cfg1
, EXYNOS_CISCCTRL
);
1041 /* Enable image capture*/
1042 cfg0
|= EXYNOS_CIIMGCPT_IMGCPTEN
;
1043 fimc_write(ctx
, cfg0
, EXYNOS_CIIMGCPT
);
1045 /* Disable frame end irq */
1046 fimc_clear_bits(ctx
, EXYNOS_CIGCTRL
, EXYNOS_CIGCTRL_IRQ_END_DISABLE
);
1048 fimc_clear_bits(ctx
, EXYNOS_CIOCTRL
, EXYNOS_CIOCTRL_WEAVE_MASK
);
1050 fimc_set_bits(ctx
, EXYNOS_MSCTRL
, EXYNOS_MSCTRL_ENVID
);
1053 static void fimc_stop(struct fimc_context
*ctx
)
1058 cfg
= fimc_read(ctx
, EXYNOS_MSCTRL
);
1059 cfg
&= ~EXYNOS_MSCTRL_INPUT_MASK
;
1060 cfg
&= ~EXYNOS_MSCTRL_ENVID
;
1061 fimc_write(ctx
, cfg
, EXYNOS_MSCTRL
);
1063 fimc_mask_irq(ctx
, false);
1065 /* reset sequence */
1066 fimc_write(ctx
, 0x0, EXYNOS_CIFCNTSEQ
);
1068 /* Scaler disable */
1069 fimc_clear_bits(ctx
, EXYNOS_CISCCTRL
, EXYNOS_CISCCTRL_SCALERSTART
);
1071 /* Disable image capture */
1072 fimc_clear_bits(ctx
, EXYNOS_CIIMGCPT
,
1073 EXYNOS_CIIMGCPT_IMGCPTEN_SC
| EXYNOS_CIIMGCPT_IMGCPTEN
);
1075 /* Enable frame end irq */
1076 fimc_set_bits(ctx
, EXYNOS_CIGCTRL
, EXYNOS_CIGCTRL_IRQ_END_DISABLE
);
1079 static int fimc_commit(struct exynos_drm_ipp
*ipp
,
1080 struct exynos_drm_ipp_task
*task
)
1082 struct fimc_context
*ctx
=
1083 container_of(ipp
, struct fimc_context
, ipp
);
1085 pm_runtime_get_sync(ctx
->dev
);
1088 fimc_src_set_fmt(ctx
, task
->src
.buf
.fourcc
, task
->src
.buf
.modifier
);
1089 fimc_src_set_size(ctx
, &task
->src
);
1090 fimc_src_set_transf(ctx
, DRM_MODE_ROTATE_0
);
1091 fimc_src_set_addr(ctx
, &task
->src
);
1092 fimc_dst_set_fmt(ctx
, task
->dst
.buf
.fourcc
, task
->dst
.buf
.modifier
);
1093 fimc_dst_set_transf(ctx
, task
->transform
.rotation
);
1094 fimc_dst_set_size(ctx
, &task
->dst
);
1095 fimc_dst_set_addr(ctx
, &task
->dst
);
1096 fimc_set_prescaler(ctx
, &ctx
->sc
, &task
->src
.rect
, &task
->dst
.rect
);
1102 static void fimc_abort(struct exynos_drm_ipp
*ipp
,
1103 struct exynos_drm_ipp_task
*task
)
1105 struct fimc_context
*ctx
=
1106 container_of(ipp
, struct fimc_context
, ipp
);
1111 struct exynos_drm_ipp_task
*task
= ctx
->task
;
1114 pm_runtime_mark_last_busy(ctx
->dev
);
1115 pm_runtime_put_autosuspend(ctx
->dev
);
1116 exynos_drm_ipp_task_done(task
, -EIO
);
1120 static struct exynos_drm_ipp_funcs ipp_funcs
= {
1121 .commit
= fimc_commit
,
1122 .abort
= fimc_abort
,
1125 static int fimc_bind(struct device
*dev
, struct device
*master
, void *data
)
1127 struct fimc_context
*ctx
= dev_get_drvdata(dev
);
1128 struct drm_device
*drm_dev
= data
;
1129 struct exynos_drm_ipp
*ipp
= &ctx
->ipp
;
1131 ctx
->drm_dev
= drm_dev
;
1132 ipp
->drm_dev
= drm_dev
;
1133 exynos_drm_register_dma(drm_dev
, dev
);
1135 exynos_drm_ipp_register(dev
, ipp
, &ipp_funcs
,
1136 DRM_EXYNOS_IPP_CAP_CROP
| DRM_EXYNOS_IPP_CAP_ROTATE
|
1137 DRM_EXYNOS_IPP_CAP_SCALE
| DRM_EXYNOS_IPP_CAP_CONVERT
,
1138 ctx
->formats
, ctx
->num_formats
, "fimc");
1140 dev_info(dev
, "The exynos fimc has been probed successfully\n");
1145 static void fimc_unbind(struct device
*dev
, struct device
*master
,
1148 struct fimc_context
*ctx
= dev_get_drvdata(dev
);
1149 struct drm_device
*drm_dev
= data
;
1150 struct exynos_drm_ipp
*ipp
= &ctx
->ipp
;
1152 exynos_drm_ipp_unregister(dev
, ipp
);
1153 exynos_drm_unregister_dma(drm_dev
, dev
);
1156 static const struct component_ops fimc_component_ops
= {
1158 .unbind
= fimc_unbind
,
1161 static void fimc_put_clocks(struct fimc_context
*ctx
)
1165 for (i
= 0; i
< FIMC_CLKS_MAX
; i
++) {
1166 if (IS_ERR(ctx
->clocks
[i
]))
1168 clk_put(ctx
->clocks
[i
]);
1169 ctx
->clocks
[i
] = ERR_PTR(-EINVAL
);
1173 static int fimc_setup_clocks(struct fimc_context
*ctx
)
1175 struct device
*fimc_dev
= ctx
->dev
;
1179 for (i
= 0; i
< FIMC_CLKS_MAX
; i
++)
1180 ctx
->clocks
[i
] = ERR_PTR(-EINVAL
);
1182 for (i
= 0; i
< FIMC_CLKS_MAX
; i
++) {
1183 if (i
== FIMC_CLK_WB_A
|| i
== FIMC_CLK_WB_B
)
1184 dev
= fimc_dev
->parent
;
1188 ctx
->clocks
[i
] = clk_get(dev
, fimc_clock_names
[i
]);
1189 if (IS_ERR(ctx
->clocks
[i
])) {
1190 ret
= PTR_ERR(ctx
->clocks
[i
]);
1191 dev_err(fimc_dev
, "failed to get clock: %s\n",
1192 fimc_clock_names
[i
]);
1197 ret
= clk_prepare_enable(ctx
->clocks
[FIMC_CLK_LCLK
]);
1201 fimc_put_clocks(ctx
);
1205 int exynos_drm_check_fimc_device(struct device
*dev
)
1207 int id
= of_alias_get_id(dev
->of_node
, "fimc");
1209 if (id
>= 0 && (BIT(id
) & fimc_mask
))
1214 static const unsigned int fimc_formats
[] = {
1215 DRM_FORMAT_XRGB8888
, DRM_FORMAT_RGB565
,
1216 DRM_FORMAT_NV12
, DRM_FORMAT_NV16
, DRM_FORMAT_NV21
, DRM_FORMAT_NV61
,
1217 DRM_FORMAT_UYVY
, DRM_FORMAT_VYUY
, DRM_FORMAT_YUYV
, DRM_FORMAT_YVYU
,
1218 DRM_FORMAT_YUV420
, DRM_FORMAT_YVU420
, DRM_FORMAT_YUV422
,
1222 static const unsigned int fimc_tiled_formats
[] = {
1223 DRM_FORMAT_NV12
, DRM_FORMAT_NV21
,
1226 static const struct drm_exynos_ipp_limit fimc_4210_limits_v1
[] = {
1227 { IPP_SIZE_LIMIT(BUFFER
, .h
= { 16, 8192, 8 }, .v
= { 16, 8192, 2 }) },
1228 { IPP_SIZE_LIMIT(AREA
, .h
= { 16, 4224, 2 }, .v
= { 16, 0, 2 }) },
1229 { IPP_SIZE_LIMIT(ROTATED
, .h
= { 128, 1920 }, .v
= { 128, 0 }) },
1230 { IPP_SCALE_LIMIT(.h
= { (1 << 16) / 64, (1 << 16) * 64 },
1231 .v
= { (1 << 16) / 64, (1 << 16) * 64 }) },
1234 static const struct drm_exynos_ipp_limit fimc_4210_limits_v2
[] = {
1235 { IPP_SIZE_LIMIT(BUFFER
, .h
= { 16, 8192, 8 }, .v
= { 16, 8192, 2 }) },
1236 { IPP_SIZE_LIMIT(AREA
, .h
= { 16, 1920, 2 }, .v
= { 16, 0, 2 }) },
1237 { IPP_SIZE_LIMIT(ROTATED
, .h
= { 128, 1366 }, .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_tiled_v1
[] = {
1243 { IPP_SIZE_LIMIT(BUFFER
, .h
= { 128, 1920, 128 }, .v
= { 32, 1920, 32 }) },
1244 { IPP_SIZE_LIMIT(AREA
, .h
= { 128, 1920, 2 }, .v
= { 128, 0, 2 }) },
1245 { IPP_SCALE_LIMIT(.h
= { (1 << 16) / 64, (1 << 16) * 64 },
1246 .v
= { (1 << 16) / 64, (1 << 16) * 64 }) },
1249 static const struct drm_exynos_ipp_limit fimc_4210_limits_tiled_v2
[] = {
1250 { IPP_SIZE_LIMIT(BUFFER
, .h
= { 128, 1920, 128 }, .v
= { 32, 1920, 32 }) },
1251 { IPP_SIZE_LIMIT(AREA
, .h
= { 128, 1366, 2 }, .v
= { 128, 0, 2 }) },
1252 { IPP_SCALE_LIMIT(.h
= { (1 << 16) / 64, (1 << 16) * 64 },
1253 .v
= { (1 << 16) / 64, (1 << 16) * 64 }) },
1256 static int fimc_probe(struct platform_device
*pdev
)
1258 const struct drm_exynos_ipp_limit
*limits
;
1259 struct exynos_drm_ipp_formats
*formats
;
1260 struct device
*dev
= &pdev
->dev
;
1261 struct fimc_context
*ctx
;
1262 struct resource
*res
;
1264 int i
, j
, num_limits
, num_formats
;
1266 if (exynos_drm_check_fimc_device(dev
) != 0)
1269 ctx
= devm_kzalloc(dev
, sizeof(*ctx
), GFP_KERNEL
);
1274 ctx
->id
= of_alias_get_id(dev
->of_node
, "fimc");
1276 /* construct formats/limits array */
1277 num_formats
= ARRAY_SIZE(fimc_formats
) + ARRAY_SIZE(fimc_tiled_formats
);
1278 formats
= devm_kcalloc(dev
, num_formats
, sizeof(*formats
),
1283 /* linear formats */
1285 limits
= fimc_4210_limits_v1
;
1286 num_limits
= ARRAY_SIZE(fimc_4210_limits_v1
);
1288 limits
= fimc_4210_limits_v2
;
1289 num_limits
= ARRAY_SIZE(fimc_4210_limits_v2
);
1291 for (i
= 0; i
< ARRAY_SIZE(fimc_formats
); i
++) {
1292 formats
[i
].fourcc
= fimc_formats
[i
];
1293 formats
[i
].type
= DRM_EXYNOS_IPP_FORMAT_SOURCE
|
1294 DRM_EXYNOS_IPP_FORMAT_DESTINATION
;
1295 formats
[i
].limits
= limits
;
1296 formats
[i
].num_limits
= num_limits
;
1301 limits
= fimc_4210_limits_tiled_v1
;
1302 num_limits
= ARRAY_SIZE(fimc_4210_limits_tiled_v1
);
1304 limits
= fimc_4210_limits_tiled_v2
;
1305 num_limits
= ARRAY_SIZE(fimc_4210_limits_tiled_v2
);
1307 for (j
= i
, i
= 0; i
< ARRAY_SIZE(fimc_tiled_formats
); j
++, i
++) {
1308 formats
[j
].fourcc
= fimc_tiled_formats
[i
];
1309 formats
[j
].modifier
= DRM_FORMAT_MOD_SAMSUNG_64_32_TILE
;
1310 formats
[j
].type
= DRM_EXYNOS_IPP_FORMAT_SOURCE
|
1311 DRM_EXYNOS_IPP_FORMAT_DESTINATION
;
1312 formats
[j
].limits
= limits
;
1313 formats
[j
].num_limits
= num_limits
;
1316 ctx
->formats
= formats
;
1317 ctx
->num_formats
= num_formats
;
1319 /* resource memory */
1320 ctx
->regs_res
= platform_get_resource(pdev
, IORESOURCE_MEM
, 0);
1321 ctx
->regs
= devm_ioremap_resource(dev
, ctx
->regs_res
);
1322 if (IS_ERR(ctx
->regs
))
1323 return PTR_ERR(ctx
->regs
);
1326 res
= platform_get_resource(pdev
, IORESOURCE_IRQ
, 0);
1328 dev_err(dev
, "failed to request irq resource.\n");
1332 ret
= devm_request_irq(dev
, res
->start
, fimc_irq_handler
,
1333 0, dev_name(dev
), ctx
);
1335 dev_err(dev
, "failed to request irq.\n");
1339 ret
= fimc_setup_clocks(ctx
);
1343 spin_lock_init(&ctx
->lock
);
1344 platform_set_drvdata(pdev
, ctx
);
1346 pm_runtime_use_autosuspend(dev
);
1347 pm_runtime_set_autosuspend_delay(dev
, FIMC_AUTOSUSPEND_DELAY
);
1348 pm_runtime_enable(dev
);
1350 ret
= component_add(dev
, &fimc_component_ops
);
1354 dev_info(dev
, "drm fimc registered successfully.\n");
1359 pm_runtime_dont_use_autosuspend(dev
);
1360 pm_runtime_disable(dev
);
1361 fimc_put_clocks(ctx
);
1366 static int fimc_remove(struct platform_device
*pdev
)
1368 struct device
*dev
= &pdev
->dev
;
1369 struct fimc_context
*ctx
= get_fimc_context(dev
);
1371 component_del(dev
, &fimc_component_ops
);
1372 pm_runtime_dont_use_autosuspend(dev
);
1373 pm_runtime_disable(dev
);
1375 fimc_put_clocks(ctx
);
1381 static int fimc_runtime_suspend(struct device
*dev
)
1383 struct fimc_context
*ctx
= get_fimc_context(dev
);
1385 DRM_DEV_DEBUG_KMS(dev
, "id[%d]\n", ctx
->id
);
1386 clk_disable_unprepare(ctx
->clocks
[FIMC_CLK_GATE
]);
1390 static int fimc_runtime_resume(struct device
*dev
)
1392 struct fimc_context
*ctx
= get_fimc_context(dev
);
1394 DRM_DEV_DEBUG_KMS(dev
, "id[%d]\n", ctx
->id
);
1395 return clk_prepare_enable(ctx
->clocks
[FIMC_CLK_GATE
]);
1399 static const struct dev_pm_ops fimc_pm_ops
= {
1400 SET_SYSTEM_SLEEP_PM_OPS(pm_runtime_force_suspend
,
1401 pm_runtime_force_resume
)
1402 SET_RUNTIME_PM_OPS(fimc_runtime_suspend
, fimc_runtime_resume
, NULL
)
1405 static const struct of_device_id fimc_of_match
[] = {
1406 { .compatible
= "samsung,exynos4210-fimc" },
1407 { .compatible
= "samsung,exynos4212-fimc" },
1410 MODULE_DEVICE_TABLE(of
, fimc_of_match
);
1412 struct platform_driver fimc_driver
= {
1413 .probe
= fimc_probe
,
1414 .remove
= fimc_remove
,
1416 .of_match_table
= fimc_of_match
,
1417 .name
= "exynos-drm-fimc",
1418 .owner
= THIS_MODULE
,