All of lore.kernel.org
 help / color / mirror / Atom feed
* Improve Apple GMUX support on switcheroo
@ 2014-06-01 16:38 Matthew Garrett
  2014-06-01 16:38 ` [PATCH 01/11] vga_switcheroo: Add support for switching only the DDC Matthew Garrett
                   ` (10 more replies)
  0 siblings, 11 replies; 17+ messages in thread
From: Matthew Garrett @ 2014-06-01 16:38 UTC (permalink / raw)
  To: airlied; +Cc: dri-devel, platform-driver-x86

The Apple GMUX switcheroo code doesn't really work that well - there's no
straightforward way to ensure that drivers are loaded in the correct order,
and no mechanism to probe displays without performing a full switch. This
patchset adds infrastructural support to switcheroo and functionality to
GMUX in order to fix things up. This won't actually *work* in its current
form - it needs additional patches to the GPU drivers, which are currently
in a somewhat hacky state.

-- 
Matthew Garrett | matthew.garrett@nebula.com

^ permalink raw reply	[flat|nested] 17+ messages in thread

* [PATCH 01/11] vga_switcheroo: Add support for switching only the DDC
  2014-06-01 16:38 Improve Apple GMUX support on switcheroo Matthew Garrett
@ 2014-06-01 16:38 ` Matthew Garrett
  2014-06-03 13:26   ` Jani Nikula
  2014-06-12  0:37   ` Dave Airlie
  2014-06-01 16:38 ` [PATCH 02/11] vga_switcheroo: Add support for reprobing connectors Matthew Garrett
                   ` (9 subsequent siblings)
  10 siblings, 2 replies; 17+ messages in thread
From: Matthew Garrett @ 2014-06-01 16:38 UTC (permalink / raw)
  To: airlied; +Cc: dri-devel, platform-driver-x86, Seth Forshee

From: Seth Forshee <seth.forshee@canonical.com>

During graphics driver initialization its useful to be able to mux only
the DDC to the inactive client in order to read the EDID. Add a
switch_ddc callback to allow capable handlers to provide this
functionality, and add vga_switcheroo_switch_ddc() to allow DRM to mux
only the DDC.

Signed-off-by: Seth Forshee <seth.forshee@canonical.com>
---
 drivers/gpu/vga/vga_switcheroo.c | 38 +++++++++++++++++++++++++++++++++++++-
 include/linux/vga_switcheroo.h   |  4 ++++
 2 files changed, 41 insertions(+), 1 deletion(-)

diff --git a/drivers/gpu/vga/vga_switcheroo.c b/drivers/gpu/vga/vga_switcheroo.c
index ec0ae2d..dd1d587 100644
--- a/drivers/gpu/vga/vga_switcheroo.c
+++ b/drivers/gpu/vga/vga_switcheroo.c
@@ -256,6 +256,28 @@ void vga_switcheroo_client_fb_set(struct pci_dev *pdev,
 }
 EXPORT_SYMBOL(vga_switcheroo_client_fb_set);
 
+int vga_switcheroo_switch_ddc(struct pci_dev *pdev)
+{
+	int ret = 0;
+	int id;
+
+	mutex_lock(&vgasr_mutex);
+
+	if (!vgasr_priv.handler) {
+		ret = -ENODEV;
+		goto out;
+	}
+
+	if (vgasr_priv.handler->switch_ddc) {
+		id = vgasr_priv.handler->get_client_id(pdev);
+		ret = vgasr_priv.handler->switch_ddc(id);
+	}
+out:
+	mutex_unlock(&vgasr_mutex);
+	return ret;
+}
+EXPORT_SYMBOL(vga_switcheroo_switch_ddc);
+
 static int vga_switcheroo_show(struct seq_file *m, void *v)
 {
 	struct vga_switcheroo_client *client;
@@ -353,9 +375,15 @@ static int vga_switchto_stage2(struct vga_switcheroo_client *new_client)
 		console_unlock();
 	}
 
+	if (vgasr_priv.handler->switch_ddc) {
+		ret = vgasr_priv.handler->switch_ddc(new_client->id);
+		if (ret)
+			return ret;
+	}
+
 	ret = vgasr_priv.handler->switchto(new_client->id);
 	if (ret)
-		return ret;
+		goto restore_ddc;
 
 	if (new_client->ops->reprobe)
 		new_client->ops->reprobe(new_client->pdev);
@@ -367,6 +395,14 @@ static int vga_switchto_stage2(struct vga_switcheroo_client *new_client)
 
 	new_client->active = true;
 	return 0;
+
+restore_ddc:
+	if (vgasr_priv.handler->switch_ddc) {
+		int id = (new_client->id == VGA_SWITCHEROO_IGD) ?
+			VGA_SWITCHEROO_DIS : VGA_SWITCHEROO_IGD;
+		vgasr_priv.handler->switch_ddc(id);
+	}
+	return ret;
 }
 
 static bool check_can_switch(void)
diff --git a/include/linux/vga_switcheroo.h b/include/linux/vga_switcheroo.h
index 502073a..37d6850 100644
--- a/include/linux/vga_switcheroo.h
+++ b/include/linux/vga_switcheroo.h
@@ -29,6 +29,7 @@ enum vga_switcheroo_client_id {
 };
 
 struct vga_switcheroo_handler {
+	int (*switch_ddc)(enum vga_switcheroo_client_id id);
 	int (*switchto)(enum vga_switcheroo_client_id id);
 	int (*power_state)(enum vga_switcheroo_client_id id,
 			   enum vga_switcheroo_state state);
@@ -54,6 +55,8 @@ int vga_switcheroo_register_audio_client(struct pci_dev *pdev,
 void vga_switcheroo_client_fb_set(struct pci_dev *dev,
 				  struct fb_info *info);
 
+int vga_switcheroo_switch_ddc(struct pci_dev *pdev);
+
 int vga_switcheroo_register_handler(struct vga_switcheroo_handler *handler);
 void vga_switcheroo_unregister_handler(void);
 
@@ -71,6 +74,7 @@ static inline void vga_switcheroo_unregister_client(struct pci_dev *dev) {}
 static inline int vga_switcheroo_register_client(struct pci_dev *dev,
 		const struct vga_switcheroo_client_ops *ops, bool driver_power_control) { return 0; }
 static inline void vga_switcheroo_client_fb_set(struct pci_dev *dev, struct fb_info *info) {}
+static inline void vga_switcheroo_switch_ddc(struct pci_dev *pdev) { return NULL; }
 static inline int vga_switcheroo_register_handler(struct vga_switcheroo_handler *handler) { return 0; }
 static inline int vga_switcheroo_register_audio_client(struct pci_dev *pdev,
 	const struct vga_switcheroo_client_ops *ops,
-- 
1.8.5.3

^ permalink raw reply related	[flat|nested] 17+ messages in thread

* [PATCH 02/11] vga_switcheroo: Add support for reprobing connectors
  2014-06-01 16:38 Improve Apple GMUX support on switcheroo Matthew Garrett
  2014-06-01 16:38 ` [PATCH 01/11] vga_switcheroo: Add support for switching only the DDC Matthew Garrett
@ 2014-06-01 16:38 ` Matthew Garrett
  2014-06-01 16:38 ` [PATCH 03/11] vga_switcheroo: Add command line option Matthew Garrett
                   ` (8 subsequent siblings)
  10 siblings, 0 replies; 17+ messages in thread
From: Matthew Garrett @ 2014-06-01 16:38 UTC (permalink / raw)
  To: airlied; +Cc: dri-devel, platform-driver-x86, Matthew Garrett

If display MUXing is handled by an external driver, the handler may not
initialise until some time after the graphics drivers originally bound. If
the driver is unable to detect some drivers unless appropriately MUXed, this
will cause problems. This patch adds a callback to allow switcheroo to
retrigger the driver's output probing.

Signed-off-by: Matthew Garrett <matthew.garrett@nebula.com>
---
 drivers/gpu/vga/vga_switcheroo.c | 10 ++++++++++
 include/linux/vga_switcheroo.h   |  1 +
 2 files changed, 11 insertions(+)

diff --git a/drivers/gpu/vga/vga_switcheroo.c b/drivers/gpu/vga/vga_switcheroo.c
index dd1d587..c06ad5f 100644
--- a/drivers/gpu/vga/vga_switcheroo.c
+++ b/drivers/gpu/vga/vga_switcheroo.c
@@ -96,6 +96,16 @@ static void vga_switcheroo_enable(void)
 			return;
 
 		client->id = ret;
+
+		if (!client->active && client->ops->reprobe_connectors) {
+			int old_id = (client->id == VGA_SWITCHEROO_IGD) ?
+				VGA_SWITCHEROO_DIS : VGA_SWITCHEROO_IGD;
+			if (vgasr_priv.handler->switch_ddc)
+				vgasr_priv.handler->switch_ddc(client->id);
+			client->ops->reprobe_connectors(client->pdev);
+			if (vgasr_priv.handler->switch_ddc)
+				vgasr_priv.handler->switch_ddc(old_id);
+		}
 	}
 	vga_switcheroo_debugfs_init(&vgasr_priv);
 	vgasr_priv.active = true;
diff --git a/include/linux/vga_switcheroo.h b/include/linux/vga_switcheroo.h
index 37d6850..bae62fd 100644
--- a/include/linux/vga_switcheroo.h
+++ b/include/linux/vga_switcheroo.h
@@ -40,6 +40,7 @@ struct vga_switcheroo_handler {
 struct vga_switcheroo_client_ops {
 	void (*set_gpu_state)(struct pci_dev *dev, enum vga_switcheroo_state);
 	void (*reprobe)(struct pci_dev *dev);
+	void (*reprobe_connectors)(struct pci_dev *dev);
 	bool (*can_switch)(struct pci_dev *dev);
 };
 
-- 
1.8.5.3

^ permalink raw reply related	[flat|nested] 17+ messages in thread

* [PATCH 03/11] vga_switcheroo: Add command line option
  2014-06-01 16:38 Improve Apple GMUX support on switcheroo Matthew Garrett
  2014-06-01 16:38 ` [PATCH 01/11] vga_switcheroo: Add support for switching only the DDC Matthew Garrett
  2014-06-01 16:38 ` [PATCH 02/11] vga_switcheroo: Add support for reprobing connectors Matthew Garrett
@ 2014-06-01 16:38 ` Matthew Garrett
  2014-06-01 16:38 ` [PATCH 04/11] vga_switcheroo: Allow stashing of panel data Matthew Garrett
                   ` (7 subsequent siblings)
  10 siblings, 0 replies; 17+ messages in thread
From: Matthew Garrett @ 2014-06-01 16:38 UTC (permalink / raw)
  To: airlied; +Cc: dri-devel, platform-driver-x86, Matthew Garrett

Add a command line option in order to allow the user to provide a perferred
GPU at boot time.

Signed-off-by: Matthew Garrett <matthew.garrett@nebula.com>
---
 Documentation/kernel-parameters.txt |  5 +++++
 drivers/gpu/vga/vga_switcheroo.c    | 29 +++++++++++++++++++++++++++++
 2 files changed, 34 insertions(+)

diff --git a/Documentation/kernel-parameters.txt b/Documentation/kernel-parameters.txt
index 30a8ad0d..6e6d505 100644
--- a/Documentation/kernel-parameters.txt
+++ b/Documentation/kernel-parameters.txt
@@ -3486,6 +3486,11 @@ bytes respectively. Such letter suffixes can also be entirely omitted.
 			This is actually a boot loader parameter; the value is
 			passed to the kernel using a special protocol.
 
+	vga_switcheroo= [HW] Switches the enabled GPU at boot time.
+			Format: { IGD | DIS }
+			IGD -- enable the Integrated GPU
+			DIS -- enable the Discrete GPU
+
 	vmalloc=nn[KMG]	[KNL,BOOT] Forces the vmalloc area to have an exact
 			size of <nn>. This can be used to increase the
 			minimum size (128MB on x86). It can also be used to
diff --git a/drivers/gpu/vga/vga_switcheroo.c b/drivers/gpu/vga/vga_switcheroo.c
index c06ad5f..6d95626 100644
--- a/drivers/gpu/vga/vga_switcheroo.c
+++ b/drivers/gpu/vga/vga_switcheroo.c
@@ -67,6 +67,11 @@ struct vgasr_priv {
 static int vga_switcheroo_debugfs_init(struct vgasr_priv *priv);
 static void vga_switcheroo_debugfs_fini(struct vgasr_priv *priv);
 
+static enum vga_switcheroo_client_id vga_switcheroo_default = -1;
+
+static int vga_switchto_stage1(struct vga_switcheroo_client *new_client);
+static int vga_switchto_stage2(struct vga_switcheroo_client *new_client);
+
 /* only one switcheroo per system */
 static struct vgasr_priv vgasr_priv = {
 	.clients = LIST_HEAD_INIT(vgasr_priv.clients),
@@ -107,6 +112,18 @@ static void vga_switcheroo_enable(void)
 				vgasr_priv.handler->switch_ddc(old_id);
 		}
 	}
+
+	list_for_each_entry(client, &vgasr_priv.clients, list) {
+		if (!client->active && client->id == vga_switcheroo_default) {
+			ret = vga_switchto_stage1(client);
+			if (ret)
+				printk(KERN_ERR "vga_switcheroo: switching failed stage 1 %d\n", ret);
+
+			ret = vga_switchto_stage2(client);
+			if (ret)
+				printk(KERN_ERR "vga_switcheroo: switching failed stage 2 %d\n", ret);
+		}
+	}
 	vga_switcheroo_debugfs_init(&vgasr_priv);
 	vgasr_priv.active = true;
 }
@@ -748,3 +765,15 @@ int vga_switcheroo_init_domain_pm_optimus_hdmi_audio(struct device *dev, struct
 	return -EINVAL;
 }
 EXPORT_SYMBOL(vga_switcheroo_init_domain_pm_optimus_hdmi_audio);
+
+static int __init vga_switcheroo_setup(char *str)
+{
+	if (!strcmp(str, "IGD"))
+		vga_switcheroo_default = VGA_SWITCHEROO_IGD;
+	else if (!strcmp(str, "DIS"))
+		vga_switcheroo_default = VGA_SWITCHEROO_DIS;
+
+	return 1;
+}
+
+__setup("vga_switcheroo=", vga_switcheroo_setup);
-- 
1.8.5.3

^ permalink raw reply related	[flat|nested] 17+ messages in thread

* [PATCH 04/11] vga_switcheroo: Allow stashing of panel data
  2014-06-01 16:38 Improve Apple GMUX support on switcheroo Matthew Garrett
                   ` (2 preceding siblings ...)
  2014-06-01 16:38 ` [PATCH 03/11] vga_switcheroo: Add command line option Matthew Garrett
@ 2014-06-01 16:38 ` Matthew Garrett
  2014-06-03 13:40   ` Jani Nikula
  2014-06-01 16:38 ` [PATCH 05/11] vga_switcheroo: Allow handlers to indicate that they can handle PM Matthew Garrett
                   ` (6 subsequent siblings)
  10 siblings, 1 reply; 17+ messages in thread
From: Matthew Garrett @ 2014-06-01 16:38 UTC (permalink / raw)
  To: airlied; +Cc: dri-devel, platform-driver-x86, Matthew Garrett

Not all MUXes allow us to connect the panel data channel to a GPU without
handing over the entire panel and triggering additional flickering during
boot. We only need to do this in order to probe for data that the first
GPU driver has already identified, so add some functions for stashing that
data in vga_switcheroo where it can be retrieved by the other driver later.

Signed-off-by: Matthew Garrett <matthew.garrett@nebula.com>
---
 drivers/gpu/vga/vga_switcheroo.c | 59 ++++++++++++++++++++++++++++++++++++++++
 include/linux/vga_switcheroo.h   | 12 ++++++++
 2 files changed, 71 insertions(+)

diff --git a/drivers/gpu/vga/vga_switcheroo.c b/drivers/gpu/vga/vga_switcheroo.c
index 6d95626..1a80b93 100644
--- a/drivers/gpu/vga/vga_switcheroo.c
+++ b/drivers/gpu/vga/vga_switcheroo.c
@@ -17,6 +17,8 @@
  - switch_check  - check if the device is in a position to switch now
  */
 
+#include <drm/drm_edid.h>
+
 #include <linux/module.h>
 #include <linux/seq_file.h>
 #include <linux/uaccess.h>
@@ -39,6 +41,7 @@ struct vga_switcheroo_client {
 	int id;
 	bool active;
 	bool driver_power_control;
+	bool use_panel;
 	struct list_head list;
 };
 
@@ -56,6 +59,9 @@ struct vgasr_priv {
 	int registered_clients;
 	struct list_head clients;
 
+	struct edid *edid;
+	u8 *dpcd;
+
 	struct vga_switcheroo_handler *handler;
 };
 
@@ -107,7 +113,9 @@ static void vga_switcheroo_enable(void)
 				VGA_SWITCHEROO_DIS : VGA_SWITCHEROO_IGD;
 			if (vgasr_priv.handler->switch_ddc)
 				vgasr_priv.handler->switch_ddc(client->id);
+			client->use_panel = true;
 			client->ops->reprobe_connectors(client->pdev);
+			client->use_panel = false;
 			if (vgasr_priv.handler->switch_ddc)
 				vgasr_priv.handler->switch_ddc(old_id);
 		}
@@ -412,6 +420,9 @@ static int vga_switchto_stage2(struct vga_switcheroo_client *new_client)
 	if (ret)
 		goto restore_ddc;
 
+	new_client->use_panel = true;
+	active->use_panel = false;
+
 	if (new_client->ops->reprobe)
 		new_client->ops->reprobe(new_client->pdev);
 
@@ -766,6 +777,54 @@ int vga_switcheroo_init_domain_pm_optimus_hdmi_audio(struct device *dev, struct
 }
 EXPORT_SYMBOL(vga_switcheroo_init_domain_pm_optimus_hdmi_audio);
 
+int vga_switcheroo_set_dpcd(u8 *dpcd)
+{
+	if (vgasr_priv.dpcd)
+		return -EEXIST;
+
+	vgasr_priv.dpcd = kmalloc(8, GFP_KERNEL);
+	memcpy(vgasr_priv.dpcd, dpcd, 8);
+	return 0;
+}
+EXPORT_SYMBOL(vga_switcheroo_set_dpcd);
+
+u8 *vga_switcheroo_get_dpcd(struct pci_dev *pdev)
+{
+	struct vga_switcheroo_client *client;
+	client = find_client_from_pci(&vgasr_priv.clients, pdev);
+
+	if (!client || !client->use_panel)
+		return NULL;
+
+	return vgasr_priv.dpcd;
+}
+EXPORT_SYMBOL(vga_switcheroo_get_dpcd);
+
+int vga_switcheroo_set_edid(struct edid *edid)
+{
+	int size = EDID_LENGTH * (1 + edid->extensions);
+
+	if (vgasr_priv.edid)
+		return -EEXIST;
+
+	vgasr_priv.edid = kmalloc(size, GFP_KERNEL);
+	memcpy(vgasr_priv.edid, edid, size);
+	return 0;
+}
+EXPORT_SYMBOL(vga_switcheroo_set_edid);
+
+struct edid *vga_switcheroo_get_edid(struct pci_dev *pdev)
+{
+	struct vga_switcheroo_client *client;
+	client = find_client_from_pci(&vgasr_priv.clients, pdev);
+
+	if (!client || !client->use_panel)
+		return NULL;
+
+	return vgasr_priv.edid;
+}
+EXPORT_SYMBOL(vga_switcheroo_get_edid);
+
 static int __init vga_switcheroo_setup(char *str)
 {
 	if (!strcmp(str, "IGD"))
diff --git a/include/linux/vga_switcheroo.h b/include/linux/vga_switcheroo.h
index bae62fd..07b07fc 100644
--- a/include/linux/vga_switcheroo.h
+++ b/include/linux/vga_switcheroo.h
@@ -10,6 +10,7 @@
 #ifndef _LINUX_VGA_SWITCHEROO_H_
 #define _LINUX_VGA_SWITCHEROO_H_
 
+#include <drm/drm_edid.h>
 #include <linux/fb.h>
 
 struct pci_dev;
@@ -69,6 +70,12 @@ void vga_switcheroo_set_dynamic_switch(struct pci_dev *pdev, enum vga_switcheroo
 
 int vga_switcheroo_init_domain_pm_ops(struct device *dev, struct dev_pm_domain *domain);
 int vga_switcheroo_init_domain_pm_optimus_hdmi_audio(struct device *dev, struct dev_pm_domain *domain);
+
+int vga_switcheroo_set_dpcd(u8 *dpcd);
+u8 *vga_switcheroo_get_dpcd(struct pci_dev *pdev);
+int vga_switcheroo_set_edid(struct edid *edid);
+struct edid *vga_switcheroo_get_edid(struct pci_dev *pdev);
+
 #else
 
 static inline void vga_switcheroo_unregister_client(struct pci_dev *dev) {}
@@ -89,5 +96,10 @@ static inline void vga_switcheroo_set_dynamic_switch(struct pci_dev *pdev, enum
 static inline int vga_switcheroo_init_domain_pm_ops(struct device *dev, struct dev_pm_domain *domain) { return -EINVAL; }
 static inline int vga_switcheroo_init_domain_pm_optimus_hdmi_audio(struct device *dev, struct dev_pm_domain *domain) { return -EINVAL; }
 
+static inline int vga_switcheroo_set_dpcd(u8 *dpcd) { return 0 };
+static inline u8 *vga_switcheroo_get_dpcd(struct pci_dev *pdev) { return NULL };
+static inline int vga_switcheroo_set_edid(struct edid *edid) { return 0 };
+static inline struct edid *vga_switcheroo_get_edid(struct pci_dev *pdev) { return NULL };
+
 #endif
 #endif /* _LINUX_VGA_SWITCHEROO_H_ */
-- 
1.8.5.3

^ permalink raw reply related	[flat|nested] 17+ messages in thread

* [PATCH 05/11] vga_switcheroo: Allow handlers to indicate that they can handle PM
  2014-06-01 16:38 Improve Apple GMUX support on switcheroo Matthew Garrett
                   ` (3 preceding siblings ...)
  2014-06-01 16:38 ` [PATCH 04/11] vga_switcheroo: Allow stashing of panel data Matthew Garrett
@ 2014-06-01 16:38 ` Matthew Garrett
  2014-06-01 16:38 ` [PATCH 06/11] vga_switcheroo: Add enable() call to clients and permit deferral of dynamic PM Matthew Garrett
                   ` (5 subsequent siblings)
  10 siblings, 0 replies; 17+ messages in thread
From: Matthew Garrett @ 2014-06-01 16:38 UTC (permalink / raw)
  To: airlied; +Cc: dri-devel, platform-driver-x86, Matthew Garrett

Most switcheroo setups attach power management to one of the GPUs. This is
not always the case, so provide a mechanism for handlers to declare that
they can change the power state of GPUs and permit drivers to obtain this
information.

Signed-off-by: Matthew Garrett <matthew.garrett@nebula.com>
---
 drivers/gpu/vga/vga_switcheroo.c | 8 ++++++++
 include/linux/vga_switcheroo.h   | 5 +++++
 2 files changed, 13 insertions(+)

diff --git a/drivers/gpu/vga/vga_switcheroo.c b/drivers/gpu/vga/vga_switcheroo.c
index 1a80b93..c5e97d4 100644
--- a/drivers/gpu/vga/vga_switcheroo.c
+++ b/drivers/gpu/vga/vga_switcheroo.c
@@ -825,6 +825,14 @@ struct edid *vga_switcheroo_get_edid(struct pci_dev *pdev)
 }
 EXPORT_SYMBOL(vga_switcheroo_get_edid);
 
+bool vga_switcheroo_handler_pm(void) {
+	if (!vgasr_priv.handler)
+		return false;
+
+	return vgasr_priv.handler->handler_pm;
+}
+EXPORT_SYMBOL(vga_switcheroo_handler_pm);
+
 static int __init vga_switcheroo_setup(char *str)
 {
 	if (!strcmp(str, "IGD"))
diff --git a/include/linux/vga_switcheroo.h b/include/linux/vga_switcheroo.h
index 07b07fc..4bba934 100644
--- a/include/linux/vga_switcheroo.h
+++ b/include/linux/vga_switcheroo.h
@@ -36,6 +36,7 @@ struct vga_switcheroo_handler {
 			   enum vga_switcheroo_state state);
 	int (*init)(void);
 	int (*get_client_id)(struct pci_dev *pdev);
+	bool handler_pm;
 };
 
 struct vga_switcheroo_client_ops {
@@ -76,6 +77,8 @@ u8 *vga_switcheroo_get_dpcd(struct pci_dev *pdev);
 int vga_switcheroo_set_edid(struct edid *edid);
 struct edid *vga_switcheroo_get_edid(struct pci_dev *pdev);
 
+bool vga_switcheroo_handler_pm(void);
+
 #else
 
 static inline void vga_switcheroo_unregister_client(struct pci_dev *dev) {}
@@ -101,5 +104,7 @@ static inline u8 *vga_switcheroo_get_dpcd(struct pci_dev *pdev) { return NULL };
 static inline int vga_switcheroo_set_edid(struct edid *edid) { return 0 };
 static inline struct edid *vga_switcheroo_get_edid(struct pci_dev *pdev) { return NULL };
 
+static inline bool vga_switcheroo_handler_pm(void) { return false; };
+
 #endif
 #endif /* _LINUX_VGA_SWITCHEROO_H_ */
-- 
1.8.5.3

^ permalink raw reply related	[flat|nested] 17+ messages in thread

* [PATCH 06/11] vga_switcheroo: Add enable() call to clients and permit deferral of dynamic PM
  2014-06-01 16:38 Improve Apple GMUX support on switcheroo Matthew Garrett
                   ` (4 preceding siblings ...)
  2014-06-01 16:38 ` [PATCH 05/11] vga_switcheroo: Allow handlers to indicate that they can handle PM Matthew Garrett
@ 2014-06-01 16:38 ` Matthew Garrett
  2014-06-01 16:38 ` [PATCH 07/11] vga_switcheroo: Reprobe old device on switching Matthew Garrett
                   ` (4 subsequent siblings)
  10 siblings, 0 replies; 17+ messages in thread
From: Matthew Garrett @ 2014-06-01 16:38 UTC (permalink / raw)
  To: airlied; +Cc: dri-devel, platform-driver-x86, Matthew Garrett

We may not know whether the platform supports dynamic PM of GPUs until the
switcheroo handler is registered. Add an enable() callback for clients and
another entry point to switcheroo in order to permit them to set dynamic PM
appropriately.

Signed-off-by: Matthew Garrett <matthew.garrett@nebula.com>
---
 drivers/gpu/vga/vga_switcheroo.c | 17 +++++++++++++++++
 include/linux/vga_switcheroo.h   |  3 +++
 2 files changed, 20 insertions(+)

diff --git a/drivers/gpu/vga/vga_switcheroo.c b/drivers/gpu/vga/vga_switcheroo.c
index c5e97d4..199a111 100644
--- a/drivers/gpu/vga/vga_switcheroo.c
+++ b/drivers/gpu/vga/vga_switcheroo.c
@@ -108,6 +108,9 @@ static void vga_switcheroo_enable(void)
 
 		client->id = ret;
 
+		if (client->ops->enable)
+			client->ops->enable(client->pdev);
+
 		if (!client->active && client->ops->reprobe_connectors) {
 			int old_id = (client->id == VGA_SWITCHEROO_IGD) ?
 				VGA_SWITCHEROO_DIS : VGA_SWITCHEROO_IGD;
@@ -670,6 +673,20 @@ static void vga_switcheroo_power_switch(struct pci_dev *pdev, enum vga_switchero
 	vgasr_priv.handler->power_state(client->id, state);
 }
 
+void vga_switcheroo_set_dynamic_support(struct pci_dev *pdev, bool dynamic)
+{
+	struct vga_switcheroo_client *client;
+
+	client = find_client_from_pci(&vgasr_priv.clients, pdev);
+	if (!client)
+		return;
+
+	client->driver_power_control = dynamic;
+
+	return;
+}
+EXPORT_SYMBOL(vga_switcheroo_set_dynamic_support);
+
 /* force a PCI device to a certain state - mainly to turn off audio clients */
 
 void vga_switcheroo_set_dynamic_switch(struct pci_dev *pdev, enum vga_switcheroo_state dynamic)
diff --git a/include/linux/vga_switcheroo.h b/include/linux/vga_switcheroo.h
index 4bba934..5a483c6 100644
--- a/include/linux/vga_switcheroo.h
+++ b/include/linux/vga_switcheroo.h
@@ -44,6 +44,7 @@ struct vga_switcheroo_client_ops {
 	void (*reprobe)(struct pci_dev *dev);
 	void (*reprobe_connectors)(struct pci_dev *dev);
 	bool (*can_switch)(struct pci_dev *dev);
+	void (*enable)(struct pci_dev *dev);
 };
 
 #if defined(CONFIG_VGA_SWITCHEROO)
@@ -67,6 +68,7 @@ int vga_switcheroo_process_delayed_switch(void);
 
 int vga_switcheroo_get_client_state(struct pci_dev *dev);
 
+void vga_switcheroo_set_dynamic_support(struct pci_dev *pdev, bool dynamic);
 void vga_switcheroo_set_dynamic_switch(struct pci_dev *pdev, enum vga_switcheroo_state dynamic);
 
 int vga_switcheroo_init_domain_pm_ops(struct device *dev, struct dev_pm_domain *domain);
@@ -94,6 +96,7 @@ static inline void vga_switcheroo_unregister_handler(void) {}
 static inline int vga_switcheroo_process_delayed_switch(void) { return 0; }
 static inline int vga_switcheroo_get_client_state(struct pci_dev *dev) { return VGA_SWITCHEROO_ON; }
 
+static inline void vga_switcheroo_set_dynamic_support(struct pci_dev *pdev, bool dynamic) {}
 static inline void vga_switcheroo_set_dynamic_switch(struct pci_dev *pdev, enum vga_switcheroo_state dynamic) {}
 
 static inline int vga_switcheroo_init_domain_pm_ops(struct device *dev, struct dev_pm_domain *domain) { return -EINVAL; }
-- 
1.8.5.3

^ permalink raw reply related	[flat|nested] 17+ messages in thread

* [PATCH 07/11] vga_switcheroo: Reprobe old device on switching
  2014-06-01 16:38 Improve Apple GMUX support on switcheroo Matthew Garrett
                   ` (5 preceding siblings ...)
  2014-06-01 16:38 ` [PATCH 06/11] vga_switcheroo: Add enable() call to clients and permit deferral of dynamic PM Matthew Garrett
@ 2014-06-01 16:38 ` Matthew Garrett
  2014-06-01 16:38 ` [PATCH 08/11] apple-gmux: Add support for the switch_ddc callback Matthew Garrett
                   ` (3 subsequent siblings)
  10 siblings, 0 replies; 17+ messages in thread
From: Matthew Garrett @ 2014-06-01 16:38 UTC (permalink / raw)
  To: airlied; +Cc: dri-devel, platform-driver-x86, Matthew Garrett

We need to force the previously active device to reprobe its connectors
when we switch in order to allow it to give up connectors that are no
longer in use.

Signed-off-by: Matthew Garrett <matthew.garrett@nebula.com>
---
 drivers/gpu/vga/vga_switcheroo.c | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/drivers/gpu/vga/vga_switcheroo.c b/drivers/gpu/vga/vga_switcheroo.c
index 199a111..d380158 100644
--- a/drivers/gpu/vga/vga_switcheroo.c
+++ b/drivers/gpu/vga/vga_switcheroo.c
@@ -429,6 +429,9 @@ static int vga_switchto_stage2(struct vga_switcheroo_client *new_client)
 	if (new_client->ops->reprobe)
 		new_client->ops->reprobe(new_client->pdev);
 
+	if (active->ops->reprobe)
+		active->ops->reprobe(active->pdev);
+
 	if (active->pwr_state == VGA_SWITCHEROO_ON)
 		vga_switchoff(active);
 
-- 
1.8.5.3

^ permalink raw reply related	[flat|nested] 17+ messages in thread

* [PATCH 08/11] apple-gmux: Add support for the switch_ddc callback
  2014-06-01 16:38 Improve Apple GMUX support on switcheroo Matthew Garrett
                   ` (6 preceding siblings ...)
  2014-06-01 16:38 ` [PATCH 07/11] vga_switcheroo: Reprobe old device on switching Matthew Garrett
@ 2014-06-01 16:38 ` Matthew Garrett
  2014-06-02 14:35   ` Alex Deucher
  2014-06-01 16:38 ` [PATCH 09/11] apple-gmux: Assign apple_gmux_data before registering Matthew Garrett
                   ` (2 subsequent siblings)
  10 siblings, 1 reply; 17+ messages in thread
From: Matthew Garrett @ 2014-06-01 16:38 UTC (permalink / raw)
  To: airlied; +Cc: dri-devel, platform-driver-x86, Matthew Garrett

We can switch DDC pins in a way that ought (with luck) to work for LVDS.
This isn't sufficient for eDP, which is addressed in later patches.

Signed-off-by: Matthew Garrett <matthew.garrett@nebula.com>
---
 drivers/platform/x86/apple-gmux.c | 11 +++++++++++
 1 file changed, 11 insertions(+)

diff --git a/drivers/platform/x86/apple-gmux.c b/drivers/platform/x86/apple-gmux.c
index b9429fb..5594cbc 100644
--- a/drivers/platform/x86/apple-gmux.c
+++ b/drivers/platform/x86/apple-gmux.c
@@ -271,6 +271,16 @@ static const struct backlight_ops gmux_bl_ops = {
 	.update_status = gmux_update_status,
 };
 
+static int gmux_switch_ddc(enum vga_switcheroo_client_id id)
+{
+	if (id == VGA_SWITCHEROO_IGD)
+		gmux_write8(apple_gmux_data, GMUX_PORT_SWITCH_DDC, 1);
+	else
+		gmux_write8(apple_gmux_data, GMUX_PORT_SWITCH_DDC, 2);
+
+	return 0;
+}
+
 static int gmux_switchto(enum vga_switcheroo_client_id id)
 {
 	if (id == VGA_SWITCHEROO_IGD) {
@@ -346,6 +356,7 @@ gmux_active_client(struct apple_gmux_data *gmux_data)
 
 static struct vga_switcheroo_handler gmux_handler = {
 	.switchto = gmux_switchto,
+	.switch_ddc = gmux_switch_ddc,
 	.power_state = gmux_set_power_state,
 	.get_client_id = gmux_get_client_id,
 };
-- 
1.8.5.3

^ permalink raw reply related	[flat|nested] 17+ messages in thread

* [PATCH 09/11] apple-gmux: Assign apple_gmux_data before registering
  2014-06-01 16:38 Improve Apple GMUX support on switcheroo Matthew Garrett
                   ` (7 preceding siblings ...)
  2014-06-01 16:38 ` [PATCH 08/11] apple-gmux: Add support for the switch_ddc callback Matthew Garrett
@ 2014-06-01 16:38 ` Matthew Garrett
  2014-06-01 16:38 ` [PATCH 10/11] apple-gmux: Indicate that driver supports changing of GPU power states Matthew Garrett
  2014-06-01 16:38 ` [PATCH 11/11] apple_gmux: Wait for switch completion Matthew Garrett
  10 siblings, 0 replies; 17+ messages in thread
From: Matthew Garrett @ 2014-06-01 16:38 UTC (permalink / raw)
  To: airlied; +Cc: dri-devel, platform-driver-x86, Matthew Garrett

Registering the handler after both GPUs will trigger a DDC switch for
connector reprobing. This will oops if apple_gmux_data hasn't already been
assigned. Reorder the code to do that.

Signed-off-by: Matthew Garrett <matthew.garrett@nebula.com>
---
 drivers/platform/x86/apple-gmux.c | 10 ++++++----
 1 file changed, 6 insertions(+), 4 deletions(-)

diff --git a/drivers/platform/x86/apple-gmux.c b/drivers/platform/x86/apple-gmux.c
index 5594cbc..e9b6d77 100644
--- a/drivers/platform/x86/apple-gmux.c
+++ b/drivers/platform/x86/apple-gmux.c
@@ -563,18 +563,20 @@ static int gmux_probe(struct pnp_dev *pnp, const struct pnp_device_id *id)
 		gmux_data->gpe = -1;
 	}
 
+	apple_gmux_data = gmux_data;
+	init_completion(&gmux_data->powerchange_done);
+	gmux_enable_interrupts(gmux_data);
+
 	if (vga_switcheroo_register_handler(&gmux_handler)) {
 		ret = -ENODEV;
 		goto err_register_handler;
 	}
 
-	init_completion(&gmux_data->powerchange_done);
-	apple_gmux_data = gmux_data;
-	gmux_enable_interrupts(gmux_data);
-
 	return 0;
 
 err_register_handler:
+	gmux_disable_interrupts(gmux_data);
+	apple_gmux_data = NULL;
 	if (gmux_data->gpe >= 0)
 		acpi_disable_gpe(NULL, gmux_data->gpe);
 err_enable_gpe:
-- 
1.8.5.3

^ permalink raw reply related	[flat|nested] 17+ messages in thread

* [PATCH 10/11] apple-gmux: Indicate that driver supports changing of GPU power states
  2014-06-01 16:38 Improve Apple GMUX support on switcheroo Matthew Garrett
                   ` (8 preceding siblings ...)
  2014-06-01 16:38 ` [PATCH 09/11] apple-gmux: Assign apple_gmux_data before registering Matthew Garrett
@ 2014-06-01 16:38 ` Matthew Garrett
  2014-06-01 16:38 ` [PATCH 11/11] apple_gmux: Wait for switch completion Matthew Garrett
  10 siblings, 0 replies; 17+ messages in thread
From: Matthew Garrett @ 2014-06-01 16:38 UTC (permalink / raw)
  To: airlied; +Cc: dri-devel, platform-driver-x86, Matthew Garrett

The Apple GMUX can cut power to the discrete GPU, so should declare this
to the vga_switcheroo core.

Signed-off-by: Matthew Garrett <matthew.garrett@nebula.com>
---
 drivers/platform/x86/apple-gmux.c | 1 +
 1 file changed, 1 insertion(+)

diff --git a/drivers/platform/x86/apple-gmux.c b/drivers/platform/x86/apple-gmux.c
index e9b6d77..17f906d 100644
--- a/drivers/platform/x86/apple-gmux.c
+++ b/drivers/platform/x86/apple-gmux.c
@@ -359,6 +359,7 @@ static struct vga_switcheroo_handler gmux_handler = {
 	.switch_ddc = gmux_switch_ddc,
 	.power_state = gmux_set_power_state,
 	.get_client_id = gmux_get_client_id,
+	.handler_pm = true,
 };
 
 static inline void gmux_disable_interrupts(struct apple_gmux_data *gmux_data)
-- 
1.8.5.3

^ permalink raw reply related	[flat|nested] 17+ messages in thread

* [PATCH 11/11] apple_gmux: Wait for switch completion
  2014-06-01 16:38 Improve Apple GMUX support on switcheroo Matthew Garrett
                   ` (9 preceding siblings ...)
  2014-06-01 16:38 ` [PATCH 10/11] apple-gmux: Indicate that driver supports changing of GPU power states Matthew Garrett
@ 2014-06-01 16:38 ` Matthew Garrett
  10 siblings, 0 replies; 17+ messages in thread
From: Matthew Garrett @ 2014-06-01 16:38 UTC (permalink / raw)
  To: airlied; +Cc: dri-devel, platform-driver-x86, Matthew Garrett

The GMUX doesn't appear to switch instantly, which can trigger problems in
panel detection and setup. Wait for an interrupt or 200msec, whichever comes
first.

Signed-off-by: Matthew Garrett <matthew.garrett@nebula.com>
---
 drivers/platform/x86/apple-gmux.c | 12 ++++++++++++
 1 file changed, 12 insertions(+)

diff --git a/drivers/platform/x86/apple-gmux.c b/drivers/platform/x86/apple-gmux.c
index 17f906d..6826ede 100644
--- a/drivers/platform/x86/apple-gmux.c
+++ b/drivers/platform/x86/apple-gmux.c
@@ -38,6 +38,7 @@ struct apple_gmux_data {
 	int gpe;
 	enum vga_switcheroo_client_id resume_client_id;
 	enum vga_switcheroo_state power_state;
+	struct completion switch_done;
 	struct completion powerchange_done;
 };
 
@@ -283,6 +284,8 @@ static int gmux_switch_ddc(enum vga_switcheroo_client_id id)
 
 static int gmux_switchto(enum vga_switcheroo_client_id id)
 {
+	reinit_completion(&apple_gmux_data->switch_done);
+
 	if (id == VGA_SWITCHEROO_IGD) {
 		gmux_write8(apple_gmux_data, GMUX_PORT_SWITCH_DDC, 1);
 		gmux_write8(apple_gmux_data, GMUX_PORT_SWITCH_DISPLAY, 2);
@@ -293,6 +296,11 @@ static int gmux_switchto(enum vga_switcheroo_client_id id)
 		gmux_write8(apple_gmux_data, GMUX_PORT_SWITCH_EXTERNAL, 3);
 	}
 
+	if (apple_gmux_data->gpe >= 0 &&
+	    !wait_for_completion_interruptible_timeout(&apple_gmux_data->switch_done,
+						       msecs_to_jiffies(200)))
+		pr_warn("Timeout waiting for gmux GPU switch to complete\n");
+
 	return 0;
 }
 
@@ -401,6 +409,9 @@ static void gmux_notify_handler(acpi_handle device, u32 value, void *context)
 	gmux_clear_interrupts(gmux_data);
 	gmux_enable_interrupts(gmux_data);
 
+	if (status & GMUX_INTERRUPT_STATUS_DISPLAY)
+		complete(&gmux_data->switch_done);
+
 	if (status & GMUX_INTERRUPT_STATUS_POWER)
 		complete(&gmux_data->powerchange_done);
 }
@@ -565,6 +576,7 @@ static int gmux_probe(struct pnp_dev *pnp, const struct pnp_device_id *id)
 	}
 
 	apple_gmux_data = gmux_data;
+	init_completion(&gmux_data->switch_done);
 	init_completion(&gmux_data->powerchange_done);
 	gmux_enable_interrupts(gmux_data);
 
-- 
1.8.5.3

^ permalink raw reply related	[flat|nested] 17+ messages in thread

* Re: [PATCH 08/11] apple-gmux: Add support for the switch_ddc callback
  2014-06-01 16:38 ` [PATCH 08/11] apple-gmux: Add support for the switch_ddc callback Matthew Garrett
@ 2014-06-02 14:35   ` Alex Deucher
  0 siblings, 0 replies; 17+ messages in thread
From: Alex Deucher @ 2014-06-02 14:35 UTC (permalink / raw)
  To: Matthew Garrett
  Cc: Dave Airlie, Maling list - DRI developers, platform-driver-x86

On Sun, Jun 1, 2014 at 12:38 PM, Matthew Garrett
<matthew.garrett@nebula.com> wrote:
> We can switch DDC pins in a way that ought (with luck) to work for LVDS.
> This isn't sufficient for eDP, which is addressed in later patches.
>
> Signed-off-by: Matthew Garrett <matthew.garrett@nebula.com>

FWIW, on AMD muxed PX systems, there are separate muxes for ddc/hpd
and data lines so it would be trivial to implement there as well.

Alex

> ---
>  drivers/platform/x86/apple-gmux.c | 11 +++++++++++
>  1 file changed, 11 insertions(+)
>
> diff --git a/drivers/platform/x86/apple-gmux.c b/drivers/platform/x86/apple-gmux.c
> index b9429fb..5594cbc 100644
> --- a/drivers/platform/x86/apple-gmux.c
> +++ b/drivers/platform/x86/apple-gmux.c
> @@ -271,6 +271,16 @@ static const struct backlight_ops gmux_bl_ops = {
>         .update_status = gmux_update_status,
>  };
>
> +static int gmux_switch_ddc(enum vga_switcheroo_client_id id)
> +{
> +       if (id == VGA_SWITCHEROO_IGD)
> +               gmux_write8(apple_gmux_data, GMUX_PORT_SWITCH_DDC, 1);
> +       else
> +               gmux_write8(apple_gmux_data, GMUX_PORT_SWITCH_DDC, 2);
> +
> +       return 0;
> +}
> +
>  static int gmux_switchto(enum vga_switcheroo_client_id id)
>  {
>         if (id == VGA_SWITCHEROO_IGD) {
> @@ -346,6 +356,7 @@ gmux_active_client(struct apple_gmux_data *gmux_data)
>
>  static struct vga_switcheroo_handler gmux_handler = {
>         .switchto = gmux_switchto,
> +       .switch_ddc = gmux_switch_ddc,
>         .power_state = gmux_set_power_state,
>         .get_client_id = gmux_get_client_id,
>  };
> --
> 1.8.5.3
>
> _______________________________________________
> dri-devel mailing list
> dri-devel@lists.freedesktop.org
> http://lists.freedesktop.org/mailman/listinfo/dri-devel

^ permalink raw reply	[flat|nested] 17+ messages in thread

* Re: [PATCH 01/11] vga_switcheroo: Add support for switching only the DDC
  2014-06-01 16:38 ` [PATCH 01/11] vga_switcheroo: Add support for switching only the DDC Matthew Garrett
@ 2014-06-03 13:26   ` Jani Nikula
  2014-06-12  0:37   ` Dave Airlie
  1 sibling, 0 replies; 17+ messages in thread
From: Jani Nikula @ 2014-06-03 13:26 UTC (permalink / raw)
  To: Matthew Garrett, airlied; +Cc: Seth Forshee, dri-devel, platform-driver-x86

On Sun, 01 Jun 2014, Matthew Garrett <matthew.garrett@nebula.com> wrote:
> From: Seth Forshee <seth.forshee@canonical.com>
>
> During graphics driver initialization its useful to be able to mux only
> the DDC to the inactive client in order to read the EDID. Add a
> switch_ddc callback to allow capable handlers to provide this
> functionality, and add vga_switcheroo_switch_ddc() to allow DRM to mux
> only the DDC.
>
> Signed-off-by: Seth Forshee <seth.forshee@canonical.com>
> ---
>  drivers/gpu/vga/vga_switcheroo.c | 38 +++++++++++++++++++++++++++++++++++++-
>  include/linux/vga_switcheroo.h   |  4 ++++
>  2 files changed, 41 insertions(+), 1 deletion(-)
>
> diff --git a/drivers/gpu/vga/vga_switcheroo.c b/drivers/gpu/vga/vga_switcheroo.c
> index ec0ae2d..dd1d587 100644
> --- a/drivers/gpu/vga/vga_switcheroo.c
> +++ b/drivers/gpu/vga/vga_switcheroo.c
> @@ -256,6 +256,28 @@ void vga_switcheroo_client_fb_set(struct pci_dev *pdev,
>  }
>  EXPORT_SYMBOL(vga_switcheroo_client_fb_set);
>  
> +int vga_switcheroo_switch_ddc(struct pci_dev *pdev)
> +{
> +	int ret = 0;
> +	int id;
> +
> +	mutex_lock(&vgasr_mutex);
> +
> +	if (!vgasr_priv.handler) {
> +		ret = -ENODEV;
> +		goto out;
> +	}
> +
> +	if (vgasr_priv.handler->switch_ddc) {
> +		id = vgasr_priv.handler->get_client_id(pdev);
> +		ret = vgasr_priv.handler->switch_ddc(id);
> +	}
> +out:
> +	mutex_unlock(&vgasr_mutex);
> +	return ret;
> +}
> +EXPORT_SYMBOL(vga_switcheroo_switch_ddc);
> +
>  static int vga_switcheroo_show(struct seq_file *m, void *v)
>  {
>  	struct vga_switcheroo_client *client;
> @@ -353,9 +375,15 @@ static int vga_switchto_stage2(struct vga_switcheroo_client *new_client)
>  		console_unlock();
>  	}
>  
> +	if (vgasr_priv.handler->switch_ddc) {
> +		ret = vgasr_priv.handler->switch_ddc(new_client->id);
> +		if (ret)
> +			return ret;
> +	}
> +
>  	ret = vgasr_priv.handler->switchto(new_client->id);
>  	if (ret)
> -		return ret;
> +		goto restore_ddc;
>  
>  	if (new_client->ops->reprobe)
>  		new_client->ops->reprobe(new_client->pdev);
> @@ -367,6 +395,14 @@ static int vga_switchto_stage2(struct vga_switcheroo_client *new_client)
>  
>  	new_client->active = true;
>  	return 0;
> +
> +restore_ddc:
> +	if (vgasr_priv.handler->switch_ddc) {
> +		int id = (new_client->id == VGA_SWITCHEROO_IGD) ?
> +			VGA_SWITCHEROO_DIS : VGA_SWITCHEROO_IGD;
> +		vgasr_priv.handler->switch_ddc(id);
> +	}
> +	return ret;
>  }
>  
>  static bool check_can_switch(void)
> diff --git a/include/linux/vga_switcheroo.h b/include/linux/vga_switcheroo.h
> index 502073a..37d6850 100644
> --- a/include/linux/vga_switcheroo.h
> +++ b/include/linux/vga_switcheroo.h
> @@ -29,6 +29,7 @@ enum vga_switcheroo_client_id {
>  };
>  
>  struct vga_switcheroo_handler {
> +	int (*switch_ddc)(enum vga_switcheroo_client_id id);
>  	int (*switchto)(enum vga_switcheroo_client_id id);
>  	int (*power_state)(enum vga_switcheroo_client_id id,
>  			   enum vga_switcheroo_state state);
> @@ -54,6 +55,8 @@ int vga_switcheroo_register_audio_client(struct pci_dev *pdev,
>  void vga_switcheroo_client_fb_set(struct pci_dev *dev,
>  				  struct fb_info *info);
>  
> +int vga_switcheroo_switch_ddc(struct pci_dev *pdev);
> +
>  int vga_switcheroo_register_handler(struct vga_switcheroo_handler *handler);
>  void vga_switcheroo_unregister_handler(void);
>  
> @@ -71,6 +74,7 @@ static inline void vga_switcheroo_unregister_client(struct pci_dev *dev) {}
>  static inline int vga_switcheroo_register_client(struct pci_dev *dev,
>  		const struct vga_switcheroo_client_ops *ops, bool driver_power_control) { return 0; }
>  static inline void vga_switcheroo_client_fb_set(struct pci_dev *dev, struct fb_info *info) {}
> +static inline void vga_switcheroo_switch_ddc(struct pci_dev *pdev) { return NULL; }

Not really reviewing, but this three-way contradiction of return types
caught my eye.

BR,
Jani.


>  static inline int vga_switcheroo_register_handler(struct vga_switcheroo_handler *handler) { return 0; }
>  static inline int vga_switcheroo_register_audio_client(struct pci_dev *pdev,
>  	const struct vga_switcheroo_client_ops *ops,
> -- 
> 1.8.5.3
>
> _______________________________________________
> dri-devel mailing list
> dri-devel@lists.freedesktop.org
> http://lists.freedesktop.org/mailman/listinfo/dri-devel

-- 
Jani Nikula, Intel Open Source Technology Center

^ permalink raw reply	[flat|nested] 17+ messages in thread

* Re: [PATCH 04/11] vga_switcheroo: Allow stashing of panel data
  2014-06-01 16:38 ` [PATCH 04/11] vga_switcheroo: Allow stashing of panel data Matthew Garrett
@ 2014-06-03 13:40   ` Jani Nikula
  0 siblings, 0 replies; 17+ messages in thread
From: Jani Nikula @ 2014-06-03 13:40 UTC (permalink / raw)
  To: airlied; +Cc: Matthew Garrett, dri-devel, platform-driver-x86

On Sun, 01 Jun 2014, Matthew Garrett <matthew.garrett@nebula.com> wrote:
> Not all MUXes allow us to connect the panel data channel to a GPU without
> handing over the entire panel and triggering additional flickering during
> boot. We only need to do this in order to probe for data that the first
> GPU driver has already identified, so add some functions for stashing that
> data in vga_switcheroo where it can be retrieved by the other driver later.
>
> Signed-off-by: Matthew Garrett <matthew.garrett@nebula.com>
> ---
>  drivers/gpu/vga/vga_switcheroo.c | 59 ++++++++++++++++++++++++++++++++++++++++
>  include/linux/vga_switcheroo.h   | 12 ++++++++
>  2 files changed, 71 insertions(+)
>
> diff --git a/drivers/gpu/vga/vga_switcheroo.c b/drivers/gpu/vga/vga_switcheroo.c
> index 6d95626..1a80b93 100644
> --- a/drivers/gpu/vga/vga_switcheroo.c
> +++ b/drivers/gpu/vga/vga_switcheroo.c
> @@ -17,6 +17,8 @@
>   - switch_check  - check if the device is in a position to switch now
>   */
>  
> +#include <drm/drm_edid.h>
> +
>  #include <linux/module.h>
>  #include <linux/seq_file.h>
>  #include <linux/uaccess.h>
> @@ -39,6 +41,7 @@ struct vga_switcheroo_client {
>  	int id;
>  	bool active;
>  	bool driver_power_control;
> +	bool use_panel;
>  	struct list_head list;
>  };
>  
> @@ -56,6 +59,9 @@ struct vgasr_priv {
>  	int registered_clients;
>  	struct list_head clients;
>  
> +	struct edid *edid;
> +	u8 *dpcd;
> +
>  	struct vga_switcheroo_handler *handler;
>  };
>  
> @@ -107,7 +113,9 @@ static void vga_switcheroo_enable(void)
>  				VGA_SWITCHEROO_DIS : VGA_SWITCHEROO_IGD;
>  			if (vgasr_priv.handler->switch_ddc)
>  				vgasr_priv.handler->switch_ddc(client->id);
> +			client->use_panel = true;
>  			client->ops->reprobe_connectors(client->pdev);
> +			client->use_panel = false;
>  			if (vgasr_priv.handler->switch_ddc)
>  				vgasr_priv.handler->switch_ddc(old_id);
>  		}
> @@ -412,6 +420,9 @@ static int vga_switchto_stage2(struct vga_switcheroo_client *new_client)
>  	if (ret)
>  		goto restore_ddc;
>  
> +	new_client->use_panel = true;
> +	active->use_panel = false;
> +
>  	if (new_client->ops->reprobe)
>  		new_client->ops->reprobe(new_client->pdev);
>  
> @@ -766,6 +777,54 @@ int vga_switcheroo_init_domain_pm_optimus_hdmi_audio(struct device *dev, struct
>  }
>  EXPORT_SYMBOL(vga_switcheroo_init_domain_pm_optimus_hdmi_audio);
>  
> +int vga_switcheroo_set_dpcd(u8 *dpcd)

Quite a few DPCD related things in drm_dp_helper.h expect
DP_RECEIVER_CAP_SIZE bytes of DPCD. Might be helpful to conform to that.

Can also be made const u8 *.

> +{
> +	if (vgasr_priv.dpcd)
> +		return -EEXIST;
> +
> +	vgasr_priv.dpcd = kmalloc(8, GFP_KERNEL);
> +	memcpy(vgasr_priv.dpcd, dpcd, 8);

kmemdup.

> +	return 0;
> +}
> +EXPORT_SYMBOL(vga_switcheroo_set_dpcd);
> +
> +u8 *vga_switcheroo_get_dpcd(struct pci_dev *pdev)
> +{
> +	struct vga_switcheroo_client *client;
> +	client = find_client_from_pci(&vgasr_priv.clients, pdev);
> +
> +	if (!client || !client->use_panel)
> +		return NULL;
> +
> +	return vgasr_priv.dpcd;
> +}
> +EXPORT_SYMBOL(vga_switcheroo_get_dpcd);
> +
> +int vga_switcheroo_set_edid(struct edid *edid)
> +{
> +	int size = EDID_LENGTH * (1 + edid->extensions);
> +
> +	if (vgasr_priv.edid)
> +		return -EEXIST;
> +
> +	vgasr_priv.edid = kmalloc(size, GFP_KERNEL);
> +	memcpy(vgasr_priv.edid, edid, size);

kmemdup.

BR,
Jani.

> +	return 0;
> +}
> +EXPORT_SYMBOL(vga_switcheroo_set_edid);
> +
> +struct edid *vga_switcheroo_get_edid(struct pci_dev *pdev)
> +{
> +	struct vga_switcheroo_client *client;
> +	client = find_client_from_pci(&vgasr_priv.clients, pdev);
> +
> +	if (!client || !client->use_panel)
> +		return NULL;
> +
> +	return vgasr_priv.edid;
> +}
> +EXPORT_SYMBOL(vga_switcheroo_get_edid);
> +
>  static int __init vga_switcheroo_setup(char *str)
>  {
>  	if (!strcmp(str, "IGD"))
> diff --git a/include/linux/vga_switcheroo.h b/include/linux/vga_switcheroo.h
> index bae62fd..07b07fc 100644
> --- a/include/linux/vga_switcheroo.h
> +++ b/include/linux/vga_switcheroo.h
> @@ -10,6 +10,7 @@
>  #ifndef _LINUX_VGA_SWITCHEROO_H_
>  #define _LINUX_VGA_SWITCHEROO_H_
>  
> +#include <drm/drm_edid.h>
>  #include <linux/fb.h>
>  
>  struct pci_dev;
> @@ -69,6 +70,12 @@ void vga_switcheroo_set_dynamic_switch(struct pci_dev *pdev, enum vga_switcheroo
>  
>  int vga_switcheroo_init_domain_pm_ops(struct device *dev, struct dev_pm_domain *domain);
>  int vga_switcheroo_init_domain_pm_optimus_hdmi_audio(struct device *dev, struct dev_pm_domain *domain);
> +
> +int vga_switcheroo_set_dpcd(u8 *dpcd);
> +u8 *vga_switcheroo_get_dpcd(struct pci_dev *pdev);
> +int vga_switcheroo_set_edid(struct edid *edid);
> +struct edid *vga_switcheroo_get_edid(struct pci_dev *pdev);
> +
>  #else
>  
>  static inline void vga_switcheroo_unregister_client(struct pci_dev *dev) {}
> @@ -89,5 +96,10 @@ static inline void vga_switcheroo_set_dynamic_switch(struct pci_dev *pdev, enum
>  static inline int vga_switcheroo_init_domain_pm_ops(struct device *dev, struct dev_pm_domain *domain) { return -EINVAL; }
>  static inline int vga_switcheroo_init_domain_pm_optimus_hdmi_audio(struct device *dev, struct dev_pm_domain *domain) { return -EINVAL; }
>  
> +static inline int vga_switcheroo_set_dpcd(u8 *dpcd) { return 0 };
> +static inline u8 *vga_switcheroo_get_dpcd(struct pci_dev *pdev) { return NULL };
> +static inline int vga_switcheroo_set_edid(struct edid *edid) { return 0 };
> +static inline struct edid *vga_switcheroo_get_edid(struct pci_dev *pdev) { return NULL };
> +
>  #endif
>  #endif /* _LINUX_VGA_SWITCHEROO_H_ */
> -- 
> 1.8.5.3
>
> _______________________________________________
> dri-devel mailing list
> dri-devel@lists.freedesktop.org
> http://lists.freedesktop.org/mailman/listinfo/dri-devel

-- 
Jani Nikula, Intel Open Source Technology Center

^ permalink raw reply	[flat|nested] 17+ messages in thread

* Re: [PATCH 01/11] vga_switcheroo: Add support for switching only the DDC
  2014-06-01 16:38 ` [PATCH 01/11] vga_switcheroo: Add support for switching only the DDC Matthew Garrett
  2014-06-03 13:26   ` Jani Nikula
@ 2014-06-12  0:37   ` Dave Airlie
  1 sibling, 0 replies; 17+ messages in thread
From: Dave Airlie @ 2014-06-12  0:37 UTC (permalink / raw)
  To: Matthew Garrett; +Cc: dri-devel, platform-driver-x86, Seth Forshee

On 2 June 2014 02:38, Matthew Garrett <matthew.garrett@nebula.com> wrote:
> From: Seth Forshee <seth.forshee@canonical.com>
>
> During graphics driver initialization its useful to be able to mux only
> the DDC to the inactive client in order to read the EDID. Add a
> switch_ddc callback to allow capable handlers to provide this
> functionality, and add vga_switcheroo_switch_ddc() to allow DRM to mux
> only the DDC.
>

I can't figure out why I didn't like this, but I rewrote this way back
to lock/unlock the ddc lines,
bits are contained in this WIP mess.
http://cgit.freedesktop.org/~airlied/linux/commit/?h=switchy-wip&id=aead3bb72d82bd63149082a2670cc2521f2290a4

I think I'd prefer something like that otherwise the interface got really ugly.

Dave.

^ permalink raw reply	[flat|nested] 17+ messages in thread

* [PATCH 01/11] vga_switcheroo: Add support for switching only the DDC
  2015-04-21  9:58 [PATCH 00/11] Enable gpu switching on the MacBook Pro Lukas Wunner
@ 2012-09-07 15:22 ` Lukas Wunner
  0 siblings, 0 replies; 17+ messages in thread
From: Lukas Wunner @ 2012-09-07 15:22 UTC (permalink / raw)
  To: dri-devel; +Cc: Daniel Vetter, Seth Forshee, Matthew Garrett, Dave Airlie

From: Seth Forshee <seth.forshee@canonical.com>

During graphics driver initialization its useful to be able to mux only
the DDC to the inactive client in order to read the EDID. Add a
switch_ddc callback to allow capable handlers to provide this
functionality, and add vga_switcheroo_switch_ddc() to allow DRM to mux
only the DDC.

Signed-off-by: Seth Forshee <seth.forshee@canonical.com>
Signed-off-by: Dave Airlie <airlied@gmail.com>
Signed-off-by: Lukas Wunner <lukas@wunner.de>
---
 drivers/gpu/vga/vga_switcheroo.c | 39 ++++++++++++++++++++++++++++++++++++++-
 include/linux/vga_switcheroo.h   |  4 ++++
 2 files changed, 42 insertions(+), 1 deletion(-)

diff --git a/drivers/gpu/vga/vga_switcheroo.c b/drivers/gpu/vga/vga_switcheroo.c
index 37ac7b5..0d3ac20 100644
--- a/drivers/gpu/vga/vga_switcheroo.c
+++ b/drivers/gpu/vga/vga_switcheroo.c
@@ -256,6 +256,29 @@ void vga_switcheroo_client_fb_set(struct pci_dev *pdev,
 }
 EXPORT_SYMBOL(vga_switcheroo_client_fb_set);
 
+int vga_switcheroo_switch_ddc(struct pci_dev *pdev)
+{
+	int ret = 0;
+	int id;
+
+	mutex_lock(&vgasr_mutex);
+
+	if (!vgasr_priv.handler) {
+		ret = -ENODEV;
+		goto out;
+	}
+
+	if (vgasr_priv.handler->switch_ddc) {
+		id = vgasr_priv.handler->get_client_id(pdev);
+		ret = vgasr_priv.handler->switch_ddc(id);
+	}
+
+out:
+	mutex_unlock(&vgasr_mutex);
+	return ret;
+}
+EXPORT_SYMBOL(vga_switcheroo_switch_ddc);
+
 static int vga_switcheroo_show(struct seq_file *m, void *v)
 {
 	struct vga_switcheroo_client *client;
@@ -353,9 +376,15 @@ static int vga_switchto_stage2(struct vga_switcheroo_client *new_client)
 		console_unlock();
 	}
 
+	if (vgasr_priv.handler->switch_ddc) {
+		ret = vgasr_priv.handler->switch_ddc(new_client->id);
+		if (ret)
+			return ret;
+	}
+
 	ret = vgasr_priv.handler->switchto(new_client->id);
 	if (ret)
-		return ret;
+		goto restore_ddc;
 
 	if (new_client->ops->reprobe)
 		new_client->ops->reprobe(new_client->pdev);
@@ -367,6 +396,14 @@ static int vga_switchto_stage2(struct vga_switcheroo_client *new_client)
 
 	new_client->active = true;
 	return 0;
+
+restore_ddc:
+	if (vgasr_priv.handler->switch_ddc) {
+		int id = (new_client->id == VGA_SWITCHEROO_IGD) ?
+				VGA_SWITCHEROO_DIS : VGA_SWITCHEROO_IGD;
+		ret = vgasr_priv.handler->switch_ddc(id);
+	}
+	return ret;
 }
 
 static bool check_can_switch(void)
diff --git a/include/linux/vga_switcheroo.h b/include/linux/vga_switcheroo.h
index b483abd..2fef78b 100644
--- a/include/linux/vga_switcheroo.h
+++ b/include/linux/vga_switcheroo.h
@@ -29,6 +29,7 @@ enum vga_switcheroo_client_id {
 };
 
 struct vga_switcheroo_handler {
+	int (*switch_ddc)(enum vga_switcheroo_client_id id);
 	int (*switchto)(enum vga_switcheroo_client_id id);
 	int (*power_state)(enum vga_switcheroo_client_id id,
 			   enum vga_switcheroo_state state);
@@ -54,6 +55,8 @@ int vga_switcheroo_register_audio_client(struct pci_dev *pdev,
 void vga_switcheroo_client_fb_set(struct pci_dev *dev,
 				  struct fb_info *info);
 
+int vga_switcheroo_switch_ddc(struct pci_dev *pdev);
+
 int vga_switcheroo_register_handler(struct vga_switcheroo_handler *handler);
 void vga_switcheroo_unregister_handler(void);
 
@@ -72,6 +75,7 @@ static inline void vga_switcheroo_unregister_client(struct pci_dev *dev) {}
 static inline int vga_switcheroo_register_client(struct pci_dev *dev,
 		const struct vga_switcheroo_client_ops *ops, bool driver_power_control) { return 0; }
 static inline void vga_switcheroo_client_fb_set(struct pci_dev *dev, struct fb_info *info) {}
+static inline void vga_switcheroo_switch_ddc(struct pci_dev *pdev) { return NULL; }
 static inline int vga_switcheroo_register_handler(struct vga_switcheroo_handler *handler) { return 0; }
 static inline int vga_switcheroo_register_audio_client(struct pci_dev *pdev,
 	const struct vga_switcheroo_client_ops *ops,
-- 
1.8.5.2 (Apple Git-48)

_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/dri-devel

^ permalink raw reply related	[flat|nested] 17+ messages in thread

end of thread, other threads:[~2015-04-21 11:36 UTC | newest]

Thread overview: 17+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2014-06-01 16:38 Improve Apple GMUX support on switcheroo Matthew Garrett
2014-06-01 16:38 ` [PATCH 01/11] vga_switcheroo: Add support for switching only the DDC Matthew Garrett
2014-06-03 13:26   ` Jani Nikula
2014-06-12  0:37   ` Dave Airlie
2014-06-01 16:38 ` [PATCH 02/11] vga_switcheroo: Add support for reprobing connectors Matthew Garrett
2014-06-01 16:38 ` [PATCH 03/11] vga_switcheroo: Add command line option Matthew Garrett
2014-06-01 16:38 ` [PATCH 04/11] vga_switcheroo: Allow stashing of panel data Matthew Garrett
2014-06-03 13:40   ` Jani Nikula
2014-06-01 16:38 ` [PATCH 05/11] vga_switcheroo: Allow handlers to indicate that they can handle PM Matthew Garrett
2014-06-01 16:38 ` [PATCH 06/11] vga_switcheroo: Add enable() call to clients and permit deferral of dynamic PM Matthew Garrett
2014-06-01 16:38 ` [PATCH 07/11] vga_switcheroo: Reprobe old device on switching Matthew Garrett
2014-06-01 16:38 ` [PATCH 08/11] apple-gmux: Add support for the switch_ddc callback Matthew Garrett
2014-06-02 14:35   ` Alex Deucher
2014-06-01 16:38 ` [PATCH 09/11] apple-gmux: Assign apple_gmux_data before registering Matthew Garrett
2014-06-01 16:38 ` [PATCH 10/11] apple-gmux: Indicate that driver supports changing of GPU power states Matthew Garrett
2014-06-01 16:38 ` [PATCH 11/11] apple_gmux: Wait for switch completion Matthew Garrett
2015-04-21  9:58 [PATCH 00/11] Enable gpu switching on the MacBook Pro Lukas Wunner
2012-09-07 15:22 ` [PATCH 01/11] vga_switcheroo: Add support for switching only the DDC Lukas Wunner

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.