1 /* Terratec ActiveRadio ISA Standalone card driver for Linux radio support
2 * (c) 1999 R. Offermanns (rolf@offermanns.de)
3 * based on the aimslab radio driver from M. Kirkwood
4 * many thanks to Michael Becker and Friedhelm Birth (from TerraTec)
8 * 1999-05-21 First preview release
10 * Notes on the hardware:
11 * There are two "main" chips on the card:
12 * - Philips OM5610 (http://www-us.semiconductors.philips.com/acrobat/datasheets/OM5610_2.pdf)
13 * - Philips SAA6588 (http://www-us.semiconductors.philips.com/acrobat/datasheets/SAA6588_1.pdf)
14 * (you can get the datasheet at the above links)
16 * Frequency control is done digitally -- ie out(port,encodefreq(95.8));
17 * Volume Control is done digitally
19 * Converted to the radio-isa framework by Hans Verkuil <hans.verkuil@cisco.com>
20 * Converted to V4L2 API by Mauro Carvalho Chehab <mchehab@infradead.org>
23 #include <linux/module.h> /* Modules */
24 #include <linux/init.h> /* Initdata */
25 #include <linux/ioport.h> /* request_region */
26 #include <linux/videodev2.h> /* kernel radio structs */
27 #include <linux/mutex.h>
28 #include <linux/io.h> /* outb, outb_p */
29 #include <linux/slab.h>
30 #include <media/v4l2-device.h>
31 #include <media/v4l2-ioctl.h>
32 #include "radio-isa.h"
34 MODULE_AUTHOR("R. Offermans & others");
35 MODULE_DESCRIPTION("A driver for the TerraTec ActiveRadio Standalone radio card.");
36 MODULE_LICENSE("GPL");
37 MODULE_VERSION("0.1.99");
39 /* Note: there seems to be only one possible port (0x590), but without
40 hardware this is hard to verify. For now, this is the only one we will
42 static int io
= 0x590;
43 static int radio_nr
= -1;
45 module_param(radio_nr
, int, 0444);
46 MODULE_PARM_DESC(radio_nr
, "Radio device number");
56 static struct radio_isa_card
*terratec_alloc(void)
58 return kzalloc(sizeof(struct radio_isa_card
), GFP_KERNEL
);
61 static int terratec_s_mute_volume(struct radio_isa_card
*isa
, bool mute
, int vol
)
67 vol
= vol
+ (vol
* 32); /* change both channels */
68 for (i
= 0; i
< 8; i
++) {
69 if (vol
& (0x80 >> i
))
70 outb(0x80, isa
->io
+ 1);
72 outb(0x00, isa
->io
+ 1);
78 /* this is the worst part in this driver */
79 /* many more or less strange things are going on here, but hey, it works :) */
81 static int terratec_s_frequency(struct radio_isa_card
*isa
, u32 freq
)
87 unsigned char buffer
[25]; /* we have to bit shift 25 registers */
89 freq
= freq
/ 160; /* convert the freq. to a nice to handle value */
90 memset(buffer
, 0, sizeof(buffer
));
92 rest
= freq
* 10 + 10700; /* I once had understood what is going on here */
93 /* maybe some wise guy (friedhelm?) can comment this stuff */
98 if (rest
% temp
== rest
)
109 for (i
= 24; i
> -1; i
--) { /* bit shift the values to the radiocard */
110 if (buffer
[i
] == 1) {
111 outb(WRT_EN
| DATA
, isa
->io
);
112 outb(WRT_EN
| DATA
| CLK_ON
, isa
->io
);
113 outb(WRT_EN
| DATA
, isa
->io
);
115 outb(WRT_EN
| 0x00, isa
->io
);
116 outb(WRT_EN
| 0x00 | CLK_ON
, isa
->io
);
123 static u32
terratec_g_signal(struct radio_isa_card
*isa
)
125 /* bit set = no signal present */
126 return (inb(isa
->io
) & 2) ? 0 : 0xffff;
129 static const struct radio_isa_ops terratec_ops
= {
130 .alloc
= terratec_alloc
,
131 .s_mute_volume
= terratec_s_mute_volume
,
132 .s_frequency
= terratec_s_frequency
,
133 .g_signal
= terratec_g_signal
,
136 static const int terratec_ioports
[] = { 0x590 };
138 static struct radio_isa_driver terratec_driver
= {
140 .match
= radio_isa_match
,
141 .probe
= radio_isa_probe
,
142 .remove
= radio_isa_remove
,
144 .name
= "radio-terratec",
148 .radio_nr_params
= &radio_nr
,
149 .io_ports
= terratec_ioports
,
150 .num_of_io_ports
= ARRAY_SIZE(terratec_ioports
),
152 .card
= "TerraTec ActiveRadio",
153 .ops
= &terratec_ops
,
158 static int __init
terratec_init(void)
160 return isa_register_driver(&terratec_driver
.driver
, 1);
163 static void __exit
terratec_exit(void)
165 isa_unregister_driver(&terratec_driver
.driver
);
168 module_init(terratec_init
);
169 module_exit(terratec_exit
);