1 #include <minix/blockdriver.h> 2 #include <minix/drivers.h> 3 #include <minix/ds.h> 4 #include <minix/i2c.h> 5 #include <minix/i2cdriver.h> 6 #include <minix/log.h> 7 8 #include <ctype.h> 9 #include <stdio.h> 10 #include <stdlib.h> 11 12 /* constants */ 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 */ 16 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]; 21 22 /* The device has two I2C interfaces CEC (0x34) and HDMI (0x70). This driver 23 * needs access to both. 24 */ 25 26 /* 27 * CEC - Register and Bit Definitions 28 */ 29 30 #define CEC_STATUS_REG 0xfe 31 #define CEC_STATUS_CONNECTED_MASK 0x02 32 33 #define CEC_ENABLE_REG 0xff 34 #define CEC_ENABLE_ALL_MASK 0x87 35 36 /* 37 * HDMI - Pages 38 * 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). 43 */ 44 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 52 53 /* 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. 56 */ 57 #define HDMI_PAGELESS 0xff 58 59 /* 60 * Control Page Registers and Bit Definitions 61 */ 62 63 #define HDMI_CTRL_REV_LO_REG 0x00 64 #define HDMI_CTRL_REV_HI_REG 0x02 65 66 #define HDMI_CTRL_RESET_REG 0x0a 67 #define HDMI_CTRL_RESET_DDC_MASK 0x02 68 69 #define HDMI_CTRL_DDC_CTRL_REG 0x0b 70 #define HDMI_CTRL_DDC_EN_MASK 0x00 71 72 #define HDMI_CTRL_DDC_CLK_REG 0x0c 73 #define HDMI_CTRL_DDC_CLK_EN_MASK 0x01 74 75 #define HDMI_CTRL_INTR_CTRL_REG 0x0f 76 #define HDMI_CTRL_INTR_EN_GLO_MASK 0x04 77 78 #define HDMI_CTRL_INT_REG 0x11 79 #define HDMI_CTRL_INT_EDID_MASK 0x02 80 81 /* 82 * EDID Page Registers and Bit Definitions 83 */ 84 85 #define HDMI_EDID_DATA_REG 0x00 86 87 #define HDMI_EDID_DEV_ADDR_REG 0xfb 88 #define HDMI_EDID_DEV_ADDR 0xa0 89 90 #define HDMI_EDID_OFFSET_REG 0xfc 91 #define HDMI_EDID_OFFSET 0x00 92 93 #define HDMI_EDID_SEG_PTR_ADDR_REG 0xfc 94 #define HDMI_EDID_SEG_PTR_ADDR 0x00 95 96 #define HDMI_EDID_SEG_ADDR_REG 0xfe 97 #define HDMI_EDID_SEG_ADDR 0x00 98 99 #define HDMI_EDID_REQ_REG 0xfa 100 #define HDMI_EDID_REQ_READ_MASK 0x01 101 102 /* 103 * HDCP and OTP 104 */ 105 #define HDMI_HDCP_OTP_DDC_CLK_REG 0x9a 106 #define HDMI_HDCP_OTP_DDC_CLK_MASK 0x27 107 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 111 112 /* 113 * Pageless Registers 114 */ 115 116 #define HDMI_PAGE_SELECT_REG 0xff 117 118 /* 119 * Constants 120 */ 121 122 /* Revision of the TDA19988. */ 123 #define HDMI_REV_TDA19988 0x0331 124 125 /* the bus that this device is on (counting starting at 1) */ 126 static uint32_t cec_bus; 127 static uint32_t hdmi_bus; 128 129 /* slave address of the device */ 130 static i2c_addr_t cec_address; 131 static i2c_addr_t hdmi_address; 132 133 /* endpoint for the driver for the bus itself. */ 134 static endpoint_t cec_bus_endpoint; 135 static endpoint_t hdmi_bus_endpoint; 136 137 /* logging - use with log_warn(), log_info(), log_debug(), log_trace(), etc */ 138 static struct log log = { 139 .name = "tda19988", 140 .log_level = LEVEL_INFO, 141 .log_func = default_log 142 }; 143 144 static void sef_local_startup(void); 145 static int sef_cb_lu_state_save(int); 146 static int lu_state_restore(void); 147 static int sef_cb_init(int type, sef_init_info_t * info); 148 149 /* CEC Module */ 150 static int is_display_connected(void); 151 static int enable_hdmi_module(void); 152 153 /* HDMI Module */ 154 static int set_page(uint8_t page); 155 static int hdmi_read(uint8_t page, uint8_t reg, uint8_t * val); 156 static int hdmi_write(uint8_t page, uint8_t reg, uint8_t val); 157 static int hdmi_set(uint8_t page, uint8_t reg, uint8_t mask); 158 static int hdmi_clear(uint8_t page, uint8_t reg, uint8_t mask); 159 160 static int hdmi_ddc_enable(void); 161 static int hdmi_init(void); 162 static int check_revision(void); 163 static int read_edid(uint8_t * data, size_t count); 164 165 /* libblockdriver callbacks */ 166 static int tda19988_blk_open(devminor_t minor, int access); 167 static int tda19988_blk_close(devminor_t minor); 168 static ssize_t tda19988_blk_transfer(devminor_t minor, int do_write, u64_t pos, 169 endpoint_t endpt, iovec_t * iov, unsigned int count, int flags); 170 static int tda19988_blk_ioctl(devminor_t minor, unsigned long request, 171 endpoint_t endpt, cp_grant_id_t grant, endpoint_t user_endpt); 172 static struct device *tda19988_blk_part(devminor_t minor); 173 static void tda19988_blk_other(message * m, int ipc_status); 174 175 /* Entry points into the device dependent code of block drivers. */ 176 struct blockdriver tda19988_tab = { 177 .bdr_type = BLOCKDRIVER_TYPE_OTHER, 178 .bdr_open = tda19988_blk_open, 179 .bdr_close = tda19988_blk_close, 180 .bdr_transfer = tda19988_blk_transfer, 181 .bdr_ioctl = tda19988_blk_ioctl, /* always returns ENOTTY */ 182 .bdr_part = tda19988_blk_part, 183 .bdr_other = tda19988_blk_other /* for notify events from DS */ 184 }; 185 186 /* counts the number of times a device file is open */ 187 static int openct[NR_DEVS]; 188 189 /* base and size of each device */ 190 static struct device geom[NR_DEVS]; 191 192 static int 193 tda19988_blk_open(devminor_t minor, int access) 194 { 195 log_trace(&log, "tda19988_blk_open(%d,%d)\n", minor, access); 196 if (tda19988_blk_part(minor) == NULL) { 197 return ENXIO; 198 } 199 200 openct[minor]++; 201 202 return OK; 203 } 204 205 static int 206 tda19988_blk_close(devminor_t minor) 207 { 208 log_trace(&log, "tda19988_blk_close(%d)\n", minor); 209 if (tda19988_blk_part(minor) == NULL) { 210 return ENXIO; 211 } 212 213 if (openct[minor] < 1) { 214 log_warn(&log, "closing unopened device %d\n", minor); 215 return EINVAL; 216 } 217 openct[minor]--; 218 219 return OK; 220 } 221 222 static ssize_t 223 tda19988_blk_transfer(devminor_t minor, int do_write, u64_t pos64, 224 endpoint_t endpt, iovec_t * iov, unsigned int nr_req, int flags) 225 { 226 unsigned count; 227 struct device *dv; 228 u64_t dv_size; 229 int r; 230 cp_grant_id_t grant; 231 232 log_trace(&log, "tda19988_blk_transfer()\n"); 233 234 /* Get minor device information. */ 235 dv = tda19988_blk_part(minor); 236 if (dv == NULL) { 237 return ENXIO; 238 } 239 240 if (nr_req > NR_IOREQS) { 241 return EINVAL; 242 } 243 244 dv_size = dv->dv_size; 245 if (pos64 >= dv_size) { 246 return OK; /* Beyond EOF */ 247 } 248 249 if (nr_req > 0) { 250 251 /* How much to transfer and where to / from. */ 252 count = iov->iov_size; 253 grant = (cp_grant_id_t) iov->iov_addr; 254 255 /* check for EOF */ 256 if (pos64 >= dv_size) { 257 return 0; 258 } 259 260 /* don't go past the end of the device */ 261 if (pos64 + count > dv_size) { 262 count = dv_size - pos64; 263 } 264 265 /* don't overflow copybuf */ 266 if (count > COPYBUF_SIZE) { 267 count = COPYBUF_SIZE; 268 } 269 270 log_debug(&log, "transfering 0x%x bytes\n", count); 271 272 if (do_write) { 273 274 log_warn(&log, "Error: writing to read-only device\n"); 275 return EACCES; 276 277 } else { 278 279 if (is_display_connected() == 1) { 280 281 r = hdmi_init(); 282 if (r != OK) { 283 log_warn(&log, 284 "Failed to enable HDMI module\n"); 285 return EIO; 286 } 287 288 memset(copybuf, '\0', COPYBUF_SIZE); 289 r = read_edid(copybuf, count); 290 if (r != OK) { 291 log_warn(&log, 292 "read_edid() failed (r=%d)\n", r); 293 return r; 294 } 295 296 r = sys_safecopyto(endpt, grant, (vir_bytes) 297 0, (vir_bytes) copybuf, count); 298 if (r != OK) { 299 log_warn(&log, "safecopyto failed\n"); 300 return EINVAL; 301 } 302 303 return iov->iov_size; 304 } else { 305 log_warn(&log, "Display not connected.\n"); 306 return ENODEV; 307 } 308 } 309 } else { 310 311 /* empty request */ 312 return 0; 313 } 314 } 315 316 static int 317 tda19988_blk_ioctl(devminor_t minor, unsigned long request, endpoint_t endpt, 318 cp_grant_id_t grant, endpoint_t UNUSED(user_endpt)) 319 { 320 log_trace(&log, "tda19988_blk_ioctl(%d)\n", minor); 321 /* no supported ioctls for this device */ 322 return ENOTTY; 323 } 324 325 static struct device * 326 tda19988_blk_part(devminor_t minor) 327 { 328 log_trace(&log, "tda19988_blk_part(%d)\n", minor); 329 330 if (minor < 0 || minor >= NR_DEVS) { 331 return NULL; 332 } 333 334 return &geom[minor]; 335 } 336 337 static void 338 tda19988_blk_other(message * m, int ipc_status) 339 { 340 log_trace(&log, "tda19988_blk_other(0x%x)\n", m->m_type); 341 342 if (is_ipc_notify(ipc_status)) { 343 if (m->m_source == DS_PROC_NR) { 344 log_debug(&log, 345 "bus driver changed state, update endpoint\n"); 346 i2cdriver_handle_bus_update(&cec_bus_endpoint, cec_bus, 347 cec_address); 348 i2cdriver_handle_bus_update(&hdmi_bus_endpoint, 349 hdmi_bus, hdmi_address); 350 } 351 } else { 352 log_warn(&log, "Invalid message type (0x%x)\n", m->m_type); 353 } 354 } 355 356 /* 357 * Check to see if a display is connected. 358 * Returns 1 for yes, 0 for no, -1 for error. 359 */ 360 static int 361 is_display_connected(void) 362 { 363 int r; 364 uint8_t val; 365 366 r = i2creg_read8(cec_bus_endpoint, cec_address, CEC_STATUS_REG, &val); 367 if (r != OK) { 368 log_warn(&log, "Reading connection status failed (r=%d)\n", r); 369 return -1; 370 } 371 372 if ((CEC_STATUS_CONNECTED_MASK & val) == 0) { 373 log_debug(&log, "No Display Detected\n"); 374 return 0; 375 } else { 376 log_debug(&log, "Display Detected\n"); 377 return 1; 378 } 379 } 380 381 /* 382 * Enable all the modules and clocks. 383 */ 384 static int 385 enable_hdmi_module(void) 386 { 387 int r; 388 389 r = i2creg_write8(cec_bus_endpoint, cec_address, CEC_ENABLE_REG, 390 CEC_ENABLE_ALL_MASK); 391 if (r != OK) { 392 log_warn(&log, "Writing enable bits failed (r=%d)\n", r); 393 return -1; 394 } 395 396 log_debug(&log, "HDMI module enabled\n"); 397 398 return OK; 399 } 400 401 static int 402 set_page(uint8_t page) 403 { 404 int r; 405 static int current_page = HDMI_PAGELESS; 406 407 if (page != current_page) { 408 409 r = i2creg_write8(hdmi_bus_endpoint, hdmi_address, 410 HDMI_PAGE_SELECT_REG, page); 411 if (r != OK) { 412 return r; 413 } 414 415 current_page = page; 416 } 417 418 return OK; 419 } 420 421 static int 422 hdmi_read_block(uint8_t page, uint8_t reg, uint8_t * buf, size_t buflen) 423 { 424 425 int r; 426 minix_i2c_ioctl_exec_t ioctl_exec; 427 428 if (buf == NULL || buflen > I2C_EXEC_MAX_BUFLEN) { 429 log_warn(&log, 430 "Read block called with NULL pointer or invalid buflen.\n"); 431 return EINVAL; 432 } 433 434 if (page != HDMI_PAGELESS) { 435 r = set_page(page); 436 if (r != OK) { 437 log_warn(&log, "Unable to set page to 0x%x\n", page); 438 return r; 439 } 440 } 441 442 memset(&ioctl_exec, '\0', sizeof(minix_i2c_ioctl_exec_t)); 443 444 /* Read from HDMI */ 445 ioctl_exec.iie_op = I2C_OP_READ_WITH_STOP; 446 ioctl_exec.iie_addr = hdmi_address; 447 448 /* write the register address */ 449 ioctl_exec.iie_cmd[0] = reg; 450 ioctl_exec.iie_cmdlen = 1; 451 452 /* read bytes */ 453 ioctl_exec.iie_buflen = buflen; 454 455 r = i2cdriver_exec(hdmi_bus_endpoint, &ioctl_exec); 456 if (r != OK) { 457 log_warn(&log, "hdmi_read() failed (r=%d)\n", r); 458 return -1; 459 } 460 461 memcpy(buf, ioctl_exec.iie_buf, buflen); 462 463 log_trace(&log, "Read %d bytes from reg 0x%x in page 0x%x\n", buflen, 464 reg, page); 465 466 return OK; 467 } 468 469 static int 470 hdmi_read(uint8_t page, uint8_t reg, uint8_t * val) 471 { 472 473 int r; 474 475 if (val == NULL) { 476 log_warn(&log, "Read called with NULL pointer\n"); 477 return EINVAL; 478 } 479 480 if (page != HDMI_PAGELESS) { 481 r = set_page(page); 482 if (r != OK) { 483 log_warn(&log, "Unable to set page to 0x%x\n", page); 484 return r; 485 } 486 } 487 488 r = i2creg_read8(hdmi_bus_endpoint, hdmi_address, reg, val); 489 if (r != OK) { 490 log_warn(&log, "hdmi_read() failed (r=%d)\n", r); 491 return -1; 492 } 493 494 log_trace(&log, "Read 0x%x from reg 0x%x in page 0x%x\n", *val, reg, 495 page); 496 497 return OK; 498 } 499 500 static int 501 hdmi_write(uint8_t page, uint8_t reg, uint8_t val) 502 { 503 int r; 504 505 if (page != HDMI_PAGELESS) { 506 r = set_page(page); 507 if (r != OK) { 508 log_warn(&log, "Unable to set page to 0x%x\n", page); 509 return r; 510 } 511 } 512 513 r = i2creg_write8(hdmi_bus_endpoint, hdmi_address, reg, val); 514 if (r != OK) { 515 log_warn(&log, "hdmi_write() failed (r=%d)\n", r); 516 return -1; 517 } 518 519 log_trace(&log, "Successfully wrote 0x%x to reg 0x%x in page 0x%x\n", 520 val, reg, page); 521 522 return OK; 523 } 524 525 static int 526 hdmi_set(uint8_t page, uint8_t reg, uint8_t mask) 527 { 528 529 int r; 530 uint8_t val; 531 532 val = 0x00; 533 534 r = hdmi_read(page, reg, &val); 535 if (r != OK) { 536 return r; 537 } 538 539 val |= mask; 540 541 r = hdmi_write(page, reg, val); 542 if (r != OK) { 543 return r; 544 } 545 546 return OK; 547 } 548 549 static int 550 hdmi_clear(uint8_t page, uint8_t reg, uint8_t mask) 551 { 552 553 int r; 554 uint8_t val; 555 556 val = 0x00; 557 558 r = hdmi_read(page, reg, &val); 559 if (r != OK) { 560 return r; 561 } 562 563 val &= ~mask; 564 565 r = hdmi_write(page, reg, val); 566 if (r != OK) { 567 return r; 568 } 569 570 return OK; 571 } 572 573 static int 574 check_revision(void) 575 { 576 int r; 577 uint8_t rev_lo; 578 uint8_t rev_hi; 579 uint16_t revision; 580 581 r = hdmi_read(HDMI_CTRL_PAGE, HDMI_CTRL_REV_LO_REG, &rev_lo); 582 if (r != OK) { 583 log_warn(&log, "Failed to read rev_lo (r=%d)\n", r); 584 return -1; 585 } 586 587 r = hdmi_read(HDMI_CTRL_PAGE, HDMI_CTRL_REV_HI_REG, &rev_hi); 588 if (r != OK) { 589 log_warn(&log, "Failed to read rev_hi (r=%d)\n", r); 590 return -1; 591 } 592 593 revision = ((rev_hi << 8) | rev_lo); 594 if (revision != HDMI_REV_TDA19988) { 595 596 log_warn(&log, "Unrecognized value in revision registers.\n"); 597 log_warn(&log, "Read: 0x%x | Expected: 0x%x\n", revision, 598 HDMI_REV_TDA19988); 599 return -1; 600 } 601 602 log_debug(&log, "Device Revision: 0x%x\n", revision); 603 604 return OK; 605 } 606 607 static int 608 hdmi_ddc_enable(void) 609 { 610 int r; 611 612 /* Soft Reset DDC Bus */ 613 r = hdmi_set(HDMI_CTRL_PAGE, HDMI_CTRL_RESET_REG, 614 HDMI_CTRL_RESET_DDC_MASK); 615 if (r != OK) { 616 return r; 617 } 618 micro_delay(100000); 619 r = hdmi_clear(HDMI_CTRL_PAGE, HDMI_CTRL_RESET_REG, 620 HDMI_CTRL_RESET_DDC_MASK); 621 if (r != OK) { 622 return r; 623 } 624 micro_delay(100000); 625 626 /* Enable DDC */ 627 r = hdmi_write(HDMI_CTRL_PAGE, HDMI_CTRL_DDC_CTRL_REG, 628 HDMI_CTRL_DDC_EN_MASK); 629 if (r != OK) { 630 return r; 631 } 632 633 /* Setup the clock (I think) */ 634 r = hdmi_write(HDMI_CTRL_PAGE, HDMI_CTRL_DDC_CLK_REG, 635 HDMI_CTRL_DDC_CLK_EN_MASK); 636 if (r != OK) { 637 return r; 638 } 639 640 r = hdmi_write(HDMI_HDCP_OTP_PAGE, HDMI_HDCP_OTP_DDC_CLK_REG, 641 HDMI_HDCP_OTP_DDC_CLK_MASK); 642 if (r != OK) { 643 return r; 644 } 645 log_debug(&log, "DDC Enabled\n"); 646 647 return OK; 648 } 649 650 static int 651 hdmi_init(void) 652 { 653 int r; 654 655 /* Turn on HDMI module (slave 0x70) */ 656 r = enable_hdmi_module(); 657 if (r != OK) { 658 log_warn(&log, "HDMI Module Init Failed\n"); 659 return -1; 660 } 661 662 /* Read chip version to ensure compatibility */ 663 r = check_revision(); 664 if (r != OK) { 665 log_warn(&log, "Couldn't find expected TDA19988 revision\n"); 666 return -1; 667 } 668 669 /* Turn on DDC interface between TDA19988 and display */ 670 r = hdmi_ddc_enable(); 671 if (r != OK) { 672 log_warn(&log, "Failed to enable DDC\n"); 673 return -1; 674 } 675 676 return OK; 677 } 678 679 static int 680 read_edid(uint8_t * buf, size_t count) 681 { 682 int r; 683 int i, j; 684 int tries; 685 int edid_ready; 686 uint8_t val; 687 688 log_debug(&log, "Reading edid...\n"); 689 690 if (buf == NULL || count < EDID_LEN) { 691 log_warn(&log, "Expected 128 byte data buffer\n"); 692 return -1; 693 } 694 695 r = hdmi_clear(HDMI_HDCP_OTP_PAGE, HDMI_HDCP_OTP_SOME_REG, 696 HDMI_HDCP_OTP_SOME_MASK); 697 if (r != OK) { 698 log_warn(&log, "Failed to clear bit in HDCP OTP reg\n"); 699 return -1; 700 } 701 702 /* Enable EDID Block Read Interrupt */ 703 r = hdmi_set(HDMI_CTRL_PAGE, HDMI_CTRL_INT_REG, 704 HDMI_CTRL_INT_EDID_MASK); 705 if (r != OK) { 706 log_warn(&log, "Failed to enable EDID Block Read interrupt\n"); 707 return -1; 708 } 709 710 /* enable global interrupts */ 711 r = hdmi_write(HDMI_CTRL_PAGE, HDMI_CTRL_INTR_CTRL_REG, 712 HDMI_CTRL_INTR_EN_GLO_MASK); 713 if (r != OK) { 714 log_warn(&log, "Failed to enable interrupts\n"); 715 return -1; 716 } 717 718 /* Set Device Address */ 719 r = hdmi_write(HDMI_EDID_PAGE, HDMI_EDID_DEV_ADDR_REG, 720 HDMI_EDID_DEV_ADDR); 721 if (r != OK) { 722 log_warn(&log, "Couldn't set device address\n"); 723 return -1; 724 } 725 726 /* Set Offset */ 727 r = hdmi_write(HDMI_EDID_PAGE, HDMI_EDID_OFFSET_REG, HDMI_EDID_OFFSET); 728 if (r != OK) { 729 log_warn(&log, "Couldn't set offset\n"); 730 return -1; 731 } 732 733 /* Set Segment Pointer Address */ 734 r = hdmi_write(HDMI_EDID_PAGE, HDMI_EDID_SEG_PTR_ADDR_REG, 735 HDMI_EDID_SEG_PTR_ADDR); 736 if (r != OK) { 737 log_warn(&log, "Couldn't set segment pointer address\n"); 738 return -1; 739 } 740 741 /* Set Segment Address */ 742 r = hdmi_write(HDMI_EDID_PAGE, HDMI_EDID_SEG_ADDR_REG, 743 HDMI_EDID_SEG_ADDR); 744 if (r != OK) { 745 log_warn(&log, "Couldn't set segment address\n"); 746 return -1; 747 } 748 749 /* 750 * Toggle EDID Read Request Bit to request a read. 751 */ 752 753 r = hdmi_write(HDMI_EDID_PAGE, HDMI_EDID_REQ_REG, 754 HDMI_EDID_REQ_READ_MASK); 755 if (r != OK) { 756 log_warn(&log, "Couldn't set Read Request bit\n"); 757 return -1; 758 } 759 760 r = hdmi_write(HDMI_EDID_PAGE, HDMI_EDID_REQ_REG, 0x00); 761 if (r != OK) { 762 log_warn(&log, "Couldn't clear Read Request bit\n"); 763 return -1; 764 } 765 766 log_debug(&log, "Starting polling\n"); 767 768 /* poll interrupt status flag */ 769 edid_ready = 0; 770 for (tries = 0; tries < 100; tries++) { 771 772 r = hdmi_read(HDMI_CTRL_PAGE, HDMI_CTRL_INT_REG, &val); 773 if (r != OK) { 774 log_warn(&log, "Read failed while polling int flag\n"); 775 return -1; 776 } 777 778 if (val & HDMI_CTRL_INT_EDID_MASK) { 779 log_debug(&log, "Mask Set\n"); 780 edid_ready = 1; 781 break; 782 } 783 784 micro_delay(1000); 785 } 786 787 if (!edid_ready) { 788 log_warn(&log, "Data Ready interrupt never fired.\n"); 789 return EBUSY; 790 } 791 792 log_debug(&log, "Ready to read\n"); 793 794 /* Finally, perform the read. */ 795 memset(buf, '\0', count); 796 r = hdmi_read_block(HDMI_EDID_PAGE, HDMI_EDID_DATA_REG, buf, EDID_LEN); 797 if (r != OK) { 798 log_warn(&log, "Failed to read EDID data\n"); 799 return -1; 800 } 801 802 /* Disable EDID Block Read Interrupt */ 803 r = hdmi_clear(HDMI_CTRL_PAGE, HDMI_CTRL_INT_REG, 804 HDMI_CTRL_INT_EDID_MASK); 805 if (r != OK) { 806 log_warn(&log, 807 "Failed to disable EDID Block Read interrupt\n"); 808 return -1; 809 } 810 811 r = hdmi_set(HDMI_HDCP_OTP_PAGE, HDMI_HDCP_OTP_SOME_REG, 812 HDMI_HDCP_OTP_SOME_MASK); 813 if (r != OK) { 814 log_warn(&log, "Failed to set bit in HDCP/OTP reg\n"); 815 return -1; 816 } 817 818 log_debug(&log, "Done EDID Reading\n"); 819 820 return OK; 821 } 822 823 static int 824 sef_cb_lu_state_save(int UNUSED(state)) 825 { 826 ds_publish_u32("cec_bus", cec_bus, DSF_OVERWRITE); 827 ds_publish_u32("hdmi_bus", hdmi_bus, DSF_OVERWRITE); 828 ds_publish_u32("cec_address", cec_address, DSF_OVERWRITE); 829 ds_publish_u32("hdmi_address", hdmi_address, DSF_OVERWRITE); 830 return OK; 831 } 832 833 static int 834 lu_state_restore(void) 835 { 836 /* Restore the state. */ 837 u32_t value; 838 839 ds_retrieve_u32("cec_bus", &value); 840 ds_delete_u32("cec_bus"); 841 cec_bus = (int) value; 842 843 ds_retrieve_u32("hdmi_bus", &value); 844 ds_delete_u32("hdmi_bus"); 845 hdmi_bus = (int) value; 846 847 ds_retrieve_u32("cec_address", &value); 848 ds_delete_u32("cec_address"); 849 cec_address = (int) value; 850 851 ds_retrieve_u32("hdmi_address", &value); 852 ds_delete_u32("hdmi_address"); 853 hdmi_address = (int) value; 854 855 return OK; 856 } 857 858 static int 859 sef_cb_init(int type, sef_init_info_t * UNUSED(info)) 860 { 861 int r; 862 863 if (type == SEF_INIT_LU) { 864 /* Restore the state. */ 865 lu_state_restore(); 866 } 867 868 geom[TDA19988_DEV].dv_base = ((u64_t) (0)); 869 geom[TDA19988_DEV].dv_size = ((u64_t) (128)); 870 871 /* 872 * CEC Module 873 */ 874 875 /* look-up the endpoint for the bus driver */ 876 cec_bus_endpoint = i2cdriver_bus_endpoint(cec_bus); 877 if (cec_bus_endpoint == 0) { 878 log_warn(&log, "Couldn't find bus driver.\n"); 879 return EXIT_FAILURE; 880 } 881 882 /* claim the device */ 883 r = i2cdriver_reserve_device(cec_bus_endpoint, cec_address); 884 if (r != OK) { 885 log_warn(&log, "Couldn't reserve device 0x%x (r=%d)\n", 886 cec_address, r); 887 return EXIT_FAILURE; 888 } 889 890 /* 891 * HDMI Module 892 */ 893 894 /* look-up the endpoint for the bus driver */ 895 hdmi_bus_endpoint = i2cdriver_bus_endpoint(hdmi_bus); 896 if (hdmi_bus_endpoint == 0) { 897 log_warn(&log, "Couldn't find bus driver.\n"); 898 return EXIT_FAILURE; 899 } 900 901 /* claim the device */ 902 r = i2cdriver_reserve_device(hdmi_bus_endpoint, hdmi_address); 903 if (r != OK) { 904 log_warn(&log, "Couldn't reserve device 0x%x (r=%d)\n", 905 hdmi_address, r); 906 return EXIT_FAILURE; 907 } 908 909 if (type != SEF_INIT_LU) { 910 911 /* sign up for updates about the i2c bus going down/up */ 912 r = i2cdriver_subscribe_bus_updates(cec_bus); 913 if (r != OK) { 914 log_warn(&log, "Couldn't subscribe to bus updates\n"); 915 return EXIT_FAILURE; 916 } 917 918 /* sign up for updates about the i2c bus going down/up */ 919 r = i2cdriver_subscribe_bus_updates(hdmi_bus); 920 if (r != OK) { 921 log_warn(&log, "Couldn't subscribe to bus updates\n"); 922 return EXIT_FAILURE; 923 } 924 925 i2cdriver_announce(cec_bus); 926 if (cec_bus != hdmi_bus) { 927 i2cdriver_announce(hdmi_bus); 928 } 929 930 blockdriver_announce(type); 931 log_trace(&log, "announced\n"); 932 } 933 934 return OK; 935 } 936 937 static void 938 sef_local_startup(void) 939 { 940 /* 941 * Register init callbacks. Use the same function for all event types 942 */ 943 sef_setcb_init_fresh(sef_cb_init); 944 sef_setcb_init_lu(sef_cb_init); 945 sef_setcb_init_restart(sef_cb_init); 946 947 /* 948 * Register live update callbacks. 949 */ 950 /* Agree to update immediately when LU is requested in a valid state. */ 951 sef_setcb_lu_prepare(sef_cb_lu_prepare_always_ready); 952 /* Support live update starting from any standard state. */ 953 sef_setcb_lu_state_isvalid(sef_cb_lu_state_isvalid_standard); 954 /* Register a custom routine to save the state. */ 955 sef_setcb_lu_state_save(sef_cb_lu_state_save); 956 957 /* Let SEF perform startup. */ 958 sef_startup(); 959 } 960 961 static int 962 tda19988_env_parse() 963 { 964 int r; 965 long int cec_busl; 966 long int cec_addressl; 967 long int hdmi_busl; 968 long int hdmi_addressl; 969 970 r = env_parse("cec_bus", "d", 0, &cec_busl, 1, 3); 971 if (r != EP_SET) { 972 return -1; 973 } 974 cec_bus = (uint32_t) cec_busl; 975 976 r = env_parse("cec_address", "x", 0, &cec_addressl, 0x34, 0x37); 977 if (r != EP_SET) { 978 return -1; 979 } 980 cec_address = (i2c_addr_t) cec_addressl; 981 982 r = env_parse("hdmi_bus", "d", 0, &hdmi_busl, 1, 3); 983 if (r != EP_SET) { 984 return -1; 985 } 986 hdmi_bus = (uint32_t) hdmi_busl; 987 988 r = env_parse("hdmi_address", "x", 0, &hdmi_addressl, 0x70, 0x73); 989 if (r != EP_SET) { 990 return -1; 991 } 992 hdmi_address = (i2c_addr_t) hdmi_addressl; 993 994 return OK; 995 } 996 997 int 998 main(int argc, char *argv[]) 999 { 1000 int r; 1001 1002 env_setargs(argc, argv); 1003 1004 r = tda19988_env_parse(); 1005 if (r < 0) { 1006 log_warn(&log, 1007 "Expecting -args 'cec_bus=X cec_address=0xAA hdmi_bus=Y hdmi_address=0xBB'\n"); 1008 log_warn(&log, 1009 "Example -args 'cec_bus=1 cec_address=0x34 hdmi_bus=1 hdmi_address=0x70'\n"); 1010 return EXIT_FAILURE; 1011 } 1012 1013 sef_local_startup(); 1014 1015 log_debug(&log, "Startup Complete\n"); 1016 blockdriver_task(&tda19988_tab); 1017 log_debug(&log, "Shutting down\n"); 1018 1019 return OK; 1020 } 1021