|
@@ -124,6 +124,10 @@ struct sabi_commands {
|
|
|
u16 get_wireless_status;
|
|
|
u16 set_wireless_status;
|
|
|
|
|
|
+ /* 0x80 is off, 0x81 is on */
|
|
|
+ u16 get_lid_handling;
|
|
|
+ u16 set_lid_handling;
|
|
|
+
|
|
|
/* 0x81 to read, (0x82 | level << 8) to set, 0xaabb to enable */
|
|
|
u16 kbd_backlight;
|
|
|
|
|
@@ -194,6 +198,9 @@ static const struct sabi_config sabi_configs[] = {
|
|
|
.get_wireless_status = 0xFFFF,
|
|
|
.set_wireless_status = 0xFFFF,
|
|
|
|
|
|
+ .get_lid_handling = 0xFFFF,
|
|
|
+ .set_lid_handling = 0xFFFF,
|
|
|
+
|
|
|
.kbd_backlight = 0xFFFF,
|
|
|
|
|
|
.set_linux = 0x0a,
|
|
@@ -254,6 +261,9 @@ static const struct sabi_config sabi_configs[] = {
|
|
|
.get_wireless_status = 0x69,
|
|
|
.set_wireless_status = 0x6a,
|
|
|
|
|
|
+ .get_lid_handling = 0x6d,
|
|
|
+ .set_lid_handling = 0x6e,
|
|
|
+
|
|
|
.kbd_backlight = 0x78,
|
|
|
|
|
|
.set_linux = 0xff,
|
|
@@ -354,6 +364,7 @@ struct samsung_quirks {
|
|
|
bool four_kbd_backlight_levels;
|
|
|
bool enable_kbd_backlight;
|
|
|
bool use_native_backlight;
|
|
|
+ bool lid_handling;
|
|
|
};
|
|
|
|
|
|
static struct samsung_quirks samsung_unknown = {};
|
|
@@ -371,6 +382,10 @@ static struct samsung_quirks samsung_np740u3e = {
|
|
|
.enable_kbd_backlight = true,
|
|
|
};
|
|
|
|
|
|
+static struct samsung_quirks samsung_lid_handling = {
|
|
|
+ .lid_handling = true,
|
|
|
+};
|
|
|
+
|
|
|
static bool force;
|
|
|
module_param(force, bool, 0);
|
|
|
MODULE_PARM_DESC(force,
|
|
@@ -835,10 +850,76 @@ static ssize_t set_usb_charge(struct device *dev,
|
|
|
static DEVICE_ATTR(usb_charge, S_IWUSR | S_IRUGO,
|
|
|
get_usb_charge, set_usb_charge);
|
|
|
|
|
|
+static int read_lid_handling(struct samsung_laptop *samsung)
|
|
|
+{
|
|
|
+ const struct sabi_commands *commands = &samsung->config->commands;
|
|
|
+ struct sabi_data data;
|
|
|
+ int retval;
|
|
|
+
|
|
|
+ if (commands->get_lid_handling == 0xFFFF)
|
|
|
+ return -ENODEV;
|
|
|
+
|
|
|
+ memset(&data, 0, sizeof(data));
|
|
|
+ retval = sabi_command(samsung, commands->get_lid_handling,
|
|
|
+ &data, &data);
|
|
|
+
|
|
|
+ if (retval)
|
|
|
+ return retval;
|
|
|
+
|
|
|
+ return data.data[0] & 0x1;
|
|
|
+}
|
|
|
+
|
|
|
+static int write_lid_handling(struct samsung_laptop *samsung,
|
|
|
+ int enabled)
|
|
|
+{
|
|
|
+ const struct sabi_commands *commands = &samsung->config->commands;
|
|
|
+ struct sabi_data data;
|
|
|
+
|
|
|
+ memset(&data, 0, sizeof(data));
|
|
|
+ data.data[0] = 0x80 | enabled;
|
|
|
+ return sabi_command(samsung, commands->set_lid_handling,
|
|
|
+ &data, NULL);
|
|
|
+}
|
|
|
+
|
|
|
+static ssize_t get_lid_handling(struct device *dev,
|
|
|
+ struct device_attribute *attr,
|
|
|
+ char *buf)
|
|
|
+{
|
|
|
+ struct samsung_laptop *samsung = dev_get_drvdata(dev);
|
|
|
+ int ret;
|
|
|
+
|
|
|
+ ret = read_lid_handling(samsung);
|
|
|
+ if (ret < 0)
|
|
|
+ return ret;
|
|
|
+
|
|
|
+ return sprintf(buf, "%d\n", ret);
|
|
|
+}
|
|
|
+
|
|
|
+static ssize_t set_lid_handling(struct device *dev,
|
|
|
+ struct device_attribute *attr,
|
|
|
+ const char *buf, size_t count)
|
|
|
+{
|
|
|
+ struct samsung_laptop *samsung = dev_get_drvdata(dev);
|
|
|
+ int ret, value;
|
|
|
+
|
|
|
+ if (!count || kstrtoint(buf, 0, &value) != 0)
|
|
|
+ return -EINVAL;
|
|
|
+
|
|
|
+ ret = write_lid_handling(samsung, !!value);
|
|
|
+ if (ret < 0)
|
|
|
+ return ret;
|
|
|
+
|
|
|
+ return count;
|
|
|
+}
|
|
|
+
|
|
|
+static DEVICE_ATTR(lid_handling, S_IWUSR | S_IRUGO,
|
|
|
+ get_lid_handling, set_lid_handling);
|
|
|
+
|
|
|
static struct attribute *platform_attributes[] = {
|
|
|
&dev_attr_performance_level.attr,
|
|
|
&dev_attr_battery_life_extender.attr,
|
|
|
&dev_attr_usb_charge.attr,
|
|
|
+ &dev_attr_lid_handling.attr,
|
|
|
NULL
|
|
|
};
|
|
|
|
|
@@ -961,6 +1042,22 @@ static int __init samsung_rfkill_init(struct samsung_laptop *samsung)
|
|
|
return 0;
|
|
|
}
|
|
|
|
|
|
+static void samsung_lid_handling_exit(struct samsung_laptop *samsung)
|
|
|
+{
|
|
|
+ if (samsung->quirks->lid_handling)
|
|
|
+ write_lid_handling(samsung, 0);
|
|
|
+}
|
|
|
+
|
|
|
+static int __init samsung_lid_handling_init(struct samsung_laptop *samsung)
|
|
|
+{
|
|
|
+ int retval = 0;
|
|
|
+
|
|
|
+ if (samsung->quirks->lid_handling)
|
|
|
+ retval = write_lid_handling(samsung, 1);
|
|
|
+
|
|
|
+ return retval;
|
|
|
+}
|
|
|
+
|
|
|
static int kbd_backlight_enable(struct samsung_laptop *samsung)
|
|
|
{
|
|
|
const struct sabi_commands *commands = &samsung->config->commands;
|
|
@@ -1116,7 +1213,7 @@ static int __init samsung_backlight_init(struct samsung_laptop *samsung)
|
|
|
}
|
|
|
|
|
|
static umode_t samsung_sysfs_is_visible(struct kobject *kobj,
|
|
|
- struct attribute *attr, int idx)
|
|
|
+ struct attribute *attr, int idx)
|
|
|
{
|
|
|
struct device *dev = container_of(kobj, struct device, kobj);
|
|
|
struct platform_device *pdev = to_platform_device(dev);
|
|
@@ -1129,6 +1226,8 @@ static umode_t samsung_sysfs_is_visible(struct kobject *kobj,
|
|
|
ok = !!(read_battery_life_extender(samsung) >= 0);
|
|
|
if (attr == &dev_attr_usb_charge.attr)
|
|
|
ok = !!(read_usb_charge(samsung) >= 0);
|
|
|
+ if (attr == &dev_attr_lid_handling.attr)
|
|
|
+ ok = !!(read_lid_handling(samsung) >= 0);
|
|
|
|
|
|
return ok ? attr->mode : 0;
|
|
|
}
|
|
@@ -1441,6 +1540,9 @@ static int samsung_pm_notification(struct notifier_block *nb,
|
|
|
samsung->quirks->enable_kbd_backlight)
|
|
|
kbd_backlight_enable(samsung);
|
|
|
|
|
|
+ if (val == PM_POST_HIBERNATION && samsung->quirks->lid_handling)
|
|
|
+ write_lid_handling(samsung, 1);
|
|
|
+
|
|
|
return 0;
|
|
|
}
|
|
|
|
|
@@ -1583,6 +1685,15 @@ static struct dmi_system_id __initdata samsung_dmi_table[] = {
|
|
|
},
|
|
|
.driver_data = &samsung_np740u3e,
|
|
|
},
|
|
|
+ {
|
|
|
+ .callback = samsung_dmi_matched,
|
|
|
+ .ident = "300V3Z/300V4Z/300V5Z",
|
|
|
+ .matches = {
|
|
|
+ DMI_MATCH(DMI_SYS_VENDOR, "SAMSUNG ELECTRONICS CO., LTD."),
|
|
|
+ DMI_MATCH(DMI_PRODUCT_NAME, "300V3Z/300V4Z/300V5Z"),
|
|
|
+ },
|
|
|
+ .driver_data = &samsung_lid_handling,
|
|
|
+ },
|
|
|
{ },
|
|
|
};
|
|
|
MODULE_DEVICE_TABLE(dmi, samsung_dmi_table);
|
|
@@ -1662,6 +1773,10 @@ static int __init samsung_init(void)
|
|
|
if (ret)
|
|
|
goto error_leds;
|
|
|
|
|
|
+ ret = samsung_lid_handling_init(samsung);
|
|
|
+ if (ret)
|
|
|
+ goto error_lid_handling;
|
|
|
+
|
|
|
ret = samsung_debugfs_init(samsung);
|
|
|
if (ret)
|
|
|
goto error_debugfs;
|
|
@@ -1673,6 +1788,8 @@ static int __init samsung_init(void)
|
|
|
return ret;
|
|
|
|
|
|
error_debugfs:
|
|
|
+ samsung_lid_handling_exit(samsung);
|
|
|
+error_lid_handling:
|
|
|
samsung_leds_exit(samsung);
|
|
|
error_leds:
|
|
|
samsung_rfkill_exit(samsung);
|
|
@@ -1697,6 +1814,7 @@ static void __exit samsung_exit(void)
|
|
|
unregister_pm_notifier(&samsung->pm_nb);
|
|
|
|
|
|
samsung_debugfs_exit(samsung);
|
|
|
+ samsung_lid_handling_exit(samsung);
|
|
|
samsung_leds_exit(samsung);
|
|
|
samsung_rfkill_exit(samsung);
|
|
|
samsung_backlight_exit(samsung);
|