Loading drivers/media/platform/msm/camera_v2/sensor/flash/Makefile +5 −0 Original line number Diff line number Diff line Loading @@ -3,3 +3,8 @@ ccflags-y += -Idrivers/media/platform/msm/camera_v2 ccflags-y += -Idrivers/media/platform/msm/camera_v2/common ccflags-y += -Idrivers/media/platform/msm/camera_v2/sensor/io obj-$(CONFIG_MSMB_CAMERA) += msm_flash.o obj-$(CONFIG_MSMB_CAMERA) += msm_led_flash.o obj-$(CONFIG_MSMB_CAMERA) += msm_led_trigger.o obj-$(CONFIG_MSMB_CAMERA) += msm_led_i2c_trigger.o obj-$(CONFIG_MSMB_CAMERA) += adp1660.o obj-$(CONFIG_MSMB_CAMERA) += msm_led_torch.o No newline at end of file drivers/media/platform/msm/camera_v2/sensor/flash/adp1660.c 0 → 100644 +217 −0 Original line number Diff line number Diff line /* Copyright (c) 2017, 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. * */ #include <linux/module.h> #include <linux/export.h> #include "msm_led_flash.h" #define FLASH_NAME "qcom,led-flash" #undef CDBG #define CDBG(fmt, args...) pr_debug(fmt, ##args) static struct msm_led_flash_ctrl_t fctrl; static struct i2c_driver adp1660_i2c_driver; static struct msm_camera_i2c_reg_array adp1660_init_array[] = { {0x01, 0x03}, {0x02, 0x0F}, {0x09, 0x28}, {0x03, 0x09}, }; static struct msm_camera_i2c_reg_array adp1660_off_array[] = { {0x0f, 0x00}, }; static struct msm_camera_i2c_reg_array adp1660_release_array[] = { {0x0f, 0x00}, }; static struct msm_camera_i2c_reg_array adp1660_low_array[] = { {0x08, 0x04}, {0x06, 0x28}, {0x01, 0xBD}, {0x0f, 0x01}, }; static struct msm_camera_i2c_reg_array adp1660_high_array[] = { {0x02, 0x4F}, {0x06, 0x3C}, {0x09, 0x3C}, {0x0f, 0x01}, {0x01, 0xBB}, }; static void __exit msm_flash_adp1660_i2c_remove(void) { i2c_del_driver(&adp1660_i2c_driver); } static const struct of_device_id adp1660_trigger_dt_match[] = { {.compatible = "qcom,led-flash", .data = &fctrl}, {} }; MODULE_DEVICE_TABLE(of, adp1660_trigger_dt_match); static const struct i2c_device_id flash_i2c_id[] = { {"qcom,led-flash", (kernel_ulong_t)&fctrl}, { } }; static const struct i2c_device_id adp1660_i2c_id[] = { {FLASH_NAME, (kernel_ulong_t)&fctrl}, { } }; static int msm_flash_adp1660_i2c_probe(struct i2c_client *client, const struct i2c_device_id *id) { if (!id) { pr_err("msm_flash_adp1660_i2c_probe: id is NULL"); id = adp1660_i2c_id; } return msm_flash_i2c_probe(client, id); } static struct i2c_driver adp1660_i2c_driver = { .id_table = adp1660_i2c_id, .probe = msm_flash_adp1660_i2c_probe, .remove = __exit_p(msm_flash_adp1660_i2c_remove), .driver = { .name = FLASH_NAME, .owner = THIS_MODULE, .of_match_table = adp1660_trigger_dt_match, }, }; static int msm_flash_adp1660_platform_probe(struct platform_device *pdev) { const struct of_device_id *match; match = of_match_device(adp1660_trigger_dt_match, &pdev->dev); if (!match) return -EFAULT; return msm_flash_probe(pdev, match->data); } static struct platform_driver adp1660_platform_driver = { .probe = msm_flash_adp1660_platform_probe, .driver = { .name = "qcom,led-flash", .owner = THIS_MODULE, .of_match_table = adp1660_trigger_dt_match, }, }; static int __init msm_flash_adp1660_init_module(void) { int32_t rc = 0; rc = platform_driver_register(&adp1660_platform_driver); if (fctrl.pdev != NULL && rc == 0) pr_err("adp1660 platform_driver_register success"); else if (rc != 0) pr_err("adp1660 platform_driver_register failed"); else { rc = i2c_add_driver(&adp1660_i2c_driver); if (!rc) pr_err("adp1660 i2c_add_driver success"); } return rc; } static void __exit msm_flash_adp1660_exit_module(void) { if (fctrl.pdev) platform_driver_unregister(&adp1660_platform_driver); else i2c_del_driver(&adp1660_i2c_driver); } static struct msm_camera_i2c_client adp1660_i2c_client = { .addr_type = MSM_CAMERA_I2C_BYTE_ADDR, }; static struct msm_camera_i2c_reg_setting adp1660_init_setting = { .reg_setting = adp1660_init_array, .size = ARRAY_SIZE(adp1660_init_array), .addr_type = MSM_CAMERA_I2C_BYTE_ADDR, .data_type = MSM_CAMERA_I2C_BYTE_DATA, .delay = 0, }; static struct msm_camera_i2c_reg_setting adp1660_off_setting = { .reg_setting = adp1660_off_array, .size = ARRAY_SIZE(adp1660_off_array), .addr_type = MSM_CAMERA_I2C_BYTE_ADDR, .data_type = MSM_CAMERA_I2C_BYTE_DATA, .delay = 0, }; static struct msm_camera_i2c_reg_setting adp1660_release_setting = { .reg_setting = adp1660_release_array, .size = ARRAY_SIZE(adp1660_release_array), .addr_type = MSM_CAMERA_I2C_BYTE_ADDR, .data_type = MSM_CAMERA_I2C_BYTE_DATA, .delay = 0, }; static struct msm_camera_i2c_reg_setting adp1660_low_setting = { .reg_setting = adp1660_low_array, .size = ARRAY_SIZE(adp1660_low_array), .addr_type = MSM_CAMERA_I2C_BYTE_ADDR, .data_type = MSM_CAMERA_I2C_BYTE_DATA, .delay = 0, }; static struct msm_camera_i2c_reg_setting adp1660_high_setting = { .reg_setting = adp1660_high_array, .size = ARRAY_SIZE(adp1660_high_array), .addr_type = MSM_CAMERA_I2C_BYTE_ADDR, .data_type = MSM_CAMERA_I2C_BYTE_DATA, .delay = 0, }; static struct msm_led_flash_reg_t adp1660_regs = { .init_setting = &adp1660_init_setting, .off_setting = &adp1660_off_setting, .low_setting = &adp1660_low_setting, .high_setting = &adp1660_high_setting, .release_setting = &adp1660_release_setting, }; static struct msm_flash_fn_t adp1660_func_tbl = { .flash_get_subdev_id = msm_led_i2c_trigger_get_subdev_id, .flash_led_config = msm_led_i2c_trigger_config, .flash_led_init = msm_flash_led_init, .flash_led_release = msm_flash_led_release, .flash_led_off = msm_flash_led_off, .flash_led_low = msm_flash_led_low, .flash_led_high = msm_flash_led_high, }; static struct msm_led_flash_ctrl_t fctrl = { .flash_i2c_client = &adp1660_i2c_client, .reg_setting = &adp1660_regs, .func_tbl = &adp1660_func_tbl, }; /*subsys_initcall(msm_flash_i2c_add_driver);*/ module_init(msm_flash_adp1660_init_module); module_exit(msm_flash_adp1660_exit_module); MODULE_DESCRIPTION("adp1660 FLASH"); MODULE_LICENSE("GPL v2"); drivers/media/platform/msm/camera_v2/sensor/flash/msm_flash.c +110 −0 Original line number Diff line number Diff line Loading @@ -27,6 +27,16 @@ 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_i2c_dt_match[] = { {.compatible = "qcom,camera-flash"}, {} }; static const struct i2c_device_id msm_flash_i2c_id[] = { {"qcom,camera-flash", (kernel_ulong_t)NULL}, { } }; static const struct of_device_id msm_flash_dt_match[] = { {.compatible = "qcom,camera-flash", .data = NULL}, {} Loading @@ -42,6 +52,16 @@ static struct msm_flash_table *flash_table[] = { &msm_pmic_flash_table }; static struct msm_camera_i2c_fn_t msm_flash_qup_func_tbl = { .i2c_read = msm_camera_qup_i2c_read, .i2c_read_seq = msm_camera_qup_i2c_read_seq, .i2c_write = msm_camera_qup_i2c_write, .i2c_write_table = msm_camera_qup_i2c_write_table, .i2c_write_seq_table = msm_camera_qup_i2c_write_seq_table, .i2c_write_table_w_microdelay = msm_camera_qup_i2c_write_table_w_microdelay, }; 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, Loading Loading @@ -1111,6 +1131,75 @@ static long msm_flash_subdev_fops_ioctl(struct file *file, return video_usercopy(file, cmd, arg, msm_flash_subdev_do_ioctl); } #endif static int msm_camera_flash_i2c_probe(struct i2c_client *client, const struct i2c_device_id *id) { int32_t rc = 0; struct msm_flash_ctrl_t *flash_ctrl = NULL; CDBG("Enter\n"); if (client == NULL) { pr_err("msm_flash_i2c_probe: client is null\n"); return -EINVAL; } flash_ctrl = kzalloc(sizeof(struct msm_flash_ctrl_t), GFP_KERNEL); if (!flash_ctrl) return -ENOMEM; memset(flash_ctrl, 0, sizeof(struct msm_flash_ctrl_t)); if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) { pr_err("i2c_check_functionality failed\n"); kfree(flash_ctrl); return -EINVAL; } rc = msm_flash_get_dt_data(client->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 = &client->dev; flash_ctrl->flash_device_type = MSM_CAMERA_I2C_DEVICE; flash_ctrl->flash_mutex = &msm_flash_mutex; flash_ctrl->flash_i2c_client.i2c_func_tbl = &msm_flash_qup_func_tbl; flash_ctrl->flash_i2c_client.client = client; /* 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_flash_v4l2_subdev_fops = 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; CDBG("probe success\n"); return rc; } static int32_t msm_flash_platform_probe(struct platform_device *pdev) { int32_t rc = 0; Loading Loading @@ -1189,6 +1278,19 @@ static int32_t msm_flash_platform_probe(struct platform_device *pdev) return rc; } MODULE_DEVICE_TABLE(of, msm_flash_i2c_dt_match); static struct i2c_driver msm_flash_i2c_driver = { .id_table = msm_flash_i2c_id, .probe = msm_camera_flash_i2c_probe, .remove = __exit_p(msm_camera_flash_i2c_remove), .driver = { .name = "qcom,camera-flash", .owner = THIS_MODULE, .of_match_table = msm_flash_i2c_dt_match, }, }; MODULE_DEVICE_TABLE(of, msm_flash_dt_match); static struct platform_driver msm_flash_platform_driver = { Loading @@ -1205,6 +1307,13 @@ 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) return rc; pr_err("platform probe for flash failed"); /* Perform i2c probe if platform probe fails. */ rc = i2c_add_driver(&msm_flash_i2c_driver); if (rc) pr_err("platform probe for flash failed"); Loading @@ -1214,6 +1323,7 @@ static int __init msm_flash_init_module(void) static void __exit msm_flash_exit_module(void) { platform_driver_unregister(&msm_flash_platform_driver); i2c_del_driver(&msm_flash_i2c_driver); return; } Loading drivers/media/platform/msm/camera_v2/sensor/flash/msm_led_flash.c 0 → 100644 +128 −0 Original line number Diff line number Diff line /* Copyright (c) 2017, 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 "msm_led_flash.h" #undef CDBG #define CDBG(fmt, args...) pr_err(fmt, ##args) static struct v4l2_file_operations msm_led_flash_v4l2_subdev_fops; static long msm_led_flash_subdev_ioctl(struct v4l2_subdev *sd, unsigned int cmd, void *arg) { struct msm_led_flash_ctrl_t *fctrl = NULL; void *argp = (void *)arg; 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 fctrl->func_tbl->flash_get_subdev_id(fctrl, argp); case VIDIOC_MSM_FLASH_LED_DATA_CFG: return fctrl->func_tbl->flash_led_config(fctrl, argp); case MSM_SD_NOTIFY_FREEZE: return 0; case MSM_SD_SHUTDOWN: return fctrl->func_tbl->flash_led_release(fctrl); default: pr_err_ratelimited("invalid cmd %d\n", cmd); return -ENOIOCTLCMD; } } static struct v4l2_subdev_core_ops msm_flash_subdev_core_ops = { .ioctl = msm_led_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; int32_t msm_led_flash_create_v4lsubdev(struct platform_device *pdev, void *data) { struct msm_led_flash_ctrl_t *fctrl = (struct msm_led_flash_ctrl_t *)data; CDBG("Enter\n"); if (!fctrl) { pr_err("fctrl NULL\n"); return -EINVAL; } /* Initialize sub device */ v4l2_subdev_init(&fctrl->msm_sd.sd, &msm_flash_subdev_ops); v4l2_set_subdevdata(&fctrl->msm_sd.sd, fctrl); fctrl->pdev = pdev; fctrl->msm_sd.sd.internal_ops = &msm_flash_internal_ops; fctrl->msm_sd.sd.flags |= V4L2_SUBDEV_FL_HAS_DEVNODE; snprintf(fctrl->msm_sd.sd.name, ARRAY_SIZE(fctrl->msm_sd.sd.name), "msm_flash"); media_entity_init(&fctrl->msm_sd.sd.entity, 0, NULL, 0); fctrl->msm_sd.sd.entity.type = MEDIA_ENT_T_V4L2_SUBDEV; fctrl->msm_sd.sd.entity.group_id = MSM_CAMERA_SUBDEV_FLASH; fctrl->msm_sd.close_seq = MSM_SD_CLOSE_2ND_CATEGORY | 0x1; msm_sd_register(&fctrl->msm_sd); msm_led_flash_v4l2_subdev_fops = v4l2_subdev_fops; #ifdef CONFIG_COMPAT msm_led_flash_v4l2_subdev_fops.compat_ioctl32 = msm_led_flash_v4l2_subdev_fops.unlocked_ioctl; #endif fctrl->msm_sd.sd.devnode->fops = &msm_led_flash_v4l2_subdev_fops; CDBG("probe success\n"); return 0; } int32_t msm_led_i2c_flash_create_v4lsubdev(void *data) { struct msm_led_flash_ctrl_t *fctrl = (struct msm_led_flash_ctrl_t *)data; CDBG("Enter\n"); if (!fctrl) { pr_err("fctrl NULL\n"); return -EINVAL; } /* Initialize sub device */ v4l2_subdev_init(&fctrl->msm_sd.sd, &msm_flash_subdev_ops); v4l2_set_subdevdata(&fctrl->msm_sd.sd, fctrl); fctrl->msm_sd.sd.internal_ops = &msm_flash_internal_ops; fctrl->msm_sd.sd.flags |= V4L2_SUBDEV_FL_HAS_DEVNODE; snprintf(fctrl->msm_sd.sd.name, ARRAY_SIZE(fctrl->msm_sd.sd.name), "msm_flash"); media_entity_init(&fctrl->msm_sd.sd.entity, 0, NULL, 0); fctrl->msm_sd.sd.entity.type = MEDIA_ENT_T_V4L2_SUBDEV; fctrl->msm_sd.sd.entity.group_id = MSM_CAMERA_SUBDEV_LED_FLASH; msm_sd_register(&fctrl->msm_sd); msm_led_flash_v4l2_subdev_fops = v4l2_subdev_fops; fctrl->msm_sd.sd.devnode->fops = &msm_led_flash_v4l2_subdev_fops; CDBG("probe success\n"); return 0; } drivers/media/platform/msm/camera_v2/sensor/flash/msm_led_flash.h 0 → 100644 +97 −0 Original line number Diff line number Diff line /* Copyright (c) 2017, 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_LED_FLASH_H #define MSM_LED_FLASH_H #include <linux/leds.h> #include <linux/platform_device.h> #include <media/v4l2-subdev.h> #include <media/msm_cam_sensor.h> #include <soc/qcom/camera2.h> #include "msm_camera_i2c.h" #include "msm_sd.h" struct msm_led_flash_ctrl_t; struct msm_flash_fn_t { int32_t (*flash_get_subdev_id)(struct msm_led_flash_ctrl_t *, void *); int32_t (*flash_led_config)(struct msm_led_flash_ctrl_t *, void *); int32_t (*flash_led_init)(struct msm_led_flash_ctrl_t *); int32_t (*flash_led_release)(struct msm_led_flash_ctrl_t *); int32_t (*flash_led_off)(struct msm_led_flash_ctrl_t *); int32_t (*flash_led_low)(struct msm_led_flash_ctrl_t *); int32_t (*flash_led_high)(struct msm_led_flash_ctrl_t *); }; struct msm_led_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_led_flash_ctrl_t { struct msm_camera_i2c_client *flash_i2c_client; struct msm_sd_subdev msm_sd; struct platform_device *pdev; struct msm_flash_fn_t *func_tbl; struct msm_camera_sensor_board_info *flashdata; struct msm_led_flash_reg_t *reg_setting; /* Flash */ const char *flash_trigger_name[MAX_LED_TRIGGERS]; struct led_trigger *flash_trigger[MAX_LED_TRIGGERS]; uint32_t flash_num_sources; 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 */ const char *torch_trigger_name[MAX_LED_TRIGGERS]; struct led_trigger *torch_trigger[MAX_LED_TRIGGERS]; uint32_t torch_num_sources; 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; enum msm_camera_led_config_t led_state; uint32_t subdev_id; struct msm_pinctrl_info pinctrl_info; }; 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_led_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_led_flash_ctrl_t *fctrl, void *arg); int32_t msm_led_i2c_trigger_config(struct msm_led_flash_ctrl_t *fctrl, void *data); int32_t msm_led_torch_create_classdev(struct platform_device *pdev, void *data); int msm_flash_led_init(struct msm_led_flash_ctrl_t *fctrl); int msm_flash_led_release(struct msm_led_flash_ctrl_t *fctrl); int msm_flash_led_off(struct msm_led_flash_ctrl_t *fctrl); int msm_flash_led_low(struct msm_led_flash_ctrl_t *fctrl); int msm_flash_led_high(struct msm_led_flash_ctrl_t *fctrl); #endif Loading
drivers/media/platform/msm/camera_v2/sensor/flash/Makefile +5 −0 Original line number Diff line number Diff line Loading @@ -3,3 +3,8 @@ ccflags-y += -Idrivers/media/platform/msm/camera_v2 ccflags-y += -Idrivers/media/platform/msm/camera_v2/common ccflags-y += -Idrivers/media/platform/msm/camera_v2/sensor/io obj-$(CONFIG_MSMB_CAMERA) += msm_flash.o obj-$(CONFIG_MSMB_CAMERA) += msm_led_flash.o obj-$(CONFIG_MSMB_CAMERA) += msm_led_trigger.o obj-$(CONFIG_MSMB_CAMERA) += msm_led_i2c_trigger.o obj-$(CONFIG_MSMB_CAMERA) += adp1660.o obj-$(CONFIG_MSMB_CAMERA) += msm_led_torch.o No newline at end of file
drivers/media/platform/msm/camera_v2/sensor/flash/adp1660.c 0 → 100644 +217 −0 Original line number Diff line number Diff line /* Copyright (c) 2017, 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. * */ #include <linux/module.h> #include <linux/export.h> #include "msm_led_flash.h" #define FLASH_NAME "qcom,led-flash" #undef CDBG #define CDBG(fmt, args...) pr_debug(fmt, ##args) static struct msm_led_flash_ctrl_t fctrl; static struct i2c_driver adp1660_i2c_driver; static struct msm_camera_i2c_reg_array adp1660_init_array[] = { {0x01, 0x03}, {0x02, 0x0F}, {0x09, 0x28}, {0x03, 0x09}, }; static struct msm_camera_i2c_reg_array adp1660_off_array[] = { {0x0f, 0x00}, }; static struct msm_camera_i2c_reg_array adp1660_release_array[] = { {0x0f, 0x00}, }; static struct msm_camera_i2c_reg_array adp1660_low_array[] = { {0x08, 0x04}, {0x06, 0x28}, {0x01, 0xBD}, {0x0f, 0x01}, }; static struct msm_camera_i2c_reg_array adp1660_high_array[] = { {0x02, 0x4F}, {0x06, 0x3C}, {0x09, 0x3C}, {0x0f, 0x01}, {0x01, 0xBB}, }; static void __exit msm_flash_adp1660_i2c_remove(void) { i2c_del_driver(&adp1660_i2c_driver); } static const struct of_device_id adp1660_trigger_dt_match[] = { {.compatible = "qcom,led-flash", .data = &fctrl}, {} }; MODULE_DEVICE_TABLE(of, adp1660_trigger_dt_match); static const struct i2c_device_id flash_i2c_id[] = { {"qcom,led-flash", (kernel_ulong_t)&fctrl}, { } }; static const struct i2c_device_id adp1660_i2c_id[] = { {FLASH_NAME, (kernel_ulong_t)&fctrl}, { } }; static int msm_flash_adp1660_i2c_probe(struct i2c_client *client, const struct i2c_device_id *id) { if (!id) { pr_err("msm_flash_adp1660_i2c_probe: id is NULL"); id = adp1660_i2c_id; } return msm_flash_i2c_probe(client, id); } static struct i2c_driver adp1660_i2c_driver = { .id_table = adp1660_i2c_id, .probe = msm_flash_adp1660_i2c_probe, .remove = __exit_p(msm_flash_adp1660_i2c_remove), .driver = { .name = FLASH_NAME, .owner = THIS_MODULE, .of_match_table = adp1660_trigger_dt_match, }, }; static int msm_flash_adp1660_platform_probe(struct platform_device *pdev) { const struct of_device_id *match; match = of_match_device(adp1660_trigger_dt_match, &pdev->dev); if (!match) return -EFAULT; return msm_flash_probe(pdev, match->data); } static struct platform_driver adp1660_platform_driver = { .probe = msm_flash_adp1660_platform_probe, .driver = { .name = "qcom,led-flash", .owner = THIS_MODULE, .of_match_table = adp1660_trigger_dt_match, }, }; static int __init msm_flash_adp1660_init_module(void) { int32_t rc = 0; rc = platform_driver_register(&adp1660_platform_driver); if (fctrl.pdev != NULL && rc == 0) pr_err("adp1660 platform_driver_register success"); else if (rc != 0) pr_err("adp1660 platform_driver_register failed"); else { rc = i2c_add_driver(&adp1660_i2c_driver); if (!rc) pr_err("adp1660 i2c_add_driver success"); } return rc; } static void __exit msm_flash_adp1660_exit_module(void) { if (fctrl.pdev) platform_driver_unregister(&adp1660_platform_driver); else i2c_del_driver(&adp1660_i2c_driver); } static struct msm_camera_i2c_client adp1660_i2c_client = { .addr_type = MSM_CAMERA_I2C_BYTE_ADDR, }; static struct msm_camera_i2c_reg_setting adp1660_init_setting = { .reg_setting = adp1660_init_array, .size = ARRAY_SIZE(adp1660_init_array), .addr_type = MSM_CAMERA_I2C_BYTE_ADDR, .data_type = MSM_CAMERA_I2C_BYTE_DATA, .delay = 0, }; static struct msm_camera_i2c_reg_setting adp1660_off_setting = { .reg_setting = adp1660_off_array, .size = ARRAY_SIZE(adp1660_off_array), .addr_type = MSM_CAMERA_I2C_BYTE_ADDR, .data_type = MSM_CAMERA_I2C_BYTE_DATA, .delay = 0, }; static struct msm_camera_i2c_reg_setting adp1660_release_setting = { .reg_setting = adp1660_release_array, .size = ARRAY_SIZE(adp1660_release_array), .addr_type = MSM_CAMERA_I2C_BYTE_ADDR, .data_type = MSM_CAMERA_I2C_BYTE_DATA, .delay = 0, }; static struct msm_camera_i2c_reg_setting adp1660_low_setting = { .reg_setting = adp1660_low_array, .size = ARRAY_SIZE(adp1660_low_array), .addr_type = MSM_CAMERA_I2C_BYTE_ADDR, .data_type = MSM_CAMERA_I2C_BYTE_DATA, .delay = 0, }; static struct msm_camera_i2c_reg_setting adp1660_high_setting = { .reg_setting = adp1660_high_array, .size = ARRAY_SIZE(adp1660_high_array), .addr_type = MSM_CAMERA_I2C_BYTE_ADDR, .data_type = MSM_CAMERA_I2C_BYTE_DATA, .delay = 0, }; static struct msm_led_flash_reg_t adp1660_regs = { .init_setting = &adp1660_init_setting, .off_setting = &adp1660_off_setting, .low_setting = &adp1660_low_setting, .high_setting = &adp1660_high_setting, .release_setting = &adp1660_release_setting, }; static struct msm_flash_fn_t adp1660_func_tbl = { .flash_get_subdev_id = msm_led_i2c_trigger_get_subdev_id, .flash_led_config = msm_led_i2c_trigger_config, .flash_led_init = msm_flash_led_init, .flash_led_release = msm_flash_led_release, .flash_led_off = msm_flash_led_off, .flash_led_low = msm_flash_led_low, .flash_led_high = msm_flash_led_high, }; static struct msm_led_flash_ctrl_t fctrl = { .flash_i2c_client = &adp1660_i2c_client, .reg_setting = &adp1660_regs, .func_tbl = &adp1660_func_tbl, }; /*subsys_initcall(msm_flash_i2c_add_driver);*/ module_init(msm_flash_adp1660_init_module); module_exit(msm_flash_adp1660_exit_module); MODULE_DESCRIPTION("adp1660 FLASH"); MODULE_LICENSE("GPL v2");
drivers/media/platform/msm/camera_v2/sensor/flash/msm_flash.c +110 −0 Original line number Diff line number Diff line Loading @@ -27,6 +27,16 @@ 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_i2c_dt_match[] = { {.compatible = "qcom,camera-flash"}, {} }; static const struct i2c_device_id msm_flash_i2c_id[] = { {"qcom,camera-flash", (kernel_ulong_t)NULL}, { } }; static const struct of_device_id msm_flash_dt_match[] = { {.compatible = "qcom,camera-flash", .data = NULL}, {} Loading @@ -42,6 +52,16 @@ static struct msm_flash_table *flash_table[] = { &msm_pmic_flash_table }; static struct msm_camera_i2c_fn_t msm_flash_qup_func_tbl = { .i2c_read = msm_camera_qup_i2c_read, .i2c_read_seq = msm_camera_qup_i2c_read_seq, .i2c_write = msm_camera_qup_i2c_write, .i2c_write_table = msm_camera_qup_i2c_write_table, .i2c_write_seq_table = msm_camera_qup_i2c_write_seq_table, .i2c_write_table_w_microdelay = msm_camera_qup_i2c_write_table_w_microdelay, }; 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, Loading Loading @@ -1111,6 +1131,75 @@ static long msm_flash_subdev_fops_ioctl(struct file *file, return video_usercopy(file, cmd, arg, msm_flash_subdev_do_ioctl); } #endif static int msm_camera_flash_i2c_probe(struct i2c_client *client, const struct i2c_device_id *id) { int32_t rc = 0; struct msm_flash_ctrl_t *flash_ctrl = NULL; CDBG("Enter\n"); if (client == NULL) { pr_err("msm_flash_i2c_probe: client is null\n"); return -EINVAL; } flash_ctrl = kzalloc(sizeof(struct msm_flash_ctrl_t), GFP_KERNEL); if (!flash_ctrl) return -ENOMEM; memset(flash_ctrl, 0, sizeof(struct msm_flash_ctrl_t)); if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) { pr_err("i2c_check_functionality failed\n"); kfree(flash_ctrl); return -EINVAL; } rc = msm_flash_get_dt_data(client->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 = &client->dev; flash_ctrl->flash_device_type = MSM_CAMERA_I2C_DEVICE; flash_ctrl->flash_mutex = &msm_flash_mutex; flash_ctrl->flash_i2c_client.i2c_func_tbl = &msm_flash_qup_func_tbl; flash_ctrl->flash_i2c_client.client = client; /* 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_flash_v4l2_subdev_fops = 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; CDBG("probe success\n"); return rc; } static int32_t msm_flash_platform_probe(struct platform_device *pdev) { int32_t rc = 0; Loading Loading @@ -1189,6 +1278,19 @@ static int32_t msm_flash_platform_probe(struct platform_device *pdev) return rc; } MODULE_DEVICE_TABLE(of, msm_flash_i2c_dt_match); static struct i2c_driver msm_flash_i2c_driver = { .id_table = msm_flash_i2c_id, .probe = msm_camera_flash_i2c_probe, .remove = __exit_p(msm_camera_flash_i2c_remove), .driver = { .name = "qcom,camera-flash", .owner = THIS_MODULE, .of_match_table = msm_flash_i2c_dt_match, }, }; MODULE_DEVICE_TABLE(of, msm_flash_dt_match); static struct platform_driver msm_flash_platform_driver = { Loading @@ -1205,6 +1307,13 @@ 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) return rc; pr_err("platform probe for flash failed"); /* Perform i2c probe if platform probe fails. */ rc = i2c_add_driver(&msm_flash_i2c_driver); if (rc) pr_err("platform probe for flash failed"); Loading @@ -1214,6 +1323,7 @@ static int __init msm_flash_init_module(void) static void __exit msm_flash_exit_module(void) { platform_driver_unregister(&msm_flash_platform_driver); i2c_del_driver(&msm_flash_i2c_driver); return; } Loading
drivers/media/platform/msm/camera_v2/sensor/flash/msm_led_flash.c 0 → 100644 +128 −0 Original line number Diff line number Diff line /* Copyright (c) 2017, 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 "msm_led_flash.h" #undef CDBG #define CDBG(fmt, args...) pr_err(fmt, ##args) static struct v4l2_file_operations msm_led_flash_v4l2_subdev_fops; static long msm_led_flash_subdev_ioctl(struct v4l2_subdev *sd, unsigned int cmd, void *arg) { struct msm_led_flash_ctrl_t *fctrl = NULL; void *argp = (void *)arg; 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 fctrl->func_tbl->flash_get_subdev_id(fctrl, argp); case VIDIOC_MSM_FLASH_LED_DATA_CFG: return fctrl->func_tbl->flash_led_config(fctrl, argp); case MSM_SD_NOTIFY_FREEZE: return 0; case MSM_SD_SHUTDOWN: return fctrl->func_tbl->flash_led_release(fctrl); default: pr_err_ratelimited("invalid cmd %d\n", cmd); return -ENOIOCTLCMD; } } static struct v4l2_subdev_core_ops msm_flash_subdev_core_ops = { .ioctl = msm_led_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; int32_t msm_led_flash_create_v4lsubdev(struct platform_device *pdev, void *data) { struct msm_led_flash_ctrl_t *fctrl = (struct msm_led_flash_ctrl_t *)data; CDBG("Enter\n"); if (!fctrl) { pr_err("fctrl NULL\n"); return -EINVAL; } /* Initialize sub device */ v4l2_subdev_init(&fctrl->msm_sd.sd, &msm_flash_subdev_ops); v4l2_set_subdevdata(&fctrl->msm_sd.sd, fctrl); fctrl->pdev = pdev; fctrl->msm_sd.sd.internal_ops = &msm_flash_internal_ops; fctrl->msm_sd.sd.flags |= V4L2_SUBDEV_FL_HAS_DEVNODE; snprintf(fctrl->msm_sd.sd.name, ARRAY_SIZE(fctrl->msm_sd.sd.name), "msm_flash"); media_entity_init(&fctrl->msm_sd.sd.entity, 0, NULL, 0); fctrl->msm_sd.sd.entity.type = MEDIA_ENT_T_V4L2_SUBDEV; fctrl->msm_sd.sd.entity.group_id = MSM_CAMERA_SUBDEV_FLASH; fctrl->msm_sd.close_seq = MSM_SD_CLOSE_2ND_CATEGORY | 0x1; msm_sd_register(&fctrl->msm_sd); msm_led_flash_v4l2_subdev_fops = v4l2_subdev_fops; #ifdef CONFIG_COMPAT msm_led_flash_v4l2_subdev_fops.compat_ioctl32 = msm_led_flash_v4l2_subdev_fops.unlocked_ioctl; #endif fctrl->msm_sd.sd.devnode->fops = &msm_led_flash_v4l2_subdev_fops; CDBG("probe success\n"); return 0; } int32_t msm_led_i2c_flash_create_v4lsubdev(void *data) { struct msm_led_flash_ctrl_t *fctrl = (struct msm_led_flash_ctrl_t *)data; CDBG("Enter\n"); if (!fctrl) { pr_err("fctrl NULL\n"); return -EINVAL; } /* Initialize sub device */ v4l2_subdev_init(&fctrl->msm_sd.sd, &msm_flash_subdev_ops); v4l2_set_subdevdata(&fctrl->msm_sd.sd, fctrl); fctrl->msm_sd.sd.internal_ops = &msm_flash_internal_ops; fctrl->msm_sd.sd.flags |= V4L2_SUBDEV_FL_HAS_DEVNODE; snprintf(fctrl->msm_sd.sd.name, ARRAY_SIZE(fctrl->msm_sd.sd.name), "msm_flash"); media_entity_init(&fctrl->msm_sd.sd.entity, 0, NULL, 0); fctrl->msm_sd.sd.entity.type = MEDIA_ENT_T_V4L2_SUBDEV; fctrl->msm_sd.sd.entity.group_id = MSM_CAMERA_SUBDEV_LED_FLASH; msm_sd_register(&fctrl->msm_sd); msm_led_flash_v4l2_subdev_fops = v4l2_subdev_fops; fctrl->msm_sd.sd.devnode->fops = &msm_led_flash_v4l2_subdev_fops; CDBG("probe success\n"); return 0; }
drivers/media/platform/msm/camera_v2/sensor/flash/msm_led_flash.h 0 → 100644 +97 −0 Original line number Diff line number Diff line /* Copyright (c) 2017, 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_LED_FLASH_H #define MSM_LED_FLASH_H #include <linux/leds.h> #include <linux/platform_device.h> #include <media/v4l2-subdev.h> #include <media/msm_cam_sensor.h> #include <soc/qcom/camera2.h> #include "msm_camera_i2c.h" #include "msm_sd.h" struct msm_led_flash_ctrl_t; struct msm_flash_fn_t { int32_t (*flash_get_subdev_id)(struct msm_led_flash_ctrl_t *, void *); int32_t (*flash_led_config)(struct msm_led_flash_ctrl_t *, void *); int32_t (*flash_led_init)(struct msm_led_flash_ctrl_t *); int32_t (*flash_led_release)(struct msm_led_flash_ctrl_t *); int32_t (*flash_led_off)(struct msm_led_flash_ctrl_t *); int32_t (*flash_led_low)(struct msm_led_flash_ctrl_t *); int32_t (*flash_led_high)(struct msm_led_flash_ctrl_t *); }; struct msm_led_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_led_flash_ctrl_t { struct msm_camera_i2c_client *flash_i2c_client; struct msm_sd_subdev msm_sd; struct platform_device *pdev; struct msm_flash_fn_t *func_tbl; struct msm_camera_sensor_board_info *flashdata; struct msm_led_flash_reg_t *reg_setting; /* Flash */ const char *flash_trigger_name[MAX_LED_TRIGGERS]; struct led_trigger *flash_trigger[MAX_LED_TRIGGERS]; uint32_t flash_num_sources; 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 */ const char *torch_trigger_name[MAX_LED_TRIGGERS]; struct led_trigger *torch_trigger[MAX_LED_TRIGGERS]; uint32_t torch_num_sources; 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; enum msm_camera_led_config_t led_state; uint32_t subdev_id; struct msm_pinctrl_info pinctrl_info; }; 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_led_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_led_flash_ctrl_t *fctrl, void *arg); int32_t msm_led_i2c_trigger_config(struct msm_led_flash_ctrl_t *fctrl, void *data); int32_t msm_led_torch_create_classdev(struct platform_device *pdev, void *data); int msm_flash_led_init(struct msm_led_flash_ctrl_t *fctrl); int msm_flash_led_release(struct msm_led_flash_ctrl_t *fctrl); int msm_flash_led_off(struct msm_led_flash_ctrl_t *fctrl); int msm_flash_led_low(struct msm_led_flash_ctrl_t *fctrl); int msm_flash_led_high(struct msm_led_flash_ctrl_t *fctrl); #endif