media: rockchip: ispp: fec to support output size crop by mesh

add rkispp-subdev pad2:Source set format API to support fec
crop output size by mesh size.

Change-Id: I8857547d1dc07ff033a50b1dc7bc2079a9221b12
Signed-off-by: Cai YiWei <cyw@rock-chips.com>
This commit is contained in:
Cai YiWei
2022-07-29 16:41:37 +08:00
committed by Tao Huang
parent 36d10fca69
commit bbce16690e
3 changed files with 36 additions and 114 deletions

View File

@@ -139,10 +139,15 @@ static int rkispp_sd_get_fmt(struct v4l2_subdev *sd,
ispp_fmt = find_fmt(fmt->format.code);
if (!ispp_fmt)
goto err;
if (ispp_sdev->in_fmt.width != mf->width ||
ispp_sdev->in_fmt.height != mf->height) {
ispp_sdev->out_fmt = *ispp_fmt;
ispp_sdev->out_fmt.width = mf->width;
ispp_sdev->out_fmt.height = mf->height;
}
ispp_sdev->in_fmt = *mf;
ispp_sdev->out_fmt = *ispp_fmt;
}
} else if (fmt->pad == RKISPP_PAD_SOURCE) {
} else {
*mf = ispp_sdev->in_fmt;
mf->width = ispp_sdev->out_fmt.width;
mf->height = ispp_sdev->out_fmt.height;
@@ -183,87 +188,6 @@ static int rkispp_sd_set_fmt(struct v4l2_subdev *sd,
return 0;
}
static int rkispp_sd_get_selection(struct v4l2_subdev *sd,
struct v4l2_subdev_pad_config *cfg,
struct v4l2_subdev_selection *sel)
{
struct rkispp_subdev *ispp_sdev = v4l2_get_subdevdata(sd);
struct v4l2_rect *crop;
int ret = 0;
if (!sel)
goto err;
if (sel->pad != RKISPP_PAD_SINK)
goto err;
crop = &sel->r;
if (sel->which == V4L2_SUBDEV_FORMAT_TRY) {
if (!cfg)
goto err;
crop = v4l2_subdev_get_try_crop(sd, cfg, sel->pad);
}
if (ispp_sdev->dev->inp != INP_ISP) {
crop->left = 0;
crop->top = 0;
crop->width = ispp_sdev->in_fmt.width;
crop->height = ispp_sdev->in_fmt.height;
return 0;
}
ret = v4l2_subdev_call(ispp_sdev->remote_sd,
pad, get_selection, cfg, sel);
if (!ret && sel->target == V4L2_SEL_TGT_CROP) {
ispp_sdev->out_fmt.width = crop->width;
ispp_sdev->out_fmt.height = crop->height;
}
return ret;
err:
return -EINVAL;
}
static int rkispp_sd_set_selection(struct v4l2_subdev *sd,
struct v4l2_subdev_pad_config *cfg,
struct v4l2_subdev_selection *sel)
{
struct rkispp_subdev *ispp_sdev = v4l2_get_subdevdata(sd);
struct v4l2_rect *crop;
int ret = 0;
if (!sel)
goto err;
if (sel->pad != RKISPP_PAD_SINK ||
sel->target != V4L2_SEL_TGT_CROP)
goto err;
crop = &sel->r;
if (sel->which == V4L2_SUBDEV_FORMAT_TRY) {
if (!cfg)
goto err;
crop = v4l2_subdev_get_try_crop(sd, cfg, sel->pad);
}
if (ispp_sdev->dev->inp != INP_ISP) {
crop->left = 0;
crop->top = 0;
crop->width = ispp_sdev->in_fmt.width;
crop->height = ispp_sdev->in_fmt.height;
return 0;
}
ret = v4l2_subdev_call(ispp_sdev->remote_sd,
pad, set_selection, cfg, sel);
if (!ret) {
ispp_sdev->out_fmt.width = crop->width;
ispp_sdev->out_fmt.height = crop->height;
}
return ret;
err:
return -EINVAL;
}
static int rkispp_sd_s_stream(struct v4l2_subdev *sd, int on)
{
struct rkispp_subdev *ispp_sdev = v4l2_get_subdevdata(sd);
@@ -338,7 +262,6 @@ static int rkispp_sd_s_power(struct v4l2_subdev *sd, int on)
if (on) {
if (ispp_dev->inp == INP_ISP) {
struct v4l2_subdev_format fmt;
struct v4l2_subdev_selection sel;
/* update format, if ispp input change */
fmt.pad = RKISPP_PAD_SINK;
@@ -350,17 +273,6 @@ static int rkispp_sd_s_power(struct v4l2_subdev *sd, int on)
__func__, ret);
return ret;
}
sel.pad = RKISPP_PAD_SINK;
sel.target = V4L2_SEL_TGT_CROP;
sel.which = V4L2_SUBDEV_FORMAT_ACTIVE;
ret = v4l2_subdev_call(sd, pad,
get_selection, NULL, &sel);
if (ret) {
v4l2_err(&ispp_dev->v4l2_dev,
"%s get crop fail:%d\n",
__func__, ret);
return ret;
}
ret = v4l2_subdev_call(ispp_sdev->remote_sd,
core, s_power, 1);
@@ -507,8 +419,6 @@ static const struct media_entity_operations rkispp_sd_media_ops = {
static const struct v4l2_subdev_pad_ops rkispp_sd_pad_ops = {
.get_fmt = rkispp_sd_get_fmt,
.set_fmt = rkispp_sd_set_fmt,
.get_selection = rkispp_sd_get_selection,
.set_selection = rkispp_sd_set_selection,
};
static const struct v4l2_subdev_video_ops rkispp_sd_video_ops = {

View File

@@ -7,6 +7,8 @@
#include "common.h"
#include "params.h"
#define RKISPP_FEC_BUF_MAX 7
struct rkispp_stream;
/*
@@ -86,7 +88,7 @@ struct in_tnr_buf {
struct in_nr_buf {
struct rkispp_dummy_buffer tmp_yuv;
struct rkispp_dummy_buffer wr[RKISPP_BUF_MAX];
struct rkispp_dummy_buffer wr[RKISPP_FEC_BUF_MAX];
};
struct tnr_module {
@@ -228,7 +230,6 @@ struct rkispp_vir_cpy {
/* rkispp stream device */
struct rkispp_stream_vdev {
struct rkispp_stream stream[STREAM_MAX];
struct rkispp_isp_buf_pool pool[RKISPP_BUF_POOL_MAX];
struct tnr_module tnr;
struct nr_module nr;
struct fec_module fec;

View File

@@ -282,8 +282,8 @@ static int config_tnr(struct rkispp_device *dev)
fmt = dev->isp_mode & (FMT_YUV422 | FMT_FBC);
}
width = dev->ispp_sdev.out_fmt.width;
height = dev->ispp_sdev.out_fmt.height;
width = dev->ispp_sdev.in_fmt.width;
height = dev->ispp_sdev.in_fmt.height;
max_w = hw->max_in.w ? hw->max_in.w : width;
max_h = hw->max_in.h ? hw->max_in.h : height;
w = (fmt & FMT_FBC) ? ALIGN(max_w, 16) : max_w;
@@ -416,10 +416,18 @@ static int nr_init_buf(struct rkispp_device *dev, u32 size)
{
struct rkispp_stream_vdev *vdev = &dev->stream_vdev;
struct rkispp_dummy_buffer *buf;
int i, ret, cnt = 0;
int i, ret, cnt;
if (vdev->module_ens & ISPP_MODULE_FEC)
cnt = vdev->is_done_early ? 1 : RKISPP_BUF_MAX;
switch (vdev->module_ens & ISPP_MODULE_FEC_ST) {
case ISPP_MODULE_FEC_ST:
cnt = RKISPP_FEC_BUF_MAX;
break;
case ISPP_MODULE_FEC:
cnt = RKISPP_BUF_MAX;
break;
default:
cnt = 0;
}
for (i = 0; i < cnt; i++) {
buf = &vdev->nr.buf.wr[i];
@@ -431,7 +439,7 @@ static int nr_init_buf(struct rkispp_device *dev, u32 size)
}
buf = &vdev->nr.buf.tmp_yuv;
cnt = DIV_ROUND_UP(dev->ispp_sdev.out_fmt.width, 32);
cnt = DIV_ROUND_UP(dev->ispp_sdev.in_fmt.width, 32);
buf->size = PAGE_ALIGN(cnt * 42 * 32);
ret = rkispp_allow_buffer(dev, buf);
if (ret)
@@ -468,8 +476,8 @@ static int config_nr_shp(struct rkispp_device *dev)
fmt = dev->isp_mode & (FMT_YUV422 | FMT_FBC);
}
width = dev->ispp_sdev.out_fmt.width;
height = dev->ispp_sdev.out_fmt.height;
width = dev->ispp_sdev.in_fmt.width;
height = dev->ispp_sdev.in_fmt.height;
w = width;
h = height;
max_w = hw->max_in.w ? hw->max_in.w : w;
@@ -598,7 +606,8 @@ static int config_fec(struct rkispp_device *dev)
{
struct rkispp_stream_vdev *vdev;
struct rkispp_stream *stream = NULL;
u32 width, height, fmt, mult = 1;
u32 in_width, in_height, fmt, mult = 1;
u32 out_width, out_height;
vdev = &dev->stream_vdev;
vdev->fec.is_end = true;
@@ -612,8 +621,10 @@ static int config_fec(struct rkispp_device *dev)
fmt = dev->isp_mode & FMT_YUV422;
}
width = dev->ispp_sdev.out_fmt.width;
height = dev->ispp_sdev.out_fmt.height;
in_width = dev->ispp_sdev.in_fmt.width;
in_height = dev->ispp_sdev.in_fmt.height;
out_width = dev->ispp_sdev.out_fmt.width;
out_height = dev->ispp_sdev.out_fmt.height;
if (vdev->module_ens & (ISPP_MODULE_NR | ISPP_MODULE_SHP)) {
rkispp_write(dev, RKISPP_FEC_RD_Y_BASE,
@@ -631,8 +642,8 @@ static int config_fec(struct rkispp_device *dev)
if (fmt & FMT_YUYV)
mult = 2;
rkispp_set_bits(dev, RKISPP_FEC_CTRL, FMT_RD_MASK, fmt);
rkispp_write(dev, RKISPP_FEC_RD_VIR_STRIDE, ALIGN(width * mult, 16) >> 2);
rkispp_write(dev, RKISPP_FEC_DST_SIZE, height << 16 | width);
rkispp_write(dev, RKISPP_FEC_RD_VIR_STRIDE, ALIGN(in_width * mult, 16) >> 2);
rkispp_write(dev, RKISPP_FEC_PIC_SIZE, out_height << 16 | out_width);
rkispp_set_bits(dev, RKISPP_CTRL_QUICK, 0, GLB_FEC2SCL_EN);
if (vdev->monitor.is_en) {
@@ -640,8 +651,8 @@ static int config_fec(struct rkispp_device *dev)
schedule_work(&vdev->monitor.fec.work);
}
v4l2_dbg(1, rkispp_debug, &dev->v4l2_dev,
"%s size:%dx%d ctrl:0x%x core_ctrl:0x%x\n",
__func__, width, height,
"%s size:%dx%d->%dx%d ctrl:0x%x core_ctrl:0x%x\n",
__func__, in_width, in_height, out_width, out_height,
rkispp_read(dev, RKISPP_FEC_CTRL),
rkispp_read(dev, RKISPP_FEC_CORE_CTRL));
return 0;