1 // SPDX-License-Identifier: GPL-2.0-or-later
3 * Copyright (C) 2017 Sean Young <sean@mess.org>
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>
12 #include <linux/platform_device.h>
13 #include <media/rc-core.h>
15 #define DRIVER_NAME "gpio-ir-tx"
16 #define DEVICE_NAME "GPIO IR Bit Banging Transmitter"
19 struct gpio_desc
*gpio
;
21 unsigned int duty_cycle
;
24 static const struct of_device_id gpio_ir_tx_of_match
[] = {
25 { .compatible
= "gpio-ir-tx", },
28 MODULE_DEVICE_TABLE(of
, gpio_ir_tx_of_match
);
30 static int gpio_ir_tx_set_duty_cycle(struct rc_dev
*dev
, u32 duty_cycle
)
32 struct gpio_ir
*gpio_ir
= dev
->priv
;
34 gpio_ir
->duty_cycle
= duty_cycle
;
39 static int gpio_ir_tx_set_carrier(struct rc_dev
*dev
, u32 carrier
)
41 struct gpio_ir
*gpio_ir
= dev
->priv
;
46 gpio_ir
->carrier
= carrier
;
51 static void delay_until(ktime_t until
)
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.
60 delta
= ktime_us_delta(until
, ktime_get());
64 /* udelay more than 1ms may not work */
75 static void gpio_ir_tx_unmodulated(struct gpio_ir
*gpio_ir
, uint
*txbuf
,
83 for (i
= 0; i
< count
; i
++) {
84 gpiod_set_value(gpio_ir
->gpio
, !(i
% 2));
86 edge
= ktime_add_us(edge
, txbuf
[i
]);
90 gpiod_set_value(gpio_ir
->gpio
, 0);
93 static void gpio_ir_tx_modulated(struct gpio_ir
*gpio_ir
, uint
*txbuf
,
98 * delta should never exceed 0.5 seconds (IR_MAX_DURATION) and on
99 * m68k ndelay(s64) does not compile; so use s32 rather than s64.
103 unsigned int pulse
, space
;
105 /* Ensure the dividend fits into 32 bit */
106 pulse
= DIV_ROUND_CLOSEST(gpio_ir
->duty_cycle
* (NSEC_PER_SEC
/ 100),
108 space
= DIV_ROUND_CLOSEST((100 - gpio_ir
->duty_cycle
) *
109 (NSEC_PER_SEC
/ 100), gpio_ir
->carrier
);
113 for (i
= 0; i
< count
; i
++) {
116 edge
= ktime_add_us(edge
, txbuf
[i
]);
120 ktime_t last
= ktime_add_us(edge
, txbuf
[i
]);
122 while (ktime_before(ktime_get(), last
)) {
123 gpiod_set_value(gpio_ir
->gpio
, 1);
124 edge
= ktime_add_ns(edge
, pulse
);
125 delta
= ktime_to_ns(ktime_sub(edge
,
129 gpiod_set_value(gpio_ir
->gpio
, 0);
130 edge
= ktime_add_ns(edge
, space
);
131 delta
= ktime_to_ns(ktime_sub(edge
,
142 static int gpio_ir_tx(struct rc_dev
*dev
, unsigned int *txbuf
,
145 struct gpio_ir
*gpio_ir
= dev
->priv
;
148 local_irq_save(flags
);
149 if (gpio_ir
->carrier
)
150 gpio_ir_tx_modulated(gpio_ir
, txbuf
, count
);
152 gpio_ir_tx_unmodulated(gpio_ir
, txbuf
, count
);
153 local_irq_restore(flags
);
158 static int gpio_ir_tx_probe(struct platform_device
*pdev
)
160 struct gpio_ir
*gpio_ir
;
161 struct rc_dev
*rcdev
;
164 gpio_ir
= devm_kmalloc(&pdev
->dev
, sizeof(*gpio_ir
), GFP_KERNEL
);
168 rcdev
= devm_rc_allocate_device(&pdev
->dev
, RC_DRIVER_IR_RAW_TX
);
172 gpio_ir
->gpio
= devm_gpiod_get(&pdev
->dev
, NULL
, GPIOD_OUT_LOW
);
173 if (IS_ERR(gpio_ir
->gpio
))
174 return dev_err_probe(&pdev
->dev
, PTR_ERR(gpio_ir
->gpio
),
175 "Failed to get gpio\n");
177 rcdev
->priv
= gpio_ir
;
178 rcdev
->driver_name
= DRIVER_NAME
;
179 rcdev
->device_name
= DEVICE_NAME
;
180 rcdev
->tx_ir
= gpio_ir_tx
;
181 rcdev
->s_tx_duty_cycle
= gpio_ir_tx_set_duty_cycle
;
182 rcdev
->s_tx_carrier
= gpio_ir_tx_set_carrier
;
184 gpio_ir
->carrier
= 38000;
185 gpio_ir
->duty_cycle
= 50;
187 rc
= devm_rc_register_device(&pdev
->dev
, rcdev
);
189 dev_err(&pdev
->dev
, "failed to register rc device\n");
194 static struct platform_driver gpio_ir_tx_driver
= {
195 .probe
= gpio_ir_tx_probe
,
198 .of_match_table
= gpio_ir_tx_of_match
,
201 module_platform_driver(gpio_ir_tx_driver
);
203 MODULE_DESCRIPTION("GPIO IR Bit Banging Transmitter");
204 MODULE_AUTHOR("Sean Young <sean@mess.org>");
205 MODULE_LICENSE("GPL");