// SPDX-License-Identifier: GPL-2.0-only
/*
 * Arizona haptics driver
 *
 * Copyright 2012 Wolfson Microelectronics plc
 *
 * Author: Mark Brown <broonie@opensource.wolfsonmicro.com>
 */

#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>");
