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