forked from Minki/linux
platform-drivers-x86 for v5.12-2
Summary: - dell-wmi-sysman: A set of probe-error-exit-handling fixes to fix some systems which advertise the WMI GUIDs, but are not compatible, not booting - intel-vbtn/intel-hid: Misc. bugfixes - intel_pmc: Bug-fixes + a quirk to lower suspend power-consumption on Tiger Lake - thinkpad_acpi: Misc. bugfixes The following is an automated git shortlog grouped by driver: dell-wmi-sysman: - Cleanup create_attributes_level_sysfs_files() - Make sysman_init() return -ENODEV of the interfaces are not found - Cleanup sysman_init() error-exit handling - Fix release_attributes_data() getting called twice on init_bios_attributes() failure - Make it safe to call exit_foo_attributes() multiple times - Fix possible NULL pointer deref on exit - Fix crash caused by calling kset_unregister twice intel-hid: - Support Lenovo ThinkPad X1 Tablet Gen 2 intel-vbtn: - Stop reporting SW_DOCK events intel_pmc_core: - Ignore GBE LTR on Tiger Lake platforms - Update Kconfig intel_pmt_class: - Initial resource to 0 intel_pmt_crashlog: - Fix incorrect macros thinkpad_acpi: - Disable DYTC CQL mode around switching to balanced mode - Allow the FnLock LED to change state - check dytc version for lapmode sysfs -----BEGIN PGP SIGNATURE----- iQFIBAABCAAyFiEEuvA7XScYQRpenhd+kuxHeUQDJ9wFAmBbbL0UHGhkZWdvZWRl QHJlZGhhdC5jb20ACgkQkuxHeUQDJ9yYEgf/dWwTip21gYoi02mdsHsPduaL0Mtu grcZpnRSEuWvgl5P26zttmLjAK4rTyySePVBWsxDwH/4qBqY2DCicSQfeQke2/9c PJU3i8zXTQxlBUWFrjM8vqFKdTypFXJwpdoBGQD3JJAh8LcSQj5xkhhDQVJYIXLQ HIxVM44gPLZc/lHOFGUEtREc2/k2/A09pER6udvVGxSy/Vz1w646G3u9f5edi1jz jX5HIlEtEYpZ55E8bQSUcMIVpiv6HLAu5qQXQ+1xeQXXwM7mM6gRpG8Qr9Cy70Aq us0AA5AjYd4IudlgFtUQ7NOB5YYEs2WHiFx4+ck0DSE7CMzcamnUNNp7Tg== =ybep -----END PGP SIGNATURE----- Merge tag 'platform-drivers-x86-v5.12-2' of git://git.kernel.org/pub/scm/linux/kernel/git/pdx86/platform-drivers-x86 Pull x86 platform drivers fixes from Hans de Goede: "A set of bug-fixes and some model specific quirks. Summary: - dell-wmi-sysman: A set of probe-error-exit-handling fixes to fix some systems which advertise the WMI GUIDs, but are not compatible, not booting - intel-vbtn/intel-hid: Misc. bugfixes - intel_pmc: Bug-fixes + a quirk to lower suspend power-consumption on Tiger Lake - thinkpad_acpi: misc bugfixes" * tag 'platform-drivers-x86-v5.12-2' of git://git.kernel.org/pub/scm/linux/kernel/git/pdx86/platform-drivers-x86: platform/x86: intel_pmc_core: Ignore GBE LTR on Tiger Lake platforms platform/x86: intel_pmc_core: Update Kconfig platform/x86: intel_pmt_crashlog: Fix incorrect macros platform/x86: intel_pmt_class: Initial resource to 0 platform/x86: intel-vbtn: Stop reporting SW_DOCK events platform/x86: dell-wmi-sysman: Cleanup create_attributes_level_sysfs_files() platform/x86: dell-wmi-sysman: Make sysman_init() return -ENODEV of the interfaces are not found platform/x86: dell-wmi-sysman: Cleanup sysman_init() error-exit handling platform/x86: dell-wmi-sysman: Fix release_attributes_data() getting called twice on init_bios_attributes() failure platform/x86: dell-wmi-sysman: Make it safe to call exit_foo_attributes() multiple times platform/x86: dell-wmi-sysman: Fix possible NULL pointer deref on exit platform/x86: dell-wmi-sysman: Fix crash caused by calling kset_unregister twice platform/x86: thinkpad_acpi: Disable DYTC CQL mode around switching to balanced mode platform/x86: thinkpad_acpi: Allow the FnLock LED to change state platform/x86: thinkpad_acpi: check dytc version for lapmode sysfs platform/x86: intel-hid: Support Lenovo ThinkPad X1 Tablet Gen 2
This commit is contained in:
commit
a0a4df6a9e
@ -1173,15 +1173,20 @@ config INTEL_PMC_CORE
|
||||
depends on PCI
|
||||
help
|
||||
The Intel Platform Controller Hub for Intel Core SoCs provides access
|
||||
to Power Management Controller registers via a PCI interface. This
|
||||
to Power Management Controller registers via various interfaces. This
|
||||
driver can utilize debugging capabilities and supported features as
|
||||
exposed by the Power Management Controller.
|
||||
exposed by the Power Management Controller. It also may perform some
|
||||
tasks in the PMC in order to enable transition into the SLPS0 state.
|
||||
It should be selected on all Intel platforms supported by the driver.
|
||||
|
||||
Supported features:
|
||||
- SLP_S0_RESIDENCY counter
|
||||
- PCH IP Power Gating status
|
||||
- LTR Ignore
|
||||
- LTR Ignore / LTR Show
|
||||
- MPHY/PLL gating status (Sunrisepoint PCH only)
|
||||
- SLPS0 Debug registers (Cannonlake/Icelake PCH)
|
||||
- Low Power Mode registers (Tigerlake and beyond)
|
||||
- PMC quirks as needed to enable SLPS0/S0ix
|
||||
|
||||
config INTEL_PMT_CLASS
|
||||
tristate
|
||||
|
@ -185,5 +185,8 @@ void exit_enum_attributes(void)
|
||||
sysfs_remove_group(wmi_priv.enumeration_data[instance_id].attr_name_kobj,
|
||||
&enumeration_attr_group);
|
||||
}
|
||||
wmi_priv.enumeration_instances_count = 0;
|
||||
|
||||
kfree(wmi_priv.enumeration_data);
|
||||
wmi_priv.enumeration_data = NULL;
|
||||
}
|
||||
|
@ -175,5 +175,8 @@ void exit_int_attributes(void)
|
||||
sysfs_remove_group(wmi_priv.integer_data[instance_id].attr_name_kobj,
|
||||
&integer_attr_group);
|
||||
}
|
||||
wmi_priv.integer_instances_count = 0;
|
||||
|
||||
kfree(wmi_priv.integer_data);
|
||||
wmi_priv.integer_data = NULL;
|
||||
}
|
||||
|
@ -183,5 +183,8 @@ void exit_po_attributes(void)
|
||||
sysfs_remove_group(wmi_priv.po_data[instance_id].attr_name_kobj,
|
||||
&po_attr_group);
|
||||
}
|
||||
wmi_priv.po_instances_count = 0;
|
||||
|
||||
kfree(wmi_priv.po_data);
|
||||
wmi_priv.po_data = NULL;
|
||||
}
|
||||
|
@ -155,5 +155,8 @@ void exit_str_attributes(void)
|
||||
sysfs_remove_group(wmi_priv.str_data[instance_id].attr_name_kobj,
|
||||
&str_attr_group);
|
||||
}
|
||||
wmi_priv.str_instances_count = 0;
|
||||
|
||||
kfree(wmi_priv.str_data);
|
||||
wmi_priv.str_data = NULL;
|
||||
}
|
||||
|
@ -210,25 +210,17 @@ static struct kobj_attribute pending_reboot = __ATTR_RO(pending_reboot);
|
||||
*/
|
||||
static int create_attributes_level_sysfs_files(void)
|
||||
{
|
||||
int ret = sysfs_create_file(&wmi_priv.main_dir_kset->kobj, &reset_bios.attr);
|
||||
int ret;
|
||||
|
||||
if (ret) {
|
||||
pr_debug("could not create reset_bios file\n");
|
||||
ret = sysfs_create_file(&wmi_priv.main_dir_kset->kobj, &reset_bios.attr);
|
||||
if (ret)
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = sysfs_create_file(&wmi_priv.main_dir_kset->kobj, &pending_reboot.attr);
|
||||
if (ret) {
|
||||
pr_debug("could not create changing_pending_reboot file\n");
|
||||
sysfs_remove_file(&wmi_priv.main_dir_kset->kobj, &reset_bios.attr);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
static void release_reset_bios_data(void)
|
||||
{
|
||||
sysfs_remove_file(&wmi_priv.main_dir_kset->kobj, &reset_bios.attr);
|
||||
sysfs_remove_file(&wmi_priv.main_dir_kset->kobj, &pending_reboot.attr);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static ssize_t wmi_sysman_attr_show(struct kobject *kobj, struct attribute *attr,
|
||||
@ -373,8 +365,6 @@ static void destroy_attribute_objs(struct kset *kset)
|
||||
*/
|
||||
static void release_attributes_data(void)
|
||||
{
|
||||
release_reset_bios_data();
|
||||
|
||||
mutex_lock(&wmi_priv.mutex);
|
||||
exit_enum_attributes();
|
||||
exit_int_attributes();
|
||||
@ -386,11 +376,13 @@ static void release_attributes_data(void)
|
||||
wmi_priv.authentication_dir_kset = NULL;
|
||||
}
|
||||
if (wmi_priv.main_dir_kset) {
|
||||
sysfs_remove_file(&wmi_priv.main_dir_kset->kobj, &reset_bios.attr);
|
||||
sysfs_remove_file(&wmi_priv.main_dir_kset->kobj, &pending_reboot.attr);
|
||||
destroy_attribute_objs(wmi_priv.main_dir_kset);
|
||||
kset_unregister(wmi_priv.main_dir_kset);
|
||||
wmi_priv.main_dir_kset = NULL;
|
||||
}
|
||||
mutex_unlock(&wmi_priv.mutex);
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
@ -497,7 +489,6 @@ nextobj:
|
||||
|
||||
err_attr_init:
|
||||
mutex_unlock(&wmi_priv.mutex);
|
||||
release_attributes_data();
|
||||
kfree(obj);
|
||||
return retval;
|
||||
}
|
||||
@ -513,102 +504,91 @@ static int __init sysman_init(void)
|
||||
}
|
||||
|
||||
ret = init_bios_attr_set_interface();
|
||||
if (ret || !wmi_priv.bios_attr_wdev) {
|
||||
pr_debug("failed to initialize set interface\n");
|
||||
goto fail_set_interface;
|
||||
}
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
ret = init_bios_attr_pass_interface();
|
||||
if (ret || !wmi_priv.password_attr_wdev) {
|
||||
pr_debug("failed to initialize pass interface\n");
|
||||
goto fail_pass_interface;
|
||||
if (ret)
|
||||
goto err_exit_bios_attr_set_interface;
|
||||
|
||||
if (!wmi_priv.bios_attr_wdev || !wmi_priv.password_attr_wdev) {
|
||||
pr_debug("failed to find set or pass interface\n");
|
||||
ret = -ENODEV;
|
||||
goto err_exit_bios_attr_pass_interface;
|
||||
}
|
||||
|
||||
ret = class_register(&firmware_attributes_class);
|
||||
if (ret)
|
||||
goto fail_class;
|
||||
goto err_exit_bios_attr_pass_interface;
|
||||
|
||||
wmi_priv.class_dev = device_create(&firmware_attributes_class, NULL, MKDEV(0, 0),
|
||||
NULL, "%s", DRIVER_NAME);
|
||||
if (IS_ERR(wmi_priv.class_dev)) {
|
||||
ret = PTR_ERR(wmi_priv.class_dev);
|
||||
goto fail_classdev;
|
||||
goto err_unregister_class;
|
||||
}
|
||||
|
||||
wmi_priv.main_dir_kset = kset_create_and_add("attributes", NULL,
|
||||
&wmi_priv.class_dev->kobj);
|
||||
if (!wmi_priv.main_dir_kset) {
|
||||
ret = -ENOMEM;
|
||||
goto fail_main_kset;
|
||||
goto err_destroy_classdev;
|
||||
}
|
||||
|
||||
wmi_priv.authentication_dir_kset = kset_create_and_add("authentication", NULL,
|
||||
&wmi_priv.class_dev->kobj);
|
||||
if (!wmi_priv.authentication_dir_kset) {
|
||||
ret = -ENOMEM;
|
||||
goto fail_authentication_kset;
|
||||
goto err_release_attributes_data;
|
||||
}
|
||||
|
||||
ret = create_attributes_level_sysfs_files();
|
||||
if (ret) {
|
||||
pr_debug("could not create reset BIOS attribute\n");
|
||||
goto fail_reset_bios;
|
||||
goto err_release_attributes_data;
|
||||
}
|
||||
|
||||
ret = init_bios_attributes(ENUM, DELL_WMI_BIOS_ENUMERATION_ATTRIBUTE_GUID);
|
||||
if (ret) {
|
||||
pr_debug("failed to populate enumeration type attributes\n");
|
||||
goto fail_create_group;
|
||||
goto err_release_attributes_data;
|
||||
}
|
||||
|
||||
ret = init_bios_attributes(INT, DELL_WMI_BIOS_INTEGER_ATTRIBUTE_GUID);
|
||||
if (ret) {
|
||||
pr_debug("failed to populate integer type attributes\n");
|
||||
goto fail_create_group;
|
||||
goto err_release_attributes_data;
|
||||
}
|
||||
|
||||
ret = init_bios_attributes(STR, DELL_WMI_BIOS_STRING_ATTRIBUTE_GUID);
|
||||
if (ret) {
|
||||
pr_debug("failed to populate string type attributes\n");
|
||||
goto fail_create_group;
|
||||
goto err_release_attributes_data;
|
||||
}
|
||||
|
||||
ret = init_bios_attributes(PO, DELL_WMI_BIOS_PASSOBJ_ATTRIBUTE_GUID);
|
||||
if (ret) {
|
||||
pr_debug("failed to populate pass object type attributes\n");
|
||||
goto fail_create_group;
|
||||
goto err_release_attributes_data;
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
fail_create_group:
|
||||
err_release_attributes_data:
|
||||
release_attributes_data();
|
||||
|
||||
fail_reset_bios:
|
||||
if (wmi_priv.authentication_dir_kset) {
|
||||
kset_unregister(wmi_priv.authentication_dir_kset);
|
||||
wmi_priv.authentication_dir_kset = NULL;
|
||||
}
|
||||
|
||||
fail_authentication_kset:
|
||||
if (wmi_priv.main_dir_kset) {
|
||||
kset_unregister(wmi_priv.main_dir_kset);
|
||||
wmi_priv.main_dir_kset = NULL;
|
||||
}
|
||||
|
||||
fail_main_kset:
|
||||
err_destroy_classdev:
|
||||
device_destroy(&firmware_attributes_class, MKDEV(0, 0));
|
||||
|
||||
fail_classdev:
|
||||
err_unregister_class:
|
||||
class_unregister(&firmware_attributes_class);
|
||||
|
||||
fail_class:
|
||||
err_exit_bios_attr_pass_interface:
|
||||
exit_bios_attr_pass_interface();
|
||||
|
||||
fail_pass_interface:
|
||||
err_exit_bios_attr_set_interface:
|
||||
exit_bios_attr_set_interface();
|
||||
|
||||
fail_set_interface:
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
@ -90,6 +90,13 @@ static const struct dmi_system_id button_array_table[] = {
|
||||
DMI_MATCH(DMI_PRODUCT_NAME, "HP Spectre x2 Detachable"),
|
||||
},
|
||||
},
|
||||
{
|
||||
.ident = "Lenovo ThinkPad X1 Tablet Gen 2",
|
||||
.matches = {
|
||||
DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"),
|
||||
DMI_MATCH(DMI_PRODUCT_FAMILY, "ThinkPad X1 Tablet Gen 2"),
|
||||
},
|
||||
},
|
||||
{ }
|
||||
};
|
||||
|
||||
|
@ -48,8 +48,16 @@ static const struct key_entry intel_vbtn_keymap[] = {
|
||||
};
|
||||
|
||||
static const struct key_entry intel_vbtn_switchmap[] = {
|
||||
{ KE_SW, 0xCA, { .sw = { SW_DOCK, 1 } } }, /* Docked */
|
||||
{ KE_SW, 0xCB, { .sw = { SW_DOCK, 0 } } }, /* Undocked */
|
||||
/*
|
||||
* SW_DOCK should only be reported for docking stations, but DSDTs using the
|
||||
* intel-vbtn code, always seem to use this for 2-in-1s / convertibles and set
|
||||
* SW_DOCK=1 when in laptop-mode (in tandem with setting SW_TABLET_MODE=0).
|
||||
* This causes userspace to think the laptop is docked to a port-replicator
|
||||
* and to disable suspend-on-lid-close, which is undesirable.
|
||||
* Map the dock events to KEY_IGNORE to avoid this broken SW_DOCK reporting.
|
||||
*/
|
||||
{ KE_IGNORE, 0xCA, { .sw = { SW_DOCK, 1 } } }, /* Docked */
|
||||
{ KE_IGNORE, 0xCB, { .sw = { SW_DOCK, 0 } } }, /* Undocked */
|
||||
{ KE_SW, 0xCC, { .sw = { SW_TABLET_MODE, 1 } } }, /* Tablet */
|
||||
{ KE_SW, 0xCD, { .sw = { SW_TABLET_MODE, 0 } } }, /* Laptop */
|
||||
{ KE_END }
|
||||
|
@ -863,34 +863,45 @@ out_unlock:
|
||||
}
|
||||
DEFINE_SHOW_ATTRIBUTE(pmc_core_pll);
|
||||
|
||||
static ssize_t pmc_core_ltr_ignore_write(struct file *file,
|
||||
const char __user *userbuf,
|
||||
size_t count, loff_t *ppos)
|
||||
static int pmc_core_send_ltr_ignore(u32 value)
|
||||
{
|
||||
struct pmc_dev *pmcdev = &pmc;
|
||||
const struct pmc_reg_map *map = pmcdev->map;
|
||||
u32 val, buf_size, fd;
|
||||
int err;
|
||||
|
||||
buf_size = count < 64 ? count : 64;
|
||||
|
||||
err = kstrtou32_from_user(userbuf, buf_size, 10, &val);
|
||||
if (err)
|
||||
return err;
|
||||
u32 reg;
|
||||
int err = 0;
|
||||
|
||||
mutex_lock(&pmcdev->lock);
|
||||
|
||||
if (val > map->ltr_ignore_max) {
|
||||
if (value > map->ltr_ignore_max) {
|
||||
err = -EINVAL;
|
||||
goto out_unlock;
|
||||
}
|
||||
|
||||
fd = pmc_core_reg_read(pmcdev, map->ltr_ignore_offset);
|
||||
fd |= (1U << val);
|
||||
pmc_core_reg_write(pmcdev, map->ltr_ignore_offset, fd);
|
||||
reg = pmc_core_reg_read(pmcdev, map->ltr_ignore_offset);
|
||||
reg |= BIT(value);
|
||||
pmc_core_reg_write(pmcdev, map->ltr_ignore_offset, reg);
|
||||
|
||||
out_unlock:
|
||||
mutex_unlock(&pmcdev->lock);
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
static ssize_t pmc_core_ltr_ignore_write(struct file *file,
|
||||
const char __user *userbuf,
|
||||
size_t count, loff_t *ppos)
|
||||
{
|
||||
u32 buf_size, value;
|
||||
int err;
|
||||
|
||||
buf_size = min_t(u32, count, 64);
|
||||
|
||||
err = kstrtou32_from_user(userbuf, buf_size, 10, &value);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
err = pmc_core_send_ltr_ignore(value);
|
||||
|
||||
return err == 0 ? count : err;
|
||||
}
|
||||
|
||||
@ -1244,6 +1255,15 @@ static int pmc_core_probe(struct platform_device *pdev)
|
||||
pmcdev->pmc_xram_read_bit = pmc_core_check_read_lock_bit();
|
||||
dmi_check_system(pmc_core_dmi_table);
|
||||
|
||||
/*
|
||||
* On TGL, due to a hardware limitation, the GBE LTR blocks PC10 when
|
||||
* a cable is attached. Tell the PMC to ignore it.
|
||||
*/
|
||||
if (pmcdev->map == &tgl_reg_map) {
|
||||
dev_dbg(&pdev->dev, "ignoring GBE LTR\n");
|
||||
pmc_core_send_ltr_ignore(3);
|
||||
}
|
||||
|
||||
pmc_core_dbgfs_register(pmcdev);
|
||||
|
||||
device_initialized = true;
|
||||
|
@ -173,7 +173,7 @@ static int intel_pmt_dev_register(struct intel_pmt_entry *entry,
|
||||
struct intel_pmt_namespace *ns,
|
||||
struct device *parent)
|
||||
{
|
||||
struct resource res;
|
||||
struct resource res = {0};
|
||||
struct device *dev;
|
||||
int ret;
|
||||
|
||||
|
@ -23,18 +23,17 @@
|
||||
#define CRASH_TYPE_OOBMSM 1
|
||||
|
||||
/* Control Flags */
|
||||
#define CRASHLOG_FLAG_DISABLE BIT(27)
|
||||
#define CRASHLOG_FLAG_DISABLE BIT(28)
|
||||
|
||||
/*
|
||||
* Bits 28 and 29 control the state of bit 31.
|
||||
* Bits 29 and 30 control the state of bit 31.
|
||||
*
|
||||
* Bit 28 will clear bit 31, if set, allowing a new crashlog to be captured.
|
||||
* Bit 29 will immediately trigger a crashlog to be generated, setting bit 31.
|
||||
* Bit 30 is read-only and reserved as 0.
|
||||
* Bit 29 will clear bit 31, if set, allowing a new crashlog to be captured.
|
||||
* Bit 30 will immediately trigger a crashlog to be generated, setting bit 31.
|
||||
* Bit 31 is the read-only status with a 1 indicating log is complete.
|
||||
*/
|
||||
#define CRASHLOG_FLAG_TRIGGER_CLEAR BIT(28)
|
||||
#define CRASHLOG_FLAG_TRIGGER_EXECUTE BIT(29)
|
||||
#define CRASHLOG_FLAG_TRIGGER_CLEAR BIT(29)
|
||||
#define CRASHLOG_FLAG_TRIGGER_EXECUTE BIT(30)
|
||||
#define CRASHLOG_FLAG_TRIGGER_COMPLETE BIT(31)
|
||||
#define CRASHLOG_FLAG_TRIGGER_MASK GENMASK(31, 28)
|
||||
|
||||
|
@ -4081,13 +4081,19 @@ static bool hotkey_notify_6xxx(const u32 hkey,
|
||||
|
||||
case TP_HKEY_EV_KEY_NUMLOCK:
|
||||
case TP_HKEY_EV_KEY_FN:
|
||||
case TP_HKEY_EV_KEY_FN_ESC:
|
||||
/* key press events, we just ignore them as long as the EC
|
||||
* is still reporting them in the normal keyboard stream */
|
||||
*send_acpi_ev = false;
|
||||
*ignore_acpi_ev = true;
|
||||
return true;
|
||||
|
||||
case TP_HKEY_EV_KEY_FN_ESC:
|
||||
/* Get the media key status to foce the status LED to update */
|
||||
acpi_evalf(hkey_handle, NULL, "GMKS", "v");
|
||||
*send_acpi_ev = false;
|
||||
*ignore_acpi_ev = true;
|
||||
return true;
|
||||
|
||||
case TP_HKEY_EV_TABLET_CHANGED:
|
||||
tpacpi_input_send_tabletsw();
|
||||
hotkey_tablet_mode_notify_change();
|
||||
@ -9845,6 +9851,11 @@ static struct ibm_struct lcdshadow_driver_data = {
|
||||
* Thinkpad sensor interfaces
|
||||
*/
|
||||
|
||||
#define DYTC_CMD_QUERY 0 /* To get DYTC status - enable/revision */
|
||||
#define DYTC_QUERY_ENABLE_BIT 8 /* Bit 8 - 0 = disabled, 1 = enabled */
|
||||
#define DYTC_QUERY_SUBREV_BIT 16 /* Bits 16 - 27 - sub revision */
|
||||
#define DYTC_QUERY_REV_BIT 28 /* Bits 28 - 31 - revision */
|
||||
|
||||
#define DYTC_CMD_GET 2 /* To get current IC function and mode */
|
||||
#define DYTC_GET_LAPMODE_BIT 17 /* Set when in lapmode */
|
||||
|
||||
@ -9855,6 +9866,7 @@ static bool has_palmsensor;
|
||||
static bool has_lapsensor;
|
||||
static bool palm_state;
|
||||
static bool lap_state;
|
||||
static int dytc_version;
|
||||
|
||||
static int dytc_command(int command, int *output)
|
||||
{
|
||||
@ -9869,6 +9881,33 @@ static int dytc_command(int command, int *output)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int dytc_get_version(void)
|
||||
{
|
||||
int err, output;
|
||||
|
||||
/* Check if we've been called before - and just return cached value */
|
||||
if (dytc_version)
|
||||
return dytc_version;
|
||||
|
||||
/* Otherwise query DYTC and extract version information */
|
||||
err = dytc_command(DYTC_CMD_QUERY, &output);
|
||||
/*
|
||||
* If support isn't available (ENODEV) then don't return an error
|
||||
* and don't create the sysfs group
|
||||
*/
|
||||
if (err == -ENODEV)
|
||||
return 0;
|
||||
/* For all other errors we can flag the failure */
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
/* Check DYTC is enabled and supports mode setting */
|
||||
if (output & BIT(DYTC_QUERY_ENABLE_BIT))
|
||||
dytc_version = (output >> DYTC_QUERY_REV_BIT) & 0xF;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int lapsensor_get(bool *present, bool *state)
|
||||
{
|
||||
int output, err;
|
||||
@ -9974,7 +10013,18 @@ static int tpacpi_proxsensor_init(struct ibm_init_struct *iibm)
|
||||
if (err)
|
||||
return err;
|
||||
}
|
||||
if (has_lapsensor) {
|
||||
|
||||
/* Check if we know the DYTC version, if we don't then get it */
|
||||
if (!dytc_version) {
|
||||
err = dytc_get_version();
|
||||
if (err)
|
||||
return err;
|
||||
}
|
||||
/*
|
||||
* Platforms before DYTC version 5 claim to have a lap sensor, but it doesn't work, so we
|
||||
* ignore them
|
||||
*/
|
||||
if (has_lapsensor && (dytc_version >= 5)) {
|
||||
err = sysfs_create_file(&tpacpi_pdev->dev.kobj, &dev_attr_dytc_lapmode.attr);
|
||||
if (err)
|
||||
return err;
|
||||
@ -9999,14 +10049,9 @@ static struct ibm_struct proxsensor_driver_data = {
|
||||
* DYTC Platform Profile interface
|
||||
*/
|
||||
|
||||
#define DYTC_CMD_QUERY 0 /* To get DYTC status - enable/revision */
|
||||
#define DYTC_CMD_SET 1 /* To enable/disable IC function mode */
|
||||
#define DYTC_CMD_RESET 0x1ff /* To reset back to default */
|
||||
|
||||
#define DYTC_QUERY_ENABLE_BIT 8 /* Bit 8 - 0 = disabled, 1 = enabled */
|
||||
#define DYTC_QUERY_SUBREV_BIT 16 /* Bits 16 - 27 - sub revision */
|
||||
#define DYTC_QUERY_REV_BIT 28 /* Bits 28 - 31 - revision */
|
||||
|
||||
#define DYTC_GET_FUNCTION_BIT 8 /* Bits 8-11 - function setting */
|
||||
#define DYTC_GET_MODE_BIT 12 /* Bits 12-15 - mode setting */
|
||||
|
||||
@ -10142,8 +10187,13 @@ static int dytc_profile_set(struct platform_profile_handler *pprof,
|
||||
return err;
|
||||
|
||||
if (profile == PLATFORM_PROFILE_BALANCED) {
|
||||
/* To get back to balanced mode we just issue a reset command */
|
||||
err = dytc_command(DYTC_CMD_RESET, &output);
|
||||
/*
|
||||
* To get back to balanced mode we need to issue a reset command.
|
||||
* Note we still need to disable CQL mode before hand and re-enable
|
||||
* it afterwards, otherwise dytc_lapmode gets reset to 0 and stays
|
||||
* stuck at 0 for aprox. 30 minutes.
|
||||
*/
|
||||
err = dytc_cql_command(DYTC_CMD_RESET, &output);
|
||||
if (err)
|
||||
goto unlock;
|
||||
} else {
|
||||
@ -10211,28 +10261,28 @@ static int tpacpi_dytc_profile_init(struct ibm_init_struct *iibm)
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
/* Check if we know the DYTC version, if we don't then get it */
|
||||
if (!dytc_version) {
|
||||
err = dytc_get_version();
|
||||
if (err)
|
||||
return err;
|
||||
}
|
||||
/* Check DYTC is enabled and supports mode setting */
|
||||
if (output & BIT(DYTC_QUERY_ENABLE_BIT)) {
|
||||
/* Only DYTC v5.0 and later has this feature. */
|
||||
int dytc_version;
|
||||
if (dytc_version >= 5) {
|
||||
dbg_printk(TPACPI_DBG_INIT,
|
||||
"DYTC version %d: thermal mode available\n", dytc_version);
|
||||
/* Create platform_profile structure and register */
|
||||
err = platform_profile_register(&dytc_profile);
|
||||
/*
|
||||
* If for some reason platform_profiles aren't enabled
|
||||
* don't quit terminally.
|
||||
*/
|
||||
if (err)
|
||||
return 0;
|
||||
|
||||
dytc_version = (output >> DYTC_QUERY_REV_BIT) & 0xF;
|
||||
if (dytc_version >= 5) {
|
||||
dbg_printk(TPACPI_DBG_INIT,
|
||||
"DYTC version %d: thermal mode available\n", dytc_version);
|
||||
/* Create platform_profile structure and register */
|
||||
err = platform_profile_register(&dytc_profile);
|
||||
/*
|
||||
* If for some reason platform_profiles aren't enabled
|
||||
* don't quit terminally.
|
||||
*/
|
||||
if (err)
|
||||
return 0;
|
||||
|
||||
dytc_profile_available = true;
|
||||
/* Ensure initial values are correct */
|
||||
dytc_profile_refresh();
|
||||
}
|
||||
dytc_profile_available = true;
|
||||
/* Ensure initial values are correct */
|
||||
dytc_profile_refresh();
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user