radio-sf16fmi.c (4b8303747474033d6d73828607eafab77c620d96) radio-sf16fmi.c (67cabf503cd0ad7473cf1856f9c9bb6320098be6)
1/* SF16-FMI and SF16-FMP radio driver for Linux radio support
2 * heavily based on rtrack driver...
3 * (c) 1997 M. Kirkwood
4 * (c) 1998 Petr Vandrovec, vandrove@vc.cvut.cz
5 *
6 * Fitted to new interface by Alan Cox <alan@lxorguk.ukuu.org.uk>
7 * Made working and cleaned up functions <mikael.hedin@irf.se>
8 * Support for ISAPnP by Ladislav Michl <ladis@psi.cz>

--- 40 unchanged lines hidden (view full) ---

49 int io;
50 bool mute;
51 unsigned long curfreq; /* freq in kHz */
52 struct mutex lock;
53};
54
55static struct fmi fmi_card;
56static struct pnp_dev *dev;
1/* SF16-FMI and SF16-FMP radio driver for Linux radio support
2 * heavily based on rtrack driver...
3 * (c) 1997 M. Kirkwood
4 * (c) 1998 Petr Vandrovec, vandrove@vc.cvut.cz
5 *
6 * Fitted to new interface by Alan Cox <alan@lxorguk.ukuu.org.uk>
7 * Made working and cleaned up functions <mikael.hedin@irf.se>
8 * Support for ISAPnP by Ladislav Michl <ladis@psi.cz>

--- 40 unchanged lines hidden (view full) ---

49 int io;
50 bool mute;
51 unsigned long curfreq; /* freq in kHz */
52 struct mutex lock;
53};
54
55static struct fmi fmi_card;
56static struct pnp_dev *dev;
57bool pnp_attached;
57
58/* 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 * other bits will be truncated, e.g 92.7400016 -> 92.7, but
61 * 92.7400017 -> 92.75
62 */
63#define RSF16_ENCODE(x) ((x) / 800 + 214)
64#define RSF16_MINFREQ (87 * 16000)

--- 250 unchanged lines hidden (view full) ---

315
316 return i;
317}
318
319static int __init fmi_init(void)
320{
321 struct fmi *fmi = &fmi_card;
322 struct v4l2_device *v4l2_dev = &fmi->v4l2_dev;
58
59/* freq is in 1/16 kHz to internal number, hw precision is 50 kHz */
60/* It is only useful to give freq in interval of 800 (=0.05Mhz),
61 * other bits will be truncated, e.g 92.7400016 -> 92.7, but
62 * 92.7400017 -> 92.75
63 */
64#define RSF16_ENCODE(x) ((x) / 800 + 214)
65#define RSF16_MINFREQ (87 * 16000)

--- 250 unchanged lines hidden (view full) ---

316
317 return i;
318}
319
320static int __init fmi_init(void)
321{
322 struct fmi *fmi = &fmi_card;
323 struct v4l2_device *v4l2_dev = &fmi->v4l2_dev;
323 int res;
324 int res, i;
325 int probe_ports[] = { 0, 0x284, 0x384 };
324
326
325 if (io < 0)
326 io = isapnp_fmi_probe();
327 strlcpy(v4l2_dev->name, "sf16fmi", sizeof(v4l2_dev->name));
328 fmi->io = io;
329 if (fmi->io < 0) {
330 v4l2_err(v4l2_dev, "No PnP card found.\n");
331 return fmi->io;
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 }
332 }
358 }
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;
359 if (io < 0) {
360 printk(KERN_ERR "radio-sf16fmi: no cards found\n");
361 return -ENODEV;
337 }
338
362 }
363
364 strlcpy(v4l2_dev->name, "sf16fmi", sizeof(v4l2_dev->name));
365 fmi->io = io;
366
339 res = v4l2_device_register(NULL, v4l2_dev);
340 if (res < 0) {
341 release_region(fmi->io, 2);
367 res = v4l2_device_register(NULL, v4l2_dev);
368 if (res < 0) {
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");
344 return res;
345 }
346
347 strlcpy(fmi->vdev.name, v4l2_dev->name, sizeof(fmi->vdev.name));
348 fmi->vdev.v4l2_dev = v4l2_dev;
349 fmi->vdev.fops = &fmi_fops;
350 fmi->vdev.ioctl_ops = &fmi_ioctl_ops;
351 fmi->vdev.release = video_device_release_empty;
352 video_set_drvdata(&fmi->vdev, fmi);
353
354 mutex_init(&fmi->lock);
355
356 if (video_register_device(&fmi->vdev, VFL_TYPE_RADIO, radio_nr) < 0) {
357 v4l2_device_unregister(v4l2_dev);
358 release_region(fmi->io, 2);
372 v4l2_err(v4l2_dev, "Could not register v4l2_device\n");
373 return res;
374 }
375
376 strlcpy(fmi->vdev.name, v4l2_dev->name, sizeof(fmi->vdev.name));
377 fmi->vdev.v4l2_dev = v4l2_dev;
378 fmi->vdev.fops = &fmi_fops;
379 fmi->vdev.ioctl_ops = &fmi_ioctl_ops;
380 fmi->vdev.release = video_device_release_empty;
381 video_set_drvdata(&fmi->vdev, fmi);
382
383 mutex_init(&fmi->lock);
384
385 if (video_register_device(&fmi->vdev, VFL_TYPE_RADIO, radio_nr) < 0) {
386 v4l2_device_unregister(v4l2_dev);
387 release_region(fmi->io, 2);
359 pnp_device_detach(dev);
388 if (pnp_attached)
389 pnp_device_detach(dev);
360 return -EINVAL;
361 }
362
363 v4l2_info(v4l2_dev, "card driver at 0x%x\n", fmi->io);
364 /* mute card - prevents noisy bootups */
365 fmi_mute(fmi);
366 return 0;
367}
368
369static void __exit fmi_exit(void)
370{
371 struct fmi *fmi = &fmi_card;
372
373 video_unregister_device(&fmi->vdev);
374 v4l2_device_unregister(&fmi->v4l2_dev);
375 release_region(fmi->io, 2);
390 return -EINVAL;
391 }
392
393 v4l2_info(v4l2_dev, "card driver at 0x%x\n", fmi->io);
394 /* mute card - prevents noisy bootups */
395 fmi_mute(fmi);
396 return 0;
397}
398
399static void __exit fmi_exit(void)
400{
401 struct fmi *fmi = &fmi_card;
402
403 video_unregister_device(&fmi->vdev);
404 v4l2_device_unregister(&fmi->v4l2_dev);
405 release_region(fmi->io, 2);
376 if (dev)
406 if (dev && pnp_attached)
377 pnp_device_detach(dev);
378}
379
380module_init(fmi_init);
381module_exit(fmi_exit);
407 pnp_device_detach(dev);
408}
409
410module_init(fmi_init);
411module_exit(fmi_exit);