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