Пример #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
/*
 * csi2_set_stream - Enable/Disable streaming on the CSI2 module
 * @sd: ISP CSI2 V4L2 subdevice
 * @enable: ISP 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 isp_csi2_device *csi2 = v4l2_get_subdevdata(sd);
    struct isp_device *isp = csi2->isp;
    struct isp_video *video_out = &csi2->video_out;

    switch (enable) {
    case ISP_PIPELINE_STREAM_CONTINUOUS:
        if (omap3isp_csiphy_acquire(csi2->phy) < 0)
            return -ENODEV;
        if (csi2->output & CSI2_OUTPUT_MEMORY)
            omap3isp_sbl_enable(isp, OMAP3_ISP_SBL_CSI2A_WRITE);
        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
         * ISP_VIDEO_DMAQUEUE_QUEUED will be set as soon as there is
         * a buffer available.
         */
        if (csi2->output & CSI2_OUTPUT_MEMORY &&
                !(video_out->dmaqueue_flags & ISP_VIDEO_DMAQUEUE_QUEUED))
            break;
        /* Enable context 0 and IRQs */
        atomic_set(&csi2->stopping, 0);
        csi2_ctx_enable(isp, csi2, 0, 1);
        csi2_if_enable(isp, csi2, 1);
        isp_video_dmaqueue_flags_clr(video_out);
        break;

    case ISP_PIPELINE_STREAM_STOPPED:
        if (csi2->state == ISP_PIPELINE_STREAM_STOPPED)
            return 0;
        if (omap3isp_module_sync_idle(&sd->entity, &csi2->wait,
                                      &csi2->stopping))
            dev_dbg(isp->dev, "%s: module stop timeout.\n",
                    sd->name);
        csi2_ctx_enable(isp, csi2, 0, 0);
        csi2_if_enable(isp, csi2, 0);
        csi2_irq_ctx_set(isp, csi2, 0);
        omap3isp_csiphy_release(csi2->phy);
        isp_video_dmaqueue_flags_clr(video_out);
        omap3isp_sbl_disable(isp, OMAP3_ISP_SBL_CSI2A_WRITE);
        break;
    }

    csi2->state = enable;
    return 0;
}
Пример #3
0
/*
 * csi2_isr_buffer - Does buffer handling at end-of-frame
 * when writing to memory.
 */
static void csi2_isr_buffer(struct iss_csi2_device *csi2)
{
	struct iss_buffer *buffer;

	csi2_ctx_enable(csi2, 0, 0);

	buffer = omap4iss_video_buffer_next(&csi2->video_out);

	/*
	 * Let video queue operation restart engine if there is an underrun
	 * condition.
	 */
	if (buffer == NULL)
		return;

	csi2_set_outaddr(csi2, buffer->iss_addr);
	csi2_ctx_enable(csi2, 0, 1);
}
Пример #4
0
static void csi2_isr_ctx(struct isp_csi2_device *csi2,
			 struct isp_csi2_ctx_cfg *ctx)
{
	struct isp_device *isp = csi2->isp;
	unsigned int n = ctx->ctxnum;
	u32 status;

	status = isp_reg_readl(isp, csi2->regs1, ISPCSI2_CTX_IRQSTATUS(n));
	isp_reg_writel(isp, status, csi2->regs1, ISPCSI2_CTX_IRQSTATUS(n));

	/* Propagate frame number */
	if (status & ISPCSI2_CTX_IRQSTATUS_FS_IRQ) {
		struct isp_pipeline *pipe =
				     to_isp_pipeline(&csi2->subdev.entity);
		if (pipe->do_propagation)
			atomic_inc(&pipe->frame_number);
	}

	if (!(status & ISPCSI2_CTX_IRQSTATUS_FE_IRQ))
		return;

	/* Skip interrupts until we reach the frame skip count. The CSI2 will be
	 * automatically disabled, as the frame skip count has been programmed
	 * in the CSI2_CTx_CTRL1::COUNT field, so reenable it.
	 *
	 * It would have been nice to rely on the FRAME_NUMBER interrupt instead
	 * but it turned out that the interrupt is only generated when the CSI2
	 * writes to memory (the CSI2_CTx_CTRL1::COUNT field is decreased
	 * correctly and reaches 0 when data is forwarded to the video port only
	 * but no interrupt arrives). Maybe a CSI2 hardware bug.
	 */
	if (csi2->frame_skip) {
		csi2->frame_skip--;
		if (csi2->frame_skip == 0) {
			ctx->format_id = csi2_ctx_map_format(csi2);
			csi2_ctx_config(isp, csi2, ctx);
			csi2_ctx_enable(isp, csi2, n, 1);
		}
		return;
	}

	if (csi2->output & CSI2_OUTPUT_MEMORY)
		csi2_isr_buffer(csi2);
}
Пример #5
0
/*
 * csi2_queue - Queues the first buffer when using memory output
 * @video: The video node
 * @buffer: buffer to queue
 */
static int csi2_queue(struct isp_video *video, struct isp_buffer *buffer)
{
    struct isp_device *isp = video->isp;
    struct isp_csi2_device *csi2 = &isp->isp_csi2a;

    csi2_set_outaddr(csi2, buffer->dma);

    /*
     * 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 ISP_VIDEO_DMAQUEUE_UNDERRUN is still set.
     * Enable it now.
     */
    if (csi2->video_out.dmaqueue_flags & ISP_VIDEO_DMAQUEUE_UNDERRUN) {
        /* Enable / disable context 0 and IRQs */
        csi2_if_enable(isp, csi2, 1);
        csi2_ctx_enable(isp, csi2, 0, 1);
        isp_video_dmaqueue_flags_clr(&csi2->video_out);
    }

    return 0;
}