dev: qpnp_haptic: Add ERM Vibrator support to LK for PMI632

Add control flow to check for ERM based or LRA based vibrator
depending on the PMIC type

Change-Id: Icaf27523af19dd1b19dfd92b68e862ea5a130336
Signed-off-by: Umang Agrawal <uagrawal@codeaurora.org>
diff --git a/dev/pmic/pm8x41/include/pm_vib.h b/dev/pmic/pm8x41/include/pm_vib.h
index 9b10327..d072d69 100644
--- a/dev/pmic/pm8x41/include/pm_vib.h
+++ b/dev/pmic/pm8x41/include/pm_vib.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2014, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2014, 2017-2018, The Linux Foundation. All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions are
@@ -35,4 +35,10 @@
 
 void pm_vib_turn_on(void);
 void pm_vib_turn_off(void);
+
+void pm_vib_ldo_turn_on(void);
+void pm_vib_ldo_turn_off(void);
+
+void pm_haptic_vib_turn_on(void);
+void pm_haptic_vib_turn_off(void);
 #endif/* __DEV_PMIC_VIB_VIBRATOR_H */
diff --git a/dev/qpnp_haptic/qpnp_haptic.c b/dev/qpnp_haptic/qpnp_haptic.c
index a4e3820..ec91d2a 100644
--- a/dev/qpnp_haptic/qpnp_haptic.c
+++ b/dev/qpnp_haptic/qpnp_haptic.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2015, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2015, 2017-2018, The Linux Foundation. All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions are
@@ -83,7 +83,7 @@
 #define QPNP_HAP_LRA_AUTO_MASK 0x70
 
 /* Turn on vibrator */
-void pm_vib_turn_on(void)
+void pm_haptic_vib_turn_on(void)
 {
 	struct qpnp_hap vib_config = {0};
 
@@ -150,7 +150,7 @@
 }
 
 /* Turn off vibrator */
-void pm_vib_turn_off(void)
+void pm_haptic_vib_turn_off(void)
 {
 	if(!target_is_pmi_enabled())
 		return;
diff --git a/dev/qpnp_haptic/qpnp_vib.c b/dev/qpnp_haptic/qpnp_vib.c
new file mode 100644
index 0000000..fecb794
--- /dev/null
+++ b/dev/qpnp_haptic/qpnp_vib.c
@@ -0,0 +1,46 @@
+/* Copyright (c) 2018, The Linux Foundation. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *   * Redistributions of source code must retain the above copyright
+ *     notice, this list of conditions and the following disclaimer.
+ *   * Redistributions in binary form must reproduce the above
+ *     copyright notice, this list of conditions and the following
+ *     disclaimer in the documentation and/or other materials provided
+ *     with the distribution.
+ *   * Neither the name of The Linux Foundation nor the names of its
+ *     contributors may be used to endorse or promote products derived
+ *     from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+ * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <pm_vib.h>
+#include <board.h>
+
+void pm_vib_turn_on()
+{
+	if ((board_pmic_target(1) & 0xffff) == PMIC_IS_PMI632)
+		pm_vib_ldo_turn_on();
+	else
+		pm_haptic_vib_turn_on();
+}
+
+void pm_vib_turn_off()
+{
+	if ((board_pmic_target(1) & 0xffff) == PMIC_IS_PMI632)
+		pm_vib_ldo_turn_off();
+	else
+		pm_haptic_vib_turn_off();
+}
diff --git a/dev/qpnp_haptic/qpnp_vib_ldo.c b/dev/qpnp_haptic/qpnp_vib_ldo.c
new file mode 100644
index 0000000..7b327cf
--- /dev/null
+++ b/dev/qpnp_haptic/qpnp_vib_ldo.c
@@ -0,0 +1,143 @@
+/* Copyright (c) 2018, The Linux Foundation. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *   * Redistributions of source code must retain the above copyright
+ *     notice, this list of conditions and the following disclaimer.
+ *   * Redistributions in binary form must reproduce the above
+ *     copyright notice, this list of conditions and the following
+ *     disclaimer in the documentation and/or other materials provided
+ *     with the distribution.
+ *   * Neither the name of The Linux Foundation nor the names of its
+ *     contributors may be used to endorse or promote products derived
+ *     from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+ * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <kernel/timer.h>
+#include <qtimer.h>
+#include <bits.h>
+#include <debug.h>
+#include <smem.h>
+#include <spmi.h>
+#include <platform/iomap.h>
+#include <board.h>
+#include <target.h>
+#include <pm_vib.h>
+
+#define VIB_LDO_BASE			(PMI_SECOND_SLAVE_ADDR_BASE + 0x5700)
+#define QPNP_VIB_LDO_STATUS1_REG	(VIB_LDO_BASE + 0x08)
+#define QPNP_VIB_LDO_VSET_LB_REG	(VIB_LDO_BASE + 0x40)
+#define QPNP_VIB_LDO_VSET_UB_REG	(VIB_LDO_BASE + 0x41)
+#define QPNP_VIB_LDO_EN_CTL_REG		(VIB_LDO_BASE + 0x46)
+
+#define QPNP_VIB_LDO_VSET_LB_MASK	0xFF
+#define QPNP_VIB_LDO_VSET_UB_MASK	0xFF
+#define QPNP_VIB_LDO_EN_CTL_MASK	0x80
+#define QPNP_VIB_LDO_EN			0x80
+#define QPNP_VIB_LDO_DIS		0x00
+
+#define VREG_READY BIT(7)
+
+#define MAX_WAIT_FOR_VREG_READY_US	1000
+#define VREG_READY_STEP_DELAY_US	100
+#define VIB_LDO_OVERDRIVE_VOLTAGE_MV	3000
+#define VIB_LDO_NOMINAL_VOLTAGE_MV	1500
+#define OVERDRIVE_TIME_US		30000
+
+/* Turn on vibrator */
+void pm_vib_ldo_turn_on(void)
+{
+	uint8_t status;
+	uint8_t vreg_timer_count = 0;
+
+	if (!target_is_pmi_enabled())
+		return;
+
+	/* Set overdrive voltage*/
+	pmic_spmi_reg_mask_write(QPNP_VIB_LDO_VSET_LB_REG,
+				QPNP_VIB_LDO_VSET_LB_MASK,
+				(VIB_LDO_OVERDRIVE_VOLTAGE_MV & 0xff));
+	pmic_spmi_reg_mask_write(QPNP_VIB_LDO_VSET_UB_REG,
+				QPNP_VIB_LDO_VSET_UB_MASK,
+				((VIB_LDO_OVERDRIVE_VOLTAGE_MV >> 8) & 0xff));
+
+	/* Set Register VIB_LDO_EN_CTL to enable vibrator */
+	pmic_spmi_reg_mask_write(QPNP_VIB_LDO_EN_CTL_REG,
+				QPNP_VIB_LDO_EN_CTL_MASK,
+				QPNP_VIB_LDO_EN);
+
+	/* Wait for VREG_READY*/
+	while (1) {
+		status = pmic_spmi_reg_read(QPNP_VIB_LDO_STATUS1_REG);
+		if ( status & VREG_READY ) {
+			break;
+		}
+		else if ( vreg_timer_count < (MAX_WAIT_FOR_VREG_READY_US /
+						VREG_READY_STEP_DELAY_US) ) {
+			vreg_timer_count++;
+			udelay(VREG_READY_STEP_DELAY_US);
+		}
+		else {
+			dprintf(CRITICAL, "LDO failed to start in 1 msec, "
+				"turning off vibrator\n");
+			pm_vib_ldo_turn_off();
+			return;
+		}
+	}
+
+	udelay(OVERDRIVE_TIME_US);
+
+	/* Set normal voltage */
+	pmic_spmi_reg_mask_write(QPNP_VIB_LDO_VSET_LB_REG,
+				QPNP_VIB_LDO_VSET_LB_MASK,
+				(VIB_LDO_NOMINAL_VOLTAGE_MV & 0xff));
+	pmic_spmi_reg_mask_write(QPNP_VIB_LDO_VSET_UB_REG,
+				QPNP_VIB_LDO_VSET_UB_MASK,
+				((VIB_LDO_NOMINAL_VOLTAGE_MV >> 8) & 0xff));
+
+	vreg_timer_count = 0;
+	/* Wait for VREG_READY*/
+	while (1) {
+		status = pmic_spmi_reg_read(QPNP_VIB_LDO_STATUS1_REG);
+		if ( status & VREG_READY ) {
+			break;
+		}
+		else if ( vreg_timer_count < (MAX_WAIT_FOR_VREG_READY_US /
+						VREG_READY_STEP_DELAY_US) ) {
+			vreg_timer_count++;
+			udelay(VREG_READY_STEP_DELAY_US);
+		}
+		else {
+			dprintf(CRITICAL, "LDO failed to start in 1 msec, "
+				"turning off vibrator\n");
+			pm_vib_ldo_turn_off();
+			return;
+		}
+	}
+
+}
+
+/* Turn off vibrator */
+void pm_vib_ldo_turn_off(void)
+{
+	if (!target_is_pmi_enabled())
+		return;
+
+	/* Clear Register VIB_LDO_EN_CTL to disable vibrator */
+	pmic_spmi_reg_mask_write(QPNP_VIB_LDO_EN_CTL_REG,
+				QPNP_VIB_LDO_EN_CTL_MASK,
+				QPNP_VIB_LDO_DIS);
+}
diff --git a/dev/qpnp_haptic/rules.mk b/dev/qpnp_haptic/rules.mk
index 8922bb7..6beb706 100644
--- a/dev/qpnp_haptic/rules.mk
+++ b/dev/qpnp_haptic/rules.mk
@@ -4,5 +4,7 @@
 
 ifeq ($(ENABLE_HAP_VIB_SUPPORT),true)
 OBJS += \
-	$(LOCAL_DIR)/qpnp_haptic.o
+	$(LOCAL_DIR)/qpnp_vib.o \
+	$(LOCAL_DIR)/qpnp_haptic.o \
+	$(LOCAL_DIR)/qpnp_vib_ldo.o
 endif