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