/*
 * Arizona haptics driver
 *
 * Copyright 2012 Wolfson Microelectronics plc
 *
 * Author: Mark Brown <broonie@opensource.wolfsonmicro.com>
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License version 2 as
 * published by the Free Software Foundation.
 */

#include <linux/module.h>
#include <linux/platform_device.h>
#include <linux/input.h>
#include <linux/slab.h>

#include <sound/soc.h>
#include <sound/soc-dapm.h>

#include <linux/mfd/arizona/core.h>
#include <linux/mfd/arizona/pdata.h>
#include <linux/mfd/arizona/registers.h>

struct arizona_haptics {
	struct arizona *arizona;
	struct input_dev *input_dev;
	struct work_struct work;

	struct mutex mutex;
	u8 intensity;
};

static void arizona_haptics_work(struct work_struct *work)
{
	struct arizona_haptics *haptics = container_of(work,
						       struct arizona_haptics,
						       work);
	struct arizona *arizona = haptics->arizona;
	struct snd_soc_component *component =
		snd_soc_dapm_to_component(arizona->dapm);
	int ret;

	if (!haptics->arizona->dapm) {
		dev_err(arizona->dev, "No DAPM context\n");
		return;
	}

	if (haptics->intensity) {
		ret = regmap_update_bits(arizona->regmap,
					 ARIZONA_HAPTICS_PHASE_2_INTENSITY,
					 ARIZONA_PHASE2_INTENSITY_MASK,
					 haptics->intensity);
		if (ret != 0) {
			dev_err(arizona->dev, "Failed to set intensity: %d\n",
				ret);
			return;
		}

		/* This enable sequence will be a noop if already enabled */
		ret = regmap_update_bits(arizona->regmap,
					 ARIZONA_HAPTICS_CONTROL_1,
					 ARIZONA_HAP_CTRL_MASK,
					 1 << ARIZONA_HAP_CTRL_SHIFT);
		if (ret != 0) {
			dev_err(arizona->dev, "Failed to start haptics: %d\n",
				ret);
			return;
		}

		ret = snd_soc_component_enable_pin(component, "HAPTICS");
		if (ret != 0) {
			dev_err(arizona->dev, "Failed to start HAPTICS: %d\n",
				ret);
			return;
		}

		ret = snd_soc_dapm_sync(arizona->dapm);
		if (ret != 0) {
			dev_err(arizona->dev, "Failed to sync DAPM: %d\n",
				ret);
			return;
		}
	} else {
		/* This disable sequence will be a noop if already enabled */
		ret = snd_soc_component_disable_pin(component, "HAPTICS");
		if (ret != 0) {
			dev_err(arizona->dev, "Failed to disable HAPTICS: %d\n",
				ret);
			return;
		}

		ret = snd_soc_dapm_sync(arizona->dapm);
		if (ret != 0) {
			dev_err(arizona->dev, "Failed to sync DAPM: %d\n",
				ret);
			return;
		}

		ret = regmap_update_bits(arizona->regmap,
					 ARIZONA_HAPTICS_CONTROL_1,
					 ARIZONA_HAP_CTRL_MASK, 0);
		if (ret != 0) {
			dev_err(arizona->dev, "Failed to stop haptics: %d\n",
				ret);
			return;
		}
	}
}

static int arizona_haptics_play(struct input_dev *input, void *data,
				struct ff_effect *effect)
{
	struct arizona_haptics *haptics = input_get_drvdata(input);
	struct arizona *arizona = haptics->arizona;

	if (!arizona->dapm) {
		dev_err(arizona->dev, "No DAPM context\n");
		return -EBUSY;
	}

	if (effect->u.rumble.strong_magnitude) {
		/* Scale the magnitude into the range the device supports */
		if (arizona->pdata.hap_act) {
			haptics->intensity =
				effect->u.rumble.strong_magnitude >> 9;
			if (effect->direction < 0x8000)
				haptics->intensity += 0x7f;
		} else {
			haptics->intensity =
				effect->u.rumble.strong_magnitude >> 8;
		}
	} else {
		haptics->intensity = 0;
	}

	schedule_work(&haptics->work);

	return 0;
}

static void arizona_haptics_close(struct input_dev *input)
{
	struct arizona_haptics *haptics = input_get_drvdata(input);
	struct snd_soc_component *component;

	cancel_work_sync(&haptics->work);

	if (haptics->arizona->dapm) {
		component = snd_soc_dapm_to_component(haptics->arizona->dapm);
		snd_soc_component_disable_pin(component, "HAPTICS");
	}
}

static int arizona_haptics_probe(struct platform_device *pdev)
{
	struct arizona *arizona = dev_get_drvdata(pdev->dev.parent);
	struct arizona_haptics *haptics;
	int ret;

	haptics = devm_kzalloc(&pdev->dev, sizeof(*haptics), GFP_KERNEL);
	if (!haptics)
		return -ENOMEM;

	haptics->arizona = arizona;

	ret = regmap_update_bits(arizona->regmap, ARIZONA_HAPTICS_CONTROL_1,
				 ARIZONA_HAP_ACT, arizona->pdata.hap_act);
	if (ret != 0) {
		dev_err(arizona->dev, "Failed to set haptics actuator: %d\n",
			ret);
		return ret;
	}

	INIT_WORK(&haptics->work, arizona_haptics_work);

	haptics->input_dev = devm_input_allocate_device(&pdev->dev);
	if (!haptics->input_dev) {
		dev_err(arizona->dev, "Failed to allocate input device\n");
		return -ENOMEM;
	}

	input_set_drvdata(haptics->input_dev, haptics);

	haptics->input_dev->name = "arizona:haptics";
	haptics->input_dev->close = arizona_haptics_close;
	__set_bit(FF_RUMBLE, haptics->input_dev->ffbit);

	ret = input_ff_create_memless(haptics->input_dev, NULL,
				      arizona_haptics_play);
	if (ret < 0) {
		dev_err(arizona->dev, "input_ff_create_memless() failed: %d\n",
			ret);
		return ret;
	}

	ret = input_register_device(haptics->input_dev);
	if (ret < 0) {
		dev_err(arizona->dev, "couldn't register input device: %d\n",
			ret);
		return ret;
	}

	return 0;
}

static struct platform_driver arizona_haptics_driver = {
	.probe		= arizona_haptics_probe,
	.driver		= {
		.name	= "arizona-haptics",
	},
};
module_platform_driver(arizona_haptics_driver);

MODULE_ALIAS("platform:arizona-haptics");
MODULE_DESCRIPTION("Arizona haptics driver");
MODULE_LICENSE("GPL");
MODULE_AUTHOR("Mark Brown <broonie@opensource.wolfsonmicro.com>");
