Compare commits

..

No commits in common. "7bae1af5698a149481501c9dfdc7f05cd53792cb" and "a02b101be882535f84b7b51b41b14d4e4b03e89e" have entirely different histories.

3 changed files with 54 additions and 122 deletions

View File

@ -1,18 +1,3 @@
# System76 ACPI Driver (DKMS)
This provides the system76_acpi in-tree driver for systems missing it.
## Building .deb from source
```bash
sudo dpkg-buildpackage -b -uc -us
```
## Installing from built .deb
```bash
sudo dpkg -i ../system76-acpi-dkms_1.0.2_amd64.deb
```
## build, install and reload kernel module (for developing)
```bash
sudo dpkg-buildpackage -b -uc -us && sudo dpkg -i ../system76-acpi-dkms_1.0.2_amd64.deb && sudo modprobe -r system76_acpi && sleep 5 && sudo modprobe system76_acpi
```

3
debian/control vendored
View File

@ -4,8 +4,7 @@ Priority: optional
Maintainer: Jeremy Soller <jeremy@system76.com>
Build-Depends:
debhelper (>=9),
dh-sequence-dkms,
dkms,
dkms
Standards-Version: 4.1.1
Homepage: https://github.com/pop-os/system76-acpi-dkms

View File

@ -25,12 +25,6 @@
#include <acpi/battery.h>
enum kbled_type {
KBLED_NONE,
KBLED_WHITE,
KBLED_RGB,
};
struct system76_data {
struct acpi_device *acpi_dev;
struct led_classdev ap_led;
@ -42,8 +36,6 @@ struct system76_data {
union acpi_object *nfan;
union acpi_object *ntmp;
struct input_dev *input;
bool has_open_ec;
enum kbled_type kbled_type;
};
static const struct acpi_device_id device_ids[] = {
@ -156,6 +148,8 @@ static int system76_set(struct system76_data *data, char *method, int value)
return -1;
}
/* Battery */
#define BATTERY_THRESHOLD_INVALID 0xFF
enum {
@ -266,11 +260,7 @@ static struct attribute *system76_battery_attrs[] = {
ATTRIBUTE_GROUPS(system76_battery);
#if LINUX_VERSION_CODE >= KERNEL_VERSION(6,2,0)
static int system76_battery_add(struct power_supply *battery, struct acpi_battery_hook *hook)
#else
static int system76_battery_add(struct power_supply *battery)
#endif
{
// System76 EC only supports 1 battery
if (strcmp(battery->desc->name, "BAT0") != 0)
@ -282,11 +272,7 @@ static int system76_battery_add(struct power_supply *battery)
return 0;
}
#if LINUX_VERSION_CODE >= KERNEL_VERSION(6,2,0)
static int system76_battery_remove(struct power_supply *battery, struct acpi_battery_hook *hook)
#else
static int system76_battery_remove(struct power_supply *battery)
#endif
{
device_remove_groups(&battery->dev, system76_battery_groups);
return 0;
@ -300,14 +286,24 @@ static struct acpi_battery_hook system76_battery_hook = {
static void system76_battery_init(void)
{
acpi_handle handle;
handle = ec_get_handle();
if (handle && acpi_has_method(handle, "GBCT"))
battery_hook_register(&system76_battery_hook);
}
static void system76_battery_exit(void)
{
acpi_handle handle;
handle = ec_get_handle();
if (handle && acpi_has_method(handle, "GBCT"))
battery_hook_unregister(&system76_battery_hook);
}
/* Keyboard */
// Get the airplane mode LED brightness
static enum led_brightness ap_led_get(struct led_classdev *led)
{
@ -347,12 +343,8 @@ static int kb_led_set(struct led_classdev *led, enum led_brightness value)
data = container_of(led, struct system76_data, kb_led);
data->kb_brightness = value;
if (acpi_has_method(acpi_device_handle(data->acpi_dev), "GKBK")) {
return system76_set(data, "SKBB", (int)data->kb_brightness);
} else {
return system76_set(data, "SKBL", (int)data->kb_brightness);
}
}
// Get the last set keyboard LED color
static ssize_t kb_led_color_show(
@ -363,7 +355,7 @@ static ssize_t kb_led_color_show(
struct led_classdev *led;
struct system76_data *data;
led = dev_get_drvdata(dev);
led = (struct led_classdev *)dev->driver_data;
data = container_of(led, struct system76_data, kb_led);
#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 10, 0)
return sysfs_emit(buf, "%06X\n", data->kb_color);
@ -384,7 +376,7 @@ static ssize_t kb_led_color_store(
unsigned int val;
int ret;
led = dev_get_drvdata(dev);
led = (struct led_classdev *)dev->driver_data;
data = container_of(led, struct system76_data, kb_led);
ret = kstrtouint(buf, 16, &val);
if (ret)
@ -427,12 +419,7 @@ static void kb_led_hotkey_hardware(struct system76_data *data)
{
int value;
if (acpi_has_method(acpi_device_handle(data->acpi_dev), "GKBK")) {
value = system76_get(data, "GKBB");
} else {
value = system76_get(data, "GKBL");
}
if (value < 0)
return;
data->kb_brightness = value;
@ -492,9 +479,8 @@ static void kb_led_hotkey_color(struct system76_data *data)
{
int i;
if (data->kbled_type != KBLED_RGB)
if (data->kb_color < 0)
return;
if (data->kb_brightness > 0) {
for (i = 0; i < ARRAY_SIZE(kb_colors); i++) {
if (kb_colors[i] == data->kb_color)
@ -511,6 +497,8 @@ static void kb_led_hotkey_color(struct system76_data *data)
kb_led_notify(data);
}
/* hwmon */
static umode_t thermal_is_visible(const void *drvdata, enum hwmon_sensor_types type,
u32 attr, int channel)
{
@ -615,7 +603,7 @@ static const struct hwmon_ops thermal_ops = {
};
// Allocate up to 8 fans and temperatures
static const struct hwmon_channel_info * const thermal_channel_info[] = {
static const struct hwmon_channel_info *thermal_channel_info[] = {
HWMON_CHANNEL_INFO(fan,
HWMON_F_INPUT | HWMON_F_LABEL,
HWMON_F_INPUT | HWMON_F_LABEL,
@ -651,6 +639,8 @@ static const struct hwmon_chip_info thermal_chip_info = {
.info = thermal_channel_info,
};
/* ACPI driver */
static void input_key(struct system76_data *data, unsigned int code)
{
input_report_key(data->input, code, 1);
@ -700,10 +690,6 @@ static int system76_add(struct acpi_device *acpi_dev)
acpi_dev->driver_data = data;
data->acpi_dev = acpi_dev;
// Some models do not run open EC firmware. Check for an ACPI method
// that only exists on open EC to guard functionality specific to it.
data->has_open_ec = acpi_has_method(acpi_device_handle(data->acpi_dev), "NFAN");
err = system76_get(data, "INIT");
if (err)
return err;
@ -721,46 +707,19 @@ static int system76_add(struct acpi_device *acpi_dev)
data->kb_led.flags = LED_BRIGHT_HW_CHANGED | LED_CORE_SUSPENDRESUME;
data->kb_led.brightness_get = kb_led_get;
data->kb_led.brightness_set_blocking = kb_led_set;
if (acpi_has_method(acpi_device_handle(data->acpi_dev), "GKBK")) {
// Use the new ACPI methods
data->kbled_type = system76_get(data, "GKBK");
switch (data->kbled_type) {
case KBLED_NONE:
// Nothing to do: Device will not be registered.
break;
case KBLED_WHITE:
data->kb_led.max_brightness = 255;
data->kb_toggle_brightness = 72;
break;
case KBLED_RGB:
data->kb_led.max_brightness = 255;
data->kb_led.groups = system76_kb_led_color_groups;
data->kb_toggle_brightness = 72;
data->kb_color = 0xffffff;
system76_set(data, "SKBC", data->kb_color);
break;
}
} else {
// Use the old ACPI methods
if (acpi_has_method(acpi_device_handle(data->acpi_dev), "SKBC")) {
data->kbled_type = KBLED_RGB;
data->kb_led.max_brightness = 255;
data->kb_led.groups = system76_kb_led_color_groups;
data->kb_toggle_brightness = 72;
data->kb_color = 0xffffff;
system76_set(data, "SKBC", data->kb_color);
} else {
data->kbled_type = KBLED_WHITE;
data->kb_led.max_brightness = 5;
data->kb_color = -1;
}
}
if (data->kbled_type != KBLED_NONE) {
err = devm_led_classdev_register(&acpi_dev->dev, &data->kb_led);
if (err)
return err;
}
data->input = devm_input_allocate_device(&acpi_dev->dev);
if (!data->input)
@ -776,7 +735,6 @@ static int system76_add(struct acpi_device *acpi_dev)
if (err)
goto error;
if (data->has_open_ec) {
err = system76_get_object(data, "NFAN", &data->nfan);
if (err)
goto error;
@ -792,43 +750,33 @@ static int system76_add(struct acpi_device *acpi_dev)
goto error;
system76_battery_init();
}
return 0;
error:
if (data->has_open_ec) {
kfree(data->ntmp);
kfree(data->nfan);
}
return err;
}
// Remove a System76 ACPI device
#if LINUX_VERSION_CODE >= KERNEL_VERSION(6,2,0)
static void system76_remove(struct acpi_device *acpi_dev)
#else
static int system76_remove(struct acpi_device *acpi_dev)
#endif
{
struct system76_data *data;
data = acpi_driver_data(acpi_dev);
if (data->has_open_ec) {
system76_battery_exit();
kfree(data->nfan);
kfree(data->ntmp);
}
devm_led_classdev_unregister(&acpi_dev->dev, &data->ap_led);
devm_led_classdev_unregister(&acpi_dev->dev, &data->kb_led);
kfree(data->nfan);
kfree(data->ntmp);
system76_get(data, "FINI");
#if LINUX_VERSION_CODE < KERNEL_VERSION(6,2,0)
return 0;
#endif
}
static struct acpi_driver system76_driver = {