From cedb72825d1bcd296ba097d9f7b3ed930b138b86 Mon Sep 17 00:00:00 2001 From: Zefa Chen Date: Tue, 27 Jun 2023 09:53:45 +0800 Subject: [PATCH] media: rockchip: vicap support tool video capture raw with rdbk by isp used in the case of thunderboot Signed-off-by: Zefa Chen Change-Id: I94e21fe6c130dd52f08cf695a5f1e46d555d7399 --- drivers/media/platform/rockchip/cif/capture.c | 89 ++++++++++++----- .../media/platform/rockchip/cif/cif-tools.c | 98 ++++++++++++++++++- drivers/media/platform/rockchip/cif/dev.h | 3 +- drivers/media/platform/rockchip/cif/procfs.c | 5 + .../media/platform/rockchip/cif/subdev-itf.c | 4 +- 5 files changed, 168 insertions(+), 31 deletions(-) diff --git a/drivers/media/platform/rockchip/cif/capture.c b/drivers/media/platform/rockchip/cif/capture.c index 94a2347feb78..ee29771164ca 100644 --- a/drivers/media/platform/rockchip/cif/capture.c +++ b/drivers/media/platform/rockchip/cif/capture.c @@ -1670,6 +1670,20 @@ static void rkcif_disable_skip_frame(struct rkcif_stream *stream) stream->skip_info.skip_en = false; } +static void rkcif_rdbk_with_tools(struct rkcif_stream *stream, + struct rkcif_rx_buffer *active_buf) +{ + 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 (!work_busy(&stream->tools_vdev->work)) + schedule_work(&stream->tools_vdev->work); + } + spin_unlock_irqrestore(&stream->tools_vdev->vbq_lock, flags); +} + static void rkcif_rdbk_frame_end_toisp(struct rkcif_stream *stream, struct rkcif_rx_buffer *buffer) { @@ -1734,6 +1748,12 @@ static void rkcif_rdbk_frame_end_toisp(struct rkcif_stream *stream, rkcif_s_rx_buffer(dev, &dev->rdbk_rx_buf[RDBK_L]->dbufs); rkcif_s_rx_buffer(dev, &dev->rdbk_rx_buf[RDBK_M]->dbufs); rkcif_s_rx_buffer(dev, &dev->rdbk_rx_buf[RDBK_S]->dbufs); + rkcif_rdbk_with_tools(&dev->stream[RDBK_L], dev->rdbk_rx_buf[RDBK_L]); + rkcif_rdbk_with_tools(&dev->stream[RDBK_M], dev->rdbk_rx_buf[RDBK_M]); + rkcif_rdbk_with_tools(&dev->stream[RDBK_S], dev->rdbk_rx_buf[RDBK_S]); + atomic_dec(&dev->stream[RDBK_L].buf_cnt); + atomic_dec(&dev->stream[RDBK_M].buf_cnt); + atomic_dec(&dev->stream[RDBK_S].buf_cnt); dev->rdbk_rx_buf[RDBK_L] = NULL; dev->rdbk_rx_buf[RDBK_M] = NULL; dev->rdbk_rx_buf[RDBK_S] = NULL; @@ -1772,6 +1792,10 @@ static void rkcif_rdbk_frame_end_toisp(struct rkcif_stream *stream, dev->rdbk_rx_buf[RDBK_M]->dbufs.sequence = dev->rdbk_rx_buf[RDBK_L]->dbufs.sequence; rkcif_s_rx_buffer(dev, &dev->rdbk_rx_buf[RDBK_L]->dbufs); rkcif_s_rx_buffer(dev, &dev->rdbk_rx_buf[RDBK_M]->dbufs); + rkcif_rdbk_with_tools(&dev->stream[RDBK_L], dev->rdbk_rx_buf[RDBK_L]); + rkcif_rdbk_with_tools(&dev->stream[RDBK_M], dev->rdbk_rx_buf[RDBK_M]); + atomic_dec(&dev->stream[RDBK_L].buf_cnt); + atomic_dec(&dev->stream[RDBK_M].buf_cnt); dev->rdbk_rx_buf[RDBK_L] = NULL; dev->rdbk_rx_buf[RDBK_M] = NULL; } @@ -1889,14 +1913,18 @@ static int rkcif_assign_new_buffer_update_toisp(struct rkcif_stream *stream, active_buf->dbufs.timestamp = stream->readout.fs_timestamp; active_buf->fe_timestamp = ktime_get_ns(); stream->last_frame_idx = stream->frame_idx; - if (dev->hdr.hdr_mode == NO_HDR) + if (dev->hdr.hdr_mode == NO_HDR) { rkcif_s_rx_buffer(dev, &active_buf->dbufs); - else + if (dev->is_support_tools && stream->tools_vdev) + rkcif_rdbk_with_tools(stream, active_buf); + atomic_dec(&stream->buf_cnt); + } else { rkcif_rdbk_frame_end_toisp(stream, active_buf); - stream->buf_num_toisp--; + } } else { - rkcif_s_rx_buffer(dev, &stream->next_buf_toisp->dbufs); - stream->buf_num_toisp--; + rkcif_s_rx_buffer(dev, &active_buf->dbufs); + if (dev->is_support_tools && stream->tools_vdev) + rkcif_rdbk_with_tools(stream, active_buf); } } else if (stream->frame_phase == CIF_CSI_FRAME1_READY) { if (stream->curr_buf_toisp == stream->next_buf_toisp) @@ -1918,14 +1946,18 @@ static int rkcif_assign_new_buffer_update_toisp(struct rkcif_stream *stream, active_buf->dbufs.timestamp = stream->readout.fs_timestamp; active_buf->fe_timestamp = ktime_get_ns(); stream->last_frame_idx = stream->frame_idx; - if (dev->hdr.hdr_mode == NO_HDR) + if (dev->hdr.hdr_mode == NO_HDR) { rkcif_s_rx_buffer(dev, &active_buf->dbufs); - else + if (dev->is_support_tools && stream->tools_vdev) + rkcif_rdbk_with_tools(stream, active_buf); + atomic_dec(&stream->buf_cnt); + } else { rkcif_rdbk_frame_end_toisp(stream, active_buf); - stream->buf_num_toisp--; + } } else { - rkcif_s_rx_buffer(dev, &stream->curr_buf_toisp->dbufs); - stream->buf_num_toisp--; + rkcif_s_rx_buffer(dev, &active_buf->dbufs); + if (dev->is_support_tools && stream->tools_vdev) + rkcif_rdbk_with_tools(stream, active_buf); } } if (stream->lack_buf_cnt) @@ -1967,10 +1999,14 @@ static int rkcif_assign_new_buffer_update_toisp(struct rkcif_stream *stream, active_buf->dbufs.timestamp = stream->readout.fs_timestamp; active_buf->fe_timestamp = ktime_get_ns(); stream->last_frame_idx = stream->frame_idx; - if (dev->hdr.hdr_mode == NO_HDR) + if (dev->hdr.hdr_mode == NO_HDR) { rkcif_s_rx_buffer(dev, &active_buf->dbufs); - else + if (dev->is_support_tools && stream->tools_vdev) + rkcif_rdbk_with_tools(stream, active_buf); + atomic_dec(&stream->buf_cnt); + } else { rkcif_rdbk_frame_end_toisp(stream, active_buf); + } } else { if (stream->cifdev->rdbk_debug && dev->hw_dev->dummy_buf.vaddr) v4l2_info(&stream->cifdev->v4l2_dev, @@ -1978,6 +2014,8 @@ static int rkcif_assign_new_buffer_update_toisp(struct rkcif_stream *stream, stream->id, stream->frame_idx - 1); } + if (dev->is_support_tools && stream->tools_vdev && stream->curr_buf_toisp) + rkcif_rdbk_with_tools(stream, stream->curr_buf_toisp); } out_get_buf: @@ -2091,7 +2129,6 @@ void rkcif_assign_check_buffer_update_toisp(struct rkcif_stream *stream) stream->id, stream->frame_idx - 1, frm_addr_y, (u32)stream->curr_buf_toisp->dummy.dma_addr); - stream->buf_num_toisp--; } } else if (frame_phase == CIF_CSI_FRAME1_READY) { active_buf = stream->next_buf_toisp; @@ -2109,7 +2146,6 @@ void rkcif_assign_check_buffer_update_toisp(struct rkcif_stream *stream) stream->id, stream->frame_idx - 1, frm_addr_y, (u32)stream->next_buf_toisp->dummy.dma_addr); - stream->buf_num_toisp--; } } if (stream->lack_buf_cnt) @@ -2439,7 +2475,6 @@ static int rkcif_assign_new_buffer_update(struct rkcif_stream *stream, } if (dbufs) rkcif_s_rx_buffer(dev, dbufs); - stream->buf_num_toisp--; } } else { if (stream->dma_en & RKCIF_DMAEN_BY_ISP) { @@ -2460,7 +2495,6 @@ static int rkcif_assign_new_buffer_update(struct rkcif_stream *stream, dbufs = &stream->curr_buf_toisp->dbufs; } rkcif_s_rx_buffer(dev, dbufs); - stream->buf_num_toisp--; if (stream->curr_buf && stream->frame_phase == CIF_CSI_FRAME0_READY) { stream->curr_buf = NULL; if (stream->buf_replace_cnt) @@ -2507,7 +2541,6 @@ stop_dma: } if (dbufs) rkcif_s_rx_buffer(dev, dbufs); - stream->buf_num_toisp--; if (stream->frame_phase == CIF_CSI_FRAME0_READY && stream->curr_buf) { @@ -3955,7 +3988,7 @@ static int rkcif_queue_setup(struct vb2_queue *queue, plane_fmt = &pixm->plane_fmt[i]; sizes[i] = plane_fmt->sizeimage / height * h; } - + stream->total_buf_num = *num_buffers; v4l2_dbg(1, rkcif_debug, &dev->v4l2_dev, "%s count %d, size %d, extended(%d, %d)\n", v4l2_type_names[queue->type], *num_buffers, sizes[0], is_extended, extend_line->is_extended); @@ -4230,6 +4263,8 @@ void rkcif_free_rx_buf(struct rkcif_stream *stream, int buf_num) rkcif_free_buffer(dev, &buf->dummy); else list_add_tail(&buf->list_free, &priv->buf_free_list); + atomic_dec(&stream->buf_cnt); + stream->total_buf_num--; } if (dev->is_thunderboot) { @@ -4323,7 +4358,6 @@ int rkcif_init_rx_buf(struct rkcif_stream *stream, int buf_num) if (priv && priv->mode.rdbk_mode == RKISP_VICAP_ONLINE && i == 0) { buf->dbufs.is_first = true; rkcif_s_rx_buffer(dev, &buf->dbufs); - stream->buf_num_toisp--; } i++; if (!dev->is_thunderboot && i >= buf_num) { @@ -4339,7 +4373,8 @@ int rkcif_init_rx_buf(struct rkcif_stream *stream, int buf_num) (u64)dummy->dma_addr, pixm->plane_fmt[0].sizeimage); } if (priv->buf_num) { - stream->buf_num_toisp = priv->buf_num; + stream->total_buf_num = priv->buf_num; + atomic_set(&stream->buf_cnt, priv->buf_num); return 0; } else { return -EINVAL; @@ -4665,7 +4700,7 @@ void rkcif_do_stop_stream(struct rkcif_stream *stream, vb2_buffer_done(&buf->vb.vb2_buf, VB2_BUF_STATE_ERROR); } } - + stream->total_buf_num = 0; atomic_set(&stream->buf_cnt, 0); stream->lack_buf_cnt = 0; stream->dma_en &= ~RKCIF_DMAEN_BY_VICAP; @@ -8313,8 +8348,10 @@ static void rkcif_release_unnecessary_buf_for_online(struct rkcif_stream *stream spin_lock_irqsave(&priv->cif_dev->buffree_lock, flags); for (i = 0; i < priv->buf_num; i++) { rx_buf = &stream->rx_buf[i]; - if (rx_buf && (!rx_buf->dummy.is_free) && rx_buf != buf) + if (rx_buf && (!rx_buf->dummy.is_free) && rx_buf != buf) { list_add_tail(&rx_buf->list_free, &priv->buf_free_list); + stream->total_buf_num--; + } } spin_unlock_irqrestore(&priv->cif_dev->buffree_lock, flags); schedule_work(&priv->buffree_work.work); @@ -8384,11 +8421,13 @@ static void rkcif_line_wake_up_rdbk(struct rkcif_stream *stream, int mipi_id) active_buf->dbufs.timestamp = stream->readout.fs_timestamp; active_buf->fe_timestamp = ktime_get_ns(); stream->last_frame_idx = stream->frame_idx; - if (stream->cifdev->hdr.hdr_mode == NO_HDR) + if (stream->cifdev->hdr.hdr_mode == NO_HDR) { rkcif_s_rx_buffer(stream->cifdev, &active_buf->dbufs); - else + if (stream->cifdev->is_support_tools && stream->tools_vdev) + rkcif_rdbk_with_tools(stream, active_buf); + } else { rkcif_rdbk_frame_end_toisp(stream, active_buf); - stream->buf_num_toisp--; + } } } } diff --git a/drivers/media/platform/rockchip/cif/cif-tools.c b/drivers/media/platform/rockchip/cif/cif-tools.c index 5c9f2b812623..e3a676c04b4b 100644 --- a/drivers/media/platform/rockchip/cif/cif-tools.c +++ b/drivers/media/platform/rockchip/cif/cif-tools.c @@ -589,11 +589,8 @@ static int rkcif_tools_init_vb2_queue(struct vb2_queue *q, return vb2_queue_init(q); } -static void rkcif_tools_work(struct work_struct *work) +static void rkcif_tools_buf_done(struct rkcif_tools_vdev *tools_vdev) { - struct rkcif_tools_vdev *tools_vdev = container_of(work, - struct rkcif_tools_vdev, - work); struct rkcif_stream *stream = tools_vdev->stream; struct rkcif_tools_buffer *tools_buf; const struct cif_output_fmt *fmt = tools_vdev->tools_out_fmt; @@ -700,6 +697,99 @@ retry_done_buf: spin_unlock_irqrestore(&tools_vdev->vbq_lock, flags); } +static void rkcif_tools_buf_done_rdbk(struct rkcif_tools_vdev *tools_vdev) +{ + struct rkcif_stream *stream = tools_vdev->stream; + struct rkcif_device *dev = stream->cifdev; + const struct cif_output_fmt *fmt = tools_vdev->tools_out_fmt; + struct rkcif_rx_buffer *buf = NULL; + int i = 0; + unsigned long flags; + +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); + if (buf) + list_del(&buf->list); + } + spin_unlock_irqrestore(&tools_vdev->vbq_lock, flags); + if (!buf) { + v4l2_err(&dev->v4l2_dev, "stream[%d] tools fail to get buf form list\n", + stream->id); + return; + } + + if (tools_vdev->stopping) { + rkcif_tools_stop(tools_vdev); + tools_vdev->stopping = false; + 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); + } + spin_unlock_irqrestore(&tools_vdev->vbq_lock, flags); + wake_up(&tools_vdev->wq_stopped); + return; + } + + if (!list_empty(&tools_vdev->buf_head)) { + tools_vdev->curr_buf = list_first_entry(&tools_vdev->buf_head, + struct rkcif_buffer, queue); + 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)) { + spin_unlock_irqrestore(&stream->tools_vdev->vbq_lock, flags); + goto retry_done_rdbk_buf; + } + spin_unlock_irqrestore(&tools_vdev->vbq_lock, flags); + return; + } + list_del(&tools_vdev->curr_buf->queue); + /* Dequeue a filled buffer */ + for (i = 0; i < fmt->mplanes; i++) { + u32 payload_size = tools_vdev->pixm.plane_fmt[i].sizeimage; + void *src = buf->dummy.vaddr; + void *dst = vb2_plane_vaddr(&tools_vdev->curr_buf->vb.vb2_buf, i); + + if (!src || !dst) + break; + dma_sync_single_for_device(dev->dev, + buf->dummy.dma_addr, + buf->dummy.size, + DMA_FROM_DEVICE); + vb2_set_plane_payload(&tools_vdev->curr_buf->vb.vb2_buf, i, + payload_size); + memcpy(dst, src, payload_size); + } + 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; + } + + spin_lock_irqsave(&tools_vdev->vbq_lock, flags); + if (!list_empty(&tools_vdev->buf_done_head)) { + spin_unlock_irqrestore(&stream->tools_vdev->vbq_lock, flags); + goto retry_done_rdbk_buf; + } + spin_unlock_irqrestore(&tools_vdev->vbq_lock, flags); +} + +static void rkcif_tools_work(struct work_struct *work) +{ + struct rkcif_tools_vdev *tools_vdev = container_of(work, + struct rkcif_tools_vdev, + work); + if (tools_vdev->stream->dma_en & RKCIF_DMAEN_BY_VICAP) + rkcif_tools_buf_done(tools_vdev); + else if (tools_vdev->stream->dma_en & RKCIF_DMAEN_BY_ISP) + rkcif_tools_buf_done_rdbk(tools_vdev); +} + void rkcif_init_tools_vdev(struct rkcif_device *cif_dev, u32 ch) { struct rkcif_tools_vdev *tools_vdev = &cif_dev->tools_vdev[ch]; diff --git a/drivers/media/platform/rockchip/cif/dev.h b/drivers/media/platform/rockchip/cif/dev.h index 503c5562f75d..8cdfab14fd27 100644 --- a/drivers/media/platform/rockchip/cif/dev.h +++ b/drivers/media/platform/rockchip/cif/dev.h @@ -193,6 +193,7 @@ struct rkcif_buffer { struct rkcif_tools_buffer { struct vb2_v4l2_buffer *vb; + struct rkisp_rx_buf *dbufs; struct list_head list; u32 frame_idx; u64 timestamp; @@ -526,7 +527,7 @@ struct rkcif_stream { unsigned int cur_stream_mode; struct rkcif_rx_buffer rx_buf[RKISP_VICAP_BUF_CNT_MAX]; struct list_head rx_buf_head; - int buf_num_toisp; + int total_buf_num; u64 line_int_cnt; int lack_buf_cnt; unsigned int buf_wake_up_cnt; diff --git a/drivers/media/platform/rockchip/cif/procfs.c b/drivers/media/platform/rockchip/cif/procfs.c index 9686faacf036..d9f063f63f13 100644 --- a/drivers/media/platform/rockchip/cif/procfs.c +++ b/drivers/media/platform/rockchip/cif/procfs.c @@ -376,6 +376,11 @@ static void rkcif_show_format(struct rkcif_device *dev, struct seq_file *f) atomic_read(&dev->stream[1].buf_cnt), atomic_read(&dev->stream[2].buf_cnt), atomic_read(&dev->stream[3].buf_cnt)); + seq_printf(f, "total buf_cnt: %d %d %d %d\n", + dev->stream[0].total_buf_num, + dev->stream[1].total_buf_num, + dev->stream[2].total_buf_num, + dev->stream[3].total_buf_num); } } diff --git a/drivers/media/platform/rockchip/cif/subdev-itf.c b/drivers/media/platform/rockchip/cif/subdev-itf.c index 7f850cc75e47..27f83002ca37 100644 --- a/drivers/media/platform/rockchip/cif/subdev-itf.c +++ b/drivers/media/platform/rockchip/cif/subdev-itf.c @@ -781,8 +781,8 @@ static int sditf_s_rx_buffer(struct v4l2_subdev *sd, rx_buf = to_cif_rx_buf(dbufs); spin_lock_irqsave(&stream->vbq_lock, flags); - stream->buf_num_toisp++; stream->last_rx_buf_idx = dbufs->sequence + 1; + atomic_inc(&stream->buf_cnt); if (!list_empty(&stream->rx_buf_head) && cif_dev->is_thunderboot && @@ -791,6 +791,8 @@ static int sditf_s_rx_buffer(struct v4l2_subdev *sd, spin_lock_irqsave(&cif_dev->buffree_lock, buffree_flags); list_add_tail(&rx_buf->list_free, &priv->buf_free_list); spin_unlock_irqrestore(&cif_dev->buffree_lock, buffree_flags); + atomic_dec(&stream->buf_cnt); + stream->total_buf_num--; schedule_work(&priv->buffree_work.work); is_free = true; }