Browse Source

Merge "msm: camera: common: Add sysfs support for bw override" into camera-kernel.lnx.4.0

Camera Software Integration 5 years ago
parent
commit
6d5b2a796c

+ 84 - 0
drivers/cam_cpas/cam_cpas_hw.c

@@ -13,10 +13,63 @@
 #include "cam_cpas_hw.h"
 #include "cam_cpas_hw.h"
 #include "cam_cpas_hw_intf.h"
 #include "cam_cpas_hw_intf.h"
 #include "cam_cpas_soc.h"
 #include "cam_cpas_soc.h"
+#include "cam_req_mgr_dev.h"
 
 
 static uint cam_min_camnoc_ib_bw;
 static uint cam_min_camnoc_ib_bw;
 module_param(cam_min_camnoc_ib_bw, uint, 0644);
 module_param(cam_min_camnoc_ib_bw, uint, 0644);
 
 
+static void cam_cpas_process_bw_overrides(
+	struct cam_cpas_bus_client *bus_client, uint64_t *ab, uint64_t *ib,
+	const struct cam_cpas_debug_settings *cpas_settings)
+{
+	uint64_t curr_ab = *ab;
+	uint64_t curr_ib = *ib;
+	size_t name_len = strlen(bus_client->common_data.name);
+
+	if (!cpas_settings) {
+		CAM_ERR(CAM_CPAS, "Invalid cpas debug settings");
+		return;
+	}
+
+	if (strnstr(bus_client->common_data.name, "cam_hf_0", name_len)) {
+		if (cpas_settings->mnoc_hf_0_ab_bw)
+			*ab = cpas_settings->mnoc_hf_0_ab_bw;
+		if (cpas_settings->mnoc_hf_0_ib_bw)
+			*ib = cpas_settings->mnoc_hf_0_ib_bw;
+	} else if (strnstr(bus_client->common_data.name, "cam_hf_1",
+		name_len)) {
+		if (cpas_settings->mnoc_hf_1_ab_bw)
+			*ab = cpas_settings->mnoc_hf_1_ab_bw;
+		if (cpas_settings->mnoc_hf_0_ib_bw)
+			*ib = cpas_settings->mnoc_hf_1_ib_bw;
+	} else if (strnstr(bus_client->common_data.name, "cam_sf_0",
+		name_len)) {
+		if (cpas_settings->mnoc_sf_0_ab_bw)
+			*ab = cpas_settings->mnoc_sf_0_ab_bw;
+		if (cpas_settings->mnoc_sf_0_ib_bw)
+			*ib = cpas_settings->mnoc_sf_0_ib_bw;
+	} else if (strnstr(bus_client->common_data.name, "cam_sf_1",
+		name_len)) {
+		if (cpas_settings->mnoc_sf_1_ab_bw)
+			*ab = cpas_settings->mnoc_sf_1_ab_bw;
+		if (cpas_settings->mnoc_sf_1_ib_bw)
+			*ib = cpas_settings->mnoc_sf_1_ib_bw;
+	} else if (strnstr(bus_client->common_data.name, "cam_sf_icp",
+		name_len)) {
+		if (cpas_settings->mnoc_sf_icp_ab_bw)
+			*ab = cpas_settings->mnoc_sf_icp_ab_bw;
+		if (cpas_settings->mnoc_sf_icp_ib_bw)
+			*ib = cpas_settings->mnoc_sf_icp_ib_bw;
+	} else {
+		CAM_ERR(CAM_CPAS, "unknown mnoc port: %s, bw override failed",
+			bus_client->common_data.name);
+		return;
+	}
+
+	CAM_INFO(CAM_CPAS,
+		"Overriding mnoc bw for: %s with ab: %llu, ib: %llu, curr_ab: %llu, curr_ib: %llu",
+		bus_client->common_data.name, *ab, *ib, curr_ab, curr_ib);
+}
 
 
 int cam_cpas_util_reg_update(struct cam_hw_info *cpas_hw,
 int cam_cpas_util_reg_update(struct cam_hw_info *cpas_hw,
 	enum cam_cpas_reg_base reg_base, struct cam_cpas_reg *reg_info)
 	enum cam_cpas_reg_base reg_base, struct cam_cpas_reg *reg_info)
@@ -85,6 +138,7 @@ static int cam_cpas_util_vote_bus_client_bw(
 {
 {
 	int rc = 0;
 	int rc = 0;
 	uint64_t min_camnoc_ib_bw = CAM_CPAS_AXI_MIN_CAMNOC_IB_BW;
 	uint64_t min_camnoc_ib_bw = CAM_CPAS_AXI_MIN_CAMNOC_IB_BW;
+	const struct camera_debug_settings *cam_debug = NULL;
 
 
 	if (!bus_client->valid) {
 	if (!bus_client->valid) {
 		CAM_ERR(CAM_CPAS, "bus client: %s not valid",
 		CAM_ERR(CAM_CPAS, "bus client: %s not valid",
@@ -116,6 +170,21 @@ static int cam_cpas_util_vote_bus_client_bw(
 			ib = CAM_CPAS_AXI_MIN_MNOC_IB_BW;
 			ib = CAM_CPAS_AXI_MIN_MNOC_IB_BW;
 	}
 	}
 
 
+	cam_debug = cam_debug_get_settings();
+
+	if (cam_debug && (cam_debug->cpas_settings.mnoc_hf_0_ab_bw ||
+		cam_debug->cpas_settings.mnoc_hf_0_ib_bw ||
+		cam_debug->cpas_settings.mnoc_hf_1_ab_bw ||
+		cam_debug->cpas_settings.mnoc_hf_1_ib_bw ||
+		cam_debug->cpas_settings.mnoc_sf_0_ab_bw ||
+		cam_debug->cpas_settings.mnoc_sf_0_ib_bw ||
+		cam_debug->cpas_settings.mnoc_sf_1_ab_bw ||
+		cam_debug->cpas_settings.mnoc_sf_1_ib_bw ||
+		cam_debug->cpas_settings.mnoc_sf_icp_ab_bw ||
+		cam_debug->cpas_settings.mnoc_sf_icp_ib_bw))
+		cam_cpas_process_bw_overrides(bus_client, &ab, &ib,
+			&cam_debug->cpas_settings);
+
 	rc = cam_soc_bus_client_update_bw(bus_client->soc_bus_client, ab, ib);
 	rc = cam_soc_bus_client_update_bw(bus_client->soc_bus_client, ab, ib);
 	if (rc) {
 	if (rc) {
 		CAM_ERR(CAM_CPAS,
 		CAM_ERR(CAM_CPAS,
@@ -376,6 +445,8 @@ static int cam_cpas_util_set_camnoc_axi_clk_rate(
 	struct cam_cpas *cpas_core = (struct cam_cpas *) cpas_hw->core_info;
 	struct cam_cpas *cpas_core = (struct cam_cpas *) cpas_hw->core_info;
 	struct cam_cpas_tree_node *tree_node = NULL;
 	struct cam_cpas_tree_node *tree_node = NULL;
 	int rc = 0, i = 0;
 	int rc = 0, i = 0;
+	const struct camera_debug_settings *cam_debug = NULL;
+
 
 
 	CAM_DBG(CAM_CPAS, "control_camnoc_axi_clk=%d",
 	CAM_DBG(CAM_CPAS, "control_camnoc_axi_clk=%d",
 		soc_private->control_camnoc_axi_clk);
 		soc_private->control_camnoc_axi_clk);
@@ -415,6 +486,19 @@ static int cam_cpas_util_set_camnoc_axi_clk_rate(
 			soc_private->camnoc_axi_min_ib_bw))
 			soc_private->camnoc_axi_min_ib_bw))
 			required_camnoc_bw = soc_private->camnoc_axi_min_ib_bw;
 			required_camnoc_bw = soc_private->camnoc_axi_min_ib_bw;
 
 
+		cam_debug = cam_debug_get_settings();
+		if (cam_debug && cam_debug->cpas_settings.camnoc_bw) {
+			if (cam_debug->cpas_settings.camnoc_bw <
+				soc_private->camnoc_bus_width)
+				required_camnoc_bw =
+					soc_private->camnoc_bus_width;
+			else
+				required_camnoc_bw =
+					cam_debug->cpas_settings.camnoc_bw;
+			CAM_INFO(CAM_CPAS, "Overriding camnoc bw: %llu",
+				required_camnoc_bw);
+		}
+
 		intermediate_result = required_camnoc_bw;
 		intermediate_result = required_camnoc_bw;
 		do_div(intermediate_result, soc_private->camnoc_bus_width);
 		do_div(intermediate_result, soc_private->camnoc_bus_width);
 		clk_rate = intermediate_result;
 		clk_rate = intermediate_result;

+ 13 - 0
drivers/cam_req_mgr/cam_req_mgr_dev.c

@@ -25,12 +25,16 @@
 #include "cam_debug_util.h"
 #include "cam_debug_util.h"
 #include "cam_common_util.h"
 #include "cam_common_util.h"
 #include "cam_compat.h"
 #include "cam_compat.h"
+#include "cam_cpas_hw.h"
 
 
 #define CAM_REQ_MGR_EVENT_MAX 30
 #define CAM_REQ_MGR_EVENT_MAX 30
 
 
 static struct cam_req_mgr_device g_dev;
 static struct cam_req_mgr_device g_dev;
 struct kmem_cache *g_cam_req_mgr_timer_cachep;
 struct kmem_cache *g_cam_req_mgr_timer_cachep;
 
 
+static struct device_attribute camera_debug_sysfs_attr =
+	__ATTR(debug_node, 0600, NULL, cam_debug_sysfs_node_store);
+
 static int cam_media_device_setup(struct device *dev)
 static int cam_media_device_setup(struct device *dev)
 {
 {
 	int rc;
 	int rc;
@@ -810,9 +814,17 @@ static int cam_req_mgr_component_master_bind(struct device *dev)
 	}
 	}
 
 
 	CAM_INFO(CAM_CRM, "All camera components bound successfully");
 	CAM_INFO(CAM_CRM, "All camera components bound successfully");
+	rc = sysfs_create_file(&dev->kobj, &camera_debug_sysfs_attr.attr);
+	if (rc < 0) {
+		CAM_ERR(CAM_CPAS,
+			"Failed to create debug attribute, rc=%d\n", rc);
+		goto sysfs_fail;
+	}
 
 
 	return rc;
 	return rc;
 
 
+sysfs_fail:
+	sysfs_remove_file(&dev->kobj, &camera_debug_sysfs_attr.attr);
 req_mgr_device_deinit:
 req_mgr_device_deinit:
 	cam_req_mgr_core_device_deinit();
 	cam_req_mgr_core_device_deinit();
 req_mgr_core_fail:
 req_mgr_core_fail:
@@ -835,6 +847,7 @@ static void cam_req_mgr_component_master_unbind(struct device *dev)
 	component_unbind_all(dev, NULL);
 	component_unbind_all(dev, NULL);
 
 
 	/* Now proceed with unbinding master */
 	/* Now proceed with unbinding master */
+	sysfs_remove_file(&dev->kobj, &camera_debug_sysfs_attr.attr);
 	cam_req_mgr_core_device_deinit();
 	cam_req_mgr_core_device_deinit();
 	cam_req_mgr_util_deinit();
 	cam_req_mgr_util_deinit();
 	cam_media_device_cleanup();
 	cam_media_device_cleanup();

+ 103 - 0
drivers/cam_utils/cam_debug_util.c

@@ -4,12 +4,115 @@
  */
  */
 
 
 #include <linux/io.h>
 #include <linux/io.h>
+#include <linux/slab.h>
 #include <linux/module.h>
 #include <linux/module.h>
 
 
 #include "cam_debug_util.h"
 #include "cam_debug_util.h"
 
 
 static uint debug_mdl;
 static uint debug_mdl;
 module_param(debug_mdl, uint, 0644);
 module_param(debug_mdl, uint, 0644);
+struct camera_debug_settings cam_debug;
+
+const struct camera_debug_settings *cam_debug_get_settings()
+{
+	return &cam_debug;
+}
+
+static int cam_debug_parse_cpas_settings(const char *setting, u64 value)
+{
+	if (!strcmp(setting, "camnoc_bw")) {
+		cam_debug.cpas_settings.camnoc_bw = value;
+	} else if (!strcmp(setting, "mnoc_hf_0_ab_bw")) {
+		cam_debug.cpas_settings.mnoc_hf_0_ab_bw = value;
+	} else if (!strcmp(setting, "mnoc_hf_0_ib_bw")) {
+		cam_debug.cpas_settings.mnoc_hf_0_ib_bw = value;
+	} else if (!strcmp(setting, "mnoc_hf_1_ab_bw")) {
+		cam_debug.cpas_settings.mnoc_hf_1_ab_bw = value;
+	} else if (!strcmp(setting, "mnoc_hf_1_ib_bw")) {
+		cam_debug.cpas_settings.mnoc_hf_1_ib_bw = value;
+	} else if (!strcmp(setting, "mnoc_sf_0_ab_bw")) {
+		cam_debug.cpas_settings.mnoc_sf_0_ab_bw = value;
+	} else if (!strcmp(setting, "mnoc_sf_0_ib_bw")) {
+		cam_debug.cpas_settings.mnoc_sf_0_ib_bw = value;
+	} else if (!strcmp(setting, "mnoc_sf_1_ab_bw")) {
+		cam_debug.cpas_settings.mnoc_sf_1_ab_bw = value;
+	} else if (!strcmp(setting, "mnoc_sf_1_ib_bw")) {
+		cam_debug.cpas_settings.mnoc_sf_1_ib_bw = value;
+	} else if (!strcmp(setting, "mnoc_sf_icp_ab_bw")) {
+		cam_debug.cpas_settings.mnoc_sf_icp_ab_bw = value;
+	} else if (!strcmp(setting, "mnoc_sf_icp_ib_bw")) {
+		cam_debug.cpas_settings.mnoc_sf_icp_ib_bw = value;
+	} else {
+		CAM_ERR(CAM_UTIL, "Unsupported cpas sysfs entry");
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
+ssize_t cam_debug_sysfs_node_store(struct device *dev,
+		struct device_attribute *attr, const char *buf, size_t count)
+{
+	int rc = 0;
+	char *local_buf = NULL, *local_buf_temp = NULL;
+	char *driver;
+	char *setting = NULL;
+	char *value_str = NULL;
+	u64 value;
+
+	CAM_INFO(CAM_UTIL, "Sysfs debug attr name:[%s] buf:[%s] bytes:[%d]",
+		attr->attr.name, buf, count);
+	local_buf = kmemdup(buf, (count + sizeof(char)), GFP_KERNEL);
+	local_buf_temp = local_buf;
+	driver = strsep(&local_buf, "#");
+	if (!driver) {
+		CAM_ERR(CAM_UTIL,
+			"Invalid input driver name buf:[%s], count:%d",
+			buf, count);
+		goto error;
+	}
+
+	setting = strsep(&local_buf, "=");
+	if (!setting) {
+		CAM_ERR(CAM_UTIL, "Invalid input setting buf:[%s], count:%d",
+			buf, count);
+		goto error;
+	}
+
+	value_str = strsep(&local_buf, "=");
+	if (!value_str) {
+		CAM_ERR(CAM_UTIL, "Invalid input value buf:[%s], count:%d",
+			buf, count);
+		goto error;
+	}
+
+	rc = kstrtou64(value_str, 0, &value);
+	if (rc < 0) {
+		CAM_ERR(CAM_UTIL, "Error converting value:[%s], buf:[%s]",
+			value_str, buf);
+		goto error;
+	}
+
+	CAM_INFO(CAM_UTIL,
+		"Processing sysfs store for driver:[%s], setting:[%s], value:[%llu]",
+		driver, setting, value);
+
+	if (!strcmp(driver, "cpas")) {
+		rc = cam_debug_parse_cpas_settings(setting, value);
+		if (rc)
+			goto error;
+	} else {
+		CAM_ERR(CAM_UTIL, "Unsupported driver in camera debug node");
+		goto error;
+	}
+
+	kfree(local_buf_temp);
+	return count;
+
+error:
+	kfree(local_buf_temp);
+	return -EPERM;
+}
 
 
 const char *cam_get_module_name(unsigned int module_id)
 const char *cam_get_module_name(unsigned int module_id)
 {
 {

+ 41 - 0
drivers/cam_utils/cam_debug_util.h

@@ -6,6 +6,8 @@
 #ifndef _CAM_DEBUG_UTIL_H_
 #ifndef _CAM_DEBUG_UTIL_H_
 #define _CAM_DEBUG_UTIL_H_
 #define _CAM_DEBUG_UTIL_H_
 
 
+#include <linux/platform_device.h>
+
 #define CAM_CDM        (1 << 0)
 #define CAM_CDM        (1 << 0)
 #define CAM_CORE       (1 << 1)
 #define CAM_CORE       (1 << 1)
 #define CAM_CPAS       (1 << 2)
 #define CAM_CPAS       (1 << 2)
@@ -44,6 +46,32 @@
 
 
 #define STR_BUFFER_MAX_LENGTH  1024
 #define STR_BUFFER_MAX_LENGTH  1024
 
 
+/**
+ * struct cam_cpas_debug_settings - Sysfs debug settings for cpas driver
+ */
+struct cam_cpas_debug_settings {
+	uint64_t mnoc_hf_0_ab_bw;
+	uint64_t mnoc_hf_0_ib_bw;
+	uint64_t mnoc_hf_1_ab_bw;
+	uint64_t mnoc_hf_1_ib_bw;
+	uint64_t mnoc_sf_0_ab_bw;
+	uint64_t mnoc_sf_0_ib_bw;
+	uint64_t mnoc_sf_1_ab_bw;
+	uint64_t mnoc_sf_1_ib_bw;
+	uint64_t mnoc_sf_icp_ab_bw;
+	uint64_t mnoc_sf_icp_ib_bw;
+	uint64_t camnoc_bw;
+};
+
+/**
+ * struct camera_debug_settings - Sysfs debug settings for camera
+ *
+ * @cpas_settings: Debug settings for cpas driver.
+ */
+struct camera_debug_settings {
+	struct cam_cpas_debug_settings cpas_settings;
+};
+
 /*
 /*
  *  cam_debug_log()
  *  cam_debug_log()
  *
  *
@@ -211,4 +239,17 @@ const char *cam_get_module_name(unsigned int module_id);
 				__LINE__, ##args);                         \
 				__LINE__, ##args);                         \
 	})
 	})
 
 
+/**
+ * @brief : API to get camera debug settings
+ * @return const struct camera_debug_settings pointer.
+ */
+const struct camera_debug_settings *cam_debug_get_settings(void);
+
+/**
+ * @brief : API to parse and store input from sysfs debug node
+ * @return Number of bytes read from buffer on success, or -EPERM on error.
+ */
+ssize_t cam_debug_sysfs_node_store(struct device *dev,
+		struct device_attribute *attr, const char *buf, size_t count);
+
 #endif /* _CAM_DEBUG_UTIL_H_ */
 #endif /* _CAM_DEBUG_UTIL_H_ */