From 1543e317f1da31b75942316931e8f491a8920811 Mon Sep 17 00:00:00 2001
From: hc <hc@nodka.com>
Date: Thu, 04 Jan 2024 10:08:02 +0000
Subject: [PATCH] disable FB
---
kernel/drivers/media/platform/rockchip/isp/rkisp.c | 2021 +++++++++++++++++++++++++++++++++++++++++++++++------------
1 files changed, 1,612 insertions(+), 409 deletions(-)
diff --git a/kernel/drivers/media/platform/rockchip/isp/rkisp.c b/kernel/drivers/media/platform/rockchip/isp/rkisp.c
index f65e7e7..ac40adf 100644
--- a/kernel/drivers/media/platform/rockchip/isp/rkisp.c
+++ b/kernel/drivers/media/platform/rockchip/isp/rkisp.c
@@ -33,6 +33,7 @@
*/
#include <linux/clk.h>
+#include <linux/compat.h>
#include <linux/iopoll.h>
#include <linux/pm_runtime.h>
#include <linux/regmap.h>
@@ -42,12 +43,13 @@
#include <linux/kfifo.h>
#include <linux/interrupt.h>
#include <linux/rk-preisp.h>
-#include <linux/rkisp21-config.h>
+#include <linux/rk-isp21-config.h>
#include <linux/iommu.h>
#include <media/v4l2-event.h>
#include <media/media-entity.h>
#include "common.h"
+#include "isp_external.h"
#include "regs.h"
#include "rkisp_tb_helper.h"
@@ -83,11 +85,7 @@
* +---------------------------------------------------------+
*/
-struct backup_reg {
- const u32 base;
- const u32 shd;
- u32 val;
-};
+static void rkisp_config_cmsk(struct rkisp_device *dev);
static inline struct rkisp_device *sd_to_isp_dev(struct v4l2_subdev *sd)
{
@@ -188,41 +186,50 @@
u32 code = dev->isp_sdev.in_frm.code;
u32 src_w = dev->isp_sdev.in_frm.width;
u32 src_h = dev->isp_sdev.in_frm.height;
- u32 dest_w, dest_h, w, h;
+ u32 dest_w, dest_h, w, h, max_size, max_h, max_w;
int ret = 0;
if (!crop)
return -EINVAL;
- if (dev->isp_ver == ISP_V12) {
- w = clamp_t(u32, src_w,
- CIF_ISP_INPUT_W_MIN,
- CIF_ISP_INPUT_W_MAX_V12);
- h = clamp_t(u32, src_h,
- CIF_ISP_INPUT_H_MIN,
- CIF_ISP_INPUT_H_MAX_V12);
- } else if (dev->isp_ver == ISP_V13) {
- w = clamp_t(u32, src_w,
- CIF_ISP_INPUT_W_MIN,
- CIF_ISP_INPUT_W_MAX_V13);
- h = clamp_t(u32, src_h,
- CIF_ISP_INPUT_H_MIN,
- CIF_ISP_INPUT_H_MAX_V13);
- } else if (dev->isp_ver == ISP_V21) {
- w = clamp_t(u32, src_w,
- CIF_ISP_INPUT_W_MIN,
- CIF_ISP_INPUT_W_MAX_V21);
- h = clamp_t(u32, src_h,
- CIF_ISP_INPUT_H_MIN,
- CIF_ISP_INPUT_H_MAX_V21);
- } else {
- w = clamp_t(u32, src_w,
- CIF_ISP_INPUT_W_MIN,
- CIF_ISP_INPUT_W_MAX);
- h = clamp_t(u32, src_h,
- CIF_ISP_INPUT_H_MIN,
- CIF_ISP_INPUT_H_MAX);
+ memset(&sel, 0, sizeof(sel));
+ switch (dev->isp_ver) {
+ case ISP_V12:
+ max_w = CIF_ISP_INPUT_W_MAX_V12;
+ max_h = CIF_ISP_INPUT_H_MAX_V12;
+ break;
+ case ISP_V13:
+ max_w = CIF_ISP_INPUT_W_MAX_V13;
+ max_h = CIF_ISP_INPUT_H_MAX_V13;
+ break;
+ case ISP_V21:
+ max_w = CIF_ISP_INPUT_W_MAX_V21;
+ max_h = CIF_ISP_INPUT_H_MAX_V21;
+ break;
+ case ISP_V30:
+ max_w = dev->hw_dev->unite ?
+ CIF_ISP_INPUT_W_MAX_V30_UNITE : CIF_ISP_INPUT_W_MAX_V30;
+ max_h = dev->hw_dev->unite ?
+ CIF_ISP_INPUT_H_MAX_V30_UNITE : CIF_ISP_INPUT_H_MAX_V30;
+ break;
+ case ISP_V32:
+ max_w = dev->hw_dev->unite ?
+ CIF_ISP_INPUT_W_MAX_V32_UNITE : CIF_ISP_INPUT_W_MAX_V32;
+ max_h = dev->hw_dev->unite ?
+ CIF_ISP_INPUT_H_MAX_V32_UNITE : CIF_ISP_INPUT_H_MAX_V32;
+ break;
+ case ISP_V32_L:
+ max_w = CIF_ISP_INPUT_W_MAX_V32_L;
+ max_h = CIF_ISP_INPUT_H_MAX_V32_L;
+ break;
+ default:
+ max_w = CIF_ISP_INPUT_W_MAX;
+ max_h = CIF_ISP_INPUT_H_MAX;
}
+ max_size = max_w * max_h;
+ w = clamp_t(u32, src_w, CIF_ISP_INPUT_W_MIN, max_w);
+ max_h = max_size / w;
+ h = clamp_t(u32, src_h, CIF_ISP_INPUT_H_MIN, max_h);
if (dev->active_sensor)
sensor = dev->active_sensor->sd;
@@ -343,35 +350,51 @@
return -ENODEV;
sensor = sd_to_sensor(dev, sensor_sd);
- ret = v4l2_subdev_call(sensor->sd, video, g_mbus_config,
- &sensor->mbus);
+ if (!sensor)
+ return -ENODEV;
+ ret = v4l2_subdev_call(sensor->sd, pad, get_mbus_config,
+ 0, &sensor->mbus);
if (ret && ret != -ENOIOCTLCMD)
return ret;
- if (sensor->mbus.type == V4L2_MBUS_CSI2) {
+ sensor->fmt[0].pad = 0;
+ sensor->fmt[0].which = V4L2_SUBDEV_FORMAT_ACTIVE;
+ ret = v4l2_subdev_call(sensor->sd, pad, get_fmt,
+ &sensor->cfg, &sensor->fmt[0]);
+ if (ret && ret != -ENOIOCTLCMD)
+ return ret;
+
+ if (sensor->mbus.type == V4L2_MBUS_CSI2_DPHY &&
+ dev->isp_ver < ISP_V30) {
u8 vc = 0;
- memset(dev->csi_dev.mipi_di, 0,
- sizeof(dev->csi_dev.mipi_di));
- memset(sensor->fmt, 0, sizeof(sensor->fmt));
+ sensor_sd = get_remote_sensor(sensor->sd);
+ if (!sensor_sd)
+ return -ENODEV;
+ memset(dev->csi_dev.mipi_di, 0, sizeof(dev->csi_dev.mipi_di));
for (i = 0; i < dev->csi_dev.max_pad - 1; i++) {
+ struct rkmodule_channel_info ch = { 0 };
+
fmt = &sensor->fmt[i];
- fmt->pad = i;
- fmt->which = V4L2_SUBDEV_FORMAT_ACTIVE;
- ret = v4l2_subdev_call(sensor->sd, pad, get_fmt,
- &sensor->cfg, fmt);
- if (ret && ret != -ENOIOCTLCMD)
- return ret;
+ ch.index = i;
+ ret = v4l2_subdev_call(sensor_sd, core, ioctl,
+ RKMODULE_GET_CHANNEL_INFO, &ch);
+ if (ret) {
+ if (i)
+ *fmt = sensor->fmt[0];
+ } else {
+ fmt->format.width = ch.width;
+ fmt->format.height = ch.height;
+ fmt->format.code = ch.bus_fmt;
+ }
ret = mbus_pixelcode_to_mipi_dt(fmt->format.code);
if (ret < 0) {
v4l2_err(&dev->v4l2_dev,
"Invalid mipi data type\n");
return ret;
}
- /* v4l2_subdev_format reserved[0]
- * using as mipi virtual channel
- */
- switch (fmt->reserved[0]) {
+
+ switch (ch.vc) {
case V4L2_MBUS_CSI2_CHANNEL_3:
vc = 3;
break;
@@ -393,18 +416,14 @@
fmt->format.width,
fmt->format.height);
}
- } else {
- sensor->fmt[0].pad = 0;
- sensor->fmt[0].which = V4L2_SUBDEV_FORMAT_ACTIVE;
- ret = v4l2_subdev_call(sensor->sd, pad, get_fmt,
- &sensor->cfg, &sensor->fmt[0]);
- if (ret && ret != -ENOIOCTLCMD)
- return ret;
}
v4l2_subdev_call(sensor->sd, video, g_frame_interval, &sensor->fi);
dev->active_sensor = sensor;
-
+ i = dev->dev_id;
+ if (sensor->fi.interval.numerator)
+ dev->hw_dev->isp_size[i].fps =
+ sensor->fi.interval.denominator / sensor->fi.interval.numerator;
return ret;
}
@@ -471,6 +490,86 @@
return pixelformat;
}
+static void rkisp_dvfs(struct rkisp_device *dev)
+{
+ struct rkisp_hw_dev *hw = dev->hw_dev;
+ u64 data_rate = 0;
+ int i, fps, num = 0;
+
+ if (!hw->is_dvfs)
+ return;
+ hw->is_dvfs = false;
+ for (i = 0; i < hw->dev_num; i++) {
+ if (!hw->isp_size[i].is_on)
+ continue;
+ fps = hw->isp_size[i].fps;
+ if (!fps)
+ fps = 30;
+ data_rate += (fps * hw->isp_size[i].size);
+ num++;
+ }
+ do_div(data_rate, 1000 * 1000);
+ /* increase margin: 25% * num */
+ data_rate += (data_rate >> 2) * num;
+ /* one frame two-run, data double */
+ if (hw->is_multi_overflow && num > 1)
+ data_rate *= 2;
+ /* compare with isp clock adjustment table */
+ for (i = 0; i < hw->num_clk_rate_tbl; i++)
+ if (data_rate <= hw->clk_rate_tbl[i].clk_rate)
+ break;
+ if (i == hw->num_clk_rate_tbl)
+ i--;
+
+ /* set isp clock rate */
+ rkisp_set_clk_rate(hw->clks[0], hw->clk_rate_tbl[i].clk_rate * 1000000UL);
+ if (hw->unite == ISP_UNITE_TWO)
+ rkisp_set_clk_rate(hw->clks[5], hw->clk_rate_tbl[i].clk_rate * 1000000UL);
+ /* aclk equal to core clk */
+ if (dev->isp_ver == ISP_V32)
+ rkisp_set_clk_rate(hw->clks[1], hw->clk_rate_tbl[i].clk_rate * 1000000UL);
+ dev_info(hw->dev, "set isp clk = %luHz\n", clk_get_rate(hw->clks[0]));
+}
+
+static void rkisp_multi_overflow_hdl(struct rkisp_device *dev, bool on)
+{
+ struct rkisp_hw_dev *hw = dev->hw_dev;
+
+ if (on) {
+ /* enable 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_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_SWS_CFG, ISP3X_SWS_CFG);
+ } 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);
+ }
+ } else {
+ /* disabled mi. rv1106 sdmmc workaround, 3a_wr no close */
+ writel(CIF_MI_CTRL_INIT_OFFSET_EN | CIF_MI_CTRL_INIT_BASE_EN,
+ hw->base_addr + ISP3X_MI_WR_CTRL);
+ 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(0xc, hw->base_addr + ISP3X_SWS_CFG);
+ if (hw->unite == ISP_UNITE_TWO) {
+ writel(0, hw->base_next_addr + ISP3X_MI_WR_CTRL);
+ writel(0, hw->base_next_addr + ISP3X_MPFBC_CTRL);
+ writel(0, hw->base_next_addr + ISP3X_MI_BP_WR_CTRL);
+ writel(0xc, hw->base_next_addr + ISP3X_SWS_CFG);
+ }
+ } 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);
+ }
+ }
+ rkisp_unite_write(dev, ISP3X_MI_WR_INIT, CIF_MI_INIT_SOFT_UPD, true);
+}
/*
* for hdr read back mode, rawrd read back data
@@ -479,6 +578,7 @@
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;
@@ -488,8 +588,12 @@
hw->cur_dev_id = dev->dev_id;
rkisp_dmarx_get_frame(dev, &cur_frame_id, NULL, NULL, true);
+ /* isp process the same frame */
+ if (is_try)
+ goto run_next;
+
val = 0;
- if (mode & T_START_X1) {
+ if (mode & (T_START_X1 | T_START_C)) {
rd_mode = HDR_RDBK_FRAME1;
} else if (mode & T_START_X2) {
rd_mode = HDR_RDBK_FRAME2;
@@ -502,6 +606,11 @@
val = rkisp_read(dev, ISP_HDRMGE_BASE, false) & 0xf;
}
+ if (mode & T_START_C)
+ rkisp_expander_config(dev, NULL, true);
+ else
+ rkisp_expander_config(dev, NULL, false);
+
if (is_feature_on) {
if ((ISP2X_MODULE_HDRMGE & ~iq_feature) && (val & SW_HDRMGE_EN)) {
v4l2_err(&dev->v4l2_dev, "hdrmge is not supported\n");
@@ -509,24 +618,22 @@
}
}
- tmp = rkisp_read(dev, ISP_HDRMGE_BASE, false) & 0xf;
- if (val != tmp) {
- rkisp_write(dev, ISP_HDRMGE_BASE, val, false);
+ if (rd_mode != dev->rd_mode) {
+ rkisp_unite_set_bits(dev, ISP_HDRMGE_BASE, ISP_HDRMGE_MODE_MASK, val, false);
dev->skip_frame = 2;
is_upd = true;
}
- if (dev->isp_ver == ISP_V20 && dev->dmarx_dev.trigger == T_MANUAL && !is_try) {
- if (dev->rd_mode != rd_mode && RKMODULE_EXTEND_LINE != 0) {
+ if (dev->isp_ver == ISP_V20 && dev->dmarx_dev.trigger == T_MANUAL) {
+ if (dev->rd_mode != rd_mode && dev->br_dev.en) {
tmp = dev->isp_sdev.in_crop.height;
val = rkisp_read(dev, CIF_DUAL_CROP_CTRL, false);
if (rd_mode == HDR_RDBK_FRAME1) {
- val |= CIF_DUAL_CROP_MP_MODE_YUV | CIF_DUAL_CROP_SP_MODE_YUV;
+ val |= CIF_DUAL_CROP_MP_MODE_YUV;
tmp += RKMODULE_EXTEND_LINE;
} else {
- val &= ~(CIF_DUAL_CROP_MP_MODE_YUV | CIF_DUAL_CROP_SP_MODE_YUV);
+ val &= ~CIF_DUAL_CROP_MP_MODE_YUV;
}
- val |= CIF_DUAL_CROP_CFG_UPD;
rkisp_write(dev, CIF_DUAL_CROP_CTRL, val, false);
rkisp_write(dev, CIF_ISP_ACQ_V_SIZE, tmp, false);
rkisp_write(dev, CIF_ISP_OUT_V_SIZE, tmp, false);
@@ -538,19 +645,38 @@
}
dev->rd_mode = rd_mode;
- rkisp_params_first_cfg(&dev->params_vdev, &dev->isp_sdev.in_fmt,
- dev->isp_sdev.quantization);
- rkisp_params_cfg(params_vdev, cur_frame_id);
+ if (hw->unite != ISP_UNITE_ONE || dev->unite_index == ISP_UNITE_LEFT) {
+ rkisp_params_first_cfg(&dev->params_vdev, &dev->isp_sdev.in_fmt,
+ dev->isp_sdev.quantization);
+ rkisp_params_cfg(params_vdev, cur_frame_id);
+ rkisp_config_cmsk(dev);
+ rkisp_stream_frame_start(dev, 0);
+ }
- if (!hw->is_single && !is_try) {
+ if (!hw->is_single) {
+ /* multi sensor need to reset isp resize mode if scale up */
+ val = 0;
+ if (rkisp_read(dev, ISP3X_MAIN_RESIZE_CTRL, true) & 0xf0)
+ val |= BIT(3);
+ if (dev->isp_ver != ISP_V32_L &&
+ rkisp_read(dev, ISP3X_SELF_RESIZE_CTRL, true) & 0xf0)
+ val |= BIT(4);
+ if (rkisp_read(dev, ISP32_BP_RESIZE_CTRL, true) & 0xf0)
+ val |= BIT(12);
+ if (val) {
+ writel(val, hw->base_addr + CIF_IRCL);
+ writel(0, hw->base_addr + CIF_IRCL);
+ }
+
rkisp_update_regs(dev, CTRL_VI_ISP_PATH, SUPER_IMP_COLOR_CR);
- rkisp_update_regs(dev, DUAL_CROP_M_H_OFFS, DUAL_CROP_S_V_SIZE);
- rkisp_update_regs(dev, ISP_ACQ_PROP, DUAL_CROP_CTRL);
- rkisp_update_regs(dev, MAIN_RESIZE_SCALE_HY, MI_WR_CTRL);
- rkisp_update_regs(dev, SELF_RESIZE_SCALE_HY, MAIN_RESIZE_CTRL);
- rkisp_update_regs(dev, ISP_GAMMA_OUT_CTRL, SELF_RESIZE_CTRL);
+ rkisp_update_regs(dev, DUAL_CROP_M_H_OFFS, ISP3X_DUAL_CROP_FBC_V_SIZE);
+ rkisp_update_regs(dev, ISP_ACQ_H_OFFS, DUAL_CROP_CTRL);
+ rkisp_update_regs(dev, SELF_RESIZE_SCALE_HY, MI_WR_CTRL);
+ rkisp_update_regs(dev, ISP32_BP_RESIZE_SCALE_HY, SELF_RESIZE_CTRL);
+ rkisp_update_regs(dev, MAIN_RESIZE_SCALE_HY, ISP32_BP_RESIZE_CTRL);
+ rkisp_update_regs(dev, ISP_GAMMA_OUT_CTRL, MAIN_RESIZE_CTRL);
rkisp_update_regs(dev, MI_RD_CTRL2, ISP_LSC_CTRL);
- rkisp_update_regs(dev, MI_MP_WR_Y_BASE, MI_MP_WR_Y_LLENGTH);
+ rkisp_update_regs(dev, MI_MP_WR_Y_BASE, MI_WR_CTRL2 - 4);
rkisp_update_regs(dev, ISP_LSC_XGRAD_01, ISP_RAWAWB_RAM_DATA);
if (dev->isp_ver == ISP_V20 &&
(rkisp_read(dev, ISP_DHAZ_CTRL, false) & ISP_DHAZ_ENMUX ||
@@ -560,53 +686,148 @@
val = rkisp_read(dev, MI_WR_CTRL2, false);
rkisp_set_bits(dev, MI_WR_CTRL2, 0, val, true);
rkisp_write(dev, MI_WR_INIT, ISP21_SP_FORCE_UPD | ISP21_MP_FORCE_UPD, true);
- /* sensor mode & index */
+ } else {
+ if (dev->isp_ver == ISP_V32_L)
+ rkisp_write(dev, ISP32_SELF_SCALE_UPDATE, ISP32_SCALE_FORCE_UPD, true);
+ rkisp_unite_write(dev, ISP3X_MI_WR_INIT, CIF_MI_INIT_SOFT_UPD, true);
+ }
+ /* sensor mode & index */
+ if (dev->isp_ver >= ISP_V21) {
val = rkisp_read_reg_cache(dev, ISP_ACQ_H_OFFS);
- val |= ISP21_SENSOR_MODE(hw->dev_num >= 3 ? 2 : hw->dev_num - 1) |
- ISP21_SENSOR_INDEX(dev->dev_id);
+ val |= ISP21_SENSOR_INDEX(dev->multi_index);
+ if (dev->isp_ver == ISP_V32_L)
+ val |= ISP32L_SENSOR_MODE(dev->multi_mode);
+ else
+ val |= ISP21_SENSOR_MODE(dev->multi_mode);
writel(val, hw->base_addr + ISP_ACQ_H_OFFS);
+ if (hw->unite == ISP_UNITE_TWO)
+ writel(val, hw->base_next_addr + ISP_ACQ_H_OFFS);
+ v4l2_dbg(2, rkisp_debug, &dev->v4l2_dev,
+ "sensor mode:%d index:%d | 0x%x\n",
+ dev->multi_mode, dev->multi_index, val);
}
is_upd = true;
}
- if (dev->isp_ver == ISP_V21)
+ if (dev->isp_ver > ISP_V20)
dma2frm = 0;
if (dma2frm > 2)
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++;
dev->rdbk_cnt++;
+ if (dev->isp_ver == ISP_V20)
+ params_vdev->rdbk_times = dma2frm + 1;
- rkisp_params_cfgsram(params_vdev);
- params_vdev->rdbk_times = dma2frm + 1;
+run_next:
+ rkisp_params_cfgsram(params_vdev, true);
+ stats_vdev->rdbk_drop = false;
+ if (dev->is_frame_double) {
+ is_upd = true;
+ if (is_try) {
+ /* the frame second running to on mi */
+ rkisp_multi_overflow_hdl(dev, true);
+ rkisp_update_regs(dev, ISP_LDCH_BASE, ISP_LDCH_BASE);
- /* read 3d lut at frame end */
+ val = ISP3X_YNR_FST_FRAME | ISP3X_DHAZ_FST_FRAME | ISP3X_CNR_FST_FRAME;
+ if (dev->isp_ver == ISP_V32)
+ val |= ISP32_SHP_FST_FRAME;
+ else
+ val |= ISP3X_CNR_FST_FRAME;
+ rkisp_unite_clear_bits(dev, ISP3X_ISP_CTRL1, val, false);
+ val = rkisp_read_reg_cache(dev, ISP3X_DRC_IIRWG_GAIN);
+ writel(val, hw->base_addr + ISP3X_DRC_IIRWG_GAIN);
+ if (hw->unite == ISP_UNITE_TWO)
+ writel(val, hw->base_next_addr + ISP3X_DRC_IIRWG_GAIN);
+ val = rkisp_read_reg_cache(dev, ISP3X_DRC_EXPLRATIO);
+ writel(val, hw->base_addr + ISP3X_DRC_EXPLRATIO);
+ if (hw->unite == ISP_UNITE_TWO)
+ writel(val, hw->base_next_addr + ISP3X_DRC_EXPLRATIO);
+ val = rkisp_read_reg_cache(dev, ISP3X_YNR_GLOBAL_CTRL);
+ writel(val, hw->base_addr + ISP3X_YNR_GLOBAL_CTRL);
+ if (hw->unite == ISP_UNITE_TWO)
+ writel(val, hw->base_next_addr + ISP3X_YNR_GLOBAL_CTRL);
+ if (dev->isp_ver == ISP_V21 || dev->isp_ver == ISP_V30) {
+ val = rkisp_read_reg_cache(dev, ISP3X_CNR_CTRL);
+ writel(val, hw->base_addr + ISP3X_CNR_CTRL);
+ if (hw->unite == ISP_UNITE_TWO)
+ writel(val, hw->base_next_addr + ISP3X_CNR_CTRL);
+ }
+ } else {
+ /* the frame first running to off mi to save bandwidth */
+ rkisp_multi_overflow_hdl(dev, false);
+
+ /* FST_FRAME no to read sram thumb */
+ val = ISP3X_YNR_FST_FRAME | ISP3X_DHAZ_FST_FRAME;
+ if (dev->isp_ver == ISP_V32)
+ val |= ISP32_SHP_FST_FRAME;
+ else
+ val |= ISP3X_CNR_FST_FRAME;
+ rkisp_unite_set_bits(dev, ISP3X_ISP_CTRL1, 0, val, false);
+ /* ADRC low iir thumb weight for first sensor switch */
+ val = rkisp_read_reg_cache(dev, ISP3X_DRC_IIRWG_GAIN);
+ val &= ~ISP3X_DRC_IIR_WEIGHT_MASK;
+ writel(val, hw->base_addr + ISP3X_DRC_IIRWG_GAIN);
+ if (hw->unite == ISP_UNITE_TWO)
+ writel(val, hw->base_next_addr + ISP3X_DRC_IIRWG_GAIN);
+ /* ADRC iir5x5 and cur3x3 weight */
+ val = rkisp_read_reg_cache(dev, ISP3X_DRC_EXPLRATIO);
+ val &= ~ISP3X_DRC_WEIPRE_FRAME_MASK;
+ writel(val, hw->base_addr + ISP3X_DRC_EXPLRATIO);
+ if (hw->unite == ISP_UNITE_TWO)
+ writel(val, hw->base_next_addr + ISP3X_DRC_EXPLRATIO);
+ /* YNR_THUMB_MIX_CUR_EN for thumb read addr to 0 */
+ val = rkisp_read_reg_cache(dev, ISP3X_YNR_GLOBAL_CTRL);
+ val |= ISP3X_YNR_THUMB_MIX_CUR_EN;
+ writel(val, hw->base_addr + ISP3X_YNR_GLOBAL_CTRL);
+ if (hw->unite == ISP_UNITE_TWO)
+ writel(val, hw->base_next_addr + ISP3X_YNR_GLOBAL_CTRL);
+ if (dev->isp_ver == ISP_V21 || dev->isp_ver == ISP_V30) {
+ /* CNR_THUMB_MIX_CUR_EN for thumb read addr to 0 */
+ val = rkisp_read_reg_cache(dev, ISP3X_CNR_CTRL);
+ val |= ISP3X_CNR_THUMB_MIX_CUR_EN;
+ writel(val, hw->base_addr + ISP3X_CNR_CTRL);
+ if (hw->unite == ISP_UNITE_TWO)
+ writel(val, hw->base_next_addr + ISP3X_CNR_CTRL);
+ }
+ stats_vdev->rdbk_drop = true;
+ }
+ }
+
+ /* disable isp force update to read 3dlut
+ * 3dlut auto update at frame end for single sensor
+ */
if (hw->is_single && is_upd &&
rkisp_read_reg_cache(dev, ISP_3DLUT_UPDATE) & 0x1) {
- rkisp_write(dev, ISP_3DLUT_UPDATE, 0, true);
+ rkisp_unite_write(dev, ISP_3DLUT_UPDATE, 0, true);
is_3dlut_upd = true;
}
if (is_upd) {
val = rkisp_read(dev, ISP_CTRL, false);
val |= CIF_ISP_CTRL_ISP_CFG_UPD;
- rkisp_write(dev, ISP_CTRL, val, true);
+ rkisp_unite_write(dev, ISP_CTRL, val, true);
+ /* bayer pat after ISP_CFG_UPD for multi sensor to read lsc r/g/b table */
+ rkisp_update_regs(dev, ISP3X_ISP_CTRL1, ISP3X_ISP_CTRL1);
/* fix ldch multi sensor case:
* ldch will pre-read data when en and isp force upd or frame end,
* udelay for ldch pre-read data.
* ldch en=0 before start for frame end to stop ldch read data.
*/
- if (!hw->is_single &&
- (rkisp_read(dev, ISP_LDCH_BASE, true) & 0x1)) {
+ val = rkisp_read(dev, ISP_LDCH_BASE, true);
+ if (!hw->is_single && val & BIT(0)) {
udelay(50);
- writel(0, hw->base_addr + ISP_LDCH_BASE);
+ val &= ~(BIT(0) | BIT(31));
+ writel(val, hw->base_addr + ISP_LDCH_BASE);
+ if (hw->unite == ISP_UNITE_TWO)
+ writel(val, hw->base_next_addr + ISP_LDCH_BASE);
}
}
if (is_3dlut_upd)
- rkisp_write(dev, ISP_3DLUT_UPDATE, 1, true);
+ rkisp_unite_write(dev, ISP_3DLUT_UPDATE, 1, true);
/* if output stream enable, wait it end */
val = rkisp_read(dev, CIF_MI_CTRL_SHD, true);
@@ -618,21 +839,68 @@
dev->irq_ends_mask |= ISP_FRAME_SP;
else
dev->irq_ends_mask &= ~ISP_FRAME_SP;
-
- memset(dev->filt_state, 0, sizeof(dev->filt_state));
- dev->filt_state[RDBK_F_VS] = dma2frm;
+ if ((dev->isp_ver == ISP_V20 &&
+ rkisp_read(dev, ISP_MPFBC_CTRL, true) & SW_MPFBC_EN) ||
+ (dev->isp_ver == ISP_V30 &&
+ rkisp_read(dev, ISP3X_MPFBC_CTRL, true) & ISP3X_MPFBC_EN_SHD))
+ dev->irq_ends_mask |= ISP_FRAME_MPFBC;
+ else
+ dev->irq_ends_mask &= ~ISP_FRAME_MPFBC;
+ if ((dev->isp_ver == ISP_V30 &&
+ rkisp_read(dev, ISP3X_MI_BP_WR_CTRL, true) & ISP3X_BP_ENABLE) ||
+ (dev->isp_ver == ISP_V32 &&
+ rkisp_read(dev, ISP32_MI_WR_CTRL2_SHD, true) & ISP32_BP_EN_OUT_SHD))
+ dev->irq_ends_mask |= ISP_FRAME_BP;
+ else
+ dev->irq_ends_mask &= ~ISP_FRAME_BP;
val = rkisp_read(dev, CSI2RX_CTRL0, true);
val &= ~SW_IBUF_OP_MODE(0xf);
tmp = SW_IBUF_OP_MODE(dev->rd_mode);
val |= tmp | SW_CSI2RX_EN | SW_DMA_2FRM_MODE(dma2frm);
+ if (dev->isp_ver > ISP_V20)
+ dma2frm = dev->sw_rd_cnt;
v4l2_dbg(2, rkisp_debug, &dev->v4l2_dev,
- "readback frame:%d time:%d 0x%x\n",
- cur_frame_id, dma2frm + 1, val);
- if (!dma2frm)
- rkisp_bridge_update_mi(dev, 0);
+ "readback frame:%d time:%d 0x%x try:%d\n",
+ cur_frame_id, dma2frm + 1, val, is_try);
if (!hw->is_shutdown)
- rkisp_write(dev, CSI2RX_CTRL0, val, true);
+ rkisp_unite_write(dev, CSI2RX_CTRL0, val, true);
+}
+
+static void rkisp_fast_switch_rx_buf(struct rkisp_device *dev, bool is_current)
+{
+ struct rkisp_stream *stream;
+ struct rkisp_buffer *buf;
+ u32 i, val;
+
+ if (!dev->is_rtt_first)
+ return;
+
+ for (i = RKISP_STREAM_RAWRD0; i < RKISP_MAX_DMARX_STREAM; i++) {
+ stream = &dev->dmarx_dev.stream[i];
+ if (!stream->ops)
+ continue;
+ buf = NULL;
+ if (is_current)
+ buf = stream->curr_buf;
+ else if (!list_empty(&stream->buf_queue))
+ buf = list_first_entry(&stream->buf_queue,
+ struct rkisp_buffer, queue);
+ if (!buf)
+ continue;
+ val = buf->buff_addr[RKISP_PLANE_Y];
+ /* f1 -> f0 -> f1 for normal
+ * L:f1 L:f1 -> L:f0 S:f0 -> L:f1 S:f1 for hdr2
+ */
+ if (dev->rd_mode == HDR_RDBK_FRAME2 && !is_current &&
+ rkisp_read_reg_cache(dev, ISP3X_HDRMGE_GAIN0) == 0xfff0040) {
+ if (i == RKISP_STREAM_RAWRD2)
+ continue;
+ else
+ rkisp_write(dev, ISP3X_MI_RAWS_RD_BASE, val, false);
+ }
+ rkisp_write(dev, stream->config->mi.y_base_ad_init, val, false);
+ }
}
static void rkisp_rdbk_trigger_handle(struct rkisp_device *dev, u32 cmd)
@@ -644,20 +912,44 @@
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;
+ if (hw->unite == ISP_UNITE_ONE) {
+ if (dev->sw_rd_cnt < 2)
+ isp->unite_index = ISP_UNITE_RIGHT;
+ if (!hw->is_multi_overflow || (dev->sw_rd_cnt & 0x1))
+ is_try = false;
+ }
+ 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)
goto end;
if (hw->monitor.state & ISP_MIPI_ERROR && hw->monitor.is_en)
goto end;
+ if (!IS_HDR_RDBK(dev->rd_mode))
+ goto end;
+ if (dev->is_suspend) {
+ if (dev->suspend_sync)
+ complete(&dev->pm_cmpl);
+ goto end;
+ }
for (i = 0; i < hw->dev_num; i++) {
isp = hw->isp[i];
- if (!(isp->isp_state & ISP_START))
+ if (!isp ||
+ (isp && (!(isp->isp_state & ISP_START) || isp->is_suspend)))
continue;
rkisp_rdbk_trigger_event(isp, T_CMD_LEN, &len[i]);
if (max < len[i]) {
@@ -666,10 +958,14 @@
}
}
+ /* wait 2 frame to start isp for fast */
+ if (dev->is_rtt_first && max == 1 && !atomic_read(&dev->isp_sdev.frm_sync_seq))
+ goto end;
+
if (max) {
- v4l2_dbg(2, rkisp_debug, &dev->v4l2_dev,
- "trigger fifo len:%d\n", max);
isp = hw->isp[id];
+ v4l2_dbg(2, rkisp_debug, &isp->v4l2_dev,
+ "trigger fifo len:%d\n", max);
rkisp_rdbk_trigger_event(isp, T_CMD_DEQUEUE, &t);
isp->dmarx_dev.pre_frame = isp->dmarx_dev.cur_frame;
if (t.frame_id > isp->dmarx_dev.pre_frame.id &&
@@ -680,15 +976,52 @@
isp->dmarx_dev.cur_frame.sof_timestamp = t.sof_timestamp;
isp->dmarx_dev.cur_frame.timestamp = t.frame_timestamp;
isp->isp_sdev.frm_timestamp = t.sof_timestamp;
+ atomic_set(&isp->isp_sdev.frm_sync_seq, t.frame_id + 1);
mode = t.mode;
times = t.times;
hw->cur_dev_id = id;
hw->is_idle = false;
+ /* this frame will read count by isp */
+ isp->sw_rd_cnt = 0;
+ /* frame double for multi camera resolution out of hardware limit
+ * first for HW save this camera information, and second to output image
+ */
+ isp->is_frame_double = false;
+ if (hw->is_multi_overflow &&
+ (hw->unite == ISP_UNITE_ONE ||
+ (hw->pre_dev_id != -1 && hw->pre_dev_id != id))) {
+ isp->is_frame_double = true;
+ isp->sw_rd_cnt = 1;
+ times = 0;
+ }
+ /* resolution out of hardware limit
+ * frame is vertically divided into left and right
+ */
+ isp->unite_index = ISP_UNITE_LEFT;
+ if (hw->unite == ISP_UNITE_ONE) {
+ isp->sw_rd_cnt *= 2;
+ isp->sw_rd_cnt += 1;
+ }
+ /* first frame handle twice for thunderboot
+ * first output stats to AIQ and wait new params to run second
+ */
+ if (isp->is_rtt_first && t.frame_id == 0) {
+ isp->is_first_double = true;
+ isp->skip_frame = 1;
+ if (hw->unite != ISP_UNITE_ONE) {
+ isp->sw_rd_cnt = 0;
+ isp->is_frame_double = false;
+ }
+ rkisp_fast_switch_rx_buf(isp, false);
+ } else {
+ isp->is_rtt_first = false;
+ }
+ isp->params_vdev.rdbk_times = isp->sw_rd_cnt + 1;
}
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)
@@ -697,9 +1030,6 @@
struct isp2x_csi_trigger *trigger = NULL;
unsigned long lock_flags = 0;
int val, ret = 0;
-
- if (dev->dmarx_dev.trigger != T_MANUAL)
- return 0;
spin_lock_irqsave(&dev->rdbk_lock, lock_flags);
switch (cmd) {
@@ -732,6 +1062,14 @@
return ret;
}
+static void rkisp_rdbk_work(struct work_struct *work)
+{
+ struct rkisp_device *dev = container_of(work, struct rkisp_device, rdbk_work);
+
+ rkisp_dvfs(dev);
+ rkisp_rdbk_trigger_event(dev, T_CMD_END, NULL);
+}
+
void rkisp_check_idle(struct rkisp_device *dev, u32 irq)
{
u32 val = 0;
@@ -750,13 +1088,24 @@
!IS_HDR_RDBK(dev->rd_mode))
return;
+ if (dev->sw_rd_cnt)
+ goto end;
+
+ if (dev->is_first_double) {
+ rkisp_fast_switch_rx_buf(dev, true);
+ dev->is_rtt_first = false;
+ dev->skip_frame = 0;
+ dev->irq_ends = 0;
+ return;
+ }
+
/* check output stream is off */
- val = ISP_FRAME_MP | ISP_FRAME_SP | ISP_FRAME_MPFBC;
+ val = ISP_FRAME_MP | ISP_FRAME_SP | ISP_FRAME_MPFBC | ISP_FRAME_BP;
if (!(dev->irq_ends_mask & val)) {
u32 state = dev->isp_state;
struct rkisp_stream *s;
- for (val = 0; val <= RKISP_STREAM_SP; val++) {
+ for (val = 0; val < RKISP_STREAM_VIR; val++) {
s = &dev->cap_dev.stream[val];
dev->isp_state = ISP_STOP;
if (s->streaming) {
@@ -767,7 +1116,6 @@
}
val = 0;
- dev->irq_ends = 0;
switch (dev->rd_mode) {
case HDR_RDBK_FRAME3://for rd1 rd0 rd2
val |= RAW1_RD_FRAME;
@@ -780,7 +1128,12 @@
/* FALLTHROUGH */
}
rkisp2_rawrd_isr(val, dev);
- if (dev->dmarx_dev.trigger == T_MANUAL)
+
+end:
+ dev->irq_ends = 0;
+ if (dev->hw_dev->is_dvfs)
+ schedule_work(&dev->rdbk_work);
+ else
rkisp_rdbk_trigger_event(dev, T_CMD_END, NULL);
if (dev->isp_state == ISP_STOP)
wake_up(&dev->sync_onoff);
@@ -803,113 +1156,48 @@
*/
static void rkisp_config_ism(struct rkisp_device *dev)
{
- void __iomem *base = dev->base_addr;
struct v4l2_rect *out_crop = &dev->isp_sdev.out_crop;
- u32 val;
+ u32 width = out_crop->width, mult = 1;
+ u32 unite = dev->hw_dev->unite;
/* isp2.0 no ism */
- if (dev->isp_ver == ISP_V20 || dev->isp_ver == ISP_V21)
+ if (dev->isp_ver == ISP_V20 || dev->isp_ver == ISP_V21 ||
+ dev->isp_ver == ISP_V32_L)
return;
- writel(0, base + CIF_ISP_IS_RECENTER);
- writel(0, base + CIF_ISP_IS_MAX_DX);
- writel(0, base + CIF_ISP_IS_MAX_DY);
- writel(0, base + CIF_ISP_IS_DISPLACE);
- writel(out_crop->left, base + CIF_ISP_IS_H_OFFS);
- writel(out_crop->top, base + CIF_ISP_IS_V_OFFS);
- writel(out_crop->width, base + CIF_ISP_IS_H_SIZE);
+ if (unite)
+ width = width / 2 + RKMOUDLE_UNITE_EXTEND_PIXEL;
+ rkisp_unite_write(dev, CIF_ISP_IS_RECENTER, 0, false);
+ rkisp_unite_write(dev, CIF_ISP_IS_MAX_DX, 0, false);
+ rkisp_unite_write(dev, CIF_ISP_IS_MAX_DY, 0, false);
+ rkisp_unite_write(dev, CIF_ISP_IS_DISPLACE, 0, false);
+ rkisp_unite_write(dev, CIF_ISP_IS_H_OFFS, out_crop->left, false);
+ rkisp_unite_write(dev, CIF_ISP_IS_V_OFFS, out_crop->top, false);
+ rkisp_unite_write(dev, CIF_ISP_IS_H_SIZE, width, false);
if (dev->cap_dev.stream[RKISP_STREAM_SP].interlaced)
- writel(out_crop->height / 2, base + CIF_ISP_IS_V_SIZE);
- else
- writel(out_crop->height, base + CIF_ISP_IS_V_SIZE);
+ mult = 2;
+ rkisp_unite_write(dev, CIF_ISP_IS_V_SIZE, out_crop->height / mult, false);
+
+ if (dev->isp_ver == ISP_V30 || dev->isp_ver == ISP_V32)
+ return;
/* IS(Image Stabilization) is always on, working as output crop */
- writel(1, base + CIF_ISP_IS_CTRL);
- val = readl(base + CIF_ISP_CTRL);
- val |= CIF_ISP_CTRL_ISP_CFG_UPD;
- writel(val, base + CIF_ISP_CTRL);
+ rkisp_write(dev, CIF_ISP_IS_CTRL, 1, false);
}
-static int rkisp_reset_handle_v2x(struct rkisp_device *dev)
+static int rkisp_reset_handle(struct rkisp_device *dev)
{
- void __iomem *base = dev->base_addr;
- void *reg_buf = NULL;
- u32 *reg, *reg1, i;
- struct backup_reg backup[] = {
- {
- .base = MI_MP_WR_Y_BASE,
- .shd = MI_MP_WR_Y_BASE_SHD,
- }, {
- .base = MI_MP_WR_CB_BASE,
- .shd = MI_MP_WR_CB_BASE_SHD,
- }, {
- .base = MI_MP_WR_CR_BASE,
- .shd = MI_MP_WR_CR_BASE_SHD,
- }, {
- .base = MI_SP_WR_Y_BASE,
- .shd = MI_SP_WR_Y_BASE_SHD,
- }, {
- .base = MI_SP_WR_CB_BASE,
- .shd = MI_SP_WR_CB_BASE_AD_SHD,
- }, {
- .base = MI_SP_WR_CR_BASE,
- .shd = MI_SP_WR_CR_BASE_AD_SHD,
- }, {
- .base = MI_RAW0_WR_BASE,
- .shd = MI_RAW0_WR_BASE_SHD,
- }, {
- .base = MI_RAW1_WR_BASE,
- .shd = MI_RAW1_WR_BASE_SHD,
- }, {
- .base = MI_RAW2_WR_BASE,
- .shd = MI_RAW2_WR_BASE_SHD,
- }, {
- .base = MI_RAW3_WR_BASE,
- .shd = MI_RAW3_WR_BASE_SHD,
- }, {
- .base = MI_RAW0_RD_BASE,
- .shd = MI_RAW0_RD_BASE_SHD,
- }, {
- .base = MI_RAW1_RD_BASE,
- .shd = MI_RAW1_RD_BASE_SHD,
- }, {
- .base = MI_RAW2_RD_BASE,
- .shd = MI_RAW2_RD_BASE_SHD,
- }, {
- .base = MI_GAIN_WR_BASE,
- .shd = MI_GAIN_WR_BASE_SHD,
- }
- };
-
- reg_buf = kzalloc(RKISP_ISP_SW_REG_SIZE, GFP_KERNEL);
- if (!reg_buf)
- return -ENOMEM;
+ u32 val;
dev_info(dev->dev, "%s enter\n", __func__);
+ rkisp_hw_reg_save(dev->hw_dev);
- memcpy_fromio(reg_buf, base, RKISP_ISP_SW_REG_SIZE);
rkisp_soft_reset(dev->hw_dev, true);
- /* process special reg */
- reg = reg_buf + ISP_CTRL;
- *reg &= ~(CIF_ISP_CTRL_ISP_ENABLE |
- CIF_ISP_CTRL_ISP_INFORM_ENABLE |
- CIF_ISP_CTRL_ISP_CFG_UPD);
- reg = reg_buf + MI_WR_INIT;
- *reg = 0;
- reg = reg_buf + CSI2RX_CTRL0;
- *reg &= ~SW_CSI2RX_EN;
- /* skip mmu range */
- memcpy_toio(base, reg_buf, ISP21_MI_BAY3D_RD_BASE_SHD);
- memcpy_toio(base + CSI2RX_CTRL0, reg_buf + CSI2RX_CTRL0,
- RKISP_ISP_SW_REG_SIZE - CSI2RX_CTRL0);
- /* config shd_reg to base_reg */
- for (i = 0; i < ARRAY_SIZE(backup); i++) {
- reg = reg_buf + backup[i].base;
- reg1 = reg_buf + backup[i].shd;
- backup[i].val = *reg;
- writel(*reg1, base + backup[i].base);
- }
+ rkisp_hw_reg_restore(dev->hw_dev);
+
+ val = CIF_ISP_DATA_LOSS | CIF_ISP_PIC_SIZE_ERROR;
+ rkisp_unite_set_bits(dev, CIF_ISP_IMSC, 0, val, true);
/* clear state */
dev->isp_err_cnt = 0;
@@ -917,40 +1205,12 @@
rkisp_set_state(&dev->isp_state, ISP_FRAME_END);
dev->hw_dev->monitor.state = ISP_FRAME_END;
- /* update module */
- reg = reg_buf + DUAL_CROP_CTRL;
- if (*reg & 0xf)
- writel(*reg | CIF_DUAL_CROP_CFG_UPD, base + DUAL_CROP_CTRL);
- reg = reg_buf + SELF_RESIZE_CTRL;
- if (*reg & 0xf)
- writel(*reg | CIF_RSZ_CTRL_CFG_UPD, base + SELF_RESIZE_CTRL);
- reg = reg_buf + MAIN_RESIZE_CTRL;
- if (*reg & 0xf)
- writel(*reg | CIF_RSZ_CTRL_CFG_UPD, base + MAIN_RESIZE_CTRL);
-
- /* update mi and isp, base_reg will update to shd_reg */
- force_cfg_update(dev);
- reg = reg_buf + ISP_CTRL;
- *reg |= CIF_ISP_CTRL_ISP_ENABLE |
- CIF_ISP_CTRL_ISP_INFORM_ENABLE |
- CIF_ISP_CTRL_ISP_CFG_UPD;
- writel(*reg, base + ISP_CTRL);
- udelay(50);
- /* config base_reg */
- for (i = 0; i < ARRAY_SIZE(backup); i++)
- writel(backup[i].val, base + backup[i].base);
- /* mpfbc base_reg = shd_reg, write is base but read is shd */
- if (dev->isp_ver == ISP_V20)
- writel(rkisp_read_reg_cache(dev, ISP_MPFBC_HEAD_PTR),
- base + ISP_MPFBC_HEAD_PTR);
- rkisp_set_bits(dev, CIF_ISP_IMSC, 0, CIF_ISP_DATA_LOSS | CIF_ISP_PIC_SIZE_ERROR, true);
if (IS_HDR_RDBK(dev->hdr.op_mode)) {
if (!dev->hw_dev->is_idle)
rkisp_trigger_read_back(dev, 1, 0, true);
else
rkisp_rdbk_trigger_event(dev, T_CMD_QUEUE, NULL);
}
- kfree(reg_buf);
dev_info(dev->dev, "%s exit\n", __func__);
return 0;
}
@@ -964,11 +1224,6 @@
struct rkisp_pipeline *p;
int ret, i, j, timeout = 5, mipi_irq_cnt = 0;
- if (!monitor->reset_handle) {
- monitor->is_en = false;
- return;
- }
-
dev_info(hw->dev, "%s enter\n", __func__);
while (!(monitor->state & ISP_STOP) && monitor->is_en) {
ret = wait_for_completion_timeout(&monitor->cmpl,
@@ -976,15 +1231,18 @@
/* isp stop to exit
* isp err to reset
* mipi err wait isp idle, then reset
+ * online vicap if isp err, notify vicap reset, then vicap notify isp reset
+ * by ioctl RKISP_VICAP_CMD_SET_STREAM
*/
if (monitor->state & ISP_STOP ||
+ monitor->state & ISP_CIF_RESET ||
(ret && !(monitor->state & ISP_ERROR)) ||
(!ret &&
monitor->state & ISP_FRAME_END &&
!(monitor->state & ISP_MIPI_ERROR))) {
for (i = 0; i < hw->dev_num; i++) {
isp = hw->isp[i];
- if (!(isp->isp_inp & INP_CSI))
+ if (!isp || (isp && !(isp->isp_inp & INP_CSI)))
continue;
if (!(isp->isp_state & ISP_START))
break;
@@ -1006,6 +1264,8 @@
}
for (i = 0; i < hw->dev_num; i++) {
isp = hw->isp[i];
+ if (!isp)
+ continue;
if (isp->isp_inp & INP_CSI ||
isp->isp_inp & INP_DVP ||
isp->isp_inp & INP_LVDS) {
@@ -1024,14 +1284,28 @@
/* restart isp */
isp = hw->isp[hw->cur_dev_id];
- ret = monitor->reset_handle(isp);
- if (ret) {
- monitor->is_en = false;
- break;
+ if (!IS_HDR_RDBK(isp->hdr.op_mode) && isp->isp_ver >= ISP_V30) {
+ struct v4l2_subdev *remote = NULL;
+ struct v4l2_subdev *isp_subdev = NULL;
+
+ isp_subdev = &(isp->isp_sdev.sd);
+ remote = get_remote_sensor(isp_subdev);
+ v4l2_subdev_call(remote, core, ioctl,
+ RKISP_VICAP_CMD_SET_RESET, NULL);
+ monitor->state |= ISP_CIF_RESET;
+ continue;
+ } else {
+ ret = rkisp_reset_handle(isp);
+ if (ret) {
+ monitor->is_en = false;
+ break;
+ }
}
for (i = 0; i < hw->dev_num; i++) {
isp = hw->isp[i];
+ if (!isp)
+ continue;
if (isp->isp_inp & INP_CSI ||
isp->isp_inp & INP_DVP ||
isp->isp_inp & INP_LVDS) {
@@ -1059,9 +1333,6 @@
struct rkisp_monitor *monitor = &dev->hw_dev->monitor;
monitor->dev = dev->hw_dev;
- monitor->reset_handle = NULL;
- if (dev->isp_ver == ISP_V20 || dev->isp_ver == ISP_V21)
- monitor->reset_handle = rkisp_reset_handle_v2x;
init_completion(&monitor->cmpl);
INIT_WORK(&monitor->work, rkisp_restart_monitor);
@@ -1085,6 +1356,8 @@
*/
static void rkisp_config_color_space(struct rkisp_device *dev)
{
+ u32 val = 0;
+
u16 bt601_coeff[] = {
0x0026, 0x004b, 0x000f,
0x01ea, 0x01d6, 0x0040,
@@ -1116,16 +1389,222 @@
}
for (i = 0; i < 9; i++)
- rkisp_write(dev, CIF_ISP_CC_COEFF_0 + i * 4, *(coeff + i), false);
+ rkisp_unite_write(dev, CIF_ISP_CC_COEFF_0 + i * 4,
+ *(coeff + i), false);
+
+ val = rkisp_read_reg_cache(dev, CIF_ISP_CTRL);
if (dev->isp_sdev.quantization == V4L2_QUANTIZATION_FULL_RANGE)
- rkisp_set_bits(dev, CIF_ISP_CTRL, 0,
- CIF_ISP_CTRL_ISP_CSM_Y_FULL_ENA |
- CIF_ISP_CTRL_ISP_CSM_C_FULL_ENA, false);
+ rkisp_unite_write(dev, CIF_ISP_CTRL, val |
+ CIF_ISP_CTRL_ISP_CSM_Y_FULL_ENA |
+ CIF_ISP_CTRL_ISP_CSM_C_FULL_ENA, false);
else
- rkisp_clear_bits(dev, CIF_ISP_CTRL,
- CIF_ISP_CTRL_ISP_CSM_Y_FULL_ENA |
- CIF_ISP_CTRL_ISP_CSM_C_FULL_ENA, false);
+ rkisp_unite_write(dev, CIF_ISP_CTRL, val &
+ ~(CIF_ISP_CTRL_ISP_CSM_Y_FULL_ENA |
+ CIF_ISP_CTRL_ISP_CSM_C_FULL_ENA), false);
+}
+
+static void rkisp_config_cmsk_single(struct rkisp_device *dev,
+ struct rkisp_cmsk_cfg *cfg)
+{
+ u32 i, val, ctrl = 0;
+ u32 mp_en = cfg->win[0].win_en;
+ u32 sp_en = cfg->win[1].win_en;
+ u32 bp_en = cfg->win[2].win_en;
+ u32 win_max = (dev->isp_ver == ISP_V30) ?
+ RKISP_CMSK_WIN_MAX_V30 : RKISP_CMSK_WIN_MAX;
+
+ if (mp_en) {
+ ctrl |= ISP3X_SW_CMSK_EN_MP;
+ rkisp_write(dev, ISP3X_CMSK_CTRL1, mp_en, false);
+ val = cfg->win[0].mode;
+ rkisp_write(dev, ISP3X_CMSK_CTRL4, val, false);
+ }
+
+ if (sp_en) {
+ ctrl |= ISP3X_SW_CMSK_EN_SP;
+ rkisp_write(dev, ISP3X_CMSK_CTRL2, sp_en, false);
+ val = cfg->win[1].mode;
+ rkisp_write(dev, ISP3X_CMSK_CTRL5, val, false);
+ }
+
+ if (bp_en) {
+ ctrl |= ISP3X_SW_CMSK_EN_BP;
+ rkisp_write(dev, ISP3X_CMSK_CTRL3, bp_en, false);
+ val = cfg->win[2].mode;
+ rkisp_write(dev, ISP3X_CMSK_CTRL6, val, false);
+ }
+
+ for (i = 0; i < win_max; i++) {
+ if (!(mp_en & BIT(i)) && !(sp_en & BIT(i)) && !(bp_en & BIT(i)))
+ continue;
+
+ val = ISP3X_SW_CMSK_YUV(cfg->win[i].cover_color_y,
+ cfg->win[i].cover_color_u,
+ cfg->win[i].cover_color_v);
+ rkisp_write(dev, ISP3X_CMSK_YUV0 + i * 4, val, false);
+
+ val = ISP_PACK_2SHORT(cfg->win[i].h_offs, cfg->win[i].v_offs);
+ rkisp_write(dev, ISP3X_CMSK_OFFS0 + i * 8, val, false);
+
+ val = ISP_PACK_2SHORT(cfg->win[i].h_size, cfg->win[i].v_size);
+ rkisp_write(dev, ISP3X_CMSK_SIZE0 + i * 8, val, false);
+ }
+
+ if (ctrl) {
+ val = ISP_PACK_2SHORT(dev->isp_sdev.out_crop.width,
+ dev->isp_sdev.out_crop.height);
+ rkisp_write(dev, ISP3X_CMSK_PIC_SIZE, val, false);
+ ctrl |= ISP3X_SW_CMSK_EN | ISP3X_SW_CMSK_ORDER_MODE;
+ ctrl |= ISP3X_SW_CMSK_BLKSIZE(cfg->mosaic_block);
+ }
+ rkisp_write(dev, ISP3X_CMSK_CTRL0, ctrl, false);
+
+ val = rkisp_read(dev, ISP3X_CMSK_CTRL0, true);
+ if (dev->hw_dev->is_single &&
+ ((val & ISP32_SW_CMSK_EN_PATH) != (val & ISP32_SW_CMSK_EN_PATH_SHD)))
+ rkisp_write(dev, ISP3X_CMSK_CTRL0, val | ISP3X_SW_CMSK_FORCE_UPD, true);
+}
+
+static void rkisp_config_cmsk_dual(struct rkisp_device *dev,
+ struct rkisp_cmsk_cfg *cfg)
+{
+ struct rkisp_cmsk_cfg left = *cfg;
+ struct rkisp_cmsk_cfg right = *cfg;
+ u32 width = dev->isp_sdev.out_crop.width;
+ u32 height = dev->isp_sdev.out_crop.height;
+ u32 w = width / 2;
+ u32 i, val, h_offs, h_size, ctrl;
+ u8 mp_en = cfg->win[0].win_en;
+ u8 sp_en = cfg->win[1].win_en;
+ u8 bp_en = cfg->win[2].win_en;
+ u32 win_max = (dev->isp_ver == ISP_V30) ?
+ RKISP_CMSK_WIN_MAX_V30 : RKISP_CMSK_WIN_MAX;
+
+ for (i = 0; i < win_max; i++) {
+ if (!(mp_en & BIT(i)) && !(sp_en & BIT(i)) && !(bp_en & BIT(i)))
+ continue;
+
+ h_offs = cfg->win[i].h_offs;
+ h_size = cfg->win[i].h_size;
+ if (h_offs + h_size <= w) {
+ /* cmsk window at left isp */
+ right.win[0].win_en &= ~BIT(i);
+ right.win[1].win_en &= ~BIT(i);
+ right.win[2].win_en &= ~BIT(i);
+ } else if (h_offs >= w) {
+ /* cmsk window at right isp */
+ left.win[0].win_en &= ~BIT(i);
+ left.win[1].win_en &= ~BIT(i);
+ left.win[2].win_en &= ~BIT(i);
+ right.win[i].h_offs = h_offs - w + RKMOUDLE_UNITE_EXTEND_PIXEL;
+ } else {
+ /* cmsk window at dual isp */
+ left.win[i].h_size = ALIGN(w - h_offs, 8);
+
+ right.win[i].h_offs = RKMOUDLE_UNITE_EXTEND_PIXEL;
+ val = h_offs + h_size - w;
+ right.win[i].h_size = ALIGN(val, 8);
+ right.win[i].h_offs -= right.win[i].h_size - val;
+ }
+
+ val = ISP3X_SW_CMSK_YUV(left.win[i].cover_color_y,
+ left.win[i].cover_color_u,
+ left.win[i].cover_color_v);
+ rkisp_write(dev, ISP3X_CMSK_YUV0 + i * 4, val, false);
+ rkisp_next_write(dev, ISP3X_CMSK_YUV0 + i * 4, val, false);
+
+ val = ISP_PACK_2SHORT(left.win[i].h_offs, left.win[i].v_offs);
+ rkisp_write(dev, ISP3X_CMSK_OFFS0 + i * 8, val, false);
+ val = ISP_PACK_2SHORT(left.win[i].h_size, left.win[i].v_size);
+ rkisp_write(dev, ISP3X_CMSK_SIZE0 + i * 8, val, false);
+
+ val = ISP_PACK_2SHORT(right.win[i].h_offs, right.win[i].v_offs);
+ rkisp_next_write(dev, ISP3X_CMSK_OFFS0 + i * 8, val, false);
+ val = ISP_PACK_2SHORT(right.win[i].h_size, right.win[i].v_size);
+ rkisp_next_write(dev, ISP3X_CMSK_SIZE0 + i * 8, val, false);
+ }
+
+ w += RKMOUDLE_UNITE_EXTEND_PIXEL;
+ ctrl = 0;
+ if (left.win[0].win_en) {
+ ctrl |= ISP3X_SW_CMSK_EN_MP;
+ rkisp_write(dev, ISP3X_CMSK_CTRL1, left.win[0].win_en, false);
+ val = left.win[0].mode;
+ rkisp_write(dev, ISP3X_CMSK_CTRL4, val, false);
+ }
+ if (left.win[1].win_en) {
+ ctrl |= ISP3X_SW_CMSK_EN_SP;
+ rkisp_write(dev, ISP3X_CMSK_CTRL2, left.win[1].win_en, false);
+ val = left.win[1].mode;
+ rkisp_write(dev, ISP3X_CMSK_CTRL5, val, false);
+ }
+ if (left.win[2].win_en) {
+ ctrl |= ISP3X_SW_CMSK_EN_BP;
+ rkisp_write(dev, ISP3X_CMSK_CTRL3, left.win[2].win_en, false);
+ val = left.win[2].mode;
+ rkisp_write(dev, ISP3X_CMSK_CTRL6, val, false);
+ }
+ if (ctrl) {
+ val = ISP_PACK_2SHORT(w, height);
+ rkisp_write(dev, ISP3X_CMSK_PIC_SIZE, val, false);
+ ctrl |= ISP3X_SW_CMSK_EN | ISP3X_SW_CMSK_ORDER_MODE;
+ }
+ rkisp_write(dev, ISP3X_CMSK_CTRL0, ctrl, false);
+
+ ctrl = 0;
+ if (right.win[0].win_en) {
+ ctrl |= ISP3X_SW_CMSK_EN_MP;
+ rkisp_next_write(dev, ISP3X_CMSK_CTRL1, right.win[0].win_en, false);
+ val = right.win[0].mode;
+ rkisp_next_write(dev, ISP3X_CMSK_CTRL4, val, false);
+ }
+ if (right.win[1].win_en) {
+ ctrl |= ISP3X_SW_CMSK_EN_SP;
+ rkisp_next_write(dev, ISP3X_CMSK_CTRL2, right.win[1].win_en, false);
+ val = right.win[1].mode;
+ rkisp_next_write(dev, ISP3X_CMSK_CTRL5, val, false);
+ }
+ if (right.win[2].win_en) {
+ ctrl |= ISP3X_SW_CMSK_EN_BP;
+ rkisp_next_write(dev, ISP3X_CMSK_CTRL3, right.win[2].win_en, false);
+ val = right.win[2].mode;
+ rkisp_next_write(dev, ISP3X_CMSK_CTRL6, val, false);
+ }
+ if (ctrl) {
+ val = ISP_PACK_2SHORT(w, height);
+ rkisp_next_write(dev, ISP3X_CMSK_PIC_SIZE, val, false);
+ ctrl |= ISP3X_SW_CMSK_EN | ISP3X_SW_CMSK_ORDER_MODE;
+ }
+ rkisp_next_write(dev, ISP3X_CMSK_CTRL0, ctrl, false);
+
+ val = rkisp_next_read(dev, ISP3X_CMSK_CTRL0, true);
+ if (dev->hw_dev->is_single &&
+ ((val & ISP32_SW_CMSK_EN_PATH) != (val & ISP32_SW_CMSK_EN_PATH_SHD)))
+ rkisp_next_write(dev, ISP3X_CMSK_CTRL0, val | ISP3X_SW_CMSK_FORCE_UPD, false);
+}
+
+static void rkisp_config_cmsk(struct rkisp_device *dev)
+{
+ unsigned long lock_flags = 0;
+ struct rkisp_cmsk_cfg cfg;
+
+ if (dev->isp_ver != ISP_V30 && dev->isp_ver != ISP_V32)
+ return;
+
+ spin_lock_irqsave(&dev->cmsk_lock, lock_flags);
+ if (!dev->is_cmsk_upd) {
+ spin_unlock_irqrestore(&dev->cmsk_lock, lock_flags);
+ return;
+ }
+ dev->is_cmsk_upd = false;
+ cfg = dev->cmsk_cfg;
+ spin_unlock_irqrestore(&dev->cmsk_lock, lock_flags);
+
+ if (!dev->hw_dev->unite)
+ rkisp_config_cmsk_single(dev, &cfg);
+ else
+ rkisp_config_cmsk_dual(dev, &cfg);
}
/*
@@ -1137,17 +1616,20 @@
struct ispsd_out_fmt *out_fmt;
struct v4l2_rect *in_crop;
struct rkisp_sensor_info *sensor;
+ bool is_unite = !!dev->hw_dev->unite;
u32 isp_ctrl = 0;
u32 irq_mask = 0;
u32 signal = 0;
u32 acq_mult = 0;
u32 acq_prop = 0;
u32 extend_line = 0;
+ u32 width;
sensor = dev->active_sensor;
in_fmt = &dev->isp_sdev.in_fmt;
out_fmt = &dev->isp_sdev.out_fmt;
in_crop = &dev->isp_sdev.in_crop;
+ width = in_crop->width;
if (in_fmt->fmt_type == FMT_BAYER) {
acq_mult = 1;
@@ -1163,21 +1645,21 @@
if (in_fmt->mbus_code == MEDIA_BUS_FMT_Y8_1X8 ||
in_fmt->mbus_code == MEDIA_BUS_FMT_Y10_1X10 ||
in_fmt->mbus_code == MEDIA_BUS_FMT_Y12_1X12) {
- if (dev->isp_ver == ISP_V20 || dev->isp_ver == ISP_V21)
- rkisp_write(dev, ISP_DEBAYER_CONTROL, 0, false);
+ if (dev->isp_ver >= ISP_V20)
+ rkisp_unite_write(dev, ISP_DEBAYER_CONTROL, 0, false);
else
rkisp_write(dev, CIF_ISP_DEMOSAIC,
- CIF_ISP_DEMOSAIC_BYPASS |
- CIF_ISP_DEMOSAIC_TH(0xc), false);
+ CIF_ISP_DEMOSAIC_BYPASS |
+ CIF_ISP_DEMOSAIC_TH(0xc), false);
} else {
- if (dev->isp_ver == ISP_V20 || dev->isp_ver == ISP_V21)
- rkisp_write(dev, ISP_DEBAYER_CONTROL,
- SW_DEBAYER_EN |
- SW_DEBAYER_FILTER_G_EN |
- SW_DEBAYER_FILTER_C_EN, false);
+ if (dev->isp_ver >= ISP_V20)
+ rkisp_unite_write(dev, ISP_DEBAYER_CONTROL,
+ SW_DEBAYER_EN |
+ SW_DEBAYER_FILTER_G_EN |
+ SW_DEBAYER_FILTER_C_EN, false);
else
rkisp_write(dev, CIF_ISP_DEMOSAIC,
- CIF_ISP_DEMOSAIC_TH(0xc), false);
+ CIF_ISP_DEMOSAIC_TH(0xc), false);
}
if (sensor && sensor->mbus.type == V4L2_MBUS_BT656)
@@ -1195,7 +1677,7 @@
} else if (in_fmt->fmt_type == FMT_YUV) {
acq_mult = 2;
if (sensor &&
- (sensor->mbus.type == V4L2_MBUS_CSI2 ||
+ (sensor->mbus.type == V4L2_MBUS_CSI2_DPHY ||
sensor->mbus.type == V4L2_MBUS_CCP2)) {
isp_ctrl = CIF_ISP_CTRL_ISP_MODE_ITU601;
} else {
@@ -1227,39 +1709,46 @@
signal |= CIF_ISP_ACQ_PROP_HSYNC_LOW;
}
- rkisp_write(dev, CIF_ISP_CTRL, isp_ctrl, false);
+ if (rkisp_read_reg_cache(dev, CIF_ISP_CTRL) & ISP32_MIR_ENABLE)
+ isp_ctrl |= ISP32_MIR_ENABLE;
+
+ rkisp_unite_write(dev, CIF_ISP_CTRL, isp_ctrl, false);
acq_prop |= signal | in_fmt->yuv_seq |
CIF_ISP_ACQ_PROP_BAYER_PAT(in_fmt->bayer_pat) |
CIF_ISP_ACQ_PROP_FIELD_SEL_ALL;
- rkisp_write(dev, CIF_ISP_ACQ_PROP, acq_prop, false);
- rkisp_write(dev, CIF_ISP_ACQ_NR_FRAMES, 0, true);
+ rkisp_unite_write(dev, CIF_ISP_ACQ_PROP, acq_prop, false);
+ rkisp_unite_write(dev, CIF_ISP_ACQ_NR_FRAMES, 0, true);
+ if (is_unite)
+ width = width / 2 + RKMOUDLE_UNITE_EXTEND_PIXEL;
/* Acquisition Size */
- rkisp_write(dev, CIF_ISP_ACQ_H_OFFS, acq_mult * in_crop->left, false);
- rkisp_write(dev, CIF_ISP_ACQ_V_OFFS, in_crop->top, false);
- rkisp_write(dev, CIF_ISP_ACQ_H_SIZE, acq_mult * in_crop->width, false);
+ rkisp_unite_write(dev, CIF_ISP_ACQ_H_OFFS, acq_mult * in_crop->left, false);
+ rkisp_unite_write(dev, CIF_ISP_ACQ_V_OFFS, in_crop->top, false);
+ rkisp_unite_write(dev, CIF_ISP_ACQ_H_SIZE, acq_mult * width, false);
/* ISP Out Area differ with ACQ is only FIFO, so don't crop in this */
- rkisp_write(dev, CIF_ISP_OUT_H_OFFS, 0, true);
- rkisp_write(dev, CIF_ISP_OUT_V_OFFS, 0, true);
- rkisp_write(dev, CIF_ISP_OUT_H_SIZE, in_crop->width, false);
+ rkisp_unite_write(dev, CIF_ISP_OUT_H_OFFS, 0, true);
+ rkisp_unite_write(dev, CIF_ISP_OUT_V_OFFS, 0, true);
+ rkisp_unite_write(dev, CIF_ISP_OUT_H_SIZE, width, false);
if (dev->cap_dev.stream[RKISP_STREAM_SP].interlaced) {
- rkisp_write(dev, CIF_ISP_ACQ_V_SIZE, in_crop->height / 2, false);
- rkisp_write(dev, CIF_ISP_OUT_V_SIZE, in_crop->height / 2, false);
+ rkisp_unite_write(dev, CIF_ISP_ACQ_V_SIZE, in_crop->height / 2, false);
+ rkisp_unite_write(dev, CIF_ISP_OUT_V_SIZE, in_crop->height / 2, false);
} else {
- rkisp_write(dev, CIF_ISP_ACQ_V_SIZE, in_crop->height + extend_line, false);
- rkisp_write(dev, CIF_ISP_OUT_V_SIZE, in_crop->height + extend_line, false);
+ rkisp_unite_write(dev, CIF_ISP_ACQ_V_SIZE, in_crop->height + extend_line, false);
+ rkisp_unite_write(dev, CIF_ISP_OUT_V_SIZE, in_crop->height + extend_line, false);
}
/* interrupt mask */
- irq_mask |= CIF_ISP_FRAME | CIF_ISP_V_START | CIF_ISP_PIC_SIZE_ERROR |
- CIF_ISP_FRAME_IN;
- if (dev->isp_ver == ISP_V20 || dev->isp_ver == ISP_V21)
+ irq_mask |= CIF_ISP_FRAME | CIF_ISP_V_START | CIF_ISP_PIC_SIZE_ERROR;
+ if (dev->isp_ver >= ISP_V20)
irq_mask |= ISP2X_LSC_LUT_ERR;
- rkisp_write(dev, CIF_ISP_IMSC, irq_mask, true);
+ if (dev->is_pre_on)
+ irq_mask |= CIF_ISP_FRAME_IN;
+ rkisp_unite_write(dev, CIF_ISP_IMSC, irq_mask, true);
- if ((dev->isp_ver == ISP_V20 || dev->isp_ver == ISP_V21) &&
+ if ((dev->isp_ver == ISP_V20 ||
+ dev->isp_ver == ISP_V21) &&
IS_HDR_RDBK(dev->hdr.op_mode)) {
irq_mask = ISP2X_3A_RAWAE_BIG;
rkisp_write(dev, ISP_ISP3A_IMSC, irq_mask, true);
@@ -1276,6 +1765,8 @@
rkisp_update_regs(dev, CIF_ISP_ACQ_H_OFFS, CIF_ISP_ACQ_V_SIZE);
rkisp_update_regs(dev, CIF_ISP_OUT_H_SIZE, CIF_ISP_OUT_V_SIZE);
}
+
+ rkisp_config_cmsk(dev);
return 0;
}
@@ -1379,12 +1870,12 @@
/* Configure MUX */
static int rkisp_config_path(struct rkisp_device *dev)
{
- int ret = 0;
struct rkisp_sensor_info *sensor = dev->active_sensor;
- u32 dpcl = readl(dev->base_addr + CIF_VI_DPCL);
+ int ret = 0;
+ u32 dpcl = 0;
/* isp input interface selects */
- if ((sensor && sensor->mbus.type == V4L2_MBUS_CSI2) ||
+ if ((sensor && sensor->mbus.type == V4L2_MBUS_CSI2_DPHY) ||
dev->isp_inp & (INP_RAWRD0 | INP_RAWRD1 | INP_RAWRD2 | INP_CIF)) {
/* mipi sensor->isp or isp read from ddr */
dpcl |= CIF_VI_DPCL_IF_SEL_MIPI;
@@ -1406,12 +1897,10 @@
ret = -EINVAL;
}
- /* fix 3a_wr no output with selfpath */
- if (dev->isp_ver == ISP_V21)
- dpcl |= CIF_VI_DPCL_CHAN_MODE_MP | CIF_VI_DPCL_MP_MUX_MRSZ_MI;
+ if (dev->isp_ver == ISP_V32)
+ dpcl |= BIT(0);
- writel(dpcl, dev->base_addr + CIF_VI_DPCL);
-
+ rkisp_unite_set_bits(dev, CIF_VI_DPCL, 0, dpcl, true);
return ret;
}
@@ -1483,7 +1972,7 @@
int ret = 1000;
if (!rkisp_is_need_3a(dev) || dev->isp_ver == ISP_V20 ||
- !params_vdev->is_subs_evt)
+ !params_vdev->is_subs_evt || dev->hw_dev->is_shutdown)
return;
v4l2_event_queue(vdev, &ev);
@@ -1500,6 +1989,7 @@
/* Mess register operations to stop isp */
static int rkisp_isp_stop(struct rkisp_device *dev)
{
+ struct rkisp_hw_dev *hw = dev->hw_dev;
void __iomem *base = dev->base_addr;
unsigned long old_rate, safe_rate;
u32 val;
@@ -1507,9 +1997,9 @@
v4l2_dbg(1, rkisp_debug, &dev->v4l2_dev,
"%s refcnt:%d\n", __func__,
- atomic_read(&dev->hw_dev->refcnt));
+ atomic_read(&hw->refcnt));
- if (atomic_read(&dev->hw_dev->refcnt) > 1)
+ if (atomic_read(&hw->refcnt) > 1)
goto end;
/*
* ISP(mi) stop in mi frame end -> Stop ISP(mipi) ->
@@ -1523,7 +2013,7 @@
readl(base + CIF_ISP_CSI0_ERR1);
readl(base + CIF_ISP_CSI0_ERR2);
readl(base + CIF_ISP_CSI0_ERR3);
- } else if (dev->isp_ver == ISP_V20 || dev->isp_ver == ISP_V21) {
+ } else if (dev->isp_ver >= ISP_V20) {
writel(0, base + CSI2RX_MASK_PHY);
writel(0, base + CSI2RX_MASK_PACKET);
writel(0, base + CSI2RX_MASK_OVERFLOW);
@@ -1540,7 +2030,7 @@
writel(0, base + CIF_ISP_IMSC);
writel(~0, base + CIF_ISP_ICR);
- if (dev->isp_ver == ISP_V20 || dev->isp_ver == ISP_V21) {
+ if (dev->isp_ver >= ISP_V20) {
writel(0, base + ISP_ISP3A_IMSC);
writel(~0, base + ISP_ISP3A_ICR);
}
@@ -1556,7 +2046,7 @@
udelay(20);
}
/* stop lsc to avoid lsclut error */
- if (dev->isp_ver == ISP_V20 || dev->isp_ver == ISP_V21)
+ if (dev->isp_ver >= ISP_V20)
writel(0, base + ISP_LSC_CTRL);
/* stop ISP */
val = readl(base + CIF_ISP_CTRL);
@@ -1565,6 +2055,9 @@
val = readl(base + CIF_ISP_CTRL);
writel(val | CIF_ISP_CTRL_ISP_CFG_UPD, base + CIF_ISP_CTRL);
+ if (hw->unite == ISP_UNITE_TWO)
+ rkisp_next_write(dev, CIF_ISP_CTRL,
+ val | CIF_ISP_CTRL_ISP_CFG_UPD, true);
readx_poll_timeout_atomic(readl, base + CIF_ISP_RIS,
val, val & CIF_ISP_OFF, 20, 100);
@@ -1572,19 +2065,19 @@
"MI_CTRL:%x, ISP_CTRL:%x\n",
readl(base + CIF_MI_CTRL), readl(base + CIF_ISP_CTRL));
- val = rkisp_read(dev, CTRL_VI_ISP_CLK_CTRL, true);
if (!in_interrupt()) {
/* normal case */
/* check the isp_clk before isp reset operation */
- old_rate = clk_get_rate(dev->hw_dev->clks[0]);
- safe_rate = dev->hw_dev->clk_rate_tbl[0].clk_rate * 1000000UL;
+ old_rate = clk_get_rate(hw->clks[0]);
+ safe_rate = hw->clk_rate_tbl[0].clk_rate * 1000000UL;
if (old_rate > safe_rate) {
- rkisp_set_clk_rate(dev->hw_dev->clks[0], safe_rate);
+ rkisp_set_clk_rate(hw->clks[0], safe_rate);
+ if (hw->unite == ISP_UNITE_TWO)
+ rkisp_set_clk_rate(hw->clks[5], safe_rate);
udelay(100);
}
- rkisp_soft_reset(dev->hw_dev, false);
+ rkisp_soft_reset(hw, false);
}
- rkisp_write(dev, CTRL_VI_ISP_CLK_CTRL, val, true);
if (dev->isp_ver == ISP_V12 || dev->isp_ver == ISP_V13) {
writel(0, base + CIF_ISP_CSI0_CSI2_RESETN);
@@ -1592,19 +2085,28 @@
writel(0, base + CIF_ISP_CSI0_MASK1);
writel(0, base + CIF_ISP_CSI0_MASK2);
writel(0, base + CIF_ISP_CSI0_MASK3);
- } else if (dev->isp_ver == ISP_V20 || dev->isp_ver == ISP_V21) {
+ } else if (dev->isp_ver >= ISP_V20) {
writel(0, base + CSI2RX_CSI2_RESETN);
+ if (hw->unite == ISP_UNITE_TWO)
+ rkisp_next_write(dev, CSI2RX_CSI2_RESETN, 0, true);
}
- dev->hw_dev->is_idle = true;
- dev->hw_dev->is_mi_update = false;
+ hw->is_dvfs = false;
+ hw->is_runing = false;
+ hw->is_idle = true;
+ hw->is_mi_update = false;
+ hw->pre_dev_id = -1;
end:
dev->irq_ends_mask = 0;
dev->hdr.op_mode = 0;
+ dev->sw_rd_cnt = 0;
+ dev->stats_vdev.rdbk_drop = false;
rkisp_set_state(&dev->isp_state, ISP_STOP);
- if (dev->isp_ver == ISP_V20 || dev->isp_ver == ISP_V21)
+ if (dev->isp_ver >= ISP_V20)
kfifo_reset(&dev->rdbk_kfifo);
+ if (dev->isp_ver == ISP_V30 || dev->isp_ver == ISP_V32)
+ memset(&dev->cmsk_cfg, 0, sizeof(dev->cmsk_cfg));
if (dev->emd_vc <= CIF_ISP_ADD_DATA_VC_MAX) {
for (i = 0; i < RKISP_EMDDATA_FIFO_MAX; i++)
kfifo_free(&dev->emd_data_fifo[i].mipi_kfifo);
@@ -1622,15 +2124,37 @@
{
struct rkisp_sensor_info *sensor = dev->active_sensor;
void __iomem *base = dev->base_addr;
- u32 val;
bool is_direct = true;
+ u32 val;
v4l2_dbg(1, rkisp_debug, &dev->v4l2_dev,
- "%s refcnt:%d\n", __func__,
- atomic_read(&dev->hw_dev->refcnt));
+ "%s refcnt:%d link_num:%d\n", __func__,
+ atomic_read(&dev->hw_dev->refcnt),
+ dev->hw_dev->dev_link_num);
+
+ dev->cap_dev.is_done_early = false;
+ if (dev->cap_dev.wait_line >= dev->isp_sdev.out_crop.height)
+ dev->cap_dev.wait_line = 0;
+ if (dev->cap_dev.wait_line) {
+ dev->cap_dev.is_done_early = true;
+ if (dev->isp_ver >= ISP_V32) {
+ val = dev->cap_dev.wait_line;
+ rkisp_write(dev, ISP32_ISP_IRQ_CFG0, val << 16, false);
+ rkisp_set_bits(dev, CIF_ISP_IMSC, 0, ISP3X_OUT_FRM_HALF, false);
+ } else {
+ /* using AF 15x15 block */
+ val = dev->isp_sdev.out_crop.height / 15;
+ val = dev->cap_dev.wait_line / val;
+ val = ISP3X_RAWAF_INELINE0(val) | ISP3X_RAWAF_INTLINE0_EN;
+ rkisp_unite_write(dev, ISP3X_RAWAF_INT_LINE, val, false);
+ rkisp_unite_set_bits(dev, ISP_ISP3A_IMSC, 0, ISP2X_3A_RAWAF, false);
+ rkisp_unite_clear_bits(dev, CIF_ISP_IMSC, ISP2X_LSC_LUT_ERR, false);
+ dev->rawaf_irq_cnt = 0;
+ }
+ }
/* Activate MIPI */
- if (sensor && sensor->mbus.type == V4L2_MBUS_CSI2) {
+ if (sensor && sensor->mbus.type == V4L2_MBUS_CSI2_DPHY) {
if (dev->isp_ver == ISP_V12 || dev->isp_ver == ISP_V13) {
/* clear interrupts state */
readl(base + CIF_ISP_CSI0_ERR1);
@@ -1645,19 +2169,19 @@
}
}
/* Activate ISP */
- val = rkisp_read(dev, CIF_ISP_CTRL, false);
+ val = rkisp_read_reg_cache(dev, CIF_ISP_CTRL);
val |= CIF_ISP_CTRL_ISP_CFG_UPD | CIF_ISP_CTRL_ISP_ENABLE |
CIF_ISP_CTRL_ISP_INFORM_ENABLE | CIF_ISP_CTRL_ISP_CFG_UPD_PERMANENT;
if (dev->isp_ver == ISP_V20)
val |= NOC_HURRY_PRIORITY(2) | NOC_HURRY_W_MODE(2) | NOC_HURRY_R_MODE(1);
if (atomic_read(&dev->hw_dev->refcnt) > 1)
is_direct = false;
- rkisp_write(dev, CIF_ISP_CTRL, val, is_direct);
+ rkisp_unite_write(dev, CIF_ISP_CTRL, val, is_direct);
+ rkisp_clear_reg_cache_bits(dev, CIF_ISP_CTRL, CIF_ISP_CTRL_ISP_CFG_UPD);
dev->isp_err_cnt = 0;
dev->isp_isr_cnt = 0;
- dev->isp_state = ISP_START | ISP_FRAME_END;
- dev->irq_ends_mask |= ISP_FRAME_END | ISP_FRAME_IN;
+ dev->irq_ends_mask |= ISP_FRAME_END;
dev->irq_ends = 0;
/* XXX: Is the 1000us too long?
@@ -2097,7 +2621,7 @@
struct rkisp_isp_subdev *isp_sd = sd_to_isp_sd(sd);
struct rkisp_device *dev = sd_to_isp_dev(sd);
struct v4l2_rect *crop;
- u32 max_w, max_h;
+ u32 max_w, max_h, max_size;
if (!sel)
goto err;
@@ -2118,19 +2642,42 @@
crop->left = 0;
crop->top = 0;
if (sel->pad == RKISP_ISP_PAD_SINK) {
- if (dev->isp_ver == ISP_V12) {
+ switch (dev->isp_ver) {
+ case ISP_V12:
max_w = CIF_ISP_INPUT_W_MAX_V12;
max_h = CIF_ISP_INPUT_H_MAX_V12;
- } else if (dev->isp_ver == ISP_V13) {
+ break;
+ case ISP_V13:
max_w = CIF_ISP_INPUT_W_MAX_V13;
max_h = CIF_ISP_INPUT_H_MAX_V13;
- } else if (dev->isp_ver == ISP_V21) {
+ break;
+ case ISP_V21:
max_w = CIF_ISP_INPUT_W_MAX_V21;
max_h = CIF_ISP_INPUT_H_MAX_V21;
- } else {
+ break;
+ case ISP_V30:
+ max_w = dev->hw_dev->unite ?
+ CIF_ISP_INPUT_W_MAX_V30_UNITE : CIF_ISP_INPUT_W_MAX_V30;
+ max_h = dev->hw_dev->unite ?
+ CIF_ISP_INPUT_H_MAX_V30_UNITE : CIF_ISP_INPUT_H_MAX_V30;
+ break;
+ case ISP_V32:
+ max_w = dev->hw_dev->unite ?
+ CIF_ISP_INPUT_W_MAX_V32_UNITE : CIF_ISP_INPUT_W_MAX_V32;
+ max_h = dev->hw_dev->unite ?
+ CIF_ISP_INPUT_H_MAX_V32_UNITE : CIF_ISP_INPUT_H_MAX_V32;
+ break;
+ case ISP_V32_L:
+ max_w = CIF_ISP_INPUT_W_MAX_V32_L;
+ max_h = CIF_ISP_INPUT_H_MAX_V32_L;
+ break;
+ default:
max_w = CIF_ISP_INPUT_W_MAX;
max_h = CIF_ISP_INPUT_H_MAX;
}
+ max_size = max_w * max_h;
+ max_h = max_size / isp_sd->in_frm.width;
+
crop->width = min_t(u32, isp_sd->in_frm.width, max_w);
crop->height = min_t(u32, isp_sd->in_frm.height, max_h);
}
@@ -2146,6 +2693,40 @@
return 0;
err:
return -EINVAL;
+}
+
+static void rkisp_check_stream_dcrop(struct rkisp_device *dev,
+ struct v4l2_rect *crop)
+{
+ struct rkisp_stream *stream;
+ struct v4l2_rect *dcrop;
+ u32 i;
+
+ for (i = 0; i < RKISP_MAX_STREAM; i++) {
+ if (i != RKISP_STREAM_MP && i != RKISP_STREAM_SP &&
+ i != RKISP_STREAM_FBC && i != RKISP_STREAM_BP)
+ continue;
+ stream = &dev->cap_dev.stream[i];
+ dcrop = &stream->dcrop;
+ v4l2_dbg(1, rkisp_debug, &dev->v4l2_dev,
+ "%s id:%d %dx%d(%d %d) from %dx%d(%d %d)\n",
+ __func__, i,
+ dcrop->width, dcrop->height, dcrop->left, dcrop->top,
+ crop->width, crop->height, crop->left, crop->top);
+ /* make sure dcrop window in isp output window */
+ if (dcrop->width > crop->width) {
+ dcrop->width = crop->width;
+ dcrop->left = 0;
+ } else if ((dcrop->left + dcrop->width) > crop->width) {
+ dcrop->left = crop->width - dcrop->width;
+ }
+ if (dcrop->height > crop->height) {
+ dcrop->height = crop->height;
+ dcrop->top = 0;
+ } else if ((dcrop->top + dcrop->height) > crop->height) {
+ dcrop->top = crop->height - dcrop->height;
+ }
+ }
}
static int rkisp_isp_sd_set_selection(struct v4l2_subdev *sd,
@@ -2179,18 +2760,20 @@
if (sel->pad == RKISP_ISP_PAD_SINK) {
isp_sd->in_crop = *crop;
- /* ISP20 don't have out crop */
- if (dev->isp_ver == ISP_V20 || dev->isp_ver == ISP_V21) {
+ /* don't have out crop */
+ if (dev->isp_ver >= ISP_V20) {
isp_sd->out_crop = *crop;
isp_sd->out_crop.left = 0;
isp_sd->out_crop.top = 0;
dev->br_dev.crop = isp_sd->out_crop;
}
} else {
- if (dev->isp_ver == ISP_V20 || dev->isp_ver == ISP_V21)
+ if (dev->isp_ver >= ISP_V20)
*crop = isp_sd->out_crop;
isp_sd->out_crop = *crop;
}
+
+ rkisp_check_stream_dcrop(dev, crop);
return 0;
err:
@@ -2246,53 +2829,301 @@
struct rkisp_stream *stream;
int i;
+ rkisp_stats_first_ddr_config(&dev->stats_vdev);
if (dev->hw_dev->is_mi_update)
return;
- rkisp_stats_first_ddr_config(&dev->stats_vdev);
rkisp_config_dmatx_valid_buf(dev);
force_cfg_update(dev);
hdr_update_dmatx_buf(dev);
- if (dev->br_dev.en && dev->isp_ver == ISP_V20) {
- stream = &dev->cap_dev.stream[RKISP_STREAM_SP];
- rkisp_update_spstream_buf(stream);
- }
if (dev->hw_dev->is_single) {
for (i = 0; i < RKISP_MAX_STREAM; i++) {
stream = &dev->cap_dev.stream[i];
- if (stream->streaming && !stream->next_buf)
- stream->ops->frame_end(stream);
+ if (stream->id == RKISP_STREAM_VIR ||
+ stream->id == RKISP_STREAM_LUMA)
+ continue;
+ if (stream->streaming && !stream->curr_buf)
+ stream->ops->frame_end(stream, FRAME_INIT);
}
}
+ rkisp_stats_next_ddr_config(&dev->stats_vdev);
}
static int rkisp_isp_sd_s_stream(struct v4l2_subdev *sd, int on)
{
struct rkisp_device *isp_dev = sd_to_isp_dev(sd);
+ struct rkisp_hw_dev *hw_dev = isp_dev->hw_dev;
+ int ret;
if (!on) {
- wait_event_timeout(isp_dev->sync_onoff,
- isp_dev->irq_ends_mask == (ISP_FRAME_END | ISP_FRAME_IN) &&
- (!IS_HDR_RDBK(isp_dev->rd_mode) ||
- isp_dev->isp_state & ISP_STOP), msecs_to_jiffies(5));
+ if (IS_HDR_RDBK(isp_dev->rd_mode)) {
+ struct rkisp_stream *s;
+ int i;
+
+ for (i = RKISP_STREAM_RAWRD0; i <= RKISP_STREAM_RAWRD2; i++) {
+ s = &isp_dev->dmarx_dev.stream[i];
+ if (s->stopping)
+ wake_up(&s->done);
+ }
+ }
+ ret = wait_event_timeout(isp_dev->sync_onoff,
+ isp_dev->isp_state & ISP_STOP ||
+ !IS_HDR_RDBK(isp_dev->rd_mode),
+ msecs_to_jiffies(500));
+ if (!ret)
+ v4l2_warn(&isp_dev->v4l2_dev, "%s wait timeout, mode:%d state:0x%x\n",
+ __func__, isp_dev->rd_mode, isp_dev->isp_state);
rkisp_isp_stop(isp_dev);
- atomic_dec(&isp_dev->hw_dev->refcnt);
+ atomic_dec(&hw_dev->refcnt);
rkisp_params_stream_stop(&isp_dev->params_vdev);
+ atomic_set(&isp_dev->isp_sdev.frm_sync_seq, 0);
rkisp_stop_3a_run(isp_dev);
return 0;
}
+ hw_dev->is_runing = true;
rkisp_start_3a_run(isp_dev);
memset(&isp_dev->isp_sdev.dbg, 0, sizeof(isp_dev->isp_sdev.dbg));
- atomic_inc(&isp_dev->hw_dev->refcnt);
- atomic_set(&isp_dev->isp_sdev.frm_sync_seq, 0);
- rkisp_global_update_mi(isp_dev);
+ if (atomic_inc_return(&hw_dev->refcnt) > hw_dev->dev_link_num) {
+ dev_err(isp_dev->dev, "%s fail: input link before hw start\n", __func__);
+ atomic_dec(&hw_dev->refcnt);
+ return -EINVAL;
+ }
+
rkisp_config_cif(isp_dev);
rkisp_isp_start(isp_dev);
+ rkisp_global_update_mi(isp_dev);
+ isp_dev->isp_state = ISP_START | ISP_FRAME_END;
rkisp_rdbk_trigger_event(isp_dev, T_CMD_QUEUE, NULL);
return 0;
+}
+
+static void rkisp_rx_buf_free(struct rkisp_device *dev, struct rkisp_rx_buf *dbufs)
+{
+ const struct vb2_mem_ops *g_ops = dev->hw_dev->mem_ops;
+ struct rkisp_rx_buf_pool *pool;
+ int i = 0;
+
+ if (!dbufs)
+ return;
+
+ for (i = 0; i < RKISP_RX_BUF_POOL_MAX; i++) {
+ pool = &dev->pv_pool[i];
+ if (dbufs == pool->dbufs) {
+ if (pool->mem_priv) {
+ g_ops->unmap_dmabuf(pool->mem_priv);
+ g_ops->detach_dmabuf(pool->mem_priv);
+ dma_buf_put(pool->dbufs->dbuf);
+ pool->mem_priv = NULL;
+ }
+ pool->dbufs = NULL;
+ break;
+ }
+ }
+}
+
+static void rkisp_rx_qbuf_online(struct rkisp_stream *stream,
+ struct rkisp_rx_buf_pool *pool)
+{
+ struct rkisp_device *dev = stream->ispdev;
+ u32 val = pool->buf.buff_addr[RKISP_PLANE_Y];
+
+ rkisp_write(dev, stream->config->mi.y_base_ad_init, val, false);
+ if (dev->hw_dev->unite == ISP_UNITE_TWO) {
+ u32 offs = stream->out_fmt.width / 2 - RKMOUDLE_UNITE_EXTEND_PIXEL;
+
+ if (stream->memory)
+ offs *= DIV_ROUND_UP(stream->out_isp_fmt.bpp[0], 8);
+ else
+ offs = offs * stream->out_isp_fmt.bpp[0] / 8;
+ val += offs;
+ rkisp_next_write(dev, stream->config->mi.y_base_ad_init, val, false);
+ }
+}
+
+static void rkisp_rx_qbuf_rdbk(struct rkisp_stream *stream,
+ struct rkisp_rx_buf_pool *pool)
+{
+ struct rkisp_device *dev = stream->ispdev;
+ unsigned long lock_flags = 0;
+ struct rkisp_buffer *ispbuf = &pool->buf;
+ struct isp2x_csi_trigger trigger = {
+ .frame_timestamp = ispbuf->vb.vb2_buf.timestamp,
+ .sof_timestamp = ispbuf->vb.vb2_buf.timestamp,
+ .frame_id = ispbuf->vb.sequence,
+ .mode = 0,
+ .times = 0,
+ };
+ spin_lock_irqsave(&stream->vbq_lock, lock_flags);
+ if (list_empty(&stream->buf_queue) && !stream->curr_buf) {
+ stream->curr_buf = ispbuf;
+ stream->ops->update_mi(stream);
+ } else {
+ list_add_tail(&ispbuf->queue, &stream->buf_queue);
+ }
+ spin_unlock_irqrestore(&stream->vbq_lock, lock_flags);
+ if (stream->id == RKISP_STREAM_RAWRD2)
+ rkisp_rdbk_trigger_event(dev, T_CMD_QUEUE, &trigger);
+}
+
+static int rkisp_rx_qbuf(struct rkisp_device *dev,
+ struct rkisp_rx_buf *dbufs)
+{
+ struct rkisp_stream *stream;
+ struct rkisp_rx_buf_pool *pool;
+ int i;
+
+ for (i = 0; i < RKISP_RX_BUF_POOL_MAX; i++) {
+ pool = &dev->pv_pool[i];
+ if (dbufs == pool->dbufs)
+ break;
+ }
+
+ if (pool->dbufs == NULL || pool->dbufs != dbufs)
+ return -EINVAL;
+ switch (dbufs->type) {
+ case BUF_SHORT:
+ stream = &dev->dmarx_dev.stream[RKISP_STREAM_RAWRD2];
+ break;
+ case BUF_MIDDLE:
+ stream = &dev->dmarx_dev.stream[RKISP_STREAM_RAWRD0];
+ break;
+ case BUF_LONG:
+ default:
+ stream = &dev->dmarx_dev.stream[RKISP_STREAM_RAWRD1];
+ }
+
+ v4l2_dbg(2, rkisp_debug, &dev->v4l2_dev,
+ "%s rd_mode:%d seq:%d dma:0x%x\n",
+ __func__, dev->rd_mode, dbufs->sequence,
+ pool->buf.buff_addr[RKISP_PLANE_Y]);
+
+ if (!IS_HDR_RDBK(dev->rd_mode)) {
+ rkisp_rx_qbuf_online(stream, pool);
+ } else {
+ pool->buf.vb.vb2_buf.timestamp = dbufs->timestamp;
+ pool->buf.vb.sequence = dbufs->sequence;
+ rkisp_rx_qbuf_rdbk(stream, pool);
+ }
+ return 0;
+}
+
+void rkisp_rx_buf_pool_free(struct rkisp_device *dev)
+{
+ const struct vb2_mem_ops *g_ops = dev->hw_dev->mem_ops;
+ struct rkisp_rx_buf_pool *pool;
+ int i;
+
+ for (i = 0; i < RKISP_RX_BUF_POOL_MAX; i++) {
+ pool = &dev->pv_pool[i];
+ if (!pool->dbufs)
+ break;
+ if (pool->mem_priv) {
+ g_ops->unmap_dmabuf(pool->mem_priv);
+ g_ops->detach_dmabuf(pool->mem_priv);
+ dma_buf_put(pool->dbufs->dbuf);
+ pool->mem_priv = NULL;
+ }
+ pool->dbufs = NULL;
+ }
+}
+
+static int rkisp_rx_buf_pool_init(struct rkisp_device *dev,
+ struct rkisp_rx_buf *dbufs)
+{
+ const struct vb2_mem_ops *g_ops = dev->hw_dev->mem_ops;
+ struct rkisp_stream *stream;
+ struct rkisp_rx_buf_pool *pool;
+ struct sg_table *sg_tbl;
+ dma_addr_t dma;
+ int i, ret;
+ void *mem, *vaddr = NULL;
+
+ for (i = 0; i < RKISP_RX_BUF_POOL_MAX; i++) {
+ pool = &dev->pv_pool[i];
+ if (!pool->dbufs)
+ break;
+ }
+
+ pool->dbufs = dbufs;
+ v4l2_dbg(1, rkisp_debug, &dev->v4l2_dev,
+ "%s type:0x%x first:%d dbufs[%d]:%p", __func__,
+ dbufs->type, dbufs->is_first, i, dbufs);
+
+ if (dbufs->is_resmem) {
+ dma = dbufs->dma;
+ goto end;
+ }
+ mem = g_ops->attach_dmabuf(dev->hw_dev->dev, dbufs->dbuf,
+ dbufs->dbuf->size, DMA_BIDIRECTIONAL);
+ if (IS_ERR(mem)) {
+ ret = PTR_ERR(mem);
+ goto err;
+ }
+ pool->mem_priv = mem;
+ ret = g_ops->map_dmabuf(mem);
+ if (ret)
+ goto err;
+ if (dev->hw_dev->is_dma_sg_ops) {
+ sg_tbl = (struct sg_table *)g_ops->cookie(mem);
+ dma = sg_dma_address(sg_tbl->sgl);
+ } else {
+ dma = *((dma_addr_t *)g_ops->cookie(mem));
+ }
+ get_dma_buf(dbufs->dbuf);
+ vaddr = g_ops->vaddr(mem);
+end:
+ dbufs->is_init = true;
+ pool->buf.other = dbufs;
+ pool->buf.buff_addr[RKISP_PLANE_Y] = dma;
+ pool->buf.vaddr[RKISP_PLANE_Y] = vaddr;
+
+ switch (dbufs->type) {
+ case BUF_SHORT:
+ stream = &dev->dmarx_dev.stream[RKISP_STREAM_RAWRD2];
+ break;
+ case BUF_MIDDLE:
+ stream = &dev->dmarx_dev.stream[RKISP_STREAM_RAWRD0];
+ break;
+ case BUF_LONG:
+ default:
+ stream = &dev->dmarx_dev.stream[RKISP_STREAM_RAWRD1];
+ }
+ if (dbufs->is_first) {
+ stream->memory = 0;
+ if (dbufs->is_uncompact)
+ stream->memory = SW_CSI_RAW_WR_SIMG_MODE;
+ rkisp_dmarx_set_fmt(stream, stream->out_fmt);
+ stream->ops->config_mi(stream);
+ dbufs->is_first = false;
+ }
+ v4l2_dbg(1, rkisp_debug, &dev->v4l2_dev,
+ "%s dma:0x%x vaddr:%p", __func__, (u32)dma, vaddr);
+ return 0;
+err:
+ rkisp_rx_buf_pool_free(dev);
+ return ret;
+}
+
+static int rkisp_sd_s_rx_buffer(struct v4l2_subdev *sd,
+ void *buf, unsigned int *size)
+{
+ struct rkisp_device *dev = sd_to_isp_dev(sd);
+ struct rkisp_rx_buf *dbufs;
+ int ret = 0;
+
+ if (!buf)
+ return -EINVAL;
+
+ dbufs = buf;
+ if (!dbufs->is_init)
+ ret = rkisp_rx_buf_pool_init(dev, dbufs);
+ if (!ret)
+ ret = rkisp_rx_qbuf(dev, dbufs);
+
+ return ret;
}
static int rkisp_isp_sd_s_power(struct v4l2_subdev *sd, int on)
@@ -2300,14 +3131,11 @@
struct rkisp_device *isp_dev = sd_to_isp_dev(sd);
int ret;
- if (isp_dev->hw_dev->is_thunderboot)
- return 0;
-
v4l2_dbg(1, rkisp_debug, &isp_dev->v4l2_dev,
"%s on:%d\n", __func__, on);
if (on) {
- if (isp_dev->isp_ver == ISP_V20 || isp_dev->isp_ver == ISP_V21)
+ if (isp_dev->isp_ver >= ISP_V20)
kfifo_reset(&isp_dev->rdbk_kfifo);
ret = pm_runtime_get_sync(isp_dev->dev);
} else {
@@ -2337,6 +3165,15 @@
dev = sd_to_isp_dev(sd);
if (!dev)
return -ENODEV;
+
+ if (dev->hw_dev->is_runing &&
+ (!dev->isp_inp ||
+ !(dev->isp_inp & ~rawrd) ||
+ !strcmp(remote->entity->name, CSI_DEV_NAME) ||
+ strstr(remote->entity->name, "rkcif"))) {
+ v4l2_err(sd, "no support link for isp hw working\n");
+ return -EINVAL;
+ }
if (!strcmp(remote->entity->name, DMA_VDEV_NAME)) {
stream = &dev->dmarx_dev.stream[RKISP_STREAM_DMARX];
@@ -2386,6 +3223,18 @@
} else {
dev->isp_inp &= ~INP_RAWRD2;
}
+ } else if (!strcmp(remote->entity->name, FBC_VDEV_NAME)) {
+ stream = &dev->cap_dev.stream[RKISP_STREAM_FBC];
+ } else if (!strcmp(remote->entity->name, BP_VDEV_NAME)) {
+ stream = &dev->cap_dev.stream[RKISP_STREAM_BP];
+ } else if (!strcmp(remote->entity->name, MPDS_VDEV_NAME)) {
+ stream = &dev->cap_dev.stream[RKISP_STREAM_MPDS];
+ } else if (!strcmp(remote->entity->name, BPDS_VDEV_NAME)) {
+ stream = &dev->cap_dev.stream[RKISP_STREAM_BPDS];
+ } else if (!strcmp(remote->entity->name, LUMA_VDEV_NAME)) {
+ stream = &dev->cap_dev.stream[RKISP_STREAM_LUMA];
+ } else if (!strcmp(remote->entity->name, VIR_VDEV_NAME)) {
+ stream = &dev->cap_dev.stream[RKISP_STREAM_VIR];
} else if (!strcmp(remote->entity->name, SP_VDEV_NAME)) {
stream = &dev->cap_dev.stream[RKISP_STREAM_SP];
} else if (!strcmp(remote->entity->name, MP_VDEV_NAME)) {
@@ -2430,11 +3279,31 @@
if (stream)
stream->linked = flags & MEDIA_LNK_FL_ENABLED;
- if (dev->isp_inp & rawrd)
+ if (dev->isp_inp & rawrd) {
dev->dmarx_dev.trigger = T_MANUAL;
- else
+ dev->is_rdbk_auto = false;
+ } else {
dev->dmarx_dev.trigger = T_AUTO;
+ }
+ if (dev->isp_inp & INP_CIF) {
+ struct v4l2_subdev *remote = get_remote_sensor(sd);
+ struct rkisp_vicap_mode mode;
+ memset(&mode, 0, sizeof(mode));
+ mode.name = dev->name;
+ mode.rdbk_mode = !!(dev->isp_inp & rawrd);
+ /* read back mode only */
+ if (dev->isp_ver < ISP_V30 || !dev->hw_dev->is_single)
+ mode.rdbk_mode = RKISP_VICAP_RDBK_AIQ;
+ v4l2_subdev_call(remote, core, ioctl,
+ RKISP_VICAP_CMD_MODE, &mode);
+ dev->vicap_in = mode.input;
+ }
+
+ if (!dev->isp_inp)
+ dev->is_hw_link = false;
+ else
+ dev->is_hw_link = true;
v4l2_dbg(1, rkisp_debug, &dev->v4l2_dev,
"isp input:0x%x\n", dev->isp_inp);
return 0;
@@ -2482,7 +3351,6 @@
atomic_inc_return(&isp->frm_sync_seq) - 1,
};
- event.timestamp = ns_to_timespec(ktime_get_ns());
v4l2_event_queue(isp->sd.devnode, &event);
}
@@ -2499,24 +3367,148 @@
return v4l2_event_subscribe(fh, sub, ISP_V4L2_EVENT_ELEMS, NULL);
}
+static int rkisp_get_info(struct rkisp_device *dev, struct rkisp_isp_info *info)
+{
+ struct v4l2_rect *in_crop = &dev->isp_sdev.in_crop;
+ u32 rd_mode, mode = 0, bit = 0;
+ int ret;
+
+ if (!(dev->isp_state & ISP_START)) {
+ struct rkmodule_hdr_cfg cfg;
+
+ ret = rkisp_csi_get_hdr_cfg(dev, &cfg);
+ if (ret)
+ return ret;
+ rd_mode = cfg.hdr_mode;
+ if (rd_mode == HDR_COMPR)
+ bit = cfg.compr.bit > 20 ? 20 : cfg.compr.bit;
+ } else {
+ rd_mode = dev->rd_mode;
+ bit = dev->hdr.compr_bit;
+ }
+
+ switch (rd_mode) {
+ case HDR_RDBK_FRAME2:
+ case HDR_FRAMEX2_DDR:
+ case HDR_LINEX2_DDR:
+ mode = RKISP_ISP_HDR2;
+ break;
+ case HDR_RDBK_FRAME3:
+ case HDR_FRAMEX3_DDR:
+ case HDR_LINEX3_DDR:
+ mode = RKISP_ISP_HDR3;
+ break;
+ default:
+ mode = RKISP_ISP_NORMAL;
+ }
+ if (bit)
+ mode = RKISP_ISP_COMPR;
+ info->compr_bit = bit;
+
+ if (dev->is_bigmode)
+ mode |= RKISP_ISP_BIGMODE;
+ info->mode = mode;
+ if (dev->hw_dev->unite)
+ info->act_width = in_crop->width / 2 + RKMOUDLE_UNITE_EXTEND_PIXEL;
+ else
+ info->act_width = in_crop->width;
+ info->act_height = in_crop->height;
+ return 0;
+}
+
+static int rkisp_set_work_mode_by_vicap(struct rkisp_device *isp_dev,
+ struct rkisp_vicap_mode *vicap_mode)
+{
+ struct rkisp_hw_dev *hw = isp_dev->hw_dev;
+ int rd_mode = isp_dev->rd_mode;
+
+ isp_dev->is_suspend_one_frame = false;
+ if (vicap_mode->rdbk_mode == RKISP_VICAP_ONLINE) {
+ if (!hw->is_single)
+ return -EINVAL;
+ /* switch to online mode for single sensor */
+ switch (rd_mode) {
+ case HDR_RDBK_FRAME3:
+ isp_dev->rd_mode = HDR_LINEX3_DDR;
+ break;
+ case HDR_RDBK_FRAME2:
+ isp_dev->rd_mode = HDR_LINEX2_DDR;
+ break;
+ default:
+ isp_dev->rd_mode = HDR_NORMAL;
+ }
+ } else if (vicap_mode->rdbk_mode == RKISP_VICAP_RDBK_AUTO ||
+ vicap_mode->rdbk_mode == RKISP_VICAP_RDBK_AUTO_ONE_FRAME) {
+ /* switch to readback mode */
+ switch (rd_mode) {
+ case HDR_LINEX3_DDR:
+ isp_dev->rd_mode = HDR_RDBK_FRAME3;
+ break;
+ case HDR_LINEX2_DDR:
+ isp_dev->rd_mode = HDR_RDBK_FRAME2;
+ break;
+ default:
+ isp_dev->rd_mode = HDR_RDBK_FRAME1;
+ }
+ if (vicap_mode->rdbk_mode == RKISP_VICAP_RDBK_AUTO_ONE_FRAME)
+ isp_dev->is_suspend_one_frame = true;
+ } else {
+ return -EINVAL;
+ }
+ isp_dev->hdr.op_mode = isp_dev->rd_mode;
+ if (rd_mode != isp_dev->rd_mode && hw->cur_dev_id == isp_dev->dev_id) {
+ rkisp_unite_write(isp_dev, CSI2RX_CTRL0,
+ SW_IBUF_OP_MODE(isp_dev->rd_mode), true);
+ if (IS_HDR_RDBK(isp_dev->rd_mode))
+ rkisp_unite_set_bits(isp_dev, CTRL_SWS_CFG, 0,
+ SW_MPIP_DROP_FRM_DIS, true);
+ else
+ rkisp_unite_clear_bits(isp_dev, CTRL_SWS_CFG,
+ SW_MPIP_DROP_FRM_DIS, true);
+ }
+ return 0;
+}
+
static long rkisp_ioctl(struct v4l2_subdev *sd, unsigned int cmd, void *arg)
{
struct rkisp_device *isp_dev = sd_to_isp_dev(sd);
struct rkisp_thunderboot_resmem *resmem;
+ struct rkisp32_thunderboot_resmem_head *tb_head_v32;
struct rkisp_thunderboot_resmem_head *head;
struct rkisp_thunderboot_shmem *shmem;
struct isp2x_buf_idxfd *idxfd;
+ struct rkisp_rx_buf *dbufs;
void *resmem_va;
long ret = 0;
- if (!arg && cmd != RKISP_CMD_FREE_SHARED_BUF)
+ if (!arg &&
+ (cmd != RKISP_CMD_FREE_SHARED_BUF &&
+ cmd != RKISP_CMD_MULTI_DEV_FORCE_ENUM))
return -EINVAL;
switch (cmd) {
case RKISP_CMD_TRIGGER_READ_BACK:
rkisp_rdbk_trigger_event(isp_dev, T_CMD_QUEUE, arg);
break;
+ case RKISP_CMD_GET_ISP_INFO:
+ rkisp_get_info(isp_dev, arg);
+ break;
+ case RKISP_CMD_GET_TB_HEAD_V32:
+ if (isp_dev->tb_head.complete != RKISP_TB_OK) {
+ ret = -EINVAL;
+ break;
+ }
+ tb_head_v32 = arg;
+ memcpy(tb_head_v32, &isp_dev->tb_head,
+ sizeof(struct rkisp_thunderboot_resmem_head));
+ memcpy(&tb_head_v32->cfg, isp_dev->params_vdev.isp32_params,
+ sizeof(struct isp32_isp_params_cfg));
+ break;
case RKISP_CMD_GET_SHARED_BUF:
+ if (!IS_ENABLED(CONFIG_VIDEO_ROCKCHIP_THUNDER_BOOT_ISP)) {
+ ret = -ENOIOCTLCMD;
+ break;
+ }
resmem = (struct rkisp_thunderboot_resmem *)arg;
resmem->resmem_padr = isp_dev->resmem_pa;
resmem->resmem_size = isp_dev->resmem_size;
@@ -2546,6 +3538,10 @@
}
break;
case RKISP_CMD_FREE_SHARED_BUF:
+ if (!IS_ENABLED(CONFIG_VIDEO_ROCKCHIP_THUNDER_BOOT_ISP)) {
+ ret = -ENOIOCTLCMD;
+ break;
+ }
if (isp_dev->resmem_pa && isp_dev->resmem_size) {
dma_unmap_single(isp_dev->dev, isp_dev->resmem_pa,
sizeof(struct rkisp_thunderboot_resmem_head),
@@ -2564,15 +3560,48 @@
break;
case RKISP_CMD_SET_LDCHBUF_SIZE:
case RKISP_CMD_SET_MESHBUF_SIZE:
- rkisp_params_set_meshbuf_size(&isp_dev->params_vdev, arg);
+ ret = rkisp_params_set_meshbuf_size(&isp_dev->params_vdev, arg);
break;
case RKISP_CMD_GET_SHM_BUFFD:
+ if (!IS_ENABLED(CONFIG_VIDEO_ROCKCHIP_THUNDER_BOOT_ISP)) {
+ ret = -ENOIOCTLCMD;
+ break;
+ }
shmem = (struct rkisp_thunderboot_shmem *)arg;
ret = rkisp_tb_shm_ioctl(shmem);
break;
case RKISP_CMD_GET_FBCBUF_FD:
idxfd = (struct isp2x_buf_idxfd *)arg;
ret = rkisp_bridge_get_fbcbuf_fd(isp_dev, idxfd);
+ break;
+ case RKISP_CMD_INFO2DDR:
+ ret = rkisp_params_info2ddr_cfg(&isp_dev->params_vdev, arg);
+ break;
+ case RKISP_CMD_MESHBUF_FREE:
+ rkisp_params_meshbuf_free(&isp_dev->params_vdev, *(u64 *)arg);
+ break;
+ case RKISP_VICAP_CMD_RX_BUFFER_FREE:
+ dbufs = (struct rkisp_rx_buf *)arg;
+ rkisp_rx_buf_free(isp_dev, dbufs);
+ break;
+ case RKISP_CMD_MULTI_DEV_FORCE_ENUM:
+ if (isp_dev->hw_dev->is_runing) {
+ ret = -EINVAL;
+ } else {
+ isp_dev->hw_dev->is_single = true;
+ isp_dev->hw_dev->is_multi_overflow = false;
+ rkisp_hw_enum_isp_size(isp_dev->hw_dev);
+ }
+ break;
+ case RKISP_VICAP_CMD_SET_STREAM:
+ ret = rkisp_reset_handle(isp_dev);
+ if (!ret) {
+ if (isp_dev->hw_dev->monitor.state & ISP_CIF_RESET)
+ isp_dev->hw_dev->monitor.state &= ~ISP_CIF_RESET;
+ }
+ break;
+ case RKISP_VICAP_CMD_MODE:
+ ret = rkisp_set_work_mode_by_vicap(isp_dev, arg);
break;
default:
ret = -ENOIOCTLCMD;
@@ -2594,7 +3623,9 @@
struct rkisp_meshbuf_size meshsize;
struct rkisp_thunderboot_shmem shmem;
struct isp2x_buf_idxfd idxfd;
+ struct rkisp_info2ddr info2ddr;
long ret = 0;
+ u64 module_id;
if (!up && cmd != RKISP_CMD_FREE_SHARED_BUF)
return -EINVAL;
@@ -2606,11 +3637,19 @@
ret = rkisp_ioctl(sd, cmd, &trigger);
break;
case RKISP_CMD_GET_SHARED_BUF:
+ if (!IS_ENABLED(CONFIG_VIDEO_ROCKCHIP_THUNDER_BOOT_ISP)) {
+ ret = -ENOIOCTLCMD;
+ break;
+ }
ret = rkisp_ioctl(sd, cmd, &resmem);
if (!ret && copy_to_user(up, &resmem, sizeof(resmem)))
ret = -EFAULT;
break;
case RKISP_CMD_FREE_SHARED_BUF:
+ if (!IS_ENABLED(CONFIG_VIDEO_ROCKCHIP_THUNDER_BOOT_ISP)) {
+ ret = -ENOIOCTLCMD;
+ break;
+ }
ret = rkisp_ioctl(sd, cmd, NULL);
break;
case RKISP_CMD_GET_LDCHBUF_INFO:
@@ -2624,7 +3663,7 @@
ret = rkisp_ioctl(sd, cmd, &ldchsize);
break;
case RKISP_CMD_GET_MESHBUF_INFO:
- if (copy_from_user(&meshsize, up, sizeof(meshsize)))
+ if (copy_from_user(&meshbuf, up, sizeof(meshbuf)))
return -EFAULT;
ret = rkisp_ioctl(sd, cmd, &meshbuf);
if (!ret && copy_to_user(up, &meshbuf, sizeof(meshbuf)))
@@ -2636,6 +3675,10 @@
ret = rkisp_ioctl(sd, cmd, &meshsize);
break;
case RKISP_CMD_GET_SHM_BUFFD:
+ if (!IS_ENABLED(CONFIG_VIDEO_ROCKCHIP_THUNDER_BOOT_ISP)) {
+ ret = -ENOIOCTLCMD;
+ break;
+ }
if (copy_from_user(&shmem, up, sizeof(shmem)))
return -EFAULT;
ret = rkisp_ioctl(sd, cmd, &shmem);
@@ -2646,6 +3689,24 @@
ret = rkisp_ioctl(sd, cmd, &idxfd);
if (!ret && copy_to_user(up, &idxfd, sizeof(idxfd)))
ret = -EFAULT;
+ break;
+ case RKISP_CMD_INFO2DDR:
+ if (copy_from_user(&info2ddr, up, sizeof(info2ddr)))
+ return -EFAULT;
+ ret = rkisp_ioctl(sd, cmd, &info2ddr);
+ if (!ret && copy_to_user(up, &info2ddr, sizeof(info2ddr)))
+ ret = -EFAULT;
+ break;
+ case RKISP_CMD_MESHBUF_FREE:
+ if (copy_from_user(&module_id, up, sizeof(module_id)))
+ return -EFAULT;
+ ret = rkisp_ioctl(sd, cmd, &module_id);
+ break;
+ case RKISP_CMD_MULTI_DEV_FORCE_ENUM:
+ ret = rkisp_ioctl(sd, cmd, NULL);
+ break;
+ case RKISP_VICAP_CMD_SET_STREAM:
+ ret = rkisp_ioctl(sd, cmd, NULL);
break;
default:
ret = -ENOIOCTLCMD;
@@ -2673,6 +3734,7 @@
static const struct v4l2_subdev_video_ops rkisp_isp_sd_video_ops = {
.s_stream = rkisp_isp_sd_s_stream,
+ .s_rx_buffer = rkisp_sd_s_rx_buffer,
};
static const struct v4l2_subdev_core_ops rkisp_isp_core_ops = {
@@ -2699,7 +3761,7 @@
struct ispsd_in_fmt *in_fmt = &isp_sd->in_fmt;
struct ispsd_out_fmt *out_fmt = &isp_sd->out_fmt;
- *in_fmt = rkisp_isp_input_formats[0];
+ *in_fmt = rkisp_isp_input_formats[8];
in_frm->width = RKISP_DEFAULT_WIDTH;
in_frm->height = RKISP_DEFAULT_HEIGHT;
in_frm->code = in_fmt->mbus_code;
@@ -2723,6 +3785,8 @@
struct v4l2_subdev *sd = &isp_sdev->sd;
int ret;
+ mutex_init(&isp_dev->buf_lock);
+ spin_lock_init(&isp_dev->cmsk_lock);
spin_lock_init(&isp_dev->rdbk_lock);
ret = kfifo_alloc(&isp_dev->rdbk_kfifo,
16 * sizeof(struct isp2x_csi_trigger), GFP_KERNEL);
@@ -2760,8 +3824,10 @@
rkisp_isp_sd_init_default_fmt(isp_sdev);
isp_dev->hdr.sensor = NULL;
isp_dev->isp_state = ISP_STOP;
-
+ atomic_set(&isp_sdev->frm_sync_seq, 0);
rkisp_monitor_init(isp_dev);
+ INIT_WORK(&isp_dev->rdbk_work, rkisp_rdbk_work);
+ init_completion(&isp_dev->pm_cmpl);
return 0;
err_cleanup_media_entity:
media_entity_cleanup(&sd->entity);
@@ -2801,56 +3867,120 @@
(cond) ? 0 : -ETIMEDOUT; \
})
+void rkisp_save_tb_info(struct rkisp_device *isp_dev)
+{
+ struct rkisp_isp_params_vdev *params_vdev = &isp_dev->params_vdev;
+ void *resmem_va = phys_to_virt(isp_dev->resmem_pa);
+ struct rkisp_thunderboot_resmem_head *head = resmem_va;
+ int size = 0, offset = 0;
+ void *param = NULL;
+
+ switch (isp_dev->isp_ver) {
+ case ISP_V32:
+ size = sizeof(struct rkisp32_thunderboot_resmem_head);
+ offset = size * isp_dev->dev_id;
+ break;
+ default:
+ break;
+ }
+
+ if (size && size < isp_dev->resmem_size) {
+ dma_sync_single_for_cpu(isp_dev->dev, isp_dev->resmem_addr + offset,
+ size, DMA_FROM_DEVICE);
+ if (isp_dev->is_rtt_first)
+ params_vdev->is_first_cfg = true;
+ if (isp_dev->isp_ver == ISP_V32) {
+ struct rkisp32_thunderboot_resmem_head *tmp = resmem_va + offset;
+
+ param = &tmp->cfg;
+ head = &tmp->head;
+ v4l2_info(&isp_dev->v4l2_dev,
+ "tb param module en:0x%llx upd:0x%llx cfg upd:0x%llx\n",
+ tmp->cfg.module_en_update,
+ tmp->cfg.module_ens,
+ tmp->cfg.module_cfg_update);
+ }
+ if (param && (isp_dev->isp_state & ISP_STOP))
+ params_vdev->ops->save_first_param(params_vdev, param);
+ } else if (size > isp_dev->resmem_size) {
+ v4l2_err(&isp_dev->v4l2_dev,
+ "resmem size:%zu no enough for head:%d\n",
+ isp_dev->resmem_size, size);
+ head->complete = RKISP_TB_NG;
+ }
+ memcpy(&isp_dev->tb_head, head, sizeof(*head));
+}
+
#ifdef CONFIG_VIDEO_ROCKCHIP_THUNDER_BOOT_ISP
void rkisp_chk_tb_over(struct rkisp_device *isp_dev)
{
+ struct rkisp_isp_params_vdev *params_vdev = &isp_dev->params_vdev;
+ struct rkisp_hw_dev *hw = isp_dev->hw_dev;
struct rkisp_thunderboot_resmem_head *head;
enum rkisp_tb_state tb_state;
void *resmem_va;
- if (!isp_dev->hw_dev->is_thunderboot)
+ if (!isp_dev->is_thunderboot)
return;
- if (!atomic_read(&isp_dev->hw_dev->tb_ref)) {
- rkisp_tb_set_state(RKISP_TB_NG);
- rkisp_tb_unprotect_clk();
- rkisp_register_irq(isp_dev->hw_dev);
- isp_dev->hw_dev->is_thunderboot = false;
- return;
- }
+ if (isp_dev->isp_ver == ISP_V32 && params_vdev->is_first_cfg)
+ goto end;
resmem_va = phys_to_virt(isp_dev->resmem_pa);
head = (struct rkisp_thunderboot_resmem_head *)resmem_va;
- if (isp_dev->is_thunderboot) {
- shm_head_poll_timeout(isp_dev, !!head->enable, 2000, 200 * USEC_PER_MSEC);
- shm_head_poll_timeout(isp_dev, !!head->complete, 5000, 600 * USEC_PER_MSEC);
- if (head->complete != RKISP_TB_OK)
- v4l2_info(&isp_dev->v4l2_dev,
- "wait thunderboot over timeout\n");
+ dma_sync_single_for_cpu(isp_dev->dev, isp_dev->resmem_addr,
+ sizeof(struct rkisp_thunderboot_resmem_head),
+ DMA_FROM_DEVICE);
- v4l2_info(&isp_dev->v4l2_dev,
- "thunderboot info: %d, %d, %d, %d, %d, %d, 0x%x\n",
- head->enable,
- head->complete,
- head->frm_total,
- head->hdr_mode,
- head->width,
- head->height,
- head->bus_fmt);
+ shm_head_poll_timeout(isp_dev, !!head->complete, 5000, 400 * USEC_PER_MSEC);
+ if (head->complete != RKISP_TB_OK) {
+ v4l2_err(&isp_dev->v4l2_dev, "wait thunderboot over timeout\n");
+ } else {
+ int i, timeout = 50;
- tb_state = RKISP_TB_OK;
- if (head->complete != RKISP_TB_OK) {
- head->frm_total = 0;
- tb_state = RKISP_TB_NG;
+ /* wait for all isp dev to register */
+ if (head->camera_num > 1) {
+ while (timeout--) {
+ if (hw->dev_num >= head->camera_num &&
+ hw->isp[hw->dev_num - 1]->is_probe_end)
+ break;
+ usleep_range(200, 210);
+ }
+ if (head->camera_num > hw->dev_num) {
+ v4l2_err(&isp_dev->v4l2_dev,
+ "thunderboot invalid camera num:%d, dev num:%d\n",
+ head->camera_num, hw->dev_num);
+ goto end;
+ }
}
+ for (i = 0; i < head->camera_num; i++)
+ rkisp_save_tb_info(hw->isp[i]);
+ }
+end:
+ head = &isp_dev->tb_head;
+ v4l2_info(&isp_dev->v4l2_dev,
+ "tb info en:%d comp:%d cnt:%d w:%d h:%d cam:%d idx:%d\n",
+ head->enable,
+ head->complete,
+ head->frm_total,
+ head->width,
+ head->height,
+ head->camera_num,
+ head->camera_index);
+
+ tb_state = RKISP_TB_OK;
+ if (head->complete != RKISP_TB_OK) {
+ head->frm_total = 0;
+ tb_state = RKISP_TB_NG;
+ }
+
+ if (hw->is_thunderboot) {
+ rkisp_register_irq(hw);
rkisp_tb_set_state(tb_state);
rkisp_tb_unprotect_clk();
- rkisp_register_irq(isp_dev->hw_dev);
- pm_runtime_put(isp_dev->hw_dev->dev);
- isp_dev->hw_dev->is_thunderboot = false;
- isp_dev->is_thunderboot = false;
- atomic_dec(&isp_dev->hw_dev->tb_ref);
+ hw->is_thunderboot = false;
}
+ isp_dev->is_thunderboot = false;
}
#endif
@@ -2958,7 +4088,9 @@
unsigned int isp3a_mis,
struct rkisp_device *dev)
{
- void __iomem *base = dev->base_addr;
+ struct rkisp_hw_dev *hw = dev->hw_dev;
+ void __iomem *base = hw->unite != ISP_UNITE_TWO ?
+ hw->base_addr : hw->base_next_addr;
unsigned int isp_mis_tmp = 0;
unsigned int isp_err = 0;
u32 si3a_isr_mask = ISP2X_SIAWB_DONE | ISP2X_SIAF_FIN |
@@ -2968,7 +4100,7 @@
ISP2X_3A_RAWHIST_BIG | ISP2X_3A_RAWHIST_CH0 |
ISP2X_3A_RAWHIST_CH1 | ISP2X_3A_RAWHIST_CH2 |
ISP2X_3A_RAWAF_SUM | ISP2X_3A_RAWAF_LUM |
- ISP2X_3A_RAWAF | ISP2X_3A_RAWAWB;
+ ISP2X_3A_RAWAWB;
bool sof_event_later = false;
/*
@@ -2978,40 +4110,51 @@
if (isp3a_mis & ISP2X_3A_RAWAE_BIG && dev->params_vdev.rdbk_times > 0)
writel(BIT(31), base + RAWAE_BIG1_BASE + RAWAE_BIG_CTRL);
+ if (hw->unite == ISP_UNITE_TWO) {
+ u32 val = rkisp_read(dev, ISP3X_ISP_RIS, true);
+
+ if (val) {
+ rkisp_write(dev, ISP3X_ISP_ICR, val, true);
+ v4l2_dbg(3, rkisp_debug, &dev->v4l2_dev,
+ "left isp isr:0x%x\n", val);
+ if (isp_mis & CIF_ISP_FRAME && !(val & CIF_ISP_FRAME)) {
+ /* wait isp0 frame end */
+ int timeout = read_poll_timeout_atomic(rkisp_read,
+ val, val & CIF_ISP_FRAME, 20, 20 * 50, true, dev, ISP3X_ISP_RIS, true);
+
+ if (val)
+ rkisp_write(dev, ISP3X_ISP_ICR, val, true);
+ if (timeout)
+ dev_err(dev->dev, "wait isp end timeout\n");
+ }
+ }
+ }
v4l2_dbg(3, rkisp_debug, &dev->v4l2_dev,
"isp isr:0x%x, 0x%x\n", isp_mis, isp3a_mis);
dev->isp_isr_cnt++;
/* start edge of v_sync */
if (isp_mis & CIF_ISP_V_START) {
- if (dev->isp_state & ISP_FRAME_END) {
- u64 tmp = dev->isp_sdev.dbg.interval +
- dev->isp_sdev.dbg.timestamp;
-
- dev->isp_sdev.dbg.timestamp = ktime_get_ns();
- /* v-blank: frame_end - frame_start */
- dev->isp_sdev.dbg.delay = dev->isp_sdev.dbg.timestamp - tmp;
- }
- rkisp_set_state(&dev->isp_state, ISP_FRAME_VS);
if (dev->hw_dev->monitor.is_en) {
rkisp_set_state(&dev->hw_dev->monitor.state, ISP_FRAME_VS);
if (!completion_done(&dev->hw_dev->monitor.cmpl))
complete(&dev->hw_dev->monitor.cmpl);
}
- /* last vsync to config next buf */
- if (!dev->filt_state[RDBK_F_VS])
- rkisp_bridge_update_mi(dev, isp_mis);
- else
- dev->filt_state[RDBK_F_VS]--;
+
if (IS_HDR_RDBK(dev->hdr.op_mode)) {
- /* read 3d lut at isp readback */
- if (!dev->hw_dev->is_single)
- rkisp_write(dev, ISP_3DLUT_UPDATE, 0, true);
+ /* disabled frame end to read 3dlut for multi sensor
+ * 3dlut will update at isp readback
+ */
+ if (!dev->hw_dev->is_single) {
+ writel(0, hw->base_addr + ISP_3DLUT_UPDATE);
+ if (hw->unite == ISP_UNITE_TWO)
+ writel(0, hw->base_next_addr + ISP_3DLUT_UPDATE);
+ }
rkisp_stats_rdbk_enable(&dev->stats_vdev, true);
goto vs_skip;
}
if (dev->cap_dev.stream[RKISP_STREAM_SP].interlaced) {
/* 0 = ODD 1 = EVEN */
- if (dev->active_sensor->mbus.type == V4L2_MBUS_CSI2) {
+ if (dev->active_sensor->mbus.type == V4L2_MBUS_CSI2_DPHY) {
void __iomem *addr = NULL;
if (dev->isp_ver == ISP_V10 ||
@@ -3033,8 +4176,9 @@
if (isp_mis & CIF_ISP_FRAME)
sof_event_later = true;
if (dev->vs_irq < 0 && !sof_event_later) {
- dev->isp_sdev.frm_timestamp = ktime_get_ns();
+ dev->isp_sdev.frm_timestamp = rkisp_time_get_ns(dev);
rkisp_isp_queue_event_sof(&dev->isp_sdev);
+ rkisp_stream_frame_start(dev, isp_mis);
}
vs_skip:
writel(CIF_ISP_V_START, base + CIF_ISP_ICR);
@@ -3078,6 +4222,16 @@
}
}
+ if (isp3a_mis & ISP2X_3A_RAWAF) {
+ writel(ISP3X_3A_RAWAF, base + ISP3X_ISP_3A_ICR);
+ /* 3a irq will with lsc_lut_err irq if isp version below isp32 */
+ if (isp_mis & ISP2X_LSC_LUT_ERR)
+ isp_mis &= ~ISP2X_LSC_LUT_ERR;
+ if (dev->rawaf_irq_cnt == 0)
+ rkisp_stream_buf_done_early(dev);
+ dev->rawaf_irq_cnt++;
+ }
+
if (isp_mis & ISP2X_LSC_LUT_ERR) {
writel(ISP2X_LSC_LUT_ERR, base + CIF_ISP_ICR);
@@ -3089,21 +4243,22 @@
/* sampled input frame is complete */
if (isp_mis & CIF_ISP_FRAME_IN) {
+ dev->isp_sdev.dbg.interval =
+ rkisp_time_get_ns(dev) - dev->isp_sdev.dbg.timestamp;
rkisp_set_state(&dev->isp_state, ISP_FRAME_IN);
writel(CIF_ISP_FRAME_IN, base + CIF_ISP_ICR);
isp_mis_tmp = readl(base + CIF_ISP_MIS);
if (isp_mis_tmp & CIF_ISP_FRAME_IN)
v4l2_err(&dev->v4l2_dev, "isp icr frame_in err: 0x%x\n",
isp_mis_tmp);
-
- dev->isp_err_cnt = 0;
- dev->isp_state &= ~ISP_ERROR;
}
/* frame was completely put out */
if (isp_mis & CIF_ISP_FRAME) {
- dev->isp_sdev.dbg.interval =
- ktime_get_ns() - dev->isp_sdev.dbg.timestamp;
+ dev->rawaf_irq_cnt = 0;
+ if (!dev->is_pre_on || !IS_HDR_RDBK(dev->rd_mode))
+ dev->isp_sdev.dbg.interval =
+ rkisp_time_get_ns(dev) - dev->isp_sdev.dbg.timestamp;
/* Clear Frame In (ISP) */
rkisp_set_state(&dev->isp_state, ISP_FRAME_END);
writel(CIF_ISP_FRAME, base + CIF_ISP_ICR);
@@ -3113,6 +4268,25 @@
"isp icr frame end err: 0x%x\n", isp_mis_tmp);
rkisp_dmarx_get_frame(dev, &dev->isp_sdev.dbg.id, NULL, NULL, true);
rkisp_isp_read_add_fifo_data(dev);
+
+ dev->isp_err_cnt = 0;
+ dev->isp_state &= ~ISP_ERROR;
+ }
+
+ if (isp_mis & CIF_ISP_V_START) {
+ if (dev->isp_state & ISP_FRAME_END) {
+ u64 tmp = dev->isp_sdev.dbg.interval +
+ dev->isp_sdev.dbg.timestamp;
+
+ dev->isp_sdev.dbg.timestamp = rkisp_time_get_ns(dev);
+ /* v-blank: frame(N)start - frame(N-1)end */
+ dev->isp_sdev.dbg.delay = dev->isp_sdev.dbg.timestamp - tmp;
+ }
+ rkisp_set_state(&dev->isp_state, ISP_FRAME_VS);
+ if (dev->procfs.is_fs_wait) {
+ dev->procfs.is_fs_wait = false;
+ wake_up(&dev->procfs.fs_wait);
+ }
}
if ((isp_mis & (CIF_ISP_FRAME | si3a_isr_mask)) ||
@@ -3129,6 +4303,21 @@
if ((isp_mis & CIF_ISP_FRAME) && dev->stats_vdev.rdbk_mode)
rkisp_stats_rdbk_enable(&dev->stats_vdev, false);
+
+ if (!IS_HDR_RDBK(dev->hdr.op_mode))
+ rkisp_config_cmsk(dev);
+ }
+
+ if (isp_mis & CIF_ISP_FRAME) {
+ if (dev->hw_dev->isp_ver == ISP_V32) {
+ struct rkisp_stream *s = &dev->cap_dev.stream[RKISP_STREAM_LUMA];
+
+ s->ops->frame_end(s, FRAME_IRQ);
+ }
+ if (dev->procfs.is_fe_wait) {
+ dev->procfs.is_fe_wait = false;
+ wake_up(&dev->procfs.fe_wait);
+ }
}
/*
@@ -3136,16 +4325,30 @@
* lot of register writes. Do those only one per frame.
* Do the updates in the order of the processing flow.
*/
- rkisp_params_isr(&dev->params_vdev, isp_mis);
+ if (isp_mis & (CIF_ISP_V_START | CIF_ISP_FRAME))
+ rkisp_params_isr(&dev->params_vdev, isp_mis);
/* cur frame end and next frame start irq togeter */
if (dev->vs_irq < 0 && sof_event_later) {
- dev->isp_sdev.frm_timestamp = ktime_get_ns();
+ dev->isp_sdev.frm_timestamp = rkisp_time_get_ns(dev);
rkisp_isp_queue_event_sof(&dev->isp_sdev);
+ rkisp_stream_frame_start(dev, isp_mis);
}
- if (isp_mis & CIF_ISP_FRAME_IN)
- rkisp_check_idle(dev, ISP_FRAME_IN);
+ if (isp_mis & ISP3X_OUT_FRM_QUARTER) {
+ writel(ISP3X_OUT_FRM_QUARTER, base + CIF_ISP_ICR);
+ rkisp_dvbm_event(dev, ISP3X_OUT_FRM_QUARTER);
+ }
+ if (isp_mis & ISP3X_OUT_FRM_HALF) {
+ writel(ISP3X_OUT_FRM_HALF, base + CIF_ISP_ICR);
+ rkisp_dvbm_event(dev, ISP3X_OUT_FRM_HALF);
+ rkisp_stream_buf_done_early(dev);
+ }
+ if (isp_mis & ISP3X_OUT_FRM_END) {
+ writel(ISP3X_OUT_FRM_END, base + CIF_ISP_ICR);
+ rkisp_dvbm_event(dev, ISP3X_OUT_FRM_END);
+ }
+
if (isp_mis & CIF_ISP_FRAME)
rkisp_check_idle(dev, ISP_FRAME_END);
}
--
Gitblit v1.6.2