diff --git a/drivers/media/platform/rockchip/cif/capture.c b/drivers/media/platform/rockchip/cif/capture.c index 23a878ef0aea..5559b234c171 100644 --- a/drivers/media/platform/rockchip/cif/capture.c +++ b/drivers/media/platform/rockchip/cif/capture.c @@ -1968,8 +1968,9 @@ static void rkcif_rdbk_with_tools(struct rkcif_stream *stream, unsigned long flags; spin_lock_irqsave(&stream->tools_vdev->vbq_lock, flags); - if (stream->tools_vdev->state == RKCIF_STATE_STREAMING) { - list_add_tail(&active_buf->list, &stream->tools_vdev->buf_done_head); + if (stream->tools_vdev->state == RKCIF_STATE_STREAMING && active_buf) { + list_add_tail(&active_buf->list_tool, &stream->tools_vdev->buf_done_head); + active_buf->use_cnt = 2; if (!work_busy(&stream->tools_vdev->work)) schedule_work(&stream->tools_vdev->work); } diff --git a/drivers/media/platform/rockchip/cif/cif-tools.c b/drivers/media/platform/rockchip/cif/cif-tools.c index f46c744489d6..78e92678036d 100644 --- a/drivers/media/platform/rockchip/cif/cif-tools.c +++ b/drivers/media/platform/rockchip/cif/cif-tools.c @@ -474,6 +474,7 @@ static void rkcif_tools_vb2_stop_streaming(struct vb2_queue *vq) struct rkcif_device *dev = tools_vdev->cifdev; struct rkcif_buffer *buf = NULL; struct rkcif_tools_buffer *tools_buf; + struct rkcif_rx_buffer *rx_buf = NULL; int ret = 0; mutex_lock(&dev->tools_lock); @@ -485,6 +486,12 @@ static void rkcif_tools_vb2_stop_streaming(struct vb2_queue *vq) if (!ret) { rkcif_tools_stop(tools_vdev); tools_vdev->stopping = false; + while (!list_empty(&tools_vdev->buf_done_head)) { + rx_buf = list_first_entry(&tools_vdev->buf_done_head, + struct rkcif_rx_buffer, list_tool); + list_del(&rx_buf->list_tool); + v4l2_subdev_call(&dev->sditf[0]->sd, video, s_rx_buffer, &rx_buf->dbufs, NULL); + } } /* release buffers */ if (tools_vdev->curr_buf) @@ -710,9 +717,9 @@ retry_done_rdbk_buf: spin_lock_irqsave(&tools_vdev->vbq_lock, flags); if (!list_empty(&tools_vdev->buf_done_head)) { buf = list_first_entry(&tools_vdev->buf_done_head, - struct rkcif_rx_buffer, list); + struct rkcif_rx_buffer, list_tool); if (buf) - list_del(&buf->list); + list_del(&buf->list_tool); } spin_unlock_irqrestore(&tools_vdev->vbq_lock, flags); if (!buf) { @@ -724,12 +731,14 @@ retry_done_rdbk_buf: if (tools_vdev->stopping) { rkcif_tools_stop(tools_vdev); tools_vdev->stopping = false; + if (buf) + v4l2_subdev_call(&dev->sditf[0]->sd, video, s_rx_buffer, &buf->dbufs, NULL); spin_lock_irqsave(&tools_vdev->vbq_lock, flags); while (!list_empty(&tools_vdev->buf_done_head)) { buf = list_first_entry(&tools_vdev->buf_done_head, - struct rkcif_rx_buffer, list); - if (buf) - list_del(&buf->list); + struct rkcif_rx_buffer, list_tool); + list_del(&buf->list_tool); + v4l2_subdev_call(&dev->sditf[0]->sd, video, s_rx_buffer, &buf->dbufs, NULL); } spin_unlock_irqrestore(&tools_vdev->vbq_lock, flags); wake_up(&tools_vdev->wq_stopped); @@ -742,9 +751,13 @@ retry_done_rdbk_buf: if (!tools_vdev->curr_buf || tools_vdev->state != RKCIF_STATE_STREAMING) { spin_lock_irqsave(&tools_vdev->vbq_lock, flags); if (!list_empty(&tools_vdev->buf_done_head)) { + if (buf) + v4l2_subdev_call(&dev->sditf[0]->sd, video, s_rx_buffer, &buf->dbufs, NULL); spin_unlock_irqrestore(&stream->tools_vdev->vbq_lock, flags); goto retry_done_rdbk_buf; } + if (buf) + v4l2_subdev_call(&dev->sditf[0]->sd, video, s_rx_buffer, &buf->dbufs, NULL); spin_unlock_irqrestore(&tools_vdev->vbq_lock, flags); return; } @@ -765,10 +778,14 @@ retry_done_rdbk_buf: payload_size); memcpy(dst, src, payload_size); } + v4l2_subdev_call(&dev->sditf[0]->sd, video, s_rx_buffer, &buf->dbufs, NULL); tools_vdev->curr_buf->vb.sequence = buf->dbufs.sequence; tools_vdev->curr_buf->vb.vb2_buf.timestamp = buf->dbufs.timestamp; vb2_buffer_done(&tools_vdev->curr_buf->vb.vb2_buf, VB2_BUF_STATE_DONE); tools_vdev->curr_buf = NULL; + } else { + if (buf) + v4l2_subdev_call(&dev->sditf[0]->sd, video, s_rx_buffer, &buf->dbufs, NULL); } spin_lock_irqsave(&tools_vdev->vbq_lock, flags); diff --git a/drivers/media/platform/rockchip/cif/dev.h b/drivers/media/platform/rockchip/cif/dev.h index b8bb669f04ff..ca6e0983b186 100644 --- a/drivers/media/platform/rockchip/cif/dev.h +++ b/drivers/media/platform/rockchip/cif/dev.h @@ -479,12 +479,14 @@ enum rkcif_capture_mode { struct rkcif_rx_buffer { int buf_idx; struct list_head list; + struct list_head list_tool; struct list_head list_free; struct rkisp_rx_buf dbufs; struct rkcif_dummy_buffer dummy; struct rkisp_thunderboot_shmem shmem; u64 fe_timestamp; bool is_init[RKCIF_MAX_DEV]; + int use_cnt; }; enum rkcif_dma_en_mode { diff --git a/drivers/media/platform/rockchip/cif/subdev-itf.c b/drivers/media/platform/rockchip/cif/subdev-itf.c index bdd562341540..73f8b4376bc9 100644 --- a/drivers/media/platform/rockchip/cif/subdev-itf.c +++ b/drivers/media/platform/rockchip/cif/subdev-itf.c @@ -1345,6 +1345,26 @@ static int sditf_s_power(struct v4l2_subdev *sd, int on) return ret; } +static int sditf_check_toolbuf_return(struct rkcif_stream *stream, struct rkcif_rx_buffer *rx_buf) +{ + struct rkcif_tools_vdev *tools_vdev = stream->tools_vdev; + unsigned long flags; + + if (tools_vdev) { + spin_lock_irqsave(&stream->tools_vdev->vbq_lock, flags); + + if (rx_buf->use_cnt) + rx_buf->use_cnt--; + if (rx_buf->use_cnt) { + spin_unlock_irqrestore(&stream->tools_vdev->vbq_lock, flags); + return false; + } + spin_unlock_irqrestore(&stream->tools_vdev->vbq_lock, flags); + } + + return true; +} + static int sditf_s_rx_buffer(struct v4l2_subdev *sd, void *buf, unsigned int *size) { @@ -1422,7 +1442,8 @@ static int sditf_s_rx_buffer(struct v4l2_subdev *sd, is_free = true; } - if (!is_free && (!dbufs->is_switch) && stream->state == RKCIF_STATE_STREAMING) { + if (!is_free && (!dbufs->is_switch) && stream->state == RKCIF_STATE_STREAMING && + sditf_check_toolbuf_return(stream, rx_buf)) { list_add_tail(&rx_buf->list, &buf_stream->rx_buf_head); rkcif_assign_check_buffer_update_toisp(stream); if (cif_dev->resume_mode != RKISP_RTT_MODE_ONE_FRAME &&