Exemple #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;
}
Exemple #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;
}
Exemple #3
0
static int csi2_configure(struct isp_csi2_device *csi2)
{
    const struct isp_v4l2_subdevs_group *pdata;
    struct isp_device *isp = csi2->isp;
    struct isp_csi2_timing_cfg *timing = &csi2->timing[0];
    struct v4l2_subdev *sensor;
    struct media_pad *pad;

    /*
     * CSI2 fields that can be updated while the context has
     * been enabled or the interface has been enabled are not
     * updated dynamically currently. So we do not allow to
     * reconfigure if either has been enabled
     */
    if (csi2->contexts[0].enabled || csi2->ctrl.if_enable)
        return -EBUSY;

    pad = media_entity_remote_pad(&csi2->pads[CSI2_PAD_SINK]);
    sensor = media_entity_to_v4l2_subdev(pad->entity);
    pdata = sensor->host_priv;

    csi2->frame_skip = 0;
    v4l2_subdev_call(sensor, sensor, g_skip_frames, &csi2->frame_skip);

    csi2->ctrl.vp_out_ctrl = pdata->bus.csi2.vpclk_div;
    csi2->ctrl.frame_mode = ISP_CSI2_FRAME_IMMEDIATE;
    csi2->ctrl.ecc_enable = pdata->bus.csi2.crc;

    timing->ionum = 1;
    timing->force_rx_mode = 1;
    timing->stop_state_16x = 1;
    timing->stop_state_4x = 1;
    timing->stop_state_counter = 0x1FF;

    /*
     * The CSI2 receiver can't do any format conversion except DPCM
     * decompression, so every set_format call configures both pads
     * and enables DPCM decompression as a special case:
     */
    if (csi2->formats[CSI2_PAD_SINK].code !=
            csi2->formats[CSI2_PAD_SOURCE].code)
        csi2->dpcm_decompress = true;
    else
        csi2->dpcm_decompress = false;

    csi2->contexts[0].format_id = csi2_ctx_map_format(csi2);

    if (csi2->video_out.bpl_padding == 0)
        csi2->contexts[0].data_offset = 0;
    else
        csi2->contexts[0].data_offset = csi2->video_out.bpl_value;

    /*
     * Enable end of frame and end of line signals generation for
     * context 0. These signals are generated from CSI2 receiver to
     * qualify the last pixel of a frame and the last pixel of a line.
     * Without enabling the signals CSI2 receiver writes data to memory
     * beyond buffer size and/or data line offset is not handled correctly.
     */
    csi2->contexts[0].eof_enabled = 1;
    csi2->contexts[0].eol_enabled = 1;

    csi2_irq_complexio1_set(isp, csi2, 1);
    csi2_irq_ctx_set(isp, csi2, 1);
    csi2_irq_status_set(isp, csi2, 1);

    /* Set configuration (timings, format and links) */
    csi2_timing_config(isp, csi2, timing);
    csi2_recv_config(isp, csi2, &csi2->ctrl);
    csi2_ctx_config(isp, csi2, &csi2->contexts[0]);

    return 0;
}