apple debian gnu linux imac backlight howto

Unfinished business

It’s been over a year since my initial installation of Debian GNU/Linux on my iMac. By now, Wheezy’s successor Debian 8 (Jessie) has been released and since there had been some open issues for my Debian installation, I thought I’d give upgrading the Debian system a bash.

What happened in the meantime?

Tiple-boot configuration restored

I already had a dual boot configuration set up using Bootcamp. However, the Debian 7 installation rendered my Windows 7 installation unavailable. I could fix this by switching to a Hybrid MBR. It wasn’t pretty, but I made it through alright and I can now boot all three operating systems directly from rEFInd.

Sometime over the course of the year, an Apple security fix overwrote the EFI partition, but reinstantiating the rEFInd bootloader was as simple as repeating the steps for the initial rEFInd installation.

Brightness control

I found the proper command that allowed me to configure the brightness: xrandr --output eDP --brightness 0.5. However, this one is only software-based. It gets the job done, but it doesn’t really touch the backlight.

Post-upgrade

I followed Debian’s instructions on how to upgrade an existing installation and encountered no problems related to the Apple hardware.

Sound

The kernel that comes with Debian 8 supports the imac27_* option for the Intel ICH driver. The new driver in turn provides control options for the internal bass speaker, removing the “tinny” sound that annoyed me so much under Wheezy. You can pass the model option to the sound driver like this:

$ echo options snd-hda-intel model=imac27_122 | sudo tee /etc/modprobe.de/sound.conf

Once loaded (reboot), bring up the command line tool alsamixer, select the Intel PCH sound driver using the F6 key and unmute the bass speaker.

By default, GNOME’s volume control keeps lowering the bass volume out of the red area. The fix was to tell GNOME via its audio preferences to select another sound card (“Analogue Sound” in my case).

Keyboard

I want my function keys to behave as F1, F2, …, without modifying it with the fn switch. The keyboard driver has an option to swap the fn behaviour for the function keys F1F12:

# For immediate switch:
$ echo 2 > /sys/module/hid_apple/parameters/fnmode

If hid_apple.ko is loaded as a module, making this persist between reboots works like this:

echo options hid_apple fnmode=2 | sudo tee -a /etc/modprobe.d/hid_apple.conf

However, it would seem that hid_apple is statically compiled into the kernel and so I had to pass the option to Grub in order to make it stick:

# /etc/default/grub
# ..
GRUB_CMDLINE_LINUX_DEFAULT="hid_apple.fnmode=2"
# ..

I wanted to preserve the media keys on F7F12 so I remapped their functionality in my ~/.Xmodmap:

keycode  73 = XF86AudioPrev NoSymbol XF86AudioPrev NoSymbol XF86AudioPrev
keycode  74 = XF86AudioPlay XF86AudioPause XF86AudioPlay XF86AudioPause XF86AudioPlay XF86AudioPause
keycode  75 = XF86AudioNext NoSymbol XF86AudioNext NoSymbol XF86AudioNext
keycode  76 = XF86AudioMute NoSymbol XF86AudioMute NoSymbol XF86AudioMute
keycode  94 = dead_circumflex degree dead_circumflex degree U2032 U2033 U2032
keycode  95 = XF86AudioLowerVolume NoSymbol XF86AudioLowerVolume NoSymbol XF86AudioLowerVolume
keycode  96 = XF86AudioRaiseVolume NoSymbol XF86AudioRaiseVolume NoSymbol XF86AudioRaiseVolume

I saved the original F7F12 bindings in a gist.

I wasn’t lucky making the Left Alt behave like its right hand sibling. I tried several Xmodmap mappings but to no avail. It is recognized as a modifier key (ie. Alt + F2 brings up the run-command-window in GNOME) but I can only get the @-sign with ALT_R + l. I guess I have to get using Right Alt into my muscle memory then…

Brightness

Apparently GNOME’s brightness control accesses /sys/class/backlight/acpi_video0 but the firmware for that adapter doesn’t seem to have support for it. Luckily, /sys/class/backlight/radeon_bl1 does. Since I couldn’t find a way to tell GNOME to use the raw radeon_bl1 interface, I wrote a script that I bound to the brightness control keys (inspired by a Debian wiki page):

#!/usr/bin/env bash
# Copyright (c) 2015 Carsten Zimmermann, License: MIT.
#
# Original version (c) 2013 Thibaut Paumard, permitted to modify and distribute the
# file freely. https://wiki.debian.org/InstallingDebianOn/Apple/MacBookPro/9-1

CMD=/usr/lib/gnome-settings-daemon/gsd-backlight-helper
SYSBL=/sys/class/backlight/radeon_bl1
NSTEPS=20

mode="xrandr"

if [ -f "$SYSBL/brightness" ]; then
  mode=radeon_bl1
  NSTEPS=10
fi

maxbr=$(${CMD} --get-max-brightness)
curbr=$(${CMD} --get-brightness)

delta=$(expr ${maxbr} / ${NSTEPS})
if [ $delta -eq 0 ]; then
  delta=1
fi

op=$1

if [ "x$op" != "x+" -a "x$op" != "x-" ] ; then
  echo "Usage: $0 +/-"
  exit 1
fi

br=$(( ${curbr} ${op} ${delta} ))
if [ $br -ge $maxbr ]; then
  br=$maxbr
fi
if [ $br -le 0 ]; then
  br=0
fi

if [ $mode = "radeon_bl1" ]; then
  radeon_maxbr=$(cat "$SYSBL/max_brightness")
  # translate gnome brightness to 1..255 value for radeon_bl1
  radeonbr=$(echo "scale=0; ($br * $radeon_maxbr) / $maxbr" | bc -q )
  echo $radeonbr > $SYSBL/brightness
fi

if [ $mode = "xrandr" ]; then
  # translate gnome brightness to percentage value for xrandr
  xrandrbr=$(echo "scale=1; $br / $maxbr" | bc -q 2>/dev/null)
  xrandr --output eDP --brightness $xrandrbr
fi

${CMD} --set-brightness ${br}

exit 0

The script checks whether /sys/class/backlight/radeon_bl1 exists. It will access the raw backlight interface if it does or fall back to software-based xrandr brightness correction if not. You can get the latest version of this file from my dotfiles repo. Copy the file to /usr/local/bin and make sure it’s executable.

Now, bind the script to the fn + F1 and fn + F2 keys. You need xbindkeys for that, which you can install with:

$ sudo apt-get install xbindkeys

Create ~/.xbindkeysrc with the following contents and run xbindkeys -f $HOME/.xbindkeysrc after that.

"sudo apple_brightness - &"
XF86MonBrightnessDown

"sudo apple_brightness + &"
XF86MonBrightnessUp

The last step is to allow users to run the script as root without checking for a password. Use sudo visudo to add the following line to the sudoers file:

# /etc/sudoers
ALL     ALL=NOPASSWD: /usr/local/bin/apple_brightness.sh *

Reboot and rejoice: you can control your brightness again! There is one cosmetic drawback, though: after rebinding XF86MonBrightnessUp/Down, I don’t get the pretty brightness control overlay in GNOME anymore. Ideally, one tells GNOME directly which sysfs citizen it should use. If anyone is successul getting it to work with the following Xorg config hint, do drop me a line. I wasn’t able to start X any longer with this file being loaded:

# /usr/share/X11/xorg.conf.d/20-radeon.conf
Section "Device"
    Identifier  "card0"
    Driver      "radeon"
    Option      "Backlight"  "radeon_bl1"
    BusID       "PCI:0:2:0"
EndSection
comments powered by Disqus