1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31#include <linux/completion.h>
32#include <linux/init.h>
33#include <linux/interrupt.h>
34#include <linux/kernel.h>
35#include <linux/module.h>
36#include <linux/workqueue.h>
37#include <linux/serio.h>
38#include <linux/slab.h>
39#include <linux/time.h>
40#include <linux/delay.h>
41
42#include <media/cec.h>
43
44MODULE_AUTHOR("Hans Verkuil <hverkuil@xs4all.nl>");
45MODULE_DESCRIPTION("Pulse Eight HDMI CEC driver");
46MODULE_LICENSE("GPL");
47
48static int debug;
49static int persistent_config;
50module_param(debug, int, 0644);
51module_param(persistent_config, int, 0644);
52MODULE_PARM_DESC(debug, "debug level (0-2)");
53MODULE_PARM_DESC(persistent_config, "read config from persistent memory (0-1)");
54
55enum pulse8_msgcodes {
56 MSGCODE_NOTHING = 0,
57 MSGCODE_PING,
58 MSGCODE_TIMEOUT_ERROR,
59 MSGCODE_HIGH_ERROR,
60 MSGCODE_LOW_ERROR,
61 MSGCODE_FRAME_START,
62 MSGCODE_FRAME_DATA,
63 MSGCODE_RECEIVE_FAILED,
64 MSGCODE_COMMAND_ACCEPTED,
65 MSGCODE_COMMAND_REJECTED,
66 MSGCODE_SET_ACK_MASK,
67 MSGCODE_TRANSMIT,
68 MSGCODE_TRANSMIT_EOM,
69 MSGCODE_TRANSMIT_IDLETIME,
70 MSGCODE_TRANSMIT_ACK_POLARITY,
71 MSGCODE_TRANSMIT_LINE_TIMEOUT,
72 MSGCODE_TRANSMIT_SUCCEEDED,
73 MSGCODE_TRANSMIT_FAILED_LINE,
74 MSGCODE_TRANSMIT_FAILED_ACK,
75 MSGCODE_TRANSMIT_FAILED_TIMEOUT_DATA,
76 MSGCODE_TRANSMIT_FAILED_TIMEOUT_LINE,
77 MSGCODE_FIRMWARE_VERSION,
78 MSGCODE_START_BOOTLOADER,
79 MSGCODE_GET_BUILDDATE,
80 MSGCODE_SET_CONTROLLED,
81 MSGCODE_GET_AUTO_ENABLED,
82 MSGCODE_SET_AUTO_ENABLED,
83 MSGCODE_GET_DEFAULT_LOGICAL_ADDRESS,
84 MSGCODE_SET_DEFAULT_LOGICAL_ADDRESS,
85 MSGCODE_GET_LOGICAL_ADDRESS_MASK,
86 MSGCODE_SET_LOGICAL_ADDRESS_MASK,
87 MSGCODE_GET_PHYSICAL_ADDRESS,
88 MSGCODE_SET_PHYSICAL_ADDRESS,
89 MSGCODE_GET_DEVICE_TYPE,
90 MSGCODE_SET_DEVICE_TYPE,
91 MSGCODE_GET_HDMI_VERSION,
92 MSGCODE_SET_HDMI_VERSION,
93 MSGCODE_GET_OSD_NAME,
94 MSGCODE_SET_OSD_NAME,
95 MSGCODE_WRITE_EEPROM,
96 MSGCODE_GET_ADAPTER_TYPE,
97 MSGCODE_SET_ACTIVE_SOURCE,
98 MSGCODE_GET_AUTO_POWER_ON,
99 MSGCODE_SET_AUTO_POWER_ON,
100
101 MSGCODE_FRAME_EOM = 0x80,
102 MSGCODE_FRAME_ACK = 0x40,
103};
104
105static const char * const pulse8_msgnames[] = {
106 "NOTHING",
107 "PING",
108 "TIMEOUT_ERROR",
109 "HIGH_ERROR",
110 "LOW_ERROR",
111 "FRAME_START",
112 "FRAME_DATA",
113 "RECEIVE_FAILED",
114 "COMMAND_ACCEPTED",
115 "COMMAND_REJECTED",
116 "SET_ACK_MASK",
117 "TRANSMIT",
118 "TRANSMIT_EOM",
119 "TRANSMIT_IDLETIME",
120 "TRANSMIT_ACK_POLARITY",
121 "TRANSMIT_LINE_TIMEOUT",
122 "TRANSMIT_SUCCEEDED",
123 "TRANSMIT_FAILED_LINE",
124 "TRANSMIT_FAILED_ACK",
125 "TRANSMIT_FAILED_TIMEOUT_DATA",
126 "TRANSMIT_FAILED_TIMEOUT_LINE",
127 "FIRMWARE_VERSION",
128 "START_BOOTLOADER",
129 "GET_BUILDDATE",
130 "SET_CONTROLLED",
131 "GET_AUTO_ENABLED",
132 "SET_AUTO_ENABLED",
133 "GET_DEFAULT_LOGICAL_ADDRESS",
134 "SET_DEFAULT_LOGICAL_ADDRESS",
135 "GET_LOGICAL_ADDRESS_MASK",
136 "SET_LOGICAL_ADDRESS_MASK",
137 "GET_PHYSICAL_ADDRESS",
138 "SET_PHYSICAL_ADDRESS",
139 "GET_DEVICE_TYPE",
140 "SET_DEVICE_TYPE",
141 "GET_HDMI_VERSION",
142 "SET_HDMI_VERSION",
143 "GET_OSD_NAME",
144 "SET_OSD_NAME",
145 "WRITE_EEPROM",
146 "GET_ADAPTER_TYPE",
147 "SET_ACTIVE_SOURCE",
148 "GET_AUTO_POWER_ON",
149 "SET_AUTO_POWER_ON",
150};
151
152static const char *pulse8_msgname(u8 cmd)
153{
154 static char unknown_msg[5];
155
156 if ((cmd & 0x3f) < ARRAY_SIZE(pulse8_msgnames))
157 return pulse8_msgnames[cmd & 0x3f];
158 snprintf(unknown_msg, sizeof(unknown_msg), "0x%02x", cmd);
159 return unknown_msg;
160}
161
162#define MSGSTART 0xff
163#define MSGEND 0xfe
164#define MSGESC 0xfd
165#define MSGOFFSET 3
166
167#define DATA_SIZE 256
168
169#define PING_PERIOD (15 * HZ)
170
171#define NUM_MSGS 8
172
173struct pulse8 {
174 struct device *dev;
175 struct serio *serio;
176 struct cec_adapter *adap;
177 unsigned int vers;
178
179 struct delayed_work ping_eeprom_work;
180
181 struct work_struct irq_work;
182 struct cec_msg rx_msg[NUM_MSGS];
183 unsigned int rx_msg_cur_idx, rx_msg_num;
184
185 spinlock_t msg_lock;
186 u8 new_rx_msg[CEC_MAX_MSG_SIZE];
187 u8 new_rx_msg_len;
188
189 struct work_struct tx_work;
190 u32 tx_done_status;
191 u32 tx_signal_free_time;
192 struct cec_msg tx_msg;
193 bool tx_msg_is_bcast;
194
195 struct completion cmd_done;
196 u8 data[DATA_SIZE];
197 unsigned int len;
198 u8 buf[DATA_SIZE];
199 unsigned int idx;
200 bool escape;
201 bool started;
202
203
204 struct mutex lock;
205 bool config_pending;
206 bool restoring_config;
207 bool autonomous;
208};
209
210static int pulse8_send(struct serio *serio, const u8 *command, u8 cmd_len)
211{
212 int err = 0;
213
214 err = serio_write(serio, MSGSTART);
215 if (err)
216 return err;
217 for (; !err && cmd_len; command++, cmd_len--) {
218 if (*command >= MSGESC) {
219 err = serio_write(serio, MSGESC);
220 if (!err)
221 err = serio_write(serio, *command - MSGOFFSET);
222 } else {
223 err = serio_write(serio, *command);
224 }
225 }
226 if (!err)
227 err = serio_write(serio, MSGEND);
228
229 return err;
230}
231
232static int pulse8_send_and_wait_once(struct pulse8 *pulse8,
233 const u8 *cmd, u8 cmd_len,
234 u8 response, u8 size)
235{
236 int err;
237
238 if (debug > 1)
239 dev_info(pulse8->dev, "transmit %s: %*ph\n",
240 pulse8_msgname(cmd[0]), cmd_len, cmd);
241 init_completion(&pulse8->cmd_done);
242
243 err = pulse8_send(pulse8->serio, cmd, cmd_len);
244 if (err)
245 return err;
246
247 if (!wait_for_completion_timeout(&pulse8->cmd_done, HZ))
248 return -ETIMEDOUT;
249 if ((pulse8->data[0] & 0x3f) == MSGCODE_COMMAND_REJECTED &&
250 cmd[0] != MSGCODE_SET_CONTROLLED &&
251 cmd[0] != MSGCODE_SET_AUTO_ENABLED &&
252 cmd[0] != MSGCODE_GET_BUILDDATE)
253 return -ENOTTY;
254 if (response &&
255 ((pulse8->data[0] & 0x3f) != response || pulse8->len < size + 1)) {
256 dev_info(pulse8->dev, "transmit %s failed with %s\n",
257 pulse8_msgname(cmd[0]),
258 pulse8_msgname(pulse8->data[0]));
259 return -EIO;
260 }
261 return 0;
262}
263
264static int pulse8_send_and_wait(struct pulse8 *pulse8,
265 const u8 *cmd, u8 cmd_len, u8 response, u8 size)
266{
267 u8 cmd_sc[2];
268 int err;
269
270 err = pulse8_send_and_wait_once(pulse8, cmd, cmd_len, response, size);
271 if (err != -ENOTTY)
272 return err;
273
274 cmd_sc[0] = MSGCODE_SET_CONTROLLED;
275 cmd_sc[1] = 1;
276 err = pulse8_send_and_wait_once(pulse8, cmd_sc, 2,
277 MSGCODE_COMMAND_ACCEPTED, 1);
278 if (!err)
279 err = pulse8_send_and_wait_once(pulse8, cmd, cmd_len,
280 response, size);
281 return err == -ENOTTY ? -EIO : err;
282}
283
284static void pulse8_tx_work_handler(struct work_struct *work)
285{
286 struct pulse8 *pulse8 = container_of(work, struct pulse8, tx_work);
287 struct cec_msg *msg = &pulse8->tx_msg;
288 unsigned int i;
289 u8 cmd[2];
290 int err;
291
292 if (msg->len == 0)
293 return;
294
295 mutex_lock(&pulse8->lock);
296 cmd[0] = MSGCODE_TRANSMIT_IDLETIME;
297 cmd[1] = pulse8->tx_signal_free_time;
298 err = pulse8_send_and_wait(pulse8, cmd, 2,
299 MSGCODE_COMMAND_ACCEPTED, 1);
300 cmd[0] = MSGCODE_TRANSMIT_ACK_POLARITY;
301 cmd[1] = cec_msg_is_broadcast(msg);
302 pulse8->tx_msg_is_bcast = cec_msg_is_broadcast(msg);
303 if (!err)
304 err = pulse8_send_and_wait(pulse8, cmd, 2,
305 MSGCODE_COMMAND_ACCEPTED, 1);
306 cmd[0] = msg->len == 1 ? MSGCODE_TRANSMIT_EOM : MSGCODE_TRANSMIT;
307 cmd[1] = msg->msg[0];
308 if (!err)
309 err = pulse8_send_and_wait(pulse8, cmd, 2,
310 MSGCODE_COMMAND_ACCEPTED, 1);
311 if (!err && msg->len > 1) {
312 for (i = 1; !err && i < msg->len; i++) {
313 cmd[0] = ((i == msg->len - 1)) ?
314 MSGCODE_TRANSMIT_EOM : MSGCODE_TRANSMIT;
315 cmd[1] = msg->msg[i];
316 err = pulse8_send_and_wait(pulse8, cmd, 2,
317 MSGCODE_COMMAND_ACCEPTED, 1);
318 }
319 }
320 if (err && debug)
321 dev_info(pulse8->dev, "%s(0x%02x) failed with error %d for msg %*ph\n",
322 pulse8_msgname(cmd[0]), cmd[1],
323 err, msg->len, msg->msg);
324 msg->len = 0;
325 mutex_unlock(&pulse8->lock);
326 if (err)
327 cec_transmit_attempt_done(pulse8->adap, CEC_TX_STATUS_ERROR);
328}
329
330static void pulse8_irq_work_handler(struct work_struct *work)
331{
332 struct pulse8 *pulse8 =
333 container_of(work, struct pulse8, irq_work);
334 unsigned long flags;
335 u32 status;
336
337 spin_lock_irqsave(&pulse8->msg_lock, flags);
338 while (pulse8->rx_msg_num) {
339 spin_unlock_irqrestore(&pulse8->msg_lock, flags);
340 if (debug)
341 dev_info(pulse8->dev, "adap received %*ph\n",
342 pulse8->rx_msg[pulse8->rx_msg_cur_idx].len,
343 pulse8->rx_msg[pulse8->rx_msg_cur_idx].msg);
344 cec_received_msg(pulse8->adap,
345 &pulse8->rx_msg[pulse8->rx_msg_cur_idx]);
346 spin_lock_irqsave(&pulse8->msg_lock, flags);
347 if (pulse8->rx_msg_num)
348 pulse8->rx_msg_num--;
349 pulse8->rx_msg_cur_idx =
350 (pulse8->rx_msg_cur_idx + 1) % NUM_MSGS;
351 }
352 spin_unlock_irqrestore(&pulse8->msg_lock, flags);
353
354 mutex_lock(&pulse8->lock);
355 status = pulse8->tx_done_status;
356 pulse8->tx_done_status = 0;
357 mutex_unlock(&pulse8->lock);
358 if (status)
359 cec_transmit_attempt_done(pulse8->adap, status);
360}
361
362static irqreturn_t pulse8_interrupt(struct serio *serio, unsigned char data,
363 unsigned int flags)
364{
365 struct pulse8 *pulse8 = serio_get_drvdata(serio);
366 unsigned long irq_flags;
367 unsigned int idx;
368
369 if (!pulse8->started && data != MSGSTART)
370 return IRQ_HANDLED;
371 if (data == MSGESC) {
372 pulse8->escape = true;
373 return IRQ_HANDLED;
374 }
375 if (pulse8->escape) {
376 data += MSGOFFSET;
377 pulse8->escape = false;
378 } else if (data == MSGEND) {
379 u8 msgcode = pulse8->buf[0];
380
381 if (debug > 1)
382 dev_info(pulse8->dev, "received %s: %*ph\n",
383 pulse8_msgname(msgcode),
384 pulse8->idx, pulse8->buf);
385 switch (msgcode & 0x3f) {
386 case MSGCODE_FRAME_START:
387
388
389
390
391 if (!(msgcode & MSGCODE_FRAME_EOM)) {
392 pulse8->new_rx_msg_len = 1;
393 pulse8->new_rx_msg[0] = pulse8->buf[1];
394 break;
395 }
396 fallthrough;
397 case MSGCODE_FRAME_DATA:
398 if (pulse8->new_rx_msg_len < CEC_MAX_MSG_SIZE)
399 pulse8->new_rx_msg[pulse8->new_rx_msg_len++] =
400 pulse8->buf[1];
401 if (!(msgcode & MSGCODE_FRAME_EOM))
402 break;
403
404 spin_lock_irqsave(&pulse8->msg_lock, irq_flags);
405 idx = (pulse8->rx_msg_cur_idx + pulse8->rx_msg_num) %
406 NUM_MSGS;
407 if (pulse8->rx_msg_num == NUM_MSGS) {
408 dev_warn(pulse8->dev,
409 "message queue is full, dropping %*ph\n",
410 pulse8->new_rx_msg_len,
411 pulse8->new_rx_msg);
412 spin_unlock_irqrestore(&pulse8->msg_lock,
413 irq_flags);
414 pulse8->new_rx_msg_len = 0;
415 break;
416 }
417 pulse8->rx_msg_num++;
418 memcpy(pulse8->rx_msg[idx].msg, pulse8->new_rx_msg,
419 pulse8->new_rx_msg_len);
420 pulse8->rx_msg[idx].len = pulse8->new_rx_msg_len;
421 spin_unlock_irqrestore(&pulse8->msg_lock, irq_flags);
422 schedule_work(&pulse8->irq_work);
423 pulse8->new_rx_msg_len = 0;
424 break;
425 case MSGCODE_TRANSMIT_SUCCEEDED:
426 WARN_ON(pulse8->tx_done_status);
427 pulse8->tx_done_status = CEC_TX_STATUS_OK;
428 schedule_work(&pulse8->irq_work);
429 break;
430 case MSGCODE_TRANSMIT_FAILED_ACK:
431
432
433
434
435 if (pulse8->tx_msg_is_bcast)
436 break;
437 WARN_ON(pulse8->tx_done_status);
438 pulse8->tx_done_status = CEC_TX_STATUS_NACK;
439 schedule_work(&pulse8->irq_work);
440 break;
441 case MSGCODE_TRANSMIT_FAILED_LINE:
442 case MSGCODE_TRANSMIT_FAILED_TIMEOUT_DATA:
443 case MSGCODE_TRANSMIT_FAILED_TIMEOUT_LINE:
444 WARN_ON(pulse8->tx_done_status);
445 pulse8->tx_done_status = CEC_TX_STATUS_ERROR;
446 schedule_work(&pulse8->irq_work);
447 break;
448 case MSGCODE_HIGH_ERROR:
449 case MSGCODE_LOW_ERROR:
450 case MSGCODE_RECEIVE_FAILED:
451 case MSGCODE_TIMEOUT_ERROR:
452 pulse8->new_rx_msg_len = 0;
453 break;
454 case MSGCODE_COMMAND_ACCEPTED:
455 case MSGCODE_COMMAND_REJECTED:
456 default:
457 if (pulse8->idx == 0)
458 break;
459 memcpy(pulse8->data, pulse8->buf, pulse8->idx);
460 pulse8->len = pulse8->idx;
461 complete(&pulse8->cmd_done);
462 break;
463 }
464 pulse8->idx = 0;
465 pulse8->started = false;
466 return IRQ_HANDLED;
467 } else if (data == MSGSTART) {
468 pulse8->idx = 0;
469 pulse8->started = true;
470 return IRQ_HANDLED;
471 }
472
473 if (pulse8->idx >= DATA_SIZE) {
474 dev_dbg(pulse8->dev,
475 "throwing away %d bytes of garbage\n", pulse8->idx);
476 pulse8->idx = 0;
477 }
478 pulse8->buf[pulse8->idx++] = data;
479 return IRQ_HANDLED;
480}
481
482static int pulse8_cec_adap_enable(struct cec_adapter *adap, bool enable)
483{
484 struct pulse8 *pulse8 = cec_get_drvdata(adap);
485 u8 cmd[16];
486 int err;
487
488 mutex_lock(&pulse8->lock);
489 cmd[0] = MSGCODE_SET_CONTROLLED;
490 cmd[1] = enable;
491 err = pulse8_send_and_wait(pulse8, cmd, 2,
492 MSGCODE_COMMAND_ACCEPTED, 1);
493 if (!enable) {
494 pulse8->rx_msg_num = 0;
495 pulse8->tx_done_status = 0;
496 }
497 mutex_unlock(&pulse8->lock);
498 return enable ? err : 0;
499}
500
501static int pulse8_cec_adap_log_addr(struct cec_adapter *adap, u8 log_addr)
502{
503 struct pulse8 *pulse8 = cec_get_drvdata(adap);
504 u16 mask = 0;
505 u16 pa = adap->phys_addr;
506 u8 cmd[16];
507 int err = 0;
508
509 mutex_lock(&pulse8->lock);
510 if (log_addr != CEC_LOG_ADDR_INVALID)
511 mask = 1 << log_addr;
512 cmd[0] = MSGCODE_SET_ACK_MASK;
513 cmd[1] = mask >> 8;
514 cmd[2] = mask & 0xff;
515 err = pulse8_send_and_wait(pulse8, cmd, 3,
516 MSGCODE_COMMAND_ACCEPTED, 0);
517 if ((err && mask != 0) || pulse8->restoring_config)
518 goto unlock;
519
520 cmd[0] = MSGCODE_SET_AUTO_ENABLED;
521 cmd[1] = log_addr == CEC_LOG_ADDR_INVALID ? 0 : 1;
522 err = pulse8_send_and_wait(pulse8, cmd, 2,
523 MSGCODE_COMMAND_ACCEPTED, 0);
524 if (err)
525 goto unlock;
526 pulse8->autonomous = cmd[1];
527 if (log_addr == CEC_LOG_ADDR_INVALID)
528 goto unlock;
529
530 cmd[0] = MSGCODE_SET_DEVICE_TYPE;
531 cmd[1] = adap->log_addrs.primary_device_type[0];
532 err = pulse8_send_and_wait(pulse8, cmd, 2,
533 MSGCODE_COMMAND_ACCEPTED, 0);
534 if (err)
535 goto unlock;
536
537 switch (adap->log_addrs.primary_device_type[0]) {
538 case CEC_OP_PRIM_DEVTYPE_TV:
539 mask = CEC_LOG_ADDR_MASK_TV;
540 break;
541 case CEC_OP_PRIM_DEVTYPE_RECORD:
542 mask = CEC_LOG_ADDR_MASK_RECORD;
543 break;
544 case CEC_OP_PRIM_DEVTYPE_TUNER:
545 mask = CEC_LOG_ADDR_MASK_TUNER;
546 break;
547 case CEC_OP_PRIM_DEVTYPE_PLAYBACK:
548 mask = CEC_LOG_ADDR_MASK_PLAYBACK;
549 break;
550 case CEC_OP_PRIM_DEVTYPE_AUDIOSYSTEM:
551 mask = CEC_LOG_ADDR_MASK_AUDIOSYSTEM;
552 break;
553 case CEC_OP_PRIM_DEVTYPE_SWITCH:
554 mask = CEC_LOG_ADDR_MASK_UNREGISTERED;
555 break;
556 case CEC_OP_PRIM_DEVTYPE_PROCESSOR:
557 mask = CEC_LOG_ADDR_MASK_SPECIFIC;
558 break;
559 default:
560 mask = 0;
561 break;
562 }
563 cmd[0] = MSGCODE_SET_LOGICAL_ADDRESS_MASK;
564 cmd[1] = mask >> 8;
565 cmd[2] = mask & 0xff;
566 err = pulse8_send_and_wait(pulse8, cmd, 3,
567 MSGCODE_COMMAND_ACCEPTED, 0);
568 if (err)
569 goto unlock;
570
571 cmd[0] = MSGCODE_SET_DEFAULT_LOGICAL_ADDRESS;
572 cmd[1] = log_addr;
573 err = pulse8_send_and_wait(pulse8, cmd, 2,
574 MSGCODE_COMMAND_ACCEPTED, 0);
575 if (err)
576 goto unlock;
577
578 cmd[0] = MSGCODE_SET_PHYSICAL_ADDRESS;
579 cmd[1] = pa >> 8;
580 cmd[2] = pa & 0xff;
581 err = pulse8_send_and_wait(pulse8, cmd, 3,
582 MSGCODE_COMMAND_ACCEPTED, 0);
583 if (err)
584 goto unlock;
585
586 if (pulse8->vers < 10) {
587 cmd[0] = MSGCODE_SET_HDMI_VERSION;
588 cmd[1] = adap->log_addrs.cec_version;
589 err = pulse8_send_and_wait(pulse8, cmd, 2,
590 MSGCODE_COMMAND_ACCEPTED, 0);
591 if (err)
592 goto unlock;
593 }
594
595 if (adap->log_addrs.osd_name[0]) {
596 size_t osd_len = strlen(adap->log_addrs.osd_name);
597 char *osd_str = cmd + 1;
598
599 cmd[0] = MSGCODE_SET_OSD_NAME;
600 strscpy(cmd + 1, adap->log_addrs.osd_name, sizeof(cmd) - 1);
601 if (osd_len < 4) {
602 memset(osd_str + osd_len, ' ', 4 - osd_len);
603 osd_len = 4;
604 osd_str[osd_len] = '\0';
605 strscpy(adap->log_addrs.osd_name, osd_str,
606 sizeof(adap->log_addrs.osd_name));
607 }
608 err = pulse8_send_and_wait(pulse8, cmd, 1 + osd_len,
609 MSGCODE_COMMAND_ACCEPTED, 0);
610 if (err)
611 goto unlock;
612 }
613
614unlock:
615 if (pulse8->restoring_config)
616 pulse8->restoring_config = false;
617 else
618 pulse8->config_pending = true;
619 mutex_unlock(&pulse8->lock);
620 return log_addr == CEC_LOG_ADDR_INVALID ? 0 : err;
621}
622
623static int pulse8_cec_adap_transmit(struct cec_adapter *adap, u8 attempts,
624 u32 signal_free_time, struct cec_msg *msg)
625{
626 struct pulse8 *pulse8 = cec_get_drvdata(adap);
627
628 pulse8->tx_msg = *msg;
629 if (debug)
630 dev_info(pulse8->dev, "adap transmit %*ph\n",
631 msg->len, msg->msg);
632 pulse8->tx_signal_free_time = signal_free_time;
633 schedule_work(&pulse8->tx_work);
634 return 0;
635}
636
637static void pulse8_cec_adap_free(struct cec_adapter *adap)
638{
639 struct pulse8 *pulse8 = cec_get_drvdata(adap);
640
641 cancel_delayed_work_sync(&pulse8->ping_eeprom_work);
642 cancel_work_sync(&pulse8->irq_work);
643 cancel_work_sync(&pulse8->tx_work);
644 kfree(pulse8);
645}
646
647static const struct cec_adap_ops pulse8_cec_adap_ops = {
648 .adap_enable = pulse8_cec_adap_enable,
649 .adap_log_addr = pulse8_cec_adap_log_addr,
650 .adap_transmit = pulse8_cec_adap_transmit,
651 .adap_free = pulse8_cec_adap_free,
652};
653
654static void pulse8_disconnect(struct serio *serio)
655{
656 struct pulse8 *pulse8 = serio_get_drvdata(serio);
657
658 cec_unregister_adapter(pulse8->adap);
659 serio_set_drvdata(serio, NULL);
660 serio_close(serio);
661}
662
663static int pulse8_setup(struct pulse8 *pulse8, struct serio *serio,
664 struct cec_log_addrs *log_addrs, u16 *pa)
665{
666 u8 *data = pulse8->data + 1;
667 u8 cmd[2];
668 int err;
669 time64_t date;
670
671 pulse8->vers = 0;
672
673 cmd[0] = MSGCODE_FIRMWARE_VERSION;
674 err = pulse8_send_and_wait(pulse8, cmd, 1, cmd[0], 2);
675 if (err)
676 return err;
677 pulse8->vers = (data[0] << 8) | data[1];
678 dev_info(pulse8->dev, "Firmware version %04x\n", pulse8->vers);
679 if (pulse8->vers < 2) {
680 *pa = CEC_PHYS_ADDR_INVALID;
681 return 0;
682 }
683
684 cmd[0] = MSGCODE_GET_BUILDDATE;
685 err = pulse8_send_and_wait(pulse8, cmd, 1, cmd[0], 4);
686 if (err)
687 return err;
688 date = (data[0] << 24) | (data[1] << 16) | (data[2] << 8) | data[3];
689 dev_info(pulse8->dev, "Firmware build date %ptT\n", &date);
690
691 dev_dbg(pulse8->dev, "Persistent config:\n");
692 cmd[0] = MSGCODE_GET_AUTO_ENABLED;
693 err = pulse8_send_and_wait(pulse8, cmd, 1, cmd[0], 1);
694 if (err)
695 return err;
696 pulse8->autonomous = data[0];
697 dev_dbg(pulse8->dev, "Autonomous mode: %s",
698 data[0] ? "on" : "off");
699
700 if (pulse8->vers >= 10) {
701 cmd[0] = MSGCODE_GET_AUTO_POWER_ON;
702 err = pulse8_send_and_wait(pulse8, cmd, 1, cmd[0], 1);
703 if (!err)
704 dev_dbg(pulse8->dev, "Auto Power On: %s",
705 data[0] ? "on" : "off");
706 }
707
708 cmd[0] = MSGCODE_GET_DEVICE_TYPE;
709 err = pulse8_send_and_wait(pulse8, cmd, 1, cmd[0], 1);
710 if (err)
711 return err;
712 log_addrs->primary_device_type[0] = data[0];
713 dev_dbg(pulse8->dev, "Primary device type: %d\n", data[0]);
714 switch (log_addrs->primary_device_type[0]) {
715 case CEC_OP_PRIM_DEVTYPE_TV:
716 log_addrs->log_addr_type[0] = CEC_LOG_ADDR_TYPE_TV;
717 log_addrs->all_device_types[0] = CEC_OP_ALL_DEVTYPE_TV;
718 break;
719 case CEC_OP_PRIM_DEVTYPE_RECORD:
720 log_addrs->log_addr_type[0] = CEC_LOG_ADDR_TYPE_RECORD;
721 log_addrs->all_device_types[0] = CEC_OP_ALL_DEVTYPE_RECORD;
722 break;
723 case CEC_OP_PRIM_DEVTYPE_TUNER:
724 log_addrs->log_addr_type[0] = CEC_LOG_ADDR_TYPE_TUNER;
725 log_addrs->all_device_types[0] = CEC_OP_ALL_DEVTYPE_TUNER;
726 break;
727 case CEC_OP_PRIM_DEVTYPE_PLAYBACK:
728 log_addrs->log_addr_type[0] = CEC_LOG_ADDR_TYPE_PLAYBACK;
729 log_addrs->all_device_types[0] = CEC_OP_ALL_DEVTYPE_PLAYBACK;
730 break;
731 case CEC_OP_PRIM_DEVTYPE_AUDIOSYSTEM:
732 log_addrs->log_addr_type[0] = CEC_LOG_ADDR_TYPE_PLAYBACK;
733 log_addrs->all_device_types[0] = CEC_OP_ALL_DEVTYPE_AUDIOSYSTEM;
734 break;
735 case CEC_OP_PRIM_DEVTYPE_SWITCH:
736 log_addrs->log_addr_type[0] = CEC_LOG_ADDR_TYPE_UNREGISTERED;
737 log_addrs->all_device_types[0] = CEC_OP_ALL_DEVTYPE_SWITCH;
738 break;
739 case CEC_OP_PRIM_DEVTYPE_PROCESSOR:
740 log_addrs->log_addr_type[0] = CEC_LOG_ADDR_TYPE_SPECIFIC;
741 log_addrs->all_device_types[0] = CEC_OP_ALL_DEVTYPE_SWITCH;
742 break;
743 default:
744 log_addrs->log_addr_type[0] = CEC_LOG_ADDR_TYPE_UNREGISTERED;
745 log_addrs->all_device_types[0] = CEC_OP_ALL_DEVTYPE_SWITCH;
746 dev_info(pulse8->dev, "Unknown Primary Device Type: %d\n",
747 log_addrs->primary_device_type[0]);
748 break;
749 }
750
751 cmd[0] = MSGCODE_GET_LOGICAL_ADDRESS_MASK;
752 err = pulse8_send_and_wait(pulse8, cmd, 1, cmd[0], 2);
753 if (err)
754 return err;
755 log_addrs->log_addr_mask = (data[0] << 8) | data[1];
756 dev_dbg(pulse8->dev, "Logical address ACK mask: %x\n",
757 log_addrs->log_addr_mask);
758 if (log_addrs->log_addr_mask)
759 log_addrs->num_log_addrs = 1;
760
761 cmd[0] = MSGCODE_GET_PHYSICAL_ADDRESS;
762 err = pulse8_send_and_wait(pulse8, cmd, 1, cmd[0], 1);
763 if (err)
764 return err;
765 *pa = (data[0] << 8) | data[1];
766 dev_dbg(pulse8->dev, "Physical address: %x.%x.%x.%x\n",
767 cec_phys_addr_exp(*pa));
768
769 log_addrs->cec_version = CEC_OP_CEC_VERSION_1_4;
770 if (pulse8->vers < 10) {
771 cmd[0] = MSGCODE_GET_HDMI_VERSION;
772 err = pulse8_send_and_wait(pulse8, cmd, 1, cmd[0], 1);
773 if (err)
774 return err;
775 log_addrs->cec_version = data[0];
776 dev_dbg(pulse8->dev, "CEC version: %d\n", log_addrs->cec_version);
777 }
778
779 cmd[0] = MSGCODE_GET_OSD_NAME;
780 err = pulse8_send_and_wait(pulse8, cmd, 1, cmd[0], 0);
781 if (err)
782 return err;
783 strscpy(log_addrs->osd_name, data, sizeof(log_addrs->osd_name));
784 dev_dbg(pulse8->dev, "OSD name: %s\n", log_addrs->osd_name);
785
786 return 0;
787}
788
789static int pulse8_apply_persistent_config(struct pulse8 *pulse8,
790 struct cec_log_addrs *log_addrs,
791 u16 pa)
792{
793 int err;
794
795 err = cec_s_log_addrs(pulse8->adap, log_addrs, false);
796 if (err)
797 return err;
798
799 cec_s_phys_addr(pulse8->adap, pa, false);
800
801 return 0;
802}
803
804static void pulse8_ping_eeprom_work_handler(struct work_struct *work)
805{
806 struct pulse8 *pulse8 =
807 container_of(work, struct pulse8, ping_eeprom_work.work);
808 u8 cmd;
809
810 mutex_lock(&pulse8->lock);
811 cmd = MSGCODE_PING;
812 pulse8_send_and_wait(pulse8, &cmd, 1,
813 MSGCODE_COMMAND_ACCEPTED, 0);
814
815 if (pulse8->vers < 2)
816 goto unlock;
817
818 if (pulse8->config_pending && persistent_config) {
819 dev_dbg(pulse8->dev, "writing pending config to EEPROM\n");
820 cmd = MSGCODE_WRITE_EEPROM;
821 if (pulse8_send_and_wait(pulse8, &cmd, 1,
822 MSGCODE_COMMAND_ACCEPTED, 0))
823 dev_info(pulse8->dev, "failed to write pending config to EEPROM\n");
824 else
825 pulse8->config_pending = false;
826 }
827unlock:
828 schedule_delayed_work(&pulse8->ping_eeprom_work, PING_PERIOD);
829 mutex_unlock(&pulse8->lock);
830}
831
832static int pulse8_connect(struct serio *serio, struct serio_driver *drv)
833{
834 u32 caps = CEC_CAP_DEFAULTS | CEC_CAP_PHYS_ADDR | CEC_CAP_MONITOR_ALL;
835 struct pulse8 *pulse8;
836 int err = -ENOMEM;
837 struct cec_log_addrs log_addrs = {};
838 u16 pa = CEC_PHYS_ADDR_INVALID;
839
840 pulse8 = kzalloc(sizeof(*pulse8), GFP_KERNEL);
841
842 if (!pulse8)
843 return -ENOMEM;
844
845 pulse8->serio = serio;
846 pulse8->adap = cec_allocate_adapter(&pulse8_cec_adap_ops, pulse8,
847 dev_name(&serio->dev), caps, 1);
848 err = PTR_ERR_OR_ZERO(pulse8->adap);
849 if (err < 0) {
850 kfree(pulse8);
851 return err;
852 }
853
854 pulse8->dev = &serio->dev;
855 serio_set_drvdata(serio, pulse8);
856 INIT_WORK(&pulse8->irq_work, pulse8_irq_work_handler);
857 INIT_WORK(&pulse8->tx_work, pulse8_tx_work_handler);
858 INIT_DELAYED_WORK(&pulse8->ping_eeprom_work,
859 pulse8_ping_eeprom_work_handler);
860 mutex_init(&pulse8->lock);
861 spin_lock_init(&pulse8->msg_lock);
862 pulse8->config_pending = false;
863
864 err = serio_open(serio, drv);
865 if (err)
866 goto delete_adap;
867
868 err = pulse8_setup(pulse8, serio, &log_addrs, &pa);
869 if (err)
870 goto close_serio;
871
872 err = cec_register_adapter(pulse8->adap, &serio->dev);
873 if (err < 0)
874 goto close_serio;
875
876 pulse8->dev = &pulse8->adap->devnode.dev;
877
878 if (persistent_config && pulse8->autonomous) {
879 err = pulse8_apply_persistent_config(pulse8, &log_addrs, pa);
880 if (err)
881 goto close_serio;
882 pulse8->restoring_config = true;
883 }
884
885 schedule_delayed_work(&pulse8->ping_eeprom_work, PING_PERIOD);
886
887 return 0;
888
889close_serio:
890 pulse8->serio = NULL;
891 serio_set_drvdata(serio, NULL);
892 serio_close(serio);
893delete_adap:
894 cec_delete_adapter(pulse8->adap);
895 return err;
896}
897
898static const struct serio_device_id pulse8_serio_ids[] = {
899 {
900 .type = SERIO_RS232,
901 .proto = SERIO_PULSE8_CEC,
902 .id = SERIO_ANY,
903 .extra = SERIO_ANY,
904 },
905 { 0 }
906};
907
908MODULE_DEVICE_TABLE(serio, pulse8_serio_ids);
909
910static struct serio_driver pulse8_drv = {
911 .driver = {
912 .name = "pulse8-cec",
913 },
914 .description = "Pulse Eight HDMI CEC driver",
915 .id_table = pulse8_serio_ids,
916 .interrupt = pulse8_interrupt,
917 .connect = pulse8_connect,
918 .disconnect = pulse8_disconnect,
919};
920
921module_serio_driver(pulse8_drv);
922