1 // SPDX-License-Identifier: GPL-2.0-or-later
3 * Pulse Eight HDMI CEC driver
5 * Copyright 2016 Hans Verkuil <hverkuil@xs4all.nl
11 * - Devices with firmware version < 2 do not store their configuration in
14 * - In autonomous mode, only messages from a TV will be acknowledged, even
15 * polling messages. Upon receiving a message from a TV, the dongle will
16 * respond to messages from any logical address.
18 * - In autonomous mode, the dongle will by default reply Feature Abort
19 * [Unrecognized Opcode] when it receives Give Device Vendor ID. It will
20 * however observe vendor ID's reported by other devices and possibly
21 * alter this behavior. When TV's (and TV's only) report that their vendor ID
22 * is LG (0x00e091), the dongle will itself reply that it has the same vendor
23 * ID, and it will respond to at least one vendor specific command.
25 * - In autonomous mode, the dongle is known to attempt wakeup if it receives
26 * <User Control Pressed> ["Power On"], ["Power] or ["Power Toggle"], or if it
27 * receives <Set Stream Path> with its own physical address. It also does this
28 * if it receives <Vendor Specific Command> [0x03 0x00] from an LG TV.
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>
42 #include <media/cec.h>
44 MODULE_AUTHOR("Hans Verkuil <hverkuil@xs4all.nl>");
45 MODULE_DESCRIPTION("Pulse Eight HDMI CEC driver");
46 MODULE_LICENSE("GPL");
49 static int persistent_config
;
50 module_param(debug
, int, 0644);
51 module_param(persistent_config
, int, 0644);
52 MODULE_PARM_DESC(debug
, "debug level (0-2)");
53 MODULE_PARM_DESC(persistent_config
, "read config from persistent memory (0-1)");
55 enum pulse8_msgcodes
{
58 MSGCODE_TIMEOUT_ERROR
,
63 MSGCODE_RECEIVE_FAILED
,
64 MSGCODE_COMMAND_ACCEPTED
, /* 0x08 */
65 MSGCODE_COMMAND_REJECTED
,
69 MSGCODE_TRANSMIT_IDLETIME
,
70 MSGCODE_TRANSMIT_ACK_POLARITY
,
71 MSGCODE_TRANSMIT_LINE_TIMEOUT
,
72 MSGCODE_TRANSMIT_SUCCEEDED
, /* 0x10 */
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
, /* 0x18 */
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
, /* 0x20 */
89 MSGCODE_GET_DEVICE_TYPE
,
90 MSGCODE_SET_DEVICE_TYPE
,
91 MSGCODE_GET_HDMI_VERSION
, /* Removed in FW >= 10 */
92 MSGCODE_SET_HDMI_VERSION
,
96 MSGCODE_GET_ADAPTER_TYPE
, /* 0x28 */
97 MSGCODE_SET_ACTIVE_SOURCE
,
98 MSGCODE_GET_AUTO_POWER_ON
, /* New for FW >= 10 */
99 MSGCODE_SET_AUTO_POWER_ON
,
101 MSGCODE_FRAME_EOM
= 0x80,
102 MSGCODE_FRAME_ACK
= 0x40,
105 static const char * const pulse8_msgnames
[] = {
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",
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",
152 static const char *pulse8_msgname(u8 cmd
)
154 static char unknown_msg
[5];
156 if ((cmd
& 0x3f) < ARRAY_SIZE(pulse8_msgnames
))
157 return pulse8_msgnames
[cmd
& 0x3f];
158 snprintf(unknown_msg
, sizeof(unknown_msg
), "0x%02x", cmd
);
162 #define MSGSTART 0xff
167 #define DATA_SIZE 256
169 #define PING_PERIOD (15 * HZ)
176 struct cec_adapter
*adap
;
179 struct delayed_work ping_eeprom_work
;
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 /* protect rx_msg_cur_idx and rx_msg_num */
186 u8 new_rx_msg
[CEC_MAX_MSG_SIZE
];
189 struct work_struct tx_work
;
191 u32 tx_signal_free_time
;
192 struct cec_msg tx_msg
;
193 bool tx_msg_is_bcast
;
195 struct completion cmd_done
;
203 /* locks access to the adapter */
206 bool restoring_config
;
210 static int pulse8_send(struct serio
*serio
, const u8
*command
, u8 cmd_len
)
214 err
= serio_write(serio
, MSGSTART
);
217 for (; !err
&& cmd_len
; command
++, cmd_len
--) {
218 if (*command
>= MSGESC
) {
219 err
= serio_write(serio
, MSGESC
);
221 err
= serio_write(serio
, *command
- MSGOFFSET
);
223 err
= serio_write(serio
, *command
);
227 err
= serio_write(serio
, MSGEND
);
232 static int pulse8_send_and_wait_once(struct pulse8
*pulse8
,
233 const u8
*cmd
, u8 cmd_len
,
234 u8 response
, u8 size
)
239 dev_info(pulse8
->dev
, "transmit %s: %*ph\n",
240 pulse8_msgname(cmd
[0]), cmd_len
, cmd
);
241 init_completion(&pulse8
->cmd_done
);
243 err
= pulse8_send(pulse8
->serio
, cmd
, cmd_len
);
247 if (!wait_for_completion_timeout(&pulse8
->cmd_done
, HZ
))
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
)
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]));
264 static int pulse8_send_and_wait(struct pulse8
*pulse8
,
265 const u8
*cmd
, u8 cmd_len
, u8 response
, u8 size
)
270 err
= pulse8_send_and_wait_once(pulse8
, cmd
, cmd_len
, response
, size
);
274 cmd_sc
[0] = MSGCODE_SET_CONTROLLED
;
276 err
= pulse8_send_and_wait_once(pulse8
, cmd_sc
, 2,
277 MSGCODE_COMMAND_ACCEPTED
, 1);
279 err
= pulse8_send_and_wait_once(pulse8
, cmd
, cmd_len
,
281 return err
== -ENOTTY
? -EIO
: err
;
284 static void pulse8_tx_work_handler(struct work_struct
*work
)
286 struct pulse8
*pulse8
= container_of(work
, struct pulse8
, tx_work
);
287 struct cec_msg
*msg
= &pulse8
->tx_msg
;
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
);
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];
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);
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
);
325 mutex_unlock(&pulse8
->lock
);
327 cec_transmit_attempt_done(pulse8
->adap
, CEC_TX_STATUS_ERROR
);
330 static void pulse8_irq_work_handler(struct work_struct
*work
)
332 struct pulse8
*pulse8
=
333 container_of(work
, struct pulse8
, irq_work
);
337 spin_lock_irqsave(&pulse8
->msg_lock
, flags
);
338 while (pulse8
->rx_msg_num
) {
339 spin_unlock_irqrestore(&pulse8
->msg_lock
, flags
);
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
;
352 spin_unlock_irqrestore(&pulse8
->msg_lock
, flags
);
354 mutex_lock(&pulse8
->lock
);
355 status
= pulse8
->tx_done_status
;
356 pulse8
->tx_done_status
= 0;
357 mutex_unlock(&pulse8
->lock
);
359 cec_transmit_attempt_done(pulse8
->adap
, status
);
362 static irqreturn_t
pulse8_interrupt(struct serio
*serio
, unsigned char data
,
365 struct pulse8
*pulse8
= serio_get_drvdata(serio
);
366 unsigned long irq_flags
;
369 if (!pulse8
->started
&& data
!= MSGSTART
)
371 if (data
== MSGESC
) {
372 pulse8
->escape
= true;
375 if (pulse8
->escape
) {
377 pulse8
->escape
= false;
378 } else if (data
== MSGEND
) {
379 u8 msgcode
= pulse8
->buf
[0];
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
:
388 * Test if we are receiving a new msg when a previous
389 * message is still pending.
391 if (!(msgcode
& MSGCODE_FRAME_EOM
)) {
392 pulse8
->new_rx_msg_len
= 1;
393 pulse8
->new_rx_msg
[0] = pulse8
->buf
[1];
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
++] =
401 if (!(msgcode
& MSGCODE_FRAME_EOM
))
404 spin_lock_irqsave(&pulse8
->msg_lock
, irq_flags
);
405 idx
= (pulse8
->rx_msg_cur_idx
+ pulse8
->rx_msg_num
) %
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
,
412 spin_unlock_irqrestore(&pulse8
->msg_lock
,
414 pulse8
->new_rx_msg_len
= 0;
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;
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
);
430 case MSGCODE_TRANSMIT_FAILED_ACK
:
432 * A NACK for a broadcast message makes no sense, these
433 * seem to be spurious messages and are skipped.
435 if (pulse8
->tx_msg_is_bcast
)
437 WARN_ON(pulse8
->tx_done_status
);
438 pulse8
->tx_done_status
= CEC_TX_STATUS_NACK
;
439 schedule_work(&pulse8
->irq_work
);
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
);
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;
454 case MSGCODE_COMMAND_ACCEPTED
:
455 case MSGCODE_COMMAND_REJECTED
:
457 if (pulse8
->idx
== 0)
459 memcpy(pulse8
->data
, pulse8
->buf
, pulse8
->idx
);
460 pulse8
->len
= pulse8
->idx
;
461 complete(&pulse8
->cmd_done
);
465 pulse8
->started
= false;
467 } else if (data
== MSGSTART
) {
469 pulse8
->started
= true;
473 if (pulse8
->idx
>= DATA_SIZE
) {
475 "throwing away %d bytes of garbage\n", pulse8
->idx
);
478 pulse8
->buf
[pulse8
->idx
++] = data
;
482 static int pulse8_cec_adap_enable(struct cec_adapter
*adap
, bool enable
)
484 struct pulse8
*pulse8
= cec_get_drvdata(adap
);
488 mutex_lock(&pulse8
->lock
);
489 cmd
[0] = MSGCODE_SET_CONTROLLED
;
491 err
= pulse8_send_and_wait(pulse8
, cmd
, 2,
492 MSGCODE_COMMAND_ACCEPTED
, 1);
494 pulse8
->rx_msg_num
= 0;
495 pulse8
->tx_done_status
= 0;
497 mutex_unlock(&pulse8
->lock
);
498 return enable
? err
: 0;
501 static int pulse8_cec_adap_log_addr(struct cec_adapter
*adap
, u8 log_addr
)
503 struct pulse8
*pulse8
= cec_get_drvdata(adap
);
505 u16 pa
= adap
->phys_addr
;
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
;
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
)
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);
526 pulse8
->autonomous
= cmd
[1];
527 if (log_addr
== CEC_LOG_ADDR_INVALID
)
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);
537 switch (adap
->log_addrs
.primary_device_type
[0]) {
538 case CEC_OP_PRIM_DEVTYPE_TV
:
539 mask
= CEC_LOG_ADDR_MASK_TV
;
541 case CEC_OP_PRIM_DEVTYPE_RECORD
:
542 mask
= CEC_LOG_ADDR_MASK_RECORD
;
544 case CEC_OP_PRIM_DEVTYPE_TUNER
:
545 mask
= CEC_LOG_ADDR_MASK_TUNER
;
547 case CEC_OP_PRIM_DEVTYPE_PLAYBACK
:
548 mask
= CEC_LOG_ADDR_MASK_PLAYBACK
;
550 case CEC_OP_PRIM_DEVTYPE_AUDIOSYSTEM
:
551 mask
= CEC_LOG_ADDR_MASK_AUDIOSYSTEM
;
553 case CEC_OP_PRIM_DEVTYPE_SWITCH
:
554 mask
= CEC_LOG_ADDR_MASK_UNREGISTERED
;
556 case CEC_OP_PRIM_DEVTYPE_PROCESSOR
:
557 mask
= CEC_LOG_ADDR_MASK_SPECIFIC
;
563 cmd
[0] = MSGCODE_SET_LOGICAL_ADDRESS_MASK
;
565 cmd
[2] = mask
& 0xff;
566 err
= pulse8_send_and_wait(pulse8
, cmd
, 3,
567 MSGCODE_COMMAND_ACCEPTED
, 0);
571 cmd
[0] = MSGCODE_SET_DEFAULT_LOGICAL_ADDRESS
;
573 err
= pulse8_send_and_wait(pulse8
, cmd
, 2,
574 MSGCODE_COMMAND_ACCEPTED
, 0);
578 cmd
[0] = MSGCODE_SET_PHYSICAL_ADDRESS
;
581 err
= pulse8_send_and_wait(pulse8
, cmd
, 3,
582 MSGCODE_COMMAND_ACCEPTED
, 0);
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);
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;
599 cmd
[0] = MSGCODE_SET_OSD_NAME
;
600 strscpy(cmd
+ 1, adap
->log_addrs
.osd_name
, sizeof(cmd
) - 1);
602 memset(osd_str
+ osd_len
, ' ', 4 - osd_len
);
604 osd_str
[osd_len
] = '\0';
605 strscpy(adap
->log_addrs
.osd_name
, osd_str
,
606 sizeof(adap
->log_addrs
.osd_name
));
608 err
= pulse8_send_and_wait(pulse8
, cmd
, 1 + osd_len
,
609 MSGCODE_COMMAND_ACCEPTED
, 0);
615 if (pulse8
->restoring_config
)
616 pulse8
->restoring_config
= false;
618 pulse8
->config_pending
= true;
619 mutex_unlock(&pulse8
->lock
);
620 return log_addr
== CEC_LOG_ADDR_INVALID
? 0 : err
;
623 static int pulse8_cec_adap_transmit(struct cec_adapter
*adap
, u8 attempts
,
624 u32 signal_free_time
, struct cec_msg
*msg
)
626 struct pulse8
*pulse8
= cec_get_drvdata(adap
);
628 pulse8
->tx_msg
= *msg
;
630 dev_info(pulse8
->dev
, "adap transmit %*ph\n",
632 pulse8
->tx_signal_free_time
= signal_free_time
;
633 schedule_work(&pulse8
->tx_work
);
637 static void pulse8_cec_adap_free(struct cec_adapter
*adap
)
639 struct pulse8
*pulse8
= cec_get_drvdata(adap
);
641 cancel_delayed_work_sync(&pulse8
->ping_eeprom_work
);
642 cancel_work_sync(&pulse8
->irq_work
);
643 cancel_work_sync(&pulse8
->tx_work
);
647 static 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
,
654 static void pulse8_disconnect(struct serio
*serio
)
656 struct pulse8
*pulse8
= serio_get_drvdata(serio
);
658 cec_unregister_adapter(pulse8
->adap
);
659 serio_set_drvdata(serio
, NULL
);
663 static int pulse8_setup(struct pulse8
*pulse8
, struct serio
*serio
,
664 struct cec_log_addrs
*log_addrs
, u16
*pa
)
666 u8
*data
= pulse8
->data
+ 1;
673 cmd
[0] = MSGCODE_FIRMWARE_VERSION
;
674 err
= pulse8_send_and_wait(pulse8
, cmd
, 1, cmd
[0], 2);
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
;
684 cmd
[0] = MSGCODE_GET_BUILDDATE
;
685 err
= pulse8_send_and_wait(pulse8
, cmd
, 1, cmd
[0], 4);
688 date
= (data
[0] << 24) | (data
[1] << 16) | (data
[2] << 8) | data
[3];
689 dev_info(pulse8
->dev
, "Firmware build date %ptT\n", &date
);
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);
696 pulse8
->autonomous
= data
[0];
697 dev_dbg(pulse8
->dev
, "Autonomous mode: %s",
698 data
[0] ? "on" : "off");
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);
704 dev_dbg(pulse8
->dev
, "Auto Power On: %s",
705 data
[0] ? "on" : "off");
708 cmd
[0] = MSGCODE_GET_DEVICE_TYPE
;
709 err
= pulse8_send_and_wait(pulse8
, cmd
, 1, cmd
[0], 1);
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
;
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
;
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
;
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
;
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
;
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
;
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
;
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]);
751 cmd
[0] = MSGCODE_GET_LOGICAL_ADDRESS_MASK
;
752 err
= pulse8_send_and_wait(pulse8
, cmd
, 1, cmd
[0], 2);
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;
761 cmd
[0] = MSGCODE_GET_PHYSICAL_ADDRESS
;
762 err
= pulse8_send_and_wait(pulse8
, cmd
, 1, cmd
[0], 1);
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
));
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);
775 log_addrs
->cec_version
= data
[0];
776 dev_dbg(pulse8
->dev
, "CEC version: %d\n", log_addrs
->cec_version
);
779 cmd
[0] = MSGCODE_GET_OSD_NAME
;
780 err
= pulse8_send_and_wait(pulse8
, cmd
, 1, cmd
[0], 0);
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
);
789 static int pulse8_apply_persistent_config(struct pulse8
*pulse8
,
790 struct cec_log_addrs
*log_addrs
,
795 err
= cec_s_log_addrs(pulse8
->adap
, log_addrs
, false);
799 cec_s_phys_addr(pulse8
->adap
, pa
, false);
804 static void pulse8_ping_eeprom_work_handler(struct work_struct
*work
)
806 struct pulse8
*pulse8
=
807 container_of(work
, struct pulse8
, ping_eeprom_work
.work
);
810 mutex_lock(&pulse8
->lock
);
812 if (pulse8_send_and_wait(pulse8
, &cmd
, 1,
813 MSGCODE_COMMAND_ACCEPTED
, 0)) {
814 dev_warn(pulse8
->dev
, "failed to ping EEPROM\n");
818 if (pulse8
->vers
< 2)
821 if (pulse8
->config_pending
&& persistent_config
) {
822 dev_dbg(pulse8
->dev
, "writing pending config to EEPROM\n");
823 cmd
= MSGCODE_WRITE_EEPROM
;
824 if (pulse8_send_and_wait(pulse8
, &cmd
, 1,
825 MSGCODE_COMMAND_ACCEPTED
, 0))
826 dev_info(pulse8
->dev
, "failed to write pending config to EEPROM\n");
828 pulse8
->config_pending
= false;
831 schedule_delayed_work(&pulse8
->ping_eeprom_work
, PING_PERIOD
);
832 mutex_unlock(&pulse8
->lock
);
835 static int pulse8_connect(struct serio
*serio
, struct serio_driver
*drv
)
837 u32 caps
= CEC_CAP_DEFAULTS
| CEC_CAP_PHYS_ADDR
| CEC_CAP_MONITOR_ALL
;
838 struct pulse8
*pulse8
;
840 struct cec_log_addrs log_addrs
= {};
841 u16 pa
= CEC_PHYS_ADDR_INVALID
;
843 pulse8
= kzalloc(sizeof(*pulse8
), GFP_KERNEL
);
848 pulse8
->serio
= serio
;
849 pulse8
->adap
= cec_allocate_adapter(&pulse8_cec_adap_ops
, pulse8
,
850 dev_name(&serio
->dev
), caps
, 1);
851 err
= PTR_ERR_OR_ZERO(pulse8
->adap
);
857 pulse8
->dev
= &serio
->dev
;
858 serio_set_drvdata(serio
, pulse8
);
859 INIT_WORK(&pulse8
->irq_work
, pulse8_irq_work_handler
);
860 INIT_WORK(&pulse8
->tx_work
, pulse8_tx_work_handler
);
861 INIT_DELAYED_WORK(&pulse8
->ping_eeprom_work
,
862 pulse8_ping_eeprom_work_handler
);
863 mutex_init(&pulse8
->lock
);
864 spin_lock_init(&pulse8
->msg_lock
);
865 pulse8
->config_pending
= false;
867 err
= serio_open(serio
, drv
);
871 err
= pulse8_setup(pulse8
, serio
, &log_addrs
, &pa
);
875 err
= cec_register_adapter(pulse8
->adap
, &serio
->dev
);
879 pulse8
->dev
= &pulse8
->adap
->devnode
.dev
;
881 if (persistent_config
&& pulse8
->autonomous
) {
882 err
= pulse8_apply_persistent_config(pulse8
, &log_addrs
, pa
);
885 pulse8
->restoring_config
= true;
888 schedule_delayed_work(&pulse8
->ping_eeprom_work
, PING_PERIOD
);
893 pulse8
->serio
= NULL
;
894 serio_set_drvdata(serio
, NULL
);
897 cec_delete_adapter(pulse8
->adap
);
901 static const struct serio_device_id pulse8_serio_ids
[] = {
904 .proto
= SERIO_PULSE8_CEC
,
911 MODULE_DEVICE_TABLE(serio
, pulse8_serio_ids
);
913 static struct serio_driver pulse8_drv
= {
915 .name
= "pulse8-cec",
917 .description
= "Pulse Eight HDMI CEC driver",
918 .id_table
= pulse8_serio_ids
,
919 .interrupt
= pulse8_interrupt
,
920 .connect
= pulse8_connect
,
921 .disconnect
= pulse8_disconnect
,
924 module_serio_driver(pulse8_drv
);