mirror of
https://mirrors.bfsu.edu.cn/git/linux.git
synced 2024-11-16 08:44:21 +08:00
Thermal: int3406_thermal: fix thermal sysfs I/F
there are three concepts represent backlight in int3406_thermal driver. 1. the raw brightness value from native graphics driver. 2. the percentage numbers from ACPI _BCL control method. 3. the consecutive numbers represent cooling states. int3406_thermal driver 1. uses value from DDDL/DDPC as the lower/upper limit, which is consistent with ACPI _BCL control methods. 2. reads current and maximum brightness from the native graphics driver. 3. expose them to thermal sysfs I/F This patch fixes the code that switches between the raw brightness value and the cooling state, which results in bogus value in thermal sysfs I/F. Signed-off-by: Zhang Rui <rui.zhang@intel.com>
This commit is contained in:
parent
595536e0b2
commit
9ef08d7a44
@ -21,39 +21,33 @@
|
|||||||
|
|
||||||
struct int3406_thermal_data {
|
struct int3406_thermal_data {
|
||||||
int upper_limit;
|
int upper_limit;
|
||||||
int upper_limit_index;
|
|
||||||
int lower_limit;
|
int lower_limit;
|
||||||
int lower_limit_index;
|
|
||||||
acpi_handle handle;
|
acpi_handle handle;
|
||||||
struct acpi_video_device_brightness *br;
|
struct acpi_video_device_brightness *br;
|
||||||
struct backlight_device *raw_bd;
|
struct backlight_device *raw_bd;
|
||||||
struct thermal_cooling_device *cooling_dev;
|
struct thermal_cooling_device *cooling_dev;
|
||||||
};
|
};
|
||||||
|
|
||||||
static int int3406_thermal_to_raw(int level, struct int3406_thermal_data *d)
|
/*
|
||||||
{
|
* According to the ACPI spec,
|
||||||
int max_level = d->br->levels[d->br->count - 1];
|
* "Each brightness level is represented by a number between 0 and 100,
|
||||||
int raw_max = d->raw_bd->props.max_brightness;
|
* and can be thought of as a percentage. For example, 50 can be 50%
|
||||||
|
* power consumption or 50% brightness, as defined by the OEM."
|
||||||
return level * raw_max / max_level;
|
*
|
||||||
}
|
* As int3406 device uses this value to communicate with the native
|
||||||
|
* graphics driver, we make the assumption that it represents
|
||||||
static int int3406_thermal_to_acpi(int level, struct int3406_thermal_data *d)
|
* the percentage of brightness only
|
||||||
{
|
*/
|
||||||
int raw_max = d->raw_bd->props.max_brightness;
|
#define ACPI_TO_RAW(v, d) (d->raw_bd->props.max_brightness * v / 100)
|
||||||
int max_level = d->br->levels[d->br->count - 1];
|
#define RAW_TO_ACPI(v, d) (v * 100 / d->raw_bd->props.max_brightness)
|
||||||
|
|
||||||
return level * max_level / raw_max;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int
|
static int
|
||||||
int3406_thermal_get_max_state(struct thermal_cooling_device *cooling_dev,
|
int3406_thermal_get_max_state(struct thermal_cooling_device *cooling_dev,
|
||||||
unsigned long *state)
|
unsigned long *state)
|
||||||
{
|
{
|
||||||
struct int3406_thermal_data *d = cooling_dev->devdata;
|
struct int3406_thermal_data *d = cooling_dev->devdata;
|
||||||
int index = d->lower_limit_index ? d->lower_limit_index : 2;
|
|
||||||
|
|
||||||
*state = d->br->count - 1 - index;
|
*state = d->upper_limit - d->lower_limit;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -62,19 +56,15 @@ int3406_thermal_set_cur_state(struct thermal_cooling_device *cooling_dev,
|
|||||||
unsigned long state)
|
unsigned long state)
|
||||||
{
|
{
|
||||||
struct int3406_thermal_data *d = cooling_dev->devdata;
|
struct int3406_thermal_data *d = cooling_dev->devdata;
|
||||||
int level, raw_level;
|
int acpi_level, raw_level;
|
||||||
|
|
||||||
if (state > d->br->count - 3)
|
if (state > d->upper_limit - d->lower_limit)
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
|
||||||
state = d->br->count - 1 - state;
|
acpi_level = d->br->levels[d->upper_limit - state];
|
||||||
level = d->br->levels[state];
|
|
||||||
|
|
||||||
if ((d->upper_limit && level > d->upper_limit) ||
|
raw_level = ACPI_TO_RAW(acpi_level, d);
|
||||||
(d->lower_limit && level < d->lower_limit))
|
|
||||||
return -EINVAL;
|
|
||||||
|
|
||||||
raw_level = int3406_thermal_to_raw(level, d);
|
|
||||||
return backlight_device_set_brightness(d->raw_bd, raw_level);
|
return backlight_device_set_brightness(d->raw_bd, raw_level);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -83,27 +73,22 @@ int3406_thermal_get_cur_state(struct thermal_cooling_device *cooling_dev,
|
|||||||
unsigned long *state)
|
unsigned long *state)
|
||||||
{
|
{
|
||||||
struct int3406_thermal_data *d = cooling_dev->devdata;
|
struct int3406_thermal_data *d = cooling_dev->devdata;
|
||||||
int raw_level, level, i;
|
int acpi_level;
|
||||||
int *levels = d->br->levels;
|
int index;
|
||||||
|
|
||||||
raw_level = d->raw_bd->props.brightness;
|
acpi_level = RAW_TO_ACPI(d->raw_bd->props.brightness, d);
|
||||||
level = int3406_thermal_to_acpi(raw_level, d);
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* There is no 1:1 mapping between the firmware interface level with the
|
* There is no 1:1 mapping between the firmware interface level
|
||||||
* raw interface level, we will have to find one that is close enough.
|
* with the raw interface level, we will have to find one that is
|
||||||
|
* right above it.
|
||||||
*/
|
*/
|
||||||
for (i = 2; i < d->br->count; i++) {
|
for (index = d->lower_limit; index < d->upper_limit; index++) {
|
||||||
if (level < levels[i]) {
|
if (acpi_level <= d->br->levels[index])
|
||||||
if (i == 2)
|
|
||||||
break;
|
|
||||||
if ((level - levels[i - 1]) < (levels[i] - level))
|
|
||||||
i--;
|
|
||||||
break;
|
break;
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
*state = d->br->count - 1 - i;
|
*state = d->upper_limit - index;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -117,7 +102,7 @@ static int int3406_thermal_get_index(int *array, int nr, int value)
|
|||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
for (i = 0; i < nr; i++) {
|
for (i = 2; i < nr; i++) {
|
||||||
if (array[i] == value)
|
if (array[i] == value)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -128,27 +113,20 @@ static void int3406_thermal_get_limit(struct int3406_thermal_data *d)
|
|||||||
{
|
{
|
||||||
acpi_status status;
|
acpi_status status;
|
||||||
unsigned long long lower_limit, upper_limit;
|
unsigned long long lower_limit, upper_limit;
|
||||||
int index;
|
|
||||||
|
|
||||||
status = acpi_evaluate_integer(d->handle, "DDDL", NULL, &lower_limit);
|
status = acpi_evaluate_integer(d->handle, "DDDL", NULL, &lower_limit);
|
||||||
if (ACPI_SUCCESS(status)) {
|
if (ACPI_SUCCESS(status))
|
||||||
index = int3406_thermal_get_index(d->br->levels, d->br->count,
|
d->lower_limit = int3406_thermal_get_index(d->br->levels,
|
||||||
lower_limit);
|
d->br->count, lower_limit);
|
||||||
if (index > 0) {
|
|
||||||
d->lower_limit = (int)lower_limit;
|
|
||||||
d->lower_limit_index = index;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
status = acpi_evaluate_integer(d->handle, "DDPC", NULL, &upper_limit);
|
status = acpi_evaluate_integer(d->handle, "DDPC", NULL, &upper_limit);
|
||||||
if (ACPI_SUCCESS(status)) {
|
if (ACPI_SUCCESS(status))
|
||||||
index = int3406_thermal_get_index(d->br->levels, d->br->count,
|
d->upper_limit = int3406_thermal_get_index(d->br->levels,
|
||||||
upper_limit);
|
d->br->count, upper_limit);
|
||||||
if (index > 0) {
|
|
||||||
d->upper_limit = (int)upper_limit;
|
/* lower_limit and upper_limit should be always set */
|
||||||
d->upper_limit_index = index;
|
d->lower_limit = d->lower_limit > 0 ? d->lower_limit : 2;
|
||||||
}
|
d->upper_limit = d->upper_limit > 0 ? d->upper_limit : d->br->count - 1;
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void int3406_notify(acpi_handle handle, u32 event, void *data)
|
static void int3406_notify(acpi_handle handle, u32 event, void *data)
|
||||||
|
Loading…
Reference in New Issue
Block a user