// SPDX-License-Identifier: GPL-2.0
/*
 * ADC generic resistive touchscreen (GRTS)
 * This is a generic input driver that connects to an ADC
 * given the channels in device tree, and reports events to the input
 * subsystem.
 *
 * Copyright (C) 2017,2018 Microchip Technology,
 * Author: Eugen Hristev <eugen.hristev@microchip.com>
 *
 */
#include <linux/input.h>
#include <linux/input/touchscreen.h>
#include <linux/iio/consumer.h>
#include <linux/iio/iio.h>
#include <linux/module.h>
#include <linux/platform_device.h>
#include <linux/property.h>

#define DRIVER_NAME					"resistive-adc-touch"
#define GRTS_DEFAULT_PRESSURE_MIN			50000
#define GRTS_DEFAULT_PRESSURE_MAX			65535
#define GRTS_MAX_POS_MASK				GENMASK(11, 0)
#define GRTS_MAX_CHANNELS				4

enum grts_ch_type {
	GRTS_CH_X,
	GRTS_CH_Y,
	GRTS_CH_PRESSURE,
	GRTS_CH_Z1,
	GRTS_CH_Z2,
	GRTS_CH_MAX = GRTS_CH_Z2 + 1
};

/**
 * struct grts_state - generic resistive touch screen information struct
 * @x_plate_ohms:	resistance of the X plate
 * @pressure_min:	number representing the minimum for the pressure
 * @pressure:		are we getting pressure info or not
 * @iio_chans:		list of channels acquired
 * @iio_cb:		iio_callback buffer for the data
 * @input:		the input device structure that we register
 * @prop:		touchscreen properties struct
 * @ch_map:		map of channels that are defined for the touchscreen
 */
struct grts_state {
	u32				x_plate_ohms;
	u32				pressure_min;
	bool				pressure;
	struct iio_channel		*iio_chans;
	struct iio_cb_buffer		*iio_cb;
	struct input_dev		*input;
	struct touchscreen_properties	prop;
	u8				ch_map[GRTS_CH_MAX];
};

static int grts_cb(const void *data, void *private)
{
	const u16 *touch_info = data;
	struct grts_state *st = private;
	unsigned int x, y, press = 0;

	x = touch_info[st->ch_map[GRTS_CH_X]];
	y = touch_info[st->ch_map[GRTS_CH_Y]];

	if (st->ch_map[GRTS_CH_PRESSURE] < GRTS_MAX_CHANNELS) {
		press = touch_info[st->ch_map[GRTS_CH_PRESSURE]];
	} else if (st->ch_map[GRTS_CH_Z1] < GRTS_MAX_CHANNELS) {
		unsigned int z1 = touch_info[st->ch_map[GRTS_CH_Z1]];
		unsigned int z2 = touch_info[st->ch_map[GRTS_CH_Z2]];
		unsigned int Rt;

		if (likely(x && z1)) {
			Rt = z2;
			Rt -= z1;
			Rt *= st->x_plate_ohms;
			Rt = DIV_ROUND_CLOSEST(Rt, 16);
			Rt *= x;
			Rt /= z1;
			Rt = DIV_ROUND_CLOSEST(Rt, 256);
			/*
			 * On increased pressure the resistance (Rt) is
			 * decreasing so, convert values to make it looks as
			 * real pressure.
			 */
			if (Rt < GRTS_DEFAULT_PRESSURE_MAX)
				press = GRTS_DEFAULT_PRESSURE_MAX - Rt;
		}
	}

	if ((!x && !y) || (st->pressure && (press < st->pressure_min))) {
		/* report end of touch */
		input_report_key(st->input, BTN_TOUCH, 0);
		input_sync(st->input);
		return 0;
	}

	/* report proper touch to subsystem*/
	touchscreen_report_pos(st->input, &st->prop, x, y, false);
	if (st->pressure)
		input_report_abs(st->input, ABS_PRESSURE, press);
	input_report_key(st->input, BTN_TOUCH, 1);
	input_sync(st->input);

	return 0;
}

static int grts_open(struct input_dev *dev)
{
	int error;
	struct grts_state *st = input_get_drvdata(dev);

	error = iio_channel_start_all_cb(st->iio_cb);
	if (error) {
		dev_err(dev->dev.parent, "failed to start callback buffer.\n");
		return error;
	}
	return 0;
}

static void grts_close(struct input_dev *dev)
{
	struct grts_state *st = input_get_drvdata(dev);

	iio_channel_stop_all_cb(st->iio_cb);
}

static void grts_disable(void *data)
{
	iio_channel_release_all_cb(data);
}

static int grts_map_channel(struct grts_state *st, struct device *dev,
			    enum grts_ch_type type, const char *name,
			    bool optional)
{
	int idx;

	idx = device_property_match_string(dev, "io-channel-names", name);
	if (idx < 0) {
		if (!optional)
			return idx;
		idx = GRTS_MAX_CHANNELS;
	} else if (idx >= GRTS_MAX_CHANNELS) {
		return -EOVERFLOW;
	}

	st->ch_map[type] = idx;
	return 0;
}

static int grts_get_properties(struct grts_state *st, struct device *dev)
{
	int error;

	error = grts_map_channel(st, dev, GRTS_CH_X, "x", false);
	if (error)
		return error;

	error = grts_map_channel(st, dev, GRTS_CH_Y, "y", false);
	if (error)
		return error;

	/* pressure is optional */
	error = grts_map_channel(st, dev, GRTS_CH_PRESSURE, "pressure", true);
	if (error)
		return error;

	if (st->ch_map[GRTS_CH_PRESSURE] < GRTS_MAX_CHANNELS) {
		st->pressure = true;
		return 0;
	}

	/* if no pressure is defined, try optional z1 + z2 */
	error = grts_map_channel(st, dev, GRTS_CH_Z1, "z1", true);
	if (error)
		return error;

	if (st->ch_map[GRTS_CH_Z1] >= GRTS_MAX_CHANNELS)
		return 0;

	/* if z1 is provided z2 is not optional */
	error = grts_map_channel(st, dev, GRTS_CH_Z2, "z2", true);
	if (error)
		return error;

	error = device_property_read_u32(dev,
					 "touchscreen-x-plate-ohms",
					 &st->x_plate_ohms);
	if (error) {
		dev_err(dev, "can't get touchscreen-x-plate-ohms property\n");
		return error;
	}

	st->pressure = true;
	return 0;
}

static int grts_probe(struct platform_device *pdev)
{
	struct grts_state *st;
	struct input_dev *input;
	struct device *dev = &pdev->dev;
	int error;

	st = devm_kzalloc(dev, sizeof(struct grts_state), GFP_KERNEL);
	if (!st)
		return -ENOMEM;

	/* get the channels from IIO device */
	st->iio_chans = devm_iio_channel_get_all(dev);
	if (IS_ERR(st->iio_chans))
		return dev_err_probe(dev, PTR_ERR(st->iio_chans), "can't get iio channels\n");

	if (!device_property_present(dev, "io-channel-names"))
		return -ENODEV;

	error = grts_get_properties(st, dev);
	if (error) {
		dev_err(dev, "Failed to parse properties\n");
		return error;
	}

	if (st->pressure) {
		error = device_property_read_u32(dev,
						 "touchscreen-min-pressure",
						 &st->pressure_min);
		if (error) {
			dev_dbg(dev, "can't get touchscreen-min-pressure property.\n");
			st->pressure_min = GRTS_DEFAULT_PRESSURE_MIN;
		}
	}

	input = devm_input_allocate_device(dev);
	if (!input) {
		dev_err(dev, "failed to allocate input device.\n");
		return -ENOMEM;
	}

	input->name = DRIVER_NAME;
	input->id.bustype = BUS_HOST;
	input->open = grts_open;
	input->close = grts_close;

	input_set_abs_params(input, ABS_X, 0, GRTS_MAX_POS_MASK - 1, 0, 0);
	input_set_abs_params(input, ABS_Y, 0, GRTS_MAX_POS_MASK - 1, 0, 0);
	if (st->pressure)
		input_set_abs_params(input, ABS_PRESSURE, st->pressure_min,
				     GRTS_DEFAULT_PRESSURE_MAX, 0, 0);

	input_set_capability(input, EV_KEY, BTN_TOUCH);

	/* parse optional device tree properties */
	touchscreen_parse_properties(input, false, &st->prop);

	st->input = input;
	input_set_drvdata(input, st);

	error = input_register_device(input);
	if (error) {
		dev_err(dev, "failed to register input device.");
		return error;
	}

	st->iio_cb = iio_channel_get_all_cb(dev, grts_cb, st);
	if (IS_ERR(st->iio_cb)) {
		dev_err(dev, "failed to allocate callback buffer.\n");
		return PTR_ERR(st->iio_cb);
	}

	error = devm_add_action_or_reset(dev, grts_disable, st->iio_cb);
	if (error) {
		dev_err(dev, "failed to add disable action.\n");
		return error;
	}

	return 0;
}

static const struct of_device_id grts_of_match[] = {
	{
		.compatible = "resistive-adc-touch",
	}, {
		/* sentinel */
	},
};

MODULE_DEVICE_TABLE(of, grts_of_match);

static struct platform_driver grts_driver = {
	.probe = grts_probe,
	.driver = {
		.name = DRIVER_NAME,
		.of_match_table = grts_of_match,
	},
};

module_platform_driver(grts_driver);

MODULE_AUTHOR("Eugen Hristev <eugen.hristev@microchip.com>");
MODULE_DESCRIPTION("Generic ADC Resistive Touch Driver");
MODULE_LICENSE("GPL v2");
MODULE_IMPORT_NS("IIO_CONSUMER");
