msm: camera: Add common sensor functionality

Add utilities and common functionalities for
camera sensor and its associated modules.

CRs-Fixed: 2015567
Change-Id: If2547f6272a1c4c3b87ad8760f82a8778defca40
Signed-off-by: Viswanadha Raju Thotakura <viswanad@codeaurora.org>
diff --git a/drivers/media/platform/msm/camera/Makefile b/drivers/media/platform/msm/camera/Makefile
index c05c069..ada427c 100644
--- a/drivers/media/platform/msm/camera/Makefile
+++ b/drivers/media/platform/msm/camera/Makefile
@@ -6,3 +6,4 @@
 obj-$(CONFIG_SPECTRA_CAMERA) += cam_cpas/
 obj-$(CONFIG_SPECTRA_CAMERA) += cam_cdm/
 obj-$(CONFIG_SPECTRA_CAMERA) += cam_isp/
+obj-$(CONFIG_SPECTRA_CAMERA) += cam_sensor_module/
diff --git a/drivers/media/platform/msm/camera/cam_sensor_module/Makefile b/drivers/media/platform/msm/camera/cam_sensor_module/Makefile
new file mode 100644
index 0000000..d14b727
--- /dev/null
+++ b/drivers/media/platform/msm/camera/cam_sensor_module/Makefile
@@ -0,0 +1 @@
+obj-$(CONFIG_SPECTRA_CAMERA) += cam_sensor_utils/
diff --git a/drivers/media/platform/msm/camera/cam_sensor_module/cam_sensor_utils/Makefile b/drivers/media/platform/msm/camera/cam_sensor_module/cam_sensor_utils/Makefile
new file mode 100644
index 0000000..766828e
--- /dev/null
+++ b/drivers/media/platform/msm/camera/cam_sensor_module/cam_sensor_utils/Makefile
@@ -0,0 +1,6 @@
+ccflags-y += -Idrivers/media/platform/msm/camera/cam_req_mgr
+ccflags-y += -Idrivers/media/platform/msm/camera/cam_utils
+ccflags-y += -Idrivers/media/platform/msm/camera/cam_sensor_module/cam_sensor_io
+ccflags-y += -Idrivers/media/platform/msm/camera/cam_sensor_module/cam_cci
+
+obj-$(CONFIG_SPECTRA_CAMERA) +=  cam_sensor_util.o cam_sensor_soc_api.o
\ No newline at end of file
diff --git a/drivers/media/platform/msm/camera/cam_sensor_module/cam_sensor_utils/cam_sensor_cmn_header.h b/drivers/media/platform/msm/camera/cam_sensor_module/cam_sensor_utils/cam_sensor_cmn_header.h
new file mode 100644
index 0000000..e5e4872
--- /dev/null
+++ b/drivers/media/platform/msm/camera/cam_sensor_module/cam_sensor_utils/cam_sensor_cmn_header.h
@@ -0,0 +1,375 @@
+/* Copyright (c) 2017, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#ifndef _CAM_SENSOR_CMN_HEADER_
+#define _CAM_SENSOR_CMN_HEADER_
+
+#include <linux/i2c.h>
+#include <linux/types.h>
+#include <linux/kernel.h>
+#include <linux/slab.h>
+#include <linux/timer.h>
+#include <linux/delay.h>
+#include <linux/list.h>
+#include <media/cam_sensor.h>
+#include <media/cam_req_mgr.h>
+
+#define MAX_REGULATOR 5
+#define MAX_POWER_CONFIG 12
+
+#define MAX_PER_FRAME_ARRAY 8
+
+#define CAM_SENSOR_NAME    "cam-sensor"
+#define CAM_ACTUATOR_NAME  "cam-actuator"
+#define CAM_CSIPHY_NAME    "cam-csiphy"
+
+#define MAX_SYSTEM_PIPELINE_DELAY 2
+
+#define CAM_PKT_NOP_OPCODE 127
+
+enum camera_sensor_cmd_type {
+	CAMERA_SENSOR_CMD_TYPE_INVALID,
+	CAMERA_SENSOR_CMD_TYPE_PROBE,
+	CAMERA_SENSOR_CMD_TYPE_PWR_UP,
+	CAMERA_SENSOR_CMD_TYPE_PWR_DOWN,
+	CAMERA_SENSOR_CMD_TYPE_I2C_INFO,
+	CAMERA_SENSOR_CMD_TYPE_I2C_RNDM_WR,
+	CAMERA_SENSOR_CMD_TYPE_I2C_RNDM_RD,
+	CAMERA_SENSOR_CMD_TYPE_I2C_CONT_WR,
+	CAMERA_SENSOR_CMD_TYPE_I2C_CONT_RD,
+	CAMERA_SENSOR_CMD_TYPE_WAIT,
+	CAMERA_SENSOR_CMD_TYPE_MAX,
+};
+
+enum camera_sensor_i2c_op_code {
+	CAMERA_SENSOR_I2C_OP_INVALID,
+	CAMERA_SENSOR_I2C_OP_RNDM_WR,
+	CAMERA_SENSOR_I2C_OP_RNDM_WR_VERF,
+	CAMERA_SENSOR_I2C_OP_CONT_WR_BRST,
+	CAMERA_SENSOR_I2C_OP_CONT_WR_BRST_VERF,
+	CAMERA_SENSOR_I2C_OP_CONT_WR_SEQN,
+	CAMERA_SENSOR_I2C_OP_CONT_WR_SEQN_VERF,
+	CAMERA_SENSOR_I2C_OP_MAX,
+};
+
+enum camera_sensor_wait_op_code {
+	CAMERA_SENSOR_WAIT_OP_INVALID,
+	CAMERA_SENSOR_WAIT_OP_COND,
+	CAMERA_SENSOR_WAIT_OP_HW_UCND,
+	CAMERA_SENSOR_WAIT_OP_SW_UCND,
+	CAMERA_SENSOR_WAIT_OP_MAX,
+};
+
+enum camera_sensor_i2c_type {
+	CAMERA_SENSOR_I2C_TYPE_INVALID,
+	CAMERA_SENSOR_I2C_TYPE_BYTE,
+	CAMERA_SENSOR_I2C_TYPE_WORD,
+	CAMERA_SENSOR_I2C_TYPE_3B,
+	CAMERA_SENSOR_I2C_TYPE_DWORD,
+	CAMERA_SENSOR_I2C_TYPE_MAX,
+};
+
+enum i2c_freq_mode {
+	I2C_STANDARD_MODE,
+	I2C_FAST_MODE,
+	I2C_CUSTOM_MODE,
+	I2C_FAST_PLUS_MODE,
+	I2C_MAX_MODES,
+};
+
+enum position_roll {
+	ROLL_0       = 0,
+	ROLL_90      = 90,
+	ROLL_180     = 180,
+	ROLL_270     = 270,
+	ROLL_INVALID = 360,
+};
+
+enum position_yaw {
+	FRONT_CAMERA_YAW = 0,
+	REAR_CAMERA_YAW  = 180,
+	INVALID_YAW      = 360,
+};
+
+enum position_pitch {
+	LEVEL_PITCH    = 0,
+	INVALID_PITCH  = 360,
+};
+
+enum sensor_sub_module {
+	SUB_MODULE_SENSOR,
+	SUB_MODULE_ACTUATOR,
+	SUB_MODULE_EEPROM,
+	SUB_MODULE_LED_FLASH,
+	SUB_MODULE_CSID,
+	SUB_MODULE_CSIPHY,
+	SUB_MODULE_OIS,
+	SUB_MODULE_EXT,
+	SUB_MODULE_MAX,
+};
+
+enum msm_camera_power_seq_type {
+	SENSOR_MCLK,
+	SENSOR_VANA,
+	SENSOR_VDIG,
+	SENSOR_VIO,
+	SENSOR_VAF,
+	SENSOR_VAF_PWDM,
+	SENSOR_CUSTOM_REG1,
+	SENSOR_CUSTOM_REG2,
+	SENSOR_RESET,
+	SENSOR_STANDBY,
+	SENSOR_CUSTOM_GPIO1,
+	SENSOR_CUSTOM_GPIO2,
+	SENSOR_SEQ_TYPE_MAX,
+};
+
+enum cam_sensor_packet_opcodes {
+	CAM_SENSOR_PACKET_OPCODE_SENSOR_STREAMON,
+	CAM_SENSOR_PACKET_OPCODE_SENSOR_UPDATE,
+	CAM_SENSOR_PACKET_OPCODE_SENSOR_INITIAL_CONFIG,
+	CAM_SENSOR_PACKET_OPCODE_SENSOR_PROBE
+};
+
+enum cam_actuator_packet_opcodes {
+	CAM_ACTUATOR_PACKET_OPCODE_INIT,
+	CAM_ACTUATOR_PACKET_AUTO_MOVE_LENS,
+	CAM_ACTUATOR_PACKET_MANUAL_MOVE_LENS
+};
+
+enum msm_bus_perf_setting {
+	S_INIT,
+	S_PREVIEW,
+	S_VIDEO,
+	S_CAPTURE,
+	S_ZSL,
+	S_STEREO_VIDEO,
+	S_STEREO_CAPTURE,
+	S_DEFAULT,
+	S_LIVESHOT,
+	S_DUAL,
+	S_EXIT
+};
+
+enum msm_camera_device_type_t {
+	MSM_CAMERA_I2C_DEVICE,
+	MSM_CAMERA_PLATFORM_DEVICE,
+	MSM_CAMERA_SPI_DEVICE,
+};
+
+enum cci_i2c_master_t {
+	MASTER_0,
+	MASTER_1,
+	MASTER_MAX,
+};
+
+enum camera_vreg_type {
+	VREG_TYPE_DEFAULT,
+	VREG_TYPE_CUSTOM,
+};
+
+enum cam_sensor_i2c_cmd_type {
+	CAM_SENSOR_I2C_WRITE_RANDOM,
+	CAM_SENSOR_I2C_READ,
+	CAM_SENSOR_I2C_POLL
+};
+
+struct common_header {
+	uint16_t    first_word;
+	uint8_t     third_byte;
+	uint8_t     cmd_type;
+};
+
+struct camera_vreg_t {
+	const char *reg_name;
+	int min_voltage;
+	int max_voltage;
+	int op_mode;
+	uint32_t delay;
+	const char *custom_vreg_name;
+	enum camera_vreg_type type;
+};
+
+struct cam_sensor_module_power_setting {
+	enum msm_camera_power_seq_type seq_type;
+	unsigned short seq_val;
+	uint32_t config_val_low;
+	uint32_t config_val_high;
+	unsigned short delay;
+};
+
+struct msm_camera_gpio_num_info {
+	uint16_t gpio_num[SENSOR_SEQ_TYPE_MAX];
+	uint8_t valid[SENSOR_SEQ_TYPE_MAX];
+};
+
+struct msm_cam_clk_info {
+	const char *clk_name;
+	long clk_rate;
+	uint32_t delay;
+};
+
+struct msm_pinctrl_info {
+	struct pinctrl *pinctrl;
+	struct pinctrl_state *gpio_state_active;
+	struct pinctrl_state *gpio_state_suspend;
+	bool use_pinctrl;
+};
+
+struct cam_sensor_i2c_reg_array {
+	uint32_t reg_addr;
+	uint32_t reg_data;
+	uint32_t delay;
+	uint32_t data_mask;
+};
+
+struct cam_sensor_i2c_reg_setting {
+	struct cam_sensor_i2c_reg_array *reg_setting;
+	unsigned short size;
+	enum camera_sensor_i2c_type addr_type;
+	enum camera_sensor_i2c_type data_type;
+	unsigned short delay;
+};
+
+struct i2c_settings_list {
+	struct cam_sensor_i2c_reg_setting i2c_settings;
+	enum cam_sensor_i2c_cmd_type op_code;
+	struct list_head list;
+};
+
+struct i2c_settings_array {
+	struct list_head list_head;
+	int32_t is_settings_valid;
+	int64_t request_id;
+};
+
+struct i2c_data_settings {
+	struct i2c_settings_array init_settings;
+	struct i2c_settings_array *per_frame;
+};
+
+struct cam_sensor_power_ctrl_t {
+	struct device *dev;
+	struct cam_sensor_power_setting *power_setting;
+	uint16_t power_setting_size;
+	struct cam_sensor_power_setting *power_down_setting;
+	uint16_t power_down_setting_size;
+	struct msm_camera_gpio_conf *gpio_conf;
+	struct camera_vreg_t *cam_vreg;
+	int num_vreg;
+	struct clk **clk_ptr;
+	struct msm_cam_clk_info *clk_info;
+	struct msm_pinctrl_info pinctrl_info;
+	uint8_t cam_pinctrl_status;
+	size_t clk_info_size;
+};
+
+struct cam_camera_slave_info {
+	uint16_t sensor_slave_addr;
+	uint16_t sensor_id_reg_addr;
+	uint16_t sensor_id;
+	uint16_t sensor_id_mask;
+};
+
+struct msm_sensor_init_params {
+	int modes_supported;
+	unsigned int sensor_mount_angle;
+};
+
+enum msm_sensor_camera_id_t {
+	CAMERA_0,
+	CAMERA_1,
+	CAMERA_2,
+	CAMERA_3,
+	MAX_CAMERAS,
+};
+
+struct msm_sensor_id_info_t {
+	unsigned short sensor_id_reg_addr;
+	unsigned short sensor_id;
+	unsigned short sensor_id_mask;
+};
+
+enum msm_sensor_output_format_t {
+	MSM_SENSOR_BAYER,
+	MSM_SENSOR_YCBCR,
+	MSM_SENSOR_META,
+};
+
+struct cam_sensor_power_setting {
+	enum msm_camera_power_seq_type seq_type;
+	unsigned short seq_val;
+	long config_val;
+	unsigned short delay;
+	void *data[10];
+};
+
+struct cam_sensor_power_setting_array {
+	struct cam_sensor_power_setting  power_setting_a[MAX_POWER_CONFIG];
+	struct cam_sensor_power_setting *power_setting;
+	unsigned short size;
+	struct cam_sensor_power_setting  power_down_setting_a[MAX_POWER_CONFIG];
+	struct cam_sensor_power_setting *power_down_setting;
+	unsigned short size_down;
+};
+
+struct msm_camera_sensor_slave_info {
+	enum msm_sensor_camera_id_t camera_id;
+	unsigned short slave_addr;
+	enum i2c_freq_mode i2c_freq_mode;
+	enum camera_sensor_i2c_type addr_type;
+	struct msm_sensor_id_info_t sensor_id_info;
+	struct cam_sensor_power_setting_array power_setting_array;
+	unsigned char  is_init_params_valid;
+	enum msm_sensor_output_format_t output_format;
+};
+
+struct cam_sensor_board_info {
+	struct cam_camera_slave_info slave_info;
+	int32_t sensor_mount_angle;
+	int32_t secure_mode;
+	int modes_supported;
+	int32_t pos_roll;
+	int32_t pos_yaw;
+	int32_t pos_pitch;
+	int32_t  subdev_id[SUB_MODULE_MAX];
+	int32_t  subdev_intf[SUB_MODULE_MAX];
+	const char *misc_regulator;
+	struct cam_sensor_power_ctrl_t power_info;
+};
+
+enum msm_camera_vreg_name_t {
+	CAM_VDIG,
+	CAM_VIO,
+	CAM_VANA,
+	CAM_VAF,
+	CAM_V_CUSTOM1,
+	CAM_V_CUSTOM2,
+	CAM_VREG_MAX,
+};
+
+struct msm_camera_gpio_conf {
+	void *cam_gpiomux_conf_tbl;
+	uint8_t cam_gpiomux_conf_tbl_size;
+	struct gpio *cam_gpio_common_tbl;
+	uint8_t cam_gpio_common_tbl_size;
+	struct gpio *cam_gpio_req_tbl;
+	uint8_t cam_gpio_req_tbl_size;
+	uint32_t gpio_no_mux;
+	uint32_t *camera_off_table;
+	uint8_t camera_off_table_size;
+	uint32_t *camera_on_table;
+	uint8_t camera_on_table_size;
+	struct msm_camera_gpio_num_info *gpio_num_info;
+};
+
+#endif /* _CAM_SENSOR_CMN_HEADER_ */
diff --git a/drivers/media/platform/msm/camera/cam_sensor_module/cam_sensor_utils/cam_sensor_soc_api.c b/drivers/media/platform/msm/camera/cam_sensor_module/cam_sensor_utils/cam_sensor_soc_api.c
new file mode 100644
index 0000000..2eed9ce
--- /dev/null
+++ b/drivers/media/platform/msm/camera/cam_sensor_module/cam_sensor_utils/cam_sensor_soc_api.c
@@ -0,0 +1,1331 @@
+/* Copyright (c) 2015-2017, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/delay.h>
+#include <linux/module.h>
+#include <linux/of_platform.h>
+#include <linux/msm-bus.h>
+#include "cam_sensor_soc_api.h"
+
+#define NO_SET_RATE -1
+#define INIT_RATE -2
+
+#ifdef CONFIG_CAM_SOC_API_DBG
+#define CDBG(fmt, args...) pr_err(fmt, ##args)
+#else
+#define CDBG(fmt, args...) pr_debug(fmt, ##args)
+#endif
+
+int msm_cam_clk_sel_src(struct device *dev, struct msm_cam_clk_info *clk_info,
+		struct msm_cam_clk_info *clk_src_info, int num_clk)
+{
+	int i;
+	int rc = 0;
+	struct clk *mux_clk = NULL;
+	struct clk *src_clk = NULL;
+
+	for (i = 0; i < num_clk; i++) {
+		if (clk_src_info[i].clk_name) {
+			mux_clk = clk_get(dev, clk_info[i].clk_name);
+			if (IS_ERR(mux_clk)) {
+				pr_err("%s get failed\n",
+					 clk_info[i].clk_name);
+				continue;
+			}
+			src_clk = clk_get(dev, clk_src_info[i].clk_name);
+			if (IS_ERR(src_clk)) {
+				pr_err("%s get failed\n",
+					clk_src_info[i].clk_name);
+				continue;
+			}
+			clk_set_parent(mux_clk, src_clk);
+		}
+	}
+	return rc;
+}
+
+int msm_cam_clk_enable(struct device *dev, struct msm_cam_clk_info *clk_info,
+		struct clk **clk_ptr, int num_clk, int enable)
+{
+	int i;
+	int rc = 0;
+	long clk_rate;
+
+	if (enable) {
+		for (i = 0; i < num_clk; i++) {
+			CDBG("%s enable %s\n", __func__, clk_info[i].clk_name);
+			clk_ptr[i] = clk_get(dev, clk_info[i].clk_name);
+			if (IS_ERR(clk_ptr[i])) {
+				pr_err("%s get failed\n", clk_info[i].clk_name);
+				rc = PTR_ERR(clk_ptr[i]);
+				goto cam_clk_get_err;
+			}
+			if (clk_info[i].clk_rate > 0) {
+				clk_rate = clk_round_rate(clk_ptr[i],
+					clk_info[i].clk_rate);
+				if (clk_rate < 0) {
+					pr_err("%s round failed\n",
+						   clk_info[i].clk_name);
+					goto cam_clk_set_err;
+				}
+				rc = clk_set_rate(clk_ptr[i],
+					clk_rate);
+				if (rc < 0) {
+					pr_err("%s set failed\n",
+						clk_info[i].clk_name);
+					goto cam_clk_set_err;
+				}
+
+			} else if (clk_info[i].clk_rate == INIT_RATE) {
+				clk_rate = clk_get_rate(clk_ptr[i]);
+				if (clk_rate == 0) {
+					clk_rate =
+						  clk_round_rate(clk_ptr[i], 0);
+					if (clk_rate < 0) {
+						pr_err("%s round rate failed\n",
+							  clk_info[i].clk_name);
+						goto cam_clk_set_err;
+					}
+					rc = clk_set_rate(clk_ptr[i],
+								clk_rate);
+					if (rc < 0) {
+						pr_err("%s set rate failed\n",
+							  clk_info[i].clk_name);
+						goto cam_clk_set_err;
+					}
+				}
+			}
+			rc = clk_prepare(clk_ptr[i]);
+			if (rc < 0) {
+				pr_err("%s prepare failed\n",
+					   clk_info[i].clk_name);
+				goto cam_clk_prepare_err;
+			}
+
+			rc = clk_enable(clk_ptr[i]);
+			if (rc < 0) {
+				pr_err("%s enable failed\n",
+					   clk_info[i].clk_name);
+				goto cam_clk_enable_err;
+			}
+			if (clk_info[i].delay > 20)
+				msleep(clk_info[i].delay);
+			else if (clk_info[i].delay)
+				usleep_range(clk_info[i].delay * 1000,
+					(clk_info[i].delay * 1000) + 1000);
+		}
+	} else {
+		for (i = num_clk - 1; i >= 0; i--) {
+			if (clk_ptr[i] != NULL) {
+				CDBG("%s disable %s\n", __func__,
+					clk_info[i].clk_name);
+				clk_disable(clk_ptr[i]);
+				clk_unprepare(clk_ptr[i]);
+				clk_put(clk_ptr[i]);
+			}
+		}
+	}
+
+	return rc;
+
+cam_clk_enable_err:
+	clk_unprepare(clk_ptr[i]);
+cam_clk_prepare_err:
+cam_clk_set_err:
+	clk_put(clk_ptr[i]);
+cam_clk_get_err:
+	for (i--; i >= 0; i--) {
+		if (clk_ptr[i] != NULL) {
+			clk_disable(clk_ptr[i]);
+			clk_unprepare(clk_ptr[i]);
+			clk_put(clk_ptr[i]);
+		}
+	}
+
+	return rc;
+}
+
+int msm_camera_config_vreg(struct device *dev, struct camera_vreg_t *cam_vreg,
+		int num_vreg, enum msm_camera_vreg_name_t *vreg_seq,
+		int num_vreg_seq, struct regulator **reg_ptr, int config)
+{
+	int i = 0, j = 0;
+	int rc = 0;
+	struct camera_vreg_t *curr_vreg;
+
+	if (num_vreg_seq > num_vreg) {
+		pr_err("%s:%d vreg sequence invalid\n", __func__, __LINE__);
+		return -EINVAL;
+	}
+	if (!num_vreg_seq)
+		num_vreg_seq = num_vreg;
+
+	if (config) {
+		for (i = 0; i < num_vreg_seq; i++) {
+			if (vreg_seq) {
+				j = vreg_seq[i];
+				if (j >= num_vreg)
+					continue;
+			} else {
+				j = i;
+			}
+			curr_vreg = &cam_vreg[j];
+			reg_ptr[j] = regulator_get(dev,
+				curr_vreg->reg_name);
+			if (IS_ERR(reg_ptr[j])) {
+				pr_err("%s: %s get failed\n",
+					 __func__,
+					 curr_vreg->reg_name);
+				reg_ptr[j] = NULL;
+				goto vreg_get_fail;
+			}
+			if (regulator_count_voltages(reg_ptr[j]) > 0) {
+				rc = regulator_set_voltage(
+					reg_ptr[j],
+					curr_vreg->min_voltage,
+					curr_vreg->max_voltage);
+				if (rc < 0) {
+					pr_err("%s: %s set voltage failed\n",
+						__func__,
+						curr_vreg->reg_name);
+					goto vreg_set_voltage_fail;
+				}
+				if (curr_vreg->op_mode >= 0) {
+					rc = regulator_set_load(
+						reg_ptr[j],
+						curr_vreg->op_mode);
+					if (rc < 0) {
+						pr_err(
+						"%s:%s set optimum mode fail\n",
+						__func__,
+						curr_vreg->reg_name);
+						goto vreg_set_opt_mode_fail;
+					}
+				}
+			}
+		}
+	} else {
+		for (i = num_vreg_seq-1; i >= 0; i--) {
+			if (vreg_seq) {
+				j = vreg_seq[i];
+				if (j >= num_vreg)
+					continue;
+			} else {
+				j = i;
+			}
+			curr_vreg = &cam_vreg[j];
+			if (reg_ptr[j]) {
+				if (regulator_count_voltages(reg_ptr[j]) > 0) {
+					if (curr_vreg->op_mode >= 0) {
+						regulator_set_load(
+							reg_ptr[j], 0);
+					}
+					regulator_set_voltage(
+						reg_ptr[j], 0, curr_vreg->
+						max_voltage);
+				}
+				regulator_put(reg_ptr[j]);
+				reg_ptr[j] = NULL;
+			}
+		}
+	}
+
+	return 0;
+
+vreg_unconfig:
+	if (regulator_count_voltages(reg_ptr[j]) > 0)
+		regulator_set_load(reg_ptr[j], 0);
+
+vreg_set_opt_mode_fail:
+	if (regulator_count_voltages(reg_ptr[j]) > 0)
+		regulator_set_voltage(reg_ptr[j], 0,
+			curr_vreg->max_voltage);
+
+vreg_set_voltage_fail:
+	regulator_put(reg_ptr[j]);
+	reg_ptr[j] = NULL;
+
+vreg_get_fail:
+	for (i--; i >= 0; i--) {
+		if (vreg_seq) {
+			j = vreg_seq[i];
+			if (j >= num_vreg)
+				continue;
+		} else {
+			j = i;
+		}
+		curr_vreg = &cam_vreg[j];
+		goto vreg_unconfig;
+	}
+
+	return -ENODEV;
+}
+
+int msm_camera_enable_vreg(struct device *dev, struct camera_vreg_t *cam_vreg,
+		int num_vreg, enum msm_camera_vreg_name_t *vreg_seq,
+		int num_vreg_seq, struct regulator **reg_ptr, int enable)
+{
+	int i = 0, j = 0, rc = 0;
+
+	if (num_vreg_seq > num_vreg) {
+		pr_err("%s:%d vreg sequence invalid\n", __func__, __LINE__);
+		return -EINVAL;
+	}
+	if (!num_vreg_seq)
+		num_vreg_seq = num_vreg;
+
+	if (enable) {
+		for (i = 0; i < num_vreg_seq; i++) {
+			if (vreg_seq) {
+				j = vreg_seq[i];
+				if (j >= num_vreg)
+					continue;
+			} else
+				j = i;
+			if (IS_ERR(reg_ptr[j])) {
+				pr_err("%s: %s null regulator\n",
+					__func__, cam_vreg[j].reg_name);
+				goto disable_vreg;
+			}
+			rc = regulator_enable(reg_ptr[j]);
+			if (rc < 0) {
+				pr_err("%s: %s enable failed\n",
+					__func__, cam_vreg[j].reg_name);
+				goto disable_vreg;
+			}
+			if (cam_vreg[j].delay > 20)
+				msleep(cam_vreg[j].delay);
+			else if (cam_vreg[j].delay)
+				usleep_range(cam_vreg[j].delay * 1000,
+					(cam_vreg[j].delay * 1000) + 1000);
+		}
+	} else {
+		for (i = num_vreg_seq-1; i >= 0; i--) {
+			if (vreg_seq) {
+				j = vreg_seq[i];
+				if (j >= num_vreg)
+					continue;
+			} else
+				j = i;
+			regulator_disable(reg_ptr[j]);
+			if (cam_vreg[j].delay > 20)
+				msleep(cam_vreg[j].delay);
+			else if (cam_vreg[j].delay)
+				usleep_range(cam_vreg[j].delay * 1000,
+					(cam_vreg[j].delay * 1000) + 1000);
+		}
+	}
+
+	return rc;
+disable_vreg:
+	for (i--; i >= 0; i--) {
+		if (vreg_seq) {
+			j = vreg_seq[i];
+			if (j >= num_vreg)
+				continue;
+		} else
+			j = i;
+		regulator_disable(reg_ptr[j]);
+		if (cam_vreg[j].delay > 20)
+			msleep(cam_vreg[j].delay);
+		else if (cam_vreg[j].delay)
+			usleep_range(cam_vreg[j].delay * 1000,
+				(cam_vreg[j].delay * 1000) + 1000);
+	}
+
+	return rc;
+}
+
+int msm_camera_set_gpio_table(struct msm_gpio_set_tbl *gpio_tbl,
+	uint8_t gpio_tbl_size, int gpio_en)
+{
+	int rc = 0, i;
+
+	if (gpio_en) {
+		for (i = 0; i < gpio_tbl_size; i++) {
+			gpio_set_value_cansleep(gpio_tbl[i].gpio,
+				gpio_tbl[i].flags);
+			usleep_range(gpio_tbl[i].delay,
+				gpio_tbl[i].delay + 1000);
+		}
+	} else {
+		for (i = gpio_tbl_size - 1; i >= 0; i--) {
+			if (gpio_tbl[i].flags)
+				gpio_set_value_cansleep(gpio_tbl[i].gpio,
+					GPIOF_OUT_INIT_LOW);
+		}
+	}
+
+	return rc;
+}
+
+int msm_camera_config_single_vreg(struct device *dev,
+	struct camera_vreg_t *cam_vreg, struct regulator **reg_ptr, int config)
+{
+	int rc = 0;
+	const char *vreg_name = NULL;
+
+	if (!dev || !cam_vreg || !reg_ptr) {
+		pr_err("%s: get failed NULL parameter\n", __func__);
+		goto vreg_get_fail;
+	}
+	if (cam_vreg->type == VREG_TYPE_CUSTOM) {
+		if (cam_vreg->custom_vreg_name == NULL) {
+			pr_err("%s : can't find sub reg name",
+				__func__);
+			goto vreg_get_fail;
+		}
+		vreg_name = cam_vreg->custom_vreg_name;
+	} else {
+		if (cam_vreg->reg_name == NULL) {
+			pr_err("%s : can't find reg name", __func__);
+			goto vreg_get_fail;
+		}
+		vreg_name = cam_vreg->reg_name;
+	}
+
+	if (config) {
+		CDBG("%s enable %s\n", __func__, vreg_name);
+		*reg_ptr = regulator_get(dev, vreg_name);
+		if (IS_ERR(*reg_ptr)) {
+			pr_err("%s: %s get failed\n", __func__, vreg_name);
+			*reg_ptr = NULL;
+			goto vreg_get_fail;
+		}
+		if (regulator_count_voltages(*reg_ptr) > 0) {
+			CDBG("%s: voltage min=%d, max=%d\n",
+				__func__, cam_vreg->min_voltage,
+				cam_vreg->max_voltage);
+			rc = regulator_set_voltage(
+				*reg_ptr, cam_vreg->min_voltage,
+				cam_vreg->max_voltage);
+			if (rc < 0) {
+				pr_err("%s: %s set voltage failed\n",
+					__func__, vreg_name);
+				goto vreg_set_voltage_fail;
+			}
+			if (cam_vreg->op_mode >= 0) {
+				rc = regulator_set_load(*reg_ptr,
+					cam_vreg->op_mode);
+				if (rc < 0) {
+					pr_err(
+					"%s: %s set optimum mode failed\n",
+					__func__, vreg_name);
+					goto vreg_set_opt_mode_fail;
+				}
+			}
+		}
+		rc = regulator_enable(*reg_ptr);
+		if (rc < 0) {
+			pr_err("%s: %s regulator_enable failed\n", __func__,
+				vreg_name);
+			goto vreg_unconfig;
+		}
+	} else {
+		CDBG("%s disable %s\n", __func__, vreg_name);
+		if (*reg_ptr) {
+			CDBG("%s disable %s\n", __func__, vreg_name);
+			regulator_disable(*reg_ptr);
+			if (regulator_count_voltages(*reg_ptr) > 0) {
+				if (cam_vreg->op_mode >= 0)
+					regulator_set_load(*reg_ptr, 0);
+				regulator_set_voltage(
+					*reg_ptr, 0, cam_vreg->max_voltage);
+			}
+			regulator_put(*reg_ptr);
+			*reg_ptr = NULL;
+		} else {
+			pr_err("%s can't disable %s\n", __func__, vreg_name);
+		}
+	}
+
+	return 0;
+
+vreg_unconfig:
+	if (regulator_count_voltages(*reg_ptr) > 0)
+		regulator_set_load(*reg_ptr, 0);
+
+vreg_set_opt_mode_fail:
+	if (regulator_count_voltages(*reg_ptr) > 0)
+		regulator_set_voltage(*reg_ptr, 0,
+			cam_vreg->max_voltage);
+
+vreg_set_voltage_fail:
+	regulator_put(*reg_ptr);
+	*reg_ptr = NULL;
+
+vreg_get_fail:
+	return -EINVAL;
+}
+
+int msm_camera_request_gpio_table(struct gpio *gpio_tbl, uint8_t size,
+	int gpio_en)
+{
+	int rc = 0, i = 0, err = 0;
+
+	if (!gpio_tbl || !size) {
+		pr_err("%s:%d invalid gpio_tbl %pK / size %d\n", __func__,
+			__LINE__, gpio_tbl, size);
+		return -EINVAL;
+	}
+	for (i = 0; i < size; i++) {
+		CDBG("%s:%d i %d, gpio %d dir %ld\n", __func__, __LINE__, i,
+			gpio_tbl[i].gpio, gpio_tbl[i].flags);
+	}
+	if (gpio_en) {
+		for (i = 0; i < size; i++) {
+			err = gpio_request_one(gpio_tbl[i].gpio,
+				gpio_tbl[i].flags, gpio_tbl[i].label);
+			if (err) {
+				/*
+				 * After GPIO request fails, contine to
+				 * apply new gpios, outout a error message
+				 * for driver bringup debug
+				 */
+				pr_err("%s:%d gpio %d:%s request fails\n",
+					__func__, __LINE__,
+					gpio_tbl[i].gpio, gpio_tbl[i].label);
+			}
+		}
+	} else {
+		gpio_free_array(gpio_tbl, size);
+	}
+
+	return rc;
+}
+
+/* Get all clocks from DT */
+static int msm_camera_get_clk_info_internal(struct device *dev,
+			struct msm_cam_clk_info **clk_info,
+			struct clk ***clk_ptr,
+			size_t *num_clk)
+{
+	int rc = 0;
+	size_t cnt, tmp;
+	uint32_t *rates, i = 0;
+	const char *clk_ctl = NULL;
+	bool clock_cntl_support = false;
+	struct device_node *of_node;
+
+	of_node = dev->of_node;
+
+	cnt = of_property_count_strings(of_node, "clock-names");
+	if (cnt <= 0) {
+		pr_err("err: No clocks found in DT=%zu\n", cnt);
+		return -EINVAL;
+	}
+
+	tmp = of_property_count_u32_elems(of_node, "qcom,clock-rates");
+	if (tmp <= 0) {
+		pr_err("err: No clk rates device tree, count=%zu", tmp);
+		return -EINVAL;
+	}
+
+	if (cnt != tmp) {
+		pr_err("err: clk name/rates mismatch, strings=%zu, rates=%zu\n",
+			cnt, tmp);
+		return -EINVAL;
+	}
+
+	if (of_property_read_bool(of_node, "qcom,clock-cntl-support")) {
+		tmp = of_property_count_strings(of_node,
+				"qcom,clock-control");
+		if (tmp <= 0) {
+			pr_err("err: control strings not found in DT count=%zu",
+				tmp);
+			return -EINVAL;
+		}
+		if (cnt != tmp) {
+			pr_err("err: controls mismatch, strings=%zu, ctl=%zu\n",
+				cnt, tmp);
+			return -EINVAL;
+		}
+		clock_cntl_support = true;
+	}
+
+	*num_clk = cnt;
+
+	*clk_info = devm_kcalloc(dev, cnt,
+				sizeof(struct msm_cam_clk_info), GFP_KERNEL);
+	if (!*clk_info)
+		return -ENOMEM;
+
+	*clk_ptr = devm_kcalloc(dev, cnt, sizeof(struct clk *),
+				GFP_KERNEL);
+	if (!*clk_ptr) {
+		rc = -ENOMEM;
+		goto free_clk_info;
+	}
+
+	rates = devm_kcalloc(dev, cnt, sizeof(long), GFP_KERNEL);
+	if (!rates) {
+		rc = -ENOMEM;
+		goto free_clk_ptr;
+	}
+
+	rc = of_property_read_u32_array(of_node, "qcom,clock-rates",
+		rates, cnt);
+	if (rc < 0) {
+		pr_err("err: failed reading clock rates\n");
+		rc = -EINVAL;
+		goto free_rates;
+	}
+
+	for (i = 0; i < cnt; i++) {
+		rc = of_property_read_string_index(of_node, "clock-names",
+				i, &((*clk_info)[i].clk_name));
+		if (rc < 0) {
+			pr_err("%s reading clock-name failed index %d\n",
+				__func__, i);
+			rc = -EINVAL;
+			goto free_rates;
+		}
+
+		CDBG("dbg: clk-name[%d] = %s\n", i, (*clk_info)[i].clk_name);
+		if (clock_cntl_support) {
+			rc = of_property_read_string_index(of_node,
+				"qcom,clock-control", i, &clk_ctl);
+			if (rc < 0) {
+				pr_err("%s reading clock-control failed index %d\n",
+					__func__, i);
+				rc = -EINVAL;
+				goto free_rates;
+			}
+
+			if (!strcmp(clk_ctl, "NO_SET_RATE")) {
+				(*clk_info)[i].clk_rate = NO_SET_RATE;
+			} else if (!strcmp(clk_ctl, "INIT_RATE")) {
+				(*clk_info)[i].clk_rate = INIT_RATE;
+			} else if (!strcmp(clk_ctl, "SET_RATE")) {
+				(*clk_info)[i].clk_rate = rates[i];
+			} else {
+				pr_err("%s: error: clock control has invalid value\n",
+					 __func__);
+				rc = -EINVAL;
+				goto free_rates;
+			}
+		} else {
+			(*clk_info)[i].clk_rate =
+				(rates[i] == 0) ? (long)-1 : rates[i];
+		}
+
+		CDBG("dbg: clk-rate[%d] = rate: %ld\n",
+			i, (*clk_info)[i].clk_rate);
+
+		(*clk_ptr)[i] =
+			devm_clk_get(dev, (*clk_info)[i].clk_name);
+		if (IS_ERR((*clk_ptr)[i])) {
+			rc = PTR_ERR((*clk_ptr)[i]);
+			goto release_clk;
+		}
+		CDBG("clk ptr[%d] :%pK\n", i, (*clk_ptr)[i]);
+	}
+
+	devm_kfree(dev, rates);
+
+	return rc;
+
+release_clk:
+	for (--i; i >= 0; i--)
+		devm_clk_put(dev, (*clk_ptr)[i]);
+free_rates:
+	devm_kfree(dev, rates);
+free_clk_ptr:
+	devm_kfree(dev, *clk_ptr);
+free_clk_info:
+	devm_kfree(dev, *clk_info);
+	return rc;
+}
+
+/* Get all clocks from DT  for I2C devices */
+int msm_camera_i2c_dev_get_clk_info(struct device *dev,
+			struct msm_cam_clk_info **clk_info,
+			struct clk ***clk_ptr,
+			size_t *num_clk)
+{
+	int rc = 0;
+
+	if (!dev || !clk_info || !clk_ptr || !num_clk)
+		return -EINVAL;
+
+	rc = msm_camera_get_clk_info_internal(dev, clk_info, clk_ptr, num_clk);
+	return rc;
+}
+EXPORT_SYMBOL(msm_camera_i2c_dev_get_clk_info);
+
+/* Get all clocks from DT  for platform devices */
+int msm_camera_get_clk_info(struct platform_device *pdev,
+			struct msm_cam_clk_info **clk_info,
+			struct clk ***clk_ptr,
+			size_t *num_clk)
+{
+	int rc = 0;
+
+	if (!pdev || !&pdev->dev || !clk_info || !clk_ptr || !num_clk)
+		return -EINVAL;
+
+	rc = msm_camera_get_clk_info_internal(&pdev->dev,
+			clk_info, clk_ptr, num_clk);
+	return rc;
+}
+EXPORT_SYMBOL(msm_camera_get_clk_info);
+
+/* Get all clocks and multiple rates from DT */
+int msm_camera_get_clk_info_and_rates(
+			struct platform_device *pdev,
+			struct msm_cam_clk_info **pclk_info,
+			struct clk ***pclks,
+			uint32_t ***pclk_rates,
+			size_t *num_set,
+			size_t *num_clk)
+{
+	int rc = 0, tmp_var, cnt, tmp;
+	uint32_t i = 0, j = 0;
+	struct device_node *of_node;
+	uint32_t **rates;
+	struct clk **clks;
+	struct msm_cam_clk_info *clk_info;
+
+	if (!pdev || !pclk_info || !num_clk
+		|| !pclk_rates || !pclks || !num_set)
+		return -EINVAL;
+
+	of_node = pdev->dev.of_node;
+
+	cnt = of_property_count_strings(of_node, "clock-names");
+	if (cnt <= 0) {
+		pr_err("err: No clocks found in DT=%d\n", cnt);
+		return -EINVAL;
+	}
+
+	tmp = of_property_count_u32_elems(of_node, "qcom,clock-rates");
+	if (tmp <= 0) {
+		pr_err("err: No clk rates device tree, count=%d\n", tmp);
+		return -EINVAL;
+	}
+
+	if ((tmp % cnt) != 0) {
+		pr_err("err: clk name/rates mismatch, strings=%d, rates=%d\n",
+			cnt, tmp);
+		return -EINVAL;
+	}
+
+	*num_clk = cnt;
+	*num_set = (tmp / cnt);
+
+	clk_info = devm_kcalloc(&pdev->dev, cnt,
+				sizeof(struct msm_cam_clk_info), GFP_KERNEL);
+	if (!clk_info)
+		return -ENOMEM;
+
+	clks = devm_kcalloc(&pdev->dev, cnt, sizeof(struct clk *),
+				GFP_KERNEL);
+	if (!clks) {
+		rc = -ENOMEM;
+		goto free_clk_info;
+	}
+
+	rates = devm_kcalloc(&pdev->dev, *num_set,
+		sizeof(uint32_t *), GFP_KERNEL);
+	if (!rates) {
+		rc = -ENOMEM;
+		goto free_clk;
+	}
+
+	for (i = 0; i < *num_set; i++) {
+		rates[i] = devm_kcalloc(&pdev->dev, *num_clk,
+			sizeof(uint32_t), GFP_KERNEL);
+		if (!rates[i]) {
+			rc = -ENOMEM;
+			for (--i; i >= 0; i--)
+				devm_kfree(&pdev->dev, rates[i]);
+			goto free_rate;
+		}
+	}
+
+	tmp_var = 0;
+	for (i = 0; i < *num_set; i++) {
+		for (j = 0; j < *num_clk; j++) {
+			rc = of_property_read_u32_index(of_node,
+				"qcom,clock-rates", tmp_var++, &rates[i][j]);
+			if (rc < 0) {
+				pr_err("err: failed reading clock rates\n");
+				rc = -EINVAL;
+				goto free_rate_array;
+			}
+			CDBG("Clock rate idx %d idx %d value %d\n",
+				i, j, rates[i][j]);
+		}
+	}
+	for (i = 0; i < *num_clk; i++) {
+		rc = of_property_read_string_index(of_node, "clock-names",
+				i, &clk_info[i].clk_name);
+		if (rc < 0) {
+			pr_err("%s reading clock-name failed index %d\n",
+				__func__, i);
+			rc = -EINVAL;
+			goto free_rate_array;
+		}
+
+		CDBG("dbg: clk-name[%d] = %s\n", i, clk_info[i].clk_name);
+
+		clks[i] =
+			devm_clk_get(&pdev->dev, clk_info[i].clk_name);
+		if (IS_ERR(clks[i])) {
+			rc = PTR_ERR(clks[i]);
+			goto release_clk;
+		}
+		CDBG("clk ptr[%d] :%pK\n", i, clks[i]);
+	}
+	*pclk_info = clk_info;
+	*pclks = clks;
+	*pclk_rates = rates;
+
+	return rc;
+
+release_clk:
+	for (--i; i >= 0; i--)
+		devm_clk_put(&pdev->dev, clks[i]);
+free_rate_array:
+	for (i = 0; i < *num_set; i++)
+		devm_kfree(&pdev->dev, rates[i]);
+free_rate:
+	devm_kfree(&pdev->dev, rates);
+free_clk:
+	devm_kfree(&pdev->dev, clks);
+free_clk_info:
+	devm_kfree(&pdev->dev, clk_info);
+	return rc;
+}
+EXPORT_SYMBOL(msm_camera_get_clk_info_and_rates);
+
+/* Enable/Disable all clocks */
+int msm_camera_clk_enable(struct device *dev,
+		struct msm_cam_clk_info *clk_info,
+		struct clk **clk_ptr, int num_clk, int enable)
+{
+	int i;
+	int rc = 0;
+	long clk_rate;
+
+	if (enable) {
+		for (i = 0; i < num_clk; i++) {
+			pr_err("enable %s\n", clk_info[i].clk_name);
+			if (clk_info[i].clk_rate > 0) {
+				clk_rate = clk_round_rate(clk_ptr[i],
+					clk_info[i].clk_rate);
+				if (clk_rate < 0) {
+					pr_err("%s round failed\n",
+						   clk_info[i].clk_name);
+					goto cam_clk_set_err;
+				}
+				rc = clk_set_rate(clk_ptr[i],
+					clk_rate);
+				if (rc < 0) {
+					pr_err("%s set failed\n",
+						clk_info[i].clk_name);
+					goto cam_clk_set_err;
+				}
+
+			} else if (clk_info[i].clk_rate == INIT_RATE) {
+				clk_rate = clk_get_rate(clk_ptr[i]);
+				if (clk_rate == 0) {
+					clk_rate =
+						  clk_round_rate(clk_ptr[i], 0);
+					if (clk_rate < 0) {
+						pr_err("%s round rate failed\n",
+							  clk_info[i].clk_name);
+						goto cam_clk_set_err;
+					}
+					rc = clk_set_rate(clk_ptr[i],
+								clk_rate);
+					if (rc < 0) {
+						pr_err("%s set rate failed\n",
+							  clk_info[i].clk_name);
+						goto cam_clk_set_err;
+					}
+				}
+			}
+			rc = clk_prepare_enable(clk_ptr[i]);
+			if (rc < 0) {
+				pr_err("%s enable failed\n",
+					   clk_info[i].clk_name);
+				goto cam_clk_enable_err;
+			}
+			if (clk_info[i].delay > 20) {
+				msleep(clk_info[i].delay);
+			} else if (clk_info[i].delay) {
+				usleep_range(clk_info[i].delay * 1000,
+					(clk_info[i].delay * 1000) + 1000);
+			}
+		}
+	} else {
+		for (i = num_clk - 1; i >= 0; i--) {
+			if (clk_ptr[i] != NULL) {
+				pr_err("%s disable %s\n", __func__,
+					clk_info[i].clk_name);
+				clk_disable_unprepare(clk_ptr[i]);
+			}
+		}
+	}
+	return rc;
+
+cam_clk_enable_err:
+cam_clk_set_err:
+	for (i--; i >= 0; i--) {
+		if (clk_ptr[i] != NULL)
+			clk_disable_unprepare(clk_ptr[i]);
+	}
+	return rc;
+}
+EXPORT_SYMBOL(msm_camera_clk_enable);
+
+/* Set rate on a specific clock */
+long msm_camera_clk_set_rate(struct device *dev,
+			struct clk *clk,
+			long clk_rate)
+{
+	int rc = 0;
+	long rate = 0;
+
+	if (!dev || !clk || (clk_rate < 0))
+		return -EINVAL;
+
+	CDBG("clk : %pK, enable : %ld\n", clk, clk_rate);
+
+	if (clk_rate > 0) {
+		rate = clk_round_rate(clk, clk_rate);
+		if (rate < 0) {
+			pr_err("round rate failed\n");
+			return -EINVAL;
+		}
+
+		rc = clk_set_rate(clk, rate);
+		if (rc < 0) {
+			pr_err("set rate failed\n");
+			return -EINVAL;
+		}
+	}
+
+	return rate;
+}
+EXPORT_SYMBOL(msm_camera_clk_set_rate);
+
+/* release memory allocated for clocks */
+static int msm_camera_put_clk_info_internal(struct device *dev,
+				struct msm_cam_clk_info **clk_info,
+				struct clk ***clk_ptr, int cnt)
+{
+	int i;
+
+	for (i = cnt - 1; i >= 0; i--) {
+		if (clk_ptr[i] != NULL)
+			devm_clk_put(dev, (*clk_ptr)[i]);
+
+		CDBG("clk ptr[%d] :%pK\n", i, (*clk_ptr)[i]);
+	}
+	devm_kfree(dev, *clk_info);
+	devm_kfree(dev, *clk_ptr);
+	*clk_info = NULL;
+	*clk_ptr = NULL;
+	return 0;
+}
+
+/* release memory allocated for clocks for i2c devices */
+int msm_camera_i2c_dev_put_clk_info(struct device *dev,
+				struct msm_cam_clk_info **clk_info,
+				struct clk ***clk_ptr, int cnt)
+{
+	int rc = 0;
+
+	if (!dev || !clk_info || !clk_ptr)
+		return -EINVAL;
+
+	rc = msm_camera_put_clk_info_internal(dev, clk_info, clk_ptr, cnt);
+	return rc;
+}
+EXPORT_SYMBOL(msm_camera_i2c_dev_put_clk_info);
+
+/* release memory allocated for clocks for platform devices */
+int msm_camera_put_clk_info(struct platform_device *pdev,
+				struct msm_cam_clk_info **clk_info,
+				struct clk ***clk_ptr, int cnt)
+{
+	int rc = 0;
+
+	if (!pdev || !&pdev->dev || !clk_info || !clk_ptr)
+		return -EINVAL;
+
+	rc = msm_camera_put_clk_info_internal(&pdev->dev,
+			clk_info, clk_ptr, cnt);
+	return rc;
+}
+EXPORT_SYMBOL(msm_camera_put_clk_info);
+
+int msm_camera_put_clk_info_and_rates(struct platform_device *pdev,
+		struct msm_cam_clk_info **clk_info,
+		struct clk ***clk_ptr, uint32_t ***clk_rates,
+		size_t set, size_t cnt)
+{
+	int i;
+
+	for (i = set - 1; i >= 0; i--)
+		devm_kfree(&pdev->dev, (*clk_rates)[i]);
+
+	devm_kfree(&pdev->dev, *clk_rates);
+	for (i = cnt - 1; i >= 0; i--) {
+		if (clk_ptr[i] != NULL)
+			devm_clk_put(&pdev->dev, (*clk_ptr)[i]);
+		CDBG("clk ptr[%d] :%pK\n", i, (*clk_ptr)[i]);
+	}
+	devm_kfree(&pdev->dev, *clk_info);
+	devm_kfree(&pdev->dev, *clk_ptr);
+	*clk_info = NULL;
+	*clk_ptr = NULL;
+	*clk_rates = NULL;
+
+	return 0;
+}
+EXPORT_SYMBOL(msm_camera_put_clk_info_and_rates);
+
+/* Get regulators from DT */
+int msm_camera_get_regulator_info(struct platform_device *pdev,
+				struct msm_cam_regulator **vdd_info,
+				int *num_reg)
+{
+	uint32_t cnt;
+	int i, rc;
+	struct device_node *of_node;
+	char prop_name[32];
+	struct msm_cam_regulator *tmp_reg;
+
+	if (!pdev || !vdd_info || !num_reg)
+		return -EINVAL;
+
+	of_node = pdev->dev.of_node;
+
+	if (!of_get_property(of_node, "qcom,vdd-names", NULL)) {
+		pr_err("err: Regulators property not found\n");
+		return -EINVAL;
+	}
+
+	cnt = of_property_count_strings(of_node, "qcom,vdd-names");
+	if (cnt <= 0) {
+		pr_err("err: no regulators found in device tree, count=%d",
+			cnt);
+		return -EINVAL;
+	}
+
+	tmp_reg = devm_kcalloc(&pdev->dev, cnt,
+				sizeof(struct msm_cam_regulator), GFP_KERNEL);
+	if (!tmp_reg)
+		return -ENOMEM;
+
+	for (i = 0; i < cnt; i++) {
+		rc = of_property_read_string_index(of_node,
+			"qcom,vdd-names", i, &tmp_reg[i].name);
+		if (rc < 0) {
+			pr_err("Fail to fetch regulators: %d\n", i);
+			rc = -EINVAL;
+			goto err1;
+		}
+
+		CDBG("regulator-names[%d] = %s\n", i, tmp_reg[i].name);
+
+		snprintf(prop_name, 32, "%s-supply", tmp_reg[i].name);
+
+		if (of_get_property(of_node, prop_name, NULL)) {
+			tmp_reg[i].vdd =
+				devm_regulator_get(&pdev->dev, tmp_reg[i].name);
+			if (IS_ERR(tmp_reg[i].vdd)) {
+				rc = -EINVAL;
+				pr_err("Fail to get regulator :%d\n", i);
+				goto err1;
+			}
+		} else {
+			pr_err("Regulator phandle not found :%s\n",
+				tmp_reg[i].name);
+			rc = -EINVAL;
+			goto err1;
+		}
+		CDBG("vdd ptr[%d] :%pK\n", i, tmp_reg[i].vdd);
+	}
+
+	*num_reg = cnt;
+	*vdd_info = tmp_reg;
+
+	return 0;
+
+err1:
+	for (--i; i >= 0; i--)
+		devm_regulator_put(tmp_reg[i].vdd);
+	devm_kfree(&pdev->dev, tmp_reg);
+	return rc;
+}
+EXPORT_SYMBOL(msm_camera_get_regulator_info);
+
+
+/* Enable/Disable regulators */
+int msm_camera_regulator_enable(struct msm_cam_regulator *vdd_info,
+				int cnt, int enable)
+{
+	int i;
+	int rc;
+	struct msm_cam_regulator *tmp = vdd_info;
+
+	if (!tmp) {
+		pr_err("Invalid params");
+		return -EINVAL;
+	}
+	CDBG("cnt : %d\n", cnt);
+
+	for (i = 0; i < cnt; i++) {
+		if (tmp && !IS_ERR_OR_NULL(tmp->vdd)) {
+			CDBG("name : %s, enable : %d\n", tmp->name, enable);
+			if (enable) {
+				rc = regulator_enable(tmp->vdd);
+				if (rc < 0) {
+					pr_err("regulator enable failed %d\n",
+						i);
+					goto disable_reg;
+				}
+			} else {
+				rc = regulator_disable(tmp->vdd);
+				if (rc < 0)
+					pr_err("regulator disable failed %d\n",
+						i);
+			}
+		}
+		tmp++;
+	}
+
+	return 0;
+disable_reg:
+	for (--i; i > 0; i--) {
+		--tmp;
+		if (!IS_ERR_OR_NULL(tmp->vdd))
+			regulator_disable(tmp->vdd);
+	}
+	return rc;
+}
+EXPORT_SYMBOL(msm_camera_regulator_enable);
+
+/* Put regulators regulators */
+void msm_camera_put_regulators(struct platform_device *pdev,
+	struct msm_cam_regulator **vdd_info, int cnt)
+{
+	int i;
+
+	if (!vdd_info || !*vdd_info) {
+		pr_err("Invalid params\n");
+		return;
+	}
+
+	for (i = cnt - 1; i >= 0; i--) {
+		if (vdd_info[i] && !IS_ERR_OR_NULL(vdd_info[i]->vdd))
+			devm_regulator_put(vdd_info[i]->vdd);
+			CDBG("vdd ptr[%d] :%pK\n", i, vdd_info[i]->vdd);
+	}
+
+	devm_kfree(&pdev->dev, *vdd_info);
+	*vdd_info = NULL;
+}
+EXPORT_SYMBOL(msm_camera_put_regulators);
+
+struct resource *msm_camera_get_irq(struct platform_device *pdev,
+							char *irq_name)
+{
+	if (!pdev || !irq_name) {
+		pr_err("Invalid params\n");
+		return NULL;
+	}
+
+	CDBG("Get irq for %s\n", irq_name);
+	return platform_get_resource_byname(pdev, IORESOURCE_IRQ, irq_name);
+}
+EXPORT_SYMBOL(msm_camera_get_irq);
+
+int msm_camera_register_irq(struct platform_device *pdev,
+			struct resource *irq, irq_handler_t handler,
+			unsigned long irqflags, char *irq_name, void *dev_id)
+{
+	int rc = 0;
+
+	if (!pdev || !irq || !handler || !irq_name || !dev_id) {
+		pr_err("Invalid params\n");
+		return -EINVAL;
+	}
+
+	rc = devm_request_irq(&pdev->dev, irq->start, handler,
+		irqflags, irq_name, dev_id);
+	if (rc < 0) {
+		pr_err("irq request fail\n");
+		rc = -EINVAL;
+	}
+
+	CDBG("Registered irq for %s[resource - %pK]\n", irq_name, irq);
+
+	return rc;
+}
+EXPORT_SYMBOL(msm_camera_register_irq);
+
+int msm_camera_register_threaded_irq(struct platform_device *pdev,
+			struct resource *irq, irq_handler_t handler_fn,
+			irq_handler_t thread_fn, unsigned long irqflags,
+			const char *irq_name, void *dev_id)
+{
+	int rc = 0;
+
+	if (!pdev || !irq || !irq_name || !dev_id) {
+		pr_err("Invalid params\n");
+		return -EINVAL;
+	}
+
+	rc = devm_request_threaded_irq(&pdev->dev, irq->start, handler_fn,
+			thread_fn, irqflags, irq_name, dev_id);
+	if (rc < 0) {
+		pr_err("irq request fail\n");
+		rc = -EINVAL;
+	}
+
+	CDBG("Registered irq for %s[resource - %pK]\n", irq_name, irq);
+
+	return rc;
+}
+EXPORT_SYMBOL(msm_camera_register_threaded_irq);
+
+int msm_camera_enable_irq(struct resource *irq, int enable)
+{
+	if (!irq) {
+		pr_err("Invalid params\n");
+		return -EINVAL;
+	}
+
+	CDBG("irq Enable %d\n", enable);
+	if (enable)
+		enable_irq(irq->start);
+	else
+		disable_irq(irq->start);
+
+	return 0;
+}
+EXPORT_SYMBOL(msm_camera_enable_irq);
+
+int msm_camera_unregister_irq(struct platform_device *pdev,
+	struct resource *irq, void *dev_id)
+{
+
+	if (!pdev || !irq || !dev_id) {
+		pr_err("Invalid params\n");
+		return -EINVAL;
+	}
+
+	CDBG("Un Registering irq for [resource - %pK]\n", irq);
+	devm_free_irq(&pdev->dev, irq->start, dev_id);
+
+	return 0;
+}
+EXPORT_SYMBOL(msm_camera_unregister_irq);
+
+void __iomem *msm_camera_get_reg_base(struct platform_device *pdev,
+		char *device_name, int reserve_mem)
+{
+	struct resource *mem;
+	void *base;
+
+	if (!pdev || !device_name) {
+		pr_err("Invalid params\n");
+		return NULL;
+	}
+
+	CDBG("device name :%s\n", device_name);
+	mem = platform_get_resource_byname(pdev,
+			IORESOURCE_MEM, device_name);
+	if (!mem) {
+		pr_err("err: mem resource %s not found\n", device_name);
+		return NULL;
+	}
+
+	if (reserve_mem) {
+		CDBG("device:%pK, mem : %pK, size : %d\n",
+			&pdev->dev, mem, (int)resource_size(mem));
+		if (!devm_request_mem_region(&pdev->dev, mem->start,
+			resource_size(mem),
+			device_name)) {
+			pr_err("err: no valid mem region for device:%s\n",
+				device_name);
+			return NULL;
+		}
+	}
+
+	base = devm_ioremap(&pdev->dev, mem->start, resource_size(mem));
+	if (!base) {
+		devm_release_mem_region(&pdev->dev, mem->start,
+				resource_size(mem));
+		pr_err("err: ioremap failed: %s\n", device_name);
+		return NULL;
+	}
+
+	CDBG("base : %pK\n", base);
+	return base;
+}
+EXPORT_SYMBOL(msm_camera_get_reg_base);
+
+uint32_t msm_camera_get_res_size(struct platform_device *pdev,
+	char *device_name)
+{
+	struct resource *mem;
+
+	if (!pdev || !device_name) {
+		pr_err("Invalid params\n");
+		return 0;
+	}
+
+	CDBG("device name :%s\n", device_name);
+	mem = platform_get_resource_byname(pdev,
+		IORESOURCE_MEM, device_name);
+	if (!mem) {
+		pr_err("err: mem resource %s not found\n", device_name);
+		return 0;
+	}
+	return resource_size(mem);
+}
+EXPORT_SYMBOL(msm_camera_get_res_size);
+
+
+int msm_camera_put_reg_base(struct platform_device *pdev,
+	void __iomem *base, char *device_name, int reserve_mem)
+{
+	struct resource *mem;
+
+	if (!pdev || !base || !device_name) {
+		pr_err("Invalid params\n");
+		return -EINVAL;
+	}
+
+	CDBG("device name :%s\n", device_name);
+	mem = platform_get_resource_byname(pdev,
+			IORESOURCE_MEM, device_name);
+	if (!mem) {
+		pr_err("err: mem resource %s not found\n", device_name);
+		return -EINVAL;
+	}
+	CDBG("mem : %pK, size : %d\n", mem, (int)resource_size(mem));
+
+	devm_iounmap(&pdev->dev, base);
+	if (reserve_mem)
+		devm_release_mem_region(&pdev->dev,
+			mem->start, resource_size(mem));
+
+	return 0;
+}
+EXPORT_SYMBOL(msm_camera_put_reg_base);
diff --git a/drivers/media/platform/msm/camera/cam_sensor_module/cam_sensor_utils/cam_sensor_soc_api.h b/drivers/media/platform/msm/camera/cam_sensor_module/cam_sensor_utils/cam_sensor_soc_api.h
new file mode 100644
index 0000000..c316090
--- /dev/null
+++ b/drivers/media/platform/msm/camera/cam_sensor_module/cam_sensor_utils/cam_sensor_soc_api.h
@@ -0,0 +1,473 @@
+/* Copyright (c) 2017, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#ifndef _CAM_SENSOR_SOC_API_H_
+#define _CAM_SENSOR_SOC_API_H_
+
+#include <linux/io.h>
+#include <linux/module.h>
+#include <linux/of_platform.h>
+#include <linux/spinlock_types.h>
+#include <linux/mutex.h>
+#include <linux/clk.h>
+#include <linux/regulator/consumer.h>
+#include <linux/gpio.h>
+#include <linux/interrupt.h>
+#include <linux/slab.h>
+#include "cam_sensor_cmn_header.h"
+
+struct msm_cam_regulator {
+	const char *name;
+	struct regulator *vdd;
+};
+
+struct msm_gpio_set_tbl {
+	unsigned int gpio;
+	unsigned long flags;
+	uint32_t delay;
+};
+
+/**
+ * @brief      : Gets clock information from dtsi
+ *
+ * This function extracts the clocks information for a specific
+ * platform device
+ *
+ * @param pdev   : Platform device to get clocks information
+ * @param clk_info   : Pointer to populate clock information array
+ * @param clk_ptr   : Pointer to populate clock resource pointers
+ * @param num_clk: Pointer to populate the number of clocks
+ *                 extracted from dtsi
+ *
+ * @return Status of operation. Negative in case of error. Zero otherwise.
+ */
+int msm_camera_get_clk_info(struct platform_device *pdev,
+			struct msm_cam_clk_info **clk_info,
+			struct clk ***clk_ptr,
+			size_t *num_clk);
+
+/**
+ * @brief      : Gets clock information from dtsi
+ *
+ * This function extracts the clocks information for a specific
+ * i2c device
+ *
+ * @param dev   : i2c device to get clocks information
+ * @param clk_info   : Pointer to populate clock information array
+ * @param clk_ptr   : Pointer to populate clock resource pointers
+ * @param num_clk: Pointer to populate the number of clocks
+ *                 extracted from dtsi
+ *
+ * @return Status of operation. Negative in case of error. Zero otherwise.
+ */
+int msm_camera_i2c_dev_get_clk_info(struct device *dev,
+			struct msm_cam_clk_info **clk_info,
+			struct clk ***clk_ptr,
+			size_t *num_clk);
+
+/**
+ * @brief      : Gets clock information and rates from dtsi
+ *
+ * This function extracts the clocks information for a specific
+ * platform device
+ *
+ * @param pdev   : Platform device to get clocks information
+ * @param clk_info   : Pointer to populate clock information array
+ * @param clk_ptr   : Pointer to populate clock resource pointers
+ * @param clk_rates   : Pointer to populate clock rates
+ * @param num_set: Pointer to populate the number of sets of rates
+ * @param num_clk: Pointer to populate the number of clocks
+ *                 extracted from dtsi
+ *
+ * @return Status of operation. Negative in case of error. Zero otherwise.
+ */
+int msm_camera_get_clk_info_and_rates(
+			struct platform_device *pdev,
+			struct msm_cam_clk_info **clk_info,
+			struct clk ***clk_ptr,
+			uint32_t ***clk_rates,
+			size_t *num_set,
+			size_t *num_clk);
+
+/**
+ * @brief      : Puts clock information
+ *
+ * This function releases the memory allocated for the clocks
+ *
+ * @param pdev   : Pointer to platform device
+ * @param clk_info   : Pointer to release the allocated memory
+ * @param clk_ptr   : Pointer to release the clock resources
+ * @param cnt   : Number of clk resources
+ *
+ * @return Status of operation. Negative in case of error. Zero otherwise.
+ */
+int msm_camera_put_clk_info(struct platform_device *pdev,
+				struct msm_cam_clk_info **clk_info,
+				struct clk ***clk_ptr, int cnt);
+
+/**
+ * @brief      : Puts clock information
+ *
+ * This function releases the memory allocated for the clocks
+ *
+ * @param dev   : Pointer to i2c device
+ * @param clk_info   : Pointer to release the allocated memory
+ * @param clk_ptr   : Pointer to release the clock resources
+ * @param cnt   : Number of clk resources
+ *
+ * @return Status of operation. Negative in case of error. Zero otherwise.
+ */
+int msm_camera_i2c_dev_put_clk_info(struct device *dev,
+			struct msm_cam_clk_info **clk_info,
+			struct clk ***clk_ptr, int cnt);
+
+/**
+ * @brief      : Puts clock information
+ *
+ * This function releases the memory allocated for the clocks
+ *
+ * @param pdev   : Pointer to platform device
+ * @param clk_info   : Pointer to release the allocated memory
+ * @param clk_ptr   : Pointer to release the clock resources
+ * @param clk_ptr   : Pointer to release the clock rates
+ * @param set   : Number of sets of clock rates
+ * @param cnt   : Number of clk resources
+ *
+ * @return Status of operation. Negative in case of error. Zero otherwise.
+ */
+int msm_camera_put_clk_info_and_rates(struct platform_device *pdev,
+		struct msm_cam_clk_info **clk_info,
+		struct clk ***clk_ptr, uint32_t ***clk_rates,
+		size_t set, size_t cnt);
+/**
+ * @brief      : Enable clocks
+ *
+ * This function enables the clocks for a specified device
+ *
+ * @param dev   : Device to get clocks information
+ * @param clk_info   : Pointer to populate clock information
+ * @param clk_ptr   : Pointer to populate clock information
+ * @param num_clk: Pointer to populate the number of clocks
+ *                 extracted from dtsi
+ * @param enable   : Flag to specify enable/disable
+ *
+ * @return Status of operation. Negative in case of error. Zero otherwise.
+ */
+
+int msm_camera_clk_enable(struct device *dev,
+					struct msm_cam_clk_info *clk_info,
+					struct clk **clk_ptr,
+					int num_clk,
+					int enable);
+/**
+ * @brief      : Set clock rate
+ *
+ * This function sets the rate for a specified clock and
+ * returns the rounded value
+ *
+ * @param dev   : Device to get clocks information
+ * @param clk   : Pointer to clock to set rate
+ * @param clk_rate   : Rate to be set
+ *
+ * @return Status of operation. Negative in case of error. clk rate otherwise.
+ */
+
+long msm_camera_clk_set_rate(struct device *dev,
+				struct clk *clk,
+				long clk_rate);
+/**
+ * @brief      : Gets regulator info
+ *
+ * This function extracts the regulator information for a specific
+ * platform device
+ *
+ * @param pdev   : platform device to get regulator information
+ * @param vdd_info: Pointer to populate the regulator names
+ * @param num_reg: Pointer to populate the number of regulators
+ *                 extracted from dtsi
+ *
+ * @return Status of operation. Negative in case of error. Zero otherwise.
+ */
+int msm_camera_get_regulator_info(struct platform_device *pdev,
+		struct msm_cam_regulator **vdd_info, int *num_reg);
+/**
+ * @brief      : Enable/Disable the regultors
+ *
+ * This function enables/disables the regulators for a specific
+ * platform device
+ *
+ * @param vdd_info: Pointer to list of regulators
+ * @param cnt: Number of regulators to enable/disable
+ * @param enable: Flags specifies either enable/disable
+ *
+ * @return Status of operation. Negative in case of error. Zero otherwise.
+ */
+
+int msm_camera_regulator_enable(struct msm_cam_regulator *vdd_info,
+				int cnt, int enable);
+
+/**
+ * @brief      : Release the regulators
+ *
+ * This function releases the regulator resources.
+ *
+ * @param pdev: Pointer to platform device
+ * @param vdd_info: Pointer to list of regulators
+ * @param cnt: Number of regulators to release
+ */
+
+void msm_camera_put_regulators(struct platform_device *pdev,
+	struct msm_cam_regulator **vdd_info, int cnt);
+/**
+ * @brief      : Get the IRQ resource
+ *
+ * This function gets the irq resource from dtsi for a specific
+ * platform device
+ *
+ * @param pdev   : Platform device to get IRQ
+ * @param irq_name: Name of the IRQ resource to get from DTSI
+ *
+ * @return Pointer to resource if success else null
+ */
+
+struct resource *msm_camera_get_irq(struct platform_device *pdev,
+							char *irq_name);
+/**
+ * @brief      : Register the IRQ
+ *
+ * This function registers the irq resource for specified hardware
+ *
+ * @param pdev    : Platform device to register IRQ resource
+ * @param irq	  : IRQ resource
+ * @param handler : IRQ handler
+ * @param irqflags : IRQ flags
+ * @param irq_name: Name of the IRQ
+ * @param dev	 : Token of the device
+ *
+ * @return Status of operation. Negative in case of error. Zero otherwise.
+ */
+
+int msm_camera_register_irq(struct platform_device *pdev,
+						struct resource *irq,
+						irq_handler_t handler,
+						unsigned long irqflags,
+						char *irq_name,
+						void *dev);
+
+/**
+ * @brief      : Register the threaded IRQ
+ *
+ * This function registers the irq resource for specified hardware
+ *
+ * @param pdev    : Platform device to register IRQ resource
+ * @param irq	  : IRQ resource
+ * @param handler_fn : IRQ handler function
+ * @param thread_fn : thread handler function
+ * @param irqflags : IRQ flags
+ * @param irq_name: Name of the IRQ
+ * @param dev	 : Token of the device
+ *
+ * @return Status of operation. Negative in case of error. Zero otherwise.
+ */
+
+int msm_camera_register_threaded_irq(struct platform_device *pdev,
+						struct resource *irq,
+						irq_handler_t handler_fn,
+						irq_handler_t thread_fn,
+						unsigned long irqflags,
+						const char *irq_name,
+						void *dev);
+
+/**
+ * @brief      : Enable/Disable the IRQ
+ *
+ * This function enables or disables a specific IRQ
+ *
+ * @param irq    : IRQ resource
+ * @param flag   : flag to enable/disable
+ *
+ * @return Status of operation. Negative in case of error. Zero otherwise.
+ */
+
+int msm_camera_enable_irq(struct resource *irq, int flag);
+
+/**
+ * @brief      : UnRegister the IRQ
+ *
+ * This function Unregisters/Frees the irq resource
+ *
+ * @param pdev   : Pointer to platform device
+ * @param irq    : IRQ resource
+ * @param dev    : Token of the device
+ *
+ * @return Status of operation. Negative in case of error. Zero otherwise.
+ */
+
+int msm_camera_unregister_irq(struct platform_device *pdev,
+	struct resource *irq, void *dev_id);
+
+/**
+ * @brief      : Gets device register base
+ *
+ * This function extracts the device's register base from the dtsi
+ * for the specified platform device
+ *
+ * @param pdev   : Platform device to get regulator infor
+ * @param device_name   : Name of the device to fetch the register base
+ * @param reserve_mem   : Flag to decide whether to reserve memory
+ * region or not.
+ *
+ * @return Pointer to resource if success else null
+ */
+
+void __iomem *msm_camera_get_reg_base(struct platform_device *pdev,
+		char *device_name, int reserve_mem);
+
+/**
+ * @brief      :  Puts device register base
+ *
+ * This function releases the memory region for the specified
+ * resource
+ *
+ * @param pdev   : Pointer to platform device
+ * @param base   : Pointer to base to unmap
+ * @param device_name : Device name
+ * @param reserve_mem   : Flag to decide whether to release memory
+ * region or not.
+ *
+ * @return Status of operation. Negative in case of error. Zero otherwise.
+ */
+
+int msm_camera_put_reg_base(struct platform_device *pdev, void __iomem *base,
+		char *device_name, int reserve_mem);
+
+/**
+ * @brief      : Gets resource size
+ *
+ * This function returns the size of the resource for the
+ * specified platform device
+ *
+ * @param pdev   : Platform device to get regulator infor
+ * @param device_name   : Name of the device to fetch the register base
+ *
+ * @return size of the resource
+ */
+
+uint32_t msm_camera_get_res_size(struct platform_device *pdev,
+	char *device_name);
+
+/**
+ * @brief      : Selects clock source
+ *
+ *
+ * @param dev : Token of the device
+ * @param clk_info : Clock Info structure
+ * @param clk_src_info : Clock Info structure
+ * @param num_clk : Number of clocks
+ *
+ * @return Status of operation. Negative in case of error. Zero otherwise.
+ */
+int msm_cam_clk_sel_src(struct device *dev, struct msm_cam_clk_info *clk_info,
+		struct msm_cam_clk_info *clk_src_info, int num_clk);
+
+/**
+ * @brief      : Enables the clock
+ *
+ *
+ * @param dev : Token of the device
+ * @param clk_info : Clock Info structure
+ * @param clk_tr : Pointer to lock strucure
+ * @param num_clk : Number of clocks
+ * @param enable : Enable/disable the clock
+ *
+ * @return Status of operation. Negative in case of error. Zero otherwise.
+ */
+int msm_cam_clk_enable(struct device *dev, struct msm_cam_clk_info *clk_info,
+		struct clk **clk_ptr, int num_clk, int enable);
+
+/**
+ * @brief      : Configures voltage regulator
+ *
+ *
+ * @param dev : Token of the device
+ * @param cam_vreg : Regulator dt structure
+ * @param num_vreg : Number of regulators
+ * @param vreg_seq : Regulator sequence type
+ * @param num_clk : Number of clocks
+ * @param reg_ptr : Regulator pointer
+ * @param config : Enable/disable configuring the regulator
+ *
+ * @return Status of operation. Negative in case of error. Zero otherwise.
+ */
+int msm_camera_config_vreg(struct device *dev, struct camera_vreg_t *cam_vreg,
+		int num_vreg, enum msm_camera_vreg_name_t *vreg_seq,
+		int num_vreg_seq, struct regulator **reg_ptr, int config);
+
+/**
+ * @brief      : Enables voltage regulator
+ *
+ *
+ * @param dev : Token of the device
+ * @param cam_vreg : Regulator dt structure
+ * @param num_vreg : Number of regulators
+ * @param vreg_seq : Regulator sequence type
+ * @param num_clk : Number of clocks
+ * @param reg_ptr : Regulator pointer
+ * @param config : Enable/disable configuring the regulator
+ *
+ * @return Status of operation. Negative in case of error. Zero otherwise.
+ */
+int msm_camera_enable_vreg(struct device *dev, struct camera_vreg_t *cam_vreg,
+		int num_vreg, enum msm_camera_vreg_name_t *vreg_seq,
+		int num_vreg_seq, struct regulator **reg_ptr, int enable);
+
+/**
+ * @brief      : Sets table of GPIOs
+ *
+ * @param gpio_tbl : GPIO table parsed from dt
+ * @param gpio_tbl_size : Size of GPIO table
+ * @param gpio_en : Enable/disable the GPIO
+ *
+ * @return Status of operation. Negative in case of error. Zero otherwise.
+ */
+int msm_camera_set_gpio_table(struct msm_gpio_set_tbl *gpio_tbl,
+	uint8_t gpio_tbl_size, int gpio_en);
+
+/**
+ * @brief      : Configures single voltage regulator
+ *
+ *
+ * @param dev : Token of the device
+ * @param cam_vreg : Regulator dt structure
+ * @param num_vreg : Number of regulators
+ * @param reg_ptr : Regulator pointer
+ * @param config : Enable/disable configuring the regulator
+ *
+ * @return Status of operation. Negative in case of error. Zero otherwise.
+ */
+int msm_camera_config_single_vreg(struct device *dev,
+	struct camera_vreg_t *cam_vreg, struct regulator **reg_ptr, int config);
+
+/**
+ * @brief      : Request table of gpios
+ *
+ *
+ * @param gpio_tbl : Table of GPIOs
+ * @param size : Size of table
+ * @param gpio_en : Enable/disable the gpio
+ *
+ * @return Status of operation. Negative in case of error. Zero otherwise.
+ */
+int msm_camera_request_gpio_table(struct gpio *gpio_tbl, uint8_t size,
+	int gpio_en);
+
+#endif /* _CAM_SENSOR_SOC_API_H_ */
diff --git a/drivers/media/platform/msm/camera/cam_sensor_module/cam_sensor_utils/cam_sensor_util.c b/drivers/media/platform/msm/camera/cam_sensor_module/cam_sensor_utils/cam_sensor_util.c
new file mode 100644
index 0000000..44294e8
--- /dev/null
+++ b/drivers/media/platform/msm/camera/cam_sensor_module/cam_sensor_utils/cam_sensor_util.c
@@ -0,0 +1,1399 @@
+/* Copyright (c) 2017, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/kernel.h>
+#include "cam_sensor_util.h"
+#include "cam_sensor_soc_api.h"
+
+#define CAM_SENSOR_PINCTRL_STATE_SLEEP "cam_suspend"
+#define CAM_SENSOR_PINCTRL_STATE_DEFAULT "cam_default"
+
+#define VALIDATE_VOLTAGE(min, max, config_val) ((config_val) && \
+	(config_val >= min) && (config_val <= max))
+
+#undef CDBG
+#define CDBG(fmt, args...) pr_debug(fmt, ##args)
+
+static struct i2c_settings_list*
+	cam_sensor_get_i2c_ptr(struct i2c_settings_array *i2c_reg_settings,
+		uint32_t size)
+{
+	struct i2c_settings_list *tmp;
+
+	tmp = (struct i2c_settings_list *)
+		kzalloc(sizeof(struct i2c_settings_list), GFP_KERNEL);
+
+	if (tmp != NULL)
+		list_add_tail(&(tmp->list),
+			&(i2c_reg_settings->list_head));
+	else
+		return NULL;
+
+	tmp->i2c_settings.reg_setting = (struct cam_sensor_i2c_reg_array *)
+		kzalloc(sizeof(struct cam_sensor_i2c_reg_array) *
+		size, GFP_KERNEL);
+	if (tmp->i2c_settings.reg_setting == NULL) {
+		list_del(&(tmp->list));
+		kfree(tmp);
+		return NULL;
+	}
+	tmp->i2c_settings.size = size;
+
+	return tmp;
+}
+
+int32_t delete_request(struct i2c_settings_array *i2c_array)
+{
+	struct i2c_settings_list *i2c_list = NULL, *i2c_next = NULL;
+	int32_t rc = 0;
+
+	if (i2c_array == NULL) {
+		pr_err("%s:%d ::FATAL:: Invalid argument\n",
+			__func__, __LINE__);
+		return -EINVAL;
+	}
+
+	list_for_each_entry_safe(i2c_list, i2c_next,
+		&(i2c_array->list_head), list) {
+		kfree(i2c_list->i2c_settings.reg_setting);
+		list_del(&(i2c_list->list));
+		kfree(i2c_list);
+	}
+	INIT_LIST_HEAD(&(i2c_array->list_head));
+	i2c_array->is_settings_valid = 0;
+
+	return rc;
+}
+
+int32_t cam_sensor_handle_delay(
+	uint32_t **cmd_buf,
+	uint16_t generic_op_code,
+	struct i2c_settings_array *i2c_reg_settings,
+	uint32_t offset, uint32_t *byte_cnt,
+	struct list_head *list_ptr)
+{
+	int32_t rc = 0;
+	struct cam_cmd_unconditional_wait *cmd_uncond_wait =
+		(struct cam_cmd_unconditional_wait *) *cmd_buf;
+	struct i2c_settings_list *i2c_list = NULL;
+
+	if (i2c_list == NULL) {
+		pr_err("%s:%d Invalid list ptr\n",
+			__func__, __LINE__);
+		return -EINVAL;
+	}
+
+	if (offset > 0) {
+		i2c_list =
+			list_entry(list_ptr, struct i2c_settings_list, list);
+		if (generic_op_code ==
+			CAMERA_SENSOR_WAIT_OP_HW_UCND)
+			i2c_list->i2c_settings.
+				reg_setting[offset - 1].delay =
+				cmd_uncond_wait->delay;
+		else
+			i2c_list->i2c_settings.delay =
+				cmd_uncond_wait->delay;
+		(*cmd_buf) +=
+			sizeof(
+			struct cam_cmd_unconditional_wait) / sizeof(uint32_t);
+		(*byte_cnt) +=
+			sizeof(
+			struct cam_cmd_unconditional_wait);
+	} else {
+		pr_err("%s: %d Error: Delay Rxed Before any buffer: %d\n",
+			__func__, __LINE__, offset);
+		return -EINVAL;
+	}
+
+	return rc;
+}
+
+int32_t cam_sensor_handle_poll(
+	uint32_t **cmd_buf,
+	struct i2c_settings_array *i2c_reg_settings,
+	uint32_t *byte_cnt, int32_t *offset,
+	struct list_head **list_ptr)
+{
+	struct i2c_settings_list  *i2c_list;
+	int32_t rc = 0;
+	struct cam_cmd_conditional_wait *cond_wait
+		= (struct cam_cmd_conditional_wait *) *cmd_buf;
+
+	i2c_list =
+		cam_sensor_get_i2c_ptr(i2c_reg_settings, 1);
+	if (!i2c_list || !i2c_list->i2c_settings.reg_setting) {
+		pr_err("%s: %d Failed in allocating mem for list\n",
+			__func__, __LINE__);
+		return -ENOMEM;
+	}
+
+	i2c_list->op_code = CAM_SENSOR_I2C_POLL;
+	i2c_list->i2c_settings.data_type =
+		cond_wait->data_type;
+	i2c_list->i2c_settings.addr_type =
+		cond_wait->addr_type;
+	i2c_list->i2c_settings.reg_setting->reg_addr =
+		cond_wait->reg_addr;
+	i2c_list->i2c_settings.reg_setting->reg_data =
+		cond_wait->reg_data;
+	i2c_list->i2c_settings.reg_setting->delay =
+		cond_wait->timeout;
+
+	(*cmd_buf) += sizeof(struct cam_cmd_conditional_wait) /
+		sizeof(uint32_t);
+	(*byte_cnt) += sizeof(struct cam_cmd_conditional_wait);
+
+	(*offset) += 1;
+	*list_ptr = &(i2c_list->list);
+
+	return rc;
+}
+
+int32_t cam_sensor_handle_random_write(
+	struct cam_cmd_i2c_random_wr *cam_cmd_i2c_random_wr,
+	struct i2c_settings_array *i2c_reg_settings,
+	uint16_t *cmd_length_in_bytes, int32_t *offset,
+	struct list_head **list)
+{
+	struct i2c_settings_list  *i2c_list;
+	int32_t rc = 0, cnt;
+
+	i2c_list = cam_sensor_get_i2c_ptr(i2c_reg_settings,
+		cam_cmd_i2c_random_wr->header.count);
+	if (i2c_list == NULL ||
+		i2c_list->i2c_settings.reg_setting == NULL) {
+		pr_err("%s: %d Failed in allocating i2c_list\n",
+			__func__, __LINE__);
+		return -ENOMEM;
+	}
+
+	*cmd_length_in_bytes = (sizeof(struct i2c_rdwr_header) +
+		sizeof(struct i2c_random_wr_payload) *
+		(cam_cmd_i2c_random_wr->header.count));
+	i2c_list->op_code = CAM_SENSOR_I2C_WRITE_RANDOM;
+	i2c_list->i2c_settings.addr_type =
+		cam_cmd_i2c_random_wr->header.addr_type;
+	i2c_list->i2c_settings.data_type =
+		cam_cmd_i2c_random_wr->header.data_type;
+
+	for (cnt = 0; cnt < (cam_cmd_i2c_random_wr->header.count);
+		cnt++) {
+		i2c_list->i2c_settings.reg_setting[cnt].reg_addr =
+			cam_cmd_i2c_random_wr->
+			random_wr_payload[cnt].reg_addr;
+		i2c_list->i2c_settings.
+			reg_setting[cnt].reg_data =
+			cam_cmd_i2c_random_wr->
+			random_wr_payload[cnt].reg_data;
+		i2c_list->i2c_settings.
+			reg_setting[cnt].data_mask = 0;
+	}
+	(*offset) += cnt;
+	*list = &(i2c_list->list);
+
+	return rc;
+}
+
+/**
+ * Name : cam_sensor_i2c_pkt_parser
+ * Description : Parse CSL CCI packet and apply register settings
+ * Parameters :  s_ctrl  input/output    sub_device
+ *              arg     input           cam_control
+ * Description :
+ * Handle multiple I2C RD/WR and WAIT cmd formats in one command
+ * buffer, for example, a command buffer of m x RND_WR + 1 x HW_
+ * WAIT + n x RND_WR with num_cmd_buf = 1. Do not exepect RD/WR
+ * with different cmd_type and op_code in one command buffer.
+ */
+int cam_sensor_i2c_pkt_parser(struct i2c_settings_array *i2c_reg_settings,
+	struct cam_cmd_buf_desc   *cmd_desc, int32_t num_cmd_buffers)
+{
+	int16_t                   rc = 0, i = 0;
+	size_t                    len_of_buff = 0;
+	uint64_t                  generic_ptr;
+
+	for (i = 0; i < num_cmd_buffers; i++) {
+		uint32_t                  *cmd_buf = NULL;
+		struct common_header      *cmm_hdr;
+		uint16_t                  generic_op_code;
+		uint32_t                  byte_cnt = 0;
+		uint32_t                  j = 0;
+		struct list_head          *list = NULL;
+
+		/*
+		 * It is not expected the same settings to
+		 * be spread across multiple cmd buffers
+		 */
+
+		CDBG("%s:%d Total cmd Buf in Bytes: %d\n", __func__,
+			__LINE__, cmd_desc[i].length);
+
+		if (!cmd_desc[i].length)
+			continue;
+
+		rc = cam_mem_get_cpu_buf(cmd_desc[i].mem_handle,
+			(uint64_t *)&generic_ptr, &len_of_buff);
+		cmd_buf = (uint32_t *)generic_ptr;
+		if (rc < 0) {
+			pr_err("%s:%d Failed in getting cmd hdl: %d Err: %d Buffer Len: %ld\n",
+				__func__, __LINE__,
+				cmd_desc[i].mem_handle, rc,
+				len_of_buff);
+			return rc;
+		}
+		cmd_buf += cmd_desc[i].offset / sizeof(uint32_t);
+
+		while (byte_cnt < cmd_desc[i].length) {
+			cmm_hdr = (struct common_header *)cmd_buf;
+			generic_op_code = cmm_hdr->third_byte;
+			switch (cmm_hdr->cmd_type) {
+			case CAMERA_SENSOR_CMD_TYPE_I2C_RNDM_WR: {
+				uint16_t cmd_length_in_bytes   = 0;
+				struct cam_cmd_i2c_random_wr
+					*cam_cmd_i2c_random_wr =
+					(struct cam_cmd_i2c_random_wr *)cmd_buf;
+
+				rc = cam_sensor_handle_random_write(
+					cam_cmd_i2c_random_wr,
+					i2c_reg_settings,
+					&cmd_length_in_bytes, &j, &list);
+				if (rc < 0) {
+					pr_err("%s:%d :Error: Failed in random read %d\n",
+						__func__, __LINE__, rc);
+					return rc;
+				}
+
+				cmd_buf += cmd_length_in_bytes /
+					sizeof(uint32_t);
+				byte_cnt += cmd_length_in_bytes;
+				break;
+			}
+			case CAMERA_SENSOR_CMD_TYPE_WAIT: {
+				if (generic_op_code ==
+					CAMERA_SENSOR_WAIT_OP_HW_UCND ||
+					generic_op_code ==
+						CAMERA_SENSOR_WAIT_OP_SW_UCND) {
+
+					rc = cam_sensor_handle_delay(
+						&cmd_buf, generic_op_code,
+						i2c_reg_settings, j, &byte_cnt,
+						list);
+					if (rc < 0) {
+						pr_err("%s:%d :Error: Failed in handling delay %d\n",
+							__func__, __LINE__, rc);
+						return rc;
+					}
+
+				} else if (generic_op_code ==
+					CAMERA_SENSOR_WAIT_OP_COND) {
+					rc = cam_sensor_handle_poll(
+						&cmd_buf, i2c_reg_settings,
+						&byte_cnt, &j, &list);
+					if (rc < 0) {
+						pr_err("%s:%d :Error: Failed in random read %d\n",
+							__func__, __LINE__, rc);
+						return rc;
+					}
+				} else {
+					pr_err("%s: %d Wrong Wait Command: %d\n",
+						__func__, __LINE__,
+						generic_op_code);
+					return -EINVAL;
+				}
+				break;
+			}
+			default:
+				pr_err("%s:%d Invalid Command Type:%d\n",
+					__func__, __LINE__, cmm_hdr->cmd_type);
+				return -EINVAL;
+			}
+		}
+		i2c_reg_settings->is_settings_valid = 1;
+	}
+
+	return rc;
+}
+
+int32_t msm_camera_fill_vreg_params(struct camera_vreg_t *cam_vreg,
+	int num_vreg, struct cam_sensor_power_setting *power_setting,
+	uint16_t power_setting_size)
+{
+	int32_t rc = 0, j = 0, i = 0;
+
+	/* Validate input parameters */
+	if (!cam_vreg || !power_setting) {
+		pr_err("%s:%d failed: cam_vreg %pK power_setting %pK", __func__,
+			__LINE__,  cam_vreg, power_setting);
+		return -EINVAL;
+	}
+
+	/* Validate size of num_vreg */
+	if (num_vreg <= 0) {
+		pr_err("failed: num_vreg %d", num_vreg);
+		return -EINVAL;
+	}
+
+	for (i = 0; i < power_setting_size; i++) {
+		switch (power_setting[i].seq_type) {
+		case SENSOR_VDIG:
+			for (j = 0; j < num_vreg; j++) {
+				if (!strcmp(cam_vreg[j].reg_name, "cam_vdig")) {
+					CDBG("%s:%d i %d j %d cam_vdig\n",
+						__func__, __LINE__, i, j);
+					power_setting[i].seq_val = j;
+					if (VALIDATE_VOLTAGE(
+						cam_vreg[j].min_voltage,
+						cam_vreg[j].max_voltage,
+						power_setting[i].config_val)) {
+						cam_vreg[j].min_voltage =
+						cam_vreg[j].max_voltage =
+						power_setting[i].config_val;
+					}
+					break;
+				}
+			}
+			if (j == num_vreg)
+				power_setting[i].seq_val = INVALID_VREG;
+			break;
+
+		case SENSOR_VIO:
+			for (j = 0; j < num_vreg; j++) {
+				if (!strcmp(cam_vreg[j].reg_name, "cam_vio")) {
+					CDBG("%s:%d i %d j %d cam_vio\n",
+						__func__, __LINE__, i, j);
+					power_setting[i].seq_val = j;
+					if (VALIDATE_VOLTAGE(
+						cam_vreg[j].min_voltage,
+						cam_vreg[j].max_voltage,
+						power_setting[i].config_val)) {
+						cam_vreg[j].min_voltage =
+						cam_vreg[j].max_voltage =
+						power_setting[i].config_val;
+					}
+					break;
+				}
+			}
+			if (j == num_vreg)
+				power_setting[i].seq_val = INVALID_VREG;
+			break;
+
+		case SENSOR_VANA:
+			for (j = 0; j < num_vreg; j++) {
+				if (!strcmp(cam_vreg[j].reg_name, "cam_vana")) {
+					CDBG("%s:%d i %d j %d cam_vana\n",
+						__func__, __LINE__, i, j);
+					power_setting[i].seq_val = j;
+					if (VALIDATE_VOLTAGE(
+						cam_vreg[j].min_voltage,
+						cam_vreg[j].max_voltage,
+						power_setting[i].config_val)) {
+						cam_vreg[j].min_voltage =
+						cam_vreg[j].max_voltage =
+						power_setting[i].config_val;
+					}
+					break;
+				}
+			}
+			if (j == num_vreg)
+				power_setting[i].seq_val = INVALID_VREG;
+			break;
+
+		case SENSOR_VAF:
+			for (j = 0; j < num_vreg; j++) {
+				if (!strcmp(cam_vreg[j].reg_name, "cam_vaf")) {
+					CDBG("%s:%d i %d j %d cam_vaf\n",
+						__func__, __LINE__, i, j);
+					power_setting[i].seq_val = j;
+					if (VALIDATE_VOLTAGE(
+						cam_vreg[j].min_voltage,
+						cam_vreg[j].max_voltage,
+						power_setting[i].config_val)) {
+						cam_vreg[j].min_voltage =
+						cam_vreg[j].max_voltage =
+						power_setting[i].config_val;
+					}
+					break;
+				}
+			}
+			if (j == num_vreg)
+				power_setting[i].seq_val = INVALID_VREG;
+			break;
+
+		case SENSOR_CUSTOM_REG1:
+			for (j = 0; j < num_vreg; j++) {
+				if (!strcmp(cam_vreg[j].reg_name,
+					"cam_v_custom1")) {
+					CDBG("%s:%d i %d j %d cam_vcustom1\n",
+						__func__, __LINE__, i, j);
+					power_setting[i].seq_val = j;
+					if (VALIDATE_VOLTAGE(
+						cam_vreg[j].min_voltage,
+						cam_vreg[j].max_voltage,
+						power_setting[i].config_val)) {
+						cam_vreg[j].min_voltage =
+						cam_vreg[j].max_voltage =
+						power_setting[i].config_val;
+					}
+					break;
+				}
+			}
+			if (j == num_vreg)
+				power_setting[i].seq_val = INVALID_VREG;
+			break;
+		case SENSOR_CUSTOM_REG2:
+			for (j = 0; j < num_vreg; j++) {
+				if (!strcmp(cam_vreg[j].reg_name,
+					"cam_v_custom2")) {
+					CDBG("%s:%d i %d j %d cam_vcustom2\n",
+						__func__, __LINE__, i, j);
+					power_setting[i].seq_val = j;
+					if (VALIDATE_VOLTAGE(
+						cam_vreg[j].min_voltage,
+						cam_vreg[j].max_voltage,
+						power_setting[i].config_val)) {
+						cam_vreg[j].min_voltage =
+						cam_vreg[j].max_voltage =
+						power_setting[i].config_val;
+					}
+					break;
+				}
+			}
+			if (j == num_vreg)
+				power_setting[i].seq_val = INVALID_VREG;
+			break;
+
+		default: {
+			pr_err("%s:%d invalid seq_val %d\n", __func__,
+				__LINE__, power_setting[i].seq_val);
+			break;
+			}
+		}
+	}
+
+	return rc;
+}
+
+int32_t msm_camera_get_dt_gpio_req_tbl(struct device_node *of_node,
+	struct msm_camera_gpio_conf *gconf, uint16_t *gpio_array,
+	uint16_t gpio_array_size)
+{
+	int32_t rc = 0, i = 0;
+	uint32_t count = 0, *val_array = NULL;
+
+	if (!of_get_property(of_node, "qcom,gpio-req-tbl-num", &count))
+		return 0;
+
+	count /= sizeof(uint32_t);
+	if (!count) {
+		pr_err("%s qcom,gpio-req-tbl-num 0\n", __func__);
+		return 0;
+	}
+
+	val_array = kcalloc(count, sizeof(uint32_t), GFP_KERNEL);
+	if (!val_array)
+		return -ENOMEM;
+
+	gconf->cam_gpio_req_tbl = kcalloc(count, sizeof(struct gpio),
+		GFP_KERNEL);
+	if (!gconf->cam_gpio_req_tbl) {
+		rc = -ENOMEM;
+		goto free_val_array;
+	}
+	gconf->cam_gpio_req_tbl_size = count;
+
+	rc = of_property_read_u32_array(of_node, "qcom,gpio-req-tbl-num",
+		val_array, count);
+	if (rc < 0) {
+		pr_err("%s failed %d\n", __func__, __LINE__);
+		goto free_gpio_req_tbl;
+	}
+
+	for (i = 0; i < count; i++) {
+		if (val_array[i] >= gpio_array_size) {
+			pr_err("%s gpio req tbl index %d invalid\n",
+				__func__, val_array[i]);
+			return -EINVAL;
+		}
+		gconf->cam_gpio_req_tbl[i].gpio = gpio_array[val_array[i]];
+		CDBG("%s cam_gpio_req_tbl[%d].gpio = %d\n", __func__, i,
+			gconf->cam_gpio_req_tbl[i].gpio);
+	}
+
+	rc = of_property_read_u32_array(of_node, "qcom,gpio-req-tbl-flags",
+		val_array, count);
+	if (rc < 0) {
+		pr_err("%s failed %d\n", __func__, __LINE__);
+		goto free_gpio_req_tbl;
+	}
+
+	for (i = 0; i < count; i++) {
+		gconf->cam_gpio_req_tbl[i].flags = val_array[i];
+		CDBG("%s cam_gpio_req_tbl[%d].flags = %ld\n", __func__, i,
+			gconf->cam_gpio_req_tbl[i].flags);
+	}
+
+	for (i = 0; i < count; i++) {
+		rc = of_property_read_string_index(of_node,
+			"qcom,gpio-req-tbl-label", i,
+			&gconf->cam_gpio_req_tbl[i].label);
+		CDBG("%s cam_gpio_req_tbl[%d].label = %s\n", __func__, i,
+			gconf->cam_gpio_req_tbl[i].label);
+		if (rc < 0) {
+			pr_err("%s failed %d\n", __func__, __LINE__);
+			goto free_gpio_req_tbl;
+		}
+	}
+
+	kfree(val_array);
+
+	return rc;
+
+free_gpio_req_tbl:
+	kfree(gconf->cam_gpio_req_tbl);
+free_val_array:
+	kfree(val_array);
+	gconf->cam_gpio_req_tbl_size = 0;
+
+	return rc;
+}
+
+int msm_camera_init_gpio_pin_tbl(struct device_node *of_node,
+	struct msm_camera_gpio_conf *gconf, uint16_t *gpio_array,
+	uint16_t gpio_array_size)
+{
+	int rc = 0, val = 0;
+
+	gconf->gpio_num_info = kzalloc(sizeof(struct msm_camera_gpio_num_info),
+		GFP_KERNEL);
+	if (!gconf->gpio_num_info)
+		return -ENOMEM;
+
+	rc = of_property_read_u32(of_node, "qcom,gpio-vana", &val);
+	if (rc != -EINVAL) {
+		if (rc < 0) {
+			pr_err("%s:%d read qcom,gpio-vana failed rc %d\n",
+				__func__, __LINE__, rc);
+			goto free_gpio_info;
+		} else if (val >= gpio_array_size) {
+			pr_err("%s:%d qcom,gpio-vana invalid %d\n",
+				__func__, __LINE__, val);
+			rc = -EINVAL;
+			goto free_gpio_info;
+		}
+		gconf->gpio_num_info->gpio_num[SENSOR_VANA] =
+			gpio_array[val];
+		gconf->gpio_num_info->valid[SENSOR_VANA] = 1;
+		CDBG("%s qcom,gpio-vana %d\n", __func__,
+			gconf->gpio_num_info->gpio_num[SENSOR_VANA]);
+	}
+
+	rc = of_property_read_u32(of_node, "qcom,gpio-vio", &val);
+	if (rc != -EINVAL) {
+		if (rc < 0) {
+			pr_err("%s:%d read qcom,gpio-vio failed rc %d\n",
+				__func__, __LINE__, rc);
+			goto free_gpio_info;
+		} else if (val >= gpio_array_size) {
+			pr_err("%s:%d qcom,gpio-vio invalid %d\n",
+				__func__, __LINE__, val);
+			goto free_gpio_info;
+		}
+		gconf->gpio_num_info->gpio_num[SENSOR_VIO] =
+			gpio_array[val];
+		gconf->gpio_num_info->valid[SENSOR_VIO] = 1;
+		CDBG("%s qcom,gpio-vio %d\n", __func__,
+			gconf->gpio_num_info->gpio_num[SENSOR_VIO]);
+	}
+
+	rc = of_property_read_u32(of_node, "qcom,gpio-vaf", &val);
+	if (rc != -EINVAL) {
+		if (rc < 0) {
+			pr_err("%s:%d read qcom,gpio-vaf failed rc %d\n",
+				__func__, __LINE__, rc);
+			goto free_gpio_info;
+		} else if (val >= gpio_array_size) {
+			pr_err("%s:%d qcom,gpio-vaf invalid %d\n",
+				__func__, __LINE__, val);
+			rc = -EINVAL;
+			goto free_gpio_info;
+		}
+		gconf->gpio_num_info->gpio_num[SENSOR_VAF] =
+			gpio_array[val];
+		gconf->gpio_num_info->valid[SENSOR_VAF] = 1;
+		CDBG("%s qcom,gpio-vaf %d\n", __func__,
+			gconf->gpio_num_info->gpio_num[SENSOR_VAF]);
+	}
+
+	rc = of_property_read_u32(of_node, "qcom,gpio-vdig", &val);
+	if (rc != -EINVAL) {
+		if (rc < 0) {
+			pr_err("%s:%d read qcom,gpio-vdig failed rc %d\n",
+				__func__, __LINE__, rc);
+			goto free_gpio_info;
+		} else if (val >= gpio_array_size) {
+			pr_err("%s:%d qcom,gpio-vdig invalid %d\n",
+				__func__, __LINE__, val);
+			rc = -EINVAL;
+			goto free_gpio_info;
+		}
+		gconf->gpio_num_info->gpio_num[SENSOR_VDIG] =
+			gpio_array[val];
+		gconf->gpio_num_info->valid[SENSOR_VDIG] = 1;
+		CDBG("%s qcom,gpio-vdig %d\n", __func__,
+			gconf->gpio_num_info->gpio_num[SENSOR_VDIG]);
+	}
+
+	rc = of_property_read_u32(of_node, "qcom,gpio-reset", &val);
+	if (rc != -EINVAL) {
+		if (rc < 0) {
+			pr_err("%s:%d read qcom,gpio-reset failed rc %d\n",
+				__func__, __LINE__, rc);
+			goto free_gpio_info;
+		} else if (val >= gpio_array_size) {
+			pr_err("%s:%d qcom,gpio-reset invalid %d\n",
+				__func__, __LINE__, val);
+			rc = -EINVAL;
+			goto free_gpio_info;
+		}
+		gconf->gpio_num_info->gpio_num[SENSOR_RESET] =
+			gpio_array[val];
+		gconf->gpio_num_info->valid[SENSOR_RESET] = 1;
+		CDBG("%s qcom,gpio-reset %d\n", __func__,
+			gconf->gpio_num_info->gpio_num[SENSOR_RESET]);
+	}
+
+	rc = of_property_read_u32(of_node, "qcom,gpio-standby", &val);
+	if (rc != -EINVAL) {
+		if (rc < 0) {
+			pr_err("%s:%d read qcom,gpio-standby failed rc %d\n",
+				__func__, __LINE__, rc);
+			goto free_gpio_info;
+		} else if (val >= gpio_array_size) {
+			pr_err("%s:%d qcom,gpio-standby invalid %d\n",
+				__func__, __LINE__, val);
+			rc = -EINVAL;
+			goto free_gpio_info;
+		}
+		gconf->gpio_num_info->gpio_num[SENSOR_STANDBY] =
+			gpio_array[val];
+		gconf->gpio_num_info->valid[SENSOR_STANDBY] = 1;
+		CDBG("%s qcom,gpio-standby %d\n", __func__,
+			gconf->gpio_num_info->gpio_num[SENSOR_STANDBY]);
+	}
+
+	rc = of_property_read_u32(of_node, "qcom,gpio-af-pwdm", &val);
+	if (rc != -EINVAL) {
+		if (rc < 0) {
+			pr_err("%s:%d read qcom,gpio-af-pwdm failed rc %d\n",
+				__func__, __LINE__, rc);
+			goto free_gpio_info;
+		} else if (val >= gpio_array_size) {
+			pr_err("%s:%d qcom,gpio-af-pwdm invalid %d\n",
+				__func__, __LINE__, val);
+			rc = -EINVAL;
+			goto free_gpio_info;
+		}
+		gconf->gpio_num_info->gpio_num[SENSOR_VAF_PWDM] =
+			gpio_array[val];
+		gconf->gpio_num_info->valid[SENSOR_VAF_PWDM] = 1;
+		CDBG("%s qcom,gpio-af-pwdm %d\n", __func__,
+			gconf->gpio_num_info->gpio_num[SENSOR_VAF_PWDM]);
+	}
+
+	rc = of_property_read_u32(of_node, "qcom,gpio-custom1", &val);
+	if (rc != -EINVAL) {
+		if (rc < 0) {
+			pr_err("%s:%d read qcom,gpio-custom1 failed rc %d\n",
+				__func__, __LINE__, rc);
+			goto free_gpio_info;
+		} else if (val >= gpio_array_size) {
+			pr_err("%s:%d qcom,gpio-custom1 invalid %d\n",
+				__func__, __LINE__, val);
+			rc = -EINVAL;
+			goto free_gpio_info;
+		}
+		gconf->gpio_num_info->gpio_num[SENSOR_CUSTOM_GPIO1] =
+			gpio_array[val];
+		gconf->gpio_num_info->valid[SENSOR_CUSTOM_GPIO1] = 1;
+		CDBG("%s qcom,gpio-custom1 %d\n", __func__,
+			gconf->gpio_num_info->gpio_num[SENSOR_CUSTOM_GPIO1]);
+	}
+
+	rc = of_property_read_u32(of_node, "qcom,gpio-custom2", &val);
+	if (rc != -EINVAL) {
+		if (rc < 0) {
+			pr_err("%s:%d read qcom,gpio-custom2 failed rc %d\n",
+				__func__, __LINE__, rc);
+			goto free_gpio_info;
+		} else if (val >= gpio_array_size) {
+			pr_err("%s:%d qcom,gpio-custom2 invalid %d\n",
+				__func__, __LINE__, val);
+			rc = -EINVAL;
+			goto free_gpio_info;
+		}
+		gconf->gpio_num_info->gpio_num[SENSOR_CUSTOM_GPIO2] =
+			gpio_array[val];
+		gconf->gpio_num_info->valid[SENSOR_CUSTOM_GPIO2] = 1;
+		CDBG("%s qcom,gpio-custom2 %d\n", __func__,
+			gconf->gpio_num_info->gpio_num[SENSOR_CUSTOM_GPIO2]);
+	} else {
+		rc = 0;
+	}
+
+	return rc;
+
+free_gpio_info:
+	kfree(gconf->gpio_num_info);
+	gconf->gpio_num_info = NULL;
+	return rc;
+}
+
+int cam_sensor_get_dt_vreg_data(struct device_node *of_node,
+	struct camera_vreg_t **cam_vreg, int *num_vreg)
+{
+	int rc = 0, i = 0;
+	int32_t count = 0;
+	uint32_t *vreg_array = NULL;
+	struct camera_vreg_t *vreg = NULL;
+
+	count = of_property_count_strings(of_node, "qcom,cam-vreg-name");
+	CDBG("%s qcom,cam-vreg-name count %d\n", __func__, count);
+
+	if (!count || (count == -EINVAL)) {
+		pr_err("%s:%d number of entries is 0 or not present in dts\n",
+			__func__, __LINE__);
+		*num_vreg = 0;
+		return 0;
+	}
+
+	vreg = kcalloc(count, sizeof(*vreg), GFP_KERNEL);
+	if (!vreg)
+		return -ENOMEM;
+
+	*cam_vreg = vreg;
+	*num_vreg = count;
+	for (i = 0; i < count; i++) {
+		rc = of_property_read_string_index(of_node,
+			"qcom,cam-vreg-name", i,
+			&vreg[i].reg_name);
+		CDBG("%s reg_name[%d] = %s\n", __func__, i,
+			vreg[i].reg_name);
+		if (rc < 0) {
+			pr_err("%s failed %d\n", __func__, __LINE__);
+			goto free_vreg;
+		}
+	}
+
+	vreg_array = kcalloc(count, sizeof(uint32_t), GFP_KERNEL);
+	if (!vreg_array) {
+		rc = -ENOMEM;
+		goto free_vreg;
+	}
+
+	for (i = 0; i < count; i++)
+		vreg[i].type = VREG_TYPE_DEFAULT;
+
+	rc = of_property_read_u32_array(of_node, "qcom,cam-vreg-type",
+		vreg_array, count);
+	if (rc != -EINVAL) {
+		if (rc < 0) {
+			pr_err("%s failed %d\n", __func__, __LINE__);
+			goto free_vreg_array;
+		} else {
+			for (i = 0; i < count; i++) {
+				vreg[i].type = vreg_array[i];
+				CDBG("%s cam_vreg[%d].type = %d\n",
+					__func__, i, vreg[i].type);
+			}
+		}
+	} else {
+		CDBG("%s:%d no qcom,cam-vreg-type entries in dts\n",
+			__func__, __LINE__);
+		rc = 0;
+	}
+
+	rc = of_property_read_u32_array(of_node, "qcom,cam-vreg-min-voltage",
+		vreg_array, count);
+	if (rc != -EINVAL) {
+		if (rc < 0) {
+			pr_err("%s failed %d\n", __func__, __LINE__);
+			goto free_vreg_array;
+		} else {
+			for (i = 0; i < count; i++) {
+				vreg[i].min_voltage = vreg_array[i];
+				CDBG("%s cam_vreg[%d].min_voltage = %d\n",
+					__func__, i, vreg[i].min_voltage);
+			}
+		}
+	} else {
+		CDBG("%s:%d no qcom,cam-vreg-min-voltage entries in dts\n",
+			__func__, __LINE__);
+		rc = 0;
+	}
+
+	rc = of_property_read_u32_array(of_node, "qcom,cam-vreg-max-voltage",
+		vreg_array, count);
+	if (rc != -EINVAL) {
+		if (rc < 0) {
+			pr_err("%s failed %d\n", __func__, __LINE__);
+			goto free_vreg_array;
+		} else {
+			for (i = 0; i < count; i++) {
+				vreg[i].max_voltage = vreg_array[i];
+				CDBG("%s cam_vreg[%d].max_voltage = %d\n",
+					__func__, i, vreg[i].max_voltage);
+			}
+		}
+	} else {
+		CDBG("%s:%d no qcom,cam-vreg-max-voltage entries in dts\n",
+			__func__, __LINE__);
+		rc = 0;
+	}
+
+	rc = of_property_read_u32_array(of_node, "qcom,cam-vreg-op-mode",
+		vreg_array, count);
+	if (rc != -EINVAL) {
+		if (rc < 0) {
+			pr_err("%s failed %d\n", __func__, __LINE__);
+			goto free_vreg_array;
+		} else {
+			for (i = 0; i < count; i++) {
+				vreg[i].op_mode = vreg_array[i];
+				CDBG("%s cam_vreg[%d].op_mode = %d\n",
+					__func__, i, vreg[i].op_mode);
+			}
+		}
+	} else {
+		CDBG("%s:%d no qcom,cam-vreg-op-mode entries in dts\n",
+			__func__, __LINE__);
+		rc = 0;
+	}
+
+	kfree(vreg_array);
+
+	return rc;
+
+free_vreg_array:
+	kfree(vreg_array);
+free_vreg:
+	kfree(vreg);
+	*num_vreg = 0;
+
+	return rc;
+}
+
+int msm_camera_pinctrl_init(
+	struct msm_pinctrl_info *sensor_pctrl, struct device *dev) {
+
+	sensor_pctrl->pinctrl = devm_pinctrl_get(dev);
+	if (IS_ERR_OR_NULL(sensor_pctrl->pinctrl)) {
+		pr_err("%s:%d Getting pinctrl handle failed\n",
+			__func__, __LINE__);
+		return -EINVAL;
+	}
+	sensor_pctrl->gpio_state_active =
+		pinctrl_lookup_state(sensor_pctrl->pinctrl,
+				CAM_SENSOR_PINCTRL_STATE_DEFAULT);
+	if (IS_ERR_OR_NULL(sensor_pctrl->gpio_state_active)) {
+		pr_err("%s:%d Failed to get the active state pinctrl handle\n",
+			__func__, __LINE__);
+		return -EINVAL;
+	}
+	sensor_pctrl->gpio_state_suspend
+		= pinctrl_lookup_state(sensor_pctrl->pinctrl,
+				CAM_SENSOR_PINCTRL_STATE_SLEEP);
+	if (IS_ERR_OR_NULL(sensor_pctrl->gpio_state_suspend)) {
+		pr_err("%s:%d Failed to get the suspend state pinctrl handle\n",
+				__func__, __LINE__);
+		return -EINVAL;
+	}
+	return 0;
+}
+
+int msm_cam_sensor_handle_reg_gpio(int seq_type,
+	struct msm_camera_gpio_conf *gconf, int val)
+{
+
+	int gpio_offset = -1;
+
+	if (!gconf) {
+		pr_err("ERR:%s: Input Parameters are not proper\n", __func__);
+		return -EINVAL;
+	}
+	CDBG("%s: %d Seq type: %d, config: %d", __func__, __LINE__,
+		seq_type, val);
+
+	gpio_offset = seq_type;
+
+	if ((gconf->gpio_num_info->valid[gpio_offset] == 1)) {
+		CDBG("%s: %d VALID GPIO offset: %d, seqtype: %d\n",
+			__func__, __LINE__,	gpio_offset, seq_type);
+		gpio_set_value_cansleep(
+			gconf->gpio_num_info->gpio_num
+			[gpio_offset], val);
+	}
+
+	return 0;
+}
+
+int32_t msm_sensor_driver_get_gpio_data(
+	struct msm_camera_gpio_conf **gpio_conf,
+	struct device_node *of_node)
+{
+	int32_t                      rc = 0, i = 0;
+	uint16_t                    *gpio_array = NULL;
+	int16_t                     gpio_array_size = 0;
+	struct msm_camera_gpio_conf *gconf = NULL;
+
+	/* Validate input parameters */
+	if (!of_node) {
+		pr_err("failed: invalid param of_node %pK", of_node);
+		return -EINVAL;
+	}
+
+	gpio_array_size = of_gpio_count(of_node);
+	CDBG("gpio count %d\n", gpio_array_size);
+	if (gpio_array_size <= 0)
+		return 0;
+
+	gconf = kzalloc(sizeof(*gconf), GFP_KERNEL);
+	if (!gconf)
+		return -ENOMEM;
+
+	*gpio_conf = gconf;
+
+	gpio_array = kcalloc(gpio_array_size, sizeof(uint16_t), GFP_KERNEL);
+	if (!gpio_array)
+		goto free_gpio_conf;
+
+	for (i = 0; i < gpio_array_size; i++) {
+		gpio_array[i] = of_get_gpio(of_node, i);
+		CDBG("gpio_array[%d] = %d", i, gpio_array[i]);
+	}
+	rc = msm_camera_get_dt_gpio_req_tbl(of_node, gconf, gpio_array,
+		gpio_array_size);
+	if (rc < 0) {
+		pr_err("failed in msm_camera_get_dt_gpio_req_tbl\n");
+		goto free_gpio_array;
+	}
+
+	rc = msm_camera_init_gpio_pin_tbl(of_node, gconf, gpio_array,
+		gpio_array_size);
+	if (rc < 0) {
+		pr_err("failed in msm_camera_init_gpio_pin_tbl\n");
+		goto free_gpio_req_tbl;
+	}
+	kfree(gpio_array);
+
+	return rc;
+
+free_gpio_req_tbl:
+	kfree(gconf->cam_gpio_req_tbl);
+free_gpio_array:
+	kfree(gpio_array);
+free_gpio_conf:
+	kfree(gconf);
+	*gpio_conf = NULL;
+
+	return rc;
+}
+
+int cam_sensor_core_power_up(struct cam_sensor_power_ctrl_t *ctrl)
+{
+	int rc = 0, index = 0, no_gpio = 0, ret = 0, num_vreg, j = 0;
+	struct cam_sensor_power_setting *power_setting = NULL;
+	struct camera_vreg_t *cam_vreg;
+
+	CDBG("%s:%d\n", __func__, __LINE__);
+	if (!ctrl) {
+		pr_err("failed ctrl %pK\n", ctrl);
+		return -EINVAL;
+	}
+
+	cam_vreg = ctrl->cam_vreg;
+	num_vreg = ctrl->num_vreg;
+
+	if (ctrl->gpio_conf->cam_gpiomux_conf_tbl != NULL)
+		CDBG("%s:%d mux install\n", __func__, __LINE__);
+
+	ret = msm_camera_pinctrl_init(&(ctrl->pinctrl_info), ctrl->dev);
+	if (ret < 0) {
+		pr_err("%s:%d Initialization of pinctrl failed\n",
+				__func__, __LINE__);
+		ctrl->cam_pinctrl_status = 0;
+	} else {
+		ctrl->cam_pinctrl_status = 1;
+	}
+	rc = msm_camera_request_gpio_table(
+		ctrl->gpio_conf->cam_gpio_req_tbl,
+		ctrl->gpio_conf->cam_gpio_req_tbl_size, 1);
+	if (rc < 0)
+		no_gpio = rc;
+	if (ctrl->cam_pinctrl_status) {
+		ret = pinctrl_select_state(ctrl->pinctrl_info.pinctrl,
+			ctrl->pinctrl_info.gpio_state_active);
+		if (ret)
+			pr_err("%s:%d cannot set pin to active state",
+				__func__, __LINE__);
+	}
+
+	for (index = 0; index < ctrl->power_setting_size; index++) {
+		CDBG("%s index %d\n", __func__, index);
+		power_setting = &ctrl->power_setting[index];
+
+		switch (power_setting->seq_type) {
+		case SENSOR_MCLK:
+			if (power_setting->seq_val >= ctrl->clk_info_size) {
+				pr_err("%s:%d :Error: clk index %d >= max %zu\n",
+					__func__, __LINE__,
+					power_setting->seq_val,
+					ctrl->clk_info_size);
+				goto power_up_failed;
+			}
+			for (j = 0; j < num_vreg; j++) {
+				if (!strcmp(cam_vreg[j].reg_name,
+					"cam_clk")) {
+					CDBG("%s:%d Enable cam_clk: %d\n",
+						__func__, __LINE__, j);
+					msm_camera_config_single_vreg(ctrl->dev,
+						&cam_vreg[j],
+						(struct regulator **)
+						&power_setting->data[0],
+						1);
+				}
+			}
+			if (power_setting->config_val)
+				ctrl->clk_info[power_setting->seq_val].
+					clk_rate = power_setting->config_val;
+			rc = msm_camera_clk_enable(ctrl->dev,
+				ctrl->clk_info, ctrl->clk_ptr,
+				ctrl->clk_info_size, true);
+			if (rc < 0) {
+				pr_err("%s: clk enable failed\n", __func__);
+				goto power_up_failed;
+			}
+			break;
+		case SENSOR_RESET:
+		case SENSOR_STANDBY:
+		case SENSOR_CUSTOM_GPIO1:
+		case SENSOR_CUSTOM_GPIO2:
+			if (no_gpio) {
+				pr_err("%s: request gpio failed\n", __func__);
+				return no_gpio;
+			}
+			if (power_setting->seq_val >= CAM_VREG_MAX ||
+				!ctrl->gpio_conf->gpio_num_info) {
+				pr_err("%s gpio index %d >= max %d\n", __func__,
+					power_setting->seq_val,
+					CAM_VREG_MAX);
+				goto power_up_failed;
+			}
+			CDBG("%s:%d gpio set val %d\n",
+				__func__, __LINE__,
+				ctrl->gpio_conf->gpio_num_info->gpio_num
+				[power_setting->seq_val]);
+
+			rc = msm_cam_sensor_handle_reg_gpio(
+				power_setting->seq_type,
+				ctrl->gpio_conf, 1);
+			if (rc < 0) {
+				pr_err("ERR:%s Error in handling VREG GPIO\n",
+					__func__);
+				goto power_up_failed;
+			}
+			break;
+		case SENSOR_VANA:
+		case SENSOR_VDIG:
+		case SENSOR_VIO:
+		case SENSOR_VAF:
+		case SENSOR_VAF_PWDM:
+		case SENSOR_CUSTOM_REG1:
+		case SENSOR_CUSTOM_REG2:
+			if (power_setting->seq_val == INVALID_VREG)
+				break;
+
+			if (power_setting->seq_val >= CAM_VREG_MAX) {
+				pr_err("%s vreg index %d >= max %d\n", __func__,
+					power_setting->seq_val,
+					CAM_VREG_MAX);
+				goto power_up_failed;
+			}
+			if (power_setting->seq_val < ctrl->num_vreg)
+				msm_camera_config_single_vreg(ctrl->dev,
+					&ctrl->cam_vreg
+					[power_setting->seq_val],
+					(struct regulator **)
+					&power_setting->data[0],
+					1);
+			else
+				pr_err("%s: %d usr_idx:%d dts_idx:%d\n",
+					__func__, __LINE__,
+					power_setting->seq_val, ctrl->num_vreg);
+
+			rc = msm_cam_sensor_handle_reg_gpio(
+				power_setting->seq_type,
+				ctrl->gpio_conf, 1);
+			if (rc < 0) {
+				pr_err("ERR:%s Error in handling VREG GPIO\n",
+					__func__);
+				goto power_up_failed;
+			}
+			break;
+		default:
+			pr_err("%s error power seq type %d\n", __func__,
+				power_setting->seq_type);
+			break;
+		}
+		if (power_setting->delay > 20)
+			msleep(power_setting->delay);
+		else if (power_setting->delay)
+			usleep_range(power_setting->delay * 1000,
+				(power_setting->delay * 1000) + 1000);
+	}
+
+	return 0;
+power_up_failed:
+	pr_err("%s:%d failed\n", __func__, __LINE__);
+	for (index--; index >= 0; index--) {
+		CDBG("%s index %d\n", __func__, index);
+		power_setting = &ctrl->power_setting[index];
+		CDBG("%s type %d\n", __func__, power_setting->seq_type);
+		switch (power_setting->seq_type) {
+		case SENSOR_RESET:
+		case SENSOR_STANDBY:
+		case SENSOR_CUSTOM_GPIO1:
+		case SENSOR_CUSTOM_GPIO2:
+			if (!ctrl->gpio_conf->gpio_num_info)
+				continue;
+			if (!ctrl->gpio_conf->gpio_num_info->valid
+				[power_setting->seq_val])
+				continue;
+			gpio_set_value_cansleep(
+				ctrl->gpio_conf->gpio_num_info->gpio_num
+				[power_setting->seq_val], GPIOF_OUT_INIT_LOW);
+			break;
+		case SENSOR_VANA:
+		case SENSOR_VDIG:
+		case SENSOR_VIO:
+		case SENSOR_VAF:
+		case SENSOR_VAF_PWDM:
+		case SENSOR_CUSTOM_REG1:
+		case SENSOR_CUSTOM_REG2:
+			if (power_setting->seq_val < ctrl->num_vreg)
+				msm_camera_config_single_vreg(ctrl->dev,
+					&ctrl->cam_vreg
+					[power_setting->seq_val],
+					(struct regulator **)
+					&power_setting->data[0],
+					0);
+			else
+				pr_err("%s:%d:seq_val: %d > num_vreg: %d\n",
+					__func__, __LINE__,
+					power_setting->seq_val, ctrl->num_vreg);
+
+			msm_cam_sensor_handle_reg_gpio(power_setting->seq_type,
+				ctrl->gpio_conf, GPIOF_OUT_INIT_LOW);
+			break;
+		default:
+			pr_err("%s error power seq type %d\n", __func__,
+				power_setting->seq_type);
+			break;
+		}
+		if (power_setting->delay > 20) {
+			msleep(power_setting->delay);
+		} else if (power_setting->delay) {
+			usleep_range(power_setting->delay * 1000,
+				(power_setting->delay * 1000) + 1000);
+		}
+	}
+	if (ctrl->cam_pinctrl_status) {
+		ret = pinctrl_select_state(ctrl->pinctrl_info.pinctrl,
+				ctrl->pinctrl_info.gpio_state_suspend);
+		if (ret)
+			pr_err("%s:%d cannot set pin to suspend state\n",
+				__func__, __LINE__);
+		devm_pinctrl_put(ctrl->pinctrl_info.pinctrl);
+	}
+	ctrl->cam_pinctrl_status = 0;
+	msm_camera_request_gpio_table(
+		ctrl->gpio_conf->cam_gpio_req_tbl,
+		ctrl->gpio_conf->cam_gpio_req_tbl_size, 0);
+
+	return rc;
+}
+
+static struct cam_sensor_power_setting*
+msm_camera_get_power_settings(struct cam_sensor_power_ctrl_t *ctrl,
+				enum msm_camera_power_seq_type seq_type,
+				uint16_t seq_val)
+{
+	struct cam_sensor_power_setting *power_setting, *ps = NULL;
+	int idx;
+
+	for (idx = 0; idx < ctrl->power_setting_size; idx++) {
+		power_setting = &ctrl->power_setting[idx];
+		if (power_setting->seq_type == seq_type &&
+			power_setting->seq_val ==  seq_val) {
+			ps = power_setting;
+			return ps;
+		}
+
+	}
+
+	return ps;
+}
+
+static int cam_config_mclk_reg(struct cam_sensor_power_ctrl_t *ctrl,
+	int32_t index)
+{
+	struct camera_vreg_t *cam_vreg;
+	int32_t num_vreg = 0, j = 0, rc = 0, idx = 0;
+	struct cam_sensor_power_setting *ps = NULL;
+	struct cam_sensor_power_setting *pd = NULL;
+
+	cam_vreg = ctrl->cam_vreg;
+	num_vreg = ctrl->num_vreg;
+	pd = &ctrl->power_down_setting[index];
+
+	for (j = 0; j < num_vreg; j++) {
+		if (!strcmp(cam_vreg[j].reg_name, "cam_clk")) {
+
+			ps = NULL;
+			for (idx = 0; idx <
+				ctrl->power_setting_size; idx++) {
+				if (ctrl->power_setting[idx].
+					seq_type == pd->seq_type) {
+					ps = &ctrl->power_setting[idx];
+					break;
+				}
+			}
+
+			if (ps != NULL)
+				msm_camera_config_single_vreg(
+					ctrl->dev,
+					&cam_vreg[j],
+					(struct regulator **)
+					&ps->data[0], 0);
+		}
+	}
+
+	return rc;
+}
+
+int msm_camera_power_down(struct cam_sensor_power_ctrl_t *ctrl)
+{
+	int index = 0, ret = 0, num_vreg = 0;
+	struct cam_sensor_power_setting *pd = NULL;
+	struct cam_sensor_power_setting *ps;
+	struct camera_vreg_t *cam_vreg;
+
+	CDBG("%s:%d\n", __func__, __LINE__);
+	if (!ctrl) {
+		pr_err("failed ctrl %pK\n", ctrl);
+		return -EINVAL;
+	}
+
+	cam_vreg = ctrl->cam_vreg;
+	num_vreg = ctrl->num_vreg;
+
+	for (index = 0; index < ctrl->power_down_setting_size; index++) {
+		CDBG("%s index %d\n", __func__, index);
+		pd = &ctrl->power_down_setting[index];
+		ps = NULL;
+		CDBG("%s type %d\n", __func__, pd->seq_type);
+		switch (pd->seq_type) {
+		case SENSOR_MCLK:
+			ret = cam_config_mclk_reg(ctrl, index);
+			if (ret < 0) {
+				pr_err("%s:%d :Error: in config clk reg\n",
+					__func__, __LINE__);
+				return ret;
+			}
+			msm_camera_clk_enable(ctrl->dev,
+				ctrl->clk_info, ctrl->clk_ptr,
+				ctrl->clk_info_size, false);
+			break;
+		case SENSOR_RESET:
+		case SENSOR_STANDBY:
+		case SENSOR_CUSTOM_GPIO1:
+		case SENSOR_CUSTOM_GPIO2:
+			if (!ctrl->gpio_conf->gpio_num_info->valid
+				[pd->seq_val])
+				continue;
+			gpio_set_value_cansleep(
+				ctrl->gpio_conf->gpio_num_info->gpio_num
+				[pd->seq_val],
+				(int) pd->config_val);
+			break;
+		case SENSOR_VANA:
+		case SENSOR_VDIG:
+		case SENSOR_VIO:
+		case SENSOR_VAF:
+		case SENSOR_VAF_PWDM:
+		case SENSOR_CUSTOM_REG1:
+		case SENSOR_CUSTOM_REG2:
+			if (pd->seq_val == INVALID_VREG)
+				break;
+			ps = msm_camera_get_power_settings(
+				ctrl, pd->seq_type,
+				pd->seq_val);
+			if (ps) {
+				if (pd->seq_val < ctrl->num_vreg)
+					msm_camera_config_single_vreg(ctrl->dev,
+						&ctrl->cam_vreg
+						[pd->seq_val],
+						(struct regulator **)
+						&ps->data[0],
+						0);
+				else
+					pr_err("%s:%d:seq_val:%d > num_vreg: %d\n",
+						__func__, __LINE__, pd->seq_val,
+						ctrl->num_vreg);
+			} else
+				pr_err("%s error in power up/down seq data\n",
+								__func__);
+			ret = msm_cam_sensor_handle_reg_gpio(pd->seq_type,
+				ctrl->gpio_conf, GPIOF_OUT_INIT_LOW);
+			if (ret < 0)
+				pr_err("ERR:%s Error while disabling VREG GPIO\n",
+					__func__);
+			break;
+		default:
+			pr_err("%s error power seq type %d\n", __func__,
+				pd->seq_type);
+			break;
+		}
+		if (pd->delay > 20)
+			msleep(pd->delay);
+		else if (pd->delay)
+			usleep_range(pd->delay * 1000,
+				(pd->delay * 1000) + 1000);
+	}
+
+	if (ctrl->cam_pinctrl_status) {
+		ret = pinctrl_select_state(ctrl->pinctrl_info.pinctrl,
+				ctrl->pinctrl_info.gpio_state_suspend);
+		if (ret)
+			pr_err("%s:%d cannot set pin to suspend state",
+				__func__, __LINE__);
+		devm_pinctrl_put(ctrl->pinctrl_info.pinctrl);
+	}
+
+	ctrl->cam_pinctrl_status = 0;
+	msm_camera_request_gpio_table(
+		ctrl->gpio_conf->cam_gpio_req_tbl,
+		ctrl->gpio_conf->cam_gpio_req_tbl_size, 0);
+
+	return 0;
+}
+
diff --git a/drivers/media/platform/msm/camera/cam_sensor_module/cam_sensor_utils/cam_sensor_util.h b/drivers/media/platform/msm/camera/cam_sensor_module/cam_sensor_utils/cam_sensor_util.h
new file mode 100644
index 0000000..7e7fc35
--- /dev/null
+++ b/drivers/media/platform/msm/camera/cam_sensor_module/cam_sensor_utils/cam_sensor_util.h
@@ -0,0 +1,62 @@
+/* Copyright (c) 2017, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#ifndef _CAM_SENSOR_UTIL_H_
+#define _CAM_SENSOR_UTIL_H_
+
+#include <linux/kernel.h>
+#include <linux/regulator/consumer.h>
+#include <linux/gpio.h>
+#include <linux/of_gpio.h>
+#include <linux/of.h>
+#include <cam_sensor_cmn_header.h>
+#include <cam_req_mgr_util.h>
+#include <cam_req_mgr_interface.h>
+#include <cam_mem_mgr.h>
+
+#define INVALID_VREG 100
+
+int msm_camera_get_dt_power_setting_data(struct device_node *of_node,
+	struct camera_vreg_t *cam_vreg, int num_vreg,
+	struct cam_sensor_power_ctrl_t *power_info);
+
+int msm_camera_get_dt_gpio_req_tbl(struct device_node *of_node,
+	struct msm_camera_gpio_conf *gconf, uint16_t *gpio_array,
+	uint16_t gpio_array_size);
+
+int msm_camera_init_gpio_pin_tbl(struct device_node *of_node,
+	struct msm_camera_gpio_conf *gconf, uint16_t *gpio_array,
+	uint16_t gpio_array_size);
+
+int cam_sensor_get_dt_vreg_data(struct device_node *of_node,
+	struct camera_vreg_t **cam_vreg, int *num_vreg);
+
+int cam_sensor_core_power_up(struct cam_sensor_power_ctrl_t *ctrl);
+
+int msm_camera_power_down(struct cam_sensor_power_ctrl_t *ctrl);
+
+int msm_camera_fill_vreg_params(struct camera_vreg_t *cam_vreg,
+	int num_vreg, struct cam_sensor_power_setting *power_setting,
+	uint16_t power_setting_size);
+
+int msm_camera_pinctrl_init
+	(struct msm_pinctrl_info *sensor_pctrl, struct device *dev);
+
+int32_t msm_sensor_driver_get_gpio_data(
+	struct msm_camera_gpio_conf **gpio_conf,
+	struct device_node *of_node);
+
+int cam_sensor_i2c_pkt_parser(struct i2c_settings_array *i2c_reg_settings,
+	struct cam_cmd_buf_desc *cmd_desc, int32_t num_cmd_buffers);
+
+int32_t delete_request(struct i2c_settings_array *i2c_array);
+#endif /* _CAM_SENSOR_UTIL_H_ */