From b1b6113ebbc09a3fe905ecd1ccb7a4bef29269ab Mon Sep 17 00:00:00 2001 From: syoo Date: Wed, 26 Jun 2019 15:25:57 -0500 Subject: [PATCH] [9610] fimc-is2: OIS HEA test SW change - actual measured values are stored separately - calibration mode procedure is changed Change-Id: I5a67a3f6b81d314716efa45dea7e77ea68c7a685 Signed-off-by: Wooyeon Kim --- .../fimc-is-interface-sensor.h | 11 +- .../modules/fimc-is-device-module-base.c | 33 ++- .../ois/fimc_bu24218_factory.c | 219 ++++++++++++++---- .../ois/fimc_bu24218_factory.h | 20 +- 4 files changed, 225 insertions(+), 58 deletions(-) mode change 100755 => 100644 drivers/media/platform/exynos/fimc-is2/sensor/module_framework/fimc-is-interface-sensor.h diff --git a/drivers/media/platform/exynos/fimc-is2/sensor/module_framework/fimc-is-interface-sensor.h b/drivers/media/platform/exynos/fimc-is2/sensor/module_framework/fimc-is-interface-sensor.h old mode 100755 new mode 100644 index 7f9a4170649e..bfb1a659ece0 --- a/drivers/media/platform/exynos/fimc-is2/sensor/module_framework/fimc-is-interface-sensor.h +++ b/drivers/media/platform/exynos/fimc-is2/sensor/module_framework/fimc-is-interface-sensor.h @@ -659,6 +659,15 @@ struct fimc_is_long_term_expo_mode { }; /* OIS */ +#ifdef CONFIG_OIS_BU24218_FACTORY_TEST +struct fimc_is_ois_hea_parameters { + uint32_t x_max; + uint32_t x_min; + uint32_t y_max; + uint32_t y_min; +}; +#endif + struct fimc_is_ois_ops { int (*ois_init)(struct v4l2_subdev *subdev); #if defined (CONFIG_OIS_USE_RUMBA_S6) || defined (CONFIG_CAMERA_USE_MCU) @@ -706,7 +715,7 @@ struct fimc_is_ois_ops { u8 (*ois_read_mode)(struct v4l2_subdev *subdev); #ifdef CONFIG_OIS_BU24218_FACTORY_TEST int (*ois_factory_fw_ver)(struct v4l2_subdev *subdev, u32* result); - int (*ois_factory_hea)(struct v4l2_subdev *subdev, u32* result); + int (*ois_factory_hea)(struct v4l2_subdev *subdev, struct fimc_is_ois_hea_parameters *result); #endif }; diff --git a/drivers/media/platform/exynos/fimc-is2/sensor/module_framework/modules/fimc-is-device-module-base.c b/drivers/media/platform/exynos/fimc-is2/sensor/module_framework/modules/fimc-is-device-module-base.c index 5df91cea5aaf..e6b11e87bf3a 100644 --- a/drivers/media/platform/exynos/fimc-is2/sensor/module_framework/modules/fimc-is-device-module-base.c +++ b/drivers/media/platform/exynos/fimc-is2/sensor/module_framework/modules/fimc-is-device-module-base.c @@ -665,15 +665,6 @@ int sensor_module_g_ctrl(struct v4l2_subdev *subdev, struct v4l2_control *ctrl) goto p_err; } break; - case V4L2_CID_IS_FACTORY_OIS_HEA: - ret = CALL_OISOPS(sensor_peri->ois, ois_factory_hea, - sensor_peri->subdev_ois, &ctrl->value); - if (ret < 0) { - err("err!!! ret(%d)", ret); - ret = -EINVAL; - goto p_err; - } - break; #endif default: err("err!!! Unknown CID(%#x)", ctrl->id); @@ -946,6 +937,30 @@ int sensor_module_s_ext_ctrls(struct v4l2_subdev *subdev, struct v4l2_ext_contro break; } +#ifdef CONFIG_OIS_BU24218_FACTORY_TEST + case V4L2_CID_IS_FACTORY_OIS_HEA: { + struct fimc_is_ois_hea_parameters ois_hea_params = {0,0,0,0}; + + ret = CALL_OISOPS(sensor_peri->ois, ois_factory_hea, + sensor_peri->subdev_ois, &ois_hea_params); + if (ret < 0) { + err("err!!! ois_factory_hea ret(%d)", ret); + ret = -EINVAL; + goto p_err; + } + info("%s: ois_hea_params (%d %d %d %d)", __func__, + ois_hea_params.x_max,ois_hea_params.x_min,ois_hea_params.y_max,ois_hea_params.y_min); + + ret = copy_to_user(ext_ctrl->ptr, &ois_hea_params, sizeof(ois_hea_params)); + if (ret) { + err("failed copying %d bytes of data\n", ret); + ret = -EINVAL; + goto p_err; + } + break; + } +#endif + default: ctrl.id = ext_ctrl->id; ctrl.value = ext_ctrl->value; diff --git a/drivers/media/platform/exynos/fimc-is2/sensor/module_framework/ois/fimc_bu24218_factory.c b/drivers/media/platform/exynos/fimc-is2/sensor/module_framework/ois/fimc_bu24218_factory.c index 54000d86f23f..7a712ba1bb9b 100644 --- a/drivers/media/platform/exynos/fimc-is2/sensor/module_framework/ois/fimc_bu24218_factory.c +++ b/drivers/media/platform/exynos/fimc-is2/sensor/module_framework/ois/fimc_bu24218_factory.c @@ -28,7 +28,7 @@ int fimc_is_factory_ois_get_fw_rev(struct v4l2_subdev *subdev, uint32_t *result) ois = (struct fimc_is_ois *)v4l2_get_subdevdata(subdev); if(!ois) { - err("%s, ois subdev is NULL", __func__); + err("%s: ois subdev is NULL", __func__); ret = -EINVAL; return ret; } @@ -47,7 +47,7 @@ int fimc_is_factory_ois_get_fw_rev(struct v4l2_subdev *subdev, uint32_t *result) ret = fimc_is_ois_read(ois->client, MOT_BU24218_REG_FW_VERSION + 3, &version[3]); check_result(ret); - info("%s: fw version:%d, %d, %d, %d", __func__, version[0], version[1], version[2], version[3]); + info("%s: version %d %d %d %d", __func__, version[0], version[1], version[2], version[3]); *result = version[0] | (version[1] << 8) | (version[2] << 16) | (version[3] << 24); return 0; @@ -57,10 +57,10 @@ ERROR: } -int fimc_is_factory_ois_get_hea(struct v4l2_subdev *subdev, uint32_t *result) +int fimc_is_factory_ois_get_hea(struct v4l2_subdev *subdev, struct fimc_is_ois_hea_parameters *result) { int ret = 0; - char data[4] = {0, 0, 0, 0}; + uint32_t data[4] = {0, 0, 0, 0}; struct fimc_is_ois *ois = NULL; FIMC_BUG(!subdev); @@ -69,7 +69,7 @@ int fimc_is_factory_ois_get_hea(struct v4l2_subdev *subdev, uint32_t *result) ois = (struct fimc_is_ois *)v4l2_get_subdevdata(subdev); if(!ois) { - err("%s, ois subdev is NULL", __func__); + err("%s: ois subdev is NULL", __func__); ret = -EINVAL; return ret; } @@ -77,59 +77,56 @@ int fimc_is_factory_ois_get_hea(struct v4l2_subdev *subdev, uint32_t *result) WARN_ON(!ois); // 1. change to calibration mode - ret = fimc_is_factory_ois_poll(ois->client, MOT_BU24218_REG_STATUS, 0x01); + ret = fimc_is_factory_ois_calibration_mode(ois->client); check_result(ret); - fimc_is_ois_write(ois->client, MOT_BU24218_REG_MODE, 0x01); - ret = fimc_is_factory_ois_poll(ois->client, MOT_BU24218_REG_STATUS, 0x01); + usleep_range(500,500); + + // 2. set to zero position + ret = fimc_is_factory_ois_set_zero_pos(ois->client); check_result(ret); - fimc_is_ois_write(ois->client, MOT_BU24218_REG_MODE, 0x00); - ret = fimc_is_factory_ois_poll(ois->client, MOT_BU24218_REG_STATUS, 0x01); + usleep_range(20000,20000); + + // 3. set x max position and read ADC + ret = fimc_is_factory_ois_set_x_pos(ois->client, MOT_BU24218_VCM_DRV_MAX_HI, MOT_BU24218_VCM_DRV_MAX_LO); check_result(ret); - fimc_is_ois_write(ois->client, MOT_BU24218_REG_MODE, 0x04); - ret = fimc_is_factory_ois_poll(ois->client, MOT_BU24218_REG_STATUS, 0x01); + usleep_range(20000,20000); + ret = fimc_is_factory_ois_get_x_adc(ois->client,&data[0]); check_result(ret); - usleep_range(500, 500); - - // 2. set max postion - fimc_is_ois_write(ois->client, MOT_BU24218_REG_POS_XCH, (uint8_t) MOT_BU24218_VCM_DRV_MAX_HI); - fimc_is_ois_write(ois->client, MOT_BU24218_REG_POS_XCH + 1, (uint8_t) MOT_BU24218_VCM_DRV_MAX_LO); - fimc_is_ois_write(ois->client, MOT_BU24218_REG_POS_YCH, (uint8_t) MOT_BU24218_VCM_DRV_MAX_HI); - fimc_is_ois_write(ois->client, MOT_BU24218_REG_POS_YCH + 1, (uint8_t) MOT_BU24218_VCM_DRV_MAX_LO); - usleep_range(200, 200); - - // 3. check status reg - ret = fimc_is_factory_ois_poll(ois->client, MOT_BU24218_REG_STATUS, 0x01); + + // 4. set x min position and read ADC + ret = fimc_is_factory_ois_set_x_pos(ois->client, MOT_BU24218_VCM_DRV_MIN_HI, MOT_BU24218_VCM_DRV_MIN_LO); check_result(ret); - - // 4. read lens position - ret = fimc_is_ois_read(ois->client, MOT_BU24218_REG_LENS_XCH, &data[0]); + usleep_range(20000,20000); + ret = fimc_is_factory_ois_get_x_adc(ois->client,&data[1]); check_result(ret); - ret = fimc_is_ois_read(ois->client, MOT_BU24218_REG_LENS_YCH, &data[1]); + + // 5. set to zero position + ret = fimc_is_factory_ois_set_zero_pos(ois->client); check_result(ret); - - // 5. set min postion - fimc_is_ois_write(ois->client, MOT_BU24218_REG_POS_XCH, (uint8_t) MOT_BU24218_VCM_DRV_MIN_HI); - fimc_is_ois_write(ois->client, MOT_BU24218_REG_POS_XCH + 1, (uint8_t) MOT_BU24218_VCM_DRV_MIN_LO); - fimc_is_ois_write(ois->client, MOT_BU24218_REG_POS_YCH, (uint8_t) MOT_BU24218_VCM_DRV_MIN_HI); - fimc_is_ois_write(ois->client, MOT_BU24218_REG_POS_YCH + 1, (uint8_t) MOT_BU24218_VCM_DRV_MIN_LO); - usleep_range(200, 200); - - // 6. check status reg - ret = fimc_is_factory_ois_poll(ois->client, MOT_BU24218_REG_STATUS, 0x01); + usleep_range(20000,20000); + + // 6. set y max position and read ADC + ret = fimc_is_factory_ois_set_y_pos(ois->client, MOT_BU24218_VCM_DRV_MAX_HI, MOT_BU24218_VCM_DRV_MAX_LO); check_result(ret); - - usleep_range(200, 200); - // 7. read lens position - ret = fimc_is_ois_read(ois->client, MOT_BU24218_REG_LENS_XCH, &data[2]); + usleep_range(20000,20000); + ret = fimc_is_factory_ois_get_y_adc(ois->client,&data[2]); check_result(ret); - ret = fimc_is_ois_read(ois->client, MOT_BU24218_REG_LENS_YCH, &data[3]); + + // 7. set y min position and read ADC + ret = fimc_is_factory_ois_set_y_pos(ois->client, MOT_BU24218_VCM_DRV_MIN_HI, MOT_BU24218_VCM_DRV_MIN_LO); check_result(ret); + usleep_range(20000,20000); + ret = fimc_is_factory_ois_get_y_adc(ois->client,&data[3]); + check_result(ret); + + result->x_max = data[0]; + result->x_min = data[1]; + result->y_max = data[2]; + result->y_min = data[3]; - info("%s: actual pos:(%d, %d, %d, %d)", __func__, - data[0], data[2], data[1], data[3]); - // follow the format, Xmax, Xmin, Ymax, Ymin - *result = data[0] | (data[2] << 8) | (data[1] << 16) | (data[3] << 24); - + info("%s: result %d %d %d %d", __func__, + result->x_max, result->x_min, result->y_max, result->y_min); + return 0; ERROR: @@ -158,3 +155,131 @@ ERROR: err("%s: Failed with %d", __func__, ret); return -1; } + + +int fimc_is_factory_ois_calibration_mode(struct i2c_client *client) +{ + int ret = 0; + + fimc_is_ois_write(client, MOT_BU24218_REG_MODE, 0x01); + ret = fimc_is_factory_ois_poll(client, MOT_BU24218_REG_STATUS, 0x01); + if (ret < 0) { + err("fail at calib 01"); + return ret; + } + fimc_is_ois_write(client, MOT_BU24218_REG_LINEARITY, 0x00); + ret = fimc_is_factory_ois_poll(client, MOT_BU24218_REG_LINEARITY, 0x00); + if (ret < 0) { + err("fail at linearity"); + return ret; + } + fimc_is_ois_write(client, MOT_BU24218_REG_GYRO_ACCESS, 0x02); + ret = fimc_is_factory_ois_poll(client, MOT_BU24218_REG_STATUS, 0x01); + if (ret < 0) { + err("fail at gyro access"); + return ret; + } + fimc_is_ois_write(client, MOT_BU24218_REG_MODE, 0x00); + ret = fimc_is_factory_ois_poll(client, MOT_BU24218_REG_STATUS, 0x01); + if (ret < 0) { + err("fail at calib 00"); + return ret; + } + fimc_is_ois_write(client, MOT_BU24218_REG_MODE, 0x04); + ret = fimc_is_factory_ois_poll(client, MOT_BU24218_REG_STATUS, 0x01); + if (ret < 0) { + err("fail at calib 04"); + return ret; + } + + return ret; +} + +int fimc_is_factory_ois_set_zero_pos(struct i2c_client *client) +{ + int ret = 0; + fimc_is_factory_ois_set_x_pos(client, MOT_BU24218_VCM_DRV_ZERO_HI, MOT_BU24218_VCM_DRV_ZERO_LO); + fimc_is_factory_ois_set_y_pos(client, MOT_BU24218_VCM_DRV_ZERO_HI, MOT_BU24218_VCM_DRV_ZERO_LO); + + ret = fimc_is_factory_ois_poll(client, MOT_BU24218_REG_STATUS, 0x01); + if (ret < 0) { + err("fail at set to zero"); + } + return ret; +} + +int fimc_is_factory_ois_set_x_pos(struct i2c_client *client, uint8_t hi, uint8_t lo) +{ + int ret = 0; + fimc_is_ois_write(client, MOT_BU24218_REG_POS_XCH, hi); + fimc_is_ois_write(client, MOT_BU24218_REG_POS_XCH + 1, lo); + + ret = fimc_is_factory_ois_poll(client, MOT_BU24218_REG_STATUS, 0x01); + if (ret < 0) { + err("fail at %s",__func__); + } + return ret; +} + +int fimc_is_factory_ois_set_y_pos(struct i2c_client *client, uint8_t hi, uint8_t lo) +{ + int ret = 0; + fimc_is_ois_write(client, MOT_BU24218_REG_POS_YCH, hi); + fimc_is_ois_write(client, MOT_BU24218_REG_POS_YCH + 1, lo); + + ret = fimc_is_factory_ois_poll(client, MOT_BU24218_REG_STATUS, 0x01); + if (ret < 0) { + err("fail at %s",__func__); + } + return ret; +} + +int fimc_is_factory_ois_get_x_adc(struct i2c_client *client, uint32_t* data) +{ + int ret = 0; + uint8_t raw_adc_hi = 0, raw_adc_lo = 0; + + fimc_is_ois_write(client, MOT_BU24218_REG_ADC_LATCH, MOT_BU24218_ADC_LATCH_X); + usleep_range(11000,11000); + + ret = fimc_is_ois_read(client, MOT_BU24218_REG_ADC_VAL, &raw_adc_hi); + if (ret < 0) { + err("fail at %s",__func__); + return ret; + } + usleep_range(500,500); + ret = fimc_is_ois_read(client, MOT_BU24218_REG_ADC_VAL+1, &raw_adc_lo); + if (ret < 0) { + err("fail at %s",__func__); + return ret; + } + usleep_range(500,500); + + *data = (uint32_t)(raw_adc_hi << 8) + raw_adc_lo; + return ret; +} + +int fimc_is_factory_ois_get_y_adc(struct i2c_client *client, uint32_t* data) +{ + int ret = 0; + uint8_t raw_adc_hi = 0, raw_adc_lo = 0; + + fimc_is_ois_write(client, MOT_BU24218_REG_ADC_LATCH, MOT_BU24218_ADC_LATCH_Y); + usleep_range(11000,11000); + + ret = fimc_is_ois_read(client, MOT_BU24218_REG_ADC_VAL, &raw_adc_hi); + if (ret < 0) { + err("fail at %s",__func__); + return ret; + } + usleep_range(500,500); + ret = fimc_is_ois_read(client, MOT_BU24218_REG_ADC_VAL+1, &raw_adc_lo); + if (ret < 0) { + err("fail at %s",__func__); + return ret; + } + usleep_range(500,500); + + *data = (uint32_t)(raw_adc_hi << 8) + raw_adc_lo; + return ret; +} diff --git a/drivers/media/platform/exynos/fimc-is2/sensor/module_framework/ois/fimc_bu24218_factory.h b/drivers/media/platform/exynos/fimc-is2/sensor/module_framework/ois/fimc_bu24218_factory.h index 9f74cfa4da79..d4dba7a143b4 100644 --- a/drivers/media/platform/exynos/fimc-is2/sensor/module_framework/ois/fimc_bu24218_factory.h +++ b/drivers/media/platform/exynos/fimc-is2/sensor/module_framework/ois/fimc_bu24218_factory.h @@ -25,6 +25,7 @@ #define MOT_BU24218_REG_FW_VERSION 0x6010 #define MOT_BU24218_REG_GYRO_SELF_TEST 0x6104 #define MOT_BU24218_REG_GYRO_RESULT 0x6105 +#define MOT_BU24218_REG_LINEARITY 0x614F #define MOT_BU24218_REG_MAX_XCH 0x6100 #define MOT_BU24218_REG_MIN_XCH 0x6101 @@ -34,13 +35,30 @@ #define MOT_BU24218_REG_POS_YCH 0x6066 #define MOT_BU24218_REG_LENS_XCH 0x6058 #define MOT_BU24218_REG_LENS_YCH 0x6059 +#define MOT_BU24218_REG_ADC_VAL 0x6062 +#define MOT_BU24218_REG_ADC_LATCH 0x6060 #define MOT_BU24218_VCM_DRV_MAX_HI 0x03 #define MOT_BU24218_VCM_DRV_MAX_LO 0x00 #define MOT_BU24218_VCM_DRV_MIN_HI 0x0D #define MOT_BU24218_VCM_DRV_MIN_LO 0x00 +#define MOT_BU24218_VCM_DRV_ZERO_HI 0x00 +#define MOT_BU24218_VCM_DRV_ZERO_LO 0x00 + +#define MOT_BU24218_ADC_LATCH_X 0 +#define MOT_BU24218_ADC_LATCH_Y 1 + +#define OIS_HEA_NUM_VALUES 4 int fimc_is_factory_ois_get_fw_rev(struct v4l2_subdev *subdev, uint32_t *result); -int fimc_is_factory_ois_get_hea(struct v4l2_subdev *subdev, uint32_t *result); +int fimc_is_factory_ois_get_hea(struct v4l2_subdev *subdev, struct fimc_is_ois_hea_parameters *result); int fimc_is_factory_ois_poll(struct i2c_client *client, u16 addr, uint8_t expdata); + +int fimc_is_factory_ois_calibration_mode(struct i2c_client *client); +int fimc_is_factory_ois_set_zero_pos(struct i2c_client *client); +int fimc_is_factory_ois_set_x_pos(struct i2c_client *client, uint8_t hi, uint8_t lo); +int fimc_is_factory_ois_set_y_pos(struct i2c_client *client, uint8_t hi, uint8_t lo); +int fimc_is_factory_ois_get_x_adc(struct i2c_client *client, uint32_t* data); +int fimc_is_factory_ois_get_y_adc(struct i2c_client *client, uint32_t* data); + #endif -- 2.20.1