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

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

MODULE_ALIAS("wmi:551A1F84-FBDD-4125-91DB-3EA8F44F1D45");
MODULE_ALIAS("wmi:B6F3EEF2-3D2F-49DC-9DE3-85BCE18C62F2");

#define DRV_NAME "msi-wmi"

#define MSIWMI_BIOS_GUID "551A1F84-FBDD-4125-91DB-3EA8F44F1D45"
#define MSIWMI_EVENT_GUID "B6F3EEF2-3D2F-49DC-9DE3-85BCE18C62F2"

#define SCANCODE_BASE 0xD0
#define MSI_WMI_BRIGHTNESSUP   SCANCODE_BASE
#define MSI_WMI_BRIGHTNESSDOWN (SCANCODE_BASE + 1)
#define MSI_WMI_VOLUMEUP       (SCANCODE_BASE + 2)
#define MSI_WMI_VOLUMEDOWN     (SCANCODE_BASE + 3)
#define MSI_WMI_MUTE           (SCANCODE_BASE + 4)
static struct key_entry msi_wmi_keymap[] = {
	{ KE_KEY, MSI_WMI_BRIGHTNESSUP,   {KEY_BRIGHTNESSUP} },
	{ KE_KEY, MSI_WMI_BRIGHTNESSDOWN, {KEY_BRIGHTNESSDOWN} },
	{ KE_KEY, MSI_WMI_VOLUMEUP,       {KEY_VOLUMEUP} },
	{ KE_KEY, MSI_WMI_VOLUMEDOWN,     {KEY_VOLUMEDOWN} },
	{ KE_KEY, MSI_WMI_MUTE,           {KEY_MUTE} },
	{ KE_END, 0}
};
static ktime_t last_pressed[ARRAY_SIZE(msi_wmi_keymap) - 1];

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 };
	static struct key_entry *key;
	union acpi_object *obj;
	ktime_t cur;
	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) {
			ktime_t diff;
			cur = ktime_get_real();
			diff = ktime_sub(cur, last_pressed[key->code -
					SCANCODE_BASE]);
			/* Ignore event if the same 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));
				return;
			}
			last_pressed[key->code - SCANCODE_BASE] = cur;

			if (key->type == KE_KEY &&
			/* Brightness is served via acpi video driver */
			(!acpi_video_backlight_support() ||
			(key->code != MSI_WMI_BRIGHTNESSUP &&
			key->code != MSI_WMI_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 key pressed - %x\n", eventcode);
	} else
		pr_info("Unknown event received\n");
	kfree(response.pointer);
}

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

	memset(last_pressed, 0, sizeof(last_pressed));

	return 0;

err_free_keymap:
	sparse_keymap_free(msi_wmi_input_dev);
err_free_dev:
	input_free_device(msi_wmi_input_dev);
	return err;
}

static int __init msi_wmi_init(void)
{
	int err;

	if (!wmi_has_guid(MSIWMI_EVENT_GUID)) {
		pr_err("This machine doesn't have MSI-hotkeys through WMI\n");
		return -ENODEV;
	}
	err = wmi_install_notify_handler(MSIWMI_EVENT_GUID,
			msi_wmi_notify, NULL);
	if (ACPI_FAILURE(err))
		return -EINVAL;

	err = msi_wmi_input_setup();
	if (err)
		goto err_uninstall_notifier;

	if (!acpi_video_backlight_support()) {
		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)) {
			err = PTR_ERR(backlight);
			goto err_free_input;
		}

		err = bl_get(NULL);
		if (err < 0)
			goto err_free_backlight;

		backlight->props.brightness = err;
	}
	pr_debug("Event handler installed\n");

	return 0;

err_free_backlight:
	backlight_device_unregister(backlight);
err_free_input:
	sparse_keymap_free(msi_wmi_input_dev);
	input_unregister_device(msi_wmi_input_dev);
err_uninstall_notifier:
	wmi_remove_notify_handler(MSIWMI_EVENT_GUID);
	return err;
}

static void __exit msi_wmi_exit(void)
{
	if (wmi_has_guid(MSIWMI_EVENT_GUID)) {
		wmi_remove_notify_handler(MSIWMI_EVENT_GUID);
		sparse_keymap_free(msi_wmi_input_dev);
		input_unregister_device(msi_wmi_input_dev);
		backlight_device_unregister(backlight);
	}
}

module_init(msi_wmi_init);
module_exit(msi_wmi_exit);
