linux/drivers/gpu/drm/exynos/exynos_drm_fimc.c
<<
>>
Prefs
   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
  43static unsigned int fimc_mask = 0xc;
  44module_param_named(fimc_devs, fimc_mask, uint, 0644);
  45MODULE_PARM_DESC(fimc_devs, "Alias mask for assigning FIMC devices to Exynos DRM");
  46
  47#define get_fimc_context(dev)   dev_get_drvdata(dev)
  48
  49enum {
  50        FIMC_CLK_LCLK,
  51        FIMC_CLK_GATE,
  52        FIMC_CLK_WB_A,
  53        FIMC_CLK_WB_B,
  54        FIMC_CLKS_MAX
  55};
  56
  57static 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 */
  74struct 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 */
  95struct 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
 112static u32 fimc_read(struct fimc_context *ctx, u32 reg)
 113{
 114        return readl(ctx->regs + reg);
 115}
 116
 117static void fimc_write(struct fimc_context *ctx, u32 val, u32 reg)
 118{
 119        writel(val, ctx->regs + reg);
 120}
 121
 122static 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
 129static 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
 136static 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
 161static 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
 181static 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
 196static 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
 211static void fimc_clear_irq(struct fimc_context *ctx)
 212{
 213        fimc_set_bits(ctx, EXYNOS_CIGCTRL, EXYNOS_CIGCTRL_IRQ_CLR);
 214}
 215
 216static 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
 240static 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
 257static 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
 283static 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
 298static 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
 363static 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
 415static 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
 466static 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
 501static 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
 550static 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
 558static 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
 629static 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
 688static 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
 735static 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
 804static 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
 843static 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
 903static 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
 933static 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
 943static void fimc_stop(struct fimc_context *ctx);
 944
 945static 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
 980static 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
 997static 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
1008static 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
1054static 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
1080static 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
1103static 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
1121static struct exynos_drm_ipp_funcs ipp_funcs = {
1122        .commit = fimc_commit,
1123        .abort = fimc_abort,
1124};
1125
1126static 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
1146static 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
1157static const struct component_ops fimc_component_ops = {
1158        .bind   = fimc_bind,
1159        .unbind = fimc_unbind,
1160};
1161
1162static 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
1174static 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;
1201e_clk_free:
1202        fimc_put_clocks(ctx);
1203        return ret;
1204}
1205
1206int 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
1215static 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
1223static const unsigned int fimc_tiled_formats[] = {
1224        DRM_FORMAT_NV12, DRM_FORMAT_NV21,
1225};
1226
1227static 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
1235static 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
1243static 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
1250static 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
1257static 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
1359err_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
1367static 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
1382static 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
1391static 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
1400static 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
1406static const struct of_device_id fimc_of_match[] = {
1407        { .compatible = "samsung,exynos4210-fimc" },
1408        { .compatible = "samsung,exynos4212-fimc" },
1409        { },
1410};
1411MODULE_DEVICE_TABLE(of, fimc_of_match);
1412
1413struct 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