Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 2f4b990a authored by Viswanadha Raju Thotakura's avatar Viswanadha Raju Thotakura Committed by Gerrit - the friendly Code Review server
Browse files

msm: camera: Add support to enable eLDOs through GPIOs



Add support to control/enable external regulators through GPIOs.

CRs-Fixed: 974739
Change-Id: I18f1ce72dfe93da2fdb80725ed66218eb0af2f49
Signed-off-by: default avatarViswanadha Raju Thotakura <viswanad@codeaurora.org>
parent ee833ce5
Loading
Loading
Loading
Loading
+81 −1
Original line number Diff line number Diff line
@@ -1022,7 +1022,7 @@ static int32_t msm_actuator_vreg_control(struct msm_actuator_ctrl_t *a_ctrl,
	if (!cnt)
		return 0;

	if (cnt >= MSM_ACTUATOT_MAX_VREGS) {
	if (cnt >= MSM_ACTUATOR_MAX_VREGS) {
		pr_err("%s failed %d cnt %d\n", __func__, __LINE__, cnt);
		return -EINVAL;
	}
@@ -1048,6 +1048,8 @@ static int32_t msm_actuator_vreg_control(struct msm_actuator_ctrl_t *a_ctrl,
static int32_t msm_actuator_power_down(struct msm_actuator_ctrl_t *a_ctrl)
{
	int32_t rc = 0;
	enum msm_sensor_power_seq_gpio_t gpio;

	CDBG("Enter\n");
	if (a_ctrl->actuator_state != ACT_DISABLE_STATE) {

@@ -1064,6 +1066,41 @@ static int32_t msm_actuator_power_down(struct msm_actuator_ctrl_t *a_ctrl)
			return rc;
		}

		for (gpio = SENSOR_GPIO_AF_PWDM;
			gpio < SENSOR_GPIO_MAX; gpio++) {
			if (a_ctrl->gconf &&
				a_ctrl->gconf->gpio_num_info &&
				a_ctrl->gconf->gpio_num_info->
					valid[gpio] == 1) {

				gpio_set_value_cansleep(
					a_ctrl->gconf->gpio_num_info->
						gpio_num[gpio],
					GPIOF_OUT_INIT_LOW);

				if (a_ctrl->cam_pinctrl_status) {
					rc = pinctrl_select_state(
						a_ctrl->pinctrl_info.pinctrl,
						a_ctrl->pinctrl_info.
							gpio_state_suspend);
					if (rc < 0)
						pr_err("ERR:%s:%d cannot set pin to suspend state: %d",
							__func__, __LINE__, rc);

					devm_pinctrl_put(
						a_ctrl->pinctrl_info.pinctrl);
				}
				a_ctrl->cam_pinctrl_status = 0;
				rc = msm_camera_request_gpio_table(
					a_ctrl->gconf->cam_gpio_req_tbl,
					a_ctrl->gconf->cam_gpio_req_tbl_size,
					0);
				if (rc < 0)
					pr_err("ERR:%s:Failed in selecting state in actuator power down: %d\n",
						__func__, rc);
			}
		}

		kfree(a_ctrl->step_position_table);
		a_ctrl->step_position_table = NULL;
		kfree(a_ctrl->i2c_reg_tbl);
@@ -1657,6 +1694,8 @@ static long msm_actuator_subdev_fops_ioctl(struct file *file, unsigned int cmd,
static int32_t msm_actuator_power_up(struct msm_actuator_ctrl_t *a_ctrl)
{
	int rc = 0;
	enum msm_sensor_power_seq_gpio_t gpio;

	CDBG("%s called\n", __func__);

	rc = msm_actuator_vreg_control(a_ctrl, 1);
@@ -1665,6 +1704,33 @@ static int32_t msm_actuator_power_up(struct msm_actuator_ctrl_t *a_ctrl)
		return rc;
	}

	for (gpio = SENSOR_GPIO_AF_PWDM; gpio < SENSOR_GPIO_MAX; gpio++) {
		if (a_ctrl->gconf &&
			a_ctrl->gconf->gpio_num_info &&
			a_ctrl->gconf->gpio_num_info->valid[gpio] == 1) {
			rc = msm_camera_request_gpio_table(
				a_ctrl->gconf->cam_gpio_req_tbl,
				a_ctrl->gconf->cam_gpio_req_tbl_size, 1);
			if (rc < 0) {
				pr_err("ERR:%s:Failed in selecting state for actuator: %d\n",
					__func__, rc);
				return rc;
			}
			if (a_ctrl->cam_pinctrl_status) {
				rc = pinctrl_select_state(
					a_ctrl->pinctrl_info.pinctrl,
					a_ctrl->pinctrl_info.gpio_state_active);
				if (rc < 0)
					pr_err("ERR:%s:%d cannot set pin to active state: %d",
						__func__, __LINE__, rc);
			}

			gpio_set_value_cansleep(
				a_ctrl->gconf->gpio_num_info->gpio_num[gpio],
				1);
		}
	}

	/* VREG needs some delay to power up */
	usleep_range(2000, 3000);
	a_ctrl->actuator_state = ACT_ENABLE_STATE;
@@ -1825,6 +1891,20 @@ static int32_t msm_actuator_platform_probe(struct platform_device *pdev)
			return rc;
		}
	}
	rc = msm_sensor_driver_get_gpio_data(&(msm_actuator_t->gconf),
		(&pdev->dev)->of_node);
	if (rc < 0) {
		pr_err("%s: No/Error Actuator GPIOs\n", __func__);
	} else {
		msm_actuator_t->cam_pinctrl_status = 1;
		rc = msm_camera_pinctrl_init(
			&(msm_actuator_t->pinctrl_info), &(pdev->dev));
		if (rc < 0) {
			pr_err("ERR:%s: Error in reading actuator pinctrl\n",
				__func__);
			msm_actuator_t->cam_pinctrl_status = 0;
		}
	}

	msm_actuator_t->act_v4l2_subdev_ops = &msm_actuator_subdev_ops;
	msm_actuator_t->actuator_mutex = &msm_actuator_mutex;
+6 −3
Original line number Diff line number Diff line
/* Copyright (c) 2011-2015, The Linux Foundation. All rights reserved.
/* Copyright (c) 2011-2016, 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
@@ -25,7 +25,7 @@
#define DEFINE_MSM_MUTEX(mutexname) \
	static struct mutex mutexname = __MUTEX_INITIALIZER(mutexname)

#define	MSM_ACTUATOT_MAX_VREGS (10)
#define	MSM_ACTUATOR_MAX_VREGS (10)
#define	ACTUATOR_MAX_POLL_COUNT 10

struct msm_actuator_ctrl_t;
@@ -68,7 +68,7 @@ struct msm_actuator {

struct msm_actuator_vreg {
	struct camera_vreg_t *cam_vreg;
	void *data[MSM_ACTUATOT_MAX_VREGS];
	void *data[MSM_ACTUATOR_MAX_VREGS];
	int num_vreg;
};

@@ -105,6 +105,9 @@ struct msm_actuator_ctrl_t {
	struct msm_actuator_vreg vreg_cfg;
	struct park_lens_data_t park_lens;
	uint32_t max_code_size;
	struct msm_camera_gpio_conf *gconf;
	struct msm_pinctrl_info pinctrl_info;
	uint8_t cam_pinctrl_status;
};

#endif
+8 −73
Original line number Diff line number Diff line
@@ -681,77 +681,6 @@ static struct v4l2_subdev_ops msm_flash_subdev_ops = {

static const struct v4l2_subdev_internal_ops msm_flash_internal_ops;

static int32_t msm_flash_get_gpio_dt_data(struct device_node *of_node,
		struct msm_flash_ctrl_t *fctrl)
{
	int32_t rc = 0, i = 0;
	uint16_t *gpio_array = NULL;
	int16_t gpio_array_size = 0;
	struct msm_camera_gpio_conf *gconf = NULL;

	gpio_array_size = of_gpio_count(of_node);
	CDBG("%s gpio count %d\n", __func__, gpio_array_size);

	if (gpio_array_size > 0) {
		fctrl->power_info.gpio_conf =
			 kzalloc(sizeof(struct msm_camera_gpio_conf),
				 GFP_KERNEL);
		if (!fctrl->power_info.gpio_conf) {
			pr_err("%s failed %d\n", __func__, __LINE__);
			rc = -ENOMEM;
			return rc;
		}
		gconf = fctrl->power_info.gpio_conf;

		gpio_array = kzalloc(sizeof(uint16_t) * gpio_array_size,
			GFP_KERNEL);
		if (!gpio_array) {
			pr_err("%s failed %d\n", __func__, __LINE__);
			rc = -ENOMEM;
			goto free_gpio_conf;
		}
		for (i = 0; i < gpio_array_size; i++) {
			gpio_array[i] = of_get_gpio(of_node, i);
			if (((int16_t)gpio_array[i]) < 0) {
				pr_err("%s failed %d\n", __func__, __LINE__);
				rc = -EINVAL;
				goto free_gpio_array;
			}
			CDBG("%s gpio_array[%d] = %d\n", __func__, 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("%s failed %d\n", __func__, __LINE__);
			goto free_gpio_array;
		}

		rc = msm_camera_init_gpio_pin_tbl(of_node, gconf,
			gpio_array, gpio_array_size);
		if (rc < 0) {
			pr_err("%s failed %d\n", __func__, __LINE__);
			goto free_cam_gpio_req_tbl;
		}

		if (fctrl->flash_driver_type == FLASH_DRIVER_DEFAULT)
			fctrl->flash_driver_type = FLASH_DRIVER_GPIO;
		CDBG("%s:%d fctrl->flash_driver_type = %d", __func__, __LINE__,
			fctrl->flash_driver_type);
	}

	return 0;

free_cam_gpio_req_tbl:
	kfree(gconf->cam_gpio_req_tbl);
free_gpio_array:
	kfree(gpio_array);
free_gpio_conf:
	kfree(fctrl->power_info.gpio_conf);
	return rc;
}

static int32_t msm_flash_get_pmic_source_info(
	struct device_node *of_node,
	struct msm_flash_ctrl_t *fctrl)
@@ -977,13 +906,19 @@ static int32_t msm_flash_get_dt_data(struct device_node *of_node,
	}

	/* Read the gpio information from device tree */
	rc = msm_flash_get_gpio_dt_data(of_node, fctrl);
	rc = msm_sensor_driver_get_gpio_data(
		&(fctrl->power_info.gpio_conf), of_node);
	if (rc < 0) {
		pr_err("%s:%d msm_flash_get_gpio_dt_data failed rc %d\n",
		pr_err("%s:%d msm_sensor_driver_get_gpio_data failed rc %d\n",
			__func__, __LINE__, rc);
		return rc;
	}

	if (fctrl->flash_driver_type == FLASH_DRIVER_DEFAULT)
		fctrl->flash_driver_type = FLASH_DRIVER_GPIO;
	CDBG("%s:%d fctrl->flash_driver_type = %d", __func__, __LINE__,
		fctrl->flash_driver_type);

	/* Read the flash and torch source info from device tree node */
	rc = msm_flash_get_pmic_source_info(of_node, fctrl);
	if (rc < 0) {
+137 −25
Original line number Diff line number Diff line
@@ -67,8 +67,6 @@ int msm_camera_fill_vreg_params(struct camera_vreg_t *cam_vreg,
					break;
				}
			}
			if (j == num_vreg)
				power_setting[i].seq_val = INVALID_VREG;
			break;

		case CAM_VIO:
@@ -88,8 +86,6 @@ int msm_camera_fill_vreg_params(struct camera_vreg_t *cam_vreg,
					break;
				}
			}
			if (j == num_vreg)
				power_setting[i].seq_val = INVALID_VREG;
			break;

		case CAM_VANA:
@@ -109,8 +105,6 @@ int msm_camera_fill_vreg_params(struct camera_vreg_t *cam_vreg,
					break;
				}
			}
			if (j == num_vreg)
				power_setting[i].seq_val = INVALID_VREG;
			break;

		case CAM_VAF:
@@ -130,8 +124,6 @@ int msm_camera_fill_vreg_params(struct camera_vreg_t *cam_vreg,
					break;
				}
			}
			if (j == num_vreg)
				power_setting[i].seq_val = INVALID_VREG;
			break;

		case CAM_V_CUSTOM1:
@@ -152,9 +144,6 @@ int msm_camera_fill_vreg_params(struct camera_vreg_t *cam_vreg,
					break;
				}
			}
			if (j == num_vreg)
				power_setting[i].seq_val = INVALID_VREG;
			break;

		case CAM_V_CUSTOM2:
			for (j = 0; j < num_vreg; j++) {
@@ -174,8 +163,6 @@ int msm_camera_fill_vreg_params(struct camera_vreg_t *cam_vreg,
					break;
				}
			}
			if (j == num_vreg)
				power_setting[i].seq_val = INVALID_VREG;
			break;

		default:
@@ -184,7 +171,6 @@ int msm_camera_fill_vreg_params(struct camera_vreg_t *cam_vreg,
			break;
		}
	}

	return 0;
}

@@ -762,7 +748,6 @@ int msm_camera_init_gpio_pin_tbl(struct device_node *of_node,
		rc = -ENOMEM;
		return rc;
	}

	rc = of_property_read_u32(of_node, "qcom,gpio-vana", &val);
	if (rc != -EINVAL) {
		if (rc < 0) {
@@ -1036,6 +1021,7 @@ int msm_camera_get_dt_vreg_data(struct device_node *of_node,
	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;
	}

@@ -1190,12 +1176,10 @@ static int msm_camera_disable_i2c_mux(struct msm_camera_i2c_conf *i2c_conf)
	return 0;
}

static int msm_camera_pinctrl_init(struct msm_camera_power_ctrl_t *ctrl)
{
	struct msm_pinctrl_info *sensor_pctrl = NULL;
int msm_camera_pinctrl_init(
	struct msm_pinctrl_info *sensor_pctrl, struct device *dev) {

	sensor_pctrl = &ctrl->pinctrl_info;
	sensor_pctrl->pinctrl = devm_pinctrl_get(ctrl->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__);
@@ -1220,6 +1204,120 @@ static int msm_camera_pinctrl_init(struct msm_camera_power_ctrl_t *ctrl)
	return 0;
}

int msm_cam_sensor_handle_reg_gpio(int seq_val,
	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 val: %d, config: %d", __func__, __LINE__,
		seq_val, val);

	switch (seq_val) {
	case CAM_VDIG:
		gpio_offset = SENSOR_GPIO_VDIG;
		break;

	case CAM_VIO:
		gpio_offset = SENSOR_GPIO_VIO;
		break;

	case CAM_VANA:
		gpio_offset = SENSOR_GPIO_VANA;
		break;

	case CAM_VAF:
		gpio_offset = SENSOR_GPIO_VAF;
		break;

	case CAM_V_CUSTOM1:
		gpio_offset = SENSOR_GPIO_CUSTOM1;
		break;

	case CAM_V_CUSTOM2:
		gpio_offset = SENSOR_GPIO_CUSTOM2;
		break;

	default:
		pr_err("%s:%d Invalid VREG seq val %d\n", __func__,
			__LINE__, seq_val);
		return -EINVAL;
	}

	CDBG("%s: %d GPIO offset: %d, seq_val: %d\n", __func__, __LINE__,
		gpio_offset, seq_val);

	if ((gconf->gpio_num_info->valid[gpio_offset] == 1)) {
		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(struct msm_camera_gpio_conf),
		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_CONF;
	}

	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_CONF:
	kfree(gconf);
	kfree(gpio_array);
	*gpio_conf = NULL;
	return rc;
}

int msm_camera_power_up(struct msm_camera_power_ctrl_t *ctrl,
	enum msm_camera_device_type_t device_type,
	struct msm_camera_i2c_client *sensor_i2c_client)
@@ -1236,7 +1334,7 @@ int msm_camera_power_up(struct msm_camera_power_ctrl_t *ctrl,
	if (ctrl->gpio_conf->cam_gpiomux_conf_tbl != NULL)
		pr_err("%s:%d mux install\n", __func__, __LINE__);

	ret = msm_camera_pinctrl_init(ctrl);
	ret = msm_camera_pinctrl_init(&(ctrl->pinctrl_info), ctrl->dev);
	if (ret < 0) {
		pr_err("%s:%d Initialization of pinctrl failed\n",
				__func__, __LINE__);
@@ -1303,8 +1401,6 @@ int msm_camera_power_up(struct msm_camera_power_ctrl_t *ctrl,
				(int) power_setting->config_val);
			break;
		case SENSOR_VREG:
			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,
@@ -1319,9 +1415,18 @@ int msm_camera_power_up(struct msm_camera_power_ctrl_t *ctrl,
					&power_setting->data[0],
					1);
			else
				pr_err("ERR:%s: %d usr_idx:%d dts_idx:%d\n",
				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_val,
				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_I2C_MUX:
			if (ctrl->i2c_conf && ctrl->i2c_conf->use_i2c_mux)
@@ -1348,7 +1453,6 @@ int msm_camera_power_up(struct msm_camera_power_ctrl_t *ctrl,
			goto power_up_failed;
		}
	}

	CDBG("%s exit\n", __func__);
	return 0;
power_up_failed:
@@ -1380,6 +1484,9 @@ power_up_failed:
				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_val,
				ctrl->gpio_conf, GPIOF_OUT_INIT_LOW);
			break;
		case SENSOR_I2C_MUX:
			if (ctrl->i2c_conf && ctrl->i2c_conf->use_i2c_mux)
@@ -1505,6 +1612,11 @@ int msm_camera_power_down(struct msm_camera_power_ctrl_t *ctrl,
			} else
				pr_err("%s error in power up/down seq data\n",
								__func__);
			ret = msm_cam_sensor_handle_reg_gpio(pd->seq_val,
				ctrl->gpio_conf, GPIOF_OUT_INIT_LOW);
			if (ret < 0)
				pr_err("ERR:%s Error while disabling VREG GPIO\n",
					__func__);
			break;
		case SENSOR_I2C_MUX:
			if (ctrl->i2c_conf && ctrl->i2c_conf->use_i2c_mux)
+7 −0
Original line number Diff line number Diff line
@@ -15,6 +15,7 @@

#include <soc/qcom/camera2.h>
#include <linux/gpio.h>
#include <linux/of_gpio.h>
#include <linux/of.h>
#include "msm_camera_i2c.h"
#include "cam_soc_api.h"
@@ -58,4 +59,10 @@ int msm_camera_fill_vreg_params(struct camera_vreg_t *cam_vreg,
	int num_vreg, struct msm_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);
#endif
Loading