diff options
Diffstat (limited to 'drivers/media/radio')
-rw-r--r-- | drivers/media/radio/Kconfig | 4 | ||||
-rw-r--r-- | drivers/media/radio/Makefile | 1 | ||||
-rw-r--r-- | drivers/media/radio/radio-isa.c | 339 | ||||
-rw-r--r-- | drivers/media/radio/radio-isa.h | 105 |
4 files changed, 449 insertions, 0 deletions
diff --git a/drivers/media/radio/Kconfig b/drivers/media/radio/Kconfig index 48747df59453..e291e0e2669f 100644 --- a/drivers/media/radio/Kconfig +++ b/drivers/media/radio/Kconfig | |||
@@ -177,6 +177,10 @@ menuconfig V4L_RADIO_ISA_DRIVERS | |||
177 | 177 | ||
178 | if V4L_RADIO_ISA_DRIVERS | 178 | if V4L_RADIO_ISA_DRIVERS |
179 | 179 | ||
180 | config RADIO_ISA | ||
181 | depends on ISA | ||
182 | tristate | ||
183 | |||
180 | config RADIO_CADET | 184 | config RADIO_CADET |
181 | tristate "ADS Cadet AM/FM Tuner" | 185 | tristate "ADS Cadet AM/FM Tuner" |
182 | depends on ISA && VIDEO_V4L2 | 186 | depends on ISA && VIDEO_V4L2 |
diff --git a/drivers/media/radio/Makefile b/drivers/media/radio/Makefile index aec5f6fa592f..ca8c7d134b95 100644 --- a/drivers/media/radio/Makefile +++ b/drivers/media/radio/Makefile | |||
@@ -2,6 +2,7 @@ | |||
2 | # Makefile for the kernel character device drivers. | 2 | # Makefile for the kernel character device drivers. |
3 | # | 3 | # |
4 | 4 | ||
5 | obj-$(CONFIG_RADIO_ISA) += radio-isa.o | ||
5 | obj-$(CONFIG_RADIO_AZTECH) += radio-aztech.o | 6 | obj-$(CONFIG_RADIO_AZTECH) += radio-aztech.o |
6 | obj-$(CONFIG_RADIO_RTRACK2) += radio-rtrack2.o | 7 | obj-$(CONFIG_RADIO_RTRACK2) += radio-rtrack2.o |
7 | obj-$(CONFIG_RADIO_SF16FMI) += radio-sf16fmi.o | 8 | obj-$(CONFIG_RADIO_SF16FMI) += radio-sf16fmi.o |
diff --git a/drivers/media/radio/radio-isa.c b/drivers/media/radio/radio-isa.c new file mode 100644 index 000000000000..02bcead8b087 --- /dev/null +++ b/drivers/media/radio/radio-isa.c | |||
@@ -0,0 +1,339 @@ | |||
1 | /* | ||
2 | * Framework for ISA radio drivers. | ||
3 | * This takes care of all the V4L2 scaffolding, allowing the ISA drivers | ||
4 | * to concentrate on the actual hardware operation. | ||
5 | * | ||
6 | * Copyright (C) 2012 Hans Verkuil <hans.verkuil@cisco.com> | ||
7 | * | ||
8 | * This program is free software; you can redistribute it and/or | ||
9 | * modify it under the terms of the GNU General Public License | ||
10 | * version 2 as published by the Free Software Foundation. | ||
11 | * | ||
12 | * This program is distributed in the hope that it will be useful, but | ||
13 | * WITHOUT ANY WARRANTY; without even the implied warranty of | ||
14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
15 | * General Public License for more details. | ||
16 | * | ||
17 | * You should have received a copy of the GNU General Public License | ||
18 | * along with this program; if not, write to the Free Software | ||
19 | * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA | ||
20 | * 02110-1301 USA | ||
21 | */ | ||
22 | |||
23 | #include <linux/module.h> | ||
24 | #include <linux/init.h> | ||
25 | #include <linux/ioport.h> | ||
26 | #include <linux/delay.h> | ||
27 | #include <linux/videodev2.h> | ||
28 | #include <linux/io.h> | ||
29 | #include <media/v4l2-device.h> | ||
30 | #include <media/v4l2-ioctl.h> | ||
31 | #include <media/v4l2-fh.h> | ||
32 | #include <media/v4l2-ctrls.h> | ||
33 | #include <media/v4l2-event.h> | ||
34 | |||
35 | #include "radio-isa.h" | ||
36 | |||
37 | MODULE_AUTHOR("Hans Verkuil"); | ||
38 | MODULE_DESCRIPTION("A framework for ISA radio drivers."); | ||
39 | MODULE_LICENSE("GPL"); | ||
40 | |||
41 | #define FREQ_LOW (87U * 16000U) | ||
42 | #define FREQ_HIGH (108U * 16000U) | ||
43 | |||
44 | static int radio_isa_querycap(struct file *file, void *priv, | ||
45 | struct v4l2_capability *v) | ||
46 | { | ||
47 | struct radio_isa_card *isa = video_drvdata(file); | ||
48 | |||
49 | strlcpy(v->driver, isa->drv->driver.driver.name, sizeof(v->driver)); | ||
50 | strlcpy(v->card, isa->drv->card, sizeof(v->card)); | ||
51 | snprintf(v->bus_info, sizeof(v->bus_info), "ISA:%s", isa->v4l2_dev.name); | ||
52 | |||
53 | v->capabilities = V4L2_CAP_TUNER | V4L2_CAP_RADIO; | ||
54 | v->device_caps = v->capabilities | V4L2_CAP_DEVICE_CAPS; | ||
55 | return 0; | ||
56 | } | ||
57 | |||
58 | static int radio_isa_g_tuner(struct file *file, void *priv, | ||
59 | struct v4l2_tuner *v) | ||
60 | { | ||
61 | struct radio_isa_card *isa = video_drvdata(file); | ||
62 | const struct radio_isa_ops *ops = isa->drv->ops; | ||
63 | |||
64 | if (v->index > 0) | ||
65 | return -EINVAL; | ||
66 | |||
67 | strlcpy(v->name, "FM", sizeof(v->name)); | ||
68 | v->type = V4L2_TUNER_RADIO; | ||
69 | v->rangelow = FREQ_LOW; | ||
70 | v->rangehigh = FREQ_HIGH; | ||
71 | v->capability = V4L2_TUNER_CAP_LOW; | ||
72 | if (isa->drv->has_stereo) | ||
73 | v->capability |= V4L2_TUNER_CAP_STEREO; | ||
74 | |||
75 | if (ops->g_rxsubchans) | ||
76 | v->rxsubchans = ops->g_rxsubchans(isa); | ||
77 | else | ||
78 | v->rxsubchans = V4L2_TUNER_SUB_MONO | V4L2_TUNER_SUB_STEREO; | ||
79 | v->audmode = isa->stereo ? V4L2_TUNER_MODE_STEREO : V4L2_TUNER_MODE_MONO; | ||
80 | if (ops->g_signal) | ||
81 | v->signal = ops->g_signal(isa); | ||
82 | else | ||
83 | v->signal = (v->rxsubchans & V4L2_TUNER_SUB_STEREO) ? | ||
84 | 0xffff : 0; | ||
85 | return 0; | ||
86 | } | ||
87 | |||
88 | static int radio_isa_s_tuner(struct file *file, void *priv, | ||
89 | struct v4l2_tuner *v) | ||
90 | { | ||
91 | struct radio_isa_card *isa = video_drvdata(file); | ||
92 | const struct radio_isa_ops *ops = isa->drv->ops; | ||
93 | |||
94 | if (v->index) | ||
95 | return -EINVAL; | ||
96 | if (ops->s_stereo) { | ||
97 | isa->stereo = (v->audmode == V4L2_TUNER_MODE_STEREO); | ||
98 | return ops->s_stereo(isa, isa->stereo); | ||
99 | } | ||
100 | return 0; | ||
101 | } | ||
102 | |||
103 | static int radio_isa_s_frequency(struct file *file, void *priv, | ||
104 | struct v4l2_frequency *f) | ||
105 | { | ||
106 | struct radio_isa_card *isa = video_drvdata(file); | ||
107 | int res; | ||
108 | |||
109 | if (f->tuner != 0 || f->type != V4L2_TUNER_RADIO) | ||
110 | return -EINVAL; | ||
111 | f->frequency = clamp(f->frequency, FREQ_LOW, FREQ_HIGH); | ||
112 | res = isa->drv->ops->s_frequency(isa, f->frequency); | ||
113 | if (res == 0) | ||
114 | isa->freq = f->frequency; | ||
115 | return res; | ||
116 | } | ||
117 | |||
118 | static int radio_isa_g_frequency(struct file *file, void *priv, | ||
119 | struct v4l2_frequency *f) | ||
120 | { | ||
121 | struct radio_isa_card *isa = video_drvdata(file); | ||
122 | |||
123 | if (f->tuner != 0) | ||
124 | return -EINVAL; | ||
125 | f->type = V4L2_TUNER_RADIO; | ||
126 | f->frequency = isa->freq; | ||
127 | return 0; | ||
128 | } | ||
129 | |||
130 | static int radio_isa_s_ctrl(struct v4l2_ctrl *ctrl) | ||
131 | { | ||
132 | struct radio_isa_card *isa = | ||
133 | container_of(ctrl->handler, struct radio_isa_card, hdl); | ||
134 | |||
135 | switch (ctrl->id) { | ||
136 | case V4L2_CID_AUDIO_MUTE: | ||
137 | return isa->drv->ops->s_mute_volume(isa, ctrl->val, | ||
138 | isa->volume ? isa->volume->val : 0); | ||
139 | } | ||
140 | return -EINVAL; | ||
141 | } | ||
142 | |||
143 | static int radio_isa_log_status(struct file *file, void *priv) | ||
144 | { | ||
145 | struct radio_isa_card *isa = video_drvdata(file); | ||
146 | |||
147 | v4l2_info(&isa->v4l2_dev, "I/O Port = 0x%03x\n", isa->io); | ||
148 | v4l2_ctrl_handler_log_status(&isa->hdl, isa->v4l2_dev.name); | ||
149 | return 0; | ||
150 | } | ||
151 | |||
152 | static int radio_isa_subscribe_event(struct v4l2_fh *fh, | ||
153 | struct v4l2_event_subscription *sub) | ||
154 | { | ||
155 | if (sub->type == V4L2_EVENT_CTRL) | ||
156 | return v4l2_event_subscribe(fh, sub, 0); | ||
157 | return -EINVAL; | ||
158 | } | ||
159 | |||
160 | static const struct v4l2_ctrl_ops radio_isa_ctrl_ops = { | ||
161 | .s_ctrl = radio_isa_s_ctrl, | ||
162 | }; | ||
163 | |||
164 | static const struct v4l2_file_operations radio_isa_fops = { | ||
165 | .owner = THIS_MODULE, | ||
166 | .open = v4l2_fh_open, | ||
167 | .release = v4l2_fh_release, | ||
168 | .poll = v4l2_ctrl_poll, | ||
169 | .unlocked_ioctl = video_ioctl2, | ||
170 | }; | ||
171 | |||
172 | static const struct v4l2_ioctl_ops radio_isa_ioctl_ops = { | ||
173 | .vidioc_querycap = radio_isa_querycap, | ||
174 | .vidioc_g_tuner = radio_isa_g_tuner, | ||
175 | .vidioc_s_tuner = radio_isa_s_tuner, | ||
176 | .vidioc_g_frequency = radio_isa_g_frequency, | ||
177 | .vidioc_s_frequency = radio_isa_s_frequency, | ||
178 | .vidioc_log_status = radio_isa_log_status, | ||
179 | .vidioc_subscribe_event = radio_isa_subscribe_event, | ||
180 | .vidioc_unsubscribe_event = v4l2_event_unsubscribe, | ||
181 | }; | ||
182 | |||
183 | int radio_isa_match(struct device *pdev, unsigned int dev) | ||
184 | { | ||
185 | struct radio_isa_driver *drv = pdev->platform_data; | ||
186 | |||
187 | return drv->probe || drv->io_params[dev] >= 0; | ||
188 | } | ||
189 | EXPORT_SYMBOL_GPL(radio_isa_match); | ||
190 | |||
191 | static bool radio_isa_valid_io(const struct radio_isa_driver *drv, int io) | ||
192 | { | ||
193 | int i; | ||
194 | |||
195 | for (i = 0; i < drv->num_of_io_ports; i++) | ||
196 | if (drv->io_ports[i] == io) | ||
197 | return true; | ||
198 | return false; | ||
199 | } | ||
200 | |||
201 | int radio_isa_probe(struct device *pdev, unsigned int dev) | ||
202 | { | ||
203 | struct radio_isa_driver *drv = pdev->platform_data; | ||
204 | const struct radio_isa_ops *ops = drv->ops; | ||
205 | struct v4l2_device *v4l2_dev; | ||
206 | struct radio_isa_card *isa; | ||
207 | int res; | ||
208 | |||
209 | isa = drv->ops->alloc(); | ||
210 | if (isa == NULL) | ||
211 | return -ENOMEM; | ||
212 | dev_set_drvdata(pdev, isa); | ||
213 | isa->drv = drv; | ||
214 | isa->io = drv->io_params[dev]; | ||
215 | v4l2_dev = &isa->v4l2_dev; | ||
216 | strlcpy(v4l2_dev->name, dev_name(pdev), sizeof(v4l2_dev->name)); | ||
217 | |||
218 | if (drv->probe && ops->probe) { | ||
219 | int i; | ||
220 | |||
221 | for (i = 0; i < drv->num_of_io_ports; ++i) { | ||
222 | int io = drv->io_ports[i]; | ||
223 | |||
224 | if (request_region(io, drv->region_size, v4l2_dev->name)) { | ||
225 | bool found = ops->probe(isa, io); | ||
226 | |||
227 | release_region(io, drv->region_size); | ||
228 | if (found) { | ||
229 | isa->io = io; | ||
230 | break; | ||
231 | } | ||
232 | } | ||
233 | } | ||
234 | } | ||
235 | |||
236 | if (!radio_isa_valid_io(drv, isa->io)) { | ||
237 | int i; | ||
238 | |||
239 | if (isa->io < 0) | ||
240 | return -ENODEV; | ||
241 | v4l2_err(v4l2_dev, "you must set an I/O address with io=0x%03x", | ||
242 | drv->io_ports[0]); | ||
243 | for (i = 1; i < drv->num_of_io_ports; i++) | ||
244 | printk(KERN_CONT "/0x%03x", drv->io_ports[i]); | ||
245 | printk(KERN_CONT ".\n"); | ||
246 | kfree(isa); | ||
247 | return -EINVAL; | ||
248 | } | ||
249 | |||
250 | if (!request_region(isa->io, drv->region_size, v4l2_dev->name)) { | ||
251 | v4l2_err(v4l2_dev, "port 0x%x already in use\n", isa->io); | ||
252 | kfree(isa); | ||
253 | return -EBUSY; | ||
254 | } | ||
255 | |||
256 | res = v4l2_device_register(pdev, v4l2_dev); | ||
257 | if (res < 0) { | ||
258 | v4l2_err(v4l2_dev, "Could not register v4l2_device\n"); | ||
259 | goto err_dev_reg; | ||
260 | } | ||
261 | |||
262 | v4l2_ctrl_handler_init(&isa->hdl, 1); | ||
263 | isa->mute = v4l2_ctrl_new_std(&isa->hdl, &radio_isa_ctrl_ops, | ||
264 | V4L2_CID_AUDIO_MUTE, 0, 1, 1, 1); | ||
265 | if (drv->max_volume) | ||
266 | isa->volume = v4l2_ctrl_new_std(&isa->hdl, &radio_isa_ctrl_ops, | ||
267 | V4L2_CID_AUDIO_VOLUME, 0, drv->max_volume, 1, | ||
268 | drv->max_volume); | ||
269 | v4l2_dev->ctrl_handler = &isa->hdl; | ||
270 | if (isa->hdl.error) { | ||
271 | res = isa->hdl.error; | ||
272 | v4l2_err(v4l2_dev, "Could not register controls\n"); | ||
273 | goto err_hdl; | ||
274 | } | ||
275 | if (drv->max_volume) | ||
276 | v4l2_ctrl_cluster(2, &isa->mute); | ||
277 | v4l2_dev->ctrl_handler = &isa->hdl; | ||
278 | |||
279 | mutex_init(&isa->lock); | ||
280 | isa->vdev.lock = &isa->lock; | ||
281 | strlcpy(isa->vdev.name, v4l2_dev->name, sizeof(isa->vdev.name)); | ||
282 | isa->vdev.v4l2_dev = v4l2_dev; | ||
283 | isa->vdev.fops = &radio_isa_fops; | ||
284 | isa->vdev.ioctl_ops = &radio_isa_ioctl_ops; | ||
285 | isa->vdev.release = video_device_release_empty; | ||
286 | set_bit(V4L2_FL_USE_FH_PRIO, &isa->vdev.flags); | ||
287 | video_set_drvdata(&isa->vdev, isa); | ||
288 | isa->freq = FREQ_LOW; | ||
289 | isa->stereo = drv->has_stereo; | ||
290 | |||
291 | if (ops->init) | ||
292 | res = ops->init(isa); | ||
293 | if (!res) | ||
294 | res = v4l2_ctrl_handler_setup(&isa->hdl); | ||
295 | if (!res) | ||
296 | res = ops->s_frequency(isa, isa->freq); | ||
297 | if (!res && ops->s_stereo) | ||
298 | res = ops->s_stereo(isa, isa->stereo); | ||
299 | if (res < 0) { | ||
300 | v4l2_err(v4l2_dev, "Could not setup card\n"); | ||
301 | goto err_node_reg; | ||
302 | } | ||
303 | res = video_register_device(&isa->vdev, VFL_TYPE_RADIO, | ||
304 | drv->radio_nr_params[dev]); | ||
305 | if (res < 0) { | ||
306 | v4l2_err(v4l2_dev, "Could not register device node\n"); | ||
307 | goto err_node_reg; | ||
308 | } | ||
309 | |||
310 | v4l2_info(v4l2_dev, "Initialized radio card %s on port 0x%03x\n", | ||
311 | drv->card, isa->io); | ||
312 | return 0; | ||
313 | |||
314 | err_node_reg: | ||
315 | v4l2_ctrl_handler_free(&isa->hdl); | ||
316 | err_hdl: | ||
317 | v4l2_device_unregister(&isa->v4l2_dev); | ||
318 | err_dev_reg: | ||
319 | release_region(isa->io, drv->region_size); | ||
320 | kfree(isa); | ||
321 | return res; | ||
322 | } | ||
323 | EXPORT_SYMBOL_GPL(radio_isa_probe); | ||
324 | |||
325 | int radio_isa_remove(struct device *pdev, unsigned int dev) | ||
326 | { | ||
327 | struct radio_isa_card *isa = dev_get_drvdata(pdev); | ||
328 | const struct radio_isa_ops *ops = isa->drv->ops; | ||
329 | |||
330 | ops->s_mute_volume(isa, true, isa->volume ? isa->volume->cur.val : 0); | ||
331 | video_unregister_device(&isa->vdev); | ||
332 | v4l2_ctrl_handler_free(&isa->hdl); | ||
333 | v4l2_device_unregister(&isa->v4l2_dev); | ||
334 | release_region(isa->io, isa->drv->region_size); | ||
335 | v4l2_info(&isa->v4l2_dev, "Removed radio card %s\n", isa->drv->card); | ||
336 | kfree(isa); | ||
337 | return 0; | ||
338 | } | ||
339 | EXPORT_SYMBOL_GPL(radio_isa_remove); | ||
diff --git a/drivers/media/radio/radio-isa.h b/drivers/media/radio/radio-isa.h new file mode 100644 index 000000000000..8a0ea84d86de --- /dev/null +++ b/drivers/media/radio/radio-isa.h | |||
@@ -0,0 +1,105 @@ | |||
1 | /* | ||
2 | * Framework for ISA radio drivers. | ||
3 | * This takes care of all the V4L2 scaffolding, allowing the ISA drivers | ||
4 | * to concentrate on the actual hardware operation. | ||
5 | * | ||
6 | * Copyright (C) 2012 Hans Verkuil <hans.verkuil@cisco.com> | ||
7 | * | ||
8 | * This program is free software; you can redistribute it and/or | ||
9 | * modify it under the terms of the GNU General Public License | ||
10 | * version 2 as published by the Free Software Foundation. | ||
11 | * | ||
12 | * This program is distributed in the hope that it will be useful, but | ||
13 | * WITHOUT ANY WARRANTY; without even the implied warranty of | ||
14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
15 | * General Public License for more details. | ||
16 | * | ||
17 | * You should have received a copy of the GNU General Public License | ||
18 | * along with this program; if not, write to the Free Software | ||
19 | * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA | ||
20 | * 02110-1301 USA | ||
21 | */ | ||
22 | |||
23 | #ifndef _RADIO_ISA_H_ | ||
24 | #define _RADIO_ISA_H_ | ||
25 | |||
26 | #include <linux/isa.h> | ||
27 | #include <linux/videodev2.h> | ||
28 | #include <media/v4l2-device.h> | ||
29 | #include <media/v4l2-ctrls.h> | ||
30 | |||
31 | struct radio_isa_driver; | ||
32 | struct radio_isa_ops; | ||
33 | |||
34 | /* Core structure for radio ISA cards */ | ||
35 | struct radio_isa_card { | ||
36 | const struct radio_isa_driver *drv; | ||
37 | struct v4l2_device v4l2_dev; | ||
38 | struct v4l2_ctrl_handler hdl; | ||
39 | struct video_device vdev; | ||
40 | struct mutex lock; | ||
41 | const struct radio_isa_ops *ops; | ||
42 | struct { /* mute/volume cluster */ | ||
43 | struct v4l2_ctrl *mute; | ||
44 | struct v4l2_ctrl *volume; | ||
45 | }; | ||
46 | /* I/O port */ | ||
47 | int io; | ||
48 | |||
49 | /* Card is in stereo audio mode */ | ||
50 | bool stereo; | ||
51 | /* Current frequency */ | ||
52 | u32 freq; | ||
53 | }; | ||
54 | |||
55 | struct radio_isa_ops { | ||
56 | /* Allocate and initialize a radio_isa_card struct */ | ||
57 | struct radio_isa_card *(*alloc)(void); | ||
58 | /* Probe whether a card is present at the given port */ | ||
59 | bool (*probe)(struct radio_isa_card *isa, int io); | ||
60 | /* Special card initialization can be done here, this is called after | ||
61 | * the standard controls are registered, but before they are setup, | ||
62 | * thus allowing drivers to add their own controls here. */ | ||
63 | int (*init)(struct radio_isa_card *isa); | ||
64 | /* Set mute and volume. */ | ||
65 | int (*s_mute_volume)(struct radio_isa_card *isa, bool mute, int volume); | ||
66 | /* Set frequency */ | ||
67 | int (*s_frequency)(struct radio_isa_card *isa, u32 freq); | ||
68 | /* Set stereo/mono audio mode */ | ||
69 | int (*s_stereo)(struct radio_isa_card *isa, bool stereo); | ||
70 | /* Get rxsubchans value for VIDIOC_G_TUNER */ | ||
71 | u32 (*g_rxsubchans)(struct radio_isa_card *isa); | ||
72 | /* Get the signal strength for VIDIOC_G_TUNER */ | ||
73 | u32 (*g_signal)(struct radio_isa_card *isa); | ||
74 | }; | ||
75 | |||
76 | /* Top level structure needed to instantiate the cards */ | ||
77 | struct radio_isa_driver { | ||
78 | struct isa_driver driver; | ||
79 | const struct radio_isa_ops *ops; | ||
80 | /* The module_param_array with the specified I/O ports */ | ||
81 | int *io_params; | ||
82 | /* The module_param_array with the radio_nr values */ | ||
83 | int *radio_nr_params; | ||
84 | /* Whether we should probe for possible cards */ | ||
85 | bool probe; | ||
86 | /* The list of possible I/O ports */ | ||
87 | const int *io_ports; | ||
88 | /* The size of that list */ | ||
89 | int num_of_io_ports; | ||
90 | /* The region size to request */ | ||
91 | unsigned region_size; | ||
92 | /* The name of the card */ | ||
93 | const char *card; | ||
94 | /* Card can capture stereo audio */ | ||
95 | bool has_stereo; | ||
96 | /* The maximum volume for the volume control. If 0, then there | ||
97 | is no volume control possible. */ | ||
98 | int max_volume; | ||
99 | }; | ||
100 | |||
101 | int radio_isa_match(struct device *pdev, unsigned int dev); | ||
102 | int radio_isa_probe(struct device *pdev, unsigned int dev); | ||
103 | int radio_isa_remove(struct device *pdev, unsigned int dev); | ||
104 | |||
105 | #endif | ||