linux/drivers/acpi/acpi_lpat.c
<<
>>
Prefs
   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
  16#include <linux/export.h>
  17#include <linux/acpi.h>
  18#include <acpi/acpi_lpat.h>
  19
  20/**
  21 * acpi_lpat_raw_to_temp(): Return temperature from raw value through
  22 * LPAT conversion table
  23 *
  24 * @lpat_table: the temperature_raw mapping table structure
  25 * @raw: the raw value, used as a key to get the temerature from the
  26 *       above mapping table
  27 *
  28 * A positive converted temperature value will be returned on success,
  29 * a negative errno will be returned in error cases.
  30 */
  31int acpi_lpat_raw_to_temp(struct acpi_lpat_conversion_table *lpat_table,
  32                          int raw)
  33{
  34        int i, delta_temp, delta_raw, temp;
  35        struct acpi_lpat *lpat = lpat_table->lpat;
  36
  37        for (i = 0; i < lpat_table->lpat_count - 1; i++) {
  38                if ((raw >= lpat[i].raw && raw <= lpat[i+1].raw) ||
  39                    (raw <= lpat[i].raw && raw >= lpat[i+1].raw))
  40                        break;
  41        }
  42
  43        if (i == lpat_table->lpat_count - 1)
  44                return -ENOENT;
  45
  46        delta_temp = lpat[i+1].temp - lpat[i].temp;
  47        delta_raw = lpat[i+1].raw - lpat[i].raw;
  48        temp = lpat[i].temp + (raw - lpat[i].raw) * delta_temp / delta_raw;
  49
  50        return temp;
  51}
  52EXPORT_SYMBOL_GPL(acpi_lpat_raw_to_temp);
  53
  54/**
  55 * acpi_lpat_temp_to_raw(): Return raw value from temperature through
  56 * LPAT conversion table
  57 *
  58 * @lpat_table: the temperature_raw mapping table
  59 * @temp: the temperature, used as a key to get the raw value from the
  60 *        above mapping table
  61 *
  62 * The raw value will be returned on success,
  63 * a negative errno will be returned in error cases.
  64 */
  65int acpi_lpat_temp_to_raw(struct acpi_lpat_conversion_table *lpat_table,
  66                          int temp)
  67{
  68        int i, delta_temp, delta_raw, raw;
  69        struct acpi_lpat *lpat = lpat_table->lpat;
  70
  71        for (i = 0; i < lpat_table->lpat_count - 1; i++) {
  72                if (temp >= lpat[i].temp && temp <= lpat[i+1].temp)
  73                        break;
  74        }
  75
  76        if (i ==  lpat_table->lpat_count - 1)
  77                return -ENOENT;
  78
  79        delta_temp = lpat[i+1].temp - lpat[i].temp;
  80        delta_raw = lpat[i+1].raw - lpat[i].raw;
  81        raw = lpat[i].raw + (temp - lpat[i].temp) * delta_raw / delta_temp;
  82
  83        return raw;
  84}
  85EXPORT_SYMBOL_GPL(acpi_lpat_temp_to_raw);
  86
  87/**
  88 * acpi_lpat_get_conversion_table(): Parse ACPI LPAT table if present.
  89 *
  90 * @handle: Handle to acpi device
  91 *
  92 * Parse LPAT table to a struct of type acpi_lpat_table. On success
  93 * it returns a pointer to newly allocated table. This table must
  94 * be freed by the caller when finished processing, using a call to
  95 * acpi_lpat_free_conversion_table.
  96 */
  97struct acpi_lpat_conversion_table *acpi_lpat_get_conversion_table(acpi_handle
  98                                                                  handle)
  99{
 100        struct acpi_lpat_conversion_table *lpat_table = NULL;
 101        struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL };
 102        union acpi_object *obj_p, *obj_e;
 103        int *lpat, i;
 104        acpi_status status;
 105
 106        status = acpi_evaluate_object(handle, "LPAT", NULL, &buffer);
 107        if (ACPI_FAILURE(status))
 108                return NULL;
 109
 110        obj_p = (union acpi_object *)buffer.pointer;
 111        if (!obj_p || (obj_p->type != ACPI_TYPE_PACKAGE) ||
 112            (obj_p->package.count % 2) || (obj_p->package.count < 4))
 113                goto out;
 114
 115        lpat = kcalloc(obj_p->package.count, sizeof(int), GFP_KERNEL);
 116        if (!lpat)
 117                goto out;
 118
 119        for (i = 0; i < obj_p->package.count; i++) {
 120                obj_e = &obj_p->package.elements[i];
 121                if (obj_e->type != ACPI_TYPE_INTEGER) {
 122                        kfree(lpat);
 123                        goto out;
 124                }
 125                lpat[i] = (s64)obj_e->integer.value;
 126        }
 127
 128        lpat_table = kzalloc(sizeof(*lpat_table), GFP_KERNEL);
 129        if (!lpat_table) {
 130                kfree(lpat);
 131                goto out;
 132        }
 133
 134        lpat_table->lpat = (struct acpi_lpat *)lpat;
 135        lpat_table->lpat_count = obj_p->package.count / 2;
 136
 137out:
 138        kfree(buffer.pointer);
 139        return lpat_table;
 140}
 141EXPORT_SYMBOL_GPL(acpi_lpat_get_conversion_table);
 142
 143/**
 144 * acpi_lpat_free_conversion_table(): Free LPAT table.
 145 *
 146 * @lpat_table: the temperature_raw mapping table structure
 147 *
 148 * Frees the LPAT table previously allocated by a call to
 149 * acpi_lpat_get_conversion_table.
 150 */
 151void acpi_lpat_free_conversion_table(struct acpi_lpat_conversion_table
 152                                     *lpat_table)
 153{
 154        if (lpat_table) {
 155                kfree(lpat_table->lpat);
 156                kfree(lpat_table);
 157        }
 158}
 159EXPORT_SYMBOL_GPL(acpi_lpat_free_conversion_table);
 160