msm: camera: common: Add support for cesta based clk scaling
On chipsets having cesta hw block support, for cesta supported clks clk frequency can be changed during veritcal blanking based on CSID DRV events. For this to happen, camera clients need to setup high and low clock votes through hw clients. Use corresponding clk, crm APIs to setup high, low clk frquencies and do channel switch to apply newly set rates. Clients can also set clk frequency through sw client which will set the floor. This feature helps in saving power for usecases where vertical blanking is high such as Fast Shutter usecase. CRs-Fixed: 3294948 Change-Id: I1bcf650b439991a23b2a0f0f9a5162bdcd60dc64 Signed-off-by: Mukund Madhusudan Atre <quic_matre@quicinc.com> Signed-off-by: Pavan Kumar Chilamkurthi <quic_pchilamk@quicinc.com>
This commit is contained in:

committed by
Camera Software Integration

parent
fe9c1170c8
commit
b2def29ddc
@@ -176,7 +176,7 @@ int cam_cci_init(struct v4l2_subdev *sd,
|
||||
cam_cci_get_clk_rates(cci_dev, c_ctrl);
|
||||
|
||||
/* Enable Regulators and IRQ*/
|
||||
rc = cam_soc_util_enable_platform_resource(soc_info, true,
|
||||
rc = cam_soc_util_enable_platform_resource(soc_info, CAM_CLK_SW_CLIENT_IDX, true,
|
||||
CAM_LOWSVS_VOTE, true);
|
||||
if (rc < 0) {
|
||||
CAM_DBG(CAM_CCI, "CCI%d_I2C_M%d request platform resources failed, rc: %d",
|
||||
@@ -220,7 +220,7 @@ int cam_cci_init(struct v4l2_subdev *sd,
|
||||
return 0;
|
||||
|
||||
reset_complete_failed:
|
||||
cam_soc_util_disable_platform_resource(soc_info, true, true);
|
||||
cam_soc_util_disable_platform_resource(soc_info, CAM_CLK_SW_CLIENT_IDX, true, true);
|
||||
platform_enable_failed:
|
||||
cci_dev->ref_count--;
|
||||
cam_cpas_stop(cci_dev->cpas_handle);
|
||||
@@ -456,7 +456,7 @@ int cam_cci_soc_release(struct cci_device *cci_dev,
|
||||
cci_dev->i2c_freq_mode[i] = I2C_MAX_MODES;
|
||||
}
|
||||
|
||||
rc = cam_soc_util_disable_platform_resource(soc_info, true, true);
|
||||
rc = cam_soc_util_disable_platform_resource(soc_info, CAM_CLK_SW_CLIENT_IDX, true, true);
|
||||
if (rc) {
|
||||
CAM_ERR(CAM_CCI, "CCI%d_I2C_M%d platform resources disable failed, rc: %d",
|
||||
cci_dev->soc_info.index, master, rc);
|
||||
|
@@ -161,6 +161,9 @@ static void cam_csiphy_reset_phyconfig_param(struct csiphy_device *csiphy_dev,
|
||||
csiphy_dev->csiphy_info[index].mipi_flags = 0;
|
||||
csiphy_dev->csiphy_info[index].hdl_data.device_hdl = -1;
|
||||
csiphy_dev->csiphy_info[index].csiphy_3phase = -1;
|
||||
csiphy_dev->csiphy_info[index].conn_csid_idx = -1;
|
||||
csiphy_dev->csiphy_info[index].use_hw_client_voting = false;
|
||||
csiphy_dev->csiphy_info[index].is_drv_config_en = false;
|
||||
}
|
||||
|
||||
static inline void cam_csiphy_apply_onthego_reg_values(void __iomem *csiphybase, uint8_t csiphy_idx)
|
||||
@@ -1401,7 +1404,9 @@ void cam_csiphy_shutdown(struct csiphy_device *csiphy_dev)
|
||||
{
|
||||
struct cam_hw_soc_info *soc_info;
|
||||
struct csiphy_reg_parms_t *csiphy_reg;
|
||||
struct cam_csiphy_param *param;
|
||||
int32_t i = 0;
|
||||
int rc = 0;
|
||||
|
||||
if (csiphy_dev->csiphy_state == CAM_CSIPHY_INIT)
|
||||
return;
|
||||
@@ -1423,13 +1428,31 @@ void cam_csiphy_shutdown(struct csiphy_device *csiphy_dev)
|
||||
soc_info = &csiphy_dev->soc_info;
|
||||
|
||||
for (i = 0; i < csiphy_dev->acquire_count; i++) {
|
||||
if (csiphy_dev->csiphy_info[i].secure_mode)
|
||||
cam_csiphy_program_secure_mode(
|
||||
csiphy_dev,
|
||||
param = &csiphy_dev->csiphy_info[i];
|
||||
|
||||
if (param->secure_mode)
|
||||
cam_csiphy_program_secure_mode(csiphy_dev,
|
||||
CAM_SECURE_MODE_NON_SECURE, i);
|
||||
|
||||
csiphy_dev->csiphy_info[i].secure_mode =
|
||||
CAM_SECURE_MODE_NON_SECURE;
|
||||
param->secure_mode = CAM_SECURE_MODE_NON_SECURE;
|
||||
|
||||
if (soc_info->is_clk_drv_en && param->use_hw_client_voting) {
|
||||
rc = cam_soc_util_set_src_clk_rate(soc_info, param->conn_csid_idx,
|
||||
0, 0);
|
||||
if (rc) {
|
||||
CAM_ERR(CAM_CSIPHY,
|
||||
"[%d] Failed in setting clk rate for %d",
|
||||
soc_info->index, param->conn_csid_idx);
|
||||
} else {
|
||||
rc = cam_soc_util_cesta_channel_switch(param->conn_csid_idx,
|
||||
"csiphy_shutdown");
|
||||
if (rc) {
|
||||
CAM_ERR(CAM_CSIPHY,
|
||||
"Failed to apply power states for cesta client:%d rc:%d",
|
||||
param->conn_csid_idx, rc);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
cam_csiphy_reset_phyconfig_param(csiphy_dev, i);
|
||||
}
|
||||
@@ -1445,7 +1468,7 @@ void cam_csiphy_shutdown(struct csiphy_device *csiphy_dev)
|
||||
}
|
||||
|
||||
cam_csiphy_reset(csiphy_dev);
|
||||
cam_soc_util_disable_platform_resource(soc_info, true, true);
|
||||
cam_soc_util_disable_platform_resource(soc_info, CAM_CLK_SW_CLIENT_IDX, true, true);
|
||||
|
||||
cam_cpas_stop(csiphy_dev->cpas_handle);
|
||||
csiphy_dev->csiphy_state = CAM_CSIPHY_ACQUIRE;
|
||||
@@ -2092,6 +2115,9 @@ int32_t cam_csiphy_core_cfg(void *phy_dev,
|
||||
csiphy_acq_dev.session_handle;
|
||||
csiphy_dev->csiphy_info[index].csiphy_3phase =
|
||||
csiphy_acq_params.csiphy_3phase;
|
||||
csiphy_dev->csiphy_info[index].conn_csid_idx = -1;
|
||||
csiphy_dev->csiphy_info[index].use_hw_client_voting = false;
|
||||
csiphy_dev->csiphy_info[index].is_drv_config_en = false;
|
||||
|
||||
CAM_DBG(CAM_CSIPHY, "Add dev_handle:0x%x at index: %d ",
|
||||
csiphy_dev->csiphy_info[index].hdl_data.device_hdl,
|
||||
@@ -2151,6 +2177,7 @@ int32_t cam_csiphy_core_cfg(void *phy_dev,
|
||||
case CAM_STOP_DEV: {
|
||||
int32_t offset, rc = 0;
|
||||
struct cam_start_stop_dev_cmd config;
|
||||
struct cam_csiphy_param *param;
|
||||
|
||||
rc = copy_from_user(&config, (void __user *)cmd->handle,
|
||||
sizeof(config));
|
||||
@@ -2173,40 +2200,52 @@ int32_t cam_csiphy_core_cfg(void *phy_dev,
|
||||
goto release_mutex;
|
||||
}
|
||||
|
||||
param = &csiphy_dev->csiphy_info[offset];
|
||||
|
||||
if (--csiphy_dev->start_dev_count) {
|
||||
if (csiphy_dev->csiphy_info[offset].secure_mode)
|
||||
cam_csiphy_program_secure_mode(
|
||||
csiphy_dev,
|
||||
if (param->secure_mode)
|
||||
cam_csiphy_program_secure_mode(csiphy_dev,
|
||||
CAM_SECURE_MODE_NON_SECURE, offset);
|
||||
|
||||
csiphy_dev->csiphy_info[offset].secure_mode =
|
||||
CAM_SECURE_MODE_NON_SECURE;
|
||||
csiphy_dev->csiphy_info[offset].csiphy_cpas_cp_reg_mask
|
||||
= 0;
|
||||
param->secure_mode = CAM_SECURE_MODE_NON_SECURE;
|
||||
param->csiphy_cpas_cp_reg_mask = 0;
|
||||
|
||||
cam_csiphy_update_lane_selection(csiphy_dev, offset, false);
|
||||
|
||||
if (soc_info->is_clk_drv_en && param->use_hw_client_voting) {
|
||||
rc = cam_soc_util_set_src_clk_rate(soc_info, param->conn_csid_idx,
|
||||
0, 0);
|
||||
if (rc) {
|
||||
CAM_ERR(CAM_CSIPHY,
|
||||
"[%d] Failed in setting clk rate for %d",
|
||||
soc_info->index, param->conn_csid_idx);
|
||||
} else {
|
||||
rc = cam_soc_util_cesta_channel_switch(param->conn_csid_idx,
|
||||
"csiphy_stop_dev");
|
||||
if (rc) {
|
||||
CAM_ERR(CAM_CSIPHY,
|
||||
"Failed to apply power states for cesta client:%d rc:%d",
|
||||
param->conn_csid_idx, rc);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
CAM_INFO(CAM_CSIPHY,
|
||||
"CAM_STOP_PHYDEV: %d, Type: %s, dev_cnt: %u, slot: %d, Datarate: %llu, Settletime: %llu",
|
||||
soc_info->index,
|
||||
"CAM_STOP_PHYDEV: %d, CSID:%d, Type: %s, dev_cnt: %u, slot: %d, Datarate: %llu, Settletime: %llu",
|
||||
soc_info->index, param->conn_csid_idx,
|
||||
g_phy_data[soc_info->index].is_3phase ? "CPHY" : "DPHY",
|
||||
csiphy_dev->start_dev_count,
|
||||
offset,
|
||||
csiphy_dev->csiphy_info[offset].data_rate,
|
||||
csiphy_dev->csiphy_info[offset].settle_time);
|
||||
csiphy_dev->start_dev_count, offset, param->data_rate,
|
||||
param->settle_time);
|
||||
|
||||
goto release_mutex;
|
||||
}
|
||||
|
||||
if (csiphy_dev->csiphy_info[offset].secure_mode)
|
||||
cam_csiphy_program_secure_mode(
|
||||
csiphy_dev,
|
||||
CAM_SECURE_MODE_NON_SECURE, offset);
|
||||
if (param->secure_mode)
|
||||
cam_csiphy_program_secure_mode(csiphy_dev, CAM_SECURE_MODE_NON_SECURE,
|
||||
offset);
|
||||
|
||||
csiphy_dev->csiphy_info[offset].secure_mode =
|
||||
CAM_SECURE_MODE_NON_SECURE;
|
||||
|
||||
csiphy_dev->csiphy_info[offset].csiphy_cpas_cp_reg_mask = 0x0;
|
||||
param->secure_mode = CAM_SECURE_MODE_NON_SECURE;
|
||||
param->csiphy_cpas_cp_reg_mask = 0x0;
|
||||
|
||||
if (csiphy_dev->prgm_cmn_reg_across_csiphy) {
|
||||
mutex_lock(&active_csiphy_cnt_mutex);
|
||||
@@ -2225,7 +2264,7 @@ int32_t cam_csiphy_core_cfg(void *phy_dev,
|
||||
|
||||
cam_csiphy_update_lane_selection(csiphy_dev, offset, false);
|
||||
|
||||
rc = cam_csiphy_disable_hw(csiphy_dev);
|
||||
rc = cam_csiphy_disable_hw(csiphy_dev, offset);
|
||||
if (rc < 0)
|
||||
CAM_ERR(CAM_CSIPHY, "Failed in csiphy release");
|
||||
|
||||
@@ -2237,12 +2276,10 @@ int32_t cam_csiphy_core_cfg(void *phy_dev,
|
||||
csiphy_dev->csiphy_state = CAM_CSIPHY_ACQUIRE;
|
||||
|
||||
CAM_INFO(CAM_CSIPHY,
|
||||
"CAM_STOP_PHYDEV: %u, Type: %s, slot: %d, Datarate: %llu, Settletime: %llu",
|
||||
soc_info->index,
|
||||
"CAM_STOP_PHYDEV: %u, CSID:%d, Type: %s, slot: %d, Datarate: %llu, Settletime: %llu",
|
||||
soc_info->index, param->conn_csid_idx,
|
||||
g_phy_data[soc_info->index].is_3phase ? "CPHY" : "DPHY",
|
||||
offset,
|
||||
csiphy_dev->csiphy_info[offset].data_rate,
|
||||
csiphy_dev->csiphy_info[offset].settle_time);
|
||||
offset, param->data_rate, param->settle_time);
|
||||
}
|
||||
break;
|
||||
case CAM_RELEASE_DEV: {
|
||||
@@ -2350,9 +2387,11 @@ int32_t cam_csiphy_core_cfg(void *phy_dev,
|
||||
break;
|
||||
}
|
||||
case CAM_START_DEV: {
|
||||
struct cam_csiphy_param *param;
|
||||
struct cam_start_stop_dev_cmd config;
|
||||
int32_t offset;
|
||||
int clk_vote_level = -1;
|
||||
int clk_vote_level_high = -1;
|
||||
int clk_vote_level_low = -1;
|
||||
uint8_t data_rate_variant_idx = 0;
|
||||
|
||||
CAM_DBG(CAM_CSIPHY, "START_DEV Called");
|
||||
@@ -2382,17 +2421,63 @@ int32_t cam_csiphy_core_cfg(void *phy_dev,
|
||||
goto release_mutex;
|
||||
}
|
||||
|
||||
param = &csiphy_dev->csiphy_info[offset];
|
||||
|
||||
rc = cam_cpas_query_drv_enable(NULL, &soc_info->is_clk_drv_en);
|
||||
if (rc) {
|
||||
CAM_ERR(CAM_CSIPHY, "Failed to query DRV enable rc: %d", rc);
|
||||
goto release_mutex;
|
||||
}
|
||||
|
||||
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, false);
|
||||
if (rc) {
|
||||
CAM_WARN(CAM_CSIPHY,
|
||||
"Failed to set the clk_rate level: %d",
|
||||
clk_vote_level);
|
||||
rc = 0;
|
||||
clk_vote_level_high =
|
||||
csiphy_dev->ctrl_reg->getclockvoting(csiphy_dev, offset);
|
||||
clk_vote_level_low = clk_vote_level_high;
|
||||
|
||||
CAM_DBG(CAM_CSIPHY,
|
||||
"CSIPHY[%d] is_clk_drv_en[%d] conn_csid_idx[%d] use_hw_client_voting[%d] is_drv_config_en[%d]",
|
||||
csiphy_dev->soc_info.index, soc_info->is_clk_drv_en,
|
||||
param->conn_csid_idx, param->use_hw_client_voting,
|
||||
param->is_drv_config_en);
|
||||
|
||||
if (soc_info->is_clk_drv_en && param->use_hw_client_voting) {
|
||||
if (param->is_drv_config_en)
|
||||
clk_vote_level_low = CAM_LOWSVS_VOTE;
|
||||
|
||||
rc = cam_soc_util_set_clk_rate_level(&csiphy_dev->soc_info,
|
||||
param->conn_csid_idx, clk_vote_level_high,
|
||||
clk_vote_level_low, false);
|
||||
if (rc) {
|
||||
CAM_ERR(CAM_CSIPHY,
|
||||
"Failed to set the req clk_rate level[high low]: [%s %s] cesta_client_idx: %d rc: %d",
|
||||
cam_soc_util_get_string_from_level(
|
||||
clk_vote_level_high),
|
||||
cam_soc_util_get_string_from_level(
|
||||
clk_vote_level_low), param->conn_csid_idx, rc);
|
||||
rc = -EINVAL;
|
||||
goto release_mutex;
|
||||
}
|
||||
|
||||
rc = cam_soc_util_cesta_channel_switch(param->conn_csid_idx,
|
||||
"csiphy_combo");
|
||||
if (rc) {
|
||||
CAM_ERR(CAM_CSIPHY,
|
||||
"Failed to apply power states for crm client:%d rc:%d",
|
||||
param->conn_csid_idx, rc);
|
||||
rc = 0;
|
||||
}
|
||||
} else {
|
||||
rc = cam_soc_util_set_clk_rate_level(&csiphy_dev->soc_info,
|
||||
CAM_CLK_SW_CLIENT_IDX, clk_vote_level_high, 0, false);
|
||||
if (rc) {
|
||||
CAM_WARN(CAM_CSIPHY,
|
||||
"Failed to set the req clk_rate level: %s",
|
||||
cam_soc_util_get_string_from_level(
|
||||
clk_vote_level_high));
|
||||
rc = -EINVAL;
|
||||
goto release_mutex;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
if (csiphy_dev->csiphy_info[offset].secure_mode == 1) {
|
||||
@@ -2440,8 +2525,9 @@ int32_t cam_csiphy_core_cfg(void *phy_dev,
|
||||
csiphy_dev->start_dev_count++;
|
||||
|
||||
CAM_INFO(CAM_CSIPHY,
|
||||
"CAM_START_PHYDEV: %d, Type: %s, dev_cnt: %u, slot: %d, combo: %u, cphy+dphy: %u, sec_mode: %d, Datarate: %llu, Settletime: %llu",
|
||||
"CAM_START_PHYDEV: %d, CSID:%d, Type: %s, dev_cnt: %u, slot: %d, combo: %u, cphy+dphy: %u, sec_mode: %d, Datarate: %llu, Settletime: %llu",
|
||||
soc_info->index,
|
||||
csiphy_dev->csiphy_info[offset].conn_csid_idx,
|
||||
g_phy_data[soc_info->index].is_3phase ? "CPHY" : "DPHY",
|
||||
csiphy_dev->start_dev_count,
|
||||
offset,
|
||||
@@ -2505,7 +2591,7 @@ int32_t cam_csiphy_core_cfg(void *phy_dev,
|
||||
rc = cam_csiphy_config_dev(csiphy_dev, config.dev_handle, data_rate_variant_idx);
|
||||
if (rc < 0) {
|
||||
CAM_ERR(CAM_CSIPHY, "cam_csiphy_config_dev failed");
|
||||
cam_csiphy_disable_hw(csiphy_dev);
|
||||
cam_csiphy_disable_hw(csiphy_dev, offset);
|
||||
goto hw_cnt_decrement;
|
||||
}
|
||||
|
||||
@@ -2549,8 +2635,9 @@ int32_t cam_csiphy_core_cfg(void *phy_dev,
|
||||
csiphy_dev->csiphy_state = CAM_CSIPHY_START;
|
||||
|
||||
CAM_INFO(CAM_CSIPHY,
|
||||
"CAM_START_PHYDEV: %d, Type: %s, slot: %d, sec_mode: %d, Datarate: %llu, Settletime: %llu, combo: %u, cphy+dphy: %u",
|
||||
"CAM_START_PHYDEV: %d, CSID:%d, Type: %s, slot: %d, sec_mode: %d, Datarate: %llu, Settletime: %llu, combo: %u, cphy+dphy: %u",
|
||||
soc_info->index,
|
||||
csiphy_dev->csiphy_info[offset].conn_csid_idx,
|
||||
g_phy_data[soc_info->index].is_3phase ? "CPHY" : "DPHY",
|
||||
offset,
|
||||
csiphy_dev->csiphy_info[offset].secure_mode,
|
||||
|
@@ -85,6 +85,22 @@ int cam_csiphy_format_secure_phy_lane_info(
|
||||
|
||||
}
|
||||
|
||||
static int cam_csiphy_get_session_index(struct csiphy_device *csiphy_dev,
|
||||
uint32_t lane_assign)
|
||||
{
|
||||
int i = 0;
|
||||
struct cam_csiphy_param *param;
|
||||
|
||||
for (i = 0; i < CSIPHY_MAX_INSTANCES_PER_PHY; i++) {
|
||||
param = &csiphy_dev->csiphy_info[i];
|
||||
|
||||
if (param->lane_assign == lane_assign)
|
||||
break;
|
||||
}
|
||||
|
||||
return i;
|
||||
}
|
||||
|
||||
static void cam_csiphy_populate_secure_info(
|
||||
struct csiphy_device *csiphy_dev, void *data)
|
||||
{
|
||||
@@ -136,6 +152,7 @@ static void cam_csiphy_subdev_handle_message(struct v4l2_subdev *sd,
|
||||
{
|
||||
struct csiphy_device *csiphy_dev = v4l2_get_subdevdata(sd);
|
||||
uint32_t phy_idx;
|
||||
int rc = 0;
|
||||
|
||||
if (!data) {
|
||||
CAM_ERR(CAM_CSIPHY, "Empty Payload");
|
||||
@@ -172,6 +189,110 @@ static void cam_csiphy_subdev_handle_message(struct v4l2_subdev *sd,
|
||||
|
||||
break;
|
||||
}
|
||||
case CAM_SUBDEV_MESSAGE_CONN_CSID_INFO: {
|
||||
struct cam_subdev_msg_phy_conn_csid_info *conn_csid_info =
|
||||
(struct cam_subdev_msg_phy_conn_csid_info *) data;
|
||||
int idx;
|
||||
struct cam_csiphy_param *param;
|
||||
|
||||
idx = cam_csiphy_get_session_index(csiphy_dev, conn_csid_info->lane_cfg);
|
||||
if (idx >= CSIPHY_MAX_INSTANCES_PER_PHY) {
|
||||
CAM_ERR(CAM_CSIPHY, "Phy session not found %d %d",
|
||||
csiphy_dev->soc_info.index, conn_csid_info->lane_cfg);
|
||||
rc = -EBADR;
|
||||
break;
|
||||
}
|
||||
|
||||
param = &csiphy_dev->csiphy_info[idx];
|
||||
param->conn_csid_idx = conn_csid_info->core_idx;
|
||||
|
||||
CAM_DBG(CAM_CSIPHY, "PHY: %d, CSID: %d connected", csiphy_dev->soc_info.index,
|
||||
param->conn_csid_idx);
|
||||
break;
|
||||
}
|
||||
case CAM_SUBDEV_MESSAGE_DRV_INFO: {
|
||||
struct cam_subdev_msg_phy_drv_info *drv_info =
|
||||
(struct cam_subdev_msg_phy_drv_info *) data;
|
||||
int idx;
|
||||
struct cam_csiphy_param *param;
|
||||
|
||||
idx = cam_csiphy_get_session_index(csiphy_dev, drv_info->lane_cfg);
|
||||
if (idx >= CSIPHY_MAX_INSTANCES_PER_PHY) {
|
||||
CAM_ERR(CAM_CSIPHY, "Phy session not found %d %d",
|
||||
csiphy_dev->soc_info.index, drv_info->lane_cfg);
|
||||
rc = -EBADR;
|
||||
break;
|
||||
}
|
||||
|
||||
param = &csiphy_dev->csiphy_info[idx];
|
||||
param->is_drv_config_en = drv_info->is_drv_config_en;
|
||||
param->use_hw_client_voting = drv_info->use_hw_client_voting;
|
||||
|
||||
CAM_DBG(CAM_CSIPHY,
|
||||
"PHY: %d, CSID: %d DRV info : use hw client %d, enable drv config %d",
|
||||
csiphy_dev->soc_info.index, param->conn_csid_idx,
|
||||
param->use_hw_client_voting, param->is_drv_config_en);
|
||||
|
||||
break;
|
||||
}
|
||||
case CAM_SUBDEV_MESSAGE_NOTIFY_HALT_RESUME: {
|
||||
int drv_idx;
|
||||
struct cam_subdev_msg_phy_halt_resume_info *halt_resume_info =
|
||||
(struct cam_subdev_msg_phy_halt_resume_info *) data;
|
||||
int idx;
|
||||
struct cam_csiphy_param *param;
|
||||
unsigned long clk_rate;
|
||||
|
||||
idx = cam_csiphy_get_session_index(csiphy_dev, halt_resume_info->lane_cfg);
|
||||
if (idx >= CSIPHY_MAX_INSTANCES_PER_PHY) {
|
||||
CAM_ERR(CAM_CSIPHY, "Phy session not found %d %d",
|
||||
csiphy_dev->soc_info.index, halt_resume_info->lane_cfg);
|
||||
rc = -EBADR;
|
||||
break;
|
||||
}
|
||||
|
||||
param = &csiphy_dev->csiphy_info[idx];
|
||||
drv_idx = param->conn_csid_idx;
|
||||
|
||||
if (!csiphy_dev->soc_info.is_clk_drv_en || !param->use_hw_client_voting ||
|
||||
!param->is_drv_config_en)
|
||||
break;
|
||||
|
||||
CAM_DBG(CAM_CSIPHY,
|
||||
"PHY: %d, CSID: %d DRV info : use hw client %d, enable drv config %d, op=%s",
|
||||
csiphy_dev->soc_info.index, param->conn_csid_idx,
|
||||
param->use_hw_client_voting, param->is_drv_config_en,
|
||||
(halt_resume_info->csid_state == CAM_SUBDEV_PHY_CSID_HALT) ? "HALT" :
|
||||
"RESUME");
|
||||
|
||||
if (halt_resume_info->csid_state == CAM_SUBDEV_PHY_CSID_HALT) {
|
||||
clk_rate =
|
||||
csiphy_dev->soc_info.applied_src_clk_rates.hw_client[drv_idx].high;
|
||||
|
||||
rc = cam_soc_util_set_src_clk_rate(&csiphy_dev->soc_info,
|
||||
CAM_CLK_SW_CLIENT_IDX, clk_rate, 0);
|
||||
if (rc)
|
||||
CAM_ERR(CAM_CSIPHY,
|
||||
"PHY[%d] CSID HALT: csiphy set_rate %ld failed rc: %d",
|
||||
phy_idx, clk_rate, rc);
|
||||
} else if (halt_resume_info->csid_state == CAM_SUBDEV_PHY_CSID_RESUME) {
|
||||
int32_t src_idx = csiphy_dev->soc_info.src_clk_idx;
|
||||
|
||||
clk_rate = csiphy_dev->soc_info.clk_rate[CAM_LOWSVS_VOTE][src_idx];
|
||||
|
||||
rc = cam_soc_util_set_src_clk_rate(&csiphy_dev->soc_info,
|
||||
CAM_CLK_SW_CLIENT_IDX, clk_rate, 0);
|
||||
if (rc)
|
||||
CAM_ERR(CAM_CSIPHY,
|
||||
"PHY[%d] CSID RESUME: csiphy _set_rate %ld failed rc: %d",
|
||||
phy_idx, clk_rate, rc);
|
||||
} else {
|
||||
CAM_ERR(CAM_CSIPHY,
|
||||
"CSIPHY:%d Failed to handle CSID halt resume csid_state: %d",
|
||||
phy_idx, halt_resume_info->csid_state);
|
||||
}
|
||||
break;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
@@ -431,6 +552,9 @@ static int cam_csiphy_component_bind(struct device *dev,
|
||||
new_csiphy_dev->csiphy_info[i].lane_assign = 0;
|
||||
new_csiphy_dev->csiphy_info[i].lane_enable = 0;
|
||||
new_csiphy_dev->csiphy_info[i].mipi_flags = 0;
|
||||
new_csiphy_dev->csiphy_info[i].conn_csid_idx = -1;
|
||||
new_csiphy_dev->csiphy_info[i].use_hw_client_voting = false;
|
||||
new_csiphy_dev->csiphy_info[i].is_drv_config_en = false;
|
||||
}
|
||||
|
||||
new_csiphy_dev->ops.get_dev_info = NULL;
|
||||
|
@@ -334,6 +334,9 @@ struct csiphy_ctrl_t {
|
||||
* format for scm call
|
||||
* @secure_info_updated : If all information in the secure_info struct above
|
||||
* is passed and formatted properly from CSID driver
|
||||
* @conn_csid_idx : Connected CSID core idx (Primary csid in case of dual ife)
|
||||
* @use_hw_client_voting : Whether to use hw client voting for clk on chipsets with cesta
|
||||
* @is_drv_config_en : If drv is configured in CSID
|
||||
*/
|
||||
struct cam_csiphy_param {
|
||||
uint16_t lane_assign;
|
||||
@@ -348,6 +351,9 @@ struct cam_csiphy_param {
|
||||
struct csiphy_hdl_tbl hdl_data;
|
||||
struct cam_csiphy_tz_secure_info secure_info;
|
||||
bool secure_info_updated;
|
||||
int32_t conn_csid_idx;
|
||||
bool use_hw_client_voting;
|
||||
bool is_drv_config_en;
|
||||
};
|
||||
|
||||
struct csiphy_work_queue {
|
||||
|
@@ -179,53 +179,80 @@ 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;
|
||||
enum cam_vote_level vote_level = CAM_SVS_VOTE;
|
||||
enum cam_vote_level vote_level;
|
||||
struct cam_csiphy_param *param = &csiphy_dev->csiphy_info[index];
|
||||
|
||||
soc_info = &csiphy_dev->soc_info;
|
||||
|
||||
if (csiphy_dev->ref_count++) {
|
||||
CAM_ERR(CAM_CSIPHY, "csiphy refcount = %d",
|
||||
csiphy_dev->ref_count);
|
||||
return rc;
|
||||
goto end;
|
||||
}
|
||||
|
||||
vote_level = csiphy_dev->ctrl_reg->getclockvoting(csiphy_dev, index);
|
||||
rc = cam_soc_util_enable_platform_resource(soc_info, true,
|
||||
vote_level, true);
|
||||
if (rc < 0) {
|
||||
CAM_ERR(CAM_CSIPHY, "failed to enable platform resources %d",
|
||||
rc);
|
||||
return rc;
|
||||
|
||||
rc = cam_soc_util_enable_platform_resource(soc_info,
|
||||
(soc_info->is_clk_drv_en && param->use_hw_client_voting) ?
|
||||
param->conn_csid_idx : CAM_CLK_SW_CLIENT_IDX, true, vote_level, true);
|
||||
if (rc) {
|
||||
CAM_ERR(CAM_CSIPHY,
|
||||
"[%s] failed to enable platform resources, clk_drv_en=%d, use_hw_client=%d conn_csid_idx=%d, rc=%d",
|
||||
soc_info->dev_name, soc_info->is_clk_drv_en, param->use_hw_client_voting,
|
||||
param->conn_csid_idx, rc);
|
||||
goto end;
|
||||
}
|
||||
|
||||
rc = cam_soc_util_set_src_clk_rate(soc_info,
|
||||
soc_info->clk_rate[0][soc_info->src_clk_idx]);
|
||||
if (soc_info->is_clk_drv_en && param->use_hw_client_voting && param->is_drv_config_en) {
|
||||
int clk_vote_level_high = vote_level;
|
||||
int clk_vote_level_low = CAM_LOWSVS_VOTE;
|
||||
|
||||
rc = cam_soc_util_set_clk_rate_level(soc_info, param->conn_csid_idx,
|
||||
clk_vote_level_high, clk_vote_level_low, false);
|
||||
if (rc) {
|
||||
CAM_ERR(CAM_CSIPHY,
|
||||
"Failed to set the req clk_rate level[high low]: [%s %s] cesta_client_idx: %d rc: %d",
|
||||
cam_soc_util_get_string_from_level(clk_vote_level_high),
|
||||
cam_soc_util_get_string_from_level(clk_vote_level_low),
|
||||
param->conn_csid_idx, rc);
|
||||
rc = -EINVAL;
|
||||
goto disable_platform_resource;
|
||||
}
|
||||
|
||||
rc = cam_soc_util_cesta_channel_switch(param->conn_csid_idx, "csiphy_start");
|
||||
if (rc) {
|
||||
CAM_ERR(CAM_CSIPHY,
|
||||
"[%s] Failed to apply power states for crm client:%d rc:%d",
|
||||
soc_info->dev_name, param->conn_csid_idx, rc);
|
||||
goto disable_platform_resource;
|
||||
}
|
||||
|
||||
if (rc < 0) {
|
||||
CAM_ERR(CAM_CSIPHY, "csiphy_clk_set_rate failed rc: %d", rc);
|
||||
goto csiphy_disable_platform_resource;
|
||||
}
|
||||
|
||||
cam_csiphy_reset(csiphy_dev);
|
||||
|
||||
return rc;
|
||||
|
||||
|
||||
csiphy_disable_platform_resource:
|
||||
cam_soc_util_disable_platform_resource(soc_info, true, true);
|
||||
|
||||
disable_platform_resource:
|
||||
cam_soc_util_disable_platform_resource(soc_info,
|
||||
(soc_info->is_clk_drv_en && param->use_hw_client_voting) ?
|
||||
param->conn_csid_idx : CAM_CLK_SW_CLIENT_IDX,
|
||||
true, true);
|
||||
end:
|
||||
return rc;
|
||||
}
|
||||
|
||||
int32_t cam_csiphy_disable_hw(struct csiphy_device *csiphy_dev)
|
||||
int32_t cam_csiphy_disable_hw(struct csiphy_device *csiphy_dev, int32_t index)
|
||||
{
|
||||
struct cam_hw_soc_info *soc_info;
|
||||
struct cam_csiphy_param *param;
|
||||
|
||||
if (!csiphy_dev || !csiphy_dev->ref_count) {
|
||||
CAM_ERR(CAM_CSIPHY, "csiphy dev NULL / ref_count ZERO");
|
||||
return 0;
|
||||
}
|
||||
soc_info = &csiphy_dev->soc_info;
|
||||
param = &csiphy_dev->csiphy_info[index];
|
||||
|
||||
if (--csiphy_dev->ref_count) {
|
||||
CAM_ERR(CAM_CSIPHY, "csiphy refcount = %d",
|
||||
@@ -235,7 +262,10 @@ int32_t cam_csiphy_disable_hw(struct csiphy_device *csiphy_dev)
|
||||
|
||||
cam_csiphy_reset(csiphy_dev);
|
||||
|
||||
cam_soc_util_disable_platform_resource(soc_info, true, true);
|
||||
cam_soc_util_disable_platform_resource(soc_info,
|
||||
(soc_info->is_clk_drv_en && param->use_hw_client_voting) ?
|
||||
param->conn_csid_idx : CAM_CLK_SW_CLIENT_IDX,
|
||||
true, true);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@@ -65,7 +65,7 @@ int cam_csiphy_enable_hw(struct csiphy_device *csiphy_dev, int32_t index);
|
||||
*
|
||||
* This API disables SOC related parameters
|
||||
*/
|
||||
int cam_csiphy_disable_hw(struct csiphy_device *csiphy_dev);
|
||||
int cam_csiphy_disable_hw(struct csiphy_device *csiphy_dev, int32_t index);
|
||||
|
||||
/**
|
||||
* @soc_info: Soc info of cam hw driver module
|
||||
|
@@ -2174,8 +2174,8 @@ int cam_sensor_core_power_up(struct cam_sensor_power_ctrl_t *ctrl,
|
||||
power_setting->config_val;
|
||||
|
||||
for (j = 0; j < soc_info->num_clk; j++) {
|
||||
rc = cam_soc_util_clk_enable(soc_info, false,
|
||||
j, 0, NULL);
|
||||
rc = cam_soc_util_clk_enable(soc_info, CAM_CLK_SW_CLIENT_IDX,
|
||||
false, j, 0);
|
||||
if (rc) {
|
||||
CAM_ERR(CAM_UTIL,
|
||||
"Failed in clk enable %d", i);
|
||||
@@ -2318,7 +2318,7 @@ power_up_failed:
|
||||
switch (power_setting->seq_type) {
|
||||
case SENSOR_MCLK:
|
||||
for (i = soc_info->num_clk - 1; i >= 0; i--) {
|
||||
cam_soc_util_clk_disable(soc_info, false, i);
|
||||
cam_soc_util_clk_disable(soc_info, CAM_CLK_SW_CLIENT_IDX, false, i);
|
||||
}
|
||||
ret = cam_config_mclk_reg(ctrl, soc_info, index);
|
||||
if (ret < 0) {
|
||||
@@ -2475,7 +2475,7 @@ int cam_sensor_util_power_down(struct cam_sensor_power_ctrl_t *ctrl,
|
||||
switch (pd->seq_type) {
|
||||
case SENSOR_MCLK:
|
||||
for (i = soc_info->num_clk - 1; i >= 0; i--) {
|
||||
cam_soc_util_clk_disable(soc_info, false, i);
|
||||
cam_soc_util_clk_disable(soc_info, CAM_CLK_SW_CLIENT_IDX, false, i);
|
||||
}
|
||||
|
||||
ret = cam_config_mclk_reg(ctrl, soc_info, index);
|
||||
|
@@ -307,7 +307,8 @@ static int tpg_hw_soc_disable(struct tpg_hw *hw)
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
rc = cam_soc_util_disable_platform_resource(hw->soc_info, true, false);
|
||||
rc = cam_soc_util_disable_platform_resource(hw->soc_info, CAM_CLK_SW_CLIENT_IDX, true,
|
||||
false);
|
||||
if (rc) {
|
||||
CAM_ERR(CAM_TPG, "TPG[%d] Disable platform failed %d",
|
||||
hw->hw_idx, rc);
|
||||
@@ -356,7 +357,7 @@ static int tpg_hw_soc_enable(
|
||||
goto end;
|
||||
}
|
||||
|
||||
rc = cam_soc_util_enable_platform_resource(hw->soc_info, true,
|
||||
rc = cam_soc_util_enable_platform_resource(hw->soc_info, CAM_CLK_SW_CLIENT_IDX, true,
|
||||
clk_level, false);
|
||||
if (rc) {
|
||||
CAM_ERR(CAM_TPG, "TPG[%d] enable platform failed",
|
||||
@@ -963,7 +964,8 @@ int tpg_hw_reset(struct tpg_hw *hw)
|
||||
/* disable the hw */
|
||||
mutex_lock(&hw->mutex);
|
||||
if (hw->state != TPG_HW_STATE_HW_DISABLED) {
|
||||
rc = cam_soc_util_disable_platform_resource(hw->soc_info, true, false);
|
||||
rc = cam_soc_util_disable_platform_resource(hw->soc_info, CAM_CLK_SW_CLIENT_IDX,
|
||||
true, false);
|
||||
if (rc) {
|
||||
CAM_ERR(CAM_TPG, "TPG[%d] Disable platform failed %d", hw->hw_idx, rc);
|
||||
return rc;
|
||||
|
Reference in New Issue
Block a user