diff --git a/drivers/cam_sensor_module/cam_csiphy/cam_csiphy_core.c b/drivers/cam_sensor_module/cam_csiphy/cam_csiphy_core.c index 01c54cdd6c..f4d60b937c 100644 --- a/drivers/cam_sensor_module/cam_csiphy/cam_csiphy_core.c +++ b/drivers/cam_sensor_module/cam_csiphy/cam_csiphy_core.c @@ -34,17 +34,21 @@ int32_t cam_csiphy_get_instance_offset( struct csiphy_device *csiphy_dev, int32_t dev_handle) { - int32_t i; + int32_t i = 0; - if (csiphy_dev->acquire_count > - CSIPHY_MAX_INSTANCES) { - CAM_ERR(CAM_CSIPHY, "Invalid acquire count"); + if ((csiphy_dev->acquire_count > + csiphy_dev->session_max_device_support) || + (csiphy_dev->acquire_count < 0)) { + CAM_ERR(CAM_CSIPHY, + "Invalid acquire count: %d, Max supported device for session: %u", + csiphy_dev->acquire_count, + csiphy_dev->session_max_device_support); return -EINVAL; } for (i = 0; i < csiphy_dev->acquire_count; i++) { if (dev_handle == - csiphy_dev->bridge_intf.device_hdl[i]) + csiphy_dev->csiphy_info[i].hdl_data.device_hdl) break; } @@ -84,83 +88,138 @@ void cam_csiphy_reset(struct csiphy_device *csiphy_dev) } } -int32_t cam_csiphy_update_secure_info( - struct csiphy_device *csiphy_dev, - struct cam_csiphy_info *cam_cmd_csiphy_info, - struct cam_config_dev_cmd *cfg_dev) +static int32_t cam_csiphy_update_secure_info( + struct csiphy_device *csiphy_dev, int32_t index) { - uint32_t clock_lane, adj_lane_mask, temp, phy_mask_len; - int32_t offset; + uint32_t adj_lane_mask = 0; + uint16_t lane_assign = 0; + uint32_t phy_mask_len = 0; + uint8_t lane_cnt = 0; - if (csiphy_dev->acquire_count >= - CSIPHY_MAX_INSTANCES) { - CAM_ERR(CAM_CSIPHY, "Invalid acquire count"); - return -EINVAL; + lane_assign = csiphy_dev->csiphy_info[index].lane_assign; + lane_cnt = csiphy_dev->csiphy_info[index].lane_cnt; + + while (lane_cnt--) { + if ((lane_assign & 0xF) == 0x0) + adj_lane_mask |= 0x1; + else + adj_lane_mask |= (1 << (lane_assign & 0xF)); + + lane_assign >>= 4; } - offset = cam_csiphy_get_instance_offset(csiphy_dev, - cfg_dev->dev_handle); - if (offset < 0 || offset >= CSIPHY_MAX_INSTANCES) { - CAM_ERR(CAM_CSIPHY, "Invalid offset"); - return -EINVAL; - } - - if (cam_cmd_csiphy_info->combo_mode) - clock_lane = - csiphy_dev->ctrl_reg->csiphy_reg.csiphy_2ph_combo_ck_ln; - else - clock_lane = - csiphy_dev->ctrl_reg->csiphy_reg.csiphy_2ph_clock_lane; - - adj_lane_mask = cam_cmd_csiphy_info->lane_mask & LANE_MASK_2PH & - ~clock_lane; - temp = adj_lane_mask & (clock_lane - 1); - adj_lane_mask = - ((adj_lane_mask & (~(clock_lane - 1))) >> 1) | temp; - - if (cam_cmd_csiphy_info->csiphy_3phase) - adj_lane_mask = cam_cmd_csiphy_info->lane_mask & LANE_MASK_3PH; - - csiphy_dev->csiphy_info.secure_mode[offset] = 1; - if (csiphy_dev->hw_version == CSIPHY_VERSION_V201) { phy_mask_len = CAM_CSIPHY_MAX_DPHY_LANES + CAM_CSIPHY_MAX_CPHY_LANES + 1; } else if (csiphy_dev->hw_version == CSIPHY_VERSION_V121) { phy_mask_len = (csiphy_dev->soc_info.index < MAX_PHY_MSK_PER_REG) ? - CAM_CSIPHY_MAX_DPHY_LANES + CAM_CSIPHY_MAX_CPHY_LANES : - CAM_CSIPHY_MAX_DPHY_LANES + - CAM_CSIPHY_MAX_CPHY_LANES + 1; + (CAM_CSIPHY_MAX_DPHY_LANES + CAM_CSIPHY_MAX_CPHY_LANES) + : (CAM_CSIPHY_MAX_DPHY_LANES + + CAM_CSIPHY_MAX_CPHY_LANES + 1); } else { phy_mask_len = CAM_CSIPHY_MAX_DPHY_LANES + CAM_CSIPHY_MAX_CPHY_LANES; } if (csiphy_dev->soc_info.index < MAX_PHY_MSK_PER_REG) { - csiphy_dev->csiphy_cpas_cp_reg_mask[offset] = - ((uint64_t)adj_lane_mask) << - (csiphy_dev->soc_info.index * phy_mask_len + - (!cam_cmd_csiphy_info->csiphy_3phase) * + csiphy_dev->csiphy_info[index].csiphy_cpas_cp_reg_mask = + adj_lane_mask << + ((csiphy_dev->soc_info.index * phy_mask_len) + + (!csiphy_dev->csiphy_info[index].csiphy_3phase) * (CAM_CSIPHY_MAX_CPHY_LANES)); } else { - csiphy_dev->csiphy_cpas_cp_reg_mask[offset] = + csiphy_dev->csiphy_info[index].csiphy_cpas_cp_reg_mask = ((uint64_t)adj_lane_mask) << ((csiphy_dev->soc_info.index - MAX_PHY_MSK_PER_REG) * phy_mask_len + SEC_LANE_CP_REG_LEN + - (!cam_cmd_csiphy_info->csiphy_3phase) * + (!csiphy_dev->csiphy_info[index].csiphy_3phase) * (CAM_CSIPHY_MAX_CPHY_LANES)); } + CAM_DBG(CAM_CSIPHY, "csi phy idx:%d, cp_reg_mask:0x%lx", csiphy_dev->soc_info.index, - csiphy_dev->csiphy_cpas_cp_reg_mask[offset]); + csiphy_dev->csiphy_info[index].csiphy_cpas_cp_reg_mask); + return 0; } +static int cam_csiphy_get_lane_enable( + struct csiphy_device *csiphy, int index, uint32_t *lane_enable) +{ + uint32_t lane_select = 0; + uint16_t lane_assign = csiphy->csiphy_info[index].lane_assign; + uint8_t lane_cnt = csiphy->csiphy_info[index].lane_cnt; + int rc = 0; + + while (lane_cnt--) { + if (csiphy->csiphy_info[index].csiphy_3phase) { + switch (lane_assign & 0xF) { + case 0x0: + lane_select |= CPHY_LANE_0; + break; + case 0x1: + lane_select |= CPHY_LANE_1; + break; + case 0x2: + lane_select |= CPHY_LANE_2; + break; + default: + CAM_ERR(CAM_CSIPHY, + "Wrong lane configuration for CPHY : %d", + lane_assign); + *lane_enable = 0; + return -EINVAL; + } + } else { + switch (lane_assign & 0xF) { + case 0x0: + lane_select |= DPHY_LANE_0; + lane_select |= DPHY_CLK_LN; + break; + case 0x1: + lane_select |= DPHY_LANE_1; + lane_select |= DPHY_CLK_LN; + break; + case 0x2: + lane_select |= DPHY_LANE_2; + if (csiphy->combo_mode) + lane_select |= DPHY_LANE_3; + else + lane_select |= DPHY_CLK_LN; + break; + case 0x3: + if (csiphy->combo_mode) { + CAM_ERR(CAM_CSIPHY, + "Wrong lane configuration for DPHYCombo: %d", + lane_assign); + *lane_enable = 0; + return -EINVAL; + } + lane_select |= DPHY_LANE_3; + lane_select |= DPHY_CLK_LN; + break; + default: + CAM_ERR(CAM_CSIPHY, + "Wrong lane configuration for DPHY: %d", + lane_assign); + *lane_enable = 0; + return -EINVAL; + } + } + lane_assign >>= 4; + } + + CAM_DBG(CAM_CSIPHY, "Lane_enable: 0x%x", lane_enable); + *lane_enable = lane_select; + + return rc; +} + int32_t cam_cmd_buf_parser(struct csiphy_device *csiphy_dev, struct cam_config_dev_cmd *cfg_dev) { - int32_t rc = 0; + int rc = 0; uintptr_t generic_ptr; uintptr_t generic_pkt_ptr; struct cam_packet *csl_packet = NULL; @@ -169,6 +228,8 @@ int32_t cam_cmd_buf_parser(struct csiphy_device *csiphy_dev, struct cam_csiphy_info *cam_cmd_csiphy_info = NULL; size_t len; size_t remain_len; + int index; + uint32_t lane_enable = 0; if (!cfg_dev || !csiphy_dev) { CAM_ERR(CAM_CSIPHY, "Invalid Args"); @@ -227,46 +288,73 @@ int32_t cam_cmd_buf_parser(struct csiphy_device *csiphy_dev, cmd_buf += cmd_desc->offset / 4; cam_cmd_csiphy_info = (struct cam_csiphy_info *)cmd_buf; - csiphy_dev->config_count++; - csiphy_dev->csiphy_info.lane_cnt += cam_cmd_csiphy_info->lane_cnt; - csiphy_dev->csiphy_info.lane_mask |= cam_cmd_csiphy_info->lane_mask; - csiphy_dev->csiphy_info.csiphy_3phase = - cam_cmd_csiphy_info->csiphy_3phase; - csiphy_dev->csiphy_info.combo_mode |= cam_cmd_csiphy_info->combo_mode; - if (cam_cmd_csiphy_info->combo_mode == 1) { - csiphy_dev->csiphy_info.settle_time_combo_sensor = - cam_cmd_csiphy_info->settle_time; - csiphy_dev->csiphy_info.data_rate_combo_sensor = - cam_cmd_csiphy_info->data_rate; - } else { - csiphy_dev->csiphy_info.settle_time = - cam_cmd_csiphy_info->settle_time; - csiphy_dev->csiphy_info.data_rate = - cam_cmd_csiphy_info->data_rate; + index = cam_csiphy_get_instance_offset(csiphy_dev, cfg_dev->dev_handle); + if (index < 0 || index >= csiphy_dev->session_max_device_support) { + CAM_ERR(CAM_CSIPHY, "index in invalid: %d", index); + return -EINVAL; } + csiphy_dev->csiphy_info[index].lane_cnt = cam_cmd_csiphy_info->lane_cnt; + csiphy_dev->csiphy_info[index].lane_assign = + cam_cmd_csiphy_info->lane_assign; + + csiphy_dev->csiphy_info[index].settle_time = + cam_cmd_csiphy_info->settle_time; + csiphy_dev->csiphy_info[index].data_rate = + cam_cmd_csiphy_info->data_rate; + csiphy_dev->csiphy_info[index].secure_mode = + cam_cmd_csiphy_info->secure_mode; + + rc = cam_csiphy_get_lane_enable(csiphy_dev, index, &lane_enable); + if (rc) { + CAM_ERR(CAM_CSIPHY, "Wrong lane configuration: %d", + csiphy_dev->csiphy_info[index].lane_assign); + if ((csiphy_dev->combo_mode) || + (csiphy_dev->cphy_dphy_combo_mode)) { + CAM_DBG(CAM_CSIPHY, + "Resetting error to zero for other devices to configure"); + rc = 0; + } + lane_enable = 0; + csiphy_dev->csiphy_info[index].lane_enable = lane_enable; + goto reset_settings; + } + + csiphy_dev->csiphy_info[index].lane_enable = lane_enable; if (cam_cmd_csiphy_info->secure_mode == 1) cam_csiphy_update_secure_info(csiphy_dev, - cam_cmd_csiphy_info, cfg_dev); + index); + + csiphy_dev->config_count++; CAM_DBG(CAM_CSIPHY, - "phy version_%d, lane count:%d, mask:0x%x", + "phy version:%d, phy_idx: %d", csiphy_dev->hw_version, - csiphy_dev->csiphy_info.lane_cnt, - csiphy_dev->csiphy_info.lane_mask - ); + csiphy_dev->soc_info.index); CAM_DBG(CAM_CSIPHY, "3phase:%d, combo mode:%d, secure mode:%d", - csiphy_dev->csiphy_info.csiphy_3phase, - csiphy_dev->csiphy_info.combo_mode, - cam_cmd_csiphy_info->secure_mode - ); + csiphy_dev->csiphy_info[index].csiphy_3phase, + csiphy_dev->combo_mode, + cam_cmd_csiphy_info->secure_mode); CAM_DBG(CAM_CSIPHY, - "phy idx:%d, settle time:%d, datarate:%d", - csiphy_dev->soc_info.index, - csiphy_dev->csiphy_info.settle_time, - csiphy_dev->csiphy_info.data_rate); + "lane_cnt: 0x%x, lane_assign: 0x%x, lane_enable: 0x%x, settle time:%llu, datarate:%llu", + csiphy_dev->csiphy_info[index].lane_cnt, + csiphy_dev->csiphy_info[index].lane_assign, + csiphy_dev->csiphy_info[index].lane_enable, + csiphy_dev->csiphy_info[index].settle_time, + csiphy_dev->csiphy_info[index].data_rate); + + return rc; + +reset_settings: + csiphy_dev->csiphy_info[index].lane_cnt = 0; + csiphy_dev->csiphy_info[index].lane_assign = 0; + csiphy_dev->csiphy_info[index].lane_enable = 0; + csiphy_dev->csiphy_info[index].settle_time = 0; + csiphy_dev->csiphy_info[index].data_rate = 0; + csiphy_dev->csiphy_info[index].secure_mode = 0; + csiphy_dev->csiphy_info[index].hdl_data.device_hdl = -1; return rc; } @@ -284,7 +372,8 @@ void cam_csiphy_cphy_irq_config(struct csiphy_device *csiphy_dev) csiphy_dev->ctrl_reg->csiphy_irq_reg[i].reg_addr); } -void cam_csiphy_cphy_data_rate_config(struct csiphy_device *csiphy_device) +static void cam_csiphy_cphy_data_rate_config( + struct csiphy_device *csiphy_device, int32_t idx) { int i = 0, j = 0; uint64_t phy_data_rate = 0; @@ -300,7 +389,7 @@ void cam_csiphy_cphy_data_rate_config(struct csiphy_device *csiphy_device) return; } - phy_data_rate = csiphy_device->csiphy_info.data_rate; + phy_data_rate = csiphy_device->csiphy_info[idx].data_rate; csiphybase = csiphy_device->soc_info.reg_map[0].mem_base; settings_table = @@ -319,8 +408,8 @@ void cam_csiphy_cphy_data_rate_config(struct csiphy_device *csiphy_device) if (phy_data_rate > bandwidth) { CAM_DBG(CAM_CSIPHY, - "Skipping table [%d] %llu required: %llu", - i, bandwidth, phy_data_rate); + "Skipping table [%d] %llu required: %llu", + i, bandwidth, phy_data_rate); continue; } @@ -393,82 +482,124 @@ irqreturn_t cam_csiphy_irq(int irq_num, void *data) return IRQ_HANDLED; } -int32_t cam_csiphy_config_dev(struct csiphy_device *csiphy_dev) +int32_t cam_csiphy_config_dev(struct csiphy_device *csiphy_dev, + int32_t dev_handle) { int32_t rc = 0; - uint32_t lane_enable = 0, mask = 1, size = 0; - uint16_t lane_mask = 0, i = 0, cfg_size = 0, temp = 0; - uint8_t lane_cnt, lane_pos = 0; + uint32_t lane_enable = 0; + uint32_t size = 0; + uint16_t i = 0, cfg_size = 0; + uint16_t lane_assign = 0; + uint8_t lane_cnt; + int max_lanes = 0; uint16_t settle_cnt = 0; uint64_t intermediate_var; + uint8_t lane_pos = 0; + int index; void __iomem *csiphybase; struct csiphy_reg_t *csiphy_common_reg = NULL; struct csiphy_reg_t (*reg_array)[MAX_SETTINGS_PER_LANE]; - - lane_cnt = csiphy_dev->csiphy_info.lane_cnt; + bool is_3phase = false; csiphybase = csiphy_dev->soc_info.reg_map[0].mem_base; + CAM_DBG(CAM_CSIPHY, "ENTER"); if (!csiphybase) { CAM_ERR(CAM_CSIPHY, "csiphybase NULL"); return -EINVAL; } - if (!csiphy_dev->csiphy_info.csiphy_3phase) { - if (csiphy_dev->csiphy_info.combo_mode == 1) - reg_array = - csiphy_dev->ctrl_reg->csiphy_2ph_combo_mode_reg; - else - reg_array = - csiphy_dev->ctrl_reg->csiphy_2ph_reg; - csiphy_dev->num_irq_registers = 11; - cfg_size = - csiphy_dev->ctrl_reg->csiphy_reg.csiphy_2ph_config_array_size; + index = cam_csiphy_get_instance_offset(csiphy_dev, dev_handle); + if (index < 0 || index >= csiphy_dev->session_max_device_support) { + CAM_ERR(CAM_CSIPHY, "index is invalid: %d", index); + return -EINVAL; + } - lane_mask = csiphy_dev->csiphy_info.lane_mask & LANE_MASK_2PH; - for (i = 0; i < MAX_DPHY_DATA_LN; i++) { - if (mask == 0x2) { - if (lane_mask & mask) - lane_enable |= 0x80; - i--; - } else if (lane_mask & mask) { - lane_enable |= 0x1 << (i<<1); - } - mask <<= 1; - } - } else { - if (csiphy_dev->csiphy_info.combo_mode == 1) { - if (csiphy_dev->ctrl_reg->csiphy_2ph_3ph_mode_reg) - reg_array = - csiphy_dev->ctrl_reg->csiphy_2ph_3ph_mode_reg; - else { + CAM_DBG(CAM_CSIPHY, + "Index: %d: expected dev_hdl: 0x%x : derived dev_hdl: 0x%x", + index, dev_handle, + csiphy_dev->csiphy_info[index].hdl_data.device_hdl); + csiphy_dev->num_irq_registers = 11; + + if (csiphy_dev->csiphy_info[index].csiphy_3phase) + is_3phase = true; + + if (csiphy_dev->combo_mode) { + /* for CPHY(3Phase) or DPHY(2Phase) combo mode selection */ + if (is_3phase) { + /* CPHY combo mode */ + if (csiphy_dev->ctrl_reg->csiphy_3ph_combo_reg) { + reg_array = csiphy_dev->ctrl_reg + ->csiphy_3ph_combo_reg; + } else { + CAM_WARN(CAM_CSIPHY, + "CPHY combo mode reg settings not found"); reg_array = csiphy_dev->ctrl_reg->csiphy_3ph_reg; - CAM_ERR(CAM_CSIPHY, - "Unsupported configuration, Falling back to CPHY mode"); } - } else - reg_array = - csiphy_dev->ctrl_reg->csiphy_3ph_reg; - csiphy_dev->num_irq_registers = 11; - cfg_size = - csiphy_dev->ctrl_reg->csiphy_reg.csiphy_3ph_config_array_size; - - lane_mask = csiphy_dev->csiphy_info.lane_mask & LANE_MASK_3PH; - mask = lane_mask; - while (mask != 0) { - temp = (i << 1)+1; - lane_enable |= ((mask & 0x1) << temp); - mask >>= 1; - i++; + cfg_size = csiphy_dev->ctrl_reg->csiphy_reg + .csiphy_3ph_config_array_size; + max_lanes = CAM_CSIPHY_MAX_CPHY_LANES; + } else { + /* DPHY combo mode*/ + if (csiphy_dev->ctrl_reg->csiphy_2ph_combo_mode_reg) { + reg_array = csiphy_dev + ->ctrl_reg->csiphy_2ph_combo_mode_reg; + } else { + CAM_WARN(CAM_CSIPHY, + "DPHY combo mode reg settings not found"); + reg_array = csiphy_dev + ->ctrl_reg->csiphy_2ph_reg; + } + cfg_size = csiphy_dev->ctrl_reg->csiphy_reg + .csiphy_2ph_config_array_size; + max_lanes = MAX_LANES; + } + } else if (csiphy_dev->cphy_dphy_combo_mode) { + /* for CPHY and DPHY combo mode selection */ + if (csiphy_dev->ctrl_reg->csiphy_2ph_3ph_mode_reg) { + reg_array = csiphy_dev + ->ctrl_reg->csiphy_2ph_3ph_mode_reg; + cfg_size = csiphy_dev->ctrl_reg->csiphy_reg + .csiphy_2ph_3ph_config_array_size; + max_lanes = CAM_CSIPHY_MAX_CPHY_DPHY_COMBO_LN; + } else { + reg_array = csiphy_dev->ctrl_reg->csiphy_3ph_reg; + cfg_size = + csiphy_dev->ctrl_reg->csiphy_reg + .csiphy_3ph_config_array_size; + CAM_WARN(CAM_CSIPHY, + "Unsupported configuration, Falling back to CPHY mission mode"); + max_lanes = CAM_CSIPHY_MAX_CPHY_LANES; + } + } else { + /* for CPHY(3Phase) or DPHY(2Phase) Non combe mode selection */ + if (is_3phase) { + CAM_DBG(CAM_CSIPHY, + "3phase Non combo mode reg array selected"); + reg_array = csiphy_dev->ctrl_reg->csiphy_3ph_reg; + max_lanes = CAM_CSIPHY_MAX_CPHY_LANES; + cfg_size = csiphy_dev->ctrl_reg->csiphy_reg + .csiphy_3ph_config_array_size; + } else { + CAM_DBG(CAM_CSIPHY, + "2PHASE Non combo mode reg array selected"); + reg_array = csiphy_dev->ctrl_reg->csiphy_2ph_reg; + cfg_size = csiphy_dev->ctrl_reg->csiphy_reg + .csiphy_2ph_config_array_size; + max_lanes = MAX_LANES; } } - size = csiphy_dev->ctrl_reg->csiphy_reg.csiphy_common_array_size; + lane_cnt = csiphy_dev->csiphy_info[index].lane_cnt; + lane_assign = csiphy_dev->csiphy_info[index].lane_assign; + lane_enable = csiphy_dev->csiphy_info[index].lane_enable; + size = csiphy_dev->ctrl_reg->csiphy_reg.csiphy_common_array_size; for (i = 0; i < size; i++) { csiphy_common_reg = &csiphy_dev->ctrl_reg->csiphy_common_reg[i]; switch (csiphy_common_reg->csiphy_param_type) { case CSIPHY_LANE_ENABLE: + CAM_DBG(CAM_CSIPHY, "LANE_ENABLE: 0x%x", lane_enable); cam_io_w_mb(lane_enable, csiphybase + csiphy_common_reg->reg_addr); break; @@ -477,14 +608,14 @@ int32_t cam_csiphy_config_dev(struct csiphy_device *csiphy_dev) csiphybase + csiphy_common_reg->reg_addr); break; case CSIPHY_2PH_REGS: - if (!csiphy_dev->csiphy_info.csiphy_3phase) { + if (!is_3phase) { cam_io_w_mb(csiphy_common_reg->reg_data, csiphybase + csiphy_common_reg->reg_addr); } break; case CSIPHY_3PH_REGS: - if (csiphy_dev->csiphy_info.csiphy_3phase) { + if (is_3phase) { cam_io_w_mb(csiphy_common_reg->reg_data, csiphybase + csiphy_common_reg->reg_addr); @@ -498,23 +629,12 @@ int32_t cam_csiphy_config_dev(struct csiphy_device *csiphy_dev) csiphy_common_reg->delay + 5); } - while (lane_mask) { - if (!(lane_mask & 0x1)) { - lane_pos++; - lane_mask >>= 1; - continue; - } + intermediate_var = csiphy_dev->csiphy_info[index].settle_time; + do_div(intermediate_var, 200000000); + settle_cnt = intermediate_var; - intermediate_var = csiphy_dev->csiphy_info.settle_time; - do_div(intermediate_var, 200000000); - settle_cnt = intermediate_var; - if (csiphy_dev->csiphy_info.combo_mode == 1 && - (lane_pos >= 3)) { - intermediate_var = - csiphy_dev->csiphy_info.settle_time_combo_sensor; - do_div(intermediate_var, 200000000); - settle_cnt = intermediate_var; - } + for (lane_pos = 0; lane_pos < max_lanes; lane_pos++) { + CAM_DBG(CAM_CSIPHY, "lane_pos: %d is configuring", lane_pos); for (i = 0; i < cfg_size; i++) { switch (reg_array[lane_pos][i].csiphy_param_type) { case CSIPHY_LANE_ENABLE: @@ -546,15 +666,14 @@ int32_t cam_csiphy_config_dev(struct csiphy_device *csiphy_dev) reg_array[lane_pos][i].delay + 5); } } - lane_mask >>= 1; - lane_pos++; } - if (csiphy_dev->csiphy_info.csiphy_3phase) - cam_csiphy_cphy_data_rate_config(csiphy_dev); + if (csiphy_dev->csiphy_info[index].csiphy_3phase) + cam_csiphy_cphy_data_rate_config(csiphy_dev, index); cam_csiphy_cphy_irq_config(csiphy_dev); + CAM_DBG(CAM_CSIPHY, "EXIT"); return rc; } @@ -566,19 +685,31 @@ void cam_csiphy_shutdown(struct csiphy_device *csiphy_dev) if (csiphy_dev->csiphy_state == CAM_CSIPHY_INIT) return; + if (!csiphy_dev->acquire_count) + return; + + if (csiphy_dev->acquire_count >= CSIPHY_MAX_INSTANCES_PER_PHY) { + CAM_WARN(CAM_CSIPHY, "acquire count is invalid: %u", + csiphy_dev->acquire_count); + csiphy_dev->acquire_count = + CSIPHY_MAX_INSTANCES_PER_PHY; + } + if (csiphy_dev->csiphy_state == CAM_CSIPHY_START) { soc_info = &csiphy_dev->soc_info; for (i = 0; i < csiphy_dev->acquire_count; i++) { - if (csiphy_dev->csiphy_info.secure_mode[i]) + if (csiphy_dev->csiphy_info[i].secure_mode) cam_csiphy_notify_secure_mode( csiphy_dev, CAM_SECURE_MODE_NON_SECURE, i); - csiphy_dev->csiphy_info.secure_mode[i] = + csiphy_dev->csiphy_info[i].secure_mode = CAM_SECURE_MODE_NON_SECURE; - csiphy_dev->csiphy_cpas_cp_reg_mask[i] = 0; + csiphy_dev->csiphy_info[i].csiphy_cpas_cp_reg_mask = 0; + csiphy_dev->csiphy_info[i].settle_time = 0; + csiphy_dev->csiphy_info[i].data_rate = 0; } cam_csiphy_reset(csiphy_dev); @@ -589,22 +720,18 @@ void cam_csiphy_shutdown(struct csiphy_device *csiphy_dev) } if (csiphy_dev->csiphy_state == CAM_CSIPHY_ACQUIRE) { - if (csiphy_dev->bridge_intf.device_hdl[0] != -1) - cam_destroy_device_hdl( - csiphy_dev->bridge_intf.device_hdl[0]); - if (csiphy_dev->bridge_intf.device_hdl[1] != -1) - cam_destroy_device_hdl( - csiphy_dev->bridge_intf.device_hdl[1]); - csiphy_dev->bridge_intf.device_hdl[0] = -1; - csiphy_dev->bridge_intf.device_hdl[1] = -1; - csiphy_dev->bridge_intf.link_hdl[0] = -1; - csiphy_dev->bridge_intf.link_hdl[1] = -1; - csiphy_dev->bridge_intf.session_hdl[0] = -1; - csiphy_dev->bridge_intf.session_hdl[1] = -1; + for (i = 0; i < csiphy_dev->acquire_count; i++) { + if (csiphy_dev->csiphy_info[i].hdl_data.device_hdl + != -1) + cam_destroy_device_hdl( + csiphy_dev->csiphy_info[i] + .hdl_data.device_hdl); + csiphy_dev->csiphy_info[i].hdl_data.device_hdl = -1; + csiphy_dev->csiphy_info[i].hdl_data.session_hdl = -1; + } } csiphy_dev->ref_count = 0; - csiphy_dev->is_acquired_dev_combo_mode = 0; csiphy_dev->acquire_count = 0; csiphy_dev->start_dev_count = 0; csiphy_dev->csiphy_state = CAM_CSIPHY_INIT; @@ -615,6 +742,7 @@ static int32_t cam_csiphy_external_cmd(struct csiphy_device *csiphy_dev, { struct cam_csiphy_info cam_cmd_csiphy_info; int32_t rc = 0; + int32_t index = -1; if (copy_from_user(&cam_cmd_csiphy_info, u64_to_user_ptr(p_submit_cmd->packet_handle), @@ -622,37 +750,87 @@ static int32_t cam_csiphy_external_cmd(struct csiphy_device *csiphy_dev, CAM_ERR(CAM_CSIPHY, "failed to copy cam_csiphy_info\n"); rc = -EFAULT; } else { - csiphy_dev->csiphy_info.lane_cnt = + index = cam_csiphy_get_instance_offset(csiphy_dev, + p_submit_cmd->dev_handle); + if (index < 0 || + index >= csiphy_dev->session_max_device_support) { + CAM_ERR(CAM_CSIPHY, "index is invalid: %d", index); + return -EINVAL; + } + + csiphy_dev->csiphy_info[index].lane_cnt = cam_cmd_csiphy_info.lane_cnt; - csiphy_dev->csiphy_info.lane_cnt = - cam_cmd_csiphy_info.lane_cnt; - csiphy_dev->csiphy_info.lane_mask = - cam_cmd_csiphy_info.lane_mask; - csiphy_dev->csiphy_info.csiphy_3phase = - cam_cmd_csiphy_info.csiphy_3phase; - csiphy_dev->csiphy_info.combo_mode = - cam_cmd_csiphy_info.combo_mode; - csiphy_dev->csiphy_info.settle_time = + csiphy_dev->csiphy_info[index].lane_assign = + cam_cmd_csiphy_info.lane_assign; + csiphy_dev->csiphy_info[index].settle_time = cam_cmd_csiphy_info.settle_time; - csiphy_dev->csiphy_info.data_rate = + csiphy_dev->csiphy_info[index].data_rate = cam_cmd_csiphy_info.data_rate; CAM_DBG(CAM_CSIPHY, - "%s CONFIG_DEV_EXT settle_time= %lld lane_cnt=%d lane_mask=0x%x", + "%s CONFIG_DEV_EXT settle_time= %lld lane_cnt=%d", __func__, - csiphy_dev->csiphy_info.settle_time, - csiphy_dev->csiphy_info.lane_cnt, - csiphy_dev->csiphy_info.lane_mask); + csiphy_dev->csiphy_info[index].settle_time, + csiphy_dev->csiphy_info[index].lane_cnt); } return rc; } +static int cam_csiphy_update_lane( + struct csiphy_device *csiphy, int index, bool enable) +{ + int i = 0; + uint32_t lane_enable = 0; + uint32_t size = 0; + uint16_t lane_assign; + void __iomem *base_address; + struct csiphy_reg_t *csiphy_common_reg = NULL; + + base_address = csiphy->soc_info.reg_map[0].mem_base; + size = csiphy->ctrl_reg->csiphy_reg.csiphy_common_array_size; + + for (i = 0; i < size; i++) { + csiphy_common_reg = &csiphy->ctrl_reg->csiphy_common_reg[i]; + switch (csiphy_common_reg->csiphy_param_type) { + case CSIPHY_LANE_ENABLE: + CAM_DBG(CAM_CSIPHY, "LANE_ENABLE: %d", lane_enable); + lane_enable = cam_io_r(base_address + + csiphy_common_reg->reg_addr); + break; + } + } + + lane_assign = csiphy->csiphy_info[index].lane_assign; + + if (enable) + lane_enable |= csiphy->csiphy_info[index].lane_enable; + else + lane_enable &= ~csiphy->csiphy_info[index].lane_enable; + + CAM_DBG(CAM_CSIPHY, "lane_assign: 0x%x, lane_enable: 0x%x", + lane_assign, lane_enable); + for (i = 0; i < size; i++) { + csiphy_common_reg = &csiphy->ctrl_reg->csiphy_common_reg[i]; + switch (csiphy_common_reg->csiphy_param_type) { + case CSIPHY_LANE_ENABLE: + CAM_DBG(CAM_CSIPHY, "LANE_ENABLE: %d", lane_enable); + cam_io_w_mb(lane_enable, + base_address + csiphy_common_reg->reg_addr); + if (csiphy_common_reg->delay) + usleep_range(csiphy_common_reg->delay, + csiphy_common_reg->delay + 5); + break; + } + } + + return 0; +} + int32_t cam_csiphy_core_cfg(void *phy_dev, void *arg) { struct csiphy_device *csiphy_dev = (struct csiphy_device *)phy_dev; - struct csiphy_intf_params *bridge_intf = NULL; struct cam_control *cmd = (struct cam_control *)arg; int32_t rc = 0; @@ -673,13 +851,28 @@ int32_t cam_csiphy_core_cfg(void *phy_dev, case CAM_ACQUIRE_DEV: { struct cam_sensor_acquire_dev csiphy_acq_dev; struct cam_csiphy_acquire_dev_info csiphy_acq_params; - + int index; struct cam_create_dev_hdl bridge_params; - if (csiphy_dev->csiphy_state == CAM_CSIPHY_START) { + CAM_DBG(CAM_CSIPHY, "ACQUIRE_CNT: %d COMBO_MODE: %d", + csiphy_dev->acquire_count, + csiphy_dev->combo_mode); + if ((csiphy_dev->csiphy_state == CAM_CSIPHY_START) && + (csiphy_dev->combo_mode == 0) && + (csiphy_dev->acquire_count > 0)) { CAM_ERR(CAM_CSIPHY, - "Not in right state to acquire : %d", - csiphy_dev->csiphy_state); + "NonComboMode does not support multiple acquire: Acquire_count: %d", + csiphy_dev->acquire_count); + rc = -EINVAL; + goto release_mutex; + } + + if ((csiphy_dev->acquire_count) && + (csiphy_dev->acquire_count >= + csiphy_dev->session_max_device_support)) { + CAM_ERR(CAM_CSIPHY, + "Max acquires are allowed in combo mode: %d", + csiphy_dev->session_max_device_support); rc = -EINVAL; goto release_mutex; } @@ -702,32 +895,37 @@ int32_t cam_csiphy_core_cfg(void *phy_dev, goto release_mutex; } - if (csiphy_dev->acquire_count == 2) { + if (csiphy_acq_params.combo_mode && + csiphy_acq_params.cphy_dphy_combo_mode) { CAM_ERR(CAM_CSIPHY, - "CSIPHY device do not allow more than 2 acquires"); + "Cannot support both Combo_mode and cphy_dphy_combo_mode"); rc = -EINVAL; goto release_mutex; } - if ((csiphy_acq_params.combo_mode == 1) && - (csiphy_dev->is_acquired_dev_combo_mode == 1)) { - CAM_ERR(CAM_CSIPHY, - "Multiple Combo Acq are not allowed: cm: %d, acm: %d", - csiphy_acq_params.combo_mode, - csiphy_dev->is_acquired_dev_combo_mode); - rc = -EINVAL; - goto release_mutex; + if (csiphy_acq_params.combo_mode == 1) { + CAM_DBG(CAM_CSIPHY, "combo mode stream detected"); + csiphy_dev->combo_mode = 1; + if (csiphy_acq_params.csiphy_3phase) + csiphy_dev->session_max_device_support = + CSIPHY_MAX_INSTANCES_PER_PHY; + else + csiphy_dev->session_max_device_support = + CSIPHY_MAX_INSTANCES_PER_PHY - 1; } - if ((csiphy_acq_params.combo_mode != 1) && - (csiphy_dev->is_acquired_dev_combo_mode != 1) && - (csiphy_dev->acquire_count == 1)) { - CAM_ERR(CAM_CSIPHY, - "Multiple Acquires are not allowed cm: %d acm: %d", - csiphy_acq_params.combo_mode, - csiphy_dev->is_acquired_dev_combo_mode); - rc = -EINVAL; - goto release_mutex; + if (csiphy_acq_params.cphy_dphy_combo_mode == 1) { + CAM_DBG(CAM_CSIPHY, + "cphy_dphy_combo_mode stream detected"); + csiphy_dev->cphy_dphy_combo_mode = 1; + csiphy_dev->session_max_device_support = + CSIPHY_MAX_INSTANCES_PER_PHY - 1; + } + + if (!csiphy_acq_params.combo_mode && + !csiphy_acq_params.cphy_dphy_combo_mode) { + CAM_DBG(CAM_CSIPHY, "Non Combo Mode stream"); + csiphy_dev->session_max_device_support = 1; } bridge_params.ops = NULL; @@ -735,22 +933,19 @@ int32_t cam_csiphy_core_cfg(void *phy_dev, bridge_params.v4l2_sub_dev_flag = 0; bridge_params.media_entity_flag = 0; bridge_params.priv = csiphy_dev; - - if (csiphy_acq_params.combo_mode >= 2) { - CAM_ERR(CAM_CSIPHY, "Invalid combo_mode %d", - csiphy_acq_params.combo_mode); - rc = -EINVAL; - goto release_mutex; - } - + index = csiphy_dev->acquire_count; csiphy_acq_dev.device_handle = cam_create_device_hdl(&bridge_params); - bridge_intf = &csiphy_dev->bridge_intf; - bridge_intf->device_hdl[csiphy_acq_params.combo_mode] - = csiphy_acq_dev.device_handle; - bridge_intf->session_hdl[csiphy_acq_params.combo_mode] = + csiphy_dev->csiphy_info[index].hdl_data.device_hdl = + csiphy_acq_dev.device_handle; + csiphy_dev->csiphy_info[index].hdl_data.session_hdl = csiphy_acq_dev.session_handle; + csiphy_dev->csiphy_info[index].csiphy_3phase = + csiphy_acq_params.csiphy_3phase; + CAM_DBG(CAM_CSIPHY, "Add dev_handle:0x%x at index: %d ", + csiphy_dev->csiphy_info[index].hdl_data.device_hdl, + index); if (copy_to_user(u64_to_user_ptr(cmd->handle), &csiphy_acq_dev, sizeof(struct cam_sensor_acquire_dev))) { @@ -758,11 +953,12 @@ int32_t cam_csiphy_core_cfg(void *phy_dev, rc = -EINVAL; goto release_mutex; } - if (csiphy_acq_params.combo_mode == 1) - csiphy_dev->is_acquired_dev_combo_mode = 1; csiphy_dev->acquire_count++; - csiphy_dev->csiphy_state = CAM_CSIPHY_ACQUIRE; + CAM_DBG(CAM_CSIPHY, "ACQUIRE_CNT: %d", + csiphy_dev->acquire_count); + if (csiphy_dev->csiphy_state == CAM_CSIPHY_INIT) + csiphy_dev->csiphy_state = CAM_CSIPHY_ACQUIRE; } break; case CAM_QUERY_CAP: { @@ -788,8 +984,7 @@ int32_t cam_csiphy_core_cfg(void *phy_dev, goto release_mutex; } - if ((csiphy_dev->csiphy_state != CAM_CSIPHY_START) || - !csiphy_dev->start_dev_count) { + if (csiphy_dev->csiphy_state != CAM_CSIPHY_START) { CAM_ERR(CAM_CSIPHY, "Not in right state to stop : %d", csiphy_dev->csiphy_state); goto release_mutex; @@ -797,35 +992,44 @@ int32_t cam_csiphy_core_cfg(void *phy_dev, offset = cam_csiphy_get_instance_offset(csiphy_dev, config.dev_handle); - if (offset < 0 || offset >= CSIPHY_MAX_INSTANCES) { - CAM_ERR(CAM_CSIPHY, "Invalid offset"); + if (offset < 0 || + offset >= csiphy_dev->session_max_device_support) { + CAM_ERR(CAM_CSIPHY, "Index is invalid: %d", offset); goto release_mutex; } + CAM_INFO(CAM_CSIPHY, + "STOP_DEV: CSIPHY_IDX: %d, Device_slot: %d, Datarate: %llu, Settletime: %llu", + csiphy_dev->soc_info.index, offset, + csiphy_dev->csiphy_info[offset].data_rate, + csiphy_dev->csiphy_info[offset].settle_time); + if (--csiphy_dev->start_dev_count) { CAM_DBG(CAM_CSIPHY, "Stop Dev ref Cnt: %d", csiphy_dev->start_dev_count); - if (csiphy_dev->csiphy_info.secure_mode[offset]) + if (csiphy_dev->csiphy_info[offset].secure_mode) cam_csiphy_notify_secure_mode( csiphy_dev, CAM_SECURE_MODE_NON_SECURE, offset); - csiphy_dev->csiphy_info.secure_mode[offset] = + csiphy_dev->csiphy_info[offset].secure_mode = CAM_SECURE_MODE_NON_SECURE; - csiphy_dev->csiphy_cpas_cp_reg_mask[offset] = 0; + csiphy_dev->csiphy_info[offset].csiphy_cpas_cp_reg_mask + = 0; + cam_csiphy_update_lane(csiphy_dev, offset, false); goto release_mutex; } - if (csiphy_dev->csiphy_info.secure_mode[offset]) + if (csiphy_dev->csiphy_info[offset].secure_mode) cam_csiphy_notify_secure_mode( csiphy_dev, CAM_SECURE_MODE_NON_SECURE, offset); - csiphy_dev->csiphy_info.secure_mode[offset] = + csiphy_dev->csiphy_info[offset].secure_mode = CAM_SECURE_MODE_NON_SECURE; - csiphy_dev->csiphy_cpas_cp_reg_mask[offset] = 0x0; + csiphy_dev->csiphy_info[offset].csiphy_cpas_cp_reg_mask = 0x0; rc = cam_csiphy_disable_hw(csiphy_dev); if (rc < 0) @@ -835,6 +1039,7 @@ int32_t cam_csiphy_core_cfg(void *phy_dev, if (rc < 0) CAM_ERR(CAM_CSIPHY, "de-voting CPAS: %d", rc); + CAM_DBG(CAM_CSIPHY, "All PHY devices stopped"); csiphy_dev->csiphy_state = CAM_CSIPHY_ACQUIRE; } break; @@ -857,17 +1062,18 @@ int32_t cam_csiphy_core_cfg(void *phy_dev, offset = cam_csiphy_get_instance_offset(csiphy_dev, release.dev_handle); - if (offset < 0 || offset >= CSIPHY_MAX_INSTANCES) { - CAM_ERR(CAM_CSIPHY, "Invalid offset"); + if (offset < 0 || + offset >= csiphy_dev->session_max_device_support) { + CAM_ERR(CAM_CSIPHY, "index is invalid: %d", offset); goto release_mutex; } - if (csiphy_dev->csiphy_info.secure_mode[offset]) + if (csiphy_dev->csiphy_info[offset].secure_mode) cam_csiphy_notify_secure_mode( csiphy_dev, CAM_SECURE_MODE_NON_SECURE, offset); - csiphy_dev->csiphy_info.secure_mode[offset] = + csiphy_dev->csiphy_info[offset].secure_mode = CAM_SECURE_MODE_NON_SECURE; csiphy_dev->csiphy_cpas_cp_reg_mask[offset] = 0x0; @@ -875,32 +1081,29 @@ int32_t cam_csiphy_core_cfg(void *phy_dev, rc = cam_destroy_device_hdl(release.dev_handle); if (rc < 0) CAM_ERR(CAM_CSIPHY, "destroying the device hdl"); - if (release.dev_handle == - csiphy_dev->bridge_intf.device_hdl[0]) { - csiphy_dev->bridge_intf.device_hdl[0] = -1; - csiphy_dev->bridge_intf.link_hdl[0] = -1; - csiphy_dev->bridge_intf.session_hdl[0] = -1; - } else { - csiphy_dev->bridge_intf.device_hdl[1] = -1; - csiphy_dev->bridge_intf.link_hdl[1] = -1; - csiphy_dev->bridge_intf.session_hdl[1] = -1; - csiphy_dev->is_acquired_dev_combo_mode = 0; - } + csiphy_dev->csiphy_info[offset].hdl_data.device_hdl = -1; + csiphy_dev->csiphy_info[offset].hdl_data.session_hdl = -1; csiphy_dev->config_count--; - csiphy_dev->acquire_count--; + if (csiphy_dev->acquire_count) { + csiphy_dev->acquire_count--; + CAM_DBG(CAM_CSIPHY, "Acquire_cnt: %d", + csiphy_dev->acquire_count); + } - if (csiphy_dev->acquire_count == 0) + if (csiphy_dev->start_dev_count == 0) { + CAM_DBG(CAM_CSIPHY, "All PHY devices released"); csiphy_dev->csiphy_state = CAM_CSIPHY_INIT; - + } if (csiphy_dev->config_count == 0) { CAM_DBG(CAM_CSIPHY, "reset csiphy_info"); - csiphy_dev->csiphy_info.lane_mask = 0; - csiphy_dev->csiphy_info.lane_cnt = 0; - csiphy_dev->csiphy_info.combo_mode = 0; + csiphy_dev->csiphy_info[offset].lane_cnt = 0; + csiphy_dev->csiphy_info[offset].lane_assign = 0; + csiphy_dev->csiphy_info[offset].csiphy_3phase = -1; + csiphy_dev->combo_mode = 0; } - } break; + } case CAM_CONFIG_DEV: { struct cam_config_dev_cmd config; @@ -922,6 +1125,7 @@ int32_t cam_csiphy_core_cfg(void *phy_dev, struct cam_axi_vote axi_vote = {0}; struct cam_start_stop_dev_cmd config; int32_t offset; + int clk_vote_level = -1; rc = copy_from_user(&config, (void __user *)cmd->handle, sizeof(config)); @@ -930,18 +1134,86 @@ int32_t cam_csiphy_core_cfg(void *phy_dev, goto release_mutex; } - if (csiphy_dev->csiphy_state == CAM_CSIPHY_START) { - csiphy_dev->start_dev_count++; + if ((csiphy_dev->csiphy_state == CAM_CSIPHY_START) && + (csiphy_dev->start_dev_count > + csiphy_dev->session_max_device_support)) { + CAM_ERR(CAM_CSIPHY, + "Invalid start count: %d, Max supported devices: %u", + csiphy_dev->start_dev_count, + csiphy_dev->session_max_device_support); + rc = -EINVAL; goto release_mutex; } offset = cam_csiphy_get_instance_offset(csiphy_dev, config.dev_handle); - if (offset < 0 || offset >= CSIPHY_MAX_INSTANCES) { - CAM_ERR(CAM_CSIPHY, "Invalid offset"); + if (offset < 0 || + offset >= csiphy_dev->session_max_device_support) { + CAM_ERR(CAM_CSIPHY, "index is invalid: %d", offset); goto release_mutex; } + CAM_INFO(CAM_CSIPHY, + "START_DEV: CSIPHY_IDX: %d, Device_slot: %d, Datarate: %llu, Settletime: %llu", + csiphy_dev->soc_info.index, offset, + csiphy_dev->csiphy_info[offset].data_rate, + csiphy_dev->csiphy_info[offset].settle_time); + + if (csiphy_dev->start_dev_count) { + clk_vote_level = + csiphy_dev->ctrl_reg->getclockvoting( + csiphy_dev, offset); + rc = cam_soc_util_set_clk_rate_level( + &csiphy_dev->soc_info, clk_vote_level); + if (rc) { + CAM_WARN(CAM_CSIPHY, + "Failed to set the clk_rate level: %d", + clk_vote_level); + rc = 0; + } + + if (csiphy_dev->csiphy_info[offset].secure_mode == 1) { + if (cam_cpas_is_feature_supported( + CAM_CPAS_SECURE_CAMERA_ENABLE) != 1) { + CAM_WARN(CAM_CSIPHY, + "sec_cam: camera fuse bit not set"); + rc = 0; + goto release_mutex; + } + + rc = cam_csiphy_notify_secure_mode(csiphy_dev, + CAM_SECURE_MODE_SECURE, offset); + if (rc < 0) { + csiphy_dev->csiphy_info[offset] + .secure_mode = + CAM_SECURE_MODE_NON_SECURE; + CAM_WARN(CAM_CSIPHY, + "sec_cam: notify failed: rc: %d", + rc); + rc = 0; + goto release_mutex; + } + } + if (csiphy_dev->csiphy_info[offset].csiphy_3phase) + cam_csiphy_cphy_data_rate_config( + csiphy_dev, offset); + + rc = cam_csiphy_update_lane(csiphy_dev, offset, true); + if (csiphy_dump == 1) + cam_csiphy_mem_dmp(&csiphy_dev->soc_info); + if (rc) { + CAM_WARN(CAM_CSIPHY, + "csiphy_config_dev failed"); + goto release_mutex; + } + + csiphy_dev->start_dev_count++; + goto release_mutex; + } + + CAM_DBG(CAM_CSIPHY, "Start_dev_cnt: %d", + csiphy_dev->start_dev_count); + ahb_vote.type = CAM_VOTE_ABSOLUTE; ahb_vote.vote.level = CAM_LOWSVS_VOTE; axi_vote.num_paths = 1; @@ -958,7 +1230,7 @@ int32_t cam_csiphy_core_cfg(void *phy_dev, goto release_mutex; } - if (csiphy_dev->csiphy_info.secure_mode[offset] == 1) { + if (csiphy_dev->csiphy_info[offset].secure_mode == 1) { if (cam_cpas_is_feature_supported( CAM_CPAS_SECURE_CAMERA_ENABLE) != 1) { CAM_ERR(CAM_CSIPHY, @@ -972,20 +1244,20 @@ int32_t cam_csiphy_core_cfg(void *phy_dev, csiphy_dev, CAM_SECURE_MODE_SECURE, offset); if (rc < 0) { - csiphy_dev->csiphy_info.secure_mode[offset] = + csiphy_dev->csiphy_info[offset].secure_mode = CAM_SECURE_MODE_NON_SECURE; cam_cpas_stop(csiphy_dev->cpas_handle); goto release_mutex; } } - rc = cam_csiphy_enable_hw(csiphy_dev); + rc = cam_csiphy_enable_hw(csiphy_dev, offset); if (rc != 0) { CAM_ERR(CAM_CSIPHY, "cam_csiphy_enable_hw failed"); cam_cpas_stop(csiphy_dev->cpas_handle); goto release_mutex; } - rc = cam_csiphy_config_dev(csiphy_dev); + rc = cam_csiphy_config_dev(csiphy_dev, config.dev_handle); if (csiphy_dump == 1) cam_csiphy_mem_dmp(&csiphy_dev->soc_info); @@ -996,6 +1268,8 @@ int32_t cam_csiphy_core_cfg(void *phy_dev, goto release_mutex; } csiphy_dev->start_dev_count++; + CAM_DBG(CAM_CSIPHY, "START DEV CNT: %d", + csiphy_dev->start_dev_count); csiphy_dev->csiphy_state = CAM_CSIPHY_START; } break; diff --git a/drivers/cam_sensor_module/cam_csiphy/cam_csiphy_dev.c b/drivers/cam_sensor_module/cam_csiphy/cam_csiphy_dev.c index ebfd041d13..9150125fe5 100644 --- a/drivers/cam_sensor_module/cam_csiphy/cam_csiphy_dev.c +++ b/drivers/cam_sensor_module/cam_csiphy/cam_csiphy_dev.c @@ -131,6 +131,7 @@ static int cam_csiphy_component_bind(struct device *dev, struct csiphy_device *new_csiphy_dev; int32_t rc = 0; struct platform_device *pdev = to_platform_device(dev); + int i; new_csiphy_dev = devm_kzalloc(&pdev->dev, sizeof(struct csiphy_device), GFP_KERNEL); @@ -183,18 +184,23 @@ static int cam_csiphy_component_bind(struct device *dev, platform_set_drvdata(pdev, &(new_csiphy_dev->v4l2_dev_str.sd)); - new_csiphy_dev->bridge_intf.device_hdl[0] = -1; - new_csiphy_dev->bridge_intf.device_hdl[1] = -1; - new_csiphy_dev->bridge_intf.ops.get_dev_info = - NULL; - new_csiphy_dev->bridge_intf.ops.link_setup = - NULL; - new_csiphy_dev->bridge_intf.ops.apply_req = - NULL; + for (i = 0; i < CSIPHY_MAX_INSTANCES_PER_PHY; i++) { + new_csiphy_dev->csiphy_info[i].hdl_data.device_hdl = -1; + new_csiphy_dev->csiphy_info[i].hdl_data.session_hdl = -1; + new_csiphy_dev->csiphy_info[i].csiphy_3phase = -1; + new_csiphy_dev->csiphy_info[i].data_rate = 0; + new_csiphy_dev->csiphy_info[i].settle_time = 0; + new_csiphy_dev->csiphy_info[i].lane_cnt = 0; + new_csiphy_dev->csiphy_info[i].lane_assign = 0; + new_csiphy_dev->csiphy_info[i].lane_enable = 0; + } + + new_csiphy_dev->ops.get_dev_info = NULL; + new_csiphy_dev->ops.link_setup = NULL; + new_csiphy_dev->ops.apply_req = NULL; new_csiphy_dev->acquire_count = 0; new_csiphy_dev->start_dev_count = 0; - new_csiphy_dev->is_acquired_dev_combo_mode = 0; cpas_parms.cam_cpas_client_cb = NULL; cpas_parms.cell_index = new_csiphy_dev->soc_info.index; diff --git a/drivers/cam_sensor_module/cam_csiphy/cam_csiphy_dev.h b/drivers/cam_sensor_module/cam_csiphy/cam_csiphy_dev.h index ac5a017b15..35c2f585de 100644 --- a/drivers/cam_sensor_module/cam_csiphy/cam_csiphy_dev.h +++ b/drivers/cam_sensor_module/cam_csiphy/cam_csiphy_dev.h @@ -29,7 +29,7 @@ #include "cam_context.h" #define MAX_CSIPHY 6 -#define MAX_DPHY_DATA_LN 4 + #define MAX_LRME_V4l2_EVENTS 30 #define CSIPHY_NUM_CLK_MAX 16 #define MAX_CSIPHY_REG_ARRAY 70 @@ -41,6 +41,7 @@ #define MAX_DATA_RATE_REGS 30 #define CAMX_CSIPHY_DEV_NAME "cam-csiphy-driver" +#define CAM_CSIPHY_RX_CLK_SRC "cphy_rx_src_clk" #define CSIPHY_POWER_UP 0 #define CSIPHY_POWER_DOWN 1 @@ -53,20 +54,25 @@ #define CSIPHY_2PH_REGS 5 #define CSIPHY_3PH_REGS 6 -#define CSIPHY_MAX_INSTANCES 2 +#define CSIPHY_MAX_INSTANCES_PER_PHY 3 #define CAM_CSIPHY_MAX_DPHY_LANES 4 #define CAM_CSIPHY_MAX_CPHY_LANES 3 +#define CAM_CSIPHY_MAX_CPHY_DPHY_COMBO_LN 3 +#define CAM_CSIPHY_MAX_CPHY_COMBO_LN 3 + + +#define DPHY_LANE_0 BIT(0) +#define CPHY_LANE_0 BIT(1) +#define DPHY_LANE_1 BIT(2) +#define CPHY_LANE_1 BIT(3) +#define DPHY_LANE_2 BIT(4) +#define CPHY_LANE_2 BIT(5) +#define DPHY_LANE_3 BIT(6) +#define DPHY_CLK_LN BIT(7) #define ENABLE_IRQ false -#undef CDBG -#ifdef CAM_CSIPHY_CORE_DEBUG -#define CDBG(fmt, args...) pr_err(fmt, ##args) -#else -#define CDBG(fmt, args...) pr_debug(fmt, ##args) -#endif - enum cam_csiphy_state { CAM_CSIPHY_INIT, CAM_CSIPHY_ACQUIRE, @@ -111,6 +117,7 @@ struct csiphy_reg_parms_t { uint32_t csiphy_reset_array_size; uint32_t csiphy_2ph_config_array_size; uint32_t csiphy_3ph_config_array_size; + uint32_t csiphy_2ph_3ph_config_array_size; uint32_t csiphy_cpas_cp_bits_per_phy; uint32_t csiphy_cpas_cp_is_interleaved; uint32_t csiphy_cpas_cp_2ph_offset; @@ -123,22 +130,17 @@ struct csiphy_reg_parms_t { * struct csiphy_intf_params * @device_hdl: Device Handle * @session_hdl: Session Handle - * @ops: KMD operations - * @crm_cb: Callback API pointers */ -struct csiphy_intf_params { - int32_t device_hdl[CSIPHY_MAX_INSTANCES]; - int32_t session_hdl[CSIPHY_MAX_INSTANCES]; - int32_t link_hdl[CSIPHY_MAX_INSTANCES]; - struct cam_req_mgr_kmd_ops ops; - struct cam_req_mgr_crm_cb *crm_cb; +struct csiphy_hdl_tbl { + int32_t device_hdl; + int32_t session_hdl; }; /** * struct csiphy_reg_t - * @reg_addr: Register address - * @reg_data: Register data - * @delay: Delay in us + * @reg_addr: Register address + * @reg_data: Register data + * @delay: Delay in us * @csiphy_param_type: CSIPhy parameter type */ struct csiphy_reg_t { @@ -200,38 +202,35 @@ struct csiphy_ctrl_t { struct csiphy_reg_t (*csiphy_2ph_reg)[MAX_SETTINGS_PER_LANE]; struct csiphy_reg_t (*csiphy_2ph_combo_mode_reg)[MAX_SETTINGS_PER_LANE]; struct csiphy_reg_t (*csiphy_3ph_reg)[MAX_SETTINGS_PER_LANE]; + struct csiphy_reg_t (*csiphy_3ph_combo_reg)[MAX_SETTINGS_PER_LANE]; struct csiphy_reg_t (*csiphy_2ph_3ph_mode_reg)[MAX_SETTINGS_PER_LANE]; - enum cam_vote_level (*getclockvoting)(struct csiphy_device *phy_dev); + enum cam_vote_level (*getclockvoting)(struct csiphy_device *phy_dev, + int32_t index); struct data_rate_settings_t *data_rates_settings_table; }; /** - * cam_csiphy_param: Provides cmdbuffer structre - * @lane_mask : Lane mask details - * @lane_assign : Lane sensor will be using - * @csiphy_3phase : Mentions DPHY or CPHY - * @combo_mode : Info regarding combo_mode is enable / disable - * @lane_cnt : Total number of lanes - * @reserved - * @3phase : Details whether 3Phase / 2Phase operation - * @settle_time : Settling time in ms - * @settle_time_combo_sensor : Settling time in ms - * @data_rate : Data rate in mbps - * @data_rate_combo_sensor: data rate of combo sensor - * in the the same phy - * + * cam_csiphy_param : Provides cmdbuffer structure + * @lane_assign : Lane sensor will be using + * @lane_cnt : Total number of lanes + * @secure_mode : To identify whether stream is secure/nonsecure + * @lane_enable : Data Lane selection + * @settle_time : Settling time in ms + * @data_rate : Data rate in mbps + * @csiphy_3phase : To identify DPHY or CPHY + * @csiphy_cpas_cp_reg_mask : CP reg mask for phy instance + * @hdl_data : CSIPHY handle table */ struct cam_csiphy_param { - uint16_t lane_mask; - uint16_t lane_assign; - uint8_t csiphy_3phase; - uint8_t combo_mode; - uint8_t lane_cnt; - uint8_t secure_mode[CSIPHY_MAX_INSTANCES]; - uint64_t settle_time; - uint64_t settle_time_combo_sensor; - uint64_t data_rate; - uint64_t data_rate_combo_sensor; + uint16_t lane_assign; + uint8_t lane_cnt; + uint8_t secure_mode; + uint32_t lane_enable; + uint64_t settle_time; + uint64_t data_rate; + int csiphy_3phase; + uint64_t csiphy_cpas_cp_reg_mask; + struct csiphy_hdl_tbl hdl_data; }; /** @@ -255,41 +254,50 @@ struct cam_csiphy_param { * @csi_3phase: Is it a 3Phase mode * @ref_count: Reference count * @clk_lane: Clock lane + * @rx_clk_src_idx: Phy src clk index * @acquire_count: Acquire device count * @start_dev_count: Start count - * @is_acquired_dev_combo_mode: Flag that mentions whether already acquired - * device is for combo mode * @soc_info: SOC information * @cpas_handle: CPAS handle * @config_count: Config reg count - * @csiphy_cpas_cp_reg_mask: CP reg mask for phy instance + * @current_data_rate: Data rate in mbps + * @csiphy_3phase: To identify DPHY or CPHY at top level + * @combo_mode: Info regarding combo_mode is enable / disable + * @ops: KMD operations + * @crm_cb: Callback API pointers */ struct csiphy_device { - char device_name[CAM_CTX_DEV_NAME_MAX_LENGTH]; - struct mutex mutex; - uint32_t hw_version; - enum cam_csiphy_state csiphy_state; - struct csiphy_ctrl_t *ctrl_reg; - uint32_t csiphy_max_clk; - struct msm_cam_clk_info csiphy_3p_clk_info[2]; - struct clk *csiphy_3p_clk[2]; - unsigned char csi_3phase; - int32_t ref_count; - uint16_t lane_mask[MAX_CSIPHY]; - uint8_t is_csiphy_3phase_hw; - uint8_t is_divisor_32_comp; - uint8_t num_irq_registers; - struct cam_subdev v4l2_dev_str; - struct cam_csiphy_param csiphy_info; - struct csiphy_intf_params bridge_intf; - uint32_t clk_lane; - uint32_t acquire_count; - uint32_t start_dev_count; - uint32_t is_acquired_dev_combo_mode; - struct cam_hw_soc_info soc_info; - uint32_t cpas_handle; - uint32_t config_count; - uint64_t csiphy_cpas_cp_reg_mask[CSIPHY_MAX_INSTANCES]; + char device_name[CAM_CTX_DEV_NAME_MAX_LENGTH]; + struct mutex mutex; + uint32_t hw_version; + enum cam_csiphy_state csiphy_state; + struct csiphy_ctrl_t *ctrl_reg; + uint32_t csiphy_max_clk; + struct msm_cam_clk_info csiphy_3p_clk_info[2]; + struct clk *csiphy_3p_clk[2]; + int32_t ref_count; + uint16_t lane_mask[MAX_CSIPHY]; + uint8_t is_csiphy_3phase_hw; + uint8_t is_divisor_32_comp; + uint8_t num_irq_registers; + struct cam_subdev v4l2_dev_str; + struct cam_csiphy_param csiphy_info[ + CSIPHY_MAX_INSTANCES_PER_PHY]; + uint32_t clk_lane; + uint8_t rx_clk_src_idx; + uint32_t acquire_count; + uint32_t start_dev_count; + struct cam_hw_soc_info soc_info; + uint32_t cpas_handle; + uint32_t config_count; + uint64_t current_data_rate; + uint64_t csiphy_cpas_cp_reg_mask[ + CSIPHY_MAX_INSTANCES_PER_PHY]; + uint8_t session_max_device_support; + uint8_t combo_mode; + uint8_t cphy_dphy_combo_mode; + struct cam_req_mgr_kmd_ops ops; + struct cam_req_mgr_crm_cb *crm_cb; }; /** diff --git a/drivers/cam_sensor_module/cam_csiphy/cam_csiphy_soc.c b/drivers/cam_sensor_module/cam_csiphy/cam_csiphy_soc.c index bedd0570b4..5143f2ab0a 100644 --- a/drivers/cam_sensor_module/cam_csiphy/cam_csiphy_soc.c +++ b/drivers/cam_sensor_module/cam_csiphy/cam_csiphy_soc.c @@ -126,26 +126,25 @@ int32_t cam_csiphy_status_dmp(struct csiphy_device *csiphy_dev) -enum cam_vote_level get_clk_vote_default(struct csiphy_device *csiphy_dev) +enum cam_vote_level get_clk_vote_default(struct csiphy_device *csiphy_dev, + int32_t index) { CAM_DBG(CAM_CSIPHY, "voting for SVS"); return CAM_SVS_VOTE; } -enum cam_vote_level get_clk_voting_dynamic(struct csiphy_device *csiphy_dev) +enum cam_vote_level get_clk_voting_dynamic( + struct csiphy_device *csiphy_dev, int32_t index) { uint32_t cam_vote_level = 0; uint32_t last_valid_vote = 0; struct cam_hw_soc_info *soc_info; - uint64_t phy_data_rate = csiphy_dev->csiphy_info.data_rate; + uint64_t phy_data_rate = csiphy_dev->csiphy_info[index].data_rate; soc_info = &csiphy_dev->soc_info; + phy_data_rate = max(phy_data_rate, csiphy_dev->current_data_rate); - if (csiphy_dev->is_acquired_dev_combo_mode) - phy_data_rate = max(phy_data_rate, - csiphy_dev->csiphy_info.data_rate_combo_sensor); - - if (csiphy_dev->csiphy_info.csiphy_3phase) { + if (csiphy_dev->csiphy_info[index].csiphy_3phase) { if (csiphy_dev->is_divisor_32_comp) do_div(phy_data_rate, CSIPHY_DIVISOR_32); else @@ -156,19 +155,21 @@ enum cam_vote_level get_clk_voting_dynamic(struct csiphy_device *csiphy_dev) /* round off to next integer */ phy_data_rate += 1; + csiphy_dev->current_data_rate = phy_data_rate; for (cam_vote_level = 0; cam_vote_level < CAM_MAX_VOTE; cam_vote_level++) { if (soc_info->clk_level_valid[cam_vote_level] != true) continue; - if (soc_info->clk_rate[cam_vote_level][0] > - phy_data_rate) { + if (soc_info->clk_rate[cam_vote_level] + [csiphy_dev->rx_clk_src_idx] > phy_data_rate) { CAM_DBG(CAM_CSIPHY, "match detected %s : %llu:%d level : %d", - soc_info->clk_name[0], + soc_info->clk_name[csiphy_dev->rx_clk_src_idx], phy_data_rate, - soc_info->clk_rate[cam_vote_level][0], + soc_info->clk_rate[cam_vote_level] + [csiphy_dev->rx_clk_src_idx], cam_vote_level); return cam_vote_level; } @@ -177,7 +178,7 @@ enum cam_vote_level get_clk_voting_dynamic(struct csiphy_device *csiphy_dev) return last_valid_vote; } -int32_t cam_csiphy_enable_hw(struct csiphy_device *csiphy_dev) +int32_t cam_csiphy_enable_hw(struct csiphy_device *csiphy_dev, int32_t index) { int32_t rc = 0; struct cam_hw_soc_info *soc_info; @@ -191,7 +192,7 @@ int32_t cam_csiphy_enable_hw(struct csiphy_device *csiphy_dev) return rc; } - vote_level = csiphy_dev->ctrl_reg->getclockvoting(csiphy_dev); + vote_level = csiphy_dev->ctrl_reg->getclockvoting(csiphy_dev, index); rc = cam_soc_util_enable_platform_resource(soc_info, true, vote_level, ENABLE_IRQ); if (rc < 0) { @@ -466,6 +467,10 @@ int32_t cam_csiphy_parse_dt_info(struct platform_device *pdev, csiphy_dev->csiphy_3p_clk[1] = soc_info->clk[i]; continue; + } else if (!strcmp(soc_info->clk_name[i], + CAM_CSIPHY_RX_CLK_SRC)) { + csiphy_dev->rx_clk_src_idx = i; + continue; } CAM_DBG(CAM_CSIPHY, "clk_rate[%d] = %d", clk_cnt, diff --git a/drivers/cam_sensor_module/cam_csiphy/cam_csiphy_soc.h b/drivers/cam_sensor_module/cam_csiphy/cam_csiphy_soc.h index 0416d8cda6..2ae08006fa 100644 --- a/drivers/cam_sensor_module/cam_csiphy/cam_csiphy_soc.h +++ b/drivers/cam_sensor_module/cam_csiphy/cam_csiphy_soc.h @@ -21,9 +21,6 @@ #include "cam_csiphy_dev.h" #include "cam_csiphy_core.h" -#undef CDBG -#define CDBG(fmt, args...) pr_debug(fmt, ##args) - #define CSI_3PHASE_HW 1 #define CSIPHY_VERSION_V35 0x35 #define CSIPHY_VERSION_V10 0x10 @@ -55,7 +52,7 @@ int cam_csiphy_parse_dt_info(struct platform_device *pdev, * * This API enables SOC related parameters */ -int cam_csiphy_enable_hw(struct csiphy_device *csiphy_dev); +int cam_csiphy_enable_hw(struct csiphy_device *csiphy_dev, int32_t index); /** * @csiphy_dev: CSIPhy device structure diff --git a/drivers/cam_sensor_module/cam_csiphy/include/cam_csiphy_1_2_3_hwreg.h b/drivers/cam_sensor_module/cam_csiphy/include/cam_csiphy_1_2_3_hwreg.h index a9290d6e6c..bddd49432d 100644 --- a/drivers/cam_sensor_module/cam_csiphy/include/cam_csiphy_1_2_3_hwreg.h +++ b/drivers/cam_sensor_module/cam_csiphy/include/cam_csiphy_1_2_3_hwreg.h @@ -16,6 +16,7 @@ struct csiphy_reg_parms_t csiphy_v1_2_3 = { .csiphy_reset_array_size = 5, .csiphy_2ph_config_array_size = 16, .csiphy_3ph_config_array_size = 28, + .csiphy_2ph_3ph_config_array_size = 0, .csiphy_2ph_clock_lane = 0x1, .csiphy_2ph_combo_ck_ln = 0x10, }; diff --git a/drivers/cam_utils/cam_compat.c b/drivers/cam_utils/cam_compat.c index 27c84b0eca..21ebc95ab3 100644 --- a/drivers/cam_utils/cam_compat.c +++ b/drivers/cam_utils/cam_compat.c @@ -77,11 +77,12 @@ int cam_csiphy_notify_secure_mode(struct csiphy_device *csiphy_dev, { int rc = 0; - if (offset >= CSIPHY_MAX_INSTANCES) { + if (offset >= CSIPHY_MAX_INSTANCES_PER_PHY) { CAM_ERR(CAM_CSIPHY, "Invalid CSIPHY offset"); rc = -EINVAL; } else if (qcom_scm_camera_protect_phy_lanes(protect, - csiphy_dev->csiphy_cpas_cp_reg_mask[offset])) { + csiphy_dev->csiphy_info[offset] + .csiphy_cpas_cp_reg_mask)) { CAM_ERR(CAM_CSIPHY, "SCM call to hypervisor failed"); rc = -EINVAL; } @@ -158,10 +159,11 @@ int cam_csiphy_notify_secure_mode(struct csiphy_device *csiphy_dev, struct scm_desc description = { .arginfo = SCM_ARGS(2, SCM_VAL, SCM_VAL), .args[0] = protect, - .args[1] = csiphy_dev->csiphy_cpas_cp_reg_mask[offset], + .args[1] = csiphy_dev->csiphy_info[offset] + .csiphy_cpas_cp_reg_mask, }; - if (offset >= CSIPHY_MAX_INSTANCES) { + if (offset >= CSIPHY_MAX_INSTANCES_PER_PHY) { CAM_ERR(CAM_CSIPHY, "Invalid CSIPHY offset"); rc = -EINVAL; } else if (scm_call2(SCM_SIP_FNID(0x18, 0x7), &description)) { diff --git a/include/uapi/camera/media/cam_sensor.h b/include/uapi/camera/media/cam_sensor.h index bc9498ea61..4ff9ecc7c3 100644 --- a/include/uapi/camera/media/cam_sensor.h +++ b/include/uapi/camera/media/cam_sensor.h @@ -324,23 +324,18 @@ struct cam_cmd_unconditional_wait { } __attribute__((packed)); /** - * cam_csiphy_info: Provides cmdbuffer structre - * @lane_mask : Lane mask details - * @lane_assign : Lane sensor will be using - * @csiphy_3phase : Total number of lanes - * @combo_mode : Info regarding combo_mode is enable / disable - * @lane_cnt : Total number of lanes - * @secure_mode : Secure mode flag to enable / disable - * @3phase : Details whether 3Phase / 2Phase operation - * @settle_time : Settling time in ms - * @data_rate : Data rate + * cam_csiphy_info : Provides cmdbuffer structre + * @lane_assign : Lane sensor will be using + * @lane_cnt : Total number of lanes + * @secure_mode : Secure mode flag to enable / disable + * @settle_time : Settling time in ms + * @data_rate : Data rate * */ struct cam_csiphy_info { - __u16 lane_mask; + __u16 reserved; __u16 lane_assign; - __u8 csiphy_3phase; - __u8 combo_mode; + __u16 reserved1; __u8 lane_cnt; __u8 secure_mode; __u64 settle_time; @@ -349,14 +344,18 @@ struct cam_csiphy_info { /** * cam_csiphy_acquire_dev_info : Information needed for - * csiphy at the time of acquire - * @combo_mode : Indicates the device mode of operation - * @reserved + * csiphy at the time of acquire + * @combo_mode : Indicates the device mode of operation + * @cphy_dphy_combo_mode : Info regarding cphy_dphy_combo mode + * @csiphy_3phase : Details whether 3Phase / 2Phase operation + * @reserve * */ struct cam_csiphy_acquire_dev_info { __u32 combo_mode; - __u32 reserved; + __u16 cphy_dphy_combo_mode; + __u8 csiphy_3phase; + __u8 reserve; } __attribute__((packed)); /**