Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0-or-later
0002 /*********************************************************************
0003  *
0004  * 2002/06/30 Karsten Wiese:
0005  *  removed kernel-version dependencies.
0006  *  ripped from linux kernel 2.4.18 (OSS Implementation) by me.
0007  *  In the OSS Version, this file is compiled to a separate MODULE,
0008  *  that is used by the pinnacle and the classic driver.
0009  *  since there is no classic driver for alsa yet (i dont have a classic
0010  *  & writing one blindfold is difficult) this file's object is statically
0011  *  linked into the pinnacle-driver-module for now. look for the string
0012  *      "uncomment this to make this a module again"
0013  *  to do guess what.
0014  *
0015  * the following is a copy of the 2.4.18 OSS FREE file-heading comment:
0016  *
0017  * msnd.c - Driver Base
0018  *
0019  * Turtle Beach MultiSound Sound Card Driver for Linux
0020  *
0021  * Copyright (C) 1998 Andrew Veliath
0022  *
0023  ********************************************************************/
0024 
0025 #include <linux/kernel.h>
0026 #include <linux/sched/signal.h>
0027 #include <linux/types.h>
0028 #include <linux/interrupt.h>
0029 #include <linux/io.h>
0030 #include <linux/fs.h>
0031 #include <linux/delay.h>
0032 #include <linux/module.h>
0033 
0034 #include <sound/core.h>
0035 #include <sound/initval.h>
0036 #include <sound/pcm.h>
0037 #include <sound/pcm_params.h>
0038 
0039 #include "msnd.h"
0040 
0041 #define LOGNAME         "msnd"
0042 
0043 
0044 void snd_msnd_init_queue(void __iomem *base, int start, int size)
0045 {
0046     writew(PCTODSP_BASED(start), base + JQS_wStart);
0047     writew(PCTODSP_OFFSET(size) - 1, base + JQS_wSize);
0048     writew(0, base + JQS_wHead);
0049     writew(0, base + JQS_wTail);
0050 }
0051 EXPORT_SYMBOL(snd_msnd_init_queue);
0052 
0053 static int snd_msnd_wait_TXDE(struct snd_msnd *dev)
0054 {
0055     unsigned int io = dev->io;
0056     int timeout = 1000;
0057 
0058     while (timeout-- > 0)
0059         if (inb(io + HP_ISR) & HPISR_TXDE)
0060             return 0;
0061 
0062     return -EIO;
0063 }
0064 
0065 static int snd_msnd_wait_HC0(struct snd_msnd *dev)
0066 {
0067     unsigned int io = dev->io;
0068     int timeout = 1000;
0069 
0070     while (timeout-- > 0)
0071         if (!(inb(io + HP_CVR) & HPCVR_HC))
0072             return 0;
0073 
0074     return -EIO;
0075 }
0076 
0077 int snd_msnd_send_dsp_cmd(struct snd_msnd *dev, u8 cmd)
0078 {
0079     unsigned long flags;
0080 
0081     spin_lock_irqsave(&dev->lock, flags);
0082     if (snd_msnd_wait_HC0(dev) == 0) {
0083         outb(cmd, dev->io + HP_CVR);
0084         spin_unlock_irqrestore(&dev->lock, flags);
0085         return 0;
0086     }
0087     spin_unlock_irqrestore(&dev->lock, flags);
0088 
0089     snd_printd(KERN_ERR LOGNAME ": Send DSP command timeout\n");
0090 
0091     return -EIO;
0092 }
0093 EXPORT_SYMBOL(snd_msnd_send_dsp_cmd);
0094 
0095 int snd_msnd_send_word(struct snd_msnd *dev, unsigned char high,
0096            unsigned char mid, unsigned char low)
0097 {
0098     unsigned int io = dev->io;
0099 
0100     if (snd_msnd_wait_TXDE(dev) == 0) {
0101         outb(high, io + HP_TXH);
0102         outb(mid, io + HP_TXM);
0103         outb(low, io + HP_TXL);
0104         return 0;
0105     }
0106 
0107     snd_printd(KERN_ERR LOGNAME ": Send host word timeout\n");
0108 
0109     return -EIO;
0110 }
0111 EXPORT_SYMBOL(snd_msnd_send_word);
0112 
0113 int snd_msnd_upload_host(struct snd_msnd *dev, const u8 *bin, int len)
0114 {
0115     int i;
0116 
0117     if (len % 3 != 0) {
0118         snd_printk(KERN_ERR LOGNAME
0119                ": Upload host data not multiple of 3!\n");
0120         return -EINVAL;
0121     }
0122 
0123     for (i = 0; i < len; i += 3)
0124         if (snd_msnd_send_word(dev, bin[i], bin[i + 1], bin[i + 2]))
0125             return -EIO;
0126 
0127     inb(dev->io + HP_RXL);
0128     inb(dev->io + HP_CVR);
0129 
0130     return 0;
0131 }
0132 EXPORT_SYMBOL(snd_msnd_upload_host);
0133 
0134 int snd_msnd_enable_irq(struct snd_msnd *dev)
0135 {
0136     unsigned long flags;
0137 
0138     if (dev->irq_ref++)
0139         return 0;
0140 
0141     snd_printdd(LOGNAME ": Enabling IRQ\n");
0142 
0143     spin_lock_irqsave(&dev->lock, flags);
0144     if (snd_msnd_wait_TXDE(dev) == 0) {
0145         outb(inb(dev->io + HP_ICR) | HPICR_TREQ, dev->io + HP_ICR);
0146         if (dev->type == msndClassic)
0147             outb(dev->irqid, dev->io + HP_IRQM);
0148 
0149         outb(inb(dev->io + HP_ICR) & ~HPICR_TREQ, dev->io + HP_ICR);
0150         outb(inb(dev->io + HP_ICR) | HPICR_RREQ, dev->io + HP_ICR);
0151         enable_irq(dev->irq);
0152         snd_msnd_init_queue(dev->DSPQ, dev->dspq_data_buff,
0153                     dev->dspq_buff_size);
0154         spin_unlock_irqrestore(&dev->lock, flags);
0155         return 0;
0156     }
0157     spin_unlock_irqrestore(&dev->lock, flags);
0158 
0159     snd_printd(KERN_ERR LOGNAME ": Enable IRQ failed\n");
0160 
0161     return -EIO;
0162 }
0163 EXPORT_SYMBOL(snd_msnd_enable_irq);
0164 
0165 int snd_msnd_disable_irq(struct snd_msnd *dev)
0166 {
0167     unsigned long flags;
0168 
0169     if (--dev->irq_ref > 0)
0170         return 0;
0171 
0172     if (dev->irq_ref < 0)
0173         snd_printd(KERN_WARNING LOGNAME ": IRQ ref count is %d\n",
0174                dev->irq_ref);
0175 
0176     snd_printdd(LOGNAME ": Disabling IRQ\n");
0177 
0178     spin_lock_irqsave(&dev->lock, flags);
0179     if (snd_msnd_wait_TXDE(dev) == 0) {
0180         outb(inb(dev->io + HP_ICR) & ~HPICR_RREQ, dev->io + HP_ICR);
0181         if (dev->type == msndClassic)
0182             outb(HPIRQ_NONE, dev->io + HP_IRQM);
0183         disable_irq(dev->irq);
0184         spin_unlock_irqrestore(&dev->lock, flags);
0185         return 0;
0186     }
0187     spin_unlock_irqrestore(&dev->lock, flags);
0188 
0189     snd_printd(KERN_ERR LOGNAME ": Disable IRQ failed\n");
0190 
0191     return -EIO;
0192 }
0193 EXPORT_SYMBOL(snd_msnd_disable_irq);
0194 
0195 static inline long get_play_delay_jiffies(struct snd_msnd *chip, long size)
0196 {
0197     long tmp = (size * HZ * chip->play_sample_size) / 8;
0198     return tmp / (chip->play_sample_rate * chip->play_channels);
0199 }
0200 
0201 static void snd_msnd_dsp_write_flush(struct snd_msnd *chip)
0202 {
0203     if (!(chip->mode & FMODE_WRITE) || !test_bit(F_WRITING, &chip->flags))
0204         return;
0205     set_bit(F_WRITEFLUSH, &chip->flags);
0206 /*  interruptible_sleep_on_timeout(
0207         &chip->writeflush,
0208         get_play_delay_jiffies(&chip, chip->DAPF.len));*/
0209     clear_bit(F_WRITEFLUSH, &chip->flags);
0210     if (!signal_pending(current))
0211         schedule_timeout_interruptible(
0212             get_play_delay_jiffies(chip, chip->play_period_bytes));
0213     clear_bit(F_WRITING, &chip->flags);
0214 }
0215 
0216 void snd_msnd_dsp_halt(struct snd_msnd *chip, struct file *file)
0217 {
0218     if ((file ? file->f_mode : chip->mode) & FMODE_READ) {
0219         clear_bit(F_READING, &chip->flags);
0220         snd_msnd_send_dsp_cmd(chip, HDEX_RECORD_STOP);
0221         snd_msnd_disable_irq(chip);
0222         if (file) {
0223             snd_printd(KERN_INFO LOGNAME
0224                    ": Stopping read for %p\n", file);
0225             chip->mode &= ~FMODE_READ;
0226         }
0227         clear_bit(F_AUDIO_READ_INUSE, &chip->flags);
0228     }
0229     if ((file ? file->f_mode : chip->mode) & FMODE_WRITE) {
0230         if (test_bit(F_WRITING, &chip->flags)) {
0231             snd_msnd_dsp_write_flush(chip);
0232             snd_msnd_send_dsp_cmd(chip, HDEX_PLAY_STOP);
0233         }
0234         snd_msnd_disable_irq(chip);
0235         if (file) {
0236             snd_printd(KERN_INFO
0237                    LOGNAME ": Stopping write for %p\n", file);
0238             chip->mode &= ~FMODE_WRITE;
0239         }
0240         clear_bit(F_AUDIO_WRITE_INUSE, &chip->flags);
0241     }
0242 }
0243 EXPORT_SYMBOL(snd_msnd_dsp_halt);
0244 
0245 
0246 int snd_msnd_DARQ(struct snd_msnd *chip, int bank)
0247 {
0248     int /*size, n,*/ timeout = 3;
0249     u16 wTmp;
0250     /* void *DAQD; */
0251 
0252     /* Increment the tail and check for queue wrap */
0253     wTmp = readw(chip->DARQ + JQS_wTail) + PCTODSP_OFFSET(DAQDS__size);
0254     if (wTmp > readw(chip->DARQ + JQS_wSize))
0255         wTmp = 0;
0256     while (wTmp == readw(chip->DARQ + JQS_wHead) && timeout--)
0257         udelay(1);
0258 
0259     if (chip->capturePeriods == 2) {
0260         void __iomem *pDAQ = chip->mappedbase + DARQ_DATA_BUFF +
0261                  bank * DAQDS__size + DAQDS_wStart;
0262         unsigned short offset = 0x3000 + chip->capturePeriodBytes;
0263 
0264         if (readw(pDAQ) != PCTODSP_BASED(0x3000))
0265             offset = 0x3000;
0266         writew(PCTODSP_BASED(offset), pDAQ);
0267     }
0268 
0269     writew(wTmp, chip->DARQ + JQS_wTail);
0270 
0271 #if 0
0272     /* Get our digital audio queue struct */
0273     DAQD = bank * DAQDS__size + chip->mappedbase + DARQ_DATA_BUFF;
0274 
0275     /* Get length of data */
0276     size = readw(DAQD + DAQDS_wSize);
0277 
0278     /* Read data from the head (unprotected bank 1 access okay
0279        since this is only called inside an interrupt) */
0280     outb(HPBLKSEL_1, chip->io + HP_BLKS);
0281     n = msnd_fifo_write(&chip->DARF,
0282                 (char *)(chip->base + bank * DAR_BUFF_SIZE),
0283                 size, 0);
0284     if (n <= 0) {
0285         outb(HPBLKSEL_0, chip->io + HP_BLKS);
0286         return n;
0287     }
0288     outb(HPBLKSEL_0, chip->io + HP_BLKS);
0289 #endif
0290 
0291     return 1;
0292 }
0293 EXPORT_SYMBOL(snd_msnd_DARQ);
0294 
0295 int snd_msnd_DAPQ(struct snd_msnd *chip, int start)
0296 {
0297     u16 DAPQ_tail;
0298     int protect = start, nbanks = 0;
0299     void    __iomem *DAQD;
0300     static int play_banks_submitted;
0301     /* unsigned long flags;
0302     spin_lock_irqsave(&chip->lock, flags); not necessary */
0303 
0304     DAPQ_tail = readw(chip->DAPQ + JQS_wTail);
0305     while (DAPQ_tail != readw(chip->DAPQ + JQS_wHead) || start) {
0306         int bank_num = DAPQ_tail / PCTODSP_OFFSET(DAQDS__size);
0307 
0308         if (start) {
0309             start = 0;
0310             play_banks_submitted = 0;
0311         }
0312 
0313         /* Get our digital audio queue struct */
0314         DAQD = bank_num * DAQDS__size + chip->mappedbase +
0315             DAPQ_DATA_BUFF;
0316 
0317         /* Write size of this bank */
0318         writew(chip->play_period_bytes, DAQD + DAQDS_wSize);
0319         if (play_banks_submitted < 3)
0320             ++play_banks_submitted;
0321         else if (chip->playPeriods == 2) {
0322             unsigned short offset = chip->play_period_bytes;
0323 
0324             if (readw(DAQD + DAQDS_wStart) != PCTODSP_BASED(0x0))
0325                 offset = 0;
0326 
0327             writew(PCTODSP_BASED(offset), DAQD + DAQDS_wStart);
0328         }
0329         ++nbanks;
0330 
0331         /* Then advance the tail */
0332         /*
0333         if (protect)
0334             snd_printd(KERN_INFO "B %X %lX\n",
0335                    bank_num, xtime.tv_usec);
0336         */
0337 
0338         DAPQ_tail = (++bank_num % 3) * PCTODSP_OFFSET(DAQDS__size);
0339         writew(DAPQ_tail, chip->DAPQ + JQS_wTail);
0340         /* Tell the DSP to play the bank */
0341         snd_msnd_send_dsp_cmd(chip, HDEX_PLAY_START);
0342         if (protect)
0343             if (2 == bank_num)
0344                 break;
0345     }
0346     /*
0347     if (protect)
0348         snd_printd(KERN_INFO "%lX\n", xtime.tv_usec);
0349     */
0350     /* spin_unlock_irqrestore(&chip->lock, flags); not necessary */
0351     return nbanks;
0352 }
0353 EXPORT_SYMBOL(snd_msnd_DAPQ);
0354 
0355 static void snd_msnd_play_reset_queue(struct snd_msnd *chip,
0356                       unsigned int pcm_periods,
0357                       unsigned int pcm_count)
0358 {
0359     int n;
0360     void    __iomem *pDAQ = chip->mappedbase + DAPQ_DATA_BUFF;
0361 
0362     chip->last_playbank = -1;
0363     chip->playLimit = pcm_count * (pcm_periods - 1);
0364     chip->playPeriods = pcm_periods;
0365     writew(PCTODSP_OFFSET(0 * DAQDS__size), chip->DAPQ + JQS_wHead);
0366     writew(PCTODSP_OFFSET(0 * DAQDS__size), chip->DAPQ + JQS_wTail);
0367 
0368     chip->play_period_bytes = pcm_count;
0369 
0370     for (n = 0; n < pcm_periods; ++n, pDAQ += DAQDS__size) {
0371         writew(PCTODSP_BASED((u32)(pcm_count * n)),
0372             pDAQ + DAQDS_wStart);
0373         writew(0, pDAQ + DAQDS_wSize);
0374         writew(1, pDAQ + DAQDS_wFormat);
0375         writew(chip->play_sample_size, pDAQ + DAQDS_wSampleSize);
0376         writew(chip->play_channels, pDAQ + DAQDS_wChannels);
0377         writew(chip->play_sample_rate, pDAQ + DAQDS_wSampleRate);
0378         writew(HIMT_PLAY_DONE * 0x100 + n, pDAQ + DAQDS_wIntMsg);
0379         writew(n, pDAQ + DAQDS_wFlags);
0380     }
0381 }
0382 
0383 static void snd_msnd_capture_reset_queue(struct snd_msnd *chip,
0384                      unsigned int pcm_periods,
0385                      unsigned int pcm_count)
0386 {
0387     int     n;
0388     void        __iomem *pDAQ;
0389     /* unsigned long    flags; */
0390 
0391     /* snd_msnd_init_queue(chip->DARQ, DARQ_DATA_BUFF, DARQ_BUFF_SIZE); */
0392 
0393     chip->last_recbank = 2;
0394     chip->captureLimit = pcm_count * (pcm_periods - 1);
0395     chip->capturePeriods = pcm_periods;
0396     writew(PCTODSP_OFFSET(0 * DAQDS__size), chip->DARQ + JQS_wHead);
0397     writew(PCTODSP_OFFSET(chip->last_recbank * DAQDS__size),
0398         chip->DARQ + JQS_wTail);
0399 
0400 #if 0 /* Critical section: bank 1 access. this is how the OSS driver does it:*/
0401     spin_lock_irqsave(&chip->lock, flags);
0402     outb(HPBLKSEL_1, chip->io + HP_BLKS);
0403     memset_io(chip->mappedbase, 0, DAR_BUFF_SIZE * 3);
0404     outb(HPBLKSEL_0, chip->io + HP_BLKS);
0405     spin_unlock_irqrestore(&chip->lock, flags);
0406 #endif
0407 
0408     chip->capturePeriodBytes = pcm_count;
0409     snd_printdd("snd_msnd_capture_reset_queue() %i\n", pcm_count);
0410 
0411     pDAQ = chip->mappedbase + DARQ_DATA_BUFF;
0412 
0413     for (n = 0; n < pcm_periods; ++n, pDAQ += DAQDS__size) {
0414         u32 tmp = pcm_count * n;
0415 
0416         writew(PCTODSP_BASED(tmp + 0x3000), pDAQ + DAQDS_wStart);
0417         writew(pcm_count, pDAQ + DAQDS_wSize);
0418         writew(1, pDAQ + DAQDS_wFormat);
0419         writew(chip->capture_sample_size, pDAQ + DAQDS_wSampleSize);
0420         writew(chip->capture_channels, pDAQ + DAQDS_wChannels);
0421         writew(chip->capture_sample_rate, pDAQ + DAQDS_wSampleRate);
0422         writew(HIMT_RECORD_DONE * 0x100 + n, pDAQ + DAQDS_wIntMsg);
0423         writew(n, pDAQ + DAQDS_wFlags);
0424     }
0425 }
0426 
0427 static const struct snd_pcm_hardware snd_msnd_playback = {
0428     .info =         SNDRV_PCM_INFO_MMAP_IOMEM |
0429                 SNDRV_PCM_INFO_INTERLEAVED |
0430                 SNDRV_PCM_INFO_MMAP_VALID |
0431                 SNDRV_PCM_INFO_BATCH,
0432     .formats =      SNDRV_PCM_FMTBIT_U8 | SNDRV_PCM_FMTBIT_S16_LE,
0433     .rates =        SNDRV_PCM_RATE_8000_48000,
0434     .rate_min =     8000,
0435     .rate_max =     48000,
0436     .channels_min =     1,
0437     .channels_max =     2,
0438     .buffer_bytes_max = 0x3000,
0439     .period_bytes_min = 0x40,
0440     .period_bytes_max = 0x1800,
0441     .periods_min =      2,
0442     .periods_max =      3,
0443     .fifo_size =        0,
0444 };
0445 
0446 static const struct snd_pcm_hardware snd_msnd_capture = {
0447     .info =         SNDRV_PCM_INFO_MMAP_IOMEM |
0448                 SNDRV_PCM_INFO_INTERLEAVED |
0449                 SNDRV_PCM_INFO_MMAP_VALID |
0450                 SNDRV_PCM_INFO_BATCH,
0451     .formats =      SNDRV_PCM_FMTBIT_U8 | SNDRV_PCM_FMTBIT_S16_LE,
0452     .rates =        SNDRV_PCM_RATE_8000_48000,
0453     .rate_min =     8000,
0454     .rate_max =     48000,
0455     .channels_min =     1,
0456     .channels_max =     2,
0457     .buffer_bytes_max = 0x3000,
0458     .period_bytes_min = 0x40,
0459     .period_bytes_max = 0x1800,
0460     .periods_min =      2,
0461     .periods_max =      3,
0462     .fifo_size =        0,
0463 };
0464 
0465 
0466 static int snd_msnd_playback_open(struct snd_pcm_substream *substream)
0467 {
0468     struct snd_pcm_runtime *runtime = substream->runtime;
0469     struct snd_msnd *chip = snd_pcm_substream_chip(substream);
0470 
0471     set_bit(F_AUDIO_WRITE_INUSE, &chip->flags);
0472     clear_bit(F_WRITING, &chip->flags);
0473     snd_msnd_enable_irq(chip);
0474 
0475     runtime->dma_area = (__force void *)chip->mappedbase;
0476     runtime->dma_addr = chip->base;
0477     runtime->dma_bytes = 0x3000;
0478 
0479     chip->playback_substream = substream;
0480     runtime->hw = snd_msnd_playback;
0481     return 0;
0482 }
0483 
0484 static int snd_msnd_playback_close(struct snd_pcm_substream *substream)
0485 {
0486     struct snd_msnd *chip = snd_pcm_substream_chip(substream);
0487 
0488     snd_msnd_disable_irq(chip);
0489     clear_bit(F_AUDIO_WRITE_INUSE, &chip->flags);
0490     return 0;
0491 }
0492 
0493 
0494 static int snd_msnd_playback_hw_params(struct snd_pcm_substream *substream,
0495                     struct snd_pcm_hw_params *params)
0496 {
0497     int i;
0498     struct snd_msnd *chip = snd_pcm_substream_chip(substream);
0499     void    __iomem *pDAQ = chip->mappedbase + DAPQ_DATA_BUFF;
0500 
0501     chip->play_sample_size = snd_pcm_format_width(params_format(params));
0502     chip->play_channels = params_channels(params);
0503     chip->play_sample_rate = params_rate(params);
0504 
0505     for (i = 0; i < 3; ++i, pDAQ += DAQDS__size) {
0506         writew(chip->play_sample_size, pDAQ + DAQDS_wSampleSize);
0507         writew(chip->play_channels, pDAQ + DAQDS_wChannels);
0508         writew(chip->play_sample_rate, pDAQ + DAQDS_wSampleRate);
0509     }
0510     /* dont do this here:
0511      * snd_msnd_calibrate_adc(chip->play_sample_rate);
0512      */
0513 
0514     return 0;
0515 }
0516 
0517 static int snd_msnd_playback_prepare(struct snd_pcm_substream *substream)
0518 {
0519     struct snd_msnd *chip = snd_pcm_substream_chip(substream);
0520     unsigned int pcm_size = snd_pcm_lib_buffer_bytes(substream);
0521     unsigned int pcm_count = snd_pcm_lib_period_bytes(substream);
0522     unsigned int pcm_periods = pcm_size / pcm_count;
0523 
0524     snd_msnd_play_reset_queue(chip, pcm_periods, pcm_count);
0525     chip->playDMAPos = 0;
0526     return 0;
0527 }
0528 
0529 static int snd_msnd_playback_trigger(struct snd_pcm_substream *substream,
0530                      int cmd)
0531 {
0532     struct snd_msnd *chip = snd_pcm_substream_chip(substream);
0533     int result = 0;
0534 
0535     if (cmd == SNDRV_PCM_TRIGGER_START) {
0536         snd_printdd("snd_msnd_playback_trigger(START)\n");
0537         chip->banksPlayed = 0;
0538         set_bit(F_WRITING, &chip->flags);
0539         snd_msnd_DAPQ(chip, 1);
0540     } else if (cmd == SNDRV_PCM_TRIGGER_STOP) {
0541         snd_printdd("snd_msnd_playback_trigger(STop)\n");
0542         /* interrupt diagnostic, comment this out later */
0543         clear_bit(F_WRITING, &chip->flags);
0544         snd_msnd_send_dsp_cmd(chip, HDEX_PLAY_STOP);
0545     } else {
0546         snd_printd(KERN_ERR "snd_msnd_playback_trigger(?????)\n");
0547         result = -EINVAL;
0548     }
0549 
0550     snd_printdd("snd_msnd_playback_trigger() ENDE\n");
0551     return result;
0552 }
0553 
0554 static snd_pcm_uframes_t
0555 snd_msnd_playback_pointer(struct snd_pcm_substream *substream)
0556 {
0557     struct snd_msnd *chip = snd_pcm_substream_chip(substream);
0558 
0559     return bytes_to_frames(substream->runtime, chip->playDMAPos);
0560 }
0561 
0562 
0563 static const struct snd_pcm_ops snd_msnd_playback_ops = {
0564     .open =     snd_msnd_playback_open,
0565     .close =    snd_msnd_playback_close,
0566     .hw_params =    snd_msnd_playback_hw_params,
0567     .prepare =  snd_msnd_playback_prepare,
0568     .trigger =  snd_msnd_playback_trigger,
0569     .pointer =  snd_msnd_playback_pointer,
0570     .mmap =     snd_pcm_lib_mmap_iomem,
0571 };
0572 
0573 static int snd_msnd_capture_open(struct snd_pcm_substream *substream)
0574 {
0575     struct snd_pcm_runtime *runtime = substream->runtime;
0576     struct snd_msnd *chip = snd_pcm_substream_chip(substream);
0577 
0578     set_bit(F_AUDIO_READ_INUSE, &chip->flags);
0579     snd_msnd_enable_irq(chip);
0580     runtime->dma_area = (__force void *)chip->mappedbase + 0x3000;
0581     runtime->dma_addr = chip->base + 0x3000;
0582     runtime->dma_bytes = 0x3000;
0583     memset(runtime->dma_area, 0, runtime->dma_bytes);
0584     chip->capture_substream = substream;
0585     runtime->hw = snd_msnd_capture;
0586     return 0;
0587 }
0588 
0589 static int snd_msnd_capture_close(struct snd_pcm_substream *substream)
0590 {
0591     struct snd_msnd *chip = snd_pcm_substream_chip(substream);
0592 
0593     snd_msnd_disable_irq(chip);
0594     clear_bit(F_AUDIO_READ_INUSE, &chip->flags);
0595     return 0;
0596 }
0597 
0598 static int snd_msnd_capture_prepare(struct snd_pcm_substream *substream)
0599 {
0600     struct snd_msnd *chip = snd_pcm_substream_chip(substream);
0601     unsigned int pcm_size = snd_pcm_lib_buffer_bytes(substream);
0602     unsigned int pcm_count = snd_pcm_lib_period_bytes(substream);
0603     unsigned int pcm_periods = pcm_size / pcm_count;
0604 
0605     snd_msnd_capture_reset_queue(chip, pcm_periods, pcm_count);
0606     chip->captureDMAPos = 0;
0607     return 0;
0608 }
0609 
0610 static int snd_msnd_capture_trigger(struct snd_pcm_substream *substream,
0611                     int cmd)
0612 {
0613     struct snd_msnd *chip = snd_pcm_substream_chip(substream);
0614 
0615     if (cmd == SNDRV_PCM_TRIGGER_START) {
0616         chip->last_recbank = -1;
0617         set_bit(F_READING, &chip->flags);
0618         if (snd_msnd_send_dsp_cmd(chip, HDEX_RECORD_START) == 0)
0619             return 0;
0620 
0621         clear_bit(F_READING, &chip->flags);
0622     } else if (cmd == SNDRV_PCM_TRIGGER_STOP) {
0623         clear_bit(F_READING, &chip->flags);
0624         snd_msnd_send_dsp_cmd(chip, HDEX_RECORD_STOP);
0625         return 0;
0626     }
0627     return -EINVAL;
0628 }
0629 
0630 
0631 static snd_pcm_uframes_t
0632 snd_msnd_capture_pointer(struct snd_pcm_substream *substream)
0633 {
0634     struct snd_pcm_runtime *runtime = substream->runtime;
0635     struct snd_msnd *chip = snd_pcm_substream_chip(substream);
0636 
0637     return bytes_to_frames(runtime, chip->captureDMAPos);
0638 }
0639 
0640 
0641 static int snd_msnd_capture_hw_params(struct snd_pcm_substream *substream,
0642                     struct snd_pcm_hw_params *params)
0643 {
0644     int     i;
0645     struct snd_msnd *chip = snd_pcm_substream_chip(substream);
0646     void        __iomem *pDAQ = chip->mappedbase + DARQ_DATA_BUFF;
0647 
0648     chip->capture_sample_size = snd_pcm_format_width(params_format(params));
0649     chip->capture_channels = params_channels(params);
0650     chip->capture_sample_rate = params_rate(params);
0651 
0652     for (i = 0; i < 3; ++i, pDAQ += DAQDS__size) {
0653         writew(chip->capture_sample_size, pDAQ + DAQDS_wSampleSize);
0654         writew(chip->capture_channels, pDAQ + DAQDS_wChannels);
0655         writew(chip->capture_sample_rate, pDAQ + DAQDS_wSampleRate);
0656     }
0657     return 0;
0658 }
0659 
0660 
0661 static const struct snd_pcm_ops snd_msnd_capture_ops = {
0662     .open =     snd_msnd_capture_open,
0663     .close =    snd_msnd_capture_close,
0664     .hw_params =    snd_msnd_capture_hw_params,
0665     .prepare =  snd_msnd_capture_prepare,
0666     .trigger =  snd_msnd_capture_trigger,
0667     .pointer =  snd_msnd_capture_pointer,
0668     .mmap =     snd_pcm_lib_mmap_iomem,
0669 };
0670 
0671 
0672 int snd_msnd_pcm(struct snd_card *card, int device)
0673 {
0674     struct snd_msnd *chip = card->private_data;
0675     struct snd_pcm  *pcm;
0676     int err;
0677 
0678     err = snd_pcm_new(card, "MSNDPINNACLE", device, 1, 1, &pcm);
0679     if (err < 0)
0680         return err;
0681 
0682     snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, &snd_msnd_playback_ops);
0683     snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, &snd_msnd_capture_ops);
0684 
0685     pcm->private_data = chip;
0686     strcpy(pcm->name, "Hurricane");
0687 
0688     return 0;
0689 }
0690 EXPORT_SYMBOL(snd_msnd_pcm);
0691 
0692 MODULE_DESCRIPTION("Common routines for Turtle Beach Multisound drivers");
0693 MODULE_LICENSE("GPL");
0694