Esempio n. 1
0
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;
}
Esempio n. 2
0
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;
}
Esempio n. 3
0
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;
}
Esempio n. 4
0
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;
}
Esempio n. 5
0
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;
}
Esempio n. 6
0
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;
}
Esempio n. 7
0
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;
}
Esempio n. 8
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);
}
Esempio n. 9
0
/*
 * 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;
}
Esempio n. 10
0
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;
}