aboutsummaryrefslogtreecommitdiff
path: root/src/drivers/apple/hybrid_graphics/gmux.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/drivers/apple/hybrid_graphics/gmux.c')
-rw-r--r--src/drivers/apple/hybrid_graphics/gmux.c138
1 files changed, 138 insertions, 0 deletions
diff --git a/src/drivers/apple/hybrid_graphics/gmux.c b/src/drivers/apple/hybrid_graphics/gmux.c
new file mode 100644
index 0000000000..e3788b2436
--- /dev/null
+++ b/src/drivers/apple/hybrid_graphics/gmux.c
@@ -0,0 +1,138 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+
+#include <delay.h>
+#include <arch/io.h>
+#include <device/device.h>
+#include "gmux.h"
+#include "chip.h"
+
+static int gmux_index_wait_ready(void)
+{
+ int i = 200;
+ u8 gwr = inb(GMUX_IOSTART + GMUX_PORT_WRITE);
+
+ while (i && (gwr & 0x01)) {
+ inb(GMUX_IOSTART + GMUX_PORT_READ);
+ gwr = inb(GMUX_IOSTART + GMUX_PORT_WRITE);
+ udelay(100);
+ i--;
+ }
+
+ return !!i;
+}
+
+static int gmux_index_wait_complete(void)
+{
+ int i = 200;
+ u8 gwr = inb(GMUX_IOSTART + GMUX_PORT_WRITE);
+
+ while (i && !(gwr & 0x01)) {
+ gwr = inb(GMUX_IOSTART + GMUX_PORT_WRITE);
+ udelay(100);
+ i--;
+ }
+
+ if (gwr & 0x01)
+ inb(GMUX_IOSTART + GMUX_PORT_READ);
+
+ return !!i;
+}
+
+u8 gmux_pio_read8(u8 port)
+{
+ return inb(GMUX_IOSTART + port);
+}
+
+u8 gmux_index_read8(u8 port)
+{
+ u8 val;
+
+ gmux_index_wait_ready();
+ outb(port, GMUX_IOSTART + GMUX_PORT_READ);
+ gmux_index_wait_complete();
+ val = inb(GMUX_IOSTART + GMUX_PORT_VALUE);
+
+ return val;
+}
+
+void gmux_pio_write8(u8 port, u8 val)
+{
+ outb(val, GMUX_IOSTART + port);
+}
+
+void gmux_index_write8(u8 port, u8 val)
+{
+ outb(val, GMUX_IOSTART + GMUX_PORT_VALUE);
+ gmux_index_wait_ready();
+ outb(port, GMUX_IOSTART + GMUX_PORT_WRITE);
+ gmux_index_wait_complete();
+}
+
+u32 gmux_pio_read32(u8 port)
+{
+ return inl(GMUX_IOSTART + port);
+}
+
+u32 gmux_index_read32(u8 port)
+{
+ u32 val;
+
+ gmux_index_wait_ready();
+ outb(port, GMUX_IOSTART + GMUX_PORT_READ);
+ gmux_index_wait_complete();
+ val = inl(GMUX_IOSTART + GMUX_PORT_VALUE);
+
+ return val;
+}
+
+u8 gmux_read8(const struct device *dev, u8 port)
+{
+ const struct drivers_apple_hybrid_graphics_config
+ *config = dev->chip_info;
+ if (config->gmux_indexed)
+ return gmux_index_read8(port);
+ else
+ return gmux_pio_read8(port);
+}
+
+void gmux_write8(const struct device *dev, u8 port, u8 val)
+{
+ const struct drivers_apple_hybrid_graphics_config
+ *config = dev->chip_info;
+ if (config->gmux_indexed)
+ gmux_index_write8(port, val);
+ else
+ gmux_pio_write8(port, val);
+}
+
+u32 gmux_read32(const struct device *dev, u8 port)
+{
+ const struct drivers_apple_hybrid_graphics_config
+ *config = dev->chip_info;
+ if (config->gmux_indexed)
+ return gmux_index_read32(port);
+ else
+ return gmux_pio_read32(port);
+}
+
+void gmux_dgpu_power_enable(const struct device *dev, bool enable)
+{
+ if (enable) {
+ gmux_write8(dev, GMUX_PORT_DISCRETE_POWER, 1);
+ gmux_write8(dev, GMUX_PORT_DISCRETE_POWER, 3);
+ } else {
+ gmux_write8(dev, GMUX_PORT_DISCRETE_POWER, 1);
+ gmux_write8(dev, GMUX_PORT_DISCRETE_POWER, 0);
+ }
+}
+
+void gmux_switch(const struct device *dev, bool dgpu)
+{
+ if (dgpu) {
+ gmux_write8(dev, GMUX_PORT_SWITCH_DDC, 2);
+ gmux_write8(dev, GMUX_PORT_SWITCH_DISPLAY, 3);
+ } else {
+ gmux_write8(dev, GMUX_PORT_SWITCH_DDC, 1);
+ gmux_write8(dev, GMUX_PORT_SWITCH_DISPLAY, 2);
+ }
+}