我给自己买了一台华为 Matebook 14s 笔记本电脑并在上面安装了 Ubuntu 22.04。这台笔记本电脑有两对扬声器。问题在于系统将第一个定义为扬声器,第二个定义为耳机。我如何让他们一起工作?也许我需要安装额外的驱动程序或类似的东西,例如英特尔的声卡。
我尝试重新启动 PulseAudio,但没有帮助。
答案1
我遇到了类似的问题,根据我找到的资料,我写了一个守护进程来解决它。您可以在我的 GitHub 存储库中获取它:https://github.com/Smoren/huawei-ubuntu-sound-fix。
问题
Linux 发行版的声卡驱动程序中耳机和扬声器通道是混合的。
连接耳机时,系统认为声音应从扬声器输出。当耳机关闭时,系统会尝试通过耳机输出声音。
问题详情(发现这里)
看起来有一些奇怪的硬件设计,因为从我的角度来看,有趣的小部件是:
- 0x01 - 音频功能组
- 0x10 - 耳机 DAC(实际上两个设备都连接在这里)
- 0x11 - 扬声器 DAC
- 0x16 - 耳机插孔
- 0x17 - 内置扬声器
和:
- 小部件 0x16 和 0x17 应该连接到不同的 DAC 0x10 和 0x11,但内部扬声器 0x17 会忽略连接选择命令并使用耳机插孔 0x16 中的值。
- 耳机插孔 0x16 由一些奇怪的东西控制,因此应该使用音频组 0x01 的 GPIO 命令启用它。
- 内部扬声器 0x17 与耳机插孔 0x16 耦合,因此应使用 EAPD/BTL Enable 命令明确禁用它。
解决方案
已实现一个守护进程,用于监视耳机的连接/断开并访问声卡设备,以便将播放切换到正确的位置。
华为-声卡-耳机-monitor.sh
#!/bin/bash
# ensures script can run only once at a time
pidof -o %PPID -x $0 >/dev/null && echo "Script $0 already running" && exit 1
function move_output() {
hda-verb /dev/snd/hwC0D0 0x16 0x701 "$@" > /dev/null 2> /dev/null
}
function move_output_to_speaker() {
move_output 0x0001
}
function move_output_to_headphones() {
move_output 0x0000
}
function switch_to_speaker() {
move_output_to_speaker
# enable speaker
hda-verb /dev/snd/hwC0D0 0x17 0x70C 0x0002 > /dev/null 2> /dev/null
# disable headphones
hda-verb /dev/snd/hwC0D0 0x1 0x715 0x2 > /dev/null 2> /dev/null
}
function switch_to_headphones() {
move_output_to_headphones
# disable speaker
hda-verb /dev/snd/hwC0D0 0x17 0x70C 0x0000 > /dev/null 2> /dev/null
# pin output mode
hda-verb /dev/snd/hwC0D0 0x1 0x717 0x2 > /dev/null 2> /dev/null
# pin enable
hda-verb /dev/snd/hwC0D0 0x1 0x716 0x2 > /dev/null 2> /dev/null
# clear pin value
hda-verb /dev/snd/hwC0D0 0x1 0x715 0x0 > /dev/null 2> /dev/null
# sets amixer sink port to headphones instead of the speaker
pacmd set-sink-port alsa_output.pci-0000_00_1f.3-platform-skl_hda_dsp_generic.HiFi__hw_sofhdadsp__sink "[Out] Headphones"
}
function get_sound_card_index() {
card_index=$(cat /proc/asound/cards | grep sof-hda-dsp | head -n1 | grep -Eo "^\s*[0-9]+")
# remove leading white spaces
card_index="${card_index#"${card_index%%[![:space:]]*}"}"
echo $card_index
}
sleep 2 # allows audio system to initialise first
card_index=$(get_sound_card_index)
if [ $card_index == "" ]; then
echo "sof-dha-dsp card is not found in /proc/asound/cards"
return 1
fi
old_status=0
while true; do
# if headphone jack isn't plugged:
if amixer "-c${card_index}" get Headphone | grep -q "off"; then
status=1
move_output_to_speaker
# if headphone jack is plugged:
else
status=2
move_output_to_headphones
fi
if [ ${status} -ne ${old_status} ]; then
case "${status}" in
1)
message="Headphones disconnected"
switch_to_speaker
;;
2)
message="Headphones connected"
switch_to_headphones
;;
esac
echo "${message}"
old_status=$status
fi
sleep .3
done
华为-声卡-耳机-monitor.service
[Unit]
Description=Huawei soundcard headphones monitor
[Service]
ExecStart=/usr/local/bin/huawei-soundcard-headphones-monitor.sh
Restart=always
User=root
[Install]
WantedBy=multi-user.target