diff --git a/drivers/media/platform/rockchip/isp/capture_v21.c b/drivers/media/platform/rockchip/isp/capture_v21.c index 27cf9c641053..a24375610d4e 100644 --- a/drivers/media/platform/rockchip/isp/capture_v21.c +++ b/drivers/media/platform/rockchip/isp/capture_v21.c @@ -1207,6 +1207,22 @@ static void destroy_buf_queue(struct rkisp_stream *stream, spin_unlock_irqrestore(&stream->vbq_lock, lock_flags); } +static void rkisp_stop_streaming_tx(struct rkisp_stream *stream) +{ + struct rkisp_device *dev = stream->ispdev; + + stream->stopping = true; + if (dev->isp_state & ISP_START && + !stream->ops->is_stream_stopped(dev->base_addr)) { + stream->ops->stop_mi(stream); + wait_event_timeout(stream->done, !stream->streaming, + msecs_to_jiffies(300)); + } + stream->stopping = false; + stream->streaming = false; + destroy_buf_queue(stream, VB2_BUF_STATE_ERROR); +} + static void rkisp_stop_streaming(struct vb2_queue *queue) { struct rkisp_stream *stream = queue->drv_priv; @@ -1215,24 +1231,23 @@ static void rkisp_stop_streaming(struct vb2_queue *queue) struct v4l2_device *v4l2_dev = &dev->v4l2_dev; int ret; - mutex_lock(&dev->hw_dev->dev_lock); - v4l2_dbg(1, rkisp_debug, &dev->v4l2_dev, "%s %d\n", __func__, stream->id); - if (!stream->streaming) - goto end; + return; + + if (stream->id != RKISP_STREAM_MP && stream->id != RKISP_STREAM_SP) + return rkisp_stop_streaming_tx(stream); + + mutex_lock(&dev->hw_dev->dev_lock); rkisp_stream_stop(stream); - if (stream->id == RKISP_STREAM_MP || - stream->id == RKISP_STREAM_SP) { - /* call to the other devices */ - media_pipeline_stop(&node->vdev.entity); - ret = dev->pipe.set_stream(&dev->pipe, false); - if (ret < 0) - v4l2_err(v4l2_dev, - "pipeline stream-off failed:%d\n", ret); - } + /* call to the other devices */ + media_pipeline_stop(&node->vdev.entity); + ret = dev->pipe.set_stream(&dev->pipe, false); + if (ret < 0) + v4l2_err(v4l2_dev, + "pipeline stream-off failed:%d\n", ret); /* release buffers */ destroy_buf_queue(stream, VB2_BUF_STATE_ERROR); @@ -1243,7 +1258,6 @@ static void rkisp_stop_streaming(struct vb2_queue *queue) rkisp_destroy_dummy_buf(stream); atomic_dec(&dev->cap_dev.refcnt); -end: mutex_unlock(&dev->hw_dev->dev_lock); } @@ -1285,6 +1299,25 @@ end: return rkisp_start(stream); } +static int +rkisp_start_streaming_tx(struct rkisp_stream *stream) +{ + struct rkisp_device *dev = stream->ispdev; + int ret = -1; + + if (!dev->isp_inp || !stream->linked) + goto buffer_done; + + ret = rkisp_stream_start(stream); + if (ret < 0) + goto buffer_done; + return 0; +buffer_done: + destroy_buf_queue(stream, VB2_BUF_STATE_QUEUED); + stream->streaming = false; + return ret; +} + static int rkisp_start_streaming(struct vb2_queue *queue, unsigned int count) { @@ -1294,17 +1327,16 @@ rkisp_start_streaming(struct vb2_queue *queue, unsigned int count) struct v4l2_device *v4l2_dev = &dev->v4l2_dev; int ret = -1; - mutex_lock(&dev->hw_dev->dev_lock); - v4l2_dbg(1, rkisp_debug, &dev->v4l2_dev, "%s %d\n", __func__, stream->id); - - if (WARN_ON(stream->streaming)) { - mutex_unlock(&dev->hw_dev->dev_lock); + if (WARN_ON(stream->streaming)) return -EBUSY; - } - memset(&stream->dbg, 0, sizeof(stream->dbg)); + + if (stream->id != RKISP_STREAM_MP && stream->id != RKISP_STREAM_SP) + return rkisp_start_streaming_tx(stream); + + mutex_lock(&dev->hw_dev->dev_lock); atomic_inc(&dev->cap_dev.refcnt); if (!dev->isp_inp || !stream->linked) { v4l2_err(v4l2_dev, "check video link or isp input\n"); @@ -1354,19 +1386,16 @@ rkisp_start_streaming(struct vb2_queue *queue, unsigned int count) goto close_pipe; } - if (stream->id == RKISP_STREAM_MP || - stream->id == RKISP_STREAM_SP) { - /* start sub-devices */ - ret = dev->pipe.set_stream(&dev->pipe, true); - if (ret < 0) - goto stop_stream; + /* start sub-devices */ + ret = dev->pipe.set_stream(&dev->pipe, true); + if (ret < 0) + goto stop_stream; - ret = media_pipeline_start(&node->vdev.entity, &dev->pipe.pipe); - if (ret < 0) { - v4l2_err(&dev->v4l2_dev, - "start pipeline failed %d\n", ret); - goto pipe_stream_off; - } + ret = media_pipeline_start(&node->vdev.entity, &dev->pipe.pipe); + if (ret < 0) { + v4l2_err(&dev->v4l2_dev, + "start pipeline failed %d\n", ret); + goto pipe_stream_off; } mutex_unlock(&dev->hw_dev->dev_lock);