From ac1a7923655b243e0b41d34ee626ec9f80ee9e53 Mon Sep 17 00:00:00 2001 From: Zefa Chen Date: Thu, 31 Mar 2022 18:02:29 +0800 Subject: [PATCH] media: rockchip: vicap check the synchronization of each group of frames Signed-off-by: Zefa Chen Change-Id: Ic2c40899649bfc5a8fc4ef291f5b05f586f328d7 --- drivers/media/platform/rockchip/cif/capture.c | 110 +++++++++++------- drivers/media/platform/rockchip/cif/hw.c | 2 +- drivers/media/platform/rockchip/cif/hw.h | 6 +- drivers/media/platform/rockchip/cif/procfs.c | 2 +- 4 files changed, 75 insertions(+), 45 deletions(-) diff --git a/drivers/media/platform/rockchip/cif/capture.c b/drivers/media/platform/rockchip/cif/capture.c index 62e1f2f79f29..c0bfafb7b3d5 100644 --- a/drivers/media/platform/rockchip/cif/capture.c +++ b/drivers/media/platform/rockchip/cif/capture.c @@ -2099,7 +2099,7 @@ static int rkcif_csi_channel_init(struct rkcif_stream *stream, channel->vc = vc >= 0 ? vc : channel->id; else channel->vc = channel->id; - v4l2_dbg(3, rkcif_debug, &dev->v4l2_dev, + v4l2_dbg(1, rkcif_debug, &dev->v4l2_dev, "%s: channel width %d, height %d, virtual_width %d, vc %d\n", __func__, channel->width, channel->height, channel->virtual_width, channel->vc); return 0; @@ -2780,7 +2780,7 @@ static void rkcif_check_buffer_update_pingpong(struct rkcif_stream *stream, get_dvp_reg_index_of_frm0_uv_addr(channel_id) : get_dvp_reg_index_of_frm1_uv_addr(channel_id); } - v4l2_dbg(1, rkcif_debug, &stream->cifdev->v4l2_dev, + v4l2_dbg(2, rkcif_debug, &stream->cifdev->v4l2_dev, "stream[%d] update buf in %s, stream->frame_phase_cache %d\n", stream->id, __func__, stream->frame_phase_cache); spin_lock_irqsave(&stream->vbq_lock, flags); @@ -2878,7 +2878,7 @@ static void rkcif_buf_queue(struct vb2_buffer *vb) spin_unlock_irqrestore(&stream->vbq_lock, flags); if (stream->cifdev->workmode == RKCIF_WORKMODE_PINGPONG) rkcif_check_buffer_update_pingpong(stream, stream->id); - v4l2_dbg(1, rkcif_debug, &stream->cifdev->v4l2_dev, + v4l2_dbg(2, rkcif_debug, &stream->cifdev->v4l2_dev, "stream[%d] buf queue, index: %d\n", stream->id, vb->index); } @@ -3213,8 +3213,6 @@ void rkcif_do_stop_stream(struct rkcif_stream *stream, vb2_buffer_done(&buf->vb.vb2_buf, VB2_BUF_STATE_ERROR); } stream->dma_en &= ~RKCIF_DMAEN_BY_VICAP; - if (dev->sync_type != RKCIF_NOSYNC_MODE) - dev->hw_dev->is_in_group_sync = false; } if (mode == stream->cur_stream_mode) { @@ -4058,18 +4056,21 @@ static void rkcif_attach_sync_mode(struct rkcif_hw *hw) hw->sync_config.ext_master.count++; hw->sync_config.dev_cnt++; dev->sync_type = EXTERNAL_MASTER_MODE; + hw->sync_config.sync_mask |= BIT(dev->csi_host_idx); } else if (sync_type == INTERNAL_MASTER_MODE) { count = hw->sync_config.int_master.count; hw->sync_config.int_master.cif_dev[count] = dev; hw->sync_config.int_master.count++; hw->sync_config.dev_cnt++; dev->sync_type = INTERNAL_MASTER_MODE; + hw->sync_config.sync_mask |= BIT(dev->csi_host_idx); } else if (sync_type == SLAVE_MODE) { count = hw->sync_config.slave.count; hw->sync_config.slave.cif_dev[count] = dev; hw->sync_config.slave.count++; hw->sync_config.dev_cnt++; dev->sync_type = SLAVE_MODE; + hw->sync_config.sync_mask |= BIT(dev->csi_host_idx); } } } @@ -5631,7 +5632,7 @@ static void rkcif_vb_done_oneframe(struct rkcif_stream *stream, vb_done->vb2_buf.timestamp = ktime_get_ns(); vb2_buffer_done(&vb_done->vb2_buf, VB2_BUF_STATE_DONE); - v4l2_dbg(1, rkcif_debug, &stream->cifdev->v4l2_dev, + v4l2_dbg(2, rkcif_debug, &stream->cifdev->v4l2_dev, "stream[%d] vb done, index: %d, sequence %d\n", stream->id, vb_done->vb2_buf.index, vb_done->sequence); } @@ -5718,11 +5719,10 @@ void rkcif_irq_oneframe(struct rkcif_device *cif_dev) RKCIF_YUV_ADDR_STATE_UPDATE); if (vb_done && (!ret)) { - vb_done->sequence = stream->frame_idx; + vb_done->sequence = stream->frame_idx - 1; rkcif_vb_done_oneframe(stream, vb_done); } - stream->frame_idx++; cif_dev->irq_stats.all_frm_end_cnt++; } } @@ -6125,7 +6125,7 @@ static void rkcif_monitor_reset_event(struct rkcif_device *dev) spin_unlock_irqrestore(&timer->timer_lock, flags); - v4l2_dbg(1, rkcif_debug, &dev->v4l2_dev, + v4l2_dbg(3, rkcif_debug, &dev->v4l2_dev, "%s:mode:%d, raw height:%d,vblank:%d, cycle:%ld, fps:%llu\n", __func__, timer->monitor_mode, raw_rect->height, vblank, timer->cycle, div_u64(1000, fps)); @@ -6194,8 +6194,8 @@ static void rkcif_rdbk_frame_end(struct rkcif_stream *stream) goto RDBK_FRM_UNMATCH; } } - dev->rdbk_buf[RDBK_L]->vb.sequence = dev->rdbk_buf[RDBK_S]->vb.sequence; - dev->rdbk_buf[RDBK_M]->vb.sequence = dev->rdbk_buf[RDBK_S]->vb.sequence; + dev->rdbk_buf[RDBK_M]->vb.sequence = dev->rdbk_buf[RDBK_L]->vb.sequence; + dev->rdbk_buf[RDBK_S]->vb.sequence = dev->rdbk_buf[RDBK_L]->vb.sequence; rkcif_vb_done_oneframe(&dev->stream[RKCIF_STREAM_MIPI_ID0], &dev->rdbk_buf[RDBK_L]->vb); rkcif_vb_done_oneframe(&dev->stream[RKCIF_STREAM_MIPI_ID1], @@ -6243,7 +6243,7 @@ static void rkcif_rdbk_frame_end(struct rkcif_stream *stream) goto RDBK_FRM_UNMATCH; } } - dev->rdbk_buf[RDBK_L]->vb.sequence = dev->rdbk_buf[RDBK_M]->vb.sequence; + dev->rdbk_buf[RDBK_M]->vb.sequence = dev->rdbk_buf[RDBK_L]->vb.sequence; rkcif_vb_done_oneframe(&dev->stream[RKCIF_STREAM_MIPI_ID0], &dev->rdbk_buf[RDBK_L]->vb); rkcif_vb_done_oneframe(&dev->stream[RKCIF_STREAM_MIPI_ID1], @@ -6295,7 +6295,7 @@ static void rkcif_buf_done_prepare(struct rkcif_stream *stream, if (active_buf) { vb_done = &active_buf->vb; vb_done->vb2_buf.timestamp = stream->readout.fs_timestamp; - vb_done->sequence = stream->frame_idx; + vb_done->sequence = stream->frame_idx - 1; if (stream->is_line_wake_up) { spin_lock_irqsave(&stream->fps_lock, flags); if (mode) @@ -6408,8 +6408,6 @@ static void rkcif_line_wake_up(struct rkcif_stream *stream, int mipi_id) end_wake_up: if (mipi_id == RKCIF_STREAM_MIPI_ID0) cif_dev->buf_wake_up_cnt += 1; - stream->frame_idx++; - } static void rkcif_deal_readout_time(struct rkcif_stream *stream) @@ -6452,8 +6450,6 @@ static void rkcif_update_stream(struct rkcif_device *cif_dev, v4l2_err(&cif_dev->v4l2_dev, "stream[%d], frm0/frm1 end simultaneously,frm id:%d\n", stream->id, stream->frame_idx); - - stream->frame_idx++; return; } if (!stream->is_line_wake_up) { @@ -6476,17 +6472,12 @@ static void rkcif_update_stream(struct rkcif_device *cif_dev, if (cif_dev->inf_id == RKCIF_MIPI_LVDS) rkcif_deal_readout_time(stream); - if (cif_dev->chip_id == CHIP_RV1126_CIF || - cif_dev->chip_id == CHIP_RV1126_CIF_LITE || - cif_dev->chip_id == CHIP_RK3568_CIF) - rkcif_luma_isr(&cif_dev->luma_vdev, mipi_id, stream->frame_idx); - if (!stream->is_line_wake_up) { ret = rkcif_assign_new_buffer_pingpong(stream, RKCIF_YUV_ADDR_STATE_UPDATE, mipi_id); if (ret) - goto end; + return; } else { ret = rkcif_update_new_buffer_wake_up_mode(stream); if (ret) @@ -6495,9 +6486,10 @@ static void rkcif_update_stream(struct rkcif_device *cif_dev, if (!stream->is_line_wake_up) rkcif_buf_done_prepare(stream, active_buf, mipi_id, 0); -end: - if (!stream->is_line_wake_up) - stream->frame_idx++; + if (cif_dev->chip_id == CHIP_RV1126_CIF || + cif_dev->chip_id == CHIP_RV1126_CIF_LITE || + cif_dev->chip_id == CHIP_RK3568_CIF) + rkcif_luma_isr(&cif_dev->luma_vdev, mipi_id, cif_dev->stream[0].frame_idx - 1); } static void rkcif_update_stream_toisp(struct rkcif_device *cif_dev, @@ -7354,6 +7346,17 @@ static int rkcif_check_group_sync_state(struct rkcif_device *cif_dev) int i = 0; int ret = 0; + hw->sync_config.sync_code |= BIT(cif_dev->csi_host_idx); + if (hw->sync_config.sync_code != hw->sync_config.sync_mask) + return -EINVAL; + + v4l2_dbg(3, rkcif_debug, &cif_dev->v4l2_dev, + "sync code 0x%x, mask 0x%x, update 0x%x, cache 0x%x\n", + hw->sync_config.sync_code, + hw->sync_config.sync_mask, + hw->sync_config.update_code, + hw->sync_config.update_cache); + for (i = 0; i < hw->sync_config.dev_cnt; i++) { if (hw->sync_config.mode == RKCIF_MASTER_MASTER) { if (i < hw->sync_config.ext_master.count) @@ -7408,7 +7411,6 @@ static void rkcif_deal_sof(struct rkcif_device *cif_dev) struct rkcif_hw *hw = cif_dev->hw_dev; struct rkcif_device *tmp_dev = NULL; unsigned long flags; - unsigned int frame_idx = 0; int i = 0; int ret = 0; @@ -7417,10 +7419,17 @@ static void rkcif_deal_sof(struct rkcif_device *cif_dev) detect_stream->readout.fs_timestamp = ktime_get_ns(); spin_unlock_irqrestore(&detect_stream->fps_lock, flags); - if (cif_dev->sync_type != RKCIF_NOSYNC_MODE && !hw->is_in_group_sync) { + if (cif_dev->sync_type != RKCIF_NOSYNC_MODE) { ret = rkcif_check_group_sync_state(cif_dev); if (!ret) { - hw->is_in_group_sync = true; + hw->sync_config.sync_code = 0; + spin_lock_irqsave(&hw->group_lock, flags); + hw->sync_config.update_cache = hw->sync_config.sync_mask; + if (!hw->sync_config.update_code) { + hw->sync_config.update_code = hw->sync_config.update_cache; + hw->sync_config.update_cache = 0; + } + spin_unlock_irqrestore(&hw->group_lock, flags); for (i = 0; i < hw->sync_config.dev_cnt; i++) { if (hw->sync_config.mode == RKCIF_MASTER_MASTER) { if (i < hw->sync_config.ext_master.count) @@ -7438,16 +7447,13 @@ static void rkcif_deal_sof(struct rkcif_device *cif_dev) } if (tmp_dev) { rkcif_send_sof(tmp_dev); - frame_idx = rkcif_get_sof(tmp_dev); - tmp_dev->stream[0].frame_idx = frame_idx; - tmp_dev->stream[1].frame_idx = frame_idx; - tmp_dev->stream[2].frame_idx = frame_idx; - tmp_dev->stream[3].frame_idx = frame_idx; + tmp_dev->stream[0].frame_idx++; } } } } else { rkcif_send_sof(cif_dev); + detect_stream->frame_idx++; } } @@ -7458,7 +7464,7 @@ unsigned int rkcif_irq_global(struct rkcif_device *cif_dev) intstat_glb = rkcif_read_register(cif_dev, CIF_REG_GLB_INTST); if (intstat_glb) { rkcif_write_register(cif_dev, CIF_REG_GLB_INTST, intstat_glb); - v4l2_dbg(3, rkcif_debug, &cif_dev->v4l2_dev, + v4l2_dbg(1, rkcif_debug, &cif_dev->v4l2_dev, "intstat_glb 0x%x\n", intstat_glb); } @@ -7479,6 +7485,25 @@ unsigned int rkcif_irq_global(struct rkcif_device *cif_dev) return intstat_glb; } +static bool rkcif_check_buffer_prepare(struct rkcif_device *cif_dev) +{ + unsigned long flags; + bool is_update = false; + + spin_lock_irqsave(&cif_dev->hw_dev->group_lock, flags); + if (cif_dev->hw_dev->sync_config.update_code & BIT(cif_dev->csi_host_idx)) { + is_update = true; + cif_dev->hw_dev->sync_config.update_code &= ~(BIT(cif_dev->csi_host_idx)); + if (!cif_dev->hw_dev->sync_config.update_code && + cif_dev->hw_dev->sync_config.update_cache) { + cif_dev->hw_dev->sync_config.update_code = cif_dev->hw_dev->sync_config.update_cache; + cif_dev->hw_dev->sync_config.update_cache = 0; + } + } + spin_unlock_irqrestore(&cif_dev->hw_dev->group_lock, flags); + return is_update; +} + /* pingpong irq for rk3588 and next */ void rkcif_irq_pingpong_v1(struct rkcif_device *cif_dev) { @@ -7487,6 +7512,7 @@ void rkcif_irq_pingpong_v1(struct rkcif_device *cif_dev) struct v4l2_mbus_config *mbus; unsigned int intstat, i = 0xff, bak_intstat = 0; unsigned long flags; + bool is_update = false; if (!cif_dev->active_sensor) return; @@ -7505,7 +7531,7 @@ void rkcif_irq_pingpong_v1(struct rkcif_device *cif_dev) if (intstat) { bak_intstat = intstat; rkcif_write_register(cif_dev, CIF_REG_MIPI_LVDS_INTSTAT, intstat); - v4l2_dbg(3, rkcif_debug, &cif_dev->v4l2_dev, + v4l2_dbg(1, rkcif_debug, &cif_dev->v4l2_dev, "intstat 0x%x\n", intstat); } else { @@ -7551,6 +7577,7 @@ void rkcif_irq_pingpong_v1(struct rkcif_device *cif_dev) } else { spin_lock_irqsave(&stream->fps_lock, flags); stream->readout.fs_timestamp = ktime_get_ns(); + stream->frame_idx++; spin_unlock_irqrestore(&stream->fps_lock, flags); } } @@ -7613,12 +7640,12 @@ void rkcif_irq_pingpong_v1(struct rkcif_device *cif_dev) rkcif_dynamic_crop(stream); if (stream->dma_en & RKCIF_DMAEN_BY_VICAP) { - if (cif_dev->sync_type == RKCIF_NOSYNC_MODE) { + if (cif_dev->sync_type == RKCIF_NOSYNC_MODE) + is_update = true; + else + is_update = rkcif_check_buffer_prepare(cif_dev); + if (is_update) rkcif_update_stream(cif_dev, stream, mipi_id); - } else { - if (cif_dev->hw_dev->is_in_group_sync) - rkcif_update_stream(cif_dev, stream, mipi_id); - } } else if (stream->dma_en & RKCIF_DMAEN_BY_ISP) { rkcif_update_stream_toisp(cif_dev, stream, mipi_id); } @@ -7644,7 +7671,6 @@ void rkcif_irq_pingpong_v1(struct rkcif_device *cif_dev) detect_stream->fs_cnt_in_single_frame); detect_stream->is_fs_fe_not_paired = true; detect_stream->fs_cnt_in_single_frame = 0; - cif_dev->hw_dev->is_in_group_sync = false; } else { detect_stream->fs_cnt_in_single_frame--; } diff --git a/drivers/media/platform/rockchip/cif/hw.c b/drivers/media/platform/rockchip/cif/hw.c index b27f101de9b6..e694e5e4ece7 100644 --- a/drivers/media/platform/rockchip/cif/hw.c +++ b/drivers/media/platform/rockchip/cif/hw.c @@ -1151,7 +1151,6 @@ static int rkcif_plat_hw_probe(struct platform_device *pdev) cif_hw->chip_id = data->chip_id; cif_hw->sync_config.is_attach = false; cif_hw->sync_config.mode = RKCIF_NOSYNC_MODE; - cif_hw->is_in_group_sync = false; if (data->chip_id >= CHIP_RK1808_CIF) { res = platform_get_resource_byname(pdev, IORESOURCE_MEM, @@ -1214,6 +1213,7 @@ static int rkcif_plat_hw_probe(struct platform_device *pdev) cif_hw->is_dma_sg_ops = true; cif_hw->is_dma_contig = true; mutex_init(&cif_hw->dev_lock); + spin_lock_init(&cif_hw->group_lock); cif_hw->iommu_en = is_iommu_enable(dev); ret = of_reserved_mem_device_init(dev); diff --git a/drivers/media/platform/rockchip/cif/hw.h b/drivers/media/platform/rockchip/cif/hw.h index 79139b270d83..fd6ff6dca3ce 100644 --- a/drivers/media/platform/rockchip/cif/hw.h +++ b/drivers/media/platform/rockchip/cif/hw.h @@ -62,6 +62,10 @@ struct rkcif_multi_sync_config { enum rkcif_sync_mode mode; int dev_cnt; int streaming_cnt; + u32 sync_code; + u32 sync_mask; + u32 update_code; + u32 update_cache; bool is_attach; }; @@ -122,7 +126,7 @@ struct rkcif_hw { const struct rkcif_hw_match_data *match_data; struct mutex dev_lock; struct rkcif_multi_sync_config sync_config; - bool is_in_group_sync; + spinlock_t group_lock; }; void rkcif_hw_soft_reset(struct rkcif_hw *cif_hw, bool is_rst_iommu); diff --git a/drivers/media/platform/rockchip/cif/procfs.c b/drivers/media/platform/rockchip/cif/procfs.c index 43d6e2c232b0..d81aa05dc6dd 100644 --- a/drivers/media/platform/rockchip/cif/procfs.c +++ b/drivers/media/platform/rockchip/cif/procfs.c @@ -315,7 +315,7 @@ static void rkcif_show_format(struct rkcif_device *dev, struct seq_file *f) dev->channels[0].width, dev->channels[0].height, dev->channels[0].crop_st_x, dev->channels[0].crop_st_y); seq_printf(f, "\tcompact:%s\n", stream->is_compact ? "enable" : "disabled"); - seq_printf(f, "\tframe amount:%d\n", stream->frame_idx); + seq_printf(f, "\tframe amount:%d\n", stream->frame_idx - 1); if (dev->inf_id == RKCIF_MIPI_LVDS) { time_val = div_u64(stream->readout.early_time, 1000000); seq_printf(f, "\tearly:%u ms\n", time_val);