Merge branches 'acpi-battery', 'acpi-video', 'acpi-fan' and 'acpi-drivers'
* acpi-battery: ACPI / battery: Deal better with neither design nor full capacity not being reported ACPI / battery: Use design-cap for capacity calculations if full-cap is not available ACPI / battery: Deal with design or full capacity being reported as -1 * acpi-video: ACPI: video: Do not export a non working backlight interface on MSI MS-7721 boards ACPI: video: Use native backlight on Lenovo E41-25/45 ACPI: video: fix typo in comment * acpi-fan: ACPI: fan: Expose fan performance state information * acpi-drivers: thermal: int340x_thermal: Add Tiger Lake ACPI device IDs platform/x86: intel-hid: Add Tiger Lake ACPI device ID ACPI: fan: Add Tiger Lake ACPI device ID ACPI: DPTF: Add Tiger Lake ACPI device IDs
This commit is contained in:
@@ -0,0 +1,62 @@
|
|||||||
|
.. SPDX-License-Identifier: GPL-2.0
|
||||||
|
|
||||||
|
===========================
|
||||||
|
ACPI Fan Performance States
|
||||||
|
===========================
|
||||||
|
|
||||||
|
When the optional _FPS object is present under an ACPI device representing a
|
||||||
|
fan (for example, PNP0C0B or INT3404), the ACPI fan driver creates additional
|
||||||
|
"state*" attributes in the sysfs directory of the ACPI device in question.
|
||||||
|
These attributes list properties of fan performance states.
|
||||||
|
|
||||||
|
For more information on _FPS refer to the ACPI specification at:
|
||||||
|
|
||||||
|
http://uefi.org/specifications
|
||||||
|
|
||||||
|
For instance, the contents of the INT3404 ACPI device sysfs directory
|
||||||
|
may look as follows::
|
||||||
|
|
||||||
|
$ ls -l /sys/bus/acpi/devices/INT3404:00/
|
||||||
|
total 0
|
||||||
|
...
|
||||||
|
-r--r--r-- 1 root root 4096 Dec 13 20:38 state0
|
||||||
|
-r--r--r-- 1 root root 4096 Dec 13 20:38 state1
|
||||||
|
-r--r--r-- 1 root root 4096 Dec 13 20:38 state10
|
||||||
|
-r--r--r-- 1 root root 4096 Dec 13 20:38 state11
|
||||||
|
-r--r--r-- 1 root root 4096 Dec 13 20:38 state2
|
||||||
|
-r--r--r-- 1 root root 4096 Dec 13 20:38 state3
|
||||||
|
-r--r--r-- 1 root root 4096 Dec 13 20:38 state4
|
||||||
|
-r--r--r-- 1 root root 4096 Dec 13 20:38 state5
|
||||||
|
-r--r--r-- 1 root root 4096 Dec 13 20:38 state6
|
||||||
|
-r--r--r-- 1 root root 4096 Dec 13 20:38 state7
|
||||||
|
-r--r--r-- 1 root root 4096 Dec 13 20:38 state8
|
||||||
|
-r--r--r-- 1 root root 4096 Dec 13 20:38 state9
|
||||||
|
-r--r--r-- 1 root root 4096 Dec 13 01:00 status
|
||||||
|
...
|
||||||
|
|
||||||
|
where each of the "state*" files represents one performance state of the fan
|
||||||
|
and contains a colon-separated list of 5 integer numbers (fields) with the
|
||||||
|
following interpretation::
|
||||||
|
|
||||||
|
control_percent:trip_point_index:speed_rpm:noise_level_mdb:power_mw
|
||||||
|
|
||||||
|
* ``control_percent``: The percent value to be used to set the fan speed to a
|
||||||
|
specific level using the _FSL object (0-100).
|
||||||
|
|
||||||
|
* ``trip_point_index``: The active cooling trip point number that corresponds
|
||||||
|
to this performance state (0-9).
|
||||||
|
|
||||||
|
* ``speed_rpm``: Speed of the fan in rotations per minute.
|
||||||
|
|
||||||
|
* ``noise_level_mdb``: Audible noise emitted by the fan in this state in
|
||||||
|
millidecibels.
|
||||||
|
|
||||||
|
* ``power_mw``: Power draw of the fan in this state in milliwatts.
|
||||||
|
|
||||||
|
For example::
|
||||||
|
|
||||||
|
$cat /sys/bus/acpi/devices/INT3404:00/state1
|
||||||
|
25:0:3200:12500:1250
|
||||||
|
|
||||||
|
When a given field is not populated or its value provided by the platform
|
||||||
|
firmware is invalid, the "not-defined" string is shown instead of the value.
|
||||||
@@ -12,3 +12,4 @@ the Linux ACPI support.
|
|||||||
dsdt-override
|
dsdt-override
|
||||||
ssdt-overlays
|
ssdt-overlays
|
||||||
cppc_sysfs
|
cppc_sysfs
|
||||||
|
fan_performance_states
|
||||||
|
|||||||
@@ -2187,7 +2187,7 @@ int acpi_video_register(void)
|
|||||||
if (register_count) {
|
if (register_count) {
|
||||||
/*
|
/*
|
||||||
* if the function of acpi_video_register is already called,
|
* if the function of acpi_video_register is already called,
|
||||||
* don't register the acpi_vide_bus again and return no error.
|
* don't register the acpi_video_bus again and return no error.
|
||||||
*/
|
*/
|
||||||
goto leave;
|
goto leave;
|
||||||
}
|
}
|
||||||
|
|||||||
+56
-19
@@ -38,6 +38,8 @@
|
|||||||
#define PREFIX "ACPI: "
|
#define PREFIX "ACPI: "
|
||||||
|
|
||||||
#define ACPI_BATTERY_VALUE_UNKNOWN 0xFFFFFFFF
|
#define ACPI_BATTERY_VALUE_UNKNOWN 0xFFFFFFFF
|
||||||
|
#define ACPI_BATTERY_CAPACITY_VALID(capacity) \
|
||||||
|
((capacity) != 0 && (capacity) != ACPI_BATTERY_VALUE_UNKNOWN)
|
||||||
|
|
||||||
#define ACPI_BATTERY_DEVICE_NAME "Battery"
|
#define ACPI_BATTERY_DEVICE_NAME "Battery"
|
||||||
|
|
||||||
@@ -192,7 +194,8 @@ static int acpi_battery_is_charged(struct acpi_battery *battery)
|
|||||||
|
|
||||||
static bool acpi_battery_is_degraded(struct acpi_battery *battery)
|
static bool acpi_battery_is_degraded(struct acpi_battery *battery)
|
||||||
{
|
{
|
||||||
return battery->full_charge_capacity && battery->design_capacity &&
|
return ACPI_BATTERY_CAPACITY_VALID(battery->full_charge_capacity) &&
|
||||||
|
ACPI_BATTERY_CAPACITY_VALID(battery->design_capacity) &&
|
||||||
battery->full_charge_capacity < battery->design_capacity;
|
battery->full_charge_capacity < battery->design_capacity;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -214,7 +217,7 @@ static int acpi_battery_get_property(struct power_supply *psy,
|
|||||||
enum power_supply_property psp,
|
enum power_supply_property psp,
|
||||||
union power_supply_propval *val)
|
union power_supply_propval *val)
|
||||||
{
|
{
|
||||||
int ret = 0;
|
int full_capacity = ACPI_BATTERY_VALUE_UNKNOWN, ret = 0;
|
||||||
struct acpi_battery *battery = to_acpi_battery(psy);
|
struct acpi_battery *battery = to_acpi_battery(psy);
|
||||||
|
|
||||||
if (acpi_battery_present(battery)) {
|
if (acpi_battery_present(battery)) {
|
||||||
@@ -263,14 +266,14 @@ static int acpi_battery_get_property(struct power_supply *psy,
|
|||||||
break;
|
break;
|
||||||
case POWER_SUPPLY_PROP_CHARGE_FULL_DESIGN:
|
case POWER_SUPPLY_PROP_CHARGE_FULL_DESIGN:
|
||||||
case POWER_SUPPLY_PROP_ENERGY_FULL_DESIGN:
|
case POWER_SUPPLY_PROP_ENERGY_FULL_DESIGN:
|
||||||
if (battery->design_capacity == ACPI_BATTERY_VALUE_UNKNOWN)
|
if (!ACPI_BATTERY_CAPACITY_VALID(battery->design_capacity))
|
||||||
ret = -ENODEV;
|
ret = -ENODEV;
|
||||||
else
|
else
|
||||||
val->intval = battery->design_capacity * 1000;
|
val->intval = battery->design_capacity * 1000;
|
||||||
break;
|
break;
|
||||||
case POWER_SUPPLY_PROP_CHARGE_FULL:
|
case POWER_SUPPLY_PROP_CHARGE_FULL:
|
||||||
case POWER_SUPPLY_PROP_ENERGY_FULL:
|
case POWER_SUPPLY_PROP_ENERGY_FULL:
|
||||||
if (battery->full_charge_capacity == ACPI_BATTERY_VALUE_UNKNOWN)
|
if (!ACPI_BATTERY_CAPACITY_VALID(battery->full_charge_capacity))
|
||||||
ret = -ENODEV;
|
ret = -ENODEV;
|
||||||
else
|
else
|
||||||
val->intval = battery->full_charge_capacity * 1000;
|
val->intval = battery->full_charge_capacity * 1000;
|
||||||
@@ -283,11 +286,17 @@ static int acpi_battery_get_property(struct power_supply *psy,
|
|||||||
val->intval = battery->capacity_now * 1000;
|
val->intval = battery->capacity_now * 1000;
|
||||||
break;
|
break;
|
||||||
case POWER_SUPPLY_PROP_CAPACITY:
|
case POWER_SUPPLY_PROP_CAPACITY:
|
||||||
if (battery->capacity_now && battery->full_charge_capacity)
|
if (ACPI_BATTERY_CAPACITY_VALID(battery->full_charge_capacity))
|
||||||
val->intval = battery->capacity_now * 100/
|
full_capacity = battery->full_charge_capacity;
|
||||||
battery->full_charge_capacity;
|
else if (ACPI_BATTERY_CAPACITY_VALID(battery->design_capacity))
|
||||||
|
full_capacity = battery->design_capacity;
|
||||||
|
|
||||||
|
if (battery->capacity_now == ACPI_BATTERY_VALUE_UNKNOWN ||
|
||||||
|
full_capacity == ACPI_BATTERY_VALUE_UNKNOWN)
|
||||||
|
ret = -ENODEV;
|
||||||
else
|
else
|
||||||
val->intval = 0;
|
val->intval = battery->capacity_now * 100/
|
||||||
|
full_capacity;
|
||||||
break;
|
break;
|
||||||
case POWER_SUPPLY_PROP_CAPACITY_LEVEL:
|
case POWER_SUPPLY_PROP_CAPACITY_LEVEL:
|
||||||
if (battery->state & ACPI_BATTERY_STATE_CRITICAL)
|
if (battery->state & ACPI_BATTERY_STATE_CRITICAL)
|
||||||
@@ -333,6 +342,20 @@ static enum power_supply_property charge_battery_props[] = {
|
|||||||
POWER_SUPPLY_PROP_SERIAL_NUMBER,
|
POWER_SUPPLY_PROP_SERIAL_NUMBER,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static enum power_supply_property charge_battery_full_cap_broken_props[] = {
|
||||||
|
POWER_SUPPLY_PROP_STATUS,
|
||||||
|
POWER_SUPPLY_PROP_PRESENT,
|
||||||
|
POWER_SUPPLY_PROP_TECHNOLOGY,
|
||||||
|
POWER_SUPPLY_PROP_CYCLE_COUNT,
|
||||||
|
POWER_SUPPLY_PROP_VOLTAGE_MIN_DESIGN,
|
||||||
|
POWER_SUPPLY_PROP_VOLTAGE_NOW,
|
||||||
|
POWER_SUPPLY_PROP_CURRENT_NOW,
|
||||||
|
POWER_SUPPLY_PROP_CHARGE_NOW,
|
||||||
|
POWER_SUPPLY_PROP_MODEL_NAME,
|
||||||
|
POWER_SUPPLY_PROP_MANUFACTURER,
|
||||||
|
POWER_SUPPLY_PROP_SERIAL_NUMBER,
|
||||||
|
};
|
||||||
|
|
||||||
static enum power_supply_property energy_battery_props[] = {
|
static enum power_supply_property energy_battery_props[] = {
|
||||||
POWER_SUPPLY_PROP_STATUS,
|
POWER_SUPPLY_PROP_STATUS,
|
||||||
POWER_SUPPLY_PROP_PRESENT,
|
POWER_SUPPLY_PROP_PRESENT,
|
||||||
@@ -794,20 +817,34 @@ static void __exit battery_hook_exit(void)
|
|||||||
static int sysfs_add_battery(struct acpi_battery *battery)
|
static int sysfs_add_battery(struct acpi_battery *battery)
|
||||||
{
|
{
|
||||||
struct power_supply_config psy_cfg = { .drv_data = battery, };
|
struct power_supply_config psy_cfg = { .drv_data = battery, };
|
||||||
|
bool full_cap_broken = false;
|
||||||
|
|
||||||
|
if (!ACPI_BATTERY_CAPACITY_VALID(battery->full_charge_capacity) &&
|
||||||
|
!ACPI_BATTERY_CAPACITY_VALID(battery->design_capacity))
|
||||||
|
full_cap_broken = true;
|
||||||
|
|
||||||
if (battery->power_unit == ACPI_BATTERY_POWER_UNIT_MA) {
|
if (battery->power_unit == ACPI_BATTERY_POWER_UNIT_MA) {
|
||||||
battery->bat_desc.properties = charge_battery_props;
|
if (full_cap_broken) {
|
||||||
battery->bat_desc.num_properties =
|
battery->bat_desc.properties =
|
||||||
ARRAY_SIZE(charge_battery_props);
|
charge_battery_full_cap_broken_props;
|
||||||
} else if (battery->full_charge_capacity == 0) {
|
battery->bat_desc.num_properties =
|
||||||
battery->bat_desc.properties =
|
ARRAY_SIZE(charge_battery_full_cap_broken_props);
|
||||||
energy_battery_full_cap_broken_props;
|
} else {
|
||||||
battery->bat_desc.num_properties =
|
battery->bat_desc.properties = charge_battery_props;
|
||||||
ARRAY_SIZE(energy_battery_full_cap_broken_props);
|
battery->bat_desc.num_properties =
|
||||||
|
ARRAY_SIZE(charge_battery_props);
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
battery->bat_desc.properties = energy_battery_props;
|
if (full_cap_broken) {
|
||||||
battery->bat_desc.num_properties =
|
battery->bat_desc.properties =
|
||||||
ARRAY_SIZE(energy_battery_props);
|
energy_battery_full_cap_broken_props;
|
||||||
|
battery->bat_desc.num_properties =
|
||||||
|
ARRAY_SIZE(energy_battery_full_cap_broken_props);
|
||||||
|
} else {
|
||||||
|
battery->bat_desc.properties = energy_battery_props;
|
||||||
|
battery->bat_desc.num_properties =
|
||||||
|
ARRAY_SIZE(energy_battery_props);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
battery->bat_desc.name = acpi_device_bid(battery->device);
|
battery->bat_desc.name = acpi_device_bid(battery->device);
|
||||||
|
|||||||
@@ -1321,6 +1321,7 @@ int acpi_dev_pm_attach(struct device *dev, bool power_on)
|
|||||||
*/
|
*/
|
||||||
static const struct acpi_device_id special_pm_ids[] = {
|
static const struct acpi_device_id special_pm_ids[] = {
|
||||||
{"PNP0C0B", }, /* Generic ACPI fan */
|
{"PNP0C0B", }, /* Generic ACPI fan */
|
||||||
|
{"INT1044", }, /* Fan for Tiger Lake generation */
|
||||||
{"INT3404", }, /* Fan */
|
{"INT3404", }, /* Fan */
|
||||||
{}
|
{}
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -97,6 +97,7 @@ static int dptf_power_remove(struct platform_device *pdev)
|
|||||||
}
|
}
|
||||||
|
|
||||||
static const struct acpi_device_id int3407_device_ids[] = {
|
static const struct acpi_device_id int3407_device_ids[] = {
|
||||||
|
{"INT1047", 0},
|
||||||
{"INT3407", 0},
|
{"INT3407", 0},
|
||||||
{"", 0},
|
{"", 0},
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -13,6 +13,10 @@
|
|||||||
|
|
||||||
#define INT3401_DEVICE 0X01
|
#define INT3401_DEVICE 0X01
|
||||||
static const struct acpi_device_id int340x_thermal_device_ids[] = {
|
static const struct acpi_device_id int340x_thermal_device_ids[] = {
|
||||||
|
{"INT1040"},
|
||||||
|
{"INT1043"},
|
||||||
|
{"INT1044"},
|
||||||
|
{"INT1047"},
|
||||||
{"INT3400"},
|
{"INT3400"},
|
||||||
{"INT3401", INT3401_DEVICE},
|
{"INT3401", INT3401_DEVICE},
|
||||||
{"INT3402"},
|
{"INT3402"},
|
||||||
|
|||||||
+89
-8
@@ -25,6 +25,7 @@ static int acpi_fan_remove(struct platform_device *pdev);
|
|||||||
|
|
||||||
static const struct acpi_device_id fan_device_ids[] = {
|
static const struct acpi_device_id fan_device_ids[] = {
|
||||||
{"PNP0C0B", 0},
|
{"PNP0C0B", 0},
|
||||||
|
{"INT1044", 0},
|
||||||
{"INT3404", 0},
|
{"INT3404", 0},
|
||||||
{"", 0},
|
{"", 0},
|
||||||
};
|
};
|
||||||
@@ -44,12 +45,16 @@ static const struct dev_pm_ops acpi_fan_pm = {
|
|||||||
#define FAN_PM_OPS_PTR NULL
|
#define FAN_PM_OPS_PTR NULL
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#define ACPI_FPS_NAME_LEN 20
|
||||||
|
|
||||||
struct acpi_fan_fps {
|
struct acpi_fan_fps {
|
||||||
u64 control;
|
u64 control;
|
||||||
u64 trip_point;
|
u64 trip_point;
|
||||||
u64 speed;
|
u64 speed;
|
||||||
u64 noise_level;
|
u64 noise_level;
|
||||||
u64 power;
|
u64 power;
|
||||||
|
char name[ACPI_FPS_NAME_LEN];
|
||||||
|
struct device_attribute dev_attr;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct acpi_fan_fif {
|
struct acpi_fan_fif {
|
||||||
@@ -265,6 +270,39 @@ static int acpi_fan_speed_cmp(const void *a, const void *b)
|
|||||||
return fps1->speed - fps2->speed;
|
return fps1->speed - fps2->speed;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static ssize_t show_state(struct device *dev, struct device_attribute *attr, char *buf)
|
||||||
|
{
|
||||||
|
struct acpi_fan_fps *fps = container_of(attr, struct acpi_fan_fps, dev_attr);
|
||||||
|
int count;
|
||||||
|
|
||||||
|
if (fps->control == 0xFFFFFFFF || fps->control > 100)
|
||||||
|
count = snprintf(buf, PAGE_SIZE, "not-defined:");
|
||||||
|
else
|
||||||
|
count = snprintf(buf, PAGE_SIZE, "%lld:", fps->control);
|
||||||
|
|
||||||
|
if (fps->trip_point == 0xFFFFFFFF || fps->trip_point > 9)
|
||||||
|
count += snprintf(&buf[count], PAGE_SIZE, "not-defined:");
|
||||||
|
else
|
||||||
|
count += snprintf(&buf[count], PAGE_SIZE, "%lld:", fps->trip_point);
|
||||||
|
|
||||||
|
if (fps->speed == 0xFFFFFFFF)
|
||||||
|
count += snprintf(&buf[count], PAGE_SIZE, "not-defined:");
|
||||||
|
else
|
||||||
|
count += snprintf(&buf[count], PAGE_SIZE, "%lld:", fps->speed);
|
||||||
|
|
||||||
|
if (fps->noise_level == 0xFFFFFFFF)
|
||||||
|
count += snprintf(&buf[count], PAGE_SIZE, "not-defined:");
|
||||||
|
else
|
||||||
|
count += snprintf(&buf[count], PAGE_SIZE, "%lld:", fps->noise_level * 100);
|
||||||
|
|
||||||
|
if (fps->power == 0xFFFFFFFF)
|
||||||
|
count += snprintf(&buf[count], PAGE_SIZE, "not-defined\n");
|
||||||
|
else
|
||||||
|
count += snprintf(&buf[count], PAGE_SIZE, "%lld\n", fps->power);
|
||||||
|
|
||||||
|
return count;
|
||||||
|
}
|
||||||
|
|
||||||
static int acpi_fan_get_fps(struct acpi_device *device)
|
static int acpi_fan_get_fps(struct acpi_device *device)
|
||||||
{
|
{
|
||||||
struct acpi_fan *fan = acpi_driver_data(device);
|
struct acpi_fan *fan = acpi_driver_data(device);
|
||||||
@@ -295,12 +333,13 @@ static int acpi_fan_get_fps(struct acpi_device *device)
|
|||||||
}
|
}
|
||||||
for (i = 0; i < fan->fps_count; i++) {
|
for (i = 0; i < fan->fps_count; i++) {
|
||||||
struct acpi_buffer format = { sizeof("NNNNN"), "NNNNN" };
|
struct acpi_buffer format = { sizeof("NNNNN"), "NNNNN" };
|
||||||
struct acpi_buffer fps = { sizeof(fan->fps[i]), &fan->fps[i] };
|
struct acpi_buffer fps = { offsetof(struct acpi_fan_fps, name),
|
||||||
|
&fan->fps[i] };
|
||||||
status = acpi_extract_package(&obj->package.elements[i + 1],
|
status = acpi_extract_package(&obj->package.elements[i + 1],
|
||||||
&format, &fps);
|
&format, &fps);
|
||||||
if (ACPI_FAILURE(status)) {
|
if (ACPI_FAILURE(status)) {
|
||||||
dev_err(&device->dev, "Invalid _FPS element\n");
|
dev_err(&device->dev, "Invalid _FPS element\n");
|
||||||
break;
|
goto err;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -308,6 +347,24 @@ static int acpi_fan_get_fps(struct acpi_device *device)
|
|||||||
sort(fan->fps, fan->fps_count, sizeof(*fan->fps),
|
sort(fan->fps, fan->fps_count, sizeof(*fan->fps),
|
||||||
acpi_fan_speed_cmp, NULL);
|
acpi_fan_speed_cmp, NULL);
|
||||||
|
|
||||||
|
for (i = 0; i < fan->fps_count; ++i) {
|
||||||
|
struct acpi_fan_fps *fps = &fan->fps[i];
|
||||||
|
|
||||||
|
snprintf(fps->name, ACPI_FPS_NAME_LEN, "state%d", i);
|
||||||
|
fps->dev_attr.show = show_state;
|
||||||
|
fps->dev_attr.store = NULL;
|
||||||
|
fps->dev_attr.attr.name = fps->name;
|
||||||
|
fps->dev_attr.attr.mode = 0444;
|
||||||
|
status = sysfs_create_file(&device->dev.kobj, &fps->dev_attr.attr);
|
||||||
|
if (status) {
|
||||||
|
int j;
|
||||||
|
|
||||||
|
for (j = 0; j < i; ++j)
|
||||||
|
sysfs_remove_file(&device->dev.kobj, &fan->fps[j].dev_attr.attr);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
err:
|
err:
|
||||||
kfree(obj);
|
kfree(obj);
|
||||||
return status;
|
return status;
|
||||||
@@ -330,14 +387,20 @@ static int acpi_fan_probe(struct platform_device *pdev)
|
|||||||
platform_set_drvdata(pdev, fan);
|
platform_set_drvdata(pdev, fan);
|
||||||
|
|
||||||
if (acpi_fan_is_acpi4(device)) {
|
if (acpi_fan_is_acpi4(device)) {
|
||||||
if (acpi_fan_get_fif(device) || acpi_fan_get_fps(device))
|
result = acpi_fan_get_fif(device);
|
||||||
goto end;
|
if (result)
|
||||||
|
return result;
|
||||||
|
|
||||||
|
result = acpi_fan_get_fps(device);
|
||||||
|
if (result)
|
||||||
|
return result;
|
||||||
|
|
||||||
fan->acpi4 = true;
|
fan->acpi4 = true;
|
||||||
} else {
|
} else {
|
||||||
result = acpi_device_update_power(device, NULL);
|
result = acpi_device_update_power(device, NULL);
|
||||||
if (result) {
|
if (result) {
|
||||||
dev_err(&device->dev, "Failed to set initial power state\n");
|
dev_err(&device->dev, "Failed to set initial power state\n");
|
||||||
goto end;
|
goto err_end;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -350,7 +413,7 @@ static int acpi_fan_probe(struct platform_device *pdev)
|
|||||||
&fan_cooling_ops);
|
&fan_cooling_ops);
|
||||||
if (IS_ERR(cdev)) {
|
if (IS_ERR(cdev)) {
|
||||||
result = PTR_ERR(cdev);
|
result = PTR_ERR(cdev);
|
||||||
goto end;
|
goto err_end;
|
||||||
}
|
}
|
||||||
|
|
||||||
dev_dbg(&pdev->dev, "registered as cooling_device%d\n", cdev->id);
|
dev_dbg(&pdev->dev, "registered as cooling_device%d\n", cdev->id);
|
||||||
@@ -365,10 +428,21 @@ static int acpi_fan_probe(struct platform_device *pdev)
|
|||||||
result = sysfs_create_link(&cdev->device.kobj,
|
result = sysfs_create_link(&cdev->device.kobj,
|
||||||
&pdev->dev.kobj,
|
&pdev->dev.kobj,
|
||||||
"device");
|
"device");
|
||||||
if (result)
|
if (result) {
|
||||||
dev_err(&pdev->dev, "Failed to create sysfs link 'device'\n");
|
dev_err(&pdev->dev, "Failed to create sysfs link 'device'\n");
|
||||||
|
goto err_end;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
err_end:
|
||||||
|
if (fan->acpi4) {
|
||||||
|
int i;
|
||||||
|
|
||||||
|
for (i = 0; i < fan->fps_count; ++i)
|
||||||
|
sysfs_remove_file(&device->dev.kobj, &fan->fps[i].dev_attr.attr);
|
||||||
|
}
|
||||||
|
|
||||||
end:
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -376,6 +450,13 @@ static int acpi_fan_remove(struct platform_device *pdev)
|
|||||||
{
|
{
|
||||||
struct acpi_fan *fan = platform_get_drvdata(pdev);
|
struct acpi_fan *fan = platform_get_drvdata(pdev);
|
||||||
|
|
||||||
|
if (fan->acpi4) {
|
||||||
|
struct acpi_device *device = ACPI_COMPANION(&pdev->dev);
|
||||||
|
int i;
|
||||||
|
|
||||||
|
for (i = 0; i < fan->fps_count; ++i)
|
||||||
|
sysfs_remove_file(&device->dev.kobj, &fan->fps[i].dev_attr.attr);
|
||||||
|
}
|
||||||
sysfs_remove_link(&pdev->dev.kobj, "thermal_cooling");
|
sysfs_remove_link(&pdev->dev.kobj, "thermal_cooling");
|
||||||
sysfs_remove_link(&fan->cdev->device.kobj, "device");
|
sysfs_remove_link(&fan->cdev->device.kobj, "device");
|
||||||
thermal_cooling_device_unregister(fan->cdev);
|
thermal_cooling_device_unregister(fan->cdev);
|
||||||
|
|||||||
@@ -302,6 +302,22 @@ static const struct dmi_system_id video_detect_dmi_table[] = {
|
|||||||
DMI_MATCH(DMI_PRODUCT_NAME, "102434U"),
|
DMI_MATCH(DMI_PRODUCT_NAME, "102434U"),
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
.callback = video_detect_force_native,
|
||||||
|
.ident = "Lenovo E41-25",
|
||||||
|
.matches = {
|
||||||
|
DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"),
|
||||||
|
DMI_MATCH(DMI_PRODUCT_NAME, "81FS"),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
.callback = video_detect_force_native,
|
||||||
|
.ident = "Lenovo E41-45",
|
||||||
|
.matches = {
|
||||||
|
DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"),
|
||||||
|
DMI_MATCH(DMI_PRODUCT_NAME, "82BK"),
|
||||||
|
},
|
||||||
|
},
|
||||||
{
|
{
|
||||||
/* https://bugzilla.redhat.com/show_bug.cgi?id=1217249 */
|
/* https://bugzilla.redhat.com/show_bug.cgi?id=1217249 */
|
||||||
.callback = video_detect_force_native,
|
.callback = video_detect_force_native,
|
||||||
@@ -336,6 +352,11 @@ static const struct dmi_system_id video_detect_dmi_table[] = {
|
|||||||
DMI_MATCH(DMI_PRODUCT_NAME, "Precision 7510"),
|
DMI_MATCH(DMI_PRODUCT_NAME, "Precision 7510"),
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Desktops which falsely report a backlight and which our heuristics
|
||||||
|
* for this do not catch.
|
||||||
|
*/
|
||||||
{
|
{
|
||||||
.callback = video_detect_force_none,
|
.callback = video_detect_force_none,
|
||||||
.ident = "Dell OptiPlex 9020M",
|
.ident = "Dell OptiPlex 9020M",
|
||||||
@@ -344,6 +365,14 @@ static const struct dmi_system_id video_detect_dmi_table[] = {
|
|||||||
DMI_MATCH(DMI_PRODUCT_NAME, "OptiPlex 9020M"),
|
DMI_MATCH(DMI_PRODUCT_NAME, "OptiPlex 9020M"),
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
.callback = video_detect_force_none,
|
||||||
|
.ident = "MSI MS-7721",
|
||||||
|
.matches = {
|
||||||
|
DMI_MATCH(DMI_SYS_VENDOR, "MSI"),
|
||||||
|
DMI_MATCH(DMI_PRODUCT_NAME, "MS-7721"),
|
||||||
|
},
|
||||||
|
},
|
||||||
{ },
|
{ },
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -19,6 +19,7 @@ MODULE_LICENSE("GPL");
|
|||||||
MODULE_AUTHOR("Alex Hung");
|
MODULE_AUTHOR("Alex Hung");
|
||||||
|
|
||||||
static const struct acpi_device_id intel_hid_ids[] = {
|
static const struct acpi_device_id intel_hid_ids[] = {
|
||||||
|
{"INT1051", 0},
|
||||||
{"INT33D5", 0},
|
{"INT33D5", 0},
|
||||||
{"", 0},
|
{"", 0},
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -369,6 +369,7 @@ static int int3400_thermal_remove(struct platform_device *pdev)
|
|||||||
}
|
}
|
||||||
|
|
||||||
static const struct acpi_device_id int3400_thermal_match[] = {
|
static const struct acpi_device_id int3400_thermal_match[] = {
|
||||||
|
{"INT1040", 0},
|
||||||
{"INT3400", 0},
|
{"INT3400", 0},
|
||||||
{}
|
{}
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -282,6 +282,7 @@ static int int3403_remove(struct platform_device *pdev)
|
|||||||
}
|
}
|
||||||
|
|
||||||
static const struct acpi_device_id int3403_device_ids[] = {
|
static const struct acpi_device_id int3403_device_ids[] = {
|
||||||
|
{"INT1043", 0},
|
||||||
{"INT3403", 0},
|
{"INT3403", 0},
|
||||||
{"", 0},
|
{"", 0},
|
||||||
};
|
};
|
||||||
|
|||||||
Reference in New Issue
Block a user