vga_switcheroo.c (3a848662c75118e1ee4653e08e25943d8b4ab8b7) vga_switcheroo.c (989561de9b5112999475b406557d9c7e9e59c041)
1/*
2 * vga_switcheroo.c - Support for laptop with dual GPU using one set of outputs
3 *
4 * Copyright (c) 2010 Red Hat Inc.
5 * Author : Dave Airlie <airlied@redhat.com>
6 *
7 * Copyright (c) 2015 Lukas Wunner <lukas@wunner.de>
8 *

--- 22 unchanged lines hidden (view full) ---

31#define pr_fmt(fmt) "vga_switcheroo: " fmt
32
33#include <linux/console.h>
34#include <linux/debugfs.h>
35#include <linux/fb.h>
36#include <linux/fs.h>
37#include <linux/module.h>
38#include <linux/pci.h>
1/*
2 * vga_switcheroo.c - Support for laptop with dual GPU using one set of outputs
3 *
4 * Copyright (c) 2010 Red Hat Inc.
5 * Author : Dave Airlie <airlied@redhat.com>
6 *
7 * Copyright (c) 2015 Lukas Wunner <lukas@wunner.de>
8 *

--- 22 unchanged lines hidden (view full) ---

31#define pr_fmt(fmt) "vga_switcheroo: " fmt
32
33#include <linux/console.h>
34#include <linux/debugfs.h>
35#include <linux/fb.h>
36#include <linux/fs.h>
37#include <linux/module.h>
38#include <linux/pci.h>
39#include <linux/pm_domain.h>
39#include <linux/pm_runtime.h>
40#include <linux/seq_file.h>
41#include <linux/uaccess.h>
42#include <linux/vgaarb.h>
43#include <linux/vga_switcheroo.h>
44
45/**
46 * DOC: Overview

--- 11 unchanged lines hidden (view full) ---

58 * all muxed. Newer laptops moved to a muxless architecture for cost reasons.
59 * A notable exception is the MacBook Pro which continues to use a mux.
60 * Muxes come with varying capabilities: Some switch only the panel, others
61 * can also switch external displays. Some switch all display pins at once
62 * while others can switch just the DDC lines. (To allow EDID probing
63 * for the inactive GPU.) Also, muxes are often used to cut power to the
64 * discrete GPU while it is not used.
65 *
40#include <linux/pm_runtime.h>
41#include <linux/seq_file.h>
42#include <linux/uaccess.h>
43#include <linux/vgaarb.h>
44#include <linux/vga_switcheroo.h>
45
46/**
47 * DOC: Overview

--- 11 unchanged lines hidden (view full) ---

59 * all muxed. Newer laptops moved to a muxless architecture for cost reasons.
60 * A notable exception is the MacBook Pro which continues to use a mux.
61 * Muxes come with varying capabilities: Some switch only the panel, others
62 * can also switch external displays. Some switch all display pins at once
63 * while others can switch just the DDC lines. (To allow EDID probing
64 * for the inactive GPU.) Also, muxes are often used to cut power to the
65 * discrete GPU while it is not used.
66 *
66 * DRM drivers register GPUs with vga_switcheroo, these are henceforth called
67 * DRM drivers register GPUs with vga_switcheroo, these are heretoforth called
67 * clients. The mux is called the handler. Muxless machines also register a
68 * handler to control the power state of the discrete GPU, its ->switchto
69 * callback is a no-op for obvious reasons. The discrete GPU is often equipped
70 * with an HDA controller for the HDMI/DP audio signal, this will also
71 * register as a client so that vga_switcheroo can take care of the correct
72 * suspend/resume order when changing the discrete GPU's power state. In total
73 * there can thus be up to three clients: Two vga clients (GPUs) and one audio
74 * client (on the discrete GPU). The code is mostly prepared to support

--- 838 unchanged lines hidden (view full) ---

913 struct dev_pm_domain *domain)
914{
915 /* copy over all the bus versions */
916 if (dev->bus && dev->bus->pm) {
917 domain->ops = *dev->bus->pm;
918 domain->ops.runtime_suspend = vga_switcheroo_runtime_suspend;
919 domain->ops.runtime_resume = vga_switcheroo_runtime_resume;
920
68 * clients. The mux is called the handler. Muxless machines also register a
69 * handler to control the power state of the discrete GPU, its ->switchto
70 * callback is a no-op for obvious reasons. The discrete GPU is often equipped
71 * with an HDA controller for the HDMI/DP audio signal, this will also
72 * register as a client so that vga_switcheroo can take care of the correct
73 * suspend/resume order when changing the discrete GPU's power state. In total
74 * there can thus be up to three clients: Two vga clients (GPUs) and one audio
75 * client (on the discrete GPU). The code is mostly prepared to support

--- 838 unchanged lines hidden (view full) ---

914 struct dev_pm_domain *domain)
915{
916 /* copy over all the bus versions */
917 if (dev->bus && dev->bus->pm) {
918 domain->ops = *dev->bus->pm;
919 domain->ops.runtime_suspend = vga_switcheroo_runtime_suspend;
920 domain->ops.runtime_resume = vga_switcheroo_runtime_resume;
921
921 dev->pm_domain = domain;
922 dev_pm_domain_set(dev, domain);
922 return 0;
923 }
923 return 0;
924 }
924 dev->pm_domain = NULL;
925 dev_pm_domain_set(dev, NULL);
925 return -EINVAL;
926}
927EXPORT_SYMBOL(vga_switcheroo_init_domain_pm_ops);
928
929void vga_switcheroo_fini_domain_pm_ops(struct device *dev)
930{
926 return -EINVAL;
927}
928EXPORT_SYMBOL(vga_switcheroo_init_domain_pm_ops);
929
930void vga_switcheroo_fini_domain_pm_ops(struct device *dev)
931{
931 dev->pm_domain = NULL;
932 dev_pm_domain_set(dev, NULL);
932}
933EXPORT_SYMBOL(vga_switcheroo_fini_domain_pm_ops);
934
935static int vga_switcheroo_runtime_resume_hdmi_audio(struct device *dev)
936{
937 struct pci_dev *pdev = to_pci_dev(dev);
938 struct vga_switcheroo_client *client;
939 struct device *video_dev = NULL;

--- 44 unchanged lines hidden (view full) ---

984 struct dev_pm_domain *domain)
985{
986 /* copy over all the bus versions */
987 if (dev->bus && dev->bus->pm) {
988 domain->ops = *dev->bus->pm;
989 domain->ops.runtime_resume =
990 vga_switcheroo_runtime_resume_hdmi_audio;
991
933}
934EXPORT_SYMBOL(vga_switcheroo_fini_domain_pm_ops);
935
936static int vga_switcheroo_runtime_resume_hdmi_audio(struct device *dev)
937{
938 struct pci_dev *pdev = to_pci_dev(dev);
939 struct vga_switcheroo_client *client;
940 struct device *video_dev = NULL;

--- 44 unchanged lines hidden (view full) ---

985 struct dev_pm_domain *domain)
986{
987 /* copy over all the bus versions */
988 if (dev->bus && dev->bus->pm) {
989 domain->ops = *dev->bus->pm;
990 domain->ops.runtime_resume =
991 vga_switcheroo_runtime_resume_hdmi_audio;
992
992 dev->pm_domain = domain;
993 dev_pm_domain_set(dev, domain);
993 return 0;
994 }
994 return 0;
995 }
995 dev->pm_domain = NULL;
996 dev_pm_domain_set(dev, NULL);
996 return -EINVAL;
997}
998EXPORT_SYMBOL(vga_switcheroo_init_domain_pm_optimus_hdmi_audio);
997 return -EINVAL;
998}
999EXPORT_SYMBOL(vga_switcheroo_init_domain_pm_optimus_hdmi_audio);