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				enable_irq_failed;
187 	enum cec_pin_state		state;
188 	struct cec_msg			tx_msg;
189 	u32				tx_bit;
190 	bool				tx_nacked;
191 	u32				tx_signal_free_time;
192 	bool				tx_toggle;
193 	struct cec_msg			rx_msg;
194 	u32				rx_bit;
195 	bool				rx_toggle;
196 	u32				rx_start_bit_low_too_short_cnt;
197 	u64				rx_start_bit_low_too_short_ts;
198 	u32				rx_start_bit_low_too_short_delta;
199 	u32				rx_start_bit_too_short_cnt;
200 	u64				rx_start_bit_too_short_ts;
201 	u32				rx_start_bit_too_short_delta;
202 	u32				rx_start_bit_too_long_cnt;
203 	u32				rx_data_bit_too_short_cnt;
204 	u64				rx_data_bit_too_short_ts;
205 	u32				rx_data_bit_too_short_delta;
206 	u32				rx_data_bit_too_long_cnt;
207 	u32				rx_low_drive_cnt;
208 
209 	struct cec_msg			work_rx_msg;
210 	u8				work_tx_status;
211 	ktime_t				work_tx_ts;
212 	atomic_t			work_irq_change;
213 	atomic_t			work_pin_num_events;
214 	unsigned int			work_pin_events_wr;
215 	unsigned int			work_pin_events_rd;
216 	ktime_t				work_pin_ts[CEC_NUM_PIN_EVENTS];
217 	u8				work_pin_events[CEC_NUM_PIN_EVENTS];
218 	bool				work_pin_events_dropped;
219 	u32				work_pin_events_dropped_cnt;
220 	ktime_t				timer_ts;
221 	u32				timer_cnt;
222 	u32				timer_100us_overruns;
223 	u32				timer_300us_overruns;
224 	u32				timer_max_overrun;
225 	u32				timer_sum_overrun;
226 
227 	u32				tx_custom_low_usecs;
228 	u32				tx_custom_high_usecs;
229 	bool				tx_ignore_nack_until_eom;
230 	bool				tx_custom_pulse;
231 	bool				tx_generated_poll;
232 	bool				tx_post_eom;
233 	u8				tx_extra_bytes;
234 	u32				tx_low_drive_cnt;
235 #ifdef CONFIG_CEC_PIN_ERROR_INJ
236 	u64				error_inj[CEC_ERROR_INJ_OP_ANY + 1];
237 	u8				error_inj_args[CEC_ERROR_INJ_OP_ANY + 1][CEC_ERROR_INJ_NUM_ARGS];
238 #endif
239 };
240 
241 void cec_pin_start_timer(struct cec_pin *pin);
242 
243 #ifdef CONFIG_CEC_PIN_ERROR_INJ
244 bool cec_pin_error_inj_parse_line(struct cec_adapter *adap, char *line);
245 int cec_pin_error_inj_show(struct cec_adapter *adap, struct seq_file *sf);
246 
247 u16 cec_pin_rx_error_inj(struct cec_pin *pin);
248 u16 cec_pin_tx_error_inj(struct cec_pin *pin);
249 #endif
250 
251 #endif
252