*****************************************************************************/
-
-
#include "gc_hal.h"
#include "gc_hal_kernel.h"
#define _GC_OBJ_ZONE gcvZONE_HARDWARE
+#if gcdENABLE_AUTO_FREQ
+#include <linux/time.h>
+u32 usec_run = 0;
+u32 usec_idle = 0;
+gceCHIPPOWERSTATE lastState = gcvPOWER_IDLE;
+struct timeval tv_on, tv_idle;
+
+void get_run_idle(u32 *run, u32 *idle)
+{
+ if(gcvPOWER_IDLE==lastState)
+ {
+ do_gettimeofday(&tv_on);
+ usec_idle += (1000000*(tv_on.tv_sec-tv_idle.tv_sec)+(tv_on.tv_usec-tv_idle.tv_usec));
+ tv_idle = tv_on;
+ *idle = usec_idle;
+ *run = usec_run;
+ } else {
+ do_gettimeofday(&tv_idle);
+ usec_run += (1000000*(tv_idle.tv_sec-tv_on.tv_sec)+(tv_idle.tv_usec-tv_on.tv_usec));
+ tv_on = tv_idle;
+ *idle = usec_idle;
+ *run = usec_run;
+ }
+ usec_idle = 0;
+ usec_run = 0;
+}
+
+inline void cal_run_idle(gceCHIPPOWERSTATE State)
+{
+ if(gcvPOWER_IDLE==lastState && gcvPOWER_ON==State) //gcvPOWER_IDLE->gcvPOWER_ON
+ {
+ do_gettimeofday(&tv_on);
+ usec_idle += (1000000*(tv_on.tv_sec-tv_idle.tv_sec)+(tv_on.tv_usec-tv_idle.tv_usec));
+ }
+ if(gcvPOWER_ON==lastState && gcvPOWER_IDLE==State) //gcvPOWER_ON->gcvPOWER_IDLE
+ {
+ do_gettimeofday(&tv_idle);
+ usec_run += (1000000*(tv_idle.tv_sec-tv_on.tv_sec)+(tv_idle.tv_usec-tv_on.tv_usec));
+ }
+
+ lastState = State;
+}
+
+#endif
+
/******************************************************************************\
********************************* Support Code *********************************
\******************************************************************************/
break;
}
+#if gcdENABLE_AUTO_FREQ
+ cal_run_idle(State);
+#endif
+
/* Get current process and thread IDs. */
gcmkONERROR(gckOS_GetProcessID(&process));
gcmkONERROR(gckOS_GetThreadID(&thread));
long bankSize = 32 << 20;
module_param(bankSize, long, 0644);
-int fastClear = 0; //-1;
+int fastClear = 0; //-1;
module_param(fastClear, int, 0644);
int compression = -1;
module_param(showArgs, int, 0644);
#if ENABLE_GPU_CLOCK_BY_DRIVER
-unsigned long coreClock = 156000000;
+unsigned long coreClock = 552*1000000;
module_param(coreClock, ulong, 0644);
#endif
.mmap = drv_mmap,
};
+#if gcdENABLE_AUTO_FREQ
+#include <linux/timer.h>
+struct timer_list gpu_timer;
+extern void get_run_idle(u32 *run, u32 *idle);
+int power_cnt = 0;
+int last_precent = 0;
+int last_freq = 0;
+void gputimer_callback(unsigned long arg)
+{
+ u32 run, idle;
+ int precent, freq, diff;
+ struct clk * clk_gpu = clk_get(NULL, "gpu");
+
+ mod_timer(&gpu_timer, jiffies + HZ/10);
+
+ get_run_idle(&run, &idle);
+ precent = (int)((run*100)/(run+idle));
+
+ if(precent<90) {
+ power_cnt--;
+ } else if (precent==100){
+ power_cnt += 2;
+ } else {
+ diff = precent - last_precent;
+ if(diff>0) {
+ if(diff>5) power_cnt += 2;
+ else power_cnt += 1;
+ } else {
+ power_cnt--;
+ }
+ }
+ if(power_cnt<0) power_cnt = 0;
+ if(power_cnt>10) power_cnt = 10;
+ last_precent = precent;
+
+ if(power_cnt<=0) freq = 360;
+ else if(power_cnt>=6) freq = 552;
+ else freq = 456;
+
+ if(freq!=last_freq) {
+ clk_set_parent(clk_gpu, clk_get(NULL, "general_pll"));
+ clk_set_rate(clk_get(NULL, "codec_pll"), freq*1000000);
+ clk_set_rate(clk_gpu, freq*1000000);
+ clk_set_parent(clk_gpu, clk_get(NULL, "codec_pll"));
+ }
+
+ last_freq = freq;
+ printk("%8d /%8d = %3d %%, freq = %dM (%d)\n", (int)run, (int)(run+idle), precent, freq, power_cnt);
+}
+#endif
+
int drv_open(struct inode *inode, struct file* filp)
{
gcsHAL_PRIVATE_DATA_PTR private;
printk("clk_gpu get error: %d\n", retval);
return -ENODEV;
}
+
+ clk_set_rate(clk_get(NULL, "codec_pll"), coreClock);
/* APMU_GC_156M, APMU_GC_624M, APMU_GC_PLL2, APMU_GC_PLL2_DIV2 currently */
- if (clk_set_rate(clk_gpu, 552000000)) //designed on 500M
+ if (clk_set_rate(clk_gpu, coreClock)) //designed on 500M
{
gcmkTRACE_ZONE(gcvLEVEL_ERROR, gcvZONE_DRIVER,
"[galcore] Can't set core clock.");
contiguousBase = res->start;
contiguousSize = res->end-res->start;
+#if gcdENABLE_AUTO_FREQ
+ init_timer(&gpu_timer);
+ gpu_timer.function = gputimer_callback;
+ gpu_timer.expires = jiffies + 15*HZ;
+ add_timer(&gpu_timer);
+#endif
+
ret = drv_init();
if(!ret) {
platform_set_drvdata(pdev,galDevice);