diff -urN -X dontdiff linux-2.4.4-pre5-vanilla/Documentation/Configure.help linux/Documentation/Configure.help
--- linux-2.4.4-pre5-vanilla/Documentation/Configure.help	Fri Apr 20 02:39:32 2001
+++ linux/Documentation/Configure.help	Fri Apr 20 03:17:00 2001
@@ -14799,17 +14799,20 @@
 
   If unsure, say Y.
 
-ACI mixer (miroPCM12/PCM20)
+ACI mixer (miroSOUND PCM1-pro/PCM12/PCM20 radio)
 CONFIG_SOUND_ACI_MIXER
   ACI (Audio Command Interface) is a protocol used to communicate with
-  the microcontroller on some sound cards produced by miro, e.g. the
-  miroSOUND PCM12 and PCM20. The main function of the ACI is to
-  control the mixer and to get a product identification. 
-
-  This Voxware ACI driver currently only supports the ACI functions on
-  the miroSOUND PCM12 and PCM20 cards. On the PCM20, ACI also controls
-  the radio tuner. This is supported in the video4linux
-  radio-miropcm20 driver.
+  the microcontroller on some sound cards produced by miro and Cardinal
+  Technologies. The main function of the ACI is to control the mixer
+  and to get a product identification. 
+
+  This Voxware ACI driver currently supports the ACI functions on the
+  miroSOUND PCM1-pro, PCM12 and PCM20 radio. On the PCM20 radio, ACI
+  also controls the radio tuner. This is supported in the video4linux
+  miropcm20 driver (say M or Y here and go back to "Multimedia devices"
+  -> "Radio Adapters").
+
+  This driver is also available as a module and will be called aci.o.
 
 SB32/AWE support
 CONFIG_SOUND_AWE32_SYNTH
@@ -16563,11 +16566,11 @@
   say M here and read Documentation/modules.txt. The module will be
   called i2c-parport.o.
 
-Miro PCM20 Radio
+miroSOUND PCM20 radio
 CONFIG_RADIO_MIROPCM20
-  Choose Y here if you have this FM radio card. You also need to say Y
-  to "ACI mixer (miroPCM12/PCM20)" (in "additional low level sound
-  drivers") for this to work.
+  Choose Y here if you have this sound card. You also need to say Y
+  to "ACI mixer (miroSOUND PCM1-pro/PCM12/PCM20 radio)" (in "Sound")
+  for this to work.
 
   In order to control your radio card, you will need to use programs
   that are compatible with the Video for Linux API. Information on 
@@ -16577,7 +16580,21 @@
   If you want to compile this driver as a module ( = code which can be
   inserted in and removed from the running kernel whenever you want),
   say M here and read Documentation/modules.txt. The module will be
-  called radio-miropcm20.o
+  called miropcm20.o
+
+miroSOUND PCM20 radio RDS user interface (EXPERIMENTAL)
+CONFIG_RADIO_MIROPCM20_RDS
+  Choose Y here if you want to see RDS/RBDS information like RadioText,
+  Programme Service name, Clock Time and date, Programme TYpe and
+  Traffic Announcement/Programme identification. You also need to say
+  Y to "miroSOUND PCM20 radio" and devfs!
+
+  It's not possible to read the raw RDS packets from the device, so
+  the driver cant provide an V4L interface for this. But the
+  availability of RDS is reported over V4L by the basic driver already.
+  Here RDS can be read from files in /dev/v4l/rds.
+
+  As module the driver will be called miropcm20-rds.o.
 
 GemTek Radio Card
 CONFIG_RADIO_GEMTEK
diff -urN -X dontdiff linux-2.4.4-pre5-vanilla/Documentation/sound/README.OSS linux/Documentation/sound/README.OSS
--- linux-2.4.4-pre5-vanilla/Documentation/sound/README.OSS	Fri Apr 20 02:39:33 2001
+++ linux/Documentation/sound/README.OSS	Fri Apr 20 12:30:27 2001
@@ -17,7 +17,7 @@
 document can be still interesting and very helpful.
 
 [ File edited 17.01.1999 - Riccardo Facchetti ]
-[ Edited miroSOUND section 17.09.2000 - Robert Siemer ]
+[ Edited miroSOUND section 19.04.2001 - Robert Siemer ]
 
 OSS/Free version 3.8 release notes
 ----------------------------------
@@ -1327,7 +1327,7 @@
 ---------
 
 The miroSOUND PCM1-pro, PCM12 and PCM20 radio has been used
-successfully. This card is based on the MAD16, OPL4, and CS4231A chips
+successfully. These cards are based on the MAD16, OPL4, and CS4231A chips
 and everything said in the section about MAD16 cards applies here,
 too. The only major difference between the PCMxx and other MAD16 cards
 is that instead of the mixer in the CS4231 codec a separate mixer
@@ -1337,8 +1337,8 @@
 you compile this ACI driver together with the normal MAD16 support
 when you use a miroSOUND PCMxx card. The ACI mixer is controlled by
 /dev/mixer and the CS4231 mixer by /dev/mixer1 (depends on load
-time). Only in special cases you want to change something on the CS4231
-mixer.
+time). Only in special cases you want to change something regularly on
+the CS4231 mixer.
 
 The miroSOUND PCM12 and PCM20 radio is capable of full duplex
 operation (simultaneous PCM replay and recording), which allows you to
@@ -1354,10 +1354,9 @@
 miropcm20.o module. Also the 7-band equalizer is integrated
 (limited by the OSS-design). Developement has started and maybe
 finished for the RDS decoder on this card, too. You will be able to
-read radio text, the program service name, program type and
+read RadioText, the Programme Service name, Programme TYpe and
 others. Even the v4l radio module benefits from it with a refined
-strength value. See aci.c, radio-miropcm20.c and rds-miropcm20.c for
-more details.
+strength value. See aci.[ch] and miropcm20*.[ch] for more details.
 
 The following configuration parameters have worked fine for the PCM12
 in Markus Kuhn's system, many other configurations might work, too:
diff -urN -X dontdiff linux-2.4.4-pre5-vanilla/drivers/media/radio/Config.in linux/drivers/media/radio/Config.in
--- linux-2.4.4-pre5-vanilla/drivers/media/radio/Config.in	Fri Apr 20 02:39:58 2001
+++ linux/drivers/media/radio/Config.in	Fri Apr 20 03:27:05 2001
@@ -24,6 +24,7 @@
 dep_tristate '  Guillemot MAXI Radio FM 2000 radio' CONFIG_RADIO_MAXIRADIO $CONFIG_VIDEO_DEV
 dep_tristate '  Maestro on board radio' CONFIG_RADIO_MAESTRO $CONFIG_VIDEO_DEV
 dep_tristate '  miroSOUND PCM20 radio' CONFIG_RADIO_MIROPCM20 $CONFIG_VIDEO_DEV $CONFIG_SOUND_ACI_MIXER
+dep_tristate '    miroSOUND PCM20 radio RDS user interface (EXPERIMENTAL)' CONFIG_RADIO_MIROPCM20_RDS $CONFIG_RADIO_MIROPCM20 $CONFIG_EXPERIMENTAL
 dep_tristate '  SF16FMI Radio' CONFIG_RADIO_SF16FMI $CONFIG_VIDEO_DEV
 if [ "$CONFIG_RADIO_SF16FMI" = "y" ]; then
    hex '    SF16FMI I/O port (0x284 or 0x384)' CONFIG_RADIO_SF16FMI_PORT 284
diff -urN -X dontdiff linux-2.4.4-pre5-vanilla/drivers/media/radio/Makefile linux/drivers/media/radio/Makefile
--- linux-2.4.4-pre5-vanilla/drivers/media/radio/Makefile	Fri Apr 20 02:39:58 2001
+++ linux/drivers/media/radio/Makefile	Fri Apr 20 03:32:13 2001
@@ -21,11 +21,11 @@
 # All of the (potential) objects that export symbols.
 # This list comes from 'grep -l EXPORT_SYMBOL *.[hc]'.
 
-export-objs     :=	
+export-objs     := miropcm20-rds-core.o
 
 list-multi	:= miropcm20.o
 
-miropcm20-objs	:= radio-miropcm20.o rds-miropcm20.o
+miropcm20-objs	:= miropcm20-rds-core.o miropcm20-radio.o
 
 obj-$(CONFIG_RADIO_AZTECH) += radio-aztech.o
 obj-$(CONFIG_RADIO_RTRACK2) += radio-rtrack2.o
@@ -37,6 +37,7 @@
 obj-$(CONFIG_RADIO_RTRACK) += radio-aimslab.o
 obj-$(CONFIG_RADIO_ZOLTRIX) += radio-zoltrix.o
 obj-$(CONFIG_RADIO_MIROPCM20) += miropcm20.o
+obj-$(CONFIG_RADIO_MIROPCM20_RDS) += miropcm20-rds.o
 obj-$(CONFIG_RADIO_GEMTEK) += radio-gemtek.o
 obj-$(CONFIG_RADIO_TRUST) += radio-trust.o
 obj-$(CONFIG_RADIO_MAESTRO) += radio-maestro.o
diff -urN -X dontdiff linux-2.4.4-pre5-vanilla/drivers/media/radio/miropcm20-radio.c linux/drivers/media/radio/miropcm20-radio.c
--- linux-2.4.4-pre5-vanilla/drivers/media/radio/miropcm20-radio.c	Thu Jan  1 01:00:00 1970
+++ linux/drivers/media/radio/miropcm20-radio.c	Fri Apr 20 03:15:54 2001
@@ -0,0 +1,283 @@
+/* Miro PCM20 radio driver for Linux radio support
+ * (c) 1998 Ruurd Reitsma <R.A.Reitsma@wbmt.tudelft.nl>
+ * Thanks to Norberto Pellici for the ACI device interface specification
+ * The API part is based on the radiotrack driver by M. Kirkwood
+ * This driver relies on the aci mixer (drivers/sound/aci.c)
+ * Look there for further info...
+ */
+
+/* Revision history:
+ *
+ *   1998        Ruurd Reitsma <R.A.Reitsma@wbmt.tudelft.nl>
+ *   2000-09-05  Robert Siemer <Robert.Siemer@gmx.de>
+ *        removed unfinished volume control (maybe adding it later again)
+ *        use OSS-mixer; added stereo control
+ */
+
+/* What ever you think about the ACI, version 0x07 is not very well!
+ * I cant get frequency, 'tuner status', 'tuner flags' or mute/mono
+ * conditions...                Robert 
+ */
+
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/videodev.h>
+#include "../../sound/aci.h"
+#include "miropcm20-rds-core.h"
+
+static int users = 0;
+
+struct pcm20_device {
+	unsigned long freq;
+	int muted;
+	int stereo;
+};
+
+
+static int pcm20_mute(struct pcm20_device *dev, unsigned char mute)
+{
+	dev->muted = mute;
+	return aci_write_cmd(ACI_SET_TUNERMUTE, mute);
+}
+
+static int pcm20_stereo(struct pcm20_device *dev, unsigned char stereo)
+{
+	dev->stereo = stereo;
+	return aci_write_cmd(ACI_SET_TUNERMONO, !stereo);
+}
+
+static int pcm20_setfreq(struct pcm20_device *dev, unsigned long freq)
+{
+	unsigned char freql;
+	unsigned char freqh;
+
+	dev->freq=freq;
+
+	freq /= 160;
+	if (!(aci_version==0x07 || aci_version>=0xb0))
+		freq /= 10;  /* I don't know exactly which version
+			      * needs this hack */
+	freql = freq & 0xff;
+	freqh = freq >> 8;
+
+	aci_rds_cmd(RDS_RESET, 0, 0);
+	pcm20_stereo(dev, 1);
+
+	return aci_rw_cmd(ACI_WRITE_TUNE, freql, freqh);
+}
+
+static int pcm20_getflags(struct pcm20_device *dev, __u32 *flags, __u16 *signal)
+{
+	/* okay, check for signal, stereo and rds here... */
+	int i;
+	unsigned char buf;
+
+	if ((i=aci_rw_cmd(ACI_READ_TUNERSTATION, -1, -1))<0)
+		return i;
+#if DEBUG
+	printk("check_sig: 0x%x\n", i);
+#endif
+	if (i & 0x80) {
+		/* no signal from tuner */
+		*flags=0;
+		*signal=0;
+		return 0;
+	} else
+		*signal=0xffff;
+
+	if ((i=aci_rw_cmd(ACI_READ_TUNERSTEREO, -1, -1))<0)
+		return i;
+	if (i & 0x40) {
+		*flags=0;
+	} else {
+		/* stereo */
+		*flags=VIDEO_TUNER_STEREO_ON;
+		/* I cant see stereo, when forced to mono */
+		dev->stereo=1;
+	}
+
+	if ((i=aci_rds_cmd(RDS_STATUS, &buf, 1))<0)
+		return i;
+	if (buf & 1)
+		/* RDS available */
+		*flags|=VIDEO_TUNER_RDS_ON;
+	else
+		return 0;
+
+	if ((i=aci_rds_cmd(RDS_RXVALUE, &buf, 1))<0)
+		return i;
+#if DEBUG
+	printk("rds-signal: %d\n", buf);
+#endif
+	if (buf > 15) {
+		printk("miropcm20-radio: RX strengths unexpected high...\n");
+		buf=15;
+	}
+	/* refine signal */
+	if ((*signal=SCALE(15, 0xffff, buf))==0)
+		*signal = 1;
+
+	return 0;
+}
+
+static int pcm20_ioctl(struct video_device *dev, unsigned int cmd, void *arg)
+{
+	struct pcm20_device *pcm20=dev->priv;
+	int i;
+	
+	switch(cmd)
+	{
+		case VIDIOCGCAP:
+		{
+			struct video_capability v;
+			v.type=VID_TYPE_TUNER;
+			strcpy(v.name, "Miro PCM20");
+			v.channels=1;
+			v.audios=1;
+			/* No we don't do pictures */
+			v.maxwidth=0;
+			v.maxheight=0;
+			v.minwidth=0;
+			v.minheight=0;
+			if(copy_to_user(arg,&v,sizeof(v)))
+				return -EFAULT;
+			return 0;
+		}
+		case VIDIOCGTUNER:
+		{
+			struct video_tuner v;
+			if(copy_from_user(&v, arg,sizeof(v))!=0) 
+				return -EFAULT;
+			if(v.tuner)	/* Only 1 tuner */ 
+				return -EINVAL;
+			v.rangelow=87*16000;
+			v.rangehigh=108*16000;
+			pcm20_getflags(pcm20, &v.flags, &v.signal);
+			v.flags|=VIDEO_TUNER_LOW;
+			v.mode=VIDEO_MODE_AUTO;
+			strcpy(v.name, "FM");
+			if(copy_to_user(arg,&v, sizeof(v)))
+				return -EFAULT;
+			return 0;
+		}
+		case VIDIOCSTUNER:
+		{
+			struct video_tuner v;
+			if(copy_from_user(&v, arg, sizeof(v)))
+				return -EFAULT;
+			if(v.tuner!=0)
+				return -EINVAL;
+			/* Only 1 tuner so no setting needed ! */
+			return 0;
+		}
+		case VIDIOCGFREQ:
+			if(copy_to_user(arg, &pcm20->freq, sizeof(pcm20->freq)))
+				return -EFAULT;
+			return 0;
+		case VIDIOCSFREQ:
+			if(copy_from_user(&pcm20->freq, arg, sizeof(pcm20->freq)))
+				return -EFAULT;
+			i=pcm20_setfreq(pcm20, pcm20->freq);
+#if DEBUG
+			printk("First view (setfreq): 0x%x\n", i);
+#endif
+			return i;
+		case VIDIOCGAUDIO:
+		{	
+			struct video_audio v;
+			memset(&v,0, sizeof(v));
+			v.flags=VIDEO_AUDIO_MUTABLE;
+			if (pcm20->muted)
+				v.flags|=VIDEO_AUDIO_MUTE;
+			v.mode=VIDEO_SOUND_STEREO;
+			if (pcm20->stereo)
+				v.mode|=VIDEO_SOUND_MONO;
+			/* v.step=2048; */
+			strcpy(v.name, "Radio");
+			if(copy_to_user(arg,&v, sizeof(v)))
+				return -EFAULT;
+			return 0;			
+		}
+		case VIDIOCSAUDIO:
+		{
+			struct video_audio v;
+			if(copy_from_user(&v, arg, sizeof(v))) 
+				return -EFAULT;
+			if(v.audio) 
+				return -EINVAL;
+
+			pcm20_mute(pcm20, !!(v.flags&VIDEO_AUDIO_MUTE));
+			if(v.flags&VIDEO_SOUND_MONO)
+				pcm20_stereo(pcm20, 0);
+			if(v.flags&VIDEO_SOUND_STEREO)
+				pcm20_stereo(pcm20, 1);
+
+			return 0;
+		}
+		default:
+			return -ENOIOCTLCMD;
+	}
+}
+
+static int pcm20_open(struct video_device *dev, int flags)
+{
+	if(users)
+		return -EBUSY;
+	users++;
+	MOD_INC_USE_COUNT;
+	return 0;
+}
+
+static void pcm20_close(struct video_device *dev)
+{
+	users--;
+	MOD_DEC_USE_COUNT;
+}
+
+static struct pcm20_device pcm20_unit = {
+	freq:   87*16000,
+	muted:  1,
+	stereo: 0
+};
+
+static struct video_device pcm20_radio = {
+	name:		"Miro PCM 20 radio",
+	type:		VID_TYPE_TUNER,
+	hardware:	VID_HARDWARE_RTRACK,
+	open:		pcm20_open,
+	close:		pcm20_close,
+	ioctl:		pcm20_ioctl,
+	priv:		&pcm20_unit
+};
+
+static int __init pcm20_init(void)
+{
+	if(video_register_device(&pcm20_radio, VFL_TYPE_RADIO)==-1)
+		goto video_register_device;
+		
+	if(attach_aci_rds()<0)
+		goto attach_aci_rds;
+
+	printk(KERN_INFO "Miro PCM20 radio card driver.\n");
+
+	return 0;
+
+ attach_aci_rds:
+	video_unregister_device(&pcm20_radio);
+ video_register_device:
+	return -EINVAL;
+}
+
+MODULE_AUTHOR("Ruurd Reitsma");
+MODULE_DESCRIPTION("A driver for the Miro PCM20 radio card.");
+
+EXPORT_NO_SYMBOLS;
+
+static void __exit pcm20_cleanup(void)
+{
+	unload_aci_rds();
+	video_unregister_device(&pcm20_radio);
+}
+
+module_init(pcm20_init);
+module_exit(pcm20_cleanup);
diff -urN -X dontdiff linux-2.4.4-pre5-vanilla/drivers/media/radio/miropcm20-rds-core.c linux/drivers/media/radio/miropcm20-rds-core.c
--- linux-2.4.4-pre5-vanilla/drivers/media/radio/miropcm20-rds-core.c	Thu Jan  1 01:00:00 1970
+++ linux/drivers/media/radio/miropcm20-rds-core.c	Fri Apr 20 03:15:54 2001
@@ -0,0 +1,210 @@
+/*
+ *  Many thanks to Fred Seidel <seidel@metabox.de>, the
+ *  designer of the RDS decoder hardware. With his help
+ *  I was able to code this driver.
+ *  Thanks also to Norberto Pellicci, Dominic Mounteney
+ *  <DMounteney@pinnaclesys.com> and www.teleauskunft.de
+ *  for good hints on finding Fred. It was somewhat hard
+ *  to locate him here in Germany... [:
+ *
+ * Revision history:
+ *
+ *   2000-08-09  Robert Siemer <Robert.Siemer@gmx.de>
+ *        RDS support for MiroSound PCM20 radio
+ */
+
+#define _NO_VERSION_
+
+/* #include <linux/kernel.h> */
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/slab.h>
+#include <asm/semaphore.h>
+#include <asm/io.h>
+#include "../../sound/aci.h"
+#include "miropcm20-rds-core.h"
+
+#define DEBUG 0
+
+static struct semaphore aci_rds_sem;
+
+#define RDS_DATASHIFT          2   /* Bit 2 */
+#define RDS_DATAMASK        (1 << RDS_DATASHIFT)
+#define RDS_BUSYMASK        0x10   /* Bit 4 */
+#define RDS_CLOCKMASK       0x08   /* Bit 3 */
+
+#define RDS_DATA(x)         (((x) >> RDS_DATASHIFT) & 1) 
+
+
+#if DEBUG
+static void print_matrix(char array[], unsigned int length)
+{
+        int i, j;
+
+        for (i=0; i<length; i++) {
+                printk(KERN_DEBUG "aci-rds: ");
+                for (j=7; j>=0; j--) {
+                        printk("%d", (array[i] >> j) & 0x1);
+                }
+                if (i%8 == 0)
+                        printk(" byte-border\n");
+                else
+                        printk("\n");
+        }
+}
+#endif /* DEBUG */
+
+static int byte2trans(unsigned char byte, unsigned char sendbuffer[], int size)
+{
+	int i;
+
+	if (size != 8)
+		return -1;
+	for (i = 7; i >= 0; i--)
+		sendbuffer[7-i] = (byte & (1 << i)) ? RDS_DATAMASK : 0;
+	sendbuffer[0] |= RDS_CLOCKMASK;
+
+	return 0;
+}
+
+static int rds_waitread(void)
+{
+	unsigned char byte;
+	int i=2000;
+
+	do {
+		byte=inb(RDS_REGISTER);
+		i--;
+	}
+	while ((byte & RDS_BUSYMASK) && i);
+
+	if (i) {
+		#if DEBUG
+		printk(KERN_DEBUG "rds_waitread()");
+		print_matrix(&byte, 1);
+		#endif
+		return (byte);
+	} else {
+		printk(KERN_WARNING "aci-rds: rds_waitread() timeout...\n");
+		return -1;
+	}
+}
+
+/* dont use any ..._nowait() function if you are not sure what you do... */
+
+static inline void rds_rawwrite_nowait(unsigned char byte)
+{
+	#if DEBUG
+	printk(KERN_DEBUG "rds_rawwrite()");
+	print_matrix(&byte, 1);
+	#endif
+	outb(byte, RDS_REGISTER);
+}
+
+static int rds_rawwrite(unsigned char byte)
+{
+	if (rds_waitread() >= 0) {
+		rds_rawwrite_nowait(byte);
+		return 0;
+	} else
+		return -1;
+}
+
+static int rds_write(unsigned char cmd)
+{
+	unsigned char sendbuffer[8];
+	int i;
+	
+	if (byte2trans(cmd, sendbuffer, 8) != 0){
+		return -1;
+	} else {
+		for (i=0; i<8; i++) {
+			rds_rawwrite(sendbuffer[i]);
+		}
+	}
+	return 0;
+}
+
+static int rds_readcycle_nowait(void)
+{
+	rds_rawwrite_nowait(0);
+	return rds_waitread();
+}
+
+static int rds_readcycle(void)
+{
+	if (rds_rawwrite(0) < 0)
+		return -1;
+	return rds_waitread();
+}
+
+static int rds_read(unsigned char databuffer[], int datasize)
+{
+	#define READSIZE (8*datasize)
+
+	int i,j;
+
+	if (datasize < 1)  /* nothing to read */
+		return 0;
+
+	/* to be able to use rds_readcycle_nowait()
+	   I have to waitread() here */
+	if (rds_waitread() < 0)
+		return -1;
+	
+	memset(databuffer, 0, datasize);
+
+	for (i=0; i< READSIZE; i++)
+		if((j=rds_readcycle_nowait()) < 0) {
+			return -1;
+		} else {
+			databuffer[i/8]|=(RDS_DATA(j) << (7-(i%8)));
+		}
+
+	return 0;
+}
+
+static int rds_ack(void)
+{
+	int i=rds_readcycle();
+
+	if (i < 0)
+		return -1;
+	if (i & RDS_DATAMASK) {
+		return 0;  /* ACK  */
+	} else {
+		printk(KERN_DEBUG "aci-rds: NACK\n");
+		return 1;  /* NACK */
+	}
+}
+
+int aci_rds_cmd(unsigned char cmd, unsigned char databuffer[], int datasize)
+{
+	int ret;
+
+	if (down_interruptible(&aci_rds_sem))
+		return -EINTR;
+
+	rds_write(cmd);
+
+	/* RDS_RESET doesn't need further processing */
+	if (cmd!=RDS_RESET && (rds_ack() || rds_read(databuffer, datasize)))
+		ret = -1;
+	else
+		ret = 0;
+
+	up(&aci_rds_sem);
+	
+	return ret;
+}
+EXPORT_SYMBOL(aci_rds_cmd);
+
+int __init attach_aci_rds(void)
+{
+	init_MUTEX(&aci_rds_sem);
+	return 0;
+}
+
+void __exit unload_aci_rds(void)
+{
+}
diff -urN -X dontdiff linux-2.4.4-pre5-vanilla/drivers/media/radio/miropcm20-rds-core.h linux/drivers/media/radio/miropcm20-rds-core.h
--- linux-2.4.4-pre5-vanilla/drivers/media/radio/miropcm20-rds-core.h	Thu Jan  1 01:00:00 1970
+++ linux/drivers/media/radio/miropcm20-rds-core.h	Fri Apr 20 03:15:54 2001
@@ -0,0 +1,19 @@
+#ifndef _MIROPCM20_RDS_CORE_H_
+#define _MIROPCM20_RDS_CORE_H_
+
+extern int aci_rds_cmd(unsigned char cmd, unsigned char databuffer[], int datasize);
+
+#define RDS_STATUS      0x01
+#define RDS_STATIONNAME 0x02
+#define RDS_TEXT        0x03
+#define RDS_ALTFREQ     0x04
+#define RDS_TIMEDATE    0x05
+#define RDS_PI_CODE     0x06
+#define RDS_PTYTATP     0x07
+#define RDS_RESET       0x08
+#define RDS_RXVALUE     0x09
+
+extern void __exit unload_aci_rds(void);
+extern int __init attach_aci_rds(void);
+
+#endif /* _MIROPCM20_RDS_CORE_H_ */
diff -urN -X dontdiff linux-2.4.4-pre5-vanilla/drivers/media/radio/miropcm20-rds.c linux/drivers/media/radio/miropcm20-rds.c
--- linux-2.4.4-pre5-vanilla/drivers/media/radio/miropcm20-rds.c	Thu Jan  1 01:00:00 1970
+++ linux/drivers/media/radio/miropcm20-rds.c	Fri Apr 20 03:15:54 2001
@@ -0,0 +1,140 @@
+/* MiroSOUND PCM20 radio rds interface driver
+ * (c) 2001 Robert Siemer <Robert.Siemer@gmx.de>
+ * Thanks to Fred Seidel. See miropcm20-rds-core.c for further information.
+ */
+
+/* Revision history:
+ *
+ *   2001-04-18  Robert Siemer <Robert.Siemer@gmx.de>
+ *        separate file for user interface driver
+ */
+
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/slab.h>
+#include <asm/uaccess.h>
+#include <linux/devfs_fs_kernel.h>
+#include "miropcm20-rds-core.h"
+
+devfs_handle_t dfsh;
+char * text_buffer;
+static int rds_users = 0;
+
+
+static int rds_f_open(struct inode *in, struct file *fi)
+{
+	if(rds_users)
+		return -EBUSY;
+
+	if ((text_buffer=kmalloc(66, GFP_KERNEL)) == 0) {
+		printk(KERN_NOTICE "aci-rds: Out of memory by open()...\n");
+		return -ENOMEM;
+	}
+
+	rds_users++;
+	MOD_INC_USE_COUNT;
+	return 0;
+}
+
+static int rds_f_release(struct inode *in, struct file *fi)
+{
+	kfree(text_buffer);
+
+	rds_users--;
+	MOD_DEC_USE_COUNT;
+	return 0;
+}
+
+static void print_matrix(char *ch, char out[])
+{
+        int j;
+
+	for (j=7; j>=0; j--) {
+		 out[7-j] = ((*ch >> j) & 0x1) + '0';
+	}
+}
+
+static ssize_t rds_f_read(struct file *file, char *buffer, size_t length, loff_t *offset)
+{
+//	i = sprintf(text_buffer, "length: %d, offset: %d\n", length, *offset);
+
+	char c;
+	char bits[8];
+
+	current->state=TASK_UNINTERRUPTIBLE;
+	schedule_timeout(2*HZ);
+	aci_rds_cmd(RDS_STATUS, &c, 1);
+	print_matrix(&c, bits);
+	if (copy_to_user(buffer, bits, 8))
+		return -EFAULT;
+
+/*	if ((c >> 3) & 1) {
+		aci_rds_cmd(RDS_STATIONNAME, text_buffer+1, 8);
+		text_buffer[0]  = ' ' ;
+		text_buffer[9]  = '\n';
+		return copy_to_user(buffer+8, text_buffer, 10) ? -EFAULT: 18;
+	}
+*/
+/*	if ((c >> 6) & 1) {
+		aci_rds_cmd(RDS_PTYTATP, &c, 1);
+		if ( c & 1)
+			sprintf(text_buffer, " M");
+		else
+			sprintf(text_buffer, " S");
+		if ((c >> 1) & 1)
+			sprintf(text_buffer+2, " TA");
+		else
+			sprintf(text_buffer+2, " --");
+		if ((c >> 7) & 1)
+			sprintf(text_buffer+5, " TP");
+		else
+			sprintf(text_buffer+5, " --");
+		sprintf(text_buffer+8, " %2d\n", (c >> 2) & 0x1f);
+		return copy_to_user(buffer+8, text_buffer, 12) ? -EFAULT: 20;
+	}
+*/
+
+	if ((c >> 4) & 1) {
+		aci_rds_cmd(RDS_TEXT, text_buffer, 65);
+		text_buffer[0]  = ' ' ;
+		text_buffer[65] = '\n';
+		return copy_to_user(buffer+8, text_buffer,66) ? -EFAULT : 66+8;
+	} else {
+		put_user('\n', buffer+8);
+		return 9;
+	}
+}
+
+static struct file_operations rds_f_ops = {
+	read:    rds_f_read,
+	open:    rds_f_open,
+	release: rds_f_release
+};
+
+
+static int __init miropcm20_rds_init(void)
+{
+	if ((dfsh = devfs_register(NULL, "v4l/rds/radiotext", 
+				   DEVFS_FL_DEFAULT | DEVFS_FL_AUTO_DEVNUM,
+				   0, 0, S_IRUGO | S_IFCHR, &rds_f_ops, NULL))
+	    == NULL)
+		goto devfs_register;
+
+	printk("miropcm20-rds: userinterface driver loaded.\n");
+#if DEBUG
+	printk("v4l-name: %s\n", devfs_get_name(pcm20_radio.devfs_handle, 0));
+#endif
+
+	return 0;
+
+ devfs_register:
+	return -EINVAL;
+}
+
+static void __exit miropcm20_rds_cleanup(void)
+{
+	devfs_unregister(dfsh);
+}
+
+module_init(miropcm20_rds_init);
+module_exit(miropcm20_rds_cleanup);
diff -urN -X dontdiff linux-2.4.4-pre5-vanilla/drivers/media/radio/radio-miropcm20.c linux/drivers/media/radio/radio-miropcm20.c
--- linux-2.4.4-pre5-vanilla/drivers/media/radio/radio-miropcm20.c	Fri Apr 20 02:39:58 2001
+++ linux/drivers/media/radio/radio-miropcm20.c	Thu Jan  1 01:00:00 1970
@@ -1,288 +0,0 @@
-/* Miro PCM20 radio driver for Linux radio support
- * (c) 1998 Ruurd Reitsma <R.A.Reitsma@wbmt.tudelft.nl>
- * Thanks to Norberto Pellici for the ACI device interface specification
- * The API part is based on the radiotrack driver by M. Kirkwood
- * This driver relies on the aci mixer (drivers/sound/aci.c)
- * Look there for further info...
- */
-
-/* Revision history:
- *
- *   1998        Ruurd Reitsma <R.A.Reitsma@wbmt.tudelft.nl>
- *   2000-09-05  Robert Siemer <Robert.Siemer@gmx.de>
- *        removed unfinished volume control (maybe adding it later again)
- *        use OSS-mixer; added stereo control
- */
-
-/* What ever you think about the ACI, version 0x07 is not very well!
- * I cant get frequency, 'tuner status', 'tuner flags' or mute/mono
- * conditions...                Robert 
- */
-
-#include <linux/module.h>
-#include <linux/init.h>
-#include <linux/videodev.h>
-#include <linux/devfs_fs_kernel.h>
-#include <asm/uaccess.h>
-
-char * aci_radio_name;
-
-#include "../../sound/aci.h"
-
-static int users = 0;
-
-struct pcm20_device
-{
-	unsigned long freq;
-	int muted;
-	int stereo;
-};
-
-
-static int pcm20_mute(struct pcm20_device *dev, unsigned char mute)
-{
-	dev->muted = mute;
-	return aci_write_cmd(0xa3, mute);
-}
-
-static int pcm20_stereo(struct pcm20_device *dev, unsigned char stereo)
-{
-	dev->stereo = stereo;
-	return aci_write_cmd(0xa4, !stereo);
-}
-
-static int pcm20_setfreq(struct pcm20_device *dev, unsigned long freq)
-{
-	unsigned char freql;
-	unsigned char freqh;
-
-	dev->freq=freq;
-
-	freq /= 160;
-	if (!(aci_version==0x07 || aci_version>=0xb0))
-		freq /= 10;  /* I don't know exactly which version
-			      * needs this hack */
-	freql = freq & 0xff;
-	freqh = freq >> 8;
-
-	aci_rds_cmd(RDS_RESET, 0, 0);
-	pcm20_stereo(dev, 1);
-
-	return aci_rw_cmd(0xa7, freql, freqh);	/*  Tune to frequency	*/
-}
-
-static int pcm20_getflags(struct pcm20_device *dev, __u32 *flags, __u16 *signal)
-{
-	/* okay, check for signal, stereo and rds here... */
-	int i;
-	unsigned char buf;
-
-	if ((i=aci_rw_cmd(0xa9, -1, -1))<0)
-		return i;
-#if DEBUG
-	printk("check_sig: 0x%x\n", i);
-#endif
-	if (i & 0x80) {
-		/* no signal from tuner */
-		*flags=0;
-		*signal=0;
-		return 0;
-	} else
-		*signal=0xffff;
-
-	if ((i=aci_rw_cmd(0xa8, -1, -1))<0)
-		return i;
-	if (i & 0x40) {
-		*flags=0;
-	} else {
-		/* stereo */
-		*flags=VIDEO_TUNER_STEREO_ON;
-		/* I cant see stereo, when forced to mono */
-		dev->stereo=1;
-	}
-
-	if ((i=aci_rds_cmd(RDS_STATUS, &buf, 1))<0)
-		return i;
-	if (buf & 1)
-		/* RDS available */
-		*flags|=VIDEO_TUNER_RDS_ON;
-	else
-		return 0;
-
-	if ((i=aci_rds_cmd(RDS_RXVALUE, &buf, 1))<0)
-		return i;
-#if DEBUG
-	printk("rds-signal: %d\n", buf);
-#endif
-	if (buf > 15) {
-		printk("rds-miropcm20: RX strengths unexpected high...\n");
-		buf=15;
-	}
-	/* refine signal */
-	if ((*signal=SCALE(15, 0xffff, buf))==0)
-		*signal = 1;
-
-	return 0;
-}
-
-static int pcm20_ioctl(struct video_device *dev, unsigned int cmd, void *arg)
-{
-	struct pcm20_device *pcm20=dev->priv;
-	int i;
-	
-	switch(cmd)
-	{
-		case VIDIOCGCAP:
-		{
-			struct video_capability v;
-			v.type=VID_TYPE_TUNER;
-			strcpy(v.name, "Miro PCM20");
-			v.channels=1;
-			v.audios=1;
-			/* No we don't do pictures */
-			v.maxwidth=0;
-			v.maxheight=0;
-			v.minwidth=0;
-			v.minheight=0;
-			if(copy_to_user(arg,&v,sizeof(v)))
-				return -EFAULT;
-			return 0;
-		}
-		case VIDIOCGTUNER:
-		{
-			struct video_tuner v;
-			if(copy_from_user(&v, arg,sizeof(v))!=0) 
-				return -EFAULT;
-			if(v.tuner)	/* Only 1 tuner */ 
-				return -EINVAL;
-			v.rangelow=87*16000;
-			v.rangehigh=108*16000;
-			pcm20_getflags(pcm20, &v.flags, &v.signal);
-			v.flags|=VIDEO_TUNER_LOW;
-			v.mode=VIDEO_MODE_AUTO;
-			strcpy(v.name, "FM");
-			if(copy_to_user(arg,&v, sizeof(v)))
-				return -EFAULT;
-			return 0;
-		}
-		case VIDIOCSTUNER:
-		{
-			struct video_tuner v;
-			if(copy_from_user(&v, arg, sizeof(v)))
-				return -EFAULT;
-			if(v.tuner!=0)
-				return -EINVAL;
-			/* Only 1 tuner so no setting needed ! */
-			return 0;
-		}
-		case VIDIOCGFREQ:
-			if(copy_to_user(arg, &pcm20->freq, sizeof(pcm20->freq)))
-				return -EFAULT;
-			return 0;
-		case VIDIOCSFREQ:
-			if(copy_from_user(&pcm20->freq, arg, sizeof(pcm20->freq)))
-				return -EFAULT;
-			i=pcm20_setfreq(pcm20, pcm20->freq);
-#if DEBUG
-			printk("First view (setfreq): 0x%x\n", i);
-#endif
-			return i;
-		case VIDIOCGAUDIO:
-		{	
-			struct video_audio v;
-			memset(&v,0, sizeof(v));
-			v.flags=VIDEO_AUDIO_MUTABLE;
-			if (pcm20->muted)
-				v.flags|=VIDEO_AUDIO_MUTE;
-			v.mode=VIDEO_SOUND_STEREO;
-			if (pcm20->stereo)
-				v.mode|=VIDEO_SOUND_MONO;
-			/* v.step=2048; */
-			strcpy(v.name, "Radio");
-			if(copy_to_user(arg,&v, sizeof(v)))
-				return -EFAULT;
-			return 0;			
-		}
-		case VIDIOCSAUDIO:
-		{
-			struct video_audio v;
-			if(copy_from_user(&v, arg, sizeof(v))) 
-				return -EFAULT;
-			if(v.audio) 
-				return -EINVAL;
-
-			pcm20_mute(pcm20, !!(v.flags&VIDEO_AUDIO_MUTE));
-			if(v.flags&VIDEO_SOUND_MONO)
-				pcm20_stereo(pcm20, 0);
-			if(v.flags&VIDEO_SOUND_STEREO)
-				pcm20_stereo(pcm20, 1);
-
-			return 0;
-		}
-		default:
-			return -ENOIOCTLCMD;
-	}
-}
-
-static int pcm20_open(struct video_device *dev, int flags)
-{
-	if(users)
-		return -EBUSY;
-	users++;
-	return 0;
-}
-
-static void pcm20_close(struct video_device *dev)
-{
-	users--;
-}
-
-static struct pcm20_device pcm20_unit=
-{
-	freq:   87*16000,
-	muted:  1,
-	stereo: 0
-};
-
-static struct video_device pcm20_radio=
-{
-	owner:		THIS_MODULE,
-	name:		"Miro PCM 20 radio",
-	type:		VID_TYPE_TUNER,
-	hardware:	VID_HARDWARE_RTRACK,
-	open:		pcm20_open,
-	close:		pcm20_close,
-	ioctl:		pcm20_ioctl,
-	priv:		&pcm20_unit
-};
-
-static int __init pcm20_init(void)
-{
-	if(video_register_device(&pcm20_radio, VFL_TYPE_RADIO)==-1)
-		return -EINVAL;
-		
-	if(attach_aci_rds()<0) {
-		video_unregister_device(&pcm20_radio);
-		return -EINVAL;
-	}
-#if DEBUG
-	printk("v4l-name: %s\n", devfs_get_name(pcm20_radio.devfs_handle, 0));
-#endif
-	printk(KERN_INFO "Miro PCM20 radio card driver.\n");
-
-	return 0;
-}
-
-MODULE_AUTHOR("Ruurd Reitsma");
-MODULE_DESCRIPTION("A driver for the Miro PCM20 radio card.");
-
-EXPORT_NO_SYMBOLS;
-
-static void __exit pcm20_cleanup(void)
-{
-	unload_aci_rds();
-	video_unregister_device(&pcm20_radio);
-}
-
-module_init(pcm20_init);
-module_exit(pcm20_cleanup);
diff -urN -X dontdiff linux-2.4.4-pre5-vanilla/drivers/media/radio/rds-miropcm20.c linux/drivers/media/radio/rds-miropcm20.c
--- linux-2.4.4-pre5-vanilla/drivers/media/radio/rds-miropcm20.c	Fri Apr 20 02:39:59 2001
+++ linux/drivers/media/radio/rds-miropcm20.c	Thu Jan  1 01:00:00 1970
@@ -1,249 +0,0 @@
-/*
- *  Many thanks to Fred Seidel <seidel@metabox.de>, the
- *  designer of the RDS decoder hardware. With his help
- *  I was able to code this driver.
- *  Thanks also to Norberto Pellicci, Dominic Mounteney
- *  <DMounteney@pinnaclesys.com> and www.teleauskunft.de
- *  for good hints on finding Fred. It was somewhat hard
- *  to locate him here in Germany... [:
- *
- * Revision history:
- *
- *   2000-08-09  Robert Siemer <Robert.Siemer@gmx.de>
- *        RDS support for MiroSound PCM20 radio
- */
-
-#define _NO_VERSION_
-
-/* #include <linux/kernel.h> */
-#include <linux/module.h>
-#include <linux/init.h>
-#include <linux/slab.h>
-#include <asm/semaphore.h>
-#include <asm/io.h>
-#include "../../sound/aci.h"
-
-#define WATCHMASK       0352 /* 11101010 */
-
-#define DEBUG 0
-
-static struct semaphore aci_rds_sem;
-
-
-#define RDS_BUSYMASK        0x10   /* Bit 4 */
-#define RDS_CLOCKMASK       0x08   /* Bit 3 */
-#define RDS_DATAMASK        0x04   /* Bit 2 */
-
-
-static void print_matrix(char array[], unsigned int length)
-{
-        int i, j;
-
-        for (i=0; i<length; i++) {
-                printk("aci-rds: ");
-                for (j=7; j>=0; j--) {
-                        printk("%d", (array[i] >> j) & 0x1);
-                }
-                if (i%8 == 0)
-                        printk(" byte-border\n");
-                else
-                        printk("\n");
-        }
-}
-
-static int byte2trans(unsigned char byte, unsigned char sendbuffer[], int size)
-{
-	int i;
-
-	if (size != 8)
-		return -1;
-	for (i = 7; i >= 0; i--)
-		sendbuffer[7-i] = (byte & (1 << i)) ? RDS_DATAMASK : 0;
-	sendbuffer[0] |= RDS_CLOCKMASK;
-
-	return 0;
-}
-
-static int trans2byte(unsigned char buffer[], int size)
-{
-	int i;
-	unsigned char byte=0;
-
-	if (size != 8)
-		return -1;
-	for (i = 7; i >= 0; i--)
-		byte |= ((buffer[7-i] & RDS_DATAMASK) ? 1 : 0) << i;
-
-	return byte;
-}
-
-static int trans2data(unsigned char readbuffer[], int readsize, unsigned char data[], int datasize)
-{
-	int i,j;
-
-	if (readsize != datasize*8)
-		return -1;
-	for (i = 0; i < datasize; i++)
-		if ((j=trans2byte(&readbuffer[i*8], 8)) < 0)
-			return -1;
-		else
-			data[i]=j;
-	return 0;
-}
-
-static int rds_waitread(void)
-{
-	unsigned char byte;
-	int i=2000;
-
-	do {
-		byte=inb(RDS_REGISTER);
-		if ((byte & WATCHMASK) != WATCHMASK)
-			printk("aci-rds: Hidden information discoverd!\n");
-		i--;
-	}
-	while ((byte & RDS_BUSYMASK) && i);
-
-	if (i) {
-#if DEBUG
-		printk("rds_waitread()");
-		print_matrix(&byte, 1);
-#endif
-		return (byte);
-	} else {
-		printk("aci-rds: rds_waitread() timeout...\n");
-		return -1;
-	}
-}
-
-/* dont use any ..._nowait() function if you are not sure what you do... */
-
-static inline void rds_rawwrite_nowait(unsigned char byte)
-{
-#if DEBUG
-	printk("rds_rawwrite()");
-	print_matrix(&byte, 1);
-#endif
-	outb(byte, RDS_REGISTER);
-}
-
-static int rds_rawwrite(unsigned char byte)
-{
-	if (rds_waitread() >= 0) {
-		rds_rawwrite_nowait(byte);
-		return 0;
-	} else
-		return -1;
-}
-
-static int rds_write(unsigned char cmd)
-{
-	unsigned char sendbuffer[8];
-	int i;
-	
-	if (byte2trans(cmd, sendbuffer, 8) != 0){
-		return -1;
-	} else {
-		for (i=0; i<8; i++) {
-			rds_rawwrite(sendbuffer[i]);
-		}
-	}
-	return 0;
-}
-
-static int rds_readcycle_nowait(void)
-{
-	rds_rawwrite_nowait(0);
-	return rds_waitread();
-}
-
-static int rds_readcycle(void)
-{
-	if (rds_rawwrite(0) < 0)
-		return -1;
-	return rds_waitread();
-}
-
-static int rds_read(unsigned char databuffer[], int datasize)
-{
-
-#define READSIZE (8*datasize)
-
-	int i,j;
-	unsigned char* readbuffer;
-
-	if (!datasize)  /* nothing to read */
-		return 0;
-
-	/* to be able to use rds_readcycle_nowait()
-	   I have to readwait() here */
-	if (rds_waitread() < 0)
-		return -1;
-	
-	if ((readbuffer=kmalloc(READSIZE, GFP_KERNEL)) == 0) {
-		printk("aci-rds: Out of memory...\n");
-		return -ENOMEM;
-	} else {
-		if (signal_pending(current)) {
-			kfree(readbuffer);
-			return -EINTR;
-		}
-	}
-	
-	for (i=0; i< READSIZE; i++)
-		if((j=rds_readcycle_nowait()) < 0) {
-			kfree(readbuffer);
-			return -1;
-		} else
-			readbuffer[i]=j;
-	if (trans2data(readbuffer, READSIZE, databuffer, datasize) < 0) {
-		kfree(readbuffer);
-		return -1;
-	}
-	kfree(readbuffer);
-	return 0;
-}
-
-static int rds_ack(void)
-{
-	int i=rds_readcycle();
-
-	if (i < 0)
-		return -1;
-	if (i & RDS_DATAMASK) {
-		return 0;  /* ACK  */
-	} else {
-		return 1;  /* NACK */
-	}
-}
-
-int aci_rds_cmd(unsigned char cmd, unsigned char databuffer[], int datasize)
-{
-	int ret;
-
-	if (down_interruptible(&aci_rds_sem))
-		return -EINTR;
-
-	if (rds_write(cmd))
-		ret = -2;
-
-	/* RDS_RESET doesn't need further processing */
-	if (cmd!=RDS_RESET && (rds_ack() || rds_read(databuffer, datasize)))
-		ret = -1;
-	else
-		ret = 0;
-
-	up(&aci_rds_sem);
-	
-	return ret;
-}
-
-int __init attach_aci_rds(void)
-{
-	init_MUTEX(&aci_rds_sem);
-	return 0;
-}
-
-void __exit unload_aci_rds(void)
-{
-}
diff -urN -X dontdiff linux-2.4.4-pre5-vanilla/drivers/sound/aci.c linux/drivers/sound/aci.c
--- linux-2.4.4-pre5-vanilla/drivers/sound/aci.c	Fri Apr 20 02:40:18 2001
+++ linux/drivers/sound/aci.c	Fri Apr 20 12:27:07 2001
@@ -45,6 +45,8 @@
  *        ioctl bugfix, and integration of solo-mode into OSS-API,
  *        added (OSS-limited) equalizer support, return value bugfix,
  *        changed param aci_reset to reset, new params: ide, wss.
+ *   2001-04-20  Robert Siemer
+ *        even more cleanups...
  */
 
 #include <linux/kernel.h>
@@ -95,17 +97,19 @@
 MODULE_PARM_DESC(wss,"change between ACI/WSS-mixer; use 0 and 1 - untested"
 		 " default: do nothing; for PCM1-pro only");
 
+#if DEBUG
 static void print_bits(unsigned char c)
 {
 	int j;
 	printk(KERN_DEBUG "aci: ");
 
 	for (j=7; j>=0; j--) {
-		printk(KERN_DEBUG "%d", (c >> j) & 0x1);
+		printk("%d", (c >> j) & 0x1);
 	}
 
-	printk(KERN_DEBUG "\n");
+	printk("\n");
 }
+#endif
 
 /*
  * This busy wait code normally requires less than 15 loops and
@@ -269,12 +273,12 @@
 	int buf;
 
 	/* left channel */
-	if ((buf=aci_indexed_cmd(0xf0, left_index))<0)
+	if ((buf=aci_indexed_cmd(ACI_STATUS, left_index))<0)
 		return buf;
 	vol = SCALE(0x20, 100, buf < 0x20 ? 0x20-buf : 0);
 	
 	/* right channel */
-	if ((buf=aci_indexed_cmd(0xf0, right_index))<0)
+	if ((buf=aci_indexed_cmd(ACI_STATUS, right_index))<0)
 		return buf;
 	vol |= SCALE(0x20, 100, buf < 0x20 ? 0x20-buf : 0) << 8;
 
@@ -342,12 +346,12 @@
 	unsigned int vol;
 
 	/* left channel */
-	if ((buf=aci_indexed_cmd(0xf0, left_index))<0)
+	if ((buf=aci_indexed_cmd(ACI_STATUS, left_index))<0)
 		return buf;
 	vol = eq_aci2oss(buf);
 	
 	/* right channel */
-	if ((buf=aci_indexed_cmd(0xf0, right_index))<0)
+	if ((buf=aci_indexed_cmd(ACI_STATUS, right_index))<0)
 		return buf;
 	vol |= eq_aci2oss(buf) << 8;
 
@@ -399,7 +403,7 @@
 			if (vol > 100)
 				vol = 100;
 			vol = SCALE(100, 3, vol);
-			if ((buf=aci_write_cmd(0x03, vol))<0)
+			if ((buf=aci_write_cmd(ACI_WRITE_IGAIN, vol))<0)
 				return buf;
 			aci_micpreamp = vol;
 			vol = SCALE(3, 100, vol);
@@ -416,7 +420,7 @@
 				vol = 1;
 			else
 				vol = 0;
-			if ((buf=aci_write_cmd(0x0f, vol))<0)
+			if ((buf=aci_write_cmd(ACI_SET_POWERAMP, vol))<0)
 				return buf;
 			aci_amp = vol;
 			if (aci_amp)
@@ -433,7 +437,7 @@
 		/* unset solo when RECSRC for PCM is requested */
 		if (aci_idcode[1]=='B' || aci_idcode[1]=='C') {
 			vol = !(buf & SOUND_MASK_PCM);
-			if ((buf=aci_write_cmd(0xd2, vol))<0)
+			if ((buf=aci_write_cmd(ACI_SET_SOLOMODE, vol))<0)
 				return buf;
 			aci_solo = vol;
 		}
@@ -502,7 +506,8 @@
 		case 'B': /* PCM12 */
 		case 'C': /* PCM20 radio */
 			if (aci_version >= 0xb0) {
-				if ((vol=aci_rw_cmd(0xf0, 0x00, -1))<0)
+				if ((vol=aci_rw_cmd(ACI_STATUS,
+						    ACI_S_GENERAL, -1))<0)
 					return vol;
 				if (vol & 0x20)
 					buf |= SOUND_MASK_PCM;
@@ -555,7 +560,8 @@
 		if (aci_idcode[1]=='B' || aci_idcode[1]=='C') {
 			/* aci_micpreamp or ACI? */
 			if (aci_version >= 0xb0) {
-				if ((buf=aci_indexed_cmd(0xf0, 0x21))<0)
+				if ((buf=aci_indexed_cmd(ACI_STATUS,
+							 ACI_S_READ_IGAIN))<0)
 					return buf;
 			}
 			else
@@ -612,17 +618,17 @@
 
 	/* force ACI into a known state */
 	for (i=0; i<3; i++)
-		if (aci_rw_cmd(0xdf, -1, -1)<0)
+		if (aci_rw_cmd(ACI_ERROR_OP, -1, -1)<0)
 			return -EFAULT;
 
 	/* official this is one aci read call: */
-	if ((aci_idcode[0]=aci_rw_cmd(0xf2, -1, -1))<0 ||
-	    (aci_idcode[1]=aci_rw_cmd(0xf2, -1, -1))<0) {
+	if ((aci_idcode[0]=aci_rw_cmd(ACI_READ_IDCODE, -1, -1))<0 ||
+	    (aci_idcode[1]=aci_rw_cmd(ACI_READ_IDCODE, -1, -1))<0) {
 		printk(KERN_ERR "aci: Failed to read idcode on 0x%03x.\n", aci_port);
 		return -EFAULT;
 	}
 
-	if ((aci_version=aci_rw_cmd(0xf1, -1, -1))<0) {
+	if ((aci_version=aci_rw_cmd(ACI_READ_VERSION, -1, -1))<0) {
 		printk(KERN_ERR "aci: Failed to read version on 0x%03x.\n", aci_port);
 		return -EFAULT;
 	}
@@ -656,22 +662,22 @@
 
 	if (reset) {
 		/* first write()s after reset fail with my PCM20 */
-		if (aci_rw_cmd(0xff, -1, -1)<0 ||
-		    aci_rw_cmd(0xdf, 0xdf, 0xdf)<0 ||
-		    aci_rw_cmd(0xdf, 0xdf, 0xdf)<0)
+		if (aci_rw_cmd(ACI_INIT, -1, -1)<0 ||
+		    aci_rw_cmd(ACI_ERROR_OP, ACI_ERROR_OP, ACI_ERROR_OP)<0 ||
+		    aci_rw_cmd(ACI_ERROR_OP, ACI_ERROR_OP, ACI_ERROR_OP)<0)
 			return -EBUSY;
 	}
 
 	/* the PCM20 is muted after reset (and reboot) */
-	if (aci_rw_cmd(0x0d, 0x00, -1)<0)
+	if (aci_rw_cmd(ACI_SET_MUTE, 0x00, -1)<0)
 		return -EBUSY;
 
 	if (ide>=0)
-		if (aci_rw_cmd(0xd0, !ide, -1)<0)
+		if (aci_rw_cmd(ACI_SET_IDE, !ide, -1)<0)
 			return -EBUSY;
 	
 	if (wss>=0 && aci_idcode[1]=='A')
-		if (aci_rw_cmd(0xd1, !!wss, -1)<0)
+		if (aci_rw_cmd(ACI_SET_WSS, !!wss, -1)<0)
 			return -EBUSY;
 
 	if (!request_region(aci_port, 3, "sound mixer (ACI)"))
diff -urN -X dontdiff linux-2.4.4-pre5-vanilla/drivers/sound/aci.h linux/drivers/sound/aci.h
--- linux-2.4.4-pre5-vanilla/drivers/sound/aci.h	Fri Apr 20 02:40:18 2001
+++ linux/drivers/sound/aci.h	Fri Apr 20 03:09:19 2001
@@ -6,9 +6,6 @@
 extern int aci_version;		/* ACI firmware version	*/
 extern int aci_rw_cmd(int write1, int write2, int write3);
 
-extern char * aci_radio_name;
-extern int aci_rds_cmd(unsigned char cmd, unsigned char databuffer[], int datasize);
-
 #define aci_indexed_cmd(a, b) aci_rw_cmd(a, b, -1)
 #define aci_write_cmd(a, b)   aci_rw_cmd(a, b, -1)
 #define aci_read_cmd(a)       aci_rw_cmd(a,-1, -1)
@@ -19,15 +16,24 @@
 
 #define RDS_REGISTER        BUSY_REGISTER
 
-#define RDS_STATUS      0x01
-#define RDS_STATIONNAME 0x02
-#define RDS_TEXT        0x03
-#define RDS_ALTFREQ     0x04
-#define RDS_TIMEDATE    0x05
-#define RDS_PI_CODE     0x06
-#define RDS_PTYTATP     0x07
-#define RDS_RESET       0x08
-#define RDS_RXVALUE     0x09
+#define ACI_SET_MUTE          0x0d
+#define ACI_SET_POWERAMP      0x0f
+#define ACI_SET_TUNERMUTE     0xa3
+#define ACI_SET_TUNERMONO     0xa4
+#define ACI_SET_IDE           0xd0
+#define ACI_SET_WSS           0xd1
+#define ACI_SET_SOLOMODE      0xd2
+#define ACI_WRITE_IGAIN       0x03
+#define ACI_WRITE_TUNE        0xa7
+#define ACI_READ_TUNERSTEREO  0xa8
+#define ACI_READ_TUNERSTATION 0xa9
+#define ACI_READ_VERSION      0xf1
+#define ACI_READ_IDCODE       0xf2
+#define ACI_INIT              0xff
+#define ACI_STATUS            0xf0
+#define     ACI_S_GENERAL     0x00
+#define     ACI_S_READ_IGAIN  0x21
+#define ACI_ERROR_OP          0xdf
 
 /*
  * The following macro SCALE can be used to scale one integer volume
@@ -47,9 +53,6 @@
  */
 
 #define SCALE(xmax,ymax,x) (((x)*(ymax)+(xmax)/2)/(xmax))
-
-extern void __exit unload_aci_rds(void);
-extern int __init attach_aci_rds(void);
 
 
 #endif  /* _ACI_H_ */
