File Index
Files and directories
Sign in
FILE

sb8_main.c

File preview with syntax highlighting.

linux-6.19.14/sound/isa/sb/sb8_main.c C
  1// SPDX-License-Identifier: GPL-2.0-or-later
  2/*
  3 *  Copyright (c) by Jaroslav Kysela <perex@perex.cz>
  4 *                   Uros Bizjak <uros@kss-loka.si>
  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 <gdm@gedamo.demon.co.uk>
 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 <uros@kss-loka.si>
 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
 27MODULE_AUTHOR("Jaroslav Kysela <perex@perex.cz>, Uros Bizjak <uros@kss-loka.si>");
 28MODULE_DESCRIPTION("Routines for control of 8-bit SoundBlaster cards and clones");
 29MODULE_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
 35static const struct snd_ratnum clock = {
 36	.num = SB8_CLOCK,
 37	.den_min = 1,
 38	.den_max = 256,
 39	.den_step = 1,
 40};
 41
 42static const struct snd_pcm_hw_constraint_ratnums hw_constraints_clock = {
 43	.nrats = 1,
 44	.rats = &clock,
 45};
 46
 47static 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
 62static 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
 79static 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
 90static 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
191static 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
224static 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
312static 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
348irqreturn_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
378static 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
394static 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
414static 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
433static 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 
456static 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
516static 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 
535static 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
543static 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
551int 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
576EXPORT_SYMBOL(snd_sb8dsp_pcm);
577EXPORT_SYMBOL(snd_sb8dsp_interrupt);
578  /* sb8_midi.c */
579EXPORT_SYMBOL(snd_sb8dsp_midi_interrupt);
580EXPORT_SYMBOL(snd_sb8dsp_midi);
~/ Read-only file preview.