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

📄 em28xx-video.c

📁 trident tm5600的linux驱动
💻 C
📖 第 1 页 / 共 4 页
字号:
	dev->stream_on = 1;	fh->stream_on  = 1;	mutex_unlock(&dev->lock);	return rc;}static int res_check(struct em28xx_fh *fh){	return (fh->stream_on);}static void res_free(struct em28xx_fh *fh){	struct em28xx    *dev = fh->dev;	mutex_lock(&dev->lock);	fh->stream_on = 0;	dev->stream_on = 0;	mutex_unlock(&dev->lock);}/* * em28xx_get_ctrl() * return the current saturation, brightness or contrast, mute state */static int em28xx_get_ctrl(struct em28xx *dev, struct v4l2_control *ctrl){	switch (ctrl->id) {	case V4L2_CID_AUDIO_MUTE:		ctrl->value = dev->mute;		return 0;	case V4L2_CID_AUDIO_VOLUME:		ctrl->value = dev->volume;		return 0;	default:		return -EINVAL;	}}/* * em28xx_set_ctrl() * mute or set new saturation, brightness or contrast */static int em28xx_set_ctrl(struct em28xx *dev, const struct v4l2_control *ctrl){	switch (ctrl->id) {	case V4L2_CID_AUDIO_MUTE:		if (ctrl->value != dev->mute) {			dev->mute = ctrl->value;			return em28xx_audio_analog_set(dev);		}		return 0;	case V4L2_CID_AUDIO_VOLUME:		dev->volume = ctrl->value;		return em28xx_audio_analog_set(dev);	default:		return -EINVAL;	}}static int check_dev(struct em28xx *dev){	if (dev->state & DEV_DISCONNECTED) {		em28xx_errdev("v4l2 ioctl: device not present\n");		return -ENODEV;	}	if (dev->state & DEV_MISCONFIGURED) {		em28xx_errdev("v4l2 ioctl: device is misconfigured; "			      "close and open it again\n");		return -EIO;	}	return 0;}static void get_scale(struct em28xx *dev,			unsigned int width, unsigned int height,			unsigned int *hscale, unsigned int *vscale){	unsigned int          maxw   = norm_maxw(dev);	unsigned int          maxh   = norm_maxh(dev);	*hscale = (((unsigned long)maxw) << 12) / width - 4096L;	if (*hscale >= 0x4000)		*hscale = 0x3fff;	*vscale = (((unsigned long)maxh) << 12) / height - 4096L;	if (*vscale >= 0x4000)		*vscale = 0x3fff;}/* ------------------------------------------------------------------	IOCTL vidioc handling   ------------------------------------------------------------------*/static int vidioc_g_fmt_vid_cap(struct file *file, void *priv,					struct v4l2_format *f){	struct em28xx_fh      *fh  = priv;	struct em28xx         *dev = fh->dev;	mutex_lock(&dev->lock);	f->fmt.pix.width = dev->width;	f->fmt.pix.height = dev->height;	f->fmt.pix.pixelformat = V4L2_PIX_FMT_YUYV;	f->fmt.pix.bytesperline = dev->width * 2;	f->fmt.pix.sizeimage = f->fmt.pix.bytesperline  * dev->height;	f->fmt.pix.colorspace = V4L2_COLORSPACE_SMPTE170M;	/* FIXME: TOP? NONE? BOTTOM? ALTENATE? */	f->fmt.pix.field = dev->interlaced ?			   V4L2_FIELD_INTERLACED : V4L2_FIELD_TOP;	mutex_unlock(&dev->lock);	return 0;}static int vidioc_try_fmt_vid_cap(struct file *file, void *priv,			struct v4l2_format *f){	struct em28xx_fh      *fh    = priv;	struct em28xx         *dev   = fh->dev;	int                   width  = f->fmt.pix.width;	int                   height = f->fmt.pix.height;	unsigned int          maxw   = norm_maxw(dev);	unsigned int          maxh   = norm_maxh(dev);	unsigned int          hscale, vscale;	/* width must even because of the YUYV format	   height must be even because of interlacing */	height &= 0xfffe;	width &= 0xfffe;	if (height < 32)		height = 32;	if (height > maxh)		height = maxh;	if (width < 48)		width = 48;	if (width > maxw)		width = maxw;	mutex_lock(&dev->lock);	if (dev->is_em2800) {		/* the em2800 can only scale down to 50% */		if (height % (maxh / 2))			height = maxh;		if (width % (maxw / 2))			width = maxw;		/* according to empiatech support */		/* the MaxPacketSize is to small to support */		/* framesizes larger than 640x480 @ 30 fps */		/* or 640x576 @ 25 fps. As this would cut */		/* of a part of the image we prefer */		/* 360x576 or 360x480 for now */		if (width == maxw && height == maxh)			width /= 2;	}	get_scale(dev, width, height, &hscale, &vscale);	width = (((unsigned long)maxw) << 12) / (hscale + 4096L);	height = (((unsigned long)maxh) << 12) / (vscale + 4096L);	f->fmt.pix.width = width;	f->fmt.pix.height = height;	f->fmt.pix.pixelformat = V4L2_PIX_FMT_YUYV;	f->fmt.pix.bytesperline = width * 2;	f->fmt.pix.sizeimage = width * 2 * height;	f->fmt.pix.colorspace = V4L2_COLORSPACE_SMPTE170M;	f->fmt.pix.field = V4L2_FIELD_INTERLACED;	mutex_unlock(&dev->lock);	return 0;}static int vidioc_s_fmt_vid_cap(struct file *file, void *priv,			struct v4l2_format *f){	struct em28xx_fh      *fh  = priv;	struct em28xx         *dev = fh->dev;	int                   rc;	rc = check_dev(dev);	if (rc < 0)		return rc;	vidioc_try_fmt_vid_cap(file, priv, f);	mutex_lock(&dev->lock);	if (videobuf_queue_is_busy(&fh->vb_vidq)) {		em28xx_errdev("%s queue busy\n", __func__);		rc = -EBUSY;		goto out;	}	if (dev->stream_on && !fh->stream_on) {		em28xx_errdev("%s device in use by another fh\n", __func__);		rc = -EBUSY;		goto out;	}	/* set new image size */	dev->width = f->fmt.pix.width;	dev->height = f->fmt.pix.height;	get_scale(dev, dev->width, dev->height, &dev->hscale, &dev->vscale);	em28xx_set_alternate(dev);	em28xx_resolution_set(dev);	rc = 0;out:	mutex_unlock(&dev->lock);	return rc;}static int vidioc_s_std(struct file *file, void *priv, v4l2_std_id * norm){	struct em28xx_fh   *fh  = priv;	struct em28xx      *dev = fh->dev;	struct v4l2_format f;	int                rc;	rc = check_dev(dev);	if (rc < 0)		return rc;	mutex_lock(&dev->lock);	dev->norm = *norm;	mutex_unlock(&dev->lock);	/* Adjusts width/height, if needed */	f.fmt.pix.width = dev->width;	f.fmt.pix.height = dev->height;	vidioc_try_fmt_vid_cap(file, priv, &f);	mutex_lock(&dev->lock);	/* set new image size */	dev->width = f.fmt.pix.width;	dev->height = f.fmt.pix.height;	get_scale(dev, dev->width, dev->height, &dev->hscale, &dev->vscale);	em28xx_resolution_set(dev);	em28xx_i2c_call_clients(dev, VIDIOC_S_STD, &dev->norm);	mutex_unlock(&dev->lock);	return 0;}static const char *iname[] = {	[EM28XX_VMUX_COMPOSITE1] = "Composite1",	[EM28XX_VMUX_COMPOSITE2] = "Composite2",	[EM28XX_VMUX_COMPOSITE3] = "Composite3",	[EM28XX_VMUX_COMPOSITE4] = "Composite4",	[EM28XX_VMUX_SVIDEO]     = "S-Video",	[EM28XX_VMUX_TELEVISION] = "Television",	[EM28XX_VMUX_CABLE]      = "Cable TV",	[EM28XX_VMUX_DVB]        = "DVB",	[EM28XX_VMUX_DEBUG]      = "for debug only",};static int vidioc_enum_input(struct file *file, void *priv,				struct v4l2_input *i){	struct em28xx_fh   *fh  = priv;	struct em28xx      *dev = fh->dev;	unsigned int       n;	n = i->index;	if (n >= MAX_EM28XX_INPUT)		return -EINVAL;	if (0 == INPUT(n)->type)		return -EINVAL;	i->index = n;	i->type = V4L2_INPUT_TYPE_CAMERA;	strcpy(i->name, iname[INPUT(n)->type]);	if ((EM28XX_VMUX_TELEVISION == INPUT(n)->type) ||		(EM28XX_VMUX_CABLE == INPUT(n)->type))		i->type = V4L2_INPUT_TYPE_TUNER;	i->std = dev->vdev->tvnorms;	return 0;}static int vidioc_g_input(struct file *file, void *priv, unsigned int *i){	struct em28xx_fh   *fh  = priv;	struct em28xx      *dev = fh->dev;	*i = dev->ctl_input;	return 0;}static int vidioc_s_input(struct file *file, void *priv, unsigned int i){	struct em28xx_fh   *fh  = priv;	struct em28xx      *dev = fh->dev;	int                rc;	rc = check_dev(dev);	if (rc < 0)		return rc;	if (i >= MAX_EM28XX_INPUT)		return -EINVAL;	if (0 == INPUT(i)->type)		return -EINVAL;	mutex_lock(&dev->lock);	video_mux(dev, i);	mutex_unlock(&dev->lock);	return 0;}static int vidioc_g_audio(struct file *file, void *priv, struct v4l2_audio *a){	struct em28xx_fh   *fh    = priv;	struct em28xx      *dev   = fh->dev;	unsigned int        index = a->index;	if (a->index > 1)		return -EINVAL;	index = dev->ctl_ainput;	if (index == 0)		strcpy(a->name, "Television");	else		strcpy(a->name, "Line In");	a->capability = V4L2_AUDCAP_STEREO;	a->index = index;	return 0;}static int vidioc_s_audio(struct file *file, void *priv, struct v4l2_audio *a){	struct em28xx_fh   *fh  = priv;	struct em28xx      *dev = fh->dev;	if (a->index != dev->ctl_ainput)		return -EINVAL;	return 0;}static int vidioc_queryctrl(struct file *file, void *priv,				struct v4l2_queryctrl *qc){	struct em28xx_fh      *fh  = priv;	struct em28xx         *dev = fh->dev;	int                   id  = qc->id;	int                   i;	int                   rc;	rc = check_dev(dev);	if (rc < 0)		return rc;	memset(qc, 0, sizeof(*qc));	qc->id = id;	if (!dev->has_msp34xx) {		for (i = 0; i < ARRAY_SIZE(em28xx_qctrl); i++) {			if (qc->id && qc->id == em28xx_qctrl[i].id) {				memcpy(qc, &(em28xx_qctrl[i]), sizeof(*qc));				return 0;			}		}	}	mutex_lock(&dev->lock);	em28xx_i2c_call_clients(dev, VIDIOC_QUERYCTRL, qc);	mutex_unlock(&dev->lock);	if (qc->type)		return 0;	else		return -EINVAL;}static int vidioc_g_ctrl(struct file *file, void *priv,				struct v4l2_control *ctrl){	struct em28xx_fh      *fh  = priv;	struct em28xx         *dev = fh->dev;	int                   rc;	rc = check_dev(dev);	if (rc < 0)		return rc;	mutex_lock(&dev->lock);	if (!dev->has_msp34xx)		rc = em28xx_get_ctrl(dev, ctrl);	else		rc = -EINVAL;	if (rc == -EINVAL) {		em28xx_i2c_call_clients(dev, VIDIOC_G_CTRL, ctrl);		rc = 0;	}	mutex_unlock(&dev->lock);	return rc;}static int vidioc_s_ctrl(struct file *file, void *priv,				struct v4l2_control *ctrl){	struct em28xx_fh      *fh  = priv;	struct em28xx         *dev = fh->dev;	u8                    i;	int                   rc;	rc = check_dev(dev);	if (rc < 0)		return rc;	mutex_lock(&dev->lock);	if (dev->has_msp34xx)		em28xx_i2c_call_clients(dev, VIDIOC_S_CTRL, ctrl);	else {		rc = 1;		for (i = 0; i < ARRAY_SIZE(em28xx_qctrl); i++) {			if (ctrl->id == em28xx_qctrl[i].id) {				if (ctrl->value < em28xx_qctrl[i].minimum ||				    ctrl->value > em28xx_qctrl[i].maximum) {					rc = -ERANGE;					break;				}				rc = em28xx_set_ctrl(dev, ctrl);				break;			}		}	}	/* Control not found - try to send it to the attached devices */	if (rc == 1) {		em28xx_i2c_call_clients(dev, VIDIOC_S_CTRL, ctrl);		rc = 0;	}	mutex_unlock(&dev->lock);	return rc;}static int vidioc_g_tuner(struct file *file, void *priv,				struct v4l2_tuner *t){	struct em28xx_fh      *fh  = priv;	struct em28xx         *dev = fh->dev;	int                   rc;	rc = check_dev(dev);	if (rc < 0)		return rc;	if (0 != t->index)		return -EINVAL;	strcpy(t->name, "Tuner");	mutex_lock(&dev->lock);	em28xx_i2c_call_clients(dev, VIDIOC_G_TUNER, t);	mutex_unlock(&dev->lock);	return 0;}static int vidioc_s_tuner(struct file *file, void *priv,				struct v4l2_tuner *t){	struct em28xx_fh      *fh  = priv;	struct em28xx         *dev = fh->dev;	int                   rc;	rc = check_dev(dev);	if (rc < 0)		return rc;	if (0 != t->index)		return -EINVAL;	mutex_lock(&dev->lock);	em28xx_i2c_call_clients(dev, VIDIOC_S_TUNER, t);	mutex_unlock(&dev->lock);	return 0;}static int vidioc_g_frequency(struct file *file, void *priv,				struct v4l2_frequency *f){	struct em28xx_fh      *fh  = priv;	struct em28xx         *dev = fh->dev;	f->type = fh->radio ? V4L2_TUNER_RADIO : V4L2_TUNER_ANALOG_TV;	f->frequency = dev->ctl_freq;	return 0;}static int vidioc_s_frequency(struct file *file, void *priv,				struct v4l2_frequency *f){	struct em28xx_fh      *fh  = priv;	struct em28xx         *dev = fh->dev;	int                   rc;	rc = check_dev(dev);	if (rc < 0)		return rc;	if (0 != f->tuner)		return -EINVAL;	if (unlikely(0 == fh->radio && f->type != V4L2_TUNER_ANALOG_TV))		return -EINVAL;	if (unlikely(1 == fh->radio && f->type != V4L2_TUNER_RADIO))		return -EINVAL;	mutex_lock(&dev->lock);	dev->ctl_freq = f->frequency;	em28xx_i2c_call_clients(dev, VIDIOC_S_FREQUENCY, f);	mutex_unlock(&dev->lock);	return 0;}#ifdef CONFIG_VIDEO_ADV_DEBUGstatic int em28xx_reg_len(int reg){	switch (reg) {	case EM28XX_R40_AC97LSB:	case EM28XX_R30_HSCALELOW:	case EM28XX_R32_VSCALELOW:		return 2;	default:		return 1;	}}static int vidioc_g_register(struct file *file, void *priv,			     struct v4l2_register *reg){	struct em28xx_fh      *fh  = priv;	struct em28xx         *dev = fh->dev;	int ret;	if (!v4l2_chip_match_host(reg->match_type, reg->match_chip))		return -EINVAL;	if (em28xx_reg_len(reg->reg) == 1) {		ret = em28xx_read_reg(dev, reg->reg);		if (ret < 0)			return ret;		reg->val = ret;	} else {		__le64 val = 0;		ret = em28xx_read_reg_req_len(dev, USB_REQ_GET_STATUS,						   reg->reg, (char *)&val, 2);		if (ret < 0)			return ret;		reg->val = le64_to_cpu(val);	}	return 0;}static int vidioc_s_register(struct file *file, void *priv,			     struct v4l2_register *reg){	struct em28xx_fh      *fh  = priv;	struct em28xx         *dev = fh->dev;	__le64 buf;	buf = cpu_to_le64(reg->val);	return em28xx_write_regs(dev, reg->reg, (char *)&buf,				 em28xx_reg_len(reg->reg));}#endif

⌨️ 快捷键说明

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