1 | /* SPDX-License-Identifier: GPL-2.0-only */ |
2 | /* |
3 | * cec-pin-priv.h - internal cec-pin header |
4 | * |
5 | * Copyright 2017 Cisco Systems, Inc. and/or its affiliates. All rights reserved. |
6 | */ |
7 | |
8 | #ifndef LINUX_CEC_PIN_PRIV_H |
9 | #define LINUX_CEC_PIN_PRIV_H |
10 | |
11 | #include <linux/types.h> |
12 | #include <linux/atomic.h> |
13 | #include <media/cec-pin.h> |
14 | |
15 | #define call_pin_op(pin, op, arg...) \ |
16 | ((pin && pin->ops->op && !pin->adap->devnode.unregistered) ? \ |
17 | pin->ops->op(pin->adap, ## arg) : 0) |
18 | |
19 | #define call_void_pin_op(pin, op, arg...) \ |
20 | do { \ |
21 | if (pin && pin->ops->op && \ |
22 | !pin->adap->devnode.unregistered) \ |
23 | pin->ops->op(pin->adap, ## arg); \ |
24 | } while (0) |
25 | |
26 | enum cec_pin_state { |
27 | /* CEC is off */ |
28 | CEC_ST_OFF, |
29 | /* CEC is idle, waiting for Rx or Tx */ |
30 | CEC_ST_IDLE, |
31 | |
32 | /* Tx states */ |
33 | |
34 | /* Pending Tx, waiting for Signal Free Time to expire */ |
35 | CEC_ST_TX_WAIT, |
36 | /* Low-drive was detected, wait for bus to go high */ |
37 | CEC_ST_TX_WAIT_FOR_HIGH, |
38 | /* Drive CEC low for the start bit */ |
39 | CEC_ST_TX_START_BIT_LOW, |
40 | /* Drive CEC high for the start bit */ |
41 | CEC_ST_TX_START_BIT_HIGH, |
42 | /* Generate a start bit period that is too short */ |
43 | CEC_ST_TX_START_BIT_HIGH_SHORT, |
44 | /* Generate a start bit period that is too long */ |
45 | CEC_ST_TX_START_BIT_HIGH_LONG, |
46 | /* Drive CEC low for the start bit using the custom timing */ |
47 | CEC_ST_TX_START_BIT_LOW_CUSTOM, |
48 | /* Drive CEC high for the start bit using the custom timing */ |
49 | CEC_ST_TX_START_BIT_HIGH_CUSTOM, |
50 | /* Drive CEC low for the 0 bit */ |
51 | CEC_ST_TX_DATA_BIT_0_LOW, |
52 | /* Drive CEC high for the 0 bit */ |
53 | CEC_ST_TX_DATA_BIT_0_HIGH, |
54 | /* Generate a bit period that is too short */ |
55 | CEC_ST_TX_DATA_BIT_0_HIGH_SHORT, |
56 | /* Generate a bit period that is too long */ |
57 | CEC_ST_TX_DATA_BIT_0_HIGH_LONG, |
58 | /* Drive CEC low for the 1 bit */ |
59 | CEC_ST_TX_DATA_BIT_1_LOW, |
60 | /* Drive CEC high for the 1 bit */ |
61 | CEC_ST_TX_DATA_BIT_1_HIGH, |
62 | /* Generate a bit period that is too short */ |
63 | CEC_ST_TX_DATA_BIT_1_HIGH_SHORT, |
64 | /* Generate a bit period that is too long */ |
65 | CEC_ST_TX_DATA_BIT_1_HIGH_LONG, |
66 | /* |
67 | * Wait for start of sample time to check for Ack bit or first |
68 | * four initiator bits to check for Arbitration Lost. |
69 | */ |
70 | CEC_ST_TX_DATA_BIT_1_HIGH_PRE_SAMPLE, |
71 | /* Wait for end of bit period after sampling */ |
72 | CEC_ST_TX_DATA_BIT_1_HIGH_POST_SAMPLE, |
73 | /* Generate a bit period that is too short */ |
74 | CEC_ST_TX_DATA_BIT_1_HIGH_POST_SAMPLE_SHORT, |
75 | /* Generate a bit period that is too long */ |
76 | CEC_ST_TX_DATA_BIT_1_HIGH_POST_SAMPLE_LONG, |
77 | /* Drive CEC low for a data bit using the custom timing */ |
78 | CEC_ST_TX_DATA_BIT_LOW_CUSTOM, |
79 | /* Drive CEC high for a data bit using the custom timing */ |
80 | CEC_ST_TX_DATA_BIT_HIGH_CUSTOM, |
81 | /* Drive CEC low for a standalone pulse using the custom timing */ |
82 | CEC_ST_TX_PULSE_LOW_CUSTOM, |
83 | /* Drive CEC high for a standalone pulse using the custom timing */ |
84 | CEC_ST_TX_PULSE_HIGH_CUSTOM, |
85 | /* Start low drive */ |
86 | CEC_ST_TX_LOW_DRIVE, |
87 | |
88 | /* Rx states */ |
89 | |
90 | /* Start bit low detected */ |
91 | CEC_ST_RX_START_BIT_LOW, |
92 | /* Start bit high detected */ |
93 | CEC_ST_RX_START_BIT_HIGH, |
94 | /* Wait for bit sample time */ |
95 | CEC_ST_RX_DATA_SAMPLE, |
96 | /* Wait for earliest end of bit period after sampling */ |
97 | CEC_ST_RX_DATA_POST_SAMPLE, |
98 | /* Wait for CEC to go low (i.e. end of bit period) */ |
99 | CEC_ST_RX_DATA_WAIT_FOR_LOW, |
100 | /* Drive CEC low to send 0 Ack bit */ |
101 | CEC_ST_RX_ACK_LOW, |
102 | /* End of 0 Ack time, wait for earliest end of bit period */ |
103 | CEC_ST_RX_ACK_LOW_POST, |
104 | /* Wait for CEC to go high (i.e. end of bit period */ |
105 | CEC_ST_RX_ACK_HIGH_POST, |
106 | /* Wait for earliest end of bit period and end of message */ |
107 | CEC_ST_RX_ACK_FINISH, |
108 | /* Start low drive */ |
109 | CEC_ST_RX_LOW_DRIVE, |
110 | |
111 | /* Monitor pin using interrupts */ |
112 | CEC_ST_RX_IRQ, |
113 | |
114 | /* Total number of pin states */ |
115 | CEC_PIN_STATES |
116 | }; |
117 | |
118 | /* Error Injection */ |
119 | |
120 | /* Error injection modes */ |
121 | #define CEC_ERROR_INJ_MODE_OFF 0 |
122 | #define CEC_ERROR_INJ_MODE_ONCE 1 |
123 | #define CEC_ERROR_INJ_MODE_ALWAYS 2 |
124 | #define CEC_ERROR_INJ_MODE_TOGGLE 3 |
125 | #define CEC_ERROR_INJ_MODE_MASK 3ULL |
126 | |
127 | /* Receive error injection options */ |
128 | #define CEC_ERROR_INJ_RX_NACK_OFFSET 0 |
129 | #define CEC_ERROR_INJ_RX_LOW_DRIVE_OFFSET 2 |
130 | #define CEC_ERROR_INJ_RX_ADD_BYTE_OFFSET 4 |
131 | #define CEC_ERROR_INJ_RX_REMOVE_BYTE_OFFSET 6 |
132 | #define CEC_ERROR_INJ_RX_ARB_LOST_OFFSET 8 |
133 | #define CEC_ERROR_INJ_RX_MASK 0xffffULL |
134 | |
135 | /* Transmit error injection options */ |
136 | #define CEC_ERROR_INJ_TX_NO_EOM_OFFSET 16 |
137 | #define CEC_ERROR_INJ_TX_EARLY_EOM_OFFSET 18 |
138 | #define CEC_ERROR_INJ_TX_SHORT_BIT_OFFSET 20 |
139 | #define CEC_ERROR_INJ_TX_LONG_BIT_OFFSET 22 |
140 | #define CEC_ERROR_INJ_TX_CUSTOM_BIT_OFFSET 24 |
141 | #define CEC_ERROR_INJ_TX_SHORT_START_OFFSET 26 |
142 | #define CEC_ERROR_INJ_TX_LONG_START_OFFSET 28 |
143 | #define CEC_ERROR_INJ_TX_CUSTOM_START_OFFSET 30 |
144 | #define CEC_ERROR_INJ_TX_LAST_BIT_OFFSET 32 |
145 | #define CEC_ERROR_INJ_TX_ADD_BYTES_OFFSET 34 |
146 | #define CEC_ERROR_INJ_TX_REMOVE_BYTE_OFFSET 36 |
147 | #define CEC_ERROR_INJ_TX_LOW_DRIVE_OFFSET 38 |
148 | #define CEC_ERROR_INJ_TX_MASK 0xffffffffffff0000ULL |
149 | |
150 | #define CEC_ERROR_INJ_RX_LOW_DRIVE_ARG_IDX 0 |
151 | #define CEC_ERROR_INJ_RX_ARB_LOST_ARG_IDX 1 |
152 | |
153 | #define CEC_ERROR_INJ_TX_ADD_BYTES_ARG_IDX 2 |
154 | #define CEC_ERROR_INJ_TX_SHORT_BIT_ARG_IDX 3 |
155 | #define CEC_ERROR_INJ_TX_LONG_BIT_ARG_IDX 4 |
156 | #define CEC_ERROR_INJ_TX_CUSTOM_BIT_ARG_IDX 5 |
157 | #define CEC_ERROR_INJ_TX_LAST_BIT_ARG_IDX 6 |
158 | #define CEC_ERROR_INJ_TX_LOW_DRIVE_ARG_IDX 7 |
159 | #define CEC_ERROR_INJ_NUM_ARGS 8 |
160 | |
161 | /* Special CEC op values */ |
162 | #define CEC_ERROR_INJ_OP_ANY 0x00000100 |
163 | |
164 | /* The default for the low/high time of the custom pulse */ |
165 | #define CEC_TIM_CUSTOM_DEFAULT 1000 |
166 | |
167 | #define CEC_NUM_PIN_EVENTS 128 |
168 | #define CEC_PIN_EVENT_FL_IS_HIGH (1 << 0) |
169 | #define CEC_PIN_EVENT_FL_DROPPED (1 << 1) |
170 | |
171 | #define CEC_PIN_IRQ_UNCHANGED 0 |
172 | #define CEC_PIN_IRQ_DISABLE 1 |
173 | #define CEC_PIN_IRQ_ENABLE 2 |
174 | |
175 | struct cec_pin { |
176 | struct cec_adapter *adap; |
177 | const struct cec_pin_ops *ops; |
178 | struct task_struct *kthread; |
179 | wait_queue_head_t kthread_waitq; |
180 | struct hrtimer timer; |
181 | ktime_t ts; |
182 | unsigned int wait_usecs; |
183 | u16 la_mask; |
184 | bool monitor_all; |
185 | bool rx_eom; |
186 | bool enabled_irq; |
187 | bool enable_irq_failed; |
188 | enum cec_pin_state state; |
189 | struct cec_msg tx_msg; |
190 | u32 tx_bit; |
191 | bool tx_nacked; |
192 | u32 tx_signal_free_time; |
193 | bool tx_toggle; |
194 | struct cec_msg rx_msg; |
195 | u32 rx_bit; |
196 | bool rx_toggle; |
197 | u32 rx_start_bit_low_too_short_cnt; |
198 | u64 rx_start_bit_low_too_short_ts; |
199 | u32 rx_start_bit_low_too_short_delta; |
200 | u32 rx_start_bit_too_short_cnt; |
201 | u64 rx_start_bit_too_short_ts; |
202 | u32 rx_start_bit_too_short_delta; |
203 | u32 rx_start_bit_too_long_cnt; |
204 | u32 rx_data_bit_too_short_cnt; |
205 | u64 rx_data_bit_too_short_ts; |
206 | u32 rx_data_bit_too_short_delta; |
207 | u32 rx_data_bit_too_long_cnt; |
208 | u32 rx_low_drive_cnt; |
209 | |
210 | struct cec_msg work_rx_msg; |
211 | u8 work_tx_status; |
212 | ktime_t work_tx_ts; |
213 | atomic_t work_irq_change; |
214 | atomic_t work_pin_num_events; |
215 | unsigned int work_pin_events_wr; |
216 | unsigned int work_pin_events_rd; |
217 | ktime_t work_pin_ts[CEC_NUM_PIN_EVENTS]; |
218 | u8 work_pin_events[CEC_NUM_PIN_EVENTS]; |
219 | bool work_pin_events_dropped; |
220 | u32 work_pin_events_dropped_cnt; |
221 | ktime_t timer_ts; |
222 | u32 timer_cnt; |
223 | u32 timer_100us_overruns; |
224 | u32 timer_300us_overruns; |
225 | u32 timer_max_overrun; |
226 | u32 timer_sum_overrun; |
227 | |
228 | u32 tx_custom_low_usecs; |
229 | u32 tx_custom_high_usecs; |
230 | bool tx_ignore_nack_until_eom; |
231 | bool tx_custom_pulse; |
232 | bool tx_generated_poll; |
233 | bool tx_post_eom; |
234 | u8 ; |
235 | u32 tx_low_drive_cnt; |
236 | #ifdef CONFIG_CEC_PIN_ERROR_INJ |
237 | u64 error_inj[CEC_ERROR_INJ_OP_ANY + 1]; |
238 | u8 error_inj_args[CEC_ERROR_INJ_OP_ANY + 1][CEC_ERROR_INJ_NUM_ARGS]; |
239 | #endif |
240 | }; |
241 | |
242 | void cec_pin_start_timer(struct cec_pin *pin); |
243 | |
244 | #ifdef CONFIG_CEC_PIN_ERROR_INJ |
245 | bool cec_pin_error_inj_parse_line(struct cec_adapter *adap, char *line); |
246 | int cec_pin_error_inj_show(struct cec_adapter *adap, struct seq_file *sf); |
247 | |
248 | u16 cec_pin_rx_error_inj(struct cec_pin *pin); |
249 | u16 cec_pin_tx_error_inj(struct cec_pin *pin); |
250 | #endif |
251 | |
252 | #endif |
253 | |