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

📄 bttv.c

📁 powerpc内核mpc8241linux系统下char驱动程序
💻 C
📖 第 1 页 / 共 5 页
字号:
			}			interruptible_sleep_on(&btv->vbiq);			sti();			if(signal_pending(current))			{				if(todo==count)					return -EINTR;				else					return count-todo;			}		}	}	if (todo) 	{		if(copy_to_user((void *) buf, (void *) btv->vbibuf+btv->vbip, todo))			return -EFAULT;		btv->vbip+=todo;	}	return count;}/* *	Open a bttv card. Right now the flags stuff is just playing */ static int bttv_open(struct video_device *dev, int flags){	struct bttv *btv = (struct bttv *)dev;	int users, i;        if (btv->user)                return -EBUSY;        audio(btv, AUDIO_UNMUTE);        for (i=users=0; i<bttv_num; i++)                users+=bttvs[i].user;        if (users==1)                find_vga();        btv->fbuffer=NULL;        if (!btv->fbuffer)                btv->fbuffer=(unsigned char *) rvmalloc(2*BTTV_MAX_FBUF);        if (!btv->fbuffer)                return -EINVAL;        btv->grabbing = 0;        btv->grab = 0;        btv->lastgrab = 0;        for (i = 0; i < MAX_GBUFFERS; i++)                btv->frame_stat[i] = GBUFFER_UNUSED;        btv->user++;        MOD_INC_USE_COUNT;        return 0;   }static void bttv_close(struct video_device *dev){	struct bttv *btv=(struct bttv *)dev;		btv->user--;	audio(btv, AUDIO_INTERN);	btv->cap&=~3;	bt848_set_risc_jmps(btv);	/*	 *	A word of warning. At this point the chip	 *	is still capturing because its FIFO hasn't emptied	 *	and the DMA control operations are posted PCI 	 *	operations.	 */	btread(BT848_I2C); 	/* This fixes the PCI posting delay */		/*	 *	This is sucky but right now I can't find a good way to	 *	be sure its safe to free the buffer. We wait 5-6 fields	 *	which is more than sufficient to be sure.	 */	 	current->state = TASK_UNINTERRUPTIBLE;	schedule_timeout(HZ/10);	/* Wait 1/10th of a second */		/*	 *	We have allowed it to drain.	 */	if(btv->fbuffer)		rvfree((void *) btv->fbuffer, 2*BTTV_MAX_FBUF);	btv->fbuffer=0;	MOD_DEC_USE_COUNT;  }/***********************************//* ioctls and supporting functions *//***********************************/extern inline void bt848_bright(struct bttv *btv, uint bright){	btwrite(bright&0xff, BT848_BRIGHT);}extern inline void bt848_hue(struct bttv *btv, uint hue){	btwrite(hue&0xff, BT848_HUE);}extern inline void bt848_contrast(struct bttv *btv, uint cont){	unsigned int conthi;	conthi=(cont>>6)&4;	btwrite(cont&0xff, BT848_CONTRAST_LO);	btaor(conthi, ~4, BT848_E_CONTROL);	btaor(conthi, ~4, BT848_O_CONTROL);}extern inline void bt848_sat_u(struct bttv *btv, unsigned long data){	u32 datahi;	datahi=(data>>7)&2;	btwrite(data&0xff, BT848_SAT_U_LO);	btaor(datahi, ~2, BT848_E_CONTROL);	btaor(datahi, ~2, BT848_O_CONTROL);}static inline void bt848_sat_v(struct bttv *btv, unsigned long data){	u32 datahi;	datahi=(data>>8)&1;	btwrite(data&0xff, BT848_SAT_V_LO);	btaor(datahi, ~1, BT848_E_CONTROL);	btaor(datahi, ~1, BT848_O_CONTROL);}/* *	ioctl routine */ static int bttv_ioctl(struct video_device *dev, unsigned int cmd, void *arg){	unsigned char eedata[256];	struct bttv *btv=(struct bttv *)dev; 	int i;  		switch (cmd)	{			case VIDIOCGCAP:		{			struct video_capability b;			strcpy(b.name,btv->video_dev.name);			b.type = VID_TYPE_CAPTURE|			 	VID_TYPE_TUNER|				VID_TYPE_TELETEXT|				VID_TYPE_OVERLAY|				VID_TYPE_CLIPPING|				VID_TYPE_FRAMERAM|				VID_TYPE_SCALES;			b.channels = tvcards[btv->type].video_inputs;			b.audios = tvcards[btv->type].audio_inputs;			b.maxwidth = tvnorms[btv->win.norm].swidth;			b.maxheight = tvnorms[btv->win.norm].sheight;			b.minwidth = 32;			b.minheight = 32;			if(copy_to_user(arg,&b,sizeof(b)))				return -EFAULT;			return 0;		}		case VIDIOCGCHAN:		{			struct video_channel v;			if(copy_from_user(&v, arg,sizeof(v)))				return -EFAULT;			v.flags=VIDEO_VC_AUDIO;			v.tuners=0;			v.type=VIDEO_TYPE_CAMERA;			v.norm = btv->win.norm;                        if (v.channel>=tvcards[btv->type].video_inputs)                                return -EINVAL;                        if(v.channel==tvcards[btv->type].tuner)                         {                                strcpy(v.name,"Television");                                v.flags|=VIDEO_VC_TUNER;                                v.type=VIDEO_TYPE_TV;                                v.tuners=1;                        }                         else if(v.channel==tvcards[btv->type].svhs)                                 strcpy(v.name,"S-Video");                        else                                sprintf(v.name,"Composite%d",v.channel);			if(copy_to_user(arg,&v,sizeof(v)))				return -EFAULT;			return 0;		}		/*		 *	Each channel has 1 tuner		 */		case VIDIOCSCHAN:		{			struct video_channel v;			if(copy_from_user(&v, arg,sizeof(v)))				return -EFAULT;                                                if (v.channel>tvcards[btv->type].video_inputs)                                return -EINVAL;			bt848_muxsel(btv, v.channel);			if(v.norm!=VIDEO_MODE_PAL&&v.norm!=VIDEO_MODE_NTSC			   &&v.norm!=VIDEO_MODE_SECAM)				return -EOPNOTSUPP;			btv->win.norm = v.norm;                        make_vbitab(btv);			bt848_set_winsize(btv);			btv->channel=v.channel;			return 0;		}		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, "Television");			v.rangelow=0;			v.rangehigh=0xFFFFFFFF;			v.flags=VIDEO_TUNER_PAL|VIDEO_TUNER_NTSC|VIDEO_TUNER_SECAM;			if (btv->audio_chip == TDA9840) {				v.flags |= VIDEO_AUDIO_VOLUME;				v.mode = VIDEO_SOUND_MONO|VIDEO_SOUND_STEREO;				v.mode |= VIDEO_SOUND_LANG1|VIDEO_SOUND_LANG2;			}			if (btv->audio_chip == TDA9850) {				unsigned char ALR1;				ALR1 = I2CRead(&(btv->i2c), I2C_TDA9850|1);				if (ALR1 & 32)					v.flags |= VIDEO_TUNER_STEREO_ON;			}			v.mode = btv->win.norm;			v.signal = (btread(BT848_DSTATUS)&BT848_DSTATUS_HLOC) ? 0xFFFF : 0;			if(copy_to_user(arg,&v,sizeof(v)))				return -EFAULT;			return 0;		}		/* We have but one tuner */		case VIDIOCSTUNER:		{			struct video_tuner v;			if(copy_from_user(&v, arg, sizeof(v)))				return -EFAULT;			/* Only one channel has a tuner */                        if(v.tuner!=tvcards[btv->type].tuner) 				return -EINVAL; 							if(v.mode!=VIDEO_MODE_PAL&&v.mode!=VIDEO_MODE_NTSC			   &&v.mode!=VIDEO_MODE_SECAM)				return -EOPNOTSUPP; 			btv->win.norm = v.mode; 			bt848_set_winsize(btv);			return 0;		}		case VIDIOCGPICT:		{			struct video_picture p=btv->picture;			if(btv->win.depth==8)				p.palette=VIDEO_PALETTE_HI240;			if(btv->win.depth==15)				p.palette=VIDEO_PALETTE_RGB555;			if(btv->win.depth==16)				p.palette=VIDEO_PALETTE_RGB565;			if(btv->win.depth==24)				p.palette=VIDEO_PALETTE_RGB24;			if(btv->win.depth==32)				p.palette=VIDEO_PALETTE_RGB32;						if(copy_to_user(arg, &p, sizeof(p)))				return -EFAULT;			return 0;		}		case VIDIOCSPICT:		{			struct video_picture p;			int format;			if(copy_from_user(&p, arg,sizeof(p)))				return -EFAULT;			/* We want -128 to 127 we get 0-65535 */			bt848_bright(btv, (p.brightness>>8)-128);			/* 0-511 for the colour */			bt848_sat_u(btv, p.colour>>7);			bt848_sat_v(btv, ((p.colour>>7)*201L)/237);			/* -128 to 127 */			bt848_hue(btv, (p.hue>>8)-128);			/* 0-511 */			bt848_contrast(btv, p.contrast>>7);			btv->picture = p;                        /* set palette if bpp matches */                        if (p.palette < sizeof(palette2fmt)/sizeof(int)) {                                format = palette2fmt[p.palette];                                if (fmtbppx2[format&0x0f]/2 == btv->win.bpp)                                        btv->win.color_fmt = format;                        }                	return 0;		}		case VIDIOCSWIN:		{			struct video_window vw;			struct video_clip *vcp = NULL;			int on;						if(copy_from_user(&vw,arg,sizeof(vw)))				return -EFAULT;				 			if(vw.flags || vw.width < 16 || vw.height < 16)                         { 			        bt848_cap(btv,0);				return -EINVAL;                        }					if (btv->win.bpp < 4)                         {	/* 32-bit align start and adjust width */				int i = vw.x;				vw.x = (vw.x + 3) & ~3;				i = vw.x - i;				vw.width -= i;			}			btv->win.x=vw.x;			btv->win.y=vw.y;			btv->win.width=vw.width;			btv->win.height=vw.height;			if(btv->win.height>btv->win.cropheight/2)				btv->win.interlace=1;			else				btv->win.interlace=0;			on=(btv->cap&3);						bt848_cap(btv,0);			bt848_set_winsize(btv);			/*			 *	Do any clips.			 */			if(vw.clipcount<0) {				if((vcp=vmalloc(VIDEO_CLIPMAP_SIZE))==NULL)					return -ENOMEM;				if(copy_from_user(vcp, vw.clips,					VIDEO_CLIPMAP_SIZE)) {					vfree(vcp);					return -EFAULT;				}			} else if (vw.clipcount) {				if((vcp=vmalloc(sizeof(struct video_clip)*					(vw.clipcount))) == NULL)					return -ENOMEM;				if(copy_from_user(vcp,vw.clips,					sizeof(struct video_clip)*					vw.clipcount)) {					vfree(vcp);					return -EFAULT;				}			}			make_clip_tab(btv, vcp, vw.clipcount);			if (vw.clipcount != 0)				vfree(vcp);			if(on && btv->win.vidadr!=0)				bt848_cap(btv,1);			return 0;		}		case VIDIOCGWIN:		{			struct video_window vw;			/* Oh for a COBOL move corresponding .. */			vw.x=btv->win.x;			vw.y=btv->win.y;			vw.width=btv->win.width;			vw.height=btv->win.height;			vw.chromakey=0;			vw.flags=0;			if(btv->win.interlace)				vw.flags|=VIDEO_WINDOW_INTERLACE;			if(copy_to_user(arg,&vw,sizeof(vw)))				return -EFAULT;			return 0;		}		case VIDIOCCAPTURE:		{			int v;			if(copy_from_user(&v, arg,sizeof(v)))				return -EFAULT;			if(v==0)			{				bt848_cap(btv,0);			}			else			{			        if(btv->win.vidadr==0 || btv->win.width==0				   || btv->win.height==0)				  return -EINVAL;				bt848_cap(btv,1);			}			return 0;		}		case VIDIOCGFBUF:		{			struct video_buffer v;			v.base=(void *)btv->win.vidadr;			v.height=btv->win.sheight;			v.width=btv->win.swidth;			v.depth=btv->win.depth;			v.bytesperline=btv->win.bpl;			if(copy_to_user(arg, &v,sizeof(v)))				return -EFAULT;			return 0;					}		case VIDIOCSFBUF:		{			struct video_buffer v;#if LINUX_VERSION_CODE >= 0x020100			if(!capable(CAP_SYS_ADMIN))#else			if(!suser())#endif				return -EPERM;			if(copy_from_user(&v, arg,sizeof(v)))				return -EFAULT;			if(v.depth!=8 && v.depth!=15 && v.depth!=16 && 				v.depth!=24 && v.depth!=32 && v.width > 16 &&				v.height > 16 && v.bytesperline > 16)				return -EINVAL;                        if (v.base)                        {                                if ((unsigned long)v.base&1)                                        btv->win.vidadr=(unsigned long)(PAGE_OFFSET|uvirt_to_bus((unsigned long)v.base));                                else                                        btv->win.vidadr=(unsigned long)v.base;                        }			btv->win.sheight=v.height;			btv->win.swidth=v.width;			btv->win.bpp=((v.depth+7)&0x38)/8;			btv->win.depth=v.depth;			btv->win.bpl=v.bytesperline;						DEBUG(printk("Display at %p is %d by %d, bytedepth %d, bpl %d\n",				v.base, v.width,v.height, btv->win.bpp, btv->win.bpl));			bt848_set_winsize(btv);			return 0;				}		case VIDIOCKEY:		{			/* Will be handled higher up .. */			return 0;		}		case VIDIOCGFREQ:		{			unsigned long v=btv->win.freq;			if(copy_to_user(arg,&v,sizeof(v)))				return -EFAULT;			return 0;		}		case VIDIOCSFREQ:		{			unsigned long v;			if(copy_from_user(&v, arg, sizeof(v)))				return -EFAULT;			btv->win.freq=v;			set_freq(btv, btv->win.freq);			return 0;		}			case VIDIOCGAUDIO:		{			struct video_audio v;			v=btv->audio_dev;			v.flags&=~(VIDEO_AUDIO_MUTE|VIDEO_AUDIO_MUTABLE);			v.flags|=VIDEO_AUDIO_MUTABLE;			strcpy(v.name,"TV");			if (btv->audio_chip == TDA9850) {				unsigned char ALR1;				ALR1 = I2CRead(&(btv->i2c), I2C_TDA9850|1);				v.mode = VIDEO_SOUND_MONO;				v.mode |= (ALR1 & 32) ? VIDEO_SOUND_STEREO:0;				v.mode |= (ALR1 & 64) ? VIDEO_SOUND_LANG1:0;			}			if (btv->have_msp3400) 			{                                v.flags|=VIDEO_AUDIO_VOLUME |                                	VIDEO_AUDIO_BASS |                                	VIDEO_AUDIO_TREBLE;                                i2c_control_device(&(btv->i2c),                                                I2C_DRIVERID_MSP3400,                                                MSP_GET_VOLUME,&(v.volume));                                i2c_control_device(&(btv->i2c),                                                I2C_DRIVERID_MSP3400,                                                MSP_GET_BASS,&(v.bass));                                i2c_control_device(&(btv->i2c),                                                I2C_DRIVERID_MSP3400,                                                MSP_GET_TREBLE,&(v.treble));                        	i2c_control_device(&(btv->i2c),                                		I2C_DRIVERID_MSP3400,                                                MSP_GET_STEREO,&(v.mode));

⌨️ 快捷键说明

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