From 61949a9b215c0d260cb134c3ccf272a0576053be Mon Sep 17 00:00:00 2001 From: Zefa Chen Date: Tue, 31 Oct 2023 10:32:40 +0800 Subject: [PATCH] media: rockchip: vicap fixes error when work on both thunderboot and quick suspend/resume Signed-off-by: Zefa Chen Change-Id: Ied9db7a3ed4e63735066424c48b6870830284588 --- drivers/media/platform/rockchip/cif/capture.c | 81 +++++++++++++++---- drivers/media/platform/rockchip/cif/dev.h | 1 + .../media/platform/rockchip/cif/subdev-itf.c | 47 ++++++----- 3 files changed, 91 insertions(+), 38 deletions(-) diff --git a/drivers/media/platform/rockchip/cif/capture.c b/drivers/media/platform/rockchip/cif/capture.c index 9a6ae02b2213..495c4ead57e7 100644 --- a/drivers/media/platform/rockchip/cif/capture.c +++ b/drivers/media/platform/rockchip/cif/capture.c @@ -4560,12 +4560,43 @@ void rkcif_free_rx_buf(struct rkcif_stream *stream, int buf_num) struct rkcif_rx_buffer *buf; struct rkcif_device *dev = stream->cifdev; struct sditf_priv *priv = dev->sditf[0]; + struct v4l2_subdev *sd; int i = 0; unsigned long flags; if (!priv) return; + sd = get_rkisp_sd(dev->sditf[0]); + if (!sd) + return; + + if (dev->is_rtt_suspend && dev->is_thunderboot) { + stream->curr_buf_toisp = NULL; + stream->next_buf_toisp = NULL; + INIT_LIST_HEAD(&stream->rx_buf_head); + + for (i = 0; i < buf_num; i++) { + buf = &stream->rx_buf[i]; + if (buf->dbufs.is_init) + v4l2_subdev_call(sd, core, ioctl, + RKISP_VICAP_CMD_RX_BUFFER_FREE, &buf->dbufs); + buf->dummy.is_free = true; + } + + if (buf_num > 2) { + for (i = buf_num - 1; i >= 2; i--) { + buf = &stream->rx_buf[i]; + list_add_tail(&buf->list_free, &priv->buf_free_list); + } + schedule_work(&priv->buffree_work.work); + atomic_set(&stream->buf_cnt, 0); + stream->total_buf_num = 0; + stream->rx_buf_num = 0; + } + return; + } + spin_lock_irqsave(&stream->vbq_lock, flags); stream->curr_buf_toisp = NULL; stream->next_buf_toisp = NULL; @@ -4578,6 +4609,9 @@ void rkcif_free_rx_buf(struct rkcif_stream *stream, int buf_num) buf = &stream->rx_buf[i]; if (buf->dummy.is_free) continue; + if (buf->dbufs.is_init) + v4l2_subdev_call(sd, core, ioctl, + RKISP_VICAP_CMD_RX_BUFFER_FREE, &buf->dbufs); if (!dev->is_thunderboot) rkcif_free_buffer(dev, &buf->dummy); else @@ -4585,6 +4619,7 @@ void rkcif_free_rx_buf(struct rkcif_stream *stream, int buf_num) atomic_dec(&stream->buf_cnt); stream->total_buf_num--; } + stream->rx_buf_num = 0; if (dev->is_thunderboot) { spin_unlock_irqrestore(&dev->buffree_lock, flags); @@ -4645,7 +4680,7 @@ int rkcif_init_rx_buf(struct rkcif_stream *stream, int buf_num) buf->buf_idx = i; ret = rkcif_alloc_reserved_mem_buf(dev, buf); if (ret) { - priv->buf_num = i; + stream->rx_buf_num = i; v4l2_info(&dev->v4l2_dev, "reserved mem support alloc buf num %d, require buf num %d\n", i, buf_num); @@ -4658,7 +4693,7 @@ int rkcif_init_rx_buf(struct rkcif_stream *stream, int buf_num) } else { ret = rkcif_alloc_buffer(dev, dummy); if (ret) { - priv->buf_num = i; + stream->rx_buf_num = i; v4l2_info(&dev->v4l2_dev, "alloc buf num %d, require buf num %d\n", i, buf_num); @@ -4681,10 +4716,10 @@ int rkcif_init_rx_buf(struct rkcif_stream *stream, int buf_num) } i++; if (!dev->is_thunderboot && i >= buf_num) { - priv->buf_num = buf_num; + stream->rx_buf_num = buf_num; break; } else if (i >= RKISP_VICAP_BUF_CNT_MAX) { - priv->buf_num = i; + stream->rx_buf_num = i; v4l2_info(&dev->v4l2_dev, "reserved mem alloc buf num %d\n", i); break; @@ -4693,9 +4728,9 @@ int rkcif_init_rx_buf(struct rkcif_stream *stream, int buf_num) "init rx_buf,dma_addr 0x%llx size: 0x%x\n", (u64)dummy->dma_addr, pixm->plane_fmt[0].sizeimage); } - if (priv->buf_num) { - stream->total_buf_num = priv->buf_num; - atomic_set(&stream->buf_cnt, priv->buf_num); + if (stream->rx_buf_num) { + stream->total_buf_num = stream->rx_buf_num; + atomic_set(&stream->buf_cnt, stream->rx_buf_num); return 0; } else { return -EINVAL; @@ -6632,6 +6667,7 @@ void rkcif_stream_init(struct rkcif_device *dev, u32 id) stream->is_stop_capture = false; stream->is_single_cap = false; atomic_set(&stream->buf_cnt, 0); + stream->rx_buf_num = 0; } static int rkcif_fh_open(struct file *filp) @@ -10624,20 +10660,31 @@ int rkcif_stream_resume(struct rkcif_device *cif_dev, int mode) } spin_unlock_irqrestore(&stream->vbq_lock, flags); + if (priv) { - if (capture_mode == RKCIF_STREAM_MODE_TOISP) + if (priv->mode.rdbk_mode == RKISP_VICAP_ONLINE) { sditf_change_to_online(priv); - else + if (cif_dev->resume_mode == RKISP_RTT_MODE_MULTI_FRAME && + stream->rx_buf_num && + (priv->hdr_cfg.hdr_mode == NO_HDR || + (priv->hdr_cfg.hdr_mode == HDR_X2 && stream->id == 1) || + (priv->hdr_cfg.hdr_mode == HDR_X3 && stream->id == 2))) + rkcif_free_rx_buf(stream, priv->buf_num); + else if (!stream->rx_buf_num && + ((priv->hdr_cfg.hdr_mode == HDR_X2 && stream->id == 0) || + (priv->hdr_cfg.hdr_mode == HDR_X3 && (stream->id == 0 || stream->id == 1)))) + rkcif_init_rx_buf(stream, 1); + } else { sditf_disable_immediately(priv); + if (!stream->rx_buf_num && + capture_mode == RKCIF_STREAM_MODE_TOISP_RDBK) { + if (cif_dev->resume_mode == RKISP_RTT_MODE_ONE_FRAME) + rkcif_init_rx_buf(stream, 1); + else + rkcif_init_rx_buf(stream, priv->buf_num); + } + } } - if (!stream->total_buf_num && priv && - (capture_mode == RKCIF_STREAM_MODE_TOISP_RDBK || - (capture_mode == RKCIF_STREAM_MODE_TOISP && - ((priv->hdr_cfg.hdr_mode == HDR_X2 && stream->id == 0) || - (priv->hdr_cfg.hdr_mode == HDR_X3 && (stream->id == 0 || stream->id == 1)))))) - rkcif_init_rx_buf(stream, 1); - if (priv && cif_dev->resume_mode == RKISP_RTT_MODE_MULTI_FRAME && stream->total_buf_num) - rkcif_init_rx_buf(stream, priv->buf_num); stream->lack_buf_cnt = 0; if (cif_dev->active_sensor && diff --git a/drivers/media/platform/rockchip/cif/dev.h b/drivers/media/platform/rockchip/cif/dev.h index 5122ec706f16..24c0860ae811 100644 --- a/drivers/media/platform/rockchip/cif/dev.h +++ b/drivers/media/platform/rockchip/cif/dev.h @@ -530,6 +530,7 @@ struct rkcif_stream { struct rkcif_rx_buffer rx_buf[RKISP_VICAP_BUF_CNT_MAX]; struct list_head rx_buf_head; int total_buf_num; + int rx_buf_num; u64 line_int_cnt; int lack_buf_cnt; unsigned int buf_wake_up_cnt; diff --git a/drivers/media/platform/rockchip/cif/subdev-itf.c b/drivers/media/platform/rockchip/cif/subdev-itf.c index 7ebeebde495c..10298a6c21e8 100644 --- a/drivers/media/platform/rockchip/cif/subdev-itf.c +++ b/drivers/media/platform/rockchip/cif/subdev-itf.c @@ -283,14 +283,14 @@ static void sditf_free_buf(struct sditf_priv *priv) struct rkcif_device *cif_dev = priv->cif_dev; if (priv->hdr_cfg.hdr_mode == HDR_X2) { - rkcif_free_rx_buf(&cif_dev->stream[0], priv->buf_num); - rkcif_free_rx_buf(&cif_dev->stream[1], priv->buf_num); + rkcif_free_rx_buf(&cif_dev->stream[0], cif_dev->stream[0].rx_buf_num); + rkcif_free_rx_buf(&cif_dev->stream[1], cif_dev->stream[1].rx_buf_num); } else if (priv->hdr_cfg.hdr_mode == HDR_X3) { - rkcif_free_rx_buf(&cif_dev->stream[0], priv->buf_num); - rkcif_free_rx_buf(&cif_dev->stream[1], priv->buf_num); - rkcif_free_rx_buf(&cif_dev->stream[2], priv->buf_num); + rkcif_free_rx_buf(&cif_dev->stream[0], cif_dev->stream[0].rx_buf_num); + rkcif_free_rx_buf(&cif_dev->stream[1], cif_dev->stream[1].rx_buf_num); + rkcif_free_rx_buf(&cif_dev->stream[2], cif_dev->stream[2].rx_buf_num); } else { - rkcif_free_rx_buf(&cif_dev->stream[0], priv->buf_num); + rkcif_free_rx_buf(&cif_dev->stream[0], cif_dev->stream[0].rx_buf_num); } if (cif_dev->is_thunderboot) { cif_dev->wait_line_cache = 0; @@ -622,22 +622,26 @@ void sditf_change_to_online(struct sditf_priv *priv) sditf_channel_enable(priv, 0); sditf_channel_enable(priv, 1); } - if (priv->hdr_cfg.hdr_mode == NO_HDR) { - rkcif_free_rx_buf(&cif_dev->stream[0], priv->buf_num); - cif_dev->stream[0].is_line_wake_up = false; - } else if (priv->hdr_cfg.hdr_mode == HDR_X2) { - rkcif_free_rx_buf(&cif_dev->stream[1], priv->buf_num); - cif_dev->stream[0].is_line_wake_up = false; - cif_dev->stream[1].is_line_wake_up = false; - } else if (priv->hdr_cfg.hdr_mode == HDR_X3) { - rkcif_free_rx_buf(&cif_dev->stream[2], priv->buf_num); - cif_dev->stream[0].is_line_wake_up = false; - cif_dev->stream[1].is_line_wake_up = false; - cif_dev->stream[2].is_line_wake_up = false; + + if (cif_dev->is_thunderboot) { + if (priv->hdr_cfg.hdr_mode == NO_HDR) { + rkcif_free_rx_buf(&cif_dev->stream[0], cif_dev->stream[0].rx_buf_num); + cif_dev->stream[0].is_line_wake_up = false; + } else if (priv->hdr_cfg.hdr_mode == HDR_X2) { + rkcif_free_rx_buf(&cif_dev->stream[1], cif_dev->stream[1].rx_buf_num); + cif_dev->stream[0].is_line_wake_up = false; + cif_dev->stream[1].is_line_wake_up = false; + } else if (priv->hdr_cfg.hdr_mode == HDR_X3) { + rkcif_free_rx_buf(&cif_dev->stream[2], cif_dev->stream[2].rx_buf_num); + cif_dev->stream[0].is_line_wake_up = false; + cif_dev->stream[1].is_line_wake_up = false; + cif_dev->stream[2].is_line_wake_up = false; + } + cif_dev->wait_line_cache = 0; + cif_dev->wait_line = 0; + cif_dev->wait_line_bak = 0; + cif_dev->is_thunderboot = false; } - cif_dev->wait_line_cache = 0; - cif_dev->wait_line = 0; - cif_dev->wait_line_bak = 0; } void sditf_disable_immediately(struct sditf_priv *priv) @@ -862,6 +866,7 @@ static int sditf_s_rx_buffer(struct v4l2_subdev *sd, if (!list_empty(&stream->rx_buf_head) && cif_dev->is_thunderboot && + (!cif_dev->is_rtt_suspend) && (dbufs->type == BUF_SHORT || (dbufs->type != BUF_SHORT && (!dbufs->is_switch)))) { spin_lock_irqsave(&cif_dev->buffree_lock, buffree_flags);