firmware/br-ext-chip-allwinner/board/v83x/kernel/patches/00000-drivers_input_keyboar...

278 lines
6.7 KiB
Diff
Raw Blame History

diff -drupN a/drivers/input/keyboard/sunxi-gpio-ir-tx.c b/drivers/input/keyboard/sunxi-gpio-ir-tx.c
--- a/drivers/input/keyboard/sunxi-gpio-ir-tx.c 1970-01-01 03:00:00.000000000 +0300
+++ b/drivers/input/keyboard/sunxi-gpio-ir-tx.c 2022-06-12 05:28:14.000000000 +0300
@@ -0,0 +1,273 @@
+/*
+ * 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/init.h>
+#include <linux/delay.h>
+#include <linux/platform_device.h>
+#include <linux/gpio.h>
+#include <linux/kernel.h>
+#include <linux/pm.h>
+#include <linux/arisc/arisc.h>
+#include <asm/irq.h>
+#include <linux/io.h>
+#include <linux/of.h>
+#include <linux/of_device.h>
+#include <linux/sunxi-gpio.h>
+#include <linux/of_gpio.h>
+
+#include "sunxi-gpio-ir-tx.h"
+
+/*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)
+
+#define IR_TX_GPIO_NAME "ir_gpio_tx"
+#define GPIO_IR_RX_DRIVER_NAME "sunxi-gpio-ir-tx"
+
+#define GPIO_IR_HEADER_CODE0 0x04 /* Custom code 0*/
+#define GPIO_IR_HEADER_CODE1 0xFB /* Custom code 1*/
+#define CARRIER_1MS (10000/264)
+#define CARRIER_9MS (90000/264)
+#define CARRIER_560US (5600/264)
+
+
+struct gpio_ir_tx_info {
+ unsigned int tx_gpio;
+ struct kobject *kobj;
+};
+
+struct gpio_ir_tx_info *tx_info;
+
+static DEFINE_MUTEX(sysfs_lock);
+static DEFINE_SPINLOCK(lock);
+static DEFINE_SPINLOCK(carrier);
+
+//<2F><><EFBFBD><EFBFBD><EFBFBD>ز<EFBFBD>
+void sendcarrier(int unum)
+{
+ int i;
+ unsigned long flags;
+
+ spin_lock_irqsave(&carrier, flags); //<2F><>ֹ<EFBFBD>ж<EFBFBD>
+
+ for (i = 0; i < unum; i++) {
+ gpio_set_value(tx_info->tx_gpio, 1);
+ udelay(13);
+ gpio_set_value(tx_info->tx_gpio, 0);
+ udelay(13);
+ ndelay(400);
+ }
+ gpio_set_value(tx_info->tx_gpio, 0);
+
+ spin_unlock_irqrestore(&carrier, flags);
+}
+
+void sendIrBit(unsigned char bit)
+{
+ sendcarrier(CARRIER_560US);
+ udelay(bit == 0x00 ? 560 : 1690);
+}
+
+void sendIrByte(unsigned char data)
+{
+ unsigned char uMask = 0x01;
+
+ while (uMask) {
+ /*low bit first*/
+ sendIrBit(data & uMask);
+ uMask <<= 1;
+ }
+}
+
+void sendIrInt(unsigned int data)
+{
+ unsigned int uMask = 0x01;
+
+ while (uMask) {
+ sendIrBit(data & uMask);
+ uMask <<= 1;
+ }
+}
+
+static ssize_t gpio_ir_send_code(struct device *dev,
+ struct device_attribute *attr, const char *buf, size_t size)
+{
+ int key, keyOpposite;
+ unsigned long flags;
+
+ dprintk(DEBUG_DATA_INFO, "gpio send buf: %s", buf);
+
+ if (sscanf(buf, "%d", &key) != 1) {
+ dprintk(DEBUG_ERR, "error input key code\n");
+ return -EINVAL;
+ }
+
+ keyOpposite = ~key;
+ dprintk(DEBUG_DATA_INFO, "key 0x%x, keyOpp 0x%x\n", key, keyOpposite);
+
+ spin_lock_irqsave(&lock, flags);
+ /*leader code*/
+ sendcarrier(CARRIER_9MS);
+ mdelay(4);
+ udelay(500);
+
+ /*addr code*/
+ sendIrByte(GPIO_IR_HEADER_CODE0);
+ sendIrByte(GPIO_IR_HEADER_CODE1);
+
+ /*data code*/
+ sendIrByte((unsigned char)key);
+ sendIrByte((unsigned char)keyOpposite);
+ sendcarrier(CARRIER_560US);
+
+ spin_unlock_irqrestore(&lock, flags);
+ dprintk(DEBUG_DATA_INFO, "ir code send finished\n");
+
+ return size;
+}
+
+static const DEVICE_ATTR(ir_code, 0644, NULL, gpio_ir_send_code);
+
+static ssize_t gpio_ir_send_repeat(struct device *dev,
+ struct device_attribute *attr, const char *buf, size_t size)
+{
+ int i, num;
+ unsigned long flags;
+
+ dprintk(DEBUG_DATA_INFO, "ir test buf is %s", buf);
+
+ if (sscanf(buf, "%d", &num) != 1)
+ return -EINVAL;
+
+ dprintk(DEBUG_DATA_INFO, "repeat num is %d, tx pin %d\n",
+ num, tx_info->tx_gpio);
+
+ /*repeat code*/
+ for (i = 0; i < num; i++) {
+ spin_lock_irqsave(&lock, flags);
+ /*repeat leader code*/
+ sendcarrier(CARRIER_9MS);
+ mdelay(2);
+ udelay(250);
+ sendcarrier(CARRIER_560US);
+ spin_unlock_irqrestore(&lock, flags);
+ msleep(100);
+ }
+
+ return size;
+}
+
+static const DEVICE_ATTR(ir_repeat, 0644, NULL, gpio_ir_send_repeat);
+
+static const struct attribute *ir_tx_attrs[] = {
+ &dev_attr_ir_code.attr,
+ &dev_attr_ir_repeat.attr,
+
+ NULL,
+};
+
+static const struct attribute_group tx_info_attrs_group = {
+ .attrs = (struct attribute **)ir_tx_attrs,
+};
+
+static int __init gpio_ir_tx_probe(struct platform_device *pdev)
+{
+ struct device *dev = &pdev->dev;
+ struct gpio_config config;
+ int ret = 0;
+
+ dprintk(DEBUG_INIT, "enter gpio ir rx probe\n");
+ tx_info = devm_kzalloc(dev, sizeof(struct gpio_ir_tx_info), GFP_KERNEL);
+ if (!tx_info) {
+ dev_err(dev, "can't allocate gpio ir-tx memory\n");
+ return -ENOMEM;
+ }
+ /*ir gpio tx pin*/
+ tx_info->tx_gpio = of_get_named_gpio_flags(dev->of_node,
+ "gpio-tx", 0,
+ (enum of_gpio_flags *)&config);
+
+ dprintk(DEBUG_INIT, "%s, line: %d, gpio ir tx: %d!\n",
+ __func__, __LINE__, tx_info->tx_gpio);
+
+ ret = devm_gpio_request(dev, tx_info->tx_gpio, "ir_tx_gpio");
+ if (ret < 0) {
+ dev_err(dev, "error: can't request ir tx gpio %d\n",
+ tx_info->tx_gpio);
+ goto err_free_mem;
+ }
+
+ ret = gpio_direction_output(tx_info->tx_gpio, 0);
+ if (ret < 0) {
+ dev_err(dev, "error: can't set output direction\n");
+ goto err_free_gpio;
+ }
+
+ tx_info->kobj = kobject_create_and_add(IR_TX_GPIO_NAME, NULL);
+ if (!tx_info->kobj)
+ goto err_free_gpio;
+
+ ret = sysfs_create_group(tx_info->kobj, &tx_info_attrs_group);
+ if (ret)
+ kobject_put(tx_info->kobj);
+
+ dprintk(DEBUG_INIT, "%s, line: %d succeed\n", __func__, __LINE__);
+
+ return ret;
+
+err_free_gpio:
+ gpio_free(tx_info->tx_gpio);
+
+err_free_mem:
+ devm_kfree(dev, tx_info);
+ return ret;
+}
+
+
+static int gpio_ir_tx_remove(struct platform_device *pdev)
+{
+ kobject_put(tx_info->kobj);
+ gpio_free(tx_info->tx_gpio);
+ return 0;
+}
+
+static const struct of_device_id gpio_ir_tx_match[] = {
+ { .compatible = "allwinner,gpio-ir-tx", },
+ { },
+};
+MODULE_DEVICE_TABLE(of, gpio_ir_tx_match);
+
+static struct platform_driver gpio_ir_tx_driver = {
+ .driver = {
+ .name = GPIO_IR_RX_DRIVER_NAME,
+ .owner = THIS_MODULE,
+ .of_match_table = gpio_ir_tx_match,
+ },
+ .probe = gpio_ir_tx_probe,
+ .remove = gpio_ir_tx_remove,
+};
+
+module_platform_driver(gpio_ir_tx_driver);
+module_param_named(debug_mask, debug_mask, int, 0644);
+MODULE_DESCRIPTION("Remote GPIO IR TX driver");
+MODULE_AUTHOR("xudong");
+MODULE_LICENSE("GPL");