~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

TOMOYO Linux Cross Reference
Linux/sound/isa/msnd/msnd_pinnacle.c

Version: ~ [ linux-6.2-rc3 ] ~ [ linux-6.1.5 ] ~ [ linux-6.0.19 ] ~ [ linux-5.19.17 ] ~ [ linux-5.18.19 ] ~ [ linux-5.17.15 ] ~ [ linux-5.16.20 ] ~ [ linux-5.15.87 ] ~ [ linux-5.14.21 ] ~ [ linux-5.13.19 ] ~ [ linux-5.12.19 ] ~ [ linux-5.11.22 ] ~ [ linux-5.10.162 ] ~ [ linux-5.9.16 ] ~ [ linux-5.8.18 ] ~ [ linux-5.7.19 ] ~ [ linux-5.6.19 ] ~ [ linux-5.5.19 ] ~ [ linux-5.4.228 ] ~ [ linux-5.3.18 ] ~ [ linux-5.2.21 ] ~ [ linux-5.1.21 ] ~ [ linux-5.0.21 ] ~ [ linux-4.20.17 ] ~ [ linux-4.19.269 ] ~ [ linux-4.18.20 ] ~ [ linux-4.17.19 ] ~ [ linux-4.16.18 ] ~ [ linux-4.15.18 ] ~ [ linux-4.14.302 ] ~ [ linux-4.13.16 ] ~ [ linux-4.12.14 ] ~ [ linux-4.11.12 ] ~ [ linux-4.10.17 ] ~ [ linux-4.9.337 ] ~ [ linux-4.8.17 ] ~ [ linux-4.7.10 ] ~ [ linux-4.6.7 ] ~ [ linux-4.5.7 ] ~ [ linux-4.4.302 ] ~ [ linux-4.3.6 ] ~ [ linux-4.2.8 ] ~ [ linux-4.1.52 ] ~ [ linux-4.0.9 ] ~ [ linux-3.10.108 ] ~ [ linux-2.6.32.71 ] ~ [ linux-2.6.0 ] ~ [ linux-2.4.37.11 ] ~ [ unix-v6-master ] ~ [ ccs-tools-1.8.9 ] ~ [ policy-sample ] ~
Architecture: ~ [ i386 ] ~ [ alpha ] ~ [ m68k ] ~ [ mips ] ~ [ ppc ] ~ [ sparc ] ~ [ sparc64 ] ~

  1 // SPDX-License-Identifier: GPL-2.0-or-later
  2 /*********************************************************************
  3  *
  4  * Linux multisound pinnacle/fiji driver for ALSA.
  5  *
  6  * 2002/06/30 Karsten Wiese:
  7  *      for now this is only used to build a pinnacle / fiji driver.
  8  *      the OSS parent of this code is designed to also support
  9  *      the multisound classic via the file msnd_classic.c.
 10  *      to make it easier for some brave heart to implemt classic
 11  *      support in alsa, i left all the MSND_CLASSIC tokens in this file.
 12  *      but for now this untested & undone.
 13  *
 14  * ripped from linux kernel 2.4.18 by Karsten Wiese.
 15  *
 16  * the following is a copy of the 2.4.18 OSS FREE file-heading comment:
 17  *
 18  * Turtle Beach MultiSound Sound Card Driver for Linux
 19  * msnd_pinnacle.c / msnd_classic.c
 20  *
 21  * -- If MSND_CLASSIC is defined:
 22  *
 23  *     -> driver for Turtle Beach Classic/Monterey/Tahiti
 24  *
 25  * -- Else
 26  *
 27  *     -> driver for Turtle Beach Pinnacle/Fiji
 28  *
 29  * 12-3-2000  Modified IO port validation  Steve Sycamore
 30  *
 31  * Copyright (C) 1998 Andrew Veliath
 32  *
 33  ********************************************************************/
 34 
 35 #include <linux/kernel.h>
 36 #include <linux/module.h>
 37 #include <linux/interrupt.h>
 38 #include <linux/types.h>
 39 #include <linux/delay.h>
 40 #include <linux/ioport.h>
 41 #include <linux/firmware.h>
 42 #include <linux/isa.h>
 43 #include <linux/isapnp.h>
 44 #include <linux/irq.h>
 45 #include <linux/io.h>
 46 
 47 #include <sound/core.h>
 48 #include <sound/initval.h>
 49 #include <sound/asound.h>
 50 #include <sound/pcm.h>
 51 #include <sound/mpu401.h>
 52 
 53 #ifdef MSND_CLASSIC
 54 # ifndef __alpha__
 55 #  define SLOWIO
 56 # endif
 57 #endif
 58 #include "msnd.h"
 59 #ifdef MSND_CLASSIC
 60 #  include "msnd_classic.h"
 61 #  define LOGNAME                       "msnd_classic"
 62 #  define DEV_NAME                      "msnd-classic"
 63 #else
 64 #  include "msnd_pinnacle.h"
 65 #  define LOGNAME                       "snd_msnd_pinnacle"
 66 #  define DEV_NAME                      "msnd-pinnacle"
 67 #endif
 68 
 69 static void set_default_audio_parameters(struct snd_msnd *chip)
 70 {
 71         chip->play_sample_size = snd_pcm_format_width(DEFSAMPLESIZE);
 72         chip->play_sample_rate = DEFSAMPLERATE;
 73         chip->play_channels = DEFCHANNELS;
 74         chip->capture_sample_size = snd_pcm_format_width(DEFSAMPLESIZE);
 75         chip->capture_sample_rate = DEFSAMPLERATE;
 76         chip->capture_channels = DEFCHANNELS;
 77 }
 78 
 79 static void snd_msnd_eval_dsp_msg(struct snd_msnd *chip, u16 wMessage)
 80 {
 81         switch (HIBYTE(wMessage)) {
 82         case HIMT_PLAY_DONE: {
 83                 if (chip->banksPlayed < 3)
 84                         snd_printdd("%08X: HIMT_PLAY_DONE: %i\n",
 85                                 (unsigned)jiffies, LOBYTE(wMessage));
 86 
 87                 if (chip->last_playbank == LOBYTE(wMessage)) {
 88                         snd_printdd("chip.last_playbank == LOBYTE(wMessage)\n");
 89                         break;
 90                 }
 91                 chip->banksPlayed++;
 92 
 93                 if (test_bit(F_WRITING, &chip->flags))
 94                         snd_msnd_DAPQ(chip, 0);
 95 
 96                 chip->last_playbank = LOBYTE(wMessage);
 97                 chip->playDMAPos += chip->play_period_bytes;
 98                 if (chip->playDMAPos > chip->playLimit)
 99                         chip->playDMAPos = 0;
100                 snd_pcm_period_elapsed(chip->playback_substream);
101 
102                 break;
103         }
104         case HIMT_RECORD_DONE:
105                 if (chip->last_recbank == LOBYTE(wMessage))
106                         break;
107                 chip->last_recbank = LOBYTE(wMessage);
108                 chip->captureDMAPos += chip->capturePeriodBytes;
109                 if (chip->captureDMAPos > (chip->captureLimit))
110                         chip->captureDMAPos = 0;
111 
112                 if (test_bit(F_READING, &chip->flags))
113                         snd_msnd_DARQ(chip, chip->last_recbank);
114 
115                 snd_pcm_period_elapsed(chip->capture_substream);
116                 break;
117 
118         case HIMT_DSP:
119                 switch (LOBYTE(wMessage)) {
120 #ifndef MSND_CLASSIC
121                 case HIDSP_PLAY_UNDER:
122 #endif
123                 case HIDSP_INT_PLAY_UNDER:
124                         snd_printd(KERN_WARNING LOGNAME ": Play underflow %i\n",
125                                 chip->banksPlayed);
126                         if (chip->banksPlayed > 2)
127                                 clear_bit(F_WRITING, &chip->flags);
128                         break;
129 
130                 case HIDSP_INT_RECORD_OVER:
131                         snd_printd(KERN_WARNING LOGNAME ": Record overflow\n");
132                         clear_bit(F_READING, &chip->flags);
133                         break;
134 
135                 default:
136                         snd_printd(KERN_WARNING LOGNAME
137                                    ": DSP message %d 0x%02x\n",
138                                    LOBYTE(wMessage), LOBYTE(wMessage));
139                         break;
140                 }
141                 break;
142 
143         case HIMT_MIDI_IN_UCHAR:
144                 if (chip->msndmidi_mpu)
145                         snd_msndmidi_input_read(chip->msndmidi_mpu);
146                 break;
147 
148         default:
149                 snd_printd(KERN_WARNING LOGNAME ": HIMT message %d 0x%02x\n",
150                            HIBYTE(wMessage), HIBYTE(wMessage));
151                 break;
152         }
153 }
154 
155 static irqreturn_t snd_msnd_interrupt(int irq, void *dev_id)
156 {
157         struct snd_msnd *chip = dev_id;
158         void __iomem *pwDSPQData = chip->mappedbase + DSPQ_DATA_BUFF;
159         u16 head, tail, size;
160 
161         /* Send ack to DSP */
162         /* inb(chip->io + HP_RXL); */
163 
164         /* Evaluate queued DSP messages */
165         head = readw(chip->DSPQ + JQS_wHead);
166         tail = readw(chip->DSPQ + JQS_wTail);
167         size = readw(chip->DSPQ + JQS_wSize);
168         if (head > size || tail > size)
169                 goto out;
170         while (head != tail) {
171                 snd_msnd_eval_dsp_msg(chip, readw(pwDSPQData + 2 * head));
172                 if (++head > size)
173                         head = 0;
174                 writew(head, chip->DSPQ + JQS_wHead);
175         }
176  out:
177         /* Send ack to DSP */
178         inb(chip->io + HP_RXL);
179         return IRQ_HANDLED;
180 }
181 
182 
183 static int snd_msnd_reset_dsp(long io, unsigned char *info)
184 {
185         int timeout = 100;
186 
187         outb(HPDSPRESET_ON, io + HP_DSPR);
188         msleep(1);
189 #ifndef MSND_CLASSIC
190         if (info)
191                 *info = inb(io + HP_INFO);
192 #endif
193         outb(HPDSPRESET_OFF, io + HP_DSPR);
194         msleep(1);
195         while (timeout-- > 0) {
196                 if (inb(io + HP_CVR) == HP_CVR_DEF)
197                         return 0;
198                 msleep(1);
199         }
200         snd_printk(KERN_ERR LOGNAME ": Cannot reset DSP\n");
201 
202         return -EIO;
203 }
204 
205 static int snd_msnd_probe(struct snd_card *card)
206 {
207         struct snd_msnd *chip = card->private_data;
208         unsigned char info;
209 #ifndef MSND_CLASSIC
210         char *xv, *rev = NULL;
211         char *pin = "TB Pinnacle", *fiji = "TB Fiji";
212         char *pinfiji = "TB Pinnacle/Fiji";
213 #endif
214 
215         if (!request_region(chip->io, DSP_NUMIO, "probing")) {
216                 snd_printk(KERN_ERR LOGNAME ": I/O port conflict\n");
217                 return -ENODEV;
218         }
219 
220         if (snd_msnd_reset_dsp(chip->io, &info) < 0) {
221                 release_region(chip->io, DSP_NUMIO);
222                 return -ENODEV;
223         }
224 
225 #ifdef MSND_CLASSIC
226         strcpy(card->shortname, "Classic/Tahiti/Monterey");
227         strcpy(card->longname, "Turtle Beach Multisound");
228         printk(KERN_INFO LOGNAME ": %s, "
229                "I/O 0x%lx-0x%lx, IRQ %d, memory mapped to 0x%lX-0x%lX\n",
230                card->shortname,
231                chip->io, chip->io + DSP_NUMIO - 1,
232                chip->irq,
233                chip->base, chip->base + 0x7fff);
234 #else
235         switch (info >> 4) {
236         case 0xf:
237                 xv = "<= 1.15";
238                 break;
239         case 0x1:
240                 xv = "1.18/1.2";
241                 break;
242         case 0x2:
243                 xv = "1.3";
244                 break;
245         case 0x3:
246                 xv = "1.4";
247                 break;
248         default:
249                 xv = "unknown";
250                 break;
251         }
252 
253         switch (info & 0x7) {
254         case 0x0:
255                 rev = "I";
256                 strcpy(card->shortname, pin);
257                 break;
258         case 0x1:
259                 rev = "F";
260                 strcpy(card->shortname, pin);
261                 break;
262         case 0x2:
263                 rev = "G";
264                 strcpy(card->shortname, pin);
265                 break;
266         case 0x3:
267                 rev = "H";
268                 strcpy(card->shortname, pin);
269                 break;
270         case 0x4:
271                 rev = "E";
272                 strcpy(card->shortname, fiji);
273                 break;
274         case 0x5:
275                 rev = "C";
276                 strcpy(card->shortname, fiji);
277                 break;
278         case 0x6:
279                 rev = "D";
280                 strcpy(card->shortname, fiji);
281                 break;
282         case 0x7:
283                 rev = "A-B (Fiji) or A-E (Pinnacle)";
284                 strcpy(card->shortname, pinfiji);
285                 break;
286         }
287         strcpy(card->longname, "Turtle Beach Multisound Pinnacle");
288         printk(KERN_INFO LOGNAME ": %s revision %s, Xilinx version %s, "
289                "I/O 0x%lx-0x%lx, IRQ %d, memory mapped to 0x%lX-0x%lX\n",
290                card->shortname,
291                rev, xv,
292                chip->io, chip->io + DSP_NUMIO - 1,
293                chip->irq,
294                chip->base, chip->base + 0x7fff);
295 #endif
296 
297         release_region(chip->io, DSP_NUMIO);
298         return 0;
299 }
300 
301 static int snd_msnd_init_sma(struct snd_msnd *chip)
302 {
303         static int initted;
304         u16 mastVolLeft, mastVolRight;
305         unsigned long flags;
306 
307 #ifdef MSND_CLASSIC
308         outb(chip->memid, chip->io + HP_MEMM);
309 #endif
310         outb(HPBLKSEL_0, chip->io + HP_BLKS);
311         /* Motorola 56k shared memory base */
312         chip->SMA = chip->mappedbase + SMA_STRUCT_START;
313 
314         if (initted) {
315                 mastVolLeft = readw(chip->SMA + SMA_wCurrMastVolLeft);
316                 mastVolRight = readw(chip->SMA + SMA_wCurrMastVolRight);
317         } else
318                 mastVolLeft = mastVolRight = 0;
319         memset_io(chip->mappedbase, 0, 0x8000);
320 
321         /* Critical section: bank 1 access */
322         spin_lock_irqsave(&chip->lock, flags);
323         outb(HPBLKSEL_1, chip->io + HP_BLKS);
324         memset_io(chip->mappedbase, 0, 0x8000);
325         outb(HPBLKSEL_0, chip->io + HP_BLKS);
326         spin_unlock_irqrestore(&chip->lock, flags);
327 
328         /* Digital audio play queue */
329         chip->DAPQ = chip->mappedbase + DAPQ_OFFSET;
330         snd_msnd_init_queue(chip->DAPQ, DAPQ_DATA_BUFF, DAPQ_BUFF_SIZE);
331 
332         /* Digital audio record queue */
333         chip->DARQ = chip->mappedbase + DARQ_OFFSET;
334         snd_msnd_init_queue(chip->DARQ, DARQ_DATA_BUFF, DARQ_BUFF_SIZE);
335 
336         /* MIDI out queue */
337         chip->MODQ = chip->mappedbase + MODQ_OFFSET;
338         snd_msnd_init_queue(chip->MODQ, MODQ_DATA_BUFF, MODQ_BUFF_SIZE);
339 
340         /* MIDI in queue */
341         chip->MIDQ = chip->mappedbase + MIDQ_OFFSET;
342         snd_msnd_init_queue(chip->MIDQ, MIDQ_DATA_BUFF, MIDQ_BUFF_SIZE);
343 
344         /* DSP -> host message queue */
345         chip->DSPQ = chip->mappedbase + DSPQ_OFFSET;
346         snd_msnd_init_queue(chip->DSPQ, DSPQ_DATA_BUFF, DSPQ_BUFF_SIZE);
347 
348         /* Setup some DSP values */
349 #ifndef MSND_CLASSIC
350         writew(1, chip->SMA + SMA_wCurrPlayFormat);
351         writew(chip->play_sample_size, chip->SMA + SMA_wCurrPlaySampleSize);
352         writew(chip->play_channels, chip->SMA + SMA_wCurrPlayChannels);
353         writew(chip->play_sample_rate, chip->SMA + SMA_wCurrPlaySampleRate);
354 #endif
355         writew(chip->play_sample_rate, chip->SMA + SMA_wCalFreqAtoD);
356         writew(mastVolLeft, chip->SMA + SMA_wCurrMastVolLeft);
357         writew(mastVolRight, chip->SMA + SMA_wCurrMastVolRight);
358 #ifndef MSND_CLASSIC
359         writel(0x00010000, chip->SMA + SMA_dwCurrPlayPitch);
360         writel(0x00000001, chip->SMA + SMA_dwCurrPlayRate);
361 #endif
362         writew(0x303, chip->SMA + SMA_wCurrInputTagBits);
363 
364         initted = 1;
365 
366         return 0;
367 }
368 
369 
370 static int upload_dsp_code(struct snd_card *card)
371 {
372         struct snd_msnd *chip = card->private_data;
373         const struct firmware *init_fw = NULL, *perm_fw = NULL;
374         int err;
375 
376         outb(HPBLKSEL_0, chip->io + HP_BLKS);
377 
378         err = request_firmware(&init_fw, INITCODEFILE, card->dev);
379         if (err < 0) {
380                 printk(KERN_ERR LOGNAME ": Error loading " INITCODEFILE);
381                 goto cleanup1;
382         }
383         err = request_firmware(&perm_fw, PERMCODEFILE, card->dev);
384         if (err < 0) {
385                 printk(KERN_ERR LOGNAME ": Error loading " PERMCODEFILE);
386                 goto cleanup;
387         }
388 
389         memcpy_toio(chip->mappedbase, perm_fw->data, perm_fw->size);
390         if (snd_msnd_upload_host(chip, init_fw->data, init_fw->size) < 0) {
391                 printk(KERN_WARNING LOGNAME ": Error uploading to DSP\n");
392                 err = -ENODEV;
393                 goto cleanup;
394         }
395         printk(KERN_INFO LOGNAME ": DSP firmware uploaded\n");
396         err = 0;
397 
398 cleanup:
399         release_firmware(perm_fw);
400 cleanup1:
401         release_firmware(init_fw);
402         return err;
403 }
404 
405 #ifdef MSND_CLASSIC
406 static void reset_proteus(struct snd_msnd *chip)
407 {
408         outb(HPPRORESET_ON, chip->io + HP_PROR);
409         msleep(TIME_PRO_RESET);
410         outb(HPPRORESET_OFF, chip->io + HP_PROR);
411         msleep(TIME_PRO_RESET_DONE);
412 }
413 #endif
414 
415 static int snd_msnd_initialize(struct snd_card *card)
416 {
417         struct snd_msnd *chip = card->private_data;
418         int err, timeout;
419 
420 #ifdef MSND_CLASSIC
421         outb(HPWAITSTATE_0, chip->io + HP_WAIT);
422         outb(HPBITMODE_16, chip->io + HP_BITM);
423 
424         reset_proteus(chip);
425 #endif
426         err = snd_msnd_init_sma(chip);
427         if (err < 0) {
428                 printk(KERN_WARNING LOGNAME ": Cannot initialize SMA\n");
429                 return err;
430         }
431 
432         err = snd_msnd_reset_dsp(chip->io, NULL);
433         if (err < 0)
434                 return err;
435 
436         err = upload_dsp_code(card);
437         if (err < 0) {
438                 printk(KERN_WARNING LOGNAME ": Cannot upload DSP code\n");
439                 return err;
440         }
441 
442         timeout = 200;
443 
444         while (readw(chip->mappedbase)) {
445                 msleep(1);
446                 if (!timeout--) {
447                         snd_printd(KERN_ERR LOGNAME ": DSP reset timeout\n");
448                         return -EIO;
449                 }
450         }
451 
452         snd_msndmix_setup(chip);
453         return 0;
454 }
455 
456 static int snd_msnd_dsp_full_reset(struct snd_card *card)
457 {
458         struct snd_msnd *chip = card->private_data;
459         int rv;
460 
461         if (test_bit(F_RESETTING, &chip->flags) || ++chip->nresets > 10)
462                 return 0;
463 
464         set_bit(F_RESETTING, &chip->flags);
465         snd_msnd_dsp_halt(chip, NULL);  /* Unconditionally halt */
466 
467         rv = snd_msnd_initialize(card);
468         if (rv)
469                 printk(KERN_WARNING LOGNAME ": DSP reset failed\n");
470         snd_msndmix_force_recsrc(chip, 0);
471         clear_bit(F_RESETTING, &chip->flags);
472         return rv;
473 }
474 
475 static int snd_msnd_dev_free(struct snd_device *device)
476 {
477         snd_printdd("snd_msnd_chip_free()\n");
478         return 0;
479 }
480 
481 static int snd_msnd_send_dsp_cmd_chk(struct snd_msnd *chip, u8 cmd)
482 {
483         if (snd_msnd_send_dsp_cmd(chip, cmd) == 0)
484                 return 0;
485         snd_msnd_dsp_full_reset(chip->card);
486         return snd_msnd_send_dsp_cmd(chip, cmd);
487 }
488 
489 static int snd_msnd_calibrate_adc(struct snd_msnd *chip, u16 srate)
490 {
491         snd_printdd("snd_msnd_calibrate_adc(%i)\n", srate);
492         writew(srate, chip->SMA + SMA_wCalFreqAtoD);
493         if (chip->calibrate_signal == 0)
494                 writew(readw(chip->SMA + SMA_wCurrHostStatusFlags)
495                        | 0x0001, chip->SMA + SMA_wCurrHostStatusFlags);
496         else
497                 writew(readw(chip->SMA + SMA_wCurrHostStatusFlags)
498                        & ~0x0001, chip->SMA + SMA_wCurrHostStatusFlags);
499         if (snd_msnd_send_word(chip, 0, 0, HDEXAR_CAL_A_TO_D) == 0 &&
500             snd_msnd_send_dsp_cmd_chk(chip, HDEX_AUX_REQ) == 0) {
501                 schedule_timeout_interruptible(msecs_to_jiffies(333));
502                 return 0;
503         }
504         printk(KERN_WARNING LOGNAME ": ADC calibration failed\n");
505         return -EIO;
506 }
507 
508 /*
509  * ALSA callback function, called when attempting to open the MIDI device.
510  */
511 static int snd_msnd_mpu401_open(struct snd_mpu401 *mpu)
512 {
513         snd_msnd_enable_irq(mpu->private_data);
514         snd_msnd_send_dsp_cmd(mpu->private_data, HDEX_MIDI_IN_START);
515         return 0;
516 }
517 
518 static void snd_msnd_mpu401_close(struct snd_mpu401 *mpu)
519 {
520         snd_msnd_send_dsp_cmd(mpu->private_data, HDEX_MIDI_IN_STOP);
521         snd_msnd_disable_irq(mpu->private_data);
522 }
523 
524 static long mpu_io[SNDRV_CARDS] = SNDRV_DEFAULT_PORT;
525 static int mpu_irq[SNDRV_CARDS] = SNDRV_DEFAULT_IRQ;
526 
527 static int snd_msnd_attach(struct snd_card *card)
528 {
529         struct snd_msnd *chip = card->private_data;
530         int err;
531         static const struct snd_device_ops ops = {
532                 .dev_free =      snd_msnd_dev_free,
533                 };
534 
535         err = request_irq(chip->irq, snd_msnd_interrupt, 0, card->shortname,
536                           chip);
537         if (err < 0) {
538                 printk(KERN_ERR LOGNAME ": Couldn't grab IRQ %d\n", chip->irq);
539                 return err;
540         }
541         card->sync_irq = chip->irq;
542         if (request_region(chip->io, DSP_NUMIO, card->shortname) == NULL) {
543                 free_irq(chip->irq, chip);
544                 return -EBUSY;
545         }
546 
547         if (!request_mem_region(chip->base, BUFFSIZE, card->shortname)) {
548                 printk(KERN_ERR LOGNAME
549                         ": unable to grab memory region 0x%lx-0x%lx\n",
550                         chip->base, chip->base + BUFFSIZE - 1);
551                 release_region(chip->io, DSP_NUMIO);
552                 free_irq(chip->irq, chip);
553                 return -EBUSY;
554         }
555         chip->mappedbase = ioremap(chip->base, 0x8000);
556         if (!chip->mappedbase) {
557                 printk(KERN_ERR LOGNAME
558                         ": unable to map memory region 0x%lx-0x%lx\n",
559                         chip->base, chip->base + BUFFSIZE - 1);
560                 err = -EIO;
561                 goto err_release_region;
562         }
563 
564         err = snd_msnd_dsp_full_reset(card);
565         if (err < 0)
566                 goto err_release_region;
567 
568         /* Register device */
569         err = snd_device_new(card, SNDRV_DEV_LOWLEVEL, chip, &ops);
570         if (err < 0)
571                 goto err_release_region;
572 
573         err = snd_msnd_pcm(card, 0);
574         if (err < 0) {
575                 printk(KERN_ERR LOGNAME ": error creating new PCM device\n");
576                 goto err_release_region;
577         }
578 
579         err = snd_msndmix_new(card);
580         if (err < 0) {
581                 printk(KERN_ERR LOGNAME ": error creating new Mixer device\n");
582                 goto err_release_region;
583         }
584 
585 
586         if (mpu_io[0] != SNDRV_AUTO_PORT) {
587                 struct snd_mpu401 *mpu;
588 
589                 err = snd_mpu401_uart_new(card, 0, MPU401_HW_MPU401,
590                                           mpu_io[0],
591                                           MPU401_MODE_INPUT |
592                                           MPU401_MODE_OUTPUT,
593                                           mpu_irq[0],
594                                           &chip->rmidi);
595                 if (err < 0) {
596                         printk(KERN_ERR LOGNAME
597                                 ": error creating new Midi device\n");
598                         goto err_release_region;
599                 }
600                 mpu = chip->rmidi->private_data;
601 
602                 mpu->open_input = snd_msnd_mpu401_open;
603                 mpu->close_input = snd_msnd_mpu401_close;
604                 mpu->private_data = chip;
605         }
606 
607         disable_irq(chip->irq);
608         snd_msnd_calibrate_adc(chip, chip->play_sample_rate);
609         snd_msndmix_force_recsrc(chip, 0);
610 
611         err = snd_card_register(card);
612         if (err < 0)
613                 goto err_release_region;
614 
615         return 0;
616 
617 err_release_region:
618         iounmap(chip->mappedbase);
619         release_mem_region(chip->base, BUFFSIZE);
620         release_region(chip->io, DSP_NUMIO);
621         free_irq(chip->irq, chip);
622         return err;
623 }
624 
625 
626 static void snd_msnd_unload(struct snd_card *card)
627 {
628         struct snd_msnd *chip = card->private_data;
629 
630         iounmap(chip->mappedbase);
631         release_mem_region(chip->base, BUFFSIZE);
632         release_region(chip->io, DSP_NUMIO);
633         free_irq(chip->irq, chip);
634         snd_card_free(card);
635 }
636 
637 #ifndef MSND_CLASSIC
638 
639 /* Pinnacle/Fiji Logical Device Configuration */
640 
641 static int snd_msnd_write_cfg(int cfg, int reg, int value)
642 {
643         outb(reg, cfg);
644         outb(value, cfg + 1);
645         if (value != inb(cfg + 1)) {
646                 printk(KERN_ERR LOGNAME ": snd_msnd_write_cfg: I/O error\n");
647                 return -EIO;
648         }
649         return 0;
650 }
651 
652 static int snd_msnd_write_cfg_io0(int cfg, int num, u16 io)
653 {
654         if (snd_msnd_write_cfg(cfg, IREG_LOGDEVICE, num))
655                 return -EIO;
656         if (snd_msnd_write_cfg(cfg, IREG_IO0_BASEHI, HIBYTE(io)))
657                 return -EIO;
658         if (snd_msnd_write_cfg(cfg, IREG_IO0_BASELO, LOBYTE(io)))
659                 return -EIO;
660         return 0;
661 }
662 
663 static int snd_msnd_write_cfg_io1(int cfg, int num, u16 io)
664 {
665         if (snd_msnd_write_cfg(cfg, IREG_LOGDEVICE, num))
666                 return -EIO;
667         if (snd_msnd_write_cfg(cfg, IREG_IO1_BASEHI, HIBYTE(io)))
668                 return -EIO;
669         if (snd_msnd_write_cfg(cfg, IREG_IO1_BASELO, LOBYTE(io)))
670                 return -EIO;
671         return 0;
672 }
673 
674 static int snd_msnd_write_cfg_irq(int cfg, int num, u16 irq)
675 {
676         if (snd_msnd_write_cfg(cfg, IREG_LOGDEVICE, num))
677                 return -EIO;
678         if (snd_msnd_write_cfg(cfg, IREG_IRQ_NUMBER, LOBYTE(irq)))
679                 return -EIO;
680         if (snd_msnd_write_cfg(cfg, IREG_IRQ_TYPE, IRQTYPE_EDGE))
681                 return -EIO;
682         return 0;
683 }
684 
685 static int snd_msnd_write_cfg_mem(int cfg, int num, int mem)
686 {
687         u16 wmem;
688 
689         mem >>= 8;
690         wmem = (u16)(mem & 0xfff);
691         if (snd_msnd_write_cfg(cfg, IREG_LOGDEVICE, num))
692                 return -EIO;
693         if (snd_msnd_write_cfg(cfg, IREG_MEMBASEHI, HIBYTE(wmem)))
694                 return -EIO;
695         if (snd_msnd_write_cfg(cfg, IREG_MEMBASELO, LOBYTE(wmem)))
696                 return -EIO;
697         if (wmem && snd_msnd_write_cfg(cfg, IREG_MEMCONTROL,
698                                        MEMTYPE_HIADDR | MEMTYPE_16BIT))
699                 return -EIO;
700         return 0;
701 }
702 
703 static int snd_msnd_activate_logical(int cfg, int num)
704 {
705         if (snd_msnd_write_cfg(cfg, IREG_LOGDEVICE, num))
706                 return -EIO;
707         if (snd_msnd_write_cfg(cfg, IREG_ACTIVATE, LD_ACTIVATE))
708                 return -EIO;
709         return 0;
710 }
711 
712 static int snd_msnd_write_cfg_logical(int cfg, int num, u16 io0,
713                                       u16 io1, u16 irq, int mem)
714 {
715         if (snd_msnd_write_cfg(cfg, IREG_LOGDEVICE, num))
716                 return -EIO;
717         if (snd_msnd_write_cfg_io0(cfg, num, io0))
718                 return -EIO;
719         if (snd_msnd_write_cfg_io1(cfg, num, io1))
720                 return -EIO;
721         if (snd_msnd_write_cfg_irq(cfg, num, irq))
722                 return -EIO;
723         if (snd_msnd_write_cfg_mem(cfg, num, mem))
724                 return -EIO;
725         if (snd_msnd_activate_logical(cfg, num))
726                 return -EIO;
727         return 0;
728 }
729 
730 static int snd_msnd_pinnacle_cfg_reset(int cfg)
731 {
732         int i;
733 
734         /* Reset devices if told to */
735         printk(KERN_INFO LOGNAME ": Resetting all devices\n");
736         for (i = 0; i < 4; ++i)
737                 if (snd_msnd_write_cfg_logical(cfg, i, 0, 0, 0, 0))
738                         return -EIO;
739 
740         return 0;
741 }
742 #endif
743 
744 static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX;      /* Index 0-MAX */
745 static char *id[SNDRV_CARDS] = SNDRV_DEFAULT_STR;       /* ID for this card */
746 
747 module_param_array(index, int, NULL, 0444);
748 MODULE_PARM_DESC(index, "Index value for msnd_pinnacle soundcard.");
749 module_param_array(id, charp, NULL, 0444);
750 MODULE_PARM_DESC(id, "ID string for msnd_pinnacle soundcard.");
751 
752 static long io[SNDRV_CARDS] = SNDRV_DEFAULT_PORT;
753 static int irq[SNDRV_CARDS] = SNDRV_DEFAULT_IRQ;
754 static long mem[SNDRV_CARDS] = SNDRV_DEFAULT_PORT;
755 
756 #ifndef MSND_CLASSIC
757 static long cfg[SNDRV_CARDS] = SNDRV_DEFAULT_PORT;
758 
759 /* Extra Peripheral Configuration (Default: Disable) */
760 static long ide_io0[SNDRV_CARDS] = SNDRV_DEFAULT_PORT;
761 static long ide_io1[SNDRV_CARDS] = SNDRV_DEFAULT_PORT;
762 static int ide_irq[SNDRV_CARDS] = SNDRV_DEFAULT_IRQ;
763 
764 static long joystick_io[SNDRV_CARDS] = SNDRV_DEFAULT_PORT;
765 /* If we have the digital daugherboard... */
766 static int digital[SNDRV_CARDS];
767 
768 /* Extra Peripheral Configuration */
769 static int reset[SNDRV_CARDS];
770 #endif
771 
772 static int write_ndelay[SNDRV_CARDS] = { [0 ... (SNDRV_CARDS-1)] = 1 };
773 
774 static int calibrate_signal;
775 
776 #ifdef CONFIG_PNP
777 static bool isapnp[SNDRV_CARDS] = SNDRV_DEFAULT_ENABLE_PNP;
778 module_param_array(isapnp, bool, NULL, 0444);
779 MODULE_PARM_DESC(isapnp, "ISA PnP detection for specified soundcard.");
780 #define has_isapnp(x) isapnp[x]
781 #else
782 #define has_isapnp(x) 0
783 #endif
784 
785 MODULE_AUTHOR("Karsten Wiese <annabellesgarden@yahoo.de>");
786 MODULE_DESCRIPTION("Turtle Beach " LONGNAME " Linux Driver");
787 MODULE_LICENSE("GPL");
788 MODULE_FIRMWARE(INITCODEFILE);
789 MODULE_FIRMWARE(PERMCODEFILE);
790 
791 module_param_hw_array(io, long, ioport, NULL, 0444);
792 MODULE_PARM_DESC(io, "IO port #");
793 module_param_hw_array(irq, int, irq, NULL, 0444);
794 module_param_hw_array(mem, long, iomem, NULL, 0444);
795 module_param_array(write_ndelay, int, NULL, 0444);
796 module_param(calibrate_signal, int, 0444);
797 #ifndef MSND_CLASSIC
798 module_param_array(digital, int, NULL, 0444);
799 module_param_hw_array(cfg, long, ioport, NULL, 0444);
800 module_param_array(reset, int, NULL, 0444);
801 module_param_hw_array(mpu_io, long, ioport, NULL, 0444);
802 module_param_hw_array(mpu_irq, int, irq, NULL, 0444);
803 module_param_hw_array(ide_io0, long, ioport, NULL, 0444);
804 module_param_hw_array(ide_io1, long, ioport, NULL, 0444);
805 module_param_hw_array(ide_irq, int, irq, NULL, 0444);
806 module_param_hw_array(joystick_io, long, ioport, NULL, 0444);
807 #endif
808 
809 
810 static int snd_msnd_isa_match(struct device *pdev, unsigned int i)
811 {
812         if (io[i] == SNDRV_AUTO_PORT)
813                 return 0;
814 
815         if (irq[i] == SNDRV_AUTO_PORT || mem[i] == SNDRV_AUTO_PORT) {
816                 printk(KERN_WARNING LOGNAME ": io, irq and mem must be set\n");
817                 return 0;
818         }
819 
820 #ifdef MSND_CLASSIC
821         if (!(io[i] == 0x290 ||
822               io[i] == 0x260 ||
823               io[i] == 0x250 ||
824               io[i] == 0x240 ||
825               io[i] == 0x230 ||
826               io[i] == 0x220 ||
827               io[i] == 0x210 ||
828               io[i] == 0x3e0)) {
829                 printk(KERN_ERR LOGNAME ": \"io\" - DSP I/O base must be set "
830                         " to 0x210, 0x220, 0x230, 0x240, 0x250, 0x260, 0x290, "
831                         "or 0x3E0\n");
832                 return 0;
833         }
834 #else
835         if (io[i] < 0x100 || io[i] > 0x3e0 || (io[i] % 0x10) != 0) {
836                 printk(KERN_ERR LOGNAME
837                         ": \"io\" - DSP I/O base must within the range 0x100 "
838                         "to 0x3E0 and must be evenly divisible by 0x10\n");
839                 return 0;
840         }
841 #endif /* MSND_CLASSIC */
842 
843         if (!(irq[i] == 5 ||
844               irq[i] == 7 ||
845               irq[i] == 9 ||
846               irq[i] == 10 ||
847               irq[i] == 11 ||
848               irq[i] == 12)) {
849                 printk(KERN_ERR LOGNAME
850                         ": \"irq\" - must be set to 5, 7, 9, 10, 11 or 12\n");
851                 return 0;
852         }
853 
854         if (!(mem[i] == 0xb0000 ||
855               mem[i] == 0xc8000 ||
856               mem[i] == 0xd0000 ||
857               mem[i] == 0xd8000 ||
858               mem[i] == 0xe0000 ||
859               mem[i] == 0xe8000)) {
860                 printk(KERN_ERR LOGNAME ": \"mem\" - must be set to "
861                        "0xb0000, 0xc8000, 0xd0000, 0xd8000, 0xe0000 or "
862                        "0xe8000\n");
863                 return 0;
864         }
865 
866 #ifndef MSND_CLASSIC
867         if (cfg[i] == SNDRV_AUTO_PORT) {
868                 printk(KERN_INFO LOGNAME ": Assuming PnP mode\n");
869         } else if (cfg[i] != 0x250 && cfg[i] != 0x260 && cfg[i] != 0x270) {
870                 printk(KERN_INFO LOGNAME
871                         ": Config port must be 0x250, 0x260 or 0x270 "
872                         "(or unspecified for PnP mode)\n");
873                 return 0;
874         }
875 #endif /* MSND_CLASSIC */
876 
877         return 1;
878 }
879 
880 static int snd_msnd_isa_probe(struct device *pdev, unsigned int idx)
881 {
882         int err;
883         struct snd_card *card;
884         struct snd_msnd *chip;
885 
886         if (has_isapnp(idx)
887 #ifndef MSND_CLASSIC
888             || cfg[idx] == SNDRV_AUTO_PORT
889 #endif
890             ) {
891                 printk(KERN_INFO LOGNAME ": Assuming PnP mode\n");
892                 return -ENODEV;
893         }
894 
895         err = snd_card_new(pdev, index[idx], id[idx], THIS_MODULE,
896                            sizeof(struct snd_msnd), &card);
897         if (err < 0)
898                 return err;
899 
900         chip = card->private_data;
901         chip->card = card;
902 
903 #ifdef MSND_CLASSIC
904         switch (irq[idx]) {
905         case 5:
906                 chip->irqid = HPIRQ_5; break;
907         case 7:
908                 chip->irqid = HPIRQ_7; break;
909         case 9:
910                 chip->irqid = HPIRQ_9; break;
911         case 10:
912                 chip->irqid = HPIRQ_10; break;
913         case 11:
914                 chip->irqid = HPIRQ_11; break;
915         case 12:
916                 chip->irqid = HPIRQ_12; break;
917         }
918 
919         switch (mem[idx]) {
920         case 0xb0000:
921                 chip->memid = HPMEM_B000; break;
922         case 0xc8000:
923                 chip->memid = HPMEM_C800; break;
924         case 0xd0000:
925                 chip->memid = HPMEM_D000; break;
926         case 0xd8000:
927                 chip->memid = HPMEM_D800; break;
928         case 0xe0000:
929                 chip->memid = HPMEM_E000; break;
930         case 0xe8000:
931                 chip->memid = HPMEM_E800; break;
932         }
933 #else
934         printk(KERN_INFO LOGNAME ": Non-PnP mode: configuring at port 0x%lx\n",
935                         cfg[idx]);
936 
937         if (!request_region(cfg[idx], 2, "Pinnacle/Fiji Config")) {
938                 printk(KERN_ERR LOGNAME ": Config port 0x%lx conflict\n",
939                            cfg[idx]);
940                 snd_card_free(card);
941                 return -EIO;
942         }
943         if (reset[idx])
944                 if (snd_msnd_pinnacle_cfg_reset(cfg[idx])) {
945                         err = -EIO;
946                         goto cfg_error;
947                 }
948 
949         /* DSP */
950         err = snd_msnd_write_cfg_logical(cfg[idx], 0,
951                                          io[idx], 0,
952                                          irq[idx], mem[idx]);
953 
954         if (err)
955                 goto cfg_error;
956 
957         /* The following are Pinnacle specific */
958 
959         /* MPU */
960         if (mpu_io[idx] != SNDRV_AUTO_PORT
961             && mpu_irq[idx] != SNDRV_AUTO_IRQ) {
962                 printk(KERN_INFO LOGNAME
963                        ": Configuring MPU to I/O 0x%lx IRQ %d\n",
964                        mpu_io[idx], mpu_irq[idx]);
965                 err = snd_msnd_write_cfg_logical(cfg[idx], 1,
966                                                  mpu_io[idx], 0,
967                                                  mpu_irq[idx], 0);
968 
969                 if (err)
970                         goto cfg_error;
971         }
972 
973         /* IDE */
974         if (ide_io0[idx] != SNDRV_AUTO_PORT
975             && ide_io1[idx] != SNDRV_AUTO_PORT
976             && ide_irq[idx] != SNDRV_AUTO_IRQ) {
977                 printk(KERN_INFO LOGNAME
978                        ": Configuring IDE to I/O 0x%lx, 0x%lx IRQ %d\n",
979                        ide_io0[idx], ide_io1[idx], ide_irq[idx]);
980                 err = snd_msnd_write_cfg_logical(cfg[idx], 2,
981                                                  ide_io0[idx], ide_io1[idx],
982                                                  ide_irq[idx], 0);
983 
984                 if (err)
985                         goto cfg_error;
986         }
987 
988         /* Joystick */
989         if (joystick_io[idx] != SNDRV_AUTO_PORT) {
990                 printk(KERN_INFO LOGNAME
991                        ": Configuring joystick to I/O 0x%lx\n",
992                        joystick_io[idx]);
993                 err = snd_msnd_write_cfg_logical(cfg[idx], 3,
994                                                  joystick_io[idx], 0,
995                                                  0, 0);
996 
997                 if (err)
998                         goto cfg_error;
999         }
1000         release_region(cfg[idx], 2);
1001 
1002 #endif /* MSND_CLASSIC */
1003 
1004         set_default_audio_parameters(chip);
1005 #ifdef MSND_CLASSIC
1006         chip->type = msndClassic;
1007 #else
1008         chip->type = msndPinnacle;
1009 #endif
1010         chip->io = io[idx];
1011         chip->irq = irq[idx];
1012         chip->base = mem[idx];
1013 
1014         chip->calibrate_signal = calibrate_signal ? 1 : 0;
1015         chip->recsrc = 0;
1016         chip->dspq_data_buff = DSPQ_DATA_BUFF;
1017         chip->dspq_buff_size = DSPQ_BUFF_SIZE;
1018         if (write_ndelay[idx])
1019                 clear_bit(F_DISABLE_WRITE_NDELAY, &chip->flags);
1020         else
1021                 set_bit(F_DISABLE_WRITE_NDELAY, &chip->flags);
1022 #ifndef MSND_CLASSIC
1023         if (digital[idx])
1024                 set_bit(F_HAVEDIGITAL, &chip->flags);
1025 #endif
1026         spin_lock_init(&chip->lock);
1027         err = snd_msnd_probe(card);
1028         if (err < 0) {
1029                 printk(KERN_ERR LOGNAME ": Probe failed\n");
1030                 snd_card_free(card);
1031                 return err;
1032         }
1033 
1034         err = snd_msnd_attach(card);
1035         if (err < 0) {
1036                 printk(KERN_ERR LOGNAME ": Attach failed\n");
1037                 snd_card_free(card);
1038                 return err;
1039         }
1040         dev_set_drvdata(pdev, card);
1041 
1042         return 0;
1043 
1044 #ifndef MSND_CLASSIC
1045 cfg_error:
1046         release_region(cfg[idx], 2);
1047         snd_card_free(card);
1048         return err;
1049 #endif
1050 }
1051 
1052 static void snd_msnd_isa_remove(struct device *pdev, unsigned int dev)
1053 {
1054         snd_msnd_unload(dev_get_drvdata(pdev));
1055 }
1056 
1057 static struct isa_driver snd_msnd_driver = {
1058         .match          = snd_msnd_isa_match,
1059         .probe          = snd_msnd_isa_probe,
1060         .remove         = snd_msnd_isa_remove,
1061         /* FIXME: suspend, resume */
1062         .driver         = {
1063                 .name   = DEV_NAME
1064         },
1065 };
1066 
1067 #ifdef CONFIG_PNP
1068 static int snd_msnd_pnp_detect(struct pnp_card_link *pcard,
1069                                const struct pnp_card_device_id *pid)
1070 {
1071         static int idx;
1072         struct pnp_dev *pnp_dev;
1073         struct pnp_dev *mpu_dev;
1074         struct snd_card *card;
1075         struct snd_msnd *chip;
1076         int ret;
1077 
1078         for ( ; idx < SNDRV_CARDS; idx++) {
1079                 if (has_isapnp(idx))
1080                         break;
1081         }
1082         if (idx >= SNDRV_CARDS)
1083                 return -ENODEV;
1084 
1085         /*
1086          * Check that we still have room for another sound card ...
1087          */
1088         pnp_dev = pnp_request_card_device(pcard, pid->devs[0].id, NULL);
1089         if (!pnp_dev)
1090                 return -ENODEV;
1091 
1092         mpu_dev = pnp_request_card_device(pcard, pid->devs[1].id, NULL);
1093         if (!mpu_dev)
1094                 return -ENODEV;
1095 
1096         if (!pnp_is_active(pnp_dev) && pnp_activate_dev(pnp_dev) < 0) {
1097                 printk(KERN_INFO "msnd_pinnacle: device is inactive\n");
1098                 return -EBUSY;
1099         }
1100 
1101         if (!pnp_is_active(mpu_dev) && pnp_activate_dev(mpu_dev) < 0) {
1102                 printk(KERN_INFO "msnd_pinnacle: MPU device is inactive\n");
1103                 return -EBUSY;
1104         }
1105 
1106         /*
1107          * Create a new ALSA sound card entry, in anticipation
1108          * of detecting our hardware ...
1109          */
1110         ret = snd_card_new(&pcard->card->dev,
1111                            index[idx], id[idx], THIS_MODULE,
1112                            sizeof(struct snd_msnd), &card);
1113         if (ret < 0)
1114                 return ret;
1115 
1116         chip = card->private_data;
1117         chip->card = card;
1118 
1119         /*
1120          * Read the correct parameters off the ISA PnP bus ...
1121          */
1122         io[idx] = pnp_port_start(pnp_dev, 0);
1123         irq[idx] = pnp_irq(pnp_dev, 0);
1124         mem[idx] = pnp_mem_start(pnp_dev, 0);
1125         mpu_io[idx] = pnp_port_start(mpu_dev, 0);
1126         mpu_irq[idx] = pnp_irq(mpu_dev, 0);
1127 
1128         set_default_audio_parameters(chip);
1129 #ifdef MSND_CLASSIC
1130         chip->type = msndClassic;
1131 #else
1132         chip->type = msndPinnacle;
1133 #endif
1134         chip->io = io[idx];
1135         chip->irq = irq[idx];
1136         chip->base = mem[idx];
1137 
1138         chip->calibrate_signal = calibrate_signal ? 1 : 0;
1139         chip->recsrc = 0;
1140         chip->dspq_data_buff = DSPQ_DATA_BUFF;
1141         chip->dspq_buff_size = DSPQ_BUFF_SIZE;
1142         if (write_ndelay[idx])
1143                 clear_bit(F_DISABLE_WRITE_NDELAY, &chip->flags);
1144         else
1145                 set_bit(F_DISABLE_WRITE_NDELAY, &chip->flags);
1146 #ifndef MSND_CLASSIC
1147         if (digital[idx])
1148                 set_bit(F_HAVEDIGITAL, &chip->flags);
1149 #endif
1150         spin_lock_init(&chip->lock);
1151         ret = snd_msnd_probe(card);
1152         if (ret < 0) {
1153                 printk(KERN_ERR LOGNAME ": Probe failed\n");
1154                 goto _release_card;
1155         }
1156 
1157         ret = snd_msnd_attach(card);
1158         if (ret < 0) {
1159                 printk(KERN_ERR LOGNAME ": Attach failed\n");
1160                 goto _release_card;
1161         }
1162 
1163         pnp_set_card_drvdata(pcard, card);
1164         ++idx;
1165         return 0;
1166 
1167 _release_card:
1168         snd_card_free(card);
1169         return ret;
1170 }
1171 
1172 static void snd_msnd_pnp_remove(struct pnp_card_link *pcard)
1173 {
1174         snd_msnd_unload(pnp_get_card_drvdata(pcard));
1175         pnp_set_card_drvdata(pcard, NULL);
1176 }
1177 
1178 static int isa_registered;
1179 static int pnp_registered;
1180 
1181 static const struct pnp_card_device_id msnd_pnpids[] = {
1182         /* Pinnacle PnP */
1183         { .id = "BVJ0440", .devs = { { "TBS0000" }, { "TBS0001" } } },
1184         { .id = "" }    /* end */
1185 };
1186 
1187 MODULE_DEVICE_TABLE(pnp_card, msnd_pnpids);
1188 
1189 static struct pnp_card_driver msnd_pnpc_driver = {
1190         .flags = PNP_DRIVER_RES_DO_NOT_CHANGE,
1191         .name = "msnd_pinnacle",
1192         .id_table = msnd_pnpids,
1193         .probe = snd_msnd_pnp_detect,
1194         .remove = snd_msnd_pnp_remove,
1195 };
1196 #endif /* CONFIG_PNP */
1197 
1198 static int __init snd_msnd_init(void)
1199 {
1200         int err;
1201 
1202         err = isa_register_driver(&snd_msnd_driver, SNDRV_CARDS);
1203 #ifdef CONFIG_PNP
1204         if (!err)
1205                 isa_registered = 1;
1206 
1207         err = pnp_register_card_driver(&msnd_pnpc_driver);
1208         if (!err)
1209                 pnp_registered = 1;
1210 
1211         if (isa_registered)
1212                 err = 0;
1213 #endif
1214         return err;
1215 }
1216 
1217 static void __exit snd_msnd_exit(void)
1218 {
1219 #ifdef CONFIG_PNP
1220         if (pnp_registered)
1221                 pnp_unregister_card_driver(&msnd_pnpc_driver);
1222         if (isa_registered)
1223 #endif
1224                 isa_unregister_driver(&snd_msnd_driver);
1225 }
1226 
1227 module_init(snd_msnd_init);
1228 module_exit(snd_msnd_exit);
1229 
1230 

~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

kernel.org | git.kernel.org | LWN.net | Project Home | Wiki (Japanese) | Wiki (English) | SVN repository | Mail admin

Linux® is a registered trademark of Linus Torvalds in the United States and other countries.
TOMOYO® is a registered trademark of NTT DATA CORPORATION.

osdn.jp