platform-drivers-x86 for v6.15-3

Fixes:
 
  - amd/pmf: Fix STT limits
 
  - asus-laptop: Fix an uninitialized variable
 
  - intel_pmc_ipc: Allow building without ACPI
 
  - mlxbf-bootctl: Use sysfs_emit_at() in secure_boot_fuse_state_show()
 
  - msi-wmi-platform: Add locking to workaround ACPI firmware bug
 
 New HW support:
 
  - alienware-wmi-wmax:
    - Extended thermal control support to:
      - Alienware Area-51m R2
      - Alienware m16 R1
      - Alienware m16 R2
      - Dell G16 7630
      - Dell G5 5505 SE
    - G-Mode support to Alienware m16 R1
 
  - x86-android-tablets: Add Vexia Edu Atla 10 tablet 5V data
 
 The following is an automated shortlog grouped by driver:
 
 alienware-wmi-wmax:
  -  Add G-Mode support to Alienware m16 R1
  -  Extend support to more laptops
 
 amd: pmf:
  -  Fix STT limits
 
 asus-laptop:
  -  Fix an uninitialized variable
 
 intel_pmc_ipc:
  -  add option to build without ACPI
 
 mlxbf-bootctl:
  -  use sysfs_emit_at() in secure_boot_fuse_state_show()
 
 msi-wmi-platform:
  -  Rename "data" variable
  -  Workaround a ACPI firmware bug
 
 x86-android-tablets:
  -  Add "9v" to Vexia EDU ATLA 10 tablet symbols
  -  Add Vexia Edu Atla 10 tablet 5V data
 -----BEGIN PGP SIGNATURE-----
 
 iHUEABYIAB0WIQSCSUwRdwTNL2MhaBlZrE9hU+XOMQUCaADiBwAKCRBZrE9hU+XO
 MYKKAP422M/5lQvZ0paUfSPqqNEG9OVbvMRGBQObh2GndvSy9AD/f66RnPoP11hw
 4eIYTstCQ1vQkv/u0ckehey6jGJ5ngQ=
 =Aidx
 -----END PGP SIGNATURE-----

Merge tag 'platform-drivers-x86-v6.15-3' of git://git.kernel.org/pub/scm/linux/kernel/git/pdx86/platform-drivers-x86

Pull x86 platform drivers fixes from Ilpo Järvinen:
 "Fixes:
   - amd/pmf: Fix STT limits
   - asus-laptop: Fix an uninitialized variable
   - intel_pmc_ipc: Allow building without ACPI
   - mlxbf-bootctl: Use sysfs_emit_at() in secure_boot_fuse_state_show()
   - msi-wmi-platform: Add locking to workaround ACPI firmware bug

  New HW support:
   - alienware-wmi-wmax:
      - Extended thermal control support to:
         - Alienware Area-51m R2
         - Alienware m16 R1
         - Alienware m16 R2
         - Dell G16 7630
         - Dell G5 5505 SE
      - G-Mode support to Alienware m16 R1
   - x86-android-tablets: Add Vexia Edu Atla 10 tablet 5V data"

* tag 'platform-drivers-x86-v6.15-3' of git://git.kernel.org/pub/scm/linux/kernel/git/pdx86/platform-drivers-x86:
  platform/x86: msi-wmi-platform: Workaround a ACPI firmware bug
  platform/x86: msi-wmi-platform: Rename "data" variable
  platform/x86: alienware-wmi-wmax: Extend support to more laptops
  platform/x86: alienware-wmi-wmax: Add G-Mode support to Alienware m16 R1
  platform/x86: amd: pmf: Fix STT limits
  mlxbf-bootctl: use sysfs_emit_at() in secure_boot_fuse_state_show()
  platform/x86: x86-android-tablets: Add Vexia Edu Atla 10 tablet 5V data
  platform/x86: x86-android-tablets: Add "9v" to Vexia EDU ATLA 10 tablet symbols
  asus-laptop: Fix an uninitialized variable
  platform/x86: intel_pmc_ipc: add option to build without ACPI
This commit is contained in:
Linus Torvalds 2025-04-17 10:05:33 -07:00
commit 8499899816
15 changed files with 285 additions and 105 deletions

View file

@ -138,6 +138,10 @@ input data, the meaning of which depends on the subfeature being accessed.
The output buffer contains a single byte which signals success or failure (``0x00`` on failure)
and 31 bytes of output data, the meaning if which depends on the subfeature being accessed.
.. note::
The ACPI control method responsible for handling the WMI method calls is not thread-safe.
This is a firmware bug that needs to be handled inside the driver itself.
WMI method Get_EC()
-------------------

View file

@ -333,9 +333,9 @@ static ssize_t secure_boot_fuse_state_show(struct device *dev,
else
status = valid ? "Invalid" : "Free";
}
buf_len += sysfs_emit(buf + buf_len, "%d:%s ", key, status);
buf_len += sysfs_emit_at(buf, buf_len, "%d:%s ", key, status);
}
buf_len += sysfs_emit(buf + buf_len, "\n");
buf_len += sysfs_emit_at(buf, buf_len, "\n");
return buf_len;
}

View file

@ -120,9 +120,9 @@ static void amd_pmf_set_automode(struct amd_pmf_dev *dev, int idx,
amd_pmf_send_cmd(dev, SET_SPPT_APU_ONLY, false, pwr_ctrl->sppt_apu_only, NULL);
amd_pmf_send_cmd(dev, SET_STT_MIN_LIMIT, false, pwr_ctrl->stt_min, NULL);
amd_pmf_send_cmd(dev, SET_STT_LIMIT_APU, false,
pwr_ctrl->stt_skin_temp[STT_TEMP_APU], NULL);
fixp_q88_fromint(pwr_ctrl->stt_skin_temp[STT_TEMP_APU]), NULL);
amd_pmf_send_cmd(dev, SET_STT_LIMIT_HS2, false,
pwr_ctrl->stt_skin_temp[STT_TEMP_HS2], NULL);
fixp_q88_fromint(pwr_ctrl->stt_skin_temp[STT_TEMP_HS2]), NULL);
if (is_apmf_func_supported(dev, APMF_FUNC_SET_FAN_IDX))
apmf_update_fan_idx(dev, config_store.mode_set[idx].fan_control.manual,

View file

@ -81,10 +81,10 @@ static int amd_pmf_set_cnqf(struct amd_pmf_dev *dev, int src, int idx,
amd_pmf_send_cmd(dev, SET_SPPT, false, pc->sppt, NULL);
amd_pmf_send_cmd(dev, SET_SPPT_APU_ONLY, false, pc->sppt_apu_only, NULL);
amd_pmf_send_cmd(dev, SET_STT_MIN_LIMIT, false, pc->stt_min, NULL);
amd_pmf_send_cmd(dev, SET_STT_LIMIT_APU, false, pc->stt_skin_temp[STT_TEMP_APU],
NULL);
amd_pmf_send_cmd(dev, SET_STT_LIMIT_HS2, false, pc->stt_skin_temp[STT_TEMP_HS2],
NULL);
amd_pmf_send_cmd(dev, SET_STT_LIMIT_APU, false,
fixp_q88_fromint(pc->stt_skin_temp[STT_TEMP_APU]), NULL);
amd_pmf_send_cmd(dev, SET_STT_LIMIT_HS2, false,
fixp_q88_fromint(pc->stt_skin_temp[STT_TEMP_HS2]), NULL);
if (is_apmf_func_supported(dev, APMF_FUNC_SET_FAN_IDX))
apmf_update_fan_idx(dev,

View file

@ -176,6 +176,20 @@ static void __maybe_unused amd_pmf_dump_registers(struct amd_pmf_dev *dev)
dev_dbg(dev->dev, "AMD_PMF_REGISTER_MESSAGE:%x\n", value);
}
/**
* fixp_q88_fromint: Convert integer to Q8.8
* @val: input value
*
* Converts an integer into binary fixed point format where 8 bits
* are used for integer and 8 bits are used for the decimal.
*
* Return: unsigned integer converted to Q8.8 format
*/
u32 fixp_q88_fromint(u32 val)
{
return val << 8;
}
int amd_pmf_send_cmd(struct amd_pmf_dev *dev, u8 message, bool get, u32 arg, u32 *data)
{
int rc;

View file

@ -777,6 +777,7 @@ int apmf_install_handler(struct amd_pmf_dev *pmf_dev);
int apmf_os_power_slider_update(struct amd_pmf_dev *dev, u8 flag);
int amd_pmf_set_dram_addr(struct amd_pmf_dev *dev, bool alloc_buffer);
int amd_pmf_notify_sbios_heartbeat_event_v2(struct amd_pmf_dev *dev, u8 flag);
u32 fixp_q88_fromint(u32 val);
/* SPS Layer */
int amd_pmf_get_pprof_modes(struct amd_pmf_dev *pmf);

View file

@ -198,9 +198,11 @@ static void amd_pmf_update_slider_v2(struct amd_pmf_dev *dev, int idx)
amd_pmf_send_cmd(dev, SET_STT_MIN_LIMIT, false,
apts_config_store.val[idx].stt_min_limit, NULL);
amd_pmf_send_cmd(dev, SET_STT_LIMIT_APU, false,
apts_config_store.val[idx].stt_skin_temp_limit_apu, NULL);
fixp_q88_fromint(apts_config_store.val[idx].stt_skin_temp_limit_apu),
NULL);
amd_pmf_send_cmd(dev, SET_STT_LIMIT_HS2, false,
apts_config_store.val[idx].stt_skin_temp_limit_hs2, NULL);
fixp_q88_fromint(apts_config_store.val[idx].stt_skin_temp_limit_hs2),
NULL);
}
void amd_pmf_update_slider(struct amd_pmf_dev *dev, bool op, int idx,
@ -217,9 +219,11 @@ void amd_pmf_update_slider(struct amd_pmf_dev *dev, bool op, int idx,
amd_pmf_send_cmd(dev, SET_STT_MIN_LIMIT, false,
config_store.prop[src][idx].stt_min, NULL);
amd_pmf_send_cmd(dev, SET_STT_LIMIT_APU, false,
config_store.prop[src][idx].stt_skin_temp[STT_TEMP_APU], NULL);
fixp_q88_fromint(config_store.prop[src][idx].stt_skin_temp[STT_TEMP_APU]),
NULL);
amd_pmf_send_cmd(dev, SET_STT_LIMIT_HS2, false,
config_store.prop[src][idx].stt_skin_temp[STT_TEMP_HS2], NULL);
fixp_q88_fromint(config_store.prop[src][idx].stt_skin_temp[STT_TEMP_HS2]),
NULL);
} else if (op == SLIDER_OP_GET) {
amd_pmf_send_cmd(dev, GET_SPL, true, ARG_NONE, &table->prop[src][idx].spl);
amd_pmf_send_cmd(dev, GET_FPPT, true, ARG_NONE, &table->prop[src][idx].fppt);

View file

@ -123,7 +123,8 @@ static void amd_pmf_apply_policies(struct amd_pmf_dev *dev, struct ta_pmf_enact_
case PMF_POLICY_STT_SKINTEMP_APU:
if (dev->prev_data->stt_skintemp_apu != val) {
amd_pmf_send_cmd(dev, SET_STT_LIMIT_APU, false, val, NULL);
amd_pmf_send_cmd(dev, SET_STT_LIMIT_APU, false,
fixp_q88_fromint(val), NULL);
dev_dbg(dev->dev, "update STT_SKINTEMP_APU: %u\n", val);
dev->prev_data->stt_skintemp_apu = val;
}
@ -131,7 +132,8 @@ static void amd_pmf_apply_policies(struct amd_pmf_dev *dev, struct ta_pmf_enact_
case PMF_POLICY_STT_SKINTEMP_HS2:
if (dev->prev_data->stt_skintemp_hs2 != val) {
amd_pmf_send_cmd(dev, SET_STT_LIMIT_HS2, false, val, NULL);
amd_pmf_send_cmd(dev, SET_STT_LIMIT_HS2, false,
fixp_q88_fromint(val), NULL);
dev_dbg(dev->dev, "update STT_SKINTEMP_HS2: %u\n", val);
dev->prev_data->stt_skintemp_hs2 = val;
}

View file

@ -426,11 +426,14 @@ static int asus_pega_lucid_set(struct asus_laptop *asus, int unit, bool enable)
static int pega_acc_axis(struct asus_laptop *asus, int curr, char *method)
{
unsigned long long val = (unsigned long long)curr;
acpi_status status;
int i, delta;
unsigned long long val;
for (i = 0; i < PEGA_ACC_RETRIES; i++) {
acpi_evaluate_integer(asus->handle, method, NULL, &val);
for (i = 0; i < PEGA_ACC_RETRIES; i++) {
status = acpi_evaluate_integer(asus->handle, method, NULL, &val);
if (ACPI_FAILURE(status))
continue;
/* The output is noisy. From reading the ASL
* dissassembly, timeout errors are returned with 1's
* in the high word, and the lack of locking around

View file

@ -61,12 +61,36 @@ static struct awcc_quirks generic_quirks = {
static struct awcc_quirks empty_quirks;
static const struct dmi_system_id awcc_dmi_table[] __initconst = {
{
.ident = "Alienware Area-51m R2",
.matches = {
DMI_MATCH(DMI_SYS_VENDOR, "Alienware"),
DMI_MATCH(DMI_PRODUCT_NAME, "Alienware Area-51m R2"),
},
.driver_data = &generic_quirks,
},
{
.ident = "Alienware m16 R1",
.matches = {
DMI_MATCH(DMI_SYS_VENDOR, "Alienware"),
DMI_MATCH(DMI_PRODUCT_NAME, "Alienware m16 R1"),
},
.driver_data = &g_series_quirks,
},
{
.ident = "Alienware m16 R1 AMD",
.matches = {
DMI_MATCH(DMI_SYS_VENDOR, "Alienware"),
DMI_MATCH(DMI_PRODUCT_NAME, "Alienware m16 R1 AMD"),
},
.driver_data = &g_series_quirks,
},
{
.ident = "Alienware m16 R2",
.matches = {
DMI_MATCH(DMI_SYS_VENDOR, "Alienware"),
DMI_MATCH(DMI_PRODUCT_NAME, "Alienware m16 R2"),
},
.driver_data = &generic_quirks,
},
{
@ -93,6 +117,14 @@ static const struct dmi_system_id awcc_dmi_table[] __initconst = {
},
.driver_data = &generic_quirks,
},
{
.ident = "Alienware x15 R2",
.matches = {
DMI_MATCH(DMI_SYS_VENDOR, "Alienware"),
DMI_MATCH(DMI_PRODUCT_NAME, "Alienware x15 R2"),
},
.driver_data = &generic_quirks,
},
{
.ident = "Alienware x17 R2",
.matches = {
@ -125,6 +157,14 @@ static const struct dmi_system_id awcc_dmi_table[] __initconst = {
},
.driver_data = &g_series_quirks,
},
{
.ident = "Dell Inc. G16 7630",
.matches = {
DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."),
DMI_MATCH(DMI_PRODUCT_NAME, "Dell G16 7630"),
},
.driver_data = &g_series_quirks,
},
{
.ident = "Dell Inc. G3 3500",
.matches = {
@ -149,6 +189,14 @@ static const struct dmi_system_id awcc_dmi_table[] __initconst = {
},
.driver_data = &g_series_quirks,
},
{
.ident = "Dell Inc. G5 5505",
.matches = {
DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."),
DMI_MATCH(DMI_PRODUCT_NAME, "G5 5505"),
},
.driver_data = &g_series_quirks,
},
};
enum WMAX_THERMAL_INFORMATION_OPERATIONS {

View file

@ -10,6 +10,7 @@
#include <linux/acpi.h>
#include <linux/bits.h>
#include <linux/bitfield.h>
#include <linux/cleanup.h>
#include <linux/debugfs.h>
#include <linux/device.h>
#include <linux/device/driver.h>
@ -17,6 +18,7 @@
#include <linux/hwmon.h>
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/mutex.h>
#include <linux/printk.h>
#include <linux/rwsem.h>
#include <linux/types.h>
@ -76,8 +78,13 @@ enum msi_wmi_platform_method {
MSI_PLATFORM_GET_WMI = 0x1d,
};
struct msi_wmi_platform_debugfs_data {
struct msi_wmi_platform_data {
struct wmi_device *wdev;
struct mutex wmi_lock; /* Necessary when calling WMI methods */
};
struct msi_wmi_platform_debugfs_data {
struct msi_wmi_platform_data *data;
enum msi_wmi_platform_method method;
struct rw_semaphore buffer_lock; /* Protects debugfs buffer */
size_t length;
@ -132,8 +139,9 @@ static int msi_wmi_platform_parse_buffer(union acpi_object *obj, u8 *output, siz
return 0;
}
static int msi_wmi_platform_query(struct wmi_device *wdev, enum msi_wmi_platform_method method,
u8 *input, size_t input_length, u8 *output, size_t output_length)
static int msi_wmi_platform_query(struct msi_wmi_platform_data *data,
enum msi_wmi_platform_method method, u8 *input,
size_t input_length, u8 *output, size_t output_length)
{
struct acpi_buffer out = { ACPI_ALLOCATE_BUFFER, NULL };
struct acpi_buffer in = {
@ -147,9 +155,15 @@ static int msi_wmi_platform_query(struct wmi_device *wdev, enum msi_wmi_platform
if (!input_length || !output_length)
return -EINVAL;
status = wmidev_evaluate_method(wdev, 0x0, method, &in, &out);
if (ACPI_FAILURE(status))
return -EIO;
/*
* The ACPI control method responsible for handling the WMI method calls
* is not thread-safe. Because of this we have to do the locking ourself.
*/
scoped_guard(mutex, &data->wmi_lock) {
status = wmidev_evaluate_method(data->wdev, 0x0, method, &in, &out);
if (ACPI_FAILURE(status))
return -EIO;
}
obj = out.pointer;
if (!obj)
@ -170,22 +184,22 @@ static umode_t msi_wmi_platform_is_visible(const void *drvdata, enum hwmon_senso
static int msi_wmi_platform_read(struct device *dev, enum hwmon_sensor_types type, u32 attr,
int channel, long *val)
{
struct wmi_device *wdev = dev_get_drvdata(dev);
struct msi_wmi_platform_data *data = dev_get_drvdata(dev);
u8 input[32] = { 0 };
u8 output[32];
u16 data;
u16 value;
int ret;
ret = msi_wmi_platform_query(wdev, MSI_PLATFORM_GET_FAN, input, sizeof(input), output,
ret = msi_wmi_platform_query(data, MSI_PLATFORM_GET_FAN, input, sizeof(input), output,
sizeof(output));
if (ret < 0)
return ret;
data = get_unaligned_be16(&output[channel * 2 + 1]);
if (!data)
value = get_unaligned_be16(&output[channel * 2 + 1]);
if (!value)
*val = 0;
else
*val = 480000 / data;
*val = 480000 / value;
return 0;
}
@ -231,7 +245,7 @@ static ssize_t msi_wmi_platform_write(struct file *fp, const char __user *input,
return ret;
down_write(&data->buffer_lock);
ret = msi_wmi_platform_query(data->wdev, data->method, payload, data->length, data->buffer,
ret = msi_wmi_platform_query(data->data, data->method, payload, data->length, data->buffer,
data->length);
up_write(&data->buffer_lock);
@ -277,17 +291,17 @@ static void msi_wmi_platform_debugfs_remove(void *data)
debugfs_remove_recursive(dir);
}
static void msi_wmi_platform_debugfs_add(struct wmi_device *wdev, struct dentry *dir,
static void msi_wmi_platform_debugfs_add(struct msi_wmi_platform_data *drvdata, struct dentry *dir,
const char *name, enum msi_wmi_platform_method method)
{
struct msi_wmi_platform_debugfs_data *data;
struct dentry *entry;
data = devm_kzalloc(&wdev->dev, sizeof(*data), GFP_KERNEL);
data = devm_kzalloc(&drvdata->wdev->dev, sizeof(*data), GFP_KERNEL);
if (!data)
return;
data->wdev = wdev;
data->data = drvdata;
data->method = method;
init_rwsem(&data->buffer_lock);
@ -298,82 +312,82 @@ static void msi_wmi_platform_debugfs_add(struct wmi_device *wdev, struct dentry
entry = debugfs_create_file(name, 0600, dir, data, &msi_wmi_platform_debugfs_fops);
if (IS_ERR(entry))
devm_kfree(&wdev->dev, data);
devm_kfree(&drvdata->wdev->dev, data);
}
static void msi_wmi_platform_debugfs_init(struct wmi_device *wdev)
static void msi_wmi_platform_debugfs_init(struct msi_wmi_platform_data *data)
{
struct dentry *dir;
char dir_name[64];
int ret, method;
scnprintf(dir_name, ARRAY_SIZE(dir_name), "%s-%s", DRIVER_NAME, dev_name(&wdev->dev));
scnprintf(dir_name, ARRAY_SIZE(dir_name), "%s-%s", DRIVER_NAME, dev_name(&data->wdev->dev));
dir = debugfs_create_dir(dir_name, NULL);
if (IS_ERR(dir))
return;
ret = devm_add_action_or_reset(&wdev->dev, msi_wmi_platform_debugfs_remove, dir);
ret = devm_add_action_or_reset(&data->wdev->dev, msi_wmi_platform_debugfs_remove, dir);
if (ret < 0)
return;
for (method = MSI_PLATFORM_GET_PACKAGE; method <= MSI_PLATFORM_GET_WMI; method++)
msi_wmi_platform_debugfs_add(wdev, dir, msi_wmi_platform_debugfs_names[method - 1],
msi_wmi_platform_debugfs_add(data, dir, msi_wmi_platform_debugfs_names[method - 1],
method);
}
static int msi_wmi_platform_hwmon_init(struct wmi_device *wdev)
static int msi_wmi_platform_hwmon_init(struct msi_wmi_platform_data *data)
{
struct device *hdev;
hdev = devm_hwmon_device_register_with_info(&wdev->dev, "msi_wmi_platform", wdev,
hdev = devm_hwmon_device_register_with_info(&data->wdev->dev, "msi_wmi_platform", data,
&msi_wmi_platform_chip_info, NULL);
return PTR_ERR_OR_ZERO(hdev);
}
static int msi_wmi_platform_ec_init(struct wmi_device *wdev)
static int msi_wmi_platform_ec_init(struct msi_wmi_platform_data *data)
{
u8 input[32] = { 0 };
u8 output[32];
u8 flags;
int ret;
ret = msi_wmi_platform_query(wdev, MSI_PLATFORM_GET_EC, input, sizeof(input), output,
ret = msi_wmi_platform_query(data, MSI_PLATFORM_GET_EC, input, sizeof(input), output,
sizeof(output));
if (ret < 0)
return ret;
flags = output[MSI_PLATFORM_EC_FLAGS_OFFSET];
dev_dbg(&wdev->dev, "EC RAM version %lu.%lu\n",
dev_dbg(&data->wdev->dev, "EC RAM version %lu.%lu\n",
FIELD_GET(MSI_PLATFORM_EC_MAJOR_MASK, flags),
FIELD_GET(MSI_PLATFORM_EC_MINOR_MASK, flags));
dev_dbg(&wdev->dev, "EC firmware version %.28s\n",
dev_dbg(&data->wdev->dev, "EC firmware version %.28s\n",
&output[MSI_PLATFORM_EC_VERSION_OFFSET]);
if (!(flags & MSI_PLATFORM_EC_IS_TIGERLAKE)) {
if (!force)
return -ENODEV;
dev_warn(&wdev->dev, "Loading on a non-Tigerlake platform\n");
dev_warn(&data->wdev->dev, "Loading on a non-Tigerlake platform\n");
}
return 0;
}
static int msi_wmi_platform_init(struct wmi_device *wdev)
static int msi_wmi_platform_init(struct msi_wmi_platform_data *data)
{
u8 input[32] = { 0 };
u8 output[32];
int ret;
ret = msi_wmi_platform_query(wdev, MSI_PLATFORM_GET_WMI, input, sizeof(input), output,
ret = msi_wmi_platform_query(data, MSI_PLATFORM_GET_WMI, input, sizeof(input), output,
sizeof(output));
if (ret < 0)
return ret;
dev_dbg(&wdev->dev, "WMI interface version %u.%u\n",
dev_dbg(&data->wdev->dev, "WMI interface version %u.%u\n",
output[MSI_PLATFORM_WMI_MAJOR_OFFSET],
output[MSI_PLATFORM_WMI_MINOR_OFFSET]);
@ -381,7 +395,8 @@ static int msi_wmi_platform_init(struct wmi_device *wdev)
if (!force)
return -ENODEV;
dev_warn(&wdev->dev, "Loading despite unsupported WMI interface version (%u.%u)\n",
dev_warn(&data->wdev->dev,
"Loading despite unsupported WMI interface version (%u.%u)\n",
output[MSI_PLATFORM_WMI_MAJOR_OFFSET],
output[MSI_PLATFORM_WMI_MINOR_OFFSET]);
}
@ -391,19 +406,31 @@ static int msi_wmi_platform_init(struct wmi_device *wdev)
static int msi_wmi_platform_probe(struct wmi_device *wdev, const void *context)
{
struct msi_wmi_platform_data *data;
int ret;
ret = msi_wmi_platform_init(wdev);
data = devm_kzalloc(&wdev->dev, sizeof(*data), GFP_KERNEL);
if (!data)
return -ENOMEM;
data->wdev = wdev;
dev_set_drvdata(&wdev->dev, data);
ret = devm_mutex_init(&wdev->dev, &data->wmi_lock);
if (ret < 0)
return ret;
ret = msi_wmi_platform_ec_init(wdev);
ret = msi_wmi_platform_init(data);
if (ret < 0)
return ret;
msi_wmi_platform_debugfs_init(wdev);
ret = msi_wmi_platform_ec_init(data);
if (ret < 0)
return ret;
return msi_wmi_platform_hwmon_init(wdev);
msi_wmi_platform_debugfs_init(data);
return msi_wmi_platform_hwmon_init(data);
}
static const struct wmi_device_id msi_wmi_platform_id_table[] = {

View file

@ -179,6 +179,18 @@ const struct dmi_system_id x86_android_tablet_ids[] __initconst = {
},
.driver_data = (void *)&peaq_c1010_info,
},
{
/* Vexia Edu Atla 10 tablet 5V version */
.matches = {
/* Having all 3 of these not set is somewhat unique */
DMI_MATCH(DMI_SYS_VENDOR, "To be filled by O.E.M."),
DMI_MATCH(DMI_PRODUCT_NAME, "To be filled by O.E.M."),
DMI_MATCH(DMI_BOARD_NAME, "To be filled by O.E.M."),
/* Above strings are too generic, also match on BIOS date */
DMI_MATCH(DMI_BIOS_DATE, "05/14/2015"),
},
.driver_data = (void *)&vexia_edu_atla10_5v_info,
},
{
/* Vexia Edu Atla 10 tablet 9V version */
.matches = {
@ -187,7 +199,7 @@ const struct dmi_system_id x86_android_tablet_ids[] __initconst = {
/* Above strings are too generic, also match on BIOS date */
DMI_MATCH(DMI_BIOS_DATE, "08/25/2014"),
},
.driver_data = (void *)&vexia_edu_atla10_info,
.driver_data = (void *)&vexia_edu_atla10_9v_info,
},
{
/* Whitelabel (sold as various brands) TM800A550L */

View file

@ -599,62 +599,122 @@ const struct x86_dev_info whitelabel_tm800a550l_info __initconst = {
};
/*
* Vexia EDU ATLA 10 tablet, Android 4.2 / 4.4 + Guadalinex Ubuntu tablet
* Vexia EDU ATLA 10 tablet 5V, Android 4.4 + Guadalinex Ubuntu tablet
* distributed to schools in the Spanish Andalucía region.
*/
static const char * const crystal_cove_pwrsrc_psy[] = { "crystal_cove_pwrsrc" };
static const struct property_entry vexia_edu_atla10_ulpmc_props[] = {
PROPERTY_ENTRY_STRING_ARRAY("supplied-from", crystal_cove_pwrsrc_psy),
{ }
};
static const struct software_node vexia_edu_atla10_ulpmc_node = {
.properties = vexia_edu_atla10_ulpmc_props,
};
static const char * const vexia_edu_atla10_accel_mount_matrix[] = {
"0", "-1", "0",
"1", "0", "0",
"0", "0", "1"
};
static const struct property_entry vexia_edu_atla10_accel_props[] = {
PROPERTY_ENTRY_STRING_ARRAY("mount-matrix", vexia_edu_atla10_accel_mount_matrix),
{ }
};
static const struct software_node vexia_edu_atla10_accel_node = {
.properties = vexia_edu_atla10_accel_props,
};
static const struct property_entry vexia_edu_atla10_touchscreen_props[] = {
static const struct property_entry vexia_edu_atla10_5v_touchscreen_props[] = {
PROPERTY_ENTRY_U32("hid-descr-addr", 0x0000),
PROPERTY_ENTRY_U32("post-reset-deassert-delay-ms", 120),
{ }
};
static const struct software_node vexia_edu_atla10_touchscreen_node = {
.properties = vexia_edu_atla10_touchscreen_props,
static const struct software_node vexia_edu_atla10_5v_touchscreen_node = {
.properties = vexia_edu_atla10_5v_touchscreen_props,
};
static const struct property_entry vexia_edu_atla10_pmic_props[] = {
static const struct x86_i2c_client_info vexia_edu_atla10_5v_i2c_clients[] __initconst = {
{
/* kxcjk1013 accelerometer */
.board_info = {
.type = "kxcjk1013",
.addr = 0x0f,
.dev_name = "kxcjk1013",
},
.adapter_path = "\\_SB_.I2C3",
}, {
/* touchscreen controller */
.board_info = {
.type = "hid-over-i2c",
.addr = 0x38,
.dev_name = "FTSC1000",
.swnode = &vexia_edu_atla10_5v_touchscreen_node,
},
.adapter_path = "\\_SB_.I2C4",
.irq_data = {
.type = X86_ACPI_IRQ_TYPE_APIC,
.index = 0x44,
.trigger = ACPI_LEVEL_SENSITIVE,
.polarity = ACPI_ACTIVE_HIGH,
},
}
};
static struct gpiod_lookup_table vexia_edu_atla10_5v_ft5416_gpios = {
.dev_id = "i2c-FTSC1000",
.table = {
GPIO_LOOKUP("INT33FC:01", 26, "reset", GPIO_ACTIVE_LOW),
{ }
},
};
static struct gpiod_lookup_table * const vexia_edu_atla10_5v_gpios[] = {
&vexia_edu_atla10_5v_ft5416_gpios,
NULL
};
const struct x86_dev_info vexia_edu_atla10_5v_info __initconst = {
.i2c_client_info = vexia_edu_atla10_5v_i2c_clients,
.i2c_client_count = ARRAY_SIZE(vexia_edu_atla10_5v_i2c_clients),
.gpiod_lookup_tables = vexia_edu_atla10_5v_gpios,
};
/*
* Vexia EDU ATLA 10 tablet 9V, Android 4.2 + Guadalinex Ubuntu tablet
* distributed to schools in the Spanish Andalucía region.
*/
static const char * const crystal_cove_pwrsrc_psy[] = { "crystal_cove_pwrsrc" };
static const struct property_entry vexia_edu_atla10_9v_ulpmc_props[] = {
PROPERTY_ENTRY_STRING_ARRAY("supplied-from", crystal_cove_pwrsrc_psy),
{ }
};
static const struct software_node vexia_edu_atla10_9v_ulpmc_node = {
.properties = vexia_edu_atla10_9v_ulpmc_props,
};
static const char * const vexia_edu_atla10_9v_accel_mount_matrix[] = {
"0", "-1", "0",
"1", "0", "0",
"0", "0", "1"
};
static const struct property_entry vexia_edu_atla10_9v_accel_props[] = {
PROPERTY_ENTRY_STRING_ARRAY("mount-matrix", vexia_edu_atla10_9v_accel_mount_matrix),
{ }
};
static const struct software_node vexia_edu_atla10_9v_accel_node = {
.properties = vexia_edu_atla10_9v_accel_props,
};
static const struct property_entry vexia_edu_atla10_9v_touchscreen_props[] = {
PROPERTY_ENTRY_U32("hid-descr-addr", 0x0000),
PROPERTY_ENTRY_U32("post-reset-deassert-delay-ms", 120),
{ }
};
static const struct software_node vexia_edu_atla10_9v_touchscreen_node = {
.properties = vexia_edu_atla10_9v_touchscreen_props,
};
static const struct property_entry vexia_edu_atla10_9v_pmic_props[] = {
PROPERTY_ENTRY_BOOL("linux,register-pwrsrc-power_supply"),
{ }
};
static const struct software_node vexia_edu_atla10_pmic_node = {
.properties = vexia_edu_atla10_pmic_props,
static const struct software_node vexia_edu_atla10_9v_pmic_node = {
.properties = vexia_edu_atla10_9v_pmic_props,
};
static const struct x86_i2c_client_info vexia_edu_atla10_i2c_clients[] __initconst = {
static const struct x86_i2c_client_info vexia_edu_atla10_9v_i2c_clients[] __initconst = {
{
/* I2C attached embedded controller, used to access fuel-gauge */
.board_info = {
.type = "vexia_atla10_ec",
.addr = 0x76,
.dev_name = "ulpmc",
.swnode = &vexia_edu_atla10_ulpmc_node,
.swnode = &vexia_edu_atla10_9v_ulpmc_node,
},
.adapter_path = "0000:00:18.1",
}, {
@ -679,7 +739,7 @@ static const struct x86_i2c_client_info vexia_edu_atla10_i2c_clients[] __initcon
.type = "kxtj21009",
.addr = 0x0f,
.dev_name = "kxtj21009",
.swnode = &vexia_edu_atla10_accel_node,
.swnode = &vexia_edu_atla10_9v_accel_node,
},
.adapter_path = "0000:00:18.5",
}, {
@ -688,7 +748,7 @@ static const struct x86_i2c_client_info vexia_edu_atla10_i2c_clients[] __initcon
.type = "hid-over-i2c",
.addr = 0x38,
.dev_name = "FTSC1000",
.swnode = &vexia_edu_atla10_touchscreen_node,
.swnode = &vexia_edu_atla10_9v_touchscreen_node,
},
.adapter_path = "0000:00:18.6",
.irq_data = {
@ -703,7 +763,7 @@ static const struct x86_i2c_client_info vexia_edu_atla10_i2c_clients[] __initcon
.type = "intel_soc_pmic_crc",
.addr = 0x6e,
.dev_name = "intel_soc_pmic_crc",
.swnode = &vexia_edu_atla10_pmic_node,
.swnode = &vexia_edu_atla10_9v_pmic_node,
},
.adapter_path = "0000:00:18.7",
.irq_data = {
@ -715,7 +775,7 @@ static const struct x86_i2c_client_info vexia_edu_atla10_i2c_clients[] __initcon
}
};
static const struct x86_serdev_info vexia_edu_atla10_serdevs[] __initconst = {
static const struct x86_serdev_info vexia_edu_atla10_9v_serdevs[] __initconst = {
{
.ctrl.pci.devfn = PCI_DEVFN(0x1e, 3),
.ctrl_devname = "serial0",
@ -723,7 +783,7 @@ static const struct x86_serdev_info vexia_edu_atla10_serdevs[] __initconst = {
},
};
static struct gpiod_lookup_table vexia_edu_atla10_ft5416_gpios = {
static struct gpiod_lookup_table vexia_edu_atla10_9v_ft5416_gpios = {
.dev_id = "i2c-FTSC1000",
.table = {
GPIO_LOOKUP("INT33FC:00", 60, "reset", GPIO_ACTIVE_LOW),
@ -731,12 +791,12 @@ static struct gpiod_lookup_table vexia_edu_atla10_ft5416_gpios = {
},
};
static struct gpiod_lookup_table * const vexia_edu_atla10_gpios[] = {
&vexia_edu_atla10_ft5416_gpios,
static struct gpiod_lookup_table * const vexia_edu_atla10_9v_gpios[] = {
&vexia_edu_atla10_9v_ft5416_gpios,
NULL
};
static int __init vexia_edu_atla10_init(struct device *dev)
static int __init vexia_edu_atla10_9v_init(struct device *dev)
{
struct pci_dev *pdev;
int ret;
@ -760,13 +820,13 @@ static int __init vexia_edu_atla10_init(struct device *dev)
return 0;
}
const struct x86_dev_info vexia_edu_atla10_info __initconst = {
.i2c_client_info = vexia_edu_atla10_i2c_clients,
.i2c_client_count = ARRAY_SIZE(vexia_edu_atla10_i2c_clients),
.serdev_info = vexia_edu_atla10_serdevs,
.serdev_count = ARRAY_SIZE(vexia_edu_atla10_serdevs),
.gpiod_lookup_tables = vexia_edu_atla10_gpios,
.init = vexia_edu_atla10_init,
const struct x86_dev_info vexia_edu_atla10_9v_info __initconst = {
.i2c_client_info = vexia_edu_atla10_9v_i2c_clients,
.i2c_client_count = ARRAY_SIZE(vexia_edu_atla10_9v_i2c_clients),
.serdev_info = vexia_edu_atla10_9v_serdevs,
.serdev_count = ARRAY_SIZE(vexia_edu_atla10_9v_serdevs),
.gpiod_lookup_tables = vexia_edu_atla10_9v_gpios,
.init = vexia_edu_atla10_9v_init,
.use_pci = true,
};

View file

@ -127,7 +127,8 @@ extern const struct x86_dev_info nextbook_ares8_info;
extern const struct x86_dev_info nextbook_ares8a_info;
extern const struct x86_dev_info peaq_c1010_info;
extern const struct x86_dev_info whitelabel_tm800a550l_info;
extern const struct x86_dev_info vexia_edu_atla10_info;
extern const struct x86_dev_info vexia_edu_atla10_5v_info;
extern const struct x86_dev_info vexia_edu_atla10_9v_info;
extern const struct x86_dev_info xiaomi_mipad2_info;
extern const struct dmi_system_id x86_android_tablet_ids[];

View file

@ -36,6 +36,7 @@ struct pmc_ipc_rbuf {
*/
static inline int intel_pmc_ipc(struct pmc_ipc_cmd *ipc_cmd, struct pmc_ipc_rbuf *rbuf)
{
#ifdef CONFIG_ACPI
struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL };
union acpi_object params[PMC_IPCS_PARAM_COUNT] = {
{.type = ACPI_TYPE_INTEGER,},
@ -89,6 +90,9 @@ static inline int intel_pmc_ipc(struct pmc_ipc_cmd *ipc_cmd, struct pmc_ipc_rbuf
}
return 0;
#else
return -ENODEV;
#endif /* CONFIG_ACPI */
}
#endif /* INTEL_PMC_IPC_H */