10
10
#include <linux/slab.h>
11
11
#include <linux/of.h>
12
12
#include <linux/platform_device.h>
13
+ #include <linux/hrtimer.h>
14
+ #include <linux/completion.h>
13
15
#include <media/rc-core.h>
14
16
15
17
#define DRIVER_NAME "pwm-ir-tx"
16
18
#define DEVICE_NAME "PWM IR Transmitter"
17
19
18
20
struct pwm_ir {
19
21
struct pwm_device * pwm ;
20
- unsigned int carrier ;
21
- unsigned int duty_cycle ;
22
+ struct hrtimer timer ;
23
+ struct completion tx_done ;
24
+ struct pwm_state * state ;
25
+ u32 carrier ;
26
+ u32 duty_cycle ;
27
+ const unsigned int * txbuf ;
28
+ unsigned int txbuf_len ;
29
+ unsigned int txbuf_index ;
22
30
};
23
31
24
32
static const struct of_device_id pwm_ir_of_match [] = {
@@ -49,8 +57,8 @@ static int pwm_ir_set_carrier(struct rc_dev *dev, u32 carrier)
49
57
return 0 ;
50
58
}
51
59
52
- static int pwm_ir_tx (struct rc_dev * dev , unsigned int * txbuf ,
53
- unsigned int count )
60
+ static int pwm_ir_tx_sleep (struct rc_dev * dev , unsigned int * txbuf ,
61
+ unsigned int count )
54
62
{
55
63
struct pwm_ir * pwm_ir = dev -> priv ;
56
64
struct pwm_device * pwm = pwm_ir -> pwm ;
@@ -82,6 +90,62 @@ static int pwm_ir_tx(struct rc_dev *dev, unsigned int *txbuf,
82
90
return count ;
83
91
}
84
92
93
+ static int pwm_ir_tx_atomic (struct rc_dev * dev , unsigned int * txbuf ,
94
+ unsigned int count )
95
+ {
96
+ struct pwm_ir * pwm_ir = dev -> priv ;
97
+ struct pwm_device * pwm = pwm_ir -> pwm ;
98
+ struct pwm_state state ;
99
+
100
+ pwm_init_state (pwm , & state );
101
+
102
+ state .period = DIV_ROUND_CLOSEST (NSEC_PER_SEC , pwm_ir -> carrier );
103
+ pwm_set_relative_duty_cycle (& state , pwm_ir -> duty_cycle , 100 );
104
+
105
+ pwm_ir -> txbuf = txbuf ;
106
+ pwm_ir -> txbuf_len = count ;
107
+ pwm_ir -> txbuf_index = 0 ;
108
+ pwm_ir -> state = & state ;
109
+
110
+ hrtimer_start (& pwm_ir -> timer , 0 , HRTIMER_MODE_REL );
111
+
112
+ wait_for_completion (& pwm_ir -> tx_done );
113
+
114
+ return count ;
115
+ }
116
+
117
+ static enum hrtimer_restart pwm_ir_timer (struct hrtimer * timer )
118
+ {
119
+ struct pwm_ir * pwm_ir = container_of (timer , struct pwm_ir , timer );
120
+ ktime_t now ;
121
+
122
+ /*
123
+ * If we happen to hit an odd latency spike, loop through the
124
+ * pulses until we catch up.
125
+ */
126
+ do {
127
+ u64 ns ;
128
+
129
+ pwm_ir -> state -> enabled = !(pwm_ir -> txbuf_index % 2 );
130
+ pwm_apply_atomic (pwm_ir -> pwm , pwm_ir -> state );
131
+
132
+ if (pwm_ir -> txbuf_index >= pwm_ir -> txbuf_len ) {
133
+ complete (& pwm_ir -> tx_done );
134
+
135
+ return HRTIMER_NORESTART ;
136
+ }
137
+
138
+ ns = US_TO_NS (pwm_ir -> txbuf [pwm_ir -> txbuf_index ]);
139
+ hrtimer_add_expires_ns (timer , ns );
140
+
141
+ pwm_ir -> txbuf_index ++ ;
142
+
143
+ now = timer -> base -> get_time ();
144
+ } while (hrtimer_get_expires_tv64 (timer ) < now );
145
+
146
+ return HRTIMER_RESTART ;
147
+ }
148
+
85
149
static int pwm_ir_probe (struct platform_device * pdev )
86
150
{
87
151
struct pwm_ir * pwm_ir ;
@@ -103,10 +167,19 @@ static int pwm_ir_probe(struct platform_device *pdev)
103
167
if (!rcdev )
104
168
return - ENOMEM ;
105
169
170
+ if (pwm_might_sleep (pwm_ir -> pwm )) {
171
+ dev_info (& pdev -> dev , "TX will not be accurate as PWM device might sleep\n" );
172
+ rcdev -> tx_ir = pwm_ir_tx_sleep ;
173
+ } else {
174
+ init_completion (& pwm_ir -> tx_done );
175
+ hrtimer_init (& pwm_ir -> timer , CLOCK_MONOTONIC , HRTIMER_MODE_REL );
176
+ pwm_ir -> timer .function = pwm_ir_timer ;
177
+ rcdev -> tx_ir = pwm_ir_tx_atomic ;
178
+ }
179
+
106
180
rcdev -> priv = pwm_ir ;
107
181
rcdev -> driver_name = DRIVER_NAME ;
108
182
rcdev -> device_name = DEVICE_NAME ;
109
- rcdev -> tx_ir = pwm_ir_tx ;
110
183
rcdev -> s_tx_duty_cycle = pwm_ir_set_duty_cycle ;
111
184
rcdev -> s_tx_carrier = pwm_ir_set_carrier ;
112
185
0 commit comments