Skip to main content

Fan control

The console's embedded controller (EMC) runs the fan through its own "autoservo" firmware. Linux can either hand that firmware a target temperature and let it ramp the fan, or set the fan duty itself from a temperature curve. Which one you start with depends on the kernel:

KernelDefaultInterface
Upstream (current packages) and rmuxnet's kernelKernel curve, on at boot. Nothing to install.hwmon ps5_fan; pwm1_enable 2 is the curve.
PS5 Bazzite DeckFirmware control toward an 80 °C target, set by the driver at boot (v2.5 and v2.5.1 started on the kernel curve instead).hwmon ps5_fan plus target_temp; pwm1_enable 2 is the curve, 3 the firmware.
Older upstream kernelsFirmware control toward target_temp, 80 °C by default. The oldest kernels had no fan driver at all and left the fan off until ps5_control --fan on.target_temp only.

Change it from Game Mode or the desktop​

The easiest way is NotHavocc's PS5 Hardware Control, in two forms that do the same:

Its Fan tab shows the temperatures and switches between Target and Curve. On kernels with the hwmon driver, PS5 Bazzite Deck included, it runs every setting as a kernel curve (pwm1_enable 2), a target too: a target there is a curve that reaches 45% at the target and full speed 6 °C above it. Restore on Startup re-applies your setting at every start, because the kernel starts from its default again.

To go back to the console's own control on PS5 Bazzite Deck, turn Restore on Startup off and restart, or write a target directly:

echo 80 | sudo tee /sys/bus/platform/devices/ps5-fan/target_temp

hwmon driver​

Find the device:

grep -l ps5_fan /sys/class/hwmon/hwmon*/name
AttributeMeaning
temp1_input to temp4_inputFan zone temperatures MainSoC and Local1 to Local3, in millidegrees.
temp5_inputLocal4, the ICC's sensor 18. Part of the upstream driver; rmuxnet's kernel leaves it out.
pwm1Fan duty, 0 to 255. Read it for the current duty; write it in manual mode.
pwm1_enable0 = full speed, 1 = manual (pwm1), 2 = the kernel curve. PS5 Bazzite Deck adds 3, the firmware's autoservo, and starts there.
pwm1_auto_point1_temp to pwm1_auto_point8_temp, ..._pwmThe curve: eight temperature and duty points.
pwm1_auto_point1_temp_hystThe temperature below which the fan stops, 45 °C by default.
curve_resetWrite 1 to restore the default curve.
fan1_inputFan speed in RPM, where the console reports it. On a PS5 Pro it reads n/a, which is normal.

The default curve:

MainSoC50 °C60 °C65 °C70 °C75 °C80 °C85 °C87 °C
Duty10%30%40%50%65%80%95%100%

Below 45 °C the fan stops. The duty follows a filtered temperature with slew limiting, so the fan doesn't hunt; above 80 °C it follows the raw reading. At 90 °C the driver goes to full speed and stays there until the SoC is below 85 °C, in any mode; if the hardware stops answering it falls back to the firmware's own control. The boot log names the mode it started in: on upstream and rmuxnet's kernels quiet fan curve enabled; configure through hwmonN, on PS5 Bazzite Deck firmware fan control (pwm1_enable 3, target 80 C); the kernel curve is pwm1_enable 2 through hwmonN.

A cooler, louder curve, for example 60% from 70 °C:

H=$(dirname $(grep -l ps5_fan /sys/class/hwmon/hwmon*/name))
echo 153 | sudo tee $H/pwm1_auto_point4_pwm

A point's temperature has to stay between its neighbours and at most 90 °C, the duties have to rise with the temperatures and the last point stays at 100%; the driver rejects anything else. Settings don't survive a reboot: put them in a systemd unit or a udev rule.

Manual duty, for example 50%:

echo 1 | sudo tee $H/pwm1_enable
echo 128 | sudo tee $H/pwm1

Back to the curve: echo 2 | sudo tee $H/pwm1_enable.

PS5 Bazzite Deck

The image starts in firmware mode (pwm1_enable 3) with an 80 °C target that the driver sets at boot and again after sleep; ps5_fan.curve=1 in cmdline.txt starts with the curve instead. Writing target_temp (40 to 90) returns to firmware control, and so does the driver after an emergency. v2.5 and v2.5.1 started on the curve, and kept the firmware's lower target during sleep and shutdown, which made the fan ramp up then; v2.6.1 fixes both.

Target temperature (older kernels and PS5 Bazzite Deck)​

Kernels without the curve, and PS5 Bazzite Deck in its default mode, set a target SoC temperature and nothing else. The EMC's firmware then speeds the fan up or slows it down to hold that temperature; you don't set a duty or an RPM.

/sys/bus/platform/devices/ps5-fan/target_temp

Read the current target:

cat /sys/bus/platform/devices/ps5-fan/target_temp

Set a lower target for more cooling at the cost of noise, for example 65 °C:

echo 65 | sudo tee /sys/bus/platform/devices/ps5-fan/target_temp

The driver accepts 0 to 100 °C (PS5 Bazzite Deck from v2.6.1: 40 to 90 °C). A very low target doesn't make the fan a "max" switch: the firmware ramps as far as it needs to for any target, and below roughly 40 °C the fan is constantly audible while the SoC temperature barely moves any more. Pick a target you are happy to listen to.

On the oldest kernels, without a fan driver, the fan stays off until ps5_control --fan on from ps5-linux-tools turns it on; its install.sh installs ps5fan.service so that happens at every boot, see Clocks and boost.

ps5ctl​

ps5ctl is a TUI, CLI and web panel for the fan target, the LED, the buzzer and the GPU clock. It needs a kernel with target_temp, which rmuxnet's own kernel no longer has:

sudo ps5ctl --temp 65

Or use the Fan tab in sudo ps5ctl.

Standalone fan_mode kernel module​

A small out-of-tree module for benchmarking, which puts the fan into one of the EMC's fixed modes (auto, max or min) instead of following a target. It talks to the EMC with the same ICC commands the driver uses.

Build it:

make -C /lib/modules/$(uname -r)/build M=$PWD obj-m=fan_mode.o modules

Force maximum speed:

sudo insmod fan_mode.ko zone=0 fan_mode=2 ; sudo rmmod fan_mode

Return to automatic mode:

sudo insmod fan_mode.ko zone=0 fan_mode=1 ; sudo rmmod fan_mode

There is no percentage here, only the three EMC modes; for a duty, use the hwmon driver above. Max is very loud.

No separate GPU temperature sensor​

The CPU and GPU sit on one die, so there is no GPU-only temperature. The number to watch is the APU temperature Tctl from k10temp (the current kernels bind it to the PS5's CPU model 0x48); it covers both:

cat /sys/class/hwmon/hwmon*/temp*_label # find Tctl
cat /sys/class/hwmon/hwmon*/temp*_input # value in millidegrees Celsius

On a PS5 Pro the SMU backend adds a GPU temperature of its own, see PS5 Pro.

The GPU clock is reported by the devfreq driver of your kernel: look under /sys/class/devfreq/ for the device name (ps5-gpufreq on current kernels) and read its cur_freq. At idle the clock sits at the governor's minimum.

Fan problems​

  • Louder and hunting at idle on PS5 Bazzite Deck v2.5 and v2.5.1 (ps5-perf status shows kernel curve): the 7.3.1 kernel started on its own curve. v2.6.1 returns to the console's firmware control with an 80 °C target. Until you update, a quieter curve from PS5 Hardware Control helps.
  • Target back at 50 °C after sleep: some PS5 Bazzite Deck releases; fixed in the current one.
  • Fan or CPU boost off: on upstream kernels the CPU boost is off until you install ps5-linux-tools and enable ps5boost.service; older upstream kernels also needed ps5fan.service, current ones run a fan curve by themselves. On rmuxnet's kernel the fan curve and the GPU clock are automatic and the CPU boost is a sysfs switch; on PS5 Bazzite Deck both are on. See Other distros and Clocks and boost.