aboutsummaryrefslogtreecommitdiff
path: root/camera/sensor/flash
diff options
context:
space:
mode:
authorwzedlare <vedatak01@gmail.com>2017-06-18 16:38:26 +0000
committerwzedlare <vedatak01@gmail.com>2017-06-19 16:57:11 +0000
commitc7d4e3fd588e3ba3d3fa4d5cfa224aa54bc288bf (patch)
treeb8b64cb9deb6832c1e41f58f0f143514beafc709 /camera/sensor/flash
parent28c99c87b881bb664c44bb26e80a681f87d54e60 (diff)
p2a42: Import fully working kernel sourceHEADn7.1
Change-Id: Ia4c94f09e29843b1af34d466243378a357e97b70
Diffstat (limited to 'camera/sensor/flash')
-rw-r--r--camera/sensor/flash/Makefile5
-rw-r--r--camera/sensor/flash/msm_flash.c1222
-rw-r--r--camera/sensor/flash/msm_flash.h124
3 files changed, 1351 insertions, 0 deletions
diff --git a/camera/sensor/flash/Makefile b/camera/sensor/flash/Makefile
new file mode 100644
index 00000000..3ffd2060
--- /dev/null
+++ b/camera/sensor/flash/Makefile
@@ -0,0 +1,5 @@
+ccflags-y += -Icamera/sensor/cci
+ccflags-y += -Icamera
+ccflags-y += -Icamera/common
+ccflags-y += -Icamera/sensor/io
+obj-$(CONFIG_MSMB_CAMERA) += msm_flash.o
diff --git a/camera/sensor/flash/msm_flash.c b/camera/sensor/flash/msm_flash.c
new file mode 100644
index 00000000..20f216c7
--- /dev/null
+++ b/camera/sensor/flash/msm_flash.c
@@ -0,0 +1,1222 @@
+/* Copyright (c) 2009-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
+ * only 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.
+ *
+ */
+
+#define pr_fmt(fmt) "%s:%d " fmt, __func__, __LINE__
+
+#include <linux/module.h>
+#include <linux/of_gpio.h>
+#include "msm_flash.h"
+#include "msm_camera_dt_util.h"
+#include "msm_cci.h"
+
+#undef CDBG
+#define CDBG(fmt, args...) pr_err(fmt, ##args)
+
+DEFINE_MSM_MUTEX(msm_flash_mutex);
+
+static struct v4l2_file_operations msm_flash_v4l2_subdev_fops;
+static struct led_trigger *torch_trigger;
+
+static const struct of_device_id msm_flash_dt_match[] = {
+ {.compatible = "qcom,camera-flash", .data = NULL},
+ {}
+};
+
+static struct msm_flash_table msm_i2c_flash_table;
+static struct msm_flash_table msm_gpio_flash_table;
+static struct msm_flash_table msm_pmic_flash_table;
+
+static struct msm_flash_table *flash_table[] = {
+ &msm_i2c_flash_table,
+ &msm_gpio_flash_table,
+ &msm_pmic_flash_table
+};
+
+static struct msm_camera_i2c_fn_t msm_sensor_cci_func_tbl = {
+ .i2c_read = msm_camera_cci_i2c_read,
+ .i2c_read_seq = msm_camera_cci_i2c_read_seq,
+ .i2c_write = msm_camera_cci_i2c_write,
+ .i2c_write_table = msm_camera_cci_i2c_write_table,
+ .i2c_write_seq_table = msm_camera_cci_i2c_write_seq_table,
+ .i2c_write_table_w_microdelay =
+ msm_camera_cci_i2c_write_table_w_microdelay,
+ .i2c_util = msm_sensor_cci_i2c_util,
+ .i2c_poll = msm_camera_cci_i2c_poll,
+};
+
+void msm_torch_brightness_set(struct led_classdev *led_cdev,
+ enum led_brightness value)
+{
+ if (!torch_trigger) {
+ pr_err("No torch trigger found, can't set brightness\n");
+ return;
+ }
+
+ led_trigger_event(torch_trigger, value);
+};
+
+static struct led_classdev msm_torch_led[MAX_LED_TRIGGERS] = {
+ {
+ .name = "torch-light0",
+ .brightness_set = msm_torch_brightness_set,
+ .brightness = LED_OFF,
+ },
+ {
+ .name = "torch-light1",
+ .brightness_set = msm_torch_brightness_set,
+ .brightness = LED_OFF,
+ },
+ {
+ .name = "torch-light2",
+ .brightness_set = msm_torch_brightness_set,
+ .brightness = LED_OFF,
+ },
+};
+
+static int32_t msm_torch_create_classdev(struct platform_device *pdev,
+ void *data)
+{
+ int32_t rc = 0;
+ int32_t i = 0;
+ struct msm_flash_ctrl_t *fctrl =
+ (struct msm_flash_ctrl_t *)data;
+
+ if (!fctrl) {
+ pr_err("Invalid fctrl\n");
+ return -EINVAL;
+ }
+
+ for (i = 0; i < fctrl->torch_num_sources; i++) {
+ if (fctrl->torch_trigger[i]) {
+ torch_trigger = fctrl->torch_trigger[i];
+ CDBG("%s:%d msm_torch_brightness_set for torch %d",
+ __func__, __LINE__, i);
+ msm_torch_brightness_set(&msm_torch_led[i],
+ LED_OFF);
+
+ rc = led_classdev_register(&pdev->dev,
+ &msm_torch_led[i]);
+ if (rc) {
+ pr_err("Failed to register %d led dev. rc = %d\n",
+ i, rc);
+ return rc;
+ }
+ } else {
+ pr_err("Invalid fctrl->torch_trigger[%d]\n", i);
+ return -EINVAL;
+ }
+ }
+
+ return 0;
+};
+
+static int32_t msm_flash_get_subdev_id(
+ struct msm_flash_ctrl_t *flash_ctrl, void *arg)
+{
+ uint32_t *subdev_id = (uint32_t *)arg;
+ CDBG("Enter\n");
+ if (!subdev_id) {
+ pr_err("failed\n");
+ return -EINVAL;
+ }
+ if (flash_ctrl->flash_device_type == MSM_CAMERA_PLATFORM_DEVICE)
+ *subdev_id = flash_ctrl->pdev->id;
+ else
+ *subdev_id = flash_ctrl->subdev_id;
+
+ CDBG("subdev_id %d\n", *subdev_id);
+ CDBG("Exit\n");
+ return 0;
+}
+
+static int32_t msm_flash_i2c_write_table(
+ struct msm_flash_ctrl_t *flash_ctrl,
+ struct msm_camera_i2c_reg_setting_array *settings)
+{
+ struct msm_camera_i2c_reg_setting conf_array;
+
+ conf_array.addr_type = settings->addr_type;
+ conf_array.data_type = settings->data_type;
+ conf_array.delay = settings->delay;
+ conf_array.reg_setting = settings->reg_setting_a;
+ conf_array.size = settings->size;
+ flash_ctrl->flash_i2c_client.addr_type = conf_array.addr_type;
+
+ return flash_ctrl->flash_i2c_client.i2c_func_tbl->i2c_write_table(
+ &flash_ctrl->flash_i2c_client, &conf_array);
+}
+
+#ifdef CONFIG_COMPAT
+static void msm_flash_copy_power_settings_compat(
+ struct msm_sensor_power_setting *ps,
+ struct msm_sensor_power_setting32 *ps32, uint32_t size)
+{
+ uint16_t i = 0;
+
+ for (i = 0; i < size; i++) {
+ ps[i].config_val = ps32[i].config_val;
+ ps[i].delay = ps32[i].delay;
+ ps[i].seq_type = ps32[i].seq_type;
+ ps[i].seq_val = ps32[i].seq_val;
+ }
+}
+#endif
+
+static int32_t msm_flash_i2c_init(
+ struct msm_flash_ctrl_t *flash_ctrl,
+ struct msm_flash_cfg_data_t *flash_data)
+{
+ int32_t rc = 0;
+ struct msm_flash_init_info_t *flash_init_info =
+ flash_data->cfg.flash_init_info;
+ struct msm_camera_i2c_reg_setting_array *settings = NULL;
+ struct msm_camera_cci_client *cci_client = NULL;
+#ifdef CONFIG_COMPAT
+ struct msm_sensor_power_setting_array32 *power_setting_array32 = NULL;
+#endif
+ if (!flash_init_info || !flash_init_info->power_setting_array) {
+ pr_err("%s:%d failed: Null pointer\n", __func__, __LINE__);
+ return -EFAULT;
+ }
+
+#ifdef CONFIG_COMPAT
+ if (is_compat_task()) {
+ power_setting_array32 = kzalloc(
+ sizeof(struct msm_sensor_power_setting_array32),
+ GFP_KERNEL);
+ if (!power_setting_array32) {
+ pr_err("%s mem allocation failed %d\n",
+ __func__, __LINE__);
+ return -ENOMEM;
+ }
+
+ if (copy_from_user(power_setting_array32,
+ (void *)flash_init_info->power_setting_array,
+ sizeof(struct msm_sensor_power_setting_array32))) {
+ pr_err("%s copy_from_user failed %d\n",
+ __func__, __LINE__);
+ kfree(power_setting_array32);
+ return -EFAULT;
+ }
+
+ flash_ctrl->power_setting_array.size =
+ power_setting_array32->size;
+ flash_ctrl->power_setting_array.size_down =
+ power_setting_array32->size_down;
+ flash_ctrl->power_setting_array.power_down_setting =
+ compat_ptr(power_setting_array32->power_down_setting);
+ flash_ctrl->power_setting_array.power_setting =
+ compat_ptr(power_setting_array32->power_setting);
+
+ /* Validate power_up array size and power_down array size */
+ if ((!flash_ctrl->power_setting_array.size) ||
+ (flash_ctrl->power_setting_array.size >
+ MAX_POWER_CONFIG) ||
+ (!flash_ctrl->power_setting_array.size_down) ||
+ (flash_ctrl->power_setting_array.size_down >
+ MAX_POWER_CONFIG)) {
+
+ pr_err("failed: invalid size %d, size_down %d",
+ flash_ctrl->power_setting_array.size,
+ flash_ctrl->power_setting_array.size_down);
+ kfree(power_setting_array32);
+ power_setting_array32 = NULL;
+ return -EINVAL;
+ }
+ /* Copy the settings from compat struct to regular struct */
+ msm_flash_copy_power_settings_compat(
+ flash_ctrl->power_setting_array.power_setting_a,
+ power_setting_array32->power_setting_a,
+ flash_ctrl->power_setting_array.size);
+
+ msm_flash_copy_power_settings_compat(
+ flash_ctrl->power_setting_array.power_down_setting_a,
+ power_setting_array32->power_down_setting_a,
+ flash_ctrl->power_setting_array.size_down);
+ } else
+#endif
+ if (copy_from_user(&flash_ctrl->power_setting_array,
+ (void *)flash_init_info->power_setting_array,
+ sizeof(struct msm_sensor_power_setting_array))) {
+ pr_err("%s copy_from_user failed %d\n", __func__, __LINE__);
+ return -EFAULT;
+ }
+
+ if (flash_ctrl->flash_device_type == MSM_CAMERA_PLATFORM_DEVICE) {
+ cci_client = flash_ctrl->flash_i2c_client.cci_client;
+ cci_client->sid = flash_init_info->slave_addr >> 1;
+ cci_client->retries = 3;
+ cci_client->id_map = 0;
+ cci_client->i2c_freq_mode = flash_init_info->i2c_freq_mode;
+ }
+
+ flash_ctrl->power_info.power_setting =
+ flash_ctrl->power_setting_array.power_setting_a;
+ flash_ctrl->power_info.power_down_setting =
+ flash_ctrl->power_setting_array.power_down_setting_a;
+ flash_ctrl->power_info.power_setting_size =
+ flash_ctrl->power_setting_array.size;
+ flash_ctrl->power_info.power_down_setting_size =
+ flash_ctrl->power_setting_array.size_down;
+
+ rc = msm_camera_fill_vreg_params(
+ flash_ctrl->power_info.cam_vreg,
+ flash_ctrl->power_info.num_vreg,
+ flash_ctrl->power_info.power_setting,
+ flash_ctrl->power_info.power_setting_size);
+ if (rc < 0) {
+ pr_err("%s:%d failed in camera_fill_vreg_params rc %d",
+ __func__, __LINE__, rc);
+ return rc;
+ }
+
+ /* Parse and fill vreg params for powerdown settings*/
+ rc = msm_camera_fill_vreg_params(
+ flash_ctrl->power_info.cam_vreg,
+ flash_ctrl->power_info.num_vreg,
+ flash_ctrl->power_info.power_down_setting,
+ flash_ctrl->power_info.power_down_setting_size);
+ if (rc < 0) {
+ pr_err("%s:%d failed msm_camera_fill_vreg_params for PDOWN rc %d",
+ __func__, __LINE__, rc);
+ return rc;
+ }
+
+ rc = msm_camera_power_up(&flash_ctrl->power_info,
+ flash_ctrl->flash_device_type,
+ &flash_ctrl->flash_i2c_client);
+ if (rc < 0) {
+ pr_err("%s msm_camera_power_up failed %d\n",
+ __func__, __LINE__);
+ goto msm_flash_i2c_init_fail;
+ }
+
+ if (flash_data->cfg.flash_init_info->settings) {
+ settings = kzalloc(sizeof(
+ struct msm_camera_i2c_reg_setting_array), GFP_KERNEL);
+ if (!settings) {
+ pr_err("%s mem allocation failed %d\n",
+ __func__, __LINE__);
+ return -ENOMEM;
+ }
+
+ if (copy_from_user(settings, (void *)flash_init_info->settings,
+ sizeof(struct msm_camera_i2c_reg_setting_array))) {
+ kfree(settings);
+ pr_err("%s copy_from_user failed %d\n",
+ __func__, __LINE__);
+ return -EFAULT;
+ }
+
+ rc = msm_flash_i2c_write_table(flash_ctrl, settings);
+ kfree(settings);
+
+ if (rc < 0) {
+ pr_err("%s:%d msm_flash_i2c_write_table rc %d failed\n",
+ __func__, __LINE__, rc);
+ }
+ }
+
+ return 0;
+
+msm_flash_i2c_init_fail:
+ return rc;
+}
+
+static int32_t msm_flash_gpio_init(
+ struct msm_flash_ctrl_t *flash_ctrl,
+ struct msm_flash_cfg_data_t *flash_data)
+{
+ int32_t i = 0;
+ int32_t rc = 0;
+
+ CDBG("Enter");
+ for (i = 0; i < flash_ctrl->flash_num_sources; i++)
+ flash_ctrl->flash_op_current[i] = LED_FULL;
+
+ for (i = 0; i < flash_ctrl->torch_num_sources; i++)
+ flash_ctrl->torch_op_current[i] = LED_HALF;
+
+ for (i = 0; i < flash_ctrl->torch_num_sources; i++) {
+ if (!flash_ctrl->torch_trigger[i]) {
+ if (i < flash_ctrl->flash_num_sources)
+ flash_ctrl->torch_trigger[i] =
+ flash_ctrl->flash_trigger[i];
+ else
+ flash_ctrl->torch_trigger[i] =
+ flash_ctrl->flash_trigger[
+ flash_ctrl->flash_num_sources - 1];
+ }
+ }
+
+ rc = flash_ctrl->func_tbl->camera_flash_off(flash_ctrl, flash_data);
+
+ CDBG("Exit");
+ return rc;
+}
+
+static int32_t msm_flash_i2c_release(
+ struct msm_flash_ctrl_t *flash_ctrl)
+{
+ int32_t rc = 0;
+
+ if (!(&flash_ctrl->power_info) || !(&flash_ctrl->flash_i2c_client)) {
+ pr_err("%s:%d failed: %p %p\n",
+ __func__, __LINE__, &flash_ctrl->power_info,
+ &flash_ctrl->flash_i2c_client);
+ return -EINVAL;
+ }
+
+ rc = msm_camera_power_down(&flash_ctrl->power_info,
+ flash_ctrl->flash_device_type,
+ &flash_ctrl->flash_i2c_client);
+ if (rc < 0) {
+ pr_err("%s msm_camera_power_down failed %d\n",
+ __func__, __LINE__);
+ return -EINVAL;
+ }
+ flash_ctrl->flash_state = MSM_CAMERA_FLASH_RELEASE;
+ return 0;
+}
+
+static int32_t msm_flash_off(struct msm_flash_ctrl_t *flash_ctrl,
+ struct msm_flash_cfg_data_t *flash_data)
+{
+ int32_t i = 0;
+
+ CDBG("Enter\n");
+
+ for (i = 0; i < flash_ctrl->flash_num_sources; i++)
+ if (flash_ctrl->flash_trigger[i])
+ led_trigger_event(flash_ctrl->flash_trigger[i], 0);
+
+ for (i = 0; i < flash_ctrl->torch_num_sources; i++)
+ if (flash_ctrl->torch_trigger[i])
+ led_trigger_event(flash_ctrl->torch_trigger[i], 0);
+ if (flash_ctrl->switch_trigger)
+ led_trigger_event(flash_ctrl->switch_trigger, 0);
+
+ CDBG("Exit\n");
+ return 0;
+}
+static int32_t msm_flash_i2c_read_setting_array(
+ struct msm_flash_ctrl_t *flash_ctrl,
+ struct msm_flash_cfg_data_t *flash_data)
+{
+ if (!flash_data->cfg.read_config) {
+ pr_err("%s:%d failed: Null pointer\n", __func__, __LINE__);
+ return -EFAULT;
+ }
+
+ return flash_ctrl->flash_i2c_client.i2c_func_tbl->i2c_read(
+ &flash_ctrl->flash_i2c_client,
+ flash_data->cfg.read_config->reg_addr,
+ &flash_data->cfg.read_config->data,
+ MSM_CAMERA_I2C_BYTE_DATA);
+}
+
+static int32_t msm_flash_i2c_write_setting_array(
+ struct msm_flash_ctrl_t *flash_ctrl,
+ struct msm_flash_cfg_data_t *flash_data)
+{
+ int32_t rc = 0;
+ struct msm_camera_i2c_reg_setting_array *settings = NULL;
+
+ if (!flash_data->cfg.settings) {
+ pr_err("%s:%d failed: Null pointer\n", __func__, __LINE__);
+ return -EFAULT;
+ }
+
+ settings = kzalloc(sizeof(struct msm_camera_i2c_reg_setting_array),
+ GFP_KERNEL);
+ if (!settings) {
+ pr_err("%s mem allocation failed %d\n", __func__, __LINE__);
+ return -ENOMEM;
+ }
+
+ if (copy_from_user(settings, (void *)flash_data->cfg.settings,
+ sizeof(struct msm_camera_i2c_reg_setting_array))) {
+ kfree(settings);
+ pr_err("%s copy_from_user failed %d\n", __func__, __LINE__);
+ return -EFAULT;
+ }
+
+ rc = msm_flash_i2c_write_table(flash_ctrl, settings);
+ kfree(settings);
+
+ if (rc < 0) {
+ pr_err("%s:%d msm_flash_i2c_write_table rc = %d failed\n",
+ __func__, __LINE__, rc);
+ }
+ return rc;
+}
+
+static int32_t msm_flash_init(
+ struct msm_flash_ctrl_t *flash_ctrl,
+ struct msm_flash_cfg_data_t *flash_data)
+{
+ uint32_t i = 0;
+ int32_t rc = -EFAULT;
+ enum msm_flash_driver_type flash_driver_type = FLASH_DRIVER_DEFAULT;
+
+ CDBG("Enter");
+
+ if (flash_ctrl->flash_state == MSM_CAMERA_FLASH_INIT) {
+ pr_err("%s:%d Invalid flash state = %d",
+ __func__, __LINE__, flash_ctrl->flash_state);
+ return 0;
+ }
+
+ if (flash_data->cfg.flash_init_info->flash_driver_type ==
+ FLASH_DRIVER_DEFAULT) {
+ flash_driver_type = flash_ctrl->flash_driver_type;
+ for (i = 0; i < MAX_LED_TRIGGERS; i++) {
+ flash_data->flash_current[i] =
+ flash_ctrl->flash_max_current[i];
+ flash_data->flash_duration[i] =
+ flash_ctrl->flash_max_duration[i];
+ }
+ } else if (flash_data->cfg.flash_init_info->flash_driver_type ==
+ flash_ctrl->flash_driver_type) {
+ flash_driver_type = flash_ctrl->flash_driver_type;
+ for (i = 0; i < MAX_LED_TRIGGERS; i++) {
+ flash_ctrl->flash_max_current[i] =
+ flash_data->flash_current[i];
+ flash_ctrl->flash_max_duration[i] =
+ flash_data->flash_duration[i];
+ }
+ }
+
+ if (flash_driver_type == FLASH_DRIVER_DEFAULT) {
+ pr_err("%s:%d invalid flash_driver_type", __func__, __LINE__);
+ return -EINVAL;
+ }
+
+ for (i = 0; i < ARRAY_SIZE(flash_table); i++) {
+ if (flash_driver_type == flash_table[i]->flash_driver_type) {
+ flash_ctrl->func_tbl = &flash_table[i]->func_tbl;
+ rc = 0;
+ }
+ }
+
+ if (rc < 0) {
+ pr_err("%s:%d failed invalid flash_driver_type %d\n",
+ __func__, __LINE__,
+ flash_data->cfg.flash_init_info->flash_driver_type);
+ }
+
+ if (flash_ctrl->func_tbl->camera_flash_init) {
+ rc = flash_ctrl->func_tbl->camera_flash_init(
+ flash_ctrl, flash_data);
+ if (rc < 0) {
+ pr_err("%s:%d camera_flash_init failed rc = %d",
+ __func__, __LINE__, rc);
+ return rc;
+ }
+ }
+
+ flash_ctrl->flash_state = MSM_CAMERA_FLASH_INIT;
+
+ CDBG("Exit");
+ return 0;
+}
+
+static int32_t msm_flash_low(
+ struct msm_flash_ctrl_t *flash_ctrl,
+ struct msm_flash_cfg_data_t *flash_data)
+{
+ uint32_t curr = 0, max_current = 0;
+ int32_t i = 0;
+
+ CDBG("Enter\n");
+ /* Turn off flash triggers */
+ for (i = 0; i < flash_ctrl->flash_num_sources; i++)
+ if (flash_ctrl->flash_trigger[i])
+ led_trigger_event(flash_ctrl->flash_trigger[i], 0);
+
+ /* Turn on flash triggers */
+ for (i = 0; i < flash_ctrl->torch_num_sources; i++) {
+ if (flash_ctrl->torch_trigger[i]) {
+ max_current = flash_ctrl->torch_max_current[i];
+ if (flash_data->flash_current[i] >= 0 &&
+ flash_data->flash_current[i] <=
+ max_current) {
+ curr = flash_data->flash_current[i];
+ } else {
+ curr = flash_ctrl->torch_op_current[i];
+ CDBG("LED current clamped to %d\n",
+ curr);
+ }
+ CDBG("low_flash_current[%d] = %d", i, curr);
+ led_trigger_event(flash_ctrl->torch_trigger[i],
+ curr);
+ }
+ }
+ if (flash_ctrl->switch_trigger)
+ led_trigger_event(flash_ctrl->switch_trigger, 1);
+ CDBG("Exit\n");
+ return 0;
+}
+
+static int32_t msm_flash_high(
+ struct msm_flash_ctrl_t *flash_ctrl,
+ struct msm_flash_cfg_data_t *flash_data)
+{
+ int32_t curr = 0;
+ int32_t max_current = 0;
+ int32_t i = 0;
+
+ /* Turn off torch triggers */
+ for (i = 0; i < flash_ctrl->torch_num_sources; i++)
+ if (flash_ctrl->torch_trigger[i])
+ led_trigger_event(flash_ctrl->torch_trigger[i], 0);
+
+ /* Turn on flash triggers */
+ for (i = 0; i < flash_ctrl->flash_num_sources; i++) {
+ if (flash_ctrl->flash_trigger[i]) {
+ max_current = flash_ctrl->flash_max_current[i];
+ if (flash_data->flash_current[i] >= 0 &&
+ flash_data->flash_current[i] <=
+ max_current) {
+ curr = flash_data->flash_current[i];
+ } else {
+ curr = flash_ctrl->flash_op_current[i];
+ CDBG("LED flash_current[%d] clamped %d\n",
+ i, curr);
+ }
+ CDBG("high_flash_current[%d] = %d", i, curr);
+ led_trigger_event(flash_ctrl->flash_trigger[i],
+ curr);
+ }
+ }
+ if (flash_ctrl->switch_trigger)
+ led_trigger_event(flash_ctrl->switch_trigger, 1);
+ return 0;
+}
+
+static int32_t msm_flash_release(
+ struct msm_flash_ctrl_t *flash_ctrl)
+{
+ int32_t rc = 0;
+ if (flash_ctrl->flash_state == MSM_CAMERA_FLASH_RELEASE) {
+ pr_err("%s:%d Invalid flash state = %d",
+ __func__, __LINE__, flash_ctrl->flash_state);
+ return 0;
+ }
+
+ rc = flash_ctrl->func_tbl->camera_flash_off(flash_ctrl, NULL);
+ if (rc < 0) {
+ pr_err("%s:%d camera_flash_init failed rc = %d",
+ __func__, __LINE__, rc);
+ return rc;
+ }
+ flash_ctrl->flash_state = MSM_CAMERA_FLASH_RELEASE;
+ return 0;
+}
+
+static int32_t msm_flash_config(struct msm_flash_ctrl_t *flash_ctrl,
+ void __user *argp)
+{
+ int32_t rc = -EINVAL;
+ struct msm_flash_cfg_data_t *flash_data =
+ (struct msm_flash_cfg_data_t *) argp;
+
+ mutex_lock(flash_ctrl->flash_mutex);
+
+ CDBG("Enter %s type %d\n", __func__, flash_data->cfg_type);
+
+ switch (flash_data->cfg_type) {
+ case CFG_FLASH_INIT:
+ rc = msm_flash_init(flash_ctrl, flash_data);
+ break;
+ case CFG_FLASH_RELEASE:
+ if (flash_ctrl->flash_state == MSM_CAMERA_FLASH_INIT)
+ rc = flash_ctrl->func_tbl->camera_flash_release(
+ flash_ctrl);
+ break;
+ case CFG_FLASH_OFF:
+ if (flash_ctrl->flash_state == MSM_CAMERA_FLASH_INIT)
+ rc = flash_ctrl->func_tbl->camera_flash_off(
+ flash_ctrl, flash_data);
+ break;
+ case CFG_FLASH_LOW:
+ if (flash_ctrl->flash_state == MSM_CAMERA_FLASH_INIT)
+ rc = flash_ctrl->func_tbl->camera_flash_low(
+ flash_ctrl, flash_data);
+ break;
+ case CFG_FLASH_HIGH:
+ if (flash_ctrl->flash_state == MSM_CAMERA_FLASH_INIT)
+ rc = flash_ctrl->func_tbl->camera_flash_high(
+ flash_ctrl, flash_data);
+ break;
+ case CFG_FLASH_READ_I2C:
+ if (flash_ctrl->flash_state == MSM_CAMERA_FLASH_INIT)
+ rc = flash_ctrl->func_tbl->camera_flash_read(
+ flash_ctrl, flash_data);
+ break;
+ case CFG_FLASH_WRITE_I2C:
+ if (flash_ctrl->flash_state == MSM_CAMERA_FLASH_INIT)
+ rc = flash_ctrl->func_tbl->camera_flash_write(
+ flash_ctrl, flash_data);
+ break;
+ default:
+ rc = -EFAULT;
+ break;
+ }
+
+ mutex_unlock(flash_ctrl->flash_mutex);
+
+ CDBG("Exit %s type %d\n", __func__, flash_data->cfg_type);
+
+ return rc;
+}
+
+static long msm_flash_subdev_ioctl(struct v4l2_subdev *sd,
+ unsigned int cmd, void *arg)
+{
+ struct msm_flash_ctrl_t *fctrl = NULL;
+ void __user *argp = (void __user *)arg;
+
+ CDBG("Enter\n");
+
+ if (!sd) {
+ pr_err("sd NULL\n");
+ return -EINVAL;
+ }
+ fctrl = v4l2_get_subdevdata(sd);
+ if (!fctrl) {
+ pr_err("fctrl NULL\n");
+ return -EINVAL;
+ }
+ switch (cmd) {
+ case VIDIOC_MSM_SENSOR_GET_SUBDEV_ID:
+ return msm_flash_get_subdev_id(fctrl, argp);
+ case VIDIOC_MSM_FLASH_CFG:
+ return msm_flash_config(fctrl, argp);
+ case MSM_SD_NOTIFY_FREEZE:
+ return 0;
+ case MSM_SD_UNNOTIFY_FREEZE:
+ return 0;
+ case MSM_SD_SHUTDOWN:
+ if (!fctrl->func_tbl) {
+ pr_err("fctrl->func_tbl NULL\n");
+ return -EINVAL;
+ } else {
+ return fctrl->func_tbl->camera_flash_release(fctrl);
+ }
+ default:
+ pr_err_ratelimited("invalid cmd %d\n", cmd);
+ return -ENOIOCTLCMD;
+ }
+ CDBG("Exit\n");
+}
+
+static struct v4l2_subdev_core_ops msm_flash_subdev_core_ops = {
+ .ioctl = msm_flash_subdev_ioctl,
+};
+
+static struct v4l2_subdev_ops msm_flash_subdev_ops = {
+ .core = &msm_flash_subdev_core_ops,
+};
+
+static const struct v4l2_subdev_internal_ops msm_flash_internal_ops;
+
+static int32_t msm_flash_get_pmic_source_info(
+ struct device_node *of_node,
+ struct msm_flash_ctrl_t *fctrl)
+{
+ int32_t rc = 0;
+ uint32_t count = 0, i = 0;
+ struct device_node *flash_src_node = NULL;
+ struct device_node *torch_src_node = NULL;
+ struct device_node *switch_src_node = NULL;
+
+ switch_src_node = of_parse_phandle(of_node, "qcom,switch-source", 0);
+ if (!switch_src_node) {
+ CDBG("%s:%d switch_src_node NULL\n", __func__, __LINE__);
+ } else {
+ rc = of_property_read_string(switch_src_node,
+ "qcom,default-led-trigger",
+ &fctrl->switch_trigger_name);
+ if (rc < 0) {
+ rc = of_property_read_string(switch_src_node,
+ "linux,default-trigger",
+ &fctrl->switch_trigger_name);
+ if (rc < 0)
+ pr_err("default-trigger read failed\n");
+ }
+ of_node_put(switch_src_node);
+ switch_src_node = NULL;
+ if (!rc) {
+ CDBG("switch trigger %s\n",
+ fctrl->switch_trigger_name);
+ led_trigger_register_simple(
+ fctrl->switch_trigger_name,
+ &fctrl->switch_trigger);
+ }
+ }
+
+ if (of_get_property(of_node, "qcom,flash-source", &count)) {
+ count /= sizeof(uint32_t);
+ CDBG("count %d\n", count);
+ if (count > MAX_LED_TRIGGERS) {
+ pr_err("invalid count\n");
+ return -EINVAL;
+ }
+ fctrl->flash_num_sources = count;
+ CDBG("%s:%d flash_num_sources = %d",
+ __func__, __LINE__, fctrl->flash_num_sources);
+ for (i = 0; i < count; i++) {
+ flash_src_node = of_parse_phandle(of_node,
+ "qcom,flash-source", i);
+ if (!flash_src_node) {
+ pr_err("flash_src_node NULL\n");
+ continue;
+ }
+
+ rc = of_property_read_string(flash_src_node,
+ "qcom,default-led-trigger",
+ &fctrl->flash_trigger_name[i]);
+ if (rc < 0) {
+ rc = of_property_read_string(flash_src_node,
+ "linux,default-trigger",
+ &fctrl->flash_trigger_name[i]);
+ if (rc < 0) {
+ pr_err("default-trigger read failed\n");
+ of_node_put(flash_src_node);
+ continue;
+ }
+ }
+
+ CDBG("default trigger %s\n",
+ fctrl->flash_trigger_name[i]);
+
+ /* Read operational-current */
+ rc = of_property_read_u32(flash_src_node,
+ "qcom,current",
+ &fctrl->flash_op_current[i]);
+ if (rc < 0) {
+ pr_err("current: read failed\n");
+ of_node_put(flash_src_node);
+ continue;
+ }
+
+ /* Read max-current */
+ rc = of_property_read_u32(flash_src_node,
+ "qcom,max-current",
+ &fctrl->flash_max_current[i]);
+ if (rc < 0) {
+ pr_err("current: read failed\n");
+ of_node_put(flash_src_node);
+ continue;
+ }
+
+ /* Read max-duration */
+ rc = of_property_read_u32(flash_src_node,
+ "qcom,duration",
+ &fctrl->flash_max_duration[i]);
+ if (rc < 0) {
+ pr_err("duration: read failed\n");
+ of_node_put(flash_src_node);
+ /* Non-fatal; this property is optional */
+ }
+
+ of_node_put(flash_src_node);
+
+ CDBG("max_current[%d] %d\n",
+ i, fctrl->flash_op_current[i]);
+
+ led_trigger_register_simple(
+ fctrl->flash_trigger_name[i],
+ &fctrl->flash_trigger[i]);
+ }
+ if (fctrl->flash_driver_type == FLASH_DRIVER_DEFAULT)
+ fctrl->flash_driver_type = FLASH_DRIVER_PMIC;
+ CDBG("%s:%d fctrl->flash_driver_type = %d", __func__, __LINE__,
+ fctrl->flash_driver_type);
+ }
+
+ if (of_get_property(of_node, "qcom,torch-source", &count)) {
+ count /= sizeof(uint32_t);
+ CDBG("count %d\n", count);
+ if (count > MAX_LED_TRIGGERS) {
+ pr_err("invalid count\n");
+ return -EINVAL;
+ }
+ fctrl->torch_num_sources = count;
+ CDBG("%s:%d torch_num_sources = %d",
+ __func__, __LINE__, fctrl->torch_num_sources);
+ for (i = 0; i < count; i++) {
+ torch_src_node = of_parse_phandle(of_node,
+ "qcom,torch-source", i);
+ if (!torch_src_node) {
+ pr_err("torch_src_node NULL\n");
+ continue;
+ }
+
+ rc = of_property_read_string(torch_src_node,
+ "qcom,default-led-trigger",
+ &fctrl->torch_trigger_name[i]);
+ if (rc < 0) {
+ rc = of_property_read_string(torch_src_node,
+ "linux,default-trigger",
+ &fctrl->torch_trigger_name[i]);
+ if (rc < 0) {
+ pr_err("default-trigger read failed\n");
+ of_node_put(torch_src_node);
+ continue;
+ }
+ }
+
+ CDBG("default trigger %s\n",
+ fctrl->torch_trigger_name[i]);
+
+ /* Read operational-current */
+ rc = of_property_read_u32(torch_src_node,
+ "qcom,current",
+ &fctrl->torch_op_current[i]);
+ if (rc < 0) {
+ pr_err("current: read failed\n");
+ of_node_put(torch_src_node);
+ continue;
+ }
+
+ /* Read max-current */
+ rc = of_property_read_u32(torch_src_node,
+ "qcom,max-current",
+ &fctrl->torch_max_current[i]);
+ if (rc < 0) {
+ pr_err("current: read failed\n");
+ of_node_put(torch_src_node);
+ continue;
+ }
+
+ of_node_put(torch_src_node);
+
+ CDBG("max_current[%d] %d\n",
+ i, fctrl->torch_op_current[i]);
+
+ led_trigger_register_simple(
+ fctrl->torch_trigger_name[i],
+ &fctrl->torch_trigger[i]);
+ }
+ if (fctrl->flash_driver_type == FLASH_DRIVER_DEFAULT)
+ fctrl->flash_driver_type = FLASH_DRIVER_PMIC;
+ CDBG("%s:%d fctrl->flash_driver_type = %d", __func__, __LINE__,
+ fctrl->flash_driver_type);
+ }
+
+ return 0;
+}
+
+static int32_t msm_flash_get_dt_data(struct device_node *of_node,
+ struct msm_flash_ctrl_t *fctrl)
+{
+ int32_t rc = 0;
+ struct msm_camera_power_ctrl_t *power_info =
+ &fctrl->power_info;
+
+ CDBG("called\n");
+
+ if (!of_node) {
+ pr_err("of_node NULL\n");
+ return -EINVAL;
+ }
+
+ /* Read the sub device */
+ rc = of_property_read_u32(of_node, "cell-index", &fctrl->pdev->id);
+ if (rc < 0) {
+ pr_err("failed rc %d\n", rc);
+ return rc;
+ }
+
+ CDBG("subdev id %d\n", fctrl->subdev_id);
+
+ fctrl->flash_driver_type = FLASH_DRIVER_DEFAULT;
+
+ /* Read the CCI master. Use M0 if not available in the node */
+ rc = of_property_read_u32(of_node, "qcom,cci-master",
+ &fctrl->cci_i2c_master);
+ CDBG("%s qcom,cci-master %d, rc %d\n", __func__, fctrl->cci_i2c_master,
+ rc);
+ if (rc < 0) {
+ /* Set default master 0 */
+ fctrl->cci_i2c_master = MASTER_0;
+ rc = 0;
+ } else {
+ fctrl->flash_driver_type = FLASH_DRIVER_I2C;
+ }
+
+ /* Read the gpio information from device tree */
+ rc = msm_sensor_driver_get_gpio_data(
+ &(fctrl->power_info.gpio_conf), of_node);
+ if (rc < 0) {
+ 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)
+/*+Begin. wangdw10. Change flash type to PMIC for karate/karateplus project.2016.06.23*/
+ fctrl->flash_driver_type = FLASH_DRIVER_PMIC;
+/*+End.*/
+ CDBG("%s:%d fctrl->flash_driver_type = %d", __func__, __LINE__,
+ fctrl->flash_driver_type);
+
+ /* Read the regulator information from device tree */
+ rc = msm_camera_get_dt_vreg_data(of_node, &power_info->cam_vreg,
+ &power_info->num_vreg);
+ if (rc < 0) {
+ pr_err("%s:%d msm_camera_get_dt_vreg_data failed rc %d\n",
+ __func__, __LINE__, rc);
+ return rc;
+ }
+
+ /* Read the flash and torch source info from device tree node */
+ rc = msm_flash_get_pmic_source_info(of_node, fctrl);
+ if (rc < 0) {
+ pr_err("%s:%d msm_flash_get_pmic_source_info failed rc %d\n",
+ __func__, __LINE__, rc);
+ return rc;
+ }
+ return rc;
+}
+
+#ifdef CONFIG_COMPAT
+static long msm_flash_subdev_do_ioctl(
+ struct file *file, unsigned int cmd, void *arg)
+{
+ int32_t i = 0;
+ int32_t rc = 0;
+ struct video_device *vdev;
+ struct v4l2_subdev *sd;
+ struct msm_flash_cfg_data_t32 *u32;
+ struct msm_flash_cfg_data_t flash_data;
+ struct msm_flash_init_info_t32 flash_init_info32;
+ struct msm_flash_init_info_t flash_init_info;
+
+ CDBG("Enter");
+
+ if (!file || !arg) {
+ pr_err("%s:failed NULL parameter\n", __func__);
+ return -EINVAL;
+ }
+ vdev = video_devdata(file);
+ sd = vdev_to_v4l2_subdev(vdev);
+ u32 = (struct msm_flash_cfg_data_t32 *)arg;
+
+ flash_data.cfg_type = u32->cfg_type;
+ for (i = 0; i < MAX_LED_TRIGGERS; i++) {
+ flash_data.flash_current[i] = u32->flash_current[i];
+ flash_data.flash_duration[i] = u32->flash_duration[i];
+ }
+ switch (cmd) {
+ case VIDIOC_MSM_FLASH_CFG32:
+ cmd = VIDIOC_MSM_FLASH_CFG;
+ switch (flash_data.cfg_type) {
+ case CFG_FLASH_OFF:
+ case CFG_FLASH_LOW:
+ case CFG_FLASH_HIGH:
+ case CFG_FLASH_READ_I2C:
+ case CFG_FLASH_WRITE_I2C:
+ flash_data.cfg.settings = compat_ptr(u32->cfg.settings);
+ break;
+ case CFG_FLASH_INIT:
+ flash_data.cfg.flash_init_info = &flash_init_info;
+ if (copy_from_user(&flash_init_info32,
+ (void *)compat_ptr(u32->cfg.flash_init_info),
+ sizeof(struct msm_flash_init_info_t32))) {
+ pr_err("%s copy_from_user failed %d\n",
+ __func__, __LINE__);
+ return -EFAULT;
+ }
+ flash_init_info.flash_driver_type =
+ flash_init_info32.flash_driver_type;
+ flash_init_info.slave_addr =
+ flash_init_info32.slave_addr;
+ flash_init_info.i2c_freq_mode =
+ flash_init_info32.i2c_freq_mode;
+ flash_init_info.settings =
+ compat_ptr(flash_init_info32.settings);
+ flash_init_info.power_setting_array =
+ compat_ptr(
+ flash_init_info32.power_setting_array);
+ break;
+ default:
+ break;
+ }
+ break;
+ default:
+ return msm_flash_subdev_ioctl(sd, cmd, arg);
+ }
+
+ rc = msm_flash_subdev_ioctl(sd, cmd, &flash_data);
+ for (i = 0; i < MAX_LED_TRIGGERS; i++) {
+ u32->flash_current[i] = flash_data.flash_current[i];
+ u32->flash_duration[i] = flash_data.flash_duration[i];
+ }
+ CDBG("Exit");
+ return rc;
+}
+
+static long msm_flash_subdev_fops_ioctl(struct file *file,
+ unsigned int cmd, unsigned long arg)
+{
+ return video_usercopy(file, cmd, arg, msm_flash_subdev_do_ioctl);
+}
+#endif
+static int32_t msm_flash_platform_probe(struct platform_device *pdev)
+{
+ int32_t rc = 0;
+ struct msm_flash_ctrl_t *flash_ctrl = NULL;
+ struct msm_camera_cci_client *cci_client = NULL;
+
+ CDBG("Enter");
+ if (!pdev->dev.of_node) {
+ pr_err("of_node NULL\n");
+ return -EINVAL;
+ }
+
+ flash_ctrl = kzalloc(sizeof(struct msm_flash_ctrl_t), GFP_KERNEL);
+ if (!flash_ctrl) {
+ pr_err("%s:%d failed no memory\n", __func__, __LINE__);
+ return -ENOMEM;
+ }
+
+ memset(flash_ctrl, 0, sizeof(struct msm_flash_ctrl_t));
+
+ flash_ctrl->pdev = pdev;
+
+ rc = msm_flash_get_dt_data(pdev->dev.of_node, flash_ctrl);
+ if (rc < 0) {
+ pr_err("%s:%d msm_flash_get_dt_data failed\n",
+ __func__, __LINE__);
+ kfree(flash_ctrl);
+ return -EINVAL;
+ }
+
+ flash_ctrl->flash_state = MSM_CAMERA_FLASH_RELEASE;
+ flash_ctrl->power_info.dev = &flash_ctrl->pdev->dev;
+ flash_ctrl->flash_device_type = MSM_CAMERA_PLATFORM_DEVICE;
+ flash_ctrl->flash_mutex = &msm_flash_mutex;
+ flash_ctrl->flash_i2c_client.i2c_func_tbl = &msm_sensor_cci_func_tbl;
+ flash_ctrl->flash_i2c_client.cci_client = kzalloc(
+ sizeof(struct msm_camera_cci_client), GFP_KERNEL);
+ if (!flash_ctrl->flash_i2c_client.cci_client) {
+ kfree(flash_ctrl);
+ pr_err("failed no memory\n");
+ return -ENOMEM;
+ }
+
+ cci_client = flash_ctrl->flash_i2c_client.cci_client;
+ cci_client->cci_subdev = msm_cci_get_subdev();
+ cci_client->cci_i2c_master = flash_ctrl->cci_i2c_master;
+
+ /* Initialize sub device */
+ v4l2_subdev_init(&flash_ctrl->msm_sd.sd, &msm_flash_subdev_ops);
+ v4l2_set_subdevdata(&flash_ctrl->msm_sd.sd, flash_ctrl);
+
+ flash_ctrl->msm_sd.sd.internal_ops = &msm_flash_internal_ops;
+ flash_ctrl->msm_sd.sd.flags |= V4L2_SUBDEV_FL_HAS_DEVNODE;
+ snprintf(flash_ctrl->msm_sd.sd.name,
+ ARRAY_SIZE(flash_ctrl->msm_sd.sd.name),
+ "msm_camera_flash");
+ media_entity_init(&flash_ctrl->msm_sd.sd.entity, 0, NULL, 0);
+ flash_ctrl->msm_sd.sd.entity.type = MEDIA_ENT_T_V4L2_SUBDEV;
+ flash_ctrl->msm_sd.sd.entity.group_id = MSM_CAMERA_SUBDEV_FLASH;
+ flash_ctrl->msm_sd.close_seq = MSM_SD_CLOSE_2ND_CATEGORY | 0x1;
+ msm_sd_register(&flash_ctrl->msm_sd);
+
+ CDBG("%s:%d flash sd name = %s", __func__, __LINE__,
+ flash_ctrl->msm_sd.sd.entity.name);
+ msm_cam_copy_v4l2_subdev_fops(&msm_flash_v4l2_subdev_fops);
+#ifdef CONFIG_COMPAT
+ msm_flash_v4l2_subdev_fops.compat_ioctl32 =
+ msm_flash_subdev_fops_ioctl;
+#endif
+ flash_ctrl->msm_sd.sd.devnode->fops = &msm_flash_v4l2_subdev_fops;
+
+ if (flash_ctrl->flash_driver_type == FLASH_DRIVER_PMIC)
+ rc = msm_torch_create_classdev(pdev, flash_ctrl);
+
+ CDBG("probe success\n");
+ return rc;
+}
+
+MODULE_DEVICE_TABLE(of, msm_flash_dt_match);
+
+static struct platform_driver msm_flash_platform_driver = {
+ .probe = msm_flash_platform_probe,
+ .driver = {
+ .name = "qcom,camera-flash",
+ .owner = THIS_MODULE,
+ .of_match_table = msm_flash_dt_match,
+ },
+};
+
+static int __init msm_flash_init_module(void)
+{
+ int32_t rc = 0;
+ CDBG("Enter\n");
+ rc = platform_driver_register(&msm_flash_platform_driver);
+ if (rc)
+ pr_err("platform probe for flash failed");
+
+ return rc;
+}
+
+static void __exit msm_flash_exit_module(void)
+{
+ platform_driver_unregister(&msm_flash_platform_driver);
+ return;
+}
+
+static struct msm_flash_table msm_pmic_flash_table = {
+ .flash_driver_type = FLASH_DRIVER_PMIC,
+ .func_tbl = {
+ .camera_flash_init = NULL,
+ .camera_flash_release = msm_flash_release,
+ .camera_flash_off = msm_flash_off,
+ .camera_flash_low = msm_flash_low,
+ .camera_flash_high = msm_flash_high,
+ },
+};
+
+static struct msm_flash_table msm_gpio_flash_table = {
+ .flash_driver_type = FLASH_DRIVER_GPIO,
+ .func_tbl = {
+ .camera_flash_init = msm_flash_gpio_init,
+ .camera_flash_release = msm_flash_release,
+ .camera_flash_off = msm_flash_off,
+ .camera_flash_low = msm_flash_low,
+ .camera_flash_high = msm_flash_high,
+ },
+};
+
+static struct msm_flash_table msm_i2c_flash_table = {
+ .flash_driver_type = FLASH_DRIVER_I2C,
+ .func_tbl = {
+ .camera_flash_init = msm_flash_i2c_init,
+ .camera_flash_release = msm_flash_i2c_release,
+ .camera_flash_off = msm_flash_i2c_write_setting_array,
+ .camera_flash_low = msm_flash_i2c_write_setting_array,
+ .camera_flash_high = msm_flash_i2c_write_setting_array,
+ .camera_flash_read = msm_flash_i2c_read_setting_array,
+ .camera_flash_write = msm_flash_i2c_write_setting_array,
+ },
+};
+
+module_init(msm_flash_init_module);
+module_exit(msm_flash_exit_module);
+MODULE_DESCRIPTION("MSM FLASH");
+MODULE_LICENSE("GPL v2");
diff --git a/camera/sensor/flash/msm_flash.h b/camera/sensor/flash/msm_flash.h
new file mode 100644
index 00000000..df84e8d9
--- /dev/null
+++ b/camera/sensor/flash/msm_flash.h
@@ -0,0 +1,124 @@
+/* Copyright (c) 2009-2015, 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
+ * only 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.
+ *
+ */
+#ifndef MSM_FLASH_H
+#define MSM_FLASH_H
+
+#include <linux/leds.h>
+#include <linux/platform_device.h>
+#include <media/v4l2-subdev.h>
+#include <media/v4l2-ioctl.h>
+#include <lenovo_media/msm_cam_sensor.h>
+#include <lenovo_soc/qcom/camera2.h>
+#include "msm_camera_i2c.h"
+#include "msm_sd.h"
+
+#define DEFINE_MSM_MUTEX(mutexname) \
+ static struct mutex mutexname = __MUTEX_INITIALIZER(mutexname)
+
+enum msm_camera_flash_state_t {
+ MSM_CAMERA_FLASH_INIT,
+ MSM_CAMERA_FLASH_RELEASE,
+};
+
+struct msm_flash_ctrl_t;
+
+struct msm_flash_func_t {
+ int32_t (*camera_flash_init)(struct msm_flash_ctrl_t *,
+ struct msm_flash_cfg_data_t *);
+ int32_t (*camera_flash_release)(struct msm_flash_ctrl_t *);
+ int32_t (*camera_flash_off)(struct msm_flash_ctrl_t *,
+ struct msm_flash_cfg_data_t *);
+ int32_t (*camera_flash_low)(struct msm_flash_ctrl_t *,
+ struct msm_flash_cfg_data_t *);
+ int32_t (*camera_flash_high)(struct msm_flash_ctrl_t *,
+ struct msm_flash_cfg_data_t *);
+ int32_t (*camera_flash_read)(struct msm_flash_ctrl_t *,
+ struct msm_flash_cfg_data_t *);
+ int32_t (*camera_flash_write)(struct msm_flash_ctrl_t *,
+ struct msm_flash_cfg_data_t *);
+};
+
+struct msm_flash_table {
+ enum msm_flash_driver_type flash_driver_type;
+ struct msm_flash_func_t func_tbl;
+};
+
+struct msm_flash_reg_t {
+ struct msm_camera_i2c_reg_setting *init_setting;
+ struct msm_camera_i2c_reg_setting *off_setting;
+ struct msm_camera_i2c_reg_setting *release_setting;
+ struct msm_camera_i2c_reg_setting *low_setting;
+ struct msm_camera_i2c_reg_setting *high_setting;
+};
+
+struct msm_flash_ctrl_t {
+ struct msm_camera_i2c_client flash_i2c_client;
+ struct msm_sd_subdev msm_sd;
+ struct platform_device *pdev;
+ struct msm_flash_func_t *func_tbl;
+ struct msm_camera_power_ctrl_t power_info;
+
+ /* Switch node to trigger led */
+ const char *switch_trigger_name;
+ struct led_trigger *switch_trigger;
+
+ /* Flash */
+ uint32_t flash_num_sources;
+ const char *flash_trigger_name[MAX_LED_TRIGGERS];
+ struct led_trigger *flash_trigger[MAX_LED_TRIGGERS];
+ uint32_t flash_op_current[MAX_LED_TRIGGERS];
+ uint32_t flash_max_current[MAX_LED_TRIGGERS];
+ uint32_t flash_max_duration[MAX_LED_TRIGGERS];
+
+ /* Torch */
+ uint32_t torch_num_sources;
+ const char *torch_trigger_name[MAX_LED_TRIGGERS];
+ struct led_trigger *torch_trigger[MAX_LED_TRIGGERS];
+ uint32_t torch_op_current[MAX_LED_TRIGGERS];
+ uint32_t torch_max_current[MAX_LED_TRIGGERS];
+
+ void *data;
+ enum msm_camera_device_type_t flash_device_type;
+ enum cci_i2c_master_t cci_i2c_master;
+ uint32_t subdev_id;
+ struct mutex *flash_mutex;
+ struct msm_sensor_power_setting_array power_setting_array;
+
+ /* flash driver type */
+ enum msm_flash_driver_type flash_driver_type;
+
+ /* flash state */
+ enum msm_camera_flash_state_t flash_state;
+};
+
+int msm_flash_i2c_probe(struct i2c_client *client,
+ const struct i2c_device_id *id);
+
+int msm_flash_probe(struct platform_device *pdev, const void *data);
+
+int32_t msm_flash_create_v4lsubdev(struct platform_device *pdev,
+ void *data);
+int32_t msm_led_i2c_flash_create_v4lsubdev(void *data);
+
+int32_t msm_led_i2c_trigger_get_subdev_id(struct msm_flash_ctrl_t *fctrl,
+ void *arg);
+
+int32_t msm_led_i2c_trigger_config(struct msm_flash_ctrl_t *fctrl,
+ void *data);
+
+int msm_flash_led_init(struct msm_flash_ctrl_t *fctrl);
+int msm_flash_led_release(struct msm_flash_ctrl_t *fctrl);
+int msm_flash_led_off(struct msm_flash_ctrl_t *fctrl);
+int msm_flash_led_low(struct msm_flash_ctrl_t *fctrl);
+int msm_flash_led_high(struct msm_flash_ctrl_t *fctrl);
+#endif