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