Just got this Surface 3 as a hand-me-down. And I wanted to breathe some new life into it.

Plus it’d be cool to have a small x86 computer to run around with. Who knows I may use it as a dedicated radio demodulator or something else fun.

There’s actually a lot of support for these computers. Honestly I had no idea. The Linux Surface Project on github addresses most of the problems you’d run into with installing linux on a Surface.

I had a problem though. Support for the Surface 3 hasn’t really kept up with the rest of the line. And some of the recommended fixes for problems I ran into didn’t work or, at most, partially worked.

I’ve worked with this computer for the last couple of days and have finally got it to a point where I’m happy. Bluetooth and the cameras still don’t work (but to be honest I wasn’t going to use them). Most importantly to me however, the touchscreen controller isn’t crashing any more and the backlight controls finally work and are playing well with gnome.

If you’ve run into the same issues that I have and haven’t been able to find a fix yet. I hope this helps! :)


List of Fixes

List of all fixes that worked on my surface 3

DEVICE INFO: Kernel 6.8.1 Arch; GNOME 45.5; Surface 3; 2GB Ram

General Surface Drivers and Support

Arch install

Linux Surface Project

libwacom-surface driver can be installed through the AUR.

Even though it’s not needed, I did install the marvel firmware for the wifi.

Broken Drivers

Touchscreen

Problem: Touchscreen controller randomly dies.

Fix: Added intel_idle.max_cstate=1 i915.enable_dc=0 intel_iommu=off iommu=off to kernel settings.

Backlight

Problem: Backlight controls do not work.

Fix: Rebuild kernel with two drivers (pwm and i2c) switching places.

This causes the drivers to load in a different order. It’s more of a hack than anything.


Step by step

This is exactly what I did to install arch with gnome and get the touchscreen and backlight to work.

Install Arch

https://wiki.archlinux.org/title/Installation_guide Follow this guide for the initial setup before you get to the chroot part.

Preface

I do recommend changing the font in the live environment

># setfont ter-132b

And mount boot efi disk to /boot and not /boot/efi


After Chroot

Once you’re in root partition

Set timezone

># ln -sf /usr/share/zoneinfo/<Region>/<City> /etc/localtime

Update hardware clock

># hwclock --systohc

Generate locales

edit /etc/locale.gen and uncomment en_US.UTF-8 UTF-8 and other needed UTF-8 locales

># locale-gen
/etc/locale.conf
---------------------------------------
LANG=en_us.UTF-8

Set terminal font

># pacman -S terminus-font
/etc/vconsole.conf
---------------------------------------
FONT=ter-132b

Set hostname

/etc/hostname
---------------------------------------
<yourhostname>

Install text editors for later

># pacman -S vi vim

Set root password

># passwd

Install linux-surface project

These commands are subject to change. I will write out everything that I did so that maybe you can find where something went wrong

># curl -s https://raw.githubusercontent.com/linux-surface/linux-surface/master/pkg/keys/surface.asc | sudo pacman-key --add -
># pacman-key --finger 56C464BAAC421453
># pacman-key --lsign-key 56C464BAAC421453

Add repository to the end of pacman.conf

/etc/pacman.conf
---------------------------------------
[linux-surface]
Server = https://pkg.surfacelinux.com/arch/

Install main packages for linux-surface

># pacman -Syu linux-surface linux-surface-headers iptsd

Install additional packages we will need later

># pacman -S linux-firmware-marvell intel-ucode sudo networkmanager

This is everything for linux-surface for now, but we’ll get back to it later.


Install grub

># pacman -S grub efibootmgr
># grub-mkconfig -o /boot/grub/grub.cfg

Create update-grub script

/usr/sbin/update-grub
---------------------------------------
#!/bin/sh
set -e
exec grub-mkconfig -o /boot/grub/grub.cfg "$@"
># chown root:root /usr/sbin/update-grub
># chmod 755 /usr/sbin/update-grub

Install into /boot

># grub-install --target=x86_64-efi --efi-directory=/boot --bootloader-id=GRUB

Update grub config

Change line GRUB_CMDLINE_LINUX_DEFAULT="loglevel=3 quiet"

/etc/default/grub
---------------------------------------
GRUB_CMDLINE_LINUX_DEFAULT="loglevel=3 quiet intel_idle.max_cstate=1 i915.enable_dc=0 intel_iommu=off iommu=off"

The setting: intel_idle.max_cstate=1 i915.enable_dc=0 intel_iommu=off iommu=off, along with the wacom driver (that we will install later) will fix the issue of the touchscreen controller randomly dying some time after boot.

># update-grub

Create user

># useradd -m -g users -G wheel,video <username>

Set new user password

># password <username>

Enable sudo for new user

># visudo

This will open the sudoers file

Uncomment either:

%wheel ALL=(ALL:ALL) ALL For sudo access for the wheel group

%wheel ALL=(ALL:ALL) NOPASSWD: ALL Same thing without a password

Done with Arch install

># exit
># reboot

Login as user

Setup NetworkManager

>$ systemctl enable NetworkManager
>$ systemctl start NetworkManager
>$ nmcli device wifi connect <SSID> password <password>

Install gnome

>$ sudo pacman -S gnome
>$ systemctl enable gdm.service
>$ reboot

Install yay

>$ sudo pacman -S git base-devel
>$ git clone https://aur.archlinux.org/yay-bin.git
>$ cd yay-bin/
>$ makepkg -si

Install libwacom-surface

>$ yay -S libwacom-surface

Install onscreen keyboard panel button

>$ sudo pacman -S firefox gnome-browser-connector

Open firefox and go to https://extensions.gnome.org/

Install the browser extension

Search for Enhanced OSK and install

In the preferences for Enhanced OSK enable “Show Panel Indicator”

Disable login screen

On boot

Go to Settings > Users > Automatic Login : Enable

Out of suspend

>$ gsettings set org.gnome.desktop.screensaver lock-enabled false

Rebuild the Kernel

This is the only way that I have found to make the backlight controller work. There is a forum post discussing this issue. But the gist is you have two competing drivers and the wrong one is loaded first. To fix this we have to recompile the kernel.

Config settings that have worked for people in kernel version 5.6.13

CONFIG_PWM=y
CONFIG_PWM_CRC=y
CONFIG_I2C_DESIGNWARE_PLATFORM=y
CONFIG_I2C_DESIGNWARE_PCI=m
CONFIG_INTEL_SOC_PMIC=y
CONFIG_DRM_I915=m

For arch-6.8.1 the only ones we need to change are CONFIG_PWM_CRC and CONFIG_I2C_DESIGNWARE_PCI

Caution: kernel build files use approximately 10-12 GB of disk space,
and the build took me around 5 hours to complete.

Alright so lets get into it

>$ git clone https://github.com/linux-surface/linux-surface.git
>$ cd linux-surface/pkg/arch/kernel/

Get checksum of default config

>$ sha256sum config 

Keep this output for a bit later

Edit kernel configuration
config
---------------------------------------
CONFIG_PWM_CRC=y
...
CONFIG_I2C_DESIGNWARE_PCI=m

Now you have to resign the config file

>$ sha256sum config

Take the output of that command and place it into PKGBUILD

PKGBUILD
---------------------------------------
sha256sums=('SKIP'
            '<checksum>'
            ...)

Replace old config checksum with the new one.

It should be the second one in the list right after 'SKIP'

But use the old checksum we got from earlier to confirm.

Replace checksum and save PKGBUILD

Build kernel
>$ PKGEXT=".pkg.tar" MAKEFLAGS="-j8" makepkg -s --skippgpcheck
Install new kernel package
>$ sudo pacman -U linux-surface-*.pkg.tar
>$ sudo update-grub
>$ reboot

And that’s it. That is everything I’ve done to make gnome arch working on my surface 3.

References & Resources

https://wiki.archlinux.org/title/Installation_guide

https://github.com/linux-surface/linux-surface/wiki/Installation-and-Setup#arch

https://github.com/linux-surface/linux-surface/wiki/Surface-3

https://github.com/linux-surface/linux-surface/tree/master/pkg/arch

https://gitlab.freedesktop.org/drm/intel/-/issues/26