media: coda: use encoder crop rectangle to set visible width and height
authorPhilipp Zabel <p.zabel@pengutronix.de>
Thu, 28 Jun 2018 10:57:54 +0000 (06:57 -0400)
committerMauro Carvalho Chehab <mchehab+samsung@kernel.org>
Wed, 25 Jul 2018 12:30:25 +0000 (08:30 -0400)
Allow to set a crop rectangle on the encoder output queue to set the
visible resolution as required by the V4L2 codec API.

Signed-off-by: Philipp Zabel <p.zabel@pengutronix.de>
Signed-off-by: Hans Verkuil <hans.verkuil@cisco.com>
Signed-off-by: Mauro Carvalho Chehab <mchehab+samsung@kernel.org>
drivers/media/platform/coda/coda-bit.c
drivers/media/platform/coda/coda-common.c

index bf8d848..529fc18 100644 (file)
@@ -398,10 +398,10 @@ static int coda_alloc_framebuffers(struct coda_ctx *ctx,
            ctx->codec->dst_fourcc == V4L2_PIX_FMT_H264 ||
            ctx->codec->src_fourcc == V4L2_PIX_FMT_MPEG4 ||
            ctx->codec->dst_fourcc == V4L2_PIX_FMT_MPEG4)
-               ysize = round_up(q_data->width, 16) *
-                       round_up(q_data->height, 16);
+               ysize = round_up(q_data->rect.width, 16) *
+                       round_up(q_data->rect.height, 16);
        else
-               ysize = round_up(q_data->width, 8) * q_data->height;
+               ysize = round_up(q_data->rect.width, 8) * q_data->rect.height;
 
        if (ctx->tiled_map_type == GDI_TILED_FRAME_MB_RASTER_MAP)
                ycbcr_size = round_up(ysize, 4096) + ysize / 2;
@@ -497,8 +497,8 @@ static int coda_alloc_context_buffers(struct coda_ctx *ctx,
 
        if (!ctx->slicebuf.vaddr && q_data->fourcc == V4L2_PIX_FMT_H264) {
                /* worst case slice size */
-               size = (DIV_ROUND_UP(q_data->width, 16) *
-                       DIV_ROUND_UP(q_data->height, 16)) * 3200 / 8 + 512;
+               size = (DIV_ROUND_UP(q_data->rect.width, 16) *
+                       DIV_ROUND_UP(q_data->rect.height, 16)) * 3200 / 8 + 512;
                ret = coda_alloc_context_buf(ctx, &ctx->slicebuf, size,
                                             "slicebuf");
                if (ret < 0)
@@ -630,7 +630,7 @@ static void coda_setup_iram(struct coda_ctx *ctx)
                struct coda_q_data *q_data_src;
 
                q_data_src = get_q_data(ctx, V4L2_BUF_TYPE_VIDEO_OUTPUT);
-               mb_width = DIV_ROUND_UP(q_data_src->width, 16);
+               mb_width = DIV_ROUND_UP(q_data_src->rect.width, 16);
                w128 = mb_width * 128;
                w64 = mb_width * 64;
 
@@ -927,25 +927,25 @@ static int coda_start_encoding(struct coda_ctx *ctx)
        value = 0;
        switch (dev->devtype->product) {
        case CODA_DX6:
-               value = (q_data_src->width & CODADX6_PICWIDTH_MASK)
+               value = (q_data_src->rect.width & CODADX6_PICWIDTH_MASK)
                        << CODADX6_PICWIDTH_OFFSET;
-               value |= (q_data_src->height & CODADX6_PICHEIGHT_MASK)
+               value |= (q_data_src->rect.height & CODADX6_PICHEIGHT_MASK)
                         << CODA_PICHEIGHT_OFFSET;
                break;
        case CODA_HX4:
        case CODA_7541:
                if (dst_fourcc == V4L2_PIX_FMT_H264) {
-                       value = (round_up(q_data_src->width, 16) &
+                       value = (round_up(q_data_src->rect.width, 16) &
                                 CODA7_PICWIDTH_MASK) << CODA7_PICWIDTH_OFFSET;
-                       value |= (round_up(q_data_src->height, 16) &
+                       value |= (round_up(q_data_src->rect.height, 16) &
                                 CODA7_PICHEIGHT_MASK) << CODA_PICHEIGHT_OFFSET;
                        break;
                }
                /* fallthrough */
        case CODA_960:
-               value = (q_data_src->width & CODA7_PICWIDTH_MASK)
+               value = (q_data_src->rect.width & CODA7_PICWIDTH_MASK)
                        << CODA7_PICWIDTH_OFFSET;
-               value |= (q_data_src->height & CODA7_PICHEIGHT_MASK)
+               value |= (q_data_src->rect.height & CODA7_PICHEIGHT_MASK)
                         << CODA_PICHEIGHT_OFFSET;
        }
        coda_write(dev, value, CODA_CMD_ENC_SEQ_SRC_SIZE);
index f25f141..726b3b9 100644 (file)
@@ -933,6 +933,40 @@ static int coda_g_selection(struct file *file, void *fh,
        return 0;
 }
 
+static int coda_s_selection(struct file *file, void *fh,
+                           struct v4l2_selection *s)
+{
+       struct coda_ctx *ctx = fh_to_ctx(fh);
+       struct coda_q_data *q_data;
+
+       if (ctx->inst_type == CODA_INST_ENCODER &&
+           s->type == V4L2_BUF_TYPE_VIDEO_OUTPUT &&
+           s->target == V4L2_SEL_TGT_CROP) {
+               q_data = get_q_data(ctx, s->type);
+               if (!q_data)
+                       return -EINVAL;
+
+               s->r.left = 0;
+               s->r.top = 0;
+               s->r.width = clamp(s->r.width, 2U, q_data->width);
+               s->r.height = clamp(s->r.height, 2U, q_data->height);
+
+               if (s->flags & V4L2_SEL_FLAG_LE) {
+                       s->r.width = round_up(s->r.width, 2);
+                       s->r.height = round_up(s->r.height, 2);
+               } else {
+                       s->r.width = round_down(s->r.width, 2);
+                       s->r.height = round_down(s->r.height, 2);
+               }
+
+               q_data->rect = s->r;
+
+               return 0;
+       }
+
+       return coda_g_selection(file, fh, s);
+}
+
 static int coda_try_encoder_cmd(struct file *file, void *fh,
                                struct v4l2_encoder_cmd *ec)
 {
@@ -1146,6 +1180,7 @@ static const struct v4l2_ioctl_ops coda_ioctl_ops = {
        .vidioc_streamoff       = v4l2_m2m_ioctl_streamoff,
 
        .vidioc_g_selection     = coda_g_selection,
+       .vidioc_s_selection     = coda_s_selection,
 
        .vidioc_try_encoder_cmd = coda_try_encoder_cmd,
        .vidioc_encoder_cmd     = coda_encoder_cmd,
@@ -1587,12 +1622,12 @@ static int coda_start_streaming(struct vb2_queue *q, unsigned int count)
                goto out;
 
        q_data_dst = get_q_data(ctx, V4L2_BUF_TYPE_VIDEO_CAPTURE);
-       if ((q_data_src->width != q_data_dst->width &&
-            round_up(q_data_src->width, 16) != q_data_dst->width) ||
-           (q_data_src->height != q_data_dst->height &&
-            round_up(q_data_src->height, 16) != q_data_dst->height)) {
+       if ((q_data_src->rect.width != q_data_dst->width &&
+            round_up(q_data_src->rect.width, 16) != q_data_dst->width) ||
+           (q_data_src->rect.height != q_data_dst->height &&
+            round_up(q_data_src->rect.height, 16) != q_data_dst->height)) {
                v4l2_err(v4l2_dev, "can't convert %dx%d to %dx%d\n",
-                        q_data_src->width, q_data_src->height,
+                        q_data_src->rect.width, q_data_src->rect.height,
                         q_data_dst->width, q_data_dst->height);
                ret = -EINVAL;
                goto err;