| Linux kernel & device driver programming |
| [ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] |
1 /* radiotrack (radioreveal) driver for Linux r 1 /* radiotrack (radioreveal) driver for Linux radio support
2 * (c) 1997 M. Kirkwood 2 * (c) 1997 M. Kirkwood
3 * Converted to V4L2 API by Mauro Carvalho Che !! 3 * Converted to new API by Alan Cox <Alan.Cox@linux.org>
4 * Converted to new API by Alan Cox <alan@lxor <<
5 * Various bugfixes and enhancements by Russel 4 * Various bugfixes and enhancements by Russell Kroll <rkroll@exploits.org>
6 * 5 *
7 * History: 6 * History:
8 * 1999-02-24 Russell Kroll <rkroll@exploits 7 * 1999-02-24 Russell Kroll <rkroll@exploits.org>
9 * Fine tuning/VIDEO_TUNER_LOW 8 * Fine tuning/VIDEO_TUNER_LOW
10 * Frequency range expanded to st 9 * Frequency range expanded to start at 87 MHz
11 * 10 *
12 * TODO: Allow for more than one of these fool 11 * TODO: Allow for more than one of these foolish entities :-)
13 * 12 *
14 * Notes on the hardware (reverse engineered f 13 * Notes on the hardware (reverse engineered from other peoples'
15 * reverse engineering of AIMS' code :-) 14 * reverse engineering of AIMS' code :-)
16 * 15 *
17 * Frequency control is done digitally -- ie 16 * Frequency control is done digitally -- ie out(port,encodefreq(95.8));
18 * 17 *
19 * The signal strength query is unsurprisingl 18 * The signal strength query is unsurprisingly inaccurate. And it seems
20 * to indicate that (on my card, at least) th 19 * to indicate that (on my card, at least) the frequency setting isn't
21 * too great. (I have to tune up .025MHz fro 20 * too great. (I have to tune up .025MHz from what the freq should be
22 * to get a report that the thing is tuned.) 21 * to get a report that the thing is tuned.)
23 * 22 *
24 * Volume control is (ugh) analogue: 23 * Volume control is (ugh) analogue:
25 * out(port, start_increasing_volume); 24 * out(port, start_increasing_volume);
26 * wait(a_wee_while); 25 * wait(a_wee_while);
27 * out(port, stop_changing_the_volume); 26 * out(port, stop_changing_the_volume);
28 * !! 27 *
29 */ 28 */
30 29
31 #include <linux/module.h> /* Modules 30 #include <linux/module.h> /* Modules */
32 #include <linux/init.h> /* Initdata 31 #include <linux/init.h> /* Initdata */
33 #include <linux/ioport.h> /* request_reg !! 32 #include <linux/ioport.h> /* check_region, request_region */
34 #include <linux/delay.h> /* udelay 33 #include <linux/delay.h> /* udelay */
35 #include <linux/videodev2.h> /* kernel radi !! 34 #include <asm/io.h> /* outb, outb_p */
36 #include <linux/version.h> /* for KERNEL_ !! 35 #include <asm/uaccess.h> /* copy to/from user */
37 #include <linux/io.h> /* outb, outb_ !! 36 #include <linux/videodev.h> /* kernel radio structs */
38 #include <media/v4l2-device.h> !! 37 #include <linux/config.h> /* CONFIG_RADIO_RTRACK_PORT */
39 #include <media/v4l2-ioctl.h> !! 38 #include <asm/semaphore.h> /* Lock for the I/O */
40 <<
41 MODULE_AUTHOR("M.Kirkwood"); <<
42 MODULE_DESCRIPTION("A driver for the RadioTrac <<
43 MODULE_LICENSE("GPL"); <<
44 39
45 #ifndef CONFIG_RADIO_RTRACK_PORT 40 #ifndef CONFIG_RADIO_RTRACK_PORT
46 #define CONFIG_RADIO_RTRACK_PORT -1 41 #define CONFIG_RADIO_RTRACK_PORT -1
47 #endif 42 #endif
48 43
49 static int io = CONFIG_RADIO_RTRACK_PORT; !! 44 static int io = CONFIG_RADIO_RTRACK_PORT;
50 static int radio_nr = -1; 45 static int radio_nr = -1;
>> 46 static struct semaphore lock;
51 47
52 module_param(io, int, 0); !! 48 struct rt_device
53 MODULE_PARM_DESC(io, "I/O address of the Radio <<
54 module_param(radio_nr, int, 0); <<
55 <<
56 #define RADIO_VERSION KERNEL_VERSION(0, 0, 2) <<
57 <<
58 struct rtrack <<
59 { 49 {
60 struct v4l2_device v4l2_dev; <<
61 struct video_device vdev; <<
62 int port; 50 int port;
63 int curvol; 51 int curvol;
64 unsigned long curfreq; 52 unsigned long curfreq;
65 int muted; 53 int muted;
66 int io; <<
67 struct mutex lock; <<
68 }; 54 };
69 55
70 static struct rtrack rtrack_card; <<
71 56
72 /* local things */ 57 /* local things */
73 58
74 static void sleep_delay(long n) 59 static void sleep_delay(long n)
75 { 60 {
76 /* Sleep nicely for 'n' uS */ 61 /* Sleep nicely for 'n' uS */
77 int d = n / msecs_to_jiffies(1000); !! 62 int d=n/(1000000/HZ);
78 if (!d) !! 63 if(!d)
79 udelay(n); 64 udelay(n);
80 else 65 else
81 msleep(jiffies_to_msecs(d)); 66 msleep(jiffies_to_msecs(d));
82 } 67 }
83 68
84 static void rt_decvol(struct rtrack *rt) !! 69 static void rt_decvol(void)
85 { 70 {
86 outb(0x58, rt->io); /* vol !! 71 outb(0x58, io); /* volume down + sigstr + on */
87 sleep_delay(100000); 72 sleep_delay(100000);
88 outb(0xd8, rt->io); /* vol !! 73 outb(0xd8, io); /* volume steady + sigstr + on */
89 } 74 }
90 75
91 static void rt_incvol(struct rtrack *rt) !! 76 static void rt_incvol(void)
92 { 77 {
93 outb(0x98, rt->io); /* vol !! 78 outb(0x98, io); /* volume up + sigstr + on */
94 sleep_delay(100000); 79 sleep_delay(100000);
95 outb(0xd8, rt->io); /* vol !! 80 outb(0xd8, io); /* volume steady + sigstr + on */
96 } 81 }
97 82
98 static void rt_mute(struct rtrack *rt) !! 83 static void rt_mute(struct rt_device *dev)
99 { 84 {
100 rt->muted = 1; !! 85 dev->muted = 1;
101 mutex_lock(&rt->lock); !! 86 down(&lock);
102 outb(0xd0, rt->io); /* vol !! 87 outb(0xd0, io); /* volume steady, off */
103 mutex_unlock(&rt->lock); !! 88 up(&lock);
104 } 89 }
105 90
106 static int rt_setvol(struct rtrack *rt, int vo !! 91 static int rt_setvol(struct rt_device *dev, int vol)
107 { 92 {
108 int i; 93 int i;
109 94
110 mutex_lock(&rt->lock); !! 95 down(&lock);
111 !! 96
112 if (vol == rt->curvol) { /* req !! 97 if(vol == dev->curvol) { /* requested volume = current */
113 if (rt->muted) { /* use !! 98 if (dev->muted) { /* user is unmuting the card */
114 rt->muted = 0; !! 99 dev->muted = 0;
115 outb(0xd8, rt->io); !! 100 outb (0xd8, io); /* enable card */
116 } !! 101 }
117 mutex_unlock(&rt->lock); !! 102 up(&lock);
118 return 0; 103 return 0;
119 } 104 }
120 105
121 if (vol == 0) { /* vol !! 106 if(vol == 0) { /* volume = 0 means mute the card */
122 outb(0x48, rt->io); /* vol !! 107 outb(0x48, io); /* volume down but still "on" */
123 sleep_delay(2000000); /* mak 108 sleep_delay(2000000); /* make sure it's totally down */
124 outb(0xd0, rt->io); /* vol !! 109 outb(0xd0, io); /* volume steady, off */
125 rt->curvol = 0; /* tra !! 110 dev->curvol = 0; /* track the volume state! */
126 mutex_unlock(&rt->lock); !! 111 up(&lock);
127 return 0; 112 return 0;
128 } 113 }
129 114
130 rt->muted = 0; !! 115 dev->muted = 0;
131 if (vol > rt->curvol) !! 116 if(vol > dev->curvol)
132 for (i = rt->curvol; i < vol; !! 117 for(i = dev->curvol; i < vol; i++)
133 rt_incvol(rt); !! 118 rt_incvol();
134 else 119 else
135 for (i = rt->curvol; i > vol; !! 120 for(i = dev->curvol; i > vol; i--)
136 rt_decvol(rt); !! 121 rt_decvol();
137 122
138 rt->curvol = vol; !! 123 dev->curvol = vol;
139 mutex_unlock(&rt->lock); !! 124 up(&lock);
140 return 0; 125 return 0;
141 } 126 }
142 127
143 /* the 128+64 on these outb's is to keep the v !! 128 /* the 128+64 on these outb's is to keep the volume stable while tuning
144 * without them, the volume _will_ creep up wi 129 * without them, the volume _will_ creep up with each frequency change
145 * and bit 4 (+16) is to keep the signal stren 130 * and bit 4 (+16) is to keep the signal strength meter enabled
146 */ 131 */
147 132
148 static void send_0_byte(struct rtrack *rt) !! 133 static void send_0_byte(int port, struct rt_device *dev)
149 { 134 {
150 if (rt->curvol == 0 || rt->muted) { !! 135 if ((dev->curvol == 0) || (dev->muted)) {
151 outb_p(128+64+16+ 1, rt->io); !! 136 outb_p(128+64+16+ 1, port); /* wr-enable + data low */
152 outb_p(128+64+16+2+1, rt->io); !! 137 outb_p(128+64+16+2+1, port); /* clock */
153 } 138 }
154 else { 139 else {
155 outb_p(128+64+16+8+ 1, rt->io !! 140 outb_p(128+64+16+8+ 1, port); /* on + wr-enable + data low */
156 outb_p(128+64+16+8+2+1, rt->io !! 141 outb_p(128+64+16+8+2+1, port); /* clock */
157 } 142 }
158 sleep_delay(1000); !! 143 sleep_delay(1000);
159 } 144 }
160 145
161 static void send_1_byte(struct rtrack *rt) !! 146 static void send_1_byte(int port, struct rt_device *dev)
162 { 147 {
163 if (rt->curvol == 0 || rt->muted) { !! 148 if ((dev->curvol == 0) || (dev->muted)) {
164 outb_p(128+64+16+4 +1, rt->io !! 149 outb_p(128+64+16+4 +1, port); /* wr-enable+data high */
165 outb_p(128+64+16+4+2+1, rt->io !! 150 outb_p(128+64+16+4+2+1, port); /* clock */
166 } !! 151 }
167 else { 152 else {
168 outb_p(128+64+16+8+4 +1, rt-> !! 153 outb_p(128+64+16+8+4 +1, port); /* on+wr-enable+data high */
169 outb_p(128+64+16+8+4+2+1, rt-> !! 154 outb_p(128+64+16+8+4+2+1, port); /* clock */
170 } 155 }
171 156
172 sleep_delay(1000); !! 157 sleep_delay(1000);
173 } 158 }
174 159
175 static int rt_setfreq(struct rtrack *rt, unsig !! 160 static int rt_setfreq(struct rt_device *dev, unsigned long freq)
176 { 161 {
177 int i; 162 int i;
178 163
179 mutex_lock(&rt->lock); !! 164 /* adapted from radio-aztech.c */
180 <<
181 rt->curfreq = freq; <<
182 165
183 /* now uses VIDEO_TUNER_LOW for fine t 166 /* now uses VIDEO_TUNER_LOW for fine tuning */
184 167
185 freq += 171200; /* Add 168 freq += 171200; /* Add 10.7 MHz IF */
186 freq /= 800; /* Con 169 freq /= 800; /* Convert to 50 kHz units */
187 !! 170
188 send_0_byte(rt); /* 0: !! 171 down(&lock); /* Stop other ops interfering */
>> 172
>> 173 send_0_byte (io, dev); /* 0: LSB of frequency */
189 174
190 for (i = 0; i < 13; i++) /* : 175 for (i = 0; i < 13; i++) /* : frequency bits (1-13) */
191 if (freq & (1 << i)) 176 if (freq & (1 << i))
192 send_1_byte(rt); !! 177 send_1_byte (io, dev);
193 else 178 else
194 send_0_byte(rt); !! 179 send_0_byte (io, dev);
195 180
196 send_0_byte(rt); /* 14: !! 181 send_0_byte (io, dev); /* 14: test bit - always 0 */
197 send_0_byte(rt); /* 15: !! 182 send_0_byte (io, dev); /* 15: test bit - always 0 */
198 183
199 send_0_byte(rt); /* 16: !! 184 send_0_byte (io, dev); /* 16: band data 0 - always 0 */
200 send_0_byte(rt); /* 17: !! 185 send_0_byte (io, dev); /* 17: band data 1 - always 0 */
201 send_0_byte(rt); /* 18: !! 186 send_0_byte (io, dev); /* 18: band data 2 - always 0 */
202 send_0_byte(rt); /* 19: !! 187 send_0_byte (io, dev); /* 19: time base - always 0 */
203 !! 188
204 send_0_byte(rt); /* 20: !! 189 send_0_byte (io, dev); /* 20: spacing (0 = 25 kHz) */
205 send_1_byte(rt); /* 21: !! 190 send_1_byte (io, dev); /* 21: spacing (1 = 25 kHz) */
206 send_0_byte(rt); /* 22: !! 191 send_0_byte (io, dev); /* 22: spacing (0 = 25 kHz) */
207 send_1_byte(rt); /* 23: !! 192 send_1_byte (io, dev); /* 23: AM/FM (FM = 1, always) */
208 193
209 if (rt->curvol == 0 || rt->muted) !! 194 if ((dev->curvol == 0) || (dev->muted))
210 outb(0xd0, rt->io); /* vol !! 195 outb (0xd0, io); /* volume steady + sigstr */
211 else 196 else
212 outb(0xd8, rt->io); /* vol !! 197 outb (0xd8, io); /* volume steady + sigstr + on */
213 !! 198
214 mutex_unlock(&rt->lock); !! 199 up(&lock);
215 200
216 return 0; 201 return 0;
217 } 202 }
218 203
219 static int rt_getsigstr(struct rtrack *rt) !! 204 static int rt_getsigstr(struct rt_device *dev)
220 { 205 {
221 int sig = 1; !! 206 if (inb(io) & 2) /* bit set = no signal present */
222 <<
223 mutex_lock(&rt->lock); <<
224 if (inb(rt->io) & 2) /* bit set = n <<
225 sig = 0; <<
226 mutex_unlock(&rt->lock); <<
227 return sig; <<
228 } <<
229 <<
230 static int vidioc_querycap(struct file *file, <<
231 struct <<
232 { <<
233 strlcpy(v->driver, "radio-aimslab", si <<
234 strlcpy(v->card, "RadioTrack", sizeof( <<
235 strlcpy(v->bus_info, "ISA", sizeof(v-> <<
236 v->version = RADIO_VERSION; <<
237 v->capabilities = V4L2_CAP_TUNER | V4L <<
238 return 0; <<
239 } <<
240 <<
241 static int vidioc_g_tuner(struct file *file, v <<
242 struct <<
243 { <<
244 struct rtrack *rt = video_drvdata(file <<
245 <<
246 if (v->index > 0) <<
247 return -EINVAL; <<
248 <<
249 strlcpy(v->name, "FM", sizeof(v->name) <<
250 v->type = V4L2_TUNER_RADIO; <<
251 v->rangelow = 87 * 16000; <<
252 v->rangehigh = 108 * 16000; <<
253 v->rxsubchans = V4L2_TUNER_SUB_MONO; <<
254 v->capability = V4L2_TUNER_CAP_LOW; <<
255 v->audmode = V4L2_TUNER_MODE_MONO; <<
256 v->signal = 0xffff * rt_getsigstr(rt); <<
257 return 0; <<
258 } <<
259 <<
260 static int vidioc_s_tuner(struct file *file, v <<
261 struct <<
262 { <<
263 return v->index ? -EINVAL : 0; <<
264 } <<
265 <<
266 static int vidioc_s_frequency(struct file *fil <<
267 struct <<
268 { <<
269 struct rtrack *rt = video_drvdata(file <<
270 <<
271 rt_setfreq(rt, f->frequency); <<
272 return 0; <<
273 } <<
274 <<
275 static int vidioc_g_frequency(struct file *fil <<
276 struct <<
277 { <<
278 struct rtrack *rt = video_drvdata(file <<
279 <<
280 f->type = V4L2_TUNER_RADIO; <<
281 f->frequency = rt->curfreq; <<
282 return 0; <<
283 } <<
284 <<
285 static int vidioc_queryctrl(struct file *file, <<
286 struct <<
287 { <<
288 switch (qc->id) { <<
289 case V4L2_CID_AUDIO_MUTE: <<
290 return v4l2_ctrl_query_fill(qc <<
291 case V4L2_CID_AUDIO_VOLUME: <<
292 return v4l2_ctrl_query_fill(qc <<
293 } <<
294 return -EINVAL; <<
295 } <<
296 <<
297 static int vidioc_g_ctrl(struct file *file, vo <<
298 struct <<
299 { <<
300 struct rtrack *rt = video_drvdata(file <<
301 <<
302 switch (ctrl->id) { <<
303 case V4L2_CID_AUDIO_MUTE: <<
304 ctrl->value = rt->muted; <<
305 return 0; <<
306 case V4L2_CID_AUDIO_VOLUME: <<
307 ctrl->value = rt->curvol; <<
308 return 0; 207 return 0;
309 } !! 208 return 1; /* signal present */
310 return -EINVAL; <<
311 } 209 }
312 210
313 static int vidioc_s_ctrl(struct file *file, vo !! 211 static int rt_do_ioctl(struct inode *inode, struct file *file,
314 struct !! 212 unsigned int cmd, void *arg)
315 { 213 {
316 struct rtrack *rt = video_drvdata(file !! 214 struct video_device *dev = video_devdata(file);
317 !! 215 struct rt_device *rt=dev->priv;
318 switch (ctrl->id) { !! 216
319 case V4L2_CID_AUDIO_MUTE: !! 217 switch(cmd)
320 if (ctrl->value) !! 218 {
321 rt_mute(rt); !! 219 case VIDIOCGCAP:
322 else !! 220 {
323 rt_setvol(rt, rt->curv !! 221 struct video_capability *v = arg;
324 return 0; !! 222 memset(v,0,sizeof(*v));
325 case V4L2_CID_AUDIO_VOLUME: !! 223 v->type=VID_TYPE_TUNER;
326 rt_setvol(rt, ctrl->value); !! 224 v->channels=1;
327 return 0; !! 225 v->audios=1;
>> 226 strcpy(v->name, "RadioTrack");
>> 227 return 0;
>> 228 }
>> 229 case VIDIOCGTUNER:
>> 230 {
>> 231 struct video_tuner *v = arg;
>> 232 if(v->tuner) /* Only 1 tuner */
>> 233 return -EINVAL;
>> 234 v->rangelow=(87*16000);
>> 235 v->rangehigh=(108*16000);
>> 236 v->flags=VIDEO_TUNER_LOW;
>> 237 v->mode=VIDEO_MODE_AUTO;
>> 238 strcpy(v->name, "FM");
>> 239 v->signal=0xFFFF*rt_getsigstr(rt);
>> 240 return 0;
>> 241 }
>> 242 case VIDIOCSTUNER:
>> 243 {
>> 244 struct video_tuner *v = arg;
>> 245 if(v->tuner!=0)
>> 246 return -EINVAL;
>> 247 /* Only 1 tuner so no setting needed ! */
>> 248 return 0;
>> 249 }
>> 250 case VIDIOCGFREQ:
>> 251 {
>> 252 unsigned long *freq = arg;
>> 253 *freq = rt->curfreq;
>> 254 return 0;
>> 255 }
>> 256 case VIDIOCSFREQ:
>> 257 {
>> 258 unsigned long *freq = arg;
>> 259 rt->curfreq = *freq;
>> 260 rt_setfreq(rt, rt->curfreq);
>> 261 return 0;
>> 262 }
>> 263 case VIDIOCGAUDIO:
>> 264 {
>> 265 struct video_audio *v = arg;
>> 266 memset(v,0, sizeof(*v));
>> 267 v->flags|=VIDEO_AUDIO_MUTABLE|VIDEO_AUDIO_VOLUME;
>> 268 v->volume=rt->curvol * 6554;
>> 269 v->step=6554;
>> 270 strcpy(v->name, "Radio");
>> 271 return 0;
>> 272 }
>> 273 case VIDIOCSAUDIO:
>> 274 {
>> 275 struct video_audio *v = arg;
>> 276 if(v->audio)
>> 277 return -EINVAL;
>> 278 if(v->flags&VIDEO_AUDIO_MUTE)
>> 279 rt_mute(rt);
>> 280 else
>> 281 rt_setvol(rt,v->volume/6554);
>> 282 return 0;
>> 283 }
>> 284 default:
>> 285 return -ENOIOCTLCMD;
328 } 286 }
329 return -EINVAL; <<
330 } <<
331 <<
332 static int vidioc_g_input(struct file *filp, v <<
333 { <<
334 *i = 0; <<
335 return 0; <<
336 } <<
337 <<
338 static int vidioc_s_input(struct file *filp, v <<
339 { <<
340 return i ? -EINVAL : 0; <<
341 } 287 }
342 288
343 static int vidioc_g_audio(struct file *file, v !! 289 static int rt_ioctl(struct inode *inode, struct file *file,
344 struct !! 290 unsigned int cmd, unsigned long arg)
345 { 291 {
346 a->index = 0; !! 292 return video_usercopy(inode, file, cmd, arg, rt_do_ioctl);
347 strlcpy(a->name, "Radio", sizeof(a->na <<
348 a->capability = V4L2_AUDCAP_STEREO; <<
349 return 0; <<
350 } 293 }
351 294
352 static int vidioc_s_audio(struct file *file, v !! 295 static struct rt_device rtrack_unit;
353 struct <<
354 { <<
355 return a->index ? -EINVAL : 0; <<
356 } <<
357 296
358 static const struct v4l2_file_operations rtrac !! 297 static struct file_operations rtrack_fops = {
359 .owner = THIS_MODULE, 298 .owner = THIS_MODULE,
360 .ioctl = video_ioctl2, !! 299 .open = video_exclusive_open,
>> 300 .release = video_exclusive_release,
>> 301 .ioctl = rt_ioctl,
>> 302 .llseek = no_llseek,
361 }; 303 };
362 304
363 static const struct v4l2_ioctl_ops rtrack_ioct !! 305 static struct video_device rtrack_radio=
364 .vidioc_querycap = vidioc_querycap, !! 306 {
365 .vidioc_g_tuner = vidioc_g_tuner, !! 307 .owner = THIS_MODULE,
366 .vidioc_s_tuner = vidioc_s_tuner, !! 308 .name = "RadioTrack radio",
367 .vidioc_g_audio = vidioc_g_audio, !! 309 .type = VID_TYPE_TUNER,
368 .vidioc_s_audio = vidioc_s_audio, !! 310 .hardware = VID_HARDWARE_RTRACK,
369 .vidioc_g_input = vidioc_g_input, !! 311 .fops = &rtrack_fops,
370 .vidioc_s_input = vidioc_s_input, <<
371 .vidioc_g_frequency = vidioc_g_frequen <<
372 .vidioc_s_frequency = vidioc_s_frequen <<
373 .vidioc_queryctrl = vidioc_queryctrl <<
374 .vidioc_g_ctrl = vidioc_g_ctrl, <<
375 .vidioc_s_ctrl = vidioc_s_ctrl, <<
376 }; 312 };
377 313
378 static int __init rtrack_init(void) 314 static int __init rtrack_init(void)
379 { 315 {
380 struct rtrack *rt = &rtrack_card; !! 316 if(io==-1)
381 struct v4l2_device *v4l2_dev = &rt->v4 !! 317 {
382 int res; !! 318 printk(KERN_ERR "You must set an I/O address with io=0x???\n");
383 <<
384 strlcpy(v4l2_dev->name, "rtrack", size <<
385 rt->io = io; <<
386 <<
387 if (rt->io == -1) { <<
388 v4l2_err(v4l2_dev, "you must s <<
389 return -EINVAL; 319 return -EINVAL;
390 } 320 }
391 321
392 if (!request_region(rt->io, 2, "rtrack !! 322 if (!request_region(io, 2, "rtrack"))
393 v4l2_err(v4l2_dev, "port 0x%x !! 323 {
>> 324 printk(KERN_ERR "rtrack: port 0x%x already in use\n", io);
394 return -EBUSY; 325 return -EBUSY;
395 } 326 }
396 327
397 res = v4l2_device_register(NULL, v4l2_ !! 328 rtrack_radio.priv=&rtrack_unit;
398 if (res < 0) { !! 329
399 release_region(rt->io, 2); !! 330 if(video_register_device(&rtrack_radio, VFL_TYPE_RADIO, radio_nr)==-1)
400 v4l2_err(v4l2_dev, "could not !! 331 {
401 return res; !! 332 release_region(io, 2);
402 } <<
403 <<
404 strlcpy(rt->vdev.name, v4l2_dev->name, <<
405 rt->vdev.v4l2_dev = v4l2_dev; <<
406 rt->vdev.fops = &rtrack_fops; <<
407 rt->vdev.ioctl_ops = &rtrack_ioctl_ops <<
408 rt->vdev.release = video_device_releas <<
409 video_set_drvdata(&rt->vdev, rt); <<
410 <<
411 if (video_register_device(&rt->vdev, V <<
412 v4l2_device_unregister(&rt->v4 <<
413 release_region(rt->io, 2); <<
414 return -EINVAL; 333 return -EINVAL;
415 } 334 }
416 v4l2_info(v4l2_dev, "AIMSlab RadioTrac !! 335 printk(KERN_INFO "AIMSlab RadioTrack/RadioReveal card driver.\n");
417 336
418 /* Set up the I/O locking */ 337 /* Set up the I/O locking */
419 !! 338
420 mutex_init(&rt->lock); !! 339 init_MUTEX(&lock);
421 !! 340
422 /* mute card - prevents noisy bootups !! 341 /* mute card - prevents noisy bootups */
423 342
424 /* this ensures that the volume is all 343 /* this ensures that the volume is all the way down */
425 outb(0x48, rt->io); /* vol !! 344 outb(0x48, io); /* volume down but still "on" */
426 sleep_delay(2000000); /* make sure i 345 sleep_delay(2000000); /* make sure it's totally down */
427 outb(0xc0, rt->io); /* ste !! 346 outb(0xc0, io); /* steady volume, mute card */
>> 347 rtrack_unit.curvol = 0;
428 348
429 return 0; 349 return 0;
430 } 350 }
431 351
432 static void __exit rtrack_exit(void) !! 352 MODULE_AUTHOR("M.Kirkwood");
433 { !! 353 MODULE_DESCRIPTION("A driver for the RadioTrack/RadioReveal radio card.");
434 struct rtrack *rt = &rtrack_card; !! 354 MODULE_LICENSE("GPL");
435 355
436 video_unregister_device(&rt->vdev); !! 356 module_param(io, int, 0);
437 v4l2_device_unregister(&rt->v4l2_dev); !! 357 MODULE_PARM_DESC(io, "I/O address of the RadioTrack card (0x20f or 0x30f)");
438 release_region(rt->io, 2); !! 358 module_param(radio_nr, int, 0);
>> 359
>> 360 static void __exit cleanup_rtrack_module(void)
>> 361 {
>> 362 video_unregister_device(&rtrack_radio);
>> 363 release_region(io,2);
439 } 364 }
440 365
441 module_init(rtrack_init); 366 module_init(rtrack_init);
442 module_exit(rtrack_exit); !! 367 module_exit(cleanup_rtrack_module);
443 368
444 369
| This page was automatically generated by the LXR engine. |