1 /* SPDX-License-Identifier: GPL-2.0-only */
3 * apple-gmux.h - microcontroller built into dual GPU MacBook Pro & Mac Pro
7 #ifndef LINUX_APPLE_GMUX_H
8 #define LINUX_APPLE_GMUX_H
10 #include <linux/acpi.h>
12 #include <linux/pnp.h>
14 #define GMUX_ACPI_HID "APP000B"
17 * gmux port offsets. Many of these are not yet used, but may be in the
18 * future, and it's useful to have them documented here anyhow.
20 #define GMUX_PORT_VERSION_MAJOR 0x04
21 #define GMUX_PORT_VERSION_MINOR 0x05
22 #define GMUX_PORT_VERSION_RELEASE 0x06
23 #define GMUX_PORT_SWITCH_DISPLAY 0x10
24 #define GMUX_PORT_SWITCH_GET_DISPLAY 0x11
25 #define GMUX_PORT_INTERRUPT_ENABLE 0x14
26 #define GMUX_PORT_INTERRUPT_STATUS 0x16
27 #define GMUX_PORT_SWITCH_DDC 0x28
28 #define GMUX_PORT_SWITCH_EXTERNAL 0x40
29 #define GMUX_PORT_SWITCH_GET_EXTERNAL 0x41
30 #define GMUX_PORT_DISCRETE_POWER 0x50
31 #define GMUX_PORT_MAX_BRIGHTNESS 0x70
32 #define GMUX_PORT_BRIGHTNESS 0x74
33 #define GMUX_PORT_VALUE 0xc2
34 #define GMUX_PORT_READ 0xd0
35 #define GMUX_PORT_WRITE 0xd4
37 #define GMUX_MIN_IO_LEN (GMUX_PORT_BRIGHTNESS + 4)
39 #if IS_ENABLED(CONFIG_APPLE_GMUX)
40 static inline bool apple_gmux_is_indexed(unsigned long iostart)
44 outb(0xaa, iostart + 0xcc);
45 outb(0x55, iostart + 0xcd);
46 outb(0x00, iostart + 0xce);
48 val = inb(iostart + 0xcc) | (inb(iostart + 0xcd) << 8);
56 * apple_gmux_detect() - detect if gmux is built into the machine
58 * @pnp_dev: Device to probe or NULL to use the first matching device
59 * @indexed_ret: Returns (by reference) if the gmux is indexed or not
61 * Detect if a supported gmux device is present by actually probing it.
62 * This avoids the false positives returned on some models by
63 * apple_gmux_present().
65 * Return: %true if a supported gmux ACPI device is detected and the kernel
66 * was configured with CONFIG_APPLE_GMUX, %false otherwise.
68 static inline bool apple_gmux_detect(struct pnp_dev *pnp_dev, bool *indexed_ret)
70 u8 ver_major, ver_minor, ver_release;
71 struct device *dev = NULL;
72 struct acpi_device *adev;
78 adev = acpi_dev_get_first_match_dev(GMUX_ACPI_HID, NULL, -1);
82 dev = get_device(acpi_get_first_physical_node(adev));
87 pnp_dev = to_pnp_dev(dev);
90 res = pnp_get_resource(pnp_dev, IORESOURCE_IO, 0);
91 if (!res || resource_size(res) < GMUX_MIN_IO_LEN)
95 * Invalid version information may indicate either that the gmux
96 * device isn't present or that it's a new one that uses indexed io.
98 ver_major = inb(res->start + GMUX_PORT_VERSION_MAJOR);
99 ver_minor = inb(res->start + GMUX_PORT_VERSION_MINOR);
100 ver_release = inb(res->start + GMUX_PORT_VERSION_RELEASE);
101 if (ver_major == 0xff && ver_minor == 0xff && ver_release == 0xff) {
102 indexed = apple_gmux_is_indexed(res->start);
108 *indexed_ret = indexed;
117 * apple_gmux_present() - check if gmux ACPI device is present
119 * Drivers may use this to activate quirks specific to dual GPU MacBook Pros
120 * and Mac Pros, e.g. for deferred probing, runtime pm and backlight.
122 * Return: %true if gmux ACPI device is present and the kernel was configured
123 * with CONFIG_APPLE_GMUX, %false otherwise.
125 static inline bool apple_gmux_present(void)
127 return acpi_dev_found(GMUX_ACPI_HID);
130 #else /* !CONFIG_APPLE_GMUX */
132 static inline bool apple_gmux_present(void)
137 static inline bool apple_gmux_detect(struct pnp_dev *pnp_dev, bool *indexed_ret)
142 #endif /* !CONFIG_APPLE_GMUX */
144 #endif /* LINUX_APPLE_GMUX_H */