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
= 1;
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_done(pulse8
->adap
, CEC_TX_STATUS_OK
,
154 case MSGCODE_TRANSMIT_FAILED_ACK
:
155 cec_transmit_done(pulse8
->adap
, CEC_TX_STATUS_NACK
,
158 case MSGCODE_TRANSMIT_FAILED_LINE
:
159 case MSGCODE_TRANSMIT_FAILED_TIMEOUT_DATA
:
160 case MSGCODE_TRANSMIT_FAILED_TIMEOUT_LINE
:
161 cec_transmit_done(pulse8
->adap
, CEC_TX_STATUS_ERROR
,
167 static irqreturn_t
pulse8_interrupt(struct serio
*serio
, unsigned char data
,
170 struct pulse8
*pulse8
= serio_get_drvdata(serio
);
172 if (!pulse8
->started
&& data
!= MSGSTART
)
174 if (data
== MSGESC
) {
175 pulse8
->escape
= true;
178 if (pulse8
->escape
) {
180 pulse8
->escape
= false;
181 } else if (data
== MSGEND
) {
182 struct cec_msg
*msg
= &pulse8
->rx_msg
;
185 dev_info(pulse8
->dev
, "received: %*ph\n",
186 pulse8
->idx
, pulse8
->buf
);
187 pulse8
->data
[0] = pulse8
->buf
[0];
188 switch (pulse8
->buf
[0] & 0x3f) {
189 case MSGCODE_FRAME_START
:
191 msg
->msg
[0] = pulse8
->buf
[1];
193 case MSGCODE_FRAME_DATA
:
194 if (msg
->len
== CEC_MAX_MSG_SIZE
)
196 msg
->msg
[msg
->len
++] = pulse8
->buf
[1];
197 if (pulse8
->buf
[0] & MSGCODE_FRAME_EOM
)
198 schedule_work(&pulse8
->work
);
200 case MSGCODE_TRANSMIT_SUCCEEDED
:
201 case MSGCODE_TRANSMIT_FAILED_LINE
:
202 case MSGCODE_TRANSMIT_FAILED_ACK
:
203 case MSGCODE_TRANSMIT_FAILED_TIMEOUT_DATA
:
204 case MSGCODE_TRANSMIT_FAILED_TIMEOUT_LINE
:
205 schedule_work(&pulse8
->work
);
207 case MSGCODE_HIGH_ERROR
:
208 case MSGCODE_LOW_ERROR
:
209 case MSGCODE_RECEIVE_FAILED
:
210 case MSGCODE_TIMEOUT_ERROR
:
212 case MSGCODE_COMMAND_ACCEPTED
:
213 case MSGCODE_COMMAND_REJECTED
:
215 if (pulse8
->idx
== 0)
217 memcpy(pulse8
->data
, pulse8
->buf
, pulse8
->idx
);
218 pulse8
->len
= pulse8
->idx
;
219 complete(&pulse8
->cmd_done
);
223 pulse8
->started
= false;
225 } else if (data
== MSGSTART
) {
227 pulse8
->started
= true;
231 if (pulse8
->idx
>= DATA_SIZE
) {
233 "throwing away %d bytes of garbage\n", pulse8
->idx
);
236 pulse8
->buf
[pulse8
->idx
++] = data
;
240 static void pulse8_disconnect(struct serio
*serio
)
242 struct pulse8
*pulse8
= serio_get_drvdata(serio
);
244 cec_unregister_adapter(pulse8
->adap
);
245 cancel_delayed_work_sync(&pulse8
->ping_eeprom_work
);
246 dev_info(&serio
->dev
, "disconnected\n");
248 serio_set_drvdata(serio
, NULL
);
252 static int pulse8_send(struct serio
*serio
, const u8
*command
, u8 cmd_len
)
256 err
= serio_write(serio
, MSGSTART
);
259 for (; !err
&& cmd_len
; command
++, cmd_len
--) {
260 if (*command
>= MSGESC
) {
261 err
= serio_write(serio
, MSGESC
);
263 err
= serio_write(serio
, *command
- MSGOFFSET
);
265 err
= serio_write(serio
, *command
);
269 err
= serio_write(serio
, MSGEND
);
274 static int pulse8_send_and_wait_once(struct pulse8
*pulse8
,
275 const u8
*cmd
, u8 cmd_len
,
276 u8 response
, u8 size
)
280 /*dev_info(pulse8->dev, "transmit: %*ph\n", cmd_len, cmd);*/
281 init_completion(&pulse8
->cmd_done
);
283 err
= pulse8_send(pulse8
->serio
, cmd
, cmd_len
);
287 if (!wait_for_completion_timeout(&pulse8
->cmd_done
, HZ
))
289 if ((pulse8
->data
[0] & 0x3f) == MSGCODE_COMMAND_REJECTED
&&
290 cmd
[0] != MSGCODE_SET_CONTROLLED
&&
291 cmd
[0] != MSGCODE_SET_AUTO_ENABLED
&&
292 cmd
[0] != MSGCODE_GET_BUILDDATE
)
295 ((pulse8
->data
[0] & 0x3f) != response
|| pulse8
->len
< size
+ 1)) {
296 dev_info(pulse8
->dev
, "transmit: failed %02x\n",
297 pulse8
->data
[0] & 0x3f);
303 static int pulse8_send_and_wait(struct pulse8
*pulse8
,
304 const u8
*cmd
, u8 cmd_len
, u8 response
, u8 size
)
309 mutex_lock(&pulse8
->write_lock
);
310 err
= pulse8_send_and_wait_once(pulse8
, cmd
, cmd_len
, response
, size
);
312 if (err
== -ENOTTY
) {
313 cmd_sc
[0] = MSGCODE_SET_CONTROLLED
;
315 err
= pulse8_send_and_wait_once(pulse8
, cmd_sc
, 2,
316 MSGCODE_COMMAND_ACCEPTED
, 1);
319 err
= pulse8_send_and_wait_once(pulse8
, cmd
, cmd_len
,
324 mutex_unlock(&pulse8
->write_lock
);
325 return err
== -ENOTTY
? -EIO
: err
;
328 static int pulse8_setup(struct pulse8
*pulse8
, struct serio
*serio
,
329 struct cec_log_addrs
*log_addrs
, u16
*pa
)
331 u8
*data
= pulse8
->data
+ 1;
339 cmd
[0] = MSGCODE_FIRMWARE_VERSION
;
340 err
= pulse8_send_and_wait(pulse8
, cmd
, 1, cmd
[0], 2);
343 pulse8
->vers
= (data
[0] << 8) | data
[1];
344 dev_info(pulse8
->dev
, "Firmware version %04x\n", pulse8
->vers
);
345 if (pulse8
->vers
< 2) {
346 *pa
= CEC_PHYS_ADDR_INVALID
;
350 cmd
[0] = MSGCODE_GET_BUILDDATE
;
351 err
= pulse8_send_and_wait(pulse8
, cmd
, 1, cmd
[0], 4);
354 date
= (data
[0] << 24) | (data
[1] << 16) | (data
[2] << 8) | data
[3];
355 time_to_tm(date
, 0, &tm
);
356 dev_info(pulse8
->dev
, "Firmware build date %04ld.%02d.%02d %02d:%02d:%02d\n",
357 tm
.tm_year
+ 1900, tm
.tm_mon
+ 1, tm
.tm_mday
,
358 tm
.tm_hour
, tm
.tm_min
, tm
.tm_sec
);
360 dev_dbg(pulse8
->dev
, "Persistent config:\n");
361 cmd
[0] = MSGCODE_GET_AUTO_ENABLED
;
362 err
= pulse8_send_and_wait(pulse8
, cmd
, 1, cmd
[0], 1);
365 pulse8
->autonomous
= data
[0];
366 dev_dbg(pulse8
->dev
, "Autonomous mode: %s",
367 data
[0] ? "on" : "off");
369 cmd
[0] = MSGCODE_GET_DEVICE_TYPE
;
370 err
= pulse8_send_and_wait(pulse8
, cmd
, 1, cmd
[0], 1);
373 log_addrs
->primary_device_type
[0] = data
[0];
374 dev_dbg(pulse8
->dev
, "Primary device type: %d\n", data
[0]);
375 switch (log_addrs
->primary_device_type
[0]) {
376 case CEC_OP_PRIM_DEVTYPE_TV
:
377 log_addrs
->log_addr_type
[0] = CEC_LOG_ADDR_TYPE_TV
;
378 log_addrs
->all_device_types
[0] = CEC_OP_ALL_DEVTYPE_TV
;
380 case CEC_OP_PRIM_DEVTYPE_RECORD
:
381 log_addrs
->log_addr_type
[0] = CEC_LOG_ADDR_TYPE_RECORD
;
382 log_addrs
->all_device_types
[0] = CEC_OP_ALL_DEVTYPE_RECORD
;
384 case CEC_OP_PRIM_DEVTYPE_TUNER
:
385 log_addrs
->log_addr_type
[0] = CEC_LOG_ADDR_TYPE_TUNER
;
386 log_addrs
->all_device_types
[0] = CEC_OP_ALL_DEVTYPE_TUNER
;
388 case CEC_OP_PRIM_DEVTYPE_PLAYBACK
:
389 log_addrs
->log_addr_type
[0] = CEC_LOG_ADDR_TYPE_PLAYBACK
;
390 log_addrs
->all_device_types
[0] = CEC_OP_ALL_DEVTYPE_PLAYBACK
;
392 case CEC_OP_PRIM_DEVTYPE_AUDIOSYSTEM
:
393 log_addrs
->log_addr_type
[0] = CEC_LOG_ADDR_TYPE_PLAYBACK
;
394 log_addrs
->all_device_types
[0] = CEC_OP_ALL_DEVTYPE_AUDIOSYSTEM
;
396 case CEC_OP_PRIM_DEVTYPE_SWITCH
:
397 log_addrs
->log_addr_type
[0] = CEC_LOG_ADDR_TYPE_UNREGISTERED
;
398 log_addrs
->all_device_types
[0] = CEC_OP_ALL_DEVTYPE_SWITCH
;
400 case CEC_OP_PRIM_DEVTYPE_PROCESSOR
:
401 log_addrs
->log_addr_type
[0] = CEC_LOG_ADDR_TYPE_SPECIFIC
;
402 log_addrs
->all_device_types
[0] = CEC_OP_ALL_DEVTYPE_SWITCH
;
405 log_addrs
->log_addr_type
[0] = CEC_LOG_ADDR_TYPE_UNREGISTERED
;
406 log_addrs
->all_device_types
[0] = CEC_OP_ALL_DEVTYPE_SWITCH
;
407 dev_info(pulse8
->dev
, "Unknown Primary Device Type: %d\n",
408 log_addrs
->primary_device_type
[0]);
412 cmd
[0] = MSGCODE_GET_LOGICAL_ADDRESS_MASK
;
413 err
= pulse8_send_and_wait(pulse8
, cmd
, 1, cmd
[0], 2);
416 log_addrs
->log_addr_mask
= (data
[0] << 8) | data
[1];
417 dev_dbg(pulse8
->dev
, "Logical address ACK mask: %x\n",
418 log_addrs
->log_addr_mask
);
419 if (log_addrs
->log_addr_mask
)
420 log_addrs
->num_log_addrs
= 1;
422 cmd
[0] = MSGCODE_GET_PHYSICAL_ADDRESS
;
423 err
= pulse8_send_and_wait(pulse8
, cmd
, 1, cmd
[0], 1);
426 *pa
= (data
[0] << 8) | data
[1];
427 dev_dbg(pulse8
->dev
, "Physical address: %x.%x.%x.%x\n",
428 cec_phys_addr_exp(*pa
));
430 cmd
[0] = MSGCODE_GET_HDMI_VERSION
;
431 err
= pulse8_send_and_wait(pulse8
, cmd
, 1, cmd
[0], 1);
434 log_addrs
->cec_version
= data
[0];
435 dev_dbg(pulse8
->dev
, "CEC version: %d\n", log_addrs
->cec_version
);
437 cmd
[0] = MSGCODE_GET_OSD_NAME
;
438 err
= pulse8_send_and_wait(pulse8
, cmd
, 1, cmd
[0], 0);
441 strncpy(log_addrs
->osd_name
, data
, 13);
442 dev_dbg(pulse8
->dev
, "OSD name: %s\n", log_addrs
->osd_name
);
447 static int pulse8_apply_persistent_config(struct pulse8
*pulse8
,
448 struct cec_log_addrs
*log_addrs
,
453 err
= cec_s_log_addrs(pulse8
->adap
, log_addrs
, false);
457 cec_s_phys_addr(pulse8
->adap
, pa
, false);
462 static int pulse8_cec_adap_enable(struct cec_adapter
*adap
, bool enable
)
464 struct pulse8
*pulse8
= adap
->priv
;
468 cmd
[0] = MSGCODE_SET_CONTROLLED
;
470 err
= pulse8_send_and_wait(pulse8
, cmd
, 2,
471 MSGCODE_COMMAND_ACCEPTED
, 1);
472 return enable
? err
: 0;
475 static int pulse8_cec_adap_log_addr(struct cec_adapter
*adap
, u8 log_addr
)
477 struct pulse8
*pulse8
= adap
->priv
;
479 u16 pa
= adap
->phys_addr
;
483 mutex_lock(&pulse8
->config_lock
);
484 if (log_addr
!= CEC_LOG_ADDR_INVALID
)
485 mask
= 1 << log_addr
;
486 cmd
[0] = MSGCODE_SET_ACK_MASK
;
488 cmd
[2] = mask
& 0xff;
489 err
= pulse8_send_and_wait(pulse8
, cmd
, 3,
490 MSGCODE_COMMAND_ACCEPTED
, 0);
491 if ((err
&& mask
!= 0) || pulse8
->restoring_config
)
494 cmd
[0] = MSGCODE_SET_AUTO_ENABLED
;
495 cmd
[1] = log_addr
== CEC_LOG_ADDR_INVALID
? 0 : 1;
496 err
= pulse8_send_and_wait(pulse8
, cmd
, 2,
497 MSGCODE_COMMAND_ACCEPTED
, 0);
500 pulse8
->autonomous
= cmd
[1];
501 if (log_addr
== CEC_LOG_ADDR_INVALID
)
504 cmd
[0] = MSGCODE_SET_DEVICE_TYPE
;
505 cmd
[1] = adap
->log_addrs
.primary_device_type
[0];
506 err
= pulse8_send_and_wait(pulse8
, cmd
, 2,
507 MSGCODE_COMMAND_ACCEPTED
, 0);
511 switch (adap
->log_addrs
.primary_device_type
[0]) {
512 case CEC_OP_PRIM_DEVTYPE_TV
:
513 mask
= CEC_LOG_ADDR_MASK_TV
;
515 case CEC_OP_PRIM_DEVTYPE_RECORD
:
516 mask
= CEC_LOG_ADDR_MASK_RECORD
;
518 case CEC_OP_PRIM_DEVTYPE_TUNER
:
519 mask
= CEC_LOG_ADDR_MASK_TUNER
;
521 case CEC_OP_PRIM_DEVTYPE_PLAYBACK
:
522 mask
= CEC_LOG_ADDR_MASK_PLAYBACK
;
524 case CEC_OP_PRIM_DEVTYPE_AUDIOSYSTEM
:
525 mask
= CEC_LOG_ADDR_MASK_AUDIOSYSTEM
;
527 case CEC_OP_PRIM_DEVTYPE_SWITCH
:
528 mask
= CEC_LOG_ADDR_MASK_UNREGISTERED
;
530 case CEC_OP_PRIM_DEVTYPE_PROCESSOR
:
531 mask
= CEC_LOG_ADDR_MASK_SPECIFIC
;
537 cmd
[0] = MSGCODE_SET_LOGICAL_ADDRESS_MASK
;
539 cmd
[2] = mask
& 0xff;
540 err
= pulse8_send_and_wait(pulse8
, cmd
, 3,
541 MSGCODE_COMMAND_ACCEPTED
, 0);
545 cmd
[0] = MSGCODE_SET_DEFAULT_LOGICAL_ADDRESS
;
547 err
= pulse8_send_and_wait(pulse8
, cmd
, 2,
548 MSGCODE_COMMAND_ACCEPTED
, 0);
552 cmd
[0] = MSGCODE_SET_PHYSICAL_ADDRESS
;
555 err
= pulse8_send_and_wait(pulse8
, cmd
, 3,
556 MSGCODE_COMMAND_ACCEPTED
, 0);
560 cmd
[0] = MSGCODE_SET_HDMI_VERSION
;
561 cmd
[1] = adap
->log_addrs
.cec_version
;
562 err
= pulse8_send_and_wait(pulse8
, cmd
, 2,
563 MSGCODE_COMMAND_ACCEPTED
, 0);
567 if (adap
->log_addrs
.osd_name
[0]) {
568 size_t osd_len
= strlen(adap
->log_addrs
.osd_name
);
569 char *osd_str
= cmd
+ 1;
571 cmd
[0] = MSGCODE_SET_OSD_NAME
;
572 strncpy(cmd
+ 1, adap
->log_addrs
.osd_name
, 13);
574 memset(osd_str
+ osd_len
, ' ', 4 - osd_len
);
576 osd_str
[osd_len
] = '\0';
577 strcpy(adap
->log_addrs
.osd_name
, osd_str
);
579 err
= pulse8_send_and_wait(pulse8
, cmd
, 1 + osd_len
,
580 MSGCODE_COMMAND_ACCEPTED
, 0);
586 if (pulse8
->restoring_config
)
587 pulse8
->restoring_config
= false;
589 pulse8
->config_pending
= true;
590 mutex_unlock(&pulse8
->config_lock
);
594 static int pulse8_cec_adap_transmit(struct cec_adapter
*adap
, u8 attempts
,
595 u32 signal_free_time
, struct cec_msg
*msg
)
597 struct pulse8
*pulse8
= adap
->priv
;
602 cmd
[0] = MSGCODE_TRANSMIT_IDLETIME
;
603 cmd
[1] = signal_free_time
;
604 err
= pulse8_send_and_wait(pulse8
, cmd
, 2,
605 MSGCODE_COMMAND_ACCEPTED
, 1);
606 cmd
[0] = MSGCODE_TRANSMIT_ACK_POLARITY
;
607 cmd
[1] = cec_msg_is_broadcast(msg
);
609 err
= pulse8_send_and_wait(pulse8
, cmd
, 2,
610 MSGCODE_COMMAND_ACCEPTED
, 1);
611 cmd
[0] = msg
->len
== 1 ? MSGCODE_TRANSMIT_EOM
: MSGCODE_TRANSMIT
;
612 cmd
[1] = msg
->msg
[0];
614 err
= pulse8_send_and_wait(pulse8
, cmd
, 2,
615 MSGCODE_COMMAND_ACCEPTED
, 1);
616 if (!err
&& msg
->len
> 1) {
617 cmd
[0] = msg
->len
== 2 ? MSGCODE_TRANSMIT_EOM
:
619 cmd
[1] = msg
->msg
[1];
620 err
= pulse8_send_and_wait(pulse8
, cmd
, 2,
621 MSGCODE_COMMAND_ACCEPTED
, 1);
622 for (i
= 0; !err
&& i
+ 2 < msg
->len
; i
++) {
623 cmd
[0] = (i
+ 2 == msg
->len
- 1) ?
624 MSGCODE_TRANSMIT_EOM
: MSGCODE_TRANSMIT
;
625 cmd
[1] = msg
->msg
[i
+ 2];
626 err
= pulse8_send_and_wait(pulse8
, cmd
, 2,
627 MSGCODE_COMMAND_ACCEPTED
, 1);
634 static int pulse8_received(struct cec_adapter
*adap
, struct cec_msg
*msg
)
639 static const struct cec_adap_ops pulse8_cec_adap_ops
= {
640 .adap_enable
= pulse8_cec_adap_enable
,
641 .adap_log_addr
= pulse8_cec_adap_log_addr
,
642 .adap_transmit
= pulse8_cec_adap_transmit
,
643 .received
= pulse8_received
,
646 static int pulse8_connect(struct serio
*serio
, struct serio_driver
*drv
)
648 u32 caps
= CEC_CAP_TRANSMIT
| CEC_CAP_LOG_ADDRS
| CEC_CAP_PHYS_ADDR
|
649 CEC_CAP_PASSTHROUGH
| CEC_CAP_RC
| CEC_CAP_MONITOR_ALL
;
650 struct pulse8
*pulse8
;
652 struct cec_log_addrs log_addrs
= {};
653 u16 pa
= CEC_PHYS_ADDR_INVALID
;
655 pulse8
= kzalloc(sizeof(*pulse8
), GFP_KERNEL
);
660 pulse8
->serio
= serio
;
661 pulse8
->adap
= cec_allocate_adapter(&pulse8_cec_adap_ops
, pulse8
,
662 "HDMI CEC", caps
, 1);
663 err
= PTR_ERR_OR_ZERO(pulse8
->adap
);
667 pulse8
->dev
= &serio
->dev
;
668 serio_set_drvdata(serio
, pulse8
);
669 INIT_WORK(&pulse8
->work
, pulse8_irq_work_handler
);
670 mutex_init(&pulse8
->write_lock
);
671 mutex_init(&pulse8
->config_lock
);
672 pulse8
->config_pending
= false;
674 err
= serio_open(serio
, drv
);
678 err
= pulse8_setup(pulse8
, serio
, &log_addrs
, &pa
);
682 err
= cec_register_adapter(pulse8
->adap
, &serio
->dev
);
686 pulse8
->dev
= &pulse8
->adap
->devnode
.dev
;
688 if (persistent_config
&& pulse8
->autonomous
) {
689 err
= pulse8_apply_persistent_config(pulse8
, &log_addrs
, pa
);
692 pulse8
->restoring_config
= true;
695 INIT_DELAYED_WORK(&pulse8
->ping_eeprom_work
,
696 pulse8_ping_eeprom_work_handler
);
697 schedule_delayed_work(&pulse8
->ping_eeprom_work
, PING_PERIOD
);
704 cec_delete_adapter(pulse8
->adap
);
705 serio_set_drvdata(serio
, NULL
);
711 static void pulse8_ping_eeprom_work_handler(struct work_struct
*work
)
713 struct pulse8
*pulse8
=
714 container_of(work
, struct pulse8
, ping_eeprom_work
.work
);
717 schedule_delayed_work(&pulse8
->ping_eeprom_work
, PING_PERIOD
);
719 pulse8_send_and_wait(pulse8
, &cmd
, 1,
720 MSGCODE_COMMAND_ACCEPTED
, 0);
722 if (pulse8
->vers
< 2)
725 mutex_lock(&pulse8
->config_lock
);
726 if (pulse8
->config_pending
&& persistent_config
) {
727 dev_dbg(pulse8
->dev
, "writing pending config to EEPROM\n");
728 cmd
= MSGCODE_WRITE_EEPROM
;
729 if (pulse8_send_and_wait(pulse8
, &cmd
, 1,
730 MSGCODE_COMMAND_ACCEPTED
, 0))
731 dev_info(pulse8
->dev
, "failed to write pending config to EEPROM\n");
733 pulse8
->config_pending
= false;
735 mutex_unlock(&pulse8
->config_lock
);
738 static struct serio_device_id pulse8_serio_ids
[] = {
741 .proto
= SERIO_PULSE8_CEC
,
748 MODULE_DEVICE_TABLE(serio
, pulse8_serio_ids
);
750 static struct serio_driver pulse8_drv
= {
752 .name
= "pulse8-cec",
754 .description
= "Pulse Eight HDMI CEC driver",
755 .id_table
= pulse8_serio_ids
,
756 .interrupt
= pulse8_interrupt
,
757 .connect
= pulse8_connect
,
758 .disconnect
= pulse8_disconnect
,
761 module_serio_driver(pulse8_drv
);