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:
@ -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;
|
||||
|
||||
@ -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, ¶ms->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(¶ms_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(¶ms_buf->queue, ¶ms_vdev->params);
|
||||
spin_unlock_irqrestore(¶ms_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;
|
||||
}
|
||||
|
||||
@ -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;
|
||||
};
|
||||
|
||||
|
||||
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -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;
|
||||
|
||||
@ -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,
|
||||
|
||||
@ -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 {
|
||||
|
||||
Reference in New Issue
Block a user