aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/media/radio/Kconfig5
-rw-r--r--drivers/media/radio/radio-sf16fmi.c60
2 files changed, 46 insertions, 19 deletions
diff --git a/drivers/media/radio/Kconfig b/drivers/media/radio/Kconfig
index 0fe93f2b48bd..3f40f375981b 100644
--- a/drivers/media/radio/Kconfig
+++ b/drivers/media/radio/Kconfig
@@ -218,10 +218,7 @@ config RADIO_SF16FMI
218 tristate "SF16-FMI/SF16-FMP Radio" 218 tristate "SF16-FMI/SF16-FMP Radio"
219 depends on ISA && VIDEO_V4L2 219 depends on ISA && VIDEO_V4L2
220 ---help--- 220 ---help---
221 Choose Y here if you have one of these FM radio cards. If you 221 Choose Y here if you have one of these FM radio cards.
222 compile the driver into the kernel and your card is not PnP one, you
223 have to add "sf16fm=<io>" to the kernel command line (I/O address is
224 0x284 or 0x384).
225 222
226 In order to control your radio card, you will need to use programs 223 In order to control your radio card, you will need to use programs
227 that are compatible with the Video For Linux API. Information on 224 that are compatible with the Video For Linux API. Information on
diff --git a/drivers/media/radio/radio-sf16fmi.c b/drivers/media/radio/radio-sf16fmi.c
index e9ecfe11cda5..985359d18aa5 100644
--- a/drivers/media/radio/radio-sf16fmi.c
+++ b/drivers/media/radio/radio-sf16fmi.c
@@ -54,6 +54,7 @@ struct fmi
54 54
55static struct fmi fmi_card; 55static struct fmi fmi_card;
56static struct pnp_dev *dev; 56static struct pnp_dev *dev;
57bool pnp_attached;
57 58
58/* freq is in 1/16 kHz to internal number, hw precision is 50 kHz */ 59/* freq is in 1/16 kHz to internal number, hw precision is 50 kHz */
59/* It is only useful to give freq in interval of 800 (=0.05Mhz), 60/* It is only useful to give freq in interval of 800 (=0.05Mhz),
@@ -320,26 +321,54 @@ static int __init fmi_init(void)
320{ 321{
321 struct fmi *fmi = &fmi_card; 322 struct fmi *fmi = &fmi_card;
322 struct v4l2_device *v4l2_dev = &fmi->v4l2_dev; 323 struct v4l2_device *v4l2_dev = &fmi->v4l2_dev;
323 int res; 324 int res, i;
325 int probe_ports[] = { 0, 0x284, 0x384 };
326
327 if (io < 0) {
328 for (i = 0; i < ARRAY_SIZE(probe_ports); i++) {
329 io = probe_ports[i];
330 if (io == 0) {
331 io = isapnp_fmi_probe();
332 if (io < 0)
333 continue;
334 pnp_attached = 1;
335 }
336 if (!request_region(io, 2, "radio-sf16fmi")) {
337 if (pnp_attached)
338 pnp_device_detach(dev);
339 io = -1;
340 continue;
341 }
342 if (pnp_attached ||
343 ((inb(io) & 0xf9) == 0xf9 && (inb(io) & 0x4) == 0))
344 break;
345 release_region(io, 2);
346 io = -1;
347 }
348 } else {
349 if (!request_region(io, 2, "radio-sf16fmi")) {
350 printk(KERN_ERR "radio-sf16fmi: port %#x already in use\n", io);
351 return -EBUSY;
352 }
353 if (inb(io) == 0xff) {
354 printk(KERN_ERR "radio-sf16fmi: card not present at %#x\n", io);
355 release_region(io, 2);
356 return -ENODEV;
357 }
358 }
359 if (io < 0) {
360 printk(KERN_ERR "radio-sf16fmi: no cards found\n");
361 return -ENODEV;
362 }
324 363
325 if (io < 0)
326 io = isapnp_fmi_probe();
327 strlcpy(v4l2_dev->name, "sf16fmi", sizeof(v4l2_dev->name)); 364 strlcpy(v4l2_dev->name, "sf16fmi", sizeof(v4l2_dev->name));
328 fmi->io = io; 365 fmi->io = io;
329 if (fmi->io < 0) {
330 v4l2_err(v4l2_dev, "No PnP card found.\n");
331 return fmi->io;
332 }
333 if (!request_region(io, 2, "radio-sf16fmi")) {
334 v4l2_err(v4l2_dev, "port 0x%x already in use\n", fmi->io);
335 pnp_device_detach(dev);
336 return -EBUSY;
337 }
338 366
339 res = v4l2_device_register(NULL, v4l2_dev); 367 res = v4l2_device_register(NULL, v4l2_dev);
340 if (res < 0) { 368 if (res < 0) {
341 release_region(fmi->io, 2); 369 release_region(fmi->io, 2);
342 pnp_device_detach(dev); 370 if (pnp_attached)
371 pnp_device_detach(dev);
343 v4l2_err(v4l2_dev, "Could not register v4l2_device\n"); 372 v4l2_err(v4l2_dev, "Could not register v4l2_device\n");
344 return res; 373 return res;
345 } 374 }
@@ -356,7 +385,8 @@ static int __init fmi_init(void)
356 if (video_register_device(&fmi->vdev, VFL_TYPE_RADIO, radio_nr) < 0) { 385 if (video_register_device(&fmi->vdev, VFL_TYPE_RADIO, radio_nr) < 0) {
357 v4l2_device_unregister(v4l2_dev); 386 v4l2_device_unregister(v4l2_dev);
358 release_region(fmi->io, 2); 387 release_region(fmi->io, 2);
359 pnp_device_detach(dev); 388 if (pnp_attached)
389 pnp_device_detach(dev);
360 return -EINVAL; 390 return -EINVAL;
361 } 391 }
362 392
@@ -373,7 +403,7 @@ static void __exit fmi_exit(void)
373 video_unregister_device(&fmi->vdev); 403 video_unregister_device(&fmi->vdev);
374 v4l2_device_unregister(&fmi->v4l2_dev); 404 v4l2_device_unregister(&fmi->v4l2_dev);
375 release_region(fmi->io, 2); 405 release_region(fmi->io, 2);
376 if (dev) 406 if (dev && pnp_attached)
377 pnp_device_detach(dev); 407 pnp_device_detach(dev);
378} 408}
379 409