18b7a186cSManjunatha Halli /*
28b7a186cSManjunatha Halli  *  FM Driver for Connectivity chip of Texas Instruments.
38b7a186cSManjunatha Halli  *  This sub-module of FM driver implements FM TX functionality.
48b7a186cSManjunatha Halli  *
58b7a186cSManjunatha Halli  *  Copyright (C) 2011 Texas Instruments
68b7a186cSManjunatha Halli  *
78b7a186cSManjunatha Halli  *  This program is free software; you can redistribute it and/or modify
88b7a186cSManjunatha Halli  *  it under the terms of the GNU General Public License version 2 as
98b7a186cSManjunatha Halli  *  published by the Free Software Foundation.
108b7a186cSManjunatha Halli  *
118b7a186cSManjunatha Halli  *  This program is distributed in the hope that it will be useful,
128b7a186cSManjunatha Halli  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
138b7a186cSManjunatha Halli  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
148b7a186cSManjunatha Halli  *  GNU General Public License for more details.
158b7a186cSManjunatha Halli  *
168b7a186cSManjunatha Halli  *  You should have received a copy of the GNU General Public License
178b7a186cSManjunatha Halli  *  along with this program; if not, write to the Free Software
188b7a186cSManjunatha Halli  *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
198b7a186cSManjunatha Halli  *
208b7a186cSManjunatha Halli  */
218b7a186cSManjunatha Halli 
228b7a186cSManjunatha Halli #include <linux/delay.h>
238b7a186cSManjunatha Halli #include "fmdrv.h"
248b7a186cSManjunatha Halli #include "fmdrv_common.h"
258b7a186cSManjunatha Halli #include "fmdrv_tx.h"
268b7a186cSManjunatha Halli 
278cc20dd8SXi Wang int fm_tx_set_stereo_mono(struct fmdev *fmdev, u16 mode)
288b7a186cSManjunatha Halli {
298b7a186cSManjunatha Halli 	u16 payload;
308cc20dd8SXi Wang 	int ret;
318b7a186cSManjunatha Halli 
328b7a186cSManjunatha Halli 	if (fmdev->tx_data.aud_mode == mode)
338b7a186cSManjunatha Halli 		return 0;
348b7a186cSManjunatha Halli 
358b7a186cSManjunatha Halli 	fmdbg("stereo mode: %d\n", mode);
368b7a186cSManjunatha Halli 
378b7a186cSManjunatha Halli 	/* Set Stereo/Mono mode */
388b7a186cSManjunatha Halli 	payload = (1 - mode);
398b7a186cSManjunatha Halli 	ret = fmc_send_cmd(fmdev, MONO_SET, REG_WR, &payload,
408b7a186cSManjunatha Halli 			sizeof(payload), NULL, NULL);
418b7a186cSManjunatha Halli 	if (ret < 0)
428b7a186cSManjunatha Halli 		return ret;
438b7a186cSManjunatha Halli 
448b7a186cSManjunatha Halli 	fmdev->tx_data.aud_mode = mode;
458b7a186cSManjunatha Halli 
468b7a186cSManjunatha Halli 	return ret;
478b7a186cSManjunatha Halli }
488b7a186cSManjunatha Halli 
498cc20dd8SXi Wang static int set_rds_text(struct fmdev *fmdev, u8 *rds_text)
508b7a186cSManjunatha Halli {
518b7a186cSManjunatha Halli 	u16 payload;
528cc20dd8SXi Wang 	int ret;
538b7a186cSManjunatha Halli 
548b7a186cSManjunatha Halli 	ret = fmc_send_cmd(fmdev, RDS_DATA_SET, REG_WR, rds_text,
558b7a186cSManjunatha Halli 			strlen(rds_text), NULL, NULL);
568b7a186cSManjunatha Halli 	if (ret < 0)
578b7a186cSManjunatha Halli 		return ret;
588b7a186cSManjunatha Halli 
598b7a186cSManjunatha Halli 	/* Scroll mode */
608b7a186cSManjunatha Halli 	payload = (u16)0x1;
618b7a186cSManjunatha Halli 	ret = fmc_send_cmd(fmdev, DISPLAY_MODE, REG_WR, &payload,
628b7a186cSManjunatha Halli 			sizeof(payload), NULL, NULL);
638b7a186cSManjunatha Halli 	if (ret < 0)
648b7a186cSManjunatha Halli 		return ret;
658b7a186cSManjunatha Halli 
668b7a186cSManjunatha Halli 	return 0;
678b7a186cSManjunatha Halli }
688b7a186cSManjunatha Halli 
698cc20dd8SXi Wang static int set_rds_data_mode(struct fmdev *fmdev, u8 mode)
708b7a186cSManjunatha Halli {
718b7a186cSManjunatha Halli 	u16 payload;
728cc20dd8SXi Wang 	int ret;
738b7a186cSManjunatha Halli 
748b7a186cSManjunatha Halli 	/* Setting unique PI TODO: how unique? */
758b7a186cSManjunatha Halli 	payload = (u16)0xcafe;
768b7a186cSManjunatha Halli 	ret = fmc_send_cmd(fmdev, PI_SET, REG_WR, &payload,
778b7a186cSManjunatha Halli 			sizeof(payload), NULL, NULL);
788b7a186cSManjunatha Halli 	if (ret < 0)
798b7a186cSManjunatha Halli 		return ret;
808b7a186cSManjunatha Halli 
818b7a186cSManjunatha Halli 	/* Set decoder id */
828b7a186cSManjunatha Halli 	payload = (u16)0xa;
838b7a186cSManjunatha Halli 	ret = fmc_send_cmd(fmdev, DI_SET, REG_WR, &payload,
848b7a186cSManjunatha Halli 			sizeof(payload), NULL, NULL);
858b7a186cSManjunatha Halli 	if (ret < 0)
868b7a186cSManjunatha Halli 		return ret;
878b7a186cSManjunatha Halli 
888b7a186cSManjunatha Halli 	/* TODO: RDS_MODE_GET? */
898b7a186cSManjunatha Halli 	return 0;
908b7a186cSManjunatha Halli }
918b7a186cSManjunatha Halli 
928cc20dd8SXi Wang static int set_rds_len(struct fmdev *fmdev, u8 type, u16 len)
938b7a186cSManjunatha Halli {
948b7a186cSManjunatha Halli 	u16 payload;
958cc20dd8SXi Wang 	int ret;
968b7a186cSManjunatha Halli 
978b7a186cSManjunatha Halli 	len |= type << 8;
988b7a186cSManjunatha Halli 	payload = len;
998b7a186cSManjunatha Halli 	ret = fmc_send_cmd(fmdev, RDS_CONFIG_DATA_SET, REG_WR, &payload,
1008b7a186cSManjunatha Halli 			sizeof(payload), NULL, NULL);
1018b7a186cSManjunatha Halli 	if (ret < 0)
1028b7a186cSManjunatha Halli 		return ret;
1038b7a186cSManjunatha Halli 
1048b7a186cSManjunatha Halli 	/* TODO: LENGTH_GET? */
1058b7a186cSManjunatha Halli 	return 0;
1068b7a186cSManjunatha Halli }
1078b7a186cSManjunatha Halli 
1088cc20dd8SXi Wang int fm_tx_set_rds_mode(struct fmdev *fmdev, u8 rds_en_dis)
1098b7a186cSManjunatha Halli {
1108b7a186cSManjunatha Halli 	u16 payload;
1118cc20dd8SXi Wang 	int ret;
1128b7a186cSManjunatha Halli 	u8 rds_text[] = "Zoom2\n";
1138b7a186cSManjunatha Halli 
1148b7a186cSManjunatha Halli 	fmdbg("rds_en_dis:%d(E:%d, D:%d)\n", rds_en_dis,
1158b7a186cSManjunatha Halli 		   FM_RDS_ENABLE, FM_RDS_DISABLE);
1168b7a186cSManjunatha Halli 
1178b7a186cSManjunatha Halli 	if (rds_en_dis == FM_RDS_ENABLE) {
1188b7a186cSManjunatha Halli 		/* Set RDS length */
1198b7a186cSManjunatha Halli 		set_rds_len(fmdev, 0, strlen(rds_text));
1208b7a186cSManjunatha Halli 
1218b7a186cSManjunatha Halli 		/* Set RDS text */
1228b7a186cSManjunatha Halli 		set_rds_text(fmdev, rds_text);
1238b7a186cSManjunatha Halli 
1248b7a186cSManjunatha Halli 		/* Set RDS mode */
1258b7a186cSManjunatha Halli 		set_rds_data_mode(fmdev, 0x0);
1268b7a186cSManjunatha Halli 	}
1278b7a186cSManjunatha Halli 
1288b7a186cSManjunatha Halli 	/* Send command to enable RDS */
1298b7a186cSManjunatha Halli 	if (rds_en_dis == FM_RDS_ENABLE)
1308b7a186cSManjunatha Halli 		payload = 0x01;
1318b7a186cSManjunatha Halli 	else
1328b7a186cSManjunatha Halli 		payload = 0x00;
1338b7a186cSManjunatha Halli 
1348b7a186cSManjunatha Halli 	ret = fmc_send_cmd(fmdev, RDS_DATA_ENB, REG_WR, &payload,
1358b7a186cSManjunatha Halli 			sizeof(payload), NULL, NULL);
1368b7a186cSManjunatha Halli 	if (ret < 0)
1378b7a186cSManjunatha Halli 		return ret;
1388b7a186cSManjunatha Halli 
1398b7a186cSManjunatha Halli 	if (rds_en_dis == FM_RDS_ENABLE) {
1408b7a186cSManjunatha Halli 		/* Set RDS length */
1418b7a186cSManjunatha Halli 		set_rds_len(fmdev, 0, strlen(rds_text));
1428b7a186cSManjunatha Halli 
1438b7a186cSManjunatha Halli 		/* Set RDS text */
1448b7a186cSManjunatha Halli 		set_rds_text(fmdev, rds_text);
1458b7a186cSManjunatha Halli 	}
1468b7a186cSManjunatha Halli 	fmdev->tx_data.rds.flag = rds_en_dis;
1478b7a186cSManjunatha Halli 
1488b7a186cSManjunatha Halli 	return 0;
1498b7a186cSManjunatha Halli }
1508b7a186cSManjunatha Halli 
1518cc20dd8SXi Wang int fm_tx_set_radio_text(struct fmdev *fmdev, u8 *rds_text, u8 rds_type)
1528b7a186cSManjunatha Halli {
1538b7a186cSManjunatha Halli 	u16 payload;
1548cc20dd8SXi Wang 	int ret;
1558b7a186cSManjunatha Halli 
1568b7a186cSManjunatha Halli 	if (fmdev->curr_fmmode != FM_MODE_TX)
1578b7a186cSManjunatha Halli 		return -EPERM;
1588b7a186cSManjunatha Halli 
1598b7a186cSManjunatha Halli 	fm_tx_set_rds_mode(fmdev, 0);
1608b7a186cSManjunatha Halli 
1618b7a186cSManjunatha Halli 	/* Set RDS length */
1628b7a186cSManjunatha Halli 	set_rds_len(fmdev, rds_type, strlen(rds_text));
1638b7a186cSManjunatha Halli 
1648b7a186cSManjunatha Halli 	/* Set RDS text */
1658b7a186cSManjunatha Halli 	set_rds_text(fmdev, rds_text);
1668b7a186cSManjunatha Halli 
1678b7a186cSManjunatha Halli 	/* Set RDS mode */
1688b7a186cSManjunatha Halli 	set_rds_data_mode(fmdev, 0x0);
1698b7a186cSManjunatha Halli 
1708b7a186cSManjunatha Halli 	payload = 1;
1718b7a186cSManjunatha Halli 	ret = fmc_send_cmd(fmdev, RDS_DATA_ENB, REG_WR, &payload,
1728b7a186cSManjunatha Halli 			sizeof(payload), NULL, NULL);
1738b7a186cSManjunatha Halli 	if (ret < 0)
1748b7a186cSManjunatha Halli 		return ret;
1758b7a186cSManjunatha Halli 
1768b7a186cSManjunatha Halli 	return 0;
1778b7a186cSManjunatha Halli }
1788b7a186cSManjunatha Halli 
1798cc20dd8SXi Wang int fm_tx_set_af(struct fmdev *fmdev, u32 af)
1808b7a186cSManjunatha Halli {
1818b7a186cSManjunatha Halli 	u16 payload;
1828cc20dd8SXi Wang 	int ret;
1838b7a186cSManjunatha Halli 
1848b7a186cSManjunatha Halli 	if (fmdev->curr_fmmode != FM_MODE_TX)
1858b7a186cSManjunatha Halli 		return -EPERM;
1868b7a186cSManjunatha Halli 
1878b7a186cSManjunatha Halli 	fmdbg("AF: %d\n", af);
1888b7a186cSManjunatha Halli 
1898b7a186cSManjunatha Halli 	af = (af - 87500) / 100;
1908b7a186cSManjunatha Halli 	payload = (u16)af;
1918b7a186cSManjunatha Halli 	ret = fmc_send_cmd(fmdev, TA_SET, REG_WR, &payload,
1928b7a186cSManjunatha Halli 			sizeof(payload), NULL, NULL);
1938b7a186cSManjunatha Halli 	if (ret < 0)
1948b7a186cSManjunatha Halli 		return ret;
1958b7a186cSManjunatha Halli 
1968b7a186cSManjunatha Halli 	return 0;
1978b7a186cSManjunatha Halli }
1988b7a186cSManjunatha Halli 
1998cc20dd8SXi Wang int fm_tx_set_region(struct fmdev *fmdev, u8 region)
2008b7a186cSManjunatha Halli {
2018b7a186cSManjunatha Halli 	u16 payload;
2028cc20dd8SXi Wang 	int ret;
2038b7a186cSManjunatha Halli 
2048b7a186cSManjunatha Halli 	if (region != FM_BAND_EUROPE_US && region != FM_BAND_JAPAN) {
2058b7a186cSManjunatha Halli 		fmerr("Invalid band\n");
2068b7a186cSManjunatha Halli 		return -EINVAL;
2078b7a186cSManjunatha Halli 	}
2088b7a186cSManjunatha Halli 
2098b7a186cSManjunatha Halli 	/* Send command to set the band */
2108b7a186cSManjunatha Halli 	payload = (u16)region;
2118b7a186cSManjunatha Halli 	ret = fmc_send_cmd(fmdev, TX_BAND_SET, REG_WR, &payload,
2128b7a186cSManjunatha Halli 			sizeof(payload), NULL, NULL);
2138b7a186cSManjunatha Halli 	if (ret < 0)
2148b7a186cSManjunatha Halli 		return ret;
2158b7a186cSManjunatha Halli 
2168b7a186cSManjunatha Halli 	return 0;
2178b7a186cSManjunatha Halli }
2188b7a186cSManjunatha Halli 
2198cc20dd8SXi Wang int fm_tx_set_mute_mode(struct fmdev *fmdev, u8 mute_mode_toset)
2208b7a186cSManjunatha Halli {
2218b7a186cSManjunatha Halli 	u16 payload;
2228cc20dd8SXi Wang 	int ret;
2238b7a186cSManjunatha Halli 
2248b7a186cSManjunatha Halli 	fmdbg("tx: mute mode %d\n", mute_mode_toset);
2258b7a186cSManjunatha Halli 
2268b7a186cSManjunatha Halli 	payload = mute_mode_toset;
2278b7a186cSManjunatha Halli 	ret = fmc_send_cmd(fmdev, MUTE, REG_WR, &payload,
2288b7a186cSManjunatha Halli 			sizeof(payload), NULL, NULL);
2298b7a186cSManjunatha Halli 	if (ret < 0)
2308b7a186cSManjunatha Halli 		return ret;
2318b7a186cSManjunatha Halli 
2328b7a186cSManjunatha Halli 	return 0;
2338b7a186cSManjunatha Halli }
2348b7a186cSManjunatha Halli 
2358b7a186cSManjunatha Halli /* Set TX Audio I/O */
2368cc20dd8SXi Wang static int set_audio_io(struct fmdev *fmdev)
2378b7a186cSManjunatha Halli {
2388b7a186cSManjunatha Halli 	struct fmtx_data *tx = &fmdev->tx_data;
2398b7a186cSManjunatha Halli 	u16 payload;
2408cc20dd8SXi Wang 	int ret;
2418b7a186cSManjunatha Halli 
2428b7a186cSManjunatha Halli 	/* Set Audio I/O Enable */
2438b7a186cSManjunatha Halli 	payload = tx->audio_io;
2448b7a186cSManjunatha Halli 	ret = fmc_send_cmd(fmdev, AUDIO_IO_SET, REG_WR, &payload,
2458b7a186cSManjunatha Halli 			sizeof(payload), NULL, NULL);
2468b7a186cSManjunatha Halli 	if (ret < 0)
2478b7a186cSManjunatha Halli 		return ret;
2488b7a186cSManjunatha Halli 
2498b7a186cSManjunatha Halli 	/* TODO: is audio set? */
2508b7a186cSManjunatha Halli 	return 0;
2518b7a186cSManjunatha Halli }
2528b7a186cSManjunatha Halli 
2538b7a186cSManjunatha Halli /* Start TX Transmission */
2548cc20dd8SXi Wang static int enable_xmit(struct fmdev *fmdev, u8 new_xmit_state)
2558b7a186cSManjunatha Halli {
2568b7a186cSManjunatha Halli 	struct fmtx_data *tx = &fmdev->tx_data;
2578b7a186cSManjunatha Halli 	unsigned long timeleft;
2588b7a186cSManjunatha Halli 	u16 payload;
2598cc20dd8SXi Wang 	int ret;
2608b7a186cSManjunatha Halli 
2618b7a186cSManjunatha Halli 	/* Enable POWER_ENB interrupts */
2628b7a186cSManjunatha Halli 	payload = FM_POW_ENB_EVENT;
2638b7a186cSManjunatha Halli 	ret = fmc_send_cmd(fmdev, INT_MASK_SET, REG_WR, &payload,
2648b7a186cSManjunatha Halli 			sizeof(payload), NULL, NULL);
2658b7a186cSManjunatha Halli 	if (ret < 0)
2668b7a186cSManjunatha Halli 		return ret;
2678b7a186cSManjunatha Halli 
2688b7a186cSManjunatha Halli 	/* Set Power Enable */
2698b7a186cSManjunatha Halli 	payload = new_xmit_state;
2708b7a186cSManjunatha Halli 	ret = fmc_send_cmd(fmdev, POWER_ENB_SET, REG_WR, &payload,
2718b7a186cSManjunatha Halli 			sizeof(payload), NULL, NULL);
2728b7a186cSManjunatha Halli 	if (ret < 0)
2738b7a186cSManjunatha Halli 		return ret;
2748b7a186cSManjunatha Halli 
2758b7a186cSManjunatha Halli 	/* Wait for Power Enabled */
2768b7a186cSManjunatha Halli 	init_completion(&fmdev->maintask_comp);
2778b7a186cSManjunatha Halli 	timeleft = wait_for_completion_timeout(&fmdev->maintask_comp,
2788b7a186cSManjunatha Halli 			FM_DRV_TX_TIMEOUT);
2798b7a186cSManjunatha Halli 	if (!timeleft) {
2808b7a186cSManjunatha Halli 		fmerr("Timeout(%d sec),didn't get tune ended interrupt\n",
2818b7a186cSManjunatha Halli 			   jiffies_to_msecs(FM_DRV_TX_TIMEOUT) / 1000);
2828b7a186cSManjunatha Halli 		return -ETIMEDOUT;
2838b7a186cSManjunatha Halli 	}
2848b7a186cSManjunatha Halli 
2858b7a186cSManjunatha Halli 	set_bit(FM_CORE_TX_XMITING, &fmdev->flag);
2868b7a186cSManjunatha Halli 	tx->xmit_state = new_xmit_state;
2878b7a186cSManjunatha Halli 
2888b7a186cSManjunatha Halli 	return 0;
2898b7a186cSManjunatha Halli }
2908b7a186cSManjunatha Halli 
2918b7a186cSManjunatha Halli /* Set TX power level */
2928cc20dd8SXi Wang int fm_tx_set_pwr_lvl(struct fmdev *fmdev, u8 new_pwr_lvl)
2938b7a186cSManjunatha Halli {
2948b7a186cSManjunatha Halli 	u16 payload;
2958b7a186cSManjunatha Halli 	struct fmtx_data *tx = &fmdev->tx_data;
2968cc20dd8SXi Wang 	int ret;
2978b7a186cSManjunatha Halli 
2988b7a186cSManjunatha Halli 	if (fmdev->curr_fmmode != FM_MODE_TX)
2998b7a186cSManjunatha Halli 		return -EPERM;
3008b7a186cSManjunatha Halli 	fmdbg("tx: pwr_level_to_set %ld\n", (long int)new_pwr_lvl);
3018b7a186cSManjunatha Halli 
3028b7a186cSManjunatha Halli 	/* If the core isn't ready update global variable */
3038b7a186cSManjunatha Halli 	if (!test_bit(FM_CORE_READY, &fmdev->flag)) {
3048b7a186cSManjunatha Halli 		tx->pwr_lvl = new_pwr_lvl;
3058b7a186cSManjunatha Halli 		return 0;
3068b7a186cSManjunatha Halli 	}
3078b7a186cSManjunatha Halli 
3088b7a186cSManjunatha Halli 	/* Set power level: Application will specify power level value in
3098b7a186cSManjunatha Halli 	 * units of dB/uV, whereas range and step are specific to FM chip.
3108b7a186cSManjunatha Halli 	 * For TI's WL chips, convert application specified power level value
3118b7a186cSManjunatha Halli 	 * to chip specific value by subtracting 122 from it. Refer to TI FM
3128b7a186cSManjunatha Halli 	 * data sheet for details.
3138b7a186cSManjunatha Halli 	 * */
3148b7a186cSManjunatha Halli 
3158b7a186cSManjunatha Halli 	payload = (FM_PWR_LVL_HIGH - new_pwr_lvl);
3168b7a186cSManjunatha Halli 	ret = fmc_send_cmd(fmdev, POWER_LEV_SET, REG_WR, &payload,
3178b7a186cSManjunatha Halli 			sizeof(payload), NULL, NULL);
3188b7a186cSManjunatha Halli 	if (ret < 0)
3198b7a186cSManjunatha Halli 		return ret;
3208b7a186cSManjunatha Halli 
3218b7a186cSManjunatha Halli 	/* TODO: is the power level set? */
3228b7a186cSManjunatha Halli 	tx->pwr_lvl = new_pwr_lvl;
3238b7a186cSManjunatha Halli 
3248b7a186cSManjunatha Halli 	return 0;
3258b7a186cSManjunatha Halli }
3268b7a186cSManjunatha Halli 
3278b7a186cSManjunatha Halli /*
3288b7a186cSManjunatha Halli  * Sets FM TX pre-emphasis filter value (OFF, 50us, or 75us)
3298b7a186cSManjunatha Halli  * Convert V4L2 specified filter values to chip specific filter values.
3308b7a186cSManjunatha Halli  */
3318cc20dd8SXi Wang int fm_tx_set_preemph_filter(struct fmdev *fmdev, u32 preemphasis)
3328b7a186cSManjunatha Halli {
3338b7a186cSManjunatha Halli 	struct fmtx_data *tx = &fmdev->tx_data;
3348b7a186cSManjunatha Halli 	u16 payload;
3358cc20dd8SXi Wang 	int ret;
3368b7a186cSManjunatha Halli 
3378b7a186cSManjunatha Halli 	if (fmdev->curr_fmmode != FM_MODE_TX)
3388b7a186cSManjunatha Halli 		return -EPERM;
3398b7a186cSManjunatha Halli 
3408b7a186cSManjunatha Halli 	switch (preemphasis) {
3418b7a186cSManjunatha Halli 	case V4L2_PREEMPHASIS_DISABLED:
3428b7a186cSManjunatha Halli 		payload = FM_TX_PREEMPH_OFF;
3438b7a186cSManjunatha Halli 		break;
3448b7a186cSManjunatha Halli 	case V4L2_PREEMPHASIS_50_uS:
3458b7a186cSManjunatha Halli 		payload = FM_TX_PREEMPH_50US;
3468b7a186cSManjunatha Halli 		break;
3478b7a186cSManjunatha Halli 	case V4L2_PREEMPHASIS_75_uS:
3488b7a186cSManjunatha Halli 		payload = FM_TX_PREEMPH_75US;
3498b7a186cSManjunatha Halli 		break;
3508b7a186cSManjunatha Halli 	}
3518b7a186cSManjunatha Halli 
3528b7a186cSManjunatha Halli 	ret = fmc_send_cmd(fmdev, PREMPH_SET, REG_WR, &payload,
3538b7a186cSManjunatha Halli 			sizeof(payload), NULL, NULL);
3548b7a186cSManjunatha Halli 	if (ret < 0)
3558b7a186cSManjunatha Halli 		return ret;
3568b7a186cSManjunatha Halli 
3578b7a186cSManjunatha Halli 	tx->preemph = payload;
3588b7a186cSManjunatha Halli 
3598b7a186cSManjunatha Halli 	return ret;
3608b7a186cSManjunatha Halli }
3618b7a186cSManjunatha Halli 
3628b7a186cSManjunatha Halli /* Get the TX tuning capacitor value.*/
3638cc20dd8SXi Wang int fm_tx_get_tune_cap_val(struct fmdev *fmdev)
3648b7a186cSManjunatha Halli {
3658b7a186cSManjunatha Halli 	u16 curr_val;
3668cc20dd8SXi Wang 	u32 resp_len;
3678cc20dd8SXi Wang 	int ret;
3688b7a186cSManjunatha Halli 
3698b7a186cSManjunatha Halli 	if (fmdev->curr_fmmode != FM_MODE_TX)
3708b7a186cSManjunatha Halli 		return -EPERM;
3718b7a186cSManjunatha Halli 
3728b7a186cSManjunatha Halli 	ret = fmc_send_cmd(fmdev, READ_FMANT_TUNE_VALUE, REG_RD,
3738b7a186cSManjunatha Halli 			NULL, sizeof(curr_val), &curr_val, &resp_len);
3748b7a186cSManjunatha Halli 	if (ret < 0)
3758b7a186cSManjunatha Halli 		return ret;
3768b7a186cSManjunatha Halli 
3772a8b7e58SHans Verkuil 	curr_val = be16_to_cpu((__force __be16)curr_val);
3788b7a186cSManjunatha Halli 
3798b7a186cSManjunatha Halli 	return curr_val;
3808b7a186cSManjunatha Halli }
3818b7a186cSManjunatha Halli 
3828b7a186cSManjunatha Halli /* Set TX Frequency */
3838cc20dd8SXi Wang int fm_tx_set_freq(struct fmdev *fmdev, u32 freq_to_set)
3848b7a186cSManjunatha Halli {
3858b7a186cSManjunatha Halli 	struct fmtx_data *tx = &fmdev->tx_data;
3868b7a186cSManjunatha Halli 	u16 payload, chanl_index;
3878cc20dd8SXi Wang 	int ret;
3888b7a186cSManjunatha Halli 
3898b7a186cSManjunatha Halli 	if (test_bit(FM_CORE_TX_XMITING, &fmdev->flag)) {
3908b7a186cSManjunatha Halli 		enable_xmit(fmdev, 0);
3918b7a186cSManjunatha Halli 		clear_bit(FM_CORE_TX_XMITING, &fmdev->flag);
3928b7a186cSManjunatha Halli 	}
3938b7a186cSManjunatha Halli 
3948b7a186cSManjunatha Halli 	/* Enable FR, BL interrupts */
3958b7a186cSManjunatha Halli 	payload = (FM_FR_EVENT | FM_BL_EVENT);
3968b7a186cSManjunatha Halli 	ret = fmc_send_cmd(fmdev, INT_MASK_SET, REG_WR, &payload,
3978b7a186cSManjunatha Halli 			sizeof(payload), NULL, NULL);
3988b7a186cSManjunatha Halli 	if (ret < 0)
3998b7a186cSManjunatha Halli 		return ret;
4008b7a186cSManjunatha Halli 
4018b7a186cSManjunatha Halli 	tx->tx_frq = (unsigned long)freq_to_set;
4028b7a186cSManjunatha Halli 	fmdbg("tx: freq_to_set %ld\n", (long int)tx->tx_frq);
4038b7a186cSManjunatha Halli 
4048b7a186cSManjunatha Halli 	chanl_index = freq_to_set / 10;
4058b7a186cSManjunatha Halli 
4068b7a186cSManjunatha Halli 	/* Set current tuner channel */
4078b7a186cSManjunatha Halli 	payload = chanl_index;
4088b7a186cSManjunatha Halli 	ret = fmc_send_cmd(fmdev, CHANL_SET, REG_WR, &payload,
4098b7a186cSManjunatha Halli 			sizeof(payload), NULL, NULL);
4108b7a186cSManjunatha Halli 	if (ret < 0)
4118b7a186cSManjunatha Halli 		return ret;
4128b7a186cSManjunatha Halli 
4138b7a186cSManjunatha Halli 	fm_tx_set_pwr_lvl(fmdev, tx->pwr_lvl);
4148b7a186cSManjunatha Halli 	fm_tx_set_preemph_filter(fmdev, tx->preemph);
4158b7a186cSManjunatha Halli 
4168b7a186cSManjunatha Halli 	tx->audio_io = 0x01;	/* I2S */
4178b7a186cSManjunatha Halli 	set_audio_io(fmdev);
4188b7a186cSManjunatha Halli 
4198b7a186cSManjunatha Halli 	enable_xmit(fmdev, 0x01);	/* Enable transmission */
4208b7a186cSManjunatha Halli 
4218b7a186cSManjunatha Halli 	tx->aud_mode = FM_STEREO_MODE;
4228b7a186cSManjunatha Halli 	tx->rds.flag = FM_RDS_DISABLE;
4238b7a186cSManjunatha Halli 
4248b7a186cSManjunatha Halli 	return 0;
4258b7a186cSManjunatha Halli }
4268b7a186cSManjunatha Halli 
427