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

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

Merge branch 'for_linus' of git://cavan.codon.org.uk/platform-drivers-x86

Pull x86 platform driver updates from Matthew Garrett:
 "Some significant improvements for the Sony driver on newer machines,
  but other than that mostly just minor fixes and a patch to remove the
  broken rfkill code from the Dell driver."

* 'for_linus' of git://cavan.codon.org.uk/platform-drivers-x86: (35 commits)
  apple-gmux: Fix up the suspend/resume patch
  dell-laptop: Remove rfkill code
  toshiba_acpi: Fix mis-merge
  dell-laptop: Add touchpad led support for Dell V3450
  acer-wmi: add 3 laptops to video backlight vendor mode quirk table
  sony-laptop: add touchpad enable/disable function
  sony-laptop: add missing Fn key combos for 0x100 handlers
  sony-laptop: add support for more WWAN modems
  sony-laptop: new keyboard backlight handle
  sony-laptop: add high speed battery charging function
  sony-laptop: support automatic resume on lid open
  sony-laptop: adjust error handling in finding SNC handles
  sony-laptop: add thermal profiles support
  sony-laptop: support battery care functions
  sony-laptop: additional debug statements
  sony-laptop: improve SNC initialization and acpi notify callback code
  sony-laptop: use kstrtoul to parse sysfs values
  sony-laptop: generalise ACPI calls into SNC functions
  sony-laptop: fix return path when no ACPI buffer is allocated
  sony-laptop: use soft rfkill status stored in hw
  ...
parents af4f8ba3 a2f01a89
Loading
Loading
Loading
Loading
+24 −0
Original line number Diff line number Diff line
@@ -523,6 +523,30 @@ static const struct dmi_system_id video_vendor_dmi_table[] = {
			DMI_MATCH(DMI_PRODUCT_NAME, "TravelMate 4750"),
		},
	},
	{
		.callback = video_set_backlight_video_vendor,
		.ident = "Acer Extensa 5235",
		.matches = {
			DMI_MATCH(DMI_BOARD_VENDOR, "Acer"),
			DMI_MATCH(DMI_PRODUCT_NAME, "Extensa 5235"),
		},
	},
	{
		.callback = video_set_backlight_video_vendor,
		.ident = "Acer TravelMate 5760",
		.matches = {
			DMI_MATCH(DMI_BOARD_VENDOR, "Acer"),
			DMI_MATCH(DMI_PRODUCT_NAME, "TravelMate 5760"),
		},
	},
	{
		.callback = video_set_backlight_video_vendor,
		.ident = "Acer Aspire 5750",
		.matches = {
			DMI_MATCH(DMI_BOARD_VENDOR, "Acer"),
			DMI_MATCH(DMI_PRODUCT_NAME, "Aspire 5750"),
		},
	},
	{}
};

+4 −0
Original line number Diff line number Diff line
@@ -87,6 +87,9 @@ static int gmux_update_status(struct backlight_device *bd)
	struct apple_gmux_data *gmux_data = bl_get_data(bd);
	u32 brightness = bd->props.brightness;

	if (bd->props.state & BL_CORE_SUSPENDED)
		return 0;

	/*
	 * Older gmux versions require writing out lower bytes first then
	 * setting the upper byte to 0 to flush the values. Newer versions
@@ -102,6 +105,7 @@ static int gmux_update_status(struct backlight_device *bd)
}

static const struct backlight_ops gmux_bl_ops = {
	.options = BL_CORE_SUSPENDRESUME,
	.get_brightness = gmux_get_brightness,
	.update_status = gmux_update_status,
};
+32 −276
Original line number Diff line number Diff line
@@ -21,7 +21,6 @@
#include <linux/err.h>
#include <linux/dmi.h>
#include <linux/io.h>
#include <linux/rfkill.h>
#include <linux/power_supply.h>
#include <linux/acpi.h>
#include <linux/mm.h>
@@ -90,11 +89,8 @@ static struct platform_driver platform_driver = {

static struct platform_device *platform_device;
static struct backlight_device *dell_backlight_device;
static struct rfkill *wifi_rfkill;
static struct rfkill *bluetooth_rfkill;
static struct rfkill *wwan_rfkill;

static const struct dmi_system_id __initdata dell_device_table[] = {
static const struct dmi_system_id dell_device_table[] __initconst = {
	{
		.ident = "Dell laptop",
		.matches = {
@@ -119,96 +115,94 @@ static const struct dmi_system_id __initdata dell_device_table[] = {
};
MODULE_DEVICE_TABLE(dmi, dell_device_table);

static struct dmi_system_id __devinitdata dell_blacklist[] = {
	/* Supported by compal-laptop */
	{
		.ident = "Dell Mini 9",
		.matches = {
			DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."),
			DMI_MATCH(DMI_PRODUCT_NAME, "Inspiron 910"),
		},
	},
static struct dmi_system_id __devinitdata dell_quirks[] = {
	{
		.ident = "Dell Mini 10",
		.callback = dmi_matched,
		.ident = "Dell Vostro V130",
		.matches = {
			DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."),
			DMI_MATCH(DMI_PRODUCT_NAME, "Inspiron 1010"),
			DMI_MATCH(DMI_PRODUCT_NAME, "Vostro V130"),
		},
		.driver_data = &quirk_dell_vostro_v130,
	},
	{
		.ident = "Dell Mini 10v",
		.callback = dmi_matched,
		.ident = "Dell Vostro V131",
		.matches = {
			DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."),
			DMI_MATCH(DMI_PRODUCT_NAME, "Inspiron 1011"),
			DMI_MATCH(DMI_PRODUCT_NAME, "Vostro V131"),
		},
		.driver_data = &quirk_dell_vostro_v130,
	},
	{
		.ident = "Dell Mini 1012",
		.callback = dmi_matched,
		.ident = "Dell Vostro 3350",
		.matches = {
			DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."),
			DMI_MATCH(DMI_PRODUCT_NAME, "Inspiron 1012"),
			DMI_MATCH(DMI_PRODUCT_NAME, "Vostro 3350"),
		},
		.driver_data = &quirk_dell_vostro_v130,
	},
	{
		.ident = "Dell Inspiron 11z",
		.callback = dmi_matched,
		.ident = "Dell Vostro 3555",
		.matches = {
			DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."),
			DMI_MATCH(DMI_PRODUCT_NAME, "Inspiron 1110"),
			DMI_MATCH(DMI_PRODUCT_NAME, "Vostro 3555"),
		},
		.driver_data = &quirk_dell_vostro_v130,
	},
	{
		.ident = "Dell Mini 12",
		.callback = dmi_matched,
		.ident = "Dell Inspiron N311z",
		.matches = {
			DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."),
			DMI_MATCH(DMI_PRODUCT_NAME, "Inspiron 1210"),
			DMI_MATCH(DMI_PRODUCT_NAME, "Inspiron N311z"),
		},
		.driver_data = &quirk_dell_vostro_v130,
	},
	{}
};

static struct dmi_system_id __devinitdata dell_quirks[] = {
	{
		.callback = dmi_matched,
		.ident = "Dell Vostro V130",
		.ident = "Dell Inspiron M5110",
		.matches = {
			DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."),
			DMI_MATCH(DMI_PRODUCT_NAME, "Vostro V130"),
			DMI_MATCH(DMI_PRODUCT_NAME, "Inspiron M5110"),
		},
		.driver_data = &quirk_dell_vostro_v130,
	},
	{
		.callback = dmi_matched,
		.ident = "Dell Vostro V131",
		.ident = "Dell Vostro 3360",
		.matches = {
			DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."),
			DMI_MATCH(DMI_PRODUCT_NAME, "Vostro V131"),
			DMI_MATCH(DMI_PRODUCT_NAME, "Vostro 3360"),
		},
		.driver_data = &quirk_dell_vostro_v130,
	},
	{
		.callback = dmi_matched,
		.ident = "Dell Vostro 3555",
		.ident = "Dell Vostro 3460",
		.matches = {
			DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."),
			DMI_MATCH(DMI_PRODUCT_NAME, "Vostro 3555"),
			DMI_MATCH(DMI_PRODUCT_NAME, "Vostro 3460"),
		},
		.driver_data = &quirk_dell_vostro_v130,
	},
	{
		.callback = dmi_matched,
		.ident = "Dell Inspiron N311z",
		.ident = "Dell Vostro 3560",
		.matches = {
			DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."),
			DMI_MATCH(DMI_PRODUCT_NAME, "Inspiron N311z"),
			DMI_MATCH(DMI_PRODUCT_NAME, "Vostro 3560"),
		},
		.driver_data = &quirk_dell_vostro_v130,
	},
	{
		.callback = dmi_matched,
		.ident = "Dell Inspiron M5110",
		.ident = "Dell Vostro 3450",
		.matches = {
			DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."),
			DMI_MATCH(DMI_PRODUCT_NAME, "Inspiron M5110"),
			DMI_MATCH(DMI_PRODUCT_NAME, "Dell System Vostro 3450"),
		},
		.driver_data = &quirk_dell_vostro_v130,
	},
@@ -305,94 +299,6 @@ dell_send_request(struct calling_interface_buffer *buffer, int class,
	return buffer;
}

/* Derived from information in DellWirelessCtl.cpp:
   Class 17, select 11 is radio control. It returns an array of 32-bit values.

   Input byte 0 = 0: Wireless information

   result[0]: return code
   result[1]:
     Bit 0:      Hardware switch supported
     Bit 1:      Wifi locator supported
     Bit 2:      Wifi is supported
     Bit 3:      Bluetooth is supported
     Bit 4:      WWAN is supported
     Bit 5:      Wireless keyboard supported
     Bits 6-7:   Reserved
     Bit 8:      Wifi is installed
     Bit 9:      Bluetooth is installed
     Bit 10:     WWAN is installed
     Bits 11-15: Reserved
     Bit 16:     Hardware switch is on
     Bit 17:     Wifi is blocked
     Bit 18:     Bluetooth is blocked
     Bit 19:     WWAN is blocked
     Bits 20-31: Reserved
   result[2]: NVRAM size in bytes
   result[3]: NVRAM format version number

   Input byte 0 = 2: Wireless switch configuration
   result[0]: return code
   result[1]:
     Bit 0:      Wifi controlled by switch
     Bit 1:      Bluetooth controlled by switch
     Bit 2:      WWAN controlled by switch
     Bits 3-6:   Reserved
     Bit 7:      Wireless switch config locked
     Bit 8:      Wifi locator enabled
     Bits 9-14:  Reserved
     Bit 15:     Wifi locator setting locked
     Bits 16-31: Reserved
*/

static int dell_rfkill_set(void *data, bool blocked)
{
	int disable = blocked ? 1 : 0;
	unsigned long radio = (unsigned long)data;
	int hwswitch_bit = (unsigned long)data - 1;
	int ret = 0;

	get_buffer();
	dell_send_request(buffer, 17, 11);

	/* If the hardware switch controls this radio, and the hardware
	   switch is disabled, don't allow changing the software state */
	if ((hwswitch_state & BIT(hwswitch_bit)) &&
	    !(buffer->output[1] & BIT(16))) {
		ret = -EINVAL;
		goto out;
	}

	buffer->input[0] = (1 | (radio<<8) | (disable << 16));
	dell_send_request(buffer, 17, 11);

out:
	release_buffer();
	return ret;
}

static void dell_rfkill_query(struct rfkill *rfkill, void *data)
{
	int status;
	int bit = (unsigned long)data + 16;
	int hwswitch_bit = (unsigned long)data - 1;

	get_buffer();
	dell_send_request(buffer, 17, 11);
	status = buffer->output[1];
	release_buffer();

	rfkill_set_sw_state(rfkill, !!(status & BIT(bit)));

	if (hwswitch_state & (BIT(hwswitch_bit)))
		rfkill_set_hw_state(rfkill, !(status & BIT(16)));
}

static const struct rfkill_ops dell_rfkill_ops = {
	.set_block = dell_rfkill_set,
	.query = dell_rfkill_query,
};

static struct dentry *dell_laptop_dir;

static int dell_debugfs_show(struct seq_file *s, void *data)
@@ -462,108 +368,6 @@ static const struct file_operations dell_debugfs_fops = {
	.release = single_release,
};

static void dell_update_rfkill(struct work_struct *ignored)
{
	if (wifi_rfkill)
		dell_rfkill_query(wifi_rfkill, (void *)1);
	if (bluetooth_rfkill)
		dell_rfkill_query(bluetooth_rfkill, (void *)2);
	if (wwan_rfkill)
		dell_rfkill_query(wwan_rfkill, (void *)3);
}
static DECLARE_DELAYED_WORK(dell_rfkill_work, dell_update_rfkill);


static int __init dell_setup_rfkill(void)
{
	int status;
	int ret;

	if (dmi_check_system(dell_blacklist)) {
		pr_info("Blacklisted hardware detected - not enabling rfkill\n");
		return 0;
	}

	get_buffer();
	dell_send_request(buffer, 17, 11);
	status = buffer->output[1];
	buffer->input[0] = 0x2;
	dell_send_request(buffer, 17, 11);
	hwswitch_state = buffer->output[1];
	release_buffer();

	if ((status & (1<<2|1<<8)) == (1<<2|1<<8)) {
		wifi_rfkill = rfkill_alloc("dell-wifi", &platform_device->dev,
					   RFKILL_TYPE_WLAN,
					   &dell_rfkill_ops, (void *) 1);
		if (!wifi_rfkill) {
			ret = -ENOMEM;
			goto err_wifi;
		}
		ret = rfkill_register(wifi_rfkill);
		if (ret)
			goto err_wifi;
	}

	if ((status & (1<<3|1<<9)) == (1<<3|1<<9)) {
		bluetooth_rfkill = rfkill_alloc("dell-bluetooth",
						&platform_device->dev,
						RFKILL_TYPE_BLUETOOTH,
						&dell_rfkill_ops, (void *) 2);
		if (!bluetooth_rfkill) {
			ret = -ENOMEM;
			goto err_bluetooth;
		}
		ret = rfkill_register(bluetooth_rfkill);
		if (ret)
			goto err_bluetooth;
	}

	if ((status & (1<<4|1<<10)) == (1<<4|1<<10)) {
		wwan_rfkill = rfkill_alloc("dell-wwan",
					   &platform_device->dev,
					   RFKILL_TYPE_WWAN,
					   &dell_rfkill_ops, (void *) 3);
		if (!wwan_rfkill) {
			ret = -ENOMEM;
			goto err_wwan;
		}
		ret = rfkill_register(wwan_rfkill);
		if (ret)
			goto err_wwan;
	}

	return 0;
err_wwan:
	rfkill_destroy(wwan_rfkill);
	if (bluetooth_rfkill)
		rfkill_unregister(bluetooth_rfkill);
err_bluetooth:
	rfkill_destroy(bluetooth_rfkill);
	if (wifi_rfkill)
		rfkill_unregister(wifi_rfkill);
err_wifi:
	rfkill_destroy(wifi_rfkill);

	return ret;
}

static void dell_cleanup_rfkill(void)
{
	if (wifi_rfkill) {
		rfkill_unregister(wifi_rfkill);
		rfkill_destroy(wifi_rfkill);
	}
	if (bluetooth_rfkill) {
		rfkill_unregister(bluetooth_rfkill);
		rfkill_destroy(bluetooth_rfkill);
	}
	if (wwan_rfkill) {
		rfkill_unregister(wwan_rfkill);
		rfkill_destroy(wwan_rfkill);
	}
}

static int dell_send_intensity(struct backlight_device *bd)
{
	int ret = 0;
@@ -655,30 +459,6 @@ static void touchpad_led_exit(void)
	led_classdev_unregister(&touchpad_led);
}

static bool dell_laptop_i8042_filter(unsigned char data, unsigned char str,
			      struct serio *port)
{
	static bool extended;

	if (str & 0x20)
		return false;

	if (unlikely(data == 0xe0)) {
		extended = true;
		return false;
	} else if (unlikely(extended)) {
		switch (data) {
		case 0x8:
			schedule_delayed_work(&dell_rfkill_work,
					      round_jiffies_relative(HZ));
			break;
		}
		extended = false;
	}

	return false;
}

static int __init dell_init(void)
{
	int max_intensity = 0;
@@ -720,26 +500,10 @@ static int __init dell_init(void)
		goto fail_buffer;
	buffer = page_address(bufferpage);

	ret = dell_setup_rfkill();

	if (ret) {
		pr_warn("Unable to setup rfkill\n");
		goto fail_rfkill;
	}

	ret = i8042_install_filter(dell_laptop_i8042_filter);
	if (ret) {
		pr_warn("Unable to install key filter\n");
		goto fail_filter;
	}

	if (quirks && quirks->touchpad_led)
		touchpad_led_init(&platform_device->dev);

	dell_laptop_dir = debugfs_create_dir("dell_laptop", NULL);
	if (dell_laptop_dir != NULL)
		debugfs_create_file("rfkill", 0444, dell_laptop_dir, NULL,
				    &dell_debugfs_fops);

#ifdef CONFIG_ACPI
	/* In the event of an ACPI backlight being available, don't
@@ -782,11 +546,6 @@ static int __init dell_init(void)
	return 0;

fail_backlight:
	i8042_remove_filter(dell_laptop_i8042_filter);
	cancel_delayed_work_sync(&dell_rfkill_work);
fail_filter:
	dell_cleanup_rfkill();
fail_rfkill:
	free_page((unsigned long)bufferpage);
fail_buffer:
	platform_device_del(platform_device);
@@ -804,10 +563,7 @@ static void __exit dell_exit(void)
	debugfs_remove_recursive(dell_laptop_dir);
	if (quirks && quirks->touchpad_led)
		touchpad_led_exit();
	i8042_remove_filter(dell_laptop_i8042_filter);
	cancel_delayed_work_sync(&dell_rfkill_work);
	backlight_device_unregister(dell_backlight_device);
	dell_cleanup_rfkill();
	if (platform_device) {
		platform_device_unregister(platform_device);
		platform_driver_unregister(&platform_driver);
+21 −13
Original line number Diff line number Diff line
@@ -16,6 +16,8 @@
 * 59 Temple Place Suite 330, Boston, MA 02111-1307, USA.
 */

#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt

#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/init.h>
@@ -34,7 +36,8 @@
#define ACPI_FUJITSU_CLASS "fujitsu"

#define INVERT_TABLET_MODE_BIT      0x01
#define FORCE_TABLET_MODE_IF_UNDOCK 0x02
#define INVERT_DOCK_STATE_BIT       0x02
#define FORCE_TABLET_MODE_IF_UNDOCK 0x04

#define KEYMAP_LEN 16

@@ -161,6 +164,8 @@ static void fujitsu_send_state(void)
	state = fujitsu_read_register(0xdd);

	dock = state & 0x02;
	if (fujitsu.config.quirks & INVERT_DOCK_STATE_BIT)
		dock = !dock;

	if ((fujitsu.config.quirks & FORCE_TABLET_MODE_IF_UNDOCK) && (!dock)) {
		tablet_mode = 1;
@@ -221,9 +226,6 @@ static int __devinit input_fujitsu_setup(struct device *parent,
	input_set_capability(idev, EV_SW, SW_DOCK);
	input_set_capability(idev, EV_SW, SW_TABLET_MODE);

	input_set_capability(idev, EV_SW, SW_DOCK);
	input_set_capability(idev, EV_SW, SW_TABLET_MODE);

	error = input_register_device(idev);
	if (error) {
		input_free_device(idev);
@@ -275,25 +277,31 @@ static irqreturn_t fujitsu_interrupt(int irq, void *dev_id)
	return IRQ_HANDLED;
}

static int __devinit fujitsu_dmi_default(const struct dmi_system_id *dmi)
static void __devinit fujitsu_dmi_common(const struct dmi_system_id *dmi)
{
	printk(KERN_INFO MODULENAME ": %s\n", dmi->ident);
	pr_info("%s\n", dmi->ident);
	memcpy(fujitsu.config.keymap, dmi->driver_data,
			sizeof(fujitsu.config.keymap));
}

static int __devinit fujitsu_dmi_lifebook(const struct dmi_system_id *dmi)
{
	fujitsu_dmi_common(dmi);
	fujitsu.config.quirks |= INVERT_TABLET_MODE_BIT;
	return 1;
}

static int __devinit fujitsu_dmi_stylistic(const struct dmi_system_id *dmi)
{
	fujitsu_dmi_default(dmi);
	fujitsu_dmi_common(dmi);
	fujitsu.config.quirks |= FORCE_TABLET_MODE_IF_UNDOCK;
	fujitsu.config.quirks |= INVERT_TABLET_MODE_BIT;
	fujitsu.config.quirks |= INVERT_DOCK_STATE_BIT;
	return 1;
}

static struct dmi_system_id dmi_ids[] __initconst = {
	{
		.callback = fujitsu_dmi_default,
		.callback = fujitsu_dmi_lifebook,
		.ident = "Fujitsu Siemens P/T Series",
		.matches = {
			DMI_MATCH(DMI_SYS_VENDOR, "FUJITSU"),
@@ -302,7 +310,7 @@ static struct dmi_system_id dmi_ids[] __initconst = {
		.driver_data = keymap_Lifebook_Tseries
	},
	{
		.callback = fujitsu_dmi_default,
		.callback = fujitsu_dmi_lifebook,
		.ident = "Fujitsu Lifebook T Series",
		.matches = {
			DMI_MATCH(DMI_SYS_VENDOR, "FUJITSU"),
@@ -320,7 +328,7 @@ static struct dmi_system_id dmi_ids[] __initconst = {
		.driver_data = keymap_Stylistic_Tseries
	},
	{
		.callback = fujitsu_dmi_default,
		.callback = fujitsu_dmi_lifebook,
		.ident = "Fujitsu LifeBook U810",
		.matches = {
			DMI_MATCH(DMI_SYS_VENDOR, "FUJITSU"),
@@ -347,7 +355,7 @@ static struct dmi_system_id dmi_ids[] __initconst = {
		.driver_data = keymap_Stylistic_ST5xxx
	},
	{
		.callback = fujitsu_dmi_default,
		.callback = fujitsu_dmi_lifebook,
		.ident = "Unknown (using defaults)",
		.matches = {
			DMI_MATCH(DMI_SYS_VENDOR, ""),
@@ -473,6 +481,6 @@ module_exit(fujitsu_module_exit);
MODULE_AUTHOR("Robert Gerlach <khnz@gmx.de>");
MODULE_DESCRIPTION("Fujitsu tablet pc extras driver");
MODULE_LICENSE("GPL");
MODULE_VERSION("2.4");
MODULE_VERSION("2.5");

MODULE_DEVICE_TABLE(acpi, fujitsu_ids);
+1 −1
Original line number Diff line number Diff line
@@ -2,7 +2,7 @@
 * hdaps.c - driver for IBM's Hard Drive Active Protection System
 *
 * Copyright (C) 2005 Robert Love <rml@novell.com>
 * Copyright (C) 2005 Jesper Juhl <jesper.juhl@gmail.com>
 * Copyright (C) 2005 Jesper Juhl <jj@chaosbits.net>
 *
 * The HardDisk Active Protection System (hdaps) is present in IBM ThinkPads
 * starting with the R40, T41, and X40.  It provides a basic two-axis
Loading