Commit d9b2ba67 authored by Linus Torvalds's avatar Linus Torvalds

Merge tag 'platform-drivers-x86-v5.19-3' of...

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

Pull x86 platform driver fixes from Hans de Goede:

 - thinkpad_acpi/ideapad-laptop: mem-leak and platform-profile fixes

 - panasonic-laptop: missing hotkey presses regression fix

 - some hardware-id additions

 - some other small fixes

* tag 'platform-drivers-x86-v5.19-3' of git://git.kernel.org/pub/scm/linux/kernel/git/pdx86/platform-drivers-x86:
  platform/x86: hp-wmi: Ignore Sanitization Mode event
  platform/x86: thinkpad_acpi: do not use PSC mode on Intel platforms
  platform/x86: thinkpad-acpi: profile capabilities as integer
  platform/x86: panasonic-laptop: filter out duplicate volume up/down/mute keypresses
  platform/x86: panasonic-laptop: don't report duplicate brightness key-presses
  platform/x86: panasonic-laptop: revert "Resolve hotkey double trigger bug"
  platform/x86: panasonic-laptop: sort includes alphabetically
  platform/x86: panasonic-laptop: de-obfuscate button codes
  ACPI: video: Change how we determine if brightness key-presses are handled
  platform/x86: ideapad-laptop: Add Ideapad 5 15ITL05 to ideapad_dytc_v4_allow_table[]
  platform/x86: ideapad-laptop: Add allow_v4_dytc module parameter
  platform/x86: thinkpad_acpi: Fix a memory leak of EFCH MMIO resource
  platform/mellanox: nvsw-sn2201: fix error code in nvsw_sn2201_create_static_devices()
  platform/x86: intel/pmc: Add Alder Lake N support to PMC core driver
parents 732f3069 9ab762a8
......@@ -73,6 +73,7 @@ module_param(device_id_scheme, bool, 0444);
static int only_lcd = -1;
module_param(only_lcd, int, 0444);
static bool has_backlight;
static int register_count;
static DEFINE_MUTEX(register_count_mutex);
static DEFINE_MUTEX(video_list_lock);
......@@ -1222,6 +1223,9 @@ acpi_video_bus_get_one_device(struct acpi_device *device,
acpi_video_device_bind(video, data);
acpi_video_device_find_cap(data);
if (data->cap._BCM && data->cap._BCL)
has_backlight = true;
mutex_lock(&video->device_list_lock);
list_add_tail(&data->entry, &video->video_device_list);
mutex_unlock(&video->device_list_lock);
......@@ -2249,6 +2253,7 @@ void acpi_video_unregister(void)
if (register_count) {
acpi_bus_unregister_driver(&acpi_video_bus);
register_count = 0;
has_backlight = false;
}
mutex_unlock(&register_count_mutex);
}
......@@ -2270,13 +2275,7 @@ void acpi_video_unregister_backlight(void)
bool acpi_video_handles_brightness_key_presses(void)
{
bool have_video_busses;
mutex_lock(&video_list_lock);
have_video_busses = !list_empty(&video_bus_head);
mutex_unlock(&video_list_lock);
return have_video_busses &&
return has_backlight &&
(report_key_events & REPORT_BRIGHTNESS_KEY_EVENTS);
}
EXPORT_SYMBOL(acpi_video_handles_brightness_key_presses);
......
......@@ -890,6 +890,7 @@ nvsw_sn2201_create_static_devices(struct nvsw_sn2201 *nvsw_sn2201,
int size)
{
struct mlxreg_hotplug_device *dev = devs;
int ret;
int i;
/* Create I2C static devices. */
......@@ -901,6 +902,7 @@ nvsw_sn2201_create_static_devices(struct nvsw_sn2201 *nvsw_sn2201,
dev->nr, dev->brdinfo->addr);
dev->adapter = NULL;
ret = PTR_ERR(dev->client);
goto fail_create_static_devices;
}
}
......@@ -914,7 +916,7 @@ nvsw_sn2201_create_static_devices(struct nvsw_sn2201 *nvsw_sn2201,
dev->client = NULL;
dev->adapter = NULL;
}
return IS_ERR(dev->client);
return ret;
}
static void nvsw_sn2201_destroy_static_devices(struct nvsw_sn2201 *nvsw_sn2201,
......
......@@ -945,6 +945,8 @@ config PANASONIC_LAPTOP
tristate "Panasonic Laptop Extras"
depends on INPUT && ACPI
depends on BACKLIGHT_CLASS_DEVICE
depends on ACPI_VIDEO=n || ACPI_VIDEO
depends on SERIO_I8042 || SERIO_I8042 = n
select INPUT_SPARSEKMAP
help
This driver adds support for access to backlight control and hotkeys
......
......@@ -89,6 +89,7 @@ enum hp_wmi_event_ids {
HPWMI_BACKLIT_KB_BRIGHTNESS = 0x0D,
HPWMI_PEAKSHIFT_PERIOD = 0x0F,
HPWMI_BATTERY_CHARGE_PERIOD = 0x10,
HPWMI_SANITIZATION_MODE = 0x17,
};
/*
......@@ -853,6 +854,8 @@ static void hp_wmi_notify(u32 value, void *context)
break;
case HPWMI_BATTERY_CHARGE_PERIOD:
break;
case HPWMI_SANITIZATION_MODE:
break;
default:
pr_info("Unknown event_id - %d - 0x%x\n", event_id, event_data);
break;
......
......@@ -152,6 +152,10 @@ static bool no_bt_rfkill;
module_param(no_bt_rfkill, bool, 0444);
MODULE_PARM_DESC(no_bt_rfkill, "No rfkill for bluetooth.");
static bool allow_v4_dytc;
module_param(allow_v4_dytc, bool, 0444);
MODULE_PARM_DESC(allow_v4_dytc, "Enable DYTC version 4 platform-profile support.");
/*
* ACPI Helpers
*/
......@@ -871,12 +875,18 @@ static void dytc_profile_refresh(struct ideapad_private *priv)
static const struct dmi_system_id ideapad_dytc_v4_allow_table[] = {
{
/* Ideapad 5 Pro 16ACH6 */
.ident = "LENOVO 82L5",
.matches = {
DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"),
DMI_MATCH(DMI_PRODUCT_NAME, "82L5")
}
},
{
/* Ideapad 5 15ITL05 */
.matches = {
DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"),
DMI_MATCH(DMI_PRODUCT_VERSION, "IdeaPad 5 15ITL05")
}
},
{}
};
......@@ -901,13 +911,16 @@ static int ideapad_dytc_profile_init(struct ideapad_private *priv)
dytc_version = (output >> DYTC_QUERY_REV_BIT) & 0xF;
if (dytc_version < 5) {
if (dytc_version < 4 || !dmi_check_system(ideapad_dytc_v4_allow_table)) {
dev_info(&priv->platform_device->dev,
"DYTC_VERSION is less than 4 or is not allowed: %d\n",
dytc_version);
return -ENODEV;
}
if (dytc_version < 4) {
dev_info(&priv->platform_device->dev, "DYTC_VERSION < 4 is not supported\n");
return -ENODEV;
}
if (dytc_version < 5 &&
!(allow_v4_dytc || dmi_check_system(ideapad_dytc_v4_allow_table))) {
dev_info(&priv->platform_device->dev,
"DYTC_VERSION 4 support may not work. Pass ideapad_laptop.allow_v4_dytc=Y on the kernel commandline to enable\n");
return -ENODEV;
}
priv->dytc = kzalloc(sizeof(*priv->dytc), GFP_KERNEL);
......
......@@ -1911,6 +1911,7 @@ static const struct x86_cpu_id intel_pmc_core_ids[] = {
X86_MATCH_INTEL_FAM6_MODEL(ATOM_TREMONT_L, &icl_reg_map),
X86_MATCH_INTEL_FAM6_MODEL(ROCKETLAKE, &tgl_reg_map),
X86_MATCH_INTEL_FAM6_MODEL(ALDERLAKE_L, &tgl_reg_map),
X86_MATCH_INTEL_FAM6_MODEL(ALDERLAKE_N, &tgl_reg_map),
X86_MATCH_INTEL_FAM6_MODEL(ALDERLAKE, &adl_reg_map),
X86_MATCH_INTEL_FAM6_MODEL(RAPTORLAKE_P, &tgl_reg_map),
{}
......
......@@ -119,20 +119,22 @@
* - v0.1 start from toshiba_acpi driver written by John Belmonte
*/
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/init.h>
#include <linux/types.h>
#include <linux/acpi.h>
#include <linux/backlight.h>
#include <linux/ctype.h>
#include <linux/seq_file.h>
#include <linux/uaccess.h>
#include <linux/slab.h>
#include <linux/acpi.h>
#include <linux/i8042.h>
#include <linux/init.h>
#include <linux/input.h>
#include <linux/input/sparse-keymap.h>
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/platform_device.h>
#include <linux/seq_file.h>
#include <linux/serio.h>
#include <linux/slab.h>
#include <linux/types.h>
#include <linux/uaccess.h>
#include <acpi/video.h>
MODULE_AUTHOR("Hiroshi Miura <miura@da-cha.org>");
MODULE_AUTHOR("David Bronaugh <dbronaugh@linuxboxen.org>");
......@@ -241,6 +243,42 @@ struct pcc_acpi {
struct platform_device *platform;
};
/*
* On some Panasonic models the volume up / down / mute keys send duplicate
* keypress events over the PS/2 kbd interface, filter these out.
*/
static bool panasonic_i8042_filter(unsigned char data, unsigned char str,
struct serio *port)
{
static bool extended;
if (str & I8042_STR_AUXDATA)
return false;
if (data == 0xe0) {
extended = true;
return true;
} else if (extended) {
extended = false;
switch (data & 0x7f) {
case 0x20: /* e0 20 / e0 a0, Volume Mute press / release */
case 0x2e: /* e0 2e / e0 ae, Volume Down press / release */
case 0x30: /* e0 30 / e0 b0, Volume Up press / release */
return true;
default:
/*
* Report the previously filtered e0 before continuing
* with the next non-filtered byte.
*/
serio_interrupt(port, 0xe0, 0);
return false;
}
}
return false;
}
/* method access functions */
static int acpi_pcc_write_sset(struct pcc_acpi *pcc, int func, int val)
{
......@@ -762,6 +800,8 @@ static void acpi_pcc_generate_keyinput(struct pcc_acpi *pcc)
struct input_dev *hotk_input_dev = pcc->input_dev;
int rc;
unsigned long long result;
unsigned int key;
unsigned int updown;
rc = acpi_evaluate_integer(pcc->handle, METHOD_HKEY_QUERY,
NULL, &result);
......@@ -770,20 +810,27 @@ static void acpi_pcc_generate_keyinput(struct pcc_acpi *pcc)
return;
}
key = result & 0xf;
updown = result & 0x80; /* 0x80 == key down; 0x00 = key up */
/* hack: some firmware sends no key down for sleep / hibernate */
if ((result & 0xf) == 0x7 || (result & 0xf) == 0xa) {
if (result & 0x80)
if (key == 7 || key == 10) {
if (updown)
sleep_keydown_seen = 1;
if (!sleep_keydown_seen)
sparse_keymap_report_event(hotk_input_dev,
result & 0xf, 0x80, false);
key, 0x80, false);
}
if ((result & 0xf) == 0x7 || (result & 0xf) == 0x9 || (result & 0xf) == 0xa) {
if (!sparse_keymap_report_event(hotk_input_dev,
result & 0xf, result & 0x80, false))
pr_err("Unknown hotkey event: 0x%04llx\n", result);
}
/*
* Don't report brightness key-presses if they are also reported
* by the ACPI video bus.
*/
if ((key == 1 || key == 2) && acpi_video_handles_brightness_key_presses())
return;
if (!sparse_keymap_report_event(hotk_input_dev, key, updown, false))
pr_err("Unknown hotkey event: 0x%04llx\n", result);
}
static void acpi_pcc_hotkey_notify(struct acpi_device *device, u32 event)
......@@ -997,6 +1044,7 @@ static int acpi_pcc_hotkey_add(struct acpi_device *device)
pcc->platform = NULL;
}
i8042_install_filter(panasonic_i8042_filter);
return 0;
out_platform:
......@@ -1020,6 +1068,8 @@ static int acpi_pcc_hotkey_remove(struct acpi_device *device)
if (!device || !pcc)
return -EINVAL;
i8042_remove_filter(panasonic_i8042_filter);
if (pcc->platform) {
device_remove_file(&pcc->platform->dev, &dev_attr_cdpower);
platform_device_unregister(pcc->platform);
......
......@@ -4529,6 +4529,7 @@ static void thinkpad_acpi_amd_s2idle_restore(void)
iounmap(addr);
cleanup_resource:
release_resource(res);
kfree(res);
}
static struct acpi_s2idle_dev_ops thinkpad_acpi_s2idle_dev_ops = {
......@@ -10299,21 +10300,15 @@ static struct ibm_struct proxsensor_driver_data = {
#define DYTC_DISABLE_CQL DYTC_SET_COMMAND(DYTC_FUNCTION_CQL, DYTC_MODE_MMC_BALANCE, 0)
#define DYTC_ENABLE_CQL DYTC_SET_COMMAND(DYTC_FUNCTION_CQL, DYTC_MODE_MMC_BALANCE, 1)
enum dytc_profile_funcmode {
DYTC_FUNCMODE_NONE = 0,
DYTC_FUNCMODE_MMC,
DYTC_FUNCMODE_PSC,
};
static enum dytc_profile_funcmode dytc_profile_available;
static enum platform_profile_option dytc_current_profile;
static atomic_t dytc_ignore_event = ATOMIC_INIT(0);
static DEFINE_MUTEX(dytc_mutex);
static int dytc_capabilities;
static bool dytc_mmc_get_available;
static int convert_dytc_to_profile(int dytcmode, enum platform_profile_option *profile)
{
if (dytc_profile_available == DYTC_FUNCMODE_MMC) {
if (dytc_capabilities & BIT(DYTC_FC_MMC)) {
switch (dytcmode) {
case DYTC_MODE_MMC_LOWPOWER:
*profile = PLATFORM_PROFILE_LOW_POWER;
......@@ -10330,7 +10325,7 @@ static int convert_dytc_to_profile(int dytcmode, enum platform_profile_option *p
}
return 0;
}
if (dytc_profile_available == DYTC_FUNCMODE_PSC) {
if (dytc_capabilities & BIT(DYTC_FC_PSC)) {
switch (dytcmode) {
case DYTC_MODE_PSC_LOWPOWER:
*profile = PLATFORM_PROFILE_LOW_POWER;
......@@ -10352,21 +10347,21 @@ static int convert_profile_to_dytc(enum platform_profile_option profile, int *pe
{
switch (profile) {
case PLATFORM_PROFILE_LOW_POWER:
if (dytc_profile_available == DYTC_FUNCMODE_MMC)
if (dytc_capabilities & BIT(DYTC_FC_MMC))
*perfmode = DYTC_MODE_MMC_LOWPOWER;
else if (dytc_profile_available == DYTC_FUNCMODE_PSC)
else if (dytc_capabilities & BIT(DYTC_FC_PSC))
*perfmode = DYTC_MODE_PSC_LOWPOWER;
break;
case PLATFORM_PROFILE_BALANCED:
if (dytc_profile_available == DYTC_FUNCMODE_MMC)
if (dytc_capabilities & BIT(DYTC_FC_MMC))
*perfmode = DYTC_MODE_MMC_BALANCE;
else if (dytc_profile_available == DYTC_FUNCMODE_PSC)
else if (dytc_capabilities & BIT(DYTC_FC_PSC))
*perfmode = DYTC_MODE_PSC_BALANCE;
break;
case PLATFORM_PROFILE_PERFORMANCE:
if (dytc_profile_available == DYTC_FUNCMODE_MMC)
if (dytc_capabilities & BIT(DYTC_FC_MMC))
*perfmode = DYTC_MODE_MMC_PERFORM;
else if (dytc_profile_available == DYTC_FUNCMODE_PSC)
else if (dytc_capabilities & BIT(DYTC_FC_PSC))
*perfmode = DYTC_MODE_PSC_PERFORM;
break;
default: /* Unknown profile */
......@@ -10445,7 +10440,7 @@ static int dytc_profile_set(struct platform_profile_handler *pprof,
if (err)
goto unlock;
if (dytc_profile_available == DYTC_FUNCMODE_MMC) {
if (dytc_capabilities & BIT(DYTC_FC_MMC)) {
if (profile == PLATFORM_PROFILE_BALANCED) {
/*
* To get back to balanced mode we need to issue a reset command.
......@@ -10464,7 +10459,7 @@ static int dytc_profile_set(struct platform_profile_handler *pprof,
goto unlock;
}
}
if (dytc_profile_available == DYTC_FUNCMODE_PSC) {
if (dytc_capabilities & BIT(DYTC_FC_PSC)) {
err = dytc_command(DYTC_SET_COMMAND(DYTC_FUNCTION_PSC, perfmode, 1), &output);
if (err)
goto unlock;
......@@ -10483,12 +10478,12 @@ static void dytc_profile_refresh(void)
int perfmode;
mutex_lock(&dytc_mutex);
if (dytc_profile_available == DYTC_FUNCMODE_MMC) {
if (dytc_capabilities & BIT(DYTC_FC_MMC)) {
if (dytc_mmc_get_available)
err = dytc_command(DYTC_CMD_MMC_GET, &output);
else
err = dytc_cql_command(DYTC_CMD_GET, &output);
} else if (dytc_profile_available == DYTC_FUNCMODE_PSC)
} else if (dytc_capabilities & BIT(DYTC_FC_PSC))
err = dytc_command(DYTC_CMD_GET, &output);
mutex_unlock(&dytc_mutex);
......@@ -10517,7 +10512,6 @@ static int tpacpi_dytc_profile_init(struct ibm_init_struct *iibm)
set_bit(PLATFORM_PROFILE_BALANCED, dytc_profile.choices);
set_bit(PLATFORM_PROFILE_PERFORMANCE, dytc_profile.choices);
dytc_profile_available = DYTC_FUNCMODE_NONE;
err = dytc_command(DYTC_CMD_QUERY, &output);
if (err)
return err;
......@@ -10530,13 +10524,12 @@ static int tpacpi_dytc_profile_init(struct ibm_init_struct *iibm)
return -ENODEV;
/* Check what capabilities are supported */
err = dytc_command(DYTC_CMD_FUNC_CAP, &output);
err = dytc_command(DYTC_CMD_FUNC_CAP, &dytc_capabilities);
if (err)
return err;
if (output & BIT(DYTC_FC_MMC)) { /* MMC MODE */
dytc_profile_available = DYTC_FUNCMODE_MMC;
if (dytc_capabilities & BIT(DYTC_FC_MMC)) { /* MMC MODE */
pr_debug("MMC is supported\n");
/*
* Check if MMC_GET functionality available
* Version > 6 and return success from MMC_GET command
......@@ -10547,8 +10540,13 @@ static int tpacpi_dytc_profile_init(struct ibm_init_struct *iibm)
if (!err && ((output & DYTC_ERR_MASK) == DYTC_ERR_SUCCESS))
dytc_mmc_get_available = true;
}
} else if (output & BIT(DYTC_FC_PSC)) { /* PSC MODE */
dytc_profile_available = DYTC_FUNCMODE_PSC;
} else if (dytc_capabilities & BIT(DYTC_FC_PSC)) { /* PSC MODE */
/* Support for this only works on AMD platforms */
if (boot_cpu_data.x86_vendor != X86_VENDOR_AMD) {
dbg_printk(TPACPI_DBG_INIT, "PSC not support on Intel platforms\n");
return -ENODEV;
}
pr_debug("PSC is supported\n");
} else {
dbg_printk(TPACPI_DBG_INIT, "No DYTC support available\n");
return -ENODEV;
......@@ -10574,7 +10572,6 @@ static int tpacpi_dytc_profile_init(struct ibm_init_struct *iibm)
static void dytc_profile_exit(void)
{
dytc_profile_available = DYTC_FUNCMODE_NONE;
platform_profile_remove();
}
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment