--- zzzz-none-000/linux-3.10.107/drivers/media/platform/marvell-ccic/mcam-core.c 2017-06-27 09:49:32.000000000 +0000 +++ scorpion-7490-727/linux-3.10.107/drivers/media/platform/marvell-ccic/mcam-core.c 2021-02-04 17:41:59.000000000 +0000 @@ -19,11 +19,12 @@ #include #include #include +#include #include #include #include #include -#include +#include #include #include #include @@ -67,7 +68,7 @@ "parameters require larger buffers, an attempt to reallocate " "will be made."); #else /* MCAM_MODE_VMALLOC */ -static const bool alloc_bufs_at_read = 0; +static const bool alloc_bufs_at_read; static const int n_dma_bufs = 3; /* Used by S/G_PARM */ #endif /* MCAM_MODE_VMALLOC */ @@ -94,6 +95,9 @@ #define CF_CONFIG_NEEDED 4 /* Must configure hardware */ #define CF_SINGLE_BUFFER 5 /* Running with a single buffer */ #define CF_SG_RESTART 6 /* SG restart needed */ +#define CF_FRAME_SOF0 7 /* Frame 0 started */ +#define CF_FRAME_SOF1 8 +#define CF_FRAME_SOF2 9 #define sensor_call(cam, o, f, args...) \ v4l2_subdev_call(cam->sensor, o, f, ##args) @@ -102,31 +106,57 @@ __u8 *desc; __u32 pixelformat; int bpp; /* Bytes per pixel */ - enum v4l2_mbus_pixelcode mbus_code; + bool planar; + u32 mbus_code; } mcam_formats[] = { { .desc = "YUYV 4:2:2", .pixelformat = V4L2_PIX_FMT_YUYV, - .mbus_code = V4L2_MBUS_FMT_YUYV8_2X8, + .mbus_code = MEDIA_BUS_FMT_YUYV8_2X8, .bpp = 2, + .planar = false, }, { - .desc = "RGB 444", - .pixelformat = V4L2_PIX_FMT_RGB444, - .mbus_code = V4L2_MBUS_FMT_RGB444_2X8_PADHI_LE, + .desc = "YVYU 4:2:2", + .pixelformat = V4L2_PIX_FMT_YVYU, + .mbus_code = MEDIA_BUS_FMT_YUYV8_2X8, .bpp = 2, + .planar = false, + }, + { + .desc = "YUV 4:2:0 PLANAR", + .pixelformat = V4L2_PIX_FMT_YUV420, + .mbus_code = MEDIA_BUS_FMT_YUYV8_2X8, + .bpp = 1, + .planar = true, + }, + { + .desc = "YVU 4:2:0 PLANAR", + .pixelformat = V4L2_PIX_FMT_YVU420, + .mbus_code = MEDIA_BUS_FMT_YUYV8_2X8, + .bpp = 1, + .planar = true, + }, + { + .desc = "XRGB 444", + .pixelformat = V4L2_PIX_FMT_XRGB444, + .mbus_code = MEDIA_BUS_FMT_RGB444_2X8_PADHI_LE, + .bpp = 2, + .planar = false, }, { .desc = "RGB 565", .pixelformat = V4L2_PIX_FMT_RGB565, - .mbus_code = V4L2_MBUS_FMT_RGB565_2X8_LE, + .mbus_code = MEDIA_BUS_FMT_RGB565_2X8_LE, .bpp = 2, + .planar = false, }, { .desc = "Raw RGB Bayer", .pixelformat = V4L2_PIX_FMT_SBGGR8, - .mbus_code = V4L2_MBUS_FMT_SBGGR8_1X8, - .bpp = 1 + .mbus_code = MEDIA_BUS_FMT_SBGGR8_1X8, + .bpp = 1, + .planar = false, }, }; #define N_MCAM_FMTS ARRAY_SIZE(mcam_formats) @@ -152,10 +182,10 @@ .field = V4L2_FIELD_NONE, .bytesperline = VGA_WIDTH*2, .sizeimage = VGA_WIDTH*VGA_HEIGHT*2, + .colorspace = V4L2_COLORSPACE_SRGB, }; -static const enum v4l2_mbus_pixelcode mcam_def_mbus_code = - V4L2_MBUS_FMT_YUYV8_2X8; +static const u32 mcam_def_mbus_code = MEDIA_BUS_FMT_YUYV8_2X8; /* @@ -171,18 +201,18 @@ /* * Our buffer type for working with videobuf2. Note that the vb2 - * developers have decreed that struct vb2_buffer must be at the + * developers have decreed that struct vb2_v4l2_buffer must be at the * beginning of this structure. */ struct mcam_vb_buffer { - struct vb2_buffer vb_buf; + struct vb2_v4l2_buffer vb_buf; struct list_head queue; struct mcam_dma_desc *dma_desc; /* Descriptor virtual address */ dma_addr_t dma_desc_pa; /* Descriptor physical address */ int dma_desc_nent; /* Number of mapped descriptors */ }; -static inline struct mcam_vb_buffer *vb_to_mvb(struct vb2_buffer *vb) +static inline struct mcam_vb_buffer *vb_to_mvb(struct vb2_v4l2_buffer *vb) { return container_of(vb, struct mcam_vb_buffer, vb_buf); } @@ -191,12 +221,14 @@ * Hand a completed buffer back to user space. */ static void mcam_buffer_done(struct mcam_camera *cam, int frame, - struct vb2_buffer *vbuf) + struct vb2_v4l2_buffer *vbuf) { - vbuf->v4l2_buf.bytesused = cam->pix_format.sizeimage; - vbuf->v4l2_buf.sequence = cam->buf_seq[frame]; - vb2_set_plane_payload(vbuf, 0, cam->pix_format.sizeimage); - vb2_buffer_done(vbuf, VB2_BUF_STATE_DONE); + vbuf->vb2_buf.planes[0].bytesused = cam->pix_format.sizeimage; + vbuf->sequence = cam->buf_seq[frame]; + vbuf->field = V4L2_FIELD_NONE; + v4l2_get_timestamp(&vbuf->timestamp); + vb2_set_plane_payload(&vbuf->vb2_buf, 0, cam->pix_format.sizeimage); + vb2_buffer_done(&vbuf->vb2_buf, VB2_BUF_STATE_DONE); } @@ -220,8 +252,10 @@ int i; cam->next_buf = -1; - for (i = 0; i < cam->nbufs; i++) + for (i = 0; i < cam->nbufs; i++) { clear_bit(i, &cam->flags); + clear_bit(CF_FRAME_SOF0 + i, &cam->flags); + } } static inline int mcam_needs_config(struct mcam_camera *cam) @@ -254,6 +288,82 @@ mcam_reg_clear_bit(cam, REG_CTRL0, C0_ENABLE); } +static void mcam_enable_mipi(struct mcam_camera *mcam) +{ + /* Using MIPI mode and enable MIPI */ + cam_dbg(mcam, "camera: DPHY3=0x%x, DPHY5=0x%x, DPHY6=0x%x\n", + mcam->dphy[0], mcam->dphy[1], mcam->dphy[2]); + mcam_reg_write(mcam, REG_CSI2_DPHY3, mcam->dphy[0]); + mcam_reg_write(mcam, REG_CSI2_DPHY5, mcam->dphy[1]); + mcam_reg_write(mcam, REG_CSI2_DPHY6, mcam->dphy[2]); + + if (!mcam->mipi_enabled) { + if (mcam->lane > 4 || mcam->lane <= 0) { + cam_warn(mcam, "lane number error\n"); + mcam->lane = 1; /* set the default value */ + } + /* + * 0x41 actives 1 lane + * 0x43 actives 2 lanes + * 0x45 actives 3 lanes (never happen) + * 0x47 actives 4 lanes + */ + mcam_reg_write(mcam, REG_CSI2_CTRL0, + CSI2_C0_MIPI_EN | CSI2_C0_ACT_LANE(mcam->lane)); + mcam_reg_write(mcam, REG_CLKCTRL, + (mcam->mclk_src << 29) | mcam->mclk_div); + + mcam->mipi_enabled = true; + } +} + +static void mcam_disable_mipi(struct mcam_camera *mcam) +{ + /* Using Parallel mode or disable MIPI */ + mcam_reg_write(mcam, REG_CSI2_CTRL0, 0x0); + mcam_reg_write(mcam, REG_CSI2_DPHY3, 0x0); + mcam_reg_write(mcam, REG_CSI2_DPHY5, 0x0); + mcam_reg_write(mcam, REG_CSI2_DPHY6, 0x0); + mcam->mipi_enabled = false; +} + +static bool mcam_fmt_is_planar(__u32 pfmt) +{ + struct mcam_format_struct *f; + + f = mcam_find_format(pfmt); + return f->planar; +} + +static void mcam_write_yuv_bases(struct mcam_camera *cam, + unsigned frame, dma_addr_t base) +{ + struct v4l2_pix_format *fmt = &cam->pix_format; + u32 pixel_count = fmt->width * fmt->height; + dma_addr_t y, u = 0, v = 0; + + y = base; + + switch (fmt->pixelformat) { + case V4L2_PIX_FMT_YUV420: + u = y + pixel_count; + v = u + pixel_count / 4; + break; + case V4L2_PIX_FMT_YVU420: + v = y + pixel_count; + u = v + pixel_count / 4; + break; + default: + break; + } + + mcam_reg_write(cam, REG_Y0BAR + frame * 4, y); + if (mcam_fmt_is_planar(fmt->pixelformat)) { + mcam_reg_write(cam, REG_U0BAR + frame * 4, u); + mcam_reg_write(cam, REG_V0BAR + frame * 4, v); + } +} + /* ------------------------------------------------------------------- */ #ifdef MCAM_MODE_VMALLOC @@ -324,19 +434,18 @@ static void mcam_ctlr_dma_vmalloc(struct mcam_camera *cam) { /* - * Store the first two Y buffers (we aren't supporting - * planar formats for now, so no UV bufs). Then either + * Store the first two YUV buffers. Then either * set the third if it exists, or tell the controller * to just use two. */ - mcam_reg_write(cam, REG_Y0BAR, cam->dma_handles[0]); - mcam_reg_write(cam, REG_Y1BAR, cam->dma_handles[1]); + mcam_write_yuv_bases(cam, 0, cam->dma_handles[0]); + mcam_write_yuv_bases(cam, 1, cam->dma_handles[1]); if (cam->nbufs > 2) { - mcam_reg_write(cam, REG_Y2BAR, cam->dma_handles[2]); + mcam_write_yuv_bases(cam, 2, cam->dma_handles[2]); mcam_reg_clear_bit(cam, REG_CTRL1, C1_TWOBUFS); } else mcam_reg_set_bit(cam, REG_CTRL1, C1_TWOBUFS); - if (cam->chip_id == V4L2_IDENT_CAFE) + if (cam->chip_id == MCAM_CAFE) mcam_reg_write(cam, REG_UBAR, 0); /* 32 bits only */ } @@ -373,7 +482,8 @@ * Drop the lock during the big copy. This *should* be safe... */ spin_unlock_irqrestore(&cam->dev_lock, flags); - memcpy(vb2_plane_vaddr(&buf->vb_buf, 0), cam->dma_bufs[bufno], + memcpy(vb2_plane_vaddr(&buf->vb_buf.vb2_buf, 0), + cam->dma_bufs[bufno], cam->pix_format.sizeimage); mcam_buffer_done(cam, bufno, &buf->vb_buf); spin_lock_irqsave(&cam->dev_lock, flags); @@ -426,6 +536,7 @@ /* * DMA-contiguous code. */ + /* * Set up a contiguous buffer for the given frame. Here also is where * the underrun strategy is set: if there is no buffer available, reuse @@ -437,27 +548,31 @@ static void mcam_set_contig_buffer(struct mcam_camera *cam, int frame) { struct mcam_vb_buffer *buf; + dma_addr_t dma_handle; + struct vb2_v4l2_buffer *vb; + /* * If there are no available buffers, go into single mode */ if (list_empty(&cam->buffers)) { buf = cam->vb_bufs[frame ^ 0x1]; - cam->vb_bufs[frame] = buf; - mcam_reg_write(cam, frame == 0 ? REG_Y0BAR : REG_Y1BAR, - vb2_dma_contig_plane_dma_addr(&buf->vb_buf, 0)); set_bit(CF_SINGLE_BUFFER, &cam->flags); cam->frame_state.singles++; - return; + } else { + /* + * OK, we have a buffer we can use. + */ + buf = list_first_entry(&cam->buffers, struct mcam_vb_buffer, + queue); + list_del_init(&buf->queue); + clear_bit(CF_SINGLE_BUFFER, &cam->flags); } - /* - * OK, we have a buffer we can use. - */ - buf = list_first_entry(&cam->buffers, struct mcam_vb_buffer, queue); - list_del_init(&buf->queue); - mcam_reg_write(cam, frame == 0 ? REG_Y0BAR : REG_Y1BAR, - vb2_dma_contig_plane_dma_addr(&buf->vb_buf, 0)); + cam->vb_bufs[frame] = buf; - clear_bit(CF_SINGLE_BUFFER, &cam->flags); + vb = &buf->vb_buf; + + dma_handle = vb2_dma_contig_plane_dma_addr(&vb->vb2_buf, 0); + mcam_write_yuv_bases(cam, frame, dma_handle); } /* @@ -480,6 +595,7 @@ if (!test_bit(CF_SINGLE_BUFFER, &cam->flags)) { cam->frame_state.delivered++; + cam->vb_bufs[frame] = NULL; mcam_buffer_done(cam, frame, &buf->vb_buf); } mcam_set_contig_buffer(cam, frame); @@ -615,48 +731,80 @@ */ static void mcam_ctlr_image(struct mcam_camera *cam) { - int imgsz; struct v4l2_pix_format *fmt = &cam->pix_format; + u32 widthy = 0, widthuv = 0, imgsz_h, imgsz_w; + + cam_dbg(cam, "camera: bytesperline = %d; height = %d\n", + fmt->bytesperline, fmt->sizeimage / fmt->bytesperline); + imgsz_h = (fmt->height << IMGSZ_V_SHIFT) & IMGSZ_V_MASK; + imgsz_w = (fmt->width * 2) & IMGSZ_H_MASK; + + switch (fmt->pixelformat) { + case V4L2_PIX_FMT_YUYV: + case V4L2_PIX_FMT_YVYU: + widthy = fmt->width * 2; + widthuv = 0; + break; + case V4L2_PIX_FMT_YUV420: + case V4L2_PIX_FMT_YVU420: + widthy = fmt->width; + widthuv = fmt->width / 2; + break; + default: + widthy = fmt->bytesperline; + widthuv = 0; + break; + } + + mcam_reg_write_mask(cam, REG_IMGPITCH, widthuv << 16 | widthy, + IMGP_YP_MASK | IMGP_UVP_MASK); + mcam_reg_write(cam, REG_IMGSIZE, imgsz_h | imgsz_w); + mcam_reg_write(cam, REG_IMGOFFSET, 0x0); - imgsz = ((fmt->height << IMGSZ_V_SHIFT) & IMGSZ_V_MASK) | - (fmt->bytesperline & IMGSZ_H_MASK); - mcam_reg_write(cam, REG_IMGSIZE, imgsz); - mcam_reg_write(cam, REG_IMGOFFSET, 0); - /* YPITCH just drops the last two bits */ - mcam_reg_write_mask(cam, REG_IMGPITCH, fmt->bytesperline, - IMGP_YP_MASK); /* * Tell the controller about the image format we are using. */ - switch (cam->pix_format.pixelformat) { + switch (fmt->pixelformat) { + case V4L2_PIX_FMT_YUV420: + case V4L2_PIX_FMT_YVU420: + mcam_reg_write_mask(cam, REG_CTRL0, + C0_DF_YUV | C0_YUV_420PL | C0_YUVE_VYUY, C0_DF_MASK); + break; case V4L2_PIX_FMT_YUYV: - mcam_reg_write_mask(cam, REG_CTRL0, - C0_DF_YUV|C0_YUV_PACKED|C0_YUVE_YUYV, - C0_DF_MASK); - break; - - case V4L2_PIX_FMT_RGB444: - mcam_reg_write_mask(cam, REG_CTRL0, - C0_DF_RGB|C0_RGBF_444|C0_RGB4_XRGB, - C0_DF_MASK); - /* Alpha value? */ - break; - + mcam_reg_write_mask(cam, REG_CTRL0, + C0_DF_YUV | C0_YUV_PACKED | C0_YUVE_NOSWAP, C0_DF_MASK); + break; + case V4L2_PIX_FMT_YVYU: + mcam_reg_write_mask(cam, REG_CTRL0, + C0_DF_YUV | C0_YUV_PACKED | C0_YUVE_SWAP24, C0_DF_MASK); + break; + case V4L2_PIX_FMT_XRGB444: + mcam_reg_write_mask(cam, REG_CTRL0, + C0_DF_RGB | C0_RGBF_444 | C0_RGB4_XBGR, C0_DF_MASK); + break; case V4L2_PIX_FMT_RGB565: - mcam_reg_write_mask(cam, REG_CTRL0, - C0_DF_RGB|C0_RGBF_565|C0_RGB5_BGGR, - C0_DF_MASK); - break; - + mcam_reg_write_mask(cam, REG_CTRL0, + C0_DF_RGB | C0_RGBF_565 | C0_RGB5_BGGR, C0_DF_MASK); + break; + case V4L2_PIX_FMT_SBGGR8: + mcam_reg_write_mask(cam, REG_CTRL0, + C0_DF_RGB | C0_RGB5_GRBG, C0_DF_MASK); + break; default: - cam_err(cam, "Unknown format %x\n", cam->pix_format.pixelformat); - break; + cam_err(cam, "camera: unknown format: %#x\n", fmt->pixelformat); + break; } + /* * Make sure it knows we want to use hsync/vsync. */ - mcam_reg_write_mask(cam, REG_CTRL0, C0_SIF_HVSYNC, - C0_SIFM_MASK); + mcam_reg_write_mask(cam, REG_CTRL0, C0_SIF_HVSYNC, C0_SIFM_MASK); + /* + * This field controls the generation of EOF(DVP only) + */ + if (cam->bus_type != V4L2_MBUS_CSI2) + mcam_reg_set_bit(cam, REG_CTRL0, + C0_EOF_VSYNC | C0_VEDGE_CTRL); } @@ -754,15 +902,21 @@ /* * Power up and down. */ -static void mcam_ctlr_power_up(struct mcam_camera *cam) +static int mcam_ctlr_power_up(struct mcam_camera *cam) { unsigned long flags; + int ret; spin_lock_irqsave(&cam->dev_lock, flags); - cam->plat_power_up(cam); + ret = cam->plat_power_up(cam); + if (ret) { + spin_unlock_irqrestore(&cam->dev_lock, flags); + return ret; + } mcam_reg_clear_bit(cam, REG_CTRL1, C1_PWRDWN); spin_unlock_irqrestore(&cam->dev_lock, flags); msleep(5); /* Just to be sure */ + return 0; } static void mcam_ctlr_power_down(struct mcam_camera *cam) @@ -796,34 +950,15 @@ */ static int mcam_cam_init(struct mcam_camera *cam) { - struct v4l2_dbg_chip_ident chip; int ret; - mutex_lock(&cam->s_mutex); if (cam->state != S_NOTREADY) cam_warn(cam, "Cam init with device in funky state %d", cam->state); ret = __mcam_cam_reset(cam); - if (ret) - goto out; - chip.ident = V4L2_IDENT_NONE; - chip.match.type = V4L2_CHIP_MATCH_I2C_ADDR; - chip.match.addr = cam->sensor_addr; - ret = sensor_call(cam, core, g_chip_ident, &chip); - if (ret) - goto out; - cam->sensor_type = chip.ident; - if (cam->sensor_type != V4L2_IDENT_OV7670) { - cam_err(cam, "Unsupported sensor type 0x%x", cam->sensor_type); - ret = -EINVAL; - goto out; - } -/* Get/set parameters? */ - ret = 0; + /* Get/set parameters? */ cam->state = S_IDLE; -out: mcam_ctlr_power_down(cam); - mutex_unlock(&cam->s_mutex); return ret; } @@ -844,13 +979,15 @@ static int mcam_cam_configure(struct mcam_camera *cam) { - struct v4l2_mbus_framefmt mbus_fmt; + struct v4l2_subdev_format format = { + .which = V4L2_SUBDEV_FORMAT_ACTIVE, + }; int ret; - v4l2_fill_mbus_format(&mbus_fmt, &cam->pix_format, cam->mbus_code); + v4l2_fill_mbus_format(&format.format, &cam->pix_format, cam->mbus_code); ret = sensor_call(cam, core, init, 0); if (ret == 0) - ret = sensor_call(cam, video, s_mbus_fmt, &mbus_fmt); + ret = sensor_call(cam, pad, set_fmt, NULL, &format); /* * OV7670 does weird things if flip is set *before* format... */ @@ -887,6 +1024,17 @@ spin_lock_irqsave(&cam->dev_lock, flags); clear_bit(CF_DMA_ACTIVE, &cam->flags); mcam_reset_buffers(cam); + /* + * Update CSI2_DPHY value + */ + if (cam->calc_dphy) + cam->calc_dphy(cam); + cam_dbg(cam, "camera: DPHY sets: dphy3=0x%x, dphy5=0x%x, dphy6=0x%x\n", + cam->dphy[0], cam->dphy[1], cam->dphy[2]); + if (cam->bus_type == V4L2_MBUS_CSI2) + mcam_enable_mipi(cam); + else + mcam_disable_mipi(cam); mcam_ctlr_irq_enable(cam); cam->state = S_STREAMING; if (!test_bit(CF_SG_RESTART, &cam->flags)) @@ -901,26 +1049,32 @@ */ static int mcam_vb_queue_setup(struct vb2_queue *vq, - const struct v4l2_format *fmt, unsigned int *nbufs, + const void *parg, unsigned int *nbufs, unsigned int *num_planes, unsigned int sizes[], void *alloc_ctxs[]) { + const struct v4l2_format *fmt = parg; struct mcam_camera *cam = vb2_get_drv_priv(vq); int minbufs = (cam->buffer_mode == B_DMA_contig) ? 3 : 2; - sizes[0] = cam->pix_format.sizeimage; + if (fmt && fmt->fmt.pix.sizeimage < cam->pix_format.sizeimage) + return -EINVAL; + sizes[0] = fmt ? fmt->fmt.pix.sizeimage : cam->pix_format.sizeimage; *num_planes = 1; /* Someday we have to support planar formats... */ if (*nbufs < minbufs) *nbufs = minbufs; if (cam->buffer_mode == B_DMA_contig) alloc_ctxs[0] = cam->vb_alloc_ctx; + else if (cam->buffer_mode == B_DMA_sg) + alloc_ctxs[0] = cam->vb_alloc_ctx_sg; return 0; } static void mcam_vb_buf_queue(struct vb2_buffer *vb) { - struct mcam_vb_buffer *mvb = vb_to_mvb(vb); + struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb); + struct mcam_vb_buffer *mvb = vb_to_mvb(vbuf); struct mcam_camera *cam = vb2_get_drv_priv(vb->vb2_queue); unsigned long flags; int start; @@ -935,24 +1089,28 @@ mcam_read_setup(cam); } - -/* - * vb2 uses these to release the mutex when waiting in dqbuf. I'm - * not actually sure we need to do this (I'm not sure that vb2_dqbuf() needs - * to be called with the mutex held), but better safe than sorry. - */ -static void mcam_vb_wait_prepare(struct vb2_queue *vq) -{ - struct mcam_camera *cam = vb2_get_drv_priv(vq); - - mutex_unlock(&cam->s_mutex); -} - -static void mcam_vb_wait_finish(struct vb2_queue *vq) +static void mcam_vb_requeue_bufs(struct vb2_queue *vq, + enum vb2_buffer_state state) { struct mcam_camera *cam = vb2_get_drv_priv(vq); + struct mcam_vb_buffer *buf, *node; + unsigned long flags; + unsigned i; - mutex_lock(&cam->s_mutex); + spin_lock_irqsave(&cam->dev_lock, flags); + list_for_each_entry_safe(buf, node, &cam->buffers, queue) { + vb2_buffer_done(&buf->vb_buf.vb2_buf, state); + list_del(&buf->queue); + } + for (i = 0; i < MAX_DMA_BUFS; i++) { + buf = cam->vb_bufs[i]; + + if (buf) { + vb2_buffer_done(&buf->vb_buf.vb2_buf, state); + cam->vb_bufs[i] = NULL; + } + } + spin_unlock_irqrestore(&cam->dev_lock, flags); } /* @@ -961,11 +1119,16 @@ static int mcam_vb_start_streaming(struct vb2_queue *vq, unsigned int count) { struct mcam_camera *cam = vb2_get_drv_priv(vq); + unsigned int frame; + int ret; if (cam->state != S_IDLE) { - INIT_LIST_HEAD(&cam->buffers); + mcam_vb_requeue_bufs(vq, VB2_BUF_STATE_QUEUED); return -EINVAL; } + cam->frame_state.frames = 0; + cam->frame_state.singles = 0; + cam->frame_state.delivered = 0; cam->sequence = 0; /* * Videobuf2 sneakily hoards all the buffers and won't @@ -978,30 +1141,46 @@ cam->state = S_BUFWAIT; return 0; } - return mcam_read_setup(cam); + + /* + * Ensure clear the left over frame flags + * before every really start streaming + */ + for (frame = 0; frame < cam->nbufs; frame++) + clear_bit(CF_FRAME_SOF0 + frame, &cam->flags); + + ret = mcam_read_setup(cam); + if (ret) + mcam_vb_requeue_bufs(vq, VB2_BUF_STATE_QUEUED); + return ret; } -static int mcam_vb_stop_streaming(struct vb2_queue *vq) +static void mcam_vb_stop_streaming(struct vb2_queue *vq) { struct mcam_camera *cam = vb2_get_drv_priv(vq); - unsigned long flags; + cam_dbg(cam, "stop_streaming: %d frames, %d singles, %d delivered\n", + cam->frame_state.frames, cam->frame_state.singles, + cam->frame_state.delivered); if (cam->state == S_BUFWAIT) { /* They never gave us buffers */ cam->state = S_IDLE; - return 0; + return; } if (cam->state != S_STREAMING) - return -EINVAL; + return; mcam_ctlr_stop_dma(cam); /* + * Reset the CCIC PHY after stopping streaming, + * otherwise, the CCIC may be unstable. + */ + if (cam->ctlr_reset) + cam->ctlr_reset(cam); + /* * VB2 reclaims the buffers, so we need to forget * about them. */ - spin_lock_irqsave(&cam->dev_lock, flags); - INIT_LIST_HEAD(&cam->buffers); - spin_unlock_irqrestore(&cam->dev_lock, flags); - return 0; + mcam_vb_requeue_bufs(vq, VB2_BUF_STATE_ERROR); } @@ -1010,8 +1189,8 @@ .buf_queue = mcam_vb_buf_queue, .start_streaming = mcam_vb_start_streaming, .stop_streaming = mcam_vb_stop_streaming, - .wait_prepare = mcam_vb_wait_prepare, - .wait_finish = mcam_vb_wait_finish, + .wait_prepare = vb2_ops_wait_prepare, + .wait_finish = vb2_ops_wait_finish, }; @@ -1022,7 +1201,8 @@ */ static int mcam_vb_sg_buf_init(struct vb2_buffer *vb) { - struct mcam_vb_buffer *mvb = vb_to_mvb(vb); + struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb); + struct mcam_vb_buffer *mvb = vb_to_mvb(vbuf); struct mcam_camera *cam = vb2_get_drv_priv(vb->vb2_queue); int ndesc = cam->pix_format.sizeimage/PAGE_SIZE + 1; @@ -1038,18 +1218,14 @@ static int mcam_vb_sg_buf_prepare(struct vb2_buffer *vb) { - struct mcam_vb_buffer *mvb = vb_to_mvb(vb); - struct mcam_camera *cam = vb2_get_drv_priv(vb->vb2_queue); - struct vb2_dma_sg_desc *sgd = vb2_dma_sg_plane_desc(vb, 0); + struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb); + struct mcam_vb_buffer *mvb = vb_to_mvb(vbuf); + struct sg_table *sg_table = vb2_dma_sg_plane_desc(vb, 0); struct mcam_dma_desc *desc = mvb->dma_desc; struct scatterlist *sg; int i; - mvb->dma_desc_nent = dma_map_sg(cam->dev, sgd->sglist, sgd->num_pages, - DMA_FROM_DEVICE); - if (mvb->dma_desc_nent <= 0) - return -EIO; /* Not sure what's right here */ - for_each_sg(sgd->sglist, sg, mvb->dma_desc_nent, i) { + for_each_sg(sg_table->sgl, sg, sg_table->nents, i) { desc->dma_addr = sg_dma_address(sg); desc->segment_len = sg_dma_len(sg); desc++; @@ -1057,19 +1233,11 @@ return 0; } -static int mcam_vb_sg_buf_finish(struct vb2_buffer *vb) -{ - struct mcam_camera *cam = vb2_get_drv_priv(vb->vb2_queue); - struct vb2_dma_sg_desc *sgd = vb2_dma_sg_plane_desc(vb, 0); - - dma_unmap_sg(cam->dev, sgd->sglist, sgd->num_pages, DMA_FROM_DEVICE); - return 0; -} - static void mcam_vb_sg_buf_cleanup(struct vb2_buffer *vb) { + struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb); struct mcam_camera *cam = vb2_get_drv_priv(vb->vb2_queue); - struct mcam_vb_buffer *mvb = vb_to_mvb(vb); + struct mcam_vb_buffer *mvb = vb_to_mvb(vbuf); int ndesc = cam->pix_format.sizeimage/PAGE_SIZE + 1; dma_free_coherent(cam->dev, ndesc * sizeof(struct mcam_dma_desc), @@ -1082,12 +1250,11 @@ .buf_init = mcam_vb_sg_buf_init, .buf_prepare = mcam_vb_sg_buf_prepare, .buf_queue = mcam_vb_buf_queue, - .buf_finish = mcam_vb_sg_buf_finish, .buf_cleanup = mcam_vb_sg_buf_cleanup, .start_streaming = mcam_vb_start_streaming, .stop_streaming = mcam_vb_stop_streaming, - .wait_prepare = mcam_vb_wait_prepare, - .wait_finish = mcam_vb_wait_finish, + .wait_prepare = vb2_ops_wait_prepare, + .wait_finish = vb2_ops_wait_finish, }; #endif /* MCAM_MODE_DMA_SG */ @@ -1099,25 +1266,32 @@ memset(vq, 0, sizeof(*vq)); vq->type = V4L2_BUF_TYPE_VIDEO_CAPTURE; vq->drv_priv = cam; + vq->lock = &cam->s_mutex; + vq->timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_MONOTONIC; + vq->io_modes = VB2_MMAP | VB2_USERPTR | VB2_DMABUF | VB2_READ; + vq->buf_struct_size = sizeof(struct mcam_vb_buffer); INIT_LIST_HEAD(&cam->buffers); switch (cam->buffer_mode) { case B_DMA_contig: #ifdef MCAM_MODE_DMA_CONTIG vq->ops = &mcam_vb2_ops; vq->mem_ops = &vb2_dma_contig_memops; - cam->vb_alloc_ctx = vb2_dma_contig_init_ctx(cam->dev); - vq->io_modes = VB2_MMAP | VB2_USERPTR; cam->dma_setup = mcam_ctlr_dma_contig; cam->frame_complete = mcam_dma_contig_done; + cam->vb_alloc_ctx = vb2_dma_contig_init_ctx(cam->dev); + if (IS_ERR(cam->vb_alloc_ctx)) + return PTR_ERR(cam->vb_alloc_ctx); #endif break; case B_DMA_sg: #ifdef MCAM_MODE_DMA_SG vq->ops = &mcam_vb2_sg_ops; vq->mem_ops = &vb2_dma_sg_memops; - vq->io_modes = VB2_MMAP | VB2_USERPTR; cam->dma_setup = mcam_ctlr_dma_sg; cam->frame_complete = mcam_dma_sg_done; + cam->vb_alloc_ctx_sg = vb2_dma_sg_init_ctx(cam->dev); + if (IS_ERR(cam->vb_alloc_ctx_sg)) + return PTR_ERR(cam->vb_alloc_ctx_sg); #endif break; case B_vmalloc: @@ -1126,8 +1300,6 @@ (unsigned long) cam); vq->ops = &mcam_vb2_ops; vq->mem_ops = &vb2_vmalloc_memops; - vq->buf_struct_size = sizeof(struct mcam_vb_buffer); - vq->io_modes = VB2_MMAP; cam->dma_setup = mcam_ctlr_dma_vmalloc; cam->frame_complete = mcam_vmalloc_done; #endif @@ -1138,11 +1310,14 @@ static void mcam_cleanup_vb2(struct mcam_camera *cam) { - vb2_queue_release(&cam->vb_queue); #ifdef MCAM_MODE_DMA_CONTIG if (cam->buffer_mode == B_DMA_contig) vb2_dma_contig_cleanup_ctx(cam->vb_alloc_ctx); #endif +#ifdef MCAM_MODE_DMA_SG + if (cam->buffer_mode == B_DMA_sg) + vb2_dma_sg_cleanup_ctx(cam->vb_alloc_ctx_sg); +#endif } @@ -1151,89 +1326,17 @@ * The long list of V4L2 ioctl() operations. */ -static int mcam_vidioc_streamon(struct file *filp, void *priv, - enum v4l2_buf_type type) -{ - struct mcam_camera *cam = filp->private_data; - int ret; - - mutex_lock(&cam->s_mutex); - ret = vb2_streamon(&cam->vb_queue, type); - mutex_unlock(&cam->s_mutex); - return ret; -} - - -static int mcam_vidioc_streamoff(struct file *filp, void *priv, - enum v4l2_buf_type type) -{ - struct mcam_camera *cam = filp->private_data; - int ret; - - mutex_lock(&cam->s_mutex); - ret = vb2_streamoff(&cam->vb_queue, type); - mutex_unlock(&cam->s_mutex); - return ret; -} - - -static int mcam_vidioc_reqbufs(struct file *filp, void *priv, - struct v4l2_requestbuffers *req) -{ - struct mcam_camera *cam = filp->private_data; - int ret; - - mutex_lock(&cam->s_mutex); - ret = vb2_reqbufs(&cam->vb_queue, req); - mutex_unlock(&cam->s_mutex); - return ret; -} - - -static int mcam_vidioc_querybuf(struct file *filp, void *priv, - struct v4l2_buffer *buf) -{ - struct mcam_camera *cam = filp->private_data; - int ret; - - mutex_lock(&cam->s_mutex); - ret = vb2_querybuf(&cam->vb_queue, buf); - mutex_unlock(&cam->s_mutex); - return ret; -} - -static int mcam_vidioc_qbuf(struct file *filp, void *priv, - struct v4l2_buffer *buf) -{ - struct mcam_camera *cam = filp->private_data; - int ret; - - mutex_lock(&cam->s_mutex); - ret = vb2_qbuf(&cam->vb_queue, buf); - mutex_unlock(&cam->s_mutex); - return ret; -} - -static int mcam_vidioc_dqbuf(struct file *filp, void *priv, - struct v4l2_buffer *buf) -{ - struct mcam_camera *cam = filp->private_data; - int ret; - - mutex_lock(&cam->s_mutex); - ret = vb2_dqbuf(&cam->vb_queue, buf, filp->f_flags & O_NONBLOCK); - mutex_unlock(&cam->s_mutex); - return ret; -} - static int mcam_vidioc_querycap(struct file *file, void *priv, struct v4l2_capability *cap) { + struct mcam_camera *cam = video_drvdata(file); + strcpy(cap->driver, "marvell_ccic"); strcpy(cap->card, "marvell_ccic"); - cap->version = 1; - cap->capabilities = V4L2_CAP_VIDEO_CAPTURE | + strlcpy(cap->bus_info, cam->bus_info, sizeof(cap->bus_info)); + cap->device_caps = V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_READWRITE | V4L2_CAP_STREAMING; + cap->capabilities = cap->device_caps | V4L2_CAP_DEVICE_CAPS; return 0; } @@ -1252,28 +1355,38 @@ static int mcam_vidioc_try_fmt_vid_cap(struct file *filp, void *priv, struct v4l2_format *fmt) { - struct mcam_camera *cam = priv; + struct mcam_camera *cam = video_drvdata(filp); struct mcam_format_struct *f; struct v4l2_pix_format *pix = &fmt->fmt.pix; - struct v4l2_mbus_framefmt mbus_fmt; + struct v4l2_subdev_pad_config pad_cfg; + struct v4l2_subdev_format format = { + .which = V4L2_SUBDEV_FORMAT_TRY, + }; int ret; f = mcam_find_format(pix->pixelformat); pix->pixelformat = f->pixelformat; - v4l2_fill_mbus_format(&mbus_fmt, pix, f->mbus_code); - mutex_lock(&cam->s_mutex); - ret = sensor_call(cam, video, try_mbus_fmt, &mbus_fmt); - mutex_unlock(&cam->s_mutex); - v4l2_fill_pix_format(pix, &mbus_fmt); + v4l2_fill_mbus_format(&format.format, pix, f->mbus_code); + ret = sensor_call(cam, pad, set_fmt, &pad_cfg, &format); + v4l2_fill_pix_format(pix, &format.format); pix->bytesperline = pix->width * f->bpp; - pix->sizeimage = pix->height * pix->bytesperline; + switch (f->pixelformat) { + case V4L2_PIX_FMT_YUV420: + case V4L2_PIX_FMT_YVU420: + pix->sizeimage = pix->height * pix->bytesperline * 3 / 2; + break; + default: + pix->sizeimage = pix->height * pix->bytesperline; + break; + } + pix->colorspace = V4L2_COLORSPACE_SRGB; return ret; } static int mcam_vidioc_s_fmt_vid_cap(struct file *filp, void *priv, struct v4l2_format *fmt) { - struct mcam_camera *cam = priv; + struct mcam_camera *cam = video_drvdata(filp); struct mcam_format_struct *f; int ret; @@ -1281,7 +1394,7 @@ * Can't do anything if the device is not idle * Also can't if there are streaming buffers in place. */ - if (cam->state != S_IDLE || cam->vb_queue.num_buffers > 0) + if (cam->state != S_IDLE || vb2_is_busy(&cam->vb_queue)) return -EBUSY; f = mcam_find_format(fmt->fmt.pix.pixelformat); @@ -1296,7 +1409,6 @@ * Now we start to change things for real, so let's do it * under lock. */ - mutex_lock(&cam->s_mutex); cam->pix_format = fmt->fmt.pix; cam->mbus_code = f->mbus_code; @@ -1310,7 +1422,6 @@ } mcam_set_config_needed(cam, 1); out: - mutex_unlock(&cam->s_mutex); return ret; } @@ -1322,7 +1433,7 @@ static int mcam_vidioc_g_fmt_vid_cap(struct file *filp, void *priv, struct v4l2_format *f) { - struct mcam_camera *cam = priv; + struct mcam_camera *cam = video_drvdata(filp); f->fmt.pix = cam->pix_format; return 0; @@ -1338,7 +1449,6 @@ return -EINVAL; input->type = V4L2_INPUT_TYPE_CAMERA; - input->std = V4L2_STD_ALL; /* Not sure what should go here */ strcpy(input->name, "Camera"); return 0; } @@ -1356,12 +1466,6 @@ return 0; } -/* from vivi.c */ -static int mcam_vidioc_s_std(struct file *filp, void *priv, v4l2_std_id a) -{ - return 0; -} - /* * G/S_PARM. Most of this is done by the sensor, but we are * the level which controls the number of read buffers. @@ -1369,12 +1473,10 @@ static int mcam_vidioc_g_parm(struct file *filp, void *priv, struct v4l2_streamparm *parms) { - struct mcam_camera *cam = priv; + struct mcam_camera *cam = video_drvdata(filp); int ret; - mutex_lock(&cam->s_mutex); ret = sensor_call(cam, video, g_parm, parms); - mutex_unlock(&cam->s_mutex); parms->parm.capture.readbuffers = n_dma_bufs; return ret; } @@ -1382,78 +1484,96 @@ static int mcam_vidioc_s_parm(struct file *filp, void *priv, struct v4l2_streamparm *parms) { - struct mcam_camera *cam = priv; + struct mcam_camera *cam = video_drvdata(filp); int ret; - mutex_lock(&cam->s_mutex); ret = sensor_call(cam, video, s_parm, parms); - mutex_unlock(&cam->s_mutex); parms->parm.capture.readbuffers = n_dma_bufs; return ret; } -static int mcam_vidioc_g_chip_ident(struct file *file, void *priv, - struct v4l2_dbg_chip_ident *chip) -{ - struct mcam_camera *cam = priv; - - chip->ident = V4L2_IDENT_NONE; - chip->revision = 0; - if (v4l2_chip_match_host(&chip->match)) { - chip->ident = cam->chip_id; - return 0; - } - return sensor_call(cam, core, g_chip_ident, chip); -} - static int mcam_vidioc_enum_framesizes(struct file *filp, void *priv, struct v4l2_frmsizeenum *sizes) { - struct mcam_camera *cam = priv; + struct mcam_camera *cam = video_drvdata(filp); + struct mcam_format_struct *f; + struct v4l2_subdev_frame_size_enum fse = { + .index = sizes->index, + .which = V4L2_SUBDEV_FORMAT_ACTIVE, + }; int ret; - mutex_lock(&cam->s_mutex); - ret = sensor_call(cam, video, enum_framesizes, sizes); - mutex_unlock(&cam->s_mutex); - return ret; + f = mcam_find_format(sizes->pixel_format); + if (f->pixelformat != sizes->pixel_format) + return -EINVAL; + fse.code = f->mbus_code; + ret = sensor_call(cam, pad, enum_frame_size, NULL, &fse); + if (ret) + return ret; + if (fse.min_width == fse.max_width && + fse.min_height == fse.max_height) { + sizes->type = V4L2_FRMSIZE_TYPE_DISCRETE; + sizes->discrete.width = fse.min_width; + sizes->discrete.height = fse.min_height; + return 0; + } + sizes->type = V4L2_FRMSIZE_TYPE_CONTINUOUS; + sizes->stepwise.min_width = fse.min_width; + sizes->stepwise.max_width = fse.max_width; + sizes->stepwise.min_height = fse.min_height; + sizes->stepwise.max_height = fse.max_height; + sizes->stepwise.step_width = 1; + sizes->stepwise.step_height = 1; + return 0; } static int mcam_vidioc_enum_frameintervals(struct file *filp, void *priv, struct v4l2_frmivalenum *interval) { - struct mcam_camera *cam = priv; + struct mcam_camera *cam = video_drvdata(filp); + struct mcam_format_struct *f; + struct v4l2_subdev_frame_interval_enum fie = { + .index = interval->index, + .width = interval->width, + .height = interval->height, + .which = V4L2_SUBDEV_FORMAT_ACTIVE, + }; int ret; - mutex_lock(&cam->s_mutex); - ret = sensor_call(cam, video, enum_frameintervals, interval); - mutex_unlock(&cam->s_mutex); - return ret; + f = mcam_find_format(interval->pixel_format); + if (f->pixelformat != interval->pixel_format) + return -EINVAL; + fie.code = f->mbus_code; + ret = sensor_call(cam, pad, enum_frame_interval, NULL, &fie); + if (ret) + return ret; + interval->type = V4L2_FRMIVAL_TYPE_DISCRETE; + interval->discrete = fie.interval; + return 0; } #ifdef CONFIG_VIDEO_ADV_DEBUG static int mcam_vidioc_g_register(struct file *file, void *priv, struct v4l2_dbg_register *reg) { - struct mcam_camera *cam = priv; + struct mcam_camera *cam = video_drvdata(file); - if (v4l2_chip_match_host(®->match)) { - reg->val = mcam_reg_read(cam, reg->reg); - reg->size = 4; - return 0; - } - return sensor_call(cam, core, g_register, reg); + if (reg->reg > cam->regs_size - 4) + return -EINVAL; + reg->val = mcam_reg_read(cam, reg->reg); + reg->size = 4; + return 0; } static int mcam_vidioc_s_register(struct file *file, void *priv, const struct v4l2_dbg_register *reg) { - struct mcam_camera *cam = priv; + struct mcam_camera *cam = video_drvdata(file); - if (v4l2_chip_match_host(®->match)) { - mcam_reg_write(cam, reg->reg, reg->val); - return 0; - } - return sensor_call(cam, core, s_register, reg); + if (reg->reg > cam->regs_size - 4) + return -EINVAL; + mcam_reg_write(cam, reg->reg, reg->val); + return 0; } #endif @@ -1466,18 +1586,20 @@ .vidioc_enum_input = mcam_vidioc_enum_input, .vidioc_g_input = mcam_vidioc_g_input, .vidioc_s_input = mcam_vidioc_s_input, - .vidioc_s_std = mcam_vidioc_s_std, - .vidioc_reqbufs = mcam_vidioc_reqbufs, - .vidioc_querybuf = mcam_vidioc_querybuf, - .vidioc_qbuf = mcam_vidioc_qbuf, - .vidioc_dqbuf = mcam_vidioc_dqbuf, - .vidioc_streamon = mcam_vidioc_streamon, - .vidioc_streamoff = mcam_vidioc_streamoff, + .vidioc_reqbufs = vb2_ioctl_reqbufs, + .vidioc_create_bufs = vb2_ioctl_create_bufs, + .vidioc_querybuf = vb2_ioctl_querybuf, + .vidioc_qbuf = vb2_ioctl_qbuf, + .vidioc_dqbuf = vb2_ioctl_dqbuf, + .vidioc_expbuf = vb2_ioctl_expbuf, + .vidioc_streamon = vb2_ioctl_streamon, + .vidioc_streamoff = vb2_ioctl_streamoff, .vidioc_g_parm = mcam_vidioc_g_parm, .vidioc_s_parm = mcam_vidioc_s_parm, .vidioc_enum_framesizes = mcam_vidioc_enum_framesizes, .vidioc_enum_frameintervals = mcam_vidioc_enum_frameintervals, - .vidioc_g_chip_ident = mcam_vidioc_g_chip_ident, + .vidioc_subscribe_event = v4l2_ctrl_subscribe_event, + .vidioc_unsubscribe_event = v4l2_event_unsubscribe, #ifdef CONFIG_VIDEO_ADV_DEBUG .vidioc_g_register = mcam_vidioc_g_register, .vidioc_s_register = mcam_vidioc_s_register, @@ -1491,97 +1613,53 @@ static int mcam_v4l_open(struct file *filp) { struct mcam_camera *cam = video_drvdata(filp); - int ret = 0; - - filp->private_data = cam; + int ret; - cam->frame_state.frames = 0; - cam->frame_state.singles = 0; - cam->frame_state.delivered = 0; mutex_lock(&cam->s_mutex); - if (cam->users == 0) { - ret = mcam_setup_vb2(cam); + ret = v4l2_fh_open(filp); + if (ret) + goto out; + if (v4l2_fh_is_singular_file(filp)) { + ret = mcam_ctlr_power_up(cam); if (ret) goto out; - mcam_ctlr_power_up(cam); __mcam_cam_reset(cam); mcam_set_config_needed(cam, 1); } - (cam->users)++; out: mutex_unlock(&cam->s_mutex); + if (ret) + v4l2_fh_release(filp); return ret; } static int mcam_v4l_release(struct file *filp) { - struct mcam_camera *cam = filp->private_data; + struct mcam_camera *cam = video_drvdata(filp); + bool last_open; - cam_dbg(cam, "Release, %d frames, %d singles, %d delivered\n", - cam->frame_state.frames, cam->frame_state.singles, - cam->frame_state.delivered); mutex_lock(&cam->s_mutex); - (cam->users)--; - if (cam->users == 0) { - mcam_ctlr_stop_dma(cam); - mcam_cleanup_vb2(cam); + last_open = v4l2_fh_is_singular_file(filp); + _vb2_fop_release(filp, NULL); + if (last_open) { + mcam_disable_mipi(cam); mcam_ctlr_power_down(cam); if (cam->buffer_mode == B_vmalloc && alloc_bufs_at_read) mcam_free_dma_bufs(cam); } - mutex_unlock(&cam->s_mutex); - return 0; -} - -static ssize_t mcam_v4l_read(struct file *filp, - char __user *buffer, size_t len, loff_t *pos) -{ - struct mcam_camera *cam = filp->private_data; - int ret; - - mutex_lock(&cam->s_mutex); - ret = vb2_read(&cam->vb_queue, buffer, len, pos, - filp->f_flags & O_NONBLOCK); - mutex_unlock(&cam->s_mutex); - return ret; -} - - -static unsigned int mcam_v4l_poll(struct file *filp, - struct poll_table_struct *pt) -{ - struct mcam_camera *cam = filp->private_data; - int ret; - - mutex_lock(&cam->s_mutex); - ret = vb2_poll(&cam->vb_queue, filp, pt); mutex_unlock(&cam->s_mutex); - return ret; -} - - -static int mcam_v4l_mmap(struct file *filp, struct vm_area_struct *vma) -{ - struct mcam_camera *cam = filp->private_data; - int ret; - - mutex_lock(&cam->s_mutex); - ret = vb2_mmap(&cam->vb_queue, vma); - mutex_unlock(&cam->s_mutex); - return ret; + return 0; } - - static const struct v4l2_file_operations mcam_v4l_fops = { .owner = THIS_MODULE, .open = mcam_v4l_open, .release = mcam_v4l_release, - .read = mcam_v4l_read, - .poll = mcam_v4l_poll, - .mmap = mcam_v4l_mmap, + .read = vb2_fop_read, + .poll = vb2_fop_poll, + .mmap = vb2_fop_mmap, .unlocked_ioctl = video_ioctl2, }; @@ -1592,9 +1670,6 @@ */ static struct video_device mcam_v4l_template = { .name = "mcam", - .tvnorms = V4L2_STD_NTSC_M, - .current_norm = V4L2_STD_NTSC_M, /* make mplayer happy */ - .fops = &mcam_v4l_fops, .ioctl_ops = &mcam_v4l_ioctl_ops, .release = video_device_release_empty, @@ -1612,7 +1687,7 @@ set_bit(frame, &cam->flags); clear_bit(CF_DMA_ACTIVE, &cam->flags); cam->next_buf = frame; - cam->buf_seq[frame] = ++(cam->sequence); + cam->buf_seq[frame] = cam->sequence++; cam->frame_state.frames++; /* * "This should never happen" @@ -1646,9 +1721,11 @@ * each time. */ for (frame = 0; frame < cam->nbufs; frame++) - if (irqs & (IRQ_EOF0 << frame)) { + if (irqs & (IRQ_EOF0 << frame) && + test_bit(CF_FRAME_SOF0 + frame, &cam->flags)) { mcam_frame_complete(cam, frame); handled = 1; + clear_bit(CF_FRAME_SOF0 + frame, &cam->flags); if (cam->buffer_mode == B_DMA_sg) break; } @@ -1657,9 +1734,15 @@ * code assumes that we won't get multiple frame interrupts * at once; may want to rethink that. */ - if (irqs & (IRQ_SOF0 | IRQ_SOF1 | IRQ_SOF2)) { + for (frame = 0; frame < cam->nbufs; frame++) { + if (irqs & (IRQ_SOF0 << frame)) { + set_bit(CF_FRAME_SOF0 + frame, &cam->flags); + handled = IRQ_HANDLED; + } + } + + if (handled == IRQ_HANDLED) { set_bit(CF_DMA_ACTIVE, &cam->flags); - handled = 1; if (cam->buffer_mode == B_DMA_sg) mcam_ctlr_stop(cam); } @@ -1695,7 +1778,7 @@ if (buffer_mode >= 0) cam->buffer_mode = buffer_mode; if (cam->buffer_mode == B_DMA_sg && - cam->chip_id == V4L2_IDENT_CAFE) { + cam->chip_id == MCAM_CAFE) { printk(KERN_ERR "marvell-cam: Cafe can't do S/G I/O, " "attempting vmalloc mode instead\n"); cam->buffer_mode = B_vmalloc; @@ -1717,10 +1800,17 @@ mcam_set_config_needed(cam, 1); cam->pix_format = mcam_def_pix_format; cam->mbus_code = mcam_def_mbus_code; - INIT_LIST_HEAD(&cam->buffers); mcam_ctlr_init(cam); /* + * Get the v4l2 setup done. + */ + ret = v4l2_ctrl_handler_init(&cam->ctrl_handler, 10); + if (ret) + goto out_unregister; + cam->v4l2_dev.ctrl_handler = &cam->ctrl_handler; + + /* * Try to find the sensor. */ sensor_cfg.clock_speed = cam->clock_speed; @@ -1736,22 +1826,22 @@ ret = mcam_cam_init(cam); if (ret) goto out_unregister; - /* - * Get the v4l2 setup done. - */ - ret = v4l2_ctrl_handler_init(&cam->ctrl_handler, 10); + + ret = mcam_setup_vb2(cam); if (ret) goto out_unregister; - cam->v4l2_dev.ctrl_handler = &cam->ctrl_handler; mutex_lock(&cam->s_mutex); cam->vdev = mcam_v4l_template; - cam->vdev.debug = 0; cam->vdev.v4l2_dev = &cam->v4l2_dev; + cam->vdev.lock = &cam->s_mutex; + cam->vdev.queue = &cam->vb_queue; video_set_drvdata(&cam->vdev, cam); ret = video_register_device(&cam->vdev, VFL_TYPE_GRABBER, -1); - if (ret) - goto out; + if (ret) { + mutex_unlock(&cam->s_mutex); + goto out_unregister; + } /* * If so requested, try to get our DMA buffers now. @@ -1762,11 +1852,11 @@ " will try again later."); } -out: - v4l2_ctrl_handler_free(&cam->ctrl_handler); mutex_unlock(&cam->s_mutex); - return ret; + return 0; + out_unregister: + v4l2_ctrl_handler_free(&cam->ctrl_handler); v4l2_device_unregister(&cam->v4l2_dev); return ret; } @@ -1780,11 +1870,11 @@ * take it down again will wedge the machine, which is frowned * upon. */ - if (cam->users > 0) { + if (!list_empty(&cam->vdev.fh_list)) { cam_warn(cam, "Removing a device with users!\n"); mcam_ctlr_power_down(cam); } - vb2_queue_release(&cam->vb_queue); + mcam_cleanup_vb2(cam); if (cam->buffer_mode == B_vmalloc) mcam_free_dma_bufs(cam); video_unregister_device(&cam->vdev); @@ -1800,7 +1890,7 @@ void mccic_suspend(struct mcam_camera *cam) { mutex_lock(&cam->s_mutex); - if (cam->users > 0) { + if (!list_empty(&cam->vdev.fh_list)) { enum mcam_state cstate = cam->state; mcam_ctlr_stop_dma(cam); @@ -1815,8 +1905,12 @@ int ret = 0; mutex_lock(&cam->s_mutex); - if (cam->users > 0) { - mcam_ctlr_power_up(cam); + if (!list_empty(&cam->vdev.fh_list)) { + ret = mcam_ctlr_power_up(cam); + if (ret) { + mutex_unlock(&cam->s_mutex); + return ret; + } __mcam_cam_reset(cam); } else { mcam_ctlr_power_down(cam);