diff options
author | Javier Achirica <jachirica@gmail.com> | 2014-03-20 19:01:13 -0400 |
---|---|---|
committer | Matthew Garrett <matthew.garrett@nebula.com> | 2014-04-06 12:58:12 -0400 |
commit | 353120760599c565e2d0a4174a0f3faeeb2e56ae (patch) | |
tree | 05ca5f4a3a2134467290d98a070fa961bee3bcf2 /drivers/platform | |
parent | 94d164dc411ffe8d59c7201ade73126297380733 (diff) |
sony-laptop: Add support for lid resume settings on Vaio Pro
Vaio Pro uses a different handle and doesn't support all the options as
other models (only S5 setting v/s S3/4/5).
Minor code rework to generalize functions by Mattia Dongili.
Signed-off-by: Javier Achirica <jachirica@gmail.com>
Signed-off-by: Mattia Dongili <malattia@linux.it>
Signed-off-by: Matthew Garrett <matthew.garrett@nebula.com>
Diffstat (limited to 'drivers/platform')
-rw-r--r-- | drivers/platform/x86/sony-laptop.c | 110 |
1 files changed, 62 insertions, 48 deletions
diff --git a/drivers/platform/x86/sony-laptop.c b/drivers/platform/x86/sony-laptop.c index fe5424c3b9af..de173909257a 100644 --- a/drivers/platform/x86/sony-laptop.c +++ b/drivers/platform/x86/sony-laptop.c | |||
@@ -152,7 +152,8 @@ static void sony_nc_battery_care_cleanup(struct platform_device *pd); | |||
152 | static int sony_nc_thermal_setup(struct platform_device *pd); | 152 | static int sony_nc_thermal_setup(struct platform_device *pd); |
153 | static void sony_nc_thermal_cleanup(struct platform_device *pd); | 153 | static void sony_nc_thermal_cleanup(struct platform_device *pd); |
154 | 154 | ||
155 | static int sony_nc_lid_resume_setup(struct platform_device *pd); | 155 | static int sony_nc_lid_resume_setup(struct platform_device *pd, |
156 | unsigned int handle); | ||
156 | static void sony_nc_lid_resume_cleanup(struct platform_device *pd); | 157 | static void sony_nc_lid_resume_cleanup(struct platform_device *pd); |
157 | 158 | ||
158 | static int sony_nc_gfx_switch_setup(struct platform_device *pd, | 159 | static int sony_nc_gfx_switch_setup(struct platform_device *pd, |
@@ -1341,7 +1342,8 @@ static void sony_nc_function_setup(struct acpi_device *device, | |||
1341 | result); | 1342 | result); |
1342 | break; | 1343 | break; |
1343 | case 0x0119: | 1344 | case 0x0119: |
1344 | result = sony_nc_lid_resume_setup(pf_device); | 1345 | case 0x015D: |
1346 | result = sony_nc_lid_resume_setup(pf_device, handle); | ||
1345 | if (result) | 1347 | if (result) |
1346 | pr_err("couldn't set up lid resume function (%d)\n", | 1348 | pr_err("couldn't set up lid resume function (%d)\n", |
1347 | result); | 1349 | result); |
@@ -1422,6 +1424,7 @@ static void sony_nc_function_cleanup(struct platform_device *pd) | |||
1422 | sony_nc_battery_care_cleanup(pd); | 1424 | sony_nc_battery_care_cleanup(pd); |
1423 | break; | 1425 | break; |
1424 | case 0x0119: | 1426 | case 0x0119: |
1427 | case 0x015D: | ||
1425 | sony_nc_lid_resume_cleanup(pd); | 1428 | sony_nc_lid_resume_cleanup(pd); |
1426 | break; | 1429 | break; |
1427 | case 0x0122: | 1430 | case 0x0122: |
@@ -2223,9 +2226,14 @@ static void sony_nc_thermal_resume(void) | |||
2223 | #endif | 2226 | #endif |
2224 | 2227 | ||
2225 | /* resume on LID open */ | 2228 | /* resume on LID open */ |
2229 | #define LID_RESUME_S5 0 | ||
2230 | #define LID_RESUME_S4 1 | ||
2231 | #define LID_RESUME_S3 2 | ||
2232 | #define LID_RESUME_MAX 3 | ||
2226 | struct snc_lid_resume_control { | 2233 | struct snc_lid_resume_control { |
2227 | struct device_attribute attrs[3]; | 2234 | struct device_attribute attrs[LID_RESUME_MAX]; |
2228 | unsigned int status; | 2235 | unsigned int status; |
2236 | int handle; | ||
2229 | }; | 2237 | }; |
2230 | static struct snc_lid_resume_control *lid_ctl; | 2238 | static struct snc_lid_resume_control *lid_ctl; |
2231 | 2239 | ||
@@ -2233,8 +2241,9 @@ static ssize_t sony_nc_lid_resume_store(struct device *dev, | |||
2233 | struct device_attribute *attr, | 2241 | struct device_attribute *attr, |
2234 | const char *buffer, size_t count) | 2242 | const char *buffer, size_t count) |
2235 | { | 2243 | { |
2236 | unsigned int result, pos; | 2244 | unsigned int result; |
2237 | unsigned long value; | 2245 | unsigned long value; |
2246 | unsigned int pos = LID_RESUME_S5; | ||
2238 | if (count > 31) | 2247 | if (count > 31) |
2239 | return -EINVAL; | 2248 | return -EINVAL; |
2240 | 2249 | ||
@@ -2247,21 +2256,21 @@ static ssize_t sony_nc_lid_resume_store(struct device *dev, | |||
2247 | * +--------------+ | 2256 | * +--------------+ |
2248 | * 2 1 0 | 2257 | * 2 1 0 |
2249 | */ | 2258 | */ |
2250 | if (strcmp(attr->attr.name, "lid_resume_S3") == 0) | 2259 | while (pos < LID_RESUME_MAX) { |
2251 | pos = 2; | 2260 | if (&lid_ctl->attrs[pos].attr == &attr->attr) |
2252 | else if (strcmp(attr->attr.name, "lid_resume_S4") == 0) | 2261 | break; |
2253 | pos = 1; | 2262 | pos++; |
2254 | else if (strcmp(attr->attr.name, "lid_resume_S5") == 0) | 2263 | } |
2255 | pos = 0; | 2264 | if (pos == LID_RESUME_MAX) |
2256 | else | 2265 | return -EINVAL; |
2257 | return -EINVAL; | ||
2258 | 2266 | ||
2259 | if (value) | 2267 | if (value) |
2260 | value = lid_ctl->status | (1 << pos); | 2268 | value = lid_ctl->status | (1 << pos); |
2261 | else | 2269 | else |
2262 | value = lid_ctl->status & ~(1 << pos); | 2270 | value = lid_ctl->status & ~(1 << pos); |
2263 | 2271 | ||
2264 | if (sony_call_snc_handle(0x0119, value << 0x10 | 0x0100, &result)) | 2272 | if (sony_call_snc_handle(lid_ctl->handle, value << 0x10 | 0x0100, |
2273 | &result)) | ||
2265 | return -EIO; | 2274 | return -EIO; |
2266 | 2275 | ||
2267 | lid_ctl->status = value; | 2276 | lid_ctl->status = value; |
@@ -2270,29 +2279,27 @@ static ssize_t sony_nc_lid_resume_store(struct device *dev, | |||
2270 | } | 2279 | } |
2271 | 2280 | ||
2272 | static ssize_t sony_nc_lid_resume_show(struct device *dev, | 2281 | static ssize_t sony_nc_lid_resume_show(struct device *dev, |
2273 | struct device_attribute *attr, char *buffer) | 2282 | struct device_attribute *attr, |
2283 | char *buffer) | ||
2274 | { | 2284 | { |
2275 | unsigned int pos; | 2285 | unsigned int pos = LID_RESUME_S5; |
2276 | 2286 | ||
2277 | if (strcmp(attr->attr.name, "lid_resume_S3") == 0) | 2287 | while (pos < LID_RESUME_MAX) { |
2278 | pos = 2; | 2288 | if (&lid_ctl->attrs[pos].attr == &attr->attr) |
2279 | else if (strcmp(attr->attr.name, "lid_resume_S4") == 0) | 2289 | return snprintf(buffer, PAGE_SIZE, "%d\n", |
2280 | pos = 1; | 2290 | (lid_ctl->status >> pos) & 0x01); |
2281 | else if (strcmp(attr->attr.name, "lid_resume_S5") == 0) | 2291 | pos++; |
2282 | pos = 0; | 2292 | } |
2283 | else | 2293 | return -EINVAL; |
2284 | return -EINVAL; | ||
2285 | |||
2286 | return snprintf(buffer, PAGE_SIZE, "%d\n", | ||
2287 | (lid_ctl->status >> pos) & 0x01); | ||
2288 | } | 2294 | } |
2289 | 2295 | ||
2290 | static int sony_nc_lid_resume_setup(struct platform_device *pd) | 2296 | static int sony_nc_lid_resume_setup(struct platform_device *pd, |
2297 | unsigned int handle) | ||
2291 | { | 2298 | { |
2292 | unsigned int result; | 2299 | unsigned int result; |
2293 | int i; | 2300 | int i; |
2294 | 2301 | ||
2295 | if (sony_call_snc_handle(0x0119, 0x0000, &result)) | 2302 | if (sony_call_snc_handle(handle, 0x0000, &result)) |
2296 | return -EIO; | 2303 | return -EIO; |
2297 | 2304 | ||
2298 | lid_ctl = kzalloc(sizeof(struct snc_lid_resume_control), GFP_KERNEL); | 2305 | lid_ctl = kzalloc(sizeof(struct snc_lid_resume_control), GFP_KERNEL); |
@@ -2300,26 +2307,29 @@ static int sony_nc_lid_resume_setup(struct platform_device *pd) | |||
2300 | return -ENOMEM; | 2307 | return -ENOMEM; |
2301 | 2308 | ||
2302 | lid_ctl->status = result & 0x7; | 2309 | lid_ctl->status = result & 0x7; |
2310 | lid_ctl->handle = handle; | ||
2303 | 2311 | ||
2304 | sysfs_attr_init(&lid_ctl->attrs[0].attr); | 2312 | sysfs_attr_init(&lid_ctl->attrs[0].attr); |
2305 | lid_ctl->attrs[0].attr.name = "lid_resume_S3"; | 2313 | lid_ctl->attrs[LID_RESUME_S5].attr.name = "lid_resume_S5"; |
2306 | lid_ctl->attrs[0].attr.mode = S_IRUGO | S_IWUSR; | 2314 | lid_ctl->attrs[LID_RESUME_S5].attr.mode = S_IRUGO | S_IWUSR; |
2307 | lid_ctl->attrs[0].show = sony_nc_lid_resume_show; | 2315 | lid_ctl->attrs[LID_RESUME_S5].show = sony_nc_lid_resume_show; |
2308 | lid_ctl->attrs[0].store = sony_nc_lid_resume_store; | 2316 | lid_ctl->attrs[LID_RESUME_S5].store = sony_nc_lid_resume_store; |
2309 | 2317 | ||
2310 | sysfs_attr_init(&lid_ctl->attrs[1].attr); | 2318 | if (handle == 0x0119) { |
2311 | lid_ctl->attrs[1].attr.name = "lid_resume_S4"; | 2319 | sysfs_attr_init(&lid_ctl->attrs[1].attr); |
2312 | lid_ctl->attrs[1].attr.mode = S_IRUGO | S_IWUSR; | 2320 | lid_ctl->attrs[LID_RESUME_S4].attr.name = "lid_resume_S4"; |
2313 | lid_ctl->attrs[1].show = sony_nc_lid_resume_show; | 2321 | lid_ctl->attrs[LID_RESUME_S4].attr.mode = S_IRUGO | S_IWUSR; |
2314 | lid_ctl->attrs[1].store = sony_nc_lid_resume_store; | 2322 | lid_ctl->attrs[LID_RESUME_S4].show = sony_nc_lid_resume_show; |
2315 | 2323 | lid_ctl->attrs[LID_RESUME_S4].store = sony_nc_lid_resume_store; | |
2316 | sysfs_attr_init(&lid_ctl->attrs[2].attr); | 2324 | |
2317 | lid_ctl->attrs[2].attr.name = "lid_resume_S5"; | 2325 | sysfs_attr_init(&lid_ctl->attrs[2].attr); |
2318 | lid_ctl->attrs[2].attr.mode = S_IRUGO | S_IWUSR; | 2326 | lid_ctl->attrs[LID_RESUME_S3].attr.name = "lid_resume_S3"; |
2319 | lid_ctl->attrs[2].show = sony_nc_lid_resume_show; | 2327 | lid_ctl->attrs[LID_RESUME_S3].attr.mode = S_IRUGO | S_IWUSR; |
2320 | lid_ctl->attrs[2].store = sony_nc_lid_resume_store; | 2328 | lid_ctl->attrs[LID_RESUME_S3].show = sony_nc_lid_resume_show; |
2321 | 2329 | lid_ctl->attrs[LID_RESUME_S3].store = sony_nc_lid_resume_store; | |
2322 | for (i = 0; i < 3; i++) { | 2330 | } |
2331 | for (i = 0; i < LID_RESUME_MAX && | ||
2332 | lid_ctl->attrs[LID_RESUME_S3].attr.name; i++) { | ||
2323 | result = device_create_file(&pd->dev, &lid_ctl->attrs[i]); | 2333 | result = device_create_file(&pd->dev, &lid_ctl->attrs[i]); |
2324 | if (result) | 2334 | if (result) |
2325 | goto liderror; | 2335 | goto liderror; |
@@ -2342,8 +2352,12 @@ static void sony_nc_lid_resume_cleanup(struct platform_device *pd) | |||
2342 | int i; | 2352 | int i; |
2343 | 2353 | ||
2344 | if (lid_ctl) { | 2354 | if (lid_ctl) { |
2345 | for (i = 0; i < 3; i++) | 2355 | for (i = 0; i < LID_RESUME_MAX; i++) { |
2356 | if (!lid_ctl->attrs[i].attr.name) | ||
2357 | break; | ||
2358 | |||
2346 | device_remove_file(&pd->dev, &lid_ctl->attrs[i]); | 2359 | device_remove_file(&pd->dev, &lid_ctl->attrs[i]); |
2360 | } | ||
2347 | 2361 | ||
2348 | kfree(lid_ctl); | 2362 | kfree(lid_ctl); |
2349 | lid_ctl = NULL; | 2363 | lid_ctl = NULL; |