High-performance, multi-client Linux driver for the Elgato 4K60 Pro MK.2 and Elgato 4K Pro PCI-e capture cards. Engineered for stability on modern kernels (6.12 through 7.0+).
For older kernels, use the original stoth68000/sc0710 repository (MK.2 only).
| Card | Subsystem ID | Notes |
|---|---|---|
| Elgato 4k60 Pro MK.2 | 1cfa:000e |
Plug-and-play after driver load. No FPGA firmware step. |
| Elgato 4K Pro | 1cfa:0012 |
Requires ECP5 FPGA firmware programming on every cold boot. Handled automatically by the installer and the AUR package; manual insmod builds need extra steps (see below). |
Both cards share the same 12ab:0710 Magewell chipset but use different board profiles in the driver.
| Distribution | Status | Notes |
|---|---|---|
| Arch Linux | Stable | DKMS via AUR (sc0710-dkms-git) or manual build. Includes sc0710-cli and 4K Pro firmware helpers (see below). |
| Fedora / RHEL | Stable | DKMS via the automatic installer. |
| Debian / Ubuntu | Stable | Warning: distro OBS packages may crash; prefer Flatpak OBS. |
| Fedora Atomic (Bazzite, Bluefin, Aurora, Silverblue) | Stable | Boot-time build service at /var/lib/sc0710. No DKMS. 4K Pro ECP5 stack included. |
| NixOS | Supported | Flake module builds the driver and installs sc0710-cli; 4K Pro firmware is a one-time extract-firmware.sh run (see below). |
Tested on kernel 6.12 through 7.0+. Newer kernels may work but are not guaranteed until tested.
Unified installer — auto-detects atomic vs standard distros. Supported on Arch, Debian/Ubuntu, Fedora, and Fedora Atomic (Bazzite, Silverblue, Bluefin, Aurora).
sudo bash -c "$(curl -fsSL https://raw.githubusercontent.com/Nakildias/sc0710/main/scripts/install-sc0710.sh)"Standard distros get DKMS (optional) or a manual module build, sc0710-cli, and boot-time module loading via modules-load.d.
Atomic distros get:
- Driver source at
/var/lib/sc0710/(persists acrossrpm-ostreeupdates) sc0710-build.service— rebuilds and loads the module on each bootsc0710-cliwith atomic-specific commands (--rebuild, etc.)
4K Pro on any distro additionally gets extraction of SC0710.FWI.HEX from the Elgato Windows driver at install time (extract-firmware.sh, with pinned checksums). Downloading from Elgato always asks for consent first, so a non-interactive install extracts only if the Elgato package is already on disk — otherwise re-run the script in a terminal afterwards.
The 4K Pro has a Lattice ECP5 FPGA whose configuration is volatile — it is lost on full power-off / cold boot. Windows programs it on every boot; this driver programs it during its probe, and fails the probe if it can't (missing firmware file, upload failure) — the card then stays unbound and no /dev/video* appears, with the reason in dmesg.
If the card didn't bind:
sudo dmesg | grep sc0710 # shows why the probe failed
sudo bash scripts/extract-firmware.sh # if the firmware file is missing
sudo sc0710-cli --restartyay -S sc0710-dkms-gitThe AUR package installs:
- DKMS kernel module — rebuilds automatically on kernel updates
sc0710-cliat/usr/bin/sc0710-cli— same management tool as the automatic installer- 4K Pro firmware helpers under
/usr/lib/sc0710/(extract-firmware.sh,sc0710-firmware-lib.sh)
MK.2 users can load with sudo modprobe sc0710 (or enable /etc/modules-load.d/sc0710.conf for boot load) and manage the driver with sc0710-cli.
4K Pro users — if a 4K Pro card (1cfa:0012) is present at install/upgrade time, the package hook:
- Extracts
SC0710.FWI.HEXif the Elgato installer is already on disk (p7zipneeded; the hook never downloads — pacman runs it non-interactively, and downloading from Elgato requires a consent prompt). If firmware ends up missing, runsudo bash /usr/lib/sc0710/extract-firmware.shin a terminal afterwards. - Configures boot module loading via
modules-load.dandmodprobe.dsoftdeps - Loads the driver (which programs the ECP5 during its probe)
After a cold boot, the driver programs the ECP5 when the module loads — no services involved. If the card didn't bind (no /dev/video*):
sudo dmesg | grep sc0710
sudo sc0710-cli --restartIf the card was added after the AUR install, extract the firmware manually:
sudo /usr/lib/sc0710/extract-firmware.sh
sudo sc0710-cli --restartRemoving the AUR package — firmware files under /lib/firmware/sc0710/ are not removed by yay -R; use sc0710-cli --remove for a full cleanup.
Upgrading from an older package version — old versions created sc0710-firmware.service/sc0710-firmware-verify.service outside the package (the driver programs the ECP5 itself now, so they no longer exist). The package upgrade removes those leftovers automatically; the removal check script flags any stragglers.
4K Pro on Arch — the maintainer primarily tests on MK.2 hardware. Cold-boot ECP5 reports from 4K Pro users are especially welcome (open an issue with sc0710-cli --dump).
Add github:Nakildias/sc0710 as a flake input and import sc0710.nixosModules.default:
{
inputs = {
# ...
sc0710.url = "github:Nakildias/sc0710";
};
outputs = { self, nixpkgs, sc0710 }: {
nixosConfigurations.<your-hostname> = nixpkgs.lib.nixosSystem {
modules = [
# ...
sc0710.nixosModules.default
];
};
};
}Host configuration:
hardware.sc0710.enable = true; # kernel module + sc0710-cli
# hardware.sc0710.kernel = pkgs.linuxPackages_6_19.kernel; # optional overrideNote: The NixOS module builds the driver and installs sc0710-cli. 4K Pro users on NixOS additionally run scripts/extract-firmware.sh once (as root, from a repo checkout) to provision the ECP5 firmware and EDID profiles — it installs to /lib/firmware/sc0710, which the kernel firmware loader reads directly. (MK.2 users don't need it: capture works without firmware files, and custom EDIDs are written at runtime — no firmware install required.) The driver programs the FPGA at every module load and refuses to bind if it can't, so no boot service is needed.
For development or unsupported distros.
-
Install dependencies
- Arch:
sudo pacman -S base-devel linux-headers git - Debian/Ubuntu:
sudo apt install build-essential linux-headers-$(uname -r) git - Fedora/RHEL:
sudo dnf install kernel-modules-$(uname -r) kernel-devel kernel-headers gcc make git
- Arch:
-
Build and load
git clone https://github.com/Nakildias/sc0710 cd sc0710 make sudo insmod build/sc0710.ko -
4K Pro only —
insmodalone is not enough on cold boot. You also need:SC0710.FWI.HEXin/lib/firmware/sc0710/(extract withscripts/extract-firmware.sh)- Reload the module after cold boot so the driver can program the ECP5, or use the automatic installer
Installed by the automatic installer, the AUR package, and the NixOS module. Provides real-time control on both atomic and standard distros.
| Command | Alias | Description |
|---|---|---|
--status |
-s |
Module state, card info, signal format, ECP5 status (4K Pro), DKMS or build service status |
--load |
-l |
Load the module. On 4K Pro, verifies ECP5 programming after load |
--unload |
-u |
Unload the module (stops PipeWire consumers if the module is busy) |
--restart |
Full reload. On 4K Pro, runs ECP5 programming with retries | |
--debug |
-d |
Toggle verbose dmesg logging |
--image-toggle |
-it |
Toggle No Signal images vs colorbars |
--procedural-timings |
-pt |
Cycle timing mode: merge → procedural-only → static-only |
--update |
-U |
Pull latest source, rebuild, reload. On 4K Pro, re-runs ECP5 programming with retries |
--rebuild |
(Atomic only) Force rebuild the module for the running kernel | |
--dump |
Save a debug report to the Desktop (dump-DD-MM-YYYY.txt) for GitHub issues |
|
--remove |
-r, -R |
Uninstall driver, CLI, services, config files, and 4K Pro firmware |
--version |
-v |
Show installed driver version |
--help |
-h |
Show all options |
After sc0710-cli --remove, verify everything is gone:
bash -c "$(curl -fsSL https://raw.githubusercontent.com/Nakildias/sc0710/main/scripts/check-sc0710-removal.sh)"Same command as above — checks module, DKMS, CLI, systemd units, config files, logs, and 4K Pro firmware. No clone or sudo required. Exits 0 when fully clean.
- Multi-client support — multiple apps (e.g. OBS + Discord) can open the device simultaneously
- DKMS integration — automatic rebuilds on kernel updates (standard distros)
- Atomic / immutable support — boot-time rebuild via
sc0710-build.service(Bazzite, Silverblue, etc.) - 4K Pro ECP5 auto-programming — firmware extraction at install time; the driver programs the FPGA at load and refuses to bind if it can't
- Status images — storage-efficient No Signal / No Device screens
- Connection sensing — distinguishes unplugged cables from signal loss (not 100% reliable)
- Video formats — 4K60, 1440p144, 1080p240. EDID Source control (Internal/Display/Merged) on both cards via the
EDID SourceV4L2 control (v4l2-ctl --set-ctrl=edid_source=N). Custom EDID read/write on both cards viaVIDIOC_G_EDID/VIDIOC_S_EDID— the 4K Pro through its EEPROM (edid=boot param, profiles fromscripts/extract-firmware.sh), the MK.2 through its MCU (runtime only). The graphical EDID Config app (sc0710-cli --edid-config) manages this for both cards and can fetch Elgato's official EDID profiles - Mode-switch stability — DMA resync, restart validation, and watchdog recovery during resolution/refresh changes; apps are told to renegotiate via
V4L2_EVENT_SOURCE_CHANGE - Timing controls — runtime modes (
merge,procedural-only,static-only) via CLI - HDR (MK.2) — host PQ→SDR tonemap on YUYV and BGR24, MCU hardware tonemap via
hw_tonemap/ MCU0x11, or native BGR24 HDR passthrough with BT.2020/PQ tags - Driver manager GUI —
sc0710-cli --gui(load/unload/restart, toggles, EDID/HDR config launchers, dump + HDR tests) - Debug dumps —
sc0710-cli --dumpcollects distro, kernel,lspci, driver version, and service state for issue reports
Two capture formats are offered; pick per app over V4L2, no reload:
YUYV(default) — packed 4:2:2, 2 bytes/pixel. Lowest bandwidth, always available.BGR24— native 4:4:4, 3 bytes/pixel: the card's full-chroma mode (Elgato markets it "RGB24 8-bit 4:4:4"; the bytes are BGR-ordered). ~50 % more PCIe/RAM bandwidth than YUYV, so it is opt-in. Reported as full-range sRGB for SDR, or BT.2020 / PQ when HDMI is HDR and host tonemap is off.
v4l2-ctl -d /dev/video0 --list-formats # YUYV + BGR3
v4l2-ctl -d /dev/video0 --set-fmt-video=pixelformat=BGR3 # select 4:4:4
# OBS / ffmpeg pick it via the normal format menu / -pixel_format bgr24On MK.2, HDR mode can also auto-select the format while idle:
sw_tonemap=1(default) + HDMI HDR-PQ → host PQ→SDR preview: BGR24 luminance-preserving RGB (preferred); YUYV limited-range Y LUT + mild chroma pull. SDR tags.sw_tonemap=0+hdr_bgr24=1(default) + HDMI HDR → prefer BGR24, BT.2020/PQ tags (no P010)- SDR → leave format alone / YUYV default; no tonemap
Use sc0710-cli --gui for the manager, --hdr-config (-hc) for tonemap presets, or --hdr-toggle to cycle modes.
The format is device-wide (one card, one DMA pipeline) and can only be changed while no app
is capturing or holding buffers (a change attempt then returns EBUSY). Interlaced sources
are YUYV-only: a BGR24 request is clamped to YUYV, and if a signal turns interlaced
mid-session under BGR24 the driver delivers no frames until the format or signal changes.
For bit-accurate RGB capture, also present an RGB-only EDID (below): on a YCbCr wire the
card round-trips RGB→YCbCr→RGB and loses ~2 codes; on an RGB wire it captures within ±1 of
bit-perfect.
The card presents an EDID to the HDMI source; changing it changes what the source outputs (resolution, and RGB vs YCbCr). Two ways:
edid=<name>module param — loads/lib/firmware/sc0710/edid/<name>.binat module load (profiles installed byextract-firmware.sh), e.g.edid=1440p.VIDIOC_S_EDIDat runtime —v4l2-ctl --set-edid. For a raw binary EDID file add,format=raw; the default expects the hex-text format that--get-edidproduces:
v4l2-ctl -d /dev/video0 --get-edid # dump current (hex text)
v4l2-ctl -d /dev/video0 --set-edid=file=my-edid.bin,format=raw # write a raw .binAn RGB-only EDID (color-encoding bits 00, no YCbCr flags) makes the source output RGB
4:4:4 — the wire to pair with BGR24 for bit-accurate 4:4:4 capture. The source
renegotiates ~8–10 s after a write (a brief re-detect of the old mode first is normal).
- Interrupt-driven completion (
irq_service=1, default) — the card's MSI wakes the DMA service when a frame completes, replacing the 2 ms completion polling; completion latency drops to interrupt latency and the idle polling load goes away. Polling survives as a 100 ms watchdog tick: completed work the watchdog finds that no interrupt announced is logged and counted (irq:line in/proc/sc0710-state), and three consecutive misses drop the session back to 2 ms polling with a KERN_ERR in dmesg.irq_service=0restores classic polling; failed MSI allocation logs a warning and falls back to polling. (thread_dma_poll_interval_msremains as an override for the service tick; the default auto-selects.) zero_copy=1(experimental) — DMA frames straight into the capturing app's buffers, skipping the per-frame copy (~1.5–3 ms at 4K). Strict single-client mode: one streaming app per video node (a second getsEBUSY). Load-time only. The DMA descriptor fetcher is credit-gated in this mode — early hardware testing caught it consuming stale (pre-rewrite) descriptors and writing into already-delivered buffers; with credits a chain is only fetchable after its rewrites, and a permanent writeback sentinel trips loudly (and falls back to the copy path) if a stale fetch ever happens anyway. Validated on hardware: a userspace mutation checker (checksumming app-owned buffers) runs clean, with zero sentinel events across long captures. For full engagement keep more buffers queued than the DMA ring has chains (5+, e.g.--stream-mmap=8; most players do) — a thin queue routes starved laps through the copy path (zc frames:in/proc/sc0710-stateshows the direct/copied split). Buffers can be exported as dmabufs (VIDIOC_EXPBUF) for GPU-direct consumers.zero_copy=0(the default) keeps the vendor's free-running ring, byte-identical.
Zero-copy buffer eligibility: a frame is DMA'd directly into a buffer when the
buffer's DMA segments fit the chain's descriptor budget (zc_split=, default 8, max
32); the frame is tiled across the buffer's own segments, so fragmentation within the
budget is fine. Buffers over the 32-segment hard limit are refused at QBUF with a
zero-copy: buffer memory too fragmented dmesg line; buffers between the budget and
the limit are accepted but served through the copy path (visible in the zc frames:
split — raise zc_split= to widen the budget). If buffers are too fragmented, fixes,
best first:
# Give ONLY the capture card a translating IOMMU domain (runtime, reversible,
# no reboot; resets to the boot default on reboot). VFIO passthrough and every
# other host device are unaffected.
G=$(basename $(readlink /sys/bus/pci/devices/<BDF>/iommu_group))
echo <BDF> | sudo tee /sys/bus/pci/devices/<BDF>/driver/unbind
echo DMA-FQ | sudo tee /sys/kernel/iommu_groups/$G/type
echo <BDF> | sudo tee /sys/bus/pci/drivers_probe
# or: defragment and retry
sudo sh -c 'echo 1 > /proc/sys/vm/compact_memory'| Problem | What to try |
|---|---|
4K Pro: card didn't bind / no /dev/video* (cold boot) |
sudo dmesg | grep sc0710 for the probe error; if firmware is missing run extract-firmware.sh, then sudo sc0710-cli --restart |
| Module won't unload (app in use) | sc0710-cli --unload stops PipeWire first; close OBS/etc. |
| Atomic: module not built after kernel update | sudo sc0710-cli --rebuild or check journalctl -u sc0710-build.service -b |
Driver still present after --remove |
Run sudo sc0710-cli --remove again, then the removal check script |
| 4K60 tearing / frame shifts at max bandwidth | Under investigation; try lower resolution/refresh or close extra consumers in the meantime |
For GitHub issues, attach output from sc0710-cli --dump.
- 4K60 DMA tearing — horizontal tears or frame shifts at 4K60 (~995 MB/s) under heavy load; under active investigation
- 10-bit planar formats — P010/P016 not implemented; HDR passthrough uses native BGR24 4:4:4 instead
Maintainer Nakildias only has an Elgato 4k60 Pro MK.2 available for hands-on testing. That limits how much can be validated on other hardware.
Contributions and testing help are especially welcome for:
- Elgato 4K Pro — ECP5 cold-boot behavior, atomic/Bazzite installs, and general capture stability
- Unsupported cards — other
12ab:0710subsystem IDs (e.g. HD60 Pro) that are not yet fully supported - Open issues — bugs that need reproduction on hardware the maintainer does not own (4K60 tearing, edge-case distros, etc.)
If you can test, debug, or submit patches for any of the above, please open an issue or a pull request. Include sc0710-cli --dump output when reporting problems.
This fork is maintained by Nakildias (nakildiaspro@gmail.com).
- Based on original reverse engineering by Steven Toth (@stoth68000) and subsequent work by @Subtixx.
- Thanks to Onhil (@Onhil) for his work on the Elgato 4K Pro.
- Thanks to JerwuQu (@JerwuQu) for his work on the Elgato 4K Pro EDID Flashing & BRG24 Support.
The kernel module is a derivative of Steven Toth's sc0710 driver (GPL v2). Original copyright notices are preserved in source files; modifications in this fork are attributed separately. Installer scripts are original work in this repository. See COPYRIGHT for details.
This project is not affiliated with or endorsed by Elgato, Magewell, or Kernel Labs.