[COMMON] media: smfc: add support for HWFC configuration
authorCho KyongHo <pullip.cho@samsung.com>
Mon, 4 May 2015 06:13:32 +0000 (15:13 +0900)
committerSeungchul Kim <sc377.kim@samsung.com>
Mon, 28 May 2018 05:30:58 +0000 (14:30 +0900)
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 <pullip.cho@samsung.com>
drivers/media/platform/exynos/smfc/smfc-regs.c
drivers/media/platform/exynos/smfc/smfc.c
drivers/media/platform/exynos/smfc/smfc.h

index d76dc0440f01fea080959465df8136955216b944..ff24f3147ee7c345830b0b3105e8800ec336cc6b 100644 (file)
@@ -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))
index 1708c9d215db19b54a76b9d2e1fcb64c9dbd7e5d..26775a031a2c779b348e68472055fcba52834856 100644 (file)
@@ -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:
index 52d0a7d44db5228ddecb2d3d96c802537675478e..a59e01b6a25c8a9f7029f4dc756eb6558e763742 100644 (file)
@@ -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);