[Intel-gfx] [PATCH] drm/i915: try not to lose backlight CBLV precision
Jani Nikula
jani.nikula at intel.com
Fri Sep 6 06:53:39 CEST 2013
Daniel, ping?
On Fri, 23 Aug 2013, Jani Nikula <jani.nikula at intel.com> wrote:
> ACPI has _BCM and _BQC methods to set and query the backlight
> brightness, respectively. The ACPI opregion has variables BCLP and CBLV
> to hold the requested and current backlight brightness, respectively.
>
> The BCLP variable has range 0..255 while the others have range
> 0..100. This means the _BCM method has to scale the brightness for BCLP,
> and the gfx driver has to scale the requested value back for CBLV. If
> the _BQC method uses the CBLV variable (apparently some implementations
> do, some don't) for current backlight level reporting, there's room for
> rounding errors.
>
> Use DIV_ROUND_UP for scaling back to CBLV to get back to the same values
> that were passed to _BCM, presuming the _BCM simply uses bclp = (in *
> 255) / 100 for scaling to BCLP.
>
> Reference: https://gist.github.com/aaronlu/6314920
> Reported-by: Aaron Lu <aaron.lu at intel.com>
> Signed-off-by: Jani Nikula <jani.nikula at intel.com>
>
> ---
>
> All of https://gist.github.com/aaronlu/6314920 included here for
> reference:
>
> 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.
> ---
> drivers/gpu/drm/i915/intel_opregion.c | 2 +-
> 1 file changed, 1 insertion(+), 1 deletion(-)
>
> diff --git a/drivers/gpu/drm/i915/intel_opregion.c b/drivers/gpu/drm/i915/intel_opregion.c
> index cfb8fb6..119771f 100644
> --- a/drivers/gpu/drm/i915/intel_opregion.c
> +++ b/drivers/gpu/drm/i915/intel_opregion.c
> @@ -173,7 +173,7 @@ static u32 asle_set_backlight(struct drm_device *dev, u32 bclp)
> return ASLE_BACKLIGHT_FAILED;
>
> intel_panel_set_backlight(dev, bclp, 255);
> - iowrite32((bclp*0x64)/0xff | ASLE_CBLV_VALID, &asle->cblv);
> + iowrite32(DIV_ROUND_UP(bclp * 100, 255) | ASLE_CBLV_VALID, &asle->cblv);
>
> return 0;
> }
> --
> 1.7.9.5
More information about the Intel-gfx
mailing list