cx88-blackbird.c

来自「linux 内核源代码」· C语言 代码 · 共 1,348 行 · 第 1/3 页

C
1,348
字号
	qctrl->id = v4l2_ctrl_next(ctrl_classes, qctrl->id);	if (unlikely(qctrl->id == 0))		return -EINVAL;	return cx8800_ctrl_query(qctrl);}static int vidioc_enum_input (struct file *file, void *priv,				struct v4l2_input *i){	struct cx88_core  *core = ((struct cx8802_fh *)priv)->dev->core;	return cx88_enum_input (core,i);}static int vidioc_g_ctrl (struct file *file, void *priv,				struct v4l2_control *ctl){	struct cx88_core  *core = ((struct cx8802_fh *)priv)->dev->core;	return		cx88_get_control(core,ctl);}static int vidioc_s_ctrl (struct file *file, void *priv,				struct v4l2_control *ctl){	struct cx88_core  *core = ((struct cx8802_fh *)priv)->dev->core;	return		cx88_set_control(core,ctl);}static int vidioc_g_frequency (struct file *file, void *priv,				struct v4l2_frequency *f){	struct cx8802_fh  *fh   = priv;	struct cx88_core  *core = fh->dev->core;	if (unlikely(UNSET == core->board.tuner_type))		return -EINVAL;	f->type = V4L2_TUNER_ANALOG_TV;	f->frequency = core->freq;	cx88_call_i2c_clients(core,VIDIOC_G_FREQUENCY,f);	return 0;}static int vidioc_g_input (struct file *file, void *priv, unsigned int *i){	struct cx88_core  *core = ((struct cx8802_fh *)priv)->dev->core;	*i = core->input;	return 0;}static int vidioc_s_input (struct file *file, void *priv, unsigned int i){	struct cx88_core  *core = ((struct cx8802_fh *)priv)->dev->core;	if (i >= 4)		return -EINVAL;	mutex_lock(&core->lock);	cx88_newstation(core);	cx88_video_mux(core,i);	mutex_unlock(&core->lock);	return 0;}static int vidioc_g_tuner (struct file *file, void *priv,				struct v4l2_tuner *t){	struct cx88_core  *core = ((struct cx8802_fh *)priv)->dev->core;	u32 reg;	if (unlikely(UNSET == core->board.tuner_type))		return -EINVAL;	if (0 != t->index)		return -EINVAL;	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;}static int vidioc_s_tuner (struct file *file, void *priv,				struct v4l2_tuner *t){	struct cx88_core  *core = ((struct cx8802_fh *)priv)->dev->core;	if (UNSET == core->board.tuner_type)		return -EINVAL;	if (0 != t->index)		return -EINVAL;	cx88_set_stereo(core, t->audmode, 1);	return 0;}static int vidioc_s_std (struct file *file, void *priv, v4l2_std_id *id){	struct cx88_core  *core = ((struct cx8802_fh *)priv)->dev->core;	mutex_lock(&core->lock);	cx88_set_tvnorm(core,*id);	mutex_unlock(&core->lock);	return 0;}/* FIXME: cx88_ioctl_hook not implemented */static int mpeg_open(struct inode *inode, struct file *file){	int minor = iminor(inode);	struct cx8802_dev *dev = NULL;	struct cx8802_fh *fh;	struct cx8802_driver *drv = NULL;	int err;	dev = cx8802_get_device(inode);	dprintk( 1, "%s\n", __FUNCTION__);	if (dev == NULL)		return -ENODEV;	/* Make sure we can acquire the hardware */	drv = cx8802_get_driver(dev, CX88_MPEG_BLACKBIRD);	if (drv) {		err = drv->request_acquire(drv);		if(err != 0) {			dprintk(1,"%s: Unable to acquire hardware, %d\n", __FUNCTION__, err);			return err;		}	}	if (blackbird_initialize_codec(dev) < 0) {		if (drv)			drv->request_release(drv);		return -EINVAL;	}	dprintk(1,"open minor=%d\n",minor);	/* allocate + initialize per filehandle data */	fh = kzalloc(sizeof(*fh),GFP_KERNEL);	if (NULL == fh) {		if (drv)			drv->request_release(drv);		return -ENOMEM;	}	file->private_data = fh;	fh->dev      = dev;	videobuf_queue_pci_init(&fh->mpegq, &blackbird_qops,			    dev->pci, &dev->slock,			    V4L2_BUF_TYPE_VIDEO_CAPTURE,			    V4L2_FIELD_INTERLACED,			    sizeof(struct cx88_buffer),			    fh);	/* FIXME: locking against other video device */	cx88_set_scale(dev->core, dev->width, dev->height,			fh->mpegq.field);	return 0;}static int mpeg_release(struct inode *inode, struct file *file){	struct cx8802_fh  *fh  = file->private_data;	struct cx8802_dev *dev = NULL;	struct cx8802_driver *drv = NULL;	/* blackbird_api_cmd(fh->dev, CX2341X_ENC_STOP_CAPTURE, 3, 0, BLACKBIRD_END_NOW, 0, 0x13); */	blackbird_api_cmd(fh->dev, CX2341X_ENC_STOP_CAPTURE, 3, 0,			BLACKBIRD_END_NOW,			BLACKBIRD_MPEG_CAPTURE,			BLACKBIRD_RAW_BITS_NONE		);	cx8802_cancel_buffers(fh->dev);	/* stop mpeg capture */	videobuf_stop(&fh->mpegq);	videobuf_mmap_free(&fh->mpegq);	file->private_data = NULL;	kfree(fh);	/* Make sure we release the hardware */	dev = cx8802_get_device(inode);	if (dev == NULL)		return -ENODEV;	drv = cx8802_get_driver(dev, CX88_MPEG_BLACKBIRD);	if (drv)		drv->request_release(drv);	return 0;}static ssize_tmpeg_read(struct file *file, char __user *data, size_t count, loff_t *ppos){	struct cx8802_fh *fh = file->private_data;	return videobuf_read_stream(&fh->mpegq, data, count, ppos, 0,				    file->f_flags & O_NONBLOCK);}static unsigned intmpeg_poll(struct file *file, struct poll_table_struct *wait){	struct cx8802_fh *fh = file->private_data;	return videobuf_poll_stream(file, &fh->mpegq, wait);}static intmpeg_mmap(struct file *file, struct vm_area_struct * vma){	struct cx8802_fh *fh = file->private_data;	return videobuf_mmap_mapper(&fh->mpegq, vma);}static const struct file_operations mpeg_fops ={	.owner	       = THIS_MODULE,	.open	       = mpeg_open,	.release       = mpeg_release,	.read	       = mpeg_read,	.poll          = mpeg_poll,	.mmap	       = mpeg_mmap,	.ioctl	       = video_ioctl2,	.llseek        = no_llseek,};static struct video_device cx8802_mpeg_template ={	.name                 = "cx8802",	.type                 = VID_TYPE_CAPTURE|VID_TYPE_TUNER|VID_TYPE_SCALES|VID_TYPE_MPEG_ENCODER,	.fops                 = &mpeg_fops,	.minor                = -1,	.vidioc_querymenu     = vidioc_querymenu,	.vidioc_querycap      = vidioc_querycap,	.vidioc_enum_fmt_cap  = vidioc_enum_fmt_cap,	.vidioc_g_fmt_cap     = vidioc_g_fmt_cap,	.vidioc_try_fmt_cap   = vidioc_try_fmt_cap,	.vidioc_s_fmt_cap     = vidioc_s_fmt_cap,	.vidioc_reqbufs       = vidioc_reqbufs,	.vidioc_querybuf      = vidioc_querybuf,	.vidioc_qbuf          = vidioc_qbuf,	.vidioc_dqbuf         = vidioc_dqbuf,	.vidioc_streamon      = vidioc_streamon,	.vidioc_streamoff     = vidioc_streamoff,	.vidioc_g_ext_ctrls   = vidioc_g_ext_ctrls,	.vidioc_s_ext_ctrls   = vidioc_s_ext_ctrls,	.vidioc_try_ext_ctrls = vidioc_try_ext_ctrls,	.vidioc_s_frequency   = vidioc_s_frequency,	.vidioc_log_status    = vidioc_log_status,	.vidioc_queryctrl     = vidioc_queryctrl,	.vidioc_enum_input    = vidioc_enum_input,	.vidioc_g_ctrl        = vidioc_g_ctrl,	.vidioc_s_ctrl        = vidioc_s_ctrl,	.vidioc_g_frequency   = vidioc_g_frequency,	.vidioc_g_input       = vidioc_g_input,	.vidioc_s_input       = vidioc_s_input,	.vidioc_g_tuner       = vidioc_g_tuner,	.vidioc_s_tuner       = vidioc_s_tuner,	.vidioc_s_std         = vidioc_s_std,	.tvnorms              = CX88_NORMS,	.current_norm         = V4L2_STD_NTSC_M,};/* ------------------------------------------------------------------ *//* The CX8802 MPEG API will call this when we can use the hardware */static int cx8802_blackbird_advise_acquire(struct cx8802_driver *drv){	struct cx88_core *core = drv->core;	int err = 0;	switch (core->boardnr) {	case CX88_BOARD_HAUPPAUGE_HVR1300:		/* By default, core setup will leave the cx22702 out of reset, on the bus.		 * We left the hardware on power up with the cx22702 active.		 * We're being given access to re-arrange the GPIOs.		 * Take the bus off the cx22702 and put the cx23416 on it.		 */		cx_clear(MO_GP0_IO, 0x00000080); /* cx22702 in reset */		cx_set(MO_GP0_IO,   0x00000004); /* Disable the cx22702 */		break;	default:		err = -ENODEV;	}	return err;}/* The CX8802 MPEG API will call this when we need to release the hardware */static int cx8802_blackbird_advise_release(struct cx8802_driver *drv){	struct cx88_core *core = drv->core;	int err = 0;	switch (core->boardnr) {	case CX88_BOARD_HAUPPAUGE_HVR1300:		/* Exit leaving the cx23416 on the bus */		break;	default:		err = -ENODEV;	}	return err;}static void blackbird_unregister_video(struct cx8802_dev *dev){	if (dev->mpeg_dev) {		if (-1 != dev->mpeg_dev->minor)			video_unregister_device(dev->mpeg_dev);		else			video_device_release(dev->mpeg_dev);		dev->mpeg_dev = NULL;	}}static int blackbird_register_video(struct cx8802_dev *dev){	int err;	dev->mpeg_dev = cx88_vdev_init(dev->core,dev->pci,				       &cx8802_mpeg_template,"mpeg");	err = video_register_device(dev->mpeg_dev,VFL_TYPE_GRABBER, -1);	if (err < 0) {		printk(KERN_INFO "%s/2: can't register mpeg device\n",		       dev->core->name);		return err;	}	printk(KERN_INFO "%s/2: registered device video%d [mpeg]\n",	       dev->core->name,dev->mpeg_dev->minor & 0x1f);	return 0;}/* ----------------------------------------------------------- */static int cx8802_blackbird_probe(struct cx8802_driver *drv){	struct cx88_core *core = drv->core;	struct cx8802_dev *dev = core->dvbdev;	int err;	dprintk( 1, "%s\n", __FUNCTION__);	dprintk( 1, " ->being probed by Card=%d Name=%s, PCI %02x:%02x\n",		core->boardnr,		core->name,		core->pci_bus,		core->pci_slot);	err = -ENODEV;	if (!(core->board.mpeg & CX88_MPEG_BLACKBIRD))		goto fail_core;	dev->width = 720;	dev->height = 576;	cx2341x_fill_defaults(&dev->params);	dev->params.port = CX2341X_PORT_STREAMING;	cx8802_mpeg_template.current_norm = core->tvnorm;	if (core->tvnorm & V4L2_STD_525_60) {		dev->height = 480;	} else {		dev->height = 576;	}	/* blackbird stuff */	printk("%s/2: cx23416 based mpeg encoder (blackbird reference design)\n",	       core->name);	host_setup(dev->core);	blackbird_register_video(dev);	/* initial device configuration: needed ? */	mutex_lock(&dev->core->lock);//	init_controls(core);	cx88_set_tvnorm(core,core->tvnorm);	cx88_video_mux(core,0);	mutex_unlock(&dev->core->lock);	return 0; fail_core:	return err;}static int cx8802_blackbird_remove(struct cx8802_driver *drv){	/* blackbird */	blackbird_unregister_video(drv->core->dvbdev);	return 0;}static struct cx8802_driver cx8802_blackbird_driver = {	.type_id	= CX88_MPEG_BLACKBIRD,	.hw_access	= CX8802_DRVCTL_SHARED,	.probe		= cx8802_blackbird_probe,	.remove		= cx8802_blackbird_remove,	.advise_acquire	= cx8802_blackbird_advise_acquire,	.advise_release	= cx8802_blackbird_advise_release,};static int blackbird_init(void){	printk(KERN_INFO "cx2388x blackbird driver version %d.%d.%d loaded\n",	       (CX88_VERSION_CODE >> 16) & 0xff,	       (CX88_VERSION_CODE >>  8) & 0xff,	       CX88_VERSION_CODE & 0xff);#ifdef SNAPSHOT	printk(KERN_INFO "cx2388x: snapshot date %04d-%02d-%02d\n",	       SNAPSHOT/10000, (SNAPSHOT/100)%100, SNAPSHOT%100);#endif	return cx8802_register_driver(&cx8802_blackbird_driver);}static void blackbird_fini(void){	cx8802_unregister_driver(&cx8802_blackbird_driver);}module_init(blackbird_init);module_exit(blackbird_fini);module_param_named(video_debug,cx8802_mpeg_template.debug, int, 0644);MODULE_PARM_DESC(debug,"enable debug messages [video]");/* ----------------------------------------------------------- *//* * Local variables: * c-basic-offset: 8 * End: * kate: eol "unix"; indent-width 3; remove-trailing-space on; replace-trailing-space-save on; tab-width 8; replace-tabs off; space-indent off; mixed-indent off */

⌨️ 快捷键说明

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