diff options
Diffstat (limited to 'linux/drivers/media/video/em28xx/em28xx-video.c')
-rw-r--r-- | linux/drivers/media/video/em28xx/em28xx-video.c | 71 |
1 files changed, 52 insertions, 19 deletions
diff --git a/linux/drivers/media/video/em28xx/em28xx-video.c b/linux/drivers/media/video/em28xx/em28xx-video.c index a4493da8a..19684ad45 100644 --- a/linux/drivers/media/video/em28xx/em28xx-video.c +++ b/linux/drivers/media/video/em28xx/em28xx-video.c @@ -1656,8 +1656,6 @@ static void em28xx_release_resources(struct em28xx *dev) /*FIXME: I2C IR should be disconnected */ - em28xx_info("V4L2 devices /dev/video%d and /dev/vbi%d deregistered\n", - dev->vdev->num, dev->vbi_dev->num); list_del(&dev->devlist); if (dev->sbutton_input_dev) em28xx_deregister_snapshot_button(dev); @@ -1669,6 +1667,8 @@ static void em28xx_release_resources(struct em28xx *dev) dev->radio_dev = NULL; } if (dev->vbi_dev) { + em28xx_info("V4L2 device /dev/vbi%d deregistered\n", + dev->vbi_dev->num); if (-1 != dev->vbi_dev->minor) video_unregister_device(dev->vbi_dev); else @@ -1676,6 +1676,8 @@ static void em28xx_release_resources(struct em28xx *dev) dev->vbi_dev = NULL; } if (dev->vdev) { + em28xx_info("V4L2 device /dev/video%d deregistered\n", + dev->vdev->num); if (-1 != dev->vdev->minor) video_unregister_device(dev->vdev); else @@ -1982,6 +1984,19 @@ static struct video_device *em28xx_vdev_init(struct em28xx *dev, return vfd; } +int em28xx_supports_audio_extension(struct em28xx *dev) +{ + /* The chip dictates whether we support the Empia analog audio + extension */ + switch (dev->chip_id) { + case CHIP_ID_EM2874: + /* Either a digital-only device or provides AC97 audio */ + return 0; + case CHIP_ID_EM2883: + default: + return 1; + } +} /* * em28xx_init_dev() @@ -2171,7 +2186,7 @@ static void request_module_async(struct work_struct *work) if (dev->has_audio_class) request_module("snd-usb-audio"); - else + else if (dev->has_alsa_audio) request_module("em28xx-alsa"); if (dev->has_dvb) @@ -2204,7 +2219,7 @@ static int em28xx_usb_probe(struct usb_interface *interface, struct usb_interface *uif; struct em28xx *dev = NULL; int retval = -ENODEV; - int i, nr, ifnum; + int i, nr, ifnum, isoc_pipe; udev = usb_get_dev(interface_to_usbdev(interface)); ifnum = interface->altsetting[0].desc.bInterfaceNumber; @@ -2231,19 +2246,29 @@ static int em28xx_usb_probe(struct usb_interface *interface, ifnum, interface->altsetting[0].desc.bInterfaceClass); - endpoint = &interface->cur_altsetting->endpoint[1].desc; + endpoint = &interface->cur_altsetting->endpoint[0].desc; /* check if the device has the iso in endpoint at the correct place */ - if ((endpoint->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) != - USB_ENDPOINT_XFER_ISOC) { - em28xx_err(DRIVER_NAME " probing error: endpoint is non-ISO endpoint!\n"); - em28xx_devused &= ~(1<<nr); - return -ENODEV; - } - if ((endpoint->bEndpointAddress & USB_ENDPOINT_DIR_MASK) == USB_DIR_OUT) { - em28xx_err(DRIVER_NAME " probing error: endpoint is ISO OUT endpoint!\n"); - em28xx_devused &= ~(1<<nr); - return -ENODEV; + if ((endpoint->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) == + USB_ENDPOINT_XFER_ISOC && + (interface->altsetting[1].endpoint[0].desc.wMaxPacketSize == 940)) + { + /* It's a newer em2874/em2875 device */ + isoc_pipe = 0; + } else { + isoc_pipe = 1; + endpoint = &interface->cur_altsetting->endpoint[1].desc; + if ((endpoint->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) != + USB_ENDPOINT_XFER_ISOC) { + em28xx_err(DRIVER_NAME " probing error: endpoint is non-ISO endpoint!\n"); + em28xx_devused &= ~(1<<nr); + return -ENODEV; + } + if ((endpoint->bEndpointAddress & USB_ENDPOINT_DIR_MASK) == USB_DIR_OUT) { + em28xx_err(DRIVER_NAME " probing error: endpoint is ISO OUT endpoint!\n"); + em28xx_devused &= ~(1<<nr); + return -ENODEV; + } } if (nr >= EM28XX_MAXBOARDS) { @@ -2275,9 +2300,6 @@ static int em28xx_usb_probe(struct usb_interface *interface, } } - printk(KERN_INFO DRIVER_NAME " %s usb audio class\n", - dev->has_audio_class ? "Has" : "Doesn't have"); - /* compute alternate max packet sizes */ uif = udev->actconfig->interface[0]; @@ -2294,7 +2316,7 @@ static int em28xx_usb_probe(struct usb_interface *interface, } for (i = 0; i < dev->num_alt ; i++) { - u16 tmp = le16_to_cpu(uif->altsetting[i].endpoint[1].desc. + u16 tmp = le16_to_cpu(uif->altsetting[i].endpoint[isoc_pipe].desc. wMaxPacketSize); dev->alt_max_pkt_size[i] = (tmp & 0x07ff) * (((tmp & 0x1800) >> 11) + 1); @@ -2312,6 +2334,17 @@ static int em28xx_usb_probe(struct usb_interface *interface, em28xx_info("Found %s\n", em28xx_boards[dev->model].name); + if (dev->has_audio_class == 0) { + /* We don't have a USB audio class, let's see if we support + ALSA Audio */ + dev->has_alsa_audio = em28xx_supports_audio_extension(dev); + if (dev->has_alsa_audio) + printk(KERN_INFO DRIVER_NAME " supports alsa audio\n"); + } else { + printk(KERN_INFO DRIVER_NAME " has usb audio class\n"); + } + + /* save our data pointer in this interface device */ usb_set_intfdata(interface, dev); |