From f08082651fa2f3da9c51dc56c8df80bc0fbe725d Mon Sep 17 00:00:00 2001 From: Jacob Chen Date: Mon, 10 Jul 2017 10:43:08 +0800 Subject: [PATCH] media: isp: migrate isp driver to videobuf2 Verify the functionality of isp driver with sensor ov7750. V4l2n or gstreamer is suitable for test. Change-Id: I4f0cf68b84f4909dd1c132ec3506777f39d487ee Signed-off-by: Jacob Chen --- drivers/media/platform/rk-isp10/Kconfig | 5 +- drivers/media/platform/rk-isp10/cif_isp10.c | 304 ++++++++--- drivers/media/platform/rk-isp10/cif_isp10.h | 87 +++- .../rk-isp10/cif_isp10_img_src_v4l2-subdev.c | 5 + .../media/platform/rk-isp10/cif_isp10_isp.c | 242 ++++----- .../media/platform/rk-isp10/cif_isp10_isp.h | 7 +- .../platform/rk-isp10/cif_isp10_pltfrm.c | 249 ++++++++- .../platform/rk-isp10/cif_isp10_pltfrm.h | 3 +- .../media/platform/rk-isp10/cif_isp10_v4l2.c | 491 +++++++++--------- 9 files changed, 918 insertions(+), 475 deletions(-) diff --git a/drivers/media/platform/rk-isp10/Kconfig b/drivers/media/platform/rk-isp10/Kconfig index bb2679b79677..a51aac2410a2 100644 --- a/drivers/media/platform/rk-isp10/Kconfig +++ b/drivers/media/platform/rk-isp10/Kconfig @@ -1,9 +1,10 @@ config VIDEO_RK_CIF_ISP10 tristate "Rockchip cif isp10 camera sensors" depends on VIDEO_V4L2 && I2C + select VIDEOBUF2_CORE select VIDEOBUF_GEN - select VIDEOBUF_DMA_CONTIG - select VIDEOBUF_VMALLOC + select VIDEOBUF2_DMA_SG + select VIDEOBUF2_VMALLOC default n ---help--- diff --git a/drivers/media/platform/rk-isp10/cif_isp10.c b/drivers/media/platform/rk-isp10/cif_isp10.c index 3f1dd33a225d..dd44afe2bedf 100644 --- a/drivers/media/platform/rk-isp10/cif_isp10.c +++ b/drivers/media/platform/rk-isp10/cif_isp10.c @@ -15,7 +15,8 @@ */ #include -#include +#include +#include #include "cif_isp10_regs.h" #include "cif_isp10.h" #include @@ -157,6 +158,7 @@ static const unsigned char uvq_table_base_zigzag[] = { static struct cif_isp10_fmt cif_isp10_output_format[] = { /* ************* YUV422 ************* */ +// index 0 { .name = "YUV422-Interleaved", .fourcc = V4L2_PIX_FMT_YUYV, @@ -165,6 +167,7 @@ static struct cif_isp10_fmt cif_isp10_output_format[] = { .rotation = false, .overlay = false, }, +// index 1 { .name = "YUV422-Interleaved", .fourcc = V4L2_PIX_FMT_YUYV, @@ -173,6 +176,7 @@ static struct cif_isp10_fmt cif_isp10_output_format[] = { .rotation = false, .overlay = false, }, +// index 2 { .name = "YVU422-Interleaved", .fourcc = V4L2_PIX_FMT_UYVY, @@ -181,6 +185,7 @@ static struct cif_isp10_fmt cif_isp10_output_format[] = { .rotation = false, .overlay = false, }, +// index 3 { .name = "YUV422-Planar", .fourcc = V4L2_PIX_FMT_YUV422P, @@ -189,6 +194,7 @@ static struct cif_isp10_fmt cif_isp10_output_format[] = { .rotation = false, .overlay = false, }, +// index 4 { .name = "YUV422-Semi-Planar", .fourcc = V4L2_PIX_FMT_NV16, @@ -198,6 +204,7 @@ static struct cif_isp10_fmt cif_isp10_output_format[] = { .overlay = false, }, /* ************* YUV420 ************* */ +// index 5 { .name = "YUV420-Planar", .fourcc = V4L2_PIX_FMT_YUV420, @@ -206,6 +213,7 @@ static struct cif_isp10_fmt cif_isp10_output_format[] = { .rotation = false, .overlay = false, }, +// index 6 { .name = "YUV420-Planar", .fourcc = V4L2_PIX_FMT_YUV420, @@ -214,6 +222,7 @@ static struct cif_isp10_fmt cif_isp10_output_format[] = { .rotation = false, .overlay = false, }, +// index 7 { .name = "YVU420-Planar", .fourcc = V4L2_PIX_FMT_YVU420, @@ -222,6 +231,7 @@ static struct cif_isp10_fmt cif_isp10_output_format[] = { .rotation = false, .overlay = false, }, +// index 8 { .name = "YUV420-Semi-Planar", .fourcc = V4L2_PIX_FMT_NV12, @@ -230,6 +240,7 @@ static struct cif_isp10_fmt cif_isp10_output_format[] = { .rotation = false, .overlay = false, }, +// index 9 { .name = "YVU420-Semi-Planar", .fourcc = V4L2_PIX_FMT_NV21, @@ -239,6 +250,7 @@ static struct cif_isp10_fmt cif_isp10_output_format[] = { .overlay = false, }, /* ************* YUV400 ************* */ +// index 10 { .name = "YVU400-Grey-Planar", .fourcc = V4L2_PIX_FMT_GREY, @@ -248,6 +260,7 @@ static struct cif_isp10_fmt cif_isp10_output_format[] = { .overlay = false, }, /* ************* YUV444 ************* */ +// index 11 { .name = "YVU444-Planar", .fourcc = V4L2_PIX_FMT_YUV444, @@ -256,6 +269,7 @@ static struct cif_isp10_fmt cif_isp10_output_format[] = { .rotation = false, .overlay = false, }, +// index 12 { .name = "YVU444-Semi-Planar", .fourcc = V4L2_PIX_FMT_NV24, @@ -265,6 +279,7 @@ static struct cif_isp10_fmt cif_isp10_output_format[] = { .overlay = false, }, /* ************* JPEG ************* */ +// index 13 { .name = "JPEG", .fourcc = V4L2_PIX_FMT_JPEG, @@ -274,6 +289,7 @@ static struct cif_isp10_fmt cif_isp10_output_format[] = { .overlay = false, }, /* ************ RGB565 *********** */ +// index 14 { .name = "RGB565", .fourcc = V4L2_PIX_FMT_RGB565, @@ -283,6 +299,7 @@ static struct cif_isp10_fmt cif_isp10_output_format[] = { .overlay = false, }, /* ************ SGRBG8 *********** */ +// index 15 { .name = "SGRBG8", .fourcc = V4L2_PIX_FMT_SGRBG8, @@ -1134,6 +1151,7 @@ static int cif_isp10_img_src_select_strm_fmt( img_src_width = strm_fmt_desc.min_frmsize.width; img_src_height = strm_fmt_desc.min_frmsize.height; } + if ((img_src_width >= target_width) && (img_src_height >= target_height)) { u32 diff = abs( @@ -1192,6 +1210,23 @@ static int cif_isp10_img_src_select_strm_fmt( best_diff = diff; matching_format_found = true; } + // FIXME::GST set fomat(any@32768x32768) failed, force pass + } else { + request_strm_fmt.frm_fmt.width = + strm_fmt_desc.min_frmsize.width; + request_strm_fmt.frm_fmt.height = + strm_fmt_desc.min_frmsize.height; + request_strm_fmt.frm_fmt.std_id = + strm_fmt_desc.std_id; + request_strm_fmt.frm_fmt.pix_fmt = + strm_fmt_desc.pix_fmt; + request_strm_fmt.frm_intrvl.numerator = + strm_fmt_desc.min_intrvl.numerator; + request_strm_fmt.frm_intrvl.denominator = + strm_fmt_desc.min_intrvl.denominator; + request_strm_fmt.frm_fmt.defrect = + strm_fmt_desc.defrect; + matching_format_found = true; } } @@ -1913,7 +1948,6 @@ static int cif_isp10_config_mipi( mipi_ctrl = CIF_MIPI_CTRL_NUM_LANES( dev->config.cam_itf.cfg.mipi.nb_lanes - 1) | - CIF_MIPI_CTRL_ERR_SOT_HS_ENA | CIF_MIPI_CTRL_ERR_SOT_SYNC_HS_SKIP | CIF_MIPI_CTRL_SHUTDOWNLANES(shutdown_lanes) | CIF_MIPI_CTRL_ERR_SOT_SYNC_HS_ENA | @@ -2585,8 +2619,9 @@ static int cif_isp10_config_jpeg_enc( break; default: cif_isp10_pltfrm_pr_err(NULL, - "format %s not supported as input for JPEG encoder\n", - cif_isp10_pix_fmt_string(inp_fmt->pix_fmt)); + "format %s (%.8x) not supported as input for JPEG encoder\n", + cif_isp10_pix_fmt_string(inp_fmt->pix_fmt), + inp_fmt->pix_fmt); WARN_ON(1); break; } @@ -3247,7 +3282,7 @@ static int cif_isp10_config_cif( cif_id = cif_ioread32(dev->config.base_addr + CIF_VI_ID); dev->config.out_of_buffer_stall = - CIF_ISP10_ALWAYS_STALL_ON_NO_BUFS; + CIF_ISP10_ALWAYS_STALL_ON_NO_BUFS ? 1 : 0; cif_isp10_pltfrm_pr_dbg(dev->dev, "CIF_ID 0x%08x\n", cif_id); @@ -3377,6 +3412,13 @@ static void cif_isp10_init_stream( enum cif_isp10_stream_id stream_id) { struct cif_isp10_stream *stream = NULL; + struct cif_isp10_frm_fmt frm_fmt; + + frm_fmt.pix_fmt = CIF_YUV422I; + frm_fmt.width = dev->config.img_src_output.frm_fmt.width; + frm_fmt.height = dev->config.img_src_output.frm_fmt.height; + frm_fmt.stride = dev->config.img_src_output.frm_fmt.stride; + frm_fmt.quantization = 0; switch (stream_id) { case CIF_ISP10_STREAM_SP: @@ -3384,6 +3426,16 @@ static void cif_isp10_init_stream( dev->config.sp_config.rsz_config.ycflt_adjust = false; dev->config.sp_config.rsz_config.ism_adjust = false; dev->config.mi_config.sp.busy = false; + + // init default formats + dev->config.mi_config.sp.output = frm_fmt; + dev->config.mi_config.sp.llength = + cif_isp10_calc_llength( + frm_fmt.width, + frm_fmt.stride, + frm_fmt.pix_fmt); + + dev->sp_stream.updt_cfg = true; break; case CIF_ISP10_STREAM_MP: stream = &dev->mp_stream; @@ -3395,10 +3447,23 @@ static void cif_isp10_init_stream( dev->config.mp_config.rsz_config.ycflt_adjust = false; dev->config.mp_config.rsz_config.ism_adjust = false; dev->config.mi_config.mp.busy = false; + + // init default formats + dev->config.mi_config.mp.output = frm_fmt; + dev->config.mi_config.mp.output.stride = frm_fmt.stride; + + dev->config.mi_config.mp.llength = + cif_isp10_calc_llength( + frm_fmt.width, + frm_fmt.stride, + frm_fmt.pix_fmt); + + dev->mp_stream.updt_cfg = true; break; case CIF_ISP10_STREAM_DMA: stream = &dev->dma_stream; dev->config.mi_config.dma.busy = false; + dev->dma_stream.updt_cfg = false; break; default: cif_isp10_pltfrm_pr_err(NULL, @@ -3410,12 +3475,17 @@ static void cif_isp10_init_stream( INIT_LIST_HEAD(&stream->buf_queue); stream->next_buf = NULL; stream->curr_buf = NULL; - stream->updt_cfg = false; stream->stop = false; stream->stall = false; cif_isp10_pltfrm_event_clear(dev->dev, &stream->done); - stream->state = CIF_ISP10_STATE_INACTIVE; + + if (stream->updt_cfg) { + stream->state = CIF_ISP10_STATE_READY; + cif_isp10_img_src_select_strm_fmt(dev); + } else { + stream->state = CIF_ISP10_STATE_INACTIVE; + } } static int cif_isp10_jpeg_gen_header( @@ -3900,6 +3970,10 @@ err: static void cif_isp10_dma_next_buff( struct cif_isp10_device *dev) { +#ifdef CIF_ISP10_MODE_DMA_SG + struct sg_table *sgt = NULL; +#endif + cif_isp10_pltfrm_pr_dbg(NULL, "\n"); if (!list_empty(&dev->dma_stream.buf_queue) && @@ -3908,12 +3982,21 @@ static void cif_isp10_dma_next_buff( WARN_ON(1); dev->dma_stream.curr_buf = list_first_entry(&dev->dma_stream.buf_queue, - struct videobuf_buffer, queue); + struct cif_isp10_buffer, queue); list_del(&dev->dma_stream.curr_buf->queue); - dev->dma_stream.curr_buf->state = VIDEOBUF_ACTIVE; + +#ifdef CIF_ISP10_MODE_DMA_CONTIG + dev->config.mi_config.dma.next_buff_addr = + vb2_dma_contig_plane_dma_addr( + &dev->dma_stream.curr_buf->vb.vb2_buf, 0); +#endif + +#ifdef CIF_ISP10_MODE_DMA_SG + sgt = vb2_dma_sg_plane_desc( + &dev->dma_stream.curr_buf->vb.vb2_buf, 0); dev->config.mi_config.dma.next_buff_addr = - videobuf_to_dma_contig( - dev->dma_stream.curr_buf); + sg_dma_address(sgt->sgl); +#endif cif_isp10_mi_update_buff_addr(dev, CIF_ISP10_STREAM_DMA); dev->config.mi_config.dma.busy = true; @@ -3955,8 +4038,7 @@ static void cif_isp10_dma_ready( cif_isp10_pltfrm_pr_err(dev->dev, "dma icr err: 0x%x\n", mi_mis_tmp); - dev->dma_stream.curr_buf->state = VIDEOBUF_DONE; - wake_up(&dev->dma_stream.curr_buf->done); + wake_up(&dev->dma_stream.curr_buf->vb.vb2_buf.vb2_queue->done_wq); dev->dma_stream.curr_buf = NULL; dev->config.mi_config.dma.busy = false; cif_isp10_pltfrm_event_signal(dev->dev, &dev->dma_stream.done); @@ -3967,7 +4049,17 @@ static int cif_isp10_mi_frame_end( enum cif_isp10_stream_id stream_id) { struct cif_isp10_stream *stream = NULL; + u32 cur_buff_addr = -1; u32 *next_buff_addr = NULL; + struct vb2_buffer *vb2_buf; + dma_addr_t tmp_addr; +#ifdef CIF_ISP10_MODE_DMA_SG + struct sg_table *sgt = NULL; + struct scatterlist *sg; + dma_addr_t tmp_phy_addr; + int i; +#endif + CIF_ISP10_PLTFRM_MEM_IO_ADDR y_base_addr; int (*update_mi)( struct cif_isp10_device *dev); @@ -4034,19 +4126,28 @@ static int cif_isp10_mi_frame_end( !(dev->config.jpeg_config.enable && (stream_id == CIF_ISP10_STREAM_MP))) { stream->stall = dev->config.out_of_buffer_stall; - } else if ((stream->next_buf) && - (videobuf_to_dma_contig(stream->next_buf) != - cif_ioread32(y_base_addr))) { - cif_isp10_pltfrm_pr_warn(dev->dev, - "%s buffer queue is not advancing (0x%08x/0x%08x)\n", - cif_isp10_stream_id_string(stream_id), - (stream_id & CIF_ISP10_STREAM_MP) ? - cif_ioread32(dev->config.base_addr + - CIF_MI_MP_Y_BASE_AD_INIT) : - cif_ioread32(dev->config.base_addr + - CIF_MI_SP_Y_BASE_AD_INIT), - cif_ioread32(y_base_addr)); - stream->stall = true; + } else if ((stream->next_buf)) { +#ifdef CIF_ISP10_MODE_DMA_CONTIG + tmp_addr = vb2_dma_contig_plane_dma_addr( + &stream->next_buf->vb.vb2_buf, 0); +#endif +#ifdef CIF_ISP10_MODE_DMA_SG + sgt = vb2_dma_sg_plane_desc( + &stream->next_buf->vb.vb2_buf, 0); + tmp_addr = sg_dma_address(sgt->sgl); +#endif + if (tmp_addr != cif_ioread32(y_base_addr)) { + cif_isp10_pltfrm_pr_warn(dev->dev, + "%s buffer queue is not advancing (0x%08x/0x%08x)\n", + cif_isp10_stream_id_string(stream_id), + (stream_id & CIF_ISP10_STREAM_MP) ? + cif_ioread32(dev->config.base_addr + + CIF_MI_MP_Y_BASE_AD_INIT) : + cif_ioread32(dev->config.base_addr + + CIF_MI_SP_Y_BASE_AD_INIT), + cif_ioread32(y_base_addr)); + stream->stall = true; + } } if (!stream->stall) { @@ -4060,8 +4161,8 @@ static int cif_isp10_mi_frame_end( (stream->next_buf)) { bool wake_now; - stream->curr_buf->field_count = dev->isp_dev.frame_id; - stream->curr_buf->state = VIDEOBUF_DONE; + vb2_buf = &stream->curr_buf->vb.vb2_buf; + vb2_buffer_done(vb2_buf, VB2_BUF_STATE_DONE); wake_now = false; if (stream->metadata.d && dev->isp_dev.streamon) { @@ -4069,7 +4170,7 @@ static int cif_isp10_mi_frame_end( metadata = (struct v4l2_buffer_metadata_s *) (stream->metadata.d + - stream->curr_buf->i * + stream->curr_buf->vb.vb2_buf.index * CAMERA_METADATA_LEN); metadata->frame_id = dev->isp_dev.frame_id; metadata->frame_t.vs_t = dev->isp_dev.vs_t; @@ -4089,7 +4190,8 @@ static int cif_isp10_mi_frame_end( &dev->isp_dev; work->frame_id = dev->isp_dev.frame_id; - work->vb = stream->curr_buf; + work->vb = + &stream->curr_buf->vb.vb2_buf; work->stream_id = stream->id; if (!queue_work(dev->isp_dev.readout_wq, (struct work_struct *)work)) { @@ -4111,7 +4213,8 @@ static int cif_isp10_mi_frame_end( if (wake_now) { cif_isp10_pltfrm_pr_dbg(NULL, "frame done\n"); - wake_up(&stream->curr_buf->done); + vb2_buf = &stream->curr_buf->vb.vb2_buf; + wake_up(&vb2_buf->vb2_queue->done_wq); } stream->curr_buf = NULL; } @@ -4132,41 +4235,82 @@ static int cif_isp10_mi_frame_end( if (!list_empty(&stream->buf_queue)) { stream->next_buf = list_first_entry(&stream->buf_queue, - struct videobuf_buffer, queue); + struct cif_isp10_buffer, queue); list_del(&stream->next_buf->queue); - stream->next_buf->state = VIDEOBUF_ACTIVE; - *next_buff_addr = videobuf_to_dma_contig( - stream->next_buf); +#ifdef CIF_ISP10_MODE_DMA_CONTIG + *next_buff_addr = vb2_dma_contig_plane_dma_addr( + &stream->next_buf->vb.vb2_buf, 0); +#endif +#ifdef CIF_ISP10_MODE_DMA_SG + sgt = vb2_dma_sg_plane_desc( + &stream->next_buf->vb.vb2_buf, 0); + *next_buff_addr = sg_dma_address(sgt->sgl); +#endif } else if ( - !dev->config.out_of_buffer_stall || + (!dev->config.out_of_buffer_stall || (dev->config.jpeg_config.enable && - (stream_id == CIF_ISP10_STREAM_MP))) { -/* - * If mi restart after switch off for buffer is empty, - * mi may be restart failed. So mi write data to last - * buffer, the last buffer isn't been release to user - * until new buffer queue; - * - * if - * *next_buff_addr = CIF_ISP10_INVALID_BUFF_ADDR; - * mi will stop; - */ + (stream_id == CIF_ISP10_STREAM_MP))) && + (stream->curr_buf)) { + /* + * If mi restart after switch off for buffer is empty, + * mi may be restart failed. So mi write data to last + * buffer, the last buffer isn't been release to user + * until new buffer queue; + * + * if + * *next_buff_addr = CIF_ISP10_INVALID_BUFF_ADDR; + * mi will stop; + */ + vb2_buf = &stream->curr_buf->vb.vb2_buf; +#ifdef CIF_ISP10_MODE_DMA_CONTIG *next_buff_addr = - videobuf_to_dma_contig( - stream->curr_buf); + vb2_dma_contig_plane_dma_addr(vb2_buf, 0); +#endif +#ifdef CIF_ISP10_MODE_DMA_SG + sgt = vb2_dma_sg_plane_desc(vb2_buf, 0); + *next_buff_addr = sg_dma_address(sgt->sgl); +#endif } } (void)update_mi(dev); stream->stall = false; + if (stream->curr_buf) { + // TODO::current vb2 buffer is null + if (!stream->curr_buf->vb.vb2_buf.planes[0].mem_priv) { + cif_isp10_pltfrm_pr_err(dev->dev, + "error isp buffer is null\n"); + return 0; + } + +#ifdef CIF_ISP10_MODE_DMA_CONTIG + cur_buff_addr = vb2_dma_contig_plane_dma_addr + (&stream->curr_buf->vb.vb2_buf, 0); + +#endif +#ifdef CIF_ISP10_MODE_DMA_SG + sgt = vb2_dma_sg_plane_desc(&stream->curr_buf->vb.vb2_buf, 0); + cur_buff_addr = sg_dma_address(sgt->sgl); + + cif_isp10_pltfrm_pr_dbg(dev->dev, + "current buffer scatter list: "); + for_each_sg(sgt->sgl, sg, sgt->nents, i) { + tmp_addr = sg_dma_address(sg); + tmp_phy_addr = sg_phys(sg); + cif_isp10_pltfrm_pr_dbg(dev->dev, + "dma_addr: %pad tmp_phy: %pad length: %.8x\n", + &tmp_addr, &tmp_phy_addr, (int)sg_dma_len(sg)); + } +#endif + } + cif_isp10_pltfrm_pr_dbg(dev->dev, "%s curr_buff: %d, 0x%08x next_buf: %d, 0x%x\n", cif_isp10_stream_id_string(stream_id), - (stream->curr_buf) ? stream->curr_buf->i : -1, - (stream->curr_buf) ? (int)videobuf_to_dma_contig - (stream->curr_buf) : -1, - (stream->next_buf) ? stream->next_buf->i : -1, + (stream->curr_buf) ? stream->curr_buf->vb.vb2_buf.index : -1, + cur_buff_addr, + (stream->next_buf) ? stream->next_buf->vb.vb2_buf.index : -1, *next_buff_addr); return 0; @@ -4547,7 +4691,7 @@ static int cif_isp10_start( bool start_mp) { unsigned int ret; - struct videobuf_buffer *vb, *n; + struct vb2_buffer *vb, *n; cif_isp10_pltfrm_pr_dbg(dev->dev, "SP state = %s, MP state = %s, DMA state = %s, img_src state = %s, start_sp = %d, start_mp = %d\n", @@ -4612,17 +4756,16 @@ static int cif_isp10_start( /* start sensor output! */ dev->isp_dev.frame_id = 0; dev->isp_dev.frame_id_setexp = 0; - videobuf_queue_lock(&dev->isp_dev.vbq_stat); + list_for_each_entry_safe( - vb, n, &dev->isp_dev.vbq_stat.stream, queue) { - if (vb->state == VIDEOBUF_DONE) { - vb->field_count = -1; + vb, n, &dev->isp_dev.stat, queued_entry) { + if (vb->state == VB2_BUF_STATE_DONE) { cif_isp10_pltfrm_pr_info( dev->dev, - "discard vb: %d\n", vb->i); + "discard vb: %d\n", vb->index); } } - videobuf_queue_unlock(&dev->isp_dev.vbq_stat); + // spin_unlock_irq(&dev->isp_dev.lock); mutex_lock(&dev->img_src_exps.mutex); cif_isp10_img_src_ioctl(dev->img_src, @@ -5199,7 +5342,7 @@ int cif_isp10_streamoff( (dev->sp_stream.state <= CIF_ISP10_STATE_INACTIVE)) { dev->isp_dev.input_width = 0; dev->isp_dev.input_height = 0; - dev->config.isp_config.ism_config.ism_en = 0; + dev->config.isp_config.ism_config.ism_en = false; } cif_isp10_pltfrm_pr_dbg(dev->dev, @@ -5302,11 +5445,14 @@ int cif_isp10_s_fmt( switch (stream_id) { case CIF_ISP10_STREAM_SP: - return cif_isp10_s_fmt_sp(dev, strm_fmt, stride); + ret = cif_isp10_s_fmt_sp(dev, strm_fmt, stride); + break; case CIF_ISP10_STREAM_MP: - return cif_isp10_s_fmt_mp(dev, strm_fmt, stride); + ret = cif_isp10_s_fmt_mp(dev, strm_fmt, stride); + break; case CIF_ISP10_STREAM_DMA: - return cif_isp10_s_fmt_dma(dev, strm_fmt, stride); + ret = cif_isp10_s_fmt_dma(dev, strm_fmt, stride); + break; default: cif_isp10_pltfrm_pr_err(NULL, "unknown/unsupported stream ID %d\n", stream_id); @@ -5314,7 +5460,7 @@ int cif_isp10_s_fmt( goto err; } - return 0; + return ret; err: cif_isp10_pltfrm_pr_err(NULL, "failed with error %d\n", ret); @@ -5485,7 +5631,6 @@ struct cif_isp10_device *cif_isp10_create( if (IS_ERR_VALUE(ret)) goto err; - (void)cif_isp10_init(dev, CIF_ISP10_ALL_STREAMS); dev->pm_state = CIF_ISP10_PM_STATE_OFF; dev->sp_stream.state = CIF_ISP10_STATE_DISABLED; dev->sp_stream.id = CIF_ISP10_STREAM_SP; @@ -5494,6 +5639,8 @@ struct cif_isp10_device *cif_isp10_create( dev->dma_stream.state = CIF_ISP10_STATE_DISABLED; dev->dma_stream.id = CIF_ISP10_STREAM_DMA; dev->config.mi_config.async_updt = 0; + + (void)cif_isp10_init(dev, CIF_ISP10_ALL_STREAMS); cif_isp10_pltfrm_event_init(dev->dev, &dev->dma_stream.done); cif_isp10_pltfrm_event_init(dev->dev, &dev->sp_stream.done); cif_isp10_pltfrm_event_init(dev->dev, &dev->mp_stream.done); @@ -5534,9 +5681,15 @@ int cif_isp10_s_input( enum cif_isp10_inp inp; cif_isp10_pltfrm_pr_dbg(dev->dev, - "setting input to %s\n", + "setting input to %s, [w-h]=[%d-%d], defrect=[%d-%d-%d-%d]\n", cif_isp10_inp_string( - cif_isp10_input_index2inp(dev, input))); + cif_isp10_input_index2inp(dev, input)), + dev->config.img_src_output.frm_fmt.width, + dev->config.img_src_output.frm_fmt.height, + dev->config.img_src_output.frm_fmt.defrect.left, + dev->config.img_src_output.frm_fmt.defrect.top, + dev->config.img_src_output.frm_fmt.defrect.width, + dev->config.img_src_output.frm_fmt.defrect.height); if (input >= dev->img_src_cnt + CIF_ISP10_INP_DMA_CNT()) { cif_isp10_pltfrm_pr_err(NULL, @@ -5691,7 +5844,7 @@ int cif_isp10_s_isp_metadata( { unsigned int stream_id = readout_work->stream_id; - struct videobuf_buffer *vb = + struct vb2_buffer *vb = readout_work->vb; struct cif_isp10_stream *strm_dev = NULL; struct v4l2_buffer_metadata_s *metadata; @@ -5713,7 +5866,7 @@ int cif_isp10_s_isp_metadata( if (vb && strm_dev->metadata.d) { metadata = (struct v4l2_buffer_metadata_s *) (strm_dev->metadata.d + - vb->i * CAMERA_METADATA_LEN); + vb->index * CAMERA_METADATA_LEN); metadata->frame_id = readout_work->frame_id; isp_last = @@ -5755,7 +5908,7 @@ int cif_isp10_s_isp_metadata( if (vb) { cif_isp10_pltfrm_pr_dbg(NULL, "frame done\n"); - wake_up(&vb->done); + wake_up(&vb->vb2_queue->done_wq); } return 0; @@ -5850,7 +6003,8 @@ int cif_isp10_get_target_frm_size( *target_height = dev->config.mi_config.mp.output.height; } else { cif_isp10_pltfrm_pr_err(dev->dev, - "cannot get target frame size, no path ready\n"); + "cannot get target frame size, no path ready, state(mp[%d]-sp[%d])\n", + dev->mp_stream.state, dev->sp_stream.state); return -EFAULT; } return 0; @@ -5910,7 +6064,7 @@ err: int cif_isp10_calc_min_out_buff_size( struct cif_isp10_device *dev, enum cif_isp10_stream_id stream_id, - u32 *size) + u32 *size, bool payload) { int ret = 0; enum cif_isp10_pix_fmt pix_fmt; @@ -5955,8 +6109,8 @@ int cif_isp10_calc_min_out_buff_size( "mi_path->llength: 0x%x\n", mi_path->llength); - if (CIF_ISP10_PIX_FMT_IS_RAW_BAYER(pix_fmt) && - CIF_ISP10_PIX_FMT_GET_BPP(pix_fmt) > 8) + if ((CIF_ISP10_PIX_FMT_IS_RAW_BAYER(pix_fmt) && + CIF_ISP10_PIX_FMT_GET_BPP(pix_fmt) > 8) || payload) /* RAW input > 8BPP is stored with 16BPP by MI */ bpp = 16; else diff --git a/drivers/media/platform/rk-isp10/cif_isp10.h b/drivers/media/platform/rk-isp10/cif_isp10.h index c8eb6c5377ee..cdc0a74c63d5 100644 --- a/drivers/media/platform/rk-isp10/cif_isp10.h +++ b/drivers/media/platform/rk-isp10/cif_isp10.h @@ -24,7 +24,29 @@ #include #include #include +#include + +#include +#include +#include +#include + /*****************************************************************************/ + +#if IS_ENABLED(CONFIG_VIDEOBUF2_DMA_CONTIG) +#define CIF_ISP10_MODE_DMA_CONTIG 1 +#endif + +#if IS_ENABLED(CONFIG_VIDEOBUF2_DMA_SG) +#define CIF_ISP10_MODE_DMA_SG 1 +#endif + +#if !defined(CIF_ISP10_MODE_DMA_CONTIG) && \ + !defined(CIF_ISP10_MODE_DMA_SG) +#error One of the videobuf buffer modes(COTING/SG) \ + must be selected in the config +#endif + /* Definitions */ #define CONFIG_CIF_ISP_AUTO_UPD_CFG_BUG @@ -133,6 +155,7 @@ enum cif_isp10_cid { CIF_ISP10_CID_AUTO_FPS = 16, CIF_ISP10_CID_VBLANKING = 17, CIF_ISP10_CID_ISO_SENSITIVITY = 18, + CIF_ISP10_CID_MIN_BUFFER_FOR_CAPTURE = 19, }; @@ -426,15 +449,11 @@ struct cif_isp10_mi_config { struct cif_isp10_mi_path_config dma; }; -#ifdef NO_YET struct cif_isp10_buffer { - struct list_head list; - u32 dma_addr; - u32 size; + struct vb2_v4l2_buffer vb; + struct list_head queue; + unsigned long int size; }; -#else -#define cif_isp10_buffer videobuf_buffer -#endif struct cif_isp10_metadata_s { unsigned int cnt; @@ -447,8 +466,8 @@ struct cif_isp10_stream { enum cif_isp10_state state; enum cif_isp10_state saved_state; struct list_head buf_queue; - struct videobuf_buffer *curr_buf; - struct videobuf_buffer *next_buf; + struct cif_isp10_buffer *curr_buf; + struct cif_isp10_buffer *next_buf; bool updt_cfg; bool stall; bool stop; @@ -559,6 +578,23 @@ struct cif_isp10_fmt { unsigned char overlay; }; +#ifdef CIF_ISP10_MODE_DMA_SG +struct cif_isp10_iommu { + int client_fd; + int map_fd; + unsigned long linear_addr; + unsigned long len; +}; + +struct cif_isp10_dma_buf { + struct dma_buf *dma_buffer; + struct dma_buf_attachment *attach; + struct sg_table *sgt; + dma_addr_t dma_addr; + int fd; +}; +#endif + struct cif_isp10_device { unsigned int dev_id; CIF_ISP10_PLTFRM_DEVICE dev; @@ -572,6 +608,13 @@ struct cif_isp10_device { struct cif_isp10_img_src *img_src; struct cif_isp10_img_src *img_src_array[CIF_ISP10_NUM_INPUTS]; unsigned int img_src_cnt; + struct vb2_alloc_ctx *alloc_ctx; + +#ifdef CIF_ISP10_MODE_DMA_SG + struct iommu_domain *domain; + struct cif_isp10_dma_buf dma_buffer[VB2_MAX_FRAME]; + int dma_buf_cnt; +#endif struct cif_isp10_img_src_exps img_src_exps; struct cif_isp10_config config; @@ -608,6 +651,29 @@ int get_cif_isp10_output_format_desc_size(void); /* Clean code starts from here */ +static inline +struct cif_isp10_stream *to_stream_by_id(struct cif_isp10_device *dev, + enum cif_isp10_stream_id id) +{ + if (WARN_ON(id != CIF_ISP10_STREAM_MP && + id != CIF_ISP10_STREAM_SP && + id != CIF_ISP10_STREAM_DMA && + id != CIF_ISP10_STREAM_ISP)) + return &dev->sp_stream; + + switch (id) { + case CIF_ISP10_STREAM_MP: + return &dev->mp_stream; + case CIF_ISP10_STREAM_SP: + return &dev->sp_stream; + case CIF_ISP10_STREAM_DMA: + return &dev->dma_stream; + case CIF_ISP10_STREAM_ISP: + return NULL; + } + return NULL; +} + struct cif_isp10_device *cif_isp10_create( CIF_ISP10_PLTFRM_DEVICE pdev, void (*sof_event)(struct cif_isp10_device *dev, __u32 frame_sequence), @@ -683,7 +749,8 @@ const char *cif_isp10_g_input_name( int cif_isp10_calc_min_out_buff_size( struct cif_isp10_device *dev, enum cif_isp10_stream_id stream_id, - u32 *size); + u32 *size, + bool payload); int cif_isp10_s_ctrl( struct cif_isp10_device *dev, diff --git a/drivers/media/platform/rk-isp10/cif_isp10_img_src_v4l2-subdev.c b/drivers/media/platform/rk-isp10/cif_isp10_img_src_v4l2-subdev.c index 7b9b45e4b359..9871d9e8fbf9 100644 --- a/drivers/media/platform/rk-isp10/cif_isp10_img_src_v4l2-subdev.c +++ b/drivers/media/platform/rk-isp10/cif_isp10_img_src_v4l2-subdev.c @@ -206,6 +206,8 @@ static int cif_isp10_v4l2_cid2v4l2_cid(u32 cif_isp10_cid) return V4L2_CID_HFLIP; case CIF_ISP10_CID_VFLIP: return V4L2_CID_VFLIP; + case CIF_ISP10_CID_MIN_BUFFER_FOR_CAPTURE: + return V4L2_CID_MIN_BUFFERS_FOR_CAPTURE; default: cif_isp10_pltfrm_pr_err(NULL, "unknown/unsupported CIF ISP20 ID %d\n", @@ -352,6 +354,9 @@ int cif_isp10_img_src_v4l2_subdev_g_ctrl( } } *val = ctrl.value; + } else { + cif_isp10_pltfrm_pr_err(NULL, + "subdevcall got err: %d\n", ret); } return ret; } diff --git a/drivers/media/platform/rk-isp10/cif_isp10_isp.c b/drivers/media/platform/rk-isp10/cif_isp10_isp.c index a01f591ae5b0..26de7f1ce214 100644 --- a/drivers/media/platform/rk-isp10/cif_isp10_isp.c +++ b/drivers/media/platform/rk-isp10/cif_isp10_isp.c @@ -20,8 +20,8 @@ #include #include #include -#include -#include /* for ISP statistics */ +#include +#include /* for ISP statistics */ #include #include #include @@ -314,12 +314,16 @@ static void cifisp_reg_dump(const struct cif_isp10_isp_dev *isp_dev, static void cifisp_reg_dump_capture(const struct cif_isp10_isp_dev *isp_dev); #endif +static struct cif_isp10_buffer *to_cif_isp10_vb(struct vb2_v4l2_buffer *vb) +{ + return container_of(vb, struct cif_isp10_buffer, vb); +} + static int cifisp_module_enable(struct cif_isp10_isp_dev *isp_dev, bool flag, __s32 *value, unsigned int module) { unsigned int *curr_ens, *updates, *new_ens; unsigned long lock_flags = 0; - int retval = 0; spin_lock_irqsave(&isp_dev->config_lock, lock_flags); @@ -353,7 +357,7 @@ static int cifisp_module_enable(struct cif_isp10_isp_dev *isp_dev, end: spin_unlock_irqrestore(&isp_dev->config_lock, lock_flags); - return retval; + return 0; } /* ISP BP interface function */ @@ -2596,120 +2600,40 @@ static void cifisp_dpf_end(struct cif_isp10_isp_dev *isp_dev) CIF_ISP_DPF_MODE); } -/* ================================QUEUE OPS ================== */ -static int cifisp_stat_vbq_setup(struct videobuf_queue *vq, - unsigned int *cnt, unsigned int *size) -{ - *size = sizeof(struct cifisp_stat_buffer); - - return 0; -} - -static void cifisp_stat_vbq_release(struct videobuf_queue *vq, - struct videobuf_buffer *vb) -{ - CIFISP_DPRINT(CIFISP_DEBUG, "Releasing buffer entry!\n"); - - videobuf_waiton(vq, vb, 0, 0); - - videobuf_vmalloc_free(vb); - - CIFISP_DPRINT(CIFISP_DEBUG, "Releasing buffer exit!\n"); -} - -static int cifisp_stat_vbq_prepare(struct videobuf_queue *vq, - struct videobuf_buffer *vb, - enum v4l2_field field) -{ - int err = 0; - - vb->size = sizeof(struct cifisp_stat_buffer); - vb->width = 0; - vb->height = 0; - vb->field = field; - - if (vb->state == VIDEOBUF_NEEDS_INIT) - err = videobuf_iolock(vq, vb, NULL); - - if (!err) - vb->state = VIDEOBUF_PREPARED; - else - cifisp_stat_vbq_release(vq, vb); - - return err; -} - -static void cifisp_stat_vbq_queue(struct videobuf_queue *vq, - struct videobuf_buffer *vb) -{ - struct cif_isp10_isp_dev *isp_dev = vq->priv_data; - - vb->state = VIDEOBUF_QUEUED; - - CIFISP_DPRINT(CIFISP_DEBUG, "Queueing stat buffer!\n"); - - list_add_tail(&vb->queue, &isp_dev->stat); -} - -/* Queue Ops */ -static struct videobuf_queue_ops cifisp_stat_qops = { - .buf_setup = cifisp_stat_vbq_setup, - .buf_prepare = cifisp_stat_vbq_prepare, - .buf_queue = cifisp_stat_vbq_queue, - .buf_release = cifisp_stat_vbq_release, -}; - /* ================== IOCTL implementation ========================= */ static int cifisp_reqbufs(struct file *file, void *priv, struct v4l2_requestbuffers *p) { - struct cif_isp10_isp_dev *isp_dev = - video_get_drvdata(video_devdata(file)); - CIFISP_DPRINT(CIFISP_DEBUG, - " %s: %s: p->type %d p->count %d\n", - ISP_VDEV_NAME, __func__, p->type, p->count); - - return videobuf_reqbufs(&isp_dev->vbq_stat, p); + " %s: %s: p->type %d p->count %d\n", + ISP_VDEV_NAME, __func__, p->type, p->count); + return vb2_ioctl_reqbufs(file, priv, p); } static int cifisp_querybuf(struct file *file, void *priv, struct v4l2_buffer *p) { - struct cif_isp10_isp_dev *isp_dev = - video_get_drvdata(video_devdata(file)); - CIFISP_DPRINT(CIFISP_DEBUG, " %s: %s: p->type %d p->index %d\n", ISP_VDEV_NAME, __func__, p->type, p->index); - - return videobuf_querybuf(&isp_dev->vbq_stat, p); + return vb2_ioctl_querybuf(file, priv, p); } static int cifisp_qbuf(struct file *file, void *priv, struct v4l2_buffer *p) { - struct cif_isp10_isp_dev *isp_dev = - video_get_drvdata(video_devdata(file)); - CIFISP_DPRINT(CIFISP_DEBUG, " %s: %s: p->type %d p->index %d\n", ISP_VDEV_NAME, __func__, p->type, p->index); - - return videobuf_qbuf(&isp_dev->vbq_stat, p); + return vb2_ioctl_qbuf(file, priv, p); } /* ========================================================== */ static int cifisp_dqbuf(struct file *file, void *priv, struct v4l2_buffer *p) { - struct cif_isp10_isp_dev *isp_dev = - video_get_drvdata(video_devdata(file)); - CIFISP_DPRINT(CIFISP_DEBUG, " %s: %s: p->type %d p->index %d\n", ISP_VDEV_NAME, __func__, p->type, p->index); - - return videobuf_dqbuf(&isp_dev->vbq_stat, p, - file->f_flags & O_NONBLOCK); + return vb2_ioctl_dqbuf(file, priv, p); } static int cifisp_streamon(struct file *file, void *priv, enum v4l2_buf_type i) @@ -2717,7 +2641,7 @@ static int cifisp_streamon(struct file *file, void *priv, enum v4l2_buf_type i) struct cif_isp10_isp_dev *isp_dev = video_get_drvdata(video_devdata(file)); - int ret = videobuf_streamon(&isp_dev->vbq_stat); + int ret = vb2_ioctl_streamon(file, priv, i); if (ret == 0) isp_dev->streamon = true; @@ -2731,13 +2655,12 @@ static int cifisp_streamon(struct file *file, void *priv, enum v4l2_buf_type i) /* ========================================================== */ static int cifisp_streamoff(struct file *file, void *priv, enum v4l2_buf_type i) { + int ret; struct cif_isp10_isp_dev *isp_dev = video_get_drvdata(video_devdata(file)); - int ret; drain_workqueue(isp_dev->readout_wq); - - ret = videobuf_streamoff(&isp_dev->vbq_stat); + ret = vb2_ioctl_streamoff(file, priv, i); if (ret == 0) isp_dev->streamon = false; @@ -3167,11 +3090,9 @@ static const struct v4l2_ioctl_ops cifisp_ioctl = { static unsigned int cifisp_poll(struct file *file, struct poll_table_struct *wait) { - struct cif_isp10_isp_dev *isp_dev = - video_get_drvdata(video_devdata(file)); unsigned int ret; - ret = videobuf_poll_stream(file, &isp_dev->vbq_stat, wait); + ret = vb2_fop_poll(file, wait); CIFISP_DPRINT(CIFISP_DEBUG, "Polling on vbq_stat buffer %d\n", ret); @@ -3182,10 +3103,7 @@ static unsigned int cifisp_poll(struct file *file, /* ======================================================== */ static int cifisp_mmap(struct file *file, struct vm_area_struct *vma) { - struct cif_isp10_isp_dev *isp_dev = - video_get_drvdata(video_devdata(file)); - - return videobuf_mmap_mapper(&isp_dev->vbq_stat, vma); + return vb2_fop_mmap(file, vma); } /* ddl@rock-chips.com: v1.0.8 */ @@ -3225,13 +3143,9 @@ static int cifisp_open(struct file *file) static int cifisp_close(struct file *file) { - struct cif_isp10_isp_dev *isp_dev = - video_get_drvdata(video_devdata(file)); - CIFISP_DPRINT(CIFISP_DEBUG, "cifisp_close\n"); - videobuf_stop(&isp_dev->vbq_stat); - videobuf_mmap_free(&isp_dev->vbq_stat); + vb2_fop_release(file); /* cifisp_reset(file); */ return 0; @@ -3257,6 +3171,73 @@ static void cifisp_release(struct video_device *vdev) destroy_workqueue(isp_dev->readout_wq); } +/************************************************************/ +static int cif_isp10_vb2_queue_setup(struct vb2_queue *vq, + const void *parg, + unsigned int *count, unsigned int *num_planes, + unsigned int sizes[], void *alloc_ctxs[]) +{ + sizes[0] = sizeof(struct cifisp_stat_buffer); + *num_planes = 1; + + if (!*count) + *count = 2; + + return 0; +} + +static void cif_isp10_vb2_queue(struct vb2_buffer *vb) +{ + struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb); + struct cif_isp10_buffer *ispbuf = to_cif_isp10_vb(vbuf); + struct vb2_queue *vq = vb->vb2_queue; + struct cif_isp10_isp_dev *isp_dev = vq->drv_priv; + unsigned long flags; + + CIFISP_DPRINT(CIFISP_DEBUG, "Queueing stat buffer!\n"); + spin_lock_irqsave(&isp_dev->irq_lock, flags); + list_add_tail(&ispbuf->queue, &isp_dev->stat); + spin_unlock_irqrestore(&isp_dev->irq_lock, flags); +} + +static void cif_isp10_vb2_stop_streaming(struct vb2_queue *vq) +{ + struct cif_isp10_isp_dev *isp_dev = vq->drv_priv; + struct cif_isp10_buffer *buf, *tmp; + unsigned long flags; + + spin_lock_irqsave(&isp_dev->irq_lock, flags); + list_for_each_entry_safe(buf, tmp, &isp_dev->stat, queue) { + list_del_init(&buf->queue); + vb2_buffer_done(&buf->vb.vb2_buf, VB2_BUF_STATE_ERROR); + } + spin_unlock_irqrestore(&isp_dev->irq_lock, flags); +} + +static struct vb2_ops cif_isp10_vb2_ops = { + .queue_setup = cif_isp10_vb2_queue_setup, + .buf_queue = cif_isp10_vb2_queue, + .wait_prepare = vb2_ops_wait_prepare, + .wait_finish = vb2_ops_wait_finish, + .stop_streaming = cif_isp10_vb2_stop_streaming, +}; + +static int cif_isp10_init_vb2_queue(struct vb2_queue *q, + struct cif_isp10_isp_dev *isp_dev) +{ + memset(q, 0, sizeof(*q)); + + q->type = V4L2_BUF_TYPE_VIDEO_CAPTURE; + q->io_modes = VB2_MMAP | VB2_USERPTR; + q->drv_priv = isp_dev; + q->ops = &cif_isp10_vb2_ops; + q->mem_ops = &vb2_vmalloc_memops; + q->buf_struct_size = sizeof(struct cif_isp10_buffer); + q->timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_MONOTONIC; + + return vb2_queue_init(q); +} + /************************************************************/ int register_cifisp_device(struct cif_isp10_isp_dev *isp_dev, struct video_device *vdev_cifisp, @@ -3288,16 +3269,10 @@ int register_cifisp_device(struct cif_isp10_isp_dev *isp_dev, vdev_cifisp->lock = &isp_dev->mutex; vdev_cifisp->v4l2_dev = v4l2_dev; - videobuf_queue_vmalloc_init( - &isp_dev->vbq_stat, - &cifisp_stat_qops, - NULL, - &isp_dev->irq_lock, - V4L2_BUF_TYPE_VIDEO_CAPTURE, - V4L2_FIELD_NONE, - sizeof(struct videobuf_buffer), - isp_dev, - NULL); /* ext_lock: NULL */ + cif_isp10_init_vb2_queue(&isp_dev->vb2_vidq, isp_dev); + + vdev_cifisp->queue = &isp_dev->vb2_vidq; + if (video_register_device(vdev_cifisp, VFL_TYPE_GRABBER, -1) < 0) { dev_err(&vdev_cifisp->dev, @@ -3693,7 +3668,10 @@ static void cifisp_send_measurement( struct cif_isp10_isp_readout_work *meas_work) { unsigned long lock_flags = 0; - struct videobuf_buffer *vb = NULL; + struct cif_isp10_buffer *buf = NULL; + struct vb2_buffer *vb = NULL; + void *mem_addr; + unsigned int active_meas = isp_dev->active_meas; struct cifisp_stat_buffer *stat_buf; struct cif_isp10_device *cif_dev = @@ -3710,8 +3688,10 @@ static void cifisp_send_measurement( } if (!list_empty(&isp_dev->stat)) { - vb = list_first_entry(&isp_dev->stat, - struct videobuf_buffer, queue); + buf = list_first_entry(&isp_dev->stat, + struct cif_isp10_buffer, queue); + + vb = &buf->vb.vb2_buf; } else { spin_unlock_irqrestore(&isp_dev->irq_lock, lock_flags); CIFISP_DPRINT(CIFISP_DEBUG, @@ -3720,9 +3700,11 @@ static void cifisp_send_measurement( } spin_unlock_irqrestore(&isp_dev->irq_lock, lock_flags); - vb->state = VIDEOBUF_ACTIVE; + vb->state = VB2_BUF_STATE_ACTIVE; - stat_buf = (struct cifisp_stat_buffer *)videobuf_to_vmalloc(vb); + mem_addr = vb->vb2_queue->mem_ops->vaddr( + vb->planes[0].mem_priv); + stat_buf = (struct cifisp_stat_buffer *)mem_addr; memset(stat_buf, 0x00, sizeof(struct cifisp_stat_buffer)); if (active_meas & CIF_ISP_AWB_DONE) @@ -3749,9 +3731,8 @@ static void cifisp_send_measurement( meas_work->frame_id); goto end; } + list_del(&buf->queue); - vb->ts = isp_dev->vs_t; - list_del(&vb->queue); spin_unlock_irqrestore(&isp_dev->irq_lock, lock_flags); if (active_meas & CIF_ISP_AWB_DONE) { @@ -3787,19 +3768,16 @@ static void cifisp_send_measurement( } isp_dev->meas_stats.g_frame_id = meas_work->frame_id; - vb->field_count = meas_work->frame_id; - vb->state = VIDEOBUF_DONE; - wake_up(&vb->done); + vb2_buffer_done(vb, VB2_BUF_STATE_DONE); + wake_up(&vb->vb2_queue->done_wq); CIFISP_DPRINT(CIFISP_DEBUG, - "Measurement done(%d, %d)\n", - vb->field_count, - vb->i); + "Measurement done\n"); vb = NULL; end: - if (vb && (vb->state == VIDEOBUF_ACTIVE)) - vb->state = VIDEOBUF_QUEUED; + if (vb && (vb->state == VB2_BUF_STATE_ACTIVE)) + vb->state = VB2_BUF_STATE_QUEUED; } void cifisp_isp_readout_work(struct work_struct *work) @@ -4332,7 +4310,7 @@ int cifisp_isp_isr(struct cif_isp10_isp_dev *isp_dev, u32 isp_mis) * Do the updates in the order of the processing flow. */ spin_lock(&isp_dev->config_lock); - if (cifisp_isp_isr_other_config(isp_dev, &time_left) == false) + if (!cifisp_isp_isr_other_config(isp_dev, &time_left)) cifisp_isp_isr_meas_config(isp_dev, &time_left); spin_unlock(&isp_dev->config_lock); diff --git a/drivers/media/platform/rk-isp10/cif_isp10_isp.h b/drivers/media/platform/rk-isp10/cif_isp10_isp.h index 27f6bb6873c1..2c97e6effd50 100644 --- a/drivers/media/platform/rk-isp10/cif_isp10_isp.h +++ b/drivers/media/platform/rk-isp10/cif_isp10_isp.h @@ -18,7 +18,7 @@ #define _CIF_ISP10_ISP_H #include -#include +#include #include #include @@ -78,7 +78,6 @@ struct cif_isp10_isp_dev { spinlock_t irq_lock; /* ISP statistics related */ spinlock_t req_lock; - struct videobuf_queue vbq_stat; struct list_head stat; void __iomem *base_addr; /* registers base address */ @@ -94,6 +93,8 @@ struct cif_isp10_isp_dev { struct workqueue_struct *readout_wq; unsigned int *dev_id; + + struct vb2_queue vb2_vidq; }; enum cif_isp10_isp_readout_cmd { @@ -107,7 +108,7 @@ struct cif_isp10_isp_readout_work { unsigned int frame_id; enum cif_isp10_isp_readout_cmd readout; - struct videobuf_buffer *vb; + struct vb2_buffer *vb; unsigned int stream_id; }; diff --git a/drivers/media/platform/rk-isp10/cif_isp10_pltfrm.c b/drivers/media/platform/rk-isp10/cif_isp10_pltfrm.c index 126a0375faa9..9304f83bbe27 100644 --- a/drivers/media/platform/rk-isp10/cif_isp10_pltfrm.c +++ b/drivers/media/platform/rk-isp10/cif_isp10_pltfrm.c @@ -713,6 +713,9 @@ static ssize_t cif_isp10_dbgfs_reg_trace_write( if (count > CIF_ISP10_DBGFS_BUF_SIZE) { cif_isp10_pltfrm_pr_err(dev, "command line too long\n"); + if (!in_irq()) + spin_unlock_irqrestore( + &cif_isp10_reg_trace.lock, flags); return -EINVAL; } @@ -950,6 +953,190 @@ inline u32 cif_isp10_pltfrm_read_reg( return ioread32(addr); } +#ifdef CIF_ISP10_MODE_DMA_SG +int cif_isp10_dma_attach_device(struct cif_isp10_device *cif_isp10_dev) +{ + struct iommu_domain *domain = cif_isp10_dev->domain; + struct device *dev = cif_isp10_dev->dev; + int ret; + + cif_isp10_pltfrm_pr_dbg(NULL, "camsys_drm_dma_attach_device\n"); + + ret = dma_set_coherent_mask(dev, DMA_BIT_MASK(32)); + if (ret) + return ret; + + dma_set_max_seg_size(dev, DMA_BIT_MASK(32)); + ret = iommu_attach_device(domain, dev); + if (ret) { + dev_err(dev, "Failed to attach iommu device\n"); + return ret; + } + + if (!common_iommu_setup_dma_ops(dev, 0x10000000, SZ_2G, domain->ops)) { + dev_err(dev, "Failed to set dma_ops\n"); + iommu_detach_device(domain, dev); + ret = -ENODEV; + } + + return ret; +} + +void cif_isp10_dma_detach_device(struct cif_isp10_device *cif_isp10_dev) +{ + struct iommu_domain *domain = cif_isp10_dev->domain; + struct device *dev = cif_isp10_dev->dev; + + cif_isp10_pltfrm_pr_dbg(NULL, "camsys_drm_dma_detach_device\n"); + + iommu_detach_device(domain, dev); +} + +int cif_isp10_drm_iommu_cb(struct device *dev, + struct cif_isp10_device *cif_isp10_dev, + bool on) +{ + struct cif_isp10_iommu *iommu = NULL; + struct cif_isp10_iommu fake_iommu; + struct dma_buf *dma_buffer; + struct dma_buf_attachment *attach; + struct sg_table *sgt; + dma_addr_t dma_addr; + int index = 0; + int ret = 0; + struct cif_isp10_device *camsys_dev = cif_isp10_dev; + + fake_iommu.client_fd = -1; + fake_iommu.len = 0; + fake_iommu.linear_addr = 0; + fake_iommu.map_fd = -1; + iommu = &fake_iommu; + + if (on) { + /*ummap mapped fd first*/ + int cur_mapped_cnt = camsys_dev->dma_buf_cnt; + + for (index = 0; index < cur_mapped_cnt; index++) { + if (camsys_dev->dma_buffer[index].fd == iommu->map_fd) + break; + } + + if (index != cur_mapped_cnt) { + attach = camsys_dev->dma_buffer[index].attach; + dma_buffer = camsys_dev->dma_buffer[index].dma_buffer; + sgt = camsys_dev->dma_buffer[index].sgt; + cif_isp10_pltfrm_pr_dbg(NULL, + "exist mapped buf,release it before map:\n"); + cif_isp10_pltfrm_pr_dbg(NULL, + "attach %p,dma_buf %p,sgt %p,fd %d,index %d\n", + attach, + dma_buffer, + sgt, + iommu->map_fd, + index); + dma_buf_unmap_attachment + (attach, + sgt, + DMA_BIDIRECTIONAL); + dma_buf_detach(dma_buffer, attach); + dma_buf_put(dma_buffer); + if (camsys_dev->dma_buf_cnt == 1) + cif_isp10_dma_attach_device(camsys_dev); + camsys_dev->dma_buf_cnt--; + camsys_dev->dma_buffer[index].fd = -1; + } + /*get a free slot*/ + for (index = 0; index < VB2_MAX_FRAME; index++) + if (camsys_dev->dma_buffer[index].fd == -1) + break; + + if (index == VB2_MAX_FRAME) + return -ENOMEM; + + if (camsys_dev->dma_buf_cnt == 0) { + ret = cif_isp10_dma_attach_device(camsys_dev); + if (ret) + return ret; + } + + dma_buffer = dma_buf_get(iommu->map_fd); + if (IS_ERR(dma_buffer)) + return PTR_ERR(dma_buffer); + attach = dma_buf_attach(dma_buffer, dev); + if (IS_ERR(attach)) { + dma_buf_put(dma_buffer); + return PTR_ERR(attach); + } + sgt = dma_buf_map_attachment(attach, DMA_BIDIRECTIONAL); + if (IS_ERR(sgt)) { + dma_buf_detach(dma_buffer, attach); + dma_buf_put(dma_buffer); + return PTR_ERR(sgt); + } + dma_addr = sg_dma_address(sgt->sgl); + camsys_dev->dma_buffer[index].dma_addr = dma_addr; + camsys_dev->dma_buffer[index].attach = attach; + camsys_dev->dma_buffer[index].dma_buffer = dma_buffer; + camsys_dev->dma_buffer[index].sgt = sgt; + camsys_dev->dma_buffer[index].fd = iommu->map_fd; + iommu->linear_addr = dma_addr; + iommu->len = sg_dma_len(sgt->sgl); + camsys_dev->dma_buf_cnt++; + + cif_isp10_pltfrm_pr_dbg(NULL, + "dma buf map: dma_addr 0x%lx\n", + (unsigned long)dma_addr); + cif_isp10_pltfrm_pr_dbg(NULL, + "attach %p, dma_buf %p,sgt %p,fd %d,buf_cnt %d\n", + attach, + dma_buffer, + sgt, + iommu->map_fd, + camsys_dev->dma_buf_cnt); + } else { + if ( + (camsys_dev->dma_buf_cnt == 0) || + (index < 0) || + (index >= VB2_MAX_FRAME)) + return -EINVAL; + + for (index = 0; index < camsys_dev->dma_buf_cnt; index++) { + if (camsys_dev->dma_buffer[index].fd == iommu->map_fd) + break; + } + if (index == camsys_dev->dma_buf_cnt) { + cif_isp10_pltfrm_pr_warn(NULL, + "can't find map fd %d", + iommu->map_fd); + return -EINVAL; + } + attach = camsys_dev->dma_buffer[index].attach; + dma_buffer = camsys_dev->dma_buffer[index].dma_buffer; + sgt = camsys_dev->dma_buffer[index].sgt; + dma_addr = sg_dma_address(sgt->sgl); + cif_isp10_pltfrm_pr_dbg(NULL, + "dma buf unmap: dma_addr 0x%lx", + (unsigned long)dma_addr); + cif_isp10_pltfrm_pr_dbg(NULL, + "attach %p,dma_buf %p,sgt %p,index %d", + attach, + dma_buffer, + sgt, + index); + dma_buf_unmap_attachment(attach, sgt, DMA_BIDIRECTIONAL); + dma_buf_detach(dma_buffer, attach); + dma_buf_put(dma_buffer); + if (camsys_dev->dma_buf_cnt == 1) + cif_isp10_dma_detach_device(camsys_dev); + + camsys_dev->dma_buf_cnt--; + camsys_dev->dma_buffer[index].fd = -1; + } + + return ret; +} +#endif + int cif_isp10_pltfrm_dev_init( struct cif_isp10_device *cif_isp10_dev, struct device **_dev, @@ -963,6 +1150,12 @@ int cif_isp10_pltfrm_dev_init( struct resource *res; void __iomem *base_addr; unsigned int i, irq; +#ifdef CIF_ISP10_MODE_DMA_SG + struct iommu_domain *domain; + struct iommu_group *group; + struct device_node *np; + int err = 0; +#endif dev_set_drvdata(dev, cif_isp10_dev); cif_isp10_dev->dev = dev; @@ -1005,7 +1198,11 @@ int cif_isp10_pltfrm_dev_init( irq, cif_isp10_pltfrm_irq_handler, NULL, +#ifdef CIF_ISP10_MODE_DMA_SG + 0x80, +#else 0, +#endif dev_driver_string(dev), dev); if (IS_ERR_VALUE(ret)) { @@ -1043,6 +1240,45 @@ int cif_isp10_pltfrm_dev_init( for (i = 0; i < ARRAY_SIZE(pdata->irq_handlers); i++) pdata->irq_handlers[i].mis = -EINVAL; +#ifdef CIF_ISP10_MODE_DMA_SG + np = of_find_node_by_name(NULL, "isp0_mmu"); + if (!np) { + int index = 0; + /* iommu domain */ + domain = iommu_domain_alloc(&platform_bus_type); + if (!domain) + goto err; + + err = iommu_get_dma_cookie(domain); + if (err) + goto err_free_domain; + + group = iommu_group_get(&pdev->dev); + if (!group) { + group = iommu_group_alloc(); + if (IS_ERR(group)) { + dev_err(&pdev->dev, "Failed to allocate IOMMU group\n"); + goto err_put_cookie; + } + + err = iommu_group_add_device(group, &pdev->dev); + iommu_group_put(group); + if (err) { + dev_err(&pdev->dev, "failed to add device to IOMMU group\n"); + goto err_put_cookie; + } + } + cif_isp10_dev->domain = domain; + cif_isp10_dev->dma_buf_cnt = 0; + for (index = 0; index < VB2_MAX_FRAME; index++) + cif_isp10_dev->dma_buffer[index].fd = -1; + + cif_isp10_drm_iommu_cb(&pdev->dev, cif_isp10_dev, true); + } else { + //cif_isp10_mrv_iommu_cb(); + } +#endif + dev->platform_data = pdata; INIT_LIST_HEAD(&pdata->csi0_configs); @@ -1093,6 +1329,13 @@ int cif_isp10_pltfrm_dev_init( #endif return 0; + +#ifdef CIF_ISP10_MODE_DMA_SG +err_put_cookie: + iommu_put_dma_cookie(domain); +err_free_domain: + iommu_domain_free(domain); +#endif err: cif_isp10_pltfrm_pr_err(NULL, "failed with error %d\n", ret); if (!IS_ERR_OR_NULL(pdata)) @@ -1428,8 +1671,12 @@ err: } void cif_isp10_pltfrm_dev_release( - struct device *dev) + struct device *dev, struct cif_isp10_device *cif_isp10_dev) { +#ifdef CIF_ISP10_MODE_DMA_SG + cif_isp10_drm_iommu_cb(dev, cif_isp10_dev, false); +#endif + #ifndef CONFIG_DEBUG_FS { struct cif_isp10_pltfrm_data *pdata = diff --git a/drivers/media/platform/rk-isp10/cif_isp10_pltfrm.h b/drivers/media/platform/rk-isp10/cif_isp10_pltfrm.h index 4a205475958c..cc4e4118a133 100644 --- a/drivers/media/platform/rk-isp10/cif_isp10_pltfrm.h +++ b/drivers/media/platform/rk-isp10/cif_isp10_pltfrm.h @@ -159,7 +159,8 @@ int cif_isp10_pltfrm_dev_init( void __iomem **reg_base_addr); void cif_isp10_pltfrm_dev_release( - struct device *dev); + struct device *dev, + struct cif_isp10_device *cif_isp10_dev); int cif_isp10_pltfrm_pm_set_state( struct device *dev, diff --git a/drivers/media/platform/rk-isp10/cif_isp10_v4l2.c b/drivers/media/platform/rk-isp10/cif_isp10_v4l2.c index 448ecfe4852f..c68b5b59f1eb 100644 --- a/drivers/media/platform/rk-isp10/cif_isp10_v4l2.c +++ b/drivers/media/platform/rk-isp10/cif_isp10_v4l2.c @@ -18,7 +18,8 @@ #include #include #include -#include +#include +#include #include "cif_isp10.h" #include "cif_isp10_regs.h" #include "cif_isp10_version.h" @@ -47,8 +48,12 @@ struct cif_isp10_v4l2_fh { /* One structure per video node */ struct cif_isp10_v4l2_node { - struct videobuf_queue buf_queue; + struct vb2_queue buf_queue; + /* queue lock */ + struct mutex qlock; struct video_device vdev; + struct media_pad pad; + struct cif_isp10_pipeline *pipe; int users; struct cif_isp10_v4l2_fh *owner; }; @@ -79,13 +84,24 @@ static struct cif_isp10_v4l2_node *to_node(struct cif_isp10_v4l2_fh *fh) return container_of(vdev, struct cif_isp10_v4l2_node, vdev); } -static struct videobuf_queue *to_videobuf_queue( +static inline struct cif_isp10_v4l2_node *queue_to_node(struct vb2_queue *q) +{ + return container_of(q, struct cif_isp10_v4l2_node, buf_queue); +} + +static inline struct cif_isp10_buffer *to_cif_isp10_vb( + struct vb2_v4l2_buffer *vb) +{ + return container_of(vb, struct cif_isp10_buffer, vb); +} + +static struct vb2_queue *to_vb2_queue( struct file *file) { struct cif_isp10_v4l2_fh *fh = to_fh(file); struct video_device *vdev = fh ? fh->fh.vdev : NULL; struct cif_isp10_v4l2_node *node = to_node(fh); - struct videobuf_queue *q; + struct vb2_queue *q; if (unlikely(!vdev)) { cif_isp10_pltfrm_pr_err(NULL, @@ -123,13 +139,13 @@ static enum cif_isp10_stream_id to_stream_id( } static struct cif_isp10_device *to_cif_isp10_device( - struct videobuf_queue *queue) + struct vb2_queue *queue) { - return queue->priv_data; + return queue->drv_priv; } static enum cif_isp10_stream_id to_cif_isp10_stream_id( - struct videobuf_queue *queue) + struct vb2_queue *queue) { struct cif_isp10_v4l2_node *node = container_of(queue, struct cif_isp10_v4l2_node, buf_queue); @@ -269,6 +285,8 @@ static int cif_isp10_v4l2_cid2cif_isp10_cid(u32 v4l2_cid) return CIF_ISP10_CID_ISO_SENSITIVITY; case RK_V4L2_CID_AUTO_FPS: return CIF_ISP10_CID_AUTO_FPS; + case V4L2_CID_MIN_BUFFERS_FOR_CAPTURE: + return CIF_ISP10_CID_MIN_BUFFER_FOR_CAPTURE; default: cif_isp10_pltfrm_pr_err(NULL, "unknown/unsupported V4L2 CID 0x%x\n", @@ -304,7 +322,7 @@ static enum cif_isp10_image_effect cif_isp10_v4l2_colorfx2cif_isp10_ie( } static enum cif_isp10_pix_fmt cif_isp10_v4l2_pix_fmt2cif_isp10_pix_fmt( - u32 v4l2_pix_fmt, struct videobuf_queue *queue) + u32 v4l2_pix_fmt, struct vb2_queue *queue) { /*struct cif_isp10_v4l2_node *node = * container_of(queue, struct cif_isp10_v4l2_node, buf_queue); @@ -425,25 +443,20 @@ static int cif_isp10_v4l2_streamon( enum v4l2_buf_type buf_type) { int ret; - struct videobuf_queue *queue = to_videobuf_queue(file); + struct vb2_queue *queue = to_vb2_queue(file); struct cif_isp10_device *dev = to_cif_isp10_device(queue); static u32 streamon_cnt_sp; static u32 streamon_cnt_mp; static u32 streamon_cnt_dma; - struct cif_isp10_v4l2_fh *fh = to_fh(file); - struct cif_isp10_v4l2_node *node = to_node(fh); u32 stream_ids = to_stream_id(file); - if (node->owner != fh) - return -EBUSY; - cif_isp10_pltfrm_pr_dbg(dev->dev, "%s(%d)\n", cif_isp10_v4l2_buf_type_string(queue->type), (stream_ids & CIF_ISP10_STREAM_MP) ? ++streamon_cnt_mp : ((stream_ids & CIF_ISP10_STREAM_SP) ? ++streamon_cnt_sp : ++streamon_cnt_dma)); - ret = videobuf_streamon(queue); + ret = vb2_streamon(queue, buf_type); if (IS_ERR_VALUE(ret)) { cif_isp10_pltfrm_pr_err(dev->dev, "videobuf_streamon failed\n"); @@ -452,13 +465,12 @@ static int cif_isp10_v4l2_streamon( ret = cif_isp10_streamon(dev, stream_ids); if (IS_ERR_VALUE(ret)) { - videobuf_queue_cancel(queue); goto err; } return 0; err: - (void)videobuf_mmap_free(queue); + (void)vb2_queue_release(queue); cif_isp10_pltfrm_pr_err(dev->dev, "failed with error %d\n", ret); return ret; } @@ -468,33 +480,24 @@ static int cif_isp10_v4l2_do_streamoff( { int ret = 0; int err; - struct videobuf_queue *queue = to_videobuf_queue(file); + struct vb2_queue *queue = to_vb2_queue(file); struct cif_isp10_device *dev = to_cif_isp10_device(queue); - struct cif_isp10_v4l2_fh *fh = to_fh(file); - struct cif_isp10_v4l2_node *node = to_node(fh); u32 stream_ids = to_stream_id(file); cif_isp10_pltfrm_pr_dbg(dev->dev, "%s\n", cif_isp10_v4l2_buf_type_string(queue->type)); - if (node->owner != fh) - return -EBUSY; - err = cif_isp10_streamoff(dev, stream_ids); if (IS_ERR_VALUE(err)) ret = -EFAULT; - err = videobuf_streamoff(queue); + err = vb2_streamoff(queue, queue->type); if (IS_ERR_VALUE(err)) { cif_isp10_pltfrm_pr_err(dev->dev, "videobuf_streamoff failed with error %d\n", err); ret = -EFAULT; } - err = videobuf_mmap_free(queue); - if (IS_ERR_VALUE(err)) { - cif_isp10_pltfrm_pr_err(dev->dev, - "videobuf_mmap_free failed with error %d\n", err); - ret = -EFAULT; - } + + vb2_queue_release(queue); if (IS_ERR_VALUE(ret)) cif_isp10_pltfrm_pr_err(dev->dev, @@ -523,20 +526,8 @@ static int cif_isp10_v4l2_qbuf( struct v4l2_buffer *buf) { int ret; - struct videobuf_queue *queue = to_videobuf_queue(file); - struct cif_isp10_v4l2_fh *fh = to_fh(file); - struct cif_isp10_v4l2_node *node = to_node(fh); - - cif_isp10_pltfrm_pr_dbg(NULL, - "%s buffer type %s, index %d, length %d\n", - cif_isp10_v4l2_buf_type_string(queue->type), - cif_isp10_v4l2_buf_type_string(buf->type), - buf->index, buf->length); - - if (node->owner != fh) - return -EBUSY; - ret = videobuf_qbuf(queue, buf); + ret = vb2_ioctl_qbuf(file, priv, buf); if (IS_ERR_VALUE(ret)) cif_isp10_pltfrm_pr_err(NULL, "videobuf_qbuf failed with error %d\n", ret); @@ -549,17 +540,8 @@ static int cif_isp10_v4l2_dqbuf( struct v4l2_buffer *buf) { int ret; - struct videobuf_queue *queue = to_videobuf_queue(file); - struct cif_isp10_v4l2_fh *fh = to_fh(file); - struct cif_isp10_v4l2_node *node = to_node(fh); - cif_isp10_pltfrm_pr_dbg(NULL, "%s\n", - cif_isp10_v4l2_buf_type_string(queue->type)); - - if (node->owner != fh) - return -EBUSY; - - ret = videobuf_dqbuf(queue, buf, file->f_flags & O_NONBLOCK); + ret = vb2_ioctl_dqbuf(file, priv, buf); if (IS_ERR_VALUE(ret) && (ret != -EAGAIN)) cif_isp10_pltfrm_pr_err(NULL, "videobuf_dqbuf failed with error %d\n", ret); @@ -570,152 +552,17 @@ static int cif_isp10_v4l2_dqbuf( return ret; } -static void cif_isp10_v4l2_buf_release( - struct videobuf_queue *queue, - struct videobuf_buffer *buf) -{ - cif_isp10_pltfrm_pr_dbg(NULL, - "%s\n", - cif_isp10_v4l2_buf_type_string(queue->type)); - - if (in_interrupt()) - WARN_ON(1); - - videobuf_dma_contig_free(queue, buf); - - buf->state = VIDEOBUF_NEEDS_INIT; -} - -static void cif_isp10_v4l2_buf_queue( - struct videobuf_queue *queue, - struct videobuf_buffer *buf) -{ - struct cif_isp10_device *dev = to_cif_isp10_device(queue); - enum cif_isp10_stream_id strm = to_cif_isp10_stream_id(queue); - - cif_isp10_pltfrm_pr_dbg(NULL, - "%s %dx%d, size %lu, bytesperline %d\n", - cif_isp10_v4l2_buf_type_string(queue->type), - buf->width, buf->height, buf->size, buf->bytesperline); - - if (!IS_ERR_VALUE(cif_isp10_qbuf(dev, strm, buf))) - buf->state = VIDEOBUF_QUEUED; - else - cif_isp10_pltfrm_pr_err(NULL, "failed\n"); -} - -static int cif_isp10_v4l2_buf_setup( - struct videobuf_queue *queue, - unsigned int *cnt, - unsigned int *size) -{ - int ret; - struct cif_isp10_device *dev = to_cif_isp10_device(queue); - enum cif_isp10_stream_id strm = to_cif_isp10_stream_id(queue); - - cif_isp10_pltfrm_pr_dbg(NULL, "%s count %d, size %d\n", - cif_isp10_v4l2_buf_type_string(queue->type), - *cnt, *size); - - ret = cif_isp10_calc_min_out_buff_size( - dev, strm, size); - if (IS_ERR_VALUE(ret)) { - cif_isp10_pltfrm_pr_err(NULL, "failed with error %d\n", ret); - return ret; - } - - cif_isp10_pltfrm_pr_dbg(NULL, "%s count %d, size %d\n", - cif_isp10_v4l2_buf_type_string(queue->type), - *cnt, *size); - - return 0; -} - -static int cif_isp10_v4l2_buf_prepare( - struct videobuf_queue *queue, - struct videobuf_buffer *buf, - enum v4l2_field field) -{ - int ret; - struct cif_isp10_device *dev = to_cif_isp10_device(queue); - enum cif_isp10_stream_id strm = to_cif_isp10_stream_id(queue); - u32 size; - - cif_isp10_pltfrm_pr_dbg(NULL, "%s\n", - cif_isp10_v4l2_buf_type_string(queue->type)); - - ret = cif_isp10_calc_min_out_buff_size( - dev, strm, &size); - if (IS_ERR_VALUE(ret)) - goto err; - buf->size = size; - if (strm == CIF_ISP10_STREAM_SP) { - buf->width = - dev->config.mi_config.sp.output.width; - buf->height = - dev->config.mi_config.sp.output.height; - } else if (strm == CIF_ISP10_STREAM_MP) { - buf->width = - dev->config.mi_config.mp.output.width; - buf->height = - dev->config.mi_config.mp.output.height; - } else if (strm == CIF_ISP10_STREAM_DMA) { - buf->width = - dev->config.mi_config.dma.output.width; - buf->height = - dev->config.mi_config.dma.output.height; - } else { - cif_isp10_pltfrm_pr_err(NULL, - "wrong buffer queue %d\n", queue->type); - ret = -EINVAL; - goto err; - } - buf->field = field; - - cif_isp10_pltfrm_pr_dbg(NULL, "%s buffer prepared %dx%d, size %d\n", - cif_isp10_v4l2_buf_type_string(queue->type), - buf->width, buf->height, size); - - if (buf->state == VIDEOBUF_NEEDS_INIT) { - ret = videobuf_iolock(queue, buf, NULL); - if (IS_ERR_VALUE(ret)) { - cif_isp10_pltfrm_pr_err(NULL, - "videobuf_iolock failed with error %d\n", ret); - goto err; - } - } - buf->state = VIDEOBUF_PREPARED; - - return 0; -err: - cif_isp10_pltfrm_pr_err(NULL, "failed with error %d\n", ret); - cif_isp10_v4l2_buf_release(queue, buf); - return ret; -} - static int cif_isp10_v4l2_reqbufs( struct file *file, void *priv, struct v4l2_requestbuffers *req) { - struct cif_isp10_v4l2_fh *fh = to_fh(file); - struct cif_isp10_v4l2_node *node = to_node(fh); int ret; - struct videobuf_queue *queue = to_videobuf_queue(file); + struct vb2_queue *queue = to_vb2_queue(file); struct cif_isp10_device *dev = to_cif_isp10_device(queue); enum cif_isp10_stream_id strm = to_cif_isp10_stream_id(queue); - cif_isp10_pltfrm_pr_dbg(NULL, - "%s requested type %s, count %d\n", - cif_isp10_v4l2_buf_type_string(queue->type), - cif_isp10_v4l2_buf_type_string(req->type), - req->count); - - if (node->owner && node->owner != fh) - return -EBUSY; - node->owner = fh; - - ret = videobuf_reqbufs(queue, req); + ret = vb2_ioctl_reqbufs(file, priv, req); if (IS_ERR_VALUE(ret)) { cif_isp10_pltfrm_pr_err(NULL, "videobuf_reqbufs failed with error %d\n", ret); @@ -730,13 +577,8 @@ static int cif_isp10_v4l2_querybuf( struct v4l2_buffer *buf) { int ret; - struct videobuf_queue *queue = to_videobuf_queue(file); - - cif_isp10_pltfrm_pr_dbg(NULL, - "%s, index %d\n", - cif_isp10_v4l2_buf_type_string(queue->type), buf->index); - ret = videobuf_querybuf(queue, buf); + ret = vb2_ioctl_querybuf(file, priv, buf); if (IS_ERR_VALUE(ret)) cif_isp10_pltfrm_pr_err(NULL, "videobuf_querybuf failed with error %d\n", ret); @@ -749,7 +591,7 @@ static int cif_isp10_v4l2_s_ctrl( void *priv, struct v4l2_control *vc) { - struct videobuf_queue *queue = to_videobuf_queue(file); + struct vb2_queue *queue = to_vb2_queue(file); struct cif_isp10_device *dev = to_cif_isp10_device(queue); enum cif_isp10_cid id = cif_isp10_v4l2_cid2cif_isp10_cid(vc->id); @@ -785,7 +627,7 @@ static int cif_isp10_v4l2_s_fmt( struct v4l2_format *f) { int ret; - struct videobuf_queue *queue = to_videobuf_queue(file); + struct vb2_queue *queue = to_vb2_queue(file); struct cif_isp10_device *dev = to_cif_isp10_device(queue); struct cif_isp10_v4l2_fh *fh = to_fh(file); struct cif_isp10_v4l2_node *node = to_node(fh); @@ -809,6 +651,13 @@ static int cif_isp10_v4l2_s_fmt( to_stream_id(file), &strm_fmt, f->fmt.pix.bytesperline); + + //TODO:: check s_fmt format field and size; + f->fmt.pix.field = V4L2_FIELD_NONE; + cif_isp10_calc_min_out_buff_size(dev, + to_stream_id(file), &f->fmt.pix.sizeimage, false); + //f->fmt.pix.sizeimage = PAGE_ALIGN(f->fmt.pix.sizeimage); + if (IS_ERR_VALUE(ret)) goto err; @@ -834,7 +683,7 @@ static int cif_isp10_v4l2_s_input( unsigned int i) { int ret; - struct videobuf_queue *queue = to_videobuf_queue(file); + struct vb2_queue *queue = to_vb2_queue(file); struct cif_isp10_device *dev = to_cif_isp10_device(queue); cif_isp10_pltfrm_pr_dbg(dev->dev, "setting input to %d\n", i); @@ -857,7 +706,7 @@ static int cif_isp10_v4l2_enum_framesizes( { /* THIS FUNCTION IS UNDER CONSTRUCTION */ int ret; - struct videobuf_queue *queue = to_videobuf_queue(file); + struct vb2_queue *queue = to_vb2_queue(file); struct cif_isp10_device *dev = to_cif_isp10_device(queue); if (IS_ERR_OR_NULL(dev->img_src)) { @@ -873,15 +722,140 @@ err: return ret; } -/* fops **********************************************************************/ +static int cif_isp10_v4l2_vb2_queue_setup(struct vb2_queue *queue, + const void *parg, + unsigned int *num_buffers, unsigned int *num_planes, + unsigned int sizes[], void *alloc_ctxs[]) +{ + int ret; + struct cif_isp10_device *dev = to_cif_isp10_device(queue); + enum cif_isp10_stream_id strm = to_cif_isp10_stream_id(queue); + + cif_isp10_pltfrm_pr_dbg(NULL, + "%s request planes %d count %d, size %d\n", + cif_isp10_v4l2_buf_type_string(queue->type), + *num_planes, + *num_buffers, sizes[0]); + + if (*num_planes == 0) + *num_planes = 1; + + if (*num_buffers == 0) + *num_buffers = 4; + + alloc_ctxs[0] = dev->alloc_ctx; + + ret = cif_isp10_calc_min_out_buff_size(dev, strm, &sizes[0], false); + //sizes[0] = PAGE_ALIGN(sizes[0] ); + if (ret) + return -EINVAL; + + cif_isp10_pltfrm_pr_dbg(NULL, "%s count %d, size %d\n", + cif_isp10_v4l2_buf_type_string(queue->type), + *num_buffers, sizes[0]); + + return 0; +} + +static void cif_isp10_v4l2_vb2_queue(struct vb2_buffer *vb) +{ + struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb); + struct cif_isp10_buffer *ispbuf = to_cif_isp10_vb(vbuf); + struct vb2_queue *queue = vb->vb2_queue; + struct cif_isp10_device *dev = to_cif_isp10_device(queue); + enum cif_isp10_stream_id strm = to_cif_isp10_stream_id(queue); + struct cif_isp10_stream *stream = to_stream_by_id(dev, strm); + u32 size; + + cif_isp10_pltfrm_pr_dbg(NULL, + "buffer type %s\n", + cif_isp10_v4l2_buf_type_string(queue->type)); -const struct videobuf_queue_ops cif_isp10_qops = { - .buf_setup = cif_isp10_v4l2_buf_setup, - .buf_prepare = cif_isp10_v4l2_buf_prepare, - .buf_queue = cif_isp10_v4l2_buf_queue, - .buf_release = cif_isp10_v4l2_buf_release, + list_add_tail(&ispbuf->queue, &stream->buf_queue); + + cif_isp10_calc_min_out_buff_size(dev, strm, &size, true); + //size = PAGE_ALIGN(size); + vb2_set_plane_payload(vb, 0, size); +} + +static void cif_isp10_v4l2_vb2_stop_streaming(struct vb2_queue *queue) +{ + struct cif_isp10_v4l2_node *node; + enum cif_isp10_stream_id strm = to_cif_isp10_stream_id(queue); + struct cif_isp10_stream *stream = NULL; + struct cif_isp10_device *dev; + struct cif_isp10_buffer *buf, *buf_tmp; + unsigned long lock_flags = 0; + + node = queue_to_node(queue); + + dev = video_get_drvdata(&node->vdev); + + stream = to_stream_by_id(dev, strm); + + spin_lock_irqsave(&dev->vbq_lock, lock_flags); + + if (stream->curr_buf) { + vb2_buffer_done(&stream->curr_buf->vb.vb2_buf, + VB2_BUF_STATE_ERROR); + stream->curr_buf = NULL; + } + if (stream->next_buf) { + vb2_buffer_done(&stream->next_buf->vb.vb2_buf, + VB2_BUF_STATE_ERROR); + stream->next_buf = NULL; + } + + list_for_each_entry_safe(buf, buf_tmp, &stream->buf_queue, queue) { + list_del(&buf->queue); + if (buf->vb.vb2_buf.state == VB2_BUF_STATE_ACTIVE) + vb2_buffer_done(&buf->vb.vb2_buf, + VB2_BUF_STATE_ERROR); + } + spin_unlock_irqrestore(&dev->vbq_lock, lock_flags); +} + +static struct vb2_ops cif_isp10_v4l2_vb2_ops = { + .queue_setup = cif_isp10_v4l2_vb2_queue_setup, + .buf_queue = cif_isp10_v4l2_vb2_queue, + //.buf_cleanup = cif_isp10_v4l2_vb2_release, + //.buf_init = cif_isp10_v4l2_vb2_init, + .wait_prepare = vb2_ops_wait_prepare, + .wait_finish = vb2_ops_wait_finish, + .stop_streaming = cif_isp10_v4l2_vb2_stop_streaming, }; +static int cif_isp10_init_vb2_queue(struct vb2_queue *q, + struct cif_isp10_device *dev, + enum v4l2_buf_type buf_type) +{ + struct cif_isp10_v4l2_node *node; + + memset(q, 0, sizeof(*q)); + node = queue_to_node(q); + mutex_init(&node->qlock); + + q->type = buf_type; + q->io_modes = VB2_MMAP | VB2_USERPTR; + q->drv_priv = dev; + q->ops = &cif_isp10_v4l2_vb2_ops; + q->buf_struct_size = sizeof(struct cif_isp10_buffer); + q->min_buffers_needed = 4; + q->timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_MONOTONIC; + q->lock = &node->qlock; + +#ifdef CIF_ISP10_MODE_DMA_CONTIG + q->mem_ops = &vb2_dma_contig_memops; + dev->alloc_ctx = vb2_dma_contig_init_ctx(dev->dev); +#endif + +#ifdef CIF_ISP10_MODE_DMA_SG + q->mem_ops = &vb2_dma_sg_memops; + dev->alloc_ctx = vb2_dma_sg_init_ctx(dev->dev); +#endif + return vb2_queue_init(q); +} + static int cif_isp10_v4l2_open( struct file *file) { @@ -900,7 +874,7 @@ static int cif_isp10_v4l2_open( vdev->num, vdev->minor, vdev->name); if (vdev->minor == cif_isp10_v4l2_dev->node[SP_DEV].vdev.minor) { - buf_type = V4L2_BUF_TYPE_VIDEO_OVERLAY; + buf_type = V4L2_BUF_TYPE_VIDEO_CAPTURE; stream_id = CIF_ISP10_STREAM_SP; } else if (vdev->minor == cif_isp10_v4l2_dev->node[MP_DEV].vdev.minor) { buf_type = V4L2_BUF_TYPE_VIDEO_CAPTURE; @@ -937,15 +911,8 @@ static int cif_isp10_v4l2_open( /* First open of the device, so initialize everything */ node->owner = NULL; - videobuf_queue_dma_contig_init( - to_videobuf_queue(file), - &cif_isp10_qops, - dev->dev, - &dev->vbq_lock, - buf_type, - V4L2_FIELD_NONE, - sizeof(struct videobuf_buffer), - dev, NULL); + cif_isp10_init_vb2_queue(to_vb2_queue(file), dev, buf_type); + vdev->queue = to_vb2_queue(file); ret = cif_isp10_init(dev, to_stream_id(file)); if (IS_ERR_VALUE(ret)) { @@ -966,7 +933,7 @@ err: static int cif_isp10_v4l2_release(struct file *file) { int ret = 0; - struct videobuf_queue *queue = to_videobuf_queue(file); + struct vb2_queue *queue = to_vb2_queue(file); struct cif_isp10_device *dev = to_cif_isp10_device(queue); struct cif_isp10_v4l2_fh *fh = to_fh(file); struct cif_isp10_v4l2_node *node = to_node(fh); @@ -1006,6 +973,7 @@ static int cif_isp10_v4l2_release(struct file *file) return ret; } +/* static unsigned int cif_isp10_v4l2_poll( struct file *file, struct poll_table_struct *wait) @@ -1033,10 +1001,12 @@ static unsigned int cif_isp10_v4l2_poll( } return ret; } +*/ /* * VMA operations. */ +/* static void cif_isp10_v4l2_vm_open(struct vm_area_struct *vma) { struct cif_isp10_metadata_s *metadata = @@ -1076,6 +1046,7 @@ int cif_isp10_v4l2_mmap(struct file *file, struct vm_area_struct *vma) done: return retval; } +*/ const struct v4l2_file_operations cif_isp10_v4l2_fops = { .open = cif_isp10_v4l2_open, @@ -1084,8 +1055,10 @@ const struct v4l2_file_operations cif_isp10_v4l2_fops = { .compat_ioctl32 = video_ioctl2, #endif .release = cif_isp10_v4l2_release, - .poll = cif_isp10_v4l2_poll, - .mmap = cif_isp10_v4l2_mmap, + //.poll = cif_isp10_v4l2_poll, + //.mmap = cif_isp10_v4l2_mmap, + .poll = vb2_fop_poll, + .mmap = vb2_fop_mmap, }; /*TBD: clean up code below this line******************************************/ @@ -1093,8 +1066,7 @@ const struct v4l2_file_operations cif_isp10_v4l2_fops = { static int v4l2_querycap(struct file *file, void *priv, struct v4l2_capability *cap) { - int ret = 0; - struct videobuf_queue *queue = to_videobuf_queue(file); + struct vb2_queue *queue = to_vb2_queue(file); struct video_device *vdev = video_devdata(file); struct cif_isp10_device *dev = to_cif_isp10_device(queue); u32 stream_ids = to_stream_id(file); @@ -1105,20 +1077,23 @@ static int v4l2_querycap(struct file *file, "platform:" DRIVER_NAME "-%03i", dev->dev_id); - if (stream_ids == CIF_ISP10_STREAM_SP) - cap->capabilities = V4L2_CAP_VIDEO_OVERLAY | - V4L2_CAP_VIDEO_CAPTURE_MPLANE | + if (stream_ids == CIF_ISP10_STREAM_SP) { + cap->capabilities = V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_STREAMING; - else if (stream_ids == CIF_ISP10_STREAM_MP) + cap->device_caps |= V4L2_CAP_VIDEO_CAPTURE | + V4L2_CAP_STREAMING; + } else if (stream_ids == CIF_ISP10_STREAM_MP) { cap->capabilities = V4L2_CAP_VIDEO_CAPTURE | - V4L2_CAP_VIDEO_CAPTURE_MPLANE | V4L2_CAP_STREAMING; + cap->device_caps |= V4L2_CAP_VIDEO_CAPTURE | + V4L2_CAP_STREAMING; + } else if (stream_ids == CIF_ISP10_STREAM_DMA) cap->capabilities = V4L2_CAP_VIDEO_M2M_MPLANE | V4L2_CAP_VIDEO_M2M; cap->capabilities |= V4L2_CAP_DEVICE_CAPS; - cap->device_caps = V4L2_CAP_DEVICE_CAPS; - return ret; + cap->device_caps |= V4L2_CAP_DEVICE_CAPS; + return 0; } static int cif_isp10_v4l2_subscribe_event(struct v4l2_fh *fh, @@ -1153,8 +1128,9 @@ static void cif_isp10_v4l2_requeue_bufs( struct cif_isp10_device *dev, enum cif_isp10_stream_id stream_id) { - struct videobuf_buffer *buf; - struct videobuf_queue *q = NULL; + struct cif_isp10_buffer *ispbuf; + struct vb2_buffer *buf; + struct vb2_queue *q = NULL; struct cif_isp10_v4l2_device *cif_isp10_v4l2_dev = (struct cif_isp10_v4l2_device *)dev->nodes; @@ -1169,22 +1145,22 @@ static void cif_isp10_v4l2_requeue_bufs( dev = to_cif_isp10_device(q); - list_for_each_entry(buf, &q->stream, stream) { + list_for_each_entry(buf, &q->queued_list, queued_entry) { + ispbuf = to_cif_isp10_vb(to_vb2_v4l2_buffer(buf)); if (!IS_ERR_VALUE(cif_isp10_qbuf( - to_cif_isp10_device(q), stream_id, buf))) { + to_cif_isp10_device(q), stream_id, ispbuf))) { spin_lock(&dev->vbreq_lock); - if ((buf->state == VIDEOBUF_QUEUED) || - (buf->state == VIDEOBUF_ACTIVE) || - (buf->state == VIDEOBUF_DONE)) - buf->state = VIDEOBUF_QUEUED; + if ((buf->state == VB2_BUF_STATE_QUEUED) || + (buf->state == VB2_BUF_STATE_ACTIVE)) + buf->state = VB2_BUF_STATE_ACTIVE; else cif_isp10_pltfrm_pr_err(NULL, - "ERR: buf->state is: %d\n", - buf->state); + "skip state change for buf: %d, state: %d\n", + buf->index, buf->state); spin_unlock(&dev->vbreq_lock); } else { cif_isp10_pltfrm_pr_err(NULL, - "failed for buffer %d\n", buf->i); + "failed for buffer %d\n", buf->index); } } } @@ -1193,7 +1169,7 @@ static long v4l2_default_ioctl(struct file *file, void *fh, bool valid_prio, unsigned int cmd, void *arg) { int ret = -EINVAL; - struct videobuf_queue *queue = to_videobuf_queue(file); + struct vb2_queue *queue = to_vb2_queue(file); struct cif_isp10_device *dev = to_cif_isp10_device(queue); if (!arg) { @@ -1229,12 +1205,6 @@ static long v4l2_default_ioctl(struct file *file, void *fh, dev->config.isp_config.output.width; p_mode_data->isp_output_height = dev->config.isp_config.output.height; - - if (ret < 0) { - cif_isp10_pltfrm_pr_err(dev->dev, - "failed to get isp input info\n"); - return ret; - } } else if (cmd == RK_VIDIOC_CAMERA_MODULEINFO) { struct camera_module_info_s *p_camera_module = (struct camera_module_info_s *)arg; @@ -1263,7 +1233,7 @@ static int v4l2_s_parm( static int v4l2_enum_input(struct file *file, void *priv, struct v4l2_input *input) { - struct videobuf_queue *queue = to_videobuf_queue(file); + struct vb2_queue *queue = to_vb2_queue(file); struct cif_isp10_device *dev = to_cif_isp10_device(queue); const char *inp_name; @@ -1377,11 +1347,23 @@ static int v4l2_enum_fmt_cap(struct file *file, void *fh, static int v4l2_g_ctrl(struct file *file, void *priv, struct v4l2_control *vc) { - struct videobuf_queue *queue = to_videobuf_queue(file); + struct vb2_queue *queue = to_vb2_queue(file); struct cif_isp10_device *dev = to_cif_isp10_device(queue); enum cif_isp10_cid id = cif_isp10_v4l2_cid2cif_isp10_cid(vc->id); + if (id == CIF_ISP10_CID_MIN_BUFFER_FOR_CAPTURE) { + /* Three buffers needed at least. + * one for MI_MP_Y_BASE_AD_INIT, one for MI_MP_Y_BASE_AD_SHD + * the other one stay in the waiting queue. + */ + vc->value = 3; + cif_isp10_pltfrm_pr_dbg(dev->dev, + "V4L2_CID_MIN_BUFFERS_FOR_CAPTURE %d\n", + vc->value); + return 0; + } + return cif_isp10_img_src_g_ctrl(dev->img_src, id, &vc->value); } @@ -1391,7 +1373,7 @@ static int v4l2_s_ext_ctrls(struct file *file, void *priv, { struct cif_isp10_img_src_ctrl *ctrls; struct cif_isp10_img_src_ext_ctrl *ctrl; - struct videobuf_queue *queue = to_videobuf_queue(file); + struct vb2_queue *queue = to_vb2_queue(file); struct cif_isp10_device *dev = to_cif_isp10_device(queue); int ret = -EINVAL; unsigned int i; @@ -1438,7 +1420,7 @@ int cif_isp10_v4l2_cropcap( struct v4l2_cropcap *a) { int ret = 0; - struct videobuf_queue *queue = to_videobuf_queue(file); + struct vb2_queue *queue = to_vb2_queue(file); struct cif_isp10_device *dev = to_cif_isp10_device(queue); u32 target_width, target_height; u32 h_offs, v_offs; @@ -1549,6 +1531,7 @@ int cif_isp10_v4l2_s_crop( const struct v4l2_ioctl_ops cif_isp10_v4l2_sp_ioctlops = { .vidioc_reqbufs = cif_isp10_v4l2_reqbufs, .vidioc_querybuf = cif_isp10_v4l2_querybuf, + .vidioc_create_bufs = vb2_ioctl_create_bufs, .vidioc_qbuf = cif_isp10_v4l2_qbuf, .vidioc_dqbuf = cif_isp10_v4l2_dqbuf, .vidioc_streamon = cif_isp10_v4l2_streamon, @@ -1557,9 +1540,15 @@ const struct v4l2_ioctl_ops cif_isp10_v4l2_sp_ioctlops = { .vidioc_enum_input = v4l2_enum_input, .vidioc_g_ctrl = v4l2_g_ctrl, .vidioc_s_ctrl = cif_isp10_v4l2_s_ctrl, + .vidioc_s_fmt_vid_cap = cif_isp10_v4l2_s_fmt, + .vidioc_g_fmt_vid_cap = cif_isp10_v4l2_g_fmt, + .vidioc_s_fmt_vid_cap_mplane = cif_isp10_v4l2_s_fmt, + .vidioc_g_fmt_vid_cap_mplane = cif_isp10_v4l2_g_fmt, .vidioc_s_fmt_vid_overlay = cif_isp10_v4l2_s_fmt, .vidioc_g_fmt_vid_overlay = cif_isp10_v4l2_g_fmt, .vidioc_s_ext_ctrls = v4l2_s_ext_ctrls, + .vidioc_enum_fmt_vid_cap = v4l2_enum_fmt_cap, + .vidioc_enum_framesizes = cif_isp10_v4l2_enum_framesizes, .vidioc_querycap = v4l2_querycap, .vidioc_cropcap = cif_isp10_v4l2_cropcap, .vidioc_s_crop = cif_isp10_v4l2_s_crop, @@ -1736,7 +1725,7 @@ static int cif_isp10_v4l2_drv_remove(struct platform_device *pdev) video_unregister_device(&cif_isp10_v4l2_dev->node[DMA_DEV].vdev); unregister_cifisp_device(&cif_isp10_v4l2_dev->node[ISP_DEV].vdev); v4l2_device_unregister(&cif_isp10_dev->v4l2_dev); - cif_isp10_pltfrm_dev_release(&pdev->dev); + cif_isp10_pltfrm_dev_release(&pdev->dev, cif_isp10_dev); cif_isp10_destroy(cif_isp10_dev); cif_isp10_v4l2_dev_cnt--; -- 2.34.1