mirror of
https://github.com/adulau/aha.git
synced 2024-12-28 19:56:18 +00:00
ALSA: sscape: add supoort for SPEA Media FX/Reveal SC-600
Move code from the OSS sscape driver in order to support old Soundscape OEM models. Signed-off-by: Krzysztof Helt <krzysztof.h1@wp.pl> Signed-off-by: Takashi Iwai <tiwai@suse.de>
This commit is contained in:
parent
4f272341c7
commit
f0968e3f7a
2 changed files with 86 additions and 36 deletions
|
@ -377,10 +377,12 @@ config SND_SSCAPE
|
||||||
select SND_WSS_LIB
|
select SND_WSS_LIB
|
||||||
help
|
help
|
||||||
Say Y here to include support for Ensoniq SoundScape
|
Say Y here to include support for Ensoniq SoundScape
|
||||||
soundcards.
|
and Ensoniq OEM soundcards.
|
||||||
|
|
||||||
The PCM audio is supported on SoundScape Classic, Elite, PnP
|
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.
|
||||||
|
|
||||||
To compile this driver as a module, choose M here: the module
|
To compile this driver as a module, choose M here: the module
|
||||||
will be called snd-sscape.
|
will be called snd-sscape.
|
||||||
|
|
|
@ -127,7 +127,8 @@ enum GA_REG {
|
||||||
|
|
||||||
|
|
||||||
enum card_type {
|
enum card_type {
|
||||||
SSCAPE,
|
MEDIA_FX, /* Sequoia S-1000 */
|
||||||
|
SSCAPE, /* Sequoia S-2000 */
|
||||||
SSCAPE_PNP,
|
SSCAPE_PNP,
|
||||||
SSCAPE_VIVO,
|
SSCAPE_VIVO,
|
||||||
};
|
};
|
||||||
|
@ -784,20 +785,25 @@ static struct snd_kcontrol_new midi_mixer_ctl = {
|
||||||
* These IRQs are encoded as bit patterns so that they can be
|
* These IRQs are encoded as bit patterns so that they can be
|
||||||
* written to the control registers.
|
* written to the control registers.
|
||||||
*/
|
*/
|
||||||
static unsigned __devinit get_irq_config(int irq)
|
static unsigned __devinit get_irq_config(int sscape_type, int irq)
|
||||||
{
|
{
|
||||||
static const int valid_irq[] = { 9, 5, 7, 10 };
|
static const int valid_irq[] = { 9, 5, 7, 10 };
|
||||||
|
static const int old_irq[] = { 9, 7, 5, 15 };
|
||||||
unsigned cfg;
|
unsigned cfg;
|
||||||
|
|
||||||
for (cfg = 0; cfg < ARRAY_SIZE(valid_irq); ++cfg) {
|
if (sscape_type == MEDIA_FX) {
|
||||||
if (irq == valid_irq[cfg])
|
for (cfg = 0; cfg < ARRAY_SIZE(old_irq); ++cfg)
|
||||||
return cfg;
|
if (irq == old_irq[cfg])
|
||||||
} /* for */
|
return cfg;
|
||||||
|
} else {
|
||||||
|
for (cfg = 0; cfg < ARRAY_SIZE(valid_irq); ++cfg)
|
||||||
|
if (irq == valid_irq[cfg])
|
||||||
|
return cfg;
|
||||||
|
}
|
||||||
|
|
||||||
return INVALID_IRQ;
|
return INVALID_IRQ;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Perform certain arcane port-checks to see whether there
|
* Perform certain arcane port-checks to see whether there
|
||||||
* is a SoundScape board lurking behind the given ports.
|
* is a SoundScape board lurking behind the given ports.
|
||||||
|
@ -842,11 +848,39 @@ static int __devinit detect_sscape(struct soundscape *s, long wss_io)
|
||||||
if (s->type != SSCAPE_VIVO && (d & 0x9f) != 0x0e)
|
if (s->type != SSCAPE_VIVO && (d & 0x9f) != 0x0e)
|
||||||
goto _done;
|
goto _done;
|
||||||
|
|
||||||
d = sscape_read_unsafe(s->io_base, GA_HMCTL_REG) & 0x3f;
|
if (s->ic_type == IC_OPUS)
|
||||||
sscape_write_unsafe(s->io_base, GA_HMCTL_REG, d | 0xc0);
|
activate_ad1845_unsafe(s->io_base);
|
||||||
|
|
||||||
if (s->type == SSCAPE_VIVO)
|
if (s->type == SSCAPE_VIVO)
|
||||||
wss_io += 4;
|
wss_io += 4;
|
||||||
|
|
||||||
|
d = sscape_read_unsafe(s->io_base, GA_HMCTL_REG) & 0x3f;
|
||||||
|
sscape_write_unsafe(s->io_base, GA_HMCTL_REG, d | 0xc0);
|
||||||
|
|
||||||
|
/* wait for WSS codec */
|
||||||
|
for (d = 0; d < 500; d++) {
|
||||||
|
if ((inb(wss_io) & 0x80) == 0)
|
||||||
|
break;
|
||||||
|
spin_unlock_irqrestore(&s->lock, flags);
|
||||||
|
msleep(1);
|
||||||
|
spin_lock_irqsave(&s->lock, flags);
|
||||||
|
}
|
||||||
|
snd_printd(KERN_INFO "init delay = %d ms\n", d);
|
||||||
|
|
||||||
|
if ((inb(wss_io) & 0x80) != 0)
|
||||||
|
goto _done;
|
||||||
|
|
||||||
|
if (inb(wss_io + 2) == 0xff)
|
||||||
|
goto _done;
|
||||||
|
|
||||||
|
d = sscape_read_unsafe(s->io_base, GA_HMCTL_REG) & 0x3f;
|
||||||
|
sscape_write_unsafe(s->io_base, GA_HMCTL_REG, d);
|
||||||
|
|
||||||
|
if ((inb(wss_io) & 0x80) != 0)
|
||||||
|
s->type = MEDIA_FX;
|
||||||
|
|
||||||
|
d = sscape_read_unsafe(s->io_base, GA_HMCTL_REG) & 0x3f;
|
||||||
|
sscape_write_unsafe(s->io_base, GA_HMCTL_REG, d | 0xc0);
|
||||||
/* wait for WSS codec */
|
/* wait for WSS codec */
|
||||||
for (d = 0; d < 500; d++) {
|
for (d = 0; d < 500; d++) {
|
||||||
if ((inb(wss_io) & 0x80) == 0)
|
if ((inb(wss_io) & 0x80) == 0)
|
||||||
|
@ -954,9 +988,6 @@ static int __devinit create_ad1845(struct snd_card *card, unsigned port,
|
||||||
if (sscape->type == SSCAPE_VIVO)
|
if (sscape->type == SSCAPE_VIVO)
|
||||||
port += 4;
|
port += 4;
|
||||||
|
|
||||||
if (dma1 == dma2)
|
|
||||||
dma2 = -1;
|
|
||||||
|
|
||||||
err = snd_wss_create(card, port, -1, irq, dma1, dma2,
|
err = snd_wss_create(card, port, -1, irq, dma1, dma2,
|
||||||
WSS_HW_DETECT, WSS_HWSHARE_DMA1, &chip);
|
WSS_HW_DETECT, WSS_HWSHARE_DMA1, &chip);
|
||||||
if (!err) {
|
if (!err) {
|
||||||
|
@ -1051,21 +1082,7 @@ static int __devinit create_sscape(int dev, struct snd_card *card)
|
||||||
struct resource *wss_res;
|
struct resource *wss_res;
|
||||||
unsigned long flags;
|
unsigned long flags;
|
||||||
int err;
|
int err;
|
||||||
|
const char *name;
|
||||||
/*
|
|
||||||
* Check that the user didn't pass us garbage data ...
|
|
||||||
*/
|
|
||||||
irq_cfg = get_irq_config(irq[dev]);
|
|
||||||
if (irq_cfg == INVALID_IRQ) {
|
|
||||||
snd_printk(KERN_ERR "sscape: Invalid IRQ %d\n", irq[dev]);
|
|
||||||
return -ENXIO;
|
|
||||||
}
|
|
||||||
|
|
||||||
mpu_irq_cfg = get_irq_config(mpu_irq[dev]);
|
|
||||||
if (mpu_irq_cfg == INVALID_IRQ) {
|
|
||||||
printk(KERN_ERR "sscape: Invalid IRQ %d\n", mpu_irq[dev]);
|
|
||||||
return -ENXIO;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Grab IO ports that we will need to probe so that we
|
* Grab IO ports that we will need to probe so that we
|
||||||
|
@ -1109,8 +1126,41 @@ static int __devinit create_sscape(int dev, struct snd_card *card)
|
||||||
goto _release_dma;
|
goto _release_dma;
|
||||||
}
|
}
|
||||||
|
|
||||||
printk(KERN_INFO "sscape: hardware detected at 0x%x, using IRQ %d, DMA %d\n",
|
switch (sscape->type) {
|
||||||
sscape->io_base, irq[dev], dma[dev]);
|
case MEDIA_FX:
|
||||||
|
name = "MediaFX/SoundFX";
|
||||||
|
break;
|
||||||
|
case SSCAPE:
|
||||||
|
name = "Soundscape";
|
||||||
|
break;
|
||||||
|
case SSCAPE_PNP:
|
||||||
|
name = "Soundscape PnP";
|
||||||
|
break;
|
||||||
|
case SSCAPE_VIVO:
|
||||||
|
name = "Soundscape VIVO";
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
name = "unknown Soundscape";
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
printk(KERN_INFO "sscape: %s card detected at 0x%x, using IRQ %d, DMA %d\n",
|
||||||
|
name, sscape->io_base, irq[dev], dma[dev]);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Check that the user didn't pass us garbage data ...
|
||||||
|
*/
|
||||||
|
irq_cfg = get_irq_config(sscape->type, irq[dev]);
|
||||||
|
if (irq_cfg == INVALID_IRQ) {
|
||||||
|
snd_printk(KERN_ERR "sscape: Invalid IRQ %d\n", irq[dev]);
|
||||||
|
return -ENXIO;
|
||||||
|
}
|
||||||
|
|
||||||
|
mpu_irq_cfg = get_irq_config(sscape->type, mpu_irq[dev]);
|
||||||
|
if (mpu_irq_cfg == INVALID_IRQ) {
|
||||||
|
printk(KERN_ERR "sscape: Invalid IRQ %d\n", mpu_irq[dev]);
|
||||||
|
return -ENXIO;
|
||||||
|
}
|
||||||
|
|
||||||
if (sscape->type != SSCAPE_VIVO) {
|
if (sscape->type != SSCAPE_VIVO) {
|
||||||
/*
|
/*
|
||||||
|
@ -1141,8 +1191,6 @@ static int __devinit create_sscape(int dev, struct snd_card *card)
|
||||||
*/
|
*/
|
||||||
spin_lock_irqsave(&sscape->lock, flags);
|
spin_lock_irqsave(&sscape->lock, flags);
|
||||||
|
|
||||||
activate_ad1845_unsafe(sscape->io_base);
|
|
||||||
|
|
||||||
sscape_write_unsafe(sscape->io_base, GA_INTENA_REG, 0x00); /* disable */
|
sscape_write_unsafe(sscape->io_base, GA_INTENA_REG, 0x00); /* disable */
|
||||||
sscape_write_unsafe(sscape->io_base, GA_SMCFGA_REG, 0x2e);
|
sscape_write_unsafe(sscape->io_base, GA_SMCFGA_REG, 0x2e);
|
||||||
sscape_write_unsafe(sscape->io_base, GA_SMCFGB_REG, 0x00);
|
sscape_write_unsafe(sscape->io_base, GA_SMCFGB_REG, 0x00);
|
||||||
|
@ -1151,12 +1199,12 @@ static int __devinit create_sscape(int dev, struct snd_card *card)
|
||||||
* Enable and configure the DMA channels ...
|
* Enable and configure the DMA channels ...
|
||||||
*/
|
*/
|
||||||
sscape_write_unsafe(sscape->io_base, GA_DMACFG_REG, 0x50);
|
sscape_write_unsafe(sscape->io_base, GA_DMACFG_REG, 0x50);
|
||||||
dma_cfg = (sscape->ic_type == IC_ODIE ? 0x70 : 0x40);
|
dma_cfg = (sscape->ic_type == IC_OPUS ? 0x40 : 0x70);
|
||||||
sscape_write_unsafe(sscape->io_base, GA_DMAA_REG, dma_cfg);
|
sscape_write_unsafe(sscape->io_base, GA_DMAA_REG, dma_cfg);
|
||||||
sscape_write_unsafe(sscape->io_base, GA_DMAB_REG, 0x20);
|
sscape_write_unsafe(sscape->io_base, GA_DMAB_REG, 0x20);
|
||||||
|
|
||||||
sscape_write_unsafe(sscape->io_base,
|
mpu_irq_cfg |= mpu_irq_cfg << 2;
|
||||||
GA_INTCFG_REG, 0xf0 | (mpu_irq_cfg << 2) | mpu_irq_cfg);
|
sscape_write_unsafe(sscape->io_base, GA_INTCFG_REG, 0xf0 | mpu_irq_cfg);
|
||||||
sscape_write_unsafe(sscape->io_base,
|
sscape_write_unsafe(sscape->io_base,
|
||||||
GA_CDCFG_REG, 0x09 | DMA_8BIT
|
GA_CDCFG_REG, 0x09 | DMA_8BIT
|
||||||
| (dma[dev] << 4) | (irq_cfg << 1));
|
| (dma[dev] << 4) | (irq_cfg << 1));
|
||||||
|
|
Loading…
Reference in a new issue