// SPDX-License-Identifier: GPL-2.0-only
/*
 * GPIO driven charlieplex keypad driver
 *
 * Copyright (c) 2026 Hugo Villeneuve <hvilleneuve@dimonoff.com>
 *
 * Based on matrix_keyboard.c
 */

#include <linux/bitops.h>
#include <linux/delay.h>
#include <linux/dev_printk.h>
#include <linux/device/devres.h>
#include <linux/err.h>
#include <linux/gpio/consumer.h>
#include <linux/input.h>
#include <linux/input/matrix_keypad.h>
#include <linux/math.h>
#include <linux/module.h>
#include <linux/mod_devicetable.h>
#include <linux/platform_device.h>
#include <linux/property.h>
#include <linux/string_helpers.h>
#include <linux/types.h>

struct charlieplex_keypad {
	struct input_dev *input_dev;
	struct gpio_descs *line_gpios;
	unsigned int nlines;
	unsigned int settling_time_us;
	unsigned int debounce_threshold;
	unsigned int debounce_count;
	int debounce_code;
	int current_code;
};

static void charlieplex_keypad_report_key(struct input_dev *input)
{
	struct charlieplex_keypad *keypad = input_get_drvdata(input);
	const unsigned short *keycodes = input->keycode;

	if (keypad->current_code > 0) {
		input_event(input, EV_MSC, MSC_SCAN, keypad->current_code);
		input_report_key(input, keycodes[keypad->current_code], 0);
		input_sync(input);
	}

	if (keypad->debounce_code) {
		input_event(input, EV_MSC, MSC_SCAN, keypad->debounce_code);
		input_report_key(input, keycodes[keypad->debounce_code], 1);
		input_sync(input);
	}

	keypad->current_code = keypad->debounce_code;
}

static void charlieplex_keypad_check_switch_change(struct input_dev *input,
						   unsigned int code)
{
	struct charlieplex_keypad *keypad = input_get_drvdata(input);

	if (code != keypad->debounce_code) {
		keypad->debounce_count = 0;
		keypad->debounce_code = code;
	}

	if (keypad->debounce_code != keypad->current_code) {
		if (keypad->debounce_count++ >= keypad->debounce_threshold)
			charlieplex_keypad_report_key(input);
	}
}

static int charlieplex_keypad_scan_line(struct charlieplex_keypad *keypad,
					unsigned int oline)
{
	struct gpio_descs *line_gpios = keypad->line_gpios;
	DECLARE_BITMAP(values, MATRIX_MAX_ROWS);
	int err;

	/* Activate only one line as output at a time. */
	gpiod_direction_output(line_gpios->desc[oline], 1);

	if (keypad->settling_time_us)
		fsleep(keypad->settling_time_us);

	/* Read input on all other lines. */
	err = gpiod_get_array_value_cansleep(line_gpios->ndescs, line_gpios->desc,
					     line_gpios->info, values);

	gpiod_direction_input(line_gpios->desc[oline]);

	if (err)
		return err;

	for (unsigned int iline = 0; iline < keypad->nlines; iline++) {
		if (iline == oline)
			continue; /* Do not read active output line. */

		/* Check if GPIO is asserted. */
		if (test_bit(iline, values))
			return MATRIX_SCAN_CODE(oline, iline,
						get_count_order(keypad->nlines));
	}

	return 0;
}

static void charlieplex_keypad_poll(struct input_dev *input)
{
	struct charlieplex_keypad *keypad = input_get_drvdata(input);
	int code = 0;

	for (unsigned int oline = 0; oline < keypad->nlines; oline++) {
		code = charlieplex_keypad_scan_line(keypad, oline);
		if (code != 0)
			break;
	}

	if (code >= 0)
		charlieplex_keypad_check_switch_change(input, code);
}

static int charlieplex_keypad_init_gpio(struct platform_device *pdev,
					struct charlieplex_keypad *keypad)
{
	char **pin_names;
	char label[32];

	snprintf(label, sizeof(label), "%s-pin", pdev->name);

	keypad->line_gpios = devm_gpiod_get_array(&pdev->dev, "line", GPIOD_IN);
	if (IS_ERR(keypad->line_gpios))
		return PTR_ERR(keypad->line_gpios);

	keypad->nlines = keypad->line_gpios->ndescs;

	if (keypad->nlines > MATRIX_MAX_ROWS)
		return -EINVAL;

	pin_names = devm_kasprintf_strarray(&pdev->dev, label, keypad->nlines);
	if (IS_ERR(pin_names))
		return PTR_ERR(pin_names);

	for (unsigned int i = 0; i < keypad->line_gpios->ndescs; i++)
		gpiod_set_consumer_name(keypad->line_gpios->desc[i], pin_names[i]);

	return 0;
}

static int charlieplex_keypad_probe(struct platform_device *pdev)
{
	struct charlieplex_keypad *keypad;
	struct input_dev *input_dev;
	unsigned int debounce_interval_ms = 5;
	unsigned int poll_interval_ms;
	int err;

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

	input_dev = devm_input_allocate_device(&pdev->dev);
	if (!input_dev)
		return -ENOMEM;

	keypad->input_dev = input_dev;

	err = device_property_read_u32(&pdev->dev, "poll-interval", &poll_interval_ms);
	if (err)
		return dev_err_probe(&pdev->dev, err,
				     "failed to parse 'poll-interval' property\n");

	if (poll_interval_ms == 0)
		return dev_err_probe(&pdev->dev, -EINVAL, "invalid 'poll-interval' value\n");

	device_property_read_u32(&pdev->dev, "debounce-delay-ms", &debounce_interval_ms);
	device_property_read_u32(&pdev->dev, "settling-time-us", &keypad->settling_time_us);

	keypad->current_code = -1;
	keypad->debounce_code = -1;
	keypad->debounce_threshold = DIV_ROUND_UP(debounce_interval_ms, poll_interval_ms);

	err = charlieplex_keypad_init_gpio(pdev, keypad);
	if (err)
		return err;

	input_dev->name = pdev->name;
	input_dev->id.bustype = BUS_HOST;

	err = matrix_keypad_build_keymap(NULL, NULL, keypad->nlines,
					 keypad->nlines, NULL, input_dev);
	if (err)
		return dev_err_probe(&pdev->dev, err, "failed to build keymap\n");

	if (device_property_read_bool(&pdev->dev, "autorepeat"))
		__set_bit(EV_REP, input_dev->evbit);

	input_set_capability(input_dev, EV_MSC, MSC_SCAN);

	err = input_setup_polling(input_dev, charlieplex_keypad_poll);
	if (err)
		return dev_err_probe(&pdev->dev, err, "unable to set up polling\n");

	input_set_poll_interval(input_dev, poll_interval_ms);

	input_set_drvdata(input_dev, keypad);

	err = input_register_device(keypad->input_dev);
	if (err)
		return err;

	return 0;
}

static const struct of_device_id charlieplex_keypad_dt_match[] = {
	{ .compatible = "gpio-charlieplex-keypad" },
	{ }
};
MODULE_DEVICE_TABLE(of, charlieplex_keypad_dt_match);

static struct platform_driver charlieplex_keypad_driver = {
	.probe		= charlieplex_keypad_probe,
	.driver		= {
		.name	= "charlieplex-keypad",
		.of_match_table = charlieplex_keypad_dt_match,
	},
};
module_platform_driver(charlieplex_keypad_driver);

MODULE_AUTHOR("Hugo Villeneuve <hvilleneuve@dimonoff.com>");
MODULE_DESCRIPTION("GPIO driven charlieplex keypad driver");
MODULE_LICENSE("GPL");
