nouveau_acpi.c 3.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125
  1. #include <linux/pci.h>
  2. #include <linux/acpi.h>
  3. #include <acpi/acpi_drivers.h>
  4. #include <acpi/acpi_bus.h>
  5. #include "drmP.h"
  6. #include "drm.h"
  7. #include "drm_sarea.h"
  8. #include "drm_crtc_helper.h"
  9. #include "nouveau_drv.h"
  10. #include "nouveau_drm.h"
  11. #include "nv50_display.h"
  12. #define NOUVEAU_DSM_SUPPORTED 0x00
  13. #define NOUVEAU_DSM_SUPPORTED_FUNCTIONS 0x00
  14. #define NOUVEAU_DSM_ACTIVE 0x01
  15. #define NOUVEAU_DSM_ACTIVE_QUERY 0x00
  16. #define NOUVEAU_DSM_LED 0x02
  17. #define NOUVEAU_DSM_LED_STATE 0x00
  18. #define NOUVEAU_DSM_LED_OFF 0x10
  19. #define NOUVEAU_DSM_LED_STAMINA 0x11
  20. #define NOUVEAU_DSM_LED_SPEED 0x12
  21. #define NOUVEAU_DSM_POWER 0x03
  22. #define NOUVEAU_DSM_POWER_STATE 0x00
  23. #define NOUVEAU_DSM_POWER_SPEED 0x01
  24. #define NOUVEAU_DSM_POWER_STAMINA 0x02
  25. static int nouveau_dsm(struct drm_device *dev, int func, int arg, int *result)
  26. {
  27. static char muid[] = {
  28. 0xA0, 0xA0, 0x95, 0x9D, 0x60, 0x00, 0x48, 0x4D,
  29. 0xB3, 0x4D, 0x7E, 0x5F, 0xEA, 0x12, 0x9F, 0xD4,
  30. };
  31. struct pci_dev *pdev = dev->pdev;
  32. struct acpi_handle *handle;
  33. struct acpi_buffer output = { ACPI_ALLOCATE_BUFFER, NULL };
  34. struct acpi_object_list input;
  35. union acpi_object params[4];
  36. union acpi_object *obj;
  37. int err;
  38. handle = DEVICE_ACPI_HANDLE(&pdev->dev);
  39. if (!handle)
  40. return -ENODEV;
  41. input.count = 4;
  42. input.pointer = params;
  43. params[0].type = ACPI_TYPE_BUFFER;
  44. params[0].buffer.length = sizeof(muid);
  45. params[0].buffer.pointer = (char *)muid;
  46. params[1].type = ACPI_TYPE_INTEGER;
  47. params[1].integer.value = 0x00000102;
  48. params[2].type = ACPI_TYPE_INTEGER;
  49. params[2].integer.value = func;
  50. params[3].type = ACPI_TYPE_INTEGER;
  51. params[3].integer.value = arg;
  52. err = acpi_evaluate_object(handle, "_DSM", &input, &output);
  53. if (err) {
  54. NV_INFO(dev, "failed to evaluate _DSM: %d\n", err);
  55. return err;
  56. }
  57. obj = (union acpi_object *)output.pointer;
  58. if (obj->type == ACPI_TYPE_INTEGER)
  59. if (obj->integer.value == 0x80000002)
  60. return -ENODEV;
  61. if (obj->type == ACPI_TYPE_BUFFER) {
  62. if (obj->buffer.length == 4 && result) {
  63. *result = 0;
  64. *result |= obj->buffer.pointer[0];
  65. *result |= (obj->buffer.pointer[1] << 8);
  66. *result |= (obj->buffer.pointer[2] << 16);
  67. *result |= (obj->buffer.pointer[3] << 24);
  68. }
  69. }
  70. kfree(output.pointer);
  71. return 0;
  72. }
  73. int nouveau_hybrid_setup(struct drm_device *dev)
  74. {
  75. int result;
  76. if (nouveau_dsm(dev, NOUVEAU_DSM_ACTIVE, NOUVEAU_DSM_ACTIVE_QUERY,
  77. &result))
  78. return -ENODEV;
  79. NV_INFO(dev, "_DSM hardware status gave 0x%x\n", result);
  80. if (result & 0x1) { /* Stamina mode - disable the external GPU */
  81. nouveau_dsm(dev, NOUVEAU_DSM_LED, NOUVEAU_DSM_LED_STAMINA,
  82. NULL);
  83. nouveau_dsm(dev, NOUVEAU_DSM_POWER, NOUVEAU_DSM_POWER_STAMINA,
  84. NULL);
  85. } else { /* Ensure that the external GPU is enabled */
  86. nouveau_dsm(dev, NOUVEAU_DSM_LED, NOUVEAU_DSM_LED_SPEED, NULL);
  87. nouveau_dsm(dev, NOUVEAU_DSM_POWER, NOUVEAU_DSM_POWER_SPEED,
  88. NULL);
  89. }
  90. return 0;
  91. }
  92. bool nouveau_dsm_probe(struct drm_device *dev)
  93. {
  94. int support = 0;
  95. if (nouveau_dsm(dev, NOUVEAU_DSM_SUPPORTED,
  96. NOUVEAU_DSM_SUPPORTED_FUNCTIONS, &support))
  97. return false;
  98. if (!support)
  99. return false;
  100. return true;
  101. }