aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/media/radio/radio-maxiradio.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/media/radio/radio-maxiradio.c')
-rw-r--r--drivers/media/radio/radio-maxiradio.c81
1 files changed, 41 insertions, 40 deletions
diff --git a/drivers/media/radio/radio-maxiradio.c b/drivers/media/radio/radio-maxiradio.c
index f0bf47bcb64c..f93d7afe7304 100644
--- a/drivers/media/radio/radio-maxiradio.c
+++ b/drivers/media/radio/radio-maxiradio.c
@@ -1,15 +1,15 @@
1/* 1/*
2 * Guillemot Maxi Radio FM 2000 PCI radio card driver for Linux 2 * Guillemot Maxi Radio FM 2000 PCI radio card driver for Linux
3 * (C) 2001 Dimitromanolakis Apostolos <apdim@grecian.net> 3 * (C) 2001 Dimitromanolakis Apostolos <apdim@grecian.net>
4 * 4 *
5 * Based in the radio Maestro PCI driver. Actually it uses the same chip 5 * Based in the radio Maestro PCI driver. Actually it uses the same chip
6 * for radio but different pci controller. 6 * for radio but different pci controller.
7 * 7 *
8 * I didn't have any specs I reversed engineered the protocol from 8 * I didn't have any specs I reversed engineered the protocol from
9 * the windows driver (radio.dll). 9 * the windows driver (radio.dll).
10 * 10 *
11 * The card uses the TEA5757 chip that includes a search function but it 11 * The card uses the TEA5757 chip that includes a search function but it
12 * is useless as I haven't found any way to read back the frequency. If 12 * is useless as I haven't found any way to read back the frequency. If
13 * anybody does please mail me. 13 * anybody does please mail me.
14 * 14 *
15 * For the pdf file see: 15 * For the pdf file see:
@@ -24,7 +24,7 @@
24 * - tiding up 24 * - tiding up
25 * - removed support for multiple devices as it didn't work anyway 25 * - removed support for multiple devices as it didn't work anyway
26 * 26 *
27 * BUGS: 27 * BUGS:
28 * - card unmutes if you change frequency 28 * - card unmutes if you change frequency
29 * 29 *
30 */ 30 */
@@ -41,6 +41,7 @@
41 41
42#include <linux/pci.h> 42#include <linux/pci.h>
43#include <linux/videodev.h> 43#include <linux/videodev.h>
44#include <media/v4l2-common.h>
44 45
45/* version 0.75 Sun Feb 4 22:51:27 EET 2001 */ 46/* version 0.75 Sun Feb 4 22:51:27 EET 2001 */
46#define DRIVER_VERSION "0.75" 47#define DRIVER_VERSION "0.75"
@@ -80,7 +81,7 @@ static struct file_operations maxiradio_fops = {
80 .owner = THIS_MODULE, 81 .owner = THIS_MODULE,
81 .open = video_exclusive_open, 82 .open = video_exclusive_open,
82 .release = video_exclusive_release, 83 .release = video_exclusive_release,
83 .ioctl = radio_ioctl, 84 .ioctl = radio_ioctl,
84 .compat_ioctl = v4l_compat_ioctl32, 85 .compat_ioctl = v4l_compat_ioctl32,
85 .llseek = no_llseek, 86 .llseek = no_llseek,
86}; 87};
@@ -97,11 +98,11 @@ static struct radio_device
97{ 98{
98 __u16 io, /* base of radio io */ 99 __u16 io, /* base of radio io */
99 muted, /* VIDEO_AUDIO_MUTE */ 100 muted, /* VIDEO_AUDIO_MUTE */
100 stereo, /* VIDEO_TUNER_STEREO_ON */ 101 stereo, /* VIDEO_TUNER_STEREO_ON */
101 tuned; /* signal strength (0 or 0xffff) */ 102 tuned; /* signal strength (0 or 0xffff) */
102 103
103 unsigned long freq; 104 unsigned long freq;
104 105
105 struct mutex lock; 106 struct mutex lock;
106} radio_unit = {0, 0, 0, 0, }; 107} radio_unit = {0, 0, 0, 0, };
107 108
@@ -114,7 +115,7 @@ static void outbit(unsigned long bit, __u16 io)
114 outb( power|wren|data|clk ,io); udelay(4); 115 outb( power|wren|data|clk ,io); udelay(4);
115 outb( power|wren|data ,io); udelay(4); 116 outb( power|wren|data ,io); udelay(4);
116 } 117 }
117 else 118 else
118 { 119 {
119 outb( power|wren ,io); udelay(4); 120 outb( power|wren ,io); udelay(4);
120 outb( power|wren|clk ,io); udelay(4); 121 outb( power|wren|clk ,io); udelay(4);
@@ -132,12 +133,12 @@ static void set_freq(__u16 io, __u32 data)
132{ 133{
133 unsigned long int si; 134 unsigned long int si;
134 int bl; 135 int bl;
135 136
136 /* TEA5757 shift register bits (see pdf) */ 137 /* TEA5757 shift register bits (see pdf) */
137 138
138 outbit(0,io); // 24 search 139 outbit(0,io); // 24 search
139 outbit(1,io); // 23 search up/down 140 outbit(1,io); // 23 search up/down
140 141
141 outbit(0,io); // 22 stereo/mono 142 outbit(0,io); // 22 stereo/mono
142 143
143 outbit(0,io); // 21 band 144 outbit(0,io); // 21 band
@@ -145,24 +146,24 @@ static void set_freq(__u16 io, __u32 data)
145 146
146 outbit(0,io); // 19 port ? 147 outbit(0,io); // 19 port ?
147 outbit(0,io); // 18 port ? 148 outbit(0,io); // 18 port ?
148 149
149 outbit(0,io); // 17 search level 150 outbit(0,io); // 17 search level
150 outbit(0,io); // 16 search level 151 outbit(0,io); // 16 search level
151 152
152 si = 0x8000; 153 si = 0x8000;
153 for(bl = 1; bl <= 16 ; bl++) { outbit(data & si,io); si >>=1; } 154 for(bl = 1; bl <= 16 ; bl++) { outbit(data & si,io); si >>=1; }
154 155
155 outb(power,io); 156 outb(power,io);
156} 157}
157 158
158static int get_stereo(__u16 io) 159static int get_stereo(__u16 io)
159{ 160{
160 outb(power,io); udelay(4); 161 outb(power,io); udelay(4);
161 return !(inb(io) & mo_st); 162 return !(inb(io) & mo_st);
162} 163}
163 164
164static int get_tune(__u16 io) 165static int get_tune(__u16 io)
165{ 166{
166 outb(power+clk,io); udelay(4); 167 outb(power+clk,io); udelay(4);
167 return !(inb(io) & mo_st); 168 return !(inb(io) & mo_st);
168} 169}
@@ -177,7 +178,7 @@ static inline int radio_function(struct inode *inode, struct file *file,
177 switch(cmd) { 178 switch(cmd) {
178 case VIDIOCGCAP: { 179 case VIDIOCGCAP: {
179 struct video_capability *v = arg; 180 struct video_capability *v = arg;
180 181
181 memset(v,0,sizeof(*v)); 182 memset(v,0,sizeof(*v));
182 strcpy(v->name, "Maxi Radio FM2000 radio"); 183 strcpy(v->name, "Maxi Radio FM2000 radio");
183 v->type=VID_TYPE_TUNER; 184 v->type=VID_TYPE_TUNER;
@@ -186,22 +187,22 @@ static inline int radio_function(struct inode *inode, struct file *file,
186 } 187 }
187 case VIDIOCGTUNER: { 188 case VIDIOCGTUNER: {
188 struct video_tuner *v = arg; 189 struct video_tuner *v = arg;
189 190
190 if(v->tuner) 191 if(v->tuner)
191 return -EINVAL; 192 return -EINVAL;
192 193
193 card->stereo = 0xffff * get_stereo(card->io); 194 card->stereo = 0xffff * get_stereo(card->io);
194 card->tuned = 0xffff * get_tune(card->io); 195 card->tuned = 0xffff * get_tune(card->io);
195 196
196 v->flags = VIDEO_TUNER_LOW | card->stereo; 197 v->flags = VIDEO_TUNER_LOW | card->stereo;
197 v->signal = card->tuned; 198 v->signal = card->tuned;
198 199
199 strcpy(v->name, "FM"); 200 strcpy(v->name, "FM");
200 201
201 v->rangelow = FREQ_LO; 202 v->rangelow = FREQ_LO;
202 v->rangehigh = FREQ_HI; 203 v->rangehigh = FREQ_HI;
203 v->mode = VIDEO_MODE_AUTO; 204 v->mode = VIDEO_MODE_AUTO;
204 205
205 return 0; 206 return 0;
206 } 207 }
207 case VIDIOCSTUNER: { 208 case VIDIOCSTUNER: {
@@ -212,13 +213,13 @@ static inline int radio_function(struct inode *inode, struct file *file,
212 } 213 }
213 case VIDIOCGFREQ: { 214 case VIDIOCGFREQ: {
214 unsigned long *freq = arg; 215 unsigned long *freq = arg;
215 216
216 *freq = card->freq; 217 *freq = card->freq;
217 return 0; 218 return 0;
218 } 219 }
219 case VIDIOCSFREQ: { 220 case VIDIOCSFREQ: {
220 unsigned long *freq = arg; 221 unsigned long *freq = arg;
221 222
222 if (*freq < FREQ_LO || *freq > FREQ_HI) 223 if (*freq < FREQ_LO || *freq > FREQ_HI)
223 return -EINVAL; 224 return -EINVAL;
224 card->freq = *freq; 225 card->freq = *freq;
@@ -226,18 +227,18 @@ static inline int radio_function(struct inode *inode, struct file *file,
226 msleep(125); 227 msleep(125);
227 return 0; 228 return 0;
228 } 229 }
229 case VIDIOCGAUDIO: { 230 case VIDIOCGAUDIO: {
230 struct video_audio *v = arg; 231 struct video_audio *v = arg;
231 memset(v,0,sizeof(*v)); 232 memset(v,0,sizeof(*v));
232 strcpy(v->name, "Radio"); 233 strcpy(v->name, "Radio");
233 v->flags=VIDEO_AUDIO_MUTABLE | card->muted; 234 v->flags=VIDEO_AUDIO_MUTABLE | card->muted;
234 v->mode=VIDEO_SOUND_STEREO; 235 v->mode=VIDEO_SOUND_STEREO;
235 return 0; 236 return 0;
236 } 237 }
237 238
238 case VIDIOCSAUDIO: { 239 case VIDIOCSAUDIO: {
239 struct video_audio *v = arg; 240 struct video_audio *v = arg;
240 241
241 if(v->audio) 242 if(v->audio)
242 return -EINVAL; 243 return -EINVAL;
243 card->muted = v->flags & VIDEO_AUDIO_MUTE; 244 card->muted = v->flags & VIDEO_AUDIO_MUTE;
@@ -249,13 +250,13 @@ static inline int radio_function(struct inode *inode, struct file *file,
249 } 250 }
250 case VIDIOCGUNIT: { 251 case VIDIOCGUNIT: {
251 struct video_unit *v = arg; 252 struct video_unit *v = arg;
252 253
253 v->video=VIDEO_NO_UNIT; 254 v->video=VIDEO_NO_UNIT;
254 v->vbi=VIDEO_NO_UNIT; 255 v->vbi=VIDEO_NO_UNIT;
255 v->radio=dev->minor; 256 v->radio=dev->minor;
256 v->audio=0; 257 v->audio=0;
257 v->teletext=VIDEO_NO_UNIT; 258 v->teletext=VIDEO_NO_UNIT;
258 return 0; 259 return 0;
259 } 260 }
260 default: return -ENOIOCTLCMD; 261 default: return -ENOIOCTLCMD;
261 } 262 }
@@ -267,7 +268,7 @@ static int radio_ioctl(struct inode *inode, struct file *file,
267 struct video_device *dev = video_devdata(file); 268 struct video_device *dev = video_devdata(file);
268 struct radio_device *card=dev->priv; 269 struct radio_device *card=dev->priv;
269 int ret; 270 int ret;
270 271
271 mutex_lock(&card->lock); 272 mutex_lock(&card->lock);
272 ret = video_usercopy(inode, file, cmd, arg, radio_function); 273 ret = video_usercopy(inode, file, cmd, arg, radio_function);
273 mutex_unlock(&card->lock); 274 mutex_unlock(&card->lock);
@@ -282,21 +283,21 @@ MODULE_LICENSE("GPL");
282static int __devinit maxiradio_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) 283static int __devinit maxiradio_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
283{ 284{
284 if(!request_region(pci_resource_start(pdev, 0), 285 if(!request_region(pci_resource_start(pdev, 0),
285 pci_resource_len(pdev, 0), "Maxi Radio FM 2000")) { 286 pci_resource_len(pdev, 0), "Maxi Radio FM 2000")) {
286 printk(KERN_ERR "radio-maxiradio: can't reserve I/O ports\n"); 287 printk(KERN_ERR "radio-maxiradio: can't reserve I/O ports\n");
287 goto err_out; 288 goto err_out;
288 } 289 }
289 290
290 if (pci_enable_device(pdev)) 291 if (pci_enable_device(pdev))
291 goto err_out_free_region; 292 goto err_out_free_region;
292 293
293 radio_unit.io = pci_resource_start(pdev, 0); 294 radio_unit.io = pci_resource_start(pdev, 0);
294 mutex_init(&radio_unit.lock); 295 mutex_init(&radio_unit.lock);
295 maxiradio_radio.priv = &radio_unit; 296 maxiradio_radio.priv = &radio_unit;
296 297
297 if(video_register_device(&maxiradio_radio, VFL_TYPE_RADIO, radio_nr)==-1) { 298 if(video_register_device(&maxiradio_radio, VFL_TYPE_RADIO, radio_nr)==-1) {
298 printk("radio-maxiradio: can't register device!"); 299 printk("radio-maxiradio: can't register device!");
299 goto err_out_free_region; 300 goto err_out_free_region;
300 } 301 }
301 302
302 printk(KERN_INFO "radio-maxiradio: version " 303 printk(KERN_INFO "radio-maxiradio: version "