This patch adds support for SCALER device which is a new device
for scaling, blending, color fill  and color space conversion
on EXYNOS5410 and EXYNOS5420 SoCs.

This device supports the followings as key feature.
    input image format
        - YCbCr420 2P(UV/VU), 3P
        - YCbCr422 1P(YUYV/UYVY/YVYU), 2P(UV,VU), 3P
        - YCbCr444 2P(UV,VU), 3P
        - RGB565, ARGB1555, ARGB4444, ARGB8888, RGBA8888
        - Pre-multiplexed ARGB8888, L8A8 and L8
    output image format
        - YCbCr420 2P(UV/VU), 3P
        - YCbCr422 1P(YUYV/UYVY/YVYU), 2P(UV,VU), 3P
        - YCbCr444 2P(UV,VU), 3P
        - RGB565, ARGB1555, ARGB4444, ARGB8888, RGBA8888
        - Pre-multiplexed ARGB8888
    input rotation
        - 0/90/180/270 degree, X/Y/XY Flip
    scale ratio
        - 1/4 scale down to 16 scale up
    color space conversion
        - RGB to YUV / YUV to RGB
    Size - Exynos5420
        - Input : 16x16 to 8192x8192
        - Output:   4x4 to 8192x8192
    Size - Exynos5410
        - Input/Output: 4x4 to 4096x4096
    alpha blending, color fill

Signed-off-by: Shaik Ameer Basha <shaik.am...@samsung.com>
---
 drivers/media/platform/exynos-scaler/scaler-regs.c |  336 ++++++++++++++++++++
 drivers/media/platform/exynos-scaler/scaler-regs.h |  331 +++++++++++++++++++
 2 files changed, 667 insertions(+)
 create mode 100644 drivers/media/platform/exynos-scaler/scaler-regs.c
 create mode 100644 drivers/media/platform/exynos-scaler/scaler-regs.h

diff --git a/drivers/media/platform/exynos-scaler/scaler-regs.c 
b/drivers/media/platform/exynos-scaler/scaler-regs.c
new file mode 100644
index 0000000..ae4a548
--- /dev/null
+++ b/drivers/media/platform/exynos-scaler/scaler-regs.c
@@ -0,0 +1,336 @@
+/*
+ * Copyright (c) 2013 Samsung Electronics Co., Ltd.
+ *             http://www.samsung.com
+ *
+ * Samsung EXYNOS5 SoC series SCALER driver
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/delay.h>
+#include <linux/platform_device.h>
+
+#include "scaler-regs.h"
+
+/* Scaler reset timeout in milliseconds */
+#define SCALER_RESET_TIMEOUT   50
+
+void scaler_hw_set_sw_reset(struct scaler_dev *dev)
+{
+       u32 cfg;
+
+       cfg = scaler_read(dev, SCALER_CFG);
+       cfg |= SCALER_CFG_SOFT_RESET;
+
+       scaler_write(dev, SCALER_CFG, cfg);
+}
+
+int scaler_wait_reset(struct scaler_dev *dev)
+{
+       unsigned long end = jiffies + msecs_to_jiffies(SCALER_RESET_TIMEOUT);
+       u32 cfg, reset_done = 0;
+
+       while (time_before(jiffies, end)) {
+               cfg = scaler_read(dev, SCALER_CFG);
+               if (!(cfg & SCALER_CFG_SOFT_RESET)) {
+                       reset_done = 1;
+                       break;
+               }
+               usleep_range(10, 20);
+       }
+
+       /*
+        * Write any value to read/write register and read it back.
+        * If the written and read value matches, then the reset process is
+        * succeeded.
+        */
+       while (reset_done) {
+
+               /*
+                * TODO: need to define number of tries before returning
+                * -EBUSY to the caller
+                */
+
+               scaler_write(dev, SCALER_CFG_SOFT_RESET_CHECK_REG,
+                               SCALER_CFG_SOFT_RESET_CHECK_VAL);
+               if (SCALER_CFG_SOFT_RESET_CHECK_VAL ==
+                       scaler_read(dev, SCALER_CFG_SOFT_RESET_CHECK_REG))
+                       return 0;
+       }
+
+       return -EBUSY;
+}
+
+void scaler_hw_set_irq(struct scaler_dev *dev, int irq_num, bool enable)
+{
+       u32 cfg;
+
+       if ((irq_num < SCALER_INT_FRAME_END) ||
+           (irq_num > SCALER_INT_TIMEOUT))
+               return;
+
+       cfg = scaler_read(dev, SCALER_INT_EN);
+       if (enable)
+               cfg |= (1 << irq_num);
+       else
+               cfg &= ~(1 << irq_num);
+       scaler_write(dev, SCALER_INT_EN, cfg);
+}
+
+void scaler_hw_set_input_addr(struct scaler_dev *dev, struct scaler_addr *addr)
+{
+       scaler_dbg(dev, "src_buf: 0x%x, cb: 0x%x, cr: 0x%x",
+                               addr->y, addr->cb, addr->cr);
+       scaler_write(dev, SCALER_SRC_Y_BASE, addr->y);
+       scaler_write(dev, SCALER_SRC_CB_BASE, addr->cb);
+       scaler_write(dev, SCALER_SRC_CR_BASE, addr->cr);
+}
+
+void scaler_hw_set_output_addr(struct scaler_dev *dev,
+                            struct scaler_addr *addr)
+{
+       scaler_dbg(dev, "dst_buf: 0x%x, cb: 0x%x, cr: 0x%x",
+                       addr->y, addr->cb, addr->cr);
+       scaler_write(dev, SCALER_DST_Y_BASE, addr->y);
+       scaler_write(dev, SCALER_DST_CB_BASE, addr->cb);
+       scaler_write(dev, SCALER_DST_CR_BASE, addr->cr);
+}
+
+void scaler_hw_set_in_size(struct scaler_ctx *ctx)
+{
+       struct scaler_dev *dev = ctx->scaler_dev;
+       struct scaler_frame *frame = &ctx->s_frame;
+       u32 cfg;
+
+       /* set input pixel offset */
+       cfg = (frame->selection.left & SCALER_SRC_YH_POS_MASK) <<
+                                 SCALER_SRC_YH_POS_SHIFT;
+       cfg |= ((frame->selection.top & SCALER_SRC_YV_POS_MASK) <<
+                                  SCALER_SRC_YV_POS_SHIFT);
+       scaler_write(dev, SCALER_SRC_Y_POS, cfg);
+
+       /* TODO: calculate 'C' plane h/v offset using 'Y' plane h/v offset */
+
+       /* Set input span */
+       cfg = (frame->f_width & SCALER_SRC_Y_SPAN_MASK) <<
+                               SCALER_SRC_Y_SPAN_SHIFT;
+       if (is_yuv420_2p(frame->fmt))
+               cfg |= ((frame->f_width & SCALER_SRC_C_SPAN_MASK) <<
+                                         SCALER_SRC_C_SPAN_SHIFT);
+       else /* TODO: Verify */
+               cfg |= ((frame->f_width & SCALER_SRC_C_SPAN_MASK) <<
+                                         SCALER_SRC_C_SPAN_SHIFT);
+
+       scaler_write(dev, SCALER_SRC_SPAN, cfg);
+
+       /* Set input cropped size */
+       cfg = (frame->selection.width & SCALER_SRC_WIDTH_MASK) <<
+                                  SCALER_SRC_WIDTH_SHIFT;
+       cfg |= ((frame->selection.height & SCALER_SRC_HEIGHT_MASK) <<
+                                     SCALER_SRC_HEIGHT_SHIFT);
+       scaler_write(dev, SCALER_SRC_WH, cfg);
+
+       scaler_dbg(dev, "src: posx: %d, posY: %d, spanY: %d, spanC: %d, cropX: 
%d, cropY: %d\n",
+               frame->selection.left, frame->selection.top,
+               frame->f_width, frame->f_width, frame->selection.width,
+               frame->selection.height);
+}
+
+void scaler_hw_set_in_image_format(struct scaler_ctx *ctx)
+{
+       struct scaler_dev *dev = ctx->scaler_dev;
+       struct scaler_frame *frame = &ctx->s_frame;
+       u32 cfg;
+
+       cfg = scaler_read(dev, SCALER_SRC_CFG);
+       cfg &= ~(SCALER_SRC_COLOR_FORMAT_MASK << SCALER_SRC_COLOR_FORMAT_SHIFT);
+       cfg |= ((frame->fmt->scaler_color & SCALER_SRC_COLOR_FORMAT_MASK) <<
+                                          SCALER_SRC_COLOR_FORMAT_SHIFT);
+
+       /* Setting tiled/linear format */
+       if (is_tiled_fmt(frame->fmt))
+               cfg |= SCALER_SRC_TILE_EN;
+       else
+               cfg &= ~SCALER_SRC_TILE_EN;
+
+       scaler_write(dev, SCALER_SRC_CFG, cfg);
+}
+
+void scaler_hw_set_out_size(struct scaler_ctx *ctx)
+{
+       struct scaler_dev *dev = ctx->scaler_dev;
+       struct scaler_frame *frame = &ctx->d_frame;
+       u32 cfg;
+
+       /* Set output pixel offset */
+       cfg = (frame->selection.left & SCALER_DST_H_POS_MASK) <<
+                                 SCALER_DST_H_POS_SHIFT;
+       cfg |= (frame->selection.top & SCALER_DST_V_POS_MASK) <<
+                                 SCALER_DST_V_POS_SHIFT;
+       scaler_write(dev, SCALER_DST_POS, cfg);
+
+       /* Set output span */
+       cfg = (frame->f_width & SCALER_DST_Y_SPAN_MASK) <<
+                               SCALER_DST_Y_SPAN_SHIFT;
+       if (is_yuv420_2p(frame->fmt))
+               cfg |= (((frame->f_width / 2) & SCALER_DST_C_SPAN_MASK) <<
+                                            SCALER_DST_C_SPAN_SHIFT);
+       else
+               cfg |= (((frame->f_width) & SCALER_DST_C_SPAN_MASK) <<
+                                            SCALER_DST_C_SPAN_SHIFT);
+       scaler_write(dev, SCALER_DST_SPAN, cfg);
+
+       /* Set output scaled size */
+       cfg = (frame->selection.width & SCALER_DST_WIDTH_MASK) <<
+                                  SCALER_DST_WIDTH_SHIFT;
+       cfg |= (frame->selection.height & SCALER_DST_HEIGHT_MASK) <<
+                                    SCALER_DST_HEIGHT_SHIFT;
+       scaler_write(dev, SCALER_DST_WH, cfg);
+
+       scaler_dbg(dev, "dst: pos X: %d, pos Y: %d, span Y: %d, span C: %d, 
crop X: %d, crop Y: %d\n",
+               frame->selection.left, frame->selection.top,
+               frame->f_width, frame->f_width, frame->selection.width,
+               frame->selection.height);
+}
+
+void scaler_hw_set_out_image_format(struct scaler_ctx *ctx)
+{
+       struct scaler_dev *dev = ctx->scaler_dev;
+       struct scaler_frame *frame = &ctx->d_frame;
+       u32 cfg;
+
+       cfg = scaler_read(dev, SCALER_DST_CFG);
+       cfg &= ~SCALER_DST_COLOR_FORMAT_MASK;
+       cfg |= (frame->fmt->scaler_color & SCALER_DST_COLOR_FORMAT_MASK);
+
+       scaler_write(dev, SCALER_DST_CFG, cfg);
+}
+
+void scaler_hw_set_scaler_ratio(struct scaler_ctx *ctx)
+{
+       struct scaler_dev *dev = ctx->scaler_dev;
+       struct scaler_scaler *sc = &ctx->scaler;
+       u32 cfg;
+
+       cfg = (sc->hratio & SCALER_H_RATIO_MASK) << SCALER_H_RATIO_SHIFT;
+       scaler_write(dev, SCALER_H_RATIO, cfg);
+
+       cfg = (sc->vratio & SCALER_V_RATIO_MASK) << SCALER_V_RATIO_SHIFT;
+       scaler_write(dev, SCALER_V_RATIO, cfg);
+}
+
+void scaler_hw_set_rotation(struct scaler_ctx *ctx)
+{
+       struct scaler_dev *dev = ctx->scaler_dev;
+       u32 cfg = 0;
+
+       cfg = ((ctx->ctrls_scaler.rotate->val / 90) & SCALER_ROTMODE_MASK) <<
+                                                     SCALER_ROTMODE_SHIFT;
+
+       if (ctx->ctrls_scaler.hflip->val)
+               cfg |= SCALER_FLIP_X_EN;
+
+       if (ctx->ctrls_scaler.vflip->val)
+               cfg |= SCALER_FLIP_Y_EN;
+
+       scaler_write(dev, SCALER_ROT_CFG, cfg);
+}
+
+void scaler_hw_set_csc_coeff(struct scaler_ctx *ctx)
+{
+       struct scaler_dev *dev = ctx->scaler_dev;
+       enum scaler_csc_coeff type;
+       u32 cfg = 0;
+       int i, j;
+       static const u32 csc_coeff[SCALER_CSC_COEFF_MAX][3][3] = {
+               { /* YCbCr to RGB */
+                       {0x254, 0x000, 0x331},
+                       {0x254, 0xec8, 0xFA0},
+                       {0x254, 0x409, 0x000}
+               },
+               { /* RGB to YCbCr */
+                       {0x084, 0x102, 0x032},
+                       {0xe4c, 0xe95, 0x0e1},
+                       {0x0e1, 0xebc, 0xe24}
+               } };
+
+       /* TODO: add check for BT.601,BT.709 narrow/wide ranges */
+       if (is_rgb(ctx->s_frame.fmt) == is_rgb(ctx->d_frame.fmt)) {
+               type = SCALER_CSC_COEFF_NONE;
+       } else if (is_rgb(ctx->d_frame.fmt)) {
+               type = SCALER_CSC_COEFF_YCBCR_TO_RGB;
+               scaler_hw_src_y_offset_en(ctx->scaler_dev, true);
+       } else {
+               type = SCALER_CSC_COEFF_RGB_TO_YCBCR;
+               scaler_hw_src_y_offset_en(ctx->scaler_dev, true);
+       }
+
+       if (type == ctx->scaler_dev->coeff_type || type >= SCALER_CSC_COEFF_MAX)
+               return;
+
+       for (i = 0; i < 3; i++) {
+               for (j = 0; j < 3; j++) {
+                       cfg = csc_coeff[type][i][j];
+                       scaler_write(dev, SCALER_CSC_COEF(i, j), cfg);
+               }
+       }
+
+       ctx->scaler_dev->coeff_type = type;
+}
+
+void scaler_hw_src_y_offset_en(struct scaler_dev *dev, bool on)
+{
+       u32 cfg;
+
+       cfg = scaler_read(dev, SCALER_CFG);
+       if (on)
+               cfg |= SCALER_CFG_CSC_Y_OFFSET_SRC_EN;
+       else
+               cfg &= ~SCALER_CFG_CSC_Y_OFFSET_SRC_EN;
+
+       scaler_write(dev, SCALER_CFG, cfg);
+}
+
+void scaler_hw_dst_y_offset_en(struct scaler_dev *dev, bool on)
+{
+       u32 cfg;
+
+       cfg = scaler_read(dev, SCALER_CFG);
+       if (on)
+               cfg |= SCALER_CFG_CSC_Y_OFFSET_DST_EN;
+       else
+               cfg &= ~SCALER_CFG_CSC_Y_OFFSET_DST_EN;
+
+       scaler_write(dev, SCALER_CFG, cfg);
+}
+
+void scaler_hw_enable_control(struct scaler_dev *dev, bool on)
+{
+       u32 cfg;
+
+       if (on)
+               scaler_write(dev, SCALER_INT_EN, 0xffffffff);
+
+       cfg = scaler_read(dev, SCALER_CFG);
+       cfg |= SCALER_CFG_16_BURST_MODE;
+       if (on)
+               cfg |= SCALER_CFG_START_CMD;
+       else
+               cfg &= ~SCALER_CFG_START_CMD;
+
+       scaler_dbg(dev, "%s: SCALER_CFG:0x%x\n", __func__, cfg);
+
+       scaler_write(dev, SCALER_CFG, cfg);
+}
+
+unsigned int scaler_hw_get_irq_status(struct scaler_dev *dev)
+{
+       return scaler_read(dev, SCALER_INT_STATUS);
+}
+
+void scaler_hw_clear_irq(struct scaler_dev *dev, unsigned int irq)
+{
+       scaler_write(dev, SCALER_INT_STATUS, irq);
+}
diff --git a/drivers/media/platform/exynos-scaler/scaler-regs.h 
b/drivers/media/platform/exynos-scaler/scaler-regs.h
new file mode 100644
index 0000000..2170df5
--- /dev/null
+++ b/drivers/media/platform/exynos-scaler/scaler-regs.h
@@ -0,0 +1,331 @@
+/*
+ * Copyright (c) 2013 Samsung Electronics Co., Ltd.
+ *             http://www.samsung.com
+ *
+ * Samsung EXYNOS5 SoC series SCALER driver
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#ifndef REGS_SCALER_H_
+#define REGS_SCALER_H_
+
+#include "scaler.h"
+
+/* SCALER status */
+#define SCALER_STATUS                          0x00
+#define SCALER_STATUS_RUNNING                  (1 << 1)
+#define SCALER_STATUS_READY_CLK_DOWN           (1 << 0)
+
+/* SCALER config */
+#define SCALER_CFG                             0x04
+#define SCALER_CFG_FILL_EN                     (1 << 24)
+#define SCALER_CFG_BLEND_CLR_DIV_ALPHA_EN      (1 << 17)
+#define SCALER_CFG_BLEND_EN                    (1 << 16)
+#define SCALER_CFG_CSC_Y_OFFSET_SRC_EN         (1 << 10)
+#define SCALER_CFG_CSC_Y_OFFSET_DST_EN         (1 << 9)
+#define SCALER_CFG_16_BURST_MODE               (1 << 8)
+#define SCALER_CFG_SOFT_RESET                  (1 << 1)
+#define SCALER_CFG_START_CMD                   (1 << 0)
+
+/* SCALER interrupts */
+#define SCALER_INT_TIMEOUT                     31
+#define SCALER_INT_ILLEGAL_BLEND               24
+#define SCALER_INT_ILLEGAL_RATIO               23
+#define SCALER_INT_ILLEGAL_DST_HEIGHT          22
+#define SCALER_INT_ILLEGAL_DST_WIDTH           21
+#define SCALER_INT_ILLEGAL_DST_V_POS           20
+#define SCALER_INT_ILLEGAL_DST_H_POS           19
+#define SCALER_INT_ILLEGAL_DST_C_SPAN          18
+#define SCALER_INT_ILLEGAL_DST_Y_SPAN          17
+#define SCALER_INT_ILLEGAL_DST_CR_BASE         16
+#define SCALER_INT_ILLEGAL_DST_CB_BASE         15
+#define SCALER_INT_ILLEGAL_DST_Y_BASE          14
+#define SCALER_INT_ILLEGAL_DST_COLOR           13
+#define SCALER_INT_ILLEGAL_SRC_HEIGHT          12
+#define SCALER_INT_ILLEGAL_SRC_WIDTH           11
+#define SCALER_INT_ILLEGAL_SRC_CV_POS          10
+#define SCALER_INT_ILLEGAL_SRC_CH_POS          9
+#define SCALER_INT_ILLEGAL_SRC_YV_POS          8
+#define SCALER_INT_ILLEGAL_SRC_YH_POS          7
+#define SCALER_INT_ILLEGAL_SRC_C_SPAN          6
+#define SCALER_INT_ILLEGAL_SRC_Y_SPAN          5
+#define SCALER_INT_ILLEGAL_SRC_CR_BASE         4
+#define SCALER_INT_ILLEGAL_SRC_CB_BASE         3
+#define SCALER_INT_ILLEGAL_SRC_Y_BASE          2
+#define SCALER_INT_ILLEGAL_SRC_COLOR           1
+#define SCALER_INT_FRAME_END                   0
+
+/* SCALER interrupt enable */
+#define SCALER_INT_EN                          0x08
+#define SCALER_INT_EN_DEFAULT                  0x81ffffff
+
+/* SCALER interrupt status */
+#define SCALER_INT_STATUS                      0x0c
+#define SCALER_INT_STATUS_CLEAR                        0xffffffff
+#define SCALER_INT_STATUS_ERROR                        0x81fffffe
+
+/* SCALER source format configuration */
+#define SCALER_SRC_CFG                         0x10
+#define SCALER_SRC_TILE_EN                     (0x1 << 10)
+#define SCALER_SRC_BYTE_SWAP_MASK              0x3
+#define SCALER_SRC_BYTE_SWAP_SHIFT             5
+#define SCALER_SRC_COLOR_FORMAT_MASK           0xf
+#define SCALER_SRC_COLOR_FORMAT_SHIFT          0
+
+/* SCALER source y-base */
+#define SCALER_SRC_Y_BASE                      0x14
+
+/* SCALER source cb-base */
+#define SCALER_SRC_CB_BASE                     0x18
+
+/* SCALER source cr-base */
+#define SCALER_SRC_CR_BASE                     0x294
+
+/* SCALER source span */
+#define SCALER_SRC_SPAN                                0x1c
+#define SCALER_SRC_C_SPAN_MASK                 0x3fff
+#define SCALER_SRC_C_SPAN_SHIFT                        16
+#define SCALER_SRC_Y_SPAN_MASK                 0x3fff
+#define SCALER_SRC_Y_SPAN_SHIFT                        0
+
+/*
+ * SCALER source y-position
+ * 14.2 fixed-point format
+ *      - 14 bits at the MSB are for the integer part.
+ *      - 2 bits at LSB are for fractional part and always has to be set to 0.
+ */
+#define SCALER_SRC_Y_POS                       0x20
+#define SCALER_SRC_YH_POS_MASK                 0xfffc
+#define SCALER_SRC_YH_POS_SHIFT                        16
+#define SCALER_SRC_YV_POS_MASK                 0xfffc
+#define SCALER_SRC_YV_POS_SHIFT                        0
+
+/* SCALER source width/height */
+#define SCALER_SRC_WH                          0x24
+#define SCALER_SRC_WIDTH_MASK                  0x3fff
+#define SCALER_SRC_WIDTH_SHIFT                 16
+#define SCALER_SRC_HEIGHT_MASK                 0x3fff
+#define SCALER_SRC_HEIGHT_SHIFT                        0
+
+/*
+ * SCALER source c-position
+ * 14.2 fixed-point format
+ *      - 14 bits at the MSB are for the integer part.
+ *      - 2 bits at LSB are for fractional part and always has to be set to 0.
+ */
+#define SCALER_SRC_C_POS                       0x28
+#define SCALER_SRC_CH_POS_MASK                 0xfffc
+#define SCALER_SRC_CH_POS_SHIFT                        16
+#define SCALER_SRC_CV_POS_MASK                 0xfffc
+#define SCALER_SRC_CV_POS_SHIFT                        0
+
+/* SCALER destination format configuration */
+#define SCALER_DST_CFG                         0x30
+#define SCALER_DST_BYTE_SWAP_MASK              0x3
+#define SCALER_DST_BYTE_SWAP_SHIFT             5
+#define SCALER_DST_COLOR_FORMAT_MASK           0xf
+
+/* SCALER destination y-base */
+#define SCALER_DST_Y_BASE                      0x34
+
+/* SCALER destination cb-base */
+#define SCALER_DST_CB_BASE                     0x38
+
+/* SCALER destination cr-base */
+#define SCALER_DST_CR_BASE                     0x298
+
+/* SCALER destination span */
+#define SCALER_DST_SPAN                                0x3c
+#define SCALER_DST_C_SPAN_MASK                 0x3fff
+#define SCALER_DST_C_SPAN_SHIFT                        16
+#define SCALER_DST_Y_SPAN_MASK                 0x3fff
+#define SCALER_DST_Y_SPAN_SHIFT                        0
+
+/* SCALER destination width/height */
+#define SCALER_DST_WH                          0x40
+#define SCALER_DST_WIDTH_MASK                  0x3fff
+#define SCALER_DST_WIDTH_SHIFT                 16
+#define SCALER_DST_HEIGHT_MASK                 0x3fff
+#define SCALER_DST_HEIGHT_SHIFT                        0
+
+/* SCALER destination position */
+#define SCALER_DST_POS                         0x44
+#define SCALER_DST_H_POS_MASK                  0x3fff
+#define SCALER_DST_H_POS_SHIFT                 16
+#define SCALER_DST_V_POS_MASK                  0x3fff
+#define SCALER_DST_V_POS_SHIFT                 0
+
+/* SCALER horizontal scale ratio */
+#define SCALER_H_RATIO                         0x50
+#define SCALER_H_RATIO_MASK                    0x7ffff
+#define SCALER_H_RATIO_SHIFT                   0
+
+/* SCALER vertical scale ratio */
+#define SCALER_V_RATIO                         0x54
+#define SCALER_V_RATIO_MASK                    0x7ffff
+#define SCALER_V_RATIO_SHIFT                   0
+
+/* SCALER rotation config */
+#define SCALER_ROT_CFG                         0x58
+#define SCALER_FLIP_X_EN                       (1 << 3)
+#define SCALER_FLIP_Y_EN                       (1 << 2)
+#define SCALER_ROTMODE_MASK                    0x3
+#define SCALER_ROTMODE_SHIFT                   0
+
+/* SCALER csc coefficients */
+#define SCALER_CSC_COEF(x, y)                  (0x220 + ((x * 12) + (y * 4)))
+
+/* SCALER dither config */
+#define SCALER_DITH_CFG                                0x250
+#define SCALER_DITHER_R_TYPE_MASK              0x7
+#define SCALER_DITHER_R_TYPE_SHIFT             6
+#define SCALER_DITHER_G_TYPE_MASK              0x7
+#define SCALER_DITHER_G_TYPE_SHIFT             3
+#define SCALER_DITHER_B_TYPE_MASK              0x7
+#define SCALER_DITHER_B_TYPE_SHIFT             0
+
+/* SCALER src blend color */
+#define SCALER_SRC_BLEND_COLOR                 0x280
+#define SCALER_SRC_COLOR_SEL_INV               (1 << 31)
+#define SCALER_SRC_COLOR_SEL_MASK              0x3
+#define SCALER_SRC_COLOR_SEL_SHIFT             29
+#define SCALER_SRC_COLOR_OP_SEL_INV            (1 << 28)
+#define SCALER_SRC_COLOR_OP_SEL_MASK           0xf
+#define SCALER_SRC_COLOR_OP_SEL_SHIFT          24
+#define SCALER_SRC_GLOBAL_COLOR0_MASK          0xff
+#define SCALER_SRC_GLOBAL_COLOR0_SHIFT         16
+#define SCALER_SRC_GLOBAL_COLOR1_MASK          0xff
+#define SCALER_SRC_GLOBAL_COLOR1_SHIFT         8
+#define SCALER_SRC_GLOBAL_COLOR2_MASK          0xff
+#define SCALER_SRC_GLOBAL_COLOR2_SHIFT         0
+
+/* SCALER src blend alpha */
+#define SCALER_SRC_BLEND_ALPHA                 0x284
+#define SCALER_SRC_ALPHA_SEL_INV               (1 << 31)
+#define SCALER_SRC_ALPHA_SEL_MASK              0x3
+#define SCALER_SRC_ALPHA_SEL_SHIFT             29
+#define SCALER_SRC_ALPHA_OP_SEL_INV            (1 << 28)
+#define SCALER_SRC_ALPHA_OP_SEL_MASK           0xf
+#define SCALER_SRC_ALPHA_OP_SEL_SHIFT          24
+#define SCALER_SRC_GLOBAL_ALPHA_MASK           0xff
+#define SCALER_SRC_GLOBAL_ALPHA_SHIFT          0
+
+/* SCALER dst blend color */
+#define SCALER_DST_BLEND_COLOR                 0x288
+#define SCALER_DST_COLOR_SEL_INV               (1 << 31)
+#define SCALER_DST_COLOR_SEL_MASK              0x3
+#define SCALER_DST_COLOR_SEL_SHIFT             29
+#define SCALER_DST_COLOR_OP_SEL_INV            (1 << 28)
+#define SCALER_DST_COLOR_OP_SEL_MASK           0xf
+#define SCALER_DST_COLOR_OP_SEL_SHIFT          24
+#define SCALER_DST_GLOBAL_COLOR0_MASK          0xff
+#define SCALER_DST_GLOBAL_COLOR0_SHIFT         16
+#define SCALER_DST_GLOBAL_COLOR1_MASK          0xff
+#define SCALER_DST_GLOBAL_COLOR1_SHIFT         8
+#define SCALER_DST_GLOBAL_COLOR2_MASK          0xff
+#define SCALER_DST_GLOBAL_COLOR2_SHIFT         0
+
+/* SCALER dst blend alpha */
+#define SCALER_DST_BLEND_ALPHA                 0x28c
+#define SCALER_DST_ALPHA_SEL_INV               (1 << 31)
+#define SCALER_DST_ALPHA_SEL_MASK              0x3
+#define SCALER_DST_ALPHA_SEL_SHIFT             29
+#define SCALER_DST_ALPHA_OP_SEL_INV            (1 << 28)
+#define SCALER_DST_ALPHA_OP_SEL_MASK           0xf
+#define SCALER_DST_ALPHA_OP_SEL_SHIFT          24
+#define SCALER_DST_GLOBAL_ALPHA_MASK           0xff
+#define SCALER_DST_GLOBAL_ALPHA_SHIFT          0
+
+/* SCALER fill color */
+#define SCALER_FILL_COLOR                      0x290
+#define SCALER_FILL_ALPHA_MASK                 0xff
+#define SCALER_FILL_ALPHA_SHIFT                        24
+#define SCALER_FILL_COLOR0_MASK                        0xff
+#define SCALER_FILL_COLOR0_SHIFT               16
+#define SCALER_FILL_COLOR1_MASK                        0xff
+#define SCALER_FILL_COLOR1_SHIFT               8
+#define SCALER_FILL_COLOR2_MASK                        0xff
+#define SCALER_FILL_COLOR2_SHIFT               0
+
+/* SCALER address queue config */
+#define SCALER_ADDR_QUEUE_CONFIG               0x2a0
+#define SCALER_ADDR_QUEUE_RST                  0x1
+
+/* Arbitrary R/W register and value to check if soft reset succeeded */
+#define SCALER_CFG_SOFT_RESET_CHECK_REG                SCALER_SRC_CFG
+#define SCALER_CFG_SOFT_RESET_CHECK_VAL                0x3
+
+struct scaler_error {
+       u32 irq_num;
+       const char * const name;
+};
+
+static const struct scaler_error scaler_errors[] = {
+       {SCALER_INT_TIMEOUT,                    "Timeout"},
+       {SCALER_INT_ILLEGAL_BLEND,              "Illegal Blend setting"},
+       {SCALER_INT_ILLEGAL_RATIO,              "Illegal Scale ratio setting"},
+       {SCALER_INT_ILLEGAL_DST_HEIGHT,         "Illegal Dst Height"},
+       {SCALER_INT_ILLEGAL_DST_WIDTH,          "Illegal Dst Width"},
+       {SCALER_INT_ILLEGAL_DST_V_POS,          "Illegal Dst V-Pos"},
+       {SCALER_INT_ILLEGAL_DST_H_POS,          "Illegal Dst H-Pos"},
+       {SCALER_INT_ILLEGAL_DST_C_SPAN,         "Illegal Dst C-Span"},
+       {SCALER_INT_ILLEGAL_DST_Y_SPAN,         "Illegal Dst Y-span"},
+       {SCALER_INT_ILLEGAL_DST_CR_BASE,        "Illegal Dst Cr-base"},
+       {SCALER_INT_ILLEGAL_DST_CB_BASE,        "Illegal Dst Cb-base"},
+       {SCALER_INT_ILLEGAL_DST_Y_BASE,         "Illegal Dst Y-base"},
+       {SCALER_INT_ILLEGAL_DST_COLOR,          "Illegal Dst Color"},
+       {SCALER_INT_ILLEGAL_SRC_HEIGHT,         "Illegal Src Height"},
+       {SCALER_INT_ILLEGAL_SRC_WIDTH,          "Illegal Src Width"},
+       {SCALER_INT_ILLEGAL_SRC_CV_POS,         "Illegal Src Chroma V-pos"},
+       {SCALER_INT_ILLEGAL_SRC_CH_POS,         "Illegal Src Chroma H-pos"},
+       {SCALER_INT_ILLEGAL_SRC_YV_POS,         "Illegal Src Luma V-pos"},
+       {SCALER_INT_ILLEGAL_SRC_YH_POS,         "Illegal Src Luma H-pos"},
+       {SCALER_INT_ILLEGAL_SRC_C_SPAN,         "Illegal Src C-span"},
+       {SCALER_INT_ILLEGAL_SRC_Y_SPAN,         "Illegal Src Y-span"},
+       {SCALER_INT_ILLEGAL_SRC_CR_BASE,        "Illegal Src Cr-base"},
+       {SCALER_INT_ILLEGAL_SRC_CB_BASE,        "Illegal Src Cb-base"},
+       {SCALER_INT_ILLEGAL_SRC_Y_BASE,         "Illegal Src Y-base"},
+       {SCALER_INT_ILLEGAL_SRC_COLOR,          "Illegal Src Color setting"},
+};
+
+#define SCALER_NUM_ERRORS      ARRAY_SIZE(scaler_errors)
+
+static inline u32 scaler_read(struct scaler_dev *dev, u32 offset)
+{
+       return readl(dev->regs + offset);
+}
+
+static inline void scaler_write(struct scaler_dev *dev, u32 offset, u32 value)
+{
+       writel(value, dev->regs + offset);
+}
+
+static inline void scaler_hw_address_queue_reset(struct scaler_ctx *ctx)
+{
+       scaler_write(ctx->scaler_dev, SCALER_ADDR_QUEUE_CONFIG,
+                                       SCALER_ADDR_QUEUE_RST);
+}
+
+void scaler_hw_set_sw_reset(struct scaler_dev *dev);
+int scaler_wait_reset(struct scaler_dev *dev);
+void scaler_hw_set_irq(struct scaler_dev *dev, int interrupt, bool mask);
+void scaler_hw_set_input_addr(struct scaler_dev *dev, struct scaler_addr 
*addr);
+void scaler_hw_set_output_addr(struct scaler_dev *dev,
+                               struct scaler_addr *addr);
+void scaler_hw_set_in_size(struct scaler_ctx *ctx);
+void scaler_hw_set_in_image_format(struct scaler_ctx *ctx);
+void scaler_hw_set_out_size(struct scaler_ctx *ctx);
+void scaler_hw_set_out_image_format(struct scaler_ctx *ctx);
+void scaler_hw_set_scaler_ratio(struct scaler_ctx *ctx);
+void scaler_hw_set_rotation(struct scaler_ctx *ctx);
+void scaler_hw_set_csc_coeff(struct scaler_ctx *ctx);
+void scaler_hw_src_y_offset_en(struct scaler_dev *dev, bool on);
+void scaler_hw_dst_y_offset_en(struct scaler_dev *dev, bool on);
+void scaler_hw_enable_control(struct scaler_dev *dev, bool on);
+unsigned int scaler_hw_get_irq_status(struct scaler_dev *dev);
+void scaler_hw_clear_irq(struct scaler_dev *dev, unsigned int irq);
+
+#endif /* REGS_SCALER_H_ */
-- 
1.7.9.5

--
To unsubscribe from this list: send the line "unsubscribe linux-media" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

Reply via email to