예제 #1
0
/*
 * csi2_set_stream - Enable/Disable streaming on the CSI2 module
 * @sd: ISS CSI2 V4L2 subdevice
 * @enable: ISS pipeline stream state
 *
 * Return 0 on success or a negative error code otherwise.
 */
static int csi2_set_stream(struct v4l2_subdev *sd, int enable)
{
	struct iss_csi2_device *csi2 = v4l2_get_subdevdata(sd);
	struct iss_device *iss = csi2->iss;
	struct iss_pipeline *pipe = to_iss_pipeline(&csi2->subdev.entity);
	struct iss_video *video_out = &csi2->video_out;

	if (csi2->state == ISS_PIPELINE_STREAM_STOPPED) {
		if (enable == ISS_PIPELINE_STREAM_STOPPED)
			return 0;

		omap4iss_subclk_enable(iss, OMAP4_ISS_SUBCLK_CSI2_A);
	}

	switch (enable) {
	case ISS_PIPELINE_STREAM_CONTINUOUS:
		if (omap4iss_csiphy_acquire(csi2->phy) < 0)
			return -ENODEV;
		csi2->use_fs_irq = pipe->do_propagation;
		csi2_configure(csi2);
		csi2_print_status(csi2);

		/*
		 * When outputting to memory with no buffer available, let the
		 * buffer queue handler start the hardware. A DMA queue flag
		 * ISS_VIDEO_DMAQUEUE_QUEUED will be set as soon as there is
		 * a buffer available.
		 */
		if (csi2->output & CSI2_OUTPUT_MEMORY &&
		    !(video_out->dmaqueue_flags & ISS_VIDEO_DMAQUEUE_QUEUED))
			break;
		/* Enable context 0 and IRQs */
		atomic_set(&csi2->stopping, 0);
		csi2_ctx_enable(csi2, 0, 1);
		csi2_if_enable(csi2, 1);
		iss_video_dmaqueue_flags_clr(video_out);
		break;

	case ISS_PIPELINE_STREAM_STOPPED:
		if (csi2->state == ISS_PIPELINE_STREAM_STOPPED)
			return 0;
		if (omap4iss_module_sync_idle(&sd->entity, &csi2->wait,
					      &csi2->stopping))
			dev_dbg(iss->dev, "%s: module stop timeout.\n",
				sd->name);
		csi2_ctx_enable(csi2, 0, 0);
		csi2_if_enable(csi2, 0);
		csi2_irq_ctx_set(csi2, 0);
		omap4iss_csiphy_release(csi2->phy);
		omap4iss_subclk_disable(iss, OMAP4_ISS_SUBCLK_CSI2_A);
		iss_video_dmaqueue_flags_clr(video_out);
		break;
	}

	csi2->state = enable;
	return 0;
}
예제 #2
0
파일: iss_ipipeif.c 프로젝트: 3null/linux
/*
 * ipipeif_set_stream - Enable/Disable streaming on the IPIPEIF module
 * @sd: ISP IPIPEIF V4L2 subdevice
 * @enable: Enable/disable stream
 */
static int ipipeif_set_stream(struct v4l2_subdev *sd, int enable)
{
	struct iss_ipipeif_device *ipipeif = v4l2_get_subdevdata(sd);
	struct iss_device *iss = to_iss_device(ipipeif);
	struct iss_video *video_out = &ipipeif->video_out;
	int ret = 0;

	if (ipipeif->state == ISS_PIPELINE_STREAM_STOPPED) {
		if (enable == ISS_PIPELINE_STREAM_STOPPED)
			return 0;

		omap4iss_isp_subclk_enable(iss, IPIPEIF_DRV_SUBCLK_MASK);
	}

	switch (enable) {
	case ISS_PIPELINE_STREAM_CONTINUOUS:

		ipipeif_configure(ipipeif);
		ipipeif_print_status(ipipeif);

		/*
		 * When outputting to memory with no buffer available, let the
		 * buffer queue handler start the hardware. A DMA queue flag
		 * ISS_VIDEO_DMAQUEUE_QUEUED will be set as soon as there is
		 * a buffer available.
		 */
		if (ipipeif->output & IPIPEIF_OUTPUT_MEMORY &&
		    !(video_out->dmaqueue_flags & ISS_VIDEO_DMAQUEUE_QUEUED))
			break;

		atomic_set(&ipipeif->stopping, 0);
		if (ipipeif->output & IPIPEIF_OUTPUT_MEMORY)
			ipipeif_write_enable(ipipeif, 1);
		ipipeif_enable(ipipeif, 1);
		iss_video_dmaqueue_flags_clr(video_out);
		break;

	case ISS_PIPELINE_STREAM_STOPPED:
		if (ipipeif->state == ISS_PIPELINE_STREAM_STOPPED)
			return 0;
		if (omap4iss_module_sync_idle(&sd->entity, &ipipeif->wait,
					      &ipipeif->stopping))
			ret = -ETIMEDOUT;

		if (ipipeif->output & IPIPEIF_OUTPUT_MEMORY)
			ipipeif_write_enable(ipipeif, 0);
		ipipeif_enable(ipipeif, 0);
		omap4iss_isp_subclk_disable(iss, IPIPEIF_DRV_SUBCLK_MASK);
		iss_video_dmaqueue_flags_clr(video_out);
		break;
	}

	ipipeif->state = enable;
	return ret;
}
예제 #3
0
파일: iss_ipipeif.c 프로젝트: 3null/linux
static int ipipeif_video_queue(struct iss_video *video,
			       struct iss_buffer *buffer)
{
	struct iss_ipipeif_device *ipipeif = container_of(video,
				struct iss_ipipeif_device, video_out);

	if (!(ipipeif->output & IPIPEIF_OUTPUT_MEMORY))
		return -ENODEV;

	ipipeif_set_outaddr(ipipeif, buffer->iss_addr);

	/*
	 * If streaming was enabled before there was a buffer queued
	 * or underrun happened in the ISR, the hardware was not enabled
	 * and DMA queue flag ISS_VIDEO_DMAQUEUE_UNDERRUN is still set.
	 * Enable it now.
	 */
	if (video->dmaqueue_flags & ISS_VIDEO_DMAQUEUE_UNDERRUN) {
		if (ipipeif->output & IPIPEIF_OUTPUT_MEMORY)
			ipipeif_write_enable(ipipeif, 1);
		ipipeif_enable(ipipeif, 1);
		iss_video_dmaqueue_flags_clr(video);
	}

	return 0;
}
예제 #4
0
파일: iss_csi2.c 프로젝트: MaxChina/linux
/*
 * csi2_queue - Queues the first buffer when using memory output
 * @video: The video node
 * @buffer: buffer to queue
 */
static int csi2_queue(struct iss_video *video, struct iss_buffer *buffer)
{
	struct iss_csi2_device *csi2 = container_of(video,
				struct iss_csi2_device, video_out);

	csi2_set_outaddr(csi2, buffer->iss_addr);

	/*
	 * If streaming was enabled before there was a buffer queued
	 * or underrun happened in the ISR, the hardware was not enabled
	 * and DMA queue flag ISS_VIDEO_DMAQUEUE_UNDERRUN is still set.
	 * Enable it now.
	 */
	if (csi2->video_out.dmaqueue_flags & ISS_VIDEO_DMAQUEUE_UNDERRUN) {
		/* Enable / disable context 0 and IRQs */
		csi2_if_enable(csi2, 1);
		csi2_ctx_enable(csi2, 0, 1);
		iss_video_dmaqueue_flags_clr(&csi2->video_out);
	}

	return 0;
}