Commit 0e13f6f6 authored by Michael Tretter's avatar Michael Tretter Committed by Mauro Carvalho Chehab

media: allegro: remove custom drain state handling

The v4l2-m2m has various helpers for correctly handle the draining. Drop
the driver specific state machine and use the m2m helper functions.
Signed-off-by: default avatarMichael Tretter <m.tretter@pengutronix.de>
Signed-off-by: default avatarHans Verkuil <hverkuil-cisco@xs4all.nl>
Signed-off-by: default avatarMauro Carvalho Chehab <mchehab+huawei@kernel.org>
parent 0f3cc7ca
...@@ -167,13 +167,6 @@ static struct regmap_config allegro_sram_config = { ...@@ -167,13 +167,6 @@ static struct regmap_config allegro_sram_config = {
.cache_type = REGCACHE_NONE, .cache_type = REGCACHE_NONE,
}; };
enum allegro_state {
ALLEGRO_STATE_ENCODING,
ALLEGRO_STATE_DRAIN,
ALLEGRO_STATE_WAIT_FOR_BUFFER,
ALLEGRO_STATE_STOPPED,
};
#define fh_to_channel(__fh) container_of(__fh, struct allegro_channel, fh) #define fh_to_channel(__fh) container_of(__fh, struct allegro_channel, fh)
struct allegro_channel { struct allegro_channel {
...@@ -246,23 +239,8 @@ struct allegro_channel { ...@@ -246,23 +239,8 @@ struct allegro_channel {
struct completion completion; struct completion completion;
unsigned int error; unsigned int error;
enum allegro_state state;
}; };
static inline int
allegro_set_state(struct allegro_channel *channel, enum allegro_state state)
{
channel->state = state;
return 0;
}
static inline enum allegro_state
allegro_get_state(struct allegro_channel *channel)
{
return channel->state;
}
struct allegro_m2m_buffer { struct allegro_m2m_buffer {
struct v4l2_m2m_buffer buf; struct v4l2_m2m_buffer buf;
struct list_head head; struct list_head head;
...@@ -1392,45 +1370,13 @@ static ssize_t allegro_h264_write_pps(struct allegro_channel *channel, ...@@ -1392,45 +1370,13 @@ static ssize_t allegro_h264_write_pps(struct allegro_channel *channel,
return size; return size;
} }
static bool allegro_channel_is_at_eos(struct allegro_channel *channel) static void allegro_channel_eos_event(struct allegro_channel *channel)
{
bool is_at_eos = false;
switch (allegro_get_state(channel)) {
case ALLEGRO_STATE_STOPPED:
is_at_eos = true;
break;
case ALLEGRO_STATE_DRAIN:
case ALLEGRO_STATE_WAIT_FOR_BUFFER:
mutex_lock(&channel->shadow_list_lock);
if (v4l2_m2m_num_src_bufs_ready(channel->fh.m2m_ctx) == 0 &&
list_empty(&channel->source_shadow_list))
is_at_eos = true;
mutex_unlock(&channel->shadow_list_lock);
break;
default:
break;
}
return is_at_eos;
}
static void allegro_channel_buf_done(struct allegro_channel *channel,
struct vb2_v4l2_buffer *buf,
enum vb2_buffer_state state)
{ {
const struct v4l2_event eos_event = { const struct v4l2_event eos_event = {
.type = V4L2_EVENT_EOS .type = V4L2_EVENT_EOS
}; };
if (allegro_channel_is_at_eos(channel)) { v4l2_event_queue_fh(&channel->fh, &eos_event);
buf->flags |= V4L2_BUF_FLAG_LAST;
v4l2_event_queue_fh(&channel->fh, &eos_event);
allegro_set_state(channel, ALLEGRO_STATE_STOPPED);
}
v4l2_m2m_buf_done(buf, state);
} }
static u64 allegro_put_buffer(struct allegro_channel *channel, static u64 allegro_put_buffer(struct allegro_channel *channel,
...@@ -1500,6 +1446,12 @@ static void allegro_channel_finish_frame(struct allegro_channel *channel, ...@@ -1500,6 +1446,12 @@ static void allegro_channel_finish_frame(struct allegro_channel *channel,
if (!src_buf || !dst_buf) if (!src_buf || !dst_buf)
goto err; goto err;
if (v4l2_m2m_is_last_draining_src_buf(channel->fh.m2m_ctx, src_buf)) {
dst_buf->flags |= V4L2_BUF_FLAG_LAST;
allegro_channel_eos_event(channel);
v4l2_m2m_mark_stopped(channel->fh.m2m_ctx);
}
dst_buf->sequence = channel->csequence++; dst_buf->sequence = channel->csequence++;
if (msg->error_code & AL_ERROR) { if (msg->error_code & AL_ERROR) {
...@@ -1626,7 +1578,7 @@ static void allegro_channel_finish_frame(struct allegro_channel *channel, ...@@ -1626,7 +1578,7 @@ static void allegro_channel_finish_frame(struct allegro_channel *channel,
v4l2_m2m_buf_done(src_buf, VB2_BUF_STATE_DONE); v4l2_m2m_buf_done(src_buf, VB2_BUF_STATE_DONE);
if (dst_buf) if (dst_buf)
allegro_channel_buf_done(channel, dst_buf, state); v4l2_m2m_buf_done(dst_buf, state);
} }
static int allegro_handle_init(struct allegro_dev *dev, static int allegro_handle_init(struct allegro_dev *dev,
...@@ -2145,10 +2097,6 @@ static int allegro_buf_prepare(struct vb2_buffer *vb) ...@@ -2145,10 +2097,6 @@ static int allegro_buf_prepare(struct vb2_buffer *vb)
struct allegro_channel *channel = vb2_get_drv_priv(vb->vb2_queue); struct allegro_channel *channel = vb2_get_drv_priv(vb->vb2_queue);
struct allegro_dev *dev = channel->dev; struct allegro_dev *dev = channel->dev;
if (allegro_get_state(channel) == ALLEGRO_STATE_DRAIN &&
V4L2_TYPE_IS_OUTPUT(vb->vb2_queue->type))
return -EBUSY;
if (V4L2_TYPE_IS_OUTPUT(vb->vb2_queue->type)) { if (V4L2_TYPE_IS_OUTPUT(vb->vb2_queue->type)) {
if (vbuf->field == V4L2_FIELD_ANY) if (vbuf->field == V4L2_FIELD_ANY)
vbuf->field = V4L2_FIELD_NONE; vbuf->field = V4L2_FIELD_NONE;
...@@ -2167,10 +2115,21 @@ static void allegro_buf_queue(struct vb2_buffer *vb) ...@@ -2167,10 +2115,21 @@ static void allegro_buf_queue(struct vb2_buffer *vb)
{ {
struct allegro_channel *channel = vb2_get_drv_priv(vb->vb2_queue); struct allegro_channel *channel = vb2_get_drv_priv(vb->vb2_queue);
struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb); struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb);
struct vb2_queue *q = vb->vb2_queue;
if (V4L2_TYPE_IS_CAPTURE(q->type) &&
vb2_is_streaming(q) &&
v4l2_m2m_dst_buf_is_last(channel->fh.m2m_ctx)) {
unsigned int i;
for (i = 0; i < vb->num_planes; i++)
vb->planes[i].bytesused = 0;
if (allegro_get_state(channel) == ALLEGRO_STATE_WAIT_FOR_BUFFER && vbuf->field = V4L2_FIELD_NONE;
vb->vb2_queue->type == V4L2_BUF_TYPE_VIDEO_CAPTURE) { vbuf->sequence = channel->csequence++;
allegro_channel_buf_done(channel, vbuf, VB2_BUF_STATE_DONE);
v4l2_m2m_last_buffer_done(channel->fh.m2m_ctx, vbuf);
allegro_channel_eos_event(channel);
return; return;
} }
...@@ -2186,12 +2145,12 @@ static int allegro_start_streaming(struct vb2_queue *q, unsigned int count) ...@@ -2186,12 +2145,12 @@ static int allegro_start_streaming(struct vb2_queue *q, unsigned int count)
"%s: start streaming\n", "%s: start streaming\n",
V4L2_TYPE_IS_OUTPUT(q->type) ? "output" : "capture"); V4L2_TYPE_IS_OUTPUT(q->type) ? "output" : "capture");
if (V4L2_TYPE_IS_OUTPUT(q->type)) { v4l2_m2m_update_start_streaming_state(channel->fh.m2m_ctx, q);
if (V4L2_TYPE_IS_OUTPUT(q->type))
channel->osequence = 0; channel->osequence = 0;
allegro_set_state(channel, ALLEGRO_STATE_ENCODING); else
} else if (q->type == V4L2_BUF_TYPE_VIDEO_CAPTURE) {
channel->csequence = 0; channel->csequence = 0;
}
return 0; return 0;
} }
...@@ -2216,10 +2175,9 @@ static void allegro_stop_streaming(struct vb2_queue *q) ...@@ -2216,10 +2175,9 @@ static void allegro_stop_streaming(struct vb2_queue *q)
} }
mutex_unlock(&channel->shadow_list_lock); mutex_unlock(&channel->shadow_list_lock);
allegro_set_state(channel, ALLEGRO_STATE_STOPPED);
while ((buffer = v4l2_m2m_src_buf_remove(channel->fh.m2m_ctx))) while ((buffer = v4l2_m2m_src_buf_remove(channel->fh.m2m_ctx)))
v4l2_m2m_buf_done(buffer, VB2_BUF_STATE_ERROR); v4l2_m2m_buf_done(buffer, VB2_BUF_STATE_ERROR);
} else if (q->type == V4L2_BUF_TYPE_VIDEO_CAPTURE) { } else {
mutex_lock(&channel->shadow_list_lock); mutex_lock(&channel->shadow_list_lock);
list_for_each_entry_safe(shadow, tmp, list_for_each_entry_safe(shadow, tmp,
&channel->stream_shadow_list, head) { &channel->stream_shadow_list, head) {
...@@ -2232,6 +2190,12 @@ static void allegro_stop_streaming(struct vb2_queue *q) ...@@ -2232,6 +2190,12 @@ static void allegro_stop_streaming(struct vb2_queue *q)
while ((buffer = v4l2_m2m_dst_buf_remove(channel->fh.m2m_ctx))) while ((buffer = v4l2_m2m_dst_buf_remove(channel->fh.m2m_ctx)))
v4l2_m2m_buf_done(buffer, VB2_BUF_STATE_ERROR); v4l2_m2m_buf_done(buffer, VB2_BUF_STATE_ERROR);
} }
v4l2_m2m_update_stop_streaming_state(channel->fh.m2m_ctx, q);
if (V4L2_TYPE_IS_OUTPUT(q->type) &&
v4l2_m2m_has_stopped(channel->fh.m2m_ctx))
allegro_channel_eos_event(channel);
} }
static const struct vb2_ops allegro_queue_ops = { static const struct vb2_ops allegro_queue_ops = {
...@@ -2669,62 +2633,16 @@ static int allegro_s_fmt_vid_out(struct file *file, void *fh, ...@@ -2669,62 +2633,16 @@ static int allegro_s_fmt_vid_out(struct file *file, void *fh,
static int allegro_channel_cmd_stop(struct allegro_channel *channel) static int allegro_channel_cmd_stop(struct allegro_channel *channel)
{ {
struct allegro_dev *dev = channel->dev; if (v4l2_m2m_has_stopped(channel->fh.m2m_ctx))
struct vb2_v4l2_buffer *dst_buf; allegro_channel_eos_event(channel);
switch (allegro_get_state(channel)) {
case ALLEGRO_STATE_DRAIN:
case ALLEGRO_STATE_WAIT_FOR_BUFFER:
return -EBUSY;
case ALLEGRO_STATE_ENCODING:
allegro_set_state(channel, ALLEGRO_STATE_DRAIN);
break;
default:
return 0;
}
/* If there are output buffers, they must be encoded */
if (v4l2_m2m_num_src_bufs_ready(channel->fh.m2m_ctx) != 0) {
v4l2_dbg(1, debug, &dev->v4l2_dev,
"channel %d: CMD_STOP: continue encoding src buffers\n",
channel->mcu_channel_id);
return 0;
}
/* If there are capture buffers, use it to signal EOS */
dst_buf = v4l2_m2m_dst_buf_remove(channel->fh.m2m_ctx);
if (dst_buf) {
v4l2_dbg(1, debug, &dev->v4l2_dev,
"channel %d: CMD_STOP: signaling EOS\n",
channel->mcu_channel_id);
allegro_channel_buf_done(channel, dst_buf, VB2_BUF_STATE_DONE);
return 0;
}
/*
* If there are no capture buffers, we need to wait for the next
* buffer to signal EOS.
*/
v4l2_dbg(1, debug, &dev->v4l2_dev,
"channel %d: CMD_STOP: wait for CAPTURE buffer to signal EOS\n",
channel->mcu_channel_id);
allegro_set_state(channel, ALLEGRO_STATE_WAIT_FOR_BUFFER);
return 0; return 0;
} }
static int allegro_channel_cmd_start(struct allegro_channel *channel) static int allegro_channel_cmd_start(struct allegro_channel *channel)
{ {
switch (allegro_get_state(channel)) { if (v4l2_m2m_has_stopped(channel->fh.m2m_ctx))
case ALLEGRO_STATE_DRAIN: vb2_clear_last_buffer_dequeued(&channel->fh.m2m_ctx->cap_q_ctx.q);
case ALLEGRO_STATE_WAIT_FOR_BUFFER:
return -EBUSY;
case ALLEGRO_STATE_STOPPED:
allegro_set_state(channel, ALLEGRO_STATE_ENCODING);
break;
default:
return 0;
}
return 0; return 0;
} }
...@@ -2739,17 +2657,15 @@ static int allegro_encoder_cmd(struct file *file, void *fh, ...@@ -2739,17 +2657,15 @@ static int allegro_encoder_cmd(struct file *file, void *fh,
if (err) if (err)
return err; return err;
switch (cmd->cmd) { err = v4l2_m2m_ioctl_encoder_cmd(file, fh, cmd);
case V4L2_ENC_CMD_STOP: if (err)
return err;
if (cmd->cmd == V4L2_ENC_CMD_STOP)
err = allegro_channel_cmd_stop(channel); err = allegro_channel_cmd_stop(channel);
break;
case V4L2_ENC_CMD_START: if (cmd->cmd == V4L2_ENC_CMD_START)
err = allegro_channel_cmd_start(channel); err = allegro_channel_cmd_start(channel);
break;
default:
err = -EINVAL;
break;
}
return err; return err;
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment