diff --git a/drivers/media/platform/rockchip/isp/capture.c b/drivers/media/platform/rockchip/isp/capture.c index 70cad7dec608..e8984145dd5f 100644 --- a/drivers/media/platform/rockchip/isp/capture.c +++ b/drivers/media/platform/rockchip/isp/capture.c @@ -923,21 +923,41 @@ struct capture_fmt *find_fmt(struct rkisp_stream *stream, const u32 pixelfmt) return NULL; } -/* - * Make sure max resize/output resolution is smaller than - * isp sub device output size. This assumes it's not - * recommended to use ISP scale-up function to get output size - * that exceeds sensor max resolution. - */ -static void restrict_rsz_resolution(struct rkisp_device *dev, - const struct stream_config *config, +static void restrict_rsz_resolution(struct rkisp_stream *stream, + const struct stream_config *cfg, struct v4l2_rect *max_rsz) { - struct v4l2_rect *input_win; + struct rkisp_device *dev = stream->ispdev; + struct v4l2_rect *input_win = rkisp_get_isp_sd_win(&dev->isp_sdev); - input_win = rkisp_get_isp_sd_win(&dev->isp_sdev); - max_rsz->width = min_t(int, input_win->width, config->max_rsz_width); - max_rsz->height = min_t(int, input_win->height, config->max_rsz_height); + if (stream->id == RKISP_STREAM_VIR || + (dev->isp_ver == ISP_V30 && stream->id == RKISP_STREAM_BP)) { + max_rsz->width = input_win->width; + max_rsz->height = input_win->height; + } else if (stream->id == RKISP_STREAM_FBC) { + max_rsz->width = stream->dcrop.width; + max_rsz->height = stream->dcrop.height; + } else if (stream->id == RKISP_STREAM_MPDS || + stream->id == RKISP_STREAM_BPDS) { + struct rkisp_stream *t = &dev->cap_dev.stream[stream->conn_id]; + + 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; + + max_rsz->width = input_win->width / div; + max_rsz->height = input_win->height / div; + } else if (dev->hw_dev->is_unite) { + /* 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); + } else { + /* scale up/down */ + max_rsz->width = cfg->max_rsz_width; + max_rsz->height = cfg->max_rsz_height; + } } static int rkisp_set_fmt(struct rkisp_stream *stream, @@ -948,10 +968,60 @@ static int rkisp_set_fmt(struct rkisp_stream *stream, struct rkisp_vdev_node *node = &stream->vnode; const struct stream_config *config = stream->config; struct rkisp_device *dev = stream->ispdev; - u32 planes, imagsize = 0; - u32 i = 0, xsubs = 1, ysubs = 1; + struct v4l2_rect max_rsz; + u32 i, planes, imagsize = 0, xsubs = 1, ysubs = 1; - if (stream->id == RKISP_STREAM_VIR) { + fmt = find_fmt(stream, pixm->pixelformat); + if (!fmt) { + v4l2_err(&dev->v4l2_dev, + "%s nonsupport pixelformat:%c%c%c%c\n", + node->vdev.name, + pixm->pixelformat, + pixm->pixelformat >> 8, + pixm->pixelformat >> 16, + pixm->pixelformat >> 24); + return -EINVAL; + } + + /* do checks on resolution */ + restrict_rsz_resolution(stream, config, &max_rsz); + if (stream->id == RKISP_STREAM_MP || + stream->id == RKISP_STREAM_SP || + (stream->id == RKISP_STREAM_BP && dev->isp_ver != ISP_V30)) { + pixm->width = clamp_t(u32, pixm->width, + config->min_rsz_width, max_rsz.width); + pixm->height = clamp_t(u32, pixm->height, + config->min_rsz_height, max_rsz.height); + } else if (pixm->width != max_rsz.width && + pixm->height != max_rsz.height && + (stream->id == RKISP_STREAM_LUMA || + (dev->isp_ver == ISP_V30 && + (stream->id == RKISP_STREAM_BP || stream->id == RKISP_STREAM_FBC)))) { + v4l2_warn(&dev->v4l2_dev, + "%s no scale %dx%d should equal to %dx%d\n", + node->vdev.name, + pixm->width, pixm->height, + max_rsz.width, max_rsz.height); + pixm->width = max_rsz.width; + pixm->height = max_rsz.height; + } else if (stream->id == RKISP_STREAM_MPDS || stream->id == RKISP_STREAM_BPDS) { + struct rkisp_stream *t = &dev->cap_dev.stream[stream->conn_id]; + + if (pixm->pixelformat != t->out_fmt.pixelformat || + pixm->width != max_rsz.width || pixm->height != max_rsz.height) { + v4l2_warn(&dev->v4l2_dev, + "%s from %s, force to %dx%d %c%c%c%c\n", + node->vdev.name, t->vnode.vdev.name, + max_rsz.width, max_rsz.height, + t->out_fmt.pixelformat, + t->out_fmt.pixelformat >> 8, + t->out_fmt.pixelformat >> 16, + t->out_fmt.pixelformat >> 24); + pixm->pixelformat = t->out_fmt.pixelformat; + pixm->width = max_rsz.width; + pixm->height = max_rsz.height; + } + } else if (stream->id == RKISP_STREAM_VIR) { for (i = RKISP_STREAM_MP; i < RKISP_STREAM_VIR; i++) { struct rkisp_stream *t = &dev->cap_dev.stream[i]; @@ -970,77 +1040,6 @@ static int rkisp_set_fmt(struct rkisp_stream *stream, imagsize = 0; } - fmt = find_fmt(stream, pixm->pixelformat); - if (!fmt) { - v4l2_err(&dev->v4l2_dev, - "%s nonsupport pixelformat:%c%c%c%c\n", - node->vdev.name, - pixm->pixelformat, - pixm->pixelformat >> 8, - pixm->pixelformat >> 16, - pixm->pixelformat >> 24); - return -EINVAL; - } - - if (stream->id == RKISP_STREAM_MP || stream->id == RKISP_STREAM_SP) { - struct v4l2_rect max_rsz; - - /* do checks on resolution */ - restrict_rsz_resolution(stream->ispdev, config, &max_rsz); - pixm->width = clamp_t(u32, pixm->width, - config->min_rsz_width, max_rsz.width); - pixm->height = clamp_t(u32, pixm->height, - config->min_rsz_height, max_rsz.height); - } else if (dev->isp_ver == ISP_V30) { - if (stream->id == RKISP_STREAM_BP && - pixm->width != dev->isp_sdev.out_crop.width && - pixm->height != dev->isp_sdev.out_crop.height) { - v4l2_warn(&dev->v4l2_dev, - "%s %dx%d no equal to isp output %dx%d\n", - node->vdev.name, - pixm->width, pixm->height, - dev->isp_sdev.out_crop.width, - dev->isp_sdev.out_crop.height); - pixm->width = dev->isp_sdev.out_crop.width; - pixm->height = dev->isp_sdev.out_crop.height; - } else if (stream->id == RKISP_STREAM_FBC && - pixm->width != stream->dcrop.width && - pixm->height != stream->dcrop.height) { - v4l2_warn(&dev->v4l2_dev, - "%s no scale %dx%d should equal to crop %dx%d\n", - node->vdev.name, - pixm->width, pixm->height, - stream->dcrop.width, stream->dcrop.height); - pixm->width = stream->dcrop.width; - pixm->height = stream->dcrop.height; - } - } else if (stream->id == RKISP_STREAM_MPDS || stream->id == RKISP_STREAM_BPDS) { - struct rkisp_stream *t = &dev->cap_dev.stream[stream->conn_id]; - - if (pixm->pixelformat != t->out_fmt.pixelformat || - pixm->width != t->out_fmt.width / 4 || - pixm->height != t->out_fmt.height / 4) { - v4l2_warn(&dev->v4l2_dev, - "%s from %s, force to %dx%d %c%c%c%c\n", - node->vdev.name, t->vnode.vdev.name, - t->out_fmt.width / 4, t->out_fmt.height / 4, - t->out_fmt.pixelformat, - t->out_fmt.pixelformat >> 8, - t->out_fmt.pixelformat >> 16, - t->out_fmt.pixelformat >> 24); - pixm->pixelformat = t->out_fmt.pixelformat; - pixm->width = t->out_fmt.width / 4; - pixm->height = t->out_fmt.height / 4; - } - } else if (stream->id == RKISP_STREAM_LUMA) { - struct v4l2_rect *out_crop = &dev->isp_sdev.out_crop; - bool bigmode = rkisp_params_check_bigmode(&dev->params_vdev); - u32 div = bigmode ? 32 : 16; - - pixm->width = out_crop->width / div; - pixm->height = out_crop->height / div; - } - pixm->num_planes = fmt->mplanes; pixm->field = V4L2_FIELD_NONE; /* get quantization from ispsd */ @@ -1223,7 +1222,7 @@ static int rkisp_enum_framesizes(struct file *file, void *prov, const struct stream_config *config = stream->config; struct v4l2_frmsize_stepwise *s = &fsize->stepwise; struct v4l2_frmsize_discrete *d = &fsize->discrete; - const struct ispsd_out_fmt *input_isp_fmt; + struct rkisp_device *dev = stream->ispdev; struct v4l2_rect max_rsz; if (fsize->index != 0) @@ -1232,10 +1231,15 @@ static int rkisp_enum_framesizes(struct file *file, void *prov, if (!find_fmt(stream, fsize->pixel_format)) return -EINVAL; - restrict_rsz_resolution(stream->ispdev, config, &max_rsz); + restrict_rsz_resolution(stream, config, &max_rsz); - input_isp_fmt = rkisp_get_ispsd_out_fmt(&stream->ispdev->isp_sdev); - if (input_isp_fmt->fmt_type == FMT_BAYER) { + if (stream->out_isp_fmt.fmt_type == FMT_BAYER || + stream->id == RKISP_STREAM_FBC || + stream->id == RKISP_STREAM_BPDS || + stream->id == RKISP_STREAM_MPDS || + stream->id == RKISP_STREAM_LUMA || + stream->id == RKISP_STREAM_VIR || + (stream->id == RKISP_STREAM_BP && dev->hw_dev->isp_ver == ISP_V30)) { fsize->type = V4L2_FRMSIZE_TYPE_DISCRETE; d->width = max_rsz.width; d->height = max_rsz.height; @@ -1652,6 +1656,7 @@ static struct v4l2_rect *rkisp_update_crop(struct rkisp_stream *stream, "try horizontal center crop(%d,%d)/%dx%d for dual isp\n", sel->left, sel->top, sel->width, sel->height); } + stream->is_crop_upd = true; return sel; } @@ -1659,25 +1664,17 @@ static int rkisp_s_selection(struct file *file, void *prv, struct v4l2_selection *sel) { struct rkisp_stream *stream = video_drvdata(file); - struct video_device *vdev = &stream->vnode.vdev; - struct rkisp_vdev_node *node = vdev_to_node(vdev); struct rkisp_device *dev = stream->ispdev; struct v4l2_rect *dcrop = &stream->dcrop; const struct v4l2_rect *input_win; - if (vb2_is_busy(&node->buf_queue)) { - v4l2_err(&dev->v4l2_dev, "%s queue busy\n", __func__); - return -EBUSY; - } - - input_win = rkisp_get_isp_sd_win(&dev->isp_sdev); - if (sel->target != V4L2_SEL_TGT_CROP) return -EINVAL; if (sel->flags != 0) return -EINVAL; + input_win = rkisp_get_isp_sd_win(&dev->isp_sdev); *dcrop = *rkisp_update_crop(stream, &sel->r, input_win); v4l2_dbg(1, rkisp_debug, &dev->v4l2_dev, "stream %d crop(%d,%d)/%dx%d\n", stream->id, diff --git a/drivers/media/platform/rockchip/isp/capture.h b/drivers/media/platform/rockchip/isp/capture.h index 5cff46494179..b310012bf066 100644 --- a/drivers/media/platform/rockchip/isp/capture.h +++ b/drivers/media/platform/rockchip/isp/capture.h @@ -262,6 +262,7 @@ struct rkisp_stream { bool is_mf_upd; bool is_flip; bool is_pause; + bool is_crop_upd; wait_queue_head_t done; unsigned int burst; atomic_t sequence; diff --git a/drivers/media/platform/rockchip/isp/capture_v32.c b/drivers/media/platform/rockchip/isp/capture_v32.c index 715c40b61af2..2b3262d5e992 100644 --- a/drivers/media/platform/rockchip/isp/capture_v32.c +++ b/drivers/media/platform/rockchip/isp/capture_v32.c @@ -995,6 +995,12 @@ static int mi_frame_start(struct rkisp_stream *stream, u32 mis) /* readback start to update stream buf if null */ spin_lock_irqsave(&stream->vbq_lock, lock_flags); if (stream->streaming) { + /* only dynamic clipping and scaling at readback */ + if (!mis && stream->is_crop_upd) { + rkisp_stream_config_dcrop(stream, false); + rkisp_stream_config_rsz(stream, false); + stream->is_crop_upd = false; + } /* update buf for mulit sensor at readback */ if (!mis && !stream->ispdev->hw_dev->is_single && !stream->curr_buf && diff --git a/drivers/media/platform/rockchip/isp/regs.c b/drivers/media/platform/rockchip/isp/regs.c index 908e05d8c6a0..fd77e13c4d4b 100644 --- a/drivers/media/platform/rockchip/isp/regs.c +++ b/drivers/media/platform/rockchip/isp/regs.c @@ -322,7 +322,5 @@ void rkisp_disable_rsz(struct rkisp_stream *stream, bool async) bool is_unite = stream->ispdev->hw_dev->is_unite; rkisp_unite_write(stream->ispdev, stream->config->rsz.ctrl, 0, false, is_unite); - - if (!async) - update_rsz_shadow(stream, async); + update_rsz_shadow(stream, async); }