summaryrefslogtreecommitdiffstats
path: root/sound/pci/riptide/riptide.c
diff options
context:
space:
mode:
Diffstat (limited to 'sound/pci/riptide/riptide.c')
-rw-r--r--sound/pci/riptide/riptide.c357
1 files changed, 166 insertions, 191 deletions
diff --git a/sound/pci/riptide/riptide.c b/sound/pci/riptide/riptide.c
index 6f1034417a0..235a71e5ac8 100644
--- a/sound/pci/riptide/riptide.c
+++ b/sound/pci/riptide/riptide.c
@@ -507,41 +507,19 @@ static int riptide_reset(struct cmdif *cif, struct snd_riptide *chip);
*/
static struct pci_device_id snd_riptide_ids[] = {
- {
- .vendor = 0x127a,.device = 0x4310,
- .subvendor = PCI_ANY_ID,.subdevice = PCI_ANY_ID,
- },
- {
- .vendor = 0x127a,.device = 0x4320,
- .subvendor = PCI_ANY_ID,.subdevice = PCI_ANY_ID,
- },
- {
- .vendor = 0x127a,.device = 0x4330,
- .subvendor = PCI_ANY_ID,.subdevice = PCI_ANY_ID,
- },
- {
- .vendor = 0x127a,.device = 0x4340,
- .subvendor = PCI_ANY_ID,.subdevice = PCI_ANY_ID,
- },
+ { PCI_DEVICE(0x127a, 0x4310) },
+ { PCI_DEVICE(0x127a, 0x4320) },
+ { PCI_DEVICE(0x127a, 0x4330) },
+ { PCI_DEVICE(0x127a, 0x4340) },
{0,},
};
#ifdef SUPPORT_JOYSTICK
static struct pci_device_id snd_riptide_joystick_ids[] __devinitdata = {
- {
- .vendor = 0x127a,.device = 0x4312,
- .subvendor = PCI_ANY_ID,.subdevice = PCI_ANY_ID,
- },
- {
- .vendor = 0x127a,.device = 0x4322,
- .subvendor = PCI_ANY_ID,.subdevice = PCI_ANY_ID,
- },
- {.vendor = 0x127a,.device = 0x4332,
- .subvendor = PCI_ANY_ID,.subdevice = PCI_ANY_ID,
- },
- {.vendor = 0x127a,.device = 0x4342,
- .subvendor = PCI_ANY_ID,.subdevice = PCI_ANY_ID,
- },
+ { PCI_DEVICE(0x127a, 0x4312) },
+ { PCI_DEVICE(0x127a, 0x4322) },
+ { PCI_DEVICE(0x127a, 0x4332) },
+ { PCI_DEVICE(0x127a, 0x4342) },
{0,},
};
#endif
@@ -889,7 +867,7 @@ static int sendcmd(struct cmdif *cif, u32 flags, u32 cmd, u32 parm,
spin_lock_irqsave(&cif->lock, irqflags);
while (i++ < CMDIF_TIMEOUT && !IS_READY(cif->hwport))
udelay(10);
- if (i >= CMDIF_TIMEOUT) {
+ if (i > CMDIF_TIMEOUT) {
err = -EBUSY;
goto errout;
}
@@ -907,8 +885,10 @@ static int sendcmd(struct cmdif *cif, u32 flags, u32 cmd, u32 parm,
WRITE_PORT_ULONG(cmdport->data1, cmd); /* write cmd */
if ((flags & RESP) && ret) {
while (!IS_DATF(cmdport) &&
- time++ < CMDIF_TIMEOUT)
+ time < CMDIF_TIMEOUT) {
udelay(10);
+ time++;
+ }
if (time < CMDIF_TIMEOUT) { /* read response */
ret->retlongs[0] =
READ_PORT_ULONG(cmdport->data1);
@@ -1207,12 +1187,79 @@ static int riptide_resume(struct pci_dev *pci)
}
#endif
+static int try_to_load_firmware(struct cmdif *cif, struct snd_riptide *chip)
+{
+ union firmware_version firmware = { .ret = CMDRET_ZERO };
+ int i, timeout, err;
+
+ for (i = 0; i < 2; i++) {
+ WRITE_PORT_ULONG(cif->hwport->port[i].data1, 0);
+ WRITE_PORT_ULONG(cif->hwport->port[i].data2, 0);
+ }
+ SET_GRESET(cif->hwport);
+ udelay(100);
+ UNSET_GRESET(cif->hwport);
+ udelay(100);
+
+ for (timeout = 100000; --timeout; udelay(10)) {
+ if (IS_READY(cif->hwport) && !IS_GERR(cif->hwport))
+ break;
+ }
+ if (!timeout) {
+ snd_printk(KERN_ERR
+ "Riptide: device not ready, audio status: 0x%x "
+ "ready: %d gerr: %d\n",
+ READ_AUDIO_STATUS(cif->hwport),
+ IS_READY(cif->hwport), IS_GERR(cif->hwport));
+ return -EIO;
+ } else {
+ snd_printdd
+ ("Riptide: audio status: 0x%x ready: %d gerr: %d\n",
+ READ_AUDIO_STATUS(cif->hwport),
+ IS_READY(cif->hwport), IS_GERR(cif->hwport));
+ }
+
+ SEND_GETV(cif, &firmware.ret);
+ snd_printdd("Firmware version: ASIC: %d CODEC %d AUXDSP %d PROG %d\n",
+ firmware.firmware.ASIC, firmware.firmware.CODEC,
+ firmware.firmware.AUXDSP, firmware.firmware.PROG);
+
+ for (i = 0; i < FIRMWARE_VERSIONS; i++) {
+ if (!memcmp(&firmware_versions[i], &firmware, sizeof(firmware)))
+ break;
+ }
+ if (i >= FIRMWARE_VERSIONS)
+ return 0; /* no match */
+
+ if (!chip)
+ return 1; /* OK */
+
+ snd_printdd("Writing Firmware\n");
+ if (!chip->fw_entry) {
+ err = request_firmware(&chip->fw_entry, "riptide.hex",
+ &chip->pci->dev);
+ if (err) {
+ snd_printk(KERN_ERR
+ "Riptide: Firmware not available %d\n", err);
+ return -EIO;
+ }
+ }
+ err = loadfirmware(cif, chip->fw_entry->data, chip->fw_entry->size);
+ if (err) {
+ snd_printk(KERN_ERR
+ "Riptide: Could not load firmware %d\n", err);
+ return err;
+ }
+
+ chip->firmware = firmware;
+
+ return 1; /* OK */
+}
+
static int riptide_reset(struct cmdif *cif, struct snd_riptide *chip)
{
- int timeout, tries;
union cmdret rptr = CMDRET_ZERO;
- union firmware_version firmware;
- int i, j, err, has_firmware;
+ int err, tries;
if (!cif)
return -EINVAL;
@@ -1225,75 +1272,11 @@ static int riptide_reset(struct cmdif *cif, struct snd_riptide *chip)
cif->is_reset = 0;
tries = RESET_TRIES;
- has_firmware = 0;
- while (has_firmware == 0 && tries-- > 0) {
- for (i = 0; i < 2; i++) {
- WRITE_PORT_ULONG(cif->hwport->port[i].data1, 0);
- WRITE_PORT_ULONG(cif->hwport->port[i].data2, 0);
- }
- SET_GRESET(cif->hwport);
- udelay(100);
- UNSET_GRESET(cif->hwport);
- udelay(100);
-
- for (timeout = 100000; --timeout; udelay(10)) {
- if (IS_READY(cif->hwport) && !IS_GERR(cif->hwport))
- break;
- }
- if (timeout == 0) {
- snd_printk(KERN_ERR
- "Riptide: device not ready, audio status: 0x%x ready: %d gerr: %d\n",
- READ_AUDIO_STATUS(cif->hwport),
- IS_READY(cif->hwport), IS_GERR(cif->hwport));
- return -EIO;
- } else {
- snd_printdd
- ("Riptide: audio status: 0x%x ready: %d gerr: %d\n",
- READ_AUDIO_STATUS(cif->hwport),
- IS_READY(cif->hwport), IS_GERR(cif->hwport));
- }
-
- SEND_GETV(cif, &rptr);
- for (i = 0; i < 4; i++)
- firmware.ret.retwords[i] = rptr.retwords[i];
-
- snd_printdd
- ("Firmware version: ASIC: %d CODEC %d AUXDSP %d PROG %d\n",
- firmware.firmware.ASIC, firmware.firmware.CODEC,
- firmware.firmware.AUXDSP, firmware.firmware.PROG);
-
- for (j = 0; j < FIRMWARE_VERSIONS; j++) {
- has_firmware = 1;
- for (i = 0; i < 4; i++) {
- if (firmware_versions[j].ret.retwords[i] !=
- firmware.ret.retwords[i])
- has_firmware = 0;
- }
- if (has_firmware)
- break;
- }
-
- if (chip != NULL && has_firmware == 0) {
- snd_printdd("Writing Firmware\n");
- if (!chip->fw_entry) {
- if ((err =
- request_firmware(&chip->fw_entry,
- "riptide.hex",
- &chip->pci->dev)) != 0) {
- snd_printk(KERN_ERR
- "Riptide: Firmware not available %d\n",
- err);
- return -EIO;
- }
- }
- err = loadfirmware(cif, chip->fw_entry->data,
- chip->fw_entry->size);
- if (err)
- snd_printk(KERN_ERR
- "Riptide: Could not load firmware %d\n",
- err);
- }
- }
+ do {
+ err = try_to_load_firmware(cif, chip);
+ if (err < 0)
+ return err;
+ } while (!err && --tries);
SEND_SACR(cif, 0, AC97_RESET);
SEND_RACR(cif, AC97_RESET, &rptr);
@@ -1335,11 +1318,6 @@ static int riptide_reset(struct cmdif *cif, struct snd_riptide *chip)
SET_AIE(cif->hwport);
SET_AIACK(cif->hwport);
cif->is_reset = 1;
- if (chip) {
- for (i = 0; i < 4; i++)
- chip->firmware.ret.retwords[i] =
- firmware.ret.retwords[i];
- }
return 0;
}
@@ -1454,7 +1432,7 @@ static int snd_riptide_trigger(struct snd_pcm_substream *substream, int cmd)
SEND_GPOS(cif, 0, data->id, &rptr);
udelay(1);
} while (i != rptr.retlongs[1] && j++ < MAX_WRITE_RETRY);
- if (j >= MAX_WRITE_RETRY)
+ if (j > MAX_WRITE_RETRY)
snd_printk(KERN_ERR "Riptide: Could not stop stream!");
break;
case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
@@ -1783,7 +1761,7 @@ snd_riptide_codec_write(struct snd_ac97 *ac97, unsigned short reg,
SEND_SACR(cif, val, reg);
SEND_RACR(cif, reg, &rptr);
} while (rptr.retwords[1] != val && i++ < MAX_WRITE_RETRY);
- if (i == MAX_WRITE_RETRY)
+ if (i > MAX_WRITE_RETRY)
snd_printdd("Write AC97 reg failed\n");
}
@@ -2036,14 +2014,12 @@ static int __devinit snd_riptide_mixer(struct snd_riptide *chip)
}
#ifdef SUPPORT_JOYSTICK
-static int have_joystick;
-static struct pci_dev *riptide_gameport_pci;
-static struct gameport *riptide_gameport;
static int __devinit
snd_riptide_joystick_probe(struct pci_dev *pci, const struct pci_device_id *id)
{
static int dev;
+ struct gameport *gameport;
if (dev >= SNDRV_CARDS)
return -ENODEV;
@@ -2052,36 +2028,33 @@ snd_riptide_joystick_probe(struct pci_dev *pci, const struct pci_device_id *id)
return -ENOENT;
}
- if (joystick_port[dev]) {
- riptide_gameport = gameport_allocate_port();
- if (riptide_gameport) {
- if (!request_region
- (joystick_port[dev], 8, "Riptide gameport")) {
- snd_printk(KERN_WARNING
- "Riptide: cannot grab gameport 0x%x\n",
- joystick_port[dev]);
- gameport_free_port(riptide_gameport);
- riptide_gameport = NULL;
- } else {
- riptide_gameport_pci = pci;
- riptide_gameport->io = joystick_port[dev];
- gameport_register_port(riptide_gameport);
- }
- }
+ if (!joystick_port[dev++])
+ return 0;
+
+ gameport = gameport_allocate_port();
+ if (!gameport)
+ return -ENOMEM;
+ if (!request_region(joystick_port[dev], 8, "Riptide gameport")) {
+ snd_printk(KERN_WARNING
+ "Riptide: cannot grab gameport 0x%x\n",
+ joystick_port[dev]);
+ gameport_free_port(gameport);
+ return -EBUSY;
}
- dev++;
+
+ gameport->io = joystick_port[dev];
+ gameport_register_port(gameport);
+ pci_set_drvdata(pci, gameport);
return 0;
}
static void __devexit snd_riptide_joystick_remove(struct pci_dev *pci)
{
- if (riptide_gameport) {
- if (riptide_gameport_pci == pci) {
- release_region(riptide_gameport->io, 8);
- riptide_gameport_pci = NULL;
- gameport_unregister_port(riptide_gameport);
- riptide_gameport = NULL;
- }
+ struct gameport *gameport = pci_get_drvdata(pci);
+ if (gameport) {
+ release_region(gameport->io, 8);
+ gameport_unregister_port(gameport);
+ pci_set_drvdata(pci, NULL);
}
}
#endif
@@ -2092,8 +2065,8 @@ snd_card_riptide_probe(struct pci_dev *pci, const struct pci_device_id *pci_id)
static int dev;
struct snd_card *card;
struct snd_riptide *chip;
- unsigned short addr;
- int err = 0;
+ unsigned short val;
+ int err;
if (dev >= SNDRV_CARDS)
return -ENODEV;
@@ -2105,60 +2078,63 @@ snd_card_riptide_probe(struct pci_dev *pci, const struct pci_device_id *pci_id)
err = snd_card_create(index[dev], id[dev], THIS_MODULE, 0, &card);
if (err < 0)
return err;
- if ((err = snd_riptide_create(card, pci, &chip)) < 0) {
- snd_card_free(card);
- return err;
- }
+ err = snd_riptide_create(card, pci, &chip);
+ if (err < 0)
+ goto error;
card->private_data = chip;
- if ((err = snd_riptide_pcm(chip, 0, NULL)) < 0) {
- snd_card_free(card);
- return err;
- }
- if ((err = snd_riptide_mixer(chip)) < 0) {
- snd_card_free(card);
- return err;
- }
- pci_write_config_word(chip->pci, PCI_EXT_Legacy_Mask, LEGACY_ENABLE_ALL
- | (opl3_port[dev] ? LEGACY_ENABLE_FM : 0)
+ err = snd_riptide_pcm(chip, 0, NULL);
+ if (err < 0)
+ goto error;
+ err = snd_riptide_mixer(chip);
+ if (err < 0)
+ goto error;
+
+ val = LEGACY_ENABLE_ALL;
+ if (opl3_port[dev])
+ val |= LEGACY_ENABLE_FM;
#ifdef SUPPORT_JOYSTICK
- | (joystick_port[dev] ? LEGACY_ENABLE_GAMEPORT :
- 0)
+ if (joystick_port[dev])
+ val |= LEGACY_ENABLE_GAMEPORT;
#endif
- | (mpu_port[dev]
- ? (LEGACY_ENABLE_MPU_INT | LEGACY_ENABLE_MPU) :
- 0)
- | ((chip->irq << 4) & 0xF0));
- if ((addr = mpu_port[dev]) != 0) {
- pci_write_config_word(chip->pci, PCI_EXT_MPU_Base, addr);
- if ((err = snd_mpu401_uart_new(card, 0, MPU401_HW_RIPTIDE,
- addr, 0, chip->irq, 0,
- &chip->rmidi)) < 0)
+ if (mpu_port[dev])
+ val |= LEGACY_ENABLE_MPU_INT | LEGACY_ENABLE_MPU;
+ val |= (chip->irq << 4) & 0xf0;
+ pci_write_config_word(chip->pci, PCI_EXT_Legacy_Mask, val);
+ if (mpu_port[dev]) {
+ val = mpu_port[dev];
+ pci_write_config_word(chip->pci, PCI_EXT_MPU_Base, val);
+ err = snd_mpu401_uart_new(card, 0, MPU401_HW_RIPTIDE,
+ val, 0, chip->irq, 0,
+ &chip->rmidi);
+ if (err < 0)
snd_printk(KERN_WARNING
"Riptide: Can't Allocate MPU at 0x%x\n",
- addr);
+ val);
else
- chip->mpuaddr = addr;
+ chip->mpuaddr = val;
}
- if ((addr = opl3_port[dev]) != 0) {
- pci_write_config_word(chip->pci, PCI_EXT_FM_Base, addr);
- if ((err = snd_opl3_create(card, addr, addr + 2,
- OPL3_HW_RIPTIDE, 0,
- &chip->opl3)) < 0)
+ if (opl3_port[dev]) {
+ val = opl3_port[dev];
+ pci_write_config_word(chip->pci, PCI_EXT_FM_Base, val);
+ err = snd_opl3_create(card, val, val + 2,
+ OPL3_HW_RIPTIDE, 0, &chip->opl3);
+ if (err < 0)
snd_printk(KERN_WARNING
"Riptide: Can't Allocate OPL3 at 0x%x\n",
- addr);
+ val);
else {
- chip->opladdr = addr;
- if ((err =
- snd_opl3_hwdep_new(chip->opl3, 0, 1, NULL)) < 0)
+ chip->opladdr = val;
+ err = snd_opl3_hwdep_new(chip->opl3, 0, 1, NULL);
+ if (err < 0)
snd_printk(KERN_WARNING
"Riptide: Can't Allocate OPL3-HWDEP\n");
}
}
#ifdef SUPPORT_JOYSTICK
- if ((addr = joystick_port[dev]) != 0) {
- pci_write_config_word(chip->pci, PCI_EXT_Game_Base, addr);
- chip->gameaddr = addr;
+ if (joystick_port[dev]) {
+ val = joystick_port[dev];
+ pci_write_config_word(chip->pci, PCI_EXT_Game_Base, val);
+ chip->gameaddr = val;
}
#endif
@@ -2176,13 +2152,16 @@ snd_card_riptide_probe(struct pci_dev *pci, const struct pci_device_id *pci_id)
chip->opladdr);
#endif
snd_riptide_proc_init(chip);
- if ((err = snd_card_register(card)) < 0) {
- snd_card_free(card);
- return err;
- }
+ err = snd_card_register(card);
+ if (err < 0)
+ goto error;
pci_set_drvdata(pci, card);
dev++;
return 0;
+
+ error:
+ snd_card_free(card);
+ return err;
}
static void __devexit snd_card_riptide_remove(struct pci_dev *pci)
@@ -2214,14 +2193,11 @@ static struct pci_driver joystick_driver = {
static int __init alsa_card_riptide_init(void)
{
int err;
- if ((err = pci_register_driver(&driver)) < 0)
+ err = pci_register_driver(&driver);
+ if (err < 0)
return err;
#if defined(SUPPORT_JOYSTICK)
- if (pci_register_driver(&joystick_driver) < 0) {
- have_joystick = 0;
- snd_printk(KERN_INFO "no joystick found\n");
- } else
- have_joystick = 1;
+ pci_register_driver(&joystick_driver);
#endif
return 0;
}
@@ -2230,8 +2206,7 @@ static void __exit alsa_card_riptide_exit(void)
{
pci_unregister_driver(&driver);
#if defined(SUPPORT_JOYSTICK)
- if (have_joystick)
- pci_unregister_driver(&joystick_driver);
+ pci_unregister_driver(&joystick_driver);
#endif
}