Giving an old laptop a new lease on life

I have an old laptop from 2012. It’s an old Ivy Bridge i7-3630QM CPU chip with one of those Nvidia Optimus chips (a GeForce GT 650M). The laptop itself is a rebranded Clevo W110ER. The screen resolution is 1366x768 (before HiDPI was a thing) and it’s certainly too old to handle UEFI as it uses the old way of booting.

Back in the day it ran Linux (I forget which distro) and I used it a lot for gaming, including Steam and playing one of my favorite games, the MMORPG known as Dark Age of Camelot which runs really well under WINE now. I used to use the “Bumblebee” app to run games off of the Nvidia secondary GPU (the BIOS had no facility to switch between the onboard Intel and the Nvidia GPU, so it has to be done in the OS)

The last time I checked if FreeBSD could do this, back in 2017 or 2018, it couldn’t, so I forgot about it for a while. The laptop was brought back from the dead when I took out its original SATA disk which had died and replaced it with a 256 GB SSD.

Fast-forward and it’s now 2022, and FreeBSD 13.1 is due to be released very very soon. I thought I’d give it another try as I wanted a machine to play around with Jails on and also wanted ZFS as well.

I pulled down the FreeBSD 13.1-RC2 memstick image and proceeded to install FreeBSD.

Configuring FreeBSD

After a few false starts with the network. (I made the mistake of looking online to try and remember how to do the WiFi networking as it had been a while and things changed since the last time I tried FreeBSD, then remembered the FreeBSD Handbook was the best and authoritative source and two lines later in /etc/rc.conf and configuring wpa_supplicant, I was ready to rumble:

wlans_iwn0="wlan0"
ifconfig_wlan0="WPA SYNCDHCP"

I also wanted to turn off the excruciating console beep which was like nails on a chalkboard:

allscreens_kbdflags="-b quiet.off"

So much better. I install xorg and drm-kmod (for the Intel modesetting), added it to kld_list in /etc/rc.conf and enabled dbus and X was running pretty nicely. Since the keyboard is the United Kingdom (GB) layout, I just added a file called kbd-layout.conf to the /usr/local/etc/X11/xorg.conf.d directory:

Section "InputClass"
        Identifier      "Keyboard"
        MatchIsKeyboard "yes"
        Option          "XkbLayout" "gb"
EndSection

Fun with Nvidia Optimus

I found two packages that looked like they would do the trick, they are:

x11/nvidia-hybrid-graphics-390
x11/nvidia-secondary-driver-390

Because this laptop is so old and is running an Nvidia GeForce GT 650M, the last Nvidia driver to support it was 417. However, 390 is in FreeBSD’s ports/packages, so I went with that. I installed those and then needed to edit xorg-nvidia-headless.conf which runs a headless X windows server on :8.

pciconf -lv shows me the bus ID and info for the Nvidia display:

vgapci0@pci0:1:0:0:     class=0x030000 rev=0xa1 hdr=0x00 vendor=0x10de device=0x0fd1 subvendor=0x1558 subdevice=0x1150
    vendor     = 'NVIDIA Corporation'
    device     = 'GK107M [GeForce GT 650M]'
    class      = display
    subclass   = VGA

For some reason, the nvidia-headless-xconfig in x11/nvidia-hybrid-graphics-390 didn’t add this BusID, and I mistakenly tried using the incorrect mapping:

 BusID       "PCI:0:1:0"

However, this didn’t work and the nvidia_xorg didn’t start. I sent an email to the package maintainer and they helpfully pointed me in the right direction.. the BusID needed to be “PCI:1:0:0” – I must have just read the output wrong. It had been a while since I configured X by hand!

The working /usr/local/etc/X11/xorg-nvidia-headless.conf:

Section "ServerLayout"
    Identifier     "nvidia"
    Screen      0  "Screen0" 0 0
    InputDevice    "fake" "CorePointer" "CoreKeyboard"
    Option         "AutoAddDevices" "false"
EndSection

Section "Files"
    ModulePath      "/usr/local/lib/xorg/modules-NVIDIA"
    ModulePath      "/usr/local/lib/xorg/modules"
EndSection

Section "Module"
    Load           "dri3"
    Load           "glx"
    Disable        "efifb"
EndSection

Section "InputDevice"
    Identifier     "fake"
    Driver         ""
EndSection

Section "Monitor"
    Identifier     "Monitor0"
EndSection

Section "Device"
    Identifier     "Device0"
    Driver         "nvidia"
    BusID          "PCI:1:0:0"
EndSection

Section "Screen"
    Identifier     "Screen0"
    Device         "Device0"
    Monitor        "Monitor0"
EndSection

Service starts up now and works!

Testing with glxinfo / glxgears

glxinfo -B snippet with the Intel driver:

name of display: :0
display: :0  screen: 0
direct rendering: Yes
Extended renderer info (GLX_MESA_query_renderer):
    Vendor: Intel Open Source Technology Center (0x8086)
    Device: Mesa DRI Intel(R) HD Graphics 4000 (IVB GT2) (0x166)
    Version: 21.3.8
    Accelerated: yes
    Video memory: 1536MB
    Unified memory: yes
    Preferred profile: core (0x1)
    Max core profile version: 4.2
    Max compat profile version: 3.0
    Max GLES1 profile version: 1.1
    Max GLES[23] profile version: 3.0
OpenGL vendor string: Intel Open Source Technology Center
OpenGL renderer string: Mesa DRI Intel(R) HD Graphics 4000 (IVB GT2)
OpenGL core profile version string: 4.2 (Core Profile) Mesa 21.3.8
OpenGL core profile shading language version string: 4.20
OpenGL core profile context flags: (none)
OpenGL core profile profile mask: core profile

glxinfo -B snippet with the Nvidia driver on :8 :

name of display: :0
display: :0  screen: 0
direct rendering: Yes
Memory info (GL_NVX_gpu_memory_info):
    Dedicated video memory: 2048 MB
    Total available memory: 2048 MB
    Currently available dedicated video memory: 1992 MB
OpenGL vendor string: NVIDIA Corporation
OpenGL renderer string: GeForce GT 650M/PCIe/SSE2
OpenGL core profile version string: 4.5.0 NVIDIA 390.144
OpenGL core profile shading language version string: 4.50 NVIDIA
OpenGL core profile context flags: (none)
OpenGL core profile profile mask: core profile

OpenGL version string: 4.5.0 NVIDIA 390.144
OpenGL shading language version string: 4.50 NVIDIA
OpenGL context flags: (none)
OpenGL profile mask: (none)

glxgears with the Intel driver:

Running synchronized to the vertical refresh.  The framerate should be
approximately the same as the monitor refresh rate.
319 frames in 5.0 seconds = 63.756 FPS
300 frames in 5.0 seconds = 59.937 FPS
300 frames in 5.0 seconds = 59.938 FPS

glxgears with the Nvidia driver:

2681 frames in 5.0 seconds = 536.023 FPS
2758 frames in 5.0 seconds = 551.551 FPS

Not synced to vertical refresh.

Lastly, I fired up Dark Age of Camelot by running WINE (7.4) with optirun and it ran pretty fast (faster than when I tested on the Intel driver). The laptop remained fairly cool, which, for this laptop was about 60-65 C. The fan didn’t run that much and the game ran pretty smoothly on my external monitor at 1920x1080.

One thing I wasn’t expecting when using 2 monitors in FreeBSD: X windows would extend the desktop over two monitors making it really hard to see the windows, so I ended up running xrandr --output LVDS-1 --off to just send output to the external monitor (listed as HDMI-1). I think this may just be Xinerama doing it so it might just need some tweaks.

Now all I have to do is figure out how I can get ckb-next ported to the BSDs so I can use my 12-button Corsair RGB Pro mouse. (It only can be programmed in Linux currently, but it looks like it might be it needs a hook written into libusb for the port.)

That’s a project for another day.

It’s great that FreeBSD fully supports the Nvidia Optimus chipset and that should make gaming a whole lot better with this laptop on FreeBSD.

Update: 19th April 2022

I found that Xorg probes two drivers before the modesetting driver: scfb and vesa. So, I removed xf86-video-scfb and xf86-video-vesa. Once those were removed, Xorg started up with the modesetting driver and Xinerama and Xrandr extensions both work and I don’t get the desktop stretched across two monitors any more.