Loading drivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_bus/cam_vfe_bus_ver2.c +90 −24 Original line number Diff line number Diff line Loading @@ -71,6 +71,16 @@ enum cam_vfe_bus_packer_format { PACKER_FMT_MAX = 0xF, }; enum cam_vfe_bus_comp_grp_id { CAM_VFE_BUS_COMP_GROUP_NONE = -EINVAL, CAM_VFE_BUS_COMP_GROUP_ID_0 = 0x0, CAM_VFE_BUS_COMP_GROUP_ID_1 = 0x1, CAM_VFE_BUS_COMP_GROUP_ID_2 = 0x2, CAM_VFE_BUS_COMP_GROUP_ID_3 = 0x3, CAM_VFE_BUS_COMP_GROUP_ID_4 = 0x4, CAM_VFE_BUS_COMP_GROUP_ID_5 = 0x5, }; struct cam_vfe_bus_ver2_common_data { uint32_t core_index; void __iomem *mem_base; Loading Loading @@ -136,6 +146,9 @@ struct cam_vfe_bus_ver2_comp_grp_data { uint32_t intra_client_mask; uint32_t composite_mask; uint32_t acquire_dev_cnt; uint32_t irq_trigger_cnt; void *ctx; }; Loading Loading @@ -187,6 +200,28 @@ static int cam_vfe_bus_get_evt_payload( return 0; } static enum cam_vfe_bus_comp_grp_id cam_vfe_bus_comp_grp_id_convert(uint32_t comp_grp) { switch (comp_grp) { case CAM_ISP_RES_COMP_GROUP_ID_0: return CAM_VFE_BUS_COMP_GROUP_ID_0; case CAM_ISP_RES_COMP_GROUP_ID_1: return CAM_VFE_BUS_COMP_GROUP_ID_1; case CAM_ISP_RES_COMP_GROUP_ID_2: return CAM_VFE_BUS_COMP_GROUP_ID_2; case CAM_ISP_RES_COMP_GROUP_ID_3: return CAM_VFE_BUS_COMP_GROUP_ID_3; case CAM_ISP_RES_COMP_GROUP_ID_4: return CAM_VFE_BUS_COMP_GROUP_ID_4; case CAM_ISP_RES_COMP_GROUP_ID_5: return CAM_VFE_BUS_COMP_GROUP_ID_5; case CAM_ISP_RES_COMP_GROUP_NONE: default: return CAM_VFE_BUS_COMP_GROUP_NONE; } } static int cam_vfe_bus_put_evt_payload(void *core_info, struct cam_vfe_bus_irq_evt_payload **evt_payload) { Loading Loading @@ -1188,12 +1223,18 @@ static int cam_vfe_bus_acquire_comp_grp( struct cam_isp_resource_node **comp_grp) { int rc = 0; uint32_t bus_comp_grp_id; struct cam_isp_resource_node *comp_grp_local = NULL; struct cam_vfe_bus_ver2_comp_grp_data *rsrc_data = NULL; bus_comp_grp_id = cam_vfe_bus_comp_grp_id_convert( out_port_info->comp_grp_id); /* Perform match only if there is valid comp grp request */ if (out_port_info->comp_grp_id != CAM_ISP_RES_COMP_GROUP_NONE) { /* Check if matching comp_grp already acquired */ cam_vfe_bus_match_comp_grp(ver2_bus_priv, &comp_grp_local, out_port_info->comp_grp_id, unique_id); bus_comp_grp_id, unique_id); } if (!comp_grp_local) { /* First find a free group */ Loading Loading @@ -1228,7 +1269,7 @@ static int cam_vfe_bus_acquire_comp_grp( rsrc_data->is_master = is_master; rsrc_data->composite_mask = 0; rsrc_data->unique_id = unique_id; rsrc_data->comp_grp_local_idx = out_port_info->comp_grp_id; rsrc_data->comp_grp_local_idx = bus_comp_grp_id; list_add_tail(&comp_grp_local->list, &ver2_bus_priv->used_comp_grp); Loading @@ -1246,6 +1287,7 @@ static int cam_vfe_bus_acquire_comp_grp( } rsrc_data->ctx = ctx; rsrc_data->acquire_dev_cnt++; *comp_grp = comp_grp_local; return rc; Loading @@ -1260,15 +1302,21 @@ static int cam_vfe_bus_release_comp_grp( int match_found = 0; if (!in_comp_grp) { CAM_ERR(CAM_ISP, "Invalid Params Comp Grp %pK", in_rsrc_data); CAM_ERR(CAM_ISP, "Invalid Params Comp Grp %pK", in_comp_grp); return -EINVAL; } if (in_comp_grp->res_state == CAM_ISP_RESOURCE_STATE_AVAILABLE) { /* Already Released. Do Nothing */ CAM_ERR(CAM_ISP, "Already released Comp Grp"); return 0; } if (in_comp_grp->res_state == CAM_ISP_RESOURCE_STATE_STREAMING) { CAM_ERR(CAM_ISP, "Invalid State %d", in_comp_grp->res_state); return -EBUSY; } in_rsrc_data = in_comp_grp->res_priv; list_for_each_entry(comp_grp, &ver2_bus_priv->used_comp_grp, list) { Loading @@ -1284,24 +1332,32 @@ static int cam_vfe_bus_release_comp_grp( return -ENODEV; } in_rsrc_data->acquire_dev_cnt--; if (in_rsrc_data->acquire_dev_cnt == 0) { list_del(&comp_grp->list); if (in_rsrc_data->comp_grp_type >= CAM_VFE_BUS_VER2_COMP_GRP_DUAL_0 && in_rsrc_data->comp_grp_type <= CAM_VFE_BUS_VER2_COMP_GRP_DUAL_5) list_add_tail(&comp_grp->list, &ver2_bus_priv->free_dual_comp_grp); else if (in_rsrc_data->comp_grp_type >= CAM_VFE_BUS_VER2_COMP_GRP_0 && in_rsrc_data->comp_grp_type <= CAM_VFE_BUS_VER2_COMP_GRP_5) list_add_tail(&comp_grp->list, &ver2_bus_priv->free_comp_grp); in_rsrc_data->unique_id = 0; in_rsrc_data->comp_grp_local_idx = 0; in_rsrc_data->comp_grp_local_idx = CAM_VFE_BUS_COMP_GROUP_NONE; in_rsrc_data->composite_mask = 0; in_rsrc_data->dual_slave_core = CAM_VFE_BUS_VER2_VFE_CORE_MAX; comp_grp->tasklet_info = NULL; comp_grp->res_state = CAM_ISP_RESOURCE_STATE_AVAILABLE; if (in_rsrc_data->comp_grp_type >= CAM_VFE_BUS_VER2_COMP_GRP_DUAL_0 && in_rsrc_data->comp_grp_type <= CAM_VFE_BUS_VER2_COMP_GRP_DUAL_5) list_add_tail(&comp_grp->list, &ver2_bus_priv->free_dual_comp_grp); else if (in_rsrc_data->comp_grp_type >= CAM_VFE_BUS_VER2_COMP_GRP_0 && in_rsrc_data->comp_grp_type <= CAM_VFE_BUS_VER2_COMP_GRP_5) list_add_tail(&comp_grp->list, &ver2_bus_priv->free_comp_grp); } return 0; } Loading Loading @@ -1491,8 +1547,13 @@ static int cam_vfe_bus_handle_comp_done_bottom_half( /* Regular Composite SUCCESS */ if (status_reg & BIT(comp_grp_id + 5)) { rsrc_data->irq_trigger_cnt++; if (rsrc_data->irq_trigger_cnt == rsrc_data->acquire_dev_cnt) { cam_ife_irq_regs[CAM_IFE_IRQ_BUS_REG_STATUS0] &= ~BIT(comp_grp_id + 5); rsrc_data->irq_trigger_cnt = 0; } rc = CAM_VFE_IRQ_STATUS_SUCCESS; } Loading Loading @@ -1530,8 +1591,13 @@ static int cam_vfe_bus_handle_comp_done_bottom_half( /* DUAL Composite SUCCESS */ if (status_reg & BIT(comp_grp_id)) { rsrc_data->irq_trigger_cnt++; if (rsrc_data->irq_trigger_cnt == rsrc_data->acquire_dev_cnt) { cam_ife_irq_regs[CAM_IFE_IRQ_BUS_REG_STATUS2] &= ~BIT(comp_grp_id + 5); rsrc_data->irq_trigger_cnt = 0; } rc = CAM_VFE_IRQ_STATUS_SUCCESS; } Loading drivers/media/platform/msm/camera/cam_sensor_module/Makefile +1 −0 Original line number Diff line number Diff line Loading @@ -6,3 +6,4 @@ obj-$(CONFIG_SPECTRA_CAMERA) += cam_actuator/ obj-$(CONFIG_SPECTRA_CAMERA) += cam_sensor/ obj-$(CONFIG_SPECTRA_CAMERA) += cam_flash/ obj-$(CONFIG_SPECTRA_CAMERA) += cam_eeprom/ obj-$(CONFIG_SPECTRA_CAMERA) += cam_ois/ drivers/media/platform/msm/camera/cam_sensor_module/cam_ois/Makefile 0 → 100644 +9 −0 Original line number Diff line number Diff line ccflags-y += -Idrivers/media/platform/msm/camera/cam_utils ccflags-y += -Idrivers/media/platform/msm/camera/cam_cpas/include ccflags-y += -Idrivers/media/platform/msm/camera/cam_sensor_module/cam_sensor_io ccflags-y += -Idrivers/media/platform/msm/camera/cam_sensor_module/cam_sensor_utils ccflags-y += -Idrivers/media/platform/msm/camera/cam_req_mgr ccflags-y += -Idrivers/media/platform/msm/camera/cam_sensor_module/cam_cci ccflags-y += -Idrivers/media/platform/msm/camera/cam_smmu/ obj-$(CONFIG_SPECTRA_CAMERA) += cam_ois_dev.o cam_ois_core.o cam_ois_soc.o drivers/media/platform/msm/camera/cam_sensor_module/cam_ois/cam_ois_core.c 0 → 100644 +594 −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/firmware.h> #include <cam_sensor_cmn_header.h> #include "cam_ois_core.h" #include "cam_ois_soc.h" #include "cam_sensor_util.h" #include "cam_debug_util.h" /** * cam_ois_get_dev_handle - get device handle * @o_ctrl: ctrl structure * @arg: Camera control command argument * * Returns success or failure */ static int cam_ois_get_dev_handle(struct cam_ois_ctrl_t *o_ctrl, void *arg) { struct cam_sensor_acquire_dev ois_acq_dev; struct cam_create_dev_hdl bridge_params; struct cam_control *cmd = (struct cam_control *)arg; if (o_ctrl->bridge_intf.device_hdl != -1) { CAM_ERR(CAM_OIS, "Device is already acquired"); return -EFAULT; } if (copy_from_user(&ois_acq_dev, (void __user *) cmd->handle, sizeof(ois_acq_dev))) return -EFAULT; bridge_params.session_hdl = ois_acq_dev.session_handle; bridge_params.ops = &o_ctrl->bridge_intf.ops; bridge_params.v4l2_sub_dev_flag = 0; bridge_params.media_entity_flag = 0; bridge_params.priv = o_ctrl; ois_acq_dev.device_handle = cam_create_device_hdl(&bridge_params); o_ctrl->bridge_intf.device_hdl = ois_acq_dev.device_handle; o_ctrl->bridge_intf.session_hdl = ois_acq_dev.session_handle; CAM_DBG(CAM_OIS, "Device Handle: %d", ois_acq_dev.device_handle); if (copy_to_user((void __user *) cmd->handle, &ois_acq_dev, sizeof(struct cam_sensor_acquire_dev))) { CAM_ERR(CAM_OIS, "ACQUIRE_DEV: copy to user failed"); return -EFAULT; } return 0; } static int cam_ois_vreg_control(struct cam_ois_ctrl_t *o_ctrl, int config) { int rc = 0, cnt; struct cam_hw_soc_info *soc_info; soc_info = &o_ctrl->soc_info; cnt = soc_info->num_rgltr; if (!cnt) return 0; if (cnt >= CAM_SOC_MAX_REGULATOR) { CAM_ERR(CAM_OIS, "Regulators more than supported %d", cnt); return -EINVAL; } if (config) rc = cam_soc_util_enable_platform_resource(soc_info, false, 0, false); else rc = cam_soc_util_disable_platform_resource(soc_info, false, false); return rc; } static int cam_ois_power_up(struct cam_ois_ctrl_t *o_ctrl) { int rc = 0; struct cam_hw_soc_info *soc_info = &o_ctrl->soc_info; struct msm_camera_gpio_num_info *gpio_num_info = NULL; rc = cam_ois_vreg_control(o_ctrl, 1); if (rc < 0) { CAM_ERR(CAM_OIS, "OIS Reg Failed %d", rc); return rc; } gpio_num_info = o_ctrl->gpio_num_info; if (soc_info->gpio_data && gpio_num_info && gpio_num_info->valid[SENSOR_VAF] == 1) { rc = cam_soc_util_request_platform_resource(&o_ctrl->soc_info, NULL, NULL); rc = cam_soc_util_enable_platform_resource(&o_ctrl->soc_info, false, 0, false); if (rc < 0) { CAM_ERR(CAM_OIS, "Failed in req gpio: %d", rc); return rc; } gpio_set_value_cansleep( gpio_num_info->gpio_num[SENSOR_VAF], 1); } /* VREG needs some delay to power up */ usleep_range(2000, 2050); return rc; } static int cam_ois_power_down(struct cam_ois_ctrl_t *o_ctrl) { int32_t rc = 0; struct cam_hw_soc_info *soc_info = &o_ctrl->soc_info; struct msm_camera_gpio_num_info *gpio_num_info = NULL; rc = cam_ois_vreg_control(o_ctrl, 0); if (rc < 0) { CAM_ERR(CAM_OIS, "Failed %d"); return rc; } gpio_num_info = o_ctrl->gpio_num_info; if (soc_info->gpio_data && gpio_num_info && gpio_num_info->valid[SENSOR_VAF] == 1) { gpio_set_value_cansleep( gpio_num_info->gpio_num[SENSOR_VAF], GPIOF_OUT_INIT_LOW); rc = cam_soc_util_release_platform_resource(&o_ctrl->soc_info); rc |= cam_soc_util_disable_platform_resource(&o_ctrl->soc_info, 0, 0); if (rc < 0) CAM_ERR(CAM_OIS, "Failed to disable platform resources: %d", rc); } return rc; } static int cam_ois_apply_settings(struct cam_ois_ctrl_t *o_ctrl, struct i2c_settings_array *i2c_set) { struct i2c_settings_list *i2c_list; int32_t rc = 0; uint32_t i, size; if (o_ctrl == NULL || i2c_set == NULL) { CAM_ERR(CAM_OIS, "Invalid Args"); return -EINVAL; } if (i2c_set->is_settings_valid != 1) { CAM_ERR(CAM_OIS, " Invalid settings"); return -EINVAL; } list_for_each_entry(i2c_list, &(i2c_set->list_head), list) { if (i2c_list->op_code == CAM_SENSOR_I2C_WRITE_RANDOM) { rc = camera_io_dev_write(&(o_ctrl->io_master_info), &(i2c_list->i2c_settings)); if (rc < 0) { CAM_ERR(CAM_OIS, "Failed in Applying i2c wrt settings"); return rc; } } else if (i2c_list->op_code == CAM_SENSOR_I2C_POLL) { size = i2c_list->i2c_settings.size; for (i = 0; i < size; i++) { rc = camera_io_dev_poll( &(o_ctrl->io_master_info), i2c_list->i2c_settings. reg_setting[i].reg_addr, i2c_list->i2c_settings. reg_setting[i].reg_data, i2c_list->i2c_settings. reg_setting[i].data_mask, i2c_list->i2c_settings.addr_type, i2c_list->i2c_settings.data_type, i2c_list->i2c_settings. reg_setting[i].delay); if (rc < 0) { CAM_ERR(CAM_OIS, "i2c poll apply setting Fail"); return rc; } } } } return rc; } static int cam_ois_slaveInfo_pkt_parser(struct cam_ois_ctrl_t *o_ctrl, uint32_t *cmd_buf) { int32_t rc = 0; struct cam_cmd_ois_info *ois_info; if (!o_ctrl || !cmd_buf) { CAM_ERR(CAM_OIS, "Invalid Args"); return -EINVAL; } ois_info = (struct cam_cmd_ois_info *)cmd_buf; if (o_ctrl->io_master_info.master_type == CCI_MASTER) { o_ctrl->io_master_info.cci_client->i2c_freq_mode = ois_info->i2c_freq_mode; 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->is_ois_calib = ois_info->is_ois_calib; memcpy(o_ctrl->ois_name, ois_info->ois_name, 32); o_ctrl->io_master_info.cci_client->retries = 3; o_ctrl->io_master_info.cci_client->id_map = 0; memcpy(&(o_ctrl->opcode), &(ois_info->opcode), sizeof(struct cam_ois_opcode)); CAM_DBG(CAM_OIS, "Slave addr: 0x%x Freq Mode: %d", ois_info->slave_addr, ois_info->i2c_freq_mode); } else if (o_ctrl->io_master_info.master_type == I2C_MASTER) { o_ctrl->io_master_info.client->addr = ois_info->slave_addr; CAM_DBG(CAM_OIS, "Slave addr: 0x%x", ois_info->slave_addr); } else { CAM_ERR(CAM_OIS, "Invalid Master type : %d", o_ctrl->io_master_info.master_type); rc = -EINVAL; } return rc; } static int cam_ois_fw_download(struct cam_ois_ctrl_t *o_ctrl) { uint16_t total_bytes = 0; uint8_t *ptr = NULL; int32_t rc = 0, cnt; const struct firmware *fw = NULL; const char *fw_name_prog = NULL; const char *fw_name_coeff = NULL; char name_prog[32] = {0}; char name_coeff[32] = {0}; struct device *dev = &(o_ctrl->pdev->dev); struct cam_sensor_i2c_reg_setting i2c_reg_setting; if (!o_ctrl) { CAM_ERR(CAM_OIS, "Invalid Args"); return -EINVAL; } 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.reg_setting = (struct cam_sensor_i2c_reg_array *) kzalloc(sizeof(struct cam_sensor_i2c_reg_array) * total_bytes, GFP_KERNEL); if (!i2c_reg_setting.reg_setting) { CAM_ERR(CAM_OIS, "Failed in allocating i2c_array"); release_firmware(fw); return -ENOMEM; } 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; } kfree(i2c_reg_setting.reg_setting); release_firmware(fw); rc = request_firmware(&fw, fw_name_coeff, dev); if (rc) { CAM_ERR(CAM_OIS, "Failed to locate %s", fw_name_coeff); 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.reg_setting = (struct cam_sensor_i2c_reg_array *) kzalloc(sizeof(struct cam_sensor_i2c_reg_array) * total_bytes, GFP_KERNEL); if (!i2c_reg_setting.reg_setting) { CAM_ERR(CAM_OIS, "Failed in allocating i2c_array"); release_firmware(fw); return -ENOMEM; } 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; } 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: kfree(i2c_reg_setting.reg_setting); release_firmware(fw); return rc; } /** * cam_ois_pkt_parse - Parse csl packet * @o_ctrl: ctrl structure * @arg: Camera control command argument * * Returns success or failure */ static int cam_ois_pkt_parse(struct cam_ois_ctrl_t *o_ctrl, void *arg) { int32_t rc = 0; uint64_t generic_ptr; struct cam_control *ioctl_ctrl = NULL; struct cam_config_dev_cmd dev_config; struct i2c_settings_array *i2c_reg_settings = NULL; struct cam_cmd_buf_desc *cmd_desc = NULL; uint64_t generic_pkt_addr; size_t pkt_len; struct cam_packet *csl_packet = NULL; size_t len_of_buff = 0; uint32_t *offset = NULL, *cmd_buf; ioctl_ctrl = (struct cam_control *)arg; if (copy_from_user(&dev_config, (void __user *) ioctl_ctrl->handle, sizeof(dev_config))) return -EFAULT; rc = cam_mem_get_cpu_buf(dev_config.packet_handle, (uint64_t *)&generic_pkt_addr, &pkt_len); if (rc) { CAM_ERR(CAM_OIS, "error in converting command Handle Error: %d", rc); return rc; } if (dev_config.offset > pkt_len) { CAM_ERR(CAM_OIS, "offset is out of bound: off: %lld len: %zu", dev_config.offset, pkt_len); return -EINVAL; } csl_packet = (struct cam_packet *) (generic_pkt_addr + dev_config.offset); switch (csl_packet->header.op_code & 0xFFFFFF) { case CAM_OIS_PACKET_OPCODE_INIT: offset = (uint32_t *)&csl_packet->payload; offset += (csl_packet->cmd_buf_offset / sizeof(uint32_t)); cmd_desc = (struct cam_cmd_buf_desc *)(offset); if ((csl_packet->num_cmd_buf < 2) && (csl_packet->num_cmd_buf > 3)) { CAM_ERR(CAM_OIS, "wrong cmd Buffer count: %d", csl_packet->num_cmd_buf); return -EINVAL; } rc = cam_mem_get_cpu_buf(cmd_desc[0].mem_handle, (uint64_t *)&generic_ptr, &len_of_buff); if (rc < 0) { CAM_ERR(CAM_OIS, "Failed to get cpu buf"); return rc; } cmd_buf = (uint32_t *)generic_ptr; cmd_buf += cmd_desc->offset / sizeof(uint32_t); rc = cam_ois_slaveInfo_pkt_parser(o_ctrl, cmd_buf); if (rc < 0) { CAM_ERR(CAM_OIS, "Failed in parsing the pkt"); return rc; } cmd_buf += (sizeof(struct cam_cmd_i2c_info)/sizeof(uint32_t)); i2c_reg_settings = &(o_ctrl->i2c_init_data); i2c_reg_settings->is_settings_valid = 1; i2c_reg_settings->request_id = 0; rc = cam_sensor_i2c_pkt_parser(i2c_reg_settings, &cmd_desc[1], 1); if (rc < 0) { CAM_ERR(CAM_OIS, "OIS pkt parsing failed: %d", rc); return rc; } if (o_ctrl->is_ois_calib) { i2c_reg_settings = &(o_ctrl->i2c_calib_data); i2c_reg_settings->is_settings_valid = 1; i2c_reg_settings->request_id = 0; rc = cam_sensor_i2c_pkt_parser(i2c_reg_settings, &cmd_desc[2], 1); if (rc < 0) { CAM_ERR(CAM_OIS, "OIS pkt parsing failed: %d", rc); return rc; } } break; case CAM_OIS_PACKET_OPCODE_OIS_CONTROL: offset = (uint32_t *)&csl_packet->payload; offset += (csl_packet->cmd_buf_offset / sizeof(uint32_t)); cmd_desc = (struct cam_cmd_buf_desc *)(offset); i2c_reg_settings = &(o_ctrl->i2c_mode_data); i2c_reg_settings->is_settings_valid = 1; i2c_reg_settings->request_id = 0; rc = cam_sensor_i2c_pkt_parser(i2c_reg_settings, cmd_desc, 1); if (rc < 0) { CAM_ERR(CAM_OIS, "OIS pkt parsing failed: %d", rc); return rc; } rc = cam_ois_apply_settings(o_ctrl, i2c_reg_settings); if (rc < 0) CAM_ERR(CAM_OIS, "Cannot apply mode settings"); break; default: break; } return rc; } /** * cam_ois_driver_cmd - Handle ois cmds * @e_ctrl: ctrl structure * @arg: Camera control command argument * * Returns success or failure */ int cam_ois_driver_cmd(struct cam_ois_ctrl_t *o_ctrl, void *arg) { int rc = 0; struct cam_ois_query_cap_t ois_cap = {0}; struct cam_control *cmd = (struct cam_control *)arg; if (!o_ctrl) { CAM_ERR(CAM_OIS, "e_ctrl is NULL"); return -EINVAL; } mutex_lock(&(o_ctrl->ois_mutex)); switch (cmd->op_code) { case CAM_QUERY_CAP: ois_cap.slot_info = o_ctrl->subdev_id; if (copy_to_user((void __user *) cmd->handle, &ois_cap, sizeof(struct cam_ois_query_cap_t))) { CAM_ERR(CAM_OIS, "Failed Copy to User"); return -EFAULT; goto release_mutex; } CAM_DBG(CAM_OIS, "ois_cap: ID: %d", ois_cap.slot_info); break; case CAM_ACQUIRE_DEV: rc = cam_ois_get_dev_handle(o_ctrl, arg); if (rc) { CAM_ERR(CAM_OIS, "Failed to acquire dev"); goto release_mutex; } break; case CAM_START_DEV: rc = cam_ois_power_up(o_ctrl); if (rc) { CAM_ERR(CAM_OIS, " OIS Power up failed"); goto release_mutex; } rc = camera_io_init(&o_ctrl->io_master_info); if (rc) { CAM_ERR(CAM_OIS, "cci_init failed"); goto pwr_dwn; } if (o_ctrl->ois_fw_flag) { rc = cam_ois_fw_download(o_ctrl); if (rc) { CAM_ERR(CAM_OIS, "Failed OIS FW Download"); goto pwr_dwn; } } rc = cam_ois_apply_settings(o_ctrl, &o_ctrl->i2c_init_data); if (rc < 0) { CAM_ERR(CAM_OIS, "Cannot apply Init settings"); goto pwr_dwn; } if (o_ctrl->is_ois_calib) { rc = cam_ois_apply_settings(o_ctrl, &o_ctrl->i2c_calib_data); if (rc) { CAM_ERR(CAM_OIS, "Cannot apply calib data"); goto pwr_dwn; } } break; case CAM_CONFIG_DEV: rc = cam_ois_pkt_parse(o_ctrl, arg); if (rc) { CAM_ERR(CAM_OIS, "Failed in ois pkt Parsing"); goto release_mutex; } break; case CAM_RELEASE_DEV: if (o_ctrl->bridge_intf.device_hdl == -1) { CAM_ERR(CAM_OIS, "link hdl: %d device hdl: %d", o_ctrl->bridge_intf.device_hdl, o_ctrl->bridge_intf.link_hdl); rc = -EINVAL; goto release_mutex; } rc = cam_destroy_device_hdl(o_ctrl->bridge_intf.device_hdl); if (rc < 0) CAM_ERR(CAM_OIS, "destroying the device hdl"); o_ctrl->bridge_intf.device_hdl = -1; o_ctrl->bridge_intf.link_hdl = -1; o_ctrl->bridge_intf.session_hdl = -1; break; case CAM_STOP_DEV: rc = camera_io_release(&o_ctrl->io_master_info); if (rc < 0) CAM_ERR(CAM_OIS, "Failed in releasing CCI"); rc = cam_ois_power_down(o_ctrl); if (rc < 0) { CAM_ERR(CAM_OIS, "OIS Power down failed"); goto release_mutex; } break; default: CAM_ERR(CAM_OIS, "invalid opcode"); goto release_mutex; } pwr_dwn: cam_ois_power_down(o_ctrl); release_mutex: mutex_unlock(&(o_ctrl->ois_mutex)); return rc; } drivers/media/platform/msm/camera/cam_sensor_module/cam_ois/cam_ois_core.h 0 → 100644 +20 −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 _CAM_OIS_CORE_H_ #define _CAM_OIS_CORE_H_ #include "cam_ois_dev.h" int cam_ois_driver_cmd(struct cam_ois_ctrl_t *e_ctrl, void *arg); #endif /* _CAM_OIS_CORE_H_ */ Loading
drivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_bus/cam_vfe_bus_ver2.c +90 −24 Original line number Diff line number Diff line Loading @@ -71,6 +71,16 @@ enum cam_vfe_bus_packer_format { PACKER_FMT_MAX = 0xF, }; enum cam_vfe_bus_comp_grp_id { CAM_VFE_BUS_COMP_GROUP_NONE = -EINVAL, CAM_VFE_BUS_COMP_GROUP_ID_0 = 0x0, CAM_VFE_BUS_COMP_GROUP_ID_1 = 0x1, CAM_VFE_BUS_COMP_GROUP_ID_2 = 0x2, CAM_VFE_BUS_COMP_GROUP_ID_3 = 0x3, CAM_VFE_BUS_COMP_GROUP_ID_4 = 0x4, CAM_VFE_BUS_COMP_GROUP_ID_5 = 0x5, }; struct cam_vfe_bus_ver2_common_data { uint32_t core_index; void __iomem *mem_base; Loading Loading @@ -136,6 +146,9 @@ struct cam_vfe_bus_ver2_comp_grp_data { uint32_t intra_client_mask; uint32_t composite_mask; uint32_t acquire_dev_cnt; uint32_t irq_trigger_cnt; void *ctx; }; Loading Loading @@ -187,6 +200,28 @@ static int cam_vfe_bus_get_evt_payload( return 0; } static enum cam_vfe_bus_comp_grp_id cam_vfe_bus_comp_grp_id_convert(uint32_t comp_grp) { switch (comp_grp) { case CAM_ISP_RES_COMP_GROUP_ID_0: return CAM_VFE_BUS_COMP_GROUP_ID_0; case CAM_ISP_RES_COMP_GROUP_ID_1: return CAM_VFE_BUS_COMP_GROUP_ID_1; case CAM_ISP_RES_COMP_GROUP_ID_2: return CAM_VFE_BUS_COMP_GROUP_ID_2; case CAM_ISP_RES_COMP_GROUP_ID_3: return CAM_VFE_BUS_COMP_GROUP_ID_3; case CAM_ISP_RES_COMP_GROUP_ID_4: return CAM_VFE_BUS_COMP_GROUP_ID_4; case CAM_ISP_RES_COMP_GROUP_ID_5: return CAM_VFE_BUS_COMP_GROUP_ID_5; case CAM_ISP_RES_COMP_GROUP_NONE: default: return CAM_VFE_BUS_COMP_GROUP_NONE; } } static int cam_vfe_bus_put_evt_payload(void *core_info, struct cam_vfe_bus_irq_evt_payload **evt_payload) { Loading Loading @@ -1188,12 +1223,18 @@ static int cam_vfe_bus_acquire_comp_grp( struct cam_isp_resource_node **comp_grp) { int rc = 0; uint32_t bus_comp_grp_id; struct cam_isp_resource_node *comp_grp_local = NULL; struct cam_vfe_bus_ver2_comp_grp_data *rsrc_data = NULL; bus_comp_grp_id = cam_vfe_bus_comp_grp_id_convert( out_port_info->comp_grp_id); /* Perform match only if there is valid comp grp request */ if (out_port_info->comp_grp_id != CAM_ISP_RES_COMP_GROUP_NONE) { /* Check if matching comp_grp already acquired */ cam_vfe_bus_match_comp_grp(ver2_bus_priv, &comp_grp_local, out_port_info->comp_grp_id, unique_id); bus_comp_grp_id, unique_id); } if (!comp_grp_local) { /* First find a free group */ Loading Loading @@ -1228,7 +1269,7 @@ static int cam_vfe_bus_acquire_comp_grp( rsrc_data->is_master = is_master; rsrc_data->composite_mask = 0; rsrc_data->unique_id = unique_id; rsrc_data->comp_grp_local_idx = out_port_info->comp_grp_id; rsrc_data->comp_grp_local_idx = bus_comp_grp_id; list_add_tail(&comp_grp_local->list, &ver2_bus_priv->used_comp_grp); Loading @@ -1246,6 +1287,7 @@ static int cam_vfe_bus_acquire_comp_grp( } rsrc_data->ctx = ctx; rsrc_data->acquire_dev_cnt++; *comp_grp = comp_grp_local; return rc; Loading @@ -1260,15 +1302,21 @@ static int cam_vfe_bus_release_comp_grp( int match_found = 0; if (!in_comp_grp) { CAM_ERR(CAM_ISP, "Invalid Params Comp Grp %pK", in_rsrc_data); CAM_ERR(CAM_ISP, "Invalid Params Comp Grp %pK", in_comp_grp); return -EINVAL; } if (in_comp_grp->res_state == CAM_ISP_RESOURCE_STATE_AVAILABLE) { /* Already Released. Do Nothing */ CAM_ERR(CAM_ISP, "Already released Comp Grp"); return 0; } if (in_comp_grp->res_state == CAM_ISP_RESOURCE_STATE_STREAMING) { CAM_ERR(CAM_ISP, "Invalid State %d", in_comp_grp->res_state); return -EBUSY; } in_rsrc_data = in_comp_grp->res_priv; list_for_each_entry(comp_grp, &ver2_bus_priv->used_comp_grp, list) { Loading @@ -1284,24 +1332,32 @@ static int cam_vfe_bus_release_comp_grp( return -ENODEV; } in_rsrc_data->acquire_dev_cnt--; if (in_rsrc_data->acquire_dev_cnt == 0) { list_del(&comp_grp->list); if (in_rsrc_data->comp_grp_type >= CAM_VFE_BUS_VER2_COMP_GRP_DUAL_0 && in_rsrc_data->comp_grp_type <= CAM_VFE_BUS_VER2_COMP_GRP_DUAL_5) list_add_tail(&comp_grp->list, &ver2_bus_priv->free_dual_comp_grp); else if (in_rsrc_data->comp_grp_type >= CAM_VFE_BUS_VER2_COMP_GRP_0 && in_rsrc_data->comp_grp_type <= CAM_VFE_BUS_VER2_COMP_GRP_5) list_add_tail(&comp_grp->list, &ver2_bus_priv->free_comp_grp); in_rsrc_data->unique_id = 0; in_rsrc_data->comp_grp_local_idx = 0; in_rsrc_data->comp_grp_local_idx = CAM_VFE_BUS_COMP_GROUP_NONE; in_rsrc_data->composite_mask = 0; in_rsrc_data->dual_slave_core = CAM_VFE_BUS_VER2_VFE_CORE_MAX; comp_grp->tasklet_info = NULL; comp_grp->res_state = CAM_ISP_RESOURCE_STATE_AVAILABLE; if (in_rsrc_data->comp_grp_type >= CAM_VFE_BUS_VER2_COMP_GRP_DUAL_0 && in_rsrc_data->comp_grp_type <= CAM_VFE_BUS_VER2_COMP_GRP_DUAL_5) list_add_tail(&comp_grp->list, &ver2_bus_priv->free_dual_comp_grp); else if (in_rsrc_data->comp_grp_type >= CAM_VFE_BUS_VER2_COMP_GRP_0 && in_rsrc_data->comp_grp_type <= CAM_VFE_BUS_VER2_COMP_GRP_5) list_add_tail(&comp_grp->list, &ver2_bus_priv->free_comp_grp); } return 0; } Loading Loading @@ -1491,8 +1547,13 @@ static int cam_vfe_bus_handle_comp_done_bottom_half( /* Regular Composite SUCCESS */ if (status_reg & BIT(comp_grp_id + 5)) { rsrc_data->irq_trigger_cnt++; if (rsrc_data->irq_trigger_cnt == rsrc_data->acquire_dev_cnt) { cam_ife_irq_regs[CAM_IFE_IRQ_BUS_REG_STATUS0] &= ~BIT(comp_grp_id + 5); rsrc_data->irq_trigger_cnt = 0; } rc = CAM_VFE_IRQ_STATUS_SUCCESS; } Loading Loading @@ -1530,8 +1591,13 @@ static int cam_vfe_bus_handle_comp_done_bottom_half( /* DUAL Composite SUCCESS */ if (status_reg & BIT(comp_grp_id)) { rsrc_data->irq_trigger_cnt++; if (rsrc_data->irq_trigger_cnt == rsrc_data->acquire_dev_cnt) { cam_ife_irq_regs[CAM_IFE_IRQ_BUS_REG_STATUS2] &= ~BIT(comp_grp_id + 5); rsrc_data->irq_trigger_cnt = 0; } rc = CAM_VFE_IRQ_STATUS_SUCCESS; } Loading
drivers/media/platform/msm/camera/cam_sensor_module/Makefile +1 −0 Original line number Diff line number Diff line Loading @@ -6,3 +6,4 @@ obj-$(CONFIG_SPECTRA_CAMERA) += cam_actuator/ obj-$(CONFIG_SPECTRA_CAMERA) += cam_sensor/ obj-$(CONFIG_SPECTRA_CAMERA) += cam_flash/ obj-$(CONFIG_SPECTRA_CAMERA) += cam_eeprom/ obj-$(CONFIG_SPECTRA_CAMERA) += cam_ois/
drivers/media/platform/msm/camera/cam_sensor_module/cam_ois/Makefile 0 → 100644 +9 −0 Original line number Diff line number Diff line ccflags-y += -Idrivers/media/platform/msm/camera/cam_utils ccflags-y += -Idrivers/media/platform/msm/camera/cam_cpas/include ccflags-y += -Idrivers/media/platform/msm/camera/cam_sensor_module/cam_sensor_io ccflags-y += -Idrivers/media/platform/msm/camera/cam_sensor_module/cam_sensor_utils ccflags-y += -Idrivers/media/platform/msm/camera/cam_req_mgr ccflags-y += -Idrivers/media/platform/msm/camera/cam_sensor_module/cam_cci ccflags-y += -Idrivers/media/platform/msm/camera/cam_smmu/ obj-$(CONFIG_SPECTRA_CAMERA) += cam_ois_dev.o cam_ois_core.o cam_ois_soc.o
drivers/media/platform/msm/camera/cam_sensor_module/cam_ois/cam_ois_core.c 0 → 100644 +594 −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/firmware.h> #include <cam_sensor_cmn_header.h> #include "cam_ois_core.h" #include "cam_ois_soc.h" #include "cam_sensor_util.h" #include "cam_debug_util.h" /** * cam_ois_get_dev_handle - get device handle * @o_ctrl: ctrl structure * @arg: Camera control command argument * * Returns success or failure */ static int cam_ois_get_dev_handle(struct cam_ois_ctrl_t *o_ctrl, void *arg) { struct cam_sensor_acquire_dev ois_acq_dev; struct cam_create_dev_hdl bridge_params; struct cam_control *cmd = (struct cam_control *)arg; if (o_ctrl->bridge_intf.device_hdl != -1) { CAM_ERR(CAM_OIS, "Device is already acquired"); return -EFAULT; } if (copy_from_user(&ois_acq_dev, (void __user *) cmd->handle, sizeof(ois_acq_dev))) return -EFAULT; bridge_params.session_hdl = ois_acq_dev.session_handle; bridge_params.ops = &o_ctrl->bridge_intf.ops; bridge_params.v4l2_sub_dev_flag = 0; bridge_params.media_entity_flag = 0; bridge_params.priv = o_ctrl; ois_acq_dev.device_handle = cam_create_device_hdl(&bridge_params); o_ctrl->bridge_intf.device_hdl = ois_acq_dev.device_handle; o_ctrl->bridge_intf.session_hdl = ois_acq_dev.session_handle; CAM_DBG(CAM_OIS, "Device Handle: %d", ois_acq_dev.device_handle); if (copy_to_user((void __user *) cmd->handle, &ois_acq_dev, sizeof(struct cam_sensor_acquire_dev))) { CAM_ERR(CAM_OIS, "ACQUIRE_DEV: copy to user failed"); return -EFAULT; } return 0; } static int cam_ois_vreg_control(struct cam_ois_ctrl_t *o_ctrl, int config) { int rc = 0, cnt; struct cam_hw_soc_info *soc_info; soc_info = &o_ctrl->soc_info; cnt = soc_info->num_rgltr; if (!cnt) return 0; if (cnt >= CAM_SOC_MAX_REGULATOR) { CAM_ERR(CAM_OIS, "Regulators more than supported %d", cnt); return -EINVAL; } if (config) rc = cam_soc_util_enable_platform_resource(soc_info, false, 0, false); else rc = cam_soc_util_disable_platform_resource(soc_info, false, false); return rc; } static int cam_ois_power_up(struct cam_ois_ctrl_t *o_ctrl) { int rc = 0; struct cam_hw_soc_info *soc_info = &o_ctrl->soc_info; struct msm_camera_gpio_num_info *gpio_num_info = NULL; rc = cam_ois_vreg_control(o_ctrl, 1); if (rc < 0) { CAM_ERR(CAM_OIS, "OIS Reg Failed %d", rc); return rc; } gpio_num_info = o_ctrl->gpio_num_info; if (soc_info->gpio_data && gpio_num_info && gpio_num_info->valid[SENSOR_VAF] == 1) { rc = cam_soc_util_request_platform_resource(&o_ctrl->soc_info, NULL, NULL); rc = cam_soc_util_enable_platform_resource(&o_ctrl->soc_info, false, 0, false); if (rc < 0) { CAM_ERR(CAM_OIS, "Failed in req gpio: %d", rc); return rc; } gpio_set_value_cansleep( gpio_num_info->gpio_num[SENSOR_VAF], 1); } /* VREG needs some delay to power up */ usleep_range(2000, 2050); return rc; } static int cam_ois_power_down(struct cam_ois_ctrl_t *o_ctrl) { int32_t rc = 0; struct cam_hw_soc_info *soc_info = &o_ctrl->soc_info; struct msm_camera_gpio_num_info *gpio_num_info = NULL; rc = cam_ois_vreg_control(o_ctrl, 0); if (rc < 0) { CAM_ERR(CAM_OIS, "Failed %d"); return rc; } gpio_num_info = o_ctrl->gpio_num_info; if (soc_info->gpio_data && gpio_num_info && gpio_num_info->valid[SENSOR_VAF] == 1) { gpio_set_value_cansleep( gpio_num_info->gpio_num[SENSOR_VAF], GPIOF_OUT_INIT_LOW); rc = cam_soc_util_release_platform_resource(&o_ctrl->soc_info); rc |= cam_soc_util_disable_platform_resource(&o_ctrl->soc_info, 0, 0); if (rc < 0) CAM_ERR(CAM_OIS, "Failed to disable platform resources: %d", rc); } return rc; } static int cam_ois_apply_settings(struct cam_ois_ctrl_t *o_ctrl, struct i2c_settings_array *i2c_set) { struct i2c_settings_list *i2c_list; int32_t rc = 0; uint32_t i, size; if (o_ctrl == NULL || i2c_set == NULL) { CAM_ERR(CAM_OIS, "Invalid Args"); return -EINVAL; } if (i2c_set->is_settings_valid != 1) { CAM_ERR(CAM_OIS, " Invalid settings"); return -EINVAL; } list_for_each_entry(i2c_list, &(i2c_set->list_head), list) { if (i2c_list->op_code == CAM_SENSOR_I2C_WRITE_RANDOM) { rc = camera_io_dev_write(&(o_ctrl->io_master_info), &(i2c_list->i2c_settings)); if (rc < 0) { CAM_ERR(CAM_OIS, "Failed in Applying i2c wrt settings"); return rc; } } else if (i2c_list->op_code == CAM_SENSOR_I2C_POLL) { size = i2c_list->i2c_settings.size; for (i = 0; i < size; i++) { rc = camera_io_dev_poll( &(o_ctrl->io_master_info), i2c_list->i2c_settings. reg_setting[i].reg_addr, i2c_list->i2c_settings. reg_setting[i].reg_data, i2c_list->i2c_settings. reg_setting[i].data_mask, i2c_list->i2c_settings.addr_type, i2c_list->i2c_settings.data_type, i2c_list->i2c_settings. reg_setting[i].delay); if (rc < 0) { CAM_ERR(CAM_OIS, "i2c poll apply setting Fail"); return rc; } } } } return rc; } static int cam_ois_slaveInfo_pkt_parser(struct cam_ois_ctrl_t *o_ctrl, uint32_t *cmd_buf) { int32_t rc = 0; struct cam_cmd_ois_info *ois_info; if (!o_ctrl || !cmd_buf) { CAM_ERR(CAM_OIS, "Invalid Args"); return -EINVAL; } ois_info = (struct cam_cmd_ois_info *)cmd_buf; if (o_ctrl->io_master_info.master_type == CCI_MASTER) { o_ctrl->io_master_info.cci_client->i2c_freq_mode = ois_info->i2c_freq_mode; 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->is_ois_calib = ois_info->is_ois_calib; memcpy(o_ctrl->ois_name, ois_info->ois_name, 32); o_ctrl->io_master_info.cci_client->retries = 3; o_ctrl->io_master_info.cci_client->id_map = 0; memcpy(&(o_ctrl->opcode), &(ois_info->opcode), sizeof(struct cam_ois_opcode)); CAM_DBG(CAM_OIS, "Slave addr: 0x%x Freq Mode: %d", ois_info->slave_addr, ois_info->i2c_freq_mode); } else if (o_ctrl->io_master_info.master_type == I2C_MASTER) { o_ctrl->io_master_info.client->addr = ois_info->slave_addr; CAM_DBG(CAM_OIS, "Slave addr: 0x%x", ois_info->slave_addr); } else { CAM_ERR(CAM_OIS, "Invalid Master type : %d", o_ctrl->io_master_info.master_type); rc = -EINVAL; } return rc; } static int cam_ois_fw_download(struct cam_ois_ctrl_t *o_ctrl) { uint16_t total_bytes = 0; uint8_t *ptr = NULL; int32_t rc = 0, cnt; const struct firmware *fw = NULL; const char *fw_name_prog = NULL; const char *fw_name_coeff = NULL; char name_prog[32] = {0}; char name_coeff[32] = {0}; struct device *dev = &(o_ctrl->pdev->dev); struct cam_sensor_i2c_reg_setting i2c_reg_setting; if (!o_ctrl) { CAM_ERR(CAM_OIS, "Invalid Args"); return -EINVAL; } 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.reg_setting = (struct cam_sensor_i2c_reg_array *) kzalloc(sizeof(struct cam_sensor_i2c_reg_array) * total_bytes, GFP_KERNEL); if (!i2c_reg_setting.reg_setting) { CAM_ERR(CAM_OIS, "Failed in allocating i2c_array"); release_firmware(fw); return -ENOMEM; } 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; } kfree(i2c_reg_setting.reg_setting); release_firmware(fw); rc = request_firmware(&fw, fw_name_coeff, dev); if (rc) { CAM_ERR(CAM_OIS, "Failed to locate %s", fw_name_coeff); 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.reg_setting = (struct cam_sensor_i2c_reg_array *) kzalloc(sizeof(struct cam_sensor_i2c_reg_array) * total_bytes, GFP_KERNEL); if (!i2c_reg_setting.reg_setting) { CAM_ERR(CAM_OIS, "Failed in allocating i2c_array"); release_firmware(fw); return -ENOMEM; } 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; } 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: kfree(i2c_reg_setting.reg_setting); release_firmware(fw); return rc; } /** * cam_ois_pkt_parse - Parse csl packet * @o_ctrl: ctrl structure * @arg: Camera control command argument * * Returns success or failure */ static int cam_ois_pkt_parse(struct cam_ois_ctrl_t *o_ctrl, void *arg) { int32_t rc = 0; uint64_t generic_ptr; struct cam_control *ioctl_ctrl = NULL; struct cam_config_dev_cmd dev_config; struct i2c_settings_array *i2c_reg_settings = NULL; struct cam_cmd_buf_desc *cmd_desc = NULL; uint64_t generic_pkt_addr; size_t pkt_len; struct cam_packet *csl_packet = NULL; size_t len_of_buff = 0; uint32_t *offset = NULL, *cmd_buf; ioctl_ctrl = (struct cam_control *)arg; if (copy_from_user(&dev_config, (void __user *) ioctl_ctrl->handle, sizeof(dev_config))) return -EFAULT; rc = cam_mem_get_cpu_buf(dev_config.packet_handle, (uint64_t *)&generic_pkt_addr, &pkt_len); if (rc) { CAM_ERR(CAM_OIS, "error in converting command Handle Error: %d", rc); return rc; } if (dev_config.offset > pkt_len) { CAM_ERR(CAM_OIS, "offset is out of bound: off: %lld len: %zu", dev_config.offset, pkt_len); return -EINVAL; } csl_packet = (struct cam_packet *) (generic_pkt_addr + dev_config.offset); switch (csl_packet->header.op_code & 0xFFFFFF) { case CAM_OIS_PACKET_OPCODE_INIT: offset = (uint32_t *)&csl_packet->payload; offset += (csl_packet->cmd_buf_offset / sizeof(uint32_t)); cmd_desc = (struct cam_cmd_buf_desc *)(offset); if ((csl_packet->num_cmd_buf < 2) && (csl_packet->num_cmd_buf > 3)) { CAM_ERR(CAM_OIS, "wrong cmd Buffer count: %d", csl_packet->num_cmd_buf); return -EINVAL; } rc = cam_mem_get_cpu_buf(cmd_desc[0].mem_handle, (uint64_t *)&generic_ptr, &len_of_buff); if (rc < 0) { CAM_ERR(CAM_OIS, "Failed to get cpu buf"); return rc; } cmd_buf = (uint32_t *)generic_ptr; cmd_buf += cmd_desc->offset / sizeof(uint32_t); rc = cam_ois_slaveInfo_pkt_parser(o_ctrl, cmd_buf); if (rc < 0) { CAM_ERR(CAM_OIS, "Failed in parsing the pkt"); return rc; } cmd_buf += (sizeof(struct cam_cmd_i2c_info)/sizeof(uint32_t)); i2c_reg_settings = &(o_ctrl->i2c_init_data); i2c_reg_settings->is_settings_valid = 1; i2c_reg_settings->request_id = 0; rc = cam_sensor_i2c_pkt_parser(i2c_reg_settings, &cmd_desc[1], 1); if (rc < 0) { CAM_ERR(CAM_OIS, "OIS pkt parsing failed: %d", rc); return rc; } if (o_ctrl->is_ois_calib) { i2c_reg_settings = &(o_ctrl->i2c_calib_data); i2c_reg_settings->is_settings_valid = 1; i2c_reg_settings->request_id = 0; rc = cam_sensor_i2c_pkt_parser(i2c_reg_settings, &cmd_desc[2], 1); if (rc < 0) { CAM_ERR(CAM_OIS, "OIS pkt parsing failed: %d", rc); return rc; } } break; case CAM_OIS_PACKET_OPCODE_OIS_CONTROL: offset = (uint32_t *)&csl_packet->payload; offset += (csl_packet->cmd_buf_offset / sizeof(uint32_t)); cmd_desc = (struct cam_cmd_buf_desc *)(offset); i2c_reg_settings = &(o_ctrl->i2c_mode_data); i2c_reg_settings->is_settings_valid = 1; i2c_reg_settings->request_id = 0; rc = cam_sensor_i2c_pkt_parser(i2c_reg_settings, cmd_desc, 1); if (rc < 0) { CAM_ERR(CAM_OIS, "OIS pkt parsing failed: %d", rc); return rc; } rc = cam_ois_apply_settings(o_ctrl, i2c_reg_settings); if (rc < 0) CAM_ERR(CAM_OIS, "Cannot apply mode settings"); break; default: break; } return rc; } /** * cam_ois_driver_cmd - Handle ois cmds * @e_ctrl: ctrl structure * @arg: Camera control command argument * * Returns success or failure */ int cam_ois_driver_cmd(struct cam_ois_ctrl_t *o_ctrl, void *arg) { int rc = 0; struct cam_ois_query_cap_t ois_cap = {0}; struct cam_control *cmd = (struct cam_control *)arg; if (!o_ctrl) { CAM_ERR(CAM_OIS, "e_ctrl is NULL"); return -EINVAL; } mutex_lock(&(o_ctrl->ois_mutex)); switch (cmd->op_code) { case CAM_QUERY_CAP: ois_cap.slot_info = o_ctrl->subdev_id; if (copy_to_user((void __user *) cmd->handle, &ois_cap, sizeof(struct cam_ois_query_cap_t))) { CAM_ERR(CAM_OIS, "Failed Copy to User"); return -EFAULT; goto release_mutex; } CAM_DBG(CAM_OIS, "ois_cap: ID: %d", ois_cap.slot_info); break; case CAM_ACQUIRE_DEV: rc = cam_ois_get_dev_handle(o_ctrl, arg); if (rc) { CAM_ERR(CAM_OIS, "Failed to acquire dev"); goto release_mutex; } break; case CAM_START_DEV: rc = cam_ois_power_up(o_ctrl); if (rc) { CAM_ERR(CAM_OIS, " OIS Power up failed"); goto release_mutex; } rc = camera_io_init(&o_ctrl->io_master_info); if (rc) { CAM_ERR(CAM_OIS, "cci_init failed"); goto pwr_dwn; } if (o_ctrl->ois_fw_flag) { rc = cam_ois_fw_download(o_ctrl); if (rc) { CAM_ERR(CAM_OIS, "Failed OIS FW Download"); goto pwr_dwn; } } rc = cam_ois_apply_settings(o_ctrl, &o_ctrl->i2c_init_data); if (rc < 0) { CAM_ERR(CAM_OIS, "Cannot apply Init settings"); goto pwr_dwn; } if (o_ctrl->is_ois_calib) { rc = cam_ois_apply_settings(o_ctrl, &o_ctrl->i2c_calib_data); if (rc) { CAM_ERR(CAM_OIS, "Cannot apply calib data"); goto pwr_dwn; } } break; case CAM_CONFIG_DEV: rc = cam_ois_pkt_parse(o_ctrl, arg); if (rc) { CAM_ERR(CAM_OIS, "Failed in ois pkt Parsing"); goto release_mutex; } break; case CAM_RELEASE_DEV: if (o_ctrl->bridge_intf.device_hdl == -1) { CAM_ERR(CAM_OIS, "link hdl: %d device hdl: %d", o_ctrl->bridge_intf.device_hdl, o_ctrl->bridge_intf.link_hdl); rc = -EINVAL; goto release_mutex; } rc = cam_destroy_device_hdl(o_ctrl->bridge_intf.device_hdl); if (rc < 0) CAM_ERR(CAM_OIS, "destroying the device hdl"); o_ctrl->bridge_intf.device_hdl = -1; o_ctrl->bridge_intf.link_hdl = -1; o_ctrl->bridge_intf.session_hdl = -1; break; case CAM_STOP_DEV: rc = camera_io_release(&o_ctrl->io_master_info); if (rc < 0) CAM_ERR(CAM_OIS, "Failed in releasing CCI"); rc = cam_ois_power_down(o_ctrl); if (rc < 0) { CAM_ERR(CAM_OIS, "OIS Power down failed"); goto release_mutex; } break; default: CAM_ERR(CAM_OIS, "invalid opcode"); goto release_mutex; } pwr_dwn: cam_ois_power_down(o_ctrl); release_mutex: mutex_unlock(&(o_ctrl->ois_mutex)); return rc; }
drivers/media/platform/msm/camera/cam_sensor_module/cam_ois/cam_ois_core.h 0 → 100644 +20 −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 _CAM_OIS_CORE_H_ #define _CAM_OIS_CORE_H_ #include "cam_ois_dev.h" int cam_ois_driver_cmd(struct cam_ois_ctrl_t *e_ctrl, void *arg); #endif /* _CAM_OIS_CORE_H_ */