utils.c 4.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135
  1. /*
  2. * X86 ACPI Utility Functions
  3. *
  4. * Copyright (C) 2017 Hans de Goede <hdegoede@redhat.com>
  5. *
  6. * Based on various non upstream patches to support the CHT Whiskey Cove PMIC:
  7. * Copyright (C) 2013-2015 Intel Corporation. All rights reserved.
  8. *
  9. * This program is free software; you can redistribute it and/or modify
  10. * it under the terms of the GNU General Public License version 2 as
  11. * published by the Free Software Foundation.
  12. */
  13. #include <linux/acpi.h>
  14. #include <linux/dmi.h>
  15. #include <asm/cpu_device_id.h>
  16. #include <asm/intel-family.h>
  17. #include "../internal.h"
  18. /*
  19. * Some ACPI devices are hidden (status == 0x0) in recent BIOS-es because
  20. * some recent Windows drivers bind to one device but poke at multiple
  21. * devices at the same time, so the others get hidden.
  22. *
  23. * Some BIOS-es (temporarily) hide specific APCI devices to work around Windows
  24. * driver bugs. We use DMI matching to match known cases of this.
  25. *
  26. * We work around this by always reporting ACPI_STA_DEFAULT for these
  27. * devices. Note this MUST only be done for devices where this is safe.
  28. *
  29. * This forcing of devices to be present is limited to specific CPU (SoC)
  30. * models both to avoid potentially causing trouble on other models and
  31. * because some HIDs are re-used on different SoCs for completely
  32. * different devices.
  33. */
  34. struct always_present_id {
  35. struct acpi_device_id hid[2];
  36. struct x86_cpu_id cpu_ids[2];
  37. struct dmi_system_id dmi_ids[2]; /* Optional */
  38. const char *uid;
  39. };
  40. #define ICPU(model) { X86_VENDOR_INTEL, 6, model, X86_FEATURE_ANY, }
  41. #define ENTRY(hid, uid, cpu_models, dmi...) { \
  42. { { hid, }, {} }, \
  43. { cpu_models, {} }, \
  44. { { .matches = dmi }, {} }, \
  45. uid, \
  46. }
  47. static const struct always_present_id always_present_ids[] = {
  48. /*
  49. * Bay / Cherry Trail PWM directly poked by GPU driver in win10,
  50. * but Linux uses a separate PWM driver, harmless if not used.
  51. */
  52. ENTRY("80860F09", "1", ICPU(INTEL_FAM6_ATOM_SILVERMONT), {}),
  53. ENTRY("80862288", "1", ICPU(INTEL_FAM6_ATOM_AIRMONT), {}),
  54. /*
  55. * The INT0002 device is necessary to clear wakeup interrupt sources
  56. * on Cherry Trail devices, without it we get nobody cared IRQ msgs.
  57. */
  58. ENTRY("INT0002", "1", ICPU(INTEL_FAM6_ATOM_AIRMONT), {}),
  59. /*
  60. * On the Dell Venue 11 Pro 7130 and 7139, the DSDT hides
  61. * the touchscreen ACPI device until a certain time
  62. * after _SB.PCI0.GFX0.LCD.LCD1._ON gets called has passed
  63. * *and* _STA has been called at least 3 times since.
  64. */
  65. ENTRY("SYNA7500", "1", ICPU(INTEL_FAM6_HASWELL_ULT), {
  66. DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."),
  67. DMI_MATCH(DMI_PRODUCT_NAME, "Venue 11 Pro 7130"),
  68. }),
  69. ENTRY("SYNA7500", "1", ICPU(INTEL_FAM6_HASWELL_ULT), {
  70. DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."),
  71. DMI_MATCH(DMI_PRODUCT_NAME, "Venue 11 Pro 7139"),
  72. }),
  73. /*
  74. * The GPD win BIOS dated 20170221 has disabled the accelerometer, the
  75. * drivers sometimes cause crashes under Windows and this is how the
  76. * manufacturer has solved this :| Note that the the DMI data is less
  77. * generic then it seems, a board_vendor of "AMI Corporation" is quite
  78. * rare and a board_name of "Default String" also is rare.
  79. *
  80. * Unfortunately the GPD pocket also uses these strings and its BIOS
  81. * was copy-pasted from the GPD win, so it has a disabled KIOX000A
  82. * node which we should not enable, thus we also check the BIOS date.
  83. */
  84. ENTRY("KIOX000A", "1", ICPU(INTEL_FAM6_ATOM_AIRMONT), {
  85. DMI_MATCH(DMI_BOARD_VENDOR, "AMI Corporation"),
  86. DMI_MATCH(DMI_BOARD_NAME, "Default string"),
  87. DMI_MATCH(DMI_PRODUCT_NAME, "Default string"),
  88. DMI_MATCH(DMI_BIOS_DATE, "02/21/2017")
  89. }),
  90. ENTRY("KIOX000A", "1", ICPU(INTEL_FAM6_ATOM_AIRMONT), {
  91. DMI_MATCH(DMI_BOARD_VENDOR, "AMI Corporation"),
  92. DMI_MATCH(DMI_BOARD_NAME, "Default string"),
  93. DMI_MATCH(DMI_PRODUCT_NAME, "Default string"),
  94. DMI_MATCH(DMI_BIOS_DATE, "03/20/2017")
  95. }),
  96. ENTRY("KIOX000A", "1", ICPU(INTEL_FAM6_ATOM_AIRMONT), {
  97. DMI_MATCH(DMI_BOARD_VENDOR, "AMI Corporation"),
  98. DMI_MATCH(DMI_BOARD_NAME, "Default string"),
  99. DMI_MATCH(DMI_PRODUCT_NAME, "Default string"),
  100. DMI_MATCH(DMI_BIOS_DATE, "05/25/2017")
  101. }),
  102. };
  103. bool acpi_device_always_present(struct acpi_device *adev)
  104. {
  105. bool ret = false;
  106. unsigned int i;
  107. for (i = 0; i < ARRAY_SIZE(always_present_ids); i++) {
  108. if (acpi_match_device_ids(adev, always_present_ids[i].hid))
  109. continue;
  110. if (!adev->pnp.unique_id ||
  111. strcmp(adev->pnp.unique_id, always_present_ids[i].uid))
  112. continue;
  113. if (!x86_match_cpu(always_present_ids[i].cpu_ids))
  114. continue;
  115. if (always_present_ids[i].dmi_ids[0].matches[0].slot &&
  116. !dmi_check_system(always_present_ids[i].dmi_ids))
  117. continue;
  118. ret = true;
  119. break;
  120. }
  121. return ret;
  122. }