V(CR): Port OIS Kernel Changes

-Add new fields to OIS data structures
-Add capability to program OIS more flexibly

Change-Id: I97988cc3a6d7fa2241016bd4a269618c8ff10ad0
Reviewed-on: https://gerrit.mot.com/1736525
SLTApproved: Slta Waiver
SME-Granted: SME Approvals Granted
Tested-by: Jira Key
Reviewed-by: Dawei Wang <wangdw10@motorola.com>
Reviewed-by: Rav(CR) Vembu <raviv@motorola.com>
Submit-Approved: Jira Key
This commit is contained in:
timwang 2020-07-16 09:37:16 -05:00 • committed by zhaoji1
commit 23cf72040d
3 changed files with 226 additions and 54 deletions

View file

@ -332,7 +332,13 @@ static int cam_ois_slaveInfo_pkt_parser(struct cam_ois_ctrl_t *o_ctrl,
o_ctrl->io_master_info.cci_client->sid =
ois_info->slave_addr >> 1;
o_ctrl->ois_fw_flag = ois_info->ois_fw_flag;
o_ctrl->ois_preprog_flag = ois_info->ois_preprog_flag;
o_ctrl->ois_precoeff_flag = ois_info->ois_precoeff_flag;
o_ctrl->is_ois_calib = ois_info->is_ois_calib;
o_ctrl->ois_postcalib_flag = ois_info->ois_postcalib_flag;
o_ctrl->ois_fw_txn_data_sz = ois_info->ois_fw_txn_data_sz;
o_ctrl->ois_fw_inc_addr = ois_info->ois_fw_inc_addr;
o_ctrl->ois_fw_addr_type = ois_info->ois_fw_addr_type;
memcpy(o_ctrl->ois_name, ois_info->ois_name, OIS_NAME_LEN);
o_ctrl->ois_name[OIS_NAME_LEN - 1] = '\0';
o_ctrl->io_master_info.cci_client->retries = 3;
@ -353,16 +359,97 @@ static int cam_ois_slaveInfo_pkt_parser(struct cam_ois_ctrl_t *o_ctrl,
return rc;
}
static int cam_ois_fw_download(struct cam_ois_ctrl_t *o_ctrl)
static int cam_ois_fw_prog_download(struct cam_ois_ctrl_t *o_ctrl)
{
uint16_t total_bytes = 0;
uint8_t *ptr = NULL;
int32_t rc = 0, cnt;
uint32_t fw_size;
int32_t rc = 0, total_idx, packet_idx;
uint32_t txn_data_size, txn_regsetting_size;
const struct firmware *fw = NULL;
const char *fw_name_prog = NULL;
const char *fw_name_coeff = NULL;
char name_prog[32] = {0};
struct device *dev = &(o_ctrl->pdev->dev);
struct cam_sensor_i2c_reg_setting i2c_reg_setting;
void *vaddr = NULL;
if (!o_ctrl) {
CAM_ERR(CAM_OIS, "Invalid Args");
return -EINVAL;
}
snprintf(name_prog, 32, "%s.prog", o_ctrl->ois_name);
/* cast pointer as const pointer*/
fw_name_prog = name_prog;
/* Load FW */
rc = request_firmware(&fw, fw_name_prog, dev);
if (rc) {
CAM_ERR(CAM_OIS, "Failed to locate %s", fw_name_prog);
return rc;
}
total_bytes = fw->size;
if(o_ctrl->ois_fw_txn_data_sz == 0)
txn_data_size = total_bytes;
else
txn_data_size = o_ctrl->ois_fw_txn_data_sz;
i2c_reg_setting.addr_type = o_ctrl->ois_fw_addr_type;
i2c_reg_setting.data_type = CAMERA_SENSOR_I2C_TYPE_BYTE;
i2c_reg_setting.delay = 0;
txn_regsetting_size = sizeof(struct cam_sensor_i2c_reg_array) * txn_data_size;
vaddr = vmalloc(txn_regsetting_size);
if (!vaddr) {
CAM_ERR(CAM_OIS, "Failed in allocating i2c_array");
release_firmware(fw);
return -ENOMEM;
}
i2c_reg_setting.reg_setting = (struct cam_sensor_i2c_reg_array *) (vaddr);
for (total_idx = 0, ptr = (uint8_t *)fw->data; total_idx < total_bytes;) {
for(packet_idx = 0;
(packet_idx < txn_data_size) && (total_idx + packet_idx < total_bytes);
packet_idx++, ptr++)
{
int regAddrOffset = 0;
if(o_ctrl->ois_fw_inc_addr == 1)
regAddrOffset = total_idx + packet_idx;
i2c_reg_setting.reg_setting[packet_idx].reg_addr =
o_ctrl->opcode.prog + regAddrOffset;
i2c_reg_setting.reg_setting[packet_idx].reg_data = *ptr;
i2c_reg_setting.reg_setting[packet_idx].delay = 0;
i2c_reg_setting.reg_setting[packet_idx].data_mask = 0;
}
i2c_reg_setting.size = packet_idx;
rc = camera_io_dev_write_continuous(&(o_ctrl->io_master_info),
&i2c_reg_setting, 1);
if (rc < 0) {
CAM_ERR(CAM_OIS, "OIS FW download failed %d", rc);
goto release_firmware;
}
total_idx += packet_idx;
}
release_firmware:
vfree(vaddr);
vaddr = NULL;
txn_regsetting_size = 0;
release_firmware(fw);
return rc;
}
static int cam_ois_fw_coeff_download(struct cam_ois_ctrl_t *o_ctrl)
{
uint16_t total_bytes = 0;
uint8_t *ptr = NULL;
int32_t rc = 0, total_idx, packet_idx;
uint32_t txn_data_size, txn_regsetting_size;
const struct firmware *fw = NULL;
const char *fw_name_coeff = NULL;
char name_coeff[32] = {0};
struct device *dev = &(o_ctrl->pdev->dev);
struct cam_sensor_i2c_reg_setting i2c_reg_setting;
@ -374,57 +461,8 @@ static int cam_ois_fw_download(struct cam_ois_ctrl_t *o_ctrl)
}
snprintf(name_coeff, 32, "%s.coeff", o_ctrl->ois_name);
snprintf(name_prog, 32, "%s.prog", o_ctrl->ois_name);
/* cast pointer as const pointer*/
fw_name_prog = name_prog;
fw_name_coeff = name_coeff;
/* Load FW */
rc = request_firmware(&fw, fw_name_prog, dev);
if (rc) {
CAM_ERR(CAM_OIS, "Failed to locate %s", fw_name_prog);
return rc;
}
total_bytes = fw->size;
i2c_reg_setting.addr_type = CAMERA_SENSOR_I2C_TYPE_BYTE;
i2c_reg_setting.data_type = CAMERA_SENSOR_I2C_TYPE_BYTE;
i2c_reg_setting.size = total_bytes;
i2c_reg_setting.delay = 0;
fw_size = (sizeof(struct cam_sensor_i2c_reg_array) * total_bytes);
vaddr = vmalloc(fw_size);
if (!vaddr) {
CAM_ERR(CAM_OIS,
"Failed in allocating i2c_array: fw_size: %u", fw_size);
release_firmware(fw);
return -ENOMEM;
}
i2c_reg_setting.reg_setting = (struct cam_sensor_i2c_reg_array *) (
vaddr);
for (cnt = 0, ptr = (uint8_t *)fw->data; cnt < total_bytes;
cnt++, ptr++) {
i2c_reg_setting.reg_setting[cnt].reg_addr =
o_ctrl->opcode.prog;
i2c_reg_setting.reg_setting[cnt].reg_data = *ptr;
i2c_reg_setting.reg_setting[cnt].delay = 0;
i2c_reg_setting.reg_setting[cnt].data_mask = 0;
}
rc = camera_io_dev_write_continuous(&(o_ctrl->io_master_info),
&i2c_reg_setting, 1);
if (rc < 0) {
CAM_ERR(CAM_OIS, "OIS FW download failed %d", rc);
goto release_firmware;
}
vfree(vaddr);
vaddr = NULL;
fw_size = 0;
release_firmware(fw);
rc = request_firmware(&fw, fw_name_coeff, dev);
if (rc) {
CAM_ERR(CAM_OIS, "Failed to locate %s", fw_name_coeff);
@ -432,41 +470,55 @@ static int cam_ois_fw_download(struct cam_ois_ctrl_t *o_ctrl)
}
total_bytes = fw->size;
i2c_reg_setting.addr_type = CAMERA_SENSOR_I2C_TYPE_BYTE;
if(o_ctrl->ois_fw_txn_data_sz == 0)
txn_data_size = total_bytes;
else
txn_data_size = o_ctrl->ois_fw_txn_data_sz;
i2c_reg_setting.addr_type = o_ctrl->ois_fw_addr_type;
i2c_reg_setting.data_type = CAMERA_SENSOR_I2C_TYPE_BYTE;
i2c_reg_setting.size = total_bytes;
i2c_reg_setting.delay = 0;
fw_size = (sizeof(struct cam_sensor_i2c_reg_array) * total_bytes);
vaddr = vmalloc(fw_size);
txn_regsetting_size = sizeof(struct cam_sensor_i2c_reg_array) * txn_data_size;
vaddr = vmalloc(txn_regsetting_size);
if (!vaddr) {
CAM_ERR(CAM_OIS,
"Failed in allocating i2c_array: fw_size: %u", fw_size);
CAM_ERR(CAM_OIS, "Failed in allocating i2c_array");
release_firmware(fw);
return -ENOMEM;
}
i2c_reg_setting.reg_setting = (struct cam_sensor_i2c_reg_array *) (
vaddr);
i2c_reg_setting.reg_setting = (struct cam_sensor_i2c_reg_array *) (vaddr);
for (cnt = 0, ptr = (uint8_t *)fw->data; cnt < total_bytes;
cnt++, ptr++) {
i2c_reg_setting.reg_setting[cnt].reg_addr =
o_ctrl->opcode.coeff;
i2c_reg_setting.reg_setting[cnt].reg_data = *ptr;
i2c_reg_setting.reg_setting[cnt].delay = 0;
i2c_reg_setting.reg_setting[cnt].data_mask = 0;
for (total_idx = 0, ptr = (uint8_t *)fw->data; total_idx < total_bytes;) {
for(packet_idx = 0;
(packet_idx < txn_data_size) && (total_idx + packet_idx < total_bytes);
packet_idx++, ptr++)
{
int regAddrOffset = 0;
if(o_ctrl->ois_fw_inc_addr == 1)
regAddrOffset = total_idx + packet_idx;
i2c_reg_setting.reg_setting[packet_idx].reg_addr =
o_ctrl->opcode.coeff + regAddrOffset;
i2c_reg_setting.reg_setting[packet_idx].reg_data = *ptr;
i2c_reg_setting.reg_setting[packet_idx].delay = 0;
i2c_reg_setting.reg_setting[packet_idx].data_mask = 0;
}
i2c_reg_setting.size = packet_idx;
rc = camera_io_dev_write_continuous(&(o_ctrl->io_master_info),
&i2c_reg_setting, 1);
if (rc < 0) {
CAM_ERR(CAM_OIS, "OIS FW download failed %d", rc);
goto release_firmware;
}
total_idx += packet_idx;
}
rc = camera_io_dev_write_continuous(&(o_ctrl->io_master_info),
&i2c_reg_setting, 1);
if (rc < 0)
CAM_ERR(CAM_OIS, "OIS FW download failed %d", rc);
release_firmware:
vfree(vaddr);
vaddr = NULL;
fw_size = 0;
txn_regsetting_size = 0;
release_firmware(fw);
return rc;
}
@ -609,6 +661,34 @@ static int cam_ois_pkt_parse(struct cam_ois_ctrl_t *o_ctrl, void *arg)
"init parsing failed: %d", rc);
return rc;
}
} else if (((o_ctrl->ois_preprog_flag) != 0) &&
o_ctrl->i2c_preprog_data.is_settings_valid == 0) {
CAM_DBG(CAM_OIS, "Received PreProg Settings");
i2c_reg_settings = &(o_ctrl->i2c_preprog_data);
i2c_reg_settings->request_id = 0;
rc = cam_sensor_i2c_command_parser(
&o_ctrl->io_master_info,
i2c_reg_settings,
&cmd_desc[i], 1, NULL);
if (rc < 0) {
CAM_ERR(CAM_OIS,
"preprog parsing failed: %d", rc);
return rc;
}
} else if (((o_ctrl->ois_precoeff_flag) != 0) &&
o_ctrl->i2c_precoeff_data.is_settings_valid == 0) {
CAM_DBG(CAM_OIS, "Received PreCoeff Settings");
i2c_reg_settings = &(o_ctrl->i2c_precoeff_data);
i2c_reg_settings->request_id = 0;
rc = cam_sensor_i2c_command_parser(
&o_ctrl->io_master_info,
i2c_reg_settings,
&cmd_desc[i], 1, NULL);
if (rc < 0) {
CAM_ERR(CAM_OIS,
"precoeff parsing failed: %d", rc);
return rc;
}
} else if ((o_ctrl->is_ois_calib != 0) &&
(o_ctrl->i2c_calib_data.is_settings_valid ==
0)) {
@ -626,6 +706,20 @@ static int cam_ois_pkt_parse(struct cam_ois_ctrl_t *o_ctrl, void *arg)
"Calib parsing failed: %d", rc);
return rc;
}
} else if (((o_ctrl->ois_postcalib_flag) != 0) &&
o_ctrl->i2c_postcalib_data.is_settings_valid == 0) {
CAM_DBG(CAM_OIS, "Received PostCalib Settings");
i2c_reg_settings = &(o_ctrl->i2c_postcalib_data);
i2c_reg_settings->request_id = 0;
rc = cam_sensor_i2c_command_parser(
&o_ctrl->io_master_info,
i2c_reg_settings,
&cmd_desc[i], 1, NULL);
if (rc < 0) {
CAM_ERR(CAM_OIS,
"postcalib parsing failed: %d", rc);
return rc;
}
}
break;
}
@ -640,14 +734,40 @@ static int cam_ois_pkt_parse(struct cam_ois_ctrl_t *o_ctrl, void *arg)
o_ctrl->cam_ois_state = CAM_OIS_CONFIG;
}
if (o_ctrl->ois_preprog_flag) {
rc = cam_ois_apply_settings(o_ctrl,
&o_ctrl->i2c_preprog_data);
if (rc) {
CAM_ERR(CAM_OIS, "Cannot apply preprog settings");
goto pwr_dwn;
}
}
if (o_ctrl->ois_fw_flag) {
rc = cam_ois_fw_download(o_ctrl);
rc = cam_ois_fw_prog_download(o_ctrl);
if (rc) {
CAM_ERR(CAM_OIS, "Failed OIS FW Download");
goto pwr_dwn;
}
}
if (o_ctrl->ois_precoeff_flag) {
rc = cam_ois_apply_settings(o_ctrl,
&o_ctrl->i2c_precoeff_data);
if (rc) {
CAM_ERR(CAM_OIS, "Cannot apply precoeff settings");
goto pwr_dwn;
}
}
if (o_ctrl->ois_fw_flag) {
rc = cam_ois_fw_coeff_download(o_ctrl);
if (rc) {
CAM_ERR(CAM_OIS, "Failed OIS COEFF FW Download");
goto pwr_dwn;
}
}
rc = cam_ois_apply_settings(o_ctrl, &o_ctrl->i2c_init_data);
if ((rc == -EAGAIN) &&
(o_ctrl->io_master_info.master_type == CCI_MASTER)) {
@ -673,18 +793,46 @@ static int cam_ois_pkt_parse(struct cam_ois_ctrl_t *o_ctrl, void *arg)
}
}
if (o_ctrl->ois_postcalib_flag) {
CAM_DBG(CAM_OIS, "starting post calib data");
rc = cam_ois_apply_settings(o_ctrl,
&o_ctrl->i2c_postcalib_data);
if (rc) {
CAM_ERR(CAM_OIS, "Cannot apply post calib data");
goto pwr_dwn;
}
}
rc = delete_request(&o_ctrl->i2c_init_data);
if (rc < 0) {
CAM_WARN(CAM_OIS,
"Fail deleting Init data: rc: %d", rc);
rc = 0;
}
rc = delete_request(&o_ctrl->i2c_preprog_data);
if (rc < 0) {
CAM_WARN(CAM_OIS,
"Fail deleting PreProg data: rc: %d", rc);
rc = 0;
}
rc = delete_request(&o_ctrl->i2c_precoeff_data);
if (rc < 0) {
CAM_WARN(CAM_OIS,
"Fail deleting PreCoeff data: rc: %d", rc);
rc = 0;
}
rc = delete_request(&o_ctrl->i2c_calib_data);
if (rc < 0) {
CAM_WARN(CAM_OIS,
"Fail deleting Calibration data: rc: %d", rc);
rc = 0;
}
rc = delete_request(&o_ctrl->i2c_postcalib_data);
if (rc < 0) {
CAM_WARN(CAM_OIS,
"Fail deleting PostCalib data: rc: %d", rc);
rc = 0;
}
break;
case CAM_OIS_PACKET_OPCODE_OIS_CONTROL:
if (o_ctrl->cam_ois_state < CAM_OIS_CONFIG) {

View file

@ -95,12 +95,21 @@ struct cam_ois_intf_params {
* @i2c_init_data : ois i2c init settings
* @i2c_mode_data : ois i2c mode settings
* @i2c_time_data : ois i2c time write settings
* @i2c_preprog_data : ois i2c preprog settings
* @i2c_precoeff_data : ois i2c precoeff settings
* @i2c_postcalib_data : ois i2c postcalib settings
* @i2c_calib_data : ois i2c calib settings
* @ois_device_type : ois device type
* @cam_ois_state : ois_device_state
* @ois_fw_flag : flag for firmware download
* @ois_preprog_flag : flag for preprog reg settings
* @ois_precoeff_flag : flag for precoeff reg settings
* @is_ois_calib : flag for Calibration data
* @ois_postcalib_flag : flag for postcalib reg settings
* @opcode : ois opcode
* @ois_fw_inc_addr : flag to increment address when sending fw
* @ois_fw_addr_type : address type of fw
* @ois_fw_txn_data_sz : num data bytes per i2c txn when sending fw
* @device_name : Device name
*
*/
@ -115,14 +124,23 @@ struct cam_ois_ctrl_t {
struct cam_subdev v4l2_dev_str;
struct cam_ois_intf_params bridge_intf;
struct i2c_settings_array i2c_init_data;
struct i2c_settings_array i2c_preprog_data;
struct i2c_settings_array i2c_precoeff_data;
struct i2c_settings_array i2c_calib_data;
struct i2c_settings_array i2c_postcalib_data;
struct i2c_settings_array i2c_mode_data;
struct i2c_settings_array i2c_time_data;
enum msm_camera_device_type_t ois_device_type;
enum cam_ois_state cam_ois_state;
char ois_name[32];
uint8_t ois_fw_flag;
uint8_t ois_preprog_flag;
uint8_t ois_precoeff_flag;
uint8_t is_ois_calib;
uint8_t ois_postcalib_flag;
uint8_t ois_fw_txn_data_sz;
uint8_t ois_fw_inc_addr;
uint8_t ois_fw_addr_type;
struct cam_ois_opcode opcode;
};

View file

@ -137,6 +137,12 @@ struct cam_cmd_ois_info {
__u8 cmd_type;
__u8 ois_fw_flag;
__u8 is_ois_calib;
__u8 ois_preprog_flag;
__u8 ois_precoeff_flag;
__u8 ois_postcalib_flag;
__u8 ois_fw_txn_data_sz;
__u8 ois_fw_inc_addr;
__u8 ois_fw_addr_type;
char ois_name[MAX_OIS_NAME_SIZE];
struct cam_ois_opcode opcode;
} __attribute__((packed));