Zenith CPUFreq Governor An adaptive, profile-driven CPU frequency governor for Android 12 GKI 5.10 kernels.
Zenith replaces the stock schedutil / ondemand governor with a multi-tier decision engine. It reads the same signals the scheduler does — CPU utilization, iowait, input activity, thermal pressure, PSI — and layers scenario awareness (rendering, audio, camera) and workload classification on top. The goal: lower interactive latency when you're using the phone, lower idle drain when you're not, and stay out of the way the rest of the time.
Requirements
Android kernel common-android12-5.10 (AOSP GKI branch)
arm64 (the only arch tested; portable in principle)
Clang 12.x or newer, matching the AOSP GKI toolchain
Cy, Cy in your defconfig
No vendor-module ABI changes — single-file drop into kernel/sched/cpufreq_zenith.c, no header changes, no new KMI symbols
How it picks a frequency
Every sample, Zenith walks a ladder of decision tiers — the highest tier that matches wins:
Input boost — touch event → temporary floor, decays linearly or cubically
Brutality snap — sustained heavy load → policy->max instantly (streak-gated to avoid spikes)
Hispeed — medium-high load → jump to a hispeed band
Frame-pace floor — if render thread is active → at least enough freq to hit the vblank budget
Scenario floors — audio / render / camera threads detected → per-tier floor
EAS / EM-based pick — default tier, uses the energy model
Efficient-freq ladder — low load → cap at one of the configured efficient bins
Light-load cap — very low load → drop to policy->min
On top of that, PSI pressure (memory / CPU / IO), uclamp min/max, and thermal derate act as multiplicative caps.
Profiles
Five curated presets that snapshot ~17 tunables each:
performance — aggressive ramp, no rate limits, full pin on touch
balanced — defaults + gentle bias (same shape as a stock Zenith install)
battery — slow ramp, big down-bias, capped boost, skip hispeed entirely
legacy — cpufreq_ondemand look-alike (no hysteresis)
custom — no preset, operator wires the tunables by hand
Apply a profile from:
cmdline at boot: zenith.profile=performance or per-policy zenith.policy_profile=0:battery,4:performance
sysfs at runtime: echo battery > /sys/.../cpufreq/policy*/zenith/profile
auto-tune (auto_tune=1): classifier runs every 10 s and picks a profile from load saturation + input-event rate, with optional scenario overlay (camera/render → performance, memstall → battery, audio → balanced)
Feature highlights
Input-aware boost with linear or cubic decay, cap %, and duration knobs
Frame-pace floor tied to a configurable vblank budget (16.7 ms / 8.3 ms / 6.9 ms)
Render / audio / camera awareness via comm-name matching (sysfs-configurable at runtime)
PSI-aware caps on memory pressure (CPU and IO dimensions too)
Thermal derate — level-based and rate-of-change
Efficient-freq ladder — up to 8 bins with per-bin hysteresis
uclamp floor/ceiling — respects per-task sched uclamp
Game mode levels 0/1/2 — composable overlay for aggressive scenarios
EAS fallthrough — when no tier fires, hands off to the EM-driven picker
Auto-tune classifier — periodic workload shape classification with scenario overrides
Decision stats — sysfs node dumps per-tier hit counts, boost activations, ladder holds, predictor accuracy
Zenith_decision tracepoint — single enriched tracepoint per frequency decision for perfetto / ftrace
Tuning
Every feature above is backed by a sysfs knob under /sys/devices/system/cpu/cpufreq/policy*/zenith/. New tunables default to their legacy value, so a fresh install behaves identically to a stock Zenith build until you opt in. profile_values (read-only) dumps every profile's tunable values if you want to see what each preset does without source-grepping.
Credits : https://t.me/ShadowbytePrjkt/3132