void fthd_v4l2_unregister(struct fthd_private *dev_priv) { v4l2_ctrl_handler_free(&dev_priv->v4l2_ctrl_handler); vb2_dma_sg_cleanup_ctx(dev_priv->alloc_ctx); video_unregister_device(dev_priv->videodev); v4l2_device_unregister(&dev_priv->v4l2_dev); }
static void tw68_finidev(struct pci_dev *pci_dev) { struct v4l2_device *v4l2_dev = pci_get_drvdata(pci_dev); struct tw68_dev *dev = container_of(v4l2_dev, struct tw68_dev, v4l2_dev); /* shutdown subsystems */ tw_clearl(TW68_DMAC, TW68_DMAP_EN | TW68_FIFO_EN); tw_writel(TW68_INTMASK, 0); /* unregister */ video_unregister_device(&dev->vdev); v4l2_ctrl_handler_free(&dev->hdl); vb2_dma_sg_cleanup_ctx(dev->alloc_ctx); /* release resources */ iounmap(dev->lmmio); release_mem_region(pci_resource_start(pci_dev, 0), pci_resource_len(pci_dev, 0)); v4l2_device_unregister(&dev->v4l2_dev); }
static int tw68_initdev(struct pci_dev *pci_dev, const struct pci_device_id *pci_id) { struct tw68_dev *dev; int vidnr = -1; int err; dev = devm_kzalloc(&pci_dev->dev, sizeof(*dev), GFP_KERNEL); if (NULL == dev) return -ENOMEM; dev->instance = v4l2_device_set_name(&dev->v4l2_dev, "tw68", &tw68_instance); err = v4l2_device_register(&pci_dev->dev, &dev->v4l2_dev); if (err) return err; /* pci init */ dev->pci = pci_dev; if (pci_enable_device(pci_dev)) { err = -EIO; goto fail1; } dev->name = dev->v4l2_dev.name; if (UNSET != latency) { pr_info("%s: setting pci latency timer to %d\n", dev->name, latency); pci_write_config_byte(pci_dev, PCI_LATENCY_TIMER, latency); } /* print pci info */ pci_read_config_byte(pci_dev, PCI_CLASS_REVISION, &dev->pci_rev); pci_read_config_byte(pci_dev, PCI_LATENCY_TIMER, &dev->pci_lat); pr_info("%s: found at %s, rev: %d, irq: %d, latency: %d, mmio: 0x%llx\n", dev->name, pci_name(pci_dev), dev->pci_rev, pci_dev->irq, dev->pci_lat, (u64)pci_resource_start(pci_dev, 0)); pci_set_master(pci_dev); if (!pci_dma_supported(pci_dev, DMA_BIT_MASK(32))) { pr_info("%s: Oops: no 32bit PCI DMA ???\n", dev->name); err = -EIO; goto fail1; } switch (pci_id->device) { case PCI_DEVICE_ID_6800: /* TW6800 */ dev->vdecoder = TW6800; dev->board_virqmask = TW68_VID_INTS; break; case PCI_DEVICE_ID_6801: /* Video decoder for TW6802 */ dev->vdecoder = TW6801; dev->board_virqmask = TW68_VID_INTS | TW68_VID_INTSX; break; case PCI_DEVICE_ID_6804: /* Video decoder for TW6804 */ dev->vdecoder = TW6804; dev->board_virqmask = TW68_VID_INTS | TW68_VID_INTSX; break; default: dev->vdecoder = TWXXXX; /* To be announced */ dev->board_virqmask = TW68_VID_INTS | TW68_VID_INTSX; break; } /* get mmio */ if (!request_mem_region(pci_resource_start(pci_dev, 0), pci_resource_len(pci_dev, 0), dev->name)) { err = -EBUSY; pr_err("%s: can't get MMIO memory @ 0x%llx\n", dev->name, (unsigned long long)pci_resource_start(pci_dev, 0)); goto fail1; } dev->lmmio = ioremap(pci_resource_start(pci_dev, 0), pci_resource_len(pci_dev, 0)); dev->bmmio = (__u8 __iomem *)dev->lmmio; if (NULL == dev->lmmio) { err = -EIO; pr_err("%s: can't ioremap() MMIO memory\n", dev->name); goto fail2; } /* initialize hardware #1 */ /* Then do any initialisation wanted before interrupts are on */ tw68_hw_init1(dev); dev->alloc_ctx = vb2_dma_sg_init_ctx(&pci_dev->dev); if (IS_ERR(dev->alloc_ctx)) { err = PTR_ERR(dev->alloc_ctx); goto fail3; } /* get irq */ err = devm_request_irq(&pci_dev->dev, pci_dev->irq, tw68_irq, IRQF_SHARED, dev->name, dev); if (err < 0) { pr_err("%s: can't get IRQ %d\n", dev->name, pci_dev->irq); goto fail4; } /* * Now do remainder of initialisation, first for * things unique for this card, then for general board */ if (dev->instance < TW68_MAXBOARDS) vidnr = video_nr[dev->instance]; /* initialise video function first */ err = tw68_video_init2(dev, vidnr); if (err < 0) { pr_err("%s: can't register video device\n", dev->name); goto fail5; } tw_setl(TW68_INTMASK, dev->pci_irqmask); pr_info("%s: registered device %s\n", dev->name, video_device_node_name(&dev->vdev)); return 0; fail5: video_unregister_device(&dev->vdev); fail4: vb2_dma_sg_cleanup_ctx(dev->alloc_ctx); fail3: iounmap(dev->lmmio); fail2: release_mem_region(pci_resource_start(pci_dev, 0), pci_resource_len(pci_dev, 0)); fail1: v4l2_device_unregister(&dev->v4l2_dev); return err; }