Commit | Line | Data |
---|---|---|
ea5c8ef2 HV |
1 | /* |
2 | * cec-pin.h - low-level CEC pin control | |
3 | * | |
4 | * Copyright 2017 Cisco Systems, Inc. and/or its affiliates. All rights reserved. | |
5 | * | |
6 | * This program is free software; you may redistribute it and/or modify | |
7 | * it under the terms of the GNU General Public License as published by | |
8 | * the Free Software Foundation; version 2 of the License. | |
9 | * | |
10 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, | |
11 | * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF | |
12 | * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND | |
13 | * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS | |
14 | * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN | |
15 | * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN | |
16 | * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE | |
17 | * SOFTWARE. | |
18 | */ | |
19 | ||
20 | #ifndef LINUX_CEC_PIN_H | |
21 | #define LINUX_CEC_PIN_H | |
22 | ||
23 | #include <linux/types.h> | |
24 | #include <linux/atomic.h> | |
25 | #include <media/cec.h> | |
26 | ||
27 | enum cec_pin_state { | |
28 | /* CEC is off */ | |
29 | CEC_ST_OFF, | |
30 | /* CEC is idle, waiting for Rx or Tx */ | |
31 | CEC_ST_IDLE, | |
32 | ||
33 | /* Tx states */ | |
34 | ||
35 | /* Pending Tx, waiting for Signal Free Time to expire */ | |
36 | CEC_ST_TX_WAIT, | |
37 | /* Low-drive was detected, wait for bus to go high */ | |
38 | CEC_ST_TX_WAIT_FOR_HIGH, | |
39 | /* Drive CEC low for the start bit */ | |
40 | CEC_ST_TX_START_BIT_LOW, | |
41 | /* Drive CEC high for the start bit */ | |
42 | CEC_ST_TX_START_BIT_HIGH, | |
43 | /* Drive CEC low for the 0 bit */ | |
44 | CEC_ST_TX_DATA_BIT_0_LOW, | |
45 | /* Drive CEC high for the 0 bit */ | |
46 | CEC_ST_TX_DATA_BIT_0_HIGH, | |
47 | /* Drive CEC low for the 1 bit */ | |
48 | CEC_ST_TX_DATA_BIT_1_LOW, | |
49 | /* Drive CEC high for the 1 bit */ | |
50 | CEC_ST_TX_DATA_BIT_1_HIGH, | |
51 | /* | |
52 | * Wait for start of sample time to check for Ack bit or first | |
53 | * four initiator bits to check for Arbitration Lost. | |
54 | */ | |
55 | CEC_ST_TX_DATA_BIT_1_HIGH_PRE_SAMPLE, | |
56 | /* Wait for end of bit period after sampling */ | |
57 | CEC_ST_TX_DATA_BIT_1_HIGH_POST_SAMPLE, | |
58 | ||
59 | /* Rx states */ | |
60 | ||
61 | /* Start bit low detected */ | |
62 | CEC_ST_RX_START_BIT_LOW, | |
63 | /* Start bit high detected */ | |
64 | CEC_ST_RX_START_BIT_HIGH, | |
65 | /* Wait for bit sample time */ | |
66 | CEC_ST_RX_DATA_SAMPLE, | |
67 | /* Wait for earliest end of bit period after sampling */ | |
68 | CEC_ST_RX_DATA_POST_SAMPLE, | |
69 | /* Wait for CEC to go high (i.e. end of bit period */ | |
70 | CEC_ST_RX_DATA_HIGH, | |
71 | /* Drive CEC low to send 0 Ack bit */ | |
72 | CEC_ST_RX_ACK_LOW, | |
73 | /* End of 0 Ack time, wait for earliest end of bit period */ | |
74 | CEC_ST_RX_ACK_LOW_POST, | |
75 | /* Wait for CEC to go high (i.e. end of bit period */ | |
76 | CEC_ST_RX_ACK_HIGH_POST, | |
77 | /* Wait for earliest end of bit period and end of message */ | |
78 | CEC_ST_RX_ACK_FINISH, | |
79 | ||
80 | /* Start low drive */ | |
81 | CEC_ST_LOW_DRIVE, | |
82 | /* Monitor pin using interrupts */ | |
83 | CEC_ST_RX_IRQ, | |
84 | ||
85 | /* Total number of pin states */ | |
86 | CEC_PIN_STATES | |
87 | }; | |
88 | ||
89 | /** | |
90 | * struct cec_pin_ops - low-level CEC pin operations | |
91 | * @read: read the CEC pin. Return true if high, false if low. | |
92 | * @low: drive the CEC pin low. | |
93 | * @high: stop driving the CEC pin. The pull-up will drive the pin | |
94 | * high, unless someone else is driving the pin low. | |
95 | * @enable_irq: optional, enable the interrupt to detect pin voltage changes. | |
96 | * @disable_irq: optional, disable the interrupt. | |
97 | * @free: optional. Free any allocated resources. Called when the | |
98 | * adapter is deleted. | |
99 | * @status: optional, log status information. | |
100 | * | |
101 | * These operations are used by the cec pin framework to manipulate | |
102 | * the CEC pin. | |
103 | */ | |
104 | struct cec_pin_ops { | |
105 | bool (*read)(struct cec_adapter *adap); | |
106 | void (*low)(struct cec_adapter *adap); | |
107 | void (*high)(struct cec_adapter *adap); | |
108 | bool (*enable_irq)(struct cec_adapter *adap); | |
109 | void (*disable_irq)(struct cec_adapter *adap); | |
110 | void (*free)(struct cec_adapter *adap); | |
111 | void (*status)(struct cec_adapter *adap, struct seq_file *file); | |
112 | }; | |
113 | ||
114 | #define CEC_NUM_PIN_EVENTS 128 | |
115 | ||
cb747494 HV |
116 | #define CEC_PIN_IRQ_UNCHANGED 0 |
117 | #define CEC_PIN_IRQ_DISABLE 1 | |
118 | #define CEC_PIN_IRQ_ENABLE 2 | |
119 | ||
ea5c8ef2 HV |
120 | struct cec_pin { |
121 | struct cec_adapter *adap; | |
122 | const struct cec_pin_ops *ops; | |
123 | struct task_struct *kthread; | |
124 | wait_queue_head_t kthread_waitq; | |
125 | struct hrtimer timer; | |
126 | ktime_t ts; | |
127 | unsigned int wait_usecs; | |
128 | u16 la_mask; | |
129 | bool enabled; | |
130 | bool monitor_all; | |
ea5c8ef2 HV |
131 | bool rx_eom; |
132 | bool enable_irq_failed; | |
133 | enum cec_pin_state state; | |
134 | struct cec_msg tx_msg; | |
135 | u32 tx_bit; | |
136 | bool tx_nacked; | |
137 | u32 tx_signal_free_time; | |
138 | struct cec_msg rx_msg; | |
139 | u32 rx_bit; | |
140 | ||
141 | struct cec_msg work_rx_msg; | |
142 | u8 work_tx_status; | |
ea5c8ef2 | 143 | ktime_t work_tx_ts; |
cb747494 | 144 | atomic_t work_irq_change; |
ea5c8ef2 HV |
145 | atomic_t work_pin_events; |
146 | unsigned int work_pin_events_wr; | |
147 | unsigned int work_pin_events_rd; | |
148 | ktime_t work_pin_ts[CEC_NUM_PIN_EVENTS]; | |
149 | bool work_pin_is_high[CEC_NUM_PIN_EVENTS]; | |
150 | ktime_t timer_ts; | |
151 | u32 timer_cnt; | |
152 | u32 timer_100ms_overruns; | |
153 | u32 timer_300ms_overruns; | |
154 | u32 timer_max_overrun; | |
155 | u32 timer_sum_overrun; | |
156 | }; | |
157 | ||
158 | /** | |
159 | * cec_pin_changed() - update pin state from interrupt | |
160 | * | |
161 | * @adap: pointer to the cec adapter | |
162 | * @value: when true the pin is high, otherwise it is low | |
163 | * | |
164 | * If changes of the CEC voltage are detected via an interrupt, then | |
165 | * cec_pin_changed is called from the interrupt with the new value. | |
166 | */ | |
167 | void cec_pin_changed(struct cec_adapter *adap, bool value); | |
168 | ||
169 | /** | |
170 | * cec_pin_allocate_adapter() - allocate a pin-based cec adapter | |
171 | * | |
172 | * @pin_ops: low-level pin operations | |
173 | * @priv: will be stored in adap->priv and can be used by the adapter ops. | |
174 | * Use cec_get_drvdata(adap) to get the priv pointer. | |
175 | * @name: the name of the CEC adapter. Note: this name will be copied. | |
176 | * @caps: capabilities of the CEC adapter. This will be ORed with | |
177 | * CEC_CAP_MONITOR_ALL and CEC_CAP_MONITOR_PIN. | |
178 | * | |
179 | * Allocate a cec adapter using the cec pin framework. | |
180 | * | |
181 | * Return: a pointer to the cec adapter or an error pointer | |
182 | */ | |
183 | struct cec_adapter *cec_pin_allocate_adapter(const struct cec_pin_ops *pin_ops, | |
184 | void *priv, const char *name, u32 caps); | |
185 | ||
186 | #endif |