static void mali_dvfs_handler(struct work_struct *work) { /*unsigned long flags;*/ int enabled; int duration; int boostID; int perfID; int gedID; int halID; int targetID; if (0 == atomic_read(&g_is_power_enabled)) { MALI_DEBUG_PRINT(4, ("GPU clock is switching down\n")); return; } // Get related settings enabled = mtk_get_input_boost_enabled(); duration = mtk_get_input_boost_duration(); boostID = mtk_get_boost_frequency_id(); perfID = mtk_get_perf_hal_frequency_id(); gedID = mtk_get_ged_hal_frequency_id(); targetID = mtk_get_current_frequency_id(); if ((enabled != 0) && (duration > 0)) { targetID = boostID; } else { if (targetID < mt_gpufreq_get_thermal_limit_index()) { targetID = mt_gpufreq_get_thermal_limit_index(); } /* Calculate higher boost frequency (e.g. lower index id) */ if(perfID < gedID) { halID = perfID; } else { halID = gedID; } if(targetID > halID) { MALI_DEBUG_PRINT(4, ("Use GPU boost frequency %d as target!\n", halID)); targetID = halID; } } if (targetID != mt_gpufreq_get_cur_freq_index()) { mt_gpufreq_target(targetID); } }
bool ged_dvfs_gpu_freq_commit(unsigned long ui32NewFreqID, GED_DVFS_COMMIT_TYPE eCommitType) { int bCommited=false; #ifdef GED_DVFS_ENABLE unsigned long ui32CurFreqID; ui32CurFreqID = mt_gpufreq_get_cur_freq_index(); if (NULL != ged_dvfs_gpu_freq_commit_fp) { if (ui32NewFreqID > g_bottom_freq_id) { ui32NewFreqID = g_bottom_freq_id; } if (ui32NewFreqID > g_cust_boost_freq_id) { ui32NewFreqID = g_cust_boost_freq_id; } // up bound if (ui32NewFreqID < g_cust_upbound_freq_id) { ui32NewFreqID = g_cust_upbound_freq_id; } // thermal power limit if (ui32NewFreqID < mt_gpufreq_get_thermal_limit_index()) { ui32NewFreqID = mt_gpufreq_get_thermal_limit_index(); } // do change if (ui32NewFreqID != ui32CurFreqID) { // call to DVFS module ged_dvfs_gpu_freq_commit_fp(ui32NewFreqID, eCommitType, &bCommited); /* * To-Do: refine previous freq contributions, * since it is possible to have multiple freq settings in previous execution period * Does this fatal for precision? */ ged_log_buf_print(ghLogBuf_DVFS, "[GED_K] new freq ID commited: idx=%lu type=%u",ui32NewFreqID, eCommitType); if(true==bCommited) { ged_log_buf_print(ghLogBuf_DVFS, "[GED_K] commited true"); g_ui32PreFreqID = ui32CurFreqID; } } } #endif return bCommited; }
/* this function will be called periodically with sampling period 200ms~1000ms */ void mali_pmm_utilization_handler(struct mali_gpu_utilization_data *data) { int utilization; mali_dvfs_action action; int frequency; int duration; int currentID; int targetID; int deferred; mali_utilization = data->utilization_gpu; if (0 == atomic_read(&g_is_power_enabled)) { MALI_DEBUG_PRINT(4, ("GPU clock is in off state\n")); return; } utilization = (mali_utilization * 100) / 256; MALI_DEBUG_PRINT(4, ("%s GPU utilization=%d\n", __FUNCTION__, utilization)); if (utilization <= mtk_get_dvfs_threshold_min()) { action = MALI_DVFS_CLOCK_DOWN; } else if (utilization >= mtk_get_dvfs_threshold_max()) { action = MALI_DVFS_CLOCK_UP; } else { MALI_DEBUG_PRINT(4, ("No need to adjust GPU frequency!\n")); return; } // Get current frequency id currentID = mt_gpufreq_get_cur_freq_index(); // Get current deferred count deferred = mtk_get_current_deferred_count(); switch(action) { case MALI_DVFS_CLOCK_UP: frequency = mapIndexToFrequency(currentID) * utilization / mtk_get_dvfs_threshold_min(); targetID = mapFrequencyToIndex(frequency); deferred += 1; break; case MALI_DVFS_CLOCK_DOWN: frequency = mapIndexToFrequency(currentID) * utilization / mtk_get_dvfs_threshold_max(); targetID = mapFrequencyToIndex(frequency); deferred += 1; break; default: MALI_DEBUG_PRINT(4, ("Unknown GPU DVFS operation!\n")); return; } // Thermal power limit if (targetID < mt_gpufreq_get_thermal_limit_index()) { targetID = mt_gpufreq_get_thermal_limit_index(); } duration = mtk_get_input_boost_duration(); if((duration > 0) && (mtk_get_input_boost_enabled() != 0)) { MALI_DEBUG_PRINT(4, ("Still in the boost duration!\n")); mtk_set_input_boost_duration(duration - 1); if (targetID >= mtk_get_boost_frequency_id()) { mtk_set_current_deferred_count(deferred); return; } } else if (deferred < mtk_get_dvfs_deferred_count()) { MALI_DEBUG_PRINT(4, ("Defer DVFS frequency operation!\n")); mtk_set_current_deferred_count(deferred); return; } if(currentID == targetID) { MALI_DEBUG_PRINT(4, ("Target GPU frequency is the same!\n")); return; } if (targetID < 0) { targetID = 0; } else if (targetID >= mt_gpufreq_get_dvfs_table_num()) { targetID = mt_gpufreq_get_dvfs_table_num() - 1; } mtk_set_current_frequency_id(targetID); if (targetID < mtk_get_boost_frequency_id()) { mtk_set_boost_frequency_id(targetID); } mtk_set_current_deferred_count(0); #if MALI_LICENSE_IS_GPL if (mali_dvfs_queue && (1 == atomic_read(&g_is_power_enabled))) { queue_work(mali_dvfs_queue, &mali_dvfs_work); } #endif // MALI_LICENSE_IS_GPL }