[media] s5p-fimc: Configure scaler registers depending on FIMC version
authorHyunwoong Kim <khw0178.kim@samsung.com>
Tue, 28 Dec 2010 14:27:13 +0000 (11:27 -0300)
committerMauro Carvalho Chehab <mchehab@redhat.com>
Mon, 21 Mar 2011 23:31:39 +0000 (20:31 -0300)
The main scaler has four SFRs for main scaler ratio depending on FIMC version.
FIMC 4.x has only two SFRs and FIMC 5.x has four SFRs for main scaler.
Those are MainHorRatio, MainHorRatio_ext, MainVerRatio and MainverRatio_ext.

The FIMC 5.x has 15 bit resolution for scaling ratio as below.
{MainHorRatio,MainHorRatio_ext} = {[14:6],[5:0]}.
{MainVerRatio,MainVerRatio_ext} = {[14:6],[5:0]}.
MainHorRatio = CISCCTRL[24:16], MainHorRatio_ext = CIEXTEN[15:10]
MainVerRatio = CISCCTRL[8:0],   MainVerRatio_ext = CIEXTEN[5:0]

This patch supports FIMC 4.x and FIMC 5.x using platform_device_id::driver_data.

Reviewed-by: Jonghun Han <jonghun.han@samsung.com>
Signed-off-by: Hyunwoong Kim <khw0178.kim@samsung.com>
Signed-off-by: Sylwester Nawrocki <s.nawrocki@samsung.com>
Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
drivers/media/video/s5p-fimc/fimc-capture.c
drivers/media/video/s5p-fimc/fimc-core.c
drivers/media/video/s5p-fimc/fimc-core.h
drivers/media/video/s5p-fimc/fimc-reg.c
drivers/media/video/s5p-fimc/regs-fimc.h

index 03ddf5d6164fb0afc74ac03c5cc07d740d69b51a..91304eef812b8787a90431f82cb44a9ddeb4cbc8 100644 (file)
@@ -237,6 +237,7 @@ static int start_streaming(struct vb2_queue *q)
        struct fimc_ctx *ctx = q->drv_priv;
        struct fimc_dev *fimc = ctx->fimc_dev;
        struct s5p_fimc_isp_info *isp_info;
+       struct samsung_fimc_variant *variant = ctx->fimc_dev->variant;
        int ret;
 
        ret = v4l2_subdev_call(fimc->vid_cap.sd, video, s_stream, 1);
@@ -259,7 +260,11 @@ static int start_streaming(struct vb2_queue *q)
                        return ret;
                }
                fimc_hw_set_input_path(ctx);
-               fimc_hw_set_scaler(ctx);
+               fimc_hw_set_prescaler(ctx);
+               if (variant->has_mainscaler_ext)
+                       fimc_hw_set_mainscaler_ext(ctx);
+               else
+                       fimc_hw_set_mainscaler(ctx);
                fimc_hw_set_target_format(ctx);
                fimc_hw_set_rotation(ctx);
                fimc_hw_set_effect(ctx);
index 70d6b4c9760fb8569aa70c837cee9f7859c0fe07..59fa5126fc2d00555ec5d8e7fbda089ce82d186e 100644 (file)
@@ -248,6 +248,7 @@ int fimc_set_scaler_info(struct fimc_ctx *ctx)
        struct fimc_scaler *sc = &ctx->scaler;
        struct fimc_frame *s_frame = &ctx->s_frame;
        struct fimc_frame *d_frame = &ctx->d_frame;
+       struct samsung_fimc_variant *variant = ctx->fimc_dev->variant;
        int tx, ty, sx, sy;
        int ret;
 
@@ -286,8 +287,14 @@ int fimc_set_scaler_info(struct fimc_ctx *ctx)
        sc->pre_dst_width = sx / sc->pre_hratio;
        sc->pre_dst_height = sy / sc->pre_vratio;
 
-       sc->main_hratio = (sx << 8) / (tx << sc->hfactor);
-       sc->main_vratio = (sy << 8) / (ty << sc->vfactor);
+       if (variant->has_mainscaler_ext) {
+               sc->main_hratio = (sx << 14) / (tx << sc->hfactor);
+               sc->main_vratio = (sy << 14) / (ty << sc->vfactor);
+       } else {
+               sc->main_hratio = (sx << 8) / (tx << sc->hfactor);
+               sc->main_vratio = (sy << 8) / (ty << sc->vfactor);
+
+       }
 
        sc->scaleup_h = (tx >= sx) ? 1 : 0;
        sc->scaleup_v = (ty >= sy) ? 1 : 0;
@@ -571,6 +578,7 @@ static void fimc_dma_run(void *priv)
 {
        struct fimc_ctx *ctx = priv;
        struct fimc_dev *fimc;
+       struct samsung_fimc_variant *variant = ctx->fimc_dev->variant;
        unsigned long flags;
        u32 ret;
 
@@ -603,7 +611,12 @@ static void fimc_dma_run(void *priv)
                        err("Scaler setup error");
                        goto dma_unlock;
                }
-               fimc_hw_set_scaler(ctx);
+
+               fimc_hw_set_prescaler(ctx);
+               if (variant->has_mainscaler_ext)
+                       fimc_hw_set_mainscaler_ext(ctx);
+               else
+                       fimc_hw_set_mainscaler(ctx);
                fimc_hw_set_target_format(ctx);
                fimc_hw_set_rotation(ctx);
                fimc_hw_set_effect(ctx);
@@ -1730,6 +1743,7 @@ static struct samsung_fimc_variant fimc1_variant_s5pv210 = {
        .pix_hoff        = 1,
        .has_inp_rot     = 1,
        .has_out_rot     = 1,
+       .has_mainscaler_ext = 1,
        .min_inp_pixsize = 16,
        .min_out_pixsize = 16,
        .hor_offs_align  = 1,
@@ -1751,6 +1765,7 @@ static struct samsung_fimc_variant fimc0_variant_s5pv310 = {
        .has_inp_rot     = 1,
        .has_out_rot     = 1,
        .has_cistatus2   = 1,
+       .has_mainscaler_ext = 1,
        .min_inp_pixsize = 16,
        .min_out_pixsize = 16,
        .hor_offs_align  = 1,
@@ -1761,6 +1776,7 @@ static struct samsung_fimc_variant fimc0_variant_s5pv310 = {
 static struct samsung_fimc_variant fimc2_variant_s5pv310 = {
        .pix_hoff        = 1,
        .has_cistatus2   = 1,
+       .has_mainscaler_ext = 1,
        .min_inp_pixsize = 16,
        .min_out_pixsize = 16,
        .hor_offs_align  = 1,
index 562d15d7059a8c3ef0ab3880b9d992289100e55e..8aee9e3207f9a83c38f6c915c440247a03bb0b8d 100644 (file)
@@ -361,6 +361,8 @@ struct fimc_pix_limit {
  * @has_inp_rot: set if has input rotator
  * @has_out_rot: set if has output rotator
  * @has_cistatus2: 1 if CISTATUS2 register is present in this IP revision
+ * @has_mainscaler_ext: 1 if extended mainscaler ratios in CIEXTEN register
+ *                      are present in this IP revision
  * @pix_limit: pixel size constraints for the scaler
  * @min_inp_pixsize: minimum input pixel size
  * @min_out_pixsize: minimum output pixel size
@@ -372,6 +374,7 @@ struct samsung_fimc_variant {
        unsigned int    has_inp_rot:1;
        unsigned int    has_out_rot:1;
        unsigned int    has_cistatus2:1;
+       unsigned int    has_mainscaler_ext:1;
        struct fimc_pix_limit *pix_limit;
        u16             min_inp_pixsize;
        u16             min_out_pixsize;
@@ -569,7 +572,9 @@ void fimc_hw_set_target_format(struct fimc_ctx *ctx);
 void fimc_hw_set_out_dma(struct fimc_ctx *ctx);
 void fimc_hw_en_lastirq(struct fimc_dev *fimc, int enable);
 void fimc_hw_en_irq(struct fimc_dev *fimc, int enable);
-void fimc_hw_set_scaler(struct fimc_ctx *ctx);
+void fimc_hw_set_prescaler(struct fimc_ctx *ctx);
+void fimc_hw_set_mainscaler(struct fimc_ctx *ctx);
+void fimc_hw_set_mainscaler_ext(struct fimc_ctx *ctx);
 void fimc_hw_en_capture(struct fimc_ctx *ctx);
 void fimc_hw_set_effect(struct fimc_ctx *ctx);
 void fimc_hw_set_in_dma(struct fimc_ctx *ctx);
index c14c8316ea135c5148c07a319adb91603ffea534..064fa0a8b893b78d3e1a9f68cf95433c80ea9b66 100644 (file)
@@ -243,7 +243,7 @@ void fimc_hw_en_lastirq(struct fimc_dev *dev, int enable)
        writel(cfg, dev->regs + S5P_CIOCTRL);
 }
 
-static void fimc_hw_set_prescaler(struct fimc_ctx *ctx)
+void fimc_hw_set_prescaler(struct fimc_ctx *ctx)
 {
        struct fimc_dev *dev =  ctx->fimc_dev;
        struct fimc_scaler *sc = &ctx->scaler;
@@ -261,7 +261,7 @@ static void fimc_hw_set_prescaler(struct fimc_ctx *ctx)
        writel(cfg, dev->regs + S5P_CISCPREDST);
 }
 
-void fimc_hw_set_scaler(struct fimc_ctx *ctx)
+static void fimc_hw_set_scaler(struct fimc_ctx *ctx)
 {
        struct fimc_dev *dev = ctx->fimc_dev;
        struct fimc_scaler *sc = &ctx->scaler;
@@ -269,8 +269,6 @@ void fimc_hw_set_scaler(struct fimc_ctx *ctx)
        struct fimc_frame *dst_frame = &ctx->d_frame;
        u32 cfg = 0;
 
-       fimc_hw_set_prescaler(ctx);
-
        if (!(ctx->flags & FIMC_COLOR_RANGE_NARROW))
                cfg |= (S5P_CISCCTRL_CSCR2Y_WIDE | S5P_CISCCTRL_CSCY2R_WIDE);
 
@@ -310,13 +308,55 @@ void fimc_hw_set_scaler(struct fimc_ctx *ctx)
                        cfg |= S5P_CISCCTRL_INTERLACE;
        }
 
+       writel(cfg, dev->regs + S5P_CISCCTRL);
+}
+
+void fimc_hw_set_mainscaler(struct fimc_ctx *ctx)
+{
+       struct fimc_dev *dev = ctx->fimc_dev;
+       struct fimc_scaler *sc = &ctx->scaler;
+       u32 cfg;
+
+       dbg("main_hratio= 0x%X  main_vratio= 0x%X",
+               sc->main_hratio, sc->main_vratio);
+
+       fimc_hw_set_scaler(ctx);
+
+       cfg = readl(dev->regs + S5P_CISCCTRL);
+       cfg &= ~S5P_CISCCTRL_MHRATIO_MASK;
+       cfg &= ~S5P_CISCCTRL_MVRATIO_MASK;
+       cfg |= S5P_CISCCTRL_MHRATIO(sc->main_hratio);
+       cfg |= S5P_CISCCTRL_MVRATIO(sc->main_vratio);
+
+       writel(cfg, dev->regs + S5P_CISCCTRL);
+}
+
+void fimc_hw_set_mainscaler_ext(struct fimc_ctx *ctx)
+{
+       struct fimc_dev *dev = ctx->fimc_dev;
+       struct fimc_scaler *sc = &ctx->scaler;
+       u32 cfg, cfg_ext;
+
        dbg("main_hratio= 0x%X  main_vratio= 0x%X",
                sc->main_hratio, sc->main_vratio);
 
-       cfg |= S5P_CISCCTRL_SC_HORRATIO(sc->main_hratio);
-       cfg |= S5P_CISCCTRL_SC_VERRATIO(sc->main_vratio);
+       fimc_hw_set_scaler(ctx);
+
+       cfg = readl(dev->regs + S5P_CISCCTRL);
+       cfg &= ~S5P_CISCCTRL_MHRATIO_MASK;
+       cfg &= ~S5P_CISCCTRL_MVRATIO_MASK;
+       cfg |= S5P_CISCCTRL_MHRATIO_EXT(sc->main_hratio);
+       cfg |= S5P_CISCCTRL_MVRATIO_EXT(sc->main_vratio);
 
        writel(cfg, dev->regs + S5P_CISCCTRL);
+
+       cfg_ext = readl(dev->regs + S5P_CIEXTEN);
+       cfg_ext &= ~S5P_CIEXTEN_MHRATIO_EXT_MASK;
+       cfg_ext &= ~S5P_CIEXTEN_MVRATIO_EXT_MASK;
+       cfg_ext |= S5P_CIEXTEN_MHRATIO_EXT(sc->main_hratio);
+       cfg_ext |= S5P_CIEXTEN_MVRATIO_EXT(sc->main_vratio);
+
+       writel(cfg_ext, dev->regs + S5P_CIEXTEN);
 }
 
 void fimc_hw_en_capture(struct fimc_ctx *ctx)
index fe19b4b0fb6a68d2eb50f9e0bcba1ab68bb2fc78..04669a54a3c220ccc22778c55533094a4f1ccf85 100644 (file)
 #define S5P_CISCCTRL_OUTRGB_FMT_MASK   (3 << 11)
 #define S5P_CISCCTRL_RGB_EXT           (1 << 10)
 #define S5P_CISCCTRL_ONE2ONE           (1 << 9)
-#define S5P_CISCCTRL_SC_HORRATIO(x)    ((x) << 16)
-#define S5P_CISCCTRL_SC_VERRATIO(x)    ((x) << 0)
+#define S5P_CISCCTRL_MHRATIO(x)                ((x) << 16)
+#define S5P_CISCCTRL_MVRATIO(x)                ((x) << 0)
+#define S5P_CISCCTRL_MHRATIO_MASK      (0x1ff << 16)
+#define S5P_CISCCTRL_MVRATIO_MASK      (0x1ff << 0)
+#define S5P_CISCCTRL_MHRATIO_EXT(x)    (((x) >> 6) << 16)
+#define S5P_CISCCTRL_MVRATIO_EXT(x)    (((x) >> 6) << 0)
 
 /* Target area */
 #define S5P_CITAREA                    0x5c
 
 /* Real output DMA image size (extension register) */
 #define S5P_CIEXTEN                    0x188
+#define S5P_CIEXTEN_MHRATIO_EXT(x)     (((x) & 0x3f) << 10)
+#define S5P_CIEXTEN_MVRATIO_EXT(x)     ((x) & 0x3f)
+#define S5P_CIEXTEN_MHRATIO_EXT_MASK   (0x3f << 10)
+#define S5P_CIEXTEN_MVRATIO_EXT_MASK   0x3f
 
 #define S5P_CIDMAPARAM                 0x18c
 #define S5P_CIDMAPARAM_R_LINEAR                (0 << 29)