From alsa-devel-owner@alsa.jcu.cz  Sun Jan 10 05:11:29 1999
Received: from Speed.FreeI.Net (tugrul@speed.freei.net [209.162.132.18])
	by marvin.jcu.cz (8.9.1a/8.9.1) with ESMTP id FAA14296
	for <alsa-devel@alsa.jcu.cz>; Sun, 10 Jan 1999 05:09:53 +0100
Received: from localhost (tugrul@localhost)
	by Speed.FreeI.Net (8.9.1/8.9.1) with ESMTP id UAA32374
	for <alsa-devel@alsa.jcu.cz>; Sat, 9 Jan 1999 20:09:45 -0800 (PST)
	(envelope-from tugrul@Speed.FreeI.Net)
Date: Sat, 9 Jan 1999 20:09:45 -0800 (PST)
From: Tugrul Galatali <tugrul@Speed.FreeI.Net>
To: alsa-devel@alsa.jcu.cz
Subject: experimental alsa driver for Ensoniq Vivo 90 (fwd)
Message-ID: <Pine.BSF.4.05.9901092007470.32371-100000@Speed.FreeI.Net>
MIME-Version: 1.0
Content-Type: TEXT/PLAIN; charset=US-ASCII
Reply-To: alsa-devel@alsa.jcu.cz
Sender: alsa-devel-owner@alsa.jcu.cz
Precedence: list



        That stupid spam thingie on alsa.jcu.cz's smtp server zapped my
message again. Please fix that, or tell me how to make sure I don't get
shot down for it.

---------- Forwarded message ----------
Date: Sat, 9 Jan 1999 22:50:58 -0500 (EST)
From: Tugrul Galatali <galatalt@stuy.edu>
To: alsa-devel@alsa.jcu.cz
Subject: experimental alsa driver for Ensoniq Vivo 90

        I had originally inserted a sb16 into my machine to try Alsa as a
act of desparation to avoid the skipping of mp3s on my machine (AMD
K6-2 300 128MB Deskstar 10) from trivial operations. Operations that
didn't even cause skipping on my old P133. I was plesantly surprised that
ALSA did cure the skipping, but the sb16s sound quality was a bit less
than what I expected from some mp3s. So here is my first attempt at a
driver for my Ensoniq Vivo90. Its only been tested with this card on
2.2.0-pre6, but its generic enough to probably work with any AD1848/MPU401
compliant card, and with a 2.0 kernel. I'll get around to more testing,
and I'll attempt to get more cards to test with, but I did not want to
delay releasing this source. Its my first kernel related project, and I'm
not too knowledgeable about ALSA yet, but patches and comments will be
really really appreciated so I may become a more active member of this
community.
        The name of the driver, snd-ens4081, currently reflects its
limited testing. If a more generic name for it wants to be applied to it,
like card-ad1848 or somesuch, feel free. I just didn't want to imply
support for beyond which I tested it.
        The following patch should work cleanly with alsa-drivers 0.3pre2.
I load it with "modprobe snd-ens4081" with the following additions to
conf.modules:

options snd-ens4081 snd_index=1 snd_port=0x534 snd_irq=5 snd_dma1=0
snd_mpu_port=0x330 snd_mpu_irq=9

post-install snd-ens4081 /usr/sbin/alsactl restore ; modprobe snd-pcm1-oss

        Perhaps not the best way, but I like it :-)

        Tugrul Galatali

<--- Cut Here --->
diff -urdN --exclude=CVS alsa-driver/cards/Makefile alsa-driver.tug/cards/Makefile
--- alsa-driver/cards/Makefile	Sat Jan  9 22:10:08 1999
+++ alsa-driver.tug/cards/Makefile	Sat Jan  9 22:15:52 1999
@@ -19,6 +19,7 @@
           $(TOPDIR)/modules/snd-sbawe.o \
 	  $(TOPDIR)/modules/snd-opl3sa.o \
 	  $(TOPDIR)/modules/snd-mozart.o \
+	  $(TOPDIR)/modules/snd-ens4081.o \
 	  $(TOPDIR)/modules/snd-card-cs4232.o \
 	  $(TOPDIR)/modules/snd-card-cs4236.o
 
@@ -42,6 +43,7 @@
 MOZART		 = mozart.o
 SONICVIBES	 = sonicvibes.o
 AUDIOPCI	 = audiopci.o
+ENS4081          = ens4081.o
 CARD_CS4232	 = card-cs4232.o
 CARD_CS4236	 = card-cs4236.o
 ESSSOLO1	 = esssolo1.o
@@ -109,6 +111,9 @@
 
 $(TOPDIR)/modules/snd-esssolo1.o: .depend $(ESSSOLO1)
 	$(LINKER) -o $@ $(ESSSOLO1)
+
+$(TOPDIR)/modules/snd-ens4081.o: .depend $(ENS4081)
+	$(LINKER) -o $@ $(ENS4081)
 
 gcompile: $(TARGETS)
 
diff -urdN --exclude=CVS alsa-driver/cards/ens4081.c alsa-driver.tug/cards/ens4081.c
--- alsa-driver/cards/ens4081.c	Wed Dec 31 19:00:00 1969
+++ alsa-driver.tug/cards/ens4081.c	Sat Jan  9 22:21:52 1999
@@ -0,0 +1,350 @@
+/*
+ *  Driver for Ensoniq Vivo90 (0.1 Alpha)
+ *  Copyright (c) by Tugrul Galatali <galatalt@stuy.edu>
+ *  Based on card-4232.c by Jaroslav Kysela <perex@jcu.cz>
+ *
+ *
+ *   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
+ *   the Free Software Foundation; either version 2 of the License, or
+ *   (at your option) any later version.
+ *
+ *   This program is distributed in the hope that it will be useful,
+ *   but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *   GNU General Public License for more details.
+ *
+ *   You should have received a copy of the GNU General Public License
+ *   along with this program; if not, write to the Free Software
+ *   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ */
+
+/*
+ * This is what I consider an ugly hack of card-4232.c for now. It works on
+ * my Ensoniq Vivo90, so I'm happy, yet I would like to extend its abilities
+ * to at least the entire SoundScape family, and its probably generic enough
+ * to go beyond that. Comments and patches would be much appreciated as this is * not only my first kernel related project, but my first serious release of 
+ * anything :-)
+ *
+ * One significant problem I have in the development of this driver is that
+ * this card doesn't seem to work at all with two dmas on my new AMD K6-2, with
+ * any driver. I might have to install Linux on my old box I promised to leave
+ * to my parents now :/
+ *
+ * Everything I couldn't get working on my first swing at the code has been
+ * completely stripped out of the source, like the second dma handling source.
+ * They'll be back =]
+ *
+ * This code has only been tested on 2.2.0-pre6. I see no reason for it to fail
+ * on a 2.0 kernel.
+ */
+
+/*
+ * 0.1 First Public Release
+ */
+
+#define SND_MAIN_OBJECT_FILE
+#include "driver.h"
+#include "ad1848.h"
+#include "mpu401.h"
+#include "initval.h"
+
+int snd_index[SND_CARDS] = SND_DEFAULT_IDX;	/* Index 1-MAX */
+char *snd_id[SND_CARDS] = SND_DEFAULT_STR;	/* ID for this card */
+int snd_port[SND_CARDS] = SND_DEFAULT_PORT;	/* PnP setup */
+int snd_mpu_port[SND_CARDS] = SND_DEFAULT_PORT;	/* PnP setup */
+int snd_irq[SND_CARDS] = SND_DEFAULT_IRQ;	/* 5,7,9,11,12,15 */
+int snd_mpu_irq[SND_CARDS] = SND_DEFAULT_IRQ;	/* 9,11,12,15 */
+int snd_dma1[SND_CARDS] = SND_DEFAULT_DMA;	/* 0,1,3,5,6,7 */
+int snd_dma1_size[SND_CARDS] = SND_DEFAULT_DMA_SIZE;	/* 8,16,32,64,128 */
+#ifdef MODULE_PARM
+MODULE_PARM(snd_index, "1-" __MODULE_STRING(SND_CARDS) "i");
+MODULE_PARM_DESC(snd_index, "Index value for ENS4081 soundcard.");
+MODULE_PARM(snd_id, "1-" __MODULE_STRING(SND_CARDS) "s");
+MODULE_PARM_DESC(snd_id, "ID string for ENS4081 soundcard.");
+MODULE_PARM(snd_port, "1-" __MODULE_STRING(SND_CARDS) "i");
+MODULE_PARM_DESC(snd_port, "Port # for ENS4081 driver.");
+MODULE_PARM(snd_mpu_port, "1-" __MODULE_STRING(SND_CARDS) "i");
+MODULE_PARM_DESC(snd_mpu_port, "MPU-401 port # for ENS4081 driver.");
+MODULE_PARM(snd_irq, "1-" __MODULE_STRING(SND_CARDS) "i");
+MODULE_PARM_DESC(snd_irq, "IRQ # for ENS4081 driver.");
+MODULE_PARM(snd_mpu_irq, "1-" __MODULE_STRING(SND_CARDS) "i");
+MODULE_PARM_DESC(snd_mpu_irq, "MPU-401 IRQ # for ENS4081 driver.");
+MODULE_PARM(snd_dma1, "1-" __MODULE_STRING(SND_CARDS) "i");
+MODULE_PARM_DESC(snd_dma1, "DMA1 # for ENS4081 driver.");
+MODULE_PARM(snd_dma1_size, "1-" __MODULE_STRING(SND_CARDS) "i");
+MODULE_PARM_DESC(snd_dma1_size, "Size of DMA1 # for ENS4081 driver.");
+#endif
+
+static struct snd_card_ens4081 {
+  snd_irq_t *irqptr;
+  snd_irq_t *mpuirqptr;
+  snd_dma_t *dma1ptr;
+  snd_card_t *card;
+  snd_pcm_t *pcm;
+  snd_kmixer_t *mixer;
+  snd_rawmidi_t *rmidi;
+  ad1848_t *codec;
+  unsigned short pcm_status_reg;
+} *snd_card_ens4081_cards[SND_CARDS] = SND_DEFAULT_PTR;
+
+static void snd_card_ens4081_use_inc(snd_card_t * card)
+{
+  MOD_INC_USE_COUNT;
+}
+
+static void snd_card_ens4081_use_dec(snd_card_t * card)
+{
+  MOD_DEC_USE_COUNT;
+}
+
+static snd_pcm_t *snd_card_ens4081_detect(snd_card_t * card,
+					  unsigned short port,
+					  unsigned short mpu_port,
+					  snd_irq_t *irqptr,
+					  snd_dma_t *dma1ptr)
+{
+  snd_pcm_t *pcm;
+
+  if (snd_register_ioport(card, port, 4, "ENS4081", NULL) < 0)
+    return NULL;
+
+  if (mpu_port != SND_AUTO_PORT) {
+    if (snd_register_ioport(card, mpu_port, 2, "ENS4081 - MPU-401", NULL) < 0) {
+      snd_unregister_ioports(card);
+      snd_printk("ports for ENS4081 MPU-401 are already used, try another\n");
+      return NULL;
+    }
+  }
+
+  pcm = snd_ad1848_new_device(card, port, irqptr, dma1ptr, AD1848_HW_DETECT);
+
+  if (!pcm) {
+    snd_unregister_ioports(card);
+    return NULL;
+  }
+
+  return pcm;
+}
+
+static void snd_card_ens4081_interrupt(int irq, void *dev_id, struct pt_regs *regs)
+{
+  struct snd_card_ens4081 *acard;
+  register unsigned char status;
+  
+  acard = (struct snd_card_ens4081 *) dev_id;
+
+  if (acard == NULL || acard->pcm == NULL)
+    return;
+  
+  status = inb(acard->pcm_status_reg);
+
+  if (status & 0x01)
+    snd_ad1848_interrupt(acard->pcm, status);
+}
+
+static void snd_card_ens4081_midi_interrupt(int irq, void *dev_id, struct pt_regs *regs)
+{
+  struct snd_card_ens4081 *acard;
+  
+  acard = (struct snd_card_ens4081 *) dev_id;
+
+  if (acard == NULL || acard->rmidi == NULL)
+    return;
+
+  snd_mpu401_uart_interrupt(acard->rmidi);
+}
+
+static int snd_card_ens4081_resources(int dev, struct snd_card_ens4081 *acard,
+				      snd_card_t * card)
+{
+  static int possible_irqs[] = {-1};
+  static int possible_dmas[] = {-1};
+  int err;
+  
+  if ((err = snd_register_interrupt(card, "ENS4081",
+				    snd_irq[dev], SND_IRQ_TYPE_ISA,
+				    snd_card_ens4081_interrupt, acard,
+				    possible_irqs, &acard->irqptr)) < 0)
+    return err;
+
+  acard->mpuirqptr = NULL;
+
+  if (snd_mpu_port[dev] != SND_AUTO_PORT && snd_mpu_irq[dev] >= 0) {
+    if (snd_register_interrupt(card,
+			       "ENS4081 - MPU401", snd_mpu_irq[dev],
+			       SND_IRQ_TYPE_ISA,
+			       snd_card_ens4081_midi_interrupt,
+			       acard, possible_irqs, &acard->mpuirqptr) < 0) {
+      snd_mpu_port[dev] = SND_AUTO_PORT;
+      snd_printk("warning: can't allocate IRQ for MPU401, midi port is disabled\n");
+    }
+  } else {
+    snd_mpu_port[dev] = SND_AUTO_PORT;
+    acard->mpuirqptr = NULL;
+  }
+
+  if ((err = snd_register_dma_channel(card,
+				      "ENS4081 - DMA1", snd_dma1[dev],
+				      SND_DMA_TYPE_ISA, snd_dma1_size[dev],
+				      possible_dmas, &acard->dma1ptr)) < 0)
+    return err;
+  
+  return 0;
+}
+
+static int snd_card_ens4081_probe(int dev, struct snd_card_ens4081 *acard)
+{
+  snd_card_t *card;
+  snd_pcm_t *pcm = NULL;
+  snd_pcm1_t *pcm1;
+  snd_kmixer_t *mixer = NULL;
+  snd_rawmidi_t *rmidi = NULL;
+  ad1848_t *codec;
+
+  card = snd_card_new(snd_index[dev], snd_id[dev],
+		      snd_card_ens4081_use_inc, snd_card_ens4081_use_dec);
+  if (!card)
+    return -ENOMEM;
+
+  card->type = SND_CARD_TYPE_ENS4081;
+  if (snd_card_ens4081_resources(dev, acard, card) < 0) {
+    snd_card_free(card);
+    return -EBUSY;
+  }
+
+  pcm = snd_card_ens4081_detect(card, snd_port[dev],
+				snd_mpu_port[dev],
+				acard->irqptr, acard->dma1ptr);
+
+  if (!pcm) {
+    snd_card_free(card);
+    return -ENODEV;
+  }
+
+  pcm1 = (snd_pcm1_t *) pcm->private_data;
+  codec = (ad1848_t *) pcm1->private_data;
+  acard->codec = codec;
+  acard->pcm_status_reg = codec->port + 2;
+
+  mixer = snd_ad1848_new_mixer(pcm);
+  if (!mixer)
+    goto __nodev;
+
+  if (acard->mpuirqptr) {
+    rmidi = snd_mpu401_uart_new_device(card, MPU401_HW_MPU401,
+				       snd_mpu_port[dev],
+				       acard->mpuirqptr->irq);
+    if (!rmidi)
+      goto __nodev;
+    if (snd_rawmidi_register(rmidi, 0) < 0)
+      goto __nodev;
+  }
+
+  if (snd_mixer_register(mixer, 0) < 0) {
+    if (rmidi)
+      snd_rawmidi_unregister(rmidi);
+    rmidi = NULL;
+    goto __nodev;
+  }
+
+  if (snd_pcm_register(pcm, 0)) {
+    if (rmidi)
+      snd_rawmidi_unregister(rmidi);
+    rmidi = NULL;
+    snd_mixer_unregister(mixer);
+    mixer = NULL;
+    goto __nodev;
+  }
+
+  strcpy(card->abbreviation, "ENS4081");
+  strcpy(card->shortname, pcm->name);
+
+  sprintf(card->longname, "%s at 0x%x, irq %i, dma %i",
+	  pcm->name,
+	  codec->port,
+	  acard->irqptr->irq,
+	  acard->dma1ptr->dma);
+
+  if (!snd_card_register(card)) {
+    acard->card = card;
+    acard->pcm = pcm;
+    acard->mixer = mixer;
+    acard->rmidi = rmidi;
+    return 0;
+  }
+
+  snd_mixer_unregister(mixer);
+  snd_pcm_unregister(pcm);
+  snd_card_free(card);
+  return -ENOMEM;
+
+ __nodev:
+  if (rmidi)
+    snd_rawmidi_free(rmidi);
+  if (mixer)
+    snd_mixer_free(mixer);
+  if (pcm)
+    snd_pcm_free(pcm);
+  snd_card_free(card);
+
+  return -ENXIO;
+}
+
+int init_module(void)
+{
+  int dev, cards;
+  struct snd_card_ens4081 *acard;
+
+#ifndef LINUX_2_1
+  register_symtab(NULL);
+#endif
+
+  for (dev = cards = 0; dev < SND_CARDS && snd_port[dev] > 0; dev++) {
+    acard = (struct snd_card_ens4081 *)
+      snd_malloc(sizeof(struct snd_card_ens4081));
+    if (!acard)
+      continue;
+    memset(acard, 0, sizeof(struct snd_card_ens4081));
+    if (snd_card_ens4081_probe(dev, acard) < 0) {
+      snd_free(acard, sizeof(struct snd_card_ens4081));
+      if (snd_port[dev] == SND_AUTO_PORT)
+	break;
+      snd_printk("ENS4081 soundcard #%i not found at 0x%x or device busy\n", dev + 1, snd_port[dev]);
+      continue;
+    }
+    snd_card_ens4081_cards[dev] = acard;
+    cards++;
+  }
+
+  if (!cards) {
+    snd_printk("ENS4081 soundcard #%i not found or device busy\n", dev + 1);
+    return -ENODEV;
+  }
+
+  return 0;
+}
+
+void cleanup_module(void)
+{
+  int idx;
+  struct snd_card_ens4081 *acard;
+
+  for (idx = 0; idx < SND_CARDS; idx++) {
+    acard = snd_card_ens4081_cards[idx];
+    if (acard) {
+      snd_card_unregister(acard->card);
+
+      if (acard->rmidi)
+	snd_rawmidi_unregister(acard->rmidi);
+      if (acard->mixer)
+	snd_mixer_unregister(acard->mixer);
+      if (acard->pcm) {
+	snd_pcm_unregister(acard->pcm);
+      }
+      snd_card_free(acard->card);
+      snd_free(acard, sizeof(struct snd_card_ens4081));
+    }
+  }
+}
diff -urdN --exclude=CVS alsa-driver/include/asoundid.h alsa-driver.tug/include/asoundid.h
--- alsa-driver/include/asoundid.h	Sat Jan  9 22:10:09 1999
+++ alsa-driver.tug/include/asoundid.h	Sat Jan  9 22:25:48 1999
@@ -51,7 +51,8 @@
 #define SND_CARD_TYPE_AMD_INTERWAVE_STB	0x00000013	/* AMD InterWave + TEA6330T */
 #define SND_CARD_TYPE_ESS_ES1938	0x00000014	/* ESS Solo-1 ES1938 */
 #define SND_CARD_TYPE_ESS_ES1869	0x00000015	/* ESS AudioDrive ES1869 */
+#define SND_CARD_TYPE_ENS4081   	0x00000016	/* Ensoniq Vivo90 */
 /* --- */
-#define SND_CARD_TYPE_LAST		0x00000015
+#define SND_CARD_TYPE_LAST		0x00000016
   
 #endif				/* __ASOUNDID_H */
<--- EOF --->



