Skip to content

Instantly share code, notes, and snippets.

@aaronlu
Last active December 21, 2015 13:48
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save aaronlu/6314920 to your computer and use it in GitHub Desktop.
Save aaronlu/6314920 to your computer and use it in GitHub Desktop.
Intel operation region and _BQC
A typical ASL code for the backlight control method _BCM with Intel
graphics card is as follows:
Method (_BCM, 1, NotSerialized)
{
If (BRNC)
{
AINT (One, Arg0)
}
Else
{
^^^LPCB.EC0.STBR ()
}
}
_BCM method takes one param: the target brightness level in the range
of 0-100. The BRNC variable is set if bit2 of _DOS's param is set,
which we do for Win8 systems now, so AINT will be executed.
And the simplified ASL code for AINT on backlight control is:
Method (AINT, 2, Serialized)
{
If (LEqual (Arg0, One))
{
Store (Divide (Multiply (Arg1, 0xFF), 0x64, ), BCLP)
Or (BCLP, 0x80000000, BCLP)
Store (0x02, ASLC)
}
}
The ASLC/BCLP are variables declared in IGD operation region. BCLP is
used to store the target brightness level in the range of 0-255. Due to
the mismatch of the level range in _BCM and BCLP, a convert is done here
for BCLP. The setting of the ASLC variable will trigger interrupt of the
graphics card and the GPU driver will find out this is due to IGD operation
region and will handle the irq accordingly. In backlight case, it will
set backlight level in the GPU driver according to the value of BCLP.
So the setting of backlight is actually done in GPU driver, even though
it is triggered through firmware's interface. A side note is, there are
ASL implementations that would trigger the SMI handler on backlight
control and that would also result in GPU driver's irq handler and GPU
driver will handle backlight setting then.
So this is how to make use of IGD operation region to do the backlight
brightness level control.
There is a problem related to _BQC though on some firmware implementation.
_BQC is a control method provided by firmware to tell which backlight
level the firmware thinks the device is in. The broken implementation is:
Method (_BQC, 0, NotSerialized) // _BQC: Brightness Query Current
{
If (LGreaterEqual (MSOS (), OSW8))
{
And (CBLV, 0x7FFFFFFF, Local0)
Return (Local0)
}
}
CBLV is a variable in IGD operation region, used to represent the
current brightness level in the range of 0-100 and is updated by
GPU driver everytime it is asked to set the backlight level.
Say user wants to set target level to 8, then 8 will be converted to
20(8 * 255 / 100) for BCLP in AINT, then in GPU driver, 20 will be
converted again to 7(20 * 100 / 255) for CBLV, so _BQC will return 7
afterwards though user actually sets 8 in _BCM. But this doesn't happen
for every level set through _BCM, for those values that do not lose
precisions during the conversion back and forth like 20 are not affected.
This needs to be remembered when enhancing the quirk logic of _BQC,
unless we can somehow fix the problem.
Some firmware doesn't have this problem as they simply store the target
level user has requested in _BCM in a variable and then return that
variable in _BQC, but then we probably do not need to evaluate _BQC at
all since we also know what level the device should be in too in ACPI
video module.
PS: The above example ASL code is taken from a ASUS NV5Z system.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment