Monday, 1 September 2014

Optimus and Ubuntu 14.04

This post takes the reader through Nvidia Optimus related tweaks I applied on my Lenovo W530 after upgrading it to Ubuntu 14.04. I have dedicated a a series of 5 posts to the same topic on Ubuntu 12.10. Please take those previous posts as prerequisite knowledge, as I do not intend to repeat the detailed descriptions I have already provided. As outlined earlier, my goal is to get a very stable system with extended battery life, and the ability to connect an external projector to the VGA port and cover the following use cases (a verbatim copy of the enumeration from a previous post):

  • Extend the desktop to the external monitor.
  • Get a cloned output of the primary monitor to the external monitor with panning support - this means, that in the case the external monitor's resolution is smaller, a smaller viewport will follow the mouse and show a cropped clone of the desktop's content. The viewport will follow the mouse to show the area of interest.
  • Run LibreOffice presentations with the external monitor showing the current slide and the primary monitor showing the presentation overview, notes and time.
  • Never ever get X freezes or kernel lockups on suspend/resume with or without an external monitor connected.
  • Switching to virtual terminals should always work in a bulletproof manner. The box is a workhorse, cannot allow hiccups.
  • Might sound like a small detail, but a properly displayed usplash/plymouth is also important, not only for cosmetic purposes.

Prime and Optimus support out of the box

As documented in the official wiki of the nouveau driver, Optimus support has improved much in the open source driver, and automatic power management of the discrete graphics chip is also documented to work properly with Linux kernel 3.13. This means, Optimus should work out of the box: the discrete graphics chip should be turned on when needed, and fully powered off automatically when idle for 5 seconds.

The following command listing can be used to quickly review the current state of the two graphics chips. As it can be seen, the discrete chip's status is DynOff meaning that automatic power management is active and the device is currently powered off. Further, xrandr lists all outputs - those wired to the integrated chip as well as those wired to the Nvidia GPU.

uname -a
Linux gluon 3.13.0-35-generic #62-Ubuntu SMP Fri Aug 15 01:58:42 UTC 2014 x86_64 x86_64 x86_64 GNU/Linux
sudo cat /sys/kernel/debug/vgaswitcheroo/switch
0:DIS: :DynOff:0000:01:00.0
xrandr -q | grep conn # confirms that outputs wired IDG and also those wired to DIS are visible to X
LVDS2 connected primary 1920x1080+0+0 (normal left inverted right x axis y axis) 344mm x 193mm
VGA2 disconnected (normal left inverted right x axis y axis)
VIRTUAL1 disconnected (normal left inverted right x axis y axis)
LVDS-1-1 disconnected
VGA-1-1 disconnected
DP-1-1 disconnected
DP-1-2 disconnected
DP-1-3 disconnected

When connecting an external display, DIS will be powered on automatically and outputs are detected and handled almost perfectly by Ubuntu out of the box (more on this later). However, once DIS has been powered on, it cannot be powered off, even if no external monitor is connected. Further, if DIS is not powered off, the Thinkpad cannot be suspended, which is a pain.

sudo cat /sys/kernel/debug/vgaswitcheroo/switch 
0:DIS: :DynPwr:0000:01:00.0
echo "OFF" | sudo tee /sys/kernel/debug/vgaswitcheroo/switch
sudo cat /sys/kernel/debug/vgaswitcheroo/switch 
0:DIS: :DynPwr:0000:01:00.0

Others have experienced slightly different behaviour, in particular DIS being powered on (DynPwr) at boot, the common phenomenon is the inability to power off DIS via the command line. The author has suggested disabling the new automatic power management feature to allow the user to explicitly power on and power off the devices as needed.

Disabling automatic power management of the Nvidia graphics chip

Adapting the suggestion to Ubuntu 14.04 involved editing bootloader configuration so it passes the additional argument nouveau.runpm=0 to the kernel.

sudo nano /etc/default/grub # find and edit the GRUB_CMDLINE_LINUX_DEFAULT as follows:
GRUB_CMDLINE_LINUX_DEFAULT="quiet splash nouveau.runpm=0"
sudo update-grub
sudo init 6 # reboot

Having rebooted the system, I verified that the configuration change indeed took effect. Power states DynPwr and DynOff disappeared, and manual power state switching could be successfully performed the same way as in Ubuntu 12.10.

cat /proc/cmdline # verify nouveau.runpm=0 was successfully passed to the kernel
BOOT_IMAGE=/boot/vmlinuz-3.13.0-35-generic.efi.signed root=UUID=2a924e40-1f12-4c5a-8f22-556d6e66ffa6 ro quiet splash nouveau.runpm=0 vt.handoff=7
sudo cat /sys/kernel/debug/vgaswitcheroo/switch # verify current power state
0:DIS: :Pwr:0000:01:00.0
echo "OFF" | sudo tee /sys/kernel/debug/vgaswitcheroo/switch # power off DIS
sudo cat /sys/kernel/debug/vgaswitcheroo/switch # verify power state again
0:DIS: :Off:0000:01:00.0

The surprise

Based on my knowledge of how outputs are wired on W530, my experiences on Ubuntu 12.10 and my observation in 14.04 so far I assumed that with DIS powered off, xrandr -q would not list the external VGA and DisplayPort outputs, or at least that connecting an external display to those outputs wired to the Nvidia chip would not do anything if the discrete GPU is powered off.

Contrary to my expectations, even if DIS is powered OFF, the external VGA and DiplayPort outputs are available to X, and hooking up an external monitor works the same way after this tweak as before. The Thinkpad can now be suspended, even with external outputs connected.

However, if an external display was active at the time the laptop was suspended, compiz crashed once the system resumed. This is a minor glitch resulting in a prompt to submit a bug report, and compiz is automatically restarted and fully functional even in this case. To be on the safe side, I would disconnect external displays before suspending - this seems to make sense anyway.

Disabling the discrete GPU on boot by default to save power

In order to save power, I disabled the Nvidia GPU during the boot process. I wanted X to be started with both IDG and DIS powered on, to make sure all outputs are properly detected. Customising /etc/rc.local is the approach I settled with, as this file is run after all other services, including X, have been started. This script does not do anything on a clean install, so all one needs to do is to insert one line before exit 0:

echo "OFF" > /sys/kernel/debug/vgaswitcheroo/switch
exit 0

External VGA working almost perfectly

In general I can confirm a lot of progress related to Optimus since 12.10. Outputs are detected out of the box, no need for a second X servers, special Xorg configuration and hybrid screenclone or other voodoo magic. The desktop can be extended to the external VGA, resolution and other parameters all configured using the GUI.

I observed one issue while testing LibreOffice presentations with the external monitor showing the current slide and the primary monitor showing the presentation overview. The current slide, rendered to the external VGA in fullscreen mode did not properly update. At first sight it seems to always be 1 slide behind compared to the LCD of the thinkpad, but moving the cursor over this area of the screen made the area around the cursor refresh, unveiling parts the actual current slide (XDamage came to my mind).

This issue I have not yet resolved. I do not have an external monitor at home, so I will have to wait and squeeze the investigation into my schedule during working hours.

Update: Workaround

I have settled with launching watch -n xrefresh before starting my presentation, and terminating it once I am done. This essentially forces a full refresh every second which yields acceptable experience. Not optimal, but just good enough.

No comments:

Post a Comment