summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Documentation/DocBook/gpu.tmpl1
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_atpx_handler.c3
-rw-r--r--drivers/gpu/drm/nouveau/nouveau_acpi.c2
-rw-r--r--drivers/gpu/drm/radeon/radeon_atpx_handler.c3
-rw-r--r--drivers/gpu/vga/vga_switcheroo.c22
-rw-r--r--drivers/platform/x86/apple-gmux.c2
-rw-r--r--include/linux/vga_switcheroo.h28
7 files changed, 54 insertions, 7 deletions
diff --git a/Documentation/DocBook/gpu.tmpl b/Documentation/DocBook/gpu.tmpl
index 49c97913c5ae..d6579d8c1341 100644
--- a/Documentation/DocBook/gpu.tmpl
+++ b/Documentation/DocBook/gpu.tmpl
@@ -3422,6 +3422,7 @@ int num_ioctls;</synopsis>
</sect1>
<sect1>
<title>Public constants</title>
+!Finclude/linux/vga_switcheroo.h vga_switcheroo_handler_flags_t
!Finclude/linux/vga_switcheroo.h vga_switcheroo_client_id
!Finclude/linux/vga_switcheroo.h vga_switcheroo_state
</sect1>
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_atpx_handler.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_atpx_handler.c
index 3c895863fcf5..fa948dcbdd5d 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_atpx_handler.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_atpx_handler.c
@@ -552,13 +552,14 @@ static bool amdgpu_atpx_detect(void)
void amdgpu_register_atpx_handler(void)
{
bool r;
+ enum vga_switcheroo_handler_flags_t handler_flags = 0;
/* detect if we have any ATPX + 2 VGA in the system */
r = amdgpu_atpx_detect();
if (!r)
return;
- vga_switcheroo_register_handler(&amdgpu_atpx_handler);
+ vga_switcheroo_register_handler(&amdgpu_atpx_handler, handler_flags);
}
/**
diff --git a/drivers/gpu/drm/nouveau/nouveau_acpi.c b/drivers/gpu/drm/nouveau/nouveau_acpi.c
index d5e6938cc6bc..cdf522770cfa 100644
--- a/drivers/gpu/drm/nouveau/nouveau_acpi.c
+++ b/drivers/gpu/drm/nouveau/nouveau_acpi.c
@@ -314,7 +314,7 @@ void nouveau_register_dsm_handler(void)
if (!r)
return;
- vga_switcheroo_register_handler(&nouveau_dsm_handler);
+ vga_switcheroo_register_handler(&nouveau_dsm_handler, 0);
}
/* Must be called for Optimus models before the card can be turned off */
diff --git a/drivers/gpu/drm/radeon/radeon_atpx_handler.c b/drivers/gpu/drm/radeon/radeon_atpx_handler.c
index c4b4f298a283..56482e35d43e 100644
--- a/drivers/gpu/drm/radeon/radeon_atpx_handler.c
+++ b/drivers/gpu/drm/radeon/radeon_atpx_handler.c
@@ -551,13 +551,14 @@ static bool radeon_atpx_detect(void)
void radeon_register_atpx_handler(void)
{
bool r;
+ enum vga_switcheroo_handler_flags_t handler_flags = 0;
/* detect if we have any ATPX + 2 VGA in the system */
r = radeon_atpx_detect();
if (!r)
return;
- vga_switcheroo_register_handler(&radeon_atpx_handler);
+ vga_switcheroo_register_handler(&radeon_atpx_handler, handler_flags);
}
/**
diff --git a/drivers/gpu/vga/vga_switcheroo.c b/drivers/gpu/vga/vga_switcheroo.c
index 665ab9fd0e01..e89f6ad5d83e 100644
--- a/drivers/gpu/vga/vga_switcheroo.c
+++ b/drivers/gpu/vga/vga_switcheroo.c
@@ -126,6 +126,7 @@ static DEFINE_MUTEX(vgasr_mutex);
* (counting only vga clients, not audio clients)
* @clients: list of registered clients
* @handler: registered handler
+ * @handler_flags: flags of registered handler
*
* vga_switcheroo private data. Currently only one vga_switcheroo instance
* per system is supported.
@@ -142,6 +143,7 @@ struct vgasr_priv {
struct list_head clients;
const struct vga_switcheroo_handler *handler;
+ enum vga_switcheroo_handler_flags_t handler_flags;
};
#define ID_BIT_AUDIO 0x100
@@ -190,13 +192,15 @@ static void vga_switcheroo_enable(void)
/**
* vga_switcheroo_register_handler() - register handler
* @handler: handler callbacks
+ * @handler_flags: handler flags
*
* Register handler. Enable vga_switcheroo if two vga clients have already
* registered.
*
* Return: 0 on success, -EINVAL if a handler was already registered.
*/
-int vga_switcheroo_register_handler(const struct vga_switcheroo_handler *handler)
+int vga_switcheroo_register_handler(const struct vga_switcheroo_handler *handler,
+ enum vga_switcheroo_handler_flags_t handler_flags)
{
mutex_lock(&vgasr_mutex);
if (vgasr_priv.handler) {
@@ -205,6 +209,7 @@ int vga_switcheroo_register_handler(const struct vga_switcheroo_handler *handler
}
vgasr_priv.handler = handler;
+ vgasr_priv.handler_flags = handler_flags;
if (vga_switcheroo_ready()) {
pr_info("enabled\n");
vga_switcheroo_enable();
@@ -222,6 +227,7 @@ EXPORT_SYMBOL(vga_switcheroo_register_handler);
void vga_switcheroo_unregister_handler(void)
{
mutex_lock(&vgasr_mutex);
+ vgasr_priv.handler_flags = 0;
vgasr_priv.handler = NULL;
if (vgasr_priv.active) {
pr_info("disabled\n");
@@ -232,6 +238,20 @@ void vga_switcheroo_unregister_handler(void)
}
EXPORT_SYMBOL(vga_switcheroo_unregister_handler);
+/**
+ * vga_switcheroo_handler_flags() - obtain handler flags
+ *
+ * Helper for clients to obtain the handler flags bitmask.
+ *
+ * Return: Handler flags. A value of 0 means that no handler is registered
+ * or that the handler has no special capabilities.
+ */
+enum vga_switcheroo_handler_flags_t vga_switcheroo_handler_flags(void)
+{
+ return vgasr_priv.handler_flags;
+}
+EXPORT_SYMBOL(vga_switcheroo_handler_flags);
+
static int register_client(struct pci_dev *pdev,
const struct vga_switcheroo_client_ops *ops,
enum vga_switcheroo_client_id id, bool active,
diff --git a/drivers/platform/x86/apple-gmux.c b/drivers/platform/x86/apple-gmux.c
index f236250ac106..c401d4936b65 100644
--- a/drivers/platform/x86/apple-gmux.c
+++ b/drivers/platform/x86/apple-gmux.c
@@ -705,7 +705,7 @@ static int gmux_probe(struct pnp_dev *pnp, const struct pnp_device_id *id)
init_completion(&gmux_data->powerchange_done);
gmux_enable_interrupts(gmux_data);
- if (vga_switcheroo_register_handler(&gmux_handler)) {
+ if (vga_switcheroo_register_handler(&gmux_handler, 0)) {
ret = -ENODEV;
goto err_register_handler;
}
diff --git a/include/linux/vga_switcheroo.h b/include/linux/vga_switcheroo.h
index 69e1d4a1f1b3..a745f4f0f729 100644
--- a/include/linux/vga_switcheroo.h
+++ b/include/linux/vga_switcheroo.h
@@ -36,6 +36,26 @@
struct pci_dev;
/**
+ * enum vga_switcheroo_handler_flags_t - handler flags bitmask
+ * @VGA_SWITCHEROO_CAN_SWITCH_DDC: whether the handler is able to switch the
+ * DDC lines separately. This signals to clients that they should call
+ * drm_get_edid_switcheroo() to probe the EDID
+ * @VGA_SWITCHEROO_NEEDS_EDP_CONFIG: whether the handler is unable to switch
+ * the AUX channel separately. This signals to clients that the active
+ * GPU needs to train the link and communicate the link parameters to the
+ * inactive GPU (mediated by vga_switcheroo). The inactive GPU may then
+ * skip the AUX handshake and set up its output with these pre-calibrated
+ * values (DisplayPort specification v1.1a, section 2.5.3.3)
+ *
+ * Handler flags bitmask. Used by handlers to declare their capabilities upon
+ * registering with vga_switcheroo.
+ */
+enum vga_switcheroo_handler_flags_t {
+ VGA_SWITCHEROO_CAN_SWITCH_DDC = (1 << 0),
+ VGA_SWITCHEROO_NEEDS_EDP_CONFIG = (1 << 1),
+};
+
+/**
* enum vga_switcheroo_state - client power state
* @VGA_SWITCHEROO_OFF: off
* @VGA_SWITCHEROO_ON: on
@@ -132,8 +152,10 @@ 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_register_handler(const struct vga_switcheroo_handler *handler);
+int vga_switcheroo_register_handler(const struct vga_switcheroo_handler *handler,
+ enum vga_switcheroo_handler_flags_t handler_flags);
void vga_switcheroo_unregister_handler(void);
+enum vga_switcheroo_handler_flags_t vga_switcheroo_handler_flags(void);
int vga_switcheroo_process_delayed_switch(void);
@@ -150,11 +172,13 @@ 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 int vga_switcheroo_register_handler(const struct vga_switcheroo_handler *handler) { return 0; }
+static inline int vga_switcheroo_register_handler(const struct vga_switcheroo_handler *handler,
+ enum vga_switcheroo_handler_flags_t handler_flags) { return 0; }
static inline int vga_switcheroo_register_audio_client(struct pci_dev *pdev,
const struct vga_switcheroo_client_ops *ops,
enum vga_switcheroo_client_id id) { return 0; }
static inline void vga_switcheroo_unregister_handler(void) {}
+static inline enum vga_switcheroo_handler_flags_t vga_switcheroo_handler_flags(void) { return 0; }
static inline int vga_switcheroo_process_delayed_switch(void) { return 0; }
static inline enum vga_switcheroo_state vga_switcheroo_get_client_state(struct pci_dev *dev) { return VGA_SWITCHEROO_ON; }