Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
torvalds
GitHub Repository: torvalds/linux
Path: blob/master/sound/isa/sb/sb8_main.c
26424 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
unsigned long flags;
93
struct snd_sb *chip = snd_pcm_substream_chip(substream);
94
struct snd_pcm_runtime *runtime = substream->runtime;
95
unsigned int mixreg, rate, size, count;
96
unsigned char format;
97
unsigned char stereo = runtime->channels > 1;
98
int dma;
99
100
rate = runtime->rate;
101
switch (chip->hardware) {
102
case SB_HW_JAZZ16:
103
if (runtime->format == SNDRV_PCM_FORMAT_S16_LE) {
104
if (chip->mode & SB_MODE_CAPTURE_16)
105
return -EBUSY;
106
else
107
chip->mode |= SB_MODE_PLAYBACK_16;
108
}
109
chip->playback_format = SB_DSP_LO_OUTPUT_AUTO;
110
break;
111
case SB_HW_PRO:
112
if (runtime->channels > 1) {
113
if (snd_BUG_ON(rate != SB8_RATE(11025) &&
114
rate != SB8_RATE(22050)))
115
return -EINVAL;
116
chip->playback_format = SB_DSP_HI_OUTPUT_AUTO;
117
break;
118
}
119
fallthrough;
120
case SB_HW_201:
121
if (rate > 23000) {
122
chip->playback_format = SB_DSP_HI_OUTPUT_AUTO;
123
break;
124
}
125
fallthrough;
126
case SB_HW_20:
127
chip->playback_format = SB_DSP_LO_OUTPUT_AUTO;
128
break;
129
case SB_HW_10:
130
chip->playback_format = SB_DSP_OUTPUT;
131
break;
132
default:
133
return -EINVAL;
134
}
135
if (chip->mode & SB_MODE_PLAYBACK_16) {
136
format = stereo ? SB_DSP_STEREO_16BIT : SB_DSP_MONO_16BIT;
137
dma = chip->dma16;
138
} else {
139
format = stereo ? SB_DSP_STEREO_8BIT : SB_DSP_MONO_8BIT;
140
chip->mode |= SB_MODE_PLAYBACK_8;
141
dma = chip->dma8;
142
}
143
size = chip->p_dma_size = snd_pcm_lib_buffer_bytes(substream);
144
count = chip->p_period_size = snd_pcm_lib_period_bytes(substream);
145
spin_lock_irqsave(&chip->reg_lock, flags);
146
snd_sbdsp_command(chip, SB_DSP_SPEAKER_ON);
147
if (chip->hardware == SB_HW_JAZZ16)
148
snd_sbdsp_command(chip, format);
149
else if (stereo) {
150
/* set playback stereo mode */
151
spin_lock(&chip->mixer_lock);
152
mixreg = snd_sbmixer_read(chip, SB_DSP_STEREO_SW);
153
snd_sbmixer_write(chip, SB_DSP_STEREO_SW, mixreg | 0x02);
154
spin_unlock(&chip->mixer_lock);
155
156
/* Soundblaster hardware programming reference guide, 3-23 */
157
snd_sbdsp_command(chip, SB_DSP_DMA8_EXIT);
158
runtime->dma_area[0] = 0x80;
159
snd_dma_program(dma, runtime->dma_addr, 1, DMA_MODE_WRITE);
160
/* force interrupt */
161
snd_sbdsp_command(chip, SB_DSP_OUTPUT);
162
snd_sbdsp_command(chip, 0);
163
snd_sbdsp_command(chip, 0);
164
}
165
snd_sbdsp_command(chip, SB_DSP_SAMPLE_RATE);
166
if (stereo) {
167
snd_sbdsp_command(chip, 256 - runtime->rate_den / 2);
168
spin_lock(&chip->mixer_lock);
169
/* save output filter status and turn it off */
170
mixreg = snd_sbmixer_read(chip, SB_DSP_PLAYBACK_FILT);
171
snd_sbmixer_write(chip, SB_DSP_PLAYBACK_FILT, mixreg | 0x20);
172
spin_unlock(&chip->mixer_lock);
173
/* just use force_mode16 for temporary storate... */
174
chip->force_mode16 = mixreg;
175
} else {
176
snd_sbdsp_command(chip, 256 - runtime->rate_den);
177
}
178
if (chip->playback_format != SB_DSP_OUTPUT) {
179
if (chip->mode & SB_MODE_PLAYBACK_16)
180
count /= 2;
181
count--;
182
snd_sbdsp_command(chip, SB_DSP_BLOCK_SIZE);
183
snd_sbdsp_command(chip, count & 0xff);
184
snd_sbdsp_command(chip, count >> 8);
185
}
186
spin_unlock_irqrestore(&chip->reg_lock, flags);
187
snd_dma_program(dma, runtime->dma_addr,
188
size, DMA_MODE_WRITE | DMA_AUTOINIT);
189
return 0;
190
}
191
192
static int snd_sb8_playback_trigger(struct snd_pcm_substream *substream,
193
int cmd)
194
{
195
unsigned long flags;
196
struct snd_sb *chip = snd_pcm_substream_chip(substream);
197
unsigned int count;
198
199
spin_lock_irqsave(&chip->reg_lock, flags);
200
switch (cmd) {
201
case SNDRV_PCM_TRIGGER_START:
202
snd_sbdsp_command(chip, chip->playback_format);
203
if (chip->playback_format == SB_DSP_OUTPUT) {
204
count = chip->p_period_size - 1;
205
snd_sbdsp_command(chip, count & 0xff);
206
snd_sbdsp_command(chip, count >> 8);
207
}
208
break;
209
case SNDRV_PCM_TRIGGER_STOP:
210
if (chip->playback_format == SB_DSP_HI_OUTPUT_AUTO) {
211
struct snd_pcm_runtime *runtime = substream->runtime;
212
snd_sbdsp_reset(chip);
213
if (runtime->channels > 1) {
214
spin_lock(&chip->mixer_lock);
215
/* restore output filter and set hardware to mono mode */
216
snd_sbmixer_write(chip, SB_DSP_STEREO_SW, chip->force_mode16 & ~0x02);
217
spin_unlock(&chip->mixer_lock);
218
}
219
} else {
220
snd_sbdsp_command(chip, SB_DSP_DMA8_OFF);
221
}
222
snd_sbdsp_command(chip, SB_DSP_SPEAKER_OFF);
223
}
224
spin_unlock_irqrestore(&chip->reg_lock, flags);
225
return 0;
226
}
227
228
static int snd_sb8_capture_prepare(struct snd_pcm_substream *substream)
229
{
230
unsigned long flags;
231
struct snd_sb *chip = snd_pcm_substream_chip(substream);
232
struct snd_pcm_runtime *runtime = substream->runtime;
233
unsigned int mixreg, rate, size, count;
234
unsigned char format;
235
unsigned char stereo = runtime->channels > 1;
236
int dma;
237
238
rate = runtime->rate;
239
switch (chip->hardware) {
240
case SB_HW_JAZZ16:
241
if (runtime->format == SNDRV_PCM_FORMAT_S16_LE) {
242
if (chip->mode & SB_MODE_PLAYBACK_16)
243
return -EBUSY;
244
else
245
chip->mode |= SB_MODE_CAPTURE_16;
246
}
247
chip->capture_format = SB_DSP_LO_INPUT_AUTO;
248
break;
249
case SB_HW_PRO:
250
if (runtime->channels > 1) {
251
if (snd_BUG_ON(rate != SB8_RATE(11025) &&
252
rate != SB8_RATE(22050)))
253
return -EINVAL;
254
chip->capture_format = SB_DSP_HI_INPUT_AUTO;
255
break;
256
}
257
chip->capture_format = (rate > 23000) ? SB_DSP_HI_INPUT_AUTO : SB_DSP_LO_INPUT_AUTO;
258
break;
259
case SB_HW_201:
260
if (rate > 13000) {
261
chip->capture_format = SB_DSP_HI_INPUT_AUTO;
262
break;
263
}
264
fallthrough;
265
case SB_HW_20:
266
chip->capture_format = SB_DSP_LO_INPUT_AUTO;
267
break;
268
case SB_HW_10:
269
chip->capture_format = SB_DSP_INPUT;
270
break;
271
default:
272
return -EINVAL;
273
}
274
if (chip->mode & SB_MODE_CAPTURE_16) {
275
format = stereo ? SB_DSP_STEREO_16BIT : SB_DSP_MONO_16BIT;
276
dma = chip->dma16;
277
} else {
278
format = stereo ? SB_DSP_STEREO_8BIT : SB_DSP_MONO_8BIT;
279
chip->mode |= SB_MODE_CAPTURE_8;
280
dma = chip->dma8;
281
}
282
size = chip->c_dma_size = snd_pcm_lib_buffer_bytes(substream);
283
count = chip->c_period_size = snd_pcm_lib_period_bytes(substream);
284
spin_lock_irqsave(&chip->reg_lock, flags);
285
snd_sbdsp_command(chip, SB_DSP_SPEAKER_OFF);
286
if (chip->hardware == SB_HW_JAZZ16)
287
snd_sbdsp_command(chip, format);
288
else if (stereo)
289
snd_sbdsp_command(chip, SB_DSP_STEREO_8BIT);
290
snd_sbdsp_command(chip, SB_DSP_SAMPLE_RATE);
291
if (stereo) {
292
snd_sbdsp_command(chip, 256 - runtime->rate_den / 2);
293
spin_lock(&chip->mixer_lock);
294
/* save input filter status and turn it off */
295
mixreg = snd_sbmixer_read(chip, SB_DSP_CAPTURE_FILT);
296
snd_sbmixer_write(chip, SB_DSP_CAPTURE_FILT, mixreg | 0x20);
297
spin_unlock(&chip->mixer_lock);
298
/* just use force_mode16 for temporary storate... */
299
chip->force_mode16 = mixreg;
300
} else {
301
snd_sbdsp_command(chip, 256 - runtime->rate_den);
302
}
303
if (chip->capture_format != SB_DSP_INPUT) {
304
if (chip->mode & SB_MODE_PLAYBACK_16)
305
count /= 2;
306
count--;
307
snd_sbdsp_command(chip, SB_DSP_BLOCK_SIZE);
308
snd_sbdsp_command(chip, count & 0xff);
309
snd_sbdsp_command(chip, count >> 8);
310
}
311
spin_unlock_irqrestore(&chip->reg_lock, flags);
312
snd_dma_program(dma, runtime->dma_addr,
313
size, DMA_MODE_READ | DMA_AUTOINIT);
314
return 0;
315
}
316
317
static int snd_sb8_capture_trigger(struct snd_pcm_substream *substream,
318
int cmd)
319
{
320
unsigned long flags;
321
struct snd_sb *chip = snd_pcm_substream_chip(substream);
322
unsigned int count;
323
324
spin_lock_irqsave(&chip->reg_lock, flags);
325
switch (cmd) {
326
case SNDRV_PCM_TRIGGER_START:
327
snd_sbdsp_command(chip, chip->capture_format);
328
if (chip->capture_format == SB_DSP_INPUT) {
329
count = chip->c_period_size - 1;
330
snd_sbdsp_command(chip, count & 0xff);
331
snd_sbdsp_command(chip, count >> 8);
332
}
333
break;
334
case SNDRV_PCM_TRIGGER_STOP:
335
if (chip->capture_format == SB_DSP_HI_INPUT_AUTO) {
336
struct snd_pcm_runtime *runtime = substream->runtime;
337
snd_sbdsp_reset(chip);
338
if (runtime->channels > 1) {
339
/* restore input filter status */
340
spin_lock(&chip->mixer_lock);
341
snd_sbmixer_write(chip, SB_DSP_CAPTURE_FILT, chip->force_mode16);
342
spin_unlock(&chip->mixer_lock);
343
/* set hardware to mono mode */
344
snd_sbdsp_command(chip, SB_DSP_MONO_8BIT);
345
}
346
} else {
347
snd_sbdsp_command(chip, SB_DSP_DMA8_OFF);
348
}
349
snd_sbdsp_command(chip, SB_DSP_SPEAKER_OFF);
350
}
351
spin_unlock_irqrestore(&chip->reg_lock, flags);
352
return 0;
353
}
354
355
irqreturn_t snd_sb8dsp_interrupt(struct snd_sb *chip)
356
{
357
struct snd_pcm_substream *substream;
358
359
snd_sb_ack_8bit(chip);
360
switch (chip->mode) {
361
case SB_MODE_PLAYBACK_16: /* ok.. playback is active */
362
if (chip->hardware != SB_HW_JAZZ16)
363
break;
364
fallthrough;
365
case SB_MODE_PLAYBACK_8:
366
substream = chip->playback_substream;
367
if (chip->playback_format == SB_DSP_OUTPUT)
368
snd_sb8_playback_trigger(substream, SNDRV_PCM_TRIGGER_START);
369
snd_pcm_period_elapsed(substream);
370
break;
371
case SB_MODE_CAPTURE_16:
372
if (chip->hardware != SB_HW_JAZZ16)
373
break;
374
fallthrough;
375
case SB_MODE_CAPTURE_8:
376
substream = chip->capture_substream;
377
if (chip->capture_format == SB_DSP_INPUT)
378
snd_sb8_capture_trigger(substream, SNDRV_PCM_TRIGGER_START);
379
snd_pcm_period_elapsed(substream);
380
break;
381
}
382
return IRQ_HANDLED;
383
}
384
385
static snd_pcm_uframes_t snd_sb8_playback_pointer(struct snd_pcm_substream *substream)
386
{
387
struct snd_sb *chip = snd_pcm_substream_chip(substream);
388
size_t ptr;
389
int dma;
390
391
if (chip->mode & SB_MODE_PLAYBACK_8)
392
dma = chip->dma8;
393
else if (chip->mode & SB_MODE_PLAYBACK_16)
394
dma = chip->dma16;
395
else
396
return 0;
397
ptr = snd_dma_pointer(dma, chip->p_dma_size);
398
return bytes_to_frames(substream->runtime, ptr);
399
}
400
401
static snd_pcm_uframes_t snd_sb8_capture_pointer(struct snd_pcm_substream *substream)
402
{
403
struct snd_sb *chip = snd_pcm_substream_chip(substream);
404
size_t ptr;
405
int dma;
406
407
if (chip->mode & SB_MODE_CAPTURE_8)
408
dma = chip->dma8;
409
else if (chip->mode & SB_MODE_CAPTURE_16)
410
dma = chip->dma16;
411
else
412
return 0;
413
ptr = snd_dma_pointer(dma, chip->c_dma_size);
414
return bytes_to_frames(substream->runtime, ptr);
415
}
416
417
/*
418
419
*/
420
421
static const struct snd_pcm_hardware snd_sb8_playback =
422
{
423
.info = (SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_INTERLEAVED |
424
SNDRV_PCM_INFO_MMAP_VALID),
425
.formats = SNDRV_PCM_FMTBIT_U8,
426
.rates = (SNDRV_PCM_RATE_CONTINUOUS | SNDRV_PCM_RATE_8000 |
427
SNDRV_PCM_RATE_11025 | SNDRV_PCM_RATE_22050),
428
.rate_min = 4000,
429
.rate_max = 23000,
430
.channels_min = 1,
431
.channels_max = 1,
432
.buffer_bytes_max = 65536,
433
.period_bytes_min = 64,
434
.period_bytes_max = 65536,
435
.periods_min = 1,
436
.periods_max = 1024,
437
.fifo_size = 0,
438
};
439
440
static const struct snd_pcm_hardware snd_sb8_capture =
441
{
442
.info = (SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_INTERLEAVED |
443
SNDRV_PCM_INFO_MMAP_VALID),
444
.formats = SNDRV_PCM_FMTBIT_U8,
445
.rates = (SNDRV_PCM_RATE_CONTINUOUS | SNDRV_PCM_RATE_8000 |
446
SNDRV_PCM_RATE_11025),
447
.rate_min = 4000,
448
.rate_max = 13000,
449
.channels_min = 1,
450
.channels_max = 1,
451
.buffer_bytes_max = 65536,
452
.period_bytes_min = 64,
453
.period_bytes_max = 65536,
454
.periods_min = 1,
455
.periods_max = 1024,
456
.fifo_size = 0,
457
};
458
459
/*
460
*
461
*/
462
463
static int snd_sb8_open(struct snd_pcm_substream *substream)
464
{
465
struct snd_sb *chip = snd_pcm_substream_chip(substream);
466
struct snd_pcm_runtime *runtime = substream->runtime;
467
unsigned long flags;
468
469
spin_lock_irqsave(&chip->open_lock, flags);
470
if (chip->open) {
471
spin_unlock_irqrestore(&chip->open_lock, flags);
472
return -EAGAIN;
473
}
474
chip->open |= SB_OPEN_PCM;
475
spin_unlock_irqrestore(&chip->open_lock, flags);
476
if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
477
chip->playback_substream = substream;
478
runtime->hw = snd_sb8_playback;
479
} else {
480
chip->capture_substream = substream;
481
runtime->hw = snd_sb8_capture;
482
}
483
switch (chip->hardware) {
484
case SB_HW_JAZZ16:
485
if (chip->dma16 == 5 || chip->dma16 == 7)
486
runtime->hw.formats |= SNDRV_PCM_FMTBIT_S16_LE;
487
runtime->hw.rates |= SNDRV_PCM_RATE_8000_48000;
488
runtime->hw.rate_min = 4000;
489
runtime->hw.rate_max = 50000;
490
runtime->hw.channels_max = 2;
491
break;
492
case SB_HW_PRO:
493
runtime->hw.rate_max = 44100;
494
runtime->hw.channels_max = 2;
495
snd_pcm_hw_rule_add(runtime, 0, SNDRV_PCM_HW_PARAM_RATE,
496
snd_sb8_hw_constraint_rate_channels, NULL,
497
SNDRV_PCM_HW_PARAM_CHANNELS,
498
SNDRV_PCM_HW_PARAM_RATE, -1);
499
snd_pcm_hw_rule_add(runtime, 0, SNDRV_PCM_HW_PARAM_CHANNELS,
500
snd_sb8_hw_constraint_channels_rate, NULL,
501
SNDRV_PCM_HW_PARAM_RATE, -1);
502
break;
503
case SB_HW_201:
504
if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
505
runtime->hw.rate_max = 44100;
506
} else {
507
runtime->hw.rate_max = 15000;
508
}
509
break;
510
default:
511
break;
512
}
513
snd_pcm_hw_constraint_ratnums(runtime, 0, SNDRV_PCM_HW_PARAM_RATE,
514
&hw_constraints_clock);
515
if (chip->dma8 > 3 || chip->dma16 >= 0) {
516
snd_pcm_hw_constraint_step(runtime, 0,
517
SNDRV_PCM_HW_PARAM_BUFFER_BYTES, 2);
518
snd_pcm_hw_constraint_step(runtime, 0,
519
SNDRV_PCM_HW_PARAM_PERIOD_BYTES, 2);
520
runtime->hw.buffer_bytes_max = 128 * 1024 * 1024;
521
runtime->hw.period_bytes_max = 128 * 1024 * 1024;
522
}
523
return 0;
524
}
525
526
static int snd_sb8_close(struct snd_pcm_substream *substream)
527
{
528
unsigned long flags;
529
struct snd_sb *chip = snd_pcm_substream_chip(substream);
530
531
chip->playback_substream = NULL;
532
chip->capture_substream = NULL;
533
spin_lock_irqsave(&chip->open_lock, flags);
534
chip->open &= ~SB_OPEN_PCM;
535
if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
536
chip->mode &= ~SB_MODE_PLAYBACK;
537
else
538
chip->mode &= ~SB_MODE_CAPTURE;
539
spin_unlock_irqrestore(&chip->open_lock, flags);
540
return 0;
541
}
542
543
/*
544
* Initialization part
545
*/
546
547
static const struct snd_pcm_ops snd_sb8_playback_ops = {
548
.open = snd_sb8_open,
549
.close = snd_sb8_close,
550
.prepare = snd_sb8_playback_prepare,
551
.trigger = snd_sb8_playback_trigger,
552
.pointer = snd_sb8_playback_pointer,
553
};
554
555
static const struct snd_pcm_ops snd_sb8_capture_ops = {
556
.open = snd_sb8_open,
557
.close = snd_sb8_close,
558
.prepare = snd_sb8_capture_prepare,
559
.trigger = snd_sb8_capture_trigger,
560
.pointer = snd_sb8_capture_pointer,
561
};
562
563
int snd_sb8dsp_pcm(struct snd_sb *chip, int device)
564
{
565
struct snd_card *card = chip->card;
566
struct snd_pcm *pcm;
567
int err;
568
size_t max_prealloc = 64 * 1024;
569
570
err = snd_pcm_new(card, "SB8 DSP", device, 1, 1, &pcm);
571
if (err < 0)
572
return err;
573
sprintf(pcm->name, "DSP v%i.%i", chip->version >> 8, chip->version & 0xff);
574
pcm->info_flags = SNDRV_PCM_INFO_HALF_DUPLEX;
575
pcm->private_data = chip;
576
577
snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, &snd_sb8_playback_ops);
578
snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, &snd_sb8_capture_ops);
579
580
if (chip->dma8 > 3 || chip->dma16 >= 0)
581
max_prealloc = 128 * 1024;
582
snd_pcm_set_managed_buffer_all(pcm, SNDRV_DMA_TYPE_DEV,
583
card->dev, 64*1024, max_prealloc);
584
585
return 0;
586
}
587
588
EXPORT_SYMBOL(snd_sb8dsp_pcm);
589
EXPORT_SYMBOL(snd_sb8dsp_interrupt);
590
/* sb8_midi.c */
591
EXPORT_SYMBOL(snd_sb8dsp_midi_interrupt);
592
EXPORT_SYMBOL(snd_sb8dsp_midi);
593
594