Fglrx Quick Switch

From Gentoo Wiki
Jump to:navigation Jump to:search
Article status
This article needs wikification.
The information in this article has been deprecated. It may or may not be relevant for contemporary usage. Handle with care!
Warning
These instructions are outdated because ati-drivers and old versions of xorg-server are not available.

Rationale

Unlike other distributions, Gentoo can install the fglrx and open Radeon drivers alongside each other, thanks to eselect opengl, but obviously you can only use one at a time. To make matters worse, fglrx can't be used while the open kernel modules are loaded, and older devices only support older versions of xorg-server.

I didn't want to be forced to downgrade xorg-server and as I'm usually short on time, if it was too fiddly to switch between the two, I knew I'd never bother doing it in practise. I set out to find an optimal way.

Research

I experimented with disabling the framebuffer under the running kernel, unloading the modules, resetting the adapter's state with vbetool, and also faster reboots with kexec. While all of these worked by themselves, starting X with fglrx always caused a freeze or crash of some kind. Sadly it seems that a proper reboot is still necessary.

Procedure

Here's what I came up with. This assumes that you're already using the open driver.

If you have an older device...

The legacy driver for HD2000, HD3000 and HD4000 devices is currently in the tree as x11-drivers/ati-drivers-13.1_pre897. This is not really a beta and I think it is only versioned like this to differentiate it from the non-legacy 13.1 driver. It has been patched to work with Linux 3.7. Start by masking any newer versions.

FILE /etc/portage/package.mask
x11-drivers/ati-drivers:1

If you try to emerge ati-drivers like this, it will downgrade xorg-server to 1.12.4. We can install this version to a separate root instead and then fool the regular system into thinking we also have this version. This assumes that you use xf86-input-evdev for input.

root #ROOT="/mnt/fglrx" CPPFLAGS="-I/mnt/fglrx/usr/include/xorg" emerge --nodeps =x11-base/xorg-server-1.12.4 x11-drivers/xf86-input-evdev
FILE /etc/portage/profile/package.provided
x11-base/xorg-server-1.12.4

Everyone can continue from here...

Now you can emerge ati-drivers.

root #emerge --ask ati-drivers

Generate a xorg-server configuration file for fglrx with aticonfig. Set any additional options you require.

root #/opt/bin/aticonfig -i /dev/null -o /etc/X11/fglrx.conf --initial

If you're using an old device, you need to manually set the module path in the configuration file that was just generated. Add the following to the start of the file. If you're not using an old device, just skip this step.

FILE /etc/X11/fglrx.conf
Section "Files"
  ModulePath "/mnt/fglrx/usr/lib/xorg/modules"
  ModulePath "/usr/lib/xorg/modules"
EndSection

If you have a 64-bit system, you must use this instead:

FILE /etc/X11/fglrx.conf
Section "Files"
  ModulePath "/mnt/fglrx/usr/lib64/xorg/modules"
  ModulePath "/usr/lib/xorg/modules"
EndSection

To save ourselves from having to swap configuration files around all the time, we can edit the script that is usually used to start the X server so that it uses the right server and configuration file automatically. It'll also ensure that we're using the correct OpenGL driver, which is important because trying to use fglrx with the wrong OpenGL driver will lock up your machine. Replace all the contents of the existing file below. Change /mnt/fglrx/usr/bin/X to just /usr/bin/X if you don't have an older device.

FILE /etc/X11/xinit/xserverrc
#!/bin/sh

if lsmod | grep -q "^fglrx\b"; then
	eselect opengl set ati
	exec /mnt/fglrx/usr/bin/X -config fglrx.conf -nolisten tcp "$@"
else
	eselect opengl set xorg-x11
	exec /usr/bin/X -nolisten tcp "$@"
fi

In hybrid system setups, drm is needed by i915 (intel) module so the grep expression was changed from "^drm\b" to "^fglrx\b" and branches swapped. This should be enough for startx. lightdm and gdm need the following adjustments. I'm afraid I don't know about other display managers. They may just work.

FILE /etc/lightdm/lightdm.conf
...
[SeatDefaults]
xserver-command=/etc/X11/xinit/xserverrc
...
FILE /etc/X11/gdm/custom.conf
...
[server-Standard]
command=/etc/X11/xinit/xserverrc -audit 0 
...
# There is a graphical tool for gdm setup that can be reached 
# from the gdm greeter screen. Aside from "server-Standard" 
# there are two more option groups where the path to /usr/bin/X 
# can be replaced by the xserverrc script, as needed.

If you haven't already done so, you now need to have the radeon and drm drivers built as modules rather than built into the kernel. These are the CONFIG_DRM_RADEON and CONFIG_DRM options respectively. The framebuffer drivers can remain built in.

Now we need to control which kernel modules are loaded. The good news is that this can be done from the kernel command line. The bad news is that GRUB 2 doesn't support complex configurations out of the box with grub2-mkconfig. The other good news is that we can still easily hack it for our needs. Apply this patch or manually apply the changes.

CODE
--- /etc/config-archive/etc/grub.d/10_linux.dist	2012-12-26 16:17:08.000000000 +0000
+++ /etc/grub.d/10_linux	2012-12-26 12:42:28.501458324 +0000
@@ -228,7 +228,7 @@
 
   if [ "x$is_first_entry" = xtrue ]; then
     linux_entry "${OS}" "${version}" simple \
-    "${GRUB_CMDLINE_LINUX} ${GRUB_CMDLINE_LINUX_DEFAULT}"
+    "${GRUB_CMDLINE_LINUX} ${GRUB_CMDLINE_LINUX_DEFAULT} modprobe.blacklist=fglrx"
 
     submenu_indentation="\t"
     
@@ -240,11 +240,13 @@
   fi
 
   linux_entry "${OS}" "${version}" advanced \
-              "${GRUB_CMDLINE_LINUX} ${GRUB_CMDLINE_LINUX_DEFAULT}"
+              "${GRUB_CMDLINE_LINUX} ${GRUB_CMDLINE_LINUX_DEFAULT} modprobe.blacklist=fglrx"
   if [ "x${GRUB_DISABLE_RECOVERY}" != "xtrue" ]; then
     linux_entry "${OS}" "${version}" recovery \
-                "single ${GRUB_CMDLINE_LINUX}"
+                "single ${GRUB_CMDLINE_LINUX} modprobe.blacklist=fglrx"
   fi
+  linux_entry "${OS}" "${version} (fglrx)" advanced \
+              "${GRUB_CMDLINE_LINUX} ${GRUB_CMDLINE_LINUX_DEFAULT} modprobe.blacklist=drm,radeon"
 
   list=`echo $list | tr ' ' '\n' | grep -vx $linux | tr '\n' ' '`
   is_first_entry=false

Now run grub2-mkconfig as normal. It will create an additional fglrx entry under the advanced menu alongside the usual entries.

root #mount /boot
root #grub2-mkconfig --output /boot/grub2/grub.cfg

Now reboot and enjoy!