All of lore.kernel.org
 help / color / mirror / Atom feed
* 2.3.13 sound driver updates
@ 1999-08-12 19:20 Thomas Sailer
  0 siblings, 0 replies; only message in thread
From: Thomas Sailer @ 1999-08-12 19:20 UTC (permalink / raw)
  To: linux-sound

Changes:
- esssolo1: recording might now work, also MIDI shouldn't cause the driver
  to lock up hard
- es1371: (actually es1373) SPDIF output can now be enabled
- rest: module_init/__setup changes

Note: The makefiles-2.3.13 patch posted a moment ago to linux-kernel
is necessary for the drivers if built-in (modules work fine without)

Tom

--- drivers/sound/es1370.c	1999/08/10 11:13:08	0.26
+++ drivers/sound/es1370.c	1999/08/12 19:06:08
@@ -106,6 +106,7 @@
  *    03.08.99   0.26  adapt to Linus' new __setup/__initcall
  *                     added kernel command line option "es1370=joystick[,lineout[,micbias]]"
  *                     removed CONFIG_SOUND_ES1370_JOYPORT_BOOT kludge
+ *    12.08.99   0.27  module_init/__setup fixes
  *
  * some important things missing in Ensoniq documentation:
  *
@@ -1067,9 +1068,10 @@
                         current->state = TASK_RUNNING;
                         return -EBUSY;
                 }
-		tmo = (count * HZ) / dac1_samplerate[(s->ctrl & CTRL_WTSRSEL) >> CTRL_SH_WTSRSEL];
+		tmo = 3 * HZ * (count + s->dma_dac1.fragsize) / 2
+			/ dac1_samplerate[(s->ctrl & CTRL_WTSRSEL) >> CTRL_SH_WTSRSEL];
 		tmo >>= sample_shift[(s->sctrl & SCTRL_P1FMT) >> SCTRL_SH_P1FMT];
-		if (!schedule_timeout(tmo ? : 1) && tmo)
+		if (!schedule_timeout(tmo + 1))
 			DBG(printk(KERN_DEBUG "es1370: dma timed out??\n");)
         }
         remove_wait_queue(&s->dma_dac1.wait, &wait);
@@ -1102,9 +1104,10 @@
                         current->state = TASK_RUNNING;
                         return -EBUSY;
                 }
-		tmo = (count * HZ) / DAC2_DIVTOSR((s->ctrl & CTRL_PCLKDIV) >> CTRL_SH_PCLKDIV);
+		tmo = 3 * HZ * (count + s->dma_dac2.fragsize) / 2
+			/ DAC2_DIVTOSR((s->ctrl & CTRL_PCLKDIV) >> CTRL_SH_PCLKDIV);
 		tmo >>= sample_shift[(s->sctrl & SCTRL_P2FMT) >> SCTRL_SH_P2FMT];
-		if (!schedule_timeout(tmo ? : 1) && tmo)
+		if (!schedule_timeout(tmo + 1))
 			DBG(printk(KERN_DEBUG "es1370: dma timed out??\n");)
         }
         remove_wait_queue(&s->dma_dac2.wait, &wait);
@@ -2300,6 +2303,16 @@
 static int lineout[NR_DEVICE] = { 0, };
 static int micbias[NR_DEVICE] = { 0, };
 
+MODULE_PARM(joystick, "1-" __MODULE_STRING(NR_DEVICE) "i");
+MODULE_PARM_DESC(joystick, "if 1 enables joystick interface (still need separate driver)");
+MODULE_PARM(lineout, "1-" __MODULE_STRING(NR_DEVICE) "i");
+MODULE_PARM_DESC(lineout, "if 1 the LINE input is converted to LINE out");
+MODULE_PARM(micbias, "1-" __MODULE_STRING(NR_DEVICE) "i");
+MODULE_PARM_DESC(micbias, "sets the +5V bias for an electret microphone");
+
+MODULE_AUTHOR("Thomas M. Sailer, sailer@ife.ee.ethz.ch, hb9jnx@hb9w.che.eu");
+MODULE_DESCRIPTION("ES1370 AudioPCI Driver");
+
 /* --------------------------------------------------------------------- */
 
 static struct initvol {
@@ -2318,10 +2331,7 @@
 	{ SOUND_MIXER_WRITE_OGAIN, 0x4040 }
 };
 
-#ifndef MODULE
-static
-#endif
-int __init init_module(void)
+static int __init init_es1370(void)
 {
 	struct es1370_state *s;
 	struct pci_dev *pcidev = NULL;
@@ -2330,7 +2340,7 @@
 
 	if (!pci_present())   /* No PCI bus in this machine! */
 		return -ENODEV;
-	printk(KERN_INFO "es1370: version v0.26 time " __TIME__ " " __DATE__ "\n");
+	printk(KERN_INFO "es1370: version v0.27 time " __TIME__ " " __DATE__ "\n");
 	while (index < NR_DEVICE && 
 	       (pcidev = pci_find_device(PCI_VENDOR_ID_ENSONIQ, PCI_DEVICE_ID_ENSONIQ_ES1370, pcidev))) {
 		if (pcidev->resource[0].flags = 0 || 
@@ -2438,21 +2448,7 @@
 	return 0;
 }
 
-/* --------------------------------------------------------------------- */
-
-#ifdef MODULE
-
-MODULE_PARM(joystick, "1-" __MODULE_STRING(NR_DEVICE) "i");
-MODULE_PARM_DESC(joystick, "if 1 enables joystick interface (still need separate driver)");
-MODULE_PARM(lineout, "1-" __MODULE_STRING(NR_DEVICE) "i");
-MODULE_PARM_DESC(lineout, "if 1 the LINE input is converted to LINE out");
-MODULE_PARM(micbias, "1-" __MODULE_STRING(NR_DEVICE) "i");
-MODULE_PARM_DESC(micbias, "sets the +5V bias for an electret microphone");
-
-MODULE_AUTHOR("Thomas M. Sailer, sailer@ife.ee.ethz.ch, hb9jnx@hb9w.che.eu");
-MODULE_DESCRIPTION("ES1370 AudioPCI Driver");
-
-void cleanup_module(void)
+static void __exit cleanup_es1370(void)
 {
 	struct es1370_state *s;
 
@@ -2472,7 +2468,12 @@
 	printk(KERN_INFO "es1370: unloading\n");
 }
 
-#else /* MODULE */
+module_init(init_es1370);
+module_exit(cleanup_es1370);
+
+/* --------------------------------------------------------------------- */
+
+#ifndef MODULE
 
 /* format is: es1370=[joystick[,lineout[,micbias]]] */
 
@@ -2493,6 +2494,5 @@
 }
 
 __setup("es1370=", es1370_setup);
-__initcall(init_module);
 
 #endif /* MODULE */
--- drivers/sound/es1371.c	1999/08/10 11:13:46	0.14
+++ drivers/sound/es1371.c	1999/08/12 19:05:51
@@ -3,7 +3,7 @@
 /*
  *      es1371.c  --  Creative Ensoniq ES1371.
  *
- *      Copyright (C) 1998  Thomas Sailer (sailer@ife.ee.ethz.ch)
+ *      Copyright (C) 1998-1999  Thomas Sailer (sailer@ife.ee.ethz.ch)
  *
  *      This program is free software; you can redistribute it and/or modify
  *      it under the terms of the GNU General Public License as published by
@@ -71,6 +71,9 @@
  *    03.08.99   0.14  adapt to Linus' new __setup/__initcall
  *                     added kernel command line option "es1371=joystickaddr"
  *                     removed CONFIG_SOUND_ES1371_JOYPORT_BOOT kludge
+ *    10.08.99   0.15  (Re)added S/PDIF module option for cards revision >= 4.
+ *                     Initial version by Dave Platt <dplatt@snulbug.mtview.ca.us>.
+ *                     module_init/__setup fixes
  *
  */
 
@@ -145,6 +148,7 @@
 static const unsigned sample_size[] = { 1, 2, 2, 4 };
 static const unsigned sample_shift[] = { 0, 1, 1, 2 };
 
+#define CTRL_SPDIFEN_B  0x04000000
 #define CTRL_JOY_SHIFT  24
 #define CTRL_JOY_MASK   3
 #define CTRL_JOY_200    0x00000000  /* joystick base address */
@@ -180,6 +184,9 @@
 
 
 #define STAT_INTR       0x80000000  /* wired or of all interrupt bits */
+#define STAT_EN_SPDIF   0x00040000  /* enable S/PDIF circuitry */
+#define STAT_TS_SPDIF   0x00020000  /* test S/PDIF circuitry */
+#define STAT_TESTMODE   0x00010000  /* test ASIC */
 #define STAT_SYNC_ERR   0x00000100  /* 1 = codec sync error */
 #define STAT_VC         0x000000c0  /* CCB int source, 0ÚC1, 1ÚC2, 2­C, 3=undef */
 #define STAT_SH_VC      6
@@ -1481,9 +1488,9 @@
                         current->state = TASK_RUNNING;
                         return -EBUSY;
                 }
-		tmo = (count * HZ) / s->dac1rate;
+		tmo = 3 * HZ * (count + s->dma_dac1.fragsize) / 2 / s->dac1rate;
 		tmo >>= sample_shift[(s->sctrl & SCTRL_P1FMT) >> SCTRL_SH_P1FMT];
-		if (!schedule_timeout(tmo ? : 1) && tmo)
+		if (!schedule_timeout(tmo + 1))
 			printk(KERN_DEBUG "es1371: dma timed out??\n");
         }
         remove_wait_queue(&s->dma_dac1.wait, &wait);
@@ -1516,9 +1523,9 @@
                         current->state = TASK_RUNNING;
                         return -EBUSY;
                 }
-		tmo = (count * HZ) / s->dac2rate;
+		tmo = 3 * HZ * (count + s->dma_dac2.fragsize) / 2 / s->dac2rate;
 		tmo >>= sample_shift[(s->sctrl & SCTRL_P2FMT) >> SCTRL_SH_P2FMT];
-		if (!schedule_timeout(tmo ? : 1) && tmo)
+		if (!schedule_timeout(tmo + 1))
 			printk(KERN_DEBUG "es1371: dma timed out??\n");
         }
         remove_wait_queue(&s->dma_dac2.wait, &wait);
@@ -2697,6 +2704,15 @@
 #define NR_DEVICE 5
 
 static int joystick[NR_DEVICE] = { 0, };
+static int spdif[NR_DEVICE] = { 0, };
+
+MODULE_PARM(joystick, "1-" __MODULE_STRING(NR_DEVICE) "i");
+MODULE_PARM_DESC(joystick, "sets address and enables joystick interface (still need separate driver)");
+MODULE_PARM(spdif, "1-" __MODULE_STRING(NR_DEVICE) "i");
+MODULE_PARM_DESC(spdif, "if 1 the output is in S/PDIF digital mode");
+
+MODULE_AUTHOR("Thomas M. Sailer, sailer@ife.ee.ethz.ch, hb9jnx@hb9w.che.eu");
+MODULE_DESCRIPTION("ES1371 AudioPCI97 Driver");
 
 /* --------------------------------------------------------------------- */
 
@@ -2719,19 +2735,18 @@
 	{ SOUND_MIXER_WRITE_IGAIN, 0x4040 }
 };
 
-#ifndef MODULE
-static
-#endif
-int __init init_module(void)
+static int __init init_es1371(void)
 {
 	struct es1371_state *s;
 	struct pci_dev *pcidev = NULL;
 	mm_segment_t fs;
 	int i, val, val2, index = 0;
+	u8 revision;
+	unsigned cssr;
 
 	if (!pci_present())   /* No PCI bus in this machine! */
 		return -ENODEV;
-	printk(KERN_INFO "es1371: version v0.14 time " __TIME__ " " __DATE__ "\n");
+	printk(KERN_INFO "es1371: version v0.15 time " __TIME__ " " __DATE__ "\n");
 	while (index < NR_DEVICE && 
 	       (pcidev = pci_find_device(PCI_VENDOR_ID_ENSONIQ, PCI_DEVICE_ID_ENSONIQ_ES1371, pcidev))) {
 		if (pcidev->resource[0].flags = 0 || 
@@ -2784,6 +2799,18 @@
 			}
 		}
 		s->sctrl = 0;
+		cssr = 0;
+		/* check to see if s/pdif mode is being requested */
+		pci_read_config_byte(pcidev, PCI_REVISION_ID, &revision);
+		if (spdif[index]) {
+			if (revision >= 4) {
+				printk(KERN_INFO "es1371: enabling S/PDIF output\n");
+				cssr |= STAT_EN_SPDIF;
+				s->ctrl |= CTRL_SPDIFEN_B;
+			} else {
+				printk(KERN_ERR "es1371: revision %d does not support S/PDIF\n", revision);
+			}
+		}
 		/* initialize the chips */
 		outl(s->ctrl, s->io+ES1371_REG_CONTROL);
 		outl(s->sctrl, s->io+ES1371_REG_SERIAL_CONTROL);
@@ -2858,6 +2885,8 @@
 			mixer_ioctl(s, initvol[i].mixch, (unsigned long)&val);
 		}
 		set_fs(fs);
+		/* turn on S/PDIF output driver if requested */
+		outl(cssr, s->io+ES1371_REG_STATUS);
 		/* queue it for later freeing */
 		s->next = devs;
 		devs = s;
@@ -2883,17 +2912,7 @@
 	return 0;
 }
 
-/* --------------------------------------------------------------------- */
-
-#ifdef MODULE
-
-MODULE_PARM(joystick, "1-" __MODULE_STRING(NR_DEVICE) "i");
-MODULE_PARM_DESC(joystick, "sets address and enables joystick interface (still need separate driver)");
-
-MODULE_AUTHOR("Thomas M. Sailer, sailer@ife.ee.ethz.ch, hb9jnx@hb9w.che.eu");
-MODULE_DESCRIPTION("ES1371 AudioPCI97 Driver");
-
-void cleanup_module(void)
+static void __exit cleanup_es1371(void)
 {
 	struct es1371_state *s;
 
@@ -2913,23 +2932,27 @@
 	printk(KERN_INFO "es1371: unloading\n");
 }
 
-#else /* MODULE */
+module_init(init_es1371);
+module_exit(cleanup_es1371);
+
+/* --------------------------------------------------------------------- */
+
+#ifndef MODULE
 
 /* format is: es1371=[joystick] */
 
 static int __init es1371_setup(char *str)
 {
 	static unsigned __initdata nr_dev = 0;
-        int ints[11];
 
 	if (nr_dev >= NR_DEVICE)
 		return 0;
-	get_option(&str, &joystick[nr_dev]);
+	if (get_option(&str, &joystick[nr_dev]) = 2)
+		get_option(&str, &spdif[nr_dev]);
 	nr_dev++;
 	return 1;
 }
 
 __setup("es1371=", es1371_setup);
-__initcall(init_module);
 
 #endif /* MODULE */
--- drivers/sound/sonicvibes.c	1999/08/10 11:14:09	0.17
+++ drivers/sound/sonicvibes.c	1999/08/12 19:06:41
@@ -73,6 +73,7 @@
  *    28.06.99   0.16  Add pci_set_master
  *    03.08.99   0.17  adapt to Linus' new __setup/__initcall
  *                     added kernel command line options "sonicvibes=reverb" and "sonicvibesdmaio=dmaioaddr"
+ *    12.08.99   0.18  module_init/__setup fixes
  *
  */
 
@@ -1268,9 +1269,9 @@
                         current->state = TASK_RUNNING;
                         return -EBUSY;
                 }
-		tmo = (count * HZ) / s->ratedac;
+		tmo = 3 * HZ * (count + s->dma_dac.fragsize) / 2 / s->ratedac;
 		tmo >>= sample_shift[(s->fmt >> SV_CFMT_ASHIFT) & SV_CFMT_MASK];
-		if (!schedule_timeout(tmo ? : 1) && tmo)
+		if (!schedule_timeout(tmo + 1))
 			printk(KERN_DEBUG "sv: dma timed out??\n");
         }
         remove_wait_queue(&s->dma_dac.wait, &wait);
@@ -2297,6 +2298,19 @@
 
 static unsigned dmaio = 0xac00;
 
+MODULE_PARM(reverb, "1-" __MODULE_STRING(NR_DEVICE) "i");
+MODULE_PARM_DESC(reverb, "if 1 enables the reverb circuitry. NOTE: your card must have the reverb RAM");
+#if 0
+MODULE_PARM(wavetable, "1-" __MODULE_STRING(NR_DEVICE) "i");
+MODULE_PARM_DESC(wavetable, "if 1 the wavetable synth is enabled");
+#endif
+
+MODULE_PARM(dmaio, "i");
+MODULE_PARM_DESC(dmaio, "if the motherboard BIOS did not allocate DDMA io, allocate them starting at this address");
+
+MODULE_AUTHOR("Thomas M. Sailer, sailer@ife.ee.ethz.ch, hb9jnx@hb9w.che.eu");
+MODULE_DESCRIPTION("S3 SonicVibes Driver");
+
 /* --------------------------------------------------------------------- */
 
 static struct initvol {
@@ -2314,10 +2328,7 @@
 	{ SOUND_MIXER_WRITE_PCM, 0x4040 }
 };
 
-#ifndef MODULE
-static
-#endif
-int __init init_module(void)
+static int __init init_sonicvibes(void)
 {
 	struct sv_state *s;
 	struct pci_dev *pcidev = NULL;
@@ -2326,7 +2337,7 @@
 
 	if (!pci_present())   /* No PCI bus in this machine! */
 		return -ENODEV;
-	printk(KERN_INFO "sv: version v0.17 time " __TIME__ " " __DATE__ "\n");
+	printk(KERN_INFO "sv: version v0.18 time " __TIME__ " " __DATE__ "\n");
 #if 0
 	if (!(wavetable_mem = __get_free_pages(GFP_KERNEL, 20-PAGE_SHIFT)))
 		printk(KERN_INFO "sv: cannot allocate 1MB of contiguous nonpageable memory for wavetable data\n");
@@ -2499,24 +2510,7 @@
 	return 0;
 }
 
-/* --------------------------------------------------------------------- */
-
-#ifdef MODULE
-
-MODULE_PARM(reverb, "1-" __MODULE_STRING(NR_DEVICE) "i");
-MODULE_PARM_DESC(reverb, "if 1 enables the reverb circuitry. NOTE: your card must have the reverb RAM");
-#if 0
-MODULE_PARM(wavetable, "1-" __MODULE_STRING(NR_DEVICE) "i");
-MODULE_PARM_DESC(wavetable, "if 1 the wavetable synth is enabled");
-#endif
-
-MODULE_PARM(dmaio, "i");
-MODULE_PARM_DESC(dmaio, "if the motherboard BIOS did not allocate DDMA io, allocate them starting at this address");
-
-MODULE_AUTHOR("Thomas M. Sailer, sailer@ife.ee.ethz.ch, hb9jnx@hb9w.che.eu");
-MODULE_DESCRIPTION("S3 SonicVibes Driver");
-
-void cleanup_module(void)
+static void __exit cleanup_sonicvibes(void)
 {
 	struct sv_state *s;
 
@@ -2545,7 +2539,12 @@
 	printk(KERN_INFO "sv: unloading\n");
 }
 
-#else /* MODULE */
+module_init(init_sonicvibes);
+module_exit(cleanup_sonicvibes);
+
+/* --------------------------------------------------------------------- */
+
+#ifndef MODULE
 
 /* format is: sonicvibes=[reverb] sonicvibesdmaio=dmaioaddr */
 
@@ -2555,12 +2554,12 @@
 
 	if (nr_dev >= NR_DEVICE)
 		return 0;
-
-	(   (get_option(&str, &reverb   [nr_dev]) = 2)
 #if 0
-	 &&  get_option(&str, &wavetable[nr_dev])
+	if (get_option(&str, &reverb[nr_dev]) = 2)
+		get_option(&str, &wavetable[nr_dev]);
+#else
+	get_option(&str, &reverb[nr_dev]);
 #endif
-	};
 
 	nr_dev++;
 	return 1;
@@ -2568,16 +2567,14 @@
 
 static int __init sonicvibesdmaio_setup(char *str)
 {
-        int ints[11];
+        int io;
 
-        get_options(str, ints);
-	if (ints[0] >= 1)
-		dmaio = ints[1];
+	if (get_option(&str, &io))
+		dmaio = io;
 	return 1;
 }
 
 __setup("sonicvibes=", sonicvibes_setup);
 __setup("sonicvibesdmaio=", sonicvibesdmaio_setup);
-__initcall(init_module);
 
 #endif /* MODULE */
--- drivers/sound/esssolo1.c	1999/08/10 11:14:43	0.5
+++ drivers/sound/esssolo1.c	1999/08/12 17:57:24
@@ -39,7 +39,21 @@
  *    15.06.99   0.4   Fix bad allocation bug.
  *                     Thanks to Deti Fliegl <fliegl@in.tum.de>
  *    28.06.99   0.5   Add pci_set_master
- *
+ *    12.08.99   0.6   Fix MIDI UART crashing the driver
+ *                     Changed mixer semantics from OSS documented
+ *                     behaviour to OSS "code behaviour".
+ *                     Recording might actually work now.
+ *                     The real DDMA controller address register is at PCI config
+ *                     0x60, while the register at 0x18 is used as a placeholder
+ *                     register for BIOS address allocation. This register
+ *                     is supposed to be copied into 0x60, according
+ *                     to the Solo1 datasheet. When I do that, I can access
+ *                     the DDMA registers except the mask bit, which
+ *                     is stuck at 1. When I copy the contents of 0x18 +0x10
+ *                     to the DDMA base register, everything seems to work.
+ *                     The fun part is that the Windows Solo1 driver doesn't
+ *                     seem to do these tricks.
+ *                     Bugs remaining: plops and clicks when starting/stopping playback
  *
  */
 
@@ -69,6 +83,10 @@
 
 /* --------------------------------------------------------------------- */
 
+#undef OSS_DOCUMENTED_MIXER_SEMANTICS
+
+/* --------------------------------------------------------------------- */
+
 #ifndef PCI_VENDOR_ID_ESS
 #define PCI_VENDOR_ID_ESS         0x125d
 #endif
@@ -78,9 +96,12 @@
 
 #define SOLO1_MAGIC  ((PCI_VENDOR_ID_ESS<<16)|PCI_DEVICE_ID_ESS_SOLO1)
 
+#define DDMABASE_OFFSET           0x10    /* chip bug workaround kludge */
+#define DDMABASE_EXTENT           16
+
 #define IOBASE_EXTENT             16
 #define SBBASE_EXTENT             16
-#define VCBASE_EXTENT             16
+#define VCBASE_EXTENT             (DDMABASE_EXTENT+DDMABASE_OFFSET)
 #define MPUBASE_EXTENT            4
 #define GPBASE_EXTENT             4
 
@@ -98,16 +119,15 @@
 
 /* --------------------------------------------------------------------- */
 
-#define DEBUGREC
-
-/* --------------------------------------------------------------------- */
-
 struct solo1_state {
 	/* magic */
 	unsigned int magic;
 
-	/* we keep sb cards in a linked list */
+	/* we keep the cards in a linked list */
 	struct solo1_state *next;
+	
+	/* pcidev is needed to turn off the DDMA controller at driver shutdown */
+	struct pci_dev *pcidev;
 
 	/* soundcore stuff */
 	int dev_audio;
@@ -116,10 +136,10 @@
 	int dev_dmfm;
 
 	/* hardware resources */
-	unsigned long iobase, sbbase, vcbase, mpubase, gpbase; /* long for SPARC */
+	unsigned long iobase, sbbase, vcbase, ddmabase, mpubase, gpbase; /* long for SPARC */
 	unsigned int irq;
 
-	/* mixer registers; there is no HW readback */
+	/* mixer registers */
 	struct {
 		unsigned short vol[10];
 		unsigned int recsrc;
@@ -302,6 +322,8 @@
 	spin_lock_irqsave(&s->lock, flags);
 	if (!(s->ena & FMODE_WRITE) && (s->dma_dac.mapped || s->dma_dac.count > 0) && s->dma_dac.ready) {
 		s->ena |= FMODE_WRITE;
+		write_mixer(s, 0x78, 0x12);
+		udelay(10);
 		write_mixer(s, 0x78, 0x13);
 	}
 	spin_unlock_irqrestore(&s->lock, flags);
@@ -326,47 +348,24 @@
 	    && s->dma_adc.ready) {
 		s->ena |= FMODE_READ;
 		write_ctrl(s, 0xb8, 0xf);
-#ifdef DEBUGREC
+#if 0
 		printk(KERN_DEBUG "solo1: DMAbuffer: 0x%08lx\n", (long)s->dma_adc.rawbuf);
 		printk(KERN_DEBUG "solo1: DMA: mask: 0x%02x cnt: 0x%04x addr: 0x%08x  stat: 0x%02x\n", 
-		       inb(s->vcbase+0xf), inw(s->vcbase+4), inl(s->vcbase), inb(s->vcbase+8));
-#endif
-                outb(0, s->vcbase+0xd); /* master reset */
-#ifdef DEBUGREC
-		printk(KERN_DEBUG "solo1: DMA: mask: 0x%02x cnt: 0x%04x addr: 0x%08x  stat: 0x%02x (a. clr)\n", 
-		       inb(s->vcbase+0xf), inw(s->vcbase+4), inl(s->vcbase), inb(s->vcbase+8));
-#endif
-		outb(1, s->vcbase+0xf);  /* mask */
-#ifdef DEBUGREC
-		printk(KERN_DEBUG "solo1: DMA: mask: 0x%02x cnt: 0x%04x addr: 0x%08x  stat: 0x%02x (a. mask)\n", 
-		       inb(s->vcbase+0xf), inw(s->vcbase+4), inl(s->vcbase), inb(s->vcbase+8));
-#endif
-		outb(0x54/*0x14*/, s->vcbase+0xb);  /* DMA_MODE_READ | DMA_MODE_AUTOINIT */
-#ifdef DEBUGREC
-		printk(KERN_DEBUG "solo1: DMA: mask: 0x%02x cnt: 0x%04x addr: 0x%08x  stat: 0x%02x (a. wrmode)\n", 
-		       inb(s->vcbase+0xf), inw(s->vcbase+4), inl(s->vcbase), inb(s->vcbase+8));
-#endif
-		outl(virt_to_bus(s->dma_adc.rawbuf), s->vcbase);
-#ifdef DEBUGREC
-		printk(KERN_DEBUG "solo1: DMA: mask: 0x%02x cnt: 0x%04x addr: 0x%08x  stat: 0x%02x (a. wrbase)\n", 
-		       inb(s->vcbase+0xf), inw(s->vcbase+4), inl(s->vcbase), inb(s->vcbase+8));
-#endif
-		outw(s->dma_adc.dmasize-1, s->vcbase+4);
-#ifdef DEBUGREC
-		printk(KERN_DEBUG "solo1: DMA: mask: 0x%02x cnt: 0x%04x addr: 0x%08x  stat: 0x%02x (a. wrcnt)\n", 
-		       inb(s->vcbase+0xf), inw(s->vcbase+4), inl(s->vcbase), inb(s->vcbase+8));
-#endif
-		outb(0, s->vcbase+0xf);
-#ifdef DEBUGREC
-		printk(KERN_DEBUG "solo1: DMA: mask: 0x%02x cnt: 0x%04x addr: 0x%08x  stat: 0x%02x (a. clrmask)\n", 
-		       inb(s->vcbase+0xf), inw(s->vcbase+4), inl(s->vcbase), inb(s->vcbase+8));
+		       inb(s->ddmabase+0xf), inw(s->ddmabase+4), inl(s->ddmabase), inb(s->ddmabase+8));
 #endif
+                outb(0, s->ddmabase+0xd); /* master reset */
+		outb(1, s->ddmabase+0xf);  /* mask */
+		outb(0x54/*0x14*/, s->ddmabase+0xb);  /* DMA_MODE_READ | DMA_MODE_AUTOINIT */
+		outl(virt_to_bus(s->dma_adc.rawbuf), s->ddmabase);
+		outw(s->dma_adc.dmasize-1, s->ddmabase+4);
+		outb(0, s->ddmabase+0xf);
 	}
 	spin_unlock_irqrestore(&s->lock, flags);
-#ifdef DEBUGREC
-	printk(KERN_DEBUG "solo1: start DMA: reg B8: 0x%02x  DMAstat: 0x%02x  DMAcnt: 0x%04x  DMAmask: 0x%02x  SBstat: 0x%02x\n", 
-	       read_ctrl(s, 0xb8), inb(s->vcbase+8), inw(s->vcbase+4), inb(s->vcbase+0xf), inb(s->sbbase+0xc));
-
+#if 0
+	printk(KERN_DEBUG "solo1: start DMA: reg B8: 0x%02x  SBstat: 0x%02x\n"
+	       KERN_DEBUG "solo1: DMA: stat: 0x%02x  cnt: 0x%04x  mask: 0x%02x\n", 
+	       read_ctrl(s, 0xb8), inb(s->sbbase+0xc), 
+	       inb(s->ddmabase+8), inw(s->ddmabase+4), inb(s->ddmabase+0xf));
 	printk(KERN_DEBUG "solo1: A1: 0x%02x  A2: 0x%02x  A4: 0x%02x  A5: 0x%02x  A8: 0x%02x\n"  
 	       KERN_DEBUG "solo1: B1: 0x%02x  B2: 0x%02x  B4: 0x%02x  B7: 0x%02x  B8: 0x%02x  B9: 0x%02x\n",
 	       read_ctrl(s, 0xa1), read_ctrl(s, 0xa2), read_ctrl(s, 0xa4), read_ctrl(s, 0xa5), read_ctrl(s, 0xa8), 
@@ -456,16 +455,16 @@
 	va = virt_to_bus(s->dma_adc.rawbuf);
 	if ((va & ~((1<<24)-1)))
 		panic("solo1: buffer above 16M boundary");
-	outb(0, s->vcbase+0xd);  /* clear */
-	outb(1, s->vcbase+0xf); /* mask */
-	//outb(0, s->vcbase+8);  /* enable (enable is active low!) */
-	outb(0x54, s->vcbase+0xb);  /* DMA_MODE_READ | DMA_MODE_AUTOINIT */
-	outl(va, s->vcbase);
-	outw(s->dma_adc.dmasize-1, s->vcbase+4);
+	outb(0, s->ddmabase+0xd);  /* clear */
+	outb(1, s->ddmabase+0xf); /* mask */
+	/*outb(0, s->ddmabase+8);*/  /* enable (enable is active low!) */
+	outb(0x54, s->ddmabase+0xb);  /* DMA_MODE_READ | DMA_MODE_AUTOINIT */
+	outl(va, s->ddmabase);
+	outw(s->dma_adc.dmasize-1, s->ddmabase+4);
 	c = - s->dma_adc.fragsamples;
 	write_ctrl(s, 0xa4, c);
 	write_ctrl(s, 0xa5, c >> 8);
-	outb(0, s->vcbase+0xf);
+	outb(0, s->ddmabase+0xf);
 	s->dma_adc.ready = 1;
 	return 0;
 }
@@ -513,12 +512,12 @@
 
 	/* update ADC pointer */
 	if (s->ena & FMODE_READ) {
-		hwptr = (s->dma_adc.dmasize - 1 - inw(s->vcbase+4)) % s->dma_adc.dmasize;
+		hwptr = (s->dma_adc.dmasize - 1 - inw(s->ddmabase+4)) % s->dma_adc.dmasize;
                 diff = (s->dma_adc.dmasize + hwptr - s->dma_adc.hwptr) % s->dma_adc.dmasize;
                 s->dma_adc.hwptr = hwptr;
 		s->dma_adc.total_bytes += diff;
 		s->dma_adc.count += diff;
-#ifdef DEBUGREC
+#if 0
 		printk(KERN_DEBUG "solo1: rd: hwptr %u swptr %u dmasize %u count %u\n",
 		       s->dma_adc.hwptr, s->dma_adc.swptr, s->dma_adc.dmasize, s->dma_adc.count);
 #endif
@@ -633,16 +632,28 @@
 		SOUND_MASK_MIC, SOUND_MASK_MIC, SOUND_MASK_CD, SOUND_MASK_VOLUME,
 		SOUND_MASK_MIC, 0, SOUND_MASK_LINE, 0
 	};
-	static const unsigned char mixtable[SOUND_MIXER_NRDEVICES] = {
-		[SOUND_MIXER_PCM]    = 0x7c,   /* voice */
-		[SOUND_MIXER_SYNTH]  = 0x36,   /* FM */
-		[SOUND_MIXER_CD]     = 0x38,   /* CD */
-		[SOUND_MIXER_LINE]   = 0x3e,   /* Line */
-		[SOUND_MIXER_LINE1]  = 0x3a,   /* AUX */
-		[SOUND_MIXER_MIC]    = 0x1a,   /* Mic */
-		[SOUND_MIXER_LINE2]  = 0x6d    /* Mono in */
+	static const unsigned char mixtable1[SOUND_MIXER_NRDEVICES] = {
+		[SOUND_MIXER_PCM]     = 1,   /* voice */
+		[SOUND_MIXER_SYNTH]   = 2,   /* FM */
+		[SOUND_MIXER_CD]      = 3,   /* CD */
+		[SOUND_MIXER_LINE]    = 4,   /* Line */
+		[SOUND_MIXER_LINE1]   = 5,   /* AUX */
+		[SOUND_MIXER_MIC]     = 6,   /* Mic */
+		[SOUND_MIXER_LINE2]   = 7,   /* Mono in */
+		[SOUND_MIXER_SPEAKER] = 8,   /* Speaker */
+		[SOUND_MIXER_RECLEV]  = 9,   /* Recording level */
+		[SOUND_MIXER_VOLUME]  = 10   /* Master Volume */
 	};
-	unsigned char l, r, rl, rr;
+	static const unsigned char mixreg[] = {
+		0x7c,   /* voice */
+		0x36,   /* FM */
+		0x38,   /* CD */
+		0x3e,   /* Line */
+		0x3a,   /* AUX */
+		0x1a,   /* Mic */
+		0x6d    /* Mono in */
+	};
+	unsigned char l, r, rl, rr, vidx;
 	int i, val;
 
 	VALIDATE_STATE(s);
@@ -657,16 +668,6 @@
 		val = (read_mixer(s, 0x7d) & 0x08) ? 1 : 0;
 		return put_user(val, (int *)arg);
 	}
-	if (cmd = SOUND_MIXER_PRIVATE1) {
-		/* enable/disable/query mixer preamp */
-		get_user_ret(val, (int *)arg, -EFAULT);
-		if (val != -1) {
-			val = val ? 0xff : 0xf7;
-			write_mixer(s, 0x7d, (read_mixer(s, 0x7d) | 0x08) & val);
-		}
-		val = (read_mixer(s, 0x7d) & 0x08) ? 1 : 0;
-		return put_user(val, (int *)arg);
-	}
 	if (cmd = SOUND_MIXER_PRIVATE2) {
 		/* enable/disable/query spatializer */
 		get_user_ret(val, (int *)arg, -EFAULT);
@@ -720,36 +721,11 @@
                 case SOUND_MIXER_CAPS:
 			return put_user(SOUND_CAP_EXCL_INPUT, (int *)arg);
 
-		case SOUND_MIXER_VOLUME:
-			rl = read_mixer(s, 0x60);
-			rr = read_mixer(s, 0x62);
-			l = (rl * 3 + 11) / 2;
-			if (rl & 0x40)
-				l = 0;
-			r = (rr * 3 + 11) / 2;
-			if (rr & 0x40)
-				r = 0;
-			return put_user((((unsigned int)r) << 8) | l, (int *)arg);
-
-		case SOUND_MIXER_SPEAKER:
-			rl = read_mixer(s, 0x3c);
-			l = (rl & 7) * 14 + 2;
-			return put_user(l * 0x101, (int *)arg);
-
-		case SOUND_MIXER_RECLEV:
-			rl = read_ctrl(s, 0xb4);
-			r = ((rl & 0xf) * 13 + 5) / 2;
-			l = (((rl >> 4) & 0xf) * 13 + 5) / 2;
-			return put_user((((unsigned int)r) << 8) | l, (int *)arg);
-
 		default:
 			i = _IOC_NR(cmd);
-                        if (i >= SOUND_MIXER_NRDEVICES || !mixtable[i])
+                        if (i >= SOUND_MIXER_NRDEVICES || !(vidx = mixtable1[i]))
                                 return -EINVAL;
-			rl = read_mixer(s, mixtable[i]);
-			r = ((rl & 0xf) * 13 + 5) / 2;
-			l = (((rl >> 4) & 0xf) * 13 + 5) / 2;
-			return put_user((((unsigned int)r) << 8) | l, (int *)arg);
+			return put_user(s->mix.vol[vidx-1], (int *)arg);
 		}
 	}
         if (_IOC_DIR(cmd) != (_IOC_READ|_IOC_WRITE)) 
@@ -757,21 +733,21 @@
 	s->mix.modcnt++;
 	switch (_IOC_NR(cmd)) {
 	case SOUND_MIXER_RECSRC: /* Arg contains a bit for each recording source */
-
-	{
-		static const unsigned char regs[] = {
-			0x1c, 0x1a, 0x36, 0x38, 0x3a, 0x3c, 0x3e, 0x60, 0x62, 0x6d, 0x7c
-		};
-		int i;
-
-		for (i = 0; i < sizeof(regs); i++)
-			printk(KERN_DEBUG "solo1: mixer reg 0x%02x: 0x%02x\n",
-			       regs[i], read_mixer(s, regs[i]));
-		printk(KERN_DEBUG "solo1: ctrl reg 0x%02x: 0x%02x\n",
-		       0xb4, read_ctrl(s, 0xb4));
-	} 
-
-		get_user_ret(val, (int *)arg, -EFAULT);
+#if 0
+	        {
+			static const unsigned char regs[] = {
+				0x1c, 0x1a, 0x36, 0x38, 0x3a, 0x3c, 0x3e, 0x60, 0x62, 0x6d, 0x7c
+			};
+			int i;
+			
+			for (i = 0; i < sizeof(regs); i++)
+				printk(KERN_DEBUG "solo1: mixer reg 0x%02x: 0x%02x\n",
+				       regs[i], read_mixer(s, regs[i]));
+			printk(KERN_DEBUG "solo1: ctrl reg 0x%02x: 0x%02x\n",
+			       0xb4, read_ctrl(s, 0xb4));
+		}
+#endif
+	        get_user_ret(val, (int *)arg, -EFAULT);
                 i = hweight32(val);
                 if (i = 0)
                         return 0;
@@ -810,7 +786,12 @@
 		}
 		write_mixer(s, 0x60, rl);
 		write_mixer(s, 0x62, rr);
-		return put_user((((unsigned int)r) << 8) | l, (int *)arg);
+#ifdef OSS_DOCUMENTED_MIXER_SEMANTICS
+                s->mix.vol[9] = ((unsigned int)r << 8) | l;
+#else
+                s->mix.vol[9] = val;
+#endif
+		return put_user(s->mix.vol[9], (int *)arg);
 
 	case SOUND_MIXER_SPEAKER:
 		get_user_ret(val, (int *)arg, -EFAULT);
@@ -822,7 +803,12 @@
 		rl = (l - 2) / 14;
 		l = rl * 14 + 2;
 		write_mixer(s, 0x3c, rl);
-		return put_user(l * 0x101, (int *)arg);
+#ifdef OSS_DOCUMENTED_MIXER_SEMANTICS
+                s->mix.vol[7] = l * 0x101;
+#else
+                s->mix.vol[7] = val;
+#endif
+		return put_user(s->mix.vol[7], (int *)arg);
 
 	case SOUND_MIXER_RECLEV:
 		get_user_ret(val, (int *)arg, -EFAULT);
@@ -841,11 +827,16 @@
 		r = (rl * 13 + 5) / 2;
 		l = (rr * 13 + 5) / 2;
 		write_ctrl(s, 0xb4, (rl << 4) | rr);
-		return put_user((((unsigned int)r) << 8) | l, (int *)arg);
+#ifdef OSS_DOCUMENTED_MIXER_SEMANTICS
+                s->mix.vol[8] = ((unsigned int)r << 8) | l;
+#else
+                s->mix.vol[8] = val;
+#endif
+		return put_user(s->mix.vol[8], (int *)arg);
 
 	default:
 		i = _IOC_NR(cmd);
-		if (i >= SOUND_MIXER_NRDEVICES || !mixtable[i])
+		if (i >= SOUND_MIXER_NRDEVICES || !(vidx = mixtable1[i]))
 			return -EINVAL;
 		get_user_ret(val, (int *)arg, -EFAULT);
 		l = (val << 1) & 0x1fe;
@@ -862,8 +853,13 @@
 		rr = (r - 5) / 13;
 		r = (rl * 13 + 5) / 2;
 		l = (rr * 13 + 5) / 2;
-		write_mixer(s, mixtable[i], (rl << 4) | rr);
-		return put_user((((unsigned int)r) << 8) | l, (int *)arg);
+		write_mixer(s, mixreg[vidx-1], (rl << 4) | rr);
+#ifdef OSS_DOCUMENTED_MIXER_SEMANTICS
+                s->mix.vol[vidx-1] = ((unsigned int)r << 8) | l;
+#else
+                s->mix.vol[vidx-1] = val;
+#endif
+		return put_user(s->mix.vol[vidx-1], (int *)arg);
 	}
 }
 
@@ -919,10 +915,8 @@
 	NULL,  /* fsync */
 	NULL,  /* fasync */
 	NULL,  /* check_media_change */
-#if 0
 	NULL,  /* revalidate */
 	NULL,  /* lock */
-#endif
 };
 
 /* --------------------------------------------------------------------- */
@@ -931,7 +925,8 @@
 {
 	DECLARE_WAITQUEUE(wait, current);
 	unsigned long flags;
-	int count, tmo;
+	int count;
+	unsigned tmo;
 	
 	if (s->dma_dac.mapped)
 		return 0;
@@ -950,12 +945,12 @@
                         current->state = TASK_RUNNING;
                         return -EBUSY;
                 }
-		tmo = (count * HZ) / s->rate;
+		tmo = 3 * HZ * (count + s->dma_dac.fragsize) / 2 / s->rate;
 		if (s->fmt & (AFMT_S16_LE | AFMT_U16_LE))
 			tmo >>= 1;
 		if (s->channels > 1)
 			tmo >>= 1;
-                if (!schedule_timeout(tmo ? : 1) && tmo)
+                if (!schedule_timeout(tmo + 1))
                         printk(KERN_DEBUG "solo1: dma timed out??\n");
         }
         remove_wait_queue(&s->dma_dac.wait, &wait);
@@ -996,7 +991,7 @@
 			cnt = count;
 #ifdef DEBUGREC
 		printk(KERN_DEBUG "solo1_read: reg B8: 0x%02x  DMAstat: 0x%02x  DMAcnt: 0x%04x  SBstat: 0x%02x  cnt: %u\n", 
-		       read_ctrl(s, 0xb8), inb(s->vcbase+8), inw(s->vcbase+4), inb(s->sbbase+0xc), cnt);
+		       read_ctrl(s, 0xb8), inb(s->ddmabase+8), inw(s->ddmabase+4), inb(s->sbbase+0xc), cnt);
 #endif
 		if (cnt <= 0) {
 			start_adc(s);
@@ -1007,12 +1002,10 @@
 			       KERN_DEBUG "solo1_read: SBstat: 0x%02x  cnt: %u\n",
 			       read_ctrl(s, 0xa1), read_ctrl(s, 0xa2), read_ctrl(s, 0xa4), read_ctrl(s, 0xa5), read_ctrl(s, 0xa8), 
 			       read_ctrl(s, 0xb1), read_ctrl(s, 0xb2), read_ctrl(s, 0xb7), read_ctrl(s, 0xb8), read_ctrl(s, 0xb9), 
-			       inl(s->vcbase), inw(s->vcbase+4), inb(s->vcbase+8), inb(s->vcbase+15), inb(s->sbbase+0xc), cnt);
+			       inl(s->ddmabase), inw(s->ddmabase+4), inb(s->ddmabase+8), inb(s->ddmabase+15), inb(s->sbbase+0xc), cnt);
 #endif
-			if (inb(s->vcbase+15) & 1) {
+			if (inb(s->ddmabase+15) & 1)
 				printk(KERN_ERR "solo1: cannot start recording, DDMA mask bit stuck at 1\n");
-				return -EIO;
-			}
 			if (file->f_flags & O_NONBLOCK)
 				return ret ? ret : -EAGAIN;
 			interruptible_sleep_on(&s->dma_adc.wait);
@@ -1023,7 +1016,7 @@
 			       KERN_DEBUG "solo1_read: SBstat: 0x%02x  cnt: %u\n",
 			       read_ctrl(s, 0xa1), read_ctrl(s, 0xa2), read_ctrl(s, 0xa4), read_ctrl(s, 0xa5), read_ctrl(s, 0xa8), 
 			       read_ctrl(s, 0xb1), read_ctrl(s, 0xb2), read_ctrl(s, 0xb7), read_ctrl(s, 0xb8), read_ctrl(s, 0xb9), 
-			       inl(s->vcbase), inw(s->vcbase+4), inb(s->vcbase+8), inb(s->vcbase+15), inb(s->sbbase+0xc), cnt);
+			       inl(s->ddmabase), inw(s->ddmabase+4), inb(s->ddmabase+8), inb(s->ddmabase+15), inb(s->sbbase+0xc), cnt);
 #endif
 			if (signal_pending(current))
 				return ret ? ret : -ERESTARTSYS;
@@ -1042,7 +1035,7 @@
 		start_adc(s);
 #ifdef DEBUGREC
 		printk(KERN_DEBUG "solo1_read: reg B8: 0x%02x  DMAstat: 0x%02x  DMAcnt: 0x%04x  SBstat: 0x%02x\n", 
-		       read_ctrl(s, 0xb8), inb(s->vcbase+8), inw(s->vcbase+4), inb(s->sbbase+0xc));
+		       read_ctrl(s, 0xb8), inb(s->ddmabase+8), inw(s->ddmabase+4), inb(s->sbbase+0xc));
 #endif
 	}
 	return ret;
@@ -1304,7 +1297,7 @@
 				if (!s->dma_adc.ready && (ret = prog_dmabuf_adc(s)))
 					return ret;
 				start_adc(s);
-				if (inb(s->vcbase+15) & 1)
+				if (inb(s->ddmabase+15) & 1)
 					printk(KERN_ERR "solo1: cannot start recording, DDMA mask bit stuck at 1\n");
 			} else
 				stop_adc(s);
@@ -1466,8 +1459,8 @@
 	}
 	if (file->f_mode & FMODE_READ) {
 		stop_adc(s);
-		outb(1, s->vcbase+0xf); /* mask DMA channel */
-		//outb(0, s->vcbase+0xd); /* DMA master clear */
+		outb(1, s->ddmabase+0xf); /* mask DMA channel */
+		outb(0, s->ddmabase+0xd); /* DMA master clear */
 		dealloc_dmabuf(&s->dma_adc);
 	}
 	s->open_mode &= ~(FMODE_READ | FMODE_WRITE);
@@ -1533,10 +1526,8 @@
 	NULL,  /* fsync */
 	NULL,  /* fasync */
 	NULL,  /* check_media_change */
-#if 0
 	NULL,  /* revalidate */
 	NULL,  /* lock */
-#endif
 };
 
 /* --------------------------------------------------------------------- */
@@ -1550,7 +1541,7 @@
 	if (!(s->mpubase))
 		return;
 	wake = 0;
-	while (inb(s->mpubase+1) & 0x80) {
+	while (!(inb(s->mpubase+1) & 0x80)) {
 		ch = inb(s->mpubase);
 		if (s->midi.icnt < MIDIINBUF) {
 			s->midi.ibuf[s->midi.iwr] = ch;
@@ -1562,7 +1553,7 @@
 	if (wake)
 		wake_up(&s->midi.iwait);
 	wake = 0;
-	while ((inb(s->mpubase+1) & 0x40) && s->midi.ocnt > 0) {
+	while (!(inb(s->mpubase+1) & 0x40) && s->midi.ocnt > 0) {
 		outb(s->midi.obuf[s->midi.ord], s->mpubase);
 		s->midi.ord = (s->midi.ord + 1) % MIDIOUTBUF;
 		s->midi.ocnt--;
@@ -1577,22 +1568,12 @@
 {
         struct solo1_state *s = (struct solo1_state *)dev_id;
 	unsigned int intsrc;
-
-	static unsigned lim = 0;
 	
 	/* fastpath out, to ease interrupt sharing */
 	intsrc = inb(s->iobase+7); /* get interrupt source(s) */
 	if (!intsrc)
 		return;
 	(void)inb(s->sbbase+0xe);  /* clear interrupt */
-#ifdef DEBUGREC
-	if (intsrc & 0x10 && lim < 20) {
-		lim++;
-		printk(KERN_DEBUG "solo1: audio1int reg B8: 0x%02x  DMAstat: 0x%02x  DMAcnt: 0x%04x  SBstat: 0x%02x\n", 
-		       read_ctrl(s, 0xb8), inb(s->vcbase+8), inw(s->vcbase+4), inb(s->sbbase+0xc));
-	}
-	//printk(KERN_DEBUG "solo1: interrupt 0x%02x\n", intsrc);
-#endif
 	spin_lock(&s->lock);
 	/* clear audio interrupts first */
 	if (intsrc & 0x20)
@@ -1849,10 +1830,8 @@
 	NULL,  /* fsync */
 	NULL,  /* fasync */
 	NULL,  /* check_media_change */
-#if 0
 	NULL,  /* revalidate */
 	NULL,  /* lock */
-#endif
 };
 
 /* --------------------------------------------------------------------- */
@@ -2025,10 +2004,8 @@
 	NULL,  /* fsync */
 	NULL,  /* fasync */
 	NULL,  /* check_media_change */
-#if 0
 	NULL,  /* revalidate */
 	NULL,  /* lock */
-#endif
 };
 
 /* --------------------------------------------------------------------- */
@@ -2060,11 +2037,10 @@
 	struct pci_dev *pcidev = NULL;
 	mm_segment_t fs;
 	int i, val, index = 0;
-	u16 ddmabase;
 
 	if (!pci_present())   /* No PCI bus in this machine! */
 		return -ENODEV;
-	printk(KERN_INFO "solo1: version v0.5 time " __TIME__ " " __DATE__ "\n");
+	printk(KERN_INFO "solo1: version v0.6 time " __TIME__ " " __DATE__ "\n");
 	while (index < NR_DEVICE && 
 	       (pcidev = pci_find_device(PCI_VENDOR_ID_ESS, PCI_DEVICE_ID_ESS_SOLO1, pcidev))) {
 		if (pcidev->resource[0].start = 0 ||
@@ -2090,35 +2066,32 @@
 		init_waitqueue_head(&s->midi.owait);
 		init_MUTEX(&s->open_sem);
 		s->magic = SOLO1_MAGIC;
+		s->pcidev = pcidev;
 		s->iobase = pcidev->resource[0].start;
 		s->sbbase = pcidev->resource[1].start;
 		s->vcbase = pcidev->resource[2].start;
+		s->ddmabase = s->vcbase + DDMABASE_OFFSET;
 		s->mpubase = pcidev->resource[3].start;
 		s->gpbase = pcidev->resource[4].start;
 		s->irq = pcidev->irq;
 		if (check_region(s->iobase, IOBASE_EXTENT) ||
 		    check_region(s->sbbase, SBBASE_EXTENT) ||
-		    check_region(s->vcbase, VCBASE_EXTENT) ||
+		    check_region(s->ddmabase, DDMABASE_EXTENT) ||
 		    check_region(s->mpubase, MPUBASE_EXTENT)) {
 			printk(KERN_ERR "solo1: io ports in use\n");
 			goto err_region;
 		}
 		request_region(s->iobase, IOBASE_EXTENT, "ESS Solo1");
 		request_region(s->sbbase, SBBASE_EXTENT, "ESS Solo1");
-		request_region(s->vcbase, VCBASE_EXTENT, "ESS Solo1");
+		request_region(s->ddmabase, DDMABASE_EXTENT, "ESS Solo1");
 		request_region(s->mpubase, MPUBASE_EXTENT, "ESS Solo1");
 		if (request_irq(s->irq, solo1_interrupt, SA_SHIRQ, "ESS Solo1", s)) {
 			printk(KERN_ERR "solo1: irq %u in use\n", s->irq);
 			goto err_irq;
 		}
 		/* initialize DDMA base address */
-		/* use PCI config reg, and not vcbase, we need the bus view */
-		pci_read_config_word(pcidev, 0x18, &ddmabase);
-		pci_write_config_word(pcidev, 0x60, (ddmabase & (~0xf)) | 1);
-#ifdef DEBUGREC
-		printk(KERN_DEBUG "solo1: DMA: mask: 0x%02x cnt: 0x%04x addr: 0x%08x  stat: 0x%02x\n", 
-		       inb(s->vcbase+0xf), inw(s->vcbase+4), inl(s->vcbase), inb(s->vcbase+8));
-#endif
+		printk(KERN_DEBUG "solo1: ddma base address: 0x%lx\n", s->ddmabase);
+		pci_write_config_word(pcidev, 0x60, (s->ddmabase & (~0xf)) | 1);
 		/* set DMA policy to DDMA, IRQ emulation off (CLKRUN disabled for now) */
 		pci_write_config_dword(pcidev, 0x50, 0);
 		/* disable legacy audio address decode */
@@ -2147,21 +2120,9 @@
 		write_mixer(s, 0x52, 0);
 		write_mixer(s, 0x14, 0);  /* DAC1 minimum volume */
 		write_mixer(s, 0x71, 0x20); /* enable new 0xA1 reg format */
-#ifdef DEBUGREC
-		printk(KERN_DEBUG "solo1: DMA: mask: 0x%02x cnt: 0x%04x addr: 0x%08x  stat: 0x%02x\n", 
-		       inb(s->vcbase+0xf), inw(s->vcbase+4), inl(s->vcbase), inb(s->vcbase+8));
-#endif
-		outb(0, s->vcbase+0xd); /* DMA master clear */
-#ifdef DEBUGREC
-		printk(KERN_DEBUG "solo1: DMA: mask: 0x%02x cnt: 0x%04x addr: 0x%08x  stat: 0x%02x\n", 
-		       inb(s->vcbase+0xf), inw(s->vcbase+4), inl(s->vcbase), inb(s->vcbase+8));
-#endif
-		outb(1, s->vcbase+0xf); /* mask channel */
-#ifdef DEBUGREC
-		printk(KERN_DEBUG "solo1: DMA: mask: 0x%02x cnt: 0x%04x addr: 0x%08x  stat: 0x%02x\n", 
-		       inb(s->vcbase+0xf), inw(s->vcbase+4), inl(s->vcbase), inb(s->vcbase+8));
-#endif
-		//outb(0, s->vcbase+0x8); /* enable controller (enable is low active!!) */
+		outb(0, s->ddmabase+0xd); /* DMA master clear */
+		outb(1, s->ddmabase+0xf); /* mask channel */
+		/*outb(0, s->ddmabase+0x8);*/ /* enable controller (enable is low active!!) */
 
 		pci_set_master(pcidev);  /* enable bus mastering */
 		
@@ -2173,6 +2134,8 @@
 			val = initvol[i].vol;
 			mixer_ioctl(s, initvol[i].mixch, (unsigned long)&val);
 		}
+		val = 1; /* enable mic preamp */
+		mixer_ioctl(s, SOUND_MIXER_PRIVATE1, (unsigned long)&val);
 		set_fs(fs);
 		/* queue it for later freeing */
 		s->next = devs;
@@ -2192,7 +2155,7 @@
 	err_irq:
 		release_region(s->iobase, IOBASE_EXTENT);
 		release_region(s->sbbase, SBBASE_EXTENT);
-		release_region(s->vcbase, VCBASE_EXTENT);
+		release_region(s->ddmabase, DDMABASE_EXTENT);
 		release_region(s->mpubase, MPUBASE_EXTENT);
 	err_region:
 		kfree_s(s, sizeof(struct solo1_state));
@@ -2215,13 +2178,14 @@
 		devs = devs->next;
 		/* stop DMA controller */
 		outb(0, s->iobase+6);
-		outb(0, s->vcbase+0xd); /* DMA master clear */
+		outb(0, s->ddmabase+0xd); /* DMA master clear */
 		outb(3, s->sbbase+6); /* reset sequencer and FIFO */
 		synchronize_irq();
+		pci_write_config_word(s->pcidev, 0x60, 0); /* turn off DDMA controller address space */
 		free_irq(s->irq, s);
 		release_region(s->iobase, IOBASE_EXTENT);
 		release_region(s->sbbase, SBBASE_EXTENT);
-		release_region(s->vcbase, VCBASE_EXTENT);
+		release_region(s->ddmabase, DDMABASE_EXTENT);
 		release_region(s->mpubase, MPUBASE_EXTENT);
 		unregister_sound_dsp(s->dev_audio);
 		unregister_sound_mixer(s->dev_mixer);

^ permalink raw reply	[flat|nested] only message in thread

only message in thread, other threads:[~1999-08-12 19:20 UTC | newest]

Thread overview: (only message) (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
1999-08-12 19:20 2.3.13 sound driver updates Thomas Sailer

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.