diff options
Diffstat (limited to 'sound/oss/emu10k1/audio.c')
-rw-r--r-- | sound/oss/emu10k1/audio.c | 1595 |
1 files changed, 0 insertions, 1595 deletions
diff --git a/sound/oss/emu10k1/audio.c b/sound/oss/emu10k1/audio.c deleted file mode 100644 index e75ea21eb811..000000000000 --- a/sound/oss/emu10k1/audio.c +++ /dev/null | |||
@@ -1,1595 +0,0 @@ | |||
1 | /* | ||
2 | ********************************************************************** | ||
3 | * audio.c -- /dev/dsp interface for emu10k1 driver | ||
4 | * Copyright 1999, 2000 Creative Labs, Inc. | ||
5 | * | ||
6 | ********************************************************************** | ||
7 | * | ||
8 | * Date Author Summary of changes | ||
9 | * ---- ------ ------------------ | ||
10 | * October 20, 1999 Bertrand Lee base code release | ||
11 | * November 2, 1999 Alan Cox cleaned up types/leaks | ||
12 | * | ||
13 | ********************************************************************** | ||
14 | * | ||
15 | * This program is free software; you can redistribute it and/or | ||
16 | * modify it under the terms of the GNU General Public License as | ||
17 | * published by the Free Software Foundation; either version 2 of | ||
18 | * the License, or (at your option) any later version. | ||
19 | * | ||
20 | * This program is distributed in the hope that it will be useful, | ||
21 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
22 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
23 | * GNU General Public License for more details. | ||
24 | * | ||
25 | * You should have received a copy of the GNU General Public | ||
26 | * License along with this program; if not, write to the Free | ||
27 | * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, | ||
28 | * USA. | ||
29 | * | ||
30 | ********************************************************************** | ||
31 | */ | ||
32 | |||
33 | #include <linux/module.h> | ||
34 | #include <linux/poll.h> | ||
35 | #include <linux/slab.h> | ||
36 | #include <linux/bitops.h> | ||
37 | #include <asm/io.h> | ||
38 | #include <linux/sched.h> | ||
39 | #include <linux/mm.h> | ||
40 | #include <linux/smp_lock.h> | ||
41 | |||
42 | #include "hwaccess.h" | ||
43 | #include "cardwo.h" | ||
44 | #include "cardwi.h" | ||
45 | #include "recmgr.h" | ||
46 | #include "irqmgr.h" | ||
47 | #include "audio.h" | ||
48 | #include "8010.h" | ||
49 | |||
50 | static void calculate_ofrag(struct woinst *); | ||
51 | static void calculate_ifrag(struct wiinst *); | ||
52 | |||
53 | static void emu10k1_waveout_bh(unsigned long refdata); | ||
54 | static void emu10k1_wavein_bh(unsigned long refdata); | ||
55 | |||
56 | /* Audio file operations */ | ||
57 | static ssize_t emu10k1_audio_read(struct file *file, char __user *buffer, size_t count, loff_t * ppos) | ||
58 | { | ||
59 | struct emu10k1_wavedevice *wave_dev = (struct emu10k1_wavedevice *) file->private_data; | ||
60 | struct wiinst *wiinst = wave_dev->wiinst; | ||
61 | ssize_t ret = 0; | ||
62 | unsigned long flags; | ||
63 | |||
64 | DPD(3, "emu10k1_audio_read(), buffer=%p, count=%d\n", buffer, (u32) count); | ||
65 | |||
66 | if (!access_ok(VERIFY_WRITE, buffer, count)) | ||
67 | return -EFAULT; | ||
68 | |||
69 | spin_lock_irqsave(&wiinst->lock, flags); | ||
70 | |||
71 | if (wiinst->mmapped) { | ||
72 | spin_unlock_irqrestore(&wiinst->lock, flags); | ||
73 | return -ENXIO; | ||
74 | } | ||
75 | |||
76 | if (wiinst->state == WAVE_STATE_CLOSED) { | ||
77 | calculate_ifrag(wiinst); | ||
78 | |||
79 | while (emu10k1_wavein_open(wave_dev) < 0) { | ||
80 | spin_unlock_irqrestore(&wiinst->lock, flags); | ||
81 | |||
82 | if (file->f_flags & O_NONBLOCK) | ||
83 | return -EAGAIN; | ||
84 | |||
85 | interruptible_sleep_on(&wave_dev->card->open_wait); | ||
86 | |||
87 | if (signal_pending(current)) | ||
88 | return -ERESTARTSYS; | ||
89 | |||
90 | spin_lock_irqsave(&wiinst->lock, flags); | ||
91 | } | ||
92 | } | ||
93 | |||
94 | spin_unlock_irqrestore(&wiinst->lock, flags); | ||
95 | |||
96 | while (count > 0) { | ||
97 | u32 bytestocopy; | ||
98 | |||
99 | spin_lock_irqsave(&wiinst->lock, flags); | ||
100 | |||
101 | if (!(wiinst->state & WAVE_STATE_STARTED) | ||
102 | && (wave_dev->enablebits & PCM_ENABLE_INPUT)) | ||
103 | emu10k1_wavein_start(wave_dev); | ||
104 | |||
105 | emu10k1_wavein_update(wave_dev->card, wiinst); | ||
106 | emu10k1_wavein_getxfersize(wiinst, &bytestocopy); | ||
107 | |||
108 | spin_unlock_irqrestore(&wiinst->lock, flags); | ||
109 | |||
110 | DPD(3, "bytestocopy --> %d\n", bytestocopy); | ||
111 | |||
112 | if ((bytestocopy >= wiinst->buffer.fragment_size) | ||
113 | || (bytestocopy >= count)) { | ||
114 | int rc; | ||
115 | |||
116 | bytestocopy = min_t(u32, bytestocopy, count); | ||
117 | |||
118 | rc = emu10k1_wavein_xferdata(wiinst, | ||
119 | (u8 __user *)buffer, | ||
120 | &bytestocopy); | ||
121 | if (rc) | ||
122 | return rc; | ||
123 | |||
124 | count -= bytestocopy; | ||
125 | buffer += bytestocopy; | ||
126 | ret += bytestocopy; | ||
127 | } | ||
128 | |||
129 | if (count > 0) { | ||
130 | if ((file->f_flags & O_NONBLOCK) | ||
131 | || (!(wave_dev->enablebits & PCM_ENABLE_INPUT))) | ||
132 | return (ret ? ret : -EAGAIN); | ||
133 | |||
134 | interruptible_sleep_on(&wiinst->wait_queue); | ||
135 | |||
136 | if (signal_pending(current)) | ||
137 | return (ret ? ret : -ERESTARTSYS); | ||
138 | |||
139 | } | ||
140 | } | ||
141 | |||
142 | DPD(3, "bytes copied -> %d\n", (u32) ret); | ||
143 | |||
144 | return ret; | ||
145 | } | ||
146 | |||
147 | static ssize_t emu10k1_audio_write(struct file *file, const char __user *buffer, size_t count, loff_t * ppos) | ||
148 | { | ||
149 | struct emu10k1_wavedevice *wave_dev = (struct emu10k1_wavedevice *) file->private_data; | ||
150 | struct woinst *woinst = wave_dev->woinst; | ||
151 | ssize_t ret; | ||
152 | unsigned long flags; | ||
153 | |||
154 | DPD(3, "emu10k1_audio_write(), buffer=%p, count=%d\n", buffer, (u32) count); | ||
155 | |||
156 | if (!access_ok(VERIFY_READ, buffer, count)) | ||
157 | return -EFAULT; | ||
158 | |||
159 | spin_lock_irqsave(&woinst->lock, flags); | ||
160 | |||
161 | if (woinst->mmapped) { | ||
162 | spin_unlock_irqrestore(&woinst->lock, flags); | ||
163 | return -ENXIO; | ||
164 | } | ||
165 | // This is for emu10k1 revs less than 7, we need to go through tram | ||
166 | if (woinst->format.passthrough == 1) { | ||
167 | int r; | ||
168 | |||
169 | woinst->buffer.ossfragshift = PT_BLOCKSIZE_LOG2; | ||
170 | woinst->buffer.numfrags = PT_BLOCKCOUNT; | ||
171 | calculate_ofrag(woinst); | ||
172 | |||
173 | r = emu10k1_pt_write(file, buffer, count); | ||
174 | spin_unlock_irqrestore(&woinst->lock, flags); | ||
175 | return r; | ||
176 | } | ||
177 | |||
178 | if (woinst->state == WAVE_STATE_CLOSED) { | ||
179 | calculate_ofrag(woinst); | ||
180 | |||
181 | while (emu10k1_waveout_open(wave_dev) < 0) { | ||
182 | spin_unlock_irqrestore(&woinst->lock, flags); | ||
183 | |||
184 | if (file->f_flags & O_NONBLOCK) | ||
185 | return -EAGAIN; | ||
186 | |||
187 | interruptible_sleep_on(&wave_dev->card->open_wait); | ||
188 | |||
189 | if (signal_pending(current)) | ||
190 | return -ERESTARTSYS; | ||
191 | |||
192 | spin_lock_irqsave(&woinst->lock, flags); | ||
193 | } | ||
194 | } | ||
195 | |||
196 | spin_unlock_irqrestore(&woinst->lock, flags); | ||
197 | |||
198 | ret = 0; | ||
199 | if (count % woinst->format.bytespersample) | ||
200 | return -EINVAL; | ||
201 | |||
202 | count /= woinst->num_voices; | ||
203 | |||
204 | while (count > 0) { | ||
205 | u32 bytestocopy; | ||
206 | |||
207 | spin_lock_irqsave(&woinst->lock, flags); | ||
208 | emu10k1_waveout_update(woinst); | ||
209 | emu10k1_waveout_getxfersize(woinst, &bytestocopy); | ||
210 | spin_unlock_irqrestore(&woinst->lock, flags); | ||
211 | |||
212 | DPD(3, "bytestocopy --> %d\n", bytestocopy); | ||
213 | |||
214 | if ((bytestocopy >= woinst->buffer.fragment_size) | ||
215 | || (bytestocopy >= count)) { | ||
216 | |||
217 | bytestocopy = min_t(u32, bytestocopy, count); | ||
218 | |||
219 | emu10k1_waveout_xferdata(woinst, (u8 __user *) buffer, &bytestocopy); | ||
220 | |||
221 | count -= bytestocopy; | ||
222 | buffer += bytestocopy * woinst->num_voices; | ||
223 | ret += bytestocopy * woinst->num_voices; | ||
224 | |||
225 | spin_lock_irqsave(&woinst->lock, flags); | ||
226 | woinst->total_copied += bytestocopy; | ||
227 | |||
228 | if (!(woinst->state & WAVE_STATE_STARTED) | ||
229 | && (wave_dev->enablebits & PCM_ENABLE_OUTPUT) | ||
230 | && (woinst->total_copied >= woinst->buffer.fragment_size)) | ||
231 | emu10k1_waveout_start(wave_dev); | ||
232 | |||
233 | spin_unlock_irqrestore(&woinst->lock, flags); | ||
234 | } | ||
235 | |||
236 | if (count > 0) { | ||
237 | if ((file->f_flags & O_NONBLOCK) | ||
238 | || (!(wave_dev->enablebits & PCM_ENABLE_OUTPUT))) | ||
239 | return (ret ? ret : -EAGAIN); | ||
240 | |||
241 | interruptible_sleep_on(&woinst->wait_queue); | ||
242 | |||
243 | if (signal_pending(current)) | ||
244 | return (ret ? ret : -ERESTARTSYS); | ||
245 | } | ||
246 | } | ||
247 | |||
248 | DPD(3, "bytes copied -> %d\n", (u32) ret); | ||
249 | |||
250 | return ret; | ||
251 | } | ||
252 | |||
253 | static int emu10k1_audio_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg) | ||
254 | { | ||
255 | struct emu10k1_wavedevice *wave_dev = (struct emu10k1_wavedevice *) file->private_data; | ||
256 | struct woinst *woinst = NULL; | ||
257 | struct wiinst *wiinst = NULL; | ||
258 | int val = 0; | ||
259 | u32 bytestocopy; | ||
260 | unsigned long flags; | ||
261 | int __user *p = (int __user *)arg; | ||
262 | |||
263 | DPF(4, "emu10k1_audio_ioctl()\n"); | ||
264 | |||
265 | if (file->f_mode & FMODE_WRITE) | ||
266 | woinst = wave_dev->woinst; | ||
267 | |||
268 | if (file->f_mode & FMODE_READ) | ||
269 | wiinst = wave_dev->wiinst; | ||
270 | |||
271 | switch (cmd) { | ||
272 | case OSS_GETVERSION: | ||
273 | DPF(2, "OSS_GETVERSION:\n"); | ||
274 | return put_user(SOUND_VERSION, p); | ||
275 | |||
276 | case SNDCTL_DSP_RESET: | ||
277 | DPF(2, "SNDCTL_DSP_RESET:\n"); | ||
278 | wave_dev->enablebits = PCM_ENABLE_OUTPUT | PCM_ENABLE_INPUT; | ||
279 | |||
280 | if (file->f_mode & FMODE_WRITE) { | ||
281 | spin_lock_irqsave(&woinst->lock, flags); | ||
282 | |||
283 | if (woinst->state & WAVE_STATE_OPEN) { | ||
284 | emu10k1_waveout_close(wave_dev); | ||
285 | } | ||
286 | |||
287 | woinst->mmapped = 0; | ||
288 | woinst->total_copied = 0; | ||
289 | woinst->total_played = 0; | ||
290 | woinst->blocks = 0; | ||
291 | |||
292 | spin_unlock_irqrestore(&woinst->lock, flags); | ||
293 | } | ||
294 | |||
295 | if (file->f_mode & FMODE_READ) { | ||
296 | spin_lock_irqsave(&wiinst->lock, flags); | ||
297 | |||
298 | if (wiinst->state & WAVE_STATE_OPEN) { | ||
299 | emu10k1_wavein_close(wave_dev); | ||
300 | } | ||
301 | |||
302 | wiinst->mmapped = 0; | ||
303 | wiinst->total_recorded = 0; | ||
304 | wiinst->blocks = 0; | ||
305 | spin_unlock_irqrestore(&wiinst->lock, flags); | ||
306 | } | ||
307 | |||
308 | break; | ||
309 | |||
310 | case SNDCTL_DSP_SYNC: | ||
311 | DPF(2, "SNDCTL_DSP_SYNC:\n"); | ||
312 | |||
313 | if (file->f_mode & FMODE_WRITE) { | ||
314 | |||
315 | spin_lock_irqsave(&woinst->lock, flags); | ||
316 | |||
317 | if (woinst->state & WAVE_STATE_OPEN) { | ||
318 | |||
319 | if (woinst->state & WAVE_STATE_STARTED) | ||
320 | while ((woinst->total_played < woinst->total_copied) | ||
321 | && !signal_pending(current)) { | ||
322 | spin_unlock_irqrestore(&woinst->lock, flags); | ||
323 | interruptible_sleep_on(&woinst->wait_queue); | ||
324 | spin_lock_irqsave(&woinst->lock, flags); | ||
325 | } | ||
326 | emu10k1_waveout_close(wave_dev); | ||
327 | } | ||
328 | |||
329 | woinst->mmapped = 0; | ||
330 | woinst->total_copied = 0; | ||
331 | woinst->total_played = 0; | ||
332 | woinst->blocks = 0; | ||
333 | |||
334 | spin_unlock_irqrestore(&woinst->lock, flags); | ||
335 | } | ||
336 | |||
337 | if (file->f_mode & FMODE_READ) { | ||
338 | spin_lock_irqsave(&wiinst->lock, flags); | ||
339 | |||
340 | if (wiinst->state & WAVE_STATE_OPEN) { | ||
341 | emu10k1_wavein_close(wave_dev); | ||
342 | } | ||
343 | |||
344 | wiinst->mmapped = 0; | ||
345 | wiinst->total_recorded = 0; | ||
346 | wiinst->blocks = 0; | ||
347 | spin_unlock_irqrestore(&wiinst->lock, flags); | ||
348 | } | ||
349 | |||
350 | break; | ||
351 | |||
352 | case SNDCTL_DSP_SETDUPLEX: | ||
353 | DPF(2, "SNDCTL_DSP_SETDUPLEX:\n"); | ||
354 | break; | ||
355 | |||
356 | case SNDCTL_DSP_GETCAPS: | ||
357 | DPF(2, "SNDCTL_DSP_GETCAPS:\n"); | ||
358 | return put_user(DSP_CAP_DUPLEX | DSP_CAP_REALTIME | | ||
359 | DSP_CAP_TRIGGER | DSP_CAP_MMAP | | ||
360 | DSP_CAP_COPROC| DSP_CAP_MULTI, p); | ||
361 | case SNDCTL_DSP_SPEED: | ||
362 | DPF(2, "SNDCTL_DSP_SPEED:\n"); | ||
363 | |||
364 | if (get_user(val, p)) | ||
365 | return -EFAULT; | ||
366 | |||
367 | DPD(2, "val is %d\n", val); | ||
368 | |||
369 | if (val > 0) { | ||
370 | if (file->f_mode & FMODE_READ) { | ||
371 | struct wave_format format; | ||
372 | |||
373 | spin_lock_irqsave(&wiinst->lock, flags); | ||
374 | |||
375 | format = wiinst->format; | ||
376 | format.samplingrate = val; | ||
377 | |||
378 | if (emu10k1_wavein_setformat(wave_dev, &format) < 0) { | ||
379 | spin_unlock_irqrestore(&wiinst->lock, flags); | ||
380 | return -EINVAL; | ||
381 | } | ||
382 | |||
383 | val = wiinst->format.samplingrate; | ||
384 | |||
385 | spin_unlock_irqrestore(&wiinst->lock, flags); | ||
386 | |||
387 | DPD(2, "set recording sampling rate -> %d\n", val); | ||
388 | } | ||
389 | |||
390 | if (file->f_mode & FMODE_WRITE) { | ||
391 | struct wave_format format; | ||
392 | |||
393 | spin_lock_irqsave(&woinst->lock, flags); | ||
394 | |||
395 | format = woinst->format; | ||
396 | format.samplingrate = val; | ||
397 | |||
398 | if (emu10k1_waveout_setformat(wave_dev, &format) < 0) { | ||
399 | spin_unlock_irqrestore(&woinst->lock, flags); | ||
400 | return -EINVAL; | ||
401 | } | ||
402 | |||
403 | val = woinst->format.samplingrate; | ||
404 | |||
405 | spin_unlock_irqrestore(&woinst->lock, flags); | ||
406 | |||
407 | DPD(2, "set playback sampling rate -> %d\n", val); | ||
408 | } | ||
409 | |||
410 | return put_user(val, p); | ||
411 | } else { | ||
412 | if (file->f_mode & FMODE_READ) | ||
413 | val = wiinst->format.samplingrate; | ||
414 | else if (file->f_mode & FMODE_WRITE) | ||
415 | val = woinst->format.samplingrate; | ||
416 | |||
417 | return put_user(val, p); | ||
418 | } | ||
419 | break; | ||
420 | |||
421 | case SNDCTL_DSP_STEREO: | ||
422 | DPF(2, "SNDCTL_DSP_STEREO:\n"); | ||
423 | |||
424 | if (get_user(val, p)) | ||
425 | return -EFAULT; | ||
426 | |||
427 | DPD(2, " val is %d\n", val); | ||
428 | |||
429 | if (file->f_mode & FMODE_READ) { | ||
430 | struct wave_format format; | ||
431 | |||
432 | spin_lock_irqsave(&wiinst->lock, flags); | ||
433 | |||
434 | format = wiinst->format; | ||
435 | format.channels = val ? 2 : 1; | ||
436 | |||
437 | if (emu10k1_wavein_setformat(wave_dev, &format) < 0) { | ||
438 | spin_unlock_irqrestore(&wiinst->lock, flags); | ||
439 | return -EINVAL; | ||
440 | } | ||
441 | |||
442 | val = wiinst->format.channels - 1; | ||
443 | |||
444 | spin_unlock_irqrestore(&wiinst->lock, flags); | ||
445 | DPD(2, "set recording stereo -> %d\n", val); | ||
446 | } | ||
447 | |||
448 | if (file->f_mode & FMODE_WRITE) { | ||
449 | struct wave_format format; | ||
450 | |||
451 | spin_lock_irqsave(&woinst->lock, flags); | ||
452 | |||
453 | format = woinst->format; | ||
454 | format.channels = val ? 2 : 1; | ||
455 | |||
456 | if (emu10k1_waveout_setformat(wave_dev, &format) < 0) { | ||
457 | spin_unlock_irqrestore(&woinst->lock, flags); | ||
458 | return -EINVAL; | ||
459 | } | ||
460 | |||
461 | val = woinst->format.channels - 1; | ||
462 | |||
463 | spin_unlock_irqrestore(&woinst->lock, flags); | ||
464 | |||
465 | DPD(2, "set playback stereo -> %d\n", val); | ||
466 | } | ||
467 | |||
468 | return put_user(val, p); | ||
469 | |||
470 | break; | ||
471 | |||
472 | case SNDCTL_DSP_CHANNELS: | ||
473 | DPF(2, "SNDCTL_DSP_CHANNELS:\n"); | ||
474 | |||
475 | if (get_user(val, p)) | ||
476 | return -EFAULT; | ||
477 | |||
478 | DPD(2, " val is %d\n", val); | ||
479 | |||
480 | if (val > 0) { | ||
481 | if (file->f_mode & FMODE_READ) { | ||
482 | struct wave_format format; | ||
483 | |||
484 | spin_lock_irqsave(&wiinst->lock, flags); | ||
485 | |||
486 | format = wiinst->format; | ||
487 | format.channels = val; | ||
488 | |||
489 | if (emu10k1_wavein_setformat(wave_dev, &format) < 0) { | ||
490 | spin_unlock_irqrestore(&wiinst->lock, flags); | ||
491 | return -EINVAL; | ||
492 | } | ||
493 | val = wiinst->format.channels; | ||
494 | |||
495 | spin_unlock_irqrestore(&wiinst->lock, flags); | ||
496 | DPD(2, "set recording number of channels -> %d\n", val); | ||
497 | } | ||
498 | |||
499 | if (file->f_mode & FMODE_WRITE) { | ||
500 | struct wave_format format; | ||
501 | |||
502 | spin_lock_irqsave(&woinst->lock, flags); | ||
503 | |||
504 | format = woinst->format; | ||
505 | format.channels = val; | ||
506 | |||
507 | if (emu10k1_waveout_setformat(wave_dev, &format) < 0) { | ||
508 | spin_unlock_irqrestore(&woinst->lock, flags); | ||
509 | return -EINVAL; | ||
510 | } | ||
511 | |||
512 | val = woinst->format.channels; | ||
513 | |||
514 | spin_unlock_irqrestore(&woinst->lock, flags); | ||
515 | DPD(2, "set playback number of channels -> %d\n", val); | ||
516 | } | ||
517 | |||
518 | return put_user(val, p); | ||
519 | } else { | ||
520 | if (file->f_mode & FMODE_READ) | ||
521 | val = wiinst->format.channels; | ||
522 | else if (file->f_mode & FMODE_WRITE) | ||
523 | val = woinst->format.channels; | ||
524 | |||
525 | return put_user(val, p); | ||
526 | } | ||
527 | break; | ||
528 | |||
529 | case SNDCTL_DSP_GETFMTS: | ||
530 | DPF(2, "SNDCTL_DSP_GETFMTS:\n"); | ||
531 | |||
532 | if (file->f_mode & FMODE_READ) | ||
533 | val = AFMT_S16_LE; | ||
534 | else if (file->f_mode & FMODE_WRITE) { | ||
535 | val = AFMT_S16_LE | AFMT_U8; | ||
536 | if (emu10k1_find_control_gpr(&wave_dev->card->mgr, | ||
537 | wave_dev->card->pt.patch_name, | ||
538 | wave_dev->card->pt.enable_gpr_name) >= 0) | ||
539 | val |= AFMT_AC3; | ||
540 | } | ||
541 | return put_user(val, p); | ||
542 | |||
543 | case SNDCTL_DSP_SETFMT: /* Same as SNDCTL_DSP_SAMPLESIZE */ | ||
544 | DPF(2, "SNDCTL_DSP_SETFMT:\n"); | ||
545 | |||
546 | if (get_user(val, p)) | ||
547 | return -EFAULT; | ||
548 | |||
549 | DPD(2, " val is %d\n", val); | ||
550 | |||
551 | if (val != AFMT_QUERY) { | ||
552 | if (file->f_mode & FMODE_READ) { | ||
553 | struct wave_format format; | ||
554 | |||
555 | spin_lock_irqsave(&wiinst->lock, flags); | ||
556 | |||
557 | format = wiinst->format; | ||
558 | format.id = val; | ||
559 | |||
560 | if (emu10k1_wavein_setformat(wave_dev, &format) < 0) { | ||
561 | spin_unlock_irqrestore(&wiinst->lock, flags); | ||
562 | return -EINVAL; | ||
563 | } | ||
564 | |||
565 | val = wiinst->format.id; | ||
566 | |||
567 | spin_unlock_irqrestore(&wiinst->lock, flags); | ||
568 | DPD(2, "set recording format -> %d\n", val); | ||
569 | } | ||
570 | |||
571 | if (file->f_mode & FMODE_WRITE) { | ||
572 | struct wave_format format; | ||
573 | |||
574 | spin_lock_irqsave(&woinst->lock, flags); | ||
575 | |||
576 | format = woinst->format; | ||
577 | format.id = val; | ||
578 | |||
579 | if (emu10k1_waveout_setformat(wave_dev, &format) < 0) { | ||
580 | spin_unlock_irqrestore(&woinst->lock, flags); | ||
581 | return -EINVAL; | ||
582 | } | ||
583 | |||
584 | val = woinst->format.id; | ||
585 | |||
586 | spin_unlock_irqrestore(&woinst->lock, flags); | ||
587 | DPD(2, "set playback format -> %d\n", val); | ||
588 | } | ||
589 | |||
590 | return put_user(val, p); | ||
591 | } else { | ||
592 | if (file->f_mode & FMODE_READ) | ||
593 | val = wiinst->format.id; | ||
594 | else if (file->f_mode & FMODE_WRITE) | ||
595 | val = woinst->format.id; | ||
596 | |||
597 | return put_user(val, p); | ||
598 | } | ||
599 | break; | ||
600 | |||
601 | case SOUND_PCM_READ_BITS: | ||
602 | |||
603 | if (file->f_mode & FMODE_READ) | ||
604 | val = wiinst->format.bitsperchannel; | ||
605 | else if (file->f_mode & FMODE_WRITE) | ||
606 | val = woinst->format.bitsperchannel; | ||
607 | |||
608 | return put_user(val, p); | ||
609 | |||
610 | case SOUND_PCM_READ_RATE: | ||
611 | |||
612 | if (file->f_mode & FMODE_READ) | ||
613 | val = wiinst->format.samplingrate; | ||
614 | else if (file->f_mode & FMODE_WRITE) | ||
615 | val = woinst->format.samplingrate; | ||
616 | |||
617 | return put_user(val, p); | ||
618 | |||
619 | case SOUND_PCM_READ_CHANNELS: | ||
620 | |||
621 | if (file->f_mode & FMODE_READ) | ||
622 | val = wiinst->format.channels; | ||
623 | else if (file->f_mode & FMODE_WRITE) | ||
624 | val = woinst->format.channels; | ||
625 | |||
626 | return put_user(val, p); | ||
627 | |||
628 | case SOUND_PCM_WRITE_FILTER: | ||
629 | DPF(2, "SOUND_PCM_WRITE_FILTER: not implemented\n"); | ||
630 | break; | ||
631 | |||
632 | case SOUND_PCM_READ_FILTER: | ||
633 | DPF(2, "SOUND_PCM_READ_FILTER: not implemented\n"); | ||
634 | break; | ||
635 | |||
636 | case SNDCTL_DSP_SETSYNCRO: | ||
637 | DPF(2, "SNDCTL_DSP_SETSYNCRO: not implemented\n"); | ||
638 | break; | ||
639 | |||
640 | case SNDCTL_DSP_GETTRIGGER: | ||
641 | DPF(2, "SNDCTL_DSP_GETTRIGGER:\n"); | ||
642 | |||
643 | if (file->f_mode & FMODE_WRITE && (wave_dev->enablebits & PCM_ENABLE_OUTPUT)) | ||
644 | val |= PCM_ENABLE_OUTPUT; | ||
645 | |||
646 | if (file->f_mode & FMODE_READ && (wave_dev->enablebits & PCM_ENABLE_INPUT)) | ||
647 | val |= PCM_ENABLE_INPUT; | ||
648 | |||
649 | return put_user(val, p); | ||
650 | |||
651 | case SNDCTL_DSP_SETTRIGGER: | ||
652 | DPF(2, "SNDCTL_DSP_SETTRIGGER:\n"); | ||
653 | |||
654 | if (get_user(val, p)) | ||
655 | return -EFAULT; | ||
656 | |||
657 | if (file->f_mode & FMODE_WRITE) { | ||
658 | spin_lock_irqsave(&woinst->lock, flags); | ||
659 | |||
660 | if (val & PCM_ENABLE_OUTPUT) { | ||
661 | wave_dev->enablebits |= PCM_ENABLE_OUTPUT; | ||
662 | if (woinst->state & WAVE_STATE_OPEN) | ||
663 | emu10k1_waveout_start(wave_dev); | ||
664 | } else { | ||
665 | wave_dev->enablebits &= ~PCM_ENABLE_OUTPUT; | ||
666 | if (woinst->state & WAVE_STATE_STARTED) | ||
667 | emu10k1_waveout_stop(wave_dev); | ||
668 | } | ||
669 | |||
670 | spin_unlock_irqrestore(&woinst->lock, flags); | ||
671 | } | ||
672 | |||
673 | if (file->f_mode & FMODE_READ) { | ||
674 | spin_lock_irqsave(&wiinst->lock, flags); | ||
675 | |||
676 | if (val & PCM_ENABLE_INPUT) { | ||
677 | wave_dev->enablebits |= PCM_ENABLE_INPUT; | ||
678 | if (wiinst->state & WAVE_STATE_OPEN) | ||
679 | emu10k1_wavein_start(wave_dev); | ||
680 | } else { | ||
681 | wave_dev->enablebits &= ~PCM_ENABLE_INPUT; | ||
682 | if (wiinst->state & WAVE_STATE_STARTED) | ||
683 | emu10k1_wavein_stop(wave_dev); | ||
684 | } | ||
685 | |||
686 | spin_unlock_irqrestore(&wiinst->lock, flags); | ||
687 | } | ||
688 | break; | ||
689 | |||
690 | case SNDCTL_DSP_GETOSPACE: | ||
691 | { | ||
692 | audio_buf_info info; | ||
693 | |||
694 | DPF(4, "SNDCTL_DSP_GETOSPACE:\n"); | ||
695 | |||
696 | if (!(file->f_mode & FMODE_WRITE)) | ||
697 | return -EINVAL; | ||
698 | |||
699 | spin_lock_irqsave(&woinst->lock, flags); | ||
700 | |||
701 | if (woinst->state & WAVE_STATE_OPEN) { | ||
702 | emu10k1_waveout_update(woinst); | ||
703 | emu10k1_waveout_getxfersize(woinst, &bytestocopy); | ||
704 | info.bytes = bytestocopy; | ||
705 | } else { | ||
706 | calculate_ofrag(woinst); | ||
707 | info.bytes = woinst->buffer.size; | ||
708 | } | ||
709 | spin_unlock_irqrestore(&woinst->lock, flags); | ||
710 | |||
711 | info.bytes *= woinst->num_voices; | ||
712 | info.fragsize = woinst->buffer.fragment_size * woinst->num_voices; | ||
713 | info.fragstotal = woinst->buffer.numfrags * woinst->num_voices; | ||
714 | info.fragments = info.bytes / info.fragsize; | ||
715 | |||
716 | if (copy_to_user(p, &info, sizeof(info))) | ||
717 | return -EFAULT; | ||
718 | } | ||
719 | break; | ||
720 | |||
721 | case SNDCTL_DSP_GETISPACE: | ||
722 | { | ||
723 | audio_buf_info info; | ||
724 | |||
725 | DPF(4, "SNDCTL_DSP_GETISPACE:\n"); | ||
726 | |||
727 | if (!(file->f_mode & FMODE_READ)) | ||
728 | return -EINVAL; | ||
729 | |||
730 | spin_lock_irqsave(&wiinst->lock, flags); | ||
731 | if (wiinst->state & WAVE_STATE_OPEN) { | ||
732 | emu10k1_wavein_update(wave_dev->card, wiinst); | ||
733 | emu10k1_wavein_getxfersize(wiinst, &bytestocopy); | ||
734 | info.bytes = bytestocopy; | ||
735 | } else { | ||
736 | calculate_ifrag(wiinst); | ||
737 | info.bytes = 0; | ||
738 | } | ||
739 | spin_unlock_irqrestore(&wiinst->lock, flags); | ||
740 | |||
741 | info.fragstotal = wiinst->buffer.numfrags; | ||
742 | info.fragments = info.bytes / wiinst->buffer.fragment_size; | ||
743 | info.fragsize = wiinst->buffer.fragment_size; | ||
744 | |||
745 | if (copy_to_user(p, &info, sizeof(info))) | ||
746 | return -EFAULT; | ||
747 | } | ||
748 | break; | ||
749 | |||
750 | case SNDCTL_DSP_NONBLOCK: | ||
751 | DPF(2, "SNDCTL_DSP_NONBLOCK:\n"); | ||
752 | |||
753 | file->f_flags |= O_NONBLOCK; | ||
754 | break; | ||
755 | |||
756 | case SNDCTL_DSP_GETODELAY: | ||
757 | DPF(4, "SNDCTL_DSP_GETODELAY:\n"); | ||
758 | |||
759 | if (!(file->f_mode & FMODE_WRITE)) | ||
760 | return -EINVAL; | ||
761 | |||
762 | spin_lock_irqsave(&woinst->lock, flags); | ||
763 | if (woinst->state & WAVE_STATE_OPEN) { | ||
764 | emu10k1_waveout_update(woinst); | ||
765 | emu10k1_waveout_getxfersize(woinst, &bytestocopy); | ||
766 | val = woinst->buffer.size - bytestocopy; | ||
767 | } else | ||
768 | val = 0; | ||
769 | |||
770 | val *= woinst->num_voices; | ||
771 | spin_unlock_irqrestore(&woinst->lock, flags); | ||
772 | |||
773 | return put_user(val, p); | ||
774 | |||
775 | case SNDCTL_DSP_GETIPTR: | ||
776 | { | ||
777 | count_info cinfo; | ||
778 | |||
779 | DPF(4, "SNDCTL_DSP_GETIPTR: \n"); | ||
780 | |||
781 | if (!(file->f_mode & FMODE_READ)) | ||
782 | return -EINVAL; | ||
783 | |||
784 | spin_lock_irqsave(&wiinst->lock, flags); | ||
785 | |||
786 | if (wiinst->state & WAVE_STATE_OPEN) { | ||
787 | emu10k1_wavein_update(wave_dev->card, wiinst); | ||
788 | cinfo.ptr = wiinst->buffer.hw_pos; | ||
789 | cinfo.bytes = cinfo.ptr + wiinst->total_recorded - wiinst->total_recorded % wiinst->buffer.size; | ||
790 | cinfo.blocks = cinfo.bytes / wiinst->buffer.fragment_size - wiinst->blocks; | ||
791 | wiinst->blocks = cinfo.bytes / wiinst->buffer.fragment_size; | ||
792 | } else { | ||
793 | cinfo.ptr = 0; | ||
794 | cinfo.bytes = 0; | ||
795 | cinfo.blocks = 0; | ||
796 | } | ||
797 | |||
798 | if (wiinst->mmapped) | ||
799 | wiinst->buffer.bytestocopy %= wiinst->buffer.fragment_size; | ||
800 | |||
801 | spin_unlock_irqrestore(&wiinst->lock, flags); | ||
802 | |||
803 | if (copy_to_user(p, &cinfo, sizeof(cinfo))) | ||
804 | return -EFAULT; | ||
805 | } | ||
806 | break; | ||
807 | |||
808 | case SNDCTL_DSP_GETOPTR: | ||
809 | { | ||
810 | count_info cinfo; | ||
811 | |||
812 | DPF(4, "SNDCTL_DSP_GETOPTR:\n"); | ||
813 | |||
814 | if (!(file->f_mode & FMODE_WRITE)) | ||
815 | return -EINVAL; | ||
816 | |||
817 | spin_lock_irqsave(&woinst->lock, flags); | ||
818 | |||
819 | if (woinst->state & WAVE_STATE_OPEN || | ||
820 | ((woinst->format.passthrough == 1) && wave_dev->card->pt.state)) { | ||
821 | int num_fragments; | ||
822 | |||
823 | if (woinst->format.passthrough == 1) { | ||
824 | emu10k1_pt_waveout_update(wave_dev); | ||
825 | cinfo.bytes = woinst->total_played; | ||
826 | } else { | ||
827 | emu10k1_waveout_update(woinst); | ||
828 | cinfo.bytes = woinst->total_played; | ||
829 | } | ||
830 | |||
831 | cinfo.ptr = woinst->buffer.hw_pos; | ||
832 | num_fragments = cinfo.bytes / woinst->buffer.fragment_size; | ||
833 | cinfo.blocks = num_fragments - woinst->blocks; | ||
834 | woinst->blocks = num_fragments; | ||
835 | |||
836 | cinfo.bytes *= woinst->num_voices; | ||
837 | cinfo.ptr *= woinst->num_voices; | ||
838 | } else { | ||
839 | cinfo.ptr = 0; | ||
840 | cinfo.bytes = 0; | ||
841 | cinfo.blocks = 0; | ||
842 | } | ||
843 | |||
844 | if (woinst->mmapped) | ||
845 | woinst->buffer.free_bytes %= woinst->buffer.fragment_size; | ||
846 | |||
847 | spin_unlock_irqrestore(&woinst->lock, flags); | ||
848 | |||
849 | if (copy_to_user(p, &cinfo, sizeof(cinfo))) | ||
850 | return -EFAULT; | ||
851 | } | ||
852 | break; | ||
853 | |||
854 | case SNDCTL_DSP_GETBLKSIZE: | ||
855 | DPF(2, "SNDCTL_DSP_GETBLKSIZE:\n"); | ||
856 | |||
857 | if (file->f_mode & FMODE_WRITE) { | ||
858 | spin_lock_irqsave(&woinst->lock, flags); | ||
859 | |||
860 | calculate_ofrag(woinst); | ||
861 | val = woinst->buffer.fragment_size * woinst->num_voices; | ||
862 | |||
863 | spin_unlock_irqrestore(&woinst->lock, flags); | ||
864 | } | ||
865 | |||
866 | if (file->f_mode & FMODE_READ) { | ||
867 | spin_lock_irqsave(&wiinst->lock, flags); | ||
868 | |||
869 | calculate_ifrag(wiinst); | ||
870 | val = wiinst->buffer.fragment_size; | ||
871 | |||
872 | spin_unlock_irqrestore(&wiinst->lock, flags); | ||
873 | } | ||
874 | |||
875 | return put_user(val, p); | ||
876 | |||
877 | break; | ||
878 | |||
879 | case SNDCTL_DSP_POST: | ||
880 | if (file->f_mode & FMODE_WRITE) { | ||
881 | spin_lock_irqsave(&woinst->lock, flags); | ||
882 | |||
883 | if (!(woinst->state & WAVE_STATE_STARTED) | ||
884 | && (wave_dev->enablebits & PCM_ENABLE_OUTPUT) | ||
885 | && (woinst->total_copied > 0)) | ||
886 | emu10k1_waveout_start(wave_dev); | ||
887 | |||
888 | spin_unlock_irqrestore(&woinst->lock, flags); | ||
889 | } | ||
890 | |||
891 | break; | ||
892 | |||
893 | case SNDCTL_DSP_SUBDIVIDE: | ||
894 | DPF(2, "SNDCTL_DSP_SUBDIVIDE: not implemented\n"); | ||
895 | break; | ||
896 | |||
897 | case SNDCTL_DSP_SETFRAGMENT: | ||
898 | DPF(2, "SNDCTL_DSP_SETFRAGMENT:\n"); | ||
899 | |||
900 | if (get_user(val, p)) | ||
901 | return -EFAULT; | ||
902 | |||
903 | DPD(2, "val is %#x\n", val); | ||
904 | |||
905 | if (val == 0) | ||
906 | return -EIO; | ||
907 | |||
908 | if (file->f_mode & FMODE_WRITE) { | ||
909 | /* digital pass-through fragment count and size are fixed values */ | ||
910 | if (woinst->state & WAVE_STATE_OPEN || (woinst->format.passthrough == 1)) | ||
911 | return -EINVAL; /* too late to change */ | ||
912 | |||
913 | woinst->buffer.ossfragshift = val & 0xffff; | ||
914 | woinst->buffer.numfrags = (val >> 16) & 0xffff; | ||
915 | } | ||
916 | |||
917 | if (file->f_mode & FMODE_READ) { | ||
918 | if (wiinst->state & WAVE_STATE_OPEN) | ||
919 | return -EINVAL; /* too late to change */ | ||
920 | |||
921 | wiinst->buffer.ossfragshift = val & 0xffff; | ||
922 | wiinst->buffer.numfrags = (val >> 16) & 0xffff; | ||
923 | } | ||
924 | |||
925 | break; | ||
926 | |||
927 | case SNDCTL_COPR_LOAD: | ||
928 | { | ||
929 | copr_buffer *buf; | ||
930 | u32 i; | ||
931 | |||
932 | DPF(4, "SNDCTL_COPR_LOAD:\n"); | ||
933 | |||
934 | buf = kmalloc(sizeof(copr_buffer), GFP_KERNEL); | ||
935 | if (!buf) | ||
936 | return -ENOMEM; | ||
937 | |||
938 | if (copy_from_user(buf, p, sizeof(copr_buffer))) { | ||
939 | kfree (buf); | ||
940 | return -EFAULT; | ||
941 | } | ||
942 | |||
943 | if ((buf->command != CMD_READ) && (buf->command != CMD_WRITE)) { | ||
944 | kfree (buf); | ||
945 | return -EINVAL; | ||
946 | } | ||
947 | |||
948 | if (buf->command == CMD_WRITE) { | ||
949 | |||
950 | #ifdef DBGEMU | ||
951 | if ((buf->offs < 0) || (buf->offs + buf->len > 0xe00) || (buf->len > 1000)) { | ||
952 | #else | ||
953 | if (((buf->offs < 0x100) || (buf->offs + buf->len > (wave_dev->card->is_audigy ? 0xe00 : 0x800)) || (buf->len > 1000) | ||
954 | ) && !( | ||
955 | //any register allowed raw access to users goes here: | ||
956 | (buf->offs == DBG || | ||
957 | buf->offs == A_DBG) | ||
958 | && (buf->len == 1))) { | ||
959 | #endif | ||
960 | kfree(buf); | ||
961 | return -EINVAL; | ||
962 | } | ||
963 | } else { | ||
964 | if ((buf->offs < 0) || (buf->offs + buf->len > 0xe00) || (buf->len > 1000)) { | ||
965 | kfree(buf); | ||
966 | return -EINVAL; | ||
967 | } | ||
968 | } | ||
969 | |||
970 | if (((unsigned)buf->flags) > 0x3f) | ||
971 | buf->flags = 0; | ||
972 | |||
973 | if (buf->command == CMD_READ) { | ||
974 | for (i = 0; i < buf->len; i++) | ||
975 | ((u32 *) buf->data)[i] = sblive_readptr(wave_dev->card, buf->offs + i, buf->flags); | ||
976 | |||
977 | if (copy_to_user(p, buf, sizeof(copr_buffer))) { | ||
978 | kfree(buf); | ||
979 | return -EFAULT; | ||
980 | } | ||
981 | } else { | ||
982 | for (i = 0; i < buf->len; i++) | ||
983 | sblive_writeptr(wave_dev->card, buf->offs + i, buf->flags, ((u32 *) buf->data)[i]); | ||
984 | } | ||
985 | |||
986 | kfree (buf); | ||
987 | break; | ||
988 | } | ||
989 | |||
990 | default: /* Default is unrecognized command */ | ||
991 | DPD(2, "default: %#x\n", cmd); | ||
992 | return -EINVAL; | ||
993 | } | ||
994 | return 0; | ||
995 | } | ||
996 | |||
997 | static struct page *emu10k1_mm_nopage (struct vm_area_struct * vma, unsigned long address, int *type) | ||
998 | { | ||
999 | struct emu10k1_wavedevice *wave_dev = vma->vm_private_data; | ||
1000 | struct woinst *woinst = wave_dev->woinst; | ||
1001 | struct wiinst *wiinst = wave_dev->wiinst; | ||
1002 | struct page *dmapage; | ||
1003 | unsigned long pgoff; | ||
1004 | int rd, wr; | ||
1005 | |||
1006 | DPF(3, "emu10k1_mm_nopage()\n"); | ||
1007 | DPD(3, "addr: %#lx\n", address); | ||
1008 | |||
1009 | if (address > vma->vm_end) { | ||
1010 | DPF(1, "EXIT, returning NOPAGE_SIGBUS\n"); | ||
1011 | return NOPAGE_SIGBUS; /* Disallow mremap */ | ||
1012 | } | ||
1013 | |||
1014 | pgoff = vma->vm_pgoff + ((address - vma->vm_start) >> PAGE_SHIFT); | ||
1015 | if (woinst != NULL) | ||
1016 | wr = woinst->mmapped; | ||
1017 | else | ||
1018 | wr = 0; | ||
1019 | |||
1020 | if (wiinst != NULL) | ||
1021 | rd = wiinst->mmapped; | ||
1022 | else | ||
1023 | rd = 0; | ||
1024 | |||
1025 | /* if full-duplex (read+write) and we have two sets of bufs, | ||
1026 | * then the playback buffers come first, sez soundcard.c */ | ||
1027 | if (wr) { | ||
1028 | if (pgoff >= woinst->buffer.pages) { | ||
1029 | pgoff -= woinst->buffer.pages; | ||
1030 | dmapage = virt_to_page ((u8 *) wiinst->buffer.addr + pgoff * PAGE_SIZE); | ||
1031 | } else | ||
1032 | dmapage = virt_to_page (woinst->voice[0].mem.addr[pgoff]); | ||
1033 | } else { | ||
1034 | dmapage = virt_to_page ((u8 *) wiinst->buffer.addr + pgoff * PAGE_SIZE); | ||
1035 | } | ||
1036 | |||
1037 | get_page (dmapage); | ||
1038 | |||
1039 | DPD(3, "page: %#lx\n", (unsigned long) dmapage); | ||
1040 | if (type) | ||
1041 | *type = VM_FAULT_MINOR; | ||
1042 | return dmapage; | ||
1043 | } | ||
1044 | |||
1045 | static struct vm_operations_struct emu10k1_mm_ops = { | ||
1046 | .nopage = emu10k1_mm_nopage, | ||
1047 | }; | ||
1048 | |||
1049 | static int emu10k1_audio_mmap(struct file *file, struct vm_area_struct *vma) | ||
1050 | { | ||
1051 | struct emu10k1_wavedevice *wave_dev = (struct emu10k1_wavedevice *) file->private_data; | ||
1052 | unsigned long max_pages, n_pages, pgoffset; | ||
1053 | struct woinst *woinst = NULL; | ||
1054 | struct wiinst *wiinst = NULL; | ||
1055 | unsigned long flags; | ||
1056 | |||
1057 | DPF(2, "emu10k1_audio_mmap()\n"); | ||
1058 | |||
1059 | max_pages = 0; | ||
1060 | if (vma->vm_flags & VM_WRITE) { | ||
1061 | woinst = wave_dev->woinst; | ||
1062 | |||
1063 | spin_lock_irqsave(&woinst->lock, flags); | ||
1064 | |||
1065 | /* No m'mapping possible for multichannel */ | ||
1066 | if (woinst->num_voices > 1) { | ||
1067 | spin_unlock_irqrestore(&woinst->lock, flags); | ||
1068 | return -EINVAL; | ||
1069 | } | ||
1070 | |||
1071 | if (woinst->state == WAVE_STATE_CLOSED) { | ||
1072 | calculate_ofrag(woinst); | ||
1073 | |||
1074 | if (emu10k1_waveout_open(wave_dev) < 0) { | ||
1075 | spin_unlock_irqrestore(&woinst->lock, flags); | ||
1076 | ERROR(); | ||
1077 | return -EINVAL; | ||
1078 | } | ||
1079 | } | ||
1080 | |||
1081 | woinst->mmapped = 1; | ||
1082 | max_pages += woinst->buffer.pages; | ||
1083 | spin_unlock_irqrestore(&woinst->lock, flags); | ||
1084 | } | ||
1085 | |||
1086 | if (vma->vm_flags & VM_READ) { | ||
1087 | wiinst = wave_dev->wiinst; | ||
1088 | |||
1089 | spin_lock_irqsave(&wiinst->lock, flags); | ||
1090 | if (wiinst->state == WAVE_STATE_CLOSED) { | ||
1091 | calculate_ifrag(wiinst); | ||
1092 | |||
1093 | if (emu10k1_wavein_open(wave_dev) < 0) { | ||
1094 | spin_unlock_irqrestore(&wiinst->lock, flags); | ||
1095 | ERROR(); | ||
1096 | return -EINVAL; | ||
1097 | } | ||
1098 | } | ||
1099 | |||
1100 | wiinst->mmapped = 1; | ||
1101 | max_pages += wiinst->buffer.pages; | ||
1102 | spin_unlock_irqrestore(&wiinst->lock, flags); | ||
1103 | } | ||
1104 | |||
1105 | n_pages = ((vma->vm_end - vma->vm_start) + PAGE_SIZE - 1) >> PAGE_SHIFT; | ||
1106 | pgoffset = vma->vm_pgoff; | ||
1107 | |||
1108 | DPD(2, "vma_start: %#lx, vma_end: %#lx, vma_offset: %ld\n", vma->vm_start, vma->vm_end, pgoffset); | ||
1109 | DPD(2, "n_pages: %ld, max_pages: %ld\n", n_pages, max_pages); | ||
1110 | |||
1111 | if (pgoffset + n_pages > max_pages) | ||
1112 | return -EINVAL; | ||
1113 | |||
1114 | vma->vm_flags |= VM_RESERVED; | ||
1115 | vma->vm_ops = &emu10k1_mm_ops; | ||
1116 | vma->vm_private_data = wave_dev; | ||
1117 | return 0; | ||
1118 | } | ||
1119 | |||
1120 | static int emu10k1_audio_open(struct inode *inode, struct file *file) | ||
1121 | { | ||
1122 | int minor = iminor(inode); | ||
1123 | struct emu10k1_card *card = NULL; | ||
1124 | struct list_head *entry; | ||
1125 | struct emu10k1_wavedevice *wave_dev; | ||
1126 | |||
1127 | DPF(2, "emu10k1_audio_open()\n"); | ||
1128 | |||
1129 | /* Check for correct device to open */ | ||
1130 | |||
1131 | list_for_each(entry, &emu10k1_devs) { | ||
1132 | card = list_entry(entry, struct emu10k1_card, list); | ||
1133 | |||
1134 | if (!((card->audio_dev ^ minor) & ~0xf) || !((card->audio_dev1 ^ minor) & ~0xf)) | ||
1135 | goto match; | ||
1136 | } | ||
1137 | |||
1138 | return -ENODEV; | ||
1139 | |||
1140 | match: | ||
1141 | |||
1142 | wave_dev = kmalloc(sizeof(struct emu10k1_wavedevice), GFP_KERNEL); | ||
1143 | |||
1144 | if (wave_dev == NULL) { | ||
1145 | ERROR(); | ||
1146 | return -ENOMEM; | ||
1147 | } | ||
1148 | |||
1149 | wave_dev->card = card; | ||
1150 | wave_dev->wiinst = NULL; | ||
1151 | wave_dev->woinst = NULL; | ||
1152 | wave_dev->enablebits = PCM_ENABLE_OUTPUT | PCM_ENABLE_INPUT; /* Default */ | ||
1153 | |||
1154 | if (file->f_mode & FMODE_READ) { | ||
1155 | /* Recording */ | ||
1156 | struct wiinst *wiinst; | ||
1157 | |||
1158 | if ((wiinst = kmalloc(sizeof(struct wiinst), GFP_KERNEL)) == NULL) { | ||
1159 | ERROR(); | ||
1160 | kfree(wave_dev); | ||
1161 | return -ENOMEM; | ||
1162 | } | ||
1163 | |||
1164 | wiinst->recsrc = card->wavein.recsrc; | ||
1165 | wiinst->fxwc = card->wavein.fxwc; | ||
1166 | |||
1167 | switch (wiinst->recsrc) { | ||
1168 | case WAVERECORD_AC97: | ||
1169 | wiinst->format.id = AFMT_S16_LE; | ||
1170 | wiinst->format.samplingrate = 8000; | ||
1171 | wiinst->format.bitsperchannel = 16; | ||
1172 | wiinst->format.channels = 1; | ||
1173 | break; | ||
1174 | case WAVERECORD_MIC: | ||
1175 | wiinst->format.id = AFMT_S16_LE; | ||
1176 | wiinst->format.samplingrate = 8000; | ||
1177 | wiinst->format.bitsperchannel = 16; | ||
1178 | wiinst->format.channels = 1; | ||
1179 | break; | ||
1180 | case WAVERECORD_FX: | ||
1181 | wiinst->format.id = AFMT_S16_LE; | ||
1182 | wiinst->format.samplingrate = 48000; | ||
1183 | wiinst->format.bitsperchannel = 16; | ||
1184 | wiinst->format.channels = hweight32(wiinst->fxwc); | ||
1185 | break; | ||
1186 | default: | ||
1187 | kfree(wave_dev); | ||
1188 | kfree(wiinst); | ||
1189 | BUG(); | ||
1190 | break; | ||
1191 | } | ||
1192 | |||
1193 | wiinst->state = WAVE_STATE_CLOSED; | ||
1194 | |||
1195 | wiinst->buffer.ossfragshift = 0; | ||
1196 | wiinst->buffer.fragment_size = 0; | ||
1197 | wiinst->buffer.numfrags = 0; | ||
1198 | |||
1199 | init_waitqueue_head(&wiinst->wait_queue); | ||
1200 | |||
1201 | wiinst->mmapped = 0; | ||
1202 | wiinst->total_recorded = 0; | ||
1203 | wiinst->blocks = 0; | ||
1204 | spin_lock_init(&wiinst->lock); | ||
1205 | tasklet_init(&wiinst->timer.tasklet, emu10k1_wavein_bh, (unsigned long) wave_dev); | ||
1206 | wave_dev->wiinst = wiinst; | ||
1207 | emu10k1_wavein_setformat(wave_dev, &wiinst->format); | ||
1208 | } | ||
1209 | |||
1210 | if (file->f_mode & FMODE_WRITE) { | ||
1211 | struct woinst *woinst; | ||
1212 | int i; | ||
1213 | |||
1214 | if ((woinst = kmalloc(sizeof(struct woinst), GFP_KERNEL)) == NULL) { | ||
1215 | ERROR(); | ||
1216 | kfree(wave_dev); | ||
1217 | return -ENOMEM; | ||
1218 | } | ||
1219 | |||
1220 | if (wave_dev->wiinst != NULL) { | ||
1221 | woinst->format = wave_dev->wiinst->format; | ||
1222 | } else { | ||
1223 | woinst->format.id = AFMT_U8; | ||
1224 | woinst->format.samplingrate = 8000; | ||
1225 | woinst->format.bitsperchannel = 8; | ||
1226 | woinst->format.channels = 1; | ||
1227 | } | ||
1228 | |||
1229 | woinst->state = WAVE_STATE_CLOSED; | ||
1230 | |||
1231 | woinst->buffer.fragment_size = 0; | ||
1232 | woinst->buffer.ossfragshift = 0; | ||
1233 | woinst->buffer.numfrags = 0; | ||
1234 | woinst->device = (card->audio_dev1 == minor); | ||
1235 | woinst->timer.state = TIMER_STATE_UNINSTALLED; | ||
1236 | woinst->num_voices = 1; | ||
1237 | for (i = 0; i < WAVEOUT_MAXVOICES; i++) { | ||
1238 | woinst->voice[i].usage = VOICE_USAGE_FREE; | ||
1239 | woinst->voice[i].mem.emupageindex = -1; | ||
1240 | } | ||
1241 | |||
1242 | init_waitqueue_head(&woinst->wait_queue); | ||
1243 | |||
1244 | woinst->mmapped = 0; | ||
1245 | woinst->total_copied = 0; | ||
1246 | woinst->total_played = 0; | ||
1247 | woinst->blocks = 0; | ||
1248 | spin_lock_init(&woinst->lock); | ||
1249 | tasklet_init(&woinst->timer.tasklet, emu10k1_waveout_bh, (unsigned long) wave_dev); | ||
1250 | wave_dev->woinst = woinst; | ||
1251 | emu10k1_waveout_setformat(wave_dev, &woinst->format); | ||
1252 | } | ||
1253 | |||
1254 | file->private_data = (void *) wave_dev; | ||
1255 | |||
1256 | return nonseekable_open(inode, file); | ||
1257 | } | ||
1258 | |||
1259 | static int emu10k1_audio_release(struct inode *inode, struct file *file) | ||
1260 | { | ||
1261 | struct emu10k1_wavedevice *wave_dev = (struct emu10k1_wavedevice *) file->private_data; | ||
1262 | struct emu10k1_card *card; | ||
1263 | unsigned long flags; | ||
1264 | |||
1265 | card = wave_dev->card; | ||
1266 | |||
1267 | DPF(2, "emu10k1_audio_release()\n"); | ||
1268 | |||
1269 | if (file->f_mode & FMODE_WRITE) { | ||
1270 | struct woinst *woinst = wave_dev->woinst; | ||
1271 | |||
1272 | spin_lock_irqsave(&woinst->lock, flags); | ||
1273 | if(woinst->format.passthrough==2) | ||
1274 | card->pt.state=PT_STATE_PLAYING; | ||
1275 | if (woinst->format.passthrough && card->pt.state != PT_STATE_INACTIVE){ | ||
1276 | spin_lock(&card->pt.lock); | ||
1277 | emu10k1_pt_stop(card); | ||
1278 | spin_unlock(&card->pt.lock); | ||
1279 | } | ||
1280 | if (woinst->state & WAVE_STATE_OPEN) { | ||
1281 | if (woinst->state & WAVE_STATE_STARTED) { | ||
1282 | if (!(file->f_flags & O_NONBLOCK)) { | ||
1283 | while (!signal_pending(current) | ||
1284 | && (woinst->total_played < woinst->total_copied)) { | ||
1285 | DPF(4, "Buffer hasn't been totally played, sleep....\n"); | ||
1286 | spin_unlock_irqrestore(&woinst->lock, flags); | ||
1287 | interruptible_sleep_on(&woinst->wait_queue); | ||
1288 | spin_lock_irqsave(&woinst->lock, flags); | ||
1289 | } | ||
1290 | } | ||
1291 | } | ||
1292 | emu10k1_waveout_close(wave_dev); | ||
1293 | } | ||
1294 | |||
1295 | spin_unlock_irqrestore(&woinst->lock, flags); | ||
1296 | /* remove the tasklet */ | ||
1297 | tasklet_kill(&woinst->timer.tasklet); | ||
1298 | kfree(wave_dev->woinst); | ||
1299 | } | ||
1300 | |||
1301 | if (file->f_mode & FMODE_READ) { | ||
1302 | struct wiinst *wiinst = wave_dev->wiinst; | ||
1303 | |||
1304 | spin_lock_irqsave(&wiinst->lock, flags); | ||
1305 | |||
1306 | if (wiinst->state & WAVE_STATE_OPEN) { | ||
1307 | emu10k1_wavein_close(wave_dev); | ||
1308 | } | ||
1309 | |||
1310 | spin_unlock_irqrestore(&wiinst->lock, flags); | ||
1311 | tasklet_kill(&wiinst->timer.tasklet); | ||
1312 | kfree(wave_dev->wiinst); | ||
1313 | } | ||
1314 | |||
1315 | kfree(wave_dev); | ||
1316 | |||
1317 | if (waitqueue_active(&card->open_wait)) | ||
1318 | wake_up_interruptible(&card->open_wait); | ||
1319 | |||
1320 | return 0; | ||
1321 | } | ||
1322 | |||
1323 | /* FIXME sort out poll() + mmap() */ | ||
1324 | static unsigned int emu10k1_audio_poll(struct file *file, struct poll_table_struct *wait) | ||
1325 | { | ||
1326 | struct emu10k1_wavedevice *wave_dev = (struct emu10k1_wavedevice *) file->private_data; | ||
1327 | struct woinst *woinst = wave_dev->woinst; | ||
1328 | struct wiinst *wiinst = wave_dev->wiinst; | ||
1329 | unsigned int mask = 0; | ||
1330 | u32 bytestocopy; | ||
1331 | unsigned long flags; | ||
1332 | |||
1333 | DPF(4, "emu10k1_audio_poll()\n"); | ||
1334 | |||
1335 | if (file->f_mode & FMODE_WRITE) | ||
1336 | poll_wait(file, &woinst->wait_queue, wait); | ||
1337 | |||
1338 | if (file->f_mode & FMODE_READ) | ||
1339 | poll_wait(file, &wiinst->wait_queue, wait); | ||
1340 | |||
1341 | if (file->f_mode & FMODE_WRITE) { | ||
1342 | spin_lock_irqsave(&woinst->lock, flags); | ||
1343 | |||
1344 | if (woinst->state & WAVE_STATE_OPEN) { | ||
1345 | emu10k1_waveout_update(woinst); | ||
1346 | emu10k1_waveout_getxfersize(woinst, &bytestocopy); | ||
1347 | |||
1348 | if (bytestocopy >= woinst->buffer.fragment_size) | ||
1349 | mask |= POLLOUT | POLLWRNORM; | ||
1350 | } else | ||
1351 | mask |= POLLOUT | POLLWRNORM; | ||
1352 | |||
1353 | spin_unlock_irqrestore(&woinst->lock, flags); | ||
1354 | } | ||
1355 | |||
1356 | if (file->f_mode & FMODE_READ) { | ||
1357 | spin_lock_irqsave(&wiinst->lock, flags); | ||
1358 | |||
1359 | if (wiinst->state & WAVE_STATE_OPEN) { | ||
1360 | emu10k1_wavein_update(wave_dev->card, wiinst); | ||
1361 | emu10k1_wavein_getxfersize(wiinst, &bytestocopy); | ||
1362 | |||
1363 | if (bytestocopy >= wiinst->buffer.fragment_size) | ||
1364 | mask |= POLLIN | POLLRDNORM; | ||
1365 | } | ||
1366 | |||
1367 | spin_unlock_irqrestore(&wiinst->lock, flags); | ||
1368 | } | ||
1369 | |||
1370 | return mask; | ||
1371 | } | ||
1372 | |||
1373 | static void calculate_ofrag(struct woinst *woinst) | ||
1374 | { | ||
1375 | struct waveout_buffer *buffer = &woinst->buffer; | ||
1376 | u32 fragsize; | ||
1377 | |||
1378 | if (buffer->fragment_size) | ||
1379 | return; | ||
1380 | |||
1381 | if (!buffer->ossfragshift) { | ||
1382 | fragsize = (woinst->format.bytespervoicesample * woinst->format.samplingrate * WAVEOUT_DEFAULTFRAGLEN) / 1000 - 1; | ||
1383 | |||
1384 | while (fragsize) { | ||
1385 | fragsize >>= 1; | ||
1386 | buffer->ossfragshift++; | ||
1387 | } | ||
1388 | } | ||
1389 | |||
1390 | if (buffer->ossfragshift < WAVEOUT_MINFRAGSHIFT) | ||
1391 | buffer->ossfragshift = WAVEOUT_MINFRAGSHIFT; | ||
1392 | |||
1393 | buffer->fragment_size = 1 << buffer->ossfragshift; | ||
1394 | |||
1395 | while (buffer->fragment_size * WAVEOUT_MINFRAGS > WAVEOUT_MAXBUFSIZE) | ||
1396 | buffer->fragment_size >>= 1; | ||
1397 | |||
1398 | /* now we are sure that: | ||
1399 | (2^WAVEOUT_MINFRAGSHIFT) <= (fragment_size = 2^n) <= (WAVEOUT_MAXBUFSIZE / WAVEOUT_MINFRAGS) | ||
1400 | */ | ||
1401 | |||
1402 | if (!buffer->numfrags) { | ||
1403 | u32 numfrags; | ||
1404 | |||
1405 | numfrags = (woinst->format.bytespervoicesample * woinst->format.samplingrate * WAVEOUT_DEFAULTBUFLEN) / | ||
1406 | (buffer->fragment_size * 1000) - 1; | ||
1407 | |||
1408 | buffer->numfrags = 1; | ||
1409 | |||
1410 | while (numfrags) { | ||
1411 | numfrags >>= 1; | ||
1412 | buffer->numfrags <<= 1; | ||
1413 | } | ||
1414 | } | ||
1415 | |||
1416 | if (buffer->numfrags < WAVEOUT_MINFRAGS) | ||
1417 | buffer->numfrags = WAVEOUT_MINFRAGS; | ||
1418 | |||
1419 | if (buffer->numfrags * buffer->fragment_size > WAVEOUT_MAXBUFSIZE) | ||
1420 | buffer->numfrags = WAVEOUT_MAXBUFSIZE / buffer->fragment_size; | ||
1421 | |||
1422 | if (buffer->numfrags < WAVEOUT_MINFRAGS) | ||
1423 | BUG(); | ||
1424 | |||
1425 | buffer->size = buffer->fragment_size * buffer->numfrags; | ||
1426 | buffer->pages = buffer->size / PAGE_SIZE + ((buffer->size % PAGE_SIZE) ? 1 : 0); | ||
1427 | |||
1428 | DPD(2, " calculated playback fragment_size -> %d\n", buffer->fragment_size); | ||
1429 | DPD(2, " calculated playback numfrags -> %d\n", buffer->numfrags); | ||
1430 | |||
1431 | return; | ||
1432 | } | ||
1433 | |||
1434 | static void calculate_ifrag(struct wiinst *wiinst) | ||
1435 | { | ||
1436 | struct wavein_buffer *buffer = &wiinst->buffer; | ||
1437 | u32 fragsize, bufsize, size[4]; | ||
1438 | int i, j; | ||
1439 | |||
1440 | if (buffer->fragment_size) | ||
1441 | return; | ||
1442 | |||
1443 | if (!buffer->ossfragshift) { | ||
1444 | fragsize = (wiinst->format.bytespersec * WAVEIN_DEFAULTFRAGLEN) / 1000 - 1; | ||
1445 | |||
1446 | while (fragsize) { | ||
1447 | fragsize >>= 1; | ||
1448 | buffer->ossfragshift++; | ||
1449 | } | ||
1450 | } | ||
1451 | |||
1452 | if (buffer->ossfragshift < WAVEIN_MINFRAGSHIFT) | ||
1453 | buffer->ossfragshift = WAVEIN_MINFRAGSHIFT; | ||
1454 | |||
1455 | buffer->fragment_size = 1 << buffer->ossfragshift; | ||
1456 | |||
1457 | while (buffer->fragment_size * WAVEIN_MINFRAGS > WAVEIN_MAXBUFSIZE) | ||
1458 | buffer->fragment_size >>= 1; | ||
1459 | |||
1460 | /* now we are sure that: | ||
1461 | (2^WAVEIN_MINFRAGSHIFT) <= (fragment_size = 2^n) <= (WAVEIN_MAXBUFSIZE / WAVEIN_MINFRAGS) | ||
1462 | */ | ||
1463 | |||
1464 | |||
1465 | if (!buffer->numfrags) | ||
1466 | buffer->numfrags = (wiinst->format.bytespersec * WAVEIN_DEFAULTBUFLEN) / (buffer->fragment_size * 1000) - 1; | ||
1467 | |||
1468 | if (buffer->numfrags < WAVEIN_MINFRAGS) | ||
1469 | buffer->numfrags = WAVEIN_MINFRAGS; | ||
1470 | |||
1471 | if (buffer->numfrags * buffer->fragment_size > WAVEIN_MAXBUFSIZE) | ||
1472 | buffer->numfrags = WAVEIN_MAXBUFSIZE / buffer->fragment_size; | ||
1473 | |||
1474 | if (buffer->numfrags < WAVEIN_MINFRAGS) | ||
1475 | BUG(); | ||
1476 | |||
1477 | bufsize = buffer->fragment_size * buffer->numfrags; | ||
1478 | |||
1479 | /* the buffer size for recording is restricted to certain values, adjust it now */ | ||
1480 | if (bufsize >= 0x10000) { | ||
1481 | buffer->size = 0x10000; | ||
1482 | buffer->sizeregval = 0x1f; | ||
1483 | } else { | ||
1484 | buffer->size = 0; | ||
1485 | size[0] = 384; | ||
1486 | size[1] = 448; | ||
1487 | size[2] = 512; | ||
1488 | size[3] = 640; | ||
1489 | |||
1490 | for (i = 0; i < 8; i++) | ||
1491 | for (j = 0; j < 4; j++) | ||
1492 | if (bufsize >= size[j]) { | ||
1493 | buffer->size = size[j]; | ||
1494 | size[j] *= 2; | ||
1495 | buffer->sizeregval = i * 4 + j + 1; | ||
1496 | } else | ||
1497 | goto exitloop; | ||
1498 | exitloop: | ||
1499 | if (buffer->size == 0) { | ||
1500 | buffer->size = 384; | ||
1501 | buffer->sizeregval = 0x01; | ||
1502 | } | ||
1503 | } | ||
1504 | |||
1505 | /* adjust the fragment size so that buffer size is an integer multiple */ | ||
1506 | while (buffer->size % buffer->fragment_size) | ||
1507 | buffer->fragment_size >>= 1; | ||
1508 | |||
1509 | buffer->numfrags = buffer->size / buffer->fragment_size; | ||
1510 | buffer->pages = buffer->size / PAGE_SIZE + ((buffer->size % PAGE_SIZE) ? 1 : 0); | ||
1511 | |||
1512 | DPD(2, " calculated recording fragment_size -> %d\n", buffer->fragment_size); | ||
1513 | DPD(2, " calculated recording numfrags -> %d\n", buffer->numfrags); | ||
1514 | DPD(2, " buffer size register -> %#04x\n", buffer->sizeregval); | ||
1515 | |||
1516 | return; | ||
1517 | } | ||
1518 | |||
1519 | static void emu10k1_wavein_bh(unsigned long refdata) | ||
1520 | { | ||
1521 | struct emu10k1_wavedevice *wave_dev = (struct emu10k1_wavedevice *) refdata; | ||
1522 | struct wiinst *wiinst = wave_dev->wiinst; | ||
1523 | u32 bytestocopy; | ||
1524 | unsigned long flags; | ||
1525 | |||
1526 | if (!wiinst) | ||
1527 | return; | ||
1528 | |||
1529 | spin_lock_irqsave(&wiinst->lock, flags); | ||
1530 | |||
1531 | if (!(wiinst->state & WAVE_STATE_STARTED)) { | ||
1532 | spin_unlock_irqrestore(&wiinst->lock, flags); | ||
1533 | return; | ||
1534 | } | ||
1535 | |||
1536 | emu10k1_wavein_update(wave_dev->card, wiinst); | ||
1537 | emu10k1_wavein_getxfersize(wiinst, &bytestocopy); | ||
1538 | |||
1539 | spin_unlock_irqrestore(&wiinst->lock, flags); | ||
1540 | |||
1541 | if (bytestocopy >= wiinst->buffer.fragment_size) { | ||
1542 | if (waitqueue_active(&wiinst->wait_queue)) | ||
1543 | wake_up_interruptible(&wiinst->wait_queue); | ||
1544 | } else | ||
1545 | DPD(3, "Not enough transfer size, %d\n", bytestocopy); | ||
1546 | |||
1547 | return; | ||
1548 | } | ||
1549 | |||
1550 | static void emu10k1_waveout_bh(unsigned long refdata) | ||
1551 | { | ||
1552 | struct emu10k1_wavedevice *wave_dev = (struct emu10k1_wavedevice *) refdata; | ||
1553 | struct woinst *woinst = wave_dev->woinst; | ||
1554 | u32 bytestocopy; | ||
1555 | unsigned long flags; | ||
1556 | |||
1557 | if (!woinst) | ||
1558 | return; | ||
1559 | |||
1560 | spin_lock_irqsave(&woinst->lock, flags); | ||
1561 | |||
1562 | if (!(woinst->state & WAVE_STATE_STARTED)) { | ||
1563 | spin_unlock_irqrestore(&woinst->lock, flags); | ||
1564 | return; | ||
1565 | } | ||
1566 | |||
1567 | emu10k1_waveout_update(woinst); | ||
1568 | emu10k1_waveout_getxfersize(woinst, &bytestocopy); | ||
1569 | |||
1570 | if (woinst->buffer.fill_silence) { | ||
1571 | spin_unlock_irqrestore(&woinst->lock, flags); | ||
1572 | emu10k1_waveout_fillsilence(woinst); | ||
1573 | } else | ||
1574 | spin_unlock_irqrestore(&woinst->lock, flags); | ||
1575 | |||
1576 | if (bytestocopy >= woinst->buffer.fragment_size) { | ||
1577 | if (waitqueue_active(&woinst->wait_queue)) | ||
1578 | wake_up_interruptible(&woinst->wait_queue); | ||
1579 | } else | ||
1580 | DPD(3, "Not enough transfer size -> %d\n", bytestocopy); | ||
1581 | |||
1582 | return; | ||
1583 | } | ||
1584 | |||
1585 | const struct file_operations emu10k1_audio_fops = { | ||
1586 | .owner = THIS_MODULE, | ||
1587 | .llseek = no_llseek, | ||
1588 | .read = emu10k1_audio_read, | ||
1589 | .write = emu10k1_audio_write, | ||
1590 | .poll = emu10k1_audio_poll, | ||
1591 | .ioctl = emu10k1_audio_ioctl, | ||
1592 | .mmap = emu10k1_audio_mmap, | ||
1593 | .open = emu10k1_audio_open, | ||
1594 | .release = emu10k1_audio_release, | ||
1595 | }; | ||