📄 saa7134-core.c
字号:
#if DEBUG_SPINLOCKS BUG_ON(!spin_is_locked(&dev->slock));#endif BUG_ON(NULL != q->curr); if (!list_empty(&q->queue)) { /* activate next one from queue */ buf = list_entry(q->queue.next,struct saa7134_buf,vb.queue); dprintk("buffer_next %p [prev=%p/next=%p]\n", buf,q->queue.prev,q->queue.next); list_del(&buf->vb.queue); if (!list_empty(&q->queue)) next = list_entry(q->queue.next,struct saa7134_buf, vb.queue); q->curr = buf; buf->activate(dev,buf,next); dprintk("buffer_next #2 prev=%p/next=%p\n", q->queue.prev,q->queue.next); } else { /* nothing to do -- just stop DMA */ dprintk("buffer_next %p\n",NULL); saa7134_set_dmabits(dev); del_timer(&q->timeout); }}void saa7134_buffer_timeout(unsigned long data){ struct saa7134_dmaqueue *q = (struct saa7134_dmaqueue*)data; struct saa7134_dev *dev = q->dev; unsigned long flags; spin_lock_irqsave(&dev->slock,flags); /* try to reset the hardware (SWRST) */ saa_writeb(SAA7134_REGION_ENABLE, 0x00); saa_writeb(SAA7134_REGION_ENABLE, 0x80); saa_writeb(SAA7134_REGION_ENABLE, 0x00); /* flag current buffer as failed, try to start over with the next one. */ if (q->curr) { dprintk("timeout on %p\n",q->curr); saa7134_buffer_finish(dev,q,STATE_ERROR); } saa7134_buffer_next(dev,q); spin_unlock_irqrestore(&dev->slock,flags);}/* ------------------------------------------------------------------ */int saa7134_set_dmabits(struct saa7134_dev *dev){ u32 split, task=0, ctrl=0, irq=0; enum v4l2_field cap = V4L2_FIELD_ANY; enum v4l2_field ov = V4L2_FIELD_ANY;#if DEBUG_SPINLOCKS BUG_ON(!spin_is_locked(&dev->slock));#endif /* video capture -- dma 0 + video task A */ if (dev->video_q.curr) { task |= 0x01; ctrl |= SAA7134_MAIN_CTRL_TE0; irq |= SAA7134_IRQ1_INTE_RA0_1 | SAA7134_IRQ1_INTE_RA0_0; cap = dev->video_q.curr->vb.field; } /* video capture -- dma 1+2 (planar modes) */ if (dev->video_q.curr && dev->video_q.curr->fmt->planar) { ctrl |= SAA7134_MAIN_CTRL_TE4 | SAA7134_MAIN_CTRL_TE5; } /* screen overlay -- dma 0 + video task B */ if (dev->ovenable) { task |= 0x10; ctrl |= SAA7134_MAIN_CTRL_TE1; ov = dev->ovfield; } /* vbi capture -- dma 0 + vbi task A+B */ if (dev->vbi_q.curr) { task |= 0x22; ctrl |= SAA7134_MAIN_CTRL_TE2 | SAA7134_MAIN_CTRL_TE3; irq |= SAA7134_IRQ1_INTE_RA0_7 | SAA7134_IRQ1_INTE_RA0_6 | SAA7134_IRQ1_INTE_RA0_5 | SAA7134_IRQ1_INTE_RA0_4; } /* audio capture -- dma 3 */ if (dev->oss.dma_running) { ctrl |= SAA7134_MAIN_CTRL_TE6; irq |= SAA7134_IRQ1_INTE_RA3_1 | SAA7134_IRQ1_INTE_RA3_0; } /* TS capture -- dma 5 */ if (dev->ts_q.curr) { ctrl |= SAA7134_MAIN_CTRL_TE5; irq |= SAA7134_IRQ1_INTE_RA2_3 | SAA7134_IRQ1_INTE_RA2_2 | SAA7134_IRQ1_INTE_RA2_1 | SAA7134_IRQ1_INTE_RA2_0; } /* set task conditions + field handling */ if (V4L2_FIELD_HAS_BOTH(cap) || V4L2_FIELD_HAS_BOTH(ov) || cap == ov) { /* default config -- use full frames */ saa_writeb(SAA7134_TASK_CONDITIONS(TASK_A), 0x0d); saa_writeb(SAA7134_TASK_CONDITIONS(TASK_B), 0x0d); saa_writeb(SAA7134_FIELD_HANDLING(TASK_A), 0x02); saa_writeb(SAA7134_FIELD_HANDLING(TASK_B), 0x02); split = 0; } else { /* split fields between tasks */ if (V4L2_FIELD_TOP == cap) { /* odd A, even B, repeat */ saa_writeb(SAA7134_TASK_CONDITIONS(TASK_A), 0x0d); saa_writeb(SAA7134_TASK_CONDITIONS(TASK_B), 0x0e); } else { /* odd B, even A, repeat */ saa_writeb(SAA7134_TASK_CONDITIONS(TASK_A), 0x0e); saa_writeb(SAA7134_TASK_CONDITIONS(TASK_B), 0x0d); } saa_writeb(SAA7134_FIELD_HANDLING(TASK_A), 0x01); saa_writeb(SAA7134_FIELD_HANDLING(TASK_B), 0x01); split = 1; } /* irqs */ saa_writeb(SAA7134_REGION_ENABLE, task); saa_writel(SAA7134_IRQ1, irq); saa_andorl(SAA7134_MAIN_CTRL, SAA7134_MAIN_CTRL_TE0 | SAA7134_MAIN_CTRL_TE1 | SAA7134_MAIN_CTRL_TE2 | SAA7134_MAIN_CTRL_TE3 | SAA7134_MAIN_CTRL_TE4 | SAA7134_MAIN_CTRL_TE5 | SAA7134_MAIN_CTRL_TE6, ctrl); dprintk("dmabits: task=0x%02x ctrl=0x%02x irq=0x%x split=%s\n", task, ctrl, irq, split ? "no" : "yes"); return 0;}/* ------------------------------------------------------------------ *//* IRQ handler + helpers */static char *irqbits[] = { "DONE_RA0", "DONE_RA1", "DONE_RA2", "DONE_RA3", "AR", "PE", "PWR_ON", "RDCAP", "INTL", "FIDT", "MMC", "TRIG_ERR", "CONF_ERR", "LOAD_ERR", "GPIO16?", "GPIO18", "GPIO22", "GPIO23"};#define IRQBITS ARRAY_SIZE(irqbits)static void print_irqstatus(struct saa7134_dev *dev, int loop, unsigned long report, unsigned long status){ unsigned int i; printk(KERN_DEBUG "%s/irq[%d,%ld]: r=0x%lx s=0x%02lx", dev->name,loop,jiffies,report,status); for (i = 0; i < IRQBITS; i++) { if (!(report & (1 << i))) continue; printk(" %s",irqbits[i]); } if (report & SAA7134_IRQ_REPORT_DONE_RA0) { printk(" | RA0=%s,%s,%s,%ld", (status & 0x40) ? "vbi" : "video", (status & 0x20) ? "b" : "a", (status & 0x10) ? "odd" : "even", (status & 0x0f)); } printk("\n");}static irqreturn_t saa7134_irq(int irq, void *dev_id, struct pt_regs *regs){ struct saa7134_dev *dev = (struct saa7134_dev*) dev_id; unsigned long report,status; int loop, handled = 0; for (loop = 0; loop < 10; loop++) { report = saa_readl(SAA7134_IRQ_REPORT); status = saa_readl(SAA7134_IRQ_STATUS); if (0 == report) { if (irq_debug > 1) printk(KERN_DEBUG "%s/irq: no (more) work\n", dev->name); goto out; } handled = 1; saa_writel(SAA7134_IRQ_REPORT,report); if (irq_debug) print_irqstatus(dev,loop,report,status);#if 0 if (report & SAA7134_IRQ_REPORT_CONF_ERR) dump_statusregs(dev);#endif if (report & SAA7134_IRQ_REPORT_INTL) saa7134_irq_video_intl(dev); if ((report & SAA7134_IRQ_REPORT_DONE_RA0) && (status & 0x60) == 0) saa7134_irq_video_done(dev,status); if ((report & SAA7134_IRQ_REPORT_DONE_RA0) && (status & 0x40) == 0x40) saa7134_irq_vbi_done(dev,status); if ((report & SAA7134_IRQ_REPORT_DONE_RA2) && card_has_ts(dev)) saa7134_irq_ts_done(dev,status); if ((report & SAA7134_IRQ_REPORT_DONE_RA3)) saa7134_irq_oss_done(dev,status); if ((report & (SAA7134_IRQ_REPORT_GPIO16 | SAA7134_IRQ_REPORT_GPIO18)) && dev->remote) saa7134_input_irq(dev); }; if (10 == loop) { print_irqstatus(dev,loop,report,status); printk(KERN_WARNING "%s/irq: looping -- clearing enable bits\n",dev->name); /* disable all irqs */ saa_writel(SAA7134_IRQ1,0); saa_writel(SAA7134_IRQ2,0); } out: return IRQ_RETVAL(handled);}/* ------------------------------------------------------------------ *//* early init (no i2c, no irq) */static int saa7134_hwinit1(struct saa7134_dev *dev){ dprintk("hwinit1\n"); saa_writel(SAA7134_IRQ1, 0); saa_writel(SAA7134_IRQ2, 0); init_MUTEX(&dev->lock); dev->slock = SPIN_LOCK_UNLOCKED; saa7134_track_gpio(dev,"pre-init"); saa7134_video_init1(dev); saa7134_vbi_init1(dev); if (card_has_ts(dev)) saa7134_ts_init1(dev); saa7134_input_init1(dev); switch (dev->pci->device) { case PCI_DEVICE_ID_PHILIPS_SAA7134: case PCI_DEVICE_ID_PHILIPS_SAA7133: case PCI_DEVICE_ID_PHILIPS_SAA7135: saa7134_oss_init1(dev); break; } /* RAM FIFO config */ saa_writel(SAA7134_FIFO_SIZE, 0x08070503); saa_writel(SAA7134_THRESHOULD,0x02020202); /* enable audio + video processing */ saa_writel(SAA7134_MAIN_CTRL, SAA7134_MAIN_CTRL_VPLLE | SAA7134_MAIN_CTRL_APLLE | SAA7134_MAIN_CTRL_EXOSC | SAA7134_MAIN_CTRL_EVFE1 | SAA7134_MAIN_CTRL_EVFE2 | SAA7134_MAIN_CTRL_ESFE | SAA7134_MAIN_CTRL_EBADC | SAA7134_MAIN_CTRL_EBDAC); /* enable peripheral devices */ saa_writeb(SAA7134_SPECIAL_MODE, 0x01); /* set vertical line numbering start (vbi needs this) */ saa_writeb(SAA7134_SOURCE_TIMING2, 0x20); return 0;}/* late init (with i2c + irq) */static int saa7134_hwinit2(struct saa7134_dev *dev){ dprintk("hwinit2\n"); saa7134_video_init2(dev); saa7134_tvaudio_init2(dev); /* enable IRQ's */ saa_writel(SAA7134_IRQ1, 0); saa_writel(SAA7134_IRQ2, SAA7134_IRQ2_INTE_GPIO18 | SAA7134_IRQ2_INTE_GPIO18A | SAA7134_IRQ2_INTE_GPIO16 | SAA7134_IRQ2_INTE_SC2 | SAA7134_IRQ2_INTE_SC1 | SAA7134_IRQ2_INTE_SC0 | /* SAA7134_IRQ2_INTE_DEC5 | FIXME: TRIG_ERR ??? */ SAA7134_IRQ2_INTE_DEC3 | SAA7134_IRQ2_INTE_DEC2 | /* SAA7134_IRQ2_INTE_DEC1 | */ SAA7134_IRQ2_INTE_DEC0 | SAA7134_IRQ2_INTE_PE | SAA7134_IRQ2_INTE_AR); return 0;}/* shutdown */static int saa7134_hwfini(struct saa7134_dev *dev){ dprintk("hwfini\n"); switch (dev->pci->device) { case PCI_DEVICE_ID_PHILIPS_SAA7134: case PCI_DEVICE_ID_PHILIPS_SAA7133: case PCI_DEVICE_ID_PHILIPS_SAA7135: saa7134_oss_fini(dev); break; } if (card_has_ts(dev)) saa7134_ts_fini(dev); saa7134_input_fini(dev); saa7134_vbi_fini(dev); saa7134_video_fini(dev); saa7134_tvaudio_fini(dev); return 0;}static void __devinit must_configure_manually(void){ unsigned int i,p; printk(KERN_WARNING "saa7134: <rant>\n" "saa7134: Congratulations! Your TV card vendor saved a few\n" "saa7134: cents for a eeprom, thus your pci board has no\n" "saa7134: subsystem ID and I can't identify it automatically\n" "saa7134: </rant>\n" "saa7134: I feel better now. Ok, here are the good news:\n" "saa7134: You can use the card=<nr> insmod option to specify\n" "saa7134: which board do you have. The list:\n"); for (i = 0; i < saa7134_bcount; i++) { printk(KERN_WARNING "saa7134: card=%d -> %-40.40s", i,saa7134_boards[i].name); for (p = 0; saa7134_pci_tbl[p].driver_data; p++) { if (saa7134_pci_tbl[p].driver_data != i) continue; printk(" %04x:%04x", saa7134_pci_tbl[p].subvendor, saa7134_pci_tbl[p].subdevice); }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -