Lukas Wunner
2015-Oct-05 13:26 UTC
[Nouveau] [PATCH v3 5/6] drm/nouveau: Switch DDC when reading the EDID
The pre-retina MacBook Pro uses an LVDS panel and a gmux controller to switch the panel between its two GPUs. The panel mode in VBIOS is notoriously bogus on these machines. Use drm_get_edid_switcheroo() in lieu of drm_get_edid() on LVDS. This allows us to retrieve the EDID if the outputs are currently muxed to the other GPU by temporarily switching the panel's DDC lines. Likewise, ask vga_switcheroo to switch DDC before probing LVDS connectors. This only enables EDID probing on the pre-retina MBP (2008 - 2013). The retina MBP (2012 - present) uses eDP and gmux is apparently not capable of switching AUX separately from the main link on these models. This will be addressed in later patches. List of pre-retina MBPs with dual GPUs, either or both Nvidia: [MBP 5,1 2008 nvidia MCP79 + G96 pre-retina 15"] [MBP 5,2 2009 nvidia MCP79 + G96 pre-retina 17"] [MBP 5,3 2009 nvidia MCP79 + G96 pre-retina 15"] [MBP 6,2 2010 intel ILK + nvidia GT216 pre-retina 15"] [MBP 6,1 2010 intel ILK + nvidia GT216 pre-retina 17"] [MBP 9,1 2012 intel IVB + nvidia GK107 pre-retina 15"] Bugzilla: https://bugzilla.kernel.org/show_bug.cgi?id=88861 Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=61115 Tested-by: Pierre Moreau <pierre.morrow at free.fr> [MBP 5,3 2009 nvidia MCP79 + G96 pre-retina 15"] Tested-by: Lukas Wunner <lukas at wunner.de> [MBP 9,1 2012 intel IVB + nvidia GK107 pre-retina 15"] Signed-off-by: Lukas Wunner <lukas at wunner.de> --- drivers/gpu/drm/nouveau/nouveau_connector.c | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/nouveau/nouveau_connector.c b/drivers/gpu/drm/nouveau/nouveau_connector.c index 2e7cbe9..b3b0ca5 100644 --- a/drivers/gpu/drm/nouveau/nouveau_connector.c +++ b/drivers/gpu/drm/nouveau/nouveau_connector.c @@ -27,6 +27,7 @@ #include <acpi/button.h> #include <linux/pm_runtime.h> +#include <linux/vga_switcheroo.h> #include <drm/drmP.h> #include <drm/drm_edid.h> @@ -148,7 +149,13 @@ nouveau_connector_ddc_detect(struct drm_connector *connector) break; } else if (nv_encoder->i2c) { - if (nvkm_probe_i2c(nv_encoder->i2c, 0x50)) + int ret; + if (nv_encoder->dcb->type == DCB_OUTPUT_LVDS) + vga_switcheroo_lock_ddc(dev->pdev); + ret = nvkm_probe_i2c(nv_encoder->i2c, 0x50); + if (nv_encoder->dcb->type == DCB_OUTPUT_LVDS) + vga_switcheroo_unlock_ddc(dev->pdev); + if (ret) break; } } @@ -259,7 +266,9 @@ nouveau_connector_detect(struct drm_connector *connector, bool force) nv_encoder = nouveau_connector_ddc_detect(connector); if (nv_encoder && (i2c = nv_encoder->i2c) != NULL) { - nv_connector->edid = drm_get_edid(connector, i2c); + nv_connector->edid = nv_encoder->dcb->type == DCB_OUTPUT_LVDS ? + drm_get_edid_switcheroo(connector, i2c) : + drm_get_edid(connector, i2c); drm_mode_connector_update_edid_property(connector, nv_connector->edid); if (!nv_connector->edid) { -- 1.8.5.2 (Apple Git-48)