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