### Build and Install RyzenAdj with ryzen_smu Source: https://github.com/flygoat/ryzenadj/blob/master/README.md Compile and install RyzenAdj after the kernel module is ready. ```bash git clone https://github.com/FlyGoat/RyzenAdj cd RyzenAdj cmake -B build -DCMAKE_BUILD_TYPE=Release make -C build -j"$(nproc)" sudo cp -v build/ryzenadj /usr/local/bin/ ``` -------------------------------- ### Complete Example: Balanced Configuration Source: https://github.com/flygoat/ryzenadj/blob/master/_autodocs/11-usage-examples.md This example demonstrates applying a balanced power and thermal configuration suitable for gaming and productivity. It includes setting sustained and peak power limits, thermal throttling temperatures, VRM current limits, and fabric clock frequencies. The snippet also shows how to initialize, apply settings, read back values for verification, and clean up the ryzenadj context. ```c #include #include "lib/ryzenadj.h" int main(void) { ryzen_access ry = init_ryzenadj(); if (!ry) { fprintf(stderr, "Failed to initialize\n"); return 1; } printf("Applying balanced configuration...\n"); // Power limits (balanced for gaming/productivity) set_stapm_limit(ry, 45000); // 45W sustained set_fast_limit(ry, 60000); // 60W peak set_slow_limit(ry, 50000); // 50W average set_stapm_time(ry, 30); // 30s averaging window // Thermal management set_tctl_temp(ry, 95); // 95°C core limit set_apu_skin_temp_limit(ry, 55); // 55°C skin limit set_skin_temp_power_limit(ry, 30000); // 30W when hot // VRM current (allow good performance) set_vrm_current(ry, 140000); // 140A sustained set_vrmmax_current(ry, 200000); // 200A peak set_vrmsoc_current(ry, 40000); // 40A SoC // Fabric clocks set_max_socclk_freq(ry, 1800); // 1800 MHz SoC set_max_fclk_freq(ry, 1600); // 1600 MHz FCLK printf("Configuration applied\n"); // Read back and verify if (init_table(ry) == 0) { refresh_table(ry); printf("\nVerification:\n"); printf("STAPM: %.0f mW\n", get_stapm_limit(ry)); printf("Fast: %.0f mW\n", get_fast_limit(ry)); printf("Slow: %.0f mW\n", get_slow_limit(ry)); printf("Core Temp Limit: %.0f °C\n", get_tctl_temp(ry)); printf("Skin Temp Limit: %.0f °C\n", get_apu_skin_temp_limit(ry)); } cleanup_ryzenadj(ry); return 0; } ``` -------------------------------- ### Clone and Install ryzen_smu Source: https://github.com/flygoat/ryzenadj/blob/master/README.md Download and install the ryzen_smu kernel module. ```bash git clone https://github.com/amkillam/ryzen_smu # Active fork of the original module (cd ryzen_smu/ && sudo make dkms-install) ``` -------------------------------- ### Example: Set Power Limits Source: https://github.com/flygoat/ryzenadj/blob/master/_autodocs/03-power-limits.md Demonstrates setting the fast, slow, and STAPM power limits. Ensure ryzen_access is initialized before calling. ```c // Set fast limit to 50 W, slow limit to 30 W, STAPM to 25 W set_fast_limit(ry, 50000); set_slow_limit(ry, 30000); set_stapm_limit(ry, 25000); ``` -------------------------------- ### Install Linux Build Dependencies Source: https://github.com/flygoat/ryzenadj/blob/master/README.md Install necessary build tools and libraries for compiling RyzenAdj on various Linux distributions. ```bash sudo apt install build-essential cmake libpci-dev ``` ```bash sudo dnf install cmake gcc-c++ pciutils-devel ``` ```bash sudo pacman -S base-devel pciutils cmake ``` ```bash sudo zypper in cmake gcc14-c++ pciutils-devel ``` -------------------------------- ### RyzenAdj Library Overview Source: https://github.com/flygoat/ryzenadj/blob/master/_autodocs/00-index.md Provides context on the RyzenAdj library, including its purpose, supported processor families, core architecture, error codes, and getting started workflow. ```Markdown # RyzenAdj Library Technical Reference — Complete Index This is the complete technical reference for RyzenAdj, a power management adjustment library for AMD Ryzen Mobile processors. ## Documentation Structure The reference is organized into 11 focused documents: ### 1. **01-overview.md** — Project Context - Project purpose and design - Supported processor families (Raven through StrixHalo) - Core architecture (Public API, SMU communication, OS abstraction) - Error code reference table - Library version (19.0.0) - Getting started workflow ### 2. **02-initialization.md** — Library Lifecycle - `init_ryzenadj()` — Initialize the library and SMU communication - `cleanup_ryzenadj()` — Release all resources - `get_cpu_family()` — Detect processor variant - `get_bios_if_ver()` — Query SMU firmware version - `init_table()` — Prepare PowerMetric table for use - `refresh_table()` — Update in-memory PM table snapshot - Table metadata: `get_table_ver()`, `get_table_size()`, `get_table_values()` ### 3. **03-power-limits.md** — Power Management - STAPM (sustained) limits: setters, getters, time constant - PPT Fast (peak) limits: setters and getters - PPT Slow (average) limits: setters, getters, time constant - Practical power budget layering ### 4. **04-thermal-limits.md** — Temperature Control - Core thermal limit (Tctl): setter, limit, current value - APU skin temperature: setter, limit, current value - Discrete GPU (dGPU) skin temperature: setter, limit, current value - Skin-temperature-based power limit ### 5. **05-current-limits.md** — Power Rail Control - VRM (Voltage Regulator Module) sustained and peak current limits for core, SoC, and GFX - EDC (Electrical Design Current) peak limits - PSI (Power Stage Integration) limits for core and SoC - Overclocking: `set_enable_oc()`, `set_disable_oc()`, `set_oc_clk()`, `set_oc_volt()` ### 6. **06-frequency-clocks.md** — Clock Frequency Control - GPU (GFX) clock: min/max, voltage, temperature metrics - SoC clock: min/max (system fabric) - FCLK (CPU-GPU interconnect): min/max - VCN (video encoding): min/max - LCLK (data launch): min/max - Memory clock (MCLK): read-only - Power modes: `set_power_saving()`, `set_max_performance()` - Overclocking frequency: `set_oc_clk()`, `set_per_core_oc_clk()` ### 7. **07-core-metrics.md** — Per-Core and System Telemetry - Per-core metrics (cores 0–15): clock, voltage, temperature, power - L3 cache metrics: clock, logic, VDDM, temperature - SoC metrics: voltage, power - System-wide (socket) power measurement - Core overclocking tuning: `set_coall()`, `set_coper()`, `set_cogfx()` - Thermal throttle ramp control - CCLK boost monitoring ### 8. **08-apu-slow-limits.md** — A+A Platform Power Limits - APU slow limit (for systems with discrete GPU) - Context on A+A (APU + discrete GPU) configurations - Integration with APU power adjustment workflow - Distinction from GPU overclocking controls ### 9. **09-types.md** — Type Definitions and Constants - `ryzen_access` opaque handle type (lifetime, thread safety) - `enum ryzen_family` (all 17 supported families) - Error code constants (`ADJ_ERR_*`) - SMU response codes - Known PM table versions (16 versions documented) - Parameter units and ranges - Index parameter conventions ### 10. **10-command-line.md** — CLI Tool Reference - Usage: `ryzenadj [options]` - Informational options: `-h`, `-i`, `--dump-table` - All settable parameters mapped to library functions - 40+ command-line flags documented - Practical examples (conservative, gaming, A+A platform) - Argument parsing and error handling ### 11. **11-usage-examples.md** — Code Examples - 17 complete, runnable C examples covering: - Basic init/cleanup - Power limit setting - Thermal configuration - PM table reading and monitoring - Per-core metrics loops - VRM and current control - Frequency management - A+A platform setup - Overclocking - Power mode presets - Python ctypes integration - Error handling patterns - Balanced configuration --- ``` -------------------------------- ### Install ryzen_smu Dependencies Source: https://github.com/flygoat/ryzenadj/blob/master/README.md Install required packages for building the ryzen_smu kernel module on Fedora. ```bash sudo dnf install cmake gcc gcc-c++ dkms openssl ``` -------------------------------- ### Initialize RyzenAdj and Get CPU Info Source: https://github.com/flygoat/ryzenadj/blob/master/_autodocs/11-usage-examples.md Demonstrates how to initialize the RyzenAdj library, retrieve CPU family and BIOS interface version, and clean up resources. Ensure the library is initialized before accessing processor information. ```c #include #include "lib/ryzenadj.h" int main(void) { // Initialize library ryzen_access ry = init_ryzenadj(); if (!ry) { fprintf(stderr, "Failed to initialize RyzenAdj\n"); return 1; } // Get processor info enum ryzen_family family = get_cpu_family(ry); int bios_ver = get_bios_if_ver(ry); printf("CPU Family: %d\n", family); printf("BIOS Interface Version: %d\n", bios_ver); // Cleanup cleanup_ryzenadj(ry); return 0; } ``` -------------------------------- ### Apply Power Mode Presets Source: https://github.com/flygoat/ryzenadj/blob/master/_autodocs/11-usage-examples.md This example demonstrates switching between power modes using ryzenadj. It shows how to apply a maximum performance preset and a power-saving preset, including optionally adjusting specific power limits like STAPM and fast limits for each mode. Remember to clean up resources after use. ```c #include "lib/ryzenadj.h" int main(void) { ryzen_access ry = init_ryzenadj(); if (!ry) return 1; // Mode 1: Maximum performance (plugged in) printf("Applying max performance mode...\n"); set_max_performance(ry); // Optionally boost specific limits set_stapm_limit(ry, 50000); set_fast_limit(ry, 70000); sleep(10); // Mode 2: Power saving (on battery) printf("Applying power saving mode...\n"); set_power_saving(ry); // Optionally enforce lower limits set_stapm_limit(ry, 25000); set_fast_limit(ry, 35000); cleanup_ryzenadj(ry); return 0; } ``` -------------------------------- ### Set Minimum SoC Clock Frequency Source: https://github.com/flygoat/ryzenadj/blob/master/_autodocs/10-command-line.md Sets the minimum SoC clock frequency in Megahertz (MHz). Example: 1200 MHz. ```bash ./ryzenadj --min-socclk-frequency=1200 ``` -------------------------------- ### Get Core PSI0 Current Limit Source: https://github.com/flygoat/ryzenadj/blob/master/_autodocs/05-current-limits.md Reads the PSI0 current limit for the CPU core in milliamps. Returns NAN if the table is not initialized. ```c float CALL get_psi0_current(ryzen_access ry); ``` -------------------------------- ### Get PowerMetric Table Version Source: https://github.com/flygoat/ryzenadj/blob/master/_autodocs/02-initialization.md Retrieves the detected PowerMetric table version. Lazy-initializes the table if needed and returns the version cached at init_table() time. ```c uint32_t CALL get_table_ver(ryzen_access ry); ``` ```c uint32_t ver = get_table_ver(ry); printf("0x%x\n", ver); // Prints "0x5d0008" on Strix Point, etc. ``` -------------------------------- ### Get Core Clock, Temperature, Voltage, and Power Source: https://github.com/flygoat/ryzenadj/blob/master/_autodocs/09-types.md Functions to retrieve telemetry data for a specific core. The core index ranges from 0 to 15. ```c float CALL get_core_clk(ryzen_access ry, uint32_t core); float CALL get_core_temp(ryzen_access ry, uint32_t core); float CALL get_core_volt(ryzen_access ry, uint32_t core); float CALL get_core_power(ryzen_access ry, uint32_t core); ``` -------------------------------- ### Set Skin Temperature Power Limit Source: https://github.com/flygoat/ryzenadj/blob/master/_autodocs/04-thermal-limits.md Example of calling the set_skin_temp_power_limit function to set a 30W limit when skin temperature is high. Ensure the ryzen_access handle is properly initialized. ```c set_skin_temp_power_limit(ry, 30000); // 30 W limit when skin temp is high ``` -------------------------------- ### Set Minimum VCN Clock Frequency Source: https://github.com/flygoat/ryzenadj/blob/master/_autodocs/10-command-line.md Sets the minimum Video Core Next clock frequency in Megahertz (MHz). Example: 400 MHz. ```bash ./ryzenadj --min-vcn=400 ``` -------------------------------- ### Power Limits (STAPM, Fast, Slow) Source: https://github.com/flygoat/ryzenadj/blob/master/_autodocs/00-index.md Functions to set and get sustained, peak, and average power limits, as well as their averaging time constants. ```APIDOC ## Power Limits (STAPM, Fast, Slow) ### `set_stapm_limit()` #### Description Set the sustained power limit (STAPM). ### `get_stapm_limit()` #### Description Read the sustained power limit setting. ### `get_stapm_value()` #### Description Read the current STAPM power value. ### `set_fast_limit()` #### Description Set the peak power limit (Fast). ### `get_fast_limit()` #### Description Read the peak power limit setting. ### `get_fast_value()` #### Description Read the current fast power value. ### `set_slow_limit()` #### Description Set the average power limit (Slow). ### `get_slow_limit()` #### Description Read the average power limit setting. ### `get_slow_value()` #### Description Read the current slow power value. ### `set_stapm_time()` #### Description Set the STAPM averaging window. ### `get_stapm_time()` #### Description Read the STAPM time constant. ### `set_slow_time()` #### Description Set the slow PPT averaging window. ### `get_slow_time()` #### Description Read the slow PPT time constant. ``` -------------------------------- ### Get Fast Power Limit Source: https://github.com/flygoat/ryzenadj/blob/master/_autodocs/03-power-limits.md Reads the current fast power limit setting in milliwatts. Returns NAN if the power metric table is not initialized. ```c float CALL get_fast_limit(ryzen_access ry); ``` -------------------------------- ### Get PowerMetric Table Size Source: https://github.com/flygoat/ryzenadj/blob/master/_autodocs/02-initialization.md Retrieves the detected PowerMetric table size in bytes. Lazy-initializes the table if needed and returns the size determined at init_table() time. ```c size_t CALL get_table_size(ryzen_access ry); ``` ```c size_t sz = get_table_size(ry); printf("PM table is %zu bytes\n", sz); // Prints "0xd54" (3412 bytes) on Strix Point ``` -------------------------------- ### Get Core Clock (CCLK) Boost Setpoint Source: https://github.com/flygoat/ryzenadj/blob/master/_autodocs/07-core-metrics.md Reads the core clock boost setpoint frequency in MHz from the PowerMetric table. Returns NAN if the table is not initialized. Use this to understand the target boost frequency of the CPU. ```c float CALL get_cclk_setpoint(ryzen_access ry); ``` ```c refresh_table(ry); printf("CCLK Boost Setpoint: %.0f MHz\n", get_cclk_setpoint(ry)); ``` -------------------------------- ### Enable Overclocking and Apply Settings Source: https://github.com/flygoat/ryzenadj/blob/master/_autodocs/11-usage-examples.md This snippet shows how to initialize the ryzenadj library, enable overclocking mode, and apply various overclocking parameters such as core clock offsets, voltage boosts, and performance tuning for CPU and GPU cores. Ensure proper initialization and cleanup. ```c #include "lib/ryzenadj.h" int main(void) { ryzen_access ry = init_ryzenadj(); if (!ry) return 1; // Enable overclocking mode if (set_enable_oc(ry) == 0) { printf("Overclocking enabled\n"); // Apply core clock offset set_oc_clk(ry, 100); // +100 MHz all cores // Apply per-core offset set_per_core_oc_clk(ry, 50); // +50 MHz per-core // Apply voltage offset set_oc_volt(ry, 50); // +50 mV boost // Tune core performance set_coall(ry, 75); // All-core +75 MHz set_cogfx(ry, 100); // GPU +100 MHz set_coper(ry, 1); // Core operation setting printf("Overclocking profiles applied\n"); } else { printf("Failed to enable overclocking\n"); } cleanup_ryzenadj(ry); return 0; } ``` -------------------------------- ### Get STAPM Limit Source: https://github.com/flygoat/ryzenadj/blob/master/_autodocs/03-power-limits.md Reads the current STAPM limit setting in milliwatts. Call `refresh_table()` before this function to ensure you get the latest value. Returns NAN if the table is not initialized. ```c refresh_table(ry); float limit = get_stapm_limit(ry); printf("STAPM Limit: %.1f mW (%.1f W)\n", limit, limit / 1000); ``` -------------------------------- ### Display Help Information Source: https://github.com/flygoat/ryzenadj/blob/master/README.md View the available command-line options and usage instructions. ```bash $./ryzenadj -h ``` -------------------------------- ### Get Current STAPM Value Source: https://github.com/flygoat/ryzenadj/blob/master/_autodocs/03-power-limits.md Reads the current STAPM power consumption in milliwatts. This is a live measurement, not a limit. Call `refresh_table()` before this function to ensure you get the latest value. Returns NAN if the table is not initialized. ```c refresh_table(ry); float current = get_stapm_value(ry); float limit = get_stapm_limit(ry); printf("STAPM: %.1f / %.1f mW\n", current, limit); ``` -------------------------------- ### Get CPU Family Enumeration Source: https://github.com/flygoat/ryzenadj/blob/master/_autodocs/02-initialization.md Retrieves the detected CPU family. This function returns a cached value and does not re-check the CPUID. ```c enum ryzen_family CALL get_cpu_family(ryzen_access ry); ``` ```c const char *family_name(enum ryzen_family fam) { switch (fam) { case FAM_RAVEN: return "Raven"; case FAM_RENOIR: return "Renoir"; case FAM_STRIXPOINT: return "Strix Point"; default: return "Unknown"; } } printf("CPU: %s\n", family_name(get_cpu_family(ry))); ``` -------------------------------- ### init_ryzenadj() Source: https://github.com/flygoat/ryzenadj/blob/master/_autodocs/02-initialization.md Initializes the library and establishes communication with the SMU. It detects the CPU family, initializes OS-specific access objects, and connects to MP1 and PSMU. Initialization is lazy for the PowerMetric table. ```APIDOC ## init_ryzenadj() ### Description Initializes the library and establishes communication with the SMU. It detects the CPU family, initializes OS-specific access objects, and connects to MP1 and PSMU. Initialization is lazy for the PowerMetric table. ### Method `CALL` (C function) ### Parameters None. ### Return Type `ryzen_access` — Opaque handle to a `_ryzen_access` structure. Returns `NULL` if initialization fails. ### Behavior - Detects CPU family via CPUID - Returns `NULL` if the processor is not an AMD Ryzen Mobile APU - Initializes OS-specific access objects (libpci on Linux, WinRing0 on Windows) - Connects to MP1 (ARM CPU running SMU) and PSMU (power SMU) via PCI configuration space - Lazy-initializes the PowerMetric table on first table access (does not call `init_table()` automatically) ### Throws / Errors Returns `NULL` on: - Non-AMD or unsupported processor family - Insufficient permissions (missing root on Linux, admin on Windows) - Failure to locate SMU objects (hardware compatibility issue) - Out of memory during allocation ### Example ```c #include #include "lib/ryzenadj.h" int main(void) { ryzen_access ry = init_ryzenadj(); if (!ry) { fprintf(stderr, "RyzenAdj initialization failed\n"); return 1; } enum ryzen_family family = get_cpu_family(ry); printf("CPU Family: %d\n", family); cleanup_ryzenadj(ry); return 0; } ``` ``` -------------------------------- ### Display Help Message Source: https://github.com/flygoat/ryzenadj/blob/master/_autodocs/10-command-line.md Use the -h or --help option to display the full command-line usage, including all available options and their descriptions. This is useful for understanding the tool's capabilities. ```bash ./ryzenadj -h ``` -------------------------------- ### Get SoC PSI0 Current Limit Source: https://github.com/flygoat/ryzenadj/blob/master/_autodocs/05-current-limits.md Reads the PSI0 current limit for the SoC in milliamps. Returns NAN if the table is not initialized. ```c float CALL get_psi0soc_current(ryzen_access ry); ``` -------------------------------- ### Build RyzenAdj on Linux Source: https://github.com/flygoat/ryzenadj/blob/master/README.md Standard procedure to clone, build, and symlink the RyzenAdj binary. ```bash git clone https://github.com/FlyGoat/RyzenAdj.git cd RyzenAdj rm -r win32 mkdir build && cd build cmake -DCMAKE_BUILD_TYPE=Release .. make if [ -d ~/.local/bin ]; then ln -s $(readlink -f ryzenadj) ~/.local/bin/ryzenadj && echo "symlinked to ~/.local/bin/ryzenadj"; fi if [ -d ~/.bin ]; then ln -s $(readlink -f ryzenadj) ~/.bin/ryzenadj && echo "symlinked to ~/.bin/ryzenadj"; fi ``` -------------------------------- ### Set Minimum GFX Clock Frequency Source: https://github.com/flygoat/ryzenadj/blob/master/_autodocs/10-command-line.md Sets the minimum GPU clock frequency in Megahertz (MHz). Example: 800 MHz. ```bash ./ryzenadj --min-gfxclk=800 ``` -------------------------------- ### Initialization & Lifecycle Source: https://github.com/flygoat/ryzenadj/blob/master/_autodocs/00-index.md Functions for initializing the library, detecting the processor, connecting to the SMU, and cleaning up resources. ```APIDOC ## Initialization & Lifecycle ### `init_ryzenadj()` #### Description Initialize library, detect processor, and connect to the SMU. ### `cleanup_ryzenadj()` #### Description Release all resources allocated by the library. ### `get_cpu_family()` #### Description Get the detected CPU family. ### `get_bios_if_ver()` #### Description Get the SMU BIOS interface version. ``` -------------------------------- ### Set Minimum Fabric Clock Frequency Source: https://github.com/flygoat/ryzenadj/blob/master/_autodocs/10-command-line.md Sets the minimum fabric clock frequency in Megahertz (MHz). Example: 800 MHz. ```bash ./ryzenadj --min-fclk-frequency=800 ``` -------------------------------- ### Set Ryzen Power Limits Source: https://github.com/flygoat/ryzenadj/blob/master/_autodocs/11-usage-examples.md Shows how to set sustained, peak, and average power limits, along with the time window for sustained limits. Check return values to ensure limits were applied successfully. ```c #include "lib/ryzenadj.h" int main(void) { ryzen_access ry = init_ryzenadj(); if (!ry) return 1; // Set power limits int err1 = set_stapm_limit(ry, 45000); // 45W sustained int err2 = set_fast_limit(ry, 60000); // 60W peak int err3 = set_slow_limit(ry, 50000); // 50W average int err4 = set_stapm_time(ry, 30); // 30 second window if (err1 == 0 && err2 == 0 && err3 == 0 && err4 == 0) { printf("Power limits applied successfully\n"); } else { fprintf(stderr, "Some limits failed to apply\n"); } cleanup_ryzenadj(ry); return 0; } ``` -------------------------------- ### Set Maximum SoC Clock Frequency Source: https://github.com/flygoat/ryzenadj/blob/master/_autodocs/10-command-line.md Sets the maximum SoC clock frequency in Megahertz (MHz). Example: 1800 MHz. ```bash ./ryzenadj --max-socclk-frequency=1800 ``` -------------------------------- ### Initialize RyzenAdj Library Source: https://github.com/flygoat/ryzenadj/blob/master/_autodocs/02-initialization.md Call `init_ryzenadj()` to initialize the library and establish communication with the SMU. It detects the CPU family and initializes OS-specific access objects. Returns `NULL` on failure, such as unsupported processors or insufficient permissions. ```c #include #include "lib/ryzenadj.h" int main(void) { ryzen_access ry = init_ryzenadj(); if (!ry) { fprintf(stderr, "RyzenAdj initialization failed\n"); return 1; } enum ryzen_family family = get_cpu_family(ry); printf("CPU Family: %d\n", family); cleanup_ryzenadj(ry); return 0; } ``` -------------------------------- ### Dump Full Settings Table Source: https://github.com/flygoat/ryzenadj/blob/master/_autodocs/10-command-line.md Outputs the entire configuration table for detailed analysis without applying any changes. ```bash ./ryzenadj --dump-table ``` -------------------------------- ### Show System Information and Power Metrics Source: https://github.com/flygoat/ryzenadj/blob/master/_autodocs/10-command-line.md The -i or --info option displays CPU family, SMU BIOS Interface version, RyzenAdj version, and a markdown-formatted table of key power metrics. This is useful for monitoring current system power states. ```bash ./ryzenadj -i ``` -------------------------------- ### Thermal Limits Source: https://github.com/flygoat/ryzenadj/blob/master/_autodocs/00-index.md Functions to set and get thermal throttle limits for cores and APU/dGPU skin temperatures, and related power limit adjustments. ```APIDOC ## Thermal Limits ### `set_tctl_temp()` #### Description Set the core thermal throttle limit. ### `get_tctl_temp()` #### Description Read the core throttle limit setting. ### `get_tctl_temp_value()` #### Description Read the current core temperature. ### `set_apu_skin_temp_limit()` #### Description Set the APU skin temperature limit. ### `get_apu_skin_temp_limit()` #### Description Read the APU skin temperature limit setting. ### `get_apu_skin_temp_value()` #### Description Read the current APU skin temperature. ### `set_dgpu_skin_temp_limit()` #### Description Set the dGPU skin temperature limit. ### `get_dgpu_skin_temp_limit()` #### Description Read the dGPU skin temperature limit setting. ### `get_dgpu_skin_temp_value()` #### Description Read the current dGPU skin temperature. ### `set_skin_temp_power_limit()` #### Description Set a power limit based on skin temperature. ### `set_prochot_deassertion_ramp()` #### Description Set the throttle ramp after a thermal event. ``` -------------------------------- ### Inspect Current Settings Source: https://github.com/flygoat/ryzenadj/blob/master/_autodocs/10-command-line.md Reads and displays the current power and thermal settings without making any modifications. ```bash ./ryzenadj --info ``` -------------------------------- ### Set Maximum GFX Clock Frequency Source: https://github.com/flygoat/ryzenadj/blob/master/_autodocs/10-command-line.md Sets the maximum GPU (GFX) clock frequency in Megahertz (MHz). Example: 1500 MHz. ```bash ./ryzenadj --max-gfxclk=1500 ``` -------------------------------- ### Set Maximum Fabric Clock Frequency Source: https://github.com/flygoat/ryzenadj/blob/master/_autodocs/10-command-line.md Sets the maximum fabric (CPU-GPU) clock frequency in Megahertz (MHz). Example: 1600 MHz. ```bash ./ryzenadj --max-fclk-frequency=1600 ``` -------------------------------- ### Python Library Usage with ctypes Source: https://github.com/flygoat/ryzenadj/blob/master/_autodocs/11-usage-examples.md Demonstrates how to load and use the RyzenAdj library from Python using the ctypes module. Includes initialization, setting power limits, and cleanup. ```python import os import sys from ctypes import * # Load the library if sys.platform == 'win32': lib = cdll.LoadLibrary('libryzenadj') else: lib = cdll.LoadLibrary('libryzenadj.so') # Configure ctypes return types lib.init_ryzenadj.restype = c_void_p lib.get_cpu_family.restype = c_int lib.get_stapm_limit.restype = c_float # Initialize ry = lib.init_ryzenadj() if not ry: sys.exit("Failed to init RyzenAdj") try: # Get CPU family family = lib.get_cpu_family(ry) print(f"CPU Family: {family}") # Set power limits lib.set_stapm_limit.argtypes = [c_void_p, c_uint] lib.set_stapm_limit(ry, 45000) # Initialize and read metrics lib.init_table.argtypes = [c_void_p] lib.refresh_table.argtypes = [c_void_p] lib.init_table(ry) lib.refresh_table(ry) # Read value lib.get_stapm_limit.argtypes = [c_void_p] limit = lib.get_stapm_limit(ry) print(f"STAPM Limit: {limit:.0f} mW") finally: # Cleanup lib.cleanup_ryzenadj.argtypes = [c_void_p] lib.cleanup_ryzenadj(ry) ``` -------------------------------- ### Set VRM Current Limit Source: https://github.com/flygoat/ryzenadj/blob/master/_autodocs/10-command-line.md Sets the VRM current limit (TDC LIMIT VDD) in milliamps. Example: 140000 mA = 140 A. ```bash ./ryzenadj --vrm-current=140000 ``` -------------------------------- ### Import MOK for Secure Boot Source: https://github.com/flygoat/ryzenadj/blob/master/README.md Import the DKMS public key to the MOK manager for Secure Boot support. ```bash sudo mokutil --import /var/lib/dkms/mok.pub ``` -------------------------------- ### Monitor Power Metrics Periodically Source: https://github.com/flygoat/ryzenadj/blob/master/_autodocs/11-usage-examples.md This C code snippet demonstrates how to initialize the ryzenadj library, set up a monitoring loop, and periodically refresh and print power metrics such as STAPM, fast/slow current, and core temperature. It runs for a fixed duration before cleaning up. ```c #include #include #include "lib/ryzenadj.h" int main(void) { ryzen_access ry = init_ryzenadj(); if (!ry) return 1; if (init_table(ry) != 0) { cleanup_ryzenadj(ry); return 1; } printf("Monitoring power metrics (Ctrl+C to stop)... "); printf("Time | STAPM | Fast | Slow | Core Temp "); printf("----------|--------|--------|--------|---------- "); for (int i = 0; i < 60; i++) { // 60 iterations refresh_table(ry); time_t now = time(NULL); struct tm *tm_info = localtime(&now); char time_str[10]; strftime(time_str, sizeof(time_str), "%H:%M:%S", tm_info); printf("%s | %.0f | %.0f | %.0f | %.1f°C\n", time_str, get_stapm_value(ry), get_fast_value(ry), get_slow_value(ry), get_tctl_temp_value(ry)); sleep(1); // Wait 1 second between refreshes } cleanup_ryzenadj(ry); return 0; } ``` -------------------------------- ### Get SoC VRM Current Limit Source: https://github.com/flygoat/ryzenadj/blob/master/_autodocs/05-current-limits.md Reads the current VRM current limit setting for the SoC power rail. Returns the limit in milliamps (mA). ```c float CALL get_vrmsoc_current(ryzen_access ry); ``` -------------------------------- ### Get Core VRM Current Limit Source: https://github.com/flygoat/ryzenadj/blob/master/_autodocs/05-current-limits.md Reads the current VRM current limit setting for the core power rail. Returns the limit in milliamps (mA). ```c float CALL get_vrm_current(ryzen_access ry); ``` -------------------------------- ### Apply Power and Temperature Limits Source: https://github.com/flygoat/ryzenadj/blob/master/README.md Set sustained, fast, and slow power limits to 45W and the Tctl temperature limit to 90 degrees Celsius. ```bash ./ryzenadj --stapm-limit=45000 --fast-limit=45000 --slow-limit=45000 --tctl-temp=90 ``` -------------------------------- ### init_table() Source: https://github.com/flygoat/ryzenadj/blob/master/_autodocs/02-initialization.md Prepares the PowerMetric table for reading and writing by detecting its version, size, and requesting its physical address. It also initializes an in-memory buffer for the table. This function can be called explicitly to detect errors early or ensure table operations are complete. ```APIDOC ## init_table() ### Description Prepare the PowerMetric table for reading and writing. ### Method Signature ```c int CALL init_table(ryzen_access ry); ``` ### Parameters #### Path Parameters - **ry** (`ryzen_access`) - Required - Handle returned by `init_ryzenadj()`. ### Return Type `int` — Status code. `0` on success, negative on error. ### Error Codes - `-1` (`ADJ_ERR_FAM_UNSUPPORTED`) — PM table not supported on this family - `-3` (`ADJ_ERR_SMU_UNSUPPORTED`) — SMU firmware does not support table operations - `-4` (`ADJ_ERR_SMU_REJECTED`) — SMU rejected the request - `-5` (`ADJ_ERR_MEMORY_ACCESS`) — Failed to open or access physical memory ### Behavior 1. Detects table version via SMU service request (0x6 or 0xC depending on family) 2. Determines table size based on version (known mappings; unknown versions assume 0x1000 bytes) 3. Requests table physical address via SMU service (0x66 or 0xB) 4. Initializes OS-level memory access to that address 5. For `ryzen_smu` kernel module: overrides detected size with actual kernel-reported size 6. Allocates a float buffer to cache the table in user-space memory 7. Calls `refresh_table()` once to populate the buffer 8. On Raven/Picasso, retries with a 10ms delay if the first refresh returns zeros (boot-time quirk) ### Lazy Initialization Setter and getter functions automatically call `init_table()` if the table has not been initialized (via a `_lazy_init_table` macro). You may call `init_table()` explicitly to detect errors early or to ensure table operations are complete before proceeding. ### Example ```c int err = init_table(ry); if (err) { fprintf(stderr, "Failed to init PM table: %d\n", err); cleanup_ryzenadj(ry); return 1; } printf("PM table version: 0x%x\n", get_table_ver(ry)); printf("PM table size: %zu bytes\n", get_table_size(ry)); ``` ``` -------------------------------- ### Read Per-Core Metrics Source: https://github.com/flygoat/ryzenadj/blob/master/_autodocs/11-usage-examples.md This C code snippet shows how to initialize the ryzenadj library and retrieve per-core performance metrics including clock speed, voltage, temperature, and power consumption for up to 8 cores. It includes error handling for table initialization and checks for valid clock speed data. ```c #include #include #include "lib/ryzenadj.h" int main(void) { ryzen_access ry = init_ryzenadj(); if (!ry) return 1; if (init_table(ry) != 0) { cleanup_ryzenadj(ry); return 1; } refresh_table(ry); printf("Per-Core Metrics:\n"); printf("Core | Clock | Volt | Temp | Power\n"); printf("-----|---------|------|------|-------\n"); for (int i = 0; i < 8; i++) { float clk = get_core_clk(ry, i); float volt = get_core_volt(ry, i); float temp = get_core_temp(ry, i); float power = get_core_power(ry, i); if (!isnan(clk)) { printf("%4d | %7.0f | %.2f | %.1f | %.1f\n", i, clk, volt, temp, power); } } cleanup_ryzenadj(ry); return 0; } ``` -------------------------------- ### Conservative Power Budget for Thin Laptops Source: https://github.com/flygoat/ryzenadj/blob/master/_autodocs/10-command-line.md Sets sustained, fast, and average power limits, along with conservative thermal limits for thin laptops. ```bash ./ryzenadj \ --stapm-limit=30000 \ --fast-limit=35000 \ --slow-limit=25000 \ --tctl-temp=85 \ --apu-skin-temp=45 \ --vrmmax-current=100000 \ --info ``` -------------------------------- ### Balanced Power Budget for Gaming Laptops Source: https://github.com/flygoat/ryzenadj/blob/master/_autodocs/10-command-line.md Increases the power budget for gaming laptops while managing thermals and setting VRM current limits. ```bash ./ryzenadj \ --stapm-limit=45000 \ --fast-limit=60000 \ --slow-limit=40000 \ --tctl-temp=95 \ --apu-skin-temp=55 \ --vrm-current=140000 \ --vrmmax-current=200000 \ --max-socclk-frequency=1800 \ --info ``` -------------------------------- ### Get Current APU Skin Temperature Value Source: https://github.com/flygoat/ryzenadj/blob/master/_autodocs/04-thermal-limits.md Reads the current APU skin temperature. This function provides a live measurement of the external case temperature. ```c float CALL get_apu_skin_temp_value(ryzen_access ry); ``` ```c refresh_table(ry); printf("APU Skin: %.1f / %.1f °C\n", get_apu_skin_temp_value(ry), get_apu_skin_temp_limit(ry)); ``` -------------------------------- ### Read Power Management Table Metrics Source: https://github.com/flygoat/ryzenadj/blob/master/_autodocs/11-usage-examples.md This C code snippet demonstrates how to initialize the ryzenadj library, read various power management table metrics like STAPM, Fast Limit, Slow Limit, and temperature, and then clean up the resources. ```c #include #include #include "lib/ryzenadj.h" int main(void) { ryzen_access ry = init_ryzenadj(); if (!ry) return 1; // Initialize table (must be done before reading metrics) if (init_table(ry) != 0) { fprintf(stderr, "Failed to initialize PM table\n"); cleanup_ryzenadj(ry); return 1; } // Refresh to get latest values refresh_table(ry); // Read metrics printf("PM Table Version: 0x%x\n", get_table_ver(ry)); printf("PM Table Size: %zu bytes\n", get_table_size(ry)); float stapm_limit = get_stapm_limit(ry); float stapm_value = get_stapm_value(ry); printf("STAPM: %.0f / %.0f mW\n", stapm_value, stapm_limit); float fast_limit = get_fast_limit(ry); float fast_value = get_fast_value(ry); printf("Fast Limit: %.0f / %.0f mW\n", fast_value, fast_limit); float slow_limit = get_slow_limit(ry); float slow_value = get_slow_value(ry); printf("Slow Limit: %.0f / %.0f mW\n", slow_value, slow_limit); float core_temp = get_tctl_temp_value(ry); float temp_limit = get_tctl_temp(ry); printf("Core Temp: %.1f / %.1f °C\n", core_temp, temp_limit); cleanup_ryzenadj(ry); return 0; } ``` -------------------------------- ### CLI Command Execution Source: https://github.com/flygoat/ryzenadj/blob/master/README.md The primary interface for interacting with the RyzenAdj tool to adjust system power metrics. ```APIDOC ## CLI Execution ### Description Executes power management adjustments on Ryzen Mobile Processors using command-line flags. ### Method CLI Execution ### Parameters #### Options - **-i, --info** (flag) - Optional - Show information and power metrics after adjustment. - **--dump-table** (flag) - Optional - Show the full power metric table before and after adjustment. #### Settings - **-a, --stapm-limit** (u32) - Optional - Sustained Power Limit (mW). - **-b, --fast-limit** (u32) - Optional - Actual Power Limit (PPT LIMIT FAST) (mW). - **-c, --slow-limit** (u32) - Optional - Average Power Limit (PPT LIMIT SLOW) (mW). - **-f, --tctl-temp** (u32) - Optional - Tctl Temperature Limit (degree C). - **-g, --vrm-current** (u32) - Optional - VRM Current Limit (TDC LIMIT VDD) (mA). - **-w, --max-gfxclk** (u32) - Optional - Maximum GFX Clock (MHz). ### Request Example ./ryzenadj --stapm-limit=45000 --fast-limit=45000 --slow-limit=45000 --tctl-temp=90 ``` -------------------------------- ### Get SMU BIOS Interface Version Source: https://github.com/flygoat/ryzenadj/blob/master/_autodocs/02-initialization.md Retrieves the SMU BIOS Interface version. This function caches the result after the first call and returns 0 on failure. ```c int CALL get_bios_if_ver(ryzen_access ry); ``` ```c printf("SMU BIOS Interface Version: %d\n", get_bios_if_ver(ry)); ``` -------------------------------- ### Enable Maximum Performance Mode Source: https://github.com/flygoat/ryzenadj/blob/master/_autodocs/10-command-line.md Activates a predefined high-performance configuration. Behavior is device and firmware-specific. ```bash ./ryzenadj --max-performance ``` -------------------------------- ### Set Maximum VCN Clock Frequency Source: https://github.com/flygoat/ryzenadj/blob/master/_autodocs/10-command-line.md Sets the maximum Video Core Next (VCN) clock frequency in Megahertz (MHz). Example: 800 MHz. ```bash ./ryzenadj --max-vcn=800 ``` -------------------------------- ### Set Frequency Limits Source: https://github.com/flygoat/ryzenadj/blob/master/_autodocs/11-usage-examples.md Configure maximum and minimum clock frequencies for SoC, FCLK, VCN, and LCLK. Ensure ryzenadj is initialized and cleaned up properly. ```c #include "lib/ryzenadj.h" int main(void) { ryzen_access ry = init_ryzenadj(); if (!ry) return 1; // Set SoC (system fabric) clock set_max_socclk_freq(ry, 1800); // 1800 MHz max set_min_socclk_freq(ry, 1200); // 1200 MHz min // Set FCLK (CPU-GPU interconnect) set_max_fclk_freq(ry, 1600); // 1600 MHz max set_min_fclk_freq(ry, 800); // 800 MHz min // Set video encoding clock set_max_vcn(ry, 800); // 800 MHz max set_min_vcn(ry, 400); // 400 MHz min // Set data launch clock set_max_lclk(ry, 400); // 400 MHz max set_min_lclk(ry, 200); // 200 MHz min printf("Frequency limits configured\n"); cleanup_ryzenadj(ry); return 0; } ``` -------------------------------- ### Set VRM Maximum Current Limit Source: https://github.com/flygoat/ryzenadj/blob/master/_autodocs/10-command-line.md Sets the VRM maximum current limit (EDC LIMIT VDD) in milliamps. Example: 200000 mA = 200 A. ```bash ./ryzenadj --vrmmax-current=200000 ``` -------------------------------- ### Set VRM SoC Current Limit Source: https://github.com/flygoat/ryzenadj/blob/master/_autodocs/10-command-line.md Sets the VRM SoC current limit (TDC LIMIT SoC) in milliamps. Example: 40000 mA = 40 A. ```bash ./ryzenadj --vrmsoc-current=40000 ``` -------------------------------- ### Set Fast Power Limit Source: https://github.com/flygoat/ryzenadj/blob/master/_autodocs/10-command-line.md Configure the fast (peak) power limit (PPT LIMIT FAST) in milliwatts. This controls the maximum power the CPU can draw for short bursts. ```bash ./ryzenadj --fast-limit=50000 ``` -------------------------------- ### System Information and Monitoring Source: https://github.com/flygoat/ryzenadj/wiki/Options Commands for retrieving system information and monitoring power metric tables. ```APIDOC ## --info ### Description Displays basic system information, including versions and CPU family, and shows important power metrics after adjustments. ## --dump-table ### Description Displays the entire power metric table before and after adjustments to verify if changes were applied successfully. ``` -------------------------------- ### Get APU Skin Temperature Limit Source: https://github.com/flygoat/ryzenadj/blob/master/_autodocs/04-thermal-limits.md Reads the APU skin temperature limit setting. This function retrieves the currently configured maximum external case temperature. ```c float CALL get_apu_skin_temp_limit(ryzen_access ry); ``` -------------------------------- ### Configure A+A Platform Settings Source: https://github.com/flygoat/ryzenadj/blob/master/_autodocs/11-usage-examples.md Set power and thermal limits for APU and dGPU on A+A platforms. The `set_apu_slow_limit` function returns -1 if the platform is not A+A. ```c #include "lib/ryzenadj.h" int main(void) { ryzen_access ry = init_ryzenadj(); if (!ry) return 1; // Configure for A+A (APU + discrete GPU) platform // APU power limits (integrated GPU) set_stapm_limit(ry, 25000); // 25W sustained set_fast_limit(ry, 40000); // 40W peak set_slow_limit(ry, 30000); // 30W average // APU-specific slow limit (when dGPU is active) int err = set_apu_slow_limit(ry, 20000); // 20W for APU if (err == -1) { printf("Note: Not an A+A platform\n"); } else if (err == 0) { printf("A+A configuration applied\n"); } // Thermal limits set_tctl_temp(ry, 90); set_apu_skin_temp_limit(ry, 50); set_dgpu_skin_temp_limit(ry, 85); // dGPU thermal limit cleanup_ryzenadj(ry); return 0; } ``` -------------------------------- ### Get Current Core VRM Current Draw Source: https://github.com/flygoat/ryzenadj/blob/master/_autodocs/05-current-limits.md Reads the live current draw from the core power rail in milliamps (mA). This provides a real-time measurement of the current being consumed. ```c float CALL get_vrm_current_value(ryzen_access ry); ``` ```c refresh_table(ry); printf("VRM Current: %.0f / %.0f mA\n", get_vrm_current_value(ry), get_vrm_current(ry)); ```