drm/exynos: remove redundant devm_kfree()
[deliverable/linux.git] / drivers / gpu / drm / exynos / exynos_drm_fimc.c
CommitLineData
16102edb
EK
1/*
2 * Copyright (C) 2012 Samsung Electronics Co.Ltd
3 * Authors:
4 * Eunchul Kim <chulspro.kim@samsung.com>
5 * Jinyoung Jeon <jy0.jeon@samsung.com>
6 * Sangmin Lee <lsmin.lee@samsung.com>
7 *
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.
12 *
13 */
14#include <linux/kernel.h>
15#include <linux/module.h>
16#include <linux/platform_device.h>
17#include <linux/clk.h>
18#include <linux/pm_runtime.h>
19#include <plat/map-base.h>
20
21#include <drm/drmP.h>
22#include <drm/exynos_drm.h>
23#include "regs-fimc.h"
24#include "exynos_drm_ipp.h"
25#include "exynos_drm_fimc.h"
26
27/*
6fe891f6 28 * FIMC stands for Fully Interactive Mobile Camera and
16102edb
EK
29 * supports image scaler/rotator and input/output DMA operations.
30 * input DMA reads image data from the memory.
31 * output DMA writes image data to memory.
32 * FIMC supports image rotation and image effect functions.
33 *
34 * M2M operation : supports crop/scale/rotation/csc so on.
35 * Memory ----> FIMC H/W ----> Memory.
36 * Writeback operation : supports cloned screen with FIMD.
37 * FIMD ----> FIMC H/W ----> Memory.
38 * Output operation : supports direct display using local path.
39 * Memory ----> FIMC H/W ----> FIMD.
40 */
41
42/*
43 * TODO
44 * 1. check suspend/resume api if needed.
45 * 2. need to check use case platform_device_id.
46 * 3. check src/dst size with, height.
47 * 4. added check_prepare api for right register.
48 * 5. need to add supported list in prop_list.
49 * 6. check prescaler/scaler optimization.
50 */
51
52#define FIMC_MAX_DEVS 4
53#define FIMC_MAX_SRC 2
54#define FIMC_MAX_DST 32
55#define FIMC_SHFACTOR 10
56#define FIMC_BUF_STOP 1
57#define FIMC_BUF_START 2
58#define FIMC_REG_SZ 32
59#define FIMC_WIDTH_ITU_709 1280
60#define FIMC_REFRESH_MAX 60
61#define FIMC_REFRESH_MIN 12
62#define FIMC_CROP_MAX 8192
63#define FIMC_CROP_MIN 32
64#define FIMC_SCALE_MAX 4224
65#define FIMC_SCALE_MIN 32
66
67#define get_fimc_context(dev) platform_get_drvdata(to_platform_device(dev))
68#define get_ctx_from_ippdrv(ippdrv) container_of(ippdrv,\
69 struct fimc_context, ippdrv);
70#define fimc_read(offset) readl(ctx->regs + (offset))
71#define fimc_write(cfg, offset) writel(cfg, ctx->regs + (offset))
72
73enum fimc_wb {
74 FIMC_WB_NONE,
75 FIMC_WB_A,
76 FIMC_WB_B,
77};
78
79/*
80 * A structure of scaler.
81 *
82 * @range: narrow, wide.
83 * @bypass: unused scaler path.
84 * @up_h: horizontal scale up.
85 * @up_v: vertical scale up.
86 * @hratio: horizontal ratio.
87 * @vratio: vertical ratio.
88 */
89struct fimc_scaler {
90 bool range;
91 bool bypass;
92 bool up_h;
93 bool up_v;
94 u32 hratio;
95 u32 vratio;
96};
97
98/*
99 * A structure of scaler capability.
100 *
101 * find user manual table 43-1.
102 * @in_hori: scaler input horizontal size.
103 * @bypass: scaler bypass mode.
104 * @dst_h_wo_rot: target horizontal size without output rotation.
105 * @dst_h_rot: target horizontal size with output rotation.
106 * @rl_w_wo_rot: real width without input rotation.
107 * @rl_h_rot: real height without output rotation.
108 */
109struct fimc_capability {
110 /* scaler */
111 u32 in_hori;
112 u32 bypass;
113 /* output rotator */
114 u32 dst_h_wo_rot;
115 u32 dst_h_rot;
116 /* input rotator */
117 u32 rl_w_wo_rot;
118 u32 rl_h_rot;
119};
120
121/*
122 * A structure of fimc driver data.
123 *
124 * @parent_clk: name of parent clock.
125 */
126struct fimc_driverdata {
127 char *parent_clk;
128};
129
130/*
131 * A structure of fimc context.
132 *
133 * @ippdrv: prepare initialization using ippdrv.
134 * @regs_res: register resources.
135 * @regs: memory mapped io registers.
136 * @lock: locking of operations.
137 * @sclk_fimc_clk: fimc source clock.
138 * @fimc_clk: fimc clock.
139 * @wb_clk: writeback a clock.
140 * @wb_b_clk: writeback b clock.
141 * @sc: scaler infomations.
142 * @odr: ordering of YUV.
143 * @ver: fimc version.
144 * @pol: porarity of writeback.
145 * @id: fimc id.
146 * @irq: irq number.
147 * @suspended: qos operations.
148 */
149struct fimc_context {
150 struct exynos_drm_ippdrv ippdrv;
151 struct resource *regs_res;
152 void __iomem *regs;
153 struct mutex lock;
154 struct clk *sclk_fimc_clk;
155 struct clk *fimc_clk;
156 struct clk *wb_clk;
157 struct clk *wb_b_clk;
158 struct fimc_scaler sc;
159 struct fimc_driverdata *ddata;
160 struct exynos_drm_ipp_pol pol;
161 int id;
162 int irq;
163 bool suspended;
164};
165
b5c0b552 166static void fimc_sw_reset(struct fimc_context *ctx)
16102edb
EK
167{
168 u32 cfg;
169
b5c0b552 170 DRM_DEBUG_KMS("%s\n", __func__);
16102edb 171
e39d5ce1
JJ
172 /* stop dma operation */
173 cfg = fimc_read(EXYNOS_CISTATUS);
174 if (EXYNOS_CISTATUS_GET_ENVID_STATUS(cfg)) {
175 cfg = fimc_read(EXYNOS_MSCTRL);
176 cfg &= ~EXYNOS_MSCTRL_ENVID;
177 fimc_write(cfg, EXYNOS_MSCTRL);
178 }
16102edb
EK
179
180 cfg = fimc_read(EXYNOS_CISRCFMT);
181 cfg |= EXYNOS_CISRCFMT_ITU601_8BIT;
16102edb
EK
182 fimc_write(cfg, EXYNOS_CISRCFMT);
183
e39d5ce1
JJ
184 /* disable image capture */
185 cfg = fimc_read(EXYNOS_CIIMGCPT);
186 cfg &= ~(EXYNOS_CIIMGCPT_IMGCPTEN_SC | EXYNOS_CIIMGCPT_IMGCPTEN);
187 fimc_write(cfg, EXYNOS_CIIMGCPT);
188
16102edb
EK
189 /* s/w reset */
190 cfg = fimc_read(EXYNOS_CIGCTRL);
191 cfg |= (EXYNOS_CIGCTRL_SWRST);
192 fimc_write(cfg, EXYNOS_CIGCTRL);
193
194 /* s/w reset complete */
195 cfg = fimc_read(EXYNOS_CIGCTRL);
196 cfg &= ~EXYNOS_CIGCTRL_SWRST;
197 fimc_write(cfg, EXYNOS_CIGCTRL);
198
199 /* reset sequence */
200 fimc_write(0x0, EXYNOS_CIFCNTSEQ);
201}
202
203static void fimc_set_camblk_fimd0_wb(struct fimc_context *ctx)
204{
205 u32 camblk_cfg;
206
207 DRM_DEBUG_KMS("%s\n", __func__);
208
209 camblk_cfg = readl(SYSREG_CAMERA_BLK);
210 camblk_cfg &= ~(SYSREG_FIMD0WB_DEST_MASK);
211 camblk_cfg |= ctx->id << (SYSREG_FIMD0WB_DEST_SHIFT);
212
213 writel(camblk_cfg, SYSREG_CAMERA_BLK);
214}
215
216static void fimc_set_type_ctrl(struct fimc_context *ctx, enum fimc_wb wb)
217{
218 u32 cfg;
219
220 DRM_DEBUG_KMS("%s:wb[%d]\n", __func__, wb);
221
222 cfg = fimc_read(EXYNOS_CIGCTRL);
223 cfg &= ~(EXYNOS_CIGCTRL_TESTPATTERN_MASK |
224 EXYNOS_CIGCTRL_SELCAM_ITU_MASK |
225 EXYNOS_CIGCTRL_SELCAM_MIPI_MASK |
226 EXYNOS_CIGCTRL_SELCAM_FIMC_MASK |
227 EXYNOS_CIGCTRL_SELWB_CAMIF_MASK |
228 EXYNOS_CIGCTRL_SELWRITEBACK_MASK);
229
230 switch (wb) {
231 case FIMC_WB_A:
232 cfg |= (EXYNOS_CIGCTRL_SELWRITEBACK_A |
233 EXYNOS_CIGCTRL_SELWB_CAMIF_WRITEBACK);
234 break;
235 case FIMC_WB_B:
236 cfg |= (EXYNOS_CIGCTRL_SELWRITEBACK_B |
237 EXYNOS_CIGCTRL_SELWB_CAMIF_WRITEBACK);
238 break;
239 case FIMC_WB_NONE:
240 default:
241 cfg |= (EXYNOS_CIGCTRL_SELCAM_ITU_A |
242 EXYNOS_CIGCTRL_SELWRITEBACK_A |
243 EXYNOS_CIGCTRL_SELCAM_MIPI_A |
244 EXYNOS_CIGCTRL_SELCAM_FIMC_ITU);
245 break;
246 }
247
248 fimc_write(cfg, EXYNOS_CIGCTRL);
249}
250
251static void fimc_set_polarity(struct fimc_context *ctx,
252 struct exynos_drm_ipp_pol *pol)
253{
254 u32 cfg;
255
256 DRM_DEBUG_KMS("%s:inv_pclk[%d]inv_vsync[%d]\n",
257 __func__, pol->inv_pclk, pol->inv_vsync);
258 DRM_DEBUG_KMS("%s:inv_href[%d]inv_hsync[%d]\n",
259 __func__, pol->inv_href, pol->inv_hsync);
260
261 cfg = fimc_read(EXYNOS_CIGCTRL);
262 cfg &= ~(EXYNOS_CIGCTRL_INVPOLPCLK | EXYNOS_CIGCTRL_INVPOLVSYNC |
263 EXYNOS_CIGCTRL_INVPOLHREF | EXYNOS_CIGCTRL_INVPOLHSYNC);
264
265 if (pol->inv_pclk)
266 cfg |= EXYNOS_CIGCTRL_INVPOLPCLK;
267 if (pol->inv_vsync)
268 cfg |= EXYNOS_CIGCTRL_INVPOLVSYNC;
269 if (pol->inv_href)
270 cfg |= EXYNOS_CIGCTRL_INVPOLHREF;
271 if (pol->inv_hsync)
272 cfg |= EXYNOS_CIGCTRL_INVPOLHSYNC;
273
274 fimc_write(cfg, EXYNOS_CIGCTRL);
275}
276
277static void fimc_handle_jpeg(struct fimc_context *ctx, bool enable)
278{
279 u32 cfg;
280
281 DRM_DEBUG_KMS("%s:enable[%d]\n", __func__, enable);
282
283 cfg = fimc_read(EXYNOS_CIGCTRL);
284 if (enable)
285 cfg |= EXYNOS_CIGCTRL_CAM_JPEG;
286 else
287 cfg &= ~EXYNOS_CIGCTRL_CAM_JPEG;
288
289 fimc_write(cfg, EXYNOS_CIGCTRL);
290}
291
292static void fimc_handle_irq(struct fimc_context *ctx, bool enable,
293 bool overflow, bool level)
294{
295 u32 cfg;
296
297 DRM_DEBUG_KMS("%s:enable[%d]overflow[%d]level[%d]\n", __func__,
298 enable, overflow, level);
299
300 cfg = fimc_read(EXYNOS_CIGCTRL);
301 if (enable) {
302 cfg &= ~(EXYNOS_CIGCTRL_IRQ_OVFEN | EXYNOS_CIGCTRL_IRQ_LEVEL);
303 cfg |= EXYNOS_CIGCTRL_IRQ_ENABLE;
304 if (overflow)
305 cfg |= EXYNOS_CIGCTRL_IRQ_OVFEN;
306 if (level)
307 cfg |= EXYNOS_CIGCTRL_IRQ_LEVEL;
308 } else
309 cfg &= ~(EXYNOS_CIGCTRL_IRQ_OVFEN | EXYNOS_CIGCTRL_IRQ_ENABLE);
310
311 fimc_write(cfg, EXYNOS_CIGCTRL);
312}
313
314static void fimc_clear_irq(struct fimc_context *ctx)
315{
316 u32 cfg;
317
318 DRM_DEBUG_KMS("%s\n", __func__);
319
320 cfg = fimc_read(EXYNOS_CIGCTRL);
321 cfg |= EXYNOS_CIGCTRL_IRQ_CLR;
322 fimc_write(cfg, EXYNOS_CIGCTRL);
323}
324
325static bool fimc_check_ovf(struct fimc_context *ctx)
326{
327 struct exynos_drm_ippdrv *ippdrv = &ctx->ippdrv;
328 u32 cfg, status, flag;
329
330 status = fimc_read(EXYNOS_CISTATUS);
331 flag = EXYNOS_CISTATUS_OVFIY | EXYNOS_CISTATUS_OVFICB |
332 EXYNOS_CISTATUS_OVFICR;
333
334 DRM_DEBUG_KMS("%s:flag[0x%x]\n", __func__, flag);
335
336 if (status & flag) {
337 cfg = fimc_read(EXYNOS_CIWDOFST);
338 cfg |= (EXYNOS_CIWDOFST_CLROVFIY | EXYNOS_CIWDOFST_CLROVFICB |
339 EXYNOS_CIWDOFST_CLROVFICR);
340
341 fimc_write(cfg, EXYNOS_CIWDOFST);
342
343 cfg = fimc_read(EXYNOS_CIWDOFST);
344 cfg &= ~(EXYNOS_CIWDOFST_CLROVFIY | EXYNOS_CIWDOFST_CLROVFICB |
345 EXYNOS_CIWDOFST_CLROVFICR);
346
347 fimc_write(cfg, EXYNOS_CIWDOFST);
348
349 dev_err(ippdrv->dev, "occured overflow at %d, status 0x%x.\n",
350 ctx->id, status);
351 return true;
352 }
353
354 return false;
355}
356
357static bool fimc_check_frame_end(struct fimc_context *ctx)
358{
359 u32 cfg;
360
361 cfg = fimc_read(EXYNOS_CISTATUS);
362
363 DRM_DEBUG_KMS("%s:cfg[0x%x]\n", __func__, cfg);
364
365 if (!(cfg & EXYNOS_CISTATUS_FRAMEEND))
366 return false;
367
368 cfg &= ~(EXYNOS_CISTATUS_FRAMEEND);
369 fimc_write(cfg, EXYNOS_CISTATUS);
370
371 return true;
372}
373
374static int fimc_get_buf_id(struct fimc_context *ctx)
375{
376 u32 cfg;
377 int frame_cnt, buf_id;
378
379 DRM_DEBUG_KMS("%s\n", __func__);
380
381 cfg = fimc_read(EXYNOS_CISTATUS2);
382 frame_cnt = EXYNOS_CISTATUS2_GET_FRAMECOUNT_BEFORE(cfg);
383
384 if (frame_cnt == 0)
385 frame_cnt = EXYNOS_CISTATUS2_GET_FRAMECOUNT_PRESENT(cfg);
386
387 DRM_DEBUG_KMS("%s:present[%d]before[%d]\n", __func__,
388 EXYNOS_CISTATUS2_GET_FRAMECOUNT_PRESENT(cfg),
389 EXYNOS_CISTATUS2_GET_FRAMECOUNT_BEFORE(cfg));
390
391 if (frame_cnt == 0) {
392 DRM_ERROR("failed to get frame count.\n");
393 return -EIO;
394 }
395
396 buf_id = frame_cnt - 1;
397 DRM_DEBUG_KMS("%s:buf_id[%d]\n", __func__, buf_id);
398
399 return buf_id;
400}
401
402static void fimc_handle_lastend(struct fimc_context *ctx, bool enable)
403{
404 u32 cfg;
405
406 DRM_DEBUG_KMS("%s:enable[%d]\n", __func__, enable);
407
408 cfg = fimc_read(EXYNOS_CIOCTRL);
409 if (enable)
410 cfg |= EXYNOS_CIOCTRL_LASTENDEN;
411 else
412 cfg &= ~EXYNOS_CIOCTRL_LASTENDEN;
413
414 fimc_write(cfg, EXYNOS_CIOCTRL);
415}
416
417
418static int fimc_src_set_fmt_order(struct fimc_context *ctx, u32 fmt)
419{
420 struct exynos_drm_ippdrv *ippdrv = &ctx->ippdrv;
421 u32 cfg;
422
423 DRM_DEBUG_KMS("%s:fmt[0x%x]\n", __func__, fmt);
424
425 /* RGB */
426 cfg = fimc_read(EXYNOS_CISCCTRL);
427 cfg &= ~EXYNOS_CISCCTRL_INRGB_FMT_RGB_MASK;
428
429 switch (fmt) {
430 case DRM_FORMAT_RGB565:
431 cfg |= EXYNOS_CISCCTRL_INRGB_FMT_RGB565;
432 fimc_write(cfg, EXYNOS_CISCCTRL);
433 return 0;
434 case DRM_FORMAT_RGB888:
435 case DRM_FORMAT_XRGB8888:
436 cfg |= EXYNOS_CISCCTRL_INRGB_FMT_RGB888;
437 fimc_write(cfg, EXYNOS_CISCCTRL);
438 return 0;
439 default:
440 /* bypass */
441 break;
442 }
443
444 /* YUV */
445 cfg = fimc_read(EXYNOS_MSCTRL);
446 cfg &= ~(EXYNOS_MSCTRL_ORDER2P_SHIFT_MASK |
447 EXYNOS_MSCTRL_C_INT_IN_2PLANE |
448 EXYNOS_MSCTRL_ORDER422_YCBYCR);
449
450 switch (fmt) {
451 case DRM_FORMAT_YUYV:
452 cfg |= EXYNOS_MSCTRL_ORDER422_YCBYCR;
453 break;
454 case DRM_FORMAT_YVYU:
455 cfg |= EXYNOS_MSCTRL_ORDER422_YCRYCB;
456 break;
457 case DRM_FORMAT_UYVY:
458 cfg |= EXYNOS_MSCTRL_ORDER422_CBYCRY;
459 break;
460 case DRM_FORMAT_VYUY:
461 case DRM_FORMAT_YUV444:
462 cfg |= EXYNOS_MSCTRL_ORDER422_CRYCBY;
463 break;
464 case DRM_FORMAT_NV21:
465 case DRM_FORMAT_NV61:
466 cfg |= (EXYNOS_MSCTRL_ORDER2P_LSB_CRCB |
467 EXYNOS_MSCTRL_C_INT_IN_2PLANE);
468 break;
469 case DRM_FORMAT_YUV422:
470 case DRM_FORMAT_YUV420:
471 case DRM_FORMAT_YVU420:
472 cfg |= EXYNOS_MSCTRL_C_INT_IN_3PLANE;
473 break;
474 case DRM_FORMAT_NV12:
475 case DRM_FORMAT_NV12MT:
476 case DRM_FORMAT_NV16:
477 cfg |= (EXYNOS_MSCTRL_ORDER2P_LSB_CBCR |
478 EXYNOS_MSCTRL_C_INT_IN_2PLANE);
479 break;
480 default:
481 dev_err(ippdrv->dev, "inavlid source yuv order 0x%x.\n", fmt);
482 return -EINVAL;
483 }
484
485 fimc_write(cfg, EXYNOS_MSCTRL);
486
487 return 0;
488}
489
490static int fimc_src_set_fmt(struct device *dev, u32 fmt)
491{
492 struct fimc_context *ctx = get_fimc_context(dev);
493 struct exynos_drm_ippdrv *ippdrv = &ctx->ippdrv;
494 u32 cfg;
495
496 DRM_DEBUG_KMS("%s:fmt[0x%x]\n", __func__, fmt);
497
498 cfg = fimc_read(EXYNOS_MSCTRL);
499 cfg &= ~EXYNOS_MSCTRL_INFORMAT_RGB;
500
501 switch (fmt) {
502 case DRM_FORMAT_RGB565:
503 case DRM_FORMAT_RGB888:
504 case DRM_FORMAT_XRGB8888:
505 cfg |= EXYNOS_MSCTRL_INFORMAT_RGB;
506 break;
507 case DRM_FORMAT_YUV444:
508 cfg |= EXYNOS_MSCTRL_INFORMAT_YCBCR420;
509 break;
510 case DRM_FORMAT_YUYV:
511 case DRM_FORMAT_YVYU:
512 case DRM_FORMAT_UYVY:
513 case DRM_FORMAT_VYUY:
514 cfg |= EXYNOS_MSCTRL_INFORMAT_YCBCR422_1PLANE;
515 break;
516 case DRM_FORMAT_NV16:
517 case DRM_FORMAT_NV61:
518 case DRM_FORMAT_YUV422:
519 cfg |= EXYNOS_MSCTRL_INFORMAT_YCBCR422;
520 break;
521 case DRM_FORMAT_YUV420:
522 case DRM_FORMAT_YVU420:
523 case DRM_FORMAT_NV12:
524 case DRM_FORMAT_NV21:
525 case DRM_FORMAT_NV12MT:
526 cfg |= EXYNOS_MSCTRL_INFORMAT_YCBCR420;
527 break;
528 default:
529 dev_err(ippdrv->dev, "inavlid source format 0x%x.\n", fmt);
530 return -EINVAL;
531 }
532
533 fimc_write(cfg, EXYNOS_MSCTRL);
534
535 cfg = fimc_read(EXYNOS_CIDMAPARAM);
536 cfg &= ~EXYNOS_CIDMAPARAM_R_MODE_MASK;
537
538 if (fmt == DRM_FORMAT_NV12MT)
539 cfg |= EXYNOS_CIDMAPARAM_R_MODE_64X32;
540 else
541 cfg |= EXYNOS_CIDMAPARAM_R_MODE_LINEAR;
542
543 fimc_write(cfg, EXYNOS_CIDMAPARAM);
544
545 return fimc_src_set_fmt_order(ctx, fmt);
546}
547
548static int fimc_src_set_transf(struct device *dev,
549 enum drm_exynos_degree degree,
550 enum drm_exynos_flip flip, bool *swap)
551{
552 struct fimc_context *ctx = get_fimc_context(dev);
553 struct exynos_drm_ippdrv *ippdrv = &ctx->ippdrv;
554 u32 cfg1, cfg2;
555
556 DRM_DEBUG_KMS("%s:degree[%d]flip[0x%x]\n", __func__,
557 degree, flip);
558
559 cfg1 = fimc_read(EXYNOS_MSCTRL);
560 cfg1 &= ~(EXYNOS_MSCTRL_FLIP_X_MIRROR |
561 EXYNOS_MSCTRL_FLIP_Y_MIRROR);
562
563 cfg2 = fimc_read(EXYNOS_CITRGFMT);
564 cfg2 &= ~EXYNOS_CITRGFMT_INROT90_CLOCKWISE;
565
566 switch (degree) {
567 case EXYNOS_DRM_DEGREE_0:
568 if (flip & EXYNOS_DRM_FLIP_VERTICAL)
569 cfg1 |= EXYNOS_MSCTRL_FLIP_X_MIRROR;
570 if (flip & EXYNOS_DRM_FLIP_HORIZONTAL)
571 cfg1 |= EXYNOS_MSCTRL_FLIP_Y_MIRROR;
572 break;
573 case EXYNOS_DRM_DEGREE_90:
574 cfg2 |= EXYNOS_CITRGFMT_INROT90_CLOCKWISE;
575 if (flip & EXYNOS_DRM_FLIP_VERTICAL)
576 cfg1 |= EXYNOS_MSCTRL_FLIP_X_MIRROR;
577 if (flip & EXYNOS_DRM_FLIP_HORIZONTAL)
578 cfg1 |= EXYNOS_MSCTRL_FLIP_Y_MIRROR;
579 break;
580 case EXYNOS_DRM_DEGREE_180:
581 cfg1 |= (EXYNOS_MSCTRL_FLIP_X_MIRROR |
582 EXYNOS_MSCTRL_FLIP_Y_MIRROR);
583 if (flip & EXYNOS_DRM_FLIP_VERTICAL)
584 cfg1 &= ~EXYNOS_MSCTRL_FLIP_X_MIRROR;
585 if (flip & EXYNOS_DRM_FLIP_HORIZONTAL)
586 cfg1 &= ~EXYNOS_MSCTRL_FLIP_Y_MIRROR;
587 break;
588 case EXYNOS_DRM_DEGREE_270:
589 cfg1 |= (EXYNOS_MSCTRL_FLIP_X_MIRROR |
590 EXYNOS_MSCTRL_FLIP_Y_MIRROR);
591 cfg2 |= EXYNOS_CITRGFMT_INROT90_CLOCKWISE;
592 if (flip & EXYNOS_DRM_FLIP_VERTICAL)
593 cfg1 &= ~EXYNOS_MSCTRL_FLIP_X_MIRROR;
594 if (flip & EXYNOS_DRM_FLIP_HORIZONTAL)
595 cfg1 &= ~EXYNOS_MSCTRL_FLIP_Y_MIRROR;
596 break;
597 default:
598 dev_err(ippdrv->dev, "inavlid degree value %d.\n", degree);
599 return -EINVAL;
600 }
601
602 fimc_write(cfg1, EXYNOS_MSCTRL);
603 fimc_write(cfg2, EXYNOS_CITRGFMT);
604 *swap = (cfg2 & EXYNOS_CITRGFMT_INROT90_CLOCKWISE) ? 1 : 0;
605
606 return 0;
607}
608
609static int fimc_set_window(struct fimc_context *ctx,
610 struct drm_exynos_pos *pos, struct drm_exynos_sz *sz)
611{
612 u32 cfg, h1, h2, v1, v2;
613
614 /* cropped image */
615 h1 = pos->x;
616 h2 = sz->hsize - pos->w - pos->x;
617 v1 = pos->y;
618 v2 = sz->vsize - pos->h - pos->y;
619
620 DRM_DEBUG_KMS("%s:x[%d]y[%d]w[%d]h[%d]hsize[%d]vsize[%d]\n",
621 __func__, pos->x, pos->y, pos->w, pos->h, sz->hsize, sz->vsize);
622 DRM_DEBUG_KMS("%s:h1[%d]h2[%d]v1[%d]v2[%d]\n", __func__,
623 h1, h2, v1, v2);
624
625 /*
626 * set window offset 1, 2 size
627 * check figure 43-21 in user manual
628 */
629 cfg = fimc_read(EXYNOS_CIWDOFST);
630 cfg &= ~(EXYNOS_CIWDOFST_WINHOROFST_MASK |
631 EXYNOS_CIWDOFST_WINVEROFST_MASK);
632 cfg |= (EXYNOS_CIWDOFST_WINHOROFST(h1) |
633 EXYNOS_CIWDOFST_WINVEROFST(v1));
634 cfg |= EXYNOS_CIWDOFST_WINOFSEN;
635 fimc_write(cfg, EXYNOS_CIWDOFST);
636
637 cfg = (EXYNOS_CIWDOFST2_WINHOROFST2(h2) |
638 EXYNOS_CIWDOFST2_WINVEROFST2(v2));
639 fimc_write(cfg, EXYNOS_CIWDOFST2);
640
641 return 0;
642}
643
644static int fimc_src_set_size(struct device *dev, int swap,
645 struct drm_exynos_pos *pos, struct drm_exynos_sz *sz)
646{
647 struct fimc_context *ctx = get_fimc_context(dev);
648 struct drm_exynos_pos img_pos = *pos;
649 struct drm_exynos_sz img_sz = *sz;
650 u32 cfg;
651
652 DRM_DEBUG_KMS("%s:swap[%d]hsize[%d]vsize[%d]\n",
653 __func__, swap, sz->hsize, sz->vsize);
654
655 /* original size */
656 cfg = (EXYNOS_ORGISIZE_HORIZONTAL(img_sz.hsize) |
657 EXYNOS_ORGISIZE_VERTICAL(img_sz.vsize));
658
659 fimc_write(cfg, EXYNOS_ORGISIZE);
660
661 DRM_DEBUG_KMS("%s:x[%d]y[%d]w[%d]h[%d]\n", __func__,
662 pos->x, pos->y, pos->w, pos->h);
663
664 if (swap) {
665 img_pos.w = pos->h;
666 img_pos.h = pos->w;
667 img_sz.hsize = sz->vsize;
668 img_sz.vsize = sz->hsize;
669 }
670
671 /* set input DMA image size */
672 cfg = fimc_read(EXYNOS_CIREAL_ISIZE);
673 cfg &= ~(EXYNOS_CIREAL_ISIZE_HEIGHT_MASK |
674 EXYNOS_CIREAL_ISIZE_WIDTH_MASK);
675 cfg |= (EXYNOS_CIREAL_ISIZE_WIDTH(img_pos.w) |
676 EXYNOS_CIREAL_ISIZE_HEIGHT(img_pos.h));
677 fimc_write(cfg, EXYNOS_CIREAL_ISIZE);
678
679 /*
680 * set input FIFO image size
681 * for now, we support only ITU601 8 bit mode
682 */
683 cfg = (EXYNOS_CISRCFMT_ITU601_8BIT |
684 EXYNOS_CISRCFMT_SOURCEHSIZE(img_sz.hsize) |
685 EXYNOS_CISRCFMT_SOURCEVSIZE(img_sz.vsize));
686 fimc_write(cfg, EXYNOS_CISRCFMT);
687
688 /* offset Y(RGB), Cb, Cr */
689 cfg = (EXYNOS_CIIYOFF_HORIZONTAL(img_pos.x) |
690 EXYNOS_CIIYOFF_VERTICAL(img_pos.y));
691 fimc_write(cfg, EXYNOS_CIIYOFF);
692 cfg = (EXYNOS_CIICBOFF_HORIZONTAL(img_pos.x) |
693 EXYNOS_CIICBOFF_VERTICAL(img_pos.y));
694 fimc_write(cfg, EXYNOS_CIICBOFF);
695 cfg = (EXYNOS_CIICROFF_HORIZONTAL(img_pos.x) |
696 EXYNOS_CIICROFF_VERTICAL(img_pos.y));
697 fimc_write(cfg, EXYNOS_CIICROFF);
698
699 return fimc_set_window(ctx, &img_pos, &img_sz);
700}
701
702static int fimc_src_set_addr(struct device *dev,
703 struct drm_exynos_ipp_buf_info *buf_info, u32 buf_id,
704 enum drm_exynos_ipp_buf_type buf_type)
705{
706 struct fimc_context *ctx = get_fimc_context(dev);
707 struct exynos_drm_ippdrv *ippdrv = &ctx->ippdrv;
7259c3d6 708 struct drm_exynos_ipp_cmd_node *c_node = ippdrv->c_node;
16102edb
EK
709 struct drm_exynos_ipp_property *property;
710 struct drm_exynos_ipp_config *config;
711
712 if (!c_node) {
713 DRM_ERROR("failed to get c_node.\n");
714 return -EINVAL;
715 }
716
717 property = &c_node->property;
16102edb
EK
718
719 DRM_DEBUG_KMS("%s:prop_id[%d]buf_id[%d]buf_type[%d]\n", __func__,
720 property->prop_id, buf_id, buf_type);
721
722 if (buf_id > FIMC_MAX_SRC) {
723 dev_info(ippdrv->dev, "inavlid buf_id %d.\n", buf_id);
724 return -ENOMEM;
725 }
726
727 /* address register set */
728 switch (buf_type) {
729 case IPP_BUF_ENQUEUE:
730 config = &property->config[EXYNOS_DRM_OPS_SRC];
731 fimc_write(buf_info->base[EXYNOS_DRM_PLANAR_Y],
732 EXYNOS_CIIYSA(buf_id));
733
734 if (config->fmt == DRM_FORMAT_YVU420) {
735 fimc_write(buf_info->base[EXYNOS_DRM_PLANAR_CR],
736 EXYNOS_CIICBSA(buf_id));
737 fimc_write(buf_info->base[EXYNOS_DRM_PLANAR_CB],
738 EXYNOS_CIICRSA(buf_id));
739 } else {
740 fimc_write(buf_info->base[EXYNOS_DRM_PLANAR_CB],
741 EXYNOS_CIICBSA(buf_id));
742 fimc_write(buf_info->base[EXYNOS_DRM_PLANAR_CR],
743 EXYNOS_CIICRSA(buf_id));
744 }
745 break;
746 case IPP_BUF_DEQUEUE:
747 fimc_write(0x0, EXYNOS_CIIYSA(buf_id));
748 fimc_write(0x0, EXYNOS_CIICBSA(buf_id));
749 fimc_write(0x0, EXYNOS_CIICRSA(buf_id));
750 break;
751 default:
752 /* bypass */
753 break;
754 }
755
756 return 0;
757}
758
759static struct exynos_drm_ipp_ops fimc_src_ops = {
760 .set_fmt = fimc_src_set_fmt,
761 .set_transf = fimc_src_set_transf,
762 .set_size = fimc_src_set_size,
763 .set_addr = fimc_src_set_addr,
764};
765
766static int fimc_dst_set_fmt_order(struct fimc_context *ctx, u32 fmt)
767{
768 struct exynos_drm_ippdrv *ippdrv = &ctx->ippdrv;
769 u32 cfg;
770
771 DRM_DEBUG_KMS("%s:fmt[0x%x]\n", __func__, fmt);
772
773 /* RGB */
774 cfg = fimc_read(EXYNOS_CISCCTRL);
775 cfg &= ~EXYNOS_CISCCTRL_OUTRGB_FMT_RGB_MASK;
776
777 switch (fmt) {
778 case DRM_FORMAT_RGB565:
779 cfg |= EXYNOS_CISCCTRL_OUTRGB_FMT_RGB565;
780 fimc_write(cfg, EXYNOS_CISCCTRL);
781 return 0;
782 case DRM_FORMAT_RGB888:
783 cfg |= EXYNOS_CISCCTRL_OUTRGB_FMT_RGB888;
784 fimc_write(cfg, EXYNOS_CISCCTRL);
785 return 0;
786 case DRM_FORMAT_XRGB8888:
787 cfg |= (EXYNOS_CISCCTRL_OUTRGB_FMT_RGB888 |
788 EXYNOS_CISCCTRL_EXTRGB_EXTENSION);
789 fimc_write(cfg, EXYNOS_CISCCTRL);
790 break;
791 default:
792 /* bypass */
793 break;
794 }
795
796 /* YUV */
797 cfg = fimc_read(EXYNOS_CIOCTRL);
798 cfg &= ~(EXYNOS_CIOCTRL_ORDER2P_MASK |
799 EXYNOS_CIOCTRL_ORDER422_MASK |
800 EXYNOS_CIOCTRL_YCBCR_PLANE_MASK);
801
802 switch (fmt) {
803 case DRM_FORMAT_XRGB8888:
804 cfg |= EXYNOS_CIOCTRL_ALPHA_OUT;
805 break;
806 case DRM_FORMAT_YUYV:
807 cfg |= EXYNOS_CIOCTRL_ORDER422_YCBYCR;
808 break;
809 case DRM_FORMAT_YVYU:
810 cfg |= EXYNOS_CIOCTRL_ORDER422_YCRYCB;
811 break;
812 case DRM_FORMAT_UYVY:
813 cfg |= EXYNOS_CIOCTRL_ORDER422_CBYCRY;
814 break;
815 case DRM_FORMAT_VYUY:
816 cfg |= EXYNOS_CIOCTRL_ORDER422_CRYCBY;
817 break;
818 case DRM_FORMAT_NV21:
819 case DRM_FORMAT_NV61:
820 cfg |= EXYNOS_CIOCTRL_ORDER2P_LSB_CRCB;
821 cfg |= EXYNOS_CIOCTRL_YCBCR_2PLANE;
822 break;
823 case DRM_FORMAT_YUV422:
824 case DRM_FORMAT_YUV420:
825 case DRM_FORMAT_YVU420:
826 cfg |= EXYNOS_CIOCTRL_YCBCR_3PLANE;
827 break;
828 case DRM_FORMAT_NV12:
829 case DRM_FORMAT_NV12MT:
830 case DRM_FORMAT_NV16:
831 cfg |= EXYNOS_CIOCTRL_ORDER2P_LSB_CBCR;
832 cfg |= EXYNOS_CIOCTRL_YCBCR_2PLANE;
833 break;
834 default:
835 dev_err(ippdrv->dev, "inavlid target yuv order 0x%x.\n", fmt);
836 return -EINVAL;
837 }
838
839 fimc_write(cfg, EXYNOS_CIOCTRL);
840
841 return 0;
842}
843
844static int fimc_dst_set_fmt(struct device *dev, u32 fmt)
845{
846 struct fimc_context *ctx = get_fimc_context(dev);
847 struct exynos_drm_ippdrv *ippdrv = &ctx->ippdrv;
848 u32 cfg;
849
850 DRM_DEBUG_KMS("%s:fmt[0x%x]\n", __func__, fmt);
851
852 cfg = fimc_read(EXYNOS_CIEXTEN);
853
854 if (fmt == DRM_FORMAT_AYUV) {
855 cfg |= EXYNOS_CIEXTEN_YUV444_OUT;
856 fimc_write(cfg, EXYNOS_CIEXTEN);
857 } else {
858 cfg &= ~EXYNOS_CIEXTEN_YUV444_OUT;
859 fimc_write(cfg, EXYNOS_CIEXTEN);
860
861 cfg = fimc_read(EXYNOS_CITRGFMT);
862 cfg &= ~EXYNOS_CITRGFMT_OUTFORMAT_MASK;
863
864 switch (fmt) {
865 case DRM_FORMAT_RGB565:
866 case DRM_FORMAT_RGB888:
867 case DRM_FORMAT_XRGB8888:
868 cfg |= EXYNOS_CITRGFMT_OUTFORMAT_RGB;
869 break;
870 case DRM_FORMAT_YUYV:
871 case DRM_FORMAT_YVYU:
872 case DRM_FORMAT_UYVY:
873 case DRM_FORMAT_VYUY:
874 cfg |= EXYNOS_CITRGFMT_OUTFORMAT_YCBCR422_1PLANE;
875 break;
876 case DRM_FORMAT_NV16:
877 case DRM_FORMAT_NV61:
878 case DRM_FORMAT_YUV422:
879 cfg |= EXYNOS_CITRGFMT_OUTFORMAT_YCBCR422;
880 break;
881 case DRM_FORMAT_YUV420:
882 case DRM_FORMAT_YVU420:
883 case DRM_FORMAT_NV12:
884 case DRM_FORMAT_NV12MT:
885 case DRM_FORMAT_NV21:
886 cfg |= EXYNOS_CITRGFMT_OUTFORMAT_YCBCR420;
887 break;
888 default:
889 dev_err(ippdrv->dev, "inavlid target format 0x%x.\n",
890 fmt);
891 return -EINVAL;
892 }
893
894 fimc_write(cfg, EXYNOS_CITRGFMT);
895 }
896
897 cfg = fimc_read(EXYNOS_CIDMAPARAM);
898 cfg &= ~EXYNOS_CIDMAPARAM_W_MODE_MASK;
899
900 if (fmt == DRM_FORMAT_NV12MT)
901 cfg |= EXYNOS_CIDMAPARAM_W_MODE_64X32;
902 else
903 cfg |= EXYNOS_CIDMAPARAM_W_MODE_LINEAR;
904
905 fimc_write(cfg, EXYNOS_CIDMAPARAM);
906
907 return fimc_dst_set_fmt_order(ctx, fmt);
908}
909
910static int fimc_dst_set_transf(struct device *dev,
911 enum drm_exynos_degree degree,
912 enum drm_exynos_flip flip, bool *swap)
913{
914 struct fimc_context *ctx = get_fimc_context(dev);
915 struct exynos_drm_ippdrv *ippdrv = &ctx->ippdrv;
916 u32 cfg;
917
918 DRM_DEBUG_KMS("%s:degree[%d]flip[0x%x]\n", __func__,
919 degree, flip);
920
921 cfg = fimc_read(EXYNOS_CITRGFMT);
922 cfg &= ~EXYNOS_CITRGFMT_FLIP_MASK;
923 cfg &= ~EXYNOS_CITRGFMT_OUTROT90_CLOCKWISE;
924
925 switch (degree) {
926 case EXYNOS_DRM_DEGREE_0:
927 if (flip & EXYNOS_DRM_FLIP_VERTICAL)
928 cfg |= EXYNOS_CITRGFMT_FLIP_X_MIRROR;
929 if (flip & EXYNOS_DRM_FLIP_HORIZONTAL)
930 cfg |= EXYNOS_CITRGFMT_FLIP_Y_MIRROR;
931 break;
932 case EXYNOS_DRM_DEGREE_90:
933 cfg |= EXYNOS_CITRGFMT_OUTROT90_CLOCKWISE;
934 if (flip & EXYNOS_DRM_FLIP_VERTICAL)
935 cfg |= EXYNOS_CITRGFMT_FLIP_X_MIRROR;
936 if (flip & EXYNOS_DRM_FLIP_HORIZONTAL)
937 cfg |= EXYNOS_CITRGFMT_FLIP_Y_MIRROR;
938 break;
939 case EXYNOS_DRM_DEGREE_180:
940 cfg |= (EXYNOS_CITRGFMT_FLIP_X_MIRROR |
941 EXYNOS_CITRGFMT_FLIP_Y_MIRROR);
942 if (flip & EXYNOS_DRM_FLIP_VERTICAL)
943 cfg &= ~EXYNOS_CITRGFMT_FLIP_X_MIRROR;
944 if (flip & EXYNOS_DRM_FLIP_HORIZONTAL)
945 cfg &= ~EXYNOS_CITRGFMT_FLIP_Y_MIRROR;
946 break;
947 case EXYNOS_DRM_DEGREE_270:
948 cfg |= (EXYNOS_CITRGFMT_OUTROT90_CLOCKWISE |
949 EXYNOS_CITRGFMT_FLIP_X_MIRROR |
950 EXYNOS_CITRGFMT_FLIP_Y_MIRROR);
951 if (flip & EXYNOS_DRM_FLIP_VERTICAL)
952 cfg &= ~EXYNOS_CITRGFMT_FLIP_X_MIRROR;
953 if (flip & EXYNOS_DRM_FLIP_HORIZONTAL)
954 cfg &= ~EXYNOS_CITRGFMT_FLIP_Y_MIRROR;
955 break;
956 default:
957 dev_err(ippdrv->dev, "inavlid degree value %d.\n", degree);
958 return -EINVAL;
959 }
960
961 fimc_write(cfg, EXYNOS_CITRGFMT);
962 *swap = (cfg & EXYNOS_CITRGFMT_OUTROT90_CLOCKWISE) ? 1 : 0;
963
964 return 0;
965}
966
967static int fimc_get_ratio_shift(u32 src, u32 dst, u32 *ratio, u32 *shift)
968{
969 DRM_DEBUG_KMS("%s:src[%d]dst[%d]\n", __func__, src, dst);
970
971 if (src >= dst * 64) {
972 DRM_ERROR("failed to make ratio and shift.\n");
973 return -EINVAL;
974 } else if (src >= dst * 32) {
975 *ratio = 32;
976 *shift = 5;
977 } else if (src >= dst * 16) {
978 *ratio = 16;
979 *shift = 4;
980 } else if (src >= dst * 8) {
981 *ratio = 8;
982 *shift = 3;
983 } else if (src >= dst * 4) {
984 *ratio = 4;
985 *shift = 2;
986 } else if (src >= dst * 2) {
987 *ratio = 2;
988 *shift = 1;
989 } else {
990 *ratio = 1;
991 *shift = 0;
992 }
993
994 return 0;
995}
996
997static int fimc_set_prescaler(struct fimc_context *ctx, struct fimc_scaler *sc,
998 struct drm_exynos_pos *src, struct drm_exynos_pos *dst)
999{
1000 struct exynos_drm_ippdrv *ippdrv = &ctx->ippdrv;
1001 u32 cfg, cfg_ext, shfactor;
1002 u32 pre_dst_width, pre_dst_height;
1003 u32 pre_hratio, hfactor, pre_vratio, vfactor;
1004 int ret = 0;
1005 u32 src_w, src_h, dst_w, dst_h;
1006
1007 cfg_ext = fimc_read(EXYNOS_CITRGFMT);
1008 if (cfg_ext & EXYNOS_CITRGFMT_INROT90_CLOCKWISE) {
1009 src_w = src->h;
1010 src_h = src->w;
1011 } else {
1012 src_w = src->w;
1013 src_h = src->h;
1014 }
1015
1016 if (cfg_ext & EXYNOS_CITRGFMT_OUTROT90_CLOCKWISE) {
1017 dst_w = dst->h;
1018 dst_h = dst->w;
1019 } else {
1020 dst_w = dst->w;
1021 dst_h = dst->h;
1022 }
1023
1024 ret = fimc_get_ratio_shift(src_w, dst_w, &pre_hratio, &hfactor);
1025 if (ret) {
1026 dev_err(ippdrv->dev, "failed to get ratio horizontal.\n");
1027 return ret;
1028 }
1029
1030 ret = fimc_get_ratio_shift(src_h, dst_h, &pre_vratio, &vfactor);
1031 if (ret) {
1032 dev_err(ippdrv->dev, "failed to get ratio vertical.\n");
1033 return ret;
1034 }
1035
1036 pre_dst_width = src_w / pre_hratio;
1037 pre_dst_height = src_h / pre_vratio;
1038 DRM_DEBUG_KMS("%s:pre_dst_width[%d]pre_dst_height[%d]\n", __func__,
1039 pre_dst_width, pre_dst_height);
1040 DRM_DEBUG_KMS("%s:pre_hratio[%d]hfactor[%d]pre_vratio[%d]vfactor[%d]\n",
1041 __func__, pre_hratio, hfactor, pre_vratio, vfactor);
1042
1043 sc->hratio = (src_w << 14) / (dst_w << hfactor);
1044 sc->vratio = (src_h << 14) / (dst_h << vfactor);
1045 sc->up_h = (dst_w >= src_w) ? true : false;
1046 sc->up_v = (dst_h >= src_h) ? true : false;
1047 DRM_DEBUG_KMS("%s:hratio[%d]vratio[%d]up_h[%d]up_v[%d]\n",
1048 __func__, sc->hratio, sc->vratio, sc->up_h, sc->up_v);
1049
1050 shfactor = FIMC_SHFACTOR - (hfactor + vfactor);
1051 DRM_DEBUG_KMS("%s:shfactor[%d]\n", __func__, shfactor);
1052
1053 cfg = (EXYNOS_CISCPRERATIO_SHFACTOR(shfactor) |
1054 EXYNOS_CISCPRERATIO_PREHORRATIO(pre_hratio) |
1055 EXYNOS_CISCPRERATIO_PREVERRATIO(pre_vratio));
1056 fimc_write(cfg, EXYNOS_CISCPRERATIO);
1057
1058 cfg = (EXYNOS_CISCPREDST_PREDSTWIDTH(pre_dst_width) |
1059 EXYNOS_CISCPREDST_PREDSTHEIGHT(pre_dst_height));
1060 fimc_write(cfg, EXYNOS_CISCPREDST);
1061
1062 return ret;
1063}
1064
1065static void fimc_set_scaler(struct fimc_context *ctx, struct fimc_scaler *sc)
1066{
1067 u32 cfg, cfg_ext;
1068
1069 DRM_DEBUG_KMS("%s:range[%d]bypass[%d]up_h[%d]up_v[%d]\n",
1070 __func__, sc->range, sc->bypass, sc->up_h, sc->up_v);
1071 DRM_DEBUG_KMS("%s:hratio[%d]vratio[%d]\n",
1072 __func__, sc->hratio, sc->vratio);
1073
1074 cfg = fimc_read(EXYNOS_CISCCTRL);
1075 cfg &= ~(EXYNOS_CISCCTRL_SCALERBYPASS |
1076 EXYNOS_CISCCTRL_SCALEUP_H | EXYNOS_CISCCTRL_SCALEUP_V |
1077 EXYNOS_CISCCTRL_MAIN_V_RATIO_MASK |
1078 EXYNOS_CISCCTRL_MAIN_H_RATIO_MASK |
1079 EXYNOS_CISCCTRL_CSCR2Y_WIDE |
1080 EXYNOS_CISCCTRL_CSCY2R_WIDE);
1081
1082 if (sc->range)
1083 cfg |= (EXYNOS_CISCCTRL_CSCR2Y_WIDE |
1084 EXYNOS_CISCCTRL_CSCY2R_WIDE);
1085 if (sc->bypass)
1086 cfg |= EXYNOS_CISCCTRL_SCALERBYPASS;
1087 if (sc->up_h)
1088 cfg |= EXYNOS_CISCCTRL_SCALEUP_H;
1089 if (sc->up_v)
1090 cfg |= EXYNOS_CISCCTRL_SCALEUP_V;
1091
1092 cfg |= (EXYNOS_CISCCTRL_MAINHORRATIO((sc->hratio >> 6)) |
1093 EXYNOS_CISCCTRL_MAINVERRATIO((sc->vratio >> 6)));
1094 fimc_write(cfg, EXYNOS_CISCCTRL);
1095
1096 cfg_ext = fimc_read(EXYNOS_CIEXTEN);
1097 cfg_ext &= ~EXYNOS_CIEXTEN_MAINHORRATIO_EXT_MASK;
1098 cfg_ext &= ~EXYNOS_CIEXTEN_MAINVERRATIO_EXT_MASK;
1099 cfg_ext |= (EXYNOS_CIEXTEN_MAINHORRATIO_EXT(sc->hratio) |
1100 EXYNOS_CIEXTEN_MAINVERRATIO_EXT(sc->vratio));
1101 fimc_write(cfg_ext, EXYNOS_CIEXTEN);
1102}
1103
1104static int fimc_dst_set_size(struct device *dev, int swap,
1105 struct drm_exynos_pos *pos, struct drm_exynos_sz *sz)
1106{
1107 struct fimc_context *ctx = get_fimc_context(dev);
1108 struct drm_exynos_pos img_pos = *pos;
1109 struct drm_exynos_sz img_sz = *sz;
1110 u32 cfg;
1111
1112 DRM_DEBUG_KMS("%s:swap[%d]hsize[%d]vsize[%d]\n",
1113 __func__, swap, sz->hsize, sz->vsize);
1114
1115 /* original size */
1116 cfg = (EXYNOS_ORGOSIZE_HORIZONTAL(img_sz.hsize) |
1117 EXYNOS_ORGOSIZE_VERTICAL(img_sz.vsize));
1118
1119 fimc_write(cfg, EXYNOS_ORGOSIZE);
1120
1121 DRM_DEBUG_KMS("%s:x[%d]y[%d]w[%d]h[%d]\n",
1122 __func__, pos->x, pos->y, pos->w, pos->h);
1123
1124 /* CSC ITU */
1125 cfg = fimc_read(EXYNOS_CIGCTRL);
1126 cfg &= ~EXYNOS_CIGCTRL_CSC_MASK;
1127
1128 if (sz->hsize >= FIMC_WIDTH_ITU_709)
1129 cfg |= EXYNOS_CIGCTRL_CSC_ITU709;
1130 else
1131 cfg |= EXYNOS_CIGCTRL_CSC_ITU601;
1132
1133 fimc_write(cfg, EXYNOS_CIGCTRL);
1134
1135 if (swap) {
1136 img_pos.w = pos->h;
1137 img_pos.h = pos->w;
1138 img_sz.hsize = sz->vsize;
1139 img_sz.vsize = sz->hsize;
1140 }
1141
1142 /* target image size */
1143 cfg = fimc_read(EXYNOS_CITRGFMT);
1144 cfg &= ~(EXYNOS_CITRGFMT_TARGETH_MASK |
1145 EXYNOS_CITRGFMT_TARGETV_MASK);
1146 cfg |= (EXYNOS_CITRGFMT_TARGETHSIZE(img_pos.w) |
1147 EXYNOS_CITRGFMT_TARGETVSIZE(img_pos.h));
1148 fimc_write(cfg, EXYNOS_CITRGFMT);
1149
1150 /* target area */
1151 cfg = EXYNOS_CITAREA_TARGET_AREA(img_pos.w * img_pos.h);
1152 fimc_write(cfg, EXYNOS_CITAREA);
1153
1154 /* offset Y(RGB), Cb, Cr */
1155 cfg = (EXYNOS_CIOYOFF_HORIZONTAL(img_pos.x) |
1156 EXYNOS_CIOYOFF_VERTICAL(img_pos.y));
1157 fimc_write(cfg, EXYNOS_CIOYOFF);
1158 cfg = (EXYNOS_CIOCBOFF_HORIZONTAL(img_pos.x) |
1159 EXYNOS_CIOCBOFF_VERTICAL(img_pos.y));
1160 fimc_write(cfg, EXYNOS_CIOCBOFF);
1161 cfg = (EXYNOS_CIOCROFF_HORIZONTAL(img_pos.x) |
1162 EXYNOS_CIOCROFF_VERTICAL(img_pos.y));
1163 fimc_write(cfg, EXYNOS_CIOCROFF);
1164
1165 return 0;
1166}
1167
1168static int fimc_dst_get_buf_seq(struct fimc_context *ctx)
1169{
1170 u32 cfg, i, buf_num = 0;
1171 u32 mask = 0x00000001;
1172
1173 cfg = fimc_read(EXYNOS_CIFCNTSEQ);
1174
1175 for (i = 0; i < FIMC_REG_SZ; i++)
1176 if (cfg & (mask << i))
1177 buf_num++;
1178
1179 DRM_DEBUG_KMS("%s:buf_num[%d]\n", __func__, buf_num);
1180
1181 return buf_num;
1182}
1183
1184static int fimc_dst_set_buf_seq(struct fimc_context *ctx, u32 buf_id,
1185 enum drm_exynos_ipp_buf_type buf_type)
1186{
1187 struct exynos_drm_ippdrv *ippdrv = &ctx->ippdrv;
1188 bool enable;
1189 u32 cfg;
1190 u32 mask = 0x00000001 << buf_id;
1191 int ret = 0;
1192
1193 DRM_DEBUG_KMS("%s:buf_id[%d]buf_type[%d]\n", __func__,
1194 buf_id, buf_type);
1195
1196 mutex_lock(&ctx->lock);
1197
1198 /* mask register set */
1199 cfg = fimc_read(EXYNOS_CIFCNTSEQ);
1200
1201 switch (buf_type) {
1202 case IPP_BUF_ENQUEUE:
1203 enable = true;
1204 break;
1205 case IPP_BUF_DEQUEUE:
1206 enable = false;
1207 break;
1208 default:
1209 dev_err(ippdrv->dev, "invalid buf ctrl parameter.\n");
1210 ret = -EINVAL;
1211 goto err_unlock;
1212 }
1213
1214 /* sequence id */
13a32eb0 1215 cfg &= ~mask;
16102edb
EK
1216 cfg |= (enable << buf_id);
1217 fimc_write(cfg, EXYNOS_CIFCNTSEQ);
1218
1219 /* interrupt enable */
1220 if (buf_type == IPP_BUF_ENQUEUE &&
1221 fimc_dst_get_buf_seq(ctx) >= FIMC_BUF_START)
1222 fimc_handle_irq(ctx, true, false, true);
1223
1224 /* interrupt disable */
1225 if (buf_type == IPP_BUF_DEQUEUE &&
1226 fimc_dst_get_buf_seq(ctx) <= FIMC_BUF_STOP)
1227 fimc_handle_irq(ctx, false, false, true);
1228
1229err_unlock:
1230 mutex_unlock(&ctx->lock);
1231 return ret;
1232}
1233
1234static int fimc_dst_set_addr(struct device *dev,
1235 struct drm_exynos_ipp_buf_info *buf_info, u32 buf_id,
1236 enum drm_exynos_ipp_buf_type buf_type)
1237{
1238 struct fimc_context *ctx = get_fimc_context(dev);
1239 struct exynos_drm_ippdrv *ippdrv = &ctx->ippdrv;
7259c3d6 1240 struct drm_exynos_ipp_cmd_node *c_node = ippdrv->c_node;
16102edb
EK
1241 struct drm_exynos_ipp_property *property;
1242 struct drm_exynos_ipp_config *config;
1243
1244 if (!c_node) {
1245 DRM_ERROR("failed to get c_node.\n");
1246 return -EINVAL;
1247 }
1248
1249 property = &c_node->property;
16102edb
EK
1250
1251 DRM_DEBUG_KMS("%s:prop_id[%d]buf_id[%d]buf_type[%d]\n", __func__,
1252 property->prop_id, buf_id, buf_type);
1253
1254 if (buf_id > FIMC_MAX_DST) {
1255 dev_info(ippdrv->dev, "inavlid buf_id %d.\n", buf_id);
1256 return -ENOMEM;
1257 }
1258
1259 /* address register set */
1260 switch (buf_type) {
1261 case IPP_BUF_ENQUEUE:
1262 config = &property->config[EXYNOS_DRM_OPS_DST];
1263
1264 fimc_write(buf_info->base[EXYNOS_DRM_PLANAR_Y],
1265 EXYNOS_CIOYSA(buf_id));
1266
1267 if (config->fmt == DRM_FORMAT_YVU420) {
1268 fimc_write(buf_info->base[EXYNOS_DRM_PLANAR_CR],
1269 EXYNOS_CIOCBSA(buf_id));
1270 fimc_write(buf_info->base[EXYNOS_DRM_PLANAR_CB],
1271 EXYNOS_CIOCRSA(buf_id));
1272 } else {
1273 fimc_write(buf_info->base[EXYNOS_DRM_PLANAR_CB],
1274 EXYNOS_CIOCBSA(buf_id));
1275 fimc_write(buf_info->base[EXYNOS_DRM_PLANAR_CR],
1276 EXYNOS_CIOCRSA(buf_id));
1277 }
1278 break;
1279 case IPP_BUF_DEQUEUE:
1280 fimc_write(0x0, EXYNOS_CIOYSA(buf_id));
1281 fimc_write(0x0, EXYNOS_CIOCBSA(buf_id));
1282 fimc_write(0x0, EXYNOS_CIOCRSA(buf_id));
1283 break;
1284 default:
1285 /* bypass */
1286 break;
1287 }
1288
1289 return fimc_dst_set_buf_seq(ctx, buf_id, buf_type);
1290}
1291
1292static struct exynos_drm_ipp_ops fimc_dst_ops = {
1293 .set_fmt = fimc_dst_set_fmt,
1294 .set_transf = fimc_dst_set_transf,
1295 .set_size = fimc_dst_set_size,
1296 .set_addr = fimc_dst_set_addr,
1297};
1298
1299static int fimc_clk_ctrl(struct fimc_context *ctx, bool enable)
1300{
1301 DRM_DEBUG_KMS("%s:enable[%d]\n", __func__, enable);
1302
1303 if (enable) {
1304 clk_enable(ctx->sclk_fimc_clk);
1305 clk_enable(ctx->fimc_clk);
1306 clk_enable(ctx->wb_clk);
1307 ctx->suspended = false;
1308 } else {
1309 clk_disable(ctx->sclk_fimc_clk);
1310 clk_disable(ctx->fimc_clk);
1311 clk_disable(ctx->wb_clk);
1312 ctx->suspended = true;
1313 }
1314
1315 return 0;
1316}
1317
1318static irqreturn_t fimc_irq_handler(int irq, void *dev_id)
1319{
1320 struct fimc_context *ctx = dev_id;
1321 struct exynos_drm_ippdrv *ippdrv = &ctx->ippdrv;
7259c3d6 1322 struct drm_exynos_ipp_cmd_node *c_node = ippdrv->c_node;
16102edb
EK
1323 struct drm_exynos_ipp_event_work *event_work =
1324 c_node->event_work;
1325 int buf_id;
1326
1327 DRM_DEBUG_KMS("%s:fimc id[%d]\n", __func__, ctx->id);
1328
1329 fimc_clear_irq(ctx);
1330 if (fimc_check_ovf(ctx))
1331 return IRQ_NONE;
1332
1333 if (!fimc_check_frame_end(ctx))
1334 return IRQ_NONE;
1335
1336 buf_id = fimc_get_buf_id(ctx);
1337 if (buf_id < 0)
1338 return IRQ_HANDLED;
1339
1340 DRM_DEBUG_KMS("%s:buf_id[%d]\n", __func__, buf_id);
1341
1342 if (fimc_dst_set_buf_seq(ctx, buf_id, IPP_BUF_DEQUEUE) < 0) {
1343 DRM_ERROR("failed to dequeue.\n");
1344 return IRQ_HANDLED;
1345 }
1346
1347 event_work->ippdrv = ippdrv;
1348 event_work->buf_id[EXYNOS_DRM_OPS_DST] = buf_id;
1349 queue_work(ippdrv->event_workq, (struct work_struct *)event_work);
1350
1351 return IRQ_HANDLED;
1352}
1353
1354static int fimc_init_prop_list(struct exynos_drm_ippdrv *ippdrv)
1355{
1356 struct drm_exynos_ipp_prop_list *prop_list;
1357
1358 DRM_DEBUG_KMS("%s\n", __func__);
1359
1360 prop_list = devm_kzalloc(ippdrv->dev, sizeof(*prop_list), GFP_KERNEL);
1361 if (!prop_list) {
1362 DRM_ERROR("failed to alloc property list.\n");
1363 return -ENOMEM;
1364 }
1365
1366 prop_list->version = 1;
1367 prop_list->writeback = 1;
1368 prop_list->refresh_min = FIMC_REFRESH_MIN;
1369 prop_list->refresh_max = FIMC_REFRESH_MAX;
1370 prop_list->flip = (1 << EXYNOS_DRM_FLIP_NONE) |
1371 (1 << EXYNOS_DRM_FLIP_VERTICAL) |
1372 (1 << EXYNOS_DRM_FLIP_HORIZONTAL);
1373 prop_list->degree = (1 << EXYNOS_DRM_DEGREE_0) |
1374 (1 << EXYNOS_DRM_DEGREE_90) |
1375 (1 << EXYNOS_DRM_DEGREE_180) |
1376 (1 << EXYNOS_DRM_DEGREE_270);
1377 prop_list->csc = 1;
1378 prop_list->crop = 1;
1379 prop_list->crop_max.hsize = FIMC_CROP_MAX;
1380 prop_list->crop_max.vsize = FIMC_CROP_MAX;
1381 prop_list->crop_min.hsize = FIMC_CROP_MIN;
1382 prop_list->crop_min.vsize = FIMC_CROP_MIN;
1383 prop_list->scale = 1;
1384 prop_list->scale_max.hsize = FIMC_SCALE_MAX;
1385 prop_list->scale_max.vsize = FIMC_SCALE_MAX;
1386 prop_list->scale_min.hsize = FIMC_SCALE_MIN;
1387 prop_list->scale_min.vsize = FIMC_SCALE_MIN;
1388
1389 ippdrv->prop_list = prop_list;
1390
1391 return 0;
1392}
1393
1394static inline bool fimc_check_drm_flip(enum drm_exynos_flip flip)
1395{
1396 switch (flip) {
1397 case EXYNOS_DRM_FLIP_NONE:
1398 case EXYNOS_DRM_FLIP_VERTICAL:
1399 case EXYNOS_DRM_FLIP_HORIZONTAL:
4f21877c 1400 case EXYNOS_DRM_FLIP_BOTH:
16102edb
EK
1401 return true;
1402 default:
1403 DRM_DEBUG_KMS("%s:invalid flip\n", __func__);
1404 return false;
1405 }
1406}
1407
1408static int fimc_ippdrv_check_property(struct device *dev,
1409 struct drm_exynos_ipp_property *property)
1410{
1411 struct fimc_context *ctx = get_fimc_context(dev);
1412 struct exynos_drm_ippdrv *ippdrv = &ctx->ippdrv;
1413 struct drm_exynos_ipp_prop_list *pp = ippdrv->prop_list;
1414 struct drm_exynos_ipp_config *config;
1415 struct drm_exynos_pos *pos;
1416 struct drm_exynos_sz *sz;
1417 bool swap;
1418 int i;
1419
1420 DRM_DEBUG_KMS("%s\n", __func__);
1421
1422 for_each_ipp_ops(i) {
1423 if ((i == EXYNOS_DRM_OPS_SRC) &&
1424 (property->cmd == IPP_CMD_WB))
1425 continue;
1426
1427 config = &property->config[i];
1428 pos = &config->pos;
1429 sz = &config->sz;
1430
1431 /* check for flip */
1432 if (!fimc_check_drm_flip(config->flip)) {
1433 DRM_ERROR("invalid flip.\n");
1434 goto err_property;
1435 }
1436
1437 /* check for degree */
1438 switch (config->degree) {
1439 case EXYNOS_DRM_DEGREE_90:
1440 case EXYNOS_DRM_DEGREE_270:
1441 swap = true;
1442 break;
1443 case EXYNOS_DRM_DEGREE_0:
1444 case EXYNOS_DRM_DEGREE_180:
1445 swap = false;
1446 break;
1447 default:
1448 DRM_ERROR("invalid degree.\n");
1449 goto err_property;
1450 }
1451
1452 /* check for buffer bound */
1453 if ((pos->x + pos->w > sz->hsize) ||
1454 (pos->y + pos->h > sz->vsize)) {
1455 DRM_ERROR("out of buf bound.\n");
1456 goto err_property;
1457 }
1458
1459 /* check for crop */
1460 if ((i == EXYNOS_DRM_OPS_SRC) && (pp->crop)) {
1461 if (swap) {
1462 if ((pos->h < pp->crop_min.hsize) ||
1463 (sz->vsize > pp->crop_max.hsize) ||
1464 (pos->w < pp->crop_min.vsize) ||
1465 (sz->hsize > pp->crop_max.vsize)) {
1466 DRM_ERROR("out of crop size.\n");
1467 goto err_property;
1468 }
1469 } else {
1470 if ((pos->w < pp->crop_min.hsize) ||
1471 (sz->hsize > pp->crop_max.hsize) ||
1472 (pos->h < pp->crop_min.vsize) ||
1473 (sz->vsize > pp->crop_max.vsize)) {
1474 DRM_ERROR("out of crop size.\n");
1475 goto err_property;
1476 }
1477 }
1478 }
1479
1480 /* check for scale */
1481 if ((i == EXYNOS_DRM_OPS_DST) && (pp->scale)) {
1482 if (swap) {
1483 if ((pos->h < pp->scale_min.hsize) ||
1484 (sz->vsize > pp->scale_max.hsize) ||
1485 (pos->w < pp->scale_min.vsize) ||
1486 (sz->hsize > pp->scale_max.vsize)) {
1487 DRM_ERROR("out of scale size.\n");
1488 goto err_property;
1489 }
1490 } else {
1491 if ((pos->w < pp->scale_min.hsize) ||
1492 (sz->hsize > pp->scale_max.hsize) ||
1493 (pos->h < pp->scale_min.vsize) ||
1494 (sz->vsize > pp->scale_max.vsize)) {
1495 DRM_ERROR("out of scale size.\n");
1496 goto err_property;
1497 }
1498 }
1499 }
1500 }
1501
1502 return 0;
1503
1504err_property:
1505 for_each_ipp_ops(i) {
1506 if ((i == EXYNOS_DRM_OPS_SRC) &&
1507 (property->cmd == IPP_CMD_WB))
1508 continue;
1509
1510 config = &property->config[i];
1511 pos = &config->pos;
1512 sz = &config->sz;
1513
1514 DRM_ERROR("[%s]f[%d]r[%d]pos[%d %d %d %d]sz[%d %d]\n",
1515 i ? "dst" : "src", config->flip, config->degree,
1516 pos->x, pos->y, pos->w, pos->h,
1517 sz->hsize, sz->vsize);
1518 }
1519
1520 return -EINVAL;
1521}
1522
1523static void fimc_clear_addr(struct fimc_context *ctx)
1524{
1525 int i;
1526
1527 DRM_DEBUG_KMS("%s:\n", __func__);
1528
1529 for (i = 0; i < FIMC_MAX_SRC; i++) {
1530 fimc_write(0, EXYNOS_CIIYSA(i));
1531 fimc_write(0, EXYNOS_CIICBSA(i));
1532 fimc_write(0, EXYNOS_CIICRSA(i));
1533 }
1534
1535 for (i = 0; i < FIMC_MAX_DST; i++) {
1536 fimc_write(0, EXYNOS_CIOYSA(i));
1537 fimc_write(0, EXYNOS_CIOCBSA(i));
1538 fimc_write(0, EXYNOS_CIOCRSA(i));
1539 }
1540}
1541
1542static int fimc_ippdrv_reset(struct device *dev)
1543{
1544 struct fimc_context *ctx = get_fimc_context(dev);
1545
1546 DRM_DEBUG_KMS("%s\n", __func__);
1547
1548 /* reset h/w block */
b5c0b552 1549 fimc_sw_reset(ctx);
16102edb
EK
1550
1551 /* reset scaler capability */
1552 memset(&ctx->sc, 0x0, sizeof(ctx->sc));
1553
1554 fimc_clear_addr(ctx);
1555
1556 return 0;
1557}
1558
1559static int fimc_ippdrv_start(struct device *dev, enum drm_exynos_ipp_cmd cmd)
1560{
1561 struct fimc_context *ctx = get_fimc_context(dev);
1562 struct exynos_drm_ippdrv *ippdrv = &ctx->ippdrv;
7259c3d6 1563 struct drm_exynos_ipp_cmd_node *c_node = ippdrv->c_node;
16102edb
EK
1564 struct drm_exynos_ipp_property *property;
1565 struct drm_exynos_ipp_config *config;
1566 struct drm_exynos_pos img_pos[EXYNOS_DRM_OPS_MAX];
1567 struct drm_exynos_ipp_set_wb set_wb;
1568 int ret, i;
1569 u32 cfg0, cfg1;
1570
1571 DRM_DEBUG_KMS("%s:cmd[%d]\n", __func__, cmd);
1572
1573 if (!c_node) {
1574 DRM_ERROR("failed to get c_node.\n");
1575 return -EINVAL;
1576 }
1577
1578 property = &c_node->property;
16102edb
EK
1579
1580 fimc_handle_irq(ctx, true, false, true);
1581
1582 for_each_ipp_ops(i) {
1583 config = &property->config[i];
1584 img_pos[i] = config->pos;
1585 }
1586
1587 ret = fimc_set_prescaler(ctx, &ctx->sc,
1588 &img_pos[EXYNOS_DRM_OPS_SRC],
1589 &img_pos[EXYNOS_DRM_OPS_DST]);
1590 if (ret) {
1591 dev_err(dev, "failed to set precalser.\n");
1592 return ret;
1593 }
1594
1595 /* If set ture, we can save jpeg about screen */
1596 fimc_handle_jpeg(ctx, false);
1597 fimc_set_scaler(ctx, &ctx->sc);
1598 fimc_set_polarity(ctx, &ctx->pol);
1599
1600 switch (cmd) {
1601 case IPP_CMD_M2M:
1602 fimc_set_type_ctrl(ctx, FIMC_WB_NONE);
1603 fimc_handle_lastend(ctx, false);
1604
1605 /* setup dma */
1606 cfg0 = fimc_read(EXYNOS_MSCTRL);
1607 cfg0 &= ~EXYNOS_MSCTRL_INPUT_MASK;
1608 cfg0 |= EXYNOS_MSCTRL_INPUT_MEMORY;
1609 fimc_write(cfg0, EXYNOS_MSCTRL);
1610 break;
1611 case IPP_CMD_WB:
1612 fimc_set_type_ctrl(ctx, FIMC_WB_A);
1613 fimc_handle_lastend(ctx, true);
1614
1615 /* setup FIMD */
1616 fimc_set_camblk_fimd0_wb(ctx);
1617
1618 set_wb.enable = 1;
1619 set_wb.refresh = property->refresh_rate;
1620 exynos_drm_ippnb_send_event(IPP_SET_WRITEBACK, (void *)&set_wb);
1621 break;
1622 case IPP_CMD_OUTPUT:
1623 default:
1624 ret = -EINVAL;
1625 dev_err(dev, "invalid operations.\n");
1626 return ret;
1627 }
1628
1629 /* Reset status */
1630 fimc_write(0x0, EXYNOS_CISTATUS);
1631
1632 cfg0 = fimc_read(EXYNOS_CIIMGCPT);
1633 cfg0 &= ~EXYNOS_CIIMGCPT_IMGCPTEN_SC;
1634 cfg0 |= EXYNOS_CIIMGCPT_IMGCPTEN_SC;
1635
1636 /* Scaler */
1637 cfg1 = fimc_read(EXYNOS_CISCCTRL);
1638 cfg1 &= ~EXYNOS_CISCCTRL_SCAN_MASK;
1639 cfg1 |= (EXYNOS_CISCCTRL_PROGRESSIVE |
1640 EXYNOS_CISCCTRL_SCALERSTART);
1641
1642 fimc_write(cfg1, EXYNOS_CISCCTRL);
1643
1644 /* Enable image capture*/
1645 cfg0 |= EXYNOS_CIIMGCPT_IMGCPTEN;
1646 fimc_write(cfg0, EXYNOS_CIIMGCPT);
1647
1648 /* Disable frame end irq */
1649 cfg0 = fimc_read(EXYNOS_CIGCTRL);
1650 cfg0 &= ~EXYNOS_CIGCTRL_IRQ_END_DISABLE;
1651 fimc_write(cfg0, EXYNOS_CIGCTRL);
1652
1653 cfg0 = fimc_read(EXYNOS_CIOCTRL);
1654 cfg0 &= ~EXYNOS_CIOCTRL_WEAVE_MASK;
1655 fimc_write(cfg0, EXYNOS_CIOCTRL);
1656
1657 if (cmd == IPP_CMD_M2M) {
1658 cfg0 = fimc_read(EXYNOS_MSCTRL);
1659 cfg0 |= EXYNOS_MSCTRL_ENVID;
1660 fimc_write(cfg0, EXYNOS_MSCTRL);
1661
1662 cfg0 = fimc_read(EXYNOS_MSCTRL);
1663 cfg0 |= EXYNOS_MSCTRL_ENVID;
1664 fimc_write(cfg0, EXYNOS_MSCTRL);
1665 }
1666
1667 return 0;
1668}
1669
1670static void fimc_ippdrv_stop(struct device *dev, enum drm_exynos_ipp_cmd cmd)
1671{
1672 struct fimc_context *ctx = get_fimc_context(dev);
1673 struct drm_exynos_ipp_set_wb set_wb = {0, 0};
1674 u32 cfg;
1675
1676 DRM_DEBUG_KMS("%s:cmd[%d]\n", __func__, cmd);
1677
1678 switch (cmd) {
1679 case IPP_CMD_M2M:
1680 /* Source clear */
1681 cfg = fimc_read(EXYNOS_MSCTRL);
1682 cfg &= ~EXYNOS_MSCTRL_INPUT_MASK;
1683 cfg &= ~EXYNOS_MSCTRL_ENVID;
1684 fimc_write(cfg, EXYNOS_MSCTRL);
1685 break;
1686 case IPP_CMD_WB:
1687 exynos_drm_ippnb_send_event(IPP_SET_WRITEBACK, (void *)&set_wb);
1688 break;
1689 case IPP_CMD_OUTPUT:
1690 default:
1691 dev_err(dev, "invalid operations.\n");
1692 break;
1693 }
1694
1695 fimc_handle_irq(ctx, false, false, true);
1696
1697 /* reset sequence */
1698 fimc_write(0x0, EXYNOS_CIFCNTSEQ);
1699
1700 /* Scaler disable */
1701 cfg = fimc_read(EXYNOS_CISCCTRL);
1702 cfg &= ~EXYNOS_CISCCTRL_SCALERSTART;
1703 fimc_write(cfg, EXYNOS_CISCCTRL);
1704
1705 /* Disable image capture */
1706 cfg = fimc_read(EXYNOS_CIIMGCPT);
1707 cfg &= ~(EXYNOS_CIIMGCPT_IMGCPTEN_SC | EXYNOS_CIIMGCPT_IMGCPTEN);
1708 fimc_write(cfg, EXYNOS_CIIMGCPT);
1709
1710 /* Enable frame end irq */
1711 cfg = fimc_read(EXYNOS_CIGCTRL);
1712 cfg |= EXYNOS_CIGCTRL_IRQ_END_DISABLE;
1713 fimc_write(cfg, EXYNOS_CIGCTRL);
1714}
1715
56550d94 1716static int fimc_probe(struct platform_device *pdev)
16102edb
EK
1717{
1718 struct device *dev = &pdev->dev;
1719 struct fimc_context *ctx;
1720 struct clk *parent_clk;
1721 struct resource *res;
1722 struct exynos_drm_ippdrv *ippdrv;
1723 struct exynos_drm_fimc_pdata *pdata;
1724 struct fimc_driverdata *ddata;
1725 int ret;
1726
1727 pdata = pdev->dev.platform_data;
1728 if (!pdata) {
1729 dev_err(dev, "no platform data specified.\n");
1730 return -EINVAL;
1731 }
1732
1733 ctx = devm_kzalloc(dev, sizeof(*ctx), GFP_KERNEL);
1734 if (!ctx)
1735 return -ENOMEM;
1736
1737 ddata = (struct fimc_driverdata *)
1738 platform_get_device_id(pdev)->driver_data;
1739
1740 /* clock control */
15b3263e 1741 ctx->sclk_fimc_clk = devm_clk_get(dev, "sclk_fimc");
16102edb
EK
1742 if (IS_ERR(ctx->sclk_fimc_clk)) {
1743 dev_err(dev, "failed to get src fimc clock.\n");
87acdde5 1744 return PTR_ERR(ctx->sclk_fimc_clk);
16102edb
EK
1745 }
1746 clk_enable(ctx->sclk_fimc_clk);
1747
15b3263e 1748 ctx->fimc_clk = devm_clk_get(dev, "fimc");
16102edb
EK
1749 if (IS_ERR(ctx->fimc_clk)) {
1750 dev_err(dev, "failed to get fimc clock.\n");
16102edb 1751 clk_disable(ctx->sclk_fimc_clk);
87acdde5 1752 return PTR_ERR(ctx->fimc_clk);
16102edb
EK
1753 }
1754
15b3263e 1755 ctx->wb_clk = devm_clk_get(dev, "pxl_async0");
16102edb
EK
1756 if (IS_ERR(ctx->wb_clk)) {
1757 dev_err(dev, "failed to get writeback a clock.\n");
16102edb 1758 clk_disable(ctx->sclk_fimc_clk);
87acdde5 1759 return PTR_ERR(ctx->wb_clk);
16102edb
EK
1760 }
1761
15b3263e 1762 ctx->wb_b_clk = devm_clk_get(dev, "pxl_async1");
16102edb
EK
1763 if (IS_ERR(ctx->wb_b_clk)) {
1764 dev_err(dev, "failed to get writeback b clock.\n");
16102edb 1765 clk_disable(ctx->sclk_fimc_clk);
87acdde5 1766 return PTR_ERR(ctx->wb_b_clk);
16102edb
EK
1767 }
1768
15b3263e 1769 parent_clk = devm_clk_get(dev, ddata->parent_clk);
16102edb
EK
1770
1771 if (IS_ERR(parent_clk)) {
1772 dev_err(dev, "failed to get parent clock.\n");
16102edb 1773 clk_disable(ctx->sclk_fimc_clk);
87acdde5 1774 return PTR_ERR(parent_clk);
16102edb
EK
1775 }
1776
1777 if (clk_set_parent(ctx->sclk_fimc_clk, parent_clk)) {
1778 dev_err(dev, "failed to set parent.\n");
16102edb 1779 clk_disable(ctx->sclk_fimc_clk);
87acdde5 1780 return -EINVAL;
16102edb
EK
1781 }
1782
15b3263e 1783 devm_clk_put(dev, parent_clk);
16102edb
EK
1784 clk_set_rate(ctx->sclk_fimc_clk, pdata->clk_rate);
1785
1786 /* resource memory */
1787 ctx->regs_res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
d4ed6025
TR
1788 ctx->regs = devm_ioremap_resource(dev, ctx->regs_res);
1789 if (IS_ERR(ctx->regs))
1790 return PTR_ERR(ctx->regs);
16102edb
EK
1791
1792 /* resource irq */
1793 res = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
1794 if (!res) {
1795 dev_err(dev, "failed to request irq resource.\n");
15b3263e 1796 return -ENOENT;
16102edb
EK
1797 }
1798
1799 ctx->irq = res->start;
1800 ret = request_threaded_irq(ctx->irq, NULL, fimc_irq_handler,
1801 IRQF_ONESHOT, "drm_fimc", ctx);
1802 if (ret < 0) {
1803 dev_err(dev, "failed to request irq.\n");
15b3263e 1804 return ret;
16102edb
EK
1805 }
1806
1807 /* context initailization */
1808 ctx->id = pdev->id;
1809 ctx->pol = pdata->pol;
1810 ctx->ddata = ddata;
1811
1812 ippdrv = &ctx->ippdrv;
1813 ippdrv->dev = dev;
1814 ippdrv->ops[EXYNOS_DRM_OPS_SRC] = &fimc_src_ops;
1815 ippdrv->ops[EXYNOS_DRM_OPS_DST] = &fimc_dst_ops;
1816 ippdrv->check_property = fimc_ippdrv_check_property;
1817 ippdrv->reset = fimc_ippdrv_reset;
1818 ippdrv->start = fimc_ippdrv_start;
1819 ippdrv->stop = fimc_ippdrv_stop;
1820 ret = fimc_init_prop_list(ippdrv);
1821 if (ret < 0) {
1822 dev_err(dev, "failed to init property list.\n");
1823 goto err_get_irq;
1824 }
1825
1826 DRM_DEBUG_KMS("%s:id[%d]ippdrv[0x%x]\n", __func__, ctx->id,
1827 (int)ippdrv);
1828
1829 mutex_init(&ctx->lock);
1830 platform_set_drvdata(pdev, ctx);
1831
1832 pm_runtime_set_active(dev);
1833 pm_runtime_enable(dev);
1834
1835 ret = exynos_drm_ippdrv_register(ippdrv);
1836 if (ret < 0) {
1837 dev_err(dev, "failed to register drm fimc device.\n");
1838 goto err_ippdrv_register;
1839 }
1840
1841 dev_info(&pdev->dev, "drm fimc registered successfully.\n");
1842
1843 return 0;
1844
1845err_ippdrv_register:
16102edb
EK
1846 pm_runtime_disable(dev);
1847err_get_irq:
1848 free_irq(ctx->irq, ctx);
87acdde5 1849
16102edb
EK
1850 return ret;
1851}
1852
56550d94 1853static int fimc_remove(struct platform_device *pdev)
16102edb
EK
1854{
1855 struct device *dev = &pdev->dev;
1856 struct fimc_context *ctx = get_fimc_context(dev);
1857 struct exynos_drm_ippdrv *ippdrv = &ctx->ippdrv;
1858
16102edb
EK
1859 exynos_drm_ippdrv_unregister(ippdrv);
1860 mutex_destroy(&ctx->lock);
1861
1862 pm_runtime_set_suspended(dev);
1863 pm_runtime_disable(dev);
1864
1865 free_irq(ctx->irq, ctx);
16102edb
EK
1866
1867 return 0;
1868}
1869
1870#ifdef CONFIG_PM_SLEEP
1871static int fimc_suspend(struct device *dev)
1872{
1873 struct fimc_context *ctx = get_fimc_context(dev);
1874
1875 DRM_DEBUG_KMS("%s:id[%d]\n", __func__, ctx->id);
1876
1877 if (pm_runtime_suspended(dev))
1878 return 0;
1879
1880 return fimc_clk_ctrl(ctx, false);
1881}
1882
1883static int fimc_resume(struct device *dev)
1884{
1885 struct fimc_context *ctx = get_fimc_context(dev);
1886
1887 DRM_DEBUG_KMS("%s:id[%d]\n", __func__, ctx->id);
1888
1889 if (!pm_runtime_suspended(dev))
1890 return fimc_clk_ctrl(ctx, true);
1891
1892 return 0;
1893}
1894#endif
1895
1896#ifdef CONFIG_PM_RUNTIME
1897static int fimc_runtime_suspend(struct device *dev)
1898{
1899 struct fimc_context *ctx = get_fimc_context(dev);
1900
1901 DRM_DEBUG_KMS("%s:id[%d]\n", __func__, ctx->id);
1902
1903 return fimc_clk_ctrl(ctx, false);
1904}
1905
1906static int fimc_runtime_resume(struct device *dev)
1907{
1908 struct fimc_context *ctx = get_fimc_context(dev);
1909
1910 DRM_DEBUG_KMS("%s:id[%d]\n", __func__, ctx->id);
1911
1912 return fimc_clk_ctrl(ctx, true);
1913}
1914#endif
1915
1916static struct fimc_driverdata exynos4210_fimc_data = {
1917 .parent_clk = "mout_mpll",
1918};
1919
1920static struct fimc_driverdata exynos4410_fimc_data = {
1921 .parent_clk = "mout_mpll_user",
1922};
1923
1924static struct platform_device_id fimc_driver_ids[] = {
1925 {
1926 .name = "exynos4210-fimc",
1927 .driver_data = (unsigned long)&exynos4210_fimc_data,
1928 }, {
1929 .name = "exynos4412-fimc",
1930 .driver_data = (unsigned long)&exynos4410_fimc_data,
1931 },
1932 {},
1933};
1934MODULE_DEVICE_TABLE(platform, fimc_driver_ids);
1935
1936static const struct dev_pm_ops fimc_pm_ops = {
1937 SET_SYSTEM_SLEEP_PM_OPS(fimc_suspend, fimc_resume)
1938 SET_RUNTIME_PM_OPS(fimc_runtime_suspend, fimc_runtime_resume, NULL)
1939};
1940
1941struct platform_driver fimc_driver = {
1942 .probe = fimc_probe,
56550d94 1943 .remove = fimc_remove,
16102edb
EK
1944 .id_table = fimc_driver_ids,
1945 .driver = {
1946 .name = "exynos-drm-fimc",
1947 .owner = THIS_MODULE,
1948 .pm = &fimc_pm_ops,
1949 },
1950};
1951
This page took 0.12381 seconds and 5 git commands to generate.