diff options
author | Marco Chiappero <marco@absence.it> | 2012-05-19 09:35:55 -0400 |
---|---|---|
committer | Matthew Garrett <mjg@redhat.com> | 2012-05-31 14:34:42 -0400 |
commit | 88bf170646c3673877f4449127c2940c0bc307ca (patch) | |
tree | bc91a1040075947892faad50eb39bf292f84f73b /drivers/platform | |
parent | 54535d083f0ae6ee51a43a7a3e17e3ca89774937 (diff) |
sony-laptop: add high speed battery charging function
Signed-off-by: Marco Chiappero <marco@absence.it>
Signed-off-by: Mattia Dongili <malattia@linux.it>
Signed-off-by: Matthew Garrett <mjg@redhat.com>
Diffstat (limited to 'drivers/platform')
-rw-r--r-- | drivers/platform/x86/sony-laptop.c | 86 |
1 files changed, 86 insertions, 0 deletions
diff --git a/drivers/platform/x86/sony-laptop.c b/drivers/platform/x86/sony-laptop.c index bc7f40bcd9cc..fcbedc972021 100644 --- a/drivers/platform/x86/sony-laptop.c +++ b/drivers/platform/x86/sony-laptop.c | |||
@@ -155,6 +155,9 @@ static void sony_nc_thermal_resume(void); | |||
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 | static void sony_nc_lid_resume_cleanup(struct platform_device *pd); | 156 | static void sony_nc_lid_resume_cleanup(struct platform_device *pd); |
157 | 157 | ||
158 | static int sony_nc_highspeed_charging_setup(struct platform_device *pd); | ||
159 | static void sony_nc_highspeed_charging_cleanup(struct platform_device *pd); | ||
160 | |||
158 | enum sony_nc_rfkill { | 161 | enum sony_nc_rfkill { |
159 | SONY_WIFI, | 162 | SONY_WIFI, |
160 | SONY_BLUETOOTH, | 163 | SONY_BLUETOOTH, |
@@ -1301,6 +1304,12 @@ static void sony_nc_function_setup(struct acpi_device *device, | |||
1301 | pr_err("couldn't set up thermal profile function (%d)\n", | 1304 | pr_err("couldn't set up thermal profile function (%d)\n", |
1302 | result); | 1305 | result); |
1303 | break; | 1306 | break; |
1307 | case 0x0131: | ||
1308 | result = sony_nc_highspeed_charging_setup(pf_device); | ||
1309 | if (result) | ||
1310 | pr_err("couldn't set up high speed charging function (%d)\n", | ||
1311 | result); | ||
1312 | break; | ||
1304 | case 0x0124: | 1313 | case 0x0124: |
1305 | case 0x0135: | 1314 | case 0x0135: |
1306 | sony_nc_rfkill_setup(device); | 1315 | sony_nc_rfkill_setup(device); |
@@ -1348,6 +1357,9 @@ static void sony_nc_function_cleanup(struct platform_device *pd) | |||
1348 | case 0x0122: | 1357 | case 0x0122: |
1349 | sony_nc_thermal_cleanup(pd); | 1358 | sony_nc_thermal_cleanup(pd); |
1350 | break; | 1359 | break; |
1360 | case 0x0131: | ||
1361 | sony_nc_highspeed_charging_cleanup(pd); | ||
1362 | break; | ||
1351 | case 0x0124: | 1363 | case 0x0124: |
1352 | case 0x0135: | 1364 | case 0x0135: |
1353 | sony_nc_rfkill_cleanup(); | 1365 | sony_nc_rfkill_cleanup(); |
@@ -2246,6 +2258,80 @@ static void sony_nc_lid_resume_cleanup(struct platform_device *pd) | |||
2246 | } | 2258 | } |
2247 | } | 2259 | } |
2248 | 2260 | ||
2261 | /* High speed charging function */ | ||
2262 | static struct device_attribute *hsc_handle; | ||
2263 | |||
2264 | static ssize_t sony_nc_highspeed_charging_store(struct device *dev, | ||
2265 | struct device_attribute *attr, | ||
2266 | const char *buffer, size_t count) | ||
2267 | { | ||
2268 | unsigned int result; | ||
2269 | unsigned long value; | ||
2270 | |||
2271 | if (count > 31) | ||
2272 | return -EINVAL; | ||
2273 | |||
2274 | if (kstrtoul(buffer, 10, &value) || value > 1) | ||
2275 | return -EINVAL; | ||
2276 | |||
2277 | if (sony_call_snc_handle(0x0131, value << 0x10 | 0x0200, &result)) | ||
2278 | return -EIO; | ||
2279 | |||
2280 | return count; | ||
2281 | } | ||
2282 | |||
2283 | static ssize_t sony_nc_highspeed_charging_show(struct device *dev, | ||
2284 | struct device_attribute *attr, char *buffer) | ||
2285 | { | ||
2286 | unsigned int result; | ||
2287 | |||
2288 | if (sony_call_snc_handle(0x0131, 0x0100, &result)) | ||
2289 | return -EIO; | ||
2290 | |||
2291 | return snprintf(buffer, PAGE_SIZE, "%d\n", result & 0x01); | ||
2292 | } | ||
2293 | |||
2294 | static int sony_nc_highspeed_charging_setup(struct platform_device *pd) | ||
2295 | { | ||
2296 | unsigned int result; | ||
2297 | |||
2298 | if (sony_call_snc_handle(0x0131, 0x0000, &result) || !(result & 0x01)) { | ||
2299 | /* some models advertise the handle but have no implementation | ||
2300 | * for it | ||
2301 | */ | ||
2302 | pr_info("No High Speed Charging capability found\n"); | ||
2303 | return 0; | ||
2304 | } | ||
2305 | |||
2306 | hsc_handle = kzalloc(sizeof(struct device_attribute), GFP_KERNEL); | ||
2307 | if (!hsc_handle) | ||
2308 | return -ENOMEM; | ||
2309 | |||
2310 | sysfs_attr_init(&hsc_handle->attr); | ||
2311 | hsc_handle->attr.name = "battery_highspeed_charging"; | ||
2312 | hsc_handle->attr.mode = S_IRUGO | S_IWUSR; | ||
2313 | hsc_handle->show = sony_nc_highspeed_charging_show; | ||
2314 | hsc_handle->store = sony_nc_highspeed_charging_store; | ||
2315 | |||
2316 | result = device_create_file(&pd->dev, hsc_handle); | ||
2317 | if (result) { | ||
2318 | kfree(hsc_handle); | ||
2319 | hsc_handle = NULL; | ||
2320 | return result; | ||
2321 | } | ||
2322 | |||
2323 | return 0; | ||
2324 | } | ||
2325 | |||
2326 | static void sony_nc_highspeed_charging_cleanup(struct platform_device *pd) | ||
2327 | { | ||
2328 | if (hsc_handle) { | ||
2329 | device_remove_file(&pd->dev, hsc_handle); | ||
2330 | kfree(hsc_handle); | ||
2331 | hsc_handle = NULL; | ||
2332 | } | ||
2333 | } | ||
2334 | |||
2249 | static void sony_nc_backlight_ng_read_limits(int handle, | 2335 | static void sony_nc_backlight_ng_read_limits(int handle, |
2250 | struct sony_backlight_props *props) | 2336 | struct sony_backlight_props *props) |
2251 | { | 2337 | { |