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

📄 cx88-video.c

📁 Linux Kernel 2.6.9 for OMAP1710
💻 C
📖 第 1 页 / 共 5 页
字号:
		cx8800_vbi_fmt(dev, f);		return 0;	default:		return -EINVAL;	}}/* * This function is _not_ called directly, but from * video_generic_ioctl (and maybe others).  userspace * copying is done already, arg is a kernel pointer. */static int video_do_ioctl(struct inode *inode, struct file *file,			  unsigned int cmd, void *arg){	struct cx8800_fh  *fh  = file->private_data;	struct cx8800_dev *dev = fh->dev;#if 0	unsigned long flags;#endif	int err;	if (video_debug > 1)		cx88_print_ioctl(dev->name,cmd);	switch (cmd) {	case VIDIOC_QUERYCAP:	{		struct v4l2_capability *cap = arg;				memset(cap,0,sizeof(*cap));                strcpy(cap->driver, "cx8800");		strlcpy(cap->card, cx88_boards[dev->board].name,			sizeof(cap->card));		sprintf(cap->bus_info,"PCI:%s",pci_name(dev->pci));		cap->version = CX88_VERSION_CODE;		cap->capabilities =			V4L2_CAP_VIDEO_CAPTURE |			V4L2_CAP_READWRITE     |			V4L2_CAP_STREAMING     |			V4L2_CAP_VBI_CAPTURE   |#if 0			V4L2_CAP_VIDEO_OVERLAY |#endif			0;		if (UNSET != dev->tuner_type)			cap->capabilities |= V4L2_CAP_TUNER;		return 0;	}	/* ---------- tv norms ---------- */	case VIDIOC_ENUMSTD:	{		struct v4l2_standard *e = arg;		unsigned int i;		i = e->index;		if (i >= ARRAY_SIZE(tvnorms))			return -EINVAL;		err = v4l2_video_std_construct(e, tvnorms[e->index].id,					       tvnorms[e->index].name);		e->index = i;		if (err < 0)			return err;		return 0;	}	case VIDIOC_G_STD:	{		v4l2_std_id *id = arg;		*id = dev->tvnorm->id;		return 0;	}	case VIDIOC_S_STD:	{		v4l2_std_id *id = arg;		unsigned int i;		for(i = 0; i < ARRAY_SIZE(tvnorms); i++)			if (*id & tvnorms[i].id)				break;		if (i == ARRAY_SIZE(tvnorms))			return -EINVAL;		down(&dev->lock);		set_tvnorm(dev,&tvnorms[i]);		up(&dev->lock);		return 0;	}	/* ------ input switching ---------- */	case VIDIOC_ENUMINPUT:	{		static const char *iname[] = {			[ CX88_VMUX_COMPOSITE1 ] = "Composite1",			[ CX88_VMUX_COMPOSITE2 ] = "Composite2",			[ CX88_VMUX_COMPOSITE3 ] = "Composite3",			[ CX88_VMUX_COMPOSITE4 ] = "Composite4",			[ CX88_VMUX_TELEVISION ] = "Television",			[ CX88_VMUX_SVIDEO     ] = "S-Video",			[ CX88_VMUX_DEBUG      ] = "for debug only",		};		struct v4l2_input *i = arg;		unsigned int n;		n = i->index;		if (n >= 4)			return -EINVAL;		if (0 == INPUT(n)->type)			return -EINVAL;		memset(i,0,sizeof(*i));		i->index = n;		i->type  = V4L2_INPUT_TYPE_CAMERA;		strcpy(i->name,iname[INPUT(n)->type]);		if (CX88_VMUX_TELEVISION == INPUT(n)->type)			i->type = V4L2_INPUT_TYPE_TUNER;		for (n = 0; n < ARRAY_SIZE(tvnorms); n++)			i->std |= tvnorms[n].id;		return 0;	}	case VIDIOC_G_INPUT:	{		unsigned int *i = arg;		*i = dev->input;		return 0;	}	case VIDIOC_S_INPUT:	{		unsigned int *i = arg;				if (*i >= 4)			return -EINVAL;		down(&dev->lock);		video_mux(dev,*i);		up(&dev->lock);		return 0;	}	/* --- capture ioctls ---------------------------------------- */	case VIDIOC_ENUM_FMT:	{		struct v4l2_fmtdesc *f = arg;		enum v4l2_buf_type type;		unsigned int index;		index = f->index;		type  = f->type;		switch (type) {		case V4L2_BUF_TYPE_VIDEO_CAPTURE:			if (index >= ARRAY_SIZE(formats))				return -EINVAL;			memset(f,0,sizeof(*f));			f->index = index;			f->type  = type;			strlcpy(f->description,formats[index].name,sizeof(f->description));			f->pixelformat = formats[index].fourcc;			break;		default:			return -EINVAL;		}		return 0;	}	case VIDIOC_G_FMT:	{		struct v4l2_format *f = arg;		return cx8800_g_fmt(dev,fh,f);	}	case VIDIOC_S_FMT:	{		struct v4l2_format *f = arg;		return cx8800_s_fmt(dev,fh,f);	}	case VIDIOC_TRY_FMT:	{		struct v4l2_format *f = arg;		return cx8800_try_fmt(dev,fh,f);	}	/* --- controls ---------------------------------------------- */	case VIDIOC_QUERYCTRL:	{		struct v4l2_queryctrl *c = arg;		int i;		if (c->id <  V4L2_CID_BASE ||		    c->id >= V4L2_CID_LASTP1)			return -EINVAL;		for (i = 0; i < CX8800_CTLS; i++)			if (cx8800_ctls[i].v.id == c->id)				break;		if (i == CX8800_CTLS) {			*c = no_ctl;			return 0;		}		*c = cx8800_ctls[i].v;		return 0;	}	case VIDIOC_G_CTRL:		return get_control(dev,arg);	case VIDIOC_S_CTRL:		return set_control(dev,arg);			/* --- tuner ioctls ------------------------------------------ */	case VIDIOC_G_TUNER:	{		struct v4l2_tuner *t = arg;		u32 reg;				if (UNSET == dev->tuner_type)			return -EINVAL;		if (0 != t->index)			return -EINVAL;		memset(t,0,sizeof(*t));		strcpy(t->name, "Television");		t->type       = V4L2_TUNER_ANALOG_TV;		t->capability = V4L2_TUNER_CAP_NORM;		t->rangehigh  = 0xffffffffUL;		cx88_get_stereo(dev ,t);		reg = cx_read(MO_DEVICE_STATUS);                t->signal = (reg & (1<<5)) ? 0xffff : 0x0000;		return 0;	}	case VIDIOC_S_TUNER:	{		struct v4l2_tuner *t = arg;		if (UNSET == dev->tuner_type)			return -EINVAL;		if (0 != t->index)			return -EINVAL;		cx88_set_stereo(dev,t->audmode);		return 0;	}	case VIDIOC_G_FREQUENCY:	{		struct v4l2_frequency *f = arg;		if (UNSET == dev->tuner_type)			return -EINVAL;		if (f->tuner != 0)			return -EINVAL;		memset(f,0,sizeof(*f));		f->type = fh->radio ? V4L2_TUNER_RADIO : V4L2_TUNER_ANALOG_TV;		f->frequency = dev->freq;		return 0;	}	case VIDIOC_S_FREQUENCY:	{		struct v4l2_frequency *f = arg;		if (UNSET == dev->tuner_type)			return -EINVAL;		if (f->tuner != 0)			return -EINVAL;		if (0 == fh->radio && f->type != V4L2_TUNER_ANALOG_TV)			return -EINVAL;		if (1 == fh->radio && f->type != V4L2_TUNER_RADIO)			return -EINVAL;		down(&dev->lock);		dev->freq = f->frequency;#ifdef V4L2_I2C_CLIENTS		cx8800_call_i2c_clients(dev,VIDIOC_S_FREQUENCY,f);#else		cx8800_call_i2c_clients(dev,VIDIOCSFREQ,&dev->freq);#endif		up(&dev->lock);		return 0;	}	/* --- streaming capture ------------------------------------- */	case VIDIOCGMBUF:	{		struct video_mbuf *mbuf = arg;		struct videobuf_queue *q;		struct v4l2_requestbuffers req;		unsigned int i;		q = get_queue(fh);		memset(&req,0,sizeof(req));		req.type   = q->type;		req.count  = 8;		req.memory = V4L2_MEMORY_MMAP;		err = videobuf_reqbufs(file,q,&req);		if (err < 0)			return err;		memset(mbuf,0,sizeof(*mbuf));		mbuf->frames = req.count;		mbuf->size   = 0;		for (i = 0; i < mbuf->frames; i++) {			mbuf->offsets[i]  = q->bufs[i]->boff;			mbuf->size       += q->bufs[i]->bsize;		}		return 0;	}	case VIDIOC_REQBUFS:		return videobuf_reqbufs(file, get_queue(fh), arg);	case VIDIOC_QUERYBUF:		return videobuf_querybuf(get_queue(fh), arg);	case VIDIOC_QBUF:		return videobuf_qbuf(file, get_queue(fh), arg);	case VIDIOC_DQBUF:		return videobuf_dqbuf(file, get_queue(fh), arg);	case VIDIOC_STREAMON:	{		int res = get_ressource(fh);                if (!res_get(dev,fh,res))			return -EBUSY;		return videobuf_streamon(file, get_queue(fh));	}	case VIDIOC_STREAMOFF:	{		int res = get_ressource(fh);		err = videobuf_streamoff(file, get_queue(fh));		if (err < 0)			return err;		res_free(dev,fh,res);		return 0;	}	default:		return v4l_compat_translate_ioctl(inode,file,cmd,arg,						  video_do_ioctl);	}	return 0;}static int video_ioctl(struct inode *inode, struct file *file,		       unsigned int cmd, unsigned long arg){	return video_usercopy(inode, file, cmd, arg, video_do_ioctl);}/* ----------------------------------------------------------- */static int radio_do_ioctl(struct inode *inode, struct file *file,			unsigned int cmd, void *arg){	struct cx8800_fh *fh = file->private_data;	struct cx8800_dev *dev = fh->dev;		if (video_debug > 1)		cx88_print_ioctl(dev->name,cmd);	switch (cmd) {	case VIDIOC_QUERYCAP:	{		struct v4l2_capability *cap = arg;				memset(cap,0,sizeof(*cap));                strcpy(cap->driver, "cx8800");		strlcpy(cap->card, cx88_boards[dev->board].name,			sizeof(cap->card));		sprintf(cap->bus_info,"PCI:%s", pci_name(dev->pci));		cap->version = CX88_VERSION_CODE;		cap->capabilities = V4L2_CAP_TUNER;		return 0;	}	case VIDIOC_G_TUNER:	{		struct v4l2_tuner *t = arg;		if (t->index > 0)			return -EINVAL;		memset(t,0,sizeof(*t));		strcpy(t->name, "Radio");                t->rangelow  = (int)(65*16);                t->rangehigh = (int)(108*16);		#ifdef V4L2_I2C_CLIENTS		cx8800_call_i2c_clients(dev,VIDIOC_G_TUNER,t);#else		{			struct video_tuner vt;			memset(&vt,0,sizeof(vt));			cx8800_call_i2c_clients(dev,VIDIOCGTUNER,&vt);			t->signal = vt.signal;		}#endif		return 0;	}	case VIDIOC_ENUMINPUT:	{		struct v4l2_input *i = arg;				if (i->index != 0)			return -EINVAL;		strcpy(i->name,"Radio");		i->type = V4L2_INPUT_TYPE_TUNER;		return 0;	}	case VIDIOC_G_INPUT:	{		int *i = arg;		*i = 0;		return 0;	}	case VIDIOC_G_AUDIO:	{		struct v4l2_audio *a = arg;		memset(a,0,sizeof(*a));		strcpy(a->name,"Radio");		return 0;	}	case VIDIOC_G_STD:	{		v4l2_std_id *id = arg;		*id = 0;		return 0;	}	case VIDIOC_S_AUDIO:	case VIDIOC_S_TUNER:	case VIDIOC_S_INPUT:	case VIDIOC_S_STD:		return 0;	case VIDIOC_QUERYCTRL:	{		struct v4l2_queryctrl *c = arg;		int i;		if (c->id <  V4L2_CID_BASE ||		    c->id >= V4L2_CID_LASTP1)			return -EINVAL;		if (c->id == V4L2_CID_AUDIO_MUTE) {			for (i = 0; i < CX8800_CTLS; i++)				if (cx8800_ctls[i].v.id == c->id)					break;			*c = cx8800_ctls[i].v;		} else			*c = no_ctl;		return 0;	}	case VIDIOC_G_CTRL:	case VIDIOC_S_CTRL:	case VIDIOC_G_FREQUENCY:	case VIDIOC_S_FREQUENCY:		return video_do_ioctl(inode,file,cmd,arg);			default:		return v4l_compat_translate_ioctl(inode,file,cmd,arg,						  radio_do_ioctl);	}	return 0;};static int radio_ioctl(struct inode *inode, struct file *file,			unsigned int cmd, unsigned long arg){	return video_usercopy(inode, file, cmd, arg, radio_do_ioctl);};/* ----------------------------------------------------------- */static void cx8800_vid_timeout(unsigned long data){	struct cx8800_dev *dev = (struct cx8800_dev*)data;	struct cx88_dmaqueue *q = &dev->vidq;	struct cx88_buffer *buf;	unsigned long flags;	cx88_sram_channel_dump(dev, &cx88_sram_channels[SRAM_CH21]);	//cx88_risc_disasm(dev,&dev->vidq.stopper);		cx_clear(MO_VID_DMACNTRL, 0x11);	cx_clear(VID_CAPTURE_CONTROL, 0x06);	spin_lock_irqsave(&dev->slock,flags);	while (!list_empty(&q->active)) {		buf = list_entry(q->active.next, struct cx88_buffer, vb.queue);		list_del(&buf->vb.queue);		buf->vb.state = STATE_ERROR;		wake_up(&buf->vb.done);		printk("%s: [%p/%d] timeout - dma=0x%08lx\n", dev->name,		       buf, buf->vb.i, (unsigned long)buf->risc.dma);	}	restart_video_queue(dev,q);	spin_unlock_irqrestore(&dev->slock,flags);}static void cx8800_wakeup(struct cx8800_dev *dev,			  struct cx88_dmaqueue *q, u32 count){	struct cx88_buffer *buf;	for (;;) {		if (list_empty(&q->active))			break;		buf = list_entry(q->active.next,				 struct cx88_buffer, vb.queue);		if (buf->count > count)			break;		do_gettimeofday(&buf->vb.ts);		dprintk(2,"[%p/%d] wakeup reg=%d buf=%d\n",buf,buf->vb.i,			count, buf->count);		buf->vb.state = STATE_DONE;		list_del(&buf->vb.queue);		wake_up(&buf->vb.done);	}	if (list_empty(&q->active)) {		del_timer(&q->timeout);	} else {		mod_timer(&q->timeout, jiffies+BUFFER_TIMEOUT);	}

⌨️ 快捷键说明

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