Add the rt linux 4.1.3-rt3 as base
[kvmfornfv.git] / kernel / 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/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 }
63 EXPORT_SYMBOL(snd_msnd_init_queue);
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
89 int snd_msnd_send_dsp_cmd(struct snd_msnd *dev, u8 cmd)
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 }
105 EXPORT_SYMBOL(snd_msnd_send_dsp_cmd);
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 }
123 EXPORT_SYMBOL(snd_msnd_send_word);
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) {
130                 snd_printk(KERN_ERR LOGNAME
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 }
144 EXPORT_SYMBOL(snd_msnd_upload_host);
145
146 int snd_msnd_enable_irq(struct snd_msnd *dev)
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);
164                 snd_msnd_init_queue(dev->DSPQ, dev->dspq_data_buff,
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 }
175 EXPORT_SYMBOL(snd_msnd_enable_irq);
176
177 int snd_msnd_disable_irq(struct snd_msnd *dev)
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 }
205 EXPORT_SYMBOL(snd_msnd_disable_irq);
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))
223                 schedule_timeout_interruptible(
224                         get_play_delay_jiffies(chip, chip->play_period_bytes));
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);
232                 snd_msnd_send_dsp_cmd(chip, HDEX_RECORD_STOP);
233                 snd_msnd_disable_irq(chip);
234                 if (file) {
235                         snd_printd(KERN_INFO LOGNAME
236                                    ": Stopping read for %p\n", file);
237                         chip->mode &= ~FMODE_READ;
238                 }
239                 clear_bit(F_AUDIO_READ_INUSE, &chip->flags);
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);
244                         snd_msnd_send_dsp_cmd(chip, HDEX_PLAY_STOP);
245                 }
246                 snd_msnd_disable_irq(chip);
247                 if (file) {
248                         snd_printd(KERN_INFO
249                                    LOGNAME ": Stopping write for %p\n", file);
250                         chip->mode &= ~FMODE_WRITE;
251                 }
252                 clear_bit(F_AUDIO_WRITE_INUSE, &chip->flags);
253         }
254 }
255 EXPORT_SYMBOL(snd_msnd_dsp_halt);
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 }
305 EXPORT_SYMBOL(snd_msnd_DARQ);
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 +
327                         DAPQ_DATA_BUFF;
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 */
353                 snd_msnd_send_dsp_cmd(chip, HDEX_PLAY_START);
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 }
365 EXPORT_SYMBOL(snd_msnd_DAPQ);
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;
377         writew(PCTODSP_OFFSET(0 * DAQDS__size), chip->DAPQ + JQS_wHead);
378         writew(PCTODSP_OFFSET(0 * DAQDS__size), chip->DAPQ + JQS_wTail);
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);
387                 writew(chip->play_sample_size, pDAQ + DAQDS_wSampleSize);
388                 writew(chip->play_channels, pDAQ + DAQDS_wChannels);
389                 writew(chip->play_sample_rate, pDAQ + DAQDS_wSampleRate);
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;
408         writew(PCTODSP_OFFSET(0 * DAQDS__size), chip->DARQ + JQS_wHead);
409         writew(PCTODSP_OFFSET(chip->last_recbank * DAQDS__size),
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);
431                 writew(chip->capture_sample_size, pDAQ + DAQDS_wSampleSize);
432                 writew(chip->capture_channels, pDAQ + DAQDS_wChannels);
433                 writew(chip->capture_sample_rate, pDAQ + DAQDS_wSampleRate);
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 |
441                                 SNDRV_PCM_INFO_INTERLEAVED |
442                                 SNDRV_PCM_INFO_MMAP_VALID |
443                                 SNDRV_PCM_INFO_BATCH,
444         .formats =              SNDRV_PCM_FMTBIT_U8 | SNDRV_PCM_FMTBIT_S16_LE,
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 |
460                                 SNDRV_PCM_INFO_INTERLEAVED |
461                                 SNDRV_PCM_INFO_MMAP_VALID |
462                                 SNDRV_PCM_INFO_BATCH,
463         .formats =              SNDRV_PCM_FMTBIT_U8 | SNDRV_PCM_FMTBIT_S16_LE,
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
483         set_bit(F_AUDIO_WRITE_INUSE, &chip->flags);
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);
500         clear_bit(F_AUDIO_WRITE_INUSE, &chip->flags);
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
512         chip->play_sample_size = snd_pcm_format_width(params_format(params));
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) {
517                 writew(chip->play_sample_size, pDAQ + DAQDS_wSampleSize);
518                 writew(chip->play_channels, pDAQ + DAQDS_wChannels);
519                 writew(chip->play_sample_rate, pDAQ + DAQDS_wSampleRate);
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);
555                 snd_msnd_send_dsp_cmd(chip, HDEX_PLAY_STOP);
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
589         set_bit(F_AUDIO_READ_INUSE, &chip->flags);
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);
604         clear_bit(F_AUDIO_READ_INUSE, &chip->flags);
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);
628                 if (snd_msnd_send_dsp_cmd(chip, HDEX_RECORD_START) == 0)
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);
634                 snd_msnd_send_dsp_cmd(chip, HDEX_RECORD_STOP);
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
658         chip->capture_sample_size = snd_pcm_format_width(params_format(params));
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) {
663                 writew(chip->capture_sample_size, pDAQ + DAQDS_wSampleSize);
664                 writew(chip->capture_channels, pDAQ + DAQDS_wChannels);
665                 writew(chip->capture_sample_rate, pDAQ + DAQDS_wSampleRate);
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 {
684         struct snd_msnd *chip = card->private_data;
685         struct snd_pcm  *pcm;
686         int err;
687
688         err = snd_pcm_new(card, "MSNDPINNACLE", device, 1, 1, &pcm);
689         if (err < 0)
690                 return err;
691
692         snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, &snd_msnd_playback_ops);
693         snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, &snd_msnd_capture_ops);
694
695         pcm->private_data = chip;
696         strcpy(pcm->name, "Hurricane");
697
698         return 0;
699 }
700 EXPORT_SYMBOL(snd_msnd_pcm);
701
702 MODULE_DESCRIPTION("Common routines for Turtle Beach Multisound drivers");
703 MODULE_LICENSE("GPL");
704