/* * 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; }
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; }
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; }