The retina MacBook Pro uses an eDP panel and a gmux controller to switch the panel between its two GPUs. Unfortunately it seems that it cannot switch the AUX channel separately from the main link. But we can emulate switching of DDC/AUX in software by using the active client as a proxy to talk to the panel. When reading the DPCD or EDID, store the struct drm_dp_aux and struct i2c_adapter (for DDC) in vga_switcheroo. Retrieve the active client's structures and use them in lieu of the client's own structures. To avoid using proxying with external DP-connected displays, this is constrained to eDP connectors and further constrained by vga_switcheroo to its clients. Based (loosely) on patches by Matthew Garrett <mjg59@xxxxxxxxxxxxx> who used stashing instead of proxying and changed each driver rather than the generic helper functions: http://www.codon.org.uk/~mjg59/tmp/retina_patches/0025-i915-Use-vga_switcheroo-to-obtain-and-stash-EDID-DPC.patch http://www.codon.org.uk/~mjg59/tmp/retina_patches/0026-nouveau-Use-vga_switcheroo-to-obtain-and-stash-EDID-.patch Bugzilla: https://bugzilla.kernel.org/show_bug.cgi?id=88861 Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=61115 Tested-by: Paul Hordiienko <pvt.gord@xxxxxxxxx> [MBP 6,2 2010 intel ILK + nvidia GT216 pre-retina] Tested-by: William Brown <william@xxxxxxxxxxxxxxxx> [MBP 8,2 2011 intel SNB + amd turks pre-retina] Tested-by: Lukas Wunner <lukas@xxxxxxxxx> [MBP 9,1 2012 intel IVB + nvidia GK107 pre-retina] Tested-by: Bruno Bierbaumer <bruno@xxxxxxxxxxxxxx> [MBP 11,3 2013 intel HSW + nvidia GK107 retina -- work in progress] Signed-off-by: Lukas Wunner <lukas@xxxxxxxxx> --- drivers/gpu/drm/drm_dp_helper.c | 14 ++++++++++++++ drivers/gpu/drm/drm_edid.c | 12 ++++++++++++ 2 files changed, 26 insertions(+) diff --git a/drivers/gpu/drm/drm_dp_helper.c b/drivers/gpu/drm/drm_dp_helper.c index 80a02a4..f34622f 100644 --- a/drivers/gpu/drm/drm_dp_helper.c +++ b/drivers/gpu/drm/drm_dp_helper.c @@ -27,6 +27,7 @@ #include <linux/errno.h> #include <linux/sched.h> #include <linux/i2c.h> +#include <linux/vga_switcheroo.h> #include <drm/drm_dp_helper.h> #include <drm/drmP.h> @@ -239,6 +240,19 @@ static int drm_dp_dpcd_access(struct drm_dp_aux *aux, u8 request, ssize_t drm_dp_dpcd_read(struct drm_dp_aux *aux, unsigned int offset, void *buffer, size_t size) { + struct pci_dev *pdev = to_pci_dev(aux->dev); + struct drm_dp_aux *proxy_aux; + + if (aux->connector && + aux->connector->connector_type == DRM_MODE_CONNECTOR_eDP) { + vga_switcheroo_set_aux(pdev, aux); + proxy_aux = vga_switcheroo_get_aux(pdev); + if (proxy_aux && proxy_aux != aux) { + DRM_DEBUG_KMS("Using vga_switcheroo active client as proxy\n"); + aux = proxy_aux; + } + } + return drm_dp_dpcd_access(aux, DP_AUX_NATIVE_READ, offset, buffer, size); } diff --git a/drivers/gpu/drm/drm_edid.c b/drivers/gpu/drm/drm_edid.c index cdb2fa1..b4b0e01 100644 --- a/drivers/gpu/drm/drm_edid.c +++ b/drivers/gpu/drm/drm_edid.c @@ -1379,6 +1379,18 @@ struct edid *drm_get_edid(struct drm_connector *connector, { struct edid *edid; struct pci_dev *pdev = connector->dev->pdev; + struct i2c_adapter *proxy_ddc; + + if (connector->connector_type == DRM_MODE_CONNECTOR_LVDS || + connector->connector_type == DRM_MODE_CONNECTOR_eDP) { + vga_switcheroo_set_ddc(pdev, adapter); + proxy_ddc = vga_switcheroo_get_ddc(pdev); + if (proxy_ddc && proxy_ddc != adapter) { + DRM_DEBUG_KMS("Using vga_switcheroo active client as proxy\n"); + adapter = proxy_ddc; + pdev = to_pci_dev(proxy_ddc->dev.parent); + } + } vga_switcheroo_lock_ddc(pdev); -- 1.8.5.2 (Apple Git-48) _______________________________________________ dri-devel mailing list dri-devel@xxxxxxxxxxxxxxxxxxxxx http://lists.freedesktop.org/mailman/listinfo/dri-devel