Fix AMD GPU high idle power MCLK (vram / memory clock) stuck at 96 MHz / 1000 MHz for high refresh rates on Arch Linux Wayland & Xorg
On certain resolutions & refresh rates or multi-monitor setups, you might have noticed that your GPU MCLK (vram / memory clock) is stuck at the highest clock frequency (1000 MHz) [1] [2] causing higher GPU idle power draw. On Linux kernel 6.4.x, AMDGPU MCLK (vram/memory) clocks at the lowest, causing major FPS drops while gaming [1] [2]. This is likely due to a monitor not using Coordinated Video Timings (CVT) with a low V-Blank value for the affected resolutions & refresh rates. The higher clocking behavior is due to:
The monitor's non standard timings values were likely set that way to keep its pixel clock values within display cable bandwidth constraints that are more relevant on higher resolutions & refresh rates, which is why this issue tends to occur on high resolutions & refresh rates.
Version | Limit | Data rate | Bandwidth |
---|---|---|---|
1.0-1.2a | 165 MHz | 3.96 Gbps | 4.95 Gbps |
1.3-1.4b | 340 MHz* | 8.16 Gbps | 10.2 Gbps |
2.0-2.0b | 600 MHz | 14.4 Gbps | 18 Gbps |
Check https://www.monitortests.com/blog/common-pixel-clock-limits/
You can check for this issue by monitoring your GPU MCLK/VRAM/Memory clock value with nvtop
, mangohud
or cat /sys/class/drm/card0/device/pp_dpm_mclk
(Note: try card1 if file is not found). If it's stuck at the highest clock (1000 MHz), you would also notice a higher idle power draw. If the values are stuck and do not adapt to the GPU workload, try lowering the display resolution refresh rate to see if it resolves the issue. If the issue only occurs in specific resolutions & refresh rates, then it's likely that the monitor's EDID has a too low v-blank value for the specific resolution & refresh rate.
Fix for Xorg [1]
-
Use cvt_modeline_calculator_12 to obtain modeline values for your resolution & refresh rate with CVT v1.2 reduced blanking timings:
curl https://raw.githubusercontent.com/kevinlekiller/cvt_modeline_calculator_12/master/cvt12.c --output cvt12.c gcc cvt12.c -O2 -o cvt12 -lm -Wall ./cvt12 1920 1080 144 -b
Note: change 1920 1080 144 to your resolution and refresh rate, mine is 1920x1080@144.
Output Example:
# 1920x1080 @ 144.000 Hz Reduced Blank (CVT) field rate 144.000 Hz; hsync: 166.608 kHz; pclk: 333.22 MHz Modeline "1920x1080_144.00_rb2" 333.22 1920 1928 1960 2000 1080 1143 1151 1157 +hsync -vsync
-
Use xrandr to add the custom resolution modeline:
xrandr --newmode "MCLK-fix" 333.22 1920 1928 1960 2000 1080 1143 1151 1157 +hsync -vsync xrandr --addmode HDMI-2 "MCLK-fix"
Note: replace values after "MCLK-fix" with the modeline values output from step 1 and replace HDMI-2 with your connector (run
xrandr
). -
Select the resolution and check if MCLK (VRAM / Memory) clock frequency properly adjusts to GPU workloads.
Before proceeding, try temporarily switching to xorg to test if the xorg solution works. You can skip steps 1-3 if you find your resolution & refresh rate in Some CVT-RB v2 EDID values (can use this to skip steps 1-3).
-
Use cvt_modeline_calculator_12 to obtain modeline values for your resolution & refresh rate with CVT v1.2 reduced blanking timings:
curl https://raw.githubusercontent.com/kevinlekiller/cvt_modeline_calculator_12/master/cvt12.c --output cvt12.c gcc cvt12.c -O2 -o cvt12 -lm -Wall ./cvt12 1920 1080 144 -b
Note: change 1920 1080 144 to your resolution and refresh rate, mine is 1920x1080@144Hz:
Output Example:
# 1920x1080 @ 144.000 Hz Reduced Blank (CVT) field rate 144.000 Hz; hsync: 166.608 kHz; pclk: 333.22 MHz Modeline "1920x1080_144.00_rb2" 333.22 1920 1928 1960 2000 1080 1143 1151 1157 +hsync -vsync
-
Parse the modeline to edid-generator to see its values in EDID binary format:
git clone https://github.com/akatrevorjay/edid-generator.git cd edid-generator yay -S zsh edid-decode-git automake dos2unix # Required dependencies for edid-generator zsh # Need to enter zsh shell ./modeline2edid - <<< 'Modeline "MCLK-fix" 333.22 1920 1928 1960 2000 1080 1143 1151 1157 +hsync -vsync' make
Note: replace the values after "MCLK-fix" with the modeline values output from step 1.
-
Use wxedid to open the generated edid to take note of its values:
yay -S wxedid
-
Obtain your monitor's EDID binary file:
ls /sys/class/drm/ # Use xrandr, wlr-randr, gnome-randr-rust to find the correct connector. cat /sys/class/drm/card1-HDMI-A-2/edid # Check for an output (monitor name may be visible). cp /sys/class/drm/card1-HDMI-A-2/edid edid.bin # Replace card1-HDMI-A-2 with your connector.
-
Use wxEDID to edit mointor's EDID to MCLK-fix's values:
-
Open the edid.bin file with wxEDID (
/usr/bin/wxedid
) -
Find DTD: Detailed Timing Descriptor
-
Click the DTD Constructor Tab
-
Check if X-res, V-res and V-Refresh matches your resolution and refresh rate; if not, go back to the EDID tab, then keep checking another DTD until you find it:
-
Go back to the EDID tab and change the values to match the ones in MCLK-Fix.bin:
-
Click Option on the panel -> Assemble EDID:
-
Click File on the panel -> Save EDID binary (overwrite edid.bin):
-
-
Load EDID at boot for the particular monitor:
-
Place the edid file in
/lib/firmware/edid
sudo mkdir -p /lib/firmware/edid sudo cp edid.bin /lib/firmware/edid/edid_modified.bin
-
Include the custom EDID file in the initramfs
sudoedit /etc/mkinitcpio.conf FILES=(/lib/firmware/edid/edid_modified.bin)
-
Add the kernel parameter
drm.edid_firmware=HDMI-A-2:edid/edid_modified.bin
(replace HDMI-A-2 with your connector).
-
-
Reboot and check if MCLK (VRAM / Memory) clock frequency properly adjusts to GPU workloads.
Modeline "1920x1080_60.00_rb2" 133.32 1920 1928 1960 2000 1080 1097 1105 1111 +hsync -vsync
Modeline "1920x1080_120.00_rb2" 274.56 1920 1928 1960 2000 1080 1130 1138 1144 +hsync -vsync
Modeline "1920x1080_144.00_rb2" 333.22 1920 1928 1960 2000 1080 1143 1151 1157 +hsync -vsync
Modeline "1920x1080_160.00_rb2" 373.12 1920 1928 1960 2000 1080 1152 1160 1166 +hsync -vsync
Modeline "2560x1440_60.00_rb2" 234.59 2560 2568 2600 2640 1440 1467 1475 1481 +hsync -vsync
Modeline "2560x1440_120.00_rb2" 483.12 2560 2568 2600 2640 1440 1511 1519 1525 +hsync -vsync
Modeline "2560x1440_144.00_rb2" 586.59 2560 2568 2600 2640 1440 1529 1537 1543 +hsync -vsync
I want to add that when using hyprland, you do not need to modify your edid.
monitor=$monitor1,modeline 1025.80 2560 2568 2600 2640 1440 1605 1613 1619 +hsync -vsync,$moreoptionshere
Important to not double space.
Edit: currently broken with the new implementation of aquamarine: hyprwm/Hyprland#6953