关于高清音频驱动的更多说明¶
Takashi Iwai <tiwai@suse.de>
概述¶
高清音频是继 AC97 之后现代 PC 上的新型板载音频组件。尽管 Linux 很早就开始支持高清音频,但新机器经常会出现问题。一部分问题是 BIOS 损坏,其余是驱动程序实现。本文档解释了高清音频硬件的简要故障排除和调试方法。
高清音频组件由两部分组成:高清音频总线上的控制器芯片和编解码器芯片。 Linux 为所有控制器提供一个驱动程序 snd-hda-intel。 尽管驱动程序名称包含一个知名硬件供应商的词,但它并非特定于该供应商,而是适用于其他公司的所有控制器芯片。 由于高清音频控制器应该兼容,因此单个 snd-hda-driver 在大多数情况下应该可以工作。 但是,不出所料,存在一些特定于每个控制器类型的已知错误和问题。 snd-hda-intel 驱动程序针对这些问题进行了一些解决方法,如下所述。
一个控制器可能具有多个编解码器。 通常,您有一个音频编解码器,还可以选择一个调制解调器编解码器。 理论上,可能存在多个音频编解码器,例如用于模拟和数字输出,并且由于混音器元素的冲突,驱动程序可能无法正常工作。 如果真的存在这样的硬件,则应在将来修复此问题。
snd-hda-intel 驱动程序具有多个不同的编解码器解析器,具体取决于编解码器。 它具有一个通用解析器作为后备,但是到目前为止,此功能相当有限。 通常,不使用通用解析器,而是使用编解码器特定的解析器 (在 patch_*.c 中编码) 来实现编解码器特定的实现。 有关编解码器特定问题的详细信息将在后面的章节中进行说明。
如果您对高清音频的深入调试感兴趣,请首先阅读高清音频规范。 该规范可在英特尔的网页上找到,例如
高清音频控制器¶
DMA 位置问题¶
控制器最常见的问题是 DMA 指针报告不准确。 可以通过两种方式读取播放和捕获的 DMA 指针:通过 LPIB 寄存器或通过位置缓冲区映射。 默认情况下,驱动程序尝试从 I/O 映射的位置缓冲区读取,如果位置缓冲区出现故障,则回退到 LPIB。 但是,此检测在某些设备上并不完美。 在这种情况下,您可以通过 position_fix
选项更改默认方法。
position_fix=1
表示显式使用 LPIB 方法。 position_fix=2
表示使用位置缓冲区。 position_fix=3
表示使用两种方法的组合,某些 VIA 控制器需要此方法。 通过比较 LPIB 和位置缓冲区的值来校正捕获流位置。 position_fix=4
是可用于所有控制器的另一种组合,它对播放使用 LPIB,对捕获流使用位置缓冲区。 position_fix=5
是特定于英特尔平台的,到目前为止,适用于 Skylake 及更高版本。 它应用延迟计算以进行精确的位置报告。 position_fix=6
是使用固定的 FIFO 大小来校正位置,主要针对最近的 AMD 控制器。 0 是所有其他控制器的默认值,如上所述,自动检查和回退到 LPIB。 如果您遇到重复的声音问题,则此选项可能会有所帮助。
除此之外,已知每个控制器在唤醒时序方面都存在问题。 它会在实际处理缓冲区上的数据之前几个采样唤醒。 这导致了很多问题,例如,ALSA dmix 或 JACK。 从 2.6.27 内核开始,驱动程序会在唤醒时序中添加人为延迟。 此延迟通过 bdl_pos_adj
选项控制。
当 bdl_pos_adj
为负值时 (默认情况下),会根据控制器芯片为其分配一个适当的值。 对于英特尔芯片,它将为 1,而对于其他芯片,它将为 32。 通常,这会起作用。 仅在它不起作用并且您收到警告消息的情况下,才应将此参数更改为其他值。
编解码器探测问题¶
一个不常见但更严重的问题是编解码器探测。 当 BIOS 错误地报告可用的编解码器插槽时,驱动程序会感到困惑,并尝试访问不存在的编解码器插槽。 这通常会导致彻底的混乱,并破坏与编解码器芯片的进一步通信。 症状通常表现为以下错误消息:
hda_intel: azx_get_response timeout, switching to polling mode:
last cmd=0x12345678
hda_intel: azx_get_response timeout, switching to single_cmd mode:
last cmd=0x12345678
第一行是警告,通常相对无害。 这表示未通过 IRQ 通知编解码器响应。 驱动程序使用显式轮询方法读取响应。 它会带来非常轻微的 CPU 开销,但是您不太可能注意到它。
但是,第二行是致命错误。 如果发生这种情况,通常意味着出现了严重问题。 最有可能是您正在访问不存在的编解码器插槽。
因此,如果出现第二个错误消息,请尝试通过 probe_mask
选项缩小探测的编解码器插槽。 这是一个位掩码,每一位对应一个编解码器插槽。 例如,要仅探测第一个插槽,请传递 probe_mask=1
。 对于第一个和第三个插槽,请传递 probe_mask=5
(其中 5 = 1 | 4),依此类推。
从 2.6.29 内核开始,驱动程序具有更强大的探测方法,因此这种情况可能很少发生。
在 BIOS 损坏的机器上,有时您需要强制驱动程序探测硬件未报告使用的编解码器插槽。 在这种情况下,打开 probe_mask
选项的第 8 位 (0x100)。 然后,其余 8 位作为要无条件探测的编解码器插槽传递。 例如,probe_mask=0x103
将强制探测编解码器插槽 0 和 1,无论硬件报告什么。
中断处理¶
从 2.6.33 内核开始,高清音频驱动程序默认使用 MSI (如果可用),因为 MSI 在某些机器上效果更好,并且通常来说,它对于性能更好。 但是,Nvidia 控制器在 MSI 下显示出不良的回归 (尤其是在与 AMD 芯片组结合使用时),因此我们禁用了它们的 MSI。
似乎还有其他一些设备无法与 MSI 一起使用。 如果您发现声音质量 (卡顿等) 或最近内核中的锁死方面出现回归,请尝试传递 enable_msi=0
选项以禁用 MSI。 如果有效,则可以将已知的错误设备添加到 hda_intel.c 中定义的黑名单中。 在这种情况下,请报告并将补丁返回给上游开发人员。
高清音频编解码器¶
模型选项¶
关于高清音频驱动程序的最常见问题是编解码器功能不受支持或设备配置不匹配。 大多数编解码器特定代码都有多个预设模型,可以覆盖 BIOS 设置或提供更全面的功能。
驱动程序检查 PCI SSID,并搜索静态配置表,直到找到任何匹配的条目。 如果您有一台新机器,您可能会看到如下消息:
hda_codec: ALC880: BIOS auto-probing.
同时,在早期版本中,您会看到如下消息:
hda_codec: Unknown model for ALC880, trying auto-probe from BIOS...
即使您看到这样的消息,也不要惊慌。 深呼吸并保持冷静。 首先,这是一个信息性消息,没有警告,没有错误。 这表示您的设备的 PCI SSID 未列在已知的预设模型 (白) 列表中。 但是,这并不表示驱动程序已损坏。 许多编解码器驱动程序都提供了基于 BIOS 设置的自动配置机制。
高清音频编解码器通常具有“引脚”小部件,并且 BIOS 设置每个引脚的默认配置,该配置指示位置、连接类型、插孔颜色等。 高清音频驱动程序可以根据这些默认配置值猜测正确的连接。 但是 — 某些编解码器支持代码,例如 patch_analog.c,不支持自动探测 (截至 2.6.28)。 而且,BIOS 通常,是的,非常经常损坏。 它设置错误的值并破坏驱动程序。
预设模型 (或最近称为“修复”) 基本上是为了克服这种情况而提供的。 当在白名单中找到匹配的预设模型时,驱动程序会假定该预设的静态配置具有正确的引脚设置等。 因此,如果您拥有一台 PCI SSID (或编解码器 SSID) 与现有设备略有不同的较新机器,则您很可能可以重复使用相同的模型。 您可以传递 model
选项以指定预设模型,而不是 PCI (和编解码器) SSID 查找。
可用的 model
选项值取决于编解码器芯片。 从编解码器 proc 文件中检查您的编解码器芯片 (请参见下面的“编解码器 Proc 文件”部分)。 它将显示您的编解码器芯片的供应商/产品名称。 然后,请参阅高清音频编解码器特定模型文件,高清音频驱动程序部分。 您可以找到一个编解码器列表和属于每个编解码器的 model
选项。 例如,对于 Realtek ALC262 编解码器芯片,对于与 Samsung Q1 Ultra 兼容的设备,请传递 model=ultra
。
因此,您可以为任何全新的、不受支持的且无法正常工作的高清音频硬件做的第一件事是检查高清音频编解码器和几个不同的 model
选项值。 如果您有任何运气,其中一些可能很适合您的设备。
有一些特殊的模型选项值:
当传递“nofixup”时,编解码器解析器中的设备特定修复程序将被跳过。
当传递
generic
时,编解码器特定的解析器将被跳过,并且仅使用通用解析器。
自 5.15 内核版本引入了一种新的模型选项风格,即以 model=XXXX:YYYY
的形式传递 PCI 或编解码器 SSID,其中 XXXX 和 YYYY 分别是十六进制的子厂商 ID 和子设备 ID。这是一种指向另一个设备的别名;当给出这种形式时,驱动程序会将该 SSID 作为查询表的参考。当目标怪癖未在模型表中列出时,此方法尤其有用。例如,传递 model=103c:8862 将应用 HP ProBook 445 G8 的怪癖(截至撰写本文时,该怪癖未在模型表中找到),只要该设备由同一驱动程序以相同方式处理即可。
扬声器和耳机输出¶
HD-audio 最常见(且明显)的错误之一是内置扬声器和/或耳机插孔静音输出。一般来说,您应该首先尝试耳机输出。扬声器输出通常需要更多的附加控制,例如外部放大器位。因此,耳机输出的成功几率略高。
在提交错误报告之前,请仔细检查混音器是否设置正确。最新版本的 snd-hda-intel 驱动程序主要提供“Master”音量控制以及“Front”音量(其中 Front 表示前置声道)。此外,可能还有单独的“Headphone”和“Speaker”控制。
扬声器输出也一样。某些编解码器上可能存在“External Amplifier”开关。如果有,请打开此开关。
另一个相关问题是插入耳机时自动使扬声器输出静音。此功能在大多数情况下都已实现,但并非在每个预设型号或编解码器支持代码上都实现。
无论如何,如果遇到此类问题,请尝试不同的模型选项。某些其他模型可能更匹配,并为您提供更多匹配的功能。如果没有任何可用的模型起作用,请发送错误报告。有关详细信息,请参见错误报告部分。
如果您有足够的受虐倾向来调试驱动程序问题,请注意以下事项
扬声器(以及耳机)输出通常需要外部放大器。这通常可以通过 EAPD 动词或某个 GPIO 进行设置。如果编解码器引脚支持 EAPD,则您更有可能通过 SET_EAPD_BTL 动词 (0x70c) 来实现。在其他情况下,GPIO 引脚(通常是 GPIO0 或 GPIO1)可能会打开/关闭 EAPD。
某些 Realtek 编解码器需要特定的供应商系数才能打开放大器。请参见 patch_realtek.c。
IDT 编解码器可能在每个模拟引脚上都有额外的电源启用/禁用控制。请参见 patch_sigmatel.c。
非常罕见但有些设备在触发之前不接受引脚检测动词。发出 GET_PIN_SENSE 动词 (0xf09) 可能会导致编解码器通信停滞。在 patch_realtek.c 中找到了一些示例。
捕获问题¶
捕获问题通常是由于混音器设置缺失造成的。因此,在提交错误报告之前,请确保正确设置了混音器。例如,除了正确的“Capture Source”或“Input Source”选择之外,还必须正确设置“Capture Volume”和“Capture Switch”。某些设备具有“Mic Boost”音量或开关。
当通过“default”PCM(不带 pulse-audio 插件)打开 PCM 设备时,您很可能也会有“Digital Capture Volume”控制。这是为软件中信号的额外增益/衰减提供的,特别是对于没有硬件音量控制的输入(例如数字麦克风)。除非确实需要,否则应将其设置为正好 50%,对应于 0dB —— 既没有额外的增益也没有衰减。当您使用“hw”PCM 时,即原始访问 PCM,此控制将不起作用。
已知某些编解码器/设备具有相当差的模拟电路,并且录制的声音包含一定的直流偏移。这不是驱动程序的错误。
大多数现代笔记本电脑没有模拟 CD 输入连接。因此,即使驱动程序将其作为捕获源提供,从 CD 输入进行录音在许多情况下也无法工作。请改用 CDDA。
在某些编解码器型号上实现了插入时自动切换内置和外部麦克风,但并非在每个型号上都实现。部分原因是我的懒惰,但主要是缺乏测试人员。欢迎向作者提交改进补丁。
直接调试¶
如果没有模型选项能为您带来更好的结果,并且您是一位与邪恶作斗争的硬汉,请尝试通过向设备发送原始 HD-audio 编解码器动词进行调试。有一些工具可用:hda-emu 和 hda-analyzer。详细说明请参见以下各节。您需要启用 hwdep 才能使用这些工具。请参见“内核配置”部分。
其他问题¶
内核配置¶
一般来说,我建议您启用声音调试选项,CONFIG_SND_DEBUG=y
,无论您是否在调试。
不要忘记打开相应的 CONFIG_SND_HDA_CODEC_*
选项。请注意,每个选项都对应于编解码器芯片,而不是控制器芯片。因此,即使 lspci 显示 Nvidia 控制器,您也可能需要为其他供应商选择选项。如果您不确定,只需全部选择是。
CONFIG_SND_HDA_HWDEP
是一个用于调试驱动程序的有用选项。启用此选项后,驱动程序将创建硬件相关设备(每个编解码器一个),并且您可以通过这些设备文件对设备进行原始访问。例如,将为第一张卡 (#0) 的编解码器插槽 #2 创建 hwC0D2
。对于 hda-verb 和 hda-analyzer 等调试工具,必须启用 hwdep 设备。因此,最好始终将其打开。
CONFIG_SND_HDA_RECONFIG
是一个新选项,它取决于上述 hwdep 选项。启用后,您将在相应的 hwdep 目录下看到一些 sysfs 文件。请参见下面的“HD-audio 重新配置”部分。
CONFIG_SND_HDA_POWER_SAVE
选项启用省电功能。请参见下面的“省电”部分。
编解码器 Proc 文件¶
编解码器 proc 文件是调试 HD-audio 的宝库。它显示了每个编解码器小部件的大部分有用信息。
proc 文件位于 /proc/asound/card*/codec#* 中,每个编解码器插槽一个文件。您可以了解编解码器的供应商、产品 ID 和名称、每个小部件的类型、功能等等。但是,到目前为止,此文件不显示插孔感应状态。这是因为插孔感应可能取决于触发状态。
此文件将被调试工具拾取,也可以作为主要编解码器信息提供给模拟器。请参见下面的调试工具部分。
此 proc 文件还可用于检查是否使用了通用解析器。当使用通用解析器时,供应商/产品 ID 名称将显示为“Realtek ID 0262”,而不是“Realtek ALC262”。
HD-Audio 重新配置¶
这是一项实验性功能,允许您在不重新加载驱动程序的情况下动态重新配置 HD-audio 编解码器。以下 sysfs 文件在每个编解码器-hwdep 设备目录(例如 /sys/class/sound/hwC0D0)下可用
- vendor_id
显示 32 位编解码器供应商 ID 十六进制数。您可以通过写入此文件来更改 vendor-id 值。
- subsystem_id
显示 32 位编解码器子系统 ID 十六进制数。您可以通过写入此文件来更改 subsystem-id 值。
- revision_id
显示 32 位编解码器修订 ID 十六进制数。您可以通过写入此文件来更改 revision-id 值。
- afg
显示 AFG ID。这是只读的。
- mfg
显示 MFG ID。这是只读的。
- name
显示编解码器名称字符串。可以通过写入此文件来更改。
- modelname
显示当前设置的
model
选项。可以通过写入此文件来更改。- init_verbs
在初始化时执行的额外动词。您可以通过写入此文件来添加动词。传递三个数字:nid、verb 和 parameter(用空格分隔)。
- hints
显示/存储供编解码器解析器使用的提示字符串。其格式为
key = value
。例如,传递jack_detect = no
将完全禁用机器的插孔检测。- init_pin_configs
显示 BIOS 设置的初始引脚默认配置值。
- driver_pin_configs
显示编解码器解析器显式设置的引脚默认值。这不会显示所有引脚值,而只会显示解析器更改的值。也就是说,如果解析器本身不更改引脚默认配置值,则此项将不包含任何内容。
- user_pin_configs
显示覆盖 BIOS 设置的引脚默认配置值。写入此内容(使用两个数字,NID 和值)将附加新值。在下次重新配置时,将使用给定的值代替初始 BIOS 值。请注意,此配置甚至会覆盖驱动程序引脚配置。
- reconfig
触发编解码器重新配置。当向此文件写入任何值时,驱动程序将重新初始化并再次解析编解码器树。将考虑上述 sysfs 条目所做的所有更改。
- clear
重置编解码器,删除指定编解码器的混音器元素和 PCM 内容,并清除所有初始动词和提示。
例如,当您想要将引脚小部件 0x14 的引脚默认配置值更改为 0x9993013f,并让驱动程序基于该状态重新配置时,请像下面这样运行
# echo 0x14 0x9993013f > /sys/class/sound/hwC0D0/user_pin_configs
# echo 1 > /sys/class/sound/hwC0D0/reconfig
提示字符串¶
编解码器解析器有几个开关和调整旋钮,以便更好地匹配实际的编解码器或设备行为。其中许多可以通过上面的部分中提到的“hints”字符串动态调整。例如,通过 sysfs 或补丁文件传递 jack_detect = no
字符串,您可以禁用插孔检测,因此编解码器解析器将跳过诸如自动静音或麦克风自动切换之类的功能。作为布尔值,可以传递 yes
、no
、true
、false
、1
或 0
。
通用解析器支持以下提示
- jack_detect (bool)
指定此机器上是否完全可用插孔检测;默认为 true
- inv_jack_detect (bool)
表示插孔检测逻辑反转
- trigger_sense (bool)
表示插孔检测需要显式调用 AC_VERB_SET_PIN_SENSE 动词
- inv_eapd (bool)
表示 EAPD 以反转逻辑实现
- pcm_format_first (bool)
在流标签和通道 ID 之前设置 PCM 格式
- sticky_stream (bool)
尽可能长时间地保留 PCM 格式、流标签和 ID;默认值为 true
- spdif_status_reset (bool)
每次设置 SPDIF 流时重置 SPDIF 状态位
- pin_amp_workaround (bool)
输出引脚可能具有多个放大器值
- single_adc_amp (bool)
ADC 只能具有单个输入放大器
- auto_mute (bool)
启用/禁用耳机自动静音功能;默认值为 true
- auto_mic (bool)
启用/禁用麦克风自动切换功能;默认值为 true
- line_in_auto_switch (bool)
启用/禁用线路输入自动切换功能;默认值为 false
- need_dac_fix (bool)
根据通道数限制 DAC
- primary_hp (bool)
将耳机插孔作为主输出进行探测;默认值为 true
- multi_io (bool)
尝试探测多 I/O 配置(例如,共享线路输入/环绕声、麦克风/低频效果插孔)
- multi_cap_vol (bool)
提供多个捕获音量
- inv_dmic_split (bool)
为反相数字麦克风提供分离的内部麦克风音量/开关
- indep_hp (bool)
如果可用,则提供独立的耳机 PCM 流和相应的混音器控制
- add_stereo_mix_input (bool)
如果可用,将立体声混音(模拟环回混音)添加到输入多路复用器
- add_jack_modes (bool)
为每个 I/O 插孔添加“xxx 插孔模式”枚举控制,以允许更改耳机放大器和麦克风偏置 VREF 功能
- power_save_node (bool)
每个小部件的高级电源管理,根据实际引脚和流状态控制每个小部件节点的电源状态 (D0/D3)
- power_down_unused (bool)
关闭未使用的部件的电源,是 power_save_node 的一个子集,将来会被删除
- add_hp_mic (bool)
如果可能,将耳机添加到捕获源
- hp_mic_detect (bool)
为单个内置麦克风情况启用/禁用耳机/麦克风共享输入;默认值为 true
- vmaster (bool)
启用/禁用虚拟主控制;默认值为 true
- mixer_nid (int)
指定模拟环回混音器的小部件 NID
早期补丁¶
当设置 CONFIG_SND_HDA_PATCH_LOADER=y
时,您可以传递一个“补丁”作为固件文件,以便在初始化编解码器之前修改 HD 音频设置。这基本上可以像上述通过 sysfs 进行的重新配置一样工作,但它在第一次编解码器配置之前执行此操作。
补丁文件是一个纯文本文件,如下所示
[codec]
0x12345678 0xabcd1234 2
[model]
auto
[pincfg]
0x12 0x411111f0
[verb]
0x20 0x500 0x03
0x20 0x400 0xff
[hint]
jack_detect = no
该文件需要有一行 [codec]
。下一行应包含三个数字,分别指示编解码器供应商 ID(示例中为 0x12345678)、编解码器子系统 ID (0xabcd1234) 和编解码器的地址 (2)。其余补丁条目将应用于此指定的编解码器,直到给出另一个编解码器条目。将 0 或负数传递给第一个或第二个值将使跳过对相应字段的检查。这对于没有正确初始化 SSID 的真正损坏的设备很有用。
[model]
行允许更改每个编解码器的型号名称。在上面的示例中,它将更改为 model=auto。请注意,这会覆盖模块选项。
在 [pincfg]
行之后,内容将像上面的 user_pin_configs
sysfs 一样解析为初始默认引脚配置。这些值也可以在 user_pin_configs sysfs 文件中显示。
类似地,[verb]
后的行被解析为 init_verbs
sysfs 条目,[hint]
后的行分别被解析为 hints
sysfs 条目。
另一个将编解码器供应商 ID 从 0x12345678 覆盖为 0xdeadbeef 的示例如下
[codec]
0x12345678 0xabcd1234 2
[vendor_id]
0xdeadbeef
以类似的方式,您可以通过 [subsystem_id]
覆盖编解码器子系统 ID,通过 [revision_id]
行覆盖修订 ID。此外,编解码器芯片名称可以通过 [chip_name]
行重写。
[codec]
0x12345678 0xabcd1234 2
[subsystem_id]
0xffff1111
[revision_id]
0x10
[chip_name]
My-own NEWS-0002
hd-audio 驱动程序通过 request_firmware()
读取文件。因此,补丁文件必须位于相应的固件路径上,通常是 /lib/firmware。例如,当您传递选项 patch=hda-init.fw
时,必须存在文件 /lib/firmware/hda-init.fw。
补丁模块选项特定于每个卡实例,您需要为每个实例提供一个文件名,并以逗号分隔。例如,如果您有两张卡,一张用于板载模拟,另一张用于 HDMI 视频板,您可以传递如下补丁选项
options snd-hda-intel patch=on-board-patch,hdmi-patch
节能¶
节能是设备的一种自动挂起。当设备在一段时间内不活动时,设备会自动关闭以节省电量。关闭时间通过 power_save
模块选项指定,此选项可以通过 sysfs 动态更改。
当某些编解码器上启用模拟环回时,节能功能将不起作用。当您想要节能时,请确保将所有不需要的信号路由静音。
节能功能可能会在每次关闭/打开电源时导致可听见的咔哒声,具体取决于设备。其中一些可能可以解决,但恐怕有些很难解决。某些发行版(如 openSUSE)会在拔下电源线时自动启用节能功能。因此,如果您听到噪音,请首先怀疑是节能功能。请参阅 /sys/module/snd_hda_intel/parameters/power_save 以检查当前值。如果它不是零,则该功能已打开。
最近的内核也支持 HD 音频控制器芯片的运行时 PM。这意味着 HD 音频控制器也会动态地打开/关闭电源。该功能仅对某些控制器芯片(如 Intel LynxPoint)启用。您可以通过设置 power_save_controller
选项强制启用/禁用此功能,该选项也可在 /sys/module/snd_hda_intel/parameters 目录中找到。
跟踪点¶
hd-audio 驱动程序提供了一些基本的跟踪点。hda:hda_send_cmd
跟踪每个 CORB 写入,而 hda:hda_get_response
跟踪来自 RIRB 的响应(仅当从编解码器驱动程序读取时)。hda:hda_bus_reset
跟踪由于致命错误等导致的 bus-reset,hda:hda_unsol_event
跟踪非请求事件,hda:hda_power_down
和 hda:hda_power_up
跟踪通过节能行为进行的电源关闭/打开。
启用所有跟踪点可以像这样完成
# echo 1 > /sys/kernel/tracing/events/hda/enable
然后,在执行一些命令后,您可以从 /sys/kernel/tracing/trace 文件中跟踪。例如,当您想要跟踪发送了哪些编解码器命令时,启用如下跟踪点
# cat /sys/kernel/tracing/trace
# tracer: nop
#
# TASK-PID CPU# TIMESTAMP FUNCTION
# | | | | |
<...>-7807 [002] 105147.774889: hda_send_cmd: [0:0] val=e3a019
<...>-7807 [002] 105147.774893: hda_send_cmd: [0:0] val=e39019
<...>-7807 [002] 105147.999542: hda_send_cmd: [0:0] val=e3a01a
<...>-7807 [002] 105147.999543: hda_send_cmd: [0:0] val=e3901a
<...>-26764 [001] 349222.837143: hda_send_cmd: [0:0] val=e3a019
<...>-26764 [001] 349222.837148: hda_send_cmd: [0:0] val=e39019
<...>-26764 [001] 349223.058539: hda_send_cmd: [0:0] val=e3a01a
<...>-26764 [001] 349223.058541: hda_send_cmd: [0:0] val=e3901a
此处 [0:0]
指示卡号和编解码器地址,而 val
显示发送到编解码器的值。该值是一个打包值,您可以使用下面 hda-emu 包中包含的 hda-decode-verb 程序对其进行解码。例如,值 e3a019 是将左输出放大器值设置为 25。
% hda-decode-verb 0xe3a019
raw value = 0x00e3a019
cid = 0, nid = 0x0e, verb = 0x3a0, parm = 0x19
raw value: verb = 0x3a0, parm = 0x19
verbname = set_amp_gain_mute
amp raw val = 0xa019
output, left, idx=0, mute=0, val=25
开发树¶
HD 音频的最新开发代码可在 sound git 树中找到
git://git.kernel.org/pub/scm/linux/kernel/git/tiwai/sound.git
master 分支或 for-next 分支通常可以用作主要开发分支,而当前和下一个内核的开发分别在 for-linus 和 for-next 分支中找到。
发送错误报告¶
如果任何型号或模块选项对您的设备不起作用,现在是时候向开发人员发送错误报告了。在您的错误报告中提供以下内容
硬件供应商、产品和型号名称
内核版本(以及外部构建的 ALSA 驱动程序版本)
alsa-info.sh
输出;使用--no-upload
选项运行。请参阅下面有关 alsa-info 的部分
如果这是回归,最好发送工作和不工作内核的 alsa-info 输出。这真的很有帮助,因为我们可以直接比较编解码器寄存器。
通过以下方式发送错误报告
- kernel-bugzilla
- alsa-devel ML
调试工具¶
本节介绍一些可用于调试 HD 音频问题的工具。
alsa-info¶
脚本 alsa-info.sh
是一个非常有用的工具,可以收集音频设备信息。它包含在 alsa-utils 包中。最新版本可以在 git 存储库中找到
git://git.alsa-project.org/alsa-utils.git
该脚本也可以直接从以下 URL 获取
以 root 身份运行此脚本,它将收集重要信息,例如模块列表、模块参数、proc 文件内容(包括编解码器 proc 文件)、混音器输出和控制元素。默认情况下,它会将信息存储到 alsa-project.org 上的 Web 服务器上。但是,如果您发送错误报告,最好使用 --no-upload
选项运行,并附加生成的文件。
还有一些其他有用的选项。有关详细信息,请参阅 --help
选项输出。
当发生探测错误或驱动程序明显分配了不匹配的模型时,最好在冷启动后使用 probe_only=1
选项加载驱动程序,并在此状态下运行 alsa-info。使用此选项,驱动程序不会配置混音器和 PCM,而只是尝试探测编解码器插槽。探测后,proc 文件可用,因此您可以在驱动程序修改之前获取原始编解码器信息。当然,驱动程序不能与 probe_only=1
一起使用。但是,如果启用了 hda-reconfig 选项,您可以通过 hwdep sysfs 文件继续配置。使用 probe_only
掩码 2 会跳过 HDA 编解码器的重置(使用 probe_only=3
作为模块选项)。hwdep 接口可用于确定 BIOS 编解码器初始化。
hda-verb¶
hda-verb 是一个微小的程序,允许您直接访问 HD-audio 编解码器。您可以使用它执行原始的 HD-audio 编解码器动词。此程序访问 hwdep 设备,因此您需要事先启用内核配置 CONFIG_SND_HDA_HWDEP=y
。
hda-verb 程序接受四个参数:hwdep 设备文件、小部件 NID、动词和参数。当您访问卡 0 的插槽 2 上的编解码器时,通常将 /dev/snd/hwC0D2 传递给第一个参数。(但是,实际的路径名称取决于系统。)
第二个参数是要访问的小部件编号 ID。第三个参数可以是十六进制/数字,也可以是与动词对应的字符串。类似地,最后一个参数是要写入的值,也可以是参数类型的字符串。
% hda-verb /dev/snd/hwC0D0 0x12 0x701 2
nid = 0x12, verb = 0x701, param = 0x2
value = 0x0
% hda-verb /dev/snd/hwC0D0 0x0 PARAMETERS VENDOR_ID
nid = 0x0, verb = 0xf00, param = 0x0
value = 0x10ec0262
% hda-verb /dev/snd/hwC0D0 2 set_a 0xb080
nid = 0x2, verb = 0x300, param = 0xb080
value = 0x0
虽然您可以使用此程序发出任何动词,但驱动程序状态并非总是更新。例如,音量值通常缓存在驱动程序中,因此直接通过 hda-verb 更改小部件放大器值不会更改混音器值。
hda-verb 程序现在包含在 alsa-tools 中
git://git.alsa-project.org/alsa-tools.git
此外,旧的独立软件包可以在 ftp 目录中找到
还有一个 git 存储库可用
git://git.kernel.org/pub/scm/linux/kernel/git/tiwai/hda-verb.git
有关 hda-verb 程序的更多详细信息,请参阅 tarball 中的 README 文件。
hda-analyzer¶
hda-analyzer 提供了一个基于 pyGTK2 绑定的图形界面,用于访问原始的 HD-audio 控制。它是 hda-verb 的更强大的版本。该程序为您提供了一个易于使用的 GUI 工具,用于显示小部件信息和调整放大器值,以及与 proc 兼容的输出。
hda-analyzer
是 alsa-project.org 中 alsa.git 存储库的一部分
git://git.alsa-project.org/alsa.git
Codecgraph¶
Codecgraph 是一个实用程序程序,用于生成图形并可视化编解码器芯片的编解码器节点连接。当您在没有正确的数据手册的情况下分析或调试编解码器时,它特别有用。该程序解析给定的编解码器 proc 文件,并通过 graphiz 程序转换为 SVG。
tarball 和 GIT 树可以在以下网页中找到
hda-emu¶
hda-emu 是一个 HD-audio 仿真器。该程序的主要目的是在没有真实硬件的情况下调试 HD-audio 编解码器。因此,它不模拟真实的音频 I/O 的行为,而只是在探测和操作 HD-audio 驱动程序时转储编解码器寄存器更改和 ALSA 驱动程序内部更改。
该程序需要一个编解码器 proc 文件来模拟。事先获取目标编解码器的 proc 文件,或从 tarball 中的编解码器 proc 集合中选择一个示例编解码器。然后,使用 proc 文件运行该程序,hda-emu 程序将开始解析编解码器文件并模拟 HD-audio 驱动程序
% hda-emu codecs/stac9200-dell-d820-laptop
# Parsing..
hda_codec: Unknown model for STAC9200, using BIOS defaults
hda_codec: pin nid 08 bios pin config 40c003fa
....
该程序只为您提供一个非常笨拙的命令行界面。您可以获取当前状态的 proc 文件转储,获取控制(混音器)元素列表,设置/获取控制元素值,模拟 PCM 操作、插孔插入模拟等。
该程序可以在下面的 git 存储库中找到
git://git.kernel.org/pub/scm/linux/kernel/git/tiwai/hda-emu.git
有关 hda-emu 程序的更多详细信息,请参阅存储库中的 README 文件。
hda-jack-retask¶
hda-jack-retask 是一个用户友好的 GUI 程序,用于操作插孔重新分配的 HD-audio 引脚控制。如果您在插孔分配方面有问题,请尝试此程序并检查是否可以获得有用的结果。一旦您弄清楚了正确的引脚分配,就可以静态地在驱动程序代码中修复它,或者通过传递固件补丁文件(请参阅“早期修补”部分)来修复它。
该程序现在包含在 alsa-tools 中
git://git.alsa-project.org/alsa-tools.git