diff --git a/config/holicamera.conf b/config/holicamera.conf index 85bc1dae00c6..a74f301e76c5 100644 --- a/config/holicamera.conf +++ b/config/holicamera.conf @@ -9,4 +9,5 @@ export CONFIG_SPECTRA_ISP=y export CONFIG_SPECTRA_OPE=y export CONFIG_SPECTRA_TFE=y export CONFIG_SPECTRA_SENSOR=y +export CONFIG_CAMERA_FLASH_PWM=y endif diff --git a/config/holicameraconf.h b/config/holicameraconf.h index 958fe154c124..1141c53aea4e 100644 --- a/config/holicameraconf.h +++ b/config/holicameraconf.h @@ -8,3 +8,4 @@ #define CONFIG_SPECTRA_OPE 1 #define CONFIG_SPECTRA_TFE 1 #define CONFIG_SPECTRA_SENSOR 1 +#define CONFIG_CAMERA_FLASH_PWM 1 diff --git a/drivers/Makefile b/drivers/Makefile index 47797e2972cb..ffcafe6fcbe6 100644 --- a/drivers/Makefile +++ b/drivers/Makefile @@ -171,6 +171,7 @@ camera-$(CONFIG_SPECTRA_SENSOR) += \ cam_sensor_module/cam_sensor_io/cam_sensor_qup_i2c.o \ cam_sensor_module/cam_sensor_io/cam_sensor_spi.o \ cam_sensor_module/cam_sensor_utils/cam_sensor_util.o \ + cam_sensor_module/cam_flash_pm6125_gpio/pm6125_flash_gpio.o \ cam_sensor_module/cam_res_mgr/cam_res_mgr.o ifneq (,$(filter $(CONFIG_AF_NOISE_ELIMINATION), y m)) diff --git a/drivers/cam_sensor_module/cam_flash/cam_flash_core.c b/drivers/cam_sensor_module/cam_flash/cam_flash_core.c index ba6677363f8f..7dc82ebe73cc 100644 --- a/drivers/cam_sensor_module/cam_flash/cam_flash_core.c +++ b/drivers/cam_sensor_module/cam_flash/cam_flash_core.c @@ -12,6 +12,11 @@ #include "cam_packet_util.h" #include +#ifdef CONFIG_CAMERA_FLASH_PWM +#include "cam_sensor_util.h" +#include "../cam_flash_pm6125_gpio/pm6125_flash_gpio.h" +#endif + static uint default_on_timer = 2; module_param(default_on_timer, uint, 0644); @@ -517,6 +522,11 @@ int cam_flash_off(struct cam_flash_ctrl *flash_ctrl) { int rc = 0; +#ifdef CONFIG_CAMERA_FLASH_PWM + struct cam_hw_soc_info soc_info = flash_ctrl->soc_info; + struct cam_flash_private_soc *soc_private = (struct cam_flash_private_soc *)soc_info.soc_private; +#endif + if (!flash_ctrl) { CAM_ERR(CAM_FLASH, "Flash control Null"); return -EINVAL; @@ -542,7 +552,12 @@ int cam_flash_off(struct cam_flash_ctrl *flash_ctrl) cam_sensor_util_i2c_apply_setting(&(flash_ctrl->io_master_info), i2c_flash_off); } - +#ifdef CONFIG_CAMERA_FLASH_PWM + CAM_ERR(CAM_SENSOR,"cam_flash_off"); + cam_res_mgr_gpio_set_value(soc_private->flash_gpio_enable, 0); + cam_res_mgr_gpio_free(soc_info.dev, soc_private->flash_gpio_enable); + pm6125_flash_gpio_select_state(PM6125_FLASH_GPIO_STATE_SUSPEND,1); +#endif return 0; } @@ -552,6 +567,11 @@ static int cam_flash_low( { int i = 0, rc = 0; +#ifdef CONFIG_CAMERA_FLASH_PWM + struct cam_hw_soc_info soc_info = flash_ctrl->soc_info; + struct cam_flash_private_soc *soc_private = (struct cam_flash_private_soc *)soc_info.soc_private; +#endif + if (!flash_data) { CAM_ERR(CAM_FLASH, "Flash Data Null"); return -EINVAL; @@ -568,6 +588,17 @@ static int cam_flash_low( if (rc) CAM_ERR(CAM_FLASH, "Fire Torch failed: %d", rc); +#ifdef CONFIG_CAMERA_FLASH_PWM + CAM_ERR(CAM_FLASH, "Flash low Triggered"); + rc = cam_res_mgr_gpio_request(soc_info.dev, soc_private->flash_gpio_enable, 0, "CUSTOM_GPIO1"); + if(rc) { + CAM_ERR(CAM_FLASH, "gpio %d request fails", soc_private->flash_gpio_enable); + return rc; + } + cam_res_mgr_gpio_set_value(soc_private->flash_gpio_enable, 0); + pm6125_flash_gpio_select_state(PM6125_FLASH_GPIO_STATE_ACTIVE, (u64)flash_data->led_current_ma[0]*10000/1500); +#endif + return rc; } @@ -577,6 +608,11 @@ static int cam_flash_high( { int i = 0, rc = 0; +#ifdef CONFIG_CAMERA_FLASH_PWM + struct cam_hw_soc_info soc_info = flash_ctrl->soc_info; + struct cam_flash_private_soc *soc_private = (struct cam_flash_private_soc *)soc_info.soc_private; +#endif + if (!flash_data) { CAM_ERR(CAM_FLASH, "Flash Data Null"); return -EINVAL; @@ -593,6 +629,17 @@ static int cam_flash_high( if (rc) CAM_ERR(CAM_FLASH, "Fire Flash Failed: %d", rc); +#ifdef CONFIG_CAMERA_FLASH_PWM + CAM_ERR(CAM_FLASH, "Flash high Triggered"); + rc = cam_res_mgr_gpio_request(soc_info.dev, soc_private->flash_gpio_enable, 0, "CUSTOM_GPIO1"); + if(rc) { + CAM_ERR(CAM_FLASH, "gpio %d request fails", soc_private->flash_gpio_enable); + return rc; + } + cam_res_mgr_gpio_set_value(soc_private->flash_gpio_enable, 1); + pm6125_flash_gpio_select_state(PM6125_FLASH_GPIO_STATE_ACTIVE, (u64)flash_data->led_current_ma[0]*10000/1500); +#endif + return rc; } diff --git a/drivers/cam_sensor_module/cam_flash/cam_flash_dev.c b/drivers/cam_sensor_module/cam_flash/cam_flash_dev.c index 6334d2acdce1..323497be3b90 100644 --- a/drivers/cam_sensor_module/cam_flash/cam_flash_dev.c +++ b/drivers/cam_sensor_module/cam_flash/cam_flash_dev.c @@ -142,6 +142,10 @@ static int32_t cam_flash_driver_cmd(struct cam_flash_ctrl *fctrl, CAM_DBG(CAM_FLASH, "CAM_QUERY_CAP"); flash_cap.slot_info = fctrl->soc_info.index; flash_cap.flash_type = soc_private->flash_type; + CAM_DBG(CAM_FLASH, "dts flash_type is %d, it should same with camx&chi flash_type", soc_private->flash_type); +#ifdef CONFIG_CAMERA_FLASH_PWM + CAM_DBG(CAM_FLASH, "get flash_enabel_gpio %d", soc_private->flash_gpio_enable); +#endif for (i = 0; i < fctrl->flash_num_sources; i++) { flash_cap.max_current_flash[i] = soc_private->flash_max_current[i]; diff --git a/drivers/cam_sensor_module/cam_flash/cam_flash_dev.h b/drivers/cam_sensor_module/cam_flash/cam_flash_dev.h index f5437c93a843..8f76d5e8173e 100644 --- a/drivers/cam_sensor_module/cam_flash/cam_flash_dev.h +++ b/drivers/cam_sensor_module/cam_flash/cam_flash_dev.h @@ -153,6 +153,9 @@ struct cam_flash_private_soc { uint32_t torch_max_current[CAM_FLASH_MAX_LED_TRIGGERS]; bool is_wled_flash; uint32_t flash_type; +#ifdef CONFIG_CAMERA_FLASH_PWM + uint32_t flash_gpio_enable; +#endif }; struct cam_flash_func_tbl { diff --git a/drivers/cam_sensor_module/cam_flash/cam_flash_soc.c b/drivers/cam_sensor_module/cam_flash/cam_flash_soc.c index 9eac7a8b8aaf..d5f3f1ca6572 100644 --- a/drivers/cam_sensor_module/cam_flash/cam_flash_soc.c +++ b/drivers/cam_sensor_module/cam_flash/cam_flash_soc.c @@ -70,6 +70,10 @@ static int32_t cam_get_source_node_info( struct device_node *flash_src_node = NULL; struct device_node *torch_src_node = NULL; struct device_node *switch_src_node = NULL; +#ifdef CONFIG_CAMERA_FLASH_PWM + int16_t gpio_array_size = 0; + uint16_t *gpio_array = NULL; +#endif soc_private->is_wled_flash = of_property_read_bool(of_node, "wled-flash-support"); @@ -79,7 +83,29 @@ static int32_t cam_get_source_node_info( CAM_ERR(CAM_FLASH, "flash-type read failed rc=%d", rc); soc_private->flash_type = CAM_FLASH_TYPE_PMIC; // default to PMIC flash +#ifdef CONFIG_CAMERA_FLASH_PWM + } else if(soc_private->flash_type == CAM_FLASH_TYPE_GPIO) { + gpio_array_size = of_gpio_count(of_node); + if (gpio_array_size == 1){ + gpio_array = kcalloc(gpio_array_size, sizeof(uint16_t), GFP_KERNEL); + if (!gpio_array) { + CAM_ERR(CAM_FLASH, "flash gpio array alloc fail"); + } else { + for (i = 0; i < gpio_array_size; i++) { + gpio_array[i] = of_get_gpio(of_node, i); + CAM_DBG(CAM_FLASH, "flash dts gpio_array[%d] = %d name is %s %s", i, gpio_array[i], of_node->name, of_node->full_name); + } + soc_private->flash_gpio_enable = gpio_array[0]; + CAM_DBG(CAM_FLASH, "flash gpio enable %d",soc_private->flash_gpio_enable); + kfree(gpio_array); + } + } else { + CAM_ERR(CAM_FLASH, "flash should have two gpio, first is enable in flash dts, second control by flash pm6125"); + } } +#else + } +#endif switch_src_node = of_parse_phandle(of_node, "switch-source", 0); if (!switch_src_node) { diff --git a/drivers/cam_sensor_module/cam_flash_pm6125_gpio/pm6125_flash_gpio.c b/drivers/cam_sensor_module/cam_flash_pm6125_gpio/pm6125_flash_gpio.c new file mode 100644 index 000000000000..b1adf43a8d60 --- /dev/null +++ b/drivers/cam_sensor_module/cam_flash_pm6125_gpio/pm6125_flash_gpio.c @@ -0,0 +1,100 @@ +/* + *Copyright (C) 2021 Motorola Mobility LLC, + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License 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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "pm6125_flash_gpio.h" + + + +/***************************************************************************** + * Data Structure + *****************************************************************************/ + +struct pwm_device *pwm; + +/***************************************************************************** + * Function + *****************************************************************************/ + +void pm6125_flash_gpio_select_state(PM6125_FLASH_GPIO_STATE s, u64 flash_current){ + struct pwm_state pstate; + int rc = 0; + pwm_get_state(pwm, &pstate); + pstate.period = 50000; + pstate.duty_cycle = 500000*flash_current/10000; + switch(s){ + case PM6125_FLASH_GPIO_STATE_ACTIVE: + pstate.enabled = true; + rc = pwm_apply_state(pwm, &pstate); + break; + case PM6125_FLASH_GPIO_STATE_SUSPEND: + pstate.enabled = false; + rc = pwm_apply_state(pwm, &pstate); + break; + default: + PM6125_FLASH_PRINT("[pm6125_flash_gpio]Failed to control PWM use a err state!\n"); + } + + if(rc < 0) { + PM6125_FLASH_PRINT("[pm6125_flash_gpio]Apply PWM state fail, rc = %d", rc); + } +} + +static int pm6125_flash_pwm_probe(struct platform_device *pdev) +{ + int rc = 0; + pwm = devm_pwm_get(&pdev->dev, NULL); + if (IS_ERR(pwm)) + return PTR_ERR(pwm); + return rc; +} + +static const struct of_device_id gpio_of_match[] = { + { .compatible = "qualcomm,pm6125_flash_gpio", }, + {}, +}; + +static struct platform_driver pm6125_flash_gpio_platform_driver = { + .probe = pm6125_flash_pwm_probe, + .driver = { + .name = "PM6125_FLASH_GPIO_DTS", + .of_match_table = gpio_of_match, + }, +}; + +int pm6125_flash_gpio_init_module(void) +{ + if (platform_driver_register(&pm6125_flash_gpio_platform_driver)) { + PM6125_FLASH_PRINT("[pm6125_flash_gpio]Failed to register pm6125_flash_gpio_platform_driver!\n"); + return -1; + } + return 0; +} + +void pm6125_flash_gpio_exit_module(void) +{ + platform_driver_unregister(&pm6125_flash_gpio_platform_driver); +} + +MODULE_AUTHOR("liyang "); +MODULE_DESCRIPTION("CONTROL PM6125 FLASH GPIO Driver"); +MODULE_LICENSE("GPL"); \ No newline at end of file diff --git a/drivers/cam_sensor_module/cam_flash_pm6125_gpio/pm6125_flash_gpio.h b/drivers/cam_sensor_module/cam_flash_pm6125_gpio/pm6125_flash_gpio.h new file mode 100644 index 000000000000..efd6b279adb6 --- /dev/null +++ b/drivers/cam_sensor_module/cam_flash_pm6125_gpio/pm6125_flash_gpio.h @@ -0,0 +1,21 @@ +#ifndef _PM6125_FLASH_GPIO_H_ +#define _PM6125_FLASH_GPIO_H_ + +#include "../cam_sensor_utils/cam_sensor_cmn_header.h" + +#define PM6125_FLASH_PRINT pr_info //printk + +/* DTS state */ +typedef enum { + PM6125_FLASH_GPIO_STATE_ACTIVE, + PM6125_FLASH_GPIO_STATE_SUSPEND, + PM6125_FLASH_GPIO_STATE_MAX, /* for array size */ +} PM6125_FLASH_GPIO_STATE; + +/***************************************************************************** + * Function Prototype + *****************************************************************************/ +extern void pm6125_flash_gpio_select_state(PM6125_FLASH_GPIO_STATE s, u64 flash_current); +int pm6125_flash_gpio_init_module(void); +void pm6125_flash_gpio_exit_module(void); +#endif /* _PM6125_FLASH_GPIO_H_*/ \ No newline at end of file diff --git a/drivers/cam_sensor_module/cam_res_mgr/cam_res_mgr.c b/drivers/cam_sensor_module/cam_res_mgr/cam_res_mgr.c index 5165f6b2d1c9..8ea1889ebe2d 100644 --- a/drivers/cam_sensor_module/cam_res_mgr/cam_res_mgr.c +++ b/drivers/cam_sensor_module/cam_res_mgr/cam_res_mgr.c @@ -458,6 +458,7 @@ int cam_res_mgr_gpio_request(struct device *dev, uint gpio, * from the gpio_res_list * These two situations both need request gpio. */ + CAM_DBG(CAM_RES, "shared gpio enable is %d shared gpio num is %d", cam_res->shared_gpio_enabled, cam_res->dt.num_shared_gpio); if (!gpio_found) { CAM_DBG(CAM_RES, "gpio: %u not found in gpio_res list", gpio); rc = gpio_request_one(gpio, flags, label); @@ -571,7 +572,7 @@ bool cam_res_mgr_util_check_if_gpio_is_shared( } EXPORT_SYMBOL(cam_res_mgr_util_check_if_gpio_is_shared); -static void cam_res_mgr_gpio_free(struct device *dev, uint gpio) +void cam_res_mgr_gpio_free(struct device *dev, uint gpio) { bool gpio_found = false; bool need_free = true; @@ -644,6 +645,7 @@ static void cam_res_mgr_gpio_free(struct device *dev, uint gpio) mutex_unlock(&cam_res->gpio_res_lock); } +EXPORT_SYMBOL(cam_res_mgr_gpio_free); void cam_res_mgr_gpio_free_arry(struct device *dev, const struct gpio *array, size_t num) diff --git a/drivers/cam_sensor_module/cam_res_mgr/cam_res_mgr_api.h b/drivers/cam_sensor_module/cam_res_mgr/cam_res_mgr_api.h index cb5022f482e5..9a4b2b8560b8 100644 --- a/drivers/cam_sensor_module/cam_res_mgr/cam_res_mgr_api.h +++ b/drivers/cam_sensor_module/cam_res_mgr/cam_res_mgr_api.h @@ -73,6 +73,18 @@ bool cam_res_mgr_util_check_if_gpio_is_shared( int cam_res_mgr_gpio_request(struct device *dev, unsigned int gpio, unsigned long flags, const char *label); +/** + * @brief: Free a GPIO + * + * Free the GPIO and release corresponding gpio_res. + * + * @dev : Pointer to the device + * @gpio : A GPIO number + * + * @return Status of operation. Negative in case of error. Zero otherwise. + */ +void cam_res_mgr_gpio_free(struct device *dev, uint gpio); + /** * @brief: Free a array GPIO * diff --git a/drivers/camera_main.c b/drivers/camera_main.c index d126491e8d28..a49ba3b78018 100644 --- a/drivers/camera_main.c +++ b/drivers/camera_main.c @@ -26,6 +26,7 @@ #include "cam_csiphy_dev.h" #include "cam_eeprom_dev.h" #include "cam_ois_dev.h" +#include "pm6125_flash_gpio.h" #if IS_REACHABLE(CONFIG_LEDS_QPNP_FLASH_V2) || \ IS_REACHABLE(CONFIG_LEDS_QTI_FLASH) @@ -118,6 +119,9 @@ static const struct camera_submodule_component camera_sensor[] = { IS_REACHABLE(CONFIG_LEDS_QTI_FLASH) {&cam_flash_init_module, &cam_flash_exit_module}, #endif +#if IS_REACHABLE(CONFIG_CAMERA_FLASH_PWM) + {&pm6125_flash_gpio_init_module, &pm6125_flash_gpio_exit_module}, +#endif #endif };