Loading drivers/media/video/em28xx/em28xx-video.c +236 −60 Original line number Diff line number Diff line Loading @@ -62,12 +62,16 @@ static LIST_HEAD(em28xx_devlist); static unsigned int card[] = {[0 ... (EM28XX_MAXBOARDS - 1)] = UNSET }; static unsigned int video_nr[] = {[0 ... (EM28XX_MAXBOARDS - 1)] = UNSET }; static unsigned int vbi_nr[] = {[0 ... (EM28XX_MAXBOARDS - 1)] = UNSET }; static unsigned int radio_nr[] = {[0 ... (EM28XX_MAXBOARDS - 1)] = UNSET }; module_param_array(card, int, NULL, 0444); module_param_array(video_nr, int, NULL, 0444); module_param_array(vbi_nr, int, NULL, 0444); module_param_array(radio_nr, int, NULL, 0444); MODULE_PARM_DESC(card, "card type"); MODULE_PARM_DESC(video_nr, "video device numbers"); MODULE_PARM_DESC(vbi_nr, "vbi device numbers"); MODULE_PARM_DESC(radio_nr, "radio device numbers"); static unsigned int video_debug = 0; module_param(video_debug,int,0644); Loading Loading @@ -791,7 +795,7 @@ static int vidioc_g_frequency(struct file *file, void *priv, struct em28xx_fh *fh = priv; struct em28xx *dev = fh->dev; f->type = V4L2_TUNER_ANALOG_TV; f->type = fh->radio ? V4L2_TUNER_RADIO : V4L2_TUNER_ANALOG_TV; f->frequency = dev->ctl_freq; return 0; Loading @@ -811,7 +815,9 @@ static int vidioc_s_frequency(struct file *file, void *priv, if (0 != f->tuner) return -EINVAL; if (V4L2_TUNER_ANALOG_TV != f->type) 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); Loading Loading @@ -1148,6 +1154,102 @@ static int vidioc_dqbuf(struct file *file, void *priv, struct v4l2_buffer *b) return 0; } /* ----------------------------------------------------------- */ /* RADIO ESPECIFIC IOCTLS */ /* ----------------------------------------------------------- */ static int radio_querycap(struct file *file, void *priv, struct v4l2_capability *cap) { struct em28xx *dev = ((struct em28xx_fh *)priv)->dev; strlcpy(cap->driver, "em28xx", sizeof(cap->driver)); strlcpy(cap->card, em28xx_boards[dev->model].name, sizeof(cap->card)); strlcpy(cap->bus_info, dev->udev->dev.bus_id, sizeof(cap->bus_info)); cap->version = EM28XX_VERSION_CODE; cap->capabilities = V4L2_CAP_TUNER; return 0; } static int radio_g_tuner(struct file *file, void *priv, struct v4l2_tuner *t) { struct em28xx *dev = ((struct em28xx_fh *)priv)->dev; if (unlikely(t->index > 0)) return -EINVAL; strcpy(t->name, "Radio"); t->type = V4L2_TUNER_RADIO; em28xx_i2c_call_clients(dev, VIDIOC_G_TUNER, t); return 0; } static int radio_enum_input(struct file *file, void *priv, struct v4l2_input *i) { if (i->index != 0) return -EINVAL; strcpy(i->name, "Radio"); i->type = V4L2_INPUT_TYPE_TUNER; return 0; } static int radio_g_audio(struct file *file, void *priv, struct v4l2_audio *a) { if (unlikely(a->index)) return -EINVAL; strcpy(a->name, "Radio"); return 0; } static int radio_s_tuner(struct file *file, void *priv, struct v4l2_tuner *t) { struct em28xx *dev = ((struct em28xx_fh *)priv)->dev; if (0 != t->index) return -EINVAL; em28xx_i2c_call_clients(dev, VIDIOC_S_TUNER, t); return 0; } static int radio_s_audio(struct file *file, void *fh, struct v4l2_audio *a) { return 0; } static int radio_s_input(struct file *file, void *fh, unsigned int i) { return 0; } static int radio_queryctrl(struct file *file, void *priv, struct v4l2_queryctrl *qc) { int i; if (qc->id < V4L2_CID_BASE || qc->id >= V4L2_CID_LASTP1) return -EINVAL; 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; } } return -EINVAL; } /* * em28xx_v4l2_open() * inits the device and starts isoc transfer Loading @@ -1155,7 +1257,7 @@ static int vidioc_dqbuf(struct file *file, void *priv, struct v4l2_buffer *b) static int em28xx_v4l2_open(struct inode *inode, struct file *filp) { int minor = iminor(inode); int errCode = 0; int errCode = 0, radio = 0; struct em28xx *h,*dev = NULL; struct em28xx_fh *fh; Loading @@ -1168,6 +1270,11 @@ static int em28xx_v4l2_open(struct inode *inode, struct file *filp) dev = h; dev->type = V4L2_BUF_TYPE_VBI_CAPTURE; } if (h->radio_dev && h->radio_dev->minor == minor) { radio = 1; dev = h; } } if (NULL == dev) return -ENODEV; Loading @@ -1183,6 +1290,7 @@ static int em28xx_v4l2_open(struct inode *inode, struct file *filp) } mutex_lock(&dev->lock); fh->dev = dev; fh->radio = radio; filp->private_data = fh; if (dev->type == V4L2_BUF_TYPE_VIDEO_CAPTURE && dev->users == 0) { Loading @@ -1207,6 +1315,10 @@ static int em28xx_v4l2_open(struct inode *inode, struct file *filp) em28xx_empty_framequeues(dev); } if (fh->radio) { em28xx_videodbg("video_open: setting radio device\n"); em28xx_i2c_call_clients(dev, AUDC_SET_RADIO, NULL); } dev->users++; Loading @@ -1229,12 +1341,30 @@ static void em28xx_release_resources(struct em28xx *dev) dev->vdev->minor-MINOR_VFL_TYPE_GRABBER_MIN, dev->vbi_dev->minor-MINOR_VFL_TYPE_VBI_MIN); list_del(&dev->devlist); video_unregister_device(dev->vdev); if (dev->radio_dev) { if (-1 != dev->radio_dev->minor) video_unregister_device(dev->radio_dev); else video_device_release(dev->radio_dev); dev->radio_dev = NULL; } if (dev->vbi_dev) { if (-1 != dev->vbi_dev->minor) video_unregister_device(dev->vbi_dev); else video_device_release(dev->vbi_dev); dev->vbi_dev = NULL; } if (dev->vdev) { if (-1 != dev->vdev->minor) video_unregister_device(dev->vdev); else video_device_release(dev->vdev); dev->vdev = NULL; } em28xx_i2c_unregister(dev); usb_put_dev(dev->udev); /* Mark device as unused */ em28xx_devused&=~(1<<dev->devno); } Loading Loading @@ -1555,6 +1685,15 @@ static const struct file_operations em28xx_v4l_fops = { .compat_ioctl = v4l_compat_ioctl32, }; static const struct file_operations radio_fops = { .owner = THIS_MODULE, .open = em28xx_v4l2_open, .release = em28xx_v4l2_close, .ioctl = video_ioctl2, .compat_ioctl = v4l_compat_ioctl32, .llseek = no_llseek, }; static const struct video_device em28xx_video_template = { .fops = &em28xx_v4l_fops, .release = video_device_release, Loading Loading @@ -1595,6 +1734,25 @@ static const struct video_device em28xx_video_template = { .current_norm = V4L2_STD_PAL, }; static struct video_device em28xx_radio_template = { .name = "em28xx-radio", .type = VID_TYPE_TUNER, .fops = &radio_fops, .minor = -1, .vidioc_querycap = radio_querycap, .vidioc_g_tuner = radio_g_tuner, .vidioc_enum_input = radio_enum_input, .vidioc_g_audio = radio_g_audio, .vidioc_s_tuner = radio_s_tuner, .vidioc_s_audio = radio_s_audio, .vidioc_s_input = radio_s_input, .vidioc_queryctrl = radio_queryctrl, .vidioc_g_ctrl = vidioc_g_ctrl, .vidioc_s_ctrl = vidioc_s_ctrl, .vidioc_g_frequency = vidioc_g_frequency, .vidioc_s_frequency = vidioc_s_frequency, }; /******************************** usb interface *****************************************/ Loading Loading @@ -1637,6 +1795,29 @@ void em28xx_unregister_extension(struct em28xx_ops *ops) } EXPORT_SYMBOL(em28xx_unregister_extension); struct video_device *em28xx_vdev_init(struct em28xx *dev, const struct video_device *template, const int type, const char *type_name) { struct video_device *vfd; vfd = video_device_alloc(); if (NULL == vfd) return NULL; *vfd = *template; vfd->minor = -1; vfd->dev = &dev->udev->dev; vfd->release = video_device_release; vfd->type = type; snprintf(vfd->name, sizeof(vfd->name), "%s %s", dev->name, type_name); return vfd; } /* * em28xx_init_dev() * allocates and inits the device structs, registers i2c bus and v4l device Loading Loading @@ -1710,40 +1891,55 @@ static int em28xx_init_dev(struct em28xx **devhandle, struct usb_device *udev, errCode = em28xx_config(dev); list_add_tail(&dev->devlist, &em28xx_devlist); /* allocate and fill video video_device struct */ dev->vdev = video_device_alloc(); dev->vdev = em28xx_vdev_init(dev, &em28xx_video_template, VID_TYPE_CAPTURE, "video"); if (NULL == dev->vdev) { em28xx_errdev("cannot allocate video_device.\n"); em28xx_devused&=~(1<<dev->devno); kfree(dev); return -ENOMEM; goto fail_unreg; } memcpy(dev->vdev, &em28xx_video_template, sizeof(em28xx_video_template)); dev->vdev->type = VID_TYPE_CAPTURE; if (dev->has_tuner) dev->vdev->type |= VID_TYPE_TUNER; dev->vdev->dev = &dev->udev->dev; snprintf(dev->vdev->name, sizeof(dev->vbi_dev->name), "%s#%d %s", "em28xx", dev->devno, "video"); /* register v4l2 video video_device */ retval = video_register_device(dev->vdev, VFL_TYPE_GRABBER, video_nr[dev->devno]); if (retval) { em28xx_errdev("unable to register video device (error=%i).\n", retval); goto fail_unreg; } /* Allocate and fill vbi video_device struct */ dev->vbi_dev = video_device_alloc(); if (NULL == dev->vbi_dev) { dev->vbi_dev = em28xx_vdev_init(dev, &em28xx_video_template, VFL_TYPE_VBI, "vbi"); /* register v4l2 vbi video_device */ if (video_register_device(dev->vbi_dev, VFL_TYPE_VBI, vbi_nr[dev->devno]) < 0) { em28xx_errdev("unable to register vbi device\n"); retval = -ENODEV; goto fail_unreg; } if (em28xx_boards[dev->model].radio.type == EM28XX_RADIO) { dev->radio_dev = em28xx_vdev_init(dev, &em28xx_radio_template, VFL_TYPE_RADIO, "radio"); if (NULL == dev->radio_dev) { em28xx_errdev("cannot allocate video_device.\n"); kfree(dev->vdev); em28xx_devused&=~(1<<dev->devno); kfree(dev); return -ENOMEM; goto fail_unreg; } retval = video_register_device(dev->radio_dev, VFL_TYPE_RADIO, radio_nr[dev->devno]); if (retval < 0) { em28xx_errdev("can't register radio device\n"); goto fail_unreg; } em28xx_info("Registered radio device as /dev/radio%d\n", dev->radio_dev->minor & 0x1f); } memcpy(dev->vbi_dev, &em28xx_video_template, sizeof(em28xx_video_template)); dev->vbi_dev->type = VFL_TYPE_VBI; dev->vbi_dev->dev = &dev->udev->dev; snprintf(dev->vbi_dev->name, sizeof(dev->vbi_dev->name), "%s#%d %s", "em28xx", dev->devno, "vbi"); list_add_tail(&dev->devlist,&em28xx_devlist); if (dev->has_msp34xx) { /* Send a reset to other chips via gpio */ Loading @@ -1755,32 +1951,6 @@ static int em28xx_init_dev(struct em28xx **devhandle, struct usb_device *udev, video_mux(dev, 0); /* register v4l2 video video_device */ if ((retval = video_register_device(dev->vdev, VFL_TYPE_GRABBER, video_nr[dev->devno]))) { em28xx_errdev("unable to register video device (error=%i).\n", retval); mutex_unlock(&dev->lock); list_del(&dev->devlist); video_device_release(dev->vdev); em28xx_devused&=~(1<<dev->devno); kfree(dev); return -ENODEV; } /* register v4l2 vbi video_device */ if (video_register_device(dev->vbi_dev, VFL_TYPE_VBI, vbi_nr[dev->devno]) < 0) { printk("unable to register vbi device\n"); mutex_unlock(&dev->lock); list_del(&dev->devlist); video_device_release(dev->vbi_dev); video_device_release(dev->vdev); em28xx_devused&=~(1<<dev->devno); kfree(dev); return -ENODEV; } em28xx_info("V4L2 device registered as /dev/video%d and /dev/vbi%d\n", dev->vdev->minor-MINOR_VFL_TYPE_GRABBER_MIN, dev->vbi_dev->minor-MINOR_VFL_TYPE_VBI_MIN); Loading @@ -1795,6 +1965,12 @@ static int em28xx_init_dev(struct em28xx **devhandle, struct usb_device *udev, mutex_unlock(&em28xx_extension_devlist_lock); return 0; fail_unreg: em28xx_release_resources(dev); mutex_unlock(&dev->lock); kfree(dev); return retval; } #if defined(CONFIG_MODULES) && defined(MODULE) Loading drivers/media/video/em28xx/em28xx.h +2 −0 Original line number Diff line number Diff line Loading @@ -191,6 +191,7 @@ struct em28xx_board { enum em28xx_decoder decoder; struct em28xx_input input[MAX_EM28XX_INPUT]; struct em28xx_input radio; }; struct em28xx_eeprom { Loading Loading @@ -307,6 +308,7 @@ struct em28xx { struct list_head inqueue, outqueue; wait_queue_head_t open, wait_frame, wait_stream; struct video_device *vbi_dev; struct video_device *radio_dev; unsigned char eedata[256]; Loading Loading
drivers/media/video/em28xx/em28xx-video.c +236 −60 Original line number Diff line number Diff line Loading @@ -62,12 +62,16 @@ static LIST_HEAD(em28xx_devlist); static unsigned int card[] = {[0 ... (EM28XX_MAXBOARDS - 1)] = UNSET }; static unsigned int video_nr[] = {[0 ... (EM28XX_MAXBOARDS - 1)] = UNSET }; static unsigned int vbi_nr[] = {[0 ... (EM28XX_MAXBOARDS - 1)] = UNSET }; static unsigned int radio_nr[] = {[0 ... (EM28XX_MAXBOARDS - 1)] = UNSET }; module_param_array(card, int, NULL, 0444); module_param_array(video_nr, int, NULL, 0444); module_param_array(vbi_nr, int, NULL, 0444); module_param_array(radio_nr, int, NULL, 0444); MODULE_PARM_DESC(card, "card type"); MODULE_PARM_DESC(video_nr, "video device numbers"); MODULE_PARM_DESC(vbi_nr, "vbi device numbers"); MODULE_PARM_DESC(radio_nr, "radio device numbers"); static unsigned int video_debug = 0; module_param(video_debug,int,0644); Loading Loading @@ -791,7 +795,7 @@ static int vidioc_g_frequency(struct file *file, void *priv, struct em28xx_fh *fh = priv; struct em28xx *dev = fh->dev; f->type = V4L2_TUNER_ANALOG_TV; f->type = fh->radio ? V4L2_TUNER_RADIO : V4L2_TUNER_ANALOG_TV; f->frequency = dev->ctl_freq; return 0; Loading @@ -811,7 +815,9 @@ static int vidioc_s_frequency(struct file *file, void *priv, if (0 != f->tuner) return -EINVAL; if (V4L2_TUNER_ANALOG_TV != f->type) 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); Loading Loading @@ -1148,6 +1154,102 @@ static int vidioc_dqbuf(struct file *file, void *priv, struct v4l2_buffer *b) return 0; } /* ----------------------------------------------------------- */ /* RADIO ESPECIFIC IOCTLS */ /* ----------------------------------------------------------- */ static int radio_querycap(struct file *file, void *priv, struct v4l2_capability *cap) { struct em28xx *dev = ((struct em28xx_fh *)priv)->dev; strlcpy(cap->driver, "em28xx", sizeof(cap->driver)); strlcpy(cap->card, em28xx_boards[dev->model].name, sizeof(cap->card)); strlcpy(cap->bus_info, dev->udev->dev.bus_id, sizeof(cap->bus_info)); cap->version = EM28XX_VERSION_CODE; cap->capabilities = V4L2_CAP_TUNER; return 0; } static int radio_g_tuner(struct file *file, void *priv, struct v4l2_tuner *t) { struct em28xx *dev = ((struct em28xx_fh *)priv)->dev; if (unlikely(t->index > 0)) return -EINVAL; strcpy(t->name, "Radio"); t->type = V4L2_TUNER_RADIO; em28xx_i2c_call_clients(dev, VIDIOC_G_TUNER, t); return 0; } static int radio_enum_input(struct file *file, void *priv, struct v4l2_input *i) { if (i->index != 0) return -EINVAL; strcpy(i->name, "Radio"); i->type = V4L2_INPUT_TYPE_TUNER; return 0; } static int radio_g_audio(struct file *file, void *priv, struct v4l2_audio *a) { if (unlikely(a->index)) return -EINVAL; strcpy(a->name, "Radio"); return 0; } static int radio_s_tuner(struct file *file, void *priv, struct v4l2_tuner *t) { struct em28xx *dev = ((struct em28xx_fh *)priv)->dev; if (0 != t->index) return -EINVAL; em28xx_i2c_call_clients(dev, VIDIOC_S_TUNER, t); return 0; } static int radio_s_audio(struct file *file, void *fh, struct v4l2_audio *a) { return 0; } static int radio_s_input(struct file *file, void *fh, unsigned int i) { return 0; } static int radio_queryctrl(struct file *file, void *priv, struct v4l2_queryctrl *qc) { int i; if (qc->id < V4L2_CID_BASE || qc->id >= V4L2_CID_LASTP1) return -EINVAL; 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; } } return -EINVAL; } /* * em28xx_v4l2_open() * inits the device and starts isoc transfer Loading @@ -1155,7 +1257,7 @@ static int vidioc_dqbuf(struct file *file, void *priv, struct v4l2_buffer *b) static int em28xx_v4l2_open(struct inode *inode, struct file *filp) { int minor = iminor(inode); int errCode = 0; int errCode = 0, radio = 0; struct em28xx *h,*dev = NULL; struct em28xx_fh *fh; Loading @@ -1168,6 +1270,11 @@ static int em28xx_v4l2_open(struct inode *inode, struct file *filp) dev = h; dev->type = V4L2_BUF_TYPE_VBI_CAPTURE; } if (h->radio_dev && h->radio_dev->minor == minor) { radio = 1; dev = h; } } if (NULL == dev) return -ENODEV; Loading @@ -1183,6 +1290,7 @@ static int em28xx_v4l2_open(struct inode *inode, struct file *filp) } mutex_lock(&dev->lock); fh->dev = dev; fh->radio = radio; filp->private_data = fh; if (dev->type == V4L2_BUF_TYPE_VIDEO_CAPTURE && dev->users == 0) { Loading @@ -1207,6 +1315,10 @@ static int em28xx_v4l2_open(struct inode *inode, struct file *filp) em28xx_empty_framequeues(dev); } if (fh->radio) { em28xx_videodbg("video_open: setting radio device\n"); em28xx_i2c_call_clients(dev, AUDC_SET_RADIO, NULL); } dev->users++; Loading @@ -1229,12 +1341,30 @@ static void em28xx_release_resources(struct em28xx *dev) dev->vdev->minor-MINOR_VFL_TYPE_GRABBER_MIN, dev->vbi_dev->minor-MINOR_VFL_TYPE_VBI_MIN); list_del(&dev->devlist); video_unregister_device(dev->vdev); if (dev->radio_dev) { if (-1 != dev->radio_dev->minor) video_unregister_device(dev->radio_dev); else video_device_release(dev->radio_dev); dev->radio_dev = NULL; } if (dev->vbi_dev) { if (-1 != dev->vbi_dev->minor) video_unregister_device(dev->vbi_dev); else video_device_release(dev->vbi_dev); dev->vbi_dev = NULL; } if (dev->vdev) { if (-1 != dev->vdev->minor) video_unregister_device(dev->vdev); else video_device_release(dev->vdev); dev->vdev = NULL; } em28xx_i2c_unregister(dev); usb_put_dev(dev->udev); /* Mark device as unused */ em28xx_devused&=~(1<<dev->devno); } Loading Loading @@ -1555,6 +1685,15 @@ static const struct file_operations em28xx_v4l_fops = { .compat_ioctl = v4l_compat_ioctl32, }; static const struct file_operations radio_fops = { .owner = THIS_MODULE, .open = em28xx_v4l2_open, .release = em28xx_v4l2_close, .ioctl = video_ioctl2, .compat_ioctl = v4l_compat_ioctl32, .llseek = no_llseek, }; static const struct video_device em28xx_video_template = { .fops = &em28xx_v4l_fops, .release = video_device_release, Loading Loading @@ -1595,6 +1734,25 @@ static const struct video_device em28xx_video_template = { .current_norm = V4L2_STD_PAL, }; static struct video_device em28xx_radio_template = { .name = "em28xx-radio", .type = VID_TYPE_TUNER, .fops = &radio_fops, .minor = -1, .vidioc_querycap = radio_querycap, .vidioc_g_tuner = radio_g_tuner, .vidioc_enum_input = radio_enum_input, .vidioc_g_audio = radio_g_audio, .vidioc_s_tuner = radio_s_tuner, .vidioc_s_audio = radio_s_audio, .vidioc_s_input = radio_s_input, .vidioc_queryctrl = radio_queryctrl, .vidioc_g_ctrl = vidioc_g_ctrl, .vidioc_s_ctrl = vidioc_s_ctrl, .vidioc_g_frequency = vidioc_g_frequency, .vidioc_s_frequency = vidioc_s_frequency, }; /******************************** usb interface *****************************************/ Loading Loading @@ -1637,6 +1795,29 @@ void em28xx_unregister_extension(struct em28xx_ops *ops) } EXPORT_SYMBOL(em28xx_unregister_extension); struct video_device *em28xx_vdev_init(struct em28xx *dev, const struct video_device *template, const int type, const char *type_name) { struct video_device *vfd; vfd = video_device_alloc(); if (NULL == vfd) return NULL; *vfd = *template; vfd->minor = -1; vfd->dev = &dev->udev->dev; vfd->release = video_device_release; vfd->type = type; snprintf(vfd->name, sizeof(vfd->name), "%s %s", dev->name, type_name); return vfd; } /* * em28xx_init_dev() * allocates and inits the device structs, registers i2c bus and v4l device Loading Loading @@ -1710,40 +1891,55 @@ static int em28xx_init_dev(struct em28xx **devhandle, struct usb_device *udev, errCode = em28xx_config(dev); list_add_tail(&dev->devlist, &em28xx_devlist); /* allocate and fill video video_device struct */ dev->vdev = video_device_alloc(); dev->vdev = em28xx_vdev_init(dev, &em28xx_video_template, VID_TYPE_CAPTURE, "video"); if (NULL == dev->vdev) { em28xx_errdev("cannot allocate video_device.\n"); em28xx_devused&=~(1<<dev->devno); kfree(dev); return -ENOMEM; goto fail_unreg; } memcpy(dev->vdev, &em28xx_video_template, sizeof(em28xx_video_template)); dev->vdev->type = VID_TYPE_CAPTURE; if (dev->has_tuner) dev->vdev->type |= VID_TYPE_TUNER; dev->vdev->dev = &dev->udev->dev; snprintf(dev->vdev->name, sizeof(dev->vbi_dev->name), "%s#%d %s", "em28xx", dev->devno, "video"); /* register v4l2 video video_device */ retval = video_register_device(dev->vdev, VFL_TYPE_GRABBER, video_nr[dev->devno]); if (retval) { em28xx_errdev("unable to register video device (error=%i).\n", retval); goto fail_unreg; } /* Allocate and fill vbi video_device struct */ dev->vbi_dev = video_device_alloc(); if (NULL == dev->vbi_dev) { dev->vbi_dev = em28xx_vdev_init(dev, &em28xx_video_template, VFL_TYPE_VBI, "vbi"); /* register v4l2 vbi video_device */ if (video_register_device(dev->vbi_dev, VFL_TYPE_VBI, vbi_nr[dev->devno]) < 0) { em28xx_errdev("unable to register vbi device\n"); retval = -ENODEV; goto fail_unreg; } if (em28xx_boards[dev->model].radio.type == EM28XX_RADIO) { dev->radio_dev = em28xx_vdev_init(dev, &em28xx_radio_template, VFL_TYPE_RADIO, "radio"); if (NULL == dev->radio_dev) { em28xx_errdev("cannot allocate video_device.\n"); kfree(dev->vdev); em28xx_devused&=~(1<<dev->devno); kfree(dev); return -ENOMEM; goto fail_unreg; } retval = video_register_device(dev->radio_dev, VFL_TYPE_RADIO, radio_nr[dev->devno]); if (retval < 0) { em28xx_errdev("can't register radio device\n"); goto fail_unreg; } em28xx_info("Registered radio device as /dev/radio%d\n", dev->radio_dev->minor & 0x1f); } memcpy(dev->vbi_dev, &em28xx_video_template, sizeof(em28xx_video_template)); dev->vbi_dev->type = VFL_TYPE_VBI; dev->vbi_dev->dev = &dev->udev->dev; snprintf(dev->vbi_dev->name, sizeof(dev->vbi_dev->name), "%s#%d %s", "em28xx", dev->devno, "vbi"); list_add_tail(&dev->devlist,&em28xx_devlist); if (dev->has_msp34xx) { /* Send a reset to other chips via gpio */ Loading @@ -1755,32 +1951,6 @@ static int em28xx_init_dev(struct em28xx **devhandle, struct usb_device *udev, video_mux(dev, 0); /* register v4l2 video video_device */ if ((retval = video_register_device(dev->vdev, VFL_TYPE_GRABBER, video_nr[dev->devno]))) { em28xx_errdev("unable to register video device (error=%i).\n", retval); mutex_unlock(&dev->lock); list_del(&dev->devlist); video_device_release(dev->vdev); em28xx_devused&=~(1<<dev->devno); kfree(dev); return -ENODEV; } /* register v4l2 vbi video_device */ if (video_register_device(dev->vbi_dev, VFL_TYPE_VBI, vbi_nr[dev->devno]) < 0) { printk("unable to register vbi device\n"); mutex_unlock(&dev->lock); list_del(&dev->devlist); video_device_release(dev->vbi_dev); video_device_release(dev->vdev); em28xx_devused&=~(1<<dev->devno); kfree(dev); return -ENODEV; } em28xx_info("V4L2 device registered as /dev/video%d and /dev/vbi%d\n", dev->vdev->minor-MINOR_VFL_TYPE_GRABBER_MIN, dev->vbi_dev->minor-MINOR_VFL_TYPE_VBI_MIN); Loading @@ -1795,6 +1965,12 @@ static int em28xx_init_dev(struct em28xx **devhandle, struct usb_device *udev, mutex_unlock(&em28xx_extension_devlist_lock); return 0; fail_unreg: em28xx_release_resources(dev); mutex_unlock(&dev->lock); kfree(dev); return retval; } #if defined(CONFIG_MODULES) && defined(MODULE) Loading
drivers/media/video/em28xx/em28xx.h +2 −0 Original line number Diff line number Diff line Loading @@ -191,6 +191,7 @@ struct em28xx_board { enum em28xx_decoder decoder; struct em28xx_input input[MAX_EM28XX_INPUT]; struct em28xx_input radio; }; struct em28xx_eeprom { Loading Loading @@ -307,6 +308,7 @@ struct em28xx { struct list_head inqueue, outqueue; wait_queue_head_t open, wait_frame, wait_stream; struct video_device *vbi_dev; struct video_device *radio_dev; unsigned char eedata[256]; Loading