quarta-feira, 4 de março de 2015

[Guide] Patching DSDT/SSDT for LAPTOP backlight control


Note: This guide is primarily for Intel HD graphics (HD3000->HD5000+). Although some of the kexts and patches mentioned here can be used in other scenarios, that is not the focus of this post.

By default, your non-Apple DSDT does not have the necessary trigger to cause AppleBacklight.kext to load. Although it is easy to make it load by adding a PNLF device (aka "Brightness Fix" from my laptop repo), it will likely not work correctly. It may not work at all prior to sleep, and even after sleep the full range of brightness will not be available. This is becuase AppleBacklight.kext only has profiles for panels that appear in actual Apple products and there can be PWM registers that are not initialized by BIOS as OS X expects.

A slightly modified DSDT patch can correct for the problem before sleep, and the issue of full range can be fixed by patching AppleBacklight.kext (or providing an injector kext that does the same thing), or by patching EDID. But still, smooth transitions when using keyboard controls will not work (reason not known).

A complete solution to the problem can be achieved with ACPIBacklight.kext and a more complex DSDT patch.

In order to implement brightness you must have working graphics drivers (QE/CI), and you must be using a laptop snb-platorm-id/ig-platform-id. Brightness controls are available only for internal LVDS displays.

DSDT/SSDT patching

There are two different DSDT patches available. One for pre-Haswell (Arrandale, Sandy Bridge/HD3000, Ivy Bridge/HD4000) and one for Haswell (HD4400/HD4600/HD5000+).

You should follow the general guidelines for DSDT patching as presented here: [Guide] Patching LAPTOP DSDT/SSDTs

The patches are available here: https://github.com/RehabMan/Laptop-DSDT-Patch

pre-Haswell: "Brightness Fix (HD3000/HD4000)"
Haswell: "Brightness Fix (Haswell)"

Apply only the brightness patch that applies to your hardware. The patch must be applied to the the file (DSDT or SSDT) where the integrated graphics device is defined. Intel hardware is always at address 0x00020000. Searching for "Name (_ADR, 0x00020000)" is a way to find the device. It is commonly called GFX0, so searching for "Device (GFX0)" is also an effective search most of the time.

The patch will only apply to the file where it finds the device at 0x0002000.

Note: By setting LMAX to Zero, you can cause the patch to use BIOS register values at boot. This can eliminate an extra flash at boot time and may be better for some laptops (the _BCL table is automatically scaled as required).


For complete brightness control including smooth transitions, you need to install ACPIBacklight.kext.

It is available here: https://github.com/RehabMan/OS-X-ACPI-Backlight

IGPU power management

It is common to fix power management for the IGPU at the same time as applying brightness. To implement IGPU PM, apply "Rename GFX0 to IGPU" to DSDT and all patched SSDTs. Failure to apply it universally will likely cause one or more SSDTs to be ignored.

Note: Older versions of the patch required this patch, but newer versions do not have that restriction. IGPU power management is still worthwhile to implement.

Backlight troubleshooting

After installing ACPIBacklight.kext rebooting with the brightness patch in place,you should have an operational brightness slider in SysPrefs->Displays. Keyboard control over backlight is a separate issue.

If your backlight control is not working, it could be due to one or more issues:
- incorrect patch applied
- a previous PNLF patch has been applied to DSDT
- Clover is providing PNLF in DSDT (avoid AddPNLF in ACPI/DSDT/Fixes)
- you forgot to drop OEM SSDTs (Clover: ACPI/SSDT/DropOem=true; Chameleon DropSSDT=Yes)
- renames were not balanced causing OS X to ignore one or more SSDTs
- there are duplicate _DSM methods causing OS X to ignore one or more SSDTs
- your DSDT/SSDTs are out-of-sync with your native DSDT/SSDTs files
- you have not disabled a secondary discrete graphics card in a switched configuration
- your hardware does not use the IGPU PWM backlight controls

To determine if your hardware uses the PWM backlight controls, temporarily remove ACPIBacklight.kext to use AppleBacklight.kext. If the brightness slider in SysPrefs->Displays works (check both before and after display sleep), then your laptop uses the backlight registers and the cause is one of the others mentioned above. 

If it does not work, then your laptop doesn't use the backlight registers. In that case, try "Brightness Fix", which will cause ACPIBacklight.kext to use the OEM methods (most of the time, the OEM methods do not work). If your OEM methods actually work (with "Brightness Fix"), you may be able to use "Brigthness Fix (ACPI 100)" for smoother transitions and more backlight levels.

It is quite common for ACPIBacklight.kext (and the DSDT patches discussed here) to not work unless you disable the discrete card on switched dual-GPU configurations. Done in BIOS or via DSDT/SSDT patches.

Brightness Keys

The brightness patch will only enable the slider in SysPrefs->Displays. Keyboard control is a separate issue, as the keyboard driver must generate the special codes used to trigger the OS X native backlight controls.

Your brightness keys (usually one of the Fn+F1...F12 keys) may be handled with PS2 or ACPI. Most newer computers use ACPI for these keys. If your trackpad is Synaptics and you're using my fork VoodooPS2Controller.kext (https://github.com/RehabMan/OS-X-Voodoo-PS2-Controller), you can make either case work.

The first step is to determine if they are handled by PS2 or ACPI. With my driver, you can use 'ioio -s ApplePS2Keyboard LogScanCodes 1' to turn on the key logging to system.log. The ioio binary is available here: https://github.com/RehabMan/OS-X-ioio (please read the README for download locations). After turning on key logging, monitor system.log with Console.app to determine what PS2 codes (if any) are generated when you press your keys). If they generate PS2 codes, you can map them to backlight control by following the wiki: https://github.com/RehabMan/OS-X-Voo...yboard-Mapping.

If your keys do not generate PS2 codes, it is likely they generate ACPI events. In order to intercept the ACPI events, you will need to determine which method(s) are called when the keys are pressed. Usually, media keys generate EC queries. A simple strategy is to use ACPIDebug.kext to instrument all EC query methods, then press the keys while monitoring system.log. When you press the keys, the name of the method will be output, which will allow you to patch that method.

Determining EC query methods:

- install ACPIDebug.kext: https://github.com/RehabMan/OS-X-ACPI-Debug
- add the ACPIDebug repo to MaciASL "Sources" per README
- apply ""Add DSDT Debug Methods"
- apply "Instrument EC Queries"
- reboot
- monitor system.log as you press your brightness keys

After you have determined which methods correspond to the brightness keys, you can patch the methods...

Assuming _Q10 is brightness down, and _Q11 is up.
into method label _Q10 replace_content
// Brightness Down\n
    Notify(\_SB.PCI0.LPCB.PS2K, 0x0205)\n
    Notify(\_SB.PCI0.LPCB.PS2K, 0x0285)\n
into method label _Q11 replace_content
// Brightness Up\n
    Notify(\_SB.PCI0.LPCB.PS2K, 0x0206)\n
    Notify(\_SB.PCI0.LPCB.PS2K, 0x0286)\n
The 0x0205/0x0285 corresponds to PS2 keydown/keyup (e005/e085) for the brightness down key used by Dell laptops. In the default keyboard profile, these correspond to ADB codes 91/90 (brigthness down/up). If your laptop uses a keyboard profile other than the default, you may need to use different codes.

It is possible for both keys (up/down) to generate a call to the same EC query method. This is the case with the Haswell HP Envy, for example. By examining the code it is possible to determine how to disambiguate. As it turns out a variable in the EC is set to indicate the function to be performed when the _Q13 method is invoked. The patch for this case is as follows:

into method label _Q13 replace_content
Store(HKNO, Local0)\n
If (LEqual(Local0,7))\n
// Brightness Down\n
    Notify(\_SB.PCI0.LPCB.PS2K, 0x0205)\n
    Notify(\_SB.PCI0.LPCB.PS2K, 0x0285)\n
If (LEqual(Local0,8))\n
// Brightness Up\n
    Notify(\_SB.PCI0.LPCB.PS2K, 0x0206)\n
    Notify(\_SB.PCI0.LPCB.PS2K, 0x0286)\n
If (LEqual(Local0,4))\n
// Mirror toggle\n
    Notify(\_SB.PCI0.LPCB.PS2K, 0x026e)\n
    Notify(\_SB.PCI0.LPCB.PS2K, 0x02ee)\n
Of course, this code is based on the original code in the DSDT for the HP Haswell Envy. It is likely the details for disambiguation in your DSDT differs. You need to read the original code and make the adjustments to the replacement code as necessary.

Note: This patch also includes support for the "mirror toggle" function, where the standard PS2 code is 0e6e/0eee (make/break).

Note on ELAN (and other) drivers

If you are using another keyboard driver, instead of sending notifications to the PS2 object, you can send them to an object attached to ACPIKeyboard.kext The process is very similar to the process as written above (for ACPI), and is covered well at the ACPIKeyboard github README. See here:https://github.com/RehabMan/OS-X-ACPI-Keyboard

Um comentário: