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