Windows 图形显示驱动开发-WDDM 3.2-自动显示切换(十一)
GPU 设备 ACPI 方法
在启动 GPU 的图形驱动程序之前,系统需要知道多路复用 ACPI 设备是否正常工作,以及它的当前状态。 为此,ACPI 多路复用器设备的驱动程序必须已经启动。 系统在每个 GPU 的 ACPI 命名空间下使用 ACPI _DEP
方法来保证设备关系。
如果 GPU 已有 _DEP
方法,则应将多路复用器设备的 ACPI 名称添加到返回的依赖关系列表中。 如果 GPU 还没有 _DEP
方法,则应进行添加。
为了让 ACPI 固件仅在 OS 支持 ADS 的情况下声明 GPU 对多路复用器的依赖项,增加了 ACPI _OSI
查询。 ACPI 固件可使用此查询来检查是否支持 ADS。 支持 ADS 的 OS 版本将通过向 _OSI(“DisplayMux”)
ACPI 命令返回 true 来报告支持情况。
GPU 子设备 ACPI 方法
对于连接到多路复用器的每个目标,该子设备的 ACPI 设备都会公开一个 ACPI 方法,返回其所连接的多路复用器设备的 ACPI 名称。
方法 DMID(显示多路复用器标识符)
参数:
无
返回:
ASCII 字符串,包含该输出所连接的 ACPI 多路复用器设备的 ACPI 名称
示例
以下示例演示了如何在 ACPI 框架内设置和管理带有两个 GPU(GPU0 和 GPU1)和一个多路复用器的系统。
-
多路复用器设备的 ACPI 名称为“SB.MUX1”。
-
对于 GPU0:
- GPU0 的 ACPI 名称为 'SB.PCI0.GFX0'。
- 它公开了 VidPn 目标 0x40f04,该目标报告的 值为 0x400。
- 与连接到多路复用器的目标相对应的 ACPI 子设备名称是“SB.PCI0.GFX0.DD1F”。
- ACPI 方法 _ADR 在 'SB.PCI0.GFX0.DD1F' 下返回 0x400。 此返回值是操作系统如何识别此 ACPI 设备与 VidPn 目标 0x40f04 相对应的依据。
- 在“SB.PCI0.GFX0.DD1F”下的ACPI方法DMID返回“SB.MUX1”。
-
对于 GPU1:
- GPU1 的 ACPI 名称为“SB.PCI0.PEG0.PEGP”。
- 它公开了 VidPn 目标 0x1103,该目标报告的 DXGK_CHILD_DESCRIPTOR.AcpiUid 值为 0x100。
- 与连接到多路复用器的目标相对应的 ACPI 子设备名称是“SB.PCI0.PEG0.PEGP.EDP1”。
- 在“SB.PCI0.PEG0.PEGP.EDP1”下,ACPI 方法_ADR 返回 0x100。 此返回值使得操作系统知道此 ACPI 设备对应 VidPn 目标 0x1103。
- 在“SB.PCI0.PEG0.PEGP.EDP1”下的 ACPI 方法 DMID 返回“SB.MUX1”。
-
OS 知道 GPU0 目标 0x40f04 和 GPU1 目标 0x1103 连接到同一个 ACPI 名称为“SB.MUX1”的多路复用器。
-
如果 GPU1 当前连接到面板,OS 可以通过调用“SB.MUX1”上的 DMCF 方法,传入“SB.PCI0.GFX0.DD1F”,将多路复用器切换到 GPU0。
以下 ACPI 计算机语言代码用于示例的相关部分。 平台逻辑的伪代码用 <> 括起来。
DefinitionBlock
{
Device (MUX1) // This is _SB_.MUX1
{
Name (_HID, "MSFT0007") // _HID: Hardware ID
Method (DMQU, 1, Serialized) // DMQU: Display Mux Query
{
Switch (ToInteger(Arg0))
{
Case (1)
{
If (<Mux is in error>)
{
Return ("")
}
If (<Mux switched to GPU0>)
{
Return ("_SB_.PCI0.GFX0.DD1F")
}
Else
{
Return ("_SB_.PCI0.PEG0.PEGP.EDP1")
}
}
Case (2)
{
Return (1) // Mux only has developmental support
}
Case (3)
{
If (<Mux is in error>)
{
Return ("")
}
Return ("_SB_.PCI0.GFX0.DD1F")
}
Case (4)
{
If (<Mux is in error>)
{
Return ("")
}
Return ("_SB_.PCI0.PEG0.PEGP.EDP1")
}
}
// Unknown type
Return ("")
}
Method (DMCF, 1, Serialized) // DMCF: Display Mux Configure
{
If (<Arg0 does not match either of the GPU children this mux is connected to>)
{
Return (1) // Failure, use 1 to indicate this particular failure
}
// Switch the mux
If (<Mux switch was successful>)
{
Return (0) // Success
}
Else
{
Return (2) // Failure, use 2 to indicate this particular failure
}
}
}
Scope (_SB_.PCI0.GFX0) // ACPI Device for GPU0
{
Method (_DEP, 0, NotSerialized) // _DEP: Dependency on Mux device
{
If (_OSI(“DisplayMux”))
{
Return (Package {"_SB_.MUX1"})
}
Else
{
Return (Package (0x00){})
}
}
Device (DD1F) // SB.PCI0.GFX0.DD1F which is child of GPU that is connected to the Mux
{
Name (_ADR, 0x400) // _ADR: Matches the AcpiUid driver reports for the target connected to mux
Method (DMID, 0, NotSerialized) // DMID: ACPI name of the mux this target is connected to
{
Return ("_SB_.MUX1")
}
}
}
Scope (_SB_.PCI0.PEG0.PEGP) // ACPI Device for GPU1
{
Method (_DEP, 0, NotSerialized) // _DEP: Dependency on Mux device
{
If (_OSI(“DisplayMux”))
{
Return (Package {"_SB_.MUX1"})
}
Else
{
Return (Package (0x00){})
}
}
Device (EDP1) // SB.PCI0.PEG0.PEGP.EDP1 which is child of GPU that is connected to the Mux
{
Name (_ADR, 0x100) // _ADR: Matches the AcpiUid driver reports for the target connected to mux
Method (DMID, 0, NotSerialized) // DMID: ACPI name of the mux this target is connected to
{
Return ("_SB_.MUX1")
}
}
}
}