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 55void 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} 62EXPORT_SYMBOL(snd_msnd_init_queue); 63 64static 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 76static 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 88int 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} 104EXPORT_SYMBOL(snd_msnd_send_dsp_cmd); 105 106int 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} 122EXPORT_SYMBOL(snd_msnd_send_word); 123 124int 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} 143EXPORT_SYMBOL(snd_msnd_upload_host); 144 145int 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} 174EXPORT_SYMBOL(snd_msnd_enable_irq); 175 176int 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} 204EXPORT_SYMBOL(snd_msnd_disable_irq); 205 206static 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 212static 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 227void 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} 254EXPORT_SYMBOL(snd_msnd_dsp_halt); 255 256 257int 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 283 return 1; 284} 285EXPORT_SYMBOL(snd_msnd_DARQ); 286 287int snd_msnd_DAPQ(struct snd_msnd *chip, int start) 288{ 289 u16 DAPQ_tail; 290 int protect = start, nbanks = 0; 291 void *DAQD; 292 static int play_banks_submitted; 293 /* unsigned long flags; 294 spin_lock_irqsave(&chip->lock, flags); not necessary */ 295 296 DAPQ_tail = readw(chip->DAPQ + JQS_wTail); 297 while (DAPQ_tail != readw(chip->DAPQ + JQS_wHead) || start) { 298 int bank_num = DAPQ_tail / PCTODSP_OFFSET(DAQDS__size); 299 300 if (start) { 301 start = 0; 302 play_banks_submitted = 0; 303 } 304 305 /* Get our digital audio queue struct */ 306 DAQD = bank_num * DAQDS__size + chip->mappedbase + 307 DAPQ_DATA_BUFF; 308 309 /* Write size of this bank */ 310 writew(chip->play_period_bytes, DAQD + DAQDS_wSize); 311 if (play_banks_submitted < 3) 312 ++play_banks_submitted; 313 else if (chip->playPeriods == 2) { 314 unsigned short offset = chip->play_period_bytes; 315 316 if (readw(DAQD + DAQDS_wStart) != PCTODSP_BASED(0x0)) 317 offset = 0; 318 319 writew(PCTODSP_BASED(offset), DAQD + DAQDS_wStart); 320 } 321 ++nbanks; 322 323 /* Then advance the tail */ 324 /* 325 if (protect) 326 snd_printd(KERN_INFO "B %X %lX\n", 327 bank_num, xtime.tv_usec); 328 */ 329 330 DAPQ_tail = (++bank_num % 3) * PCTODSP_OFFSET(DAQDS__size); 331 writew(DAPQ_tail, chip->DAPQ + JQS_wTail); 332 /* Tell the DSP to play the bank */ 333 snd_msnd_send_dsp_cmd(chip, HDEX_PLAY_START); 334 if (protect) 335 if (2 == bank_num) 336 break; 337 } 338 /* 339 if (protect) 340 snd_printd(KERN_INFO "%lX\n", xtime.tv_usec); 341 */ 342 /* spin_unlock_irqrestore(&chip->lock, flags); not necessary */ 343 return nbanks; 344} 345EXPORT_SYMBOL(snd_msnd_DAPQ); 346 347static void snd_msnd_play_reset_queue(struct snd_msnd *chip, 348 unsigned int pcm_periods, 349 unsigned int pcm_count) 350{ 351 int n; 352 void *pDAQ = chip->mappedbase + DAPQ_DATA_BUFF; 353 354 chip->last_playbank = -1; 355 chip->playLimit = pcm_count * (pcm_periods - 1); 356 chip->playPeriods = pcm_periods; 357 writew(PCTODSP_OFFSET(0 * DAQDS__size), chip->DAPQ + JQS_wHead); 358 writew(PCTODSP_OFFSET(0 * DAQDS__size), chip->DAPQ + JQS_wTail); 359 360 chip->play_period_bytes = pcm_count; 361 362 for (n = 0; n < pcm_periods; ++n, pDAQ += DAQDS__size) { 363 writew(PCTODSP_BASED((u32)(pcm_count * n)), 364 pDAQ + DAQDS_wStart); 365 writew(0, pDAQ + DAQDS_wSize); 366 writew(1, pDAQ + DAQDS_wFormat); 367 writew(chip->play_sample_size, pDAQ + DAQDS_wSampleSize); 368 writew(chip->play_channels, pDAQ + DAQDS_wChannels); 369 writew(chip->play_sample_rate, pDAQ + DAQDS_wSampleRate); 370 writew(HIMT_PLAY_DONE * 0x100 + n, pDAQ + DAQDS_wIntMsg); 371 writew(n, pDAQ + DAQDS_wFlags); 372 } 373} 374 375static void snd_msnd_capture_reset_queue(struct snd_msnd *chip, 376 unsigned int pcm_periods, 377 unsigned int pcm_count) 378{ 379 int n; 380 void *pDAQ; 381 /* unsigned long flags; */ 382 383 /* snd_msnd_init_queue(chip->DARQ, DARQ_DATA_BUFF, DARQ_BUFF_SIZE); */ 384 385 chip->last_recbank = 2; 386 chip->captureLimit = pcm_count * (pcm_periods - 1); 387 chip->capturePeriods = pcm_periods; 388 writew(PCTODSP_OFFSET(0 * DAQDS__size), chip->DARQ + JQS_wHead); 389 writew(PCTODSP_OFFSET(chip->last_recbank * DAQDS__size), 390 chip->DARQ + JQS_wTail); 391 392 393 chip->capturePeriodBytes = pcm_count; 394 snd_printdd("snd_msnd_capture_reset_queue() %i\n", pcm_count); 395 396 pDAQ = chip->mappedbase + DARQ_DATA_BUFF; 397 398 for (n = 0; n < pcm_periods; ++n, pDAQ += DAQDS__size) { 399 u32 tmp = pcm_count * n; 400 401 writew(PCTODSP_BASED(tmp + 0x3000), pDAQ + DAQDS_wStart); 402 writew(pcm_count, pDAQ + DAQDS_wSize); 403 writew(1, pDAQ + DAQDS_wFormat); 404 writew(chip->capture_sample_size, pDAQ + DAQDS_wSampleSize); 405 writew(chip->capture_channels, pDAQ + DAQDS_wChannels); 406 writew(chip->capture_sample_rate, pDAQ + DAQDS_wSampleRate); 407 writew(HIMT_RECORD_DONE * 0x100 + n, pDAQ + DAQDS_wIntMsg); 408 writew(n, pDAQ + DAQDS_wFlags); 409 } 410} 411 412static struct snd_pcm_hardware snd_msnd_playback = { 413 .info = SNDRV_PCM_INFO_MMAP | 414 SNDRV_PCM_INFO_INTERLEAVED | 415 SNDRV_PCM_INFO_MMAP_VALID | 416 SNDRV_PCM_INFO_BATCH, 417 .formats = SNDRV_PCM_FMTBIT_U8 | SNDRV_PCM_FMTBIT_S16_LE, 418 .rates = SNDRV_PCM_RATE_8000_48000, 419 .rate_min = 8000, 420 .rate_max = 48000, 421 .channels_min = 1, 422 .channels_max = 2, 423 .buffer_bytes_max = 0x3000, 424 .period_bytes_min = 0x40, 425 .period_bytes_max = 0x1800, 426 .periods_min = 2, 427 .periods_max = 3, 428 .fifo_size = 0, 429}; 430 431static struct snd_pcm_hardware snd_msnd_capture = { 432 .info = SNDRV_PCM_INFO_MMAP | 433 SNDRV_PCM_INFO_INTERLEAVED | 434 SNDRV_PCM_INFO_MMAP_VALID | 435 SNDRV_PCM_INFO_BATCH, 436 .formats = SNDRV_PCM_FMTBIT_U8 | SNDRV_PCM_FMTBIT_S16_LE, 437 .rates = SNDRV_PCM_RATE_8000_48000, 438 .rate_min = 8000, 439 .rate_max = 48000, 440 .channels_min = 1, 441 .channels_max = 2, 442 .buffer_bytes_max = 0x3000, 443 .period_bytes_min = 0x40, 444 .period_bytes_max = 0x1800, 445 .periods_min = 2, 446 .periods_max = 3, 447 .fifo_size = 0, 448}; 449 450 451static int snd_msnd_playback_open(struct snd_pcm_substream *substream) 452{ 453 struct snd_pcm_runtime *runtime = substream->runtime; 454 struct snd_msnd *chip = snd_pcm_substream_chip(substream); 455 456 set_bit(F_AUDIO_WRITE_INUSE, &chip->flags); 457 clear_bit(F_WRITING, &chip->flags); 458 snd_msnd_enable_irq(chip); 459 460 runtime->dma_area = chip->mappedbase; 461 runtime->dma_bytes = 0x3000; 462 463 chip->playback_substream = substream; 464 runtime->hw = snd_msnd_playback; 465 return 0; 466} 467 468static int snd_msnd_playback_close(struct snd_pcm_substream *substream) 469{ 470 struct snd_msnd *chip = snd_pcm_substream_chip(substream); 471 472 snd_msnd_disable_irq(chip); 473 clear_bit(F_AUDIO_WRITE_INUSE, &chip->flags); 474 return 0; 475} 476 477 478static int snd_msnd_playback_hw_params(struct snd_pcm_substream *substream, 479 struct snd_pcm_hw_params *params) 480{ 481 int i; 482 struct snd_msnd *chip = snd_pcm_substream_chip(substream); 483 void *pDAQ = chip->mappedbase + DAPQ_DATA_BUFF; 484 485 chip->play_sample_size = snd_pcm_format_width(params_format(params)); 486 chip->play_channels = params_channels(params); 487 chip->play_sample_rate = params_rate(params); 488 489 for (i = 0; i < 3; ++i, pDAQ += DAQDS__size) { 490 writew(chip->play_sample_size, pDAQ + DAQDS_wSampleSize); 491 writew(chip->play_channels, pDAQ + DAQDS_wChannels); 492 writew(chip->play_sample_rate, pDAQ + DAQDS_wSampleRate); 493 } 494 /* dont do this here: 495 * snd_msnd_calibrate_adc(chip->play_sample_rate); 496 */ 497 498 return 0; 499} 500 501static int snd_msnd_playback_prepare(struct snd_pcm_substream *substream) 502{ 503 struct snd_msnd *chip = snd_pcm_substream_chip(substream); 504 unsigned int pcm_size = snd_pcm_lib_buffer_bytes(substream); 505 unsigned int pcm_count = snd_pcm_lib_period_bytes(substream); 506 unsigned int pcm_periods = pcm_size / pcm_count; 507 508 snd_msnd_play_reset_queue(chip, pcm_periods, pcm_count); 509 chip->playDMAPos = 0; 510 return 0; 511} 512 513static int snd_msnd_playback_trigger(struct snd_pcm_substream *substream, 514 int cmd) 515{ 516 struct snd_msnd *chip = snd_pcm_substream_chip(substream); 517 int result = 0; 518 519 if (cmd == SNDRV_PCM_TRIGGER_START) { 520 snd_printdd("snd_msnd_playback_trigger(START)\n"); 521 chip->banksPlayed = 0; 522 set_bit(F_WRITING, &chip->flags); 523 snd_msnd_DAPQ(chip, 1); 524 } else if (cmd == SNDRV_PCM_TRIGGER_STOP) { 525 snd_printdd("snd_msnd_playback_trigger(STop)\n"); 526 /* interrupt diagnostic, comment this out later */ 527 clear_bit(F_WRITING, &chip->flags); 528 snd_msnd_send_dsp_cmd(chip, HDEX_PLAY_STOP); 529 } else { 530 snd_printd(KERN_ERR "snd_msnd_playback_trigger(?????)\n"); 531 result = -EINVAL; 532 } 533 534 snd_printdd("snd_msnd_playback_trigger() ENDE\n"); 535 return result; 536} 537 538static snd_pcm_uframes_t 539snd_msnd_playback_pointer(struct snd_pcm_substream *substream) 540{ 541 struct snd_msnd *chip = snd_pcm_substream_chip(substream); 542 543 return bytes_to_frames(substream->runtime, chip->playDMAPos); 544} 545 546 547static struct snd_pcm_ops snd_msnd_playback_ops = { 548 .open = snd_msnd_playback_open, 549 .close = snd_msnd_playback_close, 550 .ioctl = snd_pcm_lib_ioctl, 551 .hw_params = snd_msnd_playback_hw_params, 552 .prepare = snd_msnd_playback_prepare, 553 .trigger = snd_msnd_playback_trigger, 554 .pointer = snd_msnd_playback_pointer, 555}; 556 557static int snd_msnd_capture_open(struct snd_pcm_substream *substream) 558{ 559 struct snd_pcm_runtime *runtime = substream->runtime; 560 struct snd_msnd *chip = snd_pcm_substream_chip(substream); 561 562 set_bit(F_AUDIO_READ_INUSE, &chip->flags); 563 snd_msnd_enable_irq(chip); 564 runtime->dma_area = chip->mappedbase + 0x3000; 565 runtime->dma_bytes = 0x3000; 566 memset(runtime->dma_area, 0, runtime->dma_bytes); 567 chip->capture_substream = substream; 568 runtime->hw = snd_msnd_capture; 569 return 0; 570} 571 572static int snd_msnd_capture_close(struct snd_pcm_substream *substream) 573{ 574 struct snd_msnd *chip = snd_pcm_substream_chip(substream); 575 576 snd_msnd_disable_irq(chip); 577 clear_bit(F_AUDIO_READ_INUSE, &chip->flags); 578 return 0; 579} 580 581static int snd_msnd_capture_prepare(struct snd_pcm_substream *substream) 582{ 583 struct snd_msnd *chip = snd_pcm_substream_chip(substream); 584 unsigned int pcm_size = snd_pcm_lib_buffer_bytes(substream); 585 unsigned int pcm_count = snd_pcm_lib_period_bytes(substream); 586 unsigned int pcm_periods = pcm_size / pcm_count; 587 588 snd_msnd_capture_reset_queue(chip, pcm_periods, pcm_count); 589 chip->captureDMAPos = 0; 590 return 0; 591} 592 593static int snd_msnd_capture_trigger(struct snd_pcm_substream *substream, 594 int cmd) 595{ 596 struct snd_msnd *chip = snd_pcm_substream_chip(substream); 597 598 if (cmd == SNDRV_PCM_TRIGGER_START) { 599 chip->last_recbank = -1; 600 set_bit(F_READING, &chip->flags); 601 if (snd_msnd_send_dsp_cmd(chip, HDEX_RECORD_START) == 0) 602 return 0; 603 604 clear_bit(F_READING, &chip->flags); 605 } else if (cmd == SNDRV_PCM_TRIGGER_STOP) { 606 clear_bit(F_READING, &chip->flags); 607 snd_msnd_send_dsp_cmd(chip, HDEX_RECORD_STOP); 608 return 0; 609 } 610 return -EINVAL; 611} 612 613 614static snd_pcm_uframes_t 615snd_msnd_capture_pointer(struct snd_pcm_substream *substream) 616{ 617 struct snd_pcm_runtime *runtime = substream->runtime; 618 struct snd_msnd *chip = snd_pcm_substream_chip(substream); 619 620 return bytes_to_frames(runtime, chip->captureDMAPos); 621} 622 623 624static int snd_msnd_capture_hw_params(struct snd_pcm_substream *substream, 625 struct snd_pcm_hw_params *params) 626{ 627 int i; 628 struct snd_msnd *chip = snd_pcm_substream_chip(substream); 629 void *pDAQ = chip->mappedbase + DARQ_DATA_BUFF; 630 631 chip->capture_sample_size = snd_pcm_format_width(params_format(params)); 632 chip->capture_channels = params_channels(params); 633 chip->capture_sample_rate = params_rate(params); 634 635 for (i = 0; i < 3; ++i, pDAQ += DAQDS__size) { 636 writew(chip->capture_sample_size, pDAQ + DAQDS_wSampleSize); 637 writew(chip->capture_channels, pDAQ + DAQDS_wChannels); 638 writew(chip->capture_sample_rate, pDAQ + DAQDS_wSampleRate); 639 } 640 return 0; 641} 642 643 644static struct snd_pcm_ops snd_msnd_capture_ops = { 645 .open = snd_msnd_capture_open, 646 .close = snd_msnd_capture_close, 647 .ioctl = snd_pcm_lib_ioctl, 648 .hw_params = snd_msnd_capture_hw_params, 649 .prepare = snd_msnd_capture_prepare, 650 .trigger = snd_msnd_capture_trigger, 651 .pointer = snd_msnd_capture_pointer, 652}; 653 654 655int snd_msnd_pcm(struct snd_card *card, int device, 656 struct snd_pcm **rpcm) 657{ 658 struct snd_msnd *chip = card->private_data; 659 struct snd_pcm *pcm; 660 int err; 661 662 err = snd_pcm_new(card, "MSNDPINNACLE", device, 1, 1, &pcm); 663 if (err < 0) 664 return err; 665 666 snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, &snd_msnd_playback_ops); 667 snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, &snd_msnd_capture_ops); 668 669 pcm->private_data = chip; 670 strcpy(pcm->name, "Hurricane"); 671 672 673 if (rpcm) 674 *rpcm = pcm; 675 return 0; 676} 677EXPORT_SYMBOL(snd_msnd_pcm); 678 679MODULE_DESCRIPTION("Common routines for Turtle Beach Multisound drivers"); 680MODULE_LICENSE("GPL"); 681