drivers/platform/x86/apple-gmux.c | 26 ++++++++++++++++++++++++++ 1 file changed, 26 insertions(+)
Make apple-gmux save the current backlight brightness to EFI on shutdown,
so the brightness level is preserved across reboots.
EFI Code inspired from drivers/input/keyboard/applespi.c:1589
(tested on iMac20,1)
Signed-off-by: Atharva Tiwari <atharvatiwarilinuxdev@gmail.com>
---
v2:
- Used correct size for efi_data
drivers/platform/x86/apple-gmux.c | 26 ++++++++++++++++++++++++++
1 file changed, 26 insertions(+)
diff --git a/drivers/platform/x86/apple-gmux.c b/drivers/platform/x86/apple-gmux.c
index 1417e230edbd..20fdebdf3c58 100644
--- a/drivers/platform/x86/apple-gmux.c
+++ b/drivers/platform/x86/apple-gmux.c
@@ -22,6 +22,7 @@
#include <linux/pci.h>
#include <linux/vga_switcheroo.h>
#include <linux/debugfs.h>
+#include <linux/efi.h>
#include <acpi/video.h>
#include <asm/io.h>
@@ -107,6 +108,9 @@ struct apple_gmux_config {
# define MMIO_GMUX_MAX_BRIGHTNESS 0xffff
+#define EFI_BRIGHTNESS_NAME L"backlight-level"
+#define EFI_BRIGHTNESS_GUID EFI_GUID(0x7c436110, 0xab2a, 0x4bbb, 0xa8, 0x80, 0xfe, 0x41, 0x99, 0x5c, 0x9f, 0x82)
+
static u8 gmux_pio_read8(struct apple_gmux_data *gmux_data, int port)
{
return inb(gmux_data->iostart + port);
@@ -1012,6 +1016,27 @@ static void gmux_remove(struct pnp_dev *pnp)
kfree(gmux_data);
}
+static void gmux_shutdown(struct pnp_dev *pnp)
+{
+ struct apple_gmux_data *gmux_data = pnp_get_drvdata(pnp);
+ efi_status_t status = EFI_UNSUPPORTED;
+ u32 efi_attr;
+ u16 efi_data;
+
+ gmux_remove(pnp);
+
+ efi_data = (u16)gmux_get_brightness(gmux_data->bdev);
+ efi_attr = EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS |
+ EFI_VARIABLE_RUNTIME_ACCESS;
+
+ if (efi_rt_services_supported(EFI_RT_SUPPORTED_SET_VARIABLE))
+ status = efi.set_variable(EFI_BRIGHTNESS_NAME, &EFI_BRIGHTNESS_GUID,
+ efi_attr, sizeof(efi_data), &efi_data);
+
+ if (status != EFI_SUCCESS)
+ pr_warn("Unable to save brightness to EFI: 0x%lx\n", status);
+
+}
static const struct pnp_device_id gmux_device_ids[] = {
{GMUX_ACPI_HID, 0},
{"", 0}
@@ -1026,6 +1051,7 @@ static struct pnp_driver gmux_pnp_driver = {
.name = "apple-gmux",
.probe = gmux_probe,
.remove = gmux_remove,
+ .shutdown = gmux_shutdown,
.id_table = gmux_device_ids,
.driver = {
.pm = &gmux_dev_pm_ops,
--
2.43.0
On Tue, Feb 03, 2026 at 10:06:58AM +0000, Atharva Tiwari wrote:
> Make apple-gmux save the current backlight brightness to EFI on shutdown,
> so the brightness level is preserved across reboots.
[...]
> +++ b/drivers/platform/x86/apple-gmux.c
> @@ -1012,6 +1016,27 @@ static void gmux_remove(struct pnp_dev *pnp)
> kfree(gmux_data);
> }
>
> +static void gmux_shutdown(struct pnp_dev *pnp)
> +{
> + struct apple_gmux_data *gmux_data = pnp_get_drvdata(pnp);
> + efi_status_t status = EFI_UNSUPPORTED;
> + u32 efi_attr;
> + u16 efi_data;
> +
> + gmux_remove(pnp);
> +
> + efi_data = (u16)gmux_get_brightness(gmux_data->bdev);
> + efi_attr = EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS |
> + EFI_VARIABLE_RUNTIME_ACCESS;
> +
> + if (efi_rt_services_supported(EFI_RT_SUPPORTED_SET_VARIABLE))
> + status = efi.set_variable(EFI_BRIGHTNESS_NAME, &EFI_BRIGHTNESS_GUID,
> + efi_attr, sizeof(efi_data), &efi_data);
> +
> + if (status != EFI_SUCCESS)
> + pr_warn("Unable to save brightness to EFI: 0x%lx\n", status);
> +
> +}
Hm, isn't efivar_set_variable() the proper API to use?
Please cc linux-efi@vger.kernel.org on future submissions so that the
EFI maintainer gets a chance to look over your patch and confirm it's
using the right API.
Older Intel Macs with a gmux can be booted in CSM mode (bypassing EFI).
I'm wondering what happens on those with the above change?
Do they only get the warning or do they crash?
The warning is probably uncalled for on CSM-booted Macs.
CONFIG_EFI may not even be enabled, I suspect that apple-gmux.c does not
compile in that case with the above change.
On my MacBookPro9,1 (which does have a gmux), the backlight-level variable
has 6 bytes which currently contain (hexdump): 07 00 00 80 35 00
I guess this is actually a struct of a 32-bit and a 16-bit value
or alternatively three 16-bit values. Yet you're only writing a
single 16-bit value to the variable. How many bytes does the variable
have on your iMac and what are their contents? I'm worried that
your change may not be compatible with all Macs which have this variable.
Instead of setting this variable only on shutdown, it may be better to
set it whenever brightness is changed. That way, if the system isn't
properly shut down (runs out of battery or crashes), brightness is still
saved. I'd introduce a work_struct which gets submitted with
queue_delayed_work() after, say, 300 msec whenever brightness is changed.
That way, multiple brightness changes are coalesced into a single
variable write.
Finally, there are Macs which don't have a gmux but which do have a
backlight. They usually control brightness through i915 I think.
It would be nice to save brightness to the EFI variable on those as well.
Could probably be achieved by amending the backlight subsystem to
trigger the variable write if x86_apple_machine is true.
The variable write would then live in the backlight subsystem as an
x86-specific quirk, instead of in the gmux driver. Perhaps the backlight
subsystem could be amended with a blocking notifier chain which is invoked
on brightness changes and the arch/x86 subsystem could then install a
notifier_block to trigger the variable write on x86_apple_machine systems
if EFI is enabled and used as boot mode.
Thanks,
Lukas
> Older Intel Macs with a gmux can be booted in CSM mode (bypassing EFI). > I'm wondering what happens on those with the above change? > Do they only get the warning or do they crash? > The warning is probably uncalled for on CSM-booted Macs. I guess CSM-booted Macs would just trigger a warning when EFI isn’t enabled, as efi_rt_services_supported(EFI_RT_SUPPORTED_SET_VARIABLE) will return 0. > On my MacBookPro9,1 (which does have a gmux), the backlight-level variable > has 6 bytes which currently contain (hexdump): 07 00 00 80 35 00 > I guess this is actually a struct of a 32-bit and a 16-bit value > or alternatively three 16-bit values. Yet you're only writing a > single 16-bit value to the variable. How many bytes does the variable > have on your iMac and what are their contents? I'm worried that > your change may not be compatible with all Macs which have this variable. This function actually writes 6 bytes, which is u32 efi_attr (first 32-bits) and u16 efi_data (last 16-bits), but im confused about the fact, that the hexdumps show that ur attr are different. the attr should be 07 00 00 00 but its 07 00 00 80, i think we should retrieve the attr in the probe function and use that for writing. to fix this problem > Finally, there are Macs which don't have a gmux but which do have a > backlight. They usually control brightness through i915 I think. > It would be nice to save brightness to the EFI variable on those as well. There should be something for Amdgpus aswell for mac pro, but i cant test i915 nor amdgpu, as i dont have these devices. so i think we should currently drop this idea.
On Wed, Feb 04, 2026 at 06:28:15PM +0000, Atharva Tiwari wrote: > > Finally, there are Macs which don't have a gmux but which do have a > > backlight. They usually control brightness through i915 I think. > > It would be nice to save brightness to the EFI variable on those as well. > > There should be something for Amdgpus aswell for mac pro, but i cant > test i915 nor amdgpu, as i dont have these devices. so i think we should > currently drop this idea. The ask is not that you should implement something you can't test. The ask is that you should implement it in a way that is extensible to be used by i915 and other drivers once someone comes along who can test it. I'd suggest adding a new drivers/firmware/efi/apple-bl.c which contains all the logic to update the variable using a delayed work item. It could provide an API call which apple-gmux invokes. Then i915 and amdgpu can be retrofitted later on to invoke the API call as well. Assuming that the new .c file is gated by a new CONFIG_EFI_APPLE_BL symbol, CONFIG_APPLE_GMUX should "select EFI_APPLE_BL if EFI". I think there are other EFI variables to store backlight brightness of the keyboard and so on, so if you anticipate that you or someone else may later on support those as well, then a more generic solution would be a drivers/firmware/efi/apple-vars.c file instead of apple-bl.c. > This function actually writes 6 bytes, which is u32 efi_attr (first 32-bits) > and u16 efi_data (last 16-bits), but im confused about the fact, that the > hexdumps show that ur attr are different. the attr should be 07 00 00 00 > but its 07 00 00 80, i think we should retrieve the attr in the probe > function and use that for writing. That could just be done in an initcall if you pursue the architecture outlined above. Thanks, Lukas
© 2016 - 2026 Red Hat, Inc.