Nội dung bài viết
Chuẩn bị
Để bắt đầu việc patch AppleHDA, bạn cần có sẵn: PlistEdit Pro hoặc Xcode, Platforms.xml, layout11.xml, layout26.xml…
Dump codec
Dùng Ubuntu(bạn có thể dùng Ubuntu Live USB nếu chưa có sẵn Ubuntu trên máy) mở Terminal gõ:
cat /proc/asound/card0/codec#0 > ~/Desktop/codec_dump_0.txt
(or)
cat /proc/asound/card0/codec1 > ~/Desktop/codec_dump_1.txt
(or)
cat /proc/asound/card0/codec#2 > ~/Desktop/codec_dump_2.txt
Sau đó bạn copy codec_dump ở Desktop vào đâu đó để đem sang macOS nhé!
Lấy thông tin cơ bản của codec
Những thông tin chính cần trích xuất:
1. Codec 2. Address 3. Vendor Id 4. Codec verbs
Với 3 thông tin đầu tiên, bạn có thể dễ dàng lấy bằng cách mở file chứa tên codec của máy bạn trong CodecDump.zip và nhìn vào dòng 1, dòng 2 và dòng 4

Với Vendor Id bạn cần chuyển nó sang hệ decimal bằng bất kì công cụ chuyển nào

Xác định codecverbs
B1: Các bạn tìm “Pin Complex” trong file chứa tên codec của máy bạn, node nào có thì copy ra 1 nơi rồi tìm tiếp “[N/A]”, nếu node nào có thì xoá node đó đi. Với codec ALC255 của mình thì nhận lại được như sau:
Node 0x12 [Pin Complex] wcaps 0x40040b: Stereo Amp-In
Control: name="Internal Mic Boost Volume", index=0, device=0
ControlAmp: chs=3, dir=In, idx=0, ofs=0
Amp-In caps: ofs=0x00, nsteps=0x03, stepsize=0x27, mute=0
Amp-In vals: [0x00 0x00]
Pincap 0x00000020: IN
Pin Default 0x90a60160: [Fixed] Mic at Int N/A
Conn = Digital, Color = Unknown
DefAssociation = 0x6, Sequence = 0x0
Misc = NO_PRESENCE
Pin-ctls: 0x20: IN
Power states: D0 D1 D2 D3 EPSS
Power: setting=D0, actual=D0
Node 0x14 [Pin Complex] wcaps 0x40058d: Stereo Amp-Out
Control: name="Speaker Playback Switch", index=0, device=0
ControlAmp: chs=3, dir=Out, idx=0, ofs=0
Amp-Out caps: ofs=0x00, nsteps=0x00, stepsize=0x00, mute=1
Amp-Out vals: [0x00 0x00]
Pincap 0x00010014: OUT EAPD Detect
EAPD 0x2: EAPD
Pin Default 0x90170120: [Fixed] Speaker at Int N/A
Conn = Analog, Color = Unknown
DefAssociation = 0x2, Sequence = 0x0
Misc = NO_PRESENCE
Pin-ctls: 0x40: OUT
Unsolicited: tag=00, enabled=0
Power states: D0 D1 D2 D3 EPSS
Power: setting=D0, actual=D0
Connection: 1
0x0c
Node 0x21 [Pin Complex] wcaps 0x40058d: Stereo Amp-Out
Control: name="Headphone Playback Switch", index=0, device=0
ControlAmp: chs=3, dir=Out, idx=0, ofs=0
Amp-Out caps: ofs=0x00, nsteps=0x00, stepsize=0x00, mute=1
Amp-Out vals: [0x80 0x80]
Pincap 0x0001001c: OUT HP EAPD Detect
EAPD 0x2: EAPD
Pin Default 0x02211030: [Jack] HP Out at Ext Front
Conn = 1/8, Color = Black
DefAssociation = 0x3, Sequence = 0x0
Pin-ctls: 0xc0: OUT HP
Unsolicited: tag=01, enabled=1
Power states: D0 D1 D2 D3 EPSS
Power: setting=D0, actual=D0
Connection: 2
0x0c 0x0d*
Với laptop thường chỉ có loa trong(Speaker), tai nghe(HP), mic trong(Mic at Int), mic ngoài(Mic at Ext).
Với máy mình thì dùng combojack nên chỉ có 3 node Speaker, HP, Mic at Int. Có nhiều bạn sẽ hỏi như vậy thì sẽ chấp nhận tạch Mic at Ext sao? Hmm cũng có thể đấy nhưng là khi bạn lười thực hiện nó mà thôi 🙂 Bắt đầu nào!
Trong các node chứ Pin Complex, các bạn tìm tiếp “Headset Mic Boost Volume” và “Headphone Mic Boost Volume” rồi lưu lại nhé!
Node 0x19 [Pin Complex] wcaps 0x40048b: Stereo Amp-In Control: name="Headset Mic Boost Volume", index=0, device=0 ControlAmp: chs=3, dir=In, idx=0, ofs=0 Amp-In caps: ofs=0x00, nsteps=0x03, stepsize=0x27, mute=0 Amp-In vals: [0x00 0x00] Pincap 0x00003724: IN Detect Vref caps: HIZ 50 GRD 80 100 Pin Default 0x411111f0: [N/A] Speaker at Ext Rear Conn = 1/8, Color = Black DefAssociation = 0xf, Sequence = 0x0 Misc = NO_PRESENCE Pin-ctls: 0x24: IN VREF_80 Unsolicited: tag=00, enabled=0 Power states: D0 D1 D2 D3 EPSS Power: setting=D0, actual=D0 Node 0x1a [Pin Complex] wcaps 0x40048b: Stereo Amp-In Control: name="Headphone Mic Boost Volume", index=0, device=0 ControlAmp: chs=3, dir=In, idx=0, ofs=0 Amp-In caps: ofs=0x00, nsteps=0x03, stepsize=0x27, mute=0 Amp-In vals: [0x00 0x00] Pincap 0x00003724: IN Detect Vref caps: HIZ 50 GRD 80 100 Pin Default 0x411111f0: [N/A] Speaker at Ext Rear Conn = 1/8, Color = Black DefAssociation = 0xf, Sequence = 0x0 Misc = NO_PRESENCE Pin-ctls: 0x20: IN VREF_HIZ Unsolicited: tag=00, enabled=0 Power states: D0 D1 D2 D3 EPSS Power: setting=D0, actual=D0
Và để bài viết không quá khó hiểu thêm thì việc fix combojack mình sẽ tách riêng ra 1 phần để không làm ảnh hưởng đến những ai patch máy không có combojack
B2: Xuất Verbs data, Node và Pin Default
Nhìn vào Pin Complex ở trên, ta sẽ xác định được Node + Pin Default còn để xuất verb data, bạn cần đọc 2 số từ phải sang trái của Pin Default.
Node 14 : Pin Default 0x90170120 Verb data: 20 01 17 90 Node 21 : Pin Default 0x02211030 Verb data: 30 10 21 02 Node 12 : Pin Default 0x90a60160 Verb data: 60 01 a6 90
Với 2 node nữa máy có combojack
Node 19 : Pin Default 0x411111f0 Verb data: f0 11 11 41 Node 1a : Pin Default 0x411111f0 Verb data: f0 11 11 41
Vậy từng số, từng cặp verb data chứa thông tin gì? Cùng tìm hiểu nhé!
- Cặp đầu tiên (XY): 20 30 60
– X là thông tin port. Nếu có 1 số lặp lại tới 2 hoặc 3 lần ở X, bạn cần thay đổi để tránh trùng lặp. VD: với 20 30 30 thì ta thấy có 2 số 3 trùng nhau nên ta phải đổi 1 số 3 thành bất kì số nào để không trùng với 2 số X còn lại như 20 30 50
– Y là thông tin kênh xuất ra. Ở đây bạn chỉnh hết về 0
Với các node thường ở máy mình thì không cần động đậy gì phần này rồi
Dành cho combojack: f0 f0
– Ở X thì mình đã thấy sự lập lại của f, nên mình sẽ chỉnh f của node 19 thành 7
– Ở Y thì không cần chỉnh gì hết
Như vậy kết quả là 70 f0
- Cặp thứ hai (XY): 01 10 01
– X là màu của cổng âm thanh
– Y là thông tin jack cắm. Chỉnh thành 0 nếu là node cho Ext, còn 1 nếu node đó dành cho Ixt
Với các node thường ở máy mình thì không cần động đậy gì phần này rồi
Dành cho combojack: 11 11
– Ở X của node 19 mình sẽ giữ nguyên nó vì mình sẽ dùng node này để liên kết với node 21, còn với X ở node 1a thì mình sẽ chuyển nó về 0 để che đi nút không hợp lệ nhằm ngăn chặn tiếng ồn hoặc thiếu tiếng
– Ở Y của node 19 mình sẽ chuyển thành 0 vì đây là thiết bị Ext, còn với node 1a thì vẫn như ở X.
Như vậy kết quả là 10 00
- Cặp thứ ba (XY): 17 21 a6
– X là thiết bị âm thanh
Line Out 0 Speaker 1 HP Out 2 CD 3 SPDIF Out 4 Digital Other Out 5 Modem Line Side 6 Modem Handset Side 7 Line In 8 AUX 9 Mic In A Telephony B SPDIF In C Digital Other In D Reserved E Other F
– Y là cổng kết nối của thiết bị âm thanh
Unknown 0 1/8" stereo/mono 1 1/4" stereo/mono 2 ATAPI internal 3 RCA 4 Optical 5 Other Digital 6 Other Analog 7 Multichannel Analog (DIN) 8 XLR/Professional 9 RJ-11 (Modem) A Combination B Other F
Với các node thường ở máy mình thì chỉ cần đổi Y của node 12 thành 0 nhằm mục đích bật thêm tính năng Ambient noise reduction
Dành cho combojack: 11 11
– Ở X của node 19 mình sẽ chuyển thành a để nó macOS nhận nó là Mic, còn với node 1a sẽ là 0
– Ở Y của node 19 mình sẽ chuyển thành b, tại sao thì các bạn dich ra là biết nhé! Còn node 1a thì vẫn chả khác gì
Như vậy kết quả là ab 00
- Cột thứ tư (XY): 90 02 90
– X là giá trị giúp ứng dụng biết được là đang kết nối với Speaker hay HP, Mic,…
– Y là vị trí cổng kết nối
Với các node thường ở máy mình thì không cần động đậy gì phần này rồi
Dành cho combojack: 41 41
– Ở X của node 19 mình sẽ chuyển thành 0 còn node 1a thì giữ nguyên
– Ở Y của node 19 mình sẽ dựa vào node 21 còn node 1a thì lại về 0 thôi
Như vậy kết quá là 02 40
Tổng kết: Như vậy là ta đã có verb data chuẩn như sau
Node 14 : Verb data: 20 01 17 90 Node 21 : Verb data: 30 10 21 02 Node 12 : Verb data: 60 01 a0 90
Với 2 node nữa máy có combojack
Node 19 : Pin Default 0x411111f0 Verb data: 70 10 ab 02 Node 1a : Pin Default 0x411111f0 Verb data: f0 00 00 40
B3: Tính toán verbs codec
Công thức: Codec Address + NodeID + Verb Commands + Verb data
Codec Address = 0 (Xác định ở B1)
NodeID 14, 21, 12 (Xác định ở B2)
Verb Commands = 71c, 71d, 71e, 71f và 70c dành cho EAPD
Verb data (Xác định ở B2)
VD: con ALC255 của máy mình
Node 14: 0 + 14 + 71c + 20 = 01471c20
0 + 14 + 71d + 01 = 01471d01
0 + 14 + 71e + 17 = 01471e17
0 + 14 + 71f + 90 = 01471f90
0 + 14 + 70c + 02 = 01470c02 (EDPD)
Node 21: 0 + 21 + 71c + 30 = 02171c30
0 + 21 + 71d + 10 = 02171d10
0 + 21 + 71e + 21 = 02171e21
0 + 21 + 71f + 02 = 02171f02
Node 12: 0 + 12 + 71c + 60 = 01271c60
0 + 12 + 71d + 01 = 01271d01
0 + 12 + 71e + a0 = 01271ea0
0 + 12 + 71f + 90 = 01271f90
Nếu máy bạn có thêm Node cho Line In thì bạn cũng làm tương tự như vậy nhé!
Với 2 node nữa máy có combojack
Node 19: 0 + 19 + 71c + 70 = 01971c70
0 + 19 + 71d + 10 = 01971d10
0 + 19 + 71e + ab = 01971eab
0 + 19 + 71f + 02 = 01971f02
Node 1a: 0 + 1a + 71c + f0 = 01a71cf0
0 + 1a + 71d + 00 = 01a71d00
0 + 1a + 71e + 00 = 01a71e00
0 + 1a + 71f + 40 = 01a71f40
Bây giờ chúng ta sẽ sắp chúng lại, ta được:
01471c20 01471d01 01471e17 01471f90 01470c02 02171c30 02171d10 02171e21 02171f02 01271c60 01271d01 01271ea0 01271f90 01971c70 01971d10 01971eab 01971f02 01a71cf0 01a71d00 01a71e00 01a71f40
Lưu lại 1 chỗ rồi tiếp tục làm nhé!
Ngoài lề: 1 bài viết mà chỉ có 1 vd thì chắc cũng sẽ là hơi khó với các bạn nên mình sẽ đưa thêm 1 codec vào nữa cho các bạn dễ hiểu nhé
VD: với codec CX20590
01971c40 01971d10 01971e21 01971f04 01b71c30 01b71d10 01b71ea1 01b71f04 01f71c10 01f71d01 01f71e17 01f71f92 02371c50 02371d01 02371ea6 02371f95 01b70c02
Có: Node 1f là Speaker, Node 19 là HP, Node 23 là Mic Int, Node 1b là Mic Ext. Vì macOS không hỗ trợ Mic ngoài nên ta phải chuyển “a1” thành “81” để chuyển thành LineIn ở node 1b, còn ở node 23 ta cần chuyển “a6” thành “a0” để kích hoạt được Ambient noise reduction. Sau khi chỉnh ta được:
01971c40 01971d10 01971e21 01971f04 01b71c30 01b71d10 01b71e81 01b71f04 01f71c10 01f71d01 01f71e17 01f71f92 01b70c02 02371c50 02371d01 02371ea6 02371f95
Xác định pathmap
Thủ công:
B1: Các bạn tìm “Audio Mixer/Selector” trong file chứa tên codec của máy bạn, node nào có thì copy ra 1 nơi rồi làm tương tự với “Audio Output” và “Audio Input“. Với codec ALC255 của mình thì nhận lại được như sau:
- Audio Mixer/Selector
Node 0x0b [Audio Mixer] wcaps 0x20010b: Stereo Amp-In Control: name="Headset Mic Playback Volume", index=0, device=0 ControlAmp: chs=3, dir=In, idx=1, ofs=0 Control: name="Headset Mic Playback Switch", index=0, device=0 ControlAmp: chs=3, dir=In, idx=1, ofs=0 Control: name="Headphone Mic Playback Volume", index=0, device=0 ControlAmp: chs=3, dir=In, idx=2, ofs=0 Control: name="Headphone Mic Playback Switch", index=0, device=0 ControlAmp: chs=3, dir=In, idx=2, ofs=0 Control: name="Beep Playback Volume", index=0, device=0 ControlAmp: chs=3, dir=In, idx=4, ofs=0 Control: name="Beep Playback Switch", index=0, device=0 ControlAmp: chs=3, dir=In, idx=4, ofs=0 Amp-In caps: ofs=0x17, nsteps=0x1f, stepsize=0x05, mute=1 Amp-In vals: [0x80 0x80] [0x80 0x80] [0x80 0x80] [0x80 0x80] [0x80 0x80] Connection: 5 0x18 0x19 0x1a 0x1b 0x1d Node 0x0c [Audio Mixer] wcaps 0x20010b: Stereo Amp-In Amp-In caps: ofs=0x00, nsteps=0x00, stepsize=0x00, mute=1 Amp-In vals: [0x00 0x00] [0x80 0x80] Connection: 2 0x02 0x0b Node 0x0d [Audio Mixer] wcaps 0x20010b: Stereo Amp-In Amp-In caps: ofs=0x00, nsteps=0x00, stepsize=0x00, mute=1 Amp-In vals: [0x00 0x00] [0x80 0x80] Connection: 2 0x03 0x0b Node 0x0f [Audio Mixer] wcaps 0x20010a: Mono Amp-In Amp-In caps: ofs=0x00, nsteps=0x00, stepsize=0x00, mute=1 Amp-In vals: [0x00 0x00] Connection: 1 0x0d Node 0x22 [Audio Mixer] wcaps 0x20010b: Stereo Amp-In Amp-In caps: ofs=0x00, nsteps=0x00, stepsize=0x00, mute=1 Amp-In vals: [0x80 0x80] [0x80 0x80] [0x80 0x80] [0x80 0x80] [0x80 0x80] [0x80 0x80] Connection: 6 0x18 0x19 0x1a 0x1b 0x1d 0x0b Node 0x23 [Audio Mixer] wcaps 0x20010b: Stereo Amp-In Amp-In caps: ofs=0x00, nsteps=0x00, stepsize=0x00, mute=1 Amp-In vals: [0x80 0x80] [0x80 0x80] [0x80 0x80] [0x80 0x80] [0x80 0x80] [0x80 0x80] [0x00 0x00] Connection: 7 0x18 0x19 0x1a 0x1b 0x1d 0x0b 0x12
- Audio Output
Node 0x02 [Audio Output] wcaps 0x41d: Stereo Amp-Out Control: name="Speaker Playback Volume", index=0, device=0 ControlAmp: chs=3, dir=Out, idx=0, ofs=0 Amp-Out caps: ofs=0x57, nsteps=0x57, stepsize=0x02, mute=0 Amp-Out vals: [0x3c 0x3c] Converter: stream=1, channel=0 PCM: rates [0x60]: 44100 48000 bits [0xe]: 16 20 24 formats [0x1]: PCM Power states: D0 D1 D2 D3 EPSS Power: setting=D0, actual=D0 Node 0x03 [Audio Output] wcaps 0x41d: Stereo Amp-Out Control: name="Headphone Playback Volume", index=0, device=0 ControlAmp: chs=3, dir=Out, idx=0, ofs=0 Device: name="ALC3234 Analog", type="Audio", device=0 Amp-Out caps: ofs=0x57, nsteps=0x57, stepsize=0x02, mute=0 Amp-Out vals: [0x00 0x00] Converter: stream=1, channel=0 PCM: rates [0x60]: 44100 48000 bits [0xe]: 16 20 24 formats [0x1]: PCM Power states: D0 D1 D2 D3 EPSS Power: setting=D0, actual=D0 Node 0x06 [Audio Output] wcaps 0x611: Stereo Digital Converter: stream=0, channel=0 Digital: Digital category: 0x0 IEC Coding Type: 0x0 PCM: rates [0x5e0]: 44100 48000 88200 96000 192000 bits [0xe]: 16 20 24 formats [0x1]: PCM Power states: D0 D1 D2 D3 EPSS Power: setting=D0, actual=D0
- Audio Input
Node 0x08 [Audio Input] wcaps 0x10051b: Stereo Amp-In Control: name="Capture Volume", index=0, device=0 ControlAmp: chs=3, dir=In, idx=0, ofs=0 Control: name="Capture Switch", index=0, device=0 ControlAmp: chs=3, dir=In, idx=0, ofs=0 Device: name="ALC3234 Analog", type="Audio", device=0 Amp-In caps: ofs=0x17, nsteps=0x3f, stepsize=0x02, mute=1 Amp-In vals: [0x27 0x27] Converter: stream=0, channel=0 SDI-Select: 0 PCM: rates [0x560]: 44100 48000 96000 192000 bits [0xe]: 16 20 24 formats [0x1]: PCM Power states: D0 D1 D2 D3 EPSS Power: setting=D0, actual=D0 Connection: 1 0x23 Node 0x09 [Audio Input] wcaps 0x10051b: Stereo Amp-In Amp-In caps: ofs=0x17, nsteps=0x3f, stepsize=0x02, mute=1 Amp-In vals: [0x97 0x97] Converter: stream=0, channel=0 SDI-Select: 0 PCM: rates [0x560]: 44100 48000 96000 192000 bits [0xe]: 16 20 24 formats [0x1]: PCM Power states: D0 D1 D2 D3 EPSS Power: setting=D0, actual=D0 Connection: 1 0x22
Để bắt đầu, chúng ta cần phải nắm công thức sau:
- Với Speaker và HP: Pin Complex->(Audio Mixer)->Audio Output
- Với Mic và LineIn: Audio Input->(Audio Selector/Mixer)->Pin Complex
Lưu ý: Nếu có 2 dấu “(” và “)” tức là có thể có hoặc có thể không
1. Speaker:
Đầu tiên bạn mở lại file chứa Pin Complex, tìm “Speaker”
Node 0x14 [Pin Complex] wcaps 0x40058d: Stereo Amp-Out Control: name="Speaker Playback Switch", index=0, device=0 ControlAmp: chs=3, dir=Out, idx=0, ofs=0 Amp-Out caps: ofs=0x00, nsteps=0x00, stepsize=0x00, mute=1 Amp-Out vals: [0x00 0x00] Pincap 0x00010014: OUT EAPD Detect EAPD 0x2: EAPD Pin Default 0x90170120: [Fixed] Speaker at Int N/A Conn = Analog, Color = Unknown DefAssociation = 0x2, Sequence = 0x0 Misc = NO_PRESENCE Pin-ctls: 0x40: OUT Unsolicited: tag=00, enabled=0 Power states: D0 D1 D2 D3 EPSS Power: setting=D0, actual=D0 Connection: 1 0x0c
Như vậy ta xác định được Pin Complex của Speaker là 0x14, nhìn xuống phần Connection của node 0x14 ta thấy 0x0c. Lại tìm “0x0c” ở file chứa Audio Mixer
Node 0x0c [Audio Mixer] wcaps 0x20010b: Stereo Amp-In Amp-In caps: ofs=0x00, nsteps=0x00, stepsize=0x00, mute=1 Amp-In vals: [0x00 0x00] [0x80 0x80] Connection: 2 0x02 0x0b
Như vậy Speaker có kết nối qua Audio Mixer nhưng ở Connection lại có 2 node nhưng không hề có dấu hiệu ưu tiên vậy phải chọn node nào. Đến giờ thử nghiệm rồi đây, mình sẽ chọn node 0x02 rồi tìm ở file chứa Audio Output
Node 0x02 [Audio Output] wcaps 0x41d: Stereo Amp-Out Control: name="Speaker Playback Volume", index=0, device=0 ControlAmp: chs=3, dir=Out, idx=0, ofs=0 Amp-Out caps: ofs=0x57, nsteps=0x57, stepsize=0x02, mute=0 Amp-Out vals: [0x3c 0x3c] Converter: stream=1, channel=0 PCM: rates [0x60]: 44100 48000 bits [0xe]: 16 20 24 formats [0x1]: PCM Power states: D0 D1 D2 D3 EPSS Power: setting=D0, actual=D0
Thật vui mừng khi chỉ có 1 node 0x02 là có, còn 0x0b thì không. Như vậy ta đã xác định được pathmap của Speaker: 0x14 -> 0x0c -> 0x02, chuyển hết sang hệ decimal ta được: 20 -> 12 -> 2
2. HP: Mở lại file chứa Pin Complex, tìm “HP“
Node 0x21 [Pin Complex] wcaps 0x40058d: Stereo Amp-Out Control: name="Headphone Playback Switch", index=0, device=0 ControlAmp: chs=3, dir=Out, idx=0, ofs=0 Amp-Out caps: ofs=0x00, nsteps=0x00, stepsize=0x00, mute=1 Amp-Out vals: [0x80 0x80] Pincap 0x0001001c: OUT HP EAPD Detect EAPD 0x2: EAPD Pin Default 0x02211030: [Jack] HP Out at Ext Front Conn = 1/8, Color = Black DefAssociation = 0x3, Sequence = 0x0 Pin-ctls: 0xc0: OUT HP Unsolicited: tag=01, enabled=1 Power states: D0 D1 D2 D3 EPSS Power: setting=D0, actual=D0 Connection: 2 0x0c 0x0d*
Như vậy ta xác định được Pin Complex của Speaker là 0x21, nhìn xuống phần Connection ta sẽ thấy 0x0d có 1 dấu * đằng sau tức đây là kết nối ưu tiên. Lại tìm “0x0d” ở file chứa Audio Mixer
Node 0x0d [Audio Mixer] wcaps 0x20010b: Stereo Amp-In Amp-In caps: ofs=0x00, nsteps=0x00, stepsize=0x00, mute=1 Amp-In vals: [0x00 0x00] [0x80 0x80] Connection: 2 0x03 0x0b
Lại gặp tương tự trường hợp như ở Speaker, nhưng vì đã xác định được Speaker rồi nên chúng ta cần tránh sự lặp lại kết nối cho nên ta xác định được pathmap của HP: 0x21 -> 0x0d -> 0x03, chuyển hết sang hệ decimal ta được: 33 -> 13 -> 3
3. Mic: Mở lại file chứa Pin Complex, tìm “Mic“
Node 0x12 [Pin Complex] wcaps 0x40040b: Stereo Amp-In Control: name="Internal Mic Boost Volume", index=0, device=0 ControlAmp: chs=3, dir=In, idx=0, ofs=0 Amp-In caps: ofs=0x00, nsteps=0x03, stepsize=0x27, mute=0 Amp-In vals: [0x00 0x00] Pincap 0x00000020: IN Pin Default 0x90a60160: [Fixed] Mic at Int N/A Conn = Digital, Color = Unknown DefAssociation = 0x6, Sequence = 0x0 Misc = NO_PRESENCE Pin-ctls: 0x20: IN Power states: D0 D1 D2 D3 EPSS Power: setting=D0, actual=D0
Như vậy không hề có thông tin kết nối trực tiếp vào, ta sẽ phải xác định từ Audio Input/Mixer/Selector. Ở Audio Mixer mình đã tìm được node có kết nối với 0x12
Node 0x23 [Audio Mixer] wcaps 0x20010b: Stereo Amp-In Amp-In caps: ofs=0x00, nsteps=0x00, stepsize=0x00, mute=1 Amp-In vals: [0x80 0x80] [0x80 0x80] [0x80 0x80] [0x80 0x80] [0x80 0x80] [0x80 0x80] [0x00 0x00] Connection: 7 0x18 0x19 0x1a 0x1b 0x1d 0x0b 0x12
Như vậy Audio Mixer là 0x23, ta tìm tiếp “0x23” ở file chứa Audio Input. Nhận lại được node 0x08
Node 0x08 [Audio Input] wcaps 0x10051b: Stereo Amp-In Control: name="Capture Volume", index=0, device=0 ControlAmp: chs=3, dir=In, idx=0, ofs=0 Control: name="Capture Switch", index=0, device=0 ControlAmp: chs=3, dir=In, idx=0, ofs=0 Device: name="ALC3234 Analog", type="Audio", device=0 Amp-In caps: ofs=0x17, nsteps=0x3f, stepsize=0x02, mute=1 Amp-In vals: [0x27 0x27] Converter: stream=0, channel=0 SDI-Select: 0 PCM: rates [0x560]: 44100 48000 96000 192000 bits [0xe]: 16 20 24 formats [0x1]: PCM Power states: D0 D1 D2 D3 EPSS Power: setting=D0, actual=D0 Connection: 1 0x23
Như vậy chúng ta đã xác định được pathmap của Mic: 0x08 -> 0x23 -> 0x12, chuyển hết sang hệ decimal ta được: 8 -> 35 -> 18
Có vẻ như những thứ làm mất nhiều thời gian của chúng ta đã 1 cái 1 nơi nhỉ? Cùng góp nó vào 1 chỗ nhé!
- Speaker: 20 -> 12 -> 2
- HP: 33 -> 13 -> 3
- Mic: 8 -> 35 -> 18
Nếu có thêm LineIn thì việc xác định cũng tương tự như trên nhé!
Đối với combojack: Công thức sẽ giống với công thức của Mic và LineIn
1. Headset: Hãy bắt đầu với Pin Complex
Node 0x19 [Pin Complex] wcaps 0x40048b: Stereo Amp-In Control: name="Headset Mic Boost Volume", index=0, device=0 ControlAmp: chs=3, dir=In, idx=0, ofs=0 Amp-In caps: ofs=0x00, nsteps=0x03, stepsize=0x27, mute=0 Amp-In vals: [0x00 0x00] Pincap 0x00003724: IN Detect Vref caps: HIZ 50 GRD 80 100 Pin Default 0x411111f0: [N/A] Speaker at Ext Rear Conn = 1/8, Color = Black DefAssociation = 0xf, Sequence = 0x0 Misc = NO_PRESENCE Pin-ctls: 0x24: IN VREF_80 Unsolicited: tag=00, enabled=0 Power states: D0 D1 D2 D3 EPSS Power: setting=D0, actual=D0
Như vậy là chúng ta không thấy bất kì node được kết nối trực tiếp nào nên mình đành phải tìm từ Audio Input/Mixer/Selector và rồi mình đã tìm được 3 node có kết nối với node 19 này ở Audio Mixer.
Node 0x0b [Audio Mixer] wcaps 0x20010b: Stereo Amp-In Control: name="Headset Mic Playback Volume", index=0, device=0 ControlAmp: chs=3, dir=In, idx=1, ofs=0 Control: name="Headset Mic Playback Switch", index=0, device=0 ControlAmp: chs=3, dir=In, idx=1, ofs=0 Control: name="Headphone Mic Playback Volume", index=0, device=0 ControlAmp: chs=3, dir=In, idx=2, ofs=0 Control: name="Headphone Mic Playback Switch", index=0, device=0 ControlAmp: chs=3, dir=In, idx=2, ofs=0 Control: name="Beep Playback Volume", index=0, device=0 ControlAmp: chs=3, dir=In, idx=4, ofs=0 Control: name="Beep Playback Switch", index=0, device=0 ControlAmp: chs=3, dir=In, idx=4, ofs=0 Amp-In caps: ofs=0x17, nsteps=0x1f, stepsize=0x05, mute=1 Amp-In vals: [0x80 0x80] [0x80 0x80] [0x80 0x80] [0x80 0x80] [0x80 0x80] Connection: 5 0x18 0x19 0x1a 0x1b 0x1d Node 0x22 [Audio Mixer] wcaps 0x20010b: Stereo Amp-In Amp-In caps: ofs=0x00, nsteps=0x00, stepsize=0x00, mute=1 Amp-In vals: [0x80 0x80] [0x80 0x80] [0x80 0x80] [0x80 0x80] [0x80 0x80] [0x80 0x80] Connection: 6 0x18 0x19 0x1a 0x1b 0x1d 0x0b Node 0x23 [Audio Mixer] wcaps 0x20010b: Stereo Amp-In Amp-In caps: ofs=0x00, nsteps=0x00, stepsize=0x00, mute=1 Amp-In vals: [0x80 0x80] [0x80 0x80] [0x80 0x80] [0x80 0x80] [0x80 0x80] [0x80 0x80] [0x00 0x00] Connection: 7 0x18 0x19 0x1a 0x1b 0x1d 0x0b 0x12
Oh, có tới 3 Audio Mixer thì bây giờ ta phải làm như nào để biết được node cần tìm đây? Cách đơn giản nhất là lấy node đó đi tìm tiếp thôi
Mình thử đầu tiên với node 0b thì mình chợt nhận ra nó lại được kết nối tới 2 node còn lại là node 22 và node 23 nên chắc rằng chúng ta sẽ loại nó đi vì không cần dựa vào nó. Còn với 2 node còn lại thì node 22 được kết nối với node 09 và node 23 được kết nối với node 08
Node 0x08 [Audio Input] wcaps 0x10051b: Stereo Amp-In Control: name="Capture Volume", index=0, device=0 ControlAmp: chs=3, dir=In, idx=0, ofs=0 Control: name="Capture Switch", index=0, device=0 ControlAmp: chs=3, dir=In, idx=0, ofs=0 Device: name="ALC3234 Analog", type="Audio", device=0 Amp-In caps: ofs=0x17, nsteps=0x3f, stepsize=0x02, mute=1 Amp-In vals: [0x27 0x27] Converter: stream=0, channel=0 SDI-Select: 0 PCM: rates [0x560]: 44100 48000 96000 192000 bits [0xe]: 16 20 24 formats [0x1]: PCM Power states: D0 D1 D2 D3 EPSS Power: setting=D0, actual=D0 Connection: 1 0x23 Node 0x09 [Audio Input] wcaps 0x10051b: Stereo Amp-In Amp-In caps: ofs=0x17, nsteps=0x3f, stepsize=0x02, mute=1 Amp-In vals: [0x97 0x97] Converter: stream=0, channel=0 SDI-Select: 0 PCM: rates [0x560]: 44100 48000 96000 192000 bits [0xe]: 16 20 24 formats [0x1]: PCM Power states: D0 D1 D2 D3 EPSS Power: setting=D0, actual=D0 Connection: 1 0x22
Như vậy pathmap của Headset sẽ là: 0x08 -> 0x23 -> 0x19 0x09 -> 0x22 -> 0x19, chuyển hết sang hệ decimal ta được: 8 -> 35 -> 25 9 -> 34 -> 25
2. Headphone: Hãy bắt đầu với Pin Complex
Node 0x1a [Pin Complex] wcaps 0x40048b: Stereo Amp-In Control: name="Headphone Mic Boost Volume", index=0, device=0 ControlAmp: chs=3, dir=In, idx=0, ofs=0 Amp-In caps: ofs=0x00, nsteps=0x03, stepsize=0x27, mute=0 Amp-In vals: [0x00 0x00] Pincap 0x00003724: IN Detect Vref caps: HIZ 50 GRD 80 100 Pin Default 0x411111f0: [N/A] Speaker at Ext Rear Conn = 1/8, Color = Black DefAssociation = 0xf, Sequence = 0x0 Misc = NO_PRESENCE Pin-ctls: 0x20: IN VREF_HIZ Unsolicited: tag=00, enabled=0 Power states: D0 D1 D2 D3 EPSS Power: setting=D0, actual=D0
Và rồi cũng giống như ở Headset, chúng ta không thấy bất kì kết nối trực tiếp nào nên mình đành phải tìm từ Audio Input/Mixer/Selector và rồi kết quả chẳng khác gì ở Headset vậy nên mình sẽ đưa hẳn kết quả luôn nhé!
Pathmap của Headphone sẽ là: 0x08 -> 0x23 -> 0x1a 0x09 -> 0x22 -> 0x1a, chuyển hết sang hệ decimal ta được: 8 -> 35 -> 26 9 -> 34 -> 26
Như vậy là đã xong pathmap cho codec ALC255, góp lại 1 lần nữa thôi 🙂
- Speaker: 20 -> 12 -> 2
- HP: 33 -> 13 -> 3
- Mic: 8 -> 35 -> 18
- Headset: 8 -> 35 -> 25 9 -> 34 -> 25
- Headphone: 8 -> 35 -> 26 9 -> 34 -> 26
Save lại rồi đi tiếp thôi.
- Xác định pathmap bằng codec_dump_dec.txt.svg (sẽ có khi bạn dùng script):
Sau khi bạn mở file, bạn sẽ nhận được 1 “mạng nhện” tương tự như sau

Nhìn mà hoa cả mắt đúng không nào? Chắc mình sẽ remove phần này mà chỉ hướng dẫn làm thủ công thôi =))
Patch Platforms.xml và layoutxx.xml
- layout#.xml: Bạn mở layout11.xml nếu bạn dùng codec của Realtek, còn 2 hãng Conexant và IDT thì bạn mở layout26.xml nhé! Dù rằng 2 file khác nhau nhưng những thứ các bạn cần làm tiếp theo thì tương tự như nhau cả thôi.
Mình dùng codec Realtek nên mình sẽ mở layout11.xml, để bài viết ngắn gọn thì mình sẽ chỉnh sửa luôn cho dễ hiểu

Các bạn cần chỉnh 1 số thứ như sau:
- LayoutID: bạn thay đổi hoặc giữ nguyên tuỳ thích, đây mình sẽ thay thành 15
- CodecID: bạn cần thay bằng Vendor Id của codec ở hệ decimal đã chuẩn bị trên
- Inputs: tuỳ vào codec của bạn có LineIn hay không, nếu không có thì xoá đi
- PatchMapID: bạn có thể cho vào đây tên codec bạn patch hoặc bất kì số nào bạn thích
Sau khi chỉnh xong bạn save nó lại để đến với file tiếp theo nhé!
- Platforms.xml: mở Platforms.xml, kèm với 1 chút chỉnh sửa, ta được như hình dưới

- PathMaps -> 0 -> PathMap -> 0 -> 0 là Mic
- PathMaps -> 0 -> PathMap -> 0 -> 1 là LineIn
- PathMaps -> 0 -> PathMap -> 1 -> 0 là HP
- PathMaps -> 0 -> PathMap -> 1 -> 1 là Speaker
- PathMaps -> 0 -> PathMap -> PathMapID: ở đây bạn cần điền số giống với PathMapID ở layout#.xml.
Tiếp theo bạn điền thông tin pathmap đã xác định vào như sau

Nếu trường hợp không có Audio Mixer/Selector thì bạn xoá đi key 1, chỉ điền vào key 0 và key 2 thôi nhé!
Binary Patch
B1: Clone git AppleALC và Lilu
B2: Build kext Lilu rồi copy vào folder đã giải nén của AppleALC repo
B3: Mở folder AppleALC vừa giải nén, vào Resources, mình xoá hết các codec khác mà thừa lại codec mình lấy làm vd cho các bạn dễ nhìn

B4: Copy layout#.xml và Platforms#.xml chuẩn bị ở trên bỏ vào folder có tên codec sound mà bạn đang patch

B5: Mở AppleALC.xcodeproj -> PinConfigs -> Info.plist -> IOKitPersonalities -> HDA Hardware Config Resource -> HDAConfigDefault, bạn có thể tự tạo hoặc edit 1 cái có sẳn

Các bạn cần chỉnh 1 số thứ sau:
- Codec: thay đổi tuỳ thích
- CodecID: thay bằng Vendor Id của codec ở hệ decimal đã chuẩn bị trên
- ConfigData: bạn copy codec verb đã chuẩn bị đưa vào đây
- LayoutID: nhập layout-id bạn đã chọn để patch ở trên
B6: Mở AppleALC.xcodeproj -> Resources -> (tên codec bạn đang patch) -> Info.plist -> Information Property List -> Files

Ở đây bạn nhìn hình chắc cũng rõ cần chỉnh gì rồi nhỉ?
Sau khi chỉnh xong bạn save lại rồi ấn build thôi

Vậy là hoàn thành phần kext, tiếp theo bạn cho kext vừa build vào EFI/CLOVER/kexts/Other/ rồi inject layout-id và cuối cùng là bạn chị việc nhấn restart và chờ kết qua thôi!
Như vậy là mình đã hướng dẫn xong cách patch AppleHDA cho các bạn rồi!
Chúc các bạn thành công và hẹn gặp lại