1 #include <minix/blockdriver.h>
2 #include <minix/drivers.h>
5 #include <minix/i2cdriver.h>
13 #define NR_DEVS 1 /* number of devices this driver handles */
14 #define TDA19988_DEV 0 /* index of TDA19988 device */
15 #define EDID_LEN 128 /* length of standard EDID block */
17 /* When passing data over a grant one needs to pass
18 * a buffer to sys_safecopy copybuff is used for that*/
19 #define COPYBUF_SIZE 0x1000 /* 4k buf */
20 static unsigned char copybuf
[COPYBUF_SIZE
];
22 /* The device has two I2C interfaces CEC (0x34) and HDMI (0x70). This driver
23 * needs access to both.
27 * CEC - Register and Bit Definitions
30 #define CEC_STATUS_REG 0xfe
31 #define CEC_STATUS_CONNECTED_MASK 0x02
33 #define CEC_ENABLE_REG 0xff
34 #define CEC_ENABLE_ALL_MASK 0x87
39 * The HDMI part is much bigger than the CEC part. Memory is accessed according
40 * to page and address. Once the page is set, only the address needs to be
41 * sent if accessing memory locations within the same page (you don't need to
42 * send the page number every time).
45 #define HDMI_CTRL_PAGE 0x00
46 #define HDMI_PPL_PAGE 0x02
47 #define HDMI_EDID_PAGE 0x09
48 #define HDMI_INFO_PAGE 0x10
49 #define HDMI_AUDIO_PAGE 0x11
50 #define HDMI_HDCP_OTP_PAGE 0x12
51 #define HDMI_GAMUT_PAGE 0x13
54 * The page select register isn't part of a page. A dummy value of 0xff is
55 * used to signfiy this in the code.
57 #define HDMI_PAGELESS 0xff
60 * Control Page Registers and Bit Definitions
63 #define HDMI_CTRL_REV_LO_REG 0x00
64 #define HDMI_CTRL_REV_HI_REG 0x02
66 #define HDMI_CTRL_RESET_REG 0x0a
67 #define HDMI_CTRL_RESET_DDC_MASK 0x02
69 #define HDMI_CTRL_DDC_CTRL_REG 0x0b
70 #define HDMI_CTRL_DDC_EN_MASK 0x00
72 #define HDMI_CTRL_DDC_CLK_REG 0x0c
73 #define HDMI_CTRL_DDC_CLK_EN_MASK 0x01
75 #define HDMI_CTRL_INTR_CTRL_REG 0x0f
76 #define HDMI_CTRL_INTR_EN_GLO_MASK 0x04
78 #define HDMI_CTRL_INT_REG 0x11
79 #define HDMI_CTRL_INT_EDID_MASK 0x02
82 * EDID Page Registers and Bit Definitions
85 #define HDMI_EDID_DATA_REG 0x00
87 #define HDMI_EDID_DEV_ADDR_REG 0xfb
88 #define HDMI_EDID_DEV_ADDR 0xa0
90 #define HDMI_EDID_OFFSET_REG 0xfc
91 #define HDMI_EDID_OFFSET 0x00
93 #define HDMI_EDID_SEG_PTR_ADDR_REG 0xfc
94 #define HDMI_EDID_SEG_PTR_ADDR 0x00
96 #define HDMI_EDID_SEG_ADDR_REG 0xfe
97 #define HDMI_EDID_SEG_ADDR 0x00
99 #define HDMI_EDID_REQ_REG 0xfa
100 #define HDMI_EDID_REQ_READ_MASK 0x01
105 #define HDMI_HDCP_OTP_DDC_CLK_REG 0x9a
106 #define HDMI_HDCP_OTP_DDC_CLK_MASK 0x27
108 /* this register/mask isn't documented but it has to be cleared/set */
109 #define HDMI_HDCP_OTP_SOME_REG 0x9b
110 #define HDMI_HDCP_OTP_SOME_MASK 0x02
116 #define HDMI_PAGE_SELECT_REG 0xff
122 /* Revision of the TDA19988. */
123 #define HDMI_REV_TDA19988 0x0331
125 /* the bus that this device is on (counting starting at 1) */
126 static uint32_t cec_bus
;
127 static uint32_t hdmi_bus
;
129 /* slave address of the device */
130 static i2c_addr_t cec_address
;
131 static i2c_addr_t hdmi_address
;
133 /* endpoint for the driver for the bus itself. */
134 static endpoint_t cec_bus_endpoint
;
135 static endpoint_t hdmi_bus_endpoint
;
137 /* logging - use with log_warn(), log_info(), log_debug(), log_trace(), etc */
138 static struct log log
= {
140 .log_level
= LEVEL_INFO
,
141 .log_func
= default_log
145 static int is_display_connected(void);
146 static int enable_hdmi_module(void);
149 static int set_page(uint8_t page
);
150 static int hdmi_read(uint8_t page
, uint8_t reg
, uint8_t * val
);
151 static int hdmi_write(uint8_t page
, uint8_t reg
, uint8_t val
);
152 static int hdmi_set(uint8_t page
, uint8_t reg
, uint8_t mask
);
153 static int hdmi_clear(uint8_t page
, uint8_t reg
, uint8_t mask
);
155 static int hdmi_ddc_enable(void);
156 static int hdmi_init(void);
157 static int check_revision(void);
158 static int read_edid(uint8_t * data
, size_t count
);
160 /* libblockdriver callbacks */
161 static int tda19988_blk_open(devminor_t minor
, int access
);
162 static int tda19988_blk_close(devminor_t minor
);
163 static ssize_t
tda19988_blk_transfer(devminor_t minor
, int do_write
, u64_t pos
,
164 endpoint_t endpt
, iovec_t
* iov
, unsigned int count
, int flags
);
165 static int tda19988_blk_ioctl(devminor_t minor
, unsigned long request
,
166 endpoint_t endpt
, cp_grant_id_t grant
, endpoint_t user_endpt
);
167 static struct device
*tda19988_blk_part(devminor_t minor
);
168 static void tda19988_blk_other(message
* m
, int ipc_status
);
170 /* Entry points into the device dependent code of block drivers. */
171 struct blockdriver tda19988_tab
= {
172 .bdr_type
= BLOCKDRIVER_TYPE_OTHER
,
173 .bdr_open
= tda19988_blk_open
,
174 .bdr_close
= tda19988_blk_close
,
175 .bdr_transfer
= tda19988_blk_transfer
,
176 .bdr_ioctl
= tda19988_blk_ioctl
, /* always returns ENOTTY */
177 .bdr_part
= tda19988_blk_part
,
178 .bdr_other
= tda19988_blk_other
/* for notify events from DS */
181 /* counts the number of times a device file is open */
182 static int openct
[NR_DEVS
];
184 /* base and size of each device */
185 static struct device geom
[NR_DEVS
];
188 tda19988_blk_open(devminor_t minor
, int access
)
190 log_trace(&log
, "tda19988_blk_open(%d,%d)\n", minor
, access
);
191 if (tda19988_blk_part(minor
) == NULL
) {
201 tda19988_blk_close(devminor_t minor
)
203 log_trace(&log
, "tda19988_blk_close(%d)\n", minor
);
204 if (tda19988_blk_part(minor
) == NULL
) {
208 if (openct
[minor
] < 1) {
209 log_warn(&log
, "closing unopened device %d\n", minor
);
218 tda19988_blk_transfer(devminor_t minor
, int do_write
, u64_t pos64
,
219 endpoint_t endpt
, iovec_t
* iov
, unsigned int nr_req
, int flags
)
227 log_trace(&log
, "tda19988_blk_transfer()\n");
229 /* Get minor device information. */
230 dv
= tda19988_blk_part(minor
);
235 if (nr_req
> NR_IOREQS
) {
239 dv_size
= dv
->dv_size
;
240 if (pos64
>= dv_size
) {
241 return OK
; /* Beyond EOF */
246 /* How much to transfer and where to / from. */
247 count
= iov
->iov_size
;
248 grant
= (cp_grant_id_t
) iov
->iov_addr
;
251 if (pos64
>= dv_size
) {
255 /* don't go past the end of the device */
256 if (pos64
+ count
> dv_size
) {
257 count
= dv_size
- pos64
;
260 /* don't overflow copybuf */
261 if (count
> COPYBUF_SIZE
) {
262 count
= COPYBUF_SIZE
;
265 log_debug(&log
, "transfering 0x%x bytes\n", count
);
269 log_warn(&log
, "Error: writing to read-only device\n");
274 if (is_display_connected() == 1) {
279 "Failed to enable HDMI module\n");
283 memset(copybuf
, '\0', COPYBUF_SIZE
);
284 r
= read_edid(copybuf
, count
);
287 "read_edid() failed (r=%d)\n", r
);
291 r
= sys_safecopyto(endpt
, grant
, (vir_bytes
)
292 0, (vir_bytes
) copybuf
, count
);
294 log_warn(&log
, "safecopyto failed\n");
298 return iov
->iov_size
;
300 log_warn(&log
, "Display not connected.\n");
312 tda19988_blk_ioctl(devminor_t minor
, unsigned long request
, endpoint_t endpt
,
313 cp_grant_id_t grant
, endpoint_t
UNUSED(user_endpt
))
315 log_trace(&log
, "tda19988_blk_ioctl(%d)\n", minor
);
316 /* no supported ioctls for this device */
320 static struct device
*
321 tda19988_blk_part(devminor_t minor
)
323 log_trace(&log
, "tda19988_blk_part(%d)\n", minor
);
325 if (minor
< 0 || minor
>= NR_DEVS
) {
333 tda19988_blk_other(message
* m
, int ipc_status
)
335 log_trace(&log
, "tda19988_blk_other(0x%x)\n", m
->m_type
);
337 if (is_ipc_notify(ipc_status
)) {
338 if (m
->m_source
== DS_PROC_NR
) {
340 "bus driver changed state, update endpoint\n");
341 i2cdriver_handle_bus_update(&cec_bus_endpoint
, cec_bus
,
343 i2cdriver_handle_bus_update(&hdmi_bus_endpoint
,
344 hdmi_bus
, hdmi_address
);
347 log_warn(&log
, "Invalid message type (0x%x)\n", m
->m_type
);
352 * Check to see if a display is connected.
353 * Returns 1 for yes, 0 for no, -1 for error.
356 is_display_connected(void)
361 r
= i2creg_read8(cec_bus_endpoint
, cec_address
, CEC_STATUS_REG
, &val
);
363 log_warn(&log
, "Reading connection status failed (r=%d)\n", r
);
367 if ((CEC_STATUS_CONNECTED_MASK
& val
) == 0) {
368 log_debug(&log
, "No Display Detected\n");
371 log_debug(&log
, "Display Detected\n");
377 * Enable all the modules and clocks.
380 enable_hdmi_module(void)
384 r
= i2creg_write8(cec_bus_endpoint
, cec_address
, CEC_ENABLE_REG
,
385 CEC_ENABLE_ALL_MASK
);
387 log_warn(&log
, "Writing enable bits failed (r=%d)\n", r
);
391 log_debug(&log
, "HDMI module enabled\n");
397 set_page(uint8_t page
)
400 static int current_page
= HDMI_PAGELESS
;
402 if (page
!= current_page
) {
404 r
= i2creg_write8(hdmi_bus_endpoint
, hdmi_address
,
405 HDMI_PAGE_SELECT_REG
, page
);
417 hdmi_read_block(uint8_t page
, uint8_t reg
, uint8_t * buf
, size_t buflen
)
421 minix_i2c_ioctl_exec_t ioctl_exec
;
423 if (buf
== NULL
|| buflen
> I2C_EXEC_MAX_BUFLEN
) {
425 "Read block called with NULL pointer or invalid buflen.\n");
429 if (page
!= HDMI_PAGELESS
) {
432 log_warn(&log
, "Unable to set page to 0x%x\n", page
);
437 memset(&ioctl_exec
, '\0', sizeof(minix_i2c_ioctl_exec_t
));
440 ioctl_exec
.iie_op
= I2C_OP_READ_WITH_STOP
;
441 ioctl_exec
.iie_addr
= hdmi_address
;
443 /* write the register address */
444 ioctl_exec
.iie_cmd
[0] = reg
;
445 ioctl_exec
.iie_cmdlen
= 1;
448 ioctl_exec
.iie_buflen
= buflen
;
450 r
= i2cdriver_exec(hdmi_bus_endpoint
, &ioctl_exec
);
452 log_warn(&log
, "hdmi_read() failed (r=%d)\n", r
);
456 memcpy(buf
, ioctl_exec
.iie_buf
, buflen
);
458 log_trace(&log
, "Read %d bytes from reg 0x%x in page 0x%x\n", buflen
,
465 hdmi_read(uint8_t page
, uint8_t reg
, uint8_t * val
)
471 log_warn(&log
, "Read called with NULL pointer\n");
475 if (page
!= HDMI_PAGELESS
) {
478 log_warn(&log
, "Unable to set page to 0x%x\n", page
);
483 r
= i2creg_read8(hdmi_bus_endpoint
, hdmi_address
, reg
, val
);
485 log_warn(&log
, "hdmi_read() failed (r=%d)\n", r
);
489 log_trace(&log
, "Read 0x%x from reg 0x%x in page 0x%x\n", *val
, reg
,
496 hdmi_write(uint8_t page
, uint8_t reg
, uint8_t val
)
500 if (page
!= HDMI_PAGELESS
) {
503 log_warn(&log
, "Unable to set page to 0x%x\n", page
);
508 r
= i2creg_write8(hdmi_bus_endpoint
, hdmi_address
, reg
, val
);
510 log_warn(&log
, "hdmi_write() failed (r=%d)\n", r
);
514 log_trace(&log
, "Successfully wrote 0x%x to reg 0x%x in page 0x%x\n",
521 hdmi_set(uint8_t page
, uint8_t reg
, uint8_t mask
)
529 r
= hdmi_read(page
, reg
, &val
);
536 r
= hdmi_write(page
, reg
, val
);
545 hdmi_clear(uint8_t page
, uint8_t reg
, uint8_t mask
)
553 r
= hdmi_read(page
, reg
, &val
);
560 r
= hdmi_write(page
, reg
, val
);
576 r
= hdmi_read(HDMI_CTRL_PAGE
, HDMI_CTRL_REV_LO_REG
, &rev_lo
);
578 log_warn(&log
, "Failed to read rev_lo (r=%d)\n", r
);
582 r
= hdmi_read(HDMI_CTRL_PAGE
, HDMI_CTRL_REV_HI_REG
, &rev_hi
);
584 log_warn(&log
, "Failed to read rev_hi (r=%d)\n", r
);
588 revision
= ((rev_hi
<< 8) | rev_lo
);
589 if (revision
!= HDMI_REV_TDA19988
) {
591 log_warn(&log
, "Unrecognized value in revision registers.\n");
592 log_warn(&log
, "Read: 0x%x | Expected: 0x%x\n", revision
,
597 log_debug(&log
, "Device Revision: 0x%x\n", revision
);
603 hdmi_ddc_enable(void)
607 /* Soft Reset DDC Bus */
608 r
= hdmi_set(HDMI_CTRL_PAGE
, HDMI_CTRL_RESET_REG
,
609 HDMI_CTRL_RESET_DDC_MASK
);
614 r
= hdmi_clear(HDMI_CTRL_PAGE
, HDMI_CTRL_RESET_REG
,
615 HDMI_CTRL_RESET_DDC_MASK
);
622 r
= hdmi_write(HDMI_CTRL_PAGE
, HDMI_CTRL_DDC_CTRL_REG
,
623 HDMI_CTRL_DDC_EN_MASK
);
628 /* Setup the clock (I think) */
629 r
= hdmi_write(HDMI_CTRL_PAGE
, HDMI_CTRL_DDC_CLK_REG
,
630 HDMI_CTRL_DDC_CLK_EN_MASK
);
635 r
= hdmi_write(HDMI_HDCP_OTP_PAGE
, HDMI_HDCP_OTP_DDC_CLK_REG
,
636 HDMI_HDCP_OTP_DDC_CLK_MASK
);
640 log_debug(&log
, "DDC Enabled\n");
650 /* Turn on HDMI module (slave 0x70) */
651 r
= enable_hdmi_module();
653 log_warn(&log
, "HDMI Module Init Failed\n");
657 /* Read chip version to ensure compatibility */
658 r
= check_revision();
660 log_warn(&log
, "Couldn't find expected TDA19988 revision\n");
664 /* Turn on DDC interface between TDA19988 and display */
665 r
= hdmi_ddc_enable();
667 log_warn(&log
, "Failed to enable DDC\n");
675 read_edid(uint8_t * buf
, size_t count
)
683 log_debug(&log
, "Reading edid...\n");
685 if (buf
== NULL
|| count
< EDID_LEN
) {
686 log_warn(&log
, "Expected 128 byte data buffer\n");
690 r
= hdmi_clear(HDMI_HDCP_OTP_PAGE
, HDMI_HDCP_OTP_SOME_REG
,
691 HDMI_HDCP_OTP_SOME_MASK
);
693 log_warn(&log
, "Failed to clear bit in HDCP OTP reg\n");
697 /* Enable EDID Block Read Interrupt */
698 r
= hdmi_set(HDMI_CTRL_PAGE
, HDMI_CTRL_INT_REG
,
699 HDMI_CTRL_INT_EDID_MASK
);
701 log_warn(&log
, "Failed to enable EDID Block Read interrupt\n");
705 /* enable global interrupts */
706 r
= hdmi_write(HDMI_CTRL_PAGE
, HDMI_CTRL_INTR_CTRL_REG
,
707 HDMI_CTRL_INTR_EN_GLO_MASK
);
709 log_warn(&log
, "Failed to enable interrupts\n");
713 /* Set Device Address */
714 r
= hdmi_write(HDMI_EDID_PAGE
, HDMI_EDID_DEV_ADDR_REG
,
717 log_warn(&log
, "Couldn't set device address\n");
722 r
= hdmi_write(HDMI_EDID_PAGE
, HDMI_EDID_OFFSET_REG
, HDMI_EDID_OFFSET
);
724 log_warn(&log
, "Couldn't set offset\n");
728 /* Set Segment Pointer Address */
729 r
= hdmi_write(HDMI_EDID_PAGE
, HDMI_EDID_SEG_PTR_ADDR_REG
,
730 HDMI_EDID_SEG_PTR_ADDR
);
732 log_warn(&log
, "Couldn't set segment pointer address\n");
736 /* Set Segment Address */
737 r
= hdmi_write(HDMI_EDID_PAGE
, HDMI_EDID_SEG_ADDR_REG
,
740 log_warn(&log
, "Couldn't set segment address\n");
745 * Toggle EDID Read Request Bit to request a read.
748 r
= hdmi_write(HDMI_EDID_PAGE
, HDMI_EDID_REQ_REG
,
749 HDMI_EDID_REQ_READ_MASK
);
751 log_warn(&log
, "Couldn't set Read Request bit\n");
755 r
= hdmi_write(HDMI_EDID_PAGE
, HDMI_EDID_REQ_REG
, 0x00);
757 log_warn(&log
, "Couldn't clear Read Request bit\n");
761 log_debug(&log
, "Starting polling\n");
763 /* poll interrupt status flag */
765 for (tries
= 0; tries
< 100; tries
++) {
767 r
= hdmi_read(HDMI_CTRL_PAGE
, HDMI_CTRL_INT_REG
, &val
);
769 log_warn(&log
, "Read failed while polling int flag\n");
773 if (val
& HDMI_CTRL_INT_EDID_MASK
) {
774 log_debug(&log
, "Mask Set\n");
783 log_warn(&log
, "Data Ready interrupt never fired.\n");
787 log_debug(&log
, "Ready to read\n");
789 /* Finally, perform the read. */
790 memset(buf
, '\0', count
);
791 r
= hdmi_read_block(HDMI_EDID_PAGE
, HDMI_EDID_DATA_REG
, buf
, EDID_LEN
);
793 log_warn(&log
, "Failed to read EDID data\n");
797 /* Disable EDID Block Read Interrupt */
798 r
= hdmi_clear(HDMI_CTRL_PAGE
, HDMI_CTRL_INT_REG
,
799 HDMI_CTRL_INT_EDID_MASK
);
802 "Failed to disable EDID Block Read interrupt\n");
806 r
= hdmi_set(HDMI_HDCP_OTP_PAGE
, HDMI_HDCP_OTP_SOME_REG
,
807 HDMI_HDCP_OTP_SOME_MASK
);
809 log_warn(&log
, "Failed to set bit in HDCP/OTP reg\n");
813 log_debug(&log
, "Done EDID Reading\n");
819 sef_cb_lu_state_save(int UNUSED(result
), int UNUSED(flags
))
821 ds_publish_u32("cec_bus", cec_bus
, DSF_OVERWRITE
);
822 ds_publish_u32("hdmi_bus", hdmi_bus
, DSF_OVERWRITE
);
823 ds_publish_u32("cec_address", cec_address
, DSF_OVERWRITE
);
824 ds_publish_u32("hdmi_address", hdmi_address
, DSF_OVERWRITE
);
829 lu_state_restore(void)
831 /* Restore the state. */
834 ds_retrieve_u32("cec_bus", &value
);
835 ds_delete_u32("cec_bus");
836 cec_bus
= (int) value
;
838 ds_retrieve_u32("hdmi_bus", &value
);
839 ds_delete_u32("hdmi_bus");
840 hdmi_bus
= (int) value
;
842 ds_retrieve_u32("cec_address", &value
);
843 ds_delete_u32("cec_address");
844 cec_address
= (int) value
;
846 ds_retrieve_u32("hdmi_address", &value
);
847 ds_delete_u32("hdmi_address");
848 hdmi_address
= (int) value
;
854 sef_cb_init(int type
, sef_init_info_t
* UNUSED(info
))
858 if (type
== SEF_INIT_LU
) {
859 /* Restore the state. */
863 geom
[TDA19988_DEV
].dv_base
= ((u64_t
) (0));
864 geom
[TDA19988_DEV
].dv_size
= ((u64_t
) (128));
870 /* look-up the endpoint for the bus driver */
871 cec_bus_endpoint
= i2cdriver_bus_endpoint(cec_bus
);
872 if (cec_bus_endpoint
== 0) {
873 log_warn(&log
, "Couldn't find bus driver.\n");
877 /* claim the device */
878 r
= i2cdriver_reserve_device(cec_bus_endpoint
, cec_address
);
880 log_warn(&log
, "Couldn't reserve device 0x%x (r=%d)\n",
889 /* look-up the endpoint for the bus driver */
890 hdmi_bus_endpoint
= i2cdriver_bus_endpoint(hdmi_bus
);
891 if (hdmi_bus_endpoint
== 0) {
892 log_warn(&log
, "Couldn't find bus driver.\n");
896 /* claim the device */
897 r
= i2cdriver_reserve_device(hdmi_bus_endpoint
, hdmi_address
);
899 log_warn(&log
, "Couldn't reserve device 0x%x (r=%d)\n",
904 if (type
!= SEF_INIT_LU
) {
906 /* sign up for updates about the i2c bus going down/up */
907 r
= i2cdriver_subscribe_bus_updates(cec_bus
);
909 log_warn(&log
, "Couldn't subscribe to bus updates\n");
913 /* sign up for updates about the i2c bus going down/up */
914 r
= i2cdriver_subscribe_bus_updates(hdmi_bus
);
916 log_warn(&log
, "Couldn't subscribe to bus updates\n");
920 i2cdriver_announce(cec_bus
);
921 if (cec_bus
!= hdmi_bus
) {
922 i2cdriver_announce(hdmi_bus
);
925 blockdriver_announce(type
);
926 log_trace(&log
, "announced\n");
933 sef_local_startup(void)
936 * Register init callbacks. Use the same function for all event types
938 sef_setcb_init_fresh(sef_cb_init
);
939 sef_setcb_init_lu(sef_cb_init
);
940 sef_setcb_init_restart(sef_cb_init
);
943 * Register live update callbacks.
945 sef_setcb_lu_state_save(sef_cb_lu_state_save
);
947 /* Let SEF perform startup. */
956 long int cec_addressl
;
958 long int hdmi_addressl
;
960 r
= env_parse("cec_bus", "d", 0, &cec_busl
, 1, 3);
964 cec_bus
= (uint32_t) cec_busl
;
966 r
= env_parse("cec_address", "x", 0, &cec_addressl
, 0x34, 0x37);
970 cec_address
= (i2c_addr_t
) cec_addressl
;
972 r
= env_parse("hdmi_bus", "d", 0, &hdmi_busl
, 1, 3);
976 hdmi_bus
= (uint32_t) hdmi_busl
;
978 r
= env_parse("hdmi_address", "x", 0, &hdmi_addressl
, 0x70, 0x73);
982 hdmi_address
= (i2c_addr_t
) hdmi_addressl
;
988 main(int argc
, char *argv
[])
992 env_setargs(argc
, argv
);
994 r
= tda19988_env_parse();
997 "Expecting -args 'cec_bus=X cec_address=0xAA hdmi_bus=Y hdmi_address=0xBB'\n");
999 "Example -args 'cec_bus=1 cec_address=0x34 hdmi_bus=1 hdmi_address=0x70'\n");
1000 return EXIT_FAILURE
;
1003 sef_local_startup();
1005 log_debug(&log
, "Startup Complete\n");
1006 blockdriver_task(&tda19988_tab
);
1007 log_debug(&log
, "Shutting down\n");