diff options
Diffstat (limited to 'drivers/media/cec/cec-pin.c')
-rw-r--r-- | drivers/media/cec/cec-pin.c | 678 |
1 files changed, 591 insertions, 87 deletions
diff --git a/drivers/media/cec/cec-pin.c b/drivers/media/cec/cec-pin.c index b48dfe844118..fafe1ebc8aff 100644 --- a/drivers/media/cec/cec-pin.c +++ b/drivers/media/cec/cec-pin.c | |||
@@ -1,18 +1,6 @@ | |||
1 | // SPDX-License-Identifier: GPL-2.0-only | ||
1 | /* | 2 | /* |
2 | * Copyright 2017 Cisco Systems, Inc. and/or its affiliates. All rights reserved. | 3 | * Copyright 2017 Cisco Systems, Inc. and/or its affiliates. All rights reserved. |
3 | * | ||
4 | * This program is free software; you may redistribute it and/or modify | ||
5 | * it under the terms of the GNU General Public License as published by | ||
6 | * the Free Software Foundation; version 2 of the License. | ||
7 | * | ||
8 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, | ||
9 | * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF | ||
10 | * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND | ||
11 | * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS | ||
12 | * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN | ||
13 | * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN | ||
14 | * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE | ||
15 | * SOFTWARE. | ||
16 | */ | 4 | */ |
17 | 5 | ||
18 | #include <linux/delay.h> | 6 | #include <linux/delay.h> |
@@ -51,11 +39,29 @@ | |||
51 | #define CEC_TIM_IDLE_SAMPLE 1000 | 39 | #define CEC_TIM_IDLE_SAMPLE 1000 |
52 | /* when processing the start bit, sample twice per millisecond */ | 40 | /* when processing the start bit, sample twice per millisecond */ |
53 | #define CEC_TIM_START_BIT_SAMPLE 500 | 41 | #define CEC_TIM_START_BIT_SAMPLE 500 |
54 | /* when polling for a state change, sample once every 50 micoseconds */ | 42 | /* when polling for a state change, sample once every 50 microseconds */ |
55 | #define CEC_TIM_SAMPLE 50 | 43 | #define CEC_TIM_SAMPLE 50 |
56 | 44 | ||
57 | #define CEC_TIM_LOW_DRIVE_ERROR (1.5 * CEC_TIM_DATA_BIT_TOTAL) | 45 | #define CEC_TIM_LOW_DRIVE_ERROR (1.5 * CEC_TIM_DATA_BIT_TOTAL) |
58 | 46 | ||
47 | /* | ||
48 | * Total data bit time that is too short/long for a valid bit, | ||
49 | * used for error injection. | ||
50 | */ | ||
51 | #define CEC_TIM_DATA_BIT_TOTAL_SHORT 1800 | ||
52 | #define CEC_TIM_DATA_BIT_TOTAL_LONG 2900 | ||
53 | |||
54 | /* | ||
55 | * Total start bit time that is too short/long for a valid bit, | ||
56 | * used for error injection. | ||
57 | */ | ||
58 | #define CEC_TIM_START_BIT_TOTAL_SHORT 4100 | ||
59 | #define CEC_TIM_START_BIT_TOTAL_LONG 5000 | ||
60 | |||
61 | /* Data bits are 0-7, EOM is bit 8 and ACK is bit 9 */ | ||
62 | #define EOM_BIT 8 | ||
63 | #define ACK_BIT 9 | ||
64 | |||
59 | struct cec_state { | 65 | struct cec_state { |
60 | const char * const name; | 66 | const char * const name; |
61 | unsigned int usecs; | 67 | unsigned int usecs; |
@@ -68,17 +74,32 @@ static const struct cec_state states[CEC_PIN_STATES] = { | |||
68 | { "Tx Wait for High", CEC_TIM_IDLE_SAMPLE }, | 74 | { "Tx Wait for High", CEC_TIM_IDLE_SAMPLE }, |
69 | { "Tx Start Bit Low", CEC_TIM_START_BIT_LOW }, | 75 | { "Tx Start Bit Low", CEC_TIM_START_BIT_LOW }, |
70 | { "Tx Start Bit High", CEC_TIM_START_BIT_TOTAL - CEC_TIM_START_BIT_LOW }, | 76 | { "Tx Start Bit High", CEC_TIM_START_BIT_TOTAL - CEC_TIM_START_BIT_LOW }, |
77 | { "Tx Start Bit High Short", CEC_TIM_START_BIT_TOTAL_SHORT - CEC_TIM_START_BIT_LOW }, | ||
78 | { "Tx Start Bit High Long", CEC_TIM_START_BIT_TOTAL_LONG - CEC_TIM_START_BIT_LOW }, | ||
79 | { "Tx Start Bit Low Custom", 0 }, | ||
80 | { "Tx Start Bit High Custom", 0 }, | ||
71 | { "Tx Data 0 Low", CEC_TIM_DATA_BIT_0_LOW }, | 81 | { "Tx Data 0 Low", CEC_TIM_DATA_BIT_0_LOW }, |
72 | { "Tx Data 0 High", CEC_TIM_DATA_BIT_TOTAL - CEC_TIM_DATA_BIT_0_LOW }, | 82 | { "Tx Data 0 High", CEC_TIM_DATA_BIT_TOTAL - CEC_TIM_DATA_BIT_0_LOW }, |
83 | { "Tx Data 0 High Short", CEC_TIM_DATA_BIT_TOTAL_SHORT - CEC_TIM_DATA_BIT_0_LOW }, | ||
84 | { "Tx Data 0 High Long", CEC_TIM_DATA_BIT_TOTAL_LONG - CEC_TIM_DATA_BIT_0_LOW }, | ||
73 | { "Tx Data 1 Low", CEC_TIM_DATA_BIT_1_LOW }, | 85 | { "Tx Data 1 Low", CEC_TIM_DATA_BIT_1_LOW }, |
74 | { "Tx Data 1 High", CEC_TIM_DATA_BIT_TOTAL - CEC_TIM_DATA_BIT_1_LOW }, | 86 | { "Tx Data 1 High", CEC_TIM_DATA_BIT_TOTAL - CEC_TIM_DATA_BIT_1_LOW }, |
75 | { "Tx Data 1 Pre Sample", CEC_TIM_DATA_BIT_SAMPLE - CEC_TIM_DATA_BIT_1_LOW }, | 87 | { "Tx Data 1 High Short", CEC_TIM_DATA_BIT_TOTAL_SHORT - CEC_TIM_DATA_BIT_1_LOW }, |
76 | { "Tx Data 1 Post Sample", CEC_TIM_DATA_BIT_TOTAL - CEC_TIM_DATA_BIT_SAMPLE }, | 88 | { "Tx Data 1 High Long", CEC_TIM_DATA_BIT_TOTAL_LONG - CEC_TIM_DATA_BIT_1_LOW }, |
89 | { "Tx Data 1 High Pre Sample", CEC_TIM_DATA_BIT_SAMPLE - CEC_TIM_DATA_BIT_1_LOW }, | ||
90 | { "Tx Data 1 High Post Sample", CEC_TIM_DATA_BIT_TOTAL - CEC_TIM_DATA_BIT_SAMPLE }, | ||
91 | { "Tx Data 1 High Post Sample Short", CEC_TIM_DATA_BIT_TOTAL_SHORT - CEC_TIM_DATA_BIT_SAMPLE }, | ||
92 | { "Tx Data 1 High Post Sample Long", CEC_TIM_DATA_BIT_TOTAL_LONG - CEC_TIM_DATA_BIT_SAMPLE }, | ||
93 | { "Tx Data Bit Low Custom", 0 }, | ||
94 | { "Tx Data Bit High Custom", 0 }, | ||
95 | { "Tx Pulse Low Custom", 0 }, | ||
96 | { "Tx Pulse High Custom", 0 }, | ||
97 | { "Tx Low Drive", CEC_TIM_LOW_DRIVE_ERROR }, | ||
77 | { "Rx Start Bit Low", CEC_TIM_SAMPLE }, | 98 | { "Rx Start Bit Low", CEC_TIM_SAMPLE }, |
78 | { "Rx Start Bit High", CEC_TIM_SAMPLE }, | 99 | { "Rx Start Bit High", CEC_TIM_SAMPLE }, |
79 | { "Rx Data Sample", CEC_TIM_DATA_BIT_SAMPLE }, | 100 | { "Rx Data Sample", CEC_TIM_DATA_BIT_SAMPLE }, |
80 | { "Rx Data Post Sample", CEC_TIM_DATA_BIT_HIGH - CEC_TIM_DATA_BIT_SAMPLE }, | 101 | { "Rx Data Post Sample", CEC_TIM_DATA_BIT_HIGH - CEC_TIM_DATA_BIT_SAMPLE }, |
81 | { "Rx Data High", CEC_TIM_SAMPLE }, | 102 | { "Rx Data Wait for Low", CEC_TIM_SAMPLE }, |
82 | { "Rx Ack Low", CEC_TIM_DATA_BIT_0_LOW }, | 103 | { "Rx Ack Low", CEC_TIM_DATA_BIT_0_LOW }, |
83 | { "Rx Ack Low Post", CEC_TIM_DATA_BIT_HIGH - CEC_TIM_DATA_BIT_0_LOW }, | 104 | { "Rx Ack Low Post", CEC_TIM_DATA_BIT_HIGH - CEC_TIM_DATA_BIT_0_LOW }, |
84 | { "Rx Ack High Post", CEC_TIM_DATA_BIT_HIGH }, | 105 | { "Rx Ack High Post", CEC_TIM_DATA_BIT_HIGH }, |
@@ -93,12 +114,21 @@ static void cec_pin_update(struct cec_pin *pin, bool v, bool force) | |||
93 | return; | 114 | return; |
94 | 115 | ||
95 | pin->adap->cec_pin_is_high = v; | 116 | pin->adap->cec_pin_is_high = v; |
96 | if (atomic_read(&pin->work_pin_events) < CEC_NUM_PIN_EVENTS) { | 117 | if (atomic_read(&pin->work_pin_num_events) < CEC_NUM_PIN_EVENTS) { |
97 | pin->work_pin_is_high[pin->work_pin_events_wr] = v; | 118 | u8 ev = v; |
119 | |||
120 | if (pin->work_pin_events_dropped) { | ||
121 | pin->work_pin_events_dropped = false; | ||
122 | v |= CEC_PIN_EVENT_FL_DROPPED; | ||
123 | } | ||
124 | pin->work_pin_events[pin->work_pin_events_wr] = ev; | ||
98 | pin->work_pin_ts[pin->work_pin_events_wr] = ktime_get(); | 125 | pin->work_pin_ts[pin->work_pin_events_wr] = ktime_get(); |
99 | pin->work_pin_events_wr = | 126 | pin->work_pin_events_wr = |
100 | (pin->work_pin_events_wr + 1) % CEC_NUM_PIN_EVENTS; | 127 | (pin->work_pin_events_wr + 1) % CEC_NUM_PIN_EVENTS; |
101 | atomic_inc(&pin->work_pin_events); | 128 | atomic_inc(&pin->work_pin_num_events); |
129 | } else { | ||
130 | pin->work_pin_events_dropped = true; | ||
131 | pin->work_pin_events_dropped_cnt++; | ||
102 | } | 132 | } |
103 | wake_up_interruptible(&pin->kthread_waitq); | 133 | wake_up_interruptible(&pin->kthread_waitq); |
104 | } | 134 | } |
@@ -123,6 +153,173 @@ static bool cec_pin_high(struct cec_pin *pin) | |||
123 | return cec_pin_read(pin); | 153 | return cec_pin_read(pin); |
124 | } | 154 | } |
125 | 155 | ||
156 | static bool rx_error_inj(struct cec_pin *pin, unsigned int mode_offset, | ||
157 | int arg_idx, u8 *arg) | ||
158 | { | ||
159 | #ifdef CONFIG_CEC_PIN_ERROR_INJ | ||
160 | u16 cmd = cec_pin_rx_error_inj(pin); | ||
161 | u64 e = pin->error_inj[cmd]; | ||
162 | unsigned int mode = (e >> mode_offset) & CEC_ERROR_INJ_MODE_MASK; | ||
163 | |||
164 | if (arg_idx >= 0) { | ||
165 | u8 pos = pin->error_inj_args[cmd][arg_idx]; | ||
166 | |||
167 | if (arg) | ||
168 | *arg = pos; | ||
169 | else if (pos != pin->rx_bit) | ||
170 | return false; | ||
171 | } | ||
172 | |||
173 | switch (mode) { | ||
174 | case CEC_ERROR_INJ_MODE_ONCE: | ||
175 | pin->error_inj[cmd] &= | ||
176 | ~(CEC_ERROR_INJ_MODE_MASK << mode_offset); | ||
177 | return true; | ||
178 | case CEC_ERROR_INJ_MODE_ALWAYS: | ||
179 | return true; | ||
180 | case CEC_ERROR_INJ_MODE_TOGGLE: | ||
181 | return pin->rx_toggle; | ||
182 | default: | ||
183 | return false; | ||
184 | } | ||
185 | #else | ||
186 | return false; | ||
187 | #endif | ||
188 | } | ||
189 | |||
190 | static bool rx_nack(struct cec_pin *pin) | ||
191 | { | ||
192 | return rx_error_inj(pin, CEC_ERROR_INJ_RX_NACK_OFFSET, -1, NULL); | ||
193 | } | ||
194 | |||
195 | static bool rx_low_drive(struct cec_pin *pin) | ||
196 | { | ||
197 | return rx_error_inj(pin, CEC_ERROR_INJ_RX_LOW_DRIVE_OFFSET, | ||
198 | CEC_ERROR_INJ_RX_LOW_DRIVE_ARG_IDX, NULL); | ||
199 | } | ||
200 | |||
201 | static bool rx_add_byte(struct cec_pin *pin) | ||
202 | { | ||
203 | return rx_error_inj(pin, CEC_ERROR_INJ_RX_ADD_BYTE_OFFSET, -1, NULL); | ||
204 | } | ||
205 | |||
206 | static bool rx_remove_byte(struct cec_pin *pin) | ||
207 | { | ||
208 | return rx_error_inj(pin, CEC_ERROR_INJ_RX_REMOVE_BYTE_OFFSET, -1, NULL); | ||
209 | } | ||
210 | |||
211 | static bool rx_arb_lost(struct cec_pin *pin, u8 *poll) | ||
212 | { | ||
213 | return pin->tx_msg.len == 0 && | ||
214 | rx_error_inj(pin, CEC_ERROR_INJ_RX_ARB_LOST_OFFSET, | ||
215 | CEC_ERROR_INJ_RX_ARB_LOST_ARG_IDX, poll); | ||
216 | } | ||
217 | |||
218 | static bool tx_error_inj(struct cec_pin *pin, unsigned int mode_offset, | ||
219 | int arg_idx, u8 *arg) | ||
220 | { | ||
221 | #ifdef CONFIG_CEC_PIN_ERROR_INJ | ||
222 | u16 cmd = cec_pin_tx_error_inj(pin); | ||
223 | u64 e = pin->error_inj[cmd]; | ||
224 | unsigned int mode = (e >> mode_offset) & CEC_ERROR_INJ_MODE_MASK; | ||
225 | |||
226 | if (arg_idx >= 0) { | ||
227 | u8 pos = pin->error_inj_args[cmd][arg_idx]; | ||
228 | |||
229 | if (arg) | ||
230 | *arg = pos; | ||
231 | else if (pos != pin->tx_bit) | ||
232 | return false; | ||
233 | } | ||
234 | |||
235 | switch (mode) { | ||
236 | case CEC_ERROR_INJ_MODE_ONCE: | ||
237 | pin->error_inj[cmd] &= | ||
238 | ~(CEC_ERROR_INJ_MODE_MASK << mode_offset); | ||
239 | return true; | ||
240 | case CEC_ERROR_INJ_MODE_ALWAYS: | ||
241 | return true; | ||
242 | case CEC_ERROR_INJ_MODE_TOGGLE: | ||
243 | return pin->tx_toggle; | ||
244 | default: | ||
245 | return false; | ||
246 | } | ||
247 | #else | ||
248 | return false; | ||
249 | #endif | ||
250 | } | ||
251 | |||
252 | static bool tx_no_eom(struct cec_pin *pin) | ||
253 | { | ||
254 | return tx_error_inj(pin, CEC_ERROR_INJ_TX_NO_EOM_OFFSET, -1, NULL); | ||
255 | } | ||
256 | |||
257 | static bool tx_early_eom(struct cec_pin *pin) | ||
258 | { | ||
259 | return tx_error_inj(pin, CEC_ERROR_INJ_TX_EARLY_EOM_OFFSET, -1, NULL); | ||
260 | } | ||
261 | |||
262 | static bool tx_short_bit(struct cec_pin *pin) | ||
263 | { | ||
264 | return tx_error_inj(pin, CEC_ERROR_INJ_TX_SHORT_BIT_OFFSET, | ||
265 | CEC_ERROR_INJ_TX_SHORT_BIT_ARG_IDX, NULL); | ||
266 | } | ||
267 | |||
268 | static bool tx_long_bit(struct cec_pin *pin) | ||
269 | { | ||
270 | return tx_error_inj(pin, CEC_ERROR_INJ_TX_LONG_BIT_OFFSET, | ||
271 | CEC_ERROR_INJ_TX_LONG_BIT_ARG_IDX, NULL); | ||
272 | } | ||
273 | |||
274 | static bool tx_custom_bit(struct cec_pin *pin) | ||
275 | { | ||
276 | return tx_error_inj(pin, CEC_ERROR_INJ_TX_CUSTOM_BIT_OFFSET, | ||
277 | CEC_ERROR_INJ_TX_CUSTOM_BIT_ARG_IDX, NULL); | ||
278 | } | ||
279 | |||
280 | static bool tx_short_start(struct cec_pin *pin) | ||
281 | { | ||
282 | return tx_error_inj(pin, CEC_ERROR_INJ_TX_SHORT_START_OFFSET, -1, NULL); | ||
283 | } | ||
284 | |||
285 | static bool tx_long_start(struct cec_pin *pin) | ||
286 | { | ||
287 | return tx_error_inj(pin, CEC_ERROR_INJ_TX_LONG_START_OFFSET, -1, NULL); | ||
288 | } | ||
289 | |||
290 | static bool tx_custom_start(struct cec_pin *pin) | ||
291 | { | ||
292 | return tx_error_inj(pin, CEC_ERROR_INJ_TX_CUSTOM_START_OFFSET, | ||
293 | -1, NULL); | ||
294 | } | ||
295 | |||
296 | static bool tx_last_bit(struct cec_pin *pin) | ||
297 | { | ||
298 | return tx_error_inj(pin, CEC_ERROR_INJ_TX_LAST_BIT_OFFSET, | ||
299 | CEC_ERROR_INJ_TX_LAST_BIT_ARG_IDX, NULL); | ||
300 | } | ||
301 | |||
302 | static u8 tx_add_bytes(struct cec_pin *pin) | ||
303 | { | ||
304 | u8 bytes; | ||
305 | |||
306 | if (tx_error_inj(pin, CEC_ERROR_INJ_TX_ADD_BYTES_OFFSET, | ||
307 | CEC_ERROR_INJ_TX_ADD_BYTES_ARG_IDX, &bytes)) | ||
308 | return bytes; | ||
309 | return 0; | ||
310 | } | ||
311 | |||
312 | static bool tx_remove_byte(struct cec_pin *pin) | ||
313 | { | ||
314 | return tx_error_inj(pin, CEC_ERROR_INJ_TX_REMOVE_BYTE_OFFSET, -1, NULL); | ||
315 | } | ||
316 | |||
317 | static bool tx_low_drive(struct cec_pin *pin) | ||
318 | { | ||
319 | return tx_error_inj(pin, CEC_ERROR_INJ_TX_LOW_DRIVE_OFFSET, | ||
320 | CEC_ERROR_INJ_TX_LOW_DRIVE_ARG_IDX, NULL); | ||
321 | } | ||
322 | |||
126 | static void cec_pin_to_idle(struct cec_pin *pin) | 323 | static void cec_pin_to_idle(struct cec_pin *pin) |
127 | { | 324 | { |
128 | /* | 325 | /* |
@@ -132,8 +329,16 @@ static void cec_pin_to_idle(struct cec_pin *pin) | |||
132 | pin->rx_bit = pin->tx_bit = 0; | 329 | pin->rx_bit = pin->tx_bit = 0; |
133 | pin->rx_msg.len = 0; | 330 | pin->rx_msg.len = 0; |
134 | memset(pin->rx_msg.msg, 0, sizeof(pin->rx_msg.msg)); | 331 | memset(pin->rx_msg.msg, 0, sizeof(pin->rx_msg.msg)); |
135 | pin->state = CEC_ST_IDLE; | ||
136 | pin->ts = ns_to_ktime(0); | 332 | pin->ts = ns_to_ktime(0); |
333 | pin->tx_generated_poll = false; | ||
334 | pin->tx_post_eom = false; | ||
335 | if (pin->state >= CEC_ST_TX_WAIT && | ||
336 | pin->state <= CEC_ST_TX_LOW_DRIVE) | ||
337 | pin->tx_toggle ^= 1; | ||
338 | if (pin->state >= CEC_ST_RX_START_BIT_LOW && | ||
339 | pin->state <= CEC_ST_RX_LOW_DRIVE) | ||
340 | pin->rx_toggle ^= 1; | ||
341 | pin->state = CEC_ST_IDLE; | ||
137 | } | 342 | } |
138 | 343 | ||
139 | /* | 344 | /* |
@@ -174,42 +379,109 @@ static void cec_pin_tx_states(struct cec_pin *pin, ktime_t ts) | |||
174 | break; | 379 | break; |
175 | 380 | ||
176 | case CEC_ST_TX_START_BIT_LOW: | 381 | case CEC_ST_TX_START_BIT_LOW: |
177 | pin->state = CEC_ST_TX_START_BIT_HIGH; | 382 | if (tx_short_start(pin)) { |
383 | /* | ||
384 | * Error Injection: send an invalid (too short) | ||
385 | * start pulse. | ||
386 | */ | ||
387 | pin->state = CEC_ST_TX_START_BIT_HIGH_SHORT; | ||
388 | } else if (tx_long_start(pin)) { | ||
389 | /* | ||
390 | * Error Injection: send an invalid (too long) | ||
391 | * start pulse. | ||
392 | */ | ||
393 | pin->state = CEC_ST_TX_START_BIT_HIGH_LONG; | ||
394 | } else { | ||
395 | pin->state = CEC_ST_TX_START_BIT_HIGH; | ||
396 | } | ||
397 | /* Generate start bit */ | ||
398 | cec_pin_high(pin); | ||
399 | break; | ||
400 | |||
401 | case CEC_ST_TX_START_BIT_LOW_CUSTOM: | ||
402 | pin->state = CEC_ST_TX_START_BIT_HIGH_CUSTOM; | ||
178 | /* Generate start bit */ | 403 | /* Generate start bit */ |
179 | cec_pin_high(pin); | 404 | cec_pin_high(pin); |
180 | break; | 405 | break; |
181 | 406 | ||
182 | case CEC_ST_TX_DATA_BIT_1_HIGH_POST_SAMPLE: | 407 | case CEC_ST_TX_DATA_BIT_1_HIGH_POST_SAMPLE: |
183 | /* If the read value is 1, then all is OK */ | 408 | case CEC_ST_TX_DATA_BIT_1_HIGH_POST_SAMPLE_SHORT: |
184 | if (!cec_pin_read(pin)) { | 409 | case CEC_ST_TX_DATA_BIT_1_HIGH_POST_SAMPLE_LONG: |
410 | if (pin->tx_nacked) { | ||
411 | cec_pin_to_idle(pin); | ||
412 | pin->tx_msg.len = 0; | ||
413 | if (pin->tx_generated_poll) | ||
414 | break; | ||
415 | pin->work_tx_ts = ts; | ||
416 | pin->work_tx_status = CEC_TX_STATUS_NACK; | ||
417 | wake_up_interruptible(&pin->kthread_waitq); | ||
418 | break; | ||
419 | } | ||
420 | /* fall through */ | ||
421 | case CEC_ST_TX_DATA_BIT_0_HIGH: | ||
422 | case CEC_ST_TX_DATA_BIT_0_HIGH_SHORT: | ||
423 | case CEC_ST_TX_DATA_BIT_0_HIGH_LONG: | ||
424 | case CEC_ST_TX_DATA_BIT_1_HIGH: | ||
425 | case CEC_ST_TX_DATA_BIT_1_HIGH_SHORT: | ||
426 | case CEC_ST_TX_DATA_BIT_1_HIGH_LONG: | ||
427 | /* | ||
428 | * If the read value is 1, then all is OK, otherwise we have a | ||
429 | * low drive condition. | ||
430 | * | ||
431 | * Special case: when we generate a poll message due to an | ||
432 | * Arbitration Lost error injection, then ignore this since | ||
433 | * the pin can actually be low in that case. | ||
434 | */ | ||
435 | if (!cec_pin_read(pin) && !pin->tx_generated_poll) { | ||
185 | /* | 436 | /* |
186 | * It's 0, so someone detected an error and pulled the | 437 | * It's 0, so someone detected an error and pulled the |
187 | * line low for 1.5 times the nominal bit period. | 438 | * line low for 1.5 times the nominal bit period. |
188 | */ | 439 | */ |
189 | pin->tx_msg.len = 0; | 440 | pin->tx_msg.len = 0; |
441 | pin->state = CEC_ST_TX_WAIT_FOR_HIGH; | ||
190 | pin->work_tx_ts = ts; | 442 | pin->work_tx_ts = ts; |
191 | pin->work_tx_status = CEC_TX_STATUS_LOW_DRIVE; | 443 | pin->work_tx_status = CEC_TX_STATUS_LOW_DRIVE; |
192 | pin->state = CEC_ST_TX_WAIT_FOR_HIGH; | 444 | pin->tx_low_drive_cnt++; |
193 | wake_up_interruptible(&pin->kthread_waitq); | 445 | wake_up_interruptible(&pin->kthread_waitq); |
194 | break; | 446 | break; |
195 | } | 447 | } |
196 | if (pin->tx_nacked) { | 448 | /* fall through */ |
449 | case CEC_ST_TX_DATA_BIT_HIGH_CUSTOM: | ||
450 | if (tx_last_bit(pin)) { | ||
451 | /* Error Injection: just stop sending after this bit */ | ||
197 | cec_pin_to_idle(pin); | 452 | cec_pin_to_idle(pin); |
198 | pin->tx_msg.len = 0; | 453 | pin->tx_msg.len = 0; |
454 | if (pin->tx_generated_poll) | ||
455 | break; | ||
199 | pin->work_tx_ts = ts; | 456 | pin->work_tx_ts = ts; |
200 | pin->work_tx_status = CEC_TX_STATUS_NACK; | 457 | pin->work_tx_status = CEC_TX_STATUS_OK; |
201 | wake_up_interruptible(&pin->kthread_waitq); | 458 | wake_up_interruptible(&pin->kthread_waitq); |
202 | break; | 459 | break; |
203 | } | 460 | } |
204 | /* fall through */ | ||
205 | case CEC_ST_TX_DATA_BIT_0_HIGH: | ||
206 | case CEC_ST_TX_DATA_BIT_1_HIGH: | ||
207 | pin->tx_bit++; | 461 | pin->tx_bit++; |
208 | /* fall through */ | 462 | /* fall through */ |
209 | case CEC_ST_TX_START_BIT_HIGH: | 463 | case CEC_ST_TX_START_BIT_HIGH: |
210 | if (pin->tx_bit / 10 >= pin->tx_msg.len) { | 464 | case CEC_ST_TX_START_BIT_HIGH_SHORT: |
465 | case CEC_ST_TX_START_BIT_HIGH_LONG: | ||
466 | case CEC_ST_TX_START_BIT_HIGH_CUSTOM: | ||
467 | if (tx_low_drive(pin)) { | ||
468 | /* Error injection: go to low drive */ | ||
469 | cec_pin_low(pin); | ||
470 | pin->state = CEC_ST_TX_LOW_DRIVE; | ||
471 | pin->tx_msg.len = 0; | ||
472 | if (pin->tx_generated_poll) | ||
473 | break; | ||
474 | pin->work_tx_ts = ts; | ||
475 | pin->work_tx_status = CEC_TX_STATUS_LOW_DRIVE; | ||
476 | pin->tx_low_drive_cnt++; | ||
477 | wake_up_interruptible(&pin->kthread_waitq); | ||
478 | break; | ||
479 | } | ||
480 | if (pin->tx_bit / 10 >= pin->tx_msg.len + pin->tx_extra_bytes) { | ||
211 | cec_pin_to_idle(pin); | 481 | cec_pin_to_idle(pin); |
212 | pin->tx_msg.len = 0; | 482 | pin->tx_msg.len = 0; |
483 | if (pin->tx_generated_poll) | ||
484 | break; | ||
213 | pin->work_tx_ts = ts; | 485 | pin->work_tx_ts = ts; |
214 | pin->work_tx_status = CEC_TX_STATUS_OK; | 486 | pin->work_tx_status = CEC_TX_STATUS_OK; |
215 | wake_up_interruptible(&pin->kthread_waitq); | 487 | wake_up_interruptible(&pin->kthread_waitq); |
@@ -217,39 +489,82 @@ static void cec_pin_tx_states(struct cec_pin *pin, ktime_t ts) | |||
217 | } | 489 | } |
218 | 490 | ||
219 | switch (pin->tx_bit % 10) { | 491 | switch (pin->tx_bit % 10) { |
220 | default: | 492 | default: { |
221 | v = pin->tx_msg.msg[pin->tx_bit / 10] & | 493 | /* |
222 | (1 << (7 - (pin->tx_bit % 10))); | 494 | * In the CEC_ERROR_INJ_TX_ADD_BYTES case we transmit |
495 | * extra bytes, so pin->tx_bit / 10 can become >= 16. | ||
496 | * Generate bit values for those extra bytes instead | ||
497 | * of reading them from the transmit buffer. | ||
498 | */ | ||
499 | unsigned int idx = (pin->tx_bit / 10); | ||
500 | u8 val = idx; | ||
501 | |||
502 | if (idx < pin->tx_msg.len) | ||
503 | val = pin->tx_msg.msg[idx]; | ||
504 | v = val & (1 << (7 - (pin->tx_bit % 10))); | ||
505 | |||
223 | pin->state = v ? CEC_ST_TX_DATA_BIT_1_LOW : | 506 | pin->state = v ? CEC_ST_TX_DATA_BIT_1_LOW : |
224 | CEC_ST_TX_DATA_BIT_0_LOW; | 507 | CEC_ST_TX_DATA_BIT_0_LOW; |
225 | break; | 508 | break; |
226 | case 8: | 509 | } |
227 | v = pin->tx_bit / 10 == pin->tx_msg.len - 1; | 510 | case EOM_BIT: { |
511 | unsigned int tot_len = pin->tx_msg.len + | ||
512 | pin->tx_extra_bytes; | ||
513 | unsigned int tx_byte_idx = pin->tx_bit / 10; | ||
514 | |||
515 | v = !pin->tx_post_eom && tx_byte_idx == tot_len - 1; | ||
516 | if (tot_len > 1 && tx_byte_idx == tot_len - 2 && | ||
517 | tx_early_eom(pin)) { | ||
518 | /* Error injection: set EOM one byte early */ | ||
519 | v = true; | ||
520 | pin->tx_post_eom = true; | ||
521 | } else if (v && tx_no_eom(pin)) { | ||
522 | /* Error injection: no EOM */ | ||
523 | v = false; | ||
524 | } | ||
228 | pin->state = v ? CEC_ST_TX_DATA_BIT_1_LOW : | 525 | pin->state = v ? CEC_ST_TX_DATA_BIT_1_LOW : |
229 | CEC_ST_TX_DATA_BIT_0_LOW; | 526 | CEC_ST_TX_DATA_BIT_0_LOW; |
230 | break; | 527 | break; |
231 | case 9: | 528 | } |
529 | case ACK_BIT: | ||
232 | pin->state = CEC_ST_TX_DATA_BIT_1_LOW; | 530 | pin->state = CEC_ST_TX_DATA_BIT_1_LOW; |
233 | break; | 531 | break; |
234 | } | 532 | } |
533 | if (tx_custom_bit(pin)) | ||
534 | pin->state = CEC_ST_TX_DATA_BIT_LOW_CUSTOM; | ||
235 | cec_pin_low(pin); | 535 | cec_pin_low(pin); |
236 | break; | 536 | break; |
237 | 537 | ||
238 | case CEC_ST_TX_DATA_BIT_0_LOW: | 538 | case CEC_ST_TX_DATA_BIT_0_LOW: |
239 | case CEC_ST_TX_DATA_BIT_1_LOW: | 539 | case CEC_ST_TX_DATA_BIT_1_LOW: |
240 | v = pin->state == CEC_ST_TX_DATA_BIT_1_LOW; | 540 | v = pin->state == CEC_ST_TX_DATA_BIT_1_LOW; |
241 | pin->state = v ? CEC_ST_TX_DATA_BIT_1_HIGH : | 541 | is_ack_bit = pin->tx_bit % 10 == ACK_BIT; |
242 | CEC_ST_TX_DATA_BIT_0_HIGH; | 542 | if (v && (pin->tx_bit < 4 || is_ack_bit)) { |
243 | is_ack_bit = pin->tx_bit % 10 == 9; | ||
244 | if (v && (pin->tx_bit < 4 || is_ack_bit)) | ||
245 | pin->state = CEC_ST_TX_DATA_BIT_1_HIGH_PRE_SAMPLE; | 543 | pin->state = CEC_ST_TX_DATA_BIT_1_HIGH_PRE_SAMPLE; |
544 | } else if (!is_ack_bit && tx_short_bit(pin)) { | ||
545 | /* Error Injection: send an invalid (too short) bit */ | ||
546 | pin->state = v ? CEC_ST_TX_DATA_BIT_1_HIGH_SHORT : | ||
547 | CEC_ST_TX_DATA_BIT_0_HIGH_SHORT; | ||
548 | } else if (!is_ack_bit && tx_long_bit(pin)) { | ||
549 | /* Error Injection: send an invalid (too long) bit */ | ||
550 | pin->state = v ? CEC_ST_TX_DATA_BIT_1_HIGH_LONG : | ||
551 | CEC_ST_TX_DATA_BIT_0_HIGH_LONG; | ||
552 | } else { | ||
553 | pin->state = v ? CEC_ST_TX_DATA_BIT_1_HIGH : | ||
554 | CEC_ST_TX_DATA_BIT_0_HIGH; | ||
555 | } | ||
556 | cec_pin_high(pin); | ||
557 | break; | ||
558 | |||
559 | case CEC_ST_TX_DATA_BIT_LOW_CUSTOM: | ||
560 | pin->state = CEC_ST_TX_DATA_BIT_HIGH_CUSTOM; | ||
246 | cec_pin_high(pin); | 561 | cec_pin_high(pin); |
247 | break; | 562 | break; |
248 | 563 | ||
249 | case CEC_ST_TX_DATA_BIT_1_HIGH_PRE_SAMPLE: | 564 | case CEC_ST_TX_DATA_BIT_1_HIGH_PRE_SAMPLE: |
250 | /* Read the CEC value at the sample time */ | 565 | /* Read the CEC value at the sample time */ |
251 | v = cec_pin_read(pin); | 566 | v = cec_pin_read(pin); |
252 | is_ack_bit = pin->tx_bit % 10 == 9; | 567 | is_ack_bit = pin->tx_bit % 10 == ACK_BIT; |
253 | /* | 568 | /* |
254 | * If v == 0 and we're within the first 4 bits | 569 | * If v == 0 and we're within the first 4 bits |
255 | * of the initiator, then someone else started | 570 | * of the initiator, then someone else started |
@@ -258,7 +573,7 @@ static void cec_pin_tx_states(struct cec_pin *pin, ktime_t ts) | |||
258 | * transmitter has more leading 0 bits in the | 573 | * transmitter has more leading 0 bits in the |
259 | * initiator). | 574 | * initiator). |
260 | */ | 575 | */ |
261 | if (!v && !is_ack_bit) { | 576 | if (!v && !is_ack_bit && !pin->tx_generated_poll) { |
262 | pin->tx_msg.len = 0; | 577 | pin->tx_msg.len = 0; |
263 | pin->work_tx_ts = ts; | 578 | pin->work_tx_ts = ts; |
264 | pin->work_tx_status = CEC_TX_STATUS_ARB_LOST; | 579 | pin->work_tx_status = CEC_TX_STATUS_ARB_LOST; |
@@ -267,18 +582,27 @@ static void cec_pin_tx_states(struct cec_pin *pin, ktime_t ts) | |||
267 | pin->tx_bit = 0; | 582 | pin->tx_bit = 0; |
268 | memset(pin->rx_msg.msg, 0, sizeof(pin->rx_msg.msg)); | 583 | memset(pin->rx_msg.msg, 0, sizeof(pin->rx_msg.msg)); |
269 | pin->rx_msg.msg[0] = pin->tx_msg.msg[0]; | 584 | pin->rx_msg.msg[0] = pin->tx_msg.msg[0]; |
270 | pin->rx_msg.msg[0] &= ~(1 << (7 - pin->rx_bit)); | 585 | pin->rx_msg.msg[0] &= (0xff << (8 - pin->rx_bit)); |
271 | pin->rx_msg.len = 0; | 586 | pin->rx_msg.len = 0; |
587 | pin->ts = ktime_sub_us(ts, CEC_TIM_DATA_BIT_SAMPLE); | ||
272 | pin->state = CEC_ST_RX_DATA_POST_SAMPLE; | 588 | pin->state = CEC_ST_RX_DATA_POST_SAMPLE; |
273 | pin->rx_bit++; | 589 | pin->rx_bit++; |
274 | break; | 590 | break; |
275 | } | 591 | } |
276 | pin->state = CEC_ST_TX_DATA_BIT_1_HIGH_POST_SAMPLE; | 592 | pin->state = CEC_ST_TX_DATA_BIT_1_HIGH_POST_SAMPLE; |
593 | if (!is_ack_bit && tx_short_bit(pin)) { | ||
594 | /* Error Injection: send an invalid (too short) bit */ | ||
595 | pin->state = CEC_ST_TX_DATA_BIT_1_HIGH_POST_SAMPLE_SHORT; | ||
596 | } else if (!is_ack_bit && tx_long_bit(pin)) { | ||
597 | /* Error Injection: send an invalid (too long) bit */ | ||
598 | pin->state = CEC_ST_TX_DATA_BIT_1_HIGH_POST_SAMPLE_LONG; | ||
599 | } | ||
277 | if (!is_ack_bit) | 600 | if (!is_ack_bit) |
278 | break; | 601 | break; |
279 | /* Was the message ACKed? */ | 602 | /* Was the message ACKed? */ |
280 | ack = cec_msg_is_broadcast(&pin->tx_msg) ? v : !v; | 603 | ack = cec_msg_is_broadcast(&pin->tx_msg) ? v : !v; |
281 | if (!ack) { | 604 | if (!ack && !pin->tx_ignore_nack_until_eom && |
605 | pin->tx_bit / 10 < pin->tx_msg.len && !pin->tx_post_eom) { | ||
282 | /* | 606 | /* |
283 | * Note: the CEC spec is ambiguous regarding | 607 | * Note: the CEC spec is ambiguous regarding |
284 | * what action to take when a NACK appears | 608 | * what action to take when a NACK appears |
@@ -295,6 +619,15 @@ static void cec_pin_tx_states(struct cec_pin *pin, ktime_t ts) | |||
295 | } | 619 | } |
296 | break; | 620 | break; |
297 | 621 | ||
622 | case CEC_ST_TX_PULSE_LOW_CUSTOM: | ||
623 | cec_pin_high(pin); | ||
624 | pin->state = CEC_ST_TX_PULSE_HIGH_CUSTOM; | ||
625 | break; | ||
626 | |||
627 | case CEC_ST_TX_PULSE_HIGH_CUSTOM: | ||
628 | cec_pin_to_idle(pin); | ||
629 | break; | ||
630 | |||
298 | default: | 631 | default: |
299 | break; | 632 | break; |
300 | } | 633 | } |
@@ -322,6 +655,7 @@ static void cec_pin_rx_states(struct cec_pin *pin, ktime_t ts) | |||
322 | bool ack; | 655 | bool ack; |
323 | bool bcast, for_us; | 656 | bool bcast, for_us; |
324 | u8 dest; | 657 | u8 dest; |
658 | u8 poll; | ||
325 | 659 | ||
326 | switch (pin->state) { | 660 | switch (pin->state) { |
327 | /* Receive states */ | 661 | /* Receive states */ |
@@ -331,24 +665,54 @@ static void cec_pin_rx_states(struct cec_pin *pin, ktime_t ts) | |||
331 | break; | 665 | break; |
332 | pin->state = CEC_ST_RX_START_BIT_HIGH; | 666 | pin->state = CEC_ST_RX_START_BIT_HIGH; |
333 | delta = ktime_us_delta(ts, pin->ts); | 667 | delta = ktime_us_delta(ts, pin->ts); |
334 | pin->ts = ts; | ||
335 | /* Start bit low is too short, go back to idle */ | 668 | /* Start bit low is too short, go back to idle */ |
336 | if (delta < CEC_TIM_START_BIT_LOW_MIN - | 669 | if (delta < CEC_TIM_START_BIT_LOW_MIN - CEC_TIM_IDLE_SAMPLE) { |
337 | CEC_TIM_IDLE_SAMPLE) { | 670 | if (!pin->rx_start_bit_low_too_short_cnt++) { |
671 | pin->rx_start_bit_low_too_short_ts = pin->ts; | ||
672 | pin->rx_start_bit_low_too_short_delta = delta; | ||
673 | } | ||
338 | cec_pin_to_idle(pin); | 674 | cec_pin_to_idle(pin); |
675 | break; | ||
676 | } | ||
677 | if (rx_arb_lost(pin, &poll)) { | ||
678 | cec_msg_init(&pin->tx_msg, poll >> 4, poll & 0xf); | ||
679 | pin->tx_generated_poll = true; | ||
680 | pin->tx_extra_bytes = 0; | ||
681 | pin->state = CEC_ST_TX_START_BIT_HIGH; | ||
682 | pin->ts = ts; | ||
339 | } | 683 | } |
340 | break; | 684 | break; |
341 | 685 | ||
342 | case CEC_ST_RX_START_BIT_HIGH: | 686 | case CEC_ST_RX_START_BIT_HIGH: |
343 | v = cec_pin_read(pin); | 687 | v = cec_pin_read(pin); |
344 | delta = ktime_us_delta(ts, pin->ts); | 688 | delta = ktime_us_delta(ts, pin->ts); |
345 | if (v && delta > CEC_TIM_START_BIT_TOTAL_MAX - | 689 | /* |
346 | CEC_TIM_START_BIT_LOW_MIN) { | 690 | * Unfortunately the spec does not specify when to give up |
691 | * and go to idle. We just pick TOTAL_LONG. | ||
692 | */ | ||
693 | if (v && delta > CEC_TIM_START_BIT_TOTAL_LONG) { | ||
694 | pin->rx_start_bit_too_long_cnt++; | ||
347 | cec_pin_to_idle(pin); | 695 | cec_pin_to_idle(pin); |
348 | break; | 696 | break; |
349 | } | 697 | } |
350 | if (v) | 698 | if (v) |
351 | break; | 699 | break; |
700 | /* Start bit is too short, go back to idle */ | ||
701 | if (delta < CEC_TIM_START_BIT_TOTAL_MIN - CEC_TIM_IDLE_SAMPLE) { | ||
702 | if (!pin->rx_start_bit_too_short_cnt++) { | ||
703 | pin->rx_start_bit_too_short_ts = pin->ts; | ||
704 | pin->rx_start_bit_too_short_delta = delta; | ||
705 | } | ||
706 | cec_pin_to_idle(pin); | ||
707 | break; | ||
708 | } | ||
709 | if (rx_low_drive(pin)) { | ||
710 | /* Error injection: go to low drive */ | ||
711 | cec_pin_low(pin); | ||
712 | pin->state = CEC_ST_RX_LOW_DRIVE; | ||
713 | pin->rx_low_drive_cnt++; | ||
714 | break; | ||
715 | } | ||
352 | pin->state = CEC_ST_RX_DATA_SAMPLE; | 716 | pin->state = CEC_ST_RX_DATA_SAMPLE; |
353 | pin->ts = ts; | 717 | pin->ts = ts; |
354 | pin->rx_eom = false; | 718 | pin->rx_eom = false; |
@@ -363,36 +727,55 @@ static void cec_pin_rx_states(struct cec_pin *pin, ktime_t ts) | |||
363 | pin->rx_msg.msg[pin->rx_bit / 10] |= | 727 | pin->rx_msg.msg[pin->rx_bit / 10] |= |
364 | v << (7 - (pin->rx_bit % 10)); | 728 | v << (7 - (pin->rx_bit % 10)); |
365 | break; | 729 | break; |
366 | case 8: | 730 | case EOM_BIT: |
367 | pin->rx_eom = v; | 731 | pin->rx_eom = v; |
368 | pin->rx_msg.len = pin->rx_bit / 10 + 1; | 732 | pin->rx_msg.len = pin->rx_bit / 10 + 1; |
369 | break; | 733 | break; |
370 | case 9: | 734 | case ACK_BIT: |
371 | break; | 735 | break; |
372 | } | 736 | } |
373 | pin->rx_bit++; | 737 | pin->rx_bit++; |
374 | break; | 738 | break; |
375 | 739 | ||
376 | case CEC_ST_RX_DATA_POST_SAMPLE: | 740 | case CEC_ST_RX_DATA_POST_SAMPLE: |
377 | pin->state = CEC_ST_RX_DATA_HIGH; | 741 | pin->state = CEC_ST_RX_DATA_WAIT_FOR_LOW; |
378 | break; | 742 | break; |
379 | 743 | ||
380 | case CEC_ST_RX_DATA_HIGH: | 744 | case CEC_ST_RX_DATA_WAIT_FOR_LOW: |
381 | v = cec_pin_read(pin); | 745 | v = cec_pin_read(pin); |
382 | delta = ktime_us_delta(ts, pin->ts); | 746 | delta = ktime_us_delta(ts, pin->ts); |
383 | if (v && delta > CEC_TIM_DATA_BIT_TOTAL_MAX) { | 747 | /* |
748 | * Unfortunately the spec does not specify when to give up | ||
749 | * and go to idle. We just pick TOTAL_LONG. | ||
750 | */ | ||
751 | if (v && delta > CEC_TIM_DATA_BIT_TOTAL_LONG) { | ||
752 | pin->rx_data_bit_too_long_cnt++; | ||
384 | cec_pin_to_idle(pin); | 753 | cec_pin_to_idle(pin); |
385 | break; | 754 | break; |
386 | } | 755 | } |
387 | if (v) | 756 | if (v) |
388 | break; | 757 | break; |
758 | |||
759 | if (rx_low_drive(pin)) { | ||
760 | /* Error injection: go to low drive */ | ||
761 | cec_pin_low(pin); | ||
762 | pin->state = CEC_ST_RX_LOW_DRIVE; | ||
763 | pin->rx_low_drive_cnt++; | ||
764 | break; | ||
765 | } | ||
766 | |||
389 | /* | 767 | /* |
390 | * Go to low drive state when the total bit time is | 768 | * Go to low drive state when the total bit time is |
391 | * too short. | 769 | * too short. |
392 | */ | 770 | */ |
393 | if (delta < CEC_TIM_DATA_BIT_TOTAL_MIN) { | 771 | if (delta < CEC_TIM_DATA_BIT_TOTAL_MIN) { |
772 | if (!pin->rx_data_bit_too_short_cnt++) { | ||
773 | pin->rx_data_bit_too_short_ts = pin->ts; | ||
774 | pin->rx_data_bit_too_short_delta = delta; | ||
775 | } | ||
394 | cec_pin_low(pin); | 776 | cec_pin_low(pin); |
395 | pin->state = CEC_ST_LOW_DRIVE; | 777 | pin->state = CEC_ST_RX_LOW_DRIVE; |
778 | pin->rx_low_drive_cnt++; | ||
396 | break; | 779 | break; |
397 | } | 780 | } |
398 | pin->ts = ts; | 781 | pin->ts = ts; |
@@ -408,6 +791,11 @@ static void cec_pin_rx_states(struct cec_pin *pin, ktime_t ts) | |||
408 | /* ACK bit value */ | 791 | /* ACK bit value */ |
409 | ack = bcast ? 1 : !for_us; | 792 | ack = bcast ? 1 : !for_us; |
410 | 793 | ||
794 | if (for_us && rx_nack(pin)) { | ||
795 | /* Error injection: toggle the ACK bit */ | ||
796 | ack = !ack; | ||
797 | } | ||
798 | |||
411 | if (ack) { | 799 | if (ack) { |
412 | /* No need to write to the bus, just wait */ | 800 | /* No need to write to the bus, just wait */ |
413 | pin->state = CEC_ST_RX_ACK_HIGH_POST; | 801 | pin->state = CEC_ST_RX_ACK_HIGH_POST; |
@@ -434,7 +822,7 @@ static void cec_pin_rx_states(struct cec_pin *pin, ktime_t ts) | |||
434 | break; | 822 | break; |
435 | } | 823 | } |
436 | pin->rx_bit++; | 824 | pin->rx_bit++; |
437 | pin->state = CEC_ST_RX_DATA_HIGH; | 825 | pin->state = CEC_ST_RX_DATA_WAIT_FOR_LOW; |
438 | break; | 826 | break; |
439 | 827 | ||
440 | case CEC_ST_RX_ACK_FINISH: | 828 | case CEC_ST_RX_ACK_FINISH: |
@@ -456,6 +844,7 @@ static enum hrtimer_restart cec_pin_timer(struct hrtimer *timer) | |||
456 | struct cec_adapter *adap = pin->adap; | 844 | struct cec_adapter *adap = pin->adap; |
457 | ktime_t ts; | 845 | ktime_t ts; |
458 | s32 delta; | 846 | s32 delta; |
847 | u32 usecs; | ||
459 | 848 | ||
460 | ts = ktime_get(); | 849 | ts = ktime_get(); |
461 | if (ktime_to_ns(pin->timer_ts)) { | 850 | if (ktime_to_ns(pin->timer_ts)) { |
@@ -503,13 +892,27 @@ static enum hrtimer_restart cec_pin_timer(struct hrtimer *timer) | |||
503 | /* Transmit states */ | 892 | /* Transmit states */ |
504 | case CEC_ST_TX_WAIT_FOR_HIGH: | 893 | case CEC_ST_TX_WAIT_FOR_HIGH: |
505 | case CEC_ST_TX_START_BIT_LOW: | 894 | case CEC_ST_TX_START_BIT_LOW: |
506 | case CEC_ST_TX_DATA_BIT_1_HIGH_POST_SAMPLE: | ||
507 | case CEC_ST_TX_DATA_BIT_0_HIGH: | ||
508 | case CEC_ST_TX_DATA_BIT_1_HIGH: | ||
509 | case CEC_ST_TX_START_BIT_HIGH: | 895 | case CEC_ST_TX_START_BIT_HIGH: |
896 | case CEC_ST_TX_START_BIT_HIGH_SHORT: | ||
897 | case CEC_ST_TX_START_BIT_HIGH_LONG: | ||
898 | case CEC_ST_TX_START_BIT_LOW_CUSTOM: | ||
899 | case CEC_ST_TX_START_BIT_HIGH_CUSTOM: | ||
510 | case CEC_ST_TX_DATA_BIT_0_LOW: | 900 | case CEC_ST_TX_DATA_BIT_0_LOW: |
901 | case CEC_ST_TX_DATA_BIT_0_HIGH: | ||
902 | case CEC_ST_TX_DATA_BIT_0_HIGH_SHORT: | ||
903 | case CEC_ST_TX_DATA_BIT_0_HIGH_LONG: | ||
511 | case CEC_ST_TX_DATA_BIT_1_LOW: | 904 | case CEC_ST_TX_DATA_BIT_1_LOW: |
905 | case CEC_ST_TX_DATA_BIT_1_HIGH: | ||
906 | case CEC_ST_TX_DATA_BIT_1_HIGH_SHORT: | ||
907 | case CEC_ST_TX_DATA_BIT_1_HIGH_LONG: | ||
512 | case CEC_ST_TX_DATA_BIT_1_HIGH_PRE_SAMPLE: | 908 | case CEC_ST_TX_DATA_BIT_1_HIGH_PRE_SAMPLE: |
909 | case CEC_ST_TX_DATA_BIT_1_HIGH_POST_SAMPLE: | ||
910 | case CEC_ST_TX_DATA_BIT_1_HIGH_POST_SAMPLE_SHORT: | ||
911 | case CEC_ST_TX_DATA_BIT_1_HIGH_POST_SAMPLE_LONG: | ||
912 | case CEC_ST_TX_DATA_BIT_LOW_CUSTOM: | ||
913 | case CEC_ST_TX_DATA_BIT_HIGH_CUSTOM: | ||
914 | case CEC_ST_TX_PULSE_LOW_CUSTOM: | ||
915 | case CEC_ST_TX_PULSE_HIGH_CUSTOM: | ||
513 | cec_pin_tx_states(pin, ts); | 916 | cec_pin_tx_states(pin, ts); |
514 | break; | 917 | break; |
515 | 918 | ||
@@ -518,7 +921,7 @@ static enum hrtimer_restart cec_pin_timer(struct hrtimer *timer) | |||
518 | case CEC_ST_RX_START_BIT_HIGH: | 921 | case CEC_ST_RX_START_BIT_HIGH: |
519 | case CEC_ST_RX_DATA_SAMPLE: | 922 | case CEC_ST_RX_DATA_SAMPLE: |
520 | case CEC_ST_RX_DATA_POST_SAMPLE: | 923 | case CEC_ST_RX_DATA_POST_SAMPLE: |
521 | case CEC_ST_RX_DATA_HIGH: | 924 | case CEC_ST_RX_DATA_WAIT_FOR_LOW: |
522 | case CEC_ST_RX_ACK_LOW: | 925 | case CEC_ST_RX_ACK_LOW: |
523 | case CEC_ST_RX_ACK_LOW_POST: | 926 | case CEC_ST_RX_ACK_LOW_POST: |
524 | case CEC_ST_RX_ACK_HIGH_POST: | 927 | case CEC_ST_RX_ACK_HIGH_POST: |
@@ -545,7 +948,10 @@ static enum hrtimer_restart cec_pin_timer(struct hrtimer *timer) | |||
545 | if (delta / CEC_TIM_DATA_BIT_TOTAL > | 948 | if (delta / CEC_TIM_DATA_BIT_TOTAL > |
546 | pin->tx_signal_free_time) { | 949 | pin->tx_signal_free_time) { |
547 | pin->tx_nacked = false; | 950 | pin->tx_nacked = false; |
548 | pin->state = CEC_ST_TX_START_BIT_LOW; | 951 | if (tx_custom_start(pin)) |
952 | pin->state = CEC_ST_TX_START_BIT_LOW_CUSTOM; | ||
953 | else | ||
954 | pin->state = CEC_ST_TX_START_BIT_LOW; | ||
549 | /* Generate start bit */ | 955 | /* Generate start bit */ |
550 | cec_pin_low(pin); | 956 | cec_pin_low(pin); |
551 | break; | 957 | break; |
@@ -555,6 +961,13 @@ static enum hrtimer_restart cec_pin_timer(struct hrtimer *timer) | |||
555 | pin->state = CEC_ST_TX_WAIT; | 961 | pin->state = CEC_ST_TX_WAIT; |
556 | break; | 962 | break; |
557 | } | 963 | } |
964 | if (pin->tx_custom_pulse && pin->state == CEC_ST_IDLE) { | ||
965 | pin->tx_custom_pulse = false; | ||
966 | /* Generate custom pulse */ | ||
967 | cec_pin_low(pin); | ||
968 | pin->state = CEC_ST_TX_PULSE_LOW_CUSTOM; | ||
969 | break; | ||
970 | } | ||
558 | if (pin->state != CEC_ST_IDLE || pin->ops->enable_irq == NULL || | 971 | if (pin->state != CEC_ST_IDLE || pin->ops->enable_irq == NULL || |
559 | pin->enable_irq_failed || adap->is_configuring || | 972 | pin->enable_irq_failed || adap->is_configuring || |
560 | adap->is_configured || adap->monitor_all_cnt) | 973 | adap->is_configured || adap->monitor_all_cnt) |
@@ -565,21 +978,40 @@ static enum hrtimer_restart cec_pin_timer(struct hrtimer *timer) | |||
565 | wake_up_interruptible(&pin->kthread_waitq); | 978 | wake_up_interruptible(&pin->kthread_waitq); |
566 | return HRTIMER_NORESTART; | 979 | return HRTIMER_NORESTART; |
567 | 980 | ||
568 | case CEC_ST_LOW_DRIVE: | 981 | case CEC_ST_TX_LOW_DRIVE: |
982 | case CEC_ST_RX_LOW_DRIVE: | ||
983 | cec_pin_high(pin); | ||
569 | cec_pin_to_idle(pin); | 984 | cec_pin_to_idle(pin); |
570 | break; | 985 | break; |
571 | 986 | ||
572 | default: | 987 | default: |
573 | break; | 988 | break; |
574 | } | 989 | } |
575 | if (!adap->monitor_pin_cnt || states[pin->state].usecs <= 150) { | 990 | |
991 | switch (pin->state) { | ||
992 | case CEC_ST_TX_START_BIT_LOW_CUSTOM: | ||
993 | case CEC_ST_TX_DATA_BIT_LOW_CUSTOM: | ||
994 | case CEC_ST_TX_PULSE_LOW_CUSTOM: | ||
995 | usecs = pin->tx_custom_low_usecs; | ||
996 | break; | ||
997 | case CEC_ST_TX_START_BIT_HIGH_CUSTOM: | ||
998 | case CEC_ST_TX_DATA_BIT_HIGH_CUSTOM: | ||
999 | case CEC_ST_TX_PULSE_HIGH_CUSTOM: | ||
1000 | usecs = pin->tx_custom_high_usecs; | ||
1001 | break; | ||
1002 | default: | ||
1003 | usecs = states[pin->state].usecs; | ||
1004 | break; | ||
1005 | } | ||
1006 | |||
1007 | if (!adap->monitor_pin_cnt || usecs <= 150) { | ||
576 | pin->wait_usecs = 0; | 1008 | pin->wait_usecs = 0; |
577 | pin->timer_ts = ktime_add_us(ts, states[pin->state].usecs); | 1009 | pin->timer_ts = ktime_add_us(ts, usecs); |
578 | hrtimer_forward_now(timer, | 1010 | hrtimer_forward_now(timer, |
579 | ns_to_ktime(states[pin->state].usecs * 1000)); | 1011 | ns_to_ktime(usecs * 1000)); |
580 | return HRTIMER_RESTART; | 1012 | return HRTIMER_RESTART; |
581 | } | 1013 | } |
582 | pin->wait_usecs = states[pin->state].usecs - 100; | 1014 | pin->wait_usecs = usecs - 100; |
583 | pin->timer_ts = ktime_add_us(ts, 100); | 1015 | pin->timer_ts = ktime_add_us(ts, 100); |
584 | hrtimer_forward_now(timer, ns_to_ktime(100000)); | 1016 | hrtimer_forward_now(timer, ns_to_ktime(100000)); |
585 | return HRTIMER_RESTART; | 1017 | return HRTIMER_RESTART; |
@@ -596,12 +1028,25 @@ static int cec_pin_thread_func(void *_adap) | |||
596 | pin->work_rx_msg.len || | 1028 | pin->work_rx_msg.len || |
597 | pin->work_tx_status || | 1029 | pin->work_tx_status || |
598 | atomic_read(&pin->work_irq_change) || | 1030 | atomic_read(&pin->work_irq_change) || |
599 | atomic_read(&pin->work_pin_events)); | 1031 | atomic_read(&pin->work_pin_num_events)); |
600 | 1032 | ||
601 | if (pin->work_rx_msg.len) { | 1033 | if (pin->work_rx_msg.len) { |
602 | cec_received_msg_ts(adap, &pin->work_rx_msg, | 1034 | struct cec_msg *msg = &pin->work_rx_msg; |
1035 | |||
1036 | if (msg->len > 1 && msg->len < CEC_MAX_MSG_SIZE && | ||
1037 | rx_add_byte(pin)) { | ||
1038 | /* Error injection: add byte to the message */ | ||
1039 | msg->msg[msg->len++] = 0x55; | ||
1040 | } | ||
1041 | if (msg->len > 2 && rx_remove_byte(pin)) { | ||
1042 | /* Error injection: remove byte from message */ | ||
1043 | msg->len--; | ||
1044 | } | ||
1045 | if (msg->len > CEC_MAX_MSG_SIZE) | ||
1046 | msg->len = CEC_MAX_MSG_SIZE; | ||
1047 | cec_received_msg_ts(adap, msg, | ||
603 | ns_to_ktime(pin->work_rx_msg.rx_ts)); | 1048 | ns_to_ktime(pin->work_rx_msg.rx_ts)); |
604 | pin->work_rx_msg.len = 0; | 1049 | msg->len = 0; |
605 | } | 1050 | } |
606 | if (pin->work_tx_status) { | 1051 | if (pin->work_tx_status) { |
607 | unsigned int tx_status = pin->work_tx_status; | 1052 | unsigned int tx_status = pin->work_tx_status; |
@@ -611,14 +1056,16 @@ static int cec_pin_thread_func(void *_adap) | |||
611 | pin->work_tx_ts); | 1056 | pin->work_tx_ts); |
612 | } | 1057 | } |
613 | 1058 | ||
614 | while (atomic_read(&pin->work_pin_events)) { | 1059 | while (atomic_read(&pin->work_pin_num_events)) { |
615 | unsigned int idx = pin->work_pin_events_rd; | 1060 | unsigned int idx = pin->work_pin_events_rd; |
1061 | u8 v = pin->work_pin_events[idx]; | ||
616 | 1062 | ||
617 | cec_queue_pin_cec_event(adap, | 1063 | cec_queue_pin_cec_event(adap, |
618 | pin->work_pin_is_high[idx], | 1064 | v & CEC_PIN_EVENT_FL_IS_HIGH, |
1065 | v & CEC_PIN_EVENT_FL_DROPPED, | ||
619 | pin->work_pin_ts[idx]); | 1066 | pin->work_pin_ts[idx]); |
620 | pin->work_pin_events_rd = (idx + 1) % CEC_NUM_PIN_EVENTS; | 1067 | pin->work_pin_events_rd = (idx + 1) % CEC_NUM_PIN_EVENTS; |
621 | atomic_dec(&pin->work_pin_events); | 1068 | atomic_dec(&pin->work_pin_num_events); |
622 | } | 1069 | } |
623 | 1070 | ||
624 | switch (atomic_xchg(&pin->work_irq_change, | 1071 | switch (atomic_xchg(&pin->work_irq_change, |
@@ -654,8 +1101,9 @@ static int cec_pin_adap_enable(struct cec_adapter *adap, bool enable) | |||
654 | 1101 | ||
655 | pin->enabled = enable; | 1102 | pin->enabled = enable; |
656 | if (enable) { | 1103 | if (enable) { |
657 | atomic_set(&pin->work_pin_events, 0); | 1104 | atomic_set(&pin->work_pin_num_events, 0); |
658 | pin->work_pin_events_rd = pin->work_pin_events_wr = 0; | 1105 | pin->work_pin_events_rd = pin->work_pin_events_wr = 0; |
1106 | pin->work_pin_events_dropped = false; | ||
659 | cec_pin_read(pin); | 1107 | cec_pin_read(pin); |
660 | cec_pin_to_idle(pin); | 1108 | cec_pin_to_idle(pin); |
661 | pin->tx_msg.len = 0; | 1109 | pin->tx_msg.len = 0; |
@@ -692,23 +1140,37 @@ static int cec_pin_adap_log_addr(struct cec_adapter *adap, u8 log_addr) | |||
692 | return 0; | 1140 | return 0; |
693 | } | 1141 | } |
694 | 1142 | ||
1143 | void cec_pin_start_timer(struct cec_pin *pin) | ||
1144 | { | ||
1145 | if (pin->state != CEC_ST_RX_IRQ) | ||
1146 | return; | ||
1147 | |||
1148 | atomic_set(&pin->work_irq_change, CEC_PIN_IRQ_UNCHANGED); | ||
1149 | pin->ops->disable_irq(pin->adap); | ||
1150 | cec_pin_high(pin); | ||
1151 | cec_pin_to_idle(pin); | ||
1152 | hrtimer_start(&pin->timer, ns_to_ktime(0), HRTIMER_MODE_REL); | ||
1153 | } | ||
1154 | |||
695 | static int cec_pin_adap_transmit(struct cec_adapter *adap, u8 attempts, | 1155 | static int cec_pin_adap_transmit(struct cec_adapter *adap, u8 attempts, |
696 | u32 signal_free_time, struct cec_msg *msg) | 1156 | u32 signal_free_time, struct cec_msg *msg) |
697 | { | 1157 | { |
698 | struct cec_pin *pin = adap->pin; | 1158 | struct cec_pin *pin = adap->pin; |
699 | 1159 | ||
700 | pin->tx_signal_free_time = signal_free_time; | 1160 | pin->tx_signal_free_time = signal_free_time; |
1161 | pin->tx_extra_bytes = 0; | ||
701 | pin->tx_msg = *msg; | 1162 | pin->tx_msg = *msg; |
1163 | if (msg->len > 1) { | ||
1164 | /* Error injection: add byte to the message */ | ||
1165 | pin->tx_extra_bytes = tx_add_bytes(pin); | ||
1166 | } | ||
1167 | if (msg->len > 2 && tx_remove_byte(pin)) { | ||
1168 | /* Error injection: remove byte from the message */ | ||
1169 | pin->tx_msg.len--; | ||
1170 | } | ||
702 | pin->work_tx_status = 0; | 1171 | pin->work_tx_status = 0; |
703 | pin->tx_bit = 0; | 1172 | pin->tx_bit = 0; |
704 | if (pin->state == CEC_ST_RX_IRQ) { | 1173 | cec_pin_start_timer(pin); |
705 | atomic_set(&pin->work_irq_change, CEC_PIN_IRQ_UNCHANGED); | ||
706 | pin->ops->disable_irq(adap); | ||
707 | cec_pin_high(pin); | ||
708 | cec_pin_to_idle(pin); | ||
709 | hrtimer_start(&pin->timer, ns_to_ktime(0), | ||
710 | HRTIMER_MODE_REL); | ||
711 | } | ||
712 | return 0; | 1174 | return 0; |
713 | } | 1175 | } |
714 | 1176 | ||
@@ -717,10 +1179,12 @@ static void cec_pin_adap_status(struct cec_adapter *adap, | |||
717 | { | 1179 | { |
718 | struct cec_pin *pin = adap->pin; | 1180 | struct cec_pin *pin = adap->pin; |
719 | 1181 | ||
720 | seq_printf(file, "state: %s\n", states[pin->state].name); | 1182 | seq_printf(file, "state: %s\n", states[pin->state].name); |
721 | seq_printf(file, "tx_bit: %d\n", pin->tx_bit); | 1183 | seq_printf(file, "tx_bit: %d\n", pin->tx_bit); |
722 | seq_printf(file, "rx_bit: %d\n", pin->rx_bit); | 1184 | seq_printf(file, "rx_bit: %d\n", pin->rx_bit); |
723 | seq_printf(file, "cec pin: %d\n", pin->ops->read(adap)); | 1185 | seq_printf(file, "cec pin: %d\n", pin->ops->read(adap)); |
1186 | seq_printf(file, "cec pin events dropped: %u\n", | ||
1187 | pin->work_pin_events_dropped_cnt); | ||
724 | seq_printf(file, "irq failed: %d\n", pin->enable_irq_failed); | 1188 | seq_printf(file, "irq failed: %d\n", pin->enable_irq_failed); |
725 | if (pin->timer_100ms_overruns) { | 1189 | if (pin->timer_100ms_overruns) { |
726 | seq_printf(file, "timer overruns > 100ms: %u of %u\n", | 1190 | seq_printf(file, "timer overruns > 100ms: %u of %u\n", |
@@ -732,11 +1196,45 @@ static void cec_pin_adap_status(struct cec_adapter *adap, | |||
732 | seq_printf(file, "avg timer overrun: %u usecs\n", | 1196 | seq_printf(file, "avg timer overrun: %u usecs\n", |
733 | pin->timer_sum_overrun / pin->timer_100ms_overruns); | 1197 | pin->timer_sum_overrun / pin->timer_100ms_overruns); |
734 | } | 1198 | } |
1199 | if (pin->rx_start_bit_low_too_short_cnt) | ||
1200 | seq_printf(file, | ||
1201 | "rx start bit low too short: %u (delta %u, ts %llu)\n", | ||
1202 | pin->rx_start_bit_low_too_short_cnt, | ||
1203 | pin->rx_start_bit_low_too_short_delta, | ||
1204 | pin->rx_start_bit_low_too_short_ts); | ||
1205 | if (pin->rx_start_bit_too_short_cnt) | ||
1206 | seq_printf(file, | ||
1207 | "rx start bit too short: %u (delta %u, ts %llu)\n", | ||
1208 | pin->rx_start_bit_too_short_cnt, | ||
1209 | pin->rx_start_bit_too_short_delta, | ||
1210 | pin->rx_start_bit_too_short_ts); | ||
1211 | if (pin->rx_start_bit_too_long_cnt) | ||
1212 | seq_printf(file, "rx start bit too long: %u\n", | ||
1213 | pin->rx_start_bit_too_long_cnt); | ||
1214 | if (pin->rx_data_bit_too_short_cnt) | ||
1215 | seq_printf(file, | ||
1216 | "rx data bit too short: %u (delta %u, ts %llu)\n", | ||
1217 | pin->rx_data_bit_too_short_cnt, | ||
1218 | pin->rx_data_bit_too_short_delta, | ||
1219 | pin->rx_data_bit_too_short_ts); | ||
1220 | if (pin->rx_data_bit_too_long_cnt) | ||
1221 | seq_printf(file, "rx data bit too long: %u\n", | ||
1222 | pin->rx_data_bit_too_long_cnt); | ||
1223 | seq_printf(file, "rx initiated low drive: %u\n", pin->rx_low_drive_cnt); | ||
1224 | seq_printf(file, "tx detected low drive: %u\n", pin->tx_low_drive_cnt); | ||
1225 | pin->work_pin_events_dropped_cnt = 0; | ||
735 | pin->timer_cnt = 0; | 1226 | pin->timer_cnt = 0; |
736 | pin->timer_100ms_overruns = 0; | 1227 | pin->timer_100ms_overruns = 0; |
737 | pin->timer_300ms_overruns = 0; | 1228 | pin->timer_300ms_overruns = 0; |
738 | pin->timer_max_overrun = 0; | 1229 | pin->timer_max_overrun = 0; |
739 | pin->timer_sum_overrun = 0; | 1230 | pin->timer_sum_overrun = 0; |
1231 | pin->rx_start_bit_low_too_short_cnt = 0; | ||
1232 | pin->rx_start_bit_too_short_cnt = 0; | ||
1233 | pin->rx_start_bit_too_long_cnt = 0; | ||
1234 | pin->rx_data_bit_too_short_cnt = 0; | ||
1235 | pin->rx_data_bit_too_long_cnt = 0; | ||
1236 | pin->rx_low_drive_cnt = 0; | ||
1237 | pin->tx_low_drive_cnt = 0; | ||
740 | if (pin->ops->status) | 1238 | if (pin->ops->status) |
741 | pin->ops->status(adap, file); | 1239 | pin->ops->status(adap, file); |
742 | } | 1240 | } |
@@ -778,6 +1276,10 @@ static const struct cec_adap_ops cec_pin_adap_ops = { | |||
778 | .adap_transmit = cec_pin_adap_transmit, | 1276 | .adap_transmit = cec_pin_adap_transmit, |
779 | .adap_status = cec_pin_adap_status, | 1277 | .adap_status = cec_pin_adap_status, |
780 | .adap_free = cec_pin_adap_free, | 1278 | .adap_free = cec_pin_adap_free, |
1279 | #ifdef CONFIG_CEC_PIN_ERROR_INJ | ||
1280 | .error_inj_parse_line = cec_pin_error_inj_parse_line, | ||
1281 | .error_inj_show = cec_pin_error_inj_show, | ||
1282 | #endif | ||
781 | }; | 1283 | }; |
782 | 1284 | ||
783 | struct cec_adapter *cec_pin_allocate_adapter(const struct cec_pin_ops *pin_ops, | 1285 | struct cec_adapter *cec_pin_allocate_adapter(const struct cec_pin_ops *pin_ops, |
@@ -792,6 +1294,8 @@ struct cec_adapter *cec_pin_allocate_adapter(const struct cec_pin_ops *pin_ops, | |||
792 | hrtimer_init(&pin->timer, CLOCK_MONOTONIC, HRTIMER_MODE_REL); | 1294 | hrtimer_init(&pin->timer, CLOCK_MONOTONIC, HRTIMER_MODE_REL); |
793 | pin->timer.function = cec_pin_timer; | 1295 | pin->timer.function = cec_pin_timer; |
794 | init_waitqueue_head(&pin->kthread_waitq); | 1296 | init_waitqueue_head(&pin->kthread_waitq); |
1297 | pin->tx_custom_low_usecs = CEC_TIM_CUSTOM_DEFAULT; | ||
1298 | pin->tx_custom_high_usecs = CEC_TIM_CUSTOM_DEFAULT; | ||
795 | 1299 | ||
796 | adap = cec_allocate_adapter(&cec_pin_adap_ops, priv, name, | 1300 | adap = cec_allocate_adapter(&cec_pin_adap_ops, priv, name, |
797 | caps | CEC_CAP_MONITOR_ALL | CEC_CAP_MONITOR_PIN, | 1301 | caps | CEC_CAP_MONITOR_ALL | CEC_CAP_MONITOR_PIN, |