/*
 * MSI WMI hotkeys
 *
 * Copyright (C) 2009 Novell <trenn@suse.de>
 *
 * Most stuff taken over from hp-wmi
 *
 *  This program is free software; you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License as published by
 *  the Free Software Foundation; either version 2 of the License, or
 *  (at your option) any later version.
 *
 *  This program is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU General Public License for more details.
 *
 *  You should have received a copy of the GNU General Public License
 *  along with this program; if not, write to the Free Software
 *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 */

#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt

#include <linux/kernel.h>
#include <linux/input.h>
#include <linux/input/sparse-keymap.h>
#include <linux/acpi.h>
#include <linux/backlight.h>
#include <linux/slab.h>
#include <linux/module.h>
#include <acpi/video.h>

MODULE_AUTHOR("Thomas Renninger <trenn@suse.de>");
MODULE_DESCRIPTION("MSI laptop WMI hotkeys driver");
MODULE_LICENSE("GPL");

#define DRV_NAME "msi-wmi"

#define MSIWMI_BIOS_GUID "551A1F84-FBDD-4125-91DB-3EA8F44F1D45"
#define MSIWMI_MSI_EVENT_GUID "B6F3EEF2-3D2F-49DC-9DE3-85BCE18C62F2"
#define MSIWMI_WIND_EVENT_GUID "5B3CC38A-40D9-7245-8AE6-1145B751BE3F"

MODULE_ALIAS("wmi:" MSIWMI_BIOS_GUID);
MODULE_ALIAS("wmi:" MSIWMI_MSI_EVENT_GUID);
MODULE_ALIAS("wmi:" MSIWMI_WIND_EVENT_GUID);

enum msi_scancodes {
	/* Generic MSI keys (not present on MSI Wind) */
	MSI_KEY_BRIGHTNESSUP	= 0xD0,
	MSI_KEY_BRIGHTNESSDOWN,
	MSI_KEY_VOLUMEUP,
	MSI_KEY_VOLUMEDOWN,
	MSI_KEY_MUTE,
	/* MSI Wind keys */
	WIND_KEY_TOUCHPAD	= 0x08,	/* Fn+F3 touchpad toggle */
	WIND_KEY_BLUETOOTH	= 0x56,	/* Fn+F11 Bluetooth toggle */
	WIND_KEY_CAMERA,		/* Fn+F6 webcam toggle */
	WIND_KEY_WLAN		= 0x5f,	/* Fn+F11 Wi-Fi toggle */
	WIND_KEY_TURBO,			/* Fn+F10 turbo mode toggle */
	WIND_KEY_ECO		= 0x69,	/* Fn+F10 ECO mode toggle */
};
static struct key_entry msi_wmi_keymap[] = {
	{ KE_KEY, MSI_KEY_BRIGHTNESSUP,		{KEY_BRIGHTNESSUP} },
	{ KE_KEY, MSI_KEY_BRIGHTNESSDOWN,	{KEY_BRIGHTNESSDOWN} },
	{ KE_KEY, MSI_KEY_VOLUMEUP,		{KEY_VOLUMEUP} },
	{ KE_KEY, MSI_KEY_VOLUMEDOWN,		{KEY_VOLUMEDOWN} },
	{ KE_KEY, MSI_KEY_MUTE,			{KEY_MUTE} },

	/* These keys work without WMI. Ignore them to avoid double keycodes */
	{ KE_IGNORE, WIND_KEY_TOUCHPAD,		{KEY_TOUCHPAD_TOGGLE} },
	{ KE_IGNORE, WIND_KEY_BLUETOOTH,	{KEY_BLUETOOTH} },
	{ KE_IGNORE, WIND_KEY_CAMERA,		{KEY_CAMERA} },
	{ KE_IGNORE, WIND_KEY_WLAN,		{KEY_WLAN} },

	/* These are unknown WMI events found on MSI Wind */
	{ KE_IGNORE, 0x00 },
	{ KE_IGNORE, 0x62 },
	{ KE_IGNORE, 0x63 },

	/* These are MSI Wind keys that should be handled via WMI */
	{ KE_KEY, WIND_KEY_TURBO,		{KEY_PROG1} },
	{ KE_KEY, WIND_KEY_ECO,			{KEY_PROG2} },

	{ KE_END, 0 }
};

static ktime_t last_pressed;

static const struct {
	const char *guid;
	bool quirk_last_pressed;
} *event_wmi, event_wmis[] = {
	{ MSIWMI_MSI_EVENT_GUID, true },
	{ MSIWMI_WIND_EVENT_GUID, false },
};

static struct backlight_device *backlight;

static int backlight_map[] = { 0x00, 0x33, 0x66, 0x99, 0xCC, 0xFF };

static struct input_dev *msi_wmi_input_dev;

static int msi_wmi_query_block(int instance, int *ret)
{
	acpi_status status;
	union acpi_object *obj;

	struct acpi_buffer output = { ACPI_ALLOCATE_BUFFER, NULL };

	status = wmi_query_block(MSIWMI_BIOS_GUID, instance, &output);

	obj = output.pointer;

	if (!obj || obj->type != ACPI_TYPE_INTEGER) {
		if (obj) {
			pr_err("query block returned object "
			       "type: %d - buffer length:%d\n", obj->type,
			       obj->type == ACPI_TYPE_BUFFER ?
			       obj->buffer.length : 0);
		}
		kfree(obj);
		return -EINVAL;
	}
	*ret = obj->integer.value;
	kfree(obj);
	return 0;
}

static int msi_wmi_set_block(int instance, int value)
{
	acpi_status status;

	struct acpi_buffer input = { sizeof(int), &value };

	pr_debug("Going to set block of instance: %d - value: %d\n",
		 instance, value);

	status = wmi_set_block(MSIWMI_BIOS_GUID, instance, &input);

	return ACPI_SUCCESS(status) ? 0 : 1;
}

static int bl_get(struct backlight_device *bd)
{
	int level, err, ret;

	/* Instance 1 is "get backlight", cmp with DSDT */
	err = msi_wmi_query_block(1, &ret);
	if (err) {
		pr_err("Could not query backlight: %d\n", err);
		return -EINVAL;
	}
	pr_debug("Get: Query block returned: %d\n", ret);
	for (level = 0; level < ARRAY_SIZE(backlight_map); level++) {
		if (backlight_map[level] == ret) {
			pr_debug("Current backlight level: 0x%X - index: %d\n",
				 backlight_map[level], level);
			break;
		}
	}
	if (level == ARRAY_SIZE(backlight_map)) {
		pr_err("get: Invalid brightness value: 0x%X\n", ret);
		return -EINVAL;
	}
	return level;
}

static int bl_set_status(struct backlight_device *bd)
{
	int bright = bd->props.brightness;
	if (bright >= ARRAY_SIZE(backlight_map) || bright < 0)
		return -EINVAL;

	/* Instance 0 is "set backlight" */
	return msi_wmi_set_block(0, backlight_map[bright]);
}

static const struct backlight_ops msi_backlight_ops = {
	.get_brightness	= bl_get,
	.update_status	= bl_set_status,
};

static void msi_wmi_notify(u32 value, void *context)
{
	struct acpi_buffer response = { ACPI_ALLOCATE_BUFFER, NULL };
	struct key_entry *key;
	union acpi_object *obj;
	acpi_status status;

	status = wmi_get_event_data(value, &response);
	if (status != AE_OK) {
		pr_info("bad event status 0x%x\n", status);
		return;
	}

	obj = (union acpi_object *)response.pointer;

	if (obj && obj->type == ACPI_TYPE_INTEGER) {
		int eventcode = obj->integer.value;
		pr_debug("Eventcode: 0x%x\n", eventcode);
		key = sparse_keymap_entry_from_scancode(msi_wmi_input_dev,
				eventcode);
		if (!key) {
			pr_info("Unknown key pressed - %x\n", eventcode);
			goto msi_wmi_notify_exit;
		}

		if (event_wmi->quirk_last_pressed) {
			ktime_t cur = ktime_get_real();
			ktime_t diff = ktime_sub(cur, last_pressed);
			/* Ignore event if any event happened in a 50 ms
			   timeframe -> Key press may result in 10-20 GPEs */
			if (ktime_to_us(diff) < 1000 * 50) {
				pr_debug("Suppressed key event 0x%X - "
					 "Last press was %lld us ago\n",
					 key->code, ktime_to_us(diff));
				goto msi_wmi_notify_exit;
			}
			last_pressed = cur;
		}

		if (key->type == KE_KEY &&
		/* Brightness is served via acpi video driver */
		(backlight ||
		(key->code != MSI_KEY_BRIGHTNESSUP &&
		key->code != MSI_KEY_BRIGHTNESSDOWN))) {
			pr_debug("Send key: 0x%X - Input layer keycode: %d\n",
				 key->code, key->keycode);
			sparse_keymap_report_entry(msi_wmi_input_dev, key, 1,
						   true);
		}
	} else
		pr_info("Unknown event received\n");

msi_wmi_notify_exit:
	kfree(response.pointer);
}

static int __init msi_wmi_backlight_setup(void)
{
	int err;
	struct backlight_properties props;

	memset(&props, 0, sizeof(struct backlight_properties));
	props.type = BACKLIGHT_PLATFORM;
	props.max_brightness = ARRAY_SIZE(backlight_map) - 1;
	backlight = backlight_device_register(DRV_NAME, NULL, NULL,
					      &msi_backlight_ops,
					      &props);
	if (IS_ERR(backlight))
		return PTR_ERR(backlight);

	err = bl_get(NULL);
	if (err < 0) {
		backlight_device_unregister(backlight);
		return err;
	}

	backlight->props.brightness = err;

	return 0;
}

static int __init msi_wmi_input_setup(void)
{
	int err;

	msi_wmi_input_dev = input_allocate_device();
	if (!msi_wmi_input_dev)
		return -ENOMEM;

	msi_wmi_input_dev->name = "MSI WMI hotkeys";
	msi_wmi_input_dev->phys = "wmi/input0";
	msi_wmi_input_dev->id.bustype = BUS_HOST;

	err = sparse_keymap_setup(msi_wmi_input_dev, msi_wmi_keymap, NULL);
	if (err)
		goto err_free_dev;

	err = input_register_device(msi_wmi_input_dev);

	if (err)
		goto err_free_dev;

	last_pressed = 0;

	return 0;

err_free_dev:
	input_free_device(msi_wmi_input_dev);
	return err;
}

static int __init msi_wmi_init(void)
{
	int err;
	int i;

	for (i = 0; i < ARRAY_SIZE(event_wmis); i++) {
		if (!wmi_has_guid(event_wmis[i].guid))
			continue;

		err = msi_wmi_input_setup();
		if (err) {
			pr_err("Unable to setup input device\n");
			return err;
		}

		err = wmi_install_notify_handler(event_wmis[i].guid,
			msi_wmi_notify, NULL);
		if (ACPI_FAILURE(err)) {
			pr_err("Unable to setup WMI notify handler\n");
			goto err_free_input;
		}

		pr_debug("Event handler installed\n");
		event_wmi = &event_wmis[i];
		break;
	}

	if (wmi_has_guid(MSIWMI_BIOS_GUID) &&
	    acpi_video_get_backlight_type() == acpi_backlight_vendor) {
		err = msi_wmi_backlight_setup();
		if (err) {
			pr_err("Unable to setup backlight device\n");
			goto err_uninstall_handler;
		}
		pr_debug("Backlight device created\n");
	}

	if (!event_wmi && !backlight) {
		pr_err("This machine doesn't have neither MSI-hotkeys nor backlight through WMI\n");
		return -ENODEV;
	}

	return 0;

err_uninstall_handler:
	if (event_wmi)
		wmi_remove_notify_handler(event_wmi->guid);
err_free_input:
	if (event_wmi)
		input_unregister_device(msi_wmi_input_dev);
	return err;
}

static void __exit msi_wmi_exit(void)
{
	if (event_wmi) {
		wmi_remove_notify_handler(event_wmi->guid);
		input_unregister_device(msi_wmi_input_dev);
	}
	backlight_device_unregister(backlight);
}

module_init(msi_wmi_init);
module_exit(msi_wmi_exit);
