diff options
author | Mauro Carvalho Chehab <mchehab@redhat.com> | 2011-06-17 14:15:12 -0400 |
---|---|---|
committer | Mauro Carvalho Chehab <mchehab@redhat.com> | 2011-07-27 16:53:04 -0400 |
commit | 4f83e7b3ef938eb9a01eadf81a0f3b2c67d3afb6 (patch) | |
tree | f49cd93355efa11d2ad2ce97bb25bbeb0d4ad155 /drivers/media | |
parent | dff0f8c279e34089128e9687d77bfc72dbb471bd (diff) |
[media] em28xx: Add support for devices with a separate audio interface
Some devices use a separate interface for the vendor audio class.
Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
Diffstat (limited to 'drivers/media')
-rw-r--r-- | drivers/media/video/em28xx/em28xx-audio.c | 44 | ||||
-rw-r--r-- | drivers/media/video/em28xx/em28xx-cards.c | 102 | ||||
-rw-r--r-- | drivers/media/video/em28xx/em28xx-core.c | 20 | ||||
-rw-r--r-- | drivers/media/video/em28xx/em28xx.h | 3 |
4 files changed, 109 insertions, 60 deletions
diff --git a/drivers/media/video/em28xx/em28xx-audio.c b/drivers/media/video/em28xx/em28xx-audio.c index 47f21a382546..cff0768afbf5 100644 --- a/drivers/media/video/em28xx/em28xx-audio.c +++ b/drivers/media/video/em28xx/em28xx-audio.c | |||
@@ -3,9 +3,9 @@ | |||
3 | * | 3 | * |
4 | * Copyright (C) 2006 Markus Rechberger <mrechberger@gmail.com> | 4 | * Copyright (C) 2006 Markus Rechberger <mrechberger@gmail.com> |
5 | * | 5 | * |
6 | * Copyright (C) 2007 Mauro Carvalho Chehab <mchehab@infradead.org> | 6 | * Copyright (C) 2007-2011 Mauro Carvalho Chehab <mchehab@redhat.com> |
7 | * - Port to work with the in-kernel driver | 7 | * - Port to work with the in-kernel driver |
8 | * - Several cleanups | 8 | * - Cleanups, fixes, alsa-controls, etc. |
9 | * | 9 | * |
10 | * This driver is based on my previous au600 usb pstn audio driver | 10 | * This driver is based on my previous au600 usb pstn audio driver |
11 | * and inherits all the copyrights | 11 | * and inherits all the copyrights |
@@ -281,23 +281,27 @@ static int snd_em28xx_capture_open(struct snd_pcm_substream *substream) | |||
281 | return -ENODEV; | 281 | return -ENODEV; |
282 | } | 282 | } |
283 | 283 | ||
284 | /* Sets volume, mute, etc */ | 284 | runtime->hw = snd_em28xx_hw_capture; |
285 | if ((dev->alt == 0 || dev->audio_ifnum) && dev->adev.users == 0) { | ||
286 | if (dev->audio_ifnum) | ||
287 | dev->alt = 1; | ||
288 | else | ||
289 | dev->alt = 7; | ||
285 | 290 | ||
286 | dev->mute = 0; | 291 | dprintk("changing alternate number on interface %d to %d\n", |
287 | mutex_lock(&dev->lock); | 292 | dev->audio_ifnum, dev->alt); |
288 | ret = em28xx_audio_analog_set(dev); | 293 | usb_set_interface(dev->udev, dev->audio_ifnum, dev->alt); |
289 | if (ret < 0) | ||
290 | goto err; | ||
291 | 294 | ||
292 | runtime->hw = snd_em28xx_hw_capture; | 295 | /* Sets volume, mute, etc */ |
293 | if (dev->alt == 0 && dev->adev.users == 0) { | 296 | dev->mute = 0; |
294 | dev->alt = 7; | 297 | mutex_lock(&dev->lock); |
295 | dprintk("changing alternate number to 7\n"); | 298 | ret = em28xx_audio_analog_set(dev); |
296 | usb_set_interface(dev->udev, 0, 7); | 299 | if (ret < 0) |
297 | } | 300 | goto err; |
298 | 301 | ||
299 | dev->adev.users++; | 302 | dev->adev.users++; |
300 | mutex_unlock(&dev->lock); | 303 | mutex_unlock(&dev->lock); |
304 | } | ||
301 | 305 | ||
302 | snd_pcm_hw_constraint_integer(runtime, SNDRV_PCM_HW_PARAM_PERIODS); | 306 | snd_pcm_hw_constraint_integer(runtime, SNDRV_PCM_HW_PARAM_PERIODS); |
303 | dev->adev.capture_pcm_substream = substream; | 307 | dev->adev.capture_pcm_substream = substream; |
@@ -635,17 +639,17 @@ static int em28xx_audio_init(struct em28xx *dev) | |||
635 | static int devnr; | 639 | static int devnr; |
636 | int err; | 640 | int err; |
637 | 641 | ||
638 | if (dev->has_alsa_audio != 1) { | 642 | if (!dev->has_alsa_audio || dev->audio_ifnum < 0) { |
639 | /* This device does not support the extension (in this case | 643 | /* This device does not support the extension (in this case |
640 | the device is expecting the snd-usb-audio module or | 644 | the device is expecting the snd-usb-audio module or |
641 | doesn't have analog audio support at all) */ | 645 | doesn't have analog audio support at all) */ |
642 | return 0; | 646 | return 0; |
643 | } | 647 | } |
644 | 648 | ||
645 | printk(KERN_INFO "em28xx-audio.c: probing for em28x1 " | 649 | printk(KERN_INFO "em28xx-audio.c: probing for em28xx Audio Vendor Class\n"); |
646 | "non standard usbaudio\n"); | ||
647 | printk(KERN_INFO "em28xx-audio.c: Copyright (C) 2006 Markus " | 650 | printk(KERN_INFO "em28xx-audio.c: Copyright (C) 2006 Markus " |
648 | "Rechberger\n"); | 651 | "Rechberger\n"); |
652 | printk(KERN_INFO "em28xx-audio.c: Copyright (C) 2007-2011 Mauro Carvalho Chehab\n"); | ||
649 | 653 | ||
650 | err = snd_card_create(index[devnr], "Em28xx Audio", THIS_MODULE, 0, | 654 | err = snd_card_create(index[devnr], "Em28xx Audio", THIS_MODULE, 0, |
651 | &card); | 655 | &card); |
@@ -737,7 +741,7 @@ static void __exit em28xx_alsa_unregister(void) | |||
737 | 741 | ||
738 | MODULE_LICENSE("GPL"); | 742 | MODULE_LICENSE("GPL"); |
739 | MODULE_AUTHOR("Markus Rechberger <mrechberger@gmail.com>"); | 743 | MODULE_AUTHOR("Markus Rechberger <mrechberger@gmail.com>"); |
740 | MODULE_AUTHOR("Mauro Carvalho Chehab <mchehab@infradead.org>"); | 744 | MODULE_AUTHOR("Mauro Carvalho Chehab <mchehab@redhat.com>"); |
741 | MODULE_DESCRIPTION("Em28xx Audio driver"); | 745 | MODULE_DESCRIPTION("Em28xx Audio driver"); |
742 | 746 | ||
743 | module_init(em28xx_alsa_register); | 747 | module_init(em28xx_alsa_register); |
diff --git a/drivers/media/video/em28xx/em28xx-cards.c b/drivers/media/video/em28xx/em28xx-cards.c index bbd67d754b59..c445bea2f27e 100644 --- a/drivers/media/video/em28xx/em28xx-cards.c +++ b/drivers/media/video/em28xx/em28xx-cards.c | |||
@@ -2846,6 +2846,16 @@ static int em28xx_init_dev(struct em28xx **devhandle, struct usb_device *udev, | |||
2846 | } | 2846 | } |
2847 | } | 2847 | } |
2848 | 2848 | ||
2849 | if (dev->is_audio_only) { | ||
2850 | errCode = em28xx_audio_setup(dev); | ||
2851 | if (errCode) | ||
2852 | return -ENODEV; | ||
2853 | em28xx_add_into_devlist(dev); | ||
2854 | em28xx_init_extension(dev); | ||
2855 | |||
2856 | return 0; | ||
2857 | } | ||
2858 | |||
2849 | /* Prepopulate cached GPO register content */ | 2859 | /* Prepopulate cached GPO register content */ |
2850 | retval = em28xx_read_reg(dev, dev->reg_gpo_num); | 2860 | retval = em28xx_read_reg(dev, dev->reg_gpo_num); |
2851 | if (retval >= 0) | 2861 | if (retval >= 0) |
@@ -2946,6 +2956,9 @@ fail_reg_devices: | |||
2946 | return retval; | 2956 | return retval; |
2947 | } | 2957 | } |
2948 | 2958 | ||
2959 | /* high bandwidth multiplier, as encoded in highspeed endpoint descriptors */ | ||
2960 | #define hb_mult(wMaxPacketSize) (1 + (((wMaxPacketSize) >> 11) & 0x03)) | ||
2961 | |||
2949 | /* | 2962 | /* |
2950 | * em28xx_usb_probe() | 2963 | * em28xx_usb_probe() |
2951 | * checks for supported devices | 2964 | * checks for supported devices |
@@ -2955,15 +2968,15 @@ static int em28xx_usb_probe(struct usb_interface *interface, | |||
2955 | { | 2968 | { |
2956 | const struct usb_endpoint_descriptor *endpoint; | 2969 | const struct usb_endpoint_descriptor *endpoint; |
2957 | struct usb_device *udev; | 2970 | struct usb_device *udev; |
2958 | struct usb_interface *uif; | ||
2959 | struct em28xx *dev = NULL; | 2971 | struct em28xx *dev = NULL; |
2960 | int retval; | 2972 | int retval; |
2961 | int i, nr, ifnum, isoc_pipe; | 2973 | bool is_audio_only = false, has_audio = false; |
2974 | int i, nr, isoc_pipe; | ||
2975 | const int ifnum = interface->altsetting[0].desc.bInterfaceNumber; | ||
2962 | char *speed; | 2976 | char *speed; |
2963 | char descr[255] = ""; | 2977 | char descr[255] = ""; |
2964 | 2978 | ||
2965 | udev = usb_get_dev(interface_to_usbdev(interface)); | 2979 | udev = usb_get_dev(interface_to_usbdev(interface)); |
2966 | ifnum = interface->altsetting[0].desc.bInterfaceNumber; | ||
2967 | 2980 | ||
2968 | /* Check to see next free device and mark as used */ | 2981 | /* Check to see next free device and mark as used */ |
2969 | nr = find_first_zero_bit(&em28xx_devused, EM28XX_MAXBOARDS); | 2982 | nr = find_first_zero_bit(&em28xx_devused, EM28XX_MAXBOARDS); |
@@ -2983,6 +2996,19 @@ static int em28xx_usb_probe(struct usb_interface *interface, | |||
2983 | goto err; | 2996 | goto err; |
2984 | } | 2997 | } |
2985 | 2998 | ||
2999 | /* Get endpoints */ | ||
3000 | for (i = 0; i < interface->num_altsetting; i++) { | ||
3001 | int ep; | ||
3002 | |||
3003 | for (ep = 0; ep < interface->altsetting[i].desc.bNumEndpoints; ep++) { | ||
3004 | struct usb_host_endpoint *e; | ||
3005 | e = &interface->altsetting[i].endpoint[ep]; | ||
3006 | |||
3007 | if (e->desc.bEndpointAddress == 0x83) | ||
3008 | has_audio = true; | ||
3009 | } | ||
3010 | } | ||
3011 | |||
2986 | endpoint = &interface->cur_altsetting->endpoint[0].desc; | 3012 | endpoint = &interface->cur_altsetting->endpoint[0].desc; |
2987 | 3013 | ||
2988 | /* check if the device has the iso in endpoint at the correct place */ | 3014 | /* check if the device has the iso in endpoint at the correct place */ |
@@ -3002,19 +3028,22 @@ static int em28xx_usb_probe(struct usb_interface *interface, | |||
3002 | check_interface = 0; | 3028 | check_interface = 0; |
3003 | 3029 | ||
3004 | if (!check_interface) { | 3030 | if (!check_interface) { |
3005 | em28xx_err(DRIVER_NAME " video device (%04x:%04x): " | 3031 | if (has_audio) { |
3006 | "interface %i, class %i found.\n", | 3032 | is_audio_only = true; |
3007 | le16_to_cpu(udev->descriptor.idVendor), | 3033 | } else { |
3008 | le16_to_cpu(udev->descriptor.idProduct), | 3034 | em28xx_err(DRIVER_NAME " video device (%04x:%04x): " |
3009 | ifnum, | 3035 | "interface %i, class %i found.\n", |
3010 | interface->altsetting[0].desc.bInterfaceClass); | 3036 | le16_to_cpu(udev->descriptor.idVendor), |
3011 | 3037 | le16_to_cpu(udev->descriptor.idProduct), | |
3012 | em28xx_err(DRIVER_NAME " This is an anciliary " | 3038 | ifnum, |
3013 | "interface not used by the driver\n"); | 3039 | interface->altsetting[0].desc.bInterfaceClass); |
3014 | 3040 | em28xx_err(DRIVER_NAME " This is an anciliary " | |
3015 | em28xx_devused &= ~(1<<nr); | 3041 | "interface not used by the driver\n"); |
3016 | retval = -ENODEV; | 3042 | |
3017 | goto err; | 3043 | em28xx_devused &= ~(1<<nr); |
3044 | retval = -ENODEV; | ||
3045 | goto err; | ||
3046 | } | ||
3018 | } | 3047 | } |
3019 | } | 3048 | } |
3020 | 3049 | ||
@@ -3044,8 +3073,8 @@ static int em28xx_usb_probe(struct usb_interface *interface, | |||
3044 | if (*descr) | 3073 | if (*descr) |
3045 | strlcat(descr, " ", sizeof(descr)); | 3074 | strlcat(descr, " ", sizeof(descr)); |
3046 | 3075 | ||
3047 | printk(DRIVER_NAME ": New device %s@ %s Mbps " | 3076 | printk(KERN_INFO DRIVER_NAME |
3048 | "(%04x:%04x, interface %d, class %d)\n", | 3077 | ": New device %s@ %s Mbps (%04x:%04x, interface %d, class %d)\n", |
3049 | descr, | 3078 | descr, |
3050 | speed, | 3079 | speed, |
3051 | le16_to_cpu(udev->descriptor.idVendor), | 3080 | le16_to_cpu(udev->descriptor.idVendor), |
@@ -3053,6 +3082,11 @@ static int em28xx_usb_probe(struct usb_interface *interface, | |||
3053 | ifnum, | 3082 | ifnum, |
3054 | interface->altsetting->desc.bInterfaceNumber); | 3083 | interface->altsetting->desc.bInterfaceNumber); |
3055 | 3084 | ||
3085 | if (has_audio) | ||
3086 | printk(KERN_INFO DRIVER_NAME | ||
3087 | ": Audio Vendor Class interface %i found\n", | ||
3088 | ifnum); | ||
3089 | |||
3056 | /* | 3090 | /* |
3057 | * Make sure we have 480 Mbps of bandwidth, otherwise things like | 3091 | * Make sure we have 480 Mbps of bandwidth, otherwise things like |
3058 | * video stream wouldn't likely work, since 12 Mbps is generally | 3092 | * video stream wouldn't likely work, since 12 Mbps is generally |
@@ -3088,10 +3122,13 @@ static int em28xx_usb_probe(struct usb_interface *interface, | |||
3088 | dev->devno = nr; | 3122 | dev->devno = nr; |
3089 | dev->model = id->driver_info; | 3123 | dev->model = id->driver_info; |
3090 | dev->alt = -1; | 3124 | dev->alt = -1; |
3125 | dev->is_audio_only = is_audio_only; | ||
3126 | dev->has_alsa_audio = has_audio; | ||
3127 | dev->audio_ifnum = ifnum; | ||
3091 | 3128 | ||
3092 | /* Checks if audio is provided by some interface */ | 3129 | /* Checks if audio is provided by some interface */ |
3093 | for (i = 0; i < udev->config->desc.bNumInterfaces; i++) { | 3130 | for (i = 0; i < udev->config->desc.bNumInterfaces; i++) { |
3094 | uif = udev->config->interface[i]; | 3131 | struct usb_interface *uif = udev->config->interface[i]; |
3095 | if (uif->altsetting[0].desc.bInterfaceClass == USB_CLASS_AUDIO) { | 3132 | if (uif->altsetting[0].desc.bInterfaceClass == USB_CLASS_AUDIO) { |
3096 | dev->has_audio_class = 1; | 3133 | dev->has_audio_class = 1; |
3097 | break; | 3134 | break; |
@@ -3099,9 +3136,7 @@ static int em28xx_usb_probe(struct usb_interface *interface, | |||
3099 | } | 3136 | } |
3100 | 3137 | ||
3101 | /* compute alternate max packet sizes */ | 3138 | /* compute alternate max packet sizes */ |
3102 | uif = udev->actconfig->interface[0]; | 3139 | dev->num_alt = interface->num_altsetting; |
3103 | |||
3104 | dev->num_alt = uif->num_altsetting; | ||
3105 | dev->alt_max_pkt_size = kmalloc(32 * dev->num_alt, GFP_KERNEL); | 3140 | dev->alt_max_pkt_size = kmalloc(32 * dev->num_alt, GFP_KERNEL); |
3106 | 3141 | ||
3107 | if (dev->alt_max_pkt_size == NULL) { | 3142 | if (dev->alt_max_pkt_size == NULL) { |
@@ -3113,14 +3148,21 @@ static int em28xx_usb_probe(struct usb_interface *interface, | |||
3113 | } | 3148 | } |
3114 | 3149 | ||
3115 | for (i = 0; i < dev->num_alt ; i++) { | 3150 | for (i = 0; i < dev->num_alt ; i++) { |
3116 | u16 tmp = le16_to_cpu(uif->altsetting[i].endpoint[isoc_pipe].desc.wMaxPacketSize); | 3151 | u16 tmp = le16_to_cpu(interface->altsetting[i].endpoint[isoc_pipe].desc.wMaxPacketSize); |
3117 | dev->alt_max_pkt_size[i] = | 3152 | unsigned int size = tmp & 0x7ff; |
3118 | (tmp & 0x07ff) * (((tmp & 0x1800) >> 11) + 1); | 3153 | |
3154 | if (udev->speed == USB_SPEED_HIGH) | ||
3155 | size = size * hb_mult(tmp); | ||
3156 | |||
3157 | dev->alt_max_pkt_size[i] = size; | ||
3119 | } | 3158 | } |
3120 | 3159 | ||
3121 | if ((card[nr] >= 0) && (card[nr] < em28xx_bcount)) | 3160 | if ((card[nr] >= 0) && (card[nr] < em28xx_bcount)) |
3122 | dev->model = card[nr]; | 3161 | dev->model = card[nr]; |
3123 | 3162 | ||
3163 | /* save our data pointer in this interface device */ | ||
3164 | usb_set_intfdata(interface, dev); | ||
3165 | |||
3124 | /* allocate device struct */ | 3166 | /* allocate device struct */ |
3125 | mutex_init(&dev->lock); | 3167 | mutex_init(&dev->lock); |
3126 | mutex_lock(&dev->lock); | 3168 | mutex_lock(&dev->lock); |
@@ -3132,9 +3174,6 @@ static int em28xx_usb_probe(struct usb_interface *interface, | |||
3132 | goto err; | 3174 | goto err; |
3133 | } | 3175 | } |
3134 | 3176 | ||
3135 | /* save our data pointer in this interface device */ | ||
3136 | usb_set_intfdata(interface, dev); | ||
3137 | |||
3138 | request_modules(dev); | 3177 | request_modules(dev); |
3139 | 3178 | ||
3140 | /* Should be the last thing to do, to avoid newer udev's to | 3179 | /* Should be the last thing to do, to avoid newer udev's to |
@@ -3163,6 +3202,13 @@ static void em28xx_usb_disconnect(struct usb_interface *interface) | |||
3163 | if (!dev) | 3202 | if (!dev) |
3164 | return; | 3203 | return; |
3165 | 3204 | ||
3205 | if (dev->is_audio_only) { | ||
3206 | mutex_lock(&dev->lock); | ||
3207 | em28xx_close_extension(dev); | ||
3208 | mutex_unlock(&dev->lock); | ||
3209 | return; | ||
3210 | } | ||
3211 | |||
3166 | em28xx_info("disconnecting %s\n", dev->vdev->name); | 3212 | em28xx_info("disconnecting %s\n", dev->vdev->name); |
3167 | 3213 | ||
3168 | flush_request_modules(dev); | 3214 | flush_request_modules(dev); |
diff --git a/drivers/media/video/em28xx/em28xx-core.c b/drivers/media/video/em28xx/em28xx-core.c index 752d4ed7f828..16c9b73b1c3f 100644 --- a/drivers/media/video/em28xx/em28xx-core.c +++ b/drivers/media/video/em28xx/em28xx-core.c | |||
@@ -499,17 +499,13 @@ int em28xx_audio_setup(struct em28xx *dev) | |||
499 | if (dev->chip_id == CHIP_ID_EM2870 || dev->chip_id == CHIP_ID_EM2874 | 499 | if (dev->chip_id == CHIP_ID_EM2870 || dev->chip_id == CHIP_ID_EM2874 |
500 | || dev->chip_id == CHIP_ID_EM28174) { | 500 | || dev->chip_id == CHIP_ID_EM28174) { |
501 | /* Digital only device - don't load any alsa module */ | 501 | /* Digital only device - don't load any alsa module */ |
502 | dev->audio_mode.has_audio = 0; | 502 | dev->audio_mode.has_audio = false; |
503 | dev->has_audio_class = 0; | 503 | dev->has_audio_class = false; |
504 | dev->has_alsa_audio = 0; | 504 | dev->has_alsa_audio = false; |
505 | return 0; | 505 | return 0; |
506 | } | 506 | } |
507 | 507 | ||
508 | /* If device doesn't support Usb Audio Class, use vendor class */ | 508 | dev->audio_mode.has_audio = true; |
509 | if (!dev->has_audio_class) | ||
510 | dev->has_alsa_audio = 1; | ||
511 | |||
512 | dev->audio_mode.has_audio = 1; | ||
513 | 509 | ||
514 | /* See how this device is configured */ | 510 | /* See how this device is configured */ |
515 | cfg = em28xx_read_reg(dev, EM28XX_R00_CHIPCFG); | 511 | cfg = em28xx_read_reg(dev, EM28XX_R00_CHIPCFG); |
@@ -519,8 +515,8 @@ int em28xx_audio_setup(struct em28xx *dev) | |||
519 | cfg = EM28XX_CHIPCFG_AC97; /* Be conservative */ | 515 | cfg = EM28XX_CHIPCFG_AC97; /* Be conservative */ |
520 | } else if ((cfg & EM28XX_CHIPCFG_AUDIOMASK) == 0x00) { | 516 | } else if ((cfg & EM28XX_CHIPCFG_AUDIOMASK) == 0x00) { |
521 | /* The device doesn't have vendor audio at all */ | 517 | /* The device doesn't have vendor audio at all */ |
522 | dev->has_alsa_audio = 0; | 518 | dev->has_alsa_audio = false; |
523 | dev->audio_mode.has_audio = 0; | 519 | dev->audio_mode.has_audio = false; |
524 | return 0; | 520 | return 0; |
525 | } else if ((cfg & EM28XX_CHIPCFG_AUDIOMASK) == | 521 | } else if ((cfg & EM28XX_CHIPCFG_AUDIOMASK) == |
526 | EM28XX_CHIPCFG_I2S_3_SAMPRATES) { | 522 | EM28XX_CHIPCFG_I2S_3_SAMPRATES) { |
@@ -549,8 +545,8 @@ int em28xx_audio_setup(struct em28xx *dev) | |||
549 | */ | 545 | */ |
550 | em28xx_warn("AC97 chip type couldn't be determined\n"); | 546 | em28xx_warn("AC97 chip type couldn't be determined\n"); |
551 | dev->audio_mode.ac97 = EM28XX_NO_AC97; | 547 | dev->audio_mode.ac97 = EM28XX_NO_AC97; |
552 | dev->has_alsa_audio = 0; | 548 | dev->has_alsa_audio = false; |
553 | dev->audio_mode.has_audio = 0; | 549 | dev->audio_mode.has_audio = false; |
554 | goto init_audio; | 550 | goto init_audio; |
555 | } | 551 | } |
556 | 552 | ||
diff --git a/drivers/media/video/em28xx/em28xx.h b/drivers/media/video/em28xx/em28xx.h index f9b77b4c90e4..e03849fd3717 100644 --- a/drivers/media/video/em28xx/em28xx.h +++ b/drivers/media/video/em28xx/em28xx.h | |||
@@ -487,6 +487,8 @@ struct em28xx { | |||
487 | int devno; /* marks the number of this device */ | 487 | int devno; /* marks the number of this device */ |
488 | enum em28xx_chip_id chip_id; | 488 | enum em28xx_chip_id chip_id; |
489 | 489 | ||
490 | int audio_ifnum; | ||
491 | |||
490 | struct v4l2_device v4l2_dev; | 492 | struct v4l2_device v4l2_dev; |
491 | struct em28xx_board board; | 493 | struct em28xx_board board; |
492 | 494 | ||
@@ -503,6 +505,7 @@ struct em28xx { | |||
503 | 505 | ||
504 | unsigned int has_audio_class:1; | 506 | unsigned int has_audio_class:1; |
505 | unsigned int has_alsa_audio:1; | 507 | unsigned int has_alsa_audio:1; |
508 | unsigned int is_audio_only:1; | ||
506 | 509 | ||
507 | /* Controls audio streaming */ | 510 | /* Controls audio streaming */ |
508 | struct work_struct wq_trigger; /* Trigger to start/stop audio for alsa module */ | 511 | struct work_struct wq_trigger; /* Trigger to start/stop audio for alsa module */ |