Merge "msm: camera: common: Add AON support" into camera-kernel.lnx.5.0

This commit is contained in:
Savita Patted
2021-03-23 18:44:50 -07:00
committed by Gerrit - the friendly Code Review server
7 changed files with 227 additions and 60 deletions

View File

@@ -43,6 +43,7 @@ module_param(csiphy_dump, int, 0644);
struct g_csiphy_data {
void __iomem *base_address;
uint8_t is_3phase;
uint32_t cpas_handle;
};
static struct g_csiphy_data g_phy_data[MAX_CSIPHY] = {{0, 0}};
@@ -1065,6 +1066,101 @@ static int cam_csiphy_update_lane(
return 0;
}
static int cam_csiphy_cpas_ops(
uint32_t cpas_handle, bool start)
{
int rc = 0;
struct cam_ahb_vote ahb_vote;
struct cam_axi_vote axi_vote = {0};
if (start) {
ahb_vote.type = CAM_VOTE_ABSOLUTE;
ahb_vote.vote.level = CAM_LOWSVS_VOTE;
axi_vote.num_paths = 1;
axi_vote.axi_path[0].path_data_type =
CAM_AXI_PATH_DATA_ALL;
axi_vote.axi_path[0].transac_type =
CAM_AXI_TRANSACTION_WRITE;
axi_vote.axi_path[0].camnoc_bw =
CAM_CPAS_DEFAULT_AXI_BW;
axi_vote.axi_path[0].mnoc_ab_bw =
CAM_CPAS_DEFAULT_AXI_BW;
axi_vote.axi_path[0].mnoc_ib_bw =
CAM_CPAS_DEFAULT_AXI_BW;
rc = cam_cpas_start(cpas_handle,
&ahb_vote, &axi_vote);
if (rc < 0) {
CAM_ERR(CAM_CSIPHY, "voting CPAS: %d", rc);
return rc;
}
CAM_DBG(CAM_CSIPHY, "CPAS START");
} else {
rc = cam_cpas_stop(cpas_handle);
if (rc < 0) {
CAM_ERR(CAM_CSIPHY, "de-voting CPAS: %d", rc);
return rc;
}
CAM_DBG(CAM_CSIPHY, "CPAS STOPPED");
}
return rc;
}
int cam_csiphy_util_update_aon_ops(
bool get_access, uint32_t phy_idx)
{
uint32_t aon_config = 0;
uint32_t cpas_hdl = 0;
int rc = 0;
if (phy_idx > MAX_CSIPHY) {
CAM_ERR(CAM_CSIPHY, "Null device");
return -ENODEV;
}
cpas_hdl = g_phy_data[phy_idx].cpas_handle;
CAM_DBG(CAM_CSIPHY, "PHY idx: %d", phy_idx);
rc = cam_csiphy_cpas_ops(cpas_hdl, true);
if (rc) {
if (rc == -EPERM) {
CAM_WARN(CAM_CSIPHY,
"CPHY: %d is already in start state");
} else {
CAM_ERR(CAM_CSIPHY, "voting CPAS: %d failed", rc);
return rc;
}
}
cam_cpas_reg_read(cpas_hdl, CAM_CPAS_REG_CPASTOP,
CAM_CSIPHY_CPAS_AON_SEL_ADDR, true, &aon_config);
if (get_access) {
aon_config &= ~(CAM_CSIPHY_CPAS_MAIN_CAM_SEL |
CAM_CSIPHY_CPAS_MCLK_SEL);
CAM_DBG(CAM_CSIPHY,
"Selecting MainCamera over AON Camera");
} else if (!get_access) {
aon_config |= (CAM_CSIPHY_CPAS_MAIN_CAM_SEL |
CAM_CSIPHY_CPAS_MCLK_SEL);
CAM_DBG(CAM_CSIPHY,
"Releasing MainCamera to AON Camera");
}
CAM_DBG(CAM_CSIPHY, "value of aon_config = %u", aon_config);
if (cam_cpas_reg_write(cpas_hdl, CAM_CPAS_REG_CPASTOP,
CAM_CSIPHY_CPAS_AON_SEL_ADDR, true, aon_config)) {
CAM_ERR(CAM_CSIPHY,
"CPAS AON sel register write failed");
}
if (rc != -EPERM)
cam_csiphy_cpas_ops(cpas_hdl, false);
return rc;
}
int32_t cam_csiphy_core_cfg(void *phy_dev,
void *arg)
{
@@ -1145,14 +1241,16 @@ int32_t cam_csiphy_core_cfg(void *phy_dev,
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)
if (csiphy_acq_params.csiphy_3phase) {
CAM_DBG(CAM_CSIPHY, "3Phase ComboMode");
csiphy_dev->session_max_device_support =
CSIPHY_MAX_INSTANCES_PER_PHY;
else
} else {
csiphy_dev->session_max_device_support =
CSIPHY_MAX_INSTANCES_PER_PHY - 1;
CAM_DBG(CAM_CSIPHY, "2Phase ComboMode");
}
}
if (csiphy_acq_params.cphy_dphy_combo_mode == 1) {
CAM_DBG(CAM_CSIPHY,
"cphy_dphy_combo_mode stream detected");
@@ -1206,6 +1304,7 @@ int32_t cam_csiphy_core_cfg(void *phy_dev,
csiphy_dev->acquire_count++;
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;
}
@@ -1226,6 +1325,7 @@ int32_t cam_csiphy_core_cfg(void *phy_dev,
int32_t offset, rc = 0;
struct cam_start_stop_dev_cmd config;
CAM_DBG(CAM_CSIPHY, "STOP_DEV CALLED");
rc = copy_from_user(&config, (void __user *)cmd->handle,
sizeof(config));
if (rc < 0) {
@@ -1287,9 +1387,10 @@ int32_t cam_csiphy_core_cfg(void *phy_dev,
if (rc < 0)
CAM_ERR(CAM_CSIPHY, "Failed in csiphy release");
rc = cam_cpas_stop(csiphy_dev->cpas_handle);
if (rc < 0)
CAM_ERR(CAM_CSIPHY, "de-voting CPAS: %d", rc);
if (cam_csiphy_cpas_ops(csiphy_dev->cpas_handle, false)) {
CAM_ERR(CAM_CSIPHY, "Failed in de-voting CPAS");
rc = -EFAULT;
}
CAM_DBG(CAM_CSIPHY, "All PHY devices stopped");
csiphy_dev->csiphy_state = CAM_CSIPHY_ACQUIRE;
@@ -1305,6 +1406,8 @@ int32_t cam_csiphy_core_cfg(void *phy_dev,
int32_t offset;
struct cam_release_dev_cmd release;
CAM_DBG(CAM_CSIPHY, "RELEASE_DEV Called");
if (!csiphy_dev->acquire_count) {
CAM_ERR(CAM_CSIPHY, "No valid devices to release");
rc = -EINVAL;
@@ -1361,6 +1464,7 @@ int32_t cam_csiphy_core_cfg(void *phy_dev,
case CAM_CONFIG_DEV: {
struct cam_config_dev_cmd config;
CAM_DBG(CAM_CSIPHY, "CONFIG_DEV Called");
if (copy_from_user(&config,
u64_to_user_ptr(cmd->handle),
sizeof(config))) {
@@ -1375,12 +1479,11 @@ int32_t cam_csiphy_core_cfg(void *phy_dev,
break;
}
case CAM_START_DEV: {
struct cam_ahb_vote ahb_vote;
struct cam_axi_vote axi_vote = {0};
struct cam_start_stop_dev_cmd config;
int32_t offset;
int clk_vote_level = -1;
CAM_DBG(CAM_CSIPHY, "START_DEV Called");
rc = copy_from_user(&config, (void __user *)cmd->handle,
sizeof(config));
if (rc < 0) {
@@ -1466,21 +1569,8 @@ int32_t cam_csiphy_core_cfg(void *phy_dev,
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;
axi_vote.axi_path[0].path_data_type = CAM_AXI_PATH_DATA_ALL;
axi_vote.axi_path[0].transac_type = CAM_AXI_TRANSACTION_WRITE;
axi_vote.axi_path[0].camnoc_bw = CAM_CPAS_DEFAULT_AXI_BW;
axi_vote.axi_path[0].mnoc_ab_bw = CAM_CPAS_DEFAULT_AXI_BW;
axi_vote.axi_path[0].mnoc_ib_bw = CAM_CPAS_DEFAULT_AXI_BW;
rc = cam_cpas_start(csiphy_dev->cpas_handle,
&ahb_vote, &axi_vote);
if (rc < 0) {
rc = cam_csiphy_cpas_ops(csiphy_dev->cpas_handle, true);
if (rc) {
CAM_ERR(CAM_CSIPHY, "voting CPAS: %d", rc);
goto release_mutex;
}
@@ -1491,9 +1581,8 @@ int32_t cam_csiphy_core_cfg(void *phy_dev,
CAM_CPAS_HW_IDX_ANY, NULL)) {
CAM_ERR(CAM_CSIPHY,
"sec_cam: camera fuse bit not set");
cam_cpas_stop(csiphy_dev->cpas_handle);
rc = -EINVAL;
goto release_mutex;
goto cpas_stop;
}
rc = cam_csiphy_notify_secure_mode(
@@ -1502,16 +1591,14 @@ int32_t cam_csiphy_core_cfg(void *phy_dev,
if (rc < 0) {
csiphy_dev->csiphy_info[offset].secure_mode =
CAM_SECURE_MODE_NON_SECURE;
cam_cpas_stop(csiphy_dev->cpas_handle);
goto release_mutex;
goto cpas_stop;
}
}
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;
goto cpas_stop;
}
rc = cam_csiphy_config_dev(csiphy_dev, config.dev_handle);
if (csiphy_dump == 1)
@@ -1520,8 +1607,7 @@ int32_t cam_csiphy_core_cfg(void *phy_dev,
if (rc < 0) {
CAM_ERR(CAM_CSIPHY, "cam_csiphy_config_dev failed");
cam_csiphy_disable_hw(csiphy_dev);
cam_cpas_stop(csiphy_dev->cpas_handle);
goto release_mutex;
goto cpas_stop;
}
csiphy_dev->start_dev_count++;
@@ -1554,8 +1640,15 @@ int32_t cam_csiphy_core_cfg(void *phy_dev,
sizeof(struct cam_config_dev_cmd))) {
CAM_ERR(CAM_CSIPHY, "failed copy config ext\n");
rc = -EFAULT;
goto release_mutex;
} else {
rc = cam_csiphy_external_cmd(csiphy_dev, &submit_cmd);
if (rc) {
CAM_ERR(CAM_CSIPHY,
"exteranal command configuration failed rc: %d",
rc);
goto release_mutex;
}
}
break;
}
@@ -1565,6 +1658,12 @@ int32_t cam_csiphy_core_cfg(void *phy_dev,
goto release_mutex;
}
mutex_unlock(&csiphy_dev->mutex);
return rc;
cpas_stop:
if (cam_csiphy_cpas_ops(csiphy_dev->cpas_handle, false))
CAM_ERR(CAM_CSIPHY, "cpas stop failed");
release_mutex:
mutex_unlock(&csiphy_dev->mutex);
@@ -1586,4 +1685,6 @@ void cam_csiphy_register_baseaddress(struct csiphy_device *csiphy_dev)
g_phy_data[csiphy_dev->soc_info.index].base_address =
csiphy_dev->soc_info.reg_map[0].mem_base;
g_phy_data[csiphy_dev->soc_info.index].cpas_handle =
csiphy_dev->cpas_handle;
}

View File

@@ -1,6 +1,6 @@
/* SPDX-License-Identifier: GPL-2.0-only */
/*
* Copyright (c) 2017-2018, 2020 The Linux Foundation. All rights reserved.
* Copyright (c) 2017-2018, 2020-2021 The Linux Foundation. All rights reserved.
*/
#ifndef _CAM_CSIPHY_CORE_H_
@@ -56,4 +56,13 @@ void cam_csiphy_shutdown(struct csiphy_device *csiphy_dev);
*/
void cam_csiphy_register_baseaddress(struct csiphy_device *csiphy_dev);
/**
* @get_access : Get Access for the Main Camera over AON Camera
* @phy_idx : To acquire the correct PHY hw to do the operation with
*
* This API provides Utility/helper function to program the MUX for
* correct PHY hw.
*
*/
int cam_csiphy_util_update_aon_ops(bool get_access, uint32_t phy_idx);
#endif /* _CAM_CSIPHY_CORE_H_ */

View File

@@ -64,6 +64,10 @@
#define DPHY_LANE_3 BIT(6)
#define DPHY_CLK_LN BIT(7)
#define CAM_CSIPHY_CPAS_AON_SEL_ADDR 0x001E0
#define CAM_CSIPHY_CPAS_MAIN_CAM_SEL BIT(0)
#define CAM_CSIPHY_CPAS_MCLK_SEL BIT(8)
enum cam_csiphy_state {
CAM_CSIPHY_INIT,
CAM_CSIPHY_ACQUIRE,

View File

@@ -1287,6 +1287,20 @@ int cam_sensor_power_up(struct cam_sensor_ctrl_t *s_ctrl)
}
}
if (s_ctrl->is_aon_user) {
CAM_DBG(CAM_SENSOR,
"Setup for Main Camera with csiphy index: %d",
s_ctrl->sensordata->subdev_id[SUB_MODULE_CSIPHY]);
rc = cam_sensor_util_aon_ops(true,
s_ctrl->sensordata->subdev_id[SUB_MODULE_CSIPHY]);
if (rc) {
CAM_WARN(CAM_SENSOR,
"Main camera access opertion is not successful rc: %d",
rc);
return rc;
}
}
rc = cam_sensor_core_power_up(power_info, soc_info);
if (rc < 0) {
CAM_ERR(CAM_SENSOR, "power up the core is failed:%d", rc);
@@ -1326,6 +1340,7 @@ int cam_sensor_power_down(struct cam_sensor_ctrl_t *s_ctrl)
CAM_ERR(CAM_SENSOR, "failed: power_info %pK", power_info);
return -EINVAL;
}
rc = cam_sensor_util_power_down(power_info, soc_info);
if (rc < 0) {
CAM_ERR(CAM_SENSOR, "power down the core is failed:%d", rc);
@@ -1342,6 +1357,20 @@ int cam_sensor_power_down(struct cam_sensor_ctrl_t *s_ctrl)
}
}
if (s_ctrl->is_aon_user) {
CAM_DBG(CAM_SENSOR,
"Setup for AON FW with csiphy index: %d",
s_ctrl->sensordata->subdev_id[SUB_MODULE_CSIPHY]);
rc = cam_sensor_util_aon_ops(false,
s_ctrl->sensordata->subdev_id[SUB_MODULE_CSIPHY]);
if (rc) {
CAM_WARN(CAM_SENSOR,
"AON FW access opertion is not successful rc: %d",
rc);
return rc;
}
}
camera_io_release(&(s_ctrl->io_master_info));
return rc;

View File

@@ -1,6 +1,6 @@
/* SPDX-License-Identifier: GPL-2.0-only */
/*
* Copyright (c) 2017-2019, The Linux Foundation. All rights reserved.
* Copyright (c) 2017-2019, 2021 The Linux Foundation. All rights reserved.
*/
#ifndef _CAM_SENSOR_DEV_H_
@@ -86,33 +86,37 @@ struct sensor_intf_params {
* @last_flush_req: Last request to flush
* @pipeline_delay: Sensor pipeline delay
* @sensor_name: Sensor name
* @is_aon_user: To determine whether sensor is AON user or not
*/
struct cam_sensor_ctrl_t {
char device_name[CAM_CTX_DEV_NAME_MAX_LENGTH];
struct platform_device *pdev;
struct cam_hw_soc_info soc_info;
struct mutex cam_sensor_mutex;
struct cam_sensor_board_info *sensordata;
enum cci_i2c_master_t cci_i2c_master;
enum cci_device_num cci_num;
struct camera_io_master io_master_info;
enum cam_sensor_state_t sensor_state;
uint8_t is_probe_succeed;
uint32_t id;
struct device_node *of_node;
struct cam_subdev v4l2_dev_str;
uint8_t sensor_probe_addr_type;
uint8_t sensor_probe_data_type;
struct i2c_data_settings i2c_data;
struct cam_sensor_query_cap sensor_info;
struct sensor_intf_params bridge_intf;
uint32_t streamon_count;
uint32_t streamoff_count;
int bob_reg_index;
bool bob_pwm_switch;
uint32_t last_flush_req;
uint16_t pipeline_delay;
char sensor_name[CAM_SENSOR_NAME_MAX_SIZE];
char device_name[
CAM_CTX_DEV_NAME_MAX_LENGTH];
struct platform_device *pdev;
struct cam_hw_soc_info soc_info;
struct mutex cam_sensor_mutex;
struct cam_sensor_board_info *sensordata;
enum cci_i2c_master_t cci_i2c_master;
enum cci_device_num cci_num;
struct camera_io_master io_master_info;
enum cam_sensor_state_t sensor_state;
uint8_t is_probe_succeed;
uint32_t id;
struct device_node *of_node;
struct cam_subdev v4l2_dev_str;
uint8_t sensor_probe_addr_type;
uint8_t sensor_probe_data_type;
struct i2c_data_settings i2c_data;
struct cam_sensor_query_cap sensor_info;
struct sensor_intf_params bridge_intf;
uint32_t streamon_count;
uint32_t streamoff_count;
int bob_reg_index;
bool bob_pwm_switch;
uint32_t last_flush_req;
uint16_t pipeline_delay;
char sensor_name[
CAM_SENSOR_NAME_MAX_SIZE];
bool is_aon_user;
};
/**

View File

@@ -1,6 +1,6 @@
// SPDX-License-Identifier: GPL-2.0-only
/*
* Copyright (c) 2017-2019, The Linux Foundation. All rights reserved.
* Copyright (c) 2017-2019, 2021 The Linux Foundation. All rights reserved.
*/
#include <linux/of.h>
@@ -203,6 +203,18 @@ static int32_t cam_sensor_driver_get_dt_data(struct cam_sensor_ctrl_t *s_ctrl)
sensordata->pos_yaw = 360;
}
if (!of_property_read_bool(of_node, "aon-user")) {
CAM_DBG(CAM_SENSOR,
"SENSOR cell_idx: %d not use for AON usecase",
s_ctrl->soc_info.index);
s_ctrl->is_aon_user = false;
} else {
CAM_DBG(CAM_SENSOR,
"SENSOR cell_idx: %d is user for AON usecase",
s_ctrl->soc_info.index);
s_ctrl->is_aon_user = true;
}
return rc;
FREE_SENSOR_DATA:

View File

@@ -1,6 +1,6 @@
/* SPDX-License-Identifier: GPL-2.0-only */
/*
* Copyright (c) 2017-2020, The Linux Foundation. All rights reserved.
* Copyright (c) 2017-2021, The Linux Foundation. All rights reserved.
*/
#ifndef _CAM_SENSOR_UTIL_H_
@@ -18,6 +18,7 @@
#include "cam_soc_util.h"
#include "cam_debug_util.h"
#include "cam_sensor_io.h"
#include "cam_csiphy_core.h"
#define INVALID_VREG 100
#define RES_MGR_GPIO_NEED_HOLD 1
@@ -81,4 +82,11 @@ int cam_sensor_bob_pwm_mode_switch(struct cam_hw_soc_info *soc_info,
int bob_reg_idx, bool flag);
bool cam_sensor_util_check_gpio_is_shared(struct cam_hw_soc_info *soc_info);
static inline int cam_sensor_util_aon_ops(bool get_access, uint32_t phy_idx)
{
CAM_DBG(CAM_SENSOR, "Updating Main/Aon operation");
return cam_csiphy_util_update_aon_ops(get_access, phy_idx);
}
#endif /* _CAM_SENSOR_UTIL_H_ */