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