~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

TOMOYO Linux Cross Reference
Linux/include/linux/apple-gmux.h

Version: ~ [ linux-6.11.5 ] ~ [ linux-6.10.14 ] ~ [ linux-6.9.12 ] ~ [ linux-6.8.12 ] ~ [ linux-6.7.12 ] ~ [ linux-6.6.58 ] ~ [ linux-6.5.13 ] ~ [ linux-6.4.16 ] ~ [ linux-6.3.13 ] ~ [ linux-6.2.16 ] ~ [ linux-6.1.114 ] ~ [ linux-6.0.19 ] ~ [ linux-5.19.17 ] ~ [ linux-5.18.19 ] ~ [ linux-5.17.15 ] ~ [ linux-5.16.20 ] ~ [ linux-5.15.169 ] ~ [ linux-5.14.21 ] ~ [ linux-5.13.19 ] ~ [ linux-5.12.19 ] ~ [ linux-5.11.22 ] ~ [ linux-5.10.228 ] ~ [ linux-5.9.16 ] ~ [ linux-5.8.18 ] ~ [ linux-5.7.19 ] ~ [ linux-5.6.19 ] ~ [ linux-5.5.19 ] ~ [ linux-5.4.284 ] ~ [ linux-5.3.18 ] ~ [ linux-5.2.21 ] ~ [ linux-5.1.21 ] ~ [ linux-5.0.21 ] ~ [ linux-4.20.17 ] ~ [ linux-4.19.322 ] ~ [ linux-4.18.20 ] ~ [ linux-4.17.19 ] ~ [ linux-4.16.18 ] ~ [ linux-4.15.18 ] ~ [ linux-4.14.336 ] ~ [ linux-4.13.16 ] ~ [ linux-4.12.14 ] ~ [ linux-4.11.12 ] ~ [ linux-4.10.17 ] ~ [ linux-4.9.337 ] ~ [ linux-4.4.302 ] ~ [ linux-3.10.108 ] ~ [ linux-2.6.32.71 ] ~ [ linux-2.6.0 ] ~ [ linux-2.4.37.11 ] ~ [ unix-v6-master ] ~ [ ccs-tools-1.8.9 ] ~ [ policy-sample ] ~
Architecture: ~ [ i386 ] ~ [ alpha ] ~ [ m68k ] ~ [ mips ] ~ [ ppc ] ~ [ sparc ] ~ [ sparc64 ] ~

  1 /* SPDX-License-Identifier: GPL-2.0-only */
  2 /*
  3  * apple-gmux.h - microcontroller built into dual GPU MacBook Pro & Mac Pro
  4  * Copyright (C) 2015 Lukas Wunner <lukas@wunner.de>
  5  */
  6 
  7 #ifndef LINUX_APPLE_GMUX_H
  8 #define LINUX_APPLE_GMUX_H
  9 
 10 #include <linux/acpi.h>
 11 #include <linux/io.h>
 12 #include <linux/pnp.h>
 13 
 14 #define GMUX_ACPI_HID "APP000B"
 15 
 16 /*
 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.
 19  */
 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
 36 
 37 #define GMUX_MMIO_PORT_SELECT           0x0e
 38 #define GMUX_MMIO_COMMAND_SEND          0x0f
 39 
 40 #define GMUX_MMIO_READ                  0x00
 41 #define GMUX_MMIO_WRITE                 0x40
 42 
 43 #define GMUX_MIN_IO_LEN                 (GMUX_PORT_BRIGHTNESS + 4)
 44 
 45 enum apple_gmux_type {
 46         APPLE_GMUX_TYPE_PIO,
 47         APPLE_GMUX_TYPE_INDEXED,
 48         APPLE_GMUX_TYPE_MMIO,
 49 };
 50 
 51 #if IS_ENABLED(CONFIG_APPLE_GMUX)
 52 static inline bool apple_gmux_is_indexed(unsigned long iostart)
 53 {
 54         u16 val;
 55 
 56         outb(0xaa, iostart + 0xcc);
 57         outb(0x55, iostart + 0xcd);
 58         outb(0x00, iostart + 0xce);
 59 
 60         val = inb(iostart + 0xcc) | (inb(iostart + 0xcd) << 8);
 61         if (val == 0x55aa)
 62                 return true;
 63 
 64         return false;
 65 }
 66 
 67 static inline bool apple_gmux_is_mmio(unsigned long iostart)
 68 {
 69         u8 __iomem *iomem_base = ioremap(iostart, 16);
 70         u8 val;
 71 
 72         if (!iomem_base)
 73                 return false;
 74 
 75         /*
 76          * If this is 0xff, then gmux must not be present, as the gmux would
 77          * reset it to 0x00, or it would be one of 0x1, 0x4, 0x41, 0x44 if a
 78          * command is currently being processed.
 79          */
 80         val = ioread8(iomem_base + GMUX_MMIO_COMMAND_SEND);
 81         iounmap(iomem_base);
 82         return (val != 0xff);
 83 }
 84 
 85 /**
 86  * apple_gmux_detect() - detect if gmux is built into the machine
 87  *
 88  * @pnp_dev:     Device to probe or NULL to use the first matching device
 89  * @type_ret: Returns (by reference) the apple_gmux_type of the device
 90  *
 91  * Detect if a supported gmux device is present by actually probing it.
 92  * This avoids the false positives returned on some models by
 93  * apple_gmux_present().
 94  *
 95  * Return: %true if a supported gmux ACPI device is detected and the kernel
 96  * was configured with CONFIG_APPLE_GMUX, %false otherwise.
 97  */
 98 static inline bool apple_gmux_detect(struct pnp_dev *pnp_dev, enum apple_gmux_type *type_ret)
 99 {
100         u8 ver_major, ver_minor, ver_release;
101         struct device *dev = NULL;
102         struct acpi_device *adev;
103         struct resource *res;
104         enum apple_gmux_type type = APPLE_GMUX_TYPE_PIO;
105         bool ret = false;
106 
107         if (!pnp_dev) {
108                 adev = acpi_dev_get_first_match_dev(GMUX_ACPI_HID, NULL, -1);
109                 if (!adev)
110                         return false;
111 
112                 dev = get_device(acpi_get_first_physical_node(adev));
113                 acpi_dev_put(adev);
114                 if (!dev)
115                         return false;
116 
117                 pnp_dev = to_pnp_dev(dev);
118         }
119 
120         res = pnp_get_resource(pnp_dev, IORESOURCE_IO, 0);
121         if (res && resource_size(res) >= GMUX_MIN_IO_LEN) {
122                 /*
123                  * Invalid version information may indicate either that the gmux
124                  * device isn't present or that it's a new one that uses indexed io.
125                  */
126                 ver_major = inb(res->start + GMUX_PORT_VERSION_MAJOR);
127                 ver_minor = inb(res->start + GMUX_PORT_VERSION_MINOR);
128                 ver_release = inb(res->start + GMUX_PORT_VERSION_RELEASE);
129                 if (ver_major == 0xff && ver_minor == 0xff && ver_release == 0xff) {
130                         if (apple_gmux_is_indexed(res->start))
131                                 type = APPLE_GMUX_TYPE_INDEXED;
132                         else
133                                 goto out;
134                 }
135         } else {
136                 res = pnp_get_resource(pnp_dev, IORESOURCE_MEM, 0);
137                 if (res && apple_gmux_is_mmio(res->start))
138                         type = APPLE_GMUX_TYPE_MMIO;
139                 else
140                         goto out;
141         }
142 
143         if (type_ret)
144                 *type_ret = type;
145 
146         ret = true;
147 out:
148         put_device(dev);
149         return ret;
150 }
151 
152 /**
153  * apple_gmux_present() - check if gmux ACPI device is present
154  *
155  * Drivers may use this to activate quirks specific to dual GPU MacBook Pros
156  * and Mac Pros, e.g. for deferred probing, runtime pm and backlight.
157  *
158  * Return: %true if gmux ACPI device is present and the kernel was configured
159  * with CONFIG_APPLE_GMUX, %false otherwise.
160  */
161 static inline bool apple_gmux_present(void)
162 {
163         return acpi_dev_found(GMUX_ACPI_HID);
164 }
165 
166 #else  /* !CONFIG_APPLE_GMUX */
167 
168 static inline bool apple_gmux_present(void)
169 {
170         return false;
171 }
172 
173 static inline bool apple_gmux_detect(struct pnp_dev *pnp_dev, bool *indexed_ret)
174 {
175         return false;
176 }
177 
178 #endif /* !CONFIG_APPLE_GMUX */
179 
180 #endif /* LINUX_APPLE_GMUX_H */
181 

~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

kernel.org | git.kernel.org | LWN.net | Project Home | SVN repository | Mail admin

Linux® is a registered trademark of Linus Torvalds in the United States and other countries.
TOMOYO® is a registered trademark of NTT DATA CORPORATION.

sflogo.php