/*
 * Synaptics DSX touchscreen driver
 *
 * Copyright (C) 2012-2016 Synaptics Incorporated. All rights reserved.
 *
 * Copyright (C) 2012 Alexandra Chin <alexandra.chin@tw.synaptics.com>
 * Copyright (C) 2012 Scott Lin <scott.lin@tw.synaptics.com>
 *
 * 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.
 *
 * INFORMATION CONTAINED IN THIS DOCUMENT IS PROVIDED "AS-IS," AND SYNAPTICS
 * EXPRESSLY DISCLAIMS ALL EXPRESS AND IMPLIED WARRANTIES, INCLUDING ANY
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE,
 * AND ANY WARRANTIES OF NON-INFRINGEMENT OF ANY INTELLECTUAL PROPERTY RIGHTS.
 * IN NO EVENT SHALL SYNAPTICS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 * SPECIAL, PUNITIVE, OR CONSEQUENTIAL DAMAGES ARISING OUT OF OR IN CONNECTION
 * WITH THE USE OF THE INFORMATION CONTAINED IN THIS DOCUMENT, HOWEVER CAUSED
 * AND BASED ON ANY THEORY OF LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
 * NEGLIGENCE OR OTHER TORTIOUS ACTION, AND EVEN IF SYNAPTICS WAS ADVISED OF
 * THE POSSIBILITY OF SUCH DAMAGE. IF A TRIBUNAL OF COMPETENT JURISDICTION DOES
 * NOT PERMIT THE DISCLAIMER OF DIRECT DAMAGES OR ANY OTHER DAMAGES, SYNAPTICS'
 * TOTAL CUMULATIVE LIABILITY TO ANY PARTY SHALL NOT EXCEED ONE HUNDRED U.S.
 * DOLLARS.
 */

#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/slab.h>
#include <linux/interrupt.h>
#include <linux/delay.h>
#include <linux/input.h>
#include <linux/platform_device.h>
#include <linux/input/synaptics_dsx.h>
#include "synaptics_dsx_core.h"

#define APEN_PHYS_NAME "synaptics_dsx/active_pen"

#define ACTIVE_PEN_MAX_PRESSURE_16BIT 65535
#define ACTIVE_PEN_MAX_PRESSURE_8BIT 255

struct synaptics_rmi4_f12_query_8 {
	union {
		struct {
			unsigned char size_of_query9;
			struct {
				unsigned char data0_is_present:1;
				unsigned char data1_is_present:1;
				unsigned char data2_is_present:1;
				unsigned char data3_is_present:1;
				unsigned char data4_is_present:1;
				unsigned char data5_is_present:1;
				unsigned char data6_is_present:1;
				unsigned char data7_is_present:1;
			} __packed;
		};
		unsigned char data[2];
	};
};

struct apen_data_8b_pressure {
	union {
		struct {
			unsigned char status_pen:1;
			unsigned char status_invert:1;
			unsigned char status_barrel:1;
			unsigned char status_reserved:5;
			unsigned char x_lsb;
			unsigned char x_msb;
			unsigned char y_lsb;
			unsigned char y_msb;
			unsigned char pressure_msb;
			unsigned char battery_state;
			unsigned char pen_id_0_7;
			unsigned char pen_id_8_15;
			unsigned char pen_id_16_23;
			unsigned char pen_id_24_31;
		} __packed;
		unsigned char data[11];
	};
};

struct apen_data {
	union {
		struct {
			unsigned char status_pen:1;
			unsigned char status_invert:1;
			unsigned char status_barrel:1;
			unsigned char status_reserved:5;
			unsigned char x_lsb;
			unsigned char x_msb;
			unsigned char y_lsb;
			unsigned char y_msb;
			unsigned char pressure_lsb;
			unsigned char pressure_msb;
			unsigned char battery_state;
			unsigned char pen_id_0_7;
			unsigned char pen_id_8_15;
			unsigned char pen_id_16_23;
			unsigned char pen_id_24_31;
		} __packed;
		unsigned char data[12];
	};
};

struct synaptics_rmi4_apen_handle {
	bool apen_present;
	unsigned char intr_mask;
	unsigned char battery_state;
	unsigned short query_base_addr;
	unsigned short control_base_addr;
	unsigned short data_base_addr;
	unsigned short command_base_addr;
	unsigned short apen_data_addr;
	unsigned short max_pressure;
	unsigned int pen_id;
	struct input_dev *apen_dev;
	struct apen_data *apen_data;
	struct synaptics_rmi4_data *rmi4_data;
};

static struct synaptics_rmi4_apen_handle *apen;

DECLARE_COMPLETION(apen_remove_complete);

static void apen_lift(void)
{
	input_report_key(apen->apen_dev, BTN_TOUCH, 0);
	input_report_key(apen->apen_dev, BTN_TOOL_PEN, 0);
	input_report_key(apen->apen_dev, BTN_TOOL_RUBBER, 0);
	input_sync(apen->apen_dev);
	apen->apen_present = false;
}

static void apen_report(void)
{
	int retval;
	int x;
	int y;
	int pressure;
	static int invert = -1;
	struct apen_data_8b_pressure *apen_data_8b;
	struct synaptics_rmi4_data *rmi4_data = apen->rmi4_data;

	retval = synaptics_rmi4_reg_read(rmi4_data,
			apen->apen_data_addr,
			apen->apen_data->data,
			sizeof(apen->apen_data->data));
	if (retval < 0) {
		dev_err(rmi4_data->pdev->dev.parent,
				"%s: Failed to read active pen data\n",
				__func__);
		return;
	}

	if (apen->apen_data->status_pen == 0) {
		if (apen->apen_present)
			apen_lift();

		dev_dbg(rmi4_data->pdev->dev.parent,
				"%s: No active pen data\n",
				__func__);

		return;
	}

	x = (apen->apen_data->x_msb << 8) | (apen->apen_data->x_lsb);
	y = (apen->apen_data->y_msb << 8) | (apen->apen_data->y_lsb);

	if ((x == -1) && (y == -1)) {
		if (apen->apen_present)
			apen_lift();

		dev_dbg(rmi4_data->pdev->dev.parent,
				"%s: Active pen in range but no valid x & y\n",
				__func__);

		return;
	}

	if (!apen->apen_present)
		invert = -1;

	if (invert != -1 && invert != apen->apen_data->status_invert)
		apen_lift();

	invert = apen->apen_data->status_invert;

	if (apen->max_pressure == ACTIVE_PEN_MAX_PRESSURE_16BIT) {
		pressure = (apen->apen_data->pressure_msb << 8) |
				apen->apen_data->pressure_lsb;
		apen->battery_state = apen->apen_data->battery_state;
		apen->pen_id = (apen->apen_data->pen_id_24_31 << 24) |
				(apen->apen_data->pen_id_16_23 << 16) |
				(apen->apen_data->pen_id_8_15 << 8) |
				apen->apen_data->pen_id_0_7;
	} else {
		apen_data_8b = (struct apen_data_8b_pressure *)apen->apen_data;
		pressure = apen_data_8b->pressure_msb;
		apen->battery_state = apen_data_8b->battery_state;
		apen->pen_id = (apen_data_8b->pen_id_24_31 << 24) |
				(apen_data_8b->pen_id_16_23 << 16) |
				(apen_data_8b->pen_id_8_15 << 8) |
				apen_data_8b->pen_id_0_7;
	}

	input_report_key(apen->apen_dev, BTN_TOUCH, pressure > 0 ? 1 : 0);
	input_report_key(apen->apen_dev,
			apen->apen_data->status_invert > 0 ?
			BTN_TOOL_RUBBER : BTN_TOOL_PEN, 1);
	input_report_key(apen->apen_dev,
			BTN_STYLUS, apen->apen_data->status_barrel > 0 ?
			1 : 0);
	input_report_abs(apen->apen_dev, ABS_X, x);
	input_report_abs(apen->apen_dev, ABS_Y, y);
	input_report_abs(apen->apen_dev, ABS_PRESSURE, pressure);

	input_sync(apen->apen_dev);

	dev_dbg(rmi4_data->pdev->dev.parent,
			"%s: Active pen: status = %d, invert = %d, barrel = %d, x = %d, y = %d, pressure = %d\n",
			__func__,
			apen->apen_data->status_pen,
			apen->apen_data->status_invert,
			apen->apen_data->status_barrel,
			x, y, pressure);

	apen->apen_present = true;
}

static void apen_set_params(void)
{
	input_set_abs_params(apen->apen_dev, ABS_X, 0,
			apen->rmi4_data->sensor_max_x, 0, 0);
	input_set_abs_params(apen->apen_dev, ABS_Y, 0,
			apen->rmi4_data->sensor_max_y, 0, 0);
	input_set_abs_params(apen->apen_dev, ABS_PRESSURE, 0,
			apen->max_pressure, 0, 0);

	return;
}

static int apen_pressure(struct synaptics_rmi4_f12_query_8 *query_8)
{
	int retval;
	unsigned char ii;
	unsigned char data_reg_presence;
	unsigned char size_of_query_9;
	unsigned char *query_9;
	unsigned char *data_desc;
	struct synaptics_rmi4_data *rmi4_data = apen->rmi4_data;

	data_reg_presence = query_8->data[1];

	size_of_query_9 = query_8->size_of_query9;
	query_9 = kmalloc(size_of_query_9, GFP_KERNEL);

	retval = synaptics_rmi4_reg_read(rmi4_data,
			apen->query_base_addr + 9,
			query_9,
			size_of_query_9);
	if (retval < 0)
		goto exit;

	data_desc = query_9;

	for (ii = 0; ii < 6; ii++) {
		if (!(data_reg_presence & (1 << ii)))
			continue; /* The data register is not present */
		data_desc++; /* Jump over the size entry */
		while (*data_desc & (1 << 7))
			data_desc++;
		data_desc++; /* Go to the next descriptor */
	}

	data_desc++; /* Jump over the size entry */
	/* Check for the presence of subpackets 1 and 2 */
	if ((*data_desc & (3 << 1)) == (3 << 1))
		apen->max_pressure = ACTIVE_PEN_MAX_PRESSURE_16BIT;
	else
		apen->max_pressure = ACTIVE_PEN_MAX_PRESSURE_8BIT;

exit:
	kfree(query_9);

	return retval;
}

static int apen_reg_init(void)
{
	int retval;
	unsigned char data_offset;
	unsigned char size_of_query8;
	struct synaptics_rmi4_f12_query_8 query_8;
	struct synaptics_rmi4_data *rmi4_data = apen->rmi4_data;

	retval = synaptics_rmi4_reg_read(rmi4_data,
			apen->query_base_addr + 7,
			&size_of_query8,
			sizeof(size_of_query8));
	if (retval < 0)
		return retval;

	retval = synaptics_rmi4_reg_read(rmi4_data,
			apen->query_base_addr + 8,
			query_8.data,
			sizeof(query_8.data));
	if (retval < 0)
		return retval;

	if ((size_of_query8 >= 2) && (query_8.data6_is_present)) {
		data_offset = query_8.data0_is_present +
				query_8.data1_is_present +
				query_8.data2_is_present +
				query_8.data3_is_present +
				query_8.data4_is_present +
				query_8.data5_is_present;
		apen->apen_data_addr = apen->data_base_addr + data_offset;
		retval = apen_pressure(&query_8);
		if (retval < 0)
			return retval;
	} else {
		dev_err(rmi4_data->pdev->dev.parent,
				"%s: Active pen support unavailable\n",
				__func__);
		retval = -ENODEV;
	}

	return retval;
}

static int apen_scan_pdt(void)
{
	int retval;
	unsigned char ii;
	unsigned char page;
	unsigned char intr_count = 0;
	unsigned char intr_off;
	unsigned char intr_src;
	unsigned short addr;
	struct synaptics_rmi4_fn_desc fd;
	struct synaptics_rmi4_data *rmi4_data = apen->rmi4_data;

	for (page = 0; page < PAGES_TO_SERVICE; page++) {
		for (addr = PDT_START; addr > PDT_END; addr -= PDT_ENTRY_SIZE) {
			addr |= (page << 8);

			retval = synaptics_rmi4_reg_read(rmi4_data,
					addr,
					(unsigned char *)&fd,
					sizeof(fd));
			if (retval < 0)
				return retval;

			addr &= ~(MASK_8BIT << 8);

			if (fd.fn_number) {
				dev_dbg(rmi4_data->pdev->dev.parent,
						"%s: Found F%02x\n",
						__func__, fd.fn_number);
				switch (fd.fn_number) {
				case SYNAPTICS_RMI4_F12:
					goto f12_found;
				}
			} else {
				break;
			}

			intr_count += fd.intr_src_count;
		}
	}

	dev_err(rmi4_data->pdev->dev.parent,
			"%s: Failed to find F12\n",
			__func__);
	return -EINVAL;

f12_found:
	apen->query_base_addr = fd.query_base_addr | (page << 8);
	apen->control_base_addr = fd.ctrl_base_addr | (page << 8);
	apen->data_base_addr = fd.data_base_addr | (page << 8);
	apen->command_base_addr = fd.cmd_base_addr | (page << 8);

	retval = apen_reg_init();
	if (retval < 0) {
		dev_err(rmi4_data->pdev->dev.parent,
				"%s: Failed to initialize active pen registers\n",
				__func__);
		return retval;
	}

	apen->intr_mask = 0;
	intr_src = fd.intr_src_count;
	intr_off = intr_count % 8;
	for (ii = intr_off;
			ii < (intr_src + intr_off);
			ii++) {
		apen->intr_mask |= 1 << ii;
	}

	rmi4_data->intr_mask[0] |= apen->intr_mask;

	addr = rmi4_data->f01_ctrl_base_addr + 1;

	retval = synaptics_rmi4_reg_write(rmi4_data,
			addr,
			&(rmi4_data->intr_mask[0]),
			sizeof(rmi4_data->intr_mask[0]));
	if (retval < 0) {
		dev_err(rmi4_data->pdev->dev.parent,
				"%s: Failed to set interrupt enable bit\n",
				__func__);
		return retval;
	}

	return 0;
}

static void synaptics_rmi4_apen_attn(struct synaptics_rmi4_data *rmi4_data,
		unsigned char intr_mask)
{
	if (!apen)
		return;

	if (apen->intr_mask & intr_mask)
		apen_report();

	return;
}

static int synaptics_rmi4_apen_init(struct synaptics_rmi4_data *rmi4_data)
{
	int retval;

	if (apen) {
		dev_dbg(rmi4_data->pdev->dev.parent,
				"%s: Handle already exists\n",
				__func__);
		return 0;
	}

	apen = kzalloc(sizeof(*apen), GFP_KERNEL);
	if (!apen) {
		dev_err(rmi4_data->pdev->dev.parent,
				"%s: Failed to alloc mem for apen\n",
				__func__);
		retval = -ENOMEM;
		goto exit;
	}

	apen->apen_data = kzalloc(sizeof(*(apen->apen_data)), GFP_KERNEL);
	if (!apen->apen_data) {
		dev_err(rmi4_data->pdev->dev.parent,
				"%s: Failed to alloc mem for apen_data\n",
				__func__);
		retval = -ENOMEM;
		goto exit_free_apen;
	}

	apen->rmi4_data = rmi4_data;

	retval = apen_scan_pdt();
	if (retval < 0)
		goto exit_free_apen_data;

	apen->apen_dev = input_allocate_device();
	if (apen->apen_dev == NULL) {
		dev_err(rmi4_data->pdev->dev.parent,
				"%s: Failed to allocate active pen device\n",
				__func__);
		retval = -ENOMEM;
		goto exit_free_apen_data;
	}

	apen->apen_dev->name = ACTIVE_PEN_DRIVER_NAME;
	apen->apen_dev->phys = APEN_PHYS_NAME;
	apen->apen_dev->id.product = SYNAPTICS_DSX_DRIVER_PRODUCT;
	apen->apen_dev->id.version = SYNAPTICS_DSX_DRIVER_VERSION;
	apen->apen_dev->dev.parent = rmi4_data->pdev->dev.parent;
	input_set_drvdata(apen->apen_dev, rmi4_data);

	set_bit(EV_KEY, apen->apen_dev->evbit);
	set_bit(EV_ABS, apen->apen_dev->evbit);
	set_bit(BTN_TOUCH, apen->apen_dev->keybit);
	set_bit(BTN_TOOL_PEN, apen->apen_dev->keybit);
	set_bit(BTN_TOOL_RUBBER, apen->apen_dev->keybit);
	set_bit(BTN_STYLUS, apen->apen_dev->keybit);
#ifdef INPUT_PROP_DIRECT
	set_bit(INPUT_PROP_DIRECT, apen->apen_dev->propbit);
#endif

	apen_set_params();

	retval = input_register_device(apen->apen_dev);
	if (retval) {
		dev_err(rmi4_data->pdev->dev.parent,
				"%s: Failed to register active pen device\n",
				__func__);
		goto exit_free_input_device;
	}

	return 0;

exit_free_input_device:
	input_free_device(apen->apen_dev);

exit_free_apen_data:
	kfree(apen->apen_data);

exit_free_apen:
	kfree(apen);
	apen = NULL;

exit:
	return retval;
}

static void synaptics_rmi4_apen_remove(struct synaptics_rmi4_data *rmi4_data)
{
	if (!apen)
		goto exit;

	input_unregister_device(apen->apen_dev);
	kfree(apen->apen_data);
	kfree(apen);
	apen = NULL;

exit:
	complete(&apen_remove_complete);
}

static void synaptics_rmi4_apen_reset(struct synaptics_rmi4_data *rmi4_data)
{
	if (!apen) {
		synaptics_rmi4_apen_init(rmi4_data);
		return;
	}

	apen_lift();

	apen_scan_pdt();
}

static void synaptics_rmi4_apen_reinit(struct synaptics_rmi4_data *rmi4_data)
{
	if (!apen)
		return;

	apen_lift();
}

static void synaptics_rmi4_apen_e_suspend(struct synaptics_rmi4_data *rmi4_data)
{
	if (!apen)
		return;

	apen_lift();
}

static void synaptics_rmi4_apen_suspend(struct synaptics_rmi4_data *rmi4_data)
{
	if (!apen)
		return;

	apen_lift();
}

static struct synaptics_rmi4_exp_fn active_pen_module = {
	.fn_type = RMI_ACTIVE_PEN,
	.init = synaptics_rmi4_apen_init,
	.remove = synaptics_rmi4_apen_remove,
	.reset = synaptics_rmi4_apen_reset,
	.reinit = synaptics_rmi4_apen_reinit,
	.early_suspend = synaptics_rmi4_apen_e_suspend,
	.suspend = synaptics_rmi4_apen_suspend,
	.resume = NULL,
	.late_resume = NULL,
	.attn = synaptics_rmi4_apen_attn,
};

static int __init rmi4_active_pen_module_init(void)
{
	synaptics_rmi4_new_function(&active_pen_module, true);

	return 0;
}

static void __exit rmi4_active_pen_module_exit(void)
{
	synaptics_rmi4_new_function(&active_pen_module, false);

	wait_for_completion(&apen_remove_complete);
}

module_init(rmi4_active_pen_module_init);
module_exit(rmi4_active_pen_module_exit);

MODULE_AUTHOR("Synaptics, Inc.");
MODULE_DESCRIPTION("Synaptics DSX Active Pen Module");
MODULE_LICENSE("GPL v2");
