Bläddra i källkod

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

Savita Patted 4 år sedan
förälder
incheckning
17ab2b21c6

+ 132 - 31
drivers/cam_sensor_module/cam_csiphy/cam_csiphy_core.c

@@ -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;
 }

+ 10 - 1
drivers/cam_sensor_module/cam_csiphy/cam_csiphy_core.h

@@ -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_ */

+ 4 - 0
drivers/cam_sensor_module/cam_csiphy/cam_csiphy_dev.h

@@ -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,

+ 29 - 0
drivers/cam_sensor_module/cam_sensor/cam_sensor_core.c

@@ -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;

+ 30 - 26
drivers/cam_sensor_module/cam_sensor/cam_sensor_dev.h

@@ -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;
 };
 
 /**

+ 13 - 1
drivers/cam_sensor_module/cam_sensor/cam_sensor_soc.c

@@ -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:

+ 9 - 1
drivers/cam_sensor_module/cam_sensor_utils/cam_sensor_util.h

@@ -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_ */