From d7448a8d9d06ca2ca4fd1f17404450ecba8bea3a Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Sat, 5 Jan 2008 09:59:03 -0300 Subject: 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 --- drivers/media/video/em28xx/em28xx-audio.c | 1 - drivers/media/video/em28xx/em28xx-video.c | 38 +++++++++++++++++++++++++++++++ drivers/media/video/em28xx/em28xx.h | 3 +++ 3 files changed, 41 insertions(+), 1 deletion(-) diff --git a/drivers/media/video/em28xx/em28xx-audio.c b/drivers/media/video/em28xx/em28xx-audio.c index c91ff52aefa..941357c4f3f 100644 --- a/drivers/media/video/em28xx/em28xx-audio.c +++ b/drivers/media/video/em28xx/em28xx-audio.c @@ -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); } diff --git a/drivers/media/video/em28xx/em28xx-video.c b/drivers/media/video/em28xx/em28xx-video.c index caa4757b7eb..a03e9d724b5 100644 --- a/drivers/media/video/em28xx/em28xx-video.c +++ b/drivers/media/video/em28xx/em28xx-video.c @@ -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; } diff --git a/drivers/media/video/em28xx/em28xx.h b/drivers/media/video/em28xx/em28xx.h index c2d9ae0ac61..9eb213132da 100644 --- a/drivers/media/video/em28xx/em28xx.h +++ b/drivers/media/video/em28xx/em28xx.h @@ -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; -- cgit v1.2.3