New video4linux driver for AIMSlab RadioTrack II

Ben Pfaff (pfaffben@pilot.msu.edu)
Mon, 27 Jul 1998 00:10:37 -0400 (EDT)


Here is a patch against a clean 2.1.111 tree that adds support for the
AIMSlab RadioTrack II, which has a different chipset from the original
RadioTrack (but packaged in an identical box!). Alan, I'm sending it
to you because you appear to be the main video4linux maintainer. I
hope that you can add it to your patches--if I should instead send it
directly to Linus, or someone else, please let me know.

RadioTrack II is based on a Philips TEA5757H FM radio receiver chip
and an AMD PALCE20V8H-15 programmable logic array. I devised this
driver from looking at the data sheets and from examining the behavior
of the Windows 95 driver in a binary 80x86 emulator.

Thanks,

Ben.

diff -urpN --exclude=*~ linux-2.1.111-clean/Documentation/Configure.help linux-2.1.111-rtrack2/Documentation/Configure.help
--- linux-2.1.111-clean/Documentation/Configure.help Sun Jul 26 23:29:52 1998
+++ linux-2.1.111-rtrack2/Documentation/Configure.help Sun Jul 26 23:44:08 1998
@@ -9169,6 +9169,10 @@ CONFIG_RADIO_RTRACK
Choose Y here if you have one of these FM radio cards, and then fill
in the port address below.

+ Note that newer AIMSlab RadioTrack cards have a different chipset,
+ not supported by this driver. For these cards, use the RadioTrack II
+ driver below.
+
In order to control your radio card, you will need to use programs
that are compatible with the Video for Linux API. Information on
this API and pointers to "v4l" programs may be found on the WWW at
@@ -9179,11 +9183,33 @@ CONFIG_RADIO_RTRACK
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-aimslab.o.
+ called radio-rtrack2.o.

RadioTrack i/o port
CONFIG_RADIO_RTRACK_PORT
Enter either 0x30f or 0x20f here. The card default is 0x30f, if you
+ haven't changed the jumper setting on the card.
+
+AIMSlab RadioTrack II support
+CONFIG_RADIO_RTRACK2
+ Choose Y here if you have this FM radio card, and then fill in the
+ port address below.
+
+ In order to control your radio card, you will need to use programs
+ that are compatible with the Video for Linux API. Information on
+ this API and pointers to "v4l" programs may be found on the WWW at
+ http://roadrunner.swansea.uk.linux.org/v4l.shtml; to browse the WWW,
+ you need to have access to a machine on the Internet that has a
+ program like lynx or netscape.
+
+ 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-aimslab.o.
+
+RadioTrack II i/o port
+CONFIG_RADIO_RTRACK2_PORT
+ Enter either 0x30c or 0x20c here. The card default is 0x30c, if you
haven't changed the jumper setting on the card.

Aztech/Packard Bell Radio
diff -urpN --exclude=*~ linux-2.1.111-clean/drivers/char/Config.in linux-2.1.111-rtrack2/drivers/char/Config.in
--- linux-2.1.111-clean/drivers/char/Config.in Sun Jul 26 23:29:52 1998
+++ linux-2.1.111-rtrack2/drivers/char/Config.in Sun Jul 26 23:44:56 1998
@@ -109,6 +109,10 @@ if [ "$CONFIG_VIDEO_DEV" != "n" ]; then
if [ "$CONFIG_RADIO_RTRACK" = "y" ]; then
hex ' RadioTrack i/o port (0x20f or 0x30f)' CONFIG_RADIO_RTRACK_PORT 20f
fi
+ dep_tristate 'AIMSlab RadioTrack II support' CONFIG_RADIO_RTRACK2 $CONFIG_VIDEO_DEV
+ if [ "$CONFIG_RADIO_RTRACK2" = "y" ]; then
+ hex ' RadioTrack II i/o port (0x20c or 0x30c)' CONFIG_RADIO_RTRACK2_PORT 30c
+ fi
dep_tristate 'Aztech/Packard Bell Radio' CONFIG_RADIO_AZTECH $CONFIG_VIDEO_DEV
if [ "$CONFIG_RADIO_AZTECH" = "y" ]; then
hex ' Aztech/Packard Bell I/O port (0x350 or 0x358)' CONFIG_RADIO_AZTECH_PORT 350
diff -urpN --exclude=*~ linux-2.1.111-clean/drivers/char/Makefile linux-2.1.111-rtrack2/drivers/char/Makefile
--- linux-2.1.111-clean/drivers/char/Makefile Sun Jul 26 23:29:52 1998
+++ linux-2.1.111-rtrack2/drivers/char/Makefile Sun Jul 26 23:50:56 1998
@@ -381,6 +381,14 @@ else
endif
endif

+ifeq ($(CONFIG_RADIO_RTRACK2),y)
+L_OBJS += radio-rtrack2.o
+else
+ ifeq ($(CONFIG_RADIO_RTRACK2),m)
+ M_OBJS += radio-rtrack2.o
+ endif
+endif
+
ifeq ($(CONFIG_RADIO_ZOLTRIX),y)
L_OBJS += radio-zoltrix.o
else
diff -urpN --exclude=*~ linux-2.1.111-clean/drivers/char/radio-rtrack2.c linux-2.1.111-rtrack2/drivers/char/radio-rtrack2.c
--- linux-2.1.111-clean/drivers/char/radio-rtrack2.c Wed Dec 31 19:00:00 1969
+++ linux-2.1.111-rtrack2/drivers/char/radio-rtrack2.c Sun Jul 26 23:53:57 1998
@@ -0,0 +1,284 @@
+/* RadioTrack II driver for Linux radio support (C) 1998 Ben Pfaff
+ *
+ * Based on RadioTrack I/RadioReveal (C) 1997 M. Kirkwood
+ * Coverted to new API by Alan Cox <Alan.Cox@linux.org>
+ * Various bugfixes and enhancements by Russell Kroll <rkroll@exploits.org>
+ *
+ * TODO: Allow for more than one of these foolish entities :-)
+ *
+ */
+
+#include <linux/module.h> /* Modules */
+#include <linux/init.h> /* Initdata */
+#include <linux/ioport.h> /* check_region, request_region */
+#include <linux/delay.h> /* udelay */
+#include <asm/io.h> /* outb, outb_p */
+#include <asm/uaccess.h> /* copy to/from user */
+#include <linux/videodev.h> /* kernel radio structs */
+#include <linux/config.h> /* CONFIG_RADIO_RTRACK2_PORT */
+
+#ifndef CONFIG_RADIO_RTRACK2_PORT
+#define CONFIG_RADIO_RTRACK2_PORT -1
+#endif
+
+static int io = CONFIG_RADIO_RTRACK2_PORT;
+static int users = 0;
+
+struct rt_device
+{
+ int port;
+ unsigned long curfreq;
+ int muted;
+};
+
+
+/* local things */
+
+static void rt_mute(struct rt_device *dev)
+{
+ if(dev->muted)
+ return;
+ outb(1, io);
+ dev->muted = 1;
+}
+
+static void rt_unmute(struct rt_device *dev)
+{
+ if(dev->muted == 0)
+ return;
+ outb(0, io);
+ dev->muted = 0;
+}
+
+static void zero(void)
+{
+ outb_p(1, io);
+ outb_p(3, io);
+ outb_p(1, io);
+}
+
+static void one(void)
+{
+ outb_p(5, io);
+ outb_p(7, io);
+ outb_p(5, io);
+}
+
+static int rt_setfreq(struct rt_device *dev, unsigned long freq)
+{
+ int i;
+
+/* The RadioTrack II card allows tuning in 12.5kHz increments.
+ Unfortunately many userspace programs assume that radio cards only
+ handle tuning in 62.5kHz increments. These programs are
+ incompatible with precise tuning. */
+/*#define PRECISE_TUNING 1*/
+#if PRECISE_TUNING
+ freq = freq / 200 + 856;
+#else
+ freq = freq * 5 + 856;
+#endif
+
+ outb_p(0xc8, io);
+ outb_p(0xc9, io);
+ outb_p(0xc9, io);
+
+ for (i = 0; i < 10; i++)
+ zero ();
+
+ for (i = 14; i >= 0; i--)
+ if (freq & (1 << i))
+ one ();
+ else
+ zero ();
+
+ outb_p(0xc8, io);
+ if (!dev->muted)
+ outb_p(0, io);
+ return 0;
+}
+
+int rt_getsigstr(struct rt_device *dev)
+{
+ if (inb(io) & 4) /* bit set = no signal present */
+ return 0;
+ return 1; /* signal present */
+}
+
+static int rt_ioctl(struct video_device *dev, unsigned int cmd, void *arg)
+{
+ struct rt_device *rt=dev->priv;
+
+ switch(cmd)
+ {
+ case VIDIOCGCAP:
+ {
+ struct video_capability v;
+ v.type=VID_TYPE_TUNER;
+ 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=(int)(88.0*16);
+ v.rangehigh=(int)(108.0*16);
+#if PRECISE_TUNING
+ v.flags=VIDEO_TUNER_LOW;
+#else
+ v.flags=0;
+#endif
+ v.mode=VIDEO_MODE_AUTO;
+ v.signal=0xFFFF*rt_getsigstr(rt);
+ 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, &rt->curfreq, sizeof(rt->curfreq)))
+ return -EFAULT;
+ return 0;
+ case VIDIOCSFREQ:
+ if(copy_from_user(&rt->curfreq, arg,sizeof(rt->curfreq)))
+ return -EFAULT;
+ rt_setfreq(rt, rt->curfreq);
+ return 0;
+ case VIDIOCGAUDIO:
+ {
+ struct video_audio v;
+ memset(&v,0, sizeof(v));
+ v.flags|=VIDEO_AUDIO_MUTABLE;
+ v.volume=1;
+ 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;
+
+ if(v.flags&VIDEO_AUDIO_MUTE)
+ rt_mute(rt);
+ else
+ rt_unmute(rt);
+
+ return 0;
+ }
+ default:
+ return -ENOIOCTLCMD;
+ }
+}
+
+static int rt_open(struct video_device *dev, int flags)
+{
+ if(users)
+ return -EBUSY;
+ users++;
+ MOD_INC_USE_COUNT;
+ return 0;
+}
+
+static void rt_close(struct video_device *dev)
+{
+ users--;
+ MOD_DEC_USE_COUNT;
+}
+
+static struct rt_device rtrack2_unit;
+
+static struct video_device rtrack2_radio=
+{
+ "RadioTrack II radio",
+ VID_TYPE_TUNER,
+ VID_HARDWARE_RTRACK2,
+ rt_open,
+ rt_close,
+ NULL, /* Can't read (no capture ability) */
+ NULL, /* Can't write */
+ rt_ioctl,
+ NULL,
+ NULL
+};
+
+__initfunc(int rtrack2_init(struct video_init *v))
+{
+ if (check_region(io, 4))
+ {
+ printk(KERN_ERR "rtrack2: port 0x%x already in use\n", io);
+ return -EBUSY;
+ }
+
+ rtrack2_radio.priv=&rtrack2_unit;
+
+ if(video_register_device(&rtrack2_radio, VFL_TYPE_RADIO)==-1)
+ return -EINVAL;
+
+ request_region(io, 4, "rtrack2");
+ printk(KERN_INFO "AIMSlab Radiotrack II card driver.\n");
+
+ /* mute card - prevents noisy bootups */
+ outb(1, io);
+ rtrack2_unit.muted = 1;
+
+ return 0;
+}
+
+#ifdef MODULE
+
+MODULE_AUTHOR("Ben Pfaff");
+MODULE_DESCRIPTION("A driver for the RadioTrack II radio card.");
+MODULE_PARM(io, "i");
+MODULE_PARM_DESC(io, "I/O address of the RadioTrack card (0x20c or 0x30c)");
+
+EXPORT_NO_SYMBOLS;
+
+int init_module(void)
+{
+ if(io==-1)
+ {
+ printk(KERN_ERR "You must set an I/O address with io=0x20c or io=0x30c\n");
+ return -EINVAL;
+ }
+ return rtrack2_init(NULL);
+}
+
+void cleanup_module(void)
+{
+ video_unregister_device(&rtrack2_radio);
+ release_region(io,4);
+}
+
+#endif
+
+/*
+ Local variables:
+ compile-command: "gcc -c -DMODVERSIONS -D__KERNEL__ -DMODULE -O6 -Wall -Wstrict-prototypes radio-rtrack2.c"
+ End:
+*/
diff -urpN --exclude=*~ linux-2.1.111-clean/include/linux/videodev.h linux-2.1.111-rtrack2/include/linux/videodev.h
--- linux-2.1.111-clean/include/linux/videodev.h Sun Jul 26 23:29:56 1998
+++ linux-2.1.111-rtrack2/include/linux/videodev.h Sun Jul 26 23:40:37 1998
@@ -205,6 +205,7 @@ struct video_key
#define VID_HARDWARE_ZOLTRIX 10
#define VID_HARDWARE_SAA7146 11
#define VID_HARDWARE_VIDEUM 12 /* Reserved for Winnov videum */
+#define VID_HARDWARE_RTRACK2 13

/*
* Initialiser list

-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.rutgers.edu
Please read the FAQ at http://www.altern.org/andrebalsa/doc/lkml-faq.html