diff options
Diffstat (limited to 'drivers/gpu/vga/vga_switcheroo.c')
-rw-r--r-- | drivers/gpu/vga/vga_switcheroo.c | 62 |
1 files changed, 46 insertions, 16 deletions
diff --git a/drivers/gpu/vga/vga_switcheroo.c b/drivers/gpu/vga/vga_switcheroo.c index cbd7c986d926..5f962bfcb43c 100644 --- a/drivers/gpu/vga/vga_switcheroo.c +++ b/drivers/gpu/vga/vga_switcheroo.c | |||
@@ -30,6 +30,7 @@ | |||
30 | 30 | ||
31 | #define pr_fmt(fmt) "vga_switcheroo: " fmt | 31 | #define pr_fmt(fmt) "vga_switcheroo: " fmt |
32 | 32 | ||
33 | #include <linux/apple-gmux.h> | ||
33 | #include <linux/console.h> | 34 | #include <linux/console.h> |
34 | #include <linux/debugfs.h> | 35 | #include <linux/debugfs.h> |
35 | #include <linux/fb.h> | 36 | #include <linux/fb.h> |
@@ -51,9 +52,9 @@ | |||
51 | * | 52 | * |
52 | * * muxed: Dual GPUs with a multiplexer chip to switch outputs between GPUs. | 53 | * * muxed: Dual GPUs with a multiplexer chip to switch outputs between GPUs. |
53 | * * muxless: Dual GPUs but only one of them is connected to outputs. | 54 | * * muxless: Dual GPUs but only one of them is connected to outputs. |
54 | * The other one is merely used to offload rendering, its results | 55 | * The other one is merely used to offload rendering, its results |
55 | * are copied over PCIe into the framebuffer. On Linux this is | 56 | * are copied over PCIe into the framebuffer. On Linux this is |
56 | * supported with DRI PRIME. | 57 | * supported with DRI PRIME. |
57 | * | 58 | * |
58 | * Hybrid graphics started to appear in the late Naughties and were initially | 59 | * Hybrid graphics started to appear in the late Naughties and were initially |
59 | * all muxed. Newer laptops moved to a muxless architecture for cost reasons. | 60 | * all muxed. Newer laptops moved to a muxless architecture for cost reasons. |
@@ -308,7 +309,8 @@ static int register_client(struct pci_dev *pdev, | |||
308 | * | 309 | * |
309 | * Register vga client (GPU). Enable vga_switcheroo if another GPU and a | 310 | * Register vga client (GPU). Enable vga_switcheroo if another GPU and a |
310 | * handler have already registered. The power state of the client is assumed | 311 | * handler have already registered. The power state of the client is assumed |
311 | * to be ON. | 312 | * to be ON. Beforehand, vga_switcheroo_client_probe_defer() shall be called |
313 | * to ensure that all prerequisites are met. | ||
312 | * | 314 | * |
313 | * Return: 0 on success, -ENOMEM on memory allocation error. | 315 | * Return: 0 on success, -ENOMEM on memory allocation error. |
314 | */ | 316 | */ |
@@ -329,7 +331,8 @@ EXPORT_SYMBOL(vga_switcheroo_register_client); | |||
329 | * @id: client identifier | 331 | * @id: client identifier |
330 | * | 332 | * |
331 | * Register audio client (audio device on a GPU). The power state of the | 333 | * Register audio client (audio device on a GPU). The power state of the |
332 | * client is assumed to be ON. | 334 | * client is assumed to be ON. Beforehand, vga_switcheroo_client_probe_defer() |
335 | * shall be called to ensure that all prerequisites are met. | ||
333 | * | 336 | * |
334 | * Return: 0 on success, -ENOMEM on memory allocation error. | 337 | * Return: 0 on success, -ENOMEM on memory allocation error. |
335 | */ | 338 | */ |
@@ -376,6 +379,33 @@ find_active_client(struct list_head *head) | |||
376 | } | 379 | } |
377 | 380 | ||
378 | /** | 381 | /** |
382 | * vga_switcheroo_client_probe_defer() - whether to defer probing a given client | ||
383 | * @pdev: client pci device | ||
384 | * | ||
385 | * Determine whether any prerequisites are not fulfilled to probe a given | ||
386 | * client. Drivers shall invoke this early on in their ->probe callback | ||
387 | * and return %-EPROBE_DEFER if it evaluates to %true. Thou shalt not | ||
388 | * register the client ere thou hast called this. | ||
389 | * | ||
390 | * Return: %true if probing should be deferred, otherwise %false. | ||
391 | */ | ||
392 | bool vga_switcheroo_client_probe_defer(struct pci_dev *pdev) | ||
393 | { | ||
394 | if ((pdev->class >> 16) == PCI_BASE_CLASS_DISPLAY) { | ||
395 | /* | ||
396 | * apple-gmux is needed on pre-retina MacBook Pro | ||
397 | * to probe the panel if pdev is the inactive GPU. | ||
398 | */ | ||
399 | if (apple_gmux_present() && pdev != vga_default_device() && | ||
400 | !vgasr_priv.handler_flags) | ||
401 | return true; | ||
402 | } | ||
403 | |||
404 | return false; | ||
405 | } | ||
406 | EXPORT_SYMBOL(vga_switcheroo_client_probe_defer); | ||
407 | |||
408 | /** | ||
379 | * vga_switcheroo_get_client_state() - obtain power state of a given client | 409 | * vga_switcheroo_get_client_state() - obtain power state of a given client |
380 | * @pdev: client pci device | 410 | * @pdev: client pci device |
381 | * | 411 | * |
@@ -530,21 +560,21 @@ EXPORT_SYMBOL(vga_switcheroo_unlock_ddc); | |||
530 | * * OFF: Power off the device not in use. | 560 | * * OFF: Power off the device not in use. |
531 | * * ON: Power on the device not in use. | 561 | * * ON: Power on the device not in use. |
532 | * * IGD: Switch to the integrated graphics device. | 562 | * * IGD: Switch to the integrated graphics device. |
533 | * Power on the integrated GPU if necessary, power off the discrete GPU. | 563 | * Power on the integrated GPU if necessary, power off the discrete GPU. |
534 | * Prerequisite is that no user space processes (e.g. Xorg, alsactl) | 564 | * Prerequisite is that no user space processes (e.g. Xorg, alsactl) |
535 | * have opened device files of the GPUs or the audio client. If the | 565 | * have opened device files of the GPUs or the audio client. If the |
536 | * switch fails, the user may invoke lsof(8) or fuser(1) on /dev/dri/ | 566 | * switch fails, the user may invoke lsof(8) or fuser(1) on /dev/dri/ |
537 | * and /dev/snd/controlC1 to identify processes blocking the switch. | 567 | * and /dev/snd/controlC1 to identify processes blocking the switch. |
538 | * * DIS: Switch to the discrete graphics device. | 568 | * * DIS: Switch to the discrete graphics device. |
539 | * * DIGD: Delayed switch to the integrated graphics device. | 569 | * * DIGD: Delayed switch to the integrated graphics device. |
540 | * This will perform the switch once the last user space process has | 570 | * This will perform the switch once the last user space process has |
541 | * closed the device files of the GPUs and the audio client. | 571 | * closed the device files of the GPUs and the audio client. |
542 | * * DDIS: Delayed switch to the discrete graphics device. | 572 | * * DDIS: Delayed switch to the discrete graphics device. |
543 | * * MIGD: Mux-only switch to the integrated graphics device. | 573 | * * MIGD: Mux-only switch to the integrated graphics device. |
544 | * Does not remap console or change the power state of either gpu. | 574 | * Does not remap console or change the power state of either gpu. |
545 | * If the integrated GPU is currently off, the screen will turn black. | 575 | * If the integrated GPU is currently off, the screen will turn black. |
546 | * If it is on, the screen will show whatever happens to be in VRAM. | 576 | * If it is on, the screen will show whatever happens to be in VRAM. |
547 | * Either way, the user has to blindly enter the command to switch back. | 577 | * Either way, the user has to blindly enter the command to switch back. |
548 | * * MDIS: Mux-only switch to the discrete graphics device. | 578 | * * MDIS: Mux-only switch to the discrete graphics device. |
549 | * | 579 | * |
550 | * For GPUs whose power state is controlled by the driver's runtime pm, | 580 | * For GPUs whose power state is controlled by the driver's runtime pm, |