mirror of
https://github.com/followmsi/android_kernel_google_msm.git
synced 2024-11-06 23:17:41 +00:00
msm: dcvs: gpu minimum frequency levels
System performance is enhanced if the gpu frequency is given a minimum corresponding to various frequency levels of CPU 0. Change-Id: Iba168d708524fc8ef164428bb5f4e0631a499342 Signed-off-by: Steve Muckle <smuckle@codeaurora.org> (cherry picked from commit 682c7a01c1d86518cdc7bec25cb413498811137b)
This commit is contained in:
parent
90c8000195
commit
b84423dc28
5 changed files with 76 additions and 2 deletions
|
@ -2626,7 +2626,7 @@ struct platform_device i2s_mdm_8064_device = {
|
|||
static struct msm_dcvs_sync_rule apq8064_dcvs_sync_rules[] = {
|
||||
{1026000, 400000},
|
||||
{384000, 200000},
|
||||
{-1, 128000},
|
||||
{0, 128000},
|
||||
};
|
||||
|
||||
static struct msm_dcvs_platform_data apq8064_dcvs_data = {
|
||||
|
|
|
@ -122,6 +122,7 @@ extern int msm_dcvs_register_core(
|
|||
unsigned int (*get_frequency)(int type_core_num),
|
||||
int (*idle_enable)(int type_core_num,
|
||||
enum msm_core_control_event event),
|
||||
int (*set_floor_frequency)(int type_core_num, unsigned int freq),
|
||||
int sensor);
|
||||
|
||||
/**
|
||||
|
|
|
@ -124,6 +124,7 @@ struct dcvs_core {
|
|||
unsigned int (*get_frequency)(int type_core_num);
|
||||
int (*idle_enable)(int type_core_num,
|
||||
enum msm_core_control_event event);
|
||||
int (*set_floor_frequency)(int type_core_num, unsigned int freq);
|
||||
|
||||
spinlock_t pending_freq_lock;
|
||||
int pending_freq;
|
||||
|
@ -252,6 +253,35 @@ static void restart_slack_timer(struct dcvs_core *core, int slack_us)
|
|||
spin_unlock_irqrestore(&core->idle_state_change_lock, flags2);
|
||||
}
|
||||
|
||||
static void apply_gpu_floor(int cpu_freq)
|
||||
{
|
||||
int i;
|
||||
int gpu_floor_freq = 0;
|
||||
struct dcvs_core *gpu;
|
||||
|
||||
if (!dcvs_pdata)
|
||||
return;
|
||||
|
||||
for (i = 0; i < dcvs_pdata->num_sync_rules; i++)
|
||||
if (cpu_freq > dcvs_pdata->sync_rules[i].cpu_khz) {
|
||||
gpu_floor_freq =
|
||||
dcvs_pdata->sync_rules[i].gpu_floor_khz;
|
||||
break;
|
||||
}
|
||||
|
||||
if (!gpu_floor_freq)
|
||||
return;
|
||||
|
||||
for (i = GPU_OFFSET; i < CORES_MAX; i++) {
|
||||
gpu = &core_list[i];
|
||||
if (gpu->dcvs_core_id == -1)
|
||||
continue;
|
||||
if (gpu->set_floor_frequency)
|
||||
gpu->set_floor_frequency(gpu->type_core_num,
|
||||
gpu_floor_freq);
|
||||
}
|
||||
}
|
||||
|
||||
static int __msm_dcvs_change_freq(struct dcvs_core *core)
|
||||
{
|
||||
int ret = 0;
|
||||
|
@ -283,6 +313,10 @@ repeat:
|
|||
|
||||
spin_unlock_irqrestore(&core->pending_freq_lock, flags);
|
||||
|
||||
if (core->type == MSM_DCVS_CORE_TYPE_CPU &&
|
||||
core->type_core_num == 0)
|
||||
apply_gpu_floor(requested_freq);
|
||||
|
||||
/**
|
||||
* Call the frequency sink driver to change the frequency
|
||||
* We will need to get back the actual frequency in KHz and
|
||||
|
@ -871,6 +905,7 @@ int msm_dcvs_register_core(
|
|||
unsigned int (*get_frequency)(int type_core_num),
|
||||
int (*idle_enable)(int type_core_num,
|
||||
enum msm_core_control_event event),
|
||||
int (*set_floor_frequency)(int type_core_num, unsigned int freq),
|
||||
int sensor)
|
||||
{
|
||||
int ret = -EINVAL;
|
||||
|
@ -894,6 +929,7 @@ int msm_dcvs_register_core(
|
|||
core->set_frequency = set_frequency;
|
||||
core->get_frequency = get_frequency;
|
||||
core->idle_enable = idle_enable;
|
||||
core->set_floor_frequency = set_floor_frequency;
|
||||
core->pending_freq = STOP_FREQ_CHANGE;
|
||||
|
||||
core->info = info;
|
||||
|
|
|
@ -253,6 +253,7 @@ static int __devinit msm_gov_probe(struct platform_device *pdev)
|
|||
msm_dcvs_freq_set,
|
||||
msm_dcvs_freq_get,
|
||||
msm_dcvs_idle_notifier,
|
||||
NULL,
|
||||
sensor);
|
||||
if (gov->dcvs_core_id < 0) {
|
||||
pr_err("Unable to register core for %d\n", cpu);
|
||||
|
|
|
@ -23,6 +23,8 @@ struct msm_priv {
|
|||
struct kgsl_device *device;
|
||||
int enabled;
|
||||
unsigned int cur_freq;
|
||||
unsigned int req_level;
|
||||
int floor_level;
|
||||
struct msm_dcvs_core_info *core_info;
|
||||
int gpu_busy;
|
||||
int dcvs_core_id;
|
||||
|
@ -69,7 +71,39 @@ static int msm_set_freq(int core_num, unsigned int freq)
|
|||
return 0;
|
||||
|
||||
mutex_lock(&device->mutex);
|
||||
kgsl_pwrctrl_pwrlevel_change(device, i);
|
||||
priv->req_level = i;
|
||||
if (priv->req_level <= priv->floor_level) {
|
||||
kgsl_pwrctrl_pwrlevel_change(device, priv->req_level);
|
||||
priv->cur_freq = pwr->pwrlevels[pwr->active_pwrlevel].gpu_freq;
|
||||
}
|
||||
mutex_unlock(&device->mutex);
|
||||
|
||||
/* return current frequency in kHz */
|
||||
return priv->cur_freq / 1000;
|
||||
}
|
||||
|
||||
static int msm_set_min_freq(int core_num, unsigned int freq)
|
||||
{
|
||||
int i, delta = 5000000;
|
||||
struct msm_priv *priv = the_msm_priv;
|
||||
struct kgsl_device *device = priv->device;
|
||||
struct kgsl_pwrctrl *pwr = &device->pwrctrl;
|
||||
|
||||
/* msm_dcvs manager uses frequencies in kHz */
|
||||
freq *= 1000;
|
||||
for (i = 0; i < pwr->num_pwrlevels; i++)
|
||||
if (abs(pwr->pwrlevels[i].gpu_freq - freq) < delta)
|
||||
break;
|
||||
if (i == pwr->num_pwrlevels)
|
||||
return 0;
|
||||
|
||||
mutex_lock(&device->mutex);
|
||||
priv->floor_level = i;
|
||||
if (priv->floor_level <= priv->req_level)
|
||||
kgsl_pwrctrl_pwrlevel_change(device, priv->floor_level);
|
||||
else if (priv->floor_level > priv->req_level)
|
||||
kgsl_pwrctrl_pwrlevel_change(device, priv->req_level);
|
||||
|
||||
priv->cur_freq = pwr->pwrlevels[pwr->active_pwrlevel].gpu_freq;
|
||||
mutex_unlock(&device->mutex);
|
||||
|
||||
|
@ -170,6 +204,7 @@ static int msm_init(struct kgsl_device *device,
|
|||
|
||||
priv->core_info = pdata->core_info;
|
||||
tbl = priv->core_info->freq_tbl;
|
||||
priv->floor_level = pwr->num_pwrlevels - 1;
|
||||
/* Fill in frequency table from low to high, reversing order. */
|
||||
low_level = pwr->num_pwrlevels - KGSL_PWRLEVEL_LAST_OFFSET;
|
||||
for (i = 0; i <= low_level; i++)
|
||||
|
@ -180,6 +215,7 @@ static int msm_init(struct kgsl_device *device,
|
|||
0,
|
||||
priv->core_info,
|
||||
msm_set_freq, msm_get_freq, msm_idle_enable,
|
||||
msm_set_min_freq,
|
||||
priv->core_info->sensors[0]);
|
||||
if (priv->dcvs_core_id < 0) {
|
||||
KGSL_PWR_ERR(device, "msm_dcvs_register_core failed");
|
||||
|
|
Loading…
Reference in a new issue