aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/media/video/samsung/mali/platform/pegasus-m400/mali_platform_dvfs.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/media/video/samsung/mali/platform/pegasus-m400/mali_platform_dvfs.c')
-rw-r--r--drivers/media/video/samsung/mali/platform/pegasus-m400/mali_platform_dvfs.c175
1 files changed, 142 insertions, 33 deletions
diff --git a/drivers/media/video/samsung/mali/platform/pegasus-m400/mali_platform_dvfs.c b/drivers/media/video/samsung/mali/platform/pegasus-m400/mali_platform_dvfs.c
index 8293d6e..2d47dba 100644
--- a/drivers/media/video/samsung/mali/platform/pegasus-m400/mali_platform_dvfs.c
+++ b/drivers/media/video/samsung/mali/platform/pegasus-m400/mali_platform_dvfs.c
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2010 ARM Limited. All rights reserved.
+ * Copyright (C) 2010-2012 ARM Limited. All rights reserved.
*
* This program is free software and is provided to you under the terms of the GNU General Public License version 2
* as published by the Free Software Foundation, and any use by you of this program is subject to the terms of such GNU licence.
@@ -27,7 +27,7 @@
#include "mali_device_pause_resume.h"
#include <linux/workqueue.h>
-#define MAX_MALI_DVFS_STEPS 4
+#define MAX_MALI_DVFS_STEPS 5
#define MALI_DVFS_WATING 10 // msec
#ifdef CONFIG_CPU_FREQ
@@ -35,10 +35,12 @@
#define EXYNOS4_ASV_ENABLED
#endif
+#include <plat/cpu.h>
+
static int bMaliDvfsRun=0;
static _mali_osk_atomic_t bottomlock_status;
-static int bottom_lock_step;
+int bottom_lock_step = 0;
typedef struct mali_dvfs_tableTag{
unsigned int clock;
@@ -73,7 +75,10 @@ mali_dvfs_step step[MALI_DVFS_STEPS]={
#if (MALI_DVFS_STEPS > 2)
/*step 2 clk*/ {350, 950000},
#if (MALI_DVFS_STEPS > 3)
- /*step 3 clk*/ {440, 1025000}
+ /*step 3 clk*/ {440, 1025000},
+#if (MALI_DVFS_STEPS > 4)
+ /*step 4 clk*/ {533, 1075000}
+#endif
#endif
#endif
#endif
@@ -86,17 +91,21 @@ mali_dvfs_staycount_table mali_dvfs_staycount[MALI_DVFS_STEPS]={
#if (MALI_DVFS_STEPS > 2)
/*step 2*/{0},
#if (MALI_DVFS_STEPS > 3)
- /*step 3*/{0}
+ /*step 3*/{0},
+#if (MALI_DVFS_STEPS > 4)
+ /*step 4*/{0}
+#endif
#endif
#endif
#endif
};
/* dvfs information */
-// L0 = 440Mhz, 1.025V
-// L1 = 350Mhz, 0.95V
-// L2 = 266Mhz, 0.90V
-// L3 = 160Mhz, 0.875V
+// L0 = 533Mhz, 1.075V
+// L1 = 440Mhz, 1.025V
+// L2 = 350Mhz, 0.95V
+// L3 = 266Mhz, 0.90V
+// L4 = 160Mhz, 0.875V
int step0_clk = 160;
int step0_vol = 875000;
@@ -114,7 +123,13 @@ int step2_down = 85;
int step3_clk = 440;
int step3_vol = 1025000;
int step2_up = 90;
-int step3_down = 90;
+int step3_down = 85;
+#if (MALI_DVFS_STEPS > 4)
+int step4_clk = 533;
+int step4_vol = 1075000;
+int step3_up = 90;
+int step4_down = 95;
+#endif
#endif
#endif
#endif
@@ -123,7 +138,8 @@ mali_dvfs_table mali_dvfs_all[MAX_MALI_DVFS_STEPS]={
{160 ,1000000 , 875000},
{266 ,1000000 , 900000},
{350 ,1000000 , 950000},
- {440 ,1000000 , 1025000} };
+ {440 ,1000000 , 1025000},
+ {533 ,1000000 , 1075000} };
mali_dvfs_table mali_dvfs[MALI_DVFS_STEPS]={
{160 ,1000000 , 875000},
@@ -132,7 +148,10 @@ mali_dvfs_table mali_dvfs[MALI_DVFS_STEPS]={
#if (MALI_DVFS_STEPS > 2)
{350 ,1000000 , 950000},
#if (MALI_DVFS_STEPS > 3)
- {440 ,1000000 ,1025000}
+ {440 ,1000000 ,1025000},
+#if (MALI_DVFS_STEPS > 4)
+ {533 ,1000000 ,1075000}
+#endif
#endif
#endif
#endif
@@ -145,7 +164,10 @@ mali_dvfs_threshold_table mali_dvfs_threshold[MALI_DVFS_STEPS]={
#if (MALI_DVFS_STEPS > 2)
{85 , 90},
#if (MALI_DVFS_STEPS > 3)
- {90 ,100}
+ {85 ,90},
+#if (MALI_DVFS_STEPS > 4)
+ {95 ,100}
+#endif
#endif
#endif
#endif
@@ -154,19 +176,48 @@ mali_dvfs_threshold_table mali_dvfs_threshold[MALI_DVFS_STEPS]={
#ifdef EXYNOS4_ASV_ENABLED
#define ASV_LEVEL 12 /* ASV0, 1, 11 is reserved */
-static unsigned int asv_3d_volt_9_table[MALI_DVFS_STEPS][ASV_LEVEL] = {
+static unsigned int asv_3d_volt_9_table_1ghz_type[MALI_DVFS_STEPS-1][ASV_LEVEL] = {
+ { 975000, 950000, 950000, 950000, 925000, 925000, 925000, 900000, 900000, 900000, 900000, 875000}, /* L3(160Mhz) */
+#if (MALI_DVFS_STEPS > 1)
+ { 1000000, 975000, 975000, 975000, 950000, 950000, 950000, 900000, 900000, 900000, 900000, 875000}, /* L2(266Mhz) */
+#if (MALI_DVFS_STEPS > 2)
+ { 1075000, 1050000, 1050000, 1050000, 1000000, 1000000, 1000000, 975000, 975000, 975000, 975000, 925000}, /* L1(350Mhz) */
+#if (MALI_DVFS_STEPS > 3)
+ { 1125000, 1100000, 1100000, 1100000, 1075000, 1075000, 1075000, 1025000, 1025000, 1025000, 1025000, 975000}, /* L0(440Mhz) */
+#endif
+#endif
+#endif
+};
+
+static unsigned int asv_3d_volt_9_table[MALI_DVFS_STEPS-1][ASV_LEVEL] = {
{ 950000, 925000, 900000, 900000, 875000, 875000, 875000, 875000, 850000, 850000, 850000, 850000}, /* L3(160Mhz) */
#if (MALI_DVFS_STEPS > 1)
- { 975000, 950000, 925000, 925000, 925000, 900000, 900000, 875000, 875000, 875000, 875000, 850000}, /* L2(266Mhz) */
+ { 975000, 950000, 925000, 925000, 925000, 900000, 900000, 875000, 875000, 875000, 875000, 850000}, /* L2(266Mhz) */
#if (MALI_DVFS_STEPS > 2)
- { 1050000, 1025000, 1000000, 1000000, 975000, 950000, 950000, 950000, 925000, 925000, 925000, 900000}, /* L1(350Mhz) */
+ { 1050000, 1025000, 1000000, 1000000, 975000, 950000, 950000, 950000, 925000, 925000, 925000, 900000}, /* L1(350Mhz) */
#if (MALI_DVFS_STEPS > 3)
- { 1100000, 1075000, 1050000, 1050000, 1050000, 1025000, 1025000, 1000000, 1000000, 1000000, 975000, 950000}, /* L0(440Mhz) */
+ { 1100000, 1075000, 1050000, 1050000, 1050000, 1025000, 1025000, 1000000, 1000000, 1000000, 975000, 950000}, /* L0(440Mhz) */
#endif
#endif
#endif
};
+
+static unsigned int asv_3d_volt_9_table_for_prime[MALI_DVFS_STEPS][ASV_LEVEL] = {
+ { 950000, 937500, 925000, 912500, 900000, 887500, 875000, 862500, 875000, 862500, 850000, 850000}, /* L4(160Mhz) */
+#if (MALI_DVFS_STEPS > 1)
+ { 975000, 962500, 950000, 937500, 925000, 912500, 900000, 887500, 900000, 887500, 875000, 862500}, /* L3(266Mhz) */
+#if (MALI_DVFS_STEPS > 2)
+ { 1025000, 1012500, 1000000, 987500, 975000, 962500, 950000, 937500, 950000, 937500, 925000, 912500}, /* L2(350Mhz) */
+#if (MALI_DVFS_STEPS > 3)
+ { 1087500, 1075000, 1062500, 1050000, 1037500, 1025000, 1012500, 1000000, 1012500, 1000000, 987500, 975000}, /* L1(440Mhz) */
+#if (MALI_DVFS_STEPS > 4)
+ { 1150000, 1137500, 1125000, 1112500, 1100000, 1087500, 1075000, 1062500, 1087500, 1075000, 1062500, 1050000}, /* L0(533Mhz) */
+#endif
#endif
+#endif
+#endif
+};
+#endif /* ASV_LEVEL */
/*dvfs status*/
mali_dvfs_currentstatus maliDvfsStatus;
@@ -279,10 +330,12 @@ static mali_bool set_mali_dvfs_status(u32 step,mali_bool boostup)
}
#ifdef EXYNOS4_ASV_ENABLED
- if (mali_dvfs[step].clock == 160)
- exynos4x12_set_abb_member(ABB_G3D, ABB_MODE_100V);
- else
- exynos4x12_set_abb_member(ABB_G3D, ABB_MODE_130V);
+ if (samsung_rev() < EXYNOS4412_REV_2_0) {
+ if (mali_dvfs[step].clock == 160)
+ exynos4x12_set_abb_member(ABB_G3D, ABB_MODE_100V);
+ else
+ exynos4x12_set_abb_member(ABB_G3D, ABB_MODE_130V);
+ }
#endif
@@ -290,11 +343,13 @@ static mali_bool set_mali_dvfs_status(u32 step,mali_bool boostup)
/*for future use*/
maliDvfsStatus.pCurrentDvfs = &mali_dvfs[validatedStep];
+#if CPUFREQ_LOCK_DURING_440
/* lock/unlock CPU freq by Mali */
if (mali_dvfs[step].clock == 440)
err = cpufreq_lock_by_mali(1200);
else
cpufreq_unlock_by_mali();
+#endif
return MALI_TRUE;
}
@@ -335,11 +390,30 @@ extern unsigned int exynos_result_of_asv;
static mali_bool mali_dvfs_table_update(void)
{
unsigned int i;
-
- for (i = 0; i < MALI_DVFS_STEPS; i++) {
- MALI_PRINT((":::exynos_result_of_asv : %d\n", exynos_result_of_asv));
- mali_dvfs[i].vol = asv_3d_volt_9_table[i][exynos_result_of_asv];
- MALI_PRINT(("mali_dvfs[%d].vol = %d\n", i, mali_dvfs[i].vol));
+ unsigned int step_num = MALI_DVFS_STEPS;
+
+ if(soc_is_exynos4412()) {
+ if (exynos_armclk_max == 1000000) {
+ step_num = MALI_DVFS_STEPS - 1;
+ for (i = 0; i < step_num; i++) {
+ MALI_PRINT((":::exynos_result_of_asv : %d\n", exynos_result_of_asv));
+ mali_dvfs[i].vol = asv_3d_volt_9_table_1ghz_type[i][exynos_result_of_asv];
+ MALI_PRINT(("mali_dvfs[%d].vol = %d 1ghz_type\n", i, mali_dvfs[i].vol));
+ }
+ } else if (samsung_rev() >= EXYNOS4412_REV_2_0) {
+ for (i = 0; i < step_num; i++) {
+ MALI_PRINT((":::exynos_result_of_asv : %d\n", exynos_result_of_asv));
+ mali_dvfs[i].vol = asv_3d_volt_9_table_for_prime[i][exynos_result_of_asv];
+ MALI_PRINT(("mali_dvfs[%d].vol = %d 1.6ghz_type\n", i, mali_dvfs[i].vol));
+ }
+ } else {
+ step_num = MALI_DVFS_STEPS - 1;
+ for (i = 0; i < step_num; i++) {
+ MALI_PRINT((":::exynos_result_of_asv : %d\n", exynos_result_of_asv));
+ mali_dvfs[i].vol = asv_3d_volt_9_table[i][exynos_result_of_asv];
+ MALI_PRINT(("mali_dvfs[%d].vol = %d 1.4ghz_type\n", i, mali_dvfs[i].vol));
+ }
+ }
}
return MALI_TRUE;
@@ -354,7 +428,6 @@ static unsigned int decideNextStatus(unsigned int utilization)
if (mali_runtime_resumed >= 0) {
level = mali_runtime_resumed;
mali_runtime_resumed = -1;
- return level;
}
if (mali_dvfs_threshold[maliDvfsStatus.currentStep].upthreshold
@@ -369,6 +442,9 @@ static unsigned int decideNextStatus(unsigned int utilization)
if (utilization > (int)(255 * mali_dvfs_threshold[maliDvfsStatus.currentStep].upthreshold / 100) &&
level < MALI_DVFS_STEPS - 1) {
level++;
+ if ((samsung_rev() < EXYNOS4412_REV_2_0) && (maliDvfsStatus.currentStep == 3)) {
+ level=get_mali_dvfs_status();
+ }
}
if (utilization < (int)(255 * mali_dvfs_threshold[maliDvfsStatus.currentStep].downthreshold / 100) &&
level > 0) {
@@ -400,6 +476,10 @@ static unsigned int decideNextStatus(unsigned int utilization)
#if (MALI_DVFS_STEPS > 3)
step3_clk = step[3].clk;
change_dvfs_tableset(step3_clk, 3);
+#if (MALI_DVFS_STEPS > 4)
+ step4_clk = step[4].clk;
+ change_dvfs_tableset(step4_clk, 4);
+#endif
#endif
#endif
#endif
@@ -422,12 +502,18 @@ static unsigned int decideNextStatus(unsigned int utilization)
step[i].clk = mali_dvfs_all[2].clock;
}
maliDvfsStatus.currentStep = 2;
- } else {
+ } else if (mali_dvfs_control < mali_dvfs_all[4].clock && mali_dvfs_control >= mali_dvfs_all[3].clock) {
int i = 0;
for (i = 0; i < MALI_DVFS_STEPS; i++) {
step[i].clk = mali_dvfs_all[3].clock;
}
maliDvfsStatus.currentStep = 3;
+ } else {
+ int i = 0;
+ for (i = 0; i < MALI_DVFS_STEPS; i++) {
+ step[i].clk = mali_dvfs_all[4].clock;
+ }
+ maliDvfsStatus.currentStep = 4;
}
step0_clk = step[0].clk;
change_dvfs_tableset(step0_clk, 0);
@@ -440,6 +526,10 @@ static unsigned int decideNextStatus(unsigned int utilization)
#if (MALI_DVFS_STEPS > 3)
step3_clk = step[3].clk;
change_dvfs_tableset(step3_clk, 3);
+#if (MALI_DVFS_STEPS > 4)
+ step4_clk = step[4].clk;
+ change_dvfs_tableset(step4_clk, 4);
+#endif
#endif
#endif
#endif
@@ -577,6 +667,22 @@ static void mali_dvfs_work_handler(struct work_struct *w)
MALI_PRINT((":::step3_down change to %d %\n", step3_down));
mali_dvfs_threshold[3].downthreshold = step3_down;
}
+#if (MALI_DVFS_STEPS > 4)
+ if (step4_clk != mali_dvfs[4].clock) {
+ MALI_PRINT(("::: step4_clk change to %d Mhz\n", step4_clk));
+ change_clk = step4_clk;
+ change_step = 4;
+ step4_clk = change_dvfs_tableset(change_clk, change_step);
+ }
+ if (step3_up != mali_dvfs_threshold[3].upthreshold) {
+ MALI_PRINT((":::step3_up change to %d %\n", step3_up));
+ mali_dvfs_threshold[3].upthreshold = step3_up;
+ }
+ if (step4_down != mali_dvfs_threshold[4].downthreshold) {
+ MALI_PRINT((":::step4_down change to %d %\n", step4_down));
+ mali_dvfs_threshold[4].downthreshold = step4_down;
+ }
+#endif
#endif
#endif
#endif
@@ -587,6 +693,7 @@ static void mali_dvfs_work_handler(struct work_struct *w)
mali_dvfs[1].vol = step1_vol;
mali_dvfs[2].vol = step2_vol;
mali_dvfs[3].vol = step3_vol;
+ mali_dvfs[4].vol = step4_vol;
#endif
MALI_DEBUG_PRINT(3, ("=== mali_dvfs_work_handler\n"));
@@ -641,8 +748,10 @@ int change_dvfs_tableset(int change_clk, int change_step)
mali_dvfs[change_step].clock = mali_dvfs_all[1].clock;
} else if (change_clk < mali_dvfs_all[3].clock && change_clk >= mali_dvfs_all[2].clock) {
mali_dvfs[change_step].clock = mali_dvfs_all[2].clock;
- } else {
+ } else if (change_clk < mali_dvfs_all[4].clock && change_clk >= mali_dvfs_all[3].clock) {
mali_dvfs[change_step].clock = mali_dvfs_all[3].clock;
+ } else {
+ mali_dvfs[change_step].clock = mali_dvfs_all[4].clock;
}
MALI_PRINT((":::mali dvfs step %d clock and voltage = %d Mhz, %d V\n",change_step, mali_dvfs[change_step].clock, mali_dvfs[change_step].vol));
@@ -655,11 +764,13 @@ int change_dvfs_tableset(int change_clk, int change_step)
/*change the clock*/
mali_clk_set_rate(mali_dvfs[change_step].clock, mali_dvfs[change_step].freq);
+#if CPUFREQ_LOCK_DURING_440
/* lock/unlock CPU freq by Mali */
if (mali_dvfs[change_step].clock == 440)
err = cpufreq_lock_by_mali(1200);
else
cpufreq_unlock_by_mali();
+#endif
}
return mali_dvfs[change_step].clock;
@@ -684,10 +795,8 @@ int mali_dvfs_bottom_lock_push(int lock_step)
if (bottom_lock_step < lock_step) {
bottom_lock_step = lock_step;
if (get_mali_dvfs_status() < lock_step) {
- mali_regulator_set_voltage(mali_dvfs[lock_step].vol,
- mali_dvfs[lock_step].vol);
- mali_clk_set_rate(mali_dvfs[lock_step].clock,
- mali_dvfs[lock_step].freq);
+ mali_regulator_set_voltage(mali_dvfs[lock_step].vol, mali_dvfs[lock_step].vol);
+ mali_clk_set_rate(mali_dvfs[lock_step].clock, mali_dvfs[lock_step].freq);
set_mali_dvfs_current_step(lock_step);
}
}