summaryrefslogtreecommitdiffstats
path: root/src/drivers/intel/gma/acpi/configure_brightness_levels.asl
blob: 0ab93d803a24268296306f2a06499665596767a3 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
/* SPDX-License-Identifier: GPL-2.0-only */

	/*
	 * 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 ())
	}