Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 94bfd740 authored by himta ram's avatar himta ram
Browse files

radio: RTC6226: Make the rtc6226 driver compatible with QTI platform



Moved the power on functionality under set control ioctl.
Removed the blocker code for tune, seek operation.
added code for posting event to user space
as part of interrupt handling.

Change-Id: Ic4c14e4661ef1524868e99588c0e11838341ed83
Signed-off-by: default avatarhimta ram <hram@codeaurora.org>
parent 3d35a227
Loading
Loading
Loading
Loading
+142 −142
Original line number Diff line number Diff line
@@ -112,7 +112,6 @@
#include <linux/delay.h>
#include <linux/i2c.h>
#include "radio-rtc6226.h"
#define SEEK_TIME_OUT_VALUE 13000
/**************************************************************************
 * Module Parameters
 **************************************************************************/
@@ -122,21 +121,11 @@
/* 1: 76   - 108 MHz (Japan wide band) */
/* 2: 76   -  90 MHz (Japan) */
static unsigned short band;
MODULE_PARM_DESC(band, "Band: *0=87.5-108MHz* 1=76-108MHz 2=76-91MHz 3=65-76MHz");

/* De-emphasis */
/* 0: 75 us (USA) */
/* 1: 50 us (Europe, Australia, Japan) */
static unsigned short de;
MODULE_PARM_DESC(de, "De-emphasis: *0=75us* 1=50us");

/* Tune timeout */
static unsigned int tune_timeout = 3000;
MODULE_PARM_DESC(tune_timeout, "Tune timeout: *3000*");

/* Seek timeout */
static unsigned int seek_timeout = SEEK_TIME_OUT_VALUE;
MODULE_PARM_DESC(seek_timeout, "Seek timeout: *13000*");

static const struct v4l2_frequency_band bands[] = {
	{
@@ -218,7 +207,6 @@ void rtc6226_q_event(struct rtc6226_device *radio,
static int rtc6226_set_chan(struct rtc6226_device *radio, unsigned short chan)
{
	int retval;
	bool timed_out = false;
	unsigned short current_chan =
		radio->registers[CHANNEL] & CHANNEL_CSR0_CH;

@@ -233,31 +221,6 @@ static int rtc6226_set_chan(struct rtc6226_device *radio, unsigned short chan)
		radio->registers[CHANNEL] = current_chan;
		goto done;
	}
	reinit_completion(&radio->completion);
	retval = wait_for_completion_timeout(&radio->completion,
			msecs_to_jiffies(tune_timeout));
	if (!retval)
		timed_out = true;

	if ((radio->registers[STATUS] & STATUS_STD) == 0)
		pr_info("%s tune does not complete\n", __func__);
	else {
		radio->seek_tune_status = TUNE_PENDING;
		rtc6226_q_event(radio, RTC6226_EVT_TUNE_SUCC);
	}
	if (timed_out)
		pr_info("%s tune timed out after %u ms\n", __func__,
					tune_timeout);

	/* stop tuning */
	current_chan = radio->registers[CHANNEL] & CHANNEL_CSR0_CH;

	radio->registers[CHANNEL] &= ~CHANNEL_CSR0_TUNE;
	retval = rtc6226_set_register(radio, CHANNEL);
	if (retval < 0)	{
		radio->registers[CHANNEL] = current_chan;
		goto done;
	}

done:
	pr_info("%s exit %d\n", __func__, retval);
@@ -269,16 +232,11 @@ static int rtc6226_set_chan(struct rtc6226_device *radio, unsigned short chan)
 */
static int rtc6226_get_freq(struct rtc6226_device *radio, unsigned int *freq)
{
	unsigned int spacing, band_bottom;
	unsigned short chan;
	unsigned short rssi = 0;
	int retval;

	pr_info("%s enter\n", __func__);
	spacing =
		((radio->registers[RADIOCFG] & CHANNEL_CSR0_CHSPACE) >> 8) * 10;
	band_bottom =
		(radio->registers[RADIOSEEKCFG2] & CHANNEL_CSR0_FREQ_BOT) * 10;

	/* read channel */
	retval = rtc6226_get_register(radio, CHANNEL1);
@@ -287,20 +245,17 @@ static int rtc6226_get_freq(struct rtc6226_device *radio, unsigned int *freq)
		goto end;
	}
	chan = radio->registers[CHANNEL1] & STATUS_READCH;
	#ifdef andrew
	retval = rtc6226_get_register(radio, RSSI);
	if (retval < 0) {
		pr_err("%s read fail to RSSI\n", __func__);
		goto end;
	}

	rssi = radio->registers[RSSI] & RSSI_RSSI;
	#endif

	pr_info("%s chan %d\n", __func__, chan);
	*freq = chan * 10;
	*freq = chan * TUNE_STEP_SIZE;
	pr_info("FMRICHWAVE, freq= %d, rssi= %d dBuV\n", *freq, rssi);

	if (rssi < radio->rssi_th)
		rtc6226_q_event(radio, RTC6226_EVT_BELOW_TH);
	else
		rtc6226_q_event(radio, RTC6226_EVT_ABOVE_TH);

end:
	return retval;
}
@@ -319,13 +274,13 @@ int rtc6226_set_freq(struct rtc6226_device *radio, unsigned int freq)
	pr_info("%s enter freq:%d\n", __func__, freq);

	band_bottom = (radio->registers[RADIOSEEKCFG2] &
		CHANNEL_CSR0_FREQ_BOT) * 10;
		CHANNEL_CSR0_FREQ_BOT) * TUNE_STEP_SIZE;

	if (freq < band_bottom)
		freq = band_bottom;

	/* Chan = Freq (Mhz) / 10 */
	chan = freq / 10;
	chan = (u16)(freq / TUNE_STEP_SIZE);

	pr_info("%s chan:%d freq:%d  band_bottom:%d\n", __func__,
			chan, freq, band_bottom);
@@ -355,9 +310,7 @@ static int rtc6226_set_seek(struct rtc6226_device *radio,
	 unsigned int seek_up, unsigned int seek_wrap)
{
	int retval = 0;
	bool timed_out = false;
	unsigned short seekcfg1_val = radio->registers[SEEKCFG1];
	int i;

	pr_info("%s enter up:%d wrap:%d, th:%d\n", __func__, seek_up, seek_wrap,
						seekcfg1_val);
@@ -386,32 +339,6 @@ static int rtc6226_set_seek(struct rtc6226_device *radio,
		goto done;
	}

	reinit_completion(&radio->completion);
	retval = wait_for_completion_timeout(&radio->completion,
			msecs_to_jiffies(seek_timeout));
	if (!retval) {
		timed_out = true;
		pr_err("%s timeout\n", __func__);
		rtc6226_get_all_registers(radio);
		for (i = 0; i < 16; i++)
			pr_info("%s registers[%d]:%x\n", __func__, i,
					radio->registers[i]);
	}

	if ((radio->registers[STATUS] & STATUS_STD) == 0)
		pr_info(" %s seek does not complete\n", __func__);
	if (radio->registers[STATUS] & STATUS_SF) {
		pr_info(" %s seek failed / band limit reached\n", __func__);
		//retval = -ESPIPE;
	}

	/* stop seeking : clear STD*/
	radio->registers[SEEKCFG1] &= ~SEEKCFG1_CSR0_SEEK;
	retval = rtc6226_set_register(radio, SEEKCFG1);

	if (retval == 0 && timed_out)
		retval = -EAGAIN;

done:
	pr_info("%s exit %d\n", __func__, retval);
	return retval;
@@ -438,11 +365,11 @@ void rtc6226_scan(struct work_struct *work)
	int len = 0;
	u32 next_freq_khz;
	int retval = 0;
	int i;

	pr_info("%s enter\n", __func__);

	radio = container_of(work, struct rtc6226_device, work_scan.work);
	radio->seek_tune_status = SEEK_PENDING;

	retval = rtc6226_get_freq(radio, &current_freq_khz);
	if (retval < 0) {
@@ -450,6 +377,16 @@ void rtc6226_scan(struct work_struct *work)
		goto seek_tune_fail;
	}
	pr_info("%s cuurent freq %d\n", __func__, current_freq_khz);
		/* tune to lowest freq of the band */
	radio->seek_tune_status = SCAN_PENDING;
	retval = rtc6226_set_freq(radio,
		radio->recv_conf.band_low_limit * TUNE_STEP_SIZE);
	if (retval < 0)
		goto seek_tune_fail;
	/* wait for tune to complete. */
	if (!wait_for_completion_timeout(&radio->completion,
				msecs_to_jiffies(WAIT_TIMEOUT_MSEC)))
		pr_err("In %s, didn't receive STC for tune\n", __func__);

	while (1) {
		if (radio->is_search_cancelled) {
@@ -469,26 +406,19 @@ void rtc6226_scan(struct work_struct *work)
			pr_err("%s seek fail %d\n", __func__, retval);
			goto seek_tune_fail;
		}

		if (radio->registers[STATUS] & STATUS_SF) {
			pr_err("%s band limit reached. Seek one more.\n",
			/* wait for seek to complete */
		if (!wait_for_completion_timeout(&radio->completion,
					msecs_to_jiffies(WAIT_TIMEOUT_MSEC))) {
			pr_err("%s:timeout didn't receive STC for seek\n",
						__func__);
			seek_timeout = 1000;
			retval = rtc6226_set_seek(radio, SRCH_UP, WRAP_ENABLE);
			seek_timeout = SEEK_TIME_OUT_VALUE;
			if (retval < 0) {
				pr_err("%s seek fail %d\n", __func__, retval);
				goto seek_tune_fail;
			}
			retval = rtc6226_get_freq(radio, &next_freq_khz);
			if (retval < 0) {
				pr_err("%s fail to get freq\n", __func__);
				goto seek_tune_fail;
			}
			pr_info("%s next freq %d\n", __func__, next_freq_khz);
			rtc6226_q_event(radio, RTC6226_EVT_TUNE_SUCC);
			break;
		}
			rtc6226_get_all_registers(radio);
			for (i = 0; i < 16; i++)
				pr_info("%s registers[%d]:%x\n", __func__, i,
					radio->registers[i]);
			/* FM is not correct state or scan is cancelled */
			continue;
		} else
			pr_err("%s: received STC for seek\n", __func__);

		retval = rtc6226_get_freq(radio, &next_freq_khz);
		if (retval < 0) {
@@ -506,9 +436,17 @@ void rtc6226_scan(struct work_struct *work)
		pr_info("%s valid channel %d, rssi %d\n", __func__,
			next_freq_khz, radio->registers[RSSI] & RSSI_RSSI);

		if (radio->registers[STATUS] & STATUS_SF) {
			pr_err("%s band limit reached. Seek one more.\n",
					__func__);
			break;
		}
		if (radio->g_search_mode == SCAN)
			rtc6226_q_event(radio, RTC6226_EVT_TUNE_SUCC);

		/*
		 * If scan is cancelled or FM is not ON, break ASAP so that we
		 * don't need to sleep for dwell time.
		 */
		if (radio->is_search_cancelled) {
			pr_err("%s: scan cancelled\n", __func__);
			if (radio->g_search_mode == SCAN_FOR_STRONG)
@@ -526,7 +464,7 @@ void rtc6226_scan(struct work_struct *work)
			msleep(radio->dwell_time_sec * 1000);
			/* need to queue the event when the seek completes */
			pr_info("%s frequency update list %d\n", __func__,
				next_freq_khz/16);
				next_freq_khz);
			rtc6226_q_event(radio, RTC6226_EVT_SCAN_NEXT);
		} else if (radio->g_search_mode == SCAN_FOR_STRONG) {
			rtc6226_update_search_list(radio, next_freq_khz);
@@ -543,8 +481,18 @@ void rtc6226_scan(struct work_struct *work)
				&radio->buf_lock[RTC6226_FM_BUF_SRCH_LIST]);
		rtc6226_q_event(radio, RTC6226_EVT_NEW_SRCH_LIST);
	}
	pr_err("%s seek tune fail %d\n", __func__, retval);

	/* tune to original frequency */
	retval = rtc6226_set_freq(radio, current_freq_khz);
	if (retval < 0)
		pr_err("%s: Tune to orig freq failed with error %d\n",
				__func__, retval);
	else {
		if (!wait_for_completion_timeout(&radio->completion,
			msecs_to_jiffies(WAIT_TIMEOUT_MSEC)))
			pr_err("%s: didn't receive STD for tune\n", __func__);
		else
			pr_err("%s: received STD for tune\n", __func__);
	}
seek_cancelled:
	rtc6226_q_event(radio, RTC6226_EVT_SEEK_COMPLETE);
	radio->seek_tune_status = NO_SEEK_TUNE_PENDING;
@@ -1431,7 +1379,17 @@ static int rtc6226_rds_on(struct rtc6226_device *radio)
int rtc6226_reset_rds_data(struct rtc6226_device *radio)
{
	mutex_lock(&radio->lock);

	radio->pi = 0;
	/* reset PS bufferes */
	memset(radio->ps_display, 0, sizeof(radio->ps_display));
	memset(radio->ps_tmp0, 0, sizeof(radio->ps_tmp0));
	memset(radio->ps_tmp1, 0, sizeof(radio->ps_tmp1));
	memset(radio->ps_cnt, 0, sizeof(radio->ps_cnt));

	memset(radio->rt_display, 0, sizeof(radio->rt_display));
	memset(radio->rt_tmp0, 0, sizeof(radio->rt_tmp0));
	memset(radio->rt_tmp1, 0, sizeof(radio->rt_tmp1));
	memset(radio->rt_cnt, 0, sizeof(radio->rt_cnt));
	radio->wr_index = 0;
	radio->rd_index = 0;
	memset(radio->buffer, 0, radio->buf_size);
@@ -1440,6 +1398,21 @@ int rtc6226_reset_rds_data(struct rtc6226_device *radio)
	return 0;
}

int rtc6226_set_rssi_threshold(struct rtc6226_device *radio, u16 rssi)
{
	int retval = 0;

	/*csr_rssi_low_th = RSSI_threshold/4*/
	rssi = rssi/4;
	if ((rssi < MIN_RSSI) && (rssi > MAX_RSSI))
		return -EINVAL;
	radio->registers[SEEKCFG1] &= ~SEEKCFG1_CSR0_RSSI_LOW_TH;
	radio->registers[SEEKCFG1] |= rssi << 8;
	retval = rtc6226_set_register(radio, SEEKCFG1);
	radio->rssi_th = (u8)(rssi*4);
	return retval;
}

int rtc6226_power_down(struct rtc6226_device *radio)
{
	int retval = 0;
@@ -1473,7 +1446,7 @@ int rtc6226_power_up(struct rtc6226_device *radio)

	/* mpxconfig */
	/* Disable Softmute / Disable Mute / De-emphasis / Volume 8 */
	radio->registers[MPXCFG] = 0x0000 |
	radio->registers[MPXCFG] = 0x0008 |
		MPXCFG_CSR0_DIS_SMUTE | MPXCFG_CSR0_DIS_MUTE |
		((de << 12) & MPXCFG_CSR0_DEEM);
	retval = rtc6226_set_register(radio, MPXCFG);
@@ -1526,6 +1499,10 @@ int rtc6226_power_up(struct rtc6226_device *radio)
	if (retval < 0)
		goto done;

	/*set default rssi threshold*/
	retval = rtc6226_set_rssi_threshold(radio, DEFAULT_RSSI_TH);
	if (retval < 0)
		pr_err("%s fail to set rssi threshold\n", __func__);

	/* powerconfig */
	/* Enable FM */
@@ -1533,7 +1510,8 @@ int rtc6226_power_up(struct rtc6226_device *radio)
	retval = rtc6226_set_register(radio, POWERCFG);
	if (retval < 0)
		goto done;

	/*wait for radio enable to complete*/
	usleep_range(50, 30000);
	retval = rtc6226_get_all_registers(radio);
	if (retval < 0)
		goto done;
@@ -1705,6 +1683,11 @@ int rtc6226_vidioc_g_ctrl(struct file *file, void *priv,
		pr_info("Get V4L2_CONTROL V4L2_CID_PRIVATE_DEVICEID: DEVICEID=0x%4.4hx\n",
			radio->registers[DEVICEID]);
		break;
	case V4L2_CID_PRIVATE_RTC6226_RDSGROUP_PROC:
		break;
	case V4L2_CID_PRIVATE_RTC6226_SIGNAL_TH:
		ctrl->value = radio->rssi_th;
		break;
	default:
		pr_info("%s in default id:%d\n", __func__, ctrl->id);
		retval = -EINVAL;
@@ -1811,11 +1794,10 @@ static int rtc6226_enable(struct rtc6226_device *radio)
{
	int retval = 0;

	retval = rtc6226_get_register(radio, POWERCFG);
	if ((radio->registers[POWERCFG] & POWERCFG_CSR0_ENABLE) == 0)
		rtc6226_power_up(radio);
	else
		pr_info("%s already turn on\n", __func__);
	rtc6226_get_register(radio, POWERCFG);
	retval = rtc6226_power_up(radio);
	if (retval < 0)
		goto done;

	if ((radio->registers[SYSCFG] &  SYSCFG_CSR0_STDIRQEN) == 0) {
		radio->registers[SYSCFG] |= SYSCFG_CSR0_RDSIRQEN;
@@ -1917,21 +1899,27 @@ int rtc6226_vidioc_s_ctrl(struct file *file, void *priv,
		rtc6226_search(radio, (bool)ctrl->value);
		break;
	case V4L2_CID_PRIVATE_RTC6226_LP_MODE:
		if (ctrl->value) {
			/* disable RDS interrupts */
			radio->registers[SYSCFG] &= ~SYSCFG_CSR0_RDSIRQEN;
			retval = rtc6226_set_register(radio, SYSCFG);
		} else {
			/* enable RDS interrupts */
			radio->registers[SYSCFG] |= SYSCFG_CSR0_RDSIRQEN;
			retval = rtc6226_set_register(radio, SYSCFG);
		}
		break;
	case V4L2_CID_PRIVATE_RTC6226_ANTENNA:
	case V4L2_CID_PRIVATE_RTC6226_RDSON:
	case V4L2_CID_PRIVATE_RTC6226_AF_JUMP:
	case V4L2_CID_PRIVATE_RTC6226_SRCH_CNT:
	case V4L2_CID_PRIVATE_RTC6226_RXREPEATCOUNT:
	case V4L2_CID_PRIVATE_RTC6226_SINR_THRESHOLD:
		retval = 0;
		break;
	case V4L2_CID_PRIVATE_RTC6226_RSSI_TH:
	case V4L2_CID_PRIVATE_RTC6226_SINR_THRESHOLD:
			radio->rssi_th = ctrl->value >> 16;
		radio->registers[SEEKCFG1] &= ~SEEKCFG1_CSR0_RSSI_LOW_TH;
		radio->registers[SEEKCFG1] |= radio->rssi_th;
		retval = rtc6226_set_register(radio, SEEKCFG1);
	case V4L2_CID_PRIVATE_RTC6226_SIGNAL_TH:
		retval = rtc6226_set_rssi_threshold(radio, ctrl->value);
		if (retval < 0)
			pr_err("%s fail to set rssi\n", __func__);
			pr_err("%s fail to set rssi threshold\n", __func__);
		rtc6226_get_register(radio, SEEKCFG1);
		pr_info("FMRICHWAVE RSSI_TH: Dec = %d , Hexa = %x\n",
			radio->registers[SEEKCFG1] & 0xFF,
@@ -1940,6 +1928,7 @@ int rtc6226_vidioc_s_ctrl(struct file *file, void *priv,
	/* case V4L2_CID_PRIVATE_RTC6226_OFS_THRESHOLD: */
	case V4L2_CID_PRIVATE_RTC6226_SPUR_FREQ_RMSSI:
		break;
	case V4L2_CID_PRIVATE_RTC6226_RDSD_BUF:
	case V4L2_CID_PRIVATE_RTC6226_RDSGROUP_MASK:
	case V4L2_CID_PRIVATE_RTC6226_RDSGROUP_PROC:
		if ((radio->registers[SYSCFG] & SYSCFG_CSR0_RDS_EN) == 0)
@@ -2003,8 +1992,8 @@ int rtc6226_vidioc_s_ctrl(struct file *file, void *priv,
			radio->registers[MPXCFG] |= MPXCFG_CSR0_DIS_MUTE;
		retval = rtc6226_set_register(radio, MPXCFG);
		break;
	case V4L2_CID_PRIVATE_CSR0_DIS_SMUTE:
		pr_info("V4L2_CID_PRIVATE_CSR0_DIS_SMUTE\n");
	case V4L2_CID_PRIVATE_RTC6226_SOFT_MUTE:
		pr_info("V4L2_CID_PRIVATE_RTC6226_SOFT_MUTE\n");
		if (ctrl->value == 1)
			radio->registers[MPXCFG] &= ~MPXCFG_CSR0_DIS_SMUTE;
		else
@@ -2083,7 +2072,7 @@ int rtc6226_vidioc_s_ctrl(struct file *file, void *priv,
		pr_info("V4L2_CID_PRIVATE_CSR0_DIS_AGC val=%d\n",
			ctrl->value);
		break;
	case V4L2_CID_PRIVATE_CSR0_RDS_EN:
	case V4L2_CID_PRIVATE_RTC6226_RDSON:
		pr_info(
		"V4L2_CSR0_RDS_EN:CHANNEL=0x%4.4hx SYSCFG=0x%4.4hx\n",
			radio->registers[CHANNEL],
@@ -2161,11 +2150,13 @@ static int rtc6226_vidioc_g_tuner(struct file *file, void *priv,
	tuner->capability = V4L2_TUNER_CAP_LOW | V4L2_TUNER_CAP_STEREO |
		V4L2_TUNER_CAP_RDS | V4L2_TUNER_CAP_RDS_BLOCK_IO;

	tuner->rangelow  = (radio->registers[RADIOSEEKCFG1] &
		CHANNEL_CSR0_FREQ_TOP) * 10;
	tuner->rangehigh = (radio->registers[RADIOSEEKCFG2] &
		CHANNEL_CSR0_FREQ_BOT) * 10;
	tuner->rangehigh = (radio->registers[RADIOSEEKCFG1] &
		CHANNEL_CSR0_FREQ_TOP) * TUNE_STEP_SIZE * TUNE_PARAM;
	tuner->rangelow = (radio->registers[RADIOSEEKCFG2] &
		CHANNEL_CSR0_FREQ_BOT) * TUNE_STEP_SIZE * TUNE_PARAM;

	pr_debug("%s low:%d high:%d\n", __func__,
		tuner->rangelow, tuner->rangehigh);
	/* stereo indicator == stereo (instead of mono) */
	if ((radio->registers[STATUS] & STATUS_SI) == 0)
		tuner->rxsubchans = V4L2_TUNER_SUB_MONO;
@@ -2178,10 +2169,13 @@ static int rtc6226_vidioc_g_tuner(struct file *file, void *priv,
	tuner->rxsubchans |= V4L2_TUNER_SUB_RDS;

	/* mono/stereo selector */
	if ((radio->registers[MPXCFG] & MPXCFG_CSR0_MONO) == 0)
	if ((radio->registers[MPXCFG] & MPXCFG_CSR0_MONO) == 0) {
		tuner->audmode = V4L2_TUNER_MODE_STEREO;
	else
		rtc6226_q_event(radio, RTC6226_EVT_STEREO);
	} else {
		tuner->audmode = V4L2_TUNER_MODE_MONO;
		rtc6226_q_event(radio, RTC6226_EVT_MONO);
	}

	/* min is worst, max is best; rssi: 0..0xff */
	tuner->signal = (radio->registers[RSSI] & RSSI_RSSI);
@@ -2259,11 +2253,14 @@ static int rtc6226_vidioc_g_frequency(struct file *file, void *priv,
{
	struct rtc6226_device *radio = video_drvdata(file);
	int retval = 0;
	unsigned int frq;

	pr_info("%s enter freq %d\n", __func__, freq->frequency);

	freq->type = V4L2_TUNER_RADIO;
	retval = rtc6226_get_freq(radio, &freq->frequency);
	retval = rtc6226_get_freq(radio, &frq);
	freq->frequency = frq * TUNE_PARAM;
	radio->tuned_freq_khz = frq * TUNE_STEP_SIZE;
	pr_info(" %s *freq=%d, ret %d\n", __func__, freq->frequency, retval);

	if (retval < 0)
@@ -2281,13 +2278,23 @@ static int rtc6226_vidioc_s_frequency(struct file *file, void *priv,
{
	struct rtc6226_device *radio = video_drvdata(file);
	int retval = 0;
	u32 f = 0;

	pr_info("%s enter freq = %d\n", __func__, freq->frequency);
	if (unlikely(freq == NULL)) {
		pr_err("%s:freq is null\n", __func__);
		return -EINVAL;
	}
	if (freq->type != V4L2_TUNER_RADIO)
		return -EINVAL;
	f = (freq->frequency)/TUNE_PARAM;

	retval = rtc6226_set_freq(radio, freq->frequency);

	radio->seek_tune_status = TUNE_PENDING;
	retval = rtc6226_set_freq(radio, f);
	if (retval < 0)
		pr_err("%s set frequency failed with %d\n", __func__, retval);
	else
		radio->tuned_freq_khz = f;

	return retval;
}
@@ -2315,9 +2322,6 @@ static int rtc6226_vidioc_s_hw_freq_seek(struct file *file, void *priv,
		radio->seek_tune_status = SEEK_PENDING;
		retval = rtc6226_set_seek(radio, seek->seek_upward,
				WRAP_ENABLE);
		rtc6226_q_event(radio, RTC6226_EVT_TUNE_SUCC);
		radio->seek_tune_status = NO_SEEK_TUNE_PENDING;
		rtc6226_q_event(radio, RTC6226_EVT_SCAN_NEXT);
	} else if ((radio->g_search_mode == SCAN) ||
			(radio->g_search_mode == SCAN_FOR_STRONG)) {
		/* scan */
@@ -2328,7 +2332,7 @@ static int rtc6226_vidioc_s_hw_freq_seek(struct file *file, void *priv,
		} else {
			pr_info("%s starting scan\n", __func__);
		}
		rtc6226_search(radio, 1);
		rtc6226_search(radio, START_SCAN);
	} else {
		retval = -EINVAL;
		pr_err("In %s, invalid search mode %d\n",
@@ -2338,13 +2342,11 @@ static int rtc6226_vidioc_s_hw_freq_seek(struct file *file, void *priv,
	return retval;
}

#ifndef RW_Kernel_ENG
static int rtc6226_vidioc_g_fmt_type_private(struct file *file, void *priv,
						struct v4l2_format *f)
{
	return 0;
}
#endif

static const struct v4l2_file_operations rtc6226_fops = {
	.owner			= THIS_MODULE,
@@ -2373,9 +2375,7 @@ const struct v4l2_ioctl_ops rtc6226_ioctl_ops = {
	.vidioc_s_frequency         =   rtc6226_vidioc_s_frequency,
	.vidioc_s_hw_freq_seek      =   rtc6226_vidioc_s_hw_freq_seek,
	.vidioc_dqbuf               =   rtc6226_vidioc_dqbuf,
#ifndef RW_Kernel_ENG
	.vidioc_g_fmt_type_private  =	rtc6226_vidioc_g_fmt_type_private,
#endif
};

/*
+62 −38
Original line number Diff line number Diff line
@@ -226,6 +226,7 @@ static void rtc6226_i2c_interrupt_handler(struct rtc6226_device *radio)
{
	unsigned char regnr;
	int retval = 0;
	unsigned short current_chan;

	pr_info("%s enter\n", __func__);

@@ -235,24 +236,55 @@ static void rtc6226_i2c_interrupt_handler(struct rtc6226_device *radio)
		pr_err("%s read fail to STATUS\n", __func__);
		goto end;
	}
	pr_debug("%s : STATUS=0x%4.4hx\n", __func__, radio->registers[STATUS]);

	retval = rtc6226_get_register(radio, RSSI);
	if (retval < 0) {
		pr_err("%s read fail to RSSI\n", __func__);
		goto end;
	}
	pr_debug("%s : RSSI=0x%4.4hx\n", __func__, radio->registers[RSSI]);

	if (radio->registers[STATUS] & STATUS_STD) {
			/* stop seeking : clear STD*/
		radio->registers[SEEKCFG1] &= ~SEEKCFG1_CSR0_SEEK;
		retval = rtc6226_set_register(radio, SEEKCFG1);
		/*clear the status bit to allow another tune or seek*/
		current_chan = radio->registers[CHANNEL] & CHANNEL_CSR0_CH;
		radio->registers[CHANNEL] &= ~CHANNEL_CSR0_TUNE;
		retval = rtc6226_set_register(radio, CHANNEL);
		if (retval < 0)
			radio->registers[CHANNEL] = current_chan;
		rtc6226_reset_rds_data(radio);
		pr_debug("%s clear Seek/Tune bit\n", __func__);
		if (radio->seek_tune_status == SEEK_PENDING) {
			pr_debug("posting RTC6226_EVT_SEEK_COMPLETE event\n");
			rtc6226_q_event(radio, RTC6226_EVT_SEEK_COMPLETE);
			/* post tune comp evt since seek results in a tune.*/
			pr_debug("posting RICHWAVE_EVT_TUNE_SUCC event\n");
			rtc6226_q_event(radio, RTC6226_EVT_TUNE_SUCC);
			radio->seek_tune_status = NO_SEEK_TUNE_PENDING;
		} else if (radio->seek_tune_status == TUNE_PENDING) {
			pr_debug("posting RICHWAVE_EVT_TUNE_SUCC event\n");
			rtc6226_q_event(radio, RTC6226_EVT_TUNE_SUCC);
			radio->seek_tune_status = NO_SEEK_TUNE_PENDING;
		} else if (radio->seek_tune_status == SCAN_PENDING) {
			/* when scan is pending and STC int is set, signal
			 * so that scan can proceed
			 */
			pr_debug("In %s, signalling scan thread\n", __func__);
			complete(&radio->completion);
		pr_info("%s Seek/Tune Done\n", __func__);
		}

	/* Update RDS registers */
		pr_debug("%s Seek/Tune done\n", __func__);
	} else {
		/* Check RDS data after tune/seek interrupt finished
		 * Update RDS registers
		 */
		for (regnr = 1; regnr < RDS_REGISTER_NUM; regnr++) {
			retval = rtc6226_get_register(radio, STATUS + regnr);
			if (retval < 0)
				goto end;
		}

		/* get rds blocks */
		if ((radio->registers[STATUS] & STATUS_RDS_RDY) == 0) {
			/* No RDS group ready, better luck next time */
@@ -260,11 +292,13 @@ static void rtc6226_i2c_interrupt_handler(struct rtc6226_device *radio)
			goto end;
		} else {
			/* avoid RDS interrupt lock disable_irq*/
		if ((radio->registers[SYSCFG] & SYSCFG_CSR0_RDS_EN) != 0) {
			pr_info("%s start rds handler\n", __func__);
			if ((radio->registers[SYSCFG] &
						SYSCFG_CSR0_RDS_EN) != 0) {
				pr_debug("%s start rds handler\n", __func__);
				schedule_work(&radio->rds_worker);
			}
		}
	}
end:
	pr_info("%s exit :%d\n", __func__, retval);
}
@@ -363,40 +397,28 @@ int rtc6226_fops_open(struct file *file)
{
	struct rtc6226_device *radio = video_drvdata(file);
	int retval = v4l2_fh_open(file);
	int i;

	pr_info("%s enter\n", __func__);
	pr_debug("%s enter user num = %d\n", __func__, radio->users);
	if (retval) {
		pr_err("%s fail to open v4l2\n", __func__);
		return retval;
	}

	if (radio->users == 0)
		radio->users++;
	else {
		pr_err("Device already in use. Try again later\n");
		return -EBUSY;
	}

	INIT_DELAYED_WORK(&radio->work, rtc6226_handler);
	INIT_DELAYED_WORK(&radio->work_scan, rtc6226_scan);
	INIT_WORK(&radio->rds_worker, rtc6226_rds_handler);

	if (v4l2_fh_is_singular_file(file)) {
		retval = rtc6226_power_up(radio);
		if (retval < 0) {
			pr_err("%s fail to power_up\n", __func__);
			goto done;
			//return retval;
		}
	}

	retval = rtc6226_get_all_registers(radio);
	if (retval < 0)
		pr_err("%s fail to get register %d\n", __func__, retval);
	else {
		for (i = 0; i < 16; i++)
			pr_info("%s registers[%d]:%x\n", __func__, i,
				radio->registers[i]);
	}
	/* Wait for the value to take effect on gpio. */
	msleep(100);
	rtc6226_enable_irq(radio);

done:
	if (retval)
		v4l2_fh_release(file);
	return retval;
@@ -417,6 +439,7 @@ int rtc6226_fops_release(struct file *file)
		}
	}
	rtc6226_disable_irq(radio);
	radio->users--;
	return v4l2_fh_release(file);
}

@@ -601,6 +624,7 @@ static int rtc6226_i2c_probe(struct i2c_client *client,
	radio->wqueue = NULL;
	radio->wqueue_scan = NULL;
	radio->wqueue_rds = NULL;
	radio->band = -1;

	/* rds buffer configuration */
	radio->wr_index = 0;
+9 −4
Original line number Diff line number Diff line
@@ -182,7 +182,7 @@

#define WRAP_ENABLE      1
#define WRAP_DISABLE     0

#define DEFAULT_RSSI_TH  8
/* Standard buffer size */
#define STD_BUF_SIZE     256

@@ -191,6 +191,8 @@
#define TUNE_PENDING 1
#define SEEK_PENDING 2
#define SCAN_PENDING 3
#define START_SCAN 1
#define WAIT_TIMEOUT_MSEC 7000

#define RTC6226_MIN_SRCH_MODE 0x00
#define RTC6226_MAX_SRCH_MODE 0x02
@@ -302,6 +304,8 @@
#define GET_AF_LIST_LEN(x) (x*4)
#define MIN_AF_FREQ_CODE 1
#define MAX_AF_FREQ_CODE 204
#define MIN_RSSI 0
#define MAX_RSSI 15

/* 25 AFs supported for a freq. 224 means 1 AF. 225 means 2 AFs and so on */
#define NO_AF_CNT_CODE 224
@@ -349,12 +353,11 @@
#define V4L2_CID_PRIVATE_RDS_SYNC	    (RW_PRIBASE + (CHIPID<<4) + 5)
#define V4L2_CID_PRIVATE_SI	            (RW_PRIBASE + (CHIPID<<4) + 6)

#define WAIT_OVER			0
#define SEEK_WAITING		1
#define NO_WAIT				2
#define TUNE_WAITING		4
#define RDS_WAITING			5
#define SEEK_CANCEL			6
#define TUNE_PARAM 16

/**************************************************************************
 * General Driver Definitions
 **************************************************************************/
@@ -666,3 +669,5 @@ void rtc6226_scan(struct work_struct *work);
void rtc6226_search(struct rtc6226_device *radio, bool on);
int rtc6226_cancel_seek(struct rtc6226_device *radio);
void rtc6226_rds_handler(struct work_struct *worker);
void rtc6226_q_event(struct rtc6226_device *radio, enum rtc6226_evt_t event);
int rtc6226_reset_rds_data(struct rtc6226_device *radio);