From patchwork Sun Jun 1 16:38:36 2014 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Matthew Garrett X-Patchwork-Id: 4279391 Return-Path: X-Original-To: patchwork-dri-devel@patchwork.kernel.org Delivered-To: patchwork-parsemail@patchwork2.web.kernel.org Received: from mail.kernel.org (mail.kernel.org [198.145.19.201]) by patchwork2.web.kernel.org (Postfix) with ESMTP id 94915BEEAA for ; Mon, 2 Jun 2014 00:52:19 +0000 (UTC) Received: from mail.kernel.org (localhost [127.0.0.1]) by mail.kernel.org (Postfix) with ESMTP id AF3ED20397 for ; Mon, 2 Jun 2014 00:52:18 +0000 (UTC) Received: from gabe.freedesktop.org (gabe.freedesktop.org [131.252.210.177]) by mail.kernel.org (Postfix) with ESMTP id A1859203AA for ; Mon, 2 Jun 2014 00:52:17 +0000 (UTC) Received: from gabe.freedesktop.org (localhost [127.0.0.1]) by gabe.freedesktop.org (Postfix) with ESMTP id 0110D6E446; Sun, 1 Jun 2014 17:52:08 -0700 (PDT) X-Original-To: dri-devel@lists.freedesktop.org Delivered-To: dri-devel@lists.freedesktop.org Received: from cavan.codon.org.uk (cavan.codon.org.uk [93.93.128.6]) by gabe.freedesktop.org (Postfix) with ESMTP id A7C456E3D9 for ; Sun, 1 Jun 2014 10:24:24 -0700 (PDT) Received: from 209-6-207-143.c3-0.smr-ubr2.sbo-smr.ma.cable.rcn.com ([209.6.207.143] helo=localhost.lan) by cavan.codon.org.uk with esmtpsa (TLS1.2:DHE_RSA_AES_256_CBC_SHA256:256) (Exim 4.80) (envelope-from ) id 1Wr8mh-00062c-Hb; Sun, 01 Jun 2014 17:39:03 +0100 From: Matthew Garrett To: airlied@gmail.com Date: Sun, 1 Jun 2014 12:38:36 -0400 Message-Id: <1401640723-2058-5-git-send-email-matthew.garrett@nebula.com> X-Mailer: git-send-email 1.8.5.3 In-Reply-To: <1401640723-2058-1-git-send-email-matthew.garrett@nebula.com> References: <1401640723-2058-1-git-send-email-matthew.garrett@nebula.com> X-SA-Do-Not-Run: Yes X-SA-Exim-Connect-IP: 209.6.207.143 X-SA-Exim-Mail-From: matthew.garrett@nebula.com X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on mail.kernel.org X-Spam-Level: X-Spam-Status: No, score=-4.8 required=5.0 tests=BAYES_00, RCVD_IN_DNSWL_MED, RP_MATCHES_RCVD, UNPARSEABLE_RELAY autolearn=unavailable version=3.3.1 X-Spam-ASN: Subject: [PATCH 04/11] vga_switcheroo: Allow stashing of panel data X-SA-Exim-Version: 4.2.1 (built Mon, 26 Dec 2011 16:54:46 +0000) X-SA-Exim-Scanned: Yes (on cavan.codon.org.uk) X-Mailman-Approved-At: Sun, 01 Jun 2014 17:52:06 -0700 Cc: Matthew Garrett , dri-devel@lists.freedesktop.org, platform-driver-x86@vger.kernel.org X-BeenThere: dri-devel@lists.freedesktop.org X-Mailman-Version: 2.1.15 Precedence: list List-Id: Direct Rendering Infrastructure - Development List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , MIME-Version: 1.0 Errors-To: dri-devel-bounces@lists.freedesktop.org Sender: "dri-devel" X-Virus-Scanned: ClamAV using ClamSMTP 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 --- 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 + #include #include #include @@ -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 #include 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_ */