/** @file ;****************************************************************************** ;* Copyright (c) 2019, Insyde Software Corp. All Rights Reserved. ;* ;* You may not reproduce, distribute, publish, display, perform, modify, adapt, ;* transmit, broadcast, present, recite, release, license or otherwise exploit ;* any part of this publication in any form, by any means, without the prior ;* written permission of Insyde Software Corporation. ;* ;****************************************************************************** */ Scope (DGPU_BRIDGE_SCOPE) { OperationRegion (RPCX, SystemMemory, PCI_SCOPE.DGBA, 0x1000) // Bridge Field (RPCX, DWordAcc, NoLock, Preserve) { Offset (0x04), // Command Register CMDR, 8, Offset (0x4A), // Device Status Register CEDR, 1, Offset (0x69), // Device Control2 Register , 2, LREN, 1, Offset (0xA4), D0ST, 2, } } Scope (DGPU_SCOPE) { OperationRegion (PCNV, SystemMemory, PCI_SCOPE.DGDA, 0x1000) // dGPU Field (PCNV, DWordAcc, NoLock, Preserve) { Offset (0x4), CMDR, 8, VGAR, 2008, Offset (0x488), , 25, HDAE, 1, // HDA Multifunction bit Register } OperationRegion (DGPU, SystemMemory, PCI_SCOPE.DGDA, 0x100) Field (DGPU, DWordAcc, NoLock, Preserve) { Offset (0x40), // Offset (64) SSSV, 32 } // OperationRegion (PCAP, PCI_Config, EECP, 0x14) // Field (PCAP, DWordAcc, NoLock, Preserve) // { // Offset (0xC), // Offset (12), // , 4, // EMLW, 6, // Offset (0x10), // Offset (16), // LCTL, 16 // } Name (VGAB, Buffer(0xFB) { 0x00 }) Name (LTRE, Zero) // Buffer for LTR Save/Restore Method (_STA, 0, Serialized) { Return (0x0F) // For Optimus function, always return DGPU is powered-ON } Method (_PS0, 0x0) { If (LNotEqual (DGPS, Zero)) { PCI_SCOPE.HGON (Zero) // IBV_customize: call to dGPU ON method If (LNotEqual (GPRF, One)) { Store (VGAB, VGAR) } Or (And (PCI_SCOPE.ELCT, 0x43), And (PCI_SCOPE.LCTR, 0xFFBC), PCI_SCOPE.LCTR) Store (Zero, DGPS) Store (Zero, HDAE) // Disable dGPU HDA device in _PS0 anyway } } Method (_PS3, 0x0) { If (LEqual (OMPR, 0x3)) { Store (PCI_SCOPE.LCTR, PCI_SCOPE.ELCT) If (LNotEqual (GPRF, One)) { Store (VGAR, VGAB) } PCI_SCOPE.HGOF (Zero) // IBV_customize: call to dGPU OFF method Store (One, DGPS) Store (0x2, OMPR) } } Method (GOBT, 1) { Name (OPVK, Buffer() { // Key below is *NOT A REAL KEY*, it is for reference // Customer need to ask NVIDIA PM to get the key // Customer need to put the key in between labels "// key start -" and // "// key end -". Please consult NVIDIA PM if any issues // Key start - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00 // Key end - }) CreateWordField (Arg0, 2, USRG) // Object type signature passed in by driver. If (LEqual (USRG, 0x564B)) { Return (OPVK) // 'VK' for Optimus Validation Key Object. } Return (Zero) } Name (DGPS, Zero) // DGPU Power Status 0:on 1:off Name (OMPR, 0x2) // Optimus MXM Power-Control Ready Name (DPST, One) Name (GPRF, Zero) Method (NVOP, 4, Serialized) // Called from Method (_DSM) { // Only Interface Revision 0x0100 is supported If (LNotEqual (Arg1, 0x100)) { Return (STATUS_ERROR_UNSPECIFIED) } // (Arg2) Sub-Function Switch (ToInteger (Arg2)) { // // Function 0: NVOP_FUNC_SUPPORT - Bit list of supported functions. // case (NVOP_FUNC_SUPPORT) { /* Store (Buffer(4) {0, 0, 0, 0}, Local0) Divide (NVOP_FUNC_SUPPORT, 8, Local2, Local1) // Function 0 // Local1 is Quotient, Local2 is Remainder ShiftLeft (0x01, Local2, Local2) Or (DeRefOf (Index (Local0, Local1)), Local2, Index (Local0, Local1)) Divide (NVOP_FUNC_OPTIMUSCAPS, 8, Local2, Local1) // Function 0x1A ShiftLeft (0x01, Local2, Local2) Or (DeRefOf (Index (Local0, Local1)), Local2, Index (Local0, Local1)) // force IGPU Divide (NVOP_FUNC_OPTIMUSFLAGS, 8, Local2, Local1) // Function 0x1B ShiftLeft (0x01, Local2, Local2) Or( DeRefOf(Index(Local0, Local1)), Local2, Index(Local0, Local1)) // Force IGPU Divide (NVOP_FUNC_GETOBJBYTYPE, 8, Local2, Local1) // Function 0x10 ShiftLeft (0x01, Local2, Local2) Or (DeRefOf (Index(Local0, Local1)), Local2, Index (Local0, Local1)) Divide (NVOP_FUNC_MDTL, 8, Local2, Local1) // Function 0x06 ShiftLeft(0x01, Local2, Local2) Or (DeRefOf (Index (Local0, Local1)), Local2, Index (Local0, Local1)) Divide (NVOP_FUNC_DISPLAYSTATUS, 8, Local2, Local1) // Function 0x05 ShiftLeft (0x01, Local2, Local2) Or (DeRefOf (Index (Local0, Local1)), Local2, Index (Local0, Local1)) Return (Local0) */ Return (Buffer(0x04) { // sub-func: 0, 5, 6, 16, 26, 27 supported 0x61, 0x00, 0x01, 0x0C }) } // // Function 5: NVOP_FUNC_DISPLAYSTATUS - Query the Display Hot-Key. // case (NVOP_FUNC_DISPLAYSTATUS) { CreateField (Arg3, 31, 1, NCSM) // Check the next combination sequence mask bit 31. Store (0, Local0) If (LEqual (ToInteger (NCSM), 0x1)) { CreateField (Arg3, 25, 5,NCIN) // Get the next combination sequence number bit 29:25 Store (ToInteger (NCIN), DPST) // Store the current valid value from driver Add (DPST, 1, DPST) // Add 1 to it because SBIOS needs to give the next combination sequence Mod (DPST, 18, Local0) } Else { If (LEqual (DPST, 0x0)) { // SBIOS sequence number should not return index 0 Add (DPST, 1, DPST) } // Just for testing, display status is implemented without the logic of attach and active display Mod (DPST, 18, Local0) ShiftLeft (Local0, 0x8, Local0) // Shift left 8 bits because display status is between bit 8:13 Add (DPST, 1, DPST) } Return (Local0) } // // Function 6: NVOP_FUNC_MDTL - Query Display Toggle List. // case (NVOP_FUNC_MDTL) { // Display Toggle List Name (TMP6, Package() { ones, 0x2C, // LVDS ones, 0x2C, // CRT ones, 0x2C, // HDMI ones, ones, 0x2C, // LVDS + CRT ones, ones, 0x2C, // LVDS + HDMI ones, ones, 0x2C // CRT + HDMI }) // Update Display Toggle List Store (DID2, Index (TMP6, 0)) // LVDS Store (DID1, Index (TMP6, 2)) // CRT Store (DID4, Index (TMP6, 4)) // HDMI Store (DID2, Index (TMP6, 6)) // LVDS + CRT Store (DID1, Index (TMP6, 7)) Store (DID2, Index (TMP6, 9)) // LVDS + HDMI Store (DID4, Index (TMP6, 10)) Store (DID1, Index (TMP6, 12)) // CRT + HDMI Store (DID4, Index (TMP6, 13)) Return (TMP6) } // // Function 16: NVOP_FUNC_GETOBJBYTYPE - Get Data Object. // case (NVOP_FUNC_GETOBJBYTYPE) { Return (DGPU_SCOPE.GOBT (Arg3)) } // // Function 26: NVOP_FUNC_OPTIMUSCAPS - Optimus Capabilities. // case (NVOP_FUNC_OPTIMUSCAPS) { CreateField (Arg3, 0, 1, FLCH) CreateField (Arg3, 1, 1, DVSR) // Modify Optimus DSM 0x1A for GC6 TDR support. CreateField (Arg3, 2, 1, DVSC) // Modify Optimus DSM 0x1A for GC6 TDR support. CreateField (Arg3, 24, 2, OPCE) If (LAnd (ToInteger (FLCH), LNotEqual (ToInteger (OPCE), OMPR))) { Store (ToInteger (OPCE), OMPR) // Optimus Power Control Enable - From DD } // Definition of return buffer. // bit 0 - Optimus Enabled // 0 : Optimus Graphics Disabled // 1 : Optimus Graphics Enabled (default) // bit 4:3 - Current GPU Control Status // 0 : GPU is powered off // 3 : GPU power has stabilized (default) // bit 6 - Shared discrete GPU Hot-Plug Capabilities // 1 : There are discrete GPU Display Hot-Plug signals co-connected to the platform // bit 8 - PCIe Configuration Space Owner Actual // 0 : SBIOS // 1 : GPU Driver // bit 26:24 - Optimus Capabilities // 0 : No special platform capabilities // 1 : Platform has dynamic GPU power control // bit 27:28 - Optimus HD Audio Codec Capabilities // 0 : No audio codec-related capabilities // 1 : Platform does not use HD audio // 2 : Platform supports Optimus dynamic codec control Store (Buffer(4) {0, 0, 0, 0}, Local0) CreateField (Local0, 0, 1, OPEN) CreateField (Local0, 3, 2, CGCS) CreateField (Local0, 6, 1, SHPC) // Shared discrete GPU Hot-Plug Capabilities CreateField (Local0, 8, 1, SNSR) // Modify Optimus DSM 0x1A for GC6 TDR support. CreateField (Local0, 24, 3, DGPC) // Optimus Power Capabilities CreateField (Local0, 27, 2, OHAC) // Optimus HD Audio Codec Capabilities Store (One, OPEN) // Optimus Enabled Store (One, SHPC) // Set '1' indicates there are discrete GPU Display Hot-Plug signals co-connected to the platform Store (One, DGPC) // Optimus Power Capabilities // 0: No special platform capabilities // 1: Dynamic GPU Power Control Store (0x2, OHAC) // Optimus HD Audio Codec Capabilities // 0: No audio codec-related capabilities // 1: Platform does not use HD audio (SBIOS will always disable audio codecs) // 2: Optimus dynamic codec control // 3: Dynamic power state reporting If (ToInteger (DVSC)) { If (ToInteger (DVSR)) { Store (One, GPRF) } Else { Store (Zero, GPRF) } } Store (GPRF, SNSR) If (LEqual (DGPS, Zero)) // IBV_customize: root port path { Store (0x3, CGCS) // Current GPU Control status: On } Else { Store (0x0, CGCS) // Current GPU Control status: Off } Return (Local0) } // // Function 27: NVOP_FUNC_OPTIMUSFLAGS - Optimus State flags. // case (NVOP_FUNC_OPTIMUSFLAGS) { Store (Arg3, Local0) CreateField (Local0, 0, 1, OPFL) CreateField (Local0, 1, 1, OPVL) If (ToInteger (OPVL)) { Store (Zero, OPTF) If (ToInteger (OPFL)) { Store(One, OPTF) } } Store (OPTF, Local0) Return (Local0) } default { // // FunctionCode or SubFunctionCode not supported // Return (STATUS_ERROR_UNSUPPORTED) } } } // // dGPU just output to HDMI in Optimus HW artchetecture // Method (_DOD, 0, NotSerialized) { Return (Package(0x01) {ACPI_ID_HDMI}) } // method : _ROM // Arguments: // Arg0: Integer Offset of the graphics device ROM data // Arg1: Integer Size of the buffer to fill in (up to 4K) // // Return Value: // Returns Buffer Buffer of requested video ROM bytes Method (_ROM, 2) { Store (Arg0, Local0) Store (Arg1, Local1) Name (VROM, Buffer(Local1) {0x00}) // Create 4K buffer to return to DD If (LGreater (Local1, 0x1000)) { Store (0x1000, Local1) // Return dummy buffer if asking for more than 4K } If (LGreater (Arg0, RVBS)) { Return (VROM) // Return dummy buffer if asking beyond VBIOS image } Add (Arg0, Arg1, Local2) If (LGreater (Local2, RVBS)) // If requested BASE+LEN > VBIOS image size { Subtract (RVBS, Local0, Local1) // Limit length to the final chunk of VBIOS image } Divide (Local0, 0x8000, Local3, Local4) // (Dividend, Divisor, Remainder, Result) Switch (Local4) { Case (0) { Store (DGPU_SCOPE.VBS1, Local5) } Case (1) { Store (DGPU_SCOPE.VBS2, Local5) } Case (2) { Store (DGPU_SCOPE.VBS3, Local5) } Case (3) { Store (DGPU_SCOPE.VBS4, Local5) } Case (4) { Store (DGPU_SCOPE.VBS5, Local5) } Case (5) { Store (DGPU_SCOPE.VBS6, Local5) } Case (6) { Store (DGPU_SCOPE.VBS7, Local5) } Case (7) { Store (DGPU_SCOPE.VBS8, Local5) } } Multiply (0x8000, Local4, Local4) // (Multiplicand, Multiplier, Result) Subtract (Local0, Local4, Local0) Mid (Local5, Local0, Local1, VROM) Return (VROM) } Method (MXMX, 1, Serialized) { If (LEqual (Arg0, Zero)) { // Acquire DDC/AUX mux // No mutex implemented. No need to acquire mutex. // Set mux to dGPU P8XH (One, 0x99) P8XH (Zero, Zero) Return (One) } If (LEqual (Arg0, One)) { // Release DDC/AUX mux // No mutex implemented. No need to release mutex. // 2-way mux. Hence no need to do anything P8XH (One, 0x99) P8XH (Zero, one) Return (One) } If (LEqual (Arg0, 0x02)) { P8XH (One, 0x99) P8XH (Zero, 0x02) // Get ddc/aux mux status for dGPU } Return (Zero) } Method (MXDS, 1, Serialized) { If (LEqual (Arg0, Zero)) { // Get display mux status for dGPU } If (LEqual (Arg0, One)) { // Set display mux to dGPU } Return (Zero) } Method (_DSM, 4, SERIALIZED) { // // Check for Nvidia Optimus _DSM UUID // // NVOP_DSM_GUID {A486D8F8-0BDA-471B-A72B-6042A6B5BEE0} If (LEqual (Arg0, ToUUID ("A486D8F8-0BDA-471B-A72B-6042A6B5BEE0"))) { Return (DGPU_SCOPE.NVOP (Arg0, Arg1, Arg2, Arg3)) } // // Check for Nvidia GPS _DSM UUID // // GPS_DSM_GUID {A3132D01-8CDA-49BA-A52E-BC9D46DF6B81} If (LEqual (Arg0, ToUUID ("A3132D01-8CDA-49BA-A52E-BC9D46DF6B81"))) { If (LNotEqual (DGPU_SCOPE.GPSS, Zero)) { Return (DGPU_SCOPE.GPS (Arg0, Arg1, Arg2, Arg3)) } } // // Check for Nvidia Optimus GC6 _DSM UUID // // GC6_DSM_GUID {CBECA351-067B-4924-9CBD-B46B00B86F34} If (LEqual (Arg0, ToUUID ("CBECA351-067B-4924-9CBD-B46B00B86F34"))) { If (LNotEqual (DGPU_SCOPE.GC6S, Zero)) { Return (DGPU_SCOPE.NVJT (Arg0, Arg1, Arg2, Arg3)) } } // // Check for Nvidia NBCI _DSM UUID // // NBCI_DSM_GUID {D4A50B75-65C7-46F7-BFB7-41514CEA0244} If (LEqual (Arg0, ToUUID ("D4A50B75-65C7-46F7-BFB7-41514CEA0244"))) { If (LNotEqual (DGPU_SCOPE.NBCS, Zero)) { Return (DGPU_SCOPE.NBCI (Arg0, Arg1, Arg2, Arg3)) } } // // Check for Nvidia SPB _DSM UUID // // SPB_DSM_GUID {95DB88FD-940A-4253-A446-70CE0504AEDF} If (LEqual (Arg0, ToUUID ("95DB88FD-940A-4253-A446-70CE0504AEDF"))) { If (LNotEqual (DGPU_SCOPE.VENS, Zero)) { Return (IGPU_SCOPE.SPB (Arg0, Arg1, Arg2, Arg3)) } } If (LEqual (Arg0, ToUUID ("4004A400-917D-4cf2-B89C-79B62FD55665"))) { Switch (ToInteger (Arg2)) { // // Function 0: MXM_FUNC_MXSS // case (MXM_FUNC_MXSS) { // Sub-Functions 0,16,24 are supported Return (ToBuffer (0x01010001)) } // // Function 24: MXM_FUNC_MXMI // case (MXM_FUNC_MXMI) { Return (ToBuffer (0x30)) } // // Function 16: MXM_FUNC_MXMS // case (MXM_FUNC_MXMS) { If(LEqual (Arg1, 0x300)) { If (LNotEqual (MXBS, 0)) { Name (MXM3, Buffer(MXBS) {0x00}) Store (MXMB, MXM3) Return (MXM3) } } } } Return (STATUS_ERROR_UNSUPPORTED) // MXM_ERROR_UNSUPPORTED - FunctionCode or SubfunctionCode not supported } Return (STATUS_ERROR_UNSPECIFIED) // MXM_ERROR_UNSPECIFIED } }