summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSeth Forshee <seth.forshee@canonical.com>2012-09-07 10:22:08 -0500
committerDave Airlie <airlied@gmail.com>2012-10-04 06:27:35 -0400
commit43ea112369efe8952fdbd60037013e081b0dcdc6 (patch)
treee1e74f4a29fc06cb00a19e2f26345d64cad4d8e0
parent08779d76e62a50dac980b3c643c04684dbf27bee (diff)
drm/edid: Switch DDC when reading the EDID
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. Signed-off-by: Seth Forshee <seth.forshee@canonical.com> Signed-off-by: Dave Airlie <airlied@gmail.com>
-rw-r--r--drivers/gpu/drm/drm_edid.c17
1 files changed, 17 insertions, 0 deletions
diff --git a/drivers/gpu/drm/drm_edid.c b/drivers/gpu/drm/drm_edid.c
index 289c9b18c0d3..76810eae934d 100644
--- a/drivers/gpu/drm/drm_edid.c
+++ b/drivers/gpu/drm/drm_edid.c
@@ -31,6 +31,7 @@
#include <linux/slab.h>
#include <linux/i2c.h>
#include <linux/module.h>
+#include <linux/vga_switcheroo.h>
#include "drmP.h"
#include "drm_edid.h"
#include "drm_edid_modes.h"
@@ -82,6 +83,8 @@ struct detailed_mode_closure {
#define LEVEL_GTF2 2
#define LEVEL_CVT 3
+static DEFINE_MUTEX(drm_edid_mutex);
+
static struct edid_quirk {
char vendor[4];
int product_id;
@@ -417,10 +420,24 @@ struct edid *drm_get_edid(struct drm_connector *connector,
struct i2c_adapter *adapter)
{
struct edid *edid = NULL;
+ struct pci_dev *pdev = connector->dev->pdev;
+ struct pci_dev *active_pdev = NULL;
+
+ mutex_lock(&drm_edid_mutex);
+
+ if (pdev) {
+ active_pdev = vga_switcheroo_get_active_client();
+ if (active_pdev != pdev)
+ vga_switcheroo_switch_ddc(pdev);
+ }
if (drm_probe_ddc(adapter))
edid = (struct edid *)drm_do_get_edid(connector, adapter);
+ if (active_pdev && active_pdev != pdev)
+ vga_switcheroo_switch_ddc(active_pdev);
+
+ mutex_unlock(&drm_edid_mutex);
return edid;
}
EXPORT_SYMBOL(drm_get_edid);