radio-tavarua: Add host side support for the new FM Search Algorithm

Change-Id: Iba497b84e525d08fa588bb7f58ff6a238452c47c
CRs-Fixed: 314648
Signed-off-by: Anantha Krishnan <ananthk@codeaurora.org>
diff --git a/drivers/media/radio/radio-tavarua.c b/drivers/media/radio/radio-tavarua.c
index 0597308..d09f89f 100644
--- a/drivers/media/radio/radio-tavarua.c
+++ b/drivers/media/radio/radio-tavarua.c
@@ -118,6 +118,7 @@
 	int pi;
 	/*PS repeatcount for PS Tx */
 	int ps_repeatcount;
+	int enable_optimized_srch_alg;
 };
 
 /**************************************************************************
@@ -1162,6 +1163,169 @@
 	return 0;
 }
 
+static int optimized_search_algorithm(struct tavarua_device *radio,
+				int region)
+{
+	unsigned char adie_type_bahma;
+	int retval = 0;
+	unsigned int rdsMask = 0;
+	unsigned char value;
+
+	adie_type_bahma = is_bahama();
+
+	switch (region) {
+	case TAVARUA_REGION_US:
+	/*
+	Radio band for all the 200KHz channel-spaced regions
+	coming under EUROPE too, have been set as TAVARUA_REGION_US.
+	*/
+	FMDBG("%s: The region selected from APP is"
+		" : TAVARUA_REGION_US", __func__);
+	break;
+	case TAVARUA_REGION_EU:
+	/*
+	Radio band for all the 50KHz channel-spaced regions
+	coming under EUROPE, have been set as TAVARUA_REGION_EU.
+	*/
+	FMDBG("%s: The region selected from APP is : "
+		"TAVARUA_REGION_EU", __func__);
+	break;
+	case TAVARUA_REGION_JAPAN:
+	/*
+	Radio band for the 100KHz channel-spaced JAPAN region
+	has been set as TAVARUA_REGION_JAPAN.
+	*/
+	FMDBG("%s: The region selected from APP is"
+		" : TAVARUA_REGION_JAPAN", __func__);
+	break;
+	case TAVARUA_REGION_JAPAN_WIDE:
+	/*
+	Radio band for the 50KHz channel-spaced JAPAN WIDE region
+	has been set as TAVARUA_REGION_JAPAN_WIDE.
+	*/
+	FMDBG("%s: The region selected from APP is"
+		" : TAVARUA_REGION_JAPAN_WIDE", __func__);
+	break;
+	case TAVARUA_REGION_OTHER:
+	/*
+	Radio band for all the 100KHz channel-spaced regions
+	including those coming under EUROPE have been set as
+	TAVARUA_REGION_OTHER.
+	*/
+	FMDBG("%s: The region selected from APP is"
+		" : TAVARUA_REGION_OTHER", __func__);
+	break;
+	default:
+		pr_err("%s: Should not reach here.", __func__);
+		break;
+
+	}
+
+	/* Enable or Disable the 200KHz enforcer */
+	switch (region) {
+	case TAVARUA_REGION_US:
+	case TAVARUA_REGION_JAPAN:
+	case TAVARUA_REGION_OTHER:
+	/*
+	These are the 3 bands for which we need to enable the
+	200KHz enforcer in ADVCTL reg.
+	*/
+		if (adie_type_bahma) {
+			FMDBG("Adie type : Bahama\n");
+			FMDBG("%s: Enabling the 200KHz enforcer for"
+				" Region : %d", __func__, region);
+			/*Enable the 200KHz enforcer*/
+			retval = tavarua_read_registers(radio,
+				ADVCTRL, 1);
+			if (retval >= 0) {
+				rdsMask = radio->registers[ADVCTRL];
+				SET_REG_FIELD(rdsMask, ENF_SRCH200khz,
+					SRCH200KHZ_OFFSET, SRCH_MASK);
+				retval = tavarua_write_register(radio,
+					ADVCTRL, rdsMask);
+			} else
+				return retval;
+		} /* if Marimba do nothing */
+		break;
+	case TAVARUA_REGION_EU:
+	case TAVARUA_REGION_JAPAN_WIDE:
+	/*
+	These are the 2 bands for which we need to disable the
+	200KHz enforcer in ADVCTL reg.
+	Radio band for all the 50KHz channel-spaced regions
+	coming under EUROPE have been set as TAVARUA_REGION_EU.
+	*/
+		if (adie_type_bahma) {
+			FMDBG("Adie type : Bahama\n");
+			FMDBG("%s: Disabling the 200KHz enforcer for"
+				" Region : %d", __func__, region);
+			/*
+			Disable 200KHz enforcer for all 50 KHz
+			spaced regions.
+			*/
+			retval = tavarua_read_registers(radio,
+				ADVCTRL, 1);
+			if (retval >= 0) {
+				rdsMask = radio->registers[ADVCTRL];
+				SET_REG_FIELD(rdsMask, NO_SRCH200khz,
+					SRCH200KHZ_OFFSET, SRCH_MASK);
+				retval = tavarua_write_register(radio,
+					ADVCTRL, rdsMask);
+			} else
+				return retval;
+		} /* if Marimba do nothing */
+		break;
+	default:
+		FMDBG("%s: Defaulting in case of Enabling/Disabling"
+			"the 200KHz Enforcer", __func__);
+		break;
+	}
+
+	/* Set channel spacing */
+	switch (region) {
+	case TAVARUA_REGION_US:
+		if (adie_type_bahma) {
+			FMDBG("Adie type : Bahama\n");
+			/*
+			Configuring all 200KHZ spaced regions as 100KHz due to
+			change in the new Bahma FM SoC search algorithm.
+			*/
+			value = FM_CH_SPACE_100KHZ;
+		} else {
+			FMDBG("Adie type : Marimba\n");
+			value = FM_CH_SPACE_200KHZ;
+		}
+		break;
+	case TAVARUA_REGION_JAPAN:
+	case TAVARUA_REGION_OTHER:
+		if (adie_type_bahma) {
+			FMDBG("Adie type : Bahama\n");
+			FMDBG("%s: Configuring the channel-spacing as 50KHz"
+				"for the Region : %d", __func__, region);
+			/*
+			Configuring all 100KHZ spaced regions as 50KHz due to
+			change in the new Bahma FM SoC search algorithm.
+			*/
+			value = FM_CH_SPACE_50KHZ;
+		} else {
+			FMDBG("Adie type : Marimba\n");
+			value = FM_CH_SPACE_100KHZ;
+		}
+		break;
+	case TAVARUA_REGION_EU:
+	case TAVARUA_REGION_JAPAN_WIDE:
+		value = FM_CH_SPACE_50KHZ;
+		break;
+	default:
+		FMDBG("%s: Defualting in case of Channel-Spacing", __func__);
+		break;
+	}
+
+	SET_REG_FIELD(radio->registers[RDCTRL], value,
+		RDCTRL_CHSPACE_OFFSET, RDCTRL_CHSPACE_MASK);
+
+	return retval;
+}
 /*************************************************************************
  * fops/IOCTL helper functions
  ************************************************************************/
@@ -1255,14 +1419,11 @@
 	switch (region) {
 	case TAVARUA_REGION_US:
 	case TAVARUA_REGION_EU:
-	case TAVARUA_REGION_JAPAN_WIDE:
 		SET_REG_FIELD(radio->registers[RDCTRL], 0,
 			RDCTRL_BAND_OFFSET, RDCTRL_BAND_MASK);
 		break;
+	case TAVARUA_REGION_JAPAN_WIDE:
 	case TAVARUA_REGION_JAPAN:
-		SET_REG_FIELD(radio->registers[RDCTRL], 1,
-			RDCTRL_BAND_OFFSET, RDCTRL_BAND_MASK);
-		break;
 	default:
 		retval = sync_read_xfr(radio, RADIO_CONFIG, xfr_buf);
 		if (retval < 0) {
@@ -1286,85 +1447,6 @@
 		break;
 	}
 
-	/* Enable/Disable the 200KHz enforcer for respectiver regions */
-	switch (region) {
-	case TAVARUA_REGION_US:
-		if (adie_type_bahma) {
-			FMDBG("Adie type : Bahama\n");
-			/*Enable the 200KHz enforcer*/
-			retval = tavarua_read_registers(radio,
-				ADVCTRL, 1);
-			if (retval >= 0) {
-				rdsMask = radio->registers[ADVCTRL];
-				SET_REG_FIELD(rdsMask, ENF_SRCH200khz,
-					SRCH200KHZ_OFFSET, SRCH_MASK);
-				msleep(TAVARUA_DELAY);
-				retval = tavarua_write_register(radio,
-					ADVCTRL, rdsMask);
-			} else
-				return retval;
-		} /* if Marimba do nothing */
-		break;
-	case TAVARUA_REGION_EU:
-	case TAVARUA_REGION_JAPAN:
-	case TAVARUA_REGION_JAPAN_WIDE:
-	default:
-		if (adie_type_bahma) {
-			FMDBG("Adie type : Bahama\n");
-			/*
-			Disable 200KHz enforcer for all 100/50 KHz
-			spaced regions.
-			*/
-			retval = tavarua_read_registers(radio,
-				ADVCTRL, 1);
-			if (retval >= 0) {
-				rdsMask = radio->registers[ADVCTRL];
-				SET_REG_FIELD(rdsMask, NO_SRCH200khz,
-					SRCH200KHZ_OFFSET, SRCH_MASK);
-				msleep(TAVARUA_DELAY);
-				retval = tavarua_write_register(radio,
-					ADVCTRL, rdsMask);
-			} else
-				return retval;
-		} /* if Marimba do nothing */
-		break;
-	}
-
-	/* Set channel spacing */
-	switch (region) {
-	case TAVARUA_REGION_US:
-		if (adie_type_bahma) {
-			FMDBG("Adie type : Bahama\n");
-			/*
-			Configuring all 200KHZ spaced regions as
-			100KHz due to change in the new Bahma
-			FM SoC search algorithm.
-			*/
-			value = FM_CH_SPACE_100KHZ;
-		} else {
-			FMDBG("Adie type : Marimba\n");
-			value = FM_CH_SPACE_200KHZ;
-		}
-		break;
-	case TAVARUA_REGION_EU:
-	case TAVARUA_REGION_JAPAN:
-		value = FM_CH_SPACE_100KHZ;
-		break;
-	case TAVARUA_REGION_JAPAN_WIDE:
-		value = FM_CH_SPACE_50KHZ;
-		break;
-	default:
-		/*
-		Set the channel spacing as configured from
-		the upper layers.
-		*/
-		value = radio->region_params.spacing;
-		break;
-	}
-
-	SET_REG_FIELD(radio->registers[RDCTRL], value,
-		RDCTRL_CHSPACE_OFFSET, RDCTRL_CHSPACE_MASK);
-
 	/* Set De-emphasis and soft band range*/
 	switch (region) {
 	case TAVARUA_REGION_US:
@@ -1403,13 +1485,6 @@
 	if (retval < 0)
 		return retval;
 
-	FMDBG("RDCTRL: %x\n", radio->registers[RDCTRL]);
-	retval = tavarua_write_register(radio, RDCTRL,
-					radio->registers[RDCTRL]);
-	if (retval < 0) {
-		FMDERR("Could not set region in rdctrl\n");
-		return retval;
-	}
 
 	/* setting soft band */
 	switch (region) {
@@ -1430,6 +1505,101 @@
 		break;
 	}
 	radio->region_params.region = region;
+
+	/* Check for the FM Algorithm used */
+	if (radio->enable_optimized_srch_alg) {
+		FMDBG("Optimized Srch Algorithm!!!");
+		optimized_search_algorithm(radio, region);
+	} else {
+		FMDBG("Native Srch Algorithm!!!");
+		/* Enable/Disable the 200KHz enforcer */
+		switch (region) {
+		case TAVARUA_REGION_US:
+			if (adie_type_bahma) {
+				FMDBG("Adie type : Bahama\n");
+				/*Enable the 200KHz enforcer*/
+				retval = tavarua_read_registers(radio,
+					ADVCTRL, 1);
+				if (retval >= 0) {
+					rdsMask = radio->registers[ADVCTRL];
+					SET_REG_FIELD(rdsMask, ENF_SRCH200khz,
+						SRCH200KHZ_OFFSET, SRCH_MASK);
+					retval = tavarua_write_register(radio,
+						ADVCTRL, rdsMask);
+				} else
+					return retval;
+			} /* if Marimba do nothing */
+			break;
+		case TAVARUA_REGION_EU:
+		case TAVARUA_REGION_JAPAN:
+		case TAVARUA_REGION_JAPAN_WIDE:
+		default:
+			if (adie_type_bahma) {
+				FMDBG("Adie type : Bahama\n");
+				/*
+				Disable 200KHz enforcer for all 100/50 KHz
+				spaced regions.
+				*/
+				retval = tavarua_read_registers(radio,
+					ADVCTRL, 1);
+				if (retval >= 0) {
+					rdsMask = radio->registers[ADVCTRL];
+					SET_REG_FIELD(rdsMask, NO_SRCH200khz,
+						SRCH200KHZ_OFFSET, SRCH_MASK);
+					retval = tavarua_write_register(radio,
+						ADVCTRL, rdsMask);
+				} else
+					return retval;
+			} /* if Marimba do nothing */
+			break;
+		}
+
+		/* Set channel spacing */
+		switch (region) {
+		case TAVARUA_REGION_US:
+			if (adie_type_bahma) {
+				FMDBG("Adie type : Bahama\n");
+				/*
+				Configuring all 200KHZ spaced regions as
+				100KHz due to change in the new Bahma
+				FM SoC search algorithm.
+				*/
+				value = FM_CH_SPACE_100KHZ;
+			} else {
+				FMDBG("Adie type : Marimba\n");
+				value = FM_CH_SPACE_200KHZ;
+			}
+			break;
+		case TAVARUA_REGION_JAPAN:
+			value = FM_CH_SPACE_100KHZ;
+			break;
+		case TAVARUA_REGION_EU:
+		case TAVARUA_REGION_JAPAN_WIDE:
+			value = FM_CH_SPACE_50KHZ;
+			break;
+		default:
+			/*
+			Set the channel spacing as configured from
+			the upper layers.
+			*/
+			value = radio->region_params.spacing;
+			break;
+		}
+
+		SET_REG_FIELD(radio->registers[RDCTRL], value,
+			RDCTRL_CHSPACE_OFFSET, RDCTRL_CHSPACE_MASK);
+
+	}
+
+	/* Write the config values into RDCTL register */
+	FMDBG("RDCTRL: %x\n", radio->registers[RDCTRL]);
+	retval = tavarua_write_register(radio, RDCTRL,
+					radio->registers[RDCTRL]);
+	if (retval < 0) {
+		FMDERR("Could not set region in rdctrl\n");
+		return retval;
+	}
+
 	return retval;
 }
 
@@ -2839,6 +3009,11 @@
 			}
 		}
 		break;
+	case V4L2_CID_PRIVATE_TAVARUA_SRCH_ALGORITHM:
+		radio->enable_optimized_srch_alg = ctrl->value;
+		FMDBG("V4L2_CID_PRIVATE_TAVARUA_SRCH_ALGORITHM : %d",
+			radio->enable_optimized_srch_alg);
+		break;
 	case V4L2_CID_PRIVATE_TAVARUA_REGION:
 		retval = tavarua_set_region(radio, ctrl->value);
 		break;
diff --git a/include/media/tavarua.h b/include/media/tavarua.h
index 43ce153..d40829e 100644
--- a/include/media/tavarua.h
+++ b/include/media/tavarua.h
@@ -148,13 +148,14 @@
 	V4L2_CID_PRIVATE_TAVARUA_RSSI_DELTA,
 	V4L2_CID_PRIVATE_TAVARUA_HLSI,
 	/*
-	* Here We have IOCTl's that are specifici to IRIS
-	* (V4L2_CID_PRIVATE_BASE+0x1D--V4L2_CID_PRIVATE_BASE+0x27)
+	* Here we have IOCTl's that are specific to IRIS
+	* (V4L2_CID_PRIVATE_BASE + 0x1E to V4L2_CID_PRIVATE_BASE + 0x27)
 	*/
 	V4L2_CID_PRIVATE_TAVARUA_SET_NOTCH_FILTER =
-		V4L2_CID_PRIVATE_BASE + 0x28,
+		V4L2_CID_PRIVATE_BASE + 0x28, /* IRIS specific command */
 	V4L2_CID_PRIVATE_TAVARUA_SET_AUDIO_PATH,
-	/*0x800002a is used for iris specific ioctl*/
+	V4L2_CID_PRIVATE_TAVARUA_DO_CALIBRATION, /* IRIS specific command */
+	V4L2_CID_PRIVATE_TAVARUA_SRCH_ALGORITHM,
 
 	V4L2_CID_PRIVATE_TAVARUA_ON_CHANNEL_THRESHOLD =
 		V4L2_CTRL_CLASS_USER + 0x92B,