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); }
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; }
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); }
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; }
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; }
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; }
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; }
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); }
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; }
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; }
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; }
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; }
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; }
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; }
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; }
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; }
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; }