Exemplo n.º 1
0
static void iss_video_buf_queue(struct vb2_buffer *vb)
{
	struct iss_video_fh *vfh = vb2_get_drv_priv(vb->vb2_queue);
	struct iss_video *video = vfh->video;
	struct iss_buffer *buffer = container_of(vb, struct iss_buffer, vb);
	struct iss_pipeline *pipe = to_iss_pipeline(&video->video.entity);
	unsigned long flags;
	bool empty;

	spin_lock_irqsave(&video->qlock, flags);

	/* Mark the buffer is faulty and give it back to the queue immediately
	 * if the video node has registered an error. vb2 will perform the same
	 * check when preparing the buffer, but that is inherently racy, so we
	 * need to handle the race condition with an authoritative check here.
	 */
	if (unlikely(video->error)) {
		vb2_buffer_done(vb, VB2_BUF_STATE_ERROR);
		spin_unlock_irqrestore(&video->qlock, flags);
		return;
	}

	empty = list_empty(&video->dmaqueue);
	list_add_tail(&buffer->list, &video->dmaqueue);

	spin_unlock_irqrestore(&video->qlock, flags);

	if (empty) {
		enum iss_pipeline_state state;
		unsigned int start;

		if (video->type == V4L2_BUF_TYPE_VIDEO_CAPTURE)
			state = ISS_PIPELINE_QUEUE_OUTPUT;
		else
			state = ISS_PIPELINE_QUEUE_INPUT;

		spin_lock_irqsave(&pipe->lock, flags);
		pipe->state |= state;
		video->ops->queue(video, buffer);
		video->dmaqueue_flags |= ISS_VIDEO_DMAQUEUE_QUEUED;

		start = iss_pipeline_ready(pipe);
		if (start)
			pipe->state |= ISS_PIPELINE_STREAM;
		spin_unlock_irqrestore(&pipe->lock, flags);

		if (start)
			omap4iss_pipeline_set_stream(pipe,
						ISS_PIPELINE_STREAM_SINGLESHOT);
	}
}
Exemplo n.º 2
0
/*
 * iss_module_sync_idle - Helper to sync module with its idle state
 * @me: ISS submodule's media entity
 * @wait: ISS submodule's wait queue for streamoff/interrupt synchronization
 * @stopping: flag which tells module wants to stop
 *
 * This function checks if ISS submodule needs to wait for next interrupt. If
 * yes, makes the caller to sleep while waiting for such event.
 */
int omap4iss_module_sync_idle(struct media_entity *me, wait_queue_head_t *wait,
			      atomic_t *stopping)
{
	struct iss_pipeline *pipe = to_iss_pipeline(me);
	struct iss_video *video = pipe->output;
	unsigned long flags;

	if (pipe->stream_state == ISS_PIPELINE_STREAM_STOPPED ||
	    (pipe->stream_state == ISS_PIPELINE_STREAM_SINGLESHOT &&
	     !iss_pipeline_ready(pipe)))
		return 0;

	/*
	 * atomic_set() doesn't include memory barrier on ARM platform for SMP
	 * scenario. We'll call it here to avoid race conditions.
	 */
	atomic_set(stopping, 1);
	smp_wmb();

	/*
	 * If module is the last one, it's writing to memory. In this case,
	 * it's necessary to check if the module is already paused due to
	 * DMA queue underrun or if it has to wait for next interrupt to be
	 * idle.
	 * If it isn't the last one, the function won't sleep but *stopping
	 * will still be set to warn next submodule caller's interrupt the
	 * module wants to be idle.
	 */
	if (!iss_pipeline_is_last(me))
		return 0;

	spin_lock_irqsave(&video->qlock, flags);
	if (video->dmaqueue_flags & ISS_VIDEO_DMAQUEUE_UNDERRUN) {
		spin_unlock_irqrestore(&video->qlock, flags);
		atomic_set(stopping, 0);
		smp_wmb();
		return 0;
	}
	spin_unlock_irqrestore(&video->qlock, flags);
	if (!wait_event_timeout(*wait, !atomic_read(stopping),
				msecs_to_jiffies(1000))) {
		atomic_set(stopping, 0);
		smp_wmb();
		return -ETIMEDOUT;
	}

	return 0;
}
Exemplo n.º 3
0
static void iss_video_buf_queue(struct vb2_buffer *vb)
{
	struct iss_video_fh *vfh = vb2_get_drv_priv(vb->vb2_queue);
	struct iss_video *video = vfh->video;
	struct iss_buffer *buffer = container_of(vb, struct iss_buffer, vb);
	struct iss_pipeline *pipe = to_iss_pipeline(&video->video.entity);
	unsigned long flags;
	bool empty;

	spin_lock_irqsave(&video->qlock, flags);

	if (unlikely(video->error)) {
		vb2_buffer_done(vb, VB2_BUF_STATE_ERROR);
		spin_unlock_irqrestore(&video->qlock, flags);
		return;
	}

	empty = list_empty(&video->dmaqueue);
	list_add_tail(&buffer->list, &video->dmaqueue);

	spin_unlock_irqrestore(&video->qlock, flags);

	if (empty) {
		enum iss_pipeline_state state;
		unsigned int start;

		if (video->type == V4L2_BUF_TYPE_VIDEO_CAPTURE)
			state = ISS_PIPELINE_QUEUE_OUTPUT;
		else
			state = ISS_PIPELINE_QUEUE_INPUT;

		spin_lock_irqsave(&pipe->lock, flags);
		pipe->state |= state;
		video->ops->queue(video, buffer);
		video->dmaqueue_flags |= ISS_VIDEO_DMAQUEUE_QUEUED;

		start = iss_pipeline_ready(pipe);
		if (start)
			pipe->state |= ISS_PIPELINE_STREAM;
		spin_unlock_irqrestore(&pipe->lock, flags);

		if (start)
			omap4iss_pipeline_set_stream(pipe,
						ISS_PIPELINE_STREAM_SINGLESHOT);
	}
}