2019-06-03 05:44:50 +00:00
|
|
|
/* SPDX-License-Identifier: GPL-2.0-only */
|
2016-01-11 19:09:20 +00:00
|
|
|
/*
|
|
|
|
* apple-gmux.h - microcontroller built into dual GPU MacBook Pro & Mac Pro
|
|
|
|
* Copyright (C) 2015 Lukas Wunner <lukas@wunner.de>
|
|
|
|
*/
|
|
|
|
|
|
|
|
#ifndef LINUX_APPLE_GMUX_H
|
|
|
|
#define LINUX_APPLE_GMUX_H
|
|
|
|
|
|
|
|
#include <linux/acpi.h>
|
2023-01-24 10:57:53 +00:00
|
|
|
#include <linux/io.h>
|
|
|
|
#include <linux/pnp.h>
|
2016-01-11 19:09:20 +00:00
|
|
|
|
|
|
|
#define GMUX_ACPI_HID "APP000B"
|
|
|
|
|
2023-01-24 10:57:52 +00:00
|
|
|
/*
|
|
|
|
* gmux port offsets. Many of these are not yet used, but may be in the
|
|
|
|
* future, and it's useful to have them documented here anyhow.
|
|
|
|
*/
|
|
|
|
#define GMUX_PORT_VERSION_MAJOR 0x04
|
|
|
|
#define GMUX_PORT_VERSION_MINOR 0x05
|
|
|
|
#define GMUX_PORT_VERSION_RELEASE 0x06
|
|
|
|
#define GMUX_PORT_SWITCH_DISPLAY 0x10
|
|
|
|
#define GMUX_PORT_SWITCH_GET_DISPLAY 0x11
|
|
|
|
#define GMUX_PORT_INTERRUPT_ENABLE 0x14
|
|
|
|
#define GMUX_PORT_INTERRUPT_STATUS 0x16
|
|
|
|
#define GMUX_PORT_SWITCH_DDC 0x28
|
|
|
|
#define GMUX_PORT_SWITCH_EXTERNAL 0x40
|
|
|
|
#define GMUX_PORT_SWITCH_GET_EXTERNAL 0x41
|
|
|
|
#define GMUX_PORT_DISCRETE_POWER 0x50
|
|
|
|
#define GMUX_PORT_MAX_BRIGHTNESS 0x70
|
|
|
|
#define GMUX_PORT_BRIGHTNESS 0x74
|
|
|
|
#define GMUX_PORT_VALUE 0xc2
|
|
|
|
#define GMUX_PORT_READ 0xd0
|
|
|
|
#define GMUX_PORT_WRITE 0xd4
|
|
|
|
|
platform/x86: apple-gmux: support MMIO gmux on T2 Macs
In some newer dual gpu MacBooks, the T2 Coprocessor functions as the
gmux, and the Intel side can interract with this new gmux type through
MMIO. Add support for these gmux controllers to the apple-gmux driver.
We start using the GMSP(0) acpi method on these gmux's when clearing
interrupts, as this prevents a flood of status=0 interrupts that can't
be cleared. It's unknown if this helps or hinders older gmux types, so
it isn't enabled for those.
Interestingly, the ACPI table only allocates 8 bytes for GMUX, but we
actually need 16, and as such we request 16 with request_mem_region.
Reading and writing from ports:
16 bytes from 0xfe0b0200 are used. 0x0 to 0x4 are where data
to read appears, and where data to write goes. Writing to 0xe
sets the gmux port being accessed, and writing to 0xf sends commands.
These commands are 0x40 & data_length for write, and data_length for
read, where data_length is 1, 2 or 4. Once byte base+0xf is 0, the
command is done.
Issues:
As with other retina models, we can't switch DDC lines so
switching at runtime doesn't work if the inactive gpu driver
already disabled eDP due to it not being connected when that
driver loaded.
Additionally, turning on the dgpu back on on the MacBookPro16,1 does
not work.
Reviewed-by: Hans de Goede <hdegoede@redhat.com>
Signed-off-by: Orlando Chamberlain <orlandoch.dev@gmail.com>
Link: https://lore.kernel.org/r/20230303112842.3094-4-orlandoch.dev@gmail.com
Signed-off-by: Hans de Goede <hdegoede@redhat.com>
2023-03-03 11:28:42 +00:00
|
|
|
#define GMUX_MMIO_PORT_SELECT 0x0e
|
|
|
|
#define GMUX_MMIO_COMMAND_SEND 0x0f
|
|
|
|
|
|
|
|
#define GMUX_MMIO_READ 0x00
|
|
|
|
#define GMUX_MMIO_WRITE 0x40
|
|
|
|
|
2023-01-24 10:57:52 +00:00
|
|
|
#define GMUX_MIN_IO_LEN (GMUX_PORT_BRIGHTNESS + 4)
|
|
|
|
|
2023-03-03 11:28:41 +00:00
|
|
|
enum apple_gmux_type {
|
|
|
|
APPLE_GMUX_TYPE_PIO,
|
|
|
|
APPLE_GMUX_TYPE_INDEXED,
|
platform/x86: apple-gmux: support MMIO gmux on T2 Macs
In some newer dual gpu MacBooks, the T2 Coprocessor functions as the
gmux, and the Intel side can interract with this new gmux type through
MMIO. Add support for these gmux controllers to the apple-gmux driver.
We start using the GMSP(0) acpi method on these gmux's when clearing
interrupts, as this prevents a flood of status=0 interrupts that can't
be cleared. It's unknown if this helps or hinders older gmux types, so
it isn't enabled for those.
Interestingly, the ACPI table only allocates 8 bytes for GMUX, but we
actually need 16, and as such we request 16 with request_mem_region.
Reading and writing from ports:
16 bytes from 0xfe0b0200 are used. 0x0 to 0x4 are where data
to read appears, and where data to write goes. Writing to 0xe
sets the gmux port being accessed, and writing to 0xf sends commands.
These commands are 0x40 & data_length for write, and data_length for
read, where data_length is 1, 2 or 4. Once byte base+0xf is 0, the
command is done.
Issues:
As with other retina models, we can't switch DDC lines so
switching at runtime doesn't work if the inactive gpu driver
already disabled eDP due to it not being connected when that
driver loaded.
Additionally, turning on the dgpu back on on the MacBookPro16,1 does
not work.
Reviewed-by: Hans de Goede <hdegoede@redhat.com>
Signed-off-by: Orlando Chamberlain <orlandoch.dev@gmail.com>
Link: https://lore.kernel.org/r/20230303112842.3094-4-orlandoch.dev@gmail.com
Signed-off-by: Hans de Goede <hdegoede@redhat.com>
2023-03-03 11:28:42 +00:00
|
|
|
APPLE_GMUX_TYPE_MMIO,
|
2023-03-03 11:28:41 +00:00
|
|
|
};
|
|
|
|
|
2016-02-10 13:17:41 +00:00
|
|
|
#if IS_ENABLED(CONFIG_APPLE_GMUX)
|
2023-01-24 10:57:53 +00:00
|
|
|
static inline bool apple_gmux_is_indexed(unsigned long iostart)
|
|
|
|
{
|
|
|
|
u16 val;
|
|
|
|
|
|
|
|
outb(0xaa, iostart + 0xcc);
|
|
|
|
outb(0x55, iostart + 0xcd);
|
|
|
|
outb(0x00, iostart + 0xce);
|
|
|
|
|
|
|
|
val = inb(iostart + 0xcc) | (inb(iostart + 0xcd) << 8);
|
|
|
|
if (val == 0x55aa)
|
|
|
|
return true;
|
|
|
|
|
|
|
|
return false;
|
|
|
|
}
|
2016-02-10 13:17:41 +00:00
|
|
|
|
platform/x86: apple-gmux: support MMIO gmux on T2 Macs
In some newer dual gpu MacBooks, the T2 Coprocessor functions as the
gmux, and the Intel side can interract with this new gmux type through
MMIO. Add support for these gmux controllers to the apple-gmux driver.
We start using the GMSP(0) acpi method on these gmux's when clearing
interrupts, as this prevents a flood of status=0 interrupts that can't
be cleared. It's unknown if this helps or hinders older gmux types, so
it isn't enabled for those.
Interestingly, the ACPI table only allocates 8 bytes for GMUX, but we
actually need 16, and as such we request 16 with request_mem_region.
Reading and writing from ports:
16 bytes from 0xfe0b0200 are used. 0x0 to 0x4 are where data
to read appears, and where data to write goes. Writing to 0xe
sets the gmux port being accessed, and writing to 0xf sends commands.
These commands are 0x40 & data_length for write, and data_length for
read, where data_length is 1, 2 or 4. Once byte base+0xf is 0, the
command is done.
Issues:
As with other retina models, we can't switch DDC lines so
switching at runtime doesn't work if the inactive gpu driver
already disabled eDP due to it not being connected when that
driver loaded.
Additionally, turning on the dgpu back on on the MacBookPro16,1 does
not work.
Reviewed-by: Hans de Goede <hdegoede@redhat.com>
Signed-off-by: Orlando Chamberlain <orlandoch.dev@gmail.com>
Link: https://lore.kernel.org/r/20230303112842.3094-4-orlandoch.dev@gmail.com
Signed-off-by: Hans de Goede <hdegoede@redhat.com>
2023-03-03 11:28:42 +00:00
|
|
|
static inline bool apple_gmux_is_mmio(unsigned long iostart)
|
|
|
|
{
|
2023-04-04 11:19:55 +00:00
|
|
|
u8 __iomem *iomem_base = ioremap(iostart, 16);
|
platform/x86: apple-gmux: support MMIO gmux on T2 Macs
In some newer dual gpu MacBooks, the T2 Coprocessor functions as the
gmux, and the Intel side can interract with this new gmux type through
MMIO. Add support for these gmux controllers to the apple-gmux driver.
We start using the GMSP(0) acpi method on these gmux's when clearing
interrupts, as this prevents a flood of status=0 interrupts that can't
be cleared. It's unknown if this helps or hinders older gmux types, so
it isn't enabled for those.
Interestingly, the ACPI table only allocates 8 bytes for GMUX, but we
actually need 16, and as such we request 16 with request_mem_region.
Reading and writing from ports:
16 bytes from 0xfe0b0200 are used. 0x0 to 0x4 are where data
to read appears, and where data to write goes. Writing to 0xe
sets the gmux port being accessed, and writing to 0xf sends commands.
These commands are 0x40 & data_length for write, and data_length for
read, where data_length is 1, 2 or 4. Once byte base+0xf is 0, the
command is done.
Issues:
As with other retina models, we can't switch DDC lines so
switching at runtime doesn't work if the inactive gpu driver
already disabled eDP due to it not being connected when that
driver loaded.
Additionally, turning on the dgpu back on on the MacBookPro16,1 does
not work.
Reviewed-by: Hans de Goede <hdegoede@redhat.com>
Signed-off-by: Orlando Chamberlain <orlandoch.dev@gmail.com>
Link: https://lore.kernel.org/r/20230303112842.3094-4-orlandoch.dev@gmail.com
Signed-off-by: Hans de Goede <hdegoede@redhat.com>
2023-03-03 11:28:42 +00:00
|
|
|
u8 val;
|
|
|
|
|
|
|
|
if (!iomem_base)
|
|
|
|
return false;
|
|
|
|
|
|
|
|
/*
|
|
|
|
* If this is 0xff, then gmux must not be present, as the gmux would
|
|
|
|
* reset it to 0x00, or it would be one of 0x1, 0x4, 0x41, 0x44 if a
|
|
|
|
* command is currently being processed.
|
|
|
|
*/
|
|
|
|
val = ioread8(iomem_base + GMUX_MMIO_COMMAND_SEND);
|
|
|
|
iounmap(iomem_base);
|
|
|
|
return (val != 0xff);
|
|
|
|
}
|
|
|
|
|
2016-01-11 19:09:20 +00:00
|
|
|
/**
|
2023-01-24 10:57:53 +00:00
|
|
|
* apple_gmux_detect() - detect if gmux is built into the machine
|
|
|
|
*
|
|
|
|
* @pnp_dev: Device to probe or NULL to use the first matching device
|
2023-03-09 10:43:54 +00:00
|
|
|
* @type_ret: Returns (by reference) the apple_gmux_type of the device
|
2023-01-24 10:57:53 +00:00
|
|
|
*
|
|
|
|
* Detect if a supported gmux device is present by actually probing it.
|
|
|
|
* This avoids the false positives returned on some models by
|
|
|
|
* apple_gmux_present().
|
|
|
|
*
|
|
|
|
* Return: %true if a supported gmux ACPI device is detected and the kernel
|
|
|
|
* was configured with CONFIG_APPLE_GMUX, %false otherwise.
|
|
|
|
*/
|
2023-03-03 11:28:41 +00:00
|
|
|
static inline bool apple_gmux_detect(struct pnp_dev *pnp_dev, enum apple_gmux_type *type_ret)
|
2023-01-24 10:57:53 +00:00
|
|
|
{
|
|
|
|
u8 ver_major, ver_minor, ver_release;
|
|
|
|
struct device *dev = NULL;
|
|
|
|
struct acpi_device *adev;
|
|
|
|
struct resource *res;
|
2023-03-03 11:28:41 +00:00
|
|
|
enum apple_gmux_type type = APPLE_GMUX_TYPE_PIO;
|
2023-01-24 10:57:53 +00:00
|
|
|
bool ret = false;
|
|
|
|
|
|
|
|
if (!pnp_dev) {
|
|
|
|
adev = acpi_dev_get_first_match_dev(GMUX_ACPI_HID, NULL, -1);
|
|
|
|
if (!adev)
|
|
|
|
return false;
|
|
|
|
|
|
|
|
dev = get_device(acpi_get_first_physical_node(adev));
|
|
|
|
acpi_dev_put(adev);
|
|
|
|
if (!dev)
|
|
|
|
return false;
|
|
|
|
|
|
|
|
pnp_dev = to_pnp_dev(dev);
|
|
|
|
}
|
|
|
|
|
|
|
|
res = pnp_get_resource(pnp_dev, IORESOURCE_IO, 0);
|
platform/x86: apple-gmux: support MMIO gmux on T2 Macs
In some newer dual gpu MacBooks, the T2 Coprocessor functions as the
gmux, and the Intel side can interract with this new gmux type through
MMIO. Add support for these gmux controllers to the apple-gmux driver.
We start using the GMSP(0) acpi method on these gmux's when clearing
interrupts, as this prevents a flood of status=0 interrupts that can't
be cleared. It's unknown if this helps or hinders older gmux types, so
it isn't enabled for those.
Interestingly, the ACPI table only allocates 8 bytes for GMUX, but we
actually need 16, and as such we request 16 with request_mem_region.
Reading and writing from ports:
16 bytes from 0xfe0b0200 are used. 0x0 to 0x4 are where data
to read appears, and where data to write goes. Writing to 0xe
sets the gmux port being accessed, and writing to 0xf sends commands.
These commands are 0x40 & data_length for write, and data_length for
read, where data_length is 1, 2 or 4. Once byte base+0xf is 0, the
command is done.
Issues:
As with other retina models, we can't switch DDC lines so
switching at runtime doesn't work if the inactive gpu driver
already disabled eDP due to it not being connected when that
driver loaded.
Additionally, turning on the dgpu back on on the MacBookPro16,1 does
not work.
Reviewed-by: Hans de Goede <hdegoede@redhat.com>
Signed-off-by: Orlando Chamberlain <orlandoch.dev@gmail.com>
Link: https://lore.kernel.org/r/20230303112842.3094-4-orlandoch.dev@gmail.com
Signed-off-by: Hans de Goede <hdegoede@redhat.com>
2023-03-03 11:28:42 +00:00
|
|
|
if (res && resource_size(res) >= GMUX_MIN_IO_LEN) {
|
|
|
|
/*
|
|
|
|
* Invalid version information may indicate either that the gmux
|
|
|
|
* device isn't present or that it's a new one that uses indexed io.
|
|
|
|
*/
|
|
|
|
ver_major = inb(res->start + GMUX_PORT_VERSION_MAJOR);
|
|
|
|
ver_minor = inb(res->start + GMUX_PORT_VERSION_MINOR);
|
|
|
|
ver_release = inb(res->start + GMUX_PORT_VERSION_RELEASE);
|
|
|
|
if (ver_major == 0xff && ver_minor == 0xff && ver_release == 0xff) {
|
|
|
|
if (apple_gmux_is_indexed(res->start))
|
|
|
|
type = APPLE_GMUX_TYPE_INDEXED;
|
|
|
|
else
|
|
|
|
goto out;
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
res = pnp_get_resource(pnp_dev, IORESOURCE_MEM, 0);
|
|
|
|
if (res && apple_gmux_is_mmio(res->start))
|
|
|
|
type = APPLE_GMUX_TYPE_MMIO;
|
2023-03-03 11:28:41 +00:00
|
|
|
else
|
2023-01-24 10:57:53 +00:00
|
|
|
goto out;
|
|
|
|
}
|
|
|
|
|
2023-03-03 11:28:41 +00:00
|
|
|
if (type_ret)
|
|
|
|
*type_ret = type;
|
2023-01-24 10:57:53 +00:00
|
|
|
|
|
|
|
ret = true;
|
|
|
|
out:
|
|
|
|
put_device(dev);
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* apple_gmux_present() - check if gmux ACPI device is present
|
2016-01-11 19:09:20 +00:00
|
|
|
*
|
|
|
|
* Drivers may use this to activate quirks specific to dual GPU MacBook Pros
|
|
|
|
* and Mac Pros, e.g. for deferred probing, runtime pm and backlight.
|
|
|
|
*
|
2023-01-24 10:57:53 +00:00
|
|
|
* Return: %true if gmux ACPI device is present and the kernel was configured
|
2016-01-11 19:09:20 +00:00
|
|
|
* with CONFIG_APPLE_GMUX, %false otherwise.
|
|
|
|
*/
|
|
|
|
static inline bool apple_gmux_present(void)
|
|
|
|
{
|
2016-03-24 12:15:20 +00:00
|
|
|
return acpi_dev_found(GMUX_ACPI_HID);
|
2016-01-11 19:09:20 +00:00
|
|
|
}
|
|
|
|
|
2016-02-10 13:17:41 +00:00
|
|
|
#else /* !CONFIG_APPLE_GMUX */
|
|
|
|
|
|
|
|
static inline bool apple_gmux_present(void)
|
|
|
|
{
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2023-01-24 10:57:53 +00:00
|
|
|
static inline bool apple_gmux_detect(struct pnp_dev *pnp_dev, bool *indexed_ret)
|
|
|
|
{
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2016-02-10 13:17:41 +00:00
|
|
|
#endif /* !CONFIG_APPLE_GMUX */
|
|
|
|
|
2016-01-11 19:09:20 +00:00
|
|
|
#endif /* LINUX_APPLE_GMUX_H */
|