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