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

This commit is contained in:
Camera Software Integration
2020-04-29 16:52:03 -07:00
committed by Gerrit - the friendly Code Review server
4 changed files with 241 additions and 0 deletions

View File

@@ -13,10 +13,63 @@
#include "cam_cpas_hw.h"
#include "cam_cpas_hw_intf.h"
#include "cam_cpas_soc.h"
#include "cam_req_mgr_dev.h"
static uint cam_min_camnoc_ib_bw;
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,
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;
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) {
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;
}
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);
if (rc) {
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_tree_node *tree_node = NULL;
int rc = 0, i = 0;
const struct camera_debug_settings *cam_debug = NULL;
CAM_DBG(CAM_CPAS, "control_camnoc_axi_clk=%d",
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))
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;
do_div(intermediate_result, soc_private->camnoc_bus_width);
clk_rate = intermediate_result;

View File

@@ -25,12 +25,16 @@
#include "cam_debug_util.h"
#include "cam_common_util.h"
#include "cam_compat.h"
#include "cam_cpas_hw.h"
#define CAM_REQ_MGR_EVENT_MAX 30
static struct cam_req_mgr_device g_dev;
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)
{
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");
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;
sysfs_fail:
sysfs_remove_file(&dev->kobj, &camera_debug_sysfs_attr.attr);
req_mgr_device_deinit:
cam_req_mgr_core_device_deinit();
req_mgr_core_fail:
@@ -835,6 +847,7 @@ static void cam_req_mgr_component_master_unbind(struct device *dev)
component_unbind_all(dev, NULL);
/* Now proceed with unbinding master */
sysfs_remove_file(&dev->kobj, &camera_debug_sysfs_attr.attr);
cam_req_mgr_core_device_deinit();
cam_req_mgr_util_deinit();
cam_media_device_cleanup();

View File

@@ -4,12 +4,115 @@
*/
#include <linux/io.h>
#include <linux/slab.h>
#include <linux/module.h>
#include "cam_debug_util.h"
static uint debug_mdl;
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)
{

View File

@@ -6,6 +6,8 @@
#ifndef _CAM_DEBUG_UTIL_H_
#define _CAM_DEBUG_UTIL_H_
#include <linux/platform_device.h>
#define CAM_CDM (1 << 0)
#define CAM_CORE (1 << 1)
#define CAM_CPAS (1 << 2)
@@ -44,6 +46,32 @@
#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()
*
@@ -211,4 +239,17 @@ const char *cam_get_module_name(unsigned int module_id);
__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_ */