1 // SPDX-License-Identifier: GPL-2.0-or-later 2 /* 3 * Copyright (C) 2012 Samsung Electronics Co.Ltd 4 * Authors: 5 * Eunchul Kim <chulspro.kim@samsung.com> 6 * Jinyoung Jeon <jy0.jeon@samsung.com> 7 * Sangmin Lee <lsmin.lee@samsung.com> 8 */ 9 10 #include <linux/clk.h> 11 #include <linux/component.h> 12 #include <linux/kernel.h> 13 #include <linux/mfd/syscon.h> 14 #include <linux/of.h> 15 #include <linux/platform_device.h> 16 #include <linux/pm_runtime.h> 17 #include <linux/regmap.h> 18 #include <linux/spinlock.h> 19 20 #include <drm/exynos_drm.h> 21 22 #include "exynos_drm_drv.h" 23 #include "exynos_drm_ipp.h" 24 #include "regs-fimc.h" 25 26 /* 27 * FIMC stands for Fully Interactive Mobile Camera and 28 * supports image scaler/rotator and input/output DMA operations. 29 * input DMA reads image data from the memory. 30 * output DMA writes image data to memory. 31 * FIMC supports image rotation and image effect functions. 32 */ 33 34 #define FIMC_MAX_DEVS 4 35 #define FIMC_MAX_SRC 2 36 #define FIMC_MAX_DST 32 37 #define FIMC_SHFACTOR 10 38 #define FIMC_BUF_STOP 1 39 #define FIMC_BUF_START 2 40 #define FIMC_WIDTH_ITU_709 1280 41 #define FIMC_AUTOSUSPEND_DELAY 2000 42 43 static unsigned int fimc_mask = 0xc; 44 module_param_named(fimc_devs, fimc_mask, uint, 0644); 45 MODULE_PARM_DESC(fimc_devs, "Alias mask for assigning FIMC devices to Exynos DRM"); 46 47 #define get_fimc_context(dev) platform_get_drvdata(to_platform_device(dev)) 48 49 enum { 50 FIMC_CLK_LCLK, 51 FIMC_CLK_GATE, 52 FIMC_CLK_WB_A, 53 FIMC_CLK_WB_B, 54 FIMC_CLKS_MAX 55 }; 56 57 static const char * const fimc_clock_names[] = { 58 [FIMC_CLK_LCLK] = "sclk_fimc", 59 [FIMC_CLK_GATE] = "fimc", 60 [FIMC_CLK_WB_A] = "pxl_async0", 61 [FIMC_CLK_WB_B] = "pxl_async1", 62 }; 63 64 /* 65 * A structure of scaler. 66 * 67 * @range: narrow, wide. 68 * @bypass: unused scaler path. 69 * @up_h: horizontal scale up. 70 * @up_v: vertical scale up. 71 * @hratio: horizontal ratio. 72 * @vratio: vertical ratio. 73 */ 74 struct fimc_scaler { 75 bool range; 76 bool bypass; 77 bool up_h; 78 bool up_v; 79 u32 hratio; 80 u32 vratio; 81 }; 82 83 /* 84 * A structure of fimc context. 85 * 86 * @regs_res: register resources. 87 * @regs: memory mapped io registers. 88 * @lock: locking of operations. 89 * @clocks: fimc clocks. 90 * @sc: scaler infomations. 91 * @pol: porarity of writeback. 92 * @id: fimc id. 93 * @irq: irq number. 94 */ 95 struct fimc_context { 96 struct exynos_drm_ipp ipp; 97 struct drm_device *drm_dev; 98 struct device *dev; 99 struct exynos_drm_ipp_task *task; 100 struct exynos_drm_ipp_formats *formats; 101 unsigned int num_formats; 102 103 struct resource *regs_res; 104 void __iomem *regs; 105 spinlock_t lock; 106 struct clk *clocks[FIMC_CLKS_MAX]; 107 struct fimc_scaler sc; 108 int id; 109 int irq; 110 }; 111 112 static u32 fimc_read(struct fimc_context *ctx, u32 reg) 113 { 114 return readl(ctx->regs + reg); 115 } 116 117 static void fimc_write(struct fimc_context *ctx, u32 val, u32 reg) 118 { 119 writel(val, ctx->regs + reg); 120 } 121 122 static void fimc_set_bits(struct fimc_context *ctx, u32 reg, u32 bits) 123 { 124 void __iomem *r = ctx->regs + reg; 125 126 writel(readl(r) | bits, r); 127 } 128 129 static void fimc_clear_bits(struct fimc_context *ctx, u32 reg, u32 bits) 130 { 131 void __iomem *r = ctx->regs + reg; 132 133 writel(readl(r) & ~bits, r); 134 } 135 136 static void fimc_sw_reset(struct fimc_context *ctx) 137 { 138 u32 cfg; 139 140 /* stop dma operation */ 141 cfg = fimc_read(ctx, EXYNOS_CISTATUS); 142 if (EXYNOS_CISTATUS_GET_ENVID_STATUS(cfg)) 143 fimc_clear_bits(ctx, EXYNOS_MSCTRL, EXYNOS_MSCTRL_ENVID); 144 145 fimc_set_bits(ctx, EXYNOS_CISRCFMT, EXYNOS_CISRCFMT_ITU601_8BIT); 146 147 /* disable image capture */ 148 fimc_clear_bits(ctx, EXYNOS_CIIMGCPT, 149 EXYNOS_CIIMGCPT_IMGCPTEN_SC | EXYNOS_CIIMGCPT_IMGCPTEN); 150 151 /* s/w reset */ 152 fimc_set_bits(ctx, EXYNOS_CIGCTRL, EXYNOS_CIGCTRL_SWRST); 153 154 /* s/w reset complete */ 155 fimc_clear_bits(ctx, EXYNOS_CIGCTRL, EXYNOS_CIGCTRL_SWRST); 156 157 /* reset sequence */ 158 fimc_write(ctx, 0x0, EXYNOS_CIFCNTSEQ); 159 } 160 161 static void fimc_set_type_ctrl(struct fimc_context *ctx) 162 { 163 u32 cfg; 164 165 cfg = fimc_read(ctx, EXYNOS_CIGCTRL); 166 cfg &= ~(EXYNOS_CIGCTRL_TESTPATTERN_MASK | 167 EXYNOS_CIGCTRL_SELCAM_ITU_MASK | 168 EXYNOS_CIGCTRL_SELCAM_MIPI_MASK | 169 EXYNOS_CIGCTRL_SELCAM_FIMC_MASK | 170 EXYNOS_CIGCTRL_SELWB_CAMIF_MASK | 171 EXYNOS_CIGCTRL_SELWRITEBACK_MASK); 172 173 cfg |= (EXYNOS_CIGCTRL_SELCAM_ITU_A | 174 EXYNOS_CIGCTRL_SELWRITEBACK_A | 175 EXYNOS_CIGCTRL_SELCAM_MIPI_A | 176 EXYNOS_CIGCTRL_SELCAM_FIMC_ITU); 177 178 fimc_write(ctx, cfg, EXYNOS_CIGCTRL); 179 } 180 181 static void fimc_handle_jpeg(struct fimc_context *ctx, bool enable) 182 { 183 u32 cfg; 184 185 DRM_DEV_DEBUG_KMS(ctx->dev, "enable[%d]\n", enable); 186 187 cfg = fimc_read(ctx, EXYNOS_CIGCTRL); 188 if (enable) 189 cfg |= EXYNOS_CIGCTRL_CAM_JPEG; 190 else 191 cfg &= ~EXYNOS_CIGCTRL_CAM_JPEG; 192 193 fimc_write(ctx, cfg, EXYNOS_CIGCTRL); 194 } 195 196 static void fimc_mask_irq(struct fimc_context *ctx, bool enable) 197 { 198 u32 cfg; 199 200 DRM_DEV_DEBUG_KMS(ctx->dev, "enable[%d]\n", enable); 201 202 cfg = fimc_read(ctx, EXYNOS_CIGCTRL); 203 if (enable) { 204 cfg &= ~EXYNOS_CIGCTRL_IRQ_OVFEN; 205 cfg |= EXYNOS_CIGCTRL_IRQ_ENABLE | EXYNOS_CIGCTRL_IRQ_LEVEL; 206 } else 207 cfg &= ~EXYNOS_CIGCTRL_IRQ_ENABLE; 208 fimc_write(ctx, cfg, EXYNOS_CIGCTRL); 209 } 210 211 static void fimc_clear_irq(struct fimc_context *ctx) 212 { 213 fimc_set_bits(ctx, EXYNOS_CIGCTRL, EXYNOS_CIGCTRL_IRQ_CLR); 214 } 215 216 static bool fimc_check_ovf(struct fimc_context *ctx) 217 { 218 u32 status, flag; 219 220 status = fimc_read(ctx, EXYNOS_CISTATUS); 221 flag = EXYNOS_CISTATUS_OVFIY | EXYNOS_CISTATUS_OVFICB | 222 EXYNOS_CISTATUS_OVFICR; 223 224 DRM_DEV_DEBUG_KMS(ctx->dev, "flag[0x%x]\n", flag); 225 226 if (status & flag) { 227 fimc_set_bits(ctx, EXYNOS_CIWDOFST, 228 EXYNOS_CIWDOFST_CLROVFIY | EXYNOS_CIWDOFST_CLROVFICB | 229 EXYNOS_CIWDOFST_CLROVFICR); 230 231 DRM_DEV_ERROR(ctx->dev, 232 "occurred overflow at %d, status 0x%x.\n", 233 ctx->id, status); 234 return true; 235 } 236 237 return false; 238 } 239 240 static bool fimc_check_frame_end(struct fimc_context *ctx) 241 { 242 u32 cfg; 243 244 cfg = fimc_read(ctx, EXYNOS_CISTATUS); 245 246 DRM_DEV_DEBUG_KMS(ctx->dev, "cfg[0x%x]\n", cfg); 247 248 if (!(cfg & EXYNOS_CISTATUS_FRAMEEND)) 249 return false; 250 251 cfg &= ~(EXYNOS_CISTATUS_FRAMEEND); 252 fimc_write(ctx, cfg, EXYNOS_CISTATUS); 253 254 return true; 255 } 256 257 static int fimc_get_buf_id(struct fimc_context *ctx) 258 { 259 u32 cfg; 260 int frame_cnt, buf_id; 261 262 cfg = fimc_read(ctx, EXYNOS_CISTATUS2); 263 frame_cnt = EXYNOS_CISTATUS2_GET_FRAMECOUNT_BEFORE(cfg); 264 265 if (frame_cnt == 0) 266 frame_cnt = EXYNOS_CISTATUS2_GET_FRAMECOUNT_PRESENT(cfg); 267 268 DRM_DEV_DEBUG_KMS(ctx->dev, "present[%d]before[%d]\n", 269 EXYNOS_CISTATUS2_GET_FRAMECOUNT_PRESENT(cfg), 270 EXYNOS_CISTATUS2_GET_FRAMECOUNT_BEFORE(cfg)); 271 272 if (frame_cnt == 0) { 273 DRM_DEV_ERROR(ctx->dev, "failed to get frame count.\n"); 274 return -EIO; 275 } 276 277 buf_id = frame_cnt - 1; 278 DRM_DEV_DEBUG_KMS(ctx->dev, "buf_id[%d]\n", buf_id); 279 280 return buf_id; 281 } 282 283 static void fimc_handle_lastend(struct fimc_context *ctx, bool enable) 284 { 285 u32 cfg; 286 287 DRM_DEV_DEBUG_KMS(ctx->dev, "enable[%d]\n", enable); 288 289 cfg = fimc_read(ctx, EXYNOS_CIOCTRL); 290 if (enable) 291 cfg |= EXYNOS_CIOCTRL_LASTENDEN; 292 else 293 cfg &= ~EXYNOS_CIOCTRL_LASTENDEN; 294 295 fimc_write(ctx, cfg, EXYNOS_CIOCTRL); 296 } 297 298 static void fimc_src_set_fmt_order(struct fimc_context *ctx, u32 fmt) 299 { 300 u32 cfg; 301 302 DRM_DEV_DEBUG_KMS(ctx->dev, "fmt[0x%x]\n", fmt); 303 304 /* RGB */ 305 cfg = fimc_read(ctx, EXYNOS_CISCCTRL); 306 cfg &= ~EXYNOS_CISCCTRL_INRGB_FMT_RGB_MASK; 307 308 switch (fmt) { 309 case DRM_FORMAT_RGB565: 310 cfg |= EXYNOS_CISCCTRL_INRGB_FMT_RGB565; 311 fimc_write(ctx, cfg, EXYNOS_CISCCTRL); 312 return; 313 case DRM_FORMAT_RGB888: 314 case DRM_FORMAT_XRGB8888: 315 cfg |= EXYNOS_CISCCTRL_INRGB_FMT_RGB888; 316 fimc_write(ctx, cfg, EXYNOS_CISCCTRL); 317 return; 318 default: 319 /* bypass */ 320 break; 321 } 322 323 /* YUV */ 324 cfg = fimc_read(ctx, EXYNOS_MSCTRL); 325 cfg &= ~(EXYNOS_MSCTRL_ORDER2P_SHIFT_MASK | 326 EXYNOS_MSCTRL_C_INT_IN_2PLANE | 327 EXYNOS_MSCTRL_ORDER422_YCBYCR); 328 329 switch (fmt) { 330 case DRM_FORMAT_YUYV: 331 cfg |= EXYNOS_MSCTRL_ORDER422_YCBYCR; 332 break; 333 case DRM_FORMAT_YVYU: 334 cfg |= EXYNOS_MSCTRL_ORDER422_YCRYCB; 335 break; 336 case DRM_FORMAT_UYVY: 337 cfg |= EXYNOS_MSCTRL_ORDER422_CBYCRY; 338 break; 339 case DRM_FORMAT_VYUY: 340 case DRM_FORMAT_YUV444: 341 cfg |= EXYNOS_MSCTRL_ORDER422_CRYCBY; 342 break; 343 case DRM_FORMAT_NV21: 344 case DRM_FORMAT_NV61: 345 cfg |= (EXYNOS_MSCTRL_ORDER2P_LSB_CRCB | 346 EXYNOS_MSCTRL_C_INT_IN_2PLANE); 347 break; 348 case DRM_FORMAT_YUV422: 349 case DRM_FORMAT_YUV420: 350 case DRM_FORMAT_YVU420: 351 cfg |= EXYNOS_MSCTRL_C_INT_IN_3PLANE; 352 break; 353 case DRM_FORMAT_NV12: 354 case DRM_FORMAT_NV16: 355 cfg |= (EXYNOS_MSCTRL_ORDER2P_LSB_CBCR | 356 EXYNOS_MSCTRL_C_INT_IN_2PLANE); 357 break; 358 } 359 360 fimc_write(ctx, cfg, EXYNOS_MSCTRL); 361 } 362 363 static void fimc_src_set_fmt(struct fimc_context *ctx, u32 fmt, bool tiled) 364 { 365 u32 cfg; 366 367 DRM_DEV_DEBUG_KMS(ctx->dev, "fmt[0x%x]\n", fmt); 368 369 cfg = fimc_read(ctx, EXYNOS_MSCTRL); 370 cfg &= ~EXYNOS_MSCTRL_INFORMAT_RGB; 371 372 switch (fmt) { 373 case DRM_FORMAT_RGB565: 374 case DRM_FORMAT_RGB888: 375 case DRM_FORMAT_XRGB8888: 376 cfg |= EXYNOS_MSCTRL_INFORMAT_RGB; 377 break; 378 case DRM_FORMAT_YUV444: 379 cfg |= EXYNOS_MSCTRL_INFORMAT_YCBCR420; 380 break; 381 case DRM_FORMAT_YUYV: 382 case DRM_FORMAT_YVYU: 383 case DRM_FORMAT_UYVY: 384 case DRM_FORMAT_VYUY: 385 cfg |= EXYNOS_MSCTRL_INFORMAT_YCBCR422_1PLANE; 386 break; 387 case DRM_FORMAT_NV16: 388 case DRM_FORMAT_NV61: 389 case DRM_FORMAT_YUV422: 390 cfg |= EXYNOS_MSCTRL_INFORMAT_YCBCR422; 391 break; 392 case DRM_FORMAT_YUV420: 393 case DRM_FORMAT_YVU420: 394 case DRM_FORMAT_NV12: 395 case DRM_FORMAT_NV21: 396 cfg |= EXYNOS_MSCTRL_INFORMAT_YCBCR420; 397 break; 398 } 399 400 fimc_write(ctx, cfg, EXYNOS_MSCTRL); 401 402 cfg = fimc_read(ctx, EXYNOS_CIDMAPARAM); 403 cfg &= ~EXYNOS_CIDMAPARAM_R_MODE_MASK; 404 405 if (tiled) 406 cfg |= EXYNOS_CIDMAPARAM_R_MODE_64X32; 407 else 408 cfg |= EXYNOS_CIDMAPARAM_R_MODE_LINEAR; 409 410 fimc_write(ctx, cfg, EXYNOS_CIDMAPARAM); 411 412 fimc_src_set_fmt_order(ctx, fmt); 413 } 414 415 static void fimc_src_set_transf(struct fimc_context *ctx, unsigned int rotation) 416 { 417 unsigned int degree = rotation & DRM_MODE_ROTATE_MASK; 418 u32 cfg1, cfg2; 419 420 DRM_DEV_DEBUG_KMS(ctx->dev, "rotation[%x]\n", rotation); 421 422 cfg1 = fimc_read(ctx, EXYNOS_MSCTRL); 423 cfg1 &= ~(EXYNOS_MSCTRL_FLIP_X_MIRROR | 424 EXYNOS_MSCTRL_FLIP_Y_MIRROR); 425 426 cfg2 = fimc_read(ctx, EXYNOS_CITRGFMT); 427 cfg2 &= ~EXYNOS_CITRGFMT_INROT90_CLOCKWISE; 428 429 switch (degree) { 430 case DRM_MODE_ROTATE_0: 431 if (rotation & DRM_MODE_REFLECT_X) 432 cfg1 |= EXYNOS_MSCTRL_FLIP_X_MIRROR; 433 if (rotation & DRM_MODE_REFLECT_Y) 434 cfg1 |= EXYNOS_MSCTRL_FLIP_Y_MIRROR; 435 break; 436 case DRM_MODE_ROTATE_90: 437 cfg2 |= EXYNOS_CITRGFMT_INROT90_CLOCKWISE; 438 if (rotation & DRM_MODE_REFLECT_X) 439 cfg1 |= EXYNOS_MSCTRL_FLIP_X_MIRROR; 440 if (rotation & DRM_MODE_REFLECT_Y) 441 cfg1 |= EXYNOS_MSCTRL_FLIP_Y_MIRROR; 442 break; 443 case DRM_MODE_ROTATE_180: 444 cfg1 |= (EXYNOS_MSCTRL_FLIP_X_MIRROR | 445 EXYNOS_MSCTRL_FLIP_Y_MIRROR); 446 if (rotation & DRM_MODE_REFLECT_X) 447 cfg1 &= ~EXYNOS_MSCTRL_FLIP_X_MIRROR; 448 if (rotation & DRM_MODE_REFLECT_Y) 449 cfg1 &= ~EXYNOS_MSCTRL_FLIP_Y_MIRROR; 450 break; 451 case DRM_MODE_ROTATE_270: 452 cfg1 |= (EXYNOS_MSCTRL_FLIP_X_MIRROR | 453 EXYNOS_MSCTRL_FLIP_Y_MIRROR); 454 cfg2 |= EXYNOS_CITRGFMT_INROT90_CLOCKWISE; 455 if (rotation & DRM_MODE_REFLECT_X) 456 cfg1 &= ~EXYNOS_MSCTRL_FLIP_X_MIRROR; 457 if (rotation & DRM_MODE_REFLECT_Y) 458 cfg1 &= ~EXYNOS_MSCTRL_FLIP_Y_MIRROR; 459 break; 460 } 461 462 fimc_write(ctx, cfg1, EXYNOS_MSCTRL); 463 fimc_write(ctx, cfg2, EXYNOS_CITRGFMT); 464 } 465 466 static void fimc_set_window(struct fimc_context *ctx, 467 struct exynos_drm_ipp_buffer *buf) 468 { 469 unsigned int real_width = buf->buf.pitch[0] / buf->format->cpp[0]; 470 u32 cfg, h1, h2, v1, v2; 471 472 /* cropped image */ 473 h1 = buf->rect.x; 474 h2 = real_width - buf->rect.w - buf->rect.x; 475 v1 = buf->rect.y; 476 v2 = buf->buf.height - buf->rect.h - buf->rect.y; 477 478 DRM_DEV_DEBUG_KMS(ctx->dev, "x[%d]y[%d]w[%d]h[%d]hsize[%d]vsize[%d]\n", 479 buf->rect.x, buf->rect.y, buf->rect.w, buf->rect.h, 480 real_width, buf->buf.height); 481 DRM_DEV_DEBUG_KMS(ctx->dev, "h1[%d]h2[%d]v1[%d]v2[%d]\n", h1, h2, v1, 482 v2); 483 484 /* 485 * set window offset 1, 2 size 486 * check figure 43-21 in user manual 487 */ 488 cfg = fimc_read(ctx, EXYNOS_CIWDOFST); 489 cfg &= ~(EXYNOS_CIWDOFST_WINHOROFST_MASK | 490 EXYNOS_CIWDOFST_WINVEROFST_MASK); 491 cfg |= (EXYNOS_CIWDOFST_WINHOROFST(h1) | 492 EXYNOS_CIWDOFST_WINVEROFST(v1)); 493 cfg |= EXYNOS_CIWDOFST_WINOFSEN; 494 fimc_write(ctx, cfg, EXYNOS_CIWDOFST); 495 496 cfg = (EXYNOS_CIWDOFST2_WINHOROFST2(h2) | 497 EXYNOS_CIWDOFST2_WINVEROFST2(v2)); 498 fimc_write(ctx, cfg, EXYNOS_CIWDOFST2); 499 } 500 501 static void fimc_src_set_size(struct fimc_context *ctx, 502 struct exynos_drm_ipp_buffer *buf) 503 { 504 unsigned int real_width = buf->buf.pitch[0] / buf->format->cpp[0]; 505 u32 cfg; 506 507 DRM_DEV_DEBUG_KMS(ctx->dev, "hsize[%d]vsize[%d]\n", real_width, 508 buf->buf.height); 509 510 /* original size */ 511 cfg = (EXYNOS_ORGISIZE_HORIZONTAL(real_width) | 512 EXYNOS_ORGISIZE_VERTICAL(buf->buf.height)); 513 514 fimc_write(ctx, cfg, EXYNOS_ORGISIZE); 515 516 DRM_DEV_DEBUG_KMS(ctx->dev, "x[%d]y[%d]w[%d]h[%d]\n", buf->rect.x, 517 buf->rect.y, buf->rect.w, buf->rect.h); 518 519 /* set input DMA image size */ 520 cfg = fimc_read(ctx, EXYNOS_CIREAL_ISIZE); 521 cfg &= ~(EXYNOS_CIREAL_ISIZE_HEIGHT_MASK | 522 EXYNOS_CIREAL_ISIZE_WIDTH_MASK); 523 cfg |= (EXYNOS_CIREAL_ISIZE_WIDTH(buf->rect.w) | 524 EXYNOS_CIREAL_ISIZE_HEIGHT(buf->rect.h)); 525 fimc_write(ctx, cfg, EXYNOS_CIREAL_ISIZE); 526 527 /* 528 * set input FIFO image size 529 * for now, we support only ITU601 8 bit mode 530 */ 531 cfg = (EXYNOS_CISRCFMT_ITU601_8BIT | 532 EXYNOS_CISRCFMT_SOURCEHSIZE(real_width) | 533 EXYNOS_CISRCFMT_SOURCEVSIZE(buf->buf.height)); 534 fimc_write(ctx, cfg, EXYNOS_CISRCFMT); 535 536 /* offset Y(RGB), Cb, Cr */ 537 cfg = (EXYNOS_CIIYOFF_HORIZONTAL(buf->rect.x) | 538 EXYNOS_CIIYOFF_VERTICAL(buf->rect.y)); 539 fimc_write(ctx, cfg, EXYNOS_CIIYOFF); 540 cfg = (EXYNOS_CIICBOFF_HORIZONTAL(buf->rect.x) | 541 EXYNOS_CIICBOFF_VERTICAL(buf->rect.y)); 542 fimc_write(ctx, cfg, EXYNOS_CIICBOFF); 543 cfg = (EXYNOS_CIICROFF_HORIZONTAL(buf->rect.x) | 544 EXYNOS_CIICROFF_VERTICAL(buf->rect.y)); 545 fimc_write(ctx, cfg, EXYNOS_CIICROFF); 546 547 fimc_set_window(ctx, buf); 548 } 549 550 static void fimc_src_set_addr(struct fimc_context *ctx, 551 struct exynos_drm_ipp_buffer *buf) 552 { 553 fimc_write(ctx, buf->dma_addr[0], EXYNOS_CIIYSA(0)); 554 fimc_write(ctx, buf->dma_addr[1], EXYNOS_CIICBSA(0)); 555 fimc_write(ctx, buf->dma_addr[2], EXYNOS_CIICRSA(0)); 556 } 557 558 static void fimc_dst_set_fmt_order(struct fimc_context *ctx, u32 fmt) 559 { 560 u32 cfg; 561 562 DRM_DEV_DEBUG_KMS(ctx->dev, "fmt[0x%x]\n", fmt); 563 564 /* RGB */ 565 cfg = fimc_read(ctx, EXYNOS_CISCCTRL); 566 cfg &= ~EXYNOS_CISCCTRL_OUTRGB_FMT_RGB_MASK; 567 568 switch (fmt) { 569 case DRM_FORMAT_RGB565: 570 cfg |= EXYNOS_CISCCTRL_OUTRGB_FMT_RGB565; 571 fimc_write(ctx, cfg, EXYNOS_CISCCTRL); 572 return; 573 case DRM_FORMAT_RGB888: 574 cfg |= EXYNOS_CISCCTRL_OUTRGB_FMT_RGB888; 575 fimc_write(ctx, cfg, EXYNOS_CISCCTRL); 576 return; 577 case DRM_FORMAT_XRGB8888: 578 cfg |= (EXYNOS_CISCCTRL_OUTRGB_FMT_RGB888 | 579 EXYNOS_CISCCTRL_EXTRGB_EXTENSION); 580 fimc_write(ctx, cfg, EXYNOS_CISCCTRL); 581 break; 582 default: 583 /* bypass */ 584 break; 585 } 586 587 /* YUV */ 588 cfg = fimc_read(ctx, EXYNOS_CIOCTRL); 589 cfg &= ~(EXYNOS_CIOCTRL_ORDER2P_MASK | 590 EXYNOS_CIOCTRL_ORDER422_MASK | 591 EXYNOS_CIOCTRL_YCBCR_PLANE_MASK); 592 593 switch (fmt) { 594 case DRM_FORMAT_XRGB8888: 595 cfg |= EXYNOS_CIOCTRL_ALPHA_OUT; 596 break; 597 case DRM_FORMAT_YUYV: 598 cfg |= EXYNOS_CIOCTRL_ORDER422_YCBYCR; 599 break; 600 case DRM_FORMAT_YVYU: 601 cfg |= EXYNOS_CIOCTRL_ORDER422_YCRYCB; 602 break; 603 case DRM_FORMAT_UYVY: 604 cfg |= EXYNOS_CIOCTRL_ORDER422_CBYCRY; 605 break; 606 case DRM_FORMAT_VYUY: 607 cfg |= EXYNOS_CIOCTRL_ORDER422_CRYCBY; 608 break; 609 case DRM_FORMAT_NV21: 610 case DRM_FORMAT_NV61: 611 cfg |= EXYNOS_CIOCTRL_ORDER2P_LSB_CRCB; 612 cfg |= EXYNOS_CIOCTRL_YCBCR_2PLANE; 613 break; 614 case DRM_FORMAT_YUV422: 615 case DRM_FORMAT_YUV420: 616 case DRM_FORMAT_YVU420: 617 cfg |= EXYNOS_CIOCTRL_YCBCR_3PLANE; 618 break; 619 case DRM_FORMAT_NV12: 620 case DRM_FORMAT_NV16: 621 cfg |= EXYNOS_CIOCTRL_ORDER2P_LSB_CBCR; 622 cfg |= EXYNOS_CIOCTRL_YCBCR_2PLANE; 623 break; 624 } 625 626 fimc_write(ctx, cfg, EXYNOS_CIOCTRL); 627 } 628 629 static void fimc_dst_set_fmt(struct fimc_context *ctx, u32 fmt, bool tiled) 630 { 631 u32 cfg; 632 633 DRM_DEV_DEBUG_KMS(ctx->dev, "fmt[0x%x]\n", fmt); 634 635 cfg = fimc_read(ctx, EXYNOS_CIEXTEN); 636 637 if (fmt == DRM_FORMAT_AYUV) { 638 cfg |= EXYNOS_CIEXTEN_YUV444_OUT; 639 fimc_write(ctx, cfg, EXYNOS_CIEXTEN); 640 } else { 641 cfg &= ~EXYNOS_CIEXTEN_YUV444_OUT; 642 fimc_write(ctx, cfg, EXYNOS_CIEXTEN); 643 644 cfg = fimc_read(ctx, EXYNOS_CITRGFMT); 645 cfg &= ~EXYNOS_CITRGFMT_OUTFORMAT_MASK; 646 647 switch (fmt) { 648 case DRM_FORMAT_RGB565: 649 case DRM_FORMAT_RGB888: 650 case DRM_FORMAT_XRGB8888: 651 cfg |= EXYNOS_CITRGFMT_OUTFORMAT_RGB; 652 break; 653 case DRM_FORMAT_YUYV: 654 case DRM_FORMAT_YVYU: 655 case DRM_FORMAT_UYVY: 656 case DRM_FORMAT_VYUY: 657 cfg |= EXYNOS_CITRGFMT_OUTFORMAT_YCBCR422_1PLANE; 658 break; 659 case DRM_FORMAT_NV16: 660 case DRM_FORMAT_NV61: 661 case DRM_FORMAT_YUV422: 662 cfg |= EXYNOS_CITRGFMT_OUTFORMAT_YCBCR422; 663 break; 664 case DRM_FORMAT_YUV420: 665 case DRM_FORMAT_YVU420: 666 case DRM_FORMAT_NV12: 667 case DRM_FORMAT_NV21: 668 cfg |= EXYNOS_CITRGFMT_OUTFORMAT_YCBCR420; 669 break; 670 } 671 672 fimc_write(ctx, cfg, EXYNOS_CITRGFMT); 673 } 674 675 cfg = fimc_read(ctx, EXYNOS_CIDMAPARAM); 676 cfg &= ~EXYNOS_CIDMAPARAM_W_MODE_MASK; 677 678 if (tiled) 679 cfg |= EXYNOS_CIDMAPARAM_W_MODE_64X32; 680 else 681 cfg |= EXYNOS_CIDMAPARAM_W_MODE_LINEAR; 682 683 fimc_write(ctx, cfg, EXYNOS_CIDMAPARAM); 684 685 fimc_dst_set_fmt_order(ctx, fmt); 686 } 687 688 static void fimc_dst_set_transf(struct fimc_context *ctx, unsigned int rotation) 689 { 690 unsigned int degree = rotation & DRM_MODE_ROTATE_MASK; 691 u32 cfg; 692 693 DRM_DEV_DEBUG_KMS(ctx->dev, "rotation[0x%x]\n", rotation); 694 695 cfg = fimc_read(ctx, EXYNOS_CITRGFMT); 696 cfg &= ~EXYNOS_CITRGFMT_FLIP_MASK; 697 cfg &= ~EXYNOS_CITRGFMT_OUTROT90_CLOCKWISE; 698 699 switch (degree) { 700 case DRM_MODE_ROTATE_0: 701 if (rotation & DRM_MODE_REFLECT_X) 702 cfg |= EXYNOS_CITRGFMT_FLIP_X_MIRROR; 703 if (rotation & DRM_MODE_REFLECT_Y) 704 cfg |= EXYNOS_CITRGFMT_FLIP_Y_MIRROR; 705 break; 706 case DRM_MODE_ROTATE_90: 707 cfg |= EXYNOS_CITRGFMT_OUTROT90_CLOCKWISE; 708 if (rotation & DRM_MODE_REFLECT_X) 709 cfg |= EXYNOS_CITRGFMT_FLIP_X_MIRROR; 710 if (rotation & DRM_MODE_REFLECT_Y) 711 cfg |= EXYNOS_CITRGFMT_FLIP_Y_MIRROR; 712 break; 713 case DRM_MODE_ROTATE_180: 714 cfg |= (EXYNOS_CITRGFMT_FLIP_X_MIRROR | 715 EXYNOS_CITRGFMT_FLIP_Y_MIRROR); 716 if (rotation & DRM_MODE_REFLECT_X) 717 cfg &= ~EXYNOS_CITRGFMT_FLIP_X_MIRROR; 718 if (rotation & DRM_MODE_REFLECT_Y) 719 cfg &= ~EXYNOS_CITRGFMT_FLIP_Y_MIRROR; 720 break; 721 case DRM_MODE_ROTATE_270: 722 cfg |= (EXYNOS_CITRGFMT_OUTROT90_CLOCKWISE | 723 EXYNOS_CITRGFMT_FLIP_X_MIRROR | 724 EXYNOS_CITRGFMT_FLIP_Y_MIRROR); 725 if (rotation & DRM_MODE_REFLECT_X) 726 cfg &= ~EXYNOS_CITRGFMT_FLIP_X_MIRROR; 727 if (rotation & DRM_MODE_REFLECT_Y) 728 cfg &= ~EXYNOS_CITRGFMT_FLIP_Y_MIRROR; 729 break; 730 } 731 732 fimc_write(ctx, cfg, EXYNOS_CITRGFMT); 733 } 734 735 static int fimc_set_prescaler(struct fimc_context *ctx, struct fimc_scaler *sc, 736 struct drm_exynos_ipp_task_rect *src, 737 struct drm_exynos_ipp_task_rect *dst) 738 { 739 u32 cfg, cfg_ext, shfactor; 740 u32 pre_dst_width, pre_dst_height; 741 u32 hfactor, vfactor; 742 int ret = 0; 743 u32 src_w, src_h, dst_w, dst_h; 744 745 cfg_ext = fimc_read(ctx, EXYNOS_CITRGFMT); 746 if (cfg_ext & EXYNOS_CITRGFMT_INROT90_CLOCKWISE) { 747 src_w = src->h; 748 src_h = src->w; 749 } else { 750 src_w = src->w; 751 src_h = src->h; 752 } 753 754 if (cfg_ext & EXYNOS_CITRGFMT_OUTROT90_CLOCKWISE) { 755 dst_w = dst->h; 756 dst_h = dst->w; 757 } else { 758 dst_w = dst->w; 759 dst_h = dst->h; 760 } 761 762 /* fimc_ippdrv_check_property assures that dividers are not null */ 763 hfactor = fls(src_w / dst_w / 2); 764 if (hfactor > FIMC_SHFACTOR / 2) { 765 dev_err(ctx->dev, "failed to get ratio horizontal.\n"); 766 return -EINVAL; 767 } 768 769 vfactor = fls(src_h / dst_h / 2); 770 if (vfactor > FIMC_SHFACTOR / 2) { 771 dev_err(ctx->dev, "failed to get ratio vertical.\n"); 772 return -EINVAL; 773 } 774 775 pre_dst_width = src_w >> hfactor; 776 pre_dst_height = src_h >> vfactor; 777 DRM_DEV_DEBUG_KMS(ctx->dev, "pre_dst_width[%d]pre_dst_height[%d]\n", 778 pre_dst_width, pre_dst_height); 779 DRM_DEV_DEBUG_KMS(ctx->dev, "hfactor[%d]vfactor[%d]\n", hfactor, 780 vfactor); 781 782 sc->hratio = (src_w << 14) / (dst_w << hfactor); 783 sc->vratio = (src_h << 14) / (dst_h << vfactor); 784 sc->up_h = (dst_w >= src_w) ? true : false; 785 sc->up_v = (dst_h >= src_h) ? true : false; 786 DRM_DEV_DEBUG_KMS(ctx->dev, "hratio[%d]vratio[%d]up_h[%d]up_v[%d]\n", 787 sc->hratio, sc->vratio, sc->up_h, sc->up_v); 788 789 shfactor = FIMC_SHFACTOR - (hfactor + vfactor); 790 DRM_DEV_DEBUG_KMS(ctx->dev, "shfactor[%d]\n", shfactor); 791 792 cfg = (EXYNOS_CISCPRERATIO_SHFACTOR(shfactor) | 793 EXYNOS_CISCPRERATIO_PREHORRATIO(1 << hfactor) | 794 EXYNOS_CISCPRERATIO_PREVERRATIO(1 << vfactor)); 795 fimc_write(ctx, cfg, EXYNOS_CISCPRERATIO); 796 797 cfg = (EXYNOS_CISCPREDST_PREDSTWIDTH(pre_dst_width) | 798 EXYNOS_CISCPREDST_PREDSTHEIGHT(pre_dst_height)); 799 fimc_write(ctx, cfg, EXYNOS_CISCPREDST); 800 801 return ret; 802 } 803 804 static void fimc_set_scaler(struct fimc_context *ctx, struct fimc_scaler *sc) 805 { 806 u32 cfg, cfg_ext; 807 808 DRM_DEV_DEBUG_KMS(ctx->dev, "range[%d]bypass[%d]up_h[%d]up_v[%d]\n", 809 sc->range, sc->bypass, sc->up_h, sc->up_v); 810 DRM_DEV_DEBUG_KMS(ctx->dev, "hratio[%d]vratio[%d]\n", 811 sc->hratio, sc->vratio); 812 813 cfg = fimc_read(ctx, EXYNOS_CISCCTRL); 814 cfg &= ~(EXYNOS_CISCCTRL_SCALERBYPASS | 815 EXYNOS_CISCCTRL_SCALEUP_H | EXYNOS_CISCCTRL_SCALEUP_V | 816 EXYNOS_CISCCTRL_MAIN_V_RATIO_MASK | 817 EXYNOS_CISCCTRL_MAIN_H_RATIO_MASK | 818 EXYNOS_CISCCTRL_CSCR2Y_WIDE | 819 EXYNOS_CISCCTRL_CSCY2R_WIDE); 820 821 if (sc->range) 822 cfg |= (EXYNOS_CISCCTRL_CSCR2Y_WIDE | 823 EXYNOS_CISCCTRL_CSCY2R_WIDE); 824 if (sc->bypass) 825 cfg |= EXYNOS_CISCCTRL_SCALERBYPASS; 826 if (sc->up_h) 827 cfg |= EXYNOS_CISCCTRL_SCALEUP_H; 828 if (sc->up_v) 829 cfg |= EXYNOS_CISCCTRL_SCALEUP_V; 830 831 cfg |= (EXYNOS_CISCCTRL_MAINHORRATIO((sc->hratio >> 6)) | 832 EXYNOS_CISCCTRL_MAINVERRATIO((sc->vratio >> 6))); 833 fimc_write(ctx, cfg, EXYNOS_CISCCTRL); 834 835 cfg_ext = fimc_read(ctx, EXYNOS_CIEXTEN); 836 cfg_ext &= ~EXYNOS_CIEXTEN_MAINHORRATIO_EXT_MASK; 837 cfg_ext &= ~EXYNOS_CIEXTEN_MAINVERRATIO_EXT_MASK; 838 cfg_ext |= (EXYNOS_CIEXTEN_MAINHORRATIO_EXT(sc->hratio) | 839 EXYNOS_CIEXTEN_MAINVERRATIO_EXT(sc->vratio)); 840 fimc_write(ctx, cfg_ext, EXYNOS_CIEXTEN); 841 } 842 843 static void fimc_dst_set_size(struct fimc_context *ctx, 844 struct exynos_drm_ipp_buffer *buf) 845 { 846 unsigned int real_width = buf->buf.pitch[0] / buf->format->cpp[0]; 847 u32 cfg, cfg_ext; 848 849 DRM_DEV_DEBUG_KMS(ctx->dev, "hsize[%d]vsize[%d]\n", real_width, 850 buf->buf.height); 851 852 /* original size */ 853 cfg = (EXYNOS_ORGOSIZE_HORIZONTAL(real_width) | 854 EXYNOS_ORGOSIZE_VERTICAL(buf->buf.height)); 855 856 fimc_write(ctx, cfg, EXYNOS_ORGOSIZE); 857 858 DRM_DEV_DEBUG_KMS(ctx->dev, "x[%d]y[%d]w[%d]h[%d]\n", buf->rect.x, 859 buf->rect.y, 860 buf->rect.w, buf->rect.h); 861 862 /* CSC ITU */ 863 cfg = fimc_read(ctx, EXYNOS_CIGCTRL); 864 cfg &= ~EXYNOS_CIGCTRL_CSC_MASK; 865 866 if (buf->buf.width >= FIMC_WIDTH_ITU_709) 867 cfg |= EXYNOS_CIGCTRL_CSC_ITU709; 868 else 869 cfg |= EXYNOS_CIGCTRL_CSC_ITU601; 870 871 fimc_write(ctx, cfg, EXYNOS_CIGCTRL); 872 873 cfg_ext = fimc_read(ctx, EXYNOS_CITRGFMT); 874 875 /* target image size */ 876 cfg = fimc_read(ctx, EXYNOS_CITRGFMT); 877 cfg &= ~(EXYNOS_CITRGFMT_TARGETH_MASK | 878 EXYNOS_CITRGFMT_TARGETV_MASK); 879 if (cfg_ext & EXYNOS_CITRGFMT_OUTROT90_CLOCKWISE) 880 cfg |= (EXYNOS_CITRGFMT_TARGETHSIZE(buf->rect.h) | 881 EXYNOS_CITRGFMT_TARGETVSIZE(buf->rect.w)); 882 else 883 cfg |= (EXYNOS_CITRGFMT_TARGETHSIZE(buf->rect.w) | 884 EXYNOS_CITRGFMT_TARGETVSIZE(buf->rect.h)); 885 fimc_write(ctx, cfg, EXYNOS_CITRGFMT); 886 887 /* target area */ 888 cfg = EXYNOS_CITAREA_TARGET_AREA(buf->rect.w * buf->rect.h); 889 fimc_write(ctx, cfg, EXYNOS_CITAREA); 890 891 /* offset Y(RGB), Cb, Cr */ 892 cfg = (EXYNOS_CIOYOFF_HORIZONTAL(buf->rect.x) | 893 EXYNOS_CIOYOFF_VERTICAL(buf->rect.y)); 894 fimc_write(ctx, cfg, EXYNOS_CIOYOFF); 895 cfg = (EXYNOS_CIOCBOFF_HORIZONTAL(buf->rect.x) | 896 EXYNOS_CIOCBOFF_VERTICAL(buf->rect.y)); 897 fimc_write(ctx, cfg, EXYNOS_CIOCBOFF); 898 cfg = (EXYNOS_CIOCROFF_HORIZONTAL(buf->rect.x) | 899 EXYNOS_CIOCROFF_VERTICAL(buf->rect.y)); 900 fimc_write(ctx, cfg, EXYNOS_CIOCROFF); 901 } 902 903 static void fimc_dst_set_buf_seq(struct fimc_context *ctx, u32 buf_id, 904 bool enqueue) 905 { 906 unsigned long flags; 907 u32 buf_num; 908 u32 cfg; 909 910 DRM_DEV_DEBUG_KMS(ctx->dev, "buf_id[%d]enqueu[%d]\n", buf_id, enqueue); 911 912 spin_lock_irqsave(&ctx->lock, flags); 913 914 cfg = fimc_read(ctx, EXYNOS_CIFCNTSEQ); 915 916 if (enqueue) 917 cfg |= (1 << buf_id); 918 else 919 cfg &= ~(1 << buf_id); 920 921 fimc_write(ctx, cfg, EXYNOS_CIFCNTSEQ); 922 923 buf_num = hweight32(cfg); 924 925 if (enqueue && buf_num >= FIMC_BUF_START) 926 fimc_mask_irq(ctx, true); 927 else if (!enqueue && buf_num <= FIMC_BUF_STOP) 928 fimc_mask_irq(ctx, false); 929 930 spin_unlock_irqrestore(&ctx->lock, flags); 931 } 932 933 static void fimc_dst_set_addr(struct fimc_context *ctx, 934 struct exynos_drm_ipp_buffer *buf) 935 { 936 fimc_write(ctx, buf->dma_addr[0], EXYNOS_CIOYSA(0)); 937 fimc_write(ctx, buf->dma_addr[1], EXYNOS_CIOCBSA(0)); 938 fimc_write(ctx, buf->dma_addr[2], EXYNOS_CIOCRSA(0)); 939 940 fimc_dst_set_buf_seq(ctx, 0, true); 941 } 942 943 static void fimc_stop(struct fimc_context *ctx); 944 945 static irqreturn_t fimc_irq_handler(int irq, void *dev_id) 946 { 947 struct fimc_context *ctx = dev_id; 948 int buf_id; 949 950 DRM_DEV_DEBUG_KMS(ctx->dev, "fimc id[%d]\n", ctx->id); 951 952 fimc_clear_irq(ctx); 953 if (fimc_check_ovf(ctx)) 954 return IRQ_NONE; 955 956 if (!fimc_check_frame_end(ctx)) 957 return IRQ_NONE; 958 959 buf_id = fimc_get_buf_id(ctx); 960 if (buf_id < 0) 961 return IRQ_HANDLED; 962 963 DRM_DEV_DEBUG_KMS(ctx->dev, "buf_id[%d]\n", buf_id); 964 965 if (ctx->task) { 966 struct exynos_drm_ipp_task *task = ctx->task; 967 968 ctx->task = NULL; 969 pm_runtime_mark_last_busy(ctx->dev); 970 pm_runtime_put_autosuspend(ctx->dev); 971 exynos_drm_ipp_task_done(task, 0); 972 } 973 974 fimc_dst_set_buf_seq(ctx, buf_id, false); 975 fimc_stop(ctx); 976 977 return IRQ_HANDLED; 978 } 979 980 static void fimc_clear_addr(struct fimc_context *ctx) 981 { 982 int i; 983 984 for (i = 0; i < FIMC_MAX_SRC; i++) { 985 fimc_write(ctx, 0, EXYNOS_CIIYSA(i)); 986 fimc_write(ctx, 0, EXYNOS_CIICBSA(i)); 987 fimc_write(ctx, 0, EXYNOS_CIICRSA(i)); 988 } 989 990 for (i = 0; i < FIMC_MAX_DST; i++) { 991 fimc_write(ctx, 0, EXYNOS_CIOYSA(i)); 992 fimc_write(ctx, 0, EXYNOS_CIOCBSA(i)); 993 fimc_write(ctx, 0, EXYNOS_CIOCRSA(i)); 994 } 995 } 996 997 static void fimc_reset(struct fimc_context *ctx) 998 { 999 /* reset h/w block */ 1000 fimc_sw_reset(ctx); 1001 1002 /* reset scaler capability */ 1003 memset(&ctx->sc, 0x0, sizeof(ctx->sc)); 1004 1005 fimc_clear_addr(ctx); 1006 } 1007 1008 static void fimc_start(struct fimc_context *ctx) 1009 { 1010 u32 cfg0, cfg1; 1011 1012 fimc_mask_irq(ctx, true); 1013 1014 /* If set true, we can save jpeg about screen */ 1015 fimc_handle_jpeg(ctx, false); 1016 fimc_set_scaler(ctx, &ctx->sc); 1017 1018 fimc_set_type_ctrl(ctx); 1019 fimc_handle_lastend(ctx, false); 1020 1021 /* setup dma */ 1022 cfg0 = fimc_read(ctx, EXYNOS_MSCTRL); 1023 cfg0 &= ~EXYNOS_MSCTRL_INPUT_MASK; 1024 cfg0 |= EXYNOS_MSCTRL_INPUT_MEMORY; 1025 fimc_write(ctx, cfg0, EXYNOS_MSCTRL); 1026 1027 /* Reset status */ 1028 fimc_write(ctx, 0x0, EXYNOS_CISTATUS); 1029 1030 cfg0 = fimc_read(ctx, EXYNOS_CIIMGCPT); 1031 cfg0 &= ~EXYNOS_CIIMGCPT_IMGCPTEN_SC; 1032 cfg0 |= EXYNOS_CIIMGCPT_IMGCPTEN_SC; 1033 1034 /* Scaler */ 1035 cfg1 = fimc_read(ctx, EXYNOS_CISCCTRL); 1036 cfg1 &= ~EXYNOS_CISCCTRL_SCAN_MASK; 1037 cfg1 |= (EXYNOS_CISCCTRL_PROGRESSIVE | 1038 EXYNOS_CISCCTRL_SCALERSTART); 1039 1040 fimc_write(ctx, cfg1, EXYNOS_CISCCTRL); 1041 1042 /* Enable image capture*/ 1043 cfg0 |= EXYNOS_CIIMGCPT_IMGCPTEN; 1044 fimc_write(ctx, cfg0, EXYNOS_CIIMGCPT); 1045 1046 /* Disable frame end irq */ 1047 fimc_clear_bits(ctx, EXYNOS_CIGCTRL, EXYNOS_CIGCTRL_IRQ_END_DISABLE); 1048 1049 fimc_clear_bits(ctx, EXYNOS_CIOCTRL, EXYNOS_CIOCTRL_WEAVE_MASK); 1050 1051 fimc_set_bits(ctx, EXYNOS_MSCTRL, EXYNOS_MSCTRL_ENVID); 1052 } 1053 1054 static void fimc_stop(struct fimc_context *ctx) 1055 { 1056 u32 cfg; 1057 1058 /* Source clear */ 1059 cfg = fimc_read(ctx, EXYNOS_MSCTRL); 1060 cfg &= ~EXYNOS_MSCTRL_INPUT_MASK; 1061 cfg &= ~EXYNOS_MSCTRL_ENVID; 1062 fimc_write(ctx, cfg, EXYNOS_MSCTRL); 1063 1064 fimc_mask_irq(ctx, false); 1065 1066 /* reset sequence */ 1067 fimc_write(ctx, 0x0, EXYNOS_CIFCNTSEQ); 1068 1069 /* Scaler disable */ 1070 fimc_clear_bits(ctx, EXYNOS_CISCCTRL, EXYNOS_CISCCTRL_SCALERSTART); 1071 1072 /* Disable image capture */ 1073 fimc_clear_bits(ctx, EXYNOS_CIIMGCPT, 1074 EXYNOS_CIIMGCPT_IMGCPTEN_SC | EXYNOS_CIIMGCPT_IMGCPTEN); 1075 1076 /* Enable frame end irq */ 1077 fimc_set_bits(ctx, EXYNOS_CIGCTRL, EXYNOS_CIGCTRL_IRQ_END_DISABLE); 1078 } 1079 1080 static int fimc_commit(struct exynos_drm_ipp *ipp, 1081 struct exynos_drm_ipp_task *task) 1082 { 1083 struct fimc_context *ctx = 1084 container_of(ipp, struct fimc_context, ipp); 1085 1086 pm_runtime_get_sync(ctx->dev); 1087 ctx->task = task; 1088 1089 fimc_src_set_fmt(ctx, task->src.buf.fourcc, task->src.buf.modifier); 1090 fimc_src_set_size(ctx, &task->src); 1091 fimc_src_set_transf(ctx, DRM_MODE_ROTATE_0); 1092 fimc_src_set_addr(ctx, &task->src); 1093 fimc_dst_set_fmt(ctx, task->dst.buf.fourcc, task->dst.buf.modifier); 1094 fimc_dst_set_transf(ctx, task->transform.rotation); 1095 fimc_dst_set_size(ctx, &task->dst); 1096 fimc_dst_set_addr(ctx, &task->dst); 1097 fimc_set_prescaler(ctx, &ctx->sc, &task->src.rect, &task->dst.rect); 1098 fimc_start(ctx); 1099 1100 return 0; 1101 } 1102 1103 static void fimc_abort(struct exynos_drm_ipp *ipp, 1104 struct exynos_drm_ipp_task *task) 1105 { 1106 struct fimc_context *ctx = 1107 container_of(ipp, struct fimc_context, ipp); 1108 1109 fimc_reset(ctx); 1110 1111 if (ctx->task) { 1112 struct exynos_drm_ipp_task *task = ctx->task; 1113 1114 ctx->task = NULL; 1115 pm_runtime_mark_last_busy(ctx->dev); 1116 pm_runtime_put_autosuspend(ctx->dev); 1117 exynos_drm_ipp_task_done(task, -EIO); 1118 } 1119 } 1120 1121 static struct exynos_drm_ipp_funcs ipp_funcs = { 1122 .commit = fimc_commit, 1123 .abort = fimc_abort, 1124 }; 1125 1126 static int fimc_bind(struct device *dev, struct device *master, void *data) 1127 { 1128 struct fimc_context *ctx = dev_get_drvdata(dev); 1129 struct drm_device *drm_dev = data; 1130 struct exynos_drm_ipp *ipp = &ctx->ipp; 1131 1132 ctx->drm_dev = drm_dev; 1133 ipp->drm_dev = drm_dev; 1134 exynos_drm_register_dma(drm_dev, dev); 1135 1136 exynos_drm_ipp_register(dev, ipp, &ipp_funcs, 1137 DRM_EXYNOS_IPP_CAP_CROP | DRM_EXYNOS_IPP_CAP_ROTATE | 1138 DRM_EXYNOS_IPP_CAP_SCALE | DRM_EXYNOS_IPP_CAP_CONVERT, 1139 ctx->formats, ctx->num_formats, "fimc"); 1140 1141 dev_info(dev, "The exynos fimc has been probed successfully\n"); 1142 1143 return 0; 1144 } 1145 1146 static void fimc_unbind(struct device *dev, struct device *master, 1147 void *data) 1148 { 1149 struct fimc_context *ctx = dev_get_drvdata(dev); 1150 struct drm_device *drm_dev = data; 1151 struct exynos_drm_ipp *ipp = &ctx->ipp; 1152 1153 exynos_drm_ipp_unregister(dev, ipp); 1154 exynos_drm_unregister_dma(drm_dev, dev); 1155 } 1156 1157 static const struct component_ops fimc_component_ops = { 1158 .bind = fimc_bind, 1159 .unbind = fimc_unbind, 1160 }; 1161 1162 static void fimc_put_clocks(struct fimc_context *ctx) 1163 { 1164 int i; 1165 1166 for (i = 0; i < FIMC_CLKS_MAX; i++) { 1167 if (IS_ERR(ctx->clocks[i])) 1168 continue; 1169 clk_put(ctx->clocks[i]); 1170 ctx->clocks[i] = ERR_PTR(-EINVAL); 1171 } 1172 } 1173 1174 static int fimc_setup_clocks(struct fimc_context *ctx) 1175 { 1176 struct device *fimc_dev = ctx->dev; 1177 struct device *dev; 1178 int ret, i; 1179 1180 for (i = 0; i < FIMC_CLKS_MAX; i++) 1181 ctx->clocks[i] = ERR_PTR(-EINVAL); 1182 1183 for (i = 0; i < FIMC_CLKS_MAX; i++) { 1184 if (i == FIMC_CLK_WB_A || i == FIMC_CLK_WB_B) 1185 dev = fimc_dev->parent; 1186 else 1187 dev = fimc_dev; 1188 1189 ctx->clocks[i] = clk_get(dev, fimc_clock_names[i]); 1190 if (IS_ERR(ctx->clocks[i])) { 1191 ret = PTR_ERR(ctx->clocks[i]); 1192 dev_err(fimc_dev, "failed to get clock: %s\n", 1193 fimc_clock_names[i]); 1194 goto e_clk_free; 1195 } 1196 } 1197 1198 ret = clk_prepare_enable(ctx->clocks[FIMC_CLK_LCLK]); 1199 if (!ret) 1200 return ret; 1201 e_clk_free: 1202 fimc_put_clocks(ctx); 1203 return ret; 1204 } 1205 1206 int exynos_drm_check_fimc_device(struct device *dev) 1207 { 1208 int id = of_alias_get_id(dev->of_node, "fimc"); 1209 1210 if (id >= 0 && (BIT(id) & fimc_mask)) 1211 return 0; 1212 return -ENODEV; 1213 } 1214 1215 static const unsigned int fimc_formats[] = { 1216 DRM_FORMAT_XRGB8888, DRM_FORMAT_RGB565, 1217 DRM_FORMAT_NV12, DRM_FORMAT_NV16, DRM_FORMAT_NV21, DRM_FORMAT_NV61, 1218 DRM_FORMAT_UYVY, DRM_FORMAT_VYUY, DRM_FORMAT_YUYV, DRM_FORMAT_YVYU, 1219 DRM_FORMAT_YUV420, DRM_FORMAT_YVU420, DRM_FORMAT_YUV422, 1220 DRM_FORMAT_YUV444, 1221 }; 1222 1223 static const unsigned int fimc_tiled_formats[] = { 1224 DRM_FORMAT_NV12, DRM_FORMAT_NV21, 1225 }; 1226 1227 static const struct drm_exynos_ipp_limit fimc_4210_limits_v1[] = { 1228 { IPP_SIZE_LIMIT(BUFFER, .h = { 16, 8192, 8 }, .v = { 16, 8192, 2 }) }, 1229 { IPP_SIZE_LIMIT(AREA, .h = { 16, 4224, 2 }, .v = { 16, 0, 2 }) }, 1230 { IPP_SIZE_LIMIT(ROTATED, .h = { 128, 1920 }, .v = { 128, 0 }) }, 1231 { IPP_SCALE_LIMIT(.h = { (1 << 16) / 64, (1 << 16) * 64 }, 1232 .v = { (1 << 16) / 64, (1 << 16) * 64 }) }, 1233 }; 1234 1235 static const struct drm_exynos_ipp_limit fimc_4210_limits_v2[] = { 1236 { IPP_SIZE_LIMIT(BUFFER, .h = { 16, 8192, 8 }, .v = { 16, 8192, 2 }) }, 1237 { IPP_SIZE_LIMIT(AREA, .h = { 16, 1920, 2 }, .v = { 16, 0, 2 }) }, 1238 { IPP_SIZE_LIMIT(ROTATED, .h = { 128, 1366 }, .v = { 128, 0 }) }, 1239 { IPP_SCALE_LIMIT(.h = { (1 << 16) / 64, (1 << 16) * 64 }, 1240 .v = { (1 << 16) / 64, (1 << 16) * 64 }) }, 1241 }; 1242 1243 static const struct drm_exynos_ipp_limit fimc_4210_limits_tiled_v1[] = { 1244 { IPP_SIZE_LIMIT(BUFFER, .h = { 128, 1920, 128 }, .v = { 32, 1920, 32 }) }, 1245 { IPP_SIZE_LIMIT(AREA, .h = { 128, 1920, 2 }, .v = { 128, 0, 2 }) }, 1246 { IPP_SCALE_LIMIT(.h = { (1 << 16) / 64, (1 << 16) * 64 }, 1247 .v = { (1 << 16) / 64, (1 << 16) * 64 }) }, 1248 }; 1249 1250 static const struct drm_exynos_ipp_limit fimc_4210_limits_tiled_v2[] = { 1251 { IPP_SIZE_LIMIT(BUFFER, .h = { 128, 1920, 128 }, .v = { 32, 1920, 32 }) }, 1252 { IPP_SIZE_LIMIT(AREA, .h = { 128, 1366, 2 }, .v = { 128, 0, 2 }) }, 1253 { IPP_SCALE_LIMIT(.h = { (1 << 16) / 64, (1 << 16) * 64 }, 1254 .v = { (1 << 16) / 64, (1 << 16) * 64 }) }, 1255 }; 1256 1257 static int fimc_probe(struct platform_device *pdev) 1258 { 1259 const struct drm_exynos_ipp_limit *limits; 1260 struct exynos_drm_ipp_formats *formats; 1261 struct device *dev = &pdev->dev; 1262 struct fimc_context *ctx; 1263 struct resource *res; 1264 int ret; 1265 int i, j, num_limits, num_formats; 1266 1267 if (exynos_drm_check_fimc_device(dev) != 0) 1268 return -ENODEV; 1269 1270 ctx = devm_kzalloc(dev, sizeof(*ctx), GFP_KERNEL); 1271 if (!ctx) 1272 return -ENOMEM; 1273 1274 ctx->dev = dev; 1275 ctx->id = of_alias_get_id(dev->of_node, "fimc"); 1276 1277 /* construct formats/limits array */ 1278 num_formats = ARRAY_SIZE(fimc_formats) + ARRAY_SIZE(fimc_tiled_formats); 1279 formats = devm_kcalloc(dev, num_formats, sizeof(*formats), 1280 GFP_KERNEL); 1281 if (!formats) 1282 return -ENOMEM; 1283 1284 /* linear formats */ 1285 if (ctx->id < 3) { 1286 limits = fimc_4210_limits_v1; 1287 num_limits = ARRAY_SIZE(fimc_4210_limits_v1); 1288 } else { 1289 limits = fimc_4210_limits_v2; 1290 num_limits = ARRAY_SIZE(fimc_4210_limits_v2); 1291 } 1292 for (i = 0; i < ARRAY_SIZE(fimc_formats); i++) { 1293 formats[i].fourcc = fimc_formats[i]; 1294 formats[i].type = DRM_EXYNOS_IPP_FORMAT_SOURCE | 1295 DRM_EXYNOS_IPP_FORMAT_DESTINATION; 1296 formats[i].limits = limits; 1297 formats[i].num_limits = num_limits; 1298 } 1299 1300 /* tiled formats */ 1301 if (ctx->id < 3) { 1302 limits = fimc_4210_limits_tiled_v1; 1303 num_limits = ARRAY_SIZE(fimc_4210_limits_tiled_v1); 1304 } else { 1305 limits = fimc_4210_limits_tiled_v2; 1306 num_limits = ARRAY_SIZE(fimc_4210_limits_tiled_v2); 1307 } 1308 for (j = i, i = 0; i < ARRAY_SIZE(fimc_tiled_formats); j++, i++) { 1309 formats[j].fourcc = fimc_tiled_formats[i]; 1310 formats[j].modifier = DRM_FORMAT_MOD_SAMSUNG_64_32_TILE; 1311 formats[j].type = DRM_EXYNOS_IPP_FORMAT_SOURCE | 1312 DRM_EXYNOS_IPP_FORMAT_DESTINATION; 1313 formats[j].limits = limits; 1314 formats[j].num_limits = num_limits; 1315 } 1316 1317 ctx->formats = formats; 1318 ctx->num_formats = num_formats; 1319 1320 /* resource memory */ 1321 ctx->regs_res = platform_get_resource(pdev, IORESOURCE_MEM, 0); 1322 ctx->regs = devm_ioremap_resource(dev, ctx->regs_res); 1323 if (IS_ERR(ctx->regs)) 1324 return PTR_ERR(ctx->regs); 1325 1326 /* resource irq */ 1327 res = platform_get_resource(pdev, IORESOURCE_IRQ, 0); 1328 if (!res) { 1329 dev_err(dev, "failed to request irq resource.\n"); 1330 return -ENOENT; 1331 } 1332 1333 ret = devm_request_irq(dev, res->start, fimc_irq_handler, 1334 0, dev_name(dev), ctx); 1335 if (ret < 0) { 1336 dev_err(dev, "failed to request irq.\n"); 1337 return ret; 1338 } 1339 1340 ret = fimc_setup_clocks(ctx); 1341 if (ret < 0) 1342 return ret; 1343 1344 spin_lock_init(&ctx->lock); 1345 platform_set_drvdata(pdev, ctx); 1346 1347 pm_runtime_use_autosuspend(dev); 1348 pm_runtime_set_autosuspend_delay(dev, FIMC_AUTOSUSPEND_DELAY); 1349 pm_runtime_enable(dev); 1350 1351 ret = component_add(dev, &fimc_component_ops); 1352 if (ret) 1353 goto err_pm_dis; 1354 1355 dev_info(dev, "drm fimc registered successfully.\n"); 1356 1357 return 0; 1358 1359 err_pm_dis: 1360 pm_runtime_dont_use_autosuspend(dev); 1361 pm_runtime_disable(dev); 1362 fimc_put_clocks(ctx); 1363 1364 return ret; 1365 } 1366 1367 static int fimc_remove(struct platform_device *pdev) 1368 { 1369 struct device *dev = &pdev->dev; 1370 struct fimc_context *ctx = get_fimc_context(dev); 1371 1372 component_del(dev, &fimc_component_ops); 1373 pm_runtime_dont_use_autosuspend(dev); 1374 pm_runtime_disable(dev); 1375 1376 fimc_put_clocks(ctx); 1377 1378 return 0; 1379 } 1380 1381 #ifdef CONFIG_PM 1382 static int fimc_runtime_suspend(struct device *dev) 1383 { 1384 struct fimc_context *ctx = get_fimc_context(dev); 1385 1386 DRM_DEV_DEBUG_KMS(dev, "id[%d]\n", ctx->id); 1387 clk_disable_unprepare(ctx->clocks[FIMC_CLK_GATE]); 1388 return 0; 1389 } 1390 1391 static int fimc_runtime_resume(struct device *dev) 1392 { 1393 struct fimc_context *ctx = get_fimc_context(dev); 1394 1395 DRM_DEV_DEBUG_KMS(dev, "id[%d]\n", ctx->id); 1396 return clk_prepare_enable(ctx->clocks[FIMC_CLK_GATE]); 1397 } 1398 #endif 1399 1400 static const struct dev_pm_ops fimc_pm_ops = { 1401 SET_SYSTEM_SLEEP_PM_OPS(pm_runtime_force_suspend, 1402 pm_runtime_force_resume) 1403 SET_RUNTIME_PM_OPS(fimc_runtime_suspend, fimc_runtime_resume, NULL) 1404 }; 1405 1406 static const struct of_device_id fimc_of_match[] = { 1407 { .compatible = "samsung,exynos4210-fimc" }, 1408 { .compatible = "samsung,exynos4212-fimc" }, 1409 { }, 1410 }; 1411 MODULE_DEVICE_TABLE(of, fimc_of_match); 1412 1413 struct platform_driver fimc_driver = { 1414 .probe = fimc_probe, 1415 .remove = fimc_remove, 1416 .driver = { 1417 .of_match_table = fimc_of_match, 1418 .name = "exynos-drm-fimc", 1419 .owner = THIS_MODULE, 1420 .pm = &fimc_pm_ops, 1421 }, 1422 }; 1423