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