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