February 19, 2011

Controlling screen brightness in Linux

3 years ago, I had a Lenovo laptop whose screen brightness keys didn't work on an old version of Ubuntu.  I wrote a blog post on how I worked around the limitation.  Now I have a Samsung N450 laptop running the most recent version of Ubuntu (10.10) and the screen brightness keys don't work again.  Like the last time, I am going to document how I am changing screen brightness on my laptop now.

I learned this from a comment Goksu left on an Ubuntu bug report.  The command that changes screen brightness is:
sudo setpci -s 00:02.0 f4.b=90

The 90 in this command is the brightness value in hexadecimal.  Valid range for this value is hexadecimal values between 0 and ff inclusive.  For instance, to set brightness to 75% replace "90" in the command with "bd" (i.e. sudo setpci -s 00:02.0 f4.b=bd).  Likewise use "7f" for 50%, and "3f" for 25% brightness.  Never set this value to 0 though, because that turns the display completely off and resetting the brightness can be hard.  (If you manage to accidentally set this to 0, reboot the machine, before you load Linux, i.e. while on the boot menu use brightness hot keys to set brightness back to normal.)

You may want to look at my old blog post to see how to avoid having to enter your password every time you change the brightness and to bind a shortcut key to adjust brightness.

Now, some details on how this works so you can adjust the command arguments to suit your computer.  Using setpci command, we are directly setting the brightness configuration on the graphics card.  -s flag says which device to control.  Running lspci shows all devices connected to the system via PCI.  On my machine this is what lspci prints:
% lspci | head -3
00:00.0 Host bridge: Intel Corporation N10 Family DMI Bridge
00:02.0 VGA compatible controller: Intel Corporation N10 Family Integrated Graphics Controller
00:02.1 Display controller: Intel Corporation N10 Family Integrated Graphics Controller
As you can see "00:02.0" is the identifier for the display controller.  Brightness is controlled by the number in f register of the VGA controller.  This register is 8 bits long and hence the range 0 to ff.  With the setpci command we change the value of the f register and that results in the brightness change.

Update (Oct 2, 2011): I have written a Go program to change the brightness from command line.  I have uploaded a 32-bit compiled binary as well, if you don't want to compile it yourself.  You can install this program to /usr/local/bin with setuid bit set so that you won't need to 'sudo' every time you run it.  (Search for "chmod" in my previous post for detailed installation instruction.)

5 comments:

  1. Yes, but the solution is only for your laptop model. It doesn`t work on mine (dell)

    ReplyDelete
  2. not on mine neather. Asus

    ReplyDelete
  3. I've built a simple shell script to do this... It's probably not as extensible as your Go program, but it works for me. An enterprising person could probably add in more options, but I'm fine with 25, 50, 75, and 100% brightnesses. Eventually I'll figure out how to make it increment and decrement brightness with command line options.

    [code]
    #!/bin/bash
    # (1) prompt user, and read command line argument
    read -p "Select a brightness level from 1 (25%) to 4(100%) or press N to quit: " answer

    # (2) handle the command line argument we were given
    while true
    do
    case $answer in
    [1]* ) sudo setpci -s 00:02.0 f4.b=3f
    break;;

    [2]* ) sudo setpci -s 00:02.0 f4.b=7f
    break;;

    [3]* ) sudo setpci -s 00:02.0 f4.b=bd
    break;;

    [4]* ) sudo setpci -s 00:02.0 f4.b=ff
    break;;

    [nN]* ) exit;;

    * ) echo "Dude, just enter 1-4 or N, please."; break ;;
    esac
    done
    [/code]

    ReplyDelete
    Replies
    1. Thanks for sharing your script, Tom. For most people something simple like this would be sufficient.

      Delete
  4. Thanks tom, your posted command worked on my eeepc. I used it on linux and haiku too.

    ReplyDelete