aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/media/platform/mtk-vcodec/mtk_vcodec_enc.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/media/platform/mtk-vcodec/mtk_vcodec_enc.c')
-rw-r--r--drivers/media/platform/mtk-vcodec/mtk_vcodec_enc.c211
1 files changed, 99 insertions, 112 deletions
diff --git a/drivers/media/platform/mtk-vcodec/mtk_vcodec_enc.c b/drivers/media/platform/mtk-vcodec/mtk_vcodec_enc.c
index d469ff6464b2..21de1431cfcb 100644
--- a/drivers/media/platform/mtk-vcodec/mtk_vcodec_enc.c
+++ b/drivers/media/platform/mtk-vcodec/mtk_vcodec_enc.c
@@ -23,58 +23,15 @@
#define DFT_CFG_WIDTH MTK_VENC_MIN_W
#define DFT_CFG_HEIGHT MTK_VENC_MIN_H
#define MTK_MAX_CTRLS_HINT 20
-#define OUT_FMT_IDX 0
-#define CAP_FMT_IDX 4
+#define MTK_DEFAULT_FRAMERATE_NUM 1001
+#define MTK_DEFAULT_FRAMERATE_DENOM 30000
static void mtk_venc_worker(struct work_struct *work);
-static const struct mtk_video_fmt mtk_video_formats[] = {
- {
- .fourcc = V4L2_PIX_FMT_NV12M,
- .type = MTK_FMT_FRAME,
- .num_planes = 2,
- },
- {
- .fourcc = V4L2_PIX_FMT_NV21M,
- .type = MTK_FMT_FRAME,
- .num_planes = 2,
- },
- {
- .fourcc = V4L2_PIX_FMT_YUV420M,
- .type = MTK_FMT_FRAME,
- .num_planes = 3,
- },
- {
- .fourcc = V4L2_PIX_FMT_YVU420M,
- .type = MTK_FMT_FRAME,
- .num_planes = 3,
- },
- {
- .fourcc = V4L2_PIX_FMT_H264,
- .type = MTK_FMT_ENC,
- .num_planes = 1,
- },
- {
- .fourcc = V4L2_PIX_FMT_VP8,
- .type = MTK_FMT_ENC,
- .num_planes = 1,
- },
-};
-
-#define NUM_FORMATS ARRAY_SIZE(mtk_video_formats)
-
-static const struct mtk_codec_framesizes mtk_venc_framesizes[] = {
- {
- .fourcc = V4L2_PIX_FMT_H264,
- .stepwise = { MTK_VENC_MIN_W, MTK_VENC_MAX_W, 16,
- MTK_VENC_MIN_H, MTK_VENC_MAX_H, 16 },
- },
- {
- .fourcc = V4L2_PIX_FMT_VP8,
- .stepwise = { MTK_VENC_MIN_W, MTK_VENC_MAX_W, 16,
- MTK_VENC_MIN_H, MTK_VENC_MAX_H, 16 },
- },
+static const struct v4l2_frmsize_stepwise mtk_venc_framesizes = {
+ MTK_VENC_MIN_W, MTK_VENC_MAX_W, 16,
+ MTK_VENC_MIN_H, MTK_VENC_MAX_H, 16,
};
#define NUM_SUPPORTED_FRAMESIZE ARRAY_SIZE(mtk_venc_framesizes)
@@ -156,59 +113,77 @@ static const struct v4l2_ctrl_ops mtk_vcodec_enc_ctrl_ops = {
.s_ctrl = vidioc_venc_s_ctrl,
};
-static int vidioc_enum_fmt(struct v4l2_fmtdesc *f, bool output_queue)
+static int vidioc_enum_fmt(struct v4l2_fmtdesc *f,
+ const struct mtk_video_fmt *formats,
+ size_t num_formats)
+{
+ if (f->index >= num_formats)
+ return -EINVAL;
+
+ f->pixelformat = formats[f->index].fourcc;
+ memset(f->reserved, 0, sizeof(f->reserved));
+
+ return 0;
+}
+
+static const struct mtk_video_fmt *
+mtk_venc_find_format(u32 fourcc, const struct mtk_vcodec_enc_pdata *pdata)
{
const struct mtk_video_fmt *fmt;
- int i, j = 0;
-
- for (i = 0; i < NUM_FORMATS; ++i) {
- if (output_queue && mtk_video_formats[i].type != MTK_FMT_FRAME)
- continue;
- if (!output_queue && mtk_video_formats[i].type != MTK_FMT_ENC)
- continue;
-
- if (j == f->index) {
- fmt = &mtk_video_formats[i];
- f->pixelformat = fmt->fourcc;
- memset(f->reserved, 0, sizeof(f->reserved));
- return 0;
- }
- ++j;
+ unsigned int k;
+
+ for (k = 0; k < pdata->num_capture_formats; k++) {
+ fmt = &pdata->capture_formats[k];
+ if (fmt->fourcc == fourcc)
+ return fmt;
+ }
+
+ for (k = 0; k < pdata->num_output_formats; k++) {
+ fmt = &pdata->output_formats[k];
+ if (fmt->fourcc == fourcc)
+ return fmt;
}
- return -EINVAL;
+ return NULL;
}
static int vidioc_enum_framesizes(struct file *file, void *fh,
struct v4l2_frmsizeenum *fsize)
{
- int i = 0;
+ const struct mtk_video_fmt *fmt;
if (fsize->index != 0)
return -EINVAL;
- for (i = 0; i < NUM_SUPPORTED_FRAMESIZE; ++i) {
- if (fsize->pixel_format != mtk_venc_framesizes[i].fourcc)
- continue;
+ fmt = mtk_venc_find_format(fsize->pixel_format,
+ fh_to_ctx(fh)->dev->venc_pdata);
+ if (!fmt)
+ return -EINVAL;
- fsize->type = V4L2_FRMSIZE_TYPE_STEPWISE;
- fsize->stepwise = mtk_venc_framesizes[i].stepwise;
- return 0;
- }
+ fsize->type = V4L2_FRMSIZE_TYPE_STEPWISE;
+ fsize->stepwise = mtk_venc_framesizes;
- return -EINVAL;
+ return 0;
}
static int vidioc_enum_fmt_vid_cap(struct file *file, void *priv,
struct v4l2_fmtdesc *f)
{
- return vidioc_enum_fmt(f, false);
+ const struct mtk_vcodec_enc_pdata *pdata =
+ fh_to_ctx(priv)->dev->venc_pdata;
+
+ return vidioc_enum_fmt(f, pdata->capture_formats,
+ pdata->num_capture_formats);
}
static int vidioc_enum_fmt_vid_out(struct file *file, void *priv,
struct v4l2_fmtdesc *f)
{
- return vidioc_enum_fmt(f, true);
+ const struct mtk_vcodec_enc_pdata *pdata =
+ fh_to_ctx(priv)->dev->venc_pdata;
+
+ return vidioc_enum_fmt(f, pdata->output_formats,
+ pdata->num_output_formats);
}
static int vidioc_venc_querycap(struct file *file, void *priv,
@@ -225,14 +200,18 @@ static int vidioc_venc_s_parm(struct file *file, void *priv,
struct v4l2_streamparm *a)
{
struct mtk_vcodec_ctx *ctx = fh_to_ctx(priv);
+ struct v4l2_fract *timeperframe = &a->parm.output.timeperframe;
if (a->type != V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE)
return -EINVAL;
- ctx->enc_params.framerate_num =
- a->parm.output.timeperframe.denominator;
- ctx->enc_params.framerate_denom =
- a->parm.output.timeperframe.numerator;
+ if (timeperframe->numerator == 0 || timeperframe->denominator == 0) {
+ timeperframe->numerator = MTK_DEFAULT_FRAMERATE_NUM;
+ timeperframe->denominator = MTK_DEFAULT_FRAMERATE_DENOM;
+ }
+
+ ctx->enc_params.framerate_num = timeperframe->denominator;
+ ctx->enc_params.framerate_denom = timeperframe->numerator;
ctx->param_change |= MTK_ENCODE_PARAM_FRAMERATE;
a->parm.output.capability = V4L2_CAP_TIMEPERFRAME;
@@ -266,20 +245,6 @@ static struct mtk_q_data *mtk_venc_get_q_data(struct mtk_vcodec_ctx *ctx,
return &ctx->q_data[MTK_Q_DATA_DST];
}
-static const struct mtk_video_fmt *mtk_venc_find_format(struct v4l2_format *f)
-{
- const struct mtk_video_fmt *fmt;
- unsigned int k;
-
- for (k = 0; k < NUM_FORMATS; k++) {
- fmt = &mtk_video_formats[k];
- if (fmt->fourcc == f->fmt.pix.pixelformat)
- return fmt;
- }
-
- return NULL;
-}
-
/* V4L2 specification suggests the driver corrects the format struct if any of
* the dimensions is unsupported
*/
@@ -332,12 +297,14 @@ static int vidioc_try_fmt(struct v4l2_format *f,
pix_fmt_mp->num_planes = fmt->num_planes;
pix_fmt_mp->plane_fmt[0].sizeimage =
- pix_fmt_mp->width * pix_fmt_mp->height;
+ pix_fmt_mp->width * pix_fmt_mp->height +
+ ((ALIGN(pix_fmt_mp->width, 16) * 2) * 16);
pix_fmt_mp->plane_fmt[0].bytesperline = pix_fmt_mp->width;
if (pix_fmt_mp->num_planes == 2) {
pix_fmt_mp->plane_fmt[1].sizeimage =
- (pix_fmt_mp->width * pix_fmt_mp->height) / 2;
+ (pix_fmt_mp->width * pix_fmt_mp->height) / 2 +
+ (ALIGN(pix_fmt_mp->width, 16) * 16);
pix_fmt_mp->plane_fmt[2].sizeimage = 0;
pix_fmt_mp->plane_fmt[1].bytesperline =
pix_fmt_mp->width;
@@ -345,7 +312,8 @@ static int vidioc_try_fmt(struct v4l2_format *f,
} else if (pix_fmt_mp->num_planes == 3) {
pix_fmt_mp->plane_fmt[1].sizeimage =
pix_fmt_mp->plane_fmt[2].sizeimage =
- (pix_fmt_mp->width * pix_fmt_mp->height) / 4;
+ (pix_fmt_mp->width * pix_fmt_mp->height) / 4 +
+ ((ALIGN(pix_fmt_mp->width, 16) / 2) * 16);
pix_fmt_mp->plane_fmt[1].bytesperline =
pix_fmt_mp->plane_fmt[2].bytesperline =
pix_fmt_mp->width / 2;
@@ -414,6 +382,7 @@ static int vidioc_venc_s_fmt_cap(struct file *file, void *priv,
struct v4l2_format *f)
{
struct mtk_vcodec_ctx *ctx = fh_to_ctx(priv);
+ const struct mtk_vcodec_enc_pdata *pdata = ctx->dev->venc_pdata;
struct vb2_queue *vq;
struct mtk_q_data *q_data;
int i, ret;
@@ -436,10 +405,10 @@ static int vidioc_venc_s_fmt_cap(struct file *file, void *priv,
return -EINVAL;
}
- fmt = mtk_venc_find_format(f);
+ fmt = mtk_venc_find_format(f->fmt.pix.pixelformat, pdata);
if (!fmt) {
- f->fmt.pix.pixelformat = mtk_video_formats[CAP_FMT_IDX].fourcc;
- fmt = mtk_venc_find_format(f);
+ fmt = &ctx->dev->venc_pdata->capture_formats[0];
+ f->fmt.pix.pixelformat = fmt->fourcc;
}
q_data->fmt = fmt;
@@ -476,6 +445,7 @@ static int vidioc_venc_s_fmt_out(struct file *file, void *priv,
struct v4l2_format *f)
{
struct mtk_vcodec_ctx *ctx = fh_to_ctx(priv);
+ const struct mtk_vcodec_enc_pdata *pdata = ctx->dev->venc_pdata;
struct vb2_queue *vq;
struct mtk_q_data *q_data;
int ret, i;
@@ -499,10 +469,10 @@ static int vidioc_venc_s_fmt_out(struct file *file, void *priv,
return -EINVAL;
}
- fmt = mtk_venc_find_format(f);
+ fmt = mtk_venc_find_format(f->fmt.pix.pixelformat, pdata);
if (!fmt) {
- f->fmt.pix.pixelformat = mtk_video_formats[OUT_FMT_IDX].fourcc;
- fmt = mtk_venc_find_format(f);
+ fmt = &ctx->dev->venc_pdata->output_formats[0];
+ f->fmt.pix.pixelformat = fmt->fourcc;
}
pix_fmt_mp->height = clamp(pix_fmt_mp->height,
@@ -580,11 +550,12 @@ static int vidioc_try_fmt_vid_cap_mplane(struct file *file, void *priv,
{
const struct mtk_video_fmt *fmt;
struct mtk_vcodec_ctx *ctx = fh_to_ctx(priv);
+ const struct mtk_vcodec_enc_pdata *pdata = ctx->dev->venc_pdata;
- fmt = mtk_venc_find_format(f);
+ fmt = mtk_venc_find_format(f->fmt.pix.pixelformat, pdata);
if (!fmt) {
- f->fmt.pix.pixelformat = mtk_video_formats[CAP_FMT_IDX].fourcc;
- fmt = mtk_venc_find_format(f);
+ fmt = &ctx->dev->venc_pdata->capture_formats[0];
+ f->fmt.pix.pixelformat = fmt->fourcc;
}
f->fmt.pix_mp.colorspace = ctx->colorspace;
f->fmt.pix_mp.ycbcr_enc = ctx->ycbcr_enc;
@@ -598,11 +569,13 @@ static int vidioc_try_fmt_vid_out_mplane(struct file *file, void *priv,
struct v4l2_format *f)
{
const struct mtk_video_fmt *fmt;
+ struct mtk_vcodec_ctx *ctx = fh_to_ctx(priv);
+ const struct mtk_vcodec_enc_pdata *pdata = ctx->dev->venc_pdata;
- fmt = mtk_venc_find_format(f);
+ fmt = mtk_venc_find_format(f->fmt.pix.pixelformat, pdata);
if (!fmt) {
- f->fmt.pix.pixelformat = mtk_video_formats[OUT_FMT_IDX].fourcc;
- fmt = mtk_venc_find_format(f);
+ fmt = &ctx->dev->venc_pdata->output_formats[0];
+ f->fmt.pix.pixelformat = fmt->fourcc;
}
if (!f->fmt.pix_mp.colorspace) {
f->fmt.pix_mp.colorspace = V4L2_COLORSPACE_REC709;
@@ -918,8 +891,17 @@ static void vb2ops_venc_stop_streaming(struct vb2_queue *q)
ctx->state = MTK_STATE_FREE;
}
+static int vb2ops_venc_buf_out_validate(struct vb2_buffer *vb)
+{
+ struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb);
+
+ vbuf->field = V4L2_FIELD_NONE;
+ return 0;
+}
+
static const struct vb2_ops mtk_venc_vb2_ops = {
.queue_setup = vb2ops_venc_queue_setup,
+ .buf_out_validate = vb2ops_venc_buf_out_validate,
.buf_prepare = vb2ops_venc_buf_prepare,
.buf_queue = vb2ops_venc_buf_queue,
.wait_prepare = vb2_ops_wait_prepare,
@@ -1187,7 +1169,7 @@ void mtk_vcodec_enc_set_default_params(struct mtk_vcodec_ctx *ctx)
q_data->coded_height = DFT_CFG_HEIGHT;
q_data->field = V4L2_FIELD_NONE;
- q_data->fmt = &mtk_video_formats[OUT_FMT_IDX];
+ q_data->fmt = &ctx->dev->venc_pdata->output_formats[0];
v4l_bound_align_image(&q_data->coded_width,
MTK_VENC_MIN_W,
@@ -1216,12 +1198,14 @@ void mtk_vcodec_enc_set_default_params(struct mtk_vcodec_ctx *ctx)
memset(q_data, 0, sizeof(struct mtk_q_data));
q_data->coded_width = DFT_CFG_WIDTH;
q_data->coded_height = DFT_CFG_HEIGHT;
- q_data->fmt = &mtk_video_formats[CAP_FMT_IDX];
+ q_data->fmt = &ctx->dev->venc_pdata->capture_formats[0];
q_data->field = V4L2_FIELD_NONE;
ctx->q_data[MTK_Q_DATA_DST].sizeimage[0] =
DFT_CFG_WIDTH * DFT_CFG_HEIGHT;
ctx->q_data[MTK_Q_DATA_DST].bytesperline[0] = 0;
+ ctx->enc_params.framerate_num = MTK_DEFAULT_FRAMERATE_NUM;
+ ctx->enc_params.framerate_denom = MTK_DEFAULT_FRAMERATE_DENOM;
}
int mtk_vcodec_enc_ctrls_setup(struct mtk_vcodec_ctx *ctx)
@@ -1231,8 +1215,11 @@ int mtk_vcodec_enc_ctrls_setup(struct mtk_vcodec_ctx *ctx)
v4l2_ctrl_handler_init(handler, MTK_MAX_CTRLS_HINT);
+ v4l2_ctrl_new_std(handler, ops, V4L2_CID_MIN_BUFFERS_FOR_OUTPUT,
+ 1, 1, 1, 1);
v4l2_ctrl_new_std(handler, ops, V4L2_CID_MPEG_VIDEO_BITRATE,
- 1, 4000000, 1, 4000000);
+ ctx->dev->venc_pdata->min_bitrate,
+ ctx->dev->venc_pdata->max_bitrate, 1, 4000000);
v4l2_ctrl_new_std(handler, ops, V4L2_CID_MPEG_VIDEO_B_FRAMES,
0, 2, 1, 0);
v4l2_ctrl_new_std(handler, ops, V4L2_CID_MPEG_VIDEO_FRAME_RC_ENABLE,