Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0-only
0002 /*
0003  * acpi_lpat.c - LPAT table processing functions
0004  *
0005  * Copyright (C) 2015 Intel Corporation. All rights reserved.
0006  */
0007 
0008 #include <linux/export.h>
0009 #include <linux/acpi.h>
0010 #include <acpi/acpi_lpat.h>
0011 
0012 /**
0013  * acpi_lpat_raw_to_temp(): Return temperature from raw value through
0014  * LPAT conversion table
0015  *
0016  * @lpat_table: the temperature_raw mapping table structure
0017  * @raw: the raw value, used as a key to get the temperature from the
0018  *       above mapping table
0019  *
0020  * A positive converted temperature value will be returned on success,
0021  * a negative errno will be returned in error cases.
0022  */
0023 int acpi_lpat_raw_to_temp(struct acpi_lpat_conversion_table *lpat_table,
0024               int raw)
0025 {
0026     int i, delta_temp, delta_raw, temp;
0027     struct acpi_lpat *lpat = lpat_table->lpat;
0028 
0029     for (i = 0; i < lpat_table->lpat_count - 1; i++) {
0030         if ((raw >= lpat[i].raw && raw <= lpat[i+1].raw) ||
0031             (raw <= lpat[i].raw && raw >= lpat[i+1].raw))
0032             break;
0033     }
0034 
0035     if (i == lpat_table->lpat_count - 1)
0036         return -ENOENT;
0037 
0038     delta_temp = lpat[i+1].temp - lpat[i].temp;
0039     delta_raw = lpat[i+1].raw - lpat[i].raw;
0040     temp = lpat[i].temp + (raw - lpat[i].raw) * delta_temp / delta_raw;
0041 
0042     return temp;
0043 }
0044 EXPORT_SYMBOL_GPL(acpi_lpat_raw_to_temp);
0045 
0046 /**
0047  * acpi_lpat_temp_to_raw(): Return raw value from temperature through
0048  * LPAT conversion table
0049  *
0050  * @lpat_table: the temperature_raw mapping table
0051  * @temp: the temperature, used as a key to get the raw value from the
0052  *        above mapping table
0053  *
0054  * The raw value will be returned on success,
0055  * a negative errno will be returned in error cases.
0056  */
0057 int acpi_lpat_temp_to_raw(struct acpi_lpat_conversion_table *lpat_table,
0058               int temp)
0059 {
0060     int i, delta_temp, delta_raw, raw;
0061     struct acpi_lpat *lpat = lpat_table->lpat;
0062 
0063     for (i = 0; i < lpat_table->lpat_count - 1; i++) {
0064         if (temp >= lpat[i].temp && temp <= lpat[i+1].temp)
0065             break;
0066     }
0067 
0068     if (i ==  lpat_table->lpat_count - 1)
0069         return -ENOENT;
0070 
0071     delta_temp = lpat[i+1].temp - lpat[i].temp;
0072     delta_raw = lpat[i+1].raw - lpat[i].raw;
0073     raw = lpat[i].raw + (temp - lpat[i].temp) * delta_raw / delta_temp;
0074 
0075     return raw;
0076 }
0077 EXPORT_SYMBOL_GPL(acpi_lpat_temp_to_raw);
0078 
0079 /**
0080  * acpi_lpat_get_conversion_table(): Parse ACPI LPAT table if present.
0081  *
0082  * @handle: Handle to acpi device
0083  *
0084  * Parse LPAT table to a struct of type acpi_lpat_table. On success
0085  * it returns a pointer to newly allocated table. This table must
0086  * be freed by the caller when finished processing, using a call to
0087  * acpi_lpat_free_conversion_table.
0088  */
0089 struct acpi_lpat_conversion_table *acpi_lpat_get_conversion_table(acpi_handle
0090                                   handle)
0091 {
0092     struct acpi_lpat_conversion_table *lpat_table = NULL;
0093     struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL };
0094     union acpi_object *obj_p, *obj_e;
0095     int *lpat, i;
0096     acpi_status status;
0097 
0098     status = acpi_evaluate_object(handle, "LPAT", NULL, &buffer);
0099     if (ACPI_FAILURE(status))
0100         return NULL;
0101 
0102     obj_p = (union acpi_object *)buffer.pointer;
0103     if (!obj_p || (obj_p->type != ACPI_TYPE_PACKAGE) ||
0104         (obj_p->package.count % 2) || (obj_p->package.count < 4))
0105         goto out;
0106 
0107     lpat = kcalloc(obj_p->package.count, sizeof(int), GFP_KERNEL);
0108     if (!lpat)
0109         goto out;
0110 
0111     for (i = 0; i < obj_p->package.count; i++) {
0112         obj_e = &obj_p->package.elements[i];
0113         if (obj_e->type != ACPI_TYPE_INTEGER) {
0114             kfree(lpat);
0115             goto out;
0116         }
0117         lpat[i] = (s64)obj_e->integer.value;
0118     }
0119 
0120     lpat_table = kzalloc(sizeof(*lpat_table), GFP_KERNEL);
0121     if (!lpat_table) {
0122         kfree(lpat);
0123         goto out;
0124     }
0125 
0126     lpat_table->lpat = (struct acpi_lpat *)lpat;
0127     lpat_table->lpat_count = obj_p->package.count / 2;
0128 
0129 out:
0130     kfree(buffer.pointer);
0131     return lpat_table;
0132 }
0133 EXPORT_SYMBOL_GPL(acpi_lpat_get_conversion_table);
0134 
0135 /**
0136  * acpi_lpat_free_conversion_table(): Free LPAT table.
0137  *
0138  * @lpat_table: the temperature_raw mapping table structure
0139  *
0140  * Frees the LPAT table previously allocated by a call to
0141  * acpi_lpat_get_conversion_table.
0142  */
0143 void acpi_lpat_free_conversion_table(struct acpi_lpat_conversion_table
0144                      *lpat_table)
0145 {
0146     if (lpat_table) {
0147         kfree(lpat_table->lpat);
0148         kfree(lpat_table);
0149     }
0150 }
0151 EXPORT_SYMBOL_GPL(acpi_lpat_free_conversion_table);