📄 saa7134-core.c
字号:
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; assert_spin_locked(&dev->slock); /* 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->dmasound.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; } /* If dmasound support is active and we get a sound report, exit and let the saa7134-alsa/oss module deal with it */ if ((report & SAA7134_IRQ_REPORT_DONE_RA3) && (dev->dmasound.priv_data != NULL) ) { if (irq_debug > 1) printk(KERN_DEBUG "%s/irq: ignoring interrupt for DMA sound\n", dev->name); goto out; } handled = 1; saa_writel(SAA7134_IRQ_REPORT,report); if (irq_debug) print_irqstatus(dev,loop,report,status); if (report & SAA7134_IRQ_REPORT_RDCAP /* _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_mpeg(dev)) saa7134_irq_ts_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); if (report & SAA7134_IRQ_REPORT_PE) { /* disable all parity error */ printk(KERN_WARNING "%s/irq: looping -- " "clearing PE (parity error!) enable bit\n",dev->name); saa_clearl(SAA7134_IRQ2,SAA7134_IRQ2_INTE_PE); } else if (report & (SAA7134_IRQ_REPORT_GPIO16 | SAA7134_IRQ_REPORT_GPIO18)) { /* disable gpio IRQs */ printk(KERN_WARNING "%s/irq: looping -- " "clearing GPIO enable bits\n",dev->name); saa_clearl(SAA7134_IRQ2, (SAA7134_IRQ2_INTE_GPIO16 | SAA7134_IRQ2_INTE_GPIO18)); } else { /* disable all irqs */ printk(KERN_WARNING "%s/irq: looping -- " "clearing all enable bits\n",dev->name); 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); spin_lock_init(&dev->slock); saa7134_track_gpio(dev,"pre-init"); saa7134_video_init1(dev); saa7134_vbi_init1(dev); if (card_has_mpeg(dev)) saa7134_ts_init1(dev); saa7134_input_init1(dev); /* 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_EBDAC); /* * Initialize OSS _after_ enabling audio clock PLL and audio processing. * OSS initialization writes to registers via the audio DSP; these * writes will fail unless the audio clock has been started. At worst, * audio will not work. */ /* 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){ unsigned int irq2_mask; dprintk("hwinit2\n"); saa7134_video_init2(dev); saa7134_tvaudio_init2(dev); /* enable IRQ's */ irq2_mask = SAA7134_IRQ2_INTE_DEC3 | SAA7134_IRQ2_INTE_DEC2 | SAA7134_IRQ2_INTE_DEC1 | SAA7134_IRQ2_INTE_DEC0 | SAA7134_IRQ2_INTE_PE | SAA7134_IRQ2_INTE_AR; if (dev->has_remote == SAA7134_REMOTE_GPIO) irq2_mask |= (SAA7134_IRQ2_INTE_GPIO18 | SAA7134_IRQ2_INTE_GPIO18A | SAA7134_IRQ2_INTE_GPIO16 ); saa_writel(SAA7134_IRQ1, 0); saa_writel(SAA7134_IRQ2, irq2_mask); return 0;}/* shutdown */static int saa7134_hwfini(struct saa7134_dev *dev){ dprintk("hwfini\n"); if (card_has_mpeg(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); } printk("\n"); }}static struct video_device *vdev_init(struct saa7134_dev *dev, struct video_device *template, char *type){ struct video_device *vfd; vfd = video_device_alloc(); if (NULL == vfd) return NULL; *vfd = *template; vfd->minor = -1; vfd->dev = &dev->pci->dev; vfd->release = video_device_release; snprintf(vfd->name, sizeof(vfd->name), "%s %s (%s)", dev->name, type, saa7134_boards[dev->board].name); return vfd;}static void saa7134_unregister_video(struct saa7134_dev *dev){ if (dev->video_dev) { if (-1 != dev->video_dev->minor) video_unregister_device(dev->video_dev); else video_device_release(dev->video_dev); dev->video_dev = NULL; } if (dev->vbi_dev) { if (-1 != dev->vbi_dev->minor) video_unregister_device(dev->vbi_dev); else video_device_release(dev->vbi_dev); dev->vbi_dev = NULL;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -