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

📄 saa7134-video.c

📁 trident tm5600的linux驱动
💻 C
📖 第 1 页 / 共 5 页
字号:
	saa7134_set_dmabits(dev);	mod_timer(&dev->video_q.timeout, jiffies+BUFFER_TIMEOUT);	return 0;}static int buffer_prepare(struct videobuf_queue *q,			  struct videobuf_buffer *vb,			  enum v4l2_field field){	struct saa7134_fh *fh = q->priv_data;	struct saa7134_dev *dev = fh->dev;	struct saa7134_buf *buf = container_of(vb,struct saa7134_buf,vb);	unsigned int size;	int err;	/* sanity checks */	if (NULL == fh->fmt)		return -EINVAL;	if (fh->width    < 48 ||	    fh->height   < 32 ||	    fh->width/4  > dev->crop_current.width  ||	    fh->height/4 > dev->crop_current.height ||	    fh->width    > dev->crop_bounds.width  ||	    fh->height   > dev->crop_bounds.height)		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(q,buf);	}	if (VIDEOBUF_NEEDS_INIT == buf->vb.state) {		struct videobuf_dmabuf *dma=videobuf_to_dma(&buf->vb);		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(q,&buf->vb,&dev->ovbuf);		if (err)			goto oops;		err = saa7134_pgtable_build(dev->pci,buf->pt,					    dma->sglist,					    dma->sglen,					    saa7134_buffer_startpage(buf));		if (err)			goto oops;	}	buf->vb.state = VIDEOBUF_PREPARED;	buf->activate = buffer_activate;	return 0; oops:	saa7134_dma_free(q,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_buf *buf = container_of(vb,struct saa7134_buf,vb);	saa7134_dma_free(q,buf);}static struct videobuf_queue_ops video_qops = {	.buf_setup    = buffer_setup,	.buf_prepare  = buffer_prepare,	.buf_queue    = buffer_queue,	.buf_release  = buffer_release,};/* ------------------------------------------------------------------ */int saa7134_g_ctrl_internal(struct saa7134_dev *dev, struct saa7134_fh *fh, 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;}EXPORT_SYMBOL_GPL(saa7134_g_ctrl_internal);static int saa7134_g_ctrl(struct file *file, void *priv, struct v4l2_control *c){	struct saa7134_fh *fh = priv;	return saa7134_g_ctrl_internal(fh->dev, fh, c);}int saa7134_s_ctrl_internal(struct saa7134_dev *dev,  struct saa7134_fh *fh, struct v4l2_control *c){	const struct v4l2_queryctrl* ctrl;	unsigned long flags;	int restart_overlay = 0;	int err;	/* When called from the empress code fh == NULL.	   That needs to be fixed somehow, but for now this is	   good enough. */	if (fh) {		err = v4l2_prio_check(&dev->prio, &fh->prio);		if (0 != err)			return err;	}	err = -EINVAL;	mutex_lock(&dev->lock);	ctrl = ctrl_by_id(c->id);	if (NULL == ctrl)		goto error;	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:	{		struct v4l2_priv_tun_config tda9887_cfg;		tda9887_cfg.tuner = TUNER_TDA9887;		tda9887_cfg.priv = &dev->tda9887_conf;		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, TUNER_SET_CONFIG,						 &tda9887_cfg);		}		break;	}	default:		goto error;	}	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);	}	err = 0;error:	mutex_unlock(&dev->lock);	return err;}EXPORT_SYMBOL_GPL(saa7134_s_ctrl_internal);static int saa7134_s_ctrl(struct file *file, void *f, struct v4l2_control *c){	struct saa7134_fh *fh = f;	return saa7134_s_ctrl_internal(fh->dev, fh, c);}/* ------------------------------------------------------------------ */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){	if (fh->type == V4L2_BUF_TYPE_VIDEO_CAPTURE)		return RESOURCE_VIDEO;	if (fh->type == V4L2_BUF_TYPE_VBI_CAPTURE)		return RESOURCE_VBI;	BUG();	return 0;}static int video_open(struct inode *inode, struct file *file){	int minor = iminor(inode);	struct saa7134_dev *dev;	struct saa7134_fh *fh;	enum v4l2_buf_type type = V4L2_BUF_TYPE_VIDEO_CAPTURE;	int radio = 0;	lock_kernel();	list_for_each_entry(dev, &saa7134_devlist, devlist) {		if (dev->video_dev && (dev->video_dev->minor == minor))			goto found;		if (dev->radio_dev && (dev->radio_dev->minor == minor)) {			radio = 1;			goto found;		}		if (dev->vbi_dev && (dev->vbi_dev->minor == minor)) {			type = V4L2_BUF_TYPE_VBI_CAPTURE;			goto found;		}	}	unlock_kernel();	return -ENODEV; found:	dprintk("open minor=%d radio=%d type=%s\n",minor,radio,		v4l2_type_names[type]);	/* allocate + initialize per filehandle data */	fh = kzalloc(sizeof(*fh),GFP_KERNEL);	if (NULL == fh) {		unlock_kernel();		return -ENOMEM;	}	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_sg_init(&fh->cap, &video_qops,			    &dev->pci->dev, &dev->slock,			    V4L2_BUF_TYPE_VIDEO_CAPTURE,			    V4L2_FIELD_INTERLACED,			    sizeof(struct saa7134_buf),			    fh);	videobuf_queue_sg_init(&fh->vbi, &saa7134_vbi_qops,			    &dev->pci->dev, &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);	}	unlock_kernel();	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 {		mutex_lock(&fh->cap.vb_lock);		if (UNSET == fh->cap.read_off) {			/* need to capture a new frame */			if (res_locked(fh->dev,RESOURCE_VIDEO))				goto err;			if (0 != fh->cap.ops->buf_prepare(&fh->cap,fh->cap.read_buf,fh->cap.field))				goto err;			fh->cap.ops->buf_queue(&fh->cap,fh->cap.read_buf);			fh->cap.read_off = 0;		}		mutex_unlock(&fh->cap.vb_lock);		buf = fh->cap.read_buf;	}	if (!buf)		return POLLERR;	poll_wait(file, &buf->done, wait);	if (buf->state == VIDEOBUF_DONE ||	    buf->state == VIDEOBUF_ERROR)		return POLLIN|POLLRDNORM;	return 0;err:	mutex_unlock(&fh->cap.vb_lock);	return POLLERR;}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)) {		videobuf_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 int video_mmap(struct file *file, struct vm_area_struct * vma){	struct saa7134_fh *fh = file->private_data;

⌨️ 快捷键说明

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