Jump to content

E6420: Brightness keys though ACPI patching


noname33

Recommended Posts

Hi, Sorry my English.

 

It's true this is a old topic, but for my, never worked properly. With the help of some kexts I could middle-solve the problem, but never ended for work fine 100% stable.

Well, now I have a few of free time, and I searched in the dsdt all the code related with the BRT6. And what a found, gives me a clear explanation to what happen here.

 

There are two post related with this. One is here: https://osxlatitude.com/forums/topic/19433-latitude-e6420-dsdt-review/#comment-120052.

The other is the code showed by Hervé about the brightness (here:

 

And this is the code of mi Latitude E6420 

  Method (SMEE, 1, NotSerialized)
    {
        Store (Arg0, Local0)
        Store (GENS (0x11, 0x00, 0x00), Local0)
        If (LGreaterEqual (\_SB.OSID (), 0x20))
        {
            If (And (Local0, 0x04))
            {
                \EV13 (0x01, 0x00)
            }
            If (And (Local0, 0x02))
            {
                \EV13 (0x02, 0x00)
            }
        }
        If (And (Local0, 0x08))
        {
            Store (GENS (0x1D, 0x00, 0x00), Local0)
            \EV14 (Local0, 0x00)
        }
    }


If we follow a bit the code, we will have this:

Method (SMEE, 1, NotSerialized)
    {
        Store (Arg0, Local0)
        Store (GENS (0x11, Zero, Zero), Local0)
        If (And (Local0, 0x04))
        {
            \_SB.PCI0.PEG0.VID.BRT6 (One, Zero)
            \_SB.PCI0.VID.BRT6 (One, Zero)
        }
        Else
        {
            If (And (Local0, 0x02))
            {
                \_SB.PCI0.PEG0.VID.BRT6 (0x02, Zero)
                \_SB.PCI0.VID.BRT6 (0x02, Zero)
            }
        }
        If (And (Local0, 0x08))
        {
            \_SB.PCI0.IGPU.IBL1 (GENS (0x1D, Zero, Zero), Zero)
        }
    }

 

Then you can see this: Store (GENS (0x11, Zero, Zero), Local0)

And GENS is the 'manager' of the SNVP, SNVG, SNWB, SNRB, SNVC, etc functions what we already know.  (see the first link). And know come the spectacle.

Method (GENS,3)
{
//here arg0 = 17, arg1=0, and arg2=0, then:
        Store (Arg1, Local0)//<-- well, Local0 is 0 now.
    if type of Arg1 is equal to number
    {
        //we enter here, because 0 is a number type
        Store (SMBI (Arg0, Arg1), Local0)

 

Now, we go to see 'Store (SMBI (Arg0, Arg1), Local0)' to know which value takes Local0.

        Method (SMBI, 2, NotSerialized)
        {
            SNVC (Arg0) //<-- we already know snvc
            Add (SMIB, 0x04, Local0)
            OperationRegion (WWPR, SystemMemory, Local0, 0x04) //we already know this Region
            Field (WWPR, ByteAcc, Lock, Preserve)
            {
                SDW0,   32
            }
            Store (Arg1, SDW0)
            ASMI ()
            Return (SDW0)
        }     


Then:

    //1
        SNVC (Arg0) => Method (SNVC, 1, NotSerialized)
        {
            OperationRegion (WWPR, SystemMemory, SMIB, 0x04)
            Field (WWPR, DWordAcc, Lock, Preserve)
            {
                SCDW,   32
            }
            Store (Arg0, SCDW)//<-- here we store 00 00 00 11 (0x11 in Dword)in SMIB pos
        }
    //2
          OperationRegion (WWPR, SystemMemory, Local0, 0x04) //we already know this Reg
          Field (WWPR, ByteAcc, Lock, Preserve)
          {
              SDW0,   32
          }
       Store (Arg1, SDW0)//<-- here we store 00 00 00 00 in SMIB + 4 position
    //3
    ASMI() => OperationRegion (SMIR, SystemIO, PSMI, 0x01)
            Field (SMIR, ByteAcc, Lock, Preserve)
            {
                SCMD,   8
            }
           Store (0x04, SCMD)// here we store 0x04 always and nothing more
    //4, The surprise!
         Return (SDW0) //<-- we two steep before, did something like Store (Arg1, SDW0), and Arg1 was 0.

    //this means return 0x00000000


 Well, now we know that inside of GENS ' Store (SMBI (Arg0, Arg1), Local0) ' assign 0 to that Local0 when GENS is called, and GENS always return its Local0 to the Local0 of SMME, and you can see at the start of this mess-up that SMME expects three valid values, 2, 4, or 8.

 

What happen?, well, Local0 of SMME always is 0 since GENS always return 0, and in this case, the call for BRT6 never will be triggered. In conclusion, the brightness never will can work. I don't say could work good or bad, it's more simple still, never will can work. 
 

Link to comment
Share on other sites

Well, then I think, so, I go to try remove the GENS and make the evaluation directly with Arg0 instead of Local0, but is not easy even do that.

 

how you can see here in other post by Hervé again:

 

 

That function called SMME is called once from SMIE, and SMIE start by:

 

        Store (GENS (0x10, 0x00, 0x00), Local0) //<--- we already learned this return 0 alway while arg0 is a number and arg1 is 0


And later make a evaluation If Else, of Local0, where it expect Local0 will take the value of 0x02, 0x08, 0x10, 0x40 or 0x80, but never 0x00, and then, no one of the clause in this function works.

 

It enter, and exit, without doing any single thing more.

 

Link to comment
Share on other sites

  • Administrators

The brightness keys ACPI patch I posted does not apply to the Sandy Bridge Latitude E6x20 as is. I tried it to no avail on my E6220, whether BIOS operating in legacy of UEFI mode. Instead, I called on a different patch I had found on the web that I adapted for my E6220. I posted the details in my E6220 Mojave guide; look it up.

 

It's a simple ACPI renaming patch in the Clover config file + a patched SSDT-Q66 table. With Mojave, I completely moved away from a patched DSDT to a simple and basic set of a few patched SSDTs + associated ACPI patches in the bootloader's config file. It's very minimal and very efficient.

 

In a nutshell, all you do is replace the original _Q66 event handling method:

            Method (_Q66, 0, NotSerialized)  // _Qxx: EC Query
            {
                If (LNotEqual (ECRD, One))
                {
                    Return (Zero)
                }
                NEVT ()
                Return (Zero)
            }

by this revised code:

        Method (_Q66, 0, NotSerialized)  // _Qxx: EC Query
        {
            If (LNotEqual (\ECRD, One))
            {
                Return (Zero)
            }
            NEVT ()
            \_SB.AMW0.WED0 (One)
            Mid (\_SB.AMW0._WED (0xD0), Zero, 0x06, Local2)
            If (LEqual (Local2, Buffer (0x06)
                    {
                         0x02, 0x00, 0x10, 0x00, 0x50, 0x00             
                    }))
            {
                Notify (\_SB.PCI0.LPCB.PS2K, 0x0365)
            }
            If (LEqual (Local2, Buffer (0x06)
                    {
                         0x02, 0x00, 0x10, 0x00, 0x48, 0x00             
                    }))
            {
                Notify (\_SB.PCI0.LPCB.PS2K, 0x0366)
            }
            Return (Zero)
        }

making sure not to forget the ACPI renaming in your config file which is necessary to bypass the original _Q66 method of the (native) DSDT table and inject its replacement through SSDT:

Find: 5F513636 (="_Q66")
Replace: 5F583636 (="_X66")

 

And that's it.

Link to comment
Share on other sites

For end the Story, I would swore that I remember get different result inside of BRT6 according to the order that I put LCD and PS2K notification. So in the other hand we can see a lot of event that never will execute via DSDT. 

 

Then I guess BRT6 is called from the BIOS directly like _SB.PCI0.VID.BRT6, and skip SMME and SMIE. Then probably this would be an aware bug for try to make difficult install other OS that Windows. I bought this laptop over 2012 and over 2017 the BIOS A24 was release, so I don't believe the people of Dell don't Know that all these functions don't works via AML ACPI.

Link to comment
Share on other sites

  • Administrators

in 2023, it's kind of irrelevant... There are many PCs with bugged BIOS tables (DSDT and/or otherwise), Dell is not a unique actor in that respect. Yet, Dell laptops remain ideal platforms by far and large (especially Latitude laptops) when it comes to running OS X/macOS on them.

Link to comment
Share on other sites

Yes you are right I think, even I believe in 2013 already should be irrelevant for them. The principal reason why I believe that is because my eyes can see that code, so of course they knew what thy made, and of course I don't go to enter to evaluate their corporation motivates.

 

We were who decided bought Dell, I don't go to blame anybody for my decision.

 

 

Link to comment
Share on other sites

I put your provided code in my DSDT, and nothing happened. It seem a good code, thank you.

 

But it doesn't work to me, and at this moment, I hesitate seriously about that code gets work in any Dell.

 

Well, the code seem to be good, at least I think so, but the issue is that the method _Q66 never is triggered!. This method's _Qxx, are called from the BIOS or embedded controller, and, I thought your code should work, fine or bad, but it should work in some way because it's under the unique _Q that exist ion this DSDT.

 

Then, because it's doesn't work, I made a script, which add a debug store inside every thing, and I run it. The result was very very disappointed, but in the other hand this help me to understand better what happen here.

 

This is a example of the debug code that I added almost in every line:

  Reveal hidden contents

 

And this is the poor result I got:

  Reveal hidden contents

 

Then I traced that log in the dsdt, and this is the result. ( You can follow the steps, they are ordered by //number_step, there are only 32  )

  Reveal hidden contents

 

And that is all. It's like the aliens do something. It stooping abruptly without a clear reason and disappears in the middle of code execution. No longer will back to work anything of the ACPI. No longer a line of ACPI debug is written.

 

The ACPI dead there, and you can connect or disconnect what you want, usb, display, etc.. but the ACPI doesn't work anymore.

 

In this point, I can see the ACPI code is used for the OS (not Windows) like a schedule of the hardware tree, but given the conditions, the OS do not used that ACPI code anymore.  And the BIOS neither, simply the ACPI doesn't exist because doesn't work, and nobody use it. Before that, you don't back to get a debug line about the ACPI. Of course that include the _Q66 method, which never is called.

 

I made some progress about the topic, by adding a ECDT table which achieve that the _Q66 works in the ACPI events, and now I'm rebuilding the .dsl for make it works, and also I had to change the method PCI0._INI  for avoid it works beyond of OSYS=0x2710. Now I have a big load of ACPI methods that are loaded in the logs, and when the display turn off or on, and when I plug and play any usb, the logs show the ACPI works.

 

This is very short log of the log that now I got from the ACPI when plug and USB (The _Q66 works activated by the BIOS):

  Reveal hidden contents

 

Well, now you know your Dell DSDT does't work anything, and it's readed by the OS like a 'boot component' for have some idea of the hardware system, but the ACPI Dell computer, are designed aware for it doesn't work, and probably after running, if you don't use windows and you use Linux, BSD, Mac , you don't have ACPI anymore, because Dell think you are Idiot and they know what is the better for you, and what OS can you use and what you can not use. 

Link to comment
Share on other sites

Definitely I abandon Hackintosh. 

 

Well, I tried to fix it, but it is highly designed for not working out of the OEM OS.

 

For example this a short list of the GNVS. The GNVS take values different according to the combination ACOS-OSYS. The worse case is given when you select OSYS=0x2710. If you write 2710 in the OSYS reg, the fields of the IGDM, GNVS, and others OperationRegion, will take at least 3 values before 'crash' and corrupt all the OperationsRegion fields.

 

The next are 3 logs of the same boot with OSYS=0x2710.

The first is the value of several fields of GNVS before make any other thing, the first thing that the dsdt do is take the fields value.

The second logs, are the same, but the values are read just after running the OS.

And the 3, is the same, but the values were read 5 min after run.

(There is a lot of fields, so I omit a lot, but the changes are similar some other hundred of fields)

 

This is before Write any thing (OSYS yet hasn't written, It's the default values):

  Reveal hidden contents

 

Now, is just running the OS, OSYS is 2710 how you can see. Also all the values of GNVS have take changes:

  Reveal hidden contents


And this is over 5 min after running the OS. All fields are corrupt:

  Reveal hidden contents

 

And this still is worse with the long field, for example it's a show other simple comparative example of some fields in the IGDM (Intel Graphics Device):

Before running:

  Reveal hidden contents

 

the same, little time after running:

  Reveal hidden contents

 

And, at least for my, the best case is when I select OSYS=Windows 2006 and ACOS 0x20. 

If I try OSYS=Linux and ACOS 0x40, the fields are corrupt in the same way, but with C0 instead of FF,. Almost all the fields take C0C0C0 etc as its value.

If try OSYS=WinXP, then all the digits becomes to 0 and F.

 

So, Ok, it's no viable, and I rather abandon because it could works very fine, but it's designed highly to it not work if the OS is not a Windows, and ok, I can see the display and I can use other OS, but none will work properly, and well, it's all :)

 

Link to comment
Share on other sites

×
×
  • Create New...