From: Cho KyongHo Date: Mon, 4 May 2015 06:13:32 +0000 (+0900) Subject: [COMMON] media: smfc: add support for HWFC configuration X-Git-Url: https://git.stricted.de/?a=commitdiff_plain;h=4e418cd7dd0e325fa1eb51cfedb48a2acc36981c;p=GitHub%2FLineageOS%2Fandroid_kernel_motorola_exynos9610.git [COMMON] media: smfc: add support for HWFC configuration HWFC is configurable with V4L2_CID_JPEG_HWFC_ENABLE boolean control. It is only configurable with YUV422 1-plane and YUV420 2-plane without change in chroma subsampling ratio. Otherwise, users will get error. Change-Id: I09d0ac8b0cd6aa801ad611f3b8a065b84c00c4bf Signed-off-by: Cho KyongHo --- diff --git a/drivers/media/platform/exynos/smfc/smfc-regs.c b/drivers/media/platform/exynos/smfc/smfc-regs.c index d76dc0440f01..ff24f3147ee7 100644 --- a/drivers/media/platform/exynos/smfc/smfc-regs.c +++ b/drivers/media/platform/exynos/smfc/smfc-regs.c @@ -309,7 +309,8 @@ void smfc_hwconfigure_image(struct smfc_ctx *ctx, ctx->smfc->reg + REG_MAIN_MAX_STREAM_SIZE); } -void smfc_hwconfigure_start(struct smfc_ctx *ctx, unsigned int rst_int) +void smfc_hwconfigure_start(struct smfc_ctx *ctx, + unsigned int rst_int, bool hwfc_en) { u32 cfg; void __iomem *base = ctx->smfc->reg; @@ -326,6 +327,8 @@ void smfc_hwconfigure_start(struct smfc_ctx *ctx, unsigned int rst_int) cfg |= 1 << 19; /* update huffman table from SFR */ cfg |= 1 << 28; /* enables interrupt */ cfg |= 1 << 29; /* Release reset */ + if (hwfc_en) + cfg |= 1 << 30; /* Enable OTF mode (default: emulation) */ if (rst_int != 0) cfg |= (rst_int << 3) | (1 << 2); if (!!(ctx->flags & SMFC_CTX_B2B_COMPRESS)) diff --git a/drivers/media/platform/exynos/smfc/smfc.c b/drivers/media/platform/exynos/smfc/smfc.c index 1708c9d215db..26775a031a2c 100644 --- a/drivers/media/platform/exynos/smfc/smfc.c +++ b/drivers/media/platform/exynos/smfc/smfc.c @@ -44,6 +44,7 @@ /* SMFC SPECIFIC CONTROLS */ #define V4L2_CID_JPEG_SEC_COMP_QUALITY (V4L2_CID_JPEG_CLASS_BASE + 20) +#define V4L2_CID_JPEG_HWFC_ENABLE (V4L2_CID_JPEG_CLASS_BASE + 25) #define SMFC_DEFAULT_OUTPUT_FORMAT (&smfc_image_formats[1]) #define SMFC_DEFAULT_CAPTURE_FORMAT (&smfc_image_formats[0]) @@ -499,6 +500,9 @@ static int smfc_s_ctrl(struct v4l2_ctrl *ctrl) case V4L2_CID_JPEG_SEC_COMP_QUALITY: ctx->thumb_quality_factor = (unsigned char)ctrl->val; break; + case V4L2_CID_JPEG_HWFC_ENABLE: + ctx->enable_hwfc = (unsigned char)ctrl->val; + break; case V4L2_CID_JPEG_RESTART_INTERVAL: ctx->restart_interval = (unsigned char)ctrl->val; break; @@ -571,6 +575,20 @@ static int smfc_init_controls(struct smfc_dev *smfc, goto err; } + memset(&ctrlcfg, 0, sizeof(ctrlcfg)); + ctrlcfg.ops = &smfc_ctrl_ops; + ctrlcfg.id = V4L2_CID_JPEG_HWFC_ENABLE; + ctrlcfg.name = "HWFC configuration"; + ctrlcfg.type = V4L2_CTRL_TYPE_BOOLEAN; + ctrlcfg.min = 0; + ctrlcfg.max = 1; + ctrlcfg.step = 1; + ctrlcfg.def = 0; + if (!v4l2_ctrl_new_custom(hdlr, &ctrlcfg, NULL)) { + msg = "secondary quality factor"; + goto err; + } + if (!v4l2_ctrl_new_std(hdlr, &smfc_ctrl_ops, V4L2_CID_JPEG_RESTART_INTERVAL, 0, 64, 1, 0)) { @@ -654,6 +672,7 @@ static int exynos_smfc_open(struct file *filp) ctx->quality_factor = 96; ctx->restart_interval = 0; ctx->thumb_quality_factor = 50; + ctx->enable_hwfc = 0; ctx->smfc = smfc; @@ -1137,6 +1156,27 @@ static void smfc_configure_secondary_image(struct smfc_ctx *ctx) { } +static bool smfc_check_hwfc_configuration(struct smfc_ctx *ctx, bool hwfc_en) +{ + const struct smfc_image_format *fmt = ctx->img_fmt; + if (!(ctx->flags & SMFC_CTX_COMPRESS) || !hwfc_en) + return true; + + if (fmt->chroma_hfactor == 2) { + /* YUV422 1-plane */ + if ((fmt->chroma_vfactor == 1) && (fmt->num_planes != 1)) + return true; + /* YUV420 2-plane */ + if ((fmt->chroma_vfactor == 2) && (fmt->num_planes != 2)) + return true; + } + + dev_err(ctx->smfc->dev, + "HWFC is only available with YUV420-2p and YUV422-1p\n"); + + return false; +} + static void smfc_m2m_device_run(void *priv) { struct smfc_ctx *ctx = priv; @@ -1147,6 +1187,7 @@ static void smfc_m2m_device_run(void *priv) unsigned char restart_interval = ctx->restart_interval; unsigned char quality_factor = ctx->quality_factor; unsigned char thumb_quality_factor = ctx->thumb_quality_factor; + unsigned char enable_hwfc = ctx->enable_hwfc; ret = in_irq() ? pm_runtime_get(ctx->smfc->dev) : pm_runtime_get_sync(ctx->smfc->dev); @@ -1169,6 +1210,9 @@ static void smfc_m2m_device_run(void *priv) goto err_clk; } + if (!smfc_check_hwfc_configuration(ctx, !!enable_hwfc)) + goto err_hwfc; + smfc_hwconfigure_reset(ctx->smfc); smfc_hwconfigure_tables(ctx, quality_factor); smfc_hwconfigure_image(ctx, chroma_hfactor, chroma_vfactor); @@ -1178,14 +1222,19 @@ static void smfc_m2m_device_run(void *priv) smfc_hwconfigure_2nd_tables(ctx, thumb_quality_factor); smfc_hwconfigure_2nd_image(ctx); } - smfc_hwconfigure_start(ctx, restart_interval); + smfc_hwconfigure_start(ctx, restart_interval, !!enable_hwfc); spin_lock_irqsave(&ctx->smfc->flag_lock, flags); ctx->smfc->flags |= SMFC_DEV_RUNNING; spin_unlock_irqrestore(&ctx->smfc->flag_lock, flags); return; - +err_hwfc: + if (!IS_ERR(ctx->smfc->clk_gate)) { + clk_disable(ctx->smfc->clk_gate); + if (!IS_ERR(ctx->smfc->clk_gate2)) + clk_disable(ctx->smfc->clk_gate2); + } err_clk: pm_runtime_put(ctx->smfc->dev); err_pm: diff --git a/drivers/media/platform/exynos/smfc/smfc.h b/drivers/media/platform/exynos/smfc/smfc.h index 52d0a7d44db5..a59e01b6a25c 100644 --- a/drivers/media/platform/exynos/smfc/smfc.h +++ b/drivers/media/platform/exynos/smfc/smfc.h @@ -86,6 +86,7 @@ struct smfc_ctx { __u32 thumb_width; __u32 thumb_height; unsigned char thumb_quality_factor; + unsigned char enable_hwfc; }; static inline struct smfc_ctx *v4l2_fh_to_smfc_ctx(struct v4l2_fh *fh) @@ -110,7 +111,8 @@ static inline bool smfc_is_compressed_type(struct smfc_ctx *ctx, __u32 type) void smfc_hwconfigure_tables(struct smfc_ctx *ctx, unsigned int qfactor); void smfc_hwconfigure_image(struct smfc_ctx *ctx, unsigned int hfactor, unsigned int vfactor); -void smfc_hwconfigure_start(struct smfc_ctx *ctx, unsigned int rst_int); +void smfc_hwconfigure_start(struct smfc_ctx *ctx, + unsigned int rst_int, bool hwfc_en); void smfc_hwconfigure_2nd_tables(struct smfc_ctx *ctx, unsigned int qfactor); void smfc_hwconfigure_2nd_image(struct smfc_ctx *ctx); bool smfc_hwstatus_okay(struct smfc_dev *smfc, struct smfc_ctx *ctx);