Compare commits

...

3 Commits

Author SHA1 Message Date
2d743165e7 drivers/gfx/nvidia: acpi: Skeleton code for NBCI
Signed-off-by: Tim Crawford <tcrawford@system76.com>
Change-Id: I5fbc8e1480670457586885c6099c19d73ca06c45
2021-12-21 13:32:33 -07:00
75468a84c0 drivers/gfx/nvidia: Misc fixes, some debugging
Change-Id: I072cd3db5859331a036ce7963a3607a56f53f37b
Signed-off-by: Tim Crawford <tcrawford@system76.com>
2021-12-21 12:10:57 -07:00
865292a883 [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>
2021-12-21 12:10:57 -07:00
5 changed files with 547 additions and 173 deletions

View File

@ -0,0 +1,37 @@
/* SPDX-License-Identifier: GPL-2.0-only */
// NVIDIA Advanced Optimus
#define NVOP_FUNC_SUPPORT 0
#define NVOP_FUNC_DISPLAYSTATUS 5
#define NVOP_FUNC_MDTL 6
#define NVOP_FUNC_GETOBJBYTYPE 16
#define NVOP_FUNC_GETALLOBJS 17
#define NVOP_FUNC_OPTIMUSCAPS 26
#define NVOP_FUNC_OPTIMUSFLAGS 27
Method (NVOP, 2, Serialized)
{
Printf("NVOP {")
Local0 = NVIDIA_ERROR_UNSUPPORTED
Switch (ToInteger(Arg0)) {
Case (NVOP_FUNC_SUPPORT) {
}
Case (NVOP_FUNC_OPTIMUSCAPS) {
CreateField (Arg1, 0, 1, FLGS) // Flag updates
CreateField (Arg1, 1, 1, PCOT) // PCIe Configuration Space Owner Target
CreateField (Arg1, 2, 1, PCOW) // PCIe Configuration Space Owner Write
CreateField (Arg1, 24, 2, OPCE) // Optimus Power Control Enable
}
Default {
Printf(" Unsupported NVOP_FUNC: %o", ToInteger(Arg0))
Local0 = NVIDIA_ERROR_UNSUPPORTED
}
}
Printf("} NVOP")
Return(Local0)
}

View File

@ -0,0 +1,83 @@
/* 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 (GPS, 2, Serialized)
{
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: %o", ToHexString(Arg1))
Local0 = Buffer (4) { 0 }
}
// Get GPU Boost platform parameters
Case (GPS_FUNC_PSHAREPARAMS) {
Printf(" GPS_FUNC_PSHAREPARAMS: %o", ToHexString(Arg1))
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
Printf(" Query Type = %o", ToInteger(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("} GPS")
Return(Local0)
}

View File

@ -1,202 +1,197 @@
/* 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 0x103
#define NVOP_DSM_GUID "A486D8F8-0BDA-471B-A72B-6042A6B5BEE0"
#define NVOP_REVISION_ID 0x100
// 00:01.0
Device (\_SB.PCI0.PEG0)
{
Name (_ADR, CONFIG_DRIVERS_GFX_NVIDIA_BRIDGE << 16)
PowerResource (PWRR, 0, 0) {
Name (_STA, 1)
Method (_ON) {
Debug = "PEGP.PWRR._ON"
If (_STA != 1) {
\_SB.PCI0.PEGP.DEV0._ON ()
_STA = 1
}
Method (_ON)
{
Printf("PEG0._ON {")
// TODO: Check for deferred GCx action
\_SB.PCI0.PEG0.DGPU._ON()
_STA = 1
Printf("} PEG0._ON")
}
Method (_OFF) {
Debug = "PEGP.PWRR._OFF"
If (_STA != 0) {
\_SB.PCI0.PEGP.DEV0._OFF ()
_STA = 0
}
Method (_OFF)
{
Printf("PEG0._OFF {")
// TODO: Check for deferred GCx action
\_SB.PCI0.PEG0.DGPU._OFF()
_STA = 0
Printf("} PEG0._OFF")
}
}
Name (_PR0, Package () { \_SB.PCI0.PEGP.PWRR })
Name (_PR2, Package () { \_SB.PCI0.PEGP.PWRR })
Name (_PR3, Package () { \_SB.PCI0.PEGP.PWRR })
Name (_PR0, Package () { PWRR })
Name (_PR2, Package () { PWRR })
Name (_PR3, Package () { PWRR })
}
Device (\_SB.PCI0.PEGP.DEV0) {
// 01:00.0
Device (\_SB.PCI0.PEG0.DGPU)
{
Name(_ADR, 0x00000000)
Name (_STA, 0xF)
Name (LTRE, 0)
// Memory mapped PCI express registers
// Not sure what this stuff is, but it is used to get into GC6
// TODO: use GPU config to generate address
OperationRegion (RPCX, SystemMemory, CONFIG_ECAM_MMCONF_BASE_ADDRESS + 0x8000, 0x1000)
Field (RPCX, ByteAcc, NoLock, Preserve) {
PVID, 16,
PDID, 16,
CMDR, 8,
Offset (0x19),
PRBN, 8,
Offset (0x84),
D0ST, 2,
Offset (0xAA),
CEDR, 1,
Offset (0xAC),
, 4,
CMLW, 6,
Offset (0xB0),
ASPM, 2,
, 2,
P0LD, 1,
RTLK, 1,
Offset (0xC9),
, 2,
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
Name (GPWR, 0) // GPU Power
Name (GCST, 6) // GCx State
Name (DPC, 0) // Deferred power control
Name (DPCX, 0) // Deferred power control on exit
Name (NVID, 0x00000000)
OperationRegion (PCIM, SystemMemory, 0x0E010000, 0xF0)
Field (PCIM, AnyAcc, Lock, Preserve)
{
Offset(0x2c),
SSID, 32,
}
Method (_ON) {
Debug = "PEGP.DEV0._ON"
// For supporting Hybrid Graphics, the package refers to the PCIe controller
// itself, which leverages GC6 Control methods under the dGPU namespace.
Name (_PR0, Package() { \_SB.PCI0.PEG0 })
Name (_PR3, Package() { \_SB.PCI0.PEG0 })
If (_STA != 0xF) {
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)
Debug = " Sleep 10"
Sleep (10)
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)
Local0++
}
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 (_STA)
{
Printf("DGPU._STA")
/*
* Only return "On" when:
* - GPU power is good
* - GPU has completed return to GC0
*
* In all other cases, return "Off".
*/
If ((GPWR == 1) && (GCST == 0)) {
Return (0xF)
} Else {
Return (0)
}
}
Method (_OFF) {
Debug = "PEGP.DEV0._OFF"
Method (_ON)
{
Printf("DGPU._ON {")
Printf(" Enable GPU power")
STXS(DGPU_PWR_EN)
Sleep(10)
If (_STA != 0x5) {
Debug = Concatenate(" LTRE = ", ToHexString(LREN))
LTRE = LREN
Printf(" Take GPU out of reset")
STXS(DGPU_RST_N)
Sleep(10)
Debug = " Q0L2 = 1"
Q0L2 = 1
GPWR = 1
GCST = 0
Debug = " Sleep 16"
Sleep (16)
/*
// TODO: Actually check link status
Printf("Wait for PCIe link")
Sleep(100)
Debug = " While Q0L2"
Local0 = Zero
While (Q0L2) {
If ((Local0 > 4)) {
Debug = " While Q0L2 timeout"
Break
}
Printf("Restore SSID: %o", NVID)
SSID = NVID
*/
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)
Debug = " While DGPU_GC6 low"
Local0 = Zero
While (! GRXS(DGPU_GC6)) {
If ((Local0 > 4)) {
Debug = " While DGPU_GC6 low timeout"
Debug = " DGPU_PWR_EN low"
CTXS (DGPU_PWR_EN)
Break
}
Sleep (16)
Local0++
}
Debug = " _STA = 0x5"
_STA = 0x5
}
Printf("} DGPU._ON")
}
Method (_OFF)
{
Printf("DGPU._OFF {")
/*
Printf("Save SSID: %o", SSID)
NVID = SSID
// TODO: Actually check link status
Printf("Wait for PCIe link")
Sleep(100)
*/
Printf("DGPU._OFF {")
Printf(" Put GPU in reset")
CTXS(DGPU_RST_N)
Sleep(10)
Printf(" Disable GPU power")
CTXS(DGPU_PWR_EN)
GPWR = 0
GCST = 6
Printf("} DGPU._OFF")
}
Method (_PS0)
{
// XGXS, XGIS, XCLM
Printf("_PS0 {}")
}
Method (_PS3)
{
// EGNS, EGIS, EGIN
Printf("_PS3 {}")
}
Method (_DSM, 4, Serialized)
{
// Notebook Common Interface
If (Arg0 == ToUUID(NBCI_DSM_GUID)) {
Printf("NBCI_DSM_GUID")
If (Arg1 <= NBCI_REVISION_ID) {
Printf(" TODO: Unimplemented!")
}
}
// NVIDIA GPU Boost
If (Arg0 == ToUUID(GPS_DSM_GUID)) {
Printf("GPS_DSM_GUID")
If (Arg1 <= GPS_REVISION_ID) {
Return(GPS(Arg2, Arg3))
}
}
// NVIDIA Low Power States
If (Arg0 == ToUUID(JT_DSM_GUID)) {
Printf("JT_DSM_GUID")
If (Arg1 <= JT_REVISION_ID) {
Return(NVJT(Arg2, Arg3))
}
}
// Advanced Optimus
If (Arg0 == ToUUID(NVOP_DSM_GUID)) {
Printf("NVOP_DSM_GUID")
If (Arg1 <= NVOP_REVISION_ID) {
Printf(" TODO: Unimplemented!")
}
}
Printf("Unsupported GUID: %o", ToHexString(Arg0))
Return(NVIDIA_ERROR_UNSUPPORTED)
}
#include "boost.asl"
#include "low_power_states.asl"
}

View File

@ -0,0 +1,169 @@
/* 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, Serialized)
{
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 }
Local0 = Buffer() { 0x13, 0, 0, 0 }
}
Case (JT_FUNC_CAPS) {
Printf(" JT_FUNC_CAPS");
Local0 = Buffer(4) { 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, 12, MXRV)
MXRV = JT_REVISION_ID
}
Case (JT_FUNC_POWERCONTROL) {
Printf(" JT_FUNC_POWERCONTROL: %o", ToHexString(Arg1));
// TODO
Local0 = NVIDIA_ERROR_UNSUPPORTED
/*
CreateField (Arg1, 0, 3, GPC) // GPU Power Control
CreateField (Arg1, 3, 1, GGP) // Global GPU Power
CreateField (Arg1, 4, 1, PPC) // Panel Power Control
CreateField (Arg1, 6, 2, NOC) // Notify on complete
CreateField (Arg1, 8, 2, PRGX) // PCIe Root Power GC6 Exit Sequence
CreateField (Arg1, 10, 2, PRGE) // PCIe Root Power GC6 Entry Sequence
CreateField (Arg1, 12, 1, PRPC) // Poll for Root Port Completion
CreateField (Arg1, 13, 1, PLON) // PCIe Root Port Control
CreateField (Arg1, 14, 2, DFGC) // Defer GC6 Enter/Exit until D3cold
CreateField (Arg1, 16, 3, GPCX) // Deferred GC6 Exit Control
CreateField (Arg1, 19, 1, EGEI) // Enable GC6 Exit ISR
CreateField (Arg1, 20, 2, PLCM) // PCIe Root Port Control Method for PLON
Local0 = Buffer(4) {0, 0, 0, 0}
CreateField (Local0, 0, 3, GCS) // GC State
CreateField (Local0, 3, 1, GPS) // GPU Power Status
CreateField (Local0, 7, 1, PSS) // Panel and SRC State
*/
/*
* DFGC
* 0: Perform request immediately
* 1: Defer GPC and GPCX to be processed when setting Device Power State
* 2: Clear any pending deferred requests
*/
/*
If (DFGC == 2) {
DPC = 0
DPCX = 0
}
*/
/*
* GPC
* 0 GSS) Get current GPU GCx Sleep Status
* 1 EGNS: Entery GC6 only. No SMI trap, No Self-Refresh. Panel
* and GPU will be powred down as normal. FB will remain powered.
* 2 EGIS: Enter GC6, keep Panel in Self-Refresh. Enable SMI trap on
* VGA I/O regiters. Control of screen is transitioned to the SRC and
* then the GPU is powered down. Panel and FB remain powered while
* the GPU is off.
* 3 XGXS: Exit GC6. Exit Panel Self-Refresh (Sparse). GPU is powered on.
* Disable SMI traps.
* 4 XGIS: Exit GC6 for Self-Refresh Update (Burst). GPU is powered on, but
* the SRC continues to retain control of screen refresh, while the
* GPU sends an update to SRC for display. Disable SMI traps.
* 5 EGIN: Enter GC6, keep Pnael in Self-Refresh. No SMI trap on VGA I/O
* registers. Control of screen is transitioned to SRC and then
* GPU is powred down. Panel and FB remain powered while the GPU is off.
* 6 XCLM: Trigger GPU_EVENT only. GPU_EVENT would be assered and de-asserted,
* regardless of GPU power state, without waiting for any GPU-side
* signaling. No change in GPU power state is made. SMI traps disabled.
*/
}
Case (JT_FUNC_PLATPOLICY) {
Printf(" JT_FUNC_PLATPOLICY: %o", ToHexString(Arg1));
//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("} NVJT")
Return(Local0)
}

View File

@ -0,0 +1,90 @@
/* SPDX-License-Identifier: GPL-2.0-only */
// Notebook Common Interface
#define NBCI_FUNC_SUPPORT 0
#define NBCI_FUNC_PLATCAPS 1
#define NBCI_FUNC_PLATPOLICY 4
#define NBCI_FUNC_DISPLAYSTATUS 5
#define NBCI_FUNC_GETOBJBYTYPE 16
#define NBCI_FUNC_GETALLOBJS 17
#define NBCI_FUNC_GETEVENTLIST 18
#define NBCI_FUNC_CALLBACKS 29
#define NBCI_FUNC_GETBACKLIGHT 20
#define NBCI_FUNC_GETLICENSE 22
#define NBCI_FUNC_GETEFITABLE 23
Scope (\_SB.PCI0.PEG0.DGPU)
{
Method (NBCI, 2, NotSerialized)
{
Printf("NBCI {")
Local0 = NVIDIA_ERROR_UNSUPPORTED
Switch (ToInteger(Arg0)) {
// Bit list of supported functions
Case (NBCI_FUNC_SUPPORT) {
// Supported functions: 0
Local0 = Buffer() {0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}
}
// Query Plaform Capabilities
Case (NBCI_FUNC_PLATCAPS) {
Printf(" NBCI_FUNC_PLATCAPS: Unimplemented!")
}
// Query Platform Policies
Case (NBCI_FUNC_PLATPOLICY) {
Printf(" NBCI_FUNC_PLATPOLICY: Unimplemented!")
}
// Query Display status
Case (NBCI_FUNC_DISPLAYSTATUS) {
Printf(" NBCI_FUNC_DISPLAYSTATUS: Unimplemented!")
}
// Fetch and specific Object by Type
Case (NBCI_FUNC_GETOBJBYTYPE) {
Printf(" NBCI_FUNC_GETOBJBYTYPE: Unimplemented!")
}
// Fetch all Objects
Case (NBCI_FUNC_GETALLOBJS) {
Printf(" NBCI_FUNC_GETALLOBJS: Unimplemented!")
}
// Get list of Notify events and their meaning
Case (NBCI_FUNC_GETEVENTLIST) {
Printf(" NBCI_FUNC_GETEVENTLIST: Unimplemented!")
}
// Get list of system-required callbacks
Case (NBCI_FUNC_CALLBACKS) {
Printf(" NBCI_FUNC_CALLBACKS: Unimplemented!")
}
// Get the Backlight setup settings
Case (NBCI_FUNC_GETBACKLIGHT) {
Printf(" NBCI_FUNC_GETBACKLIGHT: Unimplemented!")
}
// Get Software License Number
Case (NBCI_FUNC_GETLICENSE) {
Printf(" NBCI_FUNC_GETLICENSE: Unimplemented!")
}
// Get EFI System Table
Case (NBCI_FUNC_GETEFITABLE) {
Printf(" NBCI_FUNC_GETEFITABLE: Unimplemented!")
}
Default {
Printf(" Unsupported NBCI_FUNC: %o", ToInteger(Arg0))
Local0 = NVIDIA_ERROR_UNSUPPORTED
}
}
Printf("} NBCI")
Return(Local0)
}
}