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