예제 #1
0
static void at91sam9x5_video_unregister(struct at91sam9x5_video_priv *priv)
{
	unsigned long flags;

	spin_lock_irqsave(&priv->lock, flags);

	if (!priv->fbinfo) {
		spin_unlock_irqrestore(&priv->lock, flags);
		return;
	}
	/* XXX: handle fbinfo being NULL in various callbacks */
	priv->fbinfo = NULL;
	spin_unlock_irqrestore(&priv->lock, flags);

	/* silence DMA */
	at91sam9x5_video_write32(priv, REG_HEOIDR,
			REG_HEOIxR_ADD | REG_HEOIxR_DMA | REG_HEOIxR_UADD |
			REG_HEOIxR_UDMA | REG_HEOIxR_VADD | REG_HEOIxR_VDMA);

	video_unregister_device(priv->video_dev);
	free_irq(priv->irq, priv);
	vb2_queue_release(&priv->queue);
	vb2_dma_contig_cleanup_ctx(priv->alloc_ctx);
	video_device_release(priv->video_dev);
	iounmap(priv->regbase);
}
예제 #2
0
static int __devexit mx3_camera_remove(struct platform_device *pdev)
{
	struct soc_camera_host *soc_host = to_soc_camera_host(&pdev->dev);
	struct mx3_camera_dev *mx3_cam = container_of(soc_host,
					struct mx3_camera_dev, soc_host);

	clk_put(mx3_cam->clk);

	soc_camera_host_unregister(soc_host);

	iounmap(mx3_cam->base);

	/*
	 * The channel has either not been allocated,
	 * or should have been released
	 */
	if (WARN_ON(mx3_cam->idmac_channel[0]))
		dma_release_channel(&mx3_cam->idmac_channel[0]->dma_chan);

	vb2_dma_contig_cleanup_ctx(mx3_cam->alloc_ctx);

	vfree(mx3_cam);

	dmaengine_put();

	dev_info(&pdev->dev, "i.MX3x Camera driver unloaded\n");

	return 0;
}
예제 #3
0
void s5p_mfc_mem_cleanup_multi(void **alloc_ctxes, unsigned int ctx_num)
{
	/* 2 alloc ctxes are needed */
	--ctx_num;
	while (ctx_num-- > 0)
			vb2_dma_contig_cleanup_ctx(alloc_ctxes[ctx_num]);

	kfree(alloc_ctxes);
}
예제 #4
0
void solo_v4l2_exit(struct solo_dev *solo_dev)
{
	if (solo_dev->vfd == NULL)
		return;

	video_unregister_device(solo_dev->vfd);
	vb2_dma_contig_cleanup_ctx(solo_dev->alloc_ctx);
	v4l2_ctrl_handler_free(&solo_dev->disp_hdl);
	solo_dev->vfd = NULL;
}
예제 #5
0
static int fimc_lite_remove(struct platform_device *pdev)
{
	struct fimc_lite *fimc = platform_get_drvdata(pdev);
	struct device *dev = &pdev->dev;

	pm_runtime_disable(dev);
	pm_runtime_set_suspended(dev);
	fimc_lite_unregister_capture_subdev(fimc);
	vb2_dma_contig_cleanup_ctx(fimc->alloc_ctx);
	fimc_lite_clk_put(fimc);

	dev_info(dev, "Driver unloaded\n");
	return 0;
}
예제 #6
0
파일: g2d.c 프로젝트: 7799/linux
static int g2d_remove(struct platform_device *pdev)
{
	struct g2d_dev *dev = platform_get_drvdata(pdev);

	v4l2_info(&dev->v4l2_dev, "Removing " G2D_NAME);
	v4l2_m2m_release(dev->m2m_dev);
	video_unregister_device(dev->vfd);
	v4l2_device_unregister(&dev->v4l2_dev);
	vb2_dma_contig_cleanup_ctx(dev->alloc_ctx);
	clk_unprepare(dev->gate);
	clk_put(dev->gate);
	clk_unprepare(dev->clk);
	clk_put(dev->clk);
	return 0;
}
예제 #7
0
파일: fimc-is.c 프로젝트: glpaschall/linux
static int fimc_is_remove(struct platform_device *pdev)
{
	struct fimc_is *is = platform_get_drvdata(pdev);

	pm_runtime_disable(&pdev->dev);
	pm_runtime_set_suspended(&pdev->dev);
	free_irq(is->irq, is);
	fimc_is_unregister_subdevs(is);
	vb2_dma_contig_cleanup_ctx(is->alloc_ctx);
	fimc_is_put_clocks(is);
	fimc_is_debugfs_remove(is);
	release_firmware(is->fw.f_w);
	fimc_is_free_cpu_memory(is);

	return 0;
}
예제 #8
0
void xvip_dma_cleanup(struct xvip_dma *dma)
{
	if (video_is_registered(&dma->video))
		video_unregister_device(&dma->video);

	if (dma->dma)
		dma_release_channel(dma->dma);

	if (!IS_ERR_OR_NULL(dma->alloc_ctx))
		vb2_dma_contig_cleanup_ctx(dma->alloc_ctx);

	media_entity_cleanup(&dma->video.entity);

	mutex_destroy(&dma->lock);
	mutex_destroy(&dma->pipe.lock);
}
예제 #9
0
static int bdisp_remove(struct platform_device *pdev)
{
	struct bdisp_dev *bdisp = platform_get_drvdata(pdev);

	bdisp_unregister_device(bdisp);

	bdisp_hw_free_filters(bdisp->dev);

	vb2_dma_contig_cleanup_ctx(bdisp->alloc_ctx);

	pm_runtime_disable(&pdev->dev);

	bdisp_debugfs_remove(bdisp);

	v4l2_device_unregister(&bdisp->v4l2_dev);

	if (!IS_ERR(bdisp->clock))
		clk_unprepare(bdisp->clock);

	dev_dbg(&pdev->dev, "%s driver unloaded\n", pdev->name);

	return 0;
}
예제 #10
0
static int g2d_probe(struct platform_device *pdev)
{
    struct g2d_dev *dev;
    struct video_device *vfd;
    struct resource *res;
    int ret = 0;

    dev = kzalloc(sizeof(*dev), GFP_KERNEL);
    if (!dev)
        return -ENOMEM;
    spin_lock_init(&dev->ctrl_lock);
    mutex_init(&dev->mutex);
    atomic_set(&dev->num_inst, 0);
    init_waitqueue_head(&dev->irq_queue);

    res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
    if (!res) {
        dev_err(&pdev->dev, "failed to find registers\n");
        ret = -ENOENT;
        goto free_dev;
    }

    dev->res_regs = request_mem_region(res->start, resource_size(res),
                                       dev_name(&pdev->dev));

    if (!dev->res_regs) {
        dev_err(&pdev->dev, "failed to obtain register region\n");
        ret = -ENOENT;
        goto free_dev;
    }

    dev->regs = ioremap(res->start, resource_size(res));
    if (!dev->regs) {
        dev_err(&pdev->dev, "failed to map registers\n");
        ret = -ENOENT;
        goto rel_res_regs;
    }

    dev->clk = clk_get(&pdev->dev, "sclk_fimg2d");
    if (IS_ERR_OR_NULL(dev->clk)) {
        dev_err(&pdev->dev, "failed to get g2d clock\n");
        ret = -ENXIO;
        goto unmap_regs;
    }

    ret = clk_prepare(dev->clk);
    if (ret) {
        dev_err(&pdev->dev, "failed to prepare g2d clock\n");
        goto put_clk;
    }

    dev->gate = clk_get(&pdev->dev, "fimg2d");
    if (IS_ERR_OR_NULL(dev->gate)) {
        dev_err(&pdev->dev, "failed to get g2d clock gate\n");
        ret = -ENXIO;
        goto unprep_clk;
    }

    ret = clk_prepare(dev->gate);
    if (ret) {
        dev_err(&pdev->dev, "failed to prepare g2d clock gate\n");
        goto put_clk_gate;
    }

    res = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
    if (!res) {
        dev_err(&pdev->dev, "failed to find IRQ\n");
        ret = -ENXIO;
        goto unprep_clk_gate;
    }

    dev->irq = res->start;

    ret = request_irq(dev->irq, g2d_isr, 0, pdev->name, dev);
    if (ret) {
        dev_err(&pdev->dev, "failed to install IRQ\n");
        goto put_clk_gate;
    }

    dev->alloc_ctx = vb2_dma_contig_init_ctx(&pdev->dev);
    if (IS_ERR(dev->alloc_ctx)) {
        ret = PTR_ERR(dev->alloc_ctx);
        goto rel_irq;
    }

    ret = v4l2_device_register(&pdev->dev, &dev->v4l2_dev);
    if (ret)
        goto alloc_ctx_cleanup;
    vfd = video_device_alloc();
    if (!vfd) {
        v4l2_err(&dev->v4l2_dev, "Failed to allocate video device\n");
        ret = -ENOMEM;
        goto unreg_v4l2_dev;
    }
    *vfd = g2d_videodev;
    vfd->lock = &dev->mutex;
    ret = video_register_device(vfd, VFL_TYPE_GRABBER, 0);
    if (ret) {
        v4l2_err(&dev->v4l2_dev, "Failed to register video device\n");
        goto rel_vdev;
    }
    video_set_drvdata(vfd, dev);
    snprintf(vfd->name, sizeof(vfd->name), "%s", g2d_videodev.name);
    dev->vfd = vfd;
    v4l2_info(&dev->v4l2_dev, "device registered as /dev/video%d\n",
              vfd->num);
    platform_set_drvdata(pdev, dev);
    dev->m2m_dev = v4l2_m2m_init(&g2d_m2m_ops);
    if (IS_ERR(dev->m2m_dev)) {
        v4l2_err(&dev->v4l2_dev, "Failed to init mem2mem device\n");
        ret = PTR_ERR(dev->m2m_dev);
        goto unreg_video_dev;
    }

    def_frame.stride = (def_frame.width * def_frame.fmt->depth) >> 3;

    return 0;

unreg_video_dev:
    video_unregister_device(dev->vfd);
rel_vdev:
    video_device_release(vfd);
unreg_v4l2_dev:
    v4l2_device_unregister(&dev->v4l2_dev);
alloc_ctx_cleanup:
    vb2_dma_contig_cleanup_ctx(dev->alloc_ctx);
rel_irq:
    free_irq(dev->irq, dev);
unprep_clk_gate:
    clk_unprepare(dev->gate);
put_clk_gate:
    clk_put(dev->gate);
unprep_clk:
    clk_unprepare(dev->clk);
put_clk:
    clk_put(dev->clk);
unmap_regs:
    iounmap(dev->regs);
rel_res_regs:
    release_resource(dev->res_regs);
free_dev:
    kfree(dev);
    return ret;
}
예제 #11
0
static int s3c_camif_probe(struct platform_device *pdev)
{
	struct device *dev = &pdev->dev;
	struct s3c_camif_plat_data *pdata = dev->platform_data;
	struct s3c_camif_drvdata *drvdata;
	struct camif_dev *camif;
	struct resource *mres;
	int ret = 0;

	camif = devm_kzalloc(dev, sizeof(*camif), GFP_KERNEL);
	if (!camif)
		return -ENOMEM;

	spin_lock_init(&camif->slock);
	mutex_init(&camif->lock);

	camif->dev = dev;

	if (!pdata || !pdata->gpio_get || !pdata->gpio_put) {
		dev_err(dev, "wrong platform data\n");
		return -EINVAL;
	}

	camif->pdata = *pdata;
	drvdata = (void *)platform_get_device_id(pdev)->driver_data;
	camif->variant = drvdata->variant;

	mres = platform_get_resource(pdev, IORESOURCE_MEM, 0);

	camif->io_base = devm_ioremap_resource(dev, mres);
	if (IS_ERR(camif->io_base))
		return PTR_ERR(camif->io_base);

	ret = camif_request_irqs(pdev, camif);
	if (ret < 0)
		return ret;

	ret = pdata->gpio_get();
	if (ret < 0)
		return ret;

	ret = s3c_camif_create_subdev(camif);
	if (ret < 0)
		goto err_sd;

	ret = camif_clk_get(camif);
	if (ret < 0)
		goto err_clk;

	platform_set_drvdata(pdev, camif);
	clk_set_rate(camif->clock[CLK_CAM],
			camif->pdata.sensor.clock_frequency);

	dev_info(dev, "sensor clock frequency: %lu\n",
		 clk_get_rate(camif->clock[CLK_CAM]));
	/*
	 * Set initial pixel format, resolution and crop rectangle.
	 * Must be done before a sensor subdev is registered as some
	 * settings are overrode with values from sensor subdev.
	 */
	s3c_camif_set_defaults(camif);

	pm_runtime_enable(dev);

	ret = pm_runtime_get_sync(dev);
	if (ret < 0)
		goto err_pm;

	/* Initialize contiguous memory allocator */
	camif->alloc_ctx = vb2_dma_contig_init_ctx(dev);
	if (IS_ERR(camif->alloc_ctx)) {
		ret = PTR_ERR(camif->alloc_ctx);
		goto err_alloc;
	}

	ret = camif_media_dev_init(camif);
	if (ret < 0)
		goto err_mdev;

	ret = camif_register_sensor(camif);
	if (ret < 0)
		goto err_sens;

	ret = v4l2_device_register_subdev(&camif->v4l2_dev, &camif->subdev);
	if (ret < 0)
		goto err_sens;

	ret = v4l2_device_register_subdev_nodes(&camif->v4l2_dev);
	if (ret < 0)
		goto err_sens;

	ret = camif_register_video_nodes(camif);
	if (ret < 0)
		goto err_sens;

	ret = camif_create_media_links(camif);
	if (ret < 0)
		goto err_sens;

	ret = media_device_register(&camif->media_dev);
	if (ret < 0)
		goto err_sens;

	pm_runtime_put(dev);
	return 0;

err_sens:
	v4l2_device_unregister(&camif->v4l2_dev);
	media_device_unregister(&camif->media_dev);
	media_device_cleanup(&camif->media_dev);
	camif_unregister_media_entities(camif);
err_mdev:
	vb2_dma_contig_cleanup_ctx(camif->alloc_ctx);
err_alloc:
	pm_runtime_put(dev);
	pm_runtime_disable(dev);
err_pm:
	camif_clk_put(camif);
err_clk:
	s3c_camif_unregister_subdev(camif);
err_sd:
	pdata->gpio_put();
	return ret;
}
예제 #12
0
static int __devinit mx3_camera_probe(struct platform_device *pdev)
{
	struct mx3_camera_dev *mx3_cam;
	struct resource *res;
	void __iomem *base;
	int err = 0;
	struct soc_camera_host *soc_host;

	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
	if (!res) {
		err = -ENODEV;
		goto egetres;
	}

	mx3_cam = vzalloc(sizeof(*mx3_cam));
	if (!mx3_cam) {
		dev_err(&pdev->dev, "Could not allocate mx3 camera object\n");
		err = -ENOMEM;
		goto ealloc;
	}

	mx3_cam->clk = clk_get(&pdev->dev, NULL);
	if (IS_ERR(mx3_cam->clk)) {
		err = PTR_ERR(mx3_cam->clk);
		goto eclkget;
	}

	mx3_cam->pdata = pdev->dev.platform_data;
	mx3_cam->platform_flags = mx3_cam->pdata->flags;
	if (!(mx3_cam->platform_flags & (MX3_CAMERA_DATAWIDTH_4 |
			MX3_CAMERA_DATAWIDTH_8 | MX3_CAMERA_DATAWIDTH_10 |
			MX3_CAMERA_DATAWIDTH_15))) {
		/*
		 * Platform hasn't set available data widths. This is bad.
		 * Warn and use a default.
		 */
		dev_warn(&pdev->dev, "WARNING! Platform hasn't set available "
			 "data widths, using default 8 bit\n");
		mx3_cam->platform_flags |= MX3_CAMERA_DATAWIDTH_8;
	}

	mx3_cam->mclk = mx3_cam->pdata->mclk_10khz * 10000;
	if (!mx3_cam->mclk) {
		dev_warn(&pdev->dev,
			 "mclk_10khz == 0! Please, fix your platform data. "
			 "Using default 20MHz\n");
		mx3_cam->mclk = 20000000;
	}

	/* list of video-buffers */
	INIT_LIST_HEAD(&mx3_cam->capture);
	spin_lock_init(&mx3_cam->lock);

	base = ioremap(res->start, resource_size(res));
	if (!base) {
		pr_err("Couldn't map %x@%x\n", resource_size(res), res->start);
		err = -ENOMEM;
		goto eioremap;
	}

	mx3_cam->base	= base;

	soc_host		= &mx3_cam->soc_host;
	soc_host->drv_name	= MX3_CAM_DRV_NAME;
	soc_host->ops		= &mx3_soc_camera_host_ops;
	soc_host->priv		= mx3_cam;
	soc_host->v4l2_dev.dev	= &pdev->dev;
	soc_host->nr		= pdev->id;

	mx3_cam->alloc_ctx = vb2_dma_contig_init_ctx(&pdev->dev);
	if (IS_ERR(mx3_cam->alloc_ctx)) {
		err = PTR_ERR(mx3_cam->alloc_ctx);
		goto eallocctx;
	}

	err = soc_camera_host_register(soc_host);
	if (err)
		goto ecamhostreg;

	/* IDMAC interface */
	dmaengine_get();

	return 0;

ecamhostreg:
	vb2_dma_contig_cleanup_ctx(mx3_cam->alloc_ctx);
eallocctx:
	iounmap(base);
eioremap:
	clk_put(mx3_cam->clk);
eclkget:
	vfree(mx3_cam);
ealloc:
egetres:
	return err;
}
예제 #13
0
파일: g2d.c 프로젝트: 7799/linux
static int g2d_probe(struct platform_device *pdev)
{
	struct g2d_dev *dev;
	struct video_device *vfd;
	struct resource *res;
	const struct of_device_id *of_id;
	int ret = 0;

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

	spin_lock_init(&dev->ctrl_lock);
	mutex_init(&dev->mutex);
	atomic_set(&dev->num_inst, 0);
	init_waitqueue_head(&dev->irq_queue);

	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);

	dev->regs = devm_ioremap_resource(&pdev->dev, res);
	if (IS_ERR(dev->regs))
		return PTR_ERR(dev->regs);

	dev->clk = clk_get(&pdev->dev, "sclk_fimg2d");
	if (IS_ERR(dev->clk)) {
		dev_err(&pdev->dev, "failed to get g2d clock\n");
		return -ENXIO;
	}

	ret = clk_prepare(dev->clk);
	if (ret) {
		dev_err(&pdev->dev, "failed to prepare g2d clock\n");
		goto put_clk;
	}

	dev->gate = clk_get(&pdev->dev, "fimg2d");
	if (IS_ERR(dev->gate)) {
		dev_err(&pdev->dev, "failed to get g2d clock gate\n");
		ret = -ENXIO;
		goto unprep_clk;
	}

	ret = clk_prepare(dev->gate);
	if (ret) {
		dev_err(&pdev->dev, "failed to prepare g2d clock gate\n");
		goto put_clk_gate;
	}

	res = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
	if (!res) {
		dev_err(&pdev->dev, "failed to find IRQ\n");
		ret = -ENXIO;
		goto unprep_clk_gate;
	}

	dev->irq = res->start;

	ret = devm_request_irq(&pdev->dev, dev->irq, g2d_isr,
						0, pdev->name, dev);
	if (ret) {
		dev_err(&pdev->dev, "failed to install IRQ\n");
		goto put_clk_gate;
	}

	dev->alloc_ctx = vb2_dma_contig_init_ctx(&pdev->dev);
	if (IS_ERR(dev->alloc_ctx)) {
		ret = PTR_ERR(dev->alloc_ctx);
		goto unprep_clk_gate;
	}

	ret = v4l2_device_register(&pdev->dev, &dev->v4l2_dev);
	if (ret)
		goto alloc_ctx_cleanup;
	vfd = video_device_alloc();
	if (!vfd) {
		v4l2_err(&dev->v4l2_dev, "Failed to allocate video device\n");
		ret = -ENOMEM;
		goto unreg_v4l2_dev;
	}
	*vfd = g2d_videodev;
	vfd->lock = &dev->mutex;
	vfd->v4l2_dev = &dev->v4l2_dev;
	ret = video_register_device(vfd, VFL_TYPE_GRABBER, 0);
	if (ret) {
		v4l2_err(&dev->v4l2_dev, "Failed to register video device\n");
		goto rel_vdev;
	}
	video_set_drvdata(vfd, dev);
	snprintf(vfd->name, sizeof(vfd->name), "%s", g2d_videodev.name);
	dev->vfd = vfd;
	v4l2_info(&dev->v4l2_dev, "device registered as /dev/video%d\n",
								vfd->num);
	platform_set_drvdata(pdev, dev);
	dev->m2m_dev = v4l2_m2m_init(&g2d_m2m_ops);
	if (IS_ERR(dev->m2m_dev)) {
		v4l2_err(&dev->v4l2_dev, "Failed to init mem2mem device\n");
		ret = PTR_ERR(dev->m2m_dev);
		goto unreg_video_dev;
	}

	def_frame.stride = (def_frame.width * def_frame.fmt->depth) >> 3;

	if (!pdev->dev.of_node) {
		dev->variant = g2d_get_drv_data(pdev);
	} else {
		of_id = of_match_node(exynos_g2d_match, pdev->dev.of_node);
		if (!of_id) {
			ret = -ENODEV;
			goto unreg_video_dev;
		}
		dev->variant = (struct g2d_variant *)of_id->data;
	}

	return 0;

unreg_video_dev:
	video_unregister_device(dev->vfd);
rel_vdev:
	video_device_release(vfd);
unreg_v4l2_dev:
	v4l2_device_unregister(&dev->v4l2_dev);
alloc_ctx_cleanup:
	vb2_dma_contig_cleanup_ctx(dev->alloc_ctx);
unprep_clk_gate:
	clk_unprepare(dev->gate);
put_clk_gate:
	clk_put(dev->gate);
unprep_clk:
	clk_unprepare(dev->clk);
put_clk:
	clk_put(dev->clk);

	return ret;
}
예제 #14
0
static int at91sam9x5_video_register(struct at91sam9x5_video_priv *priv,
		struct fb_info *fbinfo)
{
	int ret = -ENOMEM;
	struct platform_device *pdev = priv->pdev;
	struct resource *res;
	const struct at91sam9x5_video_pdata *pdata =
		dev_get_platdata(&pdev->dev);
	struct vb2_queue *q = &priv->queue;
	unsigned long flags;

	spin_lock_irqsave(&priv->lock, flags);
	if (priv->fbinfo) {
		spin_unlock_irqrestore(&priv->lock, flags);
		return -EBUSY;
	}
	priv->fbinfo = fbinfo;
	spin_unlock_irqrestore(&priv->lock, flags);

	/* XXX: this doesn't belong here, does it? */
	pdev->dev.coherent_dma_mask = DMA_BIT_MASK(32);

	if (!pdata) {
		dev_err(&pdev->dev, "failed to get platform data\n");
		goto err_get_pdata;
	}

	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
	if (!res) {
		dev_err(&pdev->dev, "failed to get register base\n");
		goto err_get_regbase;
	}

	priv->regbase = ioremap(res->start, resource_size(res));
	if (!priv->regbase) {
		dev_err(&pdev->dev, "failed to remap register base\n");
		goto err_ioremap;
	}

	/*
	 * XXX: video_device_alloc is just a kzalloc, so embedding struct
	 * video_device into struct at91sam9x5_video_priv would work, too.
	 * Is that allowed?
	 */
	priv->video_dev = video_device_alloc();
	if (!priv->video_dev) {
		dev_err(&pdev->dev, "failed to alloc video device for %p\n",
				fbinfo);
		goto err_video_device_alloc;
	}

	priv->alloc_ctx = vb2_dma_contig_init_ctx(&pdev->dev);
	if (IS_ERR(priv->alloc_ctx)) {
		ret = PTR_ERR(priv->alloc_ctx);
		dev_err(&pdev->dev, "failed to init alloc_ctx (%d)\n", ret);
		goto err_init_ctx;
	}

	q->ops = &at91sam9x5_video_vb_ops;
	q->mem_ops = &vb2_dma_contig_memops;
	q->type = V4L2_BUF_TYPE_VIDEO_OUTPUT;
	q->io_modes = VB2_MMAP | VB2_USERPTR | VB2_WRITE;

	ret = vb2_queue_init(q);
	if (ret) {
		dev_err(&pdev->dev, "failed to init queue (%d)\n", ret);
		goto err_queue_init;
	}

	priv->video_dev->fops = &at91sam9x5_video_fops;
	priv->video_dev->ioctl_ops = &at91sam9x5_video_ioctl_ops;
	priv->video_dev->release = video_device_release;

	video_set_drvdata(priv->video_dev, priv);

	/* reset channel and clear status */
	at91sam9x5_video_write32(priv, REG_HEOCHDR, REG_HEOCHDR_CHRST);
	(void)at91sam9x5_video_read32(priv, REG_HEOISR);

	/* set maximal bursting */
	at91sam9x5_video_write32(priv, REG_HEOCFG0,
			REG_HEOCFG0_BLEN_INCR16 |
			REG_HEOCFG0_BLENUV_INCR16);

	ret = platform_get_irq(pdev, 0);
	if (ret <= 0) {
		dev_err(&pdev->dev, "failed to get irq from resources (%d)\n",
				ret);
		if (!ret)
			ret = -ENXIO;
		goto err_get_irq;
	}
	priv->irq = ret;

	ret = request_irq(priv->irq, at91sam9x5_video_irq, IRQF_SHARED,
			DRIVER_NAME, priv);
	if (ret) {
		dev_err(&pdev->dev, "failed to request irq (%d)\n", ret);
		goto err_request_irq;
	}

	ret = video_register_device(priv->video_dev,
			/* XXX: really grabber? */ VFL_TYPE_GRABBER, -1);
	if (ret) {
		dev_err(&pdev->dev, "failed to register video device (%d)\n",
				ret);

		free_irq(priv->irq, priv);
 err_request_irq:
 err_get_irq:

		vb2_queue_release(q);
err_queue_init:

		vb2_dma_contig_cleanup_ctx(priv->alloc_ctx);
 err_init_ctx:

		video_device_release(priv->video_dev);
 err_video_device_alloc:

		iounmap(priv->regbase);

		priv->fbinfo = NULL;
	}
 err_ioremap:
 err_get_regbase:
 err_get_pdata:

	return ret;
}
예제 #15
0
int solo_v4l2_init(struct solo_dev *solo_dev, unsigned nr)
{
	int ret;
	int i;

	init_waitqueue_head(&solo_dev->disp_thread_wait);
	spin_lock_init(&solo_dev->slock);
	mutex_init(&solo_dev->lock);
	INIT_LIST_HEAD(&solo_dev->vidq_active);

	solo_dev->vfd = video_device_alloc();
	if (!solo_dev->vfd)
		return -ENOMEM;

	*solo_dev->vfd = solo_v4l2_template;
	solo_dev->vfd->v4l2_dev = &solo_dev->v4l2_dev;
	solo_dev->vfd->queue = &solo_dev->vidq;
	solo_dev->vfd->lock = &solo_dev->lock;
	v4l2_ctrl_handler_init(&solo_dev->disp_hdl, 1);
	v4l2_ctrl_new_custom(&solo_dev->disp_hdl, &solo_motion_trace_ctrl, NULL);
	if (solo_dev->disp_hdl.error) {
		ret = solo_dev->disp_hdl.error;
		goto fail;
	}
	solo_dev->vfd->ctrl_handler = &solo_dev->disp_hdl;

	video_set_drvdata(solo_dev->vfd, solo_dev);

	solo_dev->vidq.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
	solo_dev->vidq.io_modes = VB2_MMAP | VB2_USERPTR | VB2_READ;
	solo_dev->vidq.ops = &solo_video_qops;
	solo_dev->vidq.mem_ops = &vb2_dma_contig_memops;
	solo_dev->vidq.drv_priv = solo_dev;
	solo_dev->vidq.timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_MONOTONIC;
	solo_dev->vidq.gfp_flags = __GFP_DMA32;
	solo_dev->vidq.buf_struct_size = sizeof(struct solo_vb2_buf);
	solo_dev->vidq.lock = &solo_dev->lock;
	ret = vb2_queue_init(&solo_dev->vidq);
	if (ret < 0)
		goto fail;

	solo_dev->alloc_ctx = vb2_dma_contig_init_ctx(&solo_dev->pdev->dev);
	if (IS_ERR(solo_dev->alloc_ctx)) {
		dev_err(&solo_dev->pdev->dev, "Can't allocate buffer context");
		return PTR_ERR(solo_dev->alloc_ctx);
	}

	/* Cycle all the channels and clear */
	for (i = 0; i < solo_dev->nr_chans; i++) {
		solo_v4l2_set_ch(solo_dev, i);
		while (erase_off(solo_dev))
			/* Do nothing */;
	}

	/* Set the default display channel */
	solo_v4l2_set_ch(solo_dev, 0);
	while (erase_off(solo_dev))
		/* Do nothing */;

	ret = video_register_device(solo_dev->vfd, VFL_TYPE_GRABBER, nr);
	if (ret < 0)
		goto fail;

	snprintf(solo_dev->vfd->name, sizeof(solo_dev->vfd->name), "%s (%i)",
		 SOLO6X10_NAME, solo_dev->vfd->num);

	dev_info(&solo_dev->pdev->dev, "Display as /dev/video%d with "
		 "%d inputs (%d extended)\n", solo_dev->vfd->num,
		 solo_dev->nr_chans, solo_dev->nr_ext);

	return 0;

fail:
	video_device_release(solo_dev->vfd);
	vb2_dma_contig_cleanup_ctx(solo_dev->alloc_ctx);
	v4l2_ctrl_handler_free(&solo_dev->disp_hdl);
	solo_dev->vfd = NULL;
	return ret;
}
예제 #16
0
static int bdisp_probe(struct platform_device *pdev)
{
	struct bdisp_dev *bdisp;
	struct resource *res;
	struct device *dev = &pdev->dev;
	int ret;

	dev_dbg(dev, "%s\n", __func__);

	bdisp = devm_kzalloc(dev, sizeof(struct bdisp_dev), GFP_KERNEL);
	if (!bdisp)
		return -ENOMEM;

	bdisp->pdev = pdev;
	bdisp->dev = dev;
	platform_set_drvdata(pdev, bdisp);

	if (dev->of_node)
		bdisp->id = of_alias_get_id(pdev->dev.of_node, BDISP_NAME);
	else
		bdisp->id = pdev->id;

	init_waitqueue_head(&bdisp->irq_queue);
	INIT_DELAYED_WORK(&bdisp->timeout_work, bdisp_irq_timeout);
	bdisp->work_queue = create_workqueue(BDISP_NAME);

	spin_lock_init(&bdisp->slock);
	mutex_init(&bdisp->lock);

	/* get resources */
	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
	bdisp->regs = devm_ioremap_resource(dev, res);
	if (IS_ERR(bdisp->regs)) {
		dev_err(dev, "failed to get regs\n");
		return PTR_ERR(bdisp->regs);
	}

	bdisp->clock = devm_clk_get(dev, BDISP_NAME);
	if (IS_ERR(bdisp->clock)) {
		dev_err(dev, "failed to get clock\n");
		return PTR_ERR(bdisp->clock);
	}

	ret = clk_prepare(bdisp->clock);
	if (ret < 0) {
		dev_err(dev, "clock prepare failed\n");
		bdisp->clock = ERR_PTR(-EINVAL);
		return ret;
	}

	res = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
	if (!res) {
		dev_err(dev, "failed to get IRQ resource\n");
		goto err_clk;
	}

	ret = devm_request_threaded_irq(dev, res->start, bdisp_irq_handler,
					bdisp_irq_thread, IRQF_ONESHOT,
					pdev->name, bdisp);
	if (ret) {
		dev_err(dev, "failed to install irq\n");
		goto err_clk;
	}

	/* v4l2 register */
	ret = v4l2_device_register(dev, &bdisp->v4l2_dev);
	if (ret) {
		dev_err(dev, "failed to register\n");
		goto err_clk;
	}

	/* Debug */
	ret = bdisp_debugfs_create(bdisp);
	if (ret) {
		dev_err(dev, "failed to create debugfs\n");
		goto err_v4l2;
	}

	/* Power management */
	pm_runtime_enable(dev);
	ret = pm_runtime_get_sync(dev);
	if (ret < 0) {
		dev_err(dev, "failed to set PM\n");
		goto err_dbg;
	}

	/* Continuous memory allocator */
	bdisp->alloc_ctx = vb2_dma_contig_init_ctx(dev);
	if (IS_ERR(bdisp->alloc_ctx)) {
		ret = PTR_ERR(bdisp->alloc_ctx);
		goto err_pm;
	}

	/* Filters */
	if (bdisp_hw_alloc_filters(bdisp->dev)) {
		dev_err(bdisp->dev, "no memory for filters\n");
		ret = -ENOMEM;
		goto err_vb2_dma;
	}

	/* Register */
	ret = bdisp_register_device(bdisp);
	if (ret) {
		dev_err(dev, "failed to register\n");
		goto err_filter;
	}

	dev_info(dev, "%s%d registered as /dev/video%d\n", BDISP_NAME,
		 bdisp->id, bdisp->vdev.num);

	pm_runtime_put(dev);

	return 0;

err_filter:
	bdisp_hw_free_filters(bdisp->dev);
err_vb2_dma:
	vb2_dma_contig_cleanup_ctx(bdisp->alloc_ctx);
err_pm:
	pm_runtime_put(dev);
err_dbg:
	bdisp_debugfs_remove(bdisp);
err_v4l2:
	v4l2_device_unregister(&bdisp->v4l2_dev);
err_clk:
	if (!IS_ERR(bdisp->clock))
		clk_unprepare(bdisp->clock);

	return ret;
}
예제 #17
0
static int fimc_is_probe(struct platform_device *pdev)
{
	struct device *dev = &pdev->dev;
	struct fimc_is *is;
	struct resource res;
	struct device_node *node;
	int ret;

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

	is->pdev = pdev;
	is->isp.pdev = pdev;

	init_waitqueue_head(&is->irq_queue);
	spin_lock_init(&is->slock);
	mutex_init(&is->lock);

	ret = of_address_to_resource(dev->of_node, 0, &res);
	if (ret < 0)
		return ret;

	is->regs = devm_ioremap_resource(dev, &res);
	if (IS_ERR(is->regs))
		return PTR_ERR(is->regs);

	node = of_get_child_by_name(dev->of_node, "pmu");
	if (!node)
		return -ENODEV;

	is->pmu_regs = of_iomap(node, 0);
	if (!is->pmu_regs)
		return -ENOMEM;

	is->irq = irq_of_parse_and_map(dev->of_node, 0);
	if (is->irq < 0) {
		dev_err(dev, "no irq found\n");
		return is->irq;
	}

	ret = fimc_is_get_clocks(is);
	if (ret < 0)
		return ret;

	platform_set_drvdata(pdev, is);

	ret = request_irq(is->irq, fimc_is_irq_handler, 0, dev_name(dev), is);
	if (ret < 0) {
		dev_err(dev, "irq request failed\n");
		goto err_clk;
	}
	pm_runtime_enable(dev);
	/*
	 * Enable only the ISP power domain, keep FIMC-IS clocks off until
	 * the whole clock tree is configured. The ISP power domain needs
	 * be active in order to acces any CMU_ISP clock registers.
	 */
	ret = pm_runtime_get_sync(dev);
	if (ret < 0)
		goto err_irq;

	ret = fimc_is_setup_clocks(is);
	pm_runtime_put_sync(dev);

	if (ret < 0)
		goto err_irq;

	is->clk_init = true;

	is->alloc_ctx = vb2_dma_contig_init_ctx(dev);
	if (IS_ERR(is->alloc_ctx)) {
		ret = PTR_ERR(is->alloc_ctx);
		goto err_irq;
	}
	/*
	 * Register FIMC-IS V4L2 subdevs to this driver. The video nodes
	 * will be created within the subdev's registered() callback.
	 */
	ret = fimc_is_register_subdevs(is);
	if (ret < 0)
		goto err_vb;

	ret = fimc_is_debugfs_create(is);
	if (ret < 0)
		goto err_sd;

	ret = fimc_is_request_firmware(is, FIMC_IS_FW_FILENAME);
	if (ret < 0)
		goto err_dfs;

	dev_dbg(dev, "FIMC-IS registered successfully\n");
	return 0;

err_dfs:
	fimc_is_debugfs_remove(is);
err_vb:
	vb2_dma_contig_cleanup_ctx(is->alloc_ctx);
err_sd:
	fimc_is_unregister_subdevs(is);
err_irq:
	free_irq(is->irq, is);
err_clk:
	fimc_is_put_clocks(is);
	return ret;
}