int fm_tx_set_rds_mode(struct fmdev *fmdev, u8 rds_en_dis) { u16 payload; int ret; u8 rds_text[] = "WL12XX Radio\n"; 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 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; }
static int fm_v4l2_fops_release(struct file *file) { int ret; struct fmdev *fmdev; fmdev = video_drvdata(file); if (!radio_disconnected) { fmdbg("FM device is already closed\n"); return 0; } mutex_lock(&fmdev->mutex); ret = fmc_set_mode(fmdev, FM_MODE_OFF); if (ret < 0) { fmerr("Unable to turn off the chip\n"); goto release_unlock; } ret = fmc_release(fmdev); if (ret < 0) { fmerr("FM CORE release failed\n"); goto release_unlock; } radio_disconnected = 0; release_unlock: mutex_unlock(&fmdev->mutex); return ret; }
/* * Handle open request for "/dev/radioX" device. * Start with FM RX mode as default. */ static int fm_v4l2_fops_open(struct file *file) { int ret; struct fmdev *fmdev = NULL; /* Don't allow multiple open */ if (radio_disconnected) { fmerr("FM device is already opened\n"); return -EBUSY; } fmdev = video_drvdata(file); if (mutex_lock_interruptible(&fmdev->mutex)) return -ERESTARTSYS; ret = fmc_prepare(fmdev); if (ret < 0) { fmerr("Unable to prepare FM CORE\n"); goto open_unlock; } fmdbg("Load FM RX firmware..\n"); ret = fmc_set_mode(fmdev, FM_MODE_RX); if (ret < 0) { fmerr("Unable to load FM RX firmware\n"); goto open_unlock; } radio_disconnected = 1; open_unlock: mutex_unlock(&fmdev->mutex); return ret; }
/* * Handle open request for "/dev/radioX" device. * Start with FM RX mode as default. */ static int fm_v4l2_fops_open(struct file *file) { int ret; struct fmdev *fmdev = NULL; /* Don't allow multiple open */ if (radio_disconnected) { fmerr("FM device is already opened\n"); return -EBUSY; } fmdev = video_drvdata(file); ret = fmc_prepare(fmdev); if (ret < 0) { fmerr("Unable to prepare FM CORE\n"); return ret; } fmdbg("Load FM RX firmware..\n"); ret = fmc_set_mode(fmdev, FM_MODE_RX); if (ret < 0) { fmerr("Unable to load FM RX firmware\n"); return ret; } radio_disconnected = 1; return ret; }
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; }
/* Write TX RDS data */ static ssize_t fm_v4l2_fops_write(struct file *file, const char __user * buf, size_t count, loff_t *ppos) { struct tx_rds rds; int ret; struct fmdev *fmdev; ret = copy_from_user(&rds, buf, sizeof(rds)); fmdbg("(%d)type: %d, text %s, af %d\n", ret, rds.text_type, rds.text, rds.af_freq); fmdev = video_drvdata(file); fm_tx_set_radio_text(fmdev, rds.text, rds.text_type); fm_tx_set_af(fmdev, rds.af_freq); 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; }
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; }
int fm_tx_set_af(struct fmdev *fmdev, u32 af) { u16 payload; int ret; if (fmdev->curr_fmmode != FM_MODE_TX) return -EPERM; fmdbg("AF: %d\n", af); af = (af - 87500) / 100; payload = (u16)af; ret = fmc_send_cmd(fmdev, TA_SET, REG_WR, &payload, sizeof(payload), NULL, NULL); if (ret < 0) return ret; return 0; }
/* Sets band (0-Europe/US; 1-Japan) */ int fm_rx_set_region(struct fmdev *fmdev, u8 region_to_set) { u16 payload; u32 new_frq = 0; int ret; if (region_to_set != FM_BAND_EUROPE_US && region_to_set != FM_BAND_JAPAN) { fmerr("Invalid band\n"); return -EINVAL; } if (fmdev->rx.region.fm_band == region_to_set) { fmerr("Requested band is already configured\n"); return 0; } /* Send cmd to set the band */ payload = (u16)region_to_set; ret = fmc_send_cmd(fmdev, BAND_SET, REG_WR, &payload, sizeof(payload), NULL, NULL); if (ret < 0) return ret; fmc_update_region_info(fmdev, region_to_set); /* Check whether current RX frequency is within band boundary */ if (fmdev->rx.freq < fmdev->rx.region.bot_freq) new_frq = fmdev->rx.region.bot_freq; else if (fmdev->rx.freq > fmdev->rx.region.top_freq) new_frq = fmdev->rx.region.top_freq; if (new_frq) { fmdbg("Current freq is not within band limit boundary," "switching to %d KHz\n", new_frq); /* Current RX frequency is not in range. So, update it */ ret = fm_rx_set_freq(fmdev, new_frq); } return ret; }
u32 fm_tx_set_stereo_mono(struct fmdev *fmdev, u16 mode) { u16 payload; u32 ret; if (fmdev->tx_data.aud_mode == mode) return 0; fmdbg("stereo mode: %d\n", mode); /* Set Stereo/Mono mode */ payload = (1 - mode); ret = fmc_send_cmd(fmdev, MONO_SET, REG_WR, &payload, sizeof(payload), NULL, NULL); if (ret < 0) return ret; fmdev->tx_data.aud_mode = mode; return ret; }
static int fm_v4l2_fops_release(struct file *file) { int ret; struct fmdev *fmdev; fmdev = video_drvdata(file); if (fmdev->rx.comp_scan_status == 1) { if (fmdev->rx.comp_scan_done == 0) { ret = fm_rx_seek(fmdev, 1, 0, FM_CHANNEL_SPACING_200KHZ, COMP_SCAN_STOP); if (ret < 0) fmerr("RX complete scan failed - %d\n", ret); } } if (!radio_disconnected) { fmdbg("FM device is already closed\n"); return 0; } ret = fmc_set_mode(fmdev, FM_MODE_OFF); if (ret < 0) { fmerr("Unable to turn off the chip\n"); return ret; } sysfs_remove_group(&fmdev->radio_dev->dev.kobj, &v4l2_fm_attr_grp); ret = fmc_release(fmdev); if (ret < 0) { fmerr("FM CORE release failed\n"); return ret; } radio_disconnected = 0; return ret; }
/* Write TX RDS data */ static ssize_t fm_v4l2_fops_write(struct file *file, const char __user * buf, size_t count, loff_t *ppos) { struct tx_rds rds; int ret; struct fmdev *fmdev; ret = copy_from_user(&rds, buf, sizeof(rds)); rds.text[sizeof(rds.text) - 1] = '\0'; fmdbg("(%d)type: %d, text %s, af %d\n", ret, rds.text_type, rds.text, rds.af_freq); if (ret) return -EFAULT; fmdev = video_drvdata(file); if (mutex_lock_interruptible(&fmdev->mutex)) return -ERESTARTSYS; fm_tx_set_radio_text(fmdev, rds.text, rds.text_type); fm_tx_set_af(fmdev, rds.af_freq); mutex_unlock(&fmdev->mutex); return sizeof(rds); }
/* * Handle open request for "/dev/radioX" device. * Start with FM RX mode as default. */ static int fm_v4l2_fops_open(struct file *file) { int ret; struct fmdev *fmdev = NULL; /* Don't allow multiple open */ if (radio_disconnected) { fmerr("FM device is already opened\n"); return -EBUSY; } fmdev = video_drvdata(file); ret = fmc_prepare(fmdev); if (ret < 0) { fmerr("Unable to prepare FM CORE\n"); return ret; } fmdbg("Load FM RX firmware..\n"); ret = fmc_set_mode(fmdev, FM_MODE_RX); if (ret < 0) { fmerr("Unable to load FM RX firmware\n"); return ret; } radio_disconnected = 1; /* Register sysfs entries */ ret = sysfs_create_group(&fmdev->radio_dev->dev.kobj, &v4l2_fm_attr_grp); if (ret) { pr_err("failed to create sysfs entries"); return ret; } return ret; }