lkml.org 
[lkml]   [1999]   [Mar]   [20]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
Patch in this message
/
Date
From
SubjectV4L Driver for ADS Cadet Radio Card
This patch adds Video4Linux support for the ADS Cadet Radio Card.  Both AM
and FM tuners are fully supported. Further information on the Cadet card
and this driver, including plans for future development can be found at
http://linux.blackhawke.net.


|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 STARTS ******
diff -u --recursive --new-file
linux-2.2.3/Documentation/Configure.help
linux/Documentation/Configure.help
--- linux-2.2.3/Documentation/Configure.help Wed Mar 17 21:20:41 1999
+++ linux/Documentation/Configure.help Sat Mar 20 15:02:26 1999
@@ -10511,6 +10511,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.3/drivers/Makefile linux/drivers/Makefile
--- linux-2.2.3/drivers/Makefile Fri Nov 20 11:59:01 1998
+++ linux/drivers/Makefile Wed Mar 17 21:30:13 1999
@@ -102,3 +102,7 @@
endif

include $(TOPDIR)/Rules.make
+
+
+
+
diff -u --recursive --new-file linux-2.2.3/drivers/char/Config.in linux/drivers/char/Config.in
--- linux-2.2.3/drivers/char/Config.in Wed Mar 17 21:20:41 1999
+++ linux/drivers/char/Config.in Wed Mar 17 21:30:36 1999
@@ -121,6 +121,10 @@
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
+ if [ "$CONFIG_RADIO_CADET" = "y" ]; then
+ hex ' ADS Cadet I/O port (0x330)' CONFIG_RADIO_CADET_PORT 330
+ fi
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.3/drivers/char/Makefile linux/drivers/char/Makefile
--- linux-2.2.3/drivers/char/Makefile Wed Mar 17 21:20:41 1999
+++ linux/drivers/char/Makefile Wed Mar 17 21:30:53 1999
@@ -388,6 +388,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
@@ -446,6 +454,7 @@
ALL_SUB_DIRS += hfmodem
MOD_SUB_DIRS += hfmodem
endif
+
endif

include $(TOPDIR)/Rules.make
diff -u --recursive --new-file linux-2.2.3/drivers/char/radio-cadet.c linux/drivers/char/radio-cadet.c
--- linux-2.2.3/drivers/char/radio-cadet.c Wed Dec 31 19:00:00 1969
+++ linux/drivers/char/radio-cadet.c Sat Mar 20 10:54:02 1999
@@ -0,0 +1,384 @@
+/* cadet.c - A video4linux driver for the ADS Cadet AM/FM Radio Card
+ *
+ * by Fred Gleason <fredg@wava.com>
+ * Version 0.1.0
+ *
+ * (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;
+ curtuner=0; /* Default the tuner to 87.9 MHz FM */
+ cadet_setfreq(1406);
+ 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))
+{
+ if (check_region(io,2))
+ {
+ printk(KERN_ERR "cadet: port 0x%x already in use\n", io);
+ return -EBUSY;
+ }
+ if(video_register_device(&cadet_radio,VFL_TYPE_RADIO)==-1)
+ return -EINVAL;
+
+ request_region(io,2,"cadet");
+ printk(KERN_INFO "ADS Cadet radio card driver v0.1.0\n");
+ return 0;
+}
+
+#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 radio card.");
+MODULE_PARM(io, "i");
+MODULE_PARM_DESC(io, "I/O address of the Cadet card (0x330)");
+
+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.3/drivers/char/videodev.c linux/drivers/char/videodev.c
--- linux-2.2.3/drivers/char/videodev.c Wed Mar 17 21:20:42 1999
+++ linux/drivers/char/videodev.c Wed Mar 17 21:31:26 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.3/include/linux/videodev.h linux/include/linux/videodev.h
--- linux-2.2.3/include/linux/videodev.h Wed Mar 17 21:20:22 1999
+++ linux/include/linux/videodev.h Sat Mar 20 11:01:28 1999
@@ -273,6 +273,7 @@
#define VID_HARDWARE_PLANB 16 /* PowerMac motherboard video-in */
#define VID_HARDWARE_BROADWAY 17 /* Broadway project */
#define VID_HARDWARE_GEMTEK 18
+#define VID_HARDWARE_CADET 19
#define VID_HARDWARE_TYPHOON 19
#define VID_HARDWARE_VINO 20 /* Reserved for SGI Indy Vino */
****** 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/

\
 
 \ /
  Last update: 2005-03-22 13:50    [from the cache]
©2003-2011 Jasper Spaans