1*4882a593Smuzhiyun=============================== 2*4882a593SmuzhiyunRealtek PC Beep Hidden Register 3*4882a593Smuzhiyun=============================== 4*4882a593Smuzhiyun 5*4882a593SmuzhiyunThis file documents the "PC Beep Hidden Register", which is present in certain 6*4882a593SmuzhiyunRealtek HDA codecs and controls a muxer and pair of passthrough mixers that can 7*4882a593Smuzhiyunroute audio between pins but aren't themselves exposed as HDA widgets. As far 8*4882a593Smuzhiyunas I can tell, these hidden routes are designed to allow flexible PC Beep output 9*4882a593Smuzhiyunfor codecs that don't have mixer widgets in their output paths. Why it's easier 10*4882a593Smuzhiyunto hide a mixer behind an undocumented vendor register than to just expose it 11*4882a593Smuzhiyunas a widget, I have no idea. 12*4882a593Smuzhiyun 13*4882a593SmuzhiyunRegister Description 14*4882a593Smuzhiyun==================== 15*4882a593Smuzhiyun 16*4882a593SmuzhiyunThe register is accessed via processing coefficient 0x36 on NID 20h. Bits not 17*4882a593Smuzhiyunidentified below have no discernible effect on my machine, a Dell XPS 13 9350:: 18*4882a593Smuzhiyun 19*4882a593Smuzhiyun MSB LSB 20*4882a593Smuzhiyun +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 21*4882a593Smuzhiyun | |h|S|L| | B |R| | Known bits 22*4882a593Smuzhiyun +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+ 23*4882a593Smuzhiyun |0|0|1|1| 0x7 |0|0x0|1| 0x7 | Reset value 24*4882a593Smuzhiyun +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 25*4882a593Smuzhiyun 26*4882a593Smuzhiyun1Ah input select (B): 2 bits 27*4882a593Smuzhiyun When zero, expose the PC Beep line (from the internal beep generator, when 28*4882a593Smuzhiyun enabled with the Set Beep Generation verb on NID 01h, or else from the 29*4882a593Smuzhiyun external PCBEEP pin) on the 1Ah pin node. When nonzero, expose the headphone 30*4882a593Smuzhiyun jack (or possibly Line In on some machines) input instead. If PC Beep is 31*4882a593Smuzhiyun selected, the 1Ah boost control has no effect. 32*4882a593Smuzhiyun 33*4882a593SmuzhiyunAmplify 1Ah loopback, left (L): 1 bit 34*4882a593Smuzhiyun Amplify the left channel of 1Ah before mixing it into outputs as specified 35*4882a593Smuzhiyun by h and S bits. Does not affect the level of 1Ah exposed to other widgets. 36*4882a593Smuzhiyun 37*4882a593SmuzhiyunAmplify 1Ah loopback, right (R): 1 bit 38*4882a593Smuzhiyun Amplify the right channel of 1Ah before mixing it into outputs as specified 39*4882a593Smuzhiyun by h and S bits. Does not affect the level of 1Ah exposed to other widgets. 40*4882a593Smuzhiyun 41*4882a593SmuzhiyunLoopback 1Ah to 21h [active low] (h): 1 bit 42*4882a593Smuzhiyun When zero, mix 1Ah (possibly with amplification, depending on L and R bits) 43*4882a593Smuzhiyun into 21h (headphone jack on my machine). Mixed signal respects the mute 44*4882a593Smuzhiyun setting on 21h. 45*4882a593Smuzhiyun 46*4882a593SmuzhiyunLoopback 1Ah to 14h (S): 1 bit 47*4882a593Smuzhiyun When one, mix 1Ah (possibly with amplification, depending on L and R bits) 48*4882a593Smuzhiyun into 14h (internal speaker on my machine). Mixed signal **ignores** the mute 49*4882a593Smuzhiyun setting on 14h and is present whenever 14h is configured as an output. 50*4882a593Smuzhiyun 51*4882a593SmuzhiyunPath diagrams 52*4882a593Smuzhiyun============= 53*4882a593Smuzhiyun 54*4882a593Smuzhiyun1Ah input selection (DIV is the PC Beep divider set on NID 01h):: 55*4882a593Smuzhiyun 56*4882a593Smuzhiyun <Beep generator> <PCBEEP pin> <Headphone jack> 57*4882a593Smuzhiyun | | | 58*4882a593Smuzhiyun +--DIV--+--!DIV--+ {1Ah boost control} 59*4882a593Smuzhiyun | | 60*4882a593Smuzhiyun +--(b == 0)--+--(b != 0)--+ 61*4882a593Smuzhiyun | 62*4882a593Smuzhiyun >1Ah (Beep/Headphone Mic/Line In)< 63*4882a593Smuzhiyun 64*4882a593SmuzhiyunLoopback of 1Ah to 21h/14h:: 65*4882a593Smuzhiyun 66*4882a593Smuzhiyun <1Ah (Beep/Headphone Mic/Line In)> 67*4882a593Smuzhiyun | 68*4882a593Smuzhiyun {amplify if L/R} 69*4882a593Smuzhiyun | 70*4882a593Smuzhiyun +-----!h-----+-----S-----+ 71*4882a593Smuzhiyun | | 72*4882a593Smuzhiyun {21h mute control} | 73*4882a593Smuzhiyun | | 74*4882a593Smuzhiyun >21h (Headphone)< >14h (Internal Speaker)< 75*4882a593Smuzhiyun 76*4882a593SmuzhiyunBackground 77*4882a593Smuzhiyun========== 78*4882a593Smuzhiyun 79*4882a593SmuzhiyunAll Realtek HDA codecs have a vendor-defined widget with node ID 20h which 80*4882a593Smuzhiyunprovides access to a bank of registers that control various codec functions. 81*4882a593SmuzhiyunRegisters are read and written via the standard HDA processing coefficient 82*4882a593Smuzhiyunverbs (Set/Get Coefficient Index, Set/Get Processing Coefficient). The node is 83*4882a593Smuzhiyunnamed "Realtek Vendor Registers" in public datasheets' verb listings and, 84*4882a593Smuzhiyunapart from that, is entirely undocumented. 85*4882a593Smuzhiyun 86*4882a593SmuzhiyunThis particular register, exposed at coefficient 0x36 and named in commits from 87*4882a593SmuzhiyunRealtek, is of note: unlike most registers, which seem to control detailed 88*4882a593Smuzhiyunamplifier parameters not in scope of the HDA specification, it controls audio 89*4882a593Smuzhiyunrouting which could just as easily have been defined using standard HDA mixer 90*4882a593Smuzhiyunand selector widgets. 91*4882a593Smuzhiyun 92*4882a593SmuzhiyunSpecifically, it selects between two sources for the input pin widget with Node 93*4882a593SmuzhiyunID (NID) 1Ah: the widget's signal can come either from an audio jack (on my 94*4882a593Smuzhiyunlaptop, a Dell XPS 13 9350, it's the headphone jack, but comments in Realtek 95*4882a593Smuzhiyuncommits indicate that it might be a Line In on some machines) or from the PC 96*4882a593SmuzhiyunBeep line (which is itself multiplexed between the codec's internal beep 97*4882a593Smuzhiyungenerator and external PCBEEP pin, depending on if the beep generator is 98*4882a593Smuzhiyunenabled via verbs on NID 01h). Additionally, it can mix (with optional 99*4882a593Smuzhiyunamplification) that signal onto the 21h and/or 14h output pins. 100*4882a593Smuzhiyun 101*4882a593SmuzhiyunThe register's reset value is 0x3717, corresponding to PC Beep on 1Ah that is 102*4882a593Smuzhiyunthen amplified and mixed into both the headphones and the speakers. Not only 103*4882a593Smuzhiyundoes this violate the HDA specification, which says that "[a vendor defined 104*4882a593Smuzhiyunbeep input pin] connection may be maintained *only* while the Link reset 105*4882a593Smuzhiyun(**RST#**) is asserted", it means that we cannot ignore the register if we care 106*4882a593Smuzhiyunabout the input that 1Ah would otherwise expose or if the PCBEEP trace is 107*4882a593Smuzhiyunpoorly shielded and picks up chassis noise (both of which are the case on my 108*4882a593Smuzhiyunmachine). 109*4882a593Smuzhiyun 110*4882a593SmuzhiyunUnfortunately, there are lots of ways to get this register configuration wrong. 111*4882a593SmuzhiyunLinux, it seems, has gone through most of them. For one, the register resets 112*4882a593Smuzhiyunafter S3 suspend: judging by existing code, this isn't the case for all vendor 113*4882a593Smuzhiyunregisters, and it's led to some fixes that improve behavior on cold boot but 114*4882a593Smuzhiyundon't last after suspend. Other fixes have successfully switched the 1Ah input 115*4882a593Smuzhiyunaway from PC Beep but have failed to disable both loopback paths. On my 116*4882a593Smuzhiyunmachine, this means that the headphone input is amplified and looped back to 117*4882a593Smuzhiyunthe headphone output, which uses the exact same pins! As you might expect, this 118*4882a593Smuzhiyuncauses terrible headphone noise, the character of which is controlled by the 119*4882a593Smuzhiyun1Ah boost control. (If you've seen instructions online to fix XPS 13 headphone 120*4882a593Smuzhiyunnoise by changing "Headphone Mic Boost" in ALSA, now you know why.) 121*4882a593Smuzhiyun 122*4882a593SmuzhiyunThe information here has been obtained through black-box reverse engineering of 123*4882a593Smuzhiyunthe ALC256 codec's behavior and is not guaranteed to be correct. It likely 124*4882a593Smuzhiyunalso applies for the ALC255, ALC257, ALC235, and ALC236, since those codecs 125*4882a593Smuzhiyunseem to be close relatives of the ALC256. (They all share one initialization 126*4882a593Smuzhiyunfunction.) Additionally, other codecs like the ALC225 and ALC285 also have this 127*4882a593Smuzhiyunregister, judging by existing fixups in ``patch_realtek.c``, but specific 128*4882a593Smuzhiyundata (e.g. node IDs, bit positions, pin mappings) for those codecs may differ 129*4882a593Smuzhiyunfrom what I've described here. 130