Merge with 2.3.99-pre1.
[linux-2.6/linux-mips.git] / drivers / sound / sound_core.c
blob217bdb605575efaf81d291701a1cec3811cd04f7
1 /*
2 * Sound core handling. Breaks out sound functions to submodules
3 *
4 * Author: Alan Cox <alan.cox@linux.org>
6 * Fixes:
9 * This program is free software; you can redistribute it and/or
10 * modify it under the terms of the GNU General Public License
11 * as published by the Free Software Foundation; either version
12 * 2 of the License, or (at your option) any later version.
14 * --------------------
16 * Top level handler for the sound subsystem. Various devices can
17 * plug into this. The fact they dont all go via OSS doesn't mean
18 * they don't have to implement the OSS API. There is a lot of logic
19 * to keeping much of the OSS weight out of the code in a compatibility
20 * module, but its up to the driver to rember to load it...
22 * The code provides a set of functions for registration of devices
23 * by type. This is done rather than providing a single call so that
24 * we can hide any future changes in the internals (eg when we go to
25 * 32bit dev_t) from the modules and their interface.
27 * Secondly we need to allocate the dsp, dsp16 and audio devices as
28 * one. Thus we misuse the chains a bit to simplify this.
30 * Thirdly to make it more fun and for 2.3.x and above we do all
31 * of this using fine grained locking.
33 * FIXME: we have to resolve modules and fine grained load/unload
34 * locking at some point in 2.3.x.
37 #include <linux/config.h>
38 #include <linux/module.h>
39 #include <linux/malloc.h>
40 #include <linux/types.h>
41 #include <linux/kernel.h>
42 #include <linux/fs.h>
43 #include <linux/sound.h>
44 #include <linux/major.h>
45 #include <linux/kmod.h>
46 #include <linux/devfs_fs_kernel.h>
48 #define SOUND_STEP 16
51 struct sound_unit
53 int unit_minor;
54 struct file_operations *unit_fops;
55 struct sound_unit *next;
56 devfs_handle_t de;
59 #ifdef CONFIG_SOUND_MSNDCLAS
60 extern int msnd_classic_init(void);
61 #endif
62 #ifdef CONFIG_SOUND_MSNDPIN
63 extern int msnd_pinnacle_init(void);
64 #endif
65 #ifdef CONFIG_SOUND_CMPCI
66 extern init_cmpci(void);
67 #endif
70 * Low level list operator. Scan the ordered list, find a hole and
71 * join into it. Called with the lock asserted
74 static int __sound_insert_unit(struct sound_unit * s, struct sound_unit **list, struct file_operations *fops, int index, int low, int top)
76 int n=low;
78 if (index < 0) { /* first free */
80 while (*list && (*list)->unit_minor<n)
81 list=&((*list)->next);
83 while(n<top)
85 /* Found a hole ? */
86 if(*list==NULL || (*list)->unit_minor>n)
87 break;
88 list=&((*list)->next);
89 n+=SOUND_STEP;
92 if(n>=top)
93 return -ENOENT;
94 } else {
95 n = low+(index*16);
96 while (*list) {
97 if ((*list)->unit_minor==n)
98 return -EBUSY;
99 if ((*list)->unit_minor>n)
100 break;
101 list=&((*list)->next);
106 * Fill it in
109 s->unit_minor=n;
110 s->unit_fops=fops;
113 * Link it
116 s->next=*list;
117 *list=s;
120 MOD_INC_USE_COUNT;
121 return n;
125 * Remove a node from the chain. Called with the lock asserted
128 static void __sound_remove_unit(struct sound_unit **list, int unit)
130 while(*list)
132 struct sound_unit *p=*list;
133 if(p->unit_minor==unit)
135 *list=p->next;
136 devfs_unregister (p->de);
137 kfree(p);
138 MOD_DEC_USE_COUNT;
139 return;
141 list=&(p->next);
143 printk(KERN_ERR "Sound device %d went missing!\n", unit);
147 * This lock guards the sound loader list.
150 spinlock_t sound_loader_lock = SPIN_LOCK_UNLOCKED;
153 * Allocate the controlling structure and add it to the sound driver
154 * list. Acquires locks as needed
157 static devfs_handle_t devfs_handle = NULL;
159 static int sound_insert_unit(struct sound_unit **list, struct file_operations *fops, int index, int low, int top, const char *name, umode_t mode)
161 int r;
162 struct sound_unit *s=(struct sound_unit *)kmalloc(sizeof(struct sound_unit), GFP_KERNEL);
163 char name_buf[16];
165 if(s==NULL)
166 return -ENOMEM;
168 spin_lock(&sound_loader_lock);
169 r=__sound_insert_unit(s,list,fops,index,low,top);
170 spin_unlock(&sound_loader_lock);
172 if(r<0)
173 kfree(s);
174 if (r == low)
175 sprintf (name_buf, "%s", name);
176 else
177 sprintf (name_buf, "%s%d", name, (r - low) / SOUND_STEP);
178 s->de = devfs_register (devfs_handle, name_buf, 0,
179 DEVFS_FL_NONE, SOUND_MAJOR, s->unit_minor,
180 S_IFCHR | mode, 0, 0, fops, NULL);
181 return r;
185 * Remove a unit. Acquires locks as needed. The drivers MUST have
186 * completed the removal before their file operations become
187 * invalid.
190 static void sound_remove_unit(struct sound_unit **list, int unit)
192 spin_lock(&sound_loader_lock);
193 __sound_remove_unit(list, unit);
194 spin_unlock(&sound_loader_lock);
198 * Allocations
200 * 0 *16 Mixers
201 * 1 *8 Sequencers
202 * 2 *16 Midi
203 * 3 *16 DSP
204 * 4 *16 SunDSP
205 * 5 *16 DSP16
206 * 6 -- sndstat (obsolete)
207 * 7 *16 unused
208 * 8 -- alternate sequencer (see above)
209 * 9 *16 raw synthesizer access
210 * 10 *16 unused
211 * 11 *16 unused
212 * 12 *16 unused
213 * 13 *16 unused
214 * 14 *16 unused
215 * 15 *16 unused
218 static struct sound_unit *chains[16];
221 * register_sound_special
222 * @fops: File operations for the driver
223 * @unit: Unit number to allocate
225 * Allocate a special sound device by minor number from the sound
226 * subsystem. The allocated number is returned on succes. On failure
227 * a negative error code is returned.
230 int register_sound_special(struct file_operations *fops, int unit)
232 char *name;
234 switch (unit) {
235 case 0:
236 name = "mixer";
237 break;
238 case 1:
239 name = "sequencer";
240 break;
241 case 2:
242 name = "midi00";
243 break;
244 case 3:
245 name = "dsp";
246 break;
247 case 4:
248 name = "audio";
249 break;
250 case 5:
251 name = "unknown5";
252 break;
253 case 6: /* Was once sndstat */
254 name = "unknown6";
255 break;
256 case 7:
257 name = "unknown7";
258 break;
259 case 8:
260 name = "sequencer2";
261 break;
262 case 9:
263 name = "dmmidi";
264 break;
265 case 10:
266 name = "dmfm";
267 break;
268 case 11:
269 name = "unknown11";
270 break;
271 case 12:
272 name = "adsp";
273 break;
274 case 13:
275 name = "amidi";
276 break;
277 case 14:
278 name = "admmidi";
279 break;
280 default:
281 name = "unknown";
282 break;
284 return sound_insert_unit(&chains[unit&15], fops, -1, unit, unit+1,
285 name, S_IRUSR | S_IWUSR);
288 EXPORT_SYMBOL(register_sound_special);
291 * register_sound_mixer
292 * @fops: File operations for the driver
293 * @dev: Unit number to allocate
295 * Allocate a mixer device. Unit is the number of the mixer requested.
296 * Pass -1 to request the next free mixer unit. On success the allocated
297 * number is returned, on failure a negative error code is returned.
300 int register_sound_mixer(struct file_operations *fops, int dev)
302 return sound_insert_unit(&chains[0], fops, dev, 0, 128,
303 "mixer", S_IRUSR | S_IWUSR);
306 EXPORT_SYMBOL(register_sound_mixer);
309 * register_sound_midi
310 * @fops: File operations for the driver
311 * @dev: Unit number to allocate
313 * Allocate a midi device. Unit is the number of the midi device requested.
314 * Pass -1 to request the next free midi unit. On success the allocated
315 * number is returned, on failure a negative error code is returned.
318 int register_sound_midi(struct file_operations *fops, int dev)
320 return sound_insert_unit(&chains[2], fops, dev, 2, 130,
321 "midi", S_IRUSR | S_IWUSR);
324 EXPORT_SYMBOL(register_sound_midi);
327 * DSP's are registered as a triple. Register only one and cheat
328 * in open - see below.
332 * register_sound_dsp
333 * @fops: File operations for the driver
334 * @dev: Unit number to allocate
336 * Allocate a DSP device. Unit is the number of the DSP requested.
337 * Pass -1 to request the next free DSP unit. On success the allocated
338 * number is returned, on failure a negative error code is returned.
340 * This function allocates both the audio and dsp device entries together
341 * and will always allocate them as a matching pair - eg dsp3/audio3
344 int register_sound_dsp(struct file_operations *fops, int dev)
346 return sound_insert_unit(&chains[3], fops, dev, 3, 131,
347 "dsp", S_IWUSR | S_IRUSR);
350 EXPORT_SYMBOL(register_sound_dsp);
353 * register_sound_synth
354 * @fops: File operations for the driver
355 * @dev: Unit number to allocate
357 * Allocate a synth device. Unit is the number of the synth device requested.
358 * Pass -1 to request the next free synth unit. On success the allocated
359 * number is returned, on failure a negative error code is returned.
363 int register_sound_synth(struct file_operations *fops, int dev)
365 return sound_insert_unit(&chains[9], fops, dev, 9, 137,
366 "synth", S_IRUSR | S_IWUSR);
369 EXPORT_SYMBOL(register_sound_synth);
372 * unregister_sound_special
373 * @unit: Unit number to allocate
375 * Release a sound device that was allocated with register_sound_special.
376 * The unit passed is the return value from the register function.
380 void unregister_sound_special(int unit)
382 sound_remove_unit(&chains[unit&15], unit);
385 EXPORT_SYMBOL(unregister_sound_special);
388 * unregister_sound_mixer
389 * @unit: Unit number to allocate
391 * Release a sound device that was allocated with register_sound_mixer.
392 * The unit passed is the return value from the register function.
395 void unregister_sound_mixer(int unit)
397 sound_remove_unit(&chains[0], unit);
400 EXPORT_SYMBOL(unregister_sound_mixer);
403 * unregister_sound_midi
404 * @unit: Unit number to allocate
406 * Release a sound device that was allocated with register_sound_midi.
407 * The unit passed is the return value from the register function.
410 void unregister_sound_midi(int unit)
412 return sound_remove_unit(&chains[2], unit);
415 EXPORT_SYMBOL(unregister_sound_midi);
418 * unregister_sound_dsp
419 * @unit: Unit number to allocate
421 * Release a sound device that was allocated with register_sound_dsp.
422 * The unit passed is the return value from the register function.
424 * Both of the allocated units are released together automatically.
427 void unregister_sound_dsp(int unit)
429 return sound_remove_unit(&chains[3], unit);
433 EXPORT_SYMBOL(unregister_sound_dsp);
436 * unregister_sound_synth
437 * @unit: Unit number to allocate
439 * Release a sound device that was allocated with register_sound_synth.
440 * The unit passed is the return value from the register function.
443 void unregister_sound_synth(int unit)
445 return sound_remove_unit(&chains[9], unit);
448 EXPORT_SYMBOL(unregister_sound_synth);
451 * Now our file operations
454 static int soundcore_open(struct inode *, struct file *);
456 static struct file_operations soundcore_fops=
458 open: soundcore_open,
461 static struct sound_unit *__look_for_unit(int chain, int unit)
463 struct sound_unit *s;
465 s=chains[chain];
466 while(s && s->unit_minor <= unit)
468 if(s->unit_minor==unit)
469 return s;
470 s=s->next;
472 return NULL;
475 int soundcore_open(struct inode *inode, struct file *file)
477 int chain;
478 int unit=MINOR(inode->i_rdev);
479 struct sound_unit *s;
481 chain=unit&0x0F;
482 if(chain==4 || chain==5) /* dsp/audio/dsp16 */
484 unit&=0xF0;
485 unit|=3;
486 chain=3;
489 spin_lock(&sound_loader_lock);
490 s = __look_for_unit(chain, unit);
491 if (s == NULL) {
492 char mod[32];
494 spin_unlock(&sound_loader_lock);
496 * Please, don't change this order or code.
497 * For ALSA slot means soundcard and OSS emulation code
498 * comes as add-on modules which aren't depend on
499 * ALSA toplevel modules for soundcards, thus we need
500 * load them at first. [Jaroslav Kysela <perex@jcu.cz>]
502 sprintf(mod, "sound-slot-%i", unit>>4);
503 request_module(mod);
504 sprintf(mod, "sound-service-%i-%i", unit>>4, chain);
505 request_module(mod);
506 spin_lock(&sound_loader_lock);
507 s = __look_for_unit(chain, unit);
509 if (s) {
510 file->f_op=s->unit_fops;
511 spin_unlock(&sound_loader_lock);
512 if(file->f_op->open)
513 return file->f_op->open(inode,file);
514 else
515 return 0;
517 spin_unlock(&sound_loader_lock);
518 return -ENODEV;
521 extern int mod_firmware_load(const char *, char **);
522 EXPORT_SYMBOL(mod_firmware_load);
524 #ifdef MODULE
526 MODULE_DESCRIPTION("Core sound module");
527 MODULE_AUTHOR("Alan Cox");
529 void cleanup_module(void)
531 /* We have nothing to really do here - we know the lists must be
532 empty */
533 devfs_unregister_chrdev(SOUND_MAJOR, "sound");
534 devfs_unregister (devfs_handle);
537 int init_module(void)
538 #else
539 int soundcore_init(void)
540 #endif
542 if(devfs_register_chrdev(SOUND_MAJOR, "sound", &soundcore_fops)==-1)
544 printk(KERN_ERR "soundcore: sound device already in use.\n");
545 return -EBUSY;
547 devfs_handle = devfs_mk_dir (NULL, "sound", 0, NULL);
549 * Now init non OSS drivers
551 #ifdef CONFIG_SOUND_CMPCI
552 init_cmpci();
553 #endif
554 #ifdef CONFIG_SOUND_MSNDCLAS
555 msnd_classic_init();
556 #endif
557 #ifdef CONFIG_SOUND_MSNDPIN
558 msnd_pinnacle_init();
559 #endif
560 #ifdef CONFIG_SOUND_VWSND
561 init_vwsnd();
562 #endif
563 return 0;