1 /* 2 * FM Driver for Connectivity chip of Texas Instruments. 3 * This sub-module of FM driver implements FM RX functionality. 4 * 5 * Copyright (C) 2011 Texas Instruments 6 * Author: Raja Mani <raja_mani@ti.com> 7 * Author: Manjunatha Halli <manjunatha_halli@ti.com> 8 * 9 * This program is free software; you can redistribute it and/or modify 10 * it under the terms of the GNU General Public License version 2 as 11 * published by the Free Software Foundation. 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 #include "fmdrv.h" 25 #include "fmdrv_common.h" 26 #include "fmdrv_rx.h" 27 28 void fm_rx_reset_rds_cache(struct fmdev *fmdev) 29 { 30 fmdev->rx.rds.flag = FM_RDS_DISABLE; 31 fmdev->rx.rds.last_blk_idx = 0; 32 fmdev->rx.rds.wr_idx = 0; 33 fmdev->rx.rds.rd_idx = 0; 34 35 if (fmdev->rx.af_mode == FM_RX_RDS_AF_SWITCH_MODE_ON) 36 fmdev->irq_info.mask |= FM_LEV_EVENT; 37 } 38 39 void fm_rx_reset_station_info(struct fmdev *fmdev) 40 { 41 fmdev->rx.stat_info.picode = FM_NO_PI_CODE; 42 fmdev->rx.stat_info.afcache_size = 0; 43 fmdev->rx.stat_info.af_list_max = 0; 44 } 45 46 int fm_rx_set_freq(struct fmdev *fmdev, u32 freq) 47 { 48 unsigned long timeleft; 49 u16 payload, curr_frq, intr_flag; 50 u32 curr_frq_in_khz; 51 u32 resp_len; 52 int ret; 53 54 if (freq < fmdev->rx.region.bot_freq || freq > fmdev->rx.region.top_freq) { 55 fmerr("Invalid frequency %d\n", freq); 56 return -EINVAL; 57 } 58 59 /* Set audio enable */ 60 payload = FM_RX_AUDIO_ENABLE_I2S_AND_ANALOG; 61 62 ret = fmc_send_cmd(fmdev, AUDIO_ENABLE_SET, REG_WR, &payload, 63 sizeof(payload), NULL, NULL); 64 if (ret < 0) 65 return ret; 66 67 /* Set hilo to automatic selection */ 68 payload = FM_RX_IFFREQ_HILO_AUTOMATIC; 69 ret = fmc_send_cmd(fmdev, HILO_SET, REG_WR, &payload, 70 sizeof(payload), NULL, NULL); 71 if (ret < 0) 72 return ret; 73 74 /* Calculate frequency index and set*/ 75 payload = (freq - fmdev->rx.region.bot_freq) / FM_FREQ_MUL; 76 77 ret = fmc_send_cmd(fmdev, FREQ_SET, REG_WR, &payload, 78 sizeof(payload), NULL, NULL); 79 if (ret < 0) 80 return ret; 81 82 /* Read flags - just to clear any pending interrupts if we had */ 83 ret = fmc_send_cmd(fmdev, FLAG_GET, REG_RD, NULL, 2, NULL, NULL); 84 if (ret < 0) 85 return ret; 86 87 /* Enable FR, BL interrupts */ 88 intr_flag = fmdev->irq_info.mask; 89 fmdev->irq_info.mask = (FM_FR_EVENT | FM_BL_EVENT); 90 payload = fmdev->irq_info.mask; 91 ret = fmc_send_cmd(fmdev, INT_MASK_SET, REG_WR, &payload, 92 sizeof(payload), NULL, NULL); 93 if (ret < 0) 94 return ret; 95 96 /* Start tune */ 97 payload = FM_TUNER_PRESET_MODE; 98 ret = fmc_send_cmd(fmdev, TUNER_MODE_SET, REG_WR, &payload, 99 sizeof(payload), NULL, NULL); 100 if (ret < 0) 101 goto exit; 102 103 /* Wait for tune ended interrupt */ 104 init_completion(&fmdev->maintask_comp); 105 timeleft = wait_for_completion_timeout(&fmdev->maintask_comp, 106 FM_DRV_TX_TIMEOUT); 107 if (!timeleft) { 108 fmerr("Timeout(%d sec),didn't get tune ended int\n", 109 jiffies_to_msecs(FM_DRV_TX_TIMEOUT) / 1000); 110 ret = -ETIMEDOUT; 111 goto exit; 112 } 113 114 /* Read freq back to confirm */ 115 ret = fmc_send_cmd(fmdev, FREQ_SET, REG_RD, NULL, 2, &curr_frq, &resp_len); 116 if (ret < 0) 117 goto exit; 118 119 curr_frq = be16_to_cpu((__force __be16)curr_frq); 120 curr_frq_in_khz = (fmdev->rx.region.bot_freq + ((u32)curr_frq * FM_FREQ_MUL)); 121 122 if (curr_frq_in_khz != freq) { 123 pr_info("Frequency is set to (%d) but " 124 "requested freq is (%d)\n", curr_frq_in_khz, freq); 125 } 126 127 /* Update local cache */ 128 fmdev->rx.freq = curr_frq_in_khz; 129 exit: 130 /* Re-enable default FM interrupts */ 131 fmdev->irq_info.mask = intr_flag; 132 payload = fmdev->irq_info.mask; 133 ret = fmc_send_cmd(fmdev, INT_MASK_SET, REG_WR, &payload, 134 sizeof(payload), NULL, NULL); 135 if (ret < 0) 136 return ret; 137 138 /* Reset RDS cache and current station pointers */ 139 fm_rx_reset_rds_cache(fmdev); 140 fm_rx_reset_station_info(fmdev); 141 142 return ret; 143 } 144 145 static int fm_rx_set_channel_spacing(struct fmdev *fmdev, u32 spacing) 146 { 147 u16 payload; 148 int ret; 149 150 if (spacing > 0 && spacing <= 50000) 151 spacing = FM_CHANNEL_SPACING_50KHZ; 152 else if (spacing > 50000 && spacing <= 100000) 153 spacing = FM_CHANNEL_SPACING_100KHZ; 154 else 155 spacing = FM_CHANNEL_SPACING_200KHZ; 156 157 /* set channel spacing */ 158 payload = spacing; 159 ret = fmc_send_cmd(fmdev, CHANL_BW_SET, REG_WR, &payload, 160 sizeof(payload), NULL, NULL); 161 if (ret < 0) 162 return ret; 163 164 fmdev->rx.region.chanl_space = spacing * FM_FREQ_MUL; 165 166 return ret; 167 } 168 169 int fm_rx_seek(struct fmdev *fmdev, u32 seek_upward, 170 u32 wrap_around, u32 spacing) 171 { 172 u32 resp_len; 173 u16 curr_frq, next_frq, last_frq; 174 u16 payload, int_reason, intr_flag; 175 u16 offset, space_idx; 176 unsigned long timeleft; 177 int ret; 178 179 /* Set channel spacing */ 180 ret = fm_rx_set_channel_spacing(fmdev, spacing); 181 if (ret < 0) { 182 fmerr("Failed to set channel spacing\n"); 183 return ret; 184 } 185 186 /* Read the current frequency from chip */ 187 ret = fmc_send_cmd(fmdev, FREQ_SET, REG_RD, NULL, 188 sizeof(curr_frq), &curr_frq, &resp_len); 189 if (ret < 0) 190 return ret; 191 192 curr_frq = be16_to_cpu((__force __be16)curr_frq); 193 last_frq = (fmdev->rx.region.top_freq - fmdev->rx.region.bot_freq) / FM_FREQ_MUL; 194 195 /* Check the offset in order to be aligned to the channel spacing*/ 196 space_idx = fmdev->rx.region.chanl_space / FM_FREQ_MUL; 197 offset = curr_frq % space_idx; 198 199 next_frq = seek_upward ? curr_frq + space_idx /* Seek Up */ : 200 curr_frq - space_idx /* Seek Down */ ; 201 202 /* 203 * Add or subtract offset in order to stay aligned to the channel 204 * spacing. 205 */ 206 if ((short)next_frq < 0) 207 next_frq = last_frq - offset; 208 else if (next_frq > last_frq) 209 next_frq = 0 + offset; 210 211 again: 212 /* Set calculated next frequency to perform seek */ 213 payload = next_frq; 214 ret = fmc_send_cmd(fmdev, FREQ_SET, REG_WR, &payload, 215 sizeof(payload), NULL, NULL); 216 if (ret < 0) 217 return ret; 218 219 /* Set search direction (0:Seek Down, 1:Seek Up) */ 220 payload = (seek_upward ? FM_SEARCH_DIRECTION_UP : FM_SEARCH_DIRECTION_DOWN); 221 ret = fmc_send_cmd(fmdev, SEARCH_DIR_SET, REG_WR, &payload, 222 sizeof(payload), NULL, NULL); 223 if (ret < 0) 224 return ret; 225 226 /* Read flags - just to clear any pending interrupts if we had */ 227 ret = fmc_send_cmd(fmdev, FLAG_GET, REG_RD, NULL, 2, NULL, NULL); 228 if (ret < 0) 229 return ret; 230 231 /* Enable FR, BL interrupts */ 232 intr_flag = fmdev->irq_info.mask; 233 fmdev->irq_info.mask = (FM_FR_EVENT | FM_BL_EVENT); 234 payload = fmdev->irq_info.mask; 235 ret = fmc_send_cmd(fmdev, INT_MASK_SET, REG_WR, &payload, 236 sizeof(payload), NULL, NULL); 237 if (ret < 0) 238 return ret; 239 240 /* Start seek */ 241 payload = FM_TUNER_AUTONOMOUS_SEARCH_MODE; 242 ret = fmc_send_cmd(fmdev, TUNER_MODE_SET, REG_WR, &payload, 243 sizeof(payload), NULL, NULL); 244 if (ret < 0) 245 return ret; 246 247 /* Wait for tune ended/band limit reached interrupt */ 248 init_completion(&fmdev->maintask_comp); 249 timeleft = wait_for_completion_timeout(&fmdev->maintask_comp, 250 FM_DRV_RX_SEEK_TIMEOUT); 251 if (!timeleft) { 252 fmerr("Timeout(%d sec),didn't get tune ended int\n", 253 jiffies_to_msecs(FM_DRV_RX_SEEK_TIMEOUT) / 1000); 254 return -ENODATA; 255 } 256 257 int_reason = fmdev->irq_info.flag & (FM_TUNE_COMPLETE | FM_BAND_LIMIT); 258 259 /* Re-enable default FM interrupts */ 260 fmdev->irq_info.mask = intr_flag; 261 payload = fmdev->irq_info.mask; 262 ret = fmc_send_cmd(fmdev, INT_MASK_SET, REG_WR, &payload, 263 sizeof(payload), NULL, NULL); 264 if (ret < 0) 265 return ret; 266 267 if (int_reason & FM_BL_EVENT) { 268 if (wrap_around == 0) { 269 fmdev->rx.freq = seek_upward ? 270 fmdev->rx.region.top_freq : 271 fmdev->rx.region.bot_freq; 272 } else { 273 fmdev->rx.freq = seek_upward ? 274 fmdev->rx.region.bot_freq : 275 fmdev->rx.region.top_freq; 276 /* Calculate frequency index to write */ 277 next_frq = (fmdev->rx.freq - 278 fmdev->rx.region.bot_freq) / FM_FREQ_MUL; 279 goto again; 280 } 281 } else { 282 /* Read freq to know where operation tune operation stopped */ 283 ret = fmc_send_cmd(fmdev, FREQ_SET, REG_RD, NULL, 2, 284 &curr_frq, &resp_len); 285 if (ret < 0) 286 return ret; 287 288 curr_frq = be16_to_cpu((__force __be16)curr_frq); 289 fmdev->rx.freq = (fmdev->rx.region.bot_freq + 290 ((u32)curr_frq * FM_FREQ_MUL)); 291 292 } 293 /* Reset RDS cache and current station pointers */ 294 fm_rx_reset_rds_cache(fmdev); 295 fm_rx_reset_station_info(fmdev); 296 297 return ret; 298 } 299 300 int fm_rx_set_volume(struct fmdev *fmdev, u16 vol_to_set) 301 { 302 u16 payload; 303 int ret; 304 305 if (fmdev->curr_fmmode != FM_MODE_RX) 306 return -EPERM; 307 308 if (vol_to_set > FM_RX_VOLUME_MAX) { 309 fmerr("Volume is not within(%d-%d) range\n", 310 FM_RX_VOLUME_MIN, FM_RX_VOLUME_MAX); 311 return -EINVAL; 312 } 313 vol_to_set *= FM_RX_VOLUME_GAIN_STEP; 314 315 payload = vol_to_set; 316 ret = fmc_send_cmd(fmdev, VOLUME_SET, REG_WR, &payload, 317 sizeof(payload), NULL, NULL); 318 if (ret < 0) 319 return ret; 320 321 fmdev->rx.volume = vol_to_set; 322 return ret; 323 } 324 325 /* Get volume */ 326 int fm_rx_get_volume(struct fmdev *fmdev, u16 *curr_vol) 327 { 328 if (fmdev->curr_fmmode != FM_MODE_RX) 329 return -EPERM; 330 331 if (curr_vol == NULL) { 332 fmerr("Invalid memory\n"); 333 return -ENOMEM; 334 } 335 336 *curr_vol = fmdev->rx.volume / FM_RX_VOLUME_GAIN_STEP; 337 338 return 0; 339 } 340 341 /* To get current band's bottom and top frequency */ 342 int fm_rx_get_band_freq_range(struct fmdev *fmdev, u32 *bot_freq, u32 *top_freq) 343 { 344 if (bot_freq != NULL) 345 *bot_freq = fmdev->rx.region.bot_freq; 346 347 if (top_freq != NULL) 348 *top_freq = fmdev->rx.region.top_freq; 349 350 return 0; 351 } 352 353 /* Returns current band index (0-Europe/US; 1-Japan) */ 354 void fm_rx_get_region(struct fmdev *fmdev, u8 *region) 355 { 356 *region = fmdev->rx.region.fm_band; 357 } 358 359 /* Sets band (0-Europe/US; 1-Japan) */ 360 int fm_rx_set_region(struct fmdev *fmdev, u8 region_to_set) 361 { 362 u16 payload; 363 u32 new_frq = 0; 364 int ret; 365 366 if (region_to_set != FM_BAND_EUROPE_US && 367 region_to_set != FM_BAND_JAPAN) { 368 fmerr("Invalid band\n"); 369 return -EINVAL; 370 } 371 372 if (fmdev->rx.region.fm_band == region_to_set) { 373 fmerr("Requested band is already configured\n"); 374 return 0; 375 } 376 377 /* Send cmd to set the band */ 378 payload = (u16)region_to_set; 379 ret = fmc_send_cmd(fmdev, BAND_SET, REG_WR, &payload, 380 sizeof(payload), NULL, NULL); 381 if (ret < 0) 382 return ret; 383 384 fmc_update_region_info(fmdev, region_to_set); 385 386 /* Check whether current RX frequency is within band boundary */ 387 if (fmdev->rx.freq < fmdev->rx.region.bot_freq) 388 new_frq = fmdev->rx.region.bot_freq; 389 else if (fmdev->rx.freq > fmdev->rx.region.top_freq) 390 new_frq = fmdev->rx.region.top_freq; 391 392 if (new_frq) { 393 fmdbg("Current freq is not within band limit boundary," 394 "switching to %d KHz\n", new_frq); 395 /* Current RX frequency is not in range. So, update it */ 396 ret = fm_rx_set_freq(fmdev, new_frq); 397 } 398 399 return ret; 400 } 401 402 /* Reads current mute mode (Mute Off/On/Attenuate)*/ 403 int fm_rx_get_mute_mode(struct fmdev *fmdev, u8 *curr_mute_mode) 404 { 405 if (fmdev->curr_fmmode != FM_MODE_RX) 406 return -EPERM; 407 408 if (curr_mute_mode == NULL) { 409 fmerr("Invalid memory\n"); 410 return -ENOMEM; 411 } 412 413 *curr_mute_mode = fmdev->rx.mute_mode; 414 415 return 0; 416 } 417 418 static int fm_config_rx_mute_reg(struct fmdev *fmdev) 419 { 420 u16 payload, muteval; 421 int ret; 422 423 muteval = 0; 424 switch (fmdev->rx.mute_mode) { 425 case FM_MUTE_ON: 426 muteval = FM_RX_AC_MUTE_MODE; 427 break; 428 429 case FM_MUTE_OFF: 430 muteval = FM_RX_UNMUTE_MODE; 431 break; 432 433 case FM_MUTE_ATTENUATE: 434 muteval = FM_RX_SOFT_MUTE_FORCE_MODE; 435 break; 436 } 437 if (fmdev->rx.rf_depend_mute == FM_RX_RF_DEPENDENT_MUTE_ON) 438 muteval |= FM_RX_RF_DEP_MODE; 439 else 440 muteval &= ~FM_RX_RF_DEP_MODE; 441 442 payload = muteval; 443 ret = fmc_send_cmd(fmdev, MUTE_STATUS_SET, REG_WR, &payload, 444 sizeof(payload), NULL, NULL); 445 if (ret < 0) 446 return ret; 447 448 return 0; 449 } 450 451 /* Configures mute mode (Mute Off/On/Attenuate) */ 452 int fm_rx_set_mute_mode(struct fmdev *fmdev, u8 mute_mode_toset) 453 { 454 u8 org_state; 455 int ret; 456 457 if (fmdev->rx.mute_mode == mute_mode_toset) 458 return 0; 459 460 org_state = fmdev->rx.mute_mode; 461 fmdev->rx.mute_mode = mute_mode_toset; 462 463 ret = fm_config_rx_mute_reg(fmdev); 464 if (ret < 0) { 465 fmdev->rx.mute_mode = org_state; 466 return ret; 467 } 468 469 return 0; 470 } 471 472 /* Gets RF dependent soft mute mode enable/disable status */ 473 int fm_rx_get_rfdepend_softmute(struct fmdev *fmdev, u8 *curr_mute_mode) 474 { 475 if (fmdev->curr_fmmode != FM_MODE_RX) 476 return -EPERM; 477 478 if (curr_mute_mode == NULL) { 479 fmerr("Invalid memory\n"); 480 return -ENOMEM; 481 } 482 483 *curr_mute_mode = fmdev->rx.rf_depend_mute; 484 485 return 0; 486 } 487 488 /* Sets RF dependent soft mute mode */ 489 int fm_rx_set_rfdepend_softmute(struct fmdev *fmdev, u8 rfdepend_mute) 490 { 491 u8 org_state; 492 int ret; 493 494 if (fmdev->curr_fmmode != FM_MODE_RX) 495 return -EPERM; 496 497 if (rfdepend_mute != FM_RX_RF_DEPENDENT_MUTE_ON && 498 rfdepend_mute != FM_RX_RF_DEPENDENT_MUTE_OFF) { 499 fmerr("Invalid RF dependent soft mute\n"); 500 return -EINVAL; 501 } 502 if (fmdev->rx.rf_depend_mute == rfdepend_mute) 503 return 0; 504 505 org_state = fmdev->rx.rf_depend_mute; 506 fmdev->rx.rf_depend_mute = rfdepend_mute; 507 508 ret = fm_config_rx_mute_reg(fmdev); 509 if (ret < 0) { 510 fmdev->rx.rf_depend_mute = org_state; 511 return ret; 512 } 513 514 return 0; 515 } 516 517 /* Returns the signal strength level of current channel */ 518 int fm_rx_get_rssi_level(struct fmdev *fmdev, u16 *rssilvl) 519 { 520 __be16 curr_rssi_lel; 521 u32 resp_len; 522 int ret; 523 524 if (rssilvl == NULL) { 525 fmerr("Invalid memory\n"); 526 return -ENOMEM; 527 } 528 /* Read current RSSI level */ 529 ret = fmc_send_cmd(fmdev, RSSI_LVL_GET, REG_RD, NULL, 2, 530 &curr_rssi_lel, &resp_len); 531 if (ret < 0) 532 return ret; 533 534 *rssilvl = be16_to_cpu(curr_rssi_lel); 535 536 return 0; 537 } 538 539 /* 540 * Sets the signal strength level that once reached 541 * will stop the auto search process 542 */ 543 int fm_rx_set_rssi_threshold(struct fmdev *fmdev, short rssi_lvl_toset) 544 { 545 u16 payload; 546 int ret; 547 548 if (rssi_lvl_toset < FM_RX_RSSI_THRESHOLD_MIN || 549 rssi_lvl_toset > FM_RX_RSSI_THRESHOLD_MAX) { 550 fmerr("Invalid RSSI threshold level\n"); 551 return -EINVAL; 552 } 553 payload = (u16)rssi_lvl_toset; 554 ret = fmc_send_cmd(fmdev, SEARCH_LVL_SET, REG_WR, &payload, 555 sizeof(payload), NULL, NULL); 556 if (ret < 0) 557 return ret; 558 559 fmdev->rx.rssi_threshold = rssi_lvl_toset; 560 561 return 0; 562 } 563 564 /* Returns current RX RSSI threshold value */ 565 int fm_rx_get_rssi_threshold(struct fmdev *fmdev, short *curr_rssi_lvl) 566 { 567 if (fmdev->curr_fmmode != FM_MODE_RX) 568 return -EPERM; 569 570 if (curr_rssi_lvl == NULL) { 571 fmerr("Invalid memory\n"); 572 return -ENOMEM; 573 } 574 575 *curr_rssi_lvl = fmdev->rx.rssi_threshold; 576 577 return 0; 578 } 579 580 /* Sets RX stereo/mono modes */ 581 int fm_rx_set_stereo_mono(struct fmdev *fmdev, u16 mode) 582 { 583 u16 payload; 584 int ret; 585 586 if (mode != FM_STEREO_MODE && mode != FM_MONO_MODE) { 587 fmerr("Invalid mode\n"); 588 return -EINVAL; 589 } 590 591 /* Set stereo/mono mode */ 592 payload = (u16)mode; 593 ret = fmc_send_cmd(fmdev, MOST_MODE_SET, REG_WR, &payload, 594 sizeof(payload), NULL, NULL); 595 if (ret < 0) 596 return ret; 597 598 /* Set stereo blending mode */ 599 payload = FM_STEREO_SOFT_BLEND; 600 ret = fmc_send_cmd(fmdev, MOST_BLEND_SET, REG_WR, &payload, 601 sizeof(payload), NULL, NULL); 602 if (ret < 0) 603 return ret; 604 605 return 0; 606 } 607 608 /* Gets current RX stereo/mono mode */ 609 int fm_rx_get_stereo_mono(struct fmdev *fmdev, u16 *mode) 610 { 611 __be16 curr_mode; 612 u32 resp_len; 613 int ret; 614 615 if (mode == NULL) { 616 fmerr("Invalid memory\n"); 617 return -ENOMEM; 618 } 619 620 ret = fmc_send_cmd(fmdev, MOST_MODE_SET, REG_RD, NULL, 2, 621 &curr_mode, &resp_len); 622 if (ret < 0) 623 return ret; 624 625 *mode = be16_to_cpu(curr_mode); 626 627 return 0; 628 } 629 630 /* Choose RX de-emphasis filter mode (50us/75us) */ 631 int fm_rx_set_deemphasis_mode(struct fmdev *fmdev, u16 mode) 632 { 633 u16 payload; 634 int ret; 635 636 if (fmdev->curr_fmmode != FM_MODE_RX) 637 return -EPERM; 638 639 if (mode != FM_RX_EMPHASIS_FILTER_50_USEC && 640 mode != FM_RX_EMPHASIS_FILTER_75_USEC) { 641 fmerr("Invalid rx de-emphasis mode (%d)\n", mode); 642 return -EINVAL; 643 } 644 645 payload = mode; 646 ret = fmc_send_cmd(fmdev, DEMPH_MODE_SET, REG_WR, &payload, 647 sizeof(payload), NULL, NULL); 648 if (ret < 0) 649 return ret; 650 651 fmdev->rx.deemphasis_mode = mode; 652 653 return 0; 654 } 655 656 /* Gets current RX de-emphasis filter mode */ 657 int fm_rx_get_deemph_mode(struct fmdev *fmdev, u16 *curr_deemphasis_mode) 658 { 659 if (fmdev->curr_fmmode != FM_MODE_RX) 660 return -EPERM; 661 662 if (curr_deemphasis_mode == NULL) { 663 fmerr("Invalid memory\n"); 664 return -ENOMEM; 665 } 666 667 *curr_deemphasis_mode = fmdev->rx.deemphasis_mode; 668 669 return 0; 670 } 671 672 /* Enable/Disable RX RDS */ 673 int fm_rx_set_rds_mode(struct fmdev *fmdev, u8 rds_en_dis) 674 { 675 u16 payload; 676 int ret; 677 678 if (rds_en_dis != FM_RDS_ENABLE && rds_en_dis != FM_RDS_DISABLE) { 679 fmerr("Invalid rds option\n"); 680 return -EINVAL; 681 } 682 683 if (rds_en_dis == FM_RDS_ENABLE 684 && fmdev->rx.rds.flag == FM_RDS_DISABLE) { 685 /* Turn on RX RDS and RDS circuit */ 686 payload = FM_RX_PWR_SET_FM_AND_RDS_BLK_ON; 687 ret = fmc_send_cmd(fmdev, POWER_SET, REG_WR, &payload, 688 sizeof(payload), NULL, NULL); 689 if (ret < 0) 690 return ret; 691 692 /* Clear and reset RDS FIFO */ 693 payload = FM_RX_RDS_FLUSH_FIFO; 694 ret = fmc_send_cmd(fmdev, RDS_CNTRL_SET, REG_WR, &payload, 695 sizeof(payload), NULL, NULL); 696 if (ret < 0) 697 return ret; 698 699 /* Read flags - just to clear any pending interrupts. */ 700 ret = fmc_send_cmd(fmdev, FLAG_GET, REG_RD, NULL, 2, 701 NULL, NULL); 702 if (ret < 0) 703 return ret; 704 705 /* Set RDS FIFO threshold value */ 706 payload = FM_RX_RDS_FIFO_THRESHOLD; 707 ret = fmc_send_cmd(fmdev, RDS_MEM_SET, REG_WR, &payload, 708 sizeof(payload), NULL, NULL); 709 if (ret < 0) 710 return ret; 711 712 /* Enable RDS interrupt */ 713 fmdev->irq_info.mask |= FM_RDS_EVENT; 714 payload = fmdev->irq_info.mask; 715 ret = fmc_send_cmd(fmdev, INT_MASK_SET, REG_WR, &payload, 716 sizeof(payload), NULL, NULL); 717 if (ret < 0) { 718 fmdev->irq_info.mask &= ~FM_RDS_EVENT; 719 return ret; 720 } 721 722 /* Update our local flag */ 723 fmdev->rx.rds.flag = FM_RDS_ENABLE; 724 } else if (rds_en_dis == FM_RDS_DISABLE 725 && fmdev->rx.rds.flag == FM_RDS_ENABLE) { 726 /* Turn off RX RDS */ 727 payload = FM_RX_PWR_SET_FM_ON_RDS_OFF; 728 ret = fmc_send_cmd(fmdev, POWER_SET, REG_WR, &payload, 729 sizeof(payload), NULL, NULL); 730 if (ret < 0) 731 return ret; 732 733 /* Reset RDS pointers */ 734 fmdev->rx.rds.last_blk_idx = 0; 735 fmdev->rx.rds.wr_idx = 0; 736 fmdev->rx.rds.rd_idx = 0; 737 fm_rx_reset_station_info(fmdev); 738 739 /* Update RDS local cache */ 740 fmdev->irq_info.mask &= ~(FM_RDS_EVENT); 741 fmdev->rx.rds.flag = FM_RDS_DISABLE; 742 } 743 744 return 0; 745 } 746 747 /* Returns current RX RDS enable/disable status */ 748 int fm_rx_get_rds_mode(struct fmdev *fmdev, u8 *curr_rds_en_dis) 749 { 750 if (fmdev->curr_fmmode != FM_MODE_RX) 751 return -EPERM; 752 753 if (curr_rds_en_dis == NULL) { 754 fmerr("Invalid memory\n"); 755 return -ENOMEM; 756 } 757 758 *curr_rds_en_dis = fmdev->rx.rds.flag; 759 760 return 0; 761 } 762 763 /* Sets RDS operation mode (RDS/RDBS) */ 764 int fm_rx_set_rds_system(struct fmdev *fmdev, u8 rds_mode) 765 { 766 u16 payload; 767 int ret; 768 769 if (fmdev->curr_fmmode != FM_MODE_RX) 770 return -EPERM; 771 772 if (rds_mode != FM_RDS_SYSTEM_RDS && rds_mode != FM_RDS_SYSTEM_RBDS) { 773 fmerr("Invalid rds mode\n"); 774 return -EINVAL; 775 } 776 /* Set RDS operation mode */ 777 payload = (u16)rds_mode; 778 ret = fmc_send_cmd(fmdev, RDS_SYSTEM_SET, REG_WR, &payload, 779 sizeof(payload), NULL, NULL); 780 if (ret < 0) 781 return ret; 782 783 fmdev->rx.rds_mode = rds_mode; 784 785 return 0; 786 } 787 788 /* Returns current RDS operation mode */ 789 int fm_rx_get_rds_system(struct fmdev *fmdev, u8 *rds_mode) 790 { 791 if (fmdev->curr_fmmode != FM_MODE_RX) 792 return -EPERM; 793 794 if (rds_mode == NULL) { 795 fmerr("Invalid memory\n"); 796 return -ENOMEM; 797 } 798 799 *rds_mode = fmdev->rx.rds_mode; 800 801 return 0; 802 } 803 804 /* Configures Alternate Frequency switch mode */ 805 int fm_rx_set_af_switch(struct fmdev *fmdev, u8 af_mode) 806 { 807 u16 payload; 808 int ret; 809 810 if (fmdev->curr_fmmode != FM_MODE_RX) 811 return -EPERM; 812 813 if (af_mode != FM_RX_RDS_AF_SWITCH_MODE_ON && 814 af_mode != FM_RX_RDS_AF_SWITCH_MODE_OFF) { 815 fmerr("Invalid af mode\n"); 816 return -EINVAL; 817 } 818 /* Enable/disable low RSSI interrupt based on af_mode */ 819 if (af_mode == FM_RX_RDS_AF_SWITCH_MODE_ON) 820 fmdev->irq_info.mask |= FM_LEV_EVENT; 821 else 822 fmdev->irq_info.mask &= ~FM_LEV_EVENT; 823 824 payload = fmdev->irq_info.mask; 825 ret = fmc_send_cmd(fmdev, INT_MASK_SET, REG_WR, &payload, 826 sizeof(payload), NULL, NULL); 827 if (ret < 0) 828 return ret; 829 830 fmdev->rx.af_mode = af_mode; 831 832 return 0; 833 } 834 835 /* Returns Alternate Frequency switch status */ 836 int fm_rx_get_af_switch(struct fmdev *fmdev, u8 *af_mode) 837 { 838 if (fmdev->curr_fmmode != FM_MODE_RX) 839 return -EPERM; 840 841 if (af_mode == NULL) { 842 fmerr("Invalid memory\n"); 843 return -ENOMEM; 844 } 845 846 *af_mode = fmdev->rx.af_mode; 847 848 return 0; 849 } 850