1 /********************************************************************* 2 * 3 * 2002/06/30 Karsten Wiese: 4 * removed kernel-version dependencies. 5 * ripped from linux kernel 2.4.18 (OSS Implementation) by me. 6 * In the OSS Version, this file is compiled to a separate MODULE, 7 * that is used by the pinnacle and the classic driver. 8 * since there is no classic driver for alsa yet (i dont have a classic 9 * & writing one blindfold is difficult) this file's object is statically 10 * linked into the pinnacle-driver-module for now. look for the string 11 * "uncomment this to make this a module again" 12 * to do guess what. 13 * 14 * the following is a copy of the 2.4.18 OSS FREE file-heading comment: 15 * 16 * msnd.c - Driver Base 17 * 18 * Turtle Beach MultiSound Sound Card Driver for Linux 19 * 20 * Copyright (C) 1998 Andrew Veliath 21 * 22 * This program is free software; you can redistribute it and/or modify 23 * it under the terms of the GNU General Public License as published by 24 * the Free Software Foundation; either version 2 of the License, or 25 * (at your option) any later version. 26 * 27 * This program is distributed in the hope that it will be useful, 28 * but WITHOUT ANY WARRANTY; without even the implied warranty of 29 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 30 * GNU General Public License for more details. 31 * 32 * You should have received a copy of the GNU General Public License 33 * along with this program; if not, write to the Free Software 34 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 35 * 36 ********************************************************************/ 37 38 #include <linux/kernel.h> 39 #include <linux/types.h> 40 #include <linux/interrupt.h> 41 #include <linux/io.h> 42 #include <linux/fs.h> 43 #include <linux/delay.h> 44 45 #include <sound/core.h> 46 #include <sound/initval.h> 47 #include <sound/pcm.h> 48 #include <sound/pcm_params.h> 49 50 #include "msnd.h" 51 52 #define LOGNAME "msnd" 53 54 55 void snd_msnd_init_queue(void *base, int start, int size) 56 { 57 writew(PCTODSP_BASED(start), base + JQS_wStart); 58 writew(PCTODSP_OFFSET(size) - 1, base + JQS_wSize); 59 writew(0, base + JQS_wHead); 60 writew(0, base + JQS_wTail); 61 } 62 EXPORT_SYMBOL(snd_msnd_init_queue); 63 64 static int snd_msnd_wait_TXDE(struct snd_msnd *dev) 65 { 66 unsigned int io = dev->io; 67 int timeout = 1000; 68 69 while (timeout-- > 0) 70 if (inb(io + HP_ISR) & HPISR_TXDE) 71 return 0; 72 73 return -EIO; 74 } 75 76 static int snd_msnd_wait_HC0(struct snd_msnd *dev) 77 { 78 unsigned int io = dev->io; 79 int timeout = 1000; 80 81 while (timeout-- > 0) 82 if (!(inb(io + HP_CVR) & HPCVR_HC)) 83 return 0; 84 85 return -EIO; 86 } 87 88 int snd_msnd_send_dsp_cmd(struct snd_msnd *dev, u8 cmd) 89 { 90 unsigned long flags; 91 92 spin_lock_irqsave(&dev->lock, flags); 93 if (snd_msnd_wait_HC0(dev) == 0) { 94 outb(cmd, dev->io + HP_CVR); 95 spin_unlock_irqrestore(&dev->lock, flags); 96 return 0; 97 } 98 spin_unlock_irqrestore(&dev->lock, flags); 99 100 snd_printd(KERN_ERR LOGNAME ": Send DSP command timeout\n"); 101 102 return -EIO; 103 } 104 EXPORT_SYMBOL(snd_msnd_send_dsp_cmd); 105 106 int snd_msnd_send_word(struct snd_msnd *dev, unsigned char high, 107 unsigned char mid, unsigned char low) 108 { 109 unsigned int io = dev->io; 110 111 if (snd_msnd_wait_TXDE(dev) == 0) { 112 outb(high, io + HP_TXH); 113 outb(mid, io + HP_TXM); 114 outb(low, io + HP_TXL); 115 return 0; 116 } 117 118 snd_printd(KERN_ERR LOGNAME ": Send host word timeout\n"); 119 120 return -EIO; 121 } 122 EXPORT_SYMBOL(snd_msnd_send_word); 123 124 int snd_msnd_upload_host(struct snd_msnd *dev, const u8 *bin, int len) 125 { 126 int i; 127 128 if (len % 3 != 0) { 129 snd_printk(KERN_ERR LOGNAME 130 ": Upload host data not multiple of 3!\n"); 131 return -EINVAL; 132 } 133 134 for (i = 0; i < len; i += 3) 135 if (snd_msnd_send_word(dev, bin[i], bin[i + 1], bin[i + 2])) 136 return -EIO; 137 138 inb(dev->io + HP_RXL); 139 inb(dev->io + HP_CVR); 140 141 return 0; 142 } 143 EXPORT_SYMBOL(snd_msnd_upload_host); 144 145 int snd_msnd_enable_irq(struct snd_msnd *dev) 146 { 147 unsigned long flags; 148 149 if (dev->irq_ref++) 150 return 0; 151 152 snd_printdd(LOGNAME ": Enabling IRQ\n"); 153 154 spin_lock_irqsave(&dev->lock, flags); 155 if (snd_msnd_wait_TXDE(dev) == 0) { 156 outb(inb(dev->io + HP_ICR) | HPICR_TREQ, dev->io + HP_ICR); 157 if (dev->type == msndClassic) 158 outb(dev->irqid, dev->io + HP_IRQM); 159 160 outb(inb(dev->io + HP_ICR) & ~HPICR_TREQ, dev->io + HP_ICR); 161 outb(inb(dev->io + HP_ICR) | HPICR_RREQ, dev->io + HP_ICR); 162 enable_irq(dev->irq); 163 snd_msnd_init_queue(dev->DSPQ, dev->dspq_data_buff, 164 dev->dspq_buff_size); 165 spin_unlock_irqrestore(&dev->lock, flags); 166 return 0; 167 } 168 spin_unlock_irqrestore(&dev->lock, flags); 169 170 snd_printd(KERN_ERR LOGNAME ": Enable IRQ failed\n"); 171 172 return -EIO; 173 } 174 EXPORT_SYMBOL(snd_msnd_enable_irq); 175 176 int snd_msnd_disable_irq(struct snd_msnd *dev) 177 { 178 unsigned long flags; 179 180 if (--dev->irq_ref > 0) 181 return 0; 182 183 if (dev->irq_ref < 0) 184 snd_printd(KERN_WARNING LOGNAME ": IRQ ref count is %d\n", 185 dev->irq_ref); 186 187 snd_printdd(LOGNAME ": Disabling IRQ\n"); 188 189 spin_lock_irqsave(&dev->lock, flags); 190 if (snd_msnd_wait_TXDE(dev) == 0) { 191 outb(inb(dev->io + HP_ICR) & ~HPICR_RREQ, dev->io + HP_ICR); 192 if (dev->type == msndClassic) 193 outb(HPIRQ_NONE, dev->io + HP_IRQM); 194 disable_irq(dev->irq); 195 spin_unlock_irqrestore(&dev->lock, flags); 196 return 0; 197 } 198 spin_unlock_irqrestore(&dev->lock, flags); 199 200 snd_printd(KERN_ERR LOGNAME ": Disable IRQ failed\n"); 201 202 return -EIO; 203 } 204 EXPORT_SYMBOL(snd_msnd_disable_irq); 205 206 static inline long get_play_delay_jiffies(struct snd_msnd *chip, long size) 207 { 208 long tmp = (size * HZ * chip->play_sample_size) / 8; 209 return tmp / (chip->play_sample_rate * chip->play_channels); 210 } 211 212 static void snd_msnd_dsp_write_flush(struct snd_msnd *chip) 213 { 214 if (!(chip->mode & FMODE_WRITE) || !test_bit(F_WRITING, &chip->flags)) 215 return; 216 set_bit(F_WRITEFLUSH, &chip->flags); 217 /* interruptible_sleep_on_timeout( 218 &chip->writeflush, 219 get_play_delay_jiffies(&chip, chip->DAPF.len));*/ 220 clear_bit(F_WRITEFLUSH, &chip->flags); 221 if (!signal_pending(current)) 222 schedule_timeout_interruptible( 223 get_play_delay_jiffies(chip, chip->play_period_bytes)); 224 clear_bit(F_WRITING, &chip->flags); 225 } 226 227 void snd_msnd_dsp_halt(struct snd_msnd *chip, struct file *file) 228 { 229 if ((file ? file->f_mode : chip->mode) & FMODE_READ) { 230 clear_bit(F_READING, &chip->flags); 231 snd_msnd_send_dsp_cmd(chip, HDEX_RECORD_STOP); 232 snd_msnd_disable_irq(chip); 233 if (file) { 234 snd_printd(KERN_INFO LOGNAME 235 ": Stopping read for %p\n", file); 236 chip->mode &= ~FMODE_READ; 237 } 238 clear_bit(F_AUDIO_READ_INUSE, &chip->flags); 239 } 240 if ((file ? file->f_mode : chip->mode) & FMODE_WRITE) { 241 if (test_bit(F_WRITING, &chip->flags)) { 242 snd_msnd_dsp_write_flush(chip); 243 snd_msnd_send_dsp_cmd(chip, HDEX_PLAY_STOP); 244 } 245 snd_msnd_disable_irq(chip); 246 if (file) { 247 snd_printd(KERN_INFO 248 LOGNAME ": Stopping write for %p\n", file); 249 chip->mode &= ~FMODE_WRITE; 250 } 251 clear_bit(F_AUDIO_WRITE_INUSE, &chip->flags); 252 } 253 } 254 EXPORT_SYMBOL(snd_msnd_dsp_halt); 255 256 257 int snd_msnd_DARQ(struct snd_msnd *chip, int bank) 258 { 259 int /*size, n,*/ timeout = 3; 260 u16 wTmp; 261 /* void *DAQD; */ 262 263 /* Increment the tail and check for queue wrap */ 264 wTmp = readw(chip->DARQ + JQS_wTail) + PCTODSP_OFFSET(DAQDS__size); 265 if (wTmp > readw(chip->DARQ + JQS_wSize)) 266 wTmp = 0; 267 while (wTmp == readw(chip->DARQ + JQS_wHead) && timeout--) 268 udelay(1); 269 270 if (chip->capturePeriods == 2) { 271 void *pDAQ = chip->mappedbase + DARQ_DATA_BUFF + 272 bank * DAQDS__size + DAQDS_wStart; 273 unsigned short offset = 0x3000 + chip->capturePeriodBytes; 274 275 if (readw(pDAQ) != PCTODSP_BASED(0x3000)) 276 offset = 0x3000; 277 writew(PCTODSP_BASED(offset), pDAQ); 278 } 279 280 writew(wTmp, chip->DARQ + JQS_wTail); 281 282 #if 0 283 /* Get our digital audio queue struct */ 284 DAQD = bank * DAQDS__size + chip->mappedbase + DARQ_DATA_BUFF; 285 286 /* Get length of data */ 287 size = readw(DAQD + DAQDS_wSize); 288 289 /* Read data from the head (unprotected bank 1 access okay 290 since this is only called inside an interrupt) */ 291 outb(HPBLKSEL_1, chip->io + HP_BLKS); 292 n = msnd_fifo_write(&chip->DARF, 293 (char *)(chip->base + bank * DAR_BUFF_SIZE), 294 size, 0); 295 if (n <= 0) { 296 outb(HPBLKSEL_0, chip->io + HP_BLKS); 297 return n; 298 } 299 outb(HPBLKSEL_0, chip->io + HP_BLKS); 300 #endif 301 302 return 1; 303 } 304 EXPORT_SYMBOL(snd_msnd_DARQ); 305 306 int snd_msnd_DAPQ(struct snd_msnd *chip, int start) 307 { 308 u16 DAPQ_tail; 309 int protect = start, nbanks = 0; 310 void *DAQD; 311 static int play_banks_submitted; 312 /* unsigned long flags; 313 spin_lock_irqsave(&chip->lock, flags); not necessary */ 314 315 DAPQ_tail = readw(chip->DAPQ + JQS_wTail); 316 while (DAPQ_tail != readw(chip->DAPQ + JQS_wHead) || start) { 317 int bank_num = DAPQ_tail / PCTODSP_OFFSET(DAQDS__size); 318 319 if (start) { 320 start = 0; 321 play_banks_submitted = 0; 322 } 323 324 /* Get our digital audio queue struct */ 325 DAQD = bank_num * DAQDS__size + chip->mappedbase + 326 DAPQ_DATA_BUFF; 327 328 /* Write size of this bank */ 329 writew(chip->play_period_bytes, DAQD + DAQDS_wSize); 330 if (play_banks_submitted < 3) 331 ++play_banks_submitted; 332 else if (chip->playPeriods == 2) { 333 unsigned short offset = chip->play_period_bytes; 334 335 if (readw(DAQD + DAQDS_wStart) != PCTODSP_BASED(0x0)) 336 offset = 0; 337 338 writew(PCTODSP_BASED(offset), DAQD + DAQDS_wStart); 339 } 340 ++nbanks; 341 342 /* Then advance the tail */ 343 /* 344 if (protect) 345 snd_printd(KERN_INFO "B %X %lX\n", 346 bank_num, xtime.tv_usec); 347 */ 348 349 DAPQ_tail = (++bank_num % 3) * PCTODSP_OFFSET(DAQDS__size); 350 writew(DAPQ_tail, chip->DAPQ + JQS_wTail); 351 /* Tell the DSP to play the bank */ 352 snd_msnd_send_dsp_cmd(chip, HDEX_PLAY_START); 353 if (protect) 354 if (2 == bank_num) 355 break; 356 } 357 /* 358 if (protect) 359 snd_printd(KERN_INFO "%lX\n", xtime.tv_usec); 360 */ 361 /* spin_unlock_irqrestore(&chip->lock, flags); not necessary */ 362 return nbanks; 363 } 364 EXPORT_SYMBOL(snd_msnd_DAPQ); 365 366 static void snd_msnd_play_reset_queue(struct snd_msnd *chip, 367 unsigned int pcm_periods, 368 unsigned int pcm_count) 369 { 370 int n; 371 void *pDAQ = chip->mappedbase + DAPQ_DATA_BUFF; 372 373 chip->last_playbank = -1; 374 chip->playLimit = pcm_count * (pcm_periods - 1); 375 chip->playPeriods = pcm_periods; 376 writew(PCTODSP_OFFSET(0 * DAQDS__size), chip->DAPQ + JQS_wHead); 377 writew(PCTODSP_OFFSET(0 * DAQDS__size), chip->DAPQ + JQS_wTail); 378 379 chip->play_period_bytes = pcm_count; 380 381 for (n = 0; n < pcm_periods; ++n, pDAQ += DAQDS__size) { 382 writew(PCTODSP_BASED((u32)(pcm_count * n)), 383 pDAQ + DAQDS_wStart); 384 writew(0, pDAQ + DAQDS_wSize); 385 writew(1, pDAQ + DAQDS_wFormat); 386 writew(chip->play_sample_size, pDAQ + DAQDS_wSampleSize); 387 writew(chip->play_channels, pDAQ + DAQDS_wChannels); 388 writew(chip->play_sample_rate, pDAQ + DAQDS_wSampleRate); 389 writew(HIMT_PLAY_DONE * 0x100 + n, pDAQ + DAQDS_wIntMsg); 390 writew(n, pDAQ + DAQDS_wFlags); 391 } 392 } 393 394 static void snd_msnd_capture_reset_queue(struct snd_msnd *chip, 395 unsigned int pcm_periods, 396 unsigned int pcm_count) 397 { 398 int n; 399 void *pDAQ; 400 /* unsigned long flags; */ 401 402 /* snd_msnd_init_queue(chip->DARQ, DARQ_DATA_BUFF, DARQ_BUFF_SIZE); */ 403 404 chip->last_recbank = 2; 405 chip->captureLimit = pcm_count * (pcm_periods - 1); 406 chip->capturePeriods = pcm_periods; 407 writew(PCTODSP_OFFSET(0 * DAQDS__size), chip->DARQ + JQS_wHead); 408 writew(PCTODSP_OFFSET(chip->last_recbank * DAQDS__size), 409 chip->DARQ + JQS_wTail); 410 411 #if 0 /* Critical section: bank 1 access. this is how the OSS driver does it:*/ 412 spin_lock_irqsave(&chip->lock, flags); 413 outb(HPBLKSEL_1, chip->io + HP_BLKS); 414 memset_io(chip->mappedbase, 0, DAR_BUFF_SIZE * 3); 415 outb(HPBLKSEL_0, chip->io + HP_BLKS); 416 spin_unlock_irqrestore(&chip->lock, flags); 417 #endif 418 419 chip->capturePeriodBytes = pcm_count; 420 snd_printdd("snd_msnd_capture_reset_queue() %i\n", pcm_count); 421 422 pDAQ = chip->mappedbase + DARQ_DATA_BUFF; 423 424 for (n = 0; n < pcm_periods; ++n, pDAQ += DAQDS__size) { 425 u32 tmp = pcm_count * n; 426 427 writew(PCTODSP_BASED(tmp + 0x3000), pDAQ + DAQDS_wStart); 428 writew(pcm_count, pDAQ + DAQDS_wSize); 429 writew(1, pDAQ + DAQDS_wFormat); 430 writew(chip->capture_sample_size, pDAQ + DAQDS_wSampleSize); 431 writew(chip->capture_channels, pDAQ + DAQDS_wChannels); 432 writew(chip->capture_sample_rate, pDAQ + DAQDS_wSampleRate); 433 writew(HIMT_RECORD_DONE * 0x100 + n, pDAQ + DAQDS_wIntMsg); 434 writew(n, pDAQ + DAQDS_wFlags); 435 } 436 } 437 438 static struct snd_pcm_hardware snd_msnd_playback = { 439 .info = SNDRV_PCM_INFO_MMAP | 440 SNDRV_PCM_INFO_INTERLEAVED | 441 SNDRV_PCM_INFO_MMAP_VALID, 442 .formats = SNDRV_PCM_FMTBIT_U8 | SNDRV_PCM_FMTBIT_S16_LE, 443 .rates = SNDRV_PCM_RATE_8000_48000, 444 .rate_min = 8000, 445 .rate_max = 48000, 446 .channels_min = 1, 447 .channels_max = 2, 448 .buffer_bytes_max = 0x3000, 449 .period_bytes_min = 0x40, 450 .period_bytes_max = 0x1800, 451 .periods_min = 2, 452 .periods_max = 3, 453 .fifo_size = 0, 454 }; 455 456 static struct snd_pcm_hardware snd_msnd_capture = { 457 .info = SNDRV_PCM_INFO_MMAP | 458 SNDRV_PCM_INFO_INTERLEAVED | 459 SNDRV_PCM_INFO_MMAP_VALID, 460 .formats = SNDRV_PCM_FMTBIT_U8 | SNDRV_PCM_FMTBIT_S16_LE, 461 .rates = SNDRV_PCM_RATE_8000_48000, 462 .rate_min = 8000, 463 .rate_max = 48000, 464 .channels_min = 1, 465 .channels_max = 2, 466 .buffer_bytes_max = 0x3000, 467 .period_bytes_min = 0x40, 468 .period_bytes_max = 0x1800, 469 .periods_min = 2, 470 .periods_max = 3, 471 .fifo_size = 0, 472 }; 473 474 475 static int snd_msnd_playback_open(struct snd_pcm_substream *substream) 476 { 477 struct snd_pcm_runtime *runtime = substream->runtime; 478 struct snd_msnd *chip = snd_pcm_substream_chip(substream); 479 480 set_bit(F_AUDIO_WRITE_INUSE, &chip->flags); 481 clear_bit(F_WRITING, &chip->flags); 482 snd_msnd_enable_irq(chip); 483 484 runtime->dma_area = chip->mappedbase; 485 runtime->dma_bytes = 0x3000; 486 487 chip->playback_substream = substream; 488 runtime->hw = snd_msnd_playback; 489 return 0; 490 } 491 492 static int snd_msnd_playback_close(struct snd_pcm_substream *substream) 493 { 494 struct snd_msnd *chip = snd_pcm_substream_chip(substream); 495 496 snd_msnd_disable_irq(chip); 497 clear_bit(F_AUDIO_WRITE_INUSE, &chip->flags); 498 return 0; 499 } 500 501 502 static int snd_msnd_playback_hw_params(struct snd_pcm_substream *substream, 503 struct snd_pcm_hw_params *params) 504 { 505 int i; 506 struct snd_msnd *chip = snd_pcm_substream_chip(substream); 507 void *pDAQ = chip->mappedbase + DAPQ_DATA_BUFF; 508 509 chip->play_sample_size = snd_pcm_format_width(params_format(params)); 510 chip->play_channels = params_channels(params); 511 chip->play_sample_rate = params_rate(params); 512 513 for (i = 0; i < 3; ++i, pDAQ += DAQDS__size) { 514 writew(chip->play_sample_size, pDAQ + DAQDS_wSampleSize); 515 writew(chip->play_channels, pDAQ + DAQDS_wChannels); 516 writew(chip->play_sample_rate, pDAQ + DAQDS_wSampleRate); 517 } 518 /* dont do this here: 519 * snd_msnd_calibrate_adc(chip->play_sample_rate); 520 */ 521 522 return 0; 523 } 524 525 static int snd_msnd_playback_prepare(struct snd_pcm_substream *substream) 526 { 527 struct snd_msnd *chip = snd_pcm_substream_chip(substream); 528 unsigned int pcm_size = snd_pcm_lib_buffer_bytes(substream); 529 unsigned int pcm_count = snd_pcm_lib_period_bytes(substream); 530 unsigned int pcm_periods = pcm_size / pcm_count; 531 532 snd_msnd_play_reset_queue(chip, pcm_periods, pcm_count); 533 chip->playDMAPos = 0; 534 return 0; 535 } 536 537 static int snd_msnd_playback_trigger(struct snd_pcm_substream *substream, 538 int cmd) 539 { 540 struct snd_msnd *chip = snd_pcm_substream_chip(substream); 541 int result = 0; 542 543 if (cmd == SNDRV_PCM_TRIGGER_START) { 544 snd_printdd("snd_msnd_playback_trigger(START)\n"); 545 chip->banksPlayed = 0; 546 set_bit(F_WRITING, &chip->flags); 547 snd_msnd_DAPQ(chip, 1); 548 } else if (cmd == SNDRV_PCM_TRIGGER_STOP) { 549 snd_printdd("snd_msnd_playback_trigger(STop)\n"); 550 /* interrupt diagnostic, comment this out later */ 551 clear_bit(F_WRITING, &chip->flags); 552 snd_msnd_send_dsp_cmd(chip, HDEX_PLAY_STOP); 553 } else { 554 snd_printd(KERN_ERR "snd_msnd_playback_trigger(?????)\n"); 555 result = -EINVAL; 556 } 557 558 snd_printdd("snd_msnd_playback_trigger() ENDE\n"); 559 return result; 560 } 561 562 static snd_pcm_uframes_t 563 snd_msnd_playback_pointer(struct snd_pcm_substream *substream) 564 { 565 struct snd_msnd *chip = snd_pcm_substream_chip(substream); 566 567 return bytes_to_frames(substream->runtime, chip->playDMAPos); 568 } 569 570 571 static struct snd_pcm_ops snd_msnd_playback_ops = { 572 .open = snd_msnd_playback_open, 573 .close = snd_msnd_playback_close, 574 .ioctl = snd_pcm_lib_ioctl, 575 .hw_params = snd_msnd_playback_hw_params, 576 .prepare = snd_msnd_playback_prepare, 577 .trigger = snd_msnd_playback_trigger, 578 .pointer = snd_msnd_playback_pointer, 579 }; 580 581 static int snd_msnd_capture_open(struct snd_pcm_substream *substream) 582 { 583 struct snd_pcm_runtime *runtime = substream->runtime; 584 struct snd_msnd *chip = snd_pcm_substream_chip(substream); 585 586 set_bit(F_AUDIO_READ_INUSE, &chip->flags); 587 snd_msnd_enable_irq(chip); 588 runtime->dma_area = chip->mappedbase + 0x3000; 589 runtime->dma_bytes = 0x3000; 590 memset(runtime->dma_area, 0, runtime->dma_bytes); 591 chip->capture_substream = substream; 592 runtime->hw = snd_msnd_capture; 593 return 0; 594 } 595 596 static int snd_msnd_capture_close(struct snd_pcm_substream *substream) 597 { 598 struct snd_msnd *chip = snd_pcm_substream_chip(substream); 599 600 snd_msnd_disable_irq(chip); 601 clear_bit(F_AUDIO_READ_INUSE, &chip->flags); 602 return 0; 603 } 604 605 static int snd_msnd_capture_prepare(struct snd_pcm_substream *substream) 606 { 607 struct snd_msnd *chip = snd_pcm_substream_chip(substream); 608 unsigned int pcm_size = snd_pcm_lib_buffer_bytes(substream); 609 unsigned int pcm_count = snd_pcm_lib_period_bytes(substream); 610 unsigned int pcm_periods = pcm_size / pcm_count; 611 612 snd_msnd_capture_reset_queue(chip, pcm_periods, pcm_count); 613 chip->captureDMAPos = 0; 614 return 0; 615 } 616 617 static int snd_msnd_capture_trigger(struct snd_pcm_substream *substream, 618 int cmd) 619 { 620 struct snd_msnd *chip = snd_pcm_substream_chip(substream); 621 622 if (cmd == SNDRV_PCM_TRIGGER_START) { 623 chip->last_recbank = -1; 624 set_bit(F_READING, &chip->flags); 625 if (snd_msnd_send_dsp_cmd(chip, HDEX_RECORD_START) == 0) 626 return 0; 627 628 clear_bit(F_READING, &chip->flags); 629 } else if (cmd == SNDRV_PCM_TRIGGER_STOP) { 630 clear_bit(F_READING, &chip->flags); 631 snd_msnd_send_dsp_cmd(chip, HDEX_RECORD_STOP); 632 return 0; 633 } 634 return -EINVAL; 635 } 636 637 638 static snd_pcm_uframes_t 639 snd_msnd_capture_pointer(struct snd_pcm_substream *substream) 640 { 641 struct snd_pcm_runtime *runtime = substream->runtime; 642 struct snd_msnd *chip = snd_pcm_substream_chip(substream); 643 644 return bytes_to_frames(runtime, chip->captureDMAPos); 645 } 646 647 648 static int snd_msnd_capture_hw_params(struct snd_pcm_substream *substream, 649 struct snd_pcm_hw_params *params) 650 { 651 int i; 652 struct snd_msnd *chip = snd_pcm_substream_chip(substream); 653 void *pDAQ = chip->mappedbase + DARQ_DATA_BUFF; 654 655 chip->capture_sample_size = snd_pcm_format_width(params_format(params)); 656 chip->capture_channels = params_channels(params); 657 chip->capture_sample_rate = params_rate(params); 658 659 for (i = 0; i < 3; ++i, pDAQ += DAQDS__size) { 660 writew(chip->capture_sample_size, pDAQ + DAQDS_wSampleSize); 661 writew(chip->capture_channels, pDAQ + DAQDS_wChannels); 662 writew(chip->capture_sample_rate, pDAQ + DAQDS_wSampleRate); 663 } 664 return 0; 665 } 666 667 668 static struct snd_pcm_ops snd_msnd_capture_ops = { 669 .open = snd_msnd_capture_open, 670 .close = snd_msnd_capture_close, 671 .ioctl = snd_pcm_lib_ioctl, 672 .hw_params = snd_msnd_capture_hw_params, 673 .prepare = snd_msnd_capture_prepare, 674 .trigger = snd_msnd_capture_trigger, 675 .pointer = snd_msnd_capture_pointer, 676 }; 677 678 679 int snd_msnd_pcm(struct snd_card *card, int device, 680 struct snd_pcm **rpcm) 681 { 682 struct snd_msnd *chip = card->private_data; 683 struct snd_pcm *pcm; 684 int err; 685 686 err = snd_pcm_new(card, "MSNDPINNACLE", device, 1, 1, &pcm); 687 if (err < 0) 688 return err; 689 690 snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, &snd_msnd_playback_ops); 691 snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, &snd_msnd_capture_ops); 692 693 pcm->private_data = chip; 694 strcpy(pcm->name, "Hurricane"); 695 696 697 if (rpcm) 698 *rpcm = pcm; 699 return 0; 700 } 701 EXPORT_SYMBOL(snd_msnd_pcm); 702 703 MODULE_DESCRIPTION("Common routines for Turtle Beach Multisound drivers"); 704 MODULE_LICENSE("GPL"); 705 706