summaryrefslogtreecommitdiffstats
path: root/pvr-source/services4/system/omap4/sgxfreq.c
diff options
context:
space:
mode:
Diffstat (limited to 'pvr-source/services4/system/omap4/sgxfreq.c')
-rwxr-xr-xpvr-source/services4/system/omap4/sgxfreq.c610
1 files changed, 0 insertions, 610 deletions
diff --git a/pvr-source/services4/system/omap4/sgxfreq.c b/pvr-source/services4/system/omap4/sgxfreq.c
deleted file mode 100755
index 65543a5..0000000
--- a/pvr-source/services4/system/omap4/sgxfreq.c
+++ /dev/null
@@ -1,610 +0,0 @@
-/*
- * Copyright (C) 2012 Texas Instruments, Inc
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 as published by
- * the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
- * more details.
- *
- * You should have received a copy of the GNU General Public License along with
- * this program. If not, see <http://www.gnu.org/licenses/>.
- */
-
-#include <linux/opp.h>
-#include <plat/gpu.h>
-#include "sgxfreq.h"
-
-static struct sgxfreq_data {
- int freq_cnt;
- unsigned long *freq_list;
- unsigned long freq;
- unsigned long freq_request;
- unsigned long freq_limit;
- unsigned long total_idle_time;
- unsigned long total_active_time;
- struct mutex freq_mutex;
- struct list_head gov_list;
- struct sgxfreq_governor *gov;
- struct mutex gov_mutex;
- struct sgxfreq_sgx_data sgx_data;
- struct device *dev;
- struct gpu_platform_data *pdata;
-} sfd;
-
-/* Governor init/deinit functions */
-int onoff_init(void);
-int onoff_deinit(void);
-int activeidle_init(void);
-int activeidle_deinit(void);
-int on3demand_init(void);
-int on3demand_deinit(void);
-int userspace_init(void);
-int userspace_deinit(void);
-
-
-typedef int sgxfreq_gov_init_t(void);
-sgxfreq_gov_init_t *sgxfreq_gov_init[] = {
- onoff_init,
- activeidle_init,
- on3demand_init,
- userspace_init,
- NULL,
-};
-
-typedef int sgxfreq_gov_deinit_t(void);
-sgxfreq_gov_deinit_t *sgxfreq_gov_deinit[] = {
- onoff_deinit,
- activeidle_deinit,
- on3demand_deinit,
- userspace_deinit,
- NULL,
-};
-
-#define SGXFREQ_DEFAULT_GOV_NAME "on3demand"
-static unsigned long _idle_curr_time;
-static unsigned long _idle_prev_time;
-static unsigned long _active_curr_time;
-static unsigned long _active_prev_time;
-
-#if defined(CONFIG_THERMAL_FRAMEWORK)
-int cool_init(void);
-void cool_deinit(void);
-#endif
-
-/*********************** begin sysfs interface ***********************/
-
-struct kobject *sgxfreq_kobj;
-
-static ssize_t show_frequency_list(struct device *dev,
- struct device_attribute *attr,
- char *buf)
-{
- int i;
- ssize_t count = 0;
-
- for (i = 0; i < sfd.freq_cnt; i++)
- count += sprintf(&buf[count], "%lu ", sfd.freq_list[i]);
- count += sprintf(&buf[count], "\n");
-
- return count;
-}
-
-static ssize_t show_frequency_request(struct device *dev,
- struct device_attribute *attr,
- char *buf)
-{
- return sprintf(buf, "%lu\n", sfd.freq_request);
-}
-
-static ssize_t show_frequency_limit(struct device *dev,
- struct device_attribute *attr,
- char *buf)
-{
- return sprintf(buf, "%lu\n", sfd.freq_limit);
-}
-
-/*
- * sysfs interface to store sgxfreq frequency limit
- * author: ketut.kumajaya@gmail.com
-*/
-static ssize_t store_frequency_limit(struct device *dev,
- struct device_attribute *attr,
- const char *buf, size_t count)
-{
- unsigned long freq_limit;
-
- if (kstrtoul(buf, 0, &freq_limit)) {
- pr_err("sgxfreq: failed storing frequency_limit\n");
- return -EINVAL;
- }
-
- freq_limit = sgxfreq_set_freq_limit(freq_limit);
- pr_info("sgxfreq: frequency_limit=%lu\n", freq_limit);
- return count;
-}
-
-static ssize_t show_frequency(struct device *dev,
- struct device_attribute *attr,
- char *buf)
-{
- return sprintf(buf, "%lu\n", sfd.freq);
-}
-
-static ssize_t show_stat(struct device *dev,
- struct device_attribute *attr,
- char *buf)
-{
- return sprintf(buf, "gpu %lu %lu\n",
- sfd.total_active_time, sfd.total_idle_time);
-}
-
-static ssize_t show_governor_list(struct device *dev,
- struct device_attribute *attr,
- char *buf)
-{
- ssize_t i = 0;
- struct sgxfreq_governor *t;
-
- list_for_each_entry(t, &sfd.gov_list, governor_list) {
- if (i >= (ssize_t) ((PAGE_SIZE / sizeof(char))
- - (SGXFREQ_NAME_LEN + 2)))
- goto out;
- i += scnprintf(&buf[i], SGXFREQ_NAME_LEN, "%s ", t->name);
- }
-out:
- i += sprintf(&buf[i], "\n");
- return i;
-}
-
-static ssize_t show_governor(struct device *dev,
- struct device_attribute *attr, char *buf)
-{
- if (sfd.gov)
- return scnprintf(buf, SGXFREQ_NAME_LEN, "%s\n", sfd.gov->name);
-
- return sprintf(buf, "\n");
-}
-
-static ssize_t store_governor(struct device *dev,
- struct device_attribute *attr, const char *buf,
- size_t count)
-{
- int ret;
- char name[16];
-
- ret = sscanf(buf, "%15s", name);
- if (ret != 1)
- return -EINVAL;
-
- ret = sgxfreq_set_governor(name);
- if (ret)
- return ret;
- else
- return count;
-}
-
-static DEVICE_ATTR(frequency_list, 0444, show_frequency_list, NULL);
-static DEVICE_ATTR(frequency_request, 0444, show_frequency_request, NULL);
-static DEVICE_ATTR(frequency_limit, 0644, show_frequency_limit, store_frequency_limit);
-static DEVICE_ATTR(frequency, 0444, show_frequency, NULL);
-static DEVICE_ATTR(governor_list, 0444, show_governor_list, NULL);
-static DEVICE_ATTR(governor, 0644, show_governor, store_governor);
-static DEVICE_ATTR(stat, 0444, show_stat, NULL);
-
-static const struct attribute *sgxfreq_attributes[] = {
- &dev_attr_frequency_list.attr,
- &dev_attr_frequency_request.attr,
- &dev_attr_frequency_limit.attr,
- &dev_attr_frequency.attr,
- &dev_attr_governor_list.attr,
- &dev_attr_governor.attr,
- &dev_attr_stat.attr,
- NULL
-};
-
-/************************ end sysfs interface ************************/
-
-static void __set_freq(void)
-{
- unsigned long freq;
-
- freq = min(sfd.freq_request, sfd.freq_limit);
- if (freq != sfd.freq) {
-#if (LINUX_VERSION_CODE < KERNEL_VERSION(3,4,0))
- sfd.pdata->device_scale(sfd.dev, sfd.dev, freq);
-#else
- sfd.pdata->device_scale(sfd.dev, freq);
-#endif
- sfd.freq = freq;
- }
-}
-
-static struct sgxfreq_governor *__find_governor(const char *name)
-{
- struct sgxfreq_governor *t;
-
- list_for_each_entry(t, &sfd.gov_list, governor_list)
- if (!strnicmp(name, t->name, SGXFREQ_NAME_LEN))
- return t;
-
- return NULL;
-}
-
-static void __update_timing_info(bool active)
-{
- struct timeval tv;
- do_gettimeofday(&tv);
- if(active)
- {
- if(sfd.sgx_data.active == true) {
- _active_curr_time = __tv2msec(tv);
- sfd.total_active_time += __delta32(
- _active_curr_time, _active_prev_time);
- SGXFREQ_TRACE("A->A TA:= %lums \tdA: %lums \tTI: %lums \tdI: %lums\n",
- sfd.total_active_time,
- __delta32(_active_curr_time, _active_prev_time),
- sfd.total_active_time,
- (unsigned long)0);
- _active_prev_time = _active_curr_time;
- } else {
- _idle_curr_time = __tv2msec(tv);
- _active_prev_time = _idle_curr_time;
- sfd.total_idle_time +=
- __delta32(_idle_curr_time, _idle_prev_time);
- SGXFREQ_TRACE("I->A TA:= %lums \tdA: %lums \tTI: %lums \tdI: %lums\n",
- sfd.total_active_time,
- (unsigned long)0,
- sfd.total_idle_time,
- __delta32(_idle_curr_time, _idle_prev_time));
- }
- } else {
- if(sfd.sgx_data.active == true)
- {
- _idle_prev_time = _active_curr_time = __tv2msec(tv);
- sfd.total_active_time +=
- __delta32(_active_curr_time, _active_prev_time);
- SGXFREQ_TRACE("A->I TA:= %lums \tdA: %lums \tTI: %lums \tdI: %lums\n",
- sfd.total_active_time,
- __delta32(_active_curr_time, _active_prev_time),
- sfd.total_active_time,
- (unsigned long)0);
- }
- else
- {
- _idle_curr_time = __tv2msec(tv);
- sfd.total_idle_time += __delta32(
- _idle_curr_time, _idle_prev_time);
- SGXFREQ_TRACE("I->I TA:= %lums \tdA: %lums \tTI: %lums \tdI: %lums\n",
- sfd.total_active_time,
- (unsigned long)0,
- sfd.total_idle_time,
- __delta32(_idle_curr_time, _idle_prev_time));
- _idle_prev_time = _idle_curr_time;
- }
- }
-}
-
-int sgxfreq_init(struct device *dev)
-{
- int i, ret;
- unsigned long freq;
- struct opp *opp;
- struct timeval tv;
-
- sfd.dev = dev;
- if (!sfd.dev)
- return -EINVAL;
-
- sfd.pdata = (struct gpu_platform_data *)dev->platform_data;
- if (!sfd.pdata ||
- !sfd.pdata->opp_get_opp_count ||
- !sfd.pdata->opp_find_freq_ceil ||
- !sfd.pdata->device_scale)
- return -EINVAL;
-
- rcu_read_lock();
-
- sfd.freq_cnt = sfd.pdata->opp_get_opp_count(dev);
- if (sfd.freq_cnt < 1) {
- rcu_read_unlock();
- return -ENODEV;
- }
-
- sfd.freq_list = kmalloc(sfd.freq_cnt * sizeof(unsigned long), GFP_ATOMIC);
- if (!sfd.freq_list) {
- rcu_read_unlock();
- return -ENOMEM;
- }
-
- freq = 0;
- for (i = 0; i < sfd.freq_cnt; i++) {
- opp = sfd.pdata->opp_find_freq_ceil(dev, &freq);
- if (IS_ERR_OR_NULL(opp)) {
- rcu_read_unlock();
- kfree(sfd.freq_list);
- return -ENODEV;
- }
- sfd.freq_list[i] = freq;
- freq++;
- }
- rcu_read_unlock();
-
- mutex_init(&sfd.freq_mutex);
- sfd.freq_limit = sfd.freq_list[sfd.freq_cnt - 1];
- sgxfreq_set_freq_request(sfd.freq_list[sfd.freq_cnt - 1]);
- sfd.sgx_data.clk_on = false;
- sfd.sgx_data.active = false;
-
- mutex_init(&sfd.gov_mutex);
- INIT_LIST_HEAD(&sfd.gov_list);
-
- sgxfreq_kobj = kobject_create_and_add("sgxfreq", &sfd.dev->kobj);
- ret = sysfs_create_files(sgxfreq_kobj, sgxfreq_attributes);
- if (ret) {
- kfree(sfd.freq_list);
- return ret;
- }
-
-#if defined(CONFIG_THERMAL_FRAMEWORK)
- cool_init();
-#endif
-
- for (i = 0; sgxfreq_gov_init[i] != NULL; i++)
- sgxfreq_gov_init[i]();
-
- if (sgxfreq_set_governor(SGXFREQ_DEFAULT_GOV_NAME)) {
- kfree(sfd.freq_list);
- return -ENODEV;
- }
- do_gettimeofday(&tv);
- _idle_prev_time = _active_curr_time = _idle_curr_time =
- _active_prev_time = __tv2msec(tv);
-
- return 0;
-}
-
-int sgxfreq_deinit(void)
-{
- int i;
-
- sgxfreq_set_governor(NULL);
-
- sgxfreq_set_freq_request(sfd.freq_list[0]);
-
-#if defined(CONFIG_THERMAL_FRAMEWORK)
- cool_deinit();
-#endif
-
- for (i = 0; sgxfreq_gov_deinit[i] != NULL; i++)
- sgxfreq_gov_deinit[i]();
-
- sysfs_remove_files(sgxfreq_kobj, sgxfreq_attributes);
- kobject_put(sgxfreq_kobj);
-
- kfree(sfd.freq_list);
-
- return 0;
-}
-
-int sgxfreq_register_governor(struct sgxfreq_governor *governor)
-{
- if (!governor)
- return -EINVAL;
-
- list_add(&governor->governor_list, &sfd.gov_list);
-
- return 0;
-}
-
-void sgxfreq_unregister_governor(struct sgxfreq_governor *governor)
-{
- if (!governor)
- return;
-
- list_del(&governor->governor_list);
-}
-
-int sgxfreq_set_governor(const char *name)
-{
- int ret = 0;
- struct sgxfreq_governor *new_gov = 0;
-
- if (name) {
- new_gov = __find_governor(name);
- if (!new_gov)
- return -EINVAL;
- }
-
- mutex_lock(&sfd.gov_mutex);
-
- if (sfd.gov && sfd.gov->gov_stop)
- sfd.gov->gov_stop();
-
- if (new_gov && new_gov->gov_start)
- ret = new_gov->gov_start(&sfd.sgx_data);
-
- if (ret) {
- if (sfd.gov && sfd.gov->gov_start)
- sfd.gov->gov_start(&sfd.sgx_data);
- return -ENODEV;
- }
- sfd.gov = new_gov;
-
- mutex_unlock(&sfd.gov_mutex);
-
- return 0;
-}
-
-int sgxfreq_get_freq_list(unsigned long **pfreq_list)
-{
- *pfreq_list = sfd.freq_list;
-
- return sfd.freq_cnt;
-}
-
-unsigned long sgxfreq_get_freq_min(void)
-{
- return sfd.freq_list[0];
-}
-
-unsigned long sgxfreq_get_freq_max(void)
-{
- return sfd.freq_list[sfd.freq_cnt - 1];
-}
-
-unsigned long sgxfreq_get_freq_floor(unsigned long freq)
-{
- int i;
- unsigned long f = 0;
-
- for (i = sfd.freq_cnt - 1; i >= 0; i--) {
- f = sfd.freq_list[i];
- if (f <= freq)
- return f;
- }
-
- return f;
-}
-
-unsigned long sgxfreq_get_freq_ceil(unsigned long freq)
-{
- int i;
- unsigned long f = 0;
-
- for (i = 0; i < sfd.freq_cnt; i++) {
- f = sfd.freq_list[i];
- if (f >= freq)
- return f;
- }
-
- return f;
-}
-
-unsigned long sgxfreq_get_freq(void)
-{
- return sfd.freq;
-}
-
-unsigned long sgxfreq_get_freq_request(void)
-{
- return sfd.freq_request;
-}
-
-unsigned long sgxfreq_get_freq_limit(void)
-{
- return sfd.freq_limit;
-}
-
-unsigned long sgxfreq_set_freq_request(unsigned long freq_request)
-{
- freq_request = sgxfreq_get_freq_ceil(freq_request);
-
- mutex_lock(&sfd.freq_mutex);
-
- sfd.freq_request = freq_request;
- __set_freq();
-
- mutex_unlock(&sfd.freq_mutex);
-
- return freq_request;
-}
-
-unsigned long sgxfreq_set_freq_limit(unsigned long freq_limit)
-{
- freq_limit = sgxfreq_get_freq_ceil(freq_limit);
-
- mutex_lock(&sfd.freq_mutex);
-
- sfd.freq_limit = freq_limit;
- __set_freq();
-
- mutex_unlock(&sfd.freq_mutex);
-
- return freq_limit;
-}
-
-unsigned long sgxfreq_get_total_active_time(void)
-{
- __update_timing_info(sfd.sgx_data.active);
- return sfd.total_active_time;
-}
-
-unsigned long sgxfreq_get_total_idle_time(void)
-{
- __update_timing_info(sfd.sgx_data.active);
- return sfd.total_idle_time;
-}
-
-/*
- * sgx_clk_on, sgx_clk_off, sgx_active, and sgx_idle notifications are
- * serialized by power lock. governor notif calls need sync with governor
- * setting.
- */
-void sgxfreq_notif_sgx_clk_on(void)
-{
- sfd.sgx_data.clk_on = true;
-
- mutex_lock(&sfd.gov_mutex);
-
- if (sfd.gov && sfd.gov->sgx_clk_on)
- sfd.gov->sgx_clk_on();
-
- mutex_unlock(&sfd.gov_mutex);
-}
-
-void sgxfreq_notif_sgx_clk_off(void)
-{
- sfd.sgx_data.clk_on = false;
-
- mutex_lock(&sfd.gov_mutex);
-
- if (sfd.gov && sfd.gov->sgx_clk_off)
- sfd.gov->sgx_clk_off();
-
- mutex_unlock(&sfd.gov_mutex);
-}
-
-
-void sgxfreq_notif_sgx_active(void)
-{
- __update_timing_info(true);
-
- sfd.sgx_data.active = true;
-
- mutex_lock(&sfd.gov_mutex);
-
- if (sfd.gov && sfd.gov->sgx_active)
- sfd.gov->sgx_active();
-
- mutex_unlock(&sfd.gov_mutex);
-
-}
-
-void sgxfreq_notif_sgx_idle(void)
-{
-
- __update_timing_info(false);
-
- sfd.sgx_data.active = false;
-
- mutex_lock(&sfd.gov_mutex);
-
- if (sfd.gov && sfd.gov->sgx_idle)
- sfd.gov->sgx_idle();
-
- mutex_unlock(&sfd.gov_mutex);
-}
-
-void sgxfreq_notif_sgx_frame_done(void)
-{
- mutex_lock(&sfd.gov_mutex);
-
- if (sfd.gov && sfd.gov->sgx_frame_done)
- sfd.gov->sgx_frame_done();
-
- mutex_unlock(&sfd.gov_mutex);
-}