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---
*/
#include <linux/videodev2.h>
-#include <media/videobuf-dma-contig.h>
+#include <media/videobuf2-dma-contig.h>
+#include <media/videobuf2-dma-sg.h>
#include "cif_isp10_regs.h"
#include "cif_isp10.h"
#include <linux/pm_runtime.h>
static struct cif_isp10_fmt cif_isp10_output_format[] = {
/* ************* YUV422 ************* */
+// index 0
{
.name = "YUV422-Interleaved",
.fourcc = V4L2_PIX_FMT_YUYV,
.rotation = false,
.overlay = false,
},
+// index 1
{
.name = "YUV422-Interleaved",
.fourcc = V4L2_PIX_FMT_YUYV,
.rotation = false,
.overlay = false,
},
+// index 2
{
.name = "YVU422-Interleaved",
.fourcc = V4L2_PIX_FMT_UYVY,
.rotation = false,
.overlay = false,
},
+// index 3
{
.name = "YUV422-Planar",
.fourcc = V4L2_PIX_FMT_YUV422P,
.rotation = false,
.overlay = false,
},
+// index 4
{
.name = "YUV422-Semi-Planar",
.fourcc = V4L2_PIX_FMT_NV16,
.overlay = false,
},
/* ************* YUV420 ************* */
+// index 5
{
.name = "YUV420-Planar",
.fourcc = V4L2_PIX_FMT_YUV420,
.rotation = false,
.overlay = false,
},
+// index 6
{
.name = "YUV420-Planar",
.fourcc = V4L2_PIX_FMT_YUV420,
.rotation = false,
.overlay = false,
},
+// index 7
{
.name = "YVU420-Planar",
.fourcc = V4L2_PIX_FMT_YVU420,
.rotation = false,
.overlay = false,
},
+// index 8
{
.name = "YUV420-Semi-Planar",
.fourcc = V4L2_PIX_FMT_NV12,
.rotation = false,
.overlay = false,
},
+// index 9
{
.name = "YVU420-Semi-Planar",
.fourcc = V4L2_PIX_FMT_NV21,
.overlay = false,
},
/* ************* YUV400 ************* */
+// index 10
{
.name = "YVU400-Grey-Planar",
.fourcc = V4L2_PIX_FMT_GREY,
.overlay = false,
},
/* ************* YUV444 ************* */
+// index 11
{
.name = "YVU444-Planar",
.fourcc = V4L2_PIX_FMT_YUV444,
.rotation = false,
.overlay = false,
},
+// index 12
{
.name = "YVU444-Semi-Planar",
.fourcc = V4L2_PIX_FMT_NV24,
.overlay = false,
},
/* ************* JPEG ************* */
+// index 13
{
.name = "JPEG",
.fourcc = V4L2_PIX_FMT_JPEG,
.overlay = false,
},
/* ************ RGB565 *********** */
+// index 14
{
.name = "RGB565",
.fourcc = V4L2_PIX_FMT_RGB565,
.overlay = false,
},
/* ************ SGRBG8 *********** */
+// index 15
{
.name = "SGRBG8",
.fourcc = V4L2_PIX_FMT_SGRBG8,
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(
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;
}
}
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 |
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;
}
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);
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:
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;
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,
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(
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) &&
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;
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);
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);
!(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) {
(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) {
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;
&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)) {
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;
}
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;
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",
/* 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,
(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,
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);
goto err;
}
- return 0;
+ return ret;
err:
cif_isp10_pltfrm_pr_err(NULL,
"failed with error %d\n", ret);
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;
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);
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,
{
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;
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 =
if (vb) {
cif_isp10_pltfrm_pr_dbg(NULL,
"frame done\n");
- wake_up(&vb->done);
+ wake_up(&vb->vb2_queue->done_wq);
}
return 0;
*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;
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;
"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
#include <linux/platform_data/rk_isp10_platform.h>
#include <media/v4l2-device.h>
#include <media/v4l2-controls_rockchip.h>
+#include <media/videobuf2-v4l2.h>
+
+#include <linux/dma-iommu.h>
+#include <drm/rockchip_drm.h>
+#include <linux/dma-mapping.h>
+#include <linux/dma-buf.h>
+
/*****************************************************************************/
+
+#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
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,
};
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;
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;
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;
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;
/* 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),
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,
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",
}
}
*val = ctrl.value;
+ } else {
+ cif_isp10_pltfrm_pr_err(NULL,
+ "subdevcall got err: %d\n", ret);
}
return ret;
}
#include <media/v4l2-device.h>
#include <media/v4l2-ioctl.h>
#include <linux/videodev2.h>
-#include <media/videobuf-core.h>
-#include <media/videobuf-vmalloc.h> /* for ISP statistics */
+#include <media/videobuf2-core.h>
+#include <media/videobuf2-vmalloc.h> /* for ISP statistics */
#include <linux/io.h>
#include <linux/wait.h>
#include <linux/sched.h>
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);
end:
spin_unlock_irqrestore(&isp_dev->config_lock, lock_flags);
- return retval;
+ return 0;
}
/* ISP BP interface function */
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)
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;
/* ========================================================== */
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;
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);
/* ======================================================== */
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 */
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;
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,
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,
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 =
}
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,
}
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)
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) {
}
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)
* 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);
#define _CIF_ISP10_ISP_H
#include <media/v4l2-common.h>
-#include <media/videobuf-core.h>
+#include <media/videobuf2-core.h>
#include <media/rk-isp10-ioctl.h>
#include <media/v4l2-controls_rockchip.h>
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 */
struct workqueue_struct *readout_wq;
unsigned int *dev_id;
+
+ struct vb2_queue vb2_vidq;
};
enum cif_isp10_isp_readout_cmd {
unsigned int frame_id;
enum cif_isp10_isp_readout_cmd readout;
- struct videobuf_buffer *vb;
+ struct vb2_buffer *vb;
unsigned int stream_id;
};
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;
}
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,
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;
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)) {
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);
#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))
}
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 =
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,
#include <media/v4l2-event.h>
#include <media/v4l2-fh.h>
#include <media/v4l2-ioctl.h>
-#include <media/videobuf-dma-contig.h>
+#include <media/videobuf2-dma-contig.h>
+#include <media/videobuf2-dma-sg.h>
#include "cif_isp10.h"
#include "cif_isp10_regs.h"
#include "cif_isp10_version.h"
/* 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;
};
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,
}
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);
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",
}
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);
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");
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;
}
{
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,
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);
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);
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);
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);
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);
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);
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;
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);
{
/* 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)) {
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)
{
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;
/* 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)) {
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);
return ret;
}
+/*
static unsigned int cif_isp10_v4l2_poll(
struct file *file,
struct poll_table_struct *wait)
}
return ret;
}
+*/
/*
* VMA operations.
*/
+/*
static void cif_isp10_v4l2_vm_open(struct vm_area_struct *vma)
{
struct cif_isp10_metadata_s *metadata =
done:
return retval;
}
+*/
const struct v4l2_file_operations cif_isp10_v4l2_fops = {
.open = cif_isp10_v4l2_open,
.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******************************************/
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);
"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,
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;
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);
}
}
}
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) {
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;
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;
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);
}
{
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;
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;
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,
.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,
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--;