59fff63cc2
Highlights: - asus-wmi: Support for screenpad and solve brightness key press duplication - int3472: Eliminate the last use of deprecated GPIO functions - mlxbf-pmc: New HW support - msi-ec: Support new EC configurations - thinkpad_acpi: Support reading aux MAC address during passthrough - wmi: Fixes & improvements - x86-android-tablets: Detection fix and avoid use of GPIO private APIs - Debug & metrics interface improvements - Miscellaneous cleanups / fixes / improvements The following is an automated shortlog grouped by driver: acer-wmi: - Remove void function return amd/hsmp: - add support for metrics tbl - create plat specific struct - Fix iomem handling - improve the error log amd/pmc: - Add dump_custom_stb module parameter - Add PMFW command id to support S2D force flush - Handle overflow cases where the num_samples range is higher - Use flex array when calling amd_pmc_stb_debugfs_open_v2() asus-wireless: - Replace open coded acpi_match_acpi_device() asus-wmi: - add support for ASUS screenpad - Do not report brightness up/down keys when also reported by acpi_video gpiolib: acpi: - Add a ignore interrupt quirk for Peaq C1010 - Check if a GPIO is listed in ignore_interrupt earlier hp-bioscfg: - Annotate struct bios_args with __counted_by inspur-platform-profile: - Add platform profile support int3472: - Add new skl_int3472_fill_gpiod_lookup() helper - Add new skl_int3472_gpiod_get_from_temp_lookup() helper - Stop using gpiod_toggle_active_low() - Switch to devm_get_gpiod() intel: bytcrc_pwrsrc: - Convert to platform remove callback returning void intel/ifs: - Add new CPU support - Add new error code - ARRAY BIST for Sierra Forest - Gen2 scan image loading - Gen2 Scan test support - Metadata validation for start_chunk - Refactor image loading code - Store IFS generation number - Validate image size intel_speed_select_if: - Remove hardcoded map size - Use devm_ioremap_resource intel/tpmi: - Add debugfs support for read/write blocked - Add defines to get version information intel-uncore-freq: - Ignore minor version change ISST: - Allow level 0 to be not present - Ignore minor version change - Use fuse enabled mask instead of allowed levels mellanox: - Fix misspelling error in routine name - Rename some init()/exit() functions for consistent naming mlxbf-bootctl: - Convert to platform remove callback returning void mlxbf-pmc: - Add support for BlueField-3 mlxbf-tmfifo: - Convert to platform remove callback returning void mlx-Convert to platform remove callback returning void: - mlx-Convert to platform remove callback returning void mlxreg-hotplug: - Convert to platform remove callback returning void mlxreg-io: - Convert to platform remove callback returning void mlxreg-lc: - Convert to platform remove callback returning void msi-ec: - Add more EC configs - rename fn_super_swap nvsw-sn2201: - Convert to platform remove callback returning void sel3350-Convert to platform remove callback returning void: - sel3350-Convert to platform remove callback returning void siemens: simatic-ipc-batt-apollolake: - Convert to platform remove callback returning void siemens: simatic-ipc-batt: - Convert to platform remove callback returning void siemens: simatic-ipc-batt-elkhartlake: - Convert to platform remove callback returning void siemens: simatic-ipc-batt-f7188x: - Convert to platform remove callback returning void siemens: simatic-ipc-batt: - Simplify simatic_ipc_batt_remove() surface: acpi-notify: - Convert to platform remove callback returning void surface: aggregator: - Annotate struct ssam_event with __counted_by surface: aggregator-cdev: - Convert to platform remove callback returning void surface: aggregator-registry: - Convert to platform remove callback returning void surface: dtx: - Convert to platform remove callback returning void surface: gpe: - Convert to platform remove callback returning void surface: hotplug: - Convert to platform remove callback returning void surface: surface3-wmi: - Convert to platform remove callback returning void think-lmi: - Add bulk save feature - Replace kstrdup() + strreplace() with kstrdup_and_replace() - Use strreplace() to replace a character by nul thinkpad_acpi: - Add battery quirk for Thinkpad X120e - replace deprecated strncpy with memcpy - sysfs interface to auxmac tools/power/x86/intel-speed-select: - Display error for core-power support - Increase max CPUs in one request - No TRL for non compute domains - Sanitize integer arguments - turbo-mode enable disable swapped - Update help for TRL - Use cgroup isolate for CPU 0 - v1.18 release wmi: - Decouple probe deferring from wmi_block_list - Decouple WMI device removal from wmi_block_list - Fix opening of char device - Fix probe failure when failing to register WMI devices - Fix refcounting of WMI devices in legacy functions x86-android-tablets: - Add a comment about x86_android_tablet_get_gpiod() - Create a platform_device from module_init() - Drop "linux,power-supply-name" from lenovo_yt3_bq25892_0_props[] - Fix Lenovo Yoga Tablet 2 830F/L vs 1050F/L detection - Remove invalid_aei_gpiochip from Peaq C1010 - Remove invalid_aei_gpiochip support - Stop using gpiolib private APIs - Use platform-device as gpio-keys parent xo15-ebook: - Replace open coded acpi_match_acpi_device() Merges: - Merge branch 'pdx86/platform-drivers-x86-int3472' into review-ilpo - Merge branch 'pdx86/platform-drivers-x86-mellanox-init' into review-ilpo - Merge remote-tracking branch 'intel-speed-select/intel-sst' into review-ilpo - Merge remote-tracking branch 'pdx86/platform-drivers-x86-android-tablets' into review-hans -----BEGIN PGP SIGNATURE----- iHUEABYIAB0WIQSCSUwRdwTNL2MhaBlZrE9hU+XOMQUCZT+lBwAKCRBZrE9hU+XO Mck0AQCFU7dYLCF4d1CXtHf1eZhSXLpYdhcO+C08JGGoM+MqSgD+Jyb9KJHk4pxE FvKG51I9neyAne9lvNrLodHRzxCYgAo= =duM8 -----END PGP SIGNATURE----- Merge tag 'platform-drivers-x86-v6.7-1' of git://git.kernel.org/pub/scm/linux/kernel/git/pdx86/platform-drivers-x86 Pull x86 platform driver updates from Ilpo Järvinen: - asus-wmi: Support for screenpad and solve brightness key press duplication - int3472: Eliminate the last use of deprecated GPIO functions - mlxbf-pmc: New HW support - msi-ec: Support new EC configurations - thinkpad_acpi: Support reading aux MAC address during passthrough - wmi: Fixes & improvements - x86-android-tablets: Detection fix and avoid use of GPIO private APIs - Debug & metrics interface improvements - Miscellaneous cleanups / fixes / improvements * tag 'platform-drivers-x86-v6.7-1' of git://git.kernel.org/pub/scm/linux/kernel/git/pdx86/platform-drivers-x86: (80 commits) platform/x86: inspur-platform-profile: Add platform profile support platform/x86: thinkpad_acpi: Add battery quirk for Thinkpad X120e platform/x86: wmi: Decouple WMI device removal from wmi_block_list platform/x86: wmi: Fix opening of char device platform/x86: wmi: Fix probe failure when failing to register WMI devices platform/x86: wmi: Fix refcounting of WMI devices in legacy functions platform/x86: wmi: Decouple probe deferring from wmi_block_list platform/x86/amd/hsmp: Fix iomem handling platform/x86: asus-wmi: Do not report brightness up/down keys when also reported by acpi_video platform/x86: thinkpad_acpi: replace deprecated strncpy with memcpy tools/power/x86/intel-speed-select: v1.18 release tools/power/x86/intel-speed-select: Use cgroup isolate for CPU 0 tools/power/x86/intel-speed-select: Increase max CPUs in one request tools/power/x86/intel-speed-select: Display error for core-power support tools/power/x86/intel-speed-select: No TRL for non compute domains tools/power/x86/intel-speed-select: turbo-mode enable disable swapped tools/power/x86/intel-speed-select: Update help for TRL tools/power/x86/intel-speed-select: Sanitize integer arguments platform/x86: acer-wmi: Remove void function return platform/x86/amd/pmc: Add dump_custom_stb module parameter ...
1364 lines
29 KiB
C
1364 lines
29 KiB
C
// SPDX-License-Identifier: GPL-2.0-or-later
|
|
|
|
/*
|
|
* msi-ec: MSI laptops' embedded controller driver.
|
|
*
|
|
* This driver allows various MSI laptops' functionalities to be
|
|
* controlled from userspace.
|
|
*
|
|
* It contains EC memory configurations for different firmware versions
|
|
* and exports battery charge thresholds to userspace.
|
|
*
|
|
* Copyright (C) 2023 Jose Angel Pastrana <japp0005@red.ujaen.es>
|
|
* Copyright (C) 2023 Aakash Singh <mail@singhaakash.dev>
|
|
* Copyright (C) 2023 Nikita Kravets <teackot@gmail.com>
|
|
*/
|
|
|
|
#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
|
|
|
|
#include "msi-ec.h"
|
|
|
|
#include <acpi/battery.h>
|
|
#include <linux/acpi.h>
|
|
#include <linux/init.h>
|
|
#include <linux/kernel.h>
|
|
#include <linux/module.h>
|
|
#include <linux/platform_device.h>
|
|
#include <linux/seq_file.h>
|
|
#include <linux/string.h>
|
|
|
|
#define SM_ECO_NAME "eco"
|
|
#define SM_COMFORT_NAME "comfort"
|
|
#define SM_SPORT_NAME "sport"
|
|
#define SM_TURBO_NAME "turbo"
|
|
|
|
#define FM_AUTO_NAME "auto"
|
|
#define FM_SILENT_NAME "silent"
|
|
#define FM_BASIC_NAME "basic"
|
|
#define FM_ADVANCED_NAME "advanced"
|
|
|
|
static const char * const ALLOWED_FW_0[] __initconst = {
|
|
"14C1EMS1.012",
|
|
"14C1EMS1.101",
|
|
"14C1EMS1.102",
|
|
NULL
|
|
};
|
|
|
|
static struct msi_ec_conf CONF0 __initdata = {
|
|
.allowed_fw = ALLOWED_FW_0,
|
|
.charge_control = {
|
|
.address = 0xef,
|
|
.offset_start = 0x8a,
|
|
.offset_end = 0x80,
|
|
.range_min = 0x8a,
|
|
.range_max = 0xe4,
|
|
},
|
|
.webcam = {
|
|
.address = 0x2e,
|
|
.block_address = 0x2f,
|
|
.bit = 1,
|
|
},
|
|
.fn_win_swap = {
|
|
.address = 0xbf,
|
|
.bit = 4,
|
|
},
|
|
.cooler_boost = {
|
|
.address = 0x98,
|
|
.bit = 7,
|
|
},
|
|
.shift_mode = {
|
|
.address = 0xf2,
|
|
.modes = {
|
|
{ SM_ECO_NAME, 0xc2 },
|
|
{ SM_COMFORT_NAME, 0xc1 },
|
|
{ SM_SPORT_NAME, 0xc0 },
|
|
MSI_EC_MODE_NULL
|
|
},
|
|
},
|
|
.super_battery = {
|
|
.address = MSI_EC_ADDR_UNKNOWN, // 0xd5 needs testing
|
|
},
|
|
.fan_mode = {
|
|
.address = 0xf4,
|
|
.modes = {
|
|
{ FM_AUTO_NAME, 0x0d },
|
|
{ FM_SILENT_NAME, 0x1d },
|
|
{ FM_BASIC_NAME, 0x4d },
|
|
{ FM_ADVANCED_NAME, 0x8d },
|
|
MSI_EC_MODE_NULL
|
|
},
|
|
},
|
|
.cpu = {
|
|
.rt_temp_address = 0x68,
|
|
.rt_fan_speed_address = 0x71,
|
|
.rt_fan_speed_base_min = 0x19,
|
|
.rt_fan_speed_base_max = 0x37,
|
|
.bs_fan_speed_address = 0x89,
|
|
.bs_fan_speed_base_min = 0x00,
|
|
.bs_fan_speed_base_max = 0x0f,
|
|
},
|
|
.gpu = {
|
|
.rt_temp_address = 0x80,
|
|
.rt_fan_speed_address = 0x89,
|
|
},
|
|
.leds = {
|
|
.micmute_led_address = 0x2b,
|
|
.mute_led_address = 0x2c,
|
|
.bit = 2,
|
|
},
|
|
.kbd_bl = {
|
|
.bl_mode_address = 0x2c, // ?
|
|
.bl_modes = { 0x00, 0x08 }, // ?
|
|
.max_mode = 1, // ?
|
|
.bl_state_address = 0xf3,
|
|
.state_base_value = 0x80,
|
|
.max_state = 3,
|
|
},
|
|
};
|
|
|
|
static const char * const ALLOWED_FW_1[] __initconst = {
|
|
"17F2EMS1.103",
|
|
"17F2EMS1.104",
|
|
"17F2EMS1.106",
|
|
"17F2EMS1.107",
|
|
NULL
|
|
};
|
|
|
|
static struct msi_ec_conf CONF1 __initdata = {
|
|
.allowed_fw = ALLOWED_FW_1,
|
|
.charge_control = {
|
|
.address = 0xef,
|
|
.offset_start = 0x8a,
|
|
.offset_end = 0x80,
|
|
.range_min = 0x8a,
|
|
.range_max = 0xe4,
|
|
},
|
|
.webcam = {
|
|
.address = 0x2e,
|
|
.block_address = 0x2f,
|
|
.bit = 1,
|
|
},
|
|
.fn_win_swap = {
|
|
.address = 0xbf,
|
|
.bit = 4,
|
|
},
|
|
.cooler_boost = {
|
|
.address = 0x98,
|
|
.bit = 7,
|
|
},
|
|
.shift_mode = {
|
|
.address = 0xf2,
|
|
.modes = {
|
|
{ SM_ECO_NAME, 0xc2 },
|
|
{ SM_COMFORT_NAME, 0xc1 },
|
|
{ SM_SPORT_NAME, 0xc0 },
|
|
{ SM_TURBO_NAME, 0xc4 },
|
|
MSI_EC_MODE_NULL
|
|
},
|
|
},
|
|
.super_battery = {
|
|
.address = MSI_EC_ADDR_UNKNOWN,
|
|
},
|
|
.fan_mode = {
|
|
.address = 0xf4,
|
|
.modes = {
|
|
{ FM_AUTO_NAME, 0x0d },
|
|
{ FM_BASIC_NAME, 0x4d },
|
|
{ FM_ADVANCED_NAME, 0x8d },
|
|
MSI_EC_MODE_NULL
|
|
},
|
|
},
|
|
.cpu = {
|
|
.rt_temp_address = 0x68,
|
|
.rt_fan_speed_address = 0x71,
|
|
.rt_fan_speed_base_min = 0x19,
|
|
.rt_fan_speed_base_max = 0x37,
|
|
.bs_fan_speed_address = 0x89,
|
|
.bs_fan_speed_base_min = 0x00,
|
|
.bs_fan_speed_base_max = 0x0f,
|
|
},
|
|
.gpu = {
|
|
.rt_temp_address = 0x80,
|
|
.rt_fan_speed_address = 0x89,
|
|
},
|
|
.leds = {
|
|
.micmute_led_address = 0x2b,
|
|
.mute_led_address = 0x2c,
|
|
.bit = 2,
|
|
},
|
|
.kbd_bl = {
|
|
.bl_mode_address = 0x2c, // ?
|
|
.bl_modes = { 0x00, 0x08 }, // ?
|
|
.max_mode = 1, // ?
|
|
.bl_state_address = 0xf3,
|
|
.state_base_value = 0x80,
|
|
.max_state = 3,
|
|
},
|
|
};
|
|
|
|
static const char * const ALLOWED_FW_2[] __initconst = {
|
|
"1552EMS1.118",
|
|
NULL
|
|
};
|
|
|
|
static struct msi_ec_conf CONF2 __initdata = {
|
|
.allowed_fw = ALLOWED_FW_2,
|
|
.charge_control = {
|
|
.address = 0xd7,
|
|
.offset_start = 0x8a,
|
|
.offset_end = 0x80,
|
|
.range_min = 0x8a,
|
|
.range_max = 0xe4,
|
|
},
|
|
.webcam = {
|
|
.address = 0x2e,
|
|
.block_address = 0x2f,
|
|
.bit = 1,
|
|
},
|
|
.fn_win_swap = {
|
|
.address = 0xe8,
|
|
.bit = 4,
|
|
},
|
|
.cooler_boost = {
|
|
.address = 0x98,
|
|
.bit = 7,
|
|
},
|
|
.shift_mode = {
|
|
.address = 0xf2,
|
|
.modes = {
|
|
{ SM_ECO_NAME, 0xc2 },
|
|
{ SM_COMFORT_NAME, 0xc1 },
|
|
{ SM_SPORT_NAME, 0xc0 },
|
|
MSI_EC_MODE_NULL
|
|
},
|
|
},
|
|
.super_battery = {
|
|
.address = 0xeb,
|
|
.mask = 0x0f,
|
|
},
|
|
.fan_mode = {
|
|
.address = 0xd4,
|
|
.modes = {
|
|
{ FM_AUTO_NAME, 0x0d },
|
|
{ FM_SILENT_NAME, 0x1d },
|
|
{ FM_BASIC_NAME, 0x4d },
|
|
{ FM_ADVANCED_NAME, 0x8d },
|
|
MSI_EC_MODE_NULL
|
|
},
|
|
},
|
|
.cpu = {
|
|
.rt_temp_address = 0x68,
|
|
.rt_fan_speed_address = 0x71,
|
|
.rt_fan_speed_base_min = 0x19,
|
|
.rt_fan_speed_base_max = 0x37,
|
|
.bs_fan_speed_address = 0x89,
|
|
.bs_fan_speed_base_min = 0x00,
|
|
.bs_fan_speed_base_max = 0x0f,
|
|
},
|
|
.gpu = {
|
|
.rt_temp_address = 0x80,
|
|
.rt_fan_speed_address = 0x89,
|
|
},
|
|
.leds = {
|
|
.micmute_led_address = 0x2c,
|
|
.mute_led_address = 0x2d,
|
|
.bit = 1,
|
|
},
|
|
.kbd_bl = {
|
|
.bl_mode_address = 0x2c, // ?
|
|
.bl_modes = { 0x00, 0x08 }, // ?
|
|
.max_mode = 1, // ?
|
|
.bl_state_address = 0xd3,
|
|
.state_base_value = 0x80,
|
|
.max_state = 3,
|
|
},
|
|
};
|
|
|
|
static const char * const ALLOWED_FW_3[] __initconst = {
|
|
"1592EMS1.111",
|
|
NULL
|
|
};
|
|
|
|
static struct msi_ec_conf CONF3 __initdata = {
|
|
.allowed_fw = ALLOWED_FW_3,
|
|
.charge_control = {
|
|
.address = 0xd7,
|
|
.offset_start = 0x8a,
|
|
.offset_end = 0x80,
|
|
.range_min = 0x8a,
|
|
.range_max = 0xe4,
|
|
},
|
|
.webcam = {
|
|
.address = 0x2e,
|
|
.block_address = 0x2f,
|
|
.bit = 1,
|
|
},
|
|
.fn_win_swap = {
|
|
.address = 0xe8,
|
|
.bit = 4,
|
|
},
|
|
.cooler_boost = {
|
|
.address = 0x98,
|
|
.bit = 7,
|
|
},
|
|
.shift_mode = {
|
|
.address = 0xd2,
|
|
.modes = {
|
|
{ SM_ECO_NAME, 0xc2 },
|
|
{ SM_COMFORT_NAME, 0xc1 },
|
|
{ SM_SPORT_NAME, 0xc0 },
|
|
MSI_EC_MODE_NULL
|
|
},
|
|
},
|
|
.super_battery = {
|
|
.address = 0xeb,
|
|
.mask = 0x0f,
|
|
},
|
|
.fan_mode = {
|
|
.address = 0xd4,
|
|
.modes = {
|
|
{ FM_AUTO_NAME, 0x0d },
|
|
{ FM_SILENT_NAME, 0x1d },
|
|
{ FM_BASIC_NAME, 0x4d },
|
|
{ FM_ADVANCED_NAME, 0x8d },
|
|
MSI_EC_MODE_NULL
|
|
},
|
|
},
|
|
.cpu = {
|
|
.rt_temp_address = 0x68,
|
|
.rt_fan_speed_address = 0xc9,
|
|
.rt_fan_speed_base_min = 0x19,
|
|
.rt_fan_speed_base_max = 0x37,
|
|
.bs_fan_speed_address = 0x89, // ?
|
|
.bs_fan_speed_base_min = 0x00,
|
|
.bs_fan_speed_base_max = 0x0f,
|
|
},
|
|
.gpu = {
|
|
.rt_temp_address = 0x80,
|
|
.rt_fan_speed_address = 0x89,
|
|
},
|
|
.leds = {
|
|
.micmute_led_address = 0x2b,
|
|
.mute_led_address = 0x2c,
|
|
.bit = 1,
|
|
},
|
|
.kbd_bl = {
|
|
.bl_mode_address = 0x2c, // ?
|
|
.bl_modes = { 0x00, 0x08 }, // ?
|
|
.max_mode = 1, // ?
|
|
.bl_state_address = 0xd3,
|
|
.state_base_value = 0x80,
|
|
.max_state = 3,
|
|
},
|
|
};
|
|
|
|
static const char * const ALLOWED_FW_4[] __initconst = {
|
|
"16V4EMS1.114",
|
|
NULL
|
|
};
|
|
|
|
static struct msi_ec_conf CONF4 __initdata = {
|
|
.allowed_fw = ALLOWED_FW_4,
|
|
.charge_control = {
|
|
.address = 0xd7,
|
|
.offset_start = 0x8a,
|
|
.offset_end = 0x80,
|
|
.range_min = 0x8a,
|
|
.range_max = 0xe4,
|
|
},
|
|
.webcam = {
|
|
.address = 0x2e,
|
|
.block_address = 0x2f,
|
|
.bit = 1,
|
|
},
|
|
.fn_win_swap = {
|
|
.address = MSI_EC_ADDR_UNKNOWN, // supported, but unknown
|
|
.bit = 4,
|
|
},
|
|
.cooler_boost = {
|
|
.address = 0x98,
|
|
.bit = 7,
|
|
},
|
|
.shift_mode = {
|
|
.address = 0xd2,
|
|
.modes = {
|
|
{ SM_ECO_NAME, 0xc2 },
|
|
{ SM_COMFORT_NAME, 0xc1 },
|
|
{ SM_SPORT_NAME, 0xc0 },
|
|
MSI_EC_MODE_NULL
|
|
},
|
|
},
|
|
.super_battery = { // may be supported, but address is unknown
|
|
.address = MSI_EC_ADDR_UNKNOWN,
|
|
.mask = 0x0f,
|
|
},
|
|
.fan_mode = {
|
|
.address = 0xd4,
|
|
.modes = {
|
|
{ FM_AUTO_NAME, 0x0d },
|
|
{ FM_SILENT_NAME, 0x1d },
|
|
{ FM_ADVANCED_NAME, 0x8d },
|
|
MSI_EC_MODE_NULL
|
|
},
|
|
},
|
|
.cpu = {
|
|
.rt_temp_address = 0x68, // needs testing
|
|
.rt_fan_speed_address = 0x71, // needs testing
|
|
.rt_fan_speed_base_min = 0x19,
|
|
.rt_fan_speed_base_max = 0x37,
|
|
.bs_fan_speed_address = MSI_EC_ADDR_UNKNOWN,
|
|
.bs_fan_speed_base_min = 0x00,
|
|
.bs_fan_speed_base_max = 0x0f,
|
|
},
|
|
.gpu = {
|
|
.rt_temp_address = 0x80,
|
|
.rt_fan_speed_address = MSI_EC_ADDR_UNKNOWN,
|
|
},
|
|
.leds = {
|
|
.micmute_led_address = MSI_EC_ADDR_UNKNOWN,
|
|
.mute_led_address = MSI_EC_ADDR_UNKNOWN,
|
|
.bit = 1,
|
|
},
|
|
.kbd_bl = {
|
|
.bl_mode_address = MSI_EC_ADDR_UNKNOWN, // ?
|
|
.bl_modes = { 0x00, 0x08 }, // ?
|
|
.max_mode = 1, // ?
|
|
.bl_state_address = MSI_EC_ADDR_UNSUPP, // 0xd3, not functional
|
|
.state_base_value = 0x80,
|
|
.max_state = 3,
|
|
},
|
|
};
|
|
|
|
static const char * const ALLOWED_FW_5[] __initconst = {
|
|
"158LEMS1.103",
|
|
"158LEMS1.105",
|
|
"158LEMS1.106",
|
|
NULL
|
|
};
|
|
|
|
static struct msi_ec_conf CONF5 __initdata = {
|
|
.allowed_fw = ALLOWED_FW_5,
|
|
.charge_control = {
|
|
.address = 0xef,
|
|
.offset_start = 0x8a,
|
|
.offset_end = 0x80,
|
|
.range_min = 0x8a,
|
|
.range_max = 0xe4,
|
|
},
|
|
.webcam = {
|
|
.address = 0x2e,
|
|
.block_address = 0x2f,
|
|
.bit = 1,
|
|
},
|
|
.fn_win_swap = { // todo: reverse
|
|
.address = 0xbf,
|
|
.bit = 4,
|
|
},
|
|
.cooler_boost = {
|
|
.address = 0x98,
|
|
.bit = 7,
|
|
},
|
|
.shift_mode = {
|
|
.address = 0xf2,
|
|
.modes = {
|
|
{ SM_ECO_NAME, 0xc2 },
|
|
{ SM_COMFORT_NAME, 0xc1 },
|
|
{ SM_TURBO_NAME, 0xc4 },
|
|
MSI_EC_MODE_NULL
|
|
},
|
|
},
|
|
.super_battery = { // unsupported?
|
|
.address = MSI_EC_ADDR_UNKNOWN,
|
|
.mask = 0x0f,
|
|
},
|
|
.fan_mode = {
|
|
.address = 0xf4,
|
|
.modes = {
|
|
{ FM_AUTO_NAME, 0x0d },
|
|
{ FM_SILENT_NAME, 0x1d },
|
|
{ FM_ADVANCED_NAME, 0x8d },
|
|
MSI_EC_MODE_NULL
|
|
},
|
|
},
|
|
.cpu = {
|
|
.rt_temp_address = 0x68, // needs testing
|
|
.rt_fan_speed_address = 0x71, // needs testing
|
|
.rt_fan_speed_base_min = 0x19,
|
|
.rt_fan_speed_base_max = 0x37,
|
|
.bs_fan_speed_address = MSI_EC_ADDR_UNSUPP,
|
|
.bs_fan_speed_base_min = 0x00,
|
|
.bs_fan_speed_base_max = 0x0f,
|
|
},
|
|
.gpu = {
|
|
.rt_temp_address = MSI_EC_ADDR_UNKNOWN,
|
|
.rt_fan_speed_address = MSI_EC_ADDR_UNKNOWN,
|
|
},
|
|
.leds = {
|
|
.micmute_led_address = 0x2b,
|
|
.mute_led_address = 0x2c,
|
|
.bit = 2,
|
|
},
|
|
.kbd_bl = {
|
|
.bl_mode_address = MSI_EC_ADDR_UNKNOWN, // ?
|
|
.bl_modes = { 0x00, 0x08 }, // ?
|
|
.max_mode = 1, // ?
|
|
.bl_state_address = MSI_EC_ADDR_UNSUPP, // 0xf3, not functional
|
|
.state_base_value = 0x80,
|
|
.max_state = 3,
|
|
},
|
|
};
|
|
|
|
static const char * const ALLOWED_FW_6[] __initconst = {
|
|
"1542EMS1.102",
|
|
"1542EMS1.104",
|
|
NULL
|
|
};
|
|
|
|
static struct msi_ec_conf CONF6 __initdata = {
|
|
.allowed_fw = ALLOWED_FW_6,
|
|
.charge_control = {
|
|
.address = 0xef,
|
|
.offset_start = 0x8a,
|
|
.offset_end = 0x80,
|
|
.range_min = 0x8a,
|
|
.range_max = 0xe4,
|
|
},
|
|
.webcam = {
|
|
.address = 0x2e,
|
|
.block_address = MSI_EC_ADDR_UNSUPP,
|
|
.bit = 1,
|
|
},
|
|
.fn_win_swap = {
|
|
.address = 0xbf, // todo: reverse
|
|
.bit = 4,
|
|
},
|
|
.cooler_boost = {
|
|
.address = 0x98,
|
|
.bit = 7,
|
|
},
|
|
.shift_mode = {
|
|
.address = 0xf2,
|
|
.modes = {
|
|
{ SM_ECO_NAME, 0xc2 },
|
|
{ SM_COMFORT_NAME, 0xc1 },
|
|
{ SM_SPORT_NAME, 0xc0 },
|
|
{ SM_TURBO_NAME, 0xc4 },
|
|
MSI_EC_MODE_NULL
|
|
},
|
|
},
|
|
.super_battery = {
|
|
.address = 0xd5,
|
|
.mask = 0x0f,
|
|
},
|
|
.fan_mode = {
|
|
.address = 0xf4,
|
|
.modes = {
|
|
{ FM_AUTO_NAME, 0x0d },
|
|
{ FM_SILENT_NAME, 0x1d },
|
|
{ FM_ADVANCED_NAME, 0x8d },
|
|
MSI_EC_MODE_NULL
|
|
},
|
|
},
|
|
.cpu = {
|
|
.rt_temp_address = 0x68,
|
|
.rt_fan_speed_address = 0xc9,
|
|
.rt_fan_speed_base_min = 0x19,
|
|
.rt_fan_speed_base_max = 0x37,
|
|
.bs_fan_speed_address = MSI_EC_ADDR_UNSUPP,
|
|
.bs_fan_speed_base_min = 0x00,
|
|
.bs_fan_speed_base_max = 0x0f,
|
|
},
|
|
.gpu = {
|
|
.rt_temp_address = 0x80,
|
|
.rt_fan_speed_address = MSI_EC_ADDR_UNKNOWN,
|
|
},
|
|
.leds = {
|
|
.micmute_led_address = MSI_EC_ADDR_UNSUPP,
|
|
.mute_led_address = MSI_EC_ADDR_UNSUPP,
|
|
.bit = 2,
|
|
},
|
|
.kbd_bl = {
|
|
.bl_mode_address = MSI_EC_ADDR_UNKNOWN, // ?
|
|
.bl_modes = { 0x00, 0x08 }, // ?
|
|
.max_mode = 1, // ?
|
|
.bl_state_address = MSI_EC_ADDR_UNSUPP, // 0xf3, not functional
|
|
.state_base_value = 0x80,
|
|
.max_state = 3,
|
|
},
|
|
};
|
|
|
|
static const char * const ALLOWED_FW_7[] __initconst = {
|
|
"17FKEMS1.108",
|
|
"17FKEMS1.109",
|
|
"17FKEMS1.10A",
|
|
NULL
|
|
};
|
|
|
|
static struct msi_ec_conf CONF7 __initdata = {
|
|
.allowed_fw = ALLOWED_FW_7,
|
|
.charge_control = {
|
|
.address = 0xef,
|
|
.offset_start = 0x8a,
|
|
.offset_end = 0x80,
|
|
.range_min = 0x8a,
|
|
.range_max = 0xe4,
|
|
},
|
|
.webcam = {
|
|
.address = 0x2e,
|
|
.block_address = MSI_EC_ADDR_UNSUPP,
|
|
.bit = 1,
|
|
},
|
|
.fn_win_swap = {
|
|
.address = 0xbf, // needs testing
|
|
.bit = 4,
|
|
},
|
|
.cooler_boost = {
|
|
.address = 0x98,
|
|
.bit = 7,
|
|
},
|
|
.shift_mode = {
|
|
.address = 0xf2,
|
|
.modes = {
|
|
{ SM_ECO_NAME, 0xc2 },
|
|
{ SM_COMFORT_NAME, 0xc1 },
|
|
{ SM_SPORT_NAME, 0xc0 },
|
|
{ SM_TURBO_NAME, 0xc4 },
|
|
MSI_EC_MODE_NULL
|
|
},
|
|
},
|
|
.super_battery = {
|
|
.address = MSI_EC_ADDR_UNKNOWN, // 0xd5 but has its own wet of modes
|
|
.mask = 0x0f,
|
|
},
|
|
.fan_mode = {
|
|
.address = 0xf4,
|
|
.modes = {
|
|
{ FM_AUTO_NAME, 0x0d }, // d may not be relevant
|
|
{ FM_SILENT_NAME, 0x1d },
|
|
{ FM_ADVANCED_NAME, 0x8d },
|
|
MSI_EC_MODE_NULL
|
|
},
|
|
},
|
|
.cpu = {
|
|
.rt_temp_address = 0x68,
|
|
.rt_fan_speed_address = 0xc9, // needs testing
|
|
.rt_fan_speed_base_min = 0x19,
|
|
.rt_fan_speed_base_max = 0x37,
|
|
.bs_fan_speed_address = MSI_EC_ADDR_UNSUPP,
|
|
.bs_fan_speed_base_min = 0x00,
|
|
.bs_fan_speed_base_max = 0x0f,
|
|
},
|
|
.gpu = {
|
|
.rt_temp_address = MSI_EC_ADDR_UNKNOWN,
|
|
.rt_fan_speed_address = MSI_EC_ADDR_UNKNOWN,
|
|
},
|
|
.leds = {
|
|
.micmute_led_address = MSI_EC_ADDR_UNSUPP,
|
|
.mute_led_address = 0x2c,
|
|
.bit = 2,
|
|
},
|
|
.kbd_bl = {
|
|
.bl_mode_address = MSI_EC_ADDR_UNKNOWN, // ?
|
|
.bl_modes = { 0x00, 0x08 }, // ?
|
|
.max_mode = 1, // ?
|
|
.bl_state_address = 0xf3,
|
|
.state_base_value = 0x80,
|
|
.max_state = 3,
|
|
},
|
|
};
|
|
|
|
static const char * const ALLOWED_FW_8[] __initconst = {
|
|
"14F1EMS1.115",
|
|
NULL
|
|
};
|
|
|
|
static struct msi_ec_conf CONF8 __initdata = {
|
|
.allowed_fw = ALLOWED_FW_8,
|
|
.charge_control = {
|
|
.address = 0xd7,
|
|
.offset_start = 0x8a,
|
|
.offset_end = 0x80,
|
|
.range_min = 0x8a,
|
|
.range_max = 0xe4,
|
|
},
|
|
.webcam = {
|
|
.address = 0x2e,
|
|
.block_address = MSI_EC_ADDR_UNSUPP,
|
|
.bit = 1,
|
|
},
|
|
.fn_win_swap = {
|
|
.address = 0xe8,
|
|
.bit = 4,
|
|
},
|
|
.cooler_boost = {
|
|
.address = 0x98,
|
|
.bit = 7,
|
|
},
|
|
.shift_mode = {
|
|
.address = 0xd2,
|
|
.modes = {
|
|
{ SM_ECO_NAME, 0xc2 },
|
|
{ SM_COMFORT_NAME, 0xc1 },
|
|
{ SM_SPORT_NAME, 0xc0 },
|
|
MSI_EC_MODE_NULL
|
|
},
|
|
},
|
|
.super_battery = {
|
|
.address = 0xeb,
|
|
.mask = 0x0f,
|
|
},
|
|
.fan_mode = {
|
|
.address = 0xd4,
|
|
.modes = {
|
|
{ FM_AUTO_NAME, 0x0d },
|
|
{ FM_SILENT_NAME, 0x1d },
|
|
{ FM_BASIC_NAME, 0x4d },
|
|
MSI_EC_MODE_NULL
|
|
},
|
|
},
|
|
.cpu = {
|
|
.rt_temp_address = 0x68,
|
|
.rt_fan_speed_address = 0x71,
|
|
.rt_fan_speed_base_min = 0x19,
|
|
.rt_fan_speed_base_max = 0x37,
|
|
.bs_fan_speed_address = MSI_EC_ADDR_UNSUPP,
|
|
.bs_fan_speed_base_min = 0x00,
|
|
.bs_fan_speed_base_max = 0x0f,
|
|
},
|
|
.gpu = {
|
|
.rt_temp_address = MSI_EC_ADDR_UNKNOWN,
|
|
.rt_fan_speed_address = MSI_EC_ADDR_UNKNOWN,
|
|
},
|
|
.leds = {
|
|
.micmute_led_address = MSI_EC_ADDR_UNSUPP,
|
|
.mute_led_address = 0x2d,
|
|
.bit = 1,
|
|
},
|
|
.kbd_bl = {
|
|
.bl_mode_address = MSI_EC_ADDR_UNKNOWN, // ?
|
|
.bl_modes = { 0x00, 0x08 }, // ?
|
|
.max_mode = 1, // ?
|
|
.bl_state_address = MSI_EC_ADDR_UNSUPP, // not functional
|
|
.state_base_value = 0x80,
|
|
.max_state = 3,
|
|
},
|
|
};
|
|
|
|
static const char * const ALLOWED_FW_9[] __initconst = {
|
|
"14JKEMS1.104",
|
|
NULL
|
|
};
|
|
|
|
static struct msi_ec_conf CONF9 __initdata = {
|
|
.allowed_fw = ALLOWED_FW_9,
|
|
.charge_control = {
|
|
.address = 0xef,
|
|
.offset_start = 0x8a,
|
|
.offset_end = 0x80,
|
|
.range_min = 0x8a,
|
|
.range_max = 0xe4,
|
|
},
|
|
.webcam = {
|
|
.address = 0x2e,
|
|
.block_address = 0x2f,
|
|
.bit = 1,
|
|
},
|
|
.fn_win_swap = {
|
|
.address = 0xbf,
|
|
.bit = 4,
|
|
},
|
|
.cooler_boost = {
|
|
.address = 0x98,
|
|
.bit = 7,
|
|
},
|
|
.shift_mode = {
|
|
.address = 0xf2,
|
|
.modes = {
|
|
{ SM_ECO_NAME, 0xc2 },
|
|
{ SM_COMFORT_NAME, 0xc1 },
|
|
{ SM_SPORT_NAME, 0xc0 },
|
|
MSI_EC_MODE_NULL
|
|
},
|
|
},
|
|
.super_battery = {
|
|
.address = MSI_EC_ADDR_UNSUPP, // unsupported or enabled by ECO shift
|
|
.mask = 0x0f,
|
|
},
|
|
.fan_mode = {
|
|
.address = 0xf4,
|
|
.modes = {
|
|
{ FM_AUTO_NAME, 0x0d },
|
|
{ FM_SILENT_NAME, 0x1d },
|
|
{ FM_ADVANCED_NAME, 0x8d },
|
|
MSI_EC_MODE_NULL
|
|
},
|
|
},
|
|
.cpu = {
|
|
.rt_temp_address = 0x68,
|
|
.rt_fan_speed_address = 0x71,
|
|
.rt_fan_speed_base_min = 0x00,
|
|
.rt_fan_speed_base_max = 0x96,
|
|
.bs_fan_speed_address = MSI_EC_ADDR_UNSUPP,
|
|
.bs_fan_speed_base_min = 0x00,
|
|
.bs_fan_speed_base_max = 0x0f,
|
|
},
|
|
.gpu = {
|
|
.rt_temp_address = MSI_EC_ADDR_UNSUPP,
|
|
.rt_fan_speed_address = MSI_EC_ADDR_UNSUPP,
|
|
},
|
|
.leds = {
|
|
.micmute_led_address = 0x2b,
|
|
.mute_led_address = 0x2c,
|
|
.bit = 2,
|
|
},
|
|
.kbd_bl = {
|
|
.bl_mode_address = MSI_EC_ADDR_UNSUPP, // not presented in MSI app
|
|
.bl_modes = { 0x00, 0x08 },
|
|
.max_mode = 1,
|
|
.bl_state_address = 0xf3,
|
|
.state_base_value = 0x80,
|
|
.max_state = 3,
|
|
},
|
|
};
|
|
|
|
static const char * const ALLOWED_FW_10[] __initconst = {
|
|
"1582EMS1.107", // GF66 11UC
|
|
NULL
|
|
};
|
|
|
|
static struct msi_ec_conf CONF10 __initdata = {
|
|
.allowed_fw = ALLOWED_FW_10,
|
|
.charge_control = {
|
|
.address = 0xd7,
|
|
.offset_start = 0x8a,
|
|
.offset_end = 0x80,
|
|
.range_min = 0x8a,
|
|
.range_max = 0xe4,
|
|
},
|
|
.webcam = {
|
|
.address = 0x2e,
|
|
.block_address = 0x2f,
|
|
.bit = 1,
|
|
},
|
|
.fn_win_swap = {
|
|
.address = MSI_EC_ADDR_UNSUPP,
|
|
.bit = 4,
|
|
},
|
|
.cooler_boost = {
|
|
.address = 0x98,
|
|
.bit = 7,
|
|
},
|
|
.shift_mode = {
|
|
.address = 0xd2,
|
|
.modes = {
|
|
{ SM_ECO_NAME, 0xc2 },
|
|
{ SM_COMFORT_NAME, 0xc1 },
|
|
{ SM_SPORT_NAME, 0xc0 },
|
|
{ SM_TURBO_NAME, 0xc4 },
|
|
MSI_EC_MODE_NULL
|
|
},
|
|
},
|
|
.super_battery = {
|
|
.address = 0xe5,
|
|
.mask = 0x0f,
|
|
},
|
|
.fan_mode = {
|
|
.address = 0xd4,
|
|
.modes = {
|
|
{ FM_AUTO_NAME, 0x0d },
|
|
{ FM_SILENT_NAME, 0x1d },
|
|
{ FM_ADVANCED_NAME, 0x8d },
|
|
MSI_EC_MODE_NULL
|
|
},
|
|
},
|
|
.cpu = {
|
|
.rt_temp_address = 0x68,
|
|
.rt_fan_speed_address = 0x71, // ?
|
|
.rt_fan_speed_base_min = 0x19,
|
|
.rt_fan_speed_base_max = 0x37,
|
|
.bs_fan_speed_address = MSI_EC_ADDR_UNKNOWN, // ?
|
|
.bs_fan_speed_base_min = 0x00,
|
|
.bs_fan_speed_base_max = 0x0f,
|
|
},
|
|
.gpu = {
|
|
.rt_temp_address = 0x80,
|
|
.rt_fan_speed_address = 0x89,
|
|
},
|
|
.leds = {
|
|
.micmute_led_address = 0x2c,
|
|
.mute_led_address = 0x2d,
|
|
.bit = 1,
|
|
},
|
|
.kbd_bl = {
|
|
.bl_mode_address = 0x2c,
|
|
.bl_modes = { 0x00, 0x08 },
|
|
.max_mode = 1,
|
|
.bl_state_address = 0xd3,
|
|
.state_base_value = 0x80,
|
|
.max_state = 3,
|
|
},
|
|
};
|
|
|
|
static const char * const ALLOWED_FW_11[] __initconst = {
|
|
"16S6EMS1.111", // Prestige 15 a11scx
|
|
"1552EMS1.115", // Modern 15 a11m
|
|
NULL
|
|
};
|
|
|
|
static struct msi_ec_conf CONF11 __initdata = {
|
|
.allowed_fw = ALLOWED_FW_11,
|
|
.charge_control = {
|
|
.address = 0xd7,
|
|
.offset_start = 0x8a,
|
|
.offset_end = 0x80,
|
|
.range_min = 0x8a,
|
|
.range_max = 0xe4,
|
|
},
|
|
.webcam = {
|
|
.address = 0x2e,
|
|
.block_address = MSI_EC_ADDR_UNKNOWN,
|
|
.bit = 1,
|
|
},
|
|
.fn_win_swap = {
|
|
.address = 0xe8,
|
|
.bit = 4,
|
|
},
|
|
.cooler_boost = {
|
|
.address = 0x98,
|
|
.bit = 7,
|
|
},
|
|
.shift_mode = {
|
|
.address = 0xd2,
|
|
.modes = {
|
|
{ SM_ECO_NAME, 0xc2 },
|
|
{ SM_COMFORT_NAME, 0xc1 },
|
|
{ SM_SPORT_NAME, 0xc0 },
|
|
MSI_EC_MODE_NULL
|
|
},
|
|
},
|
|
.super_battery = {
|
|
.address = 0xeb,
|
|
.mask = 0x0f,
|
|
},
|
|
.fan_mode = {
|
|
.address = 0xd4,
|
|
.modes = {
|
|
{ FM_AUTO_NAME, 0x0d },
|
|
{ FM_SILENT_NAME, 0x1d },
|
|
{ FM_ADVANCED_NAME, 0x4d },
|
|
MSI_EC_MODE_NULL
|
|
},
|
|
},
|
|
.cpu = {
|
|
.rt_temp_address = 0x68,
|
|
.rt_fan_speed_address = MSI_EC_ADDR_UNSUPP,
|
|
.bs_fan_speed_address = MSI_EC_ADDR_UNSUPP,
|
|
},
|
|
.gpu = {
|
|
.rt_temp_address = MSI_EC_ADDR_UNSUPP,
|
|
.rt_fan_speed_address = MSI_EC_ADDR_UNSUPP,
|
|
},
|
|
.leds = {
|
|
.micmute_led_address = 0x2c,
|
|
.mute_led_address = 0x2d,
|
|
.bit = 1,
|
|
},
|
|
.kbd_bl = {
|
|
.bl_mode_address = MSI_EC_ADDR_UNKNOWN,
|
|
.bl_modes = {}, // ?
|
|
.max_mode = 1, // ?
|
|
.bl_state_address = 0xd3,
|
|
.state_base_value = 0x80,
|
|
.max_state = 3,
|
|
},
|
|
};
|
|
|
|
static const char * const ALLOWED_FW_12[] __initconst = {
|
|
"16R6EMS1.104", // GF63 Thin 11UC
|
|
NULL
|
|
};
|
|
|
|
static struct msi_ec_conf CONF12 __initdata = {
|
|
.allowed_fw = ALLOWED_FW_12,
|
|
.charge_control = {
|
|
.address = 0xd7,
|
|
.offset_start = 0x8a,
|
|
.offset_end = 0x80,
|
|
.range_min = 0x8a,
|
|
.range_max = 0xe4,
|
|
},
|
|
.webcam = {
|
|
.address = 0x2e,
|
|
.block_address = 0x2f,
|
|
.bit = 1,
|
|
},
|
|
.fn_win_swap = {
|
|
.address = 0xe8,
|
|
.bit = 4,
|
|
},
|
|
.cooler_boost = {
|
|
.address = 0x98,
|
|
.bit = 7,
|
|
},
|
|
.shift_mode = {
|
|
.address = 0xd2,
|
|
.modes = {
|
|
{ SM_ECO_NAME, 0xc2 },
|
|
{ SM_COMFORT_NAME, 0xc1 },
|
|
{ SM_SPORT_NAME, 0xc0 },
|
|
{ SM_TURBO_NAME, 0xc4 },
|
|
MSI_EC_MODE_NULL
|
|
},
|
|
},
|
|
.super_battery = {
|
|
.address = MSI_EC_ADDR_UNSUPP, // 0xeb
|
|
.mask = 0x0f, // 00, 0f
|
|
},
|
|
.fan_mode = {
|
|
.address = 0xd4,
|
|
.modes = {
|
|
{ FM_AUTO_NAME, 0x0d },
|
|
{ FM_SILENT_NAME, 0x1d },
|
|
{ FM_ADVANCED_NAME, 0x8d },
|
|
MSI_EC_MODE_NULL
|
|
},
|
|
},
|
|
.cpu = {
|
|
.rt_temp_address = 0x68,
|
|
.rt_fan_speed_address = 0x71,
|
|
.rt_fan_speed_base_min = 0x19,
|
|
.rt_fan_speed_base_max = 0x37,
|
|
.bs_fan_speed_address = MSI_EC_ADDR_UNSUPP,
|
|
.bs_fan_speed_base_min = 0x00,
|
|
.bs_fan_speed_base_max = 0x0f,
|
|
},
|
|
.gpu = {
|
|
.rt_temp_address = MSI_EC_ADDR_UNSUPP,
|
|
.rt_fan_speed_address = 0x89,
|
|
},
|
|
.leds = {
|
|
.micmute_led_address = MSI_EC_ADDR_UNSUPP,
|
|
.mute_led_address = 0x2d,
|
|
.bit = 1,
|
|
},
|
|
.kbd_bl = {
|
|
.bl_mode_address = MSI_EC_ADDR_UNKNOWN,
|
|
.bl_modes = { 0x00, 0x08 },
|
|
.max_mode = 1,
|
|
.bl_state_address = 0xd3,
|
|
.state_base_value = 0x80,
|
|
.max_state = 3,
|
|
},
|
|
};
|
|
|
|
static const char * const ALLOWED_FW_13[] __initconst = {
|
|
"1594EMS1.109", // MSI Prestige 16 Studio A13VE
|
|
NULL
|
|
};
|
|
|
|
static struct msi_ec_conf CONF13 __initdata = {
|
|
.allowed_fw = ALLOWED_FW_13,
|
|
.charge_control = {
|
|
.address = 0xd7,
|
|
.offset_start = 0x8a,
|
|
.offset_end = 0x80,
|
|
.range_min = 0x8a,
|
|
.range_max = 0xe4,
|
|
},
|
|
.webcam = {
|
|
.address = 0x2e,
|
|
.block_address = 0x2f,
|
|
.bit = 1,
|
|
},
|
|
.fn_win_swap = {
|
|
.address = 0xe8,
|
|
.bit = 4, // 0x00-0x10
|
|
},
|
|
.cooler_boost = {
|
|
.address = 0x98,
|
|
.bit = 7,
|
|
},
|
|
.shift_mode = {
|
|
.address = 0xd2,
|
|
.modes = {
|
|
{ SM_ECO_NAME, 0xc2 }, // super battery
|
|
{ SM_COMFORT_NAME, 0xc1 }, // balanced
|
|
{ SM_TURBO_NAME, 0xc4 }, // extreme
|
|
MSI_EC_MODE_NULL
|
|
},
|
|
},
|
|
.super_battery = {
|
|
.address = MSI_EC_ADDR_UNSUPP,
|
|
.mask = 0x0f, // 00, 0f
|
|
},
|
|
.fan_mode = {
|
|
.address = 0xd4,
|
|
.modes = {
|
|
{ FM_AUTO_NAME, 0x0d },
|
|
{ FM_SILENT_NAME, 0x1d },
|
|
{ FM_ADVANCED_NAME, 0x8d },
|
|
MSI_EC_MODE_NULL
|
|
},
|
|
},
|
|
.cpu = {
|
|
.rt_temp_address = 0x68,
|
|
.rt_fan_speed_address = 0x71, // 0x0-0x96
|
|
.rt_fan_speed_base_min = 0x00,
|
|
.rt_fan_speed_base_max = 0x96,
|
|
.bs_fan_speed_address = MSI_EC_ADDR_UNSUPP,
|
|
.bs_fan_speed_base_min = 0x00,
|
|
.bs_fan_speed_base_max = 0x0f,
|
|
},
|
|
.gpu = {
|
|
.rt_temp_address = 0x80,
|
|
.rt_fan_speed_address = 0x89,
|
|
},
|
|
.leds = {
|
|
.micmute_led_address = 0x2c,
|
|
.mute_led_address = 0x2d,
|
|
.bit = 1,
|
|
},
|
|
.kbd_bl = {
|
|
.bl_mode_address = 0x2c, // KB auto turn off
|
|
.bl_modes = { 0x00, 0x08 }, // always on; off after 10 sec
|
|
.max_mode = 1,
|
|
.bl_state_address = 0xd3,
|
|
.state_base_value = 0x80,
|
|
.max_state = 3,
|
|
},
|
|
};
|
|
|
|
static struct msi_ec_conf *CONFIGS[] __initdata = {
|
|
&CONF0,
|
|
&CONF1,
|
|
&CONF2,
|
|
&CONF3,
|
|
&CONF4,
|
|
&CONF5,
|
|
&CONF6,
|
|
&CONF7,
|
|
&CONF8,
|
|
&CONF9,
|
|
&CONF10,
|
|
&CONF11,
|
|
&CONF12,
|
|
&CONF13,
|
|
NULL
|
|
};
|
|
|
|
static struct msi_ec_conf conf; // current configuration
|
|
|
|
/*
|
|
* Helper functions
|
|
*/
|
|
|
|
static int ec_read_seq(u8 addr, u8 *buf, u8 len)
|
|
{
|
|
int result;
|
|
|
|
for (u8 i = 0; i < len; i++) {
|
|
result = ec_read(addr + i, buf + i);
|
|
if (result < 0)
|
|
return result;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
static int ec_get_firmware_version(u8 buf[MSI_EC_FW_VERSION_LENGTH + 1])
|
|
{
|
|
int result;
|
|
|
|
memset(buf, 0, MSI_EC_FW_VERSION_LENGTH + 1);
|
|
result = ec_read_seq(MSI_EC_FW_VERSION_ADDRESS,
|
|
buf,
|
|
MSI_EC_FW_VERSION_LENGTH);
|
|
if (result < 0)
|
|
return result;
|
|
|
|
return MSI_EC_FW_VERSION_LENGTH + 1;
|
|
}
|
|
|
|
/*
|
|
* Sysfs power_supply subsystem
|
|
*/
|
|
|
|
static ssize_t charge_control_threshold_show(u8 offset,
|
|
struct device *device,
|
|
struct device_attribute *attr,
|
|
char *buf)
|
|
{
|
|
u8 rdata;
|
|
int result;
|
|
|
|
result = ec_read(conf.charge_control.address, &rdata);
|
|
if (result < 0)
|
|
return result;
|
|
|
|
return sysfs_emit(buf, "%i\n", rdata - offset);
|
|
}
|
|
|
|
static ssize_t charge_control_threshold_store(u8 offset,
|
|
struct device *dev,
|
|
struct device_attribute *attr,
|
|
const char *buf, size_t count)
|
|
{
|
|
u8 wdata;
|
|
int result;
|
|
|
|
result = kstrtou8(buf, 10, &wdata);
|
|
if (result < 0)
|
|
return result;
|
|
|
|
wdata += offset;
|
|
if (wdata < conf.charge_control.range_min ||
|
|
wdata > conf.charge_control.range_max)
|
|
return -EINVAL;
|
|
|
|
result = ec_write(conf.charge_control.address, wdata);
|
|
if (result < 0)
|
|
return result;
|
|
|
|
return count;
|
|
}
|
|
|
|
static ssize_t charge_control_start_threshold_show(struct device *device,
|
|
struct device_attribute *attr,
|
|
char *buf)
|
|
{
|
|
return charge_control_threshold_show(conf.charge_control.offset_start,
|
|
device, attr, buf);
|
|
}
|
|
|
|
static ssize_t charge_control_start_threshold_store(struct device *dev,
|
|
struct device_attribute *attr,
|
|
const char *buf, size_t count)
|
|
{
|
|
return charge_control_threshold_store(conf.charge_control.offset_start,
|
|
dev, attr, buf, count);
|
|
}
|
|
|
|
static ssize_t charge_control_end_threshold_show(struct device *device,
|
|
struct device_attribute *attr,
|
|
char *buf)
|
|
{
|
|
return charge_control_threshold_show(conf.charge_control.offset_end,
|
|
device, attr, buf);
|
|
}
|
|
|
|
static ssize_t charge_control_end_threshold_store(struct device *dev,
|
|
struct device_attribute *attr,
|
|
const char *buf, size_t count)
|
|
{
|
|
return charge_control_threshold_store(conf.charge_control.offset_end,
|
|
dev, attr, buf, count);
|
|
}
|
|
|
|
static DEVICE_ATTR_RW(charge_control_start_threshold);
|
|
static DEVICE_ATTR_RW(charge_control_end_threshold);
|
|
|
|
static struct attribute *msi_battery_attrs[] = {
|
|
&dev_attr_charge_control_start_threshold.attr,
|
|
&dev_attr_charge_control_end_threshold.attr,
|
|
NULL
|
|
};
|
|
|
|
ATTRIBUTE_GROUPS(msi_battery);
|
|
|
|
static int msi_battery_add(struct power_supply *battery,
|
|
struct acpi_battery_hook *hook)
|
|
{
|
|
return device_add_groups(&battery->dev, msi_battery_groups);
|
|
}
|
|
|
|
static int msi_battery_remove(struct power_supply *battery,
|
|
struct acpi_battery_hook *hook)
|
|
{
|
|
device_remove_groups(&battery->dev, msi_battery_groups);
|
|
return 0;
|
|
}
|
|
|
|
static struct acpi_battery_hook battery_hook = {
|
|
.add_battery = msi_battery_add,
|
|
.remove_battery = msi_battery_remove,
|
|
.name = MSI_EC_DRIVER_NAME,
|
|
};
|
|
|
|
/*
|
|
* Module load/unload
|
|
*/
|
|
|
|
static const struct dmi_system_id msi_dmi_table[] __initconst __maybe_unused = {
|
|
{
|
|
.matches = {
|
|
DMI_MATCH(DMI_SYS_VENDOR, "MICRO-STAR INT"),
|
|
},
|
|
},
|
|
{
|
|
.matches = {
|
|
DMI_MATCH(DMI_SYS_VENDOR, "Micro-Star International"),
|
|
},
|
|
},
|
|
{}
|
|
};
|
|
MODULE_DEVICE_TABLE(dmi, msi_dmi_table);
|
|
|
|
static int __init load_configuration(void)
|
|
{
|
|
int result;
|
|
|
|
u8 fw_version[MSI_EC_FW_VERSION_LENGTH + 1];
|
|
|
|
/* get firmware version */
|
|
result = ec_get_firmware_version(fw_version);
|
|
if (result < 0)
|
|
return result;
|
|
|
|
/* load the suitable configuration, if exists */
|
|
for (int i = 0; CONFIGS[i]; i++) {
|
|
if (match_string(CONFIGS[i]->allowed_fw, -1, fw_version) != -EINVAL) {
|
|
conf = *CONFIGS[i];
|
|
conf.allowed_fw = NULL;
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
/* config not found */
|
|
|
|
for (int i = 0; i < MSI_EC_FW_VERSION_LENGTH; i++) {
|
|
if (!isgraph(fw_version[i])) {
|
|
pr_warn("Unable to find a valid firmware version!\n");
|
|
return -EOPNOTSUPP;
|
|
}
|
|
}
|
|
|
|
pr_warn("Firmware version is not supported: '%s'\n", fw_version);
|
|
return -EOPNOTSUPP;
|
|
}
|
|
|
|
static int __init msi_ec_init(void)
|
|
{
|
|
int result;
|
|
|
|
result = load_configuration();
|
|
if (result < 0)
|
|
return result;
|
|
|
|
battery_hook_register(&battery_hook);
|
|
return 0;
|
|
}
|
|
|
|
static void __exit msi_ec_exit(void)
|
|
{
|
|
battery_hook_unregister(&battery_hook);
|
|
}
|
|
|
|
MODULE_LICENSE("GPL");
|
|
MODULE_AUTHOR("Jose Angel Pastrana <japp0005@red.ujaen.es>");
|
|
MODULE_AUTHOR("Aakash Singh <mail@singhaakash.dev>");
|
|
MODULE_AUTHOR("Nikita Kravets <teackot@gmail.com>");
|
|
MODULE_DESCRIPTION("MSI Embedded Controller");
|
|
|
|
module_init(msi_ec_init);
|
|
module_exit(msi_ec_exit);
|