2 * Copyright (C) 2012 Samsung Electronics Co.Ltd
4 * Eunchul Kim <chulspro.kim@samsung.com>
5 * Jinyoung Jeon <jy0.jeon@samsung.com>
6 * Sangmin Lee <lsmin.lee@samsung.com>
8 * This program is free software; you can redistribute it and/or modify it
9 * under the terms of the GNU General Public License as published by the
10 * Free Software Foundation; either version 2 of the License, or (at your
11 * option) any later version.
14 #include <linux/kernel.h>
15 #include <linux/platform_device.h>
16 #include <linux/mfd/syscon.h>
17 #include <linux/regmap.h>
18 #include <linux/clk.h>
19 #include <linux/pm_runtime.h>
21 #include <linux/spinlock.h>
24 #include <drm/exynos_drm.h>
25 #include "regs-fimc.h"
26 #include "exynos_drm_drv.h"
27 #include "exynos_drm_ipp.h"
28 #include "exynos_drm_fimc.h"
31 * FIMC stands for Fully Interactive Mobile Camera and
32 * supports image scaler/rotator and input/output DMA operations.
33 * input DMA reads image data from the memory.
34 * output DMA writes image data to memory.
35 * FIMC supports image rotation and image effect functions.
37 * M2M operation : supports crop/scale/rotation/csc so on.
38 * Memory ----> FIMC H/W ----> Memory.
39 * Writeback operation : supports cloned screen with FIMD.
40 * FIMD ----> FIMC H/W ----> Memory.
41 * Output operation : supports direct display using local path.
42 * Memory ----> FIMC H/W ----> FIMD.
47 * 1. check suspend/resume api if needed.
48 * 2. need to check use case platform_device_id.
49 * 3. check src/dst size with, height.
50 * 4. added check_prepare api for right register.
51 * 5. need to add supported list in prop_list.
52 * 6. check prescaler/scaler optimization.
55 #define FIMC_MAX_DEVS 4
56 #define FIMC_MAX_SRC 2
57 #define FIMC_MAX_DST 32
58 #define FIMC_SHFACTOR 10
59 #define FIMC_BUF_STOP 1
60 #define FIMC_BUF_START 2
61 #define FIMC_WIDTH_ITU_709 1280
62 #define FIMC_REFRESH_MAX 60
63 #define FIMC_REFRESH_MIN 12
64 #define FIMC_CROP_MAX 8192
65 #define FIMC_CROP_MIN 32
66 #define FIMC_SCALE_MAX 4224
67 #define FIMC_SCALE_MIN 32
69 #define get_fimc_context(dev) platform_get_drvdata(to_platform_device(dev))
70 #define get_ctx_from_ippdrv(ippdrv) container_of(ippdrv,\
71 struct fimc_context, ippdrv);
88 static const char * const fimc_clock_names[] = {
89 [FIMC_CLK_LCLK] = "sclk_fimc",
90 [FIMC_CLK_GATE] = "fimc",
91 [FIMC_CLK_WB_A] = "pxl_async0",
92 [FIMC_CLK_WB_B] = "pxl_async1",
93 [FIMC_CLK_MUX] = "mux",
94 [FIMC_CLK_PARENT] = "parent",
97 #define FIMC_DEFAULT_LCLK_FREQUENCY 133000000UL
100 * A structure of scaler.
102 * @range: narrow, wide.
103 * @bypass: unused scaler path.
104 * @up_h: horizontal scale up.
105 * @up_v: vertical scale up.
106 * @hratio: horizontal ratio.
107 * @vratio: vertical ratio.
119 * A structure of scaler capability.
121 * find user manual table 43-1.
122 * @in_hori: scaler input horizontal size.
123 * @bypass: scaler bypass mode.
124 * @dst_h_wo_rot: target horizontal size without output rotation.
125 * @dst_h_rot: target horizontal size with output rotation.
126 * @rl_w_wo_rot: real width without input rotation.
127 * @rl_h_rot: real height without output rotation.
129 struct fimc_capability {
142 * A structure of fimc context.
144 * @ippdrv: prepare initialization using ippdrv.
145 * @regs_res: register resources.
146 * @regs: memory mapped io registers.
147 * @lock: locking of operations.
148 * @clocks: fimc clocks.
149 * @clk_frequency: LCLK clock frequency.
150 * @sysreg: handle to SYSREG block regmap.
151 * @sc: scaler infomations.
152 * @pol: porarity of writeback.
155 * @suspended: qos operations.
157 struct fimc_context {
158 struct exynos_drm_ippdrv ippdrv;
159 struct resource *regs_res;
162 struct clk *clocks[FIMC_CLKS_MAX];
164 struct regmap *sysreg;
165 struct fimc_scaler sc;
171 static u32 fimc_read(struct fimc_context *ctx, u32 reg)
173 return readl(ctx->regs + reg);
176 static void fimc_write(struct fimc_context *ctx, u32 val, u32 reg)
178 writel(val, ctx->regs + reg);
181 static void fimc_set_bits(struct fimc_context *ctx, u32 reg, u32 bits)
183 void __iomem *r = ctx->regs + reg;
185 writel(readl(r) | bits, r);
188 static void fimc_clear_bits(struct fimc_context *ctx, u32 reg, u32 bits)
190 void __iomem *r = ctx->regs + reg;
192 writel(readl(r) & ~bits, r);
195 static void fimc_sw_reset(struct fimc_context *ctx)
199 /* stop dma operation */
200 cfg = fimc_read(ctx, EXYNOS_CISTATUS);
201 if (EXYNOS_CISTATUS_GET_ENVID_STATUS(cfg))
202 fimc_clear_bits(ctx, EXYNOS_MSCTRL, EXYNOS_MSCTRL_ENVID);
204 fimc_set_bits(ctx, EXYNOS_CISRCFMT, EXYNOS_CISRCFMT_ITU601_8BIT);
206 /* disable image capture */
207 fimc_clear_bits(ctx, EXYNOS_CIIMGCPT,
208 EXYNOS_CIIMGCPT_IMGCPTEN_SC | EXYNOS_CIIMGCPT_IMGCPTEN);
211 fimc_set_bits(ctx, EXYNOS_CIGCTRL, EXYNOS_CIGCTRL_SWRST);
213 /* s/w reset complete */
214 fimc_clear_bits(ctx, EXYNOS_CIGCTRL, EXYNOS_CIGCTRL_SWRST);
217 fimc_write(ctx, 0x0, EXYNOS_CIFCNTSEQ);
220 static int fimc_set_camblk_fimd0_wb(struct fimc_context *ctx)
222 return regmap_update_bits(ctx->sysreg, SYSREG_CAMERA_BLK,
223 SYSREG_FIMD0WB_DEST_MASK,
224 ctx->id << SYSREG_FIMD0WB_DEST_SHIFT);
227 static void fimc_set_type_ctrl(struct fimc_context *ctx, enum fimc_wb wb)
231 DRM_DEBUG_KMS("wb[%d]\n", wb);
233 cfg = fimc_read(ctx, EXYNOS_CIGCTRL);
234 cfg &= ~(EXYNOS_CIGCTRL_TESTPATTERN_MASK |
235 EXYNOS_CIGCTRL_SELCAM_ITU_MASK |
236 EXYNOS_CIGCTRL_SELCAM_MIPI_MASK |
237 EXYNOS_CIGCTRL_SELCAM_FIMC_MASK |
238 EXYNOS_CIGCTRL_SELWB_CAMIF_MASK |
239 EXYNOS_CIGCTRL_SELWRITEBACK_MASK);
243 cfg |= (EXYNOS_CIGCTRL_SELWRITEBACK_A |
244 EXYNOS_CIGCTRL_SELWB_CAMIF_WRITEBACK);
247 cfg |= (EXYNOS_CIGCTRL_SELWRITEBACK_B |
248 EXYNOS_CIGCTRL_SELWB_CAMIF_WRITEBACK);
252 cfg |= (EXYNOS_CIGCTRL_SELCAM_ITU_A |
253 EXYNOS_CIGCTRL_SELWRITEBACK_A |
254 EXYNOS_CIGCTRL_SELCAM_MIPI_A |
255 EXYNOS_CIGCTRL_SELCAM_FIMC_ITU);
259 fimc_write(ctx, cfg, EXYNOS_CIGCTRL);
262 static void fimc_handle_jpeg(struct fimc_context *ctx, bool enable)
266 DRM_DEBUG_KMS("enable[%d]\n", enable);
268 cfg = fimc_read(ctx, EXYNOS_CIGCTRL);
270 cfg |= EXYNOS_CIGCTRL_CAM_JPEG;
272 cfg &= ~EXYNOS_CIGCTRL_CAM_JPEG;
274 fimc_write(ctx, cfg, EXYNOS_CIGCTRL);
277 static void fimc_mask_irq(struct fimc_context *ctx, bool enable)
281 DRM_DEBUG_KMS("enable[%d]\n", enable);
283 cfg = fimc_read(ctx, EXYNOS_CIGCTRL);
285 cfg &= ~EXYNOS_CIGCTRL_IRQ_OVFEN;
286 cfg |= EXYNOS_CIGCTRL_IRQ_ENABLE | EXYNOS_CIGCTRL_IRQ_LEVEL;
288 cfg &= ~EXYNOS_CIGCTRL_IRQ_ENABLE;
289 fimc_write(ctx, cfg, EXYNOS_CIGCTRL);
292 static void fimc_clear_irq(struct fimc_context *ctx)
294 fimc_set_bits(ctx, EXYNOS_CIGCTRL, EXYNOS_CIGCTRL_IRQ_CLR);
297 static bool fimc_check_ovf(struct fimc_context *ctx)
299 struct exynos_drm_ippdrv *ippdrv = &ctx->ippdrv;
302 status = fimc_read(ctx, EXYNOS_CISTATUS);
303 flag = EXYNOS_CISTATUS_OVFIY | EXYNOS_CISTATUS_OVFICB |
304 EXYNOS_CISTATUS_OVFICR;
306 DRM_DEBUG_KMS("flag[0x%x]\n", flag);
309 fimc_set_bits(ctx, EXYNOS_CIWDOFST,
310 EXYNOS_CIWDOFST_CLROVFIY | EXYNOS_CIWDOFST_CLROVFICB |
311 EXYNOS_CIWDOFST_CLROVFICR);
313 dev_err(ippdrv->dev, "occurred overflow at %d, status 0x%x.\n",
321 static bool fimc_check_frame_end(struct fimc_context *ctx)
325 cfg = fimc_read(ctx, EXYNOS_CISTATUS);
327 DRM_DEBUG_KMS("cfg[0x%x]\n", cfg);
329 if (!(cfg & EXYNOS_CISTATUS_FRAMEEND))
332 cfg &= ~(EXYNOS_CISTATUS_FRAMEEND);
333 fimc_write(ctx, cfg, EXYNOS_CISTATUS);
338 static int fimc_get_buf_id(struct fimc_context *ctx)
341 int frame_cnt, buf_id;
343 cfg = fimc_read(ctx, EXYNOS_CISTATUS2);
344 frame_cnt = EXYNOS_CISTATUS2_GET_FRAMECOUNT_BEFORE(cfg);
347 frame_cnt = EXYNOS_CISTATUS2_GET_FRAMECOUNT_PRESENT(cfg);
349 DRM_DEBUG_KMS("present[%d]before[%d]\n",
350 EXYNOS_CISTATUS2_GET_FRAMECOUNT_PRESENT(cfg),
351 EXYNOS_CISTATUS2_GET_FRAMECOUNT_BEFORE(cfg));
353 if (frame_cnt == 0) {
354 DRM_ERROR("failed to get frame count.\n");
358 buf_id = frame_cnt - 1;
359 DRM_DEBUG_KMS("buf_id[%d]\n", buf_id);
364 static void fimc_handle_lastend(struct fimc_context *ctx, bool enable)
368 DRM_DEBUG_KMS("enable[%d]\n", enable);
370 cfg = fimc_read(ctx, EXYNOS_CIOCTRL);
372 cfg |= EXYNOS_CIOCTRL_LASTENDEN;
374 cfg &= ~EXYNOS_CIOCTRL_LASTENDEN;
376 fimc_write(ctx, cfg, EXYNOS_CIOCTRL);
380 static int fimc_src_set_fmt_order(struct fimc_context *ctx, u32 fmt)
382 struct exynos_drm_ippdrv *ippdrv = &ctx->ippdrv;
385 DRM_DEBUG_KMS("fmt[0x%x]\n", fmt);
388 cfg = fimc_read(ctx, EXYNOS_CISCCTRL);
389 cfg &= ~EXYNOS_CISCCTRL_INRGB_FMT_RGB_MASK;
392 case DRM_FORMAT_RGB565:
393 cfg |= EXYNOS_CISCCTRL_INRGB_FMT_RGB565;
394 fimc_write(ctx, cfg, EXYNOS_CISCCTRL);
396 case DRM_FORMAT_RGB888:
397 case DRM_FORMAT_XRGB8888:
398 cfg |= EXYNOS_CISCCTRL_INRGB_FMT_RGB888;
399 fimc_write(ctx, cfg, EXYNOS_CISCCTRL);
407 cfg = fimc_read(ctx, EXYNOS_MSCTRL);
408 cfg &= ~(EXYNOS_MSCTRL_ORDER2P_SHIFT_MASK |
409 EXYNOS_MSCTRL_C_INT_IN_2PLANE |
410 EXYNOS_MSCTRL_ORDER422_YCBYCR);
413 case DRM_FORMAT_YUYV:
414 cfg |= EXYNOS_MSCTRL_ORDER422_YCBYCR;
416 case DRM_FORMAT_YVYU:
417 cfg |= EXYNOS_MSCTRL_ORDER422_YCRYCB;
419 case DRM_FORMAT_UYVY:
420 cfg |= EXYNOS_MSCTRL_ORDER422_CBYCRY;
422 case DRM_FORMAT_VYUY:
423 case DRM_FORMAT_YUV444:
424 cfg |= EXYNOS_MSCTRL_ORDER422_CRYCBY;
426 case DRM_FORMAT_NV21:
427 case DRM_FORMAT_NV61:
428 cfg |= (EXYNOS_MSCTRL_ORDER2P_LSB_CRCB |
429 EXYNOS_MSCTRL_C_INT_IN_2PLANE);
431 case DRM_FORMAT_YUV422:
432 case DRM_FORMAT_YUV420:
433 case DRM_FORMAT_YVU420:
434 cfg |= EXYNOS_MSCTRL_C_INT_IN_3PLANE;
436 case DRM_FORMAT_NV12:
437 case DRM_FORMAT_NV16:
438 cfg |= (EXYNOS_MSCTRL_ORDER2P_LSB_CBCR |
439 EXYNOS_MSCTRL_C_INT_IN_2PLANE);
442 dev_err(ippdrv->dev, "invalid source yuv order 0x%x.\n", fmt);
446 fimc_write(ctx, cfg, EXYNOS_MSCTRL);
451 static int fimc_src_set_fmt(struct device *dev, u32 fmt)
453 struct fimc_context *ctx = get_fimc_context(dev);
454 struct exynos_drm_ippdrv *ippdrv = &ctx->ippdrv;
457 DRM_DEBUG_KMS("fmt[0x%x]\n", fmt);
459 cfg = fimc_read(ctx, EXYNOS_MSCTRL);
460 cfg &= ~EXYNOS_MSCTRL_INFORMAT_RGB;
463 case DRM_FORMAT_RGB565:
464 case DRM_FORMAT_RGB888:
465 case DRM_FORMAT_XRGB8888:
466 cfg |= EXYNOS_MSCTRL_INFORMAT_RGB;
468 case DRM_FORMAT_YUV444:
469 cfg |= EXYNOS_MSCTRL_INFORMAT_YCBCR420;
471 case DRM_FORMAT_YUYV:
472 case DRM_FORMAT_YVYU:
473 case DRM_FORMAT_UYVY:
474 case DRM_FORMAT_VYUY:
475 cfg |= EXYNOS_MSCTRL_INFORMAT_YCBCR422_1PLANE;
477 case DRM_FORMAT_NV16:
478 case DRM_FORMAT_NV61:
479 case DRM_FORMAT_YUV422:
480 cfg |= EXYNOS_MSCTRL_INFORMAT_YCBCR422;
482 case DRM_FORMAT_YUV420:
483 case DRM_FORMAT_YVU420:
484 case DRM_FORMAT_NV12:
485 case DRM_FORMAT_NV21:
486 cfg |= EXYNOS_MSCTRL_INFORMAT_YCBCR420;
489 dev_err(ippdrv->dev, "invalid source format 0x%x.\n", fmt);
493 fimc_write(ctx, cfg, EXYNOS_MSCTRL);
495 cfg = fimc_read(ctx, EXYNOS_CIDMAPARAM);
496 cfg &= ~EXYNOS_CIDMAPARAM_R_MODE_MASK;
498 cfg |= EXYNOS_CIDMAPARAM_R_MODE_LINEAR;
500 fimc_write(ctx, cfg, EXYNOS_CIDMAPARAM);
502 return fimc_src_set_fmt_order(ctx, fmt);
505 static int fimc_src_set_transf(struct device *dev,
506 enum drm_exynos_degree degree,
507 enum drm_exynos_flip flip, bool *swap)
509 struct fimc_context *ctx = get_fimc_context(dev);
510 struct exynos_drm_ippdrv *ippdrv = &ctx->ippdrv;
513 DRM_DEBUG_KMS("degree[%d]flip[0x%x]\n", degree, flip);
515 cfg1 = fimc_read(ctx, EXYNOS_MSCTRL);
516 cfg1 &= ~(EXYNOS_MSCTRL_FLIP_X_MIRROR |
517 EXYNOS_MSCTRL_FLIP_Y_MIRROR);
519 cfg2 = fimc_read(ctx, EXYNOS_CITRGFMT);
520 cfg2 &= ~EXYNOS_CITRGFMT_INROT90_CLOCKWISE;
523 case EXYNOS_DRM_DEGREE_0:
524 if (flip & EXYNOS_DRM_FLIP_VERTICAL)
525 cfg1 |= EXYNOS_MSCTRL_FLIP_X_MIRROR;
526 if (flip & EXYNOS_DRM_FLIP_HORIZONTAL)
527 cfg1 |= EXYNOS_MSCTRL_FLIP_Y_MIRROR;
529 case EXYNOS_DRM_DEGREE_90:
530 cfg2 |= EXYNOS_CITRGFMT_INROT90_CLOCKWISE;
531 if (flip & EXYNOS_DRM_FLIP_VERTICAL)
532 cfg1 |= EXYNOS_MSCTRL_FLIP_X_MIRROR;
533 if (flip & EXYNOS_DRM_FLIP_HORIZONTAL)
534 cfg1 |= EXYNOS_MSCTRL_FLIP_Y_MIRROR;
536 case EXYNOS_DRM_DEGREE_180:
537 cfg1 |= (EXYNOS_MSCTRL_FLIP_X_MIRROR |
538 EXYNOS_MSCTRL_FLIP_Y_MIRROR);
539 if (flip & EXYNOS_DRM_FLIP_VERTICAL)
540 cfg1 &= ~EXYNOS_MSCTRL_FLIP_X_MIRROR;
541 if (flip & EXYNOS_DRM_FLIP_HORIZONTAL)
542 cfg1 &= ~EXYNOS_MSCTRL_FLIP_Y_MIRROR;
544 case EXYNOS_DRM_DEGREE_270:
545 cfg1 |= (EXYNOS_MSCTRL_FLIP_X_MIRROR |
546 EXYNOS_MSCTRL_FLIP_Y_MIRROR);
547 cfg2 |= EXYNOS_CITRGFMT_INROT90_CLOCKWISE;
548 if (flip & EXYNOS_DRM_FLIP_VERTICAL)
549 cfg1 &= ~EXYNOS_MSCTRL_FLIP_X_MIRROR;
550 if (flip & EXYNOS_DRM_FLIP_HORIZONTAL)
551 cfg1 &= ~EXYNOS_MSCTRL_FLIP_Y_MIRROR;
554 dev_err(ippdrv->dev, "invalid degree value %d.\n", degree);
558 fimc_write(ctx, cfg1, EXYNOS_MSCTRL);
559 fimc_write(ctx, cfg2, EXYNOS_CITRGFMT);
560 *swap = (cfg2 & EXYNOS_CITRGFMT_INROT90_CLOCKWISE) ? 1 : 0;
565 static int fimc_set_window(struct fimc_context *ctx,
566 struct drm_exynos_pos *pos, struct drm_exynos_sz *sz)
568 u32 cfg, h1, h2, v1, v2;
572 h2 = sz->hsize - pos->w - pos->x;
574 v2 = sz->vsize - pos->h - pos->y;
576 DRM_DEBUG_KMS("x[%d]y[%d]w[%d]h[%d]hsize[%d]vsize[%d]\n",
577 pos->x, pos->y, pos->w, pos->h, sz->hsize, sz->vsize);
578 DRM_DEBUG_KMS("h1[%d]h2[%d]v1[%d]v2[%d]\n", h1, h2, v1, v2);
581 * set window offset 1, 2 size
582 * check figure 43-21 in user manual
584 cfg = fimc_read(ctx, EXYNOS_CIWDOFST);
585 cfg &= ~(EXYNOS_CIWDOFST_WINHOROFST_MASK |
586 EXYNOS_CIWDOFST_WINVEROFST_MASK);
587 cfg |= (EXYNOS_CIWDOFST_WINHOROFST(h1) |
588 EXYNOS_CIWDOFST_WINVEROFST(v1));
589 cfg |= EXYNOS_CIWDOFST_WINOFSEN;
590 fimc_write(ctx, cfg, EXYNOS_CIWDOFST);
592 cfg = (EXYNOS_CIWDOFST2_WINHOROFST2(h2) |
593 EXYNOS_CIWDOFST2_WINVEROFST2(v2));
594 fimc_write(ctx, cfg, EXYNOS_CIWDOFST2);
599 static int fimc_src_set_size(struct device *dev, int swap,
600 struct drm_exynos_pos *pos, struct drm_exynos_sz *sz)
602 struct fimc_context *ctx = get_fimc_context(dev);
603 struct drm_exynos_pos img_pos = *pos;
604 struct drm_exynos_sz img_sz = *sz;
607 DRM_DEBUG_KMS("swap[%d]hsize[%d]vsize[%d]\n",
608 swap, sz->hsize, sz->vsize);
611 cfg = (EXYNOS_ORGISIZE_HORIZONTAL(img_sz.hsize) |
612 EXYNOS_ORGISIZE_VERTICAL(img_sz.vsize));
614 fimc_write(ctx, cfg, EXYNOS_ORGISIZE);
616 DRM_DEBUG_KMS("x[%d]y[%d]w[%d]h[%d]\n", pos->x, pos->y, pos->w, pos->h);
621 img_sz.hsize = sz->vsize;
622 img_sz.vsize = sz->hsize;
625 /* set input DMA image size */
626 cfg = fimc_read(ctx, EXYNOS_CIREAL_ISIZE);
627 cfg &= ~(EXYNOS_CIREAL_ISIZE_HEIGHT_MASK |
628 EXYNOS_CIREAL_ISIZE_WIDTH_MASK);
629 cfg |= (EXYNOS_CIREAL_ISIZE_WIDTH(img_pos.w) |
630 EXYNOS_CIREAL_ISIZE_HEIGHT(img_pos.h));
631 fimc_write(ctx, cfg, EXYNOS_CIREAL_ISIZE);
634 * set input FIFO image size
635 * for now, we support only ITU601 8 bit mode
637 cfg = (EXYNOS_CISRCFMT_ITU601_8BIT |
638 EXYNOS_CISRCFMT_SOURCEHSIZE(img_sz.hsize) |
639 EXYNOS_CISRCFMT_SOURCEVSIZE(img_sz.vsize));
640 fimc_write(ctx, cfg, EXYNOS_CISRCFMT);
642 /* offset Y(RGB), Cb, Cr */
643 cfg = (EXYNOS_CIIYOFF_HORIZONTAL(img_pos.x) |
644 EXYNOS_CIIYOFF_VERTICAL(img_pos.y));
645 fimc_write(ctx, cfg, EXYNOS_CIIYOFF);
646 cfg = (EXYNOS_CIICBOFF_HORIZONTAL(img_pos.x) |
647 EXYNOS_CIICBOFF_VERTICAL(img_pos.y));
648 fimc_write(ctx, cfg, EXYNOS_CIICBOFF);
649 cfg = (EXYNOS_CIICROFF_HORIZONTAL(img_pos.x) |
650 EXYNOS_CIICROFF_VERTICAL(img_pos.y));
651 fimc_write(ctx, cfg, EXYNOS_CIICROFF);
653 return fimc_set_window(ctx, &img_pos, &img_sz);
656 static int fimc_src_set_addr(struct device *dev,
657 struct drm_exynos_ipp_buf_info *buf_info, u32 buf_id,
658 enum drm_exynos_ipp_buf_type buf_type)
660 struct fimc_context *ctx = get_fimc_context(dev);
661 struct exynos_drm_ippdrv *ippdrv = &ctx->ippdrv;
662 struct drm_exynos_ipp_cmd_node *c_node = ippdrv->c_node;
663 struct drm_exynos_ipp_property *property;
664 struct drm_exynos_ipp_config *config;
667 DRM_ERROR("failed to get c_node.\n");
671 property = &c_node->property;
673 DRM_DEBUG_KMS("prop_id[%d]buf_id[%d]buf_type[%d]\n",
674 property->prop_id, buf_id, buf_type);
676 if (buf_id > FIMC_MAX_SRC) {
677 dev_info(ippdrv->dev, "invalid buf_id %d.\n", buf_id);
681 /* address register set */
683 case IPP_BUF_ENQUEUE:
684 config = &property->config[EXYNOS_DRM_OPS_SRC];
685 fimc_write(ctx, buf_info->base[EXYNOS_DRM_PLANAR_Y],
688 if (config->fmt == DRM_FORMAT_YVU420) {
689 fimc_write(ctx, buf_info->base[EXYNOS_DRM_PLANAR_CR],
691 fimc_write(ctx, buf_info->base[EXYNOS_DRM_PLANAR_CB],
694 fimc_write(ctx, buf_info->base[EXYNOS_DRM_PLANAR_CB],
696 fimc_write(ctx, buf_info->base[EXYNOS_DRM_PLANAR_CR],
700 case IPP_BUF_DEQUEUE:
701 fimc_write(ctx, 0x0, EXYNOS_CIIYSA0);
702 fimc_write(ctx, 0x0, EXYNOS_CIICBSA0);
703 fimc_write(ctx, 0x0, EXYNOS_CIICRSA0);
713 static struct exynos_drm_ipp_ops fimc_src_ops = {
714 .set_fmt = fimc_src_set_fmt,
715 .set_transf = fimc_src_set_transf,
716 .set_size = fimc_src_set_size,
717 .set_addr = fimc_src_set_addr,
720 static int fimc_dst_set_fmt_order(struct fimc_context *ctx, u32 fmt)
722 struct exynos_drm_ippdrv *ippdrv = &ctx->ippdrv;
725 DRM_DEBUG_KMS("fmt[0x%x]\n", fmt);
728 cfg = fimc_read(ctx, EXYNOS_CISCCTRL);
729 cfg &= ~EXYNOS_CISCCTRL_OUTRGB_FMT_RGB_MASK;
732 case DRM_FORMAT_RGB565:
733 cfg |= EXYNOS_CISCCTRL_OUTRGB_FMT_RGB565;
734 fimc_write(ctx, cfg, EXYNOS_CISCCTRL);
736 case DRM_FORMAT_RGB888:
737 cfg |= EXYNOS_CISCCTRL_OUTRGB_FMT_RGB888;
738 fimc_write(ctx, cfg, EXYNOS_CISCCTRL);
740 case DRM_FORMAT_XRGB8888:
741 cfg |= (EXYNOS_CISCCTRL_OUTRGB_FMT_RGB888 |
742 EXYNOS_CISCCTRL_EXTRGB_EXTENSION);
743 fimc_write(ctx, cfg, EXYNOS_CISCCTRL);
751 cfg = fimc_read(ctx, EXYNOS_CIOCTRL);
752 cfg &= ~(EXYNOS_CIOCTRL_ORDER2P_MASK |
753 EXYNOS_CIOCTRL_ORDER422_MASK |
754 EXYNOS_CIOCTRL_YCBCR_PLANE_MASK);
757 case DRM_FORMAT_XRGB8888:
758 cfg |= EXYNOS_CIOCTRL_ALPHA_OUT;
760 case DRM_FORMAT_YUYV:
761 cfg |= EXYNOS_CIOCTRL_ORDER422_YCBYCR;
763 case DRM_FORMAT_YVYU:
764 cfg |= EXYNOS_CIOCTRL_ORDER422_YCRYCB;
766 case DRM_FORMAT_UYVY:
767 cfg |= EXYNOS_CIOCTRL_ORDER422_CBYCRY;
769 case DRM_FORMAT_VYUY:
770 cfg |= EXYNOS_CIOCTRL_ORDER422_CRYCBY;
772 case DRM_FORMAT_NV21:
773 case DRM_FORMAT_NV61:
774 cfg |= EXYNOS_CIOCTRL_ORDER2P_LSB_CRCB;
775 cfg |= EXYNOS_CIOCTRL_YCBCR_2PLANE;
777 case DRM_FORMAT_YUV422:
778 case DRM_FORMAT_YUV420:
779 case DRM_FORMAT_YVU420:
780 cfg |= EXYNOS_CIOCTRL_YCBCR_3PLANE;
782 case DRM_FORMAT_NV12:
783 case DRM_FORMAT_NV16:
784 cfg |= EXYNOS_CIOCTRL_ORDER2P_LSB_CBCR;
785 cfg |= EXYNOS_CIOCTRL_YCBCR_2PLANE;
788 dev_err(ippdrv->dev, "invalid target yuv order 0x%x.\n", fmt);
792 fimc_write(ctx, cfg, EXYNOS_CIOCTRL);
797 static int fimc_dst_set_fmt(struct device *dev, u32 fmt)
799 struct fimc_context *ctx = get_fimc_context(dev);
800 struct exynos_drm_ippdrv *ippdrv = &ctx->ippdrv;
803 DRM_DEBUG_KMS("fmt[0x%x]\n", fmt);
805 cfg = fimc_read(ctx, EXYNOS_CIEXTEN);
807 if (fmt == DRM_FORMAT_AYUV) {
808 cfg |= EXYNOS_CIEXTEN_YUV444_OUT;
809 fimc_write(ctx, cfg, EXYNOS_CIEXTEN);
811 cfg &= ~EXYNOS_CIEXTEN_YUV444_OUT;
812 fimc_write(ctx, cfg, EXYNOS_CIEXTEN);
814 cfg = fimc_read(ctx, EXYNOS_CITRGFMT);
815 cfg &= ~EXYNOS_CITRGFMT_OUTFORMAT_MASK;
818 case DRM_FORMAT_RGB565:
819 case DRM_FORMAT_RGB888:
820 case DRM_FORMAT_XRGB8888:
821 cfg |= EXYNOS_CITRGFMT_OUTFORMAT_RGB;
823 case DRM_FORMAT_YUYV:
824 case DRM_FORMAT_YVYU:
825 case DRM_FORMAT_UYVY:
826 case DRM_FORMAT_VYUY:
827 cfg |= EXYNOS_CITRGFMT_OUTFORMAT_YCBCR422_1PLANE;
829 case DRM_FORMAT_NV16:
830 case DRM_FORMAT_NV61:
831 case DRM_FORMAT_YUV422:
832 cfg |= EXYNOS_CITRGFMT_OUTFORMAT_YCBCR422;
834 case DRM_FORMAT_YUV420:
835 case DRM_FORMAT_YVU420:
836 case DRM_FORMAT_NV12:
837 case DRM_FORMAT_NV21:
838 cfg |= EXYNOS_CITRGFMT_OUTFORMAT_YCBCR420;
841 dev_err(ippdrv->dev, "invalid target format 0x%x.\n",
846 fimc_write(ctx, cfg, EXYNOS_CITRGFMT);
849 cfg = fimc_read(ctx, EXYNOS_CIDMAPARAM);
850 cfg &= ~EXYNOS_CIDMAPARAM_W_MODE_MASK;
852 cfg |= EXYNOS_CIDMAPARAM_W_MODE_LINEAR;
854 fimc_write(ctx, cfg, EXYNOS_CIDMAPARAM);
856 return fimc_dst_set_fmt_order(ctx, fmt);
859 static int fimc_dst_set_transf(struct device *dev,
860 enum drm_exynos_degree degree,
861 enum drm_exynos_flip flip, bool *swap)
863 struct fimc_context *ctx = get_fimc_context(dev);
864 struct exynos_drm_ippdrv *ippdrv = &ctx->ippdrv;
867 DRM_DEBUG_KMS("degree[%d]flip[0x%x]\n", degree, flip);
869 cfg = fimc_read(ctx, EXYNOS_CITRGFMT);
870 cfg &= ~EXYNOS_CITRGFMT_FLIP_MASK;
871 cfg &= ~EXYNOS_CITRGFMT_OUTROT90_CLOCKWISE;
874 case EXYNOS_DRM_DEGREE_0:
875 if (flip & EXYNOS_DRM_FLIP_VERTICAL)
876 cfg |= EXYNOS_CITRGFMT_FLIP_X_MIRROR;
877 if (flip & EXYNOS_DRM_FLIP_HORIZONTAL)
878 cfg |= EXYNOS_CITRGFMT_FLIP_Y_MIRROR;
880 case EXYNOS_DRM_DEGREE_90:
881 cfg |= EXYNOS_CITRGFMT_OUTROT90_CLOCKWISE;
882 if (flip & EXYNOS_DRM_FLIP_VERTICAL)
883 cfg |= EXYNOS_CITRGFMT_FLIP_X_MIRROR;
884 if (flip & EXYNOS_DRM_FLIP_HORIZONTAL)
885 cfg |= EXYNOS_CITRGFMT_FLIP_Y_MIRROR;
887 case EXYNOS_DRM_DEGREE_180:
888 cfg |= (EXYNOS_CITRGFMT_FLIP_X_MIRROR |
889 EXYNOS_CITRGFMT_FLIP_Y_MIRROR);
890 if (flip & EXYNOS_DRM_FLIP_VERTICAL)
891 cfg &= ~EXYNOS_CITRGFMT_FLIP_X_MIRROR;
892 if (flip & EXYNOS_DRM_FLIP_HORIZONTAL)
893 cfg &= ~EXYNOS_CITRGFMT_FLIP_Y_MIRROR;
895 case EXYNOS_DRM_DEGREE_270:
896 cfg |= (EXYNOS_CITRGFMT_OUTROT90_CLOCKWISE |
897 EXYNOS_CITRGFMT_FLIP_X_MIRROR |
898 EXYNOS_CITRGFMT_FLIP_Y_MIRROR);
899 if (flip & EXYNOS_DRM_FLIP_VERTICAL)
900 cfg &= ~EXYNOS_CITRGFMT_FLIP_X_MIRROR;
901 if (flip & EXYNOS_DRM_FLIP_HORIZONTAL)
902 cfg &= ~EXYNOS_CITRGFMT_FLIP_Y_MIRROR;
905 dev_err(ippdrv->dev, "invalid degree value %d.\n", degree);
909 fimc_write(ctx, cfg, EXYNOS_CITRGFMT);
910 *swap = (cfg & EXYNOS_CITRGFMT_OUTROT90_CLOCKWISE) ? 1 : 0;
915 static int fimc_set_prescaler(struct fimc_context *ctx, struct fimc_scaler *sc,
916 struct drm_exynos_pos *src, struct drm_exynos_pos *dst)
918 struct exynos_drm_ippdrv *ippdrv = &ctx->ippdrv;
919 u32 cfg, cfg_ext, shfactor;
920 u32 pre_dst_width, pre_dst_height;
921 u32 hfactor, vfactor;
923 u32 src_w, src_h, dst_w, dst_h;
925 cfg_ext = fimc_read(ctx, EXYNOS_CITRGFMT);
926 if (cfg_ext & EXYNOS_CITRGFMT_INROT90_CLOCKWISE) {
934 if (cfg_ext & EXYNOS_CITRGFMT_OUTROT90_CLOCKWISE) {
942 /* fimc_ippdrv_check_property assures that dividers are not null */
943 hfactor = fls(src_w / dst_w / 2);
944 if (hfactor > FIMC_SHFACTOR / 2) {
945 dev_err(ippdrv->dev, "failed to get ratio horizontal.\n");
949 vfactor = fls(src_h / dst_h / 2);
950 if (vfactor > FIMC_SHFACTOR / 2) {
951 dev_err(ippdrv->dev, "failed to get ratio vertical.\n");
955 pre_dst_width = src_w >> hfactor;
956 pre_dst_height = src_h >> vfactor;
957 DRM_DEBUG_KMS("pre_dst_width[%d]pre_dst_height[%d]\n",
958 pre_dst_width, pre_dst_height);
959 DRM_DEBUG_KMS("hfactor[%d]vfactor[%d]\n", hfactor, vfactor);
961 sc->hratio = (src_w << 14) / (dst_w << hfactor);
962 sc->vratio = (src_h << 14) / (dst_h << vfactor);
963 sc->up_h = (dst_w >= src_w) ? true : false;
964 sc->up_v = (dst_h >= src_h) ? true : false;
965 DRM_DEBUG_KMS("hratio[%d]vratio[%d]up_h[%d]up_v[%d]\n",
966 sc->hratio, sc->vratio, sc->up_h, sc->up_v);
968 shfactor = FIMC_SHFACTOR - (hfactor + vfactor);
969 DRM_DEBUG_KMS("shfactor[%d]\n", shfactor);
971 cfg = (EXYNOS_CISCPRERATIO_SHFACTOR(shfactor) |
972 EXYNOS_CISCPRERATIO_PREHORRATIO(1 << hfactor) |
973 EXYNOS_CISCPRERATIO_PREVERRATIO(1 << vfactor));
974 fimc_write(ctx, cfg, EXYNOS_CISCPRERATIO);
976 cfg = (EXYNOS_CISCPREDST_PREDSTWIDTH(pre_dst_width) |
977 EXYNOS_CISCPREDST_PREDSTHEIGHT(pre_dst_height));
978 fimc_write(ctx, cfg, EXYNOS_CISCPREDST);
983 static void fimc_set_scaler(struct fimc_context *ctx, struct fimc_scaler *sc)
987 DRM_DEBUG_KMS("range[%d]bypass[%d]up_h[%d]up_v[%d]\n",
988 sc->range, sc->bypass, sc->up_h, sc->up_v);
989 DRM_DEBUG_KMS("hratio[%d]vratio[%d]\n",
990 sc->hratio, sc->vratio);
992 cfg = fimc_read(ctx, EXYNOS_CISCCTRL);
993 cfg &= ~(EXYNOS_CISCCTRL_SCALERBYPASS |
994 EXYNOS_CISCCTRL_SCALEUP_H | EXYNOS_CISCCTRL_SCALEUP_V |
995 EXYNOS_CISCCTRL_MAIN_V_RATIO_MASK |
996 EXYNOS_CISCCTRL_MAIN_H_RATIO_MASK |
997 EXYNOS_CISCCTRL_CSCR2Y_WIDE |
998 EXYNOS_CISCCTRL_CSCY2R_WIDE);
1001 cfg |= (EXYNOS_CISCCTRL_CSCR2Y_WIDE |
1002 EXYNOS_CISCCTRL_CSCY2R_WIDE);
1004 cfg |= EXYNOS_CISCCTRL_SCALERBYPASS;
1006 cfg |= EXYNOS_CISCCTRL_SCALEUP_H;
1008 cfg |= EXYNOS_CISCCTRL_SCALEUP_V;
1010 cfg |= (EXYNOS_CISCCTRL_MAINHORRATIO((sc->hratio >> 6)) |
1011 EXYNOS_CISCCTRL_MAINVERRATIO((sc->vratio >> 6)));
1012 fimc_write(ctx, cfg, EXYNOS_CISCCTRL);
1014 cfg_ext = fimc_read(ctx, EXYNOS_CIEXTEN);
1015 cfg_ext &= ~EXYNOS_CIEXTEN_MAINHORRATIO_EXT_MASK;
1016 cfg_ext &= ~EXYNOS_CIEXTEN_MAINVERRATIO_EXT_MASK;
1017 cfg_ext |= (EXYNOS_CIEXTEN_MAINHORRATIO_EXT(sc->hratio) |
1018 EXYNOS_CIEXTEN_MAINVERRATIO_EXT(sc->vratio));
1019 fimc_write(ctx, cfg_ext, EXYNOS_CIEXTEN);
1022 static int fimc_dst_set_size(struct device *dev, int swap,
1023 struct drm_exynos_pos *pos, struct drm_exynos_sz *sz)
1025 struct fimc_context *ctx = get_fimc_context(dev);
1026 struct drm_exynos_pos img_pos = *pos;
1027 struct drm_exynos_sz img_sz = *sz;
1030 DRM_DEBUG_KMS("swap[%d]hsize[%d]vsize[%d]\n",
1031 swap, sz->hsize, sz->vsize);
1034 cfg = (EXYNOS_ORGOSIZE_HORIZONTAL(img_sz.hsize) |
1035 EXYNOS_ORGOSIZE_VERTICAL(img_sz.vsize));
1037 fimc_write(ctx, cfg, EXYNOS_ORGOSIZE);
1039 DRM_DEBUG_KMS("x[%d]y[%d]w[%d]h[%d]\n", pos->x, pos->y, pos->w, pos->h);
1042 cfg = fimc_read(ctx, EXYNOS_CIGCTRL);
1043 cfg &= ~EXYNOS_CIGCTRL_CSC_MASK;
1045 if (sz->hsize >= FIMC_WIDTH_ITU_709)
1046 cfg |= EXYNOS_CIGCTRL_CSC_ITU709;
1048 cfg |= EXYNOS_CIGCTRL_CSC_ITU601;
1050 fimc_write(ctx, cfg, EXYNOS_CIGCTRL);
1055 img_sz.hsize = sz->vsize;
1056 img_sz.vsize = sz->hsize;
1059 /* target image size */
1060 cfg = fimc_read(ctx, EXYNOS_CITRGFMT);
1061 cfg &= ~(EXYNOS_CITRGFMT_TARGETH_MASK |
1062 EXYNOS_CITRGFMT_TARGETV_MASK);
1063 cfg |= (EXYNOS_CITRGFMT_TARGETHSIZE(img_pos.w) |
1064 EXYNOS_CITRGFMT_TARGETVSIZE(img_pos.h));
1065 fimc_write(ctx, cfg, EXYNOS_CITRGFMT);
1068 cfg = EXYNOS_CITAREA_TARGET_AREA(img_pos.w * img_pos.h);
1069 fimc_write(ctx, cfg, EXYNOS_CITAREA);
1071 /* offset Y(RGB), Cb, Cr */
1072 cfg = (EXYNOS_CIOYOFF_HORIZONTAL(img_pos.x) |
1073 EXYNOS_CIOYOFF_VERTICAL(img_pos.y));
1074 fimc_write(ctx, cfg, EXYNOS_CIOYOFF);
1075 cfg = (EXYNOS_CIOCBOFF_HORIZONTAL(img_pos.x) |
1076 EXYNOS_CIOCBOFF_VERTICAL(img_pos.y));
1077 fimc_write(ctx, cfg, EXYNOS_CIOCBOFF);
1078 cfg = (EXYNOS_CIOCROFF_HORIZONTAL(img_pos.x) |
1079 EXYNOS_CIOCROFF_VERTICAL(img_pos.y));
1080 fimc_write(ctx, cfg, EXYNOS_CIOCROFF);
1085 static void fimc_dst_set_buf_seq(struct fimc_context *ctx, u32 buf_id,
1086 enum drm_exynos_ipp_buf_type buf_type)
1088 unsigned long flags;
1092 DRM_DEBUG_KMS("buf_id[%d]buf_type[%d]\n", buf_id, buf_type);
1094 spin_lock_irqsave(&ctx->lock, flags);
1096 cfg = fimc_read(ctx, EXYNOS_CIFCNTSEQ);
1098 if (buf_type == IPP_BUF_ENQUEUE)
1099 cfg |= (1 << buf_id);
1101 cfg &= ~(1 << buf_id);
1103 fimc_write(ctx, cfg, EXYNOS_CIFCNTSEQ);
1105 buf_num = hweight32(cfg);
1107 if (buf_type == IPP_BUF_ENQUEUE && buf_num >= FIMC_BUF_START)
1108 fimc_mask_irq(ctx, true);
1109 else if (buf_type == IPP_BUF_DEQUEUE && buf_num <= FIMC_BUF_STOP)
1110 fimc_mask_irq(ctx, false);
1112 spin_unlock_irqrestore(&ctx->lock, flags);
1115 static int fimc_dst_set_addr(struct device *dev,
1116 struct drm_exynos_ipp_buf_info *buf_info, u32 buf_id,
1117 enum drm_exynos_ipp_buf_type buf_type)
1119 struct fimc_context *ctx = get_fimc_context(dev);
1120 struct exynos_drm_ippdrv *ippdrv = &ctx->ippdrv;
1121 struct drm_exynos_ipp_cmd_node *c_node = ippdrv->c_node;
1122 struct drm_exynos_ipp_property *property;
1123 struct drm_exynos_ipp_config *config;
1126 DRM_ERROR("failed to get c_node.\n");
1130 property = &c_node->property;
1132 DRM_DEBUG_KMS("prop_id[%d]buf_id[%d]buf_type[%d]\n",
1133 property->prop_id, buf_id, buf_type);
1135 if (buf_id > FIMC_MAX_DST) {
1136 dev_info(ippdrv->dev, "invalid buf_id %d.\n", buf_id);
1140 /* address register set */
1142 case IPP_BUF_ENQUEUE:
1143 config = &property->config[EXYNOS_DRM_OPS_DST];
1145 fimc_write(ctx, buf_info->base[EXYNOS_DRM_PLANAR_Y],
1146 EXYNOS_CIOYSA(buf_id));
1148 if (config->fmt == DRM_FORMAT_YVU420) {
1149 fimc_write(ctx, buf_info->base[EXYNOS_DRM_PLANAR_CR],
1150 EXYNOS_CIOCBSA(buf_id));
1151 fimc_write(ctx, buf_info->base[EXYNOS_DRM_PLANAR_CB],
1152 EXYNOS_CIOCRSA(buf_id));
1154 fimc_write(ctx, buf_info->base[EXYNOS_DRM_PLANAR_CB],
1155 EXYNOS_CIOCBSA(buf_id));
1156 fimc_write(ctx, buf_info->base[EXYNOS_DRM_PLANAR_CR],
1157 EXYNOS_CIOCRSA(buf_id));
1160 case IPP_BUF_DEQUEUE:
1161 fimc_write(ctx, 0x0, EXYNOS_CIOYSA(buf_id));
1162 fimc_write(ctx, 0x0, EXYNOS_CIOCBSA(buf_id));
1163 fimc_write(ctx, 0x0, EXYNOS_CIOCRSA(buf_id));
1170 fimc_dst_set_buf_seq(ctx, buf_id, buf_type);
1175 static struct exynos_drm_ipp_ops fimc_dst_ops = {
1176 .set_fmt = fimc_dst_set_fmt,
1177 .set_transf = fimc_dst_set_transf,
1178 .set_size = fimc_dst_set_size,
1179 .set_addr = fimc_dst_set_addr,
1182 static irqreturn_t fimc_irq_handler(int irq, void *dev_id)
1184 struct fimc_context *ctx = dev_id;
1185 struct exynos_drm_ippdrv *ippdrv = &ctx->ippdrv;
1186 struct drm_exynos_ipp_cmd_node *c_node = ippdrv->c_node;
1187 struct drm_exynos_ipp_event_work *event_work =
1191 DRM_DEBUG_KMS("fimc id[%d]\n", ctx->id);
1193 fimc_clear_irq(ctx);
1194 if (fimc_check_ovf(ctx))
1197 if (!fimc_check_frame_end(ctx))
1200 buf_id = fimc_get_buf_id(ctx);
1204 DRM_DEBUG_KMS("buf_id[%d]\n", buf_id);
1206 fimc_dst_set_buf_seq(ctx, buf_id, IPP_BUF_DEQUEUE);
1208 event_work->ippdrv = ippdrv;
1209 event_work->buf_id[EXYNOS_DRM_OPS_DST] = buf_id;
1210 queue_work(ippdrv->event_workq, &event_work->work);
1215 static int fimc_init_prop_list(struct exynos_drm_ippdrv *ippdrv)
1217 struct drm_exynos_ipp_prop_list *prop_list = &ippdrv->prop_list;
1219 prop_list->version = 1;
1220 prop_list->writeback = 1;
1221 prop_list->refresh_min = FIMC_REFRESH_MIN;
1222 prop_list->refresh_max = FIMC_REFRESH_MAX;
1223 prop_list->flip = (1 << EXYNOS_DRM_FLIP_NONE) |
1224 (1 << EXYNOS_DRM_FLIP_VERTICAL) |
1225 (1 << EXYNOS_DRM_FLIP_HORIZONTAL);
1226 prop_list->degree = (1 << EXYNOS_DRM_DEGREE_0) |
1227 (1 << EXYNOS_DRM_DEGREE_90) |
1228 (1 << EXYNOS_DRM_DEGREE_180) |
1229 (1 << EXYNOS_DRM_DEGREE_270);
1231 prop_list->crop = 1;
1232 prop_list->crop_max.hsize = FIMC_CROP_MAX;
1233 prop_list->crop_max.vsize = FIMC_CROP_MAX;
1234 prop_list->crop_min.hsize = FIMC_CROP_MIN;
1235 prop_list->crop_min.vsize = FIMC_CROP_MIN;
1236 prop_list->scale = 1;
1237 prop_list->scale_max.hsize = FIMC_SCALE_MAX;
1238 prop_list->scale_max.vsize = FIMC_SCALE_MAX;
1239 prop_list->scale_min.hsize = FIMC_SCALE_MIN;
1240 prop_list->scale_min.vsize = FIMC_SCALE_MIN;
1245 static inline bool fimc_check_drm_flip(enum drm_exynos_flip flip)
1248 case EXYNOS_DRM_FLIP_NONE:
1249 case EXYNOS_DRM_FLIP_VERTICAL:
1250 case EXYNOS_DRM_FLIP_HORIZONTAL:
1251 case EXYNOS_DRM_FLIP_BOTH:
1254 DRM_DEBUG_KMS("invalid flip\n");
1259 static int fimc_ippdrv_check_property(struct device *dev,
1260 struct drm_exynos_ipp_property *property)
1262 struct fimc_context *ctx = get_fimc_context(dev);
1263 struct exynos_drm_ippdrv *ippdrv = &ctx->ippdrv;
1264 struct drm_exynos_ipp_prop_list *pp = &ippdrv->prop_list;
1265 struct drm_exynos_ipp_config *config;
1266 struct drm_exynos_pos *pos;
1267 struct drm_exynos_sz *sz;
1271 for_each_ipp_ops(i) {
1272 if ((i == EXYNOS_DRM_OPS_SRC) &&
1273 (property->cmd == IPP_CMD_WB))
1276 config = &property->config[i];
1280 /* check for flip */
1281 if (!fimc_check_drm_flip(config->flip)) {
1282 DRM_ERROR("invalid flip.\n");
1286 /* check for degree */
1287 switch (config->degree) {
1288 case EXYNOS_DRM_DEGREE_90:
1289 case EXYNOS_DRM_DEGREE_270:
1292 case EXYNOS_DRM_DEGREE_0:
1293 case EXYNOS_DRM_DEGREE_180:
1297 DRM_ERROR("invalid degree.\n");
1301 /* check for buffer bound */
1302 if ((pos->x + pos->w > sz->hsize) ||
1303 (pos->y + pos->h > sz->vsize)) {
1304 DRM_ERROR("out of buf bound.\n");
1308 /* check for crop */
1309 if ((i == EXYNOS_DRM_OPS_SRC) && (pp->crop)) {
1311 if ((pos->h < pp->crop_min.hsize) ||
1312 (sz->vsize > pp->crop_max.hsize) ||
1313 (pos->w < pp->crop_min.vsize) ||
1314 (sz->hsize > pp->crop_max.vsize)) {
1315 DRM_ERROR("out of crop size.\n");
1319 if ((pos->w < pp->crop_min.hsize) ||
1320 (sz->hsize > pp->crop_max.hsize) ||
1321 (pos->h < pp->crop_min.vsize) ||
1322 (sz->vsize > pp->crop_max.vsize)) {
1323 DRM_ERROR("out of crop size.\n");
1329 /* check for scale */
1330 if ((i == EXYNOS_DRM_OPS_DST) && (pp->scale)) {
1332 if ((pos->h < pp->scale_min.hsize) ||
1333 (sz->vsize > pp->scale_max.hsize) ||
1334 (pos->w < pp->scale_min.vsize) ||
1335 (sz->hsize > pp->scale_max.vsize)) {
1336 DRM_ERROR("out of scale size.\n");
1340 if ((pos->w < pp->scale_min.hsize) ||
1341 (sz->hsize > pp->scale_max.hsize) ||
1342 (pos->h < pp->scale_min.vsize) ||
1343 (sz->vsize > pp->scale_max.vsize)) {
1344 DRM_ERROR("out of scale size.\n");
1354 for_each_ipp_ops(i) {
1355 if ((i == EXYNOS_DRM_OPS_SRC) &&
1356 (property->cmd == IPP_CMD_WB))
1359 config = &property->config[i];
1363 DRM_ERROR("[%s]f[%d]r[%d]pos[%d %d %d %d]sz[%d %d]\n",
1364 i ? "dst" : "src", config->flip, config->degree,
1365 pos->x, pos->y, pos->w, pos->h,
1366 sz->hsize, sz->vsize);
1372 static void fimc_clear_addr(struct fimc_context *ctx)
1376 for (i = 0; i < FIMC_MAX_SRC; i++) {
1377 fimc_write(ctx, 0, EXYNOS_CIIYSA(i));
1378 fimc_write(ctx, 0, EXYNOS_CIICBSA(i));
1379 fimc_write(ctx, 0, EXYNOS_CIICRSA(i));
1382 for (i = 0; i < FIMC_MAX_DST; i++) {
1383 fimc_write(ctx, 0, EXYNOS_CIOYSA(i));
1384 fimc_write(ctx, 0, EXYNOS_CIOCBSA(i));
1385 fimc_write(ctx, 0, EXYNOS_CIOCRSA(i));
1389 static int fimc_ippdrv_reset(struct device *dev)
1391 struct fimc_context *ctx = get_fimc_context(dev);
1393 /* reset h/w block */
1396 /* reset scaler capability */
1397 memset(&ctx->sc, 0x0, sizeof(ctx->sc));
1399 fimc_clear_addr(ctx);
1404 static int fimc_ippdrv_start(struct device *dev, enum drm_exynos_ipp_cmd cmd)
1406 struct fimc_context *ctx = get_fimc_context(dev);
1407 struct exynos_drm_ippdrv *ippdrv = &ctx->ippdrv;
1408 struct drm_exynos_ipp_cmd_node *c_node = ippdrv->c_node;
1409 struct drm_exynos_ipp_property *property;
1410 struct drm_exynos_ipp_config *config;
1411 struct drm_exynos_pos img_pos[EXYNOS_DRM_OPS_MAX];
1412 struct drm_exynos_ipp_set_wb set_wb;
1416 DRM_DEBUG_KMS("cmd[%d]\n", cmd);
1419 DRM_ERROR("failed to get c_node.\n");
1423 property = &c_node->property;
1425 fimc_mask_irq(ctx, true);
1427 for_each_ipp_ops(i) {
1428 config = &property->config[i];
1429 img_pos[i] = config->pos;
1432 ret = fimc_set_prescaler(ctx, &ctx->sc,
1433 &img_pos[EXYNOS_DRM_OPS_SRC],
1434 &img_pos[EXYNOS_DRM_OPS_DST]);
1436 dev_err(dev, "failed to set precalser.\n");
1440 /* If set ture, we can save jpeg about screen */
1441 fimc_handle_jpeg(ctx, false);
1442 fimc_set_scaler(ctx, &ctx->sc);
1446 fimc_set_type_ctrl(ctx, FIMC_WB_NONE);
1447 fimc_handle_lastend(ctx, false);
1450 cfg0 = fimc_read(ctx, EXYNOS_MSCTRL);
1451 cfg0 &= ~EXYNOS_MSCTRL_INPUT_MASK;
1452 cfg0 |= EXYNOS_MSCTRL_INPUT_MEMORY;
1453 fimc_write(ctx, cfg0, EXYNOS_MSCTRL);
1456 fimc_set_type_ctrl(ctx, FIMC_WB_A);
1457 fimc_handle_lastend(ctx, true);
1460 ret = fimc_set_camblk_fimd0_wb(ctx);
1462 dev_err(dev, "camblk setup failed.\n");
1467 set_wb.refresh = property->refresh_rate;
1468 exynos_drm_ippnb_send_event(IPP_SET_WRITEBACK, (void *)&set_wb);
1470 case IPP_CMD_OUTPUT:
1473 dev_err(dev, "invalid operations.\n");
1478 fimc_write(ctx, 0x0, EXYNOS_CISTATUS);
1480 cfg0 = fimc_read(ctx, EXYNOS_CIIMGCPT);
1481 cfg0 &= ~EXYNOS_CIIMGCPT_IMGCPTEN_SC;
1482 cfg0 |= EXYNOS_CIIMGCPT_IMGCPTEN_SC;
1485 cfg1 = fimc_read(ctx, EXYNOS_CISCCTRL);
1486 cfg1 &= ~EXYNOS_CISCCTRL_SCAN_MASK;
1487 cfg1 |= (EXYNOS_CISCCTRL_PROGRESSIVE |
1488 EXYNOS_CISCCTRL_SCALERSTART);
1490 fimc_write(ctx, cfg1, EXYNOS_CISCCTRL);
1492 /* Enable image capture*/
1493 cfg0 |= EXYNOS_CIIMGCPT_IMGCPTEN;
1494 fimc_write(ctx, cfg0, EXYNOS_CIIMGCPT);
1496 /* Disable frame end irq */
1497 fimc_clear_bits(ctx, EXYNOS_CIGCTRL, EXYNOS_CIGCTRL_IRQ_END_DISABLE);
1499 fimc_clear_bits(ctx, EXYNOS_CIOCTRL, EXYNOS_CIOCTRL_WEAVE_MASK);
1501 if (cmd == IPP_CMD_M2M)
1502 fimc_set_bits(ctx, EXYNOS_MSCTRL, EXYNOS_MSCTRL_ENVID);
1507 static void fimc_ippdrv_stop(struct device *dev, enum drm_exynos_ipp_cmd cmd)
1509 struct fimc_context *ctx = get_fimc_context(dev);
1510 struct drm_exynos_ipp_set_wb set_wb = {0, 0};
1513 DRM_DEBUG_KMS("cmd[%d]\n", cmd);
1518 cfg = fimc_read(ctx, EXYNOS_MSCTRL);
1519 cfg &= ~EXYNOS_MSCTRL_INPUT_MASK;
1520 cfg &= ~EXYNOS_MSCTRL_ENVID;
1521 fimc_write(ctx, cfg, EXYNOS_MSCTRL);
1524 exynos_drm_ippnb_send_event(IPP_SET_WRITEBACK, (void *)&set_wb);
1526 case IPP_CMD_OUTPUT:
1528 dev_err(dev, "invalid operations.\n");
1532 fimc_mask_irq(ctx, false);
1534 /* reset sequence */
1535 fimc_write(ctx, 0x0, EXYNOS_CIFCNTSEQ);
1537 /* Scaler disable */
1538 fimc_clear_bits(ctx, EXYNOS_CISCCTRL, EXYNOS_CISCCTRL_SCALERSTART);
1540 /* Disable image capture */
1541 fimc_clear_bits(ctx, EXYNOS_CIIMGCPT,
1542 EXYNOS_CIIMGCPT_IMGCPTEN_SC | EXYNOS_CIIMGCPT_IMGCPTEN);
1544 /* Enable frame end irq */
1545 fimc_set_bits(ctx, EXYNOS_CIGCTRL, EXYNOS_CIGCTRL_IRQ_END_DISABLE);
1548 static void fimc_put_clocks(struct fimc_context *ctx)
1552 for (i = 0; i < FIMC_CLKS_MAX; i++) {
1553 if (IS_ERR(ctx->clocks[i]))
1555 clk_put(ctx->clocks[i]);
1556 ctx->clocks[i] = ERR_PTR(-EINVAL);
1560 static int fimc_setup_clocks(struct fimc_context *ctx)
1562 struct device *fimc_dev = ctx->ippdrv.dev;
1566 for (i = 0; i < FIMC_CLKS_MAX; i++)
1567 ctx->clocks[i] = ERR_PTR(-EINVAL);
1569 for (i = 0; i < FIMC_CLKS_MAX; i++) {
1570 if (i == FIMC_CLK_WB_A || i == FIMC_CLK_WB_B)
1571 dev = fimc_dev->parent;
1575 ctx->clocks[i] = clk_get(dev, fimc_clock_names[i]);
1576 if (IS_ERR(ctx->clocks[i])) {
1577 if (i >= FIMC_CLK_MUX)
1579 ret = PTR_ERR(ctx->clocks[i]);
1580 dev_err(fimc_dev, "failed to get clock: %s\n",
1581 fimc_clock_names[i]);
1586 /* Optional FIMC LCLK parent clock setting */
1587 if (!IS_ERR(ctx->clocks[FIMC_CLK_PARENT])) {
1588 ret = clk_set_parent(ctx->clocks[FIMC_CLK_MUX],
1589 ctx->clocks[FIMC_CLK_PARENT]);
1591 dev_err(fimc_dev, "failed to set parent.\n");
1596 ret = clk_set_rate(ctx->clocks[FIMC_CLK_LCLK], ctx->clk_frequency);
1600 ret = clk_prepare_enable(ctx->clocks[FIMC_CLK_LCLK]);
1604 fimc_put_clocks(ctx);
1608 static int fimc_parse_dt(struct fimc_context *ctx)
1610 struct device_node *node = ctx->ippdrv.dev->of_node;
1612 /* Handle only devices that support the LCD Writeback data path */
1613 if (!of_property_read_bool(node, "samsung,lcd-wb"))
1616 if (of_property_read_u32(node, "clock-frequency",
1617 &ctx->clk_frequency))
1618 ctx->clk_frequency = FIMC_DEFAULT_LCLK_FREQUENCY;
1620 ctx->id = of_alias_get_id(node, "fimc");
1623 dev_err(ctx->ippdrv.dev, "failed to get node alias id.\n");
1630 static int fimc_probe(struct platform_device *pdev)
1632 struct device *dev = &pdev->dev;
1633 struct fimc_context *ctx;
1634 struct resource *res;
1635 struct exynos_drm_ippdrv *ippdrv;
1638 if (!dev->of_node) {
1639 dev_err(dev, "device tree node not found.\n");
1643 ctx = devm_kzalloc(dev, sizeof(*ctx), GFP_KERNEL);
1647 ctx->ippdrv.dev = dev;
1649 ret = fimc_parse_dt(ctx);
1653 ctx->sysreg = syscon_regmap_lookup_by_phandle(dev->of_node,
1655 if (IS_ERR(ctx->sysreg)) {
1656 dev_err(dev, "syscon regmap lookup failed.\n");
1657 return PTR_ERR(ctx->sysreg);
1660 /* resource memory */
1661 ctx->regs_res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
1662 ctx->regs = devm_ioremap_resource(dev, ctx->regs_res);
1663 if (IS_ERR(ctx->regs))
1664 return PTR_ERR(ctx->regs);
1667 res = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
1669 dev_err(dev, "failed to request irq resource.\n");
1673 ctx->irq = res->start;
1674 ret = devm_request_threaded_irq(dev, ctx->irq, NULL, fimc_irq_handler,
1675 IRQF_ONESHOT, "drm_fimc", ctx);
1677 dev_err(dev, "failed to request irq.\n");
1681 ret = fimc_setup_clocks(ctx);
1685 ippdrv = &ctx->ippdrv;
1686 ippdrv->ops[EXYNOS_DRM_OPS_SRC] = &fimc_src_ops;
1687 ippdrv->ops[EXYNOS_DRM_OPS_DST] = &fimc_dst_ops;
1688 ippdrv->check_property = fimc_ippdrv_check_property;
1689 ippdrv->reset = fimc_ippdrv_reset;
1690 ippdrv->start = fimc_ippdrv_start;
1691 ippdrv->stop = fimc_ippdrv_stop;
1692 ret = fimc_init_prop_list(ippdrv);
1694 dev_err(dev, "failed to init property list.\n");
1698 DRM_DEBUG_KMS("id[%d]ippdrv[%p]\n", ctx->id, ippdrv);
1700 spin_lock_init(&ctx->lock);
1701 platform_set_drvdata(pdev, ctx);
1703 pm_runtime_enable(dev);
1705 ret = exynos_drm_ippdrv_register(ippdrv);
1707 dev_err(dev, "failed to register drm fimc device.\n");
1711 dev_info(dev, "drm fimc registered successfully.\n");
1716 pm_runtime_disable(dev);
1718 fimc_put_clocks(ctx);
1723 static int fimc_remove(struct platform_device *pdev)
1725 struct device *dev = &pdev->dev;
1726 struct fimc_context *ctx = get_fimc_context(dev);
1727 struct exynos_drm_ippdrv *ippdrv = &ctx->ippdrv;
1729 exynos_drm_ippdrv_unregister(ippdrv);
1731 fimc_put_clocks(ctx);
1732 pm_runtime_set_suspended(dev);
1733 pm_runtime_disable(dev);
1739 static int fimc_clk_ctrl(struct fimc_context *ctx, bool enable)
1741 DRM_DEBUG_KMS("enable[%d]\n", enable);
1744 clk_prepare_enable(ctx->clocks[FIMC_CLK_GATE]);
1745 clk_prepare_enable(ctx->clocks[FIMC_CLK_WB_A]);
1746 ctx->suspended = false;
1748 clk_disable_unprepare(ctx->clocks[FIMC_CLK_GATE]);
1749 clk_disable_unprepare(ctx->clocks[FIMC_CLK_WB_A]);
1750 ctx->suspended = true;
1756 #ifdef CONFIG_PM_SLEEP
1757 static int fimc_suspend(struct device *dev)
1759 struct fimc_context *ctx = get_fimc_context(dev);
1761 DRM_DEBUG_KMS("id[%d]\n", ctx->id);
1763 if (pm_runtime_suspended(dev))
1766 return fimc_clk_ctrl(ctx, false);
1769 static int fimc_resume(struct device *dev)
1771 struct fimc_context *ctx = get_fimc_context(dev);
1773 DRM_DEBUG_KMS("id[%d]\n", ctx->id);
1775 if (!pm_runtime_suspended(dev))
1776 return fimc_clk_ctrl(ctx, true);
1782 static int fimc_runtime_suspend(struct device *dev)
1784 struct fimc_context *ctx = get_fimc_context(dev);
1786 DRM_DEBUG_KMS("id[%d]\n", ctx->id);
1788 return fimc_clk_ctrl(ctx, false);
1791 static int fimc_runtime_resume(struct device *dev)
1793 struct fimc_context *ctx = get_fimc_context(dev);
1795 DRM_DEBUG_KMS("id[%d]\n", ctx->id);
1797 return fimc_clk_ctrl(ctx, true);
1801 static const struct dev_pm_ops fimc_pm_ops = {
1802 SET_SYSTEM_SLEEP_PM_OPS(fimc_suspend, fimc_resume)
1803 SET_RUNTIME_PM_OPS(fimc_runtime_suspend, fimc_runtime_resume, NULL)
1806 static const struct of_device_id fimc_of_match[] = {
1807 { .compatible = "samsung,exynos4210-fimc" },
1808 { .compatible = "samsung,exynos4212-fimc" },
1811 MODULE_DEVICE_TABLE(of, fimc_of_match);
1813 struct platform_driver fimc_driver = {
1814 .probe = fimc_probe,
1815 .remove = fimc_remove,
1817 .of_match_table = fimc_of_match,
1818 .name = "exynos-drm-fimc",
1819 .owner = THIS_MODULE,