media: rockchip: ispp: support fec/orb image stabilization

Change-Id: Idf6b56d44bf9ab0c0137ffaca26436752f30b57d
Signed-off-by: Cai YiWei <cyw@rock-chips.com>
This commit is contained in:
Cai YiWei
2021-03-02 16:22:39 +08:00
parent c0b2acc691
commit 0948e63218
7 changed files with 125 additions and 41 deletions

View File

@ -343,6 +343,9 @@ static long rkispp_ioctl(struct v4l2_subdev *sd, unsigned int cmd, void *arg)
case RKISPP_CMD_GET_TNRBUF_FD:
ret = rkispp_get_tnrbuf_fd(ispp_dev, (struct rkispp_buf_idxfd *)arg);
break;
case RKISPP_CMD_GET_NRBUF_FD:
ret = rkispp_get_nrbuf_fd(ispp_dev, (struct rkispp_buf_idxfd *)arg);
break;
case RKISPP_CMD_TRIGGER_MODE:
rkispp_set_trigger_mode(ispp_dev, (struct rkispp_trigger_mode *)arg);
break;

View File

@ -527,11 +527,11 @@ static void fec_config(struct rkispp_params_vdev *params_vdev,
return;
}
for (i = 0; i < FEC_MESH_BUF_NUM; i++) {
for (i = 0; i < params_vdev->buf_cnt; i++) {
if (arg->buf_fd == params_vdev->buf_fec[i].dma_fd)
break;
}
if (i == FEC_MESH_BUF_NUM) {
if (i == params_vdev->buf_cnt) {
dev_err(dev->dev, "cannot find fec buf fd(%d)\n", arg->buf_fd);
return;
}
@ -705,6 +705,13 @@ rkispp_param_init_fecbuf(struct rkispp_params_vdev *params,
u32 width, height, mesh_size, buf_size;
int i, ret;
if (fecsize->buf_cnt > FEC_MESH_BUF_MAX)
params->buf_cnt = FEC_MESH_BUF_MAX;
else if (fecsize->buf_cnt > 0)
params->buf_cnt = fecsize->buf_cnt;
else
params->buf_cnt = FEC_MESH_BUF_NUM;
width = fecsize->meas_width;
height = fecsize->meas_height;
mesh_size = cal_fec_mesh(width, height, fecsize->meas_mode);
@ -712,7 +719,7 @@ rkispp_param_init_fecbuf(struct rkispp_params_vdev *params,
buf_size += 2 * (ALIGN(mesh_size * 2, 16) + ALIGN(mesh_size, 16));
params->buf_fec_idx = 0;
for (i = 0; i < FEC_MESH_BUF_NUM; i++) {
for (i = 0; i < params->buf_cnt; i++) {
params->buf_fec[i].is_need_vaddr = true;
params->buf_fec[i].is_need_dbuf = true;
params->buf_fec[i].is_need_dmafd = true;
@ -758,7 +765,7 @@ rkispp_param_deinit_fecbuf(struct rkispp_params_vdev *params)
int i;
params->buf_fec_idx = 0;
for (i = 0; i < FEC_MESH_BUF_NUM; i++)
for (i = 0; i < FEC_MESH_BUF_MAX; i++)
rkispp_free_buffer(params->dev, &params->buf_fec[i]);
}
@ -802,9 +809,7 @@ static void rkispp_params_vb2_buf_queue(struct vb2_buffer *vb)
struct rkispp_params_vdev *params_vdev = vq->drv_priv;
struct rkispp_device *dev = params_vdev->dev;
struct rkispp_stream_vdev *vdev = &dev->stream_vdev;
void *buf_rd = NULL;
unsigned long flags;
u32 module;
spin_lock_irqsave(&params_vdev->config_lock, flags);
if (params_vdev->first_params) {
@ -819,25 +824,29 @@ static void rkispp_params_vb2_buf_queue(struct vb2_buffer *vb)
list_add_tail(&params_buf->queue, &params_vdev->params);
spin_unlock_irqrestore(&params_vdev->config_lock, flags);
switch (params_vdev->vdev_id) {
case PARAM_VDEV_TNR:
module = ISPP_MODULE_TNR;
break;
case PARAM_VDEV_NR:
module = ISPP_MODULE_NR;
if (params_vdev->vdev_id == PARAM_VDEV_NR) {
struct rkisp_ispp_buf *buf_rd = NULL;
spin_lock_irqsave(&vdev->tnr.buf_lock, flags);
if (!list_empty(&vdev->tnr.list_rpt)) {
buf_rd = list_first_entry(&vdev->tnr.list_rpt,
struct rkisp_ispp_buf, list);
list_del(&((struct rkisp_ispp_buf *)buf_rd)->list);
list_del(&buf_rd->list);
}
spin_unlock_irqrestore(&vdev->tnr.buf_lock, flags);
break;
case PARAM_VDEV_FEC:
default:
module = ISPP_MODULE_FEC;
rkispp_module_work_event(dev, buf_rd, NULL, ISPP_MODULE_NR, false);
} else if (params_vdev->vdev_id == PARAM_VDEV_FEC) {
struct rkispp_dummy_buffer *buf_rd = NULL;
spin_lock_irqsave(&vdev->nr.buf_lock, flags);
if (!list_empty(&vdev->nr.list_rpt)) {
buf_rd = list_first_entry(&vdev->nr.list_rpt,
struct rkispp_dummy_buffer, list);
list_del(&buf_rd->list);
list_add_tail(&buf_rd->list, &vdev->fec.list_rd);
}
spin_unlock_irqrestore(&vdev->nr.buf_lock, flags);
}
rkispp_module_work_event(dev, buf_rd, NULL, module, false);
}
static void rkispp_params_vb2_stop_streaming(struct vb2_queue *vq)
@ -978,7 +987,7 @@ static void fec_data_abandon(struct rkispp_params_vdev *vdev,
struct rkispp_fec_head *data;
int i;
for (i = 0; i < FEC_MESH_BUF_NUM; i++) {
for (i = 0; i < vdev->buf_cnt; i++) {
if (params->fec_cfg.buf_fd == vdev->buf_fec[i].dma_fd) {
data = (struct rkispp_fec_head *)vdev->buf_fec[i].vaddr;
if (data)
@ -1102,7 +1111,12 @@ void rkispp_params_get_fecbuf_inf(struct rkispp_params_vdev *params_vdev,
if (params_vdev->vdev_id != PARAM_VDEV_FEC)
return;
for (i = 0; i < FEC_MESH_BUF_NUM; i++) {
for (i = 0; i < FEC_MESH_BUF_MAX; i++) {
fecbuf->buf_fd[i] = -1;
fecbuf->buf_size[i] = 0;
}
for (i = 0; i < params_vdev->buf_cnt; i++) {
fecbuf->buf_fd[i] = params_vdev->buf_fec[i].dma_fd;
fecbuf->buf_size[i] = params_vdev->buf_fec[i].size;
}
@ -1140,6 +1154,7 @@ static int rkispp_register_params_vdev(struct rkispp_device *dev,
break;
case PARAM_VDEV_FEC:
default:
params_vdev->buf_cnt = FEC_MESH_BUF_NUM;
strncpy(vdev->name, "rkispp_fec_params", sizeof(vdev->name) - 1);
break;
}

View File

@ -33,9 +33,9 @@ struct rkispp_params_vdev {
bool first_params;
bool is_subs_evt;
struct rkispp_dummy_buffer buf_fec[FEC_MESH_BUF_NUM];
struct rkispp_dummy_buffer buf_fec[FEC_MESH_BUF_MAX];
u32 buf_fec_idx;
u32 buf_cnt;
enum rkispp_paramvdev_id vdev_id;
};

View File

@ -69,9 +69,16 @@ static int rkispp_stats_frame_end(struct rkispp_stats_vdev *stats_vdev)
nrbuf->total_num = readl(base + RKISPP_ORB_TOTAL_NUM);
nrbuf->frame_id = cur_frame_id;
nrbuf->image.index = -1;
if (vdev->nr.cur_wr) {
if (vdev->nr.cur_wr &&
(dev->stream_vdev.module_ens & ISPP_MODULE_FEC_ST) == ISPP_MODULE_FEC_ST) {
nrbuf->image.index = vdev->nr.cur_wr->index;
nrbuf->image.size = vdev->nr.cur_wr->size;
v4l2_dbg(3, rkispp_debug, &dev->v4l2_dev,
"%s frame:%d nr output buf index:%d fd:%d dma:0x%x\n",
__func__, cur_frame_id,
vdev->nr.cur_wr->index,
vdev->nr.cur_wr->dma_fd,
vdev->nr.cur_wr->dma_addr);
}
}

View File

@ -684,7 +684,7 @@ static void tnr_free_buf(struct rkispp_device *dev)
sizeof(struct rkispp_dummy_buffer); i++)
rkispp_free_buffer(dev, &vdev->tnr.buf.iir + i);
vdev->tnr.is_but_init = false;
vdev->tnr.is_buf_init = false;
vdev->tnr.is_trigger = false;
}
@ -742,7 +742,7 @@ static int tnr_init_buf(struct rkispp_device *dev,
if (ret < 0)
goto err;
vdev->tnr.is_but_init = true;
vdev->tnr.is_buf_init = true;
return 0;
err:
tnr_free_buf(dev);
@ -901,10 +901,15 @@ static void nr_free_buf(struct rkispp_device *dev)
vdev->nr.cur_wr = NULL;
while (!list_empty(list))
get_list_buf(list, false);
list = &vdev->nr.list_rpt;
while (!list_empty(list))
get_list_buf(list, false);
for (i = 0; i < sizeof(vdev->nr.buf) /
sizeof(struct rkispp_dummy_buffer); i++)
rkispp_free_buffer(dev, &vdev->nr.buf.tmp_yuv + i);
vdev->nr.is_buf_init = false;
}
static int nr_init_buf(struct rkispp_device *dev, u32 size)
@ -927,6 +932,10 @@ static int nr_init_buf(struct rkispp_device *dev, u32 size)
for (i = 0; i < cnt; i++) {
buf = &vdev->nr.buf.wr[i];
buf->size = size;
buf->index = i;
buf->is_need_dbuf = true;
buf->is_need_vaddr = true;
buf->is_need_dmafd = false;
ret = rkispp_allow_buffer(dev, buf);
if (ret)
goto err;
@ -939,6 +948,8 @@ static int nr_init_buf(struct rkispp_device *dev, u32 size)
ret = rkispp_allow_buffer(dev, buf);
if (ret)
goto err;
vdev->nr.is_buf_init = true;
return 0;
err:
nr_free_buf(dev);
@ -2628,8 +2639,11 @@ static void fec_work_event(struct rkispp_device *dev,
}
}
if (!dev->hw_dev->is_single)
if (!dev->hw_dev->is_single) {
rkispp_update_regs(dev, RKISPP_FEC, RKISPP_FEC_CROP);
rkispp_update_regs(dev, RKISPP_SCL0, RKISPP_SCL2_FACTOR);
}
writel(FEC_FORCE_UPD, base + RKISPP_CTRL_UPDATE);
if (vdev->nr.is_end) {
if (!dev->hw_dev->is_single)
@ -2746,7 +2760,7 @@ static void nr_work_event(struct rkispp_device *dev,
struct list_head *list;
struct dma_buf *dbuf;
unsigned long lock_flags = 0, lock_flags1 = 0;
bool is_start = false, is_quick = false;
bool is_start = false, is_quick = false, is_fec_event = false;
bool is_fec_en = (vdev->module_ens & ISPP_MODULE_FEC);
struct rkisp_ispp_reg *reg_buf = NULL;
u32 val;
@ -2766,7 +2780,7 @@ static void nr_work_event(struct rkispp_device *dev,
/* event from nr frame end */
if (!buf_rd && !buf_wr && is_isr) {
vdev->nr.is_end = true;
is_fec_event = true;
if (vdev->nr.cur_rd) {
/* nr read buf return to isp or tnr */
if (vdev->nr.cur_rd->is_isp && sd) {
@ -3037,13 +3051,21 @@ end:
* fec start working should after nr
* for scl will update by OTHER_FORCE_UPD
*/
if (buf_to_fec)
rkispp_module_work_event(dev, buf_to_fec, NULL,
ISPP_MODULE_FEC, is_isr);
if (buf_to_fec) {
if ((vdev->module_ens & ISPP_MODULE_FEC_ST) == ISPP_MODULE_FEC_ST) {
rkispp_finish_buffer(dev, buf_to_fec);
list_add_tail(&buf_to_fec->list, &dev->stream_vdev.nr.list_rpt);
buf_to_fec = NULL;
}
rkispp_module_work_event(dev, buf_to_fec, NULL, ISPP_MODULE_FEC, false);
} else if (!list_empty(&vdev->fec.list_rd) && is_fec_event) {
rkispp_module_work_event(dev, NULL, NULL, ISPP_MODULE_FEC, false);
}
spin_unlock_irqrestore(&vdev->nr.buf_lock, lock_flags);
if (is_fec_en && vdev->is_done_early &&
is_start && !dev->hw_dev->is_first)
is_start && !dev->hw_dev->is_first &&
(vdev->module_ens & ISPP_MODULE_FEC_ST) != ISPP_MODULE_FEC_ST)
hrtimer_start(&vdev->fec_qst,
ns_to_ktime(1000000),
HRTIMER_MODE_REL);
@ -3318,7 +3340,7 @@ int rkispp_get_tnrbuf_fd(struct rkispp_device *dev, struct rkispp_buf_idxfd *idx
int j, buf_idx, ret = 0;
spin_lock_irqsave(&vdev->tnr.buf_lock, lock_flags);
if (!vdev->tnr.is_but_init) {
if (!vdev->tnr.is_buf_init) {
spin_unlock_irqrestore(&vdev->tnr.buf_lock, lock_flags);
ret = -EAGAIN;
return ret;
@ -3368,6 +3390,34 @@ int rkispp_get_tnrbuf_fd(struct rkispp_device *dev, struct rkispp_buf_idxfd *idx
return ret;
}
int rkispp_get_nrbuf_fd(struct rkispp_device *dev, struct rkispp_buf_idxfd *idxfd)
{
struct rkispp_stream_vdev *vdev = &dev->stream_vdev;
struct rkispp_dummy_buffer *buf;
unsigned long lock_flags = 0;
int i, ret = 0;
spin_lock_irqsave(&vdev->nr.buf_lock, lock_flags);
if (!vdev->nr.is_buf_init) {
spin_unlock_irqrestore(&vdev->nr.buf_lock, lock_flags);
ret = -EAGAIN;
return ret;
}
spin_unlock_irqrestore(&vdev->nr.buf_lock, lock_flags);
for (i = 0; i < RKISPP_FEC_BUF_MAX; i++) {
buf = &vdev->nr.buf.wr[i];
if (!buf->dbuf)
break;
buf->dma_fd = dma_buf_fd(buf->dbuf, O_CLOEXEC);
get_dma_buf(buf->dbuf);
idxfd->index[i] = i;
idxfd->dmafd[i] = buf->dma_fd;
}
idxfd->buf_num = i;
return ret;
}
void rkispp_set_trigger_mode(struct rkispp_device *dev,
struct rkispp_trigger_mode *mode)
{
@ -3415,8 +3465,9 @@ void rkispp_module_work_event(struct rkispp_device *dev,
if (is_isr && !buf_rd && !buf_wr &&
((!is_fec_en && module == ISPP_MODULE_NR) ||
(is_fec_en &&
((module == ISPP_MODULE_NR && is_single) ||
(module == ISPP_MODULE_FEC && !is_single))))) {
((module == ISPP_MODULE_NR && (is_single ||
vdev->fec.is_end)) ||
(module == ISPP_MODULE_FEC && !is_single && vdev->fec.is_end))))) {
dev->stream_vdev.monitor.retry = 0;
rkispp_soft_reset(dev->hw_dev);
rkispp_event_handle(dev, CMD_QUEUE_DMABUF, NULL);
@ -3542,11 +3593,13 @@ int rkispp_register_stream_vdevs(struct rkispp_device *dev)
INIT_LIST_HEAD(&stream_vdev->tnr.list_rpt);
INIT_LIST_HEAD(&stream_vdev->nr.list_rd);
INIT_LIST_HEAD(&stream_vdev->nr.list_wr);
INIT_LIST_HEAD(&stream_vdev->nr.list_rpt);
INIT_LIST_HEAD(&stream_vdev->fec.list_rd);
spin_lock_init(&stream_vdev->tnr.buf_lock);
spin_lock_init(&stream_vdev->nr.buf_lock);
spin_lock_init(&stream_vdev->fec.buf_lock);
stream_vdev->tnr.is_but_init = false;
stream_vdev->tnr.is_buf_init = false;
stream_vdev->nr.is_buf_init = false;
hrtimer_init(&stream_vdev->fec_qst, CLOCK_MONOTONIC, HRTIMER_MODE_REL);
stream_vdev->fec_qst.function = rkispp_fec_do_early;

View File

@ -104,7 +104,7 @@ struct tnr_module {
u32 uv_offset;
bool is_end;
bool is_3to1;
bool is_but_init;
bool is_buf_init;
bool is_trigger;
};
@ -112,6 +112,7 @@ struct nr_module {
struct in_nr_buf buf;
struct list_head list_rd;
struct list_head list_wr;
struct list_head list_rpt;
spinlock_t buf_lock;
struct rkisp_ispp_buf *cur_rd;
struct rkispp_dummy_buffer *cur_wr;
@ -119,6 +120,7 @@ struct nr_module {
struct frame_debug_info dbg;
u32 uv_offset;
bool is_end;
bool is_buf_init;
};
struct fec_module {
@ -229,6 +231,7 @@ struct rkispp_stream_vdev {
};
int rkispp_get_tnrbuf_fd(struct rkispp_device *dev, struct rkispp_buf_idxfd *idxfd);
int rkispp_get_nrbuf_fd(struct rkispp_device *dev, struct rkispp_buf_idxfd *idxfd);
void rkispp_set_trigger_mode(struct rkispp_device *dev,
struct rkispp_trigger_mode *mode);
void rkispp_module_work_event(struct rkispp_device *dev,

View File

@ -77,8 +77,7 @@
#define ORB_BRIEF_NUM 15
#define ORB_DUMMY_NUM 13
#define FEC_MESH_XY_POINT_SIZE 6
#define FEC_MESH_XY_NUM 131072
#define FEC_MESH_BUF_MAX 7
#define FEC_MESH_BUF_NUM 2
#define MAX_BUF_IDXFD_NUM 64
@ -99,6 +98,9 @@
#define RKISPP_CMD_GET_TNRBUF_FD \
_IOR('V', BASE_VIDIOC_PRIVATE + 4, struct rkispp_buf_idxfd)
#define RKISPP_CMD_GET_NRBUF_FD \
_IOR('V', BASE_VIDIOC_PRIVATE + 5, struct rkispp_buf_idxfd)
/**independent fec video**/
#define RKISPP_CMD_FEC_IN_OUT \
_IOW('V', BASE_VIDIOC_PRIVATE + 10, struct rkispp_fec_in_out)
@ -281,14 +283,15 @@ enum rkispp_fecbuf_stat {
};
struct rkispp_fecbuf_info {
s32 buf_fd[FEC_MESH_BUF_NUM];
u32 buf_size[FEC_MESH_BUF_NUM];
s32 buf_fd[FEC_MESH_BUF_MAX];
u32 buf_size[FEC_MESH_BUF_MAX];
} __attribute__ ((packed));
struct rkispp_fecbuf_size {
u32 meas_width;
u32 meas_height;
u32 meas_mode;
int buf_cnt;
} __attribute__ ((packed));
struct rkispp_fec_head {