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