Example #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;
}
Example #2
0
static int iss_probe(struct platform_device *pdev)
{
	struct iss_platform_data *pdata = pdev->dev.platform_data;
	struct iss_device *iss;
	unsigned int i;
	int ret;

	if (!pdata)
		return -EINVAL;

	iss = devm_kzalloc(&pdev->dev, sizeof(*iss), GFP_KERNEL);
	if (!iss)
		return -ENOMEM;

	mutex_init(&iss->iss_mutex);

	iss->dev = &pdev->dev;
	iss->pdata = pdata;

	iss->raw_dmamask = DMA_BIT_MASK(32);
	iss->dev->dma_mask = &iss->raw_dmamask;
	iss->dev->coherent_dma_mask = DMA_BIT_MASK(32);

	platform_set_drvdata(pdev, iss);

	/*
	 * TODO: When implementing DT support switch to syscon regmap lookup by
	 * phandle.
	 */
	iss->syscon = syscon_regmap_lookup_by_compatible("syscon");
	if (IS_ERR(iss->syscon)) {
		ret = PTR_ERR(iss->syscon);
		goto error;
	}

	/* Clocks */
	ret = iss_map_mem_resource(pdev, iss, OMAP4_ISS_MEM_TOP);
	if (ret < 0)
		goto error;

	ret = iss_get_clocks(iss);
	if (ret < 0)
		goto error;

	if (!omap4iss_get(iss))
		goto error;

	ret = iss_reset(iss);
	if (ret < 0)
		goto error_iss;

	iss->revision = iss_reg_read(iss, OMAP4_ISS_MEM_TOP, ISS_HL_REVISION);
	dev_info(iss->dev, "Revision %08x found\n", iss->revision);

	for (i = 1; i < OMAP4_ISS_MEM_LAST; i++) {
		ret = iss_map_mem_resource(pdev, iss, i);
		if (ret)
			goto error_iss;
	}

	/* Configure BTE BW_LIMITER field to max recommended value (1 GB) */
	iss_reg_update(iss, OMAP4_ISS_MEM_BTE, BTE_CTRL,
		       BTE_CTRL_BW_LIMITER_MASK,
		       18 << BTE_CTRL_BW_LIMITER_SHIFT);

	/* Perform ISP reset */
	ret = omap4iss_subclk_enable(iss, OMAP4_ISS_SUBCLK_ISP);
	if (ret < 0)
		goto error_iss;

	ret = iss_isp_reset(iss);
	if (ret < 0)
		goto error_iss;

	dev_info(iss->dev, "ISP Revision %08x found\n",
		 iss_reg_read(iss, OMAP4_ISS_MEM_ISP_SYS1, ISP5_REVISION));

	/* Interrupt */
	ret = platform_get_irq(pdev, 0);
	if (ret <= 0) {
		dev_err(iss->dev, "No IRQ resource\n");
		ret = -ENODEV;
		goto error_iss;
	}
	iss->irq_num = ret;

	if (devm_request_irq(iss->dev, iss->irq_num, iss_isr, IRQF_SHARED,
			     "OMAP4 ISS", iss)) {
		dev_err(iss->dev, "Unable to request IRQ\n");
		ret = -EINVAL;
		goto error_iss;
	}

	/* Entities */
	ret = iss_initialize_modules(iss);
	if (ret < 0)
		goto error_iss;

	ret = iss_register_entities(iss);
	if (ret < 0)
		goto error_modules;

	ret = media_entity_enum_init(&iss->crashed, &iss->media_dev);
	if (ret)
		goto error_entities;

	ret = iss_create_links(iss);
	if (ret < 0)
		goto error_entities;

	omap4iss_put(iss);

	return 0;

error_entities:
	iss_unregister_entities(iss);
	media_entity_enum_cleanup(&iss->crashed);
error_modules:
	iss_cleanup_modules(iss);
error_iss:
	omap4iss_put(iss);
error:
	platform_set_drvdata(pdev, NULL);

	mutex_destroy(&iss->iss_mutex);

	return ret;
}
Example #3
0
static int iss_probe(struct platform_device *pdev)
{
	struct iss_platform_data *pdata = pdev->dev.platform_data;
	struct iss_device *iss;
	unsigned int i;
	int ret;

	if (pdata == NULL)
		return -EINVAL;

	iss = devm_kzalloc(&pdev->dev, sizeof(*iss), GFP_KERNEL);
	if (!iss) {
		dev_err(&pdev->dev, "Could not allocate memory\n");
		return -ENOMEM;
	}

	mutex_init(&iss->iss_mutex);

	iss->dev = &pdev->dev;
	iss->pdata = pdata;

	iss->raw_dmamask = DMA_BIT_MASK(32);
	iss->dev->dma_mask = &iss->raw_dmamask;
	iss->dev->coherent_dma_mask = DMA_BIT_MASK(32);

	platform_set_drvdata(pdev, iss);

	/* Clocks */
	ret = iss_map_mem_resource(pdev, iss, OMAP4_ISS_MEM_TOP);
	if (ret < 0)
		goto error;

	ret = iss_get_clocks(iss);
	if (ret < 0)
		goto error;

	if (omap4iss_get(iss) == NULL)
		goto error;

	ret = iss_reset(iss);
	if (ret < 0)
		goto error_iss;

	iss->revision = iss_reg_read(iss, OMAP4_ISS_MEM_TOP, ISS_HL_REVISION);
	dev_info(iss->dev, "Revision %08x found\n", iss->revision);

	for (i = 1; i < OMAP4_ISS_MEM_LAST; i++) {
		ret = iss_map_mem_resource(pdev, iss, i);
		if (ret)
			goto error_iss;
	}

	/* Configure BTE BW_LIMITER field to max recommended value (1 GB) */
	iss_reg_update(iss, OMAP4_ISS_MEM_BTE, BTE_CTRL,
		       BTE_CTRL_BW_LIMITER_MASK,
		       18 << BTE_CTRL_BW_LIMITER_SHIFT);

	/* Perform ISP reset */
	ret = omap4iss_subclk_enable(iss, OMAP4_ISS_SUBCLK_ISP);
	if (ret < 0)
		goto error_iss;

	ret = iss_isp_reset(iss);
	if (ret < 0)
		goto error_iss;

	dev_info(iss->dev, "ISP Revision %08x found\n",
		 iss_reg_read(iss, OMAP4_ISS_MEM_ISP_SYS1, ISP5_REVISION));

	/* Interrupt */
	iss->irq_num = platform_get_irq(pdev, 0);
	if (iss->irq_num <= 0) {
		dev_err(iss->dev, "No IRQ resource\n");
		ret = -ENODEV;
		goto error_iss;
	}

	if (devm_request_irq(iss->dev, iss->irq_num, iss_isr, IRQF_SHARED,
			     "OMAP4 ISS", iss)) {
		dev_err(iss->dev, "Unable to request IRQ\n");
		ret = -EINVAL;
		goto error_iss;
	}

	/* Entities */
	ret = iss_initialize_modules(iss);
	if (ret < 0)
		goto error_iss;

	ret = iss_register_entities(iss);
	if (ret < 0)
		goto error_modules;

	omap4iss_put(iss);

	return 0;

error_modules:
	iss_cleanup_modules(iss);
error_iss:
	omap4iss_put(iss);
error:
	platform_set_drvdata(pdev, NULL);

	mutex_destroy(&iss->iss_mutex);

	return ret;
}