Root/
1 | /* |
2 | * sound/oss/dev_table.c |
3 | * |
4 | * Device call tables. |
5 | * |
6 | * |
7 | * Copyright (C) by Hannu Savolainen 1993-1997 |
8 | * |
9 | * OSS/Free for Linux is distributed under the GNU GENERAL PUBLIC LICENSE (GPL) |
10 | * Version 2 (June 1991). See the "COPYING" file distributed with this software |
11 | * for more info. |
12 | */ |
13 | |
14 | #include <linux/init.h> |
15 | |
16 | #include "sound_config.h" |
17 | |
18 | struct audio_operations *audio_devs[MAX_AUDIO_DEV]; |
19 | EXPORT_SYMBOL(audio_devs); |
20 | |
21 | int num_audiodevs; |
22 | EXPORT_SYMBOL(num_audiodevs); |
23 | |
24 | struct mixer_operations *mixer_devs[MAX_MIXER_DEV]; |
25 | EXPORT_SYMBOL(mixer_devs); |
26 | |
27 | int num_mixers; |
28 | EXPORT_SYMBOL(num_mixers); |
29 | |
30 | struct synth_operations *synth_devs[MAX_SYNTH_DEV+MAX_MIDI_DEV]; |
31 | EXPORT_SYMBOL(synth_devs); |
32 | |
33 | int num_synths; |
34 | |
35 | struct midi_operations *midi_devs[MAX_MIDI_DEV]; |
36 | EXPORT_SYMBOL(midi_devs); |
37 | |
38 | int num_midis; |
39 | EXPORT_SYMBOL(num_midis); |
40 | |
41 | struct sound_timer_operations *sound_timer_devs[MAX_TIMER_DEV] = { |
42 | &default_sound_timer, NULL |
43 | }; |
44 | EXPORT_SYMBOL(sound_timer_devs); |
45 | |
46 | int num_sound_timers = 1; |
47 | |
48 | |
49 | static int sound_alloc_audiodev(void); |
50 | |
51 | int sound_install_audiodrv(int vers, char *name, struct audio_driver *driver, |
52 | int driver_size, int flags, unsigned int format_mask, |
53 | void *devc, int dma1, int dma2) |
54 | { |
55 | struct audio_driver *d; |
56 | struct audio_operations *op; |
57 | int num; |
58 | |
59 | if (vers != AUDIO_DRIVER_VERSION || driver_size > sizeof(struct audio_driver)) { |
60 | printk(KERN_ERR "Sound: Incompatible audio driver for %s\n", name); |
61 | return -(EINVAL); |
62 | } |
63 | num = sound_alloc_audiodev(); |
64 | |
65 | if (num == -1) { |
66 | printk(KERN_ERR "sound: Too many audio drivers\n"); |
67 | return -(EBUSY); |
68 | } |
69 | d = (struct audio_driver *) (sound_mem_blocks[sound_nblocks] = vmalloc(sizeof(struct audio_driver))); |
70 | sound_nblocks++; |
71 | if (sound_nblocks >= MAX_MEM_BLOCKS) |
72 | sound_nblocks = MAX_MEM_BLOCKS - 1; |
73 | |
74 | op = (struct audio_operations *) (sound_mem_blocks[sound_nblocks] = vzalloc(sizeof(struct audio_operations))); |
75 | sound_nblocks++; |
76 | if (sound_nblocks >= MAX_MEM_BLOCKS) |
77 | sound_nblocks = MAX_MEM_BLOCKS - 1; |
78 | |
79 | if (d == NULL || op == NULL) { |
80 | printk(KERN_ERR "Sound: Can't allocate driver for (%s)\n", name); |
81 | sound_unload_audiodev(num); |
82 | return -(ENOMEM); |
83 | } |
84 | init_waitqueue_head(&op->in_sleeper); |
85 | init_waitqueue_head(&op->out_sleeper); |
86 | init_waitqueue_head(&op->poll_sleeper); |
87 | if (driver_size < sizeof(struct audio_driver)) |
88 | memset((char *) d, 0, sizeof(struct audio_driver)); |
89 | |
90 | memcpy((char *) d, (char *) driver, driver_size); |
91 | |
92 | op->d = d; |
93 | strlcpy(op->name, name, sizeof(op->name)); |
94 | op->flags = flags; |
95 | op->format_mask = format_mask; |
96 | op->devc = devc; |
97 | |
98 | /* |
99 | * Hardcoded defaults |
100 | */ |
101 | audio_devs[num] = op; |
102 | |
103 | DMAbuf_init(num, dma1, dma2); |
104 | |
105 | audio_init_devices(); |
106 | return num; |
107 | } |
108 | EXPORT_SYMBOL(sound_install_audiodrv); |
109 | |
110 | int sound_install_mixer(int vers, char *name, struct mixer_operations *driver, |
111 | int driver_size, void *devc) |
112 | { |
113 | struct mixer_operations *op; |
114 | |
115 | int n = sound_alloc_mixerdev(); |
116 | |
117 | if (n == -1) { |
118 | printk(KERN_ERR "Sound: Too many mixer drivers\n"); |
119 | return -EBUSY; |
120 | } |
121 | if (vers != MIXER_DRIVER_VERSION || |
122 | driver_size > sizeof(struct mixer_operations)) { |
123 | printk(KERN_ERR "Sound: Incompatible mixer driver for %s\n", name); |
124 | return -EINVAL; |
125 | } |
126 | |
127 | /* FIXME: This leaks a mixer_operations struct every time its called |
128 | until you unload sound! */ |
129 | |
130 | op = (struct mixer_operations *) (sound_mem_blocks[sound_nblocks] = vzalloc(sizeof(struct mixer_operations))); |
131 | sound_nblocks++; |
132 | if (sound_nblocks >= MAX_MEM_BLOCKS) |
133 | sound_nblocks = MAX_MEM_BLOCKS - 1; |
134 | |
135 | if (op == NULL) { |
136 | printk(KERN_ERR "Sound: Can't allocate mixer driver for (%s)\n", name); |
137 | return -ENOMEM; |
138 | } |
139 | memcpy((char *) op, (char *) driver, driver_size); |
140 | |
141 | strlcpy(op->name, name, sizeof(op->name)); |
142 | op->devc = devc; |
143 | |
144 | mixer_devs[n] = op; |
145 | return n; |
146 | } |
147 | EXPORT_SYMBOL(sound_install_mixer); |
148 | |
149 | void sound_unload_audiodev(int dev) |
150 | { |
151 | if (dev != -1) { |
152 | DMAbuf_deinit(dev); |
153 | audio_devs[dev] = NULL; |
154 | unregister_sound_dsp((dev<<4)+3); |
155 | } |
156 | } |
157 | EXPORT_SYMBOL(sound_unload_audiodev); |
158 | |
159 | static int sound_alloc_audiodev(void) |
160 | { |
161 | int i = register_sound_dsp(&oss_sound_fops, -1); |
162 | if(i==-1) |
163 | return i; |
164 | i>>=4; |
165 | if(i>=num_audiodevs) |
166 | num_audiodevs = i + 1; |
167 | return i; |
168 | } |
169 | |
170 | int sound_alloc_mididev(void) |
171 | { |
172 | int i = register_sound_midi(&oss_sound_fops, -1); |
173 | if(i==-1) |
174 | return i; |
175 | i>>=4; |
176 | if(i>=num_midis) |
177 | num_midis = i + 1; |
178 | return i; |
179 | } |
180 | EXPORT_SYMBOL(sound_alloc_mididev); |
181 | |
182 | int sound_alloc_synthdev(void) |
183 | { |
184 | int i; |
185 | |
186 | for (i = 0; i < MAX_SYNTH_DEV; i++) { |
187 | if (synth_devs[i] == NULL) { |
188 | if (i >= num_synths) |
189 | num_synths++; |
190 | return i; |
191 | } |
192 | } |
193 | return -1; |
194 | } |
195 | EXPORT_SYMBOL(sound_alloc_synthdev); |
196 | |
197 | int sound_alloc_mixerdev(void) |
198 | { |
199 | int i = register_sound_mixer(&oss_sound_fops, -1); |
200 | if(i==-1) |
201 | return -1; |
202 | i>>=4; |
203 | if(i>=num_mixers) |
204 | num_mixers = i + 1; |
205 | return i; |
206 | } |
207 | EXPORT_SYMBOL(sound_alloc_mixerdev); |
208 | |
209 | int sound_alloc_timerdev(void) |
210 | { |
211 | int i; |
212 | |
213 | for (i = 0; i < MAX_TIMER_DEV; i++) { |
214 | if (sound_timer_devs[i] == NULL) { |
215 | if (i >= num_sound_timers) |
216 | num_sound_timers++; |
217 | return i; |
218 | } |
219 | } |
220 | return -1; |
221 | } |
222 | EXPORT_SYMBOL(sound_alloc_timerdev); |
223 | |
224 | void sound_unload_mixerdev(int dev) |
225 | { |
226 | if (dev != -1) { |
227 | mixer_devs[dev] = NULL; |
228 | unregister_sound_mixer(dev<<4); |
229 | num_mixers--; |
230 | } |
231 | } |
232 | EXPORT_SYMBOL(sound_unload_mixerdev); |
233 | |
234 | void sound_unload_mididev(int dev) |
235 | { |
236 | if (dev != -1) { |
237 | midi_devs[dev] = NULL; |
238 | unregister_sound_midi((dev<<4)+2); |
239 | } |
240 | } |
241 | EXPORT_SYMBOL(sound_unload_mididev); |
242 | |
243 | void sound_unload_synthdev(int dev) |
244 | { |
245 | if (dev != -1) |
246 | synth_devs[dev] = NULL; |
247 | } |
248 | EXPORT_SYMBOL(sound_unload_synthdev); |
249 | |
250 | void sound_unload_timerdev(int dev) |
251 | { |
252 | if (dev != -1) |
253 | sound_timer_devs[dev] = NULL; |
254 | } |
255 | EXPORT_SYMBOL(sound_unload_timerdev); |
256 | |
257 |
Branches:
ben-wpan
ben-wpan-stefan
javiroman/ks7010
jz-2.6.34
jz-2.6.34-rc5
jz-2.6.34-rc6
jz-2.6.34-rc7
jz-2.6.35
jz-2.6.36
jz-2.6.37
jz-2.6.38
jz-2.6.39
jz-3.0
jz-3.1
jz-3.11
jz-3.12
jz-3.13
jz-3.15
jz-3.16
jz-3.18-dt
jz-3.2
jz-3.3
jz-3.4
jz-3.5
jz-3.6
jz-3.6-rc2-pwm
jz-3.9
jz-3.9-clk
jz-3.9-rc8
jz47xx
jz47xx-2.6.38
master
Tags:
od-2011-09-04
od-2011-09-18
v2.6.34-rc5
v2.6.34-rc6
v2.6.34-rc7
v3.9