mirror of
https://mirrors.bfsu.edu.cn/git/linux.git
synced 2024-11-15 16:24:13 +08:00
Merge remote-tracking branch 'pdx86/fixes' into pdx86/for-next
Merge pdx86/fixes into pdx86/for-next because there are some pdx86 patches pending for the next release which build on top of some of the fixes.
This commit is contained in:
commit
b0c7f1d9d7
@ -187,7 +187,8 @@ WMI method BatteryeRawAnalytics()
|
||||
|
||||
Returns a buffer usually containg 12 blocks of analytics data.
|
||||
Those blocks contain:
|
||||
- block number starting with 0 (u8)
|
||||
|
||||
- a block number starting with 0 (u8)
|
||||
- 31 bytes of unknown data
|
||||
|
||||
.. note::
|
||||
|
@ -1714,6 +1714,7 @@ static bool acpi_device_enumeration_by_parent(struct acpi_device *device)
|
||||
{"BSG1160", },
|
||||
{"BSG2150", },
|
||||
{"CSC3551", },
|
||||
{"CSC3556", },
|
||||
{"INT33FE", },
|
||||
{"INT3515", },
|
||||
/* Non-conforming _HID for Cirrus Logic already released */
|
||||
|
@ -887,6 +887,7 @@ static bool mlxbf_tmfifo_virtio_notify(struct virtqueue *vq)
|
||||
tm_vdev = fifo->vdev[VIRTIO_ID_CONSOLE];
|
||||
mlxbf_tmfifo_console_output(tm_vdev, vring);
|
||||
spin_unlock_irqrestore(&fifo->spin_lock[0], flags);
|
||||
set_bit(MLXBF_TM_TX_LWM_IRQ, &fifo->pend_events);
|
||||
} else if (test_and_set_bit(MLXBF_TM_TX_LWM_IRQ,
|
||||
&fifo->pend_events)) {
|
||||
return true;
|
||||
|
@ -4,7 +4,7 @@
|
||||
# AMD x86 Platform-Specific Drivers
|
||||
#
|
||||
|
||||
amd-pmc-y := pmc.o
|
||||
amd-pmc-y := pmc.o pmc-quirks.o
|
||||
obj-$(CONFIG_AMD_PMC) += amd-pmc.o
|
||||
amd_hsmp-y := hsmp.o
|
||||
obj-$(CONFIG_AMD_HSMP) += amd_hsmp.o
|
||||
|
172
drivers/platform/x86/amd/pmc-quirks.c
Normal file
172
drivers/platform/x86/amd/pmc-quirks.c
Normal file
@ -0,0 +1,172 @@
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
/*
|
||||
* AMD SoC Power Management Controller Driver Quirks
|
||||
*
|
||||
* Copyright (c) 2023, Advanced Micro Devices, Inc.
|
||||
* All Rights Reserved.
|
||||
*
|
||||
* Author: Mario Limonciello <mario.limonciello@amd.com>
|
||||
*/
|
||||
|
||||
#include <linux/dmi.h>
|
||||
#include <linux/io.h>
|
||||
#include <linux/ioport.h>
|
||||
|
||||
#include "pmc.h"
|
||||
|
||||
struct quirk_entry {
|
||||
u32 s2idle_bug_mmio;
|
||||
};
|
||||
|
||||
static struct quirk_entry quirk_s2idle_bug = {
|
||||
.s2idle_bug_mmio = 0xfed80380,
|
||||
};
|
||||
|
||||
static const struct dmi_system_id fwbug_list[] = {
|
||||
{
|
||||
.ident = "L14 Gen2 AMD",
|
||||
.driver_data = &quirk_s2idle_bug,
|
||||
.matches = {
|
||||
DMI_MATCH(DMI_BOARD_VENDOR, "LENOVO"),
|
||||
DMI_MATCH(DMI_PRODUCT_NAME, "20X5"),
|
||||
}
|
||||
},
|
||||
{
|
||||
.ident = "T14s Gen2 AMD",
|
||||
.driver_data = &quirk_s2idle_bug,
|
||||
.matches = {
|
||||
DMI_MATCH(DMI_BOARD_VENDOR, "LENOVO"),
|
||||
DMI_MATCH(DMI_PRODUCT_NAME, "20XF"),
|
||||
}
|
||||
},
|
||||
{
|
||||
.ident = "X13 Gen2 AMD",
|
||||
.driver_data = &quirk_s2idle_bug,
|
||||
.matches = {
|
||||
DMI_MATCH(DMI_BOARD_VENDOR, "LENOVO"),
|
||||
DMI_MATCH(DMI_PRODUCT_NAME, "20XH"),
|
||||
}
|
||||
},
|
||||
{
|
||||
.ident = "T14 Gen2 AMD",
|
||||
.driver_data = &quirk_s2idle_bug,
|
||||
.matches = {
|
||||
DMI_MATCH(DMI_BOARD_VENDOR, "LENOVO"),
|
||||
DMI_MATCH(DMI_PRODUCT_NAME, "20XK"),
|
||||
}
|
||||
},
|
||||
{
|
||||
.ident = "T14 Gen1 AMD",
|
||||
.driver_data = &quirk_s2idle_bug,
|
||||
.matches = {
|
||||
DMI_MATCH(DMI_BOARD_VENDOR, "LENOVO"),
|
||||
DMI_MATCH(DMI_PRODUCT_NAME, "20UD"),
|
||||
}
|
||||
},
|
||||
{
|
||||
.ident = "T14 Gen1 AMD",
|
||||
.driver_data = &quirk_s2idle_bug,
|
||||
.matches = {
|
||||
DMI_MATCH(DMI_BOARD_VENDOR, "LENOVO"),
|
||||
DMI_MATCH(DMI_PRODUCT_NAME, "20UE"),
|
||||
}
|
||||
},
|
||||
{
|
||||
.ident = "T14s Gen1 AMD",
|
||||
.driver_data = &quirk_s2idle_bug,
|
||||
.matches = {
|
||||
DMI_MATCH(DMI_BOARD_VENDOR, "LENOVO"),
|
||||
DMI_MATCH(DMI_PRODUCT_NAME, "20UH"),
|
||||
}
|
||||
},
|
||||
{
|
||||
.ident = "T14s Gen1 AMD",
|
||||
.driver_data = &quirk_s2idle_bug,
|
||||
.matches = {
|
||||
DMI_MATCH(DMI_BOARD_VENDOR, "LENOVO"),
|
||||
DMI_MATCH(DMI_PRODUCT_NAME, "20UJ"),
|
||||
}
|
||||
},
|
||||
{
|
||||
.ident = "P14s Gen1 AMD",
|
||||
.driver_data = &quirk_s2idle_bug,
|
||||
.matches = {
|
||||
DMI_MATCH(DMI_BOARD_VENDOR, "LENOVO"),
|
||||
DMI_MATCH(DMI_PRODUCT_NAME, "20Y1"),
|
||||
}
|
||||
},
|
||||
{
|
||||
.ident = "P14s Gen2 AMD",
|
||||
.driver_data = &quirk_s2idle_bug,
|
||||
.matches = {
|
||||
DMI_MATCH(DMI_BOARD_VENDOR, "LENOVO"),
|
||||
DMI_MATCH(DMI_PRODUCT_NAME, "21A0"),
|
||||
}
|
||||
},
|
||||
{
|
||||
.ident = "P14s Gen2 AMD",
|
||||
.driver_data = &quirk_s2idle_bug,
|
||||
.matches = {
|
||||
DMI_MATCH(DMI_BOARD_VENDOR, "LENOVO"),
|
||||
DMI_MATCH(DMI_PRODUCT_NAME, "21A1"),
|
||||
}
|
||||
},
|
||||
/* https://gitlab.freedesktop.org/drm/amd/-/issues/2684 */
|
||||
{
|
||||
.ident = "HP Laptop 15s-eq2xxx",
|
||||
.driver_data = &quirk_s2idle_bug,
|
||||
.matches = {
|
||||
DMI_MATCH(DMI_SYS_VENDOR, "HP"),
|
||||
DMI_MATCH(DMI_PRODUCT_NAME, "HP Laptop 15s-eq2xxx"),
|
||||
}
|
||||
},
|
||||
{}
|
||||
};
|
||||
|
||||
/*
|
||||
* Laptops that run a SMI handler during the D3->D0 transition that occurs
|
||||
* specifically when exiting suspend to idle which can cause
|
||||
* large delays during resume when the IOMMU translation layer is enabled (the default
|
||||
* behavior) for NVME devices:
|
||||
*
|
||||
* To avoid this firmware problem, skip the SMI handler on these machines before the
|
||||
* D0 transition occurs.
|
||||
*/
|
||||
static void amd_pmc_skip_nvme_smi_handler(u32 s2idle_bug_mmio)
|
||||
{
|
||||
void __iomem *addr;
|
||||
u8 val;
|
||||
|
||||
if (!request_mem_region_muxed(s2idle_bug_mmio, 1, "amd_pmc_pm80"))
|
||||
return;
|
||||
|
||||
addr = ioremap(s2idle_bug_mmio, 1);
|
||||
if (!addr)
|
||||
goto cleanup_resource;
|
||||
|
||||
val = ioread8(addr);
|
||||
iowrite8(val & ~BIT(0), addr);
|
||||
|
||||
iounmap(addr);
|
||||
cleanup_resource:
|
||||
release_mem_region(s2idle_bug_mmio, 1);
|
||||
}
|
||||
|
||||
void amd_pmc_process_restore_quirks(struct amd_pmc_dev *dev)
|
||||
{
|
||||
if (dev->quirks && dev->quirks->s2idle_bug_mmio)
|
||||
amd_pmc_skip_nvme_smi_handler(dev->quirks->s2idle_bug_mmio);
|
||||
}
|
||||
|
||||
void amd_pmc_quirks_init(struct amd_pmc_dev *dev)
|
||||
{
|
||||
const struct dmi_system_id *dmi_id;
|
||||
|
||||
dmi_id = dmi_first_match(fwbug_list);
|
||||
if (!dmi_id)
|
||||
return;
|
||||
dev->quirks = dmi_id->driver_data;
|
||||
if (dev->quirks->s2idle_bug_mmio)
|
||||
pr_info("Using s2idle quirk to avoid %s platform firmware bug\n",
|
||||
dmi_id->ident);
|
||||
}
|
@ -28,6 +28,8 @@
|
||||
#include <linux/seq_file.h>
|
||||
#include <linux/uaccess.h>
|
||||
|
||||
#include "pmc.h"
|
||||
|
||||
/* SMU communication registers */
|
||||
#define AMD_PMC_REGISTER_MESSAGE 0x538
|
||||
#define AMD_PMC_REGISTER_RESPONSE 0x980
|
||||
@ -94,6 +96,7 @@
|
||||
#define AMD_CPU_ID_CB 0x14D8
|
||||
#define AMD_CPU_ID_PS 0x14E8
|
||||
#define AMD_CPU_ID_SP 0x14A4
|
||||
#define PCI_DEVICE_ID_AMD_1AH_M20H_ROOT 0x1507
|
||||
|
||||
#define PMC_MSG_DELAY_MIN_US 50
|
||||
#define RESPONSE_REGISTER_LOOP_MAX 20000
|
||||
@ -146,29 +149,6 @@ static const struct amd_pmc_bit_map soc15_ip_blk[] = {
|
||||
{}
|
||||
};
|
||||
|
||||
struct amd_pmc_dev {
|
||||
void __iomem *regbase;
|
||||
void __iomem *smu_virt_addr;
|
||||
void __iomem *stb_virt_addr;
|
||||
void __iomem *fch_virt_addr;
|
||||
bool msg_port;
|
||||
u32 base_addr;
|
||||
u32 cpu_id;
|
||||
u32 active_ips;
|
||||
u32 dram_size;
|
||||
u32 num_ips;
|
||||
u32 s2d_msg_id;
|
||||
/* SMU version information */
|
||||
u8 smu_program;
|
||||
u8 major;
|
||||
u8 minor;
|
||||
u8 rev;
|
||||
struct device *dev;
|
||||
struct pci_dev *rdev;
|
||||
struct mutex lock; /* generic mutex lock */
|
||||
struct dentry *dbgfs_dir;
|
||||
};
|
||||
|
||||
static bool enable_stb;
|
||||
module_param(enable_stb, bool, 0644);
|
||||
MODULE_PARM_DESC(enable_stb, "Enable the STB debug mechanism");
|
||||
@ -891,6 +871,8 @@ static void amd_pmc_s2idle_restore(void)
|
||||
|
||||
/* Notify on failed entry */
|
||||
amd_pmc_validate_deepest(pdev);
|
||||
|
||||
amd_pmc_process_restore_quirks(pdev);
|
||||
}
|
||||
|
||||
static struct acpi_s2idle_dev_ops amd_pmc_s2idle_dev_ops = {
|
||||
@ -926,6 +908,7 @@ static const struct pci_device_id pmc_pci_ids[] = {
|
||||
{ PCI_DEVICE(PCI_VENDOR_ID_AMD, AMD_CPU_ID_PCO) },
|
||||
{ PCI_DEVICE(PCI_VENDOR_ID_AMD, AMD_CPU_ID_RV) },
|
||||
{ PCI_DEVICE(PCI_VENDOR_ID_AMD, AMD_CPU_ID_SP) },
|
||||
{ PCI_DEVICE(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_1AH_M20H_ROOT) },
|
||||
{ }
|
||||
};
|
||||
|
||||
@ -1087,6 +1070,8 @@ static int amd_pmc_probe(struct platform_device *pdev)
|
||||
err = acpi_register_lps0_dev(&amd_pmc_s2idle_dev_ops);
|
||||
if (err)
|
||||
dev_warn(dev->dev, "failed to register LPS0 sleep handler, expect increased power consumption\n");
|
||||
if (!disable_workarounds)
|
||||
amd_pmc_quirks_init(dev);
|
||||
}
|
||||
|
||||
amd_pmc_dbgfs_register(dev);
|
||||
@ -1115,6 +1100,7 @@ static const struct acpi_device_id amd_pmc_acpi_ids[] = {
|
||||
{"AMDI0007", 0},
|
||||
{"AMDI0008", 0},
|
||||
{"AMDI0009", 0},
|
||||
{"AMDI000A", 0},
|
||||
{"AMD0004", 0},
|
||||
{"AMD0005", 0},
|
||||
{ }
|
||||
|
44
drivers/platform/x86/amd/pmc.h
Normal file
44
drivers/platform/x86/amd/pmc.h
Normal file
@ -0,0 +1,44 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0-or-later */
|
||||
/*
|
||||
* AMD SoC Power Management Controller Driver
|
||||
*
|
||||
* Copyright (c) 2023, Advanced Micro Devices, Inc.
|
||||
* All Rights Reserved.
|
||||
*
|
||||
* Author: Mario Limonciello <mario.limonciello@amd.com>
|
||||
*/
|
||||
|
||||
#ifndef PMC_H
|
||||
#define PMC_H
|
||||
|
||||
#include <linux/types.h>
|
||||
#include <linux/mutex.h>
|
||||
|
||||
struct amd_pmc_dev {
|
||||
void __iomem *regbase;
|
||||
void __iomem *smu_virt_addr;
|
||||
void __iomem *stb_virt_addr;
|
||||
void __iomem *fch_virt_addr;
|
||||
bool msg_port;
|
||||
u32 base_addr;
|
||||
u32 cpu_id;
|
||||
u32 active_ips;
|
||||
u32 dram_size;
|
||||
u32 num_ips;
|
||||
u32 s2d_msg_id;
|
||||
/* SMU version information */
|
||||
u8 smu_program;
|
||||
u8 major;
|
||||
u8 minor;
|
||||
u8 rev;
|
||||
struct device *dev;
|
||||
struct pci_dev *rdev;
|
||||
struct mutex lock; /* generic mutex lock */
|
||||
struct dentry *dbgfs_dir;
|
||||
struct quirk_entry *quirks;
|
||||
};
|
||||
|
||||
void amd_pmc_process_restore_quirks(struct amd_pmc_dev *dev);
|
||||
void amd_pmc_quirks_init(struct amd_pmc_dev *dev);
|
||||
|
||||
#endif /* PMC_H */
|
@ -106,6 +106,27 @@ int apmf_get_static_slider_granular(struct amd_pmf_dev *pdev,
|
||||
data, sizeof(*data));
|
||||
}
|
||||
|
||||
int apmf_os_power_slider_update(struct amd_pmf_dev *pdev, u8 event)
|
||||
{
|
||||
struct os_power_slider args;
|
||||
struct acpi_buffer params;
|
||||
union acpi_object *info;
|
||||
int err = 0;
|
||||
|
||||
args.size = sizeof(args);
|
||||
args.slider_event = event;
|
||||
|
||||
params.length = sizeof(args);
|
||||
params.pointer = (void *)&args;
|
||||
|
||||
info = apmf_if_call(pdev, APMF_FUNC_OS_POWER_SLIDER_UPDATE, ¶ms);
|
||||
if (!info)
|
||||
err = -EIO;
|
||||
|
||||
kfree(info);
|
||||
return err;
|
||||
}
|
||||
|
||||
static void apmf_sbios_heartbeat_notify(struct work_struct *work)
|
||||
{
|
||||
struct amd_pmf_dev *dev = container_of(work, struct amd_pmf_dev, heart_beat.work);
|
||||
@ -289,7 +310,7 @@ int apmf_acpi_init(struct amd_pmf_dev *pmf_dev)
|
||||
|
||||
ret = apmf_get_system_params(pmf_dev);
|
||||
if (ret) {
|
||||
dev_err(pmf_dev->dev, "APMF apmf_get_system_params failed :%d\n", ret);
|
||||
dev_dbg(pmf_dev->dev, "APMF apmf_get_system_params failed :%d\n", ret);
|
||||
goto out;
|
||||
}
|
||||
|
||||
|
@ -40,6 +40,7 @@
|
||||
/* List of supported CPU ids */
|
||||
#define AMD_CPU_ID_RMB 0x14b5
|
||||
#define AMD_CPU_ID_PS 0x14e8
|
||||
#define PCI_DEVICE_ID_AMD_1AH_M20H_ROOT 0x1507
|
||||
|
||||
#define PMF_MSG_DELAY_MIN_US 50
|
||||
#define RESPONSE_REGISTER_LOOP_MAX 20000
|
||||
@ -71,7 +72,11 @@ static int amd_pmf_pwr_src_notify_call(struct notifier_block *nb, unsigned long
|
||||
return NOTIFY_DONE;
|
||||
}
|
||||
|
||||
amd_pmf_set_sps_power_limits(pmf);
|
||||
if (is_apmf_func_supported(pmf, APMF_FUNC_STATIC_SLIDER_GRANULAR))
|
||||
amd_pmf_set_sps_power_limits(pmf);
|
||||
|
||||
if (is_apmf_func_supported(pmf, APMF_FUNC_OS_POWER_SLIDER_UPDATE))
|
||||
amd_pmf_power_slider_update_event(pmf);
|
||||
|
||||
return NOTIFY_OK;
|
||||
}
|
||||
@ -242,6 +247,7 @@ out_unlock:
|
||||
static const struct pci_device_id pmf_pci_ids[] = {
|
||||
{ PCI_DEVICE(PCI_VENDOR_ID_AMD, AMD_CPU_ID_RMB) },
|
||||
{ PCI_DEVICE(PCI_VENDOR_ID_AMD, AMD_CPU_ID_PS) },
|
||||
{ PCI_DEVICE(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_1AH_M20H_ROOT) },
|
||||
{ }
|
||||
};
|
||||
|
||||
@ -295,7 +301,8 @@ static void amd_pmf_init_features(struct amd_pmf_dev *dev)
|
||||
int ret;
|
||||
|
||||
/* Enable Static Slider */
|
||||
if (is_apmf_func_supported(dev, APMF_FUNC_STATIC_SLIDER_GRANULAR)) {
|
||||
if (is_apmf_func_supported(dev, APMF_FUNC_STATIC_SLIDER_GRANULAR) ||
|
||||
is_apmf_func_supported(dev, APMF_FUNC_OS_POWER_SLIDER_UPDATE)) {
|
||||
amd_pmf_init_sps(dev);
|
||||
dev->pwr_src_notifier.notifier_call = amd_pmf_pwr_src_notify_call;
|
||||
power_supply_reg_notifier(&dev->pwr_src_notifier);
|
||||
@ -333,6 +340,7 @@ static void amd_pmf_deinit_features(struct amd_pmf_dev *dev)
|
||||
static const struct acpi_device_id amd_pmf_acpi_ids[] = {
|
||||
{"AMDI0100", 0x100},
|
||||
{"AMDI0102", 0},
|
||||
{"AMDI0103", 0},
|
||||
{ }
|
||||
};
|
||||
MODULE_DEVICE_TABLE(acpi, amd_pmf_acpi_ids);
|
||||
|
@ -21,6 +21,7 @@
|
||||
#define APMF_FUNC_SBIOS_HEARTBEAT 4
|
||||
#define APMF_FUNC_AUTO_MODE 5
|
||||
#define APMF_FUNC_SET_FAN_IDX 7
|
||||
#define APMF_FUNC_OS_POWER_SLIDER_UPDATE 8
|
||||
#define APMF_FUNC_STATIC_SLIDER_GRANULAR 9
|
||||
#define APMF_FUNC_DYN_SLIDER_AC 11
|
||||
#define APMF_FUNC_DYN_SLIDER_DC 12
|
||||
@ -44,6 +45,14 @@
|
||||
#define GET_STT_LIMIT_APU 0x20
|
||||
#define GET_STT_LIMIT_HS2 0x21
|
||||
|
||||
/* OS slider update notification */
|
||||
#define DC_BEST_PERF 0
|
||||
#define DC_BETTER_PERF 1
|
||||
#define DC_BATTERY_SAVER 3
|
||||
#define AC_BEST_PERF 4
|
||||
#define AC_BETTER_PERF 5
|
||||
#define AC_BETTER_BATTERY 6
|
||||
|
||||
/* Fan Index for Auto Mode */
|
||||
#define FAN_INDEX_AUTO 0xFFFFFFFF
|
||||
|
||||
@ -193,6 +202,11 @@ struct amd_pmf_static_slider_granular {
|
||||
struct apmf_sps_prop_granular prop[POWER_SOURCE_MAX][POWER_MODE_MAX];
|
||||
};
|
||||
|
||||
struct os_power_slider {
|
||||
u16 size;
|
||||
u8 slider_event;
|
||||
} __packed;
|
||||
|
||||
struct fan_table_control {
|
||||
bool manual;
|
||||
unsigned long fan_id;
|
||||
@ -383,6 +397,7 @@ int amd_pmf_send_cmd(struct amd_pmf_dev *dev, u8 message, bool get, u32 arg, u32
|
||||
int amd_pmf_init_metrics_table(struct amd_pmf_dev *dev);
|
||||
int amd_pmf_get_power_source(void);
|
||||
int apmf_install_handler(struct amd_pmf_dev *pmf_dev);
|
||||
int apmf_os_power_slider_update(struct amd_pmf_dev *dev, u8 flag);
|
||||
|
||||
/* SPS Layer */
|
||||
int amd_pmf_get_pprof_modes(struct amd_pmf_dev *pmf);
|
||||
@ -393,6 +408,7 @@ void amd_pmf_deinit_sps(struct amd_pmf_dev *dev);
|
||||
int apmf_get_static_slider_granular(struct amd_pmf_dev *pdev,
|
||||
struct apmf_static_slider_granular_output *output);
|
||||
bool is_pprof_balanced(struct amd_pmf_dev *pmf);
|
||||
int amd_pmf_power_slider_update_event(struct amd_pmf_dev *dev);
|
||||
|
||||
|
||||
int apmf_update_fan_idx(struct amd_pmf_dev *pdev, bool manual, u32 idx);
|
||||
|
@ -174,14 +174,78 @@ int amd_pmf_get_pprof_modes(struct amd_pmf_dev *pmf)
|
||||
return mode;
|
||||
}
|
||||
|
||||
int amd_pmf_power_slider_update_event(struct amd_pmf_dev *dev)
|
||||
{
|
||||
u8 flag = 0;
|
||||
int mode;
|
||||
int src;
|
||||
|
||||
mode = amd_pmf_get_pprof_modes(dev);
|
||||
if (mode < 0)
|
||||
return mode;
|
||||
|
||||
src = amd_pmf_get_power_source();
|
||||
|
||||
if (src == POWER_SOURCE_AC) {
|
||||
switch (mode) {
|
||||
case POWER_MODE_PERFORMANCE:
|
||||
flag |= BIT(AC_BEST_PERF);
|
||||
break;
|
||||
case POWER_MODE_BALANCED_POWER:
|
||||
flag |= BIT(AC_BETTER_PERF);
|
||||
break;
|
||||
case POWER_MODE_POWER_SAVER:
|
||||
flag |= BIT(AC_BETTER_BATTERY);
|
||||
break;
|
||||
default:
|
||||
dev_err(dev->dev, "unsupported platform profile\n");
|
||||
return -EOPNOTSUPP;
|
||||
}
|
||||
|
||||
} else if (src == POWER_SOURCE_DC) {
|
||||
switch (mode) {
|
||||
case POWER_MODE_PERFORMANCE:
|
||||
flag |= BIT(DC_BEST_PERF);
|
||||
break;
|
||||
case POWER_MODE_BALANCED_POWER:
|
||||
flag |= BIT(DC_BETTER_PERF);
|
||||
break;
|
||||
case POWER_MODE_POWER_SAVER:
|
||||
flag |= BIT(DC_BATTERY_SAVER);
|
||||
break;
|
||||
default:
|
||||
dev_err(dev->dev, "unsupported platform profile\n");
|
||||
return -EOPNOTSUPP;
|
||||
}
|
||||
}
|
||||
|
||||
apmf_os_power_slider_update(dev, flag);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int amd_pmf_profile_set(struct platform_profile_handler *pprof,
|
||||
enum platform_profile_option profile)
|
||||
{
|
||||
struct amd_pmf_dev *pmf = container_of(pprof, struct amd_pmf_dev, pprof);
|
||||
int ret = 0;
|
||||
|
||||
pmf->current_profile = profile;
|
||||
|
||||
return amd_pmf_set_sps_power_limits(pmf);
|
||||
/* Notify EC about the slider position change */
|
||||
if (is_apmf_func_supported(pmf, APMF_FUNC_OS_POWER_SLIDER_UPDATE)) {
|
||||
ret = amd_pmf_power_slider_update_event(pmf);
|
||||
if (ret)
|
||||
return ret;
|
||||
}
|
||||
|
||||
if (is_apmf_func_supported(pmf, APMF_FUNC_STATIC_SLIDER_GRANULAR)) {
|
||||
ret = amd_pmf_set_sps_power_limits(pmf);
|
||||
if (ret)
|
||||
return ret;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int amd_pmf_init_sps(struct amd_pmf_dev *dev)
|
||||
@ -189,10 +253,13 @@ int amd_pmf_init_sps(struct amd_pmf_dev *dev)
|
||||
int err;
|
||||
|
||||
dev->current_profile = PLATFORM_PROFILE_BALANCED;
|
||||
amd_pmf_load_defaults_sps(dev);
|
||||
|
||||
/* update SPS balanced power mode thermals */
|
||||
amd_pmf_set_sps_power_limits(dev);
|
||||
if (is_apmf_func_supported(dev, APMF_FUNC_STATIC_SLIDER_GRANULAR)) {
|
||||
amd_pmf_load_defaults_sps(dev);
|
||||
|
||||
/* update SPS balanced power mode thermals */
|
||||
amd_pmf_set_sps_power_limits(dev);
|
||||
}
|
||||
|
||||
dev->pprof.profile_get = amd_pmf_profile_get;
|
||||
dev->pprof.profile_set = amd_pmf_profile_set;
|
||||
|
@ -854,13 +854,23 @@ static ssize_t kbd_rgb_mode_store(struct device *dev,
|
||||
struct device_attribute *attr,
|
||||
const char *buf, size_t count)
|
||||
{
|
||||
u32 cmd, mode, r, g, b, speed;
|
||||
u32 cmd, mode, r, g, b, speed;
|
||||
int err;
|
||||
|
||||
if (sscanf(buf, "%d %d %d %d %d %d", &cmd, &mode, &r, &g, &b, &speed) != 6)
|
||||
return -EINVAL;
|
||||
|
||||
cmd = !!cmd;
|
||||
/* B3 is set and B4 is save to BIOS */
|
||||
switch (cmd) {
|
||||
case 0:
|
||||
cmd = 0xb3;
|
||||
break;
|
||||
case 1:
|
||||
cmd = 0xb4;
|
||||
break;
|
||||
default:
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
/* These are the known usable modes across all TUF/ROG */
|
||||
if (mode >= 12 || mode == 9)
|
||||
|
@ -616,7 +616,8 @@ static int dell_wmi_ddv_hwmon_add(struct dell_wmi_ddv_data *data)
|
||||
}
|
||||
|
||||
if (index < 2) {
|
||||
ret = -ENODEV;
|
||||
/* Finding no available sensors is not an error */
|
||||
ret = 0;
|
||||
|
||||
goto err_release;
|
||||
}
|
||||
@ -841,13 +842,13 @@ static int dell_wmi_ddv_probe(struct wmi_device *wdev, const void *context)
|
||||
|
||||
if (IS_REACHABLE(CONFIG_ACPI_BATTERY)) {
|
||||
ret = dell_wmi_ddv_battery_add(data);
|
||||
if (ret < 0 && ret != -ENODEV)
|
||||
if (ret < 0)
|
||||
dev_warn(&wdev->dev, "Unable to register ACPI battery hook: %d\n", ret);
|
||||
}
|
||||
|
||||
if (IS_REACHABLE(CONFIG_HWMON)) {
|
||||
ret = dell_wmi_ddv_hwmon_add(data);
|
||||
if (ret < 0 && ret != -ENODEV)
|
||||
if (ret < 0)
|
||||
dev_warn(&wdev->dev, "Unable to register hwmon interface: %d\n", ret);
|
||||
}
|
||||
|
||||
|
@ -85,6 +85,8 @@ static const struct key_entry huawei_wmi_keymap[] = {
|
||||
{ KE_IGNORE, 0x293, { KEY_KBDILLUMTOGGLE } },
|
||||
{ KE_IGNORE, 0x294, { KEY_KBDILLUMUP } },
|
||||
{ KE_IGNORE, 0x295, { KEY_KBDILLUMUP } },
|
||||
// Ignore Ambient Light Sensoring
|
||||
{ KE_KEY, 0x2c1, { KEY_RESERVED } },
|
||||
{ KE_END, 0 }
|
||||
};
|
||||
|
||||
|
@ -1049,6 +1049,11 @@ static const struct key_entry ideapad_keymap[] = {
|
||||
{ KE_IGNORE, 0x03 | IDEAPAD_WMI_KEY },
|
||||
/* Customizable Lenovo Hotkey ("star" with 'S' inside) */
|
||||
{ KE_KEY, 0x01 | IDEAPAD_WMI_KEY, { KEY_FAVORITES } },
|
||||
{ KE_KEY, 0x04 | IDEAPAD_WMI_KEY, { KEY_SELECTIVE_SCREENSHOT } },
|
||||
/* Lenovo Support */
|
||||
{ KE_KEY, 0x07 | IDEAPAD_WMI_KEY, { KEY_HELP } },
|
||||
{ KE_KEY, 0x0e | IDEAPAD_WMI_KEY, { KEY_PICKUP_PHONE } },
|
||||
{ KE_KEY, 0x0f | IDEAPAD_WMI_KEY, { KEY_HANGUP_PHONE } },
|
||||
/* Dark mode toggle */
|
||||
{ KE_KEY, 0x13 | IDEAPAD_WMI_KEY, { KEY_PROG1 } },
|
||||
/* Sound profile switch */
|
||||
|
@ -150,6 +150,12 @@ static const struct dmi_system_id dmi_vgbs_allow_list[] = {
|
||||
DMI_MATCH(DMI_PRODUCT_NAME, "Surface Go"),
|
||||
},
|
||||
},
|
||||
{
|
||||
.matches = {
|
||||
DMI_MATCH(DMI_SYS_VENDOR, "HP"),
|
||||
DMI_MATCH(DMI_PRODUCT_NAME, "HP Elite Dragonfly G2 Notebook PC"),
|
||||
},
|
||||
},
|
||||
{ }
|
||||
};
|
||||
|
||||
@ -620,7 +626,7 @@ static bool button_array_present(struct platform_device *device)
|
||||
static int intel_hid_probe(struct platform_device *device)
|
||||
{
|
||||
acpi_handle handle = ACPI_HANDLE(&device->dev);
|
||||
unsigned long long mode;
|
||||
unsigned long long mode, dummy;
|
||||
struct intel_hid_priv *priv;
|
||||
acpi_status status;
|
||||
int err;
|
||||
@ -692,18 +698,15 @@ static int intel_hid_probe(struct platform_device *device)
|
||||
if (err)
|
||||
goto err_remove_notify;
|
||||
|
||||
if (priv->array) {
|
||||
unsigned long long dummy;
|
||||
intel_button_array_enable(&device->dev, true);
|
||||
|
||||
intel_button_array_enable(&device->dev, true);
|
||||
|
||||
/* Call button load method to enable HID power button */
|
||||
if (!intel_hid_evaluate_method(handle, INTEL_HID_DSM_BTNL_FN,
|
||||
&dummy)) {
|
||||
dev_warn(&device->dev,
|
||||
"failed to enable HID power button\n");
|
||||
}
|
||||
}
|
||||
/*
|
||||
* Call button load method to enable HID power button
|
||||
* Always do this since it activates events on some devices without
|
||||
* a button array too.
|
||||
*/
|
||||
if (!intel_hid_evaluate_method(handle, INTEL_HID_DSM_BTNL_FN, &dummy))
|
||||
dev_warn(&device->dev, "failed to enable HID power button\n");
|
||||
|
||||
device_init_wakeup(&device->dev, true);
|
||||
/*
|
||||
|
@ -260,7 +260,7 @@ static_assert(ARRAY_SIZE(skl_int3472_regulator_map_supplies) ==
|
||||
* This DMI table contains the name of the second sensor. This is used to add
|
||||
* entries for the second sensor to the supply_map.
|
||||
*/
|
||||
const struct dmi_system_id skl_int3472_regulator_second_sensor[] = {
|
||||
static const struct dmi_system_id skl_int3472_regulator_second_sensor[] = {
|
||||
{
|
||||
/* Lenovo Miix 510-12IKB */
|
||||
.matches = {
|
||||
|
@ -335,8 +335,8 @@ static struct pci_dev *_isst_if_get_pci_dev(int cpu, int bus_no, int dev, int fn
|
||||
|
||||
node = dev_to_node(&_pci_dev->dev);
|
||||
if (node == NUMA_NO_NODE) {
|
||||
pr_info("Fail to get numa node for CPU:%d bus:%d dev:%d fn:%d\n",
|
||||
cpu, bus_no, dev, fn);
|
||||
pr_info_once("Fail to get numa node for CPU:%d bus:%d dev:%d fn:%d\n",
|
||||
cpu, bus_no, dev, fn);
|
||||
continue;
|
||||
}
|
||||
|
||||
|
@ -723,9 +723,7 @@ static int intel_vsec_tpmi_init(struct auxiliary_device *auxdev)
|
||||
if (!pfs_start)
|
||||
pfs_start = res_start;
|
||||
|
||||
pfs->pfs_header.cap_offset *= TPMI_CAP_OFFSET_UNIT;
|
||||
|
||||
pfs->vsec_offset = pfs_start + pfs->pfs_header.cap_offset;
|
||||
pfs->vsec_offset = pfs_start + pfs->pfs_header.cap_offset * TPMI_CAP_OFFSET_UNIT;
|
||||
|
||||
/*
|
||||
* Process TPMI_INFO to get PCI device to CPU package ID.
|
||||
|
@ -24,6 +24,10 @@ static bool ec_trigger __read_mostly;
|
||||
module_param(ec_trigger, bool, 0444);
|
||||
MODULE_PARM_DESC(ec_trigger, "Enable EC triggering work-around to force emitting tablet mode events");
|
||||
|
||||
static bool force;
|
||||
module_param(force, bool, 0444);
|
||||
MODULE_PARM_DESC(force, "Force loading on boards without a convertible DMI chassis-type");
|
||||
|
||||
static const struct dmi_system_id ec_trigger_quirk_dmi_table[] = {
|
||||
{
|
||||
/* Lenovo Yoga 7 14ARB7 */
|
||||
@ -32,6 +36,27 @@ static const struct dmi_system_id ec_trigger_quirk_dmi_table[] = {
|
||||
DMI_MATCH(DMI_PRODUCT_NAME, "82QF"),
|
||||
},
|
||||
},
|
||||
{
|
||||
/* Lenovo Yoga 7 14ACN6 */
|
||||
.matches = {
|
||||
DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"),
|
||||
DMI_MATCH(DMI_PRODUCT_NAME, "82N7"),
|
||||
},
|
||||
},
|
||||
{ }
|
||||
};
|
||||
|
||||
static const struct dmi_system_id allowed_chasis_types_dmi_table[] = {
|
||||
{
|
||||
.matches = {
|
||||
DMI_EXACT_MATCH(DMI_CHASSIS_TYPE, "31" /* Convertible */),
|
||||
},
|
||||
},
|
||||
{
|
||||
.matches = {
|
||||
DMI_EXACT_MATCH(DMI_CHASSIS_TYPE, "32" /* Detachable */),
|
||||
},
|
||||
},
|
||||
{ }
|
||||
};
|
||||
|
||||
@ -111,6 +136,13 @@ static int lenovo_ymc_probe(struct wmi_device *wdev, const void *ctx)
|
||||
struct input_dev *input_dev;
|
||||
int err;
|
||||
|
||||
if (!dmi_check_system(allowed_chasis_types_dmi_table)) {
|
||||
if (force)
|
||||
dev_info(&wdev->dev, "Force loading Lenovo YMC support\n");
|
||||
else
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
ec_trigger |= dmi_check_system(ec_trigger_quirk_dmi_table);
|
||||
|
||||
priv = devm_kzalloc(&wdev->dev, sizeof(*priv), GFP_KERNEL);
|
||||
|
@ -62,10 +62,6 @@
|
||||
#define MLXPLAT_CPLD_LPC_REG_PWM_CONTROL_OFFSET 0x37
|
||||
#define MLXPLAT_CPLD_LPC_REG_AGGR_OFFSET 0x3a
|
||||
#define MLXPLAT_CPLD_LPC_REG_AGGR_MASK_OFFSET 0x3b
|
||||
#define MLXPLAT_CPLD_LPC_REG_DBG1_OFFSET 0x3c
|
||||
#define MLXPLAT_CPLD_LPC_REG_DBG2_OFFSET 0x3d
|
||||
#define MLXPLAT_CPLD_LPC_REG_DBG3_OFFSET 0x3e
|
||||
#define MLXPLAT_CPLD_LPC_REG_DBG4_OFFSET 0x3f
|
||||
#define MLXPLAT_CPLD_LPC_REG_AGGRLO_OFFSET 0x40
|
||||
#define MLXPLAT_CPLD_LPC_REG_AGGRLO_MASK_OFFSET 0x41
|
||||
#define MLXPLAT_CPLD_LPC_REG_AGGRCO_OFFSET 0x42
|
||||
@ -126,6 +122,10 @@
|
||||
#define MLXPLAT_CPLD_LPC_REG_LC_SD_EVENT_OFFSET 0xaa
|
||||
#define MLXPLAT_CPLD_LPC_REG_LC_SD_MASK_OFFSET 0xab
|
||||
#define MLXPLAT_CPLD_LPC_REG_LC_PWR_ON 0xb2
|
||||
#define MLXPLAT_CPLD_LPC_REG_DBG1_OFFSET 0xb6
|
||||
#define MLXPLAT_CPLD_LPC_REG_DBG2_OFFSET 0xb7
|
||||
#define MLXPLAT_CPLD_LPC_REG_DBG3_OFFSET 0xb8
|
||||
#define MLXPLAT_CPLD_LPC_REG_DBG4_OFFSET 0xb9
|
||||
#define MLXPLAT_CPLD_LPC_REG_GP4_RO_OFFSET 0xc2
|
||||
#define MLXPLAT_CPLD_LPC_REG_SPI_CHNL_SELECT 0xc3
|
||||
#define MLXPLAT_CPLD_LPC_REG_WD_CLEAR_OFFSET 0xc7
|
||||
@ -222,7 +222,7 @@
|
||||
MLXPLAT_CPLD_AGGR_MASK_LC_SDWN)
|
||||
#define MLXPLAT_CPLD_LOW_AGGR_MASK_LOW 0xc1
|
||||
#define MLXPLAT_CPLD_LOW_AGGR_MASK_ASIC2 BIT(2)
|
||||
#define MLXPLAT_CPLD_LOW_AGGR_MASK_PWR_BUT BIT(4)
|
||||
#define MLXPLAT_CPLD_LOW_AGGR_MASK_PWR_BUT GENMASK(5, 4)
|
||||
#define MLXPLAT_CPLD_LOW_AGGR_MASK_I2C BIT(6)
|
||||
#define MLXPLAT_CPLD_PSU_MASK GENMASK(1, 0)
|
||||
#define MLXPLAT_CPLD_PWR_MASK GENMASK(1, 0)
|
||||
@ -237,7 +237,7 @@
|
||||
#define MLXPLAT_CPLD_GWP_MASK GENMASK(0, 0)
|
||||
#define MLXPLAT_CPLD_EROT_MASK GENMASK(1, 0)
|
||||
#define MLXPLAT_CPLD_PWR_BUTTON_MASK BIT(0)
|
||||
#define MLXPLAT_CPLD_LATCH_RST_MASK BIT(5)
|
||||
#define MLXPLAT_CPLD_LATCH_RST_MASK BIT(6)
|
||||
#define MLXPLAT_CPLD_THERMAL1_PDB_MASK BIT(3)
|
||||
#define MLXPLAT_CPLD_THERMAL2_PDB_MASK BIT(4)
|
||||
#define MLXPLAT_CPLD_INTRUSION_MASK BIT(6)
|
||||
@ -2356,7 +2356,7 @@ mlxplat_mlxcpld_l1_switch_pwr_events_handler(void *handle, enum mlxreg_hotplug_k
|
||||
u8 action)
|
||||
{
|
||||
dev_info(&mlxplat_dev->dev, "System shutdown due to short press of power button");
|
||||
kernel_halt();
|
||||
kernel_power_off();
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -2475,7 +2475,7 @@ static struct mlxreg_core_item mlxplat_mlxcpld_l1_switch_events_items[] = {
|
||||
.reg = MLXPLAT_CPLD_LPC_REG_PWRB_OFFSET,
|
||||
.mask = MLXPLAT_CPLD_PWR_BUTTON_MASK,
|
||||
.count = ARRAY_SIZE(mlxplat_mlxcpld_l1_switch_pwr_events_items_data),
|
||||
.inversed = 0,
|
||||
.inversed = 1,
|
||||
.health = false,
|
||||
},
|
||||
{
|
||||
@ -2484,7 +2484,7 @@ static struct mlxreg_core_item mlxplat_mlxcpld_l1_switch_events_items[] = {
|
||||
.reg = MLXPLAT_CPLD_LPC_REG_BRD_OFFSET,
|
||||
.mask = MLXPLAT_CPLD_L1_CHA_HEALTH_MASK,
|
||||
.count = ARRAY_SIZE(mlxplat_mlxcpld_l1_switch_health_events_items_data),
|
||||
.inversed = 0,
|
||||
.inversed = 1,
|
||||
.health = false,
|
||||
.ind = 8,
|
||||
},
|
||||
@ -3677,7 +3677,7 @@ static struct mlxreg_core_data mlxplat_mlxcpld_default_ng_regs_io_data[] = {
|
||||
{
|
||||
.label = "latch_reset",
|
||||
.reg = MLXPLAT_CPLD_LPC_REG_GP1_OFFSET,
|
||||
.mask = GENMASK(7, 0) & ~BIT(5),
|
||||
.mask = GENMASK(7, 0) & ~BIT(6),
|
||||
.mode = 0200,
|
||||
},
|
||||
{
|
||||
@ -6238,8 +6238,6 @@ static void mlxplat_i2c_mux_topolgy_exit(struct mlxplat_priv *priv)
|
||||
if (priv->pdev_mux[i])
|
||||
platform_device_unregister(priv->pdev_mux[i]);
|
||||
}
|
||||
|
||||
mlxplat_post_exit();
|
||||
}
|
||||
|
||||
static int mlxplat_i2c_main_complition_notify(void *handle, int id)
|
||||
@ -6369,6 +6367,7 @@ static void __exit mlxplat_exit(void)
|
||||
pm_power_off = NULL;
|
||||
mlxplat_pre_exit(priv);
|
||||
mlxplat_i2c_main_exit(priv);
|
||||
mlxplat_post_exit();
|
||||
}
|
||||
module_exit(mlxplat_exit);
|
||||
|
||||
|
@ -27,15 +27,15 @@
|
||||
#include <linux/seq_file.h>
|
||||
#include <linux/string.h>
|
||||
|
||||
static const char *const SM_ECO_NAME = "eco";
|
||||
static const char *const SM_COMFORT_NAME = "comfort";
|
||||
static const char *const SM_SPORT_NAME = "sport";
|
||||
static const char *const SM_TURBO_NAME = "turbo";
|
||||
#define SM_ECO_NAME "eco"
|
||||
#define SM_COMFORT_NAME "comfort"
|
||||
#define SM_SPORT_NAME "sport"
|
||||
#define SM_TURBO_NAME "turbo"
|
||||
|
||||
static const char *const FM_AUTO_NAME = "auto";
|
||||
static const char *const FM_SILENT_NAME = "silent";
|
||||
static const char *const FM_BASIC_NAME = "basic";
|
||||
static const char *const FM_ADVANCED_NAME = "advanced";
|
||||
#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",
|
||||
|
@ -208,7 +208,7 @@ static ssize_t set_device_state(const char *buf, size_t count, u8 mask)
|
||||
return -EINVAL;
|
||||
|
||||
if (quirks->ec_read_only)
|
||||
return -EOPNOTSUPP;
|
||||
return 0;
|
||||
|
||||
/* read current device state */
|
||||
result = ec_read(MSI_STANDARD_EC_COMMAND_ADDRESS, &rdata);
|
||||
@ -838,15 +838,15 @@ static bool msi_laptop_i8042_filter(unsigned char data, unsigned char str,
|
||||
static void msi_init_rfkill(struct work_struct *ignored)
|
||||
{
|
||||
if (rfk_wlan) {
|
||||
rfkill_set_sw_state(rfk_wlan, !wlan_s);
|
||||
msi_rfkill_set_state(rfk_wlan, !wlan_s);
|
||||
rfkill_wlan_set(NULL, !wlan_s);
|
||||
}
|
||||
if (rfk_bluetooth) {
|
||||
rfkill_set_sw_state(rfk_bluetooth, !bluetooth_s);
|
||||
msi_rfkill_set_state(rfk_bluetooth, !bluetooth_s);
|
||||
rfkill_bluetooth_set(NULL, !bluetooth_s);
|
||||
}
|
||||
if (rfk_threeg) {
|
||||
rfkill_set_sw_state(rfk_threeg, !threeg_s);
|
||||
msi_rfkill_set_state(rfk_threeg, !threeg_s);
|
||||
rfkill_threeg_set(NULL, !threeg_s);
|
||||
}
|
||||
}
|
||||
|
@ -21,6 +21,7 @@
|
||||
#define IRQ_RESOURCE_NONE 0
|
||||
#define IRQ_RESOURCE_GPIO 1
|
||||
#define IRQ_RESOURCE_APIC 2
|
||||
#define IRQ_RESOURCE_AUTO 3
|
||||
|
||||
enum smi_bus_type {
|
||||
SMI_I2C,
|
||||
@ -52,6 +53,18 @@ static int smi_get_irq(struct platform_device *pdev, struct acpi_device *adev,
|
||||
int ret;
|
||||
|
||||
switch (inst->flags & IRQ_RESOURCE_TYPE) {
|
||||
case IRQ_RESOURCE_AUTO:
|
||||
ret = acpi_dev_gpio_irq_get(adev, inst->irq_idx);
|
||||
if (ret > 0) {
|
||||
dev_dbg(&pdev->dev, "Using gpio irq\n");
|
||||
break;
|
||||
}
|
||||
ret = platform_get_irq(pdev, inst->irq_idx);
|
||||
if (ret > 0) {
|
||||
dev_dbg(&pdev->dev, "Using platform irq\n");
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case IRQ_RESOURCE_GPIO:
|
||||
ret = acpi_dev_gpio_irq_get(adev, inst->irq_idx);
|
||||
break;
|
||||
@ -307,10 +320,23 @@ static const struct smi_node int3515_data = {
|
||||
|
||||
static const struct smi_node cs35l41_hda = {
|
||||
.instances = {
|
||||
{ "cs35l41-hda", IRQ_RESOURCE_GPIO, 0 },
|
||||
{ "cs35l41-hda", IRQ_RESOURCE_GPIO, 0 },
|
||||
{ "cs35l41-hda", IRQ_RESOURCE_GPIO, 0 },
|
||||
{ "cs35l41-hda", IRQ_RESOURCE_GPIO, 0 },
|
||||
{ "cs35l41-hda", IRQ_RESOURCE_AUTO, 0 },
|
||||
{ "cs35l41-hda", IRQ_RESOURCE_AUTO, 0 },
|
||||
{ "cs35l41-hda", IRQ_RESOURCE_AUTO, 0 },
|
||||
{ "cs35l41-hda", IRQ_RESOURCE_AUTO, 0 },
|
||||
{}
|
||||
},
|
||||
.bus_type = SMI_AUTO_DETECT,
|
||||
};
|
||||
|
||||
static const struct smi_node cs35l56_hda = {
|
||||
.instances = {
|
||||
{ "cs35l56-hda", IRQ_RESOURCE_AUTO, 0 },
|
||||
{ "cs35l56-hda", IRQ_RESOURCE_AUTO, 0 },
|
||||
{ "cs35l56-hda", IRQ_RESOURCE_AUTO, 0 },
|
||||
{ "cs35l56-hda", IRQ_RESOURCE_AUTO, 0 },
|
||||
/* a 5th entry is an alias address, not a real device */
|
||||
{ "cs35l56-hda_dummy_dev" },
|
||||
{}
|
||||
},
|
||||
.bus_type = SMI_AUTO_DETECT,
|
||||
@ -324,6 +350,7 @@ static const struct acpi_device_id smi_acpi_ids[] = {
|
||||
{ "BSG1160", (unsigned long)&bsg1160_data },
|
||||
{ "BSG2150", (unsigned long)&bsg2150_data },
|
||||
{ "CSC3551", (unsigned long)&cs35l41_hda },
|
||||
{ "CSC3556", (unsigned long)&cs35l56_hda },
|
||||
{ "INT3515", (unsigned long)&int3515_data },
|
||||
/* Non-conforming _HID for Cirrus Logic already released */
|
||||
{ "CLSA0100", (unsigned long)&cs35l41_hda },
|
||||
|
@ -719,12 +719,12 @@ static ssize_t cert_to_password_store(struct kobject *kobj,
|
||||
/* Format: 'Password,Signature' */
|
||||
auth_str = kasprintf(GFP_KERNEL, "%s,%s", passwd, setting->signature);
|
||||
if (!auth_str) {
|
||||
kfree(passwd);
|
||||
kfree_sensitive(passwd);
|
||||
return -ENOMEM;
|
||||
}
|
||||
ret = tlmi_simple_call(LENOVO_CERT_TO_PASSWORD_GUID, auth_str);
|
||||
kfree(auth_str);
|
||||
kfree(passwd);
|
||||
kfree_sensitive(passwd);
|
||||
|
||||
return ret ?: count;
|
||||
}
|
||||
|
@ -316,17 +316,12 @@ struct ibm_init_struct {
|
||||
/* DMI Quirks */
|
||||
struct quirk_entry {
|
||||
bool btusb_bug;
|
||||
u32 s2idle_bug_mmio;
|
||||
};
|
||||
|
||||
static struct quirk_entry quirk_btusb_bug = {
|
||||
.btusb_bug = true,
|
||||
};
|
||||
|
||||
static struct quirk_entry quirk_s2idle_bug = {
|
||||
.s2idle_bug_mmio = 0xfed80380,
|
||||
};
|
||||
|
||||
static struct {
|
||||
u32 bluetooth:1;
|
||||
u32 hotkey:1;
|
||||
@ -4423,136 +4418,9 @@ static const struct dmi_system_id fwbug_list[] __initconst = {
|
||||
DMI_MATCH(DMI_BOARD_NAME, "20MV"),
|
||||
},
|
||||
},
|
||||
{
|
||||
.ident = "L14 Gen2 AMD",
|
||||
.driver_data = &quirk_s2idle_bug,
|
||||
.matches = {
|
||||
DMI_MATCH(DMI_BOARD_VENDOR, "LENOVO"),
|
||||
DMI_MATCH(DMI_PRODUCT_NAME, "20X5"),
|
||||
}
|
||||
},
|
||||
{
|
||||
.ident = "T14s Gen2 AMD",
|
||||
.driver_data = &quirk_s2idle_bug,
|
||||
.matches = {
|
||||
DMI_MATCH(DMI_BOARD_VENDOR, "LENOVO"),
|
||||
DMI_MATCH(DMI_PRODUCT_NAME, "20XF"),
|
||||
}
|
||||
},
|
||||
{
|
||||
.ident = "X13 Gen2 AMD",
|
||||
.driver_data = &quirk_s2idle_bug,
|
||||
.matches = {
|
||||
DMI_MATCH(DMI_BOARD_VENDOR, "LENOVO"),
|
||||
DMI_MATCH(DMI_PRODUCT_NAME, "20XH"),
|
||||
}
|
||||
},
|
||||
{
|
||||
.ident = "T14 Gen2 AMD",
|
||||
.driver_data = &quirk_s2idle_bug,
|
||||
.matches = {
|
||||
DMI_MATCH(DMI_BOARD_VENDOR, "LENOVO"),
|
||||
DMI_MATCH(DMI_PRODUCT_NAME, "20XK"),
|
||||
}
|
||||
},
|
||||
{
|
||||
.ident = "T14 Gen1 AMD",
|
||||
.driver_data = &quirk_s2idle_bug,
|
||||
.matches = {
|
||||
DMI_MATCH(DMI_BOARD_VENDOR, "LENOVO"),
|
||||
DMI_MATCH(DMI_PRODUCT_NAME, "20UD"),
|
||||
}
|
||||
},
|
||||
{
|
||||
.ident = "T14 Gen1 AMD",
|
||||
.driver_data = &quirk_s2idle_bug,
|
||||
.matches = {
|
||||
DMI_MATCH(DMI_BOARD_VENDOR, "LENOVO"),
|
||||
DMI_MATCH(DMI_PRODUCT_NAME, "20UE"),
|
||||
}
|
||||
},
|
||||
{
|
||||
.ident = "T14s Gen1 AMD",
|
||||
.driver_data = &quirk_s2idle_bug,
|
||||
.matches = {
|
||||
DMI_MATCH(DMI_BOARD_VENDOR, "LENOVO"),
|
||||
DMI_MATCH(DMI_PRODUCT_NAME, "20UH"),
|
||||
}
|
||||
},
|
||||
{
|
||||
.ident = "T14s Gen1 AMD",
|
||||
.driver_data = &quirk_s2idle_bug,
|
||||
.matches = {
|
||||
DMI_MATCH(DMI_BOARD_VENDOR, "LENOVO"),
|
||||
DMI_MATCH(DMI_PRODUCT_NAME, "20UJ"),
|
||||
}
|
||||
},
|
||||
{
|
||||
.ident = "P14s Gen1 AMD",
|
||||
.driver_data = &quirk_s2idle_bug,
|
||||
.matches = {
|
||||
DMI_MATCH(DMI_BOARD_VENDOR, "LENOVO"),
|
||||
DMI_MATCH(DMI_PRODUCT_NAME, "20Y1"),
|
||||
}
|
||||
},
|
||||
{
|
||||
.ident = "P14s Gen2 AMD",
|
||||
.driver_data = &quirk_s2idle_bug,
|
||||
.matches = {
|
||||
DMI_MATCH(DMI_BOARD_VENDOR, "LENOVO"),
|
||||
DMI_MATCH(DMI_PRODUCT_NAME, "21A0"),
|
||||
}
|
||||
},
|
||||
{
|
||||
.ident = "P14s Gen2 AMD",
|
||||
.driver_data = &quirk_s2idle_bug,
|
||||
.matches = {
|
||||
DMI_MATCH(DMI_BOARD_VENDOR, "LENOVO"),
|
||||
DMI_MATCH(DMI_PRODUCT_NAME, "21A1"),
|
||||
}
|
||||
},
|
||||
{}
|
||||
};
|
||||
|
||||
#ifdef CONFIG_SUSPEND
|
||||
/*
|
||||
* Lenovo laptops from a variety of generations run a SMI handler during the D3->D0
|
||||
* transition that occurs specifically when exiting suspend to idle which can cause
|
||||
* large delays during resume when the IOMMU translation layer is enabled (the default
|
||||
* behavior) for NVME devices:
|
||||
*
|
||||
* To avoid this firmware problem, skip the SMI handler on these machines before the
|
||||
* D0 transition occurs.
|
||||
*/
|
||||
static void thinkpad_acpi_amd_s2idle_restore(void)
|
||||
{
|
||||
struct resource *res;
|
||||
void __iomem *addr;
|
||||
u8 val;
|
||||
|
||||
res = request_mem_region_muxed(tp_features.quirks->s2idle_bug_mmio, 1,
|
||||
"thinkpad_acpi_pm80");
|
||||
if (!res)
|
||||
return;
|
||||
|
||||
addr = ioremap(tp_features.quirks->s2idle_bug_mmio, 1);
|
||||
if (!addr)
|
||||
goto cleanup_resource;
|
||||
|
||||
val = ioread8(addr);
|
||||
iowrite8(val & ~BIT(0), addr);
|
||||
|
||||
iounmap(addr);
|
||||
cleanup_resource:
|
||||
release_resource(res);
|
||||
kfree(res);
|
||||
}
|
||||
|
||||
static struct acpi_s2idle_dev_ops thinkpad_acpi_s2idle_dev_ops = {
|
||||
.restore = thinkpad_acpi_amd_s2idle_restore,
|
||||
};
|
||||
#endif
|
||||
|
||||
static const struct pci_device_id fwbug_cards_ids[] __initconst = {
|
||||
{ PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x24F3) },
|
||||
{ PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x24FD) },
|
||||
@ -11672,10 +11540,6 @@ static void thinkpad_acpi_module_exit(void)
|
||||
|
||||
tpacpi_lifecycle = TPACPI_LIFE_EXITING;
|
||||
|
||||
#ifdef CONFIG_SUSPEND
|
||||
if (tp_features.quirks && tp_features.quirks->s2idle_bug_mmio)
|
||||
acpi_unregister_lps0_dev(&thinkpad_acpi_s2idle_dev_ops);
|
||||
#endif
|
||||
if (tpacpi_hwmon)
|
||||
hwmon_device_unregister(tpacpi_hwmon);
|
||||
if (tp_features.sensors_pdrv_registered)
|
||||
@ -11865,13 +11729,6 @@ static int __init thinkpad_acpi_module_init(void)
|
||||
tp_features.input_device_registered = 1;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_SUSPEND
|
||||
if (tp_features.quirks && tp_features.quirks->s2idle_bug_mmio) {
|
||||
if (!acpi_register_lps0_dev(&thinkpad_acpi_s2idle_dev_ops))
|
||||
pr_info("Using s2idle quirk to avoid %s platform firmware bug\n",
|
||||
(dmi_id && dmi_id->ident) ? dmi_id->ident : "");
|
||||
}
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -26,6 +26,22 @@ struct ts_dmi_data {
|
||||
|
||||
/* NOTE: Please keep all entries sorted alphabetically */
|
||||
|
||||
static const struct property_entry archos_101_cesium_educ_props[] = {
|
||||
PROPERTY_ENTRY_U32("touchscreen-size-x", 1850),
|
||||
PROPERTY_ENTRY_U32("touchscreen-size-y", 1280),
|
||||
PROPERTY_ENTRY_BOOL("touchscreen-inverted-y"),
|
||||
PROPERTY_ENTRY_BOOL("touchscreen-swapped-x-y"),
|
||||
PROPERTY_ENTRY_U32("silead,max-fingers", 10),
|
||||
PROPERTY_ENTRY_BOOL("silead,home-button"),
|
||||
PROPERTY_ENTRY_STRING("firmware-name", "gsl1680-archos-101-cesium-educ.fw"),
|
||||
{ }
|
||||
};
|
||||
|
||||
static const struct ts_dmi_data archos_101_cesium_educ_data = {
|
||||
.acpi_name = "MSSL1680:00",
|
||||
.properties = archos_101_cesium_educ_props,
|
||||
};
|
||||
|
||||
static const struct property_entry chuwi_hi8_props[] = {
|
||||
PROPERTY_ENTRY_U32("touchscreen-size-x", 1665),
|
||||
PROPERTY_ENTRY_U32("touchscreen-size-y", 1140),
|
||||
@ -1047,6 +1063,13 @@ static const struct ts_dmi_data vinga_twizzle_j116_data = {
|
||||
|
||||
/* NOTE: Please keep this table sorted alphabetically */
|
||||
const struct dmi_system_id touchscreen_dmi_table[] = {
|
||||
{
|
||||
/* Archos 101 Cesium Educ */
|
||||
.driver_data = (void *)&archos_101_cesium_educ_data,
|
||||
.matches = {
|
||||
DMI_MATCH(DMI_PRODUCT_NAME, "ARCHOS 101 Cesium Educ"),
|
||||
},
|
||||
},
|
||||
{
|
||||
/* Chuwi Hi8 */
|
||||
.driver_data = (void *)&chuwi_hi8_data,
|
||||
|
@ -136,6 +136,16 @@ static acpi_status find_guid(const char *guid_string, struct wmi_block **out)
|
||||
return AE_NOT_FOUND;
|
||||
}
|
||||
|
||||
static bool guid_parse_and_compare(const char *string, const guid_t *guid)
|
||||
{
|
||||
guid_t guid_input;
|
||||
|
||||
if (guid_parse(string, &guid_input))
|
||||
return false;
|
||||
|
||||
return guid_equal(&guid_input, guid);
|
||||
}
|
||||
|
||||
static const void *find_guid_context(struct wmi_block *wblock,
|
||||
struct wmi_driver *wdriver)
|
||||
{
|
||||
@ -146,11 +156,7 @@ static const void *find_guid_context(struct wmi_block *wblock,
|
||||
return NULL;
|
||||
|
||||
while (*id->guid_string) {
|
||||
guid_t guid_input;
|
||||
|
||||
if (guid_parse(id->guid_string, &guid_input))
|
||||
continue;
|
||||
if (guid_equal(&wblock->gblock.guid, &guid_input))
|
||||
if (guid_parse_and_compare(id->guid_string, &wblock->gblock.guid))
|
||||
return id->context;
|
||||
id++;
|
||||
}
|
||||
@ -895,11 +901,7 @@ static int wmi_dev_match(struct device *dev, struct device_driver *driver)
|
||||
return 0;
|
||||
|
||||
while (*id->guid_string) {
|
||||
guid_t driver_guid;
|
||||
|
||||
if (WARN_ON(guid_parse(id->guid_string, &driver_guid)))
|
||||
continue;
|
||||
if (guid_equal(&driver_guid, &wblock->gblock.guid))
|
||||
if (guid_parse_and_compare(id->guid_string, &wblock->gblock.guid))
|
||||
return 1;
|
||||
|
||||
id++;
|
||||
@ -1239,11 +1241,7 @@ static bool guid_already_parsed_for_legacy(struct acpi_device *device, const gui
|
||||
list_for_each_entry(wblock, &wmi_block_list, list) {
|
||||
/* skip warning and register if we know the driver will use struct wmi_driver */
|
||||
for (int i = 0; allow_duplicates[i] != NULL; i++) {
|
||||
guid_t tmp;
|
||||
|
||||
if (guid_parse(allow_duplicates[i], &tmp))
|
||||
continue;
|
||||
if (guid_equal(&tmp, guid))
|
||||
if (guid_parse_and_compare(allow_duplicates[i], guid))
|
||||
return false;
|
||||
}
|
||||
if (guid_equal(&wblock->gblock.guid, guid)) {
|
||||
|
Loading…
Reference in New Issue
Block a user