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 + -
显示快捷键?