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