diff -drupN a/drivers/input/keyboard/sunxi-gpio-ir-rx.c b/drivers/input/keyboard/sunxi-gpio-ir-rx.c
--- a/drivers/input/keyboard/sunxi-gpio-ir-rx.c	1970-01-01 03:00:00.000000000 +0300
+++ b/drivers/input/keyboard/sunxi-gpio-ir-rx.c	2022-06-12 05:28:14.000000000 +0300
@@ -0,0 +1,524 @@
+/*
+ * drivers/input/keyboard/sunxi-gpio-ir-tx.c
+ *
+ * Copyright (c) 2013-2018 Allwinnertech Co., Ltd.
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * 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.
+ *
+ */
+
+#include <linux/module.h>
+#include <linux/sched.h>
+#include <linux/kernel.h>
+#include <linux/fs.h>
+#include <linux/init.h>
+#include <linux/delay.h>
+#include <linux/irq.h>
+#include <linux/uaccess.h>
+#include <asm/irq.h>
+#include <linux/io.h>
+#include <linux/device.h>
+#include <linux/interrupt.h>
+#include <linux/poll.h>
+#include <linux/cdev.h>
+#include <linux/gpio.h>
+#include <linux/ioport.h>
+#include <linux/input.h>
+#include <linux/miscdevice.h>
+#include <linux/of.h>
+#include <linux/of_device.h>
+#include <linux/sunxi-gpio.h>
+#include <linux/of_gpio.h>
+
+#include "sunxi-ir-keymap.h"
+#include "sunxi-gpio-ir-rx.h"
+
+#define GPIO_IR_RX_DRIVER_NAME "sunxi-gpio-ir-rx"
+
+//DEBUG_INIT | DEBUG_INT | DEBUG_DATA_INFO | DEBUG_ERR;
+static u32 debug_mask = 0x13;
+
+#define dprintk(level_mask, fmt, arg...)				\
+do {									\
+	if (unlikely(debug_mask & level_mask))				\
+		pr_warn("%s()%d - "fmt, __func__, __LINE__, ##arg);	\
+} while (0)
+
+/*report input key event*/
+#define REPORT_INPUT_KEYCODE
+
+#define GPIO_IR_RAW_BUF_SIZE   128
+struct gpio_ir_raw_buffer {
+	unsigned int dcnt; /*Packet Count*/
+	unsigned int timebuf[GPIO_IR_RAW_BUF_SIZE];
+};
+
+static struct gpio_ir_raw_buffer gpio_ir_rawbuf;
+static struct gpio_ir_raw_buffer gpio_ir_tmpbuf;
+static struct gpio_ir_rx_info *rx_info;
+
+static inline void gpio_ir_reset_rawbuffer(void)
+{
+	gpio_ir_rawbuf.dcnt = 0;
+}
+
+static inline void gpio_ir_write_rawbuffer(unsigned int interval)
+{
+	if (gpio_ir_rawbuf.dcnt < GPIO_IR_RAW_BUF_SIZE)
+		gpio_ir_rawbuf.timebuf[gpio_ir_rawbuf.dcnt++] = interval;
+	else
+		dprintk(DEBUG_ERR, "IR Rx Buffer Full!!\n");
+}
+
+static inline unsigned char gpio_ir_read_rawbuffer(void)
+{
+	unsigned char data = 0x00;
+
+	if (gpio_ir_rawbuf.dcnt > 0)
+	data = gpio_ir_rawbuf.timebuf[--gpio_ir_rawbuf.dcnt];
+	return data;
+}
+
+static inline int gpio_ir_rawbuffer_empty(void)
+{
+	return (gpio_ir_rawbuf.dcnt == 0);
+}
+
+static inline int gpio_ir_rawbuffer_full(void)
+{
+	return (gpio_ir_rawbuf.dcnt >= GPIO_IR_RAW_BUF_SIZE);
+}
+
+static irqreturn_t gpio_ir_rx_isr(int irq, void *dev_id)
+{
+	static ktime_t ktime_tap;
+
+	if (true == rx_info->sampler_enable) {
+		/*begin to record the time interval*/
+		gpio_ir_reset_rawbuffer();
+		rx_info->sampler_enable = false;
+		rx_info->ktime = ktime_get();
+
+	} else {
+		ktime_tap = ktime_sub(ktime_get(), rx_info->ktime);
+		if (!gpio_ir_rawbuffer_full())
+			gpio_ir_write_rawbuffer((unsigned int)ktime_to_us(ktime_tap));
+
+		/*save the current time*/
+		rx_info->ktime = ktime_get();
+	}
+	mod_timer(&rx_info->sample_timer, jiffies + (HZ/40));
+
+	return IRQ_HANDLED;
+}
+
+
+static unsigned int gpio_ir_rx_packet_handler(unsigned int *buf,
+		unsigned int dcnt)
+{
+	unsigned int val_1 = 0x00, val_0 = 0x00;
+	unsigned int val_top = 0x00, val_btm = 0x00;
+	unsigned int code = 0;
+	int bitCnt = 0;
+	unsigned int i = 0;
+
+	dprintk(DEBUG_DATA_INFO, "dcnt = %d\n", (int)dcnt);
+
+	/* Find Lead '1' , 9ms high*/
+	for (i = 0; i < dcnt; i++) {
+		val_1 = buf[i];
+		val_0 = buf[i + 1];
+		if (val_1 > GPIO_IR_L1_MIN && val_0 > GPIO_IR_L0_MIN)
+			break;
+	}
+	dprintk(DEBUG_DATA_INFO, "%d start head found = %d\n", __LINE__, i);
+
+	/* go decoding */
+	code = 0;
+	bitCnt = 0;
+
+	for (i = i + 2; i < dcnt; i += 2) {
+		val_top = buf[i];
+			val_btm = buf[i + 1];
+		if (val_top > GPIO_IR_PMAX ||
+					val_top < GPIO_IR_PMIN ||
+					val_btm > GPIO_IR_PMAX ||
+					val_btm < GPIO_IR_PMIN) {
+			dprintk(DEBUG_DATA_INFO, "%d: Error Pulse found : %d\n",
+					__LINE__, i);
+			goto error_code;
+		}
+
+		/*to judge bit 0 0r bit 1, just check the second level interval*/
+		if (val_btm > GPIO_IR_DMID)  {
+			/* data '1' */
+			code |= 1 << bitCnt;
+		} else {
+			code &= ~(1 << bitCnt);
+		}
+		bitCnt++;
+		if (bitCnt == 32)
+		break; /* decode over */
+	}
+	return code;
+
+error_code:
+	dprintk(DEBUG_ERR, "%d: packet handler error\n", __LINE__);
+	return GPIO_IR_ERROR_CODE;
+}
+
+static int gpio_ir_code_valid(unsigned int code)
+{
+	unsigned int tmp1, tmp2;
+
+#ifdef IR_CHECK_ADDR_CODE
+	/* Check Address Value */
+	if ((code & 0xffff) != (IR_ADDR_CODE & 0xffff))
+		return 0; /* Address Error */
+
+	tmp1 = code & 0x00ff0000;
+	tmp2 = (code & 0xff000000) >> 8;
+	return ((tmp1 ^ tmp2) == 0x00ff0000);  /* Check User Code */
+
+#else
+	/* Do Not Check Address Value */
+	tmp1 = code & 0x00ff00ff;
+	tmp2 = (code & 0xff00ff00) >> 8;
+	return (((tmp1 ^ tmp2) & 0x00ff0000) == 0x00ff0000);
+
+#endif
+}
+
+static void gpio_ir_rx_tsklet(unsigned long tsklet_data)
+{
+	unsigned int code;
+	int code_valid;
+
+#ifdef RAW_DATA_DUMP
+	int i;
+
+	for (int i = 0; i < gpio_ir_tmpbuf.dcnt; i++) {
+		pr_info("%d  ", gpio_ir_tmpbuf.timebuf[i]);
+		if ((i+1)%8 == 0)
+			pr_info("\n");
+	}
+	pr_info("\n");
+#endif
+
+	code = gpio_ir_rx_packet_handler(gpio_ir_tmpbuf.timebuf,
+			gpio_ir_tmpbuf.dcnt);
+	code_valid = gpio_ir_code_valid(code);
+
+	if ((code != GPIO_IR_ERROR_CODE) && (code != GPIO_IR_REPEAT_CODE))
+		dprintk(DEBUG_INT, "ir addr code = 0x%x\n",  code & 0xffff);
+
+	if (rx_info->timer_used) {
+		if (code_valid) {
+			/*the previous-key(old key) is released*/
+			input_report_key(rx_info->ir_dev,
+				ir_keycodes[(rx_info->ir_code >> 16) & 0xff],
+				0);
+			input_sync(rx_info->ir_dev);
+			dprintk(DEBUG_INT, "IR KEY UP\n");
+			 rx_info->key_count = 0;
+		}
+
+		/*if the same  or repeat key, delay to report key up*/
+		if ((code == GPIO_IR_REPEAT_CODE) || (code_valid))
+			mod_timer(&rx_info->report_timer, jiffies + (HZ/5));
+		} else {
+			if (code_valid) {
+			/*init timer, the kery would be release*/
+			mod_timer(&rx_info->report_timer, jiffies + (HZ/5));
+			rx_info->timer_used = 1;
+		}
+	}
+
+	if (rx_info->timer_used) {
+		/*some key repeat times*/
+		rx_info->key_count++;
+		/*one new key, report key down*/
+		if (rx_info->key_count == 1) {
+			/*update saved code with a new valid code*/
+			if (code_valid)
+				rx_info->ir_code = code;
+
+			dprintk(DEBUG_INT, "ir key code: 0x%x\n",
+				ir_keycodes[(rx_info->ir_code >> 16) & 0xff]);
+
+			/*key down report*/
+			input_report_key(rx_info->ir_dev,
+				ir_keycodes[(rx_info->ir_code >> 16) & 0xff],
+				1);
+			input_sync(rx_info->ir_dev);
+		}
+	}
+
+	dprintk(DEBUG_DATA_INFO,
+			"Rx Packet End, code=0x%x, ir_code=0x%x, rx_info->timer_used=%d\n",
+			(int)code, (int)rx_info->ir_code, rx_info->timer_used);
+}
+
+static void ir_sample_timer_handle(unsigned long arg)
+{
+	/*timeout: one frame was receive finish*/
+	memcpy(&gpio_ir_tmpbuf, &gpio_ir_rawbuf,
+			sizeof(struct gpio_ir_raw_buffer));
+	rx_info->sampler_enable = true;
+	kill_fasync(&rx_info->ir_fasync, SIGIO, POLL_IN);
+	/*to parse the raw buffer, and report the key event*/
+#ifdef REPORT_INPUT_KEYCODE
+	tasklet_schedule(&rx_info->tsklet);
+#endif
+
+}
+
+static void ir_report_timer_handle(unsigned long arg)
+{
+	/*timeout: report key release*/
+	input_report_key(rx_info->ir_dev,
+			ir_keycodes[(rx_info->ir_code >> 16) & 0xff], 0);
+	input_sync(rx_info->ir_dev);
+	rx_info->key_count = 0;
+	rx_info->timer_used = 0;
+	dprintk(DEBUG_DATA_INFO, "key timeout, report keyup: 0x%x\n",
+			ir_keycodes[(rx_info->ir_code >> 16) & 0xff]);
+}
+
+static int gpio_ir_rx_open(struct inode *inode, struct file *file)
+{
+	int ret = 0;
+
+	dprintk(DEBUG_INIT, "gpio_ir_rx_open\n");
+	gpio_ir_reset_rawbuffer();
+	return ret ?: nonseekable_open(inode, file);
+}
+
+static int gpio_ir_rx_release(struct inode *inode, struct file *file)
+{
+	dprintk(DEBUG_INIT, "gpio_ir_rx_release\n");
+	gpio_ir_reset_rawbuffer();
+	return 0;
+}
+
+ssize_t gpio_ir_rx_read(struct file *file, char __user *buf,
+			size_t size, loff_t *ppos)
+{
+	int ret;
+
+	dprintk(DEBUG_INIT, "gpio_ir_rx_read, size: %d\n", size);
+	if (size != sizeof(struct gpio_ir_raw_buffer))
+		return -EINVAL;
+
+	ret = copy_to_user(buf, &gpio_ir_tmpbuf,
+		sizeof(struct gpio_ir_raw_buffer));
+	gpio_ir_reset_rawbuffer();
+
+	return ret;
+}
+
+static int gpio_ir_rx_fasync(int fd, struct file *file, int on)
+{
+	dprintk(DEBUG_INIT, "enter init fansync_helper\n");
+	if (!rx_info)
+		return -EIO;
+
+	return fasync_helper(fd, file, on, &rx_info->ir_fasync);
+}
+
+static const struct file_operations gpio_ir_rx_fops = {
+	.owner =	THIS_MODULE,
+	.read = gpio_ir_rx_read,
+	.fasync = gpio_ir_rx_fasync,
+	.release = gpio_ir_rx_release,
+	.open = gpio_ir_rx_open,
+
+};
+
+static struct miscdevice gpio_ir_rx_miscdev = {
+	.minor = MISC_DYNAMIC_MINOR,
+	.name = "gpio_ir_rx",
+	.fops = &gpio_ir_rx_fops,
+};
+
+static int __init gpio_ir_rx_probe(struct platform_device *pdev)
+{
+	struct device *dev = &pdev->dev;
+	struct gpio_config config;
+	int i;
+	int ret;
+
+	dprintk(DEBUG_INIT, "\nenter gpio ir rx probe\n");
+	rx_info = devm_kzalloc(dev, sizeof(struct gpio_ir_rx_info), GFP_KERNEL);
+	if (!rx_info) {
+		dev_err(dev, "can't allocate gpio ir-rx memory\n");
+		return -ENOMEM;
+	}
+
+	/*ir gpio rx pin*/
+	rx_info->ir_rx_gpio = of_get_named_gpio_flags(dev->of_node,
+			"gpio-rx", 0,
+			(enum of_gpio_flags *)&config);
+
+	dprintk(DEBUG_INIT, "%s, line:%d, gpio ir rx: %d!\n",
+		__func__, __LINE__, rx_info->ir_rx_gpio);
+
+	ret = devm_gpio_request(dev, rx_info->ir_rx_gpio, "ir_rx_gpio");
+	if (ret < 0) {
+		dev_err(dev, "can't request ir_rx_gpio gpio %d\n",
+			rx_info->ir_rx_gpio);
+		goto err_free_mem;
+	}
+
+	ret = gpio_direction_input(rx_info->ir_rx_gpio);
+	if (ret < 0) {
+		dev_err(dev, "can't request input direction ir_rx_gpio gpio %d\n",
+			rx_info->ir_rx_gpio);
+		goto err_free_gpio;
+	}
+
+	rx_info->ir_rx_gpio_irq = gpio_to_irq(rx_info->ir_rx_gpio);
+	if (IS_ERR_VALUE(rx_info->ir_rx_gpio_irq)) {
+		dev_err(dev, "map gpio [%d] to virq failed, errno = %d\n",
+				rx_info->ir_rx_gpio, rx_info->ir_rx_gpio_irq);
+		goto err_free_gpio;
+	}
+
+	dprintk(DEBUG_INIT, "gpio irq: %d\n", rx_info->ir_rx_gpio_irq);
+
+	/* register input device for ir */
+	rx_info->ir_dev = input_allocate_device();
+	if (!rx_info->ir_dev) {
+		dev_err(dev, "not enough memory for input device\n");
+		goto err_free_gpio;
+	}
+
+	rx_info->ir_dev->name = "sunxi-gpio-ir";
+	rx_info->ir_dev->phys = "gpioIR/input1";
+
+	rx_info->ir_dev->id.bustype = BUS_VIRTUAL;
+	rx_info->ir_dev->id.vendor = 0x0002;
+	rx_info->ir_dev->id.product = 0x0005;
+	rx_info->ir_dev->id.version = 0x0100;
+
+#ifdef REPORT_REPEAT_KEY_VALUE
+	rx_info->ir_dev->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_REP);
+#else
+	rx_info->ir_dev->evbit[0] = BIT_MASK(EV_KEY);
+#endif
+
+	for (i = 0; i < 256; i++)
+		set_bit(ir_keycodes[i], rx_info->ir_dev->keybit);
+
+	ret = input_register_device(rx_info->ir_dev);
+	if (ret) {
+		dev_err(dev, "register input device exception, exit\n");
+		goto err_free_input;
+	}
+
+	init_timer(&rx_info->report_timer);
+	rx_info->report_timer.function = ir_report_timer_handle;
+
+	/* initialize tasklet for gpio_ir_rx_hrtimer_callback */
+	tasklet_init(&rx_info->tsklet, gpio_ir_rx_tsklet,
+			(unsigned long)rx_info);
+
+	init_timer(&rx_info->sample_timer);
+	rx_info->sample_timer.function = ir_sample_timer_handle;
+	rx_info->sampler_enable = true;
+
+	//mutex_init(&rx_info->lock);
+
+	ret = request_irq(rx_info->ir_rx_gpio_irq, gpio_ir_rx_isr,
+			IRQF_TRIGGER_FALLING | IRQF_TRIGGER_RISING,
+			"ir_rx_gpio_irq", NULL);
+	if (ret != 0) {
+		dev_err(dev, "irq request failed!\n");
+		goto err_free_gpio;
+	}
+
+	ret = misc_register(&gpio_ir_rx_miscdev);
+	if (ret) {
+		dev_err(dev, "%s: cannot register miscdev on minor=%d (%d)\n",
+				__func__, MISC_DYNAMIC_MINOR, ret);
+		goto err_misc_register;
+	}
+
+	dprintk(DEBUG_INIT, "%s: gpio ir rx probe succeed!)\n", __func__);
+
+	return 0;
+
+err_misc_register:
+	del_timer(&rx_info->report_timer);
+	del_timer(&rx_info->sample_timer);
+
+err_free_input:
+	input_unregister_device(rx_info->ir_dev);
+
+err_free_gpio:
+	gpio_free(rx_info->ir_rx_gpio);
+
+err_free_mem:
+	devm_kfree(dev, rx_info);
+	return ret;
+
+}
+
+static int gpio_ir_rx_remove(struct platform_device *pdev)
+{
+	del_timer(&rx_info->report_timer);
+	del_timer(&rx_info->sample_timer);
+	input_unregister_device(rx_info->ir_dev);
+	misc_deregister(&gpio_ir_rx_miscdev);
+	free_irq(rx_info->ir_rx_gpio_irq, NULL);
+	gpio_free(rx_info->ir_rx_gpio);
+	return 0;
+}
+
+static const struct of_device_id gpio_ir_rx_match[] = {
+	{ .compatible = "allwinner,gpio-ir-rx", },
+	{ },
+};
+MODULE_DEVICE_TABLE(of, gpio_ir_rx_match);
+
+#ifdef CONFIG_PM
+static int gpio_ir_rx_resume(struct device *dev)
+{
+	return 0;
+}
+
+static int gpio_ir_rx_suspend(struct device *dev)
+{
+	return 0;
+}
+
+static const struct dev_pm_ops gpio_ir_rx_pm_ops = {
+	.suspend = gpio_ir_rx_suspend,
+	.resume = gpio_ir_rx_resume,
+};
+#endif
+
+static struct platform_driver gpio_ir_rx_driver = {
+	.driver = {
+		.name	= GPIO_IR_RX_DRIVER_NAME,
+		.owner	= THIS_MODULE,
+		.of_match_table = gpio_ir_rx_match,
+#ifdef CONFIG_PM
+		.pm = &gpio_ir_rx_pm_ops,
+#endif
+	},
+	.probe  = gpio_ir_rx_probe,
+	.remove = gpio_ir_rx_remove,
+};
+
+module_platform_driver(gpio_ir_rx_driver);
+MODULE_DESCRIPTION("Remote GPIO IR driver");
+MODULE_AUTHOR("xudong");
+MODULE_LICENSE("GPL");