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