最近在研究 Audio ,目前使用最广泛的是 Intel 的 HD Audio,和之前的 AC97 相比复杂多了,网上也少有关于如何驱动这个 Audio 的文章,看起来很痛苦。因为音频的数据量通常很大,所以通讯方面都是以 DMA 为主。好在除此之外设计上还提供了一套简单发送命令的机制。下面就是我在 Kabylake-R 的平台上实验直接发送 command 读取 codec 的 VID 和 PID的实验。
1. 找到 audio pci 设备,在 KBL-R 上是 D32:F2
我们需要的 Memory Mapped I/O 在 Offset 10 和 14 (一共是8 Bytes)
但是这时,对应的内存位置全都为0xFF:
2. 对 PCI_COMMAND_OFFSET(0x04)发送 EFI_PCI_COMMAND_MEMORY_SPACE (0x02) command:
3. 再打开 Memory Mapped I/O Register,在 0x2F FB43 0000,可以正常工作;
4. 根据 HD Audio Spec, ICW(0x60) IR(0x64) ICS(68h)。在 ICW 中写入NID=0,Verb ID=0xF00,Parameter ID=0x0的Verb Command
然后在ICS(68h) 写入 0x3
5. 很快,我们就能在IR(0x64) 看到返回值。这里我们用的是 Realtek 的 codec ,所以给出的VID 是 Realtek的,也证明方法的正确性。
如果细心观察BIOS中使用的 Verb Table 会发现在头部有一个 VID 和 PID,每次在Load 这个 Table 之前是有一个上述获取然后比较的动作的,因此,不用担心型号上的错误。比如:Realtek 298 和 798 的 PID 不同,如果使用错误会通过 Debug 口输出信息。
的确如此.
Bus 00,Device 1F,Function 03- Intel Corporation/Shuttle Computer Audio Device
Vendor ID 0x8086(Intel Corporation)
Device ID 0x9D71
Version ID 0x21
Class Code 0x040380
Cacheline size 0x10
Latency timer 0x20
Interrupt pin INTA#
Interrupt Line IRQ16
BAR0 0x0000002FFFFEC000 (16KB aligned,64bit memory space)
BAR4 0x0000002FFFFF0000 (64KB aligned,64bit memory space)
SubVendor ID 0x1297(Shuttle Computer)
SubSystem ID 0x2087
Bus Mastering Enabled
Running at 66MHz Not Capable
Fast back to back Not Capable
———————–
HDA #0
Vendor ID 0x10EC(Realtek Semiconductor)
Device ID 0x0269
SubVendorID 0xXXXX(XXXX)
SubDeviceID 0x2087
Revision 0x00100203
NID 0x12 0x90A60130
NID 0x14 0x90170110
NID 0x15 0x01211020
NID 0x17 0x40000000
NID 0x18 0x01A11040
NID 0x19 0x411111F0
NID 0x1A 0x411111F0
NID 0x1B 0x411111F0
NID 0x1D 0x40F48605
NID 0x1E 0x411111F0
Wid 0x20[0x00] 0x3025
Wid 0x20[0x01] 0xA9A8
Wid 0x20[0x02] 0x82A5
Wid 0x20[0x03] 0x8000
Wid 0x20[0x04] 0x0080
Wid 0x20[0x05] 0x0600
Wid 0x20[0x06] 0x0000
Wid 0x20[0x07] 0x0200
Wid 0x20[0x08] 0x0300
Wid 0x20[0x09] 0x0000
Wid 0x20[0x0A] 0x0031
Wid 0x20[0x0B] 0x0C01
Wid 0x20[0x0C] 0x3F00
Wid 0x20[0x0D] 0x0000
Wid 0x20[0x0E] 0x0000
Wid 0x20[0x0F] 0xCCBB
Wid 0x20[0x10] 0xCCBB
Wid 0x20[0x11] 0x0000
Wid 0x20[0x12] 0x0300
Wid 0x20[0x13] 0x0053
Wid 0x20[0x14] 0x0610
Wid 0x20[0x15] 0x8002
Wid 0x20[0x16] 0x062B
Wid 0x20[0x17] 0xC340
Wid 0x20[0x18] 0x5184
Wid 0x20[0x19] 0xDE94
Wid 0x20[0x1A] 0xC920
Wid 0x20[0x1B] 0xFC05
Wid 0x20[0x1C] 0x8800
Wid 0x20[0x1D] 0x110A
Wid 0x20[0x1E] 0x0000
Wid 0x20[0x1F] 0x60D8
Wid 0x20[0x20] 0x0014
Wid 0x20[0x21] 0xC2BA
Wid 0x20[0x22] 0xAA28
Wid 0x20[0x23] 0x0021
Wid 0x20[0x24] 0x0000
Wid 0x20[0x25] 0x0000
PCI registers
Offset[0x000] 86 80 71 9D 06 00 10 00 21 80 03 04 10 20 00 00 ..q…..!…. ..
Offset[0x010] 04 C0 FE FF 2F 00 00 00 00 00 00 00 00 00 00 00 …./………..
Offset[0x020] 04 00 FF FF 2F 00 00 00 00 00 00 00 XX XX 87 20 …./……….
Offset[0x030] 00 00 00 00 50 00 00 00 00 00 00 00 10 01 00 00 ….P………..
Offset[0x040] 00 00 00 00 00 00 00 00 FF 0D 3B 80 00 00 00 00 ……….;…..
Offset[0x050] 01 60 43 C0 08 00 00 00 00 00 00 00 00 00 00 00 .`C………….
Offset[0x060] 05 00 80 00 00 00 00 00 00 00 00 00 00 00 00 00 …………….
Offset[0x070] 10 00 91 00 00 00 00 10 00 28 10 00 00 00 00 00 ………(……
Offset[0x080] 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 …………….
Offset[0x090] 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 …………….
Offset[0x0A0] 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 …………….
Offset[0x0B0] 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 …………….
Offset[0x0C0] 08 06 02 00 00 70 80 04 00 0C A5 82 10 00 03 00 …..p……….
Offset[0x0D0] 00 0C B5 02 10 00 03 00 00 00 00 00 00 00 00 00 …………….
Offset[0x0E0] 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 …………….
Offset[0x0F0] 00 00 00 00 00 00 00 00 B3 0F 41 08 00 00 00 00 ……….A…..
能否改用efi程式,自动显示出codec VID/PID吗?给个程式范例参考,谢谢。