From 3ec1c3983d73b1e3d4cfd72afab94c34eceafe8a Mon Sep 17 00:00:00 2001 From: Mattia Dongili Date: Fri, 21 Dec 2012 07:21:08 +0900 Subject: sony-laptop: fully enable SNY controlled modems The call to handlers 0x124 and 0x135 (rfkill control) seems to take a bitmask to control various states of the device. For our rfkill we need a fully on/off. SVZ1311Z9R/X's LTE modem needs more bits up. Bugzilla: https://bugzilla.kernel.org/show_bug.cgi?id=47751 Signed-off-by: Mattia Dongili Signed-off-by: Matthew Garrett Cc: stable@kernel.org --- drivers/platform/x86/sony-laptop.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/platform/x86/sony-laptop.c') diff --git a/drivers/platform/x86/sony-laptop.c b/drivers/platform/x86/sony-laptop.c index ceb41eff4230..0bee6c2f8864 100644 --- a/drivers/platform/x86/sony-laptop.c +++ b/drivers/platform/x86/sony-laptop.c @@ -1534,7 +1534,7 @@ static int sony_nc_rfkill_set(void *data, bool blocked) int argument = sony_rfkill_address[(long) data] + 0x100; if (!blocked) - argument |= 0x030000; + argument |= 0x070000; return sony_call_snc_handle(sony_rfkill_handle, argument, &result); } -- cgit v1.2.1 From 3a7abcd809e75b3588dd4a6529238e2a9b009c9a Mon Sep 17 00:00:00 2001 From: Mattia Dongili Date: Fri, 21 Dec 2012 07:21:10 +0900 Subject: sony-laptop: allow reading the status of gfx switch Signed-off-by: Mattia Dongili Signed-off-by: Matthew Garrett --- drivers/platform/x86/sony-laptop.c | 121 ++++++++++++++++++++++++++++++++++--- 1 file changed, 112 insertions(+), 9 deletions(-) (limited to 'drivers/platform/x86/sony-laptop.c') diff --git a/drivers/platform/x86/sony-laptop.c b/drivers/platform/x86/sony-laptop.c index 0bee6c2f8864..46c71f49a6b4 100644 --- a/drivers/platform/x86/sony-laptop.c +++ b/drivers/platform/x86/sony-laptop.c @@ -158,6 +158,11 @@ static void sony_nc_thermal_cleanup(struct platform_device *pd); static int sony_nc_lid_resume_setup(struct platform_device *pd); static void sony_nc_lid_resume_cleanup(struct platform_device *pd); +static int sony_nc_gfx_switch_setup(struct platform_device *pd, + unsigned int handle); +static void sony_nc_gfx_switch_cleanup(struct platform_device *pd); +static int __sony_nc_gfx_switch_status_get(void); + static int sony_nc_highspeed_charging_setup(struct platform_device *pd); static void sony_nc_highspeed_charging_cleanup(struct platform_device *pd); @@ -1241,17 +1246,13 @@ static void sony_nc_notify(struct acpi_device *device, u32 event) /* 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); + (result == 0x1) ? "switch change" : + (result == 0x2) ? "output switch" : + (result == 0x3) ? "output switch" : + ""); ev_type = GFX_SWITCH; - real_ev = result & 0xff; + real_ev = __sony_nc_gfx_switch_status_get(); break; default: @@ -1350,6 +1351,13 @@ static void sony_nc_function_setup(struct acpi_device *device, pr_err("couldn't set up thermal profile function (%d)\n", result); break; + case 0x0128: + case 0x0146: + result = sony_nc_gfx_switch_setup(pf_device, handle); + if (result) + pr_err("couldn't set up GFX Switch status (%d)\n", + result); + break; case 0x0131: result = sony_nc_highspeed_charging_setup(pf_device); if (result) @@ -1414,6 +1422,10 @@ static void sony_nc_function_cleanup(struct platform_device *pd) case 0x0122: sony_nc_thermal_cleanup(pd); break; + case 0x0128: + case 0x0146: + sony_nc_gfx_switch_cleanup(pd); + break; case 0x0131: sony_nc_highspeed_charging_cleanup(pd); break; @@ -2355,6 +2367,97 @@ static void sony_nc_lid_resume_cleanup(struct platform_device *pd) } } +/* GFX Switch position */ +enum gfx_switch { + SPEED, + STAMINA, + AUTO +}; +struct snc_gfx_switch_control { + struct device_attribute attr; + unsigned int handle; +}; +static struct snc_gfx_switch_control *gfxs_ctl; + +/* returns 0 for speed, 1 for stamina */ +static int __sony_nc_gfx_switch_status_get(void) +{ + unsigned int result; + + if (sony_call_snc_handle(gfxs_ctl->handle, 0x0100, &result)) + return -EIO; + + switch (gfxs_ctl->handle) { + case 0x0146: + /* 1: discrete GFX (speed) + * 0: integrated GFX (stamina) + */ + return result & 0x1 ? SPEED : STAMINA; + break; + case 0x0128: + /* it's a more elaborated bitmask, for now: + * 2: integrated GFX (stamina) + * 0: discrete GFX (speed) + */ + dprintk("GFX Status: 0x%x\n", result); + return result & 0x80 ? AUTO : + result & 0x02 ? STAMINA : SPEED; + break; + } + return -EINVAL; +} + +static ssize_t sony_nc_gfx_switch_status_show(struct device *dev, + struct device_attribute *attr, + char *buffer) +{ + int pos = __sony_nc_gfx_switch_status_get(); + + if (pos < 0) + return pos; + + return snprintf(buffer, PAGE_SIZE, "%s\n", pos ? "speed" : "stamina"); +} + +static int sony_nc_gfx_switch_setup(struct platform_device *pd, + unsigned int handle) +{ + unsigned int result; + + gfxs_ctl = kzalloc(sizeof(struct snc_gfx_switch_control), GFP_KERNEL); + if (!gfxs_ctl) + return -ENOMEM; + + gfxs_ctl->handle = handle; + + sysfs_attr_init(&gfxs_ctl->attr.attr); + gfxs_ctl->attr.attr.name = "gfx_switch_status"; + gfxs_ctl->attr.attr.mode = S_IRUGO; + gfxs_ctl->attr.show = sony_nc_gfx_switch_status_show; + + result = device_create_file(&pd->dev, &gfxs_ctl->attr); + if (result) + goto gfxerror; + + return 0; + +gfxerror: + kfree(gfxs_ctl); + gfxs_ctl = NULL; + + return result; +} + +static void sony_nc_gfx_switch_cleanup(struct platform_device *pd) +{ + if (gfxs_ctl) { + device_remove_file(&pd->dev, &gfxs_ctl->attr); + + kfree(gfxs_ctl); + gfxs_ctl = NULL; + } +} + /* High speed charging function */ static struct device_attribute *hsc_handle; -- cgit v1.2.1 From 7517a17c1abfc081d19298459f3d2a0d14a86566 Mon Sep 17 00:00:00 2001 From: Mattia Dongili Date: Fri, 21 Dec 2012 07:21:11 +0900 Subject: sony-laptop: support basic functions for handle 0x14B and 0x14C Z series and other recent models have 0x14? for lid and keyboard backlight. Signed-off-by: Mattia Dongili Signed-off-by: Matthew Garrett --- drivers/platform/x86/sony-laptop.c | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) (limited to 'drivers/platform/x86/sony-laptop.c') diff --git a/drivers/platform/x86/sony-laptop.c b/drivers/platform/x86/sony-laptop.c index 46c71f49a6b4..438c7fa999f8 100644 --- a/drivers/platform/x86/sony-laptop.c +++ b/drivers/platform/x86/sony-laptop.c @@ -1373,6 +1373,8 @@ static void sony_nc_function_setup(struct acpi_device *device, break; case 0x0137: case 0x0143: + case 0x014b: + case 0x014c: result = sony_nc_kbd_backlight_setup(pf_device, handle); if (result) pr_err("couldn't set up keyboard backlight function (%d)\n", @@ -1435,6 +1437,8 @@ static void sony_nc_function_cleanup(struct platform_device *pd) break; case 0x0137: case 0x0143: + case 0x014b: + case 0x014c: sony_nc_kbd_backlight_cleanup(pd); break; default: @@ -1479,6 +1483,8 @@ static void sony_nc_function_resume(void) break; case 0x0137: case 0x0143: + case 0x014b: + case 0x014c: sony_nc_kbd_backlight_resume(); break; default: @@ -2636,6 +2642,8 @@ static void sony_nc_backlight_ng_read_limits(int handle, lvl_table_len = 9; break; case 0x143: + case 0x14b: + case 0x14c: lvl_table_len = 16; break; } @@ -2687,6 +2695,18 @@ static void sony_nc_backlight_setup(void) sony_nc_backlight_ng_read_limits(0x143, &sony_bl_props); max_brightness = sony_bl_props.maxlvl - sony_bl_props.offset; + } else if (sony_find_snc_handle(0x14b) >= 0) { + ops = &sony_backlight_ng_ops; + sony_bl_props.cmd_base = 0x3000; + sony_nc_backlight_ng_read_limits(0x14b, &sony_bl_props); + max_brightness = sony_bl_props.maxlvl - sony_bl_props.offset; + + } else if (sony_find_snc_handle(0x14c) >= 0) { + ops = &sony_backlight_ng_ops; + sony_bl_props.cmd_base = 0x3000; + sony_nc_backlight_ng_read_limits(0x14c, &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", &unused))) { ops = &sony_backlight_ops; -- cgit v1.2.1 From 34cf1df34aba1a6274deeef92ad6d02d5f52dab0 Mon Sep 17 00:00:00 2001 From: Dan Carpenter Date: Fri, 1 Feb 2013 16:28:27 +0300 Subject: sony-laptop: leak in error handling sony_nc_lid_resume_setup() We need to decrement "i" first because the current "i" was not allocated succesfully. Also we should go free the way down to zero to avoid a leak. Signed-off-by: Dan Carpenter Signed-off-by: Matthew Garrett --- drivers/platform/x86/sony-laptop.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/platform/x86/sony-laptop.c') diff --git a/drivers/platform/x86/sony-laptop.c b/drivers/platform/x86/sony-laptop.c index 438c7fa999f8..9557414954fa 100644 --- a/drivers/platform/x86/sony-laptop.c +++ b/drivers/platform/x86/sony-laptop.c @@ -2351,7 +2351,7 @@ static int sony_nc_lid_resume_setup(struct platform_device *pd) return 0; liderror: - for (; i > 0; i--) + for (i--; i >= 0; i--) device_remove_file(&pd->dev, &lid_ctl->attrs[i]); kfree(lid_ctl); -- cgit v1.2.1