diff options
Diffstat (limited to 'drivers/media')
-rw-r--r-- | drivers/media/radio/radio-si470x.c | 223 |
1 files changed, 143 insertions, 80 deletions
diff --git a/drivers/media/radio/radio-si470x.c b/drivers/media/radio/radio-si470x.c index 8e4bd4769048..a2975c8b0095 100644 --- a/drivers/media/radio/radio-si470x.c +++ b/drivers/media/radio/radio-si470x.c | |||
@@ -62,6 +62,12 @@ | |||
62 | * - code cleaned of unnecessary rds_commands | 62 | * - code cleaned of unnecessary rds_commands |
63 | * - USB Vendor/Product ID for ADS/Tech FM Radio Receiver verified | 63 | * - USB Vendor/Product ID for ADS/Tech FM Radio Receiver verified |
64 | * (thanks to Guillaume RAMOUSSE) | 64 | * (thanks to Guillaume RAMOUSSE) |
65 | * 2008-01-27 Tobias Lorenz <tobias.lorenz@gmx.net> | ||
66 | * Version 1.0.5 | ||
67 | * - number of seek_retries changed to tune_timeout | ||
68 | * - fixed problem with incomplete tune operations by own buffers | ||
69 | * - optimization of variables | ||
70 | * - improved error logging | ||
65 | * | 71 | * |
66 | * ToDo: | 72 | * ToDo: |
67 | * - add seeking support | 73 | * - add seeking support |
@@ -74,9 +80,10 @@ | |||
74 | /* driver definitions */ | 80 | /* driver definitions */ |
75 | #define DRIVER_AUTHOR "Tobias Lorenz <tobias.lorenz@gmx.net>" | 81 | #define DRIVER_AUTHOR "Tobias Lorenz <tobias.lorenz@gmx.net>" |
76 | #define DRIVER_NAME "radio-si470x" | 82 | #define DRIVER_NAME "radio-si470x" |
77 | #define DRIVER_VERSION KERNEL_VERSION(1, 0, 4) | 83 | #define DRIVER_KERNEL_VERSION KERNEL_VERSION(1, 0, 5) |
78 | #define DRIVER_CARD "Silicon Labs Si470x FM Radio Receiver" | 84 | #define DRIVER_CARD "Silicon Labs Si470x FM Radio Receiver" |
79 | #define DRIVER_DESC "USB radio driver for Si470x FM Radio Receivers" | 85 | #define DRIVER_DESC "USB radio driver for Si470x FM Radio Receivers" |
86 | #define DRIVER_VERSION "1.0.5" | ||
80 | 87 | ||
81 | 88 | ||
82 | /* kernel includes */ | 89 | /* kernel includes */ |
@@ -119,56 +126,56 @@ MODULE_PARM_DESC(radio_nr, "Radio Nr"); | |||
119 | /* 0: 200 kHz (USA, Australia) */ | 126 | /* 0: 200 kHz (USA, Australia) */ |
120 | /* 1: 100 kHz (Europe, Japan) */ | 127 | /* 1: 100 kHz (Europe, Japan) */ |
121 | /* 2: 50 kHz */ | 128 | /* 2: 50 kHz */ |
122 | static int space = 2; | 129 | static unsigned short space = 2; |
123 | module_param(space, int, 0); | 130 | module_param(space, ushort, 0); |
124 | MODULE_PARM_DESC(radio_nr, "Spacing: 0=200kHz 1=100kHz *2=50kHz*"); | 131 | MODULE_PARM_DESC(radio_nr, "Spacing: 0=200kHz 1=100kHz *2=50kHz*"); |
125 | 132 | ||
126 | /* Bottom of Band (MHz) */ | 133 | /* Bottom of Band (MHz) */ |
127 | /* 0: 87.5 - 108 MHz (USA, Europe)*/ | 134 | /* 0: 87.5 - 108 MHz (USA, Europe)*/ |
128 | /* 1: 76 - 108 MHz (Japan wide band) */ | 135 | /* 1: 76 - 108 MHz (Japan wide band) */ |
129 | /* 2: 76 - 90 MHz (Japan) */ | 136 | /* 2: 76 - 90 MHz (Japan) */ |
130 | static int band = 1; | 137 | static unsigned short band = 1; |
131 | module_param(band, int, 0); | 138 | module_param(band, ushort, 0); |
132 | MODULE_PARM_DESC(radio_nr, "Band: 0=87.5..108MHz *1=76..108MHz* 2=76..90MHz"); | 139 | MODULE_PARM_DESC(radio_nr, "Band: 0=87.5..108MHz *1=76..108MHz* 2=76..90MHz"); |
133 | 140 | ||
134 | /* De-emphasis */ | 141 | /* De-emphasis */ |
135 | /* 0: 75 us (USA) */ | 142 | /* 0: 75 us (USA) */ |
136 | /* 1: 50 us (Europe, Australia, Japan) */ | 143 | /* 1: 50 us (Europe, Australia, Japan) */ |
137 | static int de = 1; | 144 | static unsigned short de = 1; |
138 | module_param(de, int, 0); | 145 | module_param(de, ushort, 0); |
139 | MODULE_PARM_DESC(radio_nr, "De-emphasis: 0=75us *1=50us*"); | 146 | MODULE_PARM_DESC(radio_nr, "De-emphasis: 0=75us *1=50us*"); |
140 | 147 | ||
141 | /* USB timeout */ | 148 | /* USB timeout */ |
142 | static int usb_timeout = 500; | 149 | static unsigned int usb_timeout = 500; |
143 | module_param(usb_timeout, int, 0); | 150 | module_param(usb_timeout, uint, 0); |
144 | MODULE_PARM_DESC(usb_timeout, "USB timeout (ms): *500*"); | 151 | MODULE_PARM_DESC(usb_timeout, "USB timeout (ms): *500*"); |
145 | 152 | ||
146 | /* Seek retries */ | 153 | /* Tune timeout */ |
147 | static int seek_retries = 100; | 154 | static unsigned int tune_timeout = 3000; |
148 | module_param(seek_retries, int, 0); | 155 | module_param(tune_timeout, uint, 0); |
149 | MODULE_PARM_DESC(seek_retries, "Seek retries: *100*"); | 156 | MODULE_PARM_DESC(tune_timeout, "Tune timeout: *3000*"); |
150 | 157 | ||
151 | /* RDS buffer blocks */ | 158 | /* RDS buffer blocks */ |
152 | static int rds_buf = 100; | 159 | static unsigned int rds_buf = 100; |
153 | module_param(rds_buf, int, 0); | 160 | module_param(rds_buf, uint, 0); |
154 | MODULE_PARM_DESC(rds_buf, "RDS buffer entries: *100*"); | 161 | MODULE_PARM_DESC(rds_buf, "RDS buffer entries: *100*"); |
155 | 162 | ||
156 | /* RDS maximum block errors */ | 163 | /* RDS maximum block errors */ |
157 | static int max_rds_errors = 1; | 164 | static unsigned short max_rds_errors = 1; |
158 | /* 0 means 0 errors requiring correction */ | 165 | /* 0 means 0 errors requiring correction */ |
159 | /* 1 means 1-2 errors requiring correction (used by original USBRadio.exe) */ | 166 | /* 1 means 1-2 errors requiring correction (used by original USBRadio.exe) */ |
160 | /* 2 means 3-5 errors requiring correction */ | 167 | /* 2 means 3-5 errors requiring correction */ |
161 | /* 3 means 6+ errors or errors in checkword, correction not possible */ | 168 | /* 3 means 6+ errors or errors in checkword, correction not possible */ |
162 | module_param(max_rds_errors, int, 0); | 169 | module_param(max_rds_errors, ushort, 0); |
163 | MODULE_PARM_DESC(max_rds_errors, "RDS maximum block errors: *1*"); | 170 | MODULE_PARM_DESC(max_rds_errors, "RDS maximum block errors: *1*"); |
164 | 171 | ||
165 | /* RDS poll frequency */ | 172 | /* RDS poll frequency */ |
166 | static int rds_poll_time = 40; | 173 | static unsigned int rds_poll_time = 40; |
167 | /* 40 is used by the original USBRadio.exe */ | 174 | /* 40 is used by the original USBRadio.exe */ |
168 | /* 50 is used by radio-cadet */ | 175 | /* 50 is used by radio-cadet */ |
169 | /* 75 should be okay */ | 176 | /* 75 should be okay */ |
170 | /* 80 is the usual RDS receive interval */ | 177 | /* 80 is the usual RDS receive interval */ |
171 | module_param(rds_poll_time, int, 0); | 178 | module_param(rds_poll_time, uint, 0); |
172 | MODULE_PARM_DESC(rds_poll_time, "RDS poll time (ms): *40*"); | 179 | MODULE_PARM_DESC(rds_poll_time, "RDS poll time (ms): *40*"); |
173 | 180 | ||
174 | 181 | ||
@@ -395,11 +402,8 @@ struct si470x_device { | |||
395 | struct usb_device *usbdev; | 402 | struct usb_device *usbdev; |
396 | struct video_device *videodev; | 403 | struct video_device *videodev; |
397 | 404 | ||
398 | /* are these really necessary ? */ | 405 | /* driver management */ |
399 | int users; | 406 | unsigned int users; |
400 | |||
401 | /* report buffer (maximum 64 bytes) */ | ||
402 | unsigned char buf[64]; | ||
403 | 407 | ||
404 | /* Silabs internal registers (0..15) */ | 408 | /* Silabs internal registers (0..15) */ |
405 | unsigned short registers[RADIO_REGISTER_NUM]; | 409 | unsigned short registers[RADIO_REGISTER_NUM]; |
@@ -434,28 +438,46 @@ struct si470x_device { | |||
434 | /* | 438 | /* |
435 | * si470x_get_report - receive a HID report | 439 | * si470x_get_report - receive a HID report |
436 | */ | 440 | */ |
437 | static int si470x_get_report(struct si470x_device *radio, int size) | 441 | static int si470x_get_report(struct si470x_device *radio, void *buf, int size) |
438 | { | 442 | { |
439 | return usb_control_msg(radio->usbdev, | 443 | unsigned char *report = (unsigned char *) buf; |
444 | int retval; | ||
445 | |||
446 | retval = usb_control_msg(radio->usbdev, | ||
440 | usb_rcvctrlpipe(radio->usbdev, 0), | 447 | usb_rcvctrlpipe(radio->usbdev, 0), |
441 | HID_REQ_GET_REPORT, | 448 | HID_REQ_GET_REPORT, |
442 | USB_TYPE_CLASS | USB_RECIP_INTERFACE | USB_DIR_IN, | 449 | USB_TYPE_CLASS | USB_RECIP_INTERFACE | USB_DIR_IN, |
443 | radio->buf[0], 2, | 450 | report[0], 2, |
444 | radio->buf, size, usb_timeout); | 451 | buf, size, usb_timeout); |
452 | if (retval < 0) | ||
453 | printk(KERN_WARNING DRIVER_NAME | ||
454 | ": si470x_get_report: usb_control_msg returned %d\n", | ||
455 | retval); | ||
456 | |||
457 | return retval; | ||
445 | } | 458 | } |
446 | 459 | ||
447 | 460 | ||
448 | /* | 461 | /* |
449 | * si470x_set_report - send a HID report | 462 | * si470x_set_report - send a HID report |
450 | */ | 463 | */ |
451 | static int si470x_set_report(struct si470x_device *radio, int size) | 464 | static int si470x_set_report(struct si470x_device *radio, void *buf, int size) |
452 | { | 465 | { |
453 | return usb_control_msg(radio->usbdev, | 466 | unsigned char *report = (unsigned char *) buf; |
467 | int retval; | ||
468 | |||
469 | retval = usb_control_msg(radio->usbdev, | ||
454 | usb_sndctrlpipe(radio->usbdev, 0), | 470 | usb_sndctrlpipe(radio->usbdev, 0), |
455 | HID_REQ_SET_REPORT, | 471 | HID_REQ_SET_REPORT, |
456 | USB_TYPE_CLASS | USB_RECIP_INTERFACE | USB_DIR_OUT, | 472 | USB_TYPE_CLASS | USB_RECIP_INTERFACE | USB_DIR_OUT, |
457 | radio->buf[0], 2, | 473 | report[0], 2, |
458 | radio->buf, size, usb_timeout); | 474 | buf, size, usb_timeout); |
475 | if (retval < 0) | ||
476 | printk(KERN_WARNING DRIVER_NAME | ||
477 | ": si470x_set_report: usb_control_msg returned %d\n", | ||
478 | retval); | ||
479 | |||
480 | return retval; | ||
459 | } | 481 | } |
460 | 482 | ||
461 | 483 | ||
@@ -464,13 +486,15 @@ static int si470x_set_report(struct si470x_device *radio, int size) | |||
464 | */ | 486 | */ |
465 | static int si470x_get_register(struct si470x_device *radio, int regnr) | 487 | static int si470x_get_register(struct si470x_device *radio, int regnr) |
466 | { | 488 | { |
489 | unsigned char buf[REGISTER_REPORT_SIZE]; | ||
467 | int retval; | 490 | int retval; |
468 | 491 | ||
469 | radio->buf[0] = REGISTER_REPORT(regnr); | 492 | buf[0] = REGISTER_REPORT(regnr); |
493 | |||
494 | retval = si470x_get_report(radio, (void *) &buf, sizeof(buf)); | ||
470 | 495 | ||
471 | retval = si470x_get_report(radio, REGISTER_REPORT_SIZE); | ||
472 | if (retval >= 0) | 496 | if (retval >= 0) |
473 | radio->registers[regnr] = (radio->buf[1] << 8) | radio->buf[2]; | 497 | radio->registers[regnr] = (buf[1] << 8) | buf[2]; |
474 | 498 | ||
475 | return (retval < 0) ? -EINVAL : 0; | 499 | return (retval < 0) ? -EINVAL : 0; |
476 | } | 500 | } |
@@ -481,13 +505,14 @@ static int si470x_get_register(struct si470x_device *radio, int regnr) | |||
481 | */ | 505 | */ |
482 | static int si470x_set_register(struct si470x_device *radio, int regnr) | 506 | static int si470x_set_register(struct si470x_device *radio, int regnr) |
483 | { | 507 | { |
508 | unsigned char buf[REGISTER_REPORT_SIZE]; | ||
484 | int retval; | 509 | int retval; |
485 | 510 | ||
486 | radio->buf[0] = REGISTER_REPORT(regnr); | 511 | buf[0] = REGISTER_REPORT(regnr); |
487 | radio->buf[1] = (radio->registers[regnr] & 0xff00) >> 8; | 512 | buf[1] = (radio->registers[regnr] & 0xff00) >> 8; |
488 | radio->buf[2] = (radio->registers[regnr] & 0x00ff); | 513 | buf[2] = (radio->registers[regnr] & 0x00ff); |
489 | 514 | ||
490 | retval = si470x_set_report(radio, REGISTER_REPORT_SIZE); | 515 | retval = si470x_set_report(radio, (void *) &buf, sizeof(buf)); |
491 | 516 | ||
492 | return (retval < 0) ? -EINVAL : 0; | 517 | return (retval < 0) ? -EINVAL : 0; |
493 | } | 518 | } |
@@ -498,18 +523,19 @@ static int si470x_set_register(struct si470x_device *radio, int regnr) | |||
498 | */ | 523 | */ |
499 | static int si470x_get_all_registers(struct si470x_device *radio) | 524 | static int si470x_get_all_registers(struct si470x_device *radio) |
500 | { | 525 | { |
526 | unsigned char buf[ENTIRE_REPORT_SIZE]; | ||
501 | int retval; | 527 | int retval; |
502 | int regnr; | 528 | unsigned char regnr; |
503 | 529 | ||
504 | radio->buf[0] = ENTIRE_REPORT; | 530 | buf[0] = ENTIRE_REPORT; |
505 | 531 | ||
506 | retval = si470x_get_report(radio, ENTIRE_REPORT_SIZE); | 532 | retval = si470x_get_report(radio, (void *) &buf, sizeof(buf)); |
507 | 533 | ||
508 | if (retval >= 0) | 534 | if (retval >= 0) |
509 | for (regnr = 0; regnr < RADIO_REGISTER_NUM; regnr++) | 535 | for (regnr = 0; regnr < RADIO_REGISTER_NUM; regnr++) |
510 | radio->registers[regnr] = | 536 | radio->registers[regnr] = |
511 | (radio->buf[regnr * RADIO_REGISTER_SIZE + 1] << 8) | | 537 | (buf[regnr * RADIO_REGISTER_SIZE + 1] << 8) | |
512 | radio->buf[regnr * RADIO_REGISTER_SIZE + 2]; | 538 | buf[regnr * RADIO_REGISTER_SIZE + 2]; |
513 | 539 | ||
514 | return (retval < 0) ? -EINVAL : 0; | 540 | return (retval < 0) ? -EINVAL : 0; |
515 | } | 541 | } |
@@ -520,21 +546,28 @@ static int si470x_get_all_registers(struct si470x_device *radio) | |||
520 | */ | 546 | */ |
521 | static int si470x_get_rds_registers(struct si470x_device *radio) | 547 | static int si470x_get_rds_registers(struct si470x_device *radio) |
522 | { | 548 | { |
549 | unsigned char buf[RDS_REPORT_SIZE]; | ||
523 | int retval; | 550 | int retval; |
524 | int regnr; | ||
525 | int size; | 551 | int size; |
552 | unsigned char regnr; | ||
526 | 553 | ||
527 | radio->buf[0] = RDS_REPORT; | 554 | buf[0] = RDS_REPORT; |
528 | 555 | ||
529 | retval = usb_interrupt_msg(radio->usbdev, | 556 | retval = usb_interrupt_msg(radio->usbdev, |
530 | usb_rcvctrlpipe(radio->usbdev, 1), | 557 | usb_rcvintpipe(radio->usbdev, 1), |
531 | radio->buf, RDS_REPORT_SIZE, &size, usb_timeout); | 558 | (void *) &buf, sizeof(buf), &size, usb_timeout); |
559 | if (size != sizeof(buf)) | ||
560 | printk(KERN_WARNING DRIVER_NAME ": si470x_get_rds_register: " | ||
561 | "return size differs: %d != %d\n", size, sizeof(buf)); | ||
562 | if (retval < 0) | ||
563 | printk(KERN_WARNING DRIVER_NAME ": si470x_get_rds_registers: " | ||
564 | "usb_interrupt_msg returned %d\n", retval); | ||
532 | 565 | ||
533 | if (retval >= 0) | 566 | if (retval >= 0) |
534 | for (regnr = 0; regnr < RDS_REGISTER_NUM; regnr++) | 567 | for (regnr = 0; regnr < RDS_REGISTER_NUM; regnr++) |
535 | radio->registers[STATUSRSSI + regnr] = | 568 | radio->registers[STATUSRSSI + regnr] = |
536 | (radio->buf[regnr * RADIO_REGISTER_SIZE + 1] << 8) | | 569 | (buf[regnr * RADIO_REGISTER_SIZE + 1] << 8) | |
537 | radio->buf[regnr * RADIO_REGISTER_SIZE + 2]; | 570 | buf[regnr * RADIO_REGISTER_SIZE + 2]; |
538 | 571 | ||
539 | return (retval < 0) ? -EINVAL : 0; | 572 | return (retval < 0) ? -EINVAL : 0; |
540 | } | 573 | } |
@@ -543,9 +576,11 @@ static int si470x_get_rds_registers(struct si470x_device *radio) | |||
543 | /* | 576 | /* |
544 | * si470x_set_chan - set the channel | 577 | * si470x_set_chan - set the channel |
545 | */ | 578 | */ |
546 | static int si470x_set_chan(struct si470x_device *radio, int chan) | 579 | static int si470x_set_chan(struct si470x_device *radio, unsigned short chan) |
547 | { | 580 | { |
548 | int retval, i; | 581 | int retval; |
582 | unsigned long timeout; | ||
583 | bool timed_out = 0; | ||
549 | 584 | ||
550 | /* start tuning */ | 585 | /* start tuning */ |
551 | radio->registers[CHANNEL] &= ~CHANNEL_CHAN; | 586 | radio->registers[CHANNEL] &= ~CHANNEL_CHAN; |
@@ -555,16 +590,17 @@ static int si470x_set_chan(struct si470x_device *radio, int chan) | |||
555 | return retval; | 590 | return retval; |
556 | 591 | ||
557 | /* wait till seek operation has completed */ | 592 | /* wait till seek operation has completed */ |
558 | i = 0; | 593 | timeout = jiffies + msecs_to_jiffies(tune_timeout); |
559 | do { | 594 | do { |
560 | retval = si470x_get_register(radio, STATUSRSSI); | 595 | retval = si470x_get_register(radio, STATUSRSSI); |
561 | if (retval < 0) | 596 | if (retval < 0) |
562 | return retval; | 597 | return retval; |
563 | } while ((radio->registers[STATUSRSSI] & STATUSRSSI_STC) && | 598 | timed_out = time_after(jiffies, timeout); |
564 | (++i < seek_retries)); | 599 | } while (((radio->registers[STATUSRSSI] & STATUSRSSI_STC) == 0) && |
565 | if (i >= seek_retries) | 600 | (!timed_out)); |
601 | if (timed_out) | ||
566 | printk(KERN_WARNING DRIVER_NAME | 602 | printk(KERN_WARNING DRIVER_NAME |
567 | ": seek does not finish after %d tries\n", i); | 603 | ": seek does not finish after %d ms\n", tune_timeout); |
568 | 604 | ||
569 | /* stop tuning */ | 605 | /* stop tuning */ |
570 | radio->registers[CHANNEL] &= ~CHANNEL_TUNE; | 606 | radio->registers[CHANNEL] &= ~CHANNEL_TUNE; |
@@ -575,9 +611,10 @@ static int si470x_set_chan(struct si470x_device *radio, int chan) | |||
575 | /* | 611 | /* |
576 | * si470x_get_freq - get the frequency | 612 | * si470x_get_freq - get the frequency |
577 | */ | 613 | */ |
578 | static int si470x_get_freq(struct si470x_device *radio) | 614 | static unsigned int si470x_get_freq(struct si470x_device *radio) |
579 | { | 615 | { |
580 | int spacing, band_bottom, chan, freq; | 616 | unsigned int spacing, band_bottom, freq; |
617 | unsigned short chan; | ||
581 | int retval; | 618 | int retval; |
582 | 619 | ||
583 | /* Spacing (kHz) */ | 620 | /* Spacing (kHz) */ |
@@ -616,9 +653,10 @@ static int si470x_get_freq(struct si470x_device *radio) | |||
616 | /* | 653 | /* |
617 | * si470x_set_freq - set the frequency | 654 | * si470x_set_freq - set the frequency |
618 | */ | 655 | */ |
619 | static int si470x_set_freq(struct si470x_device *radio, int freq) | 656 | static int si470x_set_freq(struct si470x_device *radio, unsigned int freq) |
620 | { | 657 | { |
621 | int spacing, band_bottom, chan; | 658 | unsigned int spacing, band_bottom; |
659 | unsigned short chan; | ||
622 | 660 | ||
623 | /* Spacing (kHz) */ | 661 | /* Spacing (kHz) */ |
624 | switch (space) { | 662 | switch (space) { |
@@ -725,12 +763,6 @@ static int si470x_rds_on(struct si470x_device *radio) | |||
725 | */ | 763 | */ |
726 | static void si470x_rds(struct si470x_device *radio) | 764 | static void si470x_rds(struct si470x_device *radio) |
727 | { | 765 | { |
728 | unsigned char tmpbuf[3]; | ||
729 | unsigned char blocknum; | ||
730 | unsigned char bler; /* rds block errors */ | ||
731 | unsigned short rds; | ||
732 | unsigned int i; | ||
733 | |||
734 | /* get rds blocks */ | 766 | /* get rds blocks */ |
735 | if (si470x_get_rds_registers(radio) < 0) | 767 | if (si470x_get_rds_registers(radio) < 0) |
736 | return; | 768 | return; |
@@ -745,6 +777,12 @@ static void si470x_rds(struct si470x_device *radio) | |||
745 | 777 | ||
746 | /* copy four RDS blocks to internal buffer */ | 778 | /* copy four RDS blocks to internal buffer */ |
747 | if (spin_trylock(&radio->lock)) { | 779 | if (spin_trylock(&radio->lock)) { |
780 | unsigned char blocknum; | ||
781 | unsigned short bler; /* rds block errors */ | ||
782 | unsigned short rds; | ||
783 | unsigned char tmpbuf[3]; | ||
784 | unsigned char i; | ||
785 | |||
748 | /* process each rds block */ | 786 | /* process each rds block */ |
749 | for (blocknum = 0; blocknum < 4; blocknum++) { | 787 | for (blocknum = 0; blocknum < 4; blocknum++) { |
750 | switch (blocknum) { | 788 | switch (blocknum) { |
@@ -847,7 +885,6 @@ static ssize_t si470x_fops_read(struct file *file, char __user *buf, | |||
847 | { | 885 | { |
848 | struct si470x_device *radio = video_get_drvdata(video_devdata(file)); | 886 | struct si470x_device *radio = video_get_drvdata(video_devdata(file)); |
849 | int retval = 0; | 887 | int retval = 0; |
850 | unsigned int block_count = 0; | ||
851 | 888 | ||
852 | /* switch on rds reception */ | 889 | /* switch on rds reception */ |
853 | if ((radio->registers[SYSCONFIG1] & SYSCONFIG1_RDS) == 0) { | 890 | if ((radio->registers[SYSCONFIG1] & SYSCONFIG1_RDS) == 0) { |
@@ -867,6 +904,7 @@ static ssize_t si470x_fops_read(struct file *file, char __user *buf, | |||
867 | 904 | ||
868 | /* copy RDS block out of internal buffer and to user buffer */ | 905 | /* copy RDS block out of internal buffer and to user buffer */ |
869 | if (spin_trylock(&radio->lock)) { | 906 | if (spin_trylock(&radio->lock)) { |
907 | unsigned int block_count = 0; | ||
870 | while (block_count < count) { | 908 | while (block_count < count) { |
871 | if (radio->rd_index == radio->wr_index) | 909 | if (radio->rd_index == radio->wr_index) |
872 | break; | 910 | break; |
@@ -1030,7 +1068,7 @@ static int si470x_vidioc_querycap(struct file *file, void *priv, | |||
1030 | strlcpy(capability->driver, DRIVER_NAME, sizeof(capability->driver)); | 1068 | strlcpy(capability->driver, DRIVER_NAME, sizeof(capability->driver)); |
1031 | strlcpy(capability->card, DRIVER_CARD, sizeof(capability->card)); | 1069 | strlcpy(capability->card, DRIVER_CARD, sizeof(capability->card)); |
1032 | sprintf(capability->bus_info, "USB"); | 1070 | sprintf(capability->bus_info, "USB"); |
1033 | capability->version = DRIVER_VERSION; | 1071 | capability->version = DRIVER_KERNEL_VERSION; |
1034 | capability->capabilities = V4L2_CAP_TUNER | V4L2_CAP_RADIO; | 1072 | capability->capabilities = V4L2_CAP_TUNER | V4L2_CAP_RADIO; |
1035 | 1073 | ||
1036 | return 0; | 1074 | return 0; |
@@ -1067,16 +1105,21 @@ static int si470x_vidioc_s_input(struct file *filp, void *priv, unsigned int i) | |||
1067 | static int si470x_vidioc_queryctrl(struct file *file, void *priv, | 1105 | static int si470x_vidioc_queryctrl(struct file *file, void *priv, |
1068 | struct v4l2_queryctrl *qc) | 1106 | struct v4l2_queryctrl *qc) |
1069 | { | 1107 | { |
1070 | int i; | 1108 | unsigned char i; |
1109 | int retval = -EINVAL; | ||
1071 | 1110 | ||
1072 | for (i = 0; i < ARRAY_SIZE(si470x_v4l2_queryctrl); i++) { | 1111 | for (i = 0; i < ARRAY_SIZE(si470x_v4l2_queryctrl); i++) { |
1073 | if (qc->id && qc->id == si470x_v4l2_queryctrl[i].id) { | 1112 | if (qc->id && qc->id == si470x_v4l2_queryctrl[i].id) { |
1074 | memcpy(qc, &(si470x_v4l2_queryctrl[i]), sizeof(*qc)); | 1113 | memcpy(qc, &(si470x_v4l2_queryctrl[i]), sizeof(*qc)); |
1075 | return 0; | 1114 | retval = 0; |
1115 | break; | ||
1076 | } | 1116 | } |
1077 | } | 1117 | } |
1118 | if (retval < 0) | ||
1119 | printk(KERN_WARNING DRIVER_NAME | ||
1120 | ": query control failed with %d\n", retval); | ||
1078 | 1121 | ||
1079 | return -EINVAL; | 1122 | return retval; |
1080 | } | 1123 | } |
1081 | 1124 | ||
1082 | 1125 | ||
@@ -1110,21 +1153,29 @@ static int si470x_vidioc_s_ctrl(struct file *file, void *priv, | |||
1110 | struct v4l2_control *ctrl) | 1153 | struct v4l2_control *ctrl) |
1111 | { | 1154 | { |
1112 | struct si470x_device *radio = video_get_drvdata(video_devdata(file)); | 1155 | struct si470x_device *radio = video_get_drvdata(video_devdata(file)); |
1156 | int retval; | ||
1113 | 1157 | ||
1114 | switch (ctrl->id) { | 1158 | switch (ctrl->id) { |
1115 | case V4L2_CID_AUDIO_VOLUME: | 1159 | case V4L2_CID_AUDIO_VOLUME: |
1116 | radio->registers[SYSCONFIG2] &= ~SYSCONFIG2_VOLUME; | 1160 | radio->registers[SYSCONFIG2] &= ~SYSCONFIG2_VOLUME; |
1117 | radio->registers[SYSCONFIG2] |= ctrl->value; | 1161 | radio->registers[SYSCONFIG2] |= ctrl->value; |
1118 | return si470x_set_register(radio, SYSCONFIG2); | 1162 | retval = si470x_set_register(radio, SYSCONFIG2); |
1163 | break; | ||
1119 | case V4L2_CID_AUDIO_MUTE: | 1164 | case V4L2_CID_AUDIO_MUTE: |
1120 | if (ctrl->value == 1) | 1165 | if (ctrl->value == 1) |
1121 | radio->registers[POWERCFG] &= ~POWERCFG_DMUTE; | 1166 | radio->registers[POWERCFG] &= ~POWERCFG_DMUTE; |
1122 | else | 1167 | else |
1123 | radio->registers[POWERCFG] |= POWERCFG_DMUTE; | 1168 | radio->registers[POWERCFG] |= POWERCFG_DMUTE; |
1124 | return si470x_set_register(radio, POWERCFG); | 1169 | retval = si470x_set_register(radio, POWERCFG); |
1170 | break; | ||
1171 | default: | ||
1172 | retval = -EINVAL; | ||
1125 | } | 1173 | } |
1174 | if (retval < 0) | ||
1175 | printk(KERN_WARNING DRIVER_NAME | ||
1176 | ": set control failed with %d\n", retval); | ||
1126 | 1177 | ||
1127 | return -EINVAL; | 1178 | return retval; |
1128 | } | 1179 | } |
1129 | 1180 | ||
1130 | 1181 | ||
@@ -1163,8 +1214,8 @@ static int si470x_vidioc_s_audio(struct file *file, void *priv, | |||
1163 | static int si470x_vidioc_g_tuner(struct file *file, void *priv, | 1214 | static int si470x_vidioc_g_tuner(struct file *file, void *priv, |
1164 | struct v4l2_tuner *tuner) | 1215 | struct v4l2_tuner *tuner) |
1165 | { | 1216 | { |
1166 | int retval; | ||
1167 | struct si470x_device *radio = video_get_drvdata(video_devdata(file)); | 1217 | struct si470x_device *radio = video_get_drvdata(video_devdata(file)); |
1218 | int retval; | ||
1168 | 1219 | ||
1169 | if (tuner->index > 0) | 1220 | if (tuner->index > 0) |
1170 | return -EINVAL; | 1221 | return -EINVAL; |
@@ -1220,6 +1271,7 @@ static int si470x_vidioc_s_tuner(struct file *file, void *priv, | |||
1220 | struct v4l2_tuner *tuner) | 1271 | struct v4l2_tuner *tuner) |
1221 | { | 1272 | { |
1222 | struct si470x_device *radio = video_get_drvdata(video_devdata(file)); | 1273 | struct si470x_device *radio = video_get_drvdata(video_devdata(file)); |
1274 | int retval; | ||
1223 | 1275 | ||
1224 | if (tuner->index > 0) | 1276 | if (tuner->index > 0) |
1225 | return -EINVAL; | 1277 | return -EINVAL; |
@@ -1229,7 +1281,12 @@ static int si470x_vidioc_s_tuner(struct file *file, void *priv, | |||
1229 | else | 1281 | else |
1230 | radio->registers[POWERCFG] &= ~POWERCFG_MONO; /* try stereo */ | 1282 | radio->registers[POWERCFG] &= ~POWERCFG_MONO; /* try stereo */ |
1231 | 1283 | ||
1232 | return si470x_set_register(radio, POWERCFG); | 1284 | retval = si470x_set_register(radio, POWERCFG); |
1285 | if (retval < 0) | ||
1286 | printk(KERN_WARNING DRIVER_NAME | ||
1287 | ": set tuner failed with %d\n", retval); | ||
1288 | |||
1289 | return retval; | ||
1233 | } | 1290 | } |
1234 | 1291 | ||
1235 | 1292 | ||
@@ -1255,11 +1312,17 @@ static int si470x_vidioc_s_frequency(struct file *file, void *priv, | |||
1255 | struct v4l2_frequency *freq) | 1312 | struct v4l2_frequency *freq) |
1256 | { | 1313 | { |
1257 | struct si470x_device *radio = video_get_drvdata(video_devdata(file)); | 1314 | struct si470x_device *radio = video_get_drvdata(video_devdata(file)); |
1315 | int retval; | ||
1258 | 1316 | ||
1259 | if (freq->type != V4L2_TUNER_RADIO) | 1317 | if (freq->type != V4L2_TUNER_RADIO) |
1260 | return -EINVAL; | 1318 | return -EINVAL; |
1261 | 1319 | ||
1262 | return si470x_set_freq(radio, freq->frequency); | 1320 | retval = si470x_set_freq(radio, freq->frequency); |
1321 | if (retval < 0) | ||
1322 | printk(KERN_WARNING DRIVER_NAME | ||
1323 | ": set frequency failed with %d\n", retval); | ||
1324 | |||
1325 | return 0; | ||
1263 | } | 1326 | } |
1264 | 1327 | ||
1265 | 1328 | ||
@@ -1409,7 +1472,7 @@ static struct usb_driver si470x_usb_driver = { | |||
1409 | */ | 1472 | */ |
1410 | static int __init si470x_module_init(void) | 1473 | static int __init si470x_module_init(void) |
1411 | { | 1474 | { |
1412 | printk(KERN_INFO DRIVER_DESC "\n"); | 1475 | printk(KERN_INFO DRIVER_DESC ", Version " DRIVER_VERSION "\n"); |
1413 | return usb_register(&si470x_usb_driver); | 1476 | return usb_register(&si470x_usb_driver); |
1414 | } | 1477 | } |
1415 | 1478 | ||
@@ -1429,4 +1492,4 @@ module_exit(si470x_module_exit); | |||
1429 | MODULE_LICENSE("GPL"); | 1492 | MODULE_LICENSE("GPL"); |
1430 | MODULE_AUTHOR(DRIVER_AUTHOR); | 1493 | MODULE_AUTHOR(DRIVER_AUTHOR); |
1431 | MODULE_DESCRIPTION(DRIVER_DESC); | 1494 | MODULE_DESCRIPTION(DRIVER_DESC); |
1432 | MODULE_VERSION("1.0.4"); | 1495 | MODULE_VERSION(DRIVER_VERSION); |