static int nxp_video_streamon(struct file *file, void *fh, enum v4l2_buf_type i) { int ret; u32 pad; struct nxp_video *me = file->private_data; struct v4l2_subdev *subdev = _get_remote_subdev(me, i, &pad); void *hostdata_back; vmsg("%s: me %p, %s\n", __func__, me, me->name); if (me->vbq) { ret = vb2_streamon(me->vbq, i); if (ret < 0) { pr_err("%s: failed to vb2_streamon()\n", __func__); return ret; } } else { struct vb2_queue *vq = v4l2_m2m_get_vq(me->m2m_ctx, i); ret = vb2_streamon(vq, i); if (ret < 0) { pr_err("%s: m2m, failed to vb2_streamon()\n", __func__); return ret; } } /* for mlc subdev */ hostdata_back = v4l2_get_subdev_hostdata(subdev); v4l2_set_subdev_hostdata(subdev, me->name); ret = v4l2_subdev_call(subdev, video, s_stream, 1); v4l2_set_subdev_hostdata(subdev, hostdata_back); return ret; }
/* Stream on */ static int vidioc_streamon(struct file *file, void *priv, enum v4l2_buf_type type) { struct s5p_mfc_ctx *ctx = fh_to_ctx(priv); int ret = -EINVAL; mfc_debug_enter(); if (type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) ret = vb2_streamon(&ctx->vq_src, type); else if (type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) ret = vb2_streamon(&ctx->vq_dst, type); mfc_debug_leave(); return ret; }
static int gsc_capture_streamon(struct file *file, void *priv, enum v4l2_buf_type type) { struct gsc_dev *gsc = video_drvdata(file); struct gsc_pipeline *p = &gsc->pipeline; int ret; if (gsc_cap_active(gsc)) return -EBUSY; if (p->disp) { gsc_pm_qos_ctrl(gsc, GSC_QOS_ON, 267000, 200000); media_entity_pipeline_start(&p->disp->entity, p->pipe); } else if (p->sensor) { media_entity_pipeline_start(&p->sensor->entity, p->pipe); } else { gsc_err("Error pipeline"); return -EPIPE; } ret = gsc_cap_link_validate(gsc); if (ret) return ret; gsc_hw_set_sw_reset(gsc); ret= gsc_wait_reset(gsc); if (ret < 0) { gsc_err("gscaler s/w reset timeout"); return ret; } gsc_hw_set_output_buf_mask_all(gsc); return vb2_streamon(&gsc->cap.vbq, type); }
static int gsc_capture_streamon(struct file *file, void *priv, enum v4l2_buf_type type) { struct gsc_dev *gsc = video_drvdata(file); struct gsc_pipeline *p = &gsc->pipeline; int ret; if (gsc_cap_active(gsc)) return -EBUSY; if (p->disp) { media_entity_pipeline_start(&p->disp->entity, p->pipe); } else if (p->sensor) { media_entity_pipeline_start(&p->sensor->entity, p->pipe); } else { gsc_err("Error pipeline"); return -EPIPE; } ret = gsc_cap_link_validate(gsc); if (ret) return ret; return vb2_streamon(&gsc->cap.vbq, type); }
static int mxr_streamon(struct file *file, void *priv, enum v4l2_buf_type i) { struct mxr_layer *layer = video_drvdata(file); struct mxr_device *mdev = layer->mdev; switch (layer->idx) { case 0: mdev->layer_en.graph0 = 1; break; case 1: mdev->layer_en.graph1 = 1; break; case 2: mdev->layer_en.graph2 = 1; break; case 3: mdev->layer_en.graph3 = 1; break; default: mxr_err(mdev, "invalid layer number\n"); return -EINVAL; } if ((mdev->layer_en.graph0 && mdev->layer_en.graph2) || (mdev->layer_en.graph1 && mdev->layer_en.graph3)) { mdev->frame_packing = 1; mxr_dbg(mdev, "frame packing mode\n"); } mxr_dbg(layer->mdev, "%s:%d\n", __func__, __LINE__); return vb2_streamon(&layer->vb_queue, i); }
static int wfdioc_streamon(struct file *filp, void *fh, enum v4l2_buf_type i) { int rc = 0; struct wfd_inst *inst = filp->private_data; unsigned long flags; if (i != V4L2_BUF_TYPE_VIDEO_CAPTURE) { WFD_MSG_ERR("stream on for buffer type = %d is not " "supported.\n", i); return -EINVAL; } spin_lock_irqsave(&inst->inst_lock, flags); inst->streamoff = false; spin_unlock_irqrestore(&inst->inst_lock, flags); /*TODO: Do we need to lock the instance here*/ rc = vb2_streamon(&inst->vid_bufq, i); if (rc) { WFD_MSG_ERR("videobuf_streamon failed with err = %d\n", rc); goto vidbuf_streamon_failed; } inst->mdp_task = kthread_run(mdp_output_thread, filp, "mdp_output_thread"); if (IS_ERR(inst->mdp_task)) { rc = PTR_ERR(inst->mdp_task); goto mdp_task_failed; } return rc; mdp_task_failed: vb2_streamoff(&inst->vid_bufq, i); vidbuf_streamon_failed: return rc; }
/* * Enable or disable the video buffers queue. * * The queue must be enabled before starting video acquisition and must be * disabled after stopping it. This ensures that the video buffers queue * state can be properly initialized before buffers are accessed from the * interrupt handler. * * Enabling the video queue returns -EBUSY if the queue is already enabled. * * Disabling the video queue cancels the queue and removes all buffers from * the main queue. * * This function can't be called from interrupt context. Use * uvc_queue_cancel() instead. */ int uvc_queue_enable(struct uvc_video_queue *queue, int enable) { unsigned long flags; int ret; mutex_lock(&queue->mutex); if (enable) { ret = vb2_streamon(&queue->queue, queue->queue.type); if (ret < 0) goto done; queue->buf_used = 0; } else { ret = vb2_streamoff(&queue->queue, queue->queue.type); if (ret < 0) goto done; spin_lock_irqsave(&queue->irqlock, flags); INIT_LIST_HEAD(&queue->irqqueue); spin_unlock_irqrestore(&queue->irqlock, flags); } done: mutex_unlock(&queue->mutex); return ret; }
/* * Enable or disable the video buffers queue. * * The queue must be enabled before starting video acquisition and must be * disabled after stopping it. This ensures that the video buffers queue * state can be properly initialized before buffers are accessed from the * interrupt handler. * * Enabling the video queue initializes parameters (such as sequence number, * sync pattern, ...). If the queue is already enabled, return -EBUSY. * * Disabling the video queue cancels the queue and removes all buffers from * the main queue. * * This function can't be called from interrupt context. Use * uvcg_queue_cancel() instead. */ int uvcg_queue_enable(struct uvc_video_queue *queue, int enable) { unsigned long flags; int ret = 0; mutex_lock(&queue->mutex); if (enable) { ret = vb2_streamon(&queue->queue, queue->queue.type); if (ret < 0) goto done; queue->sequence = 0; queue->buf_used = 0; } else { ret = vb2_streamoff(&queue->queue, queue->queue.type); if (ret < 0) goto done; spin_lock_irqsave(&queue->irqlock, flags); INIT_LIST_HEAD(&queue->irqqueue); /* * FIXME: We need to clear the DISCONNECTED flag to ensure that * applications will be able to queue buffers for the next * streaming run. However, clearing it here doesn't guarantee * that the device will be reconnected in the meantime. */ queue->flags &= ~UVC_QUEUE_DISCONNECTED; spin_unlock_irqrestore(&queue->irqlock, flags); } done: mutex_unlock(&queue->mutex); return ret; }
static int at91sam9x5_video_vidioc_streamon(struct file *filp, void *fh, enum v4l2_buf_type type) { struct video_device *vdev = video_devdata(filp); struct at91sam9x5_video_priv *priv = video_get_drvdata(vdev); return vb2_streamon(&priv->queue, type); }
static int fimc_is_isp_video_streamon(struct file *file, void *priv, enum v4l2_buf_type type) { struct fimc_is_dev *is_dev = video_drvdata(file); printk(KERN_DEBUG "%s\n", __func__); return vb2_streamon(&is_dev->video[FIMC_IS_VIDEO_NUM_BAYER].vbq, type); }
int vb2_ioctl_streamon(struct file *file, void *priv, enum v4l2_buf_type i) { struct video_device *vdev = video_devdata(file); if (vb2_queue_is_busy(vdev, file)) return -EBUSY; return vb2_streamon(vdev->queue, i); }
int uvc_queue_streamon(struct uvc_video_queue *queue, enum v4l2_buf_type type) { int ret; mutex_lock(&queue->mutex); ret = vb2_streamon(&queue->queue, type); mutex_unlock(&queue->mutex); return ret; }
/* Stream on */ static int vidioc_streamon(struct file *file, void *priv, enum v4l2_buf_type type) { struct s5p_mfc_ctx *ctx = fh_to_ctx(priv); struct s5p_mfc_dev *dev = ctx->dev; int ret = -EINVAL; mfc_debug_enter(); if (type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) { if (ctx->state == MFCINST_INIT) { ctx->dst_bufs_cnt = 0; ctx->src_bufs_cnt = 0; ctx->capture_state = QUEUE_FREE; ctx->output_state = QUEUE_FREE; s5p_mfc_hw_call(dev->mfc_ops, alloc_instance_buffer, ctx); s5p_mfc_hw_call(dev->mfc_ops, alloc_dec_temp_buffers, ctx); set_work_bit_irqsave(ctx); s5p_mfc_clean_ctx_int_flags(ctx); s5p_mfc_hw_call(dev->mfc_ops, try_run, dev); if (s5p_mfc_wait_for_done_ctx(ctx, S5P_MFC_R2H_CMD_OPEN_INSTANCE_RET, 0)) { /* Error or timeout */ mfc_err("Error getting instance from hardware\n"); s5p_mfc_hw_call(dev->mfc_ops, release_instance_buffer, ctx); s5p_mfc_hw_call(dev->mfc_ops, release_dec_desc_buffer, ctx); return -EIO; } mfc_debug(2, "Got instance number: %d\n", ctx->inst_no); } ret = vb2_streamon(&ctx->vq_src, type); } else if (type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) ret = vb2_streamon(&ctx->vq_dst, type); mfc_debug_leave(); return ret; }
static int hwcam_dev_vo_streamon( struct file* filep, void* fh, enum v4l2_buf_type buf_type) { hwcam_dev_t* cam = video_drvdata(filep); hwcam_user_t* user = VO2USER(fh); BUG_ON(!cam || !user); return vb2_streamon(&user->vb2q, buf_type); }
static int gsc_capture_streamon(struct file *file, void *priv, enum v4l2_buf_type type) { struct gsc_dev *gsc = video_drvdata(file); if (gsc_cap_active(gsc)) { gsc_err("gsc didn't stop complete"); return -EBUSY; } return vb2_streamon(&gsc->cap.vbq, type); }
/* * msm_fd_streamon - V4l2 ioctl stream on handler. * @file: Pointer to file struct. * @fh: V4l2 File handle. * @buf_type: V4l2 buffer type. */ static int msm_fd_streamon(struct file *file, void *fh, enum v4l2_buf_type buf_type) { struct fd_ctx *ctx = msm_fd_ctx_from_fh(fh); int ret; ret = vb2_streamon(&ctx->vb2_q, buf_type); if (ret < 0) dev_err(ctx->fd_device->dev, "Stream on fails\n"); return ret; }
/** * v4l2_m2m_streamon() - turn on streaming for a video queue */ int v4l2_m2m_streamon(struct file *file, struct v4l2_m2m_ctx *m2m_ctx, enum v4l2_buf_type type) { struct vb2_queue *vq; int ret; vq = v4l2_m2m_get_vq(m2m_ctx, type); ret = vb2_streamon(vq, type); if (!ret) v4l2_m2m_try_schedule(m2m_ctx); return ret; }
static int fimc_cap_streamon(struct file *file, void *priv, enum v4l2_buf_type type) { struct fimc_ctx *ctx = priv; struct fimc_dev *fimc = ctx->fimc_dev; if (fimc_capture_active(fimc) || !fimc->vid_cap.sd) return -EBUSY; if (!(ctx->state & FIMC_DST_FMT)) { v4l2_err(&fimc->vid_cap.v4l2_dev, "Format is not set\n"); return -EINVAL; } return vb2_streamon(&fimc->vid_cap.vbq, type); }
int fimc_is_video_streamon(struct file *file, struct fimc_is_video_ctx *vctx, enum v4l2_buf_type type) { int ret = 0; struct vb2_queue *vbq; BUG_ON(!file); BUG_ON(!vctx); if (!(vctx->state & (BIT(FIMC_IS_VIDEO_S_BUFS) | BIT(FIMC_IS_VIDEO_STOP)))) { err("[V%02d] invalid streamon is requested(%lX)", vctx->video->id, vctx->state); return -EINVAL; } vbq = GET_QUEUE(vctx)->vbq; if (!vbq) { merr("vbq is NULL", vctx); ret = -EINVAL; goto p_err; } if (vbq->type != type) { merr("invalid stream type(%d != %d)", vctx, vbq->type, type); ret = -EINVAL; goto p_err; } if (vbq->streaming) { merr("streamon: already streaming", vctx); ret = -EINVAL; goto p_err; } ret = vb2_streamon(vbq, type); if (ret) { err("[V%02d] vb2_streamon is fail(%d)", vctx->video->id, ret); goto p_err; } vctx->state = BIT(FIMC_IS_VIDEO_START); p_err: return ret; }
static int camera_v4l2_streamon(struct file *filep, void *fh, enum v4l2_buf_type buf_type) { struct v4l2_event event; int rc; struct camera_v4l2_private *sp = fh_to_private(fh); rc = vb2_streamon(&sp->vb2_q, buf_type); camera_pack_event(filep, MSM_CAMERA_SET_PARM, MSM_CAMERA_PRIV_STREAM_ON, -1, &event); rc = msm_post_event(&event, MSM_POST_EVT_TIMEOUT); if (rc < 0) return rc; rc = camera_check_event_status(&event); return rc; }
/* * Enable or disable the video buffers queue. * * The queue must be enabled before starting video acquisition and must be * disabled after stopping it. This ensures that the video buffers queue * state can be properly initialized before buffers are accessed from the * interrupt handler. * * Enabling the video queue initializes parameters (such as sequence number, * sync pattern, ...). If the queue is already enabled, return -EBUSY. * * Disabling the video queue cancels the queue and removes all buffers from * the main queue. * * This function can't be called from interrupt context. Use * uvcg_queue_cancel() instead. */ int uvcg_queue_enable(struct uvc_video_queue *queue, int enable) { unsigned long flags; int ret = 0; if (enable) { ret = vb2_streamon(&queue->queue, queue->queue.type); if (ret < 0) return ret; queue->sequence = 0; queue->buf_used = 0; } else { ret = vb2_streamoff(&queue->queue, queue->queue.type); if (ret < 0) return ret; spin_lock_irqsave(&queu
static int fimc_cap_streamon(struct file *file, void *priv, enum v4l2_buf_type type) { struct fimc_dev *fimc = video_drvdata(file); struct fimc_pipeline *p = &fimc->pipeline; int ret; if (fimc_capture_active(fimc)) return -EBUSY; media_entity_pipeline_start(&p->sensor->entity, p->pipe); if (fimc->vid_cap.user_subdev_api) { ret = fimc_pipeline_validate(fimc); if (ret) return ret; } return vb2_streamon(&fimc->vid_cap.vbq, type); }
static int xvip_dma_streamon(struct file *file, void *fh, enum v4l2_buf_type type) { struct v4l2_fh *vfh = file->private_data; struct xvip_dma *dma = to_xvip_dma(vfh->vdev); int ret; mutex_lock(&dma->lock); if (dma->queue.owner && dma->queue.owner != vfh) { ret = -EBUSY; goto done; } ret = vb2_streamon(&dma->queue, type); done: mutex_unlock(&dma->lock); return ret; }
static int fimc_lite_streamon(struct file *file, void *priv, enum v4l2_buf_type type) { struct fimc_lite *fimc = video_drvdata(file); struct v4l2_subdev *sensor = fimc->pipeline.subdevs[IDX_SENSOR]; struct fimc_pipeline *p = &fimc->pipeline; int ret; if (fimc_lite_active(fimc)) return -EBUSY; ret = media_entity_pipeline_start(&sensor->entity, p->m_pipeline); if (ret < 0) return ret; ret = fimc_pipeline_validate(fimc); if (ret) { media_entity_pipeline_stop(&sensor->entity); return ret; } return vb2_streamon(&fimc->vb_queue, type); }
int fimc_is_video_streamon(struct file *file, struct fimc_is_video_ctx *vctx, enum v4l2_buf_type type) { int ret = 0; struct fimc_is_queue *queue; struct vb2_queue *vbq; BUG_ON(!file); BUG_ON(!vctx); queue = GET_QUEUE(vctx, type); vbq = queue->vbq; if (!vbq) { merr("vbq is NULL", vctx); ret = -EINVAL; goto p_err; } if (vbq->type != type) { merr("invalid stream type(%d != %d)", vctx, vbq->type, type); ret = -EINVAL; goto p_err; } if (vbq->streaming) { merr("streamon: already streaming", vctx); ret = -EINVAL; goto p_err; } ret = vb2_streamon(vbq, type); p_err: return ret; }
static int fimc_cap_streamon(struct file *file, void *priv, enum v4l2_buf_type type) { struct fimc_dev *fimc = video_drvdata(file); struct fimc_pipeline *p = &fimc->pipeline; struct v4l2_subdev *sd = p->subdevs[IDX_SENSOR]; int ret; if (fimc_capture_active(fimc)) return -EBUSY; ret = media_entity_pipeline_start(&sd->entity, p->m_pipeline); if (ret < 0) return ret; if (fimc->vid_cap.user_subdev_api) { ret = fimc_pipeline_validate(fimc); if (ret < 0) { media_entity_pipeline_stop(&sd->entity); return ret; } } return vb2_streamon(&fimc->vid_cap.vbq, type); }
static int vidioc_streamon(struct file *file, void *priv, enum v4l2_buf_type i) { struct vcap_client_data *c_data = file->private_data; int rc; dprintk(3, "In Stream ON\n"); if (determine_mode(c_data) != c_data->op_mode) { pr_err("VCAP Error: %s: s_fmt called after req_buf", __func__); return -ENOTRECOVERABLE; } switch (c_data->op_mode) { case VC_VCAP_OP: c_data->dev->vc_client = c_data; config_vc_format(c_data); return vb2_streamon(&c_data->vc_vidq, i); case VP_VCAP_OP: rc = streamon_validate_q(&c_data->vp_in_vidq); if (rc < 0) return rc; rc = streamon_validate_q(&c_data->vp_out_vidq); if (rc < 0) return rc; c_data->dev->vp_client = c_data; rc = config_vp_format(c_data); if (rc < 0) return rc; rc = init_motion_buf(c_data); if (rc < 0) return rc; if (c_data->vid_vp_action.nr_enabled) { rc = init_nr_buf(c_data); if (rc < 0) goto s_on_deinit_m_buf; } c_data->vid_vp_action.vp_state = VP_FRAME1; rc = vb2_streamon(&c_data->vp_in_vidq, V4L2_BUF_TYPE_INTERLACED_IN_DECODER); if (rc < 0) goto s_on_deinit_nr_buf; rc = vb2_streamon(&c_data->vp_out_vidq, V4L2_BUF_TYPE_VIDEO_OUTPUT); if (rc < 0) goto s_on_deinit_nr_buf; return rc; case VC_AND_VP_VCAP_OP: rc = streamon_validate_q(&c_data->vc_vidq); if (rc < 0) return rc; rc = streamon_validate_q(&c_data->vp_in_vidq); if (rc < 0) return rc; rc = streamon_validate_q(&c_data->vp_out_vidq); if (rc < 0) return rc; c_data->dev->vc_client = c_data; c_data->dev->vp_client = c_data; c_data->dev->vc_to_vp_work.cd = c_data; rc = config_vc_format(c_data); if (rc < 0) return rc; rc = config_vp_format(c_data); if (rc < 0) return rc; rc = init_motion_buf(c_data); if (rc < 0) return rc; if (c_data->vid_vp_action.nr_enabled) { rc = init_nr_buf(c_data); if (rc < 0) goto s_on_deinit_m_buf; } c_data->streaming = 1; c_data->vid_vp_action.vp_state = VP_FRAME1; /* These stream on calls should not fail */ rc = vb2_streamon(&c_data->vc_vidq, V4L2_BUF_TYPE_VIDEO_CAPTURE); if (rc < 0) goto s_on_deinit_nr_buf; rc = vb2_streamon(&c_data->vp_in_vidq, V4L2_BUF_TYPE_INTERLACED_IN_DECODER); if (rc < 0) goto s_on_deinit_nr_buf; rc = vb2_streamon(&c_data->vp_out_vidq, V4L2_BUF_TYPE_VIDEO_OUTPUT); if (rc < 0) goto s_on_deinit_nr_buf; return rc; default: pr_err("VCAP Error: %s: Operation Mode type", __func__); return -ENOTRECOVERABLE; } return 0; s_on_deinit_nr_buf: if (c_data->vid_vp_action.nr_enabled) deinit_nr_buf(c_data); s_on_deinit_m_buf: deinit_motion_buf(c_data); return rc; }
/** * __vb2_perform_fileio() - perform a single file io (read or write) operation * @q: videobuf2 queue * @data: pointed to target userspace buffer * @count: number of bytes to read or write * @ppos: file handle position tracking pointer * @nonblock: mode selector (1 means blocking calls, 0 means nonblocking) * @read: access mode selector (1 means read, 0 means write) */ static size_t __vb2_perform_fileio(struct vb2_queue *q, char __user *data, size_t count, loff_t *ppos, int nonblock, int read) { struct vb2_fileio_data *fileio; struct vb2_fileio_buf *buf; int ret, index; dprintk(3, "file io: mode %s, offset %ld, count %zd, %sblocking\n", read ? "read" : "write", (long)*ppos, count, nonblock ? "non" : ""); if (!data) return -EINVAL; /* * Initialize emulator on first call. */ if (!q->fileio) { ret = __vb2_init_fileio(q, read); dprintk(3, "file io: vb2_init_fileio result: %d\n", ret); if (ret) return ret; } fileio = q->fileio; /* * Hack fileio context to enable direct calls to vb2 ioctl interface. * The pointer will be restored before returning from this function. */ q->fileio = NULL; index = fileio->index; buf = &fileio->bufs[index]; /* * Check if we need to dequeue the buffer. */ if (buf->queued) { struct vb2_buffer *vb; /* * Call vb2_dqbuf to get buffer back. */ memset(&fileio->b, 0, sizeof(fileio->b)); fileio->b.type = q->type; fileio->b.memory = q->memory; fileio->b.index = index; ret = vb2_dqbuf(q, &fileio->b, nonblock); dprintk(5, "file io: vb2_dqbuf result: %d\n", ret); if (ret) goto end; fileio->dq_count += 1; /* * Get number of bytes filled by the driver */ vb = q->bufs[index]; buf->size = vb2_get_plane_payload(vb, 0); buf->queued = 0; } /* * Limit count on last few bytes of the buffer. */ if (buf->pos + count > buf->size) { count = buf->size - buf->pos; dprintk(5, "reducing read count: %zd\n", count); } /* * Transfer data to userspace. */ dprintk(3, "file io: copying %zd bytes - buffer %d, offset %u\n", count, index, buf->pos); if (read) ret = copy_to_user(data, buf->vaddr + buf->pos, count); else ret = copy_from_user(buf->vaddr + buf->pos, data, count); if (ret) { dprintk(3, "file io: error copying data\n"); ret = -EFAULT; goto end; } /* * Update counters. */ buf->pos += count; *ppos += count; /* * Queue next buffer if required. */ if (buf->pos == buf->size || (!read && (fileio->flags & VB2_FILEIO_WRITE_IMMEDIATELY))) { /* * Check if this is the last buffer to read. */ if (read && (fileio->flags & VB2_FILEIO_READ_ONCE) && fileio->dq_count == 1) { dprintk(3, "file io: read limit reached\n"); /* * Restore fileio pointer and release the context. */ q->fileio = fileio; return __vb2_cleanup_fileio(q); } /* * Call vb2_qbuf and give buffer to the driver. */ memset(&fileio->b, 0, sizeof(fileio->b)); fileio->b.type = q->type; fileio->b.memory = q->memory; fileio->b.index = index; fileio->b.bytesused = buf->pos; ret = vb2_qbuf(q, &fileio->b); dprintk(5, "file io: vb2_dbuf result: %d\n", ret); if (ret) goto end; /* * Buffer has been queued, update the status */ buf->pos = 0; buf->queued = 1; buf->size = q->bufs[0]->v4l2_planes[0].length; fileio->q_count += 1; /* * Switch to the next buffer */ fileio->index = (index + 1) % q->num_buffers; /* * Start streaming if required. */ if (!read && !q->streaming) { ret = vb2_streamon(q, q->type); if (ret) goto end; } } /* * Return proper number of bytes processed. */ if (ret == 0) ret = count; end: /* * Restore the fileio context and block vb2 ioctl interface. */ q->fileio = fileio; return ret; }
/** * __vb2_init_fileio() - initialize file io emulator * @q: videobuf2 queue * @read: mode selector (1 means read, 0 means write) */ static int __vb2_init_fileio(struct vb2_queue *q, int read) { struct vb2_fileio_data *fileio; int i, ret; unsigned int count = 0; /* * Sanity check */ if ((read && !(q->io_modes & VB2_READ)) || (!read && !(q->io_modes & VB2_WRITE))) BUG(); /* * Check if device supports mapping buffers to kernel virtual space. */ if (!q->mem_ops->vaddr) return -EBUSY; /* * Check if streaming api has not been already activated. */ if (q->streaming || q->num_buffers > 0) return -EBUSY; /* * Start with count 1, driver can increase it in queue_setup() */ count = 1; dprintk(3, "setting up file io: mode %s, count %d, flags %08x\n", (read) ? "read" : "write", count, q->io_flags); fileio = kzalloc(sizeof(struct vb2_fileio_data), GFP_KERNEL); if (fileio == NULL) return -ENOMEM; fileio->flags = q->io_flags; /* * Request buffers and use MMAP type to force driver * to allocate buffers by itself. */ fileio->req.count = count; fileio->req.memory = V4L2_MEMORY_MMAP; fileio->req.type = q->type; ret = vb2_reqbufs(q, &fileio->req); if (ret) goto err_kfree; /* * Check if plane_count is correct * (multiplane buffers are not supported). */ if (q->bufs[0]->num_planes != 1) { fileio->req.count = 0; ret = -EBUSY; goto err_reqbufs; } /* * Get kernel address of each buffer. */ for (i = 0; i < q->num_buffers; i++) { fileio->bufs[i].vaddr = vb2_plane_vaddr(q->bufs[i], 0); if (fileio->bufs[i].vaddr == NULL) goto err_reqbufs; fileio->bufs[i].size = vb2_plane_size(q->bufs[i], 0); } /* * Read mode requires pre queuing of all buffers. */ if (read) { /* * Queue all buffers. */ for (i = 0; i < q->num_buffers; i++) { struct v4l2_buffer *b = &fileio->b; memset(b, 0, sizeof(*b)); b->type = q->type; b->memory = q->memory; b->index = i; ret = vb2_qbuf(q, b); if (ret) goto err_reqbufs; fileio->bufs[i].queued = 1; } /* * Start streaming. */ ret = vb2_streamon(q, q->type); if (ret) goto err_reqbufs; } q->fileio = fileio; return ret; err_reqbufs: vb2_reqbufs(q, &fileio->req); err_kfree: kfree(fileio); return ret; }
static int myvivi_vidioc_streamon(struct file *file, void *priv, enum v4l2_buf_type i) { return vb2_streamon(&myvivi_vb_vidqueue, i); }