EDP: tegra: AP40X add option for core cap table
Rick Song [Wed, 31 Jul 2013 05:54:19 +0000 (13:54 +0800)]
ap40x, add option to select different sysedp core cap table

SYS_EDP_PROFILE_NORMAL: sysedp core cap table
SYS_EDP_PROFILE_FAVOR_GPU: sysedp core cap alternate

Bug 1329643
Bug 1339878

Change-Id: I3226205f0ad5a53d7985d351fbb8e5b26272bad9
Signed-off-by: Rick Song <ricks@nvidia.com>
Signed-off-by: Sivaram Nair <sivaramn@nvidia.com>
Reviewed-on: http://git-master/r/256138
Reviewed-by: Automatic_Commit_Validation_User
Reviewed-by: Andy Carman <acarman@nvidia.com>
Tested-by: Andy Carman <acarman@nvidia.com>
Reviewed-by: Diwakar Tundlam <dtundlam@nvidia.com>
Reviewed-by: Vandana Bansal <vandanab@nvidia.com>

drivers/edp/tegra_core.c
include/linux/platform_data/tegra_edp.h

index 42ef066..d5c82d3 100644 (file)
@@ -35,6 +35,7 @@ struct freqcap {
 static unsigned int gpu_high_threshold = 700;
 static unsigned int gpu_window = 80;
 static unsigned int gain_factor = 130;
+static unsigned int core_profile = TEGRA_SYSEDP_PROFILE_NORMAL;
 static unsigned int online_cpu_count;
 static bool gpu_busy;
 static unsigned int core_state;
@@ -53,6 +54,11 @@ static struct freqcap forced_caps;
 static struct freqcap cur_caps;
 static DEFINE_MUTEX(core_lock);
 
+static const char *profile_names[TEGRA_SYSEDP_PROFILE_NUM] = {
+       [TEGRA_SYSEDP_PROFILE_NORMAL]   = "profile_normal",
+       [TEGRA_SYSEDP_PROFILE_HIGHCORE] = "profile_highcore"
+};
+
 /* To save some cycles from a linear search */
 static unsigned int cpu_lut_match(unsigned int power,
                struct tegra_system_edp_entry *lut, unsigned int lutlen)
@@ -179,7 +185,10 @@ static void update_cur_corecap(void)
        power = core_edp_states[core_state] * gain_factor / 100;
        power += core_loan;
        i = core_platdata->corecap_size - 1;
-       cap = core_platdata->corecap + i;
+
+       cap = core_profile == TEGRA_SYSEDP_PROFILE_HIGHCORE ?
+                       core_platdata->high_corecap : core_platdata->corecap;
+       cap += i;
 
        for (; i >= 0; i--, cap--) {
                if (cap->power <= power) {
@@ -289,8 +298,47 @@ out:
        return r ?: count;
 }
 
+static ssize_t core_profile_show(struct edp_client *c,
+               struct edp_client_attribute *attr, char *buf)
+{
+       return sprintf(buf, "%s\n", profile_names[core_profile]);
+}
+
+static ssize_t core_profile_store(struct edp_client *c,
+               struct edp_client_attribute *attr, const char *buf,
+               size_t count)
+{
+       int i;
+       size_t l;
+       const char *name;
+
+       for (i = 0; i < ARRAY_SIZE(profile_names); i++) {
+               name = profile_names[i];
+               l = strlen(name);
+               if ((l <= count) && (strncmp(buf, name, l) == 0))
+                       break;
+       }
+
+       if (i == ARRAY_SIZE(profile_names))
+               return -ENOENT;
+
+       if (i == TEGRA_SYSEDP_PROFILE_HIGHCORE && !core_platdata->high_corecap)
+               return -ENODEV;
+
+       mutex_lock(&core_lock);
+
+       core_profile = i;
+       update_cur_corecap();
+       __do_cap_control();
+
+       mutex_unlock(&core_lock);
+
+       return count;
+}
+
 struct edp_client_attribute core_attrs[] = {
        __ATTR(set_request, 0200, NULL, core_request_store),
+       __ATTR(profile, 0644, core_profile_show, core_profile_store),
        __ATTR_NULL
 };
 
index 9af311c..0e4fa17 100644 (file)
@@ -42,10 +42,17 @@ struct tegra_sysedp_platform_data {
        struct tegra_system_edp_entry *cpufreq_lim;
        unsigned int cpufreq_lim_size;
        struct tegra_sysedp_corecap *corecap;
+       struct tegra_sysedp_corecap *high_corecap;
        unsigned int corecap_size;
        unsigned int init_req_watts;
 };
 
+enum tegra_sysedp_profile {
+       TEGRA_SYSEDP_PROFILE_NORMAL,
+       TEGRA_SYSEDP_PROFILE_HIGHCORE,
+       TEGRA_SYSEDP_PROFILE_NUM
+};
+
 #ifdef CONFIG_EDP_FRAMEWORK
 void tegra_edp_notify_gpu_load(unsigned int load);
 #else