acpi_lpat.c 4.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162
  1. /*
  2. * acpi_lpat.c - LPAT table processing functions
  3. *
  4. * Copyright (C) 2015 Intel Corporation. All rights reserved.
  5. *
  6. * This program is free software; you can redistribute it and/or
  7. * modify it under the terms of the GNU General Public License version
  8. * 2 as published by the Free Software Foundation.
  9. *
  10. * This program is distributed in the hope that it will be useful,
  11. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  13. * GNU General Public License for more details.
  14. */
  15. #include <linux/module.h>
  16. #include <linux/acpi.h>
  17. #include <acpi/acpi_lpat.h>
  18. /**
  19. * acpi_lpat_raw_to_temp(): Return temperature from raw value through
  20. * LPAT conversion table
  21. *
  22. * @lpat_table: the temperature_raw mapping table structure
  23. * @raw: the raw value, used as a key to get the temerature from the
  24. * above mapping table
  25. *
  26. * A positive converted temperarure value will be returned on success,
  27. * a negative errno will be returned in error cases.
  28. */
  29. int acpi_lpat_raw_to_temp(struct acpi_lpat_conversion_table *lpat_table,
  30. int raw)
  31. {
  32. int i, delta_temp, delta_raw, temp;
  33. struct acpi_lpat *lpat = lpat_table->lpat;
  34. for (i = 0; i < lpat_table->lpat_count - 1; i++) {
  35. if ((raw >= lpat[i].raw && raw <= lpat[i+1].raw) ||
  36. (raw <= lpat[i].raw && raw >= lpat[i+1].raw))
  37. break;
  38. }
  39. if (i == lpat_table->lpat_count - 1)
  40. return -ENOENT;
  41. delta_temp = lpat[i+1].temp - lpat[i].temp;
  42. delta_raw = lpat[i+1].raw - lpat[i].raw;
  43. temp = lpat[i].temp + (raw - lpat[i].raw) * delta_temp / delta_raw;
  44. return temp;
  45. }
  46. EXPORT_SYMBOL_GPL(acpi_lpat_raw_to_temp);
  47. /**
  48. * acpi_lpat_temp_to_raw(): Return raw value from temperature through
  49. * LPAT conversion table
  50. *
  51. * @lpat: the temperature_raw mapping table
  52. * @temp: the temperature, used as a key to get the raw value from the
  53. * above mapping table
  54. *
  55. * A positive converted temperature value will be returned on success,
  56. * a negative errno will be returned in error cases.
  57. */
  58. int acpi_lpat_temp_to_raw(struct acpi_lpat_conversion_table *lpat_table,
  59. int temp)
  60. {
  61. int i, delta_temp, delta_raw, raw;
  62. struct acpi_lpat *lpat = lpat_table->lpat;
  63. for (i = 0; i < lpat_table->lpat_count - 1; i++) {
  64. if (temp >= lpat[i].temp && temp <= lpat[i+1].temp)
  65. break;
  66. }
  67. if (i == lpat_table->lpat_count - 1)
  68. return -ENOENT;
  69. delta_temp = lpat[i+1].temp - lpat[i].temp;
  70. delta_raw = lpat[i+1].raw - lpat[i].raw;
  71. raw = lpat[i].raw + (temp - lpat[i].temp) * delta_raw / delta_temp;
  72. return raw;
  73. }
  74. EXPORT_SYMBOL_GPL(acpi_lpat_temp_to_raw);
  75. /**
  76. * acpi_lpat_get_conversion_table(): Parse ACPI LPAT table if present.
  77. *
  78. * @handle: Handle to acpi device
  79. *
  80. * Parse LPAT table to a struct of type acpi_lpat_table. On success
  81. * it returns a pointer to newly allocated table. This table must
  82. * be freed by the caller when finished processing, using a call to
  83. * acpi_lpat_free_conversion_table.
  84. */
  85. struct acpi_lpat_conversion_table *acpi_lpat_get_conversion_table(acpi_handle
  86. handle)
  87. {
  88. struct acpi_lpat_conversion_table *lpat_table = NULL;
  89. struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL };
  90. union acpi_object *obj_p, *obj_e;
  91. int *lpat, i;
  92. acpi_status status;
  93. status = acpi_evaluate_object(handle, "LPAT", NULL, &buffer);
  94. if (ACPI_FAILURE(status))
  95. return NULL;
  96. obj_p = (union acpi_object *)buffer.pointer;
  97. if (!obj_p || (obj_p->type != ACPI_TYPE_PACKAGE) ||
  98. (obj_p->package.count % 2) || (obj_p->package.count < 4))
  99. goto out;
  100. lpat = kcalloc(obj_p->package.count, sizeof(int), GFP_KERNEL);
  101. if (!lpat)
  102. goto out;
  103. for (i = 0; i < obj_p->package.count; i++) {
  104. obj_e = &obj_p->package.elements[i];
  105. if (obj_e->type != ACPI_TYPE_INTEGER) {
  106. kfree(lpat);
  107. goto out;
  108. }
  109. lpat[i] = (s64)obj_e->integer.value;
  110. }
  111. lpat_table = kzalloc(sizeof(*lpat_table), GFP_KERNEL);
  112. if (!lpat_table) {
  113. kfree(lpat);
  114. goto out;
  115. }
  116. lpat_table->lpat = (struct acpi_lpat *)lpat;
  117. lpat_table->lpat_count = obj_p->package.count / 2;
  118. out:
  119. kfree(buffer.pointer);
  120. return lpat_table;
  121. }
  122. EXPORT_SYMBOL_GPL(acpi_lpat_get_conversion_table);
  123. /**
  124. * acpi_lpat_free_conversion_table(): Free LPAT table.
  125. *
  126. * @lpat_table: the temperature_raw mapping table structure
  127. *
  128. * Frees the LPAT table previously allocated by a call to
  129. * acpi_lpat_get_conversion_table.
  130. */
  131. void acpi_lpat_free_conversion_table(struct acpi_lpat_conversion_table
  132. *lpat_table)
  133. {
  134. if (lpat_table) {
  135. kfree(lpat_table->lpat);
  136. kfree(lpat_table);
  137. }
  138. }
  139. EXPORT_SYMBOL_GPL(acpi_lpat_free_conversion_table);
  140. MODULE_LICENSE("GPL");