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スクリプトでテストされた方法の1つですtest_off.sh。また、これは..._OFFACPIコードに現れる唯一の方法です。

これがうまくいかない場合期待どおりに一時\_SB.PCI0.PEG0.PEGP._PS3停止して\_SB.PCI0.PEG0.PEGP._PS0再起動してみてください。コードでは、メソッドは呼び出されるように見え、いくつかの追加テストも..._OFF表示されます。.._ONこの名前は、電源投入/一時停止状態間の遷移との関係も示しています。

答え2

直接電話することはお勧めできません_ON_OFF電源状態を切り替えることができる「正しい」ACPI方法について多くのACPIテーブルを分析した結果、Nvidiaカードを無効にする2つの一般的な方法があると結論付けました。

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

関連情報