mirror of
https://github.com/hardkernel/linux.git
synced 2026-06-09 12:17:12 +09:00
media: rockchip: isp: support unite mode for isp35
Change-Id: Ie4e237d8306f4e340552b8f5541d364cc2fce2ce Signed-off-by: Cai YiWei <cyw@rock-chips.com>
This commit is contained in:
@@ -744,11 +744,12 @@ struct capture_fmt *find_fmt(struct rkisp_stream *stream, const u32 pixelfmt)
|
||||
}
|
||||
|
||||
static void restrict_rsz_resolution(struct rkisp_stream *stream,
|
||||
const struct stream_config *cfg,
|
||||
u32 dest_w, u32 dest_h,
|
||||
struct v4l2_rect *max_rsz)
|
||||
{
|
||||
struct rkisp_device *dev = stream->ispdev;
|
||||
struct v4l2_rect *input_win = rkisp_get_isp_sd_win(&dev->isp_sdev);
|
||||
const struct stream_config *cfg = stream->config;
|
||||
|
||||
if (stream->id == RKISP_STREAM_VIR ||
|
||||
stream->id == RKISP_STREAM_LDC ||
|
||||
@@ -769,14 +770,24 @@ static void restrict_rsz_resolution(struct rkisp_stream *stream,
|
||||
|
||||
max_rsz->width = ALIGN(DIV_ROUND_UP(input_win->width, div), 4);
|
||||
max_rsz->height = DIV_ROUND_UP(input_win->height, div);
|
||||
} else if (dev->hw_dev->unite) {
|
||||
} else if (dev->unite_div > ISP_UNITE_DIV1) {
|
||||
/* scale down only for unite mode */
|
||||
max_rsz->width = min_t(int, input_win->width, cfg->max_rsz_width);
|
||||
max_rsz->height = min_t(int, input_win->height, cfg->max_rsz_height);
|
||||
if (dest_w == input_win->width && dest_h == input_win->height) {
|
||||
max_rsz->width = dest_w;
|
||||
max_rsz->height = dest_h;
|
||||
} else {
|
||||
max_rsz->width = min_t(int, input_win->width, cfg->max_rsz_width);
|
||||
max_rsz->height = min_t(int, input_win->height, cfg->max_rsz_height);
|
||||
}
|
||||
} else {
|
||||
/* scale up/down */
|
||||
max_rsz->width = cfg->max_rsz_width;
|
||||
max_rsz->height = cfg->max_rsz_height;
|
||||
if (dest_w == input_win->width && dest_h == input_win->height) {
|
||||
max_rsz->width = dest_w;
|
||||
max_rsz->height = dest_h;
|
||||
} else {
|
||||
max_rsz->width = cfg->max_rsz_width;
|
||||
max_rsz->height = cfg->max_rsz_height;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -817,7 +828,7 @@ static int rkisp_set_fmt(struct rkisp_stream *stream,
|
||||
}
|
||||
|
||||
/* do checks on resolution */
|
||||
restrict_rsz_resolution(stream, config, &max_rsz);
|
||||
restrict_rsz_resolution(stream, pixm->width, pixm->height, &max_rsz);
|
||||
if (stream->id == RKISP_STREAM_MP ||
|
||||
stream->id == RKISP_STREAM_SP ||
|
||||
(stream->id == RKISP_STREAM_BP && dev->isp_ver != ISP_V30)) {
|
||||
@@ -1087,7 +1098,6 @@ static int rkisp_enum_framesizes(struct file *file, void *prov,
|
||||
struct v4l2_frmsizeenum *fsize)
|
||||
{
|
||||
struct rkisp_stream *stream = video_drvdata(file);
|
||||
const struct stream_config *config = stream->config;
|
||||
struct v4l2_frmsize_stepwise *s = &fsize->stepwise;
|
||||
struct v4l2_frmsize_discrete *d = &fsize->discrete;
|
||||
struct rkisp_device *dev = stream->ispdev;
|
||||
@@ -1100,7 +1110,7 @@ static int rkisp_enum_framesizes(struct file *file, void *prov,
|
||||
if (!find_fmt(stream, fsize->pixel_format))
|
||||
return -EINVAL;
|
||||
|
||||
restrict_rsz_resolution(stream, config, &max_rsz);
|
||||
restrict_rsz_resolution(stream, 0, 0, &max_rsz);
|
||||
|
||||
if (stream->out_isp_fmt.fmt_type == FMT_BAYER ||
|
||||
stream->id == RKISP_STREAM_FBC ||
|
||||
|
||||
@@ -760,6 +760,32 @@ static void update_mi(struct rkisp_stream *stream)
|
||||
rkisp_idx_write(dev, reg, val, ISP_UNITE_RIGHT, false);
|
||||
}
|
||||
|
||||
if (dev->unite_div == ISP_UNITE_DIV4) {
|
||||
/* left bottom of image */
|
||||
reg = stream->config->mi.y_base_ad_init;
|
||||
val = stream->next_buf->buff_addr[RKISP_PLANE_Y];
|
||||
val += (out_fmt->plane_fmt[0].bytesperline * out_fmt->height / 2);
|
||||
rkisp_idx_write(dev, reg, val, ISP_UNITE_LEFT_B, false);
|
||||
|
||||
reg = stream->config->mi.cb_base_ad_init;
|
||||
val = stream->next_buf->buff_addr[RKISP_PLANE_CB];
|
||||
val += (out_fmt->plane_fmt[1].sizeimage / 2);
|
||||
rkisp_idx_write(dev, reg, val, ISP_UNITE_LEFT_B, false);
|
||||
|
||||
/* right bottom of image */
|
||||
reg = stream->config->mi.y_base_ad_init;
|
||||
val = stream->next_buf->buff_addr[RKISP_PLANE_Y];
|
||||
val += (out_fmt->plane_fmt[0].bytesperline * out_fmt->height / 2) +
|
||||
((out_fmt->width / div) & ~0xf);
|
||||
rkisp_idx_write(dev, reg, val, ISP_UNITE_RIGHT_B, false);
|
||||
|
||||
reg = stream->config->mi.cb_base_ad_init;
|
||||
val = stream->next_buf->buff_addr[RKISP_PLANE_CB];
|
||||
val += (out_fmt->plane_fmt[1].sizeimage / 2) +
|
||||
((out_fmt->width / div) & ~0xf);
|
||||
rkisp_idx_write(dev, reg, val, ISP_UNITE_RIGHT_B, false);
|
||||
}
|
||||
|
||||
if (stream->is_pause) {
|
||||
/* single sensor mode with pingpong buffer:
|
||||
* if mi on, addr will auto update at frame end
|
||||
@@ -1618,6 +1644,8 @@ static int rkisp_stream_init(struct rkisp_device *dev, u32 id)
|
||||
strscpy(vdev->name, SP_VDEV_NAME, sizeof(vdev->name));
|
||||
stream->ops = &rkisp_sp_streams_ops;
|
||||
stream->config = &rkisp_sp_stream_cfg;
|
||||
if (dev->hw_dev->unite)
|
||||
stream->config->max_rsz_width *= 2;
|
||||
break;
|
||||
case RKISP_STREAM_VIR:
|
||||
strscpy(vdev->name, VIR_VDEV_NAME, sizeof(vdev->name));
|
||||
@@ -1629,6 +1657,10 @@ static int rkisp_stream_init(struct rkisp_device *dev, u32 id)
|
||||
strscpy(vdev->name, MP_VDEV_NAME, sizeof(vdev->name));
|
||||
stream->ops = &rkisp_mp_streams_ops;
|
||||
stream->config = &rkisp_mp_stream_cfg;
|
||||
if (dev->hw_dev->unite) {
|
||||
stream->config->max_rsz_width = CIF_ISP_INPUT_W_MAX_V35_UNITE;
|
||||
stream->config->max_rsz_height = CIF_ISP_INPUT_H_MAX_V35_UNITE;
|
||||
}
|
||||
}
|
||||
|
||||
rockit_isp_ops.rkisp_stream_start = rkisp_stream_start;
|
||||
|
||||
@@ -184,10 +184,7 @@ static long rkisp_sditf_ioctl(struct v4l2_subdev *sd, unsigned int cmd, void *ar
|
||||
rkisp_check_idle(sditf->isp, ISP_FRAME_VPSS);
|
||||
break;
|
||||
case RKISP_VPSS_GET_UNITE_MODE:
|
||||
if (sditf->isp->unite_div == ISP_UNITE_DIV2)
|
||||
*(unsigned int *)arg = sditf->isp->unite_div;
|
||||
else
|
||||
*(unsigned int *)arg = 0;
|
||||
*(unsigned int *)arg = sditf->isp->unite_div - 1;
|
||||
break;
|
||||
case RKISP_VPSS_GET_ISP_WORKING:
|
||||
*(int *)arg = sditf->isp->hw_dev->is_runing;
|
||||
|
||||
@@ -629,17 +629,17 @@ rkisp_stats_send_meas(struct rkisp_isp_stats_vdev *stats_vdev)
|
||||
cur_stat_buf = cur_buf->vaddr[0];
|
||||
}
|
||||
|
||||
/* buffer done when frame of right handle */
|
||||
if (dev->unite_div > ISP_UNITE_DIV1) {
|
||||
if (dev->unite_index == ISP_UNITE_LEFT) {
|
||||
cur_buf = NULL;
|
||||
is_dummy = false;
|
||||
} else if (cur_stat_buf) {
|
||||
cur_stat_buf = (void *)cur_stat_buf + size / 2;
|
||||
}
|
||||
if (dev->unite_index > ISP_UNITE_LEFT && cur_stat_buf)
|
||||
cur_stat_buf = (void *)cur_stat_buf + size / dev->unite_div * dev->unite_index;
|
||||
if ((dev->unite_div == ISP_UNITE_DIV2 && dev->unite_index != ISP_UNITE_RIGHT) ||
|
||||
(dev->unite_div == ISP_UNITE_DIV4 && dev->unite_index != ISP_UNITE_RIGHT_B)) {
|
||||
cur_buf = NULL;
|
||||
is_dummy = false;
|
||||
}
|
||||
|
||||
if (dev->unite_div < ISP_UNITE_DIV2 || dev->unite_index == ISP_UNITE_RIGHT) {
|
||||
if (dev->unite_div < ISP_UNITE_DIV2 ||
|
||||
(dev->unite_div == ISP_UNITE_DIV2 && dev->unite_index == ISP_UNITE_RIGHT) ||
|
||||
(dev->unite_div == ISP_UNITE_DIV4 && dev->unite_index == ISP_UNITE_RIGHT_B)) {
|
||||
/* config buf for next frame */
|
||||
stats_vdev->cur_buf = NULL;
|
||||
if (stats_vdev->nxt_buf) {
|
||||
|
||||
@@ -1377,14 +1377,16 @@ static int isp_show(struct seq_file *p, void *v)
|
||||
info, sdev->dbg.frameloss,
|
||||
dev->rdbk_cnt, dev->rdbk_cnt_x1, dev->rdbk_cnt_x2, dev->rdbk_cnt_x3,
|
||||
rkisp_stream_buf_cnt(stream));
|
||||
seq_printf(p, "\t hw link:%d idle:%d vir(mode:%d index:%d)\n",
|
||||
seq_printf(p, "\t hw link:%d idle:%d vir(mode:%d index:%d) div:%d extend:%d\n",
|
||||
dev->hw_dev->dev_link_num, dev->hw_dev->is_idle,
|
||||
dev->multi_mode, dev->multi_index);
|
||||
dev->multi_mode, dev->multi_index, dev->unite_div,
|
||||
dev->hw_dev->unite_extend_pixel);
|
||||
} else {
|
||||
seq_printf(p, "%-10s frame:%d state:%s %s v-blank:%dus\n",
|
||||
seq_printf(p, "%-10s frame:%d state:%s %s v-blank:%dus div:%d extend:%d\n",
|
||||
"Isp online", sdev->dbg.id,
|
||||
(dev->isp_state & ISP_FRAME_END) ? "idle" : "working",
|
||||
info, sdev->dbg.delay / 1000);
|
||||
info, sdev->dbg.delay / 1000,
|
||||
dev->unite_div, dev->hw_dev->unite_extend_pixel);
|
||||
}
|
||||
if (dev->br_dev.en)
|
||||
seq_printf(p, "%-10s rkispp%d Format:%s%s Size:%dx%d (frame:%d rate:%dms frameloss:%d)\n",
|
||||
|
||||
@@ -241,8 +241,10 @@ int rkisp_align_sensor_resolution(struct rkisp_device *dev,
|
||||
CIF_ISP_INPUT_H_MAX_V33_UNITE : CIF_ISP_INPUT_H_MAX_V33;
|
||||
break;
|
||||
case ISP_V35:
|
||||
max_w = CIF_ISP_INPUT_W_MAX_V35;
|
||||
max_h = CIF_ISP_INPUT_H_MAX_V35;
|
||||
max_w = dev->hw_dev->unite ?
|
||||
CIF_ISP_INPUT_W_MAX_V35_UNITE : CIF_ISP_INPUT_W_MAX_V35;
|
||||
max_h = dev->hw_dev->unite ?
|
||||
CIF_ISP_INPUT_H_MAX_V35_UNITE : CIF_ISP_INPUT_H_MAX_V35;
|
||||
break;
|
||||
default:
|
||||
max_w = CIF_ISP_INPUT_W_MAX;
|
||||
@@ -2980,6 +2982,58 @@ err:
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
static int rkisp_unite_div(struct rkisp_device *dev, u32 w, u32 h)
|
||||
{
|
||||
struct rkisp_hw_dev *hw = dev->hw_dev;
|
||||
u32 max_size, max_w, max_h;
|
||||
|
||||
dev->unite_div = ISP_UNITE_DIV1;
|
||||
if (hw->unite == ISP_UNITE_TWO && hw->isp_ver == ISP_V30) {
|
||||
dev->unite_div = ISP_UNITE_DIV2;
|
||||
return 0;
|
||||
}
|
||||
|
||||
switch (dev->isp_ver) {
|
||||
case ISP_V30:
|
||||
max_size = CIF_ISP_INPUT_W_MAX_V30 * CIF_ISP_INPUT_H_MAX_V30;
|
||||
max_w = CIF_ISP_INPUT_W_MAX_V30;
|
||||
max_h = max_size / w;
|
||||
break;
|
||||
case ISP_V32:
|
||||
max_size = CIF_ISP_INPUT_W_MAX_V32 * CIF_ISP_INPUT_H_MAX_V32;
|
||||
max_w = CIF_ISP_INPUT_W_MAX_V32;
|
||||
max_h = max_size / w;
|
||||
break;
|
||||
case ISP_V32_L:
|
||||
max_size = CIF_ISP_INPUT_W_MAX_V32_L * CIF_ISP_INPUT_H_MAX_V32_L;
|
||||
max_w = CIF_ISP_INPUT_W_MAX_V32_L;
|
||||
max_h = max_size / w;
|
||||
break;
|
||||
case ISP_V33:
|
||||
max_size = CIF_ISP_INPUT_W_MAX_V33 * CIF_ISP_INPUT_H_MAX_V33;
|
||||
max_w = CIF_ISP_INPUT_W_MAX_V33;
|
||||
max_h = max_size / w;
|
||||
break;
|
||||
case ISP_V35:
|
||||
max_size = CIF_ISP_INPUT_W_MAX_V35 * CIF_ISP_INPUT_H_MAX_V35;
|
||||
max_w = CIF_ISP_INPUT_W_MAX_V35;
|
||||
max_h = CIF_ISP_INPUT_H_MAX_V35;
|
||||
break;
|
||||
case ISP_V39:
|
||||
max_size = CIF_ISP_INPUT_W_MAX_V39_UNITE / 2 * CIF_ISP_INPUT_H_MAX_V39_UNITE;
|
||||
max_w = CIF_ISP_INPUT_W_MAX_V39;
|
||||
max_h = max_size / w;
|
||||
break;
|
||||
default:
|
||||
return -EINVAL;
|
||||
}
|
||||
if (w * h > max_size * 2 || h > max_h)
|
||||
dev->unite_div = ISP_UNITE_DIV4;
|
||||
else if (w * h > max_size || w > max_w)
|
||||
dev->unite_div = ISP_UNITE_DIV2;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void rkisp_isp_sd_try_crop(struct v4l2_subdev *sd,
|
||||
struct v4l2_rect *crop,
|
||||
u32 pad)
|
||||
@@ -2987,8 +3041,6 @@ static void rkisp_isp_sd_try_crop(struct v4l2_subdev *sd,
|
||||
struct rkisp_isp_subdev *isp_sd = sd_to_isp_sd(sd);
|
||||
struct rkisp_device *dev = sd_to_isp_dev(sd);
|
||||
struct v4l2_rect in_crop = isp_sd->in_crop;
|
||||
struct rkisp_hw_dev *hw = dev->hw_dev;
|
||||
u32 size;
|
||||
|
||||
crop->left = ALIGN(crop->left, 2);
|
||||
crop->width = ALIGN(crop->width, 2);
|
||||
@@ -2997,38 +3049,7 @@ static void rkisp_isp_sd_try_crop(struct v4l2_subdev *sd,
|
||||
/* update sensor info if sensor link be changed */
|
||||
rkisp_update_sensor_info(dev);
|
||||
rkisp_align_sensor_resolution(dev, crop, true);
|
||||
if (hw->unite == ISP_UNITE_TWO && hw->isp_ver == ISP_V30) {
|
||||
dev->unite_div = ISP_UNITE_DIV2;
|
||||
} else {
|
||||
dev->unite_div = ISP_UNITE_DIV1;
|
||||
switch (dev->isp_ver) {
|
||||
case ISP_V30:
|
||||
size = CIF_ISP_INPUT_W_MAX_V30 * CIF_ISP_INPUT_H_MAX_V30;
|
||||
break;
|
||||
case ISP_V32:
|
||||
size = CIF_ISP_INPUT_W_MAX_V32 * CIF_ISP_INPUT_H_MAX_V32;
|
||||
break;
|
||||
case ISP_V32_L:
|
||||
size = CIF_ISP_INPUT_W_MAX_V32_L * CIF_ISP_INPUT_H_MAX_V32_L;
|
||||
break;
|
||||
case ISP_V33:
|
||||
size = CIF_ISP_INPUT_W_MAX_V33 * CIF_ISP_INPUT_H_MAX_V33;
|
||||
break;
|
||||
case ISP_V35:
|
||||
size = CIF_ISP_INPUT_W_MAX_V35 * CIF_ISP_INPUT_H_MAX_V35;
|
||||
break;
|
||||
case ISP_V39:
|
||||
size = CIF_ISP_INPUT_W_MAX_V39_UNITE * CIF_ISP_INPUT_H_MAX_V39_UNITE;
|
||||
size /= 2;
|
||||
break;
|
||||
default:
|
||||
return;
|
||||
}
|
||||
if (crop->width * crop->height > size * 2)
|
||||
dev->unite_div = ISP_UNITE_DIV4;
|
||||
else if (crop->width * crop->height > size)
|
||||
dev->unite_div = ISP_UNITE_DIV2;
|
||||
}
|
||||
rkisp_unite_div(dev, crop->width, crop->height);
|
||||
} else if (pad == RKISP_ISP_PAD_SOURCE_PATH) {
|
||||
crop->left = clamp_t(u32, crop->left, 0, in_crop.width);
|
||||
crop->top = clamp_t(u32, crop->top, 0, in_crop.height);
|
||||
@@ -3105,8 +3126,10 @@ static int rkisp_isp_sd_get_selection(struct v4l2_subdev *sd,
|
||||
CIF_ISP_INPUT_H_MAX_V33_UNITE : CIF_ISP_INPUT_H_MAX_V33;
|
||||
break;
|
||||
case ISP_V35:
|
||||
max_w = CIF_ISP_INPUT_W_MAX_V35;
|
||||
max_h = CIF_ISP_INPUT_H_MAX_V35;
|
||||
max_w = dev->hw_dev->unite ?
|
||||
CIF_ISP_INPUT_W_MAX_V35_UNITE : CIF_ISP_INPUT_W_MAX_V35;
|
||||
max_h = dev->hw_dev->unite ?
|
||||
CIF_ISP_INPUT_H_MAX_V35_UNITE : CIF_ISP_INPUT_H_MAX_V35;
|
||||
break;
|
||||
case ISP_V39:
|
||||
max_w = dev->hw_dev->unite ?
|
||||
|
||||
@@ -73,6 +73,8 @@
|
||||
#define CIF_ISP_INPUT_H_MAX_V33_UNITE 2160
|
||||
#define CIF_ISP_INPUT_W_MAX_V35 4096
|
||||
#define CIF_ISP_INPUT_H_MAX_V35 3072
|
||||
#define CIF_ISP_INPUT_W_MAX_V35_UNITE 7168
|
||||
#define CIF_ISP_INPUT_H_MAX_V35_UNITE 5120
|
||||
#define CIF_ISP_INPUT_W_MIN 272
|
||||
#define CIF_ISP_INPUT_H_MIN 264
|
||||
#define CIF_ISP_OUTPUT_W_MAX CIF_ISP_INPUT_W_MAX
|
||||
|
||||
Reference in New Issue
Block a user