summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSeth Forshee <seth.forshee@canonical.com>2012-09-07 10:22:04 -0500
committerDave Airlie <airlied@gmail.com>2012-10-04 06:21:50 -0400
commitb07a814e77789d555a3b4c196747aea8797f8f7c (patch)
treefa784f7ae9931de49a9fc8a8fde170ef84dc9a02
parent4efe934c811fab2e5da4db9c09f1c684087273a6 (diff)
vga_switcheroo: Add support for switching only the DDC
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>
-rw-r--r--drivers/gpu/vga/vga_switcheroo.c39
-rw-r--r--include/linux/vga_switcheroo.h4
2 files changed, 42 insertions, 1 deletions
diff --git a/drivers/gpu/vga/vga_switcheroo.c b/drivers/gpu/vga/vga_switcheroo.c
index e25cf31faab2..ea6bcc2ae661 100644
--- a/drivers/gpu/vga/vga_switcheroo.c
+++ b/drivers/gpu/vga/vga_switcheroo.c
@@ -252,6 +252,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;
@@ -342,9 +365,15 @@ static int vga_switchto_stage2(struct vga_switcheroo_client *new_client)
fb_notifier_call_chain(FB_EVENT_REMAP_ALL_CONSOLE, &event);
}
+ 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);
@@ -356,6 +385,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 ddb419cf4530..b0d0839e57ff 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);
@@ -53,6 +54,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);
@@ -66,6 +69,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) { 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,