Acer E1 and V3 ACPI
As I have written in the previous post, to get brightness control working on Acer E1-571 I had to add acpi_osi=Linux to kernel boot parameters. It makes kernel introduce itself to the BIOS as a Linux-based OS. It may come as a surprise to you but by default Linux tries to imitate Windows in every aspect of OS – firmware interaction, which includes calling itself Windows xxxx when asked about OS name. I guess there are ACPI implementations that won’t work or will disable some of the features when they see something other than Windows running. Because the disguising technique is unlikely to go away in foreseeable future we will have to continue including acpi_osi=Linux every time we want to install Linux. Because I don’t like that I set off in an attempt to make Linux work without adding the magic parameter i.e. out-of-box on any Acer E1/V3 laptop.
Before diving into my specific problem let me first explain what ACPI is about. It’s about standardizing hardware description and access. There is a universal problem of discoverability and auto-configuration of hardware in computer systems. More advanced buses like USB or PCI (Express) make it possible for the operating system to ask the controller: What devices are connected to the bus, what are vendors and product ids of those devices and what type of devices are they (storage, network etc.) Unfortunately many simple devices either connect to simple buses or are not connected to any bus at all. ACPI defines the language in which firmware can describe the hardware that is available on the system. This description is then handed by the BIOS to the operating system.
If you look into ACPI specification you will see a multitude of method names starting with an underscore like _BST. All those method names are standardized by ACPI and the specification states what they do and how to invoke them. Now, when your vendor wants to give you control over the fan speed, he creates a device of fan class (always named PNP0C0B) inside the ACPI description of hardware and provides a few standard methods to it. One thing which confused me at the beginning is that methods are executed by the OS. There is a special ACPI language called ASL, which is interpreted by the OS. When your system loads up it will see the PNP0C0B device, recognize it as a fan and call (i.e. execute interpreter for) appropriate method to get current speed etc. The problem is that not all device interfaces are standardized. Most notably hotkeys and backlight control are not (I heard that they are in new versions of ACPI, but vendors still rely on old ones – this was supposed to change with Windows 8…)
If your device’s interface is not standardized you won’t be able to find out how to operate it in the ACPI standard and because every vendor likes to do things differently, you’ll need a separate driver for all the vendors. That’s why we have vendor specific ACPI modules like “ACPI for Lenovo” or “ACPI for Asus”. The “real”/standardized ACPI is handled by core OS and we rarely have to worry about it. What is handled by vendor-specific ACPI modules and causes a lot of headaches to Linux users is only the additional non-standardized functionality.
Before I begun I read these two (one, two) articles by Matthew Garrett and Corentin Chary and investigated how does ACPI – OS interaction look a little bit. I also watched this very helpful talk by Matthew.
Picture below shows all the elements that are important to us.
As mentioned above ACPI provides OS with descriptions of what hardware is available and what to do to get specific things done by this hardware. Methods usually involve things like hardware register access or communication with an embedded controller (motherboard microcontroller). For instance to set fan speed ACPI method may write speed in RPM multiplied by 4 to physical address 0xFF00005C… (BTW you obviously can write to the registers directly once you know their locations, without invoking ACPI interpreter, just as you would do in a standalone driver, but register location can change from a one laptop model to another so it’s better to use ACPI as a layer of indirection.) From this description it should be clear that writing ACPI drivers for not-standardized functions is pretty straightforward. You see register names, you see what ACPI interpreter will do with the values passed to the methods, so you can figure out what a method is for. Then it’s just a matter of finding right method to call!
There are two problems though – one is called Microsoft and the other Intel. Microsoft has a closed “standard” for describing driver interfaces called WMI. WMI information can be embedded inside ACPI table and there is little or no information in the public on how to interpret it. If your device’s interface is described in WMI Windows will understand how to operate it, but you won’t. Intel contributed to the problem by introducing (back in the 80s, I think) a special System Management Mode to their processors. In this mode CPU stops executing user-visible code and jumps to a hidden firmware which can do whatever it wants to. Problem here is – again – visibility, if ACPI method triggers jump to SMM firmware, you won’t be able to see what the code does.
Unfortunately firmware in new Acer laptops uses both WMI and SMM making it practically impossible to figure out how to operate the laptop without hardcore methods like trying all possible combinations or executing Windows in virtual environment and observing it’s interactions with the hardware. I’m not saying that I’ll not do one of those in the future but for now I give up… the only thing that doesn’t work with acpi_osi=Linux are the Euro and Dollar keys near arrows and being a simple Linux guy I don’t use those two a lot 😉
From what I gathered about brightness: _BCM and _BCQ methods which are supposed to modify and query brightness value do nothing but write passed value to a Embedded Controller register. We can only suspect that EC is then supposed to do its magic and eventually write that value to a graphics card register, but this never happens. When OS is set to Linux, instead of relying on EC, ACPI method AINT is called and it sets brightness in graphics register directly… maybe we should enable EC or set its operation mode first? Yes, and probably do that with a WMI method, but all they do is call SMM! Some older Acer laptops had WMI methods coded in ACPI (without SMM involvement), I hoped that methods and parameters will be the same, but unfortunately the are not.