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

📄 saa7146_video.c

📁 linux环境下的dvb驱动程序
💻 C
📖 第 1 页 / 共 3 页
字号:
	case VIDIOC_TRY_FMT:	{		struct v4l2_format *f = arg;		DEB_EE(("VIDIOC_TRY_FMT\n"));		return try_fmt(fh,f);	}	case VIDIOC_G_STD:	{		v4l2_std_id *id = arg;		DEB_EE(("VIDIOC_G_STD\n"));		*id = vv->standard->id;		return 0;	}	/* the saa7146 supfhrts (used in conjunction with the saa7111a for example)	   PAL / NTSC / SECAM. if your hardware does not (or does more)	   -- override this function in your extension */	case VIDIOC_ENUMSTD:	{		struct v4l2_standard *e = arg;		if (e->index < 0 )			return -EINVAL;		if( e->index < dev->ext_vv_data->num_stds ) {			DEB_EE(("VIDIOC_ENUMSTD: index:%d\n",e->index));			v4l2_video_std_construct(e, dev->ext_vv_data->stds[e->index].id, dev->ext_vv_data->stds[e->index].name);			return 0;		}		return -EINVAL;	}	case VIDIOC_S_STD:	{		v4l2_std_id *id = arg;		int i;				int restart_overlay = 0;		int found = 0;				struct saa7146_fh *ov_fh = NULL;								DEB_EE(("VIDIOC_S_STD\n"));		if( 0 != vv->streaming ) {			return -EBUSY;		}		down(&dev->lock);				if( vv->ov_data != NULL ) {			ov_fh = vv->ov_data->fh;			saa7146_stop_preview(ov_fh);			restart_overlay = 1;		}		for(i = 0; i < dev->ext_vv_data->num_stds; i++)			if (*id & dev->ext_vv_data->stds[i].id)				break;		if (i != dev->ext_vv_data->num_stds) {			vv->standard = &dev->ext_vv_data->stds[i];			if( NULL != dev->ext_vv_data->std_callback )				dev->ext_vv_data->std_callback(dev, vv->standard);			found = 1;		}		if( 0 != restart_overlay ) {			saa7146_start_preview(ov_fh);		}		up(&dev->lock);		if( 0 == found ) {			DEB_EE(("VIDIOC_S_STD: standard not found.\n"));			return -EINVAL;		}		DEB_EE(("VIDIOC_S_STD: set to standard to '%s'\n",vv->standard->name));		return 0;	}	case VIDIOC_OVERLAY:/* FIXME: remove when videodev2.h update is in kernel */#ifdef VIDIOC_OVERLAY_OLD	case VIDIOC_OVERLAY_OLD:#endif	{		int on = *(int *)arg;		int err = 0;		if( NULL == vv->ov_fmt && on != 0 ) {			DEB_D(("VIDIOC_OVERLAY: no framebuffer informations. call S_FBUF first!\n"));			return -EAGAIN;		}		DEB_D(("VIDIOC_OVERLAY on:%d\n",on));		if( 0 != on ) {			if( vv->ov_data != NULL ) {				if( fh != vv->ov_data->fh) {					DEB_D(("overlay already active in another open\n"));					return -EAGAIN;				}			}			if (0 == saa7146_res_get(fh, RESOURCE_DMA1_HPS|RESOURCE_DMA2_CLP)) {				DEB_D(("cannot get overlay resources\n"));				return -EBUSY;			}			spin_lock_irqsave(&dev->slock,flags);			err = saa7146_start_preview(fh);			spin_unlock_irqrestore(&dev->slock,flags);			return err;		}				if( vv->ov_data != NULL ) {			if( fh != vv->ov_data->fh) {				DEB_D(("overlay is active, but in another open\n"));				return -EAGAIN;			}		} else {			DEB_D(("overlay is not active\n"));			return 0;				}		spin_lock_irqsave(&dev->slock,flags);		err = saa7146_stop_preview(fh);		spin_unlock_irqrestore(&dev->slock,flags);		/* free resources */		saa7146_res_free(fh, RESOURCE_DMA1_HPS|RESOURCE_DMA2_CLP);		return err;	}	case VIDIOC_REQBUFS: {		struct v4l2_requestbuffers *req = arg;		DEB_D(("VIDIOC_REQBUFS, type:%d\n",req->type));		return videobuf_reqbufs(file,q,req);	}	case VIDIOC_QUERYBUF: {		struct v4l2_buffer *buf = arg;		DEB_D(("VIDIOC_QUERYBUF, type:%d, offset:%d\n",buf->type,buf->m.offset));		return videobuf_querybuf(q,buf);	}	case VIDIOC_QBUF: {		struct v4l2_buffer *buf = arg;		int ret = 0;		ret = videobuf_qbuf(file,q,buf);		DEB_D(("VIDIOC_QBUF: ret:%d, index:%d\n",ret,buf->index));		return ret;	}	case VIDIOC_DQBUF: {		struct v4l2_buffer *buf = arg;		int ret = 0;		ret = videobuf_dqbuf(file,q,buf);		DEB_D(("VIDIOC_DQBUF: ret:%d, index:%d\n",ret,buf->index));		return ret;	}	case VIDIOC_STREAMON: {		int *type = arg;		DEB_D(("VIDIOC_STREAMON, type:%d\n",*type));			if( fh == vv->streaming ) {			DEB_D(("already capturing.\n"));			return 0;		}		err = video_begin(fh);		if( 0 != err) {			return err;		}		err = videobuf_streamon(file,q);		return err;	}	case VIDIOC_STREAMOFF: {		int *type = arg;		DEB_D(("VIDIOC_STREAMOFF, type:%d\n",*type));		if( fh != vv->streaming ) {			DEB_D(("this open is not capturing.\n"));			return -EINVAL;		}		err = videobuf_streamoff(file,q);		video_end(fh, file);		return err;	}	case VIDIOCGMBUF:	{		struct video_mbuf *mbuf = arg;		struct videobuf_queue *q;		int i;		/* fixme: number of capture buffers and sizes for v4l apps */		int gbuffers = 2; 		int gbufsize = 768*576*4;				DEB_D(("VIDIOCGMBUF \n"));		q = &fh->video_q;		down(&q->lock);		err = videobuf_mmap_setup(file,q,gbuffers,gbufsize,					  V4L2_MEMORY_MMAP);		if (err < 0) {			up(&q->lock);			return err;		}		memset(mbuf,0,sizeof(*mbuf));		mbuf->frames = gbuffers;		mbuf->size   = gbuffers * gbufsize;		for (i = 0; i < gbuffers; i++)			mbuf->offsets[i] = i * gbufsize;		up(&q->lock);		return 0;	}	default:		return v4l_compat_translate_ioctl(inode,file,cmd,arg,						  saa7146_video_do_ioctl);	}	return 0;}/*********************************************************************************//* buffer handling functions                                                  */static int buffer_activate (struct saa7146_dev *dev,		     struct saa7146_buf *buf,		     struct saa7146_buf *next){	struct saa7146_vv *vv = dev->vv_data;	buf->vb.state = STATE_ACTIVE;	saa7146_set_capture(dev,buf,next);		mod_timer(&vv->video_q.timeout, jiffies+BUFFER_TIMEOUT);	return 0;}static int buffer_prepare(struct file *file, struct videobuf_buffer *vb, enum v4l2_field field){	struct saa7146_fh *fh = file->private_data;	struct saa7146_dev *dev = fh->dev;	struct saa7146_vv *vv = dev->vv_data;	struct saa7146_buf *buf = (struct saa7146_buf *)vb;	int size,err = 0;	DEB_CAP(("vbuf:%p\n",vb));	/* sanity checks */	if (fh->video_fmt.width  < 48 ||	    fh->video_fmt.height < 32 ||	    fh->video_fmt.width  > vv->standard->h_max_out ||	    fh->video_fmt.height > vv->standard->v_max_out) {		DEB_D(("w (%d) / h (%d) out of bounds.\n",fh->video_fmt.width,fh->video_fmt.height));		return -EINVAL;	}	size = fh->video_fmt.sizeimage;	if (0 != buf->vb.baddr && buf->vb.bsize < size) {		DEB_D(("size mismatch.\n"));		return -EINVAL;	}		DEB_CAP(("buffer_prepare [size=%dx%d,bytes=%d,fields=%s]\n",		fh->video_fmt.width,fh->video_fmt.height,size,v4l2_field_names[fh->video_fmt.field]));	if (buf->vb.width  != fh->video_fmt.width  ||	    buf->vb.bytesperline != fh->video_fmt.bytesperline ||	    buf->vb.height != fh->video_fmt.height ||	    buf->vb.size   != size ||	    buf->vb.field  != field      ||	    buf->vb.field  != fh->video_fmt.field  ||	    buf->fmt       != &fh->video_fmt) {		saa7146_dma_free(dev,buf);	}	if (STATE_NEEDS_INIT == buf->vb.state) {		struct saa7146_format *sfmt;				buf->vb.bytesperline  = fh->video_fmt.bytesperline;		buf->vb.width  = fh->video_fmt.width;		buf->vb.height = fh->video_fmt.height;		buf->vb.size   = size;		buf->vb.field  = field;		buf->fmt       = &fh->video_fmt;		buf->vb.field  = fh->video_fmt.field;				sfmt = format_by_fourcc(dev,buf->fmt->pixelformat);					if( 0 != IS_PLANAR(sfmt->trans)) {			saa7146_pgtable_free(dev->pci, &buf->pt[0]);			saa7146_pgtable_free(dev->pci, &buf->pt[1]);			saa7146_pgtable_free(dev->pci, &buf->pt[2]);			saa7146_pgtable_alloc(dev->pci, &buf->pt[0]);			saa7146_pgtable_alloc(dev->pci, &buf->pt[1]);			saa7146_pgtable_alloc(dev->pci, &buf->pt[2]);		} else {			saa7146_pgtable_free(dev->pci, &buf->pt[0]);			saa7146_pgtable_alloc(dev->pci, &buf->pt[0]);		}				err = videobuf_iolock(dev->pci,&buf->vb, &vv->ov_fb);		if (err)			goto oops;		err = saa7146_pgtable_build(dev,buf);		if (err)			goto oops;	}	buf->vb.state = STATE_PREPARED;	buf->activate = buffer_activate;	return 0; oops:	DEB_D(("error out.\n"));	saa7146_dma_free(dev,buf);	return err;}static int buffer_setup(struct file *file, unsigned int *count, unsigned int *size){	struct saa7146_fh *fh = file->private_data;	if (0 == *count || *count > MAX_SAA7146_CAPTURE_BUFFERS)		*count = MAX_SAA7146_CAPTURE_BUFFERS;	*size = fh->video_fmt.sizeimage;	/* check if we exceed the "memory" parameter */	if( (*count * *size) > (memory*1048576) ) {		*count = (memory*1048576) / *size;	}		DEB_CAP(("%d buffers, %d bytes each.\n",*count,*size));	return 0;}static void buffer_queue(struct file *file, struct videobuf_buffer *vb){	struct saa7146_fh *fh = file->private_data;	struct saa7146_dev *dev = fh->dev;	struct saa7146_vv *vv = dev->vv_data;	struct saa7146_buf *buf = (struct saa7146_buf *)vb;		DEB_CAP(("vbuf:%p\n",vb));	saa7146_buffer_queue(fh->dev,&vv->video_q,buf);}static void buffer_release(struct file *file, struct videobuf_buffer *vb){	struct saa7146_fh *fh = file->private_data;	struct saa7146_dev *dev = fh->dev;	struct saa7146_buf *buf = (struct saa7146_buf *)vb;		DEB_CAP(("vbuf:%p\n",vb));	saa7146_dma_free(dev,buf);}static struct videobuf_queue_ops video_qops = {	.buf_setup    = buffer_setup,	.buf_prepare  = buffer_prepare,	.buf_queue    = buffer_queue,	.buf_release  = buffer_release,};/********************************************************************************//* file operations */static void video_init(struct saa7146_dev *dev, struct saa7146_vv *vv){        INIT_LIST_HEAD(&vv->video_q.queue);	init_timer(&vv->video_q.timeout);	vv->video_q.timeout.function = saa7146_buffer_timeout;	vv->video_q.timeout.data     = (unsigned long)(&vv->video_q);	vv->video_q.dev              = dev;	/* set some default values */	vv->standard = &dev->ext_vv_data->stds[0];	/* FIXME: what's this? */	vv->current_hps_source = SAA7146_HPS_SOURCE_PORT_A;	vv->current_hps_sync = SAA7146_HPS_SYNC_PORT_A;}static int video_open(struct saa7146_dev *dev, struct file *file){	struct saa7146_fh *fh = (struct saa7146_fh *)file->private_data;	struct saa7146_format *sfmt;	fh->video_fmt.width = 384;	fh->video_fmt.height = 288;	fh->video_fmt.pixelformat = V4L2_PIX_FMT_BGR24;	fh->video_fmt.bytesperline = 0;	fh->video_fmt.field = V4L2_FIELD_ANY;	sfmt = format_by_fourcc(dev,fh->video_fmt.pixelformat);	fh->video_fmt.sizeimage = (fh->video_fmt.width * fh->video_fmt.height * sfmt->depth)/8;	videobuf_queue_init(&fh->video_q, &video_qops,			    dev->pci, &dev->slock,			    V4L2_BUF_TYPE_VIDEO_CAPTURE,			    V4L2_FIELD_INTERLACED,			    sizeof(struct saa7146_buf));	init_MUTEX(&fh->video_q.lock);	return 0;}static void video_close(struct saa7146_dev *dev, struct file *file){	struct saa7146_fh *fh = (struct saa7146_fh *)file->private_data;	struct saa7146_vv *vv = dev->vv_data;	unsigned long flags;		if( 0 != vv->ov_data ) {		if( fh == vv->ov_data->fh ) {			spin_lock_irqsave(&dev->slock,flags);			saa7146_stop_preview(fh);			spin_unlock_irqrestore(&dev->slock,flags);			saa7146_res_free(fh, RESOURCE_DMA1_HPS|RESOURCE_DMA2_CLP);		}	}		if( fh == vv->streaming ) {		video_end(fh, file);			}}static void video_irq_done(struct saa7146_dev *dev, unsigned long st){	struct saa7146_vv *vv = dev->vv_data;	struct saa7146_dmaqueue *q = &vv->video_q;		spin_lock(&dev->slock);	DEB_CAP(("called.\n"));	/* only finish the buffer if we have one... */	if( NULL != q->curr ) {		saa7146_buffer_finish(dev,q,STATE_DONE);	}	saa7146_buffer_next(dev,q,0);	spin_unlock(&dev->slock);}static ssize_t video_read(struct file *file, char *data, size_t count, loff_t *ppos){	struct saa7146_fh *fh = file->private_data;	struct saa7146_dev *dev = fh->dev;	struct saa7146_vv *vv = dev->vv_data;	ssize_t ret = 0;		int restart_overlay = 0;	struct saa7146_fh *ov_fh = NULL;	DEB_EE(("called.\n"));	/* fixme: should we allow read() captures while streaming capture? */	if( 0 != vv->streaming ) {		DEB_S(("already capturing.\n"));		return -EBUSY;	}	/* stop any active overlay */	if( vv->ov_data != NULL ) {		ov_fh = vv->ov_data->fh;		saa7146_stop_preview(ov_fh);		saa7146_res_free(ov_fh, RESOURCE_DMA1_HPS|RESOURCE_DMA2_CLP);		restart_overlay = 1;	}	ret = video_begin(fh);	if( 0 != ret) {		goto out;	}	ret = videobuf_read_one(file,&fh->video_q , data, count, ppos);	video_end(fh, file);out:	/* restart overlay if it was active before */	if( 0 != restart_overlay ) {		if (0 == saa7146_res_get(ov_fh, RESOURCE_DMA1_HPS|RESOURCE_DMA2_CLP)) {			DEB_D(("cannot get overlay resources again!\n"));			BUG();		}		saa7146_start_preview(ov_fh);	}	return ret;}struct saa7146_use_ops saa7146_video_uops = {	.init = video_init,	.open = video_open,	.release = video_close,	.irq_done = video_irq_done,	.read = video_read,};

⌨️ 快捷键说明

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