ImmortalWrt/target/linux/bcm27xx/patches-5.15/950-0503-staging-bcm2835-codec-Allow-decode-res-changed-befor.patch
Álvaro Fernández Rojas 20ea6adbf1 bcm27xx: add support for linux v5.15
Build system: x86_64
Build-tested: bcm2708, bcm2709, bcm2710, bcm2711
Run-tested: bcm2708/RPiB+, bcm2709/RPi3B, bcm2710/RPi3B, bcm2711/RPi4B

Signed-off-by: Marty Jones <mj8263788@gmail.com>
Signed-off-by: Álvaro Fernández Rojas <noltari@gmail.com>
2022-05-17 15:11:22 +02:00

239 lines
8.0 KiB
Diff

From 6eded7dd8bcf00c6c4f354cd2edfaabc8e82e8b7 Mon Sep 17 00:00:00 2001
From: Dave Stevenson <dave.stevenson@raspberrypi.com>
Date: Fri, 9 Oct 2020 10:40:27 +0100
Subject: [PATCH] staging: bcm2835-codec: Allow decode res changed
before STREAMON(CAPTURE)
The V4L2 stateful video decoder API requires that you can STREAMON
on only the OUTPUT queue, feed in buffers, and wait for the
SOURCE_CHANGE event.
This requires that we enable the MMAL output port at the same time
as the input port, because the output port is the one that creates
the SOURCE_CHANGED event.
Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.com>
---
.../bcm2835-codec/bcm2835-v4l2-codec.c | 137 +++++++++++++++---
1 file changed, 117 insertions(+), 20 deletions(-)
--- a/drivers/staging/vc04_services/bcm2835-codec/bcm2835-v4l2-codec.c
+++ b/drivers/staging/vc04_services/bcm2835-codec/bcm2835-v4l2-codec.c
@@ -1498,6 +1498,7 @@ static int vidioc_s_fmt(struct bcm2835_c
struct vb2_queue *vq;
struct vchiq_mmal_port *port;
bool update_capture_port = false;
+ bool reenable_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",
@@ -1575,6 +1576,24 @@ static int vidioc_s_fmt(struct bcm2835_c
if (!port)
return 0;
+ if (port->enabled) {
+ /*
+ * This should only ever happen with DECODE and the MMAL output
+ * port that has been enabled for resolution changed events.
+ * In this case no buffers have been allocated or sent to the
+ * component, so warn on that.
+ */
+ WARN_ON(ctx->dev->role != DECODE ||
+ f->type != V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE ||
+ atomic_read(&port->buffers_with_vpu));
+
+ ret = vchiq_mmal_port_disable(ctx->dev->instance, port);
+ if (ret)
+ v4l2_err(&ctx->dev->v4l2_dev, "%s: Error disabling port update buffer count, ret %d\n",
+ __func__, ret);
+ reenable_port = true;
+ }
+
setup_mmal_port_format(ctx, q_data, port);
ret = vchiq_mmal_port_set_format(ctx->dev->instance, port);
if (ret) {
@@ -1589,6 +1608,14 @@ static int vidioc_s_fmt(struct bcm2835_c
port->minimum_buffer.size);
}
+ if (reenable_port) {
+ ret = vchiq_mmal_port_enable(ctx->dev->instance,
+ port,
+ op_buffer_cb);
+ if (ret)
+ v4l2_err(&ctx->dev->v4l2_dev, "%s: Failed enabling o/p port, ret %d\n",
+ __func__, ret);
+ }
v4l2_dbg(1, debug, &ctx->dev->v4l2_dev, "Set format for type %d, wxh: %dx%d, fmt: %08x, size %u\n",
f->type, q_data->crop_width, q_data->height,
q_data->fmt->fourcc, q_data->sizeimage);
@@ -2467,9 +2494,11 @@ static int bcm2835_codec_create_componen
setup_mmal_port_format(ctx, &ctx->q_data[V4L2_M2M_SRC],
&ctx->component->input[0]);
+ ctx->component->input[0].cb_ctx = ctx;
setup_mmal_port_format(ctx, &ctx->q_data[V4L2_M2M_DST],
&ctx->component->output[0]);
+ ctx->component->output[0].cb_ctx = ctx;
ret = vchiq_mmal_port_set_format(dev->instance,
&ctx->component->input[0]);
@@ -2724,6 +2753,24 @@ static void bcm2835_codec_buffer_cleanup
bcm2835_codec_mmal_buf_cleanup(&buf->mmal);
}
+static void bcm2835_codec_flush_buffers(struct bcm2835_codec_ctx *ctx,
+ struct vchiq_mmal_port *port)
+{
+ int ret;
+
+ while (atomic_read(&port->buffers_with_vpu)) {
+ v4l2_dbg(1, debug, &ctx->dev->v4l2_dev, "%s: Waiting for buffers to be returned - %d outstanding\n",
+ __func__, atomic_read(&port->buffers_with_vpu));
+ ret = wait_for_completion_timeout(&ctx->frame_cmplt,
+ COMPLETE_TIMEOUT);
+ if (ret <= 0) {
+ v4l2_err(&ctx->dev->v4l2_dev, "%s: Timeout waiting for buffers to be returned - %d outstanding\n",
+ __func__,
+ atomic_read(&port->buffers_with_vpu));
+ break;
+ }
+ }
+}
static int bcm2835_codec_start_streaming(struct vb2_queue *q,
unsigned int count)
{
@@ -2731,7 +2778,7 @@ static int bcm2835_codec_start_streaming
struct bcm2835_codec_dev *dev = ctx->dev;
struct bcm2835_codec_q_data *q_data = get_q_data(ctx, q->type);
struct vchiq_mmal_port *port = get_port_data(ctx, q->type);
- int ret;
+ int ret = 0;
v4l2_dbg(1, debug, &ctx->dev->v4l2_dev, "%s: type: %d count %d\n",
__func__, q->type, count);
@@ -2746,6 +2793,34 @@ static int bcm2835_codec_start_streaming
ctx->component_enabled = true;
}
+ if (port->enabled) {
+ unsigned int num_buffers;
+
+ init_completion(&ctx->frame_cmplt);
+
+ /*
+ * This should only ever happen with DECODE and the MMAL output
+ * port that has been enabled for resolution changed events.
+ * In this case no buffers have been allocated or sent to the
+ * component, so warn on that.
+ */
+ WARN_ON(ctx->dev->role != DECODE);
+ WARN_ON(q->type != V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE);
+ WARN_ON(atomic_read(&port->buffers_with_vpu));
+
+ /*
+ * Disable will reread the port format, so retain buffer count.
+ */
+ num_buffers = port->current_buffer.num;
+
+ ret = vchiq_mmal_port_disable(dev->instance, port);
+ if (ret)
+ v4l2_err(&ctx->dev->v4l2_dev, "%s: Error disabling port update buffer count, ret %d\n",
+ __func__, ret);
+ bcm2835_codec_flush_buffers(ctx, port);
+ port->current_buffer.num = num_buffers;
+ }
+
if (count < port->minimum_buffer.num)
count = port->minimum_buffer.num;
@@ -2760,6 +2835,22 @@ static int bcm2835_codec_start_streaming
__func__, ret);
}
+ if (dev->role == DECODE &&
+ q->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE &&
+ !ctx->component->output[0].enabled) {
+ /*
+ * Decode needs to enable the MMAL output/V4L2 CAPTURE
+ * port at this point too so that we have everything
+ * set up for dynamic resolution changes.
+ */
+ ret = vchiq_mmal_port_enable(dev->instance,
+ &ctx->component->output[0],
+ op_buffer_cb);
+ if (ret)
+ v4l2_err(&ctx->dev->v4l2_dev, "%s: Failed enabling o/p port, ret %d\n",
+ __func__, ret);
+ }
+
if (q->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) {
/*
* Create the EOS buffer.
@@ -2771,7 +2862,6 @@ static int bcm2835_codec_start_streaming
&q_data->eos_buffer.mmal);
q_data->eos_buffer_in_use = false;
- port->cb_ctx = ctx;
ret = vchiq_mmal_port_enable(dev->instance,
port,
ip_buffer_cb);
@@ -2779,14 +2869,17 @@ static int bcm2835_codec_start_streaming
v4l2_err(&ctx->dev->v4l2_dev, "%s: Failed enabling i/p port, ret %d\n",
__func__, ret);
} else {
- port->cb_ctx = ctx;
- ret = vchiq_mmal_port_enable(dev->instance,
- port,
- op_buffer_cb);
- if (ret)
- v4l2_err(&ctx->dev->v4l2_dev, "%s: Failed enabling o/p port, ret %d\n",
- __func__, ret);
+ if (!port->enabled) {
+ ret = vchiq_mmal_port_enable(dev->instance,
+ port,
+ op_buffer_cb);
+ if (ret)
+ v4l2_err(&ctx->dev->v4l2_dev, "%s: Failed enabling o/p port, ret %d\n",
+ __func__, ret);
+ }
}
+ v4l2_dbg(1, debug, &ctx->dev->v4l2_dev, "%s: Done, ret %d\n",
+ __func__, ret);
return ret;
}
@@ -2825,17 +2918,21 @@ static void bcm2835_codec_stop_streaming
__func__, V4L2_TYPE_IS_OUTPUT(q->type) ? "i/p" : "o/p",
ret);
- while (atomic_read(&port->buffers_with_vpu)) {
- v4l2_dbg(1, debug, &ctx->dev->v4l2_dev, "%s: Waiting for buffers to be returned - %d outstanding\n",
- __func__, atomic_read(&port->buffers_with_vpu));
- ret = wait_for_completion_timeout(&ctx->frame_cmplt,
- COMPLETE_TIMEOUT);
- if (ret <= 0) {
- v4l2_err(&ctx->dev->v4l2_dev, "%s: Timeout waiting for buffers to be returned - %d outstanding\n",
- __func__,
- atomic_read(&port->buffers_with_vpu));
- break;
- }
+ bcm2835_codec_flush_buffers(ctx, port);
+
+ if (dev->role == DECODE &&
+ q->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE &&
+ ctx->component->input[0].enabled) {
+ /*
+ * For decode we need to keep the MMAL output port enabled for
+ * resolution changed events whenever the input is enabled.
+ */
+ ret = vchiq_mmal_port_enable(dev->instance,
+ &ctx->component->output[0],
+ op_buffer_cb);
+ if (ret)
+ v4l2_err(&ctx->dev->v4l2_dev, "%s: Failed enabling o/p port, ret %d\n",
+ __func__, ret);
}
/* If both ports disabled, then disable the component */