Commit 5cb8eaa2 authored by Lukas Wunner's avatar Lukas Wunner Committed by Daniel Vetter

drm/edid: Switch DDC when reading the EDID

Originally by Seth Forshee <seth.forshee@canonical.com>, 2012-10-04:
    Some dual graphics machines support muxing the DDC separately from
    the display, so make use of this functionality when reading the EDID
    on the inactive GPU. Also serialize drm_get_edid() with a mutex to
    avoid races on the DDC mux state.

Modified by Dave Airlie <airlied@gmail.com>, 2012-12-22:
    I can't figure out why I didn't like this, but I rewrote this [...]
    to lock/unlock the ddc lines [...]. I think I'd prefer something
    like that otherwise the interface got really ugly.

Modified by Lukas Wunner <lukas@wunner.de>, 2015-04 - 2015-09:
    v3:   Move vga_switcheroo calls to a wrapper around drm_get_edid()
          which drivers can call on muxed machines. This avoids other
          drivers having to go through the vga_switcheroo motions even
          though they are never used on a muxed platform
          (Thierry Reding, Daniel Vetter, Alex Deucher)

Bugzilla: https://bugzilla.kernel.org/show_bug.cgi?id=88861
Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=61115Tested-by: default avatarPierre Moreau <pierre.morrow@free.fr>
    [MBP  5,3 2009  nvidia MCP79 + G96        pre-retina  15"]
Tested-by: default avatarWilliam Brown <william@blackhats.net.au>
    [MBP  8,2 2011  intel SNB + amd turks     pre-retina  15"]
Tested-by: default avatarLukas Wunner <lukas@wunner.de>
    [MBP  9,1 2012  intel IVB + nvidia GK107  pre-retina  15"]
Cc: Seth Forshee <seth.forshee@canonical.com>
Cc: Dave Airlie <airlied@gmail.com>
Signed-off-by: default avatarLukas Wunner <lukas@wunner.de>
Signed-off-by: default avatarDaniel Vetter <daniel.vetter@ffwll.ch>
Link: http://patchwork.freedesktop.org/patch/msgid/b898d0da4c134f2642d0122479006863e1830723.1452525860.git.lukas@wunner.de
parent f798d965
...@@ -32,6 +32,7 @@ ...@@ -32,6 +32,7 @@
#include <linux/hdmi.h> #include <linux/hdmi.h>
#include <linux/i2c.h> #include <linux/i2c.h>
#include <linux/module.h> #include <linux/module.h>
#include <linux/vga_switcheroo.h>
#include <drm/drmP.h> #include <drm/drmP.h>
#include <drm/drm_edid.h> #include <drm/drm_edid.h>
#include <drm/drm_displayid.h> #include <drm/drm_displayid.h>
...@@ -1394,6 +1395,31 @@ struct edid *drm_get_edid(struct drm_connector *connector, ...@@ -1394,6 +1395,31 @@ struct edid *drm_get_edid(struct drm_connector *connector,
} }
EXPORT_SYMBOL(drm_get_edid); EXPORT_SYMBOL(drm_get_edid);
/**
* drm_get_edid_switcheroo - get EDID data for a vga_switcheroo output
* @connector: connector we're probing
* @adapter: I2C adapter to use for DDC
*
* Wrapper around drm_get_edid() for laptops with dual GPUs using one set of
* outputs. The wrapper adds the requisite vga_switcheroo calls to temporarily
* switch DDC to the GPU which is retrieving EDID.
*
* Return: Pointer to valid EDID or %NULL if we couldn't find any.
*/
struct edid *drm_get_edid_switcheroo(struct drm_connector *connector,
struct i2c_adapter *adapter)
{
struct pci_dev *pdev = connector->dev->pdev;
struct edid *edid;
vga_switcheroo_lock_ddc(pdev);
edid = drm_get_edid(connector, adapter);
vga_switcheroo_unlock_ddc(pdev);
return edid;
}
EXPORT_SYMBOL(drm_get_edid_switcheroo);
/** /**
* drm_edid_duplicate - duplicate an EDID and the extensions * drm_edid_duplicate - duplicate an EDID and the extensions
* @edid: EDID to duplicate * @edid: EDID to duplicate
......
...@@ -2296,6 +2296,8 @@ extern void drm_property_destroy_user_blobs(struct drm_device *dev, ...@@ -2296,6 +2296,8 @@ extern void drm_property_destroy_user_blobs(struct drm_device *dev,
extern bool drm_probe_ddc(struct i2c_adapter *adapter); extern bool drm_probe_ddc(struct i2c_adapter *adapter);
extern struct edid *drm_get_edid(struct drm_connector *connector, extern struct edid *drm_get_edid(struct drm_connector *connector,
struct i2c_adapter *adapter); struct i2c_adapter *adapter);
extern struct edid *drm_get_edid_switcheroo(struct drm_connector *connector,
struct i2c_adapter *adapter);
extern struct edid *drm_edid_duplicate(const struct edid *edid); extern struct edid *drm_edid_duplicate(const struct edid *edid);
extern int drm_add_edid_modes(struct drm_connector *connector, struct edid *edid); extern int drm_add_edid_modes(struct drm_connector *connector, struct edid *edid);
extern void drm_mode_config_init(struct drm_device *dev); extern void drm_mode_config_init(struct drm_device *dev);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment