]> git.alsa-project.org Git - alsa-ucm-conf.git/commitdiff
USB-Audio/Focusrite: fix 18i20 gen1/gen2 digital capture input mapping
authorKim McCann <amplogik@gmail.com>
Sun, 28 Jun 2026 17:13:27 +0000 (10:13 -0700)
committerJaroslav Kysela <perex@perex.cz>
Fri, 9 Oct 2026 08:35:56 +0000 (10:35 +0200)
The 1st/2nd-gen Scarlett 18i20 expose 18 USB capture channels, laid out
as Analog 1-8 (ch 0-7), S/PDIF 1-2 (ch 8-9), ADAT 1-8 (ch 10-17). The
3rd/4th gen insert two extra channels at 8-9, shifting S/PDIF to 10-11
and ADAT to 12-19. The HiFi.conf only ever encoded the 20-channel layout
for the digital inputs.

A recent fix worked around the resulting out-of-range error on gen1/gen2
by shrinking the ADAT input to 6 channels (12-17), but that is incorrect:
gen1/gen2 still have all 8 ADAT inputs (they sit at 10-17), and their
S/PDIF inputs are at 8-9, not 10-11. The previous version therefore
dropped ADAT 7-8 and mislabelled ADAT 1-2 as S/PDIF.

Make the digital-input channel indices generation-aware via new
SpdifInCh*/AdatInCh* variables (default = 20-ch layout, overridden in the
gen1/gen2 blocks). Both layouts have 8 ADAT channels, so the conditional
channel-count split collapses back into a single Direct 2 device.

Verified on 1st-gen hardware (USB 1235:800c): the capture routing
(Input Source NN Capture Route) reports Analog 1-8 / S/PDIF 1-2 / ADAT
1-8 on channels 0-17, and the profile now parses without UCM errors.

Closes: https://github.com/alsa-project/alsa-ucm-conf/pull/798
Signed-off-by: Kim McCann <amplogik@gmail.com>
Signed-off-by: Jaroslav Kysela <perex@perex.cz>
ucm2/USB-Audio/Focusrite/Scarlett-18i20-HiFi.conf
ucm2/USB-Audio/Focusrite/Scarlett-18i20.conf

index aced27b14c544dd80ee19608b98b0bb2ef8f489e..c474d67138464c6df4d1c196d530dd25cffc63dd 100644 (file)
@@ -496,7 +496,7 @@ SectionDevice."SPDIF 2" {
                Direction Capture
                HWChannels "${var:DirectCaptureChannels}"
                Channels 1
-               Channel0 10
+               Channel0 "${var:SpdifInCh0}"
                ChannelPos0 MONO
        }
 }
@@ -513,77 +513,40 @@ SectionDevice."SPDIF 3" {
                Direction Capture
                HWChannels "${var:DirectCaptureChannels}"
                Channels 1
-               Channel0 11
+               Channel0 "${var:SpdifInCh1}"
                ChannelPos0 MONO
        }
 }
 
 # Digital (Professional) Inputs
-#
-# Gen 1/2 have 18 capture channels (ADAT 1-6), Gen 3+ have 20 (ADAT 1-8).
-# Channel indices 18-19 are out of bounds when DirectCaptureChannels is 18,
-# so conditionally size the ADAT capture device.
-
-If.adat_in_18ch {
-       Condition {
-               Type String
-               String1 "${var:DirectCaptureChannels}"
-               String2 "18"
-       }
-       True.SectionDevice."Direct 2" {
-               Comment "ADAT Optical Input"
-
-               Value {
-                       CapturePriority 48
-               }
 
-               Macro.pcm_split.SplitPCMDevice {
-                       Name "18i20_adat_in"
-                       Direction Capture
-                       HWChannels "${var:DirectCaptureChannels}"
-                       Channels 6
-                       Channel0 12
-                       Channel1 13
-                       Channel2 14
-                       Channel3 15
-                       Channel4 16
-                       Channel5 17
-                       ChannelPos0 UNKNOWN
-                       ChannelPos1 UNKNOWN
-                       ChannelPos2 UNKNOWN
-                       ChannelPos3 UNKNOWN
-                       ChannelPos4 UNKNOWN
-                       ChannelPos5 UNKNOWN
-               }
-       }
-       False.SectionDevice."Direct 2" {
-               Comment "ADAT Optical Input"
+SectionDevice."Direct 2" {
+       Comment "ADAT Optical Input"
 
-               Value {
-                       CapturePriority 48
-               }
+       Value {
+               CapturePriority 48
+       }
 
-               Macro.pcm_split.SplitPCMDevice {
-                       Name "18i20_adat_in"
-                       Direction Capture
-                       HWChannels "${var:DirectCaptureChannels}"
-                       Channels 8
-                       Channel0 12
-                       Channel1 13
-                       Channel2 14
-                       Channel3 15
-                       Channel4 16
-                       Channel5 17
-                       Channel6 18
-                       Channel7 19
-                       ChannelPos0 UNKNOWN
-                       ChannelPos1 UNKNOWN
-                       ChannelPos2 UNKNOWN
-                       ChannelPos3 UNKNOWN
-                       ChannelPos4 UNKNOWN
-                       ChannelPos5 UNKNOWN
-                       ChannelPos6 UNKNOWN
-                       ChannelPos7 UNKNOWN
-               }
+       Macro.pcm_split.SplitPCMDevice {
+               Name "18i20_adat_in"
+               Direction Capture
+               HWChannels "${var:DirectCaptureChannels}"
+               Channels 8
+               Channel0 "${var:AdatInCh0}"
+               Channel1 "${var:AdatInCh1}"
+               Channel2 "${var:AdatInCh2}"
+               Channel3 "${var:AdatInCh3}"
+               Channel4 "${var:AdatInCh4}"
+               Channel5 "${var:AdatInCh5}"
+               Channel6 "${var:AdatInCh6}"
+               Channel7 "${var:AdatInCh7}"
+               ChannelPos0 UNKNOWN
+               ChannelPos1 UNKNOWN
+               ChannelPos2 UNKNOWN
+               ChannelPos3 UNKNOWN
+               ChannelPos4 UNKNOWN
+               ChannelPos5 UNKNOWN
+               ChannelPos6 UNKNOWN
+               ChannelPos7 UNKNOWN
        }
 }
index 73429495e8cfd4bd105a156556fd2c8c1bcd685a..fdc866051bedbd0b1141c00c1a3dc86891fc1ef6 100644 (file)
@@ -59,6 +59,21 @@ Define.Generation "1st"
 Define.DirectPlaybackChannels 20
 Define.DirectCaptureChannels 20  # fallback; overridden per generation
 
+# Digital (S/PDIF + ADAT) capture-input channel indices.
+# Default = 20-channel (3rd/4th gen) layout. The 18-channel 1st/2nd gen
+# capture stream omits the two extra channels at 8-9, so its S/PDIF and
+# ADAT inputs sit two channels lower (overridden in the gen1/gen2 blocks).
+Define.SpdifInCh0 10
+Define.SpdifInCh1 11
+Define.AdatInCh0 12
+Define.AdatInCh1 13
+Define.AdatInCh2 14
+Define.AdatInCh3 15
+Define.AdatInCh4 16
+Define.AdatInCh5 17
+Define.AdatInCh6 18
+Define.AdatInCh7 19
+
 If.gen1 {
        Condition {
                Type RegexMatch
@@ -67,6 +82,17 @@ If.gen1 {
        }
        True.Define {
                DirectCaptureChannels 18
+               # 18-ch capture: S/PDIF in = 8,9 ; ADAT in = 10..17
+               SpdifInCh0 8
+               SpdifInCh1 9
+               AdatInCh0 10
+               AdatInCh1 11
+               AdatInCh2 12
+               AdatInCh3 13
+               AdatInCh4 14
+               AdatInCh5 15
+               AdatInCh6 16
+               AdatInCh7 17
        }
 }
 
@@ -79,6 +105,17 @@ If.gen2 {
        True.Define {
                Generation "2nd"
                DirectCaptureChannels 18
+               # 18-ch capture: S/PDIF in = 8,9 ; ADAT in = 10..17
+               SpdifInCh0 8
+               SpdifInCh1 9
+               AdatInCh0 10
+               AdatInCh1 11
+               AdatInCh2 12
+               AdatInCh3 13
+               AdatInCh4 14
+               AdatInCh5 15
+               AdatInCh6 16
+               AdatInCh7 17
        }
 }