static int asus_led_init(struct asus_laptop *asus) { int r; /* * Functions that actually update the LED's are called from a * workqueue. By doing this as separate work rather than when the LED * subsystem asks, we avoid messing with the Asus ACPI stuff during a * potentially bad time, such as a timer interrupt. */ asus->led_workqueue = create_singlethread_workqueue("led_workqueue"); if (!asus->led_workqueue) return -ENOMEM; r = asus_led_register(asus, &asus->mled, "asus::mail", METHOD_MLED); if (r) goto error; r = asus_led_register(asus, &asus->tled, "asus::touchpad", METHOD_TLED); if (r) goto error; r = asus_led_register(asus, &asus->rled, "asus::record", METHOD_RLED); if (r) goto error; r = asus_led_register(asus, &asus->pled, "asus::phone", METHOD_PLED); if (r) goto error; r = asus_led_register(asus, &asus->gled, "asus::gaming", METHOD_GLED); if (r) goto error; if (!acpi_check_handle(asus->handle, METHOD_KBD_LIGHT_SET, NULL) && !acpi_check_handle(asus->handle, METHOD_KBD_LIGHT_GET, NULL)) { struct asus_led *led = &asus->kled; struct led_classdev *cdev = &led->led; led->asus = asus; INIT_WORK(&led->work, asus_kled_cdev_update); cdev->name = "asus::kbd_backlight"; cdev->brightness_set = asus_kled_cdev_set; cdev->brightness_get = asus_kled_cdev_get; cdev->max_brightness = 3; r = led_classdev_register(&asus->platform_device->dev, cdev); } error: if (r) asus_led_exit(asus); return r; }
static int asus_sysfs_init(struct asus_laptop *asus) { struct platform_device *device = asus->platform_device; int err; err = device_create_file(&device->dev, &dev_attr_infos); if (err) return err; if (!acpi_check_handle(asus->handle, METHOD_WLAN, NULL)) { err = device_create_file(&device->dev, &dev_attr_wlan); if (err) return err; } if (!acpi_check_handle(asus->handle, METHOD_BLUETOOTH, NULL)) { err = device_create_file(&device->dev, &dev_attr_bluetooth); if (err) return err; } if (!acpi_check_handle(asus->handle, METHOD_SWITCH_DISPLAY, NULL)) { err = device_create_file(&device->dev, &dev_attr_display); if (err) return err; } if (!acpi_check_handle(asus->handle, METHOD_LEDD, NULL)) { err = device_create_file(&device->dev, &dev_attr_ledd); if (err) return err; } if (!acpi_check_handle(asus->handle, METHOD_ALS_CONTROL, NULL) && !acpi_check_handle(asus->handle, METHOD_ALS_LEVEL, NULL)) { err = device_create_file(&device->dev, &dev_attr_ls_switch); if (err) return err; err = device_create_file(&device->dev, &dev_attr_ls_level); if (err) return err; } if (!acpi_check_handle(asus->handle, METHOD_GPS_ON, NULL) && !acpi_check_handle(asus->handle, METHOD_GPS_OFF, NULL) && !acpi_check_handle(asus->handle, METHOD_GPS_STATUS, NULL)) { err = device_create_file(&device->dev, &dev_attr_gps); if (err) return err; } return err; }
static int pega_accel_init(struct asus_laptop *asus) { int err; struct input_polled_dev *ipd; if (!asus->is_pega_lucid) return -ENODEV; if (acpi_check_handle(asus->handle, METHOD_XLRX, NULL) || acpi_check_handle(asus->handle, METHOD_XLRY, NULL) || acpi_check_handle(asus->handle, METHOD_XLRZ, NULL)) return -ENODEV; ipd = input_allocate_polled_device(); if (!ipd) return -ENOMEM; ipd->poll = pega_accel_poll; ipd->poll_interval = 125; ipd->poll_interval_min = 50; ipd->poll_interval_max = 2000; ipd->input->name = PEGA_ACCEL_DESC; ipd->input->phys = PEGA_ACCEL_NAME "/input0"; ipd->input->dev.parent = &asus->platform_device->dev; ipd->input->id.bustype = BUS_HOST; set_bit(EV_ABS, ipd->input->evbit); input_set_abs_params(ipd->input, ABS_X, -PEGA_ACC_CLAMP, PEGA_ACC_CLAMP, 0, 0); input_set_abs_params(ipd->input, ABS_Y, -PEGA_ACC_CLAMP, PEGA_ACC_CLAMP, 0, 0); input_set_abs_params(ipd->input, ABS_Z, -PEGA_ACC_CLAMP, PEGA_ACC_CLAMP, 0, 0); err = input_register_polled_device(ipd); if (err) goto exit; asus->pega_accel_poll = ipd; return 0; exit: input_free_polled_device(ipd); return err; }
static int __devinit asus_acpi_init(struct asus_laptop *asus) { int result = 0; result = acpi_bus_get_status(asus->device); if (result) return result; if (!asus->device->status.present) { pr_err("Hotkey device not present, aborting\n"); return -ENODEV; } result = asus_laptop_get_info(asus); if (result) return result; /* WLED and BLED are on by default */ if (bluetooth_status >= 0) asus_bluetooth_set(asus, !!bluetooth_status); if (wlan_status >= 0) asus_wlan_set(asus, !!wlan_status); /* Keyboard Backlight is on by default */ if (!acpi_check_handle(asus->handle, METHOD_KBD_LIGHT_SET, NULL)) asus_kled_set(asus, 1); /* LED display is off by default */ asus->ledd_status = 0xFFF; /* Set initial values of light sensor and level */ asus->light_switch = 0; /* Default to light sensor disabled */ asus->light_level = 5; /* level 5 for sensor sensitivity */ if (!acpi_check_handle(asus->handle, METHOD_ALS_CONTROL, NULL) && !acpi_check_handle(asus->handle, METHOD_ALS_LEVEL, NULL)) { asus_als_switch(asus, asus->light_switch); asus_als_level(asus, asus->light_level); } asus->lcd_state = 1; /* LCD should be on when the module load */ return result; }
static int asus_rfkill_init(struct asus_laptop *asus) { int result = 0; if (asus->is_pega_lucid) return -ENODEV; if (!acpi_check_handle(asus->handle, METHOD_GPS_ON, NULL) && !acpi_check_handle(asus->handle, METHOD_GPS_OFF, NULL) && !acpi_check_handle(asus->handle, METHOD_GPS_STATUS, NULL)) result = asus_rfkill_setup(asus, &asus->gps, "asus-gps", -1, RFKILL_TYPE_GPS, &asus_gps_rfkill_ops); if (result) goto exit; if (!acpi_check_handle(asus->handle, METHOD_WLAN, NULL) && asus->wled_type == TYPE_RFKILL) result = asus_rfkill_setup(asus, &asus->wlan, "asus-wlan", WL_RSTS, RFKILL_TYPE_WLAN, &asus_rfkill_ops); if (result) goto exit; if (!acpi_check_handle(asus->handle, METHOD_BLUETOOTH, NULL) && asus->bled_type == TYPE_RFKILL) result = asus_rfkill_setup(asus, &asus->bluetooth, "asus-bluetooth", BT_RSTS, RFKILL_TYPE_BLUETOOTH, &asus_rfkill_ops); if (result) goto exit; if (!acpi_check_handle(asus->handle, METHOD_WWAN, NULL)) result = asus_rfkill_setup(asus, &asus->wwan, "asus-wwan", WW_RSTS, RFKILL_TYPE_WWAN, &asus_rfkill_ops); if (result) goto exit; if (!acpi_check_handle(asus->handle, METHOD_WIMAX, NULL)) result = asus_rfkill_setup(asus, &asus->wimax, "asus-wimax", WM_RSTS, RFKILL_TYPE_WIMAX, &asus_rfkill_ops); if (result) goto exit; exit: if (result) asus_rfkill_exit(asus); return result; }
static int asus_rfkill_init(struct asus_laptop *asus) { int result; if (acpi_check_handle(asus->handle, METHOD_GPS_ON, NULL) || acpi_check_handle(asus->handle, METHOD_GPS_OFF, NULL) || acpi_check_handle(asus->handle, METHOD_GPS_STATUS, NULL)) return 0; asus->gps_rfkill = rfkill_alloc("asus-gps", &asus->platform_device->dev, RFKILL_TYPE_GPS, &asus_gps_rfkill_ops, asus); if (!asus->gps_rfkill) return -EINVAL; result = rfkill_register(asus->gps_rfkill); if (result) { rfkill_destroy(asus->gps_rfkill); asus->gps_rfkill = NULL; } return result; }
static mode_t asus_sysfs_is_visible(struct kobject *kobj, struct attribute *attr, int idx) { struct device *dev = container_of(kobj, struct device, kobj); struct platform_device *pdev = to_platform_device(dev); struct asus_laptop *asus = platform_get_drvdata(pdev); acpi_handle handle = asus->handle; bool supported; if (attr == &dev_attr_wlan.attr) { supported = !acpi_check_handle(handle, METHOD_WLAN, NULL); } else if (attr == &dev_attr_bluetooth.attr) { supported = !acpi_check_handle(handle, METHOD_BLUETOOTH, NULL); } else if (attr == &dev_attr_display.attr) { supported = !acpi_check_handle(handle, METHOD_SWITCH_DISPLAY, NULL); } else if (attr == &dev_attr_ledd.attr) { supported = !acpi_check_handle(handle, METHOD_LEDD, NULL); } else if (attr == &dev_attr_ls_switch.attr || attr == &dev_attr_ls_level.attr) { supported = !acpi_check_handle(handle, METHOD_ALS_CONTROL, NULL) && !acpi_check_handle(handle, METHOD_ALS_LEVEL, NULL); } else if (attr == &dev_attr_gps.attr) { supported = !acpi_check_handle(handle, METHOD_GPS_ON, NULL) && !acpi_check_handle(handle, METHOD_GPS_OFF, NULL) && !acpi_check_handle(handle, METHOD_GPS_STATUS, NULL); } else { supported = true; } return supported ? attr->mode : 0; }
/* Ugly macro, need to fix that later */ static int asus_led_register(struct asus_laptop *asus, struct asus_led *led, const char *name, const char *method) { struct led_classdev *led_cdev = &led->led; if (!method || acpi_check_handle(asus->handle, method, NULL)) return 0; /* Led not present */ led->asus = asus; led->method = method; INIT_WORK(&led->work, asus_led_cdev_update); led_cdev->name = name; led_cdev->brightness_set = asus_led_cdev_set; led_cdev->brightness_get = asus_led_cdev_get; led_cdev->max_brightness = 1; return led_classdev_register(&asus->platform_device->dev, led_cdev); }
/* * This function is used to initialize the context with right values. In this * method, we can make all the detection we want, and modify the asus_laptop * struct */ static int asus_laptop_get_info(struct asus_laptop *asus) { struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL }; union acpi_object *model = NULL; unsigned long long bsts_result, hwrs_result; char *string = NULL; acpi_status status; /* * Get DSDT headers early enough to allow for differentiating between * models, but late enough to allow acpi_bus_register_driver() to fail * before doing anything ACPI-specific. Should we encounter a machine, * which needs special handling (i.e. its hotkey device has a different * HID), this bit will be moved. */ status = acpi_get_table(ACPI_SIG_DSDT, 1, &asus->dsdt_info); if (ACPI_FAILURE(status)) pr_warning("Couldn't get the DSDT table header\n"); /* We have to write 0 on init this far for all ASUS models */ if (write_acpi_int_ret(asus->handle, "INIT", 0, &buffer)) { pr_err("Hotkey initialization failed\n"); return -ENODEV; } /* This needs to be called for some laptops to init properly */ status = acpi_evaluate_integer(asus->handle, "BSTS", NULL, &bsts_result); if (ACPI_FAILURE(status)) pr_warning("Error calling BSTS\n"); else if (bsts_result) pr_notice("BSTS called, 0x%02x returned\n", (uint) bsts_result); /* This too ... */ if (write_acpi_int(asus->handle, "CWAP", wapf)) pr_err("Error calling CWAP(%d)\n", wapf); /* * Try to match the object returned by INIT to the specific model. * Handle every possible object (or the lack of thereof) the DSDT * writers might throw at us. When in trouble, we pass NULL to * asus_model_match() and try something completely different. */ if (buffer.pointer) { model = buffer.pointer; switch (model->type) { case ACPI_TYPE_STRING: string = model->string.pointer; break; case ACPI_TYPE_BUFFER: string = model->buffer.pointer; break; default: string = ""; break; } } asus->name = kstrdup(string, GFP_KERNEL); if (!asus->name) { kfree(buffer.pointer); return -ENOMEM; } if (*string) pr_notice(" %s model detected\n", string); /* * The HWRS method return informations about the hardware. * 0x80 bit is for WLAN, 0x100 for Bluetooth. * The significance of others is yet to be found. */ status = acpi_evaluate_integer(asus->handle, "HRWS", NULL, &hwrs_result); if (!ACPI_FAILURE(status)) pr_notice(" HRWS returned %x", (int)hwrs_result); if (!acpi_check_handle(asus->handle, METHOD_WL_STATUS, NULL)) asus->have_rsts = true; /* Scheduled for removal */ ASUS_HANDLE_INIT(lcd_switch); ASUS_HANDLE_INIT(display_get); kfree(model); return AE_OK; }
static int asus_laptop_get_info(struct asus_laptop *asus) { struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL }; union acpi_object *model = NULL; unsigned long long bsts_result, hwrs_result; char *string = NULL; acpi_status status; status = acpi_get_table(ACPI_SIG_DSDT, 1, &asus->dsdt_info); if (ACPI_FAILURE(status)) pr_warn("Couldn't get the DSDT table header\n"); if (write_acpi_int_ret(asus->handle, "INIT", 0, &buffer)) { pr_err("Hotkey initialization failed\n"); return -ENODEV; } status = acpi_evaluate_integer(asus->handle, "BSTS", NULL, &bsts_result); if (ACPI_FAILURE(status)) pr_warn("Error calling BSTS\n"); else if (bsts_result) pr_notice("BSTS called, 0x%02x returned\n", (uint) bsts_result); if (write_acpi_int(asus->handle, "CWAP", wapf)) pr_err("Error calling CWAP(%d)\n", wapf); if (buffer.pointer) { model = buffer.pointer; switch (model->type) { case ACPI_TYPE_STRING: string = model->string.pointer; break; case ACPI_TYPE_BUFFER: string = model->buffer.pointer; break; default: string = ""; break; } } asus->name = kstrdup(string, GFP_KERNEL); if (!asus->name) { kfree(buffer.pointer); return -ENOMEM; } if (*string) pr_notice(" %s model detected\n", string); status = acpi_evaluate_integer(asus->handle, "HWRS", NULL, &hwrs_result); if (!ACPI_FAILURE(status)) pr_notice(" HWRS returned %x", (int)hwrs_result); if (!acpi_check_handle(asus->handle, METHOD_WL_STATUS, NULL)) asus->have_rsts = true; kfree(model); return AE_OK; }