static unsigned long aml_cal_virtual_temp(struct amlogic_thermal_platform_data *pdata)
{
    static unsigned int cpu_freq_level_cnt  = 0, gpu_freq_level_cnt  = 0;
    static unsigned int last_cpu_freq_level = 0, last_gpu_freq_level = 0;
    static unsigned int cpu_temp = 40, gpu_temp = 40;                   // default set to 40 when at homescreen
    unsigned int curr_cpu_avg_freq,   curr_gpu_avg_freq;
    int curr_cpu_freq_level, curr_gpu_freq_level;
    int cnt_level, level_diff;
    int temp_update = 0, final_temp;

    /*
     * CPU temp
     */
    if (atomic_read(&freq_update_flag)) {
        curr_cpu_avg_freq = pdata->monitor.avg_cpu_freq;
        curr_cpu_freq_level = check_freq_level(&cpu_virtual_thermal, curr_cpu_avg_freq);
        level_diff = curr_cpu_freq_level - last_cpu_freq_level;
        if (ABS(level_diff) <= 1) {  // freq change is not large
            cpu_freq_level_cnt++;
            cnt_level = check_freq_level_cnt(cpu_freq_level_cnt);
            cpu_temp  = cpu_virtual_thermal.thermal[curr_cpu_freq_level].temp_time[cnt_level];
        } else {                                                // level not match
            cpu_temp = cpu_virtual_thermal.thermal[curr_cpu_freq_level].temp_time[0];
            cpu_freq_level_cnt = 0;
        }
        last_cpu_freq_level = curr_cpu_freq_level;

        curr_gpu_avg_freq = pdata->monitor.avg_gpu_freq;
        curr_gpu_freq_level = check_freq_level(&gpu_virtual_thermal, curr_gpu_avg_freq);
        level_diff = curr_gpu_freq_level - last_gpu_freq_level;
        if (ABS(level_diff) <= 1) {  // freq change is not large
            gpu_freq_level_cnt++;
            cnt_level = check_freq_level_cnt(gpu_freq_level_cnt);
            gpu_temp  = gpu_virtual_thermal.thermal[curr_gpu_freq_level].temp_time[cnt_level];
        } else {                                                // level not match
            gpu_temp = gpu_virtual_thermal.thermal[curr_gpu_freq_level].temp_time[0];
            gpu_freq_level_cnt = 0;
        }
        last_gpu_freq_level = curr_gpu_freq_level;

        atomic_set(&freq_update_flag, 0);
        temp_update = 1;
    }

    if (cpu_temp <= 0 && gpu_temp <= 0) {
        final_temp = 40;
    }
    final_temp = (cpu_temp >= gpu_temp ? cpu_temp : gpu_temp);
    return final_temp;
}
static unsigned long aml_cal_virtual_temp(void)
{
    static unsigned int cpu_freq_level_cnt  = 0, gpu_freq_level_cnt  = 0;
    static unsigned int last_cpu_freq_level = 0, last_gpu_freq_level = 0;
    static unsigned int cpu_temp = 40, gpu_temp = 40;                   // default set to 40 when at homescreen
    unsigned int curr_cpu_avg_freq,   curr_gpu_avg_freq;
    int curr_cpu_freq_level, curr_gpu_freq_level;
    int cnt_level, level_diff; 
    int temp_update = 0, final_temp;
    
    /*
     * CPU temp 
     */
    if (atomic_read(&freq_update_flag)) {
        curr_cpu_avg_freq = atomic_read(&last_cpu_avg_freq);
        curr_cpu_freq_level = check_freq_level(&cpu_virtual_thermal, curr_cpu_avg_freq); 
        level_diff = curr_cpu_freq_level - last_cpu_freq_level;
        if (ABS(level_diff) <= 1) {  // freq change is not large 
            cpu_freq_level_cnt++;
            cnt_level = check_freq_level_cnt(cpu_freq_level_cnt);
            cpu_temp  = cpu_virtual_thermal.thermal[curr_cpu_freq_level].temp_time[cnt_level];
        #if DBG_VIRTUAL
            printk("%s, cur_freq:%7d, freq_level:%d, cnt_level:%d, cnt:%d, cpu_temp:%d\n",
                   __func__, curr_cpu_avg_freq, curr_cpu_freq_level, cnt_level, cpu_freq_level_cnt, cpu_temp);
        #endif
        } else {                                                // level not match
            cpu_temp = cpu_virtual_thermal.thermal[curr_cpu_freq_level].temp_time[0]; 
        #if DBG_VIRTUAL
            printk("%s, cur_freq:%7d, cur_level:%d, last_level:%d, last_cnt_level:%d, cpu_temp:%d\n",
                   __func__, curr_cpu_avg_freq, curr_cpu_freq_level, last_cpu_freq_level, cpu_freq_level_cnt, cpu_temp);
        #endif
            cpu_freq_level_cnt = 0;
        }
        last_cpu_freq_level = curr_cpu_freq_level;

        curr_gpu_avg_freq = atomic_read(&last_gpu_avg_freq);
        curr_gpu_freq_level = check_freq_level(&gpu_virtual_thermal, curr_gpu_avg_freq); 
        level_diff = curr_gpu_freq_level - last_gpu_freq_level;
        if (ABS(level_diff) <= 1) {  // freq change is not large 
            gpu_freq_level_cnt++;
            cnt_level = check_freq_level_cnt(gpu_freq_level_cnt);
            gpu_temp  = gpu_virtual_thermal.thermal[curr_gpu_freq_level].temp_time[cnt_level];
        #if DBG_VIRTUAL
            printk("%s, cur_freq:%7d, freq_level:%d, cnt_level:%d, cnt:%d, gpu_temp:%d\n",
                   __func__, curr_gpu_avg_freq, curr_gpu_freq_level, cnt_level, gpu_freq_level_cnt, gpu_temp);
        #endif
        } else {                                                // level not match
            gpu_temp = gpu_virtual_thermal.thermal[curr_gpu_freq_level].temp_time[0]; 
            gpu_freq_level_cnt = 0;
        #if DBG_VIRTUAL
            printk("%s, cur_freq:%7d, cur_level:%d, last_level:%d, gpu_temp:%d\n",
                   __func__, curr_gpu_avg_freq, curr_gpu_freq_level, last_gpu_freq_level, gpu_temp);
        #endif
        }
        last_gpu_freq_level = curr_gpu_freq_level;

        atomic_set(&freq_update_flag, 0);
        temp_update = 1; 
    }

    if (cpu_temp <= 0 && gpu_temp <= 0) {
        printk("%s, Bug here, cpu & gpu temp can't be 0, cpu_temp:%d, gpu_temp:%d\n", __func__, cpu_temp, gpu_temp);
        final_temp = 40;    
    }
    final_temp = (cpu_temp >= gpu_temp ? cpu_temp : gpu_temp);
    if (temp_update) {
    #if DBG_VIRTUAL
        printk("final temp:%d\n", final_temp);    
    #endif
    }
    return final_temp;
}