← Back to team overview

hybrid-graphics-linux team mailing list archive

[ANNOUNCE] Build-Your-Own-Switcheroo (byo-switcheroo)

 

Two great tastes that taste great together, asus-switcheroo has now
pulled in acpi_call functionality to allow you, yes you, to write your
own switcheroo handler.  Rather than having a fixed function set that
only works on a handful of systems, what this module does is
completely in your hands.  Each switcheroo entry point is configurable
with acpi_call style scripts.  So, if you know how to power on/off
your discrete graphics, you can now make it part of a switcheroo
handler.  If you know how to switch to and from your discrete
graphics, even better.

You can find the code in the asus-switcheroo project:
https://github.com/awilliam/asus-switcheroo
(git://github.com/awilliam/asus-switcheroo.git)

The handler loads exactly like asus-switcheroo, ie. it MUST be loaded
before the graphics driver switcheroo handler so that it can take over
the handler role.  This is typically accomplished by putting something
like this into a /etc/modprobe.d script:

install nouveau /sbin/modprobe byo-switcheroo; /sbin/modprobe
--ignore-install nouveau

This tells the module loader that when asked to load nouveau, first
load byo-switcheroo, then novueau.  If you wish to use the nvidia
proprietary driver, you can still blacklist nouveau and use the
dummy_client=1 option for byo-switcheroo just as you did for
asus-switcheroo.  If the graphics driver is loaded from an initramfs
you'll need to rebuild it after configuring modprobe.d.  Newer kernels
also seem to have trouble loading nouveau from an initramfs, but
loading them later in boot works fine.  Note, all of this should also
work for Radeon hybrid graphics too.

If your integrated graphics is not Intel based, you'll want to use the
igd_vendor option when loading the module.  The default for this is
0x8086 (the PCI vendor ID for Intel).  To find your vendor ID, run
'lspci | grep VGA'.  On my system this gives:

00:02.0 VGA compatible controller: Intel Corporation Mobile 4 Series
Chipset Integrated Graphics Controller (rev 07)
01:00.0 VGA compatible controller: nVidia Corporation GT218 [GeForce
G210M] (rev a2)

I know that Intel is my integrated graphics and I can get the vendor ID via:

# cat /sys/bus/pci/devices/0000\:00\:02.0/vendor
0x8086

If both graphics devices have the same vendor, send me the details and
we can work on adding more parameters to make it work.  To specify the
vendor ID, you can add an options line to your modprobe.d file, (ex:
options byo-switcheroo igd_vendor=0x8086).

Once the module is setup, you should be able to reboot and see
something like this in dmesg:

Found VGA device 0000:00:02.0 (\_SB_.PCI0.VGA_): IGD
Found VGA device 0000:01:00.0 (\_SB_.PCI0.P0P1.VGA_): DIS
BYO-switcheroo handler registered

This is printing the PCI device and ACPI path for each device and
letting you know which one it thinks is integrated vs discrete.  If
you don't get this far, then either the module isn't being loaded
properly (please check the instructions again before emailing
questions) or we can't find the devices (post dmesg and DSDT).

Now we need to tell it how to do things (byo-switcheroo does *nothing*
on it's own, please don't email me saying it doesn't do anything if
you haven't programmed it as below or don't already know how to make
some things work using acpi_call).  In
/sys/module/byo_switcheroo/parameters there are writable files for
each switcheroo entry point.  Note that these can also be set as a
module options (ex. modprobe byo-switcheroo
switchto_dis="MXMX;MXDS;etc..".  Each file does the following:

power_state_dis_off - Script to power OFF the discrete graphics
power_state_dis_on - Script to power ON the discrete graphics
power_state_igd_off - Script to power OFF the integrated graphics
(typically empty)
power_state_igd_on - Script to power ON the integrated graphics
(typically empty)
switchto_dis - Script to switch mux and enable discrete graphics
switchto_igd - Script to switch mux and disable discrete graphics

An acpi_call script uses the exact same syntax as acpi_call, using new
lines or semicolons (;) do separate commands.  There's also support
for special commands, that begin with an exclamation (!).  The only
special command currently defined is
nouveau_fbcon_output_poll_changed, which makes nouveau re-probe output
devices after a switch (only needed with nouveau on 2.6.37 or older
kernels).  To achieve the identical functional as asus-swticheroo on
my Asus UL30VT, I use the following scripts:

power_state_dis_off:
_DSM {0xA0,0xA0,0x95,0x9D,0x60,0x00,0x48,0x4D,0xB3,0x4D,0x7E,0x5F,0xEA,0x12,0x9F,0xD4}
0x102 0x3 {0x2,0x0,0x0,0x0}

power_state_dis_on:
_DSM {0xA0,0xA0,0x95,0x9D,0x60,0x00,0x48,0x4D,0xB3,0x4D,0x7E,0x5F,0xEA,0x12,0x9F,0xD4}
0x102 0x3 {0x1,0x0,0x0,0x0}

switchto_dis:
MXMX 0x1
MXDS 0x1
_DSM {0xA0,0xA0,0x95,0x9D,0x60,0x00,0x48,0x4D,0xB3,0x4D,0x7E,0x5F,0xEA,0x12,0x9F,0xD4}
0x102 0x2 {0x12,0x0,0x0,0x0}
!nouveau_fbcon_output_poll_changed

switchto_igd:
MXMX 0x1
MXDS 0x1
_DSM {0xA0,0xA0,0x95,0x9D,0x60,0x00,0x48,0x4D,0xB3,0x4D,0x7E,0x5F,0xEA,0x12,0x9F,0xD4}
0x102 0x2 {0x11,0x0,0x0,0x0}

Note that when specifying only the ACPI method name, the path to the
appropriate device is automatically pre-pended.  For instance in the
above switchto_igd, MXMX is pre-pended with the output shown earlier
from dmesg to become \_SB_.PCI0.VGA_.MXMX.  Likewise in the
switchto_dis, the DIS path is pre-pended to become
\_SB_.PCI0.P0P1.VGA_.MXMX.  If the methods you need to call are not on
the IGD/DIS device, use the full path, starting with \_SB.

Now when I echo ON > /sys/kernel/debug/vgaswitcheroo/switch, the
power_state_dis_on script is processed (assuming I'm using the IGD).
When I switch to the discrete graphics (echo DIS >
/sys/kernel/debug/vgaswitcheroo/switch), the power_state_dis_on script
is processed if the device needs to be powered back on, then the
switchto_dis script is processed to switch the internal mux and enable
the discrete graphics.  All of the interactions with the scripts
happens through the vgaswitcheroo interface.

As an easy example of how this might work for you, run the acpi_call
test_off.sh on your system.  If it reports that it works, use the line
that it reported to work (ex. \_SB.PCI0.LPC.EC.PUBS._OFF" and put that
in your power_state_dis_off file.  If you look in your DSDT and find a
complimenting _ON method, you might be able to use that in your
power_state_dis_on entry.

This has only been lightly tested and the asus-switcheroo install
targets haven't been updated to use byo-switcheroo yet, but I hope
folks will be able to figure it out and we can generate some recipes
to build switcheroo handlers for various systems.  Thanks,

Alex

PS - Note that asus-switcheroo and byo-switcheroo are mutually
exclusive.  They both implement switcheroo handlers, and only one can
be loaded at a time (and must be loaded before any graphics driver
takes over the switcheroo handler, as previously noted).  If you use
the current install targets, you will at a minimum need to convert the
places where asus-switcheroo is setup to load to loading
byo-switcheroo.


Follow ups