aboutsummaryrefslogtreecommitdiff
path: root/sound/isa
diff options
context:
space:
mode:
authorTakashi Iwai <tiwai@suse.de>2009-12-04 16:22:32 +0100
committerTakashi Iwai <tiwai@suse.de>2009-12-04 16:22:32 +0100
commit79598324838a25cc378ecbb8c29dd1e3d3951d35 (patch)
tree7d29e81580cba854042df4e33bdc8f38bbd65d03 /sound/isa
parent8ee763b9c82c6ca0a59a7271ce4fa29d7baf5c09 (diff)
parentb00615d163cd24fa98d155acfc1f9d81d6fe1103 (diff)
Merge branch 'topic/core-change' into for-linus
Diffstat (limited to 'sound/isa')
-rw-r--r--sound/isa/Kconfig12
-rw-r--r--sound/isa/cmi8330.c4
-rw-r--r--sound/isa/es1688/es1688_lib.c2
-rw-r--r--sound/isa/es18xx.c132
-rw-r--r--sound/isa/sb/sb_mixer.c4
-rw-r--r--sound/isa/sscape.c727
-rw-r--r--sound/isa/wss/wss_lib.c98
7 files changed, 432 insertions, 547 deletions
diff --git a/sound/isa/Kconfig b/sound/isa/Kconfig
index 51a7e3777e1..02fe81ca88f 100644
--- a/sound/isa/Kconfig
+++ b/sound/isa/Kconfig
@@ -372,15 +372,21 @@ config SND_SGALAXY
config SND_SSCAPE
tristate "Ensoniq SoundScape driver"
- select SND_HWDEP
select SND_MPU401_UART
select SND_WSS_LIB
+ select FW_LOADER
help
Say Y here to include support for Ensoniq SoundScape
- soundcards.
+ and Ensoniq OEM soundcards.
The PCM audio is supported on SoundScape Classic, Elite, PnP
- and VIVO cards. The MIDI support is very experimental.
+ and VIVO cards. The supported OEM cards are SPEA Media FX and
+ Reveal SC-600.
+ The MIDI support is very experimental and requires binary
+ firmware files called "scope.cod" and "sndscape.co?" where the
+ ? is digit 0, 1, 2, 3 or 4. The firmware files can be found
+ in DOS or Windows driver packages. One has to put the firmware
+ files into the /lib/firmware directory.
To compile this driver as a module, choose M here: the module
will be called snd-sscape.
diff --git a/sound/isa/cmi8330.c b/sound/isa/cmi8330.c
index 02f79d25271..8246aae32ab 100644
--- a/sound/isa/cmi8330.c
+++ b/sound/isa/cmi8330.c
@@ -237,7 +237,7 @@ WSS_DOUBLE("Wavetable Capture Volume", 0,
CMI8330_WAVGAIN, CMI8330_WAVGAIN, 4, 0, 15, 0),
WSS_SINGLE("3D Control - Switch", 0,
CMI8330_RMUX3D, 5, 1, 1),
-WSS_SINGLE("PC Speaker Playback Volume", 0,
+WSS_SINGLE("Beep Playback Volume", 0,
CMI8330_OUTPUTVOL, 3, 3, 0),
WSS_DOUBLE("FM Playback Switch", 0,
CS4231_AUX2_LEFT_INPUT, CS4231_AUX2_RIGHT_INPUT, 7, 7, 1, 1),
@@ -262,7 +262,7 @@ SB_DOUBLE("SB Line Playback Switch", SB_DSP4_OUTPUT_SW, SB_DSP4_OUTPUT_SW, 4, 3,
SB_DOUBLE("SB Line Playback Volume", SB_DSP4_LINE_DEV, (SB_DSP4_LINE_DEV + 1), 3, 3, 31),
SB_SINGLE("SB Mic Playback Switch", SB_DSP4_OUTPUT_SW, 0, 1),
SB_SINGLE("SB Mic Playback Volume", SB_DSP4_MIC_DEV, 3, 31),
-SB_SINGLE("SB PC Speaker Volume", SB_DSP4_SPEAKER_DEV, 6, 3),
+SB_SINGLE("SB Beep Volume", SB_DSP4_SPEAKER_DEV, 6, 3),
SB_DOUBLE("SB Capture Volume", SB_DSP4_IGAIN_DEV, (SB_DSP4_IGAIN_DEV + 1), 6, 6, 3),
SB_DOUBLE("SB Playback Volume", SB_DSP4_OGAIN_DEV, (SB_DSP4_OGAIN_DEV + 1), 6, 6, 3),
SB_SINGLE("SB Mic Auto Gain", SB_DSP4_MIC_AGC, 0, 1),
diff --git a/sound/isa/es1688/es1688_lib.c b/sound/isa/es1688/es1688_lib.c
index 4c6e14f87f2..c76bb00c9d1 100644
--- a/sound/isa/es1688/es1688_lib.c
+++ b/sound/isa/es1688/es1688_lib.c
@@ -982,7 +982,7 @@ ES1688_DOUBLE("CD Playback Volume", 0, ES1688_CD_DEV, ES1688_CD_DEV, 4, 0, 15, 0
ES1688_DOUBLE("FM Playback Volume", 0, ES1688_FM_DEV, ES1688_FM_DEV, 4, 0, 15, 0),
ES1688_DOUBLE("Mic Playback Volume", 0, ES1688_MIC_DEV, ES1688_MIC_DEV, 4, 0, 15, 0),
ES1688_DOUBLE("Aux Playback Volume", 0, ES1688_AUX_DEV, ES1688_AUX_DEV, 4, 0, 15, 0),
-ES1688_SINGLE("PC Speaker Playback Volume", 0, ES1688_SPEAKER_DEV, 0, 7, 0),
+ES1688_SINGLE("Beep Playback Volume", 0, ES1688_SPEAKER_DEV, 0, 7, 0),
ES1688_DOUBLE("Capture Volume", 0, ES1688_RECLEV_DEV, ES1688_RECLEV_DEV, 4, 0, 15, 0),
ES1688_SINGLE("Capture Switch", 0, ES1688_REC_DEV, 4, 1, 1),
{
diff --git a/sound/isa/es18xx.c b/sound/isa/es18xx.c
index 8cfbff73a83..e5bf3355d2c 100644
--- a/sound/isa/es18xx.c
+++ b/sound/isa/es18xx.c
@@ -121,7 +121,6 @@ struct snd_es18xx {
unsigned int dma1_shift;
unsigned int dma2_shift;
- struct snd_card *card;
struct snd_pcm *pcm;
struct snd_pcm_substream *playback_a_substream;
struct snd_pcm_substream *capture_a_substream;
@@ -140,10 +139,6 @@ struct snd_es18xx {
#ifdef CONFIG_PM
unsigned char pm_reg;
#endif
-};
-
-struct snd_audiodrive {
- struct snd_es18xx *chip;
#ifdef CONFIG_PNP
struct pnp_dev *dev;
struct pnp_dev *devc;
@@ -755,7 +750,8 @@ static int snd_es18xx_playback_trigger(struct snd_pcm_substream *substream,
static irqreturn_t snd_es18xx_interrupt(int irq, void *dev_id)
{
- struct snd_es18xx *chip = dev_id;
+ struct snd_card *card = dev_id;
+ struct snd_es18xx *chip = card->private_data;
unsigned char status;
if (chip->caps & ES18XX_CONTROL) {
@@ -805,12 +801,16 @@ static irqreturn_t snd_es18xx_interrupt(int irq, void *dev_id)
int split = 0;
if (chip->caps & ES18XX_HWV) {
split = snd_es18xx_mixer_read(chip, 0x64) & 0x80;
- snd_ctl_notify(chip->card, SNDRV_CTL_EVENT_MASK_VALUE, &chip->hw_switch->id);
- snd_ctl_notify(chip->card, SNDRV_CTL_EVENT_MASK_VALUE, &chip->hw_volume->id);
+ snd_ctl_notify(card, SNDRV_CTL_EVENT_MASK_VALUE,
+ &chip->hw_switch->id);
+ snd_ctl_notify(card, SNDRV_CTL_EVENT_MASK_VALUE,
+ &chip->hw_volume->id);
}
if (!split) {
- snd_ctl_notify(chip->card, SNDRV_CTL_EVENT_MASK_VALUE, &chip->master_switch->id);
- snd_ctl_notify(chip->card, SNDRV_CTL_EVENT_MASK_VALUE, &chip->master_volume->id);
+ snd_ctl_notify(card, SNDRV_CTL_EVENT_MASK_VALUE,
+ &chip->master_switch->id);
+ snd_ctl_notify(card, SNDRV_CTL_EVENT_MASK_VALUE,
+ &chip->master_volume->id);
}
/* ack interrupt */
snd_es18xx_mixer_write(chip, 0x66, 0x00);
@@ -1313,7 +1313,7 @@ ES18XX_DOUBLE("Aux Capture Volume", 0, 0x6c, 0x6c, 4, 0, 15, 0)
* The chipset specific mixer controls
*/
static struct snd_kcontrol_new snd_es18xx_opt_speaker =
- ES18XX_SINGLE("PC Speaker Playback Volume", 0, 0x3c, 0, 7, 0);
+ ES18XX_SINGLE("Beep Playback Volume", 0, 0x3c, 0, 7, 0);
static struct snd_kcontrol_new snd_es18xx_opt_1869[] = {
ES18XX_SINGLE("Capture Switch", 0, 0x1c, 4, 1, 1),
@@ -1691,8 +1691,10 @@ static struct snd_pcm_ops snd_es18xx_capture_ops = {
.pointer = snd_es18xx_capture_pointer,
};
-static int __devinit snd_es18xx_pcm(struct snd_es18xx *chip, int device, struct snd_pcm ** rpcm)
+static int __devinit snd_es18xx_pcm(struct snd_card *card, int device,
+ struct snd_pcm **rpcm)
{
+ struct snd_es18xx *chip = card->private_data;
struct snd_pcm *pcm;
char str[16];
int err;
@@ -1701,9 +1703,9 @@ static int __devinit snd_es18xx_pcm(struct snd_es18xx *chip, int device, struct
*rpcm = NULL;
sprintf(str, "ES%x", chip->version);
if (chip->caps & ES18XX_PCM2)
- err = snd_pcm_new(chip->card, str, device, 2, 1, &pcm);
+ err = snd_pcm_new(card, str, device, 2, 1, &pcm);
else
- err = snd_pcm_new(chip->card, str, device, 1, 1, &pcm);
+ err = snd_pcm_new(card, str, device, 1, 1, &pcm);
if (err < 0)
return err;
@@ -1734,10 +1736,9 @@ static int __devinit snd_es18xx_pcm(struct snd_es18xx *chip, int device, struct
#ifdef CONFIG_PM
static int snd_es18xx_suspend(struct snd_card *card, pm_message_t state)
{
- struct snd_audiodrive *acard = card->private_data;
- struct snd_es18xx *chip = acard->chip;
+ struct snd_es18xx *chip = card->private_data;
- snd_power_change_state(chip->card, SNDRV_CTL_POWER_D3hot);
+ snd_power_change_state(card, SNDRV_CTL_POWER_D3hot);
snd_pcm_suspend_all(chip->pcm);
@@ -1752,24 +1753,25 @@ static int snd_es18xx_suspend(struct snd_card *card, pm_message_t state)
static int snd_es18xx_resume(struct snd_card *card)
{
- struct snd_audiodrive *acard = card->private_data;
- struct snd_es18xx *chip = acard->chip;
+ struct snd_es18xx *chip = card->private_data;
/* restore PM register, we won't wake till (not 0x07) i/o activity though */
snd_es18xx_write(chip, ES18XX_PM, chip->pm_reg ^= ES18XX_PM_FM);
- snd_power_change_state(chip->card, SNDRV_CTL_POWER_D0);
+ snd_power_change_state(card, SNDRV_CTL_POWER_D0);
return 0;
}
#endif /* CONFIG_PM */
-static int snd_es18xx_free(struct snd_es18xx *chip)
+static int snd_es18xx_free(struct snd_card *card)
{
+ struct snd_es18xx *chip = card->private_data;
+
release_and_free_resource(chip->res_port);
release_and_free_resource(chip->res_ctrl_port);
release_and_free_resource(chip->res_mpu_port);
if (chip->irq >= 0)
- free_irq(chip->irq, (void *) chip);
+ free_irq(chip->irq, (void *) card);
if (chip->dma1 >= 0) {
disable_dma(chip->dma1);
free_dma(chip->dma1);
@@ -1778,37 +1780,29 @@ static int snd_es18xx_free(struct snd_es18xx *chip)
disable_dma(chip->dma2);
free_dma(chip->dma2);
}
- kfree(chip);
return 0;
}
static int snd_es18xx_dev_free(struct snd_device *device)
{
- struct snd_es18xx *chip = device->device_data;
- return snd_es18xx_free(chip);
+ return snd_es18xx_free(device->card);
}
static int __devinit snd_es18xx_new_device(struct snd_card *card,
unsigned long port,
unsigned long mpu_port,
unsigned long fm_port,
- int irq, int dma1, int dma2,
- struct snd_es18xx ** rchip)
+ int irq, int dma1, int dma2)
{
- struct snd_es18xx *chip;
+ struct snd_es18xx *chip = card->private_data;
static struct snd_device_ops ops = {
.dev_free = snd_es18xx_dev_free,
};
int err;
- *rchip = NULL;
- chip = kzalloc(sizeof(*chip), GFP_KERNEL);
- if (chip == NULL)
- return -ENOMEM;
spin_lock_init(&chip->reg_lock);
spin_lock_init(&chip->mixer_lock);
spin_lock_init(&chip->ctrl_lock);
- chip->card = card;
chip->port = port;
chip->mpu_port = mpu_port;
chip->fm_port = fm_port;
@@ -1818,53 +1812,53 @@ static int __devinit snd_es18xx_new_device(struct snd_card *card,
chip->audio2_vol = 0x00;
chip->active = 0;
- if ((chip->res_port = request_region(port, 16, "ES18xx")) == NULL) {
- snd_es18xx_free(chip);
+ chip->res_port = request_region(port, 16, "ES18xx");
+ if (chip->res_port == NULL) {
+ snd_es18xx_free(card);
snd_printk(KERN_ERR PFX "unable to grap ports 0x%lx-0x%lx\n", port, port + 16 - 1);
return -EBUSY;
}
- if (request_irq(irq, snd_es18xx_interrupt, IRQF_DISABLED, "ES18xx", (void *) chip)) {
- snd_es18xx_free(chip);
+ if (request_irq(irq, snd_es18xx_interrupt, IRQF_DISABLED, "ES18xx",
+ (void *) card)) {
+ snd_es18xx_free(card);
snd_printk(KERN_ERR PFX "unable to grap IRQ %d\n", irq);
return -EBUSY;
}
chip->irq = irq;
if (request_dma(dma1, "ES18xx DMA 1")) {
- snd_es18xx_free(chip);
+ snd_es18xx_free(card);
snd_printk(KERN_ERR PFX "unable to grap DMA1 %d\n", dma1);
return -EBUSY;
}
chip->dma1 = dma1;
if (dma2 != dma1 && request_dma(dma2, "ES18xx DMA 2")) {
- snd_es18xx_free(chip);
+ snd_es18xx_free(card);
snd_printk(KERN_ERR PFX "unable to grap DMA2 %d\n", dma2);
return -EBUSY;
}
chip->dma2 = dma2;
if (snd_es18xx_probe(chip) < 0) {
- snd_es18xx_free(chip);
+ snd_es18xx_free(card);
return -ENODEV;
}
- if ((err = snd_device_new(card, SNDRV_DEV_LOWLEVEL, chip, &ops)) < 0) {
- snd_es18xx_free(chip);
+ err = snd_device_new(card, SNDRV_DEV_LOWLEVEL, NULL, &ops);
+ if (err < 0) {
+ snd_es18xx_free(card);
return err;
}
- *rchip = chip;
return 0;
}
-static int __devinit snd_es18xx_mixer(struct snd_es18xx *chip)
+static int __devinit snd_es18xx_mixer(struct snd_card *card)
{
- struct snd_card *card;
+ struct snd_es18xx *chip = card->private_data;
int err;
unsigned int idx;
- card = chip->card;
-
strcpy(card->mixername, chip->pcm->name);
for (idx = 0; idx < ARRAY_SIZE(snd_es18xx_base_controls); idx++) {
@@ -2063,11 +2057,11 @@ static int __devinit snd_audiodrive_pnp_init_main(int dev, struct pnp_dev *pdev)
return 0;
}
-static int __devinit snd_audiodrive_pnp(int dev, struct snd_audiodrive *acard,
+static int __devinit snd_audiodrive_pnp(int dev, struct snd_es18xx *chip,
struct pnp_dev *pdev)
{
- acard->dev = pdev;
- if (snd_audiodrive_pnp_init_main(dev, acard->dev) < 0)
+ chip->dev = pdev;
+ if (snd_audiodrive_pnp_init_main(dev, chip->dev) < 0)
return -EBUSY;
return 0;
}
@@ -2093,26 +2087,26 @@ static struct pnp_card_device_id snd_audiodrive_pnpids[] = {
MODULE_DEVICE_TABLE(pnp_card, snd_audiodrive_pnpids);
-static int __devinit snd_audiodrive_pnpc(int dev, struct snd_audiodrive *acard,
+static int __devinit snd_audiodrive_pnpc(int dev, struct snd_es18xx *chip,
struct pnp_card_link *card,
const struct pnp_card_device_id *id)
{
- acard->dev = pnp_request_card_device(card, id->devs[0].id, NULL);
- if (acard->dev == NULL)
+ chip->dev = pnp_request_card_device(card, id->devs[0].id, NULL);
+ if (chip->dev == NULL)
return -EBUSY;
- acard->devc = pnp_request_card_device(card, id->devs[1].id, NULL);
- if (acard->devc == NULL)
+ chip->devc = pnp_request_card_device(card, id->devs[1].id, NULL);
+ if (chip->devc == NULL)
return -EBUSY;
/* Control port initialization */
- if (pnp_activate_dev(acard->devc) < 0) {
+ if (pnp_activate_dev(chip->devc) < 0) {
snd_printk(KERN_ERR PFX "PnP control configure failure (out of resources?)\n");
return -EAGAIN;
}
snd_printdd("pnp: port=0x%llx\n",
- (unsigned long long)pnp_port_start(acard->devc, 0));
- if (snd_audiodrive_pnp_init_main(dev, acard->dev) < 0)
+ (unsigned long long)pnp_port_start(chip->devc, 0));
+ if (snd_audiodrive_pnp_init_main(dev, chip->dev) < 0)
return -EBUSY;
return 0;
@@ -2128,24 +2122,20 @@ static int __devinit snd_audiodrive_pnpc(int dev, struct snd_audiodrive *acard,
static int snd_es18xx_card_new(int dev, struct snd_card **cardp)
{
return snd_card_create(index[dev], id[dev], THIS_MODULE,
- sizeof(struct snd_audiodrive), cardp);
+ sizeof(struct snd_es18xx), cardp);
}
static int __devinit snd_audiodrive_probe(struct snd_card *card, int dev)
{
- struct snd_audiodrive *acard = card->private_data;
- struct snd_es18xx *chip;
+ struct snd_es18xx *chip = card->private_data;
struct snd_opl3 *opl3;
int err;
- if ((err = snd_es18xx_new_device(card,
- port[dev],
- mpu_port[dev],
- fm_port[dev],
- irq[dev], dma1[dev], dma2[dev],
- &chip)) < 0)
+ err = snd_es18xx_new_device(card,
+ port[dev], mpu_port[dev], fm_port[dev],
+ irq[dev], dma1[dev], dma2[dev]);
+ if (err < 0)
return err;
- acard->chip = chip;
sprintf(card->driver, "ES%x", chip->version);
@@ -2161,10 +2151,12 @@ static int __devinit snd_audiodrive_probe(struct snd_card *card, int dev)
chip->port,
irq[dev], dma1[dev]);
- if ((err = snd_es18xx_pcm(chip, 0, NULL)) < 0)
+ err = snd_es18xx_pcm(card, 0, NULL);
+ if (err < 0)
return err;
- if ((err = snd_es18xx_mixer(chip)) < 0)
+ err = snd_es18xx_mixer(card);
+ if (err < 0)
return err;
if (fm_port[dev] > 0 && fm_port[dev] != SNDRV_AUTO_PORT) {
diff --git a/sound/isa/sb/sb_mixer.c b/sound/isa/sb/sb_mixer.c
index 475220bbcc9..318ff0c823e 100644
--- a/sound/isa/sb/sb_mixer.c
+++ b/sound/isa/sb/sb_mixer.c
@@ -631,7 +631,7 @@ static struct sbmix_elem snd_sb16_ctl_mic_play_switch =
static struct sbmix_elem snd_sb16_ctl_mic_play_vol =
SB_SINGLE("Mic Playback Volume", SB_DSP4_MIC_DEV, 3, 31);
static struct sbmix_elem snd_sb16_ctl_pc_speaker_vol =
- SB_SINGLE("PC Speaker Volume", SB_DSP4_SPEAKER_DEV, 6, 3);
+ SB_SINGLE("Beep Volume", SB_DSP4_SPEAKER_DEV, 6, 3);
static struct sbmix_elem snd_sb16_ctl_capture_vol =
SB_DOUBLE("Capture Volume", SB_DSP4_IGAIN_DEV, (SB_DSP4_IGAIN_DEV + 1), 6, 6, 3);
static struct sbmix_elem snd_sb16_ctl_play_vol =
@@ -689,7 +689,7 @@ static struct sbmix_elem snd_dt019x_ctl_cd_play_vol =
static struct sbmix_elem snd_dt019x_ctl_mic_play_vol =
SB_SINGLE("Mic Playback Volume", SB_DT019X_MIC_DEV, 4, 7);
static struct sbmix_elem snd_dt019x_ctl_pc_speaker_vol =
- SB_SINGLE("PC Speaker Volume", SB_DT019X_SPKR_DEV, 0, 7);
+ SB_SINGLE("Beep Volume", SB_DT019X_SPKR_DEV, 0, 7);
static struct sbmix_elem snd_dt019x_ctl_line_play_vol =
SB_DOUBLE("Line Playback Volume", SB_DT019X_LINE_DEV, SB_DT019X_LINE_DEV, 4,0, 15);
static struct sbmix_elem snd_dt019x_ctl_pcm_play_switch =
diff --git a/sound/isa/sscape.c b/sound/isa/sscape.c
index 66187122377..e2d5d2d3ed9 100644
--- a/sound/isa/sscape.c
+++ b/sound/isa/sscape.c
@@ -1,5 +1,5 @@
/*
- * Low-level ALSA driver for the ENSONIQ SoundScape PnP
+ * Low-level ALSA driver for the ENSONIQ SoundScape
* Copyright (c) by Chris Rankin
*
* This driver was written in part using information obtained from
@@ -25,31 +25,36 @@
#include <linux/err.h>
#include <linux/isa.h>
#include <linux/delay.h>
+#include <linux/firmware.h>
#include <linux/pnp.h>
#include <linux/spinlock.h>
#include <linux/moduleparam.h>
#include <asm/dma.h>
#include <sound/core.h>
-#include <sound/hwdep.h>
#include <sound/wss.h>
#include <sound/mpu401.h>
#include <sound/initval.h>
-#include <sound/sscape_ioctl.h>
-
MODULE_AUTHOR("Chris Rankin");
-MODULE_DESCRIPTION("ENSONIQ SoundScape PnP driver");
+MODULE_DESCRIPTION("ENSONIQ SoundScape driver");
MODULE_LICENSE("GPL");
-
-static int index[SNDRV_CARDS] __devinitdata = SNDRV_DEFAULT_IDX;
-static char* id[SNDRV_CARDS] __devinitdata = SNDRV_DEFAULT_STR;
-static long port[SNDRV_CARDS] __devinitdata = SNDRV_DEFAULT_PORT;
-static long wss_port[SNDRV_CARDS] __devinitdata = SNDRV_DEFAULT_PORT;
-static int irq[SNDRV_CARDS] __devinitdata = SNDRV_DEFAULT_IRQ;
-static int mpu_irq[SNDRV_CARDS] __devinitdata = SNDRV_DEFAULT_IRQ;
-static int dma[SNDRV_CARDS] __devinitdata = SNDRV_DEFAULT_DMA;
-static int dma2[SNDRV_CARDS] __devinitdata = SNDRV_DEFAULT_DMA;
+MODULE_FIRMWARE("sndscape.co0");
+MODULE_FIRMWARE("sndscape.co1");
+MODULE_FIRMWARE("sndscape.co2");
+MODULE_FIRMWARE("sndscape.co3");
+MODULE_FIRMWARE("sndscape.co4");
+MODULE_FIRMWARE("scope.cod");
+
+static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX;
+static char* id[SNDRV_CARDS] = SNDRV_DEFAULT_STR;
+static long port[SNDRV_CARDS] = SNDRV_DEFAULT_PORT;
+static long wss_port[SNDRV_CARDS] = SNDRV_DEFAULT_PORT;
+static int irq[SNDRV_CARDS] = SNDRV_DEFAULT_IRQ;
+static int mpu_irq[SNDRV_CARDS] = SNDRV_DEFAULT_IRQ;
+static int dma[SNDRV_CARDS] = SNDRV_DEFAULT_DMA;
+static int dma2[SNDRV_CARDS] = SNDRV_DEFAULT_DMA;
+static bool joystick[SNDRV_CARDS];
module_param_array(index, int, NULL, 0444);
MODULE_PARM_DESC(index, "Index number for SoundScape soundcard");
@@ -75,6 +80,9 @@ MODULE_PARM_DESC(dma, "DMA # for SoundScape driver.");
module_param_array(dma2, int, NULL, 0444);
MODULE_PARM_DESC(dma2, "DMA2 # for SoundScape driver.");
+module_param_array(joystick, bool, NULL, 0444);
+MODULE_PARM_DESC(joystick, "Enable gameport.");
+
#ifdef CONFIG_PNP
static int isa_registered;
static int pnp_registered;
@@ -101,14 +109,14 @@ MODULE_DEVICE_TABLE(pnp_card, sscape_pnpids);
#define RX_READY 0x01
#define TX_READY 0x02
-#define CMD_ACK 0x80
-#define CMD_SET_MIDI_VOL 0x84
-#define CMD_GET_MIDI_VOL 0x85
-#define CMD_XXX_MIDI_VOL 0x86
-#define CMD_SET_EXTMIDI 0x8a
-#define CMD_GET_EXTMIDI 0x8b
-#define CMD_SET_MT32 0x8c
-#define CMD_GET_MT32 0x8d
+#define CMD_ACK 0x80
+#define CMD_SET_MIDI_VOL 0x84
+#define CMD_GET_MIDI_VOL 0x85
+#define CMD_XXX_MIDI_VOL 0x86
+#define CMD_SET_EXTMIDI 0x8a
+#define CMD_GET_EXTMIDI 0x8b
+#define CMD_SET_MT32 0x8c
+#define CMD_GET_MT32 0x8d
enum GA_REG {
GA_INTSTAT_REG = 0,
@@ -127,7 +135,8 @@ enum GA_REG {
enum card_type {
- SSCAPE,
+ MEDIA_FX, /* Sequoia S-1000 */
+ SSCAPE, /* Sequoia S-2000 */
SSCAPE_PNP,
SSCAPE_VIVO,
};
@@ -140,16 +149,7 @@ struct soundscape {
struct resource *io_res;
struct resource *wss_res;
struct snd_wss *chip;
- struct snd_mpu401 *mpu;
- struct snd_hwdep *hw;
- /*
- * The MIDI device won't work until we've loaded
- * its firmware via a hardware-dependent device IOCTL
- */
- spinlock_t fwlock;
- int hw_in_use;
- unsigned long midi_usage;
unsigned char midi_vol;
};
@@ -161,28 +161,21 @@ static inline struct soundscape *get_card_soundscape(struct snd_card *c)
return (struct soundscape *) (c->private_data);
}
-static inline struct soundscape *get_mpu401_soundscape(struct snd_mpu401 * mpu)
-{
- return (struct soundscape *) (mpu->private_data);
-}
-
-static inline struct soundscape *get_hwdep_soundscape(struct snd_hwdep * hw)
-{
- return (struct soundscape *) (hw->private_data);
-}
-
-
/*
* Allocates some kernel memory that we can use for DMA.
* I think this means that the memory has to map to
* contiguous pages of physical memory.
*/
-static struct snd_dma_buffer *get_dmabuf(struct snd_dma_buffer *buf, unsigned long size)
+static struct snd_dma_buffer *get_dmabuf(struct snd_dma_buffer *buf,
+ unsigned long size)
{
if (buf) {
- if (snd_dma_alloc_pages_fallback(SNDRV_DMA_TYPE_DEV, snd_dma_isa_data(),
+ if (snd_dma_alloc_pages_fallback(SNDRV_DMA_TYPE_DEV,
+ snd_dma_isa_data(),
size, buf) < 0) {
- snd_printk(KERN_ERR "sscape: Failed to allocate %lu bytes for DMA\n", size);
+ snd_printk(KERN_ERR "sscape: Failed to allocate "
+ "%lu bytes for DMA\n",
+ size);
return NULL;
}
}
@@ -199,13 +192,13 @@ static void free_dmabuf(struct snd_dma_buffer *buf)
snd_dma_free_pages(buf);
}
-
/*
* This function writes to the SoundScape's control registers,
* but doesn't do any locking. It's up to the caller to do that.
* This is why this function is "unsafe" ...
*/
-static inline void sscape_write_unsafe(unsigned io_base, enum GA_REG reg, unsigned char val)
+static inline void sscape_write_unsafe(unsigned io_base, enum GA_REG reg,
+ unsigned char val)
{
outb(reg, ODIE_ADDR_IO(io_base));
outb(val, ODIE_DATA_IO(io_base));
@@ -215,7 +208,8 @@ static inline void sscape_write_unsafe(unsigned io_base, enum GA_REG reg, unsign
* Write to the SoundScape's control registers, and do the
* necessary locking ...
*/
-static void sscape_write(struct soundscape *s, enum GA_REG reg, unsigned char val)
+static void sscape_write(struct soundscape *s, enum GA_REG reg,
+ unsigned char val)
{
unsigned long flags;
@@ -228,7 +222,8 @@ static void sscape_write(struct soundscape *s, enum GA_REG reg, unsigned char va
* Read from the SoundScape's control registers, but leave any
* locking to the caller. This is why the function is "unsafe" ...
*/
-static inline unsigned char sscape_read_unsafe(unsigned io_base, enum GA_REG reg)
+static inline unsigned char sscape_read_unsafe(unsigned io_base,
+ enum GA_REG reg)
{
outb(reg, ODIE_ADDR_IO(io_base));
return inb(ODIE_DATA_IO(io_base));
@@ -257,9 +252,8 @@ static inline void set_midi_mode_unsafe(unsigned io_base)
static inline int host_read_unsafe(unsigned io_base)
{
int data = -1;
- if ((inb(HOST_CTRL_IO(io_base)) & RX_READY) != 0) {
+ if ((inb(HOST_CTRL_IO(io_base)) & RX_READY) != 0)
data = inb(HOST_DATA_IO(io_base));
- }
return data;
}
@@ -301,7 +295,7 @@ static inline int host_write_unsafe(unsigned io_base, unsigned char data)
* Also leaves all locking-issues to the caller ...
*/
static int host_write_ctrl_unsafe(unsigned io_base, unsigned char data,
- unsigned timeout)
+ unsigned timeout)
{
int err;
@@ -320,7 +314,7 @@ static int host_write_ctrl_unsafe(unsigned io_base, unsigned char data,
*
* NOTE: This check is based upon observation, not documentation.
*/
-static inline int verify_mpu401(const struct snd_mpu401 * mpu)
+static inline int verify_mpu401(const struct snd_mpu401 *mpu)
{
return ((inb(MPU401C(mpu)) & 0xc0) == 0x80);
}
@@ -328,7 +322,7 @@ static inline int verify_mpu401(const struct snd_mpu401 * mpu)
/*
* This is apparently the standard way to initailise an MPU-401
*/
-static inline void initialise_mpu401(const struct snd_mpu401 * mpu)
+static inline void initialise_mpu401(const struct snd_mpu401 *mpu)
{
outb(0, MPU401D(mpu));
}
@@ -338,9 +332,10 @@ static inline void initialise_mpu401(const struct snd_mpu401 * mpu)
* The AD1845 detection fails if we *don't* do this, so I
* think that this is a good idea ...
*/
-static inline void activate_ad1845_unsafe(unsigned io_base)
+static void activate_ad1845_unsafe(unsigned io_base)
{
- sscape_write_unsafe(io_base, GA_HMCTL_REG, (sscape_read_unsafe(io_base, GA_HMCTL_REG) & 0xcf) | 0x10);
+ unsigned char val = sscape_read_unsafe(io_base, GA_HMCTL_REG);
+ sscape_write_unsafe(io_base, GA_HMCTL_REG, (val & 0xcf) | 0x10);
sscape_write_unsafe(io_base, GA_CDCFG_REG, 0x80);
}
@@ -359,24 +354,27 @@ static void soundscape_free(struct snd_card *c)
* Tell the SoundScape to begin a DMA tranfer using the given channel.
* All locking issues are left to the caller.
*/
-static inline void sscape_start_dma_unsafe(unsigned io_base, enum GA_REG reg)
+static void sscape_start_dma_unsafe(unsigned io_base, enum GA_REG reg)
{
- sscape_write_unsafe(io_base, reg, sscape_read_unsafe(io_base, reg) | 0x01);
- sscape_write_unsafe(io_base, reg, sscape_read_unsafe(io_base, reg) & 0xfe);
+ sscape_write_unsafe(io_base, reg,
+ sscape_read_unsafe(io_base, reg) | 0x01);
+ sscape_write_unsafe(io_base, reg,
+ sscape_read_unsafe(io_base, reg) & 0xfe);
}
/*
* Wait for a DMA transfer to complete. This is a "limited busy-wait",
* and all locking issues are left to the caller.
*/
-static int sscape_wait_dma_unsafe(unsigned io_base, enum GA_REG reg, unsigned timeout)
+static int sscape_wait_dma_unsafe(unsigned io_base, enum GA_REG reg,
+ unsigned timeout)
{
while (!(sscape_read_unsafe(io_base, reg) & 0x01) && (timeout != 0)) {
udelay(100);
--timeout;
} /* while */
- return (sscape_read_unsafe(io_base, reg) & 0x01);
+ return sscape_read_unsafe(io_base, reg) & 0x01;
}
/*
@@ -392,12 +390,12 @@ static int obp_startup_ack(struct soundscape *s, unsigned timeout)
do {
unsigned long flags;
- unsigned char x;
+ int x;
spin_lock_irqsave(&s->lock, flags);
- x = inb(HOST_DATA_IO(s->io_base));
+ x = host_read_unsafe(s->io_base);
spin_unlock_irqrestore(&s->lock, flags);
- if ((x & 0xfe) == 0xfe)
+ if (x == 0xfe || x == 0xff)
return 1;
msleep(10);
@@ -419,10 +417,10 @@ static int host_startup_ack(struct soundscape *s, unsigned timeout)
do {
unsigned long flags;
- unsigned char x;
+ int x;
spin_lock_irqsave(&s->lock, flags);
- x = inb(HOST_DATA_IO(s->io_base));
+ x = host_read_unsafe(s->io_base);
spin_unlock_irqrestore(&s->lock, flags);
if (x == 0xfe)
return 1;
@@ -436,15 +434,15 @@ static int host_startup_ack(struct soundscape *s, unsigned timeout)
/*
* Upload a byte-stream into the SoundScape using DMA channel A.
*/
-static int upload_dma_data(struct soundscape *s,
- const unsigned char __user *data,
- size_t size)
+static int upload_dma_data(struct soundscape *s, const unsigned char *data,
+ size_t size)
{
unsigned long flags;
struct snd_dma_buffer dma;
int ret;
+ unsigned char val;
- if (!get_dmabuf(&dma, PAGE_ALIGN(size)))
+ if (!get_dmabuf(&dma, PAGE_ALIGN(32 * 1024)))
return -ENOMEM;
spin_lock_irqsave(&s->lock, flags);
@@ -452,70 +450,57 @@ static int upload_dma_data(struct soundscape *s,
/*
* Reset the board ...
*/
- sscape_write_unsafe(s->io_base, GA_HMCTL_REG, sscape_read_unsafe(s->io_base, GA_HMCTL_REG) & 0x3f);
+ val = sscape_read_unsafe(s->io_base, GA_HMCTL_REG);
+ sscape_write_unsafe(s->io_base, GA_HMCTL_REG, val & 0x3f);
/*
* Enable the DMA channels and configure them ...
*/
- sscape_write_unsafe(s->io_base, GA_DMACFG_REG, 0x50);
- sscape_write_unsafe(s->io_base, GA_DMAA_REG, (s->chip->dma1 << 4) | DMA_8BIT);
+ val = (s->chip->dma1 << 4) | DMA_8BIT;
+ sscape_write_unsafe(s->io_base, GA_DMAA_REG, val);
sscape_write_unsafe(s->io_base, GA_DMAB_REG, 0x20);
/*
* Take the board out of reset ...
*/
- sscape_write_unsafe(s->io_base, GA_HMCTL_REG, sscape_read_unsafe(s->io_base, GA_HMCTL_REG) | 0x80);
+ val = sscape_read_unsafe(s->io_base, GA_HMCTL_REG);
+ sscape_write_unsafe(s->io_base, GA_HMCTL_REG, val | 0x80);
/*
- * Upload the user's data (firmware?) to the SoundScape
+ * Upload the firmware to the SoundScape
* board through the DMA channel ...
*/
while (size != 0) {
unsigned long len;
- /*
- * Apparently, copying to/from userspace can sleep.
- * We are therefore forbidden from holding any
- * spinlocks while we copy ...
- */
- spin_unlock_irqrestore(&s->lock, flags);
-
- /*
- * Remember that the data that we want to DMA
- * comes from USERSPACE. We have already verified
- * the userspace pointer ...
- */
len = min(size, dma.bytes);
- len -= __copy_from_user(dma.area, data, len);
+ memcpy(dma.area, data, len);
data += len;
size -= len;
- /*
- * Grab that spinlock again, now that we've
- * finished copying!
- */
- spin_lock_irqsave(&s->lock, flags);
-
snd_dma_program(s->chip->dma1, dma.addr, len, DMA_MODE_WRITE);
sscape_start_dma_unsafe(s->io_base, GA_DMAA_REG);
if (!sscape_wait_dma_unsafe(s->io_base, GA_DMAA_REG, 5000)) {
/*
- * Don't forget to release this spinlock we're holding ...
+ * Don't forget to release this spinlock we're holding
*/
spin_unlock_irqrestore(&s->lock, flags);
- snd_printk(KERN_ERR "sscape: DMA upload has timed out\n");
+ snd_printk(KERN_ERR
+ "sscape: DMA upload has timed out\n");
ret = -EAGAIN;
goto _release_dma;
}
} /* while */
set_host_mode_unsafe(s->io_base);
+ outb(0x0, s->io_base);
/*
* Boot the board ... (I think)
*/
- sscape_write_unsafe(s->io_base, GA_HMCTL_REG, sscape_read_unsafe(s->io_base, GA_HMCTL_REG) | 0x40);
+ val = sscape_read_unsafe(s->io_base, GA_HMCTL_REG);
+ sscape_write_unsafe(s->io_base, GA_HMCTL_REG, val | 0x40);
spin_unlock_irqrestore(&s->lock, flags);
/*
@@ -525,10 +510,12 @@ static int upload_dma_data(struct soundscape *s,
*/
ret = 0;
if (!obp_startup_ack(s, 5000)) {
- snd_printk(KERN_ERR "sscape: No response from on-board processor after upload\n");
+ snd_printk(KERN_ERR "sscape: No response "
+ "from on-board processor after upload\n");
ret = -EAGAIN;
} else if (!host_startup_ack(s, 5000)) {
- snd_printk(KERN_ERR "sscape: SoundScape failed to initialise\n");
+ snd_printk(KERN_ERR
+ "sscape: SoundScape failed to initialise\n");
ret = -EAGAIN;
}
@@ -536,7 +523,7 @@ _release_dma:
/*
* NOTE!!! We are NOT holding any spinlocks at this point !!!
*/
- sscape_write(s, GA_DMAA_REG, (s->ic_type == IC_ODIE ? 0x70 : 0x40));
+ sscape_write(s, GA_DMAA_REG, (s->ic_type == IC_OPUS ? 0x40 : 0x70));
free_dmabuf(&dma);
return ret;
@@ -546,167 +533,76 @@ _release_dma:
* Upload the bootblock(?) into the SoundScape. The only
* purpose of this block of code seems to be to tell
* us which version of the microcode we should be using.
- *
- * NOTE: The boot-block data resides in USER-SPACE!!!
- * However, we have already verified its memory
- * addresses by the time we get here.
*/
-static int sscape_upload_bootblock(struct soundscape *sscape, struct sscape_bootblock __user *bb)
+static int sscape_upload_bootblock(struct snd_card *card)
{
+ struct soundscape *sscape = get_card_soundscape(card);
unsigned long flags;
+ const struct firmware *init_fw = NULL;
int data = 0;
int ret;
- ret = upload_dma_data(sscape, bb->code, sizeof(bb->code));
-
- spin_lock_irqsave(&sscape->lock, flags);
- if (ret == 0) {
- data = host_read_ctrl_unsafe(sscape->io_base, 100);
- }
- set_midi_mode_unsafe(sscape->io_base);
- spin_unlock_irqrestore(&sscape->lock, flags);
-
- if (ret == 0) {
- if (data < 0) {
- snd_printk(KERN_ERR "sscape: timeout reading firmware version\n");
- ret = -EAGAIN;
- }
- else if (__copy_to_user(&bb->version, &data, sizeof(bb->version))) {
- ret = -EFAULT;
- }
+ ret = request_firmware(&init_fw, "scope.cod", card->dev);
+ if (ret < 0) {
+ snd_printk(KERN_ERR "sscape: Error loading scope.cod");
+ return ret;
}
+ ret = upload_dma_data(sscape, init_fw->data, init_fw->size);
- return ret;
-}
-
-/*
- * Upload the microcode into the SoundScape. The
- * microcode is 64K of data, and if we try to copy
- * it into a local variable then we will SMASH THE
- * KERNEL'S STACK! We therefore leave it in USER
- * SPACE, and save ourselves from copying it at all.
- */
-static int sscape_upload_microcode(struct soundscape *sscape,
- const struct sscape_microcode __user *mc)
-{
- unsigned long flags;
- char __user *code;
- int err;
+ release_firmware(init_fw);
- /*
- * We are going to have to copy this data into a special
- * DMA-able buffer before we can upload it. We shall therefore
- * just check that the data pointer is valid for now.
- *
- * NOTE: This buffer is 64K long! That's WAY too big to
- * copy into a stack-temporary anyway.
- */
- if ( get_user(code, &mc->code) ||
- !access_ok(VERIFY_READ, code, SSCAPE_MICROCODE_SIZE) )
- return -EFAULT;
+ spin_lock_irqsave(&sscape->lock, flags);
+ if (ret == 0)
+ data = host_read_ctrl_unsafe(sscape->io_base, 100);
- if ((err = upload_dma_data(sscape, code, SSCAPE_MICROCODE_SIZE)) == 0) {
- snd_printk(KERN_INFO "sscape: MIDI firmware loaded\n");
- }
+ if (data & 0x10)
+ sscape_write_unsafe(sscape->io_base, GA_SMCFGA_REG, 0x2f);
- spin_lock_irqsave(&sscape->lock, flags);
- set_midi_mode_unsafe(sscape->io_base);
spin_unlock_irqrestore(&sscape->lock, flags);
- initialise_mpu401(sscape->mpu);
+ data &= 0xf;
+ if (ret == 0 && data > 7) {
+ snd_printk(KERN_ERR
+ "sscape: timeout reading firmware version\n");
+ ret = -EAGAIN;
+ }
- return err;
+ return (ret == 0) ? data : ret;
}
/*
- * Hardware-specific device functions, to implement special
- * IOCTLs for the SoundScape card. This is how we upload
- * the microcode into the card, for ex