From a8b7cd32f252e27a1b0aaa5b0e5568090121d609 Mon Sep 17 00:00:00 2001 From: Cai YiWei Date: Tue, 5 Jul 2022 11:30:37 +0800 Subject: [PATCH] media: rockchip: isp: 2 readback for support multishot large resolution Change-Id: Idffbb0836c9981cc8390881ef82e7040ca5c1f05 Signed-off-by: Cai YiWei --- .../media/platform/rockchip/isp/capture_v32.c | 2 +- drivers/media/platform/rockchip/isp/dev.c | 9 +- drivers/media/platform/rockchip/isp/dev.h | 1 + drivers/media/platform/rockchip/isp/hw.c | 5 +- drivers/media/platform/rockchip/isp/hw.h | 2 + .../platform/rockchip/isp/isp_params_v21.c | 29 ++++-- .../platform/rockchip/isp/isp_params_v32.c | 33 +++++-- .../platform/rockchip/isp/isp_params_v3x.c | 34 +++++-- .../media/platform/rockchip/isp/isp_stats.c | 1 + .../media/platform/rockchip/isp/isp_stats.h | 1 + .../platform/rockchip/isp/isp_stats_v32.c | 20 ++-- drivers/media/platform/rockchip/isp/procfs.c | 11 ++- drivers/media/platform/rockchip/isp/rkisp.c | 93 ++++++++++++++++++- 13 files changed, 197 insertions(+), 44 deletions(-) diff --git a/drivers/media/platform/rockchip/isp/capture_v32.c b/drivers/media/platform/rockchip/isp/capture_v32.c index 05f66544e0c7..e657d02b0121 100644 --- a/drivers/media/platform/rockchip/isp/capture_v32.c +++ b/drivers/media/platform/rockchip/isp/capture_v32.c @@ -1050,7 +1050,7 @@ static int mi_frame_start(struct rkisp_stream *stream, u32 mis) rkisp_stream_config_rsz(stream, false); stream->is_crop_upd = false; } - /* update buf for mulit sensor at readback */ + /* update buf for multi sensor at readback */ if (!mis && !stream->ispdev->hw_dev->is_single && !stream->curr_buf && !list_empty(&stream->buf_queue)) { diff --git a/drivers/media/platform/rockchip/isp/dev.c b/drivers/media/platform/rockchip/isp/dev.c index a3f18d58d20a..edd50805b292 100644 --- a/drivers/media/platform/rockchip/isp/dev.c +++ b/drivers/media/platform/rockchip/isp/dev.c @@ -402,7 +402,7 @@ static int rkisp_create_links(struct rkisp_device *dev) return ret; } -static int _set_pipeline_default_fmt(struct rkisp_device *dev) +static int _set_pipeline_default_fmt(struct rkisp_device *dev, bool is_init) { struct v4l2_subdev *isp; struct v4l2_subdev_format fmt; @@ -415,7 +415,8 @@ static int _set_pipeline_default_fmt(struct rkisp_device *dev) if (dev->active_sensor) { fmt = dev->active_sensor->fmt[0]; - if (fmt.format.code == dev->isp_sdev.in_frm.code && + if (!is_init && + fmt.format.code == dev->isp_sdev.in_frm.code && fmt.format.width == dev->isp_sdev.in_frm.width && fmt.format.height == dev->isp_sdev.in_frm.height) return 0; @@ -546,7 +547,7 @@ static int subdev_notifier_complete(struct v4l2_async_notifier *notifier) dev->is_hw_link = true; } - ret = _set_pipeline_default_fmt(dev); + ret = _set_pipeline_default_fmt(dev, true); if (ret < 0) goto unlock; @@ -953,7 +954,7 @@ static int __maybe_unused rkisp_runtime_resume(struct device *dev) /* power on to config default format from sensor */ if (isp_dev->isp_inp & (INP_CSI | INP_DVP | INP_LVDS | INP_CIF) && rkisp_update_sensor_info(isp_dev) >= 0) - _set_pipeline_default_fmt(isp_dev); + _set_pipeline_default_fmt(isp_dev, false); isp_dev->cap_dev.wait_line = rkisp_wait_line; isp_dev->cap_dev.wrap_line = rkisp_wrap_line; diff --git a/drivers/media/platform/rockchip/isp/dev.h b/drivers/media/platform/rockchip/isp/dev.h index 4d9e71877ea6..f215ed296d21 100644 --- a/drivers/media/platform/rockchip/isp/dev.h +++ b/drivers/media/platform/rockchip/isp/dev.h @@ -235,6 +235,7 @@ struct rkisp_device { int rdbk_cnt_x2; int rdbk_cnt_x3; u32 rd_mode; + int sw_rd_cnt; struct rkisp_rx_buf_pool pv_pool[RKISP_RX_BUF_POOL_MAX]; diff --git a/drivers/media/platform/rockchip/isp/hw.c b/drivers/media/platform/rockchip/isp/hw.c index 987f224649f1..db52cfe18017 100644 --- a/drivers/media/platform/rockchip/isp/hw.c +++ b/drivers/media/platform/rockchip/isp/hw.c @@ -905,6 +905,8 @@ static int rkisp_hw_probe(struct platform_device *pdev) hw_dev->dev_link_num = 0; hw_dev->cur_dev_id = 0; hw_dev->mipi_dev_id = 0; + hw_dev->pre_dev_id = 0; + hw_dev->is_multi_overflow = false; hw_dev->isp_ver = match_data->isp_ver; hw_dev->is_unite = match_data->unite; mutex_init(&hw_dev->dev_lock); @@ -966,8 +968,9 @@ static int __maybe_unused rkisp_runtime_suspend(struct device *dev) { struct rkisp_hw_dev *hw_dev = dev_get_drvdata(dev); - hw_dev->is_single = true; hw_dev->dev_link_num = 0; + hw_dev->is_single = true; + hw_dev->is_multi_overflow = false; disable_sys_clk(hw_dev); return pinctrl_pm_select_sleep_state(dev); } diff --git a/drivers/media/platform/rockchip/isp/hw.h b/drivers/media/platform/rockchip/isp/hw.h index 910389dbdbeb..8f222d6f97f6 100644 --- a/drivers/media/platform/rockchip/isp/hw.h +++ b/drivers/media/platform/rockchip/isp/hw.h @@ -65,6 +65,7 @@ struct rkisp_hw_dev { int dev_num; int dev_link_num; int cur_dev_id; + int pre_dev_id; int mipi_dev_id; struct max_input max_in; /* lock for multi dev */ @@ -97,6 +98,7 @@ struct rkisp_hw_dev { bool is_buf_init; bool is_shutdown; bool is_unite; + bool is_multi_overflow; }; int rkisp_register_irq(struct rkisp_hw_dev *dev); diff --git a/drivers/media/platform/rockchip/isp/isp_params_v21.c b/drivers/media/platform/rockchip/isp/isp_params_v21.c index 6b5748135987..7b8dd01e7bd9 100644 --- a/drivers/media/platform/rockchip/isp/isp_params_v21.c +++ b/drivers/media/platform/rockchip/isp/isp_params_v21.c @@ -3806,6 +3806,16 @@ rkisp_params_check_bigmode_v21(struct rkisp_isp_params_vdev *params_vdev) int i = 0, j = 0; bool is_bigmode = false; +multi_overflow: + if (hw->is_multi_overflow) { + ispdev->multi_index = 0; + ispdev->multi_mode = 0; + bigmode_max_w = ISP21_AUTO_BIGMODE_WIDTH; + bigmode_max_size = ISP21_NOBIG_OVERFLOW_SIZE; + dev_warn(dev, "over virtual isp max resolution, force to 2 readback\n"); + goto end; + } + switch (hw->dev_link_num) { case 4: bigmode_max_w = ISP21_VIR4_AUTO_BIGMODE_WIDTH; @@ -3824,10 +3834,10 @@ rkisp_params_check_bigmode_v21(struct rkisp_isp_params_vdev *params_vdev) if (hw->isp_size[i].w <= ISP21_VIR4_MAX_WIDTH && hw->isp_size[i].size <= ISP21_VIR4_MAX_SIZE) continue; - dev_err(dev, "four virtual isp max:1920x1080, isp%d:%dx%d\n", - i, hw->isp_size[i].w, hw->isp_size[i].h); - is_bigmode = true; - break; + dev_warn(dev, "isp%d %dx%d over four vir isp max:1920x1080\n", + i, hw->isp_size[i].w, hw->isp_size[i].h); + hw->is_multi_overflow = true; + goto multi_overflow; } break; case 3: @@ -3865,7 +3875,10 @@ rkisp_params_check_bigmode_v21(struct rkisp_isp_params_vdev *params_vdev) is_bigmode = true; if (k != 1 || (hw->isp_size[idx1[0]].size > ISP21_VIR4_MAX_SIZE * 2)) { - dev_err(dev, "three virtual isp max:1920x1080\n"); + dev_warn(dev, "isp%d %dx%d over three vir isp max:1920x1080\n", + idx1[0], hw->isp_size[idx1[0]].h, hw->isp_size[idx1[0]].w); + hw->is_multi_overflow = true; + goto multi_overflow; } else { if (idx1[0] == ispdev->dev_id) { ispdev->multi_mode = 0; @@ -3920,7 +3933,10 @@ rkisp_params_check_bigmode_v21(struct rkisp_isp_params_vdev *params_vdev) is_bigmode = true; if (k == 2 || j || hw->isp_size[idx1[k - 1]].size > ISP21_VIR4_MAX_SIZE * 3) { - dev_err(dev, "two virtual isp max:3840x2160\n"); + dev_warn(dev, "isp%d %dx%d over two vir isp max:3840x2160\n", + idx1[k - 1], hw->isp_size[idx1[k - 1]].w, hw->isp_size[idx1[k - 1]].h); + hw->is_multi_overflow = true; + goto multi_overflow; } else { if (idx1[0] == ispdev->dev_id) { ispdev->multi_mode = 0; @@ -3945,6 +3961,7 @@ rkisp_params_check_bigmode_v21(struct rkisp_isp_params_vdev *params_vdev) break; } +end: if (!is_bigmode && (width > bigmode_max_w || size > bigmode_max_size)) is_bigmode = true; diff --git a/drivers/media/platform/rockchip/isp/isp_params_v32.c b/drivers/media/platform/rockchip/isp/isp_params_v32.c index 771977a4f9f9..17ab0b32087e 100644 --- a/drivers/media/platform/rockchip/isp/isp_params_v32.c +++ b/drivers/media/platform/rockchip/isp/isp_params_v32.c @@ -4190,6 +4190,16 @@ rkisp_params_check_bigmode_v32(struct rkisp_isp_params_vdev *params_vdev) int i = 0, j = 0; bool is_bigmode = false; +multi_overflow: + if (hw->is_multi_overflow) { + ispdev->multi_index = 0; + ispdev->multi_mode = 0; + bigmode_max_w = ISP32_AUTO_BIGMODE_WIDTH; + bigmode_max_size = ISP32_NOBIG_OVERFLOW_SIZE; + dev_warn(dev, "over virtual isp max resolution, force to 2 readback\n"); + goto end; + } + switch (hw->dev_link_num) { case 4: bigmode_max_w = ISP32_VIR4_AUTO_BIGMODE_WIDTH; @@ -4208,9 +4218,10 @@ rkisp_params_check_bigmode_v32(struct rkisp_isp_params_vdev *params_vdev) if (hw->isp_size[i].w <= ISP32_VIR4_MAX_WIDTH && hw->isp_size[i].size <= ISP32_VIR4_MAX_SIZE) continue; - dev_err(dev, "four virtual isp max:1280x800\n"); - is_bigmode = true; - break; + dev_warn(dev, "isp%d %dx%d over four vir isp max:1280x800\n", + i, hw->isp_size[i].w, hw->isp_size[i].h); + hw->is_multi_overflow = true; + goto multi_overflow; } break; case 3: @@ -4248,7 +4259,10 @@ rkisp_params_check_bigmode_v32(struct rkisp_isp_params_vdev *params_vdev) is_bigmode = true; if (k != 1 || (hw->isp_size[idx1[0]].size > ISP32_VIR4_MAX_SIZE * 2)) { - dev_err(dev, "three virtual isp max:1280x800\n"); + dev_warn(dev, "isp%d %dx%d over three vir isp max:1280x800\n", + idx1[0], hw->isp_size[idx1[0]].w, hw->isp_size[idx1[0]].h); + hw->is_multi_overflow = true; + goto multi_overflow; } else { if (idx1[0] == ispdev->dev_id) { ispdev->multi_mode = 0; @@ -4303,7 +4317,10 @@ rkisp_params_check_bigmode_v32(struct rkisp_isp_params_vdev *params_vdev) is_bigmode = true; if (k == 2 || j || hw->isp_size[idx1[k - 1]].size > ISP32_VIR4_MAX_SIZE * 3) { - dev_err(dev, "two virtual isp max:1920x1080\n"); + dev_warn(dev, "isp%d %dx%d over two vir isp max:1920x1080\n", + idx1[k - 1], hw->isp_size[idx1[k - 1]].w, hw->isp_size[idx1[k - 1]].h); + hw->is_multi_overflow = true; + goto multi_overflow; } else { if (idx1[0] == ispdev->dev_id) { ispdev->multi_mode = 0; @@ -4328,6 +4345,7 @@ rkisp_params_check_bigmode_v32(struct rkisp_isp_params_vdev *params_vdev) break; } +end: if (!is_bigmode && (width > bigmode_max_w || size > bigmode_max_size)) is_bigmode = true; @@ -4808,8 +4826,9 @@ rkisp_params_clear_fstflg(struct rkisp_isp_params_vdev *params_vdev) value &= (ISP3X_YNR_FST_FRAME | ISP3X_ADRC_FST_FRAME | ISP3X_DHAZ_FST_FRAME | ISP3X_CNR_FST_FRAME | ISP3X_RAW3D_FST_FRAME); - if (value) + if (value) { isp3_param_clear_bits(params_vdev, ISP3X_ISP_CTRL1, value); + } } static void @@ -4839,7 +4858,7 @@ rkisp_params_isr_v32(struct rkisp_isp_params_vdev *params_vdev, } } - if (isp_mis & CIF_ISP_FRAME) + if ((isp_mis & CIF_ISP_FRAME) && !params_vdev->rdbk_times) rkisp_params_clear_fstflg(params_vdev); if ((isp_mis & CIF_ISP_FRAME) && !IS_HDR_RDBK(dev->rd_mode)) diff --git a/drivers/media/platform/rockchip/isp/isp_params_v3x.c b/drivers/media/platform/rockchip/isp/isp_params_v3x.c index 35eeef4055ac..fc6f2db6f3c6 100644 --- a/drivers/media/platform/rockchip/isp/isp_params_v3x.c +++ b/drivers/media/platform/rockchip/isp/isp_params_v3x.c @@ -4223,6 +4223,16 @@ rkisp_params_check_bigmode_v3x(struct rkisp_isp_params_vdev *params_vdev) int i = 0, j = 0; bool is_bigmode = false; +multi_overflow: + if (hw->is_multi_overflow) { + ispdev->multi_index = 0; + ispdev->multi_mode = 0; + bigmode_max_w = ISP3X_AUTO_BIGMODE_WIDTH; + bigmode_max_size = ISP3X_NOBIG_OVERFLOW_SIZE; + dev_warn(dev, "over virtual isp max resolution, force to 2 readback\n"); + goto end; + } + switch (hw->dev_link_num) { case 4: bigmode_max_w = ISP3X_VIR4_AUTO_BIGMODE_WIDTH; @@ -4241,10 +4251,11 @@ rkisp_params_check_bigmode_v3x(struct rkisp_isp_params_vdev *params_vdev) if (hw->isp_size[i].w <= ISP3X_VIR4_MAX_WIDTH && hw->isp_size[i].size <= ISP3X_VIR4_MAX_SIZE) continue; - dev_err(dev, "four virtual isp max:%dx1536\n", - hw->is_unite ? (2560 - RKMOUDLE_UNITE_EXTEND_PIXEL) * 2 : 2560); - is_bigmode = true; - break; + dev_warn(dev, "isp%d %dx%d over four vir isp max:%dx1536\n", + i, hw->isp_size[i].w, hw->isp_size[i].h, + hw->is_unite ? (2560 - RKMOUDLE_UNITE_EXTEND_PIXEL) * 2 : 2560); + hw->is_multi_overflow = true; + goto multi_overflow; } break; case 3: @@ -4282,8 +4293,11 @@ rkisp_params_check_bigmode_v3x(struct rkisp_isp_params_vdev *params_vdev) is_bigmode = true; if (k != 1 || (hw->isp_size[idx1[0]].size > ISP3X_VIR4_MAX_SIZE * 2)) { - dev_err(dev, "three virtual isp max:%dx1536\n", - hw->is_unite ? (2560 - RKMOUDLE_UNITE_EXTEND_PIXEL) * 2 : 2560); + dev_warn(dev, "isp%d %dx%d over three vir isp max:%dx1536\n", + idx1[0], hw->isp_size[idx1[0]].w, hw->isp_size[idx1[0]].h, + hw->is_unite ? (2560 - RKMOUDLE_UNITE_EXTEND_PIXEL) * 2 : 2560); + hw->is_multi_overflow = true; + goto multi_overflow; } else { if (idx1[0] == ispdev->dev_id) { ispdev->multi_mode = 0; @@ -4338,8 +4352,11 @@ rkisp_params_check_bigmode_v3x(struct rkisp_isp_params_vdev *params_vdev) is_bigmode = true; if (k == 2 || j || hw->isp_size[idx1[k - 1]].size > ISP3X_VIR4_MAX_SIZE * 3) { - dev_err(dev, "two virtual isp max:%dx2160\n", - hw->is_unite ? (3840 - RKMOUDLE_UNITE_EXTEND_PIXEL) * 2 : 3840); + dev_warn(dev, "isp%d %dx%d over two vir isp max:%dx2160\n", + idx1[k - 1], hw->isp_size[idx1[k - 1]].w, hw->isp_size[idx1[k - 1]].h, + hw->is_unite ? (3840 - RKMOUDLE_UNITE_EXTEND_PIXEL) * 2 : 3840); + hw->is_multi_overflow = true; + goto multi_overflow; } else { if (idx1[0] == ispdev->dev_id) { ispdev->multi_mode = 0; @@ -4366,6 +4383,7 @@ rkisp_params_check_bigmode_v3x(struct rkisp_isp_params_vdev *params_vdev) break; } +end: if (!is_bigmode && (width > bigmode_max_w || size > bigmode_max_size)) is_bigmode = true; diff --git a/drivers/media/platform/rockchip/isp/isp_stats.c b/drivers/media/platform/rockchip/isp/isp_stats.c index 0f2c48c43f1e..287c4e451262 100644 --- a/drivers/media/platform/rockchip/isp/isp_stats.c +++ b/drivers/media/platform/rockchip/isp/isp_stats.c @@ -203,6 +203,7 @@ rkisp_stats_vb2_start_streaming(struct vb2_queue *queue, { struct rkisp_isp_stats_vdev *stats_vdev = queue->drv_priv; + stats_vdev->rdbk_drop = false; stats_vdev->cur_buf = NULL; stats_vdev->ops->rdbk_enable(stats_vdev, false); stats_vdev->streamon = true; diff --git a/drivers/media/platform/rockchip/isp/isp_stats.h b/drivers/media/platform/rockchip/isp/isp_stats.h index 6797084a5dac..eb9f79f9aacb 100644 --- a/drivers/media/platform/rockchip/isp/isp_stats.h +++ b/drivers/media/platform/rockchip/isp/isp_stats.h @@ -65,6 +65,7 @@ struct rkisp_isp_stats_vdev { u32 wr_buf_idx; bool rd_stats_from_ddr; + bool rdbk_drop; bool rdbk_mode; u32 isp_rdbk; u32 isp3a_rdbk; diff --git a/drivers/media/platform/rockchip/isp/isp_stats_v32.c b/drivers/media/platform/rockchip/isp/isp_stats_v32.c index 325a3ae99633..c40ae6a70067 100644 --- a/drivers/media/platform/rockchip/isp/isp_stats_v32.c +++ b/drivers/media/platform/rockchip/isp/isp_stats_v32.c @@ -512,15 +512,19 @@ rkisp_stats_send_meas_v32(struct rkisp_isp_stats_vdev *stats_vdev, u32 size = sizeof(struct rkisp32_isp_stat_buffer); int ret = 0; - /* config buf for next frame */ - stats_vdev->cur_buf = NULL; - if (stats_vdev->nxt_buf) { - stats_vdev->cur_buf = stats_vdev->nxt_buf; - stats_vdev->nxt_buf = NULL; - } - rkisp_stats_update_buf(stats_vdev); + if (!stats_vdev->rdbk_drop) { + /* config buf for next frame */ + stats_vdev->cur_buf = NULL; + if (stats_vdev->nxt_buf) { + stats_vdev->cur_buf = stats_vdev->nxt_buf; + stats_vdev->nxt_buf = NULL; + } + rkisp_stats_update_buf(stats_vdev); - cur_frame_id = meas_work->frame_id; + cur_frame_id = meas_work->frame_id; + } else { + cur_buf = NULL; + } if (cur_buf) { cur_stat_buf = diff --git a/drivers/media/platform/rockchip/isp/procfs.c b/drivers/media/platform/rockchip/isp/procfs.c index f6d9e01422cd..4527430492fd 100644 --- a/drivers/media/platform/rockchip/isp/procfs.c +++ b/drivers/media/platform/rockchip/isp/procfs.c @@ -859,7 +859,7 @@ static int isp_show(struct seq_file *p, void *v) if (!(dev->isp_state & ISP_START)) return 0; - if (IS_HDR_RDBK(dev->hdr.op_mode)) + if (IS_HDR_RDBK(dev->hdr.op_mode)) { seq_printf(p, "%-10s mode:frame%d (frame:%d rate:%dms %s time:%dms frameloss:%d) cnt(total:%d X1:%d X2:%d X3:%d)\n", "Isp Read", dev->rd_mode - 3, @@ -872,14 +872,17 @@ static int isp_show(struct seq_file *p, void *v) dev->rdbk_cnt_x1, dev->rdbk_cnt_x2, dev->rdbk_cnt_x3); - else + seq_printf(p, "\t hw link:%d idle:%d vir(mode:%d index:%d)\n", + dev->hw_dev->dev_link_num, dev->hw_dev->is_idle, + dev->multi_mode, dev->multi_index); + } else { seq_printf(p, "%-10s frame:%d %s time:%dms v-blank:%dus\n", "Isp online", sdev->dbg.id, (dev->isp_state & ISP_FRAME_END) ? "idle" : "working", sdev->dbg.interval / 1000 / 1000, sdev->dbg.delay / 1000); - + } if (dev->br_dev.en) seq_printf(p, "%-10s rkispp%d Format:%s%s Size:%dx%d (frame:%d rate:%dms frameloss:%d)\n", "Output", @@ -940,7 +943,7 @@ static int isp_show(struct seq_file *p, void *v) break; } - seq_printf(p, "%-10s %s Cnt:%d\n", + seq_printf(p, "%-10s %s Cnt:%d\n\n", "Monitor", dev->hw_dev->monitor.is_en ? "ON" : "OFF", dev->hw_dev->monitor.retry); diff --git a/drivers/media/platform/rockchip/isp/rkisp.c b/drivers/media/platform/rockchip/isp/rkisp.c index cbc49345c637..c66cdfe43453 100644 --- a/drivers/media/platform/rockchip/isp/rkisp.c +++ b/drivers/media/platform/rockchip/isp/rkisp.c @@ -501,6 +501,49 @@ u32 rkisp_mbus_pixelcode_to_v4l2(u32 pixelcode) return pixelformat; } +static void rkisp_multi_overflow_hdl(struct rkisp_device *dev, bool on) +{ + struct rkisp_hw_dev *hw = dev->hw_dev; + + if (on) { + /* enable bay3d and mi */ + rkisp_update_regs(dev, ISP3X_MI_WR_CTRL, ISP3X_MI_WR_CTRL); + rkisp_update_regs(dev, ISP3X_ISP_CTRL1, ISP3X_ISP_CTRL1); + if (dev->isp_ver == ISP_V21) { + rkisp_update_regs(dev, ISP21_BAY3D_CTRL, ISP21_BAY3D_CTRL); + } else if (dev->isp_ver == ISP_V30) { + rkisp_update_regs(dev, ISP3X_MPFBC_CTRL, ISP3X_MPFBC_CTRL); + rkisp_update_regs(dev, ISP3X_MI_BP_WR_CTRL, ISP3X_MI_BP_WR_CTRL); + rkisp_update_regs(dev, ISP3X_BAY3D_CTRL, ISP3X_BAY3D_CTRL); + } else if (dev->isp_ver == ISP_V32) { + rkisp_update_regs(dev, ISP3X_MI_BP_WR_CTRL, ISP3X_MI_BP_WR_CTRL); + rkisp_update_regs(dev, ISP32_MI_BPDS_WR_CTRL, ISP32_MI_BPDS_WR_CTRL); + rkisp_update_regs(dev, ISP32_MI_MPDS_WR_CTRL, ISP32_MI_MPDS_WR_CTRL); + rkisp_update_regs(dev, ISP3X_BAY3D_CTRL, ISP3X_BAY3D_CTRL); + } + } else { + /* disabled bay3d and mi */ + writel(0, hw->base_addr + ISP3X_MI_WR_CTRL); + if (dev->isp_ver == ISP_V21) { + writel(0, hw->base_addr + ISP21_BAY3D_CTRL); + } else if (dev->isp_ver == ISP_V30) { + writel(0, hw->base_addr + ISP3X_MPFBC_CTRL); + writel(0, hw->base_addr + ISP3X_MI_BP_WR_CTRL); + writel(0, hw->base_addr + ISP3X_BAY3D_CTRL); + if (hw->is_unite) { + writel(0, hw->base_next_addr + ISP3X_MPFBC_CTRL); + writel(0, hw->base_next_addr + ISP3X_MI_BP_WR_CTRL); + writel(0, hw->base_next_addr + ISP3X_BAY3D_CTRL); + } + } else if (dev->isp_ver == ISP_V32) { + writel(0, hw->base_addr + ISP3X_MI_BP_WR_CTRL); + writel(0, hw->base_addr + ISP32_MI_BPDS_WR_CTRL); + writel(0, hw->base_addr + ISP32_MI_MPDS_WR_CTRL); + writel(0, hw->base_addr + ISP3X_BAY3D_CTRL); + } + } + rkisp_unite_write(dev, ISP3X_MI_WR_INIT, CIF_MI_INIT_SOFT_UPD, true, hw->is_unite); +} /* * for hdr read back mode, rawrd read back data @@ -509,6 +552,7 @@ u32 rkisp_mbus_pixelcode_to_v4l2(u32 pixelcode) void rkisp_trigger_read_back(struct rkisp_device *dev, u8 dma2frm, u32 mode, bool is_try) { struct rkisp_isp_params_vdev *params_vdev = &dev->params_vdev; + struct rkisp_isp_stats_vdev *stats_vdev = &dev->stats_vdev; struct rkisp_hw_dev *hw = dev->hw_dev; u32 val, cur_frame_id, tmp, rd_mode; u64 iq_feature = hw->iq_feature; @@ -518,6 +562,9 @@ void rkisp_trigger_read_back(struct rkisp_device *dev, u8 dma2frm, u32 mode, boo hw->cur_dev_id = dev->dev_id; rkisp_dmarx_get_frame(dev, &cur_frame_id, NULL, NULL, true); + if (hw->is_multi_overflow && is_try) + goto run_next; + val = 0; if (mode & (T_START_X1 | T_START_C)) { rd_mode = HDR_RDBK_FRAME1; @@ -638,7 +685,7 @@ void rkisp_trigger_read_back(struct rkisp_device *dev, u8 dma2frm, u32 mode, boo dma2frm = 2; if (dma2frm == 2) dev->rdbk_cnt_x3++; - else if (dma2frm == 1) + else if (dma2frm == 1 || dev->sw_rd_cnt) dev->rdbk_cnt_x2++; else dev->rdbk_cnt_x1++; @@ -647,6 +694,20 @@ void rkisp_trigger_read_back(struct rkisp_device *dev, u8 dma2frm, u32 mode, boo rkisp_params_cfgsram(params_vdev); params_vdev->rdbk_times = dma2frm + 1; +run_next: + if (hw->is_multi_overflow) { + stats_vdev->rdbk_drop = false; + if (dev->sw_rd_cnt) { + rkisp_multi_overflow_hdl(dev, false); + params_vdev->rdbk_times += dev->sw_rd_cnt; + stats_vdev->rdbk_drop = true; + is_upd = true; + } else if (is_try) { + rkisp_multi_overflow_hdl(dev, true); + is_upd = true; + } + } + /* read 3d lut at frame end */ if (hw->is_single && is_upd && rkisp_read_reg_cache(dev, ISP_3DLUT_UPDATE) & 0x1) { @@ -668,7 +729,7 @@ void rkisp_trigger_read_back(struct rkisp_device *dev, u8 dma2frm, u32 mode, boo v4l2_dbg(2, rkisp_debug, &dev->v4l2_dev, "readback frame:%d time:%d 0x%x\n", cur_frame_id, dma2frm + 1, val); - if (!dma2frm) + if (!dma2frm && !dev->sw_rd_cnt) rkisp_bridge_update_mi(dev, 0); if (!hw->is_shutdown) rkisp_unite_write(dev, CSI2RX_CTRL0, val, true, hw->is_unite); @@ -683,10 +744,20 @@ static void rkisp_rdbk_trigger_handle(struct rkisp_device *dev, u32 cmd) int i, times = -1, max = 0, id = 0; int len[DEV_MAX] = { 0 }; u32 mode = 0; + bool is_try = false; spin_lock_irqsave(&hw->rdbk_lock, lock_flags); - if (cmd == T_CMD_END) + if (cmd == T_CMD_END) { + if (dev->sw_rd_cnt) { + dev->sw_rd_cnt--; + isp = dev; + is_try = true; + times = 0; + goto end; + } hw->is_idle = true; + hw->pre_dev_id = dev->dev_id; + } if (hw->is_shutdown) hw->is_idle = false; if (!hw->is_idle) @@ -724,11 +795,16 @@ static void rkisp_rdbk_trigger_handle(struct rkisp_device *dev, u32 cmd) times = t.times; hw->cur_dev_id = id; hw->is_idle = false; + isp->sw_rd_cnt = 0; + if (hw->is_multi_overflow && (hw->pre_dev_id != id)) { + isp->sw_rd_cnt = 1; + times = 0; + } } end: spin_unlock_irqrestore(&hw->rdbk_lock, lock_flags); if (times >= 0) - rkisp_trigger_read_back(isp, times, mode, false); + rkisp_trigger_read_back(isp, times, mode, is_try); } int rkisp_rdbk_trigger_event(struct rkisp_device *dev, u32 cmd, void *arg) @@ -783,6 +859,11 @@ void rkisp_check_idle(struct rkisp_device *dev, u32 irq) { u32 val = 0; + if (dev->hw_dev->is_multi_overflow && + dev->sw_rd_cnt && + irq & ISP_FRAME_END) + goto end; + dev->irq_ends |= (irq & dev->irq_ends_mask); v4l2_dbg(3, rkisp_debug, &dev->v4l2_dev, "%s irq:0x%x ends:0x%x mask:0x%x\n", @@ -813,7 +894,6 @@ void rkisp_check_idle(struct rkisp_device *dev, u32 irq) } val = 0; - dev->irq_ends = 0; switch (dev->rd_mode) { case HDR_RDBK_FRAME3://for rd1 rd0 rd2 val |= RAW1_RD_FRAME; @@ -826,6 +906,8 @@ void rkisp_check_idle(struct rkisp_device *dev, u32 irq) /* FALLTHROUGH */ } rkisp2_rawrd_isr(val, dev); +end: + dev->irq_ends = 0; if (dev->dmarx_dev.trigger == T_MANUAL) tasklet_schedule(&dev->rdbk_tasklet); } @@ -1898,6 +1980,7 @@ static int rkisp_isp_stop(struct rkisp_device *dev) end: dev->irq_ends_mask = 0; dev->hdr.op_mode = 0; + dev->sw_rd_cnt = 0; rkisp_set_state(&dev->isp_state, ISP_STOP); if (dev->isp_ver == ISP_V20 || dev->isp_ver == ISP_V21 ||