* [PATCH 00/13] Fixes for apple-gmux and runtime support
@ 2026-10-25 3:59 Atharva Tiwari
2026-10-25 3:59 ` [PATCH 01/13] platform/apple-gmux: Fix power for MMIO systems Atharva Tiwari
` (12 more replies)
0 siblings, 13 replies; 14+ messages in thread
From: Atharva Tiwari @ 2026-10-25 3:59 UTC (permalink / raw)
Cc: Atharva Tiwari, Bjorn Helgaas, Thomas Gleixner, Ingo Molnar,
Borislav Petkov, Dave Hansen,
maintainer:X86 ARCHITECTURE (32-BIT AND 64-BIT),
H. Peter Anvin, Alex Deucher, Christian König, David Airlie,
Simona Vetter, Harry Wentland, Leo Li, Rodrigo Siqueira,
Kenneth Feng, Hans de Goede, Ilpo Järvinen, Andre Eikmeyer,
open list:PCI SUBSYSTEM,
open list:X86 ARCHITECTURE (32-BIT AND 64-BIT),
open list:RADEON and AMDGPU DRM DRIVERS, open list:DRM DRIVERS,
open list:X86 PLATFORM DRIVERS
This series fixes apple-gmux on T2 Macs (2018-2020):
- Fix interrupt handling
- Automatically turn on dGPU when a external monitor connects.
- Fix base register read/write
- Fix power handling
- Improve documentation
- New module parameter to toggle boot GPU.
It also adds vga_switcheroo runtime power management for T2 Macs, built
on gmux power control, so the dGPU is powered off automatically when
idle and users no longer need to toggle it manually.
Andre Eikmeyer (6):
platform/apple-gmux: Write switch state to EFI on MMIO devices
drm/amdgpu: Add Apple GMUX runtime PM support
drm/amdgpu: Catch register access while GMUX keeps the GPU off
drm/amd/display: Refuse DP AUX while GMUX keeps the GPU off
drm/amdgpu: Skip AC/DC notification while the GPU is runtime suspended
drm/amd/display: Skip panel power savings on eDP links without a panel
Atharva Tiwari (7):
platform/apple-gmux: Fix power for MMIO systems
PCI: Disable pcie port and access on D3 on specific amd devices
platform/apple-gmux: Fix MMIO interface
platform/apple-gmux: Fix Interrupts for MMIO systems
platform/apple-gmux: Add parameter to configure boot gpu
platform/apple-gmux: Add check to detect FSS
platform/apple-gmux: Add documentation about iMacs
arch/x86/pci/fixup.c | 30 ++
drivers/gpu/drm/amd/amdgpu/amdgpu.h | 4 +
drivers/gpu/drm/amd/amdgpu/amdgpu_device.c | 60 ++-
drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c | 45 ++-
.../gpu/drm/amd/amdgpu/amdgpu_reg_access.c | 24 ++
.../gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 14 +
.../display/amdgpu_dm/amdgpu_dm_backlight.c | 3 +
.../display/amdgpu_dm/amdgpu_dm_mst_types.c | 19 +-
drivers/gpu/drm/amd/pm/amdgpu_dpm.c | 19 +-
drivers/gpu/drm/amd/pm/inc/amdgpu_dpm.h | 1 +
drivers/pci/access.c | 18 +
drivers/pci/pcie/portdrv.c | 2 +-
drivers/platform/x86/Kconfig | 1 +
drivers/platform/x86/apple-gmux.c | 377 ++++++++++++++++--
include/linux/apple-gmux.h | 1 +
include/linux/pci.h | 7 +
16 files changed, 554 insertions(+), 71 deletions(-)
--
2.55.0
^ permalink raw reply [flat|nested] 14+ messages in thread
* [PATCH 01/13] platform/apple-gmux: Fix power for MMIO systems
2026-10-25 3:59 [PATCH 00/13] Fixes for apple-gmux and runtime support Atharva Tiwari
@ 2026-10-25 3:59 ` Atharva Tiwari
2026-10-25 3:59 ` [PATCH 02/13] PCI: Disable pcie port and access on D3 on specific amd devices Atharva Tiwari
` (11 subsequent siblings)
12 siblings, 0 replies; 14+ messages in thread
From: Atharva Tiwari @ 2026-10-25 3:59 UTC (permalink / raw)
Cc: Atharva Tiwari, Andre Eikmeyer, Bjorn Helgaas, Thomas Gleixner,
Ingo Molnar, Borislav Petkov, Dave Hansen,
maintainer:X86 ARCHITECTURE (32-BIT AND 64-BIT),
H. Peter Anvin, Alex Deucher, Christian König, David Airlie,
Simona Vetter, Harry Wentland, Leo Li, Rodrigo Siqueira,
Kenneth Feng, Hans de Goede, Ilpo Järvinen,
open list:PCI SUBSYSTEM,
open list:X86 ARCHITECTURE (32-BIT AND 64-BIT),
open list:RADEON and AMDGPU DRM DRIVERS, open list:DRM DRIVERS,
open list:X86 PLATFORM DRIVERS
Currently The dGPU on MMIO Systems, dies when we write the gmux values
to turn off the gpu.
On most systems we can just write PWG1 (link-training method) and the
dGPU comes up, then we write a MMIO variable, and run PWG3
(link-retraing method), to stablize the dGPU.
But on 16,1 and 16,4 this dosent work, instead we have to use PWRD
method, which turns off the entire bridge, and completely messes the
pci config, so we can't use pci to traverse through it. we save the
entire bridge using ACPI addresses then we run PWRD(1) to turn off
the bridge, then we write gmux states, and resume we do the vice
versa, but here we dont need to retrain the link and write the
MMIO variable.
Co-developed-by: Andre Eikmeyer <dev@deq.rocks>
Signed-off-by: Andre Eikmeyer <dev@deq.rocks>
Signed-off-by: Atharva Tiwari <atharvatiwarilinuxdev@gmail.com>
---
drivers/platform/x86/apple-gmux.c | 177 ++++++++++++++++++++++++++++--
1 file changed, 170 insertions(+), 7 deletions(-)
diff --git a/drivers/platform/x86/apple-gmux.c b/drivers/platform/x86/apple-gmux.c
index 9c728ac4e..4e8786a5e 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/dmi.h>
#include <acpi/video.h>
#include <asm/io.h>
@@ -65,6 +66,11 @@ struct apple_gmux_data {
struct backlight_device *bdev;
+ /* power handling data */
+ struct pci_dev *discrete_pdev;
+ bool uses_pwrd;
+ enum apple_gmux_type type;
+
/* switcheroo data */
acpi_handle dhandle;
int gpe;
@@ -502,23 +508,171 @@ static int gmux_switch_ddc(enum vga_switcheroo_client_id id)
/**
* DOC: Power control
*
- * gmux is able to cut power to the discrete GPU. It automatically takes care
+ * gmux is able to cut power to the discrete GPU. On most
+ * Systems the gmux automatically takes care
* of the correct sequence to tear down and bring up the power rails for
* core voltage, VRAM and PCIe.
+ *
+ * But on most MMIO Systems, we have to PCIE link-train the discrete GPU after
+ * power on, we can do that using PWG1 and then to stablize we write to
+ * 0x8C340 and then link-train the PCIE link again (this time using PWG3).
+ *
+ * But on MacBookPro16,1 and MacBookPro16,4, the PWG1 method does not work
+ * instead we have to use PWRD method, which turns off the entire bridge and
+ * messes up the PCI config, so we can't use pci_upstream_bridge to traverse
+ * through the bridge, so we use ACPI addresses to save/restore bridges.
+ *
+ * NOTE: Communication to these bridges (not the dGPU/HDA) in any form
+ * when the bridge is off, will result in CPU CATERR.
*/
+static int gmux_save_restore_pci(acpi_handle parent_handle, const char *name,
+ bool save, acpi_handle *out_handle)
+{
+ acpi_status status;
+ acpi_handle handle;
+ struct acpi_device *adev;
+ struct device *dev;
+ struct pci_dev *pdev;
+
+ if (name) {
+ status = acpi_get_handle(parent_handle, name, &handle);
+ if (ACPI_FAILURE(status))
+ return -EIO;
+
+ if (out_handle)
+ *out_handle = handle;
+ } else
+ handle = parent_handle;
+
+ adev = acpi_fetch_acpi_dev(handle);
+ if (!adev)
+ return -EIO;
+
+ dev = acpi_get_first_physical_node(adev);
+ if (!dev || !dev_is_pci(dev))
+ return -EIO;
+
+ pdev = to_pci_dev(dev);
+
+ if (save) {
+ pci_save_state(pdev);
+ pdev->current_state = PCI_D3cold;
+ } else {
+ pdev->current_state = PCI_D0;
+ pci_restore_state(pdev);
+ }
+ return 0;
+}
+
static int gmux_set_discrete_state(struct apple_gmux_data *gmux_data,
enum vga_switcheroo_state state)
{
reinit_completion(&gmux_data->powerchange_done);
+ acpi_handle discrete_handle = ACPI_HANDLE(&gmux_data->discrete_pdev->dev);
+ acpi_status status;
+ unsigned long long result;
+
+ if (!discrete_handle)
+ return -ENODEV;
if (state == VGA_SWITCHEROO_ON) {
- gmux_write8(gmux_data, GMUX_PORT_DISCRETE_POWER, 1);
- gmux_write8(gmux_data, GMUX_PORT_DISCRETE_POWER, 3);
+ if (gmux_data->type == APPLE_GMUX_TYPE_MMIO) {
+ u16 vendor;
+ int i;
+
+ gmux_write8(gmux_data, GMUX_PORT_DISCRETE_POWER, 2);
+ msleep(100);
+ gmux_write8(gmux_data, GMUX_PORT_DISCRETE_POWER, 3);
+
+ if (gmux_data->uses_pwrd) {
+ acpi_handle handle;
+
+ status = acpi_execute_simple_method(discrete_handle, "PWRD", 0);
+ if (ACPI_FAILURE(status))
+ return -EIO;
+
+ if (gmux_save_restore_pci(NULL, "\\_SB_.PCI0.PEG0", 0, &handle))
+ return -EIO;
+
+ if (gmux_save_restore_pci(handle, "EGP0", 0, &handle))
+ return -EIO;
+
+ if (gmux_save_restore_pci(handle, "EGP1", 0, &handle))
+ return -EIO;
+
+ if (gmux_save_restore_pci(handle, "GFX0", 0, NULL))
+ return -EIO;
+
+ if (gmux_save_restore_pci(handle, "HDAU", 0, NULL))
+ return -EIO;
+ } else {
+ status = acpi_evaluate_integer(discrete_handle,
+ "PWG1", NULL, &result);
+ if (ACPI_FAILURE(status) || result)
+ return -EIO;
+ }
+
+ for (i = 0; i < 1000; i++) {
+ pci_read_config_word(gmux_data->discrete_pdev,
+ PCI_VENDOR_ID, &vendor);
+ if (vendor != 0xffff)
+ break;
+ msleep(1);
+ }
+ if (vendor == 0xffff)
+ return -ETIMEDOUT;
+
+ if (!gmux_data->uses_pwrd) {
+ void __iomem *bar = pci_iomap(gmux_data->discrete_pdev, 0, 0);
+
+ if (!bar)
+ return -ENOMEM;
+
+ iowrite32(ioread32(bar + 0x8c340) & 0x3fffffff, bar + 0x8c340);
+ pci_iounmap(gmux_data->discrete_pdev, bar);
+
+ status = acpi_evaluate_integer(discrete_handle,
+ "PWG3", NULL, &result);
+ if (ACPI_FAILURE(status) || result)
+ return -EIO;
+ }
+ } else {
+ gmux_write8(gmux_data, GMUX_PORT_DISCRETE_POWER, 1);
+ gmux_write8(gmux_data, GMUX_PORT_DISCRETE_POWER, 3);
+ }
pr_debug("Discrete card powered up\n");
} else {
- gmux_write8(gmux_data, GMUX_PORT_DISCRETE_POWER, 1);
- gmux_write8(gmux_data, GMUX_PORT_DISCRETE_POWER, 0);
+ if (gmux_data->type == APPLE_GMUX_TYPE_MMIO) {
+ if (gmux_data->uses_pwrd) {
+ acpi_handle parent_handle = discrete_handle;
+ bool saved_hda = false;
+
+ while (ACPI_SUCCESS(acpi_get_parent(parent_handle,
+ &parent_handle))) {
+ if (!saved_hda) {
+ if (!gmux_save_restore_pci(parent_handle,
+ "HDAU", true, NULL)) {
+ saved_hda = true;
+ pci_save_state(gmux_data->discrete_pdev);
+ gmux_data->discrete_pdev->current_state =
+ PCI_D3cold;
+ }
+ }
+ if (gmux_save_restore_pci(parent_handle, NULL, true, NULL))
+ break;
+ }
+ status = acpi_execute_simple_method(discrete_handle, "PWRD", 1);
+ if (ACPI_FAILURE(status))
+ return -EIO;
+ }
+ gmux_write8(gmux_data, GMUX_PORT_DISCRETE_POWER, 1);
+ mdelay(10);
+ gmux_write8(gmux_data, GMUX_PORT_DISCRETE_POWER, 0);
+ } else {
+ gmux_write8(gmux_data, GMUX_PORT_DISCRETE_POWER, 1);
+ gmux_write8(gmux_data, GMUX_PORT_DISCRETE_POWER, 0);
+ }
pr_debug("Discrete card powered down\n");
}
@@ -552,10 +706,15 @@ static enum vga_switcheroo_client_id gmux_get_client_id(struct pci_dev *pdev)
else if (pdev->vendor == PCI_VENDOR_ID_NVIDIA &&
pdev->device == 0x0863)
return VGA_SWITCHEROO_IGD;
- else
+ else {
+ if (apple_gmux_data->discrete_pdev != pdev) {
+ pci_dev_put(apple_gmux_data->discrete_pdev);
+ apple_gmux_data->discrete_pdev = pci_dev_get(pdev);
+ }
return VGA_SWITCHEROO_DIS;
-}
+ }
+}
static const struct vga_switcheroo_handler gmux_handler_no_ddc = {
.switchto = gmux_switchto,
.power_state = gmux_set_power_state,
@@ -803,6 +962,9 @@ static int gmux_probe(struct pnp_dev *pnp, const struct pnp_device_id *id)
if (!gmux_data)
return -ENOMEM;
pnp_set_drvdata(pnp, gmux_data);
+ gmux_data->type = type;
+ gmux_data->uses_pwrd = (dmi_match(DMI_PRODUCT_NAME, "MacBookPro16,1") ||
+ dmi_match(DMI_PRODUCT_NAME, "MacBookPro16,4"));
switch (type) {
case APPLE_GMUX_TYPE_MMIO:
@@ -993,6 +1155,7 @@ static void gmux_remove(struct pnp_dev *pnp)
gmux_fini_debugfs(gmux_data);
vga_switcheroo_unregister_handler();
+ pci_dev_put(gmux_data->discrete_pdev);
gmux_disable_interrupts(gmux_data);
if (gmux_data->gpe >= 0) {
acpi_disable_gpe(NULL, gmux_data->gpe);
--
2.55.0
^ permalink raw reply [flat|nested] 14+ messages in thread
* [PATCH 02/13] PCI: Disable pcie port and access on D3 on specific amd devices
2026-10-25 3:59 [PATCH 00/13] Fixes for apple-gmux and runtime support Atharva Tiwari
2026-10-25 3:59 ` [PATCH 01/13] platform/apple-gmux: Fix power for MMIO systems Atharva Tiwari
@ 2026-10-25 3:59 ` Atharva Tiwari
2026-10-25 3:59 ` [PATCH 03/13] platform/apple-gmux: Fix MMIO interface Atharva Tiwari
` (10 subsequent siblings)
12 siblings, 0 replies; 14+ messages in thread
From: Atharva Tiwari @ 2026-10-25 3:59 UTC (permalink / raw)
Cc: Atharva Tiwari, Bjorn Helgaas, Thomas Gleixner, Ingo Molnar,
Borislav Petkov, Dave Hansen,
maintainer:X86 ARCHITECTURE (32-BIT AND 64-BIT),
H. Peter Anvin, Alex Deucher, Christian König, David Airlie,
Simona Vetter, Harry Wentland, Leo Li, Rodrigo Siqueira,
Kenneth Feng, Hans de Goede, Ilpo Järvinen, Andre Eikmeyer,
open list:PCI SUBSYSTEM,
open list:X86 ARCHITECTURE (32-BIT AND 64-BIT),
open list:RADEON and AMDGPU DRM DRIVERS, open list:DRM DRIVERS,
open list:X86 PLATFORM DRIVERS
As mentioned in the previous commit, PWRD turns off the entire
bridge, and if we read/write anything to the config space
or the PCIE space when the bridge is dead, the CPU CATERR's,
so to avoid interaction when the bridge is dead,
we remove pcieport support for the bridges, and we restrict
access to those bridges when the bridge is dead.
Signed-off-by: Atharva Tiwari <atharvatiwarilinuxdev@gmail.com>
---
arch/x86/pci/fixup.c | 30 ++++++++++++++++++++++++++++++
drivers/pci/access.c | 18 ++++++++++++++++++
drivers/pci/pcie/portdrv.c | 2 +-
include/linux/pci.h | 7 +++++++
4 files changed, 56 insertions(+), 1 deletion(-)
diff --git a/arch/x86/pci/fixup.c b/arch/x86/pci/fixup.c
index 795d81c7a..66829941e 100644
--- a/arch/x86/pci/fixup.c
+++ b/arch/x86/pci/fixup.c
@@ -1094,6 +1094,35 @@ static void asus_disable_nvme_d3cold(struct pci_dev *pdev)
}
DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, 0x9a09, asus_disable_nvme_d3cold);
+static const struct dmi_system_id quirk_disable_pcie_port_dmi_table[] = {
+ {
+ .matches = {
+ DMI_MATCH(DMI_SYS_VENDOR, "Apple Inc."),
+ DMI_MATCH(DMI_PRODUCT_NAME, "MacBookPro16,1"),
+ },
+ },
+ {
+ .matches = {
+ DMI_MATCH(DMI_SYS_VENDOR, "Apple Inc."),
+ DMI_MATCH(DMI_PRODUCT_NAME, "MacBookPro16,4"),
+ },
+ },
+ {}
+};
+
+static void quirk_disable_pcie_port(struct pci_dev *pdev)
+{
+ struct pci_dev *upstream = pdev;
+
+ if (dmi_check_system(quirk_disable_pcie_port_dmi_table)) {
+ while ((upstream = pci_upstream_bridge(upstream))) {
+ upstream->no_pcie_port = 1;
+ upstream->ignore_access_d3 = 1;
+ }
+ }
+}
+DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_ATI, 0x7340, quirk_disable_pcie_port);
+
#ifdef CONFIG_SUSPEND
/*
* Root Ports on some AMD SoCs advertise PME_Support for D3hot and D3cold, but
@@ -1179,4 +1208,5 @@ static void quirk_tuxeo_rp_d3(struct pci_dev *pdev)
}
}
DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_AMD, 0x1502, quirk_tuxeo_rp_d3);
+
#endif /* CONFIG_SUSPEND */
diff --git a/drivers/pci/access.c b/drivers/pci/access.c
index b123da16b..5e9513067 100644
--- a/drivers/pci/access.c
+++ b/drivers/pci/access.c
@@ -559,6 +559,9 @@ EXPORT_SYMBOL(pcie_capability_clear_and_set_dword);
int pci_read_config_byte(const struct pci_dev *dev, int where, u8 *val)
{
+ if (pci_dev_ignore_access(dev))
+ return PCIBIOS_SUCCESSFUL;
+
if (pci_dev_is_disconnected(dev)) {
PCI_SET_ERROR_RESPONSE(val);
return PCIBIOS_DEVICE_NOT_FOUND;
@@ -569,6 +572,9 @@ EXPORT_SYMBOL(pci_read_config_byte);
int pci_read_config_word(const struct pci_dev *dev, int where, u16 *val)
{
+ if (pci_dev_ignore_access(dev))
+ return PCIBIOS_SUCCESSFUL;
+
if (pci_dev_is_disconnected(dev)) {
PCI_SET_ERROR_RESPONSE(val);
return PCIBIOS_DEVICE_NOT_FOUND;
@@ -580,6 +586,9 @@ EXPORT_SYMBOL(pci_read_config_word);
int pci_read_config_dword(const struct pci_dev *dev, int where,
u32 *val)
{
+ if (pci_dev_ignore_access(dev))
+ return PCIBIOS_SUCCESSFUL;
+
if (pci_dev_is_disconnected(dev)) {
PCI_SET_ERROR_RESPONSE(val);
return PCIBIOS_DEVICE_NOT_FOUND;
@@ -590,6 +599,9 @@ EXPORT_SYMBOL(pci_read_config_dword);
int pci_write_config_byte(const struct pci_dev *dev, int where, u8 val)
{
+ if (pci_dev_ignore_access(dev))
+ return PCIBIOS_SUCCESSFUL;
+
if (pci_dev_is_disconnected(dev))
return PCIBIOS_DEVICE_NOT_FOUND;
return pci_bus_write_config_byte(dev->bus, dev->devfn, where, val);
@@ -598,6 +610,9 @@ EXPORT_SYMBOL(pci_write_config_byte);
int pci_write_config_word(const struct pci_dev *dev, int where, u16 val)
{
+ if (pci_dev_ignore_access(dev))
+ return PCIBIOS_SUCCESSFUL;
+
if (pci_dev_is_disconnected(dev))
return PCIBIOS_DEVICE_NOT_FOUND;
return pci_bus_write_config_word(dev->bus, dev->devfn, where, val);
@@ -607,6 +622,9 @@ EXPORT_SYMBOL(pci_write_config_word);
int pci_write_config_dword(const struct pci_dev *dev, int where,
u32 val)
{
+ if (pci_dev_ignore_access(dev))
+ return PCIBIOS_SUCCESSFUL;
+
if (pci_dev_is_disconnected(dev))
return PCIBIOS_DEVICE_NOT_FOUND;
return pci_bus_write_config_dword(dev->bus, dev->devfn, where, val);
diff --git a/drivers/pci/pcie/portdrv.c b/drivers/pci/pcie/portdrv.c
index a9cbfc1d2..d2f19e566 100644
--- a/drivers/pci/pcie/portdrv.c
+++ b/drivers/pci/pcie/portdrv.c
@@ -688,7 +688,7 @@ static int pcie_portdrv_probe(struct pci_dev *dev,
int type = pci_pcie_type(dev);
int status;
- if (!pci_is_pcie(dev) ||
+ if (!pci_is_pcie(dev) || dev->no_pcie_port ||
((type != PCI_EXP_TYPE_ROOT_PORT) &&
(type != PCI_EXP_TYPE_UPSTREAM) &&
(type != PCI_EXP_TYPE_DOWNSTREAM) &&
diff --git a/include/linux/pci.h b/include/linux/pci.h
index d31a8d107..8835b1c82 100644
--- a/include/linux/pci.h
+++ b/include/linux/pci.h
@@ -420,6 +420,8 @@ struct pci_dev {
unsigned int no_d1d2:1; /* D1 and D2 are forbidden */
unsigned int no_d3cold:1; /* D3cold is forbidden */
unsigned int bridge_d3:1; /* Allow D3 for bridge */
+ unsigned int no_pcie_port:1; /* PCIE Port driver is forbidden */
+ unsigned int ignore_access_d3:1; /* Ignore access when device is in D3Cold */
unsigned int d3cold_allowed:1; /* D3cold is allowed by user */
unsigned int mmio_always_on:1; /* Disallow turning off io/mem
decoding during BAR sizing */
@@ -2747,6 +2749,11 @@ static inline bool pci_dev_is_disconnected(const struct pci_dev *dev)
return READ_ONCE(dev->error_state) == pci_channel_io_perm_failure;
}
+static inline bool pci_dev_ignore_access(const struct pci_dev *dev)
+{
+ return dev->ignore_access_d3 && dev->current_state == PCI_D3cold;
+}
+
void pci_request_acs(void);
bool pci_acs_enabled(struct pci_dev *pdev, u16 acs_flags);
bool pci_acs_path_enabled(struct pci_dev *start,
--
2.55.0
^ permalink raw reply [flat|nested] 14+ messages in thread
* [PATCH 03/13] platform/apple-gmux: Fix MMIO interface
2026-10-25 3:59 [PATCH 00/13] Fixes for apple-gmux and runtime support Atharva Tiwari
2026-10-25 3:59 ` [PATCH 01/13] platform/apple-gmux: Fix power for MMIO systems Atharva Tiwari
2026-10-25 3:59 ` [PATCH 02/13] PCI: Disable pcie port and access on D3 on specific amd devices Atharva Tiwari
@ 2026-10-25 3:59 ` Atharva Tiwari
2026-10-25 3:59 ` [PATCH 04/13] platform/apple-gmux: Fix Interrupts for MMIO systems Atharva Tiwari
` (9 subsequent siblings)
12 siblings, 0 replies; 14+ messages in thread
From: Atharva Tiwari @ 2026-10-25 3:59 UTC (permalink / raw)
Cc: Atharva Tiwari, Andre Eikmeyer, Bjorn Helgaas, Thomas Gleixner,
Ingo Molnar, Borislav Petkov, Dave Hansen,
maintainer:X86 ARCHITECTURE (32-BIT AND 64-BIT),
H. Peter Anvin, Alex Deucher, Christian König, David Airlie,
Simona Vetter, Harry Wentland, Leo Li, Rodrigo Siqueira,
Kenneth Feng, Hans de Goede, Ilpo Järvinen,
open list:PCI SUBSYSTEM,
open list:X86 ARCHITECTURE (32-BIT AND 64-BIT),
open list:RADEON and AMDGPU DRM DRIVERS, open list:DRM DRIVERS,
open list:X86 PLATFORM DRIVERS
This patch brings a lot of fixes to MMIO interface such as:
1. Using 1ms waits instead of 100us.
2. Checking if Timed out before reading and writing
3. Adding missing wait before gmux_mmio_write32
Co-developed-by: Andre Eikmeyer <dev@deq.rocks>
Signed-off-by: Andre Eikmeyer <dev@deq.rocks>
Signed-off-by: Atharva Tiwari <atharvatiwarilinuxdev@gmail.com>
---
drivers/platform/x86/apple-gmux.c | 59 ++++++++++++++++++-------------
1 file changed, 35 insertions(+), 24 deletions(-)
diff --git a/drivers/platform/x86/apple-gmux.c b/drivers/platform/x86/apple-gmux.c
index 4e8786a5e..076ed7ba6 100644
--- a/drivers/platform/x86/apple-gmux.c
+++ b/drivers/platform/x86/apple-gmux.c
@@ -237,8 +237,8 @@ static int gmux_mmio_wait(struct apple_gmux_data *gmux_data)
u8 gwr = ioread8(gmux_data->iomem_base + GMUX_MMIO_COMMAND_SEND);
while (i && gwr) {
+ fsleep(1000);
gwr = ioread8(gmux_data->iomem_base + GMUX_MMIO_COMMAND_SEND);
- udelay(100);
i--;
}
@@ -250,12 +250,14 @@ static u8 gmux_mmio_read8(struct apple_gmux_data *gmux_data, int port)
u8 val;
mutex_lock(&gmux_data->index_lock);
- gmux_mmio_wait(gmux_data);
- iowrite8((port & 0xff), gmux_data->iomem_base + GMUX_MMIO_PORT_SELECT);
- iowrite8(GMUX_MMIO_READ | sizeof(val),
- gmux_data->iomem_base + GMUX_MMIO_COMMAND_SEND);
- gmux_mmio_wait(gmux_data);
- val = ioread8(gmux_data->iomem_base);
+ if (gmux_mmio_wait(gmux_data)) {
+ iowrite8((port & 0xff), gmux_data->iomem_base + GMUX_MMIO_PORT_SELECT);
+ iowrite8(GMUX_MMIO_READ | sizeof(val),
+ gmux_data->iomem_base + GMUX_MMIO_COMMAND_SEND);
+ if (!gmux_mmio_wait(gmux_data))
+ return 0;
+ val = ioread8(gmux_data->iomem_base);
+ }
mutex_unlock(&gmux_data->index_lock);
return val;
@@ -265,14 +267,17 @@ static void gmux_mmio_write8(struct apple_gmux_data *gmux_data, int port,
u8 val)
{
mutex_lock(&gmux_data->index_lock);
- gmux_mmio_wait(gmux_data);
- iowrite8(val, gmux_data->iomem_base);
- iowrite8(port & 0xff, gmux_data->iomem_base + GMUX_MMIO_PORT_SELECT);
- iowrite8(GMUX_MMIO_WRITE | sizeof(val),
- gmux_data->iomem_base + GMUX_MMIO_COMMAND_SEND);
+ if (gmux_mmio_wait(gmux_data)) {
+ iowrite8(val, gmux_data->iomem_base);
- gmux_mmio_wait(gmux_data);
+ iowrite8(port & 0xff, gmux_data->iomem_base + GMUX_MMIO_PORT_SELECT);
+ iowrite8(GMUX_MMIO_WRITE | sizeof(val),
+ gmux_data->iomem_base + GMUX_MMIO_COMMAND_SEND);
+
+ /* We already wrote the value there is no point to check if timeout */
+ gmux_mmio_wait(gmux_data);
+ }
mutex_unlock(&gmux_data->index_lock);
}
@@ -281,12 +286,16 @@ static u32 gmux_mmio_read32(struct apple_gmux_data *gmux_data, int port)
u32 val;
mutex_lock(&gmux_data->index_lock);
- gmux_mmio_wait(gmux_data);
- iowrite8((port & 0xff), gmux_data->iomem_base + GMUX_MMIO_PORT_SELECT);
- iowrite8(GMUX_MMIO_READ | sizeof(val),
- gmux_data->iomem_base + GMUX_MMIO_COMMAND_SEND);
- gmux_mmio_wait(gmux_data);
- val = ioread32be(gmux_data->iomem_base);
+
+ if (gmux_mmio_wait(gmux_data)) {
+ iowrite8((port & 0xff), gmux_data->iomem_base + GMUX_MMIO_PORT_SELECT);
+ iowrite8(GMUX_MMIO_READ | sizeof(val),
+ gmux_data->iomem_base + GMUX_MMIO_COMMAND_SEND);
+ if (!gmux_mmio_wait(gmux_data))
+ return 0;
+
+ val = ioread32be(gmux_data->iomem_base);
+ }
mutex_unlock(&gmux_data->index_lock);
return val;
@@ -296,11 +305,13 @@ static void gmux_mmio_write32(struct apple_gmux_data *gmux_data, int port,
u32 val)
{
mutex_lock(&gmux_data->index_lock);
- iowrite32be(val, gmux_data->iomem_base);
- iowrite8(port & 0xff, gmux_data->iomem_base + GMUX_MMIO_PORT_SELECT);
- iowrite8(GMUX_MMIO_WRITE | sizeof(val),
- gmux_data->iomem_base + GMUX_MMIO_COMMAND_SEND);
- gmux_mmio_wait(gmux_data);
+ if (gmux_mmio_wait(gmux_data)) {
+ iowrite32be(val, gmux_data->iomem_base);
+ iowrite8(port & 0xff, gmux_data->iomem_base + GMUX_MMIO_PORT_SELECT);
+ iowrite8(GMUX_MMIO_WRITE | sizeof(val),
+ gmux_data->iomem_base + GMUX_MMIO_COMMAND_SEND);
+ gmux_mmio_wait(gmux_data);
+ }
mutex_unlock(&gmux_data->index_lock);
}
--
2.55.0
^ permalink raw reply [flat|nested] 14+ messages in thread
* [PATCH 04/13] platform/apple-gmux: Fix Interrupts for MMIO systems
2026-10-25 3:59 [PATCH 00/13] Fixes for apple-gmux and runtime support Atharva Tiwari
` (2 preceding siblings ...)
2026-10-25 3:59 ` [PATCH 03/13] platform/apple-gmux: Fix MMIO interface Atharva Tiwari
@ 2026-10-25 3:59 ` Atharva Tiwari
2026-10-25 3:59 ` [PATCH 05/13] platform/apple-gmux: Write switch state to EFI on MMIO devices Atharva Tiwari
` (8 subsequent siblings)
12 siblings, 0 replies; 14+ messages in thread
From: Atharva Tiwari @ 2026-10-25 3:59 UTC (permalink / raw)
Cc: Atharva Tiwari, Andre Eikmeyer, Bjorn Helgaas, Thomas Gleixner,
Ingo Molnar, Borislav Petkov, Dave Hansen,
maintainer:X86 ARCHITECTURE (32-BIT AND 64-BIT),
H. Peter Anvin, Alex Deucher, Christian König, David Airlie,
Simona Vetter, Harry Wentland, Leo Li, Rodrigo Siqueira,
Kenneth Feng, Hans de Goede, Ilpo Järvinen,
open list:PCI SUBSYSTEM,
open list:X86 ARCHITECTURE (32-BIT AND 64-BIT),
open list:RADEON and AMDGPU DRM DRIVERS, open list:DRM DRIVERS,
open list:X86 PLATFORM DRIVERS
on MMIO systems, we need check to for failure in interrupts,
and we have implimented display hotplug to wake up the gpu.
Co-developed-by: Andre Eikmeyer <dev@deq.rocks>
Signed-off-by: Andre Eikmeyer <dev@deq.rocks>
Signed-off-by: Atharva Tiwari <atharvatiwarilinuxdev@gmail.com>
---
drivers/platform/x86/apple-gmux.c | 96 +++++++++++++++++++++++++++----
1 file changed, 84 insertions(+), 12 deletions(-)
diff --git a/drivers/platform/x86/apple-gmux.c b/drivers/platform/x86/apple-gmux.c
index 076ed7ba6..bef87a57a 100644
--- a/drivers/platform/x86/apple-gmux.c
+++ b/drivers/platform/x86/apple-gmux.c
@@ -6,6 +6,8 @@
* Copyright (C) 2010-2012 Andreas Heider <andreas@meetr.de>
* Copyright (C) 2015 Lukas Wunner <lukas@wunner.de>
* Copyright (C) 2023 Orlando Chamberlain <orlandoch.dev@gmail.com>
+ * Copyright (C) 2026 Atharva Tiwari <atharvatiwarilinuxdev@gmail.com>
+ * Copyright (C) 2026 Andre Eikmeyer <dev@deq.rocks>
*/
#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
@@ -23,6 +25,8 @@
#include <linux/vga_switcheroo.h>
#include <linux/debugfs.h>
#include <linux/dmi.h>
+#include <linux/workqueue.h>
+#include <linux/pm_runtime.h>
#include <acpi/video.h>
#include <asm/io.h>
@@ -66,6 +70,10 @@ struct apple_gmux_data {
struct backlight_device *bdev;
+ /* interrupt handling data */
+ bool external_state;
+ struct work_struct interrupt_work;
+
/* power handling data */
struct pci_dev *discrete_pdev;
bool uses_pwrd;
@@ -105,6 +113,7 @@ struct apple_gmux_config {
#define GMUX_INTERRUPT_STATUS_ACTIVE 0
#define GMUX_INTERRUPT_STATUS_DISPLAY (1 << 0)
+#define GMUX_INTERRUPT_STATUS_FAILED (1 << 1)
#define GMUX_INTERRUPT_STATUS_POWER (1 << 2)
#define GMUX_INTERRUPT_STATUS_HOTPLUG (1 << 3)
@@ -417,8 +426,8 @@ static const struct backlight_ops gmux_bl_ops = {
* the discrete GPU can then be woken to drive the newly connected display.
* The ability to switch AUX on these generations could be used to improve
* reliability of hotplug detection by having the integrated GPU poll the
- * ports while the discrete GPU is asleep, but currently we do not make use
- * of this feature.
+ * ports while the discrete GPU is asleep, but currently we only make use of
+ * this feature on MMIO/T2 Macs.
*
* Our switching policy for the external port is that on those generations
* which are able to switch it fully, the port is switched together with the
@@ -796,9 +805,10 @@ static const struct apple_gmux_config apple_gmux_mmio = {
* value is read and then inverted.
*
* Because Linux masquerades as Darwin, it ends up in the notification-only code
- * path. On MMIO gmux's, this seems to lead to us being unable to clear interrupts,
- * unless we call GMSP(0). Without this, there is a flood of status=0 interrupts
- * that can't be cleared. This issue seems to be unique to MMIO gmux's.
+ * path. On MMIO gmux's, The Polarity is initally left in a undefined state leading
+ * to lots of interrupts, that we can't clear, to fix this we set the polarity to 0
+ * everytime we enable interrupts, On MMIO gmux's, GMLV reads the same GPIO pin as
+ * GMSP, and setting the polarity to 1, stops the Interrupts completely.
*/
static inline void gmux_disable_interrupts(struct apple_gmux_data *gmux_data)
@@ -807,8 +817,11 @@ static inline void gmux_disable_interrupts(struct apple_gmux_data *gmux_data)
GMUX_INTERRUPT_DISABLE);
}
-static inline void gmux_enable_interrupts(struct apple_gmux_data *gmux_data)
+static inline void gmux_enable_interrupts(struct apple_gmux_data *gmux_data, bool do_gmsp)
{
+ if (gmux_data->type == APPLE_GMUX_TYPE_MMIO && do_gmsp)
+ acpi_execute_simple_method(gmux_data->dhandle, "GMSP", 0);
+
gmux_write8(gmux_data, GMUX_PORT_INTERRUPT_ENABLE,
GMUX_INTERRUPT_ENABLE);
}
@@ -825,23 +838,78 @@ static void gmux_clear_interrupts(struct apple_gmux_data *gmux_data)
/* to clear interrupts write back current status */
status = gmux_interrupt_get_status(gmux_data);
gmux_write8(gmux_data, GMUX_PORT_INTERRUPT_STATUS, status);
- /* Prevent flood of status=0 interrupts */
- if (gmux_data->config == &apple_gmux_mmio)
- acpi_execute_simple_method(gmux_data->dhandle, "GMSP", 0);
}
+static void gmux_notify_work(struct work_struct *work)
+{
+ struct apple_gmux_data *gmux_data =
+ container_of(work, struct apple_gmux_data, interrupt_work);
+ u8 status;
+ bool turn_on_gpu = false;
+
+ status = gmux_interrupt_get_status(gmux_data);
+ if (!status)
+ return;
+
+ gmux_disable_interrupts(gmux_data);
+ pr_debug("Notify handler called: status %d\n", status);
+ acpi_execute_simple_method(gmux_data->dhandle, "GMSP", 0);
+
+ status = gmux_interrupt_get_status(gmux_data);
+ while (status) {
+ gmux_write8(gmux_data, GMUX_PORT_INTERRUPT_STATUS, status);
+ if (status & GMUX_INTERRUPT_STATUS_FAILED) {
+ pr_warn_ratelimited("interrupt failed: status: 0x%x\n", status);
+ status = gmux_interrupt_get_status(gmux_data);
+ continue;
+ }
+ if (status & GMUX_INTERRUPT_STATUS_POWER)
+ complete(&gmux_data->powerchange_done);
+
+ if (status & GMUX_INTERRUPT_STATUS_HOTPLUG) {
+ /*
+ * We get an interrupt every time a display connects or disconnects, but
+ * the GET_DISPLAY port only tells us if a display is connected or not,
+ * so we resume every time a display is connected or disconnected.
+ */
+ bool external_state = !!gmux_read8(gmux_data,
+ GMUX_PORT_SWITCH_GET_DISPLAY);
+ if (external_state != gmux_data->external_state) {
+ gmux_data->external_state = external_state;
+ if (external_state)
+ pr_debug("A display has been connected\n");
+ else
+ pr_debug("All displays has been disconnected\n");
+ }
+ if (!gmux_data->external_switchable && gmux_data->discrete_pdev)
+ turn_on_gpu = true;
+ }
+ status = gmux_interrupt_get_status(gmux_data);
+ }
+
+ gmux_enable_interrupts(gmux_data, 0);
+
+ if (turn_on_gpu)
+ pm_runtime_resume(&gmux_data->discrete_pdev->dev);
+
+}
static void gmux_notify_handler(acpi_handle device, u32 value, void *context)
{
u8 status;
struct pnp_dev *pnp = (struct pnp_dev *)context;
struct apple_gmux_data *gmux_data = pnp_get_drvdata(pnp);
+ if (gmux_data->type == APPLE_GMUX_TYPE_MMIO) {
+ schedule_work(&gmux_data->interrupt_work);
+ return;
+ }
+
status = gmux_interrupt_get_status(gmux_data);
gmux_disable_interrupts(gmux_data);
pr_debug("Notify handler called: status %d\n", status);
gmux_clear_interrupts(gmux_data);
- gmux_enable_interrupts(gmux_data);
+ gmux_enable_interrupts(gmux_data, 0);
if (status & GMUX_INTERRUPT_STATUS_POWER)
complete(&gmux_data->powerchange_done);
@@ -935,7 +1003,7 @@ static int gmux_resume(struct device *dev)
struct pnp_dev *pnp = to_pnp_dev(dev);
struct apple_gmux_data *gmux_data = pnp_get_drvdata(pnp);
- gmux_enable_interrupts(gmux_data);
+ gmux_enable_interrupts(gmux_data, 1);
gmux_write_switch_state(gmux_data);
if (gmux_data->power_state == VGA_SWITCHEROO_OFF)
gmux_set_discrete_state(gmux_data, gmux_data->power_state);
@@ -996,6 +1064,7 @@ static int gmux_probe(struct pnp_dev *pnp, const struct pnp_device_id *id)
pr_err("couldn't remap gmux mmio region");
goto err_release;
}
+ INIT_WORK(&gmux_data->interrupt_work, gmux_notify_work);
goto get_version;
case APPLE_GMUX_TYPE_INDEXED:
gmux_data->config = &apple_gmux_index;
@@ -1115,7 +1184,7 @@ static int gmux_probe(struct pnp_dev *pnp, const struct pnp_device_id *id)
apple_gmux_data = gmux_data;
init_completion(&gmux_data->powerchange_done);
- gmux_enable_interrupts(gmux_data);
+ gmux_enable_interrupts(gmux_data, 1);
gmux_read_switch_state(gmux_data);
/*
@@ -1150,6 +1219,8 @@ static int gmux_probe(struct pnp_dev *pnp, const struct pnp_device_id *id)
err_unmap:
if (gmux_data->iomem_base)
iounmap(gmux_data->iomem_base);
+ if (gmux_data->type == APPLE_GMUX_TYPE_MMIO)
+ cancel_work_sync(&gmux_data->interrupt_work);
err_release:
if (gmux_data->config->resource_type == IORESOURCE_MEM)
release_mem_region(gmux_data->iostart, gmux_data->iolen);
@@ -1168,6 +1239,7 @@ static void gmux_remove(struct pnp_dev *pnp)
vga_switcheroo_unregister_handler();
pci_dev_put(gmux_data->discrete_pdev);
gmux_disable_interrupts(gmux_data);
+ cancel_work_sync(&gmux_data->interrupt_work);
if (gmux_data->gpe >= 0) {
acpi_disable_gpe(NULL, gmux_data->gpe);
acpi_remove_notify_handler(gmux_data->dhandle,
--
2.55.0
^ permalink raw reply [flat|nested] 14+ messages in thread
* [PATCH 05/13] platform/apple-gmux: Write switch state to EFI on MMIO devices
2026-10-25 3:59 [PATCH 00/13] Fixes for apple-gmux and runtime support Atharva Tiwari
` (3 preceding siblings ...)
2026-10-25 3:59 ` [PATCH 04/13] platform/apple-gmux: Fix Interrupts for MMIO systems Atharva Tiwari
@ 2026-10-25 3:59 ` Atharva Tiwari
2026-10-25 3:59 ` [PATCH 06/13] platform/apple-gmux: Add parameter to configure boot gpu Atharva Tiwari
` (7 subsequent siblings)
12 siblings, 0 replies; 14+ messages in thread
From: Atharva Tiwari @ 2026-10-25 3:59 UTC (permalink / raw)
Cc: Andre Eikmeyer, Atharva Tiwari, Bjorn Helgaas, Thomas Gleixner,
Ingo Molnar, Borislav Petkov, Dave Hansen,
maintainer:X86 ARCHITECTURE (32-BIT AND 64-BIT),
H. Peter Anvin, Alex Deucher, Christian König, David Airlie,
Simona Vetter, Harry Wentland, Leo Li, Rodrigo Siqueira,
Kenneth Feng, Hans de Goede, Ilpo Järvinen,
open list:PCI SUBSYSTEM,
open list:X86 ARCHITECTURE (32-BIT AND 64-BIT),
open list:RADEON and AMDGPU DRM DRIVERS, open list:DRM DRIVERS,
open list:X86 PLATFORM DRIVERS
From: Andre Eikmeyer <dev@deq.rocks>
On T2 devices (MMIO), the T2 coprocessor reads gpu-active efi
variable, and macOS seems to write it, so to properly communciate
to the T2 coprocessor, we write gpu-active.
Co-developed: Atharva Tiwari <atharvatiwarilinuxdev@gmail.com>
Signed-off-by: Atharva Tiwari <atharvatiwarilinuxdev@gmail.com>
Signed-off-by: Andre Eikmeyer <dev@deq.rocks>
---
drivers/platform/x86/Kconfig | 1 +
drivers/platform/x86/apple-gmux.c | 29 +++++++++++++++++++++++++++++
2 files changed, 30 insertions(+)
diff --git a/drivers/platform/x86/Kconfig b/drivers/platform/x86/Kconfig
index c37e76066..01895d511 100644
--- a/drivers/platform/x86/Kconfig
+++ b/drivers/platform/x86/Kconfig
@@ -217,6 +217,7 @@ config APPLE_GMUX
depends on ACPI && PCI
depends on PNP
depends on BACKLIGHT_CLASS_DEVICE
+ depends on EFI
help
This driver provides support for the gmux device found on many
Apple laptops, which controls the display mux for the hybrid
diff --git a/drivers/platform/x86/apple-gmux.c b/drivers/platform/x86/apple-gmux.c
index bef87a57a..637b3b216 100644
--- a/drivers/platform/x86/apple-gmux.c
+++ b/drivers/platform/x86/apple-gmux.c
@@ -27,6 +27,7 @@
#include <linux/dmi.h>
#include <linux/workqueue.h>
#include <linux/pm_runtime.h>
+#include <linux/efi.h>
#include <acpi/video.h>
#include <asm/io.h>
@@ -494,6 +495,31 @@ static void gmux_write_switch_state(struct apple_gmux_data *gmux_data)
gmux_write8(gmux_data, GMUX_PORT_SWITCH_EXTERNAL, 3);
}
+#define APPLE_GPU_VARS_GUID EFI_GUID(0xfa4ce28d, 0xb62f, 0x4c99, \
+ 0x9c, 0xc3, 0x68, 0x15, 0x68, 0x6e, 0x30, 0xf9)
+
+static efi_char16_t gmux_gpu_active_name[] = L"gpu-active";
+
+static void gmux_write_switch_state_efi(struct apple_gmux_data *gmux_data)
+{
+ efi_guid_t guid = APPLE_GPU_VARS_GUID;
+ u32 active = gmux_data->switch_state_display == VGA_SWITCHEROO_IGD;
+ efi_status_t status;
+
+ if (!efivar_is_available())
+ return;
+
+ status = efivar_set_variable(gmux_gpu_active_name, &guid,
+ EFI_VARIABLE_NON_VOLATILE |
+ EFI_VARIABLE_BOOTSERVICE_ACCESS |
+ EFI_VARIABLE_RUNTIME_ACCESS,
+ sizeof(active), &active);
+ if (status != EFI_SUCCESS)
+ pr_warn("writing gpu-active failed: 0x%lx\n", status);
+ else
+ pr_debug("gpu-active: %u\n", active);
+}
+
static int gmux_switchto(enum vga_switcheroo_client_id id)
{
apple_gmux_data->switch_state_ddc = id;
@@ -502,6 +528,8 @@ static int gmux_switchto(enum vga_switcheroo_client_id id)
apple_gmux_data->switch_state_external = id;
gmux_write_switch_state(apple_gmux_data);
+ if (apple_gmux_data->type == APPLE_GMUX_TYPE_MMIO)
+ gmux_write_switch_state_efi(apple_gmux_data);
return 0;
}
@@ -1283,3 +1311,4 @@ MODULE_AUTHOR("Seth Forshee <seth.forshee@canonical.com>");
MODULE_DESCRIPTION("Apple Gmux Driver");
MODULE_LICENSE("GPL");
MODULE_DEVICE_TABLE(pnp, gmux_device_ids);
+MODULE_IMPORT_NS("EFIVAR");
--
2.55.0
^ permalink raw reply [flat|nested] 14+ messages in thread
* [PATCH 06/13] platform/apple-gmux: Add parameter to configure boot gpu
2026-10-25 3:59 [PATCH 00/13] Fixes for apple-gmux and runtime support Atharva Tiwari
` (4 preceding siblings ...)
2026-10-25 3:59 ` [PATCH 05/13] platform/apple-gmux: Write switch state to EFI on MMIO devices Atharva Tiwari
@ 2026-10-25 3:59 ` Atharva Tiwari
2026-10-25 3:59 ` [PATCH 07/13] platform/apple-gmux: Add check to detect FSS Atharva Tiwari
` (6 subsequent siblings)
12 siblings, 0 replies; 14+ messages in thread
From: Atharva Tiwari @ 2026-10-25 3:59 UTC (permalink / raw)
Cc: Atharva Tiwari, Bjorn Helgaas, Thomas Gleixner, Ingo Molnar,
Borislav Petkov, Dave Hansen,
maintainer:X86 ARCHITECTURE (32-BIT AND 64-BIT),
H. Peter Anvin, Alex Deucher, Christian König, David Airlie,
Simona Vetter, Harry Wentland, Leo Li, Rodrigo Siqueira,
Kenneth Feng, Hans de Goede, Ilpo Järvinen, Andre Eikmeyer,
open list:PCI SUBSYSTEM,
open list:X86 ARCHITECTURE (32-BIT AND 64-BIT),
open list:RADEON and AMDGPU DRM DRIVERS, open list:DRM DRIVERS,
open list:X86 PLATFORM DRIVERS
Currently on Indexed and MMIO systems, the system can't change
GPU's on runtime, as the display is not trained on the secondary
GPU, to combat this, we add a module parameter to configure the boot
GPU, so users can change to iGPU or dGPU via reboot.
Signed-off-by: Atharva Tiwari <atharvatiwarilinuxdev@gmail.com>
---
drivers/platform/x86/apple-gmux.c | 9 +++++++++
1 file changed, 9 insertions(+)
diff --git a/drivers/platform/x86/apple-gmux.c b/drivers/platform/x86/apple-gmux.c
index 637b3b216..6a9580f27 100644
--- a/drivers/platform/x86/apple-gmux.c
+++ b/drivers/platform/x86/apple-gmux.c
@@ -109,6 +109,10 @@ struct apple_gmux_config {
char *name;
};
+static int boot_gpu = -1;
+module_param(boot_gpu, int, 0);
+MODULE_PARM_DESC(boot_gpu, "Configure the boot gpu (-1 = auto, 0 = iGPU, 1 = dGPU)");
+
#define GMUX_INTERRUPT_ENABLE 0xff
#define GMUX_INTERRUPT_DISABLE 0x00
@@ -1215,6 +1219,11 @@ static int gmux_probe(struct pnp_dev *pnp, const struct pnp_device_id *id)
gmux_enable_interrupts(gmux_data, 1);
gmux_read_switch_state(gmux_data);
+ if (boot_gpu == 0)
+ gmux_switchto(VGA_SWITCHEROO_IGD);
+ else if (boot_gpu == 1)
+ gmux_switchto(VGA_SWITCHEROO_DIS);
+
/*
* Retina MacBook Pros cannot switch the panel's AUX separately
* and need eDP pre-calibration. They are distinguishable from
--
2.55.0
^ permalink raw reply [flat|nested] 14+ messages in thread
* [PATCH 07/13] platform/apple-gmux: Add check to detect FSS
2026-10-25 3:59 [PATCH 00/13] Fixes for apple-gmux and runtime support Atharva Tiwari
` (5 preceding siblings ...)
2026-10-25 3:59 ` [PATCH 06/13] platform/apple-gmux: Add parameter to configure boot gpu Atharva Tiwari
@ 2026-10-25 3:59 ` Atharva Tiwari
2026-10-25 3:59 ` [PATCH 08/13] platform/apple-gmux: Add documentation about iMacs Atharva Tiwari
` (5 subsequent siblings)
12 siblings, 0 replies; 14+ messages in thread
From: Atharva Tiwari @ 2026-10-25 3:59 UTC (permalink / raw)
Cc: Atharva Tiwari, Bjorn Helgaas, Thomas Gleixner, Ingo Molnar,
Borislav Petkov, Dave Hansen,
maintainer:X86 ARCHITECTURE (32-BIT AND 64-BIT),
H. Peter Anvin, Alex Deucher, Christian König, David Airlie,
Simona Vetter, Harry Wentland, Leo Li, Rodrigo Siqueira,
Kenneth Feng, Hans de Goede, Ilpo Järvinen, Andre Eikmeyer,
open list:PCI SUBSYSTEM,
open list:X86 ARCHITECTURE (32-BIT AND 64-BIT),
open list:RADEON and AMDGPU DRM DRIVERS, open list:DRM DRIVERS,
open list:X86 PLATFORM DRIVERS
On MMIO macs, there is feature called FSS, we assume its
a display syncing technology between internal links
(for example 5K iMacs).
We detect it and then warn the user about it, if its broken/unavailable.
Signed-off-by: Atharva Tiwari <atharvatiwarilinuxdev@gmail.com>
---
drivers/platform/x86/apple-gmux.c | 2 ++
include/linux/apple-gmux.h | 1 +
2 files changed, 3 insertions(+)
diff --git a/drivers/platform/x86/apple-gmux.c b/drivers/platform/x86/apple-gmux.c
index 6a9580f27..dda281f2f 100644
--- a/drivers/platform/x86/apple-gmux.c
+++ b/drivers/platform/x86/apple-gmux.c
@@ -1224,6 +1224,8 @@ static int gmux_probe(struct pnp_dev *pnp, const struct pnp_device_id *id)
else if (boot_gpu == 1)
gmux_switchto(VGA_SWITCHEROO_DIS);
+ if (type == APPLE_GMUX_TYPE_MMIO && gmux_read8(gmux_data, GMUX_PORT_FSS) & 1)
+ pr_warn("FSS Failure, display tearing expected\n");
/*
* Retina MacBook Pros cannot switch the panel's AUX separately
* and need eDP pre-calibration. They are distinguishable from
diff --git a/include/linux/apple-gmux.h b/include/linux/apple-gmux.h
index 206d97ffd..a4fa84500 100644
--- a/include/linux/apple-gmux.h
+++ b/include/linux/apple-gmux.h
@@ -22,6 +22,7 @@
#define GMUX_PORT_VERSION_RELEASE 0x06
#define GMUX_PORT_SWITCH_DISPLAY 0x10
#define GMUX_PORT_SWITCH_GET_DISPLAY 0x11
+#define GMUX_PORT_FSS 0x12
#define GMUX_PORT_INTERRUPT_ENABLE 0x14
#define GMUX_PORT_INTERRUPT_STATUS 0x16
#define GMUX_PORT_SWITCH_DDC 0x28
--
2.55.0
^ permalink raw reply [flat|nested] 14+ messages in thread
* [PATCH 08/13] platform/apple-gmux: Add documentation about iMacs
2026-10-25 3:59 [PATCH 00/13] Fixes for apple-gmux and runtime support Atharva Tiwari
` (6 preceding siblings ...)
2026-10-25 3:59 ` [PATCH 07/13] platform/apple-gmux: Add check to detect FSS Atharva Tiwari
@ 2026-10-25 3:59 ` Atharva Tiwari
2026-10-25 3:59 ` [PATCH 09/13] drm/amdgpu: Add Apple GMUX runtime PM support Atharva Tiwari
` (4 subsequent siblings)
12 siblings, 0 replies; 14+ messages in thread
From: Atharva Tiwari @ 2026-10-25 3:59 UTC (permalink / raw)
Cc: Atharva Tiwari, Bjorn Helgaas, Thomas Gleixner, Ingo Molnar,
Borislav Petkov, Dave Hansen,
maintainer:X86 ARCHITECTURE (32-BIT AND 64-BIT),
H. Peter Anvin, Alex Deucher, Christian König, David Airlie,
Simona Vetter, Harry Wentland, Leo Li, Rodrigo Siqueira,
Kenneth Feng, Hans de Goede, Ilpo Järvinen, Andre Eikmeyer,
open list:PCI SUBSYSTEM,
open list:X86 ARCHITECTURE (32-BIT AND 64-BIT),
open list:RADEON and AMDGPU DRM DRIVERS, open list:DRM DRIVERS,
open list:X86 PLATFORM DRIVERS
Add documentation about iMacs
Signed-off-by: Atharva Tiwari <atharvatiwarilinuxdev@gmail.com>
---
drivers/platform/x86/apple-gmux.c | 5 +++++
1 file changed, 5 insertions(+)
diff --git a/drivers/platform/x86/apple-gmux.c b/drivers/platform/x86/apple-gmux.c
index dda281f2f..9f0e9ecbf 100644
--- a/drivers/platform/x86/apple-gmux.c
+++ b/drivers/platform/x86/apple-gmux.c
@@ -453,6 +453,11 @@ static const struct backlight_ops gmux_bl_ops = {
* switch the panel and the external DP connector and allocates a framebuffer
* for the selected GPU.
*
+ * There is iGPU present on iMac's aswell, and we can enable it using apple-set-os.
+ * But there arent any display lines going from the iGPU to the display. iGPU is only
+ * used for offloading then, it makes sense as iMac's display are massive (4K or 5K).
+ * A integrated GPU won't be able to handle that.
+ *
* .. _US 8,687,007 B2: https://pimg-fpiw.uspto.gov/fdd/07/870/086/0.pdf
* .. _NXP CBTL06141: https://www.nxp.com/documents/data_sheet/CBTL06141.pdf
* .. _NXP CBTL06142: https://www.nxp.com/documents/data_sheet/CBTL06141.pdf
--
2.55.0
^ permalink raw reply [flat|nested] 14+ messages in thread
* [PATCH 09/13] drm/amdgpu: Add Apple GMUX runtime PM support
2026-10-25 3:59 [PATCH 00/13] Fixes for apple-gmux and runtime support Atharva Tiwari
` (7 preceding siblings ...)
2026-10-25 3:59 ` [PATCH 08/13] platform/apple-gmux: Add documentation about iMacs Atharva Tiwari
@ 2026-10-25 3:59 ` Atharva Tiwari
2026-10-25 3:59 ` [PATCH 10/13] drm/amdgpu: Catch register access while GMUX keeps the GPU off Atharva Tiwari
` (3 subsequent siblings)
12 siblings, 0 replies; 14+ messages in thread
From: Atharva Tiwari @ 2026-10-25 3:59 UTC (permalink / raw)
Cc: Andre Eikmeyer, Bjorn Helgaas, Thomas Gleixner, Ingo Molnar,
Borislav Petkov, Dave Hansen,
maintainer:X86 ARCHITECTURE (32-BIT AND 64-BIT),
H. Peter Anvin, Alex Deucher, Christian König, David Airlie,
Simona Vetter, Harry Wentland, Leo Li, Rodrigo Siqueira,
Kenneth Feng, Hans de Goede, Ilpo Järvinen, Atharva Tiwari,
open list:PCI SUBSYSTEM,
open list:X86 ARCHITECTURE (32-BIT AND 64-BIT),
open list:RADEON and AMDGPU DRM DRIVERS, open list:DRM DRIVERS,
open list:X86 PLATFORM DRIVERS
From: Andre Eikmeyer <dev@deq.rocks>
The T2 MacBookPro's uses Apple GMUX to control power to the discrete GPU,
but it does not expose the ATPX or ACPI power-resource interfaces currently
recognized by amdgpu. The driver therefore leaves runtime PM disabled even
though vga_switcheroo can switch the GPU reliably.
A dedicated GMUX runtime PM mode uses the existing vga_switcheroo PM domain
to sequence GPU power. A runtime-suspended GMUX GPU can remain powered off
across system sleep, following the smart-suspend handling already used by
BOCO devices.
On muxed systems the inactive GPU cannot reach the panel AUX channel. Like
the macOS driver, tell Display Core that eDP is disconnected before
dc_create() when the GMUX GPU is not the boot display device, and skip eDP
detection at init as the resume path already does. This avoids powering the
panel from the inactive GPU and retaining a fail-safe sink that reports as
connected and keeps the GPU runtime busy.
This allows the discrete GPU to enter D3cold while the integrated GPU is
primary and allows PRIME workloads and external displays to wake it on
demand.
This was tested on MacBookPro15,1, 16,1, 16,4 together
with the corresponding apple-gmux power-sequencing support.
Signed-off-by: Andre Eikmeyer <dev@deq.rocks>
---
drivers/gpu/drm/amd/amdgpu/amdgpu.h | 2 +
drivers/gpu/drm/amd/amdgpu/amdgpu_device.c | 55 +++++++++++++++++--
drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c | 40 +++++++++-----
.../gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 14 +++++
drivers/gpu/drm/amd/pm/inc/amdgpu_dpm.h | 1 +
5 files changed, 93 insertions(+), 19 deletions(-)
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu.h b/drivers/gpu/drm/amd/amdgpu/amdgpu.h
index a9c6f5d4a..6fd607587 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu.h
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu.h
@@ -1194,6 +1194,8 @@ int amdgpu_device_mode1_reset(struct amdgpu_device *adev);
int amdgpu_device_link_reset(struct amdgpu_device *adev);
bool amdgpu_device_supports_atpx(struct amdgpu_device *adev);
bool amdgpu_device_supports_px(struct amdgpu_device *adev);
+bool amdgpu_device_supports_gmux(struct amdgpu_device *adev);
+bool amdgpu_device_has_gmux_edp(struct amdgpu_device *adev);
bool amdgpu_device_supports_boco(struct amdgpu_device *adev);
bool amdgpu_device_supports_smart_shift(struct amdgpu_device *adev);
int amdgpu_device_supports_baco(struct amdgpu_device *adev);
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c
index 9269e780f..c1f196242 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c
@@ -34,6 +34,7 @@
#include <linux/slab.h>
#include <linux/iommu.h>
#include <linux/pci.h>
+#include <linux/dmi.h>
#include <linux/pci-p2pdma.h>
#include <linux/apple-gmux.h>
#include <linux/nospec.h>
@@ -570,6 +571,45 @@ bool amdgpu_device_supports_px(struct amdgpu_device *adev)
return false;
}
+static const struct dmi_system_id amdgpu_gmux_runpm_dmi_table[] = {
+ {
+ .matches = {
+ DMI_MATCH(DMI_PRODUCT_NAME, "MacBookPro15,1"),
+ },
+ },
+ {
+ .matches = {
+ DMI_MATCH(DMI_PRODUCT_NAME, "MacBookPro15,3"),
+ },
+ },
+ {
+ .matches = {
+ DMI_MATCH(DMI_PRODUCT_NAME, "MacBookPro16,1"),
+ },
+ },
+ {
+ .matches = {
+ DMI_MATCH(DMI_PRODUCT_NAME, "MacBookPro16,4"),
+ },
+ },
+ { }
+};
+
+bool amdgpu_device_supports_gmux(struct amdgpu_device *adev)
+{
+ return dmi_check_system(amdgpu_gmux_runpm_dmi_table) &&
+ !dev_is_removable(&adev->pdev->dev) &&
+ apple_gmux_detect(NULL, NULL);
+}
+
+bool amdgpu_device_has_gmux_edp(struct amdgpu_device *adev)
+{
+ return amdgpu_device_supports_gmux(adev) &&
+ (dmi_match(DMI_PRODUCT_NAME, "MacBookPro15,3") ||
+ dmi_match(DMI_PRODUCT_NAME, "MacBookPro16,1") ||
+ dmi_match(DMI_PRODUCT_NAME, "MacBookPro16,4"));
+}
+
/**
* amdgpu_device_supports_boco - Is the device a dGPU with ACPI power resources
*
@@ -640,6 +680,9 @@ void amdgpu_device_detect_runtime_pm_mode(struct amdgpu_device *adev)
/* enable PX as runtime mode */
adev->pm.rpm_mode = AMDGPU_RUNPM_PX;
dev_info(adev->dev, "Using ATPX for runtime pm\n");
+ } else if (amdgpu_device_supports_gmux(adev)) {
+ adev->pm.rpm_mode = AMDGPU_RUNPM_GMUX;
+ dev_info(adev->dev, "Using Apple GMUX for runtime pm\n");
} else if (amdgpu_device_supports_boco(adev)) {
/* enable boco as runtime mode */
adev->pm.rpm_mode = AMDGPU_RUNPM_BOCO;
@@ -3767,7 +3810,7 @@ int amdgpu_device_init(struct amdgpu_device *adev,
{
struct pci_dev *pdev = adev->pdev;
int r, i;
- bool px = false;
+ bool gmux, px = false;
u32 max_MBps;
int tmp;
@@ -4202,12 +4245,13 @@ int amdgpu_device_init(struct amdgpu_device *adev,
vga_client_register(adev->pdev, amdgpu_device_vga_set_decode);
px = amdgpu_device_supports_px(adev);
+ gmux = amdgpu_device_supports_gmux(adev);
if (amdgpu_device_should_register_switcheroo(adev, px))
vga_switcheroo_register_client(adev->pdev,
- &amdgpu_switcheroo_ops, px);
+ &amdgpu_switcheroo_ops, px || gmux);
- if (px)
+ if (px || gmux)
vga_switcheroo_init_domain_pm_ops(adev->dev, &adev->vga_pm_domain);
adev->pm_nb.notifier_call = amdgpu_device_pm_notifier;
@@ -4336,7 +4380,7 @@ void amdgpu_device_fini_hw(struct amdgpu_device *adev)
void amdgpu_device_fini_sw(struct amdgpu_device *adev)
{
int i;
- bool px;
+ bool gmux, px;
amdgpu_device_ip_fini(adev);
amdgpu_fence_driver_sw_fini(adev);
@@ -4367,11 +4411,12 @@ void amdgpu_device_fini_sw(struct amdgpu_device *adev)
adev->xcp_mgr = NULL;
px = amdgpu_device_supports_px(adev);
+ gmux = amdgpu_device_supports_gmux(adev);
if (amdgpu_device_should_register_switcheroo(adev, px))
vga_switcheroo_unregister_client(adev->pdev);
- if (px)
+ if (px || gmux)
vga_switcheroo_fini_domain_pm_ops(adev->dev);
if ((adev->pdev->class >> 8) == PCI_CLASS_DISPLAY_VGA)
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c
index d9d794a7d..5ad7b6dd8 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c
@@ -2494,11 +2494,12 @@ static int amdgpu_pci_probe(struct pci_dev *pdev,
DRM_ERROR("Creating debugfs files failed (%d).\n", ret);
if (adev->pm.rpm_mode != AMDGPU_RUNPM_NONE) {
- /* only need to skip on ATPX */
+ /* ATPX requires a full system-sleep transition. */
if (amdgpu_device_supports_px(adev))
dev_pm_set_driver_flags(ddev->dev, DPM_FLAG_NO_DIRECT_COMPLETE);
- /* we want direct complete for BOCO */
- if (amdgpu_device_supports_boco(adev))
+ /* BOCO and GMUX can remain runtime suspended across system sleep. */
+ if (amdgpu_device_supports_boco(adev) ||
+ adev->pm.rpm_mode == AMDGPU_RUNPM_GMUX)
dev_pm_set_driver_flags(ddev->dev, DPM_FLAG_SMART_PREPARE |
DPM_FLAG_SMART_SUSPEND |
DPM_FLAG_MAY_SKIP_RESUME);
@@ -2610,7 +2611,9 @@ static int amdgpu_pmops_prepare(struct device *dev)
/* Return a positive number here so
* DPM_FLAG_SMART_SUSPEND works properly
*/
- if (amdgpu_device_supports_boco(adev) && pm_runtime_suspended(dev))
+ if ((amdgpu_device_supports_boco(adev) ||
+ adev->pm.rpm_mode == AMDGPU_RUNPM_GMUX) &&
+ pm_runtime_suspended(dev))
return 1;
/* if we will not support s3 or s2i for the device
@@ -2881,6 +2884,7 @@ static int amdgpu_pmops_runtime_suspend(struct device *dev)
}
adev->in_runpm = true;
+ /* GMUX dGPUs drive displays, so hotplug handlers may reopen them. */
if (adev->pm.rpm_mode == AMDGPU_RUNPM_PX)
drm_dev->switch_power_state = DRM_SWITCH_POWER_CHANGING;
@@ -2891,7 +2895,8 @@ static int amdgpu_pmops_runtime_suspend(struct device *dev)
* platforms.
* TODO: this may be also needed for PX capable platform.
*/
- if (adev->pm.rpm_mode == AMDGPU_RUNPM_BOCO)
+ if (adev->pm.rpm_mode == AMDGPU_RUNPM_BOCO ||
+ adev->pm.rpm_mode == AMDGPU_RUNPM_GMUX)
adev->mp1_state = PP_MP1_STATE_UNLOAD;
ret = amdgpu_device_prepare(drm_dev);
@@ -2900,16 +2905,19 @@ static int amdgpu_pmops_runtime_suspend(struct device *dev)
ret = amdgpu_device_suspend(drm_dev, false);
if (ret) {
adev->in_runpm = false;
- if (adev->pm.rpm_mode == AMDGPU_RUNPM_BOCO)
+ if (adev->pm.rpm_mode == AMDGPU_RUNPM_BOCO ||
+ adev->pm.rpm_mode == AMDGPU_RUNPM_GMUX)
adev->mp1_state = PP_MP1_STATE_NONE;
return ret;
}
- if (adev->pm.rpm_mode == AMDGPU_RUNPM_BOCO)
+ if (adev->pm.rpm_mode == AMDGPU_RUNPM_BOCO ||
+ adev->pm.rpm_mode == AMDGPU_RUNPM_GMUX)
adev->mp1_state = PP_MP1_STATE_NONE;
- if (adev->pm.rpm_mode == AMDGPU_RUNPM_PX) {
- /* Only need to handle PCI state in the driver for ATPX
+ if (adev->pm.rpm_mode == AMDGPU_RUNPM_PX ||
+ adev->pm.rpm_mode == AMDGPU_RUNPM_GMUX) {
+ /* Only need to handle PCI state in the driver for ATPX and GMUX.
* PCI core handles it for _PR3.
*/
amdgpu_device_cache_pci_state(pdev);
@@ -2956,10 +2964,12 @@ static int amdgpu_pmops_runtime_resume(struct device *dev)
if (!pci_device_is_present(adev->pdev))
adev->no_hw_access = true;
- if (adev->pm.rpm_mode == AMDGPU_RUNPM_PX) {
- drm_dev->switch_power_state = DRM_SWITCH_POWER_CHANGING;
+ if (adev->pm.rpm_mode == AMDGPU_RUNPM_PX ||
+ adev->pm.rpm_mode == AMDGPU_RUNPM_GMUX) {
+ if (adev->pm.rpm_mode == AMDGPU_RUNPM_PX)
+ drm_dev->switch_power_state = DRM_SWITCH_POWER_CHANGING;
- /* Only need to handle PCI state in the driver for ATPX
+ /* Only need to handle PCI state in the driver for ATPX and GMUX.
* PCI core handles it for _PR3.
*/
pci_set_power_state(pdev, PCI_D0);
@@ -2979,12 +2989,14 @@ static int amdgpu_pmops_runtime_resume(struct device *dev)
}
ret = amdgpu_device_resume(drm_dev, false);
if (ret) {
- if (adev->pm.rpm_mode == AMDGPU_RUNPM_PX)
+ if (adev->pm.rpm_mode == AMDGPU_RUNPM_PX ||
+ adev->pm.rpm_mode == AMDGPU_RUNPM_GMUX)
pci_disable_device(pdev);
return ret;
}
- if (adev->pm.rpm_mode == AMDGPU_RUNPM_PX)
+ if (adev->pm.rpm_mode == AMDGPU_RUNPM_PX ||
+ adev->pm.rpm_mode == AMDGPU_RUNPM_GMUX)
drm_dev->switch_power_state = DRM_SWITCH_POWER_ON;
amdgpu_restore_umd_profile_pstate_after_runpm(adev);
diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
index 47a0ff2ed..aee12cd76 100644
--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
+++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
@@ -81,6 +81,7 @@
#include <linux/moduleparam.h>
#include <linux/types.h>
#include <linux/pm_runtime.h>
+#include <linux/vgaarb.h>
#include <linux/pci.h>
#include <linux/power_supply.h>
#include <linux/firmware.h>
@@ -623,6 +624,10 @@ static int amdgpu_dm_init(struct amdgpu_device *adev)
else
init_data.bb_from_dmub = NULL;
+ if (amdgpu_device_has_gmux_edp(adev) &&
+ adev->pdev != vga_default_device())
+ init_data.flags.edp_not_connected = true;
+
/* Display Core create. */
adev->dm.dc = dc_create(&init_data);
@@ -2545,6 +2550,15 @@ static int amdgpu_dm_initialize_drm_device(struct amdgpu_device *adev)
dm->hpd_rx_offload_wq[aconnector->base.index].aconnector =
aconnector;
+ /* Like the resume path, skip eDP detection without a sink. */
+ if (link->connector_signal == SIGNAL_TYPE_EDP &&
+ amdgpu_device_has_gmux_edp(adev) &&
+ !link->edp_sink_present) {
+ drm_info(adev_to_drm(adev), "Skipping detection of inactive GMUX eDP link %d\n",
+ i);
+ continue;
+ }
+
if (!dc_link_detect_connection_type(link, &new_connection_type))
drm_err(adev_to_drm(adev), "KMS: Failed to detect connector\n");
diff --git a/drivers/gpu/drm/amd/pm/inc/amdgpu_dpm.h b/drivers/gpu/drm/amd/pm/inc/amdgpu_dpm.h
index 8e8a052e1..025fa806d 100644
--- a/drivers/gpu/drm/amd/pm/inc/amdgpu_dpm.h
+++ b/drivers/gpu/drm/amd/pm/inc/amdgpu_dpm.h
@@ -48,6 +48,7 @@ enum amdgpu_int_thermal_type {
enum amdgpu_runpm_mode {
AMDGPU_RUNPM_NONE,
AMDGPU_RUNPM_PX,
+ AMDGPU_RUNPM_GMUX,
AMDGPU_RUNPM_BOCO,
AMDGPU_RUNPM_BACO,
AMDGPU_RUNPM_BAMACO,
--
2.55.0
^ permalink raw reply [flat|nested] 14+ messages in thread
* [PATCH 10/13] drm/amdgpu: Catch register access while GMUX keeps the GPU off
2026-10-25 3:59 [PATCH 00/13] Fixes for apple-gmux and runtime support Atharva Tiwari
` (8 preceding siblings ...)
2026-10-25 3:59 ` [PATCH 09/13] drm/amdgpu: Add Apple GMUX runtime PM support Atharva Tiwari
@ 2026-10-25 3:59 ` Atharva Tiwari
2026-10-25 3:59 ` [PATCH 11/13] drm/amd/display: Refuse DP AUX " Atharva Tiwari
` (2 subsequent siblings)
12 siblings, 0 replies; 14+ messages in thread
From: Atharva Tiwari @ 2026-10-25 3:59 UTC (permalink / raw)
Cc: Andre Eikmeyer, Bjorn Helgaas, Thomas Gleixner, Ingo Molnar,
Borislav Petkov, Dave Hansen,
maintainer:X86 ARCHITECTURE (32-BIT AND 64-BIT),
H. Peter Anvin, Alex Deucher, Christian König, David Airlie,
Simona Vetter, Harry Wentland, Leo Li, Rodrigo Siqueira,
Kenneth Feng, Hans de Goede, Ilpo Järvinen, Atharva Tiwari,
open list:PCI SUBSYSTEM,
open list:X86 ARCHITECTURE (32-BIT AND 64-BIT),
open list:RADEON and AMDGPU DRM DRIVERS, open list:DRM DRIVERS,
open list:X86 PLATFORM DRIVERS
From: Andre Eikmeyer <dev@deq.rocks>
As mentioned previous any access to the GPU when the GMUX has
shut off the rails results in a CPU CATTER, skip and report
any register access after the GPU was runtime suspended for GMUX power-off.
Signed-off-by: Andre Eikmeyer <dev@deq.rocks>
---
drivers/gpu/drm/amd/amdgpu/amdgpu.h | 2 ++
drivers/gpu/drm/amd/amdgpu/amdgpu_device.c | 5 ++++
drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c | 5 ++++
.../gpu/drm/amd/amdgpu/amdgpu_reg_access.c | 24 +++++++++++++++++++
4 files changed, 36 insertions(+)
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu.h b/drivers/gpu/drm/amd/amdgpu/amdgpu.h
index 6fd607587..ac8dfc3ab 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu.h
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu.h
@@ -881,6 +881,8 @@ struct amdgpu_device {
/* enable runtime pm on the device */
bool in_runpm;
bool has_pr3;
+ /* GMUX has cut power, any register access would hang the PEG link */
+ bool gmux_off;
bool ucode_sysfs_en;
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c
index c1f196242..8185934b4 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c
@@ -946,6 +946,11 @@ bool amdgpu_device_skip_hw_access(struct amdgpu_device *adev)
if (adev->no_hw_access)
return true;
+ if (unlikely(READ_ONCE(adev->gmux_off))) {
+ WARN_RATELIMIT(1, "%s: register access while powered off by GMUX\n",
+ dev_name(adev->dev));
+ return true;
+ }
#ifdef CONFIG_LOCKDEP
/*
* This is a bit complicated to understand, so worth a comment. What we assert
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c
index 5ad7b6dd8..135798c76 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c
@@ -2932,6 +2932,9 @@ static int amdgpu_pmops_runtime_suspend(struct device *dev)
amdgpu_device_baco_enter(adev);
}
+ if (adev->pm.rpm_mode == AMDGPU_RUNPM_GMUX)
+ WRITE_ONCE(adev->gmux_off, true);
+
dev_dbg(&pdev->dev, "asic/device is runtime suspended\n");
return 0;
@@ -2960,6 +2963,8 @@ static int amdgpu_pmops_runtime_resume(struct device *dev)
if (adev->pm.rpm_mode == AMDGPU_RUNPM_NONE)
return -EINVAL;
+ WRITE_ONCE(adev->gmux_off, false);
+
/* Avoids registers access if device is physically gone */
if (!pci_device_is_present(adev->pdev))
adev->no_hw_access = true;
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_reg_access.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_reg_access.c
index 7468855c1..bb5dbeb7f 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_reg_access.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_reg_access.c
@@ -594,6 +594,9 @@ u32 amdgpu_device_indirect_rreg(struct amdgpu_device *adev, u32 reg_addr)
void __iomem *pcie_data_offset;
u32 r;
+ if (amdgpu_device_skip_hw_access(adev))
+ return 0;
+
pcie_index = adev->nbio.funcs->get_pcie_index_offset(adev);
pcie_data = adev->nbio.funcs->get_pcie_data_offset(adev);
@@ -677,6 +680,12 @@ u64 amdgpu_device_indirect_rreg64(struct amdgpu_device *adev, u32 reg_addr)
void __iomem *pcie_data_offset;
u64 r;
+ if (amdgpu_device_skip_hw_access(adev))
+ return 0;
+
+ if (amdgpu_device_skip_hw_access(adev))
+ return 0;
+
pcie_index = adev->nbio.funcs->get_pcie_index_offset(adev);
pcie_data = adev->nbio.funcs->get_pcie_data_offset(adev);
@@ -706,6 +715,9 @@ u64 amdgpu_device_indirect_rreg64_ext(struct amdgpu_device *adev, u64 reg_addr)
void __iomem *pcie_data_offset;
u64 r;
+ if (amdgpu_device_skip_hw_access(adev))
+ return 0;
+
pcie_index = adev->nbio.funcs->get_pcie_index_offset(adev);
pcie_data = adev->nbio.funcs->get_pcie_data_offset(adev);
if ((reg_addr >> 32) && (adev->nbio.funcs->get_pcie_index_hi_offset))
@@ -762,6 +774,9 @@ void amdgpu_device_indirect_wreg(struct amdgpu_device *adev, u32 reg_addr,
void __iomem *pcie_index_offset;
void __iomem *pcie_data_offset;
+ if (amdgpu_device_skip_hw_access(adev))
+ return;
+
pcie_index = adev->nbio.funcs->get_pcie_index_offset(adev);
pcie_data = adev->nbio.funcs->get_pcie_data_offset(adev);
@@ -784,6 +799,9 @@ void amdgpu_device_indirect_wreg_ext(struct amdgpu_device *adev, u64 reg_addr,
void __iomem *pcie_index_hi_offset;
void __iomem *pcie_data_offset;
+ if (amdgpu_device_skip_hw_access(adev))
+ return;
+
pcie_index = adev->nbio.funcs->get_pcie_index_offset(adev);
pcie_data = adev->nbio.funcs->get_pcie_data_offset(adev);
if ((reg_addr >> 32) && (adev->nbio.funcs->get_pcie_index_hi_offset))
@@ -832,6 +850,9 @@ void amdgpu_device_indirect_wreg64(struct amdgpu_device *adev, u32 reg_addr,
void __iomem *pcie_index_offset;
void __iomem *pcie_data_offset;
+ if (amdgpu_device_skip_hw_access(adev))
+ return;
+
pcie_index = adev->nbio.funcs->get_pcie_index_offset(adev);
pcie_data = adev->nbio.funcs->get_pcie_data_offset(adev);
@@ -861,6 +882,9 @@ void amdgpu_device_indirect_wreg64_ext(struct amdgpu_device *adev, u64 reg_addr,
void __iomem *pcie_index_hi_offset;
void __iomem *pcie_data_offset;
+ if (amdgpu_device_skip_hw_access(adev))
+ return;
+
pcie_index = adev->nbio.funcs->get_pcie_index_offset(adev);
pcie_data = adev->nbio.funcs->get_pcie_data_offset(adev);
if ((reg_addr >> 32) && (adev->nbio.funcs->get_pcie_index_hi_offset))
--
2.55.0
^ permalink raw reply [flat|nested] 14+ messages in thread
* [PATCH 11/13] drm/amd/display: Refuse DP AUX while GMUX keeps the GPU off
2026-10-25 3:59 [PATCH 00/13] Fixes for apple-gmux and runtime support Atharva Tiwari
` (9 preceding siblings ...)
2026-10-25 3:59 ` [PATCH 10/13] drm/amdgpu: Catch register access while GMUX keeps the GPU off Atharva Tiwari
@ 2026-10-25 3:59 ` Atharva Tiwari
2026-10-25 3:59 ` [PATCH 12/13] drm/amdgpu: Skip AC/DC notification while the GPU is runtime suspended Atharva Tiwari
2026-10-25 3:59 ` [PATCH 13/13] drm/amd/display: Skip panel power savings on eDP links without a panel Atharva Tiwari
12 siblings, 0 replies; 14+ messages in thread
From: Atharva Tiwari @ 2026-10-25 3:59 UTC (permalink / raw)
Cc: Andre Eikmeyer, Bjorn Helgaas, Thomas Gleixner, Ingo Molnar,
Borislav Petkov, Dave Hansen,
maintainer:X86 ARCHITECTURE (32-BIT AND 64-BIT),
H. Peter Anvin, Alex Deucher, Christian König, David Airlie,
Simona Vetter, Harry Wentland, Leo Li, Rodrigo Siqueira,
Kenneth Feng, Hans de Goede, Ilpo Järvinen, Atharva Tiwari,
open list:PCI SUBSYSTEM,
open list:X86 ARCHITECTURE (32-BIT AND 64-BIT),
open list:RADEON and AMDGPU DRM DRIVERS, open list:DRM DRIVERS,
open list:X86 PLATFORM DRIVERS
From: Andre Eikmeyer <dev@deq.rocks>
fwupd reads /dev/drm_dp_aux* while the GPU is runtime suspended. The AUX
device holds no runtime PM reference, so the transfer touched registers of
the powered off GPU and caused a CPU CATTER.
Signed-off-by: Andre Eikmeyer <dev@deq.rocks>
---
.../display/amdgpu_dm/amdgpu_dm_mst_types.c | 19 +++++++++++++++++--
1 file changed, 17 insertions(+), 2 deletions(-)
diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c
index 7261317d4..b099bf520 100644
--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c
+++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c
@@ -24,6 +24,7 @@
*
*/
+#include <linux/pm_runtime.h>
#include <linux/vmalloc.h>
#include <drm/display/drm_dp_helper.h>
#include <drm/display/drm_dp_mst_helper.h>
@@ -111,6 +112,20 @@ STATIC_IFN_KUNIT ssize_t dm_dp_aux_transfer(struct drm_dp_aux *aux,
if (WARN_ON(msg->size > 16))
return -E2BIG;
+ ddc = TO_DM_AUX(aux)->ddc_service;
+ adev = ddc->ctx->driver_context;
+
+ /*
+ * User space reaches this through the drm_dp_aux_dev character device
+ * without a runtime PM reference. Refuse the transfer while GMUX keeps
+ * the GPU powered off, a register access then hangs the PEG link.
+ */
+ pm_runtime_get_noresume(adev->dev);
+ if (READ_ONCE(adev->gmux_off)) {
+ pm_runtime_put_noidle(adev->dev);
+ return -EBUSY;
+ }
+
payload.address = msg->address;
payload.data = msg->buffer;
payload.length = msg->size;
@@ -126,13 +141,13 @@ STATIC_IFN_KUNIT ssize_t dm_dp_aux_transfer(struct drm_dp_aux *aux,
result = dc_link_aux_transfer_raw(TO_DM_AUX(aux)->ddc_service, &payload,
&operation_result);
+ pm_runtime_put_autosuspend(adev->dev);
+
/*
* w/a on certain intel platform where hpd is unexpected to pull low during
* 1st sideband message transaction by return AUX_RET_ERROR_HPD_DISCON
* aux transaction is succuess in such case, therefore bypass the error
*/
- ddc = TO_DM_AUX(aux)->ddc_service;
- adev = ddc->ctx->driver_context;
if (adev->dm.aux_hpd_discon_quirk) {
if (msg->address == DP_SIDEBAND_MSG_DOWN_REQ_BASE &&
operation_result == AUX_RET_ERROR_HPD_DISCON) {
--
2.55.0
^ permalink raw reply [flat|nested] 14+ messages in thread
* [PATCH 12/13] drm/amdgpu: Skip AC/DC notification while the GPU is runtime suspended
2026-10-25 3:59 [PATCH 00/13] Fixes for apple-gmux and runtime support Atharva Tiwari
` (10 preceding siblings ...)
2026-10-25 3:59 ` [PATCH 11/13] drm/amd/display: Refuse DP AUX " Atharva Tiwari
@ 2026-10-25 3:59 ` Atharva Tiwari
2026-10-25 3:59 ` [PATCH 13/13] drm/amd/display: Skip panel power savings on eDP links without a panel Atharva Tiwari
12 siblings, 0 replies; 14+ messages in thread
From: Atharva Tiwari @ 2026-10-25 3:59 UTC (permalink / raw)
Cc: Andre Eikmeyer, Atharva Tiwari, Bjorn Helgaas, Thomas Gleixner,
Ingo Molnar, Borislav Petkov, Dave Hansen,
maintainer:X86 ARCHITECTURE (32-BIT AND 64-BIT),
H. Peter Anvin, Alex Deucher, Christian König, David Airlie,
Simona Vetter, Harry Wentland, Leo Li, Rodrigo Siqueira,
Kenneth Feng, Hans de Goede, Ilpo Järvinen,
open list:PCI SUBSYSTEM,
open list:X86 ARCHITECTURE (32-BIT AND 64-BIT),
open list:RADEON and AMDGPU DRM DRIVERS, open list:DRM DRIVERS,
open list:X86 PLATFORM DRIVERS
From: Andre Eikmeyer <dev@deq.rocks>
Plugging or unplugging the charger raises an ACPI AC event. The handler
sent the new power source to the SMU without a runtime PM reference, so
with GMUX keeping the GPU off every SMU message spun on skipped register
reads for seconds. A runtime resume racing with that left the SMU
firmware unable to start on MacBookPro15,1 and the GPU in runtime PM
error state. Record the power source only and let the resume apply it.
Signed-off-by: Atharva Tiwari <atharvatiwarilinuxdev@gmail.com>
Signed-off-by: Andre Eikmeyer <dev@deq.rocks>
---
drivers/gpu/drm/amd/pm/amdgpu_dpm.c | 19 +++++++++++++------
1 file changed, 13 insertions(+), 6 deletions(-)
diff --git a/drivers/gpu/drm/amd/pm/amdgpu_dpm.c b/drivers/gpu/drm/amd/pm/amdgpu_dpm.c
index 808be6c42..b64f0b681 100644
--- a/drivers/gpu/drm/amd/pm/amdgpu_dpm.c
+++ b/drivers/gpu/drm/amd/pm/amdgpu_dpm.c
@@ -30,6 +30,7 @@
#include "amd_pcie.h"
#include "amdgpu_display.h"
#include "hwmgr.h"
+#include <linux/pm_runtime.h>
#include <linux/power_supply.h>
#include "amdgpu_smu.h"
@@ -498,20 +499,26 @@ int amdgpu_dpm_smu_i2c_bus_access(struct amdgpu_device *adev,
void amdgpu_pm_acpi_event_handler(struct amdgpu_device *adev)
{
+ int active = 0;
+
if (adev->pm.dpm_enabled) {
mutex_lock(&adev->pm.mutex);
+ active = adev->pm.rpm_mode == AMDGPU_RUNPM_GMUX ?
+ pm_runtime_get_if_active(adev->dev) : 1;
+
if (power_supply_is_system_supplied() > 0)
adev->pm.ac_power = true;
else
adev->pm.ac_power = false;
- if (adev->powerplay.pp_funcs &&
- adev->powerplay.pp_funcs->notify_ac_dc)
- amdgpu_dpm_notify_ac_dc(adev);
-
- if (is_support_sw_smu(adev))
- smu_set_ac_dc(adev->powerplay.pp_handle, true);
+ if (active) {
+ if (adev->powerplay.pp_funcs &&
+ adev->powerplay.pp_funcs->notify_ac_dc)
+ amdgpu_dpm_notify_ac_dc(adev);
+ if (is_support_sw_smu(adev))
+ smu_set_ac_dc(adev->powerplay.pp_handle, true);
+ }
mutex_unlock(&adev->pm.mutex);
}
}
--
2.55.0
^ permalink raw reply [flat|nested] 14+ messages in thread
* [PATCH 13/13] drm/amd/display: Skip panel power savings on eDP links without a panel
2026-10-25 3:59 [PATCH 00/13] Fixes for apple-gmux and runtime support Atharva Tiwari
` (11 preceding siblings ...)
2026-10-25 3:59 ` [PATCH 12/13] drm/amdgpu: Skip AC/DC notification while the GPU is runtime suspended Atharva Tiwari
@ 2026-10-25 3:59 ` Atharva Tiwari
12 siblings, 0 replies; 14+ messages in thread
From: Atharva Tiwari @ 2026-10-25 3:59 UTC (permalink / raw)
Cc: Andre Eikmeyer, Atharva Tiwari, Bjorn Helgaas, Thomas Gleixner,
Ingo Molnar, Borislav Petkov, Dave Hansen,
maintainer:X86 ARCHITECTURE (32-BIT AND 64-BIT),
H. Peter Anvin, Alex Deucher, Christian König, David Airlie,
Simona Vetter, Harry Wentland, Leo Li, Rodrigo Siqueira,
Kenneth Feng, Hans de Goede, Ilpo Järvinen,
open list:PCI SUBSYSTEM,
open list:X86 ARCHITECTURE (32-BIT AND 64-BIT),
open list:RADEON and AMDGPU DRM DRIVERS, open list:DRM DRIVERS,
open list:X86 PLATFORM DRIVERS
From: Andre Eikmeyer <dev@deq.rocks>
When GMUX routes the internal panel to the integrated GPU, the eDP link
of the AMD GPU has no sink. It still exposed panel_power_savings, and
tuned writes it on every switch between AC and battery. Each write sends
a hotplug event and the following connector probe runtime resumes the
GPU that GMUX had powered off. Only create the attribute when the link
has a panel.
Signed-off-by: Atharva Tiwari <atharvatiwarilinuxdev@gmail.com>
Signed-off-by: Andre Eikmeyer <dev@deq.rocks>
---
drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_backlight.c | 3 +++
1 file changed, 3 insertions(+)
diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_backlight.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_backlight.c
index 703d0617d..c8fbd2167 100644
--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_backlight.c
+++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_backlight.c
@@ -761,6 +761,9 @@ amdgpu_dm_should_create_sysfs(struct amdgpu_dm_connector *amdgpu_dm_connector)
if (amdgpu_dm_connector->base.connector_type != DRM_MODE_CONNECTOR_eDP)
return false;
+ if (!amdgpu_dm_connector->dc_link->edp_sink_present)
+ return false;
+
if (link->panel_type != PANEL_TYPE_LCD && !link->panel_config.cacp.cacp_supported)
return false;
--
2.55.0
^ permalink raw reply [flat|nested] 14+ messages in thread
end of thread, other threads:[~2026-10-25 4:04 UTC | newest]
Thread overview: 14+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2026-10-25 3:59 [PATCH 00/13] Fixes for apple-gmux and runtime support Atharva Tiwari
2026-10-25 3:59 ` [PATCH 01/13] platform/apple-gmux: Fix power for MMIO systems Atharva Tiwari
2026-10-25 3:59 ` [PATCH 02/13] PCI: Disable pcie port and access on D3 on specific amd devices Atharva Tiwari
2026-10-25 3:59 ` [PATCH 03/13] platform/apple-gmux: Fix MMIO interface Atharva Tiwari
2026-10-25 3:59 ` [PATCH 04/13] platform/apple-gmux: Fix Interrupts for MMIO systems Atharva Tiwari
2026-10-25 3:59 ` [PATCH 05/13] platform/apple-gmux: Write switch state to EFI on MMIO devices Atharva Tiwari
2026-10-25 3:59 ` [PATCH 06/13] platform/apple-gmux: Add parameter to configure boot gpu Atharva Tiwari
2026-10-25 3:59 ` [PATCH 07/13] platform/apple-gmux: Add check to detect FSS Atharva Tiwari
2026-10-25 3:59 ` [PATCH 08/13] platform/apple-gmux: Add documentation about iMacs Atharva Tiwari
2026-10-25 3:59 ` [PATCH 09/13] drm/amdgpu: Add Apple GMUX runtime PM support Atharva Tiwari
2026-10-25 3:59 ` [PATCH 10/13] drm/amdgpu: Catch register access while GMUX keeps the GPU off Atharva Tiwari
2026-10-25 3:59 ` [PATCH 11/13] drm/amd/display: Refuse DP AUX " Atharva Tiwari
2026-10-25 3:59 ` [PATCH 12/13] drm/amdgpu: Skip AC/DC notification while the GPU is runtime suspended Atharva Tiwari
2026-10-25 3:59 ` [PATCH 13/13] drm/amd/display: Skip panel power savings on eDP links without a panel Atharva Tiwari
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox
all inboxes | Powered by JetHome®