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

Commit c96c434d authored by Jigarkumar Zala's avatar Jigarkumar Zala
Browse files

msm: camera: Add front camera wled flash support



Front camera flash has WLED support for selfie flash.
This change enables WLED support for front image sensor to
request wled framework for brightness change based on request.

Change-Id: I84555dab7e2609814ac98448fbb3fb06da9ec7fc
Signed-off-by: default avatarJigarkumar Zala <jzala@codeaurora.org>
parent 5faec11e
Loading
Loading
Loading
Loading
+7 −1
Original line number Diff line number Diff line
@@ -65,6 +65,11 @@ First Level Node - CAM FLASH device
  Value type: <u32>
  Definition: Max duration in ms flash can glow.

- wled-flash-support
  Usage: optional
  Value type: <boolean>
  Definition: To identity wled flash hardware support.

- gpios
  Usage: optional
  Value type: <u32>
@@ -109,6 +114,7 @@ led_flash_rear: qcom,camera-flash@0 {
		flash-source = <&pmi8998_flash0 &pmi8998_flash1>;
		torch-source = <&pmi8998_torch0 &pmi8998_torch1>;
		switch-source = <&pmi8998_switch0>;
		wled-flash-support;
		qcom,slave-id = <0x00 0x00 0x0011>;
		qcom,cci-master = <0>;
		gpios = <&msmgpio 23 0>,
+83 −41
Original line number Diff line number Diff line
@@ -20,38 +20,72 @@ int cam_flash_prepare(struct cam_flash_ctrl *flash_ctrl,
	bool regulator_enable)
{
	int rc = 0;
	struct cam_flash_private_soc *soc_private =
		(struct cam_flash_private_soc *)
		flash_ctrl->soc_info.soc_private;

	if (!(flash_ctrl->switch_trigger)) {
		CAM_ERR(CAM_FLASH, "Invalid argument");
		return -EINVAL;
	}

	if (soc_private->is_wled_flash) {
		if (regulator_enable &&
			flash_ctrl->is_regulator_enabled == false) {
			rc = wled_flash_led_prepare(flash_ctrl->switch_trigger,
				ENABLE_REGULATOR, NULL);
			if (rc) {
				CAM_ERR(CAM_FLASH, "enable reg failed: rc: %d",
					rc);
				return rc;
			}

			flash_ctrl->is_regulator_enabled = true;
		} else if (!regulator_enable &&
				flash_ctrl->is_regulator_enabled == true) {
			rc = wled_flash_led_prepare(flash_ctrl->switch_trigger,
				DISABLE_REGULATOR, NULL);
			if (rc) {
				CAM_ERR(CAM_FLASH, "disalbe reg fail: rc: %d",
					rc);
				return rc;
			}

			flash_ctrl->is_regulator_enabled = false;
		} else {
			CAM_ERR(CAM_FLASH, "Wrong Wled flash state: %d",
				flash_ctrl->flash_state);
			rc = -EINVAL;
		}
	} else {
		if (regulator_enable &&
			(flash_ctrl->is_regulator_enabled == false)) {
			rc = qpnp_flash_led_prepare(flash_ctrl->switch_trigger,
				ENABLE_REGULATOR, NULL);
			if (rc) {
			CAM_ERR(CAM_FLASH, "regulator enable failed rc = %d",
				rc);
				CAM_ERR(CAM_FLASH,
					"Regulator enable failed rc = %d", rc);
				return rc;
			}

			flash_ctrl->is_regulator_enabled = true;
		} else if ((!regulator_enable) &&
			(flash_ctrl->is_regulator_enabled == true)) {
			rc = qpnp_flash_led_prepare(flash_ctrl->switch_trigger,
				DISABLE_REGULATOR, NULL);
			if (rc) {
			CAM_ERR(CAM_FLASH, "regulator disable failed rc = %d",
				rc);
				CAM_ERR(CAM_FLASH,
					"Regulator disable failed rc = %d", rc);
				return rc;
			}

			flash_ctrl->is_regulator_enabled = false;
		} else {
			CAM_ERR(CAM_FLASH, "Wrong Flash State : %d",
				flash_ctrl->flash_state);
			rc = -EINVAL;
		}

	}
	return rc;
}

@@ -144,37 +178,31 @@ static int cam_flash_ops(struct cam_flash_ctrl *flash_ctrl,
		for (i = 0; i < flash_ctrl->torch_num_sources; i++) {
			if (flash_ctrl->torch_trigger[i]) {
				max_current = soc_private->torch_max_current[i];

				if (flash_data->led_current_ma[i] <=
					max_current)
					curr = flash_data->led_current_ma[i];
				else
					curr = soc_private->torch_op_current[i];

				CAM_DBG(CAM_FLASH,
					"Led_Current[%d] = %d", i, curr);
				cam_res_mgr_led_trigger_event(
					flash_ctrl->torch_trigger[i],
					curr);
					curr = max_current;
			}
			CAM_DBG(CAM_FLASH, "Led_Torch[%d]: Current: %d",
				i, curr);
			cam_res_mgr_led_trigger_event(
				flash_ctrl->torch_trigger[i], curr);
		}
	} else if (op == CAMERA_SENSOR_FLASH_OP_FIREHIGH) {
		for (i = 0; i < flash_ctrl->flash_num_sources; i++) {
			if (flash_ctrl->flash_trigger[i]) {
				max_current = soc_private->flash_max_current[i];

				if (flash_data->led_current_ma[i] <=
					max_current)
					curr = flash_data->led_current_ma[i];
				else
					curr = soc_private->flash_op_current[i];

				CAM_DBG(CAM_FLASH, "LED flash_current[%d]: %d",
					curr = max_current;
			}
			CAM_DBG(CAM_FLASH, "LED_Flash[%d]: Current: %d",
				i, curr);
			cam_res_mgr_led_trigger_event(
					flash_ctrl->flash_trigger[i],
					curr);
			}
				flash_ctrl->flash_trigger[i], curr);
		}
	} else {
		CAM_ERR(CAM_FLASH, "Wrong Operation: %d", op);
@@ -525,11 +553,16 @@ int cam_flash_parser(struct cam_flash_ctrl *fctrl, void *arg)
	struct cam_flash_set_on_off *flash_operation_info = NULL;
	struct cam_flash_query_curr *flash_query_info = NULL;
	struct cam_flash_frame_setting *flash_data = NULL;
	struct cam_flash_private_soc *soc_private = NULL;

	if (!fctrl || !arg) {
		CAM_ERR(CAM_FLASH, "fctrl/arg is NULL");
		return -EINVAL;
	}

	soc_private = (struct cam_flash_private_soc *)
		fctrl->soc_info.soc_private;

	/* getting CSL Packet */
	ioctl_ctrl = (struct cam_control *)arg;

@@ -718,8 +751,17 @@ int cam_flash_parser(struct cam_flash_ctrl *fctrl, void *arg)
			flash_query_info =
				(struct cam_flash_query_curr *)cmd_buf;

			rc = qpnp_flash_led_prepare(fctrl->switch_trigger,
				QUERY_MAX_AVAIL_CURRENT, &query_curr_ma);
			if (soc_private->is_wled_flash)
				rc = wled_flash_led_prepare(
					fctrl->switch_trigger,
					QUERY_MAX_AVAIL_CURRENT,
					&query_curr_ma);
			else
				rc = qpnp_flash_led_prepare(
					fctrl->switch_trigger,
					QUERY_MAX_AVAIL_CURRENT,
					&query_curr_ma);

			CAM_DBG(CAM_FLASH, "query_curr_ma = %d",
				query_curr_ma);
			if (rc) {
+0 −1
Original line number Diff line number Diff line
@@ -13,7 +13,6 @@
#ifndef _CAM_FLASH_CORE_H_
#define _CAM_FLASH_CORE_H_

#include <linux/leds-qpnp-flash.h>
#include <media/cam_sensor.h>
#include "cam_flash_dev.h"
#include "cam_sync_api.h"
+3 −0
Original line number Diff line number Diff line
@@ -21,6 +21,7 @@
#include <linux/of.h>
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/leds-qpnp-flash.h>
#include <media/v4l2-subdev.h>
#include <media/v4l2-ioctl.h>
#include <media/v4l2-event.h>
@@ -123,6 +124,7 @@ struct cam_flash_frame_setting {
 * @torch_trigger_name  : Torch trigger name array
 * @torch_op_current    : Torch operational current
 * @torch_max_current   : Max supported current for LED in torch mode
 * @is_wled_flash       : Detection between WLED/LED flash
 */

struct cam_flash_private_soc {
@@ -134,6 +136,7 @@ struct cam_flash_private_soc {
	const char   *torch_trigger_name[CAM_FLASH_MAX_LED_TRIGGERS];
	uint32_t     torch_op_current[CAM_FLASH_MAX_LED_TRIGGERS];
	uint32_t     torch_max_current[CAM_FLASH_MAX_LED_TRIGGERS];
	bool         is_wled_flash;
};

/**
+77 −43
Original line number Diff line number Diff line
@@ -26,9 +26,12 @@ static int32_t cam_get_source_node_info(
	struct device_node *torch_src_node = NULL;
	struct device_node *switch_src_node = NULL;

	soc_private->is_wled_flash =
		of_property_read_bool(of_node, "wled-flash-support");

	switch_src_node = of_parse_phandle(of_node, "switch-source", 0);
	if (!switch_src_node) {
		CAM_DBG(CAM_FLASH, "switch_src_node NULL");
		CAM_WARN(CAM_FLASH, "switch_src_node NULL");
	} else {
		rc = of_property_read_string(switch_src_node,
			"qcom,default-led-trigger",
@@ -75,46 +78,61 @@ static int32_t cam_get_source_node_info(
				continue;
			}

			CAM_DBG(CAM_FLASH, "default trigger %s",
			CAM_DBG(CAM_FLASH, "Flash default trigger %s",
				soc_private->flash_trigger_name[i]);
			cam_res_mgr_led_trigger_register(
				soc_private->flash_trigger_name[i],
				&fctrl->flash_trigger[i]);

			/* Read operational-current */
			rc = of_property_read_u32(flash_src_node,
				"qcom,current-ma",
				&soc_private->flash_op_current[i]);
			if (soc_private->is_wled_flash) {
				rc = wled_flash_led_prepare(
					fctrl->flash_trigger[i],
					QUERY_MAX_CURRENT,
					&soc_private->flash_max_current[i]);
				if (rc) {
				CAM_WARN(CAM_FLASH, "op-current: read failed");
					CAM_ERR(CAM_FLASH,
					"WLED FLASH max_current read fail: %d",
						rc);
					of_node_put(flash_src_node);
					rc = 0;
					continue;
				}

			/* Read max-current */
			} else {
				rc = of_property_read_u32(flash_src_node,
					"qcom,max-current",
					&soc_private->flash_max_current[i]);
			if (rc) {
				if (rc < 0) {
					CAM_WARN(CAM_FLASH,
					"max-current: read failed");
					"LED FLASH max-current read fail: %d",
						rc);
					of_node_put(flash_src_node);
					continue;
				}
			}

			/* Read operational-current */
			rc = of_property_read_u32(flash_src_node,
				"qcom,current-ma",
				&soc_private->flash_op_current[i]);
			if (rc) {
				CAM_INFO(CAM_FLASH, "op-current: read failed");
				rc = 0;
			}

			/* Read max-duration */
			rc = of_property_read_u32(flash_src_node,
				"qcom,duration-ms",
				&soc_private->flash_max_duration[i]);
			if (rc)
				CAM_WARN(CAM_FLASH,
					"max-duration: read failed");

			if (rc) {
				CAM_INFO(CAM_FLASH,
					"max-duration prop unavailable: %d",
					rc);
				rc = 0;
			}
			of_node_put(flash_src_node);

			CAM_DBG(CAM_FLASH, "max_current[%d]: %d",
			CAM_DBG(CAM_FLASH, "MainFlashMaxCurrent[%d]: %d",
				i, soc_private->flash_max_current[i]);

			cam_res_mgr_led_trigger_register(
				soc_private->flash_trigger_name[i],
				&fctrl->flash_trigger[i]);
		}
	}

@@ -147,35 +165,51 @@ static int32_t cam_get_source_node_info(
				continue;
			}

			/* Read operational-current */
			rc = of_property_read_u32(torch_src_node,
				"qcom,current-ma",
				&soc_private->torch_op_current[i]);
			if (rc < 0) {
				CAM_WARN(CAM_FLASH, "current: read failed");
			CAM_DBG(CAM_FLASH, "Torch default trigger %s",
				soc_private->torch_trigger_name[i]);
			cam_res_mgr_led_trigger_register(
				soc_private->torch_trigger_name[i],
				&fctrl->torch_trigger[i]);

			if (soc_private->is_wled_flash) {
				rc = wled_flash_led_prepare(
					fctrl->torch_trigger[i],
					QUERY_MAX_CURRENT,
					&soc_private->torch_max_current[i]);
				if (rc) {
					CAM_ERR(CAM_FLASH,
					"WLED TORCH max_current read fail: %d",
					rc);
					of_node_put(torch_src_node);
					continue;
				}

			/* Read max-current */
			} else {
				rc = of_property_read_u32(torch_src_node,
					"qcom,max-current",
					&soc_private->torch_max_current[i]);
				if (rc < 0) {
					CAM_WARN(CAM_FLASH,
					"max-current: read failed");
					"LED-TORCH max-current read failed: %d",
						rc);
					of_node_put(torch_src_node);
					continue;
				}
			}

			/* Read operational-current */
			rc = of_property_read_u32(torch_src_node,
				"qcom,current-ma",
				&soc_private->torch_op_current[i]);
			if (rc < 0) {
				CAM_WARN(CAM_FLASH,
					"op-current prop unavailable: %d", rc);
				rc = 0;
			}

			of_node_put(torch_src_node);

			CAM_DBG(CAM_FLASH, "max_current[%d]: %d",
			CAM_DBG(CAM_FLASH, "TorchMaxCurrent[%d]: %d",
				i, soc_private->torch_max_current[i]);

			cam_res_mgr_led_trigger_register(
				soc_private->torch_trigger_name[i],
				&fctrl->torch_trigger[i]);
		}
	}