MacBook Pro hybrid graphics use a gmux chip to switch DDC lines between
gpus. It may register after the i915 driver, necessitating a reprobe of
the connectors and reinitialization of the fbdev.

Inspired by Matthew Garrett, who duplicated intel_setup_outputs() and
reduced it to just the eDP probing portion (which is not sufficient
since pre-retina MBPs used LVDS):
http://www.codon.org.uk/~mjg59/tmp/retina_patches/0024-i915-Add-support-for-reprobing-for-a-panel.patch

Commit 92122789b2d699a1e82dca502940e0dd37bf6f3b (drm/i915: preserve SSC
if previously set v3) sets lvds_use_ssc to 0, it must be reset to 1 so
that the SSC gets used on the panel.

Signed-off-by: Lukas Wunner <lukas at wunner.de>
---
 drivers/gpu/drm/i915/i915_dma.c      | 40 ++++++++++++++++++++++++++++++++++++
 drivers/gpu/drm/i915/i915_drv.h      |  1 +
 drivers/gpu/drm/i915/intel_display.c |  2 +-
 3 files changed, 42 insertions(+), 1 deletion(-)

diff --git a/drivers/gpu/drm/i915/i915_dma.c b/drivers/gpu/drm/i915/i915_dma.c
index 68e0c85..86726b7 100644
--- a/drivers/gpu/drm/i915/i915_dma.c
+++ b/drivers/gpu/drm/i915/i915_dma.c
@@ -379,9 +379,49 @@ static bool i915_switcheroo_can_switch(struct pci_dev 
*pdev)
        return dev->open_count == 0;
 }

+static void i915_switcheroo_reprobe_connectors(struct pci_dev *pdev)
+{
+       struct drm_device *dev = pci_get_drvdata(pdev);
+       struct drm_i915_private *dev_priv = dev->dev_private;
+       struct intel_encoder *encoder;
+
+       /*
+        * Check whether we've already found a panel.
+        * If so, we don't need to reprobe
+        */
+       for_each_intel_encoder(dev, encoder)
+               if (encoder->type == INTEL_OUTPUT_LVDS ||
+                   encoder->type == INTEL_OUTPUT_EDP)
+                       return;
+
+       /*
+        * intel_modeset_gem_init() sets lvds_use_ssc to 0,
+        * reset to 1 so that the SSC gets used on the panel
+        */
+       dev_priv->vbt.lvds_use_ssc =
+               !(i915.panel_use_ssc == 0 ||
+                 dev_priv->quirks & QUIRK_LVDS_SSC_DISABLE);
+       intel_setup_outputs(dev);
+
+       /* Destroy default 1024x768 fbdev and reinitialize */
+       intel_fbdev_fini(dev);
+       if (intel_fbdev_init(dev))
+               goto cleanup_gem;
+       async_schedule(intel_fbdev_initial_config, dev_priv);
+       return;
+
+cleanup_gem:
+       DRM_ERROR("failed to reinitialize fbdev\n");
+       mutex_lock(&dev->struct_mutex);
+       i915_gem_cleanup_ringbuffer(dev);
+       i915_gem_context_fini(dev);
+       mutex_unlock(&dev->struct_mutex);
+}
+
 static const struct vga_switcheroo_client_ops i915_switcheroo_ops = {
        .set_gpu_state = i915_switcheroo_set_state,
        .reprobe = NULL,
+       .reprobe_connectors = i915_switcheroo_reprobe_connectors,
        .can_switch = i915_switcheroo_can_switch,
 };

diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h
index e326ac9..7f58858 100644
--- a/drivers/gpu/drm/i915/i915_drv.h
+++ b/drivers/gpu/drm/i915/i915_drv.h
@@ -3120,6 +3120,7 @@ extern void intel_set_memory_cxsr(struct drm_i915_private 
*dev_priv,
 extern void intel_detect_pch(struct drm_device *dev);
 extern int intel_trans_dp_port_sel(struct drm_crtc *crtc);
 extern int intel_enable_rc6(const struct drm_device *dev);
+extern void intel_setup_outputs(struct drm_device *dev);

 extern bool i915_semaphore_is_enabled(struct drm_device *dev);
 int i915_reg_read_ioctl(struct drm_device *dev, void *data,
diff --git a/drivers/gpu/drm/i915/intel_display.c 
b/drivers/gpu/drm/i915/intel_display.c
index d547d9c8..9481206 100644
--- a/drivers/gpu/drm/i915/intel_display.c
+++ b/drivers/gpu/drm/i915/intel_display.c
@@ -13027,7 +13027,7 @@ static bool intel_crt_present(struct drm_device *dev)
        return true;
 }

-static void intel_setup_outputs(struct drm_device *dev)
+void intel_setup_outputs(struct drm_device *dev)
 {
        struct drm_i915_private *dev_priv = dev->dev_private;
        struct intel_encoder *encoder;
-- 
1.8.5.2 (Apple Git-48)

Reply via email to