diff options
author | Hans Verkuil <hverkuil@xs4all.nl> | 2009-03-06 11:48:18 -0500 |
---|---|---|
committer | Mauro Carvalho Chehab <mchehab@redhat.com> | 2009-03-30 11:43:12 -0400 |
commit | e697e12ecede8ee4f5beb11ed4981d7254be0125 (patch) | |
tree | 529f4b65cdf7443509f9a25ab34eacd32021353f | |
parent | 151c3f82529844c39ad52fe8d877dd2ffe06c70d (diff) |
V4L/DVB (10881): radio-aztech: convert to v4l2_device.
Signed-off-by: Hans Verkuil <hverkuil@xs4all.nl>
Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
-rw-r--r-- | drivers/media/radio/radio-aztech.c | 379 |
1 files changed, 181 insertions, 198 deletions
diff --git a/drivers/media/radio/radio-aztech.c b/drivers/media/radio/radio-aztech.c index 5604e881e96c..35f6f403f65d 100644 --- a/drivers/media/radio/radio-aztech.c +++ b/drivers/media/radio/radio-aztech.c | |||
@@ -29,33 +29,16 @@ | |||
29 | #include <linux/init.h> /* Initdata */ | 29 | #include <linux/init.h> /* Initdata */ |
30 | #include <linux/ioport.h> /* request_region */ | 30 | #include <linux/ioport.h> /* request_region */ |
31 | #include <linux/delay.h> /* udelay */ | 31 | #include <linux/delay.h> /* udelay */ |
32 | #include <asm/io.h> /* outb, outb_p */ | ||
33 | #include <asm/uaccess.h> /* copy to/from user */ | ||
34 | #include <linux/videodev2.h> /* kernel radio structs */ | 32 | #include <linux/videodev2.h> /* kernel radio structs */ |
35 | #include <media/v4l2-common.h> | 33 | #include <linux/version.h> /* for KERNEL_VERSION MACRO */ |
34 | #include <linux/io.h> /* outb, outb_p */ | ||
35 | #include <linux/uaccess.h> /* copy to/from user */ | ||
36 | #include <media/v4l2-device.h> | ||
36 | #include <media/v4l2-ioctl.h> | 37 | #include <media/v4l2-ioctl.h> |
37 | 38 | ||
38 | #include <linux/version.h> /* for KERNEL_VERSION MACRO */ | 39 | MODULE_AUTHOR("Russell Kroll, Quay Lu, Donald Song, Jason Lewis, Scott McGrath, William McGrath"); |
39 | #define RADIO_VERSION KERNEL_VERSION(0,0,2) | 40 | MODULE_DESCRIPTION("A driver for the Aztech radio card."); |
40 | 41 | MODULE_LICENSE("GPL"); | |
41 | static struct v4l2_queryctrl radio_qctrl[] = { | ||
42 | { | ||
43 | .id = V4L2_CID_AUDIO_MUTE, | ||
44 | .name = "Mute", | ||
45 | .minimum = 0, | ||
46 | .maximum = 1, | ||
47 | .default_value = 1, | ||
48 | .type = V4L2_CTRL_TYPE_BOOLEAN, | ||
49 | },{ | ||
50 | .id = V4L2_CID_AUDIO_VOLUME, | ||
51 | .name = "Volume", | ||
52 | .minimum = 0, | ||
53 | .maximum = 0xff, | ||
54 | .step = 1, | ||
55 | .default_value = 0xff, | ||
56 | .type = V4L2_CTRL_TYPE_INTEGER, | ||
57 | } | ||
58 | }; | ||
59 | 42 | ||
60 | /* acceptable ports: 0x350 (JP3 shorted), 0x358 (JP3 open) */ | 43 | /* acceptable ports: 0x350 (JP3 shorted), 0x358 (JP3 open) */ |
61 | 44 | ||
@@ -66,55 +49,64 @@ static struct v4l2_queryctrl radio_qctrl[] = { | |||
66 | static int io = CONFIG_RADIO_AZTECH_PORT; | 49 | static int io = CONFIG_RADIO_AZTECH_PORT; |
67 | static int radio_nr = -1; | 50 | static int radio_nr = -1; |
68 | static int radio_wait_time = 1000; | 51 | static int radio_wait_time = 1000; |
69 | static struct mutex lock; | ||
70 | 52 | ||
71 | struct az_device | 53 | module_param(io, int, 0); |
54 | module_param(radio_nr, int, 0); | ||
55 | MODULE_PARM_DESC(io, "I/O address of the Aztech card (0x350 or 0x358)"); | ||
56 | |||
57 | #define RADIO_VERSION KERNEL_VERSION(0, 0, 2) | ||
58 | |||
59 | struct aztech | ||
72 | { | 60 | { |
73 | unsigned long in_use; | 61 | struct v4l2_device v4l2_dev; |
62 | struct video_device vdev; | ||
63 | int io; | ||
74 | int curvol; | 64 | int curvol; |
75 | unsigned long curfreq; | 65 | unsigned long curfreq; |
76 | int stereo; | 66 | int stereo; |
67 | struct mutex lock; | ||
77 | }; | 68 | }; |
78 | 69 | ||
70 | static struct aztech aztech_card; | ||
71 | |||
79 | static int volconvert(int level) | 72 | static int volconvert(int level) |
80 | { | 73 | { |
81 | level>>=14; /* Map 16bits down to 2 bit */ | 74 | level >>= 14; /* Map 16bits down to 2 bit */ |
82 | level&=3; | 75 | level &= 3; |
83 | 76 | ||
84 | /* convert to card-friendly values */ | 77 | /* convert to card-friendly values */ |
85 | switch (level) | 78 | switch (level) { |
86 | { | 79 | case 0: |
87 | case 0: | 80 | return 0; |
88 | return 0; | 81 | case 1: |
89 | case 1: | 82 | return 1; |
90 | return 1; | 83 | case 2: |
91 | case 2: | 84 | return 4; |
92 | return 4; | 85 | case 3: |
93 | case 3: | 86 | return 5; |
94 | return 5; | ||
95 | } | 87 | } |
96 | return 0; /* Quieten gcc */ | 88 | return 0; /* Quieten gcc */ |
97 | } | 89 | } |
98 | 90 | ||
99 | static void send_0_byte (struct az_device *dev) | 91 | static void send_0_byte(struct aztech *az) |
100 | { | 92 | { |
101 | udelay(radio_wait_time); | 93 | udelay(radio_wait_time); |
102 | outb_p(2+volconvert(dev->curvol), io); | 94 | outb_p(2 + volconvert(az->curvol), az->io); |
103 | outb_p(64+2+volconvert(dev->curvol), io); | 95 | outb_p(64 + 2 + volconvert(az->curvol), az->io); |
104 | } | 96 | } |
105 | 97 | ||
106 | static void send_1_byte (struct az_device *dev) | 98 | static void send_1_byte(struct aztech *az) |
107 | { | 99 | { |
108 | udelay (radio_wait_time); | 100 | udelay (radio_wait_time); |
109 | outb_p(128+2+volconvert(dev->curvol), io); | 101 | outb_p(128 + 2 + volconvert(az->curvol), az->io); |
110 | outb_p(128+64+2+volconvert(dev->curvol), io); | 102 | outb_p(128 + 64 + 2 + volconvert(az->curvol), az->io); |
111 | } | 103 | } |
112 | 104 | ||
113 | static int az_setvol(struct az_device *dev, int vol) | 105 | static int az_setvol(struct aztech *az, int vol) |
114 | { | 106 | { |
115 | mutex_lock(&lock); | 107 | mutex_lock(&az->lock); |
116 | outb (volconvert(vol), io); | 108 | outb(volconvert(vol), az->io); |
117 | mutex_unlock(&lock); | 109 | mutex_unlock(&az->lock); |
118 | return 0; | 110 | return 0; |
119 | } | 111 | } |
120 | 112 | ||
@@ -126,116 +118,110 @@ static int az_setvol(struct az_device *dev, int vol) | |||
126 | * | 118 | * |
127 | */ | 119 | */ |
128 | 120 | ||
129 | static int az_getsigstr(struct az_device *dev) | 121 | static int az_getsigstr(struct aztech *az) |
130 | { | 122 | { |
131 | if (inb(io) & 2) /* bit set = no signal present */ | 123 | int sig = 1; |
132 | return 0; | 124 | |
133 | return 1; /* signal present */ | 125 | mutex_lock(&az->lock); |
126 | if (inb(az->io) & 2) /* bit set = no signal present */ | ||
127 | sig = 0; | ||
128 | mutex_unlock(&az->lock); | ||
129 | return sig; | ||
134 | } | 130 | } |
135 | 131 | ||
136 | static int az_getstereo(struct az_device *dev) | 132 | static int az_getstereo(struct aztech *az) |
137 | { | 133 | { |
138 | if (inb(io) & 1) /* bit set = mono */ | 134 | int stereo = 1; |
139 | return 0; | 135 | |
140 | return 1; /* stereo */ | 136 | mutex_lock(&az->lock); |
137 | if (inb(az->io) & 1) /* bit set = mono */ | ||
138 | stereo = 0; | ||
139 | mutex_unlock(&az->lock); | ||
140 | return stereo; | ||
141 | } | 141 | } |
142 | 142 | ||
143 | static int az_setfreq(struct az_device *dev, unsigned long frequency) | 143 | static int az_setfreq(struct aztech *az, unsigned long frequency) |
144 | { | 144 | { |
145 | int i; | 145 | int i; |
146 | 146 | ||
147 | mutex_lock(&az->lock); | ||
148 | |||
149 | az->curfreq = frequency; | ||
147 | frequency += 171200; /* Add 10.7 MHz IF */ | 150 | frequency += 171200; /* Add 10.7 MHz IF */ |
148 | frequency /= 800; /* Convert to 50 kHz units */ | 151 | frequency /= 800; /* Convert to 50 kHz units */ |
149 | 152 | ||
150 | mutex_lock(&lock); | 153 | send_0_byte(az); /* 0: LSB of frequency */ |
151 | |||
152 | send_0_byte (dev); /* 0: LSB of frequency */ | ||
153 | 154 | ||
154 | for (i = 0; i < 13; i++) /* : frequency bits (1-13) */ | 155 | for (i = 0; i < 13; i++) /* : frequency bits (1-13) */ |
155 | if (frequency & (1 << i)) | 156 | if (frequency & (1 << i)) |
156 | send_1_byte (dev); | 157 | send_1_byte(az); |
157 | else | 158 | else |
158 | send_0_byte (dev); | 159 | send_0_byte(az); |
159 | 160 | ||
160 | send_0_byte (dev); /* 14: test bit - always 0 */ | 161 | send_0_byte(az); /* 14: test bit - always 0 */ |
161 | send_0_byte (dev); /* 15: test bit - always 0 */ | 162 | send_0_byte(az); /* 15: test bit - always 0 */ |
162 | send_0_byte (dev); /* 16: band data 0 - always 0 */ | 163 | send_0_byte(az); /* 16: band data 0 - always 0 */ |
163 | if (dev->stereo) /* 17: stereo (1 to enable) */ | 164 | if (az->stereo) /* 17: stereo (1 to enable) */ |
164 | send_1_byte (dev); | 165 | send_1_byte(az); |
165 | else | 166 | else |
166 | send_0_byte (dev); | 167 | send_0_byte(az); |
167 | 168 | ||
168 | send_1_byte (dev); /* 18: band data 1 - unknown */ | 169 | send_1_byte(az); /* 18: band data 1 - unknown */ |
169 | send_0_byte (dev); /* 19: time base - always 0 */ | 170 | send_0_byte(az); /* 19: time base - always 0 */ |
170 | send_0_byte (dev); /* 20: spacing (0 = 25 kHz) */ | 171 | send_0_byte(az); /* 20: spacing (0 = 25 kHz) */ |
171 | send_1_byte (dev); /* 21: spacing (1 = 25 kHz) */ | 172 | send_1_byte(az); /* 21: spacing (1 = 25 kHz) */ |
172 | send_0_byte (dev); /* 22: spacing (0 = 25 kHz) */ | 173 | send_0_byte(az); /* 22: spacing (0 = 25 kHz) */ |
173 | send_1_byte (dev); /* 23: AM/FM (FM = 1, always) */ | 174 | send_1_byte(az); /* 23: AM/FM (FM = 1, always) */ |
174 | 175 | ||
175 | /* latch frequency */ | 176 | /* latch frequency */ |
176 | 177 | ||
177 | udelay (radio_wait_time); | 178 | udelay(radio_wait_time); |
178 | outb_p(128+64+volconvert(dev->curvol), io); | 179 | outb_p(128 + 64 + volconvert(az->curvol), az->io); |
179 | 180 | ||
180 | mutex_unlock(&lock); | 181 | mutex_unlock(&az->lock); |
181 | 182 | ||
182 | return 0; | 183 | return 0; |
183 | } | 184 | } |
184 | 185 | ||
185 | static int vidioc_querycap (struct file *file, void *priv, | 186 | static int vidioc_querycap(struct file *file, void *priv, |
186 | struct v4l2_capability *v) | 187 | struct v4l2_capability *v) |
187 | { | 188 | { |
188 | strlcpy(v->driver, "radio-aztech", sizeof (v->driver)); | 189 | strlcpy(v->driver, "radio-aztech", sizeof(v->driver)); |
189 | strlcpy(v->card, "Aztech Radio", sizeof (v->card)); | 190 | strlcpy(v->card, "Aztech Radio", sizeof(v->card)); |
190 | sprintf(v->bus_info,"ISA"); | 191 | strlcpy(v->bus_info, "ISA", sizeof(v->bus_info)); |
191 | v->version = RADIO_VERSION; | 192 | v->version = RADIO_VERSION; |
192 | v->capabilities = V4L2_CAP_TUNER; | 193 | v->capabilities = V4L2_CAP_TUNER | V4L2_CAP_RADIO; |
193 | return 0; | 194 | return 0; |
194 | } | 195 | } |
195 | 196 | ||
196 | static int vidioc_g_tuner (struct file *file, void *priv, | 197 | static int vidioc_g_tuner(struct file *file, void *priv, |
197 | struct v4l2_tuner *v) | 198 | struct v4l2_tuner *v) |
198 | { | 199 | { |
199 | struct az_device *az = video_drvdata(file); | 200 | struct aztech *az = video_drvdata(file); |
200 | 201 | ||
201 | if (v->index > 0) | 202 | if (v->index > 0) |
202 | return -EINVAL; | 203 | return -EINVAL; |
203 | 204 | ||
204 | strcpy(v->name, "FM"); | 205 | strlcpy(v->name, "FM", sizeof(v->name)); |
205 | v->type = V4L2_TUNER_RADIO; | 206 | v->type = V4L2_TUNER_RADIO; |
206 | 207 | ||
207 | v->rangelow=(87*16000); | 208 | v->rangelow = 87 * 16000; |
208 | v->rangehigh=(108*16000); | 209 | v->rangehigh = 108 * 16000; |
209 | v->rxsubchans =V4L2_TUNER_SUB_MONO|V4L2_TUNER_SUB_STEREO; | 210 | v->rxsubchans = V4L2_TUNER_SUB_MONO | V4L2_TUNER_SUB_STEREO; |
210 | v->capability=V4L2_TUNER_CAP_LOW; | 211 | v->capability = V4L2_TUNER_CAP_LOW; |
211 | if(az_getstereo(az)) | 212 | if (az_getstereo(az)) |
212 | v->audmode = V4L2_TUNER_MODE_STEREO; | 213 | v->audmode = V4L2_TUNER_MODE_STEREO; |
213 | else | 214 | else |
214 | v->audmode = V4L2_TUNER_MODE_MONO; | 215 | v->audmode = V4L2_TUNER_MODE_MONO; |
215 | v->signal=0xFFFF*az_getsigstr(az); | 216 | v->signal = 0xFFFF * az_getsigstr(az); |
216 | 217 | ||
217 | return 0; | 218 | return 0; |
218 | } | 219 | } |
219 | 220 | ||
220 | 221 | static int vidioc_s_tuner(struct file *file, void *priv, | |
221 | static int vidioc_s_tuner (struct file *file, void *priv, | ||
222 | struct v4l2_tuner *v) | 222 | struct v4l2_tuner *v) |
223 | { | 223 | { |
224 | if (v->index > 0) | 224 | return v->index ? -EINVAL : 0; |
225 | return -EINVAL; | ||
226 | |||
227 | return 0; | ||
228 | } | ||
229 | |||
230 | static int vidioc_g_audio (struct file *file, void *priv, | ||
231 | struct v4l2_audio *a) | ||
232 | { | ||
233 | if (a->index > 1) | ||
234 | return -EINVAL; | ||
235 | |||
236 | strcpy(a->name, "Radio"); | ||
237 | a->capability = V4L2_AUDCAP_STEREO; | ||
238 | return 0; | ||
239 | } | 225 | } |
240 | 226 | ||
241 | static int vidioc_g_input(struct file *filp, void *priv, unsigned int *i) | 227 | static int vidioc_g_input(struct file *filp, void *priv, unsigned int *i) |
@@ -246,113 +232,107 @@ static int vidioc_g_input(struct file *filp, void *priv, unsigned int *i) | |||
246 | 232 | ||
247 | static int vidioc_s_input(struct file *filp, void *priv, unsigned int i) | 233 | static int vidioc_s_input(struct file *filp, void *priv, unsigned int i) |
248 | { | 234 | { |
249 | if (i != 0) | 235 | return i ? -EINVAL : 0; |
250 | return -EINVAL; | ||
251 | return 0; | ||
252 | } | 236 | } |
253 | 237 | ||
254 | 238 | static int vidioc_g_audio(struct file *file, void *priv, | |
255 | static int vidioc_s_audio (struct file *file, void *priv, | ||
256 | struct v4l2_audio *a) | 239 | struct v4l2_audio *a) |
257 | { | 240 | { |
258 | if (a->index != 0) | 241 | a->index = 0; |
259 | return -EINVAL; | 242 | strlcpy(a->name, "Radio", sizeof(a->name)); |
260 | 243 | a->capability = V4L2_AUDCAP_STEREO; | |
261 | return 0; | 244 | return 0; |
262 | } | 245 | } |
263 | 246 | ||
264 | static int vidioc_s_frequency (struct file *file, void *priv, | 247 | static int vidioc_s_audio(struct file *file, void *priv, |
248 | struct v4l2_audio *a) | ||
249 | { | ||
250 | return a->index ? -EINVAL : 0; | ||
251 | } | ||
252 | |||
253 | static int vidioc_s_frequency(struct file *file, void *priv, | ||
265 | struct v4l2_frequency *f) | 254 | struct v4l2_frequency *f) |
266 | { | 255 | { |
267 | struct az_device *az = video_drvdata(file); | 256 | struct aztech *az = video_drvdata(file); |
268 | 257 | ||
269 | az->curfreq = f->frequency; | 258 | az_setfreq(az, f->frequency); |
270 | az_setfreq(az, az->curfreq); | ||
271 | return 0; | 259 | return 0; |
272 | } | 260 | } |
273 | 261 | ||
274 | static int vidioc_g_frequency (struct file *file, void *priv, | 262 | static int vidioc_g_frequency(struct file *file, void *priv, |
275 | struct v4l2_frequency *f) | 263 | struct v4l2_frequency *f) |
276 | { | 264 | { |
277 | struct az_device *az = video_drvdata(file); | 265 | struct aztech *az = video_drvdata(file); |
278 | 266 | ||
279 | f->type = V4L2_TUNER_RADIO; | 267 | f->type = V4L2_TUNER_RADIO; |
280 | f->frequency = az->curfreq; | 268 | f->frequency = az->curfreq; |
281 | |||
282 | return 0; | 269 | return 0; |
283 | } | 270 | } |
284 | 271 | ||
285 | static int vidioc_queryctrl (struct file *file, void *priv, | 272 | static int vidioc_queryctrl(struct file *file, void *priv, |
286 | struct v4l2_queryctrl *qc) | 273 | struct v4l2_queryctrl *qc) |
287 | { | 274 | { |
288 | int i; | 275 | switch (qc->id) { |
289 | 276 | case V4L2_CID_AUDIO_MUTE: | |
290 | for (i = 0; i < ARRAY_SIZE(radio_qctrl); i++) { | 277 | return v4l2_ctrl_query_fill(qc, 0, 1, 1, 1); |
291 | if (qc->id && qc->id == radio_qctrl[i].id) { | 278 | case V4L2_CID_AUDIO_VOLUME: |
292 | memcpy(qc, &(radio_qctrl[i]), | 279 | return v4l2_ctrl_query_fill(qc, 0, 0xff, 1, 0xff); |
293 | sizeof(*qc)); | ||
294 | return (0); | ||
295 | } | ||
296 | } | 280 | } |
297 | return -EINVAL; | 281 | return -EINVAL; |
298 | } | 282 | } |
299 | 283 | ||
300 | static int vidioc_g_ctrl (struct file *file, void *priv, | 284 | static int vidioc_g_ctrl(struct file *file, void *priv, |
301 | struct v4l2_control *ctrl) | 285 | struct v4l2_control *ctrl) |
302 | { | 286 | { |
303 | struct az_device *az = video_drvdata(file); | 287 | struct aztech *az = video_drvdata(file); |
304 | 288 | ||
305 | switch (ctrl->id) { | 289 | switch (ctrl->id) { |
306 | case V4L2_CID_AUDIO_MUTE: | 290 | case V4L2_CID_AUDIO_MUTE: |
307 | if (az->curvol==0) | 291 | if (az->curvol == 0) |
308 | ctrl->value=1; | 292 | ctrl->value = 1; |
309 | else | 293 | else |
310 | ctrl->value=0; | 294 | ctrl->value = 0; |
311 | return (0); | 295 | return 0; |
312 | case V4L2_CID_AUDIO_VOLUME: | 296 | case V4L2_CID_AUDIO_VOLUME: |
313 | ctrl->value=az->curvol * 6554; | 297 | ctrl->value = az->curvol * 6554; |
314 | return (0); | 298 | return 0; |
315 | } | 299 | } |
316 | return -EINVAL; | 300 | return -EINVAL; |
317 | } | 301 | } |
318 | 302 | ||
319 | static int vidioc_s_ctrl (struct file *file, void *priv, | 303 | static int vidioc_s_ctrl(struct file *file, void *priv, |
320 | struct v4l2_control *ctrl) | 304 | struct v4l2_control *ctrl) |
321 | { | 305 | { |
322 | struct az_device *az = video_drvdata(file); | 306 | struct aztech *az = video_drvdata(file); |
323 | 307 | ||
324 | switch (ctrl->id) { | 308 | switch (ctrl->id) { |
325 | case V4L2_CID_AUDIO_MUTE: | 309 | case V4L2_CID_AUDIO_MUTE: |
326 | if (ctrl->value) { | 310 | if (ctrl->value) |
327 | az_setvol(az,0); | 311 | az_setvol(az, 0); |
328 | } else { | 312 | else |
329 | az_setvol(az,az->curvol); | 313 | az_setvol(az, az->curvol); |
330 | } | 314 | return 0; |
331 | return (0); | 315 | case V4L2_CID_AUDIO_VOLUME: |
332 | case V4L2_CID_AUDIO_VOLUME: | 316 | az_setvol(az, ctrl->value); |
333 | az_setvol(az,ctrl->value); | 317 | return 0; |
334 | return (0); | ||
335 | } | 318 | } |
336 | return -EINVAL; | 319 | return -EINVAL; |
337 | } | 320 | } |
338 | 321 | ||
339 | static struct az_device aztech_unit; | 322 | static int aztech_open(struct file *file) |
340 | |||
341 | static int aztech_exclusive_open(struct file *file) | ||
342 | { | 323 | { |
343 | return test_and_set_bit(0, &aztech_unit.in_use) ? -EBUSY : 0; | 324 | return 0; |
344 | } | 325 | } |
345 | 326 | ||
346 | static int aztech_exclusive_release(struct file *file) | 327 | static int aztech_release(struct file *file) |
347 | { | 328 | { |
348 | clear_bit(0, &aztech_unit.in_use); | ||
349 | return 0; | 329 | return 0; |
350 | } | 330 | } |
351 | 331 | ||
352 | static const struct v4l2_file_operations aztech_fops = { | 332 | static const struct v4l2_file_operations aztech_fops = { |
353 | .owner = THIS_MODULE, | 333 | .owner = THIS_MODULE, |
354 | .open = aztech_exclusive_open, | 334 | .open = aztech_open, |
355 | .release = aztech_exclusive_release, | 335 | .release = aztech_release, |
356 | .ioctl = video_ioctl2, | 336 | .ioctl = video_ioctl2, |
357 | }; | 337 | }; |
358 | 338 | ||
@@ -371,57 +351,60 @@ static const struct v4l2_ioctl_ops aztech_ioctl_ops = { | |||
371 | .vidioc_s_ctrl = vidioc_s_ctrl, | 351 | .vidioc_s_ctrl = vidioc_s_ctrl, |
372 | }; | 352 | }; |
373 | 353 | ||
374 | static struct video_device aztech_radio = { | ||
375 | .name = "Aztech radio", | ||
376 | .fops = &aztech_fops, | ||
377 | .ioctl_ops = &aztech_ioctl_ops, | ||
378 | .release = video_device_release_empty, | ||
379 | }; | ||
380 | |||
381 | module_param_named(debug,aztech_radio.debug, int, 0644); | ||
382 | MODULE_PARM_DESC(debug,"activates debug info"); | ||
383 | |||
384 | static int __init aztech_init(void) | 354 | static int __init aztech_init(void) |
385 | { | 355 | { |
386 | if(io==-1) | 356 | struct aztech *az = &aztech_card; |
387 | { | 357 | struct v4l2_device *v4l2_dev = &az->v4l2_dev; |
388 | printk(KERN_ERR "You must set an I/O address with io=0x???\n"); | 358 | int res; |
359 | |||
360 | strlcpy(v4l2_dev->name, "aztech", sizeof(v4l2_dev->name)); | ||
361 | az->io = io; | ||
362 | |||
363 | if (az->io == -1) { | ||
364 | v4l2_err(v4l2_dev, "you must set an I/O address with io=0x???\n"); | ||
389 | return -EINVAL; | 365 | return -EINVAL; |
390 | } | 366 | } |
391 | 367 | ||
392 | if (!request_region(io, 2, "aztech")) | 368 | if (!request_region(az->io, 2, "aztech")) { |
393 | { | 369 | v4l2_err(v4l2_dev, "port 0x%x already in use\n", az->io); |
394 | printk(KERN_ERR "aztech: port 0x%x already in use\n", io); | ||
395 | return -EBUSY; | 370 | return -EBUSY; |
396 | } | 371 | } |
397 | 372 | ||
398 | mutex_init(&lock); | 373 | res = v4l2_device_register(NULL, v4l2_dev); |
399 | video_set_drvdata(&aztech_radio, &aztech_unit); | 374 | if (res < 0) { |
375 | release_region(az->io, 2); | ||
376 | v4l2_err(v4l2_dev, "Could not register v4l2_device\n"); | ||
377 | return res; | ||
378 | } | ||
400 | 379 | ||
401 | if (video_register_device(&aztech_radio, VFL_TYPE_RADIO, radio_nr) < 0) { | 380 | mutex_init(&az->lock); |
402 | release_region(io,2); | 381 | strlcpy(az->vdev.name, v4l2_dev->name, sizeof(az->vdev.name)); |
382 | az->vdev.v4l2_dev = v4l2_dev; | ||
383 | az->vdev.fops = &aztech_fops; | ||
384 | az->vdev.ioctl_ops = &aztech_ioctl_ops; | ||
385 | az->vdev.release = video_device_release_empty; | ||
386 | video_set_drvdata(&az->vdev, az); | ||
387 | |||
388 | if (video_register_device(&az->vdev, VFL_TYPE_RADIO, radio_nr) < 0) { | ||
389 | v4l2_device_unregister(v4l2_dev); | ||
390 | release_region(az->io, 2); | ||
403 | return -EINVAL; | 391 | return -EINVAL; |
404 | } | 392 | } |
405 | 393 | ||
406 | printk(KERN_INFO "Aztech radio card driver v1.00/19990224 rkroll@exploits.org\n"); | 394 | v4l2_info(v4l2_dev, "Aztech radio card driver v1.00/19990224 rkroll@exploits.org\n"); |
407 | /* mute card - prevents noisy bootups */ | 395 | /* mute card - prevents noisy bootups */ |
408 | outb (0, io); | 396 | outb(0, az->io); |
409 | return 0; | 397 | return 0; |
410 | } | 398 | } |
411 | 399 | ||
412 | MODULE_AUTHOR("Russell Kroll, Quay Lu, Donald Song, Jason Lewis, Scott McGrath, William McGrath"); | 400 | static void __exit aztech_exit(void) |
413 | MODULE_DESCRIPTION("A driver for the Aztech radio card."); | ||
414 | MODULE_LICENSE("GPL"); | ||
415 | |||
416 | module_param(io, int, 0); | ||
417 | module_param(radio_nr, int, 0); | ||
418 | MODULE_PARM_DESC(io, "I/O address of the Aztech card (0x350 or 0x358)"); | ||
419 | |||
420 | static void __exit aztech_cleanup(void) | ||
421 | { | 401 | { |
422 | video_unregister_device(&aztech_radio); | 402 | struct aztech *az = &aztech_card; |
423 | release_region(io,2); | 403 | |
404 | video_unregister_device(&az->vdev); | ||
405 | v4l2_device_unregister(&az->v4l2_dev); | ||
406 | release_region(az->io, 2); | ||
424 | } | 407 | } |
425 | 408 | ||
426 | module_init(aztech_init); | 409 | module_init(aztech_init); |
427 | module_exit(aztech_cleanup); | 410 | module_exit(aztech_exit); |