aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorTobias Lorenz <tobias.lorenz@gmx.net>2008-01-25 02:19:48 -0500
committerMauro Carvalho Chehab <mchehab@infradead.org>2008-01-25 16:05:13 -0500
commit8bf5e5ca394441e56f68300dc4e7b26b79ddfe0b (patch)
treef3485964f862781caadf646bebada258116d2d86
parented086314f4e41eb90a9107c7fb2737230686f668 (diff)
V4L/DVB (7061): radio-si470x: Some cleanups
- code reordered to avoid function prototypes - switch/case defaults are now more user-friendly - unified comment style - applied all checkpatch.pl v1.12 suggestions except the warning about the too long lines with bit comments - renamed FMRADIO to RADIO to cut line length (checkpatch.pl) Signed-off-by: Tobias Lorenz <tobias.lorenz@gmx.net> Signed-off-by: Mauro Carvalho Chehab <mchehab@infradead.org>
-rw-r--r--drivers/media/radio/radio-si470x.c843
1 files changed, 407 insertions, 436 deletions
diff --git a/drivers/media/radio/radio-si470x.c b/drivers/media/radio/radio-si470x.c
index ccb167a1acdc..d54fe6405351 100644
--- a/drivers/media/radio/radio-si470x.c
+++ b/drivers/media/radio/radio-si470x.c
@@ -5,7 +5,7 @@
5 * - Silicon Labs USB FM Radio Reference Design 5 * - Silicon Labs USB FM Radio Reference Design
6 * - ADS/Tech FM Radio Receiver (formerly Instant FM Music) (RDX-155-EF) 6 * - ADS/Tech FM Radio Receiver (formerly Instant FM Music) (RDX-155-EF)
7 * 7 *
8 * Copyright (c) 2007 Tobias Lorenz <tobias.lorenz@gmx.net> 8 * Copyright (c) 2008 Tobias Lorenz <tobias.lorenz@gmx.net>
9 * 9 *
10 * This program is free software; you can redistribute it and/or modify 10 * This program is free software; you can redistribute it and/or modify
11 * it under the terms of the GNU General Public License as published by 11 * it under the terms of the GNU General Public License as published by
@@ -29,7 +29,7 @@
29 * Version 1.0.0 29 * Version 1.0.0
30 * - First working version 30 * - First working version
31 * 2008-01-13 Tobias Lorenz <tobias.lorenz@gmx.net> 31 * 2008-01-13 Tobias Lorenz <tobias.lorenz@gmx.net>
32 * Version 1.0.1 32 * Version 1.0.1
33 * - Improved error handling, every function now returns errno 33 * - Improved error handling, every function now returns errno
34 * - Improved multi user access (start/mute/stop) 34 * - Improved multi user access (start/mute/stop)
35 * - Channel doesn't get lost anymore after start/mute/stop 35 * - Channel doesn't get lost anymore after start/mute/stop
@@ -47,6 +47,14 @@
47 * - check for firmware version 15 47 * - check for firmware version 15
48 * - code order and prototypes still remain the same 48 * - code order and prototypes still remain the same
49 * - spacing and bottom of band codes remain the same 49 * - spacing and bottom of band codes remain the same
50 * 2008-01-16 Tobias Lorenz <tobias.lorenz@gmx.net>
51 * Version 1.0.3
52 * - code reordered to avoid function prototypes
53 * - switch/case defaults are now more user-friendly
54 * - unified comment style
55 * - applied all checkpatch.pl v1.12 suggestions
56 * except the warning about the too long lines with bit comments
57 * - renamed FMRADIO to RADIO to cut line length (checkpatch.pl)
50 * 58 *
51 * ToDo: 59 * ToDo:
52 * - check USB Vendor/Product ID for ADS/Tech FM Radio Receiver 60 * - check USB Vendor/Product ID for ADS/Tech FM Radio Receiver
@@ -55,13 +63,14 @@
55 * - add firmware download/update support 63 * - add firmware download/update support
56 * - add possibility to switch off RDS 64 * - add possibility to switch off RDS
57 * - RDS support: interrupt mode, instead of polling 65 * - RDS support: interrupt mode, instead of polling
58 * - add LED status output 66 * - add LED status output (check if that's not already done in firmware)
59 */ 67 */
60 68
69
61/* driver definitions */ 70/* driver definitions */
62#define DRIVER_AUTHOR "Tobias Lorenz <tobias.lorenz@gmx.net>" 71#define DRIVER_AUTHOR "Tobias Lorenz <tobias.lorenz@gmx.net>"
63#define DRIVER_NAME "radio-si470x" 72#define DRIVER_NAME "radio-si470x"
64#define DRIVER_VERSION KERNEL_VERSION(1, 0, 2) 73#define DRIVER_VERSION KERNEL_VERSION(1, 0, 3)
65#define DRIVER_CARD "Silicon Labs Si470x FM Radio Receiver" 74#define DRIVER_CARD "Silicon Labs Si470x FM Radio Receiver"
66#define DRIVER_DESC "USB radio driver for Si470x FM Radio Receivers" 75#define DRIVER_DESC "USB radio driver for Si470x FM Radio Receivers"
67 76
@@ -80,6 +89,21 @@
80#include <media/rds.h> 89#include <media/rds.h>
81 90
82 91
92/* USB Device ID List */
93static struct usb_device_id si470x_usb_driver_id_table[] = {
94 /* Silicon Labs USB FM Radio Reference Design */
95 { USB_DEVICE_AND_INTERFACE_INFO(0x10c4, 0x818a, USB_CLASS_HID, 0, 0) },
96 /* Terminating entry */
97 { }
98};
99MODULE_DEVICE_TABLE(usb, si470x_usb_driver_id_table);
100
101
102
103/**************************************************************************
104 * Module Parameters
105 **************************************************************************/
106
83/* Radio Nr */ 107/* Radio Nr */
84static int radio_nr = -1; 108static int radio_nr = -1;
85module_param(radio_nr, int, 0); 109module_param(radio_nr, int, 0);
@@ -145,8 +169,8 @@ MODULE_PARM_DESC(rds_poll_time, "RDS poll time (ms): *40*");
145/************************************************************************** 169/**************************************************************************
146 * Register Definitions 170 * Register Definitions
147 **************************************************************************/ 171 **************************************************************************/
148#define FMRADIO_REGISTER_SIZE 2 /* 16 register bit width */ 172#define RADIO_REGISTER_SIZE 2 /* 16 register bit width */
149#define FMRADIO_REGISTER_NUM 16 /* DEVICEID ... RDSD */ 173#define RADIO_REGISTER_NUM 16 /* DEVICEID ... RDSD */
150#define RDS_REGISTER_NUM 6 /* STATUSRSSI ... RDSD */ 174#define RDS_REGISTER_NUM 6 /* STATUSRSSI ... RDSD */
151 175
152#define DEVICEID 0 /* Device ID */ 176#define DEVICEID 0 /* Device ID */
@@ -236,23 +260,23 @@ MODULE_PARM_DESC(rds_poll_time, "RDS poll time (ms): *40*");
236 260
237 261
238/************************************************************************** 262/**************************************************************************
239 * USB HID reports 263 * USB HID Reports
240 **************************************************************************/ 264 **************************************************************************/
241 265
242/* Reports 1-16 give direct read/write access to the 16 Si470x registers */ 266/* Reports 1-16 give direct read/write access to the 16 Si470x registers */
243/* with the (REPORT_ID - 1) corresponding to the register address across USB */ 267/* with the (REPORT_ID - 1) corresponding to the register address across USB */
244/* endpoint 0 using GET_REPORT and SET_REPORT */ 268/* endpoint 0 using GET_REPORT and SET_REPORT */
245#define REGISTER_REPORT_SIZE (FMRADIO_REGISTER_SIZE + 1) 269#define REGISTER_REPORT_SIZE (RADIO_REGISTER_SIZE + 1)
246#define REGISTER_REPORT(reg) ((reg) + 1) 270#define REGISTER_REPORT(reg) ((reg) + 1)
247 271
248/* Report 17 gives direct read/write access to the entire Si470x register */ 272/* Report 17 gives direct read/write access to the entire Si470x register */
249/* map across endpoint 0 using GET_REPORT and SET_REPORT */ 273/* map across endpoint 0 using GET_REPORT and SET_REPORT */
250#define ENTIRE_REPORT_SIZE (FMRADIO_REGISTER_NUM * FMRADIO_REGISTER_SIZE + 1) 274#define ENTIRE_REPORT_SIZE (RADIO_REGISTER_NUM * RADIO_REGISTER_SIZE + 1)
251#define ENTIRE_REPORT 17 275#define ENTIRE_REPORT 17
252 276
253/* Report 18 is used to send the lowest 6 Si470x registers up the HID */ 277/* Report 18 is used to send the lowest 6 Si470x registers up the HID */
254/* interrupt endpoint 1 to Windows every 20 milliseconds for status */ 278/* interrupt endpoint 1 to Windows every 20 milliseconds for status */
255#define RDS_REPORT_SIZE (RDS_REGISTER_NUM * FMRADIO_REGISTER_SIZE + 1) 279#define RDS_REPORT_SIZE (RDS_REGISTER_NUM * RADIO_REGISTER_SIZE + 1)
256#define RDS_REPORT 18 280#define RDS_REPORT 18
257 281
258/* Report 19: LED state */ 282/* Report 19: LED state */
@@ -281,12 +305,12 @@ MODULE_PARM_DESC(rds_poll_time, "RDS poll time (ms): *40*");
281 305
282 306
283/************************************************************************** 307/**************************************************************************
284 * software/hardware versions 308 * Software/Hardware Versions
285 **************************************************************************/ 309 **************************************************************************/
286#define FMRADIO_SW_VERSION_NOT_BOOTLOADABLE 6 310#define RADIO_SW_VERSION_NOT_BOOTLOADABLE 6
287#define FMRADIO_SW_VERSION 7 311#define RADIO_SW_VERSION 7
288#define FMRADIO_SW_VERSION_CURRENT 15 312#define RADIO_SW_VERSION_CURRENT 15
289#define FMRADIO_HW_VERSION 1 313#define RADIO_HW_VERSION 1
290 314
291#define SCRATCH_PAGE_SW_VERSION 1 315#define SCRATCH_PAGE_SW_VERSION 1
292#define SCRATCH_PAGE_HW_VERSION 2 316#define SCRATCH_PAGE_HW_VERSION 2
@@ -294,7 +318,7 @@ MODULE_PARM_DESC(rds_poll_time, "RDS poll time (ms): *40*");
294 318
295 319
296/************************************************************************** 320/**************************************************************************
297 * LED State definitions 321 * LED State Definitions
298 **************************************************************************/ 322 **************************************************************************/
299#define LED_COMMAND 0x35 323#define LED_COMMAND 0x35
300 324
@@ -310,7 +334,7 @@ MODULE_PARM_DESC(rds_poll_time, "RDS poll time (ms): *40*");
310 334
311 335
312/************************************************************************** 336/**************************************************************************
313 * Stream State definitions 337 * Stream State Definitions
314 **************************************************************************/ 338 **************************************************************************/
315#define STREAM_COMMAND 0x36 339#define STREAM_COMMAND 0x36
316#define STREAM_VIDPID 0x00 340#define STREAM_VIDPID 0x00
@@ -319,16 +343,16 @@ MODULE_PARM_DESC(rds_poll_time, "RDS poll time (ms): *40*");
319 343
320 344
321/************************************************************************** 345/**************************************************************************
322 * bootloader / flash commands 346 * Bootloader / Flash Commands
323 **************************************************************************/ 347 **************************************************************************/
324 348
325/* Unique ID sent to bootloader and required to put into a bootload state */ 349/* unique id sent to bootloader and required to put into a bootload state */
326#define UNIQUE_BL_ID 0x34 350#define UNIQUE_BL_ID 0x34
327 351
328/* Mask for the flash data */ 352/* mask for the flash data */
329#define FLASH_DATA_MASK 0x55 353#define FLASH_DATA_MASK 0x55
330 354
331/* Bootloader commands */ 355/* bootloader commands */
332#define GET_SW_VERSION_COMMAND 0x00 356#define GET_SW_VERSION_COMMAND 0x00
333#define SET_PAGE_COMMAND 0x01 357#define SET_PAGE_COMMAND 0x01
334#define ERASE_PAGE_COMMAND 0x02 358#define ERASE_PAGE_COMMAND 0x02
@@ -339,12 +363,12 @@ MODULE_PARM_DESC(rds_poll_time, "RDS poll time (ms): *40*");
339#define GET_HW_VERSION_COMMAND 0x07 363#define GET_HW_VERSION_COMMAND 0x07
340#define BLANK 0xff 364#define BLANK 0xff
341 365
342/* Bootloader command responses */ 366/* bootloader command responses */
343#define COMMAND_OK 0x01 367#define COMMAND_OK 0x01
344#define COMMAND_FAILED 0x02 368#define COMMAND_FAILED 0x02
345#define COMMAND_PENDING 0x03 369#define COMMAND_PENDING 0x03
346 370
347/* Buffer sizes */ 371/* buffer sizes */
348#define COMMAND_BUFFER_SIZE 4 372#define COMMAND_BUFFER_SIZE 4
349#define RESPONSE_BUFFER_SIZE 2 373#define RESPONSE_BUFFER_SIZE 2
350#define FLASH_BUFFER_SIZE 64 374#define FLASH_BUFFER_SIZE 64
@@ -353,10 +377,12 @@ MODULE_PARM_DESC(rds_poll_time, "RDS poll time (ms): *40*");
353 377
354 378
355/************************************************************************** 379/**************************************************************************
356 * Driver private definitions 380 * General Driver Definitions
357 **************************************************************************/ 381 **************************************************************************/
358 382
359/* private data */ 383/*
384 * si470x_device - private data
385 */
360struct si470x_device { 386struct si470x_device {
361 /* reference to USB and video device */ 387 /* reference to USB and video device */
362 struct usb_device *usbdev; 388 struct usb_device *usbdev;
@@ -369,12 +395,12 @@ struct si470x_device {
369 unsigned char buf[64]; 395 unsigned char buf[64];
370 396
371 /* Silabs internal registers (0..15) */ 397 /* Silabs internal registers (0..15) */
372 unsigned short registers[FMRADIO_REGISTER_NUM]; 398 unsigned short registers[RADIO_REGISTER_NUM];
373 399
374 /* RDS receive buffer */ 400 /* RDS receive buffer */
375 struct work_struct work; 401 struct work_struct work;
376 struct timer_list timer; 402 struct timer_list timer;
377 spinlock_t lock; 403 spinlock_t lock; /* buffer locking */
378 unsigned char *buffer; 404 unsigned char *buffer;
379 unsigned int buf_size; 405 unsigned int buf_size;
380 unsigned int rd_index; 406 unsigned int rd_index;
@@ -385,177 +411,20 @@ struct si470x_device {
385 int data_available_for_read; 411 int data_available_for_read;
386}; 412};
387 413
388/* register acccess functions */
389static int si470x_get_report(struct si470x_device *radio, int size);
390static int si470x_set_report(struct si470x_device *radio, int size);
391static int si470x_get_register(struct si470x_device *radio, int regnr);
392static int si470x_set_register(struct si470x_device *radio, int regnr);
393static int si470x_get_all_registers(struct si470x_device *radio);
394static int si470x_get_rds_registers(struct si470x_device *radio);
395
396/* high-level functions */
397static int si470x_start(struct si470x_device *radio);
398static int si470x_stop(struct si470x_device *radio);
399static int si470x_set_chan(struct si470x_device *radio, int chan);
400static int si470x_get_freq(struct si470x_device *radio);
401static int si470x_set_freq(struct si470x_device *radio, int freq);
402
403/* RDS functions */
404static void si470x_rds(struct si470x_device *radio);
405static void si470x_timer(unsigned long data);
406static void si470x_work(struct work_struct *work);
407
408
409
410/**************************************************************************
411 * USB interface definitions
412 **************************************************************************/
413
414/* USB device ID list (Vendor, Product, Class, SubClass, Protocol) */
415static struct usb_device_id si470x_usb_driver_id_table[] = {
416 /* Silicon Labs USB FM Radio Reference Design */
417 { USB_DEVICE_AND_INTERFACE_INFO(0x10c4, 0x818a, USB_CLASS_HID, 0, 0) },
418 /* Terminating entry */
419 { }
420};
421MODULE_DEVICE_TABLE (usb, si470x_usb_driver_id_table);
422
423/* USB driver functions */
424static int si470x_usb_driver_probe(struct usb_interface *intf,
425 const struct usb_device_id *id);
426static void si470x_usb_driver_disconnect(struct usb_interface *intf);
427
428/* USB driver interface */
429static struct usb_driver si470x_usb_driver = {
430 .name = DRIVER_NAME,
431 .probe = si470x_usb_driver_probe,
432 .disconnect = si470x_usb_driver_disconnect,
433 .id_table = si470x_usb_driver_id_table,
434};
435
436
437 414
438/************************************************************************** 415/*
439 * Video4Linux interface definitions 416 * The frequency is set in units of 62.5 Hz when using V4L2_TUNER_CAP_LOW,
440 **************************************************************************/ 417 * 62.5 kHz otherwise.
441 418 * The tuner is able to have a channel spacing of 50, 100 or 200 kHz.
442/* The frequency is set in units of 62.5 Hz when using V4L2_TUNER_CAP_LOW, */ 419 * tuner->capability is therefore set to V4L2_TUNER_CAP_LOW
443/* 62.5 kHz otherwise. */ 420 * The FREQ_MUL is then: 1 MHz / 62.5 Hz = 16000
444/* The tuner is able to have a channel spacing of 50, 100 or 200 kHz. */ 421 */
445/* tuner->capability is therefore set to V4L2_TUNER_CAP_LOW */
446/* The FREQ_MUL is then: 1 MHz / 62.5 Hz = 16000 */
447#define FREQ_MUL (1000000 / 62.5) 422#define FREQ_MUL (1000000 / 62.5)
448 423
449/* File operations functions */
450static ssize_t si470x_fops_read(struct file *file, char __user *buf,
451 size_t count, loff_t *ppos);
452static unsigned int si470x_fops_poll(struct file *file,
453 struct poll_table_struct *pts);
454static int si470x_fops_open(struct inode *inode, struct file *file);
455static int si470x_fops_release(struct inode *inode, struct file *file);
456
457/* File operations interface */
458static const struct file_operations si470x_fops = {
459 .owner = THIS_MODULE,
460 .llseek = no_llseek,
461 .read = si470x_fops_read,
462 .poll = si470x_fops_poll,
463 .ioctl = video_ioctl2,
464 .compat_ioctl = v4l_compat_ioctl32,
465 .open = si470x_fops_open,
466 .release = si470x_fops_release,
467};
468
469/* Video device functions */
470static int si470x_vidioc_querycap(struct file *file, void *priv,
471 struct v4l2_capability *capability);
472static int si470x_vidioc_g_input(struct file *file, void *priv,
473 unsigned int *i);
474static int si470x_vidioc_s_input(struct file *file, void *priv,
475 unsigned int i);
476static int si470x_vidioc_queryctrl(struct file *file, void *priv,
477 struct v4l2_queryctrl *qc);
478static int si470x_vidioc_g_ctrl(struct file *file, void *priv,
479 struct v4l2_control *ctrl);
480static int si470x_vidioc_s_ctrl(struct file *file, void *priv,
481 struct v4l2_control *ctrl);
482static int si470x_vidioc_g_audio(struct file *file, void *priv,
483 struct v4l2_audio *audio);
484static int si470x_vidioc_s_audio(struct file *file, void *priv,
485 struct v4l2_audio *audio);
486static int si470x_vidioc_g_tuner(struct file *file, void *priv,
487 struct v4l2_tuner *tuner);
488static int si470x_vidioc_s_tuner(struct file *file, void *priv,
489 struct v4l2_tuner *tuner);
490static int si470x_vidioc_g_frequency(struct file *file, void *priv,
491 struct v4l2_frequency *freq);
492static int si470x_vidioc_s_frequency(struct file *file, void *priv,
493 struct v4l2_frequency *freq);
494
495/* Video device interface */
496static struct video_device si470x_viddev_template = {
497 .fops = &si470x_fops,
498 .name = DRIVER_NAME,
499 .type = VID_TYPE_TUNER,
500 .release = video_device_release,
501 .vidioc_querycap = si470x_vidioc_querycap,
502 .vidioc_g_input = si470x_vidioc_g_input,
503 .vidioc_s_input = si470x_vidioc_s_input,
504 .vidioc_queryctrl = si470x_vidioc_queryctrl,
505 .vidioc_g_ctrl = si470x_vidioc_g_ctrl,
506 .vidioc_s_ctrl = si470x_vidioc_s_ctrl,
507 .vidioc_g_audio = si470x_vidioc_g_audio,
508 .vidioc_s_audio = si470x_vidioc_s_audio,
509 .vidioc_g_tuner = si470x_vidioc_g_tuner,
510 .vidioc_s_tuner = si470x_vidioc_s_tuner,
511 .vidioc_g_frequency = si470x_vidioc_g_frequency,
512 .vidioc_s_frequency = si470x_vidioc_s_frequency,
513 .owner = THIS_MODULE,
514};
515
516/* Query control */
517static struct v4l2_queryctrl radio_queryctrl[] = {
518/* HINT: the disabled controls are only here to satify kradio and such apps */
519 {
520 .id = V4L2_CID_AUDIO_VOLUME,
521 .type = V4L2_CTRL_TYPE_INTEGER,
522 .name = "Volume",
523 .minimum = 0,
524 .maximum = 15,
525 .step = 1,
526 .default_value = 15,
527 },
528 {
529 .id = V4L2_CID_AUDIO_BALANCE,
530 .flags = V4L2_CTRL_FLAG_DISABLED,
531 },
532 {
533 .id = V4L2_CID_AUDIO_BASS,
534 .flags = V4L2_CTRL_FLAG_DISABLED,
535 },
536 {
537 .id = V4L2_CID_AUDIO_TREBLE,
538 .flags = V4L2_CTRL_FLAG_DISABLED,
539 },
540 {
541 .id = V4L2_CID_AUDIO_MUTE,
542 .type = V4L2_CTRL_TYPE_BOOLEAN,
543 .name = "Mute",
544 .minimum = 0,
545 .maximum = 1,
546 .step = 1,
547 .default_value = 1,
548 },
549 {
550 .id = V4L2_CID_AUDIO_LOUDNESS,
551 .flags = V4L2_CTRL_FLAG_DISABLED,
552 },
553};
554
555 424
556 425
557/************************************************************************** 426/**************************************************************************
558 * Driver private functions 427 * General Driver Functions
559 **************************************************************************/ 428 **************************************************************************/
560 429
561/* 430/*
@@ -633,10 +502,10 @@ static int si470x_get_all_registers(struct si470x_device *radio)
633 retval = si470x_get_report(radio, ENTIRE_REPORT_SIZE); 502 retval = si470x_get_report(radio, ENTIRE_REPORT_SIZE);
634 503
635 if (retval >= 0) 504 if (retval >= 0)
636 for (regnr = 0; regnr < FMRADIO_REGISTER_NUM; regnr++) 505 for (regnr = 0; regnr < RADIO_REGISTER_NUM; regnr++)
637 radio->registers[regnr] = 506 radio->registers[regnr] =
638 (radio->buf[regnr * FMRADIO_REGISTER_SIZE + 1] << 8) | 507 (radio->buf[regnr * RADIO_REGISTER_SIZE + 1] << 8) |
639 radio->buf[regnr * FMRADIO_REGISTER_SIZE + 2]; 508 radio->buf[regnr * RADIO_REGISTER_SIZE + 2];
640 509
641 return (retval < 0) ? -EINVAL : 0; 510 return (retval < 0) ? -EINVAL : 0;
642} 511}
@@ -657,65 +526,13 @@ static int si470x_get_rds_registers(struct si470x_device *radio)
657 usb_rcvctrlpipe(radio->usbdev, 1), 526 usb_rcvctrlpipe(radio->usbdev, 1),
658 radio->buf, RDS_REPORT_SIZE, &size, usb_timeout); 527 radio->buf, RDS_REPORT_SIZE, &size, usb_timeout);
659 528
660 if (retval >= 0) { 529 if (retval >= 0)
661 for (regnr = 0; regnr < RDS_REGISTER_NUM; regnr++) { 530 for (regnr = 0; regnr < RDS_REGISTER_NUM; regnr++)
662 radio->registers[STATUSRSSI + regnr] = 531 radio->registers[STATUSRSSI + regnr] =
663 (radio->buf[regnr * FMRADIO_REGISTER_SIZE + 1] << 8) | 532 (radio->buf[regnr * RADIO_REGISTER_SIZE + 1] << 8) |
664 radio->buf[regnr * FMRADIO_REGISTER_SIZE + 2]; 533 radio->buf[regnr * RADIO_REGISTER_SIZE + 2];
665 }
666 }
667
668 return (retval < 0) ? - EINVAL : 0;
669}
670
671 534
672/* 535 return (retval < 0) ? -EINVAL : 0;
673 * si470x_start - switch on radio
674 */
675static int si470x_start(struct si470x_device *radio)
676{
677 int retval;
678
679 /* powercfg */
680 radio->registers[POWERCFG] =
681 POWERCFG_DMUTE | POWERCFG_ENABLE | POWERCFG_RDSM;
682 retval = si470x_set_register(radio, POWERCFG);
683 if (retval < 0)
684 return retval;
685
686 /* sysconfig 1 */
687 radio->registers[SYSCONFIG1] =
688 SYSCONFIG1_DE | SYSCONFIG1_RDS;
689 retval = si470x_set_register(radio, SYSCONFIG1);
690 if (retval < 0)
691 return retval;
692
693 /* sysconfig 2 */
694 radio->registers[SYSCONFIG2] =
695 (0x3f << 8) | /* SEEKTH */
696 (band << 6) | /* BAND */
697 (space << 4) | /* SPACE */
698 15; /* VOLUME (max) */
699 retval = si470x_set_register(radio, SYSCONFIG2);
700 if (retval < 0)
701 return retval;
702
703 /* reset last channel */
704 return si470x_set_chan(radio,
705 radio->registers[CHANNEL] & CHANNEL_CHAN);
706}
707
708
709/*
710 * si470x_stop - switch off radio
711 */
712static int si470x_stop(struct si470x_device *radio)
713{
714 /* powercfg */
715 radio->registers[POWERCFG] &= ~POWERCFG_DMUTE;
716 /* POWERCFG_ENABLE has to automatically go low */
717 radio->registers[POWERCFG] |= POWERCFG_ENABLE | POWERCFG_DISABLE;
718 return si470x_set_register(radio, POWERCFG);
719} 536}
720 537
721 538
@@ -761,22 +578,22 @@ static int si470x_get_freq(struct si470x_device *radio)
761 578
762 /* Spacing (kHz) */ 579 /* Spacing (kHz) */
763 switch (space) { 580 switch (space) {
764 /* 0: 200 kHz (USA, Australia) */ 581 /* 0: 200 kHz (USA, Australia) */
765 default: spacing = 0.200 * FREQ_MUL; break; 582 case 0 : spacing = 0.200 * FREQ_MUL; break;
766 /* 1: 100 kHz (Europe, Japan) */ 583 /* 1: 100 kHz (Europe, Japan) */
767 case 1 : spacing = 0.100 * FREQ_MUL; break; 584 case 1 : spacing = 0.100 * FREQ_MUL; break;
768 /* 2: 50 kHz */ 585 /* 2: 50 kHz */
769 case 2 : spacing = 0.050 * FREQ_MUL; break; 586 default: spacing = 0.050 * FREQ_MUL; break;
770 }; 587 };
771 588
772 /* Bottom of Band (MHz) */ 589 /* Bottom of Band (MHz) */
773 switch (band) { 590 switch (band) {
774 /* 0: 87.5 - 108 MHz (USA, Europe) */ 591 /* 0: 87.5 - 108 MHz (USA, Europe) */
775 default: band_bottom = 87.5 * FREQ_MUL; break; 592 case 0 : band_bottom = 87.5 * FREQ_MUL; break;
776 /* 1: 76 - 108 MHz (Japan wide band) */ 593 /* 1: 76 - 108 MHz (Japan wide band) */
777 case 1 : band_bottom = 76 * FREQ_MUL; break; 594 default: band_bottom = 76 * FREQ_MUL; break;
778 /* 2: 76 - 90 MHz (Japan) */ 595 /* 2: 76 - 90 MHz (Japan) */
779 case 2 : band_bottom = 76 * FREQ_MUL; break; 596 case 2 : band_bottom = 76 * FREQ_MUL; break;
780 }; 597 };
781 598
782 /* read channel */ 599 /* read channel */
@@ -801,22 +618,22 @@ static int si470x_set_freq(struct si470x_device *radio, int freq)
801 618
802 /* Spacing (kHz) */ 619 /* Spacing (kHz) */
803 switch (space) { 620 switch (space) {
804 /* 0: 200 kHz (USA, Australia) */ 621 /* 0: 200 kHz (USA, Australia) */
805 default: spacing = 0.200 * FREQ_MUL; break; 622 case 0 : spacing = 0.200 * FREQ_MUL; break;
806 /* 1: 100 kHz (Europe, Japan) */ 623 /* 1: 100 kHz (Europe, Japan) */
807 case 1 : spacing = 0.100 * FREQ_MUL; break; 624 case 1 : spacing = 0.100 * FREQ_MUL; break;
808 /* 2: 50 kHz */ 625 /* 2: 50 kHz */
809 case 2 : spacing = 0.050 * FREQ_MUL; break; 626 default: spacing = 0.050 * FREQ_MUL; break;
810 }; 627 };
811 628
812 /* Bottom of Band (MHz) */ 629 /* Bottom of Band (MHz) */
813 switch (band) { 630 switch (band) {
814 /* 0: 87.5 - 108 MHz (USA, Europe) */ 631 /* 0: 87.5 - 108 MHz (USA, Europe) */
815 default: band_bottom = 87.5 * FREQ_MUL; break; 632 case 0 : band_bottom = 87.5 * FREQ_MUL; break;
816 /* 1: 76 - 108 MHz (Japan wide band) */ 633 /* 1: 76 - 108 MHz (Japan wide band) */
817 case 1 : band_bottom = 76 * FREQ_MUL; break; 634 default: band_bottom = 76 * FREQ_MUL; break;
818 /* 2: 76 - 90 MHz (Japan) */ 635 /* 2: 76 - 90 MHz (Japan) */
819 case 2 : band_bottom = 76 * FREQ_MUL; break; 636 case 2 : band_bottom = 76 * FREQ_MUL; break;
820 }; 637 };
821 638
822 /* Chan = [ Freq (Mhz) - Bottom of Band (MHz) ] / Spacing (kHz) */ 639 /* Chan = [ Freq (Mhz) - Bottom of Band (MHz) ] / Spacing (kHz) */
@@ -826,6 +643,60 @@ static int si470x_set_freq(struct si470x_device *radio, int freq)
826} 643}
827 644
828 645
646/*
647 * si470x_start - switch on radio
648 */
649static int si470x_start(struct si470x_device *radio)
650{
651 int retval;
652
653 /* powercfg */
654 radio->registers[POWERCFG] =
655 POWERCFG_DMUTE | POWERCFG_ENABLE | POWERCFG_RDSM;
656 retval = si470x_set_register(radio, POWERCFG);
657 if (retval < 0)
658 return retval;
659
660 /* sysconfig 1 */
661 radio->registers[SYSCONFIG1] =
662 SYSCONFIG1_DE | SYSCONFIG1_RDS;
663 retval = si470x_set_register(radio, SYSCONFIG1);
664 if (retval < 0)
665 return retval;
666
667 /* sysconfig 2 */
668 radio->registers[SYSCONFIG2] =
669 (0x3f << 8) | /* SEEKTH */
670 (band << 6) | /* BAND */
671 (space << 4) | /* SPACE */
672 15; /* VOLUME (max) */
673 retval = si470x_set_register(radio, SYSCONFIG2);
674 if (retval < 0)
675 return retval;
676
677 /* reset last channel */
678 return si470x_set_chan(radio,
679 radio->registers[CHANNEL] & CHANNEL_CHAN);
680}
681
682
683/*
684 * si470x_stop - switch off radio
685 */
686static int si470x_stop(struct si470x_device *radio)
687{
688 /* powercfg */
689 radio->registers[POWERCFG] &= ~POWERCFG_DMUTE;
690 /* POWERCFG_ENABLE has to automatically go low */
691 radio->registers[POWERCFG] |= POWERCFG_ENABLE | POWERCFG_DISABLE;
692 return si470x_set_register(radio, POWERCFG);
693}
694
695
696
697/**************************************************************************
698 * RDS Driver Functions
699 **************************************************************************/
829 700
830/* 701/*
831 * si470x_rds - rds processing function 702 * si470x_rds - rds processing function
@@ -854,26 +725,26 @@ static void si470x_rds(struct si470x_device *radio)
854 725
855 for (blocknum = 0; blocknum < 4; blocknum++) { 726 for (blocknum = 0; blocknum < 4; blocknum++) {
856 switch (blocknum) { 727 switch (blocknum) {
857 default: 728 default:
858 bler = (radio->registers[STATUSRSSI] & 729 bler = (radio->registers[STATUSRSSI] &
859 STATUSRSSI_BLERA) >> 9; 730 STATUSRSSI_BLERA) >> 9;
860 rds = radio->registers[RDSA]; 731 rds = radio->registers[RDSA];
861 break; 732 break;
862 case 1: 733 case 1:
863 bler = (radio->registers[READCHAN] & 734 bler = (radio->registers[READCHAN] &
864 READCHAN_BLERB) >> 14; 735 READCHAN_BLERB) >> 14;
865 rds = radio->registers[RDSB]; 736 rds = radio->registers[RDSB];
866 break; 737 break;
867 case 2: 738 case 2:
868 bler = (radio->registers[READCHAN] & 739 bler = (radio->registers[READCHAN] &
869 READCHAN_BLERC) >> 12; 740 READCHAN_BLERC) >> 12;
870 rds = radio->registers[RDSC]; 741 rds = radio->registers[RDSC];
871 break; 742 break;
872 case 3: 743 case 3:
873 bler = (radio->registers[READCHAN] & 744 bler = (radio->registers[READCHAN] &
874 READCHAN_BLERD) >> 10; 745 READCHAN_BLERD) >> 10;
875 rds = radio->registers[RDSD]; 746 rds = radio->registers[RDSD];
876 break; 747 break;
877 }; 748 };
878 749
879 /* Fill the V4L2 RDS buffer */ 750 /* Fill the V4L2 RDS buffer */
@@ -941,107 +812,7 @@ static void si470x_work(struct work_struct *work)
941 812
942 813
943/************************************************************************** 814/**************************************************************************
944 * USB interface functions 815 * File Operations Interface
945 **************************************************************************/
946
947/*
948 * si470x_usb_driver_probe - probe for the device
949 */
950static int si470x_usb_driver_probe(struct usb_interface *intf,
951 const struct usb_device_id *id)
952{
953 struct si470x_device *radio;
954
955 if (!(radio = kmalloc(sizeof(struct si470x_device), GFP_KERNEL)))
956 return -ENOMEM;
957 if (!(radio->videodev = video_device_alloc())) {
958 kfree(radio);
959 return -ENOMEM;
960 }
961 memcpy(radio->videodev, &si470x_viddev_template,
962 sizeof(si470x_viddev_template));
963 radio->users = 0;
964 radio->usbdev = interface_to_usbdev(intf);
965 video_set_drvdata(radio->videodev, radio);
966 if (video_register_device(radio->videodev, VFL_TYPE_RADIO, radio_nr)) {
967 printk(KERN_WARNING DRIVER_NAME
968 ": Could not register video device\n");
969 video_device_release(radio->videodev);
970 kfree(radio);
971 return -EIO;
972 }
973 usb_set_intfdata(intf, radio);
974
975 /* show some infos about the specific device */
976 if (si470x_get_all_registers(radio) < 0) {
977 video_device_release(radio->videodev);
978 kfree(radio);
979 return -EIO;
980 }
981 printk(KERN_INFO DRIVER_NAME ": DeviceID=0x%4.4x ChipID=0x%4.4x\n",
982 radio->registers[DEVICEID], radio->registers[CHIPID]);
983
984 /* check if firmware is current */
985 if ((radio->registers[CHIPID] & CHIPID_FIRMWARE)
986 < FMRADIO_SW_VERSION_CURRENT) {
987 printk(KERN_WARNING DRIVER_NAME
988 ": This driver is known to work with chip version %d, "
989 "but the device has firmware %d. If you have some "
990 "trouble using this driver, please report to V4L ML "
991 "at video4linux-list@redhat.com\n",
992 radio->registers[CHIPID] & CHIPID_FIRMWARE,
993 FMRADIO_SW_VERSION_CURRENT);
994 }
995
996 /* set initial frequency */
997 si470x_set_freq(radio, 87.5 * FREQ_MUL); /* available in all regions */
998
999 /* rds initialization */
1000 radio->buf_size = rds_buf * 3;
1001 if (NULL == (radio->buffer = kmalloc(radio->buf_size, GFP_KERNEL))) {
1002 video_device_release(radio->videodev);
1003 kfree(radio);
1004 return -ENOMEM;
1005 }
1006 radio->block_count = 0;
1007 radio->wr_index = 0;
1008 radio->rd_index = 0;
1009 radio->last_blocknum = 0xff;
1010 init_waitqueue_head(&radio->read_queue);
1011 radio->data_available_for_read = 0;
1012
1013 /* prepare polling via eventd */
1014 INIT_WORK(&radio->work, si470x_work);
1015 init_timer(&radio->timer);
1016 radio->timer.function = si470x_timer;
1017 radio->timer.data = (unsigned long) radio;
1018
1019 return 0;
1020}
1021
1022
1023/*
1024 * si470x_usb_driver_disconnect - disconnect the device
1025 */
1026static void si470x_usb_driver_disconnect(struct usb_interface *intf)
1027{
1028 struct si470x_device *radio = usb_get_intfdata(intf);
1029
1030 del_timer_sync(&radio->timer);
1031 flush_scheduled_work();
1032
1033 usb_set_intfdata(intf, NULL);
1034 if (radio) {
1035 video_unregister_device(radio->videodev);
1036 kfree(radio->buffer);
1037 kfree(radio);
1038 }
1039}
1040
1041
1042
1043/**************************************************************************
1044 * Video4Linux interface functions
1045 **************************************************************************/ 816 **************************************************************************/
1046 817
1047/* 818/*
@@ -1166,6 +937,68 @@ static int si470x_fops_release(struct inode *inode, struct file *file)
1166 937
1167 938
1168/* 939/*
940 * si470x_fops - file operations interface
941 */
942static const struct file_operations si470x_fops = {
943 .owner = THIS_MODULE,
944 .llseek = no_llseek,
945 .read = si470x_fops_read,
946 .poll = si470x_fops_poll,
947 .ioctl = video_ioctl2,
948 .compat_ioctl = v4l_compat_ioctl32,
949 .open = si470x_fops_open,
950 .release = si470x_fops_release,
951};
952
953
954
955/**************************************************************************
956 * Video4Linux Interface
957 **************************************************************************/
958
959/*
960 * si470x_v4l2_queryctrl - query control
961 */
962static struct v4l2_queryctrl si470x_v4l2_queryctrl[] = {
963/* HINT: the disabled controls are only here to satify kradio and such apps */
964 {
965 .id = V4L2_CID_AUDIO_VOLUME,
966 .type = V4L2_CTRL_TYPE_INTEGER,
967 .name = "Volume",
968 .minimum = 0,
969 .maximum = 15,
970 .step = 1,
971 .default_value = 15,
972 },
973 {
974 .id = V4L2_CID_AUDIO_BALANCE,
975 .flags = V4L2_CTRL_FLAG_DISABLED,
976 },
977 {
978 .id = V4L2_CID_AUDIO_BASS,
979 .flags = V4L2_CTRL_FLAG_DISABLED,
980 },
981 {
982 .id = V4L2_CID_AUDIO_TREBLE,
983 .flags = V4L2_CTRL_FLAG_DISABLED,
984 },
985 {
986 .id = V4L2_CID_AUDIO_MUTE,
987 .type = V4L2_CTRL_TYPE_BOOLEAN,
988 .name = "Mute",
989 .minimum = 0,
990 .maximum = 1,
991 .step = 1,
992 .default_value = 1,
993 },
994 {
995 .id = V4L2_CID_AUDIO_LOUDNESS,
996 .flags = V4L2_CTRL_FLAG_DISABLED,
997 },
998};
999
1000
1001/*
1169 * si470x_vidioc_querycap - query device capabilities 1002 * si470x_vidioc_querycap - query device capabilities
1170 */ 1003 */
1171static int si470x_vidioc_querycap(struct file *file, void *priv, 1004static int si470x_vidioc_querycap(struct file *file, void *priv,
@@ -1213,9 +1046,9 @@ static int si470x_vidioc_queryctrl(struct file *file, void *priv,
1213{ 1046{
1214 int i; 1047 int i;
1215 1048
1216 for (i = 0; i < ARRAY_SIZE(radio_queryctrl); i++) { 1049 for (i = 0; i < ARRAY_SIZE(si470x_v4l2_queryctrl); i++) {
1217 if (qc->id && qc->id == radio_queryctrl[i].id) { 1050 if (qc->id && qc->id == si470x_v4l2_queryctrl[i].id) {
1218 memcpy(qc, &(radio_queryctrl[i]), sizeof(*qc)); 1051 memcpy(qc, &(si470x_v4l2_queryctrl[i]), sizeof(*qc));
1219 return 0; 1052 return 0;
1220 } 1053 }
1221 } 1054 }
@@ -1233,14 +1066,14 @@ static int si470x_vidioc_g_ctrl(struct file *file, void *priv,
1233 struct si470x_device *radio = video_get_drvdata(video_devdata(file)); 1066 struct si470x_device *radio = video_get_drvdata(video_devdata(file));
1234 1067
1235 switch (ctrl->id) { 1068 switch (ctrl->id) {
1236 case V4L2_CID_AUDIO_VOLUME: 1069 case V4L2_CID_AUDIO_VOLUME:
1237 ctrl->value = radio->registers[SYSCONFIG2] & 1070 ctrl->value = radio->registers[SYSCONFIG2] &
1238 SYSCONFIG2_VOLUME; 1071 SYSCONFIG2_VOLUME;
1239 break; 1072 break;
1240 case V4L2_CID_AUDIO_MUTE: 1073 case V4L2_CID_AUDIO_MUTE:
1241 ctrl->value = ((radio->registers[POWERCFG] & 1074 ctrl->value = ((radio->registers[POWERCFG] &
1242 POWERCFG_DMUTE) == 0) ? 1 : 0; 1075 POWERCFG_DMUTE) == 0) ? 1 : 0;
1243 break; 1076 break;
1244 } 1077 }
1245 1078
1246 return 0; 1079 return 0;
@@ -1256,16 +1089,16 @@ static int si470x_vidioc_s_ctrl(struct file *file, void *priv,
1256 struct si470x_device *radio = video_get_drvdata(video_devdata(file)); 1089 struct si470x_device *radio = video_get_drvdata(video_devdata(file));
1257 1090
1258 switch (ctrl->id) { 1091 switch (ctrl->id) {
1259 case V4L2_CID_AUDIO_VOLUME: 1092 case V4L2_CID_AUDIO_VOLUME:
1260 radio->registers[SYSCONFIG2] &= ~SYSCONFIG2_VOLUME; 1093 radio->registers[SYSCONFIG2] &= ~SYSCONFIG2_VOLUME;
1261 radio->registers[SYSCONFIG2] |= ctrl->value; 1094 radio->registers[SYSCONFIG2] |= ctrl->value;
1262 return si470x_set_register(radio, SYSCONFIG2); 1095 return si470x_set_register(radio, SYSCONFIG2);
1263 case V4L2_CID_AUDIO_MUTE: 1096 case V4L2_CID_AUDIO_MUTE:
1264 if (ctrl->value == 1) 1097 if (ctrl->value == 1)
1265 radio->registers[POWERCFG] &= ~POWERCFG_DMUTE; 1098 radio->registers[POWERCFG] &= ~POWERCFG_DMUTE;
1266 else 1099 else
1267 radio->registers[POWERCFG] |= POWERCFG_DMUTE; 1100 radio->registers[POWERCFG] |= POWERCFG_DMUTE;
1268 return si470x_set_register(radio, POWERCFG); 1101 return si470x_set_register(radio, POWERCFG);
1269 } 1102 }
1270 1103
1271 return -EINVAL; 1104 return -EINVAL;
@@ -1320,22 +1153,22 @@ static int si470x_vidioc_g_tuner(struct file *file, void *priv,
1320 1153
1321 strcpy(tuner->name, "FM"); 1154 strcpy(tuner->name, "FM");
1322 tuner->type = V4L2_TUNER_RADIO; 1155 tuner->type = V4L2_TUNER_RADIO;
1323 switch(band) { 1156 switch (band) {
1324 /* 0: 87.5 - 108 MHz (USA, Europe, default) */ 1157 /* 0: 87.5 - 108 MHz (USA, Europe, default) */
1325 default: 1158 default:
1326 tuner->rangelow = 87.5 * FREQ_MUL; 1159 tuner->rangelow = 87.5 * FREQ_MUL;
1327 tuner->rangehigh = 108 * FREQ_MUL; 1160 tuner->rangehigh = 108 * FREQ_MUL;
1328 break; 1161 break;
1329 /* 1: 76 - 108 MHz (Japan wide band) */ 1162 /* 1: 76 - 108 MHz (Japan wide band) */
1330 case 1 : 1163 case 1 :
1331 tuner->rangelow = 76 * FREQ_MUL; 1164 tuner->rangelow = 76 * FREQ_MUL;
1332 tuner->rangehigh = 108 * FREQ_MUL; 1165 tuner->rangehigh = 108 * FREQ_MUL;
1333 break; 1166 break;
1334 /* 2: 76 - 90 MHz (Japan) */ 1167 /* 2: 76 - 90 MHz (Japan) */
1335 case 2 : 1168 case 2 :
1336 tuner->rangelow = 76 * FREQ_MUL; 1169 tuner->rangelow = 76 * FREQ_MUL;
1337 tuner->rangehigh = 90 * FREQ_MUL; 1170 tuner->rangehigh = 90 * FREQ_MUL;
1338 break; 1171 break;
1339 }; 1172 };
1340 tuner->rxsubchans = V4L2_TUNER_SUB_MONO | V4L2_TUNER_SUB_STEREO; 1173 tuner->rxsubchans = V4L2_TUNER_SUB_MONO | V4L2_TUNER_SUB_STEREO;
1341 tuner->capability = V4L2_TUNER_CAP_LOW; 1174 tuner->capability = V4L2_TUNER_CAP_LOW;
@@ -1407,9 +1240,147 @@ static int si470x_vidioc_s_frequency(struct file *file, void *priv,
1407} 1240}
1408 1241
1409 1242
1243/*
1244 * si470x_viddev_tamples - video device interface
1245 */
1246static struct video_device si470x_viddev_template = {
1247 .fops = &si470x_fops,
1248 .name = DRIVER_NAME,
1249 .type = VID_TYPE_TUNER,
1250 .release = video_device_release,
1251 .vidioc_querycap = si470x_vidioc_querycap,
1252 .vidioc_g_input = si470x_vidioc_g_input,
1253 .vidioc_s_input = si470x_vidioc_s_input,
1254 .vidioc_queryctrl = si470x_vidioc_queryctrl,
1255 .vidioc_g_ctrl = si470x_vidioc_g_ctrl,
1256 .vidioc_s_ctrl = si470x_vidioc_s_ctrl,
1257 .vidioc_g_audio = si470x_vidioc_g_audio,
1258 .vidioc_s_audio = si470x_vidioc_s_audio,
1259 .vidioc_g_tuner = si470x_vidioc_g_tuner,
1260 .vidioc_s_tuner = si470x_vidioc_s_tuner,
1261 .vidioc_g_frequency = si470x_vidioc_g_frequency,
1262 .vidioc_s_frequency = si470x_vidioc_s_frequency,
1263 .owner = THIS_MODULE,
1264};
1265
1266
1267
1268/**************************************************************************
1269 * USB Interface
1270 **************************************************************************/
1271
1272/*
1273 * si470x_usb_driver_probe - probe for the device
1274 */
1275static int si470x_usb_driver_probe(struct usb_interface *intf,
1276 const struct usb_device_id *id)
1277{
1278 struct si470x_device *radio;
1279
1280 /* memory and interface allocations */
1281 radio = kmalloc(sizeof(struct si470x_device), GFP_KERNEL);
1282 if (!radio)
1283 return -ENOMEM;
1284 radio->videodev = video_device_alloc();
1285 if (!radio->videodev) {
1286 kfree(radio);
1287 return -ENOMEM;
1288 }
1289 memcpy(radio->videodev, &si470x_viddev_template,
1290 sizeof(si470x_viddev_template));
1291 radio->users = 0;
1292 radio->usbdev = interface_to_usbdev(intf);
1293 video_set_drvdata(radio->videodev, radio);
1294 if (video_register_device(radio->videodev, VFL_TYPE_RADIO, radio_nr)) {
1295 printk(KERN_WARNING DRIVER_NAME
1296 ": Could not register video device\n");
1297 video_device_release(radio->videodev);
1298 kfree(radio);
1299 return -EIO;
1300 }
1301 usb_set_intfdata(intf, radio);
1302
1303 /* show some infos about the specific device */
1304 if (si470x_get_all_registers(radio) < 0) {
1305 video_device_release(radio->videodev);
1306 kfree(radio);
1307 return -EIO;
1308 }
1309 printk(KERN_INFO DRIVER_NAME ": DeviceID=0x%4.4x ChipID=0x%4.4x\n",
1310 radio->registers[DEVICEID], radio->registers[CHIPID]);
1311
1312 /* check if firmware is current */
1313 if ((radio->registers[CHIPID] & CHIPID_FIRMWARE)
1314 < RADIO_SW_VERSION_CURRENT)
1315 printk(KERN_WARNING DRIVER_NAME
1316 ": This driver is known to work with chip version %d, "
1317 "but the device has firmware %d. If you have some "
1318 "trouble using this driver, please report to V4L ML "
1319 "at video4linux-list@redhat.com\n",
1320 radio->registers[CHIPID] & CHIPID_FIRMWARE,
1321 RADIO_SW_VERSION_CURRENT);
1322
1323 /* set initial frequency */
1324 si470x_set_freq(radio, 87.5 * FREQ_MUL); /* available in all regions */
1325
1326 /* rds initialization */
1327 radio->buf_size = rds_buf * 3;
1328 radio->buffer = kmalloc(radio->buf_size, GFP_KERNEL);
1329 if (!radio->buffer) {
1330 video_device_release(radio->videodev);
1331 kfree(radio);
1332 return -ENOMEM;
1333 }
1334 radio->block_count = 0;
1335 radio->wr_index = 0;
1336 radio->rd_index = 0;
1337 radio->last_blocknum = 0xff;
1338 init_waitqueue_head(&radio->read_queue);
1339 radio->data_available_for_read = 0;
1340
1341 /* prepare polling via eventd */
1342 INIT_WORK(&radio->work, si470x_work);
1343 init_timer(&radio->timer);
1344 radio->timer.function = si470x_timer;
1345 radio->timer.data = (unsigned long) radio;
1346
1347 return 0;
1348}
1349
1350
1351/*
1352 * si470x_usb_driver_disconnect - disconnect the device
1353 */
1354static void si470x_usb_driver_disconnect(struct usb_interface *intf)
1355{
1356 struct si470x_device *radio = usb_get_intfdata(intf);
1357
1358 del_timer_sync(&radio->timer);
1359 flush_scheduled_work();
1360
1361 usb_set_intfdata(intf, NULL);
1362 if (radio) {
1363 video_unregister_device(radio->videodev);
1364 kfree(radio->buffer);
1365 kfree(radio);
1366 }
1367}
1368
1369
1370/*
1371 * si470x_usb_driver - usb driver interface
1372 */
1373static struct usb_driver si470x_usb_driver = {
1374 .name = DRIVER_NAME,
1375 .probe = si470x_usb_driver_probe,
1376 .disconnect = si470x_usb_driver_disconnect,
1377 .id_table = si470x_usb_driver_id_table,
1378};
1379
1380
1410 1381
1411/************************************************************************** 1382/**************************************************************************
1412 * Module interface definitions and functions 1383 * Module Interface
1413 **************************************************************************/ 1384 **************************************************************************/
1414 1385
1415/* 1386/*
@@ -1437,4 +1408,4 @@ module_exit(si470x_module_exit);
1437MODULE_LICENSE("GPL"); 1408MODULE_LICENSE("GPL");
1438MODULE_AUTHOR(DRIVER_AUTHOR); 1409MODULE_AUTHOR(DRIVER_AUTHOR);
1439MODULE_DESCRIPTION(DRIVER_DESC); 1410MODULE_DESCRIPTION(DRIVER_DESC);
1440MODULE_VERSION("1.0.2"); 1411MODULE_VERSION("1.0.3");