From cde9070d9970eef1f7ec2360586c802a16230ad8 Mon Sep 17 00:00:00 2001 From: hc <hc@nodka.com> Date: Fri, 10 May 2024 07:43:50 +0000 Subject: [PATCH] rtl88x2CE_WiFi_linux driver --- kernel/drivers/media/rc/gpio-ir-tx.c | 80 +++++++++++++++++++++++++++++----------- 1 files changed, 58 insertions(+), 22 deletions(-) diff --git a/kernel/drivers/media/rc/gpio-ir-tx.c b/kernel/drivers/media/rc/gpio-ir-tx.c index 4e70b67..a50701c 100644 --- a/kernel/drivers/media/rc/gpio-ir-tx.c +++ b/kernel/drivers/media/rc/gpio-ir-tx.c @@ -1,14 +1,6 @@ +// SPDX-License-Identifier: GPL-2.0-or-later /* * Copyright (C) 2017 Sean Young <sean@mess.org> - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2, 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. */ #include <linux/kernel.h> @@ -27,8 +19,6 @@ struct gpio_desc *gpio; unsigned int carrier; unsigned int duty_cycle; - /* we need a spinlock to hold the cpu while transmitting */ - spinlock_t lock; }; static const struct of_device_id gpio_ir_tx_of_match[] = { @@ -50,7 +40,7 @@ { struct gpio_ir *gpio_ir = dev->priv; - if (!carrier) + if (carrier > 500000) return -EINVAL; gpio_ir->carrier = carrier; @@ -58,11 +48,48 @@ return 0; } -static int gpio_ir_tx(struct rc_dev *dev, unsigned int *txbuf, - unsigned int count) +static void delay_until(ktime_t until) { - struct gpio_ir *gpio_ir = dev->priv; - unsigned long flags; + /* + * delta should never exceed 0.5 seconds (IR_MAX_DURATION) and on + * m68k ndelay(s64) does not compile; so use s32 rather than s64. + */ + s32 delta; + + while (true) { + delta = ktime_us_delta(until, ktime_get()); + if (delta <= 0) + return; + + /* udelay more than 1ms may not work */ + delta = min(delta, 1000); + udelay(delta); + } +} + +static void gpio_ir_tx_unmodulated(struct gpio_ir *gpio_ir, uint *txbuf, + uint count) +{ + ktime_t edge; + int i; + + local_irq_disable(); + + edge = ktime_get(); + + for (i = 0; i < count; i++) { + gpiod_set_value(gpio_ir->gpio, !(i % 2)); + + edge = ktime_add_us(edge, txbuf[i]); + delay_until(edge); + } + + gpiod_set_value(gpio_ir->gpio, 0); +} + +static void gpio_ir_tx_modulated(struct gpio_ir *gpio_ir, uint *txbuf, + uint count) +{ ktime_t edge; /* * delta should never exceed 0.5 seconds (IR_MAX_DURATION) and on @@ -78,7 +105,7 @@ space = DIV_ROUND_CLOSEST((100 - gpio_ir->duty_cycle) * (NSEC_PER_SEC / 100), gpio_ir->carrier); - spin_lock_irqsave(&gpio_ir->lock, flags); + local_irq_disable(); edge = ktime_get(); @@ -86,9 +113,7 @@ if (i % 2) { // space edge = ktime_add_us(edge, txbuf[i]); - delta = ktime_us_delta(edge, ktime_get()); - if (delta > 0) - udelay(delta); + delay_until(edge); } else { // pulse ktime_t last = ktime_add_us(edge, txbuf[i]); @@ -111,8 +136,20 @@ edge = last; } } +} - spin_unlock_irqrestore(&gpio_ir->lock, flags); +static int gpio_ir_tx(struct rc_dev *dev, unsigned int *txbuf, + unsigned int count) +{ + struct gpio_ir *gpio_ir = dev->priv; + unsigned long flags; + + local_irq_save(flags); + if (gpio_ir->carrier) + gpio_ir_tx_modulated(gpio_ir, txbuf, count); + else + gpio_ir_tx_unmodulated(gpio_ir, txbuf, count); + local_irq_restore(flags); return count; } @@ -148,7 +185,6 @@ gpio_ir->carrier = 38000; gpio_ir->duty_cycle = 50; - spin_lock_init(&gpio_ir->lock); rc = devm_rc_register_device(&pdev->dev, rcdev); if (rc < 0) -- Gitblit v1.6.2