# shellcheck shell=sh # Profili di frequenza condivisi fra helper privilegiato, lettore di stato e plasmoide. # Sorgente unica di verità: NON scrive nulla su sysfs, contiene solo la tabella dei # profili e l'aritmetica dei limiti (kHz). Copiato da install.sh accanto all'helper # in /usr/local/libexec/enne2-cpufreq/. # # Ogni profilo agisce su: governor, energy_performance_preference (EPP), boost e # tetto di frequenza espresso come percentuale dello span utile # (floor_khz .. cpuinfo_max_freq). # Lettura minimale (il file è già stato validato dal chiamante dove serve). cf_read() { _cfout= [ -r "$1" ] || return 1 IFS= read -r _cfout < "$1" 2>/dev/null || [ -n "$_cfout" ] || return 1 printf '%s\n' "$_cfout" } # Tetto hardware reale (kHz), indipendente dallo stato del boost: # con boost disattivato il kernel riporta in cpuinfo_max_freq la frequenza # nominale (es. 3.80 GHz invece di 4.97 GHz su amd-pstate). amd_pstate_max_freq # conserva il massimo effettivo; su altri driver cpuinfo_max_freq è già corretto. cf_hw_max_khz() { _cfp0=$1 _cfmax=$(cf_read "$_cfp0/cpuinfo_max_freq" || echo 0) case "$_cfmax" in ''|*[!0-9]*) _cfmax=0 ;; esac _cfamd=$(cf_read "$_cfp0/amd_pstate_max_freq" || echo 0) case "$_cfamd" in ''|*[!0-9]*) _cfamd=0 ;; esac [ "$_cfamd" -gt "$_cfmax" ] && _cfmax=$_cfamd printf '%s\n' "$_cfmax" } cf_profiles() { printf '%s\n' quiet powersave balanced performance } cf_profile_known() { case "$1" in quiet|powersave|balanced|performance) return 0 ;; *) return 1 ;; esac } cf_profile_gov() { case "$1" in quiet|powersave|balanced) echo powersave ;; performance) echo performance ;; *) return 1 ;; esac } cf_profile_epp() { case "$1" in quiet) echo power ;; powersave) echo balance_power ;; balanced) echo balance_performance ;; performance) echo performance ;; *) return 1 ;; esac } cf_profile_boost() { case "$1" in quiet|powersave) echo 0 ;; balanced|performance) echo 1 ;; *) return 1 ;; esac } cf_profile_max_pct() { case "$1" in quiet) echo 35 ;; powersave) echo 60 ;; balanced|performance) echo 100 ;; *) return 1 ;; esac } cf_profile_label() { case "$1" in quiet) echo "Silenzioso" ;; powersave) echo "Risparmio" ;; balanced) echo "Bilanciato" ;; performance) echo "Performance" ;; custom) echo "Personalizzato" ;; *) echo "$1" ;; esac } cf_profile_desc() { case "$1" in quiet) echo "EPP power, boost off, tetto 35% dello span" ;; powersave) echo "EPP balance_power, boost off, tetto 60%" ;; balanced) echo "EPP balance_performance, boost on, nessun tetto" ;; performance) echo "governor performance, EPP performance, boost on" ;; *) echo "" ;; esac } # cf_profile_max_khz cf_profile_max_khz() { _cfp=$(cf_profile_max_pct "$1") || return 1 _cfl=$2 _cfh=$3 [ "$_cfh" -gt "$_cfl" ] || { echo "$_cfh"; return 0; } # un profilo al 100% non deve avere tetto: nessun arrotondamento [ "$_cfp" -ge 100 ] && { echo "$_cfh"; return 0; } cf_round50 $(( _cfl + (_cfh - _cfl) * _cfp / 100 )) } # Arrotonda a 50 MHz: valori leggibili e stabili fra una lettura e l'altra. cf_round50() { echo $(( ($1 + 25000) / 50000 * 50000 )) } # cf_detect_profile # Stampa il nome del profilo se lo stato coincide (tolleranza sul tetto) oppure "custom". cf_detect_profile() { _dg=$1 _de=$2 _db=$3 _dmax=$4 _dfloor=$5 _dhwmax=$6 _span=$(( _dhwmax - _dfloor )) [ "$_span" -gt 0 ] || _span=1 _tol=$(( _span / 40 )) # 2.5% dello span [ "$_tol" -lt 80000 ] && _tol=80000 for _dp in $(cf_profiles); do [ "$_dg" = "$(cf_profile_gov "$_dp")" ] || continue [ "$_db" = "$(cf_profile_boost "$_dp")" ] || continue _dp_max=$(cf_profile_max_khz "$_dp" "$_dfloor" "$_dhwmax") _diff=$(( _dmax - _dp_max )) [ "$_diff" -lt 0 ] && _diff=$(( -_diff )) [ "$_diff" -le "$_tol" ] || continue # L'EPP può non essere scrivibile con governor "performance": in quel caso # accettiamo il profilo anche se l'EPP letto non coincide. [ "$_de" = "$(cf_profile_epp "$_dp")" ] && { echo "$_dp"; return 0; } if [ "$_dg" = "performance" ] && [ "$_dp" = "performance" ]; then echo "$_dp" return 0 fi done echo custom }