1
2
3
4
5
6
7
8#ifndef _MEDIA_CEC_H
9#define _MEDIA_CEC_H
10
11#include <linux/poll.h>
12#include <linux/fs.h>
13#include <linux/debugfs.h>
14#include <linux/device.h>
15#include <linux/cdev.h>
16#include <linux/kthread.h>
17#include <linux/timer.h>
18#include <linux/cec-funcs.h>
19#include <media/rc-core.h>
20#include <media/cec-notifier.h>
21
22#define CEC_CAP_DEFAULTS (CEC_CAP_LOG_ADDRS | CEC_CAP_TRANSMIT | \
23 CEC_CAP_PASSTHROUGH | CEC_CAP_RC)
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40struct cec_devnode {
41
42 struct device dev;
43 struct cdev cdev;
44
45
46 int minor;
47 bool registered;
48 bool unregistered;
49 struct list_head fhs;
50 struct mutex lock;
51};
52
53struct cec_adapter;
54struct cec_data;
55struct cec_pin;
56
57struct cec_data {
58 struct list_head list;
59 struct list_head xfer_list;
60 struct cec_adapter *adap;
61 struct cec_msg msg;
62 struct cec_fh *fh;
63 struct delayed_work work;
64 struct completion c;
65 u8 attempts;
66 bool new_initiator;
67 bool blocking;
68 bool completed;
69};
70
71struct cec_msg_entry {
72 struct list_head list;
73 struct cec_msg msg;
74};
75
76struct cec_event_entry {
77 struct list_head list;
78 struct cec_event ev;
79};
80
81#define CEC_NUM_CORE_EVENTS 2
82#define CEC_NUM_EVENTS CEC_EVENT_PIN_HPD_HIGH
83
84struct cec_fh {
85 struct list_head list;
86 struct list_head xfer_list;
87 struct cec_adapter *adap;
88 u8 mode_initiator;
89 u8 mode_follower;
90
91
92 wait_queue_head_t wait;
93 struct mutex lock;
94 struct list_head events[CEC_NUM_EVENTS];
95 u16 queued_events[CEC_NUM_EVENTS];
96 unsigned int total_queued_events;
97 struct cec_event_entry core_events[CEC_NUM_CORE_EVENTS];
98 struct list_head msgs;
99 unsigned int queued_msgs;
100};
101
102#define CEC_SIGNAL_FREE_TIME_RETRY 3
103#define CEC_SIGNAL_FREE_TIME_NEW_INITIATOR 5
104#define CEC_SIGNAL_FREE_TIME_NEXT_XFER 7
105
106
107#define CEC_FREE_TIME_TO_USEC(ft) ((ft) * 2400)
108
109struct cec_adap_ops {
110
111 int (*adap_enable)(struct cec_adapter *adap, bool enable);
112 int (*adap_monitor_all_enable)(struct cec_adapter *adap, bool enable);
113 int (*adap_monitor_pin_enable)(struct cec_adapter *adap, bool enable);
114 int (*adap_log_addr)(struct cec_adapter *adap, u8 logical_addr);
115 int (*adap_transmit)(struct cec_adapter *adap, u8 attempts,
116 u32 signal_free_time, struct cec_msg *msg);
117 void (*adap_status)(struct cec_adapter *adap, struct seq_file *file);
118 void (*adap_free)(struct cec_adapter *adap);
119
120
121 int (*error_inj_show)(struct cec_adapter *adap, struct seq_file *sf);
122 bool (*error_inj_parse_line)(struct cec_adapter *adap, char *line);
123
124
125 int (*received)(struct cec_adapter *adap, struct cec_msg *msg);
126};
127
128
129
130
131
132
133
134
135
136
137
138#define CEC_MAX_MSG_RX_QUEUE_SZ (18 * 3)
139
140
141
142
143
144
145
146#define CEC_MAX_MSG_TX_QUEUE_SZ (18 * 1)
147
148struct cec_adapter {
149 struct module *owner;
150 char name[32];
151 struct cec_devnode devnode;
152 struct mutex lock;
153 struct rc_dev *rc;
154
155 struct list_head transmit_queue;
156 unsigned int transmit_queue_sz;
157 struct list_head wait_queue;
158 struct cec_data *transmitting;
159
160 struct task_struct *kthread_config;
161 struct completion config_completion;
162
163 struct task_struct *kthread;
164 wait_queue_head_t kthread_waitq;
165 wait_queue_head_t waitq;
166
167 const struct cec_adap_ops *ops;
168 void *priv;
169 u32 capabilities;
170 u8 available_log_addrs;
171
172 u16 phys_addr;
173 bool needs_hpd;
174 bool is_configuring;
175 bool is_configured;
176 bool cec_pin_is_high;
177 u32 monitor_all_cnt;
178 u32 monitor_pin_cnt;
179 u32 follower_cnt;
180 struct cec_fh *cec_follower;
181 struct cec_fh *cec_initiator;
182 bool passthrough;
183 struct cec_log_addrs log_addrs;
184
185 u32 tx_timeouts;
186
187#ifdef CONFIG_CEC_NOTIFIER
188 struct cec_notifier *notifier;
189#endif
190#ifdef CONFIG_CEC_PIN
191 struct cec_pin *pin;
192#endif
193
194 struct dentry *cec_dir;
195 struct dentry *status_file;
196 struct dentry *error_inj_file;
197
198 u16 phys_addrs[15];
199 u32 sequence;
200
201 char device_name[32];
202 char input_phys[32];
203 char input_drv[32];
204};
205
206static inline void *cec_get_drvdata(const struct cec_adapter *adap)
207{
208 return adap->priv;
209}
210
211static inline bool cec_has_log_addr(const struct cec_adapter *adap, u8 log_addr)
212{
213 return adap->log_addrs.log_addr_mask & (1 << log_addr);
214}
215
216static inline bool cec_is_sink(const struct cec_adapter *adap)
217{
218 return adap->phys_addr == 0;
219}
220
221
222
223
224
225
226
227
228static inline bool cec_is_registered(const struct cec_adapter *adap)
229{
230 return adap && adap->devnode.registered;
231}
232
233#define cec_phys_addr_exp(pa) \
234 ((pa) >> 12), ((pa) >> 8) & 0xf, ((pa) >> 4) & 0xf, (pa) & 0xf
235
236struct edid;
237
238#if IS_REACHABLE(CONFIG_CEC_CORE)
239struct cec_adapter *cec_allocate_adapter(const struct cec_adap_ops *ops,
240 void *priv, const char *name, u32 caps, u8 available_las);
241int cec_register_adapter(struct cec_adapter *adap, struct device *parent);
242void cec_unregister_adapter(struct cec_adapter *adap);
243void cec_delete_adapter(struct cec_adapter *adap);
244
245int cec_s_log_addrs(struct cec_adapter *adap, struct cec_log_addrs *log_addrs,
246 bool block);
247void cec_s_phys_addr(struct cec_adapter *adap, u16 phys_addr,
248 bool block);
249void cec_s_phys_addr_from_edid(struct cec_adapter *adap,
250 const struct edid *edid);
251int cec_transmit_msg(struct cec_adapter *adap, struct cec_msg *msg,
252 bool block);
253
254
255void cec_transmit_done_ts(struct cec_adapter *adap, u8 status,
256 u8 arb_lost_cnt, u8 nack_cnt, u8 low_drive_cnt,
257 u8 error_cnt, ktime_t ts);
258
259static inline void cec_transmit_done(struct cec_adapter *adap, u8 status,
260 u8 arb_lost_cnt, u8 nack_cnt,
261 u8 low_drive_cnt, u8 error_cnt)
262{
263 cec_transmit_done_ts(adap, status, arb_lost_cnt, nack_cnt,
264 low_drive_cnt, error_cnt, ktime_get());
265}
266
267
268
269
270
271void cec_transmit_attempt_done_ts(struct cec_adapter *adap,
272 u8 status, ktime_t ts);
273
274static inline void cec_transmit_attempt_done(struct cec_adapter *adap,
275 u8 status)
276{
277 cec_transmit_attempt_done_ts(adap, status, ktime_get());
278}
279
280void cec_received_msg_ts(struct cec_adapter *adap,
281 struct cec_msg *msg, ktime_t ts);
282
283static inline void cec_received_msg(struct cec_adapter *adap,
284 struct cec_msg *msg)
285{
286 cec_received_msg_ts(adap, msg, ktime_get());
287}
288
289
290
291
292
293
294
295
296
297
298void cec_queue_pin_cec_event(struct cec_adapter *adap, bool is_high,
299 bool dropped_events, ktime_t ts);
300
301
302
303
304
305
306
307
308
309void cec_queue_pin_hpd_event(struct cec_adapter *adap, bool is_high, ktime_t ts);
310
311
312
313
314
315
316
317
318
319
320
321
322u16 cec_get_edid_phys_addr(const u8 *edid, unsigned int size,
323 unsigned int *offset);
324
325
326
327
328
329
330
331
332
333
334
335
336
337void cec_set_edid_phys_addr(u8 *edid, unsigned int size, u16 phys_addr);
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358u16 cec_phys_addr_for_input(u16 phys_addr, u8 input);
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384int cec_phys_addr_validate(u16 phys_addr, u16 *parent, u16 *port);
385
386#else
387
388static inline int cec_register_adapter(struct cec_adapter *adap,
389 struct device *parent)
390{
391 return 0;
392}
393
394static inline void cec_unregister_adapter(struct cec_adapter *adap)
395{
396}
397
398static inline void cec_delete_adapter(struct cec_adapter *adap)
399{
400}
401
402static inline void cec_s_phys_addr(struct cec_adapter *adap, u16 phys_addr,
403 bool block)
404{
405}
406
407static inline void cec_s_phys_addr_from_edid(struct cec_adapter *adap,
408 const struct edid *edid)
409{
410}
411
412static inline u16 cec_get_edid_phys_addr(const u8 *edid, unsigned int size,
413 unsigned int *offset)
414{
415 if (offset)
416 *offset = 0;
417 return CEC_PHYS_ADDR_INVALID;
418}
419
420static inline void cec_set_edid_phys_addr(u8 *edid, unsigned int size,
421 u16 phys_addr)
422{
423}
424
425static inline u16 cec_phys_addr_for_input(u16 phys_addr, u8 input)
426{
427 return CEC_PHYS_ADDR_INVALID;
428}
429
430static inline int cec_phys_addr_validate(u16 phys_addr, u16 *parent, u16 *port)
431{
432 if (parent)
433 *parent = phys_addr;
434 if (port)
435 *port = 0;
436 return 0;
437}
438
439#endif
440
441
442
443
444
445
446
447
448
449static inline void cec_phys_addr_invalidate(struct cec_adapter *adap)
450{
451 cec_s_phys_addr(adap, CEC_PHYS_ADDR_INVALID, false);
452}
453
454#endif
455