diff options
author | Mauro Carvalho Chehab <mchehab@infradead.org> | 2008-01-05 07:59:03 -0500 |
---|---|---|
committer | Mauro Carvalho Chehab <mchehab@infradead.org> | 2008-01-25 16:04:32 -0500 |
commit | d7448a8d9d06ca2ca4fd1f17404450ecba8bea3a (patch) | |
tree | 61be9e95bdf31c4cde511c67ce2f526bb816d0f8 /drivers/media/video/em28xx | |
parent | 6d79468dd8537530f4150e76ed9b4b63f80571c6 (diff) |
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>
Diffstat (limited to 'drivers/media/video/em28xx')
-rw-r--r-- | drivers/media/video/em28xx/em28xx-audio.c | 1 | ||||
-rw-r--r-- | drivers/media/video/em28xx/em28xx-video.c | 38 | ||||
-rw-r--r-- | drivers/media/video/em28xx/em28xx.h | 3 |
3 files changed, 41 insertions, 1 deletions
diff --git a/drivers/media/video/em28xx/em28xx-audio.c b/drivers/media/video/em28xx/em28xx-audio.c index c91ff52aefad..941357c4f3f5 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 = { | |||
472 | 472 | ||
473 | static int __init em28xx_alsa_register(void) | 473 | static int __init em28xx_alsa_register(void) |
474 | { | 474 | { |
475 | request_module("em28xx"); | ||
476 | return em28xx_register_extension(&audio_ops); | 475 | return em28xx_register_extension(&audio_ops); |
477 | } | 476 | } |
478 | 477 | ||
diff --git a/drivers/media/video/em28xx/em28xx-video.c b/drivers/media/video/em28xx/em28xx-video.c index caa4757b7eb6..a03e9d724b5f 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, | |||
1668 | dev->em28xx_read_reg_req = em28xx_read_reg_req; | 1668 | dev->em28xx_read_reg_req = em28xx_read_reg_req; |
1669 | dev->is_em2800 = em28xx_boards[dev->model].is_em2800; | 1669 | dev->is_em2800 = em28xx_boards[dev->model].is_em2800; |
1670 | 1670 | ||
1671 | errCode = em28xx_read_reg(dev, CHIPID_REG); | ||
1672 | if (errCode >= 0) | ||
1673 | em28xx_info("em28xx chip ID = %d\n", errCode); | ||
1674 | |||
1671 | em28xx_pre_card_setup(dev); | 1675 | em28xx_pre_card_setup(dev); |
1672 | 1676 | ||
1673 | errCode = em28xx_config(dev); | 1677 | errCode = em28xx_config(dev); |
@@ -1794,6 +1798,25 @@ static int em28xx_init_dev(struct em28xx **devhandle, struct usb_device *udev, | |||
1794 | return 0; | 1798 | return 0; |
1795 | } | 1799 | } |
1796 | 1800 | ||
1801 | #if defined(CONFIG_MODULES) && defined(MODULE) | ||
1802 | static void request_module_async(struct work_struct *work) | ||
1803 | { | ||
1804 | struct em28xx *dev = container_of(work, | ||
1805 | struct em28xx, request_module_wk); | ||
1806 | |||
1807 | if (!dev->has_audio_class) | ||
1808 | request_module("em28xx-alsa"); | ||
1809 | } | ||
1810 | |||
1811 | static void request_modules(struct em28xx *dev) | ||
1812 | { | ||
1813 | INIT_WORK(&dev->request_module_wk, request_module_async); | ||
1814 | schedule_work(&dev->request_module_wk); | ||
1815 | } | ||
1816 | #else | ||
1817 | #define request_modules(dev) | ||
1818 | #endif /* CONFIG_MODULES */ | ||
1819 | |||
1797 | /* | 1820 | /* |
1798 | * em28xx_usb_probe() | 1821 | * em28xx_usb_probe() |
1799 | * checks for supported devices | 1822 | * checks for supported devices |
@@ -1864,6 +1887,18 @@ static int em28xx_usb_probe(struct usb_interface *interface, | |||
1864 | dev->devno = nr; | 1887 | dev->devno = nr; |
1865 | dev->model = id->driver_info; | 1888 | dev->model = id->driver_info; |
1866 | 1889 | ||
1890 | /* Checks if audio is provided by some interface */ | ||
1891 | for (i = 0; i < udev->config->desc.bNumInterfaces; i++) { | ||
1892 | uif = udev->config->interface[i]; | ||
1893 | if (uif->altsetting[0].desc.bInterfaceClass == USB_CLASS_AUDIO) { | ||
1894 | dev->has_audio_class = 1; | ||
1895 | break; | ||
1896 | } | ||
1897 | } | ||
1898 | |||
1899 | printk(KERN_INFO DRIVER_NAME " %s usb audio class\n", | ||
1900 | dev->has_audio_class ? "Has" : "Doesn't have"); | ||
1901 | |||
1867 | /* compute alternate max packet sizes */ | 1902 | /* compute alternate max packet sizes */ |
1868 | uif = udev->actconfig->interface[0]; | 1903 | uif = udev->actconfig->interface[0]; |
1869 | 1904 | ||
@@ -1900,6 +1935,9 @@ static int em28xx_usb_probe(struct usb_interface *interface, | |||
1900 | 1935 | ||
1901 | /* save our data pointer in this interface device */ | 1936 | /* save our data pointer in this interface device */ |
1902 | usb_set_intfdata(interface, dev); | 1937 | usb_set_intfdata(interface, dev); |
1938 | |||
1939 | request_modules(dev); | ||
1940 | |||
1903 | return 0; | 1941 | return 0; |
1904 | } | 1942 | } |
1905 | 1943 | ||
diff --git a/drivers/media/video/em28xx/em28xx.h b/drivers/media/video/em28xx/em28xx.h index c2d9ae0ac618..9eb213132da1 100644 --- a/drivers/media/video/em28xx/em28xx.h +++ b/drivers/media/video/em28xx/em28xx.h | |||
@@ -246,6 +246,7 @@ struct em28xx { | |||
246 | unsigned int has_msp34xx:1; | 246 | unsigned int has_msp34xx:1; |
247 | unsigned int has_tda9887:1; | 247 | unsigned int has_tda9887:1; |
248 | unsigned int stream_on:1; /* Locks streams */ | 248 | unsigned int stream_on:1; /* Locks streams */ |
249 | unsigned int has_audio_class:1; | ||
249 | 250 | ||
250 | int video_inputs; /* number of video inputs */ | 251 | int video_inputs; /* number of video inputs */ |
251 | struct list_head devlist; | 252 | struct list_head devlist; |
@@ -295,6 +296,8 @@ struct em28xx { | |||
295 | enum em28xx_stream_state stream; | 296 | enum em28xx_stream_state stream; |
296 | enum em28xx_io_method io; | 297 | enum em28xx_io_method io; |
297 | 298 | ||
299 | struct work_struct request_module_wk; | ||
300 | |||
298 | /* locks */ | 301 | /* locks */ |
299 | struct mutex lock; | 302 | struct mutex lock; |
300 | spinlock_t queue_lock; | 303 | spinlock_t queue_lock; |