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
;
22 /* we need a spinlock to hold the cpu while transmitting */
26 static const struct of_device_id gpio_ir_tx_of_match
[] = {
27 { .compatible
= "gpio-ir-tx", },
30 MODULE_DEVICE_TABLE(of
, gpio_ir_tx_of_match
);
32 static int gpio_ir_tx_set_duty_cycle(struct rc_dev
*dev
, u32 duty_cycle
)
34 struct gpio_ir
*gpio_ir
= dev
->priv
;
36 gpio_ir
->duty_cycle
= duty_cycle
;
41 static int gpio_ir_tx_set_carrier(struct rc_dev
*dev
, u32 carrier
)
43 struct gpio_ir
*gpio_ir
= dev
->priv
;
48 gpio_ir
->carrier
= carrier
;
53 static int gpio_ir_tx(struct rc_dev
*dev
, unsigned int *txbuf
,
56 struct gpio_ir
*gpio_ir
= dev
->priv
;
60 * delta should never exceed 0.5 seconds (IR_MAX_DURATION) and on
61 * m68k ndelay(s64) does not compile; so use s32 rather than s64.
65 unsigned int pulse
, space
;
67 /* Ensure the dividend fits into 32 bit */
68 pulse
= DIV_ROUND_CLOSEST(gpio_ir
->duty_cycle
* (NSEC_PER_SEC
/ 100),
70 space
= DIV_ROUND_CLOSEST((100 - gpio_ir
->duty_cycle
) *
71 (NSEC_PER_SEC
/ 100), gpio_ir
->carrier
);
73 spin_lock_irqsave(&gpio_ir
->lock
, flags
);
77 for (i
= 0; i
< count
; i
++) {
80 edge
= ktime_add_us(edge
, txbuf
[i
]);
81 delta
= ktime_us_delta(edge
, ktime_get());
83 spin_unlock_irqrestore(&gpio_ir
->lock
, flags
);
84 usleep_range(delta
, delta
+ 10);
85 spin_lock_irqsave(&gpio_ir
->lock
, flags
);
86 } else if (delta
> 0) {
91 ktime_t last
= ktime_add_us(edge
, txbuf
[i
]);
93 while (ktime_before(ktime_get(), last
)) {
94 gpiod_set_value(gpio_ir
->gpio
, 1);
95 edge
= ktime_add_ns(edge
, pulse
);
96 delta
= ktime_to_ns(ktime_sub(edge
,
100 gpiod_set_value(gpio_ir
->gpio
, 0);
101 edge
= ktime_add_ns(edge
, space
);
102 delta
= ktime_to_ns(ktime_sub(edge
,
112 spin_unlock_irqrestore(&gpio_ir
->lock
, flags
);
117 static int gpio_ir_tx_probe(struct platform_device
*pdev
)
119 struct gpio_ir
*gpio_ir
;
120 struct rc_dev
*rcdev
;
123 gpio_ir
= devm_kmalloc(&pdev
->dev
, sizeof(*gpio_ir
), GFP_KERNEL
);
127 rcdev
= devm_rc_allocate_device(&pdev
->dev
, RC_DRIVER_IR_RAW_TX
);
131 gpio_ir
->gpio
= devm_gpiod_get(&pdev
->dev
, NULL
, GPIOD_OUT_LOW
);
132 if (IS_ERR(gpio_ir
->gpio
)) {
133 if (PTR_ERR(gpio_ir
->gpio
) != -EPROBE_DEFER
)
134 dev_err(&pdev
->dev
, "Failed to get gpio (%ld)\n",
135 PTR_ERR(gpio_ir
->gpio
));
136 return PTR_ERR(gpio_ir
->gpio
);
139 rcdev
->priv
= gpio_ir
;
140 rcdev
->driver_name
= DRIVER_NAME
;
141 rcdev
->device_name
= DEVICE_NAME
;
142 rcdev
->tx_ir
= gpio_ir_tx
;
143 rcdev
->s_tx_duty_cycle
= gpio_ir_tx_set_duty_cycle
;
144 rcdev
->s_tx_carrier
= gpio_ir_tx_set_carrier
;
146 gpio_ir
->carrier
= 38000;
147 gpio_ir
->duty_cycle
= 50;
148 spin_lock_init(&gpio_ir
->lock
);
150 rc
= devm_rc_register_device(&pdev
->dev
, rcdev
);
152 dev_err(&pdev
->dev
, "failed to register rc device\n");
157 static struct platform_driver gpio_ir_tx_driver
= {
158 .probe
= gpio_ir_tx_probe
,
161 .of_match_table
= of_match_ptr(gpio_ir_tx_of_match
),
164 module_platform_driver(gpio_ir_tx_driver
);
166 MODULE_DESCRIPTION("GPIO IR Bit Banging Transmitter");
167 MODULE_AUTHOR("Sean Young <sean@mess.org>");
168 MODULE_LICENSE("GPL");