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