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 ---