[{"data":1,"prerenderedAt":3316},["ShallowReactive",2],{"\u002Farticles\u002Fubuntu-huawei-matebook-sn6140-headphone-speaker-fix":3},{"id":4,"title":5,"body":6,"description":3302,"draft":3303,"extension":3304,"meta":3305,"navigation":269,"path":3306,"publishedAt":3307,"seo":3308,"stem":3309,"tags":3310,"updatedAt":3314,"__hash__":3315},"articles\u002Farticles\u002Fubuntu-huawei-matebook-sn6140-headphone-speaker-fix.md","Ubuntu \u002F Huawei MateBook 16s 有线耳机与扬声器同时出声问题排查与修复",{"type":7,"value":8,"toc":3292},"minimark",[9,29,32,35,40,43,46,56,59,65,71,81,84,90,93,99,101,106,109,124,127,133,136,139,145,148,154,157,163,166,169,175,178,184,187,193,196,202,205,211,214,217,223,226,231,233,237,240,440,443,449,452,458,460,464,467,486,489,495,498,504,507,523,525,531,533,539,542,565,567,573,575,579,582,588,594,597,600,606,609,615,618,621,627,630,635,638,640,644,655,674,677,693,696,702,707,709,713,716,719,743,746,752,755,761,764,773,776,782,789,792,794,798,801,884,887,893,896,902,905,907,911,914,989,992,998,1000,1006,1008,1010,1014,1017,1020,1041,1044,1050,1053,1071,1073,1079,1082,1088,1091,1097,1100,1106,1109,1115,1118,1120,1124,1127,1133,1136,1142,1145,1151,1154,1156,1160,1162,2006,2008,2012,2014,2098,2101,2116,2119,2139,2141,2145,2147,2166,2169,2175,2178,2201,2204,2210,2213,2230,2233,2239,2241,2245,2248,2251,2257,2260,2263,2269,2272,2275,2278,2281,2287,2290,2296,2298,2302,2305,2311,2314,2320,2323,2329,2332,2335,2341,2344,2347,2352,2355,2357,2361,2364,2427,2430,2434,2508,2511,2585,2587,2591,2594,2701,2707,2713,2716,2718,2722,2725,2745,2750,2753,2756,2762,2769,2772,2778,2781,2784,2804,2807,2809,2813,2816,2819,2837,2840,2855,2858,2871,2874,2886,2889,2901,2904,2906,2910,2913,3128,3131,3170,3173,3191,3193,3197,3200,3206,3209,3215,3217,3220,3223,3229,3232,3235,3281,3288],[10,11,12],"blockquote",{},[13,14,15,16,20,21,24,25,28],"p",{},"适用场景：Ubuntu 下插入 3.5 mm 有线耳机后，耳机正常出声，但笔记本内置扬声器仍然同时播放；在系统设置中选择 ",[17,18,19],"code",{},"Headphones","、在 ",[17,22,23],{},"alsamixer"," 中启用 ",[17,26,27],{},"Auto-Mute"," 后仍无法解决。",[13,30,31],{},"本文记录一次在 Huawei MateBook 16s 类设备上的完整排障过程，包括问题定位、硬件信息确认、HDA Codec 路由测试，以及最终通过 systemd 服务实现自动切换耳机 \u002F 扬声器。",[33,34],"hr",{},[36,37,39],"h2",{"id":38},"_1-问题现象","1. 问题现象",[13,41,42],{},"系统可以正常识别有线耳机。",[13,44,45],{},"在：",[47,48,54],"pre",{"className":49,"code":51,"language":52,"meta":53},[50],"language-text","Settings -> Sound -> Output\n","text","",[17,55,51],{"__ignoreMap":53},[13,57,58],{},"中可以看到：",[47,60,63],{"className":61,"code":62,"language":52,"meta":53},[50],"Speaker\nHeadphones\nHDMI \u002F DisplayPort\n",[17,64,62],{"__ignoreMap":53},[13,66,67,68,70],{},"选择 ",[17,69,19],{}," 后：",[72,73,74,78],"ul",{},[75,76,77],"li",{},"耳机有声音；",[75,79,80],{},"笔记本内置扬声器仍然有声音。",[13,82,83],{},"也就是说，实际状态类似：",[47,85,88],{"className":86,"code":87,"language":52,"meta":53},[50],"应用程序\n   ↓\nPipeWire\n   ↓\nHeadphones\n   ↓\nHDA Codec\n   ├── Headphone   有声音\n   └── Speaker     仍然有声音\n",[17,89,87],{"__ignoreMap":53},[13,91,92],{},"正常行为应该是：",[47,94,97],{"className":95,"code":96,"language":52,"meta":53},[50],"插入耳机\n   ├── Headphone   ON\n   └── Speaker     OFF\n",[17,98,96],{"__ignoreMap":53},[33,100],{},[102,103,105],"h1",{"id":104},"_2-第一阶段检查-auto-mute","2. 第一阶段：检查 Auto-Mute",[13,107,108],{},"首先进入 ALSA Mixer：",[47,110,114],{"className":111,"code":112,"language":113,"meta":53,"style":53},"language-bash shiki shiki-themes github-light github-dark","alsamixer\n","bash",[17,115,116],{"__ignoreMap":53},[117,118,121],"span",{"class":119,"line":120},"line",1,[117,122,112],{"class":123},"sScJk",[13,125,126],{},"如果默认界面顶部显示：",[47,128,131],{"className":129,"code":130,"language":52,"meta":53},[50],"Card: PipeWire\nChip: PipeWire\n",[17,132,130],{"__ignoreMap":53},[13,134,135],{},"说明当前看到的是 PipeWire 虚拟 Mixer，而不是实际声卡。",[13,137,138],{},"按：",[47,140,143],{"className":141,"code":142,"language":52,"meta":53},[50],"F6\n",[17,144,142],{"__ignoreMap":53},[13,146,147],{},"选择：",[47,149,152],{"className":150,"code":151,"language":52,"meta":53},[50],"default:0  sof-hda-dsp\n",[17,153,151],{"__ignoreMap":53},[13,155,156],{},"然后按：",[47,158,161],{"className":159,"code":160,"language":52,"meta":53},[50],"F5\n",[17,162,160],{"__ignoreMap":53},[13,164,165],{},"显示所有控件。",[13,167,168],{},"找到：",[47,170,173],{"className":171,"code":172,"language":52,"meta":53},[50],"Auto-Mute Mode\n",[17,174,172],{"__ignoreMap":53},[13,176,177],{},"将：",[47,179,182],{"className":180,"code":181,"language":52,"meta":53},[50],"Disabled\n",[17,183,181],{"__ignoreMap":53},[13,185,186],{},"改为：",[47,188,191],{"className":189,"code":190,"language":52,"meta":53},[50],"Enabled\n",[17,192,190],{"__ignoreMap":53},[13,194,195],{},"此时在本机上可以看到：",[47,197,200],{"className":198,"code":199,"language":52,"meta":53},[50],"Auto-Mute = Enabled\nHeadphone = OO\nSpeaker   = MM\n",[17,201,199],{"__ignoreMap":53},[13,203,204],{},"其中：",[47,206,209],{"className":207,"code":208,"language":52,"meta":53},[50],"OO = 未静音\nMM = 已静音\n",[17,210,208],{"__ignoreMap":53},[13,212,213],{},"按理来说，此时扬声器应该已经关闭。",[13,215,216],{},"但实际测试发现：",[47,218,221],{"className":219,"code":220,"language":52,"meta":53},[50],"alsamixer:\nSpeaker = MM\n\n实际：\n笔记本扬声器仍然在出声\n",[17,222,220],{"__ignoreMap":53},[13,224,225],{},"因此可以判断：",[10,227,228],{},[13,229,230],{},"问题已经不是普通的 PipeWire 输出选择或 ALSA Auto-Mute 设置，而更可能发生在更底层的 HDA Codec 硬件路由。",[33,232],{},[102,234,236],{"id":235},"_3-获取硬件和-codec-信息","3. 获取硬件和 Codec 信息",[13,238,239],{},"为了继续定位，执行：",[47,241,243],{"className":111,"code":242,"language":113,"meta":53,"style":53},"echo \"===== Kernel =====\"\nuname -r\n\necho\necho \"===== Machine =====\"\ncat \u002Fsys\u002Fclass\u002Fdmi\u002Fid\u002Fproduct_name\ncat \u002Fsys\u002Fclass\u002Fdmi\u002Fid\u002Fboard_name 2>\u002Fdev\u002Fnull\n\necho\necho \"===== Audio PCI =====\"\nlspci -nnvv -s 00:1f.3 | grep -E 'Audio|Multimedia|Subsystem'\n\necho\necho \"===== HDA codecs =====\"\nfor f in \u002Fproc\u002Fasound\u002Fcard*\u002Fcodec#*; do\n    echo \"---- $f ----\"\n    grep -E '^Codec:|^Subsystem Id:' \"$f\"\ndone\n",[17,244,245,255,264,271,277,285,294,309,314,319,327,354,359,364,372,400,415,434],{"__ignoreMap":53},[117,246,247,251],{"class":119,"line":120},[117,248,250],{"class":249},"sj4cs","echo",[117,252,254],{"class":253},"sZZnC"," \"===== Kernel =====\"\n",[117,256,258,261],{"class":119,"line":257},2,[117,259,260],{"class":123},"uname",[117,262,263],{"class":249}," -r\n",[117,265,267],{"class":119,"line":266},3,[117,268,270],{"emptyLinePlaceholder":269},true,"\n",[117,272,274],{"class":119,"line":273},4,[117,275,276],{"class":249},"echo\n",[117,278,280,282],{"class":119,"line":279},5,[117,281,250],{"class":249},[117,283,284],{"class":253}," \"===== Machine =====\"\n",[117,286,288,291],{"class":119,"line":287},6,[117,289,290],{"class":123},"cat",[117,292,293],{"class":253}," \u002Fsys\u002Fclass\u002Fdmi\u002Fid\u002Fproduct_name\n",[117,295,297,299,302,306],{"class":119,"line":296},7,[117,298,290],{"class":123},[117,300,301],{"class":253}," \u002Fsys\u002Fclass\u002Fdmi\u002Fid\u002Fboard_name",[117,303,305],{"class":304},"szBVR"," 2>",[117,307,308],{"class":253},"\u002Fdev\u002Fnull\n",[117,310,312],{"class":119,"line":311},8,[117,313,270],{"emptyLinePlaceholder":269},[117,315,317],{"class":119,"line":316},9,[117,318,276],{"class":249},[117,320,322,324],{"class":119,"line":321},10,[117,323,250],{"class":249},[117,325,326],{"class":253}," \"===== Audio PCI =====\"\n",[117,328,330,333,336,339,342,345,348,351],{"class":119,"line":329},11,[117,331,332],{"class":123},"lspci",[117,334,335],{"class":249}," -nnvv",[117,337,338],{"class":249}," -s",[117,340,341],{"class":253}," 00:1f.3",[117,343,344],{"class":304}," |",[117,346,347],{"class":123}," grep",[117,349,350],{"class":249}," -E",[117,352,353],{"class":253}," 'Audio|Multimedia|Subsystem'\n",[117,355,357],{"class":119,"line":356},12,[117,358,270],{"emptyLinePlaceholder":269},[117,360,362],{"class":119,"line":361},13,[117,363,276],{"class":249},[117,365,367,369],{"class":119,"line":366},14,[117,368,250],{"class":249},[117,370,371],{"class":253}," \"===== HDA codecs =====\"\n",[117,373,375,378,382,385,388,391,394,397],{"class":119,"line":374},15,[117,376,377],{"class":304},"for",[117,379,381],{"class":380},"sVt8B"," f ",[117,383,384],{"class":304},"in",[117,386,387],{"class":253}," \u002Fproc\u002Fasound\u002Fcard*\u002Fcodec",[117,389,390],{"class":380},"#",[117,392,393],{"class":304},"*",[117,395,396],{"class":380},"; ",[117,398,399],{"class":304},"do\n",[117,401,403,406,409,412],{"class":119,"line":402},16,[117,404,405],{"class":249},"    echo",[117,407,408],{"class":253}," \"---- ",[117,410,411],{"class":380},"$f",[117,413,414],{"class":253}," ----\"\n",[117,416,418,421,423,426,429,431],{"class":119,"line":417},17,[117,419,420],{"class":123},"    grep",[117,422,350],{"class":249},[117,424,425],{"class":253}," '^Codec:|^Subsystem Id:'",[117,427,428],{"class":253}," \"",[117,430,411],{"class":380},[117,432,433],{"class":253},"\"\n",[117,435,437],{"class":119,"line":436},18,[117,438,439],{"class":304},"done\n",[13,441,442],{},"本机结果：",[47,444,447],{"className":445,"code":446,"language":52,"meta":53},[50],"===== Kernel =====\n7.0.0-34-generic\n\n===== Machine =====\nCREF-XX\nCREF-XX-PCB\n\n===== Audio PCI =====\n00:1f.3 Multimedia audio controller:\nIntel Corporation Alder Lake PCH-P High Definition Audio Controller [8086:51c8]\n\nSubsystem:\nHuawei Technologies Co., Ltd. Device [19e5:3e5f]\n\n===== HDA codecs =====\nCodec: Conexant SN6140\nSubsystem Id: 0x19e53281\n\nCodec: Intel Alderlake-P HDMI\nSubsystem Id: 0x80860101\n",[17,448,446],{"__ignoreMap":53},[13,450,451],{},"因此实际音频硬件为：",[47,453,456],{"className":454,"code":455,"language":52,"meta":53},[50],"CPU \u002F PCH      : Intel Alder Lake PCH-P\nALSA card      : sof-hda-dsp\nCodec          : Conexant SN6140\nCodec Subsystem: 0x19e53281\nVendor ID      : 0x14f11f87\n",[17,457,455],{"__ignoreMap":53},[33,459],{},[102,461,463],{"id":462},"_4-查看-hda-codec-节点","4. 查看 HDA Codec 节点",[13,465,466],{},"继续检查关键 Pin：",[47,468,470],{"className":111,"code":469,"language":113,"meta":53,"style":53},"grep -A20 'Node 0x16' \u002Fproc\u002Fasound\u002Fcard0\u002Fcodec#0\n",[17,471,472],{"__ignoreMap":53},[117,473,474,477,480,483],{"class":119,"line":120},[117,475,476],{"class":123},"grep",[117,478,479],{"class":249}," -A20",[117,481,482],{"class":253}," 'Node 0x16'",[117,484,485],{"class":253}," \u002Fproc\u002Fasound\u002Fcard0\u002Fcodec#0\n",[13,487,488],{},"得到：",[47,490,493],{"className":491,"code":492,"language":52,"meta":53},[50],"Node 0x16 [Pin Complex]\nPincap 0x0001001c: OUT HP EAPD Detect\nEAPD 0x2: EAPD\n\nPin Default 0x03211040:\n[Jack] HP Out at Ext Left\n\nPin-ctls: 0xc0: OUT HP\n\nConnection: 2\n   0x10* 0x11\n",[17,494,492],{"__ignoreMap":53},[13,496,497],{},"说明：",[47,499,502],{"className":500,"code":501,"language":52,"meta":53},[50],"0x16 = 外接耳机 Pin\n",[17,503,501],{"__ignoreMap":53},[13,505,506],{},"再检查：",[47,508,510],{"className":111,"code":509,"language":113,"meta":53,"style":53},"grep -A20 'Node 0x17' \u002Fproc\u002Fasound\u002Fcard0\u002Fcodec#0\n",[17,511,512],{"__ignoreMap":53},[117,513,514,516,518,521],{"class":119,"line":120},[117,515,476],{"class":123},[117,517,479],{"class":249},[117,519,520],{"class":253}," 'Node 0x17'",[117,522,485],{"class":253},[13,524,488],{},[47,526,529],{"className":527,"code":528,"language":52,"meta":53},[50],"Node 0x17 [Pin Complex]\nPincap 0x00010010: OUT EAPD\n\nEAPD 0x2: EAPD\n\nPin Default 0x91170110:\n[Fixed] Speaker at Int Rear\n\nConnection: 2\n   0x10 0x11*\n",[17,530,528],{"__ignoreMap":53},[13,532,497],{},[47,534,537],{"className":535,"code":536,"language":52,"meta":53},[50],"0x17 = 内置扬声器 Pin\n",[17,538,536],{"__ignoreMap":53},[13,540,541],{},"同时查看 GPIO：",[47,543,545],{"className":111,"code":544,"language":113,"meta":53,"style":53},"grep -i -A10 -B2 'GPIO' \u002Fproc\u002Fasound\u002Fcard0\u002Fcodec#0\n",[17,546,547],{"__ignoreMap":53},[117,548,549,551,554,557,560,563],{"class":119,"line":120},[117,550,476],{"class":123},[117,552,553],{"class":249}," -i",[117,555,556],{"class":249}," -A10",[117,558,559],{"class":249}," -B2",[117,561,562],{"class":253}," 'GPIO'",[117,564,485],{"class":253},[13,566,204],{},[47,568,571],{"className":569,"code":570,"language":52,"meta":53},[50],"GPIO: io=5\n\nIO[0]: enable=1, dir=1, data=1\nIO[1]: enable=1, dir=1, data=0\nIO[4]: enable=1, dir=0, data=0\n",[17,572,570],{"__ignoreMap":53},[33,574],{},[102,576,578],{"id":577},"_5-为什么-speaker-已经是-mm物理扬声器仍然响","5. 为什么 Speaker 已经是 MM，物理扬声器仍然响？",[13,580,581],{},"这一步是整个排障的关键。",[13,583,584,585,587],{},"在 ",[17,586,23],{}," 中：",[47,589,592],{"className":590,"code":591,"language":52,"meta":53},[50],"Speaker = MM\n",[17,593,591],{"__ignoreMap":53},[13,595,596],{},"只能说明 ALSA 暴露出来的 Mixer 控件处于静音状态。",[13,598,599],{},"但这台机器上，真正决定物理扬声器是否工作的还包括：",[47,601,604],{"className":602,"code":603,"language":52,"meta":53},[50],"CONNECT_SEL\nEAPD\nGPIO\n",[17,605,603],{"__ignoreMap":53},[13,607,608],{},"其中 EAPD 可以理解为：",[47,610,613],{"className":611,"code":612,"language":52,"meta":53},[50],"External Amplifier Power Down\n",[17,614,612],{"__ignoreMap":53},[13,616,617],{},"也就是外部功放控制。",[13,619,620],{},"在耳机插入后，我们观察到：",[47,622,625],{"className":623,"code":624,"language":52,"meta":53},[50],"Node 0x17:\nEAPD 0x2: EAPD\n",[17,626,624],{"__ignoreMap":53},[13,628,629],{},"也就是说：",[10,631,632],{},[13,633,634],{},"虽然 ALSA Mixer 已经认为 Speaker 被静音，但扬声器功放仍然处于启用状态。",[13,636,637],{},"因此物理扬声器仍然会播放。",[33,639],{},[102,641,643],{"id":642},"_6-安装-hda-verb","6. 安装 hda-verb",[13,645,646,647,650,651,654],{},"Ubuntu 可以通过 ",[17,648,649],{},"alsa-tools"," 提供 ",[17,652,653],{},"hda-verb","：",[47,656,658],{"className":111,"code":657,"language":113,"meta":53,"style":53},"sudo apt install alsa-tools\n",[17,659,660],{"__ignoreMap":53},[117,661,662,665,668,671],{"class":119,"line":120},[117,663,664],{"class":123},"sudo",[117,666,667],{"class":253}," apt",[117,669,670],{"class":253}," install",[117,672,673],{"class":253}," alsa-tools\n",[13,675,676],{},"检查：",[47,678,680],{"className":111,"code":679,"language":113,"meta":53,"style":53},"command -v hda-verb\n",[17,681,682],{"__ignoreMap":53},[117,683,684,687,690],{"class":119,"line":120},[117,685,686],{"class":249},"command",[117,688,689],{"class":249}," -v",[117,691,692],{"class":253}," hda-verb\n",[13,694,695],{},"正常应输出类似：",[47,697,700],{"className":698,"code":699,"language":52,"meta":53},[50],"\u002Fusr\u002Fbin\u002Fhda-verb\n",[17,701,699],{"__ignoreMap":53},[13,703,704,706],{},[17,705,653],{}," 可以直接向 HDA Codec 发送 Verb，用于读取或修改 Codec 节点状态。",[33,708],{},[102,710,712],{"id":711},"_7-最小化测试关闭扬声器-eapd","7. 最小化测试：关闭扬声器 EAPD",[13,714,715],{},"保持耳机插入，并播放音频。",[13,717,718],{},"执行：",[47,720,722],{"className":111,"code":721,"language":113,"meta":53,"style":53},"sudo hda-verb \u002Fdev\u002Fsnd\u002FhwC0D0 0x17 0x70c 0x0\n",[17,723,724],{"__ignoreMap":53},[117,725,726,728,731,734,737,740],{"class":119,"line":120},[117,727,664],{"class":123},[117,729,730],{"class":253}," hda-verb",[117,732,733],{"class":253}," \u002Fdev\u002Fsnd\u002FhwC0D0",[117,735,736],{"class":249}," 0x17",[117,738,739],{"class":249}," 0x70c",[117,741,742],{"class":249}," 0x0\n",[13,744,745],{},"本机输出：",[47,747,750],{"className":748,"code":749,"language":52,"meta":53},[50],"nid = 0x17, verb = 0x70c, param = 0x0\nvalue = 0x0\n",[17,751,749],{"__ignoreMap":53},[13,753,754],{},"执行后：",[47,756,759],{"className":757,"code":758,"language":52,"meta":53},[50],"耳机：正常有声音\n扬声器：立即停止出声\n",[17,760,758],{"__ignoreMap":53},[13,762,763],{},"这一步几乎可以直接确认：",[10,765,766],{},[13,767,768,769,772],{},"问题的核心就是 Speaker 节点 ",[17,770,771],{},"0x17"," 的 EAPD 没有随着耳机插入被正确关闭。",[13,774,775],{},"但此时如果拔掉耳机：",[47,777,780],{"className":778,"code":779,"language":52,"meta":53},[50],"耳机     已拔出\nSpeaker  没有声音\n",[17,781,779],{"__ignoreMap":53},[13,783,784,785,788],{},"这是因为我们只是手动把 EAPD 改成了 ",[17,786,787],{},"0","，系统并不会自动重新打开它。",[13,790,791],{},"所以还需要实现完整的 Speaker \u002F Headphone 路由切换。",[33,793],{},[102,795,797],{"id":796},"_8-手动验证完整-speaker-模式","8. 手动验证完整 Speaker 模式",[13,799,800],{},"拔掉耳机后执行：",[47,802,804],{"className":111,"code":803,"language":113,"meta":53,"style":53},"sudo hda-verb \u002Fdev\u002Fsnd\u002FhwC0D0 0x01 0x717 0x2\nsudo hda-verb \u002Fdev\u002Fsnd\u002FhwC0D0 0x01 0x716 0x2\nsudo hda-verb \u002Fdev\u002Fsnd\u002FhwC0D0 0x16 0x701 0x1\nsudo hda-verb \u002Fdev\u002Fsnd\u002FhwC0D0 0x17 0x70c 0x2\nsudo hda-verb \u002Fdev\u002Fsnd\u002FhwC0D0 0x01 0x715 0x2\n",[17,805,806,823,838,855,869],{"__ignoreMap":53},[117,807,808,810,812,814,817,820],{"class":119,"line":120},[117,809,664],{"class":123},[117,811,730],{"class":253},[117,813,733],{"class":253},[117,815,816],{"class":249}," 0x01",[117,818,819],{"class":249}," 0x717",[117,821,822],{"class":249}," 0x2\n",[117,824,825,827,829,831,833,836],{"class":119,"line":257},[117,826,664],{"class":123},[117,828,730],{"class":253},[117,830,733],{"class":253},[117,832,816],{"class":249},[117,834,835],{"class":249}," 0x716",[117,837,822],{"class":249},[117,839,840,842,844,846,849,852],{"class":119,"line":266},[117,841,664],{"class":123},[117,843,730],{"class":253},[117,845,733],{"class":253},[117,847,848],{"class":249}," 0x16",[117,850,851],{"class":249}," 0x701",[117,853,854],{"class":249}," 0x1\n",[117,856,857,859,861,863,865,867],{"class":119,"line":273},[117,858,664],{"class":123},[117,860,730],{"class":253},[117,862,733],{"class":253},[117,864,736],{"class":249},[117,866,739],{"class":249},[117,868,822],{"class":249},[117,870,871,873,875,877,879,882],{"class":119,"line":279},[117,872,664],{"class":123},[117,874,730],{"class":253},[117,876,733],{"class":253},[117,878,816],{"class":249},[117,880,881],{"class":249}," 0x715",[117,883,822],{"class":249},[13,885,886],{},"对应含义：",[47,888,891],{"className":889,"code":890,"language":52,"meta":53},[50],"GPIO direction = 0x2\nGPIO mask      = 0x2\nCONNECT_SEL    = 1\nSpeaker EAPD   = 2\nGPIO data      = 0x2\n",[17,892,890],{"__ignoreMap":53},[13,894,895],{},"测试结果：",[47,897,900],{"className":898,"code":899,"language":52,"meta":53},[50],"只从笔记本扬声器播放\n",[17,901,899],{"__ignoreMap":53},[13,903,904],{},"符合预期。",[33,906],{},[102,908,910],{"id":909},"_9-手动验证完整-headphone-模式","9. 手动验证完整 Headphone 模式",[13,912,913],{},"插入耳机后执行：",[47,915,917],{"className":111,"code":916,"language":113,"meta":53,"style":53},"sudo hda-verb \u002Fdev\u002Fsnd\u002FhwC0D0 0x01 0x717 0x2\nsudo hda-verb \u002Fdev\u002Fsnd\u002FhwC0D0 0x01 0x716 0x2\nsudo hda-verb \u002Fdev\u002Fsnd\u002FhwC0D0 0x16 0x701 0x0\nsudo hda-verb \u002Fdev\u002Fsnd\u002FhwC0D0 0x17 0x70c 0x0\nsudo hda-verb \u002Fdev\u002Fsnd\u002FhwC0D0 0x01 0x715 0x0\n",[17,918,919,933,947,961,975],{"__ignoreMap":53},[117,920,921,923,925,927,929,931],{"class":119,"line":120},[117,922,664],{"class":123},[117,924,730],{"class":253},[117,926,733],{"class":253},[117,928,816],{"class":249},[117,930,819],{"class":249},[117,932,822],{"class":249},[117,934,935,937,939,941,943,945],{"class":119,"line":257},[117,936,664],{"class":123},[117,938,730],{"class":253},[117,940,733],{"class":253},[117,942,816],{"class":249},[117,944,835],{"class":249},[117,946,822],{"class":249},[117,948,949,951,953,955,957,959],{"class":119,"line":266},[117,950,664],{"class":123},[117,952,730],{"class":253},[117,954,733],{"class":253},[117,956,848],{"class":249},[117,958,851],{"class":249},[117,960,742],{"class":249},[117,962,963,965,967,969,971,973],{"class":119,"line":273},[117,964,664],{"class":123},[117,966,730],{"class":253},[117,968,733],{"class":253},[117,970,736],{"class":249},[117,972,739],{"class":249},[117,974,742],{"class":249},[117,976,977,979,981,983,985,987],{"class":119,"line":279},[117,978,664],{"class":123},[117,980,730],{"class":253},[117,982,733],{"class":253},[117,984,816],{"class":249},[117,986,881],{"class":249},[117,988,742],{"class":249},[13,990,991],{},"对应：",[47,993,996],{"className":994,"code":995,"language":52,"meta":53},[50],"GPIO direction = 0x2\nGPIO mask      = 0x2\nCONNECT_SEL    = 0\nSpeaker EAPD   = 0\nGPIO data      = 0\n",[17,997,995],{"__ignoreMap":53},[13,999,895],{},[47,1001,1004],{"className":1002,"code":1003,"language":52,"meta":53},[50],"耳机有声音\n笔记本扬声器无声音\n",[17,1005,1003],{"__ignoreMap":53},[13,1007,904],{},[33,1009],{},[102,1011,1013],{"id":1012},"_10-验证耳机插拔检测","10. 验证耳机插拔检测",[13,1015,1016],{},"下一步检查 HDA Codec 能否准确知道耳机是否插入。",[13,1018,1019],{},"耳机插着时：",[47,1021,1023],{"className":111,"code":1022,"language":113,"meta":53,"style":53},"sudo hda-verb \u002Fdev\u002Fsnd\u002FhwC0D0 0x16 0xf09 0\n",[17,1024,1025],{"__ignoreMap":53},[117,1026,1027,1029,1031,1033,1035,1038],{"class":119,"line":120},[117,1028,664],{"class":123},[117,1030,730],{"class":253},[117,1032,733],{"class":253},[117,1034,848],{"class":249},[117,1036,1037],{"class":249}," 0xf09",[117,1039,1040],{"class":249}," 0\n",[13,1042,1043],{},"输出：",[47,1045,1048],{"className":1046,"code":1047,"language":52,"meta":53},[50],"nid = 0x16, verb = 0xf09, param = 0x0\nvalue = 0x80000000\n",[17,1049,1047],{"__ignoreMap":53},[13,1051,1052],{},"拔掉耳机：",[47,1054,1055],{"className":111,"code":1022,"language":113,"meta":53,"style":53},[17,1056,1057],{"__ignoreMap":53},[117,1058,1059,1061,1063,1065,1067,1069],{"class":119,"line":120},[117,1060,664],{"class":123},[117,1062,730],{"class":253},[117,1064,733],{"class":253},[117,1066,848],{"class":249},[117,1068,1037],{"class":249},[117,1070,1040],{"class":249},[13,1072,1043],{},[47,1074,1077],{"className":1075,"code":1076,"language":52,"meta":53},[50],"nid = 0x16, verb = 0xf09, param = 0x0\nvalue = 0x0\n",[17,1078,1076],{"__ignoreMap":53},[13,1080,1081],{},"Linux HDA 定义中：",[47,1083,1086],{"className":1084,"code":1085,"language":52,"meta":53},[50],"0xf09 = GET_PIN_SENSE\n",[17,1087,1085],{"__ignoreMap":53},[13,1089,1090],{},"其 bit 31：",[47,1092,1095],{"className":1093,"code":1094,"language":52,"meta":53},[50],"0x80000000\n",[17,1096,1094],{"__ignoreMap":53},[13,1098,1099],{},"表示：",[47,1101,1104],{"className":1102,"code":1103,"language":52,"meta":53},[50],"Presence Detect = 1\n",[17,1105,1103],{"__ignoreMap":53},[13,1107,1108],{},"因此：",[47,1110,1113],{"className":1111,"code":1112,"language":52,"meta":53},[50],"value & 0x80000000 != 0\n    → 耳机已插入\n\nvalue & 0x80000000 == 0\n    → 耳机未插入\n",[17,1114,1112],{"__ignoreMap":53},[13,1116,1117],{},"这意味着自动切换所需的检测条件已经完全具备。",[33,1119],{},[102,1121,1123],{"id":1122},"_11-最终自动修复方案","11. 最终自动修复方案",[13,1125,1126],{},"最终目标：",[47,1128,1131],{"className":1129,"code":1130,"language":52,"meta":53},[50],"检测 0x16 Pin Sense\n          │\n          ├── 有耳机\n          │      ↓\n          │   Headphone Mode\n          │\n          └── 无耳机\n                 ↓\n              Speaker Mode\n",[17,1132,1130],{"__ignoreMap":53},[13,1134,1135],{},"同时，为避免 ALSA card 编号发生变化，脚本不固定依赖：",[47,1137,1140],{"className":1138,"code":1139,"language":52,"meta":53},[50],"\u002Fdev\u002Fsnd\u002FhwC0D0\n",[17,1141,1139],{"__ignoreMap":53},[13,1143,1144],{},"而是根据：",[47,1146,1149],{"className":1147,"code":1148,"language":52,"meta":53},[50],"Vendor Id:    0x14f11f87\nSubsystem Id: 0x19e53281\n",[17,1150,1148],{"__ignoreMap":53},[13,1152,1153],{},"自动寻找实际 HDA 设备。",[33,1155],{},[102,1157,1159],{"id":1158},"_12-创建自动修复脚本","12. 创建自动修复脚本",[13,1161,718],{},[47,1163,1165],{"className":111,"code":1164,"language":113,"meta":53,"style":53},"sudo tee \u002Fusr\u002Flocal\u002Fsbin\u002Fhuawei-sn6140-audio-fix >\u002Fdev\u002Fnull \u003C\u003C'EOF'\n#!\u002Fusr\u002Fbin\u002Fenv bash\n\nset -u\n\nHDA_VERB=\"\u002Fusr\u002Fbin\u002Fhda-verb\"\n\n# 仅允许当前验证过的 Codec 运行。\nVENDOR_ID=\"0x14f11f87\"\nSUBSYSTEM_ID=\"0x19e53281\"\n\nPOLL_INTERVAL=1\nREFRESH_INTERVAL=10\n\nfind_hda_device() {\n    local codec card addr dev\n\n    for codec in \u002Fproc\u002Fasound\u002Fcard*\u002Fcodec#*; do\n        [[ -r \"$codec\" ]] || continue\n\n        grep -qx \"Vendor Id: $VENDOR_ID\" \"$codec\" || continue\n        grep -qx \"Subsystem Id: $SUBSYSTEM_ID\" \"$codec\" || continue\n\n        card=\"${codec#\u002Fproc\u002Fasound\u002Fcard}\"\n        card=\"${card%%\u002F*}\"\n\n        addr=\"$(awk '\u002F^Address:\u002F {print $2; exit}' \"$codec\")\"\n\n        [[ \"$card\" =~ ^[0-9]+$ ]] || continue\n        [[ \"$addr\" =~ ^[0-9]+$ ]] || continue\n\n        dev=\"\u002Fdev\u002Fsnd\u002FhwC${card}D${addr}\"\n\n        if [[ -e \"$dev\" ]]; then\n            printf '%s\\n' \"$dev\"\n            return 0\n        fi\n    done\n\n    return 1\n}\n\nverb() {\n    \"$HDA_VERB\" \"$DEV\" \"$1\" \"$2\" \"$3\" >\u002Fdev\u002Fnull 2>&1\n}\n\nset_speaker_mode() {\n    verb 0x01 0x717 0x2 &&\n    verb 0x01 0x716 0x2 &&\n    verb 0x16 0x701 0x1 &&\n    verb 0x17 0x70c 0x2 &&\n    verb 0x01 0x715 0x2\n}\n\nset_headphone_mode() {\n    verb 0x01 0x717 0x2 &&\n    verb 0x01 0x716 0x2 &&\n    verb 0x16 0x701 0x0 &&\n    verb 0x17 0x70c 0x0 &&\n    verb 0x01 0x715 0x0\n}\n\nget_mode() {\n    local output value\n\n    output=\"$(\"$HDA_VERB\" \"$DEV\" 0x16 0xf09 0 2>\u002Fdev\u002Fnull)\" || return 1\n\n    value=\"$(awk '\u002Fvalue =\u002F {print $3; exit}' \u003C\u003C\u003C\"$output\")\"\n\n    [[ \"$value\" =~ ^0x[0-9a-fA-F]+$ ]] || return 1\n\n    if (( value & 0x80000000 )); then\n        printf '%s\\n' \"headphone\"\n    else\n        printf '%s\\n' \"speaker\"\n    fi\n}\n\nif [[ ! -x \"$HDA_VERB\" ]]; then\n    echo \"hda-verb not found: $HDA_VERB\" >&2\n    exit 1\nfi\n\nDEV=\"\"\nPREVIOUS_MODE=\"\"\nREFRESH_COUNTER=0\n\nwhile true; do\n\n    # 如果设备还没找到，或者设备在休眠恢复后重新编号，则重新扫描。\n    if [[ -z \"$DEV\" || ! -e \"$DEV\" ]]; then\n        DEV=\"$(find_hda_device || true)\"\n\n        if [[ -z \"$DEV\" ]]; then\n            sleep 2\n            continue\n        fi\n\n        echo \"Huawei SN6140 codec found: $DEV\"\n        PREVIOUS_MODE=\"\"\n        REFRESH_COUNTER=0\n    fi\n\n    MODE=\"$(get_mode || true)\"\n\n    if [[ -z \"$MODE\" ]]; then\n        DEV=\"\"\n        PREVIOUS_MODE=\"\"\n        sleep 2\n        continue\n    fi\n\n    REFRESH_COUNTER=$((REFRESH_COUNTER + 1))\n\n    # 状态变化时立即设置；\n    # 同时每隔一段时间重新应用，避免 SOF \u002F runtime PM 恢复后寄存器被重置。\n    if [[ \"$MODE\" != \"$PREVIOUS_MODE\" ]] ||\n       (( REFRESH_COUNTER >= REFRESH_INTERVAL )); then\n\n        if [[ \"$MODE\" == \"headphone\" ]]; then\n            if ! set_headphone_mode; then\n                DEV=\"\"\n                PREVIOUS_MODE=\"\"\n                sleep 1\n                continue\n            fi\n        else\n            if ! set_speaker_mode; then\n                DEV=\"\"\n                PREVIOUS_MODE=\"\"\n                sleep 1\n                continue\n            fi\n        fi\n\n        if [[ \"$MODE\" != \"$PREVIOUS_MODE\" ]]; then\n            echo \"Audio route switched to: $MODE\"\n        fi\n\n        PREVIOUS_MODE=\"$MODE\"\n        REFRESH_COUNTER=0\n    fi\n\n    sleep \"$POLL_INTERVAL\"\ndone\nEOF\n\nsudo chmod 755 \u002Fusr\u002Flocal\u002Fsbin\u002Fhuawei-sn6140-audio-fix\n",[17,1166,1167,1189,1194,1198,1203,1207,1212,1216,1221,1226,1231,1235,1240,1245,1249,1254,1259,1263,1268,1274,1279,1285,1291,1296,1302,1308,1313,1319,1324,1330,1336,1341,1347,1352,1358,1364,1370,1376,1382,1387,1393,1399,1404,1410,1416,1421,1426,1432,1438,1444,1450,1456,1462,1467,1472,1478,1483,1488,1494,1500,1506,1511,1516,1522,1528,1533,1539,1544,1550,1555,1561,1566,1572,1578,1584,1590,1596,1601,1606,1612,1618,1624,1630,1635,1641,1647,1653,1658,1664,1669,1675,1681,1687,1692,1698,1704,1710,1715,1720,1726,1732,1738,1743,1748,1754,1759,1765,1771,1776,1782,1788,1793,1798,1804,1809,1815,1821,1827,1833,1838,1844,1850,1856,1862,1868,1874,1880,1886,1892,1897,1902,1907,1912,1917,1922,1927,1933,1939,1944,1949,1955,1960,1965,1970,1976,1981,1987,1992],{"__ignoreMap":53},[117,1168,1169,1171,1174,1177,1180,1183,1186],{"class":119,"line":120},[117,1170,664],{"class":123},[117,1172,1173],{"class":253}," tee",[117,1175,1176],{"class":253}," \u002Fusr\u002Flocal\u002Fsbin\u002Fhuawei-sn6140-audio-fix",[117,1178,1179],{"class":304}," >",[117,1181,1182],{"class":253},"\u002Fdev\u002Fnull",[117,1184,1185],{"class":304}," \u003C\u003C",[117,1187,1188],{"class":253},"'EOF'\n",[117,1190,1191],{"class":119,"line":257},[117,1192,1193],{"class":253},"#!\u002Fusr\u002Fbin\u002Fenv bash\n",[117,1195,1196],{"class":119,"line":266},[117,1197,270],{"emptyLinePlaceholder":269},[117,1199,1200],{"class":119,"line":273},[117,1201,1202],{"class":253},"set -u\n",[117,1204,1205],{"class":119,"line":279},[117,1206,270],{"emptyLinePlaceholder":269},[117,1208,1209],{"class":119,"line":287},[117,1210,1211],{"class":253},"HDA_VERB=\"\u002Fusr\u002Fbin\u002Fhda-verb\"\n",[117,1213,1214],{"class":119,"line":296},[117,1215,270],{"emptyLinePlaceholder":269},[117,1217,1218],{"class":119,"line":311},[117,1219,1220],{"class":253},"# 仅允许当前验证过的 Codec 运行。\n",[117,1222,1223],{"class":119,"line":316},[117,1224,1225],{"class":253},"VENDOR_ID=\"0x14f11f87\"\n",[117,1227,1228],{"class":119,"line":321},[117,1229,1230],{"class":253},"SUBSYSTEM_ID=\"0x19e53281\"\n",[117,1232,1233],{"class":119,"line":329},[117,1234,270],{"emptyLinePlaceholder":269},[117,1236,1237],{"class":119,"line":356},[117,1238,1239],{"class":253},"POLL_INTERVAL=1\n",[117,1241,1242],{"class":119,"line":361},[117,1243,1244],{"class":253},"REFRESH_INTERVAL=10\n",[117,1246,1247],{"class":119,"line":366},[117,1248,270],{"emptyLinePlaceholder":269},[117,1250,1251],{"class":119,"line":374},[117,1252,1253],{"class":253},"find_hda_device() {\n",[117,1255,1256],{"class":119,"line":402},[117,1257,1258],{"class":253},"    local codec card addr dev\n",[117,1260,1261],{"class":119,"line":417},[117,1262,270],{"emptyLinePlaceholder":269},[117,1264,1265],{"class":119,"line":436},[117,1266,1267],{"class":253},"    for codec in \u002Fproc\u002Fasound\u002Fcard*\u002Fcodec#*; do\n",[117,1269,1271],{"class":119,"line":1270},19,[117,1272,1273],{"class":253},"        [[ -r \"$codec\" ]] || continue\n",[117,1275,1277],{"class":119,"line":1276},20,[117,1278,270],{"emptyLinePlaceholder":269},[117,1280,1282],{"class":119,"line":1281},21,[117,1283,1284],{"class":253},"        grep -qx \"Vendor Id: $VENDOR_ID\" \"$codec\" || continue\n",[117,1286,1288],{"class":119,"line":1287},22,[117,1289,1290],{"class":253},"        grep -qx \"Subsystem Id: $SUBSYSTEM_ID\" \"$codec\" || continue\n",[117,1292,1294],{"class":119,"line":1293},23,[117,1295,270],{"emptyLinePlaceholder":269},[117,1297,1299],{"class":119,"line":1298},24,[117,1300,1301],{"class":253},"        card=\"${codec#\u002Fproc\u002Fasound\u002Fcard}\"\n",[117,1303,1305],{"class":119,"line":1304},25,[117,1306,1307],{"class":253},"        card=\"${card%%\u002F*}\"\n",[117,1309,1311],{"class":119,"line":1310},26,[117,1312,270],{"emptyLinePlaceholder":269},[117,1314,1316],{"class":119,"line":1315},27,[117,1317,1318],{"class":253},"        addr=\"$(awk '\u002F^Address:\u002F {print $2; exit}' \"$codec\")\"\n",[117,1320,1322],{"class":119,"line":1321},28,[117,1323,270],{"emptyLinePlaceholder":269},[117,1325,1327],{"class":119,"line":1326},29,[117,1328,1329],{"class":253},"        [[ \"$card\" =~ ^[0-9]+$ ]] || continue\n",[117,1331,1333],{"class":119,"line":1332},30,[117,1334,1335],{"class":253},"        [[ \"$addr\" =~ ^[0-9]+$ ]] || continue\n",[117,1337,1339],{"class":119,"line":1338},31,[117,1340,270],{"emptyLinePlaceholder":269},[117,1342,1344],{"class":119,"line":1343},32,[117,1345,1346],{"class":253},"        dev=\"\u002Fdev\u002Fsnd\u002FhwC${card}D${addr}\"\n",[117,1348,1350],{"class":119,"line":1349},33,[117,1351,270],{"emptyLinePlaceholder":269},[117,1353,1355],{"class":119,"line":1354},34,[117,1356,1357],{"class":253},"        if [[ -e \"$dev\" ]]; then\n",[117,1359,1361],{"class":119,"line":1360},35,[117,1362,1363],{"class":253},"            printf '%s\\n' \"$dev\"\n",[117,1365,1367],{"class":119,"line":1366},36,[117,1368,1369],{"class":253},"            return 0\n",[117,1371,1373],{"class":119,"line":1372},37,[117,1374,1375],{"class":253},"        fi\n",[117,1377,1379],{"class":119,"line":1378},38,[117,1380,1381],{"class":253},"    done\n",[117,1383,1385],{"class":119,"line":1384},39,[117,1386,270],{"emptyLinePlaceholder":269},[117,1388,1390],{"class":119,"line":1389},40,[117,1391,1392],{"class":253},"    return 1\n",[117,1394,1396],{"class":119,"line":1395},41,[117,1397,1398],{"class":253},"}\n",[117,1400,1402],{"class":119,"line":1401},42,[117,1403,270],{"emptyLinePlaceholder":269},[117,1405,1407],{"class":119,"line":1406},43,[117,1408,1409],{"class":253},"verb() {\n",[117,1411,1413],{"class":119,"line":1412},44,[117,1414,1415],{"class":253},"    \"$HDA_VERB\" \"$DEV\" \"$1\" \"$2\" \"$3\" >\u002Fdev\u002Fnull 2>&1\n",[117,1417,1419],{"class":119,"line":1418},45,[117,1420,1398],{"class":253},[117,1422,1424],{"class":119,"line":1423},46,[117,1425,270],{"emptyLinePlaceholder":269},[117,1427,1429],{"class":119,"line":1428},47,[117,1430,1431],{"class":253},"set_speaker_mode() {\n",[117,1433,1435],{"class":119,"line":1434},48,[117,1436,1437],{"class":253},"    verb 0x01 0x717 0x2 &&\n",[117,1439,1441],{"class":119,"line":1440},49,[117,1442,1443],{"class":253},"    verb 0x01 0x716 0x2 &&\n",[117,1445,1447],{"class":119,"line":1446},50,[117,1448,1449],{"class":253},"    verb 0x16 0x701 0x1 &&\n",[117,1451,1453],{"class":119,"line":1452},51,[117,1454,1455],{"class":253},"    verb 0x17 0x70c 0x2 &&\n",[117,1457,1459],{"class":119,"line":1458},52,[117,1460,1461],{"class":253},"    verb 0x01 0x715 0x2\n",[117,1463,1465],{"class":119,"line":1464},53,[117,1466,1398],{"class":253},[117,1468,1470],{"class":119,"line":1469},54,[117,1471,270],{"emptyLinePlaceholder":269},[117,1473,1475],{"class":119,"line":1474},55,[117,1476,1477],{"class":253},"set_headphone_mode() {\n",[117,1479,1481],{"class":119,"line":1480},56,[117,1482,1437],{"class":253},[117,1484,1486],{"class":119,"line":1485},57,[117,1487,1443],{"class":253},[117,1489,1491],{"class":119,"line":1490},58,[117,1492,1493],{"class":253},"    verb 0x16 0x701 0x0 &&\n",[117,1495,1497],{"class":119,"line":1496},59,[117,1498,1499],{"class":253},"    verb 0x17 0x70c 0x0 &&\n",[117,1501,1503],{"class":119,"line":1502},60,[117,1504,1505],{"class":253},"    verb 0x01 0x715 0x0\n",[117,1507,1509],{"class":119,"line":1508},61,[117,1510,1398],{"class":253},[117,1512,1514],{"class":119,"line":1513},62,[117,1515,270],{"emptyLinePlaceholder":269},[117,1517,1519],{"class":119,"line":1518},63,[117,1520,1521],{"class":253},"get_mode() {\n",[117,1523,1525],{"class":119,"line":1524},64,[117,1526,1527],{"class":253},"    local output value\n",[117,1529,1531],{"class":119,"line":1530},65,[117,1532,270],{"emptyLinePlaceholder":269},[117,1534,1536],{"class":119,"line":1535},66,[117,1537,1538],{"class":253},"    output=\"$(\"$HDA_VERB\" \"$DEV\" 0x16 0xf09 0 2>\u002Fdev\u002Fnull)\" || return 1\n",[117,1540,1542],{"class":119,"line":1541},67,[117,1543,270],{"emptyLinePlaceholder":269},[117,1545,1547],{"class":119,"line":1546},68,[117,1548,1549],{"class":253},"    value=\"$(awk '\u002Fvalue =\u002F {print $3; exit}' \u003C\u003C\u003C\"$output\")\"\n",[117,1551,1553],{"class":119,"line":1552},69,[117,1554,270],{"emptyLinePlaceholder":269},[117,1556,1558],{"class":119,"line":1557},70,[117,1559,1560],{"class":253},"    [[ \"$value\" =~ ^0x[0-9a-fA-F]+$ ]] || return 1\n",[117,1562,1564],{"class":119,"line":1563},71,[117,1565,270],{"emptyLinePlaceholder":269},[117,1567,1569],{"class":119,"line":1568},72,[117,1570,1571],{"class":253},"    if (( value & 0x80000000 )); then\n",[117,1573,1575],{"class":119,"line":1574},73,[117,1576,1577],{"class":253},"        printf '%s\\n' \"headphone\"\n",[117,1579,1581],{"class":119,"line":1580},74,[117,1582,1583],{"class":253},"    else\n",[117,1585,1587],{"class":119,"line":1586},75,[117,1588,1589],{"class":253},"        printf '%s\\n' \"speaker\"\n",[117,1591,1593],{"class":119,"line":1592},76,[117,1594,1595],{"class":253},"    fi\n",[117,1597,1599],{"class":119,"line":1598},77,[117,1600,1398],{"class":253},[117,1602,1604],{"class":119,"line":1603},78,[117,1605,270],{"emptyLinePlaceholder":269},[117,1607,1609],{"class":119,"line":1608},79,[117,1610,1611],{"class":253},"if [[ ! -x \"$HDA_VERB\" ]]; then\n",[117,1613,1615],{"class":119,"line":1614},80,[117,1616,1617],{"class":253},"    echo \"hda-verb not found: $HDA_VERB\" >&2\n",[117,1619,1621],{"class":119,"line":1620},81,[117,1622,1623],{"class":253},"    exit 1\n",[117,1625,1627],{"class":119,"line":1626},82,[117,1628,1629],{"class":253},"fi\n",[117,1631,1633],{"class":119,"line":1632},83,[117,1634,270],{"emptyLinePlaceholder":269},[117,1636,1638],{"class":119,"line":1637},84,[117,1639,1640],{"class":253},"DEV=\"\"\n",[117,1642,1644],{"class":119,"line":1643},85,[117,1645,1646],{"class":253},"PREVIOUS_MODE=\"\"\n",[117,1648,1650],{"class":119,"line":1649},86,[117,1651,1652],{"class":253},"REFRESH_COUNTER=0\n",[117,1654,1656],{"class":119,"line":1655},87,[117,1657,270],{"emptyLinePlaceholder":269},[117,1659,1661],{"class":119,"line":1660},88,[117,1662,1663],{"class":253},"while true; do\n",[117,1665,1667],{"class":119,"line":1666},89,[117,1668,270],{"emptyLinePlaceholder":269},[117,1670,1672],{"class":119,"line":1671},90,[117,1673,1674],{"class":253},"    # 如果设备还没找到，或者设备在休眠恢复后重新编号，则重新扫描。\n",[117,1676,1678],{"class":119,"line":1677},91,[117,1679,1680],{"class":253},"    if [[ -z \"$DEV\" || ! -e \"$DEV\" ]]; then\n",[117,1682,1684],{"class":119,"line":1683},92,[117,1685,1686],{"class":253},"        DEV=\"$(find_hda_device || true)\"\n",[117,1688,1690],{"class":119,"line":1689},93,[117,1691,270],{"emptyLinePlaceholder":269},[117,1693,1695],{"class":119,"line":1694},94,[117,1696,1697],{"class":253},"        if [[ -z \"$DEV\" ]]; then\n",[117,1699,1701],{"class":119,"line":1700},95,[117,1702,1703],{"class":253},"            sleep 2\n",[117,1705,1707],{"class":119,"line":1706},96,[117,1708,1709],{"class":253},"            continue\n",[117,1711,1713],{"class":119,"line":1712},97,[117,1714,1375],{"class":253},[117,1716,1718],{"class":119,"line":1717},98,[117,1719,270],{"emptyLinePlaceholder":269},[117,1721,1723],{"class":119,"line":1722},99,[117,1724,1725],{"class":253},"        echo \"Huawei SN6140 codec found: $DEV\"\n",[117,1727,1729],{"class":119,"line":1728},100,[117,1730,1731],{"class":253},"        PREVIOUS_MODE=\"\"\n",[117,1733,1735],{"class":119,"line":1734},101,[117,1736,1737],{"class":253},"        REFRESH_COUNTER=0\n",[117,1739,1741],{"class":119,"line":1740},102,[117,1742,1595],{"class":253},[117,1744,1746],{"class":119,"line":1745},103,[117,1747,270],{"emptyLinePlaceholder":269},[117,1749,1751],{"class":119,"line":1750},104,[117,1752,1753],{"class":253},"    MODE=\"$(get_mode || true)\"\n",[117,1755,1757],{"class":119,"line":1756},105,[117,1758,270],{"emptyLinePlaceholder":269},[117,1760,1762],{"class":119,"line":1761},106,[117,1763,1764],{"class":253},"    if [[ -z \"$MODE\" ]]; then\n",[117,1766,1768],{"class":119,"line":1767},107,[117,1769,1770],{"class":253},"        DEV=\"\"\n",[117,1772,1774],{"class":119,"line":1773},108,[117,1775,1731],{"class":253},[117,1777,1779],{"class":119,"line":1778},109,[117,1780,1781],{"class":253},"        sleep 2\n",[117,1783,1785],{"class":119,"line":1784},110,[117,1786,1787],{"class":253},"        continue\n",[117,1789,1791],{"class":119,"line":1790},111,[117,1792,1595],{"class":253},[117,1794,1796],{"class":119,"line":1795},112,[117,1797,270],{"emptyLinePlaceholder":269},[117,1799,1801],{"class":119,"line":1800},113,[117,1802,1803],{"class":253},"    REFRESH_COUNTER=$((REFRESH_COUNTER + 1))\n",[117,1805,1807],{"class":119,"line":1806},114,[117,1808,270],{"emptyLinePlaceholder":269},[117,1810,1812],{"class":119,"line":1811},115,[117,1813,1814],{"class":253},"    # 状态变化时立即设置；\n",[117,1816,1818],{"class":119,"line":1817},116,[117,1819,1820],{"class":253},"    # 同时每隔一段时间重新应用，避免 SOF \u002F runtime PM 恢复后寄存器被重置。\n",[117,1822,1824],{"class":119,"line":1823},117,[117,1825,1826],{"class":253},"    if [[ \"$MODE\" != \"$PREVIOUS_MODE\" ]] ||\n",[117,1828,1830],{"class":119,"line":1829},118,[117,1831,1832],{"class":253},"       (( REFRESH_COUNTER >= REFRESH_INTERVAL )); then\n",[117,1834,1836],{"class":119,"line":1835},119,[117,1837,270],{"emptyLinePlaceholder":269},[117,1839,1841],{"class":119,"line":1840},120,[117,1842,1843],{"class":253},"        if [[ \"$MODE\" == \"headphone\" ]]; then\n",[117,1845,1847],{"class":119,"line":1846},121,[117,1848,1849],{"class":253},"            if ! set_headphone_mode; then\n",[117,1851,1853],{"class":119,"line":1852},122,[117,1854,1855],{"class":253},"                DEV=\"\"\n",[117,1857,1859],{"class":119,"line":1858},123,[117,1860,1861],{"class":253},"                PREVIOUS_MODE=\"\"\n",[117,1863,1865],{"class":119,"line":1864},124,[117,1866,1867],{"class":253},"                sleep 1\n",[117,1869,1871],{"class":119,"line":1870},125,[117,1872,1873],{"class":253},"                continue\n",[117,1875,1877],{"class":119,"line":1876},126,[117,1878,1879],{"class":253},"            fi\n",[117,1881,1883],{"class":119,"line":1882},127,[117,1884,1885],{"class":253},"        else\n",[117,1887,1889],{"class":119,"line":1888},128,[117,1890,1891],{"class":253},"            if ! set_speaker_mode; then\n",[117,1893,1895],{"class":119,"line":1894},129,[117,1896,1855],{"class":253},[117,1898,1900],{"class":119,"line":1899},130,[117,1901,1861],{"class":253},[117,1903,1905],{"class":119,"line":1904},131,[117,1906,1867],{"class":253},[117,1908,1910],{"class":119,"line":1909},132,[117,1911,1873],{"class":253},[117,1913,1915],{"class":119,"line":1914},133,[117,1916,1879],{"class":253},[117,1918,1920],{"class":119,"line":1919},134,[117,1921,1375],{"class":253},[117,1923,1925],{"class":119,"line":1924},135,[117,1926,270],{"emptyLinePlaceholder":269},[117,1928,1930],{"class":119,"line":1929},136,[117,1931,1932],{"class":253},"        if [[ \"$MODE\" != \"$PREVIOUS_MODE\" ]]; then\n",[117,1934,1936],{"class":119,"line":1935},137,[117,1937,1938],{"class":253},"            echo \"Audio route switched to: $MODE\"\n",[117,1940,1942],{"class":119,"line":1941},138,[117,1943,1375],{"class":253},[117,1945,1947],{"class":119,"line":1946},139,[117,1948,270],{"emptyLinePlaceholder":269},[117,1950,1952],{"class":119,"line":1951},140,[117,1953,1954],{"class":253},"        PREVIOUS_MODE=\"$MODE\"\n",[117,1956,1958],{"class":119,"line":1957},141,[117,1959,1737],{"class":253},[117,1961,1963],{"class":119,"line":1962},142,[117,1964,1595],{"class":253},[117,1966,1968],{"class":119,"line":1967},143,[117,1969,270],{"emptyLinePlaceholder":269},[117,1971,1973],{"class":119,"line":1972},144,[117,1974,1975],{"class":253},"    sleep \"$POLL_INTERVAL\"\n",[117,1977,1979],{"class":119,"line":1978},145,[117,1980,439],{"class":253},[117,1982,1984],{"class":119,"line":1983},146,[117,1985,1986],{"class":253},"EOF\n",[117,1988,1990],{"class":119,"line":1989},147,[117,1991,270],{"emptyLinePlaceholder":269},[117,1993,1995,1997,2000,2003],{"class":119,"line":1994},148,[117,1996,664],{"class":123},[117,1998,1999],{"class":253}," chmod",[117,2001,2002],{"class":249}," 755",[117,2004,2005],{"class":253}," \u002Fusr\u002Flocal\u002Fsbin\u002Fhuawei-sn6140-audio-fix\n",[33,2007],{},[102,2009,2011],{"id":2010},"_13-创建-systemd-服务","13. 创建 systemd 服务",[13,2013,718],{},[47,2015,2017],{"className":111,"code":2016,"language":113,"meta":53,"style":53},"sudo tee \u002Fetc\u002Fsystemd\u002Fsystem\u002Fhuawei-sn6140-audio-fix.service >\u002Fdev\u002Fnull \u003C\u003C'EOF'\n[Unit]\nDescription=Huawei MateBook SN6140 speaker\u002Fheadphone routing fix\nAfter=sound.target\n\n[Service]\nType=simple\nExecStart=\u002Fusr\u002Flocal\u002Fsbin\u002Fhuawei-sn6140-audio-fix\nRestart=always\nRestartSec=2\n\n[Install]\nWantedBy=multi-user.target\nEOF\n",[17,2018,2019,2036,2041,2046,2051,2055,2060,2065,2070,2075,2080,2084,2089,2094],{"__ignoreMap":53},[117,2020,2021,2023,2025,2028,2030,2032,2034],{"class":119,"line":120},[117,2022,664],{"class":123},[117,2024,1173],{"class":253},[117,2026,2027],{"class":253}," \u002Fetc\u002Fsystemd\u002Fsystem\u002Fhuawei-sn6140-audio-fix.service",[117,2029,1179],{"class":304},[117,2031,1182],{"class":253},[117,2033,1185],{"class":304},[117,2035,1188],{"class":253},[117,2037,2038],{"class":119,"line":257},[117,2039,2040],{"class":253},"[Unit]\n",[117,2042,2043],{"class":119,"line":266},[117,2044,2045],{"class":253},"Description=Huawei MateBook SN6140 speaker\u002Fheadphone routing fix\n",[117,2047,2048],{"class":119,"line":273},[117,2049,2050],{"class":253},"After=sound.target\n",[117,2052,2053],{"class":119,"line":279},[117,2054,270],{"emptyLinePlaceholder":269},[117,2056,2057],{"class":119,"line":287},[117,2058,2059],{"class":253},"[Service]\n",[117,2061,2062],{"class":119,"line":296},[117,2063,2064],{"class":253},"Type=simple\n",[117,2066,2067],{"class":119,"line":311},[117,2068,2069],{"class":253},"ExecStart=\u002Fusr\u002Flocal\u002Fsbin\u002Fhuawei-sn6140-audio-fix\n",[117,2071,2072],{"class":119,"line":316},[117,2073,2074],{"class":253},"Restart=always\n",[117,2076,2077],{"class":119,"line":321},[117,2078,2079],{"class":253},"RestartSec=2\n",[117,2081,2082],{"class":119,"line":329},[117,2083,270],{"emptyLinePlaceholder":269},[117,2085,2086],{"class":119,"line":356},[117,2087,2088],{"class":253},"[Install]\n",[117,2090,2091],{"class":119,"line":361},[117,2092,2093],{"class":253},"WantedBy=multi-user.target\n",[117,2095,2096],{"class":119,"line":366},[117,2097,1986],{"class":253},[13,2099,2100],{},"重新加载 systemd：",[47,2102,2104],{"className":111,"code":2103,"language":113,"meta":53,"style":53},"sudo systemctl daemon-reload\n",[17,2105,2106],{"__ignoreMap":53},[117,2107,2108,2110,2113],{"class":119,"line":120},[117,2109,664],{"class":123},[117,2111,2112],{"class":253}," systemctl",[117,2114,2115],{"class":253}," daemon-reload\n",[13,2117,2118],{},"启用并立即启动：",[47,2120,2122],{"className":111,"code":2121,"language":113,"meta":53,"style":53},"sudo systemctl enable --now huawei-sn6140-audio-fix.service\n",[17,2123,2124],{"__ignoreMap":53},[117,2125,2126,2128,2130,2133,2136],{"class":119,"line":120},[117,2127,664],{"class":123},[117,2129,2112],{"class":253},[117,2131,2132],{"class":253}," enable",[117,2134,2135],{"class":249}," --now",[117,2137,2138],{"class":253}," huawei-sn6140-audio-fix.service\n",[33,2140],{},[102,2142,2144],{"id":2143},"_14-查看服务状态","14. 查看服务状态",[13,2146,718],{},[47,2148,2150],{"className":111,"code":2149,"language":113,"meta":53,"style":53},"systemctl status huawei-sn6140-audio-fix.service --no-pager\n",[17,2151,2152],{"__ignoreMap":53},[117,2153,2154,2157,2160,2163],{"class":119,"line":120},[117,2155,2156],{"class":123},"systemctl",[117,2158,2159],{"class":253}," status",[117,2161,2162],{"class":253}," huawei-sn6140-audio-fix.service",[117,2164,2165],{"class":249}," --no-pager\n",[13,2167,2168],{},"正常应看到：",[47,2170,2173],{"className":2171,"code":2172,"language":52,"meta":53},[50],"Active: active (running)\n",[17,2174,2172],{"__ignoreMap":53},[13,2176,2177],{},"查看日志：",[47,2179,2181],{"className":111,"code":2180,"language":113,"meta":53,"style":53},"journalctl -u huawei-sn6140-audio-fix.service -n 30 --no-pager\n",[17,2182,2183],{"__ignoreMap":53},[117,2184,2185,2188,2191,2193,2196,2199],{"class":119,"line":120},[117,2186,2187],{"class":123},"journalctl",[117,2189,2190],{"class":249}," -u",[117,2192,2162],{"class":253},[117,2194,2195],{"class":249}," -n",[117,2197,2198],{"class":249}," 30",[117,2200,2165],{"class":249},[13,2202,2203],{},"正常日志类似：",[47,2205,2208],{"className":2206,"code":2207,"language":52,"meta":53},[50],"Huawei SN6140 codec found: \u002Fdev\u002Fsnd\u002FhwC0D0\nAudio route switched to: speaker\nAudio route switched to: headphone\n",[17,2209,2207],{"__ignoreMap":53},[13,2211,2212],{},"实时查看：",[47,2214,2216],{"className":111,"code":2215,"language":113,"meta":53,"style":53},"sudo journalctl -fu huawei-sn6140-audio-fix.service\n",[17,2217,2218],{"__ignoreMap":53},[117,2219,2220,2222,2225,2228],{"class":119,"line":120},[117,2221,664],{"class":123},[117,2223,2224],{"class":253}," journalctl",[117,2226,2227],{"class":249}," -fu",[117,2229,2138],{"class":253},[13,2231,2232],{},"此时插拔耳机可以观察到：",[47,2234,2237],{"className":2235,"code":2236,"language":52,"meta":53},[50],"插入：\nAudio route switched to: headphone\n\n拔出：\nAudio route switched to: speaker\n",[17,2238,2236],{"__ignoreMap":53},[33,2240],{},[102,2242,2244],{"id":2243},"_15-最终结果","15. 最终结果",[13,2246,2247],{},"修复完成后：",[36,2249,2250],{"id":2250},"未插耳机",[47,2252,2255],{"className":2253,"code":2254,"language":52,"meta":53},[50],"Speaker    ON\nHeadphone  OFF\n",[17,2256,2254],{"__ignoreMap":53},[13,2258,2259],{},"声音只从笔记本扬声器播放。",[36,2261,2262],{"id":2262},"插入耳机",[47,2264,2267],{"className":2265,"code":2266,"language":52,"meta":53},[50],"Speaker    OFF\nHeadphone  ON\n",[17,2268,2266],{"__ignoreMap":53},[13,2270,2271],{},"声音只从有线耳机播放。",[36,2273,2274],{"id":2274},"拔掉耳机",[13,2276,2277],{},"系统自动重新切换到 Speaker 模式。",[13,2279,2280],{},"整个切换过程大约在：",[47,2282,2285],{"className":2283,"code":2284,"language":52,"meta":53},[50],"0 ~ 1 秒\n",[17,2286,2284],{"__ignoreMap":53},[13,2288,2289],{},"内完成。",[13,2291,2292,2293,2295],{},"重启 Ubuntu 后 systemd 服务会自动启动，不需要再次手动运行 ",[17,2294,653],{},"。",[33,2297],{},[102,2299,2301],{"id":2300},"_16-最终问题分析","16. 最终问题分析",[13,2303,2304],{},"整个问题可以概括为：",[47,2306,2309],{"className":2307,"code":2308,"language":52,"meta":53},[50],"PipeWire\n   │\n   │ 输出设备选择正常\n   ↓\nALSA\n   │\n   │ Auto-Mute 正常\n   │ Speaker 显示 MM\n   ↓\nSOF \u002F HDA\n   │\n   │ Hardware Route 未完整切换\n   ↓\nConexant SN6140\n   │\n   ├── CONNECT_SEL\n   ├── EAPD\n   └── GPIO\n          ↓\n     物理扬声器功放\n",[17,2310,2308],{"__ignoreMap":53},[13,2312,2313],{},"真正的问题不是：",[47,2315,2318],{"className":2316,"code":2317,"language":52,"meta":53},[50],"Ubuntu 不认识耳机\n",[17,2319,2317],{"__ignoreMap":53},[13,2321,2322],{},"因为：",[47,2324,2327],{"className":2325,"code":2326,"language":52,"meta":53},[50],"GET_PIN_SENSE:\n插入 = 0x80000000\n拔出 = 0x0\n",[17,2328,2326],{"__ignoreMap":53},[13,2330,2331],{},"说明耳机检测完全正常。",[13,2333,2334],{},"问题也不是：",[47,2336,2339],{"className":2337,"code":2338,"language":52,"meta":53},[50],"PipeWire 同时把音频发送给两个设备\n",[17,2340,2338],{"__ignoreMap":53},[13,2342,2343],{},"因为手动关闭 Speaker EAPD 后，耳机仍然可以正常播放。",[13,2345,2346],{},"真正的问题是：",[10,2348,2349],{},[13,2350,2351],{},"耳机插入后，Linux 当前的 HDA 路由没有为这台 Huawei + Conexant SN6140 完整同步 CONNECT_SEL、EAPD 和 GPIO 状态，导致内置扬声器物理功放仍保持开启。",[13,2353,2354],{},"最终 workaround 通过监听耳机 Pin Sense，并在耳机插拔时主动切换三组硬件状态解决问题。",[33,2356],{},[102,2358,2360],{"id":2359},"_17-本机验证的路由状态","17. 本机验证的路由状态",[13,2362,2363],{},"最终验证得到：",[2365,2366,2367,2387],"table",{},[2368,2369,2370],"thead",{},[2371,2372,2373,2377,2381,2384],"tr",{},[2374,2375,2376],"th",{},"模式",[2374,2378,2380],{"align":2379},"right","0x16 CONNECT_SEL",[2374,2382,2383],{"align":2379},"0x17 EAPD",[2374,2385,2386],{"align":2379},"GPIO1",[2388,2389,2390,2410],"tbody",{},[2371,2391,2392,2396,2401,2406],{},[2393,2394,2395],"td",{},"Speaker",[2393,2397,2398],{"align":2379},[17,2399,2400],{},"1",[2393,2402,2403],{"align":2379},[17,2404,2405],{},"2",[2393,2407,2408],{"align":2379},[17,2409,2405],{},[2371,2411,2412,2415,2419,2423],{},[2393,2413,2414],{},"Headphone",[2393,2416,2417],{"align":2379},[17,2418,787],{},[2393,2420,2421],{"align":2379},[17,2422,787],{},[2393,2424,2425],{"align":2379},[17,2426,787],{},[13,2428,2429],{},"对应命令：",[2431,2432,2395],"h3",{"id":2433},"speaker",[47,2435,2436],{"className":111,"code":803,"language":113,"meta":53,"style":53},[17,2437,2438,2452,2466,2480,2494],{"__ignoreMap":53},[117,2439,2440,2442,2444,2446,2448,2450],{"class":119,"line":120},[117,2441,664],{"class":123},[117,2443,730],{"class":253},[117,2445,733],{"class":253},[117,2447,816],{"class":249},[117,2449,819],{"class":249},[117,2451,822],{"class":249},[117,2453,2454,2456,2458,2460,2462,2464],{"class":119,"line":257},[117,2455,664],{"class":123},[117,2457,730],{"class":253},[117,2459,733],{"class":253},[117,2461,816],{"class":249},[117,2463,835],{"class":249},[117,2465,822],{"class":249},[117,2467,2468,2470,2472,2474,2476,2478],{"class":119,"line":266},[117,2469,664],{"class":123},[117,2471,730],{"class":253},[117,2473,733],{"class":253},[117,2475,848],{"class":249},[117,2477,851],{"class":249},[117,2479,854],{"class":249},[117,2481,2482,2484,2486,2488,2490,2492],{"class":119,"line":273},[117,2483,664],{"class":123},[117,2485,730],{"class":253},[117,2487,733],{"class":253},[117,2489,736],{"class":249},[117,2491,739],{"class":249},[117,2493,822],{"class":249},[117,2495,2496,2498,2500,2502,2504,2506],{"class":119,"line":279},[117,2497,664],{"class":123},[117,2499,730],{"class":253},[117,2501,733],{"class":253},[117,2503,816],{"class":249},[117,2505,881],{"class":249},[117,2507,822],{"class":249},[2431,2509,2414],{"id":2510},"headphone",[47,2512,2513],{"className":111,"code":916,"language":113,"meta":53,"style":53},[17,2514,2515,2529,2543,2557,2571],{"__ignoreMap":53},[117,2516,2517,2519,2521,2523,2525,2527],{"class":119,"line":120},[117,2518,664],{"class":123},[117,2520,730],{"class":253},[117,2522,733],{"class":253},[117,2524,816],{"class":249},[117,2526,819],{"class":249},[117,2528,822],{"class":249},[117,2530,2531,2533,2535,2537,2539,2541],{"class":119,"line":257},[117,2532,664],{"class":123},[117,2534,730],{"class":253},[117,2536,733],{"class":253},[117,2538,816],{"class":249},[117,2540,835],{"class":249},[117,2542,822],{"class":249},[117,2544,2545,2547,2549,2551,2553,2555],{"class":119,"line":266},[117,2546,664],{"class":123},[117,2548,730],{"class":253},[117,2550,733],{"class":253},[117,2552,848],{"class":249},[117,2554,851],{"class":249},[117,2556,742],{"class":249},[117,2558,2559,2561,2563,2565,2567,2569],{"class":119,"line":273},[117,2560,664],{"class":123},[117,2562,730],{"class":253},[117,2564,733],{"class":253},[117,2566,736],{"class":249},[117,2568,739],{"class":249},[117,2570,742],{"class":249},[117,2572,2573,2575,2577,2579,2581,2583],{"class":119,"line":279},[117,2574,664],{"class":123},[117,2576,730],{"class":253},[117,2578,733],{"class":253},[117,2580,816],{"class":249},[117,2582,881],{"class":249},[117,2584,742],{"class":249},[33,2586],{},[102,2588,2590],{"id":2589},"_18-hda-verb-简单说明","18. HDA Verb 简单说明",[13,2592,2593],{},"本文实际用到的 Verb：",[2365,2595,2596,2609],{},[2368,2597,2598],{},[2371,2599,2600,2603,2606],{},[2374,2601,2602],{},"Verb",[2374,2604,2605],{},"Linux 定义",[2374,2607,2608],{},"作用",[2388,2610,2611,2626,2641,2656,2671,2686],{},[2371,2612,2613,2618,2623],{},[2393,2614,2615],{},[17,2616,2617],{},"0xf09",[2393,2619,2620],{},[17,2621,2622],{},"GET_PIN_SENSE",[2393,2624,2625],{},"获取耳机插入状态",[2371,2627,2628,2633,2638],{},[2393,2629,2630],{},[17,2631,2632],{},"0x701",[2393,2634,2635],{},[17,2636,2637],{},"SET_CONNECT_SEL",[2393,2639,2640],{},"选择输入连接 \u002F DAC 路由",[2371,2642,2643,2648,2653],{},[2393,2644,2645],{},[17,2646,2647],{},"0x70c",[2393,2649,2650],{},[17,2651,2652],{},"SET_EAPD_BTLENABLE",[2393,2654,2655],{},"设置 EAPD \u002F 外部功放",[2371,2657,2658,2663,2668],{},[2393,2659,2660],{},[17,2661,2662],{},"0x715",[2393,2664,2665],{},[17,2666,2667],{},"SET_GPIO_DATA",[2393,2669,2670],{},"设置 GPIO 数据",[2371,2672,2673,2678,2683],{},[2393,2674,2675],{},[17,2676,2677],{},"0x716",[2393,2679,2680],{},[17,2681,2682],{},"SET_GPIO_MASK",[2393,2684,2685],{},"设置 GPIO Mask",[2371,2687,2688,2693,2698],{},[2393,2689,2690],{},[17,2691,2692],{},"0x717",[2393,2694,2695],{},[17,2696,2697],{},"SET_GPIO_DIRECTION",[2393,2699,2700],{},"设置 GPIO 方向",[13,2702,2703,2704,2706],{},"其中 ",[17,2705,2622],{}," 的 bit 31：",[47,2708,2711],{"className":2709,"code":2710,"language":52,"meta":53},[50],"AC_PINSENSE_PRESENCE = 1 \u003C\u003C 31\n",[17,2712,2710],{"__ignoreMap":53},[13,2714,2715],{},"用于表示插孔 Presence。",[33,2717],{},[102,2719,2721],{"id":2720},"_19-安全说明","19. 安全说明",[13,2723,2724],{},"这个方案：",[72,2726,2727,2730,2733,2736,2739,2742],{},[75,2728,2729],{},"不修改 BIOS；",[75,2731,2732],{},"不刷写声卡固件；",[75,2734,2735],{},"不修改 Codec 永久配置；",[75,2737,2738],{},"不更换内核；",[75,2740,2741],{},"不修改 PipeWire 配置；",[75,2743,2744],{},"不替换 SOF 驱动。",[13,2746,2747,2749],{},[17,2748,653],{}," 修改的是当前运行状态下的 HDA Codec 寄存器。",[13,2751,2752],{},"如果服务停止，或者机器重启，而不再启动该服务，就不会继续应用 workaround。",[13,2754,2755],{},"另外脚本限定：",[47,2757,2760],{"className":2758,"code":2759,"language":52,"meta":53},[50],"Vendor ID     = 0x14f11f87\nSubsystem ID  = 0x19e53281\n",[17,2761,2759],{"__ignoreMap":53},[13,2763,2764,2765,2295],{},"因此本文脚本",[2766,2767,2768],"strong",{},"不是 Huawei MateBook 全系列通用脚本",[13,2770,2771],{},"不同机型即使同样使用 SN6140，其：",[47,2773,2776],{"className":2774,"code":2775,"language":52,"meta":53},[50],"Node ID\nGPIO\nCONNECT_SEL\nSubsystem ID\n",[17,2777,2775],{"__ignoreMap":53},[13,2779,2780],{},"都有可能不同。",[13,2782,2783],{},"在其他机器上使用前，应先自行确认：",[47,2785,2787],{"className":111,"code":2786,"language":113,"meta":53,"style":53},"cat \u002Fproc\u002Fasound\u002Fcard*\u002Fcodec#*\n",[17,2788,2789],{"__ignoreMap":53},[117,2790,2791,2793,2796,2798,2801],{"class":119,"line":120},[117,2792,290],{"class":123},[117,2794,2795],{"class":253}," \u002Fproc\u002Fasound\u002Fcard",[117,2797,393],{"class":249},[117,2799,2800],{"class":253},"\u002Fcodec#",[117,2802,2803],{"class":249},"*\n",[13,2805,2806],{},"中的实际 Codec 拓扑。",[33,2808],{},[102,2810,2812],{"id":2811},"_20-如何撤销修复","20. 如何撤销修复",[13,2814,2815],{},"如果未来 Linux 内核已经原生支持这台机器，可以删除 workaround。",[13,2817,2818],{},"停止并禁用服务：",[47,2820,2822],{"className":111,"code":2821,"language":113,"meta":53,"style":53},"sudo systemctl disable --now huawei-sn6140-audio-fix.service\n",[17,2823,2824],{"__ignoreMap":53},[117,2825,2826,2828,2830,2833,2835],{"class":119,"line":120},[117,2827,664],{"class":123},[117,2829,2112],{"class":253},[117,2831,2832],{"class":253}," disable",[117,2834,2135],{"class":249},[117,2836,2138],{"class":253},[13,2838,2839],{},"删除 service：",[47,2841,2843],{"className":111,"code":2842,"language":113,"meta":53,"style":53},"sudo rm \u002Fetc\u002Fsystemd\u002Fsystem\u002Fhuawei-sn6140-audio-fix.service\n",[17,2844,2845],{"__ignoreMap":53},[117,2846,2847,2849,2852],{"class":119,"line":120},[117,2848,664],{"class":123},[117,2850,2851],{"class":253}," rm",[117,2853,2854],{"class":253}," \u002Fetc\u002Fsystemd\u002Fsystem\u002Fhuawei-sn6140-audio-fix.service\n",[13,2856,2857],{},"删除脚本：",[47,2859,2861],{"className":111,"code":2860,"language":113,"meta":53,"style":53},"sudo rm \u002Fusr\u002Flocal\u002Fsbin\u002Fhuawei-sn6140-audio-fix\n",[17,2862,2863],{"__ignoreMap":53},[117,2864,2865,2867,2869],{"class":119,"line":120},[117,2866,664],{"class":123},[117,2868,2851],{"class":253},[117,2870,2005],{"class":253},[13,2872,2873],{},"重新加载：",[47,2875,2876],{"className":111,"code":2103,"language":113,"meta":53,"style":53},[17,2877,2878],{"__ignoreMap":53},[117,2879,2880,2882,2884],{"class":119,"line":120},[117,2881,664],{"class":123},[117,2883,2112],{"class":253},[117,2885,2115],{"class":253},[13,2887,2888],{},"然后重启：",[47,2890,2892],{"className":111,"code":2891,"language":113,"meta":53,"style":53},"sudo reboot\n",[17,2893,2894],{"__ignoreMap":53},[117,2895,2896,2898],{"class":119,"line":120},[117,2897,664],{"class":123},[117,2899,2900],{"class":253}," reboot\n",[13,2902,2903],{},"即可恢复为系统默认音频处理逻辑。",[33,2905],{},[102,2907,2909],{"id":2908},"_21-快速诊断命令汇总","21. 快速诊断命令汇总",[13,2911,2912],{},"如果遇到类似问题，可以先执行：",[47,2914,2916],{"className":111,"code":2915,"language":113,"meta":53,"style":53},"echo \"===== Kernel =====\"\nuname -r\n\necho\necho \"===== DMI =====\"\nfor f in \\\n    sys_vendor \\\n    product_name \\\n    product_version \\\n    board_vendor \\\n    board_name \\\n    board_version\ndo\n    printf \"%-18s: \" \"$f\"\n    cat \"\u002Fsys\u002Fclass\u002Fdmi\u002Fid\u002F$f\" 2>\u002Fdev\u002Fnull\ndone\n\necho\necho \"===== Audio PCI =====\"\nlspci -nn | grep -iE 'audio|multimedia'\n\necho\necho \"===== Codecs =====\"\nfor f in \u002Fproc\u002Fasound\u002Fcard*\u002Fcodec#*; do\n    echo \"---- $f ----\"\n    grep -E '^Codec:|^Vendor Id:|^Subsystem Id:' \"$f\"\ndone\n",[17,2917,2918,2924,2930,2934,2938,2945,2956,2963,2970,2977,2984,2991,2996,3000,3014,3031,3035,3039,3043,3049,3066,3070,3074,3081,3099,3109,3124],{"__ignoreMap":53},[117,2919,2920,2922],{"class":119,"line":120},[117,2921,250],{"class":249},[117,2923,254],{"class":253},[117,2925,2926,2928],{"class":119,"line":257},[117,2927,260],{"class":123},[117,2929,263],{"class":249},[117,2931,2932],{"class":119,"line":266},[117,2933,270],{"emptyLinePlaceholder":269},[117,2935,2936],{"class":119,"line":273},[117,2937,276],{"class":249},[117,2939,2940,2942],{"class":119,"line":279},[117,2941,250],{"class":249},[117,2943,2944],{"class":253}," \"===== DMI =====\"\n",[117,2946,2947,2949,2951,2953],{"class":119,"line":287},[117,2948,377],{"class":304},[117,2950,381],{"class":380},[117,2952,384],{"class":304},[117,2954,2955],{"class":380}," \\\n",[117,2957,2958,2961],{"class":119,"line":296},[117,2959,2960],{"class":253},"    sys_vendor",[117,2962,2955],{"class":380},[117,2964,2965,2968],{"class":119,"line":311},[117,2966,2967],{"class":253},"    product_name",[117,2969,2955],{"class":380},[117,2971,2972,2975],{"class":119,"line":316},[117,2973,2974],{"class":253},"    product_version",[117,2976,2955],{"class":380},[117,2978,2979,2982],{"class":119,"line":321},[117,2980,2981],{"class":253},"    board_vendor",[117,2983,2955],{"class":380},[117,2985,2986,2989],{"class":119,"line":329},[117,2987,2988],{"class":253},"    board_name",[117,2990,2955],{"class":380},[117,2992,2993],{"class":119,"line":356},[117,2994,2995],{"class":253},"    board_version\n",[117,2997,2998],{"class":119,"line":361},[117,2999,399],{"class":304},[117,3001,3002,3005,3008,3010,3012],{"class":119,"line":366},[117,3003,3004],{"class":249},"    printf",[117,3006,3007],{"class":253}," \"%-18s: \"",[117,3009,428],{"class":253},[117,3011,411],{"class":380},[117,3013,433],{"class":253},[117,3015,3016,3019,3022,3024,3027,3029],{"class":119,"line":374},[117,3017,3018],{"class":123},"    cat",[117,3020,3021],{"class":253}," \"\u002Fsys\u002Fclass\u002Fdmi\u002Fid\u002F",[117,3023,411],{"class":380},[117,3025,3026],{"class":253},"\"",[117,3028,305],{"class":304},[117,3030,308],{"class":253},[117,3032,3033],{"class":119,"line":402},[117,3034,439],{"class":304},[117,3036,3037],{"class":119,"line":417},[117,3038,270],{"emptyLinePlaceholder":269},[117,3040,3041],{"class":119,"line":436},[117,3042,276],{"class":249},[117,3044,3045,3047],{"class":119,"line":1270},[117,3046,250],{"class":249},[117,3048,326],{"class":253},[117,3050,3051,3053,3056,3058,3060,3063],{"class":119,"line":1276},[117,3052,332],{"class":123},[117,3054,3055],{"class":249}," -nn",[117,3057,344],{"class":304},[117,3059,347],{"class":123},[117,3061,3062],{"class":249}," -iE",[117,3064,3065],{"class":253}," 'audio|multimedia'\n",[117,3067,3068],{"class":119,"line":1281},[117,3069,270],{"emptyLinePlaceholder":269},[117,3071,3072],{"class":119,"line":1287},[117,3073,276],{"class":249},[117,3075,3076,3078],{"class":119,"line":1293},[117,3077,250],{"class":249},[117,3079,3080],{"class":253}," \"===== Codecs =====\"\n",[117,3082,3083,3085,3087,3089,3091,3093,3095,3097],{"class":119,"line":1298},[117,3084,377],{"class":304},[117,3086,381],{"class":380},[117,3088,384],{"class":304},[117,3090,387],{"class":253},[117,3092,390],{"class":380},[117,3094,393],{"class":304},[117,3096,396],{"class":380},[117,3098,399],{"class":304},[117,3100,3101,3103,3105,3107],{"class":119,"line":1304},[117,3102,405],{"class":249},[117,3104,408],{"class":253},[117,3106,411],{"class":380},[117,3108,414],{"class":253},[117,3110,3111,3113,3115,3118,3120,3122],{"class":119,"line":1310},[117,3112,420],{"class":123},[117,3114,350],{"class":249},[117,3116,3117],{"class":253}," '^Codec:|^Vendor Id:|^Subsystem Id:'",[117,3119,428],{"class":253},[117,3121,411],{"class":380},[117,3123,433],{"class":253},[117,3125,3126],{"class":119,"line":1315},[117,3127,439],{"class":304},[13,3129,3130],{},"进一步检查：",[47,3132,3134],{"className":111,"code":3133,"language":113,"meta":53,"style":53},"grep -A20 'Node 0x16' \u002Fproc\u002Fasound\u002Fcard0\u002Fcodec#0\ngrep -A20 'Node 0x17' \u002Fproc\u002Fasound\u002Fcard0\u002Fcodec#0\ngrep -i -A10 -B2 'GPIO' \u002Fproc\u002Fasound\u002Fcard0\u002Fcodec#0\n",[17,3135,3136,3146,3156],{"__ignoreMap":53},[117,3137,3138,3140,3142,3144],{"class":119,"line":120},[117,3139,476],{"class":123},[117,3141,479],{"class":249},[117,3143,482],{"class":253},[117,3145,485],{"class":253},[117,3147,3148,3150,3152,3154],{"class":119,"line":257},[117,3149,476],{"class":123},[117,3151,479],{"class":249},[117,3153,520],{"class":253},[117,3155,485],{"class":253},[117,3157,3158,3160,3162,3164,3166,3168],{"class":119,"line":266},[117,3159,476],{"class":123},[117,3161,553],{"class":249},[117,3163,556],{"class":249},[117,3165,559],{"class":249},[117,3167,562],{"class":253},[117,3169,485],{"class":253},[13,3171,3172],{},"检查耳机检测：",[47,3174,3175],{"className":111,"code":1022,"language":113,"meta":53,"style":53},[17,3176,3177],{"__ignoreMap":53},[117,3178,3179,3181,3183,3185,3187,3189],{"class":119,"line":120},[117,3180,664],{"class":123},[117,3182,730],{"class":253},[117,3184,733],{"class":253},[117,3186,848],{"class":249},[117,3188,1037],{"class":249},[117,3190,1040],{"class":249},[33,3192],{},[102,3194,3196],{"id":3195},"_22-环境","22. 环境",[13,3198,3199],{},"本文实际验证环境：",[47,3201,3204],{"className":3202,"code":3203,"language":52,"meta":53},[50],"OS            : Ubuntu\nKernel        : 7.0.0-34-generic\nMachine       : HUAWEI CREF-XX\nProduct Ver.  : M1010\nBoard         : CREF-XX-PCB\nAudio         : Intel Alder Lake PCH-P\nALSA          : sof-hda-dsp\nCodec         : Conexant SN6140\nVendor ID     : 0x14f11f87\nSubsystem ID  : 0x19e53281\n",[17,3205,3203],{"__ignoreMap":53},[13,3207,3208],{},"最终结果：",[47,3210,3213],{"className":3211,"code":3212,"language":52,"meta":53},[50],"插入耳机 → 仅耳机出声\n拔出耳机 → 自动恢复笔记本扬声器\n重启系统 → 自动修复继续生效\n",[17,3214,3212],{"__ignoreMap":53},[33,3216],{},[36,3218,3219],{"id":3219},"参考",[13,3221,3222],{},"Linux 内核中的 HDA Verb 定义可以在：",[47,3224,3227],{"className":3225,"code":3226,"language":52,"meta":53},[50],"include\u002Fsound\u002Fhda_verbs.h\n",[17,3228,3226],{"__ignoreMap":53},[13,3230,3231],{},"中查看。",[13,3233,3234],{},"本文涉及的关键定义包括：",[47,3236,3240],{"className":3237,"code":3238,"language":3239,"meta":53,"style":53},"language-c shiki shiki-themes github-light github-dark","AC_VERB_GET_PIN_SENSE          0x0f09\nAC_VERB_SET_CONNECT_SEL        0x701\nAC_VERB_SET_EAPD_BTLENABLE     0x70c\nAC_VERB_SET_GPIO_DATA          0x715\nAC_VERB_SET_GPIO_MASK          0x716\nAC_VERB_SET_GPIO_DIRECTION     0x717\n\nAC_PINSENSE_PRESENCE           (1 \u003C\u003C 31)\n","c",[17,3241,3242,3247,3252,3257,3262,3267,3272,3276],{"__ignoreMap":53},[117,3243,3244],{"class":119,"line":120},[117,3245,3246],{},"AC_VERB_GET_PIN_SENSE          0x0f09\n",[117,3248,3249],{"class":119,"line":257},[117,3250,3251],{},"AC_VERB_SET_CONNECT_SEL        0x701\n",[117,3253,3254],{"class":119,"line":266},[117,3255,3256],{},"AC_VERB_SET_EAPD_BTLENABLE     0x70c\n",[117,3258,3259],{"class":119,"line":273},[117,3260,3261],{},"AC_VERB_SET_GPIO_DATA          0x715\n",[117,3263,3264],{"class":119,"line":279},[117,3265,3266],{},"AC_VERB_SET_GPIO_MASK          0x716\n",[117,3268,3269],{"class":119,"line":287},[117,3270,3271],{},"AC_VERB_SET_GPIO_DIRECTION     0x717\n",[117,3273,3274],{"class":119,"line":296},[117,3275,270],{"emptyLinePlaceholder":269},[117,3277,3278],{"class":119,"line":311},[117,3279,3280],{},"AC_PINSENSE_PRESENCE           (1 \u003C\u003C 31)\n",[13,3282,3283,3284,3287],{},"建议在其他机型上应用本文方案之前，先根据自身 ",[17,3285,3286],{},"\u002Fproc\u002Fasound\u002Fcard*\u002Fcodec#*"," 输出验证 Codec、Node 和 GPIO 拓扑，而不要直接照搬寄存器参数。",[3289,3290,3291],"style",{},"html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html.dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html pre.shiki code .sScJk, html code.shiki .sScJk{--shiki-default:#6F42C1;--shiki-dark:#B392F0}html pre.shiki code .sj4cs, html code.shiki .sj4cs{--shiki-default:#005CC5;--shiki-dark:#79B8FF}html pre.shiki code .sZZnC, html code.shiki .sZZnC{--shiki-default:#032F62;--shiki-dark:#9ECBFF}html pre.shiki code .szBVR, html code.shiki .szBVR{--shiki-default:#D73A49;--shiki-dark:#F97583}html pre.shiki code .sVt8B, html code.shiki .sVt8B{--shiki-default:#24292E;--shiki-dark:#E1E4E8}",{"title":53,"searchDepth":257,"depth":257,"links":3293},[3294,3295,3296,3297,3301],{"id":38,"depth":257,"text":39},{"id":2250,"depth":257,"text":2250},{"id":2262,"depth":257,"text":2262},{"id":2274,"depth":257,"text":2274,"children":3298},[3299,3300],{"id":2433,"depth":266,"text":2395},{"id":2510,"depth":266,"text":2414},{"id":3219,"depth":257,"text":3219},"Ubuntu 下 Huawei MateBook 16s 有线耳机与扬声器同时出声问题的排查与修复记录。",false,"md",{},"\u002Farticles\u002Fubuntu-huawei-matebook-sn6140-headphone-speaker-fix","2026-09-25",{"title":5,"description":3302},"articles\u002Fubuntu-huawei-matebook-sn6140-headphone-speaker-fix",[3311,3312,3313],"Ubuntu","音频","Huawei MateBook 16s",null,"0ACTUuYOz5KKSeXJMyplyu9FhidOGdpi2qmamXe-2WY",1791276707824]