GNU Linux-libre 6.7.9-gnu
[releases.git] / drivers / media / rc / gpio-ir-tx.c
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
18 struct gpio_ir {
19         struct gpio_desc *gpio;
20         unsigned int carrier;
21         unsigned int duty_cycle;
22 };
23
24 static const struct of_device_id gpio_ir_tx_of_match[] = {
25         { .compatible = "gpio-ir-tx", },
26         { },
27 };
28 MODULE_DEVICE_TABLE(of, gpio_ir_tx_of_match);
29
30 static 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
39 static 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
51 static 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
75 static 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
95 static 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
146 static 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
162 static 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                 return dev_err_probe(&pdev->dev, PTR_ERR(gpio_ir->gpio),
179                                      "Failed to get gpio\n");
180
181         rcdev->priv = gpio_ir;
182         rcdev->driver_name = DRIVER_NAME;
183         rcdev->device_name = DEVICE_NAME;
184         rcdev->tx_ir = gpio_ir_tx;
185         rcdev->s_tx_duty_cycle = gpio_ir_tx_set_duty_cycle;
186         rcdev->s_tx_carrier = gpio_ir_tx_set_carrier;
187
188         gpio_ir->carrier = 38000;
189         gpio_ir->duty_cycle = 50;
190
191         rc = devm_rc_register_device(&pdev->dev, rcdev);
192         if (rc < 0)
193                 dev_err(&pdev->dev, "failed to register rc device\n");
194
195         return rc;
196 }
197
198 static struct platform_driver gpio_ir_tx_driver = {
199         .probe  = gpio_ir_tx_probe,
200         .driver = {
201                 .name   = DRIVER_NAME,
202                 .of_match_table = gpio_ir_tx_of_match,
203         },
204 };
205 module_platform_driver(gpio_ir_tx_driver);
206
207 MODULE_DESCRIPTION("GPIO IR Bit Banging Transmitter");
208 MODULE_AUTHOR("Sean Young <sean@mess.org>");
209 MODULE_LICENSE("GPL");