1 // SPDX-License-Identifier: GPL-2.0-or-later 2 /* 3 * Linux driver for Uniwill notebooks. 4 * 5 * Special thanks go to Pőcze Barnabás, Christoffer Sandberg and Werner Sembach 6 * for supporting the development of this driver either through prior work or 7 * by answering questions regarding the underlying ACPI and WMI interfaces. 8 * 9 * Copyright (C) 2025 Armin Wolf <W_Armin@gmx.de> 10 */ 11 12 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt 13 14 #include <linux/acpi.h> 15 #include <linux/array_size.h> 16 #include <linux/bits.h> 17 #include <linux/bitfield.h> 18 #include <linux/cleanup.h> 19 #include <linux/debugfs.h> 20 #include <linux/delay.h> 21 #include <linux/device.h> 22 #include <linux/device/driver.h> 23 #include <linux/dmi.h> 24 #include <linux/errno.h> 25 #include <linux/fixp-arith.h> 26 #include <linux/hwmon.h> 27 #include <linux/hwmon-sysfs.h> 28 #include <linux/init.h> 29 #include <linux/input.h> 30 #include <linux/input/sparse-keymap.h> 31 #include <linux/kernel.h> 32 #include <linux/kstrtox.h> 33 #include <linux/leds.h> 34 #include <linux/led-class-multicolor.h> 35 #include <linux/limits.h> 36 #include <linux/list.h> 37 #include <linux/minmax.h> 38 #include <linux/module.h> 39 #include <linux/mutex.h> 40 #include <linux/notifier.h> 41 #include <linux/platform_device.h> 42 #include <linux/pm.h> 43 #include <linux/printk.h> 44 #include <linux/regmap.h> 45 #include <linux/string.h> 46 #include <linux/sysfs.h> 47 #include <linux/types.h> 48 #include <linux/units.h> 49 50 #include <acpi/battery.h> 51 52 #include "uniwill-wmi.h" 53 54 #define EC_ADDR_BAT_POWER_UNIT_1 0x0400 55 56 #define EC_ADDR_BAT_POWER_UNIT_2 0x0401 57 58 #define EC_ADDR_BAT_DESIGN_CAPACITY_1 0x0402 59 60 #define EC_ADDR_BAT_DESIGN_CAPACITY_2 0x0403 61 62 #define EC_ADDR_BAT_FULL_CAPACITY_1 0x0404 63 64 #define EC_ADDR_BAT_FULL_CAPACITY_2 0x0405 65 66 #define EC_ADDR_BAT_DESIGN_VOLTAGE_1 0x0408 67 68 #define EC_ADDR_BAT_DESIGN_VOLTAGE_2 0x0409 69 70 #define EC_ADDR_BAT_STATUS_1 0x0432 71 #define BAT_DISCHARGING BIT(0) 72 73 #define EC_ADDR_BAT_STATUS_2 0x0433 74 75 #define EC_ADDR_BAT_CURRENT_1 0x0434 76 77 #define EC_ADDR_BAT_CURRENT_2 0x0435 78 79 #define EC_ADDR_BAT_REMAIN_CAPACITY_1 0x0436 80 81 #define EC_ADDR_BAT_REMAIN_CAPACITY_2 0x0437 82 83 #define EC_ADDR_BAT_VOLTAGE_1 0x0438 84 85 #define EC_ADDR_BAT_VOLTAGE_2 0x0439 86 87 #define EC_ADDR_CPU_TEMP 0x043E 88 89 #define EC_ADDR_GPU_TEMP 0x044F 90 91 #define EC_ADDR_MAIN_FAN_RPM_1 0x0464 92 93 #define EC_ADDR_MAIN_FAN_RPM_2 0x0465 94 95 #define EC_ADDR_SECOND_FAN_RPM_1 0x046C 96 97 #define EC_ADDR_SECOND_FAN_RPM_2 0x046D 98 99 #define EC_ADDR_DEVICE_STATUS 0x047B 100 #define WIFI_STATUS_ON BIT(7) 101 /* BIT(5) is also unset depending on the rfkill state (bluetooth?) */ 102 103 #define EC_ADDR_BAT_ALERT 0x0494 104 105 #define EC_ADDR_BAT_CYCLE_COUNT_1 0x04A6 106 107 #define EC_ADDR_BAT_CYCLE_COUNT_2 0x04A7 108 109 #define EC_ADDR_PROJECT_ID 0x0740 110 111 #define EC_ADDR_AP_OEM 0x0741 112 #define ENABLE_MANUAL_CTRL BIT(0) 113 #define ITE_KBD_EFFECT_REACTIVE BIT(3) 114 #define FAN_ABNORMAL BIT(5) 115 116 #define EC_ADDR_SUPPORT_5 0x0742 117 #define FAN_TURBO_SUPPORTED BIT(4) 118 #define FAN_SUPPORT BIT(5) 119 120 #define EC_ADDR_CTGP_DB_CTRL 0x0743 121 #define CTGP_DB_GENERAL_ENABLE BIT(0) 122 #define CTGP_DB_DB_ENABLE BIT(1) 123 #define CTGP_DB_CTGP_ENABLE BIT(2) 124 125 #define EC_ADDR_CTGP_OFFSET 0x0744 126 127 #define EC_ADDR_TPP_OFFSET 0x0745 128 129 #define EC_ADDR_MAX_TGP 0x0746 130 131 #define EC_ADDR_LIGHTBAR_AC_CTRL 0x0748 132 #define LIGHTBAR_APP_EXISTS BIT(0) 133 #define LIGHTBAR_POWER_SAVE BIT(1) 134 #define LIGHTBAR_S0_OFF BIT(2) 135 #define LIGHTBAR_S3_OFF BIT(3) // Breathing animation when suspended 136 #define LIGHTBAR_WELCOME BIT(7) // Rainbow animation 137 138 #define EC_ADDR_LIGHTBAR_AC_RED 0x0749 139 140 #define EC_ADDR_LIGHTBAR_AC_GREEN 0x074A 141 142 #define EC_ADDR_LIGHTBAR_AC_BLUE 0x074B 143 144 #define EC_ADDR_BIOS_OEM 0x074E 145 #define FN_LOCK_STATUS BIT(4) 146 147 #define EC_ADDR_MANUAL_FAN_CTRL 0x0751 148 #define FAN_LEVEL_MASK GENMASK(2, 0) 149 #define FAN_MODE_TURBO BIT(4) 150 #define FAN_MODE_HIGH BIT(5) 151 #define FAN_MODE_BOOST BIT(6) 152 #define FAN_MODE_USER BIT(7) 153 154 #define EC_ADDR_PWM_1 0x075B 155 156 #define EC_ADDR_PWM_2 0x075C 157 158 /* Unreliable */ 159 #define EC_ADDR_SUPPORT_1 0x0765 160 #define AIRPLANE_MODE BIT(0) 161 #define GPS_SWITCH BIT(1) 162 #define OVERCLOCK BIT(2) 163 #define MACRO_KEY BIT(3) 164 #define SHORTCUT_KEY BIT(4) 165 #define SUPER_KEY_LOCK BIT(5) 166 #define LIGHTBAR BIT(6) 167 #define FAN_BOOST BIT(7) 168 169 #define EC_ADDR_SUPPORT_2 0x0766 170 #define SILENT_MODE BIT(0) 171 #define USB_CHARGING BIT(1) 172 #define RGB_KEYBOARD BIT(2) 173 #define CHINA_MODE BIT(5) 174 #define MY_BATTERY BIT(6) 175 176 #define EC_ADDR_TRIGGER 0x0767 177 #define TRIGGER_SUPER_KEY_LOCK BIT(0) 178 #define TRIGGER_LIGHTBAR BIT(1) 179 #define TRIGGER_FAN_BOOST BIT(2) 180 #define TRIGGER_SILENT_MODE BIT(3) 181 #define TRIGGER_USB_CHARGING BIT(4) 182 #define RGB_APPLY_COLOR BIT(5) 183 #define RGB_LOGO_EFFECT BIT(6) 184 #define RGB_RAINBOW_EFFECT BIT(7) 185 186 #define EC_ADDR_SWITCH_STATUS 0x0768 187 #define SUPER_KEY_LOCK_STATUS BIT(0) 188 #define LIGHTBAR_STATUS BIT(1) 189 #define FAN_BOOST_STATUS BIT(2) 190 #define MACRO_KEY_STATUS BIT(3) 191 #define MY_BAT_POWER_BAT_STATUS BIT(4) 192 193 #define EC_ADDR_RGB_RED 0x0769 194 195 #define EC_ADDR_RGB_GREEN 0x076A 196 197 #define EC_ADDR_RGB_BLUE 0x076B 198 199 #define EC_ADDR_ROMID_START 0x0770 200 #define ROMID_LENGTH 14 201 202 #define EC_ADDR_ROMID_EXTRA_1 0x077E 203 204 #define EC_ADDR_ROMID_EXTRA_2 0x077F 205 206 #define EC_ADDR_BIOS_OEM_2 0x0782 207 #define FAN_V2_NEW BIT(0) 208 #define FAN_QKEY BIT(1) 209 #define FAN_TABLE_OFFICE_MODE BIT(2) 210 #define FAN_V3 BIT(3) 211 #define DEFAULT_MODE BIT(4) 212 213 #define EC_ADDR_PL1_SETTING 0x0783 214 215 #define EC_ADDR_PL2_SETTING 0x0784 216 217 #define EC_ADDR_PL4_SETTING 0x0785 218 219 #define EC_ADDR_FAN_DEFAULT 0x0786 220 #define FAN_CURVE_LENGTH 5 221 222 #define EC_ADDR_KBD_STATUS 0x078C 223 #define KBD_WHITE_ONLY BIT(0) // ~single color 224 #define KBD_SINGLE_COLOR_OFF BIT(1) 225 #define KBD_TURBO_LEVEL_MASK GENMASK(3, 2) 226 #define KBD_APPLY BIT(4) 227 #define KBD_BRIGHTNESS GENMASK(7, 5) 228 229 #define EC_ADDR_FAN_CTRL 0x078E 230 #define FAN3P5 BIT(1) 231 #define CHARGING_PROFILE BIT(3) 232 #define UNIVERSAL_FAN_CTRL BIT(6) 233 234 #define EC_ADDR_BIOS_OEM_3 0x07A3 235 #define FAN_REDUCED_DURY_CYCLE BIT(5) 236 #define FAN_ALWAYS_ON BIT(6) 237 238 #define EC_ADDR_BIOS_BYTE 0x07A4 239 #define FN_LOCK_SWITCH BIT(3) 240 241 #define EC_ADDR_OEM_3 0x07A5 242 #define POWER_LED_MASK GENMASK(1, 0) 243 #define POWER_LED_LEFT 0x00 244 #define POWER_LED_BOTH 0x01 245 #define POWER_LED_NONE 0x02 246 #define FAN_QUIET BIT(2) 247 #define OVERBOOST BIT(4) 248 #define HIGH_POWER BIT(7) 249 250 #define EC_ADDR_OEM_4 0x07A6 251 #define OVERBOOST_DYN_TEMP_OFF BIT(1) 252 #define TOUCHPAD_TOGGLE_OFF BIT(6) 253 254 #define EC_ADDR_CHARGE_CTRL 0x07B9 255 #define CHARGE_CTRL_MASK GENMASK(6, 0) 256 #define CHARGE_CTRL_REACHED BIT(7) 257 258 #define EC_ADDR_UNIVERSAL_FAN_CTRL 0x07C5 259 #define SPLIT_TABLES BIT(7) 260 261 #define EC_ADDR_AP_OEM_6 0x07C6 262 #define ENABLE_UNIVERSAL_FAN_CTRL BIT(2) 263 #define BATTERY_CHARGE_FULL_OVER_24H BIT(3) 264 #define BATTERY_ERM_STATUS_REACHED BIT(4) 265 266 #define EC_ADDR_CHARGE_PRIO 0x07CC 267 #define CHARGING_PERFORMANCE BIT(7) 268 269 /* Same bits as EC_ADDR_LIGHTBAR_AC_CTRL except LIGHTBAR_S3_OFF */ 270 #define EC_ADDR_LIGHTBAR_BAT_CTRL 0x07E2 271 272 #define EC_ADDR_LIGHTBAR_BAT_RED 0x07E3 273 274 #define EC_ADDR_LIGHTBAR_BAT_GREEN 0x07E4 275 276 #define EC_ADDR_LIGHTBAR_BAT_BLUE 0x07E5 277 278 #define EC_ADDR_CPU_TEMP_END_TABLE 0x0F00 279 280 #define EC_ADDR_CPU_TEMP_START_TABLE 0x0F10 281 282 #define EC_ADDR_CPU_FAN_SPEED_TABLE 0x0F20 283 284 #define EC_ADDR_GPU_TEMP_END_TABLE 0x0F30 285 286 #define EC_ADDR_GPU_TEMP_START_TABLE 0x0F40 287 288 #define EC_ADDR_GPU_FAN_SPEED_TABLE 0x0F50 289 290 /* 291 * Those two registers technically allow for manual fan control, 292 * but are unstable on some models and are likely not meant to 293 * be used by applications as they are only accessible when using 294 * the WMI interface. 295 */ 296 #define EC_ADDR_PWM_1_WRITEABLE 0x1804 297 298 #define EC_ADDR_PWM_2_WRITEABLE 0x1809 299 300 #define DRIVER_NAME "uniwill" 301 302 /* 303 * The OEM software always sleeps up to 6 ms after reading/writing EC 304 * registers, so we emulate this behaviour for maximum compatibility. 305 */ 306 #define UNIWILL_EC_DELAY_US 6000 307 308 #define PWM_MAX 200 309 #define FAN_TABLE_LENGTH 16 310 311 #define LED_CHANNELS 3 312 #define LED_MAX_BRIGHTNESS 200 313 314 #define UNIWILL_FEATURE_FN_LOCK_TOGGLE BIT(0) 315 #define UNIWILL_FEATURE_SUPER_KEY_TOGGLE BIT(1) 316 #define UNIWILL_FEATURE_TOUCHPAD_TOGGLE BIT(2) 317 #define UNIWILL_FEATURE_LIGHTBAR BIT(3) 318 #define UNIWILL_FEATURE_BATTERY BIT(4) 319 #define UNIWILL_FEATURE_HWMON BIT(5) 320 321 struct uniwill_data { 322 struct device *dev; 323 acpi_handle handle; 324 struct regmap *regmap; 325 struct acpi_battery_hook hook; 326 unsigned int last_charge_ctrl; 327 struct mutex battery_lock; /* Protects the list of currently registered batteries */ 328 unsigned int last_switch_status; 329 struct mutex super_key_lock; /* Protects the toggling of the super key lock state */ 330 struct list_head batteries; 331 struct mutex led_lock; /* Protects writes to the lightbar registers */ 332 struct led_classdev_mc led_mc_cdev; 333 struct mc_subled led_mc_subled_info[LED_CHANNELS]; 334 struct mutex input_lock; /* Protects input sequence during notify */ 335 struct input_dev *input_device; 336 struct notifier_block nb; 337 }; 338 339 struct uniwill_battery_entry { 340 struct list_head head; 341 struct power_supply *battery; 342 }; 343 344 static bool force; 345 module_param_unsafe(force, bool, 0); 346 MODULE_PARM_DESC(force, "Force loading without checking for supported devices\n"); 347 348 /* Feature bitmask since the associated registers are not reliable */ 349 static unsigned int supported_features; 350 351 static const char * const uniwill_temp_labels[] = { 352 "CPU", 353 "GPU", 354 }; 355 356 static const char * const uniwill_fan_labels[] = { 357 "Main", 358 "Secondary", 359 }; 360 361 static const struct key_entry uniwill_keymap[] = { 362 /* Reported via keyboard controller */ 363 { KE_IGNORE, UNIWILL_OSD_CAPSLOCK, { KEY_CAPSLOCK }}, 364 { KE_IGNORE, UNIWILL_OSD_NUMLOCK, { KEY_NUMLOCK }}, 365 366 /* Reported when the user locks/unlocks the super key */ 367 { KE_IGNORE, UNIWILL_OSD_SUPER_KEY_LOCK_ENABLE, { KEY_UNKNOWN }}, 368 { KE_IGNORE, UNIWILL_OSD_SUPER_KEY_LOCK_DISABLE, { KEY_UNKNOWN }}, 369 /* Optional, might not be reported by all devices */ 370 { KE_IGNORE, UNIWILL_OSD_SUPER_KEY_LOCK_CHANGED, { KEY_UNKNOWN }}, 371 372 /* Reported in manual mode when toggling the airplane mode status */ 373 { KE_KEY, UNIWILL_OSD_RFKILL, { KEY_RFKILL }}, 374 { KE_IGNORE, UNIWILL_OSD_RADIOON, { KEY_UNKNOWN }}, 375 { KE_IGNORE, UNIWILL_OSD_RADIOOFF, { KEY_UNKNOWN }}, 376 377 /* Reported when user wants to cycle the platform profile */ 378 { KE_KEY, UNIWILL_OSD_PERFORMANCE_MODE_TOGGLE, { KEY_F14 }}, 379 380 /* Reported when the user wants to adjust the brightness of the keyboard */ 381 { KE_KEY, UNIWILL_OSD_KBDILLUMDOWN, { KEY_KBDILLUMDOWN }}, 382 { KE_KEY, UNIWILL_OSD_KBDILLUMUP, { KEY_KBDILLUMUP }}, 383 384 /* Reported when the user wants to toggle the microphone mute status */ 385 { KE_KEY, UNIWILL_OSD_MIC_MUTE, { KEY_MICMUTE }}, 386 387 /* Reported when the user wants to toggle the mute status */ 388 { KE_IGNORE, UNIWILL_OSD_MUTE, { KEY_MUTE }}, 389 390 /* Reported when the user locks/unlocks the Fn key */ 391 { KE_IGNORE, UNIWILL_OSD_FN_LOCK, { KEY_FN_ESC }}, 392 393 /* Reported when the user wants to toggle the brightness of the keyboard */ 394 { KE_KEY, UNIWILL_OSD_KBDILLUMTOGGLE, { KEY_KBDILLUMTOGGLE }}, 395 { KE_KEY, UNIWILL_OSD_KB_LED_LEVEL0, { KEY_KBDILLUMTOGGLE }}, 396 { KE_KEY, UNIWILL_OSD_KB_LED_LEVEL1, { KEY_KBDILLUMTOGGLE }}, 397 { KE_KEY, UNIWILL_OSD_KB_LED_LEVEL2, { KEY_KBDILLUMTOGGLE }}, 398 { KE_KEY, UNIWILL_OSD_KB_LED_LEVEL3, { KEY_KBDILLUMTOGGLE }}, 399 { KE_KEY, UNIWILL_OSD_KB_LED_LEVEL4, { KEY_KBDILLUMTOGGLE }}, 400 401 /* FIXME: find out the exact meaning of those events */ 402 { KE_IGNORE, UNIWILL_OSD_BAT_CHARGE_FULL_24_H, { KEY_UNKNOWN }}, 403 { KE_IGNORE, UNIWILL_OSD_BAT_ERM_UPDATE, { KEY_UNKNOWN }}, 404 405 /* Reported when the user wants to toggle the benchmark mode status */ 406 { KE_IGNORE, UNIWILL_OSD_BENCHMARK_MODE_TOGGLE, { KEY_UNKNOWN }}, 407 408 /* Reported when the user wants to toggle the webcam */ 409 { KE_IGNORE, UNIWILL_OSD_WEBCAM_TOGGLE, { KEY_UNKNOWN }}, 410 411 { KE_END } 412 }; 413 414 static int uniwill_ec_reg_write(void *context, unsigned int reg, unsigned int val) 415 { 416 union acpi_object params[2] = { 417 { 418 .integer = { 419 .type = ACPI_TYPE_INTEGER, 420 .value = reg, 421 }, 422 }, 423 { 424 .integer = { 425 .type = ACPI_TYPE_INTEGER, 426 .value = val, 427 }, 428 }, 429 }; 430 struct uniwill_data *data = context; 431 struct acpi_object_list input = { 432 .count = ARRAY_SIZE(params), 433 .pointer = params, 434 }; 435 acpi_status status; 436 437 status = acpi_evaluate_object(data->handle, "ECRW", &input, NULL); 438 if (ACPI_FAILURE(status)) 439 return -EIO; 440 441 usleep_range(UNIWILL_EC_DELAY_US, UNIWILL_EC_DELAY_US * 2); 442 443 return 0; 444 } 445 446 static int uniwill_ec_reg_read(void *context, unsigned int reg, unsigned int *val) 447 { 448 union acpi_object params[1] = { 449 { 450 .integer = { 451 .type = ACPI_TYPE_INTEGER, 452 .value = reg, 453 }, 454 }, 455 }; 456 struct uniwill_data *data = context; 457 struct acpi_object_list input = { 458 .count = ARRAY_SIZE(params), 459 .pointer = params, 460 }; 461 unsigned long long output; 462 acpi_status status; 463 464 status = acpi_evaluate_integer(data->handle, "ECRR", &input, &output); 465 if (ACPI_FAILURE(status)) 466 return -EIO; 467 468 if (output > U8_MAX) 469 return -ENXIO; 470 471 usleep_range(UNIWILL_EC_DELAY_US, UNIWILL_EC_DELAY_US * 2); 472 473 *val = output; 474 475 return 0; 476 } 477 478 static const struct regmap_bus uniwill_ec_bus = { 479 .reg_write = uniwill_ec_reg_write, 480 .reg_read = uniwill_ec_reg_read, 481 .reg_format_endian_default = REGMAP_ENDIAN_LITTLE, 482 .val_format_endian_default = REGMAP_ENDIAN_LITTLE, 483 }; 484 485 static bool uniwill_writeable_reg(struct device *dev, unsigned int reg) 486 { 487 switch (reg) { 488 case EC_ADDR_AP_OEM: 489 case EC_ADDR_LIGHTBAR_AC_CTRL: 490 case EC_ADDR_LIGHTBAR_AC_RED: 491 case EC_ADDR_LIGHTBAR_AC_GREEN: 492 case EC_ADDR_LIGHTBAR_AC_BLUE: 493 case EC_ADDR_BIOS_OEM: 494 case EC_ADDR_TRIGGER: 495 case EC_ADDR_OEM_4: 496 case EC_ADDR_CHARGE_CTRL: 497 case EC_ADDR_LIGHTBAR_BAT_CTRL: 498 case EC_ADDR_LIGHTBAR_BAT_RED: 499 case EC_ADDR_LIGHTBAR_BAT_GREEN: 500 case EC_ADDR_LIGHTBAR_BAT_BLUE: 501 return true; 502 default: 503 return false; 504 } 505 } 506 507 static bool uniwill_readable_reg(struct device *dev, unsigned int reg) 508 { 509 switch (reg) { 510 case EC_ADDR_CPU_TEMP: 511 case EC_ADDR_GPU_TEMP: 512 case EC_ADDR_MAIN_FAN_RPM_1: 513 case EC_ADDR_MAIN_FAN_RPM_2: 514 case EC_ADDR_SECOND_FAN_RPM_1: 515 case EC_ADDR_SECOND_FAN_RPM_2: 516 case EC_ADDR_BAT_ALERT: 517 case EC_ADDR_PROJECT_ID: 518 case EC_ADDR_AP_OEM: 519 case EC_ADDR_LIGHTBAR_AC_CTRL: 520 case EC_ADDR_LIGHTBAR_AC_RED: 521 case EC_ADDR_LIGHTBAR_AC_GREEN: 522 case EC_ADDR_LIGHTBAR_AC_BLUE: 523 case EC_ADDR_BIOS_OEM: 524 case EC_ADDR_PWM_1: 525 case EC_ADDR_PWM_2: 526 case EC_ADDR_TRIGGER: 527 case EC_ADDR_SWITCH_STATUS: 528 case EC_ADDR_OEM_4: 529 case EC_ADDR_CHARGE_CTRL: 530 case EC_ADDR_LIGHTBAR_BAT_CTRL: 531 case EC_ADDR_LIGHTBAR_BAT_RED: 532 case EC_ADDR_LIGHTBAR_BAT_GREEN: 533 case EC_ADDR_LIGHTBAR_BAT_BLUE: 534 return true; 535 default: 536 return false; 537 } 538 } 539 540 static bool uniwill_volatile_reg(struct device *dev, unsigned int reg) 541 { 542 switch (reg) { 543 case EC_ADDR_CPU_TEMP: 544 case EC_ADDR_GPU_TEMP: 545 case EC_ADDR_MAIN_FAN_RPM_1: 546 case EC_ADDR_MAIN_FAN_RPM_2: 547 case EC_ADDR_SECOND_FAN_RPM_1: 548 case EC_ADDR_SECOND_FAN_RPM_2: 549 case EC_ADDR_BAT_ALERT: 550 case EC_ADDR_PWM_1: 551 case EC_ADDR_PWM_2: 552 case EC_ADDR_TRIGGER: 553 case EC_ADDR_SWITCH_STATUS: 554 case EC_ADDR_CHARGE_CTRL: 555 return true; 556 default: 557 return false; 558 } 559 } 560 561 static const struct regmap_config uniwill_ec_config = { 562 .reg_bits = 16, 563 .val_bits = 8, 564 .writeable_reg = uniwill_writeable_reg, 565 .readable_reg = uniwill_readable_reg, 566 .volatile_reg = uniwill_volatile_reg, 567 .can_sleep = true, 568 .max_register = 0xFFF, 569 .cache_type = REGCACHE_MAPLE, 570 .use_single_read = true, 571 .use_single_write = true, 572 }; 573 574 static ssize_t fn_lock_toggle_enable_store(struct device *dev, struct device_attribute *attr, 575 const char *buf, size_t count) 576 { 577 struct uniwill_data *data = dev_get_drvdata(dev); 578 unsigned int value; 579 bool enable; 580 int ret; 581 582 ret = kstrtobool(buf, &enable); 583 if (ret < 0) 584 return ret; 585 586 if (enable) 587 value = FN_LOCK_STATUS; 588 else 589 value = 0; 590 591 ret = regmap_update_bits(data->regmap, EC_ADDR_BIOS_OEM, FN_LOCK_STATUS, value); 592 if (ret < 0) 593 return ret; 594 595 return count; 596 } 597 598 static ssize_t fn_lock_toggle_enable_show(struct device *dev, struct device_attribute *attr, 599 char *buf) 600 { 601 struct uniwill_data *data = dev_get_drvdata(dev); 602 unsigned int value; 603 int ret; 604 605 ret = regmap_read(data->regmap, EC_ADDR_BIOS_OEM, &value); 606 if (ret < 0) 607 return ret; 608 609 return sysfs_emit(buf, "%d\n", !!(value & FN_LOCK_STATUS)); 610 } 611 612 static DEVICE_ATTR_RW(fn_lock_toggle_enable); 613 614 static ssize_t super_key_toggle_enable_store(struct device *dev, struct device_attribute *attr, 615 const char *buf, size_t count) 616 { 617 struct uniwill_data *data = dev_get_drvdata(dev); 618 unsigned int value; 619 bool enable; 620 int ret; 621 622 ret = kstrtobool(buf, &enable); 623 if (ret < 0) 624 return ret; 625 626 guard(mutex)(&data->super_key_lock); 627 628 ret = regmap_read(data->regmap, EC_ADDR_SWITCH_STATUS, &value); 629 if (ret < 0) 630 return ret; 631 632 /* 633 * We can only toggle the super key lock, so we return early if the setting 634 * is already in the correct state. 635 */ 636 if (enable == !(value & SUPER_KEY_LOCK_STATUS)) 637 return count; 638 639 ret = regmap_write_bits(data->regmap, EC_ADDR_TRIGGER, TRIGGER_SUPER_KEY_LOCK, 640 TRIGGER_SUPER_KEY_LOCK); 641 if (ret < 0) 642 return ret; 643 644 return count; 645 } 646 647 static ssize_t super_key_toggle_enable_show(struct device *dev, struct device_attribute *attr, 648 char *buf) 649 { 650 struct uniwill_data *data = dev_get_drvdata(dev); 651 unsigned int value; 652 int ret; 653 654 ret = regmap_read(data->regmap, EC_ADDR_SWITCH_STATUS, &value); 655 if (ret < 0) 656 return ret; 657 658 return sysfs_emit(buf, "%d\n", !(value & SUPER_KEY_LOCK_STATUS)); 659 } 660 661 static DEVICE_ATTR_RW(super_key_toggle_enable); 662 663 static ssize_t touchpad_toggle_enable_store(struct device *dev, struct device_attribute *attr, 664 const char *buf, size_t count) 665 { 666 struct uniwill_data *data = dev_get_drvdata(dev); 667 unsigned int value; 668 bool enable; 669 int ret; 670 671 ret = kstrtobool(buf, &enable); 672 if (ret < 0) 673 return ret; 674 675 if (enable) 676 value = 0; 677 else 678 value = TOUCHPAD_TOGGLE_OFF; 679 680 ret = regmap_update_bits(data->regmap, EC_ADDR_OEM_4, TOUCHPAD_TOGGLE_OFF, value); 681 if (ret < 0) 682 return ret; 683 684 return count; 685 } 686 687 static ssize_t touchpad_toggle_enable_show(struct device *dev, struct device_attribute *attr, 688 char *buf) 689 { 690 struct uniwill_data *data = dev_get_drvdata(dev); 691 unsigned int value; 692 int ret; 693 694 ret = regmap_read(data->regmap, EC_ADDR_OEM_4, &value); 695 if (ret < 0) 696 return ret; 697 698 return sysfs_emit(buf, "%d\n", !(value & TOUCHPAD_TOGGLE_OFF)); 699 } 700 701 static DEVICE_ATTR_RW(touchpad_toggle_enable); 702 703 static ssize_t rainbow_animation_store(struct device *dev, struct device_attribute *attr, 704 const char *buf, size_t count) 705 { 706 struct uniwill_data *data = dev_get_drvdata(dev); 707 unsigned int value; 708 bool enable; 709 int ret; 710 711 ret = kstrtobool(buf, &enable); 712 if (ret < 0) 713 return ret; 714 715 if (enable) 716 value = LIGHTBAR_WELCOME; 717 else 718 value = 0; 719 720 guard(mutex)(&data->led_lock); 721 722 ret = regmap_update_bits(data->regmap, EC_ADDR_LIGHTBAR_AC_CTRL, LIGHTBAR_WELCOME, value); 723 if (ret < 0) 724 return ret; 725 726 ret = regmap_update_bits(data->regmap, EC_ADDR_LIGHTBAR_BAT_CTRL, LIGHTBAR_WELCOME, value); 727 if (ret < 0) 728 return ret; 729 730 return count; 731 } 732 733 static ssize_t rainbow_animation_show(struct device *dev, struct device_attribute *attr, char *buf) 734 { 735 struct uniwill_data *data = dev_get_drvdata(dev); 736 unsigned int value; 737 int ret; 738 739 ret = regmap_read(data->regmap, EC_ADDR_LIGHTBAR_AC_CTRL, &value); 740 if (ret < 0) 741 return ret; 742 743 return sysfs_emit(buf, "%d\n", !!(value & LIGHTBAR_WELCOME)); 744 } 745 746 static DEVICE_ATTR_RW(rainbow_animation); 747 748 static ssize_t breathing_in_suspend_store(struct device *dev, struct device_attribute *attr, 749 const char *buf, size_t count) 750 { 751 struct uniwill_data *data = dev_get_drvdata(dev); 752 unsigned int value; 753 bool enable; 754 int ret; 755 756 ret = kstrtobool(buf, &enable); 757 if (ret < 0) 758 return ret; 759 760 if (enable) 761 value = 0; 762 else 763 value = LIGHTBAR_S3_OFF; 764 765 /* We only access a single register here, so we do not need to use data->led_lock */ 766 ret = regmap_update_bits(data->regmap, EC_ADDR_LIGHTBAR_AC_CTRL, LIGHTBAR_S3_OFF, value); 767 if (ret < 0) 768 return ret; 769 770 return count; 771 } 772 773 static ssize_t breathing_in_suspend_show(struct device *dev, struct device_attribute *attr, 774 char *buf) 775 { 776 struct uniwill_data *data = dev_get_drvdata(dev); 777 unsigned int value; 778 int ret; 779 780 ret = regmap_read(data->regmap, EC_ADDR_LIGHTBAR_AC_CTRL, &value); 781 if (ret < 0) 782 return ret; 783 784 return sysfs_emit(buf, "%d\n", !(value & LIGHTBAR_S3_OFF)); 785 } 786 787 static DEVICE_ATTR_RW(breathing_in_suspend); 788 789 static struct attribute *uniwill_attrs[] = { 790 /* Keyboard-related */ 791 &dev_attr_fn_lock_toggle_enable.attr, 792 &dev_attr_super_key_toggle_enable.attr, 793 &dev_attr_touchpad_toggle_enable.attr, 794 /* Lightbar-related */ 795 &dev_attr_rainbow_animation.attr, 796 &dev_attr_breathing_in_suspend.attr, 797 NULL 798 }; 799 800 static umode_t uniwill_attr_is_visible(struct kobject *kobj, struct attribute *attr, int n) 801 { 802 if (attr == &dev_attr_fn_lock_toggle_enable.attr) { 803 if (supported_features & UNIWILL_FEATURE_FN_LOCK_TOGGLE) 804 return attr->mode; 805 } 806 807 if (attr == &dev_attr_super_key_toggle_enable.attr) { 808 if (supported_features & UNIWILL_FEATURE_SUPER_KEY_TOGGLE) 809 return attr->mode; 810 } 811 812 if (attr == &dev_attr_touchpad_toggle_enable.attr) { 813 if (supported_features & UNIWILL_FEATURE_TOUCHPAD_TOGGLE) 814 return attr->mode; 815 } 816 817 if (attr == &dev_attr_rainbow_animation.attr || 818 attr == &dev_attr_breathing_in_suspend.attr) { 819 if (supported_features & UNIWILL_FEATURE_LIGHTBAR) 820 return attr->mode; 821 } 822 823 return 0; 824 } 825 826 static const struct attribute_group uniwill_group = { 827 .is_visible = uniwill_attr_is_visible, 828 .attrs = uniwill_attrs, 829 }; 830 831 static const struct attribute_group *uniwill_groups[] = { 832 &uniwill_group, 833 NULL 834 }; 835 836 static int uniwill_read(struct device *dev, enum hwmon_sensor_types type, u32 attr, int channel, 837 long *val) 838 { 839 struct uniwill_data *data = dev_get_drvdata(dev); 840 unsigned int value; 841 __be16 rpm; 842 int ret; 843 844 switch (type) { 845 case hwmon_temp: 846 switch (channel) { 847 case 0: 848 ret = regmap_read(data->regmap, EC_ADDR_CPU_TEMP, &value); 849 break; 850 case 1: 851 ret = regmap_read(data->regmap, EC_ADDR_GPU_TEMP, &value); 852 break; 853 default: 854 return -EOPNOTSUPP; 855 } 856 857 if (ret < 0) 858 return ret; 859 860 *val = value * MILLIDEGREE_PER_DEGREE; 861 return 0; 862 case hwmon_fan: 863 switch (channel) { 864 case 0: 865 ret = regmap_bulk_read(data->regmap, EC_ADDR_MAIN_FAN_RPM_1, &rpm, 866 sizeof(rpm)); 867 break; 868 case 1: 869 ret = regmap_bulk_read(data->regmap, EC_ADDR_SECOND_FAN_RPM_1, &rpm, 870 sizeof(rpm)); 871 break; 872 default: 873 return -EOPNOTSUPP; 874 } 875 876 if (ret < 0) 877 return ret; 878 879 *val = be16_to_cpu(rpm); 880 return 0; 881 case hwmon_pwm: 882 switch (channel) { 883 case 0: 884 ret = regmap_read(data->regmap, EC_ADDR_PWM_1, &value); 885 break; 886 case 1: 887 ret = regmap_read(data->regmap, EC_ADDR_PWM_2, &value); 888 break; 889 default: 890 return -EOPNOTSUPP; 891 } 892 893 if (ret < 0) 894 return ret; 895 896 *val = fixp_linear_interpolate(0, 0, PWM_MAX, U8_MAX, value); 897 return 0; 898 default: 899 return -EOPNOTSUPP; 900 } 901 } 902 903 static int uniwill_read_string(struct device *dev, enum hwmon_sensor_types type, u32 attr, 904 int channel, const char **str) 905 { 906 switch (type) { 907 case hwmon_temp: 908 *str = uniwill_temp_labels[channel]; 909 return 0; 910 case hwmon_fan: 911 *str = uniwill_fan_labels[channel]; 912 return 0; 913 default: 914 return -EOPNOTSUPP; 915 } 916 } 917 918 static const struct hwmon_ops uniwill_ops = { 919 .visible = 0444, 920 .read = uniwill_read, 921 .read_string = uniwill_read_string, 922 }; 923 924 static const struct hwmon_channel_info * const uniwill_info[] = { 925 HWMON_CHANNEL_INFO(chip, HWMON_C_REGISTER_TZ), 926 HWMON_CHANNEL_INFO(temp, 927 HWMON_T_INPUT | HWMON_T_LABEL, 928 HWMON_T_INPUT | HWMON_T_LABEL), 929 HWMON_CHANNEL_INFO(fan, 930 HWMON_F_INPUT | HWMON_F_LABEL, 931 HWMON_F_INPUT | HWMON_F_LABEL), 932 HWMON_CHANNEL_INFO(pwm, 933 HWMON_PWM_INPUT, 934 HWMON_PWM_INPUT), 935 NULL 936 }; 937 938 static const struct hwmon_chip_info uniwill_chip_info = { 939 .ops = &uniwill_ops, 940 .info = uniwill_info, 941 }; 942 943 static int uniwill_hwmon_init(struct uniwill_data *data) 944 { 945 struct device *hdev; 946 947 if (!(supported_features & UNIWILL_FEATURE_HWMON)) 948 return 0; 949 950 hdev = devm_hwmon_device_register_with_info(data->dev, "uniwill", data, 951 &uniwill_chip_info, NULL); 952 953 return PTR_ERR_OR_ZERO(hdev); 954 } 955 956 static const unsigned int uniwill_led_channel_to_bat_reg[LED_CHANNELS] = { 957 EC_ADDR_LIGHTBAR_BAT_RED, 958 EC_ADDR_LIGHTBAR_BAT_GREEN, 959 EC_ADDR_LIGHTBAR_BAT_BLUE, 960 }; 961 962 static const unsigned int uniwill_led_channel_to_ac_reg[LED_CHANNELS] = { 963 EC_ADDR_LIGHTBAR_AC_RED, 964 EC_ADDR_LIGHTBAR_AC_GREEN, 965 EC_ADDR_LIGHTBAR_AC_BLUE, 966 }; 967 968 static int uniwill_led_brightness_set(struct led_classdev *led_cdev, enum led_brightness brightness) 969 { 970 struct led_classdev_mc *led_mc_cdev = lcdev_to_mccdev(led_cdev); 971 struct uniwill_data *data = container_of(led_mc_cdev, struct uniwill_data, led_mc_cdev); 972 unsigned int value; 973 int ret; 974 975 ret = led_mc_calc_color_components(led_mc_cdev, brightness); 976 if (ret < 0) 977 return ret; 978 979 guard(mutex)(&data->led_lock); 980 981 for (int i = 0; i < LED_CHANNELS; i++) { 982 /* Prevent the brightness values from overflowing */ 983 value = min(LED_MAX_BRIGHTNESS, data->led_mc_subled_info[i].brightness); 984 ret = regmap_write(data->regmap, uniwill_led_channel_to_ac_reg[i], value); 985 if (ret < 0) 986 return ret; 987 988 ret = regmap_write(data->regmap, uniwill_led_channel_to_bat_reg[i], value); 989 if (ret < 0) 990 return ret; 991 } 992 993 if (brightness) 994 value = 0; 995 else 996 value = LIGHTBAR_S0_OFF; 997 998 ret = regmap_update_bits(data->regmap, EC_ADDR_LIGHTBAR_AC_CTRL, LIGHTBAR_S0_OFF, value); 999 if (ret < 0) 1000 return ret; 1001 1002 return regmap_update_bits(data->regmap, EC_ADDR_LIGHTBAR_BAT_CTRL, LIGHTBAR_S0_OFF, value); 1003 } 1004 1005 #define LIGHTBAR_MASK (LIGHTBAR_APP_EXISTS | LIGHTBAR_S0_OFF | LIGHTBAR_S3_OFF | LIGHTBAR_WELCOME) 1006 1007 static int uniwill_led_init(struct uniwill_data *data) 1008 { 1009 struct led_init_data init_data = { 1010 .devicename = DRIVER_NAME, 1011 .default_label = "multicolor:" LED_FUNCTION_STATUS, 1012 .devname_mandatory = true, 1013 }; 1014 unsigned int color_indices[3] = { 1015 LED_COLOR_ID_RED, 1016 LED_COLOR_ID_GREEN, 1017 LED_COLOR_ID_BLUE, 1018 }; 1019 unsigned int value; 1020 int ret; 1021 1022 if (!(supported_features & UNIWILL_FEATURE_LIGHTBAR)) 1023 return 0; 1024 1025 ret = devm_mutex_init(data->dev, &data->led_lock); 1026 if (ret < 0) 1027 return ret; 1028 1029 /* 1030 * The EC has separate lightbar settings for AC and battery mode, 1031 * so we have to ensure that both settings are the same. 1032 */ 1033 ret = regmap_read(data->regmap, EC_ADDR_LIGHTBAR_AC_CTRL, &value); 1034 if (ret < 0) 1035 return ret; 1036 1037 value |= LIGHTBAR_APP_EXISTS; 1038 ret = regmap_write(data->regmap, EC_ADDR_LIGHTBAR_AC_CTRL, value); 1039 if (ret < 0) 1040 return ret; 1041 1042 /* 1043 * The breathing animation during suspend is not supported when 1044 * running on battery power. 1045 */ 1046 value |= LIGHTBAR_S3_OFF; 1047 ret = regmap_update_bits(data->regmap, EC_ADDR_LIGHTBAR_BAT_CTRL, LIGHTBAR_MASK, value); 1048 if (ret < 0) 1049 return ret; 1050 1051 data->led_mc_cdev.led_cdev.color = LED_COLOR_ID_MULTI; 1052 data->led_mc_cdev.led_cdev.max_brightness = LED_MAX_BRIGHTNESS; 1053 data->led_mc_cdev.led_cdev.flags = LED_REJECT_NAME_CONFLICT; 1054 data->led_mc_cdev.led_cdev.brightness_set_blocking = uniwill_led_brightness_set; 1055 1056 if (value & LIGHTBAR_S0_OFF) 1057 data->led_mc_cdev.led_cdev.brightness = 0; 1058 else 1059 data->led_mc_cdev.led_cdev.brightness = LED_MAX_BRIGHTNESS; 1060 1061 for (int i = 0; i < LED_CHANNELS; i++) { 1062 data->led_mc_subled_info[i].color_index = color_indices[i]; 1063 1064 ret = regmap_read(data->regmap, uniwill_led_channel_to_ac_reg[i], &value); 1065 if (ret < 0) 1066 return ret; 1067 1068 /* 1069 * Make sure that the initial intensity value is not greater than 1070 * the maximum brightness. 1071 */ 1072 value = min(LED_MAX_BRIGHTNESS, value); 1073 ret = regmap_write(data->regmap, uniwill_led_channel_to_ac_reg[i], value); 1074 if (ret < 0) 1075 return ret; 1076 1077 ret = regmap_write(data->regmap, uniwill_led_channel_to_bat_reg[i], value); 1078 if (ret < 0) 1079 return ret; 1080 1081 data->led_mc_subled_info[i].intensity = value; 1082 data->led_mc_subled_info[i].channel = i; 1083 } 1084 1085 data->led_mc_cdev.subled_info = data->led_mc_subled_info; 1086 data->led_mc_cdev.num_colors = LED_CHANNELS; 1087 1088 return devm_led_classdev_multicolor_register_ext(data->dev, &data->led_mc_cdev, 1089 &init_data); 1090 } 1091 1092 static int uniwill_get_property(struct power_supply *psy, const struct power_supply_ext *ext, 1093 void *drvdata, enum power_supply_property psp, 1094 union power_supply_propval *val) 1095 { 1096 struct uniwill_data *data = drvdata; 1097 union power_supply_propval prop; 1098 unsigned int regval; 1099 int ret; 1100 1101 switch (psp) { 1102 case POWER_SUPPLY_PROP_HEALTH: 1103 ret = power_supply_get_property_direct(psy, POWER_SUPPLY_PROP_PRESENT, &prop); 1104 if (ret < 0) 1105 return ret; 1106 1107 if (!prop.intval) { 1108 val->intval = POWER_SUPPLY_HEALTH_NO_BATTERY; 1109 return 0; 1110 } 1111 1112 ret = power_supply_get_property_direct(psy, POWER_SUPPLY_PROP_STATUS, &prop); 1113 if (ret < 0) 1114 return ret; 1115 1116 if (prop.intval == POWER_SUPPLY_STATUS_UNKNOWN) { 1117 val->intval = POWER_SUPPLY_HEALTH_UNKNOWN; 1118 return 0; 1119 } 1120 1121 ret = regmap_read(data->regmap, EC_ADDR_BAT_ALERT, ®val); 1122 if (ret < 0) 1123 return ret; 1124 1125 if (regval) { 1126 /* Charging issue */ 1127 val->intval = POWER_SUPPLY_HEALTH_UNSPEC_FAILURE; 1128 return 0; 1129 } 1130 1131 val->intval = POWER_SUPPLY_HEALTH_GOOD; 1132 return 0; 1133 case POWER_SUPPLY_PROP_CHARGE_CONTROL_END_THRESHOLD: 1134 ret = regmap_read(data->regmap, EC_ADDR_CHARGE_CTRL, ®val); 1135 if (ret < 0) 1136 return ret; 1137 1138 val->intval = clamp_val(FIELD_GET(CHARGE_CTRL_MASK, regval), 0, 100); 1139 return 0; 1140 default: 1141 return -EINVAL; 1142 } 1143 } 1144 1145 static int uniwill_set_property(struct power_supply *psy, const struct power_supply_ext *ext, 1146 void *drvdata, enum power_supply_property psp, 1147 const union power_supply_propval *val) 1148 { 1149 struct uniwill_data *data = drvdata; 1150 1151 switch (psp) { 1152 case POWER_SUPPLY_PROP_CHARGE_CONTROL_END_THRESHOLD: 1153 if (val->intval < 1 || val->intval > 100) 1154 return -EINVAL; 1155 1156 return regmap_update_bits(data->regmap, EC_ADDR_CHARGE_CTRL, CHARGE_CTRL_MASK, 1157 val->intval); 1158 default: 1159 return -EINVAL; 1160 } 1161 } 1162 1163 static int uniwill_property_is_writeable(struct power_supply *psy, 1164 const struct power_supply_ext *ext, void *drvdata, 1165 enum power_supply_property psp) 1166 { 1167 if (psp == POWER_SUPPLY_PROP_CHARGE_CONTROL_END_THRESHOLD) 1168 return true; 1169 1170 return false; 1171 } 1172 1173 static const enum power_supply_property uniwill_properties[] = { 1174 POWER_SUPPLY_PROP_HEALTH, 1175 POWER_SUPPLY_PROP_CHARGE_CONTROL_END_THRESHOLD, 1176 }; 1177 1178 static const struct power_supply_ext uniwill_extension = { 1179 .name = DRIVER_NAME, 1180 .properties = uniwill_properties, 1181 .num_properties = ARRAY_SIZE(uniwill_properties), 1182 .get_property = uniwill_get_property, 1183 .set_property = uniwill_set_property, 1184 .property_is_writeable = uniwill_property_is_writeable, 1185 }; 1186 1187 static int uniwill_add_battery(struct power_supply *battery, struct acpi_battery_hook *hook) 1188 { 1189 struct uniwill_data *data = container_of(hook, struct uniwill_data, hook); 1190 struct uniwill_battery_entry *entry; 1191 int ret; 1192 1193 entry = kzalloc(sizeof(*entry), GFP_KERNEL); 1194 if (!entry) 1195 return -ENOMEM; 1196 1197 ret = power_supply_register_extension(battery, &uniwill_extension, data->dev, data); 1198 if (ret < 0) { 1199 kfree(entry); 1200 return ret; 1201 } 1202 1203 guard(mutex)(&data->battery_lock); 1204 1205 entry->battery = battery; 1206 list_add(&entry->head, &data->batteries); 1207 1208 return 0; 1209 } 1210 1211 static int uniwill_remove_battery(struct power_supply *battery, struct acpi_battery_hook *hook) 1212 { 1213 struct uniwill_data *data = container_of(hook, struct uniwill_data, hook); 1214 struct uniwill_battery_entry *entry, *tmp; 1215 1216 scoped_guard(mutex, &data->battery_lock) { 1217 list_for_each_entry_safe(entry, tmp, &data->batteries, head) { 1218 if (entry->battery == battery) { 1219 list_del(&entry->head); 1220 kfree(entry); 1221 break; 1222 } 1223 } 1224 } 1225 1226 power_supply_unregister_extension(battery, &uniwill_extension); 1227 1228 return 0; 1229 } 1230 1231 static int uniwill_battery_init(struct uniwill_data *data) 1232 { 1233 int ret; 1234 1235 if (!(supported_features & UNIWILL_FEATURE_BATTERY)) 1236 return 0; 1237 1238 ret = devm_mutex_init(data->dev, &data->battery_lock); 1239 if (ret < 0) 1240 return ret; 1241 1242 INIT_LIST_HEAD(&data->batteries); 1243 data->hook.name = "Uniwill Battery Extension"; 1244 data->hook.add_battery = uniwill_add_battery; 1245 data->hook.remove_battery = uniwill_remove_battery; 1246 1247 return devm_battery_hook_register(data->dev, &data->hook); 1248 } 1249 1250 static int uniwill_notifier_call(struct notifier_block *nb, unsigned long action, void *dummy) 1251 { 1252 struct uniwill_data *data = container_of(nb, struct uniwill_data, nb); 1253 struct uniwill_battery_entry *entry; 1254 1255 switch (action) { 1256 case UNIWILL_OSD_BATTERY_ALERT: 1257 mutex_lock(&data->battery_lock); 1258 list_for_each_entry(entry, &data->batteries, head) { 1259 power_supply_changed(entry->battery); 1260 } 1261 mutex_unlock(&data->battery_lock); 1262 1263 return NOTIFY_OK; 1264 case UNIWILL_OSD_DC_ADAPTER_CHANGED: 1265 /* noop for the time being, will change once charging priority 1266 * gets implemented. 1267 */ 1268 1269 return NOTIFY_OK; 1270 default: 1271 mutex_lock(&data->input_lock); 1272 sparse_keymap_report_event(data->input_device, action, 1, true); 1273 mutex_unlock(&data->input_lock); 1274 1275 return NOTIFY_OK; 1276 } 1277 } 1278 1279 static int uniwill_input_init(struct uniwill_data *data) 1280 { 1281 int ret; 1282 1283 ret = devm_mutex_init(data->dev, &data->input_lock); 1284 if (ret < 0) 1285 return ret; 1286 1287 data->input_device = devm_input_allocate_device(data->dev); 1288 if (!data->input_device) 1289 return -ENOMEM; 1290 1291 ret = sparse_keymap_setup(data->input_device, uniwill_keymap, NULL); 1292 if (ret < 0) 1293 return ret; 1294 1295 data->input_device->name = "Uniwill WMI hotkeys"; 1296 data->input_device->phys = "wmi/input0"; 1297 data->input_device->id.bustype = BUS_HOST; 1298 ret = input_register_device(data->input_device); 1299 if (ret < 0) 1300 return ret; 1301 1302 data->nb.notifier_call = uniwill_notifier_call; 1303 1304 return devm_uniwill_wmi_register_notifier(data->dev, &data->nb); 1305 } 1306 1307 static void uniwill_disable_manual_control(void *context) 1308 { 1309 struct uniwill_data *data = context; 1310 1311 regmap_clear_bits(data->regmap, EC_ADDR_AP_OEM, ENABLE_MANUAL_CTRL); 1312 } 1313 1314 static int uniwill_ec_init(struct uniwill_data *data) 1315 { 1316 unsigned int value; 1317 int ret; 1318 1319 ret = regmap_read(data->regmap, EC_ADDR_PROJECT_ID, &value); 1320 if (ret < 0) 1321 return ret; 1322 1323 dev_dbg(data->dev, "Project ID: %u\n", value); 1324 1325 ret = regmap_set_bits(data->regmap, EC_ADDR_AP_OEM, ENABLE_MANUAL_CTRL); 1326 if (ret < 0) 1327 return ret; 1328 1329 return devm_add_action_or_reset(data->dev, uniwill_disable_manual_control, data); 1330 } 1331 1332 static int uniwill_probe(struct platform_device *pdev) 1333 { 1334 struct uniwill_data *data; 1335 struct regmap *regmap; 1336 acpi_handle handle; 1337 int ret; 1338 1339 handle = ACPI_HANDLE(&pdev->dev); 1340 if (!handle) 1341 return -ENODEV; 1342 1343 data = devm_kzalloc(&pdev->dev, sizeof(*data), GFP_KERNEL); 1344 if (!data) 1345 return -ENOMEM; 1346 1347 data->dev = &pdev->dev; 1348 data->handle = handle; 1349 platform_set_drvdata(pdev, data); 1350 1351 regmap = devm_regmap_init(&pdev->dev, &uniwill_ec_bus, data, &uniwill_ec_config); 1352 if (IS_ERR(regmap)) 1353 return PTR_ERR(regmap); 1354 1355 data->regmap = regmap; 1356 ret = devm_mutex_init(&pdev->dev, &data->super_key_lock); 1357 if (ret < 0) 1358 return ret; 1359 1360 ret = uniwill_ec_init(data); 1361 if (ret < 0) 1362 return ret; 1363 1364 ret = uniwill_battery_init(data); 1365 if (ret < 0) 1366 return ret; 1367 1368 ret = uniwill_led_init(data); 1369 if (ret < 0) 1370 return ret; 1371 1372 ret = uniwill_hwmon_init(data); 1373 if (ret < 0) 1374 return ret; 1375 1376 return uniwill_input_init(data); 1377 } 1378 1379 static void uniwill_shutdown(struct platform_device *pdev) 1380 { 1381 struct uniwill_data *data = platform_get_drvdata(pdev); 1382 1383 regmap_clear_bits(data->regmap, EC_ADDR_AP_OEM, ENABLE_MANUAL_CTRL); 1384 } 1385 1386 static int uniwill_suspend_keyboard(struct uniwill_data *data) 1387 { 1388 if (!(supported_features & UNIWILL_FEATURE_SUPER_KEY_TOGGLE)) 1389 return 0; 1390 1391 /* 1392 * The EC_ADDR_SWITCH_STATUS is marked as volatile, so we have to restore it 1393 * ourselves. 1394 */ 1395 return regmap_read(data->regmap, EC_ADDR_SWITCH_STATUS, &data->last_switch_status); 1396 } 1397 1398 static int uniwill_suspend_battery(struct uniwill_data *data) 1399 { 1400 if (!(supported_features & UNIWILL_FEATURE_BATTERY)) 1401 return 0; 1402 1403 /* 1404 * Save the current charge limit in order to restore it during resume. 1405 * We cannot use the regmap code for that since this register needs to 1406 * be declared as volatile due to CHARGE_CTRL_REACHED. 1407 */ 1408 return regmap_read(data->regmap, EC_ADDR_CHARGE_CTRL, &data->last_charge_ctrl); 1409 } 1410 1411 static int uniwill_suspend(struct device *dev) 1412 { 1413 struct uniwill_data *data = dev_get_drvdata(dev); 1414 int ret; 1415 1416 ret = uniwill_suspend_keyboard(data); 1417 if (ret < 0) 1418 return ret; 1419 1420 ret = uniwill_suspend_battery(data); 1421 if (ret < 0) 1422 return ret; 1423 1424 regcache_cache_only(data->regmap, true); 1425 regcache_mark_dirty(data->regmap); 1426 1427 return 0; 1428 } 1429 1430 static int uniwill_resume_keyboard(struct uniwill_data *data) 1431 { 1432 unsigned int value; 1433 int ret; 1434 1435 if (!(supported_features & UNIWILL_FEATURE_SUPER_KEY_TOGGLE)) 1436 return 0; 1437 1438 ret = regmap_read(data->regmap, EC_ADDR_SWITCH_STATUS, &value); 1439 if (ret < 0) 1440 return ret; 1441 1442 if ((data->last_switch_status & SUPER_KEY_LOCK_STATUS) == (value & SUPER_KEY_LOCK_STATUS)) 1443 return 0; 1444 1445 return regmap_write_bits(data->regmap, EC_ADDR_TRIGGER, TRIGGER_SUPER_KEY_LOCK, 1446 TRIGGER_SUPER_KEY_LOCK); 1447 } 1448 1449 static int uniwill_resume_battery(struct uniwill_data *data) 1450 { 1451 if (!(supported_features & UNIWILL_FEATURE_BATTERY)) 1452 return 0; 1453 1454 return regmap_update_bits(data->regmap, EC_ADDR_CHARGE_CTRL, CHARGE_CTRL_MASK, 1455 data->last_charge_ctrl); 1456 } 1457 1458 static int uniwill_resume(struct device *dev) 1459 { 1460 struct uniwill_data *data = dev_get_drvdata(dev); 1461 int ret; 1462 1463 regcache_cache_only(data->regmap, false); 1464 1465 ret = regcache_sync(data->regmap); 1466 if (ret < 0) 1467 return ret; 1468 1469 ret = uniwill_resume_keyboard(data); 1470 if (ret < 0) 1471 return ret; 1472 1473 return uniwill_resume_battery(data); 1474 } 1475 1476 static DEFINE_SIMPLE_DEV_PM_OPS(uniwill_pm_ops, uniwill_suspend, uniwill_resume); 1477 1478 /* 1479 * We only use the DMI table for auoloading because the ACPI device itself 1480 * does not guarantee that the underlying EC implementation is supported. 1481 */ 1482 static const struct acpi_device_id uniwill_id_table[] = { 1483 { "INOU0000" }, 1484 { }, 1485 }; 1486 1487 static struct platform_driver uniwill_driver = { 1488 .driver = { 1489 .name = DRIVER_NAME, 1490 .dev_groups = uniwill_groups, 1491 .probe_type = PROBE_PREFER_ASYNCHRONOUS, 1492 .acpi_match_table = uniwill_id_table, 1493 .pm = pm_sleep_ptr(&uniwill_pm_ops), 1494 }, 1495 .probe = uniwill_probe, 1496 .shutdown = uniwill_shutdown, 1497 }; 1498 1499 static const struct dmi_system_id uniwill_dmi_table[] __initconst = { 1500 { 1501 .ident = "XMG FUSION 15", 1502 .matches = { 1503 DMI_MATCH(DMI_SYS_VENDOR, "SchenkerTechnologiesGmbH"), 1504 DMI_EXACT_MATCH(DMI_BOARD_NAME, "LAPQC71A"), 1505 }, 1506 }, 1507 { 1508 .ident = "XMG FUSION 15", 1509 .matches = { 1510 DMI_MATCH(DMI_SYS_VENDOR, "SchenkerTechnologiesGmbH"), 1511 DMI_EXACT_MATCH(DMI_BOARD_NAME, "LAPQC71B"), 1512 }, 1513 }, 1514 { 1515 .ident = "Intel NUC x15", 1516 .matches = { 1517 DMI_EXACT_MATCH(DMI_SYS_VENDOR, "Intel(R) Client Systems"), 1518 DMI_EXACT_MATCH(DMI_PRODUCT_NAME, "LAPAC71H"), 1519 }, 1520 .driver_data = (void *)(UNIWILL_FEATURE_FN_LOCK_TOGGLE | 1521 UNIWILL_FEATURE_SUPER_KEY_TOGGLE | 1522 UNIWILL_FEATURE_TOUCHPAD_TOGGLE | 1523 UNIWILL_FEATURE_BATTERY | 1524 UNIWILL_FEATURE_HWMON), 1525 }, 1526 { 1527 .ident = "Intel NUC x15", 1528 .matches = { 1529 DMI_EXACT_MATCH(DMI_SYS_VENDOR, "Intel(R) Client Systems"), 1530 DMI_EXACT_MATCH(DMI_PRODUCT_NAME, "LAPKC71F"), 1531 }, 1532 .driver_data = (void *)(UNIWILL_FEATURE_FN_LOCK_TOGGLE | 1533 UNIWILL_FEATURE_SUPER_KEY_TOGGLE | 1534 UNIWILL_FEATURE_TOUCHPAD_TOGGLE | 1535 UNIWILL_FEATURE_LIGHTBAR | 1536 UNIWILL_FEATURE_BATTERY | 1537 UNIWILL_FEATURE_HWMON), 1538 }, 1539 { 1540 .ident = "TUXEDO InfinityBook Pro 14 Gen6 Intel", 1541 .matches = { 1542 DMI_MATCH(DMI_SYS_VENDOR, "TUXEDO"), 1543 DMI_EXACT_MATCH(DMI_BOARD_NAME, "PHxTxX1"), 1544 }, 1545 }, 1546 { 1547 .ident = "TUXEDO InfinityBook Pro 14 Gen6 Intel", 1548 .matches = { 1549 DMI_MATCH(DMI_SYS_VENDOR, "TUXEDO"), 1550 DMI_EXACT_MATCH(DMI_BOARD_NAME, "PHxTQx1"), 1551 }, 1552 }, 1553 { 1554 .ident = "TUXEDO InfinityBook Pro 14/16 Gen7 Intel", 1555 .matches = { 1556 DMI_MATCH(DMI_SYS_VENDOR, "TUXEDO"), 1557 DMI_EXACT_MATCH(DMI_BOARD_NAME, "PHxARX1_PHxAQF1"), 1558 }, 1559 }, 1560 { 1561 .ident = "TUXEDO InfinityBook Pro 16 Gen7 Intel/Commodore Omnia-Book Pro Gen 7", 1562 .matches = { 1563 DMI_MATCH(DMI_SYS_VENDOR, "TUXEDO"), 1564 DMI_EXACT_MATCH(DMI_BOARD_NAME, "PH6AG01_PH6AQ71_PH6AQI1"), 1565 }, 1566 }, 1567 { 1568 .ident = "TUXEDO InfinityBook Pro 14/16 Gen8 Intel/Commodore Omnia-Book Pro Gen 8", 1569 .matches = { 1570 DMI_MATCH(DMI_SYS_VENDOR, "TUXEDO"), 1571 DMI_EXACT_MATCH(DMI_BOARD_NAME, "PH4PRX1_PH6PRX1"), 1572 }, 1573 }, 1574 { 1575 .ident = "TUXEDO InfinityBook Pro 14 Gen8 Intel/Commodore Omnia-Book Pro Gen 8", 1576 .matches = { 1577 DMI_MATCH(DMI_SYS_VENDOR, "TUXEDO"), 1578 DMI_EXACT_MATCH(DMI_BOARD_NAME, "PH4PG31"), 1579 }, 1580 }, 1581 { 1582 .ident = "TUXEDO InfinityBook Pro 16 Gen8 Intel", 1583 .matches = { 1584 DMI_MATCH(DMI_SYS_VENDOR, "TUXEDO"), 1585 DMI_EXACT_MATCH(DMI_BOARD_NAME, "PH6PG01_PH6PG71"), 1586 }, 1587 }, 1588 { 1589 .ident = "TUXEDO InfinityBook Pro 14/15 Gen9 AMD", 1590 .matches = { 1591 DMI_MATCH(DMI_SYS_VENDOR, "TUXEDO"), 1592 DMI_EXACT_MATCH(DMI_BOARD_NAME, "GXxHRXx"), 1593 }, 1594 }, 1595 { 1596 .ident = "TUXEDO InfinityBook Pro 14/15 Gen9 Intel/Commodore Omnia-Book 15 Gen9", 1597 .matches = { 1598 DMI_MATCH(DMI_SYS_VENDOR, "TUXEDO"), 1599 DMI_EXACT_MATCH(DMI_BOARD_NAME, "GXxMRXx"), 1600 }, 1601 }, 1602 { 1603 .ident = "TUXEDO InfinityBook Pro 14/15 Gen10 AMD", 1604 .matches = { 1605 DMI_MATCH(DMI_SYS_VENDOR, "TUXEDO"), 1606 DMI_EXACT_MATCH(DMI_BOARD_NAME, "XxHP4NAx"), 1607 }, 1608 }, 1609 { 1610 .ident = "TUXEDO InfinityBook Pro 14/15 Gen10 AMD", 1611 .matches = { 1612 DMI_MATCH(DMI_SYS_VENDOR, "TUXEDO"), 1613 DMI_EXACT_MATCH(DMI_BOARD_NAME, "XxKK4NAx_XxSP4NAx"), 1614 }, 1615 }, 1616 { 1617 .ident = "TUXEDO InfinityBook Pro 15 Gen10 Intel", 1618 .matches = { 1619 DMI_MATCH(DMI_SYS_VENDOR, "TUXEDO"), 1620 DMI_EXACT_MATCH(DMI_BOARD_NAME, "XxAR4NAx"), 1621 }, 1622 }, 1623 { 1624 .ident = "TUXEDO InfinityBook Max 15 Gen10 AMD", 1625 .matches = { 1626 DMI_MATCH(DMI_SYS_VENDOR, "TUXEDO"), 1627 DMI_EXACT_MATCH(DMI_BOARD_NAME, "X5KK45xS_X5SP45xS"), 1628 }, 1629 }, 1630 { 1631 .ident = "TUXEDO InfinityBook Max 16 Gen10 AMD", 1632 .matches = { 1633 DMI_MATCH(DMI_SYS_VENDOR, "TUXEDO"), 1634 DMI_EXACT_MATCH(DMI_BOARD_NAME, "X6HP45xU"), 1635 }, 1636 }, 1637 { 1638 .ident = "TUXEDO InfinityBook Max 16 Gen10 AMD", 1639 .matches = { 1640 DMI_MATCH(DMI_SYS_VENDOR, "TUXEDO"), 1641 DMI_EXACT_MATCH(DMI_BOARD_NAME, "X6KK45xU_X6SP45xU"), 1642 }, 1643 }, 1644 { 1645 .ident = "TUXEDO InfinityBook Max 15 Gen10 Intel", 1646 .matches = { 1647 DMI_MATCH(DMI_SYS_VENDOR, "TUXEDO"), 1648 DMI_EXACT_MATCH(DMI_BOARD_NAME, "X5AR45xS"), 1649 }, 1650 }, 1651 { 1652 .ident = "TUXEDO InfinityBook Max 16 Gen10 Intel", 1653 .matches = { 1654 DMI_MATCH(DMI_SYS_VENDOR, "TUXEDO"), 1655 DMI_EXACT_MATCH(DMI_BOARD_NAME, "X6AR55xU"), 1656 }, 1657 }, 1658 { 1659 .ident = "TUXEDO Polaris 15 Gen1 AMD", 1660 .matches = { 1661 DMI_MATCH(DMI_SYS_VENDOR, "TUXEDO"), 1662 DMI_EXACT_MATCH(DMI_BOARD_NAME, "POLARIS1501A1650TI"), 1663 }, 1664 }, 1665 { 1666 .ident = "TUXEDO Polaris 15 Gen1 AMD", 1667 .matches = { 1668 DMI_MATCH(DMI_SYS_VENDOR, "TUXEDO"), 1669 DMI_EXACT_MATCH(DMI_BOARD_NAME, "POLARIS1501A2060"), 1670 }, 1671 }, 1672 { 1673 .ident = "TUXEDO Polaris 17 Gen1 AMD", 1674 .matches = { 1675 DMI_MATCH(DMI_SYS_VENDOR, "TUXEDO"), 1676 DMI_EXACT_MATCH(DMI_BOARD_NAME, "POLARIS1701A1650TI"), 1677 }, 1678 }, 1679 { 1680 .ident = "TUXEDO Polaris 17 Gen1 AMD", 1681 .matches = { 1682 DMI_MATCH(DMI_SYS_VENDOR, "TUXEDO"), 1683 DMI_EXACT_MATCH(DMI_BOARD_NAME, "POLARIS1701A2060"), 1684 }, 1685 }, 1686 { 1687 .ident = "TUXEDO Polaris 15 Gen1 Intel", 1688 .matches = { 1689 DMI_MATCH(DMI_SYS_VENDOR, "TUXEDO"), 1690 DMI_EXACT_MATCH(DMI_BOARD_NAME, "POLARIS1501I1650TI"), 1691 }, 1692 }, 1693 { 1694 .ident = "TUXEDO Polaris 15 Gen1 Intel", 1695 .matches = { 1696 DMI_MATCH(DMI_SYS_VENDOR, "TUXEDO"), 1697 DMI_EXACT_MATCH(DMI_BOARD_NAME, "POLARIS1501I2060"), 1698 }, 1699 }, 1700 { 1701 .ident = "TUXEDO Polaris 17 Gen1 Intel", 1702 .matches = { 1703 DMI_MATCH(DMI_SYS_VENDOR, "TUXEDO"), 1704 DMI_EXACT_MATCH(DMI_BOARD_NAME, "POLARIS1701I1650TI"), 1705 }, 1706 }, 1707 { 1708 .ident = "TUXEDO Polaris 17 Gen1 Intel", 1709 .matches = { 1710 DMI_MATCH(DMI_SYS_VENDOR, "TUXEDO"), 1711 DMI_EXACT_MATCH(DMI_BOARD_NAME, "POLARIS1701I2060"), 1712 }, 1713 }, 1714 { 1715 .ident = "TUXEDO Trinity 15 Intel Gen1", 1716 .matches = { 1717 DMI_MATCH(DMI_SYS_VENDOR, "TUXEDO"), 1718 DMI_EXACT_MATCH(DMI_BOARD_NAME, "TRINITY1501I"), 1719 }, 1720 }, 1721 { 1722 .ident = "TUXEDO Trinity 17 Intel Gen1", 1723 .matches = { 1724 DMI_MATCH(DMI_SYS_VENDOR, "TUXEDO"), 1725 DMI_EXACT_MATCH(DMI_BOARD_NAME, "TRINITY1701I"), 1726 }, 1727 }, 1728 { 1729 .ident = "TUXEDO Polaris 15/17 Gen2 AMD", 1730 .matches = { 1731 DMI_MATCH(DMI_SYS_VENDOR, "TUXEDO"), 1732 DMI_EXACT_MATCH(DMI_BOARD_NAME, "GMxMGxx"), 1733 }, 1734 }, 1735 { 1736 .ident = "TUXEDO Polaris 15/17 Gen2 Intel", 1737 .matches = { 1738 DMI_MATCH(DMI_SYS_VENDOR, "TUXEDO"), 1739 DMI_EXACT_MATCH(DMI_BOARD_NAME, "GMxNGxx"), 1740 }, 1741 }, 1742 { 1743 .ident = "TUXEDO Stellaris/Polaris 15/17 Gen3 AMD", 1744 .matches = { 1745 DMI_MATCH(DMI_SYS_VENDOR, "TUXEDO"), 1746 DMI_EXACT_MATCH(DMI_BOARD_NAME, "GMxZGxx"), 1747 }, 1748 }, 1749 { 1750 .ident = "TUXEDO Stellaris/Polaris 15/17 Gen3 Intel", 1751 .matches = { 1752 DMI_MATCH(DMI_SYS_VENDOR, "TUXEDO"), 1753 DMI_EXACT_MATCH(DMI_BOARD_NAME, "GMxTGxx"), 1754 }, 1755 }, 1756 { 1757 .ident = "TUXEDO Stellaris/Polaris 15/17 Gen4 AMD", 1758 .matches = { 1759 DMI_MATCH(DMI_SYS_VENDOR, "TUXEDO"), 1760 DMI_EXACT_MATCH(DMI_BOARD_NAME, "GMxRGxx"), 1761 }, 1762 }, 1763 { 1764 .ident = "TUXEDO Stellaris 15 Gen4 Intel", 1765 .matches = { 1766 DMI_MATCH(DMI_SYS_VENDOR, "TUXEDO"), 1767 DMI_EXACT_MATCH(DMI_BOARD_NAME, "GMxAGxx"), 1768 }, 1769 }, 1770 { 1771 .ident = "TUXEDO Polaris 15/17 Gen5 AMD", 1772 .matches = { 1773 DMI_MATCH(DMI_SYS_VENDOR, "TUXEDO"), 1774 DMI_EXACT_MATCH(DMI_BOARD_NAME, "GMxXGxx"), 1775 }, 1776 }, 1777 { 1778 .ident = "TUXEDO Stellaris 16 Gen5 AMD", 1779 .matches = { 1780 DMI_MATCH(DMI_SYS_VENDOR, "TUXEDO"), 1781 DMI_EXACT_MATCH(DMI_BOARD_NAME, "GM6XGxX"), 1782 }, 1783 }, 1784 { 1785 .ident = "TUXEDO Stellaris 16/17 Gen5 Intel/Commodore ORION Gen 5", 1786 .matches = { 1787 DMI_MATCH(DMI_SYS_VENDOR, "TUXEDO"), 1788 DMI_EXACT_MATCH(DMI_BOARD_NAME, "GMxPXxx"), 1789 }, 1790 }, 1791 { 1792 .ident = "TUXEDO Stellaris Slim 15 Gen6 AMD", 1793 .matches = { 1794 DMI_MATCH(DMI_SYS_VENDOR, "TUXEDO"), 1795 DMI_EXACT_MATCH(DMI_BOARD_NAME, "GMxHGxx"), 1796 }, 1797 }, 1798 { 1799 .ident = "TUXEDO Stellaris Slim 15 Gen6 Intel/Commodore ORION Slim 15 Gen6", 1800 .matches = { 1801 DMI_MATCH(DMI_SYS_VENDOR, "TUXEDO"), 1802 DMI_EXACT_MATCH(DMI_BOARD_NAME, "GM5IXxA"), 1803 }, 1804 }, 1805 { 1806 .ident = "TUXEDO Stellaris 16 Gen6 Intel/Commodore ORION 16 Gen6", 1807 .matches = { 1808 DMI_MATCH(DMI_SYS_VENDOR, "TUXEDO"), 1809 DMI_EXACT_MATCH(DMI_BOARD_NAME, "GM6IXxB_MB1"), 1810 }, 1811 }, 1812 { 1813 .ident = "TUXEDO Stellaris 16 Gen6 Intel/Commodore ORION 16 Gen6", 1814 .matches = { 1815 DMI_MATCH(DMI_SYS_VENDOR, "TUXEDO"), 1816 DMI_EXACT_MATCH(DMI_BOARD_NAME, "GM6IXxB_MB2"), 1817 }, 1818 }, 1819 { 1820 .ident = "TUXEDO Stellaris 17 Gen6 Intel/Commodore ORION 17 Gen6", 1821 .matches = { 1822 DMI_MATCH(DMI_SYS_VENDOR, "TUXEDO"), 1823 DMI_EXACT_MATCH(DMI_BOARD_NAME, "GM7IXxN"), 1824 }, 1825 }, 1826 { 1827 .ident = "TUXEDO Stellaris 16 Gen7 AMD", 1828 .matches = { 1829 DMI_MATCH(DMI_SYS_VENDOR, "TUXEDO"), 1830 DMI_EXACT_MATCH(DMI_BOARD_NAME, "X6FR5xxY"), 1831 }, 1832 }, 1833 { 1834 .ident = "TUXEDO Stellaris 16 Gen7 Intel", 1835 .matches = { 1836 DMI_MATCH(DMI_SYS_VENDOR, "TUXEDO"), 1837 DMI_EXACT_MATCH(DMI_BOARD_NAME, "X6AR5xxY"), 1838 }, 1839 }, 1840 { 1841 .ident = "TUXEDO Stellaris 16 Gen7 Intel", 1842 .matches = { 1843 DMI_MATCH(DMI_SYS_VENDOR, "TUXEDO"), 1844 DMI_EXACT_MATCH(DMI_BOARD_NAME, "X6AR5xxY_mLED"), 1845 }, 1846 }, 1847 { 1848 .ident = "TUXEDO Book BA15 Gen10 AMD", 1849 .matches = { 1850 DMI_MATCH(DMI_SYS_VENDOR, "TUXEDO"), 1851 DMI_EXACT_MATCH(DMI_BOARD_NAME, "PF5PU1G"), 1852 }, 1853 }, 1854 { 1855 .ident = "TUXEDO Pulse 14 Gen1 AMD", 1856 .matches = { 1857 DMI_MATCH(DMI_SYS_VENDOR, "TUXEDO"), 1858 DMI_EXACT_MATCH(DMI_BOARD_NAME, "PULSE1401"), 1859 }, 1860 }, 1861 { 1862 .ident = "TUXEDO Pulse 15 Gen1 AMD", 1863 .matches = { 1864 DMI_MATCH(DMI_SYS_VENDOR, "TUXEDO"), 1865 DMI_EXACT_MATCH(DMI_BOARD_NAME, "PULSE1501"), 1866 }, 1867 }, 1868 { 1869 .ident = "TUXEDO Pulse 15 Gen2 AMD", 1870 .matches = { 1871 DMI_MATCH(DMI_SYS_VENDOR, "TUXEDO"), 1872 DMI_EXACT_MATCH(DMI_BOARD_NAME, "PF5LUXG"), 1873 }, 1874 }, 1875 { } 1876 }; 1877 MODULE_DEVICE_TABLE(dmi, uniwill_dmi_table); 1878 1879 static int __init uniwill_init(void) 1880 { 1881 const struct dmi_system_id *id; 1882 int ret; 1883 1884 id = dmi_first_match(uniwill_dmi_table); 1885 if (!id) { 1886 if (!force) 1887 return -ENODEV; 1888 1889 /* Assume that the device supports all features */ 1890 supported_features = UINT_MAX; 1891 pr_warn("Loading on a potentially unsupported device\n"); 1892 } else { 1893 supported_features = (uintptr_t)id->driver_data; 1894 } 1895 1896 ret = platform_driver_register(&uniwill_driver); 1897 if (ret < 0) 1898 return ret; 1899 1900 ret = uniwill_wmi_register_driver(); 1901 if (ret < 0) { 1902 platform_driver_unregister(&uniwill_driver); 1903 return ret; 1904 } 1905 1906 return 0; 1907 } 1908 module_init(uniwill_init); 1909 1910 static void __exit uniwill_exit(void) 1911 { 1912 uniwill_wmi_unregister_driver(); 1913 platform_driver_unregister(&uniwill_driver); 1914 } 1915 module_exit(uniwill_exit); 1916 1917 MODULE_AUTHOR("Armin Wolf <W_Armin@gmx.de>"); 1918 MODULE_DESCRIPTION("Uniwill notebook driver"); 1919 MODULE_LICENSE("GPL"); 1920