Nvidia Optimus의 Acer Aspire 4830TG ACPI 코드 해독

Nvidia Optimus의 Acer Aspire 4830TG ACPI 코드 해독

Nvidia Optimus 하이브리드 그래픽 시스템을 사용하는 Acer Aspire 4830TG의 ACPI 테이블에서 다음 NVOP 방법을 이해하려고 합니다. 상단의 NVOP 방법은 나중에 _DSM 방법에서 사용할 수 있는 일련의 명령을 정의합니다. 필요에 따라 카드를 켜거나 끄려면 acpi_call 모듈 또는 byo-switcheroo 모듈을 사용하여 어떤 메서드를 호출해야 합니까?

아래 코드를 참조하세요.

Method (NVOP, 4, Serialized)
{
    Name (_T_0, Zero)
    Store ("------- NV OPTIMUS DSM --------", Debug)
    If (LNotEqual (Arg1, 0x0100))
    {
        Return (0x80000001)
    }

    While (One)
    {
        Store (ToInteger (Arg2), _T_0)
        If (LEqual (_T_0, Zero))
        {
            Store (Buffer (0x04)
                {
                    0x61, 0x00, 0x01, 0x0C
                }, Local0)
            Return (Local0)
        }
        Else
        {
            If (LEqual (_T_0, 0x05))
            {
                Name (TMP5, Buffer (0x04)
                {
                    0x00, 0x00, 0x00, 0x00
                })
                CreateField (TMP5, Zero, 0x04, DAVF)
                CreateField (TMP5, 0x04, One, LIDF)
                CreateField (TMP5, 0x08, 0x06, TOGN)
                CreateField (Arg3, 0x1F, One, NCSM)
                CreateField (Arg3, 0x19, 0x05, NCSN)
                CreateField (Arg3, 0x18, One, DIMK)
                CreateField (Arg3, 0x0C, 0x0C, ACTD)
                CreateField (Arg3, Zero, 0x0C, ATTD)
                If (ToInteger (NCSM))
                {
                    Store (ToInteger (NCSN), TOGN)
                }
                Else
                {
                    If (ToInteger (DIMK))
                    {
                        GETD (ToInteger (ATTD), ToInteger (ACTD))
                        Store (\_SB.PCI0.PEG0.PEGP.NTOI, TOGN)
                        Store (One, DAVF)
                    }
                }

                Return (TMP5)
            }
            Else
            {
                If (LEqual (_T_0, 0x06))
                {
                    Name (TMP6, Package (0x0F)
                    {
                        Ones, 
                        0x2C, 
                        Ones, 
                        0x2C, 
                        Ones, 
                        0x2C, 
                        Ones, 
                        Ones, 
                        0x2C, 
                        Ones, 
                        Ones, 
                        0x2C, 
                        Ones, 
                        Ones, 
                        0x2C
                    })
                    Store (\_SB.PCI0.GFX0.IDI2, Index (TMP6, Zero))
                    Store (\_SB.PCI0.GFX0.IDI1, Index (TMP6, 0x02))
                    Store (\_SB.PCI0.GFX0.IDI4, Index (TMP6, 0x04))
                    Store (\_SB.PCI0.GFX0.IDI2, Index (TMP6, 0x06))
                    Store (\_SB.PCI0.GFX0.IDI1, Index (TMP6, 0x07))
                    Store (\_SB.PCI0.GFX0.IDI2, Index (TMP6, 0x09))
                    Store (\_SB.PCI0.GFX0.IDI4, Index (TMP6, 0x0A))
                    Store (\_SB.PCI0.GFX0.IDI1, Index (TMP6, 0x0C))
                    Store (\_SB.PCI0.GFX0.IDI4, Index (TMP6, 0x0D))
                    Return (TMP6)
                }
                Else
                {
                    If (LEqual (_T_0, 0x10))
                    {
                        Return (\_SB.PCI0.PEG0.PEGP.GOBT (Arg3))
                    }
                    Else
                    {
                        If (LEqual (_T_0, 0x1A))
                        {
                            CreateField (Arg3, 0x18, 0x02, OPCE)
                            CreateField (Arg3, Zero, One, FLCH)
                            If (ToInteger (FLCH))
                            {
                                Store (ToInteger (OPCE), OMPR)
                            }

                            Name (RBUF, Buffer (0x04)
                            {
                                0x00, 0x00, 0x00, 0x00
                            })
                            CreateField (RBUF, Zero, One, OPEN)
                            CreateField (RBUF, 0x03, 0x02, CGCS)
                            CreateField (RBUF, 0x06, One, SHPC)
                            CreateField (RBUF, 0x18, 0x03, DGPC)
                            CreateField (RBUF, 0x1B, 0x02, HDAC)
                            Store (One, OPEN)
                            Store (One, SHPC)
                            Store (0x02, HDAC)
                            Store (One, DGPC)
                            If (\_SB.PCI0.PEG0.PEGP.GSTA ())
                            {
                                Store (0x03, CGCS)
                            }
                            Else
                            {
                                Store (Zero, CGCS)
                            }

                            Return (RBUF)
                        }
                        Else
                        {
                            If (LEqual (_T_0, 0x1B))
                            {
                                Store (Arg3, Local0)
                                CreateField (Local0, Zero, One, OPFL)
                                CreateField (Local0, One, One, OPVL)
                                If (ToInteger (OPVL))
                                {
                                    Store (Zero, OPTF)
                                    If (ToInteger (OPFL))
                                    {
                                        Store (One, OPTF)
                                    }
                                }

                                Store (OPTF, Local0)
                                Return (Local0)
                            }
                            Else
                            {
                                Return (0x80000002)
                            }
                        }
                    }
                }
            }
        }

        Break
    }
}

Method (GOBT, 1, NotSerialized)
{
    Name (OPVK, Buffer (0xE2)
    {
        /* 0000 */    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
        /* 0008 */    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
        /* 0010 */    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
        /* 0018 */    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
        /* 0020 */    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
        /* 0028 */    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
        /* 0030 */    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
        /* 0038 */    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
        /* 0040 */    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
        /* 0048 */    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
        /* 0050 */    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
        /* 0058 */    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
        /* 0060 */    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
        /* 0068 */    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
        /* 0070 */    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
        /* 0078 */    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
        /* 0080 */    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
        /* 0088 */    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
        /* 0090 */    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
        /* 0098 */    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
        /* 00A0 */    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
        /* 00A8 */    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
        /* 00B0 */    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
        /* 00B8 */    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
        /* 00C0 */    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
        /* 00C8 */    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
        /* 00D0 */    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
        /* 00D8 */    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
        /* 00E0 */    0x00, 0x00
    })
    CreateWordField (Arg0, 0x02, USRG)
    If (LEqual (USRG, 0x564B))
    {
        Return (OPVK)
    }

    Return (Zero)
}

Method (_INI, 0, NotSerialized)
{
    Store (Zero, \_SB.PCI0.PEG0.PEGP._ADR)
}

Method (GSTA, 0, Serialized)
{
    If (LEqual (\_SB.PCI0.PEG0.PEGP.PI17, One))
    {
        Return (One)
    }
    Else
    {
        Return (Zero)
    }
}

Method (_ON, 0, Serialized)
{
    \_SB.PCI0.PEG0.PEGP.PWRE ()
    Store (Zero, LNKD)
    While (LLess (LNKS, 0x07))
    {
        Sleep (One)
    }

    Store (Zero, CMDR)
    Store (VGAB, VGAR)
    Store (0x06, CMDR)
}

Method (_OFF, 0, Serialized)
{
    Store (VGAR, VGAB)
    Store (One, LNKD)
    While (LNotEqual (LNKS, Zero))
    {
        Sleep (One)
    }

    \_SB.PCI0.PEG0.PEGP.PWRD ()
}

Method (_PS0, 0, NotSerialized)
{
    If (DGOS)
    {
        GLSC ()
        \_SB.PCI0.PEG0.PEGP._ON ()
        GLSR ()
        Store (Zero, DGOS)
        Store (Zero, MLTF)
        Store (Zero, \_SB.PCI0.LPCB.EC0.DSPM)
    }
}

Method (_PS3, 0, NotSerialized)
{
    If (LEqual (\_SB.PCI0.PEG0.PEGP.OMPR, 0x03))
    {
        GLSC ()
        \_SB.PCI0.PEG0.PEGP._OFF ()
        GLSR ()
        Store (One, DGOS)
        Store (0x02, \_SB.PCI0.PEG0.PEGP.OMPR)
        Store (One, \_SB.PCI0.LPCB.EC0.DSPM)
    }
}

Method (_STA, 0, Serialized)
{
    Return (0x0F)
}

Method (_ROM, 2, NotSerialized)
{
    Store (Arg0, Local0)
    Store (Arg1, Local1)
    If (LGreater (Local1, 0x1000))
    {
        Store (0x1000, Local1)
    }

    If (LGreater (Local0, 0x00010000))
    {
        Return (Buffer (Local1)
        {
            0x00
        })
    }

    If (LGreater (Local0, RVBS))
    {
        Return (Buffer (Local1)
        {
            0x00
        })
    }

    Multiply (Local1, 0x08, Local3)
    Name (ROM1, Buffer (0x8000)
    {
        0x00
    })
    Name (ROM2, Buffer (Local1)
    {
        0x00
    })
    If (LLess (Local0, 0x8000))
    {
        Store (RBF1, ROM1)
    }
    Else
    {
        Subtract (Local0, 0x8000, Local0)
        Store (RBF2, ROM1)
    }

    Multiply (Local0, 0x08, Local2)
    CreateField (ROM1, Local2, Local3, TMPB)
    Store (TMPB, ROM2)
    Return (ROM2)
}

Method (MXMX, 1, Serialized)
{
    If (LEqual (Arg0, One))
    {
        P8XH (One, 0x99, P8XH (Zero, One, Return (One), Return (Zero)))
    }
}

Name (MXM3, Buffer (0x45)
{
    /* 0000 */    0x4D, 0x58, 0x4D, 0x5F, 0x03, 0x00, 0x3D, 0x00, 
    /* 0008 */    0x30, 0x10, 0xB8, 0xFF, 0xF9, 0x3E, 0x00, 0x00, 
    /* 0010 */    0x00, 0x01, 0x8A, 0xFF, 0xF9, 0x3E, 0x00, 0x00, 
    /* 0018 */    0x60, 0x79, 0xD0, 0xFE, 0xF9, 0x3E, 0x00, 0x00, 
    /* 0020 */    0x20, 0x2B, 0xE2, 0xFE, 0xF9, 0x3E, 0x00, 0x00, 
    /* 0028 */    0x60, 0x6C, 0xEA, 0xFE, 0xF9, 0x3E, 0x00, 0x00, 
    /* 0030 */    0x01, 0x90, 0x01, 0x00, 0x03, 0x00, 0x90, 0x01, 
    /* 0038 */    0x13, 0x00, 0x90, 0x01, 0xE5, 0x0D, 0x01, 0x01, 
    /* 0040 */    0x01, 0x00, 0x00, 0x00, 0x96
})
Method (_DSM, 4, Serialized)
{
    Name (_T_0, Zero)
    If (LEqual (Arg0, Buffer (0x10)
            {
                /* 0000 */    0xF8, 0xD8, 0x86, 0xA4, 0xDA, 0x0B, 0x1B, 0x47, 
                /* 0008 */    0xA7, 0x2B, 0x60, 0x42, 0xA6, 0xB5, 0xBE, 0xE0
            }))
    {
        Return (\_SB.PCI0.PEG0.PEGP.NVOP (Arg0, Arg1, Arg2, Arg3))
    }

    If (LEqual (Arg0, Buffer (0x10)
            {
                /* 0000 */    0x00, 0xA4, 0x04, 0x40, 0x7D, 0x91, 0xF2, 0x4C, 
                /* 0008 */    0xB8, 0x9C, 0x79, 0xB6, 0x2F, 0xD5, 0x56, 0x65
            }))
    {
        While (One)
        {
            Store (ToInteger (Arg2), _T_0)
            If (LEqual (_T_0, Zero))
            {
                Return (Buffer (0x04)
                {
                    0x01, 0x00, 0x01, 0x01
                })
            }
            Else
            {
                If (LEqual (_T_0, 0x18))
                {
                    Return (Buffer (0x04)
                    {
                        0x00, 0x03, 0x00, 0x00
                    })
                }
                Else
                {
                    If (LEqual (_T_0, 0x10))
                    {
                        If (LEqual (Arg1, 0x0300))
                        {
                            Return (MXM3)
                        }
                    }
                }
            }

            Break
        }

        Return (0x80000002)
    }

    Return (0x80000001)
}

원본 ACPI 테이블은 다음에서 확인할 수 있습니다.
http://bugs.launchpad.net/lpbugreporter/+bug/752542/+attachment/2235754/+files/Aspire%204830TG.tar.gz

http://github.com/mkottman/acpi_call
http://github.com/awilliam/asus-switcheroo

답변1

귀하가 게시한 코드와 코드를 분석한 결과 acpi_call가장 유력한 후보는 다음과 같다는 결론에 도달했습니다.

echo '\_SB.PCI0.PEG0.PEGP._OFF' > /proc/acpi/call

카드를 닫고

echo '\_SB.PCI0.PEG0.PEGP._ON' > /proc/acpi/call

다시 열어보세요.

~해야 한다README다음 과 같이 안전하게 테스트할 수 있습니다 acpi_call.

모든 방법을 테스트하면 괜찮을 것입니다.

이것은 \_SB.PCI0.PEG0.PEGP._OFF스크립트에서 테스트된 방법 중 하나입니다 test_off.sh. 또한 이는 ..._OFFACPI 코드에 나타나는 유일한 방법입니다.

이것이 작동하지 않으면예상한 대로 \_SB.PCI0.PEG0.PEGP._PS3일시 중지하고 \_SB.PCI0.PEG0.PEGP._PS0다시 시작해 볼 수 있습니다. 코드에서 메소드는 호출하는 것으로 나타나고 일부 추가 테스트 등도 ..._OFF표시됩니다 . .._ON해당 이름은 전원 켜기/일시 중지 상태 간 전환과의 관계도 암시합니다.

답변2

직접 전화하는 것은 권장되지 않습니다 _ON. _OFF전원 상태를 전환할 수 있는 "올바른" ACPI 방법에 대해 많은 ACPI 테이블을 분석한 결과 Nvidia 카드를 비활성화하는 두 가지 일반적인 방법이 있다는 결론을 내렸습니다.

Launchpad의 SSDT4 문서에 따르면 노트북은 두 가지 방법을 모두 지원하는 것으로 보입니다. acpi_callACPI 메서드 호출을 실행하여 전원을 전환하는 것은 중단으로 인해 중단될 수 있으므로 권장되지 않습니다. 당신은 사용해야합니다bbswitch대신, 방법하다일시 중지/재개 전원 전환을 올바르게 처리합니다. (공개: 나는 그 저자입니다)

자세한 기술 내용은 다음을 참조하세요.http://wiki.bumblebee-project.org/ACPI-for-Developers. acpi_call, bbswitch 및 vgaswitcheroo를 비교했습니다.http://wiki.bumblebee-project.org/Comparison-of-PM-methods.

관련 정보