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

📄 saa7146_video.c

📁 linux环境下的dvb驱动程序
💻 C
📖 第 1 页 / 共 3 页
字号:
		/* nothing */;	};	switch (c->id) {	case V4L2_CID_BRIGHTNESS: {		u32 value = saa7146_read(dev, BCS_CTRL);		value &= 0x00ffffff;		value |= (c->value << 24);		saa7146_write(dev, BCS_CTRL, value);		saa7146_write(dev, MC2, MASK_22 | MASK_06 );		break;	}	case V4L2_CID_CONTRAST: {		u32 value = saa7146_read(dev, BCS_CTRL);		value &= 0xff00ffff;		value |= (c->value << 16);		saa7146_write(dev, BCS_CTRL, value);		saa7146_write(dev, MC2, MASK_22 | MASK_06 );		break;	}	case V4L2_CID_SATURATION: {		u32 value = saa7146_read(dev, BCS_CTRL);		value &= 0xffffff00;		value |= (c->value << 0);		saa7146_write(dev, BCS_CTRL, value);		saa7146_write(dev, MC2, MASK_22 | MASK_06 );		break;	}	case V4L2_CID_HFLIP:		/* fixme: we can supfhrt changing VFLIP and HFLIP here... */		if( 0 != vv->streaming ) {			DEB_D(("V4L2_CID_HFLIP while active capture.\n"));			return -EINVAL;		}		vv->hflip = c->value;		restart_overlay = 1;		break;	case V4L2_CID_VFLIP:		if( 0 != vv->streaming ) {			DEB_D(("V4L2_CID_VFLIP while active capture.\n"));			return -EINVAL;		}		vv->vflip = c->value;		restart_overlay = 1;		break;	default: {		return -EINVAL;	}	}	if( 0 != restart_overlay ) {		if( 0 != vv->ov_data ) {			if( fh == vv->ov_data->fh ) {				spin_lock_irqsave(&dev->slock,flags);				saa7146_stop_preview(fh);				saa7146_start_preview(fh);				spin_unlock_irqrestore(&dev->slock,flags);			}		}	}	return 0;}/********************************************************************************//* common pagetable functions */static int saa7146_pgtable_build(struct saa7146_dev *dev, struct saa7146_buf *buf){	struct pci_dev *pci = dev->pci;	struct scatterlist *list = buf->vb.dma.sglist;	int length = buf->vb.dma.sglen;	struct saa7146_format *sfmt = format_by_fourcc(dev,buf->fmt->pixelformat);	DEB_EE(("dev:%p, buf:%p, sg_len:%d\n",dev,buf,length));	if( 0 != IS_PLANAR(sfmt->trans)) {		struct saa7146_pgtable *pt1 = &buf->pt[0];		struct saa7146_pgtable *pt2 = &buf->pt[1];		struct saa7146_pgtable *pt3 = &buf->pt[2];		u32  *ptr1, *ptr2, *ptr3;		u32 fill;		int size = buf->fmt->width*buf->fmt->height;		int i,p,m1,m2,m3,o1,o2;		switch( sfmt->depth ) {			case 12: {				/* create some offsets inside the page table */				m1 = ((size+PAGE_SIZE)/PAGE_SIZE)-1;				m2 = ((size+(size/4)+PAGE_SIZE)/PAGE_SIZE)-1;				m3 = ((size+(size/2)+PAGE_SIZE)/PAGE_SIZE)-1;				o1 = size%PAGE_SIZE;				o2 = (size+(size/4))%PAGE_SIZE;				DEB_CAP(("size:%d, m1:%d, m2:%d, m3:%d, o1:%d, o2:%d\n",size,m1,m2,m3,o1,o2));				break;			}			case 16: {				/* create some offsets inside the page table */				m1 = ((size+PAGE_SIZE)/PAGE_SIZE)-1;				m2 = ((size+(size/2)+PAGE_SIZE)/PAGE_SIZE)-1;				m3 = ((2*size+PAGE_SIZE)/PAGE_SIZE)-1;				o1 = size%PAGE_SIZE;				o2 = (size+(size/2))%PAGE_SIZE;				DEB_CAP(("size:%d, m1:%d, m2:%d, m3:%d, o1:%d, o2:%d\n",size,m1,m2,m3,o1,o2));				break;			}			default: {				return -1;			}		}				ptr1 = pt1->cpu;		ptr2 = pt2->cpu;		ptr3 = pt3->cpu;		/* walk all pages, copy all page addresses to ptr1 */		for (i = 0; i < length; i++, list++) {			for (p = 0; p * 4096 < list->length; p++, ptr1++) {				*ptr1 = sg_dma_address(list) - list->offset;			}		}/*		ptr1 = pt1->cpu;		for(j=0;j<40;j++) {			printk("ptr1 %d: 0x%08x\n",j,ptr1[j]);		}*/				/* if we have a user buffer, the first page may not be		   aligned to a page boundary. */		pt1->offset = buf->vb.dma.sglist->offset;		pt2->offset = pt1->offset+o1;		pt3->offset = pt1->offset+o2;				/* create video-dma2 page table */		ptr1 = pt1->cpu;		for(i = m1; i <= m2 ; i++, ptr2++) {			*ptr2 = ptr1[i];		}		fill = *(ptr2-1);		for(;i<1024;i++,ptr2++) {			*ptr2 = fill;		}		/* create video-dma3 page table */		ptr1 = pt1->cpu;		for(i = m2; i <= m3; i++,ptr3++) {			*ptr3 = ptr1[i];		}		fill = *(ptr3-1);		for(;i<1024;i++,ptr3++) {			*ptr3 = fill;		}		/* finally: finish up video-dma1 page table */				ptr1 = pt1->cpu+m1;		fill = pt1->cpu[m1];		for(i=m1;i<1024;i++,ptr1++) {			*ptr1 = fill;		}/*		ptr1 = pt1->cpu;		ptr2 = pt2->cpu;		ptr3 = pt3->cpu;		for(j=0;j<40;j++) {			printk("ptr1 %d: 0x%08x\n",j,ptr1[j]);		}		for(j=0;j<40;j++) {			printk("ptr2 %d: 0x%08x\n",j,ptr2[j]);		}		for(j=0;j<40;j++) {			printk("ptr3 %d: 0x%08x\n",j,ptr3[j]);		}*/					} else {		struct saa7146_pgtable *pt = &buf->pt[0];		return saa7146_pgtable_build_single(pci, pt, list, length);	}	return 0;}/********************************************************************************//* file operations */static int video_begin(struct saa7146_fh *fh){	struct saa7146_dev *dev = fh->dev;	struct saa7146_vv *vv = dev->vv_data;	struct saa7146_format *fmt = NULL;	unsigned long flags;	unsigned int resource;	int ret = 0;	DEB_EE(("dev:%p, fh:%p\n",dev,fh));	if( fh == vv->streaming ) {		DEB_S(("already capturing.\n"));		return -EBUSY;	}	if( vv->streaming != 0 ) {		DEB_S(("already capturing, but in another open.\n"));		return -EBUSY;	}		fmt = format_by_fourcc(dev,fh->video_fmt.pixelformat);	/* we need to have a valid format set here */	BUG_ON(NULL == fmt);	if (0 != (fmt->flags & FORMAT_IS_PLANAR)) {		resource = RESOURCE_DMA1_HPS|RESOURCE_DMA2_CLP|RESOURCE_DMA3_BRS;	} else {		resource = RESOURCE_DMA1_HPS;	}	ret = saa7146_res_get(fh, resource);	if (0 == ret) {		DEB_S(("cannot get capture resource %d\n",resource));		return -EBUSY;	}		spin_lock_irqsave(&dev->slock,flags);	/* clear out beginning of streaming bit (rps register 0)*/	saa7146_write(dev, MC2, MASK_27 );	/* enable rps0 irqs */	IER_ENABLE(dev, MASK_27);	vv->streaming = fh;	spin_unlock_irqrestore(&dev->slock,flags);	return 0;}static int video_end(struct saa7146_fh *fh, struct file *file){	struct saa7146_dev *dev = fh->dev;	struct saa7146_vv *vv = dev->vv_data;	struct saa7146_format *fmt = NULL;	unsigned long flags;	unsigned int resource;	u32 dmas = 0;	DEB_EE(("dev:%p, fh:%p\n",dev,fh));	if( vv->streaming != fh ) {		DEB_S(("not capturing.\n"));		return -EINVAL;	}	fmt = format_by_fourcc(dev,fh->video_fmt.pixelformat);	/* we need to have a valid format set here */	BUG_ON(NULL == fmt);	if (0 != (fmt->flags & FORMAT_IS_PLANAR)) {		resource = RESOURCE_DMA1_HPS|RESOURCE_DMA2_CLP|RESOURCE_DMA3_BRS;		dmas = MASK_22 | MASK_21 | MASK_20;	} else {		resource = RESOURCE_DMA1_HPS;		dmas = MASK_22;	}	saa7146_res_free(fh, resource);	spin_lock_irqsave(&dev->slock,flags);	/* disable rps0  */	saa7146_write(dev, MC1, MASK_28);	/* disable rps0 irqs */	IER_DISABLE(dev, MASK_27);	/* shut down all used video dma transfers */	saa7146_write(dev, MC1, dmas);	vv->streaming = NULL;	spin_unlock_irqrestore(&dev->slock, flags);		return 0;}/* * This function is _not_ called directly, but from * video_generic_ioctl (and maybe others).  userspace * copying is done already, arg is a kernel pointer. */int saa7146_video_do_ioctl(struct inode *inode, struct file *file, unsigned int cmd, void *arg){	struct saa7146_fh *fh  = file->private_data;	struct saa7146_dev *dev = fh->dev;	struct saa7146_vv *vv = dev->vv_data;	unsigned long flags;	int err = 0, result = 0, ee = 0;	struct saa7146_use_ops *ops;	struct videobuf_queue *q;	/* check if extension handles the command */	for(ee = 0; dev->ext_vv_data->ioctls[ee].flags != 0; ee++) {		if( cmd == dev->ext_vv_data->ioctls[ee].cmd )			break;	}		if( 0 != (dev->ext_vv_data->ioctls[ee].flags & SAA7146_EXCLUSIVE) ) {		DEB_D(("extension handles ioctl exclusive.\n"));		result = dev->ext_vv_data->ioctl(fh, cmd, arg);		return result;	}	if( 0 != (dev->ext_vv_data->ioctls[ee].flags & SAA7146_BEFORE) ) {		DEB_D(("extension handles ioctl before.\n"));		result = dev->ext_vv_data->ioctl(fh, cmd, arg);		if( -EAGAIN != result ) {			return result;		}	}		/* fixme: add handle "after" case (is it still needed?) */	switch (fh->type) {	case V4L2_BUF_TYPE_VIDEO_CAPTURE: {		ops = &saa7146_video_uops;		q = &fh->video_q;		break;		}	case V4L2_BUF_TYPE_VBI_CAPTURE: {		ops = &saa7146_vbi_uops;		q = &fh->vbi_q;		break;		}	default:		BUG();		return 0;	}	switch (cmd) { 	case VIDIOC_QUERYCAP:	{		struct v4l2_capability *cap = arg;		memset(cap,0,sizeof(*cap));		DEB_EE(("VIDIOC_QUERYCAP\n"));		                strcpy(cap->driver, "saa7146 v4l2");		strlcpy(cap->card, dev->ext->name, sizeof(cap->card));		sprintf(cap->bus_info,"PCI:%s",dev->pci->slot_name);		cap->version = SAA7146_VERSION_CODE;		cap->capabilities =			V4L2_CAP_VIDEO_CAPTURE |			V4L2_CAP_VIDEO_OVERLAY |			V4L2_CAP_READWRITE | 			V4L2_CAP_STREAMING;		cap->capabilities |= dev->ext_vv_data->capabilities;		return 0;	}	case VIDIOC_G_FBUF:	{		struct v4l2_framebuffer *fb = arg;		DEB_EE(("VIDIOC_G_FBUF\n"));		*fb = vv->ov_fb;		fb->capability = V4L2_FBUF_CAP_LIST_CLIPPING;		return 0;	}	case VIDIOC_S_FBUF:	{		struct v4l2_framebuffer *fb = arg;		struct saa7146_format *fmt;		struct saa7146_fh *ov_fh = NULL;		int restart_overlay = 0;		DEB_EE(("VIDIOC_S_FBUF\n"));/*		if(!capable(CAP_SYS_ADMIN)) { // && !capable(CAP_SYS_RAWIO)) {			DEB_D(("VIDIOC_S_FBUF: not CAP_SYS_ADMIN or CAP_SYS_RAWIO.\n"));			return -EPERM;		}*/		/* check args */		fmt = format_by_fourcc(dev,fb->fmt.pixelformat);		if (NULL == fmt) {			return -EINVAL;		}				/* planar formats are not allowed for overlay video, clipping and video dma would clash */		if (0 != (fmt->flags & FORMAT_IS_PLANAR)) {			DEB_S(("planar pixelformat '%4.4s' not allowed for overlay\n",(char *)&fmt->pixelformat));		}				down(&dev->lock);		if( vv->ov_data != NULL ) {			ov_fh = vv->ov_data->fh;			saa7146_stop_preview(ov_fh);			restart_overlay = 1;		}		/* ok, accept it */		vv->ov_fb = *fb;		vv->ov_fmt = fmt;		if (0 == vv->ov_fb.fmt.bytesperline)			vv->ov_fb.fmt.bytesperline =				vv->ov_fb.fmt.width*fmt->depth/8;		if( 0 != restart_overlay ) {			saa7146_start_preview(ov_fh);		}		up(&dev->lock);		return 0;	}	case VIDIOC_ENUM_FMT:	{		struct v4l2_fmtdesc *f = arg;		int index;		switch (f->type) {		case V4L2_BUF_TYPE_VIDEO_CAPTURE:		case V4L2_BUF_TYPE_VIDEO_OVERLAY: {			index = f->index;			if (index < 0 || index >= NUM_FORMATS) {				return -EINVAL;			}			memset(f,0,sizeof(*f));			f->index = index;			strlcpy(f->description,formats[index].name,sizeof(f->description));			f->pixelformat = formats[index].pixelformat;			break;		}		default:			return -EINVAL;			}		DEB_EE(("VIDIOC_ENUM_FMT: type:%d, index:%d\n",f->type,f->index));		return 0;	}	case VIDIOC_QUERYCTRL:	{		const struct v4l2_queryctrl *ctrl;		struct v4l2_queryctrl *c = arg;		if ((c->id <  V4L2_CID_BASE ||		     c->id >= V4L2_CID_LASTP1) &&		    (c->id <  V4L2_CID_PRIVATE_BASE ||		     c->id >= V4L2_CID_PRIVATE_LASTP1))			return -EINVAL;					ctrl = ctrl_by_id(c->id);		if( NULL == ctrl ) {			return -EINVAL;/*			c->flags = V4L2_CTRL_FLAG_DISABLED;				return 0;*/		}		DEB_EE(("VIDIOC_QUERYCTRL: id:%d\n",c->id));		*c = *ctrl;		return 0;	}	case VIDIOC_G_CTRL: {		DEB_EE(("VIDIOC_G_CTRL\n"));		return get_control(fh,arg);	}	case VIDIOC_S_CTRL:/* FIXME: remove when videodev2.h update is in kernel */#ifdef VIDIOC_S_CTRL_OLD	case VIDIOC_S_CTRL_OLD:#endif	{		DEB_EE(("VIDIOC_S_CTRL\n"));		down(&dev->lock);		err = set_control(fh,arg);		up(&dev->lock);		return err;	}        case VIDIOC_G_PARM:        {                struct v4l2_streamparm *parm = arg;		if( parm->type != V4L2_BUF_TYPE_VIDEO_CAPTURE ) {			return -EINVAL;		}                memset(&parm->parm.capture,0,sizeof(struct v4l2_captureparm));		parm->parm.capture.readbuffers = 1;		// fixme: only for PAL!		parm->parm.capture.timeperframe.numerator = 1;		parm->parm.capture.timeperframe.denominator = 25;                return 0;        }	case VIDIOC_G_FMT:	{		struct v4l2_format *f = arg;		DEB_EE(("VIDIOC_G_FMT\n"));		return g_fmt(fh,f);	}	case VIDIOC_S_FMT:	{		struct v4l2_format *f = arg;		DEB_EE(("VIDIOC_S_FMT\n"));		return s_fmt(fh,f);	}

⌨️ 快捷键说明

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