at v6.2 3.8 kB view raw
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_MIN_IO_LEN (GMUX_PORT_BRIGHTNESS + 4) 38 39#if IS_ENABLED(CONFIG_APPLE_GMUX) 40static inline bool apple_gmux_is_indexed(unsigned long iostart) 41{ 42 u16 val; 43 44 outb(0xaa, iostart + 0xcc); 45 outb(0x55, iostart + 0xcd); 46 outb(0x00, iostart + 0xce); 47 48 val = inb(iostart + 0xcc) | (inb(iostart + 0xcd) << 8); 49 if (val == 0x55aa) 50 return true; 51 52 return false; 53} 54 55/** 56 * apple_gmux_detect() - detect if gmux is built into the machine 57 * 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 60 * 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(). 64 * 65 * Return: %true if a supported gmux ACPI device is detected and the kernel 66 * was configured with CONFIG_APPLE_GMUX, %false otherwise. 67 */ 68static inline bool apple_gmux_detect(struct pnp_dev *pnp_dev, bool *indexed_ret) 69{ 70 u8 ver_major, ver_minor, ver_release; 71 struct device *dev = NULL; 72 struct acpi_device *adev; 73 struct resource *res; 74 bool indexed = false; 75 bool ret = false; 76 77 if (!pnp_dev) { 78 adev = acpi_dev_get_first_match_dev(GMUX_ACPI_HID, NULL, -1); 79 if (!adev) 80 return false; 81 82 dev = get_device(acpi_get_first_physical_node(adev)); 83 acpi_dev_put(adev); 84 if (!dev) 85 return false; 86 87 pnp_dev = to_pnp_dev(dev); 88 } 89 90 res = pnp_get_resource(pnp_dev, IORESOURCE_IO, 0); 91 if (!res || resource_size(res) < GMUX_MIN_IO_LEN) 92 goto out; 93 94 /* 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. 97 */ 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); 103 if (!indexed) 104 goto out; 105 } 106 107 if (indexed_ret) 108 *indexed_ret = indexed; 109 110 ret = true; 111out: 112 put_device(dev); 113 return ret; 114} 115 116/** 117 * apple_gmux_present() - check if gmux ACPI device is present 118 * 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. 121 * 122 * Return: %true if gmux ACPI device is present and the kernel was configured 123 * with CONFIG_APPLE_GMUX, %false otherwise. 124 */ 125static inline bool apple_gmux_present(void) 126{ 127 return acpi_dev_found(GMUX_ACPI_HID); 128} 129 130#else /* !CONFIG_APPLE_GMUX */ 131 132static inline bool apple_gmux_present(void) 133{ 134 return false; 135} 136 137static inline bool apple_gmux_detect(struct pnp_dev *pnp_dev, bool *indexed_ret) 138{ 139 return false; 140} 141 142#endif /* !CONFIG_APPLE_GMUX */ 143 144#endif /* LINUX_APPLE_GMUX_H */