diff --git a/drivers/media/platform/rockchip/isp/capture.c b/drivers/media/platform/rockchip/isp/capture.c index 3eec58894253..273e46b1e359 100644 --- a/drivers/media/platform/rockchip/isp/capture.c +++ b/drivers/media/platform/rockchip/isp/capture.c @@ -1481,6 +1481,24 @@ static int rkisp_get_fps(struct rkisp_stream *stream, int *fps) return rkisp_rockit_fps_get(fps, stream); } +static int rkisp_get_tb_stream_info(struct rkisp_stream *stream, + struct rkisp_tb_stream_info *info) +{ + struct rkisp_device *dev = stream->ispdev; + + if (stream->id != RKISP_STREAM_MP) { + v4l2_err(&dev->v4l2_dev, "fast only support for MP\n"); + return -EINVAL; + } + + if (!dev->tb_stream_info.buf_max) { + v4l2_err(&dev->v4l2_dev, "thunderboot no enough memory for image\n"); + return -EINVAL; + } + memcpy(info, &dev->tb_stream_info, sizeof(*info)); + return 0; +} + static long rkisp_ioctl_default(struct file *file, void *fh, bool valid_prio, unsigned int cmd, void *arg) { @@ -1545,6 +1563,9 @@ static long rkisp_ioctl_default(struct file *file, void *fh, case RKISP_CMD_GET_FPS: ret = rkisp_get_fps(stream, arg); break; + case RKISP_CMD_GET_TB_STREAM_INFO: + ret = rkisp_get_tb_stream_info(stream, arg); + break; default: ret = -EINVAL; } @@ -1801,6 +1822,8 @@ static void rkisp_stream_fast(struct work_struct *work) struct rkisp_stream *stream = &cap_dev->stream[0]; struct vb2_queue *q = &stream->vnode.buf_queue; struct rkisp_device *ispdev = cap_dev->ispdev; + struct rkisp_tb_stream_info *info = &ispdev->tb_stream_info; + u32 i; v4l2_pipeline_pm_get(&stream->vnode.vdev.entity); rkisp_chk_tb_over(ispdev); @@ -1810,12 +1833,23 @@ static void rkisp_stream_fast(struct work_struct *work) } stream->is_pre_on = true; stream->is_using_resmem = true; - ispdev->resmem_addr_curr = ispdev->resmem_addr; - if (ispdev->resmem_size < stream->out_fmt.plane_fmt[0].sizeimage) { + info->width = stream->out_fmt.width; + info->height = stream->out_fmt.height; + info->bytesperline = stream->out_fmt.plane_fmt[0].bytesperline; + info->frame_size = info->bytesperline * ALIGN(info->height, 16) * 3 / 2; + info->buf_max = ispdev->resmem_size / info->frame_size; + if (!info->buf_max) { stream->is_using_resmem = false; v4l2_warn(&ispdev->v4l2_dev, "resmem size:%zu no enough for image:%d\n", - ispdev->resmem_size, stream->out_fmt.plane_fmt[0].sizeimage); + ispdev->resmem_size, info->frame_size); + } else { + ispdev->tb_addr_idx = 0; + info->buf_cnt = 0; + if (info->buf_max > RKISP_TB_STREAM_BUF_MAX) + info->buf_max = RKISP_TB_STREAM_BUF_MAX; + for (i = 0; i < info->buf_max; i++) + info->buf[i].dma_addr = ispdev->resmem_addr + i * info->frame_size; } q->ops->start_streaming(q, 1); } diff --git a/drivers/media/platform/rockchip/isp/capture_v32.c b/drivers/media/platform/rockchip/isp/capture_v32.c index 753b01be3b3c..cbd18d405fad 100644 --- a/drivers/media/platform/rockchip/isp/capture_v32.c +++ b/drivers/media/platform/rockchip/isp/capture_v32.c @@ -799,20 +799,16 @@ static void update_mi(struct rkisp_stream *stream) } } else if (stream->is_using_resmem) { /* resmem for fast stream NV12 output */ - dma_addr_t max_addr = dev->resmem_addr + dev->resmem_size; - u32 bytesperline = stream->out_fmt.plane_fmt[0].bytesperline; - u32 buf_size = bytesperline * ALIGN(stream->out_fmt.height, 16) * 3 / 2; - reg = stream->config->mi.y_base_ad_init; - val = dev->resmem_addr_curr; + val = dev->tb_stream_info.buf[dev->tb_addr_idx].dma_addr; rkisp_write(dev, reg, val, false); reg = stream->config->mi.cb_base_ad_init; - val += bytesperline * stream->out_fmt.height; + val += dev->tb_stream_info.bytesperline * stream->out_fmt.height; rkisp_write(dev, reg, val, false); - if (dev->resmem_addr_curr + buf_size * 2 <= max_addr) - dev->resmem_addr_curr += buf_size; + if (dev->tb_addr_idx < dev->tb_stream_info.buf_max - 1) + dev->tb_addr_idx++; } else if (!stream->is_pause) { stream->is_pause = true; stream->ops->disable_mi(stream); @@ -1759,6 +1755,17 @@ void rkisp_mi_v32_isr(u32 mis_val, struct rkisp_device *dev) stream->dbg.timestamp = ns; stream->dbg.id = seq; + if (stream->is_using_resmem) { + struct rkisp_tb_stream_info *tb_info = &dev->tb_stream_info; + u32 idx; + + if (tb_info->buf_cnt < tb_info->buf_max) + tb_info->buf_cnt++; + idx = tb_info->buf_cnt - 1; + dev->tb_stream_info.buf[idx].sequence = seq; + dev->tb_stream_info.buf[idx].timestamp = ns; + } + if (stream->stopping) { /* * Make sure stream is actually stopped, whose state diff --git a/drivers/media/platform/rockchip/isp/dev.h b/drivers/media/platform/rockchip/isp/dev.h index d6de18d3be3c..cec4216697f8 100644 --- a/drivers/media/platform/rockchip/isp/dev.h +++ b/drivers/media/platform/rockchip/isp/dev.h @@ -210,12 +210,15 @@ struct rkisp_device { struct mutex apilock; /* mutex to serialize the calls of stream */ struct mutex iqlock; /* mutex to serialize the calls of iq */ wait_queue_head_t sync_onoff; + dma_addr_t resmem_addr; phys_addr_t resmem_pa; - dma_addr_t resmem_addr_curr; size_t resmem_size; struct rkisp_thunderboot_resmem_head tb_head; bool is_thunderboot; + struct rkisp_tb_stream_info tb_stream_info; + unsigned int tb_addr_idx; + int dev_id; unsigned int skip_frame; unsigned int irq_ends; diff --git a/include/uapi/linux/rkisp2-config.h b/include/uapi/linux/rkisp2-config.h index e34be3ff2b04..c08145189a84 100644 --- a/include/uapi/linux/rkisp2-config.h +++ b/include/uapi/linux/rkisp2-config.h @@ -86,6 +86,9 @@ #define RKISP_CMD_GET_FPS \ _IOR('V', BASE_VIDIOC_PRIVATE + 110, int) + +#define RKISP_CMD_GET_TB_STREAM_INFO \ + _IOR('V', BASE_VIDIOC_PRIVATE + 111, struct rkisp_tb_stream_info) /*************************************************************/ #define ISP2X_ID_DPCC (0) @@ -368,6 +371,28 @@ struct rkisp_mirror_flip { unsigned char flip; } __attribute__ ((packed)); +#define RKISP_TB_STREAM_BUF_MAX 5 +struct rkisp_tb_stream_buf { + unsigned int dma_addr; + unsigned int sequence; + long long timestamp; +} __attribute__ ((packed)); + +/* struct rkisp_tb_stream_info + * frame_size: nv12 frame buf size, bytesperline * height_16align * 1.5 + * buf_max: memory size / frame_size + * buf_cnt: the num of frame write to buf. + */ +struct rkisp_tb_stream_info { + unsigned int width; + unsigned int height; + unsigned int bytesperline; + unsigned int frame_size; + unsigned int buf_max; + unsigned int buf_cnt; + struct rkisp_tb_stream_buf buf[RKISP_TB_STREAM_BUF_MAX]; +} __attribute__ ((packed)); + /* trigger event mode * T_TRY: trigger maybe with retry * T_TRY_YES: trigger to retry