@@ -417,6 +417,25 @@ static int gmux_switchto(enum vga_switcheroo_client_id id)
return 0;
}
+static int gmux_switch_ddc(enum vga_switcheroo_client_id id)
+{
+ enum vga_switcheroo_client_id old_ddc_owner =
+ apple_gmux_data->switch_state_ddc;
+
+ if (id == old_ddc_owner)
+ return id;
+
+ pr_debug("Switching DDC from %d to %d\n", old_ddc_owner, id);
+ apple_gmux_data->switch_state_ddc = id;
+
+ if (id == VGA_SWITCHEROO_IGD)
+ gmux_write8(apple_gmux_data, GMUX_PORT_SWITCH_DDC, 1);
+ else
+ gmux_write8(apple_gmux_data, GMUX_PORT_SWITCH_DDC, 2);
+
+ return old_ddc_owner;
+}
+
/**
* DOC: Power control
*
@@ -474,12 +493,19 @@ static int gmux_get_client_id(struct pci_dev *pdev)
return VGA_SWITCHEROO_DIS;
}
-static const struct vga_switcheroo_handler gmux_handler = {
+static const struct vga_switcheroo_handler gmux_handler_indexed = {
.switchto = gmux_switchto,
.power_state = gmux_set_power_state,
.get_client_id = gmux_get_client_id,
};
+static const struct vga_switcheroo_handler gmux_handler_classic = {
+ .switchto = gmux_switchto,
+ .switch_ddc = gmux_switch_ddc,
+ .power_state = gmux_set_power_state,
+ .get_client_id = gmux_get_client_id,
+};
+
/**
* DOC: Interrupt
*
@@ -730,8 +756,21 @@ static int gmux_probe(struct pnp_dev *pnp, const struct pnp_device_id *id)
gmux_enable_interrupts(gmux_data);
gmux_read_switch_state(gmux_data);
- if (vga_switcheroo_register_handler(&gmux_handler, 0)) {
- ret = -ENODEV;
+ /*
+ * Retina MacBook Pros cannot switch the panel's AUX separately
+ * and need eDP pre-calibration. They are distinguishable from
+ * pre-retinas by having an "indexed" gmux.
+ *
+ * Pre-retina MacBook Pros can switch the panel's DDC separately.
+ */
+ if (gmux_data->indexed)
+ ret = vga_switcheroo_register_handler(&gmux_handler_indexed,
+ VGA_SWITCHEROO_NEEDS_EDP_CONFIG);
+ else
+ ret = vga_switcheroo_register_handler(&gmux_handler_classic,
+ VGA_SWITCHEROO_CAN_SWITCH_DDC);
+ if (ret) {
+ pr_err("Failed to register vga_switcheroo handler\n");
goto err_register_handler;
}