David Schlachter

FreeBSD on the Lenovo Thinkpad T480

Last updated: March 12, 2020

Recently I replaced my 2014 MacBook Air with a Lenovo Thinkpad T480, on which I've installed FreeBSD, currently 12.1-RELEASE. This page documents my set-up along with various configuration tweaks and fixes.

Working:

Not working: Bluetooth (causes hang on reboot, no driver available), 802.11ac (no support in FreeBSD). I don't have any Thunderbolt devices to test and don't have a fingerprint sensor installed.

X11 and Intel Graphics

Xorg requires the Intel video drivers from the package drm-fbsd12.0-kmod. I've found building them from ports to work more reliably than installing from packages. After installation, load them at boot by adding
kld_list="/boot/modules/i915kms.ko"
to /etc/rc.conf.

I've had the best success using the xf86-video-intel driver. The default modesetting driver works but has frequent screen tearing. You'll want to install xf86-video-intel and use the SNA acceleration option (the default UXA method is very slow -- e.g. rendering marching ants in GIMP will freeze the program). I use the following configuration file placed in /usr/local/etc/X11/xorg.d.conf/:

# /usr/local/etc/X11/xorg.conf.d/20-intel.conf
Section "Device"
 Identifier "Intel Graphics"
 Driver "intel"
 Option "AccelMethod" "SNA"
 Option "TearFree" "true"
EndSection

Trackpad / Trackpoint

Good news is that since udev/libinput was merged into the default xorg-server trackpad setup is much easier than previously. My configuration is inspired by a blog post by Michael Gmelin.

I've found that setting kern.evdev.rcpt_mask to 12 rather than 6 (as suggested by the xorg-server package) exposes more keys to X to be settable as hotkeys.

To have the trackpoint, buttons, and trackpad working as expected I use the following configuration file in /usr/local/etc/X11/xorg.conf.d/10-input.conf:

Section "InputClass"
Identifier "libinput keyboard catchall"
MatchIsKeyboard "on"
MatchDevicePath "/dev/input/event*"
Driver "libinput"
Option "XkbRules" "evdev"
EndSection

Section "InputClass"
Identifier "libinput touchpad catchall"
MatchIsTouchpad "on"
MatchDevicePath "/dev/input/event*"
Driver "libinput"
Option "NaturalScrolling" "on"
Option "Tapping" "on"
Option "DisableWhileTyping" "on"
Option "AccelSpeed" "0.42"
EndSection

5GHz WiFi networks

5 GHz networks won't be visible unless the country code is properly set for the WiFi interface (otherwise connectivity will be limited to the 2.4GHz band). I set the country code (for me, Canada, "CA") on this line in /etc/rc.conf:
ifconfig_wlan0="WPA country CA powersave"

WiFi is also limited to 802.11g speeds for the Intel 8265 Wireless card. I've tried using PCI passthrough with a Linux virtual machine in bhyve to use 802.11ac speeds, but haven't figured out how to keep this working after suspend/resume.

Suspend / resume

To enable suspend / resume on lid close when running X11, add hw.acpi.lid_switch_state=S3 to /etc/sysctl.conf.

Note that the TPM must be disabled in the BIOS for suspend/resume to work. Supported TPM models are listed in man tpm and I guess the T480 TPM is not yet supported. According to the manual page, the TPM must be told to save its state before suspend; otherwise resume will fail.

Screen brightness

I'm currently using acpi_video, see my article on brightness increments for details.

Sound

On 12.1-RELEASE p2, sound is great on the speakers but really bad from the headphone jack. Lots of static and distortion, and at lower volumes nothing can be heard. As of March 2020, this problem is not present in 12.1-STABLE or 13.0-CURRENT (I suspect it was fixed in r351325). For a temporary fix, I downloaded the source code for the hda driver from the stable branch (stable/12/sys/dev/sound/pci/hda/) to the corresponding directory in /usr/src and rebuilt the kernel and kernel modules. Until these changes get merged to the RELEASE branch, this has fixed headphone jack audio for me.

Camera

The IR camera is the only camera option included with the WQHD screen. Setting up webcamd with default settings has the infrared camera working fine but only as creepy night vision!

usbconfig shows two camera devices:

ugen0.2: <Bison Integrated IR Camera> at usbus0, cfg=0 md=HOST spd=HIGH (480Mbps) pwr=SAVE (500mA)
ugen0.3: <SunplusIT Inc Integrated Camera> at usbus0, cfg=0 md=HOST spd=HIGH (480Mbps) pwr=SAVE (500mA)

To use the visible light camera instead of the IR camera, set webcamd_0_flags in /etc/rc.conf to indicate the right device to use, e.g.
webcamd_enable="YES"
webcamd_0_flags="-d ugen0.3 -B"

Alternatively, set up both cameras (as shown below in /etc/rc.conf) so that apps will ask which one you want to use.

I still haven't figured out how to make the cameras accessible to Chrome (Chromium) or Firefox.

Window manager (i3) and HiDPI GUI issues

For HiDPI support, the scaling factor must be set using xrandr. I do this in my .xinitrc:

xrandr --dpi 140 && xrdb -merge $HOME/.Xresources
exec i3 # start the window manager

For i3wm, the generated configuration is more limited than the default loaded configuration (e.g. the generated config does not have a hotkey to exit i3). Copy the example configuration as a starting point:
mkdir -p ~/.i3 && cp /usr/local/etc/i3/config ~/.i3/config

By default the cursor will be tiny. To increase the size of the cursor, select a cursor theme that has multiple cursor sizes and set the cursor size in .Xresources:

Xcursor.size: 48
Xcursor.theme: whiteglass

However, this only seems to work if you create the following symlink:
ln -s /usr/local/share/icons ~/.icons

At some point I had an issue where the cursor would still be very small in GTK apps (Firefox, xfce4-terminal); to fix, set the same cursor theme as in .Xresources in ~/.config/gtk-3.0/settings.ini and ~/.gtkrc-2.0.

If using an external monitor, by default the HiDPI scaling in xinitrc will be applied. To use a different scaling, e.g. 96 dpi, first calculate the quotient of hidpi/ext monitor dpi (in my case, 140/96 = 1.485), then set up the monitor using a command such as:

xrandr --output "HDMI-2" --mode 1920x1080 --scale 1.485x1.485 --right-of "eDP-1"

This works well for displaying, but the mouse appears to be unable to exceed the dimensions of the internal monitor on the external display. This appears to be a common issue but I haven't figured it out yet.

Configuration files

For anything not described above:

/etc/rc.conf

#
# Added by installer
#
clear_tmp_enable="YES"
syslogd_flags="-ss"
sendmail_enable="NONE"
hostname="t480"
ntpdate_enable="YES"
ntpd_enable="YES"
# Set dumpdev to "AUTO" to enable crash dumps, "NO" to disable
dumpdev="AUTO"
zfs_enable="YES"

# Power saving, see https://www.c0ffee.net/blog/freebsd-on-a-laptop/
powerdxx_enable="YES"
performance_cx_lowest="Cmax"
economy_cx_lowest="Cmax"

# Intel Graphics driver
kld_list="/boot/modules/i915kms.ko"

# Readable font size at console
allscreens_flags="-f terminus-b32"

# For XOrg
dbus_enable="YES"

# Don't pause during boot for DHCP
background_dhclient="YES"

# Networking; use ethernet if available, otherwise use WiFi
# https://www.freebsd.org/doc/handbook/network-aggregation.html
ifconfig_em0="up"
wlans_iwm0="wlan0"
ifconfig_wlan0="WPA country CA powersave"
create_args_wlan0="wlanaddr 98:fa:9b:6c:e4:4f"
# Same as em0 MAC address cloned_interfaces="lagg0"
ifconfig_lagg0="up laggproto failover laggport em0 laggport wlan0 DHCP"

# Webcam
webcamd_enable="YES"
webcamd_0_flags="-d ugen0.3" # visible light camera
webcamd_1_flags="-d ugen0.2" # IR camera

# CUPS (allow printing)
cupsd_enable="YES"

/etc/sysctl.conf

# Added by the installer
security.bsd.unprivileged_read_msgbuf=0
security.bsd.unprivileged_proc_debug=0
kern.randompid=1
vfs.zfs.min_auto_ashift=12

# Allow sleep on lid close
hw.acpi.lid_switch_state=S3

# Disable system bell / bell everywhere
kern.vt.enable_bell=0

# Allow mounting FUSE filesystems
vfs.usermount=1

/boot/loader.conf

# Added by installer
aesni_load="YES"
geom_eli_load="YES"
security.bsd.allow_destructive_dtrace=0
kern.geom.label.disk_ident.enable="0"
kern.geom.label.gptid.enable="0"
zfs_load="YES"

# Improved power and video support
acpi_ibm_load="YES"
# For webcam
cuse_load="YES"

# WiFi
if_iwm_load="YES"
iwm8265fw_load="YES"

# Touchpad driver
hw.psm.synaptics_support="1"

# FUSE
fusefs_load="YES"

# Place devices in low power state when suitable driver not found
# (man 4 pci)
hw.pci.do_power_nodriver=3