You've already forked linux-apfs
mirror of
https://github.com/linux-apfs/linux-apfs.git
synced 2026-05-01 15:00:59 -07:00
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:
@@ -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.
|
||||
|
||||
|
||||
+264
-224
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -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);
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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"
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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:
|
||||
|
||||
@@ -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],
|
||||
|
||||
@@ -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, },
|
||||
|
||||
+371
-336
File diff suppressed because it is too large
Load Diff
@@ -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)
|
||||
|
||||
Reference in New Issue
Block a user