diff options
author | Hans Verkuil <hverkuil@xs4all.nl> | 2009-03-06 11:52:06 -0500 |
---|---|---|
committer | Mauro Carvalho Chehab <mchehab@redhat.com> | 2009-03-30 11:43:12 -0400 |
commit | 922c78e9f6900ade073da1a92d43c56d77cf790f (patch) | |
tree | e46f7ee11fe53296bf9f963169b8b9f7c49461c4 /drivers/media/radio | |
parent | 2710e6aa3f15cb008577ce31fc469e8af7466075 (diff) |
V4L/DVB (10887): radio-rtrack2: convert to v4l2_device.
Signed-off-by: Hans Verkuil <hverkuil@xs4all.nl>
Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
Diffstat (limited to 'drivers/media/radio')
-rw-r--r-- | drivers/media/radio/radio-rtrack2.c | 278 |
1 files changed, 129 insertions, 149 deletions
diff --git a/drivers/media/radio/radio-rtrack2.c b/drivers/media/radio/radio-rtrack2.c index 2587227214bf..08bd8d9dc4f1 100644 --- a/drivers/media/radio/radio-rtrack2.c +++ b/drivers/media/radio/radio-rtrack2.c | |||
@@ -13,34 +13,17 @@ | |||
13 | #include <linux/init.h> /* Initdata */ | 13 | #include <linux/init.h> /* Initdata */ |
14 | #include <linux/ioport.h> /* request_region */ | 14 | #include <linux/ioport.h> /* request_region */ |
15 | #include <linux/delay.h> /* udelay */ | 15 | #include <linux/delay.h> /* udelay */ |
16 | #include <asm/io.h> /* outb, outb_p */ | ||
17 | #include <asm/uaccess.h> /* copy to/from user */ | ||
18 | #include <linux/videodev2.h> /* kernel radio structs */ | 16 | #include <linux/videodev2.h> /* kernel radio structs */ |
19 | #include <media/v4l2-common.h> | 17 | #include <linux/mutex.h> |
18 | #include <linux/version.h> /* for KERNEL_VERSION MACRO */ | ||
19 | #include <linux/io.h> /* outb, outb_p */ | ||
20 | #include <linux/uaccess.h> /* copy to/from user */ | ||
21 | #include <media/v4l2-device.h> | ||
20 | #include <media/v4l2-ioctl.h> | 22 | #include <media/v4l2-ioctl.h> |
21 | #include <linux/spinlock.h> | ||
22 | 23 | ||
23 | #include <linux/version.h> /* for KERNEL_VERSION MACRO */ | 24 | MODULE_AUTHOR("Ben Pfaff"); |
24 | #define RADIO_VERSION KERNEL_VERSION(0,0,2) | 25 | MODULE_DESCRIPTION("A driver for the RadioTrack II radio card."); |
25 | 26 | MODULE_LICENSE("GPL"); | |
26 | static struct v4l2_queryctrl radio_qctrl[] = { | ||
27 | { | ||
28 | .id = V4L2_CID_AUDIO_MUTE, | ||
29 | .name = "Mute", | ||
30 | .minimum = 0, | ||
31 | .maximum = 1, | ||
32 | .default_value = 1, | ||
33 | .type = V4L2_CTRL_TYPE_BOOLEAN, | ||
34 | },{ | ||
35 | .id = V4L2_CID_AUDIO_VOLUME, | ||
36 | .name = "Volume", | ||
37 | .minimum = 0, | ||
38 | .maximum = 65535, | ||
39 | .step = 65535, | ||
40 | .default_value = 0xff, | ||
41 | .type = V4L2_CTRL_TYPE_INTEGER, | ||
42 | } | ||
43 | }; | ||
44 | 27 | ||
45 | #ifndef CONFIG_RADIO_RTRACK2_PORT | 28 | #ifndef CONFIG_RADIO_RTRACK2_PORT |
46 | #define CONFIG_RADIO_RTRACK2_PORT -1 | 29 | #define CONFIG_RADIO_RTRACK2_PORT -1 |
@@ -48,79 +31,89 @@ static struct v4l2_queryctrl radio_qctrl[] = { | |||
48 | 31 | ||
49 | static int io = CONFIG_RADIO_RTRACK2_PORT; | 32 | static int io = CONFIG_RADIO_RTRACK2_PORT; |
50 | static int radio_nr = -1; | 33 | static int radio_nr = -1; |
51 | static spinlock_t lock; | ||
52 | 34 | ||
53 | struct rt_device | 35 | module_param(io, int, 0); |
36 | MODULE_PARM_DESC(io, "I/O address of the RadioTrack card (0x20c or 0x30c)"); | ||
37 | module_param(radio_nr, int, 0); | ||
38 | |||
39 | #define RADIO_VERSION KERNEL_VERSION(0, 0, 2) | ||
40 | |||
41 | struct rtrack2 | ||
54 | { | 42 | { |
55 | unsigned long in_use; | 43 | struct v4l2_device v4l2_dev; |
56 | int port; | 44 | struct video_device vdev; |
45 | int io; | ||
57 | unsigned long curfreq; | 46 | unsigned long curfreq; |
58 | int muted; | 47 | int muted; |
48 | struct mutex lock; | ||
59 | }; | 49 | }; |
60 | 50 | ||
51 | static struct rtrack2 rtrack2_card; | ||
52 | |||
61 | 53 | ||
62 | /* local things */ | 54 | /* local things */ |
63 | 55 | ||
64 | static void rt_mute(struct rt_device *dev) | 56 | static void rt_mute(struct rtrack2 *dev) |
65 | { | 57 | { |
66 | if(dev->muted) | 58 | if (dev->muted) |
67 | return; | 59 | return; |
68 | spin_lock(&lock); | 60 | mutex_lock(&dev->lock); |
69 | outb(1, io); | 61 | outb(1, dev->io); |
70 | spin_unlock(&lock); | 62 | mutex_unlock(&dev->lock); |
63 | mutex_unlock(&dev->lock); | ||
71 | dev->muted = 1; | 64 | dev->muted = 1; |
72 | } | 65 | } |
73 | 66 | ||
74 | static void rt_unmute(struct rt_device *dev) | 67 | static void rt_unmute(struct rtrack2 *dev) |
75 | { | 68 | { |
76 | if(dev->muted == 0) | 69 | if(dev->muted == 0) |
77 | return; | 70 | return; |
78 | spin_lock(&lock); | 71 | mutex_lock(&dev->lock); |
79 | outb(0, io); | 72 | outb(0, dev->io); |
80 | spin_unlock(&lock); | 73 | mutex_unlock(&dev->lock); |
81 | dev->muted = 0; | 74 | dev->muted = 0; |
82 | } | 75 | } |
83 | 76 | ||
84 | static void zero(void) | 77 | static void zero(struct rtrack2 *dev) |
85 | { | 78 | { |
86 | outb_p(1, io); | 79 | outb_p(1, dev->io); |
87 | outb_p(3, io); | 80 | outb_p(3, dev->io); |
88 | outb_p(1, io); | 81 | outb_p(1, dev->io); |
89 | } | 82 | } |
90 | 83 | ||
91 | static void one(void) | 84 | static void one(struct rtrack2 *dev) |
92 | { | 85 | { |
93 | outb_p(5, io); | 86 | outb_p(5, dev->io); |
94 | outb_p(7, io); | 87 | outb_p(7, dev->io); |
95 | outb_p(5, io); | 88 | outb_p(5, dev->io); |
96 | } | 89 | } |
97 | 90 | ||
98 | static int rt_setfreq(struct rt_device *dev, unsigned long freq) | 91 | static int rt_setfreq(struct rtrack2 *dev, unsigned long freq) |
99 | { | 92 | { |
100 | int i; | 93 | int i; |
101 | 94 | ||
95 | mutex_lock(&dev->lock); | ||
96 | dev->curfreq = freq; | ||
102 | freq = freq / 200 + 856; | 97 | freq = freq / 200 + 856; |
103 | 98 | ||
104 | spin_lock(&lock); | 99 | outb_p(0xc8, dev->io); |
105 | 100 | outb_p(0xc9, dev->io); | |
106 | outb_p(0xc8, io); | 101 | outb_p(0xc9, dev->io); |
107 | outb_p(0xc9, io); | ||
108 | outb_p(0xc9, io); | ||
109 | 102 | ||
110 | for (i = 0; i < 10; i++) | 103 | for (i = 0; i < 10; i++) |
111 | zero (); | 104 | zero(dev); |
112 | 105 | ||
113 | for (i = 14; i >= 0; i--) | 106 | for (i = 14; i >= 0; i--) |
114 | if (freq & (1 << i)) | 107 | if (freq & (1 << i)) |
115 | one (); | 108 | one(dev); |
116 | else | 109 | else |
117 | zero (); | 110 | zero(dev); |
118 | 111 | ||
119 | outb_p(0xc8, io); | 112 | outb_p(0xc8, dev->io); |
120 | if (!dev->muted) | 113 | if (!dev->muted) |
121 | outb_p(0, io); | 114 | outb_p(0, dev->io); |
122 | 115 | ||
123 | spin_unlock(&lock); | 116 | mutex_unlock(&dev->lock); |
124 | return 0; | 117 | return 0; |
125 | } | 118 | } |
126 | 119 | ||
@@ -129,61 +122,61 @@ static int vidioc_querycap(struct file *file, void *priv, | |||
129 | { | 122 | { |
130 | strlcpy(v->driver, "radio-rtrack2", sizeof(v->driver)); | 123 | strlcpy(v->driver, "radio-rtrack2", sizeof(v->driver)); |
131 | strlcpy(v->card, "RadioTrack II", sizeof(v->card)); | 124 | strlcpy(v->card, "RadioTrack II", sizeof(v->card)); |
132 | sprintf(v->bus_info, "ISA"); | 125 | strlcpy(v->bus_info, "ISA", sizeof(v->bus_info)); |
133 | v->version = RADIO_VERSION; | 126 | v->version = RADIO_VERSION; |
134 | v->capabilities = V4L2_CAP_TUNER; | 127 | v->capabilities = V4L2_CAP_TUNER | V4L2_CAP_RADIO; |
135 | return 0; | 128 | return 0; |
136 | } | 129 | } |
137 | 130 | ||
138 | static int vidioc_s_tuner(struct file *file, void *priv, | 131 | static int vidioc_s_tuner(struct file *file, void *priv, |
139 | struct v4l2_tuner *v) | 132 | struct v4l2_tuner *v) |
140 | { | 133 | { |
141 | if (v->index > 0) | 134 | return v->index ? -EINVAL : 0; |
142 | return -EINVAL; | ||
143 | |||
144 | return 0; | ||
145 | } | 135 | } |
146 | 136 | ||
147 | static int rt_getsigstr(struct rt_device *dev) | 137 | static int rt_getsigstr(struct rtrack2 *dev) |
148 | { | 138 | { |
149 | if (inb(io) & 2) /* bit set = no signal present */ | 139 | int sig = 1; |
150 | return 0; | 140 | |
151 | return 1; /* signal present */ | 141 | mutex_lock(&dev->lock); |
142 | if (inb(dev->io) & 2) /* bit set = no signal present */ | ||
143 | sig = 0; | ||
144 | mutex_unlock(&dev->lock); | ||
145 | return sig; | ||
152 | } | 146 | } |
153 | 147 | ||
154 | static int vidioc_g_tuner(struct file *file, void *priv, | 148 | static int vidioc_g_tuner(struct file *file, void *priv, |
155 | struct v4l2_tuner *v) | 149 | struct v4l2_tuner *v) |
156 | { | 150 | { |
157 | struct rt_device *rt = video_drvdata(file); | 151 | struct rtrack2 *rt = video_drvdata(file); |
158 | 152 | ||
159 | if (v->index > 0) | 153 | if (v->index > 0) |
160 | return -EINVAL; | 154 | return -EINVAL; |
161 | 155 | ||
162 | strcpy(v->name, "FM"); | 156 | strlcpy(v->name, "FM", sizeof(v->name)); |
163 | v->type = V4L2_TUNER_RADIO; | 157 | v->type = V4L2_TUNER_RADIO; |
164 | v->rangelow = (88*16000); | 158 | v->rangelow = 88 * 16000; |
165 | v->rangehigh = (108*16000); | 159 | v->rangehigh = 108 * 16000; |
166 | v->rxsubchans = V4L2_TUNER_SUB_MONO; | 160 | v->rxsubchans = V4L2_TUNER_SUB_MONO; |
167 | v->capability = V4L2_TUNER_CAP_LOW; | 161 | v->capability = V4L2_TUNER_CAP_LOW; |
168 | v->audmode = V4L2_TUNER_MODE_MONO; | 162 | v->audmode = V4L2_TUNER_MODE_MONO; |
169 | v->signal = 0xFFFF*rt_getsigstr(rt); | 163 | v->signal = 0xFFFF * rt_getsigstr(rt); |
170 | return 0; | 164 | return 0; |
171 | } | 165 | } |
172 | 166 | ||
173 | static int vidioc_s_frequency(struct file *file, void *priv, | 167 | static int vidioc_s_frequency(struct file *file, void *priv, |
174 | struct v4l2_frequency *f) | 168 | struct v4l2_frequency *f) |
175 | { | 169 | { |
176 | struct rt_device *rt = video_drvdata(file); | 170 | struct rtrack2 *rt = video_drvdata(file); |
177 | 171 | ||
178 | rt->curfreq = f->frequency; | 172 | rt_setfreq(rt, f->frequency); |
179 | rt_setfreq(rt, rt->curfreq); | ||
180 | return 0; | 173 | return 0; |
181 | } | 174 | } |
182 | 175 | ||
183 | static int vidioc_g_frequency(struct file *file, void *priv, | 176 | static int vidioc_g_frequency(struct file *file, void *priv, |
184 | struct v4l2_frequency *f) | 177 | struct v4l2_frequency *f) |
185 | { | 178 | { |
186 | struct rt_device *rt = video_drvdata(file); | 179 | struct rtrack2 *rt = video_drvdata(file); |
187 | 180 | ||
188 | f->type = V4L2_TUNER_RADIO; | 181 | f->type = V4L2_TUNER_RADIO; |
189 | f->frequency = rt->curfreq; | 182 | f->frequency = rt->curfreq; |
@@ -193,14 +186,11 @@ static int vidioc_g_frequency(struct file *file, void *priv, | |||
193 | static int vidioc_queryctrl(struct file *file, void *priv, | 186 | static int vidioc_queryctrl(struct file *file, void *priv, |
194 | struct v4l2_queryctrl *qc) | 187 | struct v4l2_queryctrl *qc) |
195 | { | 188 | { |
196 | int i; | 189 | switch (qc->id) { |
197 | 190 | case V4L2_CID_AUDIO_MUTE: | |
198 | for (i = 0; i < ARRAY_SIZE(radio_qctrl); i++) { | 191 | return v4l2_ctrl_query_fill(qc, 0, 1, 1, 1); |
199 | if (qc->id && qc->id == radio_qctrl[i].id) { | 192 | case V4L2_CID_AUDIO_VOLUME: |
200 | memcpy(qc, &(radio_qctrl[i]), | 193 | return v4l2_ctrl_query_fill(qc, 0, 65535, 65535, 65535); |
201 | sizeof(*qc)); | ||
202 | return 0; | ||
203 | } | ||
204 | } | 194 | } |
205 | return -EINVAL; | 195 | return -EINVAL; |
206 | } | 196 | } |
@@ -208,7 +198,7 @@ static int vidioc_queryctrl(struct file *file, void *priv, | |||
208 | static int vidioc_g_ctrl(struct file *file, void *priv, | 198 | static int vidioc_g_ctrl(struct file *file, void *priv, |
209 | struct v4l2_control *ctrl) | 199 | struct v4l2_control *ctrl) |
210 | { | 200 | { |
211 | struct rt_device *rt = video_drvdata(file); | 201 | struct rtrack2 *rt = video_drvdata(file); |
212 | 202 | ||
213 | switch (ctrl->id) { | 203 | switch (ctrl->id) { |
214 | case V4L2_CID_AUDIO_MUTE: | 204 | case V4L2_CID_AUDIO_MUTE: |
@@ -227,7 +217,7 @@ static int vidioc_g_ctrl(struct file *file, void *priv, | |||
227 | static int vidioc_s_ctrl(struct file *file, void *priv, | 217 | static int vidioc_s_ctrl(struct file *file, void *priv, |
228 | struct v4l2_control *ctrl) | 218 | struct v4l2_control *ctrl) |
229 | { | 219 | { |
230 | struct rt_device *rt = video_drvdata(file); | 220 | struct rtrack2 *rt = video_drvdata(file); |
231 | 221 | ||
232 | switch (ctrl->id) { | 222 | switch (ctrl->id) { |
233 | case V4L2_CID_AUDIO_MUTE: | 223 | case V4L2_CID_AUDIO_MUTE: |
@@ -246,17 +236,6 @@ static int vidioc_s_ctrl(struct file *file, void *priv, | |||
246 | return -EINVAL; | 236 | return -EINVAL; |
247 | } | 237 | } |
248 | 238 | ||
249 | static int vidioc_g_audio(struct file *file, void *priv, | ||
250 | struct v4l2_audio *a) | ||
251 | { | ||
252 | if (a->index > 1) | ||
253 | return -EINVAL; | ||
254 | |||
255 | strcpy(a->name, "Radio"); | ||
256 | a->capability = V4L2_AUDCAP_STEREO; | ||
257 | return 0; | ||
258 | } | ||
259 | |||
260 | static int vidioc_g_input(struct file *filp, void *priv, unsigned int *i) | 239 | static int vidioc_g_input(struct file *filp, void *priv, unsigned int *i) |
261 | { | 240 | { |
262 | *i = 0; | 241 | *i = 0; |
@@ -265,36 +244,38 @@ static int vidioc_g_input(struct file *filp, void *priv, unsigned int *i) | |||
265 | 244 | ||
266 | static int vidioc_s_input(struct file *filp, void *priv, unsigned int i) | 245 | static int vidioc_s_input(struct file *filp, void *priv, unsigned int i) |
267 | { | 246 | { |
268 | if (i != 0) | 247 | return i ? -EINVAL : 0; |
269 | return -EINVAL; | ||
270 | return 0; | ||
271 | } | 248 | } |
272 | 249 | ||
273 | static int vidioc_s_audio(struct file *file, void *priv, | 250 | static int vidioc_g_audio(struct file *file, void *priv, |
274 | struct v4l2_audio *a) | 251 | struct v4l2_audio *a) |
275 | { | 252 | { |
276 | if (a->index != 0) | 253 | a->index = 0; |
277 | return -EINVAL; | 254 | strlcpy(a->name, "Radio", sizeof(a->name)); |
255 | a->capability = V4L2_AUDCAP_STEREO; | ||
278 | return 0; | 256 | return 0; |
279 | } | 257 | } |
280 | 258 | ||
281 | static struct rt_device rtrack2_unit; | 259 | static int vidioc_s_audio(struct file *file, void *priv, |
260 | struct v4l2_audio *a) | ||
261 | { | ||
262 | return a->index ? -EINVAL : 0; | ||
263 | } | ||
282 | 264 | ||
283 | static int rtrack2_exclusive_open(struct file *file) | 265 | static int rtrack2_open(struct file *file) |
284 | { | 266 | { |
285 | return test_and_set_bit(0, &rtrack2_unit.in_use) ? -EBUSY : 0; | 267 | return 0; |
286 | } | 268 | } |
287 | 269 | ||
288 | static int rtrack2_exclusive_release(struct file *file) | 270 | static int rtrack2_release(struct file *file) |
289 | { | 271 | { |
290 | clear_bit(0, &rtrack2_unit.in_use); | ||
291 | return 0; | 272 | return 0; |
292 | } | 273 | } |
293 | 274 | ||
294 | static const struct v4l2_file_operations rtrack2_fops = { | 275 | static const struct v4l2_file_operations rtrack2_fops = { |
295 | .owner = THIS_MODULE, | 276 | .owner = THIS_MODULE, |
296 | .open = rtrack2_exclusive_open, | 277 | .open = rtrack2_open, |
297 | .release = rtrack2_exclusive_release, | 278 | .release = rtrack2_release, |
298 | .ioctl = video_ioctl2, | 279 | .ioctl = video_ioctl2, |
299 | }; | 280 | }; |
300 | 281 | ||
@@ -313,62 +294,61 @@ static const struct v4l2_ioctl_ops rtrack2_ioctl_ops = { | |||
313 | .vidioc_s_input = vidioc_s_input, | 294 | .vidioc_s_input = vidioc_s_input, |
314 | }; | 295 | }; |
315 | 296 | ||
316 | static struct video_device rtrack2_radio = { | ||
317 | .name = "RadioTrack II radio", | ||
318 | .fops = &rtrack2_fops, | ||
319 | .ioctl_ops = &rtrack2_ioctl_ops, | ||
320 | .release = video_device_release_empty, | ||
321 | }; | ||
322 | |||
323 | static int __init rtrack2_init(void) | 297 | static int __init rtrack2_init(void) |
324 | { | 298 | { |
325 | if(io==-1) | 299 | struct rtrack2 *dev = &rtrack2_card; |
326 | { | 300 | struct v4l2_device *v4l2_dev = &dev->v4l2_dev; |
327 | printk(KERN_ERR "You must set an I/O address with io=0x20c or io=0x30c\n"); | 301 | int res; |
302 | |||
303 | strlcpy(v4l2_dev->name, "rtrack2", sizeof(v4l2_dev->name)); | ||
304 | dev->io = io; | ||
305 | if (dev->io == -1) { | ||
306 | v4l2_err(v4l2_dev, "You must set an I/O address with io=0x20c or io=0x30c\n"); | ||
328 | return -EINVAL; | 307 | return -EINVAL; |
329 | } | 308 | } |
330 | if (!request_region(io, 4, "rtrack2")) | 309 | if (!request_region(dev->io, 4, "rtrack2")) { |
331 | { | 310 | v4l2_err(v4l2_dev, "port 0x%x already in use\n", dev->io); |
332 | printk(KERN_ERR "rtrack2: port 0x%x already in use\n", io); | ||
333 | return -EBUSY; | 311 | return -EBUSY; |
334 | } | 312 | } |
335 | 313 | ||
336 | video_set_drvdata(&rtrack2_radio, &rtrack2_unit); | 314 | res = v4l2_device_register(NULL, v4l2_dev); |
315 | if (res < 0) { | ||
316 | release_region(dev->io, 4); | ||
317 | v4l2_err(v4l2_dev, "Could not register v4l2_device\n"); | ||
318 | return res; | ||
319 | } | ||
337 | 320 | ||
338 | spin_lock_init(&lock); | 321 | strlcpy(dev->vdev.name, v4l2_dev->name, sizeof(dev->vdev.name)); |
339 | if (video_register_device(&rtrack2_radio, VFL_TYPE_RADIO, radio_nr) < 0) { | 322 | dev->vdev.v4l2_dev = v4l2_dev; |
340 | release_region(io, 4); | 323 | dev->vdev.fops = &rtrack2_fops; |
324 | dev->vdev.ioctl_ops = &rtrack2_ioctl_ops; | ||
325 | dev->vdev.release = video_device_release_empty; | ||
326 | video_set_drvdata(&dev->vdev, dev); | ||
327 | |||
328 | mutex_init(&dev->lock); | ||
329 | if (video_register_device(&dev->vdev, VFL_TYPE_RADIO, radio_nr) < 0) { | ||
330 | v4l2_device_unregister(v4l2_dev); | ||
331 | release_region(dev->io, 4); | ||
341 | return -EINVAL; | 332 | return -EINVAL; |
342 | } | 333 | } |
343 | 334 | ||
344 | printk(KERN_INFO "AIMSlab Radiotrack II card driver.\n"); | 335 | v4l2_info(v4l2_dev, "AIMSlab Radiotrack II card driver.\n"); |
345 | 336 | ||
346 | /* mute card - prevents noisy bootups */ | 337 | /* mute card - prevents noisy bootups */ |
347 | outb(1, io); | 338 | outb(1, dev->io); |
348 | rtrack2_unit.muted = 1; | 339 | dev->muted = 1; |
349 | 340 | ||
350 | return 0; | 341 | return 0; |
351 | } | 342 | } |
352 | 343 | ||
353 | MODULE_AUTHOR("Ben Pfaff"); | 344 | static void __exit rtrack2_exit(void) |
354 | MODULE_DESCRIPTION("A driver for the RadioTrack II radio card."); | ||
355 | MODULE_LICENSE("GPL"); | ||
356 | |||
357 | module_param(io, int, 0); | ||
358 | MODULE_PARM_DESC(io, "I/O address of the RadioTrack card (0x20c or 0x30c)"); | ||
359 | module_param(radio_nr, int, 0); | ||
360 | |||
361 | static void __exit rtrack2_cleanup_module(void) | ||
362 | { | 345 | { |
363 | video_unregister_device(&rtrack2_radio); | 346 | struct rtrack2 *dev = &rtrack2_card; |
364 | release_region(io,4); | 347 | |
348 | video_unregister_device(&dev->vdev); | ||
349 | v4l2_device_unregister(&dev->v4l2_dev); | ||
350 | release_region(dev->io, 4); | ||
365 | } | 351 | } |
366 | 352 | ||
367 | module_init(rtrack2_init); | 353 | module_init(rtrack2_init); |
368 | module_exit(rtrack2_cleanup_module); | 354 | module_exit(rtrack2_exit); |
369 | |||
370 | /* | ||
371 | Local variables: | ||
372 | compile-command: "mmake" | ||
373 | End: | ||
374 | */ | ||