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