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/component.h>
16 #include <linux/platform_device.h>
17 #include <linux/mfd/syscon.h>
18 #include <linux/regmap.h>
19 #include <linux/clk.h>
20 #include <linux/pm_runtime.h>
22 #include <linux/spinlock.h>
25 #include <drm/exynos_drm.h>
26 #include "regs-fimc.h"
27 #include "exynos_drm_drv.h"
28 #include "exynos_drm_iommu.h"
29 #include "exynos_drm_ipp.h"
32 * FIMC stands for Fully Interactive Mobile Camera and
33 * supports image scaler/rotator and input/output DMA operations.
34 * input DMA reads image data from the memory.
35 * output DMA writes image data to memory.
36 * FIMC supports image rotation and image effect functions.
39 #define FIMC_MAX_DEVS 4
40 #define FIMC_MAX_SRC 2
41 #define FIMC_MAX_DST 32
42 #define FIMC_SHFACTOR 10
43 #define FIMC_BUF_STOP 1
44 #define FIMC_BUF_START 2
45 #define FIMC_WIDTH_ITU_709 1280
46 #define FIMC_AUTOSUSPEND_DELAY 2000
48 static unsigned int fimc_mask
= 0xc;
49 module_param_named(fimc_devs
, fimc_mask
, uint
, 0644);
50 MODULE_PARM_DESC(fimc_devs
, "Alias mask for assigning FIMC devices to Exynos DRM");
52 #define get_fimc_context(dev) platform_get_drvdata(to_platform_device(dev))
62 static const char * const fimc_clock_names
[] = {
63 [FIMC_CLK_LCLK
] = "sclk_fimc",
64 [FIMC_CLK_GATE
] = "fimc",
65 [FIMC_CLK_WB_A
] = "pxl_async0",
66 [FIMC_CLK_WB_B
] = "pxl_async1",
70 * A structure of scaler.
72 * @range: narrow, wide.
73 * @bypass: unused scaler path.
74 * @up_h: horizontal scale up.
75 * @up_v: vertical scale up.
76 * @hratio: horizontal ratio.
77 * @vratio: vertical ratio.
89 * A structure of fimc context.
91 * @regs_res: register resources.
92 * @regs: memory mapped io registers.
93 * @lock: locking of operations.
94 * @clocks: fimc clocks.
95 * @sc: scaler infomations.
96 * @pol: porarity of writeback.
100 struct fimc_context
{
101 struct exynos_drm_ipp ipp
;
102 struct drm_device
*drm_dev
;
104 struct exynos_drm_ipp_task
*task
;
105 struct exynos_drm_ipp_formats
*formats
;
106 unsigned int num_formats
;
108 struct resource
*regs_res
;
111 struct clk
*clocks
[FIMC_CLKS_MAX
];
112 struct fimc_scaler sc
;
117 static u32
fimc_read(struct fimc_context
*ctx
, u32 reg
)
119 return readl(ctx
->regs
+ reg
);
122 static void fimc_write(struct fimc_context
*ctx
, u32 val
, u32 reg
)
124 writel(val
, ctx
->regs
+ reg
);
127 static void fimc_set_bits(struct fimc_context
*ctx
, u32 reg
, u32 bits
)
129 void __iomem
*r
= ctx
->regs
+ reg
;
131 writel(readl(r
) | bits
, r
);
134 static void fimc_clear_bits(struct fimc_context
*ctx
, u32 reg
, u32 bits
)
136 void __iomem
*r
= ctx
->regs
+ reg
;
138 writel(readl(r
) & ~bits
, r
);
141 static void fimc_sw_reset(struct fimc_context
*ctx
)
145 /* stop dma operation */
146 cfg
= fimc_read(ctx
, EXYNOS_CISTATUS
);
147 if (EXYNOS_CISTATUS_GET_ENVID_STATUS(cfg
))
148 fimc_clear_bits(ctx
, EXYNOS_MSCTRL
, EXYNOS_MSCTRL_ENVID
);
150 fimc_set_bits(ctx
, EXYNOS_CISRCFMT
, EXYNOS_CISRCFMT_ITU601_8BIT
);
152 /* disable image capture */
153 fimc_clear_bits(ctx
, EXYNOS_CIIMGCPT
,
154 EXYNOS_CIIMGCPT_IMGCPTEN_SC
| EXYNOS_CIIMGCPT_IMGCPTEN
);
157 fimc_set_bits(ctx
, EXYNOS_CIGCTRL
, EXYNOS_CIGCTRL_SWRST
);
159 /* s/w reset complete */
160 fimc_clear_bits(ctx
, EXYNOS_CIGCTRL
, EXYNOS_CIGCTRL_SWRST
);
163 fimc_write(ctx
, 0x0, EXYNOS_CIFCNTSEQ
);
166 static void fimc_set_type_ctrl(struct fimc_context
*ctx
)
170 cfg
= fimc_read(ctx
, EXYNOS_CIGCTRL
);
171 cfg
&= ~(EXYNOS_CIGCTRL_TESTPATTERN_MASK
|
172 EXYNOS_CIGCTRL_SELCAM_ITU_MASK
|
173 EXYNOS_CIGCTRL_SELCAM_MIPI_MASK
|
174 EXYNOS_CIGCTRL_SELCAM_FIMC_MASK
|
175 EXYNOS_CIGCTRL_SELWB_CAMIF_MASK
|
176 EXYNOS_CIGCTRL_SELWRITEBACK_MASK
);
178 cfg
|= (EXYNOS_CIGCTRL_SELCAM_ITU_A
|
179 EXYNOS_CIGCTRL_SELWRITEBACK_A
|
180 EXYNOS_CIGCTRL_SELCAM_MIPI_A
|
181 EXYNOS_CIGCTRL_SELCAM_FIMC_ITU
);
183 fimc_write(ctx
, cfg
, EXYNOS_CIGCTRL
);
186 static void fimc_handle_jpeg(struct fimc_context
*ctx
, bool enable
)
190 DRM_DEBUG_KMS("enable[%d]\n", enable
);
192 cfg
= fimc_read(ctx
, EXYNOS_CIGCTRL
);
194 cfg
|= EXYNOS_CIGCTRL_CAM_JPEG
;
196 cfg
&= ~EXYNOS_CIGCTRL_CAM_JPEG
;
198 fimc_write(ctx
, cfg
, EXYNOS_CIGCTRL
);
201 static void fimc_mask_irq(struct fimc_context
*ctx
, bool enable
)
205 DRM_DEBUG_KMS("enable[%d]\n", enable
);
207 cfg
= fimc_read(ctx
, EXYNOS_CIGCTRL
);
209 cfg
&= ~EXYNOS_CIGCTRL_IRQ_OVFEN
;
210 cfg
|= EXYNOS_CIGCTRL_IRQ_ENABLE
| EXYNOS_CIGCTRL_IRQ_LEVEL
;
212 cfg
&= ~EXYNOS_CIGCTRL_IRQ_ENABLE
;
213 fimc_write(ctx
, cfg
, EXYNOS_CIGCTRL
);
216 static void fimc_clear_irq(struct fimc_context
*ctx
)
218 fimc_set_bits(ctx
, EXYNOS_CIGCTRL
, EXYNOS_CIGCTRL_IRQ_CLR
);
221 static bool fimc_check_ovf(struct fimc_context
*ctx
)
225 status
= fimc_read(ctx
, EXYNOS_CISTATUS
);
226 flag
= EXYNOS_CISTATUS_OVFIY
| EXYNOS_CISTATUS_OVFICB
|
227 EXYNOS_CISTATUS_OVFICR
;
229 DRM_DEBUG_KMS("flag[0x%x]\n", flag
);
232 fimc_set_bits(ctx
, EXYNOS_CIWDOFST
,
233 EXYNOS_CIWDOFST_CLROVFIY
| EXYNOS_CIWDOFST_CLROVFICB
|
234 EXYNOS_CIWDOFST_CLROVFICR
);
236 dev_err(ctx
->dev
, "occurred overflow at %d, status 0x%x.\n",
244 static bool fimc_check_frame_end(struct fimc_context
*ctx
)
248 cfg
= fimc_read(ctx
, EXYNOS_CISTATUS
);
250 DRM_DEBUG_KMS("cfg[0x%x]\n", cfg
);
252 if (!(cfg
& EXYNOS_CISTATUS_FRAMEEND
))
255 cfg
&= ~(EXYNOS_CISTATUS_FRAMEEND
);
256 fimc_write(ctx
, cfg
, EXYNOS_CISTATUS
);
261 static int fimc_get_buf_id(struct fimc_context
*ctx
)
264 int frame_cnt
, buf_id
;
266 cfg
= fimc_read(ctx
, EXYNOS_CISTATUS2
);
267 frame_cnt
= EXYNOS_CISTATUS2_GET_FRAMECOUNT_BEFORE(cfg
);
270 frame_cnt
= EXYNOS_CISTATUS2_GET_FRAMECOUNT_PRESENT(cfg
);
272 DRM_DEBUG_KMS("present[%d]before[%d]\n",
273 EXYNOS_CISTATUS2_GET_FRAMECOUNT_PRESENT(cfg
),
274 EXYNOS_CISTATUS2_GET_FRAMECOUNT_BEFORE(cfg
));
276 if (frame_cnt
== 0) {
277 DRM_ERROR("failed to get frame count.\n");
281 buf_id
= frame_cnt
- 1;
282 DRM_DEBUG_KMS("buf_id[%d]\n", buf_id
);
287 static void fimc_handle_lastend(struct fimc_context
*ctx
, bool enable
)
291 DRM_DEBUG_KMS("enable[%d]\n", enable
);
293 cfg
= fimc_read(ctx
, EXYNOS_CIOCTRL
);
295 cfg
|= EXYNOS_CIOCTRL_LASTENDEN
;
297 cfg
&= ~EXYNOS_CIOCTRL_LASTENDEN
;
299 fimc_write(ctx
, cfg
, EXYNOS_CIOCTRL
);
302 static void fimc_src_set_fmt_order(struct fimc_context
*ctx
, u32 fmt
)
306 DRM_DEBUG_KMS("fmt[0x%x]\n", fmt
);
309 cfg
= fimc_read(ctx
, EXYNOS_CISCCTRL
);
310 cfg
&= ~EXYNOS_CISCCTRL_INRGB_FMT_RGB_MASK
;
313 case DRM_FORMAT_RGB565
:
314 cfg
|= EXYNOS_CISCCTRL_INRGB_FMT_RGB565
;
315 fimc_write(ctx
, cfg
, EXYNOS_CISCCTRL
);
317 case DRM_FORMAT_RGB888
:
318 case DRM_FORMAT_XRGB8888
:
319 cfg
|= EXYNOS_CISCCTRL_INRGB_FMT_RGB888
;
320 fimc_write(ctx
, cfg
, EXYNOS_CISCCTRL
);
328 cfg
= fimc_read(ctx
, EXYNOS_MSCTRL
);
329 cfg
&= ~(EXYNOS_MSCTRL_ORDER2P_SHIFT_MASK
|
330 EXYNOS_MSCTRL_C_INT_IN_2PLANE
|
331 EXYNOS_MSCTRL_ORDER422_YCBYCR
);
334 case DRM_FORMAT_YUYV
:
335 cfg
|= EXYNOS_MSCTRL_ORDER422_YCBYCR
;
337 case DRM_FORMAT_YVYU
:
338 cfg
|= EXYNOS_MSCTRL_ORDER422_YCRYCB
;
340 case DRM_FORMAT_UYVY
:
341 cfg
|= EXYNOS_MSCTRL_ORDER422_CBYCRY
;
343 case DRM_FORMAT_VYUY
:
344 case DRM_FORMAT_YUV444
:
345 cfg
|= EXYNOS_MSCTRL_ORDER422_CRYCBY
;
347 case DRM_FORMAT_NV21
:
348 case DRM_FORMAT_NV61
:
349 cfg
|= (EXYNOS_MSCTRL_ORDER2P_LSB_CRCB
|
350 EXYNOS_MSCTRL_C_INT_IN_2PLANE
);
352 case DRM_FORMAT_YUV422
:
353 case DRM_FORMAT_YUV420
:
354 case DRM_FORMAT_YVU420
:
355 cfg
|= EXYNOS_MSCTRL_C_INT_IN_3PLANE
;
357 case DRM_FORMAT_NV12
:
358 case DRM_FORMAT_NV16
:
359 cfg
|= (EXYNOS_MSCTRL_ORDER2P_LSB_CBCR
|
360 EXYNOS_MSCTRL_C_INT_IN_2PLANE
);
364 fimc_write(ctx
, cfg
, EXYNOS_MSCTRL
);
367 static void fimc_src_set_fmt(struct fimc_context
*ctx
, u32 fmt
, bool tiled
)
371 DRM_DEBUG_KMS("fmt[0x%x]\n", fmt
);
373 cfg
= fimc_read(ctx
, EXYNOS_MSCTRL
);
374 cfg
&= ~EXYNOS_MSCTRL_INFORMAT_RGB
;
377 case DRM_FORMAT_RGB565
:
378 case DRM_FORMAT_RGB888
:
379 case DRM_FORMAT_XRGB8888
:
380 cfg
|= EXYNOS_MSCTRL_INFORMAT_RGB
;
382 case DRM_FORMAT_YUV444
:
383 cfg
|= EXYNOS_MSCTRL_INFORMAT_YCBCR420
;
385 case DRM_FORMAT_YUYV
:
386 case DRM_FORMAT_YVYU
:
387 case DRM_FORMAT_UYVY
:
388 case DRM_FORMAT_VYUY
:
389 cfg
|= EXYNOS_MSCTRL_INFORMAT_YCBCR422_1PLANE
;
391 case DRM_FORMAT_NV16
:
392 case DRM_FORMAT_NV61
:
393 case DRM_FORMAT_YUV422
:
394 cfg
|= EXYNOS_MSCTRL_INFORMAT_YCBCR422
;
396 case DRM_FORMAT_YUV420
:
397 case DRM_FORMAT_YVU420
:
398 case DRM_FORMAT_NV12
:
399 case DRM_FORMAT_NV21
:
400 cfg
|= EXYNOS_MSCTRL_INFORMAT_YCBCR420
;
404 fimc_write(ctx
, cfg
, EXYNOS_MSCTRL
);
406 cfg
= fimc_read(ctx
, EXYNOS_CIDMAPARAM
);
407 cfg
&= ~EXYNOS_CIDMAPARAM_R_MODE_MASK
;
410 cfg
|= EXYNOS_CIDMAPARAM_R_MODE_64X32
;
412 cfg
|= EXYNOS_CIDMAPARAM_R_MODE_LINEAR
;
414 fimc_write(ctx
, cfg
, EXYNOS_CIDMAPARAM
);
416 fimc_src_set_fmt_order(ctx
, fmt
);
419 static void fimc_src_set_transf(struct fimc_context
*ctx
, unsigned int rotation
)
421 unsigned int degree
= rotation
& DRM_MODE_ROTATE_MASK
;
424 DRM_DEBUG_KMS("rotation[%x]\n", rotation
);
426 cfg1
= fimc_read(ctx
, EXYNOS_MSCTRL
);
427 cfg1
&= ~(EXYNOS_MSCTRL_FLIP_X_MIRROR
|
428 EXYNOS_MSCTRL_FLIP_Y_MIRROR
);
430 cfg2
= fimc_read(ctx
, EXYNOS_CITRGFMT
);
431 cfg2
&= ~EXYNOS_CITRGFMT_INROT90_CLOCKWISE
;
434 case DRM_MODE_ROTATE_0
:
435 if (rotation
& DRM_MODE_REFLECT_X
)
436 cfg1
|= EXYNOS_MSCTRL_FLIP_X_MIRROR
;
437 if (rotation
& DRM_MODE_REFLECT_Y
)
438 cfg1
|= EXYNOS_MSCTRL_FLIP_Y_MIRROR
;
440 case DRM_MODE_ROTATE_90
:
441 cfg2
|= EXYNOS_CITRGFMT_INROT90_CLOCKWISE
;
442 if (rotation
& DRM_MODE_REFLECT_X
)
443 cfg1
|= EXYNOS_MSCTRL_FLIP_X_MIRROR
;
444 if (rotation
& DRM_MODE_REFLECT_Y
)
445 cfg1
|= EXYNOS_MSCTRL_FLIP_Y_MIRROR
;
447 case DRM_MODE_ROTATE_180
:
448 cfg1
|= (EXYNOS_MSCTRL_FLIP_X_MIRROR
|
449 EXYNOS_MSCTRL_FLIP_Y_MIRROR
);
450 if (rotation
& DRM_MODE_REFLECT_X
)
451 cfg1
&= ~EXYNOS_MSCTRL_FLIP_X_MIRROR
;
452 if (rotation
& DRM_MODE_REFLECT_Y
)
453 cfg1
&= ~EXYNOS_MSCTRL_FLIP_Y_MIRROR
;
455 case DRM_MODE_ROTATE_270
:
456 cfg1
|= (EXYNOS_MSCTRL_FLIP_X_MIRROR
|
457 EXYNOS_MSCTRL_FLIP_Y_MIRROR
);
458 cfg2
|= EXYNOS_CITRGFMT_INROT90_CLOCKWISE
;
459 if (rotation
& DRM_MODE_REFLECT_X
)
460 cfg1
&= ~EXYNOS_MSCTRL_FLIP_X_MIRROR
;
461 if (rotation
& DRM_MODE_REFLECT_Y
)
462 cfg1
&= ~EXYNOS_MSCTRL_FLIP_Y_MIRROR
;
466 fimc_write(ctx
, cfg1
, EXYNOS_MSCTRL
);
467 fimc_write(ctx
, cfg2
, EXYNOS_CITRGFMT
);
470 static void fimc_set_window(struct fimc_context
*ctx
,
471 struct exynos_drm_ipp_buffer
*buf
)
473 unsigned int real_width
= buf
->buf
.pitch
[0] / buf
->format
->cpp
[0];
474 u32 cfg
, h1
, h2
, v1
, v2
;
478 h2
= real_width
- buf
->rect
.w
- buf
->rect
.x
;
480 v2
= buf
->buf
.height
- buf
->rect
.h
- buf
->rect
.y
;
482 DRM_DEBUG_KMS("x[%d]y[%d]w[%d]h[%d]hsize[%d]vsize[%d]\n",
483 buf
->rect
.x
, buf
->rect
.y
, buf
->rect
.w
, buf
->rect
.h
,
484 real_width
, buf
->buf
.height
);
485 DRM_DEBUG_KMS("h1[%d]h2[%d]v1[%d]v2[%d]\n", h1
, h2
, v1
, v2
);
488 * set window offset 1, 2 size
489 * check figure 43-21 in user manual
491 cfg
= fimc_read(ctx
, EXYNOS_CIWDOFST
);
492 cfg
&= ~(EXYNOS_CIWDOFST_WINHOROFST_MASK
|
493 EXYNOS_CIWDOFST_WINVEROFST_MASK
);
494 cfg
|= (EXYNOS_CIWDOFST_WINHOROFST(h1
) |
495 EXYNOS_CIWDOFST_WINVEROFST(v1
));
496 cfg
|= EXYNOS_CIWDOFST_WINOFSEN
;
497 fimc_write(ctx
, cfg
, EXYNOS_CIWDOFST
);
499 cfg
= (EXYNOS_CIWDOFST2_WINHOROFST2(h2
) |
500 EXYNOS_CIWDOFST2_WINVEROFST2(v2
));
501 fimc_write(ctx
, cfg
, EXYNOS_CIWDOFST2
);
504 static void fimc_src_set_size(struct fimc_context
*ctx
,
505 struct exynos_drm_ipp_buffer
*buf
)
507 unsigned int real_width
= buf
->buf
.pitch
[0] / buf
->format
->cpp
[0];
510 DRM_DEBUG_KMS("hsize[%d]vsize[%d]\n", real_width
, buf
->buf
.height
);
513 cfg
= (EXYNOS_ORGISIZE_HORIZONTAL(real_width
) |
514 EXYNOS_ORGISIZE_VERTICAL(buf
->buf
.height
));
516 fimc_write(ctx
, cfg
, EXYNOS_ORGISIZE
);
518 DRM_DEBUG_KMS("x[%d]y[%d]w[%d]h[%d]\n", buf
->rect
.x
, buf
->rect
.y
,
519 buf
->rect
.w
, buf
->rect
.h
);
521 /* set input DMA image size */
522 cfg
= fimc_read(ctx
, EXYNOS_CIREAL_ISIZE
);
523 cfg
&= ~(EXYNOS_CIREAL_ISIZE_HEIGHT_MASK
|
524 EXYNOS_CIREAL_ISIZE_WIDTH_MASK
);
525 cfg
|= (EXYNOS_CIREAL_ISIZE_WIDTH(buf
->rect
.w
) |
526 EXYNOS_CIREAL_ISIZE_HEIGHT(buf
->rect
.h
));
527 fimc_write(ctx
, cfg
, EXYNOS_CIREAL_ISIZE
);
530 * set input FIFO image size
531 * for now, we support only ITU601 8 bit mode
533 cfg
= (EXYNOS_CISRCFMT_ITU601_8BIT
|
534 EXYNOS_CISRCFMT_SOURCEHSIZE(real_width
) |
535 EXYNOS_CISRCFMT_SOURCEVSIZE(buf
->buf
.height
));
536 fimc_write(ctx
, cfg
, EXYNOS_CISRCFMT
);
538 /* offset Y(RGB), Cb, Cr */
539 cfg
= (EXYNOS_CIIYOFF_HORIZONTAL(buf
->rect
.x
) |
540 EXYNOS_CIIYOFF_VERTICAL(buf
->rect
.y
));
541 fimc_write(ctx
, cfg
, EXYNOS_CIIYOFF
);
542 cfg
= (EXYNOS_CIICBOFF_HORIZONTAL(buf
->rect
.x
) |
543 EXYNOS_CIICBOFF_VERTICAL(buf
->rect
.y
));
544 fimc_write(ctx
, cfg
, EXYNOS_CIICBOFF
);
545 cfg
= (EXYNOS_CIICROFF_HORIZONTAL(buf
->rect
.x
) |
546 EXYNOS_CIICROFF_VERTICAL(buf
->rect
.y
));
547 fimc_write(ctx
, cfg
, EXYNOS_CIICROFF
);
549 fimc_set_window(ctx
, buf
);
552 static void fimc_src_set_addr(struct fimc_context
*ctx
,
553 struct exynos_drm_ipp_buffer
*buf
)
555 fimc_write(ctx
, buf
->dma_addr
[0], EXYNOS_CIIYSA(0));
556 fimc_write(ctx
, buf
->dma_addr
[1], EXYNOS_CIICBSA(0));
557 fimc_write(ctx
, buf
->dma_addr
[2], EXYNOS_CIICRSA(0));
560 static void fimc_dst_set_fmt_order(struct fimc_context
*ctx
, u32 fmt
)
564 DRM_DEBUG_KMS("fmt[0x%x]\n", fmt
);
567 cfg
= fimc_read(ctx
, EXYNOS_CISCCTRL
);
568 cfg
&= ~EXYNOS_CISCCTRL_OUTRGB_FMT_RGB_MASK
;
571 case DRM_FORMAT_RGB565
:
572 cfg
|= EXYNOS_CISCCTRL_OUTRGB_FMT_RGB565
;
573 fimc_write(ctx
, cfg
, EXYNOS_CISCCTRL
);
575 case DRM_FORMAT_RGB888
:
576 cfg
|= EXYNOS_CISCCTRL_OUTRGB_FMT_RGB888
;
577 fimc_write(ctx
, cfg
, EXYNOS_CISCCTRL
);
579 case DRM_FORMAT_XRGB8888
:
580 cfg
|= (EXYNOS_CISCCTRL_OUTRGB_FMT_RGB888
|
581 EXYNOS_CISCCTRL_EXTRGB_EXTENSION
);
582 fimc_write(ctx
, cfg
, EXYNOS_CISCCTRL
);
590 cfg
= fimc_read(ctx
, EXYNOS_CIOCTRL
);
591 cfg
&= ~(EXYNOS_CIOCTRL_ORDER2P_MASK
|
592 EXYNOS_CIOCTRL_ORDER422_MASK
|
593 EXYNOS_CIOCTRL_YCBCR_PLANE_MASK
);
596 case DRM_FORMAT_XRGB8888
:
597 cfg
|= EXYNOS_CIOCTRL_ALPHA_OUT
;
599 case DRM_FORMAT_YUYV
:
600 cfg
|= EXYNOS_CIOCTRL_ORDER422_YCBYCR
;
602 case DRM_FORMAT_YVYU
:
603 cfg
|= EXYNOS_CIOCTRL_ORDER422_YCRYCB
;
605 case DRM_FORMAT_UYVY
:
606 cfg
|= EXYNOS_CIOCTRL_ORDER422_CBYCRY
;
608 case DRM_FORMAT_VYUY
:
609 cfg
|= EXYNOS_CIOCTRL_ORDER422_CRYCBY
;
611 case DRM_FORMAT_NV21
:
612 case DRM_FORMAT_NV61
:
613 cfg
|= EXYNOS_CIOCTRL_ORDER2P_LSB_CRCB
;
614 cfg
|= EXYNOS_CIOCTRL_YCBCR_2PLANE
;
616 case DRM_FORMAT_YUV422
:
617 case DRM_FORMAT_YUV420
:
618 case DRM_FORMAT_YVU420
:
619 cfg
|= EXYNOS_CIOCTRL_YCBCR_3PLANE
;
621 case DRM_FORMAT_NV12
:
622 case DRM_FORMAT_NV16
:
623 cfg
|= EXYNOS_CIOCTRL_ORDER2P_LSB_CBCR
;
624 cfg
|= EXYNOS_CIOCTRL_YCBCR_2PLANE
;
628 fimc_write(ctx
, cfg
, EXYNOS_CIOCTRL
);
631 static void fimc_dst_set_fmt(struct fimc_context
*ctx
, u32 fmt
, bool tiled
)
635 DRM_DEBUG_KMS("fmt[0x%x]\n", fmt
);
637 cfg
= fimc_read(ctx
, EXYNOS_CIEXTEN
);
639 if (fmt
== DRM_FORMAT_AYUV
) {
640 cfg
|= EXYNOS_CIEXTEN_YUV444_OUT
;
641 fimc_write(ctx
, cfg
, EXYNOS_CIEXTEN
);
643 cfg
&= ~EXYNOS_CIEXTEN_YUV444_OUT
;
644 fimc_write(ctx
, cfg
, EXYNOS_CIEXTEN
);
646 cfg
= fimc_read(ctx
, EXYNOS_CITRGFMT
);
647 cfg
&= ~EXYNOS_CITRGFMT_OUTFORMAT_MASK
;
650 case DRM_FORMAT_RGB565
:
651 case DRM_FORMAT_RGB888
:
652 case DRM_FORMAT_XRGB8888
:
653 cfg
|= EXYNOS_CITRGFMT_OUTFORMAT_RGB
;
655 case DRM_FORMAT_YUYV
:
656 case DRM_FORMAT_YVYU
:
657 case DRM_FORMAT_UYVY
:
658 case DRM_FORMAT_VYUY
:
659 cfg
|= EXYNOS_CITRGFMT_OUTFORMAT_YCBCR422_1PLANE
;
661 case DRM_FORMAT_NV16
:
662 case DRM_FORMAT_NV61
:
663 case DRM_FORMAT_YUV422
:
664 cfg
|= EXYNOS_CITRGFMT_OUTFORMAT_YCBCR422
;
666 case DRM_FORMAT_YUV420
:
667 case DRM_FORMAT_YVU420
:
668 case DRM_FORMAT_NV12
:
669 case DRM_FORMAT_NV21
:
670 cfg
|= EXYNOS_CITRGFMT_OUTFORMAT_YCBCR420
;
674 fimc_write(ctx
, cfg
, EXYNOS_CITRGFMT
);
677 cfg
= fimc_read(ctx
, EXYNOS_CIDMAPARAM
);
678 cfg
&= ~EXYNOS_CIDMAPARAM_W_MODE_MASK
;
681 cfg
|= EXYNOS_CIDMAPARAM_W_MODE_64X32
;
683 cfg
|= EXYNOS_CIDMAPARAM_W_MODE_LINEAR
;
685 fimc_write(ctx
, cfg
, EXYNOS_CIDMAPARAM
);
687 fimc_dst_set_fmt_order(ctx
, fmt
);
690 static void fimc_dst_set_transf(struct fimc_context
*ctx
, unsigned int rotation
)
692 unsigned int degree
= rotation
& DRM_MODE_ROTATE_MASK
;
695 DRM_DEBUG_KMS("rotation[0x%x]\n", rotation
);
697 cfg
= fimc_read(ctx
, EXYNOS_CITRGFMT
);
698 cfg
&= ~EXYNOS_CITRGFMT_FLIP_MASK
;
699 cfg
&= ~EXYNOS_CITRGFMT_OUTROT90_CLOCKWISE
;
702 case DRM_MODE_ROTATE_0
:
703 if (rotation
& DRM_MODE_REFLECT_X
)
704 cfg
|= EXYNOS_CITRGFMT_FLIP_X_MIRROR
;
705 if (rotation
& DRM_MODE_REFLECT_Y
)
706 cfg
|= EXYNOS_CITRGFMT_FLIP_Y_MIRROR
;
708 case DRM_MODE_ROTATE_90
:
709 cfg
|= EXYNOS_CITRGFMT_OUTROT90_CLOCKWISE
;
710 if (rotation
& DRM_MODE_REFLECT_X
)
711 cfg
|= EXYNOS_CITRGFMT_FLIP_X_MIRROR
;
712 if (rotation
& DRM_MODE_REFLECT_Y
)
713 cfg
|= EXYNOS_CITRGFMT_FLIP_Y_MIRROR
;
715 case DRM_MODE_ROTATE_180
:
716 cfg
|= (EXYNOS_CITRGFMT_FLIP_X_MIRROR
|
717 EXYNOS_CITRGFMT_FLIP_Y_MIRROR
);
718 if (rotation
& DRM_MODE_REFLECT_X
)
719 cfg
&= ~EXYNOS_CITRGFMT_FLIP_X_MIRROR
;
720 if (rotation
& DRM_MODE_REFLECT_Y
)
721 cfg
&= ~EXYNOS_CITRGFMT_FLIP_Y_MIRROR
;
723 case DRM_MODE_ROTATE_270
:
724 cfg
|= (EXYNOS_CITRGFMT_OUTROT90_CLOCKWISE
|
725 EXYNOS_CITRGFMT_FLIP_X_MIRROR
|
726 EXYNOS_CITRGFMT_FLIP_Y_MIRROR
);
727 if (rotation
& DRM_MODE_REFLECT_X
)
728 cfg
&= ~EXYNOS_CITRGFMT_FLIP_X_MIRROR
;
729 if (rotation
& DRM_MODE_REFLECT_Y
)
730 cfg
&= ~EXYNOS_CITRGFMT_FLIP_Y_MIRROR
;
734 fimc_write(ctx
, cfg
, EXYNOS_CITRGFMT
);
737 static int fimc_set_prescaler(struct fimc_context
*ctx
, struct fimc_scaler
*sc
,
738 struct drm_exynos_ipp_task_rect
*src
,
739 struct drm_exynos_ipp_task_rect
*dst
)
741 u32 cfg
, cfg_ext
, shfactor
;
742 u32 pre_dst_width
, pre_dst_height
;
743 u32 hfactor
, vfactor
;
745 u32 src_w
, src_h
, dst_w
, dst_h
;
747 cfg_ext
= fimc_read(ctx
, EXYNOS_CITRGFMT
);
748 if (cfg_ext
& EXYNOS_CITRGFMT_INROT90_CLOCKWISE
) {
756 if (cfg_ext
& EXYNOS_CITRGFMT_OUTROT90_CLOCKWISE
) {
764 /* fimc_ippdrv_check_property assures that dividers are not null */
765 hfactor
= fls(src_w
/ dst_w
/ 2);
766 if (hfactor
> FIMC_SHFACTOR
/ 2) {
767 dev_err(ctx
->dev
, "failed to get ratio horizontal.\n");
771 vfactor
= fls(src_h
/ dst_h
/ 2);
772 if (vfactor
> FIMC_SHFACTOR
/ 2) {
773 dev_err(ctx
->dev
, "failed to get ratio vertical.\n");
777 pre_dst_width
= src_w
>> hfactor
;
778 pre_dst_height
= src_h
>> vfactor
;
779 DRM_DEBUG_KMS("pre_dst_width[%d]pre_dst_height[%d]\n",
780 pre_dst_width
, pre_dst_height
);
781 DRM_DEBUG_KMS("hfactor[%d]vfactor[%d]\n", hfactor
, vfactor
);
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
) ? true : false;
786 sc
->up_v
= (dst_h
>= src_h
) ? true : false;
787 DRM_DEBUG_KMS("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_DEBUG_KMS("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_DEBUG_KMS("range[%d]bypass[%d]up_h[%d]up_v[%d]\n",
810 sc
->range
, sc
->bypass
, sc
->up_h
, sc
->up_v
);
811 DRM_DEBUG_KMS("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_DEBUG_KMS("hsize[%d]vsize[%d]\n", real_width
, buf
->buf
.height
);
853 cfg
= (EXYNOS_ORGOSIZE_HORIZONTAL(real_width
) |
854 EXYNOS_ORGOSIZE_VERTICAL(buf
->buf
.height
));
856 fimc_write(ctx
, cfg
, EXYNOS_ORGOSIZE
);
858 DRM_DEBUG_KMS("x[%d]y[%d]w[%d]h[%d]\n", buf
->rect
.x
, buf
->rect
.y
,
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_DEBUG_KMS("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_DEBUG_KMS("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_DEBUG_KMS("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 drm_iommu_attach_device(drm_dev
, dev
);
1134 exynos_drm_ipp_register(drm_dev
, ipp
, &ipp_funcs
,
1135 DRM_EXYNOS_IPP_CAP_CROP
| DRM_EXYNOS_IPP_CAP_ROTATE
|
1136 DRM_EXYNOS_IPP_CAP_SCALE
| DRM_EXYNOS_IPP_CAP_CONVERT
,
1137 ctx
->formats
, ctx
->num_formats
, "fimc");
1139 dev_info(dev
, "The exynos fimc has been probed successfully\n");
1144 static void fimc_unbind(struct device
*dev
, struct device
*master
,
1147 struct fimc_context
*ctx
= dev_get_drvdata(dev
);
1148 struct drm_device
*drm_dev
= data
;
1149 struct exynos_drm_ipp
*ipp
= &ctx
->ipp
;
1151 exynos_drm_ipp_unregister(drm_dev
, ipp
);
1152 drm_iommu_detach_device(drm_dev
, dev
);
1155 static const struct component_ops fimc_component_ops
= {
1157 .unbind
= fimc_unbind
,
1160 static void fimc_put_clocks(struct fimc_context
*ctx
)
1164 for (i
= 0; i
< FIMC_CLKS_MAX
; i
++) {
1165 if (IS_ERR(ctx
->clocks
[i
]))
1167 clk_put(ctx
->clocks
[i
]);
1168 ctx
->clocks
[i
] = ERR_PTR(-EINVAL
);
1172 static int fimc_setup_clocks(struct fimc_context
*ctx
)
1174 struct device
*fimc_dev
= ctx
->dev
;
1178 for (i
= 0; i
< FIMC_CLKS_MAX
; i
++)
1179 ctx
->clocks
[i
] = ERR_PTR(-EINVAL
);
1181 for (i
= 0; i
< FIMC_CLKS_MAX
; i
++) {
1182 if (i
== FIMC_CLK_WB_A
|| i
== FIMC_CLK_WB_B
)
1183 dev
= fimc_dev
->parent
;
1187 ctx
->clocks
[i
] = clk_get(dev
, fimc_clock_names
[i
]);
1188 if (IS_ERR(ctx
->clocks
[i
])) {
1189 ret
= PTR_ERR(ctx
->clocks
[i
]);
1190 dev_err(fimc_dev
, "failed to get clock: %s\n",
1191 fimc_clock_names
[i
]);
1196 ret
= clk_prepare_enable(ctx
->clocks
[FIMC_CLK_LCLK
]);
1200 fimc_put_clocks(ctx
);
1204 int exynos_drm_check_fimc_device(struct device
*dev
)
1206 int id
= of_alias_get_id(dev
->of_node
, "fimc");
1208 if (id
>= 0 && (BIT(id
) & fimc_mask
))
1213 static const unsigned int fimc_formats
[] = {
1214 DRM_FORMAT_XRGB8888
, DRM_FORMAT_RGB565
,
1215 DRM_FORMAT_NV12
, DRM_FORMAT_NV16
, DRM_FORMAT_NV21
, DRM_FORMAT_NV61
,
1216 DRM_FORMAT_UYVY
, DRM_FORMAT_VYUY
, DRM_FORMAT_YUYV
, DRM_FORMAT_YVYU
,
1217 DRM_FORMAT_YUV420
, DRM_FORMAT_YVU420
, DRM_FORMAT_YUV422
,
1221 static const unsigned int fimc_tiled_formats
[] = {
1222 DRM_FORMAT_NV12
, DRM_FORMAT_NV21
,
1225 static const struct drm_exynos_ipp_limit fimc_4210_limits_v1
[] = {
1226 { IPP_SIZE_LIMIT(BUFFER
, .h
= { 16, 8192, 8 }, .v
= { 16, 8192, 2 }) },
1227 { IPP_SIZE_LIMIT(AREA
, .h
= { 16, 4224, 2 }, .v
= { 16, 0, 2 }) },
1228 { IPP_SIZE_LIMIT(ROTATED
, .h
= { 128, 1920 }, .v
= { 128, 0 }) },
1229 { IPP_SCALE_LIMIT(.h
= { (1 << 16) / 64, (1 << 16) * 64 },
1230 .v
= { (1 << 16) / 64, (1 << 16) * 64 }) },
1233 static const struct drm_exynos_ipp_limit fimc_4210_limits_v2
[] = {
1234 { IPP_SIZE_LIMIT(BUFFER
, .h
= { 16, 8192, 8 }, .v
= { 16, 8192, 2 }) },
1235 { IPP_SIZE_LIMIT(AREA
, .h
= { 16, 1920, 2 }, .v
= { 16, 0, 2 }) },
1236 { IPP_SIZE_LIMIT(ROTATED
, .h
= { 128, 1366 }, .v
= { 128, 0 }) },
1237 { IPP_SCALE_LIMIT(.h
= { (1 << 16) / 64, (1 << 16) * 64 },
1238 .v
= { (1 << 16) / 64, (1 << 16) * 64 }) },
1241 static const struct drm_exynos_ipp_limit fimc_4210_limits_tiled_v1
[] = {
1242 { IPP_SIZE_LIMIT(BUFFER
, .h
= { 128, 1920, 128 }, .v
= { 32, 1920, 32 }) },
1243 { IPP_SIZE_LIMIT(AREA
, .h
= { 128, 1920, 2 }, .v
= { 128, 0, 2 }) },
1244 { IPP_SCALE_LIMIT(.h
= { (1 << 16) / 64, (1 << 16) * 64 },
1245 .v
= { (1 << 16) / 64, (1 << 16) * 64 }) },
1248 static const struct drm_exynos_ipp_limit fimc_4210_limits_tiled_v2
[] = {
1249 { IPP_SIZE_LIMIT(BUFFER
, .h
= { 128, 1920, 128 }, .v
= { 32, 1920, 32 }) },
1250 { IPP_SIZE_LIMIT(AREA
, .h
= { 128, 1366, 2 }, .v
= { 128, 0, 2 }) },
1251 { IPP_SCALE_LIMIT(.h
= { (1 << 16) / 64, (1 << 16) * 64 },
1252 .v
= { (1 << 16) / 64, (1 << 16) * 64 }) },
1255 static int fimc_probe(struct platform_device
*pdev
)
1257 const struct drm_exynos_ipp_limit
*limits
;
1258 struct exynos_drm_ipp_formats
*formats
;
1259 struct device
*dev
= &pdev
->dev
;
1260 struct fimc_context
*ctx
;
1261 struct resource
*res
;
1263 int i
, j
, num_limits
, num_formats
;
1265 if (exynos_drm_check_fimc_device(dev
) != 0)
1268 ctx
= devm_kzalloc(dev
, sizeof(*ctx
), GFP_KERNEL
);
1273 ctx
->id
= of_alias_get_id(dev
->of_node
, "fimc");
1275 /* construct formats/limits array */
1276 num_formats
= ARRAY_SIZE(fimc_formats
) + ARRAY_SIZE(fimc_tiled_formats
);
1277 formats
= devm_kcalloc(dev
, num_formats
, sizeof(*formats
),
1282 /* linear formats */
1284 limits
= fimc_4210_limits_v1
;
1285 num_limits
= ARRAY_SIZE(fimc_4210_limits_v1
);
1287 limits
= fimc_4210_limits_v2
;
1288 num_limits
= ARRAY_SIZE(fimc_4210_limits_v2
);
1290 for (i
= 0; i
< ARRAY_SIZE(fimc_formats
); i
++) {
1291 formats
[i
].fourcc
= fimc_formats
[i
];
1292 formats
[i
].type
= DRM_EXYNOS_IPP_FORMAT_SOURCE
|
1293 DRM_EXYNOS_IPP_FORMAT_DESTINATION
;
1294 formats
[i
].limits
= limits
;
1295 formats
[i
].num_limits
= num_limits
;
1300 limits
= fimc_4210_limits_tiled_v1
;
1301 num_limits
= ARRAY_SIZE(fimc_4210_limits_tiled_v1
);
1303 limits
= fimc_4210_limits_tiled_v2
;
1304 num_limits
= ARRAY_SIZE(fimc_4210_limits_tiled_v2
);
1306 for (j
= i
, i
= 0; i
< ARRAY_SIZE(fimc_tiled_formats
); j
++, i
++) {
1307 formats
[j
].fourcc
= fimc_tiled_formats
[i
];
1308 formats
[j
].modifier
= DRM_FORMAT_MOD_SAMSUNG_64_32_TILE
;
1309 formats
[j
].type
= DRM_EXYNOS_IPP_FORMAT_SOURCE
|
1310 DRM_EXYNOS_IPP_FORMAT_DESTINATION
;
1311 formats
[j
].limits
= limits
;
1312 formats
[j
].num_limits
= num_limits
;
1315 ctx
->formats
= formats
;
1316 ctx
->num_formats
= num_formats
;
1318 /* resource memory */
1319 ctx
->regs_res
= platform_get_resource(pdev
, IORESOURCE_MEM
, 0);
1320 ctx
->regs
= devm_ioremap_resource(dev
, ctx
->regs_res
);
1321 if (IS_ERR(ctx
->regs
))
1322 return PTR_ERR(ctx
->regs
);
1325 res
= platform_get_resource(pdev
, IORESOURCE_IRQ
, 0);
1327 dev_err(dev
, "failed to request irq resource.\n");
1331 ret
= devm_request_irq(dev
, res
->start
, fimc_irq_handler
,
1332 0, dev_name(dev
), ctx
);
1334 dev_err(dev
, "failed to request irq.\n");
1338 ret
= fimc_setup_clocks(ctx
);
1342 spin_lock_init(&ctx
->lock
);
1343 platform_set_drvdata(pdev
, ctx
);
1345 pm_runtime_use_autosuspend(dev
);
1346 pm_runtime_set_autosuspend_delay(dev
, FIMC_AUTOSUSPEND_DELAY
);
1347 pm_runtime_enable(dev
);
1349 ret
= component_add(dev
, &fimc_component_ops
);
1353 dev_info(dev
, "drm fimc registered successfully.\n");
1358 pm_runtime_dont_use_autosuspend(dev
);
1359 pm_runtime_disable(dev
);
1360 fimc_put_clocks(ctx
);
1365 static int fimc_remove(struct platform_device
*pdev
)
1367 struct device
*dev
= &pdev
->dev
;
1368 struct fimc_context
*ctx
= get_fimc_context(dev
);
1370 component_del(dev
, &fimc_component_ops
);
1371 pm_runtime_dont_use_autosuspend(dev
);
1372 pm_runtime_disable(dev
);
1374 fimc_put_clocks(ctx
);
1380 static int fimc_runtime_suspend(struct device
*dev
)
1382 struct fimc_context
*ctx
= get_fimc_context(dev
);
1384 DRM_DEBUG_KMS("id[%d]\n", ctx
->id
);
1385 clk_disable_unprepare(ctx
->clocks
[FIMC_CLK_GATE
]);
1389 static int fimc_runtime_resume(struct device
*dev
)
1391 struct fimc_context
*ctx
= get_fimc_context(dev
);
1393 DRM_DEBUG_KMS("id[%d]\n", ctx
->id
);
1394 return clk_prepare_enable(ctx
->clocks
[FIMC_CLK_GATE
]);
1398 static const struct dev_pm_ops fimc_pm_ops
= {
1399 SET_SYSTEM_SLEEP_PM_OPS(pm_runtime_force_suspend
,
1400 pm_runtime_force_resume
)
1401 SET_RUNTIME_PM_OPS(fimc_runtime_suspend
, fimc_runtime_resume
, NULL
)
1404 static const struct of_device_id fimc_of_match
[] = {
1405 { .compatible
= "samsung,exynos4210-fimc" },
1406 { .compatible
= "samsung,exynos4212-fimc" },
1409 MODULE_DEVICE_TABLE(of
, fimc_of_match
);
1411 struct platform_driver fimc_driver
= {
1412 .probe
= fimc_probe
,
1413 .remove
= fimc_remove
,
1415 .of_match_table
= fimc_of_match
,
1416 .name
= "exynos-drm-fimc",
1417 .owner
= THIS_MODULE
,