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>
diff --git a/drivers/media/video/em28xx/em28xx-video.c b/drivers/media/video/em28xx/em28xx-video.c
index caa4757..a03e9d7 100644
--- a/drivers/media/video/em28xx/em28xx-video.c
+++ b/drivers/media/video/em28xx/em28xx-video.c
@@ -1668,6 +1668,10 @@
 	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 @@
 	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 @@
 	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 @@
 
 	/* save our data pointer in this interface device */
 	usb_set_intfdata(interface, dev);
+
+	request_modules(dev);
+
 	return 0;
 }