Merge "msm: camera: Write a few registers before camera probe"
diff --git a/drivers/media/platform/msm/camera_v2/sensor/msm_sensor.c b/drivers/media/platform/msm/camera_v2/sensor/msm_sensor.c
index c0c83e5..6f39956 100644
--- a/drivers/media/platform/msm/camera_v2/sensor/msm_sensor.c
+++ b/drivers/media/platform/msm/camera_v2/sensor/msm_sensor.c
@@ -82,9 +82,13 @@
int32_t msm_sensor_free_sensor_data(struct msm_sensor_ctrl_t *s_ctrl)
{
+ struct msm_camera_sensor_slave_info *slave_info = NULL;
+
if (!s_ctrl->pdev && !s_ctrl->sensor_i2c_client->client)
return 0;
kfree(s_ctrl->sensordata->slave_info);
+ slave_info = s_ctrl->sensordata->cam_slave_info;
+ kfree(slave_info->sensor_id_info.setting.reg_setting);
kfree(s_ctrl->sensordata->cam_slave_info);
kfree(s_ctrl->sensordata->actuator_info);
kfree(s_ctrl->sensordata->power_info.gpio_conf->gpio_num_info);
@@ -261,6 +265,17 @@
return -EINVAL;
}
+ if (slave_info->setting && slave_info->setting->size > 0) {
+ rc = s_ctrl->sensor_i2c_client->i2c_func_tbl->
+ i2c_write_table(s_ctrl->sensor_i2c_client,
+ slave_info->setting);
+ if (rc < 0)
+ pr_err("Write array failed prior to probe\n");
+
+ } else {
+ CDBG("No writes needed for this sensor before probe\n");
+ }
+
rc = sensor_i2c_client->i2c_func_tbl->i2c_read(
sensor_i2c_client, slave_info->sensor_id_reg_addr,
&chipid, MSM_CAMERA_I2C_WORD_DATA);
diff --git a/drivers/media/platform/msm/camera_v2/sensor/msm_sensor_driver.c b/drivers/media/platform/msm/camera_v2/sensor/msm_sensor_driver.c
index f80de3a..7832181 100644
--- a/drivers/media/platform/msm/camera_v2/sensor/msm_sensor_driver.c
+++ b/drivers/media/platform/msm/camera_v2/sensor/msm_sensor_driver.c
@@ -757,6 +757,8 @@
unsigned long mount_pos = 0;
uint32_t is_yuv;
+ struct msm_camera_i2c_reg_array *reg_setting = NULL;
+ struct msm_sensor_id_info_t *id_info = NULL;
/* Validate input parameters */
if (!setting) {
@@ -805,7 +807,54 @@
slave_info->camera_id = slave_info32->camera_id;
slave_info->i2c_freq_mode = slave_info32->i2c_freq_mode;
- slave_info->sensor_id_info = slave_info32->sensor_id_info;
+ slave_info->sensor_id_info.sensor_id_reg_addr =
+ slave_info32->sensor_id_info.sensor_id_reg_addr;
+ slave_info->sensor_id_info.sensor_id_mask =
+ slave_info32->sensor_id_info.sensor_id_mask;
+ slave_info->sensor_id_info.sensor_id =
+ slave_info32->sensor_id_info.sensor_id;
+
+ slave_info->sensor_id_info.setting.addr_type =
+ slave_info32->sensor_id_info.setting.addr_type;
+ slave_info->sensor_id_info.setting.data_type =
+ slave_info32->sensor_id_info.setting.data_type;
+ slave_info->sensor_id_info.setting.delay =
+ slave_info32->sensor_id_info.setting.delay;
+ slave_info->sensor_id_info.setting.size =
+ slave_info32->sensor_id_info.setting.size;
+
+ if (!slave_info->sensor_id_info.setting.size ||
+ (slave_info->sensor_id_info.setting.size >
+ I2C_REG_DATA_MAX)) {
+ CDBG("%s:No writes needed to probe\n", __func__);
+ slave_info->sensor_id_info.setting.reg_setting = NULL;
+ } else {
+ id_info = &(slave_info->sensor_id_info);
+ reg_setting =
+ kzalloc(id_info->setting.size *
+ (sizeof
+ (struct msm_camera_i2c_reg_array)),
+ GFP_KERNEL);
+ if (!reg_setting) {
+ rc = -ENOMEM;
+ goto free_slave_info;
+ }
+ if (copy_from_user(reg_setting,
+ (void __user *)
+ compat_ptr(slave_info32->sensor_id_info.
+ setting.reg_setting),
+ slave_info->sensor_id_info.setting.size *
+ sizeof(struct msm_camera_i2c_reg_array))) {
+ pr_err("%s:%d: sensor id info copy failed\n",
+ __func__, __LINE__);
+ kfree(reg_setting);
+ rc = -EFAULT;
+ goto free_slave_info;
+ }
+
+ slave_info->sensor_id_info.setting.reg_setting =
+ reg_setting;
+ }
slave_info->slave_addr = slave_info32->slave_addr;
slave_info->power_setting_array.size =
@@ -841,6 +890,37 @@
rc = -EFAULT;
goto free_slave_info;
}
+ if (!slave_info->sensor_id_info.setting.size ||
+ slave_info->sensor_id_info.setting.size >
+ I2C_REG_DATA_MAX) {
+ CDBG("%s:No writes needed to probe\n", __func__);
+ slave_info->sensor_id_info.setting.reg_setting = NULL;
+ } else {
+ id_info = &(slave_info->sensor_id_info);
+ reg_setting =
+ kzalloc(id_info->setting.size *
+ (sizeof
+ (struct msm_camera_i2c_reg_array)),
+ GFP_KERNEL);
+ if (!reg_setting) {
+ rc = -ENOMEM;
+ goto free_slave_info;
+ }
+ if (copy_from_user(reg_setting,
+ (void __user *)
+ slave_info->sensor_id_info.setting.reg_setting,
+ slave_info->sensor_id_info.setting.size *
+ sizeof(struct msm_camera_i2c_reg_array))) {
+ pr_err("%s:%d: sensor id info copy failed\n",
+ __func__, __LINE__);
+ kfree(reg_setting);
+ rc = -EFAULT;
+ goto free_slave_info;
+ }
+
+ slave_info->sensor_id_info.setting.reg_setting =
+ reg_setting;
+ }
}
if (strlen(slave_info->sensor_name) >= MAX_SENSOR_NAME ||
@@ -956,6 +1036,7 @@
slave_info->sensor_id_info.sensor_id_reg_addr;
camera_info->sensor_id = slave_info->sensor_id_info.sensor_id;
camera_info->sensor_id_mask = slave_info->sensor_id_info.sensor_id_mask;
+ camera_info->setting = &(slave_info->sensor_id_info.setting);
/* Fill CCI master, slave address and CCI default params */
if (!s_ctrl->sensor_i2c_client) {
@@ -1116,6 +1197,7 @@
free_camera_info:
kfree(camera_info);
free_slave_info:
+ kfree(slave_info->sensor_id_info.setting.reg_setting);
kfree(slave_info);
return rc;
}
diff --git a/include/media/msm_cam_sensor.h b/include/media/msm_cam_sensor.h
index 2c8b651..54cd27b 100644
--- a/include/media/msm_cam_sensor.h
+++ b/include/media/msm_cam_sensor.h
@@ -26,6 +26,21 @@
uint16_t size_down;
};
+struct msm_camera_i2c_reg_setting32 {
+ compat_uptr_t reg_setting;
+ uint16_t size;
+ enum msm_camera_i2c_reg_addr_type addr_type;
+ enum msm_camera_i2c_data_type data_type;
+ uint16_t delay;
+};
+
+struct msm_sensor_id_info_t32 {
+ unsigned short sensor_id_reg_addr;
+ unsigned short sensor_id;
+ unsigned short sensor_id_mask;
+ struct msm_camera_i2c_reg_setting32 setting;
+};
+
struct msm_camera_sensor_slave_info32 {
char sensor_name[32];
char eeprom_name[32];
@@ -36,7 +51,7 @@
uint16_t slave_addr;
enum i2c_freq_mode_t i2c_freq_mode;
enum msm_camera_i2c_reg_addr_type addr_type;
- struct msm_sensor_id_info_t sensor_id_info;
+ struct msm_sensor_id_info_t32 sensor_id_info;
struct msm_sensor_power_setting_array32 power_setting_array;
uint8_t is_init_params_valid;
struct msm_sensor_init_params sensor_init_params;
@@ -128,14 +143,6 @@
uint16_t delay;
};
-struct msm_camera_i2c_reg_setting32 {
- compat_uptr_t reg_setting;
- uint16_t size;
- enum msm_camera_i2c_reg_addr_type addr_type;
- enum msm_camera_i2c_data_type data_type;
- uint16_t delay;
-};
-
struct msm_camera_i2c_array_write_config32 {
struct msm_camera_i2c_reg_setting32 conf_array;
uint16_t slave_addr;
diff --git a/include/soc/qcom/camera2.h b/include/soc/qcom/camera2.h
index c529aff..5139d22 100644
--- a/include/soc/qcom/camera2.h
+++ b/include/soc/qcom/camera2.h
@@ -47,6 +47,7 @@
uint16_t sensor_id_reg_addr;
uint16_t sensor_id;
uint16_t sensor_id_mask;
+ struct msm_camera_i2c_reg_setting *setting;
};
struct msm_cam_clk_info {
diff --git a/include/uapi/media/msm_camsensor_sdk.h b/include/uapi/media/msm_camsensor_sdk.h
index 6d25967..63abd156 100644
--- a/include/uapi/media/msm_camsensor_sdk.h
+++ b/include/uapi/media/msm_camsensor_sdk.h
@@ -50,6 +50,8 @@
#define MSM_SENSOR_BYPASS_VIDEO_NODE 1
+#define SENSOR_PROBE_WRITE
+
enum msm_sensor_camera_id_t {
CAMERA_0,
CAMERA_1,
@@ -292,10 +294,19 @@
unsigned int sensor_mount_angle;
};
+struct msm_camera_i2c_reg_setting {
+ struct msm_camera_i2c_reg_array *reg_setting;
+ unsigned short size;
+ enum msm_camera_i2c_reg_addr_type addr_type;
+ enum msm_camera_i2c_data_type data_type;
+ unsigned short delay;
+};
+
struct msm_sensor_id_info_t {
unsigned short sensor_id_reg_addr;
unsigned short sensor_id;
unsigned short sensor_id_mask;
+ struct msm_camera_i2c_reg_setting setting;
};
struct msm_camera_sensor_slave_info {
@@ -322,14 +333,6 @@
unsigned int delay;
};
-struct msm_camera_i2c_reg_setting {
- struct msm_camera_i2c_reg_array *reg_setting;
- unsigned short size;
- enum msm_camera_i2c_reg_addr_type addr_type;
- enum msm_camera_i2c_data_type data_type;
- unsigned short delay;
-};
-
struct msm_camera_csid_vc_cfg {
unsigned char cid;
unsigned char dt;