📄 saa7134-core.c
字号:
{ struct saa7134_dev *dev; struct saa7134_mpeg_ops *mops; int err; dev = kzalloc(sizeof(*dev),GFP_KERNEL); if (NULL == dev) return -ENOMEM; /* pci init */ dev->pci = pci_dev; if (pci_enable_device(pci_dev)) { err = -EIO; goto fail1; } dev->nr = saa7134_devcount; sprintf(dev->name,"saa%x[%d]",pci_dev->device,dev->nr); /* pci quirks */ if (pci_pci_problems) { if (pci_pci_problems & PCIPCI_TRITON) printk(KERN_INFO "%s: quirk: PCIPCI_TRITON\n", dev->name); if (pci_pci_problems & PCIPCI_NATOMA) printk(KERN_INFO "%s: quirk: PCIPCI_NATOMA\n", dev->name); if (pci_pci_problems & PCIPCI_VIAETBF) printk(KERN_INFO "%s: quirk: PCIPCI_VIAETBF\n", dev->name); if (pci_pci_problems & PCIPCI_VSFX) printk(KERN_INFO "%s: quirk: PCIPCI_VSFX\n",dev->name);#ifdef PCIPCI_ALIMAGIK if (pci_pci_problems & PCIPCI_ALIMAGIK) { printk(KERN_INFO "%s: quirk: PCIPCI_ALIMAGIK -- latency fixup\n", dev->name); latency = 0x0A; }#endif if (pci_pci_problems & (PCIPCI_FAIL|PCIAGP_FAIL)) { printk(KERN_INFO "%s: quirk: this driver and your " "chipset may not work together" " in overlay mode.\n",dev->name); if (!saa7134_no_overlay) { printk(KERN_INFO "%s: quirk: overlay " "mode will be disabled.\n", dev->name); saa7134_no_overlay = 1; } else { printk(KERN_INFO "%s: quirk: overlay " "mode will be forced. Use this" " option at your own risk.\n", dev->name); } } } if (UNSET != latency) { printk(KERN_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); printk(KERN_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,(unsigned long long)pci_resource_start(pci_dev,0)); pci_set_master(pci_dev); if (!pci_dma_supported(pci_dev, DMA_32BIT_MASK)) { printk("%s: Oops: no 32bit PCI DMA ???\n",dev->name); err = -EIO; goto fail1; } /* board config */ dev->board = pci_id->driver_data; if (card[dev->nr] >= 0 && card[dev->nr] < saa7134_bcount) dev->board = card[dev->nr]; if (SAA7134_BOARD_NOAUTO == dev->board) { must_configure_manually(); dev->board = SAA7134_BOARD_UNKNOWN; } dev->autodetected = card[dev->nr] != dev->board; dev->tuner_type = saa7134_boards[dev->board].tuner_type; dev->tda9887_conf = saa7134_boards[dev->board].tda9887_conf; if (UNSET != tuner[dev->nr]) dev->tuner_type = tuner[dev->nr]; printk(KERN_INFO "%s: subsystem: %04x:%04x, board: %s [card=%d,%s]\n", dev->name,pci_dev->subsystem_vendor, pci_dev->subsystem_device,saa7134_boards[dev->board].name, dev->board, dev->autodetected ? "autodetected" : "insmod option"); /* get mmio */ if (!request_mem_region(pci_resource_start(pci_dev,0), pci_resource_len(pci_dev,0), dev->name)) { err = -EBUSY; printk(KERN_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), 0x1000); dev->bmmio = (__u8 __iomem *)dev->lmmio; if (NULL == dev->lmmio) { err = -EIO; printk(KERN_ERR "%s: can't ioremap() MMIO memory\n", dev->name); goto fail2; } /* initialize hardware #1 */ saa7134_board_init1(dev); saa7134_hwinit1(dev); /* get irq */ err = request_irq(pci_dev->irq, saa7134_irq, IRQF_SHARED | IRQF_DISABLED, dev->name, dev); if (err < 0) { printk(KERN_ERR "%s: can't get IRQ %d\n", dev->name,pci_dev->irq); goto fail3; } /* wait a bit, register i2c bus */ msleep(100); saa7134_i2c_register(dev); /* initialize hardware #2 */ saa7134_board_init2(dev); saa7134_hwinit2(dev); /* load i2c helpers */ if (TUNER_ABSENT != dev->tuner_type) request_module("tuner"); if (card_is_empress(dev)) { request_module("saa6752hs"); } request_submodules(dev); v4l2_prio_init(&dev->prio); /* register v4l devices */ if (saa7134_no_overlay <= 0) { saa7134_video_template.type |= VID_TYPE_OVERLAY; } else { printk("%s: Overlay support disabled.\n",dev->name); } dev->video_dev = vdev_init(dev,&saa7134_video_template,"video"); err = video_register_device(dev->video_dev,VFL_TYPE_GRABBER, video_nr[dev->nr]); if (err < 0) { printk(KERN_INFO "%s: can't register video device\n", dev->name); goto fail4; } printk(KERN_INFO "%s: registered device video%d [v4l2]\n", dev->name,dev->video_dev->minor & 0x1f); dev->vbi_dev = vdev_init(dev,&saa7134_vbi_template,"vbi"); err = video_register_device(dev->vbi_dev,VFL_TYPE_VBI, vbi_nr[dev->nr]); if (err < 0) goto fail4; printk(KERN_INFO "%s: registered device vbi%d\n", dev->name,dev->vbi_dev->minor & 0x1f); if (card_has_radio(dev)) { dev->radio_dev = vdev_init(dev,&saa7134_radio_template,"radio"); err = video_register_device(dev->radio_dev,VFL_TYPE_RADIO, radio_nr[dev->nr]); if (err < 0) goto fail4; printk(KERN_INFO "%s: registered device radio%d\n", dev->name,dev->radio_dev->minor & 0x1f); } /* everything worked */ pci_set_drvdata(pci_dev,dev); saa7134_devcount++; mutex_lock(&devlist_lock); list_for_each_entry(mops, &mops_list, next) mpeg_ops_attach(mops, dev); list_add_tail(&dev->devlist,&saa7134_devlist); mutex_unlock(&devlist_lock); /* check for signal */ saa7134_irq_video_signalchange(dev); if (saa7134_dmasound_init && !dev->dmasound.priv_data) { saa7134_dmasound_init(dev); } if (TUNER_ABSENT != dev->tuner_type) saa7134_i2c_call_clients(dev, TUNER_SET_STANDBY, NULL); return 0; fail4: saa7134_unregister_video(dev); saa7134_i2c_unregister(dev); free_irq(pci_dev->irq, dev); fail3: saa7134_hwfini(dev); iounmap(dev->lmmio); fail2: release_mem_region(pci_resource_start(pci_dev,0), pci_resource_len(pci_dev,0)); fail1: kfree(dev); return err;}static void __devexit saa7134_finidev(struct pci_dev *pci_dev){ struct saa7134_dev *dev = pci_get_drvdata(pci_dev); struct saa7134_mpeg_ops *mops; /* Release DMA sound modules if present */ if (saa7134_dmasound_exit && dev->dmasound.priv_data) { saa7134_dmasound_exit(dev); } /* debugging ... */ if (irq_debug) { u32 report = saa_readl(SAA7134_IRQ_REPORT); u32 status = saa_readl(SAA7134_IRQ_STATUS); print_irqstatus(dev,42,report,status); } /* disable peripheral devices */ saa_writeb(SAA7134_SPECIAL_MODE,0); /* shutdown hardware */ saa_writel(SAA7134_IRQ1,0); saa_writel(SAA7134_IRQ2,0); saa_writel(SAA7134_MAIN_CTRL,0); /* shutdown subsystems */ saa7134_hwfini(dev); /* unregister */ mutex_lock(&devlist_lock); list_del(&dev->devlist); list_for_each_entry(mops, &mops_list, next) mpeg_ops_detach(mops, dev); mutex_unlock(&devlist_lock); saa7134_devcount--; saa7134_i2c_unregister(dev); saa7134_unregister_video(dev); /* the DMA sound modules should be unloaded before reaching this, but just in case they are still present... */ if (dev->dmasound.priv_data != NULL) { free_irq(pci_dev->irq, &dev->dmasound); dev->dmasound.priv_data = NULL; } /* release resources */ free_irq(pci_dev->irq, dev); iounmap(dev->lmmio); release_mem_region(pci_resource_start(pci_dev,0), pci_resource_len(pci_dev,0)); pci_set_drvdata(pci_dev, NULL); /* free memory */ kfree(dev);}#ifdef CONFIG_PMstatic int saa7134_suspend(struct pci_dev *pci_dev , pm_message_t state){ struct saa7134_dev *dev = pci_get_drvdata(pci_dev); /* disable overlay - apps should enable it explicitly on resume*/ dev->ovenable = 0; /* Disable interrupts, DMA, and rest of the chip*/ saa_writel(SAA7134_IRQ1, 0); saa_writel(SAA7134_IRQ2, 0); saa_writel(SAA7134_MAIN_CTRL, 0); synchronize_irq(pci_dev->irq); dev->insuspend = 1; /* Disable timeout timers - if we have active buffers, we will fill them on resume*/ del_timer(&dev->video_q.timeout); del_timer(&dev->vbi_q.timeout); del_timer(&dev->ts_q.timeout); if (dev->remote) saa7134_ir_stop(dev); pci_set_power_state(pci_dev, pci_choose_state(pci_dev, state)); pci_save_state(pci_dev); return 0;}static int saa7134_resume(struct pci_dev *pci_dev){ struct saa7134_dev *dev = pci_get_drvdata(pci_dev); unsigned long flags; pci_restore_state(pci_dev); pci_set_power_state(pci_dev, PCI_D0); /* Do things that are done in saa7134_initdev , except of initializing memory structures.*/ saa7134_board_init1(dev); /* saa7134_hwinit1 */ if (saa7134_boards[dev->board].video_out) saa7134_videoport_init(dev); if (card_has_mpeg(dev)) saa7134_ts_init_hw(dev); if (dev->remote) saa7134_ir_start(dev, dev->remote); saa7134_hw_enable1(dev); saa7134_board_init2(dev); /*saa7134_hwinit2*/ saa7134_set_tvnorm_hw(dev); saa7134_tvaudio_setmute(dev); saa7134_tvaudio_setvolume(dev, dev->ctl_volume); saa7134_tvaudio_do_scan(dev); saa7134_enable_i2s(dev); saa7134_hw_enable2(dev); /*resume unfinished buffer(s)*/ spin_lock_irqsave(&dev->slock, flags); saa7134_buffer_requeue(dev, &dev->video_q); saa7134_buffer_requeue(dev, &dev->vbi_q); saa7134_buffer_requeue(dev, &dev->ts_q); /* FIXME: Disable DMA audio sound - temporary till proper support is implemented*/ dev->dmasound.dma_running = 0; /* start DMA now*/ dev->insuspend = 0; saa7134_set_dmabits(dev); spin_unlock_irqrestore(&dev->slock, flags); return 0;}#endif/* ----------------------------------------------------------- */int saa7134_ts_register(struct saa7134_mpeg_ops *ops){ struct saa7134_dev *dev; mutex_lock(&devlist_lock); list_for_each_entry(dev, &saa7134_devlist, devlist) mpeg_ops_attach(ops, dev); list_add_tail(&ops->next,&mops_list); mutex_unlock(&devlist_lock); return 0;}void saa7134_ts_unregister(struct saa7134_mpeg_ops *ops){ struct saa7134_dev *dev; mutex_lock(&devlist_lock); list_del(&ops->next); list_for_each_entry(dev, &saa7134_devlist, devlist) mpeg_ops_detach(ops, dev); mutex_unlock(&devlist_lock);}EXPORT_SYMBOL(saa7134_ts_register);EXPORT_SYMBOL(saa7134_ts_unregister);/* ----------------------------------------------------------- */static struct pci_driver saa7134_pci_driver = { .name = "saa7134", .id_table = saa7134_pci_tbl, .probe = saa7134_initdev, .remove = __devexit_p(saa7134_finidev),#ifdef CONFIG_PM .suspend = saa7134_suspend, .resume = saa7134_resume#endif};static int saa7134_init(void){ INIT_LIST_HEAD(&saa7134_devlist); printk(KERN_INFO "saa7130/34: v4l2 driver version %d.%d.%d loaded\n", (SAA7134_VERSION_CODE >> 16) & 0xff, (SAA7134_VERSION_CODE >> 8) & 0xff, SAA7134_VERSION_CODE & 0xff);#ifdef SNAPSHOT printk(KERN_INFO "saa7130/34: snapshot date %04d-%02d-%02d\n", SNAPSHOT/10000, (SNAPSHOT/100)%100, SNAPSHOT%100);#endif return pci_register_driver(&saa7134_pci_driver);}static void saa7134_fini(void){ pci_unregister_driver(&saa7134_pci_driver);}module_init(saa7134_init);module_exit(saa7134_fini);/* ----------------------------------------------------------- */EXPORT_SYMBOL(saa7134_set_gpio);EXPORT_SYMBOL(saa7134_i2c_call_clients);EXPORT_SYMBOL(saa7134_devlist);EXPORT_SYMBOL(saa7134_boards);/* ----------------- for the DMA sound modules --------------- */EXPORT_SYMBOL(saa7134_dmasound_init);EXPORT_SYMBOL(saa7134_dmasound_exit);EXPORT_SYMBOL(saa7134_pgtable_free);EXPORT_SYMBOL(saa7134_pgtable_build);EXPORT_SYMBOL(saa7134_pgtable_alloc);EXPORT_SYMBOL(saa7134_set_dmabits);/* ----------------------------------------------------------- *//* * Local variables: * c-basic-offset: 8 * End: */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -