NetBSD-Bugs archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

Re: kern/43017



The following reply was made to PR kern/43017; it has been noted by GNATS.

From: =?UTF-8?B?R3LDqWdvaXJlIFN1dHJl?= <gregoire.sutre%gmail.com@localhost>
To: gnats-bugs%NetBSD.org@localhost
Cc: 
Subject: Re: kern/43017
Date: Fri, 24 Jun 2011 20:50:33 +0200

 The acpidump suggest that the BIOS of this laptop follows the Intel IGD
 OpRegion specification [1].  My understanding of this specification is
 that the BIOS relies on the graphics driver to implement various ACPI
 video extensions, and, among them, brightness management.
 
 [1] http://intellinuxgraphics.org/ACPI_IGD_OpRegion_%20Spec.pdf
 
 
 The intel drm driver in Linux implements the graphics-driver part of
 this specification.  In the hope that it helps resolving this issue in
 the future, I post here some notes regarding the implementation of the
 specification [1] by this laptop's BIOS and the Linux (2.6.38) intel drm
 driver -- at least my understanding of it.
 
 
 Initialization
 --------------
 
 Section 2.3 of [1] specifies that the firmware allocates and initializes
 the IGD opregion, which is a system memory region, and writes its base
 address into the ASLS register of graphics PCI device (at address 0xFC
 in the device's PCI configuration space).
 
 The file of interest in Linux is drivers/gpu/drm/i915/intel_opregion.c.
 The drm_i915_private structure (the softc) has a field opregion of type
 struct intel_opregion.  This stuct holds pointers to the physical
 addresses of the opregion header, the 3 mailboxes, and the video bios
 table.  These pointers are initialized in intel_opregion_setup(), by
 reading the opregion physical address in the ASLS register (address 0xFC
 in the device's PCI configuration space).  The intel_opregion_setup()
 function is called in i915_driver_load().  The latter also calls,
 afterwards, the function intel_opregion_init(), which performs various
 initializations of/from the opregion:
 
 - enumerate the outputs (ACPI children of the graphics device) and write
    them in the DIDL field of the opregion (to pass them to the firmware).
    This list is used by the firmware to package a list of IDs returned by
    the ACPI _DOD method.
 
 - notify the firmware that the OS is ready to handle ACPI video
    notifications, by setting the DRDY field of the opregion to 1.
 
 - register a dummy notify handler for the opregion.
 
 - enable ASLE interrupts if this is a MOBILE chipset (and the opregion
    has an ASLE mailbox).
 
 - set flags in the register TCHE (of the opregion) to inform the
    firmware that backlight control and other things are supported by the
    driver.
 
 Finally, i915_driver_load() calls acpi_video_register(), as the later was
 deferred (in acpi_video_init) until the opregion is initialized.
 
 
 Brightness Management
 ---------------------
 
 The GFX0.DD02._BQC ACPI method (get the current brightness level) simply
 returns the value of the internal variable BRIG.
 
 The GFX0.DD02._BCM ACPI method (set the brightness level) is more
 involved.  It first stores its argument in the internal variable BRIG,
 and, after a few steps, calls SBRV(), and then calls an SSMI method and
 signals an event.  The call to SBRV does the following:
 
        if TCHE & 0x02 == 0 then
            do noting
        else
            construct brightness data from BRID (which came from BRIG)
            BCLP <- this brightness data | 0x80000000
            ASLC <- 2
 
 TCHE, BCLP, and ASLC are all part of the opregion.  The 2nd bit of TCHE
 is set if backlight control is supported by the graphics driver.  The
 2nd bit of ASLC tells the driver that the firmware wants it to set the
 brightness level, to the value given in the BCLP.  Values for BCLP range
 from 0 to 0xFF (max brightness).
 
 Then, for some reason, possibly because of the SSMI method call, an
 interrupt is triggered.  The irq handler of the Linux i915 driver,
 i915_driver_irq_handler() or ironlake_irq_handler(), is called, detects
 an ASLE interrupt, and calls intel_opregion_asle/gse_intr().  The latter
 processes each request in ASLC, and returns the corresponding status bit
 field.  In the above scenario, ASLC = 2, asle_set_backlight() is called,
 validates the level (BLCP), and calls intel_panel_set_backlight(), and
 sets the CBLV field of the opregion with the current brightness level.
 
 The function intel_panel_set_backlight() writes into specific registers
 to set the brightness level (BLC_PWM_CTL, or BLC_PWM_CPU_CTL for
 Ironlake).
 


Home | Main Index | Thread Index | Old Index