Loading arch/arm64/boot/dts/qcom/sdm670-camera-sensor-svr.dtsi +11 −1 Original line number Diff line number Diff line Loading @@ -39,7 +39,16 @@ flash-source = <&pm660l_flash2>; torch-source = <&pm660l_torch2>; switch-source = <&pm660l_switch1>; status = "disabled"; gpios = <&tlmm 0 0>, <&tlmm 1 0>, <&tlmm 23 0>; gpio-req-tbl-num = <0 1 2>; gpio-req-tbl-flags = <0 0 0>; gpio-req-tbl-label = "TCKING_LED_3V3_EN", "TCKING_LED_1V2_EN", "TCKing_LED_EN"; gpio-req-tbl-delay = <20 20 20>; status = "ok"; }; actuator_regulator: gpio-regulator@0 { Loading Loading @@ -350,6 +359,7 @@ sensor-position-roll = <270>; sensor-position-pitch = <0>; sensor-position-yaw = <180>; led-flash-src = <&led_flash_front>; cam_vio-supply = <&pm660_l14>; cam_vana-supply = <&pm660l_l3>; cam_vdig-supply = <&pm660_l12>; Loading arch/arm64/boot/dts/qcom/sdm845-camera-sensor-svr.dtsi +10 −10 Original line number Diff line number Diff line Loading @@ -39,6 +39,12 @@ flash-source = <&pmi8998_flash2>; torch-source = <&pmi8998_torch2>; switch-source = <&pmi8998_switch1>; gpios = <&tlmm 90 0>, <&tlmm 40 0>; gpio-req-tbl-num = <0 1>; gpio-req-tbl-flags = <0 0>; gpio-req-tbl-label = "FLASH_EN", "FLASH_NOW"; status = "ok"; }; Loading Loading @@ -408,22 +414,16 @@ gpios = <&tlmm 13 0>, <&tlmm 26 0>, <&tlmm 132 0>, <&tlmm 133 0>, <&tlmm 90 0>, <&tlmm 40 0>; <&tlmm 133 0>; gpio-reset = <1>; gpio-vana = <2>; gpio-vdig = <3>; gpio-vio = <4>; gpio-standby = <5>; gpio-req-tbl-num = <0 1 2 3 4 5>; gpio-req-tbl-flags = <1 0 0 0 0 0>; gpio-req-tbl-num = <0 1 2 3>; gpio-req-tbl-flags = <1 0 0 0>; gpio-req-tbl-label = "CAMIF_MCLK0", "CAM_RESET2", "CAM_VANA2", "CAM_VDIG2", "CAM_VIO2", "CAM_STANDBY2"; "CAM_VDIG2"; sensor-mode = <0>; cci-master = <0>; status = "ok"; Loading drivers/media/platform/msm/camera/cam_sensor_module/cam_flash/cam_flash_core.c +51 −0 Original line number Diff line number Diff line Loading @@ -11,6 +11,7 @@ */ #include <linux/module.h> #include <linux/gpio.h> #include "cam_sensor_cmn_header.h" #include "cam_flash_core.h" Loading @@ -21,6 +22,10 @@ static int cam_flash_prepare(struct cam_flash_ctrl *flash_ctrl, bool regulator_enable) { struct cam_flash_private_soc *soc_private = (struct cam_flash_private_soc *) flash_ctrl->soc_info .soc_private; struct cam_soc_gpio_data *gpio_conf = soc_private->gpio_data; int rc = 0; if (!(flash_ctrl->switch_trigger)) { Loading Loading @@ -48,6 +53,11 @@ static int cam_flash_prepare(struct cam_flash_ctrl *flash_ctrl, return rc; } flash_ctrl->is_regulator_enabled = false; } else if ((gpio_conf != NULL) && (gpio_conf->cam_gpio_common_tbl_size > 0)) { CAM_INFO(CAM_FLASH, "gpio based flash not need regulator"); return rc; } else { CAM_ERR(CAM_FLASH, "Wrong Flash State : %d", flash_ctrl->flash_state); Loading Loading @@ -380,6 +390,45 @@ int cam_flash_flush_request(struct cam_req_mgr_flush_request *flush) return rc; } static void cam_flash_set_gpios(struct cam_flash_ctrl *flash_ctrl, bool enable) { struct cam_flash_private_soc *soc_private = (struct cam_flash_private_soc *) flash_ctrl->soc_info .soc_private; struct cam_soc_gpio_data *gpio_conf = soc_private->gpio_data; int i; if (gpio_conf != NULL && gpio_conf->cam_gpio_common_tbl_size > 0) { struct gpio *gpio_tbl = gpio_conf->cam_gpio_req_tbl; int size = (int) gpio_conf->cam_gpio_req_tbl_size; if (enable) { for (i = 0; i < size; i++) { CAM_DBG(CAM_FLASH, "enabling gpio %d", gpio_tbl[i].gpio); gpio_set_value_cansleep(gpio_tbl[i].gpio, 1); if (soc_private->gpio_delay_tbl_size > 0) { CAM_DBG(CAM_FLASH, "sleeping for %d ms", soc_private->gpio_delay_tbl[i]); msleep(soc_private->gpio_delay_tbl[i]); } } } else { for (i = size-1; i >= 0; i--) { CAM_DBG(CAM_FLASH, "disabling gpio %d", gpio_tbl[i].gpio); gpio_set_value_cansleep(gpio_tbl[i].gpio, 0); if (soc_private->gpio_delay_tbl_size > 0) { CAM_DBG(CAM_FLASH, "sleeping for %d ms", soc_private->gpio_delay_tbl[i]); msleep(soc_private->gpio_delay_tbl[i]); } } } } } static int cam_flash_ops(struct cam_flash_ctrl *flash_ctrl, struct cam_flash_frame_setting *flash_data, enum camera_flash_opcode op) { Loading @@ -396,6 +445,7 @@ static int cam_flash_ops(struct cam_flash_ctrl *flash_ctrl, flash_ctrl->soc_info.soc_private; if (op == CAMERA_SENSOR_FLASH_OP_FIRELOW) { cam_flash_set_gpios(flash_ctrl, true); for (i = 0; i < flash_ctrl->torch_num_sources; i++) { if (flash_ctrl->torch_trigger[i]) { max_current = soc_private->torch_max_current[i]; Loading Loading @@ -455,6 +505,7 @@ 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); cam_flash_set_gpios(flash_ctrl, false); flash_ctrl->flash_state = CAM_FLASH_STATE_START; return 0; } Loading drivers/media/platform/msm/camera/cam_sensor_module/cam_flash/cam_flash_dev.h +6 −0 Original line number Diff line number Diff line Loading @@ -136,6 +136,9 @@ 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 * @gpio_data : GPIO info * @gpio_delay_tbl : Sleep times after enabling/disabling GPIOs * @gpio_delay_tbl_size : Number of elements in cam_gpio_delay_tbl */ struct cam_flash_private_soc { Loading @@ -147,6 +150,9 @@ 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]; struct cam_soc_gpio_data *gpio_data; uint32_t *gpio_delay_tbl; uint8_t gpio_delay_tbl_size; }; struct cam_flash_func_tbl { Loading drivers/media/platform/msm/camera/cam_sensor_module/cam_flash/cam_flash_soc.c +267 −1 Original line number Diff line number Diff line /* Copyright (c) 2017-2018, The Linux Foundation. All rights reserved. /* Copyright (c) 2017-2019, 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 Loading @@ -15,6 +15,262 @@ #include "cam_flash_soc.h" #include "cam_res_mgr_api.h" static int cam_flash_get_dt_gpio_req_tbl(struct device_node *of_node, struct cam_soc_gpio_data *gconf, uint16_t *gpio_array, uint16_t gpio_array_size) { int32_t rc = 0, i = 0; uint32_t count = 0; uint32_t *val_array = NULL; if (!of_get_property(of_node, "gpio-req-tbl-num", &count)) return 0; count /= sizeof(uint32_t); if (!count) { CAM_DBG(CAM_FLASH, "gpio-req-tbl-num 0"); 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, "gpio-req-tbl-num", val_array, count); if (rc) { CAM_ERR(CAM_FLASH, "failed in reading gpio-req-tbl-num, rc = %d", rc); goto free_gpio_req_tbl; } for (i = 0; i < count; i++) { if (val_array[i] >= gpio_array_size) { CAM_ERR(CAM_FLASH, "gpio req tbl index %d invalid", val_array[i]); goto free_gpio_req_tbl; } gconf->cam_gpio_req_tbl[i].gpio = gpio_array[val_array[i]]; CAM_DBG(CAM_FLASH, "cam_gpio_req_tbl[%d].gpio = %d", i, gconf->cam_gpio_req_tbl[i].gpio); } rc = of_property_read_u32_array(of_node, "gpio-req-tbl-flags", val_array, count); if (rc) { CAM_ERR(CAM_FLASH, "Failed in gpio-req-tbl-flags, rc %d", rc); goto free_gpio_req_tbl; } for (i = 0; i < count; i++) { gconf->cam_gpio_req_tbl[i].flags = val_array[i]; CAM_DBG(CAM_FLASH, "cam_gpio_req_tbl[%d].flags = %ld", i, gconf->cam_gpio_req_tbl[i].flags); } for (i = 0; i < count; i++) { rc = of_property_read_string_index(of_node, "gpio-req-tbl-label", i, &gconf->cam_gpio_req_tbl[i].label); if (rc) { CAM_ERR(CAM_FLASH, "Failed rc %d", rc); goto free_gpio_req_tbl; } CAM_DBG(CAM_FLASH, "cam_gpio_req_tbl[%d].label = %s", i, gconf->cam_gpio_req_tbl[i].label); } 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; } static int cam_flash_get_dt_gpio_delay_tbl( struct device_node *of_node, struct cam_flash_private_soc *soc_private) { int32_t rc = 0, i = 0; uint32_t *val_array = NULL; uint32_t count = 0; soc_private->gpio_delay_tbl_size = 0; if (!of_get_property(of_node, "gpio-req-tbl-delay", &count)) return 0; count /= sizeof(uint32_t); if (!count) { CAM_ERR(CAM_FLASH, "gpio-req-tbl-delay 0"); return 0; } if (count != soc_private->gpio_data->cam_gpio_req_tbl_size) { CAM_ERR(CAM_FLASH, "Invalid number of gpio-req-tbl-delay entries: %d", count); return 0; } val_array = kcalloc(count, sizeof(uint32_t), GFP_KERNEL); if (!val_array) return -ENOMEM; soc_private->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_FLASH, "Failed in gpio-req-tbl-delay, rc %d", rc); goto free_val_array; } soc_private->gpio_delay_tbl = val_array; for (i = 0; i < count; i++) { CAM_DBG(CAM_FLASH, "gpio_delay_tbl[%d] = %ld", i, soc_private->gpio_delay_tbl[i]); } return 0; free_val_array: kfree(val_array); soc_private->gpio_delay_tbl_size = 0; return rc; } static int cam_flash_get_gpio_info( struct device_node *of_node, struct cam_flash_private_soc *soc_private) { int32_t rc = 0, i = 0; uint16_t *gpio_array = NULL; int16_t gpio_array_size = 0; struct cam_soc_gpio_data *gconf = NULL; gpio_array_size = of_gpio_count(of_node); CAM_DBG(CAM_FLASH, "gpio count %d", gpio_array_size); if (gpio_array_size <= 0) return 0; 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); CAM_DBG(CAM_FLASH, "gpio_array[%d] = %d", i, gpio_array[i]); } gconf = kzalloc(sizeof(*gconf), GFP_KERNEL); if (!gconf) return -ENOMEM; rc = cam_flash_get_dt_gpio_req_tbl(of_node, gconf, gpio_array, gpio_array_size); if (rc) { CAM_ERR(CAM_FLASH, "failed in msm_camera_get_dt_gpio_req_tbl"); goto free_gpio_array; } gconf->cam_gpio_common_tbl = kcalloc(gpio_array_size, sizeof(struct gpio), GFP_KERNEL); if (!gconf->cam_gpio_common_tbl) { rc = -ENOMEM; goto free_gpio_array; } for (i = 0; i < gpio_array_size; i++) gconf->cam_gpio_common_tbl[i].gpio = gpio_array[i]; gconf->cam_gpio_common_tbl_size = gpio_array_size; soc_private->gpio_data = gconf; kfree(gpio_array); cam_flash_get_dt_gpio_delay_tbl(of_node, soc_private); return rc; free_gpio_array: kfree(gpio_array); free_gpio_conf: kfree(gconf); soc_private->gpio_data = NULL; return rc; } static int cam_flash_request_gpio_table( struct cam_flash_private_soc *soc_private, bool gpio_en) { int rc = 0, i = 0; uint8_t size = 0; struct cam_soc_gpio_data *gpio_conf = soc_private->gpio_data; struct gpio *gpio_tbl = NULL; if (!gpio_conf) { CAM_DBG(CAM_FLASH, "No GPIO entry"); return 0; } if (gpio_conf->cam_gpio_common_tbl_size <= 0) { CAM_ERR(CAM_FLASH, "GPIO table size is invalid"); return -EINVAL; } size = gpio_conf->cam_gpio_req_tbl_size; gpio_tbl = gpio_conf->cam_gpio_req_tbl; if (!gpio_tbl || !size) { CAM_ERR(CAM_FLASH, "Invalid gpio_tbl %pK / size %d", gpio_tbl, size); return -EINVAL; } for (i = 0; i < size; i++) { CAM_DBG(CAM_FLASH, "cam_flash_request_gpio_table: i=%d, gpio=%d dir=%ld", i, gpio_tbl[i].gpio, gpio_tbl[i].flags); } if (gpio_en) { for (i = 0; i < size; i++) { rc = gpio_request_one(gpio_tbl[i].gpio, gpio_tbl[i].flags, gpio_tbl[i].label); if (rc) { /* * After GPIO request fails, contine to * apply new gpios, outout a error message * for driver bringup debug */ CAM_ERR(CAM_FLASH, "gpio %d:%s request fails", gpio_tbl[i].gpio, gpio_tbl[i].label); } } } else { gpio_free_array(gpio_tbl, size); } return rc; } static int32_t cam_get_source_node_info( struct device_node *of_node, struct cam_flash_ctrl *fctrl, Loading Loading @@ -179,6 +435,15 @@ static int32_t cam_get_source_node_info( } } (void) cam_flash_get_gpio_info(of_node, soc_private); if (soc_private->gpio_data != NULL) { rc = cam_flash_request_gpio_table(soc_private, true); if (rc < 0) CAM_ERR(CAM_FLASH, "Failed in request gpio table, rc=%d", rc); } return rc; } Loading Loading @@ -216,6 +481,7 @@ int cam_flash_get_dt_data(struct cam_flash_ctrl *fctrl, return rc; free_soc_private: cam_flash_request_gpio_table(soc_info->soc_private, false); kfree(soc_info->soc_private); soc_info->soc_private = NULL; release_soc_res: Loading Loading
arch/arm64/boot/dts/qcom/sdm670-camera-sensor-svr.dtsi +11 −1 Original line number Diff line number Diff line Loading @@ -39,7 +39,16 @@ flash-source = <&pm660l_flash2>; torch-source = <&pm660l_torch2>; switch-source = <&pm660l_switch1>; status = "disabled"; gpios = <&tlmm 0 0>, <&tlmm 1 0>, <&tlmm 23 0>; gpio-req-tbl-num = <0 1 2>; gpio-req-tbl-flags = <0 0 0>; gpio-req-tbl-label = "TCKING_LED_3V3_EN", "TCKING_LED_1V2_EN", "TCKing_LED_EN"; gpio-req-tbl-delay = <20 20 20>; status = "ok"; }; actuator_regulator: gpio-regulator@0 { Loading Loading @@ -350,6 +359,7 @@ sensor-position-roll = <270>; sensor-position-pitch = <0>; sensor-position-yaw = <180>; led-flash-src = <&led_flash_front>; cam_vio-supply = <&pm660_l14>; cam_vana-supply = <&pm660l_l3>; cam_vdig-supply = <&pm660_l12>; Loading
arch/arm64/boot/dts/qcom/sdm845-camera-sensor-svr.dtsi +10 −10 Original line number Diff line number Diff line Loading @@ -39,6 +39,12 @@ flash-source = <&pmi8998_flash2>; torch-source = <&pmi8998_torch2>; switch-source = <&pmi8998_switch1>; gpios = <&tlmm 90 0>, <&tlmm 40 0>; gpio-req-tbl-num = <0 1>; gpio-req-tbl-flags = <0 0>; gpio-req-tbl-label = "FLASH_EN", "FLASH_NOW"; status = "ok"; }; Loading Loading @@ -408,22 +414,16 @@ gpios = <&tlmm 13 0>, <&tlmm 26 0>, <&tlmm 132 0>, <&tlmm 133 0>, <&tlmm 90 0>, <&tlmm 40 0>; <&tlmm 133 0>; gpio-reset = <1>; gpio-vana = <2>; gpio-vdig = <3>; gpio-vio = <4>; gpio-standby = <5>; gpio-req-tbl-num = <0 1 2 3 4 5>; gpio-req-tbl-flags = <1 0 0 0 0 0>; gpio-req-tbl-num = <0 1 2 3>; gpio-req-tbl-flags = <1 0 0 0>; gpio-req-tbl-label = "CAMIF_MCLK0", "CAM_RESET2", "CAM_VANA2", "CAM_VDIG2", "CAM_VIO2", "CAM_STANDBY2"; "CAM_VDIG2"; sensor-mode = <0>; cci-master = <0>; status = "ok"; Loading
drivers/media/platform/msm/camera/cam_sensor_module/cam_flash/cam_flash_core.c +51 −0 Original line number Diff line number Diff line Loading @@ -11,6 +11,7 @@ */ #include <linux/module.h> #include <linux/gpio.h> #include "cam_sensor_cmn_header.h" #include "cam_flash_core.h" Loading @@ -21,6 +22,10 @@ static int cam_flash_prepare(struct cam_flash_ctrl *flash_ctrl, bool regulator_enable) { struct cam_flash_private_soc *soc_private = (struct cam_flash_private_soc *) flash_ctrl->soc_info .soc_private; struct cam_soc_gpio_data *gpio_conf = soc_private->gpio_data; int rc = 0; if (!(flash_ctrl->switch_trigger)) { Loading Loading @@ -48,6 +53,11 @@ static int cam_flash_prepare(struct cam_flash_ctrl *flash_ctrl, return rc; } flash_ctrl->is_regulator_enabled = false; } else if ((gpio_conf != NULL) && (gpio_conf->cam_gpio_common_tbl_size > 0)) { CAM_INFO(CAM_FLASH, "gpio based flash not need regulator"); return rc; } else { CAM_ERR(CAM_FLASH, "Wrong Flash State : %d", flash_ctrl->flash_state); Loading Loading @@ -380,6 +390,45 @@ int cam_flash_flush_request(struct cam_req_mgr_flush_request *flush) return rc; } static void cam_flash_set_gpios(struct cam_flash_ctrl *flash_ctrl, bool enable) { struct cam_flash_private_soc *soc_private = (struct cam_flash_private_soc *) flash_ctrl->soc_info .soc_private; struct cam_soc_gpio_data *gpio_conf = soc_private->gpio_data; int i; if (gpio_conf != NULL && gpio_conf->cam_gpio_common_tbl_size > 0) { struct gpio *gpio_tbl = gpio_conf->cam_gpio_req_tbl; int size = (int) gpio_conf->cam_gpio_req_tbl_size; if (enable) { for (i = 0; i < size; i++) { CAM_DBG(CAM_FLASH, "enabling gpio %d", gpio_tbl[i].gpio); gpio_set_value_cansleep(gpio_tbl[i].gpio, 1); if (soc_private->gpio_delay_tbl_size > 0) { CAM_DBG(CAM_FLASH, "sleeping for %d ms", soc_private->gpio_delay_tbl[i]); msleep(soc_private->gpio_delay_tbl[i]); } } } else { for (i = size-1; i >= 0; i--) { CAM_DBG(CAM_FLASH, "disabling gpio %d", gpio_tbl[i].gpio); gpio_set_value_cansleep(gpio_tbl[i].gpio, 0); if (soc_private->gpio_delay_tbl_size > 0) { CAM_DBG(CAM_FLASH, "sleeping for %d ms", soc_private->gpio_delay_tbl[i]); msleep(soc_private->gpio_delay_tbl[i]); } } } } } static int cam_flash_ops(struct cam_flash_ctrl *flash_ctrl, struct cam_flash_frame_setting *flash_data, enum camera_flash_opcode op) { Loading @@ -396,6 +445,7 @@ static int cam_flash_ops(struct cam_flash_ctrl *flash_ctrl, flash_ctrl->soc_info.soc_private; if (op == CAMERA_SENSOR_FLASH_OP_FIRELOW) { cam_flash_set_gpios(flash_ctrl, true); for (i = 0; i < flash_ctrl->torch_num_sources; i++) { if (flash_ctrl->torch_trigger[i]) { max_current = soc_private->torch_max_current[i]; Loading Loading @@ -455,6 +505,7 @@ 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); cam_flash_set_gpios(flash_ctrl, false); flash_ctrl->flash_state = CAM_FLASH_STATE_START; return 0; } Loading
drivers/media/platform/msm/camera/cam_sensor_module/cam_flash/cam_flash_dev.h +6 −0 Original line number Diff line number Diff line Loading @@ -136,6 +136,9 @@ 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 * @gpio_data : GPIO info * @gpio_delay_tbl : Sleep times after enabling/disabling GPIOs * @gpio_delay_tbl_size : Number of elements in cam_gpio_delay_tbl */ struct cam_flash_private_soc { Loading @@ -147,6 +150,9 @@ 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]; struct cam_soc_gpio_data *gpio_data; uint32_t *gpio_delay_tbl; uint8_t gpio_delay_tbl_size; }; struct cam_flash_func_tbl { Loading
drivers/media/platform/msm/camera/cam_sensor_module/cam_flash/cam_flash_soc.c +267 −1 Original line number Diff line number Diff line /* Copyright (c) 2017-2018, The Linux Foundation. All rights reserved. /* Copyright (c) 2017-2019, 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 Loading @@ -15,6 +15,262 @@ #include "cam_flash_soc.h" #include "cam_res_mgr_api.h" static int cam_flash_get_dt_gpio_req_tbl(struct device_node *of_node, struct cam_soc_gpio_data *gconf, uint16_t *gpio_array, uint16_t gpio_array_size) { int32_t rc = 0, i = 0; uint32_t count = 0; uint32_t *val_array = NULL; if (!of_get_property(of_node, "gpio-req-tbl-num", &count)) return 0; count /= sizeof(uint32_t); if (!count) { CAM_DBG(CAM_FLASH, "gpio-req-tbl-num 0"); 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, "gpio-req-tbl-num", val_array, count); if (rc) { CAM_ERR(CAM_FLASH, "failed in reading gpio-req-tbl-num, rc = %d", rc); goto free_gpio_req_tbl; } for (i = 0; i < count; i++) { if (val_array[i] >= gpio_array_size) { CAM_ERR(CAM_FLASH, "gpio req tbl index %d invalid", val_array[i]); goto free_gpio_req_tbl; } gconf->cam_gpio_req_tbl[i].gpio = gpio_array[val_array[i]]; CAM_DBG(CAM_FLASH, "cam_gpio_req_tbl[%d].gpio = %d", i, gconf->cam_gpio_req_tbl[i].gpio); } rc = of_property_read_u32_array(of_node, "gpio-req-tbl-flags", val_array, count); if (rc) { CAM_ERR(CAM_FLASH, "Failed in gpio-req-tbl-flags, rc %d", rc); goto free_gpio_req_tbl; } for (i = 0; i < count; i++) { gconf->cam_gpio_req_tbl[i].flags = val_array[i]; CAM_DBG(CAM_FLASH, "cam_gpio_req_tbl[%d].flags = %ld", i, gconf->cam_gpio_req_tbl[i].flags); } for (i = 0; i < count; i++) { rc = of_property_read_string_index(of_node, "gpio-req-tbl-label", i, &gconf->cam_gpio_req_tbl[i].label); if (rc) { CAM_ERR(CAM_FLASH, "Failed rc %d", rc); goto free_gpio_req_tbl; } CAM_DBG(CAM_FLASH, "cam_gpio_req_tbl[%d].label = %s", i, gconf->cam_gpio_req_tbl[i].label); } 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; } static int cam_flash_get_dt_gpio_delay_tbl( struct device_node *of_node, struct cam_flash_private_soc *soc_private) { int32_t rc = 0, i = 0; uint32_t *val_array = NULL; uint32_t count = 0; soc_private->gpio_delay_tbl_size = 0; if (!of_get_property(of_node, "gpio-req-tbl-delay", &count)) return 0; count /= sizeof(uint32_t); if (!count) { CAM_ERR(CAM_FLASH, "gpio-req-tbl-delay 0"); return 0; } if (count != soc_private->gpio_data->cam_gpio_req_tbl_size) { CAM_ERR(CAM_FLASH, "Invalid number of gpio-req-tbl-delay entries: %d", count); return 0; } val_array = kcalloc(count, sizeof(uint32_t), GFP_KERNEL); if (!val_array) return -ENOMEM; soc_private->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_FLASH, "Failed in gpio-req-tbl-delay, rc %d", rc); goto free_val_array; } soc_private->gpio_delay_tbl = val_array; for (i = 0; i < count; i++) { CAM_DBG(CAM_FLASH, "gpio_delay_tbl[%d] = %ld", i, soc_private->gpio_delay_tbl[i]); } return 0; free_val_array: kfree(val_array); soc_private->gpio_delay_tbl_size = 0; return rc; } static int cam_flash_get_gpio_info( struct device_node *of_node, struct cam_flash_private_soc *soc_private) { int32_t rc = 0, i = 0; uint16_t *gpio_array = NULL; int16_t gpio_array_size = 0; struct cam_soc_gpio_data *gconf = NULL; gpio_array_size = of_gpio_count(of_node); CAM_DBG(CAM_FLASH, "gpio count %d", gpio_array_size); if (gpio_array_size <= 0) return 0; 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); CAM_DBG(CAM_FLASH, "gpio_array[%d] = %d", i, gpio_array[i]); } gconf = kzalloc(sizeof(*gconf), GFP_KERNEL); if (!gconf) return -ENOMEM; rc = cam_flash_get_dt_gpio_req_tbl(of_node, gconf, gpio_array, gpio_array_size); if (rc) { CAM_ERR(CAM_FLASH, "failed in msm_camera_get_dt_gpio_req_tbl"); goto free_gpio_array; } gconf->cam_gpio_common_tbl = kcalloc(gpio_array_size, sizeof(struct gpio), GFP_KERNEL); if (!gconf->cam_gpio_common_tbl) { rc = -ENOMEM; goto free_gpio_array; } for (i = 0; i < gpio_array_size; i++) gconf->cam_gpio_common_tbl[i].gpio = gpio_array[i]; gconf->cam_gpio_common_tbl_size = gpio_array_size; soc_private->gpio_data = gconf; kfree(gpio_array); cam_flash_get_dt_gpio_delay_tbl(of_node, soc_private); return rc; free_gpio_array: kfree(gpio_array); free_gpio_conf: kfree(gconf); soc_private->gpio_data = NULL; return rc; } static int cam_flash_request_gpio_table( struct cam_flash_private_soc *soc_private, bool gpio_en) { int rc = 0, i = 0; uint8_t size = 0; struct cam_soc_gpio_data *gpio_conf = soc_private->gpio_data; struct gpio *gpio_tbl = NULL; if (!gpio_conf) { CAM_DBG(CAM_FLASH, "No GPIO entry"); return 0; } if (gpio_conf->cam_gpio_common_tbl_size <= 0) { CAM_ERR(CAM_FLASH, "GPIO table size is invalid"); return -EINVAL; } size = gpio_conf->cam_gpio_req_tbl_size; gpio_tbl = gpio_conf->cam_gpio_req_tbl; if (!gpio_tbl || !size) { CAM_ERR(CAM_FLASH, "Invalid gpio_tbl %pK / size %d", gpio_tbl, size); return -EINVAL; } for (i = 0; i < size; i++) { CAM_DBG(CAM_FLASH, "cam_flash_request_gpio_table: i=%d, gpio=%d dir=%ld", i, gpio_tbl[i].gpio, gpio_tbl[i].flags); } if (gpio_en) { for (i = 0; i < size; i++) { rc = gpio_request_one(gpio_tbl[i].gpio, gpio_tbl[i].flags, gpio_tbl[i].label); if (rc) { /* * After GPIO request fails, contine to * apply new gpios, outout a error message * for driver bringup debug */ CAM_ERR(CAM_FLASH, "gpio %d:%s request fails", gpio_tbl[i].gpio, gpio_tbl[i].label); } } } else { gpio_free_array(gpio_tbl, size); } return rc; } static int32_t cam_get_source_node_info( struct device_node *of_node, struct cam_flash_ctrl *fctrl, Loading Loading @@ -179,6 +435,15 @@ static int32_t cam_get_source_node_info( } } (void) cam_flash_get_gpio_info(of_node, soc_private); if (soc_private->gpio_data != NULL) { rc = cam_flash_request_gpio_table(soc_private, true); if (rc < 0) CAM_ERR(CAM_FLASH, "Failed in request gpio table, rc=%d", rc); } return rc; } Loading Loading @@ -216,6 +481,7 @@ int cam_flash_get_dt_data(struct cam_flash_ctrl *fctrl, return rc; free_soc_private: cam_flash_request_gpio_table(soc_info->soc_private, false); kfree(soc_info->soc_private); soc_info->soc_private = NULL; release_soc_res: Loading