diff --git a/tools/kernel/babyfacepro-ctl.c b/tools/kernel/babyfacepro-ctl.c index 7c517ab..3a25f4b 100644 --- a/tools/kernel/babyfacepro-ctl.c +++ b/tools/kernel/babyfacepro-ctl.c @@ -43,20 +43,17 @@ const struct bf_source bf_sources[14] = { { "PB6", 22, 23 }, }; -/* Crosspoint-map output order vs the master-map order - HARDWARE- - * VERIFIED 2026-08-24: the block that feeds the Phones is the FIRST - * crosspoint block (0x34), while the Phones master is the SECOND - * (0x03E2/0x0006). The crosspoint map lists the Phones first (the - * monitor output); the master map lists AN1/2 first. Control index = - * the canonical order (AN1/2=0, PH3/4=1, ...) so the crosspoint and - * master controls line up; this table maps to the register block. +/* Output blocks follow the master/loopback order. Verified on the + * local Babyface Pro using isolated register writes and all 12 loopback + * channels: AN1/2=0x000, PH3/4=0x034, AS1/2=0x068, then 0x09c, + * 0x0d0 and 0x104. No duplicate AN1/2 write into the AS1/2 bus. */ -const u8 bf_xpoint_block[6] = { 1, 0, 2, 3, 4, 5 }; +const u8 bf_xpoint_block[6] = { 0, 1, 2, 3, 4, 5 }; /* Master-register output order - the master map lists AN1/2 first * (0x03E0) and the Phones master SECOND (0x03E2, HARDWARE-VERIFIED - * 2026-08-24); the crosspoint blocks are in the opposite order - * (Phones = block 0x34 first, hence bf_xpoint_block above). Control + * 2026-08-24); the crosspoint blocks follow the same order + * (AN1/2 = block 0, Phones = block 0x34). Control * index -> canonical output (AN1/2=0, PH3/4=1, ...) = the master * register position directly: the names 'AN1/2 Playback Volume' etc. * must match the register they write (corrected 2026-08-26 - the @@ -182,9 +179,8 @@ int babyface_write_default_mixer(struct snd_usb_babyface *chip) } /* Every playback source into every output pair, L and R, at 0 dB, - * and the hardware inputs off (the standard map, plus the low map - * on AN1/2 - see bf_xpoint_write's own comment for why AN1/2 needs - * both). The addresses use the source's idx_l/idx_r on the + * and the hardware inputs off. The output block is selected by + * bf_xpoint_block. The addresses use the source's idx_l/idx_r on the * canonical block - writing the raw index on both bases would put * PB1 R on the L side and PB1 L on the R side (L+R on both = mono). * The "cross" registers (L-reg idx_r / R-reg idx_l) are cleared. @@ -466,27 +462,7 @@ int bf_preamp_state_write(struct snd_usb_babyface *chip) */ static const DECLARE_TLV_DB_LINEAR(bf_xpoint_tlv, TLV_DB_GAIN_MUTE, 600); -/* Write a crosspoint slot on the wire: the standard map always, and - - * for the AN1/2 output only - the low map as well. - * - * HARDWARE-VERIFIED 2026-09-14: AN1/2 is not just another output with - * a redundant "shadow" register, despite what this file used to say. - * Sweeping only the standard map (BF_REG_CROSS_BASE_*) into AN1/2 - * produced no audible change at all, off through +6 dB, with two - * independent sources (a generated tone via PB1, a live mic via AN2); - * the exact same code path targeting any other output (verified on - * PH3/4) tracked the fader correctly, off to +6 dB within 0.6 dB. - * PROTOCOL.md's "Scene load" capture explains why: the vendor software - * always writes BOTH the standard map and the low map - * (BF_REG_LOWMAP_BASE_*) together for AN1/2's own crosspoints, at the - * same value - the low map is what actually feeds that output's sum; - * the standard map alone is not enough. Every other output only has a - * standard map. - * - * bf_split_apply() already knew this (it writes both for AN1/2's - * playback pairs); this generalises the same pattern to the plain - * fader. - */ +/* Write exactly one output bus. AN1/2 is the first regular block. */ int bf_xpoint_write(struct snd_usb_babyface *chip, int out, int src, u16 l, u16 r) { @@ -495,17 +471,6 @@ int bf_xpoint_write(struct snd_usb_babyface *chip, int out, int src, u16 flag; int ret; - if (out == 0) { - ret = bf_vendor_write(chip, BF_REQ_CROSSPOINT, l, - BF_REG_LOWMAP_BASE_L + s->idx_l); - if (ret < 0) - return ret; - ret = bf_vendor_write(chip, BF_REQ_CROSSPOINT, r, - BF_REG_LOWMAP_BASE_R + s->idx_r); - if (ret < 0) - return ret; - } - flag = bf_flag_cycle[chip->flag_cnt]; chip->flag_cnt = (chip->flag_cnt + 1) & 3; ret = bf_vendor_write(chip, BF_REQ_CROSSPOINT, l, diff --git a/tools/kernel/babyfacepro.h b/tools/kernel/babyfacepro.h index ab9f659..7c05c0c 100644 --- a/tools/kernel/babyfacepro.h +++ b/tools/kernel/babyfacepro.h @@ -133,20 +133,11 @@ #define BF_REG_MASTER_16 0x03e0 /* + 2*out (bReq 0x12) */ #define BF_REG_MASTER_8 0x0004 /* + 2*out (bReq 0x1a) */ #define BF_REG_GAIN 0x0000 /* + mic 0-3 (bReq 0x1a) */ -#define BF_REG_CROSS_BASE_L 0x0034 /* + 0x34*out + src (bReq 0x12) */ -#define BF_REG_CROSS_BASE_R 0x004e /* + 0x34*out + src */ +#define BF_REG_CROSS_BASE_L 0x0000 /* + 0x34*out + src (bReq 0x12) */ +#define BF_REG_CROSS_BASE_R 0x001a /* + 0x34*out + src */ #define BF_REG_CROSS_STRIDE 0x0034 -/* Low map (the AN1/2 monitor bus's own per-source registers, one set - * shared across every output - not one per output block like the - * standard crosspoint map above). NOT a shadow/mirror of the standard - * map for AN1/2: it is what that output actually sums from, and the - * standard map alone has no audible effect on it (hardware-verified - * 2026-09-14, see bf_xpoint_write's own comment and KERNEL-DRIVER.md). - * Used by bf_ms_put/width's own hardcoded addresses, by bf_split_apply/ - * bf_phase_apply/bf_trim_apply for their own AN1/2-only features, and - * by bf_xpoint_write for the general crosspoint fader. PROTOCOL.md / - * tuxmix-usb's `map::low_map_l`/`low_map_r` (hardware-verified) use - * the identical BASE + idx shape. +/* AN1/2 is output block zero. These aliases are retained for the + * AN1/2-only phase/width/trim controls; they are not a second bus. */ #define BF_REG_LOWMAP_BASE_L 0x0000 /* + idx_l */ #define BF_REG_LOWMAP_BASE_R 0x001a /* + idx_r */ diff --git a/tools/kernel/dkms.conf b/tools/kernel/dkms.conf index d93bd32..603d813 100644 --- a/tools/kernel/dkms.conf +++ b/tools/kernel/dkms.conf @@ -6,7 +6,7 @@ # path this wraps. PACKAGE_NAME="snd-usb-babyface-pro" -PACKAGE_VERSION="0.2.0" +PACKAGE_VERSION="0.2.0.local1" BUILT_MODULE_NAME[0]="snd-usb-babyface-pro" DEST_MODULE_LOCATION[0]="/kernel/sound/usb"