root/drivers/media/radio/wl128x/fmdrv_rx.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. fm_rx_reset_rds_cache
  2. fm_rx_reset_station_info
  3. fm_rx_set_freq
  4. fm_rx_set_channel_spacing
  5. fm_rx_seek
  6. fm_rx_set_volume
  7. fm_rx_get_volume
  8. fm_rx_get_band_freq_range
  9. fm_rx_get_region
  10. fm_rx_set_region
  11. fm_rx_get_mute_mode
  12. fm_config_rx_mute_reg
  13. fm_rx_set_mute_mode
  14. fm_rx_get_rfdepend_softmute
  15. fm_rx_set_rfdepend_softmute
  16. fm_rx_get_rssi_level
  17. fm_rx_set_rssi_threshold
  18. fm_rx_get_rssi_threshold
  19. fm_rx_set_stereo_mono
  20. fm_rx_get_stereo_mono
  21. fm_rx_set_deemphasis_mode
  22. fm_rx_get_deemph_mode
  23. fm_rx_set_rds_mode
  24. fm_rx_get_rds_mode
  25. fm_rx_set_rds_system
  26. fm_rx_set_af_switch
  27. fm_rx_get_af_switch

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

/* [<][>][^][v][top][bottom][index][help] */