patch-2_6_7-vs1_9_1_12
[linux-2.6.git] / sound / core / sound.c
1 /*
2  *  Advanced Linux Sound Architecture
3  *  Copyright (c) by Jaroslav Kysela <perex@suse.cz>
4  *
5  *
6  *   This program is free software; you can redistribute it and/or modify
7  *   it under the terms of the GNU General Public License as published by
8  *   the Free Software Foundation; either version 2 of the License, or
9  *   (at your option) any later version.
10  *
11  *   This program is distributed in the hope that it will be useful,
12  *   but WITHOUT ANY WARRANTY; without even the implied warranty of
13  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  *   GNU General Public License for more details.
15  *
16  *   You should have received a copy of the GNU General Public License
17  *   along with this program; if not, write to the Free Software
18  *   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
19  *
20  */
21
22 #include <sound/driver.h>
23 #include <linux/init.h>
24 #include <linux/slab.h>
25 #include <linux/time.h>
26 #include <linux/moduleparam.h>
27 #include <sound/core.h>
28 #include <sound/minors.h>
29 #include <sound/info.h>
30 #include <sound/version.h>
31 #include <sound/control.h>
32 #include <sound/initval.h>
33 #include <linux/kmod.h>
34 #include <linux/devfs_fs_kernel.h>
35 #include <linux/device.h>
36
37 #define SNDRV_OS_MINORS 256
38
39 static int major = CONFIG_SND_MAJOR;
40 int snd_major;
41 static int cards_limit = 1;
42 static int device_mode = S_IFCHR | S_IRUGO | S_IWUGO;
43
44 MODULE_AUTHOR("Jaroslav Kysela <perex@suse.cz>");
45 MODULE_DESCRIPTION("Advanced Linux Sound Architecture driver for soundcards.");
46 MODULE_LICENSE("GPL");
47 MODULE_CLASSES("{sound}");
48 MODULE_SUPPORTED_DEVICE("sound");
49 module_param(major, int, 0444);
50 MODULE_PARM_DESC(major, "Major # for sound driver.");
51 MODULE_PARM_SYNTAX(major, "default:116,skill:devel");
52 module_param(cards_limit, int, 0444);
53 MODULE_PARM_DESC(cards_limit, "Count of auto-loadable soundcards.");
54 MODULE_PARM_SYNTAX(cards_limit, "default:8,skill:advanced");
55 MODULE_ALIAS_CHARDEV_MAJOR(CONFIG_SND_MAJOR);
56 #ifdef CONFIG_DEVFS_FS
57 module_param(device_mode, int, 0444);
58 MODULE_PARM_DESC(device_mode, "Device file permission mask for devfs.");
59 MODULE_PARM_SYNTAX(device_mode, "default:0666,base:8");
60 #endif
61 MODULE_ALIAS_CHARDEV_MAJOR(CONFIG_SND_MAJOR);
62
63 /* this one holds the actual max. card number currently available.
64  * as default, it's identical with cards_limit option.  when more
65  * modules are loaded manually, this limit number increases, too.
66  */
67 int snd_ecards_limit;
68
69 static struct list_head snd_minors_hash[SNDRV_CARDS];
70
71 static DECLARE_MUTEX(sound_mutex);
72
73 extern struct class_simple *sound_class;
74
75
76 #ifdef CONFIG_KMOD
77
78 /**
79  * snd_request_card - try to load the card module
80  * @card: the card number
81  *
82  * Tries to load the module "snd-card-X" for the given card number
83  * via KMOD.  Returns immediately if already loaded.
84  */
85 void snd_request_card(int card)
86 {
87         int locked;
88
89         if (! current->fs->root)
90                 return;
91         read_lock(&snd_card_rwlock);
92         locked = snd_cards_lock & (1 << card);
93         read_unlock(&snd_card_rwlock);
94         if (locked)
95                 return;
96         if (card < 0 || card >= cards_limit)
97                 return;
98         request_module("snd-card-%i", card);
99 }
100
101 static void snd_request_other(int minor)
102 {
103         char *str;
104
105         if (! current->fs->root)
106                 return;
107         switch (minor) {
108         case SNDRV_MINOR_SEQUENCER:     str = "snd-seq";        break;
109         case SNDRV_MINOR_TIMER:         str = "snd-timer";      break;
110         default:                        return;
111         }
112         request_module(str);
113 }
114
115 #endif                          /* request_module support */
116
117 static snd_minor_t *snd_minor_search(int minor)
118 {
119         struct list_head *list;
120         snd_minor_t *mptr;
121
122         list_for_each(list, &snd_minors_hash[SNDRV_MINOR_CARD(minor)]) {
123                 mptr = list_entry(list, snd_minor_t, list);
124                 if (mptr->number == minor)
125                         return mptr;
126         }
127         return NULL;
128 }
129
130 static int snd_open(struct inode *inode, struct file *file)
131 {
132         int minor = iminor(inode);
133         int card = SNDRV_MINOR_CARD(minor);
134         int dev = SNDRV_MINOR_DEVICE(minor);
135         snd_minor_t *mptr = NULL;
136         struct file_operations *old_fops;
137         int err = 0;
138
139         if (dev != SNDRV_MINOR_SEQUENCER && dev != SNDRV_MINOR_TIMER) {
140                 if (snd_cards[card] == NULL) {
141 #ifdef CONFIG_KMOD
142                         snd_request_card(card);
143                         if (snd_cards[card] == NULL)
144 #endif
145                                 return -ENODEV;
146                 }
147         } else {
148 #ifdef CONFIG_KMOD
149                 if ((mptr = snd_minor_search(minor)) == NULL)
150                         snd_request_other(minor);
151 #endif
152         }
153         if (mptr == NULL && (mptr = snd_minor_search(minor)) == NULL)
154                 return -ENODEV;
155         old_fops = file->f_op;
156         file->f_op = fops_get(mptr->f_ops);
157         if (file->f_op->open)
158                 err = file->f_op->open(inode, file);
159         if (err) {
160                 fops_put(file->f_op);
161                 file->f_op = fops_get(old_fops);
162         }
163         fops_put(old_fops);
164         return err;
165 }
166
167 struct file_operations snd_fops =
168 {
169         .owner =        THIS_MODULE,
170         .open =         snd_open
171 };
172
173 static int snd_kernel_minor(int type, snd_card_t * card, int dev)
174 {
175         int minor;
176
177         switch (type) {
178         case SNDRV_DEVICE_TYPE_SEQUENCER:
179         case SNDRV_DEVICE_TYPE_TIMER:
180                 minor = type;
181                 break;
182         case SNDRV_DEVICE_TYPE_CONTROL:
183                 snd_assert(card != NULL, return -EINVAL);
184                 minor = SNDRV_MINOR(card->number, type);
185                 break;
186         case SNDRV_DEVICE_TYPE_HWDEP:
187         case SNDRV_DEVICE_TYPE_RAWMIDI:
188         case SNDRV_DEVICE_TYPE_PCM_PLAYBACK:
189         case SNDRV_DEVICE_TYPE_PCM_CAPTURE:
190                 snd_assert(card != NULL, return -EINVAL);
191                 minor = SNDRV_MINOR(card->number, type + dev);
192                 break;
193         default:
194                 return -EINVAL;
195         }
196         snd_assert(minor >= 0 && minor < SNDRV_OS_MINORS, return -EINVAL);
197         return minor;
198 }
199
200 /**
201  * snd_register_device - Register the ALSA device file for the card
202  * @type: the device type, SNDRV_DEVICE_TYPE_XXX
203  * @card: the card instance
204  * @dev: the device index
205  * @reg: the snd_minor_t record
206  * @name: the device file name
207  *
208  * Registers an ALSA device file for the given card.
209  * The operators have to be set in reg parameter.
210  *
211  * Retrurns zero if successful, or a negative error code on failure.
212  */
213 int snd_register_device(int type, snd_card_t * card, int dev, snd_minor_t * reg, const char *name)
214 {
215         int minor = snd_kernel_minor(type, card, dev);
216         snd_minor_t *preg;
217         struct device *device = NULL;
218
219         if (minor < 0)
220                 return minor;
221         snd_assert(name, return -EINVAL);
222         preg = (snd_minor_t *)kmalloc(sizeof(snd_minor_t) + strlen(name) + 1, GFP_KERNEL);
223         if (preg == NULL)
224                 return -ENOMEM;
225         *preg = *reg;
226         preg->number = minor;
227         preg->device = dev;
228         strcpy(preg->name, name);
229         down(&sound_mutex);
230         if (snd_minor_search(minor)) {
231                 up(&sound_mutex);
232                 kfree(preg);
233                 return -EBUSY;
234         }
235         list_add_tail(&preg->list, &snd_minors_hash[SNDRV_MINOR_CARD(minor)]);
236         if (strncmp(name, "controlC", 8) || card->number >= cards_limit) {
237                 devfs_mk_cdev(MKDEV(major, minor), S_IFCHR | device_mode, "snd/%s", name);
238                 if (card)
239                         device = card->dev;
240                 class_simple_device_add(sound_class, MKDEV(major, minor), device, name);
241         }
242
243         up(&sound_mutex);
244         return 0;
245 }
246
247 /**
248  * snd_unregister_device - unregister the device on the given card
249  * @type: the device type, SNDRV_DEVICE_TYPE_XXX
250  * @card: the card instance
251  * @dev: the device index
252  *
253  * Unregisters the device file already registered via
254  * snd_register_device().
255  *
256  * Returns zero if sucecessful, or a negative error code on failure
257  */
258 int snd_unregister_device(int type, snd_card_t * card, int dev)
259 {
260         int minor = snd_kernel_minor(type, card, dev);
261         snd_minor_t *mptr;
262
263         if (minor < 0)
264                 return minor;
265         down(&sound_mutex);
266         if ((mptr = snd_minor_search(minor)) == NULL) {
267                 up(&sound_mutex);
268                 return -EINVAL;
269         }
270
271         if (strncmp(mptr->name, "controlC", 8) || card->number >= cards_limit) { /* created in sound.c */
272                 devfs_remove("snd/%s", mptr->name);
273                 class_simple_device_remove(MKDEV(major, minor));
274         }
275
276         list_del(&mptr->list);
277         up(&sound_mutex);
278         kfree(mptr);
279         return 0;
280 }
281
282 /*
283  *  INFO PART
284  */
285
286 static snd_info_entry_t *snd_minor_info_entry = NULL;
287
288 static void snd_minor_info_read(snd_info_entry_t *entry, snd_info_buffer_t * buffer)
289 {
290         int card, device;
291         struct list_head *list;
292         snd_minor_t *mptr;
293
294         down(&sound_mutex);
295         for (card = 0; card < SNDRV_CARDS; card++) {
296                 list_for_each(list, &snd_minors_hash[card]) {
297                         mptr = list_entry(list, snd_minor_t, list);
298                         if (SNDRV_MINOR_DEVICE(mptr->number) != SNDRV_MINOR_SEQUENCER) {
299                                 if ((device = mptr->device) >= 0)
300                                         snd_iprintf(buffer, "%3i: [%i-%2i]: %s\n", mptr->number, card, device, mptr->comment);
301                                 else
302                                         snd_iprintf(buffer, "%3i: [%i]   : %s\n", mptr->number, card, mptr->comment);
303                         } else {
304                                 snd_iprintf(buffer, "%3i:       : %s\n", mptr->number, mptr->comment);
305                         }
306                 }
307         }
308         up(&sound_mutex);
309 }
310
311 int __init snd_minor_info_init(void)
312 {
313         snd_info_entry_t *entry;
314
315         entry = snd_info_create_module_entry(THIS_MODULE, "devices", NULL);
316         if (entry) {
317                 entry->c.text.read_size = PAGE_SIZE;
318                 entry->c.text.read = snd_minor_info_read;
319                 if (snd_info_register(entry) < 0) {
320                         snd_info_free_entry(entry);
321                         entry = NULL;
322                 }
323         }
324         snd_minor_info_entry = entry;
325         return 0;
326 }
327
328 int __exit snd_minor_info_done(void)
329 {
330         if (snd_minor_info_entry)
331                 snd_info_unregister(snd_minor_info_entry);
332         return 0;
333 }
334
335 /*
336  *  INIT PART
337  */
338
339 static int __init alsa_sound_init(void)
340 {
341         short controlnum;
342 #ifdef CONFIG_SND_OSSEMUL
343         int err;
344 #endif
345         int card;
346
347         snd_major = major;
348         snd_ecards_limit = cards_limit;
349         for (card = 0; card < SNDRV_CARDS; card++)
350                 INIT_LIST_HEAD(&snd_minors_hash[card]);
351 #ifdef CONFIG_SND_OSSEMUL
352         if ((err = snd_oss_init_module()) < 0)
353                 return err;
354 #endif
355         devfs_mk_dir("snd");
356         if (register_chrdev(major, "alsa", &snd_fops)) {
357                 snd_printk(KERN_ERR "unable to register native major device number %d\n", major);
358                 devfs_remove("snd");
359                 return -EIO;
360         }
361 #ifdef CONFIG_SND_DEBUG_MEMORY
362         snd_memory_init();
363 #endif
364         if (snd_info_init() < 0) {
365 #ifdef CONFIG_SND_DEBUG_MEMORY
366                 snd_memory_done();
367 #endif
368                 unregister_chrdev(major, "alsa");
369                 devfs_remove("snd");
370                 return -ENOMEM;
371         }
372 #ifdef CONFIG_SND_OSSEMUL
373         snd_info_minor_register();
374 #endif
375         for (controlnum = 0; controlnum < cards_limit; controlnum++) {
376                 devfs_mk_cdev(MKDEV(major, controlnum<<5), S_IFCHR | device_mode, "snd/controlC%d", controlnum);
377                 class_simple_device_add(sound_class, MKDEV(major, controlnum<<5), NULL, "controlC%d", controlnum);
378         }
379 #ifndef MODULE
380         printk(KERN_INFO "Advanced Linux Sound Architecture Driver Version " CONFIG_SND_VERSION CONFIG_SND_DATE ".\n");
381 #endif
382         return 0;
383 }
384
385 static void __exit alsa_sound_exit(void)
386 {
387         short controlnum;
388
389         for (controlnum = 0; controlnum < cards_limit; controlnum++) {
390                 devfs_remove("snd/controlC%d", controlnum);
391                 class_simple_device_remove(MKDEV(major, controlnum<<5));
392         }
393
394 #ifdef CONFIG_SND_OSSEMUL
395         snd_info_minor_unregister();
396 #endif
397         snd_info_done();
398 #ifdef CONFIG_SND_DEBUG_MEMORY
399         snd_memory_done();
400 #endif
401         if (unregister_chrdev(major, "alsa") != 0)
402                 snd_printk(KERN_ERR "unable to unregister major device number %d\n", major);
403         devfs_remove("snd");
404 }
405
406 module_init(alsa_sound_init)
407 module_exit(alsa_sound_exit)
408
409 #ifndef MODULE
410
411 /* format is: snd=major,cards_limit[,device_mode] */
412
413 static int __init alsa_sound_setup(char *str)
414 {
415         (void)(get_option(&str,&major) == 2 &&
416                get_option(&str,&cards_limit) == 2);
417 #ifdef CONFIG_DEVFS_FS
418         (void)(get_option(&str,&device_mode) == 2);
419 #endif
420         return 1;
421 }
422
423 __setup("snd=", alsa_sound_setup);
424
425 #endif /* ifndef MODULE */
426
427   /* sound.c */
428 EXPORT_SYMBOL(snd_major);
429 EXPORT_SYMBOL(snd_ecards_limit);
430 #if defined(CONFIG_KMOD)
431 EXPORT_SYMBOL(snd_request_card);
432 #endif
433 EXPORT_SYMBOL(snd_register_device);
434 EXPORT_SYMBOL(snd_unregister_device);
435 #if defined(CONFIG_SND_OSSEMUL)
436 EXPORT_SYMBOL(snd_register_oss_device);
437 EXPORT_SYMBOL(snd_unregister_oss_device);
438 #endif
439   /* memory.c */
440 #ifdef CONFIG_SND_DEBUG_MEMORY
441 EXPORT_SYMBOL(snd_hidden_kmalloc);
442 EXPORT_SYMBOL(snd_hidden_kfree);
443 EXPORT_SYMBOL(snd_hidden_vmalloc);
444 EXPORT_SYMBOL(snd_hidden_vfree);
445 EXPORT_SYMBOL(_snd_magic_kmalloc);
446 EXPORT_SYMBOL(_snd_magic_kcalloc);
447 EXPORT_SYMBOL(snd_magic_kfree);
448 #endif
449 EXPORT_SYMBOL(snd_kcalloc);
450 EXPORT_SYMBOL(snd_kmalloc_strdup);
451 EXPORT_SYMBOL(copy_to_user_fromio);
452 EXPORT_SYMBOL(copy_from_user_toio);
453   /* init.c */
454 EXPORT_SYMBOL(snd_cards_count);
455 EXPORT_SYMBOL(snd_cards);
456 #if defined(CONFIG_SND_MIXER_OSS) || defined(CONFIG_SND_MIXER_OSS_MODULE)
457 EXPORT_SYMBOL(snd_mixer_oss_notify_callback);
458 #endif
459 EXPORT_SYMBOL(snd_card_new);
460 EXPORT_SYMBOL(snd_card_disconnect);
461 EXPORT_SYMBOL(snd_card_free);
462 EXPORT_SYMBOL(snd_card_free_in_thread);
463 EXPORT_SYMBOL(snd_card_register);
464 EXPORT_SYMBOL(snd_component_add);
465 EXPORT_SYMBOL(snd_card_file_add);
466 EXPORT_SYMBOL(snd_card_file_remove);
467 #ifdef CONFIG_PM
468 EXPORT_SYMBOL(snd_power_wait);
469 EXPORT_SYMBOL(snd_card_set_pm_callback);
470 EXPORT_SYMBOL(snd_card_set_dev_pm_callback);
471 #ifdef CONFIG_PCI
472 EXPORT_SYMBOL(snd_card_pci_suspend);
473 EXPORT_SYMBOL(snd_card_pci_resume);
474 #endif
475 #endif
476   /* device.c */
477 EXPORT_SYMBOL(snd_device_new);
478 EXPORT_SYMBOL(snd_device_register);
479 EXPORT_SYMBOL(snd_device_free);
480 EXPORT_SYMBOL(snd_device_free_all);
481   /* isadma.c */
482 #ifdef CONFIG_ISA
483 EXPORT_SYMBOL(snd_dma_program);
484 EXPORT_SYMBOL(snd_dma_disable);
485 EXPORT_SYMBOL(snd_dma_pointer);
486 #endif
487   /* info.c */
488 #ifdef CONFIG_PROC_FS
489 EXPORT_SYMBOL(snd_seq_root);
490 EXPORT_SYMBOL(snd_create_proc_entry);
491 EXPORT_SYMBOL(snd_remove_proc_entry);
492 EXPORT_SYMBOL(snd_iprintf);
493 EXPORT_SYMBOL(snd_info_get_line);
494 EXPORT_SYMBOL(snd_info_get_str);
495 EXPORT_SYMBOL(snd_info_create_module_entry);
496 EXPORT_SYMBOL(snd_info_create_card_entry);
497 EXPORT_SYMBOL(snd_info_free_entry);
498 EXPORT_SYMBOL(snd_info_register);
499 EXPORT_SYMBOL(snd_info_unregister);
500 EXPORT_SYMBOL(snd_card_proc_new);
501 #endif
502   /* info_oss.c */
503 #if defined(CONFIG_SND_OSSEMUL) && defined(CONFIG_PROC_FS)
504 EXPORT_SYMBOL(snd_oss_info_register);
505 #endif
506   /* control.c */
507 EXPORT_SYMBOL(snd_ctl_new);
508 EXPORT_SYMBOL(snd_ctl_new1);
509 EXPORT_SYMBOL(snd_ctl_free_one);
510 EXPORT_SYMBOL(snd_ctl_add);
511 EXPORT_SYMBOL(snd_ctl_remove);
512 EXPORT_SYMBOL(snd_ctl_remove_id);
513 EXPORT_SYMBOL(snd_ctl_rename_id);
514 EXPORT_SYMBOL(snd_ctl_find_numid);
515 EXPORT_SYMBOL(snd_ctl_find_id);
516 EXPORT_SYMBOL(snd_ctl_notify);
517 EXPORT_SYMBOL(snd_ctl_register_ioctl);
518 EXPORT_SYMBOL(snd_ctl_unregister_ioctl);
519   /* misc.c */
520 EXPORT_SYMBOL(snd_task_name);
521 #ifdef CONFIG_SND_VERBOSE_PRINTK
522 EXPORT_SYMBOL(snd_verbose_printk);
523 #endif
524 #if defined(CONFIG_SND_DEBUG) && defined(CONFIG_SND_VERBOSE_PRINTK)
525 EXPORT_SYMBOL(snd_verbose_printd);
526 #endif
527   /* wrappers */
528 #ifdef CONFIG_SND_DEBUG_MEMORY
529 EXPORT_SYMBOL(snd_wrapper_kmalloc);
530 EXPORT_SYMBOL(snd_wrapper_kfree);
531 EXPORT_SYMBOL(snd_wrapper_vmalloc);
532 EXPORT_SYMBOL(snd_wrapper_vfree);
533 #endif