[WIP] drivers/gfx/nvidia: ACPI rewrite
Begin rewriting the ACPI support according to the Design Guide. Partially implements Low Power States and GPU Boost methods. Change-Id: I119f3206685ad337dcbb73d55cc807d00d5659fb Signed-off-by: Tim Crawford <tcrawford@system76.com>
This commit is contained in:
81
src/drivers/gfx/nvidia/acpi/boost.asl
Normal file
81
src/drivers/gfx/nvidia/acpi/boost.asl
Normal file
@@ -0,0 +1,81 @@
|
|||||||
|
/* SPDX-License-Identifier: GPL-2.0-only */
|
||||||
|
|
||||||
|
// NVIDIA GPU Boost for Notebook and All-In-One-Projects
|
||||||
|
|
||||||
|
#define GPS_FUNC_SUPPORT 0
|
||||||
|
#define GPS_FUNC_GETOBJBYTYPE 16
|
||||||
|
#define GPS_FUNC_GETALLOBJS 17
|
||||||
|
#define GPS_FUNC_GETCALLBACKS 19
|
||||||
|
#define GPS_FUNC_PCONTROL 28
|
||||||
|
#define GPS_FUNC_PSHARESTATUS 32
|
||||||
|
#define GPS_FUNC_PSHAREPARAMS 42
|
||||||
|
|
||||||
|
Method (NVGB, 2, NotSerialized)
|
||||||
|
{
|
||||||
|
Printf("GPS {")
|
||||||
|
|
||||||
|
Switch (ToInteger(Arg0)) {
|
||||||
|
// Bit list of supported functions
|
||||||
|
Case (GPS_FUNC_SUPPORT) {
|
||||||
|
Printf(" GPS_FUNC_SUPPORT")
|
||||||
|
// Functions supported: 0, 32, 42
|
||||||
|
Local0 = Buffer () {0x01, 0x00, 0x00, 0x00, 0x01, 0x04, 0x00, 0x00}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get current platform status, thermal budget
|
||||||
|
Case (GPS_FUNC_PSHARESTATUS) {
|
||||||
|
Printf(" GPS_FUNC_PSHARESTATUS")
|
||||||
|
Local0 = Buffer (4) { 0 }
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get GPU Boost platform parameters
|
||||||
|
Case (GPS_FUNC_PSHAREPARAMS) {
|
||||||
|
Printf(" GPS_FUNC_PSHAREPARAMS")
|
||||||
|
CreateField (Arg1, 0, 3, QTYP) // Query Type
|
||||||
|
CreateField (Arg1, 8, 1, GTMP) // GPU temperature status
|
||||||
|
CreateField (Arg1, 9, 1, CTMP) // CPU temperature status
|
||||||
|
|
||||||
|
Local0 = Buffer (36) { 0 }
|
||||||
|
CreateDWordField (Local0, 0, STAT) // Status
|
||||||
|
CreateDWordField (Local0, 4, VERS) // Version
|
||||||
|
CreateDWordField (Local0, 8, TGPU) // GPU temperature (C)
|
||||||
|
CreateDWordField (Local0, 12, PDTS) // CPU package temperature (C)
|
||||||
|
|
||||||
|
VERS = 0x00010000
|
||||||
|
STAT = QTYP
|
||||||
|
|
||||||
|
Switch (ToInteger(QTYP)) {
|
||||||
|
// Get current status
|
||||||
|
Case (0) {
|
||||||
|
// TGPU must be 0.
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get supported fields
|
||||||
|
Case (1) {
|
||||||
|
STAT |= 0x100
|
||||||
|
// TGPU must be 0.
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get current operating limits
|
||||||
|
Case (2) {
|
||||||
|
// GPU temperature status must be 1.
|
||||||
|
STAT |= 0x100
|
||||||
|
// TGPU should be 0. GPU will use its own default.
|
||||||
|
}
|
||||||
|
|
||||||
|
Default {
|
||||||
|
Printf(" Unsupported Query Type: %o", ToInteger(QTYP))
|
||||||
|
Local0 = NVIDIA_ERROR_UNSUPPORTED
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Default {
|
||||||
|
Printf(" Unsupported GPS_FUNC: %o", ToInteger(Arg0))
|
||||||
|
Local0 = NVIDIA_ERROR_UNSUPPORTED
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Printf("}")
|
||||||
|
Return(Local0)
|
||||||
|
}
|
@@ -1,202 +1,133 @@
|
|||||||
/* SPDX-License-Identifier: GPL-2.0-only */
|
/* SPDX-License-Identifier: GPL-2.0-only */
|
||||||
|
|
||||||
Device (\_SB.PCI0.PEGP) {
|
#define NVIDIA_ERROR_UNSPECIFIED 0x80000001
|
||||||
|
#define NVIDIA_ERROR_UNSUPPORTED 0x80000002
|
||||||
|
|
||||||
|
#define NBCI_DSM_GUID "D4A50B75-65C7-46F7-BFB7-41514CEA0244"
|
||||||
|
#define NBCI_REVISION_ID 0x102
|
||||||
|
|
||||||
|
#define GPS_DSM_GUID "A3132D01-8CDA-49BA-A52E-BC9D46DF6B81"
|
||||||
|
#define GPS_REVISION_ID 0x200
|
||||||
|
|
||||||
|
#define JT_DSM_GUID "CBECA351-067B-4924-9CBD-B46B00B86F34"
|
||||||
|
#define JT_REVISION_ID 0x200
|
||||||
|
|
||||||
|
#define NVOP_DSM_GUID "A486D8F8-0BDA-471B-A72B-6042A6B5BEE0"
|
||||||
|
#define NVOP_REVISION_ID 0x100
|
||||||
|
|
||||||
|
Device (\_SB.PCI0.PEG0)
|
||||||
|
{
|
||||||
Name (_ADR, CONFIG_DRIVERS_GFX_NVIDIA_BRIDGE << 16)
|
Name (_ADR, CONFIG_DRIVERS_GFX_NVIDIA_BRIDGE << 16)
|
||||||
|
|
||||||
PowerResource (PWRR, 0, 0) {
|
PowerResource (PWRR, 0, 0) {
|
||||||
Name (_STA, 1)
|
Name (_STA, 1)
|
||||||
|
|
||||||
Method (_ON) {
|
Method (_ON)
|
||||||
Debug = "PEGP.PWRR._ON"
|
{
|
||||||
If (_STA != 1) {
|
|
||||||
\_SB.PCI0.PEGP.DEV0._ON ()
|
|
||||||
_STA = 1
|
_STA = 1
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
Method (_OFF) {
|
Method (_OFF)
|
||||||
Debug = "PEGP.PWRR._OFF"
|
{
|
||||||
If (_STA != 0) {
|
|
||||||
\_SB.PCI0.PEGP.DEV0._OFF ()
|
|
||||||
_STA = 0
|
_STA = 0
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
Name (_PR0, Package () { \_SB.PCI0.PEGP.PWRR })
|
Name (_PR0, Package () { PWRR })
|
||||||
Name (_PR2, Package () { \_SB.PCI0.PEGP.PWRR })
|
Name (_PR3, Package () { PWRR })
|
||||||
Name (_PR3, Package () { \_SB.PCI0.PEGP.PWRR })
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Device (\_SB.PCI0.PEGP.DEV0) {
|
Device (\_SB.PCI0.PEG0.DGPU)
|
||||||
|
{
|
||||||
Name(_ADR, 0x00000000)
|
Name(_ADR, 0x00000000)
|
||||||
Name (_STA, 0xF)
|
|
||||||
Name (LTRE, 0)
|
|
||||||
|
|
||||||
// Memory mapped PCI express registers
|
// GPU Power
|
||||||
// Not sure what this stuff is, but it is used to get into GC6
|
Name (GPWR, 0)
|
||||||
// TODO: use GPU config to generate address
|
|
||||||
OperationRegion (RPCX, SystemMemory, CONFIG_ECAM_MMCONF_BASE_ADDRESS + 0x8000, 0x1000)
|
// GCx State
|
||||||
Field (RPCX, ByteAcc, NoLock, Preserve) {
|
Name (GCST, 0)
|
||||||
PVID, 16,
|
|
||||||
PDID, 16,
|
// For supporting Hybrid Graphics, the package refers to the PCIe controller
|
||||||
CMDR, 8,
|
// itself, which leverages GC6 Control methods under the dGPU namespace.
|
||||||
Offset (0x19),
|
Name (_PR0, Package() { \_SB.PCI0.PEG0.PWRR })
|
||||||
PRBN, 8,
|
Name (_PR3, Package() { \_SB.PCI0.PEG0.PWRR })
|
||||||
Offset (0x84),
|
|
||||||
D0ST, 2,
|
Method (_STA)
|
||||||
Offset (0xAA),
|
{
|
||||||
CEDR, 1,
|
/*
|
||||||
Offset (0xAC),
|
* Only return "On" when:
|
||||||
, 4,
|
* - GPU power is good
|
||||||
CMLW, 6,
|
* - GPU has completed return to GC0
|
||||||
Offset (0xB0),
|
*
|
||||||
ASPM, 2,
|
* In all other cases, return "Off".
|
||||||
, 2,
|
*/
|
||||||
P0LD, 1,
|
If ((GPWR == 1) && (GCST == 0)) {
|
||||||
RTLK, 1,
|
Return (0xF)
|
||||||
Offset (0xC9),
|
} Else {
|
||||||
, 2,
|
Return (0)
|
||||||
LREN, 1,
|
}
|
||||||
Offset (0x11A),
|
|
||||||
, 1,
|
|
||||||
VCNP, 1,
|
|
||||||
Offset (0x214),
|
|
||||||
Offset (0x216),
|
|
||||||
P0LS, 4,
|
|
||||||
Offset (0x248),
|
|
||||||
, 7,
|
|
||||||
Q0L2, 1,
|
|
||||||
Q0L0, 1,
|
|
||||||
Offset (0x504),
|
|
||||||
Offset (0x506),
|
|
||||||
PCFG, 2,
|
|
||||||
Offset (0x508),
|
|
||||||
TREN, 1,
|
|
||||||
Offset (0xC20),
|
|
||||||
, 4,
|
|
||||||
P0AP, 2,
|
|
||||||
Offset (0xC38),
|
|
||||||
, 3,
|
|
||||||
P0RM, 1,
|
|
||||||
Offset (0xC74),
|
|
||||||
P0LT, 4,
|
|
||||||
Offset (0xD0C),
|
|
||||||
, 20,
|
|
||||||
LREV, 1
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Method (_ON) {
|
Method (_ON)
|
||||||
Debug = "PEGP.DEV0._ON"
|
{
|
||||||
|
Printf("_ON {")
|
||||||
|
Printf(" Enable GPU power")
|
||||||
|
STXS(DGPU_PWR_EN)
|
||||||
|
Sleep(10)
|
||||||
|
|
||||||
If (_STA != 0xF) {
|
Printf(" Take GPU out of reset")
|
||||||
Debug = " If DGPU_PWR_EN low"
|
|
||||||
If (! GTXS (DGPU_PWR_EN)) {
|
|
||||||
Debug = " DGPU_PWR_EN high"
|
|
||||||
STXS (DGPU_PWR_EN)
|
|
||||||
|
|
||||||
Debug = " Sleep 16"
|
|
||||||
Sleep (16)
|
|
||||||
}
|
|
||||||
|
|
||||||
Debug = " DGPU_RST_N high"
|
|
||||||
STXS(DGPU_RST_N)
|
STXS(DGPU_RST_N)
|
||||||
|
Sleep(10)
|
||||||
|
|
||||||
Debug = " Sleep 10"
|
GPWR = 1
|
||||||
Sleep (10)
|
Printf("} _ON")
|
||||||
|
|
||||||
Debug = " Q0L0 = 1"
|
|
||||||
Q0L0 = 1
|
|
||||||
|
|
||||||
Debug = " Sleep 16"
|
|
||||||
Sleep (16)
|
|
||||||
|
|
||||||
Debug = " While Q0L0"
|
|
||||||
Local0 = 0
|
|
||||||
While (Q0L0) {
|
|
||||||
If ((Local0 > 4)) {
|
|
||||||
Debug = " While Q0L0 timeout"
|
|
||||||
Break
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Sleep (16)
|
Method (_OFF)
|
||||||
Local0++
|
{
|
||||||
}
|
Printf("_OFF {")
|
||||||
|
Printf(" Put GPU in reset")
|
||||||
Debug = " P0RM = 0"
|
|
||||||
P0RM = 0
|
|
||||||
|
|
||||||
Debug = " P0AP = 0"
|
|
||||||
P0AP = 0
|
|
||||||
|
|
||||||
Debug = Concatenate(" LREN = ", ToHexString(LTRE))
|
|
||||||
LREN = LTRE
|
|
||||||
|
|
||||||
Debug = " CEDR = 1"
|
|
||||||
CEDR = 1
|
|
||||||
|
|
||||||
Debug = " CMDR |= 7"
|
|
||||||
CMDR |= 7
|
|
||||||
|
|
||||||
Debug = " _STA = 0xF"
|
|
||||||
_STA = 0xF
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Method (_OFF) {
|
|
||||||
Debug = "PEGP.DEV0._OFF"
|
|
||||||
|
|
||||||
If (_STA != 0x5) {
|
|
||||||
Debug = Concatenate(" LTRE = ", ToHexString(LREN))
|
|
||||||
LTRE = LREN
|
|
||||||
|
|
||||||
Debug = " Q0L2 = 1"
|
|
||||||
Q0L2 = 1
|
|
||||||
|
|
||||||
Debug = " Sleep 16"
|
|
||||||
Sleep (16)
|
|
||||||
|
|
||||||
Debug = " While Q0L2"
|
|
||||||
Local0 = Zero
|
|
||||||
While (Q0L2) {
|
|
||||||
If ((Local0 > 4)) {
|
|
||||||
Debug = " While Q0L2 timeout"
|
|
||||||
Break
|
|
||||||
}
|
|
||||||
|
|
||||||
Sleep (16)
|
|
||||||
Local0++
|
|
||||||
}
|
|
||||||
|
|
||||||
Debug = " P0RM = 1"
|
|
||||||
P0RM = 1
|
|
||||||
|
|
||||||
Debug = " P0AP = 3"
|
|
||||||
P0AP = 3
|
|
||||||
|
|
||||||
Debug = " Sleep 10"
|
|
||||||
Sleep (10)
|
|
||||||
|
|
||||||
Debug = " DGPU_RST_N low"
|
|
||||||
CTXS(DGPU_RST_N)
|
CTXS(DGPU_RST_N)
|
||||||
|
Sleep(10)
|
||||||
|
|
||||||
Debug = " While DGPU_GC6 low"
|
Printf(" Disable GPU power")
|
||||||
Local0 = Zero
|
CTXS(DGPU_PWR_EN)
|
||||||
While (! GRXS(DGPU_GC6)) {
|
Sleep(10)
|
||||||
If ((Local0 > 4)) {
|
|
||||||
Debug = " While DGPU_GC6 low timeout"
|
|
||||||
|
|
||||||
Debug = " DGPU_PWR_EN low"
|
GPWR = 0
|
||||||
CTXS (DGPU_PWR_EN)
|
Printf("} _OFF")
|
||||||
Break
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Sleep (16)
|
Method (_PS0)
|
||||||
Local0++
|
{
|
||||||
|
// XGXS, XGIS, XCLM
|
||||||
}
|
}
|
||||||
|
|
||||||
Debug = " _STA = 0x5"
|
Method (_PS3)
|
||||||
_STA = 0x5
|
{
|
||||||
|
// EGNS, EGIS, EGIN
|
||||||
|
}
|
||||||
|
|
||||||
|
Method (_DSM, 4, NotSerialized)
|
||||||
|
{
|
||||||
|
// NVIDIA GPU Boost
|
||||||
|
If (Arg0 == ToUUID(GPS_DSM_GUID)) {
|
||||||
|
If (Arg1 <= GPS_REVISION_ID) {
|
||||||
|
Return(NVGB(Arg2, Arg3))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// NVIDIA Low Power States
|
||||||
|
If (Arg0 == ToUUID(JT_DSM_GUID)) {
|
||||||
|
If (Arg1 <= JT_REVISION_ID) {
|
||||||
|
Return(NVJT(Arg2, Arg3))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Printf("Unsupported GUID")
|
||||||
|
Return(NVIDIA_ERROR_UNSUPPORTED)
|
||||||
|
}
|
||||||
|
|
||||||
|
#include "boost.asl"
|
||||||
|
#include "low_power_states.asl"
|
||||||
}
|
}
|
||||||
|
112
src/drivers/gfx/nvidia/acpi/low_power_states.asl
Normal file
112
src/drivers/gfx/nvidia/acpi/low_power_states.asl
Normal file
@@ -0,0 +1,112 @@
|
|||||||
|
/* SPDX-License-Identifier: GPL-2.0-only */
|
||||||
|
|
||||||
|
// NVIDIA Low Power States
|
||||||
|
|
||||||
|
#define JT_FUNC_SUPPORT 0
|
||||||
|
#define JT_FUNC_CAPS 1
|
||||||
|
#define JT_FUNC_POWERCONTROL 3
|
||||||
|
#define JT_FUNC_PLATPOLICY 4
|
||||||
|
|
||||||
|
Method (NVJT, 2, NotSerialized)
|
||||||
|
{
|
||||||
|
Printf("NVJT {")
|
||||||
|
Switch (ToInteger(Arg0)) {
|
||||||
|
Case (JT_FUNC_SUPPORT) {
|
||||||
|
Printf(" JT_FUNC_SUPPORT");
|
||||||
|
// Functions supported: 0, 1, 3, 4
|
||||||
|
Local0 = Buffer() { 0x1B, 0, 0, 0 }
|
||||||
|
}
|
||||||
|
|
||||||
|
Case (JT_FUNC_CAPS) {
|
||||||
|
Printf(" JT_FUNC_CAPS");
|
||||||
|
Local0 = Buffer(4) { 0, 0, 0, 0 }
|
||||||
|
|
||||||
|
// G-SYNC NVSR Power Features
|
||||||
|
CreateField (Local0, 0, 1, JTEN)
|
||||||
|
JTEN = 0
|
||||||
|
|
||||||
|
// NVSR
|
||||||
|
CreateField (Local0, 1, 2, NVSE)
|
||||||
|
NVSE = 1
|
||||||
|
|
||||||
|
// Panel Power Rail
|
||||||
|
CreateField (Local0, 3, 2, PPR)
|
||||||
|
PPR = 2
|
||||||
|
|
||||||
|
// Self-Refresh Control (SRC) Power Rail
|
||||||
|
CreateField (Local0, 5, 1, SRPR)
|
||||||
|
SRPR = 0
|
||||||
|
|
||||||
|
// FB Power Rail
|
||||||
|
CreateField (Local0, 6, 2, FBPR)
|
||||||
|
FBPR = 0
|
||||||
|
|
||||||
|
// GPU Power Rail
|
||||||
|
CreateField (Local0, 8, 2, GPR)
|
||||||
|
GPR = 0
|
||||||
|
|
||||||
|
// GC6 ROM
|
||||||
|
CreateField (Local0, 10, 1, GCR)
|
||||||
|
GCR = 0
|
||||||
|
|
||||||
|
// Panic Trap Handler
|
||||||
|
CreateField (Local0, 11, 1, PTH)
|
||||||
|
PTH = 1
|
||||||
|
|
||||||
|
// Supports Notify
|
||||||
|
CreateField (Local0, 12, 1, NOTS)
|
||||||
|
NOTS = 0
|
||||||
|
|
||||||
|
// MS Hybrid Support
|
||||||
|
CreateField (Local0, 13, 1, MHYB)
|
||||||
|
MHYB = 1
|
||||||
|
|
||||||
|
// Root Port Control
|
||||||
|
CreateField (Local0, 14, 1, RPC)
|
||||||
|
RPC = 1
|
||||||
|
|
||||||
|
// GC6 Version
|
||||||
|
CreateField (Local0, 15, 2, GC6V)
|
||||||
|
GC6V = 2
|
||||||
|
|
||||||
|
// GC6 Exit ISR Support
|
||||||
|
CreateField (Local0, 17, 1, GEI)
|
||||||
|
GEI = 0
|
||||||
|
|
||||||
|
// GC6 Self Wakeup Support
|
||||||
|
CreateField (Local0, 18, 1, GSW)
|
||||||
|
GSW = 0
|
||||||
|
|
||||||
|
// Maximum Revision Supported
|
||||||
|
CreateField (Local0, 20, 16, MXRV)
|
||||||
|
MXRV = JT_REVISION_ID
|
||||||
|
}
|
||||||
|
|
||||||
|
Case (JT_FUNC_POWERCONTROL) {
|
||||||
|
Printf(" JT_FUNC_POWERCONTROL: Unimplemented!");
|
||||||
|
// TODO
|
||||||
|
Local0 = NVIDIA_ERROR_UNSUPPORTED
|
||||||
|
}
|
||||||
|
|
||||||
|
Case (JT_FUNC_PLATPOLICY) {
|
||||||
|
Printf(" JT_FUNC_PLATPOLICY");
|
||||||
|
//CreateField (Arg1, 2, 1, AUD) // Azalia Audio Device
|
||||||
|
//CreateField (Arg1, 3, 1, ADM) // Audio Disable Mask
|
||||||
|
//CreateField (Arg1, 4, 4, DGS) // Driver expected State Mask
|
||||||
|
|
||||||
|
// TODO: Save policy settings to NV CMOS?
|
||||||
|
|
||||||
|
Local0 = Buffer(4) { 0, 0, 0, 0 }
|
||||||
|
//CreateField (Local0, 2, 1, AUD) // Audio Device status
|
||||||
|
//CreateField (Local0, 4, 3, GRE) // SBIOS requested GPU state
|
||||||
|
}
|
||||||
|
|
||||||
|
Default {
|
||||||
|
Printf(" Unsupported JT_FUNC: %o", ToInteger(Arg0))
|
||||||
|
Local0 = NVIDIA_ERROR_UNSUPPORTED
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Printf("}")
|
||||||
|
Return(Local0)
|
||||||
|
}
|
Reference in New Issue
Block a user