~mlaparie/tdpadj

A simple script around RyzenAdj to manipulate TDP of Ryzen APUs
Improve /etc/sudoers instructions and update tdpadj to correctly use ryzenadj in PATH if not set in tdpadj's configuration
Improve all prompts with colours, README instructions especially for keybindings, videos

refs

master
browse  log 

clone

read-only
https://git.sr.ht/~mlaparie/tdpadj
read/write
git@git.sr.ht:~mlaparie/tdpadj

You can also use your local clone with git send-email.

#tdpadj is a script around FlyGoat/RyzenAdj to manipulate TDP on Ryzen APUs

Usage: tmpadj ARG
Where ARG is optional and is either:
  a numerical value in Watts
  an increment from +1 to +10 or a decrement from -1 to -10
  a keyword such as up, inc, increase, dn, down, dec, decrease, min, max
If no ARG is supplied, you will be prompted to enter a value."

#Rationale

The typical use case for tdpadj is to assign it to global keybindings using your WM or status bar to enter a new TDP value while multitasking or increment from the current TDP value on a key press, as shown demonstration video below. ryzenadj alone doesn't allow incremental changes from the current TDP and its richer syntax can make it clunky to change TDP on the go. tdpadj tries to fill the gap so that one can manipulate TDP (still with ryzenadj under the hood) in a simple and intuitive manner. It can send desktop notifications on TDP changes.

Below is a Sway configuration example to (1) open a floating prompt to set an arbitrary TDP when pressing Super + t, or (2) to increment and decrement TDP by 1W using the Prev_track and Next_track keys, respectively:

# TDP control
for_window [app_id="^tdp$"] floating enable, sticky enable, border pixel 4, move position center
bindsym $mod+t exec footclient -a tdp -W 50x2 ~/.local/bin/tdpadj
bindsym XF86AudioPrev exec footclient -a tdp -W 20x2 ~/.local/bin/tdpadj -1
bindsym XF86AudioNext exec footclient -a tdp -W 20x2 ~/.local/bin/tdpadj +1

I use foot (footserver/footclient) as my terminal emulator, but replace footclient by your favourite terminal, i.e., bindsym XF86AudioNext exec xfce4-terminal -e ~/.local/bin/tdpadj.

#Demonstration

(Click here to watch full video in higher resolution.)

ryzenadj requires sudo permissions, and therefore so does tdpadj. This is why the above Sway configuration example runs tdpadj in a new terminal window instead of trying to run it directly without giving the user the opportunity to type their password. This way, it should work without extra configuration. However, you may have noticed that the above demo did not require using a password. See the Permissions section below if you want to use ryzenadj and therefore tdpadj without a password prompt, thereby allowing easy TDP increments with no user input other than the user-set keybinds.

#Configuration

TDP limits within which tdpadj can operate can be edited at the beginning of the script, as well as Tctl temperature and the option to show desktop notifications:

###################################################################################
# USER CONFIGURATION ##############################################################
###################################################################################
                                                                                 ##
# Set the desired TDP limits within which the script is restricted               ##
lower_limit=1                                                                    ##
upper_limit=28                                                                   ##
                                                                                 ##
# Set whether desktop notifications should be sent (requires libnotify)          ##
send_notifications=1 # 0 for no notificatons                                     ##
                                                                                 ##
# Set the absolute path to ryzenadj if not in your $PATH                         ##
ryzenadj_path=                                                                   ##
                                                                                 ##
# Set Tctl temperature                                                           ##
tctl=85                                                                          ##
                                                                                 ##
# To run ryzenadj without a password prompt, edit /etc/sudoers to whitelist it   ##
# see https://ostechnix.com/run-particular-commands-without-sudo-password-linux/ ##
                                                                                 ##
###################################################################################

#Permissions

Specific commands requiring sudo permissions can be whitelisted in /etc/sudoers to make them run with without a password prompt (see this guide, among others). Whitelisting /path/to/ryzenadj -i will for instance allow running that command without password, so that it can be used in a status bar configuration to display the current TDP and PPT values (as demonstrated in the demonstration video above).

Additionnaly, after also whitelisting ryzenadj commands that tdpadj may use (i.e., /path/to/ryzenadj -i and /path/to/ryzenadj --stapm-limit=<value in mW> --fast-limit=<value in mW> --slow-limit=<value in mW> --tctl-temp=<85 or the tctl value you edited in tdpadj> for all <value in mW> you deem relevant), then invoking tdpadj will no longer require a password (and therefore could even be run without a terminal window).

Below is an example of a modified /etc/sudoers. Never edit /etc/sudoers directly, you should always use visudo /etc/sudoers. visudo checks the file syntax before actually overwriting the file, which will prevent locking you out of sudoers if you messed up the syntax. This is critical, do not overlook this. You can use the third line of the below file as an example of whitelisted ryzenadj commands, replacing <your-username> by your actual username, and /bin/ryzenadj by the actual absolute path to the ryzenadj binary you may have installed using a package manager or compiled yourself.

root ALL=(ALL) ALL
%wheel ALL=(ALL) ALL
<your-username> ALL=(ALL) NOPASSWD: /bin/ryzenadj -i, /bin/ryzenadj --stapm-limit=1000 --fast-limit=1000 --slow-limit=1000 --tctl-temp=85, /bin/ryzenadj --stapm-limit=2000 --fast-limit=2000 --slow-limit=2000 --tctl-temp=85, /bin/ryzenadj --stapm-limit=3000 --fast-limit=3000 --slow-limit=3000 --tctl-temp=85, /bin/ryzenadj --stapm-limit=4000 --fast-limit=4000 --slow-limit=4000 --tctl-temp=85, /bin/ryzenadj --stapm-limit=5000 --fast-limit=5000 --slow-limit=5000 --tctl-temp=85, /bin/ryzenadj --stapm-limit=6000 --fast-limit=6000 --slow-limit=6000 --tctl-temp=85, /bin/ryzenadj --stapm-limit=7000 --fast-limit=7000 --slow-limit=7000 --tctl-temp=85, /bin/ryzenadj --stapm-limit=8000 --fast-limit=8000 --slow-limit=8000 --tctl-temp=85, /bin/ryzenadj --stapm-limit=9000 --fast-limit=9000 --slow-limit=9000 --tctl-temp=85, /bin/ryzenadj --stapm-limit=10000 --fast-limit=10000 --slow-limit=10000 --tctl-temp=85, /bin/ryzenadj --stapm-limit=11000 --fast-limit=11000 --slow-limit=11000 --tctl-temp=85, /bin/ryzenadj --stapm-limit=12000 --fast-limit=12000 --slow-limit=12000 --tctl-temp=85, /bin/ryzenadj --stapm-limit=13000 --fast-limit=13000 --slow-limit=13000 --tctl-temp=85, /bin/ryzenadj --stapm-limit=14000 --fast-limit=14000 --slow-limit=14000 --tctl-temp=85, /bin/ryzenadj --stapm-limit=15000 --fast-limit=15000 --slow-limit=15000 --tctl-temp=85, /bin/ryzenadj --stapm-limit=16000 --fast-limit=16000 --slow-limit=16000 --tctl-temp=85, /bin/ryzenadj --stapm-limit=17000 --fast-limit=17000 --slow-limit=17000 --tctl-temp=85, /bin/ryzenadj --stapm-limit=18000 --fast-limit=18000 --slow-limit=18000 --tctl-temp=85, /bin/ryzenadj --stapm-limit=19000 --fast-limit=19000 --slow-limit=19000 --tctl-temp=85, /bin/ryzenadj --stapm-limit=20000 --fast-limit=20000 --slow-limit=20000 --tctl-temp=85, /bin/ryzenadj --stapm-limit=21000 --fast-limit=21000 --slow-limit=21000 --tctl-temp=85, /bin/ryzenadj --stapm-limit=22000 --fast-limit=22000 --slow-limit=22000 --tctl-temp=85, /bin/ryzenadj --stapm-limit=23000 --fast-limit=23000 --slow-limit=23000 --tctl-temp=85, /bin/ryzenadj --stapm-limit=24000 --fast-limit=24000 --slow-limit=24000 --tctl-temp=85, /bin/ryzenadj --stapm-limit=25000 --fast-limit=25000 --slow-limit=25000 --tctl-temp=85, /bin/ryzenadj --stapm-limit=26000 --fast-limit=26000 --slow-limit=26000 --tctl-temp=85, /bin/ryzenadj --stapm-limit=27000 --fast-limit=27000 --slow-limit=27000 --tctl-temp=85, /bin/ryzenadj --stapm-limit=28000 --fast-limit=28000 --slow-limit=28000 --tctl-temp=85

As a side note, I use the GNU Guix distribution, where binaries installed from the package manager end up in /gnu/store/<hash>-packagename-version/bin/binaryfile instead of /bin/binary, with <hash> changing at each update. What this means is absolute paths cannot be set directly in /etc/sudoers because they change all the time (not to mention that /etc/sudoers is not even persistent in Guix, but generated from the system configuration). See here how /etc/sudoers can be modified in Guix to whitelist the ryzenadj commands.

Do not follow this link