Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit a7726f6b authored by Linus Torvalds's avatar Linus Torvalds
Browse files

Merge tag 'platform-drivers-x86-v4.17-1' of git://git.infradead.org/linux-platform-drivers-x86

Pull x86 platform driver updates from Andy Shevchenko:

 - Dell SMBIOS driver fixed against memory leaks.

 - The fujitsu-laptop driver is cleaned up and now supports hotkeys for
   Lifebook U7x7 models. Besides that the typo introduced by one of
   previous clean up series has been fixed.

 - Specific to x86-based laptops HID device now supports
   KEY_ROTATE_LOCK_TOGGLE event which is emitted, for example, by Wacom
   MobileStudio Pro 13.

 - Turbo MAX 3 technology is enabled for the rest of platforms that
   support Hardware-P-States feature which have core priority described
   by ACPI CPPC table.

 - Mellanox on x86 gets better support of I2C bus in use including
   support of hotpluggable ones.

 - Silead touchscreen is enabled on two tablet models, i.e Yours Y8W81
   and I.T.Works TW701.

 - From now on the second fan on Thinkpad P50 is supported.

 - The topstar-laptop driver is reworked to support new models, in
   particular Topstar U931.

* tag 'platform-drivers-x86-v4.17-1' of git://git.infradead.org/linux-platform-drivers-x86: (41 commits)
  platform/x86: thinkpad_acpi: Add 2nd Fan Support for Thinkpad P50
  platform/x86: dell-smbios: Fix memory leaks in build_tokens_sysfs()
  intel-hid: support KEY_ROTATE_LOCK_TOGGLE
  intel-hid: clean up and sort header files
  platform/x86: silead_dmi: Add entry for the Yours Y8W81 tablet
  platform/x86: fujitsu-laptop: Support Lifebook U7x7 hotkeys
  platform/x86: mlx-platform: Add physical bus number auto detection
  platform/mellanox: mlxreg-hotplug: Change input for device create routine
  platform/x86: mlx-platform: Add deffered bus functionality
  platform/x86: mlx-platform: Use define for the channel numbers
  platform/x86: fujitsu-laptop: Revert UNSUPPORTED_CMD back to an int
  platform/x86: Fix dell driver init order
  platform/x86: dell-smbios: Resolve dependency error on ACPI_WMI
  platform/x86: dell-smbios: Resolve dependency error on DCDBAS
  platform/x86: Allow for SMBIOS backend defaults
  platform/x86: dell-smbios: Link all dell-smbios-* modules together
  platform/x86: dell-smbios: Rename dell-smbios source to dell-smbios-base
  platform/x86: dell-smbios: Correct some style warnings
  platform/x86: wmi: Fix misuse of vsprintf extension %pULL
  platform/x86: intel-hid: Reset wakeup capable flag on removal
  ...
parents 1b02dcb9 a986c75a
Loading
Loading
Loading
Loading
+21 −10
Original line number Diff line number Diff line
@@ -93,9 +93,11 @@ struct mlxreg_hotplug_priv_data {
	bool after_probe;
};

static int mlxreg_hotplug_device_create(struct device *dev,
static int mlxreg_hotplug_device_create(struct mlxreg_hotplug_priv_data *priv,
					struct mlxreg_core_data *data)
{
	struct mlxreg_core_hotplug_platform_data *pdata;

	/*
	 * Return if adapter number is negative. It could be in case hotplug
	 * event is not associated with hotplug device.
@@ -103,19 +105,21 @@ static int mlxreg_hotplug_device_create(struct device *dev,
	if (data->hpdev.nr < 0)
		return 0;

	data->hpdev.adapter = i2c_get_adapter(data->hpdev.nr);
	pdata = dev_get_platdata(&priv->pdev->dev);
	data->hpdev.adapter = i2c_get_adapter(data->hpdev.nr +
					      pdata->shift_nr);
	if (!data->hpdev.adapter) {
		dev_err(dev, "Failed to get adapter for bus %d\n",
			data->hpdev.nr);
		dev_err(priv->dev, "Failed to get adapter for bus %d\n",
			data->hpdev.nr + pdata->shift_nr);
		return -EFAULT;
	}

	data->hpdev.client = i2c_new_device(data->hpdev.adapter,
					    data->hpdev.brdinfo);
	if (!data->hpdev.client) {
		dev_err(dev, "Failed to create client %s at bus %d at addr 0x%02x\n",
			data->hpdev.brdinfo->type, data->hpdev.nr,
			data->hpdev.brdinfo->addr);
		dev_err(priv->dev, "Failed to create client %s at bus %d at addr 0x%02x\n",
			data->hpdev.brdinfo->type, data->hpdev.nr +
			pdata->shift_nr, data->hpdev.brdinfo->addr);

		i2c_put_adapter(data->hpdev.adapter);
		data->hpdev.adapter = NULL;
@@ -270,10 +274,10 @@ mlxreg_hotplug_work_helper(struct mlxreg_hotplug_priv_data *priv,
			if (item->inversed)
				mlxreg_hotplug_device_destroy(data);
			else
				mlxreg_hotplug_device_create(priv->dev, data);
				mlxreg_hotplug_device_create(priv, data);
		} else {
			if (item->inversed)
				mlxreg_hotplug_device_create(priv->dev, data);
				mlxreg_hotplug_device_create(priv, data);
			else
				mlxreg_hotplug_device_destroy(data);
		}
@@ -319,7 +323,7 @@ mlxreg_hotplug_health_work_helper(struct mlxreg_hotplug_priv_data *priv,
		if (regval == MLXREG_HOTPLUG_HEALTH_MASK) {
			if ((data->health_cntr++ == MLXREG_HOTPLUG_RST_CNTR) ||
			    !priv->after_probe) {
				mlxreg_hotplug_device_create(priv->dev, data);
				mlxreg_hotplug_device_create(priv, data);
				data->attached = true;
			}
		} else {
@@ -550,6 +554,7 @@ static int mlxreg_hotplug_probe(struct platform_device *pdev)
{
	struct mlxreg_core_hotplug_platform_data *pdata;
	struct mlxreg_hotplug_priv_data *priv;
	struct i2c_adapter *deferred_adap;
	int err;

	pdata = dev_get_platdata(&pdev->dev);
@@ -558,6 +563,12 @@ static int mlxreg_hotplug_probe(struct platform_device *pdev)
		return -EINVAL;
	}

	/* Defer probing if the necessary adapter is not configured yet. */
	deferred_adap = i2c_get_adapter(pdata->deferred_nr);
	if (!deferred_adap)
		return -EPROBE_DEFER;
	i2c_put_adapter(deferred_adap);

	priv = devm_kzalloc(&pdev->dev, sizeof(*priv), GFP_KERNEL);
	if (!priv)
		return -ENOMEM;
+3 −0
Original line number Diff line number Diff line
@@ -757,6 +757,8 @@ config TOPSTAR_LAPTOP
	depends on ACPI
	depends on INPUT
	select INPUT_SPARSEKMAP
	select LEDS_CLASS
	select NEW_LEDS
	---help---
	  This driver adds support for hotkeys found on Topstar laptops.

@@ -1174,6 +1176,7 @@ config INTEL_TELEMETRY

config MLX_PLATFORM
	tristate "Mellanox Technologies platform support"
	depends on I2C && REGMAP
	---help---
	  This option enables system support for the Mellanox Technologies
	  platform. The Mellanox systems provide data center networking
+2 −2
Original line number Diff line number Diff line
@@ -514,7 +514,7 @@ static int build_tokens_sysfs(struct platform_device *dev)
		continue;

loop_fail_create_value:
		kfree(value_name);
		kfree(location_name);
		goto out_unwind_strings;
	}
	smbios_attribute_group.attrs = token_attrs;
@@ -525,7 +525,7 @@ static int build_tokens_sysfs(struct platform_device *dev)
	return 0;

out_unwind_strings:
	for (i = i-1; i > 0; i--) {
	while (i--) {
		kfree(token_location_attrs[i].attr.name);
		kfree(token_value_attrs[i].attr.name);
	}
+106 −93
Original line number Diff line number Diff line
@@ -53,6 +53,7 @@
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/acpi.h>
#include <linux/bitops.h>
#include <linux/dmi.h>
#include <linux/backlight.h>
#include <linux/fb.h>
@@ -61,7 +62,6 @@
#include <linux/kfifo.h>
#include <linux/leds.h>
#include <linux/platform_device.h>
#include <linux/slab.h>
#include <acpi/video.h>

#define FUJITSU_DRIVER_VERSION		"0.6.0"
@@ -76,42 +76,52 @@
#define ACPI_FUJITSU_LAPTOP_DRIVER_NAME	"Fujitsu laptop FUJ02E3 ACPI hotkeys driver"
#define ACPI_FUJITSU_LAPTOP_DEVICE_NAME	"Fujitsu FUJ02E3"

#define ACPI_FUJITSU_NOTIFY_CODE1     0x80
#define ACPI_FUJITSU_NOTIFY_CODE	0x80

/* FUNC interface - command values */
#define FUNC_FLAGS	0x1000
#define FUNC_LEDS	0x1001
#define FUNC_BUTTONS	0x1002
#define FUNC_BACKLIGHT  0x1004
#define FUNC_FLAGS			BIT(12)
#define FUNC_LEDS			(BIT(12) | BIT(0))
#define FUNC_BUTTONS			(BIT(12) | BIT(1))
#define FUNC_BACKLIGHT			(BIT(12) | BIT(2))

/* FUNC interface - responses */
#define UNSUPPORTED_CMD			0x80000000

/* FUNC interface - status flags */
#define FLAG_RFKILL	0x020
#define FLAG_LID	0x100
#define FLAG_DOCK	0x200
#define FLAG_RFKILL			BIT(5)
#define FLAG_LID			BIT(8)
#define FLAG_DOCK			BIT(9)

/* 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
#define ECO_LED	0x10000
#define ECO_LED_ON	0x80000

/* Hotkey details */
#define KEY1_CODE	0x410	/* codes for the keys in the GIRB register */
#define FUNC_LED_OFF			BIT(0)
#define FUNC_LED_ON			(BIT(0) | BIT(16) | BIT(17))
#define LOGOLAMP_POWERON		BIT(13)
#define LOGOLAMP_ALWAYS			BIT(14)
#define KEYBOARD_LAMPS			BIT(8)
#define RADIO_LED_ON			BIT(5)
#define ECO_LED				BIT(16)
#define ECO_LED_ON			BIT(19)

/* FUNC interface - backlight power control */
#define BACKLIGHT_PARAM_POWER		BIT(2)
#define BACKLIGHT_OFF			(BIT(0) | BIT(1))
#define BACKLIGHT_ON			0

/* Scancodes read from the GIRB register */
#define KEY1_CODE			0x410
#define KEY2_CODE			0x411
#define KEY3_CODE			0x412
#define KEY4_CODE			0x413
#define KEY5_CODE			0x420

/* Hotkey ringbuffer limits */
#define MAX_HOTKEY_RINGBUFFER_SIZE	100
#define RINGBUFFERSIZE			40

/* Module parameters */
static int use_alt_lcd_levels = -1;
static bool disable_brightness_adjust;

/* Device controlling the backlight and associated keys */
struct fujitsu_bl {
	struct input_dev *input;
@@ -122,8 +132,6 @@ struct fujitsu_bl {
};

static struct fujitsu_bl *fujitsu_bl;
static int use_alt_lcd_levels = -1;
static bool disable_brightness_adjust;

/* Device used to access hotkeys and other features on the laptop */
struct fujitsu_laptop {
@@ -256,9 +264,11 @@ static int bl_update_status(struct backlight_device *b)

	if (fext) {
		if (b->props.power == FB_BLANK_POWERDOWN)
			call_fext_func(fext, FUNC_BACKLIGHT, 0x1, 0x4, 0x3);
			call_fext_func(fext, FUNC_BACKLIGHT, 0x1,
				       BACKLIGHT_PARAM_POWER, BACKLIGHT_OFF);
		else
			call_fext_func(fext, FUNC_BACKLIGHT, 0x1, 0x4, 0x0);
			call_fext_func(fext, FUNC_BACKLIGHT, 0x1,
				       BACKLIGHT_PARAM_POWER, BACKLIGHT_ON);
	}

	return set_lcd_level(device, b->props.brightness);
@@ -385,7 +395,7 @@ static int fujitsu_backlight_register(struct acpi_device *device)
static int acpi_fujitsu_bl_add(struct acpi_device *device)
{
	struct fujitsu_bl *priv;
	int error;
	int ret;

	if (acpi_video_get_backlight_type() != acpi_backlight_vendor)
		return -ENODEV;
@@ -399,10 +409,6 @@ static int acpi_fujitsu_bl_add(struct acpi_device *device)
	strcpy(acpi_device_class(device), ACPI_FUJITSU_CLASS);
	device->driver_data = priv;

	error = acpi_fujitsu_bl_input_setup(device);
	if (error)
		return error;

	pr_info("ACPI: %s [%s]\n",
		acpi_device_name(device), acpi_device_bid(device));

@@ -410,11 +416,11 @@ static int acpi_fujitsu_bl_add(struct acpi_device *device)
		priv->max_brightness = FUJITSU_LCD_N_LEVELS;
	get_lcd_level(device);

	error = fujitsu_backlight_register(device);
	if (error)
		return error;
	ret = acpi_fujitsu_bl_input_setup(device);
	if (ret)
		return ret;

	return 0;
	return fujitsu_backlight_register(device);
}

/* Brightness notify */
@@ -424,7 +430,7 @@ static void acpi_fujitsu_bl_notify(struct acpi_device *device, u32 event)
	struct fujitsu_bl *priv = acpi_driver_data(device);
	int oldb, newb;

	if (event != ACPI_FUJITSU_NOTIFY_CODE1) {
	if (event != ACPI_FUJITSU_NOTIFY_CODE) {
		acpi_handle_info(device->handle, "unsupported event [0x%x]\n",
				 event);
		sparse_keymap_report_event(priv->input, -1, 1, true);
@@ -455,7 +461,9 @@ static const struct key_entry keymap_default[] = {
	{ KE_KEY, KEY3_CODE, { KEY_PROG3 } },
	{ KE_KEY, KEY4_CODE, { KEY_PROG4 } },
	{ KE_KEY, KEY5_CODE, { KEY_RFKILL } },
	{ KE_KEY, BIT(5),    { KEY_RFKILL } },
	{ KE_KEY, BIT(26),   { KEY_TOUCHPAD_TOGGLE } },
	{ KE_KEY, BIT(29),   { KEY_MICMUTE } },
	{ KE_END, 0 }
};

@@ -693,7 +701,7 @@ static int acpi_fujitsu_laptop_leds_register(struct acpi_device *device)
{
	struct fujitsu_laptop *priv = acpi_driver_data(device);
	struct led_classdev *led;
	int result;
	int ret;

	if (call_fext_func(device,
			   FUNC_LEDS, 0x0, 0x0, 0x0) & LOGOLAMP_POWERON) {
@@ -704,9 +712,9 @@ static int acpi_fujitsu_laptop_leds_register(struct acpi_device *device)
		led->name = "fujitsu::logolamp";
		led->brightness_set_blocking = logolamp_set;
		led->brightness_get = logolamp_get;
		result = devm_led_classdev_register(&device->dev, led);
		if (result)
			return result;
		ret = devm_led_classdev_register(&device->dev, led);
		if (ret)
			return ret;
	}

	if ((call_fext_func(device,
@@ -719,9 +727,9 @@ static int acpi_fujitsu_laptop_leds_register(struct acpi_device *device)
		led->name = "fujitsu::kblamps";
		led->brightness_set_blocking = kblamps_set;
		led->brightness_get = kblamps_get;
		result = devm_led_classdev_register(&device->dev, led);
		if (result)
			return result;
		ret = devm_led_classdev_register(&device->dev, led);
		if (ret)
			return ret;
	}

	/*
@@ -742,9 +750,9 @@ static int acpi_fujitsu_laptop_leds_register(struct acpi_device *device)
		led->brightness_set_blocking = radio_led_set;
		led->brightness_get = radio_led_get;
		led->default_trigger = "rfkill-any";
		result = devm_led_classdev_register(&device->dev, led);
		if (result)
			return result;
		ret = devm_led_classdev_register(&device->dev, led);
		if (ret)
			return ret;
	}

	/* Support for eco led is not always signaled in bit corresponding
@@ -762,9 +770,9 @@ static int acpi_fujitsu_laptop_leds_register(struct acpi_device *device)
		led->name = "fujitsu::eco_led";
		led->brightness_set_blocking = eco_led_set;
		led->brightness_get = eco_led_get;
		result = devm_led_classdev_register(&device->dev, led);
		if (result)
			return result;
		ret = devm_led_classdev_register(&device->dev, led);
		if (ret)
			return ret;
	}

	return 0;
@@ -773,8 +781,7 @@ static int acpi_fujitsu_laptop_leds_register(struct acpi_device *device)
static int acpi_fujitsu_laptop_add(struct acpi_device *device)
{
	struct fujitsu_laptop *priv;
	int error;
	int i;
	int ret, i = 0;

	priv = devm_kzalloc(&device->dev, sizeof(*priv), GFP_KERNEL);
	if (!priv)
@@ -789,23 +796,16 @@ static int acpi_fujitsu_laptop_add(struct acpi_device *device)

	/* kfifo */
	spin_lock_init(&priv->fifo_lock);
	error = kfifo_alloc(&priv->fifo, RINGBUFFERSIZE * sizeof(int),
	ret = kfifo_alloc(&priv->fifo, RINGBUFFERSIZE * sizeof(int),
			  GFP_KERNEL);
	if (error) {
		pr_err("kfifo_alloc failed\n");
		goto err_stop;
	}

	error = acpi_fujitsu_laptop_input_setup(device);
	if (error)
		goto err_free_fifo;
	if (ret)
		return ret;

	pr_info("ACPI: %s [%s]\n",
		acpi_device_name(device), acpi_device_bid(device));

	i = 0;
	while (call_fext_func(device, FUNC_BUTTONS, 0x1, 0x0, 0x0) != 0
		&& (i++) < MAX_HOTKEY_RINGBUFFER_SIZE)
	while (call_fext_func(device, FUNC_BUTTONS, 0x1, 0x0, 0x0) != 0 &&
	       i++ < MAX_HOTKEY_RINGBUFFER_SIZE)
		; /* No action, result is discarded */
	acpi_handle_debug(device->handle, "Discarded %i ringbuffer entries\n",
			  i);
@@ -829,26 +829,31 @@ static int acpi_fujitsu_laptop_add(struct acpi_device *device)
	/* Sync backlight power status */
	if (fujitsu_bl && fujitsu_bl->bl_device &&
	    acpi_video_get_backlight_type() == acpi_backlight_vendor) {
		if (call_fext_func(fext, FUNC_BACKLIGHT, 0x2, 0x4, 0x0) == 3)
		if (call_fext_func(fext, FUNC_BACKLIGHT, 0x2,
				   BACKLIGHT_PARAM_POWER, 0x0) == BACKLIGHT_OFF)
			fujitsu_bl->bl_device->props.power = FB_BLANK_POWERDOWN;
		else
			fujitsu_bl->bl_device->props.power = FB_BLANK_UNBLANK;
	}

	error = acpi_fujitsu_laptop_leds_register(device);
	if (error)
	ret = acpi_fujitsu_laptop_input_setup(device);
	if (ret)
		goto err_free_fifo;

	ret = acpi_fujitsu_laptop_leds_register(device);
	if (ret)
		goto err_free_fifo;

	error = fujitsu_laptop_platform_add(device);
	if (error)
	ret = fujitsu_laptop_platform_add(device);
	if (ret)
		goto err_free_fifo;

	return 0;

err_free_fifo:
	kfifo_free(&priv->fifo);
err_stop:
	return error;

	return ret;
}

static int acpi_fujitsu_laptop_remove(struct acpi_device *device)
@@ -865,11 +870,11 @@ static int acpi_fujitsu_laptop_remove(struct acpi_device *device)
static void acpi_fujitsu_laptop_press(struct acpi_device *device, int scancode)
{
	struct fujitsu_laptop *priv = acpi_driver_data(device);
	int status;
	int ret;

	status = kfifo_in_locked(&priv->fifo, (unsigned char *)&scancode,
	ret = kfifo_in_locked(&priv->fifo, (unsigned char *)&scancode,
			      sizeof(scancode), &priv->fifo_lock);
	if (status != sizeof(scancode)) {
	if (ret != sizeof(scancode)) {
		dev_info(&priv->input->dev, "Could not push scancode [0x%x]\n",
			 scancode);
		return;
@@ -882,13 +887,12 @@ static void acpi_fujitsu_laptop_press(struct acpi_device *device, int scancode)
static void acpi_fujitsu_laptop_release(struct acpi_device *device)
{
	struct fujitsu_laptop *priv = acpi_driver_data(device);
	int scancode, status;
	int scancode, ret;

	while (true) {
		status = kfifo_out_locked(&priv->fifo,
					  (unsigned char *)&scancode,
		ret = kfifo_out_locked(&priv->fifo, (unsigned char *)&scancode,
				       sizeof(scancode), &priv->fifo_lock);
		if (status != sizeof(scancode))
		if (ret != sizeof(scancode))
			return;
		sparse_keymap_report_event(priv->input, scancode, 0, false);
		dev_dbg(&priv->input->dev,
@@ -899,10 +903,10 @@ static void acpi_fujitsu_laptop_release(struct acpi_device *device)
static void acpi_fujitsu_laptop_notify(struct acpi_device *device, u32 event)
{
	struct fujitsu_laptop *priv = acpi_driver_data(device);
	int scancode, i = 0;
	int scancode, i = 0, ret;
	unsigned int irb;

	if (event != ACPI_FUJITSU_NOTIFY_CODE1) {
	if (event != ACPI_FUJITSU_NOTIFY_CODE) {
		acpi_handle_info(device->handle, "Unsupported event [0x%x]\n",
				 event);
		sparse_keymap_report_event(priv->input, -1, 1, true);
@@ -930,9 +934,18 @@ static void acpi_fujitsu_laptop_notify(struct acpi_device *device, u32 event)
	 * E736/E746/E756), the touchpad toggle hotkey (Fn+F4) is
	 * handled in software; its state is queried using FUNC_FLAGS
	 */
	if ((priv->flags_supported & BIT(26)) &&
	    (call_fext_func(device, FUNC_FLAGS, 0x1, 0x0, 0x0) & BIT(26)))
		sparse_keymap_report_event(priv->input, BIT(26), 1, true);
	if (priv->flags_supported & (BIT(5) | BIT(26) | BIT(29))) {
		ret = call_fext_func(device, FUNC_FLAGS, 0x1, 0x0, 0x0);
		if (ret & BIT(5))
			sparse_keymap_report_event(priv->input,
						   BIT(5), 1, true);
		if (ret & BIT(26))
			sparse_keymap_report_event(priv->input,
						   BIT(26), 1, true);
		if (ret & BIT(29))
			sparse_keymap_report_event(priv->input,
						   BIT(29), 1, true);
	}
}

/* Initialization */
+2 −2
Original line number Diff line number Diff line
@@ -19,12 +19,12 @@
static int temp_limits[3] = { 55000, 60000, 65000 };
module_param_array(temp_limits, int, NULL, 0444);
MODULE_PARM_DESC(temp_limits,
		 "Milli-celcius values above which the fan speed increases");
		 "Millicelsius values above which the fan speed increases");

static int hysteresis = 3000;
module_param(hysteresis, int, 0444);
MODULE_PARM_DESC(hysteresis,
		 "Hysteresis in milli-celcius before lowering the fan speed");
		 "Hysteresis in millicelsius before lowering the fan speed");

static int speed_on_ac = 2;
module_param(speed_on_ac, int, 0444);
Loading