Skip to content

Commit

Permalink
Merge tag 'platform-drivers-x86-v4.7-1' of git://git.infradead.org/us…
Browse files Browse the repository at this point in the history
…ers/dvhart/linux-platform-drivers-x86

Pull x86 platform driver updates from Darren Hart:
 "Mostly minor updates and cleanups.  One new power management
  controller driver for Intel Core SoCs.

  platform/x86:
   - Add PMC Driver for Intel Core SoC

  dell-rbtn:
   - Ignore ACPI notifications if device is suspended

  thinkpad_acpi:
   - save kbdlight state on suspend and restore it on resume

  intel_menlow:
   - reduce code duplication

  asus-wmi:
   - provide access to ALS control

  ideapad-laptop:
   - add a new WMI string for ESC key

  surfacepro3_button:
   - Add a warning when switching to tablet mode

  sony-laptop:
   - Avoid oops on module unload for older laptops

  intel_telemetry:
   - Constify telemetry_core_ops structures

  fujitsu-laptop:
   - Use IS_ENABLED() instead of checking for built-in or module

  asus-laptop:
   - correct error handling in sysfs_acpi_set
   - remove redundant initializers
   - correct error handling in asus_read_brightness()

  fujitsu-laptop:
   - Support radio LED"

* tag 'platform-drivers-x86-v4.7-1' of git://git.infradead.org/users/dvhart/linux-platform-drivers-x86:
  platform/x86: Add PMC Driver for Intel Core SoC
  dell-rbtn: Ignore ACPI notifications if device is suspended
  thinkpad_acpi: save kbdlight state on suspend and restore it on resume
  intel_menlow: reduce code duplication
  asus-wmi: provide access to ALS control
  ideapad-laptop: add a new WMI string for ESC key
  surfacepro3_button: Add a warning when switching to tablet mode
  sony-laptop: Avoid oops on module unload for older laptops
  intel_telemetry: Constify telemetry_core_ops structures
  fujitsu-laptop: Use IS_ENABLED() instead of checking for built-in or module
  asus-laptop: correct error handling in sysfs_acpi_set
  asus-laptop: remove redundant initializers
  asus-laptop: correct error handling in asus_read_brightness()
  fujitsu-laptop: Support radio LED
  • Loading branch information
torvalds committed May 27, 2016
2 parents 2566278 + b740d2e commit 1e8143d
Show file tree
Hide file tree
Showing 18 changed files with 518 additions and 53 deletions.
8 changes: 8 additions & 0 deletions MAINTAINERS
Original file line number Diff line number Diff line change
Expand Up @@ -6096,6 +6096,14 @@ S: Maintained
F: arch/x86/include/asm/intel_telemetry.h
F: drivers/platform/x86/intel_telemetry*

INTEL PMC CORE DRIVER
M: Rajneesh Bhardwaj <[email protected]>
M: Vishwanath Somayaji <[email protected]>
L: [email protected]
S: Maintained
F: arch/x86/include/asm/pmc_core.h
F: drivers/platform/x86/intel_pmc_core*

IOC3 ETHERNET DRIVER
M: Ralf Baechle <[email protected]>
L: [email protected]
Expand Down
2 changes: 1 addition & 1 deletion arch/x86/include/asm/intel_telemetry.h
Original file line number Diff line number Diff line change
Expand Up @@ -99,7 +99,7 @@ struct telemetry_core_ops {
int (*reset_events)(void);
};

int telemetry_set_pltdata(struct telemetry_core_ops *ops,
int telemetry_set_pltdata(const struct telemetry_core_ops *ops,
struct telemetry_plt_config *pltconfig);

int telemetry_clear_pltdata(void);
Expand Down
27 changes: 27 additions & 0 deletions arch/x86/include/asm/pmc_core.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
/*
* Intel Core SoC Power Management Controller Header File
*
* Copyright (c) 2016, Intel Corporation.
* All Rights Reserved.
*
* Authors: Rajneesh Bhardwaj <[email protected]>
* Vishwanath Somayaji <[email protected]>
*
* This program is free software; you can redistribute it and/or modify it
* under the terms and conditions of the GNU General Public License,
* version 2, as published by the Free Software Foundation.
*
* This program is distributed in the hope it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
*/

#ifndef _ASM_PMC_CORE_H
#define _ASM_PMC_CORE_H

/* API to read SLP_S0_RESIDENCY counter */
int intel_pmc_slp_s0_counter_read(u32 *data);

#endif /* _ASM_PMC_CORE_H */
12 changes: 12 additions & 0 deletions drivers/platform/x86/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -846,6 +846,18 @@ config INTEL_IMR

If you are running on a Galileo/Quark say Y here.

config INTEL_PMC_CORE
bool "Intel PMC Core driver"
depends on X86 && PCI
---help---
The Intel Platform Controller Hub for Intel Core SoCs provides access
to Power Management Controller registers via a PCI interface. This
driver can utilize debugging capabilities and supported features as
exposed by the Power Management Controller.

Supported features:
- SLP_S0_RESIDENCY counter.

config IBM_RTL
tristate "Device driver to enable PRTL support"
depends on X86 && PCI
Expand Down
1 change: 1 addition & 0 deletions drivers/platform/x86/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -69,3 +69,4 @@ obj-$(CONFIG_INTEL_PUNIT_IPC) += intel_punit_ipc.o
obj-$(CONFIG_INTEL_TELEMETRY) += intel_telemetry_core.o \
intel_telemetry_pltdrv.o \
intel_telemetry_debugfs.o
obj-$(CONFIG_INTEL_PMC_CORE) += intel_pmc_core.o
15 changes: 8 additions & 7 deletions drivers/platform/x86/asus-laptop.c
Original file line number Diff line number Diff line change
Expand Up @@ -771,12 +771,14 @@ static int asus_read_brightness(struct backlight_device *bd)
{
struct asus_laptop *asus = bl_get_data(bd);
unsigned long long value;
acpi_status rv = AE_OK;
acpi_status rv;

rv = acpi_evaluate_integer(asus->handle, METHOD_BRIGHTNESS_GET,
NULL, &value);
if (ACPI_FAILURE(rv))
if (ACPI_FAILURE(rv)) {
pr_warn("Error reading brightness\n");
return 0;
}

return value;
}
Expand Down Expand Up @@ -865,7 +867,7 @@ static ssize_t infos_show(struct device *dev, struct device_attribute *attr,
int len = 0;
unsigned long long temp;
char buf[16]; /* enough for all info */
acpi_status rv = AE_OK;
acpi_status rv;

/*
* We use the easy way, we don't care of off and count,
Expand Down Expand Up @@ -946,11 +948,10 @@ static ssize_t sysfs_acpi_set(struct asus_laptop *asus,
const char *method)
{
int rv, value;
int out = 0;

rv = parse_arg(buf, count, &value);
if (rv > 0)
out = value ? 1 : 0;
if (rv <= 0)
return rv;

if (write_acpi_int(asus->handle, method, value))
return -ENODEV;
Expand Down Expand Up @@ -1265,7 +1266,7 @@ static DEVICE_ATTR_RO(ls_value);
static int asus_gps_status(struct asus_laptop *asus)
{
unsigned long long status;
acpi_status rv = AE_OK;
acpi_status rv;

rv = acpi_evaluate_integer(asus->handle, METHOD_GPS_STATUS,
NULL, &status);
Expand Down
5 changes: 5 additions & 0 deletions drivers/platform/x86/asus-wmi.c
Original file line number Diff line number Diff line change
Expand Up @@ -114,6 +114,7 @@ MODULE_LICENSE("GPL");
#define ASUS_WMI_DEVID_LED6 0x00020016

/* Backlight and Brightness */
#define ASUS_WMI_DEVID_ALS_ENABLE 0x00050001 /* Ambient Light Sensor */
#define ASUS_WMI_DEVID_BACKLIGHT 0x00050011
#define ASUS_WMI_DEVID_BRIGHTNESS 0x00050012
#define ASUS_WMI_DEVID_KBD_BACKLIGHT 0x00050021
Expand Down Expand Up @@ -1730,6 +1731,7 @@ ASUS_WMI_CREATE_DEVICE_ATTR(touchpad, 0644, ASUS_WMI_DEVID_TOUCHPAD);
ASUS_WMI_CREATE_DEVICE_ATTR(camera, 0644, ASUS_WMI_DEVID_CAMERA);
ASUS_WMI_CREATE_DEVICE_ATTR(cardr, 0644, ASUS_WMI_DEVID_CARDREADER);
ASUS_WMI_CREATE_DEVICE_ATTR(lid_resume, 0644, ASUS_WMI_DEVID_LID_RESUME);
ASUS_WMI_CREATE_DEVICE_ATTR(als_enable, 0644, ASUS_WMI_DEVID_ALS_ENABLE);

static ssize_t store_cpufv(struct device *dev, struct device_attribute *attr,
const char *buf, size_t count)
Expand All @@ -1756,6 +1758,7 @@ static struct attribute *platform_attributes[] = {
&dev_attr_cardr.attr,
&dev_attr_touchpad.attr,
&dev_attr_lid_resume.attr,
&dev_attr_als_enable.attr,
NULL
};

Expand All @@ -1776,6 +1779,8 @@ static umode_t asus_sysfs_is_visible(struct kobject *kobj,
devid = ASUS_WMI_DEVID_TOUCHPAD;
else if (attr == &dev_attr_lid_resume.attr)
devid = ASUS_WMI_DEVID_LID_RESUME;
else if (attr == &dev_attr_als_enable.attr)
devid = ASUS_WMI_DEVID_ALS_ENABLE;

if (devid != -1)
ok = !(asus_wmi_get_devstate_simple(asus, devid) < 0);
Expand Down
56 changes: 56 additions & 0 deletions drivers/platform/x86/dell-rbtn.c
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ struct rbtn_data {
enum rbtn_type type;
struct rfkill *rfkill;
struct input_dev *input_dev;
bool suspended;
};


Expand Down Expand Up @@ -235,9 +236,55 @@ static const struct acpi_device_id rbtn_ids[] = {
{ "", 0 },
};

#ifdef CONFIG_PM_SLEEP
static void ACPI_SYSTEM_XFACE rbtn_clear_suspended_flag(void *context)
{
struct rbtn_data *rbtn_data = context;

rbtn_data->suspended = false;
}

static int rbtn_suspend(struct device *dev)
{
struct acpi_device *device = to_acpi_device(dev);
struct rbtn_data *rbtn_data = acpi_driver_data(device);

rbtn_data->suspended = true;

return 0;
}

static int rbtn_resume(struct device *dev)
{
struct acpi_device *device = to_acpi_device(dev);
struct rbtn_data *rbtn_data = acpi_driver_data(device);
acpi_status status;

/*
* Upon resume, some BIOSes send an ACPI notification thet triggers
* an unwanted input event. In order to ignore it, we use a flag
* that we set at suspend and clear once we have received the extra
* ACPI notification. Since ACPI notifications are delivered
* asynchronously to drivers, we clear the flag from the workqueue
* used to deliver the notifications. This should be enough
* to have the flag cleared only after we received the extra
* notification, if any.
*/
status = acpi_os_execute(OSL_NOTIFY_HANDLER,
rbtn_clear_suspended_flag, rbtn_data);
if (ACPI_FAILURE(status))
rbtn_clear_suspended_flag(rbtn_data);

return 0;
}
#endif

static SIMPLE_DEV_PM_OPS(rbtn_pm_ops, rbtn_suspend, rbtn_resume);

static struct acpi_driver rbtn_driver = {
.name = "dell-rbtn",
.ids = rbtn_ids,
.drv.pm = &rbtn_pm_ops,
.ops = {
.add = rbtn_add,
.remove = rbtn_remove,
Expand Down Expand Up @@ -399,6 +446,15 @@ static void rbtn_notify(struct acpi_device *device, u32 event)
{
struct rbtn_data *rbtn_data = device->driver_data;

/*
* Some BIOSes send a notification at resume.
* Ignore it to prevent unwanted input events.
*/
if (rbtn_data->suspended) {
dev_dbg(&device->dev, "ACPI notification ignored\n");
return;
}

if (event != 0x80) {
dev_info(&device->dev, "Received unknown event (0x%x)\n",
event);
Expand Down
63 changes: 57 additions & 6 deletions drivers/platform/x86/fujitsu-laptop.c
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,7 @@
#include <linux/kfifo.h>
#include <linux/platform_device.h>
#include <linux/slab.h>
#if defined(CONFIG_LEDS_CLASS) || defined(CONFIG_LEDS_CLASS_MODULE)
#if IS_ENABLED(CONFIG_LEDS_CLASS)
#include <linux/leds.h>
#endif
#include <acpi/video.h>
Expand Down Expand Up @@ -100,13 +100,14 @@
/* FUNC interface - responses */
#define UNSUPPORTED_CMD 0x80000000

#if defined(CONFIG_LEDS_CLASS) || defined(CONFIG_LEDS_CLASS_MODULE)
#if IS_ENABLED(CONFIG_LEDS_CLASS)
/* FUNC interface - LED control */
#define FUNC_LED_OFF 0x1
#define FUNC_LED_ON 0x30001
#define KEYBOARD_LAMPS 0x100
#define LOGOLAMP_POWERON 0x2000
#define LOGOLAMP_ALWAYS 0x4000
#define RADIO_LED_ON 0x20
#endif

/* Hotkey details */
Expand Down Expand Up @@ -174,13 +175,14 @@ struct fujitsu_hotkey_t {
int rfkill_state;
int logolamp_registered;
int kblamps_registered;
int radio_led_registered;
};

static struct fujitsu_hotkey_t *fujitsu_hotkey;

static void acpi_fujitsu_hotkey_notify(struct acpi_device *device, u32 event);

#if defined(CONFIG_LEDS_CLASS) || defined(CONFIG_LEDS_CLASS_MODULE)
#if IS_ENABLED(CONFIG_LEDS_CLASS)
static enum led_brightness logolamp_get(struct led_classdev *cdev);
static void logolamp_set(struct led_classdev *cdev,
enum led_brightness brightness);
Expand All @@ -200,6 +202,16 @@ static struct led_classdev kblamps_led = {
.brightness_get = kblamps_get,
.brightness_set = kblamps_set
};

static enum led_brightness radio_led_get(struct led_classdev *cdev);
static void radio_led_set(struct led_classdev *cdev,
enum led_brightness brightness);

static struct led_classdev radio_led = {
.name = "fujitsu::radio_led",
.brightness_get = radio_led_get,
.brightness_set = radio_led_set
};
#endif

#ifdef CONFIG_FUJITSU_LAPTOP_DEBUG
Expand Down Expand Up @@ -249,7 +261,7 @@ static int call_fext_func(int cmd, int arg0, int arg1, int arg2)
return value;
}

#if defined(CONFIG_LEDS_CLASS) || defined(CONFIG_LEDS_CLASS_MODULE)
#if IS_ENABLED(CONFIG_LEDS_CLASS)
/* LED class callbacks */

static void logolamp_set(struct led_classdev *cdev,
Expand All @@ -275,6 +287,15 @@ static void kblamps_set(struct led_classdev *cdev,
call_fext_func(FUNC_LEDS, 0x1, KEYBOARD_LAMPS, FUNC_LED_OFF);
}

static void radio_led_set(struct led_classdev *cdev,
enum led_brightness brightness)
{
if (brightness >= LED_FULL)
call_fext_func(FUNC_RFKILL, 0x5, RADIO_LED_ON, RADIO_LED_ON);
else
call_fext_func(FUNC_RFKILL, 0x5, RADIO_LED_ON, 0x0);
}

static enum led_brightness logolamp_get(struct led_classdev *cdev)
{
enum led_brightness brightness = LED_OFF;
Expand All @@ -299,6 +320,16 @@ static enum led_brightness kblamps_get(struct led_classdev *cdev)

return brightness;
}

static enum led_brightness radio_led_get(struct led_classdev *cdev)
{
enum led_brightness brightness = LED_OFF;

if (call_fext_func(FUNC_RFKILL, 0x4, 0x0, 0x0) & RADIO_LED_ON)
brightness = LED_FULL;

return brightness;
}
#endif

/* Hardware access for LCD brightness control */
Expand Down Expand Up @@ -872,7 +903,7 @@ static int acpi_fujitsu_hotkey_add(struct acpi_device *device)
/* Suspect this is a keymap of the application panel, print it */
pr_info("BTNI: [0x%x]\n", call_fext_func(FUNC_BUTTONS, 0x0, 0x0, 0x0));

#if defined(CONFIG_LEDS_CLASS) || defined(CONFIG_LEDS_CLASS_MODULE)
#if IS_ENABLED(CONFIG_LEDS_CLASS)
if (call_fext_func(FUNC_LEDS, 0x0, 0x0, 0x0) & LOGOLAMP_POWERON) {
result = led_classdev_register(&fujitsu->pf_device->dev,
&logolamp_led);
Expand All @@ -895,6 +926,23 @@ static int acpi_fujitsu_hotkey_add(struct acpi_device *device)
result);
}
}

/*
* BTNI bit 24 seems to indicate the presence of a radio toggle
* button in place of a slide switch, and all such machines appear
* to also have an RF LED. Therefore use bit 24 as an indicator
* that an RF LED is present.
*/
if (call_fext_func(FUNC_BUTTONS, 0x0, 0x0, 0x0) & BIT(24)) {
result = led_classdev_register(&fujitsu->pf_device->dev,
&radio_led);
if (result == 0) {
fujitsu_hotkey->radio_led_registered = 1;
} else {
pr_err("Could not register LED handler for radio LED, error %i\n",
result);
}
}
#endif

return result;
Expand All @@ -915,12 +963,15 @@ static int acpi_fujitsu_hotkey_remove(struct acpi_device *device)
struct fujitsu_hotkey_t *fujitsu_hotkey = acpi_driver_data(device);
struct input_dev *input = fujitsu_hotkey->input;

#if defined(CONFIG_LEDS_CLASS) || defined(CONFIG_LEDS_CLASS_MODULE)
#if IS_ENABLED(CONFIG_LEDS_CLASS)
if (fujitsu_hotkey->logolamp_registered)
led_classdev_unregister(&logolamp_led);

if (fujitsu_hotkey->kblamps_registered)
led_classdev_unregister(&kblamps_led);

if (fujitsu_hotkey->radio_led_registered)
led_classdev_unregister(&radio_led);
#endif

input_unregister_device(input);
Expand Down
Loading

0 comments on commit 1e8143d

Please sign in to comment.