diff options
Diffstat (limited to 'drivers/platform/x86')
-rw-r--r-- | drivers/platform/x86/Kconfig | 1 | ||||
-rw-r--r-- | drivers/platform/x86/hp-wmi.c | 47 | ||||
-rw-r--r-- | drivers/platform/x86/i2c-multi-instantiate.c | 2 | ||||
-rw-r--r-- | drivers/platform/x86/intel-hid.c | 36 | ||||
-rw-r--r-- | drivers/platform/x86/intel-vbtn.c | 20 | ||||
-rw-r--r-- | drivers/platform/x86/intel_cht_int33fe.c | 57 | ||||
-rw-r--r-- | drivers/platform/x86/pmc_atom.c | 7 | ||||
-rw-r--r-- | drivers/platform/x86/surfacepro3_button.c | 47 |
8 files changed, 121 insertions, 96 deletions
diff --git a/drivers/platform/x86/Kconfig b/drivers/platform/x86/Kconfig index 1b67bb578f9f..ae21d08c65e8 100644 --- a/drivers/platform/x86/Kconfig +++ b/drivers/platform/x86/Kconfig @@ -674,6 +674,7 @@ config EEEPC_LAPTOP config ASUS_WMI tristate "ASUS WMI Driver" depends on ACPI_WMI + depends on ACPI_BATTERY depends on INPUT depends on HWMON depends on BACKLIGHT_CLASS_DEVICE diff --git a/drivers/platform/x86/hp-wmi.c b/drivers/platform/x86/hp-wmi.c index 2521e45280b8..6bcbbb375401 100644 --- a/drivers/platform/x86/hp-wmi.c +++ b/drivers/platform/x86/hp-wmi.c @@ -502,6 +502,17 @@ static DEVICE_ATTR_RO(dock); static DEVICE_ATTR_RO(tablet); static DEVICE_ATTR_RW(postcode); +static struct attribute *hp_wmi_attrs[] = { + &dev_attr_display.attr, + &dev_attr_hddtemp.attr, + &dev_attr_als.attr, + &dev_attr_dock.attr, + &dev_attr_tablet.attr, + &dev_attr_postcode.attr, + NULL, +}; +ATTRIBUTE_GROUPS(hp_wmi); + static void hp_wmi_notify(u32 value, void *context) { struct acpi_buffer response = { ACPI_ALLOCATE_BUFFER, NULL }; @@ -678,16 +689,6 @@ static void hp_wmi_input_destroy(void) input_unregister_device(hp_wmi_input_dev); } -static void cleanup_sysfs(struct platform_device *device) -{ - device_remove_file(&device->dev, &dev_attr_display); - device_remove_file(&device->dev, &dev_attr_hddtemp); - device_remove_file(&device->dev, &dev_attr_als); - device_remove_file(&device->dev, &dev_attr_dock); - device_remove_file(&device->dev, &dev_attr_tablet); - device_remove_file(&device->dev, &dev_attr_postcode); -} - static int __init hp_wmi_rfkill_setup(struct platform_device *device) { int err, wireless; @@ -858,8 +859,6 @@ fail: static int __init hp_wmi_bios_setup(struct platform_device *device) { - int err; - /* clear detected rfkill devices */ wifi_rfkill = NULL; bluetooth_rfkill = NULL; @@ -869,35 +868,12 @@ static int __init hp_wmi_bios_setup(struct platform_device *device) if (hp_wmi_rfkill_setup(device)) hp_wmi_rfkill2_setup(device); - err = device_create_file(&device->dev, &dev_attr_display); - if (err) - goto add_sysfs_error; - err = device_create_file(&device->dev, &dev_attr_hddtemp); - if (err) - goto add_sysfs_error; - err = device_create_file(&device->dev, &dev_attr_als); - if (err) - goto add_sysfs_error; - err = device_create_file(&device->dev, &dev_attr_dock); - if (err) - goto add_sysfs_error; - err = device_create_file(&device->dev, &dev_attr_tablet); - if (err) - goto add_sysfs_error; - err = device_create_file(&device->dev, &dev_attr_postcode); - if (err) - goto add_sysfs_error; return 0; - -add_sysfs_error: - cleanup_sysfs(device); - return err; } static int __exit hp_wmi_bios_remove(struct platform_device *device) { int i; - cleanup_sysfs(device); for (i = 0; i < rfkill2_count; i++) { rfkill_unregister(rfkill2[i].rfkill); @@ -966,6 +942,7 @@ static struct platform_driver hp_wmi_driver = { .driver = { .name = "hp-wmi", .pm = &hp_wmi_pm_ops, + .dev_groups = hp_wmi_groups, }, .remove = __exit_p(hp_wmi_bios_remove), }; diff --git a/drivers/platform/x86/i2c-multi-instantiate.c b/drivers/platform/x86/i2c-multi-instantiate.c index 61fe341a85aa..ea68f6ed66ae 100644 --- a/drivers/platform/x86/i2c-multi-instantiate.c +++ b/drivers/platform/x86/i2c-multi-instantiate.c @@ -90,7 +90,7 @@ static int i2c_multi_inst_probe(struct platform_device *pdev) for (i = 0; i < multi->num_clients && inst_data[i].type; i++) { memset(&board_info, 0, sizeof(board_info)); strlcpy(board_info.type, inst_data[i].type, I2C_NAME_SIZE); - snprintf(name, sizeof(name), "%s-%s.%d", match->id, + snprintf(name, sizeof(name), "%s-%s.%d", dev_name(dev), inst_data[i].type, i); board_info.dev_name = name; switch (inst_data[i].flags & IRQ_RESOURCE_TYPE) { diff --git a/drivers/platform/x86/intel-hid.c b/drivers/platform/x86/intel-hid.c index bc0d55a59015..ef6d4bd77b1a 100644 --- a/drivers/platform/x86/intel-hid.c +++ b/drivers/platform/x86/intel-hid.c @@ -253,35 +253,45 @@ static void intel_button_array_enable(struct device *device, bool enable) static int intel_hid_pm_prepare(struct device *device) { - struct intel_hid_priv *priv = dev_get_drvdata(device); + if (device_may_wakeup(device)) { + struct intel_hid_priv *priv = dev_get_drvdata(device); - priv->wakeup_mode = true; + priv->wakeup_mode = true; + } return 0; } +static void intel_hid_pm_complete(struct device *device) +{ + struct intel_hid_priv *priv = dev_get_drvdata(device); + + priv->wakeup_mode = false; +} + static int intel_hid_pl_suspend_handler(struct device *device) { - if (pm_suspend_via_firmware()) { + intel_button_array_enable(device, false); + + if (!pm_suspend_no_platform()) intel_hid_set_enable(device, false); - intel_button_array_enable(device, false); - } + return 0; } static int intel_hid_pl_resume_handler(struct device *device) { - struct intel_hid_priv *priv = dev_get_drvdata(device); + intel_hid_pm_complete(device); - priv->wakeup_mode = false; - if (pm_resume_via_firmware()) { + if (!pm_suspend_no_platform()) intel_hid_set_enable(device, true); - intel_button_array_enable(device, true); - } + + intel_button_array_enable(device, true); return 0; } static const struct dev_pm_ops intel_hid_pl_pm_ops = { .prepare = intel_hid_pm_prepare, + .complete = intel_hid_pm_complete, .freeze = intel_hid_pl_suspend_handler, .thaw = intel_hid_pl_resume_handler, .restore = intel_hid_pl_resume_handler, @@ -491,6 +501,12 @@ static int intel_hid_probe(struct platform_device *device) } device_init_wakeup(&device->dev, true); + /* + * In order for system wakeup to work, the EC GPE has to be marked as + * a wakeup one, so do that here (this setting will persist, but it has + * no effect until the wakeup mask is set for the EC GPE). + */ + acpi_ec_mark_gpe_for_wake(); return 0; err_remove_notify: diff --git a/drivers/platform/x86/intel-vbtn.c b/drivers/platform/x86/intel-vbtn.c index a0d0cecff55f..b74932307d69 100644 --- a/drivers/platform/x86/intel-vbtn.c +++ b/drivers/platform/x86/intel-vbtn.c @@ -176,6 +176,12 @@ static int intel_vbtn_probe(struct platform_device *device) return -EBUSY; device_init_wakeup(&device->dev, true); + /* + * In order for system wakeup to work, the EC GPE has to be marked as + * a wakeup one, so do that here (this setting will persist, but it has + * no effect until the wakeup mask is set for the EC GPE). + */ + acpi_ec_mark_gpe_for_wake(); return 0; } @@ -195,22 +201,30 @@ static int intel_vbtn_remove(struct platform_device *device) static int intel_vbtn_pm_prepare(struct device *dev) { - struct intel_vbtn_priv *priv = dev_get_drvdata(dev); + if (device_may_wakeup(dev)) { + struct intel_vbtn_priv *priv = dev_get_drvdata(dev); - priv->wakeup_mode = true; + priv->wakeup_mode = true; + } return 0; } -static int intel_vbtn_pm_resume(struct device *dev) +static void intel_vbtn_pm_complete(struct device *dev) { struct intel_vbtn_priv *priv = dev_get_drvdata(dev); priv->wakeup_mode = false; +} + +static int intel_vbtn_pm_resume(struct device *dev) +{ + intel_vbtn_pm_complete(dev); return 0; } static const struct dev_pm_ops intel_vbtn_pm_ops = { .prepare = intel_vbtn_pm_prepare, + .complete = intel_vbtn_pm_complete, .resume = intel_vbtn_pm_resume, .restore = intel_vbtn_pm_resume, .thaw = intel_vbtn_pm_resume, diff --git a/drivers/platform/x86/intel_cht_int33fe.c b/drivers/platform/x86/intel_cht_int33fe.c index 4fbdff48a4b5..1d5d877b9582 100644 --- a/drivers/platform/x86/intel_cht_int33fe.c +++ b/drivers/platform/x86/intel_cht_int33fe.c @@ -34,7 +34,6 @@ enum { INT33FE_NODE_MAX17047, INT33FE_NODE_PI3USB30532, INT33FE_NODE_DISPLAYPORT, - INT33FE_NODE_ROLE_SWITCH, INT33FE_NODE_USB_CONNECTOR, INT33FE_NODE_MAX, }; @@ -45,7 +44,6 @@ struct cht_int33fe_data { struct i2c_client *pi3usb30532; struct fwnode_handle *dp; - struct fwnode_handle *mux; }; static const struct software_node nodes[]; @@ -139,46 +137,10 @@ static const struct software_node nodes[] = { { "max17047", NULL, max17047_props }, { "pi3usb30532" }, { "displayport" }, - { "usb-role-switch" }, { "connector", &nodes[0], usb_connector_props, usb_connector_refs }, { } }; -static int cht_int33fe_setup_mux(struct cht_int33fe_data *data) -{ - struct fwnode_handle *fwnode; - struct device *dev; - struct device *p; - - fwnode = software_node_fwnode(&nodes[INT33FE_NODE_ROLE_SWITCH]); - if (!fwnode) - return -ENODEV; - - /* First finding the platform device */ - p = bus_find_device_by_name(&platform_bus_type, NULL, - "intel_xhci_usb_sw"); - if (!p) - return -EPROBE_DEFER; - - /* Then the mux child device */ - dev = device_find_child_by_name(p, "intel_xhci_usb_sw-role-switch"); - put_device(p); - if (!dev) - return -EPROBE_DEFER; - - /* If there already is a node for the mux, using that one. */ - if (dev->fwnode) - fwnode_remove_software_node(fwnode); - else - dev->fwnode = fwnode; - - data->mux = fwnode_handle_get(dev->fwnode); - put_device(dev); - mux_ref.node = to_software_node(data->mux); - - return 0; -} - static int cht_int33fe_setup_dp(struct cht_int33fe_data *data) { struct fwnode_handle *fwnode; @@ -211,10 +173,9 @@ static void cht_int33fe_remove_nodes(struct cht_int33fe_data *data) { software_node_unregister_nodes(nodes); - if (data->mux) { - fwnode_handle_put(data->mux); + if (mux_ref.node) { + fwnode_handle_put(software_node_fwnode(mux_ref.node)); mux_ref.node = NULL; - data->mux = NULL; } if (data->dp) { @@ -235,14 +196,16 @@ static int cht_int33fe_add_nodes(struct cht_int33fe_data *data) /* The devices that are not created in this driver need extra steps. */ /* - * There is no ACPI device node for the USB role mux, so we need to find - * the mux device and assign our node directly to it. That means we - * depend on the mux driver. This function will return -PROBE_DEFER - * until the mux device is registered. + * There is no ACPI device node for the USB role mux, so we need to wait + * until the mux driver has created software node for the mux device. + * It means we depend on the mux driver. This function will return + * -EPROBE_DEFER until the mux device is registered. */ - ret = cht_int33fe_setup_mux(data); - if (ret) + mux_ref.node = software_node_find_by_name(NULL, "intel-xhci-usb-sw"); + if (!mux_ref.node) { + ret = -EPROBE_DEFER; goto err_remove_nodes; + } /* * The DP connector does have ACPI device node. In this case we can just diff --git a/drivers/platform/x86/pmc_atom.c b/drivers/platform/x86/pmc_atom.c index 9aca5e7ce6d0..07d1b911e72f 100644 --- a/drivers/platform/x86/pmc_atom.c +++ b/drivers/platform/x86/pmc_atom.c @@ -422,6 +422,13 @@ static const struct dmi_system_id critclk_systems[] = { DMI_MATCH(DMI_PRODUCT_VERSION, "6ES7647-8B"), }, }, + { + .ident = "SIMATIC IPC277E", + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "SIEMENS AG"), + DMI_MATCH(DMI_PRODUCT_VERSION, "6AV7882-0"), + }, + }, { /*sentinel*/ } }; diff --git a/drivers/platform/x86/surfacepro3_button.c b/drivers/platform/x86/surfacepro3_button.c index 47c6d000465a..ec515223f654 100644 --- a/drivers/platform/x86/surfacepro3_button.c +++ b/drivers/platform/x86/surfacepro3_button.c @@ -20,6 +20,12 @@ #define SURFACE_BUTTON_OBJ_NAME "VGBI" #define SURFACE_BUTTON_DEVICE_NAME "Surface Pro 3/4 Buttons" +#define MSHW0040_DSM_REVISION 0x01 +#define MSHW0040_DSM_GET_OMPR 0x02 // get OEM Platform Revision +static const guid_t MSHW0040_DSM_UUID = + GUID_INIT(0x6fd05c69, 0xcde3, 0x49f4, 0x95, 0xed, 0xab, 0x16, 0x65, + 0x49, 0x80, 0x35); + #define SURFACE_BUTTON_NOTIFY_TABLET_MODE 0xc8 #define SURFACE_BUTTON_NOTIFY_PRESS_POWER 0xc6 @@ -142,6 +148,44 @@ static int surface_button_resume(struct device *dev) } #endif +/* + * Surface Pro 4 and Surface Book 2 / Surface Pro 2017 use the same device + * ID (MSHW0040) for the power/volume buttons. Make sure this is the right + * device by checking for the _DSM method and OEM Platform Revision. + * + * Returns true if the driver should bind to this device, i.e. the device is + * either MSWH0028 (Pro 3) or MSHW0040 on a Pro 4 or Book 1. + */ +static bool surface_button_check_MSHW0040(struct acpi_device *dev) +{ + acpi_handle handle = dev->handle; + union acpi_object *result; + u64 oem_platform_rev = 0; // valid revisions are nonzero + + // get OEM platform revision + result = acpi_evaluate_dsm_typed(handle, &MSHW0040_DSM_UUID, + MSHW0040_DSM_REVISION, + MSHW0040_DSM_GET_OMPR, + NULL, ACPI_TYPE_INTEGER); + + /* + * If evaluating the _DSM fails, the method is not present. This means + * that we have either MSHW0028 or MSHW0040 on Pro 4 or Book 1, so we + * should use this driver. We use revision 0 indicating it is + * unavailable. + */ + + if (result) { + oem_platform_rev = result->integer.value; + ACPI_FREE(result); + } + + dev_dbg(&dev->dev, "OEM Platform Revision %llu\n", oem_platform_rev); + + return oem_platform_rev == 0; +} + + static int surface_button_add(struct acpi_device *device) { struct surface_button *button; @@ -154,6 +198,9 @@ static int surface_button_add(struct acpi_device *device) strlen(SURFACE_BUTTON_OBJ_NAME))) return -ENODEV; + if (!surface_button_check_MSHW0040(device)) + return -ENODEV; + button = kzalloc(sizeof(struct surface_button), GFP_KERNEL); if (!button) return -ENOMEM; |