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

Commit cd7ea465 authored by Lei Wang's avatar Lei Wang Committed by Gerrit - the friendly Code Review server
Browse files

msm: camera: flash: Add GPIO flash torch support



Add GPIO hardware support for flash driver

CRs-Fixed: 2640249
Change-Id: I2e0e27acbad8f16fbd658348545af52876bb8328
Signed-off-by: default avatarLei Wang <wangwanglei@codeaurora.org>
parent 4c9cf08c
Loading
Loading
Loading
Loading
+70 −9
Original line number Diff line number Diff line
@@ -11,6 +11,41 @@
#include "cam_common_util.h"
#include "cam_packet_util.h"

static int cam_flash_set_gpio(struct cam_flash_ctrl *fctrl,
	bool enable)
{
	int i;
	struct cam_hw_soc_info *soc_info = NULL;
	struct cam_soc_gpio_data *gpio_conf = NULL;
	uint8_t size = 0;

	if (!fctrl) {
		CAM_ERR(CAM_FLASH, "Flash node is NULL");
		return -EINVAL;
	}

	soc_info = &fctrl->soc_info;
	gpio_conf = soc_info->gpio_data;

	if (gpio_conf == NULL) {
		CAM_ERR(CAM_FLASH, "GPIO DATA NULL");
		return -EINVAL;
	}

	size = gpio_conf->gpio_delay_tbl_size;

	for (i = 0; i < size; i++) {
		CAM_DBG(CAM_FLASH, "flash %s gpio %d",
			(enable ? "ENABLE" : "DISABLE"),
			gpio_conf->cam_gpio_req_tbl[i].gpio);
		cam_res_mgr_gpio_set_value(gpio_conf->cam_gpio_req_tbl[i].gpio,
			(enable ? 1 : 0));
		usleep_range(gpio_conf->gpio_delay_tbl[i] * 1000,
			gpio_conf->gpio_delay_tbl[i] * 1000 + 10);
	}
	return 0;
}

static int cam_flash_prepare(struct cam_flash_ctrl *flash_ctrl,
	bool regulator_enable)
{
@@ -84,7 +119,8 @@ static int cam_flash_prepare(struct cam_flash_ctrl *flash_ctrl,
	return rc;
}

static int cam_flash_pmic_flush_nrt(struct cam_flash_ctrl *fctrl)
static int cam_flash_pmic_gpio_flush_nrt(
	struct cam_flash_ctrl *fctrl)
{
	int j = 0;
	struct cam_flash_frame_setting *nrt_settings;
@@ -180,11 +216,18 @@ static int cam_flash_construct_default_power_setting(
	return rc;
}

int cam_flash_pmic_power_ops(struct cam_flash_ctrl *fctrl,
int cam_flash_pmic_gpio_power_ops(
	struct cam_flash_ctrl *fctrl,
	bool regulator_enable)
{
	int rc = 0;

	/* Gpio flash do not need to power on and off */
	if (fctrl->soc_info.gpio_data) {
		CAM_DBG(CAM_FLASH, "gpio based flash not need power");
		return rc;
	}

	if (!(fctrl->switch_trigger)) {
		CAM_ERR(CAM_FLASH, "Invalid argument");
		return -EINVAL;
@@ -281,7 +324,8 @@ int cam_flash_i2c_power_ops(struct cam_flash_ctrl *fctrl,
	return rc;
}

int cam_flash_pmic_flush_request(struct cam_flash_ctrl *fctrl,
int cam_flash_pmic_gpio_flush_request(
	struct cam_flash_ctrl *fctrl,
	enum cam_flash_flush_type type, uint64_t req_id)
{
	int rc = 0;
@@ -318,7 +362,7 @@ int cam_flash_pmic_flush_request(struct cam_flash_ctrl *fctrl,
				flash_data->led_current_ma[j] = 0;
		}

		cam_flash_pmic_flush_nrt(fctrl);
		cam_flash_pmic_gpio_flush_nrt(fctrl);
	} else if ((type == FLUSH_REQ) && (req_id != 0)) {
	/* flush request with req_id*/
		frame_offset = req_id % MAX_PER_FRAME_ARRAY;
@@ -341,7 +385,7 @@ int cam_flash_pmic_flush_request(struct cam_flash_ctrl *fctrl,
			flash_data->led_current_ma[i] = 0;
	} else if ((type == FLUSH_REQ) && (req_id == 0)) {
		/* Handels NonRealTime usecase */
		cam_flash_pmic_flush_nrt(fctrl);
		cam_flash_pmic_gpio_flush_nrt(fctrl);
	} else {
		CAM_ERR(CAM_FLASH, "Invalid arguments");
		return -EINVAL;
@@ -456,6 +500,11 @@ static int cam_flash_ops(struct cam_flash_ctrl *flash_ctrl,
		flash_ctrl->soc_info.soc_private;

	if (op == CAMERA_SENSOR_FLASH_OP_FIRELOW) {
		/* Turn On Gpio Flash */
		if (flash_ctrl->soc_info.gpio_data) {
			cam_flash_set_gpio(flash_ctrl, true);
			return 0;
		}
		for (i = 0; i < flash_ctrl->torch_num_sources; i++) {
			if (flash_ctrl->torch_trigger[i]) {
				max_current = soc_private->torch_max_current[i];
@@ -471,6 +520,11 @@ static int cam_flash_ops(struct cam_flash_ctrl *flash_ctrl,
				flash_ctrl->torch_trigger[i], curr);
		}
	} else if (op == CAMERA_SENSOR_FLASH_OP_FIREHIGH) {
		/* Turn On Gpio Flash */
		if (flash_ctrl->soc_info.gpio_data) {
			cam_flash_set_gpio(flash_ctrl, true);
			return 0;
		}
		for (i = 0; i < flash_ctrl->flash_num_sources; i++) {
			if (flash_ctrl->flash_trigger[i]) {
				max_current = soc_private->flash_max_current[i];
@@ -509,6 +563,10 @@ int cam_flash_off(struct cam_flash_ctrl *flash_ctrl)
		cam_res_mgr_led_trigger_event(flash_ctrl->switch_trigger,
			(enum led_brightness)LED_SWITCH_OFF);

	/* Turn Off Gpio Flash */
	if (flash_ctrl->soc_info.gpio_data)
		cam_flash_set_gpio(flash_ctrl, false);

	flash_ctrl->flash_state = CAM_FLASH_STATE_START;
	return 0;
}
@@ -602,7 +660,8 @@ static int cam_flash_i2c_delete_req(struct cam_flash_ctrl *fctrl,
	return 0;
}

static int cam_flash_pmic_delete_req(struct cam_flash_ctrl *fctrl,
static int cam_flash_pmic_gpio_delete_req(
	struct cam_flash_ctrl *fctrl,
	uint64_t req_id)
{
	int i = 0;
@@ -758,7 +817,8 @@ int cam_flash_i2c_apply_setting(struct cam_flash_ctrl *fctrl,
	return rc;
}

int cam_flash_pmic_apply_setting(struct cam_flash_ctrl *fctrl,
int cam_flash_pmic_gpio_apply_setting(
	struct cam_flash_ctrl *fctrl,
	uint64_t req_id)
{
	int rc = 0, i = 0;
@@ -935,7 +995,7 @@ int cam_flash_pmic_apply_setting(struct cam_flash_ctrl *fctrl,
	}

nrt_del_req:
	cam_flash_pmic_delete_req(fctrl, req_id);
	cam_flash_pmic_gpio_delete_req(fctrl, req_id);
apply_setting_err:
	return rc;
}
@@ -1288,7 +1348,8 @@ int cam_flash_i2c_pkt_parser(struct cam_flash_ctrl *fctrl, void *arg)
	return rc;
}

int cam_flash_pmic_pkt_parser(struct cam_flash_ctrl *fctrl, void *arg)
int cam_flash_pmic_gpio_pkt_parser(
	struct cam_flash_ctrl *fctrl, void *arg)
{
	int rc = 0, i = 0;
	uintptr_t generic_ptr, cmd_buf_ptr;
+25 −6
Original line number Diff line number Diff line
// SPDX-License-Identifier: GPL-2.0-only
/*
 * Copyright (c) 2017-2019, The Linux Foundation. All rights reserved.
 * Copyright (c) 2017-2020, The Linux Foundation. All rights reserved.
 */

#include <linux/module.h>
@@ -477,11 +477,26 @@ static int32_t cam_flash_platform_probe(struct platform_device *pdev)
		fctrl->func_tbl.power_ops = cam_flash_i2c_power_ops;
		fctrl->func_tbl.flush_req = cam_flash_i2c_flush_request;
	} else {
		/* PMIC Flash */
		fctrl->func_tbl.parser = cam_flash_pmic_pkt_parser;
		fctrl->func_tbl.apply_setting = cam_flash_pmic_apply_setting;
		fctrl->func_tbl.power_ops = cam_flash_pmic_power_ops;
		fctrl->func_tbl.flush_req = cam_flash_pmic_flush_request;
		if (fctrl->soc_info.gpio_data) {
			rc = cam_sensor_util_request_gpio_table(
				&fctrl->soc_info,
				true);
			if (rc) {
				CAM_ERR(CAM_FLASH,
					"GPIO table request failed: rc: %d",
					rc);
				goto free_gpio_resource;
			}
		}
		/* PMIC GPIO Flash */
		fctrl->func_tbl.parser =
			cam_flash_pmic_gpio_pkt_parser;
		fctrl->func_tbl.apply_setting =
			cam_flash_pmic_gpio_apply_setting;
		fctrl->func_tbl.power_ops =
			cam_flash_pmic_gpio_power_ops;
		fctrl->func_tbl.flush_req =
			cam_flash_pmic_gpio_flush_request;
	}

	rc = cam_flash_init_subdev(fctrl);
@@ -509,6 +524,10 @@ static int32_t cam_flash_platform_probe(struct platform_device *pdev)
free_cci_resource:
	kfree(fctrl->io_master_info.cci_client);
	fctrl->io_master_info.cci_client = NULL;
free_gpio_resource:
	cam_sensor_util_request_gpio_table(&fctrl->soc_info, false);
	kfree(fctrl->soc_info.gpio_data);
	fctrl->soc_info.gpio_data = NULL;
free_resource:
	kfree(fctrl->i2c_data.per_frame);
	kfree(fctrl->soc_info.soc_private);
+8 −6
Original line number Diff line number Diff line
/* SPDX-License-Identifier: GPL-2.0-only */
/*
 * Copyright (c) 2017-2019, The Linux Foundation. All rights reserved.
 * Copyright (c) 2017-2020, The Linux Foundation. All rights reserved.
 */

#ifndef _CAM_FLASH_DEV_H_
@@ -115,7 +115,7 @@ struct cam_flash_frame_setting {
	uint16_t                     num_iterations;
	uint16_t                     led_on_delay_ms;
	uint16_t                     led_off_delay_ms;
	int8_t                       opcode;
	uint8_t                      opcode;
	uint32_t                     led_current_ma[CAM_FLASH_MAX_LED_TRIGGERS];
};

@@ -209,18 +209,20 @@ struct cam_flash_ctrl {
	uint32_t                            last_flush_req;
};

int cam_flash_pmic_pkt_parser(struct cam_flash_ctrl *fctrl, void *arg);
int cam_flash_pmic_gpio_pkt_parser(
	struct cam_flash_ctrl *fctrl, void *arg);
int cam_flash_i2c_pkt_parser(struct cam_flash_ctrl *fctrl, void *arg);
int cam_flash_pmic_apply_setting(struct cam_flash_ctrl *fctrl, uint64_t req_id);
int cam_flash_pmic_gpio_apply_setting(
	struct cam_flash_ctrl *fctrl, uint64_t req_id);
int cam_flash_i2c_apply_setting(struct cam_flash_ctrl *fctrl, uint64_t req_id);
int cam_flash_off(struct cam_flash_ctrl *fctrl);
int cam_flash_pmic_power_ops(struct cam_flash_ctrl *fctrl,
int cam_flash_pmic_gpio_power_ops(struct cam_flash_ctrl *fctrl,
	bool regulator_enable);
int cam_flash_i2c_power_ops(struct cam_flash_ctrl *fctrl,
	bool regulator_enable);
int cam_flash_i2c_flush_request(struct cam_flash_ctrl *fctrl,
	enum cam_flash_flush_type type, uint64_t req_id);
int cam_flash_pmic_flush_request(struct cam_flash_ctrl *fctrl,
int cam_flash_pmic_gpio_flush_request(struct cam_flash_ctrl *fctrl,
	enum cam_flash_flush_type, uint64_t req_id);
void cam_flash_shutdown(struct cam_flash_ctrl *fctrl);
int cam_flash_release_dev(struct cam_flash_ctrl *fctrl);
+47 −0
Original line number Diff line number Diff line
@@ -1029,6 +1029,53 @@ static int cam_soc_util_get_dt_gpio_req_tbl(struct device_node *of_node,
			gconf->cam_gpio_req_tbl[i].label);
	}

	if (!of_get_property(of_node, "gpio-req-tbl-delay", &count)) {
		CAM_DBG(CAM_UTIL, "no gpio-req-tbl-delay");
		kfree(val_array);
		return rc;
	}

	count /= sizeof(uint32_t);
	if (!count) {
		CAM_ERR(CAM_UTIL, "Invalid gpio count for gpio-req-tbl-delay");
		kfree(val_array);
		return rc;
	}

	if (count != gconf->cam_gpio_req_tbl_size) {
		CAM_ERR(CAM_UTIL,
			"Invalid number of gpio-req-tbl-delay entries: %d",
			count);
		goto free_val_array;
	}

	gconf->gpio_delay_tbl = kcalloc(count, sizeof(uint32_t),
		GFP_KERNEL);
	if (!gconf->gpio_delay_tbl) {
		CAM_ERR(CAM_UTIL,
			"Failed to allocate memory for gpio_delay_tbl");
		rc = -ENOMEM;
		goto free_val_array;
	}

	gconf->gpio_delay_tbl_size = count;

	rc = of_property_read_u32_array(of_node, "gpio-req-tbl-delay",
		val_array, count);
	if (rc) {
		CAM_ERR(CAM_UTIL, "Failed to read gpio-req-tbl-delay entry");
		kfree(gconf->gpio_delay_tbl);
		gconf->gpio_delay_tbl_size = 0;
		kfree(val_array);
		return rc;
	}

	for (i = 0; i < count; i++) {
		gconf->gpio_delay_tbl[i] = val_array[i];
		CAM_DBG(CAM_UTIL, "gpio_delay_tbl[%d] = %ld", i,
			gconf->gpio_delay_tbl[i]);
	}

	kfree(val_array);

	return rc;
+4 −0
Original line number Diff line number Diff line
@@ -108,12 +108,16 @@ struct cam_soc_pinctrl_info {
 *                             gpios node in DTSI
 * @cam_gpio_req_tbl            It is list of al the requesetd gpios
 * @cam_gpio_req_tbl_size:      It is size of requested gpios
 * @gpio_delay_tbl:            It is list of al requested gpios delay
 * @gpio_delay_tbl_size:       It is size of requested gpios delay
 **/
struct cam_soc_gpio_data {
	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_delay_tbl;
	uint8_t gpio_delay_tbl_size;
};

/**