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

📄 bttv-driver.c

📁 linux和2410结合开发 用他可以生成2410所需的zImage文件
💻 C
📖 第 1 页 / 共 5 页
字号:
	}	case BTTV_VERSION:	{		return BTTV_VERSION_CODE;	}                        	case BTTV_PICNR:	{		/* return picture;*/		return  0;	}	default:		return -ENOIOCTLCMD;	}	return 0;}/* *	This maps the vmalloced and reserved fbuffer to user space. * *  FIXME:  *  - PAGE_READONLY should suffice!? *  - remap_page_range is kind of inefficient for page by page remapping. *    But e.g. pte_alloc() does not work in modules ... :-( */static int do_bttv_mmap(struct bttv *btv, const char *adr, unsigned long size){        unsigned long start=(unsigned long) adr;        unsigned long page,pos;        if (size>gbuffers*gbufsize)                return -EINVAL;        if (!btv->fbuffer) {                if(fbuffer_alloc(btv))                        return -EINVAL;        }        pos=(unsigned long) btv->fbuffer;        while (size > 0) {                page = kvirt_to_pa(pos);                if (remap_page_range(start, page, PAGE_SIZE, PAGE_SHARED))                        return -EAGAIN;                start+=PAGE_SIZE;                pos+=PAGE_SIZE;                size-=PAGE_SIZE;        }        return 0;}static int bttv_mmap(struct video_device *dev, const char *adr, unsigned long size){        struct bttv *btv=(struct bttv *)dev;        int r;        down(&btv->lock);        r=do_bttv_mmap(btv, adr, size);        up(&btv->lock);        return r;}static struct video_device bttv_template={	owner:		THIS_MODULE,	name:		"UNSET",	type:		VID_TYPE_TUNER|VID_TYPE_CAPTURE|VID_TYPE_OVERLAY|VID_TYPE_TELETEXT,	hardware:	VID_HARDWARE_BT848,	open:		bttv_open,	close:		bttv_close,	read:		bttv_read,	write:		bttv_write,	ioctl:		bttv_ioctl,	mmap:		bttv_mmap,	minor:		-1,};static long vbi_read(struct video_device *v, char *buf, unsigned long count,		     int nonblock){	struct bttv *btv=(struct bttv *)(v-2);	int q,todo;	DECLARE_WAITQUEUE(wait, current);	todo=count;	while (todo && todo>(q=VBIBUF_SIZE-btv->vbip)) 	{		if (btv->needs_restart) {			down(&btv->lock);			bt848_restart(btv);			up(&btv->lock);		}		if(copy_to_user((void *) buf, (void *) btv->vbibuf+btv->vbip, q))			return -EFAULT;		todo-=q;		buf+=q;		add_wait_queue(&btv->vbiq, &wait);		current->state = TASK_INTERRUPTIBLE;		if (todo && q==VBIBUF_SIZE-btv->vbip) 		{			if(nonblock)			{				remove_wait_queue(&btv->vbiq, &wait);				current->state = TASK_RUNNING;				if(count==todo)					return -EWOULDBLOCK;				return count-todo;			}			schedule();			if(signal_pending(current))			{				remove_wait_queue(&btv->vbiq, &wait);                                current->state = TASK_RUNNING;				if(todo==count)					return -EINTR;				else					return count-todo;			}		}		remove_wait_queue(&btv->vbiq, &wait);		current->state = TASK_RUNNING;	}	if (todo) 	{		if(copy_to_user((void *) buf, (void *) btv->vbibuf+btv->vbip, todo))			return -EFAULT;		btv->vbip+=todo;	}	return count;}static unsigned int vbi_poll(struct video_device *dev, struct file *file,	poll_table *wait){	struct bttv *btv=(struct bttv *)(dev-2);	unsigned int mask = 0;	poll_wait(file, &btv->vbiq, wait);	if (btv->vbip < VBIBUF_SIZE)		mask |= (POLLIN | POLLRDNORM);	return mask;}static int vbi_open(struct video_device *dev, int flags){	struct bttv *btv=(struct bttv *)(dev-2); 	unsigned long irq_flags;        down(&btv->lock);	if (btv->needs_restart)		bt848_restart(btv);	set_pll(btv);	btv->vbip=VBIBUF_SIZE;	spin_lock_irqsave(&btv->s_lock, irq_flags);	btv->vbi_on = 1;	bt848_set_risc_jmps(btv,-1);	spin_unlock_irqrestore(&btv->s_lock, irq_flags);	up(&btv->lock);	return 0;   }static void vbi_close(struct video_device *dev){	struct bttv *btv=(struct bttv *)(dev-2); 	unsigned long irq_flags;	spin_lock_irqsave(&btv->s_lock, irq_flags);	btv->vbi_on = 0;	bt848_set_risc_jmps(btv,-1);	spin_unlock_irqrestore(&btv->s_lock, irq_flags);}static int vbi_ioctl(struct video_device *dev, unsigned int cmd, void *arg){	struct bttv *btv=(struct bttv *)(dev-2);	switch (cmd) {		case VIDIOCGCAP:	{		struct video_capability b;		strcpy(b.name,btv->vbi_dev.name);		b.type = ((bttv_tvcards[btv->type].tuner != -1) ? VID_TYPE_TUNER : 0) |			VID_TYPE_TELETEXT;		b.channels = 0;		b.audios = 0;		b.maxwidth = 0;		b.maxheight = 0;		b.minwidth = 0;		b.minheight = 0;		if(copy_to_user(arg,&b,sizeof(b)))			return -EFAULT;		return 0;	}	case VIDIOCGFREQ:	case VIDIOCSFREQ:	case VIDIOCGTUNER:	case VIDIOCSTUNER:	case VIDIOCGCHAN:	case VIDIOCSCHAN:	case BTTV_VERSION:		return bttv_ioctl(dev-2,cmd,arg);	case BTTV_VBISIZE:		/* make alevt happy :-) */		return VBIBUF_SIZE;	default:		return -EINVAL;	}}static struct video_device vbi_template={	owner:		THIS_MODULE,	name:		"bttv vbi",	type:		VID_TYPE_CAPTURE|VID_TYPE_TELETEXT,	hardware:	VID_HARDWARE_BT848,	open:		vbi_open,	close:		vbi_close,	read:		vbi_read,	write:		bttv_write,	poll:		vbi_poll,	ioctl:		vbi_ioctl,	minor:		-1,};static int radio_open(struct video_device *dev, int flags){	struct bttv *btv = (struct bttv *)(dev-1);	unsigned long v;        down(&btv->lock);	if (btv->user)		goto busy_unlock;	btv->user++;	btv->radio = 1;	v = 400*16;	bttv_call_i2c_clients(btv,VIDIOCSFREQ,&v);	bttv_call_i2c_clients(btv,AUDC_SET_RADIO,&btv->tuner_type);	bt848_muxsel(btv,0);	up(&btv->lock);	return 0;    busy_unlock:	up(&btv->lock);	return -EBUSY;}static void radio_close(struct video_device *dev){	struct bttv *btv=(struct bttv *)(dev-1);	down(&btv->lock);	btv->user--;	btv->radio = 0;	up(&btv->lock);}static long radio_read(struct video_device *v, char *buf, unsigned long count, int nonblock){	return -EINVAL;}static int radio_ioctl(struct video_device *dev, unsigned int cmd, void *arg){        struct bttv *btv=(struct bttv *)(dev-1);	switch (cmd) {		case VIDIOCGCAP:	{		struct video_capability v;		strcpy(v.name,btv->video_dev.name);		v.type = VID_TYPE_TUNER;		v.channels = 1;		v.audios = 1;		/* No we don't do pictures */		v.maxwidth = 0;		v.maxheight = 0;		v.minwidth = 0;		v.minheight = 0;		if (copy_to_user(arg, &v, sizeof(v)))			return -EFAULT;		return 0;		break;	}	case VIDIOCGTUNER:	{		struct video_tuner v;		if(copy_from_user(&v,arg,sizeof(v))!=0)			return -EFAULT;		if(v.tuner||btv->channel)	/* Only tuner 0 */			return -EINVAL;		strcpy(v.name, "Radio");		/* japan:          76.0 MHz -  89.9 MHz		   western europe: 87.5 MHz - 108.0 MHz		   russia:         65.0 MHz - 108.0 MHz */		v.rangelow=(int)(65*16);		v.rangehigh=(int)(108*16);		v.flags= 0; /* XXX */		v.mode = 0; /* XXX */		bttv_call_i2c_clients(btv,cmd,&v);		if(copy_to_user(arg,&v,sizeof(v)))			return -EFAULT;		return 0;	}	case VIDIOCSTUNER:	{		struct video_tuner v;		if(copy_from_user(&v, arg, sizeof(v)))			return -EFAULT;		/* Only channel 0 has a tuner */		if(v.tuner!=0 || btv->channel)			return -EINVAL;		/* XXX anything to do ??? */		return 0;	}	case VIDIOCGFREQ:	case VIDIOCSFREQ:	case VIDIOCGAUDIO:	case VIDIOCSAUDIO:		bttv_ioctl((struct video_device *)btv,cmd,arg);		break;	default:		return -ENOIOCTLCMD;	}	return 0;}static struct video_device radio_template={	owner:		THIS_MODULE,	name:		"bttv radio",	type:		VID_TYPE_TUNER,	hardware:	VID_HARDWARE_BT848,	open:		radio_open,	close:		radio_close,	read:		radio_read,          /* just returns -EINVAL */	write:		bttv_write,          /* just returns -EINVAL */	ioctl:		radio_ioctl,	minor:		-1,};static void bt848_set_risc_jmps(struct bttv *btv, int flags){	if (-1 == flags) {		/* defaults */		flags = 0;		if (btv->scr_on)			flags |= 0x03;		if (btv->vbi_on)			flags |= 0x0c;	}	if (bttv_debug > 1)		printk("bttv%d: set_risc_jmp %08lx:",		       btv->nr,virt_to_bus(btv->risc_jmp));	/* Sync to start of odd field */	btv->risc_jmp[0]=cpu_to_le32(BT848_RISC_SYNC|BT848_RISC_RESYNC                                |BT848_FIFO_STATUS_VRE);	btv->risc_jmp[1]=cpu_to_le32(0);	/* Jump to odd vbi sub */	btv->risc_jmp[2]=cpu_to_le32(BT848_RISC_JUMP|(0xd<<20));	if (flags&8) {		if (bttv_debug > 1)			printk(" ev=%08lx",virt_to_bus(btv->vbi_odd));		btv->risc_jmp[3]=cpu_to_le32(virt_to_bus(btv->vbi_odd));	} else {		if (bttv_debug > 1)			printk(" -----------");		btv->risc_jmp[3]=cpu_to_le32(virt_to_bus(btv->risc_jmp+4));	}        /* Jump to odd sub */	btv->risc_jmp[4]=cpu_to_le32(BT848_RISC_JUMP|(0xe<<20));	if (0 != btv->risc_cap_odd) {		if (bttv_debug > 1)			printk(" e%d=%08x",btv->gq_grab,btv->risc_cap_odd);		flags |= 3;		btv->risc_jmp[5]=cpu_to_le32(btv->risc_cap_odd);	} else if ((flags&2) &&		   (!btv->win.interlace || 0 == btv->risc_cap_even)) {		if (bttv_debug > 1)			printk(" eo=%08lx",virt_to_bus(btv->risc_scr_odd));		btv->risc_jmp[5]=cpu_to_le32(virt_to_bus(btv->risc_scr_odd));	} else {		if (bttv_debug > 1)			printk(" -----------");		btv->risc_jmp[5]=cpu_to_le32(virt_to_bus(btv->risc_jmp+6));	}	/* Sync to start of even field */	btv->risc_jmp[6]=cpu_to_le32(BT848_RISC_SYNC|BT848_RISC_RESYNC                                |BT848_FIFO_STATUS_VRO);	btv->risc_jmp[7]=cpu_to_le32(0);	/* Jump to even vbi sub */	btv->risc_jmp[8]=cpu_to_le32(BT848_RISC_JUMP);	if (flags&4) {		if (bttv_debug > 1)			printk(" ov=%08lx",virt_to_bus(btv->vbi_even));		btv->risc_jmp[9]=cpu_to_le32(virt_to_bus(btv->vbi_even));	} else {		if (bttv_debug > 1)			printk(" -----------");		btv->risc_jmp[9]=cpu_to_le32(virt_to_bus(btv->risc_jmp+10));	}	/* Jump to even sub */	btv->risc_jmp[10]=cpu_to_le32(BT848_RISC_JUMP|(8<<20));	if (0 != btv->risc_cap_even) {		if (bttv_debug > 1)			printk(" o%d=%08x",btv->gq_grab,btv->risc_cap_even);		flags |= 3;		btv->risc_jmp[11]=cpu_to_le32(btv->risc_cap_even);	} else if ((flags&1) &&		   btv->win.interlace) {		if (bttv_debug > 1)			printk(" oo=%08lx",virt_to_bus(btv->risc_scr_even));		btv->risc_jmp[11]=cpu_to_le32(virt_to_bus(btv->risc_scr_even));	} else {		if (bttv_debug > 1)			printk(" -----------");		btv->risc_jmp[11]=cpu_to_le32(virt_to_bus(btv->risc_jmp+12));	}	if (btv->gq_start) {		btv->risc_jmp[12]=cpu_to_le32(BT848_RISC_JUMP|(0x8<<16)|BT848_RISC_IRQ);	} else {		btv->risc_jmp[12]=cpu_to_le32(BT848_RISC_JUMP);	}	btv->risc_jmp[13]=cpu_to_le32(virt_to_bus(btv->risc_jmp));	/* enable cpaturing and DMA */	if (bttv_debug > 1)		printk(" flags=0x%x dma=%s\n",		       flags,(flags&0x0f) ? "on" : "off");	btaor(flags, ~0x0f, BT848_CAP_CTL);	if (flags&0x0f)		bt848_dma(btv, 3);	else		bt848_dma(btv, 0);}# define do_video_register(dev,type,nr) video_register_device(dev,type,nr)static int __devinit init_video_dev(struct bttv *btv){	audio(btv, AUDIO_MUTE, 1);        	if(do_video_register(&btv->video_dev,VFL_TYPE_GRABBER,video_nr)<0)		return -1;	if(do_video_register(&btv->vbi_dev,VFL_TYPE_VBI,vbi_nr)<0)         {	        video_unregister_device(&btv->video_dev);		return -1;	}	if (btv->has_radio)	{		if(do_video_register(&btv->radio_dev, VFL_TYPE_RADIO, radio_nr)<0)                 {		        video_unregister_device(&btv->vbi_dev);		        video_unregister_device(&btv->video_dev);			return -1;		}	}        return 1;}static int __devinit init_bt848(struct bttv *btv){	int j; 	unsigned long irq_flags;	btv->user=0;         init_MUTEX(&btv->lock);	/* dump current state of the gpio registers before changing them,	 * might help to make a new card work */	if (bttv_gpio)		bttv_gpio_tracking(btv,"init #1");	/* reset the bt848 */	btwrite(0, BT848_SRESET);	DEBUG(printk(KERN_DEBUG "bttv%d: bt848_mem: 0x%lx\n", btv->nr, (unsigned long) btv->bt848_mem));	/* not registered yet */	btv->video_dev.minor = -1;	btv->radio_dev.minor = -1;	btv->vbi_dev.minor = -1;	/* default setup for max. PAL size in a 1024xXXX hicolor framebuffer */	btv->win.norm=0; /* change this to 1 for NTSC,

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -