/* [hfactor - 1][vfactor - 1]: 444, 422V, 422, 420 */
static u32 smfc_get_jpeg_format(unsigned int hfactor, unsigned int vfactor)
{
- static unsigned char jpeg_regfmt[2][2] = { {1, 4}, {2, 3} };
- return jpeg_regfmt[hfactor - 1][vfactor - 1] << 24;
+ switch ((hfactor << 4) | vfactor) {
+ case 0x00: return 0 << 24;
+ case 0x11: return 1 << 24;
+ case 0x21: return 2 << 24;
+ case 0x22: return 3 << 24;
+ case 0x12: return 4 << 24;
+ case 0x41: return 5 << 24;
+ }
+
+ return 2 << 24; /* default: YUV422 */
}
void smfc_hwconfigure_image(struct smfc_ctx *ctx)
cfg |= 1 << 19; /* update huffman table from SFR */
cfg |= 1 << 28; /* enables interrupt */
cfg |= 1 << 29; /* Release reset */
+ if (ctx->restart_interval != 0)
+ cfg |= (ctx->restart_interval << 3) | (1 << 2);
writel(cfg, base + REG_JPEG_CNTL);
}
#include <linux/mutex.h>
#include <linux/exynos_iovmm.h>
-#include <media/v4l2-ioctl.h>
-#include <media/v4l2-device.h>
-#include <media/v4l2-mem2mem.h>
#include <media/videobuf2-core.h>
#include <media/videobuf2-dma-sg.h>
return vb2_queue_init(dst_vq);
}
+static int smfc_s_ctrl(struct v4l2_ctrl *ctrl)
+{
+ struct smfc_ctx *ctx = container_of(ctrl->handler,
+ struct smfc_ctx, v4l2_ctrlhdlr);
+ switch (ctrl->id) {
+ case V4L2_CID_JPEG_COMPRESSION_QUALITY:
+ ctx->quality_factor = (unsigned char)ctrl->val;
+ break;
+ case V4L2_CID_JPEG_RESTART_INTERVAL:
+ ctx->restart_interval = (unsigned char)ctrl->val;
+ break;
+ case V4L2_CID_JPEG_CHROMA_SUBSAMPLING:
+ switch (ctrl->val) {
+ case V4L2_JPEG_CHROMA_SUBSAMPLING_444:
+ ctx->chroma_hfactor = 1;
+ ctx->chroma_vfactor = 1;
+ break;
+ case V4L2_JPEG_CHROMA_SUBSAMPLING_420:
+ ctx->chroma_hfactor = 2;
+ ctx->chroma_vfactor = 2;
+ break;
+ case V4L2_JPEG_CHROMA_SUBSAMPLING_411:
+ ctx->chroma_hfactor = 4;
+ ctx->chroma_vfactor = 1;
+ break;
+ case V4L2_JPEG_CHROMA_SUBSAMPLING_GRAY:
+ ctx->chroma_hfactor = 0;
+ ctx->chroma_vfactor = 0;
+ break;
+ case V4L2_JPEG_CHROMA_SUBSAMPLING_410:
+ dev_info(ctx->smfc->dev,
+ "Compression to YUV410 is not supported\n");
+ /* pass through to 422 */
+ case V4L2_JPEG_CHROMA_SUBSAMPLING_422:
+ default:
+ ctx->chroma_hfactor = 2;
+ ctx->chroma_vfactor = 1;
+ break;
+ }
+ break;
+ default:
+ break;
+ }
+
+ return 0;
+}
+
+static const struct v4l2_ctrl_ops smfc_ctrl_ops = {
+ .s_ctrl = smfc_s_ctrl,
+};
+
+static int smfc_init_controls(struct smfc_dev *smfc,
+ struct v4l2_ctrl_handler *hdlr)
+{
+ const char *msg;
+
+ v4l2_ctrl_handler_init(hdlr, 1);
+
+ if (!v4l2_ctrl_new_std(hdlr, &smfc_ctrl_ops,
+ V4L2_CID_JPEG_COMPRESSION_QUALITY,
+ 1, 100, 1, 96)) {
+ msg = "quality factor";
+ goto err;
+ }
+
+ if (!v4l2_ctrl_new_std(hdlr, &smfc_ctrl_ops,
+ V4L2_CID_JPEG_RESTART_INTERVAL,
+ 0, 64, 1, 0)) {
+ msg = "restart interval";
+ goto err;
+ }
+
+ if (!v4l2_ctrl_new_std_menu(hdlr, &smfc_ctrl_ops,
+ V4L2_CID_JPEG_CHROMA_SUBSAMPLING,
+ V4L2_JPEG_CHROMA_SUBSAMPLING_GRAY, 0,
+ V4L2_JPEG_CHROMA_SUBSAMPLING_422)) {
+ msg = "chroma subsampling";
+ goto err;
+ }
+
+ return 0;
+err:
+ dev_err(smfc->dev, "Failed to install %s control (%d)\n",
+ msg, hdlr->error);
+ return hdlr->error;
+}
+
static int exynos_smfc_open(struct file *filp)
{
struct smfc_dev *smfc = video_drvdata(filp);
goto err_m2m_ctx_init;
}
-
v4l2_fh_init(&ctx->v4l2_fh, smfc->videodev);
+
+ ret = smfc_init_controls(smfc, &ctx->v4l2_ctrlhdlr);
+ if (ret)
+ goto err_control;
+
+ ctx->v4l2_fh.ctrl_handler = &ctx->v4l2_ctrlhdlr;
+
v4l2_fh_add(&ctx->v4l2_fh);
filp->private_data = &ctx->v4l2_fh;
ctx->chroma_vfactor = ctx->img_fmt->chroma_vfactor;
ctx->flags |= SMFC_CTX_COMPRESS;
ctx->quality_factor = 96;
+ ctx->restart_interval = 0;
ctx->smfc = smfc;
v4l2_fh_del(&ctx->v4l2_fh);
v4l2_fh_exit(&ctx->v4l2_fh);
v4l2_m2m_ctx_release(ctx->m2mctx);
+err_control:
err_m2m_ctx_init:
kfree(ctx);
return ret;
#ifndef _MEDIA_EXYNOS_SMFC_H_
#define _MEDIA_EXYNOS_SMFC_H_
+#include <media/v4l2-ioctl.h>
+#include <media/v4l2-device.h>
+#include <media/v4l2-mem2mem.h>
+#include <media/v4l2-ctrls.h>
+
#include "smfc-regs.h"
#define MODULE_NAME "exynos-jpeg"
struct smfc_ctx {
struct v4l2_fh v4l2_fh;
+ struct v4l2_ctrl_handler v4l2_ctrlhdlr;
struct smfc_dev *smfc;
struct v4l2_m2m_ctx *m2mctx;
u32 flags;
/* JPEG chroma subsampling factors */
unsigned char chroma_hfactor;
unsigned char chroma_vfactor;
- unsigned int quality_factor;
+ unsigned char restart_interval;
+ unsigned char quality_factor;
};
static inline struct smfc_ctx *v4l2_fh_to_smfc_ctx(struct v4l2_fh *fh)