요약·해설과 원문, 전문 번역을 서로 분리했습니다. API 이름, symbol, source path는 원문 표기를 사용합니다.
1. 요약·해설
원문의 핵심 논리와 kernel programming 관점의 보충 설명입니다. 아래의 전문 번역과는 별도로 작성했습니다.
2. 영어 원문 전체
번역 기준이 된 Linux v6.18.37 원문입니다. 줄 번호는 이 버전의 파일 좌표입니다.
원문 전체 펼치기
===============================
Realtek PC Beep Hidden Register
===============================
This file documents the "PC Beep Hidden Register", which is present in certain
Realtek HDA codecs and controls a muxer and pair of passthrough mixers that can
route audio between pins but aren't themselves exposed as HDA widgets. As far
as I can tell, these hidden routes are designed to allow flexible PC Beep output
for codecs that don't have mixer widgets in their output paths. Why it's easier
to hide a mixer behind an undocumented vendor register than to just expose it
as a widget, I have no idea.
Register Description
====================
The register is accessed via processing coefficient 0x36 on NID 20h. Bits not
identified below have no discernible effect on my machine, a 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 input select (B): 2 bits
When zero, expose the PC Beep line (from the internal beep generator, when
enabled with the Set Beep Generation verb on NID 01h, or else from the
external PCBEEP pin) on the 1Ah pin node. When nonzero, expose the headphone
jack (or possibly Line In on some machines) input instead. If PC Beep is
selected, the 1Ah boost control has no effect.
Amplify 1Ah loopback, left (L): 1 bit
Amplify the left channel of 1Ah before mixing it into outputs as specified
by h and S bits. Does not affect the level of 1Ah exposed to other widgets.
Amplify 1Ah loopback, right (R): 1 bit
Amplify the right channel of 1Ah before mixing it into outputs as specified
by h and S bits. Does not affect the level of 1Ah exposed to other widgets.
Loopback 1Ah to 21h [active low] (h): 1 bit
When zero, mix 1Ah (possibly with amplification, depending on L and R bits)
into 21h (headphone jack on my machine). Mixed signal respects the mute
setting on 21h.
Loopback 1Ah to 14h (S): 1 bit
When one, mix 1Ah (possibly with amplification, depending on L and R bits)
into 14h (internal speaker on my machine). Mixed signal **ignores** the mute
setting on 14h and is present whenever 14h is configured as an output.
Path diagrams
=============
1Ah input selection (DIV is the PC Beep divider set on NID 01h)::
<Beep generator> <PCBEEP pin> <Headphone jack>
| | |
+--DIV--+--!DIV--+ {1Ah boost control}
| |
+--(b == 0)--+--(b != 0)--+
|
>1Ah (Beep/Headphone Mic/Line In)<
Loopback of 1Ah to 21h/14h::
<1Ah (Beep/Headphone Mic/Line In)>
|
{amplify if L/R}
|
+-----!h-----+-----S-----+
| |
{21h mute control} |
| |
>21h (Headphone)< >14h (Internal Speaker)<
Background
==========
All Realtek HDA codecs have a vendor-defined widget with node ID 20h which
provides access to a bank of registers that control various codec functions.
Registers are read and written via the standard HDA processing coefficient
verbs (Set/Get Coefficient Index, Set/Get Processing Coefficient). The node is
named "Realtek Vendor Registers" in public datasheets' verb listings and,
apart from that, is entirely undocumented.
This particular register, exposed at coefficient 0x36 and named in commits from
Realtek, is of note: unlike most registers, which seem to control detailed
amplifier parameters not in scope of the HDA specification, it controls audio
routing which could just as easily have been defined using standard HDA mixer
and selector widgets.
Specifically, it selects between two sources for the input pin widget with Node
ID (NID) 1Ah: the widget's signal can come either from an audio jack (on my
laptop, a Dell XPS 13 9350, it's the headphone jack, but comments in Realtek
commits indicate that it might be a Line In on some machines) or from the PC
Beep line (which is itself multiplexed between the codec's internal beep
generator and external PCBEEP pin, depending on if the beep generator is
enabled via verbs on NID 01h). Additionally, it can mix (with optional
amplification) that signal onto the 21h and/or 14h output pins.
The register's reset value is 0x3717, corresponding to PC Beep on 1Ah that is
then amplified and mixed into both the headphones and the speakers. Not only
does this violate the HDA specification, which says that "[a vendor defined
beep input pin] connection may be maintained *only* while the Link reset
(**RST#**) is asserted", it means that we cannot ignore the register if we care
about the input that 1Ah would otherwise expose or if the PCBEEP trace is
poorly shielded and picks up chassis noise (both of which are the case on my
machine).
Unfortunately, there are lots of ways to get this register configuration wrong.
Linux, it seems, has gone through most of them. For one, the register resets
after S3 suspend: judging by existing code, this isn't the case for all vendor
registers, and it's led to some fixes that improve behavior on cold boot but
don't last after suspend. Other fixes have successfully switched the 1Ah input
away from PC Beep but have failed to disable both loopback paths. On my
machine, this means that the headphone input is amplified and looped back to
the headphone output, which uses the exact same pins! As you might expect, this
causes terrible headphone noise, the character of which is controlled by the
1Ah boost control. (If you've seen instructions online to fix XPS 13 headphone
noise by changing "Headphone Mic Boost" in ALSA, now you know why.)
The information here has been obtained through black-box reverse engineering of
the ALC256 codec's behavior and is not guaranteed to be correct. It likely
also applies for the ALC255, ALC257, ALC235, and ALC236, since those codecs
seem to be close relatives of the ALC256. (They all share one initialization
function.) Additionally, other codecs like the ALC225 and ALC285 also have this
register, judging by existing fixups in ``patch_realtek.c``, but specific
data (e.g. node IDs, bit positions, pin mappings) for those codecs may differ
from what I've described here.
3. 한국어 전문 번역
영어 원문의 문단 순서와 의미를 유지한 전체 번역입니다. 코드, 함수명, symbol과 URL은 원문 표기를 유지합니다.
숨겨진 PC Beep 경로
1-12이 문서는 일부 Realtek HDA codec에 있는 `PC Beep Hidden Register`를 설명합니다. 이 register는 HDA widget으로 노출되지 않은 muxer 하나와 passthrough mixer 한 쌍을 제어하며, pin 사이로 audio를 route할 수 있습니다.
확인된 용도는 출력 경로에 mixer widget이 없는 codec에서도 PC Beep 출력을 유연하게 구성하는 것입니다. 저자는 표준 widget으로 공개할 수 있는 mixer를 문서화되지 않은 vendor register 뒤에 숨긴 이유는 알 수 없다고 덧붙입니다.
HDA topology에 보이지 않지만 coefficient 0x36이 제어하는 기능입니다.
===============================
Realtek PC Beep Hidden Register
===============================
This file documents the "PC Beep Hidden Register", which is present in certain
Realtek HDA codecs and controls a muxer and pair of passthrough mixers that can
route audio between pins but aren't themselves exposed as HDA widgets. As far
as I can tell, these hidden routes are designed to allow flexible PC Beep output
for codecs that don't have mixer widgets in their output paths. Why it's easier
to hide a mixer behind an undocumented vendor register than to just expose it
as a widget, I have no idea.
Register 위치와 reset bit 배열
13-24Register는 node ID `20h`의 processing coefficient `0x36`을 통해 접근합니다. 아래에 식별되지 않은 bit는 저자의 Dell XPS 13 9350에서 알아볼 수 있는 효과가 없었습니다.
원문의 MSB에서 LSB 방향 ASCII bit 그림을 같은 field 순서로 구조화했습니다. 이름 없는 field는 효과가 식별되지 않은 bit입니다.
원문 그림의 reset 값은 뒤 절에서 `0x3717`로 설명됩니다. 알려진 control field는 `B` 2 bit와 `L`, `R`, active-low `h`, `S` 각각 1 bit입니다.
Register Description
====================
The register is accessed via processing coefficient 0x36 on NID 20h. Bits not
identified below have no discernible effect on my machine, a Dell XPS 13 9350::
MSB LSB
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| |h|S|L| | B |R| | Known bits
+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+
|0|0|1|1| 0x7 |0|0x0|1| 0x7 | Reset value
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
입력 선택, 증폭, loopback bit
25-50`1Ah input select (B)`는 2 bit입니다. 값이 0이면 `1Ah` pin node에 PC Beep line을 노출합니다. 이 line은 `01h`에서 Set Beep Generation verb로 내부 beep generator가 활성화됐으면 그 generator에서 오고, 그렇지 않으면 외부 `PCBEEP` pin에서 옵니다.
`B`가 0이 아니면 대신 headphone jack 입력을 노출하며 일부 장치에서는 Line In일 수 있습니다. PC Beep가 선택된 동안에는 `1Ah` boost control이 아무 효과가 없습니다.
`Amplify 1Ah loopback, left (L)`는 `h`와 `S` bit가 지정한 출력으로 섞기 전에 `1Ah`의 left channel을 증폭합니다. `Amplify 1Ah loopback, right (R)`도 right channel에 같은 역할을 합니다. 두 bit 모두 다른 widget에 노출되는 `1Ah` 신호 수준에는 영향을 주지 않습니다.
Active-low인 `Loopback 1Ah to 21h (h)`가 0이면, `L/R`에 따라 증폭될 수 있는 `1Ah`를 저자의 장치에서 headphone jack인 `21h`에 섞습니다. 이 mixed signal은 `21h`의 mute 설정을 따릅니다.
`Loopback 1Ah to 14h (S)`가 1이면 `1Ah`를 저자의 장치에서 internal speaker인 `14h`에 섞습니다. 이 mixed signal은 `14h`의 mute를 무시하며, `14h`가 output으로 구성된 동안에는 항상 존재합니다.
각 field의 활성 조건과 영향을 정리했습니다.
1Ah input select (B): 2 bits
When zero, expose the PC Beep line (from the internal beep generator, when
enabled with the Set Beep Generation verb on NID 01h, or else from the
external PCBEEP pin) on the 1Ah pin node. When nonzero, expose the headphone
jack (or possibly Line In on some machines) input instead. If PC Beep is
selected, the 1Ah boost control has no effect.
Amplify 1Ah loopback, left (L): 1 bit
Amplify the left channel of 1Ah before mixing it into outputs as specified
by h and S bits. Does not affect the level of 1Ah exposed to other widgets.
Amplify 1Ah loopback, right (R): 1 bit
Amplify the right channel of 1Ah before mixing it into outputs as specified
by h and S bits. Does not affect the level of 1Ah exposed to other widgets.
Loopback 1Ah to 21h [active low] (h): 1 bit
When zero, mix 1Ah (possibly with amplification, depending on L and R bits)
into 21h (headphone jack on my machine). Mixed signal respects the mute
setting on 21h.
Loopback 1Ah to 14h (S): 1 bit
When one, mix 1Ah (possibly with amplification, depending on L and R bits)
into 14h (internal speaker on my machine). Mixed signal **ignores** the mute
setting on 14h and is present whenever 14h is configured as an output.
1Ah 선택과 21h/14h 경로
51-75첫 번째 원문 도식에서 `DIV`는 `01h`에 설정된 PC Beep divider입니다. 내부 beep generator는 `DIV` 경로로, 외부 `PCBEEP` pin은 `!DIV` 경로로 PC Beep line에 합쳐집니다. `B == 0`이면 이 line이 `1Ah`로 가고, `B != 0`이면 boost control을 거친 headphone jack 입력이 `1Ah`로 갑니다.
원문의 분기 도식을 source, gate, destination 순으로 다시 그렸습니다.
두 번째 원문 도식에서 `1Ah` 신호는 `L/R` bit가 켜졌으면 channel별 증폭을 거친 뒤 두 갈래로 나뉩니다. `!h`, 즉 `h == 0` 경로는 `21h` mute control을 거쳐 headphone으로 가고, `S == 1` 경로는 별도의 `14h` mute control을 거치지 않고 internal speaker로 갑니다.
원문의 21h/14h 분기와 mute 차이를 보존한 구조화 경로입니다.
Input source 선택 뒤 증폭과 두 output loopback이 이어집니다.
Path diagrams
=============
1Ah input selection (DIV is the PC Beep divider set on NID 01h)::
<Beep generator> <PCBEEP pin> <Headphone jack>
| | |
+--DIV--+--!DIV--+ {1Ah boost control}
| |
+--(b == 0)--+--(b != 0)--+
|
>1Ah (Beep/Headphone Mic/Line In)<
Loopback of 1Ah to 21h/14h::
<1Ah (Beep/Headphone Mic/Line In)>
|
{amplify if L/R}
|
+-----!h-----+-----S-----+
| |
{21h mute control} |
| |
>21h (Headphone)< >14h (Internal Speaker)<
Realtek vendor register 배경
76-100모든 Realtek HDA codec에는 node ID `20h`의 vendor-defined widget이 있으며, 여러 codec 기능을 제어하는 register bank에 접근하게 합니다. Register는 표준 HDA processing coefficient verb인 Set/Get Coefficient Index와 Set/Get Processing Coefficient로 읽고 씁니다.
공개 datasheet의 verb 목록은 이 node를 `Realtek Vendor Registers`라고 부르지만 그 밖의 내용은 전혀 문서화하지 않습니다. Realtek commit에서 이름이 확인되는 coefficient `0x36`은 대부분의 vendor register와 달리 HDA specification의 표준 mixer와 selector widget으로 충분히 표현할 수 있는 audio routing을 제어한다는 점에서 주목할 만합니다.
이 register는 NID `1Ah` input pin widget의 두 source를 선택합니다. 하나는 audio jack이며 Dell XPS 13 9350에서는 headphone jack이지만 다른 장치에서는 Line In일 수 있습니다. 다른 하나는 PC Beep line으로, `01h` verb에서 beep generator가 활성화됐는지에 따라 codec 내부 generator와 외부 `PCBEEP` pin 사이에서 다시 multiplex됩니다.
또한 선택된 `1Ah` 신호를 선택적으로 증폭한 뒤 `21h`와 `14h` output pin 하나 또는 둘 모두에 섞을 수 있습니다.
공개된 HDA 구성과 coefficient 0x36 기능의 차이입니다.
Background
==========
All Realtek HDA codecs have a vendor-defined widget with node ID 20h which
provides access to a bank of registers that control various codec functions.
Registers are read and written via the standard HDA processing coefficient
verbs (Set/Get Coefficient Index, Set/Get Processing Coefficient). The node is
named "Realtek Vendor Registers" in public datasheets' verb listings and,
apart from that, is entirely undocumented.
This particular register, exposed at coefficient 0x36 and named in commits from
Realtek, is of note: unlike most registers, which seem to control detailed
amplifier parameters not in scope of the HDA specification, it controls audio
routing which could just as easily have been defined using standard HDA mixer
and selector widgets.
Specifically, it selects between two sources for the input pin widget with Node
ID (NID) 1Ah: the widget's signal can come either from an audio jack (on my
laptop, a Dell XPS 13 9350, it's the headphone jack, but comments in Realtek
commits indicate that it might be a Line In on some machines) or from the PC
Beep line (which is itself multiplexed between the codec's internal beep
generator and external PCBEEP pin, depending on if the beep generator is
enabled via verbs on NID 01h). Additionally, it can mix (with optional
amplification) that signal onto the 21h and/or 14h output pins.
Reset 상태, suspend 문제, 적용 범위
101-129Register의 reset 값은 `0x3717`입니다. 이 값은 PC Beep를 `1Ah`에 선택한 뒤 증폭해 headphone과 speaker 양쪽에 섞는 상태에 해당합니다.
이는 vendor-defined beep input pin의 연결을 Link reset인 `RST#`가 assert된 동안에만 유지할 수 있다는 HDA specification의 규칙을 위반합니다. 또한 `1Ah`가 본래 노출할 input을 사용해야 하거나 차폐가 좋지 않은 `PCBEEP` trace가 chassis noise를 수집하는 장치에서는 이 register를 무시할 수 없습니다. 저자의 장치에는 두 문제가 모두 있습니다.
이 register를 잘못 구성하는 방법은 많고 Linux도 대부분을 겪었습니다. 먼저 S3 suspend 뒤에 register가 reset됩니다. 모든 vendor register가 그런 것은 아니므로, cold boot 동작만 고치고 suspend 뒤에는 유지되지 않는 fix가 만들어졌습니다.
다른 fix는 `1Ah` input을 PC Beep에서 성공적으로 전환했지만 두 loopback 경로를 모두 끄지는 못했습니다. 저자의 장치에서는 headphone input이 증폭된 뒤 같은 pin을 쓰는 headphone output으로 loopback되어 심한 noise가 생깁니다. 그 noise의 특성은 `1Ah` boost control에 따라 달라집니다. XPS 13의 headphone noise를 ALSA `Headphone Mic Boost`로 고치라는 온라인 안내가 생긴 이유가 바로 이것입니다.
여기 수록된 정보는 ALC256 동작의 black-box reverse engineering으로 얻었으며 정확성을 보장하지 않습니다. Initialization function 하나를 공유하는 가까운 계열인 ALC255, ALC257, ALC235, ALC236에도 적용될 가능성이 큽니다.
`patch_realtek.c`의 기존 fixup을 보면 ALC225와 ALC285 같은 다른 codec에도 이 register가 있습니다. 다만 그런 codec에서는 node ID, bit 위치, pin mapping 등의 세부 정보가 이 문서의 설명과 다를 수 있습니다.
Reset 기본값과 불완전한 fix가 만드는 증상입니다.
ALC256에서 확인한 결과와 다른 codec에 대한 확실성 수준입니다.
The register's reset value is 0x3717, corresponding to PC Beep on 1Ah that is
then amplified and mixed into both the headphones and the speakers. Not only
does this violate the HDA specification, which says that "[a vendor defined
beep input pin] connection may be maintained *only* while the Link reset
(**RST#**) is asserted", it means that we cannot ignore the register if we care
about the input that 1Ah would otherwise expose or if the PCBEEP trace is
poorly shielded and picks up chassis noise (both of which are the case on my
machine).
Unfortunately, there are lots of ways to get this register configuration wrong.
Linux, it seems, has gone through most of them. For one, the register resets
after S3 suspend: judging by existing code, this isn't the case for all vendor
registers, and it's led to some fixes that improve behavior on cold boot but
don't last after suspend. Other fixes have successfully switched the 1Ah input
away from PC Beep but have failed to disable both loopback paths. On my
machine, this means that the headphone input is amplified and looped back to
the headphone output, which uses the exact same pins! As you might expect, this
causes terrible headphone noise, the character of which is controlled by the
1Ah boost control. (If you've seen instructions online to fix XPS 13 headphone
noise by changing "Headphone Mic Boost" in ALSA, now you know why.)
The information here has been obtained through black-box reverse engineering of
the ALC256 codec's behavior and is not guaranteed to be correct. It likely
also applies for the ALC255, ALC257, ALC235, and ALC236, since those codecs
seem to be close relatives of the ALC256. (They all share one initialization
function.) Additionally, other codecs like the ALC225 and ALC285 also have this
register, judging by existing fixups in ``patch_realtek.c``, but specific
data (e.g. node IDs, bit positions, pin mappings) for those codecs may differ
from what I've described here.
요약·해설
realtek-pc-beep.rst:1-129일부 Realtek HDA codec의 coefficient 0x36이 `1Ah` 입력 선택과 `21h`/`14h` loopback을 숨겨서 제어하는 방식, reset 0x3717의 문제, S3 복원 및 codec별 적용 한계를 설명합니다.
핵심은 `B`로 PC Beep와 jack input을 고르고, `L/R`로 loopback을 증폭하며, active-low `h`와 `S`로 headphone과 speaker mixing을 제어한다는 점입니다. 특히 speaker 경로는 `14h` mute를 무시하므로 단순한 mixer mute만으로 noise를 제거할 수 없습니다.
장치 fixup은 cold boot에서 값을 바꾸는 데 그치지 않고 S3 resume 뒤에도 coefficient를 복원해야 하며, input source와 두 loopback 경로를 함께 검토해야 합니다. ALC256 이외 codec에는 register 존재 여부만으로 같은 bit layout을 가정하면 안 됩니다.
운영과 debugging에서 먼저 확인할 field와 상태입니다.