asus-laptop.c (abec04dbc3dbe7577ccd9d5d6e188aa153d464eb) | asus-laptop.c (b23910c2194e0e0ee43e585788085f8e6dd4877e) |
---|---|
1/* 2 * asus-laptop.c - Asus Laptop Support 3 * 4 * 5 * Copyright (C) 2002-2005 Julien Lerouge, 2003-2006 Karol Kozimor 6 * Copyright (C) 2006-2007 Corentin Chary 7 * Copyright (C) 2011 Wind River Systems 8 * --- 179 unchanged lines hidden (view full) --- 188#define METHOD_PEGA_DISABLE "DAPR" 189#define PEGA_ALS 0x04 190#define PEGA_ALS_POWER 0x05 191 192#define METHOD_PEGA_READ "RDLN" 193#define PEGA_READ_ALS_H 0x02 194#define PEGA_READ_ALS_L 0x03 195 | 1/* 2 * asus-laptop.c - Asus Laptop Support 3 * 4 * 5 * Copyright (C) 2002-2005 Julien Lerouge, 2003-2006 Karol Kozimor 6 * Copyright (C) 2006-2007 Corentin Chary 7 * Copyright (C) 2011 Wind River Systems 8 * --- 179 unchanged lines hidden (view full) --- 188#define METHOD_PEGA_DISABLE "DAPR" 189#define PEGA_ALS 0x04 190#define PEGA_ALS_POWER 0x05 191 192#define METHOD_PEGA_READ "RDLN" 193#define PEGA_READ_ALS_H 0x02 194#define PEGA_READ_ALS_L 0x03 195 |
196#define PEGA_ACCEL_NAME "pega_accel" 197#define PEGA_ACCEL_DESC "Pegatron Lucid Tablet Accelerometer" 198#define METHOD_XLRX "XLRX" 199#define METHOD_XLRY "XLRY" 200#define METHOD_XLRZ "XLRZ" 201#define PEGA_ACC_CLAMP 512 /* 1G accel is reported as ~256, so clamp to 2G */ 202#define PEGA_ACC_RETRIES 3 203 |
|
196/* 197 * Define a specific led structure to keep the main structure clean 198 */ 199struct asus_led { 200 int wk; 201 struct work_struct work; 202 struct led_classdev led; 203 struct asus_laptop *asus; --- 9 unchanged lines hidden (view full) --- 213 214 struct acpi_table_header *dsdt_info; 215 struct platform_device *platform_device; 216 struct acpi_device *device; /* the device we are in */ 217 struct backlight_device *backlight_device; 218 219 struct input_dev *inputdev; 220 struct key_entry *keymap; | 204/* 205 * Define a specific led structure to keep the main structure clean 206 */ 207struct asus_led { 208 int wk; 209 struct work_struct work; 210 struct led_classdev led; 211 struct asus_laptop *asus; --- 9 unchanged lines hidden (view full) --- 221 222 struct acpi_table_header *dsdt_info; 223 struct platform_device *platform_device; 224 struct acpi_device *device; /* the device we are in */ 225 struct backlight_device *backlight_device; 226 227 struct input_dev *inputdev; 228 struct key_entry *keymap; |
229 struct input_polled_dev *pega_accel_poll; |
|
221 222 struct asus_led mled; 223 struct asus_led tled; 224 struct asus_led rled; 225 struct asus_led pled; 226 struct asus_led gled; 227 struct asus_led kled; 228 struct workqueue_struct *led_workqueue; 229 230 int wireless_status; 231 bool have_rsts; 232 bool is_pega_lucid; | 230 231 struct asus_led mled; 232 struct asus_led tled; 233 struct asus_led rled; 234 struct asus_led pled; 235 struct asus_led gled; 236 struct asus_led kled; 237 struct workqueue_struct *led_workqueue; 238 239 int wireless_status; 240 bool have_rsts; 241 bool is_pega_lucid; |
242 bool pega_acc_live; 243 int pega_acc_x; 244 int pega_acc_y; 245 int pega_acc_z; |
|
233 234 struct rfkill *gps_rfkill; 235 236 acpi_handle handle; /* the handle of the hotk device */ 237 u32 ledd_status; /* status of the LED display */ 238 u8 light_level; /* light sensor level */ 239 u8 light_switch; /* light sensor switch value */ 240 u16 event_count[128]; /* count for each event TODO make this better */ --- 112 unchanged lines hidden (view full) --- 353} 354 355static int asus_pega_lucid_set(struct asus_laptop *asus, int unit, bool enable) 356{ 357 char *method = enable ? METHOD_PEGA_ENABLE : METHOD_PEGA_DISABLE; 358 return write_acpi_int(asus->handle, method, unit); 359} 360 | 246 247 struct rfkill *gps_rfkill; 248 249 acpi_handle handle; /* the handle of the hotk device */ 250 u32 ledd_status; /* status of the LED display */ 251 u8 light_level; /* light sensor level */ 252 u8 light_switch; /* light sensor switch value */ 253 u16 event_count[128]; /* count for each event TODO make this better */ --- 112 unchanged lines hidden (view full) --- 366} 367 368static int asus_pega_lucid_set(struct asus_laptop *asus, int unit, bool enable) 369{ 370 char *method = enable ? METHOD_PEGA_ENABLE : METHOD_PEGA_DISABLE; 371 return write_acpi_int(asus->handle, method, unit); 372} 373 |
374static int pega_acc_axis(struct asus_laptop *asus, int curr, char *method) 375{ 376 int i, delta; 377 unsigned long long val; 378 for (i = 0; i < PEGA_ACC_RETRIES; i++) { 379 acpi_evaluate_integer(asus->handle, method, NULL, &val); 380 381 /* The output is noisy. From reading the ASL 382 * dissassembly, timeout errors are returned with 1's 383 * in the high word, and the lack of locking around 384 * thei hi/lo byte reads means that a transition 385 * between (for example) -1 and 0 could be read as 386 * 0xff00 or 0x00ff. */ 387 delta = abs(curr - (short)val); 388 if (delta < 128 && !(val & ~0xffff)) 389 break; 390 } 391 return clamp_val((short)val, -PEGA_ACC_CLAMP, PEGA_ACC_CLAMP); 392} 393 394static void pega_accel_poll(struct input_polled_dev *ipd) 395{ 396 struct device *parent = ipd->input->dev.parent; 397 struct asus_laptop *asus = dev_get_drvdata(parent); 398 399 /* In some cases, the very first call to poll causes a 400 * recursive fault under the polldev worker. This is 401 * apparently related to very early userspace access to the 402 * device, and perhaps a firmware bug. Fake the first report. */ 403 if (!asus->pega_acc_live) { 404 asus->pega_acc_live = true; 405 input_report_abs(ipd->input, ABS_X, 0); 406 input_report_abs(ipd->input, ABS_Y, 0); 407 input_report_abs(ipd->input, ABS_Z, 0); 408 input_sync(ipd->input); 409 return; 410 } 411 412 asus->pega_acc_x = pega_acc_axis(asus, asus->pega_acc_x, METHOD_XLRX); 413 asus->pega_acc_y = pega_acc_axis(asus, asus->pega_acc_y, METHOD_XLRY); 414 asus->pega_acc_z = pega_acc_axis(asus, asus->pega_acc_z, METHOD_XLRZ); 415 416 /* Note transform, convert to "right/up/out" in the native 417 * landscape orientation (i.e. the vector is the direction of 418 * "real up" in the device's cartiesian coordinates). */ 419 input_report_abs(ipd->input, ABS_X, -asus->pega_acc_x); 420 input_report_abs(ipd->input, ABS_Y, -asus->pega_acc_y); 421 input_report_abs(ipd->input, ABS_Z, asus->pega_acc_z); 422 input_sync(ipd->input); 423} 424 425static void pega_accel_exit(struct asus_laptop *asus) 426{ 427 if (asus->pega_accel_poll) { 428 input_unregister_polled_device(asus->pega_accel_poll); 429 input_free_polled_device(asus->pega_accel_poll); 430 } 431 asus->pega_accel_poll = NULL; 432} 433 434static int pega_accel_init(struct asus_laptop *asus) 435{ 436 int err; 437 struct input_polled_dev *ipd; 438 439 if (!asus->is_pega_lucid) 440 return -ENODEV; 441 442 if (acpi_check_handle(asus->handle, METHOD_XLRX, NULL) || 443 acpi_check_handle(asus->handle, METHOD_XLRY, NULL) || 444 acpi_check_handle(asus->handle, METHOD_XLRZ, NULL)) 445 return -ENODEV; 446 447 ipd = input_allocate_polled_device(); 448 if (!ipd) 449 return -ENOMEM; 450 451 ipd->poll = pega_accel_poll; 452 ipd->poll_interval = 125; 453 ipd->poll_interval_min = 50; 454 ipd->poll_interval_max = 2000; 455 456 ipd->input->name = PEGA_ACCEL_DESC; 457 ipd->input->phys = PEGA_ACCEL_NAME "/input0"; 458 ipd->input->dev.parent = &asus->platform_device->dev; 459 ipd->input->id.bustype = BUS_HOST; 460 461 set_bit(EV_ABS, ipd->input->evbit); 462 input_set_abs_params(ipd->input, ABS_X, 463 -PEGA_ACC_CLAMP, PEGA_ACC_CLAMP, 0, 0); 464 input_set_abs_params(ipd->input, ABS_Y, 465 -PEGA_ACC_CLAMP, PEGA_ACC_CLAMP, 0, 0); 466 input_set_abs_params(ipd->input, ABS_Z, 467 -PEGA_ACC_CLAMP, PEGA_ACC_CLAMP, 0, 0); 468 469 err = input_register_polled_device(ipd); 470 if (err) 471 goto exit; 472 473 asus->pega_accel_poll = ipd; 474 return 0; 475 476exit: 477 input_free_polled_device(ipd); 478 return err; 479} 480 |
|
361/* Generic LED function */ 362static int asus_led_set(struct asus_laptop *asus, const char *method, 363 int value) 364{ 365 if (!strcmp(method, METHOD_MLED)) 366 value = !value; 367 else if (!strcmp(method, METHOD_GLED)) 368 value = !value + 1; --- 974 unchanged lines hidden (view full) --- 1343 sysfs_remove_group(&asus->platform_device->dev.kobj, &asus_attr_group); 1344 platform_device_unregister(asus->platform_device); 1345} 1346 1347static struct platform_driver platform_driver = { 1348 .driver = { 1349 .name = ASUS_LAPTOP_FILE, 1350 .owner = THIS_MODULE, | 481/* Generic LED function */ 482static int asus_led_set(struct asus_laptop *asus, const char *method, 483 int value) 484{ 485 if (!strcmp(method, METHOD_MLED)) 486 value = !value; 487 else if (!strcmp(method, METHOD_GLED)) 488 value = !value + 1; --- 974 unchanged lines hidden (view full) --- 1463 sysfs_remove_group(&asus->platform_device->dev.kobj, &asus_attr_group); 1464 platform_device_unregister(asus->platform_device); 1465} 1466 1467static struct platform_driver platform_driver = { 1468 .driver = { 1469 .name = ASUS_LAPTOP_FILE, 1470 .owner = THIS_MODULE, |
1351 } | 1471 }, |
1352}; 1353 1354/* 1355 * This function is used to initialize the context with right values. In this 1356 * method, we can make all the detection we want, and modify the asus_laptop 1357 * struct 1358 */ 1359static int asus_laptop_get_info(struct asus_laptop *asus) --- 193 unchanged lines hidden (view full) --- 1553 result = asus_led_init(asus); 1554 if (result) 1555 goto fail_led; 1556 1557 result = asus_rfkill_init(asus); 1558 if (result) 1559 goto fail_rfkill; 1560 | 1472}; 1473 1474/* 1475 * This function is used to initialize the context with right values. In this 1476 * method, we can make all the detection we want, and modify the asus_laptop 1477 * struct 1478 */ 1479static int asus_laptop_get_info(struct asus_laptop *asus) --- 193 unchanged lines hidden (view full) --- 1673 result = asus_led_init(asus); 1674 if (result) 1675 goto fail_led; 1676 1677 result = asus_rfkill_init(asus); 1678 if (result) 1679 goto fail_rfkill; 1680 |
1681 result = pega_accel_init(asus); 1682 if (result && result != -ENODEV) 1683 goto fail_pega_accel; 1684 |
|
1561 asus_device_present = true; 1562 return 0; 1563 | 1685 asus_device_present = true; 1686 return 0; 1687 |
1688fail_pega_accel: 1689 asus_rfkill_exit(asus); |
|
1564fail_rfkill: 1565 asus_led_exit(asus); 1566fail_led: 1567 asus_input_exit(asus); 1568fail_input: 1569 asus_backlight_exit(asus); 1570fail_backlight: 1571 asus_platform_exit(asus); --- 7 unchanged lines hidden (view full) --- 1579static int asus_acpi_remove(struct acpi_device *device, int type) 1580{ 1581 struct asus_laptop *asus = acpi_driver_data(device); 1582 1583 asus_backlight_exit(asus); 1584 asus_rfkill_exit(asus); 1585 asus_led_exit(asus); 1586 asus_input_exit(asus); | 1690fail_rfkill: 1691 asus_led_exit(asus); 1692fail_led: 1693 asus_input_exit(asus); 1694fail_input: 1695 asus_backlight_exit(asus); 1696fail_backlight: 1697 asus_platform_exit(asus); --- 7 unchanged lines hidden (view full) --- 1705static int asus_acpi_remove(struct acpi_device *device, int type) 1706{ 1707 struct asus_laptop *asus = acpi_driver_data(device); 1708 1709 asus_backlight_exit(asus); 1710 asus_rfkill_exit(asus); 1711 asus_led_exit(asus); 1712 asus_input_exit(asus); |
1713 pega_accel_exit(asus); |
|
1587 asus_platform_exit(asus); 1588 1589 kfree(asus->name); 1590 kfree(asus); 1591 return 0; 1592} 1593 1594static const struct acpi_device_id asus_device_ids[] = { --- 51 unchanged lines hidden --- | 1714 asus_platform_exit(asus); 1715 1716 kfree(asus->name); 1717 kfree(asus); 1718 return 0; 1719} 1720 1721static const struct acpi_device_id asus_device_ids[] = { --- 51 unchanged lines hidden --- |