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