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

📄 saa7134-video.c

📁 linux-2.6.15.6
💻 C
📖 第 1 页 / 共 5 页
字号:
		return -EINVAL;	size = (fh->width * fh->height * fh->fmt->depth) >> 3;	if (0 != buf->vb.baddr  &&  buf->vb.bsize < size)		return -EINVAL;	dprintk("buffer_prepare [%d,size=%dx%d,bytes=%d,fields=%s,%s]\n",		vb->i,fh->width,fh->height,size,v4l2_field_names[field],		fh->fmt->name);	if (buf->vb.width  != fh->width  ||	    buf->vb.height != fh->height ||	    buf->vb.size   != size       ||	    buf->vb.field  != field      ||	    buf->fmt       != fh->fmt) {		saa7134_dma_free(dev,buf);	}	if (STATE_NEEDS_INIT == buf->vb.state) {		buf->vb.width  = fh->width;		buf->vb.height = fh->height;		buf->vb.size   = size;		buf->vb.field  = field;		buf->fmt       = fh->fmt;		buf->pt        = &fh->pt_cap;		err = videobuf_iolock(dev->pci,&buf->vb,&dev->ovbuf);		if (err)			goto oops;		err = saa7134_pgtable_build(dev->pci,buf->pt,					    buf->vb.dma.sglist,					    buf->vb.dma.sglen,					    saa7134_buffer_startpage(buf));		if (err)			goto oops;	}	buf->vb.state = STATE_PREPARED;	buf->activate = buffer_activate;	return 0; oops:	saa7134_dma_free(dev,buf);	return err;}static intbuffer_setup(struct videobuf_queue *q, unsigned int *count, unsigned int *size){	struct saa7134_fh *fh = q->priv_data;	*size = fh->fmt->depth * fh->width * fh->height >> 3;	if (0 == *count)		*count = gbuffers;	*count = saa7134_buffer_count(*size,*count);	return 0;}static void buffer_queue(struct videobuf_queue *q, struct videobuf_buffer *vb){	struct saa7134_fh *fh = q->priv_data;	struct saa7134_buf *buf = container_of(vb,struct saa7134_buf,vb);	saa7134_buffer_queue(fh->dev,&fh->dev->video_q,buf);}static void buffer_release(struct videobuf_queue *q, struct videobuf_buffer *vb){	struct saa7134_fh *fh = q->priv_data;	struct saa7134_buf *buf = container_of(vb,struct saa7134_buf,vb);	saa7134_dma_free(fh->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,};/* ------------------------------------------------------------------ */static int get_control(struct saa7134_dev *dev, struct v4l2_control *c){	const struct v4l2_queryctrl* ctrl;	ctrl = ctrl_by_id(c->id);	if (NULL == ctrl)		return -EINVAL;	switch (c->id) {	case V4L2_CID_BRIGHTNESS:		c->value = dev->ctl_bright;		break;	case V4L2_CID_HUE:		c->value = dev->ctl_hue;		break;	case V4L2_CID_CONTRAST:		c->value = dev->ctl_contrast;		break;	case V4L2_CID_SATURATION:		c->value = dev->ctl_saturation;		break;	case V4L2_CID_AUDIO_MUTE:		c->value = dev->ctl_mute;		break;	case V4L2_CID_AUDIO_VOLUME:		c->value = dev->ctl_volume;		break;	case V4L2_CID_PRIVATE_INVERT:		c->value = dev->ctl_invert;		break;	case V4L2_CID_HFLIP:		c->value = dev->ctl_mirror;		break;	case V4L2_CID_PRIVATE_Y_EVEN:		c->value = dev->ctl_y_even;		break;	case V4L2_CID_PRIVATE_Y_ODD:		c->value = dev->ctl_y_odd;		break;	case V4L2_CID_PRIVATE_AUTOMUTE:		c->value = dev->ctl_automute;		break;	default:		return -EINVAL;	}	return 0;}static int set_control(struct saa7134_dev *dev, struct saa7134_fh *fh,		       struct v4l2_control *c){	const struct v4l2_queryctrl* ctrl;	unsigned long flags;	int restart_overlay = 0;	ctrl = ctrl_by_id(c->id);	if (NULL == ctrl)		return -EINVAL;	dprintk("set_control name=%s val=%d\n",ctrl->name,c->value);	switch (ctrl->type) {	case V4L2_CTRL_TYPE_BOOLEAN:	case V4L2_CTRL_TYPE_MENU:	case V4L2_CTRL_TYPE_INTEGER:		if (c->value < ctrl->minimum)			c->value = ctrl->minimum;		if (c->value > ctrl->maximum)			c->value = ctrl->maximum;		break;	default:		/* nothing */;	};	switch (c->id) {	case V4L2_CID_BRIGHTNESS:		dev->ctl_bright = c->value;		saa_writeb(SAA7134_DEC_LUMA_BRIGHT, dev->ctl_bright);		break;	case V4L2_CID_HUE:		dev->ctl_hue = c->value;		saa_writeb(SAA7134_DEC_CHROMA_HUE, dev->ctl_hue);		break;	case V4L2_CID_CONTRAST:		dev->ctl_contrast = c->value;		saa_writeb(SAA7134_DEC_LUMA_CONTRAST,			   dev->ctl_invert ? -dev->ctl_contrast : dev->ctl_contrast);		break;	case V4L2_CID_SATURATION:		dev->ctl_saturation = c->value;		saa_writeb(SAA7134_DEC_CHROMA_SATURATION,			   dev->ctl_invert ? -dev->ctl_saturation : dev->ctl_saturation);		break;	case V4L2_CID_AUDIO_MUTE:		dev->ctl_mute = c->value;		saa7134_tvaudio_setmute(dev);		break;	case V4L2_CID_AUDIO_VOLUME:		dev->ctl_volume = c->value;		saa7134_tvaudio_setvolume(dev,dev->ctl_volume);		break;	case V4L2_CID_PRIVATE_INVERT:		dev->ctl_invert = c->value;		saa_writeb(SAA7134_DEC_LUMA_CONTRAST,			   dev->ctl_invert ? -dev->ctl_contrast : dev->ctl_contrast);		saa_writeb(SAA7134_DEC_CHROMA_SATURATION,			   dev->ctl_invert ? -dev->ctl_saturation : dev->ctl_saturation);		break;	case V4L2_CID_HFLIP:		dev->ctl_mirror = c->value;		restart_overlay = 1;		break;	case V4L2_CID_PRIVATE_Y_EVEN:		dev->ctl_y_even = c->value;		restart_overlay = 1;		break;	case V4L2_CID_PRIVATE_Y_ODD:		dev->ctl_y_odd = c->value;		restart_overlay = 1;		break;	case V4L2_CID_PRIVATE_AUTOMUTE:		dev->ctl_automute = c->value;		if (dev->tda9887_conf) {			if (dev->ctl_automute)				dev->tda9887_conf |= TDA9887_AUTOMUTE;			else				dev->tda9887_conf &= ~TDA9887_AUTOMUTE;			saa7134_i2c_call_clients(dev, TDA9887_SET_CONFIG,						 &dev->tda9887_conf);		}		break;	default:		return -EINVAL;	}	if (restart_overlay && fh && res_check(fh, RESOURCE_OVERLAY)) {		spin_lock_irqsave(&dev->slock,flags);		stop_preview(dev,fh);		start_preview(dev,fh);		spin_unlock_irqrestore(&dev->slock,flags);	}	return 0;}/* ------------------------------------------------------------------ */static struct videobuf_queue* saa7134_queue(struct saa7134_fh *fh){	struct videobuf_queue* q = NULL;	switch (fh->type) {	case V4L2_BUF_TYPE_VIDEO_CAPTURE:		q = &fh->cap;		break;	case V4L2_BUF_TYPE_VBI_CAPTURE:		q = &fh->vbi;		break;	default:		BUG();	}	return q;}static int saa7134_resource(struct saa7134_fh *fh){	int res = 0;	switch (fh->type) {	case V4L2_BUF_TYPE_VIDEO_CAPTURE:		res = RESOURCE_VIDEO;		break;	case V4L2_BUF_TYPE_VBI_CAPTURE:		res = RESOURCE_VBI;		break;	default:		BUG();	}	return res;}static int video_open(struct inode *inode, struct file *file){	int minor = iminor(inode);	struct saa7134_dev *h,*dev = NULL;	struct saa7134_fh *fh;	struct list_head *list;	enum v4l2_buf_type type = V4L2_BUF_TYPE_VIDEO_CAPTURE;	int radio = 0;	list_for_each(list,&saa7134_devlist) {		h = list_entry(list, struct saa7134_dev, devlist);		if (h->video_dev && (h->video_dev->minor == minor))			dev = h;		if (h->radio_dev && (h->radio_dev->minor == minor)) {			radio = 1;			dev = h;		}		if (h->vbi_dev && (h->vbi_dev->minor == minor)) {			type = V4L2_BUF_TYPE_VBI_CAPTURE;			dev = h;		}	}	if (NULL == dev)		return -ENODEV;	dprintk("open minor=%d radio=%d type=%s\n",minor,radio,		v4l2_type_names[type]);	/* allocate + initialize per filehandle data */	fh = kmalloc(sizeof(*fh),GFP_KERNEL);	if (NULL == fh)		return -ENOMEM;	memset(fh,0,sizeof(*fh));	file->private_data = fh;	fh->dev      = dev;	fh->radio    = radio;	fh->type     = type;	fh->fmt      = format_by_fourcc(V4L2_PIX_FMT_BGR24);	fh->width    = 720;	fh->height   = 576;	v4l2_prio_open(&dev->prio,&fh->prio);	videobuf_queue_init(&fh->cap, &video_qops,			    dev->pci, &dev->slock,			    V4L2_BUF_TYPE_VIDEO_CAPTURE,			    V4L2_FIELD_INTERLACED,			    sizeof(struct saa7134_buf),			    fh);	videobuf_queue_init(&fh->vbi, &saa7134_vbi_qops,			    dev->pci, &dev->slock,			    V4L2_BUF_TYPE_VBI_CAPTURE,			    V4L2_FIELD_SEQ_TB,			    sizeof(struct saa7134_buf),			    fh);	saa7134_pgtable_alloc(dev->pci,&fh->pt_cap);	saa7134_pgtable_alloc(dev->pci,&fh->pt_vbi);	if (fh->radio) {		/* switch to radio mode */		saa7134_tvaudio_setinput(dev,&card(dev).radio);		saa7134_i2c_call_clients(dev,AUDC_SET_RADIO, NULL);	} else {		/* switch to video/vbi mode */		video_mux(dev,dev->ctl_input);	}	return 0;}static ssize_tvideo_read(struct file *file, char __user *data, size_t count, loff_t *ppos){	struct saa7134_fh *fh = file->private_data;	switch (fh->type) {	case V4L2_BUF_TYPE_VIDEO_CAPTURE:		if (res_locked(fh->dev,RESOURCE_VIDEO))			return -EBUSY;		return videobuf_read_one(saa7134_queue(fh),					 data, count, ppos,					 file->f_flags & O_NONBLOCK);	case V4L2_BUF_TYPE_VBI_CAPTURE:		if (!res_get(fh->dev,fh,RESOURCE_VBI))			return -EBUSY;		return videobuf_read_stream(saa7134_queue(fh),					    data, count, ppos, 1,					    file->f_flags & O_NONBLOCK);		break;	default:		BUG();		return 0;	}}static unsigned intvideo_poll(struct file *file, struct poll_table_struct *wait){	struct saa7134_fh *fh = file->private_data;	struct videobuf_buffer *buf = NULL;	if (V4L2_BUF_TYPE_VBI_CAPTURE == fh->type)		return videobuf_poll_stream(file, &fh->vbi, wait);	if (res_check(fh,RESOURCE_VIDEO)) {		if (!list_empty(&fh->cap.stream))			buf = list_entry(fh->cap.stream.next, struct videobuf_buffer, stream);	} else {		down(&fh->cap.lock);		if (UNSET == fh->cap.read_off) {			/* need to capture a new frame */			if (res_locked(fh->dev,RESOURCE_VIDEO)) {				up(&fh->cap.lock);				return POLLERR;			}			if (0 != fh->cap.ops->buf_prepare(&fh->cap,fh->cap.read_buf,fh->cap.field)) {				up(&fh->cap.lock);				return POLLERR;			}			fh->cap.ops->buf_queue(&fh->cap,fh->cap.read_buf);			fh->cap.read_off = 0;		}		up(&fh->cap.lock);		buf = fh->cap.read_buf;	}	if (!buf)		return POLLERR;	poll_wait(file, &buf->done, wait);	if (buf->state == STATE_DONE ||	    buf->state == STATE_ERROR)		return POLLIN|POLLRDNORM;	return 0;}static int video_release(struct inode *inode, struct file *file){	struct saa7134_fh  *fh  = file->private_data;	struct saa7134_dev *dev = fh->dev;	unsigned long flags;	/* turn off overlay */	if (res_check(fh, RESOURCE_OVERLAY)) {		spin_lock_irqsave(&dev->slock,flags);		stop_preview(dev,fh);		spin_unlock_irqrestore(&dev->slock,flags);		res_free(dev,fh,RESOURCE_OVERLAY);	}	/* stop video capture */	if (res_check(fh, RESOURCE_VIDEO)) {		videobuf_streamoff(&fh->cap);		res_free(dev,fh,RESOURCE_VIDEO);	}	if (fh->cap.read_buf) {		buffer_release(&fh->cap,fh->cap.read_buf);		kfree(fh->cap.read_buf);	}	/* stop vbi capture */	if (res_check(fh, RESOURCE_VBI)) {		if (fh->vbi.streaming)			videobuf_streamoff(&fh->vbi);		if (fh->vbi.reading)			videobuf_read_stop(&fh->vbi);		res_free(dev,fh,RESOURCE_VBI);	}	/* ts-capture will not work in planar mode, so turn it off Hac: 04.05*/	saa_andorb(SAA7134_OFMT_VIDEO_A, 0x1f, 0);	saa_andorb(SAA7134_OFMT_VIDEO_B, 0x1f, 0);	saa_andorb(SAA7134_OFMT_DATA_A, 0x1f, 0);	saa_andorb(SAA7134_OFMT_DATA_B, 0x1f, 0);	saa7134_i2c_call_clients(dev, TUNER_SET_STANDBY, NULL);	/* free stuff */	videobuf_mmap_free(&fh->cap);	videobuf_mmap_free(&fh->vbi);	saa7134_pgtable_free(dev->pci,&fh->pt_cap);	saa7134_pgtable_free(dev->pci,&fh->pt_vbi);	v4l2_prio_close(&dev->prio,&fh->prio);	file->private_data = NULL;	kfree(fh);	return 0;}static intvideo_mmap(struct file *file, struct vm_area_struct * vma){	struct saa7134_fh *fh = file->private_data;	return videobuf_mmap_mapper(saa7134_queue(fh), vma);}/* ------------------------------------------------------------------ */static void saa7134_vbi_fmt(struct saa7134_dev *dev, struct v4l2_format *f){	struct saa7134_tvnorm *norm = dev->tvnorm;	f->fmt.vbi.sampling_rate = 6750000 * 4;	f->fmt.vbi.samples_per_line = 2048 /* VBI_LINE_LENGTH */;	f->fmt.vbi.sample_format = V4L2_PIX_FMT_GREY;	f->fmt.vbi.offset = 64 * 4;	f->fmt.vbi.start[0] = norm->vbi_v_start_0;	f->fmt.vbi.count[0] = norm->vbi_v_stop_0 - norm->vbi_v_start_0 +1;	f->fmt.vbi.start[1] = norm->vbi_v_start_1;	f->fmt.vbi.count[1] = f->fmt.vbi.count[0];	f->fmt.vbi.flags = 0; /* VBI_UNSYNC VBI_INTERLACED */}static int saa7134_g_fmt(struct saa7134_dev *dev, struct saa7134_fh *fh,			 struct v4l2_format *f){	switch (f->type) {	case V4L2_BUF_TYPE_VIDEO_CAPTURE:		memset(&f->fmt.pix,0,sizeof(f->fmt.pix));		f->fmt.pix.width        = fh->width;		f->fmt.pix.height       = fh->height;		f->fmt.pix.field        = fh->cap.field;		f->fmt.pix.pixelformat  = fh->fmt->fourcc;		f->fmt.pix.bytesperline =			(f->fmt.pix.width * fh->fmt->depth) >> 3;		f->fmt.pix.sizeimage =			f->fmt.pix.height * f->fmt.pix.bytesperline;		return 0;	case V4L2_BUF_TYPE_VIDEO_OVERLAY:		f->fmt.win = fh->win;		return 0;	case V4L2_BUF_TYPE_VBI_CAPTURE:		saa7134_vbi_fmt(dev,f);		return 0;	default:		return -EINVAL;	}

⌨️ 快捷键说明

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