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
26enum 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
175struct 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 tx_extra_bytes;
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
242void cec_pin_start_timer(struct cec_pin *pin);
243
244#ifdef CONFIG_CEC_PIN_ERROR_INJ
245bool cec_pin_error_inj_parse_line(struct cec_adapter *adap, char *line);
246int cec_pin_error_inj_show(struct cec_adapter *adap, struct seq_file *sf);
247
248u16 cec_pin_rx_error_inj(struct cec_pin *pin);
249u16 cec_pin_tx_error_inj(struct cec_pin *pin);
250#endif
251
252#endif
253

source code of linux/drivers/media/cec/core/cec-pin-priv.h