diff --git a/drivers/media/platform/rockchip/isp/capture.c b/drivers/media/platform/rockchip/isp/capture.c index c70d75d3f816..b099ee441c2a 100644 --- a/drivers/media/platform/rockchip/isp/capture.c +++ b/drivers/media/platform/rockchip/isp/capture.c @@ -1828,6 +1828,38 @@ static const struct v4l2_ioctl_ops rkisp_v4l2_ioctl_ops = { .vidioc_default = rkisp_ioctl_default, }; +static void rkisp_buf_done_task(unsigned long arg) +{ + struct rkisp_stream *stream = (struct rkisp_stream *)arg; + struct rkisp_buffer *buf = NULL; + unsigned long lock_flags = 0; + LIST_HEAD(local_list); + + spin_lock_irqsave(&stream->vbq_lock, lock_flags); + list_replace_init(&stream->buf_done_list, &local_list); + spin_unlock_irqrestore(&stream->vbq_lock, lock_flags); + + while (!list_empty(&local_list)) { + buf = list_first_entry(&local_list, + struct rkisp_buffer, queue); + list_del(&buf->queue); + vb2_buffer_done(&buf->vb.vb2_buf, VB2_BUF_STATE_DONE); + } +} + +void rkisp_stream_buf_done(struct rkisp_stream *stream, + struct rkisp_buffer *buf) +{ + unsigned long lock_flags = 0; + + if (!stream || !buf) + return; + spin_lock_irqsave(&stream->vbq_lock, lock_flags); + list_add_tail(&buf->queue, &stream->buf_done_list); + spin_unlock_irqrestore(&stream->vbq_lock, lock_flags); + tasklet_schedule(&stream->buf_done_tasklet); +} + static void rkisp_stream_fast(struct work_struct *work) { struct rkisp_capture_device *cap_dev = @@ -1869,6 +1901,7 @@ static void rkisp_stream_fast(struct work_struct *work) void rkisp_unregister_stream_vdev(struct rkisp_stream *stream) { + tasklet_kill(&stream->buf_done_tasklet); media_entity_cleanup(&stream->vnode.vdev.entity); video_unregister_device(&stream->vnode.vdev); } @@ -1928,6 +1961,11 @@ int rkisp_register_stream_vdev(struct rkisp_stream *stream) sink, 0, stream->linked); if (ret < 0) goto unreg; + INIT_LIST_HEAD(&stream->buf_done_list); + tasklet_init(&stream->buf_done_tasklet, + rkisp_buf_done_task, + (unsigned long)stream); + tasklet_disable(&stream->buf_done_tasklet); return 0; unreg: video_unregister_device(vdev); diff --git a/drivers/media/platform/rockchip/isp/capture.h b/drivers/media/platform/rockchip/isp/capture.h index a9de3a9962e9..058f58693728 100644 --- a/drivers/media/platform/rockchip/isp/capture.h +++ b/drivers/media/platform/rockchip/isp/capture.h @@ -268,6 +268,8 @@ struct rkisp_stream { struct rkisp_buffer *next_buf; struct rkisp_dummy_buffer dummy_buf; struct mutex apilock; + struct tasklet_struct buf_done_tasklet; + struct list_head buf_done_list; bool streaming; bool stopping; bool frame_end; @@ -319,6 +321,8 @@ extern struct stream_config rkisp_mp_stream_config; extern struct stream_config rkisp_sp_stream_config; extern struct rockit_isp_ops rockit_isp_ops; +void rkisp_stream_buf_done(struct rkisp_stream *stream, + struct rkisp_buffer *buf); void rkisp_unregister_stream_vdev(struct rkisp_stream *stream); int rkisp_register_stream_vdev(struct rkisp_stream *stream); void rkisp_unregister_stream_vdevs(struct rkisp_device *dev); diff --git a/drivers/media/platform/rockchip/isp/capture_v1x.c b/drivers/media/platform/rockchip/isp/capture_v1x.c index 31d8817ea2f0..49db32298888 100644 --- a/drivers/media/platform/rockchip/isp/capture_v1x.c +++ b/drivers/media/platform/rockchip/isp/capture_v1x.c @@ -424,8 +424,7 @@ static int mi_frame_end(struct rkisp_stream *stream) } stream->curr_buf->vb.sequence = atomic_read(&dev->isp_sdev.frm_sync_seq) - 1; stream->curr_buf->vb.vb2_buf.timestamp = ns; - vb2_buffer_done(&stream->curr_buf->vb.vb2_buf, - VB2_BUF_STATE_DONE); + rkisp_stream_buf_done(stream, stream->curr_buf); stream->curr_buf = NULL; } @@ -684,6 +683,7 @@ static void rkisp_stop_streaming(struct vb2_queue *queue) v4l2_err(v4l2_dev, "pipeline close failed error:%d\n", ret); rkisp_destroy_dummy_buf(stream); atomic_dec(&dev->cap_dev.refcnt); + tasklet_disable(&stream->buf_done_tasklet); } static int rkisp_stream_start(struct rkisp_stream *stream) @@ -788,7 +788,7 @@ rkisp_start_streaming(struct vb2_queue *queue, unsigned int count) "start pipeline failed %d\n", ret); goto pipe_stream_off; } - + tasklet_enable(&stream->buf_done_tasklet); return 0; pipe_stream_off: diff --git a/drivers/media/platform/rockchip/isp/capture_v20.c b/drivers/media/platform/rockchip/isp/capture_v20.c index 4dbb87110d54..7ae57f3b5963 100644 --- a/drivers/media/platform/rockchip/isp/capture_v20.c +++ b/drivers/media/platform/rockchip/isp/capture_v20.c @@ -937,16 +937,11 @@ static void rdbk_frame_end(struct rkisp_stream *stream) goto RDBK_FRM_UNMATCH; } - cap->rdbk_buf[RDBK_S]->vb.sequence = - cap->rdbk_buf[RDBK_L]->vb.sequence; - cap->rdbk_buf[RDBK_M]->vb.sequence = - cap->rdbk_buf[RDBK_L]->vb.sequence; - vb2_buffer_done(&cap->rdbk_buf[RDBK_L]->vb.vb2_buf, - VB2_BUF_STATE_DONE); - vb2_buffer_done(&cap->rdbk_buf[RDBK_M]->vb.vb2_buf, - VB2_BUF_STATE_DONE); - vb2_buffer_done(&cap->rdbk_buf[RDBK_S]->vb.vb2_buf, - VB2_BUF_STATE_DONE); + cap->rdbk_buf[RDBK_S]->vb.sequence = cap->rdbk_buf[RDBK_L]->vb.sequence; + cap->rdbk_buf[RDBK_M]->vb.sequence = cap->rdbk_buf[RDBK_L]->vb.sequence; + rkisp_stream_buf_done(&cap->stream[RKISP_STREAM_DMATX0], cap->rdbk_buf[RDBK_L]); + rkisp_stream_buf_done(&cap->stream[RKISP_STREAM_DMATX1], cap->rdbk_buf[RDBK_M]); + rkisp_stream_buf_done(stream, cap->rdbk_buf[RDBK_S]); } else { v4l2_err(&isp_dev->v4l2_dev, "lost long or middle frames\n"); goto RDBK_FRM_UNMATCH; @@ -981,18 +976,15 @@ static void rdbk_frame_end(struct rkisp_stream *stream) goto RDBK_FRM_UNMATCH; } - cap->rdbk_buf[RDBK_S]->vb.sequence = - cap->rdbk_buf[RDBK_L]->vb.sequence; - vb2_buffer_done(&cap->rdbk_buf[RDBK_L]->vb.vb2_buf, - VB2_BUF_STATE_DONE); - vb2_buffer_done(&cap->rdbk_buf[RDBK_S]->vb.vb2_buf, - VB2_BUF_STATE_DONE); + cap->rdbk_buf[RDBK_S]->vb.sequence = cap->rdbk_buf[RDBK_L]->vb.sequence; + rkisp_stream_buf_done(&cap->stream[RKISP_STREAM_DMATX0], cap->rdbk_buf[RDBK_L]); + rkisp_stream_buf_done(stream, cap->rdbk_buf[RDBK_S]); } else { v4l2_err(&isp_dev->v4l2_dev, "lost long frames\n"); goto RDBK_FRM_UNMATCH; } } else { - vb2_buffer_done(&cap->rdbk_buf[RDBK_S]->vb.vb2_buf, VB2_BUF_STATE_DONE); + rkisp_stream_buf_done(stream, cap->rdbk_buf[RDBK_S]); } cap->rdbk_buf[RDBK_L] = NULL; @@ -1097,7 +1089,7 @@ static int mi_frame_end(struct rkisp_stream *stream) cap->rdbk_buf[RDBK_S] = stream->curr_buf; rdbk_frame_end(stream); } else { - vb2_buffer_done(vb2_buf, VB2_BUF_STATE_DONE); + rkisp_stream_buf_done(stream, stream->curr_buf); } } else { if (stream->id == RKISP_STREAM_SP && isp_fmt->fmt_type == FMT_FBCGAIN) { @@ -1108,7 +1100,7 @@ static int mi_frame_end(struct rkisp_stream *stream) stream->curr_buf->dev_id = dev->dev_id; rkisp_bridge_save_spbuf(dev, stream->curr_buf); } else { - vb2_buffer_done(vb2_buf, VB2_BUF_STATE_DONE); + rkisp_stream_buf_done(stream, stream->curr_buf); } } diff --git a/drivers/media/platform/rockchip/isp/capture_v21.c b/drivers/media/platform/rockchip/isp/capture_v21.c index a30e978854b6..1cfe138bf958 100644 --- a/drivers/media/platform/rockchip/isp/capture_v21.c +++ b/drivers/media/platform/rockchip/isp/capture_v21.c @@ -797,7 +797,7 @@ static void rdbk_frame_end(struct rkisp_stream *stream) return; if (isp_dev->hdr.op_mode == HDR_RDBK_FRAME1) { - vb2_buffer_done(&cap->rdbk_buf[RDBK_S]->vb.vb2_buf, VB2_BUF_STATE_DONE); + rkisp_stream_buf_done(stream, cap->rdbk_buf[RDBK_S]); cap->rdbk_buf[RDBK_S] = NULL; return; } @@ -834,12 +834,9 @@ static void rdbk_frame_end(struct rkisp_stream *stream) goto RDBK_FRM_UNMATCH; } - cap->rdbk_buf[RDBK_S]->vb.sequence = - cap->rdbk_buf[RDBK_L]->vb.sequence; - vb2_buffer_done(&cap->rdbk_buf[RDBK_L]->vb.vb2_buf, - VB2_BUF_STATE_DONE); - vb2_buffer_done(&cap->rdbk_buf[RDBK_S]->vb.vb2_buf, - VB2_BUF_STATE_DONE); + cap->rdbk_buf[RDBK_S]->vb.sequence = cap->rdbk_buf[RDBK_L]->vb.sequence; + rkisp_stream_buf_done(&cap->stream[RKISP_STREAM_DMATX0], cap->rdbk_buf[RDBK_L]); + rkisp_stream_buf_done(stream, cap->rdbk_buf[RDBK_S]); } else { v4l2_err(&isp_dev->v4l2_dev, "lost long frames\n"); goto RDBK_FRM_UNMATCH; @@ -936,7 +933,7 @@ static int mi_frame_end(struct rkisp_stream *stream) rdbk_frame_end(stream); } } else { - vb2_buffer_done(vb2_buf, VB2_BUF_STATE_DONE); + rkisp_stream_buf_done(stream, stream->curr_buf); } stream->curr_buf = NULL; @@ -1251,7 +1248,7 @@ static void rkisp_stop_streaming(struct vb2_queue *queue) v4l2_err(v4l2_dev, "pipeline close failed error:%d\n", ret); rkisp_destroy_dummy_buf(stream); atomic_dec(&dev->cap_dev.refcnt); - + tasklet_disable(&stream->buf_done_tasklet); end: mutex_unlock(&dev->hw_dev->dev_lock); } @@ -1377,7 +1374,7 @@ rkisp_start_streaming(struct vb2_queue *queue, unsigned int count) goto pipe_stream_off; } } - + tasklet_enable(&stream->buf_done_tasklet); mutex_unlock(&dev->hw_dev->dev_lock); return 0; diff --git a/drivers/media/platform/rockchip/isp/capture_v30.c b/drivers/media/platform/rockchip/isp/capture_v30.c index 1bd5f65cd290..9bd39d266db0 100644 --- a/drivers/media/platform/rockchip/isp/capture_v30.c +++ b/drivers/media/platform/rockchip/isp/capture_v30.c @@ -759,20 +759,14 @@ static int mi_frame_end(struct rkisp_stream *stream) stream->dbg.delay = ns - dev->isp_sdev.frm_timestamp; if (vir->streaming && vir->conn_id == stream->id) { - spin_lock_irqsave(&vir->vbq_lock, lock_flags); - if (vir->streaming) - list_add_tail(&stream->curr_buf->queue, - &dev->cap_dev.vir_cpy.queue); + list_add_tail(&stream->curr_buf->queue, + &dev->cap_dev.vir_cpy.queue); spin_unlock_irqrestore(&vir->vbq_lock, lock_flags); if (!completion_done(&dev->cap_dev.vir_cpy.cmpl)) complete(&dev->cap_dev.vir_cpy.cmpl); - - if (!vir->streaming) - vb2_buffer_done(vb2_buf, VB2_BUF_STATE_DONE); - } else { - vb2_buffer_done(vb2_buf, VB2_BUF_STATE_DONE); + rkisp_stream_buf_done(stream, stream->curr_buf); } stream->curr_buf = NULL; @@ -1033,7 +1027,7 @@ static void rkisp_stop_streaming(struct vb2_queue *queue) v4l2_err(v4l2_dev, "pipeline close failed error:%d\n", ret); rkisp_destroy_dummy_buf(stream); atomic_dec(&dev->cap_dev.refcnt); - + tasklet_disable(&stream->buf_done_tasklet); end: mutex_unlock(&dev->hw_dev->dev_lock); } @@ -1248,7 +1242,7 @@ rkisp_start_streaming(struct vb2_queue *queue, unsigned int count) v4l2_err(v4l2_dev, "start pipeline failed %d\n", ret); goto pipe_stream_off; } - + tasklet_enable(&stream->buf_done_tasklet); mutex_unlock(&dev->hw_dev->dev_lock); return 0; diff --git a/drivers/media/platform/rockchip/isp/capture_v32.c b/drivers/media/platform/rockchip/isp/capture_v32.c index 65943d80b08f..f7379fd916f0 100644 --- a/drivers/media/platform/rockchip/isp/capture_v32.c +++ b/drivers/media/platform/rockchip/isp/capture_v32.c @@ -1090,7 +1090,7 @@ static int mi_frame_end(struct rkisp_stream *stream) } if (vb2_buf->memory) - vb2_buffer_done(vb2_buf, VB2_BUF_STATE_DONE); + rkisp_stream_buf_done(stream, stream->curr_buf); else rkisp_rockit_buf_done(stream, ROCKIT_DVBM_END); } @@ -1392,7 +1392,7 @@ static void rkisp_stop_streaming(struct vb2_queue *queue) v4l2_err(v4l2_dev, "pipeline close failed error:%d\n", ret); rkisp_destroy_dummy_buf(stream); atomic_dec(&dev->cap_dev.refcnt); - + tasklet_disable(&stream->buf_done_tasklet); end: mutex_unlock(&dev->hw_dev->dev_lock); @@ -1527,6 +1527,7 @@ rkisp_start_streaming(struct vb2_queue *queue, unsigned int count) v4l2_err(v4l2_dev, "start pipeline failed %d\n", ret); goto pipe_stream_off; } + tasklet_enable(&stream->buf_done_tasklet); end: mutex_unlock(&dev->hw_dev->dev_lock); return 0;