[ltp] Re: Thinkpad keyboard backlight ACPI interface

Pali Rohár linux-thinkpad@linux-thinkpad.org
Tue, 28 Jul 2015 12:43:31 +0200


On Monday 27 July 2015 23:55:49 Pali Rohár wrote:
> Hello,
> 
> I'm trying to control backlight of Thinkpad X1 Carbon via software ACPI 
> calls. With doing some tests I come up to conclusion that ACPI method 
> MLCS from LEN0068 ACPI device controls level of keyboard backlight.
> 
> With this shell snippet and acpi_call.ko kernel module I can control 
> keyboard backlight.
> 
>  level=2 # 0, 1 or 2
>  sudo modprobe acpi_call
>  path=`cat /sys/bus/acpi/devices/LEN0068:00/path`
>  sudo sh -c "echo $path.MLCS $level > /proc/acpi/call"
> 
> Here is relevant AML code from DSDT table for it:
> 
>  Method (MLCG, 1, NotSerialized)
>  {
>      Store (\KBLS (0x00, 0x00), Local0)
>      Return (Local0)
>  }
>  
>  Method (MLCS, 1, NotSerialized)
>  {
>      Store (\KBLS (0x01, Arg0), Local0)
>      If (LNot (And (Local0, 0x80000000)))
>      {
>          If (And (Arg0, 0x00010000))
>          {
>              \_SB.PCI0.LPC.EC.HKEY.MHKQ (0x6001)
>          }
>          Else
>          {
>              If (\_SB.PCI0.LPC.EC.HKEY.MHKK (0x00020000))
>              {
>                  \_SB.PCI0.LPC.EC.HKEY.MHKQ (0x1012)
>              }
>          }
>      }
>  
>      Return (Local0)
>  }
> 
> I would like to ask you: It is safe to call MLCS function? Do you 
> somebody have any documentation for Thinkpad machines which describe 
> this ACPI functionality? Is there any way to detect (via ACPI call) if 
> some Thinkpad model has backlight keyboard?
> 
> I would like to write kernel patch for thinkpad_acpi.c to support 
> keyboard backlight (like other modules in drivers/platform/x86/ tree), 
> but last missing information is how to detect current level of 
> brightness and check if backlight is supported...
> 
> Can you somebody help me?
> 

If somebody is interested, here is KBLS part of DSDT code:

 OperationRegion (MNVS, SystemMemory, 0xCCD7D018, 0x1000)

...

 OperationRegion (SMI0, SystemIO, 0xB2, 0x01)
 Field (SMI0, ByteAcc, NoLock, Preserve)
 {
     APMC,   8
 }
 
 Field (MNVS, AnyAcc, NoLock, Preserve)
 {
             Offset (0xFC0), 
     CMD,    8, 
     ERR,    32, 
     PAR0,   32, 
     PAR1,   32, 
     PAR2,   32, 
     PAR3,   32
 }
 
 Mutex (MSMI, 0x07)
 Method (SMI, 5, NotSerialized)
 {
     Acquire (MSMI, 0xFFFF)
     Store (Arg0, CMD)
     Store (0x01, ERR)
     Store (Arg1, PAR0)
     Store (Arg2, PAR1)
     Store (Arg3, PAR2)
     Store (Arg4, PAR3)
     Store (0xF5, APMC)
     While (LEqual (ERR, 0x01))
     {
         Sleep (0x01)
         Store (0xF5, APMC)
     }
 
     Store (PAR0, Local0)
     Release (MSMI)
     Return (Local0)
 }

...

 Method (KBLS, 2, NotSerialized)
 {
     Return (SMI (0x14, 0x09, Arg0, Arg1, 0x00))
 }


-- 
Pali Rohár
pali.rohar@gmail.com