diff --git a/drivers/media/video/s5p-fimc/fimc-capture.c b/drivers/media/video/s5p-fimc/fimc-capture.c index 03ddf5d6164f..91304eef812b 100644 --- a/drivers/media/video/s5p-fimc/fimc-capture.c +++ b/drivers/media/video/s5p-fimc/fimc-capture.c @@ -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); diff --git a/drivers/media/video/s5p-fimc/fimc-core.c b/drivers/media/video/s5p-fimc/fimc-core.c index 70d6b4c9760f..59fa5126fc2d 100644 --- a/drivers/media/video/s5p-fimc/fimc-core.c +++ b/drivers/media/video/s5p-fimc/fimc-core.c @@ -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, diff --git a/drivers/media/video/s5p-fimc/fimc-core.h b/drivers/media/video/s5p-fimc/fimc-core.h index 562d15d7059a..8aee9e3207f9 100644 --- a/drivers/media/video/s5p-fimc/fimc-core.h +++ b/drivers/media/video/s5p-fimc/fimc-core.h @@ -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); diff --git a/drivers/media/video/s5p-fimc/fimc-reg.c b/drivers/media/video/s5p-fimc/fimc-reg.c index c14c8316ea13..064fa0a8b893 100644 --- a/drivers/media/video/s5p-fimc/fimc-reg.c +++ b/drivers/media/video/s5p-fimc/fimc-reg.c @@ -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,15 +308,57 @@ 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); - 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(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); + + 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) { struct fimc_dev *dev = ctx->fimc_dev; diff --git a/drivers/media/video/s5p-fimc/regs-fimc.h b/drivers/media/video/s5p-fimc/regs-fimc.h index fe19b4b0fb6a..04669a54a3c2 100644 --- a/drivers/media/video/s5p-fimc/regs-fimc.h +++ b/drivers/media/video/s5p-fimc/regs-fimc.h @@ -139,8 +139,12 @@ #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 @@ -263,6 +267,10 @@ /* 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)