aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/platform
diff options
context:
space:
mode:
authorJavier Achirica <jachirica@gmail.com>2014-03-20 19:01:13 -0400
committerMatthew Garrett <matthew.garrett@nebula.com>2014-04-06 12:58:12 -0400
commit353120760599c565e2d0a4174a0f3faeeb2e56ae (patch)
tree05ca5f4a3a2134467290d98a070fa961bee3bcf2 /drivers/platform
parent94d164dc411ffe8d59c7201ade73126297380733 (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.c110
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);
152static int sony_nc_thermal_setup(struct platform_device *pd); 152static int sony_nc_thermal_setup(struct platform_device *pd);
153static void sony_nc_thermal_cleanup(struct platform_device *pd); 153static void sony_nc_thermal_cleanup(struct platform_device *pd);
154 154
155static int sony_nc_lid_resume_setup(struct platform_device *pd); 155static int sony_nc_lid_resume_setup(struct platform_device *pd,
156 unsigned int handle);
156static void sony_nc_lid_resume_cleanup(struct platform_device *pd); 157static void sony_nc_lid_resume_cleanup(struct platform_device *pd);
157 158
158static int sony_nc_gfx_switch_setup(struct platform_device *pd, 159static 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
2226struct snc_lid_resume_control { 2233struct 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};
2230static struct snc_lid_resume_control *lid_ctl; 2238static 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
2272static ssize_t sony_nc_lid_resume_show(struct device *dev, 2281static 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
2290static int sony_nc_lid_resume_setup(struct platform_device *pd) 2296static 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;