[Guide] How to Disable Discrete Graphics in Dual GPU Laptops (NVIDIA/AMD)



EliteMacx86

Administrator
Staff member
Many laptop has a dual graphics such as AMD Radeon or NVIDIA Geforce which utilizes a switching mechanism to switch from the integrated graphics(Intel HD) to the discrete graphics as per the graphics demand. When using NVIDIA, this feature is referred to Optimus Technology and AMD is referred to AMD Switchable Graphics. This type of switching/technology isn't supported on macOS or OS X. So you need to disable the discrete GPU in your BIOS as it's of no use on macOS or OS X.

Disabling the discrete graphics in BIOS is not the best the option as the device will be disabled in macOS as well as on Windows. To overcome this issue, you need a ACPI patching which is better option and the discrete GPU can be used in Windows or Linux.

For most of the time, the BIOS does not have such options, it can be difficult to install and you might need to delete the related graphics kexts. Also, by not disabling the discrete graphics, the device draws power even if it doesn't works on macOS or OS X. You'll need to disable the discrete graphics to save the battery life, generate less heat and noise.

For some users who might have this question in their mind that will it not affect the performance?
So the answer is "NO", not at all. This is because the discrete graphics cannot be utilized by macOS or OS X.

The other question may arise is would be i able to use the discrete graphics in Windows?
The answer is "YES", of course. You can use the discrete graphics device either NVIDIA or AMD when using Windows.

This guide covers the disabling of discrete graphics in dual GPU laptops. The dual GPU laptops comes in two variant:
Intel+NVIDIA which is known as Optimus Technoloy,
Intel+Radeon.

A laptop from ASUS (X302LJ) has been used as an example for this guide which features Intel HD Graphics 5500 and NVIDIA Geforce 920M. The ACPI files have been extracted using Clover F4 method. The native(untouched) files are under origin folder and the patched ACPI files are under patched. The files has been provided in the attachment of this post.

Before you start with this guide, i recommend you to read about DSDT and SSDT patching on laptops. The guide covers extraction of the ACPI files, disassembly, compiling, patching, saving and installing. Read here:

Patching for disabling the Discrete Graphics
First you'll need to find the SSDT with _OFF Method. To know this, we can use grep.
Open Terminal
Move to the working directory, where you dissembled the files.
Type:
Code:
grep -l Method.*_OFF *.dsl
Which results:
Code:
SSDT-10-SaSsdt .dsl
SSDT-11-SgPch.dsl
SSDT-12-OptTabl.dsl
Note down the SSDT with _OFF Method.
Also, you need to find the DSDT and SSDT which contains the _INI Method
Type:
Code:
grep -l Method.*_INI *.dsl
Which results:
Code:
DSDT.dsl
SSDT-10-SaSsdt .dsl
SSDT-11-SgPch.dsl
SSDT-12-OptTabl.dsl
Note down the DSDT and SSDT with _INI Method.
Separate those DSDT and SSDT to any other directory.

Note:
  • The SSDT-10-SaSsdt.dsl, SSDT-11-SgPch.dsl and SSDT-12-OptTabl.dsl are listed again, this is where the _OFF and _INI are located.
But you need to confirm which exact SSDT has both the methods. To do so, follow the instructions below

Open the SSDT one by one and search for "Method (_INI". This is SSDT which needs to be patched.

When searching for the _INI method in "SSDT-10-SaSsdt.dsl", we find 4 _INI methods:
Code:
Method (_INI, 0, NotSerialized)  // _INI: Initialize
        {
            Store (LTRA, LTRS)
            Store (OBFA, OBFS)
        }
The second _INI
Code:
Method (_INI, 0, NotSerialized)  // _INI: Initialize
        {
            Store (LTRB, LTRS)
            Store (OBFB, OBFS)
        }
The third _INI
Code:
Method (_INI, 0, NotSerialized)  // _INI: Initialize
        {
            Store (LTRC, LTRS)
            Store (OBFC, OBFS)
        }
And the fourth _INI
Code:
Method (_INI, 0, NotSerialized)  // _INI: Initialize
        {
            If (LAnd (LNotEqual (And (ABAR, 0xFFFFC004), 0xFFFFC004), LNotEqual (And (ABAR, 0xFFFFC000), Zero)))
            {
                Store (ABAR, BARA)
                If (LNotEqual (ABAH, Zero))
                {
                    Or (BARA, ShiftLeft (ABAH, 0x20), BARA)
                }
            }
        }
In this case, none of the methods contains the address of the discrete graphics device. So we need to look for the other SSDT searching the same _INI method.

When searching for the _INI method in "SSDT-11-SgPch.dsl", we find one _INI method:
Code:
Method (_INI, 0, NotSerialized)  // _INI: Initialize
        {
            Store (Zero, \_SB.PCI0.RP05.PEGP._ADR)
        }
This is the SSDT we're looking for. This SSDT contains the address of the discrete graphics device.
If you look for the same method in "SSDT-12-OptTabl.dsl", we find one _INI method:
Code:
Method (_INI, 0, NotSerialized)  // _INI: Initialize
        {
            Store (DID1, Index (TLPK, Zero))
            Store (DID2, Index (TLPK, 0x02))
            Store (DID3, Index (TLPK, 0x04))
            Store (DID4, Index (TLPK, 0x06))
            Store (DID5, Index (TLPK, 0x08))
            Store (DID6, Index (TLPK, 0x0A))
            Store (DID7, Index (TLPK, 0x0C))
            Store (DID2, Index (TLPK, 0x0E))
            Store (DID1, Index (TLPK, 0x0F))
            Store (DID2, Index (TLPK, 0x11))
            Store (DID3, Index (TLPK, 0x12))
            Store (DID2, Index (TLPK, 0x14))
            Store (DID4, Index (TLPK, 0x15))
            Store (DID2, Index (TLPK, 0x17))
            Store (DID5, Index (TLPK, 0x18))
            Store (DID2, Index (TLPK, 0x1A))
            Store (DID6, Index (TLPK, 0x1B))
            Store (DID2, Index (TLPK, 0x1D))
            Store (DID7, Index (TLPK, 0x1E))
        }
But this is not the SSDT we're looking for as it doesn't have any _INI method with the discrete graphics device address.

Note :
  • The correct SSDT will have a address of the GPU. For e.g \_SB.PCI0.RP05.PEGP._ADR
  • Find the access location, ACPI path in the SSDT, and note down the EC. For e.g, \SB.PCI0.RP05.PEGP -> _INI
  • In case, if you haven't find the correct SSDT which contains _INI method with the discrete graphics device address, search for the another SSDT. The only left SSDT was "SSDT-12-OptTabl.dsl" which isn't what we're looking for. We find the method in the second SSDT so didn't need to look in the third SSDT. But to confirm, you must check it.
So we've got the _INI and need to look for the _OFF method. It's pretty clear that the path to _OFF should also have \SB.PCI0.RP05.PEGP-> _OFF

So, we know that the _OFF is located in either SSDT-10-SaSsdt.dsl, SSDT-11-SgPch.dsl or SSDT-12-OptTabl.dsl
When searching for the _OFF method in "SSDT-10-SaSsdt.dsl", we find 3 _OFF methods:
Code:
Method (_OFF, 0, Serialized)  // _OFF: Power Off
            {
                If (LNotEqual (OSYS, 0x07D9))
                {
                    PGOF (Zero)
                    Store (Zero, _STA)
                }
            }
The second _OFF
Code:
Method (_OFF, 0, Serialized)  // _OFF: Power Off
            {
                If (LNotEqual (OSYS, 0x07D9))
                {
                    PGOF (One)
                    Store (Zero, _STA)
                }
            }
The third _OFF
Code:
Method (_OFF, 0, Serialized)  // _OFF: Power Off
            {
                If (LNotEqual (OSYS, 0x07D9))
                {
                    PGOF (0x02)
                    Store (Zero, _STA)
                }
            }
In this case, none of the methods contains the address of the discrete graphics device. So we need to look for the other SSDT searching the same _OFF method.

When searching for the _INI method in "SSDT-11-SgPch.dsl", we find one _OFF method:
Code:
Method (_OFF, 0, Serialized)  // _OFF: Power Off
            {
                If (LNotEqual (OSYS, 0x07D9))
                {
                    \_SB.PCI0.RP05.PEGP.SGOF ()
                    Store (Zero, _STA)
                }
            }
This is the SSDT we're looking for. This SSDT contains the address of the discrete graphics device.
If you look for the same method in "SSDT-12-OptTabl.dsl", we find one _OFF method:
Code:
Method (_OFF, 0, Serialized)  // _OFF: Power Off
        {
            If (LEqual (CTXT, Zero))
            {
                If (LNotEqual (GPRF, One))
                {
                    Store (VGAR, VGAB)
                }

                Store (One, CTXT)
            }

            SGOF ()
        }
But this is not the SSDT we're looking for as it doesn't have any _OFF method with the discrete graphics device address.

Note:
  • The correct SSDT will have a address of the GPU. For e.g \_SB.PCI0.RP05.PEGP._SGOF
  • In case, if you haven't find the correct SSDT which contains _OFF method with the discrete graphics device address, search for the another SSDT. We find the method in the second SSDT. So that's the SSDT which we're looking for.
Now, we've got the SSDT which contains the _INI and the _OFF method. Now we need to look for the errors, if any.
Compile the "SSDT-11-SgPch.dsl". Upon compiling, it has no any errors. So we're good to go.
Now the patches can be applied.

Patches (SSDT)

[igpu] Rename GFX0 to IGPU
[gfx0] Disable from _INI (SSDT)

Patches (DSDTs)

[igpu] Rename GFX0 to IGPU
[gfx0] Disable from _REG (DSDT)

Applying the Patches

For SSDT :
Open the "SSDT-11-SgPch.dsl" using MaciASL.
Click on Patch button
Find and select the patch from the left pane.
When applying the second patch, the patches will not get applied because of incorrect address of the discrete graphics device. We need to replace the address of the graphics device. See notes below.
The default patch:
Code:
into method label _INI parent_label \_SB.PCI0.PEG0.PEGP insert
begin
//added to turn nvidia/radeon off\n
//External(\_SB.PCI0.PEG0.PEGP._OFF, MethodObj)\n
_OFF()\n
end;
which doesn't gets applied.
The modified patch (PEG0 changed to RP05):
Code:
into method label _INI parent_label \_SB.PCI0.RP05.PEGP insert
begin
//added to turn nvidia/radeon off\n
External(\_SB.PCI0.RP05.PEGP._OFF, MethodObj)\n
_OFF()\n
end;
Click on Apply.
After applying the patch, the patched SSDT will read:
Code:
 Method (_INI, 0, NotSerialized)  // _INI: Initialize
        {
            Store (Zero, \_SB.PCI0.RP05.PEGP._ADR)
            //added to turn nvidia/radeon off
            External(\_SB.PCI0.RP05.PEGP._OFF, MethodObj)
            _OFF()
        }
Click on Close.

Note :
  • If the patches doesn’t gets applied, replace the address of your GPU instead the default one in both the lines. For e.g. \SB.PCI0.RP05.PEGP. This is the same address which we noted down in the very first step when searching for _INI method.
For DSDT :
Open the DSDT using MaciASL.
Click on Patch button
Find and select the patch from the left pane and click on Apply.
When using the second patch, the patches will get applied but we need to replace the address of the discrete graphics device. See notes below.
The default patch:
Code:
into method label _REG parent_hid PNP0C09 insert
begin
//added to turn nvidia/radeon off\n
If (LAnd(LEqual(Arg0,3),LEqual(Arg1,1)))\n
{\n
    External(\_SB.PCI0.PEG0.PEGP._OFF, MethodObj)\n
    \_SB.PCI0.PEG0.PEGP._OFF()\n
}\n
end;
The modified patch (PEG0 changed to RP05):
Code:
into method label _REG parent_hid PNP0C09 insert
begin
//added to turn nvidia/radeon off\n
If (LAnd(LEqual(Arg0,3),LEqual(Arg1,1)))\n
{\n
    External(\_SB.PCI0.RP05.PEGP._OFF, MethodObj)\n
    \_SB.PCI0.RP05.PEGP._OFF()\n
}\n
end;
Click on Apply.
After applying the patch, the patched DSDT will read:
Code:
Method (_REG, 2, NotSerialized)  // _REG: Region Availability
            {
                If (LEqual (Arg0, 0x03))
                {
                    Store (Arg1, ECFL)
                }
                //added to turn nvidia/radeon off
                If (LAnd(LEqual(Arg0,3),LEqual(Arg1,1)))
                {
                    External(\_SB.PCI0.RP05.PEGP._OFF, MethodObj)
                    \_SB.PCI0.RP05.PEGP._OFF()
                }
            }
        }
    }
Click on Close.

Note :
  • The patches will get applied but you’ll need to replace the address of your GPU instead the default one in both the lines. For e.g \SB.PCI0.RP05.PEGP.
Compiling

After patching the DSDT and SSDTs, you need to compile the files.
Simply click on compile and look for errors. If there's any error, fix it and again click on Compile.
If there's no error, the files will be compiled successfully.

Saving the ACPI files
After compiling, the next step is to save the file for the installation.
  1. Go to File
  2. Select Save as
  3. A dialogue box will appear asking the location and the file extension to save the file.
  4. Select ACPI(ACPI Machine Language)
  5. Click on Save
Note:
  • It's a good idea to save the patched DSDT and SSDTs in any other location than the original.
And we're ready to place the files. At this point all the patched files can be saved and placed in ACPI/patched.

Conclusion
DSDT.aml (includes _REG patch)
SSDT-11-SgPch.aml (includes _INI and _OFF patch)

Installing the DSDT and SSDT
  1. Copy all the patched DSDT and SSDTs
  2. Mount your EFI partition
  3. Navigate to : EFI/Clover/ACPI/patched
  4. Place all the patched files over here
Note :
  • If your laptop has a NVIDIA discrete graphics device, use "nv_disable=1" as a boot args in config.plist file.
Restart your laptop.
The discrete graphics device should be disabled now.

Problem Reporting
If you're having issues with your DSDT or SSDTs when patching or finding the device address or unable to fix errors, you need to provide all the fresh, native files you extracted.

In case, if the discrete graphics doesn't gets disabled, you need to provide the Problem Reporting files as per laptop FAQ: https://www.elitemacx86.com/threads/faq-read-first-frequent-questions-related-to-laptop.136/

Credits :
RehabMan

Sample Attachment
The ACPI files are attached below which has been used as a example in this guide:
 

Attachments

Similar threads



Top