diff --git a/drivers/media/platform/rockchip/cif/capture.c b/drivers/media/platform/rockchip/cif/capture.c index 98df4f36c627..6f2df9432e16 100644 --- a/drivers/media/platform/rockchip/cif/capture.c +++ b/drivers/media/platform/rockchip/cif/capture.c @@ -5079,10 +5079,12 @@ void rkcif_do_stop_stream(struct rkcif_stream *stream, dev->wait_line = 0; stream->is_line_wake_up = false; } - tasklet_disable(&stream->vb_done_tasklet); + if (can_reset && hw_dev->dummy_buf.vaddr) + rkcif_destroy_dummy_buf(stream); } - if (can_reset && hw_dev->dummy_buf.vaddr) - rkcif_destroy_dummy_buf(stream); + if (mode == RKCIF_STREAM_MODE_CAPTURE) + tasklet_disable(&stream->vb_done_tasklet); + stream->cur_stream_mode &= ~mode; INIT_LIST_HEAD(&stream->vb_done_list); v4l2_info(&dev->v4l2_dev, "stream[%d] stopping finished, dma_en 0x%x\n", stream->id, stream->dma_en); @@ -6213,8 +6215,10 @@ int rkcif_do_start_stream(struct rkcif_stream *stream, unsigned int mode) } mutex_unlock(&hw_dev->dev_lock); - if (stream->cur_stream_mode == RKCIF_STREAM_MODE_NONE) { + if (mode == RKCIF_STREAM_MODE_CAPTURE) tasklet_enable(&stream->vb_done_tasklet); + + if (stream->cur_stream_mode == RKCIF_STREAM_MODE_NONE) { ret = dev->pipe.open(&dev->pipe, &node->vdev.entity, true); if (ret < 0) { v4l2_err(v4l2_dev, "open cif pipeline failed %d\n", @@ -6232,7 +6236,7 @@ int rkcif_do_start_stream(struct rkcif_stream *stream, unsigned int mode) rkmodule_stream_seq == RKMODULE_START_STREAM_FRONT) { ret = dev->pipe.set_stream(&dev->pipe, true); if (ret < 0) - goto runtime_put; + goto destroy_buf; } } if (dev->chip_id >= CHIP_RK1808_CIF) { @@ -6248,7 +6252,7 @@ int rkcif_do_start_stream(struct rkcif_stream *stream, unsigned int mode) } if (ret < 0) - goto runtime_put; + goto destroy_buf; if (stream->cur_stream_mode == RKCIF_STREAM_MODE_NONE) { ret = media_pipeline_start(&node->vdev.entity, &dev->pipe.pipe); @@ -6294,15 +6298,19 @@ stop_stream: rkcif_stream_stop(stream); pipe_stream_off: dev->pipe.set_stream(&dev->pipe, false); -runtime_put: - pm_runtime_put_sync(dev->dev); + destroy_buf: - if (stream->next_buf) - vb2_buffer_done(&stream->next_buf->vb.vb2_buf, - VB2_BUF_STATE_QUEUED); + if (mode == RKCIF_STREAM_MODE_CAPTURE) + tasklet_disable(&stream->vb_done_tasklet); if (stream->curr_buf) - vb2_buffer_done(&stream->curr_buf->vb.vb2_buf, - VB2_BUF_STATE_QUEUED); + list_add_tail(&stream->curr_buf->queue, &stream->buf_head); + if (stream->next_buf && + stream->next_buf != stream->curr_buf) + list_add_tail(&stream->next_buf->queue, &stream->buf_head); + + stream->curr_buf = NULL; + stream->next_buf = NULL; + atomic_set(&stream->buf_cnt, 0); while (!list_empty(&stream->buf_head)) { struct rkcif_buffer *buf; diff --git a/drivers/media/platform/rockchip/cif/subdev-itf.c b/drivers/media/platform/rockchip/cif/subdev-itf.c index 9020fff82c63..3df42731f17d 100644 --- a/drivers/media/platform/rockchip/cif/subdev-itf.c +++ b/drivers/media/platform/rockchip/cif/subdev-itf.c @@ -627,36 +627,39 @@ static int sditf_start_stream(struct sditf_priv *priv) struct rkcif_device *cif_dev = priv->cif_dev; struct v4l2_subdev_format fmt; unsigned int mode = RKCIF_STREAM_MODE_TOISP; + int ret = 0; sditf_check_capture_mode(cif_dev); sditf_get_set_fmt(&priv->sd, NULL, &fmt); if (priv->mode.rdbk_mode == RKISP_VICAP_ONLINE) { if (priv->toisp_inf.link_mode == TOISP0) { - sditf_channel_enable(priv, 0); + ret = sditf_channel_enable(priv, 0); } else if (priv->toisp_inf.link_mode == TOISP1) { - sditf_channel_enable(priv, 1); + ret = sditf_channel_enable(priv, 1); } else if (priv->toisp_inf.link_mode == TOISP_UNITE) { - sditf_channel_enable(priv, 0); - sditf_channel_enable(priv, 1); + ret = sditf_channel_enable(priv, 0); + ret |= sditf_channel_enable(priv, 1); } mode = RKCIF_STREAM_MODE_TOISP; } else if (priv->mode.rdbk_mode == RKISP_VICAP_RDBK_AUTO) { mode = RKCIF_STREAM_MODE_TOISP_RDBK; } + if (ret) + return ret; if (priv->hdr_cfg.hdr_mode == NO_HDR || priv->hdr_cfg.hdr_mode == HDR_COMPR) { - rkcif_do_start_stream(&cif_dev->stream[0], mode); + ret = rkcif_do_start_stream(&cif_dev->stream[0], mode); } else if (priv->hdr_cfg.hdr_mode == HDR_X2) { - rkcif_do_start_stream(&cif_dev->stream[0], mode); - rkcif_do_start_stream(&cif_dev->stream[1], mode); + ret = rkcif_do_start_stream(&cif_dev->stream[0], mode); + ret |= rkcif_do_start_stream(&cif_dev->stream[1], mode); } else if (priv->hdr_cfg.hdr_mode == HDR_X3) { - rkcif_do_start_stream(&cif_dev->stream[0], mode); - rkcif_do_start_stream(&cif_dev->stream[1], mode); - rkcif_do_start_stream(&cif_dev->stream[2], mode); + ret = rkcif_do_start_stream(&cif_dev->stream[0], mode); + ret |= rkcif_do_start_stream(&cif_dev->stream[1], mode); + ret |= rkcif_do_start_stream(&cif_dev->stream[2], mode); } INIT_LIST_HEAD(&priv->buf_free_list); - return 0; + return ret; } static int sditf_stop_stream(struct sditf_priv *priv) @@ -718,6 +721,8 @@ static int sditf_s_stream(struct v4l2_subdev *sd, int on) } } + if (on && ret) + atomic_dec(&priv->stream_cnt); return ret; } @@ -745,6 +750,7 @@ static int sditf_s_power(struct v4l2_subdev *sd, int on) } else { v4l2_pipeline_pm_put(&node->vdev.entity); pm_runtime_put_sync(cif_dev->dev); + priv->mode.rdbk_mode = RKISP_VICAP_RDBK_AIQ; } v4l2_info(&node->vdev, "s_power %d, entity use_count %d\n", on, node->vdev.entity.use_count);