Realtek PC Beep 隐藏寄存器

此文件记录了 “PC Beep 隐藏寄存器”,它存在于某些 Realtek HDA 编解码器中,并控制一个多路复用器和一对直通混音器,这些混音器可以在引脚之间路由音频,但本身不会作为 HDA 小部件公开。 据我所知,这些隐藏的路由旨在为没有输出路径中的混音器小部件的编解码器提供灵活的 PC Beep 输出。 为什么隐藏混音器比仅仅将其作为小部件公开更容易,我不知道。

寄存器描述

该寄存器通过 NID 20h 上的处理系数 0x36 访问。 下面未标识的位对我的机器(Dell XPS 13 9350)没有明显的影响

MSB                           LSB
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| |h|S|L|         | B |R|       | Known bits
+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+
|0|0|1|1|  0x7  |0|0x0|1|  0x7  | Reset value
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1Ah 输入选择 (B): 2 位

当为零时,在 1Ah 引脚节点上公开 PC Beep 线(来自内部蜂鸣器发生器,当在 NID 01h 上使用 Set Beep Generation 动词启用时,或者来自外部 PCBEEP 引脚)。 当非零时,改为公开耳机插孔(或某些机器上的线路输入)。 如果选择了 PC Beep,则 1Ah 提升控制无效。

放大 1Ah 回路,左 (L): 1 位

在将 1Ah 的左声道混音到 h 和 S 位指定的输出之前对其进行放大。 不影响暴露给其他小部件的 1Ah 的电平。

放大 1Ah 回路,右 (R): 1 位

在将 1Ah 的右声道混音到 h 和 S 位指定的输出之前对其进行放大。 不影响暴露给其他小部件的 1Ah 的电平。

将 1Ah 回路到 21h [低电平有效] (h): 1 位

当为零时,将 1Ah(可能具有放大,具体取决于 L 和 R 位)混音到 21h(我机器上的耳机插孔)。 混合信号遵循 21h 上的静音设置。

将 1Ah 回路到 14h (S): 1 位

当为一时,将 1Ah(可能具有放大,具体取决于 L 和 R 位)混音到 14h(我机器上的内置扬声器)。 混合信号忽略 14h 上的静音设置,并且只要 14h 配置为输出,就存在。

路径图

1Ah 输入选择 (DIV 是在 NID 01h 上设置的 PC Beep 分频器)

<Beep generator>   <PCBEEP pin>    <Headphone jack>
        |                |                |
        +--DIV--+--!DIV--+       {1Ah boost control}
                |                         |
                +--(b == 0)--+--(b != 0)--+
                             |
             >1Ah (Beep/Headphone Mic/Line In)<

1Ah 到 21h/14h 的回路

     <1Ah (Beep/Headphone Mic/Line In)>
                     |
              {amplify if L/R}
                     |
        +-----!h-----+-----S-----+
        |                        |
{21h mute control}               |
        |                        |
>21h (Headphone)<     >14h (Internal Speaker)<

背景

所有 Realtek HDA 编解码器都有一个供应商定义的小部件,其节点 ID 为 20h,它提供对控制各种编解码器功能的寄存器组的访问。 寄存器通过标准 HDA 处理系数动词(Set/Get Coefficient Index, Set/Get Processing Coefficient)进行读取和写入。 该节点在公共数据表的动词列表中被命名为 “Realtek Vendor Registers”,除此之外,完全没有文档记录。

这个特定的寄存器,在系数 0x36 处公开,并在 Realtek 的提交中命名,值得注意:与大多数似乎控制不在 HDA 规范范围内的详细放大器参数的寄存器不同,它控制音频路由,音频路由同样可以使用标准 HDA 混音器和选择器小部件来定义。

具体来说,它在节点 ID (NID) 为 1Ah 的输入引脚小部件的两个源之间进行选择:小部件的信号可以来自音频插孔(在我的笔记本电脑 Dell XPS 13 9350 上,它是耳机插孔,但 Realtek 提交中的注释表明它可能是某些机器上的线路输入)或来自 PC Beep 线(它本身在编解码器的内部蜂鸣器发生器和外部 PCBEEP 引脚之间进行多路复用,具体取决于是否通过 NID 01h 上的动词启用了蜂鸣器发生器)。 此外,它可以(通过可选的放大)将该信号混合到 21h 和/或 14h 输出引脚上。

寄存器的重置值为 0x3717,对应于 1Ah 上的 PC Beep,然后将其放大并混合到耳机和扬声器中。 这不仅违反了 HDA 规范,该规范指出“[供应商定义的蜂鸣器输入引脚]连接只能在 Link 重置 (RST#) 断言时保持”,而且意味着如果我们关心 1Ah 可能公开的输入或者 PCBEEP 走线屏蔽不良并拾取机箱噪声(这两种情况都在我的机器上)时,我们不能忽略该寄存器。

不幸的是,有很多方法可以错误地配置此寄存器。 似乎 Linux 已经经历了其中的大多数方法。 例如,该寄存器在 S3 挂起后重置:从现有代码判断,并非所有供应商寄存器都是这种情况,并且它导致了一些修复,这些修复改善了冷启动时的行为,但在挂起后不会持续。 其他修复程序已成功将 1Ah 输入从 PC Beep 切换出来,但未能禁用两个回路路径。 在我的机器上,这意味着耳机输入被放大并回路到耳机输出,耳机输出使用完全相同的引脚! 正如您可能预期的那样,这会导致可怕的耳机噪声,其特征由 1Ah 提升控制控制。 (如果您在网上看到通过在 ALSA 中更改 “Headphone Mic Boost” 来修复 XPS 13 耳机噪声的说明,现在您知道原因了。)

这里的信息是通过对 ALC256 编解码器的行为进行黑盒逆向工程获得的,并且不能保证是正确的。 它可能也适用于 ALC255、ALC257、ALC235 和 ALC236,因为这些编解码器似乎与 ALC256 密切相关。 (它们都共享一个初始化函数。) 此外,其他编解码器(如 ALC225 和 ALC285)也具有此寄存器,从 patch_realtek.c 中的现有修复程序判断,但这些编解码器的特定数据(例如,节点 ID、位位置、引脚映射)可能与我在此处描述的不同。