msm:board-qrd7x27a: Switch WCN2243 I2S/PCM pins btw High-z and Normal

The PCM GPIOs on QRD are multiplexed btw I2S and PCM modes, to support
FM on QRD7x27a. The WCN2243 pins are also required to be switched btw
high-z and normal modes to keep only one of FM/BT-SCO active at a time.

Change-Id: Ida8d0e38fcb417425eed1bc78303ccc80ff7ae06
Signed-off-by: Rahul Kashyap <rkashyap@codeaurora.org>
diff --git a/arch/arm/mach-msm/board-qrd7627a.c b/arch/arm/mach-msm/board-qrd7627a.c
index 889ac00..e8f6443 100644
--- a/arch/arm/mach-msm/board-qrd7627a.c
+++ b/arch/arm/mach-msm/board-qrd7627a.c
@@ -60,6 +60,15 @@
 #define BAHAMA_SLAVE_ID_QMEMBIST_ADDR   0x7B
 #define BAHAMA_SLAVE_ID_FM_REG 0x02
 #define FM_GPIO	83
+#define BT_PCM_BCLK_MODE  0x88
+#define BT_PCM_DIN_MODE   0x89
+#define BT_PCM_DOUT_MODE  0x8A
+#define BT_PCM_SYNC_MODE  0x8B
+#define FM_I2S_SD_MODE    0x8E
+#define FM_I2S_WS_MODE    0x8F
+#define FM_I2S_SCK_MODE   0x90
+#define I2C_PIN_CTL       0x15
+#define I2C_NORMAL        0x40
 
 enum {
 	GPIO_HOST_VBUS_EN	= 107,
@@ -79,6 +88,57 @@
 #define FPGA_MSM_CNTRL_REG2 0x90008010
 
 #if defined(CONFIG_BT) && defined(CONFIG_MARIMBA_CORE)
+static int switch_pcm_i2s_reg_mode(int mode)
+{
+	unsigned char reg = 0;
+	int rc = -1;
+	unsigned char set = I2C_PIN_CTL; /*SET PIN CTL mode*/
+	unsigned char unset = I2C_NORMAL; /* UNSET PIN CTL MODE*/
+	struct marimba config = { .mod_id =  SLAVE_ID_BAHAMA};
+
+	if (mode == 0) {
+		/* as we need to switch path to FM we need to move
+		 BT AUX PCM lines to PIN CONTROL mode then move
+		 FM to normal mode.*/
+		for (reg = BT_PCM_BCLK_MODE; reg <= BT_PCM_SYNC_MODE; reg++) {
+			rc = marimba_write(&config, reg, &set, 1);
+			if (rc < 0) {
+				pr_err("pcm pinctl failed = %d", rc);
+				goto err_all;
+			}
+		}
+		for (reg = FM_I2S_SD_MODE; reg <= FM_I2S_SCK_MODE; reg++) {
+			rc = marimba_write(&config, reg, &unset, 1);
+			if (rc < 0) {
+				pr_err("i2s normal failed = %d", rc);
+				goto err_all;
+			}
+		}
+	} else {
+		/* as we need to switch path to AUXPCM we need to move
+		 FM I2S lines to PIN CONTROL mode then move
+		 BT AUX_PCM to normal mode.*/
+		for (reg = FM_I2S_SD_MODE; reg <= FM_I2S_SCK_MODE; reg++) {
+			rc = marimba_write(&config, reg, &set, 1);
+			if (rc < 0) {
+				pr_err("i2s pinctl failed = %d", rc);
+				goto err_all;
+			}
+		}
+		for (reg = BT_PCM_BCLK_MODE; reg <= BT_PCM_SYNC_MODE; reg++) {
+			rc = marimba_write(&config, reg, &unset, 1);
+			if (rc < 0) {
+				pr_err("pcm normal failed = %d", rc);
+				goto err_all;
+			}
+		}
+	}
+
+	return 0;
+
+err_all:
+	return rc;
+}
 static void config_pcm_i2s_mode(int mode)
 {
 	void __iomem *cfg_ptr;
@@ -174,6 +234,12 @@
 		if (machine_is_msm7627a_qrd1())
 			config_pcm_i2s_mode(0);
 		pr_err("%s mode = FM_I2S_ON", __func__);
+
+		rc = switch_pcm_i2s_reg_mode(0);
+		if (rc) {
+			pr_err("switch mode failed");
+			return rc;
+		}
 		for (pin = 0; pin < ARRAY_SIZE(fm_i2s_config_power_on);
 			pin++) {
 				rc = gpio_tlmm_config(
@@ -185,6 +251,11 @@
 			}
 	} else if (mode == FM_I2S_OFF) {
 		pr_err("%s mode = FM_I2S_OFF", __func__);
+		rc = switch_pcm_i2s_reg_mode(1);
+		if (rc) {
+			pr_err("switch mode failed");
+			return rc;
+		}
 		for (pin = 0; pin < ARRAY_SIZE(fm_i2s_config_power_off);
 			pin++) {
 				rc = gpio_tlmm_config(
@@ -205,6 +276,11 @@
 		if (machine_is_msm7627a_qrd1())
 			config_pcm_i2s_mode(1);
 		pr_err("%s mode =BT_PCM_ON", __func__);
+		rc = switch_pcm_i2s_reg_mode(1);
+		if (rc) {
+			pr_err("switch mode failed");
+			return rc;
+		}
 		for (pin = 0; pin < ARRAY_SIZE(bt_config_pcm_on);
 			pin++) {
 				rc = gpio_tlmm_config(bt_config_pcm_on[pin],
@@ -214,6 +290,11 @@
 			}
 	} else if (mode == BT_PCM_OFF) {
 		pr_err("%s mode =BT_PCM_OFF", __func__);
+		rc = switch_pcm_i2s_reg_mode(0);
+		if (rc) {
+			pr_err("switch mode failed");
+			return rc;
+		}
 		for (pin = 0; pin < ARRAY_SIZE(bt_config_pcm_off);
 			pin++) {
 				rc = gpio_tlmm_config(bt_config_pcm_off[pin],