From 0948e63218e00e012d8aa72a7344477e2c4262be Mon Sep 17 00:00:00 2001 From: Cai YiWei Date: Tue, 2 Mar 2021 16:22:39 +0800 Subject: [PATCH] media: rockchip: ispp: support fec/orb image stabilization Change-Id: Idf6b56d44bf9ab0c0137ffaca26436752f30b57d Signed-off-by: Cai YiWei --- drivers/media/platform/rockchip/ispp/ispp.c | 3 + drivers/media/platform/rockchip/ispp/params.c | 55 ++++++++----- drivers/media/platform/rockchip/ispp/params.h | 4 +- drivers/media/platform/rockchip/ispp/stats.c | 9 ++- drivers/media/platform/rockchip/ispp/stream.c | 79 ++++++++++++++++--- drivers/media/platform/rockchip/ispp/stream.h | 5 +- include/uapi/linux/rkispp-config.h | 11 ++- 7 files changed, 125 insertions(+), 41 deletions(-) diff --git a/drivers/media/platform/rockchip/ispp/ispp.c b/drivers/media/platform/rockchip/ispp/ispp.c index 51cc7be6da1b..b07806100f3f 100644 --- a/drivers/media/platform/rockchip/ispp/ispp.c +++ b/drivers/media/platform/rockchip/ispp/ispp.c @@ -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; diff --git a/drivers/media/platform/rockchip/ispp/params.c b/drivers/media/platform/rockchip/ispp/params.c index 09e1e6c84c30..d064a61496c0 100644 --- a/drivers/media/platform/rockchip/ispp/params.c +++ b/drivers/media/platform/rockchip/ispp/params.c @@ -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; } diff --git a/drivers/media/platform/rockchip/ispp/params.h b/drivers/media/platform/rockchip/ispp/params.h index ac48a488e1dc..d624f86e4e0c 100644 --- a/drivers/media/platform/rockchip/ispp/params.h +++ b/drivers/media/platform/rockchip/ispp/params.h @@ -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; }; diff --git a/drivers/media/platform/rockchip/ispp/stats.c b/drivers/media/platform/rockchip/ispp/stats.c index 1a1e978d5542..6ce870e03092 100644 --- a/drivers/media/platform/rockchip/ispp/stats.c +++ b/drivers/media/platform/rockchip/ispp/stats.c @@ -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); } } diff --git a/drivers/media/platform/rockchip/ispp/stream.c b/drivers/media/platform/rockchip/ispp/stream.c index a344fe2ea5c8..c5f1107ebb82 100644 --- a/drivers/media/platform/rockchip/ispp/stream.c +++ b/drivers/media/platform/rockchip/ispp/stream.c @@ -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; diff --git a/drivers/media/platform/rockchip/ispp/stream.h b/drivers/media/platform/rockchip/ispp/stream.h index ffdc61d886bf..70c3e2c27b8e 100644 --- a/drivers/media/platform/rockchip/ispp/stream.h +++ b/drivers/media/platform/rockchip/ispp/stream.h @@ -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, diff --git a/include/uapi/linux/rkispp-config.h b/include/uapi/linux/rkispp-config.h index 8d9d31e92906..0e6dfc678dbe 100644 --- a/include/uapi/linux/rkispp-config.h +++ b/include/uapi/linux/rkispp-config.h @@ -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 {