X-Git-Url: http://git.openwrt.org/?a=blobdiff_plain;f=target%2Flinux%2Fbrcm2708%2Fpatches-4.19%2F950-0648-staging-bcm2835-codec-switch-to-multi-planar-API.patch;fp=target%2Flinux%2Fbrcm2708%2Fpatches-4.19%2F950-0648-staging-bcm2835-codec-switch-to-multi-planar-API.patch;h=ce590c96451f472757d3f7f033cde58b8dc3a87e;hb=84d555aa74434392b682fd9eb0fa701c89a046d6;hp=0000000000000000000000000000000000000000;hpb=953973c2991e8640549a55df7a0574a1abac8644;p=openwrt%2Fopenwrt.git diff --git a/target/linux/brcm2708/patches-4.19/950-0648-staging-bcm2835-codec-switch-to-multi-planar-API.patch b/target/linux/brcm2708/patches-4.19/950-0648-staging-bcm2835-codec-switch-to-multi-planar-API.patch new file mode 100644 index 0000000000..ce590c9645 --- /dev/null +++ b/target/linux/brcm2708/patches-4.19/950-0648-staging-bcm2835-codec-switch-to-multi-planar-API.patch @@ -0,0 +1,351 @@ +From cb053a15c5c23e775647d6b65fef4c378bf34b5b Mon Sep 17 00:00:00 2001 +From: Chen-Yu Tsai +Date: Thu, 18 Jul 2019 17:07:05 +0800 +Subject: [PATCH] staging: bcm2835-codec: switch to multi-planar API + +There are two APIs for mem2mem devices, the older single-planar API and +the newer multi-planar one. Without making things overly complex, the +driver can only support one or the other. However the userspace libv4l2 +library has a plugin that allows multi-planar API devices to service +single-planar consumers. + +Chromium supports the multi-planar API exclusively, though this is +currently limited to ChromiumOS. It would be possible to add support +for generic Linux. + +Switching to the multi-planar API would allow usage of both APIs from +userspace. + +Signed-off-by: Chen-Yu Tsai +--- + .../bcm2835-codec/bcm2835-v4l2-codec.c | 145 +++++++++--------- + 1 file changed, 76 insertions(+), 69 deletions(-) + +--- a/drivers/staging/vc04_services/bcm2835-codec/bcm2835-v4l2-codec.c ++++ b/drivers/staging/vc04_services/bcm2835-codec/bcm2835-v4l2-codec.c +@@ -504,7 +504,7 @@ static struct bcm2835_codec_fmt *find_fo + + for (k = 0; k < fmts->num_entries; k++) { + fmt = &fmts->list[k]; +- if (fmt->fourcc == f->fmt.pix.pixelformat) ++ if (fmt->fourcc == f->fmt.pix_mp.pixelformat) + break; + } + if (k == fmts->num_entries) +@@ -522,9 +522,9 @@ static struct bcm2835_codec_q_data *get_ + enum v4l2_buf_type type) + { + switch (type) { +- case V4L2_BUF_TYPE_VIDEO_OUTPUT: ++ case V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE: + return &ctx->q_data[V4L2_M2M_SRC]; +- case V4L2_BUF_TYPE_VIDEO_CAPTURE: ++ case V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE: + return &ctx->q_data[V4L2_M2M_DST]; + default: + v4l2_err(&ctx->dev->v4l2_dev, "%s: Invalid queue type %u\n", +@@ -541,9 +541,9 @@ static struct vchiq_mmal_port *get_port_ + return NULL; + + switch (type) { +- case V4L2_BUF_TYPE_VIDEO_OUTPUT: ++ case V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE: + return &ctx->component->input[0]; +- case V4L2_BUF_TYPE_VIDEO_CAPTURE: ++ case V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE: + return &ctx->component->output[0]; + default: + v4l2_err(&ctx->dev->v4l2_dev, "%s: Invalid queue type %u\n", +@@ -752,7 +752,7 @@ static void handle_fmt_changed(struct bc + format->es.video.crop.width, format->es.video.crop.height, + format->es.video.color_space); + +- q_data = get_q_data(ctx, V4L2_BUF_TYPE_VIDEO_CAPTURE); ++ q_data = get_q_data(ctx, V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE); + q_data->crop_width = format->es.video.crop.width; + q_data->crop_height = format->es.video.crop.height; + q_data->bytesperline = format->es.video.crop.width; +@@ -945,7 +945,7 @@ static int vidioc_querycap(struct file * + strncpy(cap->card, MEM2MEM_NAME, sizeof(cap->card) - 1); + snprintf(cap->bus_info, sizeof(cap->bus_info), "platform:%s", + MEM2MEM_NAME); +- cap->device_caps = V4L2_CAP_VIDEO_M2M | V4L2_CAP_STREAMING; ++ cap->device_caps = V4L2_CAP_VIDEO_M2M_MPLANE | V4L2_CAP_STREAMING; + cap->capabilities = cap->device_caps | V4L2_CAP_DEVICE_CAPS; + return 0; + } +@@ -996,16 +996,20 @@ static int vidioc_g_fmt(struct bcm2835_c + + q_data = get_q_data(ctx, f->type); + +- f->fmt.pix.width = q_data->crop_width; +- f->fmt.pix.height = q_data->height; +- f->fmt.pix.field = V4L2_FIELD_NONE; +- f->fmt.pix.pixelformat = q_data->fmt->fourcc; +- f->fmt.pix.bytesperline = q_data->bytesperline; +- f->fmt.pix.sizeimage = q_data->sizeimage; +- f->fmt.pix.colorspace = ctx->colorspace; +- f->fmt.pix.xfer_func = ctx->xfer_func; +- f->fmt.pix.ycbcr_enc = ctx->ycbcr_enc; +- f->fmt.pix.quantization = ctx->quant; ++ f->fmt.pix_mp.width = q_data->crop_width; ++ f->fmt.pix_mp.height = q_data->height; ++ f->fmt.pix_mp.pixelformat = q_data->fmt->fourcc; ++ f->fmt.pix_mp.field = V4L2_FIELD_NONE; ++ f->fmt.pix_mp.colorspace = ctx->colorspace; ++ f->fmt.pix_mp.plane_fmt[0].sizeimage = q_data->sizeimage; ++ f->fmt.pix_mp.plane_fmt[0].bytesperline = q_data->bytesperline; ++ f->fmt.pix_mp.num_planes = 1; ++ f->fmt.pix_mp.ycbcr_enc = ctx->ycbcr_enc; ++ f->fmt.pix_mp.quantization = ctx->quant; ++ f->fmt.pix_mp.xfer_func = ctx->xfer_func; ++ ++ memset(f->fmt.pix_mp.plane_fmt[0].reserved, 0, ++ sizeof(f->fmt.pix_mp.plane_fmt[0].reserved)); + + return 0; + } +@@ -1029,17 +1033,17 @@ static int vidioc_try_fmt(struct bcm2835 + * The V4L2 specification requires the driver to correct the format + * struct if any of the dimensions is unsupported + */ +- if (f->fmt.pix.width > MAX_W) +- f->fmt.pix.width = MAX_W; +- if (f->fmt.pix.height > MAX_H) +- f->fmt.pix.height = MAX_H; ++ if (f->fmt.pix_mp.width > MAX_W) ++ f->fmt.pix_mp.width = MAX_W; ++ if (f->fmt.pix_mp.height > MAX_H) ++ f->fmt.pix_mp.height = MAX_H; + + if (!fmt->flags & V4L2_FMT_FLAG_COMPRESSED) { + /* Only clip min w/h on capture. Treat 0x0 as unknown. */ +- if (f->fmt.pix.width < MIN_W) +- f->fmt.pix.width = MIN_W; +- if (f->fmt.pix.height < MIN_H) +- f->fmt.pix.height = MIN_H; ++ if (f->fmt.pix_mp.width < MIN_W) ++ f->fmt.pix_mp.width = MIN_W; ++ if (f->fmt.pix_mp.height < MIN_H) ++ f->fmt.pix_mp.height = MIN_H; + + /* + * For codecs the buffer must have a vertical alignment of 16 +@@ -1048,16 +1052,18 @@ static int vidioc_try_fmt(struct bcm2835 + * some of the pixels are active. + */ + if (ctx->dev->role != ISP) +- f->fmt.pix.height = ALIGN(f->fmt.pix.height, 16); ++ f->fmt.pix_mp.height = ALIGN(f->fmt.pix_mp.height, 16); + } +- f->fmt.pix.bytesperline = get_bytesperline(f->fmt.pix.width, +- fmt); +- f->fmt.pix.sizeimage = get_sizeimage(f->fmt.pix.bytesperline, +- f->fmt.pix.width, +- f->fmt.pix.height, +- fmt); ++ f->fmt.pix_mp.num_planes = 1; ++ f->fmt.pix_mp.plane_fmt[0].bytesperline = ++ get_bytesperline(f->fmt.pix_mp.width, fmt); ++ f->fmt.pix_mp.plane_fmt[0].sizeimage = ++ get_sizeimage(f->fmt.pix_mp.plane_fmt[0].bytesperline, ++ f->fmt.pix_mp.width, f->fmt.pix_mp.height, fmt); ++ memset(f->fmt.pix_mp.plane_fmt[0].reserved, 0, ++ sizeof(f->fmt.pix_mp.plane_fmt[0].reserved)); + +- f->fmt.pix.field = V4L2_FIELD_NONE; ++ f->fmt.pix_mp.field = V4L2_FIELD_NONE; + + return 0; + } +@@ -1070,8 +1076,8 @@ static int vidioc_try_fmt_vid_cap(struct + + fmt = find_format(f, ctx->dev, true); + if (!fmt) { +- f->fmt.pix.pixelformat = get_default_format(ctx->dev, +- true)->fourcc; ++ f->fmt.pix_mp.pixelformat = get_default_format(ctx->dev, ++ true)->fourcc; + fmt = find_format(f, ctx->dev, true); + } + +@@ -1086,13 +1092,13 @@ static int vidioc_try_fmt_vid_out(struct + + fmt = find_format(f, ctx->dev, false); + if (!fmt) { +- f->fmt.pix.pixelformat = get_default_format(ctx->dev, +- false)->fourcc; ++ f->fmt.pix_mp.pixelformat = get_default_format(ctx->dev, ++ false)->fourcc; + fmt = find_format(f, ctx->dev, false); + } + +- if (!f->fmt.pix.colorspace) +- f->fmt.pix.colorspace = ctx->colorspace; ++ if (!f->fmt.pix_mp.colorspace) ++ f->fmt.pix_mp.colorspace = ctx->colorspace; + + return vidioc_try_fmt(ctx, f, fmt); + } +@@ -1106,9 +1112,10 @@ static int vidioc_s_fmt(struct bcm2835_c + bool update_capture_port = false; + int ret; + +- v4l2_dbg(1, debug, &ctx->dev->v4l2_dev, "Setting format for type %d, wxh: %dx%d, fmt: %08x, size %u\n", +- f->type, f->fmt.pix.width, f->fmt.pix.height, +- f->fmt.pix.pixelformat, f->fmt.pix.sizeimage); ++ v4l2_dbg(1, debug, &ctx->dev->v4l2_dev, "Setting format for type %d, wxh: %dx%d, fmt: %08x, size %u\n", ++ f->type, f->fmt.pix_mp.width, f->fmt.pix_mp.height, ++ f->fmt.pix_mp.pixelformat, f->fmt.pix_mp.plane_fmt[0].sizeimage); ++ + + vq = v4l2_m2m_get_vq(ctx->fh.m2m_ctx, f->type); + if (!vq) +@@ -1124,9 +1131,9 @@ static int vidioc_s_fmt(struct bcm2835_c + } + + q_data->fmt = find_format(f, ctx->dev, +- f->type == V4L2_BUF_TYPE_VIDEO_CAPTURE); +- q_data->crop_width = f->fmt.pix.width; +- q_data->height = f->fmt.pix.height; ++ f->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE); ++ q_data->crop_width = f->fmt.pix_mp.width; ++ q_data->height = f->fmt.pix_mp.height; + if (!q_data->selection_set) + q_data->crop_height = requested_height; + +@@ -1134,21 +1141,21 @@ static int vidioc_s_fmt(struct bcm2835_c + * Copying the behaviour of vicodec which retains a single set of + * colorspace parameters for both input and output. + */ +- ctx->colorspace = f->fmt.pix.colorspace; +- ctx->xfer_func = f->fmt.pix.xfer_func; +- ctx->ycbcr_enc = f->fmt.pix.ycbcr_enc; +- ctx->quant = f->fmt.pix.quantization; ++ ctx->colorspace = f->fmt.pix_mp.colorspace; ++ ctx->xfer_func = f->fmt.pix_mp.xfer_func; ++ ctx->ycbcr_enc = f->fmt.pix_mp.ycbcr_enc; ++ ctx->quant = f->fmt.pix_mp.quantization; + + /* All parameters should have been set correctly by try_fmt */ +- q_data->bytesperline = f->fmt.pix.bytesperline; +- q_data->sizeimage = f->fmt.pix.sizeimage; ++ q_data->bytesperline = f->fmt.pix_mp.plane_fmt[0].bytesperline; ++ q_data->sizeimage = f->fmt.pix_mp.plane_fmt[0].sizeimage; + + v4l2_dbg(1, debug, &ctx->dev->v4l2_dev, "Calulated bpl as %u, size %u\n", + q_data->bytesperline, q_data->sizeimage); + + if (ctx->dev->role == DECODE && + q_data->fmt->flags & V4L2_FMT_FLAG_COMPRESSED && +- f->fmt.pix.width && f->fmt.pix.height) { ++ q_data->crop_width && q_data->height) { + /* + * On the decoder, if provided with a resolution on the input + * side, then replicate that to the output side. +@@ -1165,7 +1172,7 @@ static int vidioc_s_fmt(struct bcm2835_c + q_data_dst->height = ALIGN(q_data->crop_height, 16); + + q_data_dst->bytesperline = +- get_bytesperline(f->fmt.pix.width, q_data_dst->fmt); ++ get_bytesperline(f->fmt.pix_mp.width, q_data_dst->fmt); + q_data_dst->sizeimage = get_sizeimage(q_data_dst->bytesperline, + q_data_dst->crop_width, + q_data_dst->height, +@@ -1215,7 +1222,7 @@ static int vidioc_s_fmt(struct bcm2835_c + static int vidioc_s_fmt_vid_cap(struct file *file, void *priv, + struct v4l2_format *f) + { +- unsigned int height = f->fmt.pix.height; ++ unsigned int height = f->fmt.pix_mp.height; + int ret; + + ret = vidioc_try_fmt_vid_cap(file, priv, f); +@@ -1228,7 +1235,7 @@ static int vidioc_s_fmt_vid_cap(struct f + static int vidioc_s_fmt_vid_out(struct file *file, void *priv, + struct v4l2_format *f) + { +- unsigned int height = f->fmt.pix.height; ++ unsigned int height = f->fmt.pix_mp.height; + int ret; + + ret = vidioc_try_fmt_vid_out(file, priv, f); +@@ -1244,7 +1251,7 @@ static int vidioc_g_selection(struct fil + { + struct bcm2835_codec_ctx *ctx = file2ctx(file); + struct bcm2835_codec_q_data *q_data; +- bool capture_queue = s->type == V4L2_BUF_TYPE_VIDEO_CAPTURE ? ++ bool capture_queue = s->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE ? + true : false; + + if ((ctx->dev->role == DECODE && !capture_queue) || +@@ -1307,7 +1314,7 @@ static int vidioc_s_selection(struct fil + { + struct bcm2835_codec_ctx *ctx = file2ctx(file); + struct bcm2835_codec_q_data *q_data = NULL; +- bool capture_queue = s->type == V4L2_BUF_TYPE_VIDEO_CAPTURE ? ++ bool capture_queue = s->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE ? + true : false; + + v4l2_dbg(1, debug, &ctx->dev->v4l2_dev, "%s: ctx %p, type %d, q_data %p, target %d, rect x/y %d/%d, w/h %ux%u\n", +@@ -1368,7 +1375,7 @@ static int vidioc_s_parm(struct file *fi + { + struct bcm2835_codec_ctx *ctx = file2ctx(file); + +- if (parm->type != V4L2_BUF_TYPE_VIDEO_OUTPUT) ++ if (parm->type != V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) + return -EINVAL; + + ctx->framerate_num = +@@ -1738,15 +1745,15 @@ static int vidioc_encoder_cmd(struct fil + static const struct v4l2_ioctl_ops bcm2835_codec_ioctl_ops = { + .vidioc_querycap = vidioc_querycap, + +- .vidioc_enum_fmt_vid_cap = vidioc_enum_fmt_vid_cap, +- .vidioc_g_fmt_vid_cap = vidioc_g_fmt_vid_cap, +- .vidioc_try_fmt_vid_cap = vidioc_try_fmt_vid_cap, +- .vidioc_s_fmt_vid_cap = vidioc_s_fmt_vid_cap, +- +- .vidioc_enum_fmt_vid_out = vidioc_enum_fmt_vid_out, +- .vidioc_g_fmt_vid_out = vidioc_g_fmt_vid_out, +- .vidioc_try_fmt_vid_out = vidioc_try_fmt_vid_out, +- .vidioc_s_fmt_vid_out = vidioc_s_fmt_vid_out, ++ .vidioc_enum_fmt_vid_cap_mplane = vidioc_enum_fmt_vid_cap, ++ .vidioc_g_fmt_vid_cap_mplane = vidioc_g_fmt_vid_cap, ++ .vidioc_try_fmt_vid_cap_mplane = vidioc_try_fmt_vid_cap, ++ .vidioc_s_fmt_vid_cap_mplane = vidioc_s_fmt_vid_cap, ++ ++ .vidioc_enum_fmt_vid_out_mplane = vidioc_enum_fmt_vid_out, ++ .vidioc_g_fmt_vid_out_mplane = vidioc_g_fmt_vid_out, ++ .vidioc_try_fmt_vid_out_mplane = vidioc_try_fmt_vid_out, ++ .vidioc_s_fmt_vid_out_mplane = vidioc_s_fmt_vid_out, + + .vidioc_reqbufs = v4l2_m2m_ioctl_reqbufs, + .vidioc_querybuf = v4l2_m2m_ioctl_querybuf, +@@ -2089,7 +2096,7 @@ static int bcm2835_codec_start_streaming + ctx->component_enabled = true; + } + +- if (q->type == V4L2_BUF_TYPE_VIDEO_OUTPUT) { ++ if (q->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) { + /* + * Create the EOS buffer. + * We only need the MMAL part, and want to NOT attach a memory +@@ -2216,7 +2223,7 @@ static int queue_init(void *priv, struct + struct bcm2835_codec_ctx *ctx = priv; + int ret; + +- src_vq->type = V4L2_BUF_TYPE_VIDEO_OUTPUT; ++ src_vq->type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE; + src_vq->io_modes = VB2_MMAP | VB2_DMABUF; + src_vq->drv_priv = ctx; + src_vq->buf_struct_size = sizeof(struct m2m_mmal_buffer); +@@ -2230,7 +2237,7 @@ static int queue_init(void *priv, struct + if (ret) + return ret; + +- dst_vq->type = V4L2_BUF_TYPE_VIDEO_CAPTURE; ++ dst_vq->type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE; + dst_vq->io_modes = VB2_MMAP | VB2_DMABUF; + dst_vq->drv_priv = ctx; + dst_vq->buf_struct_size = sizeof(struct m2m_mmal_buffer);