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 struct snd_ratnum clock = { 50 .num = SB8_CLOCK, 51 .den_min = 1, 52 .den_max = 256, 53 .den_step = 1, 54 }; 55 56 static struct snd_pcm_hw_constraint_ratnums hw_constraints_clock = { 57 .nrats = 1, 58 .rats = &clock, 59 }; 60 61 static 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 /* fallthru */ 134 case SB_HW_201: 135 if (rate > 23000) { 136 chip->playback_format = SB_DSP_HI_OUTPUT_AUTO; 137 break; 138 } 139 /* fallthru */ 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 /* fallthru */ 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 struct snd_pcm_runtime *runtime; 385 386 snd_sb_ack_8bit(chip); 387 switch (chip->mode) { 388 case SB_MODE_PLAYBACK_16: /* ok.. playback is active */ 389 if (chip->hardware != SB_HW_JAZZ16) 390 break; 391 /* fallthru */ 392 case SB_MODE_PLAYBACK_8: 393 substream = chip->playback_substream; 394 runtime = substream->runtime; 395 if (chip->playback_format == SB_DSP_OUTPUT) 396 snd_sb8_playback_trigger(substream, SNDRV_PCM_TRIGGER_START); 397 snd_pcm_period_elapsed(substream); 398 break; 399 case SB_MODE_CAPTURE_16: 400 if (chip->hardware != SB_HW_JAZZ16) 401 break; 402 /* fallthru */ 403 case SB_MODE_CAPTURE_8: 404 substream = chip->capture_substream; 405 runtime = substream->runtime; 406 if (chip->capture_format == SB_DSP_INPUT) 407 snd_sb8_capture_trigger(substream, SNDRV_PCM_TRIGGER_START); 408 snd_pcm_period_elapsed(substream); 409 break; 410 } 411 return IRQ_HANDLED; 412 } 413 414 static snd_pcm_uframes_t snd_sb8_playback_pointer(struct snd_pcm_substream *substream) 415 { 416 struct snd_sb *chip = snd_pcm_substream_chip(substream); 417 size_t ptr; 418 int dma; 419 420 if (chip->mode & SB_MODE_PLAYBACK_8) 421 dma = chip->dma8; 422 else if (chip->mode & SB_MODE_PLAYBACK_16) 423 dma = chip->dma16; 424 else 425 return 0; 426 ptr = snd_dma_pointer(dma, chip->p_dma_size); 427 return bytes_to_frames(substream->runtime, ptr); 428 } 429 430 static snd_pcm_uframes_t snd_sb8_capture_pointer(struct snd_pcm_substream *substream) 431 { 432 struct snd_sb *chip = snd_pcm_substream_chip(substream); 433 size_t ptr; 434 int dma; 435 436 if (chip->mode & SB_MODE_CAPTURE_8) 437 dma = chip->dma8; 438 else if (chip->mode & SB_MODE_CAPTURE_16) 439 dma = chip->dma16; 440 else 441 return 0; 442 ptr = snd_dma_pointer(dma, chip->c_dma_size); 443 return bytes_to_frames(substream->runtime, ptr); 444 } 445 446 /* 447 448 */ 449 450 static struct snd_pcm_hardware snd_sb8_playback = 451 { 452 .info = (SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_INTERLEAVED | 453 SNDRV_PCM_INFO_MMAP_VALID), 454 .formats = SNDRV_PCM_FMTBIT_U8, 455 .rates = (SNDRV_PCM_RATE_CONTINUOUS | SNDRV_PCM_RATE_8000 | 456 SNDRV_PCM_RATE_11025 | SNDRV_PCM_RATE_22050), 457 .rate_min = 4000, 458 .rate_max = 23000, 459 .channels_min = 1, 460 .channels_max = 1, 461 .buffer_bytes_max = 65536, 462 .period_bytes_min = 64, 463 .period_bytes_max = 65536, 464 .periods_min = 1, 465 .periods_max = 1024, 466 .fifo_size = 0, 467 }; 468 469 static struct snd_pcm_hardware snd_sb8_capture = 470 { 471 .info = (SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_INTERLEAVED | 472 SNDRV_PCM_INFO_MMAP_VALID), 473 .formats = SNDRV_PCM_FMTBIT_U8, 474 .rates = (SNDRV_PCM_RATE_CONTINUOUS | SNDRV_PCM_RATE_8000 | 475 SNDRV_PCM_RATE_11025), 476 .rate_min = 4000, 477 .rate_max = 13000, 478 .channels_min = 1, 479 .channels_max = 1, 480 .buffer_bytes_max = 65536, 481 .period_bytes_min = 64, 482 .period_bytes_max = 65536, 483 .periods_min = 1, 484 .periods_max = 1024, 485 .fifo_size = 0, 486 }; 487 488 /* 489 * 490 */ 491 492 static int snd_sb8_open(struct snd_pcm_substream *substream) 493 { 494 struct snd_sb *chip = snd_pcm_substream_chip(substream); 495 struct snd_pcm_runtime *runtime = substream->runtime; 496 unsigned long flags; 497 498 spin_lock_irqsave(&chip->open_lock, flags); 499 if (chip->open) { 500 spin_unlock_irqrestore(&chip->open_lock, flags); 501 return -EAGAIN; 502 } 503 chip->open |= SB_OPEN_PCM; 504 spin_unlock_irqrestore(&chip->open_lock, flags); 505 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { 506 chip->playback_substream = substream; 507 runtime->hw = snd_sb8_playback; 508 } else { 509 chip->capture_substream = substream; 510 runtime->hw = snd_sb8_capture; 511 } 512 switch (chip->hardware) { 513 case SB_HW_JAZZ16: 514 if (chip->dma16 == 5 || chip->dma16 == 7) 515 runtime->hw.formats |= SNDRV_PCM_FMTBIT_S16_LE; 516 runtime->hw.rates |= SNDRV_PCM_RATE_8000_48000; 517 runtime->hw.rate_min = 4000; 518 runtime->hw.rate_max = 50000; 519 runtime->hw.channels_max = 2; 520 break; 521 case SB_HW_PRO: 522 runtime->hw.rate_max = 44100; 523 runtime->hw.channels_max = 2; 524 snd_pcm_hw_rule_add(runtime, 0, SNDRV_PCM_HW_PARAM_RATE, 525 snd_sb8_hw_constraint_rate_channels, NULL, 526 SNDRV_PCM_HW_PARAM_CHANNELS, 527 SNDRV_PCM_HW_PARAM_RATE, -1); 528 snd_pcm_hw_rule_add(runtime, 0, SNDRV_PCM_HW_PARAM_CHANNELS, 529 snd_sb8_hw_constraint_channels_rate, NULL, 530 SNDRV_PCM_HW_PARAM_RATE, -1); 531 break; 532 case SB_HW_201: 533 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { 534 runtime->hw.rate_max = 44100; 535 } else { 536 runtime->hw.rate_max = 15000; 537 } 538 default: 539 break; 540 } 541 snd_pcm_hw_constraint_ratnums(runtime, 0, SNDRV_PCM_HW_PARAM_RATE, 542 &hw_constraints_clock); 543 if (chip->dma8 > 3 || chip->dma16 >= 0) { 544 snd_pcm_hw_constraint_step(runtime, 0, 545 SNDRV_PCM_HW_PARAM_BUFFER_BYTES, 2); 546 snd_pcm_hw_constraint_step(runtime, 0, 547 SNDRV_PCM_HW_PARAM_PERIOD_BYTES, 2); 548 runtime->hw.buffer_bytes_max = 128 * 1024 * 1024; 549 runtime->hw.period_bytes_max = 128 * 1024 * 1024; 550 } 551 return 0; 552 } 553 554 static int snd_sb8_close(struct snd_pcm_substream *substream) 555 { 556 unsigned long flags; 557 struct snd_sb *chip = snd_pcm_substream_chip(substream); 558 559 chip->playback_substream = NULL; 560 chip->capture_substream = NULL; 561 spin_lock_irqsave(&chip->open_lock, flags); 562 chip->open &= ~SB_OPEN_PCM; 563 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) 564 chip->mode &= ~SB_MODE_PLAYBACK; 565 else 566 chip->mode &= ~SB_MODE_CAPTURE; 567 spin_unlock_irqrestore(&chip->open_lock, flags); 568 return 0; 569 } 570 571 /* 572 * Initialization part 573 */ 574 575 static struct snd_pcm_ops snd_sb8_playback_ops = { 576 .open = snd_sb8_open, 577 .close = snd_sb8_close, 578 .ioctl = snd_pcm_lib_ioctl, 579 .hw_params = snd_sb8_hw_params, 580 .hw_free = snd_sb8_hw_free, 581 .prepare = snd_sb8_playback_prepare, 582 .trigger = snd_sb8_playback_trigger, 583 .pointer = snd_sb8_playback_pointer, 584 }; 585 586 static struct snd_pcm_ops snd_sb8_capture_ops = { 587 .open = snd_sb8_open, 588 .close = snd_sb8_close, 589 .ioctl = snd_pcm_lib_ioctl, 590 .hw_params = snd_sb8_hw_params, 591 .hw_free = snd_sb8_hw_free, 592 .prepare = snd_sb8_capture_prepare, 593 .trigger = snd_sb8_capture_trigger, 594 .pointer = snd_sb8_capture_pointer, 595 }; 596 597 int snd_sb8dsp_pcm(struct snd_sb *chip, int device) 598 { 599 struct snd_card *card = chip->card; 600 struct snd_pcm *pcm; 601 int err; 602 size_t max_prealloc = 64 * 1024; 603 604 if ((err = snd_pcm_new(card, "SB8 DSP", device, 1, 1, &pcm)) < 0) 605 return err; 606 sprintf(pcm->name, "DSP v%i.%i", chip->version >> 8, chip->version & 0xff); 607 pcm->info_flags = SNDRV_PCM_INFO_HALF_DUPLEX; 608 pcm->private_data = chip; 609 610 snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, &snd_sb8_playback_ops); 611 snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, &snd_sb8_capture_ops); 612 613 if (chip->dma8 > 3 || chip->dma16 >= 0) 614 max_prealloc = 128 * 1024; 615 snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_DEV, 616 snd_dma_isa_data(), 617 64*1024, max_prealloc); 618 619 return 0; 620 } 621 622 EXPORT_SYMBOL(snd_sb8dsp_pcm); 623 EXPORT_SYMBOL(snd_sb8dsp_interrupt); 624 /* sb8_midi.c */ 625 EXPORT_SYMBOL(snd_sb8dsp_midi_interrupt); 626 EXPORT_SYMBOL(snd_sb8dsp_midi); 627 628 /* 629 * INIT part 630 */ 631 632 static int __init alsa_sb8_init(void) 633 { 634 return 0; 635 } 636 637 static void __exit alsa_sb8_exit(void) 638 { 639 } 640 641 module_init(alsa_sb8_init) 642 module_exit(alsa_sb8_exit) 643