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