static int fm_config_rx_mute_reg(struct fmdev *fmdev) { u16 payload, muteval; int ret; muteval = 0; switch (fmdev->rx.mute_mode) { case FM_MUTE_ON: muteval = FM_RX_AC_MUTE_MODE; break; case FM_MUTE_OFF: muteval = FM_RX_UNMUTE_MODE; break; case FM_MUTE_ATTENUATE: muteval = FM_RX_SOFT_MUTE_FORCE_MODE; break; } if (fmdev->rx.rf_depend_mute == FM_RX_RF_DEPENDENT_MUTE_ON) muteval |= FM_RX_RF_DEP_MODE; else muteval &= ~FM_RX_RF_DEP_MODE; payload = muteval; ret = fmc_send_cmd(fmdev, MUTE_STATUS_SET, REG_WR, &payload, sizeof(payload), NULL, NULL); if (ret < 0) return ret; return 0; }
/* * Sets FM TX pre-emphasis filter value (OFF, 50us, or 75us) * Convert V4L2 specified filter values to chip specific filter values. */ u32 fm_tx_set_preemph_filter(struct fmdev *fmdev, u32 preemphasis) { struct fmtx_data *tx = &fmdev->tx_data; u16 payload; u32 ret; if (fmdev->curr_fmmode != FM_MODE_TX) return -EPERM; switch (preemphasis) { case V4L2_PREEMPHASIS_DISABLED: payload = FM_TX_PREEMPH_OFF; break; case V4L2_PREEMPHASIS_50_uS: payload = FM_TX_PREEMPH_50US; break; case V4L2_PREEMPHASIS_75_uS: payload = FM_TX_PREEMPH_75US; break; } ret = fmc_send_cmd(fmdev, PREMPH_SET, REG_WR, &payload, sizeof(payload), NULL, NULL); if (ret < 0) return ret; tx->preemph = payload; return ret; }
int fm_rx_set_af_switch(struct fmdev *fmdev, u8 af_mode) { u16 payload; int ret; if (fmdev->curr_fmmode != FM_MODE_RX) return -EPERM; if (af_mode != FM_RX_RDS_AF_SWITCH_MODE_ON && af_mode != FM_RX_RDS_AF_SWITCH_MODE_OFF) { fmerr("Invalid af mode\n"); return -EINVAL; } if (af_mode == FM_RX_RDS_AF_SWITCH_MODE_ON) fmdev->irq_info.mask |= FM_LEV_EVENT; else fmdev->irq_info.mask &= ~FM_LEV_EVENT; payload = fmdev->irq_info.mask; ret = fmc_send_cmd(fmdev, INT_MASK_SET, REG_WR, &payload, sizeof(payload), NULL, NULL); if (ret < 0) return ret; fmdev->rx.af_mode = af_mode; return 0; }
/* Set TX power level */ u32 fm_tx_set_pwr_lvl(struct fmdev *fmdev, u8 new_pwr_lvl) { u16 payload; struct fmtx_data *tx = &fmdev->tx_data; u32 ret; if (fmdev->curr_fmmode != FM_MODE_TX) return -EPERM; fmdbg("tx: pwr_level_to_set %ld\n", (long int)new_pwr_lvl); /* If the core isn't ready update global variable */ if (!test_bit(FM_CORE_READY, &fmdev->flag)) { tx->pwr_lvl = new_pwr_lvl; return 0; } /* Set power level: Application will specify power level value in * units of dB/uV, whereas range and step are specific to FM chip. * For TI's WL chips, convert application specified power level value * to chip specific value by subtracting 122 from it. Refer to TI FM * data sheet for details. * */ payload = (FM_PWR_LVL_HIGH - new_pwr_lvl); ret = fmc_send_cmd(fmdev, POWER_LEV_SET, REG_WR, &payload, sizeof(payload), NULL, NULL); if (ret < 0) return ret; /* TODO: is the power level set? */ tx->pwr_lvl = new_pwr_lvl; return 0; }
/* Gets current RX stereo/mono mode */ int fm_rx_get_audio_mode(struct fmdrv_ops *fmdev, unsigned char *mode) { int ret, len; unsigned char payload = FM_READ_1_BYTE_DATA, resp; if (fmdev->curr_fmmode != FM_MODE_RX) return -EPERM; if (mode == NULL) { V4L2_FM_DRV_ERR("(fmdrv): Invalid memory"); return -ENOMEM; } ret = fmc_send_cmd(fmdev, FM_REG_FM_CTRL, &payload, sizeof(payload), REG_RD, &fmdev->maintask_completion, &resp, &len); if((resp & FM_STEREO_SWITCH) && (resp & FM_STEREO_AUTO)) *mode = FM_SWITCH_MODE; else if(!(resp & FM_STEREO_AUTO)) *mode = FM_MONO_MODE; else if(!(resp & FM_STEREO_AUTO) && (resp & FM_STEREO_MANUAL)) *mode = FM_STEREO_MODE; else if(!(resp & FM_STEREO_SWITCH)) *mode = FM_AUTO_MODE; fmdev->rx.audio_mode = resp; return ret; }
int fm_tx_set_radio_text(struct fmdev *fmdev, u8 *rds_text, u8 rds_type) { u16 payload; int ret; if (fmdev->curr_fmmode != FM_MODE_TX) return -EPERM; fm_tx_set_rds_mode(fmdev, 0); /* Set RDS length */ set_rds_len(fmdev, rds_type, strlen(rds_text)); /* Set RDS text */ set_rds_text(fmdev, rds_text); /* Set RDS mode */ set_rds_data_mode(fmdev, 0x0); payload = 1; ret = fmc_send_cmd(fmdev, RDS_DATA_ENB, REG_WR, &payload, sizeof(payload), NULL, NULL); if (ret < 0) return ret; return 0; }
/* *Function to Get volume */ int fm_rx_get_volume(struct fmdrv_ops *fmdev, unsigned short *curr_vol) { int ret, resp_len; unsigned short resp_buf; unsigned char read_length; if (fmdev->curr_fmmode != FM_MODE_RX) return -EPERM; if (curr_vol == NULL) { V4L2_FM_DRV_ERR("(fmdrv): Invalid memory"); return -ENOMEM; } /* Read current volume */ read_length = FM_READ_2_BYTE_DATA; ret = fmc_send_cmd(fmdev, FM_REG_VOLUME_CTRL, &read_length, 1, REG_RD, &fmdev->maintask_completion, &resp_buf, &resp_len); FM_CHECK_SEND_CMD_STATUS(ret); *curr_vol = fmdev->rx.curr_volume = resp_buf; V4L2_FM_DRV_DBG(V4L2_DBG_TX, "(fmdrv) Volume read : %d", \ fmdev->rx.curr_volume); return ret; }
/* Configures Alternate Frequency switch mode */ int fm_rx_set_af_switch(struct fmdrv_ops *fmdev, u8 af_mode) { u16 payload; int ret; if (fmdev->curr_fmmode != FM_MODE_RX) return -EPERM; if (af_mode != FM_RX_RDS_AF_SWITCH_MODE_ON && af_mode != FM_RX_RDS_AF_SWITCH_MODE_OFF) { V4L2_FM_DRV_ERR("Invalid af mode\n"); return -EINVAL; } /* Enable/disable low RSSI interrupt based on af_mode */ if (af_mode == FM_RX_RDS_AF_SWITCH_MODE_ON) fmdev->rx.fm_rds_mask |= I2C_MASK_RSSI_LOW_BIT; else fmdev->rx.fm_rds_mask &= ~I2C_MASK_RSSI_LOW_BIT; payload = fmdev->rx.fm_rds_mask; ret = fmc_send_cmd(fmdev, FM_REG_FM_RDS_MSK, &fmdev->rx.fm_rds_mask, 2, REG_WR,&fmdev->maintask_completion, NULL, NULL); if (ret < 0) return ret; fmdev->rx.af_mode = af_mode; return 0; }
/* * Sets the signal strength level that once reached * will stop the auto search process */ int fm_rx_set_rssi_threshold(struct fmdrv_ops *fmdev, short rssi_lvl_toset) { u16 payload; int ret; V4L2_FM_DRV_DBG(V4L2_DBG_TX, " fm_rx_set_rssi_threshold to set is %d",\ rssi_lvl_toset); if (rssi_lvl_toset < FM_RX_RSSI_THRESHOLD_MIN || rssi_lvl_toset > FM_RX_RSSI_THRESHOLD_MAX) { V4L2_FM_DRV_ERR("Invalid RSSI threshold level\n"); return -EINVAL; } payload = (u16) rssi_lvl_toset; ret = fmc_send_cmd(fmdev, FM_REG_RSSI, &payload, sizeof(payload), REG_WR, &fmdev->maintask_completion, NULL,NULL); if (ret < 0){ V4L2_FM_DRV_ERR("Couldnot set RSSI level \n"); return ret; } fmdev->rx.curr_rssi= rssi_lvl_toset; return 0; }
u32 fm_tx_set_rds_mode(struct fmdev *fmdev, u8 rds_en_dis) { u16 payload; u32 ret; u8 rds_text[] = "WL128x Radio"; fmdbg("rds_en_dis:%d(E:%d, D:%d)\n", rds_en_dis, FM_RDS_ENABLE, FM_RDS_DISABLE); if (rds_en_dis == FM_RDS_ENABLE) { /* Set RDS length */ set_rds_len(fmdev, 2, strlen(rds_text)); /* Set RDS text */ set_rds_text(fmdev, rds_text); } /* Send command to enable RDS */ if (rds_en_dis == FM_RDS_ENABLE) payload = 0x01; else payload = 0x00; ret = fmc_send_cmd(fmdev, RDS_DATA_ENB, REG_WR, &payload, sizeof(payload), NULL, NULL); if (ret < 0) return ret; fmdev->tx_data.rds.flag = rds_en_dis; return 0; }
/* Set TX Frequency */ int fm_tx_set_freq(struct fmdev *fmdev, u32 freq_to_set) { struct fmtx_data *tx = &fmdev->tx_data; u16 payload, chanl_index; int ret; if (test_bit(FM_CORE_TX_XMITING, &fmdev->flag)) { enable_xmit(fmdev, 0); clear_bit(FM_CORE_TX_XMITING, &fmdev->flag); } /* Enable FR, BL interrupts */ payload = (FM_FR_EVENT | FM_BL_EVENT); ret = fmc_send_cmd(fmdev, INT_MASK_SET, REG_WR, &payload, sizeof(payload), NULL, NULL); if (ret < 0) return ret; tx->tx_frq = (unsigned long)freq_to_set; fmdbg("tx: freq_to_set %ld\n", (long int)tx->tx_frq); chanl_index = freq_to_set / 10; /* Set current tuner channel */ payload = chanl_index; ret = fmc_send_cmd(fmdev, CHANL_SET, REG_WR, &payload, sizeof(payload), NULL, NULL); if (ret < 0) return ret; fm_tx_set_pwr_lvl(fmdev, tx->pwr_lvl); fm_tx_set_preemph_filter(fmdev, tx->preemph); tx->audio_io = 0x01; /* I2S */ set_audio_io(fmdev); enable_xmit(fmdev, 0x01); /* Enable transmission */ tx->aud_mode = FM_STEREO_MODE; tx->rds.flag = FM_RDS_DISABLE; tx->tx_frq = freq_to_set * 1000; /* in KHz */ return 0; }
static u32 set_rds_text(struct fmdev *fmdev, u8 *rds_text) { u16 payload; u32 ret; *(u16 *)rds_text = cpu_to_be16(*(u16 *)rds_text); ret = fmc_send_cmd(fmdev, RDS_DATA_SET, REG_WR, rds_text, strlen(rds_text), NULL, NULL); if (ret < 0) return ret; /* Scroll mode */ payload = (u16)0x1; ret = fmc_send_cmd(fmdev, DISPLAY_MODE, REG_WR, &payload, sizeof(payload), NULL, NULL); if (ret < 0) return ret; return 0; }
/* Sets RX stereo/mono modes */ int fm_rx_config_audio_path(struct fmdrv_ops *fmdev, unsigned char path) { int ret; if (fmdev->curr_fmmode != FM_MODE_RX) return -EPERM; if (fmdev->rx.audio_path == path) { V4L2_FM_DRV_DBG(V4L2_DBG_TX, "(fmdrv): no change in audio path"); return 0; } /* if FM is on SCO and request to turn off FM over SCO */ if (!(path & FM_AUDIO_BT_MONO) && (fmdev->rx.pcm_reg & FM_PCM_ROUTE_ON_BIT)) { /* disable pcm_reg CB value FM routing bit */ fmdev->rx.pcm_reg &= ~FM_PCM_ROUTE_ON_BIT; } else if((path & FM_AUDIO_BT_MONO) && !(fmdev->rx.pcm_reg & FM_PCM_ROUTE_ON_BIT)) /* turn on FM via SCO */ { /* when FM to SCO active, FM enforce I2S output */ path |= FM_AUDIO_I2S; /* turn on pcm_reg CB value FM routing bit */ fmdev->rx.pcm_reg |= FM_PCM_ROUTE_ON_BIT; } /* write to PCM_ROUTE register */ ret = fmc_send_cmd(fmdev, FM_REG_PCM_ROUTE, &fmdev->rx.pcm_reg, sizeof(fmdev->rx.pcm_reg), REG_WR, &fmdev->maintask_completion, NULL, NULL); FM_CHECK_SEND_CMD_STATUS(ret); if (path & FM_AUDIO_I2S) fmdev->rx.aud_ctrl |= FM_AUDIO_I2S_ON; else fmdev->rx.aud_ctrl &= ~((unsigned short)FM_AUDIO_I2S_ON); if (path & FM_AUDIO_DAC) fmdev->rx.aud_ctrl |= FM_AUDIO_DAC_ON; else fmdev->rx.aud_ctrl &= ~((unsigned short)FM_AUDIO_DAC_ON); ret = fm_rx_set_audio_ctrl (fmdev, fmdev->rx.aud_ctrl); FM_CHECK_SEND_CMD_STATUS(ret); fmdev->rx.audio_path = path; return 0; }
u32 set_rds_picode(struct fmdev *fmdev, u16 pi_val) { u16 payload; u32 ret; payload = pi_val; ret = fmc_send_cmd(fmdev, PI_SET, REG_WR, &payload, sizeof(payload), NULL, NULL); if (ret < 0) return ret; return 0; }
u32 set_rds_pty(struct fmdev *fmdev, u16 pty) { u16 payload; u32 ret; payload = pty; ret = fmc_send_cmd(fmdev, PTY, REG_WR, &payload, sizeof(payload), NULL, NULL); if (ret < 0) return ret; return 0; }
static u32 set_rds_data_mode(struct fmdev *fmdev, u8 mode) { u16 payload; u32 ret; /* Setting unique PI TODO: how unique? */ payload = (u16)0xcafe; ret = fmc_send_cmd(fmdev, PI_SET, REG_WR, &payload, sizeof(payload), NULL, NULL); if (ret < 0) return ret; /* Set decoder id */ payload = (u16)0xa; ret = fmc_send_cmd(fmdev, DI_SET, REG_WR, &payload, sizeof(payload), NULL, NULL); if (ret < 0) return ret; /* TODO: RDS_MODE_GET? */ return 0; }
/* * Function to read the FM_RDS_FLAG registry */ int fm_rx_set_mask(struct fmdrv_ops *fmdev, unsigned short mask) { int ret; unsigned short flag; fmdev->rx.fm_rds_flag|= FM_RDS_FLAG_CLEAN_BIT; /* clean FM_RDS_FLAG */ ret = read_fm_rds_flag(fmdev, &flag); FM_CHECK_SEND_CMD_STATUS(ret); ret = fmc_send_cmd(fmdev, FM_REG_FM_RDS_MSK, &mask, sizeof(mask), REG_WR, &fmdev->maintask_completion, NULL, NULL); FM_CHECK_SEND_CMD_STATUS(ret); return ret; }
static int set_rds_len(struct fmdev *fmdev, u8 type, u16 len) { u16 payload; int ret; len |= type << 8; payload = len; ret = fmc_send_cmd(fmdev, RDS_CONFIG_DATA_SET, REG_WR, &payload, sizeof(payload), NULL, NULL); if (ret < 0) return ret; return 0; }
/* Start TX Transmission */ static u32 enable_xmit(struct fmdev *fmdev, u8 new_xmit_state) { struct fmtx_data *tx = &fmdev->tx_data; unsigned long timeleft; u16 payload; u32 ret; /* Enable POWER_ENB interrupts */ payload = FM_POW_ENB_EVENT; ret = fmc_send_cmd(fmdev, INT_MASK_SET, REG_WR, &payload, sizeof(payload), NULL, NULL); if (ret < 0) return ret; /* Set Power Enable */ payload = new_xmit_state; ret = fmc_send_cmd(fmdev, POWER_ENB_SET, REG_WR, &payload, sizeof(payload), NULL, NULL); if (ret < 0) return ret; /* Wait for Power Enabled */ init_completion(&fmdev->maintask_comp); timeleft = wait_for_completion_timeout(&fmdev->maintask_comp, FM_DRV_TX_TIMEOUT); if (!timeleft) { fmerr("Timeout(%d sec),didn't get tune ended interrupt\n", jiffies_to_msecs(FM_DRV_TX_TIMEOUT) / 1000); return -ETIMEDOUT; } set_bit(FM_CORE_TX_XMITING, &fmdev->flag); tx->xmit_state = new_xmit_state; return 0; }
u32 fm_tx_set_mute_mode(struct fmdev *fmdev, u8 mute_mode_toset) { u16 payload; u32 ret; fmdbg("tx: mute mode %d\n", mute_mode_toset); payload = mute_mode_toset; ret = fmc_send_cmd(fmdev, MUTE, REG_WR, &payload, sizeof(payload), NULL, NULL); if (ret < 0) return ret; return 0; }
static u32 set_rds_len(struct fmdev *fmdev, u8 type, u16 len) { u16 payload; u32 ret; len |= type << 8; payload = len; ret = fmc_send_cmd(fmdev, RDS_CONFIG_DATA_SET, REG_WR, &payload, sizeof(payload), NULL, NULL); if (ret < 0) return ret; /* TODO: LENGTH_GET? */ return 0; }
/* * Function to read the FM_RDS_FLAG registry */ int read_fm_rds_flag(struct fmdrv_ops *fmdev, unsigned short *value) { unsigned char read_length; int ret; int resp_len; unsigned char resp_buf [2]; read_length = FM_READ_2_BYTE_DATA; ret = fmc_send_cmd(fmdev, FM_REG_FM_RDS_FLAG, &read_length, sizeof(read_length), REG_RD, &fmdev->maintask_completion, &resp_buf, &resp_len); *value = (unsigned short)resp_buf[0] + ((unsigned short)resp_buf[1] << 8); V4L2_FM_DRV_DBG(V4L2_DBG_RX, "(fmdrv) FM Mask : 0x%x ", *value); return 0; }
/* Set TX Audio I/O */ static u32 set_audio_io(struct fmdev *fmdev) { struct fmtx_data *tx = &fmdev->tx_data; u16 payload; u32 ret; /* Set Audio I/O Enable */ payload = tx->audio_io; ret = fmc_send_cmd(fmdev, AUDIO_IO_SET, REG_WR, &payload, sizeof(payload), NULL, NULL); if (ret < 0) return ret; /* TODO: is audio set? */ return 0; }
/* Get the TX tuning capacitor value.*/ u32 fm_tx_get_tune_cap_val(struct fmdev *fmdev) { u16 curr_val; u32 ret, resp_len; if (fmdev->curr_fmmode != FM_MODE_TX) return -EPERM; ret = fmc_send_cmd(fmdev, READ_FMANT_TUNE_VALUE, REG_RD, NULL, sizeof(curr_val), &curr_val, &resp_len); if (ret < 0) return ret; curr_val = be16_to_cpu(curr_val); return curr_val; }
/* * Function to retrieve audio control param * from controller */ int fm_rx_get_audio_ctrl(struct fmdrv_ops *fmdev, uint16_t *audio_ctrl) { uint16_t payload = FM_READ_2_BYTE_DATA; int ret = -EINVAL, resp_len; if (fmdev->curr_fmmode != FM_MODE_RX) return ret; /* Send cmd to set the band */ ret = fmc_send_cmd(fmdev, FM_REG_AUD_CTL0, &payload, sizeof(payload), REG_RD, &fmdev->maintask_completion, audio_ctrl, &resp_len); FM_CHECK_SEND_CMD_STATUS(ret); fmdev->aud_ctrl = fmdev->rx.aud_ctrl = *audio_ctrl; if(ret == -ETIMEDOUT) return -EBUSY; return ret; }
/* * Function to set the audio control param * to controller */ int fm_rx_set_audio_ctrl(struct fmdrv_ops *fmdev,uint16_t audio_ctrl) { uint16_t payload = audio_ctrl; int ret = -EINVAL; if (fmdev->curr_fmmode != FM_MODE_RX) return ret; /* Send cmd to set the band */ ret = fmc_send_cmd(fmdev, FM_REG_AUD_CTL0, &payload, sizeof(payload), REG_WR, &fmdev->maintask_completion, NULL, NULL); FM_CHECK_SEND_CMD_STATUS(ret); fmdev->aud_ctrl = fmdev->rx.aud_ctrl = audio_ctrl; if(ret == -ETIMEDOUT) return -EBUSY; return ret; }
u32 fm_tx_set_af(struct fmdev *fmdev, u32 af) { u16 payload; u32 ret; if (fmdev->curr_fmmode != FM_MODE_TX) return -EPERM; fmdbg("AF: %d\n", af); fmdev->tx_data.af_frq = af; af = (af - FM_US_BAND_LOW) / FM_KHZ; payload = (u16)af; ret = fmc_send_cmd(fmdev, AF, REG_WR, &payload, sizeof(payload), NULL, NULL); if (ret < 0) return ret; return 0; }
/* * Function to get the current tuned frequency * This function will query controller by reading the FM_REG_FM_FREQ(0x0a) * to determine the current tuned frequency. */ int fm_rx_get_frequency(struct fmdrv_ops *fmdev, unsigned int *curr_freq) { unsigned char payload; unsigned short tmp_frq; int ret; int resp_len; payload = 2; ret = fmc_send_cmd(fmdev, FM_REG_FM_FREQ, &payload, 1, REG_RD, &fmdev->maintask_completion, &tmp_frq, &resp_len); FM_CHECK_SEND_CMD_STATUS(ret); V4L2_FM_DRV_DBG(V4L2_DBG_TX, "(fmdev) FM_REG_FM_FREQ : %d", \ FM_SET_FREQ(tmp_frq)); *curr_freq = FM_SET_FREQ(tmp_frq); return ret; }
/* Gets current RX stereo/mono mode */ u32 fm_rx_get_stereo_mono(struct fmdev *fmdev, u16 *mode) { u16 curr_mode; u32 ret, resp_len; if (mode == NULL) { fmerr("Invalid memory\n"); return -ENOMEM; } ret = fmc_send_cmd(fmdev, MOST_MODE_SET, REG_RD, NULL, 2, &curr_mode, &resp_len); if (ret < 0) return ret; *mode = be16_to_cpu(curr_mode); return 0; }
u32 fm_tx_set_region(struct fmdev *fmdev, u8 region) { u16 payload; u32 ret; if (region != FM_BAND_EUROPE_US && region != FM_BAND_JAPAN) { fmerr("Invalid band\n"); return -EINVAL; } /* Send command to set the band */ payload = (u16)region; ret = fmc_send_cmd(fmdev, TX_BAND_SET, REG_WR, &payload, sizeof(payload), NULL, NULL); if (ret < 0) return ret; return 0; }