gpio-ir-tx.c (4695B)
1// SPDX-License-Identifier: GPL-2.0-or-later 2/* 3 * Copyright (C) 2017 Sean Young <sean@mess.org> 4 */ 5 6#include <linux/kernel.h> 7#include <linux/module.h> 8#include <linux/gpio/consumer.h> 9#include <linux/delay.h> 10#include <linux/slab.h> 11#include <linux/of.h> 12#include <linux/platform_device.h> 13#include <media/rc-core.h> 14 15#define DRIVER_NAME "gpio-ir-tx" 16#define DEVICE_NAME "GPIO IR Bit Banging Transmitter" 17 18struct gpio_ir { 19 struct gpio_desc *gpio; 20 unsigned int carrier; 21 unsigned int duty_cycle; 22}; 23 24static const struct of_device_id gpio_ir_tx_of_match[] = { 25 { .compatible = "gpio-ir-tx", }, 26 { }, 27}; 28MODULE_DEVICE_TABLE(of, gpio_ir_tx_of_match); 29 30static int gpio_ir_tx_set_duty_cycle(struct rc_dev *dev, u32 duty_cycle) 31{ 32 struct gpio_ir *gpio_ir = dev->priv; 33 34 gpio_ir->duty_cycle = duty_cycle; 35 36 return 0; 37} 38 39static int gpio_ir_tx_set_carrier(struct rc_dev *dev, u32 carrier) 40{ 41 struct gpio_ir *gpio_ir = dev->priv; 42 43 if (carrier > 500000) 44 return -EINVAL; 45 46 gpio_ir->carrier = carrier; 47 48 return 0; 49} 50 51static void delay_until(ktime_t until) 52{ 53 /* 54 * delta should never exceed 0.5 seconds (IR_MAX_DURATION) and on 55 * m68k ndelay(s64) does not compile; so use s32 rather than s64. 56 */ 57 s32 delta; 58 59 while (true) { 60 delta = ktime_us_delta(until, ktime_get()); 61 if (delta <= 0) 62 return; 63 64 /* udelay more than 1ms may not work */ 65 if (delta >= 1000) { 66 mdelay(delta / 1000); 67 continue; 68 } 69 70 udelay(delta); 71 break; 72 } 73} 74 75static void gpio_ir_tx_unmodulated(struct gpio_ir *gpio_ir, uint *txbuf, 76 uint count) 77{ 78 ktime_t edge; 79 int i; 80 81 local_irq_disable(); 82 83 edge = ktime_get(); 84 85 for (i = 0; i < count; i++) { 86 gpiod_set_value(gpio_ir->gpio, !(i % 2)); 87 88 edge = ktime_add_us(edge, txbuf[i]); 89 delay_until(edge); 90 } 91 92 gpiod_set_value(gpio_ir->gpio, 0); 93} 94 95static void gpio_ir_tx_modulated(struct gpio_ir *gpio_ir, uint *txbuf, 96 uint count) 97{ 98 ktime_t edge; 99 /* 100 * delta should never exceed 0.5 seconds (IR_MAX_DURATION) and on 101 * m68k ndelay(s64) does not compile; so use s32 rather than s64. 102 */ 103 s32 delta; 104 int i; 105 unsigned int pulse, space; 106 107 /* Ensure the dividend fits into 32 bit */ 108 pulse = DIV_ROUND_CLOSEST(gpio_ir->duty_cycle * (NSEC_PER_SEC / 100), 109 gpio_ir->carrier); 110 space = DIV_ROUND_CLOSEST((100 - gpio_ir->duty_cycle) * 111 (NSEC_PER_SEC / 100), gpio_ir->carrier); 112 113 local_irq_disable(); 114 115 edge = ktime_get(); 116 117 for (i = 0; i < count; i++) { 118 if (i % 2) { 119 // space 120 edge = ktime_add_us(edge, txbuf[i]); 121 delay_until(edge); 122 } else { 123 // pulse 124 ktime_t last = ktime_add_us(edge, txbuf[i]); 125 126 while (ktime_before(ktime_get(), last)) { 127 gpiod_set_value(gpio_ir->gpio, 1); 128 edge = ktime_add_ns(edge, pulse); 129 delta = ktime_to_ns(ktime_sub(edge, 130 ktime_get())); 131 if (delta > 0) 132 ndelay(delta); 133 gpiod_set_value(gpio_ir->gpio, 0); 134 edge = ktime_add_ns(edge, space); 135 delta = ktime_to_ns(ktime_sub(edge, 136 ktime_get())); 137 if (delta > 0) 138 ndelay(delta); 139 } 140 141 edge = last; 142 } 143 } 144} 145 146static int gpio_ir_tx(struct rc_dev *dev, unsigned int *txbuf, 147 unsigned int count) 148{ 149 struct gpio_ir *gpio_ir = dev->priv; 150 unsigned long flags; 151 152 local_irq_save(flags); 153 if (gpio_ir->carrier) 154 gpio_ir_tx_modulated(gpio_ir, txbuf, count); 155 else 156 gpio_ir_tx_unmodulated(gpio_ir, txbuf, count); 157 local_irq_restore(flags); 158 159 return count; 160} 161 162static int gpio_ir_tx_probe(struct platform_device *pdev) 163{ 164 struct gpio_ir *gpio_ir; 165 struct rc_dev *rcdev; 166 int rc; 167 168 gpio_ir = devm_kmalloc(&pdev->dev, sizeof(*gpio_ir), GFP_KERNEL); 169 if (!gpio_ir) 170 return -ENOMEM; 171 172 rcdev = devm_rc_allocate_device(&pdev->dev, RC_DRIVER_IR_RAW_TX); 173 if (!rcdev) 174 return -ENOMEM; 175 176 gpio_ir->gpio = devm_gpiod_get(&pdev->dev, NULL, GPIOD_OUT_LOW); 177 if (IS_ERR(gpio_ir->gpio)) { 178 if (PTR_ERR(gpio_ir->gpio) != -EPROBE_DEFER) 179 dev_err(&pdev->dev, "Failed to get gpio (%ld)\n", 180 PTR_ERR(gpio_ir->gpio)); 181 return PTR_ERR(gpio_ir->gpio); 182 } 183 184 rcdev->priv = gpio_ir; 185 rcdev->driver_name = DRIVER_NAME; 186 rcdev->device_name = DEVICE_NAME; 187 rcdev->tx_ir = gpio_ir_tx; 188 rcdev->s_tx_duty_cycle = gpio_ir_tx_set_duty_cycle; 189 rcdev->s_tx_carrier = gpio_ir_tx_set_carrier; 190 191 gpio_ir->carrier = 38000; 192 gpio_ir->duty_cycle = 50; 193 194 rc = devm_rc_register_device(&pdev->dev, rcdev); 195 if (rc < 0) 196 dev_err(&pdev->dev, "failed to register rc device\n"); 197 198 return rc; 199} 200 201static struct platform_driver gpio_ir_tx_driver = { 202 .probe = gpio_ir_tx_probe, 203 .driver = { 204 .name = DRIVER_NAME, 205 .of_match_table = of_match_ptr(gpio_ir_tx_of_match), 206 }, 207}; 208module_platform_driver(gpio_ir_tx_driver); 209 210MODULE_DESCRIPTION("GPIO IR Bit Banging Transmitter"); 211MODULE_AUTHOR("Sean Young <sean@mess.org>"); 212MODULE_LICENSE("GPL");