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

📄 cx88-video.c

📁 h内核
💻 C
📖 第 1 页 / 共 4 页
字号:
			c = &cx8800_ctls[i];	if (NULL == c)		return -EINVAL;	if (ctl->value < c->v.minimum)		return -ERANGE;	if (ctl->value > c->v.maximum)		return -ERANGE;	switch (ctl->id) {	case V4L2_CID_AUDIO_BALANCE:		value = (ctl->value < 0x40) ? (0x40 - ctl->value) : ctl->value;		break;	case V4L2_CID_AUDIO_VOLUME:		value = 0x3f - (ctl->value & 0x3f);		break;	case V4L2_CID_SATURATION:		/* special v_sat handling */		v_sat_value = ctl->value - (0x7f - 0x5a);		if (v_sat_value > 0xff)			v_sat_value = 0xff;		if (v_sat_value < 0x00)			v_sat_value = 0x00;		cx_andor(MO_UV_SATURATION, 0xff00, v_sat_value << 8);		/* fall through to default route for u_sat */	default:		value = ((ctl->value - c->off) << c->shift) & c->mask;		break;	}	dprintk(1,"set_control id=0x%X reg=0x%x val=0x%x%s\n",		ctl->id, c->reg, value, c->sreg ? " [shadowed]" : "");	if (c->sreg) {		cx_sandor(c->sreg, c->reg, c->mask, value);	} else {		cx_andor(c->reg, c->mask, value);	}	return 0;}static void init_controls(struct cx8800_dev *dev){	static struct v4l2_control mute = {		.id    = V4L2_CID_AUDIO_MUTE,		.value = 1,	};	static struct v4l2_control volume = {		.id    = V4L2_CID_AUDIO_VOLUME,		.value = 0x3f,	};	set_control(dev,&mute);	set_control(dev,&volume);}/* ------------------------------------------------------------------ */static int cx8800_g_fmt(struct cx8800_dev *dev, struct cx8800_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->vidq.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_VBI_CAPTURE:		cx8800_vbi_fmt(dev, f);		return 0;	default:		return -EINVAL;	}}static int cx8800_try_fmt(struct cx8800_dev *dev, struct cx8800_fh *fh,			  struct v4l2_format *f){	switch (f->type) {	case V4L2_BUF_TYPE_VIDEO_CAPTURE:	{		struct cx8800_fmt *fmt;		enum v4l2_field field;		unsigned int maxw, maxh;		fmt = format_by_fourcc(f->fmt.pix.pixelformat);		if (NULL == fmt)			return -EINVAL;		field = f->fmt.pix.field;		maxw  = norm_maxw(dev->core->tvnorm);		maxh  = norm_maxh(dev->core->tvnorm);		if (V4L2_FIELD_ANY == field) {			field = (f->fmt.pix.height > maxh/2)				? V4L2_FIELD_INTERLACED				: V4L2_FIELD_BOTTOM;		}		switch (field) {		case V4L2_FIELD_TOP:		case V4L2_FIELD_BOTTOM:			maxh = maxh / 2;			break;		case V4L2_FIELD_INTERLACED:			break;		default:			return -EINVAL;		}		f->fmt.pix.field = field;		if (f->fmt.pix.height < 32)			f->fmt.pix.height = 32;		if (f->fmt.pix.height > maxh)			f->fmt.pix.height = maxh;		if (f->fmt.pix.width < 48)			f->fmt.pix.width = 48;		if (f->fmt.pix.width > maxw)			f->fmt.pix.width = maxw;		f->fmt.pix.width &= ~0x03;		f->fmt.pix.bytesperline =			(f->fmt.pix.width * fmt->depth) >> 3;		f->fmt.pix.sizeimage =			f->fmt.pix.height * f->fmt.pix.bytesperline;		return 0;	}	case V4L2_BUF_TYPE_VBI_CAPTURE:		cx8800_vbi_fmt(dev, f);		return 0;	default:		return -EINVAL;	}}static int cx8800_s_fmt(struct cx8800_dev *dev, struct cx8800_fh *fh,			struct v4l2_format *f){	int err;	switch (f->type) {	case V4L2_BUF_TYPE_VIDEO_CAPTURE:		err = cx8800_try_fmt(dev,fh,f);		if (0 != err)			return err;		fh->fmt        = format_by_fourcc(f->fmt.pix.pixelformat);		fh->width      = f->fmt.pix.width;		fh->height     = f->fmt.pix.height;		fh->vidq.field = f->fmt.pix.field;		return 0;	case V4L2_BUF_TYPE_VBI_CAPTURE:		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;	struct cx88_core  *core = dev->core;#if 0	unsigned long flags;#endif	int err;	if (video_debug > 1)		cx88_print_ioctl(core->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[core->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 != core->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 = core->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);		cx88_set_tvnorm(dev->core,&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_SVIDEO     ] = "S-Video",			[ CX88_VMUX_TELEVISION ] = "Television",			[ CX88_VMUX_CABLE      ] = "Cable TV",			[ CX88_VMUX_DVB        ] = "DVB",			[ 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) ||		    (CX88_VMUX_CABLE      == 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->core->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;	}#if 0	/* needs review */	case VIDIOC_G_AUDIO:	{		struct v4l2_audio *a = arg;		unsigned int n = a->index;		memset(a,0,sizeof(*a));		a->index = n;		switch (n) {		case 0:			if ((CX88_VMUX_TELEVISION == INPUT(n)->type)			    || (CX88_VMUX_CABLE == INPUT(n)->type)) {				strcpy(a->name,"Television");				// FIXME figure out if stereo received and set V4L2_AUDCAP_STEREO.				return 0;			}			break;		case 1:			if (CX88_BOARD_DVICO_FUSIONHDTV_3_GOLD == core->board) {				strcpy(a->name,"Line In");				a->capability = V4L2_AUDCAP_STEREO;				return 0;			}			break;		}		// Audio input not available.		return -EINVAL;	}#endif	/* --- 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 == core->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(core ,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 == core->tuner_type)			return -EINVAL;		if (0 != t->index)			return -EINVAL;		cx88_set_stereo(core, t->audmode);		return 0;	}	case VIDIOC_G_FREQUENCY:	{		struct v4l2_frequency *f = arg;		if (UNSET == core->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 == core->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		cx88_call_i2c_clients(dev->core,VIDIOC_S_FREQUENCY,f);#else		cx88_call_i2c_clients(dev->core,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(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(get_queue(fh), arg);	case VIDIOC_QUERYBUF:		return videobuf_querybuf(get_queue(fh), arg);	case VIDIOC_QBUF:		return videobuf_qbuf(get_queue(fh), arg);	case VIDIOC_DQBUF:		return videobuf_dqbuf(get_queue(fh), arg,				      file->f_flags & O_NONBLOCK);	case VIDIOC_STREAMON:	{		int res = get_ressource(fh);                if (!res_get(dev,fh,res))			return -EBUSY;		return videobuf_streamon(get_queue(fh));	}	case VIDIOC_STREAMOFF:	{		int res = get_ressource(fh);		err = videobuf_streamoff(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;	struct cx88_core  *core = dev->core;	if (video_debug > 1)		cx88_print_ioctl(core->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[core->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);

⌨️ 快捷键说明

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