Commits

Anonymous committed 9b4a733

Patches for OSS 4.2-build 2004

1) buildid.dat - version bumped to 2004
2) oss_cmi878x/.devices - added XONAR_DS
3) oss_cmi878x/oss_cmi878x.c - added bunch of fixes for XONAR_DS, XONAR_STX
and fixed up volume handling
4) oss_geode/.devices - changed the BETA tage for AMD 5536 support f
5) oss_geode/oss_geode.c - fixed up AMD 5536 support (from OSS 3.8 VxWorks
port)
6) SunOS/osdetect/ossdetect.c - fixed up sadasupport installation problem on
Sparc
7) SunOS/sbin/soundon - added devfsadm call duriong soundon to properly
install all the device links.

Comments (0)

Files changed (8)

-2003
+2004
 oss_audioloop	AUDIOLOOP	OSS loopback audio driver
 oss_audiopci	pci1274,5000	Creative AudioPCI (ES1370)
 oss_cmi878x	pci13f6,8788	CMedia CMI8788
-oss_cmi878x	pci1043,834f	Asus Xonar D1 (AV100)
-oss_cmi878x	pci1043,8275    Asus Xonar DX (AV100)
+oss_cmi878x	pci1043,8269    Asus Xonar D2 
+oss_cmi878x	pci1043,834f	Asus Xonar D1 
+oss_cmi878x	pci1043,8275    Asus Xonar DX 
+oss_cmi878x	pci1043,82b7    Asus Xonar D2X 
+oss_cmi878x	pci1043,838e    Asus Xonar DS 
+oss_cmi878x	pci1043,835c    Asus Xonar Essence STX 
 oss_cmpci	pci13f6,100	C-Media CM8338A
 oss_cmpci	pci13f6,100	MIDIMan DiO 2448
 oss_cmpci	pci13f6,101	CMedia CM8338B
 oss_fmedia	pcs1489,7008	Genius Sound Maker Live
 oss_geode	pci100b,503	National Semiconductor Geode SC1200
 oss_geode	pci1078,103	National Semiconductor Geode CS5530
-oss_geode	pci1022,2093	AMD Geode CS5536 (BETA)
+oss_geode	pci1022,2093	AMD Geode CS5536 
 oss_hdaudio	pci8086,2668	Intel High Definition Audio (ICH6)
 oss_hdaudio	pci8086,27d8	Intel High Definition Audio (ICH7)
 oss_hdaudio	pci8086,269a	Intel High Definition Audio (ESB2)

kernel/drv/oss_cmi878x/.devices

 oss_cmi878x	pci13f6,8788	CMedia CMI8788
-oss_cmi878x	pci1043,8269    Asus Xonar D2 (AV200)
-oss_cmi878x	pci1043,834f	Asus Xonar D1 (AV100)
-oss_cmi878x	pci1043,8275    Asus Xonar DX (AV100)
-oss_cmi878x	pci1043,82b7    Asus Xonar D2X (AV200)
-oss_cmi878x	pci1043,835c    Asus Xonar Essence STX (AV100)
+oss_cmi878x	pci1043,8269    Asus Xonar D2 
+oss_cmi878x	pci1043,834f	Asus Xonar D1 
+oss_cmi878x	pci1043,8275    Asus Xonar DX 
+oss_cmi878x	pci1043,82b7    Asus Xonar D2X 
+oss_cmi878x	pci1043,838e    Asus Xonar DS 
+oss_cmi878x	pci1043,835c    Asus Xonar Essence STX 
+

kernel/drv/oss_cmi878x/oss_cmi878x.c

 #define SUBID_XONAR_D1		0x834f
 #define SUBID_XONAR_DX		0x8275
 #define SUBID_XONAR_STX 	0x835c
+#define SUBID_XONAR_DS		0x838e
 
 #define SUBID_GENERIC		0x0000
 
 /* Xonar specific */
 #define XONAR_DX_FRONTDAC	0x9e
 #define XONAR_DX_SURRDAC	0x30
-#define XONAR_DX_OUTPUT		0x01
-#define XONAR_DX_MCLOCK_256	0x10
-
-/* Xonar D2 spi specific */
-#define XONAR_D2_FRONTDAC	0x98
-#define XONAR_D2_SURRDAC	0x9a
-#define XONAR_D2_LFEDAC 	0x9c
-#define XONAR_D2_REARDAC	0x9e
-
-/* defs for Xonar STX */
 #define XONAR_STX_FRONTDAC	0x98
+#define XONAR_DS_FRONTDAC	0x1
+#define XONAR_DS_SURRDAC	0x0
+#define XONAR_MCLOCK_256	0x10
 
 /* defs for AKM 4396 DAC */
 #define AK4396_CTL1        0x00
   ac97_devc ac97devc, fp_ac97devc;
   int ac97_mixer_dev, fp_mixer_dev, cmi_mixer_dev;
   int playvol[4];
+  int recvol;
   /* uart401 */
   oss_midi_inputbyte_t midi_input_intr;
   int midi_opened, midi_disabled;
 }
 cmi8788_devc;
 
+static const char xd2_codec_map[4] = {
+                0, 1, 2, 4
+        };
+
 static void cmi8788uartintr (cmi8788_devc * devc);
 static int reset_cmi8788uart (cmi8788_devc * devc);
 static void enter_uart_mode (cmi8788_devc * devc);
 }
 
 static int
-spi_write (void *devc_, int codec_num, unsigned char *data)
+spi_write (cmi8788_devc *devc, int codec_num, unsigned char reg, int val)
 {
-  cmi8788_devc *devc = devc_;
   oss_native_word flags;
-  unsigned char val;
+  unsigned int tmp;
+  int latch, shift, count;
 
   MUTEX_ENTER_IRQDISABLE (devc->low_mutex, flags);
 
+  /* check if SPI is busy */
+   count = 10;
+   while ((INB(devc, SPI_CONTROL) & 0x1) && count-- > 0) {
+    	oss_udelay(10);
+  }
+
+  if (devc->model == SUBID_XONAR_DS) {
+	shift = 9;
+	latch = 0;
+  }
+  else {
+	shift = 8;
+	latch = 0x80;
+  }
+
+  /* 2 byte data/reg info to be written */
+  tmp = val;
+  tmp |= (reg << shift);
+
   /* write 2-byte data values */
-  OUTB (devc->osdev, data[0], SPI_DATA + 0);
-  OUTB (devc->osdev, data[1], SPI_DATA + 1);
+  OUTB (devc->osdev, tmp & 0xff, SPI_DATA + 0);
+  OUTB (devc->osdev, (tmp >> 8) & 0xff, SPI_DATA + 1);
 
   /* Latch high, clock=160, Len=2byte, mode=write */
-  val = (INB (devc->osdev, SPI_CONTROL) & ~0x7E) | 0x81;
+  tmp = (INB (devc->osdev, SPI_CONTROL) & ~0x7E) | latch | 0x1;
 
   /* now address which codec you want to send the data to */
-  val |= (codec_num << 4) & 0x70;
+  tmp |= (codec_num << 4);
 
   /* send the command to write the data */
-  OUTB (devc->osdev, val, SPI_CONTROL);
-
-  oss_udelay (100);
+  OUTB (devc->osdev, tmp, SPI_CONTROL);
+
   MUTEX_EXIT_IRQRESTORE (devc->low_mutex, flags);
   return 1;
 }
 
 static int
-two_wire_write (void *devc_, unsigned char codec_num, unsigned char reg,
+i2c_write (cmi8788_devc *devc, unsigned char codec_num, unsigned char reg,
 		unsigned char data)
 {
-  cmi8788_devc *devc = devc_;
   oss_native_word flags;
   int count = 50;
 
   /* select the codec number to address */
   OUTB (devc->osdev, codec_num, TWO_WIRE_ADDR);
   MUTEX_EXIT_IRQRESTORE (devc->low_mutex, flags);
-  oss_udelay(100);
+  oss_udelay(100); 
 
   return 1;
 
 }
 
-static void
-pcm1796_write(cmi8788_devc *devc, int codec_id, unsigned char reg, unsigned char val)
-{
-static const char codec_map[4] = {
-                0, 1, 2, 4
-        };
-unsigned char data[2];
-
-      data[0] = val;
-      data[1] = reg;
-      spi_write (devc, codec_map[codec_id], data);
-}
-
 static int
 cs4398_init (void *devc_, int codec_)
 {
   OUTW(devc->osdev, 0x0100, TWO_WIRE_CTRL);
 
   // Power down, enable control mode.
-  two_wire_write(devc_, codec_, CS4398_MISC_CTRL,
+  i2c_write(devc_, codec_, CS4398_MISC_CTRL, 
     CS4398_CPEN | CS4398_POWER_DOWN);
   // Left justified PCM (DAC and 8788 support I2S, but doesn't work.
   // Setting it introduces clipping like hell).
-  two_wire_write(devc_, codec_, CS4398_MODE_CTRL, 0);
-  // That's the DAC default, set anyway.
-  two_wire_write(devc_, codec_, 3, 0x09);
+  i2c_write(devc_, codec_, CS4398_MODE_CTRL, 0);
+  // That's the DAC default, set anyway. 
+  i2c_write(devc_, codec_, 3, 0x09);
   // PCM auto-mute.
-  two_wire_write(devc_, codec_, 4, 0x82);
+  i2c_write(devc_, codec_, 4, 0x82);
   // Vol A+B to -64dB.
-  two_wire_write(devc_, codec_, 5, 0x80);
-  two_wire_write(devc_, codec_, 6, 0x80);
+  i2c_write(devc_, codec_, 5, 0x80);
+  i2c_write(devc_, codec_, 6, 0x80);
   // Soft-ramping.
-  two_wire_write(devc_, codec_, 7, 0xF0);
+  i2c_write(devc_, codec_, 7, 0xF0);
   // Remove power down flag.
-  two_wire_write(devc_, codec_, CS4398_MISC_CTRL, CS4398_CPEN);
+  i2c_write(devc_, codec_, CS4398_MISC_CTRL, CS4398_CPEN);
 
   return 1;
 }
 cs4362a_init(void * devc_, int codec_)
 {
   cmi8788_devc *devc = devc_;
-
+  
   // Fast Two-Wire. Reduces the wire ready time.
   OUTW(devc->osdev, 0x0100, TWO_WIRE_CTRL);
 
-  /* Power down and enable control port. */
-  two_wire_write(devc_, codec_, CS4362A_MODE1_CTRL, CS4362A_CPEN | CS4362A_POWER_DOWN);
+  /* Power down and enable control port. */ 
+  i2c_write(devc_, codec_, CS4362A_MODE1_CTRL, CS4362A_CPEN | CS4362A_POWER_DOWN);
   /* Left-justified PCM */
-  two_wire_write(devc_, codec_, CS4362A_MODE2_CTRL, CS4362A_DIF_LJUST);
+  i2c_write(devc_, codec_, CS4362A_MODE2_CTRL, CS4362A_DIF_LJUST);
   /* Ramp & Automute, re-set DAC defaults. */
-  two_wire_write(devc_, codec_, CS4362A_MODE3_CTRL, 0x84);
+  i2c_write(devc_, codec_, CS4362A_MODE3_CTRL, 0x84); 
   /* Filter control, DAC defs. */
-  two_wire_write(devc_, codec_, CS4362A_FILTER_CTRL, 0);
+  i2c_write(devc_, codec_, CS4362A_FILTER_CTRL, 0);
   /* Invert control, DAC defs. */
-  two_wire_write(devc_, codec_, CS4362A_INVERT_CTRL, 0);
+  i2c_write(devc_, codec_, CS4362A_INVERT_CTRL, 0);
   /* Mixing control, DAC defs. */
-  two_wire_write(devc_, codec_, CS4362A_MIX1_CTRL, 0x24);
-  two_wire_write(devc_, codec_, CS4362A_MIX2_CTRL, 0x24);
-  two_wire_write(devc_, codec_, CS4362A_MIX3_CTRL, 0x24);
+  i2c_write(devc_, codec_, CS4362A_MIX1_CTRL, 0x24);
+  i2c_write(devc_, codec_, CS4362A_MIX2_CTRL, 0x24);
+  i2c_write(devc_, codec_, CS4362A_MIX3_CTRL, 0x24);
   /* Volume to -64dB. */
-  two_wire_write(devc_, codec_, CS4362A_VOLA_1, 0x40);
-  two_wire_write(devc_, codec_, CS4362A_VOLB_1, 0x40);
-  two_wire_write(devc_, codec_, CS4362A_VOLA_2, 0x40);
-  two_wire_write(devc_, codec_, CS4362A_VOLB_2, 0x40);
-  two_wire_write(devc_, codec_, CS4362A_VOLA_3, 0x40);
-  two_wire_write(devc_, codec_, CS4362A_VOLB_3, 0x40);
+  i2c_write(devc_, codec_, CS4362A_VOLA_1, 0x40);
+  i2c_write(devc_, codec_, CS4362A_VOLB_1, 0x40);
+  i2c_write(devc_, codec_, CS4362A_VOLA_2, 0x40);
+  i2c_write(devc_, codec_, CS4362A_VOLB_2, 0x40);
+  i2c_write(devc_, codec_, CS4362A_VOLA_3, 0x40);
+  i2c_write(devc_, codec_, CS4362A_VOLB_3, 0x40);
   /* Power up. */
-  two_wire_write(devc_, codec_, CS4362A_MODE1_CTRL, CS4362A_CPEN);
+  i2c_write(devc_, codec_, CS4362A_MODE1_CTRL, CS4362A_CPEN);
 
   return 1;
 }
   vol = mix_cvt[vol];
   return (vol * ((1 << bits) - 1) / 100);
 }
-#if 0
-static int
-cs4398_cleanup(void * devc_, int codec_)
+
+
+static void
+cmi8788_generic_set_play_volume (cmi8788_devc *devc, int codec_id, int left, int right)
+
 {
-  /* Simply power down. Keep control port mode up. */
-  two_wire_write(devc_, codec_, CS4398_MISC_CTRL,
-    CS4398_POWER_DOWN | CS4398_CPEN);
-
-  return 1;
+  spi_write (devc, codec_id, AK4396_LchATTCtl | 0x20, mix_scale(left, 8));
+  spi_write (devc, codec_id, AK4396_RchATTCtl | 0x20, mix_scale(right, 8));
 }
 
-static int cs4362a_cleanup(void *devc_, int codec_)
+static void
+xonar_d1_set_play_volume(cmi8788_devc * devc, int codec_id, int left, int right)
 {
-  /* Simply power down. Keep control port mode up. */
-  two_wire_write(devc_, codec_, CS4362A_MODE1_CTRL,
-    CS4362A_CPEN | CS4362A_POWER_DOWN);
-
-  return 1;
-}
-#endif
-
-
-static void
-xonar_dx_set_play_volume(cmi8788_devc * devc, int codec_id, int value)
-{
-  int left, right;
-
-  left = (value & 0x00FF);
-  right = (value & 0xFF00) >> 8;
-
   switch(codec_id)
   {
     case 0:
-      two_wire_write(devc, XONAR_DX_FRONTDAC, CS4398_VOLA, CS4398_VOL(left));
-      two_wire_write(devc, XONAR_DX_FRONTDAC, CS4398_VOLB, CS4398_VOL(right));
+      i2c_write(devc, XONAR_DX_FRONTDAC, CS4398_VOLA, CS4398_VOL(left));
+      i2c_write(devc, XONAR_DX_FRONTDAC, CS4398_VOLB, CS4398_VOL(right));
       break;
     case 1:
-      two_wire_write(devc, XONAR_DX_SURRDAC, CS4362A_VOLA_1, CS4362A_VOL(left));
-      two_wire_write(devc, XONAR_DX_SURRDAC, CS4362A_VOLB_1, CS4362A_VOL(right));
+      i2c_write(devc, XONAR_DX_SURRDAC, CS4362A_VOLA_1, CS4362A_VOL(left));
+      i2c_write(devc, XONAR_DX_SURRDAC, CS4362A_VOLB_1, CS4362A_VOL(right));
       break;
     case 2:
-      two_wire_write(devc, XONAR_DX_SURRDAC, CS4362A_VOLA_2, CS4362A_VOL(left));
-      two_wire_write(devc, XONAR_DX_SURRDAC, CS4362A_VOLB_2, CS4362A_VOL(right));
+      i2c_write(devc, XONAR_DX_SURRDAC, CS4362A_VOLA_2, CS4362A_VOL(left));
+      i2c_write(devc, XONAR_DX_SURRDAC, CS4362A_VOLB_2, CS4362A_VOL(right));
       break;
     case 3:
-      two_wire_write(devc, XONAR_DX_SURRDAC, CS4362A_VOLA_3, CS4362A_VOL(left));
-      two_wire_write(devc, XONAR_DX_SURRDAC, CS4362A_VOLB_3, CS4362A_VOL(right));
+      i2c_write(devc, XONAR_DX_SURRDAC, CS4362A_VOLA_3, CS4362A_VOL(left));
+      i2c_write(devc, XONAR_DX_SURRDAC, CS4362A_VOLB_3, CS4362A_VOL(right));
       break;
   }
 }
 
 static void
-xonar_d2_set_play_volume(cmi8788_devc * devc, int codec_id, int value)
+xonar_d2_set_play_volume(cmi8788_devc *devc, int codec_id, int left, int right)
 {
-  int left, right;
-
-  left = (value & 0x00FF);
-  right = (value & 0xFF00) >> 8;
-
-  pcm1796_write (devc, codec_id, 16, mix_scale(left,8));
-  pcm1796_write (devc, codec_id, 17, mix_scale(right,8));
+  spi_write (devc, xd2_codec_map[codec_id], 16, mix_scale(left,8));
+  spi_write (devc, xd2_codec_map[codec_id], 17, mix_scale(right,8));
 }
 
 static void
-xonar_stx_set_play_volume(cmi8788_devc * devc, int codec_id, int value)
+xonar_stx_set_play_volume(cmi8788_devc * devc, int codec_id, int left, int right)
 {
-  int left, right;
-
-  left = (value & 0x00FF);
-  right = (value & 0xFF00) >> 8;
-
   if (codec_id == 0)
   {
-      two_wire_write(devc, XONAR_STX_FRONTDAC, 16, mix_scale(left,8));
-      two_wire_write(devc, XONAR_STX_FRONTDAC, 17, mix_scale(right,8));
+      i2c_write(devc, XONAR_STX_FRONTDAC, 16, mix_scale(left,8));
+      i2c_write(devc, XONAR_STX_FRONTDAC, 17, mix_scale(right,8));
   }
 }
 
+static void
+xonar_ds_set_play_volume(cmi8788_devc * devc, int codec_id, int left, int right)
+{
+  switch (codec_id)
+   {
+    	case 0:      /* front */
+		spi_write (devc, XONAR_DS_FRONTDAC, 0, mix_scale(left,7)|0x80);
+		spi_write (devc, XONAR_DS_FRONTDAC, 1, mix_scale(right,7)|0x180);
+		spi_write (devc, XONAR_DS_FRONTDAC, 3, mix_scale(left,7)|0x80);
+		spi_write (devc, XONAR_DS_FRONTDAC, 4, mix_scale(right,7)|0x180);
+                break;
+
+	case 1:      /* side */
+                spi_write (devc, XONAR_DS_SURRDAC, 0, mix_scale(left,7)|0x80);
+                spi_write (devc, XONAR_DS_SURRDAC, 1, mix_scale(right,7)|0x180);
+                break;
+	case 2:      /* rear */
+                spi_write (devc, XONAR_DS_SURRDAC, 4, mix_scale(left,7)|0x80);
+                spi_write (devc, XONAR_DS_SURRDAC, 5, mix_scale(right,7)|0x180);
+                break;
+	case 3:      /* center */
+                spi_write (devc, XONAR_DS_SURRDAC, 6, mix_scale(left,7)|0x80);
+                spi_write (devc, XONAR_DS_SURRDAC, 7, mix_scale(right,7)|0x180);
+                break;
+   }
+}
+
+static int
+cmi8788_set_rec_volume (cmi8788_devc * devc, int value)
+{
+  unsigned char left, right;
+
+  left = value & 0xff;
+  right = (value >> 8) & 0xff;
+
+  if (left > 100)
+	left = 100;
+  if (right > 100)
+	right = 100;
+
+  devc->recvol = left | (right << 8);
+
+  spi_write (devc, XONAR_DS_FRONTDAC, 0xe, mix_scale(left,8));
+  spi_write (devc, XONAR_DS_FRONTDAC, 0xf, mix_scale(right,8));
+
+  return devc->recvol;
+}
+
+
 
 static int
 cmi8788_set_play_volume (cmi8788_devc * devc, int codec_id, int value)
 {
-  unsigned char left, right;
-  unsigned char data[2];
-
-  left = value & 0xff;
-  right = (value >> 8) & 0xff;
-
-  devc->playvol[codec_id] = left | (right << 8);
+  int left, right;
+
+  left = (value & 0x00FF);
+  right = (value & 0xFF00) >> 8;
+
+  if (left > 100)
+	left = 100;
+  if (right > 100)
+        right = 100;
+
+  devc->playvol[codec_id] = left | (right<<8);
 
   switch(devc->model)
   {
     case SUBID_XONAR_D1:
     case SUBID_XONAR_DX:
-      xonar_dx_set_play_volume(devc, codec_id, value);
+      xonar_d1_set_play_volume(devc, codec_id, left, right);
       break;
     case SUBID_XONAR_D2:
     case SUBID_XONAR_D2X:
-      xonar_d2_set_play_volume(devc, codec_id, value);
+      xonar_d2_set_play_volume(devc, codec_id, left, right);
       break;
     case SUBID_XONAR_STX:
-      xonar_stx_set_play_volume(devc, codec_id, value);
+      xonar_stx_set_play_volume(devc, codec_id, left, right);
       break;
-
+    case SUBID_XONAR_DS:
+      xonar_ds_set_play_volume(devc, codec_id, left, right);
+      break;
     default:
-      /* Assume default AKM DACs */
-      data[0] = left;
-      data[1] = AK4396_LchATTCtl | 0x20;
-      spi_write (devc, codec_id, data);
-      data[0] = right;
-      data[1] = AK4396_RchATTCtl | 0x20;
-      spi_write (devc, codec_id, data);
+      cmi8788_generic_set_play_volume (devc, codec_id, left, right);
       break;
   }
-
   return devc->playvol[codec_id];
 }
 
 	    return *arg = 0;
 	    break;
 
-	  case SOUND_MIXER_VOLUME:
+	  case SOUND_MIXER_PCM:
 	    val = *arg;
 	    return *arg = cmi8788_set_play_volume (devc, 0, val);
 	    break;
 	    return *arg = cmi8788_set_play_volume (devc, 3, val);
 	    break;
 
+	  case SOUND_MIXER_RECLEV:
+	    val = *arg;
+	    return *arg = cmi8788_set_rec_volume (devc, val);
+	    break;
+
 	  default:
 	    val = *arg;
 	    return *arg = 0;
 	    break;
 
 	  case SOUND_MIXER_DEVMASK:
-		if (devc->model == SUBID_XONAR_STX)
-		   return *arg = SOUND_MASK_VOLUME;
-		else
-		   return *arg =
-	      SOUND_MASK_VOLUME | SOUND_MASK_REARVOL | SOUND_MASK_CENTERVOL |
-	      SOUND_MASK_SIDEVOL;
+            if (devc->model == SUBID_XONAR_STX)
+                *arg = SOUND_MASK_VOLUME;
+            else
+	    	*arg = SOUND_MASK_PCM | SOUND_MASK_REARVOL | 
+			SOUND_MASK_CENTERVOL | SOUND_MASK_SIDEVOL;
+
+	    if (devc->model == SUBID_XONAR_DS)
+		*arg |= SOUND_MASK_RECLEV;
+
+	    return *arg;
 	    break;
 
 	  case SOUND_MIXER_STEREODEVS:
-                if (devc->model == SUBID_XONAR_STX)
-                   return *arg = SOUND_MASK_VOLUME;
-                else
-                   return *arg =
-              SOUND_MASK_VOLUME | SOUND_MASK_REARVOL | SOUND_MASK_CENTERVOL |
-              SOUND_MASK_SIDEVOL;
+            if (devc->model == SUBID_XONAR_STX)
+               *arg = SOUND_MASK_VOLUME;
+            else
+	       *arg = SOUND_MASK_PCM | SOUND_MASK_REARVOL | 
+			SOUND_MASK_CENTERVOL | SOUND_MASK_SIDEVOL;
+
+	    if (devc->model == SUBID_XONAR_DS)
+		*arg |= SOUND_MASK_RECLEV;
+
+	    return *arg;
 	    break;
 
 	  case SOUND_MIXER_CAPS:
 	    return *arg = SOUND_CAP_EXCL_INPUT;
 	    break;
 
-	  case SOUND_MIXER_VOLUME:
+	  case SOUND_MIXER_PCM:
 	    return *arg = devc->playvol[0];
 	    break;
 
 	  case SOUND_MIXER_SIDEVOL:
 	    return *arg = devc->playvol[3];
 	    break;
+	
+	  case SOUND_MIXER_RECLEV:
+	    return *arg = devc->recvol;
+	    break;
 
 	  default:
 	    return *arg = 0;
 	  value = (INB (devc->osdev, REC_MONITOR) & 0x10) ? 1 : 0;
 	  break;
 	case 2:		/* Record source select */
-	  value = (ac97_read (devc, 0x72) & 0x1) ? 1 : 0;
+	  switch (devc->model)
+		{
+		  case SUBID_XONAR_DS:		
+	  		value = (INW (devc->osdev, GPIO_DATA) & 0x40) ? 1 : 0;
+			break;
+		  default: 
+	  		value = (ac97_read (devc, 0x72) & 0x1) ? 1 : 0;
+			break;
+	        }
 	  break;
 	case 3:		/* Speaker Spread - check bit15 to see if it's set */
 	  value = (INW (devc->osdev, PLAY_ROUTING) & 0x8000) ? 0 : 1;
 	case 2:
 	  if (value)
           {
-             if (devc->model == SUBID_XONAR_D1 || devc->model == SUBID_XONAR_DX)
-		OUTW(devc->osdev, INW(devc->osdev, GPIO_DATA) | 0x100, GPIO_DATA);
+	     switch (devc->model)
+		{
+		case SUBID_XONAR_DS:
+			OUTW(devc->osdev, INW(devc->osdev, GPIO_DATA) | 0x40, GPIO_DATA);
+			break;
+		case SUBID_XONAR_D1:
+		case SUBID_XONAR_DX:
+			OUTW(devc->osdev, INW(devc->osdev, GPIO_DATA) | 0x100, GPIO_DATA);
+			break;
+		}
 	     ac97_write(devc, 0x72, ac97_read(devc, 0x72) | 0x1);
 	  }
 	  else
 	  {
-             if (devc->model == SUBID_XONAR_D1 || devc->model == SUBID_XONAR_DX)
-		OUTW(devc->osdev, INW(devc->osdev, GPIO_DATA) & ~0x100, GPIO_DATA);
+             switch (devc->model)
+                {
+                case SUBID_XONAR_DS:
+                        OUTW(devc->osdev, INW(devc->osdev, GPIO_DATA) & ~0x40, GPIO_DATA);
+                        break;
+                case SUBID_XONAR_D1:
+                case SUBID_XONAR_DX:
+                        OUTW(devc->osdev, INW(devc->osdev, GPIO_DATA) & ~0x100, GPIO_DATA);
+                        break;
+                }
+
 	     ac97_write(devc, 0x72, ac97_read(devc, 0x72) & ~0x1);
 	  }
 	  break;
   return 0;
 }
 
+
 void ac97_hwinit(cmi8788_devc *devc)
 {
 
 
 
   /* I2S to 16bit, see below. */
-  sDac = 0x010A;
-
+  sDac = 0x010A; 
+ 
   /* Non-generic DAC initialization */
   switch(devc->model)
   {
     case SUBID_XONAR_D2:
     case SUBID_XONAR_D2X:
     case SUBID_XONAR_STX:
+    case SUBID_XONAR_DS:
       /* Must set master clock. */
-      sDac |= XONAR_DX_MCLOCK_256;
+      sDac |= XONAR_MCLOCK_256;
       break;
   }
 
 
                     /* for all 4 codecs: unmute, set to 24Bit SPI */
 		    for (i = 0; i < 4; ++i) {
-			pcm1796_write(devc, i, 16, mix_scale(75,8)); /* left vol*/
-			pcm1796_write(devc, i, 17, mix_scale(75,8)); /* right vol */
-			pcm1796_write(devc, i, 18, 0x30 | 0x80); /* unmute/24LSB/ATLD */
+			spi_write(devc, xd2_codec_map[i], 16, mix_scale(75,8)); /* left vol*/
+			spi_write(devc, xd2_codec_map[i], 17, mix_scale(75,8)); /* right vol */
+			spi_write(devc, xd2_codec_map[i], 18, 0x30 | 0x80); /* unmute/24LSB/ATLD */
 		    }
   		    /* initialize the codec 0 */
   		    ac97_hwinit(devc);
 		    break;
 
-       case SUBID_XONAR_STX:
-	    /*GPIO0 = Antipop control */
-	    /*GPIO1 = frontpanel h/p control*/
-            /*GPIO7 = 0x0080 controls analog out*/
-            /*GPIO8 = 0x0100 controls mic/line in*/
-            /*GPIO2/3 = 0x000C codec input control*/
-
-            /* setup for 2wire communication mode */
-            OUTB(devc->osdev, INB (devc->osdev, FUNCTION) | 0x40, FUNCTION);
-
-	    /* setup the GPIO direction control register */
-            OUTW(devc->osdev, INW(devc->osdev, GPIO_CONTROL) | 0x018F, GPIO_CONTROL);
-            /* setup GPIO pins mic/output */
-            OUTW(devc->osdev, INW(devc->osdev, GPIO_DATA) | 0x111, GPIO_DATA);
-
-            OUTW(devc->osdev, INW(devc, TWO_WIRE_CTRL)|0x0100, TWO_WIRE_CTRL);
-
-	    /* initialize the PCM1796 DAC */
-            two_wire_write(devc, XONAR_STX_FRONTDAC, 16, mix_scale(75,8));
-            two_wire_write(devc, XONAR_STX_FRONTDAC, 17, mix_scale(75,8));
-            two_wire_write(devc, XONAR_STX_FRONTDAC, 18, 0x00|0x30|0x80); /*unmute, 24LSB, ATLD */
-            two_wire_write(devc, XONAR_STX_FRONTDAC, 19, 0); /*ATS1/FLT_SHARP*/
-            two_wire_write(devc, XONAR_STX_FRONTDAC, 20, 0); /*OS_64*/
-            two_wire_write(devc, XONAR_STX_FRONTDAC, 21, 0); 
-
-            /* initialize the codec 0 */
-            ac97_hwinit(devc);
+ 		case SUBID_XONAR_STX:
+            	    /*GPIO0 = Antipop control */
+                    /*GPIO1 = frontpanel h/p control*/
+                    /*GPIO7 = 0x0080 controls analog out*/
+                    /*GPIO8 = 0x0100 controls mic/line in*/
+                    /*GPIO2/3 = 0x000C codec input control*/
+
+                    /* setup for 2wire communication mode */
+                    OUTB(devc->osdev, INB (devc->osdev, FUNCTION) | 0x40, FUNCTION);
+
+                    /* setup the GPIO direction control register */
+                    OUTW(devc->osdev, INW(devc->osdev, GPIO_CONTROL) | 0x018F, GPIO_CONTROL);
+                    /* setup GPIO pins mic/output */
+                    OUTW(devc->osdev, INW(devc->osdev, GPIO_DATA) | 0x111, GPIO_DATA);
+
+                    OUTW(devc->osdev, INW(devc, TWO_WIRE_CTRL)|0x0100, TWO_WIRE_CTRL);
+
+                    /* initialize the PCM1796 DAC */
+                    i2c_write(devc, XONAR_STX_FRONTDAC, 16, mix_scale(75,8));
+                    i2c_write(devc, XONAR_STX_FRONTDAC, 17, mix_scale(75,8));
+                    i2c_write(devc, XONAR_STX_FRONTDAC, 18, 0x00|0x30|0x80); /*unmute, 24LSB, ATLD */
+                    i2c_write(devc, XONAR_STX_FRONTDAC, 19, 0); /*ATS1/FLT_SHARP*/
+                    i2c_write(devc, XONAR_STX_FRONTDAC, 20, 0); /*OS_64*/
+                    i2c_write(devc, XONAR_STX_FRONTDAC, 21, 0);
+
+                    /* initialize the codec 0 */
+                    ac97_hwinit(devc);
+		    break;
+
+	   case SUBID_XONAR_DS:
+			/* GPIO 8 = 1 output enabled 0 mute */
+			/* GPIO 7 = 1 lineout enabled 0 mute */
+			/* GPIO 6 = 1 mic select 0 line-in select */
+			/* GPIO 4 = 1 FP Headphone plugged in */
+			/* GPIO 3 = 1 FP Mic plugged in */
+
+                    /* setup for spi communication mode */
+                    OUTB(devc->osdev, (INB (devc->osdev, FUNCTION) & ~0x40)|0x32, FUNCTION);
+                    /* setup the GPIO direction */
+                    OUTW(devc->osdev, INW(devc->osdev, GPIO_CONTROL) | 0x1D0, GPIO_CONTROL);
+	            /* setup GPIO Pins */
+	            OUTW(devc->osdev, INW(devc->osdev, GPIO_DATA) | 0x1D0, GPIO_DATA);
+#if 1
+		    spi_write(devc, XONAR_DS_FRONTDAC, 0x17, 0x1); /* reset */
+	 	    spi_write(devc, XONAR_DS_FRONTDAC, 0x7, 0x90); /* dac control */
+	 	    spi_write(devc, XONAR_DS_FRONTDAC, 0x8, 0); /* unmute */
+	 	    spi_write(devc, XONAR_DS_FRONTDAC, 0xC, 0x22 ); /* powerdown hp */
+	 	    spi_write(devc, XONAR_DS_FRONTDAC, 0xD, 0x8); /* powerdown hp */
+	 	    spi_write(devc, XONAR_DS_FRONTDAC, 0xA, 0x1); /* LJust/16bit*/
+	 	    spi_write(devc, XONAR_DS_FRONTDAC, 0xB, 0x1); /* LJust/16bit*/
+
+	 	    spi_write(devc, XONAR_DS_SURRDAC, 0x1f, 1); /* reset */
+	 	    spi_write(devc, XONAR_DS_SURRDAC, 0x3, 0x1|0x20); /* LJust/24bit*/
+#endif
+		   break;
 
 	   default:
 		   /* SPI default for anything else, including the */
 		case SUBID_XONAR_STX:
 			portc->adc_type = ADEV_I2SADC2;
       			break;
-		default:
+		case SUBID_XONAR_DS:
+			portc->adc_type = ADEV_I2SADC1;
+			break;
+		default: 
 			portc->adc_type = ADEV_I2SADC1;
       			OUTB (devc->osdev, INB (devc->osdev, REC_ROUTING) | 0x18, REC_ROUTING);
 			break;
                 case SUBID_XONAR_STX:
                         portc->adc_type = ADEV_I2SADC2;
                         break;
+                case SUBID_XONAR_DS:
+                        portc->adc_type = ADEV_I2SADC1;
+                        break;
                 default:
                         portc->adc_type = ADEV_I2SADC1;
       			OUTB (devc->osdev, INB (devc->osdev, REC_ROUTING) | 0x18, REC_ROUTING);
     }
 
   /*
-   * Setup the default volumes to 75%
+   * Setup the default volumes to 90%
    */
-  default_vol = 0x4b4b;
+  default_vol = mix_scale(90,8)<<8|mix_scale(90,8);
+
   devc->playvol[0] =
     cmi8788_mixer_ioctl (devc->cmi_mixer_dev, first_dev,
 			 MIXER_WRITE (SOUND_MIXER_PCM), &default_vol);
           case SUBID_XONAR_STX:
             devc->chip_name = "Asus Xonar Essence STX (AV100)";
             break;
+	  case SUBID_XONAR_DS:
+	    devc->chip_name = "Asus Xonar DS (AV66)";
+	    break;
           default:
             devc->chip_name = "Asus Xonar (unknown)";
             sub_id = SUBID_GENERIC;

kernel/drv/oss_geode/.devices

 oss_geode	pci100b,503	National Semiconductor Geode SC1200
 oss_geode	pci1078,103	National Semiconductor Geode CS5530
-oss_geode	pci1022,2093	AMD Geode CS5536 (BETA)
+oss_geode	pci1022,2093	AMD Geode CS5536 

kernel/drv/oss_geode/oss_geode.c

   oss_device_t *osdev;
   int physaddr;
   void *linaddr;
-  unsigned char *f3bar;
   int irq;
   char *chip_name;
   oss_mutex_t mutex;
 
   geode_devc *devc = osdev->devc;
   geode_portc *portc;
-  int i, n;
+  int i, n, irqstat;
   int serviced = 0;
   unsigned int pos;
   int ptr;
 
+  irqstat = CS_READW (devc, 0x12);
+  if (irqstat & 3) /* either gpio or gpio wakeup */
+    {
+          CS_READL (devc, 0x00);
+          serviced = 1;
+    }
+
   for (i = 0; i < MAX_PORTC; i++)
     {
       portc = &devc->portc[i];
 
-      if (portc->trigger_bits & PCM_ENABLE_OUTPUT)
+      if ((portc->trigger_bits & PCM_ENABLE_OUTPUT) && (irqstat & 4))
 	{
 	  dmap_t *dmap;
 	  dmap = audio_engines[portc->audiodev]->dmap_out;
+	  CS_READB (devc, 0x21);	/* ack interrupt */
 	  pos = CS_READL (devc, 0x24);
 	  pos = (pos - devc->prdout_phys) / 8;
 	  ptr = pos;
 	}
 
 
-      if (portc->trigger_bits & PCM_ENABLE_INPUT)
+      if ((portc->trigger_bits & PCM_ENABLE_INPUT) && (irqstat & 8))
 	{
 	  dmap_t *dmap;
 
 
   geode_devc *devc = osdev->devc;
   geode_portc *portc;
-  int i, n;
+  int i;
   int serviced = 0;
-  unsigned int pos;
-  int ptr;
   int irqstat;
 
   irqstat = CS_READW (devc, 0x12);
 
+  if (irqstat & 3) /* either gpio or gpio wakeup */
+    {
+          CS_READL (devc, 0x00);
+          serviced = 1;
+    }
+
   for (i = 0; i < MAX_PORTC; i++)
     {
       portc = &devc->portc[i];
 
-      if (irqstat & 3) /* either gpio or gpio wakeup */
-	{
-	  CS_READB (devc, 0x00);
-	  serviced = 1;
-	}
-
-      /* always clear the bits, even if we're not gonna handle it, and mark
-	 it handled. otherwise, the kernel will find noone has handled the
-	 interrupt and therefore disable it */
-      if (irqstat & 4)
-	{
-	  CS_READB (devc, 0x21);
-	  serviced = 1;
-	}
-
-      if (irqstat & 8)
-	{
-	  CS_READB (devc, 0x29);
-	  serviced = 1;
-	}
-
       if ((portc->trigger_bits & PCM_ENABLE_OUTPUT) && (irqstat & 4))
-	{
-	  dmap_t *dmap;
-	  dmap = audio_engines[portc->audiodev]->dmap_out;
-
-	  pos = CS_READL (devc, 0x60);
-	  pos = pos - dmap->dmabuf_phys;
-	  ptr = pos;
-	  ptr--;
-
-	  if (ptr < 0)
-	    ptr = 0;
-	  ptr %= dmap->nfrags;
-
-	  n = 0;
-	  while (ptr != dmap_get_qhead (dmap) && n++ < dmap->nfrags)
-	    oss_audio_outputintr (portc->audiodev, 0);
-	}
+	  if (CS_READB (devc, 0x21) & 1)
+	    {
+		oss_audio_outputintr (portc->audiodev, 0);
+		serviced = 1;
+		
+	    }
 
 
       if ((portc->trigger_bits & PCM_ENABLE_INPUT) && (irqstat & 8))
-	{
-	  dmap_t *dmap;
-
-	  dmap = audio_engines[portc->audiodev]->dmap_in;
-
-	  pos = CS_READL (devc, 0x64);
-	  pos = pos - dmap->dmabuf_phys;
-	  ptr = pos;
-	  ptr--;
-
-	  if (ptr < 0)
-	    ptr = 0;
-	  ptr %= dmap->nfrags;
-
-	  n = 0;
-	  while (ptr != dmap_get_qtail (dmap) && n++ < dmap->nfrags)
-	    oss_audio_inputintr (portc->audiodev, 0);
-	}
+	  if (CS_READB (devc, 0x29) & 1)
+	    {
+	    	oss_audio_inputintr (portc->audiodev, 0);
+		serviced = 1;
+	    }
     }
   return serviced;
 }
 	      !(portc->trigger_bits & PCM_ENABLE_OUTPUT))
 	    {
 	      CS_WRITEB (devc, 0x20, 0x01);
-	      CS_WRITEB (devc, 0x21, 0x00);
 	      portc->trigger_bits |= PCM_ENABLE_OUTPUT;
 	    }
 	}
 	    {
 	      portc->audio_enabled &= ~PCM_ENABLE_OUTPUT;
 	      portc->trigger_bits &= ~PCM_ENABLE_OUTPUT;
-
+	      CS_WRITEB (devc, 0x20, 0x00);
 	      for (i = 0; i < 512; i++)
 		{
 		  devc->prdout[i].size = PRD_EOT;	/* Stop */
 	      !(portc->trigger_bits & PCM_ENABLE_INPUT))
 	    {
 	      CS_WRITEB (devc, 0x28, 0x09);
-	      CS_WRITEB (devc, 0x29, 0x00);
 	      portc->trigger_bits |= PCM_ENABLE_INPUT;
 	    }
 	}
 	      portc->audio_enabled &= ~PCM_ENABLE_INPUT;
 	      portc->trigger_bits &= ~PCM_ENABLE_INPUT;
 
+	      CS_WRITEB (devc, 0x28, 0x00);
 	      for (i = 0; i < 512; i++)
 		{
 		  devc->prdin[i].size = PRD_EOT;	/* Stop */
   geode_devc *devc = audio_engines[dev]->devc;
   geode_portc *portc = audio_engines[dev]->portc;
   dmap_t *dmap = audio_engines[dev]->dmap_in;
-  int i, stat;
+  int i;
   oss_native_word flags;
 
   MUTEX_ENTER_IRQDISABLE (devc->mutex, flags);
   ac97_recrate (&devc->ac97devc, portc->speed);
 
-#if 0
-  if (dmap->nfrags > 256)
-    {
-      dmap->nfrags = 256;
-      dmap->bytes_in_use = 256 * dmap->fragment_size;
-    }
-#endif
-
 
   /* clear out the prd table */
   memset (devc->prdin, 0, 512 * sizeof (PRD_rec));
 
-  /* Clear DMA Bus Master Status */
-  stat = CS_READB (devc, 0x29);
-  stat++;			/* To supress warnings by lint */
-
   /* Initialize PRD entries */
   for (i = 0; i < dmap->nfrags; i++)
     {
   geode_devc *devc = audio_engines[dev]->devc;
   geode_portc *portc = audio_engines[dev]->portc;
   dmap_t *dmap = audio_engines[dev]->dmap_out;
-  int i, stat;
+  int i;
   oss_native_word flags;
 
   MUTEX_ENTER_IRQDISABLE (devc->mutex, flags);
   ac97_playrate (&devc->ac97devc, portc->speed);
-#if 0
-  if (dmap->nfrags > 256)
-    {
-      dmap->nfrags = 256;
-      dmap->bytes_in_use = 256 * dmap->fragment_size;
-    }
-#endif
+
   /* clear out the PRD table */
   memset (devc->prdout, 0, 512 * sizeof (PRD_rec));
 
 
   CS_WRITEL (devc, 0x24, devc->prdout_phys);
 
-  /* Clear DMA Bus master status */
-  stat = CS_READB (devc, 0x21);
-  stat++;			/* To supress warnings by lint */
   portc->audio_enabled &= ~PCM_ENABLE_OUTPUT;
   portc->trigger_bits &= ~PCM_ENABLE_OUTPUT;
   MUTEX_EXIT_IRQRESTORE (devc->mutex, flags);
 
   devc->prdout_phys = phaddr;
 
-  /* VSA2 IRQ config method */
-  OUTW (devc->osdev, 0xFC53, 0xAC1C);
-  OUTW (devc->osdev, 0x108, 0xAC1C);
-  OUTW (devc->osdev, devc->irq, 0xAC1E);
+  if (devc->chip != AMD_CS5536_ID)
+    {
+  	/* VSA2 IRQ config method */
+  	OUTW (devc->osdev, 0xFC53, 0xAC1C);
+  	OUTW (devc->osdev, 0x108, 0xAC1C);
+  	OUTW (devc->osdev, devc->irq, 0xAC1E);
 
-  /* VSA1 IRQ config method */
-  OUTL (devc->osdev, 0x800090D0, 0x0CF8);
-  OUTL (devc->osdev, (devc->irq << 16) | 0xA00A, 0x0CFC);
-  oss_udelay (10000);
-
+  	/* VSA1 IRQ config method */
+  	OUTL (devc->osdev, 0x800090D0, 0x0CF8);
+  	OUTL (devc->osdev, (devc->irq << 16) | 0xA00A, 0x0CFC);
+  	oss_udelay (10000);
+   }
   /* Now configure the OSS devices */
 
   devc->mixer_dev =
 
       if (i == 0)
 	{
-	  strcpy (tmp_name, devc->chip_name);
+          if (devc->chip == AMD_CS5536_ID)
+                sprintf (tmp_name, "%s", "Geode CS5536");
+          else
+                sprintf (tmp_name, "%s", "Geode CS5530");
+
 	  caps = opts | ADEV_DUPLEX;
 	}
       else
 	{
-	  strcpy (tmp_name, devc->chip_name);
+          if (devc->chip == AMD_CS5536_ID)
+                sprintf (tmp_name, "%s", "Geode CS5536 (playback)");
+          else
+                sprintf (tmp_name, "%s", "Geode CS5530 (playback");
+
 	  caps = opts | ADEV_DUPLEX | ADEV_SHADOW;
 	}
 
   pci_read_config_dword (osdev, PCI_MEM_BASE_ADDRESS_0, &pci_ioaddr);
   pci_read_config_irq (osdev, PCI_INTERRUPT_LINE, &pci_irq_line);
 
-  pci_command |= PCI_COMMAND_MASTER | PCI_COMMAND_MEMORY;
+  pci_command |= PCI_COMMAND_MASTER | PCI_COMMAND_IO;
   pci_write_config_word (osdev, PCI_COMMAND, pci_command);
 
   if (pci_ioaddr == 0)
 	}
     }
 
-  /* Now map the Memory space - BROKEN for unknown reason. all input is valid
-     and all output from it can be interpreted as valid output from codec, it
-     still does only give write timeouts.
-     as the CS_* stuff works, this is worth being fixed only for following
-     good style.
-     when it's fixed, change stuff from this:
-     CS_READL (devc, 0x09)
-     to
-     PCI_READL (devc->osdev, devc->f3bar + 0x09) */
-  /* devc->linaddr = MAP_PCI_MEM (devc->osdev, 0, devc->physaddr, 128);
-  devc->f3bar = (unsigned char *) devc->linaddr; */
-
   return init_geode (devc);	/* Detected */
 }
 
   MUTEX_CLEANUP (devc->mutex);
   MUTEX_CLEANUP (devc->low_mutex);
 
-  /* - disabled - see end of oss_geode_attach for explanation
-  UNMAP_PCI_MEM (devc->osdev, 0, devc->physaddr, devc->linaddr, 128); */
-
   if (devc->prdin != NULL)
     CONTIG_FREE (devc->osdev, devc->prdin, 512 * sizeof (PRD_rec), devc->prdin_dma_handle);
   if (devc->prdout != NULL)

os_cmd/SunOS/ossdetect/ossdetect.c

 
 #ifdef sparc
   if (stat("/kernel/drv/sparcv9/oss_sadasupport", &st) != -1)
+    if (stat("/kernel/misc/sparcv9/audiosup", &st) != -1)
 #else
   if (stat("/kernel/drv/oss_sadasupport", &st) != -1)
+    if (stat("/kernel/misc/audiosup", &st) != -1)
 #endif
-  if (stat("/kernel/misc/audiosup", &st) != -1)
      {
   	check_conf ("oss_sadasupport", 1, "");
   	add_drv ("SADA emulation layer", "oss_sadasupport", "-m '* 0666 root sys'");

setup/SunOS/sbin/soundon

    do
 	/usr/sbin/modload $DRVPATH/$n >> $LOG 2>&1
 	/usr/sbin/modinfo|grep " $n " >> $LOG
+	/usr/sbin/devfsadm -i $n
    done
 else
 	echo /etc/oss/installed_drivers not found. >> $LOG