162306a36Sopenharmony_ci=============================== 262306a36Sopenharmony_ciRealtek PC Beep Hidden Register 362306a36Sopenharmony_ci=============================== 462306a36Sopenharmony_ci 562306a36Sopenharmony_ciThis file documents the "PC Beep Hidden Register", which is present in certain 662306a36Sopenharmony_ciRealtek HDA codecs and controls a muxer and pair of passthrough mixers that can 762306a36Sopenharmony_ciroute audio between pins but aren't themselves exposed as HDA widgets. As far 862306a36Sopenharmony_cias I can tell, these hidden routes are designed to allow flexible PC Beep output 962306a36Sopenharmony_cifor codecs that don't have mixer widgets in their output paths. Why it's easier 1062306a36Sopenharmony_cito hide a mixer behind an undocumented vendor register than to just expose it 1162306a36Sopenharmony_cias a widget, I have no idea. 1262306a36Sopenharmony_ci 1362306a36Sopenharmony_ciRegister Description 1462306a36Sopenharmony_ci==================== 1562306a36Sopenharmony_ci 1662306a36Sopenharmony_ciThe register is accessed via processing coefficient 0x36 on NID 20h. Bits not 1762306a36Sopenharmony_ciidentified below have no discernible effect on my machine, a Dell XPS 13 9350:: 1862306a36Sopenharmony_ci 1962306a36Sopenharmony_ci MSB LSB 2062306a36Sopenharmony_ci +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 2162306a36Sopenharmony_ci | |h|S|L| | B |R| | Known bits 2262306a36Sopenharmony_ci +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+ 2362306a36Sopenharmony_ci |0|0|1|1| 0x7 |0|0x0|1| 0x7 | Reset value 2462306a36Sopenharmony_ci +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 2562306a36Sopenharmony_ci 2662306a36Sopenharmony_ci1Ah input select (B): 2 bits 2762306a36Sopenharmony_ci When zero, expose the PC Beep line (from the internal beep generator, when 2862306a36Sopenharmony_ci enabled with the Set Beep Generation verb on NID 01h, or else from the 2962306a36Sopenharmony_ci external PCBEEP pin) on the 1Ah pin node. When nonzero, expose the headphone 3062306a36Sopenharmony_ci jack (or possibly Line In on some machines) input instead. If PC Beep is 3162306a36Sopenharmony_ci selected, the 1Ah boost control has no effect. 3262306a36Sopenharmony_ci 3362306a36Sopenharmony_ciAmplify 1Ah loopback, left (L): 1 bit 3462306a36Sopenharmony_ci Amplify the left channel of 1Ah before mixing it into outputs as specified 3562306a36Sopenharmony_ci by h and S bits. Does not affect the level of 1Ah exposed to other widgets. 3662306a36Sopenharmony_ci 3762306a36Sopenharmony_ciAmplify 1Ah loopback, right (R): 1 bit 3862306a36Sopenharmony_ci Amplify the right channel of 1Ah before mixing it into outputs as specified 3962306a36Sopenharmony_ci by h and S bits. Does not affect the level of 1Ah exposed to other widgets. 4062306a36Sopenharmony_ci 4162306a36Sopenharmony_ciLoopback 1Ah to 21h [active low] (h): 1 bit 4262306a36Sopenharmony_ci When zero, mix 1Ah (possibly with amplification, depending on L and R bits) 4362306a36Sopenharmony_ci into 21h (headphone jack on my machine). Mixed signal respects the mute 4462306a36Sopenharmony_ci setting on 21h. 4562306a36Sopenharmony_ci 4662306a36Sopenharmony_ciLoopback 1Ah to 14h (S): 1 bit 4762306a36Sopenharmony_ci When one, mix 1Ah (possibly with amplification, depending on L and R bits) 4862306a36Sopenharmony_ci into 14h (internal speaker on my machine). Mixed signal **ignores** the mute 4962306a36Sopenharmony_ci setting on 14h and is present whenever 14h is configured as an output. 5062306a36Sopenharmony_ci 5162306a36Sopenharmony_ciPath diagrams 5262306a36Sopenharmony_ci============= 5362306a36Sopenharmony_ci 5462306a36Sopenharmony_ci1Ah input selection (DIV is the PC Beep divider set on NID 01h):: 5562306a36Sopenharmony_ci 5662306a36Sopenharmony_ci <Beep generator> <PCBEEP pin> <Headphone jack> 5762306a36Sopenharmony_ci | | | 5862306a36Sopenharmony_ci +--DIV--+--!DIV--+ {1Ah boost control} 5962306a36Sopenharmony_ci | | 6062306a36Sopenharmony_ci +--(b == 0)--+--(b != 0)--+ 6162306a36Sopenharmony_ci | 6262306a36Sopenharmony_ci >1Ah (Beep/Headphone Mic/Line In)< 6362306a36Sopenharmony_ci 6462306a36Sopenharmony_ciLoopback of 1Ah to 21h/14h:: 6562306a36Sopenharmony_ci 6662306a36Sopenharmony_ci <1Ah (Beep/Headphone Mic/Line In)> 6762306a36Sopenharmony_ci | 6862306a36Sopenharmony_ci {amplify if L/R} 6962306a36Sopenharmony_ci | 7062306a36Sopenharmony_ci +-----!h-----+-----S-----+ 7162306a36Sopenharmony_ci | | 7262306a36Sopenharmony_ci {21h mute control} | 7362306a36Sopenharmony_ci | | 7462306a36Sopenharmony_ci >21h (Headphone)< >14h (Internal Speaker)< 7562306a36Sopenharmony_ci 7662306a36Sopenharmony_ciBackground 7762306a36Sopenharmony_ci========== 7862306a36Sopenharmony_ci 7962306a36Sopenharmony_ciAll Realtek HDA codecs have a vendor-defined widget with node ID 20h which 8062306a36Sopenharmony_ciprovides access to a bank of registers that control various codec functions. 8162306a36Sopenharmony_ciRegisters are read and written via the standard HDA processing coefficient 8262306a36Sopenharmony_civerbs (Set/Get Coefficient Index, Set/Get Processing Coefficient). The node is 8362306a36Sopenharmony_cinamed "Realtek Vendor Registers" in public datasheets' verb listings and, 8462306a36Sopenharmony_ciapart from that, is entirely undocumented. 8562306a36Sopenharmony_ci 8662306a36Sopenharmony_ciThis particular register, exposed at coefficient 0x36 and named in commits from 8762306a36Sopenharmony_ciRealtek, is of note: unlike most registers, which seem to control detailed 8862306a36Sopenharmony_ciamplifier parameters not in scope of the HDA specification, it controls audio 8962306a36Sopenharmony_cirouting which could just as easily have been defined using standard HDA mixer 9062306a36Sopenharmony_ciand selector widgets. 9162306a36Sopenharmony_ci 9262306a36Sopenharmony_ciSpecifically, it selects between two sources for the input pin widget with Node 9362306a36Sopenharmony_ciID (NID) 1Ah: the widget's signal can come either from an audio jack (on my 9462306a36Sopenharmony_cilaptop, a Dell XPS 13 9350, it's the headphone jack, but comments in Realtek 9562306a36Sopenharmony_cicommits indicate that it might be a Line In on some machines) or from the PC 9662306a36Sopenharmony_ciBeep line (which is itself multiplexed between the codec's internal beep 9762306a36Sopenharmony_cigenerator and external PCBEEP pin, depending on if the beep generator is 9862306a36Sopenharmony_cienabled via verbs on NID 01h). Additionally, it can mix (with optional 9962306a36Sopenharmony_ciamplification) that signal onto the 21h and/or 14h output pins. 10062306a36Sopenharmony_ci 10162306a36Sopenharmony_ciThe register's reset value is 0x3717, corresponding to PC Beep on 1Ah that is 10262306a36Sopenharmony_cithen amplified and mixed into both the headphones and the speakers. Not only 10362306a36Sopenharmony_cidoes this violate the HDA specification, which says that "[a vendor defined 10462306a36Sopenharmony_cibeep input pin] connection may be maintained *only* while the Link reset 10562306a36Sopenharmony_ci(**RST#**) is asserted", it means that we cannot ignore the register if we care 10662306a36Sopenharmony_ciabout the input that 1Ah would otherwise expose or if the PCBEEP trace is 10762306a36Sopenharmony_cipoorly shielded and picks up chassis noise (both of which are the case on my 10862306a36Sopenharmony_cimachine). 10962306a36Sopenharmony_ci 11062306a36Sopenharmony_ciUnfortunately, there are lots of ways to get this register configuration wrong. 11162306a36Sopenharmony_ciLinux, it seems, has gone through most of them. For one, the register resets 11262306a36Sopenharmony_ciafter S3 suspend: judging by existing code, this isn't the case for all vendor 11362306a36Sopenharmony_ciregisters, and it's led to some fixes that improve behavior on cold boot but 11462306a36Sopenharmony_cidon't last after suspend. Other fixes have successfully switched the 1Ah input 11562306a36Sopenharmony_ciaway from PC Beep but have failed to disable both loopback paths. On my 11662306a36Sopenharmony_cimachine, this means that the headphone input is amplified and looped back to 11762306a36Sopenharmony_cithe headphone output, which uses the exact same pins! As you might expect, this 11862306a36Sopenharmony_cicauses terrible headphone noise, the character of which is controlled by the 11962306a36Sopenharmony_ci1Ah boost control. (If you've seen instructions online to fix XPS 13 headphone 12062306a36Sopenharmony_cinoise by changing "Headphone Mic Boost" in ALSA, now you know why.) 12162306a36Sopenharmony_ci 12262306a36Sopenharmony_ciThe information here has been obtained through black-box reverse engineering of 12362306a36Sopenharmony_cithe ALC256 codec's behavior and is not guaranteed to be correct. It likely 12462306a36Sopenharmony_cialso applies for the ALC255, ALC257, ALC235, and ALC236, since those codecs 12562306a36Sopenharmony_ciseem to be close relatives of the ALC256. (They all share one initialization 12662306a36Sopenharmony_cifunction.) Additionally, other codecs like the ALC225 and ALC285 also have this 12762306a36Sopenharmony_ciregister, judging by existing fixups in ``patch_realtek.c``, but specific 12862306a36Sopenharmony_cidata (e.g. node IDs, bit positions, pin mappings) for those codecs may differ 12962306a36Sopenharmony_cifrom what I've described here. 130