1 /* 2 * drivers/media/radio/si470x/radio-si470x-common.c 3 * 4 * Driver for radios with Silicon Labs Si470x FM Radio Receivers 5 * 6 * Copyright (c) 2009 Tobias Lorenz <tobias.lorenz@gmx.net> 7 * 8 * This program is free software; you can redistribute it and/or modify 9 * it under the terms of the GNU General Public License as published by 10 * the Free Software Foundation; either version 2 of the License, or 11 * (at your option) any later version. 12 * 13 * This program is distributed in the hope that it will be useful, 14 * but WITHOUT ANY WARRANTY; without even the implied warranty of 15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16 * GNU General Public License for more details. 17 * 18 * You should have received a copy of the GNU General Public License 19 * along with this program; if not, write to the Free Software 20 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 21 */ 22 23 24 /* 25 * History: 26 * 2008-01-12 Tobias Lorenz <tobias.lorenz@gmx.net> 27 * Version 1.0.0 28 * - First working version 29 * 2008-01-13 Tobias Lorenz <tobias.lorenz@gmx.net> 30 * Version 1.0.1 31 * - Improved error handling, every function now returns errno 32 * - Improved multi user access (start/mute/stop) 33 * - Channel doesn't get lost anymore after start/mute/stop 34 * - RDS support added (polling mode via interrupt EP 1) 35 * - marked default module parameters with *value* 36 * - switched from bit structs to bit masks 37 * - header file cleaned and integrated 38 * 2008-01-14 Tobias Lorenz <tobias.lorenz@gmx.net> 39 * Version 1.0.2 40 * - hex values are now lower case 41 * - commented USB ID for ADS/Tech moved on todo list 42 * - blacklisted si470x in hid-quirks.c 43 * - rds buffer handling functions integrated into *_work, *_read 44 * - rds_command in si470x_poll exchanged against simple retval 45 * - check for firmware version 15 46 * - code order and prototypes still remain the same 47 * - spacing and bottom of band codes remain the same 48 * 2008-01-16 Tobias Lorenz <tobias.lorenz@gmx.net> 49 * Version 1.0.3 50 * - code reordered to avoid function prototypes 51 * - switch/case defaults are now more user-friendly 52 * - unified comment style 53 * - applied all checkpatch.pl v1.12 suggestions 54 * except the warning about the too long lines with bit comments 55 * - renamed FMRADIO to RADIO to cut line length (checkpatch.pl) 56 * 2008-01-22 Tobias Lorenz <tobias.lorenz@gmx.net> 57 * Version 1.0.4 58 * - avoid poss. locking when doing copy_to_user which may sleep 59 * - RDS is automatically activated on read now 60 * - code cleaned of unnecessary rds_commands 61 * - USB Vendor/Product ID for ADS/Tech FM Radio Receiver verified 62 * (thanks to Guillaume RAMOUSSE) 63 * 2008-01-27 Tobias Lorenz <tobias.lorenz@gmx.net> 64 * Version 1.0.5 65 * - number of seek_retries changed to tune_timeout 66 * - fixed problem with incomplete tune operations by own buffers 67 * - optimization of variables and printf types 68 * - improved error logging 69 * 2008-01-31 Tobias Lorenz <tobias.lorenz@gmx.net> 70 * Oliver Neukum <oliver@neukum.org> 71 * Version 1.0.6 72 * - fixed coverity checker warnings in *_usb_driver_disconnect 73 * - probe()/open() race by correct ordering in probe() 74 * - DMA coherency rules by separate allocation of all buffers 75 * - use of endianness macros 76 * - abuse of spinlock, replaced by mutex 77 * - racy handling of timer in disconnect, 78 * replaced by delayed_work 79 * - racy interruptible_sleep_on(), 80 * replaced with wait_event_interruptible() 81 * - handle signals in read() 82 * 2008-02-08 Tobias Lorenz <tobias.lorenz@gmx.net> 83 * Oliver Neukum <oliver@neukum.org> 84 * Version 1.0.7 85 * - usb autosuspend support 86 * - unplugging fixed 87 * 2008-05-07 Tobias Lorenz <tobias.lorenz@gmx.net> 88 * Version 1.0.8 89 * - hardware frequency seek support 90 * - afc indication 91 * - more safety checks, let si470x_get_freq return errno 92 * - vidioc behavior corrected according to v4l2 spec 93 * 2008-10-20 Alexey Klimov <klimov.linux@gmail.com> 94 * - add support for KWorld USB FM Radio FM700 95 * - blacklisted KWorld radio in hid-core.c and hid-ids.h 96 * 2008-12-03 Mark Lord <mlord@pobox.com> 97 * - add support for DealExtreme USB Radio 98 * 2009-01-31 Bob Ross <pigiron@gmx.com> 99 * - correction of stereo detection/setting 100 * - correction of signal strength indicator scaling 101 * 2009-01-31 Rick Bronson <rick@efn.org> 102 * Tobias Lorenz <tobias.lorenz@gmx.net> 103 * - add LED status output 104 * - get HW/SW version from scratchpad 105 * 2009-06-16 Edouard Lafargue <edouard@lafargue.name> 106 * Version 1.0.10 107 * - add support for interrupt mode for RDS endpoint, 108 * instead of polling. 109 * Improves RDS reception significantly 110 */ 111 112 113 /* kernel includes */ 114 #include "radio-si470x.h" 115 116 117 118 /************************************************************************** 119 * Module Parameters 120 **************************************************************************/ 121 122 /* Spacing (kHz) */ 123 /* 0: 200 kHz (USA, Australia) */ 124 /* 1: 100 kHz (Europe, Japan) */ 125 /* 2: 50 kHz */ 126 static unsigned short space = 2; 127 module_param(space, ushort, 0444); 128 MODULE_PARM_DESC(space, "Spacing: 0=200kHz 1=100kHz *2=50kHz*"); 129 130 /* Bottom of Band (MHz) */ 131 /* 0: 87.5 - 108 MHz (USA, Europe)*/ 132 /* 1: 76 - 108 MHz (Japan wide band) */ 133 /* 2: 76 - 90 MHz (Japan) */ 134 static unsigned short band = 1; 135 module_param(band, ushort, 0444); 136 MODULE_PARM_DESC(band, "Band: 0=87.5..108MHz *1=76..108MHz* 2=76..90MHz"); 137 138 /* De-emphasis */ 139 /* 0: 75 us (USA) */ 140 /* 1: 50 us (Europe, Australia, Japan) */ 141 static unsigned short de = 1; 142 module_param(de, ushort, 0444); 143 MODULE_PARM_DESC(de, "De-emphasis: 0=75us *1=50us*"); 144 145 /* Tune timeout */ 146 static unsigned int tune_timeout = 3000; 147 module_param(tune_timeout, uint, 0644); 148 MODULE_PARM_DESC(tune_timeout, "Tune timeout: *3000*"); 149 150 /* Seek timeout */ 151 static unsigned int seek_timeout = 5000; 152 module_param(seek_timeout, uint, 0644); 153 MODULE_PARM_DESC(seek_timeout, "Seek timeout: *5000*"); 154 155 156 157 /************************************************************************** 158 * Generic Functions 159 **************************************************************************/ 160 161 /* 162 * si470x_set_chan - set the channel 163 */ 164 static int si470x_set_chan(struct si470x_device *radio, unsigned short chan) 165 { 166 int retval; 167 unsigned long timeout; 168 bool timed_out = 0; 169 170 /* start tuning */ 171 radio->registers[CHANNEL] &= ~CHANNEL_CHAN; 172 radio->registers[CHANNEL] |= CHANNEL_TUNE | chan; 173 retval = si470x_set_register(radio, CHANNEL); 174 if (retval < 0) 175 goto done; 176 177 /* wait till tune operation has completed */ 178 timeout = jiffies + msecs_to_jiffies(tune_timeout); 179 do { 180 retval = si470x_get_register(radio, STATUSRSSI); 181 if (retval < 0) 182 goto stop; 183 timed_out = time_after(jiffies, timeout); 184 } while (((radio->registers[STATUSRSSI] & STATUSRSSI_STC) == 0) && 185 (!timed_out)); 186 if ((radio->registers[STATUSRSSI] & STATUSRSSI_STC) == 0) 187 dev_warn(&radio->videodev->dev, "tune does not complete\n"); 188 if (timed_out) 189 dev_warn(&radio->videodev->dev, 190 "tune timed out after %u ms\n", tune_timeout); 191 192 stop: 193 /* stop tuning */ 194 radio->registers[CHANNEL] &= ~CHANNEL_TUNE; 195 retval = si470x_set_register(radio, CHANNEL); 196 197 done: 198 return retval; 199 } 200 201 202 /* 203 * si470x_get_freq - get the frequency 204 */ 205 static int si470x_get_freq(struct si470x_device *radio, unsigned int *freq) 206 { 207 unsigned int spacing, band_bottom; 208 unsigned short chan; 209 int retval; 210 211 /* Spacing (kHz) */ 212 switch ((radio->registers[SYSCONFIG2] & SYSCONFIG2_SPACE) >> 4) { 213 /* 0: 200 kHz (USA, Australia) */ 214 case 0: 215 spacing = 0.200 * FREQ_MUL; break; 216 /* 1: 100 kHz (Europe, Japan) */ 217 case 1: 218 spacing = 0.100 * FREQ_MUL; break; 219 /* 2: 50 kHz */ 220 default: 221 spacing = 0.050 * FREQ_MUL; break; 222 }; 223 224 /* Bottom of Band (MHz) */ 225 switch ((radio->registers[SYSCONFIG2] & SYSCONFIG2_BAND) >> 6) { 226 /* 0: 87.5 - 108 MHz (USA, Europe) */ 227 case 0: 228 band_bottom = 87.5 * FREQ_MUL; break; 229 /* 1: 76 - 108 MHz (Japan wide band) */ 230 default: 231 band_bottom = 76 * FREQ_MUL; break; 232 /* 2: 76 - 90 MHz (Japan) */ 233 case 2: 234 band_bottom = 76 * FREQ_MUL; break; 235 }; 236 237 /* read channel */ 238 retval = si470x_get_register(radio, READCHAN); 239 chan = radio->registers[READCHAN] & READCHAN_READCHAN; 240 241 /* Frequency (MHz) = Spacing (kHz) x Channel + Bottom of Band (MHz) */ 242 *freq = chan * spacing + band_bottom; 243 244 return retval; 245 } 246 247 248 /* 249 * si470x_set_freq - set the frequency 250 */ 251 int si470x_set_freq(struct si470x_device *radio, unsigned int freq) 252 { 253 unsigned int spacing, band_bottom; 254 unsigned short chan; 255 256 /* Spacing (kHz) */ 257 switch ((radio->registers[SYSCONFIG2] & SYSCONFIG2_SPACE) >> 4) { 258 /* 0: 200 kHz (USA, Australia) */ 259 case 0: 260 spacing = 0.200 * FREQ_MUL; break; 261 /* 1: 100 kHz (Europe, Japan) */ 262 case 1: 263 spacing = 0.100 * FREQ_MUL; break; 264 /* 2: 50 kHz */ 265 default: 266 spacing = 0.050 * FREQ_MUL; break; 267 }; 268 269 /* Bottom of Band (MHz) */ 270 switch ((radio->registers[SYSCONFIG2] & SYSCONFIG2_BAND) >> 6) { 271 /* 0: 87.5 - 108 MHz (USA, Europe) */ 272 case 0: 273 band_bottom = 87.5 * FREQ_MUL; break; 274 /* 1: 76 - 108 MHz (Japan wide band) */ 275 default: 276 band_bottom = 76 * FREQ_MUL; break; 277 /* 2: 76 - 90 MHz (Japan) */ 278 case 2: 279 band_bottom = 76 * FREQ_MUL; break; 280 }; 281 282 /* Chan = [ Freq (Mhz) - Bottom of Band (MHz) ] / Spacing (kHz) */ 283 chan = (freq - band_bottom) / spacing; 284 285 return si470x_set_chan(radio, chan); 286 } 287 288 289 /* 290 * si470x_set_seek - set seek 291 */ 292 static int si470x_set_seek(struct si470x_device *radio, 293 unsigned int wrap_around, unsigned int seek_upward) 294 { 295 int retval = 0; 296 unsigned long timeout; 297 bool timed_out = 0; 298 299 /* start seeking */ 300 radio->registers[POWERCFG] |= POWERCFG_SEEK; 301 if (wrap_around == 1) 302 radio->registers[POWERCFG] &= ~POWERCFG_SKMODE; 303 else 304 radio->registers[POWERCFG] |= POWERCFG_SKMODE; 305 if (seek_upward == 1) 306 radio->registers[POWERCFG] |= POWERCFG_SEEKUP; 307 else 308 radio->registers[POWERCFG] &= ~POWERCFG_SEEKUP; 309 retval = si470x_set_register(radio, POWERCFG); 310 if (retval < 0) 311 goto done; 312 313 /* wait till seek operation has completed */ 314 timeout = jiffies + msecs_to_jiffies(seek_timeout); 315 do { 316 retval = si470x_get_register(radio, STATUSRSSI); 317 if (retval < 0) 318 goto stop; 319 timed_out = time_after(jiffies, timeout); 320 } while (((radio->registers[STATUSRSSI] & STATUSRSSI_STC) == 0) && 321 (!timed_out)); 322 if ((radio->registers[STATUSRSSI] & STATUSRSSI_STC) == 0) 323 dev_warn(&radio->videodev->dev, "seek does not complete\n"); 324 if (radio->registers[STATUSRSSI] & STATUSRSSI_SF) 325 dev_warn(&radio->videodev->dev, 326 "seek failed / band limit reached\n"); 327 if (timed_out) 328 dev_warn(&radio->videodev->dev, 329 "seek timed out after %u ms\n", seek_timeout); 330 331 stop: 332 /* stop seeking */ 333 radio->registers[POWERCFG] &= ~POWERCFG_SEEK; 334 retval = si470x_set_register(radio, POWERCFG); 335 336 done: 337 /* try again, if timed out */ 338 if ((retval == 0) && timed_out) 339 retval = -EAGAIN; 340 341 return retval; 342 } 343 344 345 /* 346 * si470x_start - switch on radio 347 */ 348 int si470x_start(struct si470x_device *radio) 349 { 350 int retval; 351 352 /* powercfg */ 353 radio->registers[POWERCFG] = 354 POWERCFG_DMUTE | POWERCFG_ENABLE | POWERCFG_RDSM; 355 retval = si470x_set_register(radio, POWERCFG); 356 if (retval < 0) 357 goto done; 358 359 /* sysconfig 1 */ 360 radio->registers[SYSCONFIG1] = SYSCONFIG1_DE; 361 retval = si470x_set_register(radio, SYSCONFIG1); 362 if (retval < 0) 363 goto done; 364 365 /* sysconfig 2 */ 366 radio->registers[SYSCONFIG2] = 367 (0x3f << 8) | /* SEEKTH */ 368 ((band << 6) & SYSCONFIG2_BAND) | /* BAND */ 369 ((space << 4) & SYSCONFIG2_SPACE) | /* SPACE */ 370 15; /* VOLUME (max) */ 371 retval = si470x_set_register(radio, SYSCONFIG2); 372 if (retval < 0) 373 goto done; 374 375 /* reset last channel */ 376 retval = si470x_set_chan(radio, 377 radio->registers[CHANNEL] & CHANNEL_CHAN); 378 379 done: 380 return retval; 381 } 382 383 384 /* 385 * si470x_stop - switch off radio 386 */ 387 int si470x_stop(struct si470x_device *radio) 388 { 389 int retval; 390 391 /* sysconfig 1 */ 392 radio->registers[SYSCONFIG1] &= ~SYSCONFIG1_RDS; 393 retval = si470x_set_register(radio, SYSCONFIG1); 394 if (retval < 0) 395 goto done; 396 397 /* powercfg */ 398 radio->registers[POWERCFG] &= ~POWERCFG_DMUTE; 399 /* POWERCFG_ENABLE has to automatically go low */ 400 radio->registers[POWERCFG] |= POWERCFG_ENABLE | POWERCFG_DISABLE; 401 retval = si470x_set_register(radio, POWERCFG); 402 403 done: 404 return retval; 405 } 406 407 408 /* 409 * si470x_rds_on - switch on rds reception 410 */ 411 static int si470x_rds_on(struct si470x_device *radio) 412 { 413 int retval; 414 415 /* sysconfig 1 */ 416 radio->registers[SYSCONFIG1] |= SYSCONFIG1_RDS; 417 retval = si470x_set_register(radio, SYSCONFIG1); 418 if (retval < 0) 419 radio->registers[SYSCONFIG1] &= ~SYSCONFIG1_RDS; 420 421 return retval; 422 } 423 424 425 426 /************************************************************************** 427 * File Operations Interface 428 **************************************************************************/ 429 430 /* 431 * si470x_fops_read - read RDS data 432 */ 433 static ssize_t si470x_fops_read(struct file *file, char __user *buf, 434 size_t count, loff_t *ppos) 435 { 436 struct si470x_device *radio = video_drvdata(file); 437 int retval = 0; 438 unsigned int block_count = 0; 439 440 /* switch on rds reception */ 441 mutex_lock(&radio->lock); 442 if ((radio->registers[SYSCONFIG1] & SYSCONFIG1_RDS) == 0) 443 si470x_rds_on(radio); 444 445 /* block if no new data available */ 446 while (radio->wr_index == radio->rd_index) { 447 if (file->f_flags & O_NONBLOCK) { 448 retval = -EWOULDBLOCK; 449 goto done; 450 } 451 if (wait_event_interruptible(radio->read_queue, 452 radio->wr_index != radio->rd_index) < 0) { 453 retval = -EINTR; 454 goto done; 455 } 456 } 457 458 /* calculate block count from byte count */ 459 count /= 3; 460 461 /* copy RDS block out of internal buffer and to user buffer */ 462 mutex_lock(&radio->lock); 463 while (block_count < count) { 464 if (radio->rd_index == radio->wr_index) 465 break; 466 467 /* always transfer rds complete blocks */ 468 if (copy_to_user(buf, &radio->buffer[radio->rd_index], 3)) 469 /* retval = -EFAULT; */ 470 break; 471 472 /* increment and wrap read pointer */ 473 radio->rd_index += 3; 474 if (radio->rd_index >= radio->buf_size) 475 radio->rd_index = 0; 476 477 /* increment counters */ 478 block_count++; 479 buf += 3; 480 retval += 3; 481 } 482 483 done: 484 mutex_unlock(&radio->lock); 485 return retval; 486 } 487 488 489 /* 490 * si470x_fops_poll - poll RDS data 491 */ 492 static unsigned int si470x_fops_poll(struct file *file, 493 struct poll_table_struct *pts) 494 { 495 struct si470x_device *radio = video_drvdata(file); 496 int retval = 0; 497 498 /* switch on rds reception */ 499 500 mutex_lock(&radio->lock); 501 if ((radio->registers[SYSCONFIG1] & SYSCONFIG1_RDS) == 0) 502 si470x_rds_on(radio); 503 mutex_unlock(&radio->lock); 504 505 poll_wait(file, &radio->read_queue, pts); 506 507 if (radio->rd_index != radio->wr_index) 508 retval = POLLIN | POLLRDNORM; 509 510 return retval; 511 } 512 513 514 /* 515 * si470x_fops - file operations interface 516 */ 517 static const struct v4l2_file_operations si470x_fops = { 518 .owner = THIS_MODULE, 519 .read = si470x_fops_read, 520 .poll = si470x_fops_poll, 521 .unlocked_ioctl = video_ioctl2, 522 .open = si470x_fops_open, 523 .release = si470x_fops_release, 524 }; 525 526 527 528 /************************************************************************** 529 * Video4Linux Interface 530 **************************************************************************/ 531 532 /* 533 * si470x_vidioc_queryctrl - enumerate control items 534 */ 535 static int si470x_vidioc_queryctrl(struct file *file, void *priv, 536 struct v4l2_queryctrl *qc) 537 { 538 struct si470x_device *radio = video_drvdata(file); 539 int retval = -EINVAL; 540 541 /* abort if qc->id is below V4L2_CID_BASE */ 542 if (qc->id < V4L2_CID_BASE) 543 goto done; 544 545 /* search video control */ 546 switch (qc->id) { 547 case V4L2_CID_AUDIO_VOLUME: 548 return v4l2_ctrl_query_fill(qc, 0, 15, 1, 15); 549 case V4L2_CID_AUDIO_MUTE: 550 return v4l2_ctrl_query_fill(qc, 0, 1, 1, 1); 551 } 552 553 /* disable unsupported base controls */ 554 /* to satisfy kradio and such apps */ 555 if ((retval == -EINVAL) && (qc->id < V4L2_CID_LASTP1)) { 556 qc->flags = V4L2_CTRL_FLAG_DISABLED; 557 retval = 0; 558 } 559 560 done: 561 if (retval < 0) 562 dev_warn(&radio->videodev->dev, 563 "query controls failed with %d\n", retval); 564 return retval; 565 } 566 567 568 /* 569 * si470x_vidioc_g_ctrl - get the value of a control 570 */ 571 static int si470x_vidioc_g_ctrl(struct file *file, void *priv, 572 struct v4l2_control *ctrl) 573 { 574 struct si470x_device *radio = video_drvdata(file); 575 int retval = 0; 576 577 mutex_lock(&radio->lock); 578 /* safety checks */ 579 retval = si470x_disconnect_check(radio); 580 if (retval) 581 goto done; 582 583 switch (ctrl->id) { 584 case V4L2_CID_AUDIO_VOLUME: 585 ctrl->value = radio->registers[SYSCONFIG2] & 586 SYSCONFIG2_VOLUME; 587 break; 588 case V4L2_CID_AUDIO_MUTE: 589 ctrl->value = ((radio->registers[POWERCFG] & 590 POWERCFG_DMUTE) == 0) ? 1 : 0; 591 break; 592 default: 593 retval = -EINVAL; 594 } 595 596 done: 597 if (retval < 0) 598 dev_warn(&radio->videodev->dev, 599 "get control failed with %d\n", retval); 600 601 mutex_unlock(&radio->lock); 602 return retval; 603 } 604 605 606 /* 607 * si470x_vidioc_s_ctrl - set the value of a control 608 */ 609 static int si470x_vidioc_s_ctrl(struct file *file, void *priv, 610 struct v4l2_control *ctrl) 611 { 612 struct si470x_device *radio = video_drvdata(file); 613 int retval = 0; 614 615 mutex_lock(&radio->lock); 616 /* safety checks */ 617 retval = si470x_disconnect_check(radio); 618 if (retval) 619 goto done; 620 621 switch (ctrl->id) { 622 case V4L2_CID_AUDIO_VOLUME: 623 radio->registers[SYSCONFIG2] &= ~SYSCONFIG2_VOLUME; 624 radio->registers[SYSCONFIG2] |= ctrl->value; 625 retval = si470x_set_register(radio, SYSCONFIG2); 626 break; 627 case V4L2_CID_AUDIO_MUTE: 628 if (ctrl->value == 1) 629 radio->registers[POWERCFG] &= ~POWERCFG_DMUTE; 630 else 631 radio->registers[POWERCFG] |= POWERCFG_DMUTE; 632 retval = si470x_set_register(radio, POWERCFG); 633 break; 634 default: 635 retval = -EINVAL; 636 } 637 638 done: 639 if (retval < 0) 640 dev_warn(&radio->videodev->dev, 641 "set control failed with %d\n", retval); 642 mutex_unlock(&radio->lock); 643 return retval; 644 } 645 646 647 /* 648 * si470x_vidioc_g_audio - get audio attributes 649 */ 650 static int si470x_vidioc_g_audio(struct file *file, void *priv, 651 struct v4l2_audio *audio) 652 { 653 /* driver constants */ 654 audio->index = 0; 655 strcpy(audio->name, "Radio"); 656 audio->capability = V4L2_AUDCAP_STEREO; 657 audio->mode = 0; 658 659 return 0; 660 } 661 662 663 /* 664 * si470x_vidioc_g_tuner - get tuner attributes 665 */ 666 static int si470x_vidioc_g_tuner(struct file *file, void *priv, 667 struct v4l2_tuner *tuner) 668 { 669 struct si470x_device *radio = video_drvdata(file); 670 int retval = 0; 671 672 mutex_lock(&radio->lock); 673 /* safety checks */ 674 retval = si470x_disconnect_check(radio); 675 if (retval) 676 goto done; 677 678 if (tuner->index != 0) { 679 retval = -EINVAL; 680 goto done; 681 } 682 683 retval = si470x_get_register(radio, STATUSRSSI); 684 if (retval < 0) 685 goto done; 686 687 /* driver constants */ 688 strcpy(tuner->name, "FM"); 689 tuner->type = V4L2_TUNER_RADIO; 690 #if defined(CONFIG_USB_SI470X) || defined(CONFIG_USB_SI470X_MODULE) 691 tuner->capability = V4L2_TUNER_CAP_LOW | V4L2_TUNER_CAP_STEREO | 692 V4L2_TUNER_CAP_RDS | V4L2_TUNER_CAP_RDS_BLOCK_IO; 693 #else 694 tuner->capability = V4L2_TUNER_CAP_LOW | V4L2_TUNER_CAP_STEREO; 695 #endif 696 697 /* range limits */ 698 switch ((radio->registers[SYSCONFIG2] & SYSCONFIG2_BAND) >> 6) { 699 /* 0: 87.5 - 108 MHz (USA, Europe, default) */ 700 default: 701 tuner->rangelow = 87.5 * FREQ_MUL; 702 tuner->rangehigh = 108 * FREQ_MUL; 703 break; 704 /* 1: 76 - 108 MHz (Japan wide band) */ 705 case 1: 706 tuner->rangelow = 76 * FREQ_MUL; 707 tuner->rangehigh = 108 * FREQ_MUL; 708 break; 709 /* 2: 76 - 90 MHz (Japan) */ 710 case 2: 711 tuner->rangelow = 76 * FREQ_MUL; 712 tuner->rangehigh = 90 * FREQ_MUL; 713 break; 714 }; 715 716 /* stereo indicator == stereo (instead of mono) */ 717 if ((radio->registers[STATUSRSSI] & STATUSRSSI_ST) == 0) 718 tuner->rxsubchans = V4L2_TUNER_SUB_MONO; 719 else 720 tuner->rxsubchans = V4L2_TUNER_SUB_MONO | V4L2_TUNER_SUB_STEREO; 721 #if defined(CONFIG_USB_SI470X) || defined(CONFIG_USB_SI470X_MODULE) 722 /* If there is a reliable method of detecting an RDS channel, 723 then this code should check for that before setting this 724 RDS subchannel. */ 725 tuner->rxsubchans |= V4L2_TUNER_SUB_RDS; 726 #endif 727 728 /* mono/stereo selector */ 729 if ((radio->registers[POWERCFG] & POWERCFG_MONO) == 0) 730 tuner->audmode = V4L2_TUNER_MODE_STEREO; 731 else 732 tuner->audmode = V4L2_TUNER_MODE_MONO; 733 734 /* min is worst, max is best; signal:0..0xffff; rssi: 0..0xff */ 735 /* measured in units of dbµV in 1 db increments (max at ~75 dbµV) */ 736 tuner->signal = (radio->registers[STATUSRSSI] & STATUSRSSI_RSSI); 737 /* the ideal factor is 0xffff/75 = 873,8 */ 738 tuner->signal = (tuner->signal * 873) + (8 * tuner->signal / 10); 739 740 /* automatic frequency control: -1: freq to low, 1 freq to high */ 741 /* AFCRL does only indicate that freq. differs, not if too low/high */ 742 tuner->afc = (radio->registers[STATUSRSSI] & STATUSRSSI_AFCRL) ? 1 : 0; 743 744 done: 745 if (retval < 0) 746 dev_warn(&radio->videodev->dev, 747 "get tuner failed with %d\n", retval); 748 mutex_unlock(&radio->lock); 749 return retval; 750 } 751 752 753 /* 754 * si470x_vidioc_s_tuner - set tuner attributes 755 */ 756 static int si470x_vidioc_s_tuner(struct file *file, void *priv, 757 struct v4l2_tuner *tuner) 758 { 759 struct si470x_device *radio = video_drvdata(file); 760 int retval = 0; 761 762 mutex_lock(&radio->lock); 763 /* safety checks */ 764 retval = si470x_disconnect_check(radio); 765 if (retval) 766 goto done; 767 768 if (tuner->index != 0) 769 goto done; 770 771 /* mono/stereo selector */ 772 switch (tuner->audmode) { 773 case V4L2_TUNER_MODE_MONO: 774 radio->registers[POWERCFG] |= POWERCFG_MONO; /* force mono */ 775 break; 776 case V4L2_TUNER_MODE_STEREO: 777 radio->registers[POWERCFG] &= ~POWERCFG_MONO; /* try stereo */ 778 break; 779 default: 780 goto done; 781 } 782 783 retval = si470x_set_register(radio, POWERCFG); 784 785 done: 786 if (retval < 0) 787 dev_warn(&radio->videodev->dev, 788 "set tuner failed with %d\n", retval); 789 mutex_unlock(&radio->lock); 790 return retval; 791 } 792 793 794 /* 795 * si470x_vidioc_g_frequency - get tuner or modulator radio frequency 796 */ 797 static int si470x_vidioc_g_frequency(struct file *file, void *priv, 798 struct v4l2_frequency *freq) 799 { 800 struct si470x_device *radio = video_drvdata(file); 801 int retval = 0; 802 803 /* safety checks */ 804 mutex_lock(&radio->lock); 805 retval = si470x_disconnect_check(radio); 806 if (retval) 807 goto done; 808 809 if (freq->tuner != 0) { 810 retval = -EINVAL; 811 goto done; 812 } 813 814 freq->type = V4L2_TUNER_RADIO; 815 retval = si470x_get_freq(radio, &freq->frequency); 816 817 done: 818 if (retval < 0) 819 dev_warn(&radio->videodev->dev, 820 "get frequency failed with %d\n", retval); 821 mutex_unlock(&radio->lock); 822 return retval; 823 } 824 825 826 /* 827 * si470x_vidioc_s_frequency - set tuner or modulator radio frequency 828 */ 829 static int si470x_vidioc_s_frequency(struct file *file, void *priv, 830 struct v4l2_frequency *freq) 831 { 832 struct si470x_device *radio = video_drvdata(file); 833 int retval = 0; 834 835 mutex_lock(&radio->lock); 836 /* safety checks */ 837 retval = si470x_disconnect_check(radio); 838 if (retval) 839 goto done; 840 841 if (freq->tuner != 0) { 842 retval = -EINVAL; 843 goto done; 844 } 845 846 retval = si470x_set_freq(radio, freq->frequency); 847 848 done: 849 if (retval < 0) 850 dev_warn(&radio->videodev->dev, 851 "set frequency failed with %d\n", retval); 852 mutex_unlock(&radio->lock); 853 return retval; 854 } 855 856 857 /* 858 * si470x_vidioc_s_hw_freq_seek - set hardware frequency seek 859 */ 860 static int si470x_vidioc_s_hw_freq_seek(struct file *file, void *priv, 861 struct v4l2_hw_freq_seek *seek) 862 { 863 struct si470x_device *radio = video_drvdata(file); 864 int retval = 0; 865 866 mutex_lock(&radio->lock); 867 /* safety checks */ 868 retval = si470x_disconnect_check(radio); 869 if (retval) 870 goto done; 871 872 if (seek->tuner != 0) { 873 retval = -EINVAL; 874 goto done; 875 } 876 877 retval = si470x_set_seek(radio, seek->wrap_around, seek->seek_upward); 878 879 done: 880 if (retval < 0) 881 dev_warn(&radio->videodev->dev, 882 "set hardware frequency seek failed with %d\n", retval); 883 mutex_unlock(&radio->lock); 884 return retval; 885 } 886 887 888 /* 889 * si470x_ioctl_ops - video device ioctl operations 890 */ 891 static const struct v4l2_ioctl_ops si470x_ioctl_ops = { 892 .vidioc_querycap = si470x_vidioc_querycap, 893 .vidioc_queryctrl = si470x_vidioc_queryctrl, 894 .vidioc_g_ctrl = si470x_vidioc_g_ctrl, 895 .vidioc_s_ctrl = si470x_vidioc_s_ctrl, 896 .vidioc_g_audio = si470x_vidioc_g_audio, 897 .vidioc_g_tuner = si470x_vidioc_g_tuner, 898 .vidioc_s_tuner = si470x_vidioc_s_tuner, 899 .vidioc_g_frequency = si470x_vidioc_g_frequency, 900 .vidioc_s_frequency = si470x_vidioc_s_frequency, 901 .vidioc_s_hw_freq_seek = si470x_vidioc_s_hw_freq_seek, 902 }; 903 904 905 /* 906 * si470x_viddev_template - video device interface 907 */ 908 struct video_device si470x_viddev_template = { 909 .fops = &si470x_fops, 910 .name = DRIVER_NAME, 911 .release = video_device_release, 912 .ioctl_ops = &si470x_ioctl_ops, 913 }; 914