2 * Pulse Eight HDMI CEC driver
4 * Copyright 2016 Hans Verkuil <hverkuil@xs4all.nl
6 * This program is free software; you can redistribute it and/or modify it
7 * under the terms of the GNU General Public License as published by the
8 * Free Software Foundation; either version of 2 of the License, or (at your
9 * option) any later version. See the file COPYING in the main directory of
10 * this archive for more details.
16 * - Devices with firmware version < 2 do not store their configuration in
19 * - In autonomous mode, only messages from a TV will be acknowledged, even
20 * polling messages. Upon receiving a message from a TV, the dongle will
21 * respond to messages from any logical address.
23 * - In autonomous mode, the dongle will by default reply Feature Abort
24 * [Unrecognized Opcode] when it receives Give Device Vendor ID. It will
25 * however observe vendor ID's reported by other devices and possibly
26 * alter this behavior. When TV's (and TV's only) report that their vendor ID
27 * is LG (0x00e091), the dongle will itself reply that it has the same vendor
28 * ID, and it will respond to at least one vendor specific command.
30 * - In autonomous mode, the dongle is known to attempt wakeup if it receives
31 * <User Control Pressed> ["Power On"], ["Power] or ["Power Toggle"], or if it
32 * receives <Set Stream Path> with its own physical address. It also does this
33 * if it receives <Vendor Specific Command> [0x03 0x00] from an LG TV.
36 #include <linux/completion.h>
37 #include <linux/init.h>
38 #include <linux/interrupt.h>
39 #include <linux/kernel.h>
40 #include <linux/module.h>
41 #include <linux/workqueue.h>
42 #include <linux/serio.h>
43 #include <linux/slab.h>
44 #include <linux/time.h>
45 #include <linux/delay.h>
47 #include <media/cec.h>
49 MODULE_AUTHOR("Hans Verkuil <hverkuil@xs4all.nl>");
50 MODULE_DESCRIPTION("Pulse Eight HDMI CEC driver");
51 MODULE_LICENSE("GPL");
54 static int persistent_config
;
55 module_param(debug
, int, 0644);
56 module_param(persistent_config
, int, 0644);
57 MODULE_PARM_DESC(debug
, "debug level (0-1)");
58 MODULE_PARM_DESC(persistent_config
, "read config from persistent memory (0-1)");
60 enum pulse8_msgcodes
{
63 MSGCODE_TIMEOUT_ERROR
,
68 MSGCODE_RECEIVE_FAILED
,
69 MSGCODE_COMMAND_ACCEPTED
, /* 0x08 */
70 MSGCODE_COMMAND_REJECTED
,
74 MSGCODE_TRANSMIT_IDLETIME
,
75 MSGCODE_TRANSMIT_ACK_POLARITY
,
76 MSGCODE_TRANSMIT_LINE_TIMEOUT
,
77 MSGCODE_TRANSMIT_SUCCEEDED
, /* 0x10 */
78 MSGCODE_TRANSMIT_FAILED_LINE
,
79 MSGCODE_TRANSMIT_FAILED_ACK
,
80 MSGCODE_TRANSMIT_FAILED_TIMEOUT_DATA
,
81 MSGCODE_TRANSMIT_FAILED_TIMEOUT_LINE
,
82 MSGCODE_FIRMWARE_VERSION
,
83 MSGCODE_START_BOOTLOADER
,
84 MSGCODE_GET_BUILDDATE
,
85 MSGCODE_SET_CONTROLLED
, /* 0x18 */
86 MSGCODE_GET_AUTO_ENABLED
,
87 MSGCODE_SET_AUTO_ENABLED
,
88 MSGCODE_GET_DEFAULT_LOGICAL_ADDRESS
,
89 MSGCODE_SET_DEFAULT_LOGICAL_ADDRESS
,
90 MSGCODE_GET_LOGICAL_ADDRESS_MASK
,
91 MSGCODE_SET_LOGICAL_ADDRESS_MASK
,
92 MSGCODE_GET_PHYSICAL_ADDRESS
,
93 MSGCODE_SET_PHYSICAL_ADDRESS
, /* 0x20 */
94 MSGCODE_GET_DEVICE_TYPE
,
95 MSGCODE_SET_DEVICE_TYPE
,
96 MSGCODE_GET_HDMI_VERSION
,
97 MSGCODE_SET_HDMI_VERSION
,
100 MSGCODE_WRITE_EEPROM
,
101 MSGCODE_GET_ADAPTER_TYPE
, /* 0x28 */
102 MSGCODE_SET_ACTIVE_SOURCE
,
104 MSGCODE_FRAME_EOM
= 0x80,
105 MSGCODE_FRAME_ACK
= 0x40,
108 #define MSGSTART 0xff
113 #define DATA_SIZE 256
115 #define PING_PERIOD (15 * HZ)
120 struct cec_adapter
*adap
;
122 struct completion cmd_done
;
123 struct work_struct work
;
124 struct delayed_work ping_eeprom_work
;
125 struct cec_msg rx_msg
;
132 struct mutex config_lock
;
133 struct mutex write_lock
;
135 bool restoring_config
;
139 static void pulse8_ping_eeprom_work_handler(struct work_struct
*work
);
141 static void pulse8_irq_work_handler(struct work_struct
*work
)
143 struct pulse8
*pulse8
=
144 container_of(work
, struct pulse8
, work
);
146 switch (pulse8
->data
[0] & 0x3f) {
147 case MSGCODE_FRAME_DATA
:
148 cec_received_msg(pulse8
->adap
, &pulse8
->rx_msg
);
150 case MSGCODE_TRANSMIT_SUCCEEDED
:
151 cec_transmit_attempt_done(pulse8
->adap
, CEC_TX_STATUS_OK
);
153 case MSGCODE_TRANSMIT_FAILED_ACK
:
154 cec_transmit_attempt_done(pulse8
->adap
, CEC_TX_STATUS_NACK
);
156 case MSGCODE_TRANSMIT_FAILED_LINE
:
157 case MSGCODE_TRANSMIT_FAILED_TIMEOUT_DATA
:
158 case MSGCODE_TRANSMIT_FAILED_TIMEOUT_LINE
:
159 cec_transmit_attempt_done(pulse8
->adap
, CEC_TX_STATUS_ERROR
);
164 static irqreturn_t
pulse8_interrupt(struct serio
*serio
, unsigned char data
,
167 struct pulse8
*pulse8
= serio_get_drvdata(serio
);
169 if (!pulse8
->started
&& data
!= MSGSTART
)
171 if (data
== MSGESC
) {
172 pulse8
->escape
= true;
175 if (pulse8
->escape
) {
177 pulse8
->escape
= false;
178 } else if (data
== MSGEND
) {
179 struct cec_msg
*msg
= &pulse8
->rx_msg
;
182 dev_info(pulse8
->dev
, "received: %*ph\n",
183 pulse8
->idx
, pulse8
->buf
);
184 pulse8
->data
[0] = pulse8
->buf
[0];
185 switch (pulse8
->buf
[0] & 0x3f) {
186 case MSGCODE_FRAME_START
:
188 msg
->msg
[0] = pulse8
->buf
[1];
190 case MSGCODE_FRAME_DATA
:
191 if (msg
->len
== CEC_MAX_MSG_SIZE
)
193 msg
->msg
[msg
->len
++] = pulse8
->buf
[1];
194 if (pulse8
->buf
[0] & MSGCODE_FRAME_EOM
)
195 schedule_work(&pulse8
->work
);
197 case MSGCODE_TRANSMIT_SUCCEEDED
:
198 case MSGCODE_TRANSMIT_FAILED_LINE
:
199 case MSGCODE_TRANSMIT_FAILED_ACK
:
200 case MSGCODE_TRANSMIT_FAILED_TIMEOUT_DATA
:
201 case MSGCODE_TRANSMIT_FAILED_TIMEOUT_LINE
:
202 schedule_work(&pulse8
->work
);
204 case MSGCODE_HIGH_ERROR
:
205 case MSGCODE_LOW_ERROR
:
206 case MSGCODE_RECEIVE_FAILED
:
207 case MSGCODE_TIMEOUT_ERROR
:
209 case MSGCODE_COMMAND_ACCEPTED
:
210 case MSGCODE_COMMAND_REJECTED
:
212 if (pulse8
->idx
== 0)
214 memcpy(pulse8
->data
, pulse8
->buf
, pulse8
->idx
);
215 pulse8
->len
= pulse8
->idx
;
216 complete(&pulse8
->cmd_done
);
220 pulse8
->started
= false;
222 } else if (data
== MSGSTART
) {
224 pulse8
->started
= true;
228 if (pulse8
->idx
>= DATA_SIZE
) {
230 "throwing away %d bytes of garbage\n", pulse8
->idx
);
233 pulse8
->buf
[pulse8
->idx
++] = data
;
237 static void pulse8_disconnect(struct serio
*serio
)
239 struct pulse8
*pulse8
= serio_get_drvdata(serio
);
241 cec_unregister_adapter(pulse8
->adap
);
242 cancel_delayed_work_sync(&pulse8
->ping_eeprom_work
);
243 dev_info(&serio
->dev
, "disconnected\n");
245 serio_set_drvdata(serio
, NULL
);
249 static int pulse8_send(struct serio
*serio
, const u8
*command
, u8 cmd_len
)
253 err
= serio_write(serio
, MSGSTART
);
256 for (; !err
&& cmd_len
; command
++, cmd_len
--) {
257 if (*command
>= MSGESC
) {
258 err
= serio_write(serio
, MSGESC
);
260 err
= serio_write(serio
, *command
- MSGOFFSET
);
262 err
= serio_write(serio
, *command
);
266 err
= serio_write(serio
, MSGEND
);
271 static int pulse8_send_and_wait_once(struct pulse8
*pulse8
,
272 const u8
*cmd
, u8 cmd_len
,
273 u8 response
, u8 size
)
277 /*dev_info(pulse8->dev, "transmit: %*ph\n", cmd_len, cmd);*/
278 init_completion(&pulse8
->cmd_done
);
280 err
= pulse8_send(pulse8
->serio
, cmd
, cmd_len
);
284 if (!wait_for_completion_timeout(&pulse8
->cmd_done
, HZ
))
286 if ((pulse8
->data
[0] & 0x3f) == MSGCODE_COMMAND_REJECTED
&&
287 cmd
[0] != MSGCODE_SET_CONTROLLED
&&
288 cmd
[0] != MSGCODE_SET_AUTO_ENABLED
&&
289 cmd
[0] != MSGCODE_GET_BUILDDATE
)
292 ((pulse8
->data
[0] & 0x3f) != response
|| pulse8
->len
< size
+ 1)) {
293 dev_info(pulse8
->dev
, "transmit: failed %02x\n",
294 pulse8
->data
[0] & 0x3f);
300 static int pulse8_send_and_wait(struct pulse8
*pulse8
,
301 const u8
*cmd
, u8 cmd_len
, u8 response
, u8 size
)
306 mutex_lock(&pulse8
->write_lock
);
307 err
= pulse8_send_and_wait_once(pulse8
, cmd
, cmd_len
, response
, size
);
309 if (err
== -ENOTTY
) {
310 cmd_sc
[0] = MSGCODE_SET_CONTROLLED
;
312 err
= pulse8_send_and_wait_once(pulse8
, cmd_sc
, 2,
313 MSGCODE_COMMAND_ACCEPTED
, 1);
316 err
= pulse8_send_and_wait_once(pulse8
, cmd
, cmd_len
,
321 mutex_unlock(&pulse8
->write_lock
);
322 return err
== -ENOTTY
? -EIO
: err
;
325 static int pulse8_setup(struct pulse8
*pulse8
, struct serio
*serio
,
326 struct cec_log_addrs
*log_addrs
, u16
*pa
)
328 u8
*data
= pulse8
->data
+ 1;
336 cmd
[0] = MSGCODE_FIRMWARE_VERSION
;
337 err
= pulse8_send_and_wait(pulse8
, cmd
, 1, cmd
[0], 2);
340 pulse8
->vers
= (data
[0] << 8) | data
[1];
341 dev_info(pulse8
->dev
, "Firmware version %04x\n", pulse8
->vers
);
342 if (pulse8
->vers
< 2) {
343 *pa
= CEC_PHYS_ADDR_INVALID
;
347 cmd
[0] = MSGCODE_GET_BUILDDATE
;
348 err
= pulse8_send_and_wait(pulse8
, cmd
, 1, cmd
[0], 4);
351 date
= (data
[0] << 24) | (data
[1] << 16) | (data
[2] << 8) | data
[3];
352 time64_to_tm(date
, 0, &tm
);
353 dev_info(pulse8
->dev
, "Firmware build date %04ld.%02d.%02d %02d:%02d:%02d\n",
354 tm
.tm_year
+ 1900, tm
.tm_mon
+ 1, tm
.tm_mday
,
355 tm
.tm_hour
, tm
.tm_min
, tm
.tm_sec
);
357 dev_dbg(pulse8
->dev
, "Persistent config:\n");
358 cmd
[0] = MSGCODE_GET_AUTO_ENABLED
;
359 err
= pulse8_send_and_wait(pulse8
, cmd
, 1, cmd
[0], 1);
362 pulse8
->autonomous
= data
[0];
363 dev_dbg(pulse8
->dev
, "Autonomous mode: %s",
364 data
[0] ? "on" : "off");
366 cmd
[0] = MSGCODE_GET_DEVICE_TYPE
;
367 err
= pulse8_send_and_wait(pulse8
, cmd
, 1, cmd
[0], 1);
370 log_addrs
->primary_device_type
[0] = data
[0];
371 dev_dbg(pulse8
->dev
, "Primary device type: %d\n", data
[0]);
372 switch (log_addrs
->primary_device_type
[0]) {
373 case CEC_OP_PRIM_DEVTYPE_TV
:
374 log_addrs
->log_addr_type
[0] = CEC_LOG_ADDR_TYPE_TV
;
375 log_addrs
->all_device_types
[0] = CEC_OP_ALL_DEVTYPE_TV
;
377 case CEC_OP_PRIM_DEVTYPE_RECORD
:
378 log_addrs
->log_addr_type
[0] = CEC_LOG_ADDR_TYPE_RECORD
;
379 log_addrs
->all_device_types
[0] = CEC_OP_ALL_DEVTYPE_RECORD
;
381 case CEC_OP_PRIM_DEVTYPE_TUNER
:
382 log_addrs
->log_addr_type
[0] = CEC_LOG_ADDR_TYPE_TUNER
;
383 log_addrs
->all_device_types
[0] = CEC_OP_ALL_DEVTYPE_TUNER
;
385 case CEC_OP_PRIM_DEVTYPE_PLAYBACK
:
386 log_addrs
->log_addr_type
[0] = CEC_LOG_ADDR_TYPE_PLAYBACK
;
387 log_addrs
->all_device_types
[0] = CEC_OP_ALL_DEVTYPE_PLAYBACK
;
389 case CEC_OP_PRIM_DEVTYPE_AUDIOSYSTEM
:
390 log_addrs
->log_addr_type
[0] = CEC_LOG_ADDR_TYPE_PLAYBACK
;
391 log_addrs
->all_device_types
[0] = CEC_OP_ALL_DEVTYPE_AUDIOSYSTEM
;
393 case CEC_OP_PRIM_DEVTYPE_SWITCH
:
394 log_addrs
->log_addr_type
[0] = CEC_LOG_ADDR_TYPE_UNREGISTERED
;
395 log_addrs
->all_device_types
[0] = CEC_OP_ALL_DEVTYPE_SWITCH
;
397 case CEC_OP_PRIM_DEVTYPE_PROCESSOR
:
398 log_addrs
->log_addr_type
[0] = CEC_LOG_ADDR_TYPE_SPECIFIC
;
399 log_addrs
->all_device_types
[0] = CEC_OP_ALL_DEVTYPE_SWITCH
;
402 log_addrs
->log_addr_type
[0] = CEC_LOG_ADDR_TYPE_UNREGISTERED
;
403 log_addrs
->all_device_types
[0] = CEC_OP_ALL_DEVTYPE_SWITCH
;
404 dev_info(pulse8
->dev
, "Unknown Primary Device Type: %d\n",
405 log_addrs
->primary_device_type
[0]);
409 cmd
[0] = MSGCODE_GET_LOGICAL_ADDRESS_MASK
;
410 err
= pulse8_send_and_wait(pulse8
, cmd
, 1, cmd
[0], 2);
413 log_addrs
->log_addr_mask
= (data
[0] << 8) | data
[1];
414 dev_dbg(pulse8
->dev
, "Logical address ACK mask: %x\n",
415 log_addrs
->log_addr_mask
);
416 if (log_addrs
->log_addr_mask
)
417 log_addrs
->num_log_addrs
= 1;
419 cmd
[0] = MSGCODE_GET_PHYSICAL_ADDRESS
;
420 err
= pulse8_send_and_wait(pulse8
, cmd
, 1, cmd
[0], 1);
423 *pa
= (data
[0] << 8) | data
[1];
424 dev_dbg(pulse8
->dev
, "Physical address: %x.%x.%x.%x\n",
425 cec_phys_addr_exp(*pa
));
427 cmd
[0] = MSGCODE_GET_HDMI_VERSION
;
428 err
= pulse8_send_and_wait(pulse8
, cmd
, 1, cmd
[0], 1);
431 log_addrs
->cec_version
= data
[0];
432 dev_dbg(pulse8
->dev
, "CEC version: %d\n", log_addrs
->cec_version
);
434 cmd
[0] = MSGCODE_GET_OSD_NAME
;
435 err
= pulse8_send_and_wait(pulse8
, cmd
, 1, cmd
[0], 0);
438 strncpy(log_addrs
->osd_name
, data
, 13);
439 dev_dbg(pulse8
->dev
, "OSD name: %s\n", log_addrs
->osd_name
);
444 static int pulse8_apply_persistent_config(struct pulse8
*pulse8
,
445 struct cec_log_addrs
*log_addrs
,
450 err
= cec_s_log_addrs(pulse8
->adap
, log_addrs
, false);
454 cec_s_phys_addr(pulse8
->adap
, pa
, false);
459 static int pulse8_cec_adap_enable(struct cec_adapter
*adap
, bool enable
)
461 struct pulse8
*pulse8
= cec_get_drvdata(adap
);
465 cmd
[0] = MSGCODE_SET_CONTROLLED
;
467 err
= pulse8_send_and_wait(pulse8
, cmd
, 2,
468 MSGCODE_COMMAND_ACCEPTED
, 1);
469 return enable
? err
: 0;
472 static int pulse8_cec_adap_log_addr(struct cec_adapter
*adap
, u8 log_addr
)
474 struct pulse8
*pulse8
= cec_get_drvdata(adap
);
476 u16 pa
= adap
->phys_addr
;
480 mutex_lock(&pulse8
->config_lock
);
481 if (log_addr
!= CEC_LOG_ADDR_INVALID
)
482 mask
= 1 << log_addr
;
483 cmd
[0] = MSGCODE_SET_ACK_MASK
;
485 cmd
[2] = mask
& 0xff;
486 err
= pulse8_send_and_wait(pulse8
, cmd
, 3,
487 MSGCODE_COMMAND_ACCEPTED
, 0);
488 if ((err
&& mask
!= 0) || pulse8
->restoring_config
)
491 cmd
[0] = MSGCODE_SET_AUTO_ENABLED
;
492 cmd
[1] = log_addr
== CEC_LOG_ADDR_INVALID
? 0 : 1;
493 err
= pulse8_send_and_wait(pulse8
, cmd
, 2,
494 MSGCODE_COMMAND_ACCEPTED
, 0);
497 pulse8
->autonomous
= cmd
[1];
498 if (log_addr
== CEC_LOG_ADDR_INVALID
)
501 cmd
[0] = MSGCODE_SET_DEVICE_TYPE
;
502 cmd
[1] = adap
->log_addrs
.primary_device_type
[0];
503 err
= pulse8_send_and_wait(pulse8
, cmd
, 2,
504 MSGCODE_COMMAND_ACCEPTED
, 0);
508 switch (adap
->log_addrs
.primary_device_type
[0]) {
509 case CEC_OP_PRIM_DEVTYPE_TV
:
510 mask
= CEC_LOG_ADDR_MASK_TV
;
512 case CEC_OP_PRIM_DEVTYPE_RECORD
:
513 mask
= CEC_LOG_ADDR_MASK_RECORD
;
515 case CEC_OP_PRIM_DEVTYPE_TUNER
:
516 mask
= CEC_LOG_ADDR_MASK_TUNER
;
518 case CEC_OP_PRIM_DEVTYPE_PLAYBACK
:
519 mask
= CEC_LOG_ADDR_MASK_PLAYBACK
;
521 case CEC_OP_PRIM_DEVTYPE_AUDIOSYSTEM
:
522 mask
= CEC_LOG_ADDR_MASK_AUDIOSYSTEM
;
524 case CEC_OP_PRIM_DEVTYPE_SWITCH
:
525 mask
= CEC_LOG_ADDR_MASK_UNREGISTERED
;
527 case CEC_OP_PRIM_DEVTYPE_PROCESSOR
:
528 mask
= CEC_LOG_ADDR_MASK_SPECIFIC
;
534 cmd
[0] = MSGCODE_SET_LOGICAL_ADDRESS_MASK
;
536 cmd
[2] = mask
& 0xff;
537 err
= pulse8_send_and_wait(pulse8
, cmd
, 3,
538 MSGCODE_COMMAND_ACCEPTED
, 0);
542 cmd
[0] = MSGCODE_SET_DEFAULT_LOGICAL_ADDRESS
;
544 err
= pulse8_send_and_wait(pulse8
, cmd
, 2,
545 MSGCODE_COMMAND_ACCEPTED
, 0);
549 cmd
[0] = MSGCODE_SET_PHYSICAL_ADDRESS
;
552 err
= pulse8_send_and_wait(pulse8
, cmd
, 3,
553 MSGCODE_COMMAND_ACCEPTED
, 0);
557 cmd
[0] = MSGCODE_SET_HDMI_VERSION
;
558 cmd
[1] = adap
->log_addrs
.cec_version
;
559 err
= pulse8_send_and_wait(pulse8
, cmd
, 2,
560 MSGCODE_COMMAND_ACCEPTED
, 0);
564 if (adap
->log_addrs
.osd_name
[0]) {
565 size_t osd_len
= strlen(adap
->log_addrs
.osd_name
);
566 char *osd_str
= cmd
+ 1;
568 cmd
[0] = MSGCODE_SET_OSD_NAME
;
569 strncpy(cmd
+ 1, adap
->log_addrs
.osd_name
, 13);
571 memset(osd_str
+ osd_len
, ' ', 4 - osd_len
);
573 osd_str
[osd_len
] = '\0';
574 strcpy(adap
->log_addrs
.osd_name
, osd_str
);
576 err
= pulse8_send_and_wait(pulse8
, cmd
, 1 + osd_len
,
577 MSGCODE_COMMAND_ACCEPTED
, 0);
583 if (pulse8
->restoring_config
)
584 pulse8
->restoring_config
= false;
586 pulse8
->config_pending
= true;
587 mutex_unlock(&pulse8
->config_lock
);
591 static int pulse8_cec_adap_transmit(struct cec_adapter
*adap
, u8 attempts
,
592 u32 signal_free_time
, struct cec_msg
*msg
)
594 struct pulse8
*pulse8
= cec_get_drvdata(adap
);
599 cmd
[0] = MSGCODE_TRANSMIT_IDLETIME
;
600 cmd
[1] = signal_free_time
;
601 err
= pulse8_send_and_wait(pulse8
, cmd
, 2,
602 MSGCODE_COMMAND_ACCEPTED
, 1);
603 cmd
[0] = MSGCODE_TRANSMIT_ACK_POLARITY
;
604 cmd
[1] = cec_msg_is_broadcast(msg
);
606 err
= pulse8_send_and_wait(pulse8
, cmd
, 2,
607 MSGCODE_COMMAND_ACCEPTED
, 1);
608 cmd
[0] = msg
->len
== 1 ? MSGCODE_TRANSMIT_EOM
: MSGCODE_TRANSMIT
;
609 cmd
[1] = msg
->msg
[0];
611 err
= pulse8_send_and_wait(pulse8
, cmd
, 2,
612 MSGCODE_COMMAND_ACCEPTED
, 1);
613 if (!err
&& msg
->len
> 1) {
614 cmd
[0] = msg
->len
== 2 ? MSGCODE_TRANSMIT_EOM
:
616 cmd
[1] = msg
->msg
[1];
617 err
= pulse8_send_and_wait(pulse8
, cmd
, 2,
618 MSGCODE_COMMAND_ACCEPTED
, 1);
619 for (i
= 0; !err
&& i
+ 2 < msg
->len
; i
++) {
620 cmd
[0] = (i
+ 2 == msg
->len
- 1) ?
621 MSGCODE_TRANSMIT_EOM
: MSGCODE_TRANSMIT
;
622 cmd
[1] = msg
->msg
[i
+ 2];
623 err
= pulse8_send_and_wait(pulse8
, cmd
, 2,
624 MSGCODE_COMMAND_ACCEPTED
, 1);
631 static int pulse8_received(struct cec_adapter
*adap
, struct cec_msg
*msg
)
636 static const struct cec_adap_ops pulse8_cec_adap_ops
= {
637 .adap_enable
= pulse8_cec_adap_enable
,
638 .adap_log_addr
= pulse8_cec_adap_log_addr
,
639 .adap_transmit
= pulse8_cec_adap_transmit
,
640 .received
= pulse8_received
,
643 static int pulse8_connect(struct serio
*serio
, struct serio_driver
*drv
)
645 u32 caps
= CEC_CAP_DEFAULTS
| CEC_CAP_PHYS_ADDR
| CEC_CAP_MONITOR_ALL
;
646 struct pulse8
*pulse8
;
648 struct cec_log_addrs log_addrs
= {};
649 u16 pa
= CEC_PHYS_ADDR_INVALID
;
651 pulse8
= kzalloc(sizeof(*pulse8
), GFP_KERNEL
);
656 pulse8
->serio
= serio
;
657 pulse8
->adap
= cec_allocate_adapter(&pulse8_cec_adap_ops
, pulse8
,
658 dev_name(&serio
->dev
), caps
, 1);
659 err
= PTR_ERR_OR_ZERO(pulse8
->adap
);
663 pulse8
->dev
= &serio
->dev
;
664 serio_set_drvdata(serio
, pulse8
);
665 INIT_WORK(&pulse8
->work
, pulse8_irq_work_handler
);
666 mutex_init(&pulse8
->write_lock
);
667 mutex_init(&pulse8
->config_lock
);
668 pulse8
->config_pending
= false;
670 err
= serio_open(serio
, drv
);
674 err
= pulse8_setup(pulse8
, serio
, &log_addrs
, &pa
);
678 err
= cec_register_adapter(pulse8
->adap
, &serio
->dev
);
682 pulse8
->dev
= &pulse8
->adap
->devnode
.dev
;
684 if (persistent_config
&& pulse8
->autonomous
) {
685 err
= pulse8_apply_persistent_config(pulse8
, &log_addrs
, pa
);
688 pulse8
->restoring_config
= true;
691 INIT_DELAYED_WORK(&pulse8
->ping_eeprom_work
,
692 pulse8_ping_eeprom_work_handler
);
693 schedule_delayed_work(&pulse8
->ping_eeprom_work
, PING_PERIOD
);
700 cec_delete_adapter(pulse8
->adap
);
701 serio_set_drvdata(serio
, NULL
);
707 static void pulse8_ping_eeprom_work_handler(struct work_struct
*work
)
709 struct pulse8
*pulse8
=
710 container_of(work
, struct pulse8
, ping_eeprom_work
.work
);
713 schedule_delayed_work(&pulse8
->ping_eeprom_work
, PING_PERIOD
);
715 pulse8_send_and_wait(pulse8
, &cmd
, 1,
716 MSGCODE_COMMAND_ACCEPTED
, 0);
718 if (pulse8
->vers
< 2)
721 mutex_lock(&pulse8
->config_lock
);
722 if (pulse8
->config_pending
&& persistent_config
) {
723 dev_dbg(pulse8
->dev
, "writing pending config to EEPROM\n");
724 cmd
= MSGCODE_WRITE_EEPROM
;
725 if (pulse8_send_and_wait(pulse8
, &cmd
, 1,
726 MSGCODE_COMMAND_ACCEPTED
, 0))
727 dev_info(pulse8
->dev
, "failed to write pending config to EEPROM\n");
729 pulse8
->config_pending
= false;
731 mutex_unlock(&pulse8
->config_lock
);
734 static const struct serio_device_id pulse8_serio_ids
[] = {
737 .proto
= SERIO_PULSE8_CEC
,
744 MODULE_DEVICE_TABLE(serio
, pulse8_serio_ids
);
746 static struct serio_driver pulse8_drv
= {
748 .name
= "pulse8-cec",
750 .description
= "Pulse Eight HDMI CEC driver",
751 .id_table
= pulse8_serio_ids
,
752 .interrupt
= pulse8_interrupt
,
753 .connect
= pulse8_connect
,
754 .disconnect
= pulse8_disconnect
,
757 module_serio_driver(pulse8_drv
);