Exemplo n.º 1
0
/*
 * isp_video_buffer_queue - Add buffer to streaming queue
 * @buf: Video buffer
 *
 * In memory-to-memory mode, start streaming on the pipeline if buffers are
 * queued on both the input and the output, if the pipeline isn't already busy.
 * If the pipeline is busy, it will be restarted in the output module interrupt
 * handler.
 */
static void isp_video_buffer_queue(struct isp_video_buffer *buf)
{
	struct isp_video_fh *vfh = isp_video_queue_to_isp_video_fh(buf->queue);
	struct isp_buffer *buffer = to_isp_buffer(buf);
	struct isp_video *video = vfh->video;
	struct isp_pipeline *pipe = to_isp_pipeline(&video->video.entity);
	enum isp_pipeline_state state;
	unsigned long flags;
	unsigned int empty;
	unsigned int start;

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

	if (empty) {
		if (video->type == V4L2_BUF_TYPE_VIDEO_CAPTURE)
			state = ISP_PIPELINE_QUEUE_OUTPUT;
		else
			state = ISP_PIPELINE_QUEUE_INPUT;

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

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

		if (start)
			isp_pipeline_set_stream(pipe,
						ISP_PIPELINE_STREAM_SINGLESHOT);
	}
}
Exemplo n.º 2
0
static int
isp_video_streamoff(struct file *file, void *fh, enum v4l2_buf_type type)
{
	struct isp_video_fh *vfh = to_isp_video_fh(fh);
	struct isp_video *video = video_drvdata(file);
	enum isp_pipeline_state state;
	unsigned int streaming;
	unsigned long flags;

	if (type != video->type)
		return -EINVAL;

	mutex_lock(&video->stream_lock);

	/* Make sure we're not streaming yet. */
	mutex_lock(&vfh->queue.lock);
	streaming = vfh->queue.streaming;
	mutex_unlock(&vfh->queue.lock);

	if (video->pipe == NULL || !streaming)
		goto done;

	/* Update the pipeline state. */
	if (video->type == V4L2_BUF_TYPE_VIDEO_CAPTURE)
		state = ISP_PIPELINE_STREAM_OUTPUT
		      | ISP_PIPELINE_QUEUE_OUTPUT;
	else
		state = ISP_PIPELINE_STREAM_INPUT
		      | ISP_PIPELINE_QUEUE_INPUT;

	spin_lock_irqsave(&video->pipe->lock, flags);
	video->pipe->state &= ~state;
	spin_unlock_irqrestore(&video->pipe->lock, flags);

	/* Stop the stream. */
	isp_pipeline_set_stream(video->isp, video->pipe->output,
				ISP_PIPELINE_STREAM_STOPPED);

	isp_video_queue_streamoff(&vfh->queue);
	video->pipe = NULL;
	video->queue = NULL;

	omap_pm_set_min_bus_tput(video->isp->dev, OCP_INITIATOR_AGENT, 0);
	media_entity_graph_unlock(&video->video.entity);

done:
	mutex_unlock(&video->stream_lock);
	return 0;
}
Exemplo n.º 3
0
/*
 * Stream management
 *
 * Every ISP pipeline has a single input and a single output. The input can be
 * either a sensor or a video node. The output is always a video node.
 *
 * As every pipeline has an output video node, the ISP video objects at the
 * pipeline output stores the pipeline state. It tracks the streaming state of
 * both the input and output, as well as the availability of buffers.
 *
 * In sensor-to-memory mode, frames are always available at the pipeline input.
 * Starting the sensor usually requires I2C transfers and must be done in
 * interruptible context. The pipeline is started and stopped synchronously
 * to the stream on/off commands. All modules in the pipeline will get their
 * subdev set stream handler called. The module at the end of the pipeline must
 * delay starting the hardware until buffers are available at its output.
 *
 * In memory-to-memory mode, starting/stopping the stream requires
 * synchronization between the input and output. ISP modules can't be stopped
 * in the middle of a frame, and at least some of the modules seem to become
 * busy as soon as they're started, even if they don't receive a frame start
 * event. For that reason frames need to be processed in single-shot mode. The
 * driver needs to wait until a frame is completely processed and written to
 * memory before restarting the pipeline for the next frame. Pipelined
 * processing might be possible but requires more testing.
 *
 * Stream start must be delayed until buffers are available at both the input
 * and output. The pipeline must be started in the videobuf queue callback with
 * the buffers queue spinlock held. The modules subdev set stream operation must
 * not sleep.
 */
static int
isp_video_streamon(struct file *file, void *fh, enum v4l2_buf_type type)
{
	struct isp_video_fh *vfh = to_isp_video_fh(fh);
	struct isp_video *video = video_drvdata(file);
	enum isp_pipeline_state state;
	struct isp_video *far_end;
	unsigned int streaming;
	unsigned long flags;
	int ret;

	if (type != video->type)
		return -EINVAL;

	mutex_lock(&video->stream_lock);

	mutex_lock(&vfh->queue.lock);
	streaming = vfh->queue.streaming;
	mutex_unlock(&vfh->queue.lock);

	if (video->pipe != NULL || streaming) {
		mutex_unlock(&video->stream_lock);
		return -EBUSY;
	}

	/* Lock the pipeline. No link touching an entity in the pipeline can
	 * be activated or deactivated once the pipeline is locked.
	 */
	media_entity_graph_lock(&video->video.entity);

	/* Verify that the currently configured format matches the output of
	 * the connected subdev.
	 */
	ret = isp_video_check_format(video, vfh);
	if (ret < 0) {
		printk(KERN_ERR "%s check format failed\n", __func__);
		goto error;
	}

	/* Find the ISP video node connected at the far end of the pipeline. */
	far_end = isp_video_far_end(video);

	/* Update the pipeline state. */
	if (video->type == V4L2_BUF_TYPE_VIDEO_CAPTURE) {
		state = ISP_PIPELINE_STREAM_OUTPUT;
		video->pipe = &video->__pipe;
		video->pipe->input = far_end;
		video->pipe->output = video;
	} else {
		state = ISP_PIPELINE_STREAM_INPUT;
		video->pipe = &far_end->__pipe;
		video->pipe->input = video;
		video->pipe->output = far_end;
	}

	ret = isp_video_validate_pipeline(video->pipe);
	if (ret < 0)
		goto error;

	spin_lock_irqsave(&video->pipe->lock, flags);
	video->pipe->state |= state;
	spin_unlock_irqrestore(&video->pipe->lock, flags);

	/*
	 * Formula from: resource34xx.c set_opp()
	 * If MPU freq is above 500MHz, make sure the interconnect
	 * is at 100Mhz or above.
	 * throughput in KiB/s for 100 Mhz = 100 * 1000 * 4.
	 *
	 * We want to be fast enough then set OCP clock to be max as
	 * possible, in that case 185Mhz then:
	 * throughput in KiB/s for 185Mhz = 185 * 1000 * 4 = 740000 KiB/s
	 */
	omap_pm_set_min_bus_tput(video->isp->dev, OCP_INITIATOR_AGENT, 740000);

	video->queue = &vfh->queue;
	INIT_LIST_HEAD(&video->dmaqueue);
	atomic_set(&video->sequence, -1);

	ret = isp_video_queue_streamon(&vfh->queue);
	if (ret < 0)
		goto error;

	/* In sensor-to-memory mode, the stream can be started synchronously
	 * to the stream on command. In memory-to-memory mode, it will be
	 * started when buffers are queued on both the input and output.
	 */
	if (video->pipe->input == NULL) {
		ret = isp_pipeline_set_stream(video->isp, video,
					      ISP_PIPELINE_STREAM_CONTINUOUS);
		if (ret < 0)
			goto error;
	}

error:
	if (ret < 0) {
		isp_video_queue_streamoff(&vfh->queue);
		omap_pm_set_min_bus_tput(video->isp->dev,
					 OCP_INITIATOR_AGENT, 0);
		media_entity_graph_unlock(&video->video.entity);
		video->pipe = NULL;
		video->queue = NULL;
	}

	mutex_unlock(&video->stream_lock);
	return ret;
}