61ea24296b526f4c00d76dc77a0002bd94401da7
[deliverable/linux.git] / drivers / gpu / drm / exynos / exynos_drm_fimc.c
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
73 enum 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 */
89 struct 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 */
109 struct 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 */
126 struct 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 */
149 struct 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
166 static 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
193 static 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
206 static 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
241 static 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
267 static 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
282 static 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
304 static 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
315 static 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
347 static 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
364 static 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
392 static 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
408 static 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
480 static 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
538 static 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
599 static 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
634 static 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
692 static 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;
698 struct drm_exynos_ipp_cmd_node *c_node = ippdrv->cmd;
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;
708 if (!property) {
709 DRM_ERROR("failed to get property.\n");
710 return -EINVAL;
711 }
712
713 DRM_DEBUG_KMS("%s:prop_id[%d]buf_id[%d]buf_type[%d]\n", __func__,
714 property->prop_id, buf_id, buf_type);
715
716 if (buf_id > FIMC_MAX_SRC) {
717 dev_info(ippdrv->dev, "inavlid buf_id %d.\n", buf_id);
718 return -ENOMEM;
719 }
720
721 /* address register set */
722 switch (buf_type) {
723 case IPP_BUF_ENQUEUE:
724 config = &property->config[EXYNOS_DRM_OPS_SRC];
725 fimc_write(buf_info->base[EXYNOS_DRM_PLANAR_Y],
726 EXYNOS_CIIYSA(buf_id));
727
728 if (config->fmt == DRM_FORMAT_YVU420) {
729 fimc_write(buf_info->base[EXYNOS_DRM_PLANAR_CR],
730 EXYNOS_CIICBSA(buf_id));
731 fimc_write(buf_info->base[EXYNOS_DRM_PLANAR_CB],
732 EXYNOS_CIICRSA(buf_id));
733 } else {
734 fimc_write(buf_info->base[EXYNOS_DRM_PLANAR_CB],
735 EXYNOS_CIICBSA(buf_id));
736 fimc_write(buf_info->base[EXYNOS_DRM_PLANAR_CR],
737 EXYNOS_CIICRSA(buf_id));
738 }
739 break;
740 case IPP_BUF_DEQUEUE:
741 fimc_write(0x0, EXYNOS_CIIYSA(buf_id));
742 fimc_write(0x0, EXYNOS_CIICBSA(buf_id));
743 fimc_write(0x0, EXYNOS_CIICRSA(buf_id));
744 break;
745 default:
746 /* bypass */
747 break;
748 }
749
750 return 0;
751 }
752
753 static struct exynos_drm_ipp_ops fimc_src_ops = {
754 .set_fmt = fimc_src_set_fmt,
755 .set_transf = fimc_src_set_transf,
756 .set_size = fimc_src_set_size,
757 .set_addr = fimc_src_set_addr,
758 };
759
760 static int fimc_dst_set_fmt_order(struct fimc_context *ctx, u32 fmt)
761 {
762 struct exynos_drm_ippdrv *ippdrv = &ctx->ippdrv;
763 u32 cfg;
764
765 DRM_DEBUG_KMS("%s:fmt[0x%x]\n", __func__, fmt);
766
767 /* RGB */
768 cfg = fimc_read(EXYNOS_CISCCTRL);
769 cfg &= ~EXYNOS_CISCCTRL_OUTRGB_FMT_RGB_MASK;
770
771 switch (fmt) {
772 case DRM_FORMAT_RGB565:
773 cfg |= EXYNOS_CISCCTRL_OUTRGB_FMT_RGB565;
774 fimc_write(cfg, EXYNOS_CISCCTRL);
775 return 0;
776 case DRM_FORMAT_RGB888:
777 cfg |= EXYNOS_CISCCTRL_OUTRGB_FMT_RGB888;
778 fimc_write(cfg, EXYNOS_CISCCTRL);
779 return 0;
780 case DRM_FORMAT_XRGB8888:
781 cfg |= (EXYNOS_CISCCTRL_OUTRGB_FMT_RGB888 |
782 EXYNOS_CISCCTRL_EXTRGB_EXTENSION);
783 fimc_write(cfg, EXYNOS_CISCCTRL);
784 break;
785 default:
786 /* bypass */
787 break;
788 }
789
790 /* YUV */
791 cfg = fimc_read(EXYNOS_CIOCTRL);
792 cfg &= ~(EXYNOS_CIOCTRL_ORDER2P_MASK |
793 EXYNOS_CIOCTRL_ORDER422_MASK |
794 EXYNOS_CIOCTRL_YCBCR_PLANE_MASK);
795
796 switch (fmt) {
797 case DRM_FORMAT_XRGB8888:
798 cfg |= EXYNOS_CIOCTRL_ALPHA_OUT;
799 break;
800 case DRM_FORMAT_YUYV:
801 cfg |= EXYNOS_CIOCTRL_ORDER422_YCBYCR;
802 break;
803 case DRM_FORMAT_YVYU:
804 cfg |= EXYNOS_CIOCTRL_ORDER422_YCRYCB;
805 break;
806 case DRM_FORMAT_UYVY:
807 cfg |= EXYNOS_CIOCTRL_ORDER422_CBYCRY;
808 break;
809 case DRM_FORMAT_VYUY:
810 cfg |= EXYNOS_CIOCTRL_ORDER422_CRYCBY;
811 break;
812 case DRM_FORMAT_NV21:
813 case DRM_FORMAT_NV61:
814 cfg |= EXYNOS_CIOCTRL_ORDER2P_LSB_CRCB;
815 cfg |= EXYNOS_CIOCTRL_YCBCR_2PLANE;
816 break;
817 case DRM_FORMAT_YUV422:
818 case DRM_FORMAT_YUV420:
819 case DRM_FORMAT_YVU420:
820 cfg |= EXYNOS_CIOCTRL_YCBCR_3PLANE;
821 break;
822 case DRM_FORMAT_NV12:
823 case DRM_FORMAT_NV12MT:
824 case DRM_FORMAT_NV16:
825 cfg |= EXYNOS_CIOCTRL_ORDER2P_LSB_CBCR;
826 cfg |= EXYNOS_CIOCTRL_YCBCR_2PLANE;
827 break;
828 default:
829 dev_err(ippdrv->dev, "inavlid target yuv order 0x%x.\n", fmt);
830 return -EINVAL;
831 }
832
833 fimc_write(cfg, EXYNOS_CIOCTRL);
834
835 return 0;
836 }
837
838 static int fimc_dst_set_fmt(struct device *dev, u32 fmt)
839 {
840 struct fimc_context *ctx = get_fimc_context(dev);
841 struct exynos_drm_ippdrv *ippdrv = &ctx->ippdrv;
842 u32 cfg;
843
844 DRM_DEBUG_KMS("%s:fmt[0x%x]\n", __func__, fmt);
845
846 cfg = fimc_read(EXYNOS_CIEXTEN);
847
848 if (fmt == DRM_FORMAT_AYUV) {
849 cfg |= EXYNOS_CIEXTEN_YUV444_OUT;
850 fimc_write(cfg, EXYNOS_CIEXTEN);
851 } else {
852 cfg &= ~EXYNOS_CIEXTEN_YUV444_OUT;
853 fimc_write(cfg, EXYNOS_CIEXTEN);
854
855 cfg = fimc_read(EXYNOS_CITRGFMT);
856 cfg &= ~EXYNOS_CITRGFMT_OUTFORMAT_MASK;
857
858 switch (fmt) {
859 case DRM_FORMAT_RGB565:
860 case DRM_FORMAT_RGB888:
861 case DRM_FORMAT_XRGB8888:
862 cfg |= EXYNOS_CITRGFMT_OUTFORMAT_RGB;
863 break;
864 case DRM_FORMAT_YUYV:
865 case DRM_FORMAT_YVYU:
866 case DRM_FORMAT_UYVY:
867 case DRM_FORMAT_VYUY:
868 cfg |= EXYNOS_CITRGFMT_OUTFORMAT_YCBCR422_1PLANE;
869 break;
870 case DRM_FORMAT_NV16:
871 case DRM_FORMAT_NV61:
872 case DRM_FORMAT_YUV422:
873 cfg |= EXYNOS_CITRGFMT_OUTFORMAT_YCBCR422;
874 break;
875 case DRM_FORMAT_YUV420:
876 case DRM_FORMAT_YVU420:
877 case DRM_FORMAT_NV12:
878 case DRM_FORMAT_NV12MT:
879 case DRM_FORMAT_NV21:
880 cfg |= EXYNOS_CITRGFMT_OUTFORMAT_YCBCR420;
881 break;
882 default:
883 dev_err(ippdrv->dev, "inavlid target format 0x%x.\n",
884 fmt);
885 return -EINVAL;
886 }
887
888 fimc_write(cfg, EXYNOS_CITRGFMT);
889 }
890
891 cfg = fimc_read(EXYNOS_CIDMAPARAM);
892 cfg &= ~EXYNOS_CIDMAPARAM_W_MODE_MASK;
893
894 if (fmt == DRM_FORMAT_NV12MT)
895 cfg |= EXYNOS_CIDMAPARAM_W_MODE_64X32;
896 else
897 cfg |= EXYNOS_CIDMAPARAM_W_MODE_LINEAR;
898
899 fimc_write(cfg, EXYNOS_CIDMAPARAM);
900
901 return fimc_dst_set_fmt_order(ctx, fmt);
902 }
903
904 static int fimc_dst_set_transf(struct device *dev,
905 enum drm_exynos_degree degree,
906 enum drm_exynos_flip flip, bool *swap)
907 {
908 struct fimc_context *ctx = get_fimc_context(dev);
909 struct exynos_drm_ippdrv *ippdrv = &ctx->ippdrv;
910 u32 cfg;
911
912 DRM_DEBUG_KMS("%s:degree[%d]flip[0x%x]\n", __func__,
913 degree, flip);
914
915 cfg = fimc_read(EXYNOS_CITRGFMT);
916 cfg &= ~EXYNOS_CITRGFMT_FLIP_MASK;
917 cfg &= ~EXYNOS_CITRGFMT_OUTROT90_CLOCKWISE;
918
919 switch (degree) {
920 case EXYNOS_DRM_DEGREE_0:
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_90:
927 cfg |= EXYNOS_CITRGFMT_OUTROT90_CLOCKWISE;
928 if (flip & EXYNOS_DRM_FLIP_VERTICAL)
929 cfg |= EXYNOS_CITRGFMT_FLIP_X_MIRROR;
930 if (flip & EXYNOS_DRM_FLIP_HORIZONTAL)
931 cfg |= EXYNOS_CITRGFMT_FLIP_Y_MIRROR;
932 break;
933 case EXYNOS_DRM_DEGREE_180:
934 cfg |= (EXYNOS_CITRGFMT_FLIP_X_MIRROR |
935 EXYNOS_CITRGFMT_FLIP_Y_MIRROR);
936 if (flip & EXYNOS_DRM_FLIP_VERTICAL)
937 cfg &= ~EXYNOS_CITRGFMT_FLIP_X_MIRROR;
938 if (flip & EXYNOS_DRM_FLIP_HORIZONTAL)
939 cfg &= ~EXYNOS_CITRGFMT_FLIP_Y_MIRROR;
940 break;
941 case EXYNOS_DRM_DEGREE_270:
942 cfg |= (EXYNOS_CITRGFMT_OUTROT90_CLOCKWISE |
943 EXYNOS_CITRGFMT_FLIP_X_MIRROR |
944 EXYNOS_CITRGFMT_FLIP_Y_MIRROR);
945 if (flip & EXYNOS_DRM_FLIP_VERTICAL)
946 cfg &= ~EXYNOS_CITRGFMT_FLIP_X_MIRROR;
947 if (flip & EXYNOS_DRM_FLIP_HORIZONTAL)
948 cfg &= ~EXYNOS_CITRGFMT_FLIP_Y_MIRROR;
949 break;
950 default:
951 dev_err(ippdrv->dev, "inavlid degree value %d.\n", degree);
952 return -EINVAL;
953 }
954
955 fimc_write(cfg, EXYNOS_CITRGFMT);
956 *swap = (cfg & EXYNOS_CITRGFMT_OUTROT90_CLOCKWISE) ? 1 : 0;
957
958 return 0;
959 }
960
961 static int fimc_get_ratio_shift(u32 src, u32 dst, u32 *ratio, u32 *shift)
962 {
963 DRM_DEBUG_KMS("%s:src[%d]dst[%d]\n", __func__, src, dst);
964
965 if (src >= dst * 64) {
966 DRM_ERROR("failed to make ratio and shift.\n");
967 return -EINVAL;
968 } else if (src >= dst * 32) {
969 *ratio = 32;
970 *shift = 5;
971 } else if (src >= dst * 16) {
972 *ratio = 16;
973 *shift = 4;
974 } else if (src >= dst * 8) {
975 *ratio = 8;
976 *shift = 3;
977 } else if (src >= dst * 4) {
978 *ratio = 4;
979 *shift = 2;
980 } else if (src >= dst * 2) {
981 *ratio = 2;
982 *shift = 1;
983 } else {
984 *ratio = 1;
985 *shift = 0;
986 }
987
988 return 0;
989 }
990
991 static int fimc_set_prescaler(struct fimc_context *ctx, struct fimc_scaler *sc,
992 struct drm_exynos_pos *src, struct drm_exynos_pos *dst)
993 {
994 struct exynos_drm_ippdrv *ippdrv = &ctx->ippdrv;
995 u32 cfg, cfg_ext, shfactor;
996 u32 pre_dst_width, pre_dst_height;
997 u32 pre_hratio, hfactor, pre_vratio, vfactor;
998 int ret = 0;
999 u32 src_w, src_h, dst_w, dst_h;
1000
1001 cfg_ext = fimc_read(EXYNOS_CITRGFMT);
1002 if (cfg_ext & EXYNOS_CITRGFMT_INROT90_CLOCKWISE) {
1003 src_w = src->h;
1004 src_h = src->w;
1005 } else {
1006 src_w = src->w;
1007 src_h = src->h;
1008 }
1009
1010 if (cfg_ext & EXYNOS_CITRGFMT_OUTROT90_CLOCKWISE) {
1011 dst_w = dst->h;
1012 dst_h = dst->w;
1013 } else {
1014 dst_w = dst->w;
1015 dst_h = dst->h;
1016 }
1017
1018 ret = fimc_get_ratio_shift(src_w, dst_w, &pre_hratio, &hfactor);
1019 if (ret) {
1020 dev_err(ippdrv->dev, "failed to get ratio horizontal.\n");
1021 return ret;
1022 }
1023
1024 ret = fimc_get_ratio_shift(src_h, dst_h, &pre_vratio, &vfactor);
1025 if (ret) {
1026 dev_err(ippdrv->dev, "failed to get ratio vertical.\n");
1027 return ret;
1028 }
1029
1030 pre_dst_width = src_w / pre_hratio;
1031 pre_dst_height = src_h / pre_vratio;
1032 DRM_DEBUG_KMS("%s:pre_dst_width[%d]pre_dst_height[%d]\n", __func__,
1033 pre_dst_width, pre_dst_height);
1034 DRM_DEBUG_KMS("%s:pre_hratio[%d]hfactor[%d]pre_vratio[%d]vfactor[%d]\n",
1035 __func__, pre_hratio, hfactor, pre_vratio, vfactor);
1036
1037 sc->hratio = (src_w << 14) / (dst_w << hfactor);
1038 sc->vratio = (src_h << 14) / (dst_h << vfactor);
1039 sc->up_h = (dst_w >= src_w) ? true : false;
1040 sc->up_v = (dst_h >= src_h) ? true : false;
1041 DRM_DEBUG_KMS("%s:hratio[%d]vratio[%d]up_h[%d]up_v[%d]\n",
1042 __func__, sc->hratio, sc->vratio, sc->up_h, sc->up_v);
1043
1044 shfactor = FIMC_SHFACTOR - (hfactor + vfactor);
1045 DRM_DEBUG_KMS("%s:shfactor[%d]\n", __func__, shfactor);
1046
1047 cfg = (EXYNOS_CISCPRERATIO_SHFACTOR(shfactor) |
1048 EXYNOS_CISCPRERATIO_PREHORRATIO(pre_hratio) |
1049 EXYNOS_CISCPRERATIO_PREVERRATIO(pre_vratio));
1050 fimc_write(cfg, EXYNOS_CISCPRERATIO);
1051
1052 cfg = (EXYNOS_CISCPREDST_PREDSTWIDTH(pre_dst_width) |
1053 EXYNOS_CISCPREDST_PREDSTHEIGHT(pre_dst_height));
1054 fimc_write(cfg, EXYNOS_CISCPREDST);
1055
1056 return ret;
1057 }
1058
1059 static void fimc_set_scaler(struct fimc_context *ctx, struct fimc_scaler *sc)
1060 {
1061 u32 cfg, cfg_ext;
1062
1063 DRM_DEBUG_KMS("%s:range[%d]bypass[%d]up_h[%d]up_v[%d]\n",
1064 __func__, sc->range, sc->bypass, sc->up_h, sc->up_v);
1065 DRM_DEBUG_KMS("%s:hratio[%d]vratio[%d]\n",
1066 __func__, sc->hratio, sc->vratio);
1067
1068 cfg = fimc_read(EXYNOS_CISCCTRL);
1069 cfg &= ~(EXYNOS_CISCCTRL_SCALERBYPASS |
1070 EXYNOS_CISCCTRL_SCALEUP_H | EXYNOS_CISCCTRL_SCALEUP_V |
1071 EXYNOS_CISCCTRL_MAIN_V_RATIO_MASK |
1072 EXYNOS_CISCCTRL_MAIN_H_RATIO_MASK |
1073 EXYNOS_CISCCTRL_CSCR2Y_WIDE |
1074 EXYNOS_CISCCTRL_CSCY2R_WIDE);
1075
1076 if (sc->range)
1077 cfg |= (EXYNOS_CISCCTRL_CSCR2Y_WIDE |
1078 EXYNOS_CISCCTRL_CSCY2R_WIDE);
1079 if (sc->bypass)
1080 cfg |= EXYNOS_CISCCTRL_SCALERBYPASS;
1081 if (sc->up_h)
1082 cfg |= EXYNOS_CISCCTRL_SCALEUP_H;
1083 if (sc->up_v)
1084 cfg |= EXYNOS_CISCCTRL_SCALEUP_V;
1085
1086 cfg |= (EXYNOS_CISCCTRL_MAINHORRATIO((sc->hratio >> 6)) |
1087 EXYNOS_CISCCTRL_MAINVERRATIO((sc->vratio >> 6)));
1088 fimc_write(cfg, EXYNOS_CISCCTRL);
1089
1090 cfg_ext = fimc_read(EXYNOS_CIEXTEN);
1091 cfg_ext &= ~EXYNOS_CIEXTEN_MAINHORRATIO_EXT_MASK;
1092 cfg_ext &= ~EXYNOS_CIEXTEN_MAINVERRATIO_EXT_MASK;
1093 cfg_ext |= (EXYNOS_CIEXTEN_MAINHORRATIO_EXT(sc->hratio) |
1094 EXYNOS_CIEXTEN_MAINVERRATIO_EXT(sc->vratio));
1095 fimc_write(cfg_ext, EXYNOS_CIEXTEN);
1096 }
1097
1098 static int fimc_dst_set_size(struct device *dev, int swap,
1099 struct drm_exynos_pos *pos, struct drm_exynos_sz *sz)
1100 {
1101 struct fimc_context *ctx = get_fimc_context(dev);
1102 struct drm_exynos_pos img_pos = *pos;
1103 struct drm_exynos_sz img_sz = *sz;
1104 u32 cfg;
1105
1106 DRM_DEBUG_KMS("%s:swap[%d]hsize[%d]vsize[%d]\n",
1107 __func__, swap, sz->hsize, sz->vsize);
1108
1109 /* original size */
1110 cfg = (EXYNOS_ORGOSIZE_HORIZONTAL(img_sz.hsize) |
1111 EXYNOS_ORGOSIZE_VERTICAL(img_sz.vsize));
1112
1113 fimc_write(cfg, EXYNOS_ORGOSIZE);
1114
1115 DRM_DEBUG_KMS("%s:x[%d]y[%d]w[%d]h[%d]\n",
1116 __func__, pos->x, pos->y, pos->w, pos->h);
1117
1118 /* CSC ITU */
1119 cfg = fimc_read(EXYNOS_CIGCTRL);
1120 cfg &= ~EXYNOS_CIGCTRL_CSC_MASK;
1121
1122 if (sz->hsize >= FIMC_WIDTH_ITU_709)
1123 cfg |= EXYNOS_CIGCTRL_CSC_ITU709;
1124 else
1125 cfg |= EXYNOS_CIGCTRL_CSC_ITU601;
1126
1127 fimc_write(cfg, EXYNOS_CIGCTRL);
1128
1129 if (swap) {
1130 img_pos.w = pos->h;
1131 img_pos.h = pos->w;
1132 img_sz.hsize = sz->vsize;
1133 img_sz.vsize = sz->hsize;
1134 }
1135
1136 /* target image size */
1137 cfg = fimc_read(EXYNOS_CITRGFMT);
1138 cfg &= ~(EXYNOS_CITRGFMT_TARGETH_MASK |
1139 EXYNOS_CITRGFMT_TARGETV_MASK);
1140 cfg |= (EXYNOS_CITRGFMT_TARGETHSIZE(img_pos.w) |
1141 EXYNOS_CITRGFMT_TARGETVSIZE(img_pos.h));
1142 fimc_write(cfg, EXYNOS_CITRGFMT);
1143
1144 /* target area */
1145 cfg = EXYNOS_CITAREA_TARGET_AREA(img_pos.w * img_pos.h);
1146 fimc_write(cfg, EXYNOS_CITAREA);
1147
1148 /* offset Y(RGB), Cb, Cr */
1149 cfg = (EXYNOS_CIOYOFF_HORIZONTAL(img_pos.x) |
1150 EXYNOS_CIOYOFF_VERTICAL(img_pos.y));
1151 fimc_write(cfg, EXYNOS_CIOYOFF);
1152 cfg = (EXYNOS_CIOCBOFF_HORIZONTAL(img_pos.x) |
1153 EXYNOS_CIOCBOFF_VERTICAL(img_pos.y));
1154 fimc_write(cfg, EXYNOS_CIOCBOFF);
1155 cfg = (EXYNOS_CIOCROFF_HORIZONTAL(img_pos.x) |
1156 EXYNOS_CIOCROFF_VERTICAL(img_pos.y));
1157 fimc_write(cfg, EXYNOS_CIOCROFF);
1158
1159 return 0;
1160 }
1161
1162 static int fimc_dst_get_buf_seq(struct fimc_context *ctx)
1163 {
1164 u32 cfg, i, buf_num = 0;
1165 u32 mask = 0x00000001;
1166
1167 cfg = fimc_read(EXYNOS_CIFCNTSEQ);
1168
1169 for (i = 0; i < FIMC_REG_SZ; i++)
1170 if (cfg & (mask << i))
1171 buf_num++;
1172
1173 DRM_DEBUG_KMS("%s:buf_num[%d]\n", __func__, buf_num);
1174
1175 return buf_num;
1176 }
1177
1178 static int fimc_dst_set_buf_seq(struct fimc_context *ctx, u32 buf_id,
1179 enum drm_exynos_ipp_buf_type buf_type)
1180 {
1181 struct exynos_drm_ippdrv *ippdrv = &ctx->ippdrv;
1182 bool enable;
1183 u32 cfg;
1184 u32 mask = 0x00000001 << buf_id;
1185 int ret = 0;
1186
1187 DRM_DEBUG_KMS("%s:buf_id[%d]buf_type[%d]\n", __func__,
1188 buf_id, buf_type);
1189
1190 mutex_lock(&ctx->lock);
1191
1192 /* mask register set */
1193 cfg = fimc_read(EXYNOS_CIFCNTSEQ);
1194
1195 switch (buf_type) {
1196 case IPP_BUF_ENQUEUE:
1197 enable = true;
1198 break;
1199 case IPP_BUF_DEQUEUE:
1200 enable = false;
1201 break;
1202 default:
1203 dev_err(ippdrv->dev, "invalid buf ctrl parameter.\n");
1204 ret = -EINVAL;
1205 goto err_unlock;
1206 }
1207
1208 /* sequence id */
1209 cfg &= (~mask);
1210 cfg |= (enable << buf_id);
1211 fimc_write(cfg, EXYNOS_CIFCNTSEQ);
1212
1213 /* interrupt enable */
1214 if (buf_type == IPP_BUF_ENQUEUE &&
1215 fimc_dst_get_buf_seq(ctx) >= FIMC_BUF_START)
1216 fimc_handle_irq(ctx, true, false, true);
1217
1218 /* interrupt disable */
1219 if (buf_type == IPP_BUF_DEQUEUE &&
1220 fimc_dst_get_buf_seq(ctx) <= FIMC_BUF_STOP)
1221 fimc_handle_irq(ctx, false, false, true);
1222
1223 err_unlock:
1224 mutex_unlock(&ctx->lock);
1225 return ret;
1226 }
1227
1228 static int fimc_dst_set_addr(struct device *dev,
1229 struct drm_exynos_ipp_buf_info *buf_info, u32 buf_id,
1230 enum drm_exynos_ipp_buf_type buf_type)
1231 {
1232 struct fimc_context *ctx = get_fimc_context(dev);
1233 struct exynos_drm_ippdrv *ippdrv = &ctx->ippdrv;
1234 struct drm_exynos_ipp_cmd_node *c_node = ippdrv->cmd;
1235 struct drm_exynos_ipp_property *property;
1236 struct drm_exynos_ipp_config *config;
1237
1238 if (!c_node) {
1239 DRM_ERROR("failed to get c_node.\n");
1240 return -EINVAL;
1241 }
1242
1243 property = &c_node->property;
1244 if (!property) {
1245 DRM_ERROR("failed to get property.\n");
1246 return -EINVAL;
1247 }
1248
1249 DRM_DEBUG_KMS("%s:prop_id[%d]buf_id[%d]buf_type[%d]\n", __func__,
1250 property->prop_id, buf_id, buf_type);
1251
1252 if (buf_id > FIMC_MAX_DST) {
1253 dev_info(ippdrv->dev, "inavlid buf_id %d.\n", buf_id);
1254 return -ENOMEM;
1255 }
1256
1257 /* address register set */
1258 switch (buf_type) {
1259 case IPP_BUF_ENQUEUE:
1260 config = &property->config[EXYNOS_DRM_OPS_DST];
1261
1262 fimc_write(buf_info->base[EXYNOS_DRM_PLANAR_Y],
1263 EXYNOS_CIOYSA(buf_id));
1264
1265 if (config->fmt == DRM_FORMAT_YVU420) {
1266 fimc_write(buf_info->base[EXYNOS_DRM_PLANAR_CR],
1267 EXYNOS_CIOCBSA(buf_id));
1268 fimc_write(buf_info->base[EXYNOS_DRM_PLANAR_CB],
1269 EXYNOS_CIOCRSA(buf_id));
1270 } else {
1271 fimc_write(buf_info->base[EXYNOS_DRM_PLANAR_CB],
1272 EXYNOS_CIOCBSA(buf_id));
1273 fimc_write(buf_info->base[EXYNOS_DRM_PLANAR_CR],
1274 EXYNOS_CIOCRSA(buf_id));
1275 }
1276 break;
1277 case IPP_BUF_DEQUEUE:
1278 fimc_write(0x0, EXYNOS_CIOYSA(buf_id));
1279 fimc_write(0x0, EXYNOS_CIOCBSA(buf_id));
1280 fimc_write(0x0, EXYNOS_CIOCRSA(buf_id));
1281 break;
1282 default:
1283 /* bypass */
1284 break;
1285 }
1286
1287 return fimc_dst_set_buf_seq(ctx, buf_id, buf_type);
1288 }
1289
1290 static struct exynos_drm_ipp_ops fimc_dst_ops = {
1291 .set_fmt = fimc_dst_set_fmt,
1292 .set_transf = fimc_dst_set_transf,
1293 .set_size = fimc_dst_set_size,
1294 .set_addr = fimc_dst_set_addr,
1295 };
1296
1297 static int fimc_clk_ctrl(struct fimc_context *ctx, bool enable)
1298 {
1299 DRM_DEBUG_KMS("%s:enable[%d]\n", __func__, enable);
1300
1301 if (enable) {
1302 clk_enable(ctx->sclk_fimc_clk);
1303 clk_enable(ctx->fimc_clk);
1304 clk_enable(ctx->wb_clk);
1305 ctx->suspended = false;
1306 } else {
1307 clk_disable(ctx->sclk_fimc_clk);
1308 clk_disable(ctx->fimc_clk);
1309 clk_disable(ctx->wb_clk);
1310 ctx->suspended = true;
1311 }
1312
1313 return 0;
1314 }
1315
1316 static irqreturn_t fimc_irq_handler(int irq, void *dev_id)
1317 {
1318 struct fimc_context *ctx = dev_id;
1319 struct exynos_drm_ippdrv *ippdrv = &ctx->ippdrv;
1320 struct drm_exynos_ipp_cmd_node *c_node = ippdrv->cmd;
1321 struct drm_exynos_ipp_event_work *event_work =
1322 c_node->event_work;
1323 int buf_id;
1324
1325 DRM_DEBUG_KMS("%s:fimc id[%d]\n", __func__, ctx->id);
1326
1327 fimc_clear_irq(ctx);
1328 if (fimc_check_ovf(ctx))
1329 return IRQ_NONE;
1330
1331 if (!fimc_check_frame_end(ctx))
1332 return IRQ_NONE;
1333
1334 buf_id = fimc_get_buf_id(ctx);
1335 if (buf_id < 0)
1336 return IRQ_HANDLED;
1337
1338 DRM_DEBUG_KMS("%s:buf_id[%d]\n", __func__, buf_id);
1339
1340 if (fimc_dst_set_buf_seq(ctx, buf_id, IPP_BUF_DEQUEUE) < 0) {
1341 DRM_ERROR("failed to dequeue.\n");
1342 return IRQ_HANDLED;
1343 }
1344
1345 event_work->ippdrv = ippdrv;
1346 event_work->buf_id[EXYNOS_DRM_OPS_DST] = buf_id;
1347 queue_work(ippdrv->event_workq, (struct work_struct *)event_work);
1348
1349 return IRQ_HANDLED;
1350 }
1351
1352 static int fimc_init_prop_list(struct exynos_drm_ippdrv *ippdrv)
1353 {
1354 struct drm_exynos_ipp_prop_list *prop_list;
1355
1356 DRM_DEBUG_KMS("%s\n", __func__);
1357
1358 prop_list = devm_kzalloc(ippdrv->dev, sizeof(*prop_list), GFP_KERNEL);
1359 if (!prop_list) {
1360 DRM_ERROR("failed to alloc property list.\n");
1361 return -ENOMEM;
1362 }
1363
1364 prop_list->version = 1;
1365 prop_list->writeback = 1;
1366 prop_list->refresh_min = FIMC_REFRESH_MIN;
1367 prop_list->refresh_max = FIMC_REFRESH_MAX;
1368 prop_list->flip = (1 << EXYNOS_DRM_FLIP_NONE) |
1369 (1 << EXYNOS_DRM_FLIP_VERTICAL) |
1370 (1 << EXYNOS_DRM_FLIP_HORIZONTAL);
1371 prop_list->degree = (1 << EXYNOS_DRM_DEGREE_0) |
1372 (1 << EXYNOS_DRM_DEGREE_90) |
1373 (1 << EXYNOS_DRM_DEGREE_180) |
1374 (1 << EXYNOS_DRM_DEGREE_270);
1375 prop_list->csc = 1;
1376 prop_list->crop = 1;
1377 prop_list->crop_max.hsize = FIMC_CROP_MAX;
1378 prop_list->crop_max.vsize = FIMC_CROP_MAX;
1379 prop_list->crop_min.hsize = FIMC_CROP_MIN;
1380 prop_list->crop_min.vsize = FIMC_CROP_MIN;
1381 prop_list->scale = 1;
1382 prop_list->scale_max.hsize = FIMC_SCALE_MAX;
1383 prop_list->scale_max.vsize = FIMC_SCALE_MAX;
1384 prop_list->scale_min.hsize = FIMC_SCALE_MIN;
1385 prop_list->scale_min.vsize = FIMC_SCALE_MIN;
1386
1387 ippdrv->prop_list = prop_list;
1388
1389 return 0;
1390 }
1391
1392 static inline bool fimc_check_drm_flip(enum drm_exynos_flip flip)
1393 {
1394 switch (flip) {
1395 case EXYNOS_DRM_FLIP_NONE:
1396 case EXYNOS_DRM_FLIP_VERTICAL:
1397 case EXYNOS_DRM_FLIP_HORIZONTAL:
1398 return true;
1399 default:
1400 DRM_DEBUG_KMS("%s:invalid flip\n", __func__);
1401 return false;
1402 }
1403 }
1404
1405 static int fimc_ippdrv_check_property(struct device *dev,
1406 struct drm_exynos_ipp_property *property)
1407 {
1408 struct fimc_context *ctx = get_fimc_context(dev);
1409 struct exynos_drm_ippdrv *ippdrv = &ctx->ippdrv;
1410 struct drm_exynos_ipp_prop_list *pp = ippdrv->prop_list;
1411 struct drm_exynos_ipp_config *config;
1412 struct drm_exynos_pos *pos;
1413 struct drm_exynos_sz *sz;
1414 bool swap;
1415 int i;
1416
1417 DRM_DEBUG_KMS("%s\n", __func__);
1418
1419 for_each_ipp_ops(i) {
1420 if ((i == EXYNOS_DRM_OPS_SRC) &&
1421 (property->cmd == IPP_CMD_WB))
1422 continue;
1423
1424 config = &property->config[i];
1425 pos = &config->pos;
1426 sz = &config->sz;
1427
1428 /* check for flip */
1429 if (!fimc_check_drm_flip(config->flip)) {
1430 DRM_ERROR("invalid flip.\n");
1431 goto err_property;
1432 }
1433
1434 /* check for degree */
1435 switch (config->degree) {
1436 case EXYNOS_DRM_DEGREE_90:
1437 case EXYNOS_DRM_DEGREE_270:
1438 swap = true;
1439 break;
1440 case EXYNOS_DRM_DEGREE_0:
1441 case EXYNOS_DRM_DEGREE_180:
1442 swap = false;
1443 break;
1444 default:
1445 DRM_ERROR("invalid degree.\n");
1446 goto err_property;
1447 }
1448
1449 /* check for buffer bound */
1450 if ((pos->x + pos->w > sz->hsize) ||
1451 (pos->y + pos->h > sz->vsize)) {
1452 DRM_ERROR("out of buf bound.\n");
1453 goto err_property;
1454 }
1455
1456 /* check for crop */
1457 if ((i == EXYNOS_DRM_OPS_SRC) && (pp->crop)) {
1458 if (swap) {
1459 if ((pos->h < pp->crop_min.hsize) ||
1460 (sz->vsize > pp->crop_max.hsize) ||
1461 (pos->w < pp->crop_min.vsize) ||
1462 (sz->hsize > pp->crop_max.vsize)) {
1463 DRM_ERROR("out of crop size.\n");
1464 goto err_property;
1465 }
1466 } else {
1467 if ((pos->w < pp->crop_min.hsize) ||
1468 (sz->hsize > pp->crop_max.hsize) ||
1469 (pos->h < pp->crop_min.vsize) ||
1470 (sz->vsize > pp->crop_max.vsize)) {
1471 DRM_ERROR("out of crop size.\n");
1472 goto err_property;
1473 }
1474 }
1475 }
1476
1477 /* check for scale */
1478 if ((i == EXYNOS_DRM_OPS_DST) && (pp->scale)) {
1479 if (swap) {
1480 if ((pos->h < pp->scale_min.hsize) ||
1481 (sz->vsize > pp->scale_max.hsize) ||
1482 (pos->w < pp->scale_min.vsize) ||
1483 (sz->hsize > pp->scale_max.vsize)) {
1484 DRM_ERROR("out of scale size.\n");
1485 goto err_property;
1486 }
1487 } else {
1488 if ((pos->w < pp->scale_min.hsize) ||
1489 (sz->hsize > pp->scale_max.hsize) ||
1490 (pos->h < pp->scale_min.vsize) ||
1491 (sz->vsize > pp->scale_max.vsize)) {
1492 DRM_ERROR("out of scale size.\n");
1493 goto err_property;
1494 }
1495 }
1496 }
1497 }
1498
1499 return 0;
1500
1501 err_property:
1502 for_each_ipp_ops(i) {
1503 if ((i == EXYNOS_DRM_OPS_SRC) &&
1504 (property->cmd == IPP_CMD_WB))
1505 continue;
1506
1507 config = &property->config[i];
1508 pos = &config->pos;
1509 sz = &config->sz;
1510
1511 DRM_ERROR("[%s]f[%d]r[%d]pos[%d %d %d %d]sz[%d %d]\n",
1512 i ? "dst" : "src", config->flip, config->degree,
1513 pos->x, pos->y, pos->w, pos->h,
1514 sz->hsize, sz->vsize);
1515 }
1516
1517 return -EINVAL;
1518 }
1519
1520 static void fimc_clear_addr(struct fimc_context *ctx)
1521 {
1522 int i;
1523
1524 DRM_DEBUG_KMS("%s:\n", __func__);
1525
1526 for (i = 0; i < FIMC_MAX_SRC; i++) {
1527 fimc_write(0, EXYNOS_CIIYSA(i));
1528 fimc_write(0, EXYNOS_CIICBSA(i));
1529 fimc_write(0, EXYNOS_CIICRSA(i));
1530 }
1531
1532 for (i = 0; i < FIMC_MAX_DST; i++) {
1533 fimc_write(0, EXYNOS_CIOYSA(i));
1534 fimc_write(0, EXYNOS_CIOCBSA(i));
1535 fimc_write(0, EXYNOS_CIOCRSA(i));
1536 }
1537 }
1538
1539 static int fimc_ippdrv_reset(struct device *dev)
1540 {
1541 struct fimc_context *ctx = get_fimc_context(dev);
1542
1543 DRM_DEBUG_KMS("%s\n", __func__);
1544
1545 /* reset h/w block */
1546 fimc_sw_reset(ctx, false);
1547
1548 /* reset scaler capability */
1549 memset(&ctx->sc, 0x0, sizeof(ctx->sc));
1550
1551 fimc_clear_addr(ctx);
1552
1553 return 0;
1554 }
1555
1556 static int fimc_ippdrv_start(struct device *dev, enum drm_exynos_ipp_cmd cmd)
1557 {
1558 struct fimc_context *ctx = get_fimc_context(dev);
1559 struct exynos_drm_ippdrv *ippdrv = &ctx->ippdrv;
1560 struct drm_exynos_ipp_cmd_node *c_node = ippdrv->cmd;
1561 struct drm_exynos_ipp_property *property;
1562 struct drm_exynos_ipp_config *config;
1563 struct drm_exynos_pos img_pos[EXYNOS_DRM_OPS_MAX];
1564 struct drm_exynos_ipp_set_wb set_wb;
1565 int ret, i;
1566 u32 cfg0, cfg1;
1567
1568 DRM_DEBUG_KMS("%s:cmd[%d]\n", __func__, cmd);
1569
1570 if (!c_node) {
1571 DRM_ERROR("failed to get c_node.\n");
1572 return -EINVAL;
1573 }
1574
1575 property = &c_node->property;
1576 if (!property) {
1577 DRM_ERROR("failed to get property.\n");
1578 return -EINVAL;
1579 }
1580
1581 fimc_handle_irq(ctx, true, false, true);
1582
1583 for_each_ipp_ops(i) {
1584 config = &property->config[i];
1585 img_pos[i] = config->pos;
1586 }
1587
1588 ret = fimc_set_prescaler(ctx, &ctx->sc,
1589 &img_pos[EXYNOS_DRM_OPS_SRC],
1590 &img_pos[EXYNOS_DRM_OPS_DST]);
1591 if (ret) {
1592 dev_err(dev, "failed to set precalser.\n");
1593 return ret;
1594 }
1595
1596 /* If set ture, we can save jpeg about screen */
1597 fimc_handle_jpeg(ctx, false);
1598 fimc_set_scaler(ctx, &ctx->sc);
1599 fimc_set_polarity(ctx, &ctx->pol);
1600
1601 switch (cmd) {
1602 case IPP_CMD_M2M:
1603 fimc_set_type_ctrl(ctx, FIMC_WB_NONE);
1604 fimc_handle_lastend(ctx, false);
1605
1606 /* setup dma */
1607 cfg0 = fimc_read(EXYNOS_MSCTRL);
1608 cfg0 &= ~EXYNOS_MSCTRL_INPUT_MASK;
1609 cfg0 |= EXYNOS_MSCTRL_INPUT_MEMORY;
1610 fimc_write(cfg0, EXYNOS_MSCTRL);
1611 break;
1612 case IPP_CMD_WB:
1613 fimc_set_type_ctrl(ctx, FIMC_WB_A);
1614 fimc_handle_lastend(ctx, true);
1615
1616 /* setup FIMD */
1617 fimc_set_camblk_fimd0_wb(ctx);
1618
1619 set_wb.enable = 1;
1620 set_wb.refresh = property->refresh_rate;
1621 exynos_drm_ippnb_send_event(IPP_SET_WRITEBACK, (void *)&set_wb);
1622 break;
1623 case IPP_CMD_OUTPUT:
1624 default:
1625 ret = -EINVAL;
1626 dev_err(dev, "invalid operations.\n");
1627 return ret;
1628 }
1629
1630 /* Reset status */
1631 fimc_write(0x0, EXYNOS_CISTATUS);
1632
1633 cfg0 = fimc_read(EXYNOS_CIIMGCPT);
1634 cfg0 &= ~EXYNOS_CIIMGCPT_IMGCPTEN_SC;
1635 cfg0 |= EXYNOS_CIIMGCPT_IMGCPTEN_SC;
1636
1637 /* Scaler */
1638 cfg1 = fimc_read(EXYNOS_CISCCTRL);
1639 cfg1 &= ~EXYNOS_CISCCTRL_SCAN_MASK;
1640 cfg1 |= (EXYNOS_CISCCTRL_PROGRESSIVE |
1641 EXYNOS_CISCCTRL_SCALERSTART);
1642
1643 fimc_write(cfg1, EXYNOS_CISCCTRL);
1644
1645 /* Enable image capture*/
1646 cfg0 |= EXYNOS_CIIMGCPT_IMGCPTEN;
1647 fimc_write(cfg0, EXYNOS_CIIMGCPT);
1648
1649 /* Disable frame end irq */
1650 cfg0 = fimc_read(EXYNOS_CIGCTRL);
1651 cfg0 &= ~EXYNOS_CIGCTRL_IRQ_END_DISABLE;
1652 fimc_write(cfg0, EXYNOS_CIGCTRL);
1653
1654 cfg0 = fimc_read(EXYNOS_CIOCTRL);
1655 cfg0 &= ~EXYNOS_CIOCTRL_WEAVE_MASK;
1656 fimc_write(cfg0, EXYNOS_CIOCTRL);
1657
1658 if (cmd == IPP_CMD_M2M) {
1659 cfg0 = fimc_read(EXYNOS_MSCTRL);
1660 cfg0 |= EXYNOS_MSCTRL_ENVID;
1661 fimc_write(cfg0, EXYNOS_MSCTRL);
1662
1663 cfg0 = fimc_read(EXYNOS_MSCTRL);
1664 cfg0 |= EXYNOS_MSCTRL_ENVID;
1665 fimc_write(cfg0, EXYNOS_MSCTRL);
1666 }
1667
1668 return 0;
1669 }
1670
1671 static void fimc_ippdrv_stop(struct device *dev, enum drm_exynos_ipp_cmd cmd)
1672 {
1673 struct fimc_context *ctx = get_fimc_context(dev);
1674 struct drm_exynos_ipp_set_wb set_wb = {0, 0};
1675 u32 cfg;
1676
1677 DRM_DEBUG_KMS("%s:cmd[%d]\n", __func__, cmd);
1678
1679 switch (cmd) {
1680 case IPP_CMD_M2M:
1681 /* Source clear */
1682 cfg = fimc_read(EXYNOS_MSCTRL);
1683 cfg &= ~EXYNOS_MSCTRL_INPUT_MASK;
1684 cfg &= ~EXYNOS_MSCTRL_ENVID;
1685 fimc_write(cfg, EXYNOS_MSCTRL);
1686 break;
1687 case IPP_CMD_WB:
1688 exynos_drm_ippnb_send_event(IPP_SET_WRITEBACK, (void *)&set_wb);
1689 break;
1690 case IPP_CMD_OUTPUT:
1691 default:
1692 dev_err(dev, "invalid operations.\n");
1693 break;
1694 }
1695
1696 fimc_handle_irq(ctx, false, false, true);
1697
1698 /* reset sequence */
1699 fimc_write(0x0, EXYNOS_CIFCNTSEQ);
1700
1701 /* Scaler disable */
1702 cfg = fimc_read(EXYNOS_CISCCTRL);
1703 cfg &= ~EXYNOS_CISCCTRL_SCALERSTART;
1704 fimc_write(cfg, EXYNOS_CISCCTRL);
1705
1706 /* Disable image capture */
1707 cfg = fimc_read(EXYNOS_CIIMGCPT);
1708 cfg &= ~(EXYNOS_CIIMGCPT_IMGCPTEN_SC | EXYNOS_CIIMGCPT_IMGCPTEN);
1709 fimc_write(cfg, EXYNOS_CIIMGCPT);
1710
1711 /* Enable frame end irq */
1712 cfg = fimc_read(EXYNOS_CIGCTRL);
1713 cfg |= EXYNOS_CIGCTRL_IRQ_END_DISABLE;
1714 fimc_write(cfg, EXYNOS_CIGCTRL);
1715 }
1716
1717 static int __devinit fimc_probe(struct platform_device *pdev)
1718 {
1719 struct device *dev = &pdev->dev;
1720 struct fimc_context *ctx;
1721 struct clk *parent_clk;
1722 struct resource *res;
1723 struct exynos_drm_ippdrv *ippdrv;
1724 struct exynos_drm_fimc_pdata *pdata;
1725 struct fimc_driverdata *ddata;
1726 int ret;
1727
1728 pdata = pdev->dev.platform_data;
1729 if (!pdata) {
1730 dev_err(dev, "no platform data specified.\n");
1731 return -EINVAL;
1732 }
1733
1734 ctx = devm_kzalloc(dev, sizeof(*ctx), GFP_KERNEL);
1735 if (!ctx)
1736 return -ENOMEM;
1737
1738 ddata = (struct fimc_driverdata *)
1739 platform_get_device_id(pdev)->driver_data;
1740
1741 /* clock control */
1742 ctx->sclk_fimc_clk = clk_get(dev, "sclk_fimc");
1743 if (IS_ERR(ctx->sclk_fimc_clk)) {
1744 dev_err(dev, "failed to get src fimc clock.\n");
1745 ret = PTR_ERR(ctx->sclk_fimc_clk);
1746 goto err_ctx;
1747 }
1748 clk_enable(ctx->sclk_fimc_clk);
1749
1750 ctx->fimc_clk = clk_get(dev, "fimc");
1751 if (IS_ERR(ctx->fimc_clk)) {
1752 dev_err(dev, "failed to get fimc clock.\n");
1753 ret = PTR_ERR(ctx->fimc_clk);
1754 clk_disable(ctx->sclk_fimc_clk);
1755 clk_put(ctx->sclk_fimc_clk);
1756 goto err_ctx;
1757 }
1758
1759 ctx->wb_clk = clk_get(dev, "pxl_async0");
1760 if (IS_ERR(ctx->wb_clk)) {
1761 dev_err(dev, "failed to get writeback a clock.\n");
1762 ret = PTR_ERR(ctx->wb_clk);
1763 clk_disable(ctx->sclk_fimc_clk);
1764 clk_put(ctx->sclk_fimc_clk);
1765 clk_put(ctx->fimc_clk);
1766 goto err_ctx;
1767 }
1768
1769 ctx->wb_b_clk = clk_get(dev, "pxl_async1");
1770 if (IS_ERR(ctx->wb_b_clk)) {
1771 dev_err(dev, "failed to get writeback b clock.\n");
1772 ret = PTR_ERR(ctx->wb_b_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 goto err_ctx;
1778 }
1779
1780 parent_clk = clk_get(dev, ddata->parent_clk);
1781
1782 if (IS_ERR(parent_clk)) {
1783 dev_err(dev, "failed to get parent clock.\n");
1784 ret = PTR_ERR(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 if (clk_set_parent(ctx->sclk_fimc_clk, parent_clk)) {
1794 dev_err(dev, "failed to set parent.\n");
1795 ret = -EINVAL;
1796 clk_put(parent_clk);
1797 clk_disable(ctx->sclk_fimc_clk);
1798 clk_put(ctx->sclk_fimc_clk);
1799 clk_put(ctx->fimc_clk);
1800 clk_put(ctx->wb_clk);
1801 clk_put(ctx->wb_b_clk);
1802 goto err_ctx;
1803 }
1804
1805 clk_put(parent_clk);
1806 clk_set_rate(ctx->sclk_fimc_clk, pdata->clk_rate);
1807
1808 /* resource memory */
1809 ctx->regs_res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
1810 if (!ctx->regs_res) {
1811 dev_err(dev, "failed to find registers.\n");
1812 ret = -ENOENT;
1813 goto err_clk;
1814 }
1815
1816 ctx->regs = devm_request_and_ioremap(dev, ctx->regs_res);
1817 if (!ctx->regs) {
1818 dev_err(dev, "failed to map registers.\n");
1819 ret = -ENXIO;
1820 goto err_clk;
1821 }
1822
1823 /* resource irq */
1824 res = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
1825 if (!res) {
1826 dev_err(dev, "failed to request irq resource.\n");
1827 ret = -ENOENT;
1828 goto err_get_regs;
1829 }
1830
1831 ctx->irq = res->start;
1832 ret = request_threaded_irq(ctx->irq, NULL, fimc_irq_handler,
1833 IRQF_ONESHOT, "drm_fimc", ctx);
1834 if (ret < 0) {
1835 dev_err(dev, "failed to request irq.\n");
1836 goto err_get_regs;
1837 }
1838
1839 /* context initailization */
1840 ctx->id = pdev->id;
1841 ctx->pol = pdata->pol;
1842 ctx->ddata = ddata;
1843
1844 ippdrv = &ctx->ippdrv;
1845 ippdrv->dev = dev;
1846 ippdrv->ops[EXYNOS_DRM_OPS_SRC] = &fimc_src_ops;
1847 ippdrv->ops[EXYNOS_DRM_OPS_DST] = &fimc_dst_ops;
1848 ippdrv->check_property = fimc_ippdrv_check_property;
1849 ippdrv->reset = fimc_ippdrv_reset;
1850 ippdrv->start = fimc_ippdrv_start;
1851 ippdrv->stop = fimc_ippdrv_stop;
1852 ret = fimc_init_prop_list(ippdrv);
1853 if (ret < 0) {
1854 dev_err(dev, "failed to init property list.\n");
1855 goto err_get_irq;
1856 }
1857
1858 DRM_DEBUG_KMS("%s:id[%d]ippdrv[0x%x]\n", __func__, ctx->id,
1859 (int)ippdrv);
1860
1861 mutex_init(&ctx->lock);
1862 platform_set_drvdata(pdev, ctx);
1863
1864 pm_runtime_set_active(dev);
1865 pm_runtime_enable(dev);
1866
1867 ret = exynos_drm_ippdrv_register(ippdrv);
1868 if (ret < 0) {
1869 dev_err(dev, "failed to register drm fimc device.\n");
1870 goto err_ippdrv_register;
1871 }
1872
1873 dev_info(&pdev->dev, "drm fimc registered successfully.\n");
1874
1875 return 0;
1876
1877 err_ippdrv_register:
1878 devm_kfree(dev, ippdrv->prop_list);
1879 pm_runtime_disable(dev);
1880 err_get_irq:
1881 free_irq(ctx->irq, ctx);
1882 err_get_regs:
1883 devm_iounmap(dev, ctx->regs);
1884 err_clk:
1885 clk_put(ctx->sclk_fimc_clk);
1886 clk_put(ctx->fimc_clk);
1887 clk_put(ctx->wb_clk);
1888 clk_put(ctx->wb_b_clk);
1889 err_ctx:
1890 devm_kfree(dev, ctx);
1891 return ret;
1892 }
1893
1894 static int __devexit fimc_remove(struct platform_device *pdev)
1895 {
1896 struct device *dev = &pdev->dev;
1897 struct fimc_context *ctx = get_fimc_context(dev);
1898 struct exynos_drm_ippdrv *ippdrv = &ctx->ippdrv;
1899
1900 devm_kfree(dev, ippdrv->prop_list);
1901 exynos_drm_ippdrv_unregister(ippdrv);
1902 mutex_destroy(&ctx->lock);
1903
1904 pm_runtime_set_suspended(dev);
1905 pm_runtime_disable(dev);
1906
1907 free_irq(ctx->irq, ctx);
1908 devm_iounmap(dev, ctx->regs);
1909
1910 clk_put(ctx->sclk_fimc_clk);
1911 clk_put(ctx->fimc_clk);
1912 clk_put(ctx->wb_clk);
1913 clk_put(ctx->wb_b_clk);
1914
1915 devm_kfree(dev, ctx);
1916
1917 return 0;
1918 }
1919
1920 #ifdef CONFIG_PM_SLEEP
1921 static int fimc_suspend(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 0;
1929
1930 return fimc_clk_ctrl(ctx, false);
1931 }
1932
1933 static int fimc_resume(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 if (!pm_runtime_suspended(dev))
1940 return fimc_clk_ctrl(ctx, true);
1941
1942 return 0;
1943 }
1944 #endif
1945
1946 #ifdef CONFIG_PM_RUNTIME
1947 static int fimc_runtime_suspend(struct device *dev)
1948 {
1949 struct fimc_context *ctx = get_fimc_context(dev);
1950
1951 DRM_DEBUG_KMS("%s:id[%d]\n", __func__, ctx->id);
1952
1953 return fimc_clk_ctrl(ctx, false);
1954 }
1955
1956 static int fimc_runtime_resume(struct device *dev)
1957 {
1958 struct fimc_context *ctx = get_fimc_context(dev);
1959
1960 DRM_DEBUG_KMS("%s:id[%d]\n", __func__, ctx->id);
1961
1962 return fimc_clk_ctrl(ctx, true);
1963 }
1964 #endif
1965
1966 static struct fimc_driverdata exynos4210_fimc_data = {
1967 .parent_clk = "mout_mpll",
1968 };
1969
1970 static struct fimc_driverdata exynos4410_fimc_data = {
1971 .parent_clk = "mout_mpll_user",
1972 };
1973
1974 static struct platform_device_id fimc_driver_ids[] = {
1975 {
1976 .name = "exynos4210-fimc",
1977 .driver_data = (unsigned long)&exynos4210_fimc_data,
1978 }, {
1979 .name = "exynos4412-fimc",
1980 .driver_data = (unsigned long)&exynos4410_fimc_data,
1981 },
1982 {},
1983 };
1984 MODULE_DEVICE_TABLE(platform, fimc_driver_ids);
1985
1986 static const struct dev_pm_ops fimc_pm_ops = {
1987 SET_SYSTEM_SLEEP_PM_OPS(fimc_suspend, fimc_resume)
1988 SET_RUNTIME_PM_OPS(fimc_runtime_suspend, fimc_runtime_resume, NULL)
1989 };
1990
1991 struct platform_driver fimc_driver = {
1992 .probe = fimc_probe,
1993 .remove = __devexit_p(fimc_remove),
1994 .id_table = fimc_driver_ids,
1995 .driver = {
1996 .name = "exynos-drm-fimc",
1997 .owner = THIS_MODULE,
1998 .pm = &fimc_pm_ops,
1999 },
2000 };
2001
This page took 0.133401 seconds and 4 git commands to generate.