33 #include <linux/module.h>
37 #include <linux/videodev2.h>
40 #include <linux/sched.h>
48 MODULE_AUTHOR(
"Fred Gleason, Russell Kroll, Quay Lu, Donald Song, Jason Lewis, Scott McGrath, William McGrath");
54 static int radio_nr = -1;
57 MODULE_PARM_DESC(
io,
"I/O address of Cadet card (0x330,0x332,0x334,0x336,0x338,0x33a,0x33c,0x33e)");
60 #define RDS_BUFFER 256
81 static struct cadet cadet_card;
88 static u16 sigtable[2][4] = {
89 { 1835, 2621, 4128, 65535 },
90 { 2185, 4369, 13107, 65535 },
94 static int cadet_getstereo(
struct cadet *
dev)
102 if ((
inb(dev->
io + 1) & 0x40) == 0)
107 static unsigned cadet_gettune(
struct cadet *dev)
117 curvol =
inb(dev->
io + 1);
124 for (i = 0; i < 25; i++) {
125 fifo = (fifo << 1) | ((
inb(dev->
io + 1) >> 7) & 0x01);
136 outb(curvol, dev->
io + 1);
140 static unsigned cadet_getfreq(
struct cadet *dev)
148 fifo = cadet_gettune(dev);
154 return ((fifo & 0x7fff) - 450) * 16;
157 for (i = 0; i < 14; i++) {
158 if ((fifo & 0x01) != 0)
164 freq = (freq * 16) / 1000;
168 static void cadet_settune(
struct cadet *dev,
unsigned fifo)
178 test = (fifo >> 23) & 0x02;
182 for (i = 0; i < 25; i++) {
188 test = 0x1c | ((fifo >> 23) & 0x02);
193 static void cadet_setfreq(
struct cadet *dev,
unsigned freq)
208 for (i = 0; i < 14; i++) {
217 fifo = (freq / 16) + 450;
226 curvol =
inb(dev->
io + 1);
231 for (j = 3; j > -1; j--) {
232 cadet_settune(dev, fifo | (j << 16));
235 outb(curvol, dev->
io + 1);
252 static void cadet_handler(
unsigned long data)
254 struct cadet *dev = (
void *)data;
259 if ((
inb(dev->
io + 1) & 0x20) != 0)
262 while ((
inb(dev->
io) & 0x80) != 0) {
288 static void cadet_start_rds(
struct cadet *dev)
301 struct cadet *dev = video_drvdata(file);
307 cadet_start_rds(dev);
328 static int vidioc_querycap(
struct file *file,
void *
priv,
355 .rangehigh = 1728000,
360 static int vidioc_g_tuner(
struct file *file,
void *
priv,
363 struct cadet *dev = video_drvdata(file);
378 if (
inb(dev->
io + 1) & 0x80)
390 static int vidioc_s_tuner(
struct file *file,
void *priv,
396 static int vidioc_enum_freq_bands(
struct file *file,
void *priv,
403 *band = bands[band->
index];
407 static int vidioc_g_frequency(
struct file *file,
void *priv,
410 struct cadet *dev = video_drvdata(file);
420 static int vidioc_s_frequency(
struct file *file,
void *priv,
423 struct cadet *dev = video_drvdata(file);
451 static int cadet_open(
struct file *file)
453 struct cadet *dev = video_drvdata(file);
460 if (v4l2_fh_is_singular_file(file))
467 static int cadet_release(
struct file *file)
469 struct cadet *dev = video_drvdata(file);
472 if (v4l2_fh_is_singular_file(file) && dev->
rdsstat) {
483 struct cadet *dev = video_drvdata(file);
484 unsigned long req_events = poll_requested_events(wait);
491 cadet_start_rds(dev);
503 .release = cadet_release,
522 .s_ctrl = cadet_s_ctrl,
529 {.
id =
"MSM0c24", .driver_data = 0},
543 if (!pnp_port_valid(dev, 0))
546 io = pnp_port_start(dev, 0);
554 .name =
"radio-cadet",
555 .id_table = cadet_pnp_devices,
556 .probe = cadet_pnp_probe,
564 static void cadet_probe(
struct cadet *dev)
566 static int iovals[8] = { 0x330, 0x332, 0x334, 0x336, 0x338, 0x33a, 0x33c, 0x33e };
569 for (i = 0; i < 8; i++) {
572 cadet_setfreq(dev, bands[1].rangelow);
573 if (cadet_getfreq(dev) == bands[1].rangelow) {
588 static int __init cadet_init(
void)
590 struct cadet *dev = &cadet_card;
610 v4l2_err(v4l2_dev,
"you must set an I/O address with io=0x330, 0x332, 0x334,\n");
611 v4l2_err(v4l2_dev,
"0x336, 0x338, 0x33a, 0x33c or 0x33e\n");
621 v4l2_err(v4l2_dev,
"could not register v4l2_device\n");
632 v4l2_err(v4l2_dev,
"Could not register controls\n");
638 cadet_setfreq(dev, dev->
curfreq);
640 dev->
vdev.v4l2_dev = v4l2_dev;
641 dev->
vdev.fops = &cadet_fops;
642 dev->
vdev.ioctl_ops = &cadet_ioctl_ops;
646 video_set_drvdata(&dev->
vdev, dev);
650 v4l2_info(v4l2_dev,
"ADS Cadet Radio Card at 0x%x\n", dev->
io);
661 static void __exit cadet_exit(
void)
663 struct cadet *dev = &cadet_card;