/* SPDX-License-Identifier: GPL-2.0-only */ /* This file is part of the coreboot project. */ /* * Pseudo device that contains methods to modify Opregion * "Mailbox 3 BIOS to Driver Notification" * The BIOS to Driver Notification mailbox is intended to support * BIOS to Driver event notification or data storage for BIOS to * Driver data synchronization purpose. */ Device (BOX3) { Name (_ADR, 0) OperationRegion (OPRG, SystemMemory, ASLS, 0x2000) Field (OPRG, DWordAcc, NoLock, Preserve) { // OpRegion Header Offset (0x58), MBOX, 32, // Mailbox 3 Offset (0x300), ARDY, 1, /* Offset 0 Driver readiness */ , 31, ASLC, 32, /* Offset 4 ASLE interrupt command / status */ TCHE, 32, /* Offset 8 Technology enabled indicator */ ALSI, 32, /* Offset 12 Current ALS illuminance reading */ BCLP, 32, /* Offset 16 Backlight britness to set */ PFIT, 32, /* Offset 20 Panel fitting Request */ CBLV, 32, /* Offset 24 Brightness Current State */ } /* * Request back-light brightness change through mailbox 3 * * @param Arg0 The brightness level to set in percent * @Return Zero on success, Ones on failure * Errors: * ASLS is zero * * Mailbox 3 support not advertised * * Driver not loaded or not ready * * Driver reported an error during ASLE IRQ */ Method (XBCM, 1, Serialized) { If (LEqual(ASLS, Zero)) { Return (Ones) } If (LEqual(And(MBOX, 0x4), Zero)) { Return (Ones) } /* Always keep BCLP up to date, even if driver is not ready. It requires a full 8-bit brightness value. 255 = 100% */ Store (Divide (Multiply (Arg0, 255), 100), Local1) If (LGreater(Local1, 255)) { Store (255, Local1) } /* also set valid bit */ Store (Or (Local1, 0x80000000), BCLP) If (LEqual(ARDY, Zero)) { Return (Ones) } /* Request back-light change */ Store (0x2, ASLC) /* Trigger IRQ */ Store (0x1, ASLE) Store (0x20, Local0) While (LGreater(Local0, Zero)) { Sleep (1) If (LEqual (And (ASLC, 0x2), 0)) { /* Request has been processed, check status: */ And (ShiftRight (ASLC, 12), 0x3, Local1) If (LEqual (Local1, 0)) { Return (Zero) } Else { Return (Ones) } } Decrement (Local0) } Return (Ones) } } /* * Pseudo device that contains methods to operate on GTT memory */ Device (LEGA) { Name (_ADR, 0) /* Divide round closest */ Method (DRCL, 2) { Return (Divide (Add (Arg0, Divide (Arg1, 2)), Arg1)) } Method (XBCM, 1, NotSerialized) { Store (DRCL (Multiply (Arg0, BCLM), 100), BCLV) } /* Find value closest to BCLV in BRIG (which must be ordered) */ Method (XBQC, 0, NotSerialized) { /* Prevent DivideByZero if backlight control isn't enabled */ If (BCLM == 0) { Return (Zero) } /* Local0: current percentage */ Store (DRCL (Multiply (BCLV, 100), BCLM), Local0) /* Local1: loop index (selectable values start at 2 in BRIG) */ Store (2, Local1) While (LLess (Local1, Subtract (SizeOf (BRIG), 1))) { /* Local[23]: adjacent values in BRIG */ Store (DeRefOf (Index (BRIG, Local1)), Local2) Store (DeRefOf (Index (BRIG, Add (Local1, 1))), Local3) If (LLess (Local0, Local3)) { If (LOr (LLess (Local0, Local2), LLess (Subtract (Local0, Local2), Subtract (Local3, Local0)))) { Return (Local2) } Else { Return (Local3) } } Increment (Local1) } /* Didn't find greater/equal value: use the last */ Return (Local3) } } Method (XBCM, 1, NotSerialized) { If (LEqual(^BOX3.XBCM (Arg0), Ones)) { ^LEGA.XBCM (Arg0) } } Method (XBQC, 0, NotSerialized) { /* * Always query the hardware directly. Not all OS drivers * keep CBLV up to date (one is Linux' i915). Some years * after that is fixed we can probably use CBLV? */ Return (^LEGA.XBQC ()) }