nvidia optimus tricks (was: F16 - Adding a second video card)

Roberto Ragusa mail at robertoragusa.it
Tue Jul 24 07:40:59 UTC 2012


On 07/18/2012 04:11 PM, Adrian Sevcenco wrote:
> On 07/18/12 11:01, Roberto Ragusa wrote:

>> I was quite surprised to be able to use both the Intel integrated
>> and Nvidia discrete on a "Nvidia Optimus" Lenovo Thinkpad.
>> (also considering what Linus has recently expressed about Nvidia
>> commitment to Linux)
>>
>> It is possible to actually run two X servers, with the Intel chipset
>> driving the LCD panel and the Nvidia board driving the VGA.
>> It was quite a bit of work to configure, but it is working fine
>> now (I can also poweron and poweroff the Nvidia chip very simply
>> without any reboot or session restart).
>>
>> (all this experimentation because it seems it is not possible to
>> have VGA output on the Intel chipset)

> Hi! How did you do it? i have an t420 and it would be interesting to play with this...

Maybe I should write a detailed HOWTO, but I will try to describe it
here.
My investigation says that not all laptops have the same arrangement
(some do not have multiplexers and cannot switch mode), this is what
is working for me on a W520 (hopefully on your T420 too).

- BIOS: configure "Nvidia Optimus" mode: this means both the cards are
activated; the Intel one is routed to the internal panel, the Nvidia one
is routed to VGA and other external outputs. (other options are intel only
and nvidia only, they make hardware invisible).

- BIOS: turn off "detect Nvidia Optimus operating system": I don't know
what kind of magic it is trying to do, but it is always better to not
trust the BIOS.

- the kernel will init both cards (as I see in dmesg); for some reason
the Intel board appears to have a higher priority, it happens that what
you are seeing on the screen comes from Intel.

- run X in autodetection mode (no conf), it will fire up on the
Intel one (LCD)

- run everything you want on the Intel screen (including 3D)

- run another X process, I do it this way:
    xinit -display :1 -- -novtswitch -sharevts -config xorg.conf_nvidiaW520 vt1 :1

  explanations needed:

  - xinit launches an X server and a client (xterm), it could be easier to
    separate che X server (which is the hard part) and then mess with the
    clients (you just have to use DISPLAY=:1)
    The X server would have to be started with
      X -novtswitch -config xorg.conf_nvidiaW520 vt1 :1

  - we assume the existing X server (intel) is running on vt1

  - we run the second one (nvidia) on vt 1 too (!), so -sharevts

  - this is why we have to use -novtswitch; we want to avoid that enabling
    the Nvidia turns off the Intel and vice versa; in that case I've seen that
    the screen remains visible, but the software does not refresh the
    windows anymore, until you "switch" vt again with Ctrl-Alf-F{1,2,...}

  - having two X running on vt1 means they are really active at the same time;
    one funny effect of this is that key presses and mouse movements would go to
    both the screens (amazing to see that!!)

  - the specific xorg.conf I use basically does a few things (I'm pasting it below):

    - it forces nouveau (as autodetection prefers the intel)

    - it tries to disconnect any kind of mouse and keyboard from the secondary
      server, which, yes, remains without any input devices

    - it includes the vnc module and sets the necessary options to
      make it usable through a password protected connection; you have to run
      "vncpasswd /etc/X11/vncpasswd" once, to set your password

    - it sets a default size for the screen (1024x768); keep in mind that
      the nvidia hardware could have no monitor attached, so autodetection of
      resolution will not make a lot of sense

  - you can now set your DISPLAY to :1 and run things (xterm, fluxbox, ...); they
    are still invisible

  - you can connect via vnc to localhost:1 (port 5901); you get access to the
    display and send key presses and mouse inputs via vnc

  - if you have an external VGA monitor attached the nvidia will output on
    that when X starts (that is my use-case: external projector)

  - you can use xrandr (with DISPLAY=:1) and do everything you want (but I have seen
    that changing resolution on the fly confuses the vnc module and crashes X)

If that is not enough, I have more: you can switch the nvidia hardware on/off
to save battery.
You need the bbswitch kernel module (very easy to compile from source, project
Bumblebee). The switch is controlled though a /proc/acpi/bbswitch file. You can cat
and echo it. You have to avoid turning off the hardware when nouveau is loaded
or loading nouveau when the hardware is switched off.
I have two scripts for that (VGAon, VGAoff), another script launches X
(it is called X2).
So what I do is:

VGAon --- this switches the hw on and loads nouveau
X2 --- (without &, so this terminal is now busy, I move to another one)
vncviewer :1 --- here is my desktop, with just an xterm, I now run fluxbox or ooimpress, ...

stopping is done with:

Ctrl-C in the X2 terminal (everything on that screen dies)
VGAoff --- this removes nouveau and switches the hw off

Suggestions and improvements are kindly accepted. :-)

Finally, here are my files:

------------------------------------------------------------------------

# cat /etc/X11/xorg.conf_nvidiaW520
Section "ServerLayout"
        Identifier     "X.org Configured"
        Screen      0  "Screen0" 0 0
        InputDevice    "Mouse0" "CorePointer"
        InputDevice    "Keyboard0" "CoreKeyboard"
        Option "AutoAddDevices" "off"
        Option "AllowEmptyInput" "on"
EndSection

Section "Files"
        ModulePath   "/usr/lib64/xorg/modules"
        FontPath     "catalogue:/etc/X11/fontpath.d"
        FontPath     "built-ins"
EndSection

Section "Module"
        Load  "vnc"
        Load  "dri2"
        Load  "glx"
        Load  "extmod"
        Load  "dri"
        Load  "dbe"
        Load  "record"
EndSection

Section "InputDevice"
        Identifier  "Keyboard0"
        Driver      "void"
EndSection

Section "InputDevice"
        Identifier  "Mouse0"
        Driver      "void"
        Option      "Protocol" "auto"
#       Option      "Device" "/dev/input/mice"
        Option      "Device" "/dev/null"
        Option      "ZAxisMapping" "4 5 6 7"
EndSection

Section "Monitor"
        Identifier   "Monitor0"
        VendorName   "Monitor Vendor"
        ModelName    "Monitor Model"
EndSection

Section "Device"
        ### Available Driver options are:-
        ### Values: <i>: integer, <f>: float, <bool>: "True"/"False",
        ### <string>: "String", <freq>: "<f> Hz/kHz/MHz",
        ### <percent>: "<f>%"
        ### [arg]: arg optional
        #Option     "SWcursor"                  # [<bool>]
        #Option     "HWcursor"                  # [<bool>]
        #Option     "NoAccel"                   # [<bool>]
        #Option     "ShadowFB"                  # [<bool>]
        #Option     "VideoKey"                  # <i>
        #Option     "WrappedFB"                 # [<bool>]
        #Option     "GLXVBlank"                 # [<bool>]
        #Option     "ZaphodHeads"               # <str>
        #Option     "PageFlip"                  # [<bool>]
        Identifier  "Card0"
        Driver      "nouveau"
        BusID       "PCI:1:0:0"
EndSection

Section "Screen"
        Identifier "Screen0"
        Device     "Card0"
        Monitor    "Monitor0"
        SubSection "Display"
                Viewport   0 0
                Depth     1
        EndSubSection
        SubSection "Display"
                Viewport   0 0
                Depth     4
        EndSubSection
        SubSection "Display"
                Viewport   0 0
                Depth     8
        EndSubSection
        SubSection "Display"
                Viewport   0 0
                Depth     15
        EndSubSection
        SubSection "Display"
                Viewport   0 0
                Depth     16
        EndSubSection
        SubSection "Display"
                Viewport   0 0
                Depth     24
                Modes     "1024x768"
        EndSubSection
        Option "SecurityTypes" "VncAuth"
        Option "PasswordFile" "/etc/X11/vncpassword"
EndSection

------------------------------------------------------------------------

# cat `which VGAon`
#!/bin/bash

grep -q ON /proc/acpi/bbswitch && echo "Nvidia is on" ||
(
    echo "Nvidia is off, turning on..."
    echo ON >/proc/acpi/bbswitch
    grep -q ON /proc/acpi/bbswitch && echo "Nvidia is on" ||
    (
      echo "Nvidia activation FAILED."
      exit 1
    )
)

lsmod|grep -q nouveau$ && echo "nouveau is loaded" ||
(
    echo "nouveau is not loaded, loading..."
    modprobe nouveau
    lsmod|grep -q nouveau$ && echo "nouveau is loaded" ||
    (
      echo "nouveau loading FAILED."
      exit 2
    )
)

------------------------------------------------------------------------

#cat `which VGAoff`
#!/bin/bash

! lsmod|grep -q nouveau$ && echo "nouveau is not loaded" ||
(
    echo "nouveau is loaded, unloading..."
    modprobe -r nouveau
    ! lsmod| grep -q nouveau$ && echo "nouveau is not loaded" ||
    (
      echo "nouveau unloading FAILED."
      exit 2
    )
)

grep -q OFF /proc/acpi/bbswitch && echo "Nvidia is off" ||
(
    echo "Nvidia is on, turning off..."
    echo OFF >/proc/acpi/bbswitch
    grep -q OFF /proc/acpi/bbswitch && echo "Nvidia is off" ||
    (
      echo "Nvidia deactivation FAILED."
      exit 1
    )
)

------------------------------------------------------------------------

-- 
   Roberto Ragusa    mail at robertoragusa.it




More information about the users mailing list