2019-05-27 09:55:21 +03:00
// SPDX-License-Identifier: GPL-2.0-only
2015-01-28 22:56:46 +03:00
/*
* acpi_lpat . c - LPAT table processing functions
*
* Copyright ( C ) 2015 Intel Corporation . All rights reserved .
*/
2016-07-12 00:22:41 +03:00
# include <linux/export.h>
2015-01-28 22:56:46 +03:00
# include <linux/acpi.h>
# include <acpi/acpi_lpat.h>
/**
* acpi_lpat_raw_to_temp ( ) : Return temperature from raw value through
* LPAT conversion table
*
* @ lpat_table : the temperature_raw mapping table structure
2019-03-25 21:34:00 +03:00
* @ raw : the raw value , used as a key to get the temperature from the
2015-01-28 22:56:46 +03:00
* above mapping table
*
2017-07-21 21:44:42 +03:00
* A positive converted temperature value will be returned on success ,
2015-01-28 22:56:46 +03:00
* a negative errno will be returned in error cases .
*/
int acpi_lpat_raw_to_temp ( struct acpi_lpat_conversion_table * lpat_table ,
int raw )
{
int i , delta_temp , delta_raw , temp ;
struct acpi_lpat * lpat = lpat_table - > lpat ;
for ( i = 0 ; i < lpat_table - > lpat_count - 1 ; i + + ) {
if ( ( raw > = lpat [ i ] . raw & & raw < = lpat [ i + 1 ] . raw ) | |
( raw < = lpat [ i ] . raw & & raw > = lpat [ i + 1 ] . raw ) )
break ;
}
if ( i = = lpat_table - > lpat_count - 1 )
return - ENOENT ;
delta_temp = lpat [ i + 1 ] . temp - lpat [ i ] . temp ;
delta_raw = lpat [ i + 1 ] . raw - lpat [ i ] . raw ;
temp = lpat [ i ] . temp + ( raw - lpat [ i ] . raw ) * delta_temp / delta_raw ;
return temp ;
}
EXPORT_SYMBOL_GPL ( acpi_lpat_raw_to_temp ) ;
/**
* acpi_lpat_temp_to_raw ( ) : Return raw value from temperature through
* LPAT conversion table
*
2017-07-21 21:44:42 +03:00
* @ lpat_table : the temperature_raw mapping table
2015-01-28 22:56:46 +03:00
* @ temp : the temperature , used as a key to get the raw value from the
* above mapping table
*
2017-07-21 21:44:42 +03:00
* The raw value will be returned on success ,
2015-01-28 22:56:46 +03:00
* a negative errno will be returned in error cases .
*/
int acpi_lpat_temp_to_raw ( struct acpi_lpat_conversion_table * lpat_table ,
int temp )
{
int i , delta_temp , delta_raw , raw ;
struct acpi_lpat * lpat = lpat_table - > lpat ;
for ( i = 0 ; i < lpat_table - > lpat_count - 1 ; i + + ) {
if ( temp > = lpat [ i ] . temp & & temp < = lpat [ i + 1 ] . temp )
break ;
}
if ( i = = lpat_table - > lpat_count - 1 )
return - ENOENT ;
delta_temp = lpat [ i + 1 ] . temp - lpat [ i ] . temp ;
delta_raw = lpat [ i + 1 ] . raw - lpat [ i ] . raw ;
raw = lpat [ i ] . raw + ( temp - lpat [ i ] . temp ) * delta_raw / delta_temp ;
return raw ;
}
EXPORT_SYMBOL_GPL ( acpi_lpat_temp_to_raw ) ;
/**
* acpi_lpat_get_conversion_table ( ) : Parse ACPI LPAT table if present .
*
* @ handle : Handle to acpi device
*
* Parse LPAT table to a struct of type acpi_lpat_table . On success
* it returns a pointer to newly allocated table . This table must
* be freed by the caller when finished processing , using a call to
* acpi_lpat_free_conversion_table .
*/
struct acpi_lpat_conversion_table * acpi_lpat_get_conversion_table ( acpi_handle
handle )
{
struct acpi_lpat_conversion_table * lpat_table = NULL ;
struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER , NULL } ;
union acpi_object * obj_p , * obj_e ;
int * lpat , i ;
acpi_status status ;
status = acpi_evaluate_object ( handle , " LPAT " , NULL , & buffer ) ;
if ( ACPI_FAILURE ( status ) )
return NULL ;
obj_p = ( union acpi_object * ) buffer . pointer ;
if ( ! obj_p | | ( obj_p - > type ! = ACPI_TYPE_PACKAGE ) | |
( obj_p - > package . count % 2 ) | | ( obj_p - > package . count < 4 ) )
goto out ;
lpat = kcalloc ( obj_p - > package . count , sizeof ( int ) , GFP_KERNEL ) ;
if ( ! lpat )
goto out ;
for ( i = 0 ; i < obj_p - > package . count ; i + + ) {
obj_e = & obj_p - > package . elements [ i ] ;
if ( obj_e - > type ! = ACPI_TYPE_INTEGER ) {
kfree ( lpat ) ;
goto out ;
}
lpat [ i ] = ( s64 ) obj_e - > integer . value ;
}
lpat_table = kzalloc ( sizeof ( * lpat_table ) , GFP_KERNEL ) ;
if ( ! lpat_table ) {
kfree ( lpat ) ;
goto out ;
}
lpat_table - > lpat = ( struct acpi_lpat * ) lpat ;
lpat_table - > lpat_count = obj_p - > package . count / 2 ;
out :
kfree ( buffer . pointer ) ;
return lpat_table ;
}
EXPORT_SYMBOL_GPL ( acpi_lpat_get_conversion_table ) ;
/**
* acpi_lpat_free_conversion_table ( ) : Free LPAT table .
*
* @ lpat_table : the temperature_raw mapping table structure
*
* Frees the LPAT table previously allocated by a call to
* acpi_lpat_get_conversion_table .
*/
void acpi_lpat_free_conversion_table ( struct acpi_lpat_conversion_table
* lpat_table )
{
if ( lpat_table ) {
kfree ( lpat_table - > lpat ) ;
kfree ( lpat_table ) ;
}
}
EXPORT_SYMBOL_GPL ( acpi_lpat_free_conversion_table ) ;