decifrar este código ACPI Acer Aspire 4830TG para Nvidia Optimus

4

Estou tentando entender o seguinte método NVOP a partir das tabelas ACPI para um Acer Aspire 4830TG com um sistema gráfico híbrido Nvidia Optimus. O método NVOP no topo define um monte de instruções que podem ser usadas mais tarde no método _DSM. Qual método devo chamar com o módulo acpi_call ou o módulo byo-switcheroo para ligar / desligar o cartão sob demanda?

Veja o código abaixo:

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)
}

As tabelas originais da ACPI estão disponíveis aqui:
link

link
link

    
por 719016 27.07.2011 / 10:14

2 respostas

4

Analisando o código que você postou também ass acpi_call leva-me à conclusão de que os candidatos mais prováveis devem ser:

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

para desligar o cartão e

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

para ligá-lo novamente.

Você deve estar seguro para testá-los, pois o README para acpi_call declara:

It SHOULD be ok to test all of the methods

E \_SB.PCI0.PEG0.PEGP._OFF é um dos métodos testados no script test_off.sh . Ao mesmo tempo, é o único método ..._OFF que aparece no seu código ACPI.

Se eles não funcionarem como esperado, você pode tentar \_SB.PCI0.PEG0.PEGP._PS3 para suspensão e \_SB.PCI0.PEG0.PEGP._PS0 para retomada. Em seu código, esses métodos parecem chamar o ..._OFF e o .._ON com alguns testes adicionais, etc. Seus nomes também sugerem relação com a alternância entre estados de ativação / suspensão.

    
por 04.08.2011 / 11:44
1

Chamar diretamente _ON e _OFF não é recomendado. Analisei muitas tabelas ACPI para os métodos ACPI "corretos" que permitem alternar o estado de energia e concluí que existem dois métodos genéricos que desativam a placa Nvidia.

Seu laptop parece suportar os dois métodos de acordo com o arquivo SSDT4 no Launchpad. A execução de chamadas de método da ACPI usando acpi_call não é a maneira recomendada de alternar a energia quando ela é interrompida com a suspensão. Você deve usar bbswitch em vez disso, um método que faz manipular adequadamente alternando o poder de suspender / currículo. (divulgação: eu sou o autor disso)

Para mais detalhes técnicos, consulte link . Eu fiz uma comparação entre acpi_call, bbswitch e vgaswitcheroo no link .

    
por 04.10.2012 / 19:28