]> git.proxmox.com Git - mirror_ubuntu-bionic-kernel.git/blob - drivers/media/rc/gpio-ir-tx.c
net: stmmac: dwmac-meson8b: propagate rate changes to the parent clock
[mirror_ubuntu-bionic-kernel.git] / drivers / media / rc / gpio-ir-tx.c
1 /*
2 * Copyright (C) 2017 Sean Young <sean@mess.org>
3 *
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License version 2, or
6 * (at your option) any later version.
7 *
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
12 */
13
14 #include <linux/kernel.h>
15 #include <linux/module.h>
16 #include <linux/gpio/consumer.h>
17 #include <linux/delay.h>
18 #include <linux/slab.h>
19 #include <linux/of.h>
20 #include <linux/platform_device.h>
21 #include <media/rc-core.h>
22
23 #define DRIVER_NAME "gpio-ir-tx"
24 #define DEVICE_NAME "GPIO IR Bit Banging Transmitter"
25
26 struct gpio_ir {
27 struct gpio_desc *gpio;
28 unsigned int carrier;
29 unsigned int duty_cycle;
30 /* we need a spinlock to hold the cpu while transmitting */
31 spinlock_t lock;
32 };
33
34 static const struct of_device_id gpio_ir_tx_of_match[] = {
35 { .compatible = "gpio-ir-tx", },
36 { },
37 };
38 MODULE_DEVICE_TABLE(of, gpio_ir_tx_of_match);
39
40 static int gpio_ir_tx_set_duty_cycle(struct rc_dev *dev, u32 duty_cycle)
41 {
42 struct gpio_ir *gpio_ir = dev->priv;
43
44 gpio_ir->duty_cycle = duty_cycle;
45
46 return 0;
47 }
48
49 static int gpio_ir_tx_set_carrier(struct rc_dev *dev, u32 carrier)
50 {
51 struct gpio_ir *gpio_ir = dev->priv;
52
53 if (!carrier)
54 return -EINVAL;
55
56 gpio_ir->carrier = carrier;
57
58 return 0;
59 }
60
61 static int gpio_ir_tx(struct rc_dev *dev, unsigned int *txbuf,
62 unsigned int count)
63 {
64 struct gpio_ir *gpio_ir = dev->priv;
65 unsigned long flags;
66 ktime_t edge;
67 /*
68 * delta should never exceed 0.5 seconds (IR_MAX_DURATION) and on
69 * m68k ndelay(s64) does not compile; so use s32 rather than s64.
70 */
71 s32 delta;
72 int i;
73 unsigned int pulse, space;
74
75 /* Ensure the dividend fits into 32 bit */
76 pulse = DIV_ROUND_CLOSEST(gpio_ir->duty_cycle * (NSEC_PER_SEC / 100),
77 gpio_ir->carrier);
78 space = DIV_ROUND_CLOSEST((100 - gpio_ir->duty_cycle) *
79 (NSEC_PER_SEC / 100), gpio_ir->carrier);
80
81 spin_lock_irqsave(&gpio_ir->lock, flags);
82
83 edge = ktime_get();
84
85 for (i = 0; i < count; i++) {
86 if (i % 2) {
87 // space
88 edge = ktime_add_us(edge, txbuf[i]);
89 delta = ktime_us_delta(edge, ktime_get());
90 if (delta > 10) {
91 spin_unlock_irqrestore(&gpio_ir->lock, flags);
92 usleep_range(delta, delta + 10);
93 spin_lock_irqsave(&gpio_ir->lock, flags);
94 } else if (delta > 0) {
95 udelay(delta);
96 }
97 } else {
98 // pulse
99 ktime_t last = ktime_add_us(edge, txbuf[i]);
100
101 while (ktime_before(ktime_get(), last)) {
102 gpiod_set_value(gpio_ir->gpio, 1);
103 edge = ktime_add_ns(edge, pulse);
104 delta = ktime_to_ns(ktime_sub(edge,
105 ktime_get()));
106 if (delta > 0)
107 ndelay(delta);
108 gpiod_set_value(gpio_ir->gpio, 0);
109 edge = ktime_add_ns(edge, space);
110 delta = ktime_to_ns(ktime_sub(edge,
111 ktime_get()));
112 if (delta > 0)
113 ndelay(delta);
114 }
115
116 edge = last;
117 }
118 }
119
120 spin_unlock_irqrestore(&gpio_ir->lock, flags);
121
122 return count;
123 }
124
125 static int gpio_ir_tx_probe(struct platform_device *pdev)
126 {
127 struct gpio_ir *gpio_ir;
128 struct rc_dev *rcdev;
129 int rc;
130
131 gpio_ir = devm_kmalloc(&pdev->dev, sizeof(*gpio_ir), GFP_KERNEL);
132 if (!gpio_ir)
133 return -ENOMEM;
134
135 rcdev = devm_rc_allocate_device(&pdev->dev, RC_DRIVER_IR_RAW_TX);
136 if (!rcdev)
137 return -ENOMEM;
138
139 gpio_ir->gpio = devm_gpiod_get(&pdev->dev, NULL, GPIOD_OUT_LOW);
140 if (IS_ERR(gpio_ir->gpio)) {
141 if (PTR_ERR(gpio_ir->gpio) != -EPROBE_DEFER)
142 dev_err(&pdev->dev, "Failed to get gpio (%ld)\n",
143 PTR_ERR(gpio_ir->gpio));
144 return PTR_ERR(gpio_ir->gpio);
145 }
146
147 rcdev->priv = gpio_ir;
148 rcdev->driver_name = DRIVER_NAME;
149 rcdev->device_name = DEVICE_NAME;
150 rcdev->tx_ir = gpio_ir_tx;
151 rcdev->s_tx_duty_cycle = gpio_ir_tx_set_duty_cycle;
152 rcdev->s_tx_carrier = gpio_ir_tx_set_carrier;
153
154 gpio_ir->carrier = 38000;
155 gpio_ir->duty_cycle = 50;
156 spin_lock_init(&gpio_ir->lock);
157
158 rc = devm_rc_register_device(&pdev->dev, rcdev);
159 if (rc < 0)
160 dev_err(&pdev->dev, "failed to register rc device\n");
161
162 return rc;
163 }
164
165 static struct platform_driver gpio_ir_tx_driver = {
166 .probe = gpio_ir_tx_probe,
167 .driver = {
168 .name = DRIVER_NAME,
169 .of_match_table = of_match_ptr(gpio_ir_tx_of_match),
170 },
171 };
172 module_platform_driver(gpio_ir_tx_driver);
173
174 MODULE_DESCRIPTION("GPIO IR Bit Banging Transmitter");
175 MODULE_AUTHOR("Sean Young <sean@mess.org>");
176 MODULE_LICENSE("GPL");