aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/media/video/cx18
diff options
context:
space:
mode:
authorDevin Heitmueller <dheitmueller@kernellabs.com>2009-11-19 23:15:54 -0500
committerMauro Carvalho Chehab <mchehab@redhat.com>2010-02-26 13:10:43 -0500
commitd68b687b1e322e7325b1458d799e8234997e4ccd (patch)
tree57b63b7f8ec2505582a944df31e6139f60c9265a /drivers/media/video/cx18
parent4a8cfe6a5c158133f57c2e8476f259366d4bdc4d (diff)
V4L/DVB: cx18: rework cx18-alsa module loading to support automatic loading
Restructure the way the module gets loaded so that it gets loaded automatically when cx18 is loaded, and make it work properly if there are multiple cards present (since the old code would only take one opportunity to connect to cx18 instances when the module first loaded). This work was sponsored by ONELAN Limited. Signed-off-by: Devin Heitmueller <dheitmueller@kernellabs.com> Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
Diffstat (limited to 'drivers/media/video/cx18')
-rw-r--r--drivers/media/video/cx18/cx18-alsa-main.c38
-rw-r--r--drivers/media/video/cx18/cx18-driver.c34
-rw-r--r--drivers/media/video/cx18/cx18-driver.h6
3 files changed, 46 insertions, 32 deletions
diff --git a/drivers/media/video/cx18/cx18-alsa-main.c b/drivers/media/video/cx18/cx18-alsa-main.c
index 3c339774522a..6433ff0ad859 100644
--- a/drivers/media/video/cx18/cx18-alsa-main.c
+++ b/drivers/media/video/cx18/cx18-alsa-main.c
@@ -190,11 +190,9 @@ err_exit:
190 return ret; 190 return ret;
191} 191}
192 192
193static int __init cx18_alsa_init_callback(struct device *dev, void *data) 193int cx18_alsa_load(struct cx18 *cx)
194{ 194{
195 struct v4l2_device *v4l2_dev = dev_get_drvdata(dev); 195 struct v4l2_device *v4l2_dev = &cx->v4l2_dev;
196 int *count = data;
197 struct cx18 *cx;
198 struct cx18_stream *s; 196 struct cx18_stream *s;
199 197
200 if (v4l2_dev == NULL) { 198 if (v4l2_dev == NULL) {
@@ -227,41 +225,16 @@ static int __init cx18_alsa_init_callback(struct device *dev, void *data)
227 __func__); 225 __func__);
228 } else { 226 } else {
229 CX18_DEBUG_ALSA_INFO("%s: created cx18 ALSA interface instance " 227 CX18_DEBUG_ALSA_INFO("%s: created cx18 ALSA interface instance "
230 "%d\n", __func__, *count); 228 "\n", __func__);
231 (*count)++;
232 } 229 }
233 return 0; 230 return 0;
234} 231}
235 232
236static int __init cx18_alsa_init(void) 233static int __init cx18_alsa_init(void)
237{ 234{
238 struct device_driver *drv;
239 int count = 0;
240 int ret;
241
242 printk(KERN_INFO "cx18-alsa: module loading...\n"); 235 printk(KERN_INFO "cx18-alsa: module loading...\n");
243 236 cx18_ext_init = &cx18_alsa_load;
244 drv = driver_find("cx18", &pci_bus_type); 237 return 0;
245 if (drv == NULL) {
246 printk("cx18-alsa: drv was null\n");
247 return -ENODEV;
248 }
249 ret = driver_for_each_device(drv, NULL, &count,
250 cx18_alsa_init_callback);
251 put_driver(drv);
252
253 if (count == 0) {
254 printk(KERN_ERR "cx18-alsa: no cx18 cards found with a PCM "
255 "capture stream allocated\n");
256 ret = -ENODEV;
257 } else {
258 printk(KERN_INFO "cx18-alsa: ALSA interface(s) created for %d "
259 "cx18 card(s)\n", count);
260 ret = 0;
261 }
262
263 printk(KERN_INFO "cx18-alsa: module load complete\n");
264 return ret;
265} 238}
266 239
267static void snd_cx18_exit(struct snd_cx18_card *cxsc) 240static void snd_cx18_exit(struct snd_cx18_card *cxsc)
@@ -308,6 +281,7 @@ static void cx18_alsa_exit(void)
308 ret = driver_for_each_device(drv, NULL, NULL, cx18_alsa_exit_callback); 281 ret = driver_for_each_device(drv, NULL, NULL, cx18_alsa_exit_callback);
309 put_driver(drv); 282 put_driver(drv);
310 283
284 cx18_ext_init = NULL;
311 printk(KERN_INFO "cx18-alsa: module unload complete\n"); 285 printk(KERN_INFO "cx18-alsa: module unload complete\n");
312} 286}
313 287
diff --git a/drivers/media/video/cx18/cx18-driver.c b/drivers/media/video/cx18/cx18-driver.c
index 458f5f072374..870c43e6e2f9 100644
--- a/drivers/media/video/cx18/cx18-driver.c
+++ b/drivers/media/video/cx18/cx18-driver.c
@@ -47,6 +47,10 @@
47 setting this to 1 you ensure that radio0 is now also radio1. */ 47 setting this to 1 you ensure that radio0 is now also radio1. */
48int cx18_first_minor; 48int cx18_first_minor;
49 49
50/* Callback for registering extensions */
51int (*cx18_ext_init)(struct cx18 *);
52EXPORT_SYMBOL(cx18_ext_init);
53
50/* add your revision and whatnot here */ 54/* add your revision and whatnot here */
51static struct pci_device_id cx18_pci_tbl[] __devinitdata = { 55static struct pci_device_id cx18_pci_tbl[] __devinitdata = {
52 {PCI_VENDOR_ID_CX, PCI_DEVICE_ID_CX23418, 56 {PCI_VENDOR_ID_CX, PCI_DEVICE_ID_CX23418,
@@ -243,6 +247,9 @@ MODULE_LICENSE("GPL");
243 247
244MODULE_VERSION(CX18_VERSION); 248MODULE_VERSION(CX18_VERSION);
245 249
250/* Forward Declaration */
251static void request_modules(struct cx18 *dev);
252
246/* Generic utility functions */ 253/* Generic utility functions */
247int cx18_msleep_timeout(unsigned int msecs, int intr) 254int cx18_msleep_timeout(unsigned int msecs, int intr)
248{ 255{
@@ -1049,6 +1056,10 @@ static int __devinit cx18_probe(struct pci_dev *pci_dev,
1049 } 1056 }
1050 1057
1051 CX18_INFO("Initialized card: %s\n", cx->card_name); 1058 CX18_INFO("Initialized card: %s\n", cx->card_name);
1059
1060 /* Load cx18 submodules (cx18-alsa) */
1061 request_modules(cx);
1062
1052 return 0; 1063 return 0;
1053 1064
1054free_streams: 1065free_streams:
@@ -1237,6 +1248,29 @@ static void cx18_remove(struct pci_dev *pci_dev)
1237 kfree(cx); 1248 kfree(cx);
1238} 1249}
1239 1250
1251
1252#if defined(CONFIG_MODULES) && defined(MODULE)
1253static void request_module_async(struct work_struct *work)
1254{
1255 struct cx18 *dev=container_of(work, struct cx18, request_module_wk);
1256
1257 /* Make sure cx18-alsa module is loaded */
1258 request_module("cx18-alsa");
1259
1260 /* Initialize cx18-alsa for this instance of the cx18 device */
1261 if (cx18_ext_init != NULL)
1262 cx18_ext_init(dev);
1263}
1264
1265static void request_modules(struct cx18 *dev)
1266{
1267 INIT_WORK(&dev->request_module_wk, request_module_async);
1268 schedule_work(&dev->request_module_wk);
1269}
1270#else
1271#define request_modules(dev)
1272#endif /* CONFIG_MODULES */
1273
1240/* define a pci_driver for card detection */ 1274/* define a pci_driver for card detection */
1241static struct pci_driver cx18_pci_driver = { 1275static struct pci_driver cx18_pci_driver = {
1242 .name = "cx18", 1276 .name = "cx18",
diff --git a/drivers/media/video/cx18/cx18-driver.h b/drivers/media/video/cx18/cx18-driver.h
index 22634cf6a96a..23ad6d548dc5 100644
--- a/drivers/media/video/cx18/cx18-driver.h
+++ b/drivers/media/video/cx18/cx18-driver.h
@@ -637,6 +637,9 @@ struct cx18 {
637 u32 active_input; 637 u32 active_input;
638 v4l2_std_id std; 638 v4l2_std_id std;
639 v4l2_std_id tuner_std; /* The norm of the tuner (fixed) */ 639 v4l2_std_id tuner_std; /* The norm of the tuner (fixed) */
640
641 /* Used for cx18-alsa module loading */
642 struct work_struct request_module_wk;
640}; 643};
641 644
642static inline struct cx18 *to_cx18(struct v4l2_device *v4l2_dev) 645static inline struct cx18 *to_cx18(struct v4l2_device *v4l2_dev)
@@ -644,6 +647,9 @@ static inline struct cx18 *to_cx18(struct v4l2_device *v4l2_dev)
644 return container_of(v4l2_dev, struct cx18, v4l2_dev); 647 return container_of(v4l2_dev, struct cx18, v4l2_dev);
645} 648}
646 649
650/* cx18 extensions to be loaded */
651extern int (*cx18_ext_init)(struct cx18 *);
652
647/* Globals */ 653/* Globals */
648extern int cx18_first_minor; 654extern int cx18_first_minor;
649 655