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

* 'for_linus' of git://cavan.codon.org.uk/platform-drivers-x86: (45 commits)
  acer-wmi: replaced the hard coded bitmap by the communication devices bitmap from SMBIOS
  acer-wmi: check the existence of internal wireless device when set capability
  acer-wmi: add ACER_WMID_v2 interface flag to represent new notebooks
  sony-laptop:irq: Remove IRQF_DISABLED
  asus-laptop: Add rfkill support for Pegatron Lucid tablet
  asus-laptop: pega_accel - Report accelerometer orientation change through udev
  asus-laptop: fix module description
  asus-laptop: hide leds on Pegatron Lucid
  asus-laptop: Pegatron Lucid accelerometer
  asus-laptop: allow boot time control of Pegatron ALS sensor
  Platform: samsung_laptop: add support for X520 machines.
  platform: samsung_laptop: add dmi information for Samsung R700 laptops
  hp_accel: Add axis-mapping for HP ProBook / EliteBook
  hp_accel: Add a new PNP id
  WMI: properly cleanup devices to avoid crashes
  ideapad: remove sysfs node for cfg
  ideapad: add debugfs support
  ideapad: add event for Novo key
  ideapad: change parameter of ideapad_sync_rfk_state
  ideapad: define vpc commands
  ...
This commit is contained in:
Linus Torvalds
2011-10-31 16:10:33 -07:00
17 changed files with 1454 additions and 647 deletions
+10 -7
View File
@@ -61,15 +61,18 @@ config ASUS_LAPTOP
depends on INPUT
depends on RFKILL || RFKILL = n
select INPUT_SPARSEKMAP
select INPUT_POLLDEV
---help---
This is the new Linux driver for Asus laptops. It may also support some
MEDION, JVC or VICTOR laptops. It makes all the extra buttons generate
standard ACPI events and input events. It also adds
support for video output switching, LCD backlight control, Bluetooth and
Wlan control, and most importantly, allows you to blink those fancy LEDs.
This is a driver for Asus laptops, Lenovo SL and the Pegatron
Lucid tablet. It may also support some MEDION, JVC or VICTOR
laptops. It makes all the extra buttons generate standard
ACPI events and input events, and on the Lucid the built-in
accelerometer appears as an input device. It also adds
support for video output switching, LCD backlight control,
Bluetooth and Wlan control, and most importantly, allows you
to blink those fancy LEDs.
For more information and a userspace daemon for handling the extra
buttons see <http://acpi4asus.sf.net>.
For more information see <http://acpi4asus.sf.net>.
If you have an ACPI-compatible ASUS laptop, say Y or M here.
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
+3 -1
View File
@@ -453,7 +453,9 @@ static enum led_brightness kbd_led_get(struct led_classdev *led_cdev)
static void asus_wmi_led_exit(struct asus_wmi *asus)
{
if (asus->tpd_led.dev)
if (!IS_ERR_OR_NULL(asus->kbd_led.dev))
led_classdev_unregister(&asus->kbd_led);
if (!IS_ERR_OR_NULL(asus->tpd_led.dev))
led_classdev_unregister(&asus->tpd_led);
if (asus->led_workqueue)
destroy_workqueue(asus->led_workqueue);
+84
View File
@@ -60,6 +60,22 @@ struct calling_interface_structure {
struct calling_interface_token tokens[];
} __packed;
struct quirk_entry {
u8 touchpad_led;
};
static struct quirk_entry *quirks;
static struct quirk_entry quirk_dell_vostro_v130 = {
.touchpad_led = 1,
};
static int dmi_matched(const struct dmi_system_id *dmi)
{
quirks = dmi->driver_data;
return 1;
}
static int da_command_address;
static int da_command_code;
static int da_num_tokens;
@@ -149,6 +165,27 @@ static struct dmi_system_id __devinitdata dell_blacklist[] = {
{}
};
static struct dmi_system_id __devinitdata dell_quirks[] = {
{
.callback = dmi_matched,
.ident = "Dell Vostro V130",
.matches = {
DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."),
DMI_MATCH(DMI_PRODUCT_NAME, "Vostro V130"),
},
.driver_data = &quirk_dell_vostro_v130,
},
{
.callback = dmi_matched,
.ident = "Dell Vostro V131",
.matches = {
DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."),
DMI_MATCH(DMI_PRODUCT_NAME, "Vostro V131"),
},
.driver_data = &quirk_dell_vostro_v130,
},
};
static struct calling_interface_buffer *buffer;
static struct page *bufferpage;
static DEFINE_MUTEX(buffer_mutex);
@@ -552,6 +589,44 @@ static const struct backlight_ops dell_ops = {
.update_status = dell_send_intensity,
};
static void touchpad_led_on()
{
int command = 0x97;
char data = 1;
i8042_command(&data, command | 1 << 12);
}
static void touchpad_led_off()
{
int command = 0x97;
char data = 2;
i8042_command(&data, command | 1 << 12);
}
static void touchpad_led_set(struct led_classdev *led_cdev,
enum led_brightness value)
{
if (value > 0)
touchpad_led_on();
else
touchpad_led_off();
}
static struct led_classdev touchpad_led = {
.name = "dell-laptop::touchpad",
.brightness_set = touchpad_led_set,
};
static int __devinit touchpad_led_init(struct device *dev)
{
return led_classdev_register(dev, &touchpad_led);
}
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)
{
@@ -584,6 +659,10 @@ static int __init dell_init(void)
if (!dmi_check_system(dell_device_table))
return -ENODEV;
quirks = NULL;
/* find if this machine support other functions */
dmi_check_system(dell_quirks);
dmi_walk(find_tokens, NULL);
if (!da_tokens) {
@@ -626,6 +705,9 @@ static int __init dell_init(void)
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,
@@ -692,6 +774,8 @@ fail_platform_driver:
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);
+1 -1
View File
@@ -568,7 +568,7 @@ static int eeepc_led_init(struct eeepc_laptop *eeepc)
static void eeepc_led_exit(struct eeepc_laptop *eeepc)
{
if (eeepc->tpd_led.dev)
if (!IS_ERR_OR_NULL(eeepc->tpd_led.dev))
led_classdev_unregister(&eeepc->tpd_led);
if (eeepc->led_workqueue)
destroy_workqueue(eeepc->led_workqueue);
+5
View File
@@ -76,6 +76,7 @@ static inline void delayed_sysfs_set(struct led_classdev *led_cdev,
/* For automatic insertion of the module */
static struct acpi_device_id lis3lv02d_device_ids[] = {
{"HPQ0004", 0}, /* HP Mobile Data Protection System PNP */
{"HPQ6000", 0}, /* HP Mobile Data Protection System PNP */
{"", 0},
};
MODULE_DEVICE_TABLE(acpi, lis3lv02d_device_ids);
@@ -228,6 +229,10 @@ static struct dmi_system_id lis3lv02d_dmi_ids[] = {
AXIS_DMI_MATCH("HPB522x", "HP ProBook 522", xy_swap),
AXIS_DMI_MATCH("HPB532x", "HP ProBook 532", y_inverted),
AXIS_DMI_MATCH("Mini510x", "HP Mini 510", xy_rotated_left_usd),
AXIS_DMI_MATCH("HPB63xx", "HP ProBook 63", xy_swap),
AXIS_DMI_MATCH("HPB64xx", "HP ProBook 64", xy_swap),
AXIS_DMI_MATCH("HPB64xx", "HP EliteBook 84", xy_swap),
AXIS_DMI_MATCH("HPB65xx", "HP ProBook 65", x_inverted),
{ NULL, }
/* Laptop models without axis info (yet):
* "NC6910" "HP Compaq 6910"
+217 -34
View File
@@ -34,6 +34,8 @@
#include <linux/input/sparse-keymap.h>
#include <linux/backlight.h>
#include <linux/fb.h>
#include <linux/debugfs.h>
#include <linux/seq_file.h>
#define IDEAPAD_RFKILL_DEV_NUM (3)
@@ -42,15 +44,41 @@
#define CFG_WIFI_BIT (18)
#define CFG_CAMERA_BIT (19)
enum {
VPCCMD_R_VPC1 = 0x10,
VPCCMD_R_BL_MAX,
VPCCMD_R_BL,
VPCCMD_W_BL,
VPCCMD_R_WIFI,
VPCCMD_W_WIFI,
VPCCMD_R_BT,
VPCCMD_W_BT,
VPCCMD_R_BL_POWER,
VPCCMD_R_NOVO,
VPCCMD_R_VPC2,
VPCCMD_R_TOUCHPAD,
VPCCMD_W_TOUCHPAD,
VPCCMD_R_CAMERA,
VPCCMD_W_CAMERA,
VPCCMD_R_3G,
VPCCMD_W_3G,
VPCCMD_R_ODD, /* 0x21 */
VPCCMD_R_RF = 0x23,
VPCCMD_W_RF,
VPCCMD_W_BL_POWER = 0x33,
};
struct ideapad_private {
struct rfkill *rfk[IDEAPAD_RFKILL_DEV_NUM];
struct platform_device *platform_device;
struct input_dev *inputdev;
struct backlight_device *blightdev;
struct dentry *debug;
unsigned long cfg;
};
static acpi_handle ideapad_handle;
static struct ideapad_private *ideapad_priv;
static bool no_bt_rfkill;
module_param(no_bt_rfkill, bool, 0444);
MODULE_PARM_DESC(no_bt_rfkill, "No rfkill for bluetooth.");
@@ -163,6 +191,146 @@ static int write_ec_cmd(acpi_handle handle, int cmd, unsigned long data)
return -1;
}
/*
* debugfs
*/
#define DEBUGFS_EVENT_LEN (4096)
static int debugfs_status_show(struct seq_file *s, void *data)
{
unsigned long value;
if (!read_ec_data(ideapad_handle, VPCCMD_R_BL_MAX, &value))
seq_printf(s, "Backlight max:\t%lu\n", value);
if (!read_ec_data(ideapad_handle, VPCCMD_R_BL, &value))
seq_printf(s, "Backlight now:\t%lu\n", value);
if (!read_ec_data(ideapad_handle, VPCCMD_R_BL_POWER, &value))
seq_printf(s, "BL power value:\t%s\n", value ? "On" : "Off");
seq_printf(s, "=====================\n");
if (!read_ec_data(ideapad_handle, VPCCMD_R_RF, &value))
seq_printf(s, "Radio status:\t%s(%lu)\n",
value ? "On" : "Off", value);
if (!read_ec_data(ideapad_handle, VPCCMD_R_WIFI, &value))
seq_printf(s, "Wifi status:\t%s(%lu)\n",
value ? "On" : "Off", value);
if (!read_ec_data(ideapad_handle, VPCCMD_R_BT, &value))
seq_printf(s, "BT status:\t%s(%lu)\n",
value ? "On" : "Off", value);
if (!read_ec_data(ideapad_handle, VPCCMD_R_3G, &value))
seq_printf(s, "3G status:\t%s(%lu)\n",
value ? "On" : "Off", value);
seq_printf(s, "=====================\n");
if (!read_ec_data(ideapad_handle, VPCCMD_R_TOUCHPAD, &value))
seq_printf(s, "Touchpad status:%s(%lu)\n",
value ? "On" : "Off", value);
if (!read_ec_data(ideapad_handle, VPCCMD_R_CAMERA, &value))
seq_printf(s, "Camera status:\t%s(%lu)\n",
value ? "On" : "Off", value);
return 0;
}
static int debugfs_status_open(struct inode *inode, struct file *file)
{
return single_open(file, debugfs_status_show, NULL);
}
static const struct file_operations debugfs_status_fops = {
.owner = THIS_MODULE,
.open = debugfs_status_open,
.read = seq_read,
.llseek = seq_lseek,
.release = single_release,
};
static int debugfs_cfg_show(struct seq_file *s, void *data)
{
if (!ideapad_priv) {
seq_printf(s, "cfg: N/A\n");
} else {
seq_printf(s, "cfg: 0x%.8lX\n\nCapability: ",
ideapad_priv->cfg);
if (test_bit(CFG_BT_BIT, &ideapad_priv->cfg))
seq_printf(s, "Bluetooth ");
if (test_bit(CFG_3G_BIT, &ideapad_priv->cfg))
seq_printf(s, "3G ");
if (test_bit(CFG_WIFI_BIT, &ideapad_priv->cfg))
seq_printf(s, "Wireless ");
if (test_bit(CFG_CAMERA_BIT, &ideapad_priv->cfg))
seq_printf(s, "Camera ");
seq_printf(s, "\nGraphic: ");
switch ((ideapad_priv->cfg)&0x700) {
case 0x100:
seq_printf(s, "Intel");
break;
case 0x200:
seq_printf(s, "ATI");
break;
case 0x300:
seq_printf(s, "Nvidia");
break;
case 0x400:
seq_printf(s, "Intel and ATI");
break;
case 0x500:
seq_printf(s, "Intel and Nvidia");
break;
}
seq_printf(s, "\n");
}
return 0;
}
static int debugfs_cfg_open(struct inode *inode, struct file *file)
{
return single_open(file, debugfs_cfg_show, NULL);
}
static const struct file_operations debugfs_cfg_fops = {
.owner = THIS_MODULE,
.open = debugfs_cfg_open,
.read = seq_read,
.llseek = seq_lseek,
.release = single_release,
};
static int __devinit ideapad_debugfs_init(struct ideapad_private *priv)
{
struct dentry *node;
priv->debug = debugfs_create_dir("ideapad", NULL);
if (priv->debug == NULL) {
pr_err("failed to create debugfs directory");
goto errout;
}
node = debugfs_create_file("cfg", S_IRUGO, priv->debug, NULL,
&debugfs_cfg_fops);
if (!node) {
pr_err("failed to create cfg in debugfs");
goto errout;
}
node = debugfs_create_file("status", S_IRUGO, priv->debug, NULL,
&debugfs_status_fops);
if (!node) {
pr_err("failed to create event in debugfs");
goto errout;
}
return 0;
errout:
return -ENOMEM;
}
static void ideapad_debugfs_exit(struct ideapad_private *priv)
{
debugfs_remove_recursive(priv->debug);
priv->debug = NULL;
}
/*
* sysfs
*/
@@ -172,7 +340,7 @@ static ssize_t show_ideapad_cam(struct device *dev,
{
unsigned long result;
if (read_ec_data(ideapad_handle, 0x1D, &result))
if (read_ec_data(ideapad_handle, VPCCMD_R_CAMERA, &result))
return sprintf(buf, "-1\n");
return sprintf(buf, "%lu\n", result);
}
@@ -187,7 +355,7 @@ static ssize_t store_ideapad_cam(struct device *dev,
return 0;
if (sscanf(buf, "%i", &state) != 1)
return -EINVAL;
ret = write_ec_cmd(ideapad_handle, 0x1E, state);
ret = write_ec_cmd(ideapad_handle, VPCCMD_W_CAMERA, state);
if (ret < 0)
return ret;
return count;
@@ -195,20 +363,8 @@ static ssize_t store_ideapad_cam(struct device *dev,
static DEVICE_ATTR(camera_power, 0644, show_ideapad_cam, store_ideapad_cam);
static ssize_t show_ideapad_cfg(struct device *dev,
struct device_attribute *attr,
char *buf)
{
struct ideapad_private *priv = dev_get_drvdata(dev);
return sprintf(buf, "0x%.8lX\n", priv->cfg);
}
static DEVICE_ATTR(cfg, 0444, show_ideapad_cfg, NULL);
static struct attribute *ideapad_attributes[] = {
&dev_attr_camera_power.attr,
&dev_attr_cfg.attr,
NULL
};
@@ -244,9 +400,9 @@ struct ideapad_rfk_data {
};
const struct ideapad_rfk_data ideapad_rfk_data[] = {
{ "ideapad_wlan", CFG_WIFI_BIT, 0x15, RFKILL_TYPE_WLAN },
{ "ideapad_bluetooth", CFG_BT_BIT, 0x17, RFKILL_TYPE_BLUETOOTH },
{ "ideapad_3g", CFG_3G_BIT, 0x20, RFKILL_TYPE_WWAN },
{ "ideapad_wlan", CFG_WIFI_BIT, VPCCMD_W_WIFI, RFKILL_TYPE_WLAN },
{ "ideapad_bluetooth", CFG_BT_BIT, VPCCMD_W_BT, RFKILL_TYPE_BLUETOOTH },
{ "ideapad_3g", CFG_3G_BIT, VPCCMD_W_3G, RFKILL_TYPE_WWAN },
};
static int ideapad_rfk_set(void *data, bool blocked)
@@ -260,13 +416,12 @@ static struct rfkill_ops ideapad_rfk_ops = {
.set_block = ideapad_rfk_set,
};
static void ideapad_sync_rfk_state(struct acpi_device *adevice)
static void ideapad_sync_rfk_state(struct ideapad_private *priv)
{
struct ideapad_private *priv = dev_get_drvdata(&adevice->dev);
unsigned long hw_blocked;
int i;
if (read_ec_data(ideapad_handle, 0x23, &hw_blocked))
if (read_ec_data(ideapad_handle, VPCCMD_R_RF, &hw_blocked))
return;
hw_blocked = !hw_blocked;
@@ -363,8 +518,10 @@ static void ideapad_platform_exit(struct ideapad_private *priv)
* input device
*/
static const struct key_entry ideapad_keymap[] = {
{ KE_KEY, 0x06, { KEY_SWITCHVIDEOMODE } },
{ KE_KEY, 0x0D, { KEY_WLAN } },
{ KE_KEY, 6, { KEY_SWITCHVIDEOMODE } },
{ KE_KEY, 13, { KEY_WLAN } },
{ KE_KEY, 16, { KEY_PROG1 } },
{ KE_KEY, 17, { KEY_PROG2 } },
{ KE_END, 0 },
};
@@ -419,6 +576,18 @@ static void ideapad_input_report(struct ideapad_private *priv,
sparse_keymap_report_event(priv->inputdev, scancode, 1, true);
}
static void ideapad_input_novokey(struct ideapad_private *priv)
{
unsigned long long_pressed;
if (read_ec_data(ideapad_handle, VPCCMD_R_NOVO, &long_pressed))
return;
if (long_pressed)
ideapad_input_report(priv, 17);
else
ideapad_input_report(priv, 16);
}
/*
* backlight
*/
@@ -426,16 +595,17 @@ static int ideapad_backlight_get_brightness(struct backlight_device *blightdev)
{
unsigned long now;
if (read_ec_data(ideapad_handle, 0x12, &now))
if (read_ec_data(ideapad_handle, VPCCMD_R_BL, &now))
return -EIO;
return now;
}
static int ideapad_backlight_update_status(struct backlight_device *blightdev)
{
if (write_ec_cmd(ideapad_handle, 0x13, blightdev->props.brightness))
if (write_ec_cmd(ideapad_handle, VPCCMD_W_BL,
blightdev->props.brightness))
return -EIO;
if (write_ec_cmd(ideapad_handle, 0x33,
if (write_ec_cmd(ideapad_handle, VPCCMD_W_BL_POWER,
blightdev->props.power == FB_BLANK_POWERDOWN ? 0 : 1))
return -EIO;
@@ -453,11 +623,11 @@ static int ideapad_backlight_init(struct ideapad_private *priv)
struct backlight_properties props;
unsigned long max, now, power;
if (read_ec_data(ideapad_handle, 0x11, &max))
if (read_ec_data(ideapad_handle, VPCCMD_R_BL_MAX, &max))
return -EIO;
if (read_ec_data(ideapad_handle, 0x12, &now))
if (read_ec_data(ideapad_handle, VPCCMD_R_BL, &now))
return -EIO;
if (read_ec_data(ideapad_handle, 0x18, &power))
if (read_ec_data(ideapad_handle, VPCCMD_R_BL_POWER, &power))
return -EIO;
memset(&props, 0, sizeof(struct backlight_properties));
@@ -493,7 +663,9 @@ static void ideapad_backlight_notify_power(struct ideapad_private *priv)
unsigned long power;
struct backlight_device *blightdev = priv->blightdev;
if (read_ec_data(ideapad_handle, 0x18, &power))
if (!blightdev)
return;
if (read_ec_data(ideapad_handle, VPCCMD_R_BL_POWER, &power))
return;
blightdev->props.power = power ? FB_BLANK_UNBLANK : FB_BLANK_POWERDOWN;
}
@@ -504,7 +676,7 @@ static void ideapad_backlight_notify_brightness(struct ideapad_private *priv)
/* if we control brightness via acpi video driver */
if (priv->blightdev == NULL) {
read_ec_data(ideapad_handle, 0x12, &now);
read_ec_data(ideapad_handle, VPCCMD_R_BL, &now);
return;
}
@@ -533,6 +705,7 @@ static int __devinit ideapad_acpi_add(struct acpi_device *adevice)
if (!priv)
return -ENOMEM;
dev_set_drvdata(&adevice->dev, priv);
ideapad_priv = priv;
ideapad_handle = adevice->handle;
priv->cfg = cfg;
@@ -540,6 +713,10 @@ static int __devinit ideapad_acpi_add(struct acpi_device *adevice)
if (ret)
goto platform_failed;
ret = ideapad_debugfs_init(priv);
if (ret)
goto debugfs_failed;
ret = ideapad_input_init(priv);
if (ret)
goto input_failed;
@@ -550,7 +727,7 @@ static int __devinit ideapad_acpi_add(struct acpi_device *adevice)
else
priv->rfk[i] = NULL;
}
ideapad_sync_rfk_state(adevice);
ideapad_sync_rfk_state(priv);
if (!acpi_video_backlight_support()) {
ret = ideapad_backlight_init(priv);
@@ -565,6 +742,8 @@ backlight_failed:
ideapad_unregister_rfkill(adevice, i);
ideapad_input_exit(priv);
input_failed:
ideapad_debugfs_exit(priv);
debugfs_failed:
ideapad_platform_exit(priv);
platform_failed:
kfree(priv);
@@ -580,6 +759,7 @@ static int __devexit ideapad_acpi_remove(struct acpi_device *adevice, int type)
for (i = 0; i < IDEAPAD_RFKILL_DEV_NUM; i++)
ideapad_unregister_rfkill(adevice, i);
ideapad_input_exit(priv);
ideapad_debugfs_exit(priv);
ideapad_platform_exit(priv);
dev_set_drvdata(&adevice->dev, NULL);
kfree(priv);
@@ -593,9 +773,9 @@ static void ideapad_acpi_notify(struct acpi_device *adevice, u32 event)
acpi_handle handle = adevice->handle;
unsigned long vpc1, vpc2, vpc_bit;
if (read_ec_data(handle, 0x10, &vpc1))
if (read_ec_data(handle, VPCCMD_R_VPC1, &vpc1))
return;
if (read_ec_data(handle, 0x1A, &vpc2))
if (read_ec_data(handle, VPCCMD_R_VPC2, &vpc2))
return;
vpc1 = (vpc2 << 8) | vpc1;
@@ -603,11 +783,14 @@ static void ideapad_acpi_notify(struct acpi_device *adevice, u32 event)
if (test_bit(vpc_bit, &vpc1)) {
switch (vpc_bit) {
case 9:
ideapad_sync_rfk_state(adevice);
ideapad_sync_rfk_state(priv);
break;
case 4:
ideapad_backlight_notify_brightness(priv);
break;
case 3:
ideapad_input_novokey(priv);
break;
case 2:
ideapad_backlight_notify_power(priv);
break;
+6 -2
View File
@@ -24,7 +24,7 @@
#include <linux/init.h>
#include <asm/intel_scu_ipc.h>
static u32 major;
static int major;
#define MAX_FW_SIZE 264192
@@ -117,7 +117,11 @@ static const struct file_operations scu_ipc_fops = {
static int __init ipc_module_init(void)
{
return register_chrdev(0, "intel_mid_scu", &scu_ipc_fops);
major = register_chrdev(0, "intel_mid_scu", &scu_ipc_fops);
if (major < 0)
return major;
return 0;
}
static void __exit ipc_module_exit(void)
+102 -5
View File
@@ -226,6 +226,7 @@ static struct backlight_device *backlight_device;
static struct mutex sabi_mutex;
static struct platform_device *sdev;
static struct rfkill *rfk;
static bool has_stepping_quirk;
static int force;
module_param(force, bool, 0);
@@ -370,15 +371,28 @@ static u8 read_brightness(void)
&sretval);
if (!retval) {
user_brightness = sretval.retval[0];
if (user_brightness != 0)
if (user_brightness > sabi_config->min_brightness)
user_brightness -= sabi_config->min_brightness;
else
user_brightness = 0;
}
return user_brightness;
}
static void set_brightness(u8 user_brightness)
{
u8 user_level = user_brightness - sabi_config->min_brightness;
u8 user_level = user_brightness + sabi_config->min_brightness;
if (has_stepping_quirk && user_level != 0) {
/*
* short circuit if the specified level is what's already set
* to prevent the screen from flickering needlessly
*/
if (user_brightness == read_brightness())
return;
sabi_set_command(sabi_config->commands.set_brightness, 0);
}
sabi_set_command(sabi_config->commands.set_brightness, user_level);
}
@@ -388,6 +402,40 @@ static int get_brightness(struct backlight_device *bd)
return (int)read_brightness();
}
static void check_for_stepping_quirk(void)
{
u8 initial_level;
u8 check_level;
u8 orig_level = read_brightness();
/*
* Some laptops exhibit the strange behaviour of stepping toward
* (rather than setting) the brightness except when changing to/from
* brightness level 0. This behaviour is checked for here and worked
* around in set_brightness.
*/
if (orig_level == 0)
set_brightness(1);
initial_level = read_brightness();
if (initial_level <= 2)
check_level = initial_level + 2;
else
check_level = initial_level - 2;
has_stepping_quirk = false;
set_brightness(check_level);
if (read_brightness() != check_level) {
has_stepping_quirk = true;
pr_info("enabled workaround for brightness stepping quirk\n");
}
set_brightness(orig_level);
}
static int update_status(struct backlight_device *bd)
{
set_brightness(bd->props.brightness);
@@ -620,6 +668,16 @@ static struct dmi_system_id __initdata samsung_dmi_table[] = {
},
.callback = dmi_check_cb,
},
{
.ident = "N220",
.matches = {
DMI_MATCH(DMI_SYS_VENDOR,
"SAMSUNG ELECTRONICS CO., LTD."),
DMI_MATCH(DMI_PRODUCT_NAME, "N220"),
DMI_MATCH(DMI_BOARD_NAME, "N220"),
},
.callback = dmi_check_cb,
},
{
.ident = "N150/N210/N220/N230",
.matches = {
@@ -640,6 +698,15 @@ static struct dmi_system_id __initdata samsung_dmi_table[] = {
},
.callback = dmi_check_cb,
},
{
.ident = "R700",
.matches = {
DMI_MATCH(DMI_SYS_VENDOR, "SAMSUNG ELECTRONICS CO., LTD."),
DMI_MATCH(DMI_PRODUCT_NAME, "SR700"),
DMI_MATCH(DMI_BOARD_NAME, "SR700"),
},
.callback = dmi_check_cb,
},
{
.ident = "R530/R730",
.matches = {
@@ -686,6 +753,33 @@ static struct dmi_system_id __initdata samsung_dmi_table[] = {
},
.callback = dmi_check_cb,
},
{
.ident = "R528/R728",
.matches = {
DMI_MATCH(DMI_SYS_VENDOR, "SAMSUNG ELECTRONICS CO., LTD."),
DMI_MATCH(DMI_PRODUCT_NAME, "R528/R728"),
DMI_MATCH(DMI_BOARD_NAME, "R528/R728"),
},
.callback = dmi_check_cb,
},
{
.ident = "NC210/NC110",
.matches = {
DMI_MATCH(DMI_SYS_VENDOR, "SAMSUNG ELECTRONICS CO., LTD."),
DMI_MATCH(DMI_PRODUCT_NAME, "NC210/NC110"),
DMI_MATCH(DMI_BOARD_NAME, "NC210/NC110"),
},
.callback = dmi_check_cb,
},
{
.ident = "X520",
.matches = {
DMI_MATCH(DMI_SYS_VENDOR, "SAMSUNG ELECTRONICS CO., LTD."),
DMI_MATCH(DMI_PRODUCT_NAME, "X520"),
DMI_MATCH(DMI_BOARD_NAME, "X520"),
},
.callback = dmi_check_cb,
},
{ },
};
MODULE_DEVICE_TABLE(dmi, samsung_dmi_table);
@@ -770,7 +864,7 @@ static int __init samsung_init(void)
sabi_iface = ioremap_nocache(ifaceP, 16);
if (!sabi_iface) {
pr_err("Can't remap %x\n", ifaceP);
goto exit;
goto error_no_signature;
}
if (debug) {
printk(KERN_DEBUG "ifaceP = 0x%08x\n", ifaceP);
@@ -794,6 +888,9 @@ static int __init samsung_init(void)
}
}
/* Check for stepping quirk */
check_for_stepping_quirk();
/* knock up a platform device to hang stuff off of */
sdev = platform_device_register_simple("samsung", -1, NULL, 0);
if (IS_ERR(sdev))
@@ -802,7 +899,8 @@ static int __init samsung_init(void)
/* create a backlight device to talk to this one */
memset(&props, 0, sizeof(struct backlight_properties));
props.type = BACKLIGHT_PLATFORM;
props.max_brightness = sabi_config->max_brightness;
props.max_brightness = sabi_config->max_brightness -
sabi_config->min_brightness;
backlight_device = backlight_device_register("samsung", &sdev->dev,
NULL, &backlight_ops,
&props);
@@ -821,7 +919,6 @@ static int __init samsung_init(void)
if (retval)
goto error_file_create;
exit:
return 0;
error_file_create:
+1 -1
View File
@@ -3281,7 +3281,7 @@ static int sony_pic_add(struct acpi_device *device)
/* request IRQ */
list_for_each_entry_reverse(irq, &spic_dev.interrupts, list) {
if (!request_irq(irq->irq.interrupts[0], sony_pic_irq,
IRQF_DISABLED, "sony-laptop", &spic_dev)) {
0, "sony-laptop", &spic_dev)) {
dprintk("IRQ: %d - triggering: %d - "
"polarity: %d - shr: %d\n",
irq->irq.interrupts[0],
+1
View File
@@ -41,6 +41,7 @@ static const struct key_entry topstar_keymap[] = {
{ KE_KEY, 0x8c, { KEY_MEDIA } },
/* Known non hotkey events don't handled or that we don't care yet */
{ KE_IGNORE, 0x82, }, /* backlight event */
{ KE_IGNORE, 0x8e, },
{ KE_IGNORE, 0x8f, },
{ KE_IGNORE, 0x90, },
File diff suppressed because it is too large Load Diff
+5 -1
View File
@@ -754,9 +754,13 @@ static void wmi_free_devices(void)
struct wmi_block *wblock, *next;
/* Delete devices for all the GUIDs */
list_for_each_entry_safe(wblock, next, &wmi_block_list, list)
list_for_each_entry_safe(wblock, next, &wmi_block_list, list) {
list_del(&wblock->list);
if (wblock->dev.class)
device_unregister(&wblock->dev);
else
kfree(wblock);
}
}
static bool guid_already_parsed(const char *guid_string)