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
。また、これは..._OFF
ACPIコードに現れる唯一の方法です。
これがうまくいかない場合期待どおりに一時\_SB.PCI0.PEG0.PEGP._PS3
停止して\_SB.PCI0.PEG0.PEGP._PS0
再起動してみてください。コードでは、メソッドは呼び出されるように見え、いくつかの追加テストも..._OFF
表示されます。.._ON
この名前は、電源投入/一時停止状態間の遷移との関係も示しています。
答え2
直接電話することはお勧めできません_ON
。_OFF
電源状態を切り替えることができる「正しい」ACPI方法について多くのACPIテーブルを分析した結果、Nvidiaカードを無効にする2つの一般的な方法があると結論付けました。
LaunchpadのSSDT4文書によると、ノートブックは両方の方法をサポートしているようです。acpi_call
ACPIメソッド呼び出しを実行して電源を切り替えるのは中断のため中断される可能性があるため、お勧めできません。使用する必要がありますbbswitch
代わりに、方法する一時停止/再開電源の切り替えを正しく処理します。 (公開:私はその著者です)
詳細な技術については、以下を参照してください。http://wiki.bumblebee-project.org/ACPI-for-Developers。 acpi_call、bbswitch、vgaswitcherooを比較しました。http://wiki.bumblebee-project.org/Comparison-of-PM-methods。