board: msm7x27a: Put BT GPIO in LPM when not in use.

Bahama's SYS RESET GPIO from the i/o expander is put in low
power mode when not in use, for power optimization.

CRs-Fixed: 294153
CRs-Fixed: 295572
Signed-off-by: Rahul Kashyap <rkashyap@codeaurora.org>
diff --git a/arch/arm/mach-msm/board-msm7x27a.c b/arch/arm/mach-msm/board-msm7x27a.c
index 6f2249b..b727475 100644
--- a/arch/arm/mach-msm/board-msm7x27a.c
+++ b/arch/arm/mach-msm/board-msm7x27a.c
@@ -56,6 +56,7 @@
 #define MSM_PMEM_AUDIO_SIZE	0x5B000
 #define BAHAMA_SLAVE_ID_FM_ADDR         0x2A
 #define BAHAMA_SLAVE_ID_QMEMBIST_ADDR   0x7B
+#define BAHAMA_SLAVE_ID_FM_REG 0x02
 #define FM_GPIO	83
 
 enum {
@@ -299,12 +300,35 @@
 	return rc;
 }
 
+static int bt_set_gpio(int on)
+{
+	int rc = 0;
+	struct marimba config = { .mod_id =  SLAVE_ID_BAHAMA};
+
+	if (on) {
+		rc = gpio_direction_output(GPIO_BT_SYS_REST_EN, 1);
+		msleep(100);
+	} else {
+		if (!marimba_get_fm_status(&config) &&
+				!marimba_get_bt_status(&config)) {
+			gpio_set_value_cansleep(GPIO_BT_SYS_REST_EN, 0);
+			rc = gpio_direction_input(GPIO_BT_SYS_REST_EN);
+			msleep(100);
+		}
+	}
+	if (rc)
+		pr_err("%s: BT sys_reset_en GPIO : Error", __func__);
+
+	return rc;
+}
 static struct vreg *fm_regulator;
 static int fm_radio_setup(struct marimba_fm_platform_data *pdata)
 {
 	int rc = 0;
 	const char *id = "FMPW";
 	uint32_t irqcfg;
+	struct marimba config = { .mod_id =  SLAVE_ID_BAHAMA};
+	u8 value;
 
 	/* Voting for 1.8V Regulator */
 	fm_regulator = vreg_get(NULL , "msme1");
@@ -339,6 +363,19 @@
 		goto fm_clock_vote_fail;
 	}
 
+	rc = bt_set_gpio(1);
+	if (rc) {
+		pr_err("%s: bt_set_gpio = %d", __func__, rc);
+		goto fm_gpio_config_fail;
+	}
+	/*re-write FM Slave Id, after reset*/
+	value = BAHAMA_SLAVE_ID_FM_ADDR;
+	rc = marimba_write_bit_mask(&config,
+			BAHAMA_SLAVE_ID_FM_REG, &value, 1, 0xFF);
+	if (rc < 0) {
+		pr_err("%s: FM Slave ID rewrite Failed = %d", __func__, rc);
+		goto fm_gpio_config_fail;
+	}
 	/* Configuring the FM GPIO */
 	irqcfg = GPIO_CFG(FM_GPIO, 0, GPIO_CFG_INPUT, GPIO_CFG_NO_PULL,
 			GPIO_CFG_2MA);
@@ -355,6 +392,7 @@
 fm_gpio_config_fail:
 	pmapp_clock_vote(id, PMAPP_CLOCK_ID_D1,
 		PMAPP_CLOCK_VOTE_OFF);
+	bt_set_gpio(0);
 fm_clock_vote_fail:
 	vreg_disable(fm_regulator);
 
@@ -391,10 +429,12 @@
 	/* Voting off the clock */
 	rc = pmapp_clock_vote(id, PMAPP_CLOCK_ID_D1,
 		PMAPP_CLOCK_VOTE_OFF);
-
 	if (rc < 0)
 		pr_err("%s: voting off failed with :(%d)\n",
 			__func__, rc);
+	rc = bt_set_gpio(0);
+	if (rc)
+		pr_err("%s: bt_set_gpio = %d", __func__, rc);
 }
 
 static struct marimba_fm_platform_data marimba_fm_pdata = {
@@ -645,9 +685,9 @@
 			GPIO_BT_SYS_REST_EN, rc);
 		goto vreg_fail;
 	}
-	rc = gpio_direction_output(GPIO_BT_SYS_REST_EN, 1);
+	rc = bt_set_gpio(1);
 	if (rc < 0) {
-		pr_err("%s: gpio_direction_output %d = %d\n", __func__,
+		pr_err("%s: bt_set_gpio %d = %d\n", __func__,
 			GPIO_BT_SYS_REST_EN, rc);
 		goto gpio_fail;
 	}
@@ -678,18 +718,21 @@
 		vreg_put(vreg_s3);
 		return rc;
 	}
-
+	rc = bt_set_gpio(0);
+	if (rc) {
+		pr_err("%s: bt_set_gpio = %d\n",
+		       __func__, rc);
+	}
 	return rc;
 }
 
-
 static unsigned int msm_bahama_core_config(int type)
 {
 	int rc = 0;
 
 	if (type == BAHAMA_ID) {
 		int i;
-		struct marimba config = { .mod_id = SLAVE_ID_BAHAMA };
+		struct marimba config = { .mod_id =  SLAVE_ID_BAHAMA};
 		const struct bahama_config_register v20_init[] = {
 			/* reg, value, mask */
 			{ 0xF4, 0x84, 0xFF }, /* AREG */
@@ -715,6 +758,11 @@
 			}
 		}
 	}
+	rc = bt_set_gpio(0);
+	if (rc) {
+		pr_err("%s: bt_set_gpio = %d\n",
+		       __func__, rc);
+	}
 	pr_debug("core type: %d\n", type);
 	return rc;
 }
@@ -733,6 +781,12 @@
 	}
 	if (on) {
 		/*setup power for BT SOC*/
+		rc = bt_set_gpio(on);
+		if (rc) {
+			pr_err("%s: bt_set_gpio = %d\n",
+					__func__, rc);
+			goto exit;
+		}
 		rc = bluetooth_switch_regulators(on);
 		if (rc < 0) {
 			pr_err("%s: bluetooth_switch_regulators rc = %d",
@@ -786,6 +840,12 @@
 		rc = bahama_bt(0);
 		if (rc < 0)
 			pr_err("%s: bahama_bt rc = %d", __func__, rc);
+
+		rc = bt_set_gpio(on);
+		if (rc) {
+			pr_err("%s: bt_set_gpio = %d\n",
+					__func__, rc);
+		}
 fail_i2c:
 		rc = pmapp_clock_vote(id, PMAPP_CLOCK_ID_D1,
 				  PMAPP_CLOCK_VOTE_OFF);