Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
torvalds
GitHub Repository: torvalds/linux
Path: blob/master/sound/isa/sb/sb8_main.c
29269 views
1
// SPDX-License-Identifier: GPL-2.0-or-later
2
/*
3
* Copyright (c) by Jaroslav Kysela <[email protected]>
4
* Uros Bizjak <[email protected]>
5
*
6
* Routines for control of 8-bit SoundBlaster cards and clones
7
* Please note: I don't have access to old SB8 soundcards.
8
*
9
* --
10
*
11
* Thu Apr 29 20:36:17 BST 1999 George David Morrison <[email protected]>
12
* DSP can't respond to commands whilst in "high speed" mode. Caused
13
* glitching during playback. Fixed.
14
*
15
* Wed Jul 12 22:02:55 CEST 2000 Uros Bizjak <[email protected]>
16
* Cleaned up and rewrote lowlevel routines.
17
*/
18
19
#include <linux/io.h>
20
#include <asm/dma.h>
21
#include <linux/init.h>
22
#include <linux/time.h>
23
#include <linux/module.h>
24
#include <sound/core.h>
25
#include <sound/sb.h>
26
27
MODULE_AUTHOR("Jaroslav Kysela <[email protected]>, Uros Bizjak <[email protected]>");
28
MODULE_DESCRIPTION("Routines for control of 8-bit SoundBlaster cards and clones");
29
MODULE_LICENSE("GPL");
30
31
#define SB8_CLOCK 1000000
32
#define SB8_DEN(v) ((SB8_CLOCK + (v) / 2) / (v))
33
#define SB8_RATE(v) (SB8_CLOCK / SB8_DEN(v))
34
35
static const struct snd_ratnum clock = {
36
.num = SB8_CLOCK,
37
.den_min = 1,
38
.den_max = 256,
39
.den_step = 1,
40
};
41
42
static const struct snd_pcm_hw_constraint_ratnums hw_constraints_clock = {
43
.nrats = 1,
44
.rats = &clock,
45
};
46
47
static const struct snd_ratnum stereo_clocks[] = {
48
{
49
.num = SB8_CLOCK,
50
.den_min = SB8_DEN(22050),
51
.den_max = SB8_DEN(22050),
52
.den_step = 1,
53
},
54
{
55
.num = SB8_CLOCK,
56
.den_min = SB8_DEN(11025),
57
.den_max = SB8_DEN(11025),
58
.den_step = 1,
59
}
60
};
61
62
static int snd_sb8_hw_constraint_rate_channels(struct snd_pcm_hw_params *params,
63
struct snd_pcm_hw_rule *rule)
64
{
65
struct snd_interval *c = hw_param_interval(params, SNDRV_PCM_HW_PARAM_CHANNELS);
66
if (c->min > 1) {
67
unsigned int num = 0, den = 0;
68
int err = snd_interval_ratnum(hw_param_interval(params, SNDRV_PCM_HW_PARAM_RATE),
69
2, stereo_clocks, &num, &den);
70
if (err >= 0 && den) {
71
params->rate_num = num;
72
params->rate_den = den;
73
}
74
return err;
75
}
76
return 0;
77
}
78
79
static int snd_sb8_hw_constraint_channels_rate(struct snd_pcm_hw_params *params,
80
struct snd_pcm_hw_rule *rule)
81
{
82
struct snd_interval *r = hw_param_interval(params, SNDRV_PCM_HW_PARAM_RATE);
83
if (r->min > SB8_RATE(22050) || r->max <= SB8_RATE(11025)) {
84
struct snd_interval t = { .min = 1, .max = 1 };
85
return snd_interval_refine(hw_param_interval(params, SNDRV_PCM_HW_PARAM_CHANNELS), &t);
86
}
87
return 0;
88
}
89
90
static int snd_sb8_playback_prepare(struct snd_pcm_substream *substream)
91
{
92
struct snd_sb *chip = snd_pcm_substream_chip(substream);
93
struct snd_pcm_runtime *runtime = substream->runtime;
94
unsigned int mixreg, rate, size, count;
95
unsigned char format;
96
unsigned char stereo = runtime->channels > 1;
97
int dma;
98
99
rate = runtime->rate;
100
switch (chip->hardware) {
101
case SB_HW_JAZZ16:
102
if (runtime->format == SNDRV_PCM_FORMAT_S16_LE) {
103
if (chip->mode & SB_MODE_CAPTURE_16)
104
return -EBUSY;
105
else
106
chip->mode |= SB_MODE_PLAYBACK_16;
107
}
108
chip->playback_format = SB_DSP_LO_OUTPUT_AUTO;
109
break;
110
case SB_HW_PRO:
111
if (runtime->channels > 1) {
112
if (snd_BUG_ON(rate != SB8_RATE(11025) &&
113
rate != SB8_RATE(22050)))
114
return -EINVAL;
115
chip->playback_format = SB_DSP_HI_OUTPUT_AUTO;
116
break;
117
}
118
fallthrough;
119
case SB_HW_201:
120
if (rate > 23000) {
121
chip->playback_format = SB_DSP_HI_OUTPUT_AUTO;
122
break;
123
}
124
fallthrough;
125
case SB_HW_20:
126
chip->playback_format = SB_DSP_LO_OUTPUT_AUTO;
127
break;
128
case SB_HW_10:
129
chip->playback_format = SB_DSP_OUTPUT;
130
break;
131
default:
132
return -EINVAL;
133
}
134
if (chip->mode & SB_MODE_PLAYBACK_16) {
135
format = stereo ? SB_DSP_STEREO_16BIT : SB_DSP_MONO_16BIT;
136
dma = chip->dma16;
137
} else {
138
format = stereo ? SB_DSP_STEREO_8BIT : SB_DSP_MONO_8BIT;
139
chip->mode |= SB_MODE_PLAYBACK_8;
140
dma = chip->dma8;
141
}
142
size = chip->p_dma_size = snd_pcm_lib_buffer_bytes(substream);
143
count = chip->p_period_size = snd_pcm_lib_period_bytes(substream);
144
scoped_guard(spinlock_irqsave, &chip->reg_lock) {
145
snd_sbdsp_command(chip, SB_DSP_SPEAKER_ON);
146
if (chip->hardware == SB_HW_JAZZ16)
147
snd_sbdsp_command(chip, format);
148
else if (stereo) {
149
/* set playback stereo mode */
150
scoped_guard(spinlock, &chip->mixer_lock) {
151
mixreg = snd_sbmixer_read(chip, SB_DSP_STEREO_SW);
152
snd_sbmixer_write(chip, SB_DSP_STEREO_SW, mixreg | 0x02);
153
}
154
155
/* Soundblaster hardware programming reference guide, 3-23 */
156
snd_sbdsp_command(chip, SB_DSP_DMA8_EXIT);
157
runtime->dma_area[0] = 0x80;
158
snd_dma_program(dma, runtime->dma_addr, 1, DMA_MODE_WRITE);
159
/* force interrupt */
160
snd_sbdsp_command(chip, SB_DSP_OUTPUT);
161
snd_sbdsp_command(chip, 0);
162
snd_sbdsp_command(chip, 0);
163
}
164
snd_sbdsp_command(chip, SB_DSP_SAMPLE_RATE);
165
if (stereo) {
166
snd_sbdsp_command(chip, 256 - runtime->rate_den / 2);
167
scoped_guard(spinlock, &chip->mixer_lock) {
168
/* save output filter status and turn it off */
169
mixreg = snd_sbmixer_read(chip, SB_DSP_PLAYBACK_FILT);
170
snd_sbmixer_write(chip, SB_DSP_PLAYBACK_FILT, mixreg | 0x20);
171
}
172
/* just use force_mode16 for temporary storate... */
173
chip->force_mode16 = mixreg;
174
} else {
175
snd_sbdsp_command(chip, 256 - runtime->rate_den);
176
}
177
if (chip->playback_format != SB_DSP_OUTPUT) {
178
if (chip->mode & SB_MODE_PLAYBACK_16)
179
count /= 2;
180
count--;
181
snd_sbdsp_command(chip, SB_DSP_BLOCK_SIZE);
182
snd_sbdsp_command(chip, count & 0xff);
183
snd_sbdsp_command(chip, count >> 8);
184
}
185
}
186
snd_dma_program(dma, runtime->dma_addr,
187
size, DMA_MODE_WRITE | DMA_AUTOINIT);
188
return 0;
189
}
190
191
static int snd_sb8_playback_trigger(struct snd_pcm_substream *substream,
192
int cmd)
193
{
194
struct snd_sb *chip = snd_pcm_substream_chip(substream);
195
unsigned int count;
196
197
guard(spinlock_irqsave)(&chip->reg_lock);
198
switch (cmd) {
199
case SNDRV_PCM_TRIGGER_START:
200
snd_sbdsp_command(chip, chip->playback_format);
201
if (chip->playback_format == SB_DSP_OUTPUT) {
202
count = chip->p_period_size - 1;
203
snd_sbdsp_command(chip, count & 0xff);
204
snd_sbdsp_command(chip, count >> 8);
205
}
206
break;
207
case SNDRV_PCM_TRIGGER_STOP:
208
if (chip->playback_format == SB_DSP_HI_OUTPUT_AUTO) {
209
struct snd_pcm_runtime *runtime = substream->runtime;
210
snd_sbdsp_reset(chip);
211
if (runtime->channels > 1) {
212
guard(spinlock)(&chip->mixer_lock);
213
/* restore output filter and set hardware to mono mode */
214
snd_sbmixer_write(chip, SB_DSP_STEREO_SW, chip->force_mode16 & ~0x02);
215
}
216
} else {
217
snd_sbdsp_command(chip, SB_DSP_DMA8_OFF);
218
}
219
snd_sbdsp_command(chip, SB_DSP_SPEAKER_OFF);
220
}
221
return 0;
222
}
223
224
static int snd_sb8_capture_prepare(struct snd_pcm_substream *substream)
225
{
226
struct snd_sb *chip = snd_pcm_substream_chip(substream);
227
struct snd_pcm_runtime *runtime = substream->runtime;
228
unsigned int mixreg, rate, size, count;
229
unsigned char format;
230
unsigned char stereo = runtime->channels > 1;
231
int dma;
232
233
rate = runtime->rate;
234
switch (chip->hardware) {
235
case SB_HW_JAZZ16:
236
if (runtime->format == SNDRV_PCM_FORMAT_S16_LE) {
237
if (chip->mode & SB_MODE_PLAYBACK_16)
238
return -EBUSY;
239
else
240
chip->mode |= SB_MODE_CAPTURE_16;
241
}
242
chip->capture_format = SB_DSP_LO_INPUT_AUTO;
243
break;
244
case SB_HW_PRO:
245
if (runtime->channels > 1) {
246
if (snd_BUG_ON(rate != SB8_RATE(11025) &&
247
rate != SB8_RATE(22050)))
248
return -EINVAL;
249
chip->capture_format = SB_DSP_HI_INPUT_AUTO;
250
break;
251
}
252
chip->capture_format = (rate > 23000) ? SB_DSP_HI_INPUT_AUTO : SB_DSP_LO_INPUT_AUTO;
253
break;
254
case SB_HW_201:
255
if (rate > 13000) {
256
chip->capture_format = SB_DSP_HI_INPUT_AUTO;
257
break;
258
}
259
fallthrough;
260
case SB_HW_20:
261
chip->capture_format = SB_DSP_LO_INPUT_AUTO;
262
break;
263
case SB_HW_10:
264
chip->capture_format = SB_DSP_INPUT;
265
break;
266
default:
267
return -EINVAL;
268
}
269
if (chip->mode & SB_MODE_CAPTURE_16) {
270
format = stereo ? SB_DSP_STEREO_16BIT : SB_DSP_MONO_16BIT;
271
dma = chip->dma16;
272
} else {
273
format = stereo ? SB_DSP_STEREO_8BIT : SB_DSP_MONO_8BIT;
274
chip->mode |= SB_MODE_CAPTURE_8;
275
dma = chip->dma8;
276
}
277
size = chip->c_dma_size = snd_pcm_lib_buffer_bytes(substream);
278
count = chip->c_period_size = snd_pcm_lib_period_bytes(substream);
279
scoped_guard(spinlock_irqsave, &chip->reg_lock) {
280
snd_sbdsp_command(chip, SB_DSP_SPEAKER_OFF);
281
if (chip->hardware == SB_HW_JAZZ16)
282
snd_sbdsp_command(chip, format);
283
else if (stereo)
284
snd_sbdsp_command(chip, SB_DSP_STEREO_8BIT);
285
snd_sbdsp_command(chip, SB_DSP_SAMPLE_RATE);
286
if (stereo) {
287
snd_sbdsp_command(chip, 256 - runtime->rate_den / 2);
288
scoped_guard(spinlock, &chip->mixer_lock) {
289
/* save input filter status and turn it off */
290
mixreg = snd_sbmixer_read(chip, SB_DSP_CAPTURE_FILT);
291
snd_sbmixer_write(chip, SB_DSP_CAPTURE_FILT, mixreg | 0x20);
292
}
293
/* just use force_mode16 for temporary storate... */
294
chip->force_mode16 = mixreg;
295
} else {
296
snd_sbdsp_command(chip, 256 - runtime->rate_den);
297
}
298
if (chip->capture_format != SB_DSP_INPUT) {
299
if (chip->mode & SB_MODE_PLAYBACK_16)
300
count /= 2;
301
count--;
302
snd_sbdsp_command(chip, SB_DSP_BLOCK_SIZE);
303
snd_sbdsp_command(chip, count & 0xff);
304
snd_sbdsp_command(chip, count >> 8);
305
}
306
}
307
snd_dma_program(dma, runtime->dma_addr,
308
size, DMA_MODE_READ | DMA_AUTOINIT);
309
return 0;
310
}
311
312
static int snd_sb8_capture_trigger(struct snd_pcm_substream *substream,
313
int cmd)
314
{
315
struct snd_sb *chip = snd_pcm_substream_chip(substream);
316
unsigned int count;
317
318
guard(spinlock_irqsave)(&chip->reg_lock);
319
switch (cmd) {
320
case SNDRV_PCM_TRIGGER_START:
321
snd_sbdsp_command(chip, chip->capture_format);
322
if (chip->capture_format == SB_DSP_INPUT) {
323
count = chip->c_period_size - 1;
324
snd_sbdsp_command(chip, count & 0xff);
325
snd_sbdsp_command(chip, count >> 8);
326
}
327
break;
328
case SNDRV_PCM_TRIGGER_STOP:
329
if (chip->capture_format == SB_DSP_HI_INPUT_AUTO) {
330
struct snd_pcm_runtime *runtime = substream->runtime;
331
snd_sbdsp_reset(chip);
332
if (runtime->channels > 1) {
333
/* restore input filter status */
334
scoped_guard(spinlock, &chip->mixer_lock) {
335
snd_sbmixer_write(chip, SB_DSP_CAPTURE_FILT, chip->force_mode16);
336
}
337
/* set hardware to mono mode */
338
snd_sbdsp_command(chip, SB_DSP_MONO_8BIT);
339
}
340
} else {
341
snd_sbdsp_command(chip, SB_DSP_DMA8_OFF);
342
}
343
snd_sbdsp_command(chip, SB_DSP_SPEAKER_OFF);
344
}
345
return 0;
346
}
347
348
irqreturn_t snd_sb8dsp_interrupt(struct snd_sb *chip)
349
{
350
struct snd_pcm_substream *substream;
351
352
snd_sb_ack_8bit(chip);
353
switch (chip->mode) {
354
case SB_MODE_PLAYBACK_16: /* ok.. playback is active */
355
if (chip->hardware != SB_HW_JAZZ16)
356
break;
357
fallthrough;
358
case SB_MODE_PLAYBACK_8:
359
substream = chip->playback_substream;
360
if (chip->playback_format == SB_DSP_OUTPUT)
361
snd_sb8_playback_trigger(substream, SNDRV_PCM_TRIGGER_START);
362
snd_pcm_period_elapsed(substream);
363
break;
364
case SB_MODE_CAPTURE_16:
365
if (chip->hardware != SB_HW_JAZZ16)
366
break;
367
fallthrough;
368
case SB_MODE_CAPTURE_8:
369
substream = chip->capture_substream;
370
if (chip->capture_format == SB_DSP_INPUT)
371
snd_sb8_capture_trigger(substream, SNDRV_PCM_TRIGGER_START);
372
snd_pcm_period_elapsed(substream);
373
break;
374
}
375
return IRQ_HANDLED;
376
}
377
378
static snd_pcm_uframes_t snd_sb8_playback_pointer(struct snd_pcm_substream *substream)
379
{
380
struct snd_sb *chip = snd_pcm_substream_chip(substream);
381
size_t ptr;
382
int dma;
383
384
if (chip->mode & SB_MODE_PLAYBACK_8)
385
dma = chip->dma8;
386
else if (chip->mode & SB_MODE_PLAYBACK_16)
387
dma = chip->dma16;
388
else
389
return 0;
390
ptr = snd_dma_pointer(dma, chip->p_dma_size);
391
return bytes_to_frames(substream->runtime, ptr);
392
}
393
394
static snd_pcm_uframes_t snd_sb8_capture_pointer(struct snd_pcm_substream *substream)
395
{
396
struct snd_sb *chip = snd_pcm_substream_chip(substream);
397
size_t ptr;
398
int dma;
399
400
if (chip->mode & SB_MODE_CAPTURE_8)
401
dma = chip->dma8;
402
else if (chip->mode & SB_MODE_CAPTURE_16)
403
dma = chip->dma16;
404
else
405
return 0;
406
ptr = snd_dma_pointer(dma, chip->c_dma_size);
407
return bytes_to_frames(substream->runtime, ptr);
408
}
409
410
/*
411
412
*/
413
414
static const struct snd_pcm_hardware snd_sb8_playback =
415
{
416
.info = (SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_INTERLEAVED |
417
SNDRV_PCM_INFO_MMAP_VALID),
418
.formats = SNDRV_PCM_FMTBIT_U8,
419
.rates = (SNDRV_PCM_RATE_CONTINUOUS | SNDRV_PCM_RATE_8000 |
420
SNDRV_PCM_RATE_11025 | SNDRV_PCM_RATE_22050),
421
.rate_min = 4000,
422
.rate_max = 23000,
423
.channels_min = 1,
424
.channels_max = 1,
425
.buffer_bytes_max = 65536,
426
.period_bytes_min = 64,
427
.period_bytes_max = 65536,
428
.periods_min = 1,
429
.periods_max = 1024,
430
.fifo_size = 0,
431
};
432
433
static const struct snd_pcm_hardware snd_sb8_capture =
434
{
435
.info = (SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_INTERLEAVED |
436
SNDRV_PCM_INFO_MMAP_VALID),
437
.formats = SNDRV_PCM_FMTBIT_U8,
438
.rates = (SNDRV_PCM_RATE_CONTINUOUS | SNDRV_PCM_RATE_8000 |
439
SNDRV_PCM_RATE_11025),
440
.rate_min = 4000,
441
.rate_max = 13000,
442
.channels_min = 1,
443
.channels_max = 1,
444
.buffer_bytes_max = 65536,
445
.period_bytes_min = 64,
446
.period_bytes_max = 65536,
447
.periods_min = 1,
448
.periods_max = 1024,
449
.fifo_size = 0,
450
};
451
452
/*
453
*
454
*/
455
456
static int snd_sb8_open(struct snd_pcm_substream *substream)
457
{
458
struct snd_sb *chip = snd_pcm_substream_chip(substream);
459
struct snd_pcm_runtime *runtime = substream->runtime;
460
461
scoped_guard(spinlock_irqsave, &chip->open_lock) {
462
if (chip->open)
463
return -EAGAIN;
464
chip->open |= SB_OPEN_PCM;
465
}
466
if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
467
chip->playback_substream = substream;
468
runtime->hw = snd_sb8_playback;
469
} else {
470
chip->capture_substream = substream;
471
runtime->hw = snd_sb8_capture;
472
}
473
switch (chip->hardware) {
474
case SB_HW_JAZZ16:
475
if (chip->dma16 == 5 || chip->dma16 == 7)
476
runtime->hw.formats |= SNDRV_PCM_FMTBIT_S16_LE;
477
runtime->hw.rates |= SNDRV_PCM_RATE_8000_48000;
478
runtime->hw.rate_min = 4000;
479
runtime->hw.rate_max = 50000;
480
runtime->hw.channels_max = 2;
481
break;
482
case SB_HW_PRO:
483
runtime->hw.rate_max = 44100;
484
runtime->hw.channels_max = 2;
485
snd_pcm_hw_rule_add(runtime, 0, SNDRV_PCM_HW_PARAM_RATE,
486
snd_sb8_hw_constraint_rate_channels, NULL,
487
SNDRV_PCM_HW_PARAM_CHANNELS,
488
SNDRV_PCM_HW_PARAM_RATE, -1);
489
snd_pcm_hw_rule_add(runtime, 0, SNDRV_PCM_HW_PARAM_CHANNELS,
490
snd_sb8_hw_constraint_channels_rate, NULL,
491
SNDRV_PCM_HW_PARAM_RATE, -1);
492
break;
493
case SB_HW_201:
494
if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
495
runtime->hw.rate_max = 44100;
496
} else {
497
runtime->hw.rate_max = 15000;
498
}
499
break;
500
default:
501
break;
502
}
503
snd_pcm_hw_constraint_ratnums(runtime, 0, SNDRV_PCM_HW_PARAM_RATE,
504
&hw_constraints_clock);
505
if (chip->dma8 > 3 || chip->dma16 >= 0) {
506
snd_pcm_hw_constraint_step(runtime, 0,
507
SNDRV_PCM_HW_PARAM_BUFFER_BYTES, 2);
508
snd_pcm_hw_constraint_step(runtime, 0,
509
SNDRV_PCM_HW_PARAM_PERIOD_BYTES, 2);
510
runtime->hw.buffer_bytes_max = 128 * 1024 * 1024;
511
runtime->hw.period_bytes_max = 128 * 1024 * 1024;
512
}
513
return 0;
514
}
515
516
static int snd_sb8_close(struct snd_pcm_substream *substream)
517
{
518
struct snd_sb *chip = snd_pcm_substream_chip(substream);
519
520
chip->playback_substream = NULL;
521
chip->capture_substream = NULL;
522
guard(spinlock_irqsave)(&chip->open_lock);
523
chip->open &= ~SB_OPEN_PCM;
524
if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
525
chip->mode &= ~SB_MODE_PLAYBACK;
526
else
527
chip->mode &= ~SB_MODE_CAPTURE;
528
return 0;
529
}
530
531
/*
532
* Initialization part
533
*/
534
535
static const struct snd_pcm_ops snd_sb8_playback_ops = {
536
.open = snd_sb8_open,
537
.close = snd_sb8_close,
538
.prepare = snd_sb8_playback_prepare,
539
.trigger = snd_sb8_playback_trigger,
540
.pointer = snd_sb8_playback_pointer,
541
};
542
543
static const struct snd_pcm_ops snd_sb8_capture_ops = {
544
.open = snd_sb8_open,
545
.close = snd_sb8_close,
546
.prepare = snd_sb8_capture_prepare,
547
.trigger = snd_sb8_capture_trigger,
548
.pointer = snd_sb8_capture_pointer,
549
};
550
551
int snd_sb8dsp_pcm(struct snd_sb *chip, int device)
552
{
553
struct snd_card *card = chip->card;
554
struct snd_pcm *pcm;
555
int err;
556
size_t max_prealloc = 64 * 1024;
557
558
err = snd_pcm_new(card, "SB8 DSP", device, 1, 1, &pcm);
559
if (err < 0)
560
return err;
561
sprintf(pcm->name, "DSP v%i.%i", chip->version >> 8, chip->version & 0xff);
562
pcm->info_flags = SNDRV_PCM_INFO_HALF_DUPLEX;
563
pcm->private_data = chip;
564
565
snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, &snd_sb8_playback_ops);
566
snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, &snd_sb8_capture_ops);
567
568
if (chip->dma8 > 3 || chip->dma16 >= 0)
569
max_prealloc = 128 * 1024;
570
snd_pcm_set_managed_buffer_all(pcm, SNDRV_DMA_TYPE_DEV,
571
card->dev, 64*1024, max_prealloc);
572
573
return 0;
574
}
575
576
EXPORT_SYMBOL(snd_sb8dsp_pcm);
577
EXPORT_SYMBOL(snd_sb8dsp_interrupt);
578
/* sb8_midi.c */
579
EXPORT_SYMBOL(snd_sb8dsp_midi_interrupt);
580
EXPORT_SYMBOL(snd_sb8dsp_midi);
581
582