Exemple #1
0
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;
}
Exemple #3
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;
}
Exemple #4
0
/*
 * 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;
}
Exemple #8
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;
}
Exemple #11
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;
}
Exemple #14
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));
	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;
}