Loading Documentation/devicetree/bindings/media/video/msm-cci.txt +1 −0 Original line number Diff line number Diff line Loading @@ -62,6 +62,7 @@ Required properties: - "shinetech,hi256" - "shinetech,s5k4e1" - "ovti,ov5645" - "ovti,ov7695" - "qcom,mt9m114" - reg : should contain i2c slave address of the device - qcom,csiphy-sd-index : should contain csiphy instance that will used to Loading arch/arm/boot/dts/qcom/msm8916-camera-sensor-qrd-skui.dtsi +43 −0 Original line number Diff line number Diff line Loading @@ -129,6 +129,49 @@ }; qcom,camera@42 { compatible = "ovti,ov7695"; reg = <0x42 0x0>; qcom,slave-id = <0x42 0x300a 0x7695>; qcom,csiphy-sd-index = <1>; qcom,csid-sd-index = <1>; qcom,mount-angle = <90>; qcom,sensor-name = "ov7695"; cam_vdig-supply = <&pm8916_l2>; cam_vana-supply = <&pm8916_l17>; cam_vio-supply = <&pm8916_l6>; cam_vaf-supply = <&pm8916_l10>; qcom,cam-vreg-name = "cam_vdig", "cam_vio", "cam_vana", "cam_vaf"; qcom,cam-vreg-type = <0 1 0 0>; qcom,cam-vreg-min-voltage = <1200000 0 2850000 2800000>; qcom,cam-vreg-max-voltage = <1200000 0 2850000 2800000>; qcom,cam-vreg-op-mode = <200000 0 80000 100000>; pinctrl-names = "cam_default", "cam_suspend"; pinctrl-0 = <&cam_sensor_mclk1_default &cam_sensor_front_default>; pinctrl-1 = <&cam_sensor_mclk1_sleep &cam_sensor_front_sleep>; gpios = <&msm_gpio 27 0>, <&msm_gpio 28 0>, <&msm_gpio 33 0>; qcom,gpio-reset = <1>; qcom,gpio-standby = <2>; qcom,gpio-req-tbl-num = <0 1 2>; qcom,gpio-req-tbl-flags = <1 0 0>; qcom,gpio-req-tbl-label = "CAMIF_MCLK", "CAM_RESET", "CAM_STANDBY"; qcom,csi-lane-assign = <0x4320>; qcom,csi-lane-mask = <0x3>; qcom,sensor-position = <1>; qcom,sensor-mode = <0>; qcom,cci-master = <0>; qcom,mclk-23880000; status = "ok"; clocks = <&clock_gcc clk_mclk1_clk_src>, <&clock_gcc clk_gcc_camss_mclk1_clk>; clock-names = "cam_src_clk", "cam_clk"; }; qcom,camera@0 { cell-index = <0>; compatible = "qcom,camera"; Loading drivers/media/platform/msm/camera_v2/Kconfig +9 −0 Original line number Diff line number Diff line Loading @@ -173,6 +173,15 @@ config OV5645 1280 * 270. It does not support auto focus. It supports few special effects like saturation. config OV7695 bool "Sensor OV7695 (YUV 0.3MP)" depends on MSMB_CAMERA ---help--- OV7695 is Omnivision YUV sensor. It supports 0.3 MP preview and snapshot. The preview and snapshot resolution shall be VGA. It does not support auto focus. It supports few special effects like saturation. config SP1628 bool "Sensor SP1628 (YUV 720P)" depends on MSMB_CAMERA Loading drivers/media/platform/msm/camera_v2/sensor/Makefile +1 −0 Original line number Diff line number Diff line Loading @@ -7,3 +7,4 @@ obj-$(CONFIG_MSMB_CAMERA) += cci/ io/ csiphy/ csid/ actuator/ flash/ eeprom/ ois obj-$(CONFIG_MSM_CAMERA_SENSOR) += msm_sensor_init.o msm_sensor_driver.o msm_sensor.o obj-$(CONFIG_MT9M114) += mt9m114.o obj-$(CONFIG_OV5645) += ov5645.o obj-$(CONFIG_OV5645) += ov7695.o drivers/media/platform/msm/camera_v2/sensor/ov7695.c 0 → 100644 +669 −0 Original line number Diff line number Diff line /* Copyright (c) 2014, 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 "msm_sensor.h" #include "msm_cci.h" #include "msm_camera_io_util.h" #define OV7695_SENSOR_NAME "ov7695" #define PLATFORM_DRIVER_NAME "msm_camera_ov7695" #define ov7695_obj ov7695_##obj /*#define CONFIG_MSMB_CAMERA_DEBUG*/ #undef CDBG #ifdef CONFIG_MSMB_CAMERA_DEBUG #define CDBG(fmt, args...) pr_err(fmt, ##args) #else #define CDBG(fmt, args...) do { } while (0) #endif DEFINE_MSM_MUTEX(ov7695_mut); static struct msm_sensor_ctrl_t ov7695_s_ctrl; static struct msm_sensor_power_setting ov7695_power_setting[] = { { .seq_type = SENSOR_GPIO, .seq_val = SENSOR_GPIO_STANDBY, .config_val = GPIO_OUT_LOW, .delay = 0, }, { .seq_type = SENSOR_GPIO, .seq_val = SENSOR_GPIO_RESET, .config_val = GPIO_OUT_LOW, .delay = 10, }, { .seq_type = SENSOR_VREG, .seq_val = CAM_VAF, .config_val = 0, .delay = 5, }, { .seq_type = SENSOR_VREG, .seq_val = CAM_VIO, .config_val = 0, .delay = 5, }, { .seq_type = SENSOR_VREG, .seq_val = CAM_VANA, .config_val = 0, .delay = 0, }, { .seq_type = SENSOR_GPIO, .seq_val = SENSOR_GPIO_STANDBY, .config_val = GPIO_OUT_HIGH, .delay = 5, }, { .seq_type = SENSOR_GPIO, .seq_val = SENSOR_GPIO_RESET, .config_val = GPIO_OUT_HIGH, .delay = 10, }, { .seq_type = SENSOR_CLK, .seq_val = SENSOR_CAM_MCLK, .config_val = 24000000, .delay = 10, }, { .seq_type = SENSOR_I2C_MUX, .seq_val = 0, .config_val = 0, .delay = 0, }, }; static struct msm_camera_i2c_reg_conf ov7695_vga_settings[] = { {0x3630, 0x79,}, }; static struct msm_camera_i2c_reg_conf ov7695_recommend_settings[] = { {0x0103, 0x01,}, {0x0100, 0x01,}, {0x3620, 0x2f,}, {0x3623, 0x12,}, {0x3718, 0x88,}, {0x3703, 0x80,}, {0x3712, 0x40,}, {0x3706, 0x40,}, {0x3631, 0x44,}, {0x3632, 0x05,}, {0x3013, 0xd0,}, {0x3705, 0x1d,}, {0x3713, 0x0e,}, {0x3012, 0x0a,}, {0x3717, 0x18,}, {0x3621, 0x47,}, {0x0309, 0x24,}, {0x3820, 0x90,}, {0x4803, 0x08,}, {0x0101, 0x02,}, {0x5100, 0x01,}, {0x4500, 0x24,}, {0x5301, 0x05,}, {0x5302, 0x0c,}, {0x5303, 0x1c,}, {0x5304, 0x2a,}, {0x5305, 0x39,}, {0x5306, 0x45,}, {0x5307, 0x52,}, {0x5308, 0x5d,}, {0x5309, 0x68,}, {0x530a, 0x7f,}, {0x530b, 0x91,}, {0x530c, 0xa5,}, {0x530d, 0xc6,}, {0x530e, 0xde,}, {0x530f, 0xef,}, {0x5310, 0x16,}, {0x520a, 0x74,}, //f4 {0x520b, 0x64,}, //f4 {0x520c, 0xd4,}, //f4 {0x5504, 0x08,}, {0x5505, 0x48,}, {0x5506, 0x07,}, {0x5507, 0x0b,}, {0x3a18, 0x01,}, {0x3a19, 0x00,}, {0x3503, 0x03,}, {0x3500, 0x00,}, {0x3501, 0x21,}, {0x3502, 0x00,}, {0x350a, 0x00,}, {0x350b, 0x00,}, {0x4008, 0x02,}, {0x4009, 0x09,}, {0x3002, 0x09,}, {0x3024, 0x00,}, {0x3503, 0x00,}, {0x0101, 0x02,}, {0x5002, 0x48,}, {0x5910, 0x00,}, {0x3a0f, 0x58,}, {0x3a10, 0x50,}, {0x3a1b, 0x5a,}, {0x3a1e, 0x4e,}, {0x3a11, 0xa0,}, {0x3a1f, 0x28,}, {0x3a18, 0x00,}, {0x3a19, 0xf8,}, {0x3503, 0x00,}, {0x3a0d, 0x04,}, {0x5000, 0xff,}, {0x5001, 0x3f,}, {0x5100, 0x1 ,}, //01 {0x5101, 0x25,}, //48 {0x5102, 0x0 ,}, //00 {0x5103, 0xf3,}, //f8 {0x5104, 0x7f,}, //04 {0x5105, 0x5 ,}, //00 {0x5106, 0xff,}, //00 {0x5107, 0xf ,}, //00 {0x5108, 0x1 ,}, //01 {0x5109, 0x1f,}, //48 {0x510a, 0x0 ,}, //00 {0x510b, 0xde,}, //f8 {0x510c, 0x56,}, //03 {0x510d, 0x5 ,}, //00 {0x510e, 0xff,}, //00 {0x510f, 0xf ,}, //00 {0x5110, 0x1 ,}, //01 {0x5111, 0x23,}, //48 {0x5112, 0x0 ,}, //00 {0x5113, 0xe3,}, //f8 {0x5114, 0x5c,}, //03 {0x5115, 0x5 ,}, //00 {0x5116, 0xff,}, //00 {0x5117, 0xf ,}, //00 {0x520a, 0x74,}, //f4 {0x520b, 0x64,}, //f4 {0x520c, 0xd4,}, //f4 {0x5004, 0x41,}, {0x5006, 0x41,}, {0x5301, 0x05,}, {0x5302, 0x0c,}, {0x5303, 0x1c,}, {0x5304, 0x2a,}, {0x5305, 0x39,}, {0x5306, 0x45,}, {0x5307, 0x53,}, {0x5308, 0x5d,}, {0x5309, 0x68,}, {0x530a, 0x7f,}, {0x530b, 0x91,}, {0x530c, 0xa5,}, {0x530d, 0xc6,}, {0x530e, 0xde,}, {0x530f, 0xef,}, {0x5310, 0x16,}, {0x5003, 0x80,}, {0x5500, 0x08,}, {0x5501, 0x48,}, {0x5502, 0x18,}, {0x5503, 0x04,}, {0x5504, 0x08,}, {0x5505, 0x48,}, {0x5506, 0x02,}, {0x5507, 0x16,}, {0x5508, 0x2d,}, {0x5509, 0x08,}, {0x550a, 0x48,}, {0x550b, 0x06,}, {0x550c, 0x04,}, {0x550d, 0x01,}, {0x5800, 0x02,}, {0x5803, 0x2e,}, {0x5804, 0x20,}, {0x5600, 0x00,}, {0x5601, 0x2c,}, {0x5602, 0x5a,}, {0x5603, 0x06,}, {0x5604, 0x1c,}, {0x5605, 0x65,}, {0x5606, 0x81,}, {0x5607, 0x9f,}, {0x5608, 0x8a,}, {0x5609, 0x15,}, {0x560a, 0x01,}, {0x560b, 0x9c,}, {0x3811, 0x07,}, {0x3813, 0x06,}, {0x3630, 0x79,}, }; static struct v4l2_subdev_info ov7695_subdev_info[] = { { .code = V4L2_MBUS_FMT_YUYV8_2X8, .colorspace = V4L2_COLORSPACE_JPEG, .fmt = 1, .order = 0, }, }; static struct msm_camera_i2c_reg_conf ov7695_start_settings[] = { {0x301a, 0xf0}, }; static struct msm_camera_i2c_reg_conf ov7695_stop_settings[] = { {0x301a, 0xf4}, }; static const struct i2c_device_id ov7695_i2c_id[] = { {OV7695_SENSOR_NAME, (kernel_ulong_t)&ov7695_s_ctrl}, { } }; static int32_t msm_ov7695_i2c_probe(struct i2c_client *client, const struct i2c_device_id *id) { return msm_sensor_i2c_probe(client, id, &ov7695_s_ctrl); } static struct i2c_driver ov7695_i2c_driver = { .id_table = ov7695_i2c_id, .probe = msm_ov7695_i2c_probe, .driver = { .name = OV7695_SENSOR_NAME, }, }; static struct msm_camera_i2c_client ov7695_sensor_i2c_client = { .addr_type = MSM_CAMERA_I2C_WORD_ADDR, }; static const struct of_device_id ov7695_dt_match[] = { {.compatible = "ovti,ov7695", .data = &ov7695_s_ctrl}, {} }; MODULE_DEVICE_TABLE(of, ov7695_dt_match); static int32_t ov7695_platform_probe(struct platform_device *pdev) { int32_t rc; const struct of_device_id *match; match = of_match_device(ov7695_dt_match, &pdev->dev); rc = msm_sensor_platform_probe(pdev, match->data); return rc; } static struct platform_driver ov7695_platform_driver = { .driver = { .name = "ovti,ov7695", .owner = THIS_MODULE, .of_match_table = ov7695_dt_match, }, .probe = ov7695_platform_probe, }; static int __init ov7695_init_module(void) { int32_t rc; pr_err("%s:%d\n", __func__, __LINE__); rc = platform_driver_register(&ov7695_platform_driver); if (!rc) return rc; pr_err("%s:%d rc %d\n", __func__, __LINE__, rc); return i2c_add_driver(&ov7695_i2c_driver); } static void __exit ov7695_exit_module(void) { pr_err("%s:%d\n", __func__, __LINE__); if (ov7695_s_ctrl.pdev) { msm_sensor_free_sensor_data(&ov7695_s_ctrl); platform_driver_unregister(&ov7695_platform_driver); } else i2c_del_driver(&ov7695_i2c_driver); return; } int32_t ov7695_sensor_config(struct msm_sensor_ctrl_t *s_ctrl, void __user *argp) { struct sensorb_cfg_data *cdata = (struct sensorb_cfg_data *)argp; long rc = 0; int32_t i = 0; mutex_lock(s_ctrl->msm_sensor_mutex); CDBG("%s:%d %s cfgtype = %d\n", __func__, __LINE__, s_ctrl->sensordata->sensor_name, cdata->cfgtype); switch (cdata->cfgtype) { case CFG_GET_SENSOR_INFO: memcpy(cdata->cfg.sensor_info.sensor_name, s_ctrl->sensordata->sensor_name, sizeof(cdata->cfg.sensor_info.sensor_name)); cdata->cfg.sensor_info.session_id = s_ctrl->sensordata->sensor_info->session_id; for (i = 0; i < SUB_MODULE_MAX; i++) cdata->cfg.sensor_info.subdev_id[i] = s_ctrl->sensordata->sensor_info->subdev_id[i]; cdata->cfg.sensor_info.is_mount_angle_valid = s_ctrl->sensordata->sensor_info->is_mount_angle_valid; cdata->cfg.sensor_info.sensor_mount_angle = s_ctrl->sensordata->sensor_info->sensor_mount_angle; CDBG("%s:%d sensor name %s\n", __func__, __LINE__, cdata->cfg.sensor_info.sensor_name); CDBG("%s:%d session id %d\n", __func__, __LINE__, cdata->cfg.sensor_info.session_id); for (i = 0; i < SUB_MODULE_MAX; i++) CDBG("%s:%d subdev_id[%d] %d\n", __func__, __LINE__, i, cdata->cfg.sensor_info.subdev_id[i]); CDBG("%s:%d mount angle valid %d value %d\n", __func__, __LINE__, cdata->cfg.sensor_info.is_mount_angle_valid, cdata->cfg.sensor_info.sensor_mount_angle); break; case CFG_SET_INIT_SETTING: /* 1. Write Recommend settings */ /* 2. Write change settings */ rc = s_ctrl->sensor_i2c_client->i2c_func_tbl-> i2c_write_conf_tbl( s_ctrl->sensor_i2c_client, ov7695_recommend_settings, ARRAY_SIZE(ov7695_recommend_settings), MSM_CAMERA_I2C_BYTE_DATA); break; case CFG_SET_RESOLUTION: { /*copy from user the desired resoltuion*/ enum msm_sensor_resolution_t res = MSM_SENSOR_INVALID_RES; if (copy_from_user(&res, (void *)cdata->cfg.setting, sizeof(enum msm_sensor_resolution_t))) { pr_err("%s:%d failed\n", __func__, __LINE__); rc = -EFAULT; break; } pr_err("%s:%d res =%d\n", __func__, __LINE__, res); if (res == MSM_SENSOR_RES_FULL) { rc = s_ctrl->sensor_i2c_client->i2c_func_tbl-> i2c_write_conf_tbl( s_ctrl->sensor_i2c_client, ov7695_vga_settings, ARRAY_SIZE(ov7695_vga_settings), MSM_CAMERA_I2C_BYTE_DATA); pr_err("%s:%d res =%d\n ov7695_vga_settings ", __func__, __LINE__, res); } else { pr_err("%s:%d failed resoultion set\n", __func__, __LINE__); rc = -EFAULT; } } break; case CFG_SET_STOP_STREAM: rc = s_ctrl->sensor_i2c_client->i2c_func_tbl-> i2c_write_conf_tbl( s_ctrl->sensor_i2c_client, ov7695_stop_settings, ARRAY_SIZE(ov7695_stop_settings), MSM_CAMERA_I2C_BYTE_DATA); break; case CFG_SET_START_STREAM: rc = s_ctrl->sensor_i2c_client->i2c_func_tbl-> i2c_write_conf_tbl( s_ctrl->sensor_i2c_client, ov7695_start_settings, ARRAY_SIZE(ov7695_start_settings), MSM_CAMERA_I2C_BYTE_DATA); break; case CFG_GET_SENSOR_INIT_PARAMS: cdata->cfg.sensor_init_params.modes_supported = s_ctrl->sensordata->sensor_info->modes_supported; cdata->cfg.sensor_init_params.position = s_ctrl->sensordata->sensor_info->position; cdata->cfg.sensor_init_params.sensor_mount_angle = s_ctrl->sensordata->sensor_info->sensor_mount_angle; pr_err("%s:%d init params mode %d pos %d mount %d\n", __func__, __LINE__, cdata->cfg.sensor_init_params.modes_supported, cdata->cfg.sensor_init_params.position, cdata->cfg.sensor_init_params.sensor_mount_angle); break; case CFG_SET_SLAVE_INFO: { struct msm_camera_sensor_slave_info *sensor_slave_info = NULL; struct msm_camera_power_ctrl_t *p_ctrl; uint16_t size; sensor_slave_info = kmalloc(sizeof(struct msm_camera_sensor_slave_info) * 1, GFP_KERNEL); if (!sensor_slave_info) { rc = -ENOMEM; break; } if (copy_from_user(sensor_slave_info, (void *)cdata->cfg.setting, sizeof(struct msm_camera_sensor_slave_info))) { pr_err("%s:%d failed\n", __func__, __LINE__); rc = -EFAULT; break; } /* Update sensor slave address */ if (sensor_slave_info->slave_addr) s_ctrl->sensor_i2c_client->cci_client->sid = sensor_slave_info->slave_addr >> 1; /* Update sensor address type */ s_ctrl->sensor_i2c_client->addr_type = sensor_slave_info->addr_type; /* Update power up / down sequence */ p_ctrl = &s_ctrl->sensordata->power_info; size = sensor_slave_info->power_setting_array.size; if (p_ctrl->power_setting_size < size) { struct msm_sensor_power_setting *tmp; tmp = kmalloc(sizeof(struct msm_sensor_power_setting) * size, GFP_KERNEL); if (!tmp) { pr_err("%s: failed to alloc mem\n", __func__); rc = -ENOMEM; break; } kfree(p_ctrl->power_setting); p_ctrl->power_setting = tmp; } p_ctrl->power_setting_size = size; rc = copy_from_user(p_ctrl->power_setting, (void *) sensor_slave_info->power_setting_array.power_setting, size * sizeof(struct msm_sensor_power_setting)); if (rc) { pr_err("%s:%d failed\n", __func__, __LINE__); rc = -EFAULT; break; } break; } case CFG_WRITE_I2C_ARRAY: { struct msm_camera_i2c_reg_setting conf_array; struct msm_camera_i2c_reg_array *reg_setting = NULL; if (copy_from_user(&conf_array, (void *)cdata->cfg.setting, sizeof(struct msm_camera_i2c_reg_setting))) { pr_err("%s:%d failed\n", __func__, __LINE__); rc = -EFAULT; break; } reg_setting = kzalloc(conf_array.size * (sizeof(struct msm_camera_i2c_reg_array)), GFP_KERNEL); if (!reg_setting) { pr_err("%s:%d failed\n", __func__, __LINE__); rc = -ENOMEM; break; } if (copy_from_user(reg_setting, (void *)conf_array.reg_setting, conf_array.size * sizeof(struct msm_camera_i2c_reg_array))) { pr_err("%s:%d failed\n", __func__, __LINE__); kfree(reg_setting); rc = -EFAULT; break; } conf_array.reg_setting = reg_setting; rc = s_ctrl->sensor_i2c_client->i2c_func_tbl->i2c_write_table( s_ctrl->sensor_i2c_client, &conf_array); kfree(reg_setting); break; } case CFG_WRITE_I2C_SEQ_ARRAY: { struct msm_camera_i2c_seq_reg_setting conf_array; struct msm_camera_i2c_seq_reg_array *reg_setting = NULL; if (copy_from_user(&conf_array, (void *)cdata->cfg.setting, sizeof(struct msm_camera_i2c_seq_reg_setting))) { pr_err("%s:%d failed\n", __func__, __LINE__); rc = -EFAULT; break; } reg_setting = kzalloc(conf_array.size * (sizeof(struct msm_camera_i2c_seq_reg_array)), GFP_KERNEL); if (!reg_setting) { pr_err("%s:%d failed\n", __func__, __LINE__); rc = -ENOMEM; break; } if (copy_from_user(reg_setting, (void *)conf_array.reg_setting, conf_array.size * sizeof(struct msm_camera_i2c_seq_reg_array))) { pr_err("%s:%d failed\n", __func__, __LINE__); kfree(reg_setting); rc = -EFAULT; break; } conf_array.reg_setting = reg_setting; rc = s_ctrl->sensor_i2c_client->i2c_func_tbl-> i2c_write_seq_table(s_ctrl->sensor_i2c_client, &conf_array); kfree(reg_setting); break; } case CFG_POWER_UP: if (s_ctrl->func_tbl->sensor_power_up) rc = s_ctrl->func_tbl->sensor_power_up(s_ctrl); else rc = -EFAULT; break; case CFG_POWER_DOWN: if (s_ctrl->func_tbl->sensor_power_down) rc = s_ctrl->func_tbl->sensor_power_down(s_ctrl); else rc = -EFAULT; break; case CFG_SET_STOP_STREAM_SETTING: { struct msm_camera_i2c_reg_setting *stop_setting = &s_ctrl->stop_setting; struct msm_camera_i2c_reg_array *reg_setting = NULL; if (copy_from_user(stop_setting, (void *)cdata->cfg.setting, sizeof(struct msm_camera_i2c_reg_setting))) { pr_err("%s:%d failed\n", __func__, __LINE__); rc = -EFAULT; break; } reg_setting = stop_setting->reg_setting; stop_setting->reg_setting = kzalloc(stop_setting->size * (sizeof(struct msm_camera_i2c_reg_array)), GFP_KERNEL); if (!stop_setting->reg_setting) { pr_err("%s:%d failed\n", __func__, __LINE__); rc = -ENOMEM; break; } if (copy_from_user(stop_setting->reg_setting, (void *)reg_setting, stop_setting->size * sizeof(struct msm_camera_i2c_reg_array))) { pr_err("%s:%d failed\n", __func__, __LINE__); kfree(stop_setting->reg_setting); stop_setting->reg_setting = NULL; stop_setting->size = 0; rc = -EFAULT; break; } break; } case CFG_SET_STREAM_TYPE: { enum msm_camera_stream_type_t s_type = MSM_CAMERA_STREAM_INVALID; if (copy_from_user(&s_type, (void *)cdata->cfg.setting, sizeof(enum msm_camera_stream_type_t))) { pr_err("%s:%d failed\n", __func__, __LINE__); rc = -EFAULT; break; } s_ctrl->camera_stream_type = s_type; break; } case CFG_SET_SATURATION: break; case CFG_SET_CONTRAST: break; case CFG_SET_SHARPNESS: break; case CFG_SET_AUTOFOCUS: /* TO-DO: set the Auto Focus */ pr_debug("%s: Setting Auto Focus", __func__); break; case CFG_CANCEL_AUTOFOCUS: /* TO-DO: Cancel the Auto Focus */ pr_debug("%s: Cancelling Auto Focus", __func__); break; case CFG_SET_ISO: break; case CFG_SET_EXPOSURE_COMPENSATION: break; case CFG_SET_EFFECT: break; case CFG_SET_ANTIBANDING: break; case CFG_SET_BESTSHOT_MODE: break; case CFG_SET_WHITE_BALANCE: break; default: rc = -EFAULT; break; } mutex_unlock(s_ctrl->msm_sensor_mutex); return rc; } static struct msm_sensor_fn_t ov7695_sensor_func_tbl = { .sensor_config = ov7695_sensor_config, .sensor_power_up = msm_sensor_power_up, .sensor_power_down = msm_sensor_power_down, .sensor_match_id = msm_sensor_match_id, }; static struct msm_sensor_ctrl_t ov7695_s_ctrl = { .sensor_i2c_client = &ov7695_sensor_i2c_client, .power_setting_array.power_setting = ov7695_power_setting, .power_setting_array.size = ARRAY_SIZE(ov7695_power_setting), .msm_sensor_mutex = &ov7695_mut, .sensor_v4l2_subdev_info = ov7695_subdev_info, .sensor_v4l2_subdev_info_size = ARRAY_SIZE(ov7695_subdev_info), .func_tbl = &ov7695_sensor_func_tbl, }; module_init(ov7695_init_module); module_exit(ov7695_exit_module); MODULE_DESCRIPTION("Aptina 0.3MP YUV sensor driver"); MODULE_LICENSE("GPL v2"); Loading
Documentation/devicetree/bindings/media/video/msm-cci.txt +1 −0 Original line number Diff line number Diff line Loading @@ -62,6 +62,7 @@ Required properties: - "shinetech,hi256" - "shinetech,s5k4e1" - "ovti,ov5645" - "ovti,ov7695" - "qcom,mt9m114" - reg : should contain i2c slave address of the device - qcom,csiphy-sd-index : should contain csiphy instance that will used to Loading
arch/arm/boot/dts/qcom/msm8916-camera-sensor-qrd-skui.dtsi +43 −0 Original line number Diff line number Diff line Loading @@ -129,6 +129,49 @@ }; qcom,camera@42 { compatible = "ovti,ov7695"; reg = <0x42 0x0>; qcom,slave-id = <0x42 0x300a 0x7695>; qcom,csiphy-sd-index = <1>; qcom,csid-sd-index = <1>; qcom,mount-angle = <90>; qcom,sensor-name = "ov7695"; cam_vdig-supply = <&pm8916_l2>; cam_vana-supply = <&pm8916_l17>; cam_vio-supply = <&pm8916_l6>; cam_vaf-supply = <&pm8916_l10>; qcom,cam-vreg-name = "cam_vdig", "cam_vio", "cam_vana", "cam_vaf"; qcom,cam-vreg-type = <0 1 0 0>; qcom,cam-vreg-min-voltage = <1200000 0 2850000 2800000>; qcom,cam-vreg-max-voltage = <1200000 0 2850000 2800000>; qcom,cam-vreg-op-mode = <200000 0 80000 100000>; pinctrl-names = "cam_default", "cam_suspend"; pinctrl-0 = <&cam_sensor_mclk1_default &cam_sensor_front_default>; pinctrl-1 = <&cam_sensor_mclk1_sleep &cam_sensor_front_sleep>; gpios = <&msm_gpio 27 0>, <&msm_gpio 28 0>, <&msm_gpio 33 0>; qcom,gpio-reset = <1>; qcom,gpio-standby = <2>; qcom,gpio-req-tbl-num = <0 1 2>; qcom,gpio-req-tbl-flags = <1 0 0>; qcom,gpio-req-tbl-label = "CAMIF_MCLK", "CAM_RESET", "CAM_STANDBY"; qcom,csi-lane-assign = <0x4320>; qcom,csi-lane-mask = <0x3>; qcom,sensor-position = <1>; qcom,sensor-mode = <0>; qcom,cci-master = <0>; qcom,mclk-23880000; status = "ok"; clocks = <&clock_gcc clk_mclk1_clk_src>, <&clock_gcc clk_gcc_camss_mclk1_clk>; clock-names = "cam_src_clk", "cam_clk"; }; qcom,camera@0 { cell-index = <0>; compatible = "qcom,camera"; Loading
drivers/media/platform/msm/camera_v2/Kconfig +9 −0 Original line number Diff line number Diff line Loading @@ -173,6 +173,15 @@ config OV5645 1280 * 270. It does not support auto focus. It supports few special effects like saturation. config OV7695 bool "Sensor OV7695 (YUV 0.3MP)" depends on MSMB_CAMERA ---help--- OV7695 is Omnivision YUV sensor. It supports 0.3 MP preview and snapshot. The preview and snapshot resolution shall be VGA. It does not support auto focus. It supports few special effects like saturation. config SP1628 bool "Sensor SP1628 (YUV 720P)" depends on MSMB_CAMERA Loading
drivers/media/platform/msm/camera_v2/sensor/Makefile +1 −0 Original line number Diff line number Diff line Loading @@ -7,3 +7,4 @@ obj-$(CONFIG_MSMB_CAMERA) += cci/ io/ csiphy/ csid/ actuator/ flash/ eeprom/ ois obj-$(CONFIG_MSM_CAMERA_SENSOR) += msm_sensor_init.o msm_sensor_driver.o msm_sensor.o obj-$(CONFIG_MT9M114) += mt9m114.o obj-$(CONFIG_OV5645) += ov5645.o obj-$(CONFIG_OV5645) += ov7695.o
drivers/media/platform/msm/camera_v2/sensor/ov7695.c 0 → 100644 +669 −0 Original line number Diff line number Diff line /* Copyright (c) 2014, 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 "msm_sensor.h" #include "msm_cci.h" #include "msm_camera_io_util.h" #define OV7695_SENSOR_NAME "ov7695" #define PLATFORM_DRIVER_NAME "msm_camera_ov7695" #define ov7695_obj ov7695_##obj /*#define CONFIG_MSMB_CAMERA_DEBUG*/ #undef CDBG #ifdef CONFIG_MSMB_CAMERA_DEBUG #define CDBG(fmt, args...) pr_err(fmt, ##args) #else #define CDBG(fmt, args...) do { } while (0) #endif DEFINE_MSM_MUTEX(ov7695_mut); static struct msm_sensor_ctrl_t ov7695_s_ctrl; static struct msm_sensor_power_setting ov7695_power_setting[] = { { .seq_type = SENSOR_GPIO, .seq_val = SENSOR_GPIO_STANDBY, .config_val = GPIO_OUT_LOW, .delay = 0, }, { .seq_type = SENSOR_GPIO, .seq_val = SENSOR_GPIO_RESET, .config_val = GPIO_OUT_LOW, .delay = 10, }, { .seq_type = SENSOR_VREG, .seq_val = CAM_VAF, .config_val = 0, .delay = 5, }, { .seq_type = SENSOR_VREG, .seq_val = CAM_VIO, .config_val = 0, .delay = 5, }, { .seq_type = SENSOR_VREG, .seq_val = CAM_VANA, .config_val = 0, .delay = 0, }, { .seq_type = SENSOR_GPIO, .seq_val = SENSOR_GPIO_STANDBY, .config_val = GPIO_OUT_HIGH, .delay = 5, }, { .seq_type = SENSOR_GPIO, .seq_val = SENSOR_GPIO_RESET, .config_val = GPIO_OUT_HIGH, .delay = 10, }, { .seq_type = SENSOR_CLK, .seq_val = SENSOR_CAM_MCLK, .config_val = 24000000, .delay = 10, }, { .seq_type = SENSOR_I2C_MUX, .seq_val = 0, .config_val = 0, .delay = 0, }, }; static struct msm_camera_i2c_reg_conf ov7695_vga_settings[] = { {0x3630, 0x79,}, }; static struct msm_camera_i2c_reg_conf ov7695_recommend_settings[] = { {0x0103, 0x01,}, {0x0100, 0x01,}, {0x3620, 0x2f,}, {0x3623, 0x12,}, {0x3718, 0x88,}, {0x3703, 0x80,}, {0x3712, 0x40,}, {0x3706, 0x40,}, {0x3631, 0x44,}, {0x3632, 0x05,}, {0x3013, 0xd0,}, {0x3705, 0x1d,}, {0x3713, 0x0e,}, {0x3012, 0x0a,}, {0x3717, 0x18,}, {0x3621, 0x47,}, {0x0309, 0x24,}, {0x3820, 0x90,}, {0x4803, 0x08,}, {0x0101, 0x02,}, {0x5100, 0x01,}, {0x4500, 0x24,}, {0x5301, 0x05,}, {0x5302, 0x0c,}, {0x5303, 0x1c,}, {0x5304, 0x2a,}, {0x5305, 0x39,}, {0x5306, 0x45,}, {0x5307, 0x52,}, {0x5308, 0x5d,}, {0x5309, 0x68,}, {0x530a, 0x7f,}, {0x530b, 0x91,}, {0x530c, 0xa5,}, {0x530d, 0xc6,}, {0x530e, 0xde,}, {0x530f, 0xef,}, {0x5310, 0x16,}, {0x520a, 0x74,}, //f4 {0x520b, 0x64,}, //f4 {0x520c, 0xd4,}, //f4 {0x5504, 0x08,}, {0x5505, 0x48,}, {0x5506, 0x07,}, {0x5507, 0x0b,}, {0x3a18, 0x01,}, {0x3a19, 0x00,}, {0x3503, 0x03,}, {0x3500, 0x00,}, {0x3501, 0x21,}, {0x3502, 0x00,}, {0x350a, 0x00,}, {0x350b, 0x00,}, {0x4008, 0x02,}, {0x4009, 0x09,}, {0x3002, 0x09,}, {0x3024, 0x00,}, {0x3503, 0x00,}, {0x0101, 0x02,}, {0x5002, 0x48,}, {0x5910, 0x00,}, {0x3a0f, 0x58,}, {0x3a10, 0x50,}, {0x3a1b, 0x5a,}, {0x3a1e, 0x4e,}, {0x3a11, 0xa0,}, {0x3a1f, 0x28,}, {0x3a18, 0x00,}, {0x3a19, 0xf8,}, {0x3503, 0x00,}, {0x3a0d, 0x04,}, {0x5000, 0xff,}, {0x5001, 0x3f,}, {0x5100, 0x1 ,}, //01 {0x5101, 0x25,}, //48 {0x5102, 0x0 ,}, //00 {0x5103, 0xf3,}, //f8 {0x5104, 0x7f,}, //04 {0x5105, 0x5 ,}, //00 {0x5106, 0xff,}, //00 {0x5107, 0xf ,}, //00 {0x5108, 0x1 ,}, //01 {0x5109, 0x1f,}, //48 {0x510a, 0x0 ,}, //00 {0x510b, 0xde,}, //f8 {0x510c, 0x56,}, //03 {0x510d, 0x5 ,}, //00 {0x510e, 0xff,}, //00 {0x510f, 0xf ,}, //00 {0x5110, 0x1 ,}, //01 {0x5111, 0x23,}, //48 {0x5112, 0x0 ,}, //00 {0x5113, 0xe3,}, //f8 {0x5114, 0x5c,}, //03 {0x5115, 0x5 ,}, //00 {0x5116, 0xff,}, //00 {0x5117, 0xf ,}, //00 {0x520a, 0x74,}, //f4 {0x520b, 0x64,}, //f4 {0x520c, 0xd4,}, //f4 {0x5004, 0x41,}, {0x5006, 0x41,}, {0x5301, 0x05,}, {0x5302, 0x0c,}, {0x5303, 0x1c,}, {0x5304, 0x2a,}, {0x5305, 0x39,}, {0x5306, 0x45,}, {0x5307, 0x53,}, {0x5308, 0x5d,}, {0x5309, 0x68,}, {0x530a, 0x7f,}, {0x530b, 0x91,}, {0x530c, 0xa5,}, {0x530d, 0xc6,}, {0x530e, 0xde,}, {0x530f, 0xef,}, {0x5310, 0x16,}, {0x5003, 0x80,}, {0x5500, 0x08,}, {0x5501, 0x48,}, {0x5502, 0x18,}, {0x5503, 0x04,}, {0x5504, 0x08,}, {0x5505, 0x48,}, {0x5506, 0x02,}, {0x5507, 0x16,}, {0x5508, 0x2d,}, {0x5509, 0x08,}, {0x550a, 0x48,}, {0x550b, 0x06,}, {0x550c, 0x04,}, {0x550d, 0x01,}, {0x5800, 0x02,}, {0x5803, 0x2e,}, {0x5804, 0x20,}, {0x5600, 0x00,}, {0x5601, 0x2c,}, {0x5602, 0x5a,}, {0x5603, 0x06,}, {0x5604, 0x1c,}, {0x5605, 0x65,}, {0x5606, 0x81,}, {0x5607, 0x9f,}, {0x5608, 0x8a,}, {0x5609, 0x15,}, {0x560a, 0x01,}, {0x560b, 0x9c,}, {0x3811, 0x07,}, {0x3813, 0x06,}, {0x3630, 0x79,}, }; static struct v4l2_subdev_info ov7695_subdev_info[] = { { .code = V4L2_MBUS_FMT_YUYV8_2X8, .colorspace = V4L2_COLORSPACE_JPEG, .fmt = 1, .order = 0, }, }; static struct msm_camera_i2c_reg_conf ov7695_start_settings[] = { {0x301a, 0xf0}, }; static struct msm_camera_i2c_reg_conf ov7695_stop_settings[] = { {0x301a, 0xf4}, }; static const struct i2c_device_id ov7695_i2c_id[] = { {OV7695_SENSOR_NAME, (kernel_ulong_t)&ov7695_s_ctrl}, { } }; static int32_t msm_ov7695_i2c_probe(struct i2c_client *client, const struct i2c_device_id *id) { return msm_sensor_i2c_probe(client, id, &ov7695_s_ctrl); } static struct i2c_driver ov7695_i2c_driver = { .id_table = ov7695_i2c_id, .probe = msm_ov7695_i2c_probe, .driver = { .name = OV7695_SENSOR_NAME, }, }; static struct msm_camera_i2c_client ov7695_sensor_i2c_client = { .addr_type = MSM_CAMERA_I2C_WORD_ADDR, }; static const struct of_device_id ov7695_dt_match[] = { {.compatible = "ovti,ov7695", .data = &ov7695_s_ctrl}, {} }; MODULE_DEVICE_TABLE(of, ov7695_dt_match); static int32_t ov7695_platform_probe(struct platform_device *pdev) { int32_t rc; const struct of_device_id *match; match = of_match_device(ov7695_dt_match, &pdev->dev); rc = msm_sensor_platform_probe(pdev, match->data); return rc; } static struct platform_driver ov7695_platform_driver = { .driver = { .name = "ovti,ov7695", .owner = THIS_MODULE, .of_match_table = ov7695_dt_match, }, .probe = ov7695_platform_probe, }; static int __init ov7695_init_module(void) { int32_t rc; pr_err("%s:%d\n", __func__, __LINE__); rc = platform_driver_register(&ov7695_platform_driver); if (!rc) return rc; pr_err("%s:%d rc %d\n", __func__, __LINE__, rc); return i2c_add_driver(&ov7695_i2c_driver); } static void __exit ov7695_exit_module(void) { pr_err("%s:%d\n", __func__, __LINE__); if (ov7695_s_ctrl.pdev) { msm_sensor_free_sensor_data(&ov7695_s_ctrl); platform_driver_unregister(&ov7695_platform_driver); } else i2c_del_driver(&ov7695_i2c_driver); return; } int32_t ov7695_sensor_config(struct msm_sensor_ctrl_t *s_ctrl, void __user *argp) { struct sensorb_cfg_data *cdata = (struct sensorb_cfg_data *)argp; long rc = 0; int32_t i = 0; mutex_lock(s_ctrl->msm_sensor_mutex); CDBG("%s:%d %s cfgtype = %d\n", __func__, __LINE__, s_ctrl->sensordata->sensor_name, cdata->cfgtype); switch (cdata->cfgtype) { case CFG_GET_SENSOR_INFO: memcpy(cdata->cfg.sensor_info.sensor_name, s_ctrl->sensordata->sensor_name, sizeof(cdata->cfg.sensor_info.sensor_name)); cdata->cfg.sensor_info.session_id = s_ctrl->sensordata->sensor_info->session_id; for (i = 0; i < SUB_MODULE_MAX; i++) cdata->cfg.sensor_info.subdev_id[i] = s_ctrl->sensordata->sensor_info->subdev_id[i]; cdata->cfg.sensor_info.is_mount_angle_valid = s_ctrl->sensordata->sensor_info->is_mount_angle_valid; cdata->cfg.sensor_info.sensor_mount_angle = s_ctrl->sensordata->sensor_info->sensor_mount_angle; CDBG("%s:%d sensor name %s\n", __func__, __LINE__, cdata->cfg.sensor_info.sensor_name); CDBG("%s:%d session id %d\n", __func__, __LINE__, cdata->cfg.sensor_info.session_id); for (i = 0; i < SUB_MODULE_MAX; i++) CDBG("%s:%d subdev_id[%d] %d\n", __func__, __LINE__, i, cdata->cfg.sensor_info.subdev_id[i]); CDBG("%s:%d mount angle valid %d value %d\n", __func__, __LINE__, cdata->cfg.sensor_info.is_mount_angle_valid, cdata->cfg.sensor_info.sensor_mount_angle); break; case CFG_SET_INIT_SETTING: /* 1. Write Recommend settings */ /* 2. Write change settings */ rc = s_ctrl->sensor_i2c_client->i2c_func_tbl-> i2c_write_conf_tbl( s_ctrl->sensor_i2c_client, ov7695_recommend_settings, ARRAY_SIZE(ov7695_recommend_settings), MSM_CAMERA_I2C_BYTE_DATA); break; case CFG_SET_RESOLUTION: { /*copy from user the desired resoltuion*/ enum msm_sensor_resolution_t res = MSM_SENSOR_INVALID_RES; if (copy_from_user(&res, (void *)cdata->cfg.setting, sizeof(enum msm_sensor_resolution_t))) { pr_err("%s:%d failed\n", __func__, __LINE__); rc = -EFAULT; break; } pr_err("%s:%d res =%d\n", __func__, __LINE__, res); if (res == MSM_SENSOR_RES_FULL) { rc = s_ctrl->sensor_i2c_client->i2c_func_tbl-> i2c_write_conf_tbl( s_ctrl->sensor_i2c_client, ov7695_vga_settings, ARRAY_SIZE(ov7695_vga_settings), MSM_CAMERA_I2C_BYTE_DATA); pr_err("%s:%d res =%d\n ov7695_vga_settings ", __func__, __LINE__, res); } else { pr_err("%s:%d failed resoultion set\n", __func__, __LINE__); rc = -EFAULT; } } break; case CFG_SET_STOP_STREAM: rc = s_ctrl->sensor_i2c_client->i2c_func_tbl-> i2c_write_conf_tbl( s_ctrl->sensor_i2c_client, ov7695_stop_settings, ARRAY_SIZE(ov7695_stop_settings), MSM_CAMERA_I2C_BYTE_DATA); break; case CFG_SET_START_STREAM: rc = s_ctrl->sensor_i2c_client->i2c_func_tbl-> i2c_write_conf_tbl( s_ctrl->sensor_i2c_client, ov7695_start_settings, ARRAY_SIZE(ov7695_start_settings), MSM_CAMERA_I2C_BYTE_DATA); break; case CFG_GET_SENSOR_INIT_PARAMS: cdata->cfg.sensor_init_params.modes_supported = s_ctrl->sensordata->sensor_info->modes_supported; cdata->cfg.sensor_init_params.position = s_ctrl->sensordata->sensor_info->position; cdata->cfg.sensor_init_params.sensor_mount_angle = s_ctrl->sensordata->sensor_info->sensor_mount_angle; pr_err("%s:%d init params mode %d pos %d mount %d\n", __func__, __LINE__, cdata->cfg.sensor_init_params.modes_supported, cdata->cfg.sensor_init_params.position, cdata->cfg.sensor_init_params.sensor_mount_angle); break; case CFG_SET_SLAVE_INFO: { struct msm_camera_sensor_slave_info *sensor_slave_info = NULL; struct msm_camera_power_ctrl_t *p_ctrl; uint16_t size; sensor_slave_info = kmalloc(sizeof(struct msm_camera_sensor_slave_info) * 1, GFP_KERNEL); if (!sensor_slave_info) { rc = -ENOMEM; break; } if (copy_from_user(sensor_slave_info, (void *)cdata->cfg.setting, sizeof(struct msm_camera_sensor_slave_info))) { pr_err("%s:%d failed\n", __func__, __LINE__); rc = -EFAULT; break; } /* Update sensor slave address */ if (sensor_slave_info->slave_addr) s_ctrl->sensor_i2c_client->cci_client->sid = sensor_slave_info->slave_addr >> 1; /* Update sensor address type */ s_ctrl->sensor_i2c_client->addr_type = sensor_slave_info->addr_type; /* Update power up / down sequence */ p_ctrl = &s_ctrl->sensordata->power_info; size = sensor_slave_info->power_setting_array.size; if (p_ctrl->power_setting_size < size) { struct msm_sensor_power_setting *tmp; tmp = kmalloc(sizeof(struct msm_sensor_power_setting) * size, GFP_KERNEL); if (!tmp) { pr_err("%s: failed to alloc mem\n", __func__); rc = -ENOMEM; break; } kfree(p_ctrl->power_setting); p_ctrl->power_setting = tmp; } p_ctrl->power_setting_size = size; rc = copy_from_user(p_ctrl->power_setting, (void *) sensor_slave_info->power_setting_array.power_setting, size * sizeof(struct msm_sensor_power_setting)); if (rc) { pr_err("%s:%d failed\n", __func__, __LINE__); rc = -EFAULT; break; } break; } case CFG_WRITE_I2C_ARRAY: { struct msm_camera_i2c_reg_setting conf_array; struct msm_camera_i2c_reg_array *reg_setting = NULL; if (copy_from_user(&conf_array, (void *)cdata->cfg.setting, sizeof(struct msm_camera_i2c_reg_setting))) { pr_err("%s:%d failed\n", __func__, __LINE__); rc = -EFAULT; break; } reg_setting = kzalloc(conf_array.size * (sizeof(struct msm_camera_i2c_reg_array)), GFP_KERNEL); if (!reg_setting) { pr_err("%s:%d failed\n", __func__, __LINE__); rc = -ENOMEM; break; } if (copy_from_user(reg_setting, (void *)conf_array.reg_setting, conf_array.size * sizeof(struct msm_camera_i2c_reg_array))) { pr_err("%s:%d failed\n", __func__, __LINE__); kfree(reg_setting); rc = -EFAULT; break; } conf_array.reg_setting = reg_setting; rc = s_ctrl->sensor_i2c_client->i2c_func_tbl->i2c_write_table( s_ctrl->sensor_i2c_client, &conf_array); kfree(reg_setting); break; } case CFG_WRITE_I2C_SEQ_ARRAY: { struct msm_camera_i2c_seq_reg_setting conf_array; struct msm_camera_i2c_seq_reg_array *reg_setting = NULL; if (copy_from_user(&conf_array, (void *)cdata->cfg.setting, sizeof(struct msm_camera_i2c_seq_reg_setting))) { pr_err("%s:%d failed\n", __func__, __LINE__); rc = -EFAULT; break; } reg_setting = kzalloc(conf_array.size * (sizeof(struct msm_camera_i2c_seq_reg_array)), GFP_KERNEL); if (!reg_setting) { pr_err("%s:%d failed\n", __func__, __LINE__); rc = -ENOMEM; break; } if (copy_from_user(reg_setting, (void *)conf_array.reg_setting, conf_array.size * sizeof(struct msm_camera_i2c_seq_reg_array))) { pr_err("%s:%d failed\n", __func__, __LINE__); kfree(reg_setting); rc = -EFAULT; break; } conf_array.reg_setting = reg_setting; rc = s_ctrl->sensor_i2c_client->i2c_func_tbl-> i2c_write_seq_table(s_ctrl->sensor_i2c_client, &conf_array); kfree(reg_setting); break; } case CFG_POWER_UP: if (s_ctrl->func_tbl->sensor_power_up) rc = s_ctrl->func_tbl->sensor_power_up(s_ctrl); else rc = -EFAULT; break; case CFG_POWER_DOWN: if (s_ctrl->func_tbl->sensor_power_down) rc = s_ctrl->func_tbl->sensor_power_down(s_ctrl); else rc = -EFAULT; break; case CFG_SET_STOP_STREAM_SETTING: { struct msm_camera_i2c_reg_setting *stop_setting = &s_ctrl->stop_setting; struct msm_camera_i2c_reg_array *reg_setting = NULL; if (copy_from_user(stop_setting, (void *)cdata->cfg.setting, sizeof(struct msm_camera_i2c_reg_setting))) { pr_err("%s:%d failed\n", __func__, __LINE__); rc = -EFAULT; break; } reg_setting = stop_setting->reg_setting; stop_setting->reg_setting = kzalloc(stop_setting->size * (sizeof(struct msm_camera_i2c_reg_array)), GFP_KERNEL); if (!stop_setting->reg_setting) { pr_err("%s:%d failed\n", __func__, __LINE__); rc = -ENOMEM; break; } if (copy_from_user(stop_setting->reg_setting, (void *)reg_setting, stop_setting->size * sizeof(struct msm_camera_i2c_reg_array))) { pr_err("%s:%d failed\n", __func__, __LINE__); kfree(stop_setting->reg_setting); stop_setting->reg_setting = NULL; stop_setting->size = 0; rc = -EFAULT; break; } break; } case CFG_SET_STREAM_TYPE: { enum msm_camera_stream_type_t s_type = MSM_CAMERA_STREAM_INVALID; if (copy_from_user(&s_type, (void *)cdata->cfg.setting, sizeof(enum msm_camera_stream_type_t))) { pr_err("%s:%d failed\n", __func__, __LINE__); rc = -EFAULT; break; } s_ctrl->camera_stream_type = s_type; break; } case CFG_SET_SATURATION: break; case CFG_SET_CONTRAST: break; case CFG_SET_SHARPNESS: break; case CFG_SET_AUTOFOCUS: /* TO-DO: set the Auto Focus */ pr_debug("%s: Setting Auto Focus", __func__); break; case CFG_CANCEL_AUTOFOCUS: /* TO-DO: Cancel the Auto Focus */ pr_debug("%s: Cancelling Auto Focus", __func__); break; case CFG_SET_ISO: break; case CFG_SET_EXPOSURE_COMPENSATION: break; case CFG_SET_EFFECT: break; case CFG_SET_ANTIBANDING: break; case CFG_SET_BESTSHOT_MODE: break; case CFG_SET_WHITE_BALANCE: break; default: rc = -EFAULT; break; } mutex_unlock(s_ctrl->msm_sensor_mutex); return rc; } static struct msm_sensor_fn_t ov7695_sensor_func_tbl = { .sensor_config = ov7695_sensor_config, .sensor_power_up = msm_sensor_power_up, .sensor_power_down = msm_sensor_power_down, .sensor_match_id = msm_sensor_match_id, }; static struct msm_sensor_ctrl_t ov7695_s_ctrl = { .sensor_i2c_client = &ov7695_sensor_i2c_client, .power_setting_array.power_setting = ov7695_power_setting, .power_setting_array.size = ARRAY_SIZE(ov7695_power_setting), .msm_sensor_mutex = &ov7695_mut, .sensor_v4l2_subdev_info = ov7695_subdev_info, .sensor_v4l2_subdev_info_size = ARRAY_SIZE(ov7695_subdev_info), .func_tbl = &ov7695_sensor_func_tbl, }; module_init(ov7695_init_module); module_exit(ov7695_exit_module); MODULE_DESCRIPTION("Aptina 0.3MP YUV sensor driver"); MODULE_LICENSE("GPL v2");