|
@@ -973,7 +973,7 @@ static ssize_t sony_nc_sysfs_store(struct device *dev,
|
|
struct device_attribute *attr,
|
|
struct device_attribute *attr,
|
|
const char *buffer, size_t count)
|
|
const char *buffer, size_t count)
|
|
{
|
|
{
|
|
- unsigned long value = 0;
|
|
|
|
|
|
+ int value;
|
|
int ret = 0;
|
|
int ret = 0;
|
|
struct sony_nc_value *item =
|
|
struct sony_nc_value *item =
|
|
container_of(attr, struct sony_nc_value, devattr);
|
|
container_of(attr, struct sony_nc_value, devattr);
|
|
@@ -984,7 +984,7 @@ static ssize_t sony_nc_sysfs_store(struct device *dev,
|
|
if (count > 31)
|
|
if (count > 31)
|
|
return -EINVAL;
|
|
return -EINVAL;
|
|
|
|
|
|
- if (kstrtoul(buffer, 10, &value))
|
|
|
|
|
|
+ if (kstrtoint(buffer, 10, &value))
|
|
return -EINVAL;
|
|
return -EINVAL;
|
|
|
|
|
|
if (item->validate)
|
|
if (item->validate)
|
|
@@ -994,7 +994,7 @@ static ssize_t sony_nc_sysfs_store(struct device *dev,
|
|
return value;
|
|
return value;
|
|
|
|
|
|
ret = sony_nc_int_call(sony_nc_acpi_handle, *item->acpiset,
|
|
ret = sony_nc_int_call(sony_nc_acpi_handle, *item->acpiset,
|
|
- (int *)&value, NULL);
|
|
|
|
|
|
+ &value, NULL);
|
|
if (ret < 0)
|
|
if (ret < 0)
|
|
return -EIO;
|
|
return -EIO;
|
|
|
|
|
|
@@ -1010,6 +1010,7 @@ static ssize_t sony_nc_sysfs_store(struct device *dev,
|
|
struct sony_backlight_props {
|
|
struct sony_backlight_props {
|
|
struct backlight_device *dev;
|
|
struct backlight_device *dev;
|
|
int handle;
|
|
int handle;
|
|
|
|
+ int cmd_base;
|
|
u8 offset;
|
|
u8 offset;
|
|
u8 maxlvl;
|
|
u8 maxlvl;
|
|
};
|
|
};
|
|
@@ -1037,7 +1038,7 @@ static int sony_nc_get_brightness_ng(struct backlight_device *bd)
|
|
struct sony_backlight_props *sdev =
|
|
struct sony_backlight_props *sdev =
|
|
(struct sony_backlight_props *)bl_get_data(bd);
|
|
(struct sony_backlight_props *)bl_get_data(bd);
|
|
|
|
|
|
- sony_call_snc_handle(sdev->handle, 0x0200, &result);
|
|
|
|
|
|
+ sony_call_snc_handle(sdev->handle, sdev->cmd_base + 0x100, &result);
|
|
|
|
|
|
return (result & 0xff) - sdev->offset;
|
|
return (result & 0xff) - sdev->offset;
|
|
}
|
|
}
|
|
@@ -1049,7 +1050,8 @@ static int sony_nc_update_status_ng(struct backlight_device *bd)
|
|
(struct sony_backlight_props *)bl_get_data(bd);
|
|
(struct sony_backlight_props *)bl_get_data(bd);
|
|
|
|
|
|
value = bd->props.brightness + sdev->offset;
|
|
value = bd->props.brightness + sdev->offset;
|
|
- if (sony_call_snc_handle(sdev->handle, 0x0100 | (value << 16), &result))
|
|
|
|
|
|
+ if (sony_call_snc_handle(sdev->handle, sdev->cmd_base | (value << 0x10),
|
|
|
|
+ &result))
|
|
return -EIO;
|
|
return -EIO;
|
|
|
|
|
|
return value;
|
|
return value;
|
|
@@ -1172,6 +1174,11 @@ static int sony_nc_hotkeys_decode(u32 event, unsigned int handle)
|
|
/*
|
|
/*
|
|
* ACPI callbacks
|
|
* ACPI callbacks
|
|
*/
|
|
*/
|
|
|
|
+enum event_types {
|
|
|
|
+ HOTKEY = 1,
|
|
|
|
+ KILLSWITCH,
|
|
|
|
+ GFX_SWITCH
|
|
|
|
+};
|
|
static void sony_nc_notify(struct acpi_device *device, u32 event)
|
|
static void sony_nc_notify(struct acpi_device *device, u32 event)
|
|
{
|
|
{
|
|
u32 real_ev = event;
|
|
u32 real_ev = event;
|
|
@@ -1196,7 +1203,7 @@ static void sony_nc_notify(struct acpi_device *device, u32 event)
|
|
/* hotkey event */
|
|
/* hotkey event */
|
|
case 0x0100:
|
|
case 0x0100:
|
|
case 0x0127:
|
|
case 0x0127:
|
|
- ev_type = 1;
|
|
|
|
|
|
+ ev_type = HOTKEY;
|
|
real_ev = sony_nc_hotkeys_decode(event, handle);
|
|
real_ev = sony_nc_hotkeys_decode(event, handle);
|
|
|
|
|
|
if (real_ev > 0)
|
|
if (real_ev > 0)
|
|
@@ -1216,7 +1223,7 @@ static void sony_nc_notify(struct acpi_device *device, u32 event)
|
|
* update the rfkill device status when the
|
|
* update the rfkill device status when the
|
|
* switch is moved.
|
|
* switch is moved.
|
|
*/
|
|
*/
|
|
- ev_type = 2;
|
|
|
|
|
|
+ ev_type = KILLSWITCH;
|
|
sony_call_snc_handle(handle, 0x0100, &result);
|
|
sony_call_snc_handle(handle, 0x0100, &result);
|
|
real_ev = result & 0x03;
|
|
real_ev = result & 0x03;
|
|
|
|
|
|
@@ -1226,6 +1233,24 @@ static void sony_nc_notify(struct acpi_device *device, u32 event)
|
|
|
|
|
|
break;
|
|
break;
|
|
|
|
|
|
|
|
+ case 0x0128:
|
|
|
|
+ case 0x0146:
|
|
|
|
+ /* Hybrid GFX switching */
|
|
|
|
+ sony_call_snc_handle(handle, 0x0000, &result);
|
|
|
|
+ dprintk("GFX switch event received (reason: %s)\n",
|
|
|
|
+ (result & 0x01) ?
|
|
|
|
+ "switch change" : "unknown");
|
|
|
|
+
|
|
|
|
+ /* verify the switch state
|
|
|
|
+ * 1: discrete GFX
|
|
|
|
+ * 0: integrated GFX
|
|
|
|
+ */
|
|
|
|
+ sony_call_snc_handle(handle, 0x0100, &result);
|
|
|
|
+
|
|
|
|
+ ev_type = GFX_SWITCH;
|
|
|
|
+ real_ev = result & 0xff;
|
|
|
|
+ break;
|
|
|
|
+
|
|
default:
|
|
default:
|
|
dprintk("Unknown event 0x%x for handle 0x%x\n",
|
|
dprintk("Unknown event 0x%x for handle 0x%x\n",
|
|
event, handle);
|
|
event, handle);
|
|
@@ -1238,7 +1263,7 @@ static void sony_nc_notify(struct acpi_device *device, u32 event)
|
|
|
|
|
|
} else {
|
|
} else {
|
|
/* old style event */
|
|
/* old style event */
|
|
- ev_type = 1;
|
|
|
|
|
|
+ ev_type = HOTKEY;
|
|
sony_laptop_report_input_event(real_ev);
|
|
sony_laptop_report_input_event(real_ev);
|
|
}
|
|
}
|
|
|
|
|
|
@@ -1893,32 +1918,33 @@ static ssize_t sony_nc_battery_care_limit_store(struct device *dev,
|
|
* bits 4,5: store the limit into the EC
|
|
* bits 4,5: store the limit into the EC
|
|
* bits 6,7: store the limit into the battery
|
|
* bits 6,7: store the limit into the battery
|
|
*/
|
|
*/
|
|
|
|
+ cmd = 0;
|
|
|
|
|
|
- /*
|
|
|
|
- * handle 0x0115 should allow storing on battery too;
|
|
|
|
- * handle 0x0136 same as 0x0115 + health status;
|
|
|
|
- * handle 0x013f, same as 0x0136 but no storing on the battery
|
|
|
|
- *
|
|
|
|
- * Store only inside the EC for now, regardless the handle number
|
|
|
|
- */
|
|
|
|
- if (value == 0)
|
|
|
|
- /* disable limits */
|
|
|
|
- cmd = 0x0;
|
|
|
|
|
|
+ if (value > 0) {
|
|
|
|
+ if (value <= 50)
|
|
|
|
+ cmd = 0x20;
|
|
|
|
|
|
- else if (value <= 50)
|
|
|
|
- cmd = 0x21;
|
|
|
|
|
|
+ else if (value <= 80)
|
|
|
|
+ cmd = 0x10;
|
|
|
|
|
|
- else if (value <= 80)
|
|
|
|
- cmd = 0x11;
|
|
|
|
|
|
+ else if (value <= 100)
|
|
|
|
+ cmd = 0x30;
|
|
|
|
|
|
- else if (value <= 100)
|
|
|
|
- cmd = 0x31;
|
|
|
|
|
|
+ else
|
|
|
|
+ return -EINVAL;
|
|
|
|
|
|
- else
|
|
|
|
- return -EINVAL;
|
|
|
|
|
|
+ /*
|
|
|
|
+ * handle 0x0115 should allow storing on battery too;
|
|
|
|
+ * handle 0x0136 same as 0x0115 + health status;
|
|
|
|
+ * handle 0x013f, same as 0x0136 but no storing on the battery
|
|
|
|
+ */
|
|
|
|
+ if (bcare_ctl->handle != 0x013f)
|
|
|
|
+ cmd = cmd | (cmd << 2);
|
|
|
|
|
|
- if (sony_call_snc_handle(bcare_ctl->handle, (cmd << 0x10) | 0x0100,
|
|
|
|
- &result))
|
|
|
|
|
|
+ cmd = (cmd | 0x1) << 0x10;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ if (sony_call_snc_handle(bcare_ctl->handle, cmd | 0x0100, &result))
|
|
return -EIO;
|
|
return -EIO;
|
|
|
|
|
|
return count;
|
|
return count;
|
|
@@ -2113,7 +2139,7 @@ static ssize_t sony_nc_thermal_mode_show(struct device *dev,
|
|
struct device_attribute *attr, char *buffer)
|
|
struct device_attribute *attr, char *buffer)
|
|
{
|
|
{
|
|
ssize_t count = 0;
|
|
ssize_t count = 0;
|
|
- unsigned int mode = sony_nc_thermal_mode_get();
|
|
|
|
|
|
+ int mode = sony_nc_thermal_mode_get();
|
|
|
|
|
|
if (mode < 0)
|
|
if (mode < 0)
|
|
return mode;
|
|
return mode;
|
|
@@ -2472,6 +2498,7 @@ static void sony_nc_backlight_ng_read_limits(int handle,
|
|
{
|
|
{
|
|
u64 offset;
|
|
u64 offset;
|
|
int i;
|
|
int i;
|
|
|
|
+ int lvl_table_len = 0;
|
|
u8 min = 0xff, max = 0x00;
|
|
u8 min = 0xff, max = 0x00;
|
|
unsigned char buffer[32] = { 0 };
|
|
unsigned char buffer[32] = { 0 };
|
|
|
|
|
|
@@ -2480,8 +2507,6 @@ static void sony_nc_backlight_ng_read_limits(int handle,
|
|
props->maxlvl = 0xff;
|
|
props->maxlvl = 0xff;
|
|
|
|
|
|
offset = sony_find_snc_handle(handle);
|
|
offset = sony_find_snc_handle(handle);
|
|
- if (offset < 0)
|
|
|
|
- return;
|
|
|
|
|
|
|
|
/* try to read the boundaries from ACPI tables, if we fail the above
|
|
/* try to read the boundaries from ACPI tables, if we fail the above
|
|
* defaults should be reasonable
|
|
* defaults should be reasonable
|
|
@@ -2491,11 +2516,21 @@ static void sony_nc_backlight_ng_read_limits(int handle,
|
|
if (i < 0)
|
|
if (i < 0)
|
|
return;
|
|
return;
|
|
|
|
|
|
|
|
+ switch (handle) {
|
|
|
|
+ case 0x012f:
|
|
|
|
+ case 0x0137:
|
|
|
|
+ lvl_table_len = 9;
|
|
|
|
+ break;
|
|
|
|
+ case 0x143:
|
|
|
|
+ lvl_table_len = 16;
|
|
|
|
+ break;
|
|
|
|
+ }
|
|
|
|
+
|
|
/* the buffer lists brightness levels available, brightness levels are
|
|
/* the buffer lists brightness levels available, brightness levels are
|
|
* from position 0 to 8 in the array, other values are used by ALS
|
|
* from position 0 to 8 in the array, other values are used by ALS
|
|
* control.
|
|
* control.
|
|
*/
|
|
*/
|
|
- for (i = 0; i < 9 && i < ARRAY_SIZE(buffer); i++) {
|
|
|
|
|
|
+ for (i = 0; i < lvl_table_len && i < ARRAY_SIZE(buffer); i++) {
|
|
|
|
|
|
dprintk("Brightness level: %d\n", buffer[i]);
|
|
dprintk("Brightness level: %d\n", buffer[i]);
|
|
|
|
|
|
@@ -2520,16 +2555,24 @@ static void sony_nc_backlight_setup(void)
|
|
const struct backlight_ops *ops = NULL;
|
|
const struct backlight_ops *ops = NULL;
|
|
struct backlight_properties props;
|
|
struct backlight_properties props;
|
|
|
|
|
|
- if (sony_find_snc_handle(0x12f) != -1) {
|
|
|
|
|
|
+ if (sony_find_snc_handle(0x12f) >= 0) {
|
|
ops = &sony_backlight_ng_ops;
|
|
ops = &sony_backlight_ng_ops;
|
|
|
|
+ sony_bl_props.cmd_base = 0x0100;
|
|
sony_nc_backlight_ng_read_limits(0x12f, &sony_bl_props);
|
|
sony_nc_backlight_ng_read_limits(0x12f, &sony_bl_props);
|
|
max_brightness = sony_bl_props.maxlvl - sony_bl_props.offset;
|
|
max_brightness = sony_bl_props.maxlvl - sony_bl_props.offset;
|
|
|
|
|
|
- } else if (sony_find_snc_handle(0x137) != -1) {
|
|
|
|
|
|
+ } else if (sony_find_snc_handle(0x137) >= 0) {
|
|
ops = &sony_backlight_ng_ops;
|
|
ops = &sony_backlight_ng_ops;
|
|
|
|
+ sony_bl_props.cmd_base = 0x0100;
|
|
sony_nc_backlight_ng_read_limits(0x137, &sony_bl_props);
|
|
sony_nc_backlight_ng_read_limits(0x137, &sony_bl_props);
|
|
max_brightness = sony_bl_props.maxlvl - sony_bl_props.offset;
|
|
max_brightness = sony_bl_props.maxlvl - sony_bl_props.offset;
|
|
|
|
|
|
|
|
+ } else if (sony_find_snc_handle(0x143) >= 0) {
|
|
|
|
+ ops = &sony_backlight_ng_ops;
|
|
|
|
+ sony_bl_props.cmd_base = 0x3000;
|
|
|
|
+ sony_nc_backlight_ng_read_limits(0x143, &sony_bl_props);
|
|
|
|
+ max_brightness = sony_bl_props.maxlvl - sony_bl_props.offset;
|
|
|
|
+
|
|
} else if (ACPI_SUCCESS(acpi_get_handle(sony_nc_acpi_handle, "GBRT",
|
|
} else if (ACPI_SUCCESS(acpi_get_handle(sony_nc_acpi_handle, "GBRT",
|
|
&unused))) {
|
|
&unused))) {
|
|
ops = &sony_backlight_ops;
|
|
ops = &sony_backlight_ops;
|
|
@@ -2597,6 +2640,12 @@ static int sony_nc_add(struct acpi_device *device)
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+ result = sony_laptop_setup_input(device);
|
|
|
|
+ if (result) {
|
|
|
|
+ pr_err("Unable to create input devices\n");
|
|
|
|
+ goto outplatform;
|
|
|
|
+ }
|
|
|
|
+
|
|
if (ACPI_SUCCESS(acpi_get_handle(sony_nc_acpi_handle, "ECON",
|
|
if (ACPI_SUCCESS(acpi_get_handle(sony_nc_acpi_handle, "ECON",
|
|
&handle))) {
|
|
&handle))) {
|
|
int arg = 1;
|
|
int arg = 1;
|
|
@@ -2614,12 +2663,6 @@ static int sony_nc_add(struct acpi_device *device)
|
|
}
|
|
}
|
|
|
|
|
|
/* setup input devices and helper fifo */
|
|
/* setup input devices and helper fifo */
|
|
- result = sony_laptop_setup_input(device);
|
|
|
|
- if (result) {
|
|
|
|
- pr_err("Unable to create input devices\n");
|
|
|
|
- goto outsnc;
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
if (acpi_video_backlight_support()) {
|
|
if (acpi_video_backlight_support()) {
|
|
pr_info("brightness ignored, must be controlled by ACPI video driver\n");
|
|
pr_info("brightness ignored, must be controlled by ACPI video driver\n");
|
|
} else {
|
|
} else {
|
|
@@ -2667,22 +2710,21 @@ static int sony_nc_add(struct acpi_device *device)
|
|
|
|
|
|
return 0;
|
|
return 0;
|
|
|
|
|
|
- out_sysfs:
|
|
|
|
|
|
+out_sysfs:
|
|
for (item = sony_nc_values; item->name; ++item) {
|
|
for (item = sony_nc_values; item->name; ++item) {
|
|
device_remove_file(&sony_pf_device->dev, &item->devattr);
|
|
device_remove_file(&sony_pf_device->dev, &item->devattr);
|
|
}
|
|
}
|
|
sony_nc_backlight_cleanup();
|
|
sony_nc_backlight_cleanup();
|
|
-
|
|
|
|
- sony_laptop_remove_input();
|
|
|
|
-
|
|
|
|
- outsnc:
|
|
|
|
sony_nc_function_cleanup(sony_pf_device);
|
|
sony_nc_function_cleanup(sony_pf_device);
|
|
sony_nc_handles_cleanup(sony_pf_device);
|
|
sony_nc_handles_cleanup(sony_pf_device);
|
|
|
|
|
|
- outpresent:
|
|
|
|
|
|
+outplatform:
|
|
|
|
+ sony_laptop_remove_input();
|
|
|
|
+
|
|
|
|
+outpresent:
|
|
sony_pf_remove();
|
|
sony_pf_remove();
|
|
|
|
|
|
- outwalk:
|
|
|
|
|
|
+outwalk:
|
|
sony_nc_rfkill_cleanup();
|
|
sony_nc_rfkill_cleanup();
|
|
return result;
|
|
return result;
|
|
}
|
|
}
|