FreeBSD 多媒体

FreeBSD提供了广泛的多媒体硬件和软件支持,需要设置声卡驱动以及调整音量

设置声卡

当不知道系统使用了什么声卡或模块,则通过以下命令加载 snd_driver 元数据驱动:

加载 snd_driver 驱动
kldload snd_driver

为了在启动时加载上述模块,则配置 /boot/loader.conf :

启动时加载 snd_driver 驱动
snd_driver_load="YES"
  • 检查dmesg确定声卡已经被检测到:

dmesg检查pcm
dmesg | grep pcm

输出类似:

dmesg检查pcm
pcm0: <Conexant CX20590 (Analog 2.0+HP/2.0)> at nid 31,25 and 35,27 on hdaa0
pcm1: <Intel Cougar Point (HDMI/DP 8ch)> at nid 5 on hdaa1
...
  • 检查声卡状态:

检查声卡状态
cat /dev/sndstat

输出类似

检查声卡状态
Installed devices:
pcm0: <Conexant CX20590 (Analog 2.0+HP/2.0)> (play/rec) default
pcm1: <Intel Cougar Point (HDMI/DP 8ch)> (play)
pcm2: <Intel Cougar Point (HDMI/DP 8ch)> (play)
pcm3: <Intel Cougar Point (HDMI/DP 8ch)> (play)
No devices installed from userspace.

通过 beep 命令可以发出一些声音来确认声卡是否工作

Mixer

FreeBSD 提供了一些工具来设置声卡音量:

  • mixer 默认安装的命令行工具(我没有研究实践)

  • mixertui 字符终端的交互界面工具,非常类似 Arch Linux ALSA声音系统 中使用的 alsamixer

软件安装

在FreeBSD中,现在似乎使用 PipeWire 来替代传统的 ALSA,我没有详细研究。不过,系统默认就安装了 pipewirewireplumber (一种管理PipeWire的会话和策略管理器)。

备注

实际上我在 ThinkPad X220 上使用 mixertui 可以非常方便调整音量。

笔记本喇叭无声问题排查

备注

本段排查过程在Google Gemini指导下完成

虽然在X220上FreeBSD非常容易使用声卡硬件,但是我发现只有耳机能够听到声音,而外放的喇叭是没有声音的,即使我通过 mixertuispeaker 音量设置到最大也没有效果。

Gemini提示: 音频输出的 "引脚映射" (Pin Mapping) 或 "自动静音" (Auto-mute) 逻辑在ThinkPad X220上没有正确识别。在FreeBSD中,ThinkPad这种"耳机响,喇叭不响"通常是因为内核认为耳机始终插着,或者没有正确切换到喇叭引脚。

  • 检查 cat /dev/sndstat 输出如下:

检查声卡状态
Installed devices:
pcm0: <Conexant CX20590 (Analog 2.0+HP/2.0)> (play/rec) default
pcm1: <Intel Cougar Point (HDMI/DP 8ch)> (play)
pcm2: <Intel Cougar Point (HDMI/DP 8ch)> (play)
pcm3: <Intel Cougar Point (HDMI/DP 8ch)> (play)
No devices installed from userspace.

ThinkPad X220使用了 Conexant CX20590 芯片,这里显示的 pcm0 行中 Anolog 2.0 指的是内置扬声器(Speaker),而 HP 指的是 Headphone (耳机)。由于共享同一个编解码芯片(Conexant CX20590),所以驱动程序默认将它们视为"模拟输出"。

解决FreeBSD下ThinkPad喇叭的标准方法是手动告诉内核如何定义引脚(Pin)

  • 检查默认音频设备的默认配置:

检查默认配置
sysctl -a | grep "_original"

输出显示

检查默认配置
...
dev.hdaa.0.nid31_original: 0x90170110 as=1 seq=0 device=Speaker conn=Fixed ctype=Analog loc=Internal color=Unknown misc=1 
...
dev.hdaa.0.nid28_original: 0x6121401f as=1 seq=15 device=Headphones conn=None ctype=1/8 loc=Ext-Rear color=Green misc=0
...
dev.hdaa.0.nid25_original: 0x04211040 as=4 seq=0 device=Headphones conn=Jack ctype=1/8 loc=Right color=Black misc=0

导致喇叭不响的原因:

  • Speaker (喇叭) 在 nid31,它的关联组是 as=1。

  • Headphones (耳机) 在 nid25,它的关联组是 as=4。

喇叭和耳机不在同一个 as (Association) 组。在 FreeBSD 的 HDA 驱动逻辑中,只有当它们在同一个组时,驱动才能正确处理“插入耳机自动静音喇叭,拔掉耳机自动开启喇叭”的逻辑。目前由于它们相互独立,系统可能默认关闭了 as=1 的放大器。

  • 有可能是喇叭被系统级静音,需要检查和修改特定的寄存器。执行以下命令查看所有音频相关的 sysctl 变量:

检查音频相关的 sysctl 变量
# 查看所有音频相关的 sysctl 变量,这里 hdaa.0 对应 pcm0 设备
sysctl dev.hdaa.0

输出:

检查音频相关的 sysctl 变量
...
dev.hdaa.0.nid31_original: 0x90170110 as=1 seq=0 device=Speaker conn=Fixed ctype=Analog loc=Internal color=Unknown misc=1
dev.hdaa.0.nid31_config: 0x90170110 as=1 seq=0 device=Speaker conn=Fixed ctype=Analog loc=Internal color=Unknown misc=1
dev.hdaa.0.nid31: pin: Speaker (Fixed)
     Widget cap: 0x00400501 PWR STEREO
    Association: 0 (0x0001)
        Pin cap: 0x00000010 OUT
     Pin config: 0x90170110 as=1 seq=0 device=Speaker conn=Fixed ctype=Analog loc=Internal color=Unknown misc=1
    Pin control: 0x00000040 OUT
    Connections: 2
          + <- nid=16 [audio output] (selected)
          + [DISABLED] <- nid=17 [audio output] [DISABLED]
...
dev.hdaa.0.nid17: audio output [DISABLED]
     Widget cap: 0x00000c1d LRSWAP PWR STEREO
     Stream cap: 0x00000001 PCM
        PCM cap: 0x000e0560 16 20 24 bits, 44 48 96 192 KHz
     Output amp: 0x80034a4a mute=1 step=74 size=3 offset=74 (-74/+0dB)

dev.hdaa.0.nid16: audio output
     Widget cap: 0x00000c1d LRSWAP PWR STEREO
    Association: 0 (0x8001)
            OSS: pcm (pcm)
     Stream cap: 0x00000001 PCM
        PCM cap: 0x000e0560 16 20 24 bits, 44 48 96 192 KHz
     Output amp: 0x80034a4a mute=1 step=74 size=3 offset=74 (-74/+0dB)
...

可以看到 speaker 对应的是 nid31 ,其中关联的是 nid17 ( disabled ) 和 nid16 都设置了 mute=1 表示静音

在 X220 上,喇叭通常对应 nid 31,耳机对应 nid 25。如果它们没能自动切换,我们需要强制将它们分配到同一个“关联组(Association)”

  • 编辑 /boot/devices.hints :

配置喇叭和耳机自动切换
# 将喇叭设为主要输出 (as=1, seq=0)
hint.hdaa.0.nid31.config="as=1 seq=0 device=Speaker"
# 将耳机设为备用输出,并开启插拔感知 (as=1, seq=15)
hint.hdaa.0.nid25.config="as=1 seq=15 device=Headphones"

警告

没有解决,暂时不折腾了

参考