Common subdirectories: sound_v3s86/lowlevel and sound/lowlevel
diff -u sound_v3s86/sb.h sound/sb.h
--- sound_v3s86/sb.h	Wed Oct  1 01:16:45 1997
+++ sound/sb.h	Sun Feb  8 17:46:20 1998
@@ -45,6 +45,8 @@
 #define MDL_ES1868MIDI	14	/* MIDI port of ESS1868 */
 #define MDL_AEDSP	15	/* Audio Excel DSP 16 */
 
+#define SUBMDL_ALS007	42	/* ALS-007 differs from SB16 only in mixer */
+				/* register assignment */
 /*
  * Config flags
  */
diff -u sound_v3s86/sb_audio.c sound/sb_audio.c
--- sound_v3s86/sb_audio.c	Sat Dec  6 03:12:44 1997
+++ sound/sb_audio.c	Sun Mar  8 14:27:09 1998
@@ -61,6 +61,20 @@
   devc->irq_mode = IMODE_NONE;
   sb_dsp_reset (devc);
 
+  /* The ALS007 seems to require that the DSP be removed from the output */
+  /* in order for recording to be activated properly.  This is done by   */
+  /* setting the appropriate bits of the output control register 4ch to  */
+  /* zero.  This code assumes that the output control registers are not  */
+  /* used anywhere else and therefore the DSP bits are *always* ON for   */
+  /* output and OFF for sampling.                                        */
+  if (devc->submodel == SUBMDL_ALS007) 
+    if (mode & OPEN_READ) {
+      sb_setmixer(devc,ALS007_OUTPUT_CTRL2,
+        sb_getmixer(devc,ALS007_OUTPUT_CTRL2) & 0xf9);
+    } else {
+      sb_setmixer(devc,ALS007_OUTPUT_CTRL2,
+        sb_getmixer(devc,ALS007_OUTPUT_CTRL2) | 0x06);
+    }
   return 0;
 }
 
@@ -75,6 +89,12 @@
 
   if (devc->dma16 != -1 && devc->dma16 != devc->dma8)
     sound_close_dma (devc->dma16);
+
+  /* For ALS007, turn DSP output back on if closing the device for read */
+  if ((devc->submodel == SUBMDL_ALS007) && (devc->opened & OPEN_READ)) {
+    sb_setmixer(devc,ALS007_OUTPUT_CTRL2,
+      sb_getmixer(devc,ALS007_OUTPUT_CTRL2) | 0x06);
+  }
 
   devc->opened = 0;
 }
diff -u sound_v3s86/sb_common.c sound/sb_common.c
--- sound_v3s86/sb_common.c	Wed Oct  1 01:16:54 1997
+++ sound/sb_common.c	Sat Feb 21 21:28:13 1998
@@ -728,7 +728,8 @@
   sb_devc        *devc;
   char            name[100];
   extern int      sb_be_quiet;
-
+  int             mixer22, mixer30;
+  
 /*
  * Check if we had detected a SB device earlier
  */
@@ -847,6 +848,30 @@
 
     case 4:
       devc->model = hw_config->card_subtype = MDL_SB16;
+      /* ALS007 and ALS100 return DSP version 4.2 and have 2 post-reset !=0  */
+      /* registers at 0x3c and 0x4c (output ctrl registers on ALS007) whereas*/
+      /* a "standard" SB16 doesn't have a register at 0x4c.  ALS100 actively */
+      /* updates register 0x22 whenever 0x30 changes, as per the SB16 spec.  */
+      /* Since ALS007 doesn't, this can be used to differentiate the 2 cards.*/
+      if ((devc->minor == 2) && sb_getmixer(devc,0x3c) && sb_getmixer(devc,0x4c)) {
+        mixer30 = sb_getmixer(devc,0x30);
+        sb_setmixer(devc,0x22,(mixer22=sb_getmixer(devc,0x22)) & 0x0f);
+        sb_setmixer(devc,0x30,0xff);
+        /* ALS100 will force 0x30 to 0xf8 like SB16; ALS007 will allow 0xff. */
+        /* Register 0x22 & 0xf0 on ALS100 == 0xf0; on ALS007 it == 0x10.     */
+        if ((sb_getmixer(devc,0x30) != 0xff) || ((sb_getmixer(devc,0x22) & 0xf0) != 0x10)) {
+          if (hw_config->name == NULL)
+            hw_config->name = "Sound Blaster 16 (ALS-100)";
+        } else {
+          sb_setmixer(devc,0x3c,0x1f);    /* Enable all inputs */
+          sb_setmixer(devc,0x4c,0x1f);
+          sb_setmixer(devc,0x22,mixer22); /* Restore 0x22 to original value */
+          devc->submodel = SUBMDL_ALS007;
+          if (hw_config->name == NULL)
+            hw_config->name = "Sound Blaster 16 (ALS-007)";
+        }
+        sb_setmixer(devc,0x30,mixer30);
+      } else
       if (hw_config->name == NULL)
 	hw_config->name = "Sound Blaster 16";
 
diff -u sound_v3s86/sb_mixer.c sound/sb_mixer.c
--- sound_v3s86/sb_mixer.c	Wed Oct  1 01:16:55 1997
+++ sound/sb_mixer.c	Sat Feb 21 17:23:21 1998
@@ -270,15 +270,32 @@
       if (!devmask)
 	devmask = SOUND_MASK_MIC;
 
-      regimageL = regimageR = 0;
-      for (i = 0; i < SOUND_MIXER_NRDEVICES; i++)
-	if ((1 << i) & devmask)
-	  {
-	    regimageL |= sb16_recmasks_L[i];
-	    regimageR |= sb16_recmasks_R[i];
-	  }
-      sb_setmixer (devc, SB16_IMASK_L, regimageL);
-      sb_setmixer (devc, SB16_IMASK_R, regimageR);
+      if (devc->submodel == SUBMDL_ALS007) {
+        switch (devmask) {
+          case SOUND_MASK_LINE:
+            sb_setmixer(devc, ALS007_RECORD_SRC, ALS007_LINE);
+            break;
+          case SOUND_MASK_CD:
+            sb_setmixer(devc, ALS007_RECORD_SRC, ALS007_CD);
+            break;
+          case SOUND_MASK_SYNTH:
+            sb_setmixer(devc, ALS007_RECORD_SRC, ALS007_SYNTH);
+            break;
+          default:           /* Also takes care of SOUND_MASK_MIC case */
+            sb_setmixer(devc, ALS007_RECORD_SRC, ALS007_MIC);
+            break;
+        }
+      } else {
+        regimageL = regimageR = 0;
+        for (i = 0; i < SOUND_MIXER_NRDEVICES; i++)
+          if ((1 << i) & devmask)
+	    {
+	      regimageL |= sb16_recmasks_L[i];
+	      regimageR |= sb16_recmasks_R[i];
+	    }
+        sb_setmixer (devc, SB16_IMASK_L, regimageL);
+        sb_setmixer (devc, SB16_IMASK_R, regimageR);
+      }
       break;
     }
 
@@ -362,6 +379,13 @@
   sb_mixer_ioctl
 };
 
+static struct mixer_operations als007_mixer_operations =
+{
+  "ALS007",
+  "Avance ALS-007",
+  sb_mixer_ioctl
+};
+
 static void
 sb_mixer_reset (sb_devc * devc)
 {
@@ -419,9 +443,14 @@
 
     case MDL_SB16:
       devc->mixer_caps = 0;
-      devc->supported_devices = SB16_MIXER_DEVICES;
       devc->supported_rec_devices = SB16_RECORDING_DEVICES;
-      devc->iomap = &sb16_mix;
+      if (devc->submodel != SUBMDL_ALS007) {
+        devc->supported_devices = SB16_MIXER_DEVICES;
+        devc->iomap = &sb16_mix;
+      } else {
+        devc->supported_devices = ALS007_MIXER_DEVICES;
+        devc->iomap = &als007_mix;
+      }
       break;
 
     default:
@@ -444,7 +473,11 @@
       return 0;
     }
 
-  memcpy ((char *) mixer_devs[num_mixers], (char *) &sb_mixer_operations,
+  if (devc->submodel != SUBMDL_ALS007)
+    memcpy ((char *) mixer_devs[num_mixers], (char *) &sb_mixer_operations,
+	  sizeof (struct mixer_operations));
+  else
+    memcpy ((char *) mixer_devs[num_mixers], (char *) &als007_mixer_operations,
 	  sizeof (struct mixer_operations));
 
   mixer_devs[num_mixers]->devc = devc;
diff -u sound_v3s86/sb_mixer.h sound/sb_mixer.h
--- sound_v3s86/sb_mixer.h	Wed Oct  1 01:16:45 1997
+++ sound/sb_mixer.h	Fri Feb 20 22:49:22 1998
@@ -47,6 +47,13 @@
 					 SOUND_MASK_VOLUME | SOUND_MASK_BASS | SOUND_MASK_TREBLE | \
 					SOUND_MASK_IMIX)
 
+/* These are the only devices that are working at the moment.  Others could
+ * be added once they are identified and a method is found to control them.
+ */
+#define ALS007_MIXER_DEVICES	(SOUND_MASK_SYNTH | SOUND_MASK_LINE | \
+				 SOUND_MASK_PCM | SOUND_MASK_MIC | \
+				 SOUND_MASK_CD | \
+				 SOUND_MASK_VOLUME)
 /*
  * Mixer registers
  * 
@@ -95,6 +102,13 @@
 #define LEFT_CHN	0
 #define RIGHT_CHN	1
 
+/*
+ * Mixer registers of ALS007
+ */
+#define ALS007_RECORD_SRC	0x6c
+#define ALS007_OUTPUT_CTRL1	0x3c
+#define ALS007_OUTPUT_CTRL2	0x4c
+
 #define MIX_ENT(name, reg_l, bit_l, len_l, reg_r, bit_r, len_r)	\
 	{{reg_l, bit_l, len_l}, {reg_r, bit_r, len_r}}
 
@@ -169,6 +183,23 @@
 MIX_ENT(SOUND_MIXER_OGAIN,	0x41, 7, 2, 0x42, 7, 2)
 };
 
+static mixer_tab als007_mix = {
+MIX_ENT(SOUND_MIXER_VOLUME,	0x62, 7, 4, 0x62, 3, 4),
+MIX_ENT(SOUND_MIXER_BASS,	0x00, 0, 0, 0x00, 0, 0),
+MIX_ENT(SOUND_MIXER_TREBLE,	0x00, 0, 0, 0x00, 0, 0),
+MIX_ENT(SOUND_MIXER_SYNTH,	0x66, 7, 4, 0x66, 3, 4),
+MIX_ENT(SOUND_MIXER_PCM,	0x64, 7, 4, 0x64, 3, 4),
+MIX_ENT(SOUND_MIXER_SPEAKER,	0x00, 0, 0, 0x00, 0, 0),
+MIX_ENT(SOUND_MIXER_LINE,	0x6e, 7, 4, 0x6e, 3, 4),
+MIX_ENT(SOUND_MIXER_MIC,	0x6a, 2, 3, 0x00, 0, 0),
+MIX_ENT(SOUND_MIXER_CD,		0x68, 7, 4, 0x68, 3, 4),
+MIX_ENT(SOUND_MIXER_IMIX,	0x00, 0, 0, 0x00, 0, 0),
+MIX_ENT(SOUND_MIXER_ALTPCM,	0x00, 0, 0, 0x00, 0, 0),
+MIX_ENT(SOUND_MIXER_RECLEV,	0x00, 0, 0, 0x00, 0, 0), /* Obsolete. Use IGAIN */
+MIX_ENT(SOUND_MIXER_IGAIN,	0x00, 0, 0, 0x00, 0, 0),
+MIX_ENT(SOUND_MIXER_OGAIN,	0x00, 0, 0, 0x00, 0, 0)
+};
+
 #ifdef SM_GAMES       /* Master volume is lower and PCM & FM volumes
 			     higher than with SB Pro. This improves the
 			     sound quality */
@@ -282,6 +313,15 @@
 #define SRC__MIC         1	/* Select Microphone recording source */
 #define SRC__CD          3	/* Select CD recording source */
 #define SRC__LINE        7	/* Use Line-in for recording source */
+
+/*
+ *	Recording sources for ALS-007
+ */
+
+#define ALS007_MIC	4
+#define ALS007_LINE	6
+#define ALS007_CD	2
+#define ALS007_SYNTH	7
 
 #endif
 #endif
