diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index a8538ac..2f0428d 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -31,6 +31,7 @@ #include #include #include +#include #include #include "drmP.h" #include "intel_drv.h" @@ -6506,7 +6507,11 @@ static void intel_setup_outputs(struct drm_device *dev) bool dpd_is_edp = false; bool has_lvds; + /* Switch mux so lvds is detectable */ + vga_switcheroo_lock_ddc(dev->pdev); has_lvds = intel_lvds_init(dev); + vga_switcheroo_unlock_ddc(dev->pdev); + if (!has_lvds && !HAS_PCH_SPLIT(dev)) { /* disable the panel fitter on everything but LVDS */ I915_WRITE(PFIT_CONTROL, 0); diff --git a/drivers/gpu/vga/vga_switcheroo.c b/drivers/gpu/vga/vga_switcheroo.c index 5b3c7d1..ee137c3 100644 --- a/drivers/gpu/vga/vga_switcheroo.c +++ b/drivers/gpu/vga/vga_switcheroo.c @@ -41,6 +41,7 @@ struct vga_switcheroo_client { }; static DEFINE_MUTEX(vgasr_mutex); +static DEFINE_MUTEX(vgasr_ddc_mutex); struct vgasr_priv { @@ -553,3 +554,45 @@ err: } EXPORT_SYMBOL(vga_switcheroo_process_delayed_switch); +int vga_switcheroo_lock_ddc(struct pci_dev *pdev) +{ + + printk(KERN_INFO "vga_switcheroo: ddc lock\n"); + + mutex_lock(&vgasr_mutex); + + if (vgasr_priv.handler && vgasr_priv.handler->switchddc && + vgasr_priv.handler->get_client_id) { + int client_id = vgasr_priv.handler->get_client_id(pdev); + printk(KERN_INFO "vga_switcheroo: ddc lock got handler\n"); + mutex_unlock(&vgasr_mutex); + mutex_lock(&vgasr_ddc_mutex); + return vgasr_priv.handler->switchddc(client_id); + } else { + printk(KERN_INFO "vga_switcheroo: ddc lock no handler\n"); + } + + mutex_unlock(&vgasr_mutex); + return 0; +} +EXPORT_SYMBOL(vga_switcheroo_lock_ddc); + +void vga_switcheroo_unlock_ddc(struct pci_dev *pdev) +{ + static struct vga_switcheroo_client *active_client; + + printk(KERN_INFO "vga_switcheroo: ddc unlock\n"); + + mutex_lock(&vgasr_mutex); + active_client = find_active_client(&vgasr_priv.clients); + + if (vgasr_priv.handler && vgasr_priv.handler->switchddc && + active_client) + vgasr_priv.handler->switchddc(active_client->id); + else + printk(KERN_INFO "vga_switcheroo: ddc unlock no handler\n"); + + mutex_unlock(&vgasr_mutex); + mutex_unlock(&vgasr_ddc_mutex); +} +EXPORT_SYMBOL(vga_switcheroo_unlock_ddc); diff --git a/include/linux/vga_switcheroo.h b/include/linux/vga_switcheroo.h index ddb419c..4538df6 100644 --- a/include/linux/vga_switcheroo.h +++ b/include/linux/vga_switcheroo.h @@ -30,6 +30,7 @@ enum vga_switcheroo_client_id { struct vga_switcheroo_handler { int (*switchto)(enum vga_switcheroo_client_id id); + int (*switchddc)(enum vga_switcheroo_client_id id); int (*power_state)(enum vga_switcheroo_client_id id, enum vga_switcheroo_state state); int (*init)(void); @@ -60,6 +61,9 @@ int vga_switcheroo_process_delayed_switch(void); int vga_switcheroo_get_client_state(struct pci_dev *dev); +int vga_switcheroo_lock_ddc(struct pci_dev *dev); +void vga_switcheroo_unlock_ddc(struct pci_dev *dev); + #else static inline void vga_switcheroo_unregister_client(struct pci_dev *dev) {}