More information on the card, along with plans for further future
development of the driver can be found at:
http://linux.blackhawke.net/cadet.html.
|Frederick F. Gleason, Jr.|WAVA Radio - 105 FM |Voice: 1-(703)-807-2266 |
| Chief Engineer |1901 N. Moore Street| FAX: 1-(703)-807-2248 |
| |Arlington, VA 22209 | Web: HTTP://www.wava.com|
--- Patch Begins ---
diff -u --recursive --new-file linux-2.2.5/Documentation/Configure.help linux/Documentation/Configure.help
--- linux-2.2.5/Documentation/Configure.help Mon Mar 29 21:02:54 1999
+++ linux/Documentation/Configure.help Mon Mar 29 21:06:56 1999
@@ -10533,6 +10533,30 @@
haven't changed the setting of jumper JP3 on the card. Removing the
jumper sets the card to 0x358.
+ADS Cadet AM/FM Radio Tuner Card
+CONFIG_RADIO_CADET
+ Choose Y here if you have one of these AM/FM radio cards, 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.
+
+ Further documentation on this driver can be found on the WWW at
+ http://linux.blackhawke.net/cadet.html.
+
+ 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-cadet.o.
+
+ADS Cadet AM/FM Radio Tuner Card I/O Port
+CONFIG_RADIO_CADET_PORT
+ Enter the I/O address of the card here (most commonly 330).
+
SF16FMI Radio
CONFIG_RADIO_SF16FMI
Choose Y here if you have one of these FM radio cards, and then fill
diff -u --recursive --new-file linux-2.2.5/drivers/Makefile linux/drivers/Makefile
--- linux-2.2.5/drivers/Makefile Fri Nov 20 11:59:01 1998
+++ linux/drivers/Makefile Mon Mar 29 21:06:56 1999
@@ -102,3 +102,7 @@
endif
include $(TOPDIR)/Rules.make
+
+
+
+
diff -u --recursive --new-file linux-2.2.5/drivers/char/Config.in linux/drivers/char/Config.in
--- linux-2.2.5/drivers/char/Config.in Mon Mar 29 21:02:55 1999
+++ linux/drivers/char/Config.in Mon Mar 29 21:08:11 1999
@@ -123,6 +123,7 @@
if [ "$CONFIG_RADIO_AZTECH" = "y" ]; then
hex ' Aztech/Packard Bell I/O port (0x350 or 0x358)' CONFIG_RADIO_AZTECH_PORT 350
fi
+ dep_tristate 'ADS Cadet AM/FM Tuner' CONFIG_RADIO_CADET $CONFIG_VIDEO_DEV
dep_tristate 'Miro PCM20 Radio' CONFIG_RADIO_MIROPCM20 $CONFIG_VIDEO_DEV
dep_tristate 'GemTek Radio Card support' CONFIG_RADIO_GEMTEK $CONFIG_VIDEO_DEV
if [ "$CONFIG_RADIO_GEMTEK" = "y" ]; then
diff -u --recursive --new-file linux-2.2.5/drivers/char/Makefile linux/drivers/char/Makefile
--- linux-2.2.5/drivers/char/Makefile Mon Mar 29 21:02:55 1999
+++ linux/drivers/char/Makefile Mon Mar 29 21:06:56 1999
@@ -401,6 +401,14 @@
endif
endif
+ifeq ($(CONFIG_RADIO_CADET),y)
+L_OBJS += radio-cadet.o
+else
+ ifeq ($(CONFIG_RADIO_CADET),m)
+ M_OBJS += radio-cadet.o
+ endif
+endif
+
ifeq ($(CONFIG_RADIO_MIROPCM20),y)
L_OBJS += radio-miropcm20.o
else
@@ -459,6 +467,7 @@
ALL_SUB_DIRS += hfmodem
MOD_SUB_DIRS += hfmodem
endif
+
endif
include $(TOPDIR)/Rules.make
diff -u --recursive --new-file linux-2.2.5/drivers/char/radio-cadet.c linux/drivers/char/radio-cadet.c
--- linux-2.2.5/drivers/char/radio-cadet.c Wed Dec 31 19:00:00 1969
+++ linux/drivers/char/radio-cadet.c Wed Mar 31 22:54:14 1999
@@ -0,0 +1,403 @@
+/* cadet.c - A video4linux driver for the ADS Cadet AM/FM Radio Card
+ *
+ * by Fred Gleason <fredg@wava.com>
+ * Version 0.1.2
+ *
+ * (Loosely) based on code for the Aztech radio card by
+ *
+ * Russell Kroll (rkroll@exploits.org)
+ * Quay Ly
+ * Donald Song
+ * Jason Lewis (jlewis@twilight.vtc.vsc.edu)
+ * Scott McGrath (smcgrath@twilight.vtc.vsc.edu)
+ * William McGrath (wmcgrath@twilight.vtc.vsc.edu)
+ *
+*/
+
+#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_CADET_PORT */
+
+#ifndef CONFIG_RADIO_CADET_PORT
+#define CONFIG_RADIO_CADET_PORT 0x330
+#endif
+
+static int io=CONFIG_RADIO_CADET_PORT;
+static int users=0;
+static int curtuner=0;
+
+static int cadet_getstereo(void)
+{
+ if(curtuner!=0) { /* Only FM has stereo capability! */
+ return 0;
+ }
+ outb(7,io); /* Select tuner control */
+ if((inb(io+1)&0x40)==0) {
+ return 1; /* Stereo pilot detected */
+ }
+ else {
+ return 0; /* Mono */
+ }
+}
+
+
+static unsigned cadet_getfreq(void)
+{
+ int curvol,i;
+ unsigned freq=0,test,fifo=0;
+
+
+ /*
+ * Prepare for read
+ */
+ outb(7,io); /* Select tuner control */
+ curvol=inb(io+1); /* Save current volume/mute setting */
+ outb(0x00,io+1); /* Ensure WRITE-ENABLE is LOW */
+
+ /*
+ * Read the shift register
+ */
+ for(i=0;i<25;i++) {
+ fifo=(fifo<<1)|((inb(io+1)>>7)&0x01);
+ if(i<24) {
+ outb(0x01,io+1);
+ outb(0x00,io+1);
+ }
+ }
+
+ /*
+ * Restore volume/mute setting
+ */
+ outb(curvol,io+1);
+
+ /*
+ * Convert to actual frequency
+ */
+ if(curtuner==0) { /* FM */
+ test=12500;
+ for(i=0;i<14;i++) {
+ if((fifo&0x01)!=0) {
+ freq+=test;
+ }
+ test=test<<1;
+ fifo=fifo>>1;
+ }
+ freq-=10700000; /* IF frequency is 10.7 MHz */
+ freq=(freq*16)/1000000; /* Make it 1/16 MHz */
+ }
+ if(curtuner==1) { /* AM */
+ freq=((fifo&0x7fff)-2010)*16;
+ }
+
+ return freq;
+}
+
+
+static void cadet_setfreq(unsigned freq)
+{
+ unsigned fifo;
+ int i,test;
+ int curvol;
+
+ /*
+ * Formulate a fifo command
+ */
+ fifo=0;
+ if(curtuner==0) { /* FM */
+ test=102400;
+ freq=(freq*1000)/16; /* Make it kHz */
+ freq+=10700; /* IF is 10700 kHz */
+ for(i=0;i<14;i++) {
+ fifo=fifo<<1;
+ if(freq>=test) {
+ fifo|=0x01;
+ freq-=test;
+ }
+ test=test>>1;
+ }
+ }
+ if(curtuner==1) { /* AM */
+ fifo=(freq/16)+2010; /* Make it kHz */
+ fifo|=0x100000; /* Select AM Band */
+ }
+
+ /*
+ * Save current volume/mute setting
+ */
+ curvol=inb(io+1);
+
+ /*
+ * Write the shift register
+ */
+ test=0;
+ test=(fifo>>23)&0x02; /* Align data for SDO */
+ test|=0x1c; /* SDM=1, SWE=1, SEN=1, SCK=0 */
+ outb(7,io); /* Select tuner control */
+ outb(test,io+1); /* Initialize for write */
+ for(i=0;i<25;i++) {
+ test|=0x01; /* Toggle SCK High */
+ outb(test,io+1);
+ test&=0xfe; /* Toggle SCK Low */
+ outb(test,io+1);
+ fifo=fifo<<1; /* Prepare the next bit */
+ test=0x1c|((fifo>>23)&0x02);
+ outb(test,io+1);
+ }
+ /*
+ * Restore volume/mute setting
+ */
+ outb(curvol,io+1);
+}
+
+
+static int cadet_getvol(void)
+{
+ outb(7,io); /* Select tuner control */
+ if((inb(io+1)&0x20)!=0) {
+ return 0xffff;
+ }
+ else {
+ return 0;
+ }
+}
+
+
+static void cadet_setvol(int vol)
+{
+ outb(7,io); /* Select tuner control */
+ if(vol>0) {
+ outb(0x20,io+1);
+ }
+ else {
+ outb(0x00,io+1);
+ }
+}
+
+
+static int cadet_ioctl(struct video_device *dev, unsigned int cmd, void *arg)
+{
+ unsigned freq;
+ switch(cmd)
+ {
+ case VIDIOCGCAP:
+ {
+ struct video_capability v;
+ v.type=VID_TYPE_TUNER;
+ v.channels=2;
+ v.audios=1;
+ /* No we don't do pictures */
+ v.maxwidth=0;
+ v.maxheight=0;
+ v.minwidth=0;
+ v.minheight=0;
+ strcpy(v.name, "ADS Cadet");
+ 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<0)||(v.tuner>1)) {
+ return -EINVAL;
+ }
+ switch(v.tuner) {
+ case 0:
+ strcpy(v.name,"FM");
+ v.rangelow=1400; /* 87.5 MHz */
+ v.rangehigh=1728; /* 108.0 MHz */
+ v.flags=0;
+ v.mode=0;
+ v.mode|=VIDEO_MODE_AUTO;
+ v.signal=0;
+ if(cadet_getstereo()==1) {
+ v.flags|=VIDEO_TUNER_STEREO_ON;
+ }
+ if(copy_to_user(arg,&v, sizeof(v))) {
+ return -EFAULT;
+ }
+ break;
+ case 1:
+ strcpy(v.name,"AM");
+ v.rangelow=8320; /* 520 kHz */
+ v.rangehigh=26400; /* 1650 kHz */
+ v.flags=0;
+ v.flags|=VIDEO_TUNER_LOW;
+ v.mode=0;
+ v.mode|=VIDEO_MODE_AUTO;
+ v.signal=0;
+ if(copy_to_user(arg,&v, sizeof(v))) {
+ return -EFAULT;
+ }
+ break;
+ }
+ return 0;
+ }
+ case VIDIOCSTUNER:
+ {
+ struct video_tuner v;
+ if(copy_from_user(&v, arg, sizeof(v))) {
+ return -EFAULT;
+ }
+ if((v.tuner<0)||(v.tuner>1)) {
+ return -EINVAL;
+ }
+ curtuner=v.tuner;
+ return 0;
+ }
+ case VIDIOCGFREQ:
+ freq=cadet_getfreq();
+ if(copy_to_user(arg, &freq, sizeof(freq)))
+ return -EFAULT;
+ return 0;
+ case VIDIOCSFREQ:
+ if(copy_from_user(&freq, arg,sizeof(freq)))
+ return -EFAULT;
+ if((curtuner==0)&&((freq<1400)||(freq>1728))) {
+ return -EINVAL;
+ }
+ if((curtuner==1)&&((freq<8320)||(freq>26400))) {
+ return -EINVAL;
+ }
+ cadet_setfreq(freq);
+ return 0;
+ case VIDIOCGAUDIO:
+ {
+ struct video_audio v;
+ memset(&v,0, sizeof(v));
+ v.flags=VIDEO_AUDIO_MUTABLE|VIDEO_AUDIO_VOLUME;
+ if(cadet_getstereo()==0) {
+ v.mode=VIDEO_SOUND_MONO;
+ }
+ else {
+ v.mode=VIDEO_SOUND_STEREO;
+ }
+ v.volume=cadet_getvol();
+ v.step=0xffff;
+ 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;
+ cadet_setvol(v.volume);
+ if(v.flags&VIDEO_AUDIO_MUTE)
+ cadet_setvol(0);
+ else
+ cadet_setvol(0xffff);
+ return 0;
+ }
+ default:
+ return -ENOIOCTLCMD;
+ }
+}
+
+
+static int cadet_open(struct video_device *dev, int flags)
+{
+ if(users)
+ return -EBUSY;
+ users++;
+ MOD_INC_USE_COUNT;
+ return 0;
+}
+
+static void cadet_close(struct video_device *dev)
+{
+ users--;
+ MOD_DEC_USE_COUNT;
+}
+
+
+static struct video_device cadet_radio=
+{
+ "Cadet radio",
+ VID_TYPE_TUNER,
+ VID_HARDWARE_CADET,
+ cadet_open,
+ cadet_close,
+ NULL, /* Can't read (no capture ability) */
+ NULL, /* Can't write */
+ NULL, /* No poll */
+ cadet_ioctl,
+ NULL,
+ NULL
+};
+
+__initfunc(int cadet_init(struct video_init *v))
+{
+#ifndef MODULE
+ if(cadet_probe()<0) {
+ return EINVAL;
+ }
+#endif
+ if(video_register_device(&cadet_radio,VFL_TYPE_RADIO)==-1)
+ return -EINVAL;
+
+ request_region(io,2,"cadet");
+ printk(KERN_INFO "ADS Cadet Radio Card at %x\n",io);
+ return 0;
+}
+
+
+static int cadet_probe(void)
+{
+ static int iovals[8]={0x330,0x332,0x334,0x336,0x338,0x33a,0x33c,0x33e};
+ int i;
+
+ for(i=0;i<8;i++) {
+ io=iovals[i];
+ if(check_region(io,2)) {
+ return -1;
+ }
+ cadet_setfreq(1410);
+ if(cadet_getfreq()==1410) {
+ return io;
+ }
+ }
+ return -1;
+}
+
+
+
+#ifdef MODULE
+
+MODULE_AUTHOR("Fred Gleason, Russell Kroll, Quay Lu, Donald Song, Jason Lewis, Scott McGrath, William McGrath");
+MODULE_DESCRIPTION("A driver for the ADS Cadet AM/FM/RDS radio card.");
+MODULE_PARM(io, "i");
+MODULE_PARM_DESC(io, "I/O address of Cadet card (0x330,0x332,0x334,0x336,0x338,0x33a,0x33c,0x33e)");
+
+EXPORT_NO_SYMBOLS;
+
+int init_module(void)
+{
+ if(io==-1)
+ {
+ printk(KERN_ERR "You must set an I/O address with io=0x???\n");
+ return -EINVAL;
+ }
+ return cadet_init(NULL);
+}
+
+void cleanup_module(void)
+{
+ video_unregister_device(&cadet_radio);
+ release_region(io,2);
+}
+
+#endif
+
diff -u --recursive --new-file linux-2.2.5/drivers/char/videodev.c linux/drivers/char/videodev.c
--- linux-2.2.5/drivers/char/videodev.c Wed Mar 17 21:20:42 1999
+++ linux/drivers/char/videodev.c Mon Mar 29 21:06:56 1999
@@ -75,6 +75,9 @@
#ifdef CONFIG_RADIO_TYPHOON
extern int typhoon_init(struct video_init *);
#endif
+#ifdef CONFIG_RADIO_CADET
+extern int cadet_init(struct video_init *);
+#endif
#ifdef CONFIG_VIDEO_PMS
extern int init_pms_cards(struct video_init *);
#endif
@@ -111,6 +114,9 @@
#ifdef CONFIG_RADIO_MIROPCM20
{"PCM20", pcm20_init},
#endif
+#ifdef CONFIG_RADIO_CADET
+ {"Cadet", cadet_init},
+#endif
#ifdef CONFIG_RADIO_GEMTEK
{"GemTek", gemtek_init},
#endif
@@ -429,6 +435,12 @@
{
unregister_chrdev(VIDEO_MAJOR, "video_capture");
}
+
+
+
+
+
+
#endif
diff -u --recursive --new-file linux-2.2.5/include/linux/videodev.h linux/include/linux/videodev.h
--- linux-2.2.5/include/linux/videodev.h Wed Mar 17 21:20:22 1999
+++ linux/include/linux/videodev.h Mon Mar 29 21:58:40 1999
@@ -275,6 +275,7 @@
#define VID_HARDWARE_GEMTEK 18
#define VID_HARDWARE_TYPHOON 19
#define VID_HARDWARE_VINO 20 /* Reserved for SGI Indy Vino */
+#define VID_HARDWARE_CADET 21
/*
* Initialiser list
--- Patch Ends ---
-
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.tux.org/lkml/