diff --git a/drivers/media/platform/rockchip/isp/capture.c b/drivers/media/platform/rockchip/isp/capture.c index 6cdd9b3a08a4..f2211c9f02b9 100644 --- a/drivers/media/platform/rockchip/isp/capture.c +++ b/drivers/media/platform/rockchip/isp/capture.c @@ -947,8 +947,7 @@ static void restrict_rsz_resolution(struct rkisp_stream *stream, max_rsz->width = t->out_fmt.width / 4; max_rsz->height = t->out_fmt.height / 4; } else if (stream->id == RKISP_STREAM_LUMA) { - bool bigmode = rkisp_params_check_bigmode(&dev->params_vdev); - u32 div = bigmode ? 32 : 16; + u32 div = dev->is_bigmode ? 32 : 16; max_rsz->width = input_win->width / div; max_rsz->height = input_win->height / div; diff --git a/drivers/media/platform/rockchip/isp/dev.h b/drivers/media/platform/rockchip/isp/dev.h index ab600b92edaa..4d9e71877ea6 100644 --- a/drivers/media/platform/rockchip/isp/dev.h +++ b/drivers/media/platform/rockchip/isp/dev.h @@ -246,5 +246,8 @@ struct rkisp_device { bool is_bigmode; struct rkisp_vicap_input vicap_in; + + u8 multi_mode; + u8 multi_index; }; #endif diff --git a/drivers/media/platform/rockchip/isp/hw.c b/drivers/media/platform/rockchip/isp/hw.c index bc3f216b1505..987f224649f1 100644 --- a/drivers/media/platform/rockchip/isp/hw.c +++ b/drivers/media/platform/rockchip/isp/hw.c @@ -803,14 +803,20 @@ static int rkisp_hw_probe(struct platform_device *pdev) if (!hw_dev) return -ENOMEM; + match_data = match->data; + hw_dev->is_unite = match_data->unite; dev_set_drvdata(dev, hw_dev); hw_dev->dev = dev; hw_dev->is_thunderboot = IS_ENABLED(CONFIG_VIDEO_ROCKCHIP_THUNDER_BOOT_ISP); dev_info(dev, "is_thunderboot: %d\n", hw_dev->is_thunderboot); - hw_dev->max_in.w = 0; - hw_dev->max_in.h = 0; - hw_dev->max_in.fps = 0; - of_property_read_u32_array(node, "max-input", &hw_dev->max_in.w, 3); + memset(&hw_dev->max_in, 0, sizeof(hw_dev->max_in)); + if (!of_property_read_u32_array(node, "max-input", &hw_dev->max_in.w, 3)) { + hw_dev->max_in.is_fix = true; + if (hw_dev->is_unite) { + hw_dev->max_in.w /= 2; + hw_dev->max_in.w += RKMOUDLE_UNITE_EXTEND_PIXEL; + } + } dev_info(dev, "max input:%dx%d@%dfps\n", hw_dev->max_in.w, hw_dev->max_in.h, hw_dev->max_in.fps); hw_dev->grf = syscon_regmap_lookup_by_phandle(node, "rockchip,grf"); @@ -836,7 +842,6 @@ static int rkisp_hw_probe(struct platform_device *pdev) goto err; } - match_data = match->data; hw_dev->base_next_addr = NULL; if (match_data->unite) { res = platform_get_resource(pdev, IORESOURCE_MEM, 1); @@ -971,6 +976,7 @@ static int __maybe_unused rkisp_runtime_resume(struct device *dev) { struct rkisp_hw_dev *hw_dev = dev_get_drvdata(dev); void __iomem *base = hw_dev->base_addr; + struct rkisp_device *isp; int mult = hw_dev->is_unite ? 2 : 1; int ret, i; @@ -979,15 +985,33 @@ static int __maybe_unused rkisp_runtime_resume(struct device *dev) return ret; enable_sys_clk(hw_dev); - + memset(hw_dev->isp_size, 0, sizeof(hw_dev->isp_size)); + if (!hw_dev->max_in.is_fix) { + hw_dev->max_in.w = 0; + hw_dev->max_in.h = 0; + } for (i = 0; i < hw_dev->dev_num; i++) { - struct rkisp_device *isp = hw_dev->isp[i]; void *buf; + u32 w, h; + isp = hw_dev->isp[i]; if (!isp || (isp && !isp->is_hw_link)) continue; if (hw_dev->dev_link_num++) hw_dev->is_single = false; + w = isp->isp_sdev.in_crop.width; + h = isp->isp_sdev.in_crop.height; + if (hw_dev->is_unite) + w = w / 2 + RKMOUDLE_UNITE_EXTEND_PIXEL; + hw_dev->isp_size[i].w = w; + hw_dev->isp_size[i].h = h; + hw_dev->isp_size[i].size = w * h; + if (!hw_dev->max_in.is_fix) { + if (hw_dev->max_in.w < w) + hw_dev->max_in.w = w; + if (hw_dev->max_in.h < h) + hw_dev->max_in.h = h; + } buf = isp->sw_base_addr; memset(buf, 0, RKISP_ISP_SW_MAX_SIZE * mult); memcpy_fromio(buf, base, RKISP_ISP_SW_REG_SIZE); @@ -998,6 +1022,12 @@ static int __maybe_unused rkisp_runtime_resume(struct device *dev) } default_sw_reg_flag(hw_dev->isp[i]); } + for (i = 0; i < hw_dev->dev_num; i++) { + isp = hw_dev->isp[i]; + if (!isp || (isp && !isp->is_hw_link)) + continue; + rkisp_params_check_bigmode(&isp->params_vdev); + } hw_dev->monitor.is_en = rkisp_monitor; return 0; } diff --git a/drivers/media/platform/rockchip/isp/hw.h b/drivers/media/platform/rockchip/isp/hw.h index acbfe6eea26a..910389dbdbeb 100644 --- a/drivers/media/platform/rockchip/isp/hw.h +++ b/drivers/media/platform/rockchip/isp/hw.h @@ -40,6 +40,12 @@ struct rkisp_sram { u32 size; }; +struct rkisp_size_info { + u32 w; + u32 h; + u32 size; +}; + struct rkisp_hw_dev { const struct isp_match_data *match_data; struct platform_device *pdev; @@ -55,6 +61,7 @@ struct rkisp_hw_dev { int mipi_irq; enum rkisp_isp_ver isp_ver; struct rkisp_device *isp[DEV_MAX]; + struct rkisp_size_info isp_size[DEV_MAX]; int dev_num; int dev_link_num; int cur_dev_id; diff --git a/drivers/media/platform/rockchip/isp/isp_ispp.h b/drivers/media/platform/rockchip/isp/isp_ispp.h index f40158d7bc2f..a12b476fbf38 100644 --- a/drivers/media/platform/rockchip/isp/isp_ispp.h +++ b/drivers/media/platform/rockchip/isp/isp_ispp.h @@ -78,6 +78,7 @@ struct max_input { u32 w; u32 h; u32 fps; + bool is_fix; }; struct rkisp_ispp_mode { diff --git a/drivers/media/platform/rockchip/isp/isp_params_v21.c b/drivers/media/platform/rockchip/isp/isp_params_v21.c index 7598d31d00c6..6b5748135987 100644 --- a/drivers/media/platform/rockchip/isp/isp_params_v21.c +++ b/drivers/media/platform/rockchip/isp/isp_params_v21.c @@ -3795,35 +3795,161 @@ rkisp_alloc_bay3d_buf(struct rkisp_isp_params_vdev *params_vdev, static bool rkisp_params_check_bigmode_v21(struct rkisp_isp_params_vdev *params_vdev) { + struct rkisp_device *ispdev = params_vdev->dev; struct device *dev = params_vdev->dev->dev; struct rkisp_hw_dev *hw = params_vdev->dev->hw_dev; - struct v4l2_rect *out_crop = ¶ms_vdev->dev->isp_sdev.out_crop; - u32 width = hw->max_in.w ? hw->max_in.w : out_crop->width; - u32 height = hw->max_in.h ? hw->max_in.h : out_crop->height; - u32 size = width * height; + struct v4l2_rect *crop = ¶ms_vdev->dev->isp_sdev.in_crop; + u32 width = hw->max_in.w, height = hw->max_in.h, size = width * height; u32 bigmode_max_w, bigmode_max_size; + int k = 0, idx1[DEV_MAX] = { 0 }; + int n = 0, idx2[DEV_MAX] = { 0 }; + int i = 0, j = 0; bool is_bigmode = false; - if (hw->dev_link_num > 2) { + switch (hw->dev_link_num) { + case 4: bigmode_max_w = ISP21_VIR4_AUTO_BIGMODE_WIDTH; bigmode_max_size = ISP21_VIR4_NOBIG_OVERFLOW_SIZE; - if (width > ISP21_VIR4_MAX_WIDTH || size > ISP21_VIR4_MAX_SIZE) - dev_err(dev, "%dx%d > max:3840x2160 for %d virtual isp\n", - width, height, hw->dev_link_num); - } else if (hw->dev_link_num > 1) { + ispdev->multi_index = ispdev->dev_id; + ispdev->multi_mode = 2; + /* internal buf of hw divided to four parts + * bigmode nobigmode + * _________ max width:1920 max width:960 + * |_sensor0_| max size:1920*1080 max size:960*540 + * |_sensor1_| max size:1920*1080 max size:960*540 + * |_sensor2_| max size:1920*1080 max size:960*540 + * |_sensor3_| max size:1920*1080 max size:960*540 + */ + for (i = 0; i < hw->dev_num; i++) { + 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; + } + break; + case 3: + bigmode_max_w = ISP21_VIR4_AUTO_BIGMODE_WIDTH; + bigmode_max_size = ISP21_VIR4_NOBIG_OVERFLOW_SIZE; + ispdev->multi_index = ispdev->dev_id; + ispdev->multi_mode = 2; + /* case0: bigmode nobigmode + * _________ max width:1920 max width:960 + * |_sensor0_| max size:1920*1080 max size:960*540 + * |_sensor1_| max size:1920*1080 max size:960*540 + * |_sensor2_| max size:1920*1080 max size:960*540 + * |_________| + * + * case1: bigmode special reg cfg + * _________ max width:4096 + * | sensor0 | max size:1920*1080*2 mode=0 index=0 + * |_________| + * |_sensor1_| max size:1920*1080 mode=2 index=2 + * |_sensor2_| max size:1920*1080 mode=2 index=3 + * max width:1920 + */ + for (i = 0; i < hw->dev_num; i++) { + if (!hw->isp_size[i].size) { + if (i < hw->dev_link_num) + idx2[n++] = i; + continue; + } + if (hw->isp_size[i].w <= ISP21_VIR4_MAX_WIDTH && + hw->isp_size[i].size <= ISP21_VIR4_MAX_SIZE) + continue; + idx1[k++] = i; + } + if (k) { + 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"); + } else { + if (idx1[0] == ispdev->dev_id) { + ispdev->multi_mode = 0; + ispdev->multi_index = 0; + } else { + ispdev->multi_mode = 2; + if (ispdev->multi_index == 0 || + ispdev->multi_index == 1) + ispdev->multi_index = 3; + } + } + } else if (ispdev->multi_index >= hw->dev_link_num) { + ispdev->multi_index = idx2[ispdev->multi_index - hw->dev_link_num]; + } + break; + case 2: bigmode_max_w = ISP21_VIR2_AUTO_BIGMODE_WIDTH; bigmode_max_size = ISP21_VIR2_NOBIG_OVERFLOW_SIZE; - if (width > ISP21_VIR2_MAX_WIDTH || size > ISP21_VIR2_MAX_SIZE) - dev_err(dev, "%dx%d > max:1920x1080 for %d virtual isp\n", - width, height, hw->dev_link_num); - } else { + ispdev->multi_index = ispdev->dev_id; + ispdev->multi_mode = 1; + /* case0: bigmode nobigmode + * _________ max width:3840 max width:1920 + * | sensor0 | max size:3840*2160 max size:1920*1080 + * |_________| + * | sensor1 | max size:3840*2160 max size:1920*1080 + * |_________| + * + * case1: bigmode special reg cfg + * _________ max width:4096 + * | sensor0 | max size:1920*1080*3 mode=0 index=0 + * | | + * |_________| + * |_sensor1_| max size:1920*1080 mode=2 index=3 + * max width:1920 + */ + for (i = 0; i < hw->dev_num; i++) { + if (!hw->isp_size[i].size) { + if (i < hw->dev_link_num) + idx2[n++] = i; + continue; + } + if (hw->isp_size[i].w <= ISP21_VIR2_MAX_WIDTH && + hw->isp_size[i].size <= ISP21_VIR2_MAX_SIZE) { + if (hw->isp_size[i].w > ISP21_VIR4_MAX_WIDTH || + hw->isp_size[i].size > ISP21_VIR4_MAX_SIZE) + j++; + continue; + } + idx1[k++] = i; + } + if (k) { + 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"); + } else { + if (idx1[0] == ispdev->dev_id) { + ispdev->multi_mode = 0; + ispdev->multi_index = 0; + } else { + ispdev->multi_mode = 2; + ispdev->multi_index = 3; + } + } + } else if (ispdev->multi_index >= hw->dev_link_num) { + ispdev->multi_index = idx2[ispdev->multi_index - hw->dev_link_num]; + } + break; + default: bigmode_max_w = ISP21_AUTO_BIGMODE_WIDTH; bigmode_max_size = ISP21_NOBIG_OVERFLOW_SIZE; + ispdev->multi_mode = 0; + ispdev->multi_index = 0; + width = crop->width; + height = crop->height; + size = width * height; + break; } - if (width > bigmode_max_w || size > bigmode_max_size) + if (!is_bigmode && + (width > bigmode_max_w || size > bigmode_max_size)) is_bigmode = true; - return is_bigmode; + + return ispdev->is_bigmode = is_bigmode; } /* Not called when the camera active, thus not isr protection. */ diff --git a/drivers/media/platform/rockchip/isp/isp_params_v32.c b/drivers/media/platform/rockchip/isp/isp_params_v32.c index 3fe9c674e3a0..771977a4f9f9 100644 --- a/drivers/media/platform/rockchip/isp/isp_params_v32.c +++ b/drivers/media/platform/rockchip/isp/isp_params_v32.c @@ -18,7 +18,7 @@ #define ISP32_VIR2_NOBIG_OVERFLOW_SIZE (960 * 540) #define ISP32_VIR2_AUTO_BIGMODE_WIDTH 960 #define ISP32_VIR4_NOBIG_OVERFLOW_SIZE (640 * 400) -#define ISP32_VIR4_AUTO_BIGMODE_WIDTH 1280 +#define ISP32_VIR4_AUTO_BIGMODE_WIDTH 640 #define ISP32_VIR2_MAX_WIDTH 1920 #define ISP32_VIR2_MAX_SIZE (1920 * 1080) @@ -4179,35 +4179,159 @@ err_3dlut: static bool rkisp_params_check_bigmode_v32(struct rkisp_isp_params_vdev *params_vdev) { + struct rkisp_device *ispdev = params_vdev->dev; struct device *dev = params_vdev->dev->dev; struct rkisp_hw_dev *hw = params_vdev->dev->hw_dev; - struct v4l2_rect *out_crop = ¶ms_vdev->dev->isp_sdev.out_crop; - u32 width = hw->max_in.w ? hw->max_in.w : out_crop->width; - u32 height = hw->max_in.h ? hw->max_in.h : out_crop->height; - u32 size = width * height; + struct v4l2_rect *crop = ¶ms_vdev->dev->isp_sdev.in_crop; + u32 width = hw->max_in.w, height = hw->max_in.h, size = width * height; u32 bigmode_max_w, bigmode_max_size; + int k = 0, idx1[DEV_MAX] = { 0 }; + int n = 0, idx2[DEV_MAX] = { 0 }; + int i = 0, j = 0; bool is_bigmode = false; - if (hw->dev_link_num > 2) { + switch (hw->dev_link_num) { + case 4: bigmode_max_w = ISP32_VIR4_AUTO_BIGMODE_WIDTH; bigmode_max_size = ISP32_VIR4_NOBIG_OVERFLOW_SIZE; - if (width > ISP32_VIR4_MAX_WIDTH || size > ISP32_VIR4_MAX_SIZE) - dev_err(dev, "%dx%d > max:2560x1536 for %d virtual isp\n", - width, height, hw->dev_link_num); - } else if (hw->dev_link_num > 1) { + ispdev->multi_index = ispdev->dev_id; + ispdev->multi_mode = 2; + /* internal buf of hw divided to four parts + * bigmode nobigmode + * _________ max width:1280 max width:640 + * |_sensor0_| max size:1280*800 max size:640*400 + * |_sensor1_| max size:1280*800 max size:640*400 + * |_sensor2_| max size:1280*800 max size:640*400 + * |_sensor3_| max size:1280*800 max size:640*400 + */ + for (i = 0; i < hw->dev_num; i++) { + 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; + } + break; + case 3: + bigmode_max_w = ISP32_VIR4_AUTO_BIGMODE_WIDTH; + bigmode_max_size = ISP32_VIR4_NOBIG_OVERFLOW_SIZE; + ispdev->multi_index = ispdev->dev_id; + ispdev->multi_mode = 2; + /* case0: bigmode nobigmode + * _________ max width:1280 max width:640 + * |_sensor0_| max size:1280*800 max size:640*400 + * |_sensor1_| max size:1280*800 max size:640*400 + * |_sensor2_| max size:1280*800 max size:640*400 + * |_________| + * + * case1: bigmode special reg cfg + * _________ max width:3072 + * | sensor0 | max size:1280*800*2 mode=0 index=0 + * |_________| + * |_sensor1_| max size:1280*800 mode=2 index=2 + * |_sensor2_| max size:1280*800 mode=2 index=3 + * max width:1280 + */ + for (i = 0; i < hw->dev_num; i++) { + if (!hw->isp_size[i].size) { + if (i < hw->dev_link_num) + idx2[n++] = i; + continue; + } + if (hw->isp_size[i].w <= ISP32_VIR4_MAX_WIDTH && + hw->isp_size[i].size <= ISP32_VIR4_MAX_SIZE) + continue; + idx1[k++] = i; + } + if (k) { + 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"); + } else { + if (idx1[0] == ispdev->dev_id) { + ispdev->multi_mode = 0; + ispdev->multi_index = 0; + } else { + ispdev->multi_mode = 2; + if (ispdev->multi_index == 0 || + ispdev->multi_index == 1) + ispdev->multi_index = 3; + } + } + } else if (ispdev->multi_index >= hw->dev_link_num) { + ispdev->multi_index = idx2[ispdev->multi_index - hw->dev_link_num]; + } + break; + case 2: bigmode_max_w = ISP32_VIR2_AUTO_BIGMODE_WIDTH; bigmode_max_size = ISP32_VIR2_NOBIG_OVERFLOW_SIZE; - if (width > ISP32_VIR2_MAX_WIDTH || size > ISP32_VIR2_MAX_SIZE) - dev_err(dev, "%dx%d > max:3840x2160 for %d virtual isp\n", - width, height, hw->dev_link_num); - } else { + ispdev->multi_index = ispdev->dev_id; + ispdev->multi_mode = 1; + /* case0: bigmode nobigmode + * _________ max width:1920 max width:1920 + * | sensor0 | max size:1920*1080 max size:1920*1080 + * |_________| + * | sensor1 | max size:1920*1080 max size:1920*1080 + * |_________| + * + * case1: bigmode special reg cfg + * _________ max width:3072 + * | sensor0 | max size:1280*800*3 mode=0 index=0 + * | | + * |_________| + * |_sensor1_| max size:1280*800 mode=2 index=3 + * max width:1280 + */ + for (i = 0; i < hw->dev_num; i++) { + if (!hw->isp_size[i].size) { + if (i < hw->dev_link_num) + idx2[n++] = i; + continue; + } + if (hw->isp_size[i].w <= ISP32_VIR2_MAX_WIDTH && + hw->isp_size[i].size <= ISP32_VIR2_MAX_SIZE) { + if (hw->isp_size[i].w > ISP32_VIR4_MAX_WIDTH || + hw->isp_size[i].size > ISP32_VIR4_MAX_SIZE) + j++; + continue; + } + idx1[k++] = i; + } + if (k) { + 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"); + } else { + if (idx1[0] == ispdev->dev_id) { + ispdev->multi_mode = 0; + ispdev->multi_index = 0; + } else { + ispdev->multi_mode = 2; + ispdev->multi_index = 3; + } + } + } else if (ispdev->multi_index >= hw->dev_link_num) { + ispdev->multi_index = idx2[ispdev->multi_index - hw->dev_link_num]; + } + break; + default: bigmode_max_w = ISP32_AUTO_BIGMODE_WIDTH; bigmode_max_size = ISP32_NOBIG_OVERFLOW_SIZE; + ispdev->multi_mode = 0; + ispdev->multi_index = 0; + width = crop->width; + height = crop->height; + size = width * height; + break; } - if (width > bigmode_max_w || size > bigmode_max_size) + if (!is_bigmode && + (width > bigmode_max_w || size > bigmode_max_size)) is_bigmode = true; - return is_bigmode; + return ispdev->is_bigmode = is_bigmode; } /* Not called when the camera active, thus not isr protection. */ diff --git a/drivers/media/platform/rockchip/isp/isp_params_v3x.c b/drivers/media/platform/rockchip/isp/isp_params_v3x.c index 3d066c6c03b9..35eeef4055ac 100644 --- a/drivers/media/platform/rockchip/isp/isp_params_v3x.c +++ b/drivers/media/platform/rockchip/isp/isp_params_v3x.c @@ -4212,40 +4212,165 @@ err_3dlut: static bool rkisp_params_check_bigmode_v3x(struct rkisp_isp_params_vdev *params_vdev) { - struct device *dev = params_vdev->dev->dev; - struct rkisp_hw_dev *hw = params_vdev->dev->hw_dev; - struct v4l2_rect *out_crop = ¶ms_vdev->dev->isp_sdev.out_crop; - u32 width = hw->max_in.w ? hw->max_in.w : out_crop->width; - u32 height = hw->max_in.h ? hw->max_in.h : out_crop->height; - u32 size = width * height; + struct rkisp_device *ispdev = params_vdev->dev; + struct device *dev = ispdev->dev; + struct rkisp_hw_dev *hw = ispdev->hw_dev; + struct v4l2_rect *crop = ¶ms_vdev->dev->isp_sdev.in_crop; + u32 width = hw->max_in.w, height = hw->max_in.h, size = width * height; u32 bigmode_max_w, bigmode_max_size; + int k = 0, idx1[DEV_MAX] = { 0 }; + int n = 0, idx2[DEV_MAX] = { 0 }; + int i = 0, j = 0; bool is_bigmode = false; - if (hw->dev_link_num > 2) { + switch (hw->dev_link_num) { + case 4: bigmode_max_w = ISP3X_VIR4_AUTO_BIGMODE_WIDTH; bigmode_max_size = ISP3X_VIR4_NOBIG_OVERFLOW_SIZE; - if (width > ISP3X_VIR4_MAX_WIDTH || size > ISP3X_VIR4_MAX_SIZE) - dev_err(dev, "%dx%d > max:2560x1536 for %d virtual isp\n", - width, height, hw->dev_link_num); - } else if (hw->dev_link_num > 1) { + ispdev->multi_index = ispdev->dev_id; + ispdev->multi_mode = 2; + /* internal buf of hw divided to four parts + * bigmode nobigmode + * _________ max width:2560 max width:1280 + * |_sensor0_| max size:2560*1536 max size:1280*800 + * |_sensor1_| max size:2560*1536 max size:1280*800 + * |_sensor2_| max size:2560*1536 max size:1280*800 + * |_sensor3_| max size:2560*1536 max size:1280*800 + */ + for (i = 0; i < hw->dev_num; i++) { + 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; + } + break; + case 3: + bigmode_max_w = ISP3X_VIR4_AUTO_BIGMODE_WIDTH; + bigmode_max_size = ISP3X_VIR4_NOBIG_OVERFLOW_SIZE; + ispdev->multi_index = ispdev->dev_id; + ispdev->multi_mode = 2; + /* case0: bigmode nobigmode + * _________ max width:2560 max width:1280 + * |_sensor0_| max size:2560*1536 max size:1280*800 + * |_sensor1_| max size:2560*1536 max size:1280*800 + * |_sensor2_| max size:2560*1536 max size:1280*800 + * |_________| + * + * case1: bigmode special reg cfg + * _________ max width:4672 + * | sensor0 | max size:2560*1536*2 mode=0 index=0 + * |_________| + * |_sensor1_| max size:2560*1536 mode=2 index=2 + * |_sensor2_| max size:2560*1536 mode=2 index=3 + * max width:2560 + */ + for (i = 0; i < hw->dev_num; i++) { + if (!hw->isp_size[i].size) { + if (i < hw->dev_link_num) + idx2[n++] = i; + continue; + } + if (hw->isp_size[i].w <= ISP3X_VIR4_MAX_WIDTH && + hw->isp_size[i].size <= ISP3X_VIR4_MAX_SIZE) + continue; + idx1[k++] = i; + } + if (k) { + 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); + } else { + if (idx1[0] == ispdev->dev_id) { + ispdev->multi_mode = 0; + ispdev->multi_index = 0; + } else { + ispdev->multi_mode = 2; + if (ispdev->multi_index == 0 || + ispdev->multi_index == 1) + ispdev->multi_index = 3; + } + } + } else if (ispdev->multi_index >= hw->dev_link_num) { + ispdev->multi_index = idx2[ispdev->multi_index - hw->dev_link_num]; + } + break; + case 2: bigmode_max_w = ISP3X_VIR2_AUTO_BIGMODE_WIDTH; bigmode_max_size = ISP3X_VIR2_NOBIG_OVERFLOW_SIZE; - if (width > ISP3X_VIR2_MAX_WIDTH || size > ISP3X_VIR2_MAX_SIZE) - dev_err(dev, "%dx%d > max:3840x2160 for %d virtual isp\n", - width, height, hw->dev_link_num); - } else { + ispdev->multi_index = ispdev->dev_id; + ispdev->multi_mode = 1; + /* case0: bigmode nobigmode + * _________ max width:3840 max width:1920 + * | sensor0 | max size:3840*2160 max size:1920*1080 + * |_________| + * | sensor1 | max size:3840*2160 max size:1920*1080 + * |_________| + * + * case1: bigmode special reg cfg + * _________ max width:4672 + * | sensor0 | max size:2560*2160*3 mode=0 index=0 + * | | + * |_________| + * |_sensor1_| max size:2560*1536 mode=2 index=3 + * max width:2560 + */ + for (i = 0; i < hw->dev_num; i++) { + if (!hw->isp_size[i].size) { + if (i < hw->dev_link_num) + idx2[n++] = i; + continue; + } + if (hw->isp_size[i].w <= ISP3X_VIR2_MAX_WIDTH && + hw->isp_size[i].size <= ISP3X_VIR2_MAX_SIZE) { + if (hw->isp_size[i].w > ISP3X_VIR4_MAX_WIDTH || + hw->isp_size[i].size > ISP3X_VIR4_MAX_SIZE) + j++; + continue; + } + idx1[k++] = i; + } + if (k) { + 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); + } else { + if (idx1[0] == ispdev->dev_id) { + ispdev->multi_mode = 0; + ispdev->multi_index = 0; + } else { + ispdev->multi_mode = 2; + ispdev->multi_index = 3; + } + } + } else if (ispdev->multi_index >= hw->dev_link_num) { + ispdev->multi_index = idx2[ispdev->multi_index - hw->dev_link_num]; + } + break; + default: bigmode_max_w = ISP3X_AUTO_BIGMODE_WIDTH; bigmode_max_size = ISP3X_NOBIG_OVERFLOW_SIZE; + ispdev->multi_mode = 0; + ispdev->multi_index = 0; + width = crop->width; + if (hw->is_unite) + width = width / 2 + RKMOUDLE_UNITE_EXTEND_PIXEL; + height = crop->height; + size = width * height; + break; } - if (hw->is_unite) { - width = width / 2 + RKMOUDLE_UNITE_EXTEND_PIXEL; - size = width * out_crop->height; - } - - if (width > bigmode_max_w || size > bigmode_max_size) + if (!is_bigmode && + (width > bigmode_max_w || size > bigmode_max_size)) is_bigmode = true; - return is_bigmode; + + return ispdev->is_bigmode = is_bigmode; } /* Not called when the camera active, thus not isr protection. */ diff --git a/drivers/media/platform/rockchip/isp/rkisp.c b/drivers/media/platform/rockchip/isp/rkisp.c index d0d7cd6637b4..cbc49345c637 100644 --- a/drivers/media/platform/rockchip/isp/rkisp.c +++ b/drivers/media/platform/rockchip/isp/rkisp.c @@ -617,31 +617,15 @@ void rkisp_trigger_read_back(struct rkisp_device *dev, u8 dma2frm, u32 mode, boo /* sensor mode & index */ if (dev->isp_ver == ISP_V21 || dev->isp_ver == ISP_V30 || dev->isp_ver == ISP_V32) { - u32 mode = hw->dev_link_num >= 3 ? 2 : hw->dev_link_num - 1; - u32 index = dev->dev_id; - - if (index >= hw->dev_link_num) { - int i, num = 0, off[4] = { 0 }; - struct rkisp_device *isp; - - for (i = 0; i < hw->dev_link_num; i++) { - isp = hw->isp[i]; - if (isp && isp->is_hw_link) - continue; - off[num++] = i; - } - if (num == 1) - index = off[0]; - else - index = off[index - hw->dev_link_num]; - } val = rkisp_read_reg_cache(dev, ISP_ACQ_H_OFFS); - val |= ISP21_SENSOR_MODE(mode) | ISP21_SENSOR_INDEX(index); + val |= ISP21_SENSOR_MODE(dev->multi_mode) | + ISP21_SENSOR_INDEX(dev->multi_index); writel(val, hw->base_addr + ISP_ACQ_H_OFFS); if (hw->is_unite) 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", mode, index, val); + "sensor mode:%d index:%d | 0x%x\n", + dev->multi_mode, dev->multi_index, val); } is_upd = true; } @@ -3120,7 +3104,7 @@ static int rkisp_get_info(struct rkisp_device *dev, struct rkisp_isp_info *info) mode = RKISP_ISP_COMPR; info->compr_bit = bit; - if (rkisp_params_check_bigmode(&dev->params_vdev)) + if (dev->is_bigmode) mode |= RKISP_ISP_BIGMODE; info->mode = mode; if (dev->hw_dev->is_unite)