V4L/DVB (6952): Add code for autoloading em28xx-alsa, if needed
Older em28xx devices does implement standard Audio Class. However, on newer devices, this were replaced by a Vendor Class. This patch autodetects that an em28xx lacks Audio Class and auto-loads em28xx-alsa, for the devices that implements only a Vendor Class. For devices with Audio Class, snd-usb-audio module will provide an ALSA interface. This patch uses the request_module_async function as defined on cx88-mpeg.c, originally wrote by Markus Rechberger. Signed-off-by: Mauro Carvalho Chehab <mchehab@infradead.org>
This commit is contained in:
parent
6d79468dd8
commit
d7448a8d9d
|
@ -472,7 +472,6 @@ static struct em28xx_ops audio_ops = {
|
|||
|
||||
static int __init em28xx_alsa_register(void)
|
||||
{
|
||||
request_module("em28xx");
|
||||
return em28xx_register_extension(&audio_ops);
|
||||
}
|
||||
|
||||
|
|
|
@ -1668,6 +1668,10 @@ static int em28xx_init_dev(struct em28xx **devhandle, struct usb_device *udev,
|
|||
dev->em28xx_read_reg_req = em28xx_read_reg_req;
|
||||
dev->is_em2800 = em28xx_boards[dev->model].is_em2800;
|
||||
|
||||
errCode = em28xx_read_reg(dev, CHIPID_REG);
|
||||
if (errCode >= 0)
|
||||
em28xx_info("em28xx chip ID = %d\n", errCode);
|
||||
|
||||
em28xx_pre_card_setup(dev);
|
||||
|
||||
errCode = em28xx_config(dev);
|
||||
|
@ -1794,6 +1798,25 @@ static int em28xx_init_dev(struct em28xx **devhandle, struct usb_device *udev,
|
|||
return 0;
|
||||
}
|
||||
|
||||
#if defined(CONFIG_MODULES) && defined(MODULE)
|
||||
static void request_module_async(struct work_struct *work)
|
||||
{
|
||||
struct em28xx *dev = container_of(work,
|
||||
struct em28xx, request_module_wk);
|
||||
|
||||
if (!dev->has_audio_class)
|
||||
request_module("em28xx-alsa");
|
||||
}
|
||||
|
||||
static void request_modules(struct em28xx *dev)
|
||||
{
|
||||
INIT_WORK(&dev->request_module_wk, request_module_async);
|
||||
schedule_work(&dev->request_module_wk);
|
||||
}
|
||||
#else
|
||||
#define request_modules(dev)
|
||||
#endif /* CONFIG_MODULES */
|
||||
|
||||
/*
|
||||
* em28xx_usb_probe()
|
||||
* checks for supported devices
|
||||
|
@ -1864,6 +1887,18 @@ static int em28xx_usb_probe(struct usb_interface *interface,
|
|||
dev->devno = nr;
|
||||
dev->model = id->driver_info;
|
||||
|
||||
/* Checks if audio is provided by some interface */
|
||||
for (i = 0; i < udev->config->desc.bNumInterfaces; i++) {
|
||||
uif = udev->config->interface[i];
|
||||
if (uif->altsetting[0].desc.bInterfaceClass == USB_CLASS_AUDIO) {
|
||||
dev->has_audio_class = 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
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];
|
||||
|
||||
|
@ -1900,6 +1935,9 @@ static int em28xx_usb_probe(struct usb_interface *interface,
|
|||
|
||||
/* save our data pointer in this interface device */
|
||||
usb_set_intfdata(interface, dev);
|
||||
|
||||
request_modules(dev);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
|
@ -246,6 +246,7 @@ struct em28xx {
|
|||
unsigned int has_msp34xx:1;
|
||||
unsigned int has_tda9887:1;
|
||||
unsigned int stream_on:1; /* Locks streams */
|
||||
unsigned int has_audio_class:1;
|
||||
|
||||
int video_inputs; /* number of video inputs */
|
||||
struct list_head devlist;
|
||||
|
@ -295,6 +296,8 @@ struct em28xx {
|
|||
enum em28xx_stream_state stream;
|
||||
enum em28xx_io_method io;
|
||||
|
||||
struct work_struct request_module_wk;
|
||||
|
||||
/* locks */
|
||||
struct mutex lock;
|
||||
spinlock_t queue_lock;
|
||||
|
|
Loading…
Reference in a new issue