apple-gmux.h 3.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144
  1. /* SPDX-License-Identifier: GPL-2.0-only */
  2. /*
  3. * apple-gmux.h - microcontroller built into dual GPU MacBook Pro & Mac Pro
  4. * Copyright (C) 2015 Lukas Wunner <[email protected]>
  5. */
  6. #ifndef LINUX_APPLE_GMUX_H
  7. #define LINUX_APPLE_GMUX_H
  8. #include <linux/acpi.h>
  9. #include <linux/io.h>
  10. #include <linux/pnp.h>
  11. #define GMUX_ACPI_HID "APP000B"
  12. /*
  13. * gmux port offsets. Many of these are not yet used, but may be in the
  14. * future, and it's useful to have them documented here anyhow.
  15. */
  16. #define GMUX_PORT_VERSION_MAJOR 0x04
  17. #define GMUX_PORT_VERSION_MINOR 0x05
  18. #define GMUX_PORT_VERSION_RELEASE 0x06
  19. #define GMUX_PORT_SWITCH_DISPLAY 0x10
  20. #define GMUX_PORT_SWITCH_GET_DISPLAY 0x11
  21. #define GMUX_PORT_INTERRUPT_ENABLE 0x14
  22. #define GMUX_PORT_INTERRUPT_STATUS 0x16
  23. #define GMUX_PORT_SWITCH_DDC 0x28
  24. #define GMUX_PORT_SWITCH_EXTERNAL 0x40
  25. #define GMUX_PORT_SWITCH_GET_EXTERNAL 0x41
  26. #define GMUX_PORT_DISCRETE_POWER 0x50
  27. #define GMUX_PORT_MAX_BRIGHTNESS 0x70
  28. #define GMUX_PORT_BRIGHTNESS 0x74
  29. #define GMUX_PORT_VALUE 0xc2
  30. #define GMUX_PORT_READ 0xd0
  31. #define GMUX_PORT_WRITE 0xd4
  32. #define GMUX_MIN_IO_LEN (GMUX_PORT_BRIGHTNESS + 4)
  33. #if IS_ENABLED(CONFIG_APPLE_GMUX)
  34. static inline bool apple_gmux_is_indexed(unsigned long iostart)
  35. {
  36. u16 val;
  37. outb(0xaa, iostart + 0xcc);
  38. outb(0x55, iostart + 0xcd);
  39. outb(0x00, iostart + 0xce);
  40. val = inb(iostart + 0xcc) | (inb(iostart + 0xcd) << 8);
  41. if (val == 0x55aa)
  42. return true;
  43. return false;
  44. }
  45. /**
  46. * apple_gmux_detect() - detect if gmux is built into the machine
  47. *
  48. * @pnp_dev: Device to probe or NULL to use the first matching device
  49. * @indexed_ret: Returns (by reference) if the gmux is indexed or not
  50. *
  51. * Detect if a supported gmux device is present by actually probing it.
  52. * This avoids the false positives returned on some models by
  53. * apple_gmux_present().
  54. *
  55. * Return: %true if a supported gmux ACPI device is detected and the kernel
  56. * was configured with CONFIG_APPLE_GMUX, %false otherwise.
  57. */
  58. static inline bool apple_gmux_detect(struct pnp_dev *pnp_dev, bool *indexed_ret)
  59. {
  60. u8 ver_major, ver_minor, ver_release;
  61. struct device *dev = NULL;
  62. struct acpi_device *adev;
  63. struct resource *res;
  64. bool indexed = false;
  65. bool ret = false;
  66. if (!pnp_dev) {
  67. adev = acpi_dev_get_first_match_dev(GMUX_ACPI_HID, NULL, -1);
  68. if (!adev)
  69. return false;
  70. dev = get_device(acpi_get_first_physical_node(adev));
  71. acpi_dev_put(adev);
  72. if (!dev)
  73. return false;
  74. pnp_dev = to_pnp_dev(dev);
  75. }
  76. res = pnp_get_resource(pnp_dev, IORESOURCE_IO, 0);
  77. if (!res || resource_size(res) < GMUX_MIN_IO_LEN)
  78. goto out;
  79. /*
  80. * Invalid version information may indicate either that the gmux
  81. * device isn't present or that it's a new one that uses indexed io.
  82. */
  83. ver_major = inb(res->start + GMUX_PORT_VERSION_MAJOR);
  84. ver_minor = inb(res->start + GMUX_PORT_VERSION_MINOR);
  85. ver_release = inb(res->start + GMUX_PORT_VERSION_RELEASE);
  86. if (ver_major == 0xff && ver_minor == 0xff && ver_release == 0xff) {
  87. indexed = apple_gmux_is_indexed(res->start);
  88. if (!indexed)
  89. goto out;
  90. }
  91. if (indexed_ret)
  92. *indexed_ret = indexed;
  93. ret = true;
  94. out:
  95. put_device(dev);
  96. return ret;
  97. }
  98. /**
  99. * apple_gmux_present() - check if gmux ACPI device is present
  100. *
  101. * Drivers may use this to activate quirks specific to dual GPU MacBook Pros
  102. * and Mac Pros, e.g. for deferred probing, runtime pm and backlight.
  103. *
  104. * Return: %true if gmux ACPI device is present and the kernel was configured
  105. * with CONFIG_APPLE_GMUX, %false otherwise.
  106. */
  107. static inline bool apple_gmux_present(void)
  108. {
  109. return acpi_dev_found(GMUX_ACPI_HID);
  110. }
  111. #else /* !CONFIG_APPLE_GMUX */
  112. static inline bool apple_gmux_present(void)
  113. {
  114. return false;
  115. }
  116. static inline bool apple_gmux_detect(struct pnp_dev *pnp_dev, bool *indexed_ret)
  117. {
  118. return false;
  119. }
  120. #endif /* !CONFIG_APPLE_GMUX */
  121. #endif /* LINUX_APPLE_GMUX_H */