aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/platform/x86/apple-gmux.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/platform/x86/apple-gmux.c')
-rw-r--r--drivers/platform/x86/apple-gmux.c48
1 files changed, 47 insertions, 1 deletions
diff --git a/drivers/platform/x86/apple-gmux.c b/drivers/platform/x86/apple-gmux.c
index 66d6d22c239c..6808715003f6 100644
--- a/drivers/platform/x86/apple-gmux.c
+++ b/drivers/platform/x86/apple-gmux.c
@@ -22,6 +22,7 @@
22#include <linux/delay.h> 22#include <linux/delay.h>
23#include <linux/pci.h> 23#include <linux/pci.h>
24#include <linux/vga_switcheroo.h> 24#include <linux/vga_switcheroo.h>
25#include <linux/vgaarb.h>
25#include <acpi/video.h> 26#include <acpi/video.h>
26#include <asm/io.h> 27#include <asm/io.h>
27 28
@@ -31,6 +32,7 @@ struct apple_gmux_data {
31 bool indexed; 32 bool indexed;
32 struct mutex index_lock; 33 struct mutex index_lock;
33 34
35 struct pci_dev *pdev;
34 struct backlight_device *bdev; 36 struct backlight_device *bdev;
35 37
36 /* switcheroo data */ 38 /* switcheroo data */
@@ -415,6 +417,23 @@ static int gmux_resume(struct device *dev)
415 return 0; 417 return 0;
416} 418}
417 419
420static struct pci_dev *gmux_get_io_pdev(void)
421{
422 struct pci_dev *pdev = NULL;
423
424 while ((pdev = pci_get_class(PCI_CLASS_DISPLAY_VGA << 8, pdev))) {
425 u16 cmd;
426
427 pci_read_config_word(pdev, PCI_COMMAND, &cmd);
428 if (!(cmd & PCI_COMMAND_IO))
429 continue;
430
431 return pdev;
432 }
433
434 return NULL;
435}
436
418static int gmux_probe(struct pnp_dev *pnp, const struct pnp_device_id *id) 437static int gmux_probe(struct pnp_dev *pnp, const struct pnp_device_id *id)
419{ 438{
420 struct apple_gmux_data *gmux_data; 439 struct apple_gmux_data *gmux_data;
@@ -425,6 +444,7 @@ static int gmux_probe(struct pnp_dev *pnp, const struct pnp_device_id *id)
425 int ret = -ENXIO; 444 int ret = -ENXIO;
426 acpi_status status; 445 acpi_status status;
427 unsigned long long gpe; 446 unsigned long long gpe;
447 struct pci_dev *pdev = NULL;
428 448
429 if (apple_gmux_data) 449 if (apple_gmux_data)
430 return -EBUSY; 450 return -EBUSY;
@@ -475,7 +495,7 @@ static int gmux_probe(struct pnp_dev *pnp, const struct pnp_device_id *id)
475 ver_minor = (version >> 16) & 0xff; 495 ver_minor = (version >> 16) & 0xff;
476 ver_release = (version >> 8) & 0xff; 496 ver_release = (version >> 8) & 0xff;
477 } else { 497 } else {
478 pr_info("gmux device not present\n"); 498 pr_info("gmux device not present or IO disabled\n");
479 ret = -ENODEV; 499 ret = -ENODEV;
480 goto err_release; 500 goto err_release;
481 } 501 }
@@ -483,6 +503,23 @@ static int gmux_probe(struct pnp_dev *pnp, const struct pnp_device_id *id)
483 pr_info("Found gmux version %d.%d.%d [%s]\n", ver_major, ver_minor, 503 pr_info("Found gmux version %d.%d.%d [%s]\n", ver_major, ver_minor,
484 ver_release, (gmux_data->indexed ? "indexed" : "classic")); 504 ver_release, (gmux_data->indexed ? "indexed" : "classic"));
485 505
506 /*
507 * Apple systems with gmux are EFI based and normally don't use
508 * VGA. In addition changing IO+MEM ownership between IGP and dGPU
509 * disables IO/MEM used for backlight control on some systems.
510 * Lock IO+MEM to GPU with active IO to prevent switch.
511 */
512 pdev = gmux_get_io_pdev();
513 if (pdev && vga_tryget(pdev,
514 VGA_RSRC_NORMAL_IO | VGA_RSRC_NORMAL_MEM)) {
515 pr_err("IO+MEM vgaarb-locking for PCI:%s failed\n",
516 pci_name(pdev));
517 ret = -EBUSY;
518 goto err_release;
519 } else if (pdev)
520 pr_info("locked IO for PCI:%s\n", pci_name(pdev));
521 gmux_data->pdev = pdev;
522
486 memset(&props, 0, sizeof(props)); 523 memset(&props, 0, sizeof(props));
487 props.type = BACKLIGHT_PLATFORM; 524 props.type = BACKLIGHT_PLATFORM;
488 props.max_brightness = gmux_read32(gmux_data, GMUX_PORT_MAX_BRIGHTNESS); 525 props.max_brightness = gmux_read32(gmux_data, GMUX_PORT_MAX_BRIGHTNESS);
@@ -574,6 +611,10 @@ err_enable_gpe:
574err_notify: 611err_notify:
575 backlight_device_unregister(bdev); 612 backlight_device_unregister(bdev);
576err_release: 613err_release:
614 if (gmux_data->pdev)
615 vga_put(gmux_data->pdev,
616 VGA_RSRC_NORMAL_IO | VGA_RSRC_NORMAL_MEM);
617 pci_dev_put(pdev);
577 release_region(gmux_data->iostart, gmux_data->iolen); 618 release_region(gmux_data->iostart, gmux_data->iolen);
578err_free: 619err_free:
579 kfree(gmux_data); 620 kfree(gmux_data);
@@ -593,6 +634,11 @@ static void gmux_remove(struct pnp_dev *pnp)
593 &gmux_notify_handler); 634 &gmux_notify_handler);
594 } 635 }
595 636
637 if (gmux_data->pdev) {
638 vga_put(gmux_data->pdev,
639 VGA_RSRC_NORMAL_IO | VGA_RSRC_NORMAL_MEM);
640 pci_dev_put(gmux_data->pdev);
641 }
596 backlight_device_unregister(gmux_data->bdev); 642 backlight_device_unregister(gmux_data->bdev);
597 643
598 release_region(gmux_data->iostart, gmux_data->iolen); 644 release_region(gmux_data->iostart, gmux_data->iolen);