patch-2.2.0-pre8 linux/drivers/sound/sb_common.c
Next file: linux/drivers/sound/sb_ess.c
Previous file: linux/drivers/sound/sb_audio.c
Back to the patch index
Back to the overall index
- Lines: 507
- Date:
Thu Jan 14 22:59:47 1999
- Orig file:
v2.2.0-pre7/linux/drivers/sound/sb_common.c
- Orig date:
Fri Jan 8 22:36:11 1999
diff -u --recursive --new-file v2.2.0-pre7/linux/drivers/sound/sb_common.c linux/drivers/sound/sb_common.c
@@ -32,6 +32,8 @@
#include "sb_mixer.h"
#include "sb.h"
+#include "sb_ess.h"
+
static sb_devc *detected_devc = NULL; /* For communication from probe to init */
static sb_devc *last_devc = NULL; /* For MPU401 initialization */
@@ -91,7 +93,7 @@
return 0;
}
-static int sb_dsp_get_byte(sb_devc * devc)
+int sb_dsp_get_byte(sb_devc * devc)
{
int i;
@@ -103,50 +105,18 @@
return 0xffff;
}
-inline void ess_extended (sb_devc * devc)
-{
- /* Enable extended mode */
-
- sb_dsp_command(devc, 0xc6);
-}
-
-int ess_write(sb_devc * devc, unsigned char reg, unsigned char data)
-{
- /* Write a byte to an extended mode register of ES1688 */
-
- if (!sb_dsp_command(devc, reg))
- return 0;
-
- return sb_dsp_command(devc, data);
-}
-
-int ess_read(sb_devc * devc, unsigned char reg)
-{
-/* Read a byte from an extended mode register of ES1688 */
- if (!sb_dsp_command(devc, 0xc0)) /* Read register command */
- return -1;
-
- if (!sb_dsp_command(devc, reg))
- return -1;
-
- return sb_dsp_get_byte(devc);
-}
-
-static void sbintr(int irq, void *dev_id, struct pt_regs *dummy)
+static void sb_intr (sb_devc *devc)
{
int status;
unsigned char src = 0xff;
- sb_devc *devc = dev_id;
-
- devc->irq_ok = 1;
if (devc->model == MDL_SB16)
{
src = sb_getmixer(devc, IRQ_STAT); /* Interrupt source register */
#if defined(CONFIG_MIDI)&& defined(CONFIG_UART401)
- if (src & 4)
- uart401intr(devc->irq, devc->midi_irq_cookie, NULL); /* MPU401 interrupt */
+ if (src & 4) /* MPU401 interrupt */
+ uart401intr(devc->irq, devc->midi_irq_cookie, NULL);
#endif
if (!(src & 3))
@@ -209,6 +179,21 @@
status = inb(DSP_DATA_AVL16);
}
+static void sbintr(int irq, void *dev_id, struct pt_regs *dummy)
+{
+ sb_devc *devc = dev_id;
+
+ devc->irq_ok = 1;
+
+ switch (devc->model) {
+ case MDL_ESS:
+ ess_intr (devc);
+ break;
+ default:
+ sb_intr (devc);
+ break;
+ }
+}
int sb_dsp_reset(sb_devc * devc)
{
@@ -216,10 +201,11 @@
DEB(printk("Entered sb_dsp_reset()\n"));
- if (devc->model == MDL_ESS)
- outb(3, DSP_RESET); /* Reset FIFO too */
- else
- outb(1, DSP_RESET);
+ if (devc->model == MDL_ESS) return ess_dsp_reset (devc);
+
+ /* This is only for non-ESS chips */
+
+ outb(1, DSP_RESET);
udelay(10);
outb(0, DSP_RESET);
@@ -232,9 +218,9 @@
DDB(printk("sb: No response to RESET\n"));
return 0; /* Sorry */
}
- if (devc->model == MDL_ESS) ess_extended (devc);
DEB(printk("sb_dsp_reset() OK\n"));
+
return 1;
}
@@ -492,206 +478,6 @@
#endif
}
-/*
- * ESS technology describes a detection scheme in their docs. It involves
- * fiddling with the bits in certain mixer registers. ess_probe is supposed
- * to help.
- */
-static unsigned int ess_identify (sb_devc * devc);
-
-static int ess_probe (sb_devc * devc, int reg, int xorval)
-{
- int val1, val2, val3;
-
- val1 = sb_getmixer (devc, reg);
- val2 = val1 ^ xorval;
- sb_setmixer (devc, reg, val2);
- val3 = sb_getmixer (devc, reg);
- sb_setmixer (devc, reg, val1);
-
- return (val2 == val3);
-}
-
-static int ess_init(sb_devc * devc, struct address_info *hw_config)
-{
- unsigned char cfg, irq_bits = 0, dma_bits = 0;
- int ess_major = 0, ess_minor = 0;
- int i;
- static char name[100];
-
- /*
- * Try to detect ESS chips.
- */
-
- sb_dsp_command(devc, 0xe7); /* Return identification */
-
- for (i = 1000; i; i--)
- {
- if (inb(DSP_DATA_AVAIL) & 0x80)
- {
- if (ess_major == 0)
- ess_major = inb(DSP_READ);
- else
- {
- ess_minor = inb(DSP_READ);
- break;
- }
- }
- }
-
- if (ess_major == 0)
- return 0;
-
- if (ess_major == 0x48 && (ess_minor & 0xf0) == 0x80)
- {
- sprintf(name, "ESS ES488 AudioDrive (rev %d)",
- ess_minor & 0x0f);
- hw_config->name = name;
- devc->model = MDL_SBPRO;
- return 1;
- }
-
- /*
- * This the detection heuristic of ESS technology, though somewhat
- * changed to actually make it work.
- * This results in the following detection steps:
- * - distinct between ES688 and ES1688+ (as always done in this driver)
- * if ES688 we're ready
- * - try to detect ES1868, ES1869 or ES1878 (ess_identify)
- * if successful we're ready
- * - try to detect ES1888, ES1887 or ES1788 (aim: detect ES1887)
- * if successful we're ready
- * - Dunno. Must be 1688. Will do in general
- *
- * This is the most BETA part of the software: Will the detection
- * always work?
- */
- devc->model = MDL_ESS;
- devc->submodel = ess_minor & 0x0f;
-
- if (ess_major == 0x68 && (ess_minor & 0xf0) == 0x80)
- {
- char *chip = NULL;
-
- if ((ess_minor & 0x0f) < 8) {
- chip = "ES688";
- };
- if (chip == NULL) {
- int type;
-
- type = ess_identify (devc);
-
- switch (type) {
- case 0x1868:
- chip = "ES1868";
- devc->submodel = SUBMDL_ES1868;
- break;
- case 0x1869:
- chip = "ES1869";
- devc->submodel = SUBMDL_ES1869;
- break;
- case 0x1878:
- chip = "ES1878";
- devc->submodel = SUBMDL_ES1878;
- break;
- };
- };
- if (chip == NULL && !ess_probe(devc, 0x64, (1 << 3))) {
- if (ess_probe (devc, 0x70, 0x7f)) {
- if (ess_probe (devc, 0x64, (1 << 5))) {
- chip = "ES1887";
- } else {
- chip = "ES1888";
- }
- devc->submodel = SUBMDL_ES188X;
- } else {
- chip = "ES1788";
- devc->submodel = SUBMDL_ES1788;
- }
- };
- if (chip == NULL) {
- chip = "ES1688";
- };
-
- sprintf(name,"ESS %s AudioDrive (rev %d)",
- chip, ess_minor & 0x0f);
- }
- else
- strcpy(name, "Jazz16");
-
- hw_config->name = name;
- sb_dsp_reset(devc); /* Turn on extended mode */
-
- /*
- * Set IRQ configuration register
- */
-
- cfg = 0x50; /* Enable only DMA counter interrupt */
-
- switch (devc->irq)
- {
- case 2:
- case 9:
- irq_bits = 0;
- break;
-
- case 5:
- irq_bits = 1;
- break;
-
- case 7:
- irq_bits = 2;
- break;
-
- case 10:
- irq_bits = 3;
- break;
-
- default:
- irq_bits = 0;
- cfg = 0x10; /* Disable all interrupts */
- printk(KERN_ERR "ESS1688: Invalid IRQ %d\n", devc->irq);
- return 0;
- }
-
- if (!ess_write(devc, 0xb1, cfg | (irq_bits << 2)))
- printk(KERN_ERR "ESS1688: Failed to write to IRQ config register\n");
-
- /*
- * Set DMA configuration register
- */
-
- cfg = 0x50; /* Extended mode DMA enable */
-
- if (devc->dma8 > 3 || devc->dma8 < 0 || devc->dma8 == 2)
- {
- dma_bits = 0;
- cfg = 0x00; /* Disable all DMA */
- printk(KERN_ERR "ESS1688: Invalid DMA %d\n", devc->dma8);
- }
- else
- {
- if (devc->dma8 == 3)
- dma_bits = 3;
- else
- dma_bits = devc->dma8 + 1;
- }
-
- if (!ess_write(devc, 0xb2, cfg | (dma_bits << 2)))
- printk(KERN_ERR "ESS1688: Failed to write to DMA config register\n");
-
- /*
- * Enable joystick and OPL3
- */
-
- cfg = sb_getmixer(devc, 0x40);
- sb_setmixer(devc, 0x40, cfg | 0x03);
- if (devc->submodel >= 8) /* ES1688 */
- devc->caps |= SB_NO_MIDI; /* ES1688 uses MPU401 MIDI mode */
- sb_dsp_reset(devc);
- return 1;
-}
-
int sb_dsp_detect(struct address_info *hw_config)
{
sb_devc sb_info;
@@ -700,7 +486,7 @@
memset((char *) &sb_info, 0, sizeof(sb_info)); /* Zero everything */
sb_info.my_mididev = -1;
sb_info.my_mixerdev = -1;
- sb_info.my_dev = -1;
+ sb_info.dev = -1;
/*
* Initialize variables
@@ -905,11 +691,18 @@
break;
case 3: /* SB Pro and most clones */
- if (devc->model == 0)
- {
+ switch (devc->model) {
+ case 0:
devc->model = hw_config->card_subtype = MDL_SBPRO;
if (hw_config->name == NULL)
hw_config->name = "Sound Blaster Pro (8 BIT ONLY)";
+ break;
+ case MDL_ESS:
+ if (!ess_dsp_init(devc, hw_config)) {
+ release_region (hw_config->io_base, 16);
+ return 0;
+ }
+ break;
}
break;
@@ -931,6 +724,7 @@
/* Register 0x22 & 0xf0 on ALS100 == 0xf0; on ALS007 it == 0x10. */
if ((sb_getmixer(devc,0x30) != 0xff) || ((sb_getmixer(devc,0x22) & 0xf0) != 0x10))
{
+ devc->submodel = SUBMDL_ALS100;
if (hw_config->name == NULL)
hw_config->name = "Sound Blaster 16 (ALS-100)";
}
@@ -1068,7 +862,7 @@
/* But we have to do it, if UART401 is not detected */
if (!sbmpu)
sound_unload_mididev(devc->my_mididev);
- sound_unload_audiodev(devc->my_dev);
+ sound_unload_audiodev(devc->dev);
}
kfree(devc);
}
@@ -1089,20 +883,16 @@
{
unsigned long flags;
- /* MDB(printk("ESS: write port %x: %x\n", port, value)); */
+ if (devc->model == MDL_ESS) return ess_setmixer (devc, port, value);
save_flags(flags);
cli();
- if (devc->model == MDL_ESS && port >= 0xa0) {
- /* ess_extended (devc); */
- ess_write (devc, port, value);
- } else {
- outb(((unsigned char) (port & 0xff)), MIXER_ADDR);
-
- udelay(20);
- outb(((unsigned char) (value & 0xff)), MIXER_DATA);
- udelay(20);
- };
+
+ outb(((unsigned char) (port & 0xff)), MIXER_ADDR);
+ udelay(20);
+ outb(((unsigned char) (value & 0xff)), MIXER_DATA);
+ udelay(20);
+
restore_flags(flags);
}
@@ -1111,38 +901,29 @@
unsigned int val;
unsigned long flags;
+ if (devc->model == MDL_ESS) return ess_getmixer (devc, port);
+
save_flags(flags);
cli();
- outb(((unsigned char) (port & 0xff)), MIXER_ADDR);
+ outb(((unsigned char) (port & 0xff)), MIXER_ADDR);
udelay(20);
val = inb(MIXER_DATA);
udelay(20);
+
restore_flags(flags);
return val;
}
-/*
- * Some PnP chips can be identified by repeatedly reading mixer register 0x40.
- * This is done by ess_identify
- */
-static unsigned int ess_identify (sb_devc * devc)
-{
- unsigned int val;
- unsigned long flags;
- save_flags(flags);
- cli();
- outb(((unsigned char) (0x40 & 0xff)), MIXER_ADDR);
-
- udelay(20);
- val = inb(MIXER_DATA) << 8;
- udelay(20);
- val |= inb(MIXER_DATA);
- udelay(20);
- restore_flags(flags);
+void sb_chgmixer
+ (sb_devc * devc, unsigned int reg, unsigned int mask, unsigned int val)
+{
+ int value;
- return val;
+ value = sb_getmixer(devc, reg);
+ value = (value & ~mask) | (val & mask);
+ sb_setmixer(devc, reg, value);
}
#ifdef CONFIG_MIDI
@@ -1285,53 +1066,6 @@
#endif
outb((control | 0x03), mpu_base + 7); /* xxxxxx11 restarts */
hw_config->name = "SoundMan Wave";
- return 1;
-}
-
-static int ess_midi_init(sb_devc * devc, struct address_info *hw_config)
-{
- unsigned char cfg, tmp;
-
- cfg = sb_getmixer(devc, 0x40) & 0x03;
-
- if (devc->submodel < 8)
- {
- sb_setmixer(devc, 0x40, cfg | 0x03); /* Enable OPL3 & joystick */
- return 0; /* ES688 doesn't support MPU401 mode */
- }
- tmp = (hw_config->io_base & 0x0f0) >> 4;
-
- if (tmp > 3)
- {
- sb_setmixer(devc, 0x40, cfg);
- return 0;
- }
- cfg |= tmp << 3;
-
- tmp = 1; /* MPU enabled without interrupts */
-
- /* May be shared: if so the value is -ve */
-
- switch(abs(hw_config->irq))
- {
- case 9:
- tmp = 0x4;
- break;
- case 5:
- tmp = 0x5;
- break;
- case 7:
- tmp = 0x6;
- break;
- case 10:
- tmp = 0x7;
- break;
- default:
- return 0;
- }
-
- cfg |= tmp << 5;
- sb_setmixer(devc, 0x40, cfg | 0x03);
return 1;
}
FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen, slshen@lbl.gov