1 // SPDX-License-Identifier: GPL-2.0-or-later 2 /* 3 * Alienware WMAX WMI device driver 4 * 5 * Copyright (C) 2014 Dell Inc <Dell.Client.Kernel@dell.com> 6 * Copyright (C) 2025 Kurt Borja <kuurtb@gmail.com> 7 */ 8 9 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt 10 11 #include <linux/array_size.h> 12 #include <linux/bitfield.h> 13 #include <linux/bitmap.h> 14 #include <linux/bits.h> 15 #include <linux/debugfs.h> 16 #include <linux/dmi.h> 17 #include <linux/hwmon.h> 18 #include <linux/hwmon-sysfs.h> 19 #include <linux/kstrtox.h> 20 #include <linux/minmax.h> 21 #include <linux/moduleparam.h> 22 #include <linux/platform_profile.h> 23 #include <linux/pm.h> 24 #include <linux/seq_file.h> 25 #include <linux/units.h> 26 #include <linux/wmi.h> 27 #include "alienware-wmi.h" 28 29 #define WMAX_METHOD_HDMI_SOURCE 0x1 30 #define WMAX_METHOD_HDMI_STATUS 0x2 31 #define WMAX_METHOD_HDMI_CABLE 0x5 32 #define WMAX_METHOD_AMPLIFIER_CABLE 0x6 33 #define WMAX_METHOD_DEEP_SLEEP_CONTROL 0x0B 34 #define WMAX_METHOD_DEEP_SLEEP_STATUS 0x0C 35 #define WMAX_METHOD_BRIGHTNESS 0x3 36 #define WMAX_METHOD_ZONE_CONTROL 0x4 37 38 #define AWCC_METHOD_GET_FAN_SENSORS 0x13 39 #define AWCC_METHOD_THERMAL_INFORMATION 0x14 40 #define AWCC_METHOD_THERMAL_CONTROL 0x15 41 #define AWCC_METHOD_FWUP_GPIO_CONTROL 0x20 42 #define AWCC_METHOD_READ_TOTAL_GPIOS 0x21 43 #define AWCC_METHOD_READ_GPIO_STATUS 0x22 44 #define AWCC_METHOD_GAME_SHIFT_STATUS 0x25 45 46 #define AWCC_FAILURE_CODE 0xFFFFFFFF 47 #define AWCC_FAILURE_CODE_2 0xFFFFFFFE 48 49 #define AWCC_SENSOR_ID_FLAG BIT(8) 50 #define AWCC_THERMAL_MODE_MASK GENMASK(3, 0) 51 #define AWCC_THERMAL_TABLE_MASK GENMASK(7, 4) 52 #define AWCC_RESOURCE_ID_MASK GENMASK(7, 0) 53 54 /* Arbitrary limit based on supported models */ 55 #define AWCC_MAX_RES_COUNT 16 56 #define AWCC_ID_BITMAP_SIZE (U8_MAX + 1) 57 #define AWCC_ID_BITMAP_LONGS BITS_TO_LONGS(AWCC_ID_BITMAP_SIZE) 58 59 static bool force_hwmon; 60 module_param_unsafe(force_hwmon, bool, 0); 61 MODULE_PARM_DESC(force_hwmon, "Force probing for HWMON support without checking if the WMI backend is available"); 62 63 static bool force_platform_profile; 64 module_param_unsafe(force_platform_profile, bool, 0); 65 MODULE_PARM_DESC(force_platform_profile, "Forces auto-detecting thermal profiles without checking if WMI thermal backend is available"); 66 67 static bool force_gmode; 68 module_param_unsafe(force_gmode, bool, 0); 69 MODULE_PARM_DESC(force_gmode, "Forces G-Mode when performance profile is selected"); 70 71 struct awcc_quirks { 72 bool hwmon; 73 bool pprof; 74 bool gmode; 75 }; 76 77 static struct awcc_quirks g_series_quirks = { 78 .hwmon = true, 79 .pprof = true, 80 .gmode = true, 81 }; 82 83 static struct awcc_quirks generic_quirks = { 84 .hwmon = true, 85 .pprof = true, 86 .gmode = false, 87 }; 88 89 static struct awcc_quirks empty_quirks; 90 91 static const struct dmi_system_id awcc_dmi_table[] __initconst = { 92 { 93 .ident = "Alienware 16 Aurora", 94 .matches = { 95 DMI_MATCH(DMI_SYS_VENDOR, "Alienware"), 96 DMI_MATCH(DMI_PRODUCT_NAME, "Alienware 16 Aurora"), 97 }, 98 .driver_data = &g_series_quirks, 99 }, 100 { 101 .ident = "Alienware Area-51m", 102 .matches = { 103 DMI_MATCH(DMI_SYS_VENDOR, "Alienware"), 104 DMI_MATCH(DMI_PRODUCT_NAME, "Alienware Area-51m"), 105 }, 106 .driver_data = &generic_quirks, 107 }, 108 { 109 .ident = "Alienware m15", 110 .matches = { 111 DMI_MATCH(DMI_SYS_VENDOR, "Alienware"), 112 DMI_MATCH(DMI_PRODUCT_NAME, "Alienware m15"), 113 }, 114 .driver_data = &generic_quirks, 115 }, 116 { 117 .ident = "Alienware m16 R1 AMD", 118 .matches = { 119 DMI_MATCH(DMI_SYS_VENDOR, "Alienware"), 120 DMI_MATCH(DMI_PRODUCT_NAME, "Alienware m16 R1 AMD"), 121 }, 122 .driver_data = &generic_quirks, 123 }, 124 { 125 .ident = "Alienware m16 R1", 126 .matches = { 127 DMI_MATCH(DMI_SYS_VENDOR, "Alienware"), 128 DMI_MATCH(DMI_PRODUCT_NAME, "Alienware m16 R1"), 129 }, 130 .driver_data = &g_series_quirks, 131 }, 132 { 133 .ident = "Alienware m16 R2", 134 .matches = { 135 DMI_MATCH(DMI_SYS_VENDOR, "Alienware"), 136 DMI_MATCH(DMI_PRODUCT_NAME, "Alienware m16 R2"), 137 }, 138 .driver_data = &generic_quirks, 139 }, 140 { 141 .ident = "Alienware m17", 142 .matches = { 143 DMI_MATCH(DMI_SYS_VENDOR, "Alienware"), 144 DMI_MATCH(DMI_PRODUCT_NAME, "Alienware m17"), 145 }, 146 .driver_data = &generic_quirks, 147 }, 148 { 149 .ident = "Alienware m18", 150 .matches = { 151 DMI_MATCH(DMI_SYS_VENDOR, "Alienware"), 152 DMI_MATCH(DMI_PRODUCT_NAME, "Alienware m18"), 153 }, 154 .driver_data = &generic_quirks, 155 }, 156 { 157 .ident = "Alienware x15", 158 .matches = { 159 DMI_MATCH(DMI_SYS_VENDOR, "Alienware"), 160 DMI_MATCH(DMI_PRODUCT_NAME, "Alienware x15"), 161 }, 162 .driver_data = &generic_quirks, 163 }, 164 { 165 .ident = "Alienware x17", 166 .matches = { 167 DMI_MATCH(DMI_SYS_VENDOR, "Alienware"), 168 DMI_MATCH(DMI_PRODUCT_NAME, "Alienware x17"), 169 }, 170 .driver_data = &generic_quirks, 171 }, 172 { 173 .ident = "Dell Inc. G15", 174 .matches = { 175 DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."), 176 DMI_MATCH(DMI_PRODUCT_NAME, "Dell G15"), 177 }, 178 .driver_data = &g_series_quirks, 179 }, 180 { 181 .ident = "Dell Inc. G16", 182 .matches = { 183 DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."), 184 DMI_MATCH(DMI_PRODUCT_NAME, "Dell G16"), 185 }, 186 .driver_data = &g_series_quirks, 187 }, 188 { 189 .ident = "Dell Inc. G3", 190 .matches = { 191 DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."), 192 DMI_MATCH(DMI_PRODUCT_NAME, "G3"), 193 }, 194 .driver_data = &g_series_quirks, 195 }, 196 { 197 .ident = "Dell Inc. G5", 198 .matches = { 199 DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."), 200 DMI_MATCH(DMI_PRODUCT_NAME, "G5"), 201 }, 202 .driver_data = &g_series_quirks, 203 }, 204 {} 205 }; 206 207 enum AWCC_GET_FAN_SENSORS_OPERATIONS { 208 AWCC_OP_GET_TOTAL_FAN_TEMPS = 0x01, 209 AWCC_OP_GET_FAN_TEMP_ID = 0x02, 210 }; 211 212 enum AWCC_THERMAL_INFORMATION_OPERATIONS { 213 AWCC_OP_GET_SYSTEM_DESCRIPTION = 0x02, 214 AWCC_OP_GET_RESOURCE_ID = 0x03, 215 AWCC_OP_GET_TEMPERATURE = 0x04, 216 AWCC_OP_GET_FAN_RPM = 0x05, 217 AWCC_OP_GET_FAN_MIN_RPM = 0x08, 218 AWCC_OP_GET_FAN_MAX_RPM = 0x09, 219 AWCC_OP_GET_CURRENT_PROFILE = 0x0B, 220 AWCC_OP_GET_FAN_BOOST = 0x0C, 221 }; 222 223 enum AWCC_THERMAL_CONTROL_OPERATIONS { 224 AWCC_OP_ACTIVATE_PROFILE = 0x01, 225 AWCC_OP_SET_FAN_BOOST = 0x02, 226 }; 227 228 enum AWCC_GAME_SHIFT_STATUS_OPERATIONS { 229 AWCC_OP_TOGGLE_GAME_SHIFT = 0x01, 230 AWCC_OP_GET_GAME_SHIFT_STATUS = 0x02, 231 }; 232 233 enum AWCC_THERMAL_TABLES { 234 AWCC_THERMAL_TABLE_LEGACY = 0x9, 235 AWCC_THERMAL_TABLE_USTT = 0xA, 236 }; 237 238 enum AWCC_TEMP_SENSOR_TYPES { 239 AWCC_TEMP_SENSOR_CPU = 0x01, 240 AWCC_TEMP_SENSOR_FRONT = 0x03, 241 AWCC_TEMP_SENSOR_GPU = 0x06, 242 }; 243 244 enum AWCC_FAN_TYPES { 245 AWCC_FAN_CPU_1 = 0x32, 246 AWCC_FAN_GPU_1 = 0x33, 247 AWCC_FAN_PCI = 0x34, 248 AWCC_FAN_MID = 0x35, 249 AWCC_FAN_TOP_1 = 0x36, 250 AWCC_FAN_SIDE = 0x37, 251 AWCC_FAN_U2_1 = 0x38, 252 AWCC_FAN_U2_2 = 0x39, 253 AWCC_FAN_FRONT_1 = 0x3A, 254 AWCC_FAN_CPU_2 = 0x3B, 255 AWCC_FAN_GPU_2 = 0x3C, 256 AWCC_FAN_TOP_2 = 0x3D, 257 AWCC_FAN_TOP_3 = 0x3E, 258 AWCC_FAN_FRONT_2 = 0x3F, 259 AWCC_FAN_BOTTOM_1 = 0x40, 260 AWCC_FAN_BOTTOM_2 = 0x41, 261 }; 262 263 enum awcc_thermal_profile { 264 AWCC_PROFILE_SPECIAL_CUSTOM = 0x00, 265 AWCC_PROFILE_LEGACY_QUIET = 0x96, 266 AWCC_PROFILE_LEGACY_BALANCED = 0x97, 267 AWCC_PROFILE_LEGACY_BALANCED_PERFORMANCE = 0x98, 268 AWCC_PROFILE_LEGACY_PERFORMANCE = 0x99, 269 AWCC_PROFILE_USTT_BALANCED = 0xA0, 270 AWCC_PROFILE_USTT_BALANCED_PERFORMANCE = 0xA1, 271 AWCC_PROFILE_USTT_COOL = 0xA2, 272 AWCC_PROFILE_USTT_QUIET = 0xA3, 273 AWCC_PROFILE_USTT_PERFORMANCE = 0xA4, 274 AWCC_PROFILE_USTT_LOW_POWER = 0xA5, 275 AWCC_PROFILE_SPECIAL_GMODE = 0xAB, 276 }; 277 278 struct wmax_led_args { 279 u32 led_mask; 280 struct color_platform colors; 281 u8 state; 282 } __packed; 283 284 struct wmax_brightness_args { 285 u32 led_mask; 286 u32 percentage; 287 }; 288 289 struct wmax_basic_args { 290 u8 arg; 291 }; 292 293 struct wmax_u32_args { 294 u8 operation; 295 u8 arg1; 296 u8 arg2; 297 u8 arg3; 298 }; 299 300 struct awcc_fan_data { 301 unsigned long auto_channels_temp; 302 u32 min_rpm; 303 u32 max_rpm; 304 u8 suspend_cache; 305 u8 id; 306 }; 307 308 struct awcc_priv { 309 struct wmi_device *wdev; 310 union { 311 u32 system_description; 312 struct { 313 u8 fan_count; 314 u8 temp_count; 315 u8 unknown_count; 316 u8 profile_count; 317 }; 318 u8 res_count[4]; 319 }; 320 321 struct device *ppdev; 322 u8 supported_profiles[PLATFORM_PROFILE_LAST]; 323 324 struct device *hwdev; 325 struct awcc_fan_data **fan_data; 326 unsigned long temp_sensors[AWCC_ID_BITMAP_LONGS]; 327 328 u32 gpio_count; 329 }; 330 331 static struct awcc_quirks *awcc; 332 333 /* 334 * The HDMI mux sysfs node indicates the status of the HDMI input mux. 335 * It can toggle between standard system GPU output and HDMI input. 336 */ 337 static ssize_t cable_show(struct device *dev, struct device_attribute *attr, 338 char *buf) 339 { 340 struct alienfx_platdata *pdata = dev_get_platdata(dev); 341 struct wmax_basic_args in_args = { 342 .arg = 0, 343 }; 344 u32 out_data; 345 int ret; 346 347 ret = alienware_wmi_command(pdata->wdev, WMAX_METHOD_HDMI_CABLE, 348 &in_args, sizeof(in_args), &out_data); 349 if (!ret) { 350 if (out_data == 0) 351 return sysfs_emit(buf, "[unconnected] connected unknown\n"); 352 else if (out_data == 1) 353 return sysfs_emit(buf, "unconnected [connected] unknown\n"); 354 } 355 356 pr_err("alienware-wmi: unknown HDMI cable status: %d\n", ret); 357 return sysfs_emit(buf, "unconnected connected [unknown]\n"); 358 } 359 360 static ssize_t source_show(struct device *dev, struct device_attribute *attr, 361 char *buf) 362 { 363 struct alienfx_platdata *pdata = dev_get_platdata(dev); 364 struct wmax_basic_args in_args = { 365 .arg = 0, 366 }; 367 u32 out_data; 368 int ret; 369 370 ret = alienware_wmi_command(pdata->wdev, WMAX_METHOD_HDMI_STATUS, 371 &in_args, sizeof(in_args), &out_data); 372 if (!ret) { 373 if (out_data == 1) 374 return sysfs_emit(buf, "[input] gpu unknown\n"); 375 else if (out_data == 2) 376 return sysfs_emit(buf, "input [gpu] unknown\n"); 377 } 378 379 pr_err("alienware-wmi: unknown HDMI source status: %u\n", ret); 380 return sysfs_emit(buf, "input gpu [unknown]\n"); 381 } 382 383 static ssize_t source_store(struct device *dev, struct device_attribute *attr, 384 const char *buf, size_t count) 385 { 386 struct alienfx_platdata *pdata = dev_get_platdata(dev); 387 struct wmax_basic_args args; 388 int ret; 389 390 if (strcmp(buf, "gpu\n") == 0) 391 args.arg = 1; 392 else if (strcmp(buf, "input\n") == 0) 393 args.arg = 2; 394 else 395 args.arg = 3; 396 pr_debug("alienware-wmi: setting hdmi to %d : %s", args.arg, buf); 397 398 ret = alienware_wmi_command(pdata->wdev, WMAX_METHOD_HDMI_SOURCE, &args, 399 sizeof(args), NULL); 400 if (ret < 0) 401 pr_err("alienware-wmi: HDMI toggle failed: results: %u\n", ret); 402 403 return count; 404 } 405 406 static DEVICE_ATTR_RO(cable); 407 static DEVICE_ATTR_RW(source); 408 409 static bool hdmi_group_visible(struct kobject *kobj) 410 { 411 return alienware_interface == WMAX && alienfx->hdmi_mux; 412 } 413 DEFINE_SIMPLE_SYSFS_GROUP_VISIBLE(hdmi); 414 415 static struct attribute *hdmi_attrs[] = { 416 &dev_attr_cable.attr, 417 &dev_attr_source.attr, 418 NULL, 419 }; 420 421 const struct attribute_group wmax_hdmi_attribute_group = { 422 .name = "hdmi", 423 .is_visible = SYSFS_GROUP_VISIBLE(hdmi), 424 .attrs = hdmi_attrs, 425 }; 426 427 /* 428 * Alienware GFX amplifier support 429 * - Currently supports reading cable status 430 * - Leaving expansion room to possibly support dock/undock events later 431 */ 432 static ssize_t status_show(struct device *dev, struct device_attribute *attr, 433 char *buf) 434 { 435 struct alienfx_platdata *pdata = dev_get_platdata(dev); 436 struct wmax_basic_args in_args = { 437 .arg = 0, 438 }; 439 u32 out_data; 440 int ret; 441 442 ret = alienware_wmi_command(pdata->wdev, WMAX_METHOD_AMPLIFIER_CABLE, 443 &in_args, sizeof(in_args), &out_data); 444 if (!ret) { 445 if (out_data == 0) 446 return sysfs_emit(buf, "[unconnected] connected unknown\n"); 447 else if (out_data == 1) 448 return sysfs_emit(buf, "unconnected [connected] unknown\n"); 449 } 450 451 pr_err("alienware-wmi: unknown amplifier cable status: %d\n", ret); 452 return sysfs_emit(buf, "unconnected connected [unknown]\n"); 453 } 454 455 static DEVICE_ATTR_RO(status); 456 457 static bool amplifier_group_visible(struct kobject *kobj) 458 { 459 return alienware_interface == WMAX && alienfx->amplifier; 460 } 461 DEFINE_SIMPLE_SYSFS_GROUP_VISIBLE(amplifier); 462 463 static struct attribute *amplifier_attrs[] = { 464 &dev_attr_status.attr, 465 NULL, 466 }; 467 468 const struct attribute_group wmax_amplifier_attribute_group = { 469 .name = "amplifier", 470 .is_visible = SYSFS_GROUP_VISIBLE(amplifier), 471 .attrs = amplifier_attrs, 472 }; 473 474 /* 475 * Deep Sleep Control support 476 * - Modifies BIOS setting for deep sleep control allowing extra wakeup events 477 */ 478 static ssize_t deepsleep_show(struct device *dev, struct device_attribute *attr, 479 char *buf) 480 { 481 struct alienfx_platdata *pdata = dev_get_platdata(dev); 482 struct wmax_basic_args in_args = { 483 .arg = 0, 484 }; 485 u32 out_data; 486 int ret; 487 488 ret = alienware_wmi_command(pdata->wdev, WMAX_METHOD_DEEP_SLEEP_STATUS, 489 &in_args, sizeof(in_args), &out_data); 490 if (!ret) { 491 if (out_data == 0) 492 return sysfs_emit(buf, "[disabled] s5 s5_s4\n"); 493 else if (out_data == 1) 494 return sysfs_emit(buf, "disabled [s5] s5_s4\n"); 495 else if (out_data == 2) 496 return sysfs_emit(buf, "disabled s5 [s5_s4]\n"); 497 } 498 499 pr_err("alienware-wmi: unknown deep sleep status: %d\n", ret); 500 return sysfs_emit(buf, "disabled s5 s5_s4 [unknown]\n"); 501 } 502 503 static ssize_t deepsleep_store(struct device *dev, struct device_attribute *attr, 504 const char *buf, size_t count) 505 { 506 struct alienfx_platdata *pdata = dev_get_platdata(dev); 507 struct wmax_basic_args args; 508 int ret; 509 510 if (strcmp(buf, "disabled\n") == 0) 511 args.arg = 0; 512 else if (strcmp(buf, "s5\n") == 0) 513 args.arg = 1; 514 else 515 args.arg = 2; 516 pr_debug("alienware-wmi: setting deep sleep to %d : %s", args.arg, buf); 517 518 ret = alienware_wmi_command(pdata->wdev, WMAX_METHOD_DEEP_SLEEP_CONTROL, 519 &args, sizeof(args), NULL); 520 if (!ret) 521 pr_err("alienware-wmi: deep sleep control failed: results: %u\n", ret); 522 523 return count; 524 } 525 526 static DEVICE_ATTR_RW(deepsleep); 527 528 static bool deepsleep_group_visible(struct kobject *kobj) 529 { 530 return alienware_interface == WMAX && alienfx->deepslp; 531 } 532 DEFINE_SIMPLE_SYSFS_GROUP_VISIBLE(deepsleep); 533 534 static struct attribute *deepsleep_attrs[] = { 535 &dev_attr_deepsleep.attr, 536 NULL, 537 }; 538 539 const struct attribute_group wmax_deepsleep_attribute_group = { 540 .name = "deepsleep", 541 .is_visible = SYSFS_GROUP_VISIBLE(deepsleep), 542 .attrs = deepsleep_attrs, 543 }; 544 545 /* 546 * AWCC Helpers 547 */ 548 static int awcc_profile_to_pprof(enum awcc_thermal_profile profile, 549 enum platform_profile_option *pprof) 550 { 551 switch (profile) { 552 case AWCC_PROFILE_SPECIAL_CUSTOM: 553 *pprof = PLATFORM_PROFILE_CUSTOM; 554 break; 555 case AWCC_PROFILE_LEGACY_QUIET: 556 case AWCC_PROFILE_USTT_QUIET: 557 *pprof = PLATFORM_PROFILE_QUIET; 558 break; 559 case AWCC_PROFILE_LEGACY_BALANCED: 560 case AWCC_PROFILE_USTT_BALANCED: 561 *pprof = PLATFORM_PROFILE_BALANCED; 562 break; 563 case AWCC_PROFILE_LEGACY_BALANCED_PERFORMANCE: 564 case AWCC_PROFILE_USTT_BALANCED_PERFORMANCE: 565 *pprof = PLATFORM_PROFILE_BALANCED_PERFORMANCE; 566 break; 567 case AWCC_PROFILE_LEGACY_PERFORMANCE: 568 case AWCC_PROFILE_USTT_PERFORMANCE: 569 case AWCC_PROFILE_SPECIAL_GMODE: 570 *pprof = PLATFORM_PROFILE_PERFORMANCE; 571 break; 572 case AWCC_PROFILE_USTT_COOL: 573 *pprof = PLATFORM_PROFILE_COOL; 574 break; 575 case AWCC_PROFILE_USTT_LOW_POWER: 576 *pprof = PLATFORM_PROFILE_LOW_POWER; 577 break; 578 default: 579 return -EINVAL; 580 } 581 582 return 0; 583 } 584 585 static int awcc_wmi_command(struct wmi_device *wdev, u32 method_id, 586 struct wmax_u32_args *args, u32 *out) 587 { 588 int ret; 589 590 ret = alienware_wmi_command(wdev, method_id, args, sizeof(*args), out); 591 if (ret) 592 return ret; 593 594 if (*out == AWCC_FAILURE_CODE || *out == AWCC_FAILURE_CODE_2) 595 return -EBADRQC; 596 597 return 0; 598 } 599 600 static int awcc_get_fan_sensors(struct wmi_device *wdev, u8 operation, 601 u8 fan_id, u8 index, u32 *out) 602 { 603 struct wmax_u32_args args = { 604 .operation = operation, 605 .arg1 = fan_id, 606 .arg2 = index, 607 .arg3 = 0, 608 }; 609 610 return awcc_wmi_command(wdev, AWCC_METHOD_GET_FAN_SENSORS, &args, out); 611 } 612 613 static int awcc_thermal_information(struct wmi_device *wdev, u8 operation, u8 arg, 614 u32 *out) 615 { 616 struct wmax_u32_args args = { 617 .operation = operation, 618 .arg1 = arg, 619 .arg2 = 0, 620 .arg3 = 0, 621 }; 622 623 return awcc_wmi_command(wdev, AWCC_METHOD_THERMAL_INFORMATION, &args, out); 624 } 625 626 static int awcc_fwup_gpio_control(struct wmi_device *wdev, u8 pin, u8 status) 627 { 628 struct wmax_u32_args args = { 629 .operation = pin, 630 .arg1 = status, 631 .arg2 = 0, 632 .arg3 = 0, 633 }; 634 u32 out; 635 636 return awcc_wmi_command(wdev, AWCC_METHOD_FWUP_GPIO_CONTROL, &args, &out); 637 } 638 639 static int awcc_read_total_gpios(struct wmi_device *wdev, u32 *count) 640 { 641 struct wmax_u32_args args = {}; 642 643 return awcc_wmi_command(wdev, AWCC_METHOD_READ_TOTAL_GPIOS, &args, count); 644 } 645 646 static int awcc_read_gpio_status(struct wmi_device *wdev, u8 pin, u32 *status) 647 { 648 struct wmax_u32_args args = { 649 .operation = pin, 650 .arg1 = 0, 651 .arg2 = 0, 652 .arg3 = 0, 653 }; 654 655 return awcc_wmi_command(wdev, AWCC_METHOD_READ_GPIO_STATUS, &args, status); 656 } 657 658 static int awcc_game_shift_status(struct wmi_device *wdev, u8 operation, 659 u32 *out) 660 { 661 struct wmax_u32_args args = { 662 .operation = operation, 663 .arg1 = 0, 664 .arg2 = 0, 665 .arg3 = 0, 666 }; 667 668 return awcc_wmi_command(wdev, AWCC_METHOD_GAME_SHIFT_STATUS, &args, out); 669 } 670 671 /** 672 * awcc_op_get_resource_id - Get the resource ID at a given index 673 * @wdev: AWCC WMI device 674 * @index: Index 675 * @out: Value returned by the WMI call 676 * 677 * Get the resource ID at a given @index. Resource IDs are listed in the 678 * following order: 679 * 680 * - Fan IDs 681 * - Sensor IDs 682 * - Unknown IDs 683 * - Thermal Profile IDs 684 * 685 * The total number of IDs of a given type can be obtained with 686 * AWCC_OP_GET_SYSTEM_DESCRIPTION. 687 * 688 * Return: 0 on success, -errno on failure 689 */ 690 static int awcc_op_get_resource_id(struct wmi_device *wdev, u8 index, u8 *out) 691 { 692 struct wmax_u32_args args = { 693 .operation = AWCC_OP_GET_RESOURCE_ID, 694 .arg1 = index, 695 .arg2 = 0, 696 .arg3 = 0, 697 }; 698 u32 out_data; 699 int ret; 700 701 ret = awcc_wmi_command(wdev, AWCC_METHOD_THERMAL_INFORMATION, &args, &out_data); 702 if (ret) 703 return ret; 704 705 *out = FIELD_GET(AWCC_RESOURCE_ID_MASK, out_data); 706 707 return 0; 708 } 709 710 static int awcc_op_get_fan_rpm(struct wmi_device *wdev, u8 fan_id, u32 *out) 711 { 712 struct wmax_u32_args args = { 713 .operation = AWCC_OP_GET_FAN_RPM, 714 .arg1 = fan_id, 715 .arg2 = 0, 716 .arg3 = 0, 717 }; 718 719 return awcc_wmi_command(wdev, AWCC_METHOD_THERMAL_INFORMATION, &args, out); 720 } 721 722 static int awcc_op_get_temperature(struct wmi_device *wdev, u8 temp_id, u32 *out) 723 { 724 struct wmax_u32_args args = { 725 .operation = AWCC_OP_GET_TEMPERATURE, 726 .arg1 = temp_id, 727 .arg2 = 0, 728 .arg3 = 0, 729 }; 730 731 return awcc_wmi_command(wdev, AWCC_METHOD_THERMAL_INFORMATION, &args, out); 732 } 733 734 static int awcc_op_get_fan_boost(struct wmi_device *wdev, u8 fan_id, u32 *out) 735 { 736 struct wmax_u32_args args = { 737 .operation = AWCC_OP_GET_FAN_BOOST, 738 .arg1 = fan_id, 739 .arg2 = 0, 740 .arg3 = 0, 741 }; 742 743 return awcc_wmi_command(wdev, AWCC_METHOD_THERMAL_INFORMATION, &args, out); 744 } 745 746 static int awcc_op_get_current_profile(struct wmi_device *wdev, u32 *out) 747 { 748 struct wmax_u32_args args = { 749 .operation = AWCC_OP_GET_CURRENT_PROFILE, 750 .arg1 = 0, 751 .arg2 = 0, 752 .arg3 = 0, 753 }; 754 755 return awcc_wmi_command(wdev, AWCC_METHOD_THERMAL_INFORMATION, &args, out); 756 } 757 758 static int awcc_op_activate_profile(struct wmi_device *wdev, u8 profile) 759 { 760 struct wmax_u32_args args = { 761 .operation = AWCC_OP_ACTIVATE_PROFILE, 762 .arg1 = profile, 763 .arg2 = 0, 764 .arg3 = 0, 765 }; 766 u32 out; 767 768 return awcc_wmi_command(wdev, AWCC_METHOD_THERMAL_CONTROL, &args, &out); 769 } 770 771 static int awcc_op_set_fan_boost(struct wmi_device *wdev, u8 fan_id, u8 boost) 772 { 773 struct wmax_u32_args args = { 774 .operation = AWCC_OP_SET_FAN_BOOST, 775 .arg1 = fan_id, 776 .arg2 = boost, 777 .arg3 = 0, 778 }; 779 u32 out; 780 781 return awcc_wmi_command(wdev, AWCC_METHOD_THERMAL_CONTROL, &args, &out); 782 } 783 784 /* 785 * HWMON 786 * - Provides temperature and fan speed monitoring as well as manual fan 787 * control 788 */ 789 static umode_t awcc_hwmon_is_visible(const void *drvdata, enum hwmon_sensor_types type, 790 u32 attr, int channel) 791 { 792 const struct awcc_priv *priv = drvdata; 793 unsigned int temp_count; 794 795 switch (type) { 796 case hwmon_temp: 797 temp_count = bitmap_weight(priv->temp_sensors, AWCC_ID_BITMAP_SIZE); 798 799 return channel < temp_count ? 0444 : 0; 800 case hwmon_fan: 801 return channel < priv->fan_count ? 0444 : 0; 802 case hwmon_pwm: 803 return channel < priv->fan_count ? 0444 : 0; 804 default: 805 return 0; 806 } 807 } 808 809 static int awcc_hwmon_read(struct device *dev, enum hwmon_sensor_types type, 810 u32 attr, int channel, long *val) 811 { 812 struct awcc_priv *priv = dev_get_drvdata(dev); 813 const struct awcc_fan_data *fan; 814 u32 state; 815 int ret; 816 u8 temp; 817 818 switch (type) { 819 case hwmon_temp: 820 temp = find_nth_bit(priv->temp_sensors, AWCC_ID_BITMAP_SIZE, channel); 821 822 switch (attr) { 823 case hwmon_temp_input: 824 ret = awcc_op_get_temperature(priv->wdev, temp, &state); 825 if (ret) 826 return ret; 827 828 *val = state * MILLIDEGREE_PER_DEGREE; 829 break; 830 default: 831 return -EOPNOTSUPP; 832 } 833 834 break; 835 case hwmon_fan: 836 fan = priv->fan_data[channel]; 837 838 switch (attr) { 839 case hwmon_fan_input: 840 ret = awcc_op_get_fan_rpm(priv->wdev, fan->id, &state); 841 if (ret) 842 return ret; 843 844 *val = state; 845 break; 846 case hwmon_fan_min: 847 *val = fan->min_rpm; 848 break; 849 case hwmon_fan_max: 850 *val = fan->max_rpm; 851 break; 852 default: 853 return -EOPNOTSUPP; 854 } 855 856 break; 857 case hwmon_pwm: 858 fan = priv->fan_data[channel]; 859 860 switch (attr) { 861 case hwmon_pwm_auto_channels_temp: 862 *val = fan->auto_channels_temp; 863 break; 864 default: 865 return -EOPNOTSUPP; 866 } 867 868 break; 869 default: 870 return -EOPNOTSUPP; 871 } 872 873 return 0; 874 } 875 876 static int awcc_hwmon_read_string(struct device *dev, enum hwmon_sensor_types type, 877 u32 attr, int channel, const char **str) 878 { 879 struct awcc_priv *priv = dev_get_drvdata(dev); 880 u8 temp; 881 882 switch (type) { 883 case hwmon_temp: 884 temp = find_nth_bit(priv->temp_sensors, AWCC_ID_BITMAP_SIZE, channel); 885 886 switch (temp) { 887 case AWCC_TEMP_SENSOR_CPU: 888 *str = "CPU"; 889 break; 890 case AWCC_TEMP_SENSOR_FRONT: 891 *str = "Front"; 892 break; 893 case AWCC_TEMP_SENSOR_GPU: 894 *str = "GPU"; 895 break; 896 default: 897 *str = "Unknown"; 898 break; 899 } 900 901 break; 902 case hwmon_fan: 903 switch (priv->fan_data[channel]->id) { 904 case AWCC_FAN_CPU_1: 905 case AWCC_FAN_CPU_2: 906 *str = "CPU Fan"; 907 break; 908 case AWCC_FAN_GPU_1: 909 case AWCC_FAN_GPU_2: 910 *str = "GPU Fan"; 911 break; 912 case AWCC_FAN_PCI: 913 *str = "PCI Fan"; 914 break; 915 case AWCC_FAN_MID: 916 *str = "Mid Fan"; 917 break; 918 case AWCC_FAN_TOP_1: 919 case AWCC_FAN_TOP_2: 920 case AWCC_FAN_TOP_3: 921 *str = "Top Fan"; 922 break; 923 case AWCC_FAN_SIDE: 924 *str = "Side Fan"; 925 break; 926 case AWCC_FAN_U2_1: 927 case AWCC_FAN_U2_2: 928 *str = "U.2 Fan"; 929 break; 930 case AWCC_FAN_FRONT_1: 931 case AWCC_FAN_FRONT_2: 932 *str = "Front Fan"; 933 break; 934 case AWCC_FAN_BOTTOM_1: 935 case AWCC_FAN_BOTTOM_2: 936 *str = "Bottom Fan"; 937 break; 938 default: 939 *str = "Unknown Fan"; 940 break; 941 } 942 943 break; 944 default: 945 return -EOPNOTSUPP; 946 } 947 948 return 0; 949 } 950 951 static const struct hwmon_ops awcc_hwmon_ops = { 952 .is_visible = awcc_hwmon_is_visible, 953 .read = awcc_hwmon_read, 954 .read_string = awcc_hwmon_read_string, 955 }; 956 957 static const struct hwmon_channel_info * const awcc_hwmon_info[] = { 958 HWMON_CHANNEL_INFO(temp, 959 HWMON_T_LABEL | HWMON_T_INPUT, 960 HWMON_T_LABEL | HWMON_T_INPUT, 961 HWMON_T_LABEL | HWMON_T_INPUT, 962 HWMON_T_LABEL | HWMON_T_INPUT, 963 HWMON_T_LABEL | HWMON_T_INPUT, 964 HWMON_T_LABEL | HWMON_T_INPUT 965 ), 966 HWMON_CHANNEL_INFO(fan, 967 HWMON_F_LABEL | HWMON_F_INPUT | HWMON_F_MIN | HWMON_F_MAX, 968 HWMON_F_LABEL | HWMON_F_INPUT | HWMON_F_MIN | HWMON_F_MAX, 969 HWMON_F_LABEL | HWMON_F_INPUT | HWMON_F_MIN | HWMON_F_MAX, 970 HWMON_F_LABEL | HWMON_F_INPUT | HWMON_F_MIN | HWMON_F_MAX, 971 HWMON_F_LABEL | HWMON_F_INPUT | HWMON_F_MIN | HWMON_F_MAX, 972 HWMON_F_LABEL | HWMON_F_INPUT | HWMON_F_MIN | HWMON_F_MAX 973 ), 974 HWMON_CHANNEL_INFO(pwm, 975 HWMON_PWM_AUTO_CHANNELS_TEMP, 976 HWMON_PWM_AUTO_CHANNELS_TEMP, 977 HWMON_PWM_AUTO_CHANNELS_TEMP, 978 HWMON_PWM_AUTO_CHANNELS_TEMP, 979 HWMON_PWM_AUTO_CHANNELS_TEMP, 980 HWMON_PWM_AUTO_CHANNELS_TEMP 981 ), 982 NULL 983 }; 984 985 static const struct hwmon_chip_info awcc_hwmon_chip_info = { 986 .ops = &awcc_hwmon_ops, 987 .info = awcc_hwmon_info, 988 }; 989 990 static ssize_t fan_boost_show(struct device *dev, struct device_attribute *attr, 991 char *buf) 992 { 993 struct awcc_priv *priv = dev_get_drvdata(dev); 994 int index = to_sensor_dev_attr(attr)->index; 995 struct awcc_fan_data *fan = priv->fan_data[index]; 996 u32 boost; 997 int ret; 998 999 ret = awcc_op_get_fan_boost(priv->wdev, fan->id, &boost); 1000 if (ret) 1001 return ret; 1002 1003 return sysfs_emit(buf, "%u\n", boost); 1004 } 1005 1006 static ssize_t fan_boost_store(struct device *dev, struct device_attribute *attr, 1007 const char *buf, size_t count) 1008 { 1009 struct awcc_priv *priv = dev_get_drvdata(dev); 1010 int index = to_sensor_dev_attr(attr)->index; 1011 struct awcc_fan_data *fan = priv->fan_data[index]; 1012 unsigned long val; 1013 int ret; 1014 1015 ret = kstrtoul(buf, 0, &val); 1016 if (ret) 1017 return ret; 1018 1019 ret = awcc_op_set_fan_boost(priv->wdev, fan->id, clamp_val(val, 0, 255)); 1020 1021 return ret ? ret : count; 1022 } 1023 1024 static SENSOR_DEVICE_ATTR_RW(fan1_boost, fan_boost, 0); 1025 static SENSOR_DEVICE_ATTR_RW(fan2_boost, fan_boost, 1); 1026 static SENSOR_DEVICE_ATTR_RW(fan3_boost, fan_boost, 2); 1027 static SENSOR_DEVICE_ATTR_RW(fan4_boost, fan_boost, 3); 1028 static SENSOR_DEVICE_ATTR_RW(fan5_boost, fan_boost, 4); 1029 static SENSOR_DEVICE_ATTR_RW(fan6_boost, fan_boost, 5); 1030 1031 static umode_t fan_boost_attr_visible(struct kobject *kobj, struct attribute *attr, int n) 1032 { 1033 struct awcc_priv *priv = dev_get_drvdata(kobj_to_dev(kobj)); 1034 1035 return n < priv->fan_count ? attr->mode : 0; 1036 } 1037 1038 static bool fan_boost_group_visible(struct kobject *kobj) 1039 { 1040 return true; 1041 } 1042 1043 DEFINE_SYSFS_GROUP_VISIBLE(fan_boost); 1044 1045 static struct attribute *fan_boost_attrs[] = { 1046 &sensor_dev_attr_fan1_boost.dev_attr.attr, 1047 &sensor_dev_attr_fan2_boost.dev_attr.attr, 1048 &sensor_dev_attr_fan3_boost.dev_attr.attr, 1049 &sensor_dev_attr_fan4_boost.dev_attr.attr, 1050 &sensor_dev_attr_fan5_boost.dev_attr.attr, 1051 &sensor_dev_attr_fan6_boost.dev_attr.attr, 1052 NULL 1053 }; 1054 1055 static const struct attribute_group fan_boost_group = { 1056 .attrs = fan_boost_attrs, 1057 .is_visible = SYSFS_GROUP_VISIBLE(fan_boost), 1058 }; 1059 1060 static const struct attribute_group *awcc_hwmon_groups[] = { 1061 &fan_boost_group, 1062 NULL 1063 }; 1064 1065 static int awcc_hwmon_temps_init(struct wmi_device *wdev) 1066 { 1067 struct awcc_priv *priv = dev_get_drvdata(&wdev->dev); 1068 unsigned int i; 1069 int ret; 1070 u8 id; 1071 1072 for (i = 0; i < priv->temp_count; i++) { 1073 /* 1074 * Temperature sensors IDs are listed after the fan IDs at 1075 * offset `fan_count` 1076 */ 1077 ret = awcc_op_get_resource_id(wdev, i + priv->fan_count, &id); 1078 if (ret) 1079 return ret; 1080 1081 __set_bit(id, priv->temp_sensors); 1082 } 1083 1084 return 0; 1085 } 1086 1087 static int awcc_hwmon_fans_init(struct wmi_device *wdev) 1088 { 1089 struct awcc_priv *priv = dev_get_drvdata(&wdev->dev); 1090 unsigned long fan_temps[AWCC_ID_BITMAP_LONGS]; 1091 unsigned long gather[AWCC_ID_BITMAP_LONGS]; 1092 u32 min_rpm, max_rpm, temp_count, temp_id; 1093 struct awcc_fan_data *fan_data; 1094 unsigned int i, j; 1095 int ret; 1096 u8 id; 1097 1098 for (i = 0; i < priv->fan_count; i++) { 1099 fan_data = devm_kzalloc(&wdev->dev, sizeof(*fan_data), GFP_KERNEL); 1100 if (!fan_data) 1101 return -ENOMEM; 1102 1103 /* 1104 * Fan IDs are listed first at offset 0 1105 */ 1106 ret = awcc_op_get_resource_id(wdev, i, &id); 1107 if (ret) 1108 return ret; 1109 1110 ret = awcc_thermal_information(wdev, AWCC_OP_GET_FAN_MIN_RPM, id, 1111 &min_rpm); 1112 if (ret) 1113 return ret; 1114 1115 ret = awcc_thermal_information(wdev, AWCC_OP_GET_FAN_MAX_RPM, id, 1116 &max_rpm); 1117 if (ret) 1118 return ret; 1119 1120 ret = awcc_get_fan_sensors(wdev, AWCC_OP_GET_TOTAL_FAN_TEMPS, id, 1121 0, &temp_count); 1122 if (ret) 1123 return ret; 1124 1125 bitmap_zero(fan_temps, AWCC_ID_BITMAP_SIZE); 1126 1127 for (j = 0; j < temp_count; j++) { 1128 ret = awcc_get_fan_sensors(wdev, AWCC_OP_GET_FAN_TEMP_ID, 1129 id, j, &temp_id); 1130 if (ret) 1131 break; 1132 1133 temp_id = FIELD_GET(AWCC_RESOURCE_ID_MASK, temp_id); 1134 __set_bit(temp_id, fan_temps); 1135 } 1136 1137 fan_data->id = id; 1138 fan_data->min_rpm = min_rpm; 1139 fan_data->max_rpm = max_rpm; 1140 bitmap_gather(gather, fan_temps, priv->temp_sensors, AWCC_ID_BITMAP_SIZE); 1141 bitmap_copy(&fan_data->auto_channels_temp, gather, BITS_PER_LONG); 1142 priv->fan_data[i] = fan_data; 1143 } 1144 1145 return 0; 1146 } 1147 1148 static int awcc_hwmon_init(struct wmi_device *wdev) 1149 { 1150 struct awcc_priv *priv = dev_get_drvdata(&wdev->dev); 1151 int ret; 1152 1153 priv->fan_data = devm_kcalloc(&wdev->dev, priv->fan_count, 1154 sizeof(*priv->fan_data), GFP_KERNEL); 1155 if (!priv->fan_data) 1156 return -ENOMEM; 1157 1158 ret = awcc_hwmon_temps_init(wdev); 1159 if (ret) 1160 return ret; 1161 1162 ret = awcc_hwmon_fans_init(wdev); 1163 if (ret) 1164 return ret; 1165 1166 priv->hwdev = devm_hwmon_device_register_with_info(&wdev->dev, "alienware_wmi", 1167 priv, &awcc_hwmon_chip_info, 1168 awcc_hwmon_groups); 1169 1170 return PTR_ERR_OR_ZERO(priv->hwdev); 1171 } 1172 1173 static void awcc_hwmon_suspend(struct device *dev) 1174 { 1175 struct awcc_priv *priv = dev_get_drvdata(dev); 1176 struct awcc_fan_data *fan; 1177 unsigned int i; 1178 u32 boost; 1179 int ret; 1180 1181 for (i = 0; i < priv->fan_count; i++) { 1182 fan = priv->fan_data[i]; 1183 1184 ret = awcc_thermal_information(priv->wdev, AWCC_OP_GET_FAN_BOOST, 1185 fan->id, &boost); 1186 if (ret) 1187 dev_err(dev, "Failed to store Fan %u boost while suspending\n", i); 1188 1189 fan->suspend_cache = ret ? 0 : clamp_val(boost, 0, 255); 1190 1191 awcc_op_set_fan_boost(priv->wdev, fan->id, 0); 1192 if (ret) 1193 dev_err(dev, "Failed to set Fan %u boost to 0 while suspending\n", i); 1194 } 1195 } 1196 1197 static void awcc_hwmon_resume(struct device *dev) 1198 { 1199 struct awcc_priv *priv = dev_get_drvdata(dev); 1200 struct awcc_fan_data *fan; 1201 unsigned int i; 1202 int ret; 1203 1204 for (i = 0; i < priv->fan_count; i++) { 1205 fan = priv->fan_data[i]; 1206 1207 if (!fan->suspend_cache) 1208 continue; 1209 1210 ret = awcc_op_set_fan_boost(priv->wdev, fan->id, fan->suspend_cache); 1211 if (ret) 1212 dev_err(dev, "Failed to restore Fan %u boost while resuming\n", i); 1213 } 1214 } 1215 1216 /* 1217 * Thermal Profile control 1218 * - Provides thermal profile control through the Platform Profile API 1219 */ 1220 static int awcc_platform_profile_get(struct device *dev, 1221 enum platform_profile_option *profile) 1222 { 1223 struct awcc_priv *priv = dev_get_drvdata(dev); 1224 u32 out_data; 1225 int ret; 1226 1227 ret = awcc_op_get_current_profile(priv->wdev, &out_data); 1228 if (ret) 1229 return ret; 1230 1231 return awcc_profile_to_pprof(out_data, profile); 1232 } 1233 1234 static int awcc_platform_profile_set(struct device *dev, 1235 enum platform_profile_option profile) 1236 { 1237 struct awcc_priv *priv = dev_get_drvdata(dev); 1238 1239 if (awcc->gmode) { 1240 u32 gmode_status; 1241 int ret; 1242 1243 ret = awcc_game_shift_status(priv->wdev, 1244 AWCC_OP_GET_GAME_SHIFT_STATUS, 1245 &gmode_status); 1246 1247 if (ret < 0) 1248 return ret; 1249 1250 if ((profile == PLATFORM_PROFILE_PERFORMANCE && !gmode_status) || 1251 (profile != PLATFORM_PROFILE_PERFORMANCE && gmode_status)) { 1252 ret = awcc_game_shift_status(priv->wdev, 1253 AWCC_OP_TOGGLE_GAME_SHIFT, 1254 &gmode_status); 1255 1256 if (ret < 0) 1257 return ret; 1258 } 1259 } 1260 1261 return awcc_op_activate_profile(priv->wdev, priv->supported_profiles[profile]); 1262 } 1263 1264 static int awcc_platform_profile_probe(void *drvdata, unsigned long *choices) 1265 { 1266 enum platform_profile_option profile; 1267 struct awcc_priv *priv = drvdata; 1268 u8 id, offset = 0; 1269 int ret; 1270 1271 /* 1272 * Thermal profile IDs are listed last at offset 1273 * fan_count + temp_count + unknown_count 1274 */ 1275 for (unsigned int i = 0; i < ARRAY_SIZE(priv->res_count) - 1; i++) 1276 offset += priv->res_count[i]; 1277 1278 for (unsigned int i = 0; i < priv->profile_count; i++) { 1279 ret = awcc_op_get_resource_id(priv->wdev, i + offset, &id); 1280 /* 1281 * Some devices report an incorrect number of thermal profiles 1282 * so the resource ID list may end prematurely 1283 */ 1284 if (ret == -EBADRQC) 1285 break; 1286 if (ret) 1287 return ret; 1288 1289 /* 1290 * G-Mode profile ID is not listed consistently across modeles 1291 * that support it, therefore we handle it through quirks. 1292 */ 1293 if (id == AWCC_PROFILE_SPECIAL_GMODE) 1294 continue; 1295 1296 ret = awcc_profile_to_pprof(id, &profile); 1297 if (ret) { 1298 dev_dbg(&priv->wdev->dev, "Unmapped thermal profile ID 0x%02x\n", id); 1299 continue; 1300 } 1301 1302 priv->supported_profiles[profile] = id; 1303 __set_bit(profile, choices); 1304 } 1305 1306 if (bitmap_empty(choices, PLATFORM_PROFILE_LAST)) 1307 return -ENODEV; 1308 1309 if (awcc->gmode) { 1310 priv->supported_profiles[PLATFORM_PROFILE_PERFORMANCE] = 1311 AWCC_PROFILE_SPECIAL_GMODE; 1312 1313 __set_bit(PLATFORM_PROFILE_PERFORMANCE, choices); 1314 } 1315 1316 /* Every model supports the "custom" profile */ 1317 priv->supported_profiles[PLATFORM_PROFILE_CUSTOM] = 1318 AWCC_PROFILE_SPECIAL_CUSTOM; 1319 1320 __set_bit(PLATFORM_PROFILE_CUSTOM, choices); 1321 1322 return 0; 1323 } 1324 1325 static const struct platform_profile_ops awcc_platform_profile_ops = { 1326 .probe = awcc_platform_profile_probe, 1327 .profile_get = awcc_platform_profile_get, 1328 .profile_set = awcc_platform_profile_set, 1329 }; 1330 1331 static int awcc_platform_profile_init(struct wmi_device *wdev) 1332 { 1333 struct awcc_priv *priv = dev_get_drvdata(&wdev->dev); 1334 1335 priv->ppdev = devm_platform_profile_register(&wdev->dev, "alienware-wmi", 1336 priv, &awcc_platform_profile_ops); 1337 1338 return PTR_ERR_OR_ZERO(priv->ppdev); 1339 } 1340 1341 /* 1342 * DebugFS 1343 */ 1344 static int awcc_debugfs_system_description_read(struct seq_file *seq, void *data) 1345 { 1346 struct device *dev = seq->private; 1347 struct awcc_priv *priv = dev_get_drvdata(dev); 1348 1349 seq_printf(seq, "0x%08x\n", priv->system_description); 1350 1351 return 0; 1352 } 1353 1354 static int awcc_debugfs_hwmon_data_read(struct seq_file *seq, void *data) 1355 { 1356 struct device *dev = seq->private; 1357 struct awcc_priv *priv = dev_get_drvdata(dev); 1358 const struct awcc_fan_data *fan; 1359 unsigned int bit; 1360 1361 seq_printf(seq, "Number of fans: %u\n", priv->fan_count); 1362 seq_printf(seq, "Number of temperature sensors: %u\n\n", priv->temp_count); 1363 1364 for (u32 i = 0; i < priv->fan_count; i++) { 1365 fan = priv->fan_data[i]; 1366 1367 seq_printf(seq, "Fan %u:\n", i); 1368 seq_printf(seq, " ID: 0x%02x\n", fan->id); 1369 seq_printf(seq, " Related temperature sensors bitmap: %lu\n", 1370 fan->auto_channels_temp); 1371 } 1372 1373 seq_puts(seq, "\nTemperature sensor IDs:\n"); 1374 for_each_set_bit(bit, priv->temp_sensors, AWCC_ID_BITMAP_SIZE) 1375 seq_printf(seq, " 0x%02x\n", bit); 1376 1377 return 0; 1378 } 1379 1380 static int awcc_debugfs_pprof_data_read(struct seq_file *seq, void *data) 1381 { 1382 struct device *dev = seq->private; 1383 struct awcc_priv *priv = dev_get_drvdata(dev); 1384 1385 seq_printf(seq, "Number of thermal profiles: %u\n\n", priv->profile_count); 1386 1387 for (u32 i = 0; i < PLATFORM_PROFILE_LAST; i++) { 1388 if (!priv->supported_profiles[i]) 1389 continue; 1390 1391 seq_printf(seq, "Platform profile %u:\n", i); 1392 seq_printf(seq, " ID: 0x%02x\n", priv->supported_profiles[i]); 1393 } 1394 1395 return 0; 1396 } 1397 1398 static int awcc_gpio_pin_show(struct seq_file *seq, void *data) 1399 { 1400 unsigned long pin = debugfs_get_aux_num(seq->file); 1401 struct wmi_device *wdev = seq->private; 1402 u32 status; 1403 int ret; 1404 1405 ret = awcc_read_gpio_status(wdev, pin, &status); 1406 if (ret) 1407 return ret; 1408 1409 seq_printf(seq, "%u\n", status); 1410 1411 return 0; 1412 } 1413 1414 static ssize_t awcc_gpio_pin_write(struct file *file, const char __user *buf, 1415 size_t count, loff_t *ppos) 1416 { 1417 unsigned long pin = debugfs_get_aux_num(file); 1418 struct seq_file *seq = file->private_data; 1419 struct wmi_device *wdev = seq->private; 1420 bool status; 1421 int ret; 1422 1423 if (!ppos || *ppos) 1424 return -EINVAL; 1425 1426 ret = kstrtobool_from_user(buf, count, &status); 1427 if (ret) 1428 return ret; 1429 1430 ret = awcc_fwup_gpio_control(wdev, pin, status); 1431 if (ret) 1432 return ret; 1433 1434 return count; 1435 } 1436 1437 DEFINE_SHOW_STORE_ATTRIBUTE(awcc_gpio_pin); 1438 1439 static void awcc_debugfs_remove(void *data) 1440 { 1441 struct dentry *root = data; 1442 1443 debugfs_remove(root); 1444 } 1445 1446 static void awcc_debugfs_init(struct wmi_device *wdev) 1447 { 1448 struct awcc_priv *priv = dev_get_drvdata(&wdev->dev); 1449 struct dentry *root, *gpio_ctl; 1450 u32 gpio_count; 1451 char name[64]; 1452 int ret; 1453 1454 scnprintf(name, sizeof(name), "%s-%s", "alienware-wmi", dev_name(&wdev->dev)); 1455 root = debugfs_create_dir(name, NULL); 1456 1457 debugfs_create_devm_seqfile(&wdev->dev, "system_description", root, 1458 awcc_debugfs_system_description_read); 1459 1460 if (awcc->hwmon) 1461 debugfs_create_devm_seqfile(&wdev->dev, "hwmon_data", root, 1462 awcc_debugfs_hwmon_data_read); 1463 1464 if (awcc->pprof) 1465 debugfs_create_devm_seqfile(&wdev->dev, "pprof_data", root, 1466 awcc_debugfs_pprof_data_read); 1467 1468 ret = awcc_read_total_gpios(wdev, &gpio_count); 1469 if (ret) { 1470 dev_dbg(&wdev->dev, "Failed to get total GPIO Pin count\n"); 1471 goto out_add_action; 1472 } else if (gpio_count > AWCC_MAX_RES_COUNT) { 1473 dev_dbg(&wdev->dev, "Reported GPIO Pin count may be incorrect: %u\n", gpio_count); 1474 goto out_add_action; 1475 } 1476 1477 gpio_ctl = debugfs_create_dir("gpio_ctl", root); 1478 1479 priv->gpio_count = gpio_count; 1480 debugfs_create_u32("total_gpios", 0444, gpio_ctl, &priv->gpio_count); 1481 1482 for (unsigned int i = 0; i < gpio_count; i++) { 1483 scnprintf(name, sizeof(name), "pin%u", i); 1484 debugfs_create_file_aux_num(name, 0644, gpio_ctl, wdev, i, 1485 &awcc_gpio_pin_fops); 1486 } 1487 1488 out_add_action: 1489 devm_add_action_or_reset(&wdev->dev, awcc_debugfs_remove, root); 1490 } 1491 1492 static int alienware_awcc_setup(struct wmi_device *wdev) 1493 { 1494 struct awcc_priv *priv; 1495 int ret; 1496 1497 priv = devm_kzalloc(&wdev->dev, sizeof(*priv), GFP_KERNEL); 1498 if (!priv) 1499 return -ENOMEM; 1500 1501 ret = awcc_thermal_information(wdev, AWCC_OP_GET_SYSTEM_DESCRIPTION, 1502 0, &priv->system_description); 1503 if (ret < 0) 1504 return ret; 1505 1506 /* Sanity check */ 1507 for (unsigned int i = 0; i < ARRAY_SIZE(priv->res_count); i++) { 1508 if (priv->res_count[i] > AWCC_MAX_RES_COUNT) { 1509 dev_err(&wdev->dev, "Malformed system description: 0x%08x\n", 1510 priv->system_description); 1511 return -ENXIO; 1512 } 1513 } 1514 1515 priv->wdev = wdev; 1516 dev_set_drvdata(&wdev->dev, priv); 1517 1518 if (awcc->hwmon) { 1519 ret = awcc_hwmon_init(wdev); 1520 if (ret) 1521 return ret; 1522 } 1523 1524 if (awcc->pprof) { 1525 ret = awcc_platform_profile_init(wdev); 1526 if (ret) 1527 return ret; 1528 } 1529 1530 awcc_debugfs_init(wdev); 1531 1532 return 0; 1533 } 1534 1535 /* 1536 * WMAX WMI driver 1537 */ 1538 static int wmax_wmi_update_led(struct alienfx_priv *priv, 1539 struct wmi_device *wdev, u8 location) 1540 { 1541 struct wmax_led_args in_args = { 1542 .led_mask = 1 << location, 1543 .colors = priv->colors[location], 1544 .state = priv->lighting_control_state, 1545 }; 1546 1547 return alienware_wmi_command(wdev, WMAX_METHOD_ZONE_CONTROL, &in_args, 1548 sizeof(in_args), NULL); 1549 } 1550 1551 static int wmax_wmi_update_brightness(struct alienfx_priv *priv, 1552 struct wmi_device *wdev, u8 brightness) 1553 { 1554 struct wmax_brightness_args in_args = { 1555 .led_mask = 0xFF, 1556 .percentage = brightness, 1557 }; 1558 1559 return alienware_wmi_command(wdev, WMAX_METHOD_BRIGHTNESS, &in_args, 1560 sizeof(in_args), NULL); 1561 } 1562 1563 static int wmax_wmi_probe(struct wmi_device *wdev, const void *context) 1564 { 1565 struct alienfx_platdata pdata = { 1566 .wdev = wdev, 1567 .ops = { 1568 .upd_led = wmax_wmi_update_led, 1569 .upd_brightness = wmax_wmi_update_brightness, 1570 }, 1571 }; 1572 int ret; 1573 1574 if (awcc) 1575 ret = alienware_awcc_setup(wdev); 1576 else 1577 ret = alienware_alienfx_setup(&pdata); 1578 1579 return ret; 1580 } 1581 1582 static int wmax_wmi_suspend(struct device *dev) 1583 { 1584 if (awcc && awcc->hwmon) 1585 awcc_hwmon_suspend(dev); 1586 1587 return 0; 1588 } 1589 1590 static int wmax_wmi_resume(struct device *dev) 1591 { 1592 if (awcc && awcc->hwmon) 1593 awcc_hwmon_resume(dev); 1594 1595 return 0; 1596 } 1597 1598 static DEFINE_SIMPLE_DEV_PM_OPS(wmax_wmi_pm_ops, wmax_wmi_suspend, wmax_wmi_resume); 1599 1600 static const struct wmi_device_id alienware_wmax_device_id_table[] = { 1601 { WMAX_CONTROL_GUID, NULL }, 1602 { }, 1603 }; 1604 MODULE_DEVICE_TABLE(wmi, alienware_wmax_device_id_table); 1605 1606 static struct wmi_driver alienware_wmax_wmi_driver = { 1607 .driver = { 1608 .name = "alienware-wmi-wmax", 1609 .probe_type = PROBE_PREFER_ASYNCHRONOUS, 1610 .pm = pm_sleep_ptr(&wmax_wmi_pm_ops), 1611 }, 1612 .id_table = alienware_wmax_device_id_table, 1613 .probe = wmax_wmi_probe, 1614 .no_singleton = true, 1615 }; 1616 1617 int __init alienware_wmax_wmi_init(void) 1618 { 1619 const struct dmi_system_id *id; 1620 1621 id = dmi_first_match(awcc_dmi_table); 1622 if (id) 1623 awcc = id->driver_data; 1624 1625 if (force_hwmon) { 1626 if (!awcc) 1627 awcc = &empty_quirks; 1628 1629 awcc->hwmon = true; 1630 } 1631 1632 if (force_platform_profile) { 1633 if (!awcc) 1634 awcc = &empty_quirks; 1635 1636 awcc->pprof = true; 1637 } 1638 1639 if (force_gmode) { 1640 if (awcc) 1641 awcc->gmode = true; 1642 else 1643 pr_warn("force_gmode requires platform profile support\n"); 1644 } 1645 1646 return wmi_driver_register(&alienware_wmax_wmi_driver); 1647 } 1648 1649 void __exit alienware_wmax_wmi_exit(void) 1650 { 1651 wmi_driver_unregister(&alienware_wmax_wmi_driver); 1652 } 1653