xref: /openbmc/linux/sound/isa/sb/sb8_main.c (revision 8e20ba2e)
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 
27 MODULE_AUTHOR("Jaroslav Kysela <perex@perex.cz>, Uros Bizjak <uros@kss-loka.si>");
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 		/* fall through */
120 	case SB_HW_201:
121 		if (rate > 23000) {
122 			chip->playback_format = SB_DSP_HI_OUTPUT_AUTO;
123 			break;
124 		}
125 		/* fall through */
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_hw_params(struct snd_pcm_substream *substream,
229 			     struct snd_pcm_hw_params *hw_params)
230 {
231 	return snd_pcm_lib_malloc_pages(substream, params_buffer_bytes(hw_params));
232 }
233 
234 static int snd_sb8_hw_free(struct snd_pcm_substream *substream)
235 {
236 	snd_pcm_lib_free_pages(substream);
237 	return 0;
238 }
239 
240 static int snd_sb8_capture_prepare(struct snd_pcm_substream *substream)
241 {
242 	unsigned long flags;
243 	struct snd_sb *chip = snd_pcm_substream_chip(substream);
244 	struct snd_pcm_runtime *runtime = substream->runtime;
245 	unsigned int mixreg, rate, size, count;
246 	unsigned char format;
247 	unsigned char stereo = runtime->channels > 1;
248 	int dma;
249 
250 	rate = runtime->rate;
251 	switch (chip->hardware) {
252 	case SB_HW_JAZZ16:
253 		if (runtime->format == SNDRV_PCM_FORMAT_S16_LE) {
254 			if (chip->mode & SB_MODE_PLAYBACK_16)
255 				return -EBUSY;
256 			else
257 				chip->mode |= SB_MODE_CAPTURE_16;
258 		}
259 		chip->capture_format = SB_DSP_LO_INPUT_AUTO;
260 		break;
261 	case SB_HW_PRO:
262 		if (runtime->channels > 1) {
263 			if (snd_BUG_ON(rate != SB8_RATE(11025) &&
264 				       rate != SB8_RATE(22050)))
265 				return -EINVAL;
266 			chip->capture_format = SB_DSP_HI_INPUT_AUTO;
267 			break;
268 		}
269 		chip->capture_format = (rate > 23000) ? SB_DSP_HI_INPUT_AUTO : SB_DSP_LO_INPUT_AUTO;
270 		break;
271 	case SB_HW_201:
272 		if (rate > 13000) {
273 			chip->capture_format = SB_DSP_HI_INPUT_AUTO;
274 			break;
275 		}
276 		/* fall through */
277 	case SB_HW_20:
278 		chip->capture_format = SB_DSP_LO_INPUT_AUTO;
279 		break;
280 	case SB_HW_10:
281 		chip->capture_format = SB_DSP_INPUT;
282 		break;
283 	default:
284 		return -EINVAL;
285 	}
286 	if (chip->mode & SB_MODE_CAPTURE_16) {
287 		format = stereo ? SB_DSP_STEREO_16BIT : SB_DSP_MONO_16BIT;
288 		dma = chip->dma16;
289 	} else {
290 		format = stereo ? SB_DSP_STEREO_8BIT : SB_DSP_MONO_8BIT;
291 		chip->mode |= SB_MODE_CAPTURE_8;
292 		dma = chip->dma8;
293 	}
294 	size = chip->c_dma_size = snd_pcm_lib_buffer_bytes(substream);
295 	count = chip->c_period_size = snd_pcm_lib_period_bytes(substream);
296 	spin_lock_irqsave(&chip->reg_lock, flags);
297 	snd_sbdsp_command(chip, SB_DSP_SPEAKER_OFF);
298 	if (chip->hardware == SB_HW_JAZZ16)
299 		snd_sbdsp_command(chip, format);
300 	else if (stereo)
301 		snd_sbdsp_command(chip, SB_DSP_STEREO_8BIT);
302 	snd_sbdsp_command(chip, SB_DSP_SAMPLE_RATE);
303 	if (stereo) {
304 		snd_sbdsp_command(chip, 256 - runtime->rate_den / 2);
305 		spin_lock(&chip->mixer_lock);
306 		/* save input filter status and turn it off */
307 		mixreg = snd_sbmixer_read(chip, SB_DSP_CAPTURE_FILT);
308 		snd_sbmixer_write(chip, SB_DSP_CAPTURE_FILT, mixreg | 0x20);
309 		spin_unlock(&chip->mixer_lock);
310 		/* just use force_mode16 for temporary storate... */
311 		chip->force_mode16 = mixreg;
312 	} else {
313 		snd_sbdsp_command(chip, 256 - runtime->rate_den);
314 	}
315 	if (chip->capture_format != SB_DSP_INPUT) {
316 		if (chip->mode & SB_MODE_PLAYBACK_16)
317 			count /= 2;
318 		count--;
319 		snd_sbdsp_command(chip, SB_DSP_BLOCK_SIZE);
320 		snd_sbdsp_command(chip, count & 0xff);
321 		snd_sbdsp_command(chip, count >> 8);
322 	}
323 	spin_unlock_irqrestore(&chip->reg_lock, flags);
324 	snd_dma_program(dma, runtime->dma_addr,
325 			size, DMA_MODE_READ | DMA_AUTOINIT);
326 	return 0;
327 }
328 
329 static int snd_sb8_capture_trigger(struct snd_pcm_substream *substream,
330 				   int cmd)
331 {
332 	unsigned long flags;
333 	struct snd_sb *chip = snd_pcm_substream_chip(substream);
334 	unsigned int count;
335 
336 	spin_lock_irqsave(&chip->reg_lock, flags);
337 	switch (cmd) {
338 	case SNDRV_PCM_TRIGGER_START:
339 		snd_sbdsp_command(chip, chip->capture_format);
340 		if (chip->capture_format == SB_DSP_INPUT) {
341 			count = chip->c_period_size - 1;
342 			snd_sbdsp_command(chip, count & 0xff);
343 			snd_sbdsp_command(chip, count >> 8);
344 		}
345 		break;
346 	case SNDRV_PCM_TRIGGER_STOP:
347 		if (chip->capture_format == SB_DSP_HI_INPUT_AUTO) {
348 			struct snd_pcm_runtime *runtime = substream->runtime;
349 			snd_sbdsp_reset(chip);
350 			if (runtime->channels > 1) {
351 				/* restore input filter status */
352 				spin_lock(&chip->mixer_lock);
353 				snd_sbmixer_write(chip, SB_DSP_CAPTURE_FILT, chip->force_mode16);
354 				spin_unlock(&chip->mixer_lock);
355 				/* set hardware to mono mode */
356 				snd_sbdsp_command(chip, SB_DSP_MONO_8BIT);
357 			}
358 		} else {
359 			snd_sbdsp_command(chip, SB_DSP_DMA8_OFF);
360 		}
361 		snd_sbdsp_command(chip, SB_DSP_SPEAKER_OFF);
362 	}
363 	spin_unlock_irqrestore(&chip->reg_lock, flags);
364 	return 0;
365 }
366 
367 irqreturn_t snd_sb8dsp_interrupt(struct snd_sb *chip)
368 {
369 	struct snd_pcm_substream *substream;
370 
371 	snd_sb_ack_8bit(chip);
372 	switch (chip->mode) {
373 	case SB_MODE_PLAYBACK_16:	/* ok.. playback is active */
374 		if (chip->hardware != SB_HW_JAZZ16)
375 			break;
376 		/* fall through */
377 	case SB_MODE_PLAYBACK_8:
378 		substream = chip->playback_substream;
379 		if (chip->playback_format == SB_DSP_OUTPUT)
380 		    	snd_sb8_playback_trigger(substream, SNDRV_PCM_TRIGGER_START);
381 		snd_pcm_period_elapsed(substream);
382 		break;
383 	case SB_MODE_CAPTURE_16:
384 		if (chip->hardware != SB_HW_JAZZ16)
385 			break;
386 		/* fall through */
387 	case SB_MODE_CAPTURE_8:
388 		substream = chip->capture_substream;
389 		if (chip->capture_format == SB_DSP_INPUT)
390 		    	snd_sb8_capture_trigger(substream, SNDRV_PCM_TRIGGER_START);
391 		snd_pcm_period_elapsed(substream);
392 		break;
393 	}
394 	return IRQ_HANDLED;
395 }
396 
397 static snd_pcm_uframes_t snd_sb8_playback_pointer(struct snd_pcm_substream *substream)
398 {
399 	struct snd_sb *chip = snd_pcm_substream_chip(substream);
400 	size_t ptr;
401 	int dma;
402 
403 	if (chip->mode & SB_MODE_PLAYBACK_8)
404 		dma = chip->dma8;
405 	else if (chip->mode & SB_MODE_PLAYBACK_16)
406 		dma = chip->dma16;
407 	else
408 		return 0;
409 	ptr = snd_dma_pointer(dma, chip->p_dma_size);
410 	return bytes_to_frames(substream->runtime, ptr);
411 }
412 
413 static snd_pcm_uframes_t snd_sb8_capture_pointer(struct snd_pcm_substream *substream)
414 {
415 	struct snd_sb *chip = snd_pcm_substream_chip(substream);
416 	size_t ptr;
417 	int dma;
418 
419 	if (chip->mode & SB_MODE_CAPTURE_8)
420 		dma = chip->dma8;
421 	else if (chip->mode & SB_MODE_CAPTURE_16)
422 		dma = chip->dma16;
423 	else
424 		return 0;
425 	ptr = snd_dma_pointer(dma, chip->c_dma_size);
426 	return bytes_to_frames(substream->runtime, ptr);
427 }
428 
429 /*
430 
431  */
432 
433 static const struct snd_pcm_hardware snd_sb8_playback =
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 | SNDRV_PCM_RATE_22050),
440 	.rate_min =		4000,
441 	.rate_max =		23000,
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 static const struct snd_pcm_hardware snd_sb8_capture =
453 {
454 	.info =			(SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_INTERLEAVED |
455 				 SNDRV_PCM_INFO_MMAP_VALID),
456 	.formats =		SNDRV_PCM_FMTBIT_U8,
457 	.rates =		(SNDRV_PCM_RATE_CONTINUOUS | SNDRV_PCM_RATE_8000 |
458 				 SNDRV_PCM_RATE_11025),
459 	.rate_min =		4000,
460 	.rate_max =		13000,
461 	.channels_min =		1,
462 	.channels_max =		1,
463 	.buffer_bytes_max =	65536,
464 	.period_bytes_min =	64,
465 	.period_bytes_max =	65536,
466 	.periods_min =		1,
467 	.periods_max =		1024,
468 	.fifo_size =		0,
469 };
470 
471 /*
472  *
473  */
474 
475 static int snd_sb8_open(struct snd_pcm_substream *substream)
476 {
477 	struct snd_sb *chip = snd_pcm_substream_chip(substream);
478 	struct snd_pcm_runtime *runtime = substream->runtime;
479 	unsigned long flags;
480 
481 	spin_lock_irqsave(&chip->open_lock, flags);
482 	if (chip->open) {
483 		spin_unlock_irqrestore(&chip->open_lock, flags);
484 		return -EAGAIN;
485 	}
486 	chip->open |= SB_OPEN_PCM;
487 	spin_unlock_irqrestore(&chip->open_lock, flags);
488 	if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
489 		chip->playback_substream = substream;
490 		runtime->hw = snd_sb8_playback;
491 	} else {
492 		chip->capture_substream = substream;
493 		runtime->hw = snd_sb8_capture;
494 	}
495 	switch (chip->hardware) {
496 	case SB_HW_JAZZ16:
497 		if (chip->dma16 == 5 || chip->dma16 == 7)
498 			runtime->hw.formats |= SNDRV_PCM_FMTBIT_S16_LE;
499 		runtime->hw.rates |= SNDRV_PCM_RATE_8000_48000;
500 		runtime->hw.rate_min = 4000;
501 		runtime->hw.rate_max = 50000;
502 		runtime->hw.channels_max = 2;
503 		break;
504 	case SB_HW_PRO:
505 		runtime->hw.rate_max = 44100;
506 		runtime->hw.channels_max = 2;
507 		snd_pcm_hw_rule_add(runtime, 0, SNDRV_PCM_HW_PARAM_RATE,
508 				    snd_sb8_hw_constraint_rate_channels, NULL,
509 				    SNDRV_PCM_HW_PARAM_CHANNELS,
510 				    SNDRV_PCM_HW_PARAM_RATE, -1);
511 		snd_pcm_hw_rule_add(runtime, 0, SNDRV_PCM_HW_PARAM_CHANNELS,
512 				     snd_sb8_hw_constraint_channels_rate, NULL,
513 				     SNDRV_PCM_HW_PARAM_RATE, -1);
514 		break;
515 	case SB_HW_201:
516 		if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
517 			runtime->hw.rate_max = 44100;
518 		} else {
519 			runtime->hw.rate_max = 15000;
520 		}
521 	default:
522 		break;
523 	}
524 	snd_pcm_hw_constraint_ratnums(runtime, 0, SNDRV_PCM_HW_PARAM_RATE,
525 				      &hw_constraints_clock);
526 	if (chip->dma8 > 3 || chip->dma16 >= 0) {
527 		snd_pcm_hw_constraint_step(runtime, 0,
528 					   SNDRV_PCM_HW_PARAM_BUFFER_BYTES, 2);
529 		snd_pcm_hw_constraint_step(runtime, 0,
530 					   SNDRV_PCM_HW_PARAM_PERIOD_BYTES, 2);
531 		runtime->hw.buffer_bytes_max = 128 * 1024 * 1024;
532 		runtime->hw.period_bytes_max = 128 * 1024 * 1024;
533 	}
534 	return 0;
535 }
536 
537 static int snd_sb8_close(struct snd_pcm_substream *substream)
538 {
539 	unsigned long flags;
540 	struct snd_sb *chip = snd_pcm_substream_chip(substream);
541 
542 	chip->playback_substream = NULL;
543 	chip->capture_substream = NULL;
544 	spin_lock_irqsave(&chip->open_lock, flags);
545 	chip->open &= ~SB_OPEN_PCM;
546 	if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
547 		chip->mode &= ~SB_MODE_PLAYBACK;
548 	else
549 		chip->mode &= ~SB_MODE_CAPTURE;
550 	spin_unlock_irqrestore(&chip->open_lock, flags);
551 	return 0;
552 }
553 
554 /*
555  *  Initialization part
556  */
557 
558 static const struct snd_pcm_ops snd_sb8_playback_ops = {
559 	.open =			snd_sb8_open,
560 	.close =		snd_sb8_close,
561 	.ioctl =		snd_pcm_lib_ioctl,
562 	.hw_params =		snd_sb8_hw_params,
563 	.hw_free =		snd_sb8_hw_free,
564 	.prepare =		snd_sb8_playback_prepare,
565 	.trigger =		snd_sb8_playback_trigger,
566 	.pointer =		snd_sb8_playback_pointer,
567 };
568 
569 static const struct snd_pcm_ops snd_sb8_capture_ops = {
570 	.open =			snd_sb8_open,
571 	.close =		snd_sb8_close,
572 	.ioctl =		snd_pcm_lib_ioctl,
573 	.hw_params =		snd_sb8_hw_params,
574 	.hw_free =		snd_sb8_hw_free,
575 	.prepare =		snd_sb8_capture_prepare,
576 	.trigger =		snd_sb8_capture_trigger,
577 	.pointer =		snd_sb8_capture_pointer,
578 };
579 
580 int snd_sb8dsp_pcm(struct snd_sb *chip, int device)
581 {
582 	struct snd_card *card = chip->card;
583 	struct snd_pcm *pcm;
584 	int err;
585 	size_t max_prealloc = 64 * 1024;
586 
587 	if ((err = snd_pcm_new(card, "SB8 DSP", device, 1, 1, &pcm)) < 0)
588 		return err;
589 	sprintf(pcm->name, "DSP v%i.%i", chip->version >> 8, chip->version & 0xff);
590 	pcm->info_flags = SNDRV_PCM_INFO_HALF_DUPLEX;
591 	pcm->private_data = chip;
592 
593 	snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, &snd_sb8_playback_ops);
594 	snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, &snd_sb8_capture_ops);
595 
596 	if (chip->dma8 > 3 || chip->dma16 >= 0)
597 		max_prealloc = 128 * 1024;
598 	snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_DEV,
599 					      card->dev,
600 					      64*1024, max_prealloc);
601 
602 	return 0;
603 }
604 
605 EXPORT_SYMBOL(snd_sb8dsp_pcm);
606 EXPORT_SYMBOL(snd_sb8dsp_interrupt);
607   /* sb8_midi.c */
608 EXPORT_SYMBOL(snd_sb8dsp_midi_interrupt);
609 EXPORT_SYMBOL(snd_sb8dsp_midi);
610