⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 saa7134-core.c

📁 该代码是天敏电视卡天敏大师4的核心芯片在linux下面的驱动
💻 C
📖 第 1 页 / 共 3 页
字号:
#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 + -