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