Linux Kernel  3.7.1
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
msnd.c
Go to the documentation of this file.
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 
56 void 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 }
64 
65 static 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 
77 static 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 
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 }
106 
107 int 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 }
124 
125 int snd_msnd_upload_host(struct snd_msnd *dev, const u8 *bin, int len)
126 {
127  int i;
128 
129  if (len % 3 != 0) {
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 }
145 
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);
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 }
176 
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 }
206 
207 static 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 
213 static 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))
225  clear_bit(F_WRITING, &chip->flags);
226 }
227 
228 void 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);
233  snd_msnd_disable_irq(chip);
234  if (file) {
236  ": Stopping read for %p\n", file);
237  chip->mode &= ~FMODE_READ;
238  }
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);
245  }
246  snd_msnd_disable_irq(chip);
247  if (file) {
249  LOGNAME ": Stopping write for %p\n", file);
250  chip->mode &= ~FMODE_WRITE;
251  }
253  }
254 }
256 
257 
258 int 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 }
306 
307 int 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 +
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 */
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 }
366 
367 static 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;
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);
388  writew(chip->play_channels, pDAQ + DAQDS_wChannels);
390  writew(HIMT_PLAY_DONE * 0x100 + n, pDAQ + DAQDS_wIntMsg);
391  writew(n, pDAQ + DAQDS_wFlags);
392  }
393 }
394 
395 static 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;
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);
432  writew(chip->capture_channels, pDAQ + DAQDS_wChannels);
434  writew(HIMT_RECORD_DONE * 0x100 + n, pDAQ + DAQDS_wIntMsg);
435  writew(n, pDAQ + DAQDS_wFlags);
436  }
437 }
438 
439 static struct snd_pcm_hardware snd_msnd_playback = {
440  .info = SNDRV_PCM_INFO_MMAP |
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 
458 static struct snd_pcm_hardware snd_msnd_capture = {
459  .info = SNDRV_PCM_INFO_MMAP |
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 
478 static 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 
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 
495 static 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);
501  return 0;
502 }
503 
504 
505 static 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 
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) {
518  writew(chip->play_channels, pDAQ + DAQDS_wChannels);
520  }
521  /* dont do this here:
522  * snd_msnd_calibrate_adc(chip->play_sample_rate);
523  */
524 
525  return 0;
526 }
527 
528 static 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 
540 static 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);
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 
565 static snd_pcm_uframes_t
566 snd_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 
574 static 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 
584 static 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 
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 
599 static 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);
605  return 0;
606 }
607 
608 static 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 
620 static 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);
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);
635  return 0;
636  }
637  return -EINVAL;
638 }
639 
640 
641 static snd_pcm_uframes_t
642 snd_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 
651 static 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 
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) {
664  writew(chip->capture_channels, pDAQ + DAQDS_wChannels);
666  }
667  return 0;
668 }
669 
670 
671 static 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 
682 int snd_msnd_pcm(struct snd_card *card, int device,
683  struct snd_pcm **rpcm)
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 
700  if (rpcm)
701  *rpcm = pcm;
702  return 0;
703 }
705 
706 MODULE_DESCRIPTION("Common routines for Turtle Beach Multisound drivers");
707 MODULE_LICENSE("GPL");
708