diff options
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.c | 175 |
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); } } |