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