.. | .. |
---|
49 | 49 | #define DDC_SEGMENT_ADDR 0x30 |
---|
50 | 50 | |
---|
51 | 51 | #define HDMI_EDID_LEN 512 |
---|
| 52 | +#define HDMI_EDID_BLOCK_LEN 128 |
---|
52 | 53 | |
---|
53 | 54 | /* DW-HDMI Controller >= 0x200a are at least compliant with SCDC version 1 */ |
---|
54 | 55 | #define SCDC_MIN_SOURCE_VERSION 0x1 |
---|
.. | .. |
---|
320 | 321 | struct drm_display_mode previous_mode; |
---|
321 | 322 | |
---|
322 | 323 | struct i2c_adapter *ddc; |
---|
| 324 | + struct cec_adapter *cec_adap; |
---|
323 | 325 | void __iomem *regs; |
---|
324 | 326 | bool sink_is_hdmi; |
---|
325 | 327 | bool sink_has_audio; |
---|
.. | .. |
---|
358 | 360 | struct cec_notifier *cec_notifier; |
---|
359 | 361 | |
---|
360 | 362 | bool initialized; /* hdmi is enabled before bind */ |
---|
| 363 | + bool logo_plug_out; /* hdmi is plug out when kernel logo */ |
---|
361 | 364 | hdmi_codec_plugged_cb plugged_cb; |
---|
362 | 365 | struct device *codec_dev; |
---|
363 | 366 | enum drm_connector_status last_connector_result; |
---|
364 | 367 | bool rgb_quant_range_selectable; |
---|
| 368 | + bool update; |
---|
| 369 | + bool hdr2sdr; /* from hdr to sdr */ |
---|
365 | 370 | }; |
---|
366 | 371 | |
---|
367 | 372 | #define HDMI_IH_PHY_STAT0_RX_SENSE \ |
---|
.. | .. |
---|
456 | 461 | change = drm_helper_hpd_irq_event(hdmi->bridge.dev); |
---|
457 | 462 | |
---|
458 | 463 | #ifdef CONFIG_CEC_NOTIFIER |
---|
459 | | - if (change) |
---|
| 464 | + if (change) { |
---|
460 | 465 | cec_notifier_repo_cec_hpd(hdmi->cec_notifier, |
---|
461 | 466 | hdmi->hpd_state, |
---|
462 | 467 | ktime_get()); |
---|
| 468 | + } |
---|
463 | 469 | #endif |
---|
464 | 470 | } |
---|
465 | 471 | } |
---|
.. | .. |
---|
568 | 574 | unsigned char *buf, unsigned int length) |
---|
569 | 575 | { |
---|
570 | 576 | struct dw_hdmi_i2c *i2c = hdmi->i2c; |
---|
571 | | - int stat; |
---|
| 577 | + int stat, retry, i; |
---|
| 578 | + bool read_edid = false; |
---|
572 | 579 | |
---|
573 | 580 | if (!i2c->is_regaddr) { |
---|
574 | 581 | dev_dbg(hdmi->dev, "set read register address to 0\n"); |
---|
.. | .. |
---|
576 | 583 | i2c->is_regaddr = true; |
---|
577 | 584 | } |
---|
578 | 585 | |
---|
579 | | - while (length--) { |
---|
580 | | - reinit_completion(&i2c->cmp); |
---|
| 586 | + /* edid reads are in 128 bytes. scdc reads are in 1 byte */ |
---|
| 587 | + if (length == HDMI_EDID_BLOCK_LEN) |
---|
| 588 | + read_edid = true; |
---|
581 | 589 | |
---|
582 | | - hdmi_writeb(hdmi, i2c->slave_reg++, HDMI_I2CM_ADDRESS); |
---|
583 | | - if (i2c->is_segment) |
---|
584 | | - hdmi_writeb(hdmi, HDMI_I2CM_OPERATION_READ_EXT, |
---|
585 | | - HDMI_I2CM_OPERATION); |
---|
586 | | - else |
---|
587 | | - hdmi_writeb(hdmi, HDMI_I2CM_OPERATION_READ, |
---|
588 | | - HDMI_I2CM_OPERATION); |
---|
| 590 | + while (length > 0) { |
---|
| 591 | + retry = 100; |
---|
| 592 | + hdmi_writeb(hdmi, i2c->slave_reg, HDMI_I2CM_ADDRESS); |
---|
589 | 593 | |
---|
590 | | - stat = wait_for_completion_timeout(&i2c->cmp, HZ / 10); |
---|
591 | | - if (!stat) |
---|
592 | | - return -EAGAIN; |
---|
| 594 | + if (read_edid) { |
---|
| 595 | + i2c->slave_reg += 8; |
---|
| 596 | + length -= 8; |
---|
| 597 | + } else { |
---|
| 598 | + i2c->slave_reg++; |
---|
| 599 | + length--; |
---|
| 600 | + } |
---|
593 | 601 | |
---|
594 | | - /* Check for error condition on the bus */ |
---|
595 | | - if (i2c->stat & HDMI_IH_I2CM_STAT0_ERROR) |
---|
| 602 | + while (retry > 0) { |
---|
| 603 | + if (!(hdmi_readb(hdmi, HDMI_PHY_STAT0) & HDMI_PHY_HPD)) { |
---|
| 604 | + void *data = hdmi->plat_data->phy_data; |
---|
| 605 | + |
---|
| 606 | + dev_dbg(hdmi->dev, "hdmi disconnect, stop ddc read\n"); |
---|
| 607 | + if (hdmi->plat_data->set_ddc_io) |
---|
| 608 | + hdmi->plat_data->set_ddc_io(data, false); |
---|
| 609 | + return -EPERM; |
---|
| 610 | + } |
---|
| 611 | + reinit_completion(&i2c->cmp); |
---|
| 612 | + if (i2c->is_segment) { |
---|
| 613 | + if (read_edid) |
---|
| 614 | + hdmi_writeb(hdmi, HDMI_I2CM_OPERATION_READ8_EXT, |
---|
| 615 | + HDMI_I2CM_OPERATION); |
---|
| 616 | + else |
---|
| 617 | + hdmi_writeb(hdmi, HDMI_I2CM_OPERATION_READ_EXT, |
---|
| 618 | + HDMI_I2CM_OPERATION); |
---|
| 619 | + } else { |
---|
| 620 | + if (read_edid) |
---|
| 621 | + hdmi_writeb(hdmi, HDMI_I2CM_OPERATION_READ8, |
---|
| 622 | + HDMI_I2CM_OPERATION); |
---|
| 623 | + else |
---|
| 624 | + hdmi_writeb(hdmi, HDMI_I2CM_OPERATION_READ, |
---|
| 625 | + HDMI_I2CM_OPERATION); |
---|
| 626 | + } |
---|
| 627 | + stat = wait_for_completion_timeout(&i2c->cmp, HZ / 10); |
---|
| 628 | + if (!stat) { |
---|
| 629 | + dev_dbg(hdmi->dev, "ddc read time out\n"); |
---|
| 630 | + hdmi_writeb(hdmi, 0, HDMI_I2CM_SOFTRSTZ); |
---|
| 631 | + hdmi_writeb(hdmi, HDMI_I2CM_OPERATION_BUS_CLEAR, |
---|
| 632 | + HDMI_I2CM_OPERATION); |
---|
| 633 | + retry -= 10; |
---|
| 634 | + continue; |
---|
| 635 | + } |
---|
| 636 | + /* Check for error condition on the bus */ |
---|
| 637 | + if (i2c->stat & HDMI_IH_I2CM_STAT0_ERROR) { |
---|
| 638 | + dev_dbg(hdmi->dev, "ddc read err\n"); |
---|
| 639 | + hdmi_writeb(hdmi, 0, HDMI_I2CM_SOFTRSTZ); |
---|
| 640 | + hdmi_writeb(hdmi, HDMI_I2CM_OPERATION_BUS_CLEAR, |
---|
| 641 | + HDMI_I2CM_OPERATION); |
---|
| 642 | + retry--; |
---|
| 643 | + usleep_range(10000, 11000); |
---|
| 644 | + continue; |
---|
| 645 | + } |
---|
| 646 | + /* read success */ |
---|
| 647 | + break; |
---|
| 648 | + } |
---|
| 649 | + if (retry <= 0) { |
---|
| 650 | + dev_err(hdmi->dev, "ddc read failed\n"); |
---|
596 | 651 | return -EIO; |
---|
| 652 | + } |
---|
597 | 653 | |
---|
598 | | - *buf++ = hdmi_readb(hdmi, HDMI_I2CM_DATAI); |
---|
| 654 | + if (read_edid) |
---|
| 655 | + for (i = 0; i < 8; i++) |
---|
| 656 | + *buf++ = hdmi_readb(hdmi, HDMI_I2CM_READ_BUFF0 + i); |
---|
| 657 | + else |
---|
| 658 | + *buf++ = hdmi_readb(hdmi, HDMI_I2CM_DATAI); |
---|
599 | 659 | } |
---|
| 660 | + |
---|
600 | 661 | i2c->is_segment = false; |
---|
601 | 662 | |
---|
602 | 663 | return 0; |
---|
.. | .. |
---|
606 | 667 | unsigned char *buf, unsigned int length) |
---|
607 | 668 | { |
---|
608 | 669 | struct dw_hdmi_i2c *i2c = hdmi->i2c; |
---|
609 | | - int stat; |
---|
| 670 | + int stat, retry; |
---|
610 | 671 | |
---|
611 | 672 | if (!i2c->is_regaddr) { |
---|
612 | 673 | /* Use the first write byte as register address */ |
---|
.. | .. |
---|
617 | 678 | } |
---|
618 | 679 | |
---|
619 | 680 | while (length--) { |
---|
620 | | - reinit_completion(&i2c->cmp); |
---|
| 681 | + retry = 100; |
---|
621 | 682 | |
---|
622 | 683 | hdmi_writeb(hdmi, *buf++, HDMI_I2CM_DATAO); |
---|
623 | 684 | hdmi_writeb(hdmi, i2c->slave_reg++, HDMI_I2CM_ADDRESS); |
---|
624 | | - hdmi_writeb(hdmi, HDMI_I2CM_OPERATION_WRITE, |
---|
625 | | - HDMI_I2CM_OPERATION); |
---|
626 | 685 | |
---|
627 | | - stat = wait_for_completion_timeout(&i2c->cmp, HZ / 10); |
---|
628 | | - if (!stat) |
---|
629 | | - return -EAGAIN; |
---|
| 686 | + while (retry > 0) { |
---|
| 687 | + if (!(hdmi_readb(hdmi, HDMI_PHY_STAT0) & HDMI_PHY_HPD)) { |
---|
| 688 | + void *data = hdmi->plat_data->phy_data; |
---|
630 | 689 | |
---|
631 | | - /* Check for error condition on the bus */ |
---|
632 | | - if (i2c->stat & HDMI_IH_I2CM_STAT0_ERROR) |
---|
| 690 | + dev_dbg(hdmi->dev, "hdmi disconnect, stop ddc write\n"); |
---|
| 691 | + if (hdmi->plat_data->set_ddc_io) |
---|
| 692 | + hdmi->plat_data->set_ddc_io(data, false); |
---|
| 693 | + return -EPERM; |
---|
| 694 | + } |
---|
| 695 | + reinit_completion(&i2c->cmp); |
---|
| 696 | + hdmi_writeb(hdmi, HDMI_I2CM_OPERATION_WRITE, |
---|
| 697 | + HDMI_I2CM_OPERATION); |
---|
| 698 | + |
---|
| 699 | + stat = wait_for_completion_timeout(&i2c->cmp, HZ / 10); |
---|
| 700 | + if (!stat) { |
---|
| 701 | + dev_dbg(hdmi->dev, "ddc write time out\n"); |
---|
| 702 | + hdmi_writeb(hdmi, 0, HDMI_I2CM_SOFTRSTZ); |
---|
| 703 | + hdmi_writeb(hdmi, HDMI_I2CM_OPERATION_BUS_CLEAR, |
---|
| 704 | + HDMI_I2CM_OPERATION); |
---|
| 705 | + retry -= 10; |
---|
| 706 | + continue; |
---|
| 707 | + } |
---|
| 708 | + |
---|
| 709 | + /* Check for error condition on the bus */ |
---|
| 710 | + if (i2c->stat & HDMI_IH_I2CM_STAT0_ERROR) { |
---|
| 711 | + dev_dbg(hdmi->dev, "ddc write err\n"); |
---|
| 712 | + hdmi_writeb(hdmi, 0, HDMI_I2CM_SOFTRSTZ); |
---|
| 713 | + hdmi_writeb(hdmi, HDMI_I2CM_OPERATION_BUS_CLEAR, |
---|
| 714 | + HDMI_I2CM_OPERATION); |
---|
| 715 | + retry--; |
---|
| 716 | + usleep_range(10000, 11000); |
---|
| 717 | + continue; |
---|
| 718 | + } |
---|
| 719 | + |
---|
| 720 | + /* write success */ |
---|
| 721 | + break; |
---|
| 722 | + } |
---|
| 723 | + |
---|
| 724 | + if (retry <= 0) { |
---|
| 725 | + dev_err(hdmi->dev, "ddc write failed\n"); |
---|
633 | 726 | return -EIO; |
---|
| 727 | + } |
---|
634 | 728 | } |
---|
635 | 729 | |
---|
636 | 730 | return 0; |
---|
.. | .. |
---|
642 | 736 | struct dw_hdmi *hdmi = i2c_get_adapdata(adap); |
---|
643 | 737 | struct dw_hdmi_i2c *i2c = hdmi->i2c; |
---|
644 | 738 | u8 addr = msgs[0].addr; |
---|
| 739 | + void *data = hdmi->plat_data->phy_data; |
---|
645 | 740 | int i, ret = 0; |
---|
646 | 741 | |
---|
647 | 742 | if (addr == DDC_CI_ADDR) |
---|
.. | .. |
---|
665 | 760 | } |
---|
666 | 761 | |
---|
667 | 762 | mutex_lock(&i2c->lock); |
---|
| 763 | + |
---|
| 764 | + if (hdmi->plat_data->set_ddc_io) |
---|
| 765 | + hdmi->plat_data->set_ddc_io(data, true); |
---|
| 766 | + |
---|
| 767 | + hdmi_writeb(hdmi, 0, HDMI_I2CM_SOFTRSTZ); |
---|
| 768 | + udelay(100); |
---|
668 | 769 | |
---|
669 | 770 | /* Unmute DONE and ERROR interrupts */ |
---|
670 | 771 | hdmi_writeb(hdmi, 0x00, HDMI_IH_MUTE_I2CM_STAT0); |
---|
.. | .. |
---|
1378 | 1479 | HDMI_VP_CONF_PR_EN_MASK | |
---|
1379 | 1480 | HDMI_VP_CONF_BYPASS_SELECT_MASK, HDMI_VP_CONF); |
---|
1380 | 1481 | |
---|
1381 | | - if ((color_depth == 5 && hdmi->previous_mode.htotal % 4) || |
---|
1382 | | - (color_depth == 6 && hdmi->previous_mode.htotal % 2)) |
---|
1383 | | - hdmi_modb(hdmi, 0, HDMI_VP_STUFF_IDEFAULT_PHASE_MASK, |
---|
1384 | | - HDMI_VP_STUFF); |
---|
1385 | | - else |
---|
1386 | | - hdmi_modb(hdmi, 1 << HDMI_VP_STUFF_IDEFAULT_PHASE_OFFSET, |
---|
1387 | | - HDMI_VP_STUFF_IDEFAULT_PHASE_MASK, HDMI_VP_STUFF); |
---|
1388 | | - |
---|
| 1482 | + hdmi_modb(hdmi, 0, HDMI_VP_STUFF_IDEFAULT_PHASE_MASK, HDMI_VP_STUFF); |
---|
1389 | 1483 | hdmi_writeb(hdmi, remap_size, HDMI_VP_REMAP); |
---|
1390 | 1484 | |
---|
1391 | 1485 | if (output_select == HDMI_VP_CONF_OUTPUT_SELECTOR_PP) { |
---|
.. | .. |
---|
1943 | 2037 | HDMI_EXTENDED_COLORIMETRY_XV_YCC_601; |
---|
1944 | 2038 | break; |
---|
1945 | 2039 | } |
---|
| 2040 | + frame.ycc_quantization_range = HDMI_YCC_QUANTIZATION_RANGE_LIMITED; |
---|
1946 | 2041 | } else { |
---|
1947 | | - frame.colorimetry = HDMI_COLORIMETRY_NONE; |
---|
1948 | | - frame.extended_colorimetry = |
---|
1949 | | - HDMI_EXTENDED_COLORIMETRY_XV_YCC_601; |
---|
| 2042 | + if (hdmi->hdmi_data.enc_out_encoding == V4L2_YCBCR_ENC_BT2020) { |
---|
| 2043 | + frame.colorimetry = HDMI_COLORIMETRY_EXTENDED; |
---|
| 2044 | + frame.extended_colorimetry = |
---|
| 2045 | + HDMI_EXTENDED_COLORIMETRY_BT2020; |
---|
| 2046 | + } else { |
---|
| 2047 | + frame.colorimetry = HDMI_COLORIMETRY_NONE; |
---|
| 2048 | + frame.extended_colorimetry = |
---|
| 2049 | + HDMI_EXTENDED_COLORIMETRY_XV_YCC_601; |
---|
| 2050 | + } |
---|
| 2051 | + |
---|
| 2052 | + if (is_hdmi2 && frame.quantization_range == HDMI_QUANTIZATION_RANGE_FULL) |
---|
| 2053 | + frame.ycc_quantization_range = HDMI_YCC_QUANTIZATION_RANGE_FULL; |
---|
| 2054 | + else |
---|
| 2055 | + frame.ycc_quantization_range = HDMI_YCC_QUANTIZATION_RANGE_LIMITED; |
---|
1950 | 2056 | } |
---|
1951 | 2057 | |
---|
1952 | 2058 | frame.scan_mode = HDMI_SCAN_MODE_NONE; |
---|
.. | .. |
---|
1986 | 2092 | hdmi_writeb(hdmi, val, HDMI_FC_AVICONF2); |
---|
1987 | 2093 | |
---|
1988 | 2094 | /* AVI data byte 4 differences: none */ |
---|
1989 | | - val = frame.video_code & 0x7f; |
---|
| 2095 | + if (hdmi_bus_fmt_is_yuv420(hdmi->hdmi_data.enc_out_bus_format) || |
---|
| 2096 | + hdmi->connector.display_info.hdmi.scdc.supported) |
---|
| 2097 | + val = hdmi->vic; |
---|
| 2098 | + else |
---|
| 2099 | + val = frame.video_code & 0x7f; |
---|
1990 | 2100 | hdmi_writeb(hdmi, val, HDMI_FC_AVIVID); |
---|
1991 | 2101 | |
---|
1992 | 2102 | /* AVI Data Byte 5- set up input and output pixel repetition */ |
---|
.. | .. |
---|
2023 | 2133 | struct hdmi_vendor_infoframe frame; |
---|
2024 | 2134 | u8 buffer[10]; |
---|
2025 | 2135 | ssize_t err; |
---|
| 2136 | + |
---|
| 2137 | + /* if sink support hdmi2.0, don't send vsi */ |
---|
| 2138 | + if (hdmi_bus_fmt_is_yuv420(hdmi->hdmi_data.enc_out_bus_format) || |
---|
| 2139 | + hdmi->connector.display_info.hdmi.scdc.supported) { |
---|
| 2140 | + hdmi_mask_writeb(hdmi, 0, HDMI_FC_DATAUTO0, HDMI_FC_DATAUTO0_VSD_OFFSET, |
---|
| 2141 | + HDMI_FC_DATAUTO0_VSD_MASK); |
---|
| 2142 | + return; |
---|
| 2143 | + } |
---|
2026 | 2144 | |
---|
2027 | 2145 | err = drm_hdmi_vendor_infoframe_from_display_mode(&frame, |
---|
2028 | 2146 | &hdmi->connector, |
---|
.. | .. |
---|
2188 | 2306 | hdmi_writeb(hdmi, HDR_LSB(frame.max_fall), HDMI_FC_DRM_PB24); |
---|
2189 | 2307 | hdmi_writeb(hdmi, HDR_MSB(frame.max_fall), HDMI_FC_DRM_PB25); |
---|
2190 | 2308 | hdmi_writeb(hdmi, 1, HDMI_FC_DRM_UP); |
---|
| 2309 | + /* |
---|
| 2310 | + * avi and hdr infoframe cannot be sent at the same time |
---|
| 2311 | + * for compatibility with Huawei TV |
---|
| 2312 | + */ |
---|
| 2313 | + msleep(300); |
---|
2191 | 2314 | hdmi_modb(hdmi, HDMI_FC_PACKET_DRM_TX_EN, |
---|
2192 | 2315 | HDMI_FC_PACKET_DRM_TX_EN_MASK, HDMI_FC_PACKET_TX_EN); |
---|
2193 | 2316 | |
---|
.. | .. |
---|
2215 | 2338 | vmode->mtmdsclock = hdmi_get_tmdsclock(hdmi, vmode->mpixelclock); |
---|
2216 | 2339 | if (hdmi_bus_fmt_is_yuv420(hdmi->hdmi_data.enc_out_bus_format)) |
---|
2217 | 2340 | vmode->mtmdsclock /= 2; |
---|
| 2341 | + |
---|
| 2342 | + if (hdmi->update) |
---|
| 2343 | + return; |
---|
2218 | 2344 | |
---|
2219 | 2345 | /* Set up HDMI_FC_INVIDCONF |
---|
2220 | 2346 | * Some display equipments require that the interval |
---|
.. | .. |
---|
2373 | 2499 | hdmi_writeb(hdmi, 0x21, HDMI_FC_CH2PREAM); |
---|
2374 | 2500 | |
---|
2375 | 2501 | /* Enable pixel clock and tmds data path */ |
---|
2376 | | - hdmi->mc_clkdis |= HDMI_MC_CLKDIS_HDCPCLK_DISABLE | |
---|
2377 | | - HDMI_MC_CLKDIS_CSCCLK_DISABLE | |
---|
2378 | | - HDMI_MC_CLKDIS_AUDCLK_DISABLE | |
---|
2379 | | - HDMI_MC_CLKDIS_PREPCLK_DISABLE | |
---|
2380 | | - HDMI_MC_CLKDIS_TMDSCLK_DISABLE; |
---|
| 2502 | + |
---|
| 2503 | + if (!hdmi->update) |
---|
| 2504 | + hdmi->mc_clkdis |= HDMI_MC_CLKDIS_HDCPCLK_DISABLE | |
---|
| 2505 | + HDMI_MC_CLKDIS_CSCCLK_DISABLE | |
---|
| 2506 | + HDMI_MC_CLKDIS_AUDCLK_DISABLE | |
---|
| 2507 | + HDMI_MC_CLKDIS_PREPCLK_DISABLE | |
---|
| 2508 | + HDMI_MC_CLKDIS_TMDSCLK_DISABLE; |
---|
2381 | 2509 | hdmi->mc_clkdis &= ~HDMI_MC_CLKDIS_PIXELCLK_DISABLE; |
---|
2382 | 2510 | hdmi_writeb(hdmi, hdmi->mc_clkdis, HDMI_MC_CLKDIS); |
---|
2383 | 2511 | |
---|
.. | .. |
---|
2455 | 2583 | HDMI_IH_MUTE_FC_STAT2); |
---|
2456 | 2584 | } |
---|
2457 | 2585 | |
---|
| 2586 | +static void dw_hdmi_force_output_pattern(struct dw_hdmi *hdmi, struct drm_display_mode *mode) |
---|
| 2587 | +{ |
---|
| 2588 | + /* force output black */ |
---|
| 2589 | + if (hdmi_bus_fmt_is_rgb(hdmi->hdmi_data.enc_out_bus_format)) { |
---|
| 2590 | + enum hdmi_quantization_range rgb_quant_range = drm_default_rgb_quant_range(mode); |
---|
| 2591 | + |
---|
| 2592 | + if (hdmi->hdmi_data.quant_range == HDMI_QUANTIZATION_RANGE_FULL) { |
---|
| 2593 | + hdmi_writeb(hdmi, 0x00, HDMI_FC_DBGTMDS2); /*R*/ |
---|
| 2594 | + hdmi_writeb(hdmi, 0x00, HDMI_FC_DBGTMDS1); /*G*/ |
---|
| 2595 | + hdmi_writeb(hdmi, 0x00, HDMI_FC_DBGTMDS0); /*B*/ |
---|
| 2596 | + } else if (hdmi->hdmi_data.quant_range == HDMI_QUANTIZATION_RANGE_LIMITED) { |
---|
| 2597 | + hdmi_writeb(hdmi, 0x10, HDMI_FC_DBGTMDS2); /*R*/ |
---|
| 2598 | + hdmi_writeb(hdmi, 0x10, HDMI_FC_DBGTMDS1); /*G*/ |
---|
| 2599 | + hdmi_writeb(hdmi, 0x10, HDMI_FC_DBGTMDS0); /*B*/ |
---|
| 2600 | + } else if (hdmi->hdmi_data.quant_range == HDMI_QUANTIZATION_RANGE_DEFAULT) { |
---|
| 2601 | + if (rgb_quant_range == HDMI_QUANTIZATION_RANGE_FULL) { |
---|
| 2602 | + hdmi_writeb(hdmi, 0x00, HDMI_FC_DBGTMDS2); /*R*/ |
---|
| 2603 | + hdmi_writeb(hdmi, 0x00, HDMI_FC_DBGTMDS1); /*G*/ |
---|
| 2604 | + hdmi_writeb(hdmi, 0x00, HDMI_FC_DBGTMDS0); /*B*/ |
---|
| 2605 | + } else if (rgb_quant_range == HDMI_QUANTIZATION_RANGE_LIMITED) { |
---|
| 2606 | + hdmi_writeb(hdmi, 0x10, HDMI_FC_DBGTMDS2); /*R*/ |
---|
| 2607 | + hdmi_writeb(hdmi, 0x10, HDMI_FC_DBGTMDS1); /*G*/ |
---|
| 2608 | + hdmi_writeb(hdmi, 0x10, HDMI_FC_DBGTMDS0); /*B*/ |
---|
| 2609 | + } |
---|
| 2610 | + } |
---|
| 2611 | + } else { |
---|
| 2612 | + hdmi_writeb(hdmi, 0x80, HDMI_FC_DBGTMDS2); /*Cr*/ |
---|
| 2613 | + hdmi_writeb(hdmi, 0x10, HDMI_FC_DBGTMDS1); /*Y*/ |
---|
| 2614 | + hdmi_writeb(hdmi, 0x80, HDMI_FC_DBGTMDS0); /*Cb*/ |
---|
| 2615 | + } |
---|
| 2616 | +} |
---|
| 2617 | + |
---|
2458 | 2618 | static int dw_hdmi_setup(struct dw_hdmi *hdmi, struct drm_display_mode *mode) |
---|
2459 | 2619 | { |
---|
2460 | 2620 | int ret; |
---|
2461 | 2621 | void *data = hdmi->plat_data->phy_data; |
---|
2462 | | - bool need_delay = false; |
---|
2463 | 2622 | |
---|
2464 | 2623 | hdmi_disable_overflow_interrupts(hdmi); |
---|
2465 | 2624 | |
---|
.. | .. |
---|
2508 | 2667 | hdmi->hdmi_data.enc_out_bus_format = |
---|
2509 | 2668 | MEDIA_BUS_FMT_RGB888_1X24; |
---|
2510 | 2669 | |
---|
| 2670 | + if (hdmi->plat_data->set_prev_bus_format) |
---|
| 2671 | + hdmi->plat_data->set_prev_bus_format(data, hdmi->hdmi_data.enc_out_bus_format); |
---|
| 2672 | + |
---|
2511 | 2673 | /* TOFIX: Get input encoding from plat data or fallback to none */ |
---|
2512 | 2674 | if (hdmi->plat_data->get_enc_in_encoding) |
---|
2513 | 2675 | hdmi->hdmi_data.enc_in_encoding = |
---|
.. | .. |
---|
2537 | 2699 | (mode->flags & DRM_MODE_FLAG_DBLCLK) ? 1 : 0; |
---|
2538 | 2700 | hdmi->hdmi_data.video_mode.mdataenablepolarity = true; |
---|
2539 | 2701 | |
---|
| 2702 | + dw_hdmi_force_output_pattern(hdmi, mode); |
---|
| 2703 | + |
---|
2540 | 2704 | /* HDMI Initialization Step B.1 */ |
---|
2541 | 2705 | hdmi_av_composer(hdmi, mode); |
---|
2542 | 2706 | |
---|
2543 | | - /* HDMI Initializateion Step B.2 */ |
---|
2544 | | - if (!hdmi->phy.enabled || |
---|
2545 | | - hdmi->hdmi_data.video_mode.previous_pixelclock != |
---|
2546 | | - hdmi->hdmi_data.video_mode.mpixelclock || |
---|
2547 | | - hdmi->hdmi_data.video_mode.previous_tmdsclock != |
---|
2548 | | - hdmi->hdmi_data.video_mode.mtmdsclock) { |
---|
2549 | | - ret = hdmi->phy.ops->init(hdmi, hdmi->phy.data, |
---|
2550 | | - &hdmi->previous_mode); |
---|
2551 | | - if (ret) |
---|
2552 | | - return ret; |
---|
2553 | | - hdmi->phy.enabled = true; |
---|
2554 | | - } else { |
---|
2555 | | - need_delay = true; |
---|
2556 | | - } |
---|
2557 | 2707 | /* HDMI Initialization Step B.3 */ |
---|
2558 | 2708 | dw_hdmi_enable_video_path(hdmi); |
---|
2559 | 2709 | |
---|
.. | .. |
---|
2582 | 2732 | hdmi_video_sample(hdmi); |
---|
2583 | 2733 | hdmi_tx_hdcp_config(hdmi, mode); |
---|
2584 | 2734 | |
---|
| 2735 | + /* HDMI Enable phy output */ |
---|
| 2736 | + if (!hdmi->phy.enabled || |
---|
| 2737 | + hdmi->hdmi_data.video_mode.previous_pixelclock != |
---|
| 2738 | + hdmi->hdmi_data.video_mode.mpixelclock || |
---|
| 2739 | + hdmi->hdmi_data.video_mode.previous_tmdsclock != |
---|
| 2740 | + hdmi->hdmi_data.video_mode.mtmdsclock) { |
---|
| 2741 | + ret = hdmi->phy.ops->init(hdmi, hdmi->phy.data, |
---|
| 2742 | + &hdmi->previous_mode); |
---|
| 2743 | + if (ret) |
---|
| 2744 | + return ret; |
---|
| 2745 | + hdmi->phy.enabled = true; |
---|
| 2746 | + } |
---|
| 2747 | + |
---|
2585 | 2748 | dw_hdmi_clear_overflow(hdmi); |
---|
2586 | 2749 | |
---|
2587 | | - /* XXX: Add delay to make csc work before unmute video. */ |
---|
2588 | | - if (need_delay) |
---|
| 2750 | + /* |
---|
| 2751 | + * konka tv should switch pattern after set to yuv420 10bit or |
---|
| 2752 | + * the TV might not recognize the signal. |
---|
| 2753 | + */ |
---|
| 2754 | + if (!hdmi->update) { |
---|
| 2755 | + hdmi_writeb(hdmi, 1, HDMI_FC_DBGFORCE); |
---|
2589 | 2756 | msleep(50); |
---|
| 2757 | + hdmi_writeb(hdmi, 0, HDMI_FC_DBGFORCE); |
---|
| 2758 | + } |
---|
| 2759 | + |
---|
2590 | 2760 | return 0; |
---|
2591 | 2761 | } |
---|
2592 | 2762 | |
---|
.. | .. |
---|
2686 | 2856 | if (hdmi->initialized) { |
---|
2687 | 2857 | hdmi->initialized = false; |
---|
2688 | 2858 | hdmi->disabled = true; |
---|
| 2859 | + hdmi->logo_plug_out = true; |
---|
2689 | 2860 | } |
---|
2690 | 2861 | if (hdmi->bridge_is_on) |
---|
2691 | 2862 | dw_hdmi_poweroff(hdmi); |
---|
.. | .. |
---|
2793 | 2964 | |
---|
2794 | 2965 | edid = drm_get_edid(connector, hdmi->ddc); |
---|
2795 | 2966 | if (edid) { |
---|
| 2967 | + int vic = 0; |
---|
| 2968 | + |
---|
2796 | 2969 | dev_dbg(hdmi->dev, "got edid: width[%d] x height[%d]\n", |
---|
2797 | 2970 | edid->width_cm, edid->height_cm); |
---|
2798 | 2971 | |
---|
.. | .. |
---|
2802 | 2975 | drm_connector_update_edid_property(connector, edid); |
---|
2803 | 2976 | cec_notifier_set_phys_addr_from_edid(hdmi->cec_notifier, edid); |
---|
2804 | 2977 | ret = drm_add_edid_modes(connector, edid); |
---|
2805 | | - dw_hdmi_update_hdr_property(connector); |
---|
| 2978 | + |
---|
| 2979 | + list_for_each_entry(mode, &connector->probed_modes, head) { |
---|
| 2980 | + vic = drm_match_cea_mode(mode); |
---|
| 2981 | + |
---|
| 2982 | + if (mode->picture_aspect_ratio == HDMI_PICTURE_ASPECT_NONE) { |
---|
| 2983 | + if (vic >= 93 && vic <= 95) |
---|
| 2984 | + mode->picture_aspect_ratio = HDMI_PICTURE_ASPECT_16_9; |
---|
| 2985 | + else if (vic == 98) |
---|
| 2986 | + mode->picture_aspect_ratio = HDMI_PICTURE_ASPECT_256_135; |
---|
| 2987 | + } |
---|
| 2988 | + } |
---|
| 2989 | + |
---|
2806 | 2990 | kfree(edid); |
---|
2807 | 2991 | } else { |
---|
2808 | 2992 | hdmi->support_hdmi = true; |
---|
.. | .. |
---|
2815 | 2999 | |
---|
2816 | 3000 | mode = drm_mode_duplicate(connector->dev, ptr); |
---|
2817 | 3001 | if (mode) { |
---|
2818 | | - if (!i) { |
---|
| 3002 | + if (!i) |
---|
2819 | 3003 | mode->type = DRM_MODE_TYPE_PREFERRED; |
---|
2820 | | - mode->picture_aspect_ratio = |
---|
2821 | | - HDMI_PICTURE_ASPECT_NONE; |
---|
2822 | | - } |
---|
2823 | 3004 | drm_mode_probed_add(connector, mode); |
---|
2824 | 3005 | ret++; |
---|
2825 | 3006 | } |
---|
.. | .. |
---|
2830 | 3011 | |
---|
2831 | 3012 | dev_info(hdmi->dev, "failed to get edid\n"); |
---|
2832 | 3013 | } |
---|
| 3014 | + dw_hdmi_update_hdr_property(connector); |
---|
2833 | 3015 | dw_hdmi_check_output_type_changed(hdmi); |
---|
2834 | 3016 | |
---|
2835 | 3017 | return ret; |
---|
.. | .. |
---|
2892 | 3074 | return ret; |
---|
2893 | 3075 | } |
---|
2894 | 3076 | |
---|
2895 | | -static bool hdr_metadata_equal(const struct drm_connector_state *old_state, |
---|
| 3077 | +static bool hdr_metadata_equal(struct dw_hdmi *hdmi, const struct drm_connector_state *old_state, |
---|
2896 | 3078 | const struct drm_connector_state *new_state) |
---|
2897 | 3079 | { |
---|
2898 | 3080 | struct drm_property_blob *old_blob = old_state->hdr_output_metadata; |
---|
2899 | 3081 | struct drm_property_blob *new_blob = new_state->hdr_output_metadata; |
---|
| 3082 | + int i, ret; |
---|
| 3083 | + u8 *data; |
---|
2900 | 3084 | |
---|
2901 | | - if (!old_blob || !new_blob) |
---|
2902 | | - return old_blob == new_blob; |
---|
| 3085 | + hdmi->hdr2sdr = false; |
---|
| 3086 | + |
---|
| 3087 | + if (!old_blob && !new_blob) |
---|
| 3088 | + return true; |
---|
| 3089 | + |
---|
| 3090 | + if (!old_blob) { |
---|
| 3091 | + data = (u8 *)new_blob->data; |
---|
| 3092 | + |
---|
| 3093 | + for (i = 0; i < new_blob->length; i++) |
---|
| 3094 | + if (data[i]) |
---|
| 3095 | + return false; |
---|
| 3096 | + |
---|
| 3097 | + return true; |
---|
| 3098 | + } |
---|
| 3099 | + |
---|
| 3100 | + if (!new_blob) { |
---|
| 3101 | + data = (u8 *)old_blob->data; |
---|
| 3102 | + |
---|
| 3103 | + for (i = 0; i < old_blob->length; i++) |
---|
| 3104 | + if (data[i]) |
---|
| 3105 | + return false; |
---|
| 3106 | + |
---|
| 3107 | + return true; |
---|
| 3108 | + } |
---|
2903 | 3109 | |
---|
2904 | 3110 | if (old_blob->length != new_blob->length) |
---|
2905 | 3111 | return false; |
---|
2906 | 3112 | |
---|
2907 | | - return !memcmp(old_blob->data, new_blob->data, old_blob->length); |
---|
| 3113 | + ret = !memcmp(old_blob->data, new_blob->data, old_blob->length); |
---|
| 3114 | + |
---|
| 3115 | + if (!ret && new_blob) { |
---|
| 3116 | + data = (u8 *)new_blob->data; |
---|
| 3117 | + |
---|
| 3118 | + for (i = 0; i < new_blob->length; i++) |
---|
| 3119 | + if (data[i]) |
---|
| 3120 | + break; |
---|
| 3121 | + |
---|
| 3122 | + if (i == new_blob->length) |
---|
| 3123 | + hdmi->hdr2sdr = true; |
---|
| 3124 | + } |
---|
| 3125 | + |
---|
| 3126 | + return ret; |
---|
| 3127 | +} |
---|
| 3128 | + |
---|
| 3129 | +static bool check_hdr_color_change(struct drm_connector_state *old_state, |
---|
| 3130 | + struct drm_connector_state *new_state, |
---|
| 3131 | + struct dw_hdmi *hdmi) |
---|
| 3132 | +{ |
---|
| 3133 | + void *data = hdmi->plat_data->phy_data; |
---|
| 3134 | + |
---|
| 3135 | + if (!hdr_metadata_equal(hdmi, old_state, new_state)) { |
---|
| 3136 | + hdmi->plat_data->check_hdr_color_change(new_state, data); |
---|
| 3137 | + return true; |
---|
| 3138 | + } |
---|
| 3139 | + |
---|
| 3140 | + return false; |
---|
| 3141 | +} |
---|
| 3142 | + |
---|
| 3143 | +static bool check_hdmi_format_change(struct drm_connector_state *old_state, |
---|
| 3144 | + struct drm_connector_state *new_state, |
---|
| 3145 | + struct drm_connector *connector, |
---|
| 3146 | + struct dw_hdmi *hdmi) |
---|
| 3147 | +{ |
---|
| 3148 | + bool hdr_change, color_change; |
---|
| 3149 | + |
---|
| 3150 | + hdr_change = check_hdr_color_change(old_state, new_state, hdmi); |
---|
| 3151 | + color_change = dw_hdmi_color_changed(connector); |
---|
| 3152 | + |
---|
| 3153 | + if (hdr_change || color_change) |
---|
| 3154 | + return true; |
---|
| 3155 | + |
---|
| 3156 | + return false; |
---|
2908 | 3157 | } |
---|
2909 | 3158 | |
---|
2910 | 3159 | static int dw_hdmi_connector_atomic_check(struct drm_connector *connector, |
---|
.. | .. |
---|
2925 | 3174 | if (!crtc) |
---|
2926 | 3175 | return 0; |
---|
2927 | 3176 | |
---|
| 3177 | + crtc_state = drm_atomic_get_crtc_state(state, crtc); |
---|
| 3178 | + if (IS_ERR(crtc_state)) |
---|
| 3179 | + return PTR_ERR(crtc_state); |
---|
| 3180 | + |
---|
| 3181 | + mode = &crtc_state->mode; |
---|
| 3182 | + |
---|
2928 | 3183 | /* |
---|
2929 | 3184 | * If HDMI is enabled in uboot, it's need to record |
---|
2930 | 3185 | * drm_display_mode and set phy status to enabled. |
---|
2931 | 3186 | */ |
---|
2932 | 3187 | if (!vmode->mpixelclock) { |
---|
2933 | | - crtc_state = drm_atomic_get_crtc_state(state, crtc); |
---|
| 3188 | + u8 val; |
---|
| 3189 | + |
---|
2934 | 3190 | if (hdmi->plat_data->get_enc_in_encoding) |
---|
2935 | 3191 | hdmi->hdmi_data.enc_in_encoding = |
---|
2936 | 3192 | hdmi->plat_data->get_enc_in_encoding(data); |
---|
.. | .. |
---|
2944 | 3200 | hdmi->hdmi_data.enc_out_bus_format = |
---|
2945 | 3201 | hdmi->plat_data->get_output_bus_format(data); |
---|
2946 | 3202 | |
---|
2947 | | - mode = &crtc_state->mode; |
---|
2948 | 3203 | memcpy(&hdmi->previous_mode, mode, sizeof(hdmi->previous_mode)); |
---|
2949 | 3204 | vmode->mpixelclock = mode->crtc_clock * 1000; |
---|
2950 | | - vmode->previous_pixelclock = mode->clock; |
---|
2951 | | - vmode->previous_tmdsclock = mode->clock; |
---|
| 3205 | + vmode->previous_pixelclock = mode->clock * 1000; |
---|
| 3206 | + vmode->previous_tmdsclock = mode->clock * 1000; |
---|
2952 | 3207 | vmode->mtmdsclock = hdmi_get_tmdsclock(hdmi, |
---|
2953 | 3208 | vmode->mpixelclock); |
---|
2954 | 3209 | if (hdmi_bus_fmt_is_yuv420(hdmi->hdmi_data.enc_out_bus_format)) |
---|
2955 | 3210 | vmode->mtmdsclock /= 2; |
---|
| 3211 | + |
---|
| 3212 | + dw_hdmi_force_output_pattern(hdmi, mode); |
---|
| 3213 | + |
---|
| 3214 | + hdmi_clk_regenerator_update_pixel_clock(hdmi); |
---|
| 3215 | + hdmi_enable_audio_clk(hdmi, hdmi->audio_enable); |
---|
| 3216 | + |
---|
| 3217 | + drm_scdc_readb(hdmi->ddc, SCDC_TMDS_CONFIG, &val); |
---|
| 3218 | + |
---|
| 3219 | + /* if plug out before hdmi bind, reset hdmi */ |
---|
| 3220 | + if (vmode->mtmdsclock >= 340000000 && !(val & SCDC_TMDS_BIT_CLOCK_RATIO_BY_40)) |
---|
| 3221 | + hdmi->logo_plug_out = true; |
---|
2956 | 3222 | } |
---|
2957 | 3223 | |
---|
2958 | | - if (!hdr_metadata_equal(old_state, new_state) || |
---|
2959 | | - dw_hdmi_color_changed(connector)) { |
---|
2960 | | - crtc_state = drm_atomic_get_crtc_state(state, crtc); |
---|
2961 | | - if (IS_ERR(crtc_state)) |
---|
2962 | | - return PTR_ERR(crtc_state); |
---|
| 3224 | + if (check_hdmi_format_change(old_state, new_state, connector, hdmi) || |
---|
| 3225 | + hdmi->logo_plug_out) { |
---|
| 3226 | + u32 mtmdsclk; |
---|
2963 | 3227 | |
---|
2964 | | - crtc_state->mode_changed = true; |
---|
| 3228 | + if (hdmi->plat_data->update_color_format) |
---|
| 3229 | + hdmi->plat_data->update_color_format(new_state, data); |
---|
| 3230 | + if (hdmi->plat_data->get_enc_in_encoding) |
---|
| 3231 | + hdmi->hdmi_data.enc_in_encoding = |
---|
| 3232 | + hdmi->plat_data->get_enc_in_encoding(data); |
---|
| 3233 | + if (hdmi->plat_data->get_enc_out_encoding) |
---|
| 3234 | + hdmi->hdmi_data.enc_out_encoding = |
---|
| 3235 | + hdmi->plat_data->get_enc_out_encoding(data); |
---|
| 3236 | + if (hdmi->plat_data->get_input_bus_format) |
---|
| 3237 | + hdmi->hdmi_data.enc_in_bus_format = |
---|
| 3238 | + hdmi->plat_data->get_input_bus_format(data); |
---|
| 3239 | + if (hdmi->plat_data->get_output_bus_format) |
---|
| 3240 | + hdmi->hdmi_data.enc_out_bus_format = |
---|
| 3241 | + hdmi->plat_data->get_output_bus_format(data); |
---|
| 3242 | + |
---|
| 3243 | + mtmdsclk = hdmi_get_tmdsclock(hdmi, mode->clock); |
---|
| 3244 | + |
---|
| 3245 | + if (hdmi_bus_fmt_is_yuv420(hdmi->hdmi_data.enc_out_bus_format)) |
---|
| 3246 | + mtmdsclk /= 2; |
---|
| 3247 | + |
---|
| 3248 | + if (!(hdmi_readb(hdmi, HDMI_PHY_STAT0) & HDMI_PHY_HPD)) |
---|
| 3249 | + return 0; |
---|
| 3250 | + |
---|
| 3251 | + if (hdmi->hdmi_data.video_mode.mpixelclock == (mode->clock * 1000) && |
---|
| 3252 | + hdmi->hdmi_data.video_mode.mtmdsclock == (mtmdsclk * 1000) && |
---|
| 3253 | + !hdmi->logo_plug_out && !hdmi->disabled) { |
---|
| 3254 | + hdmi->update = true; |
---|
| 3255 | + hdmi_writeb(hdmi, HDMI_FC_GCP_SET_AVMUTE, HDMI_FC_GCP); |
---|
| 3256 | + mdelay(180); |
---|
| 3257 | + handle_plugged_change(hdmi, false); |
---|
| 3258 | + } else { |
---|
| 3259 | + hdmi->update = false; |
---|
| 3260 | + crtc_state->mode_changed = true; |
---|
| 3261 | + hdmi->logo_plug_out = false; |
---|
| 3262 | + } |
---|
2965 | 3263 | } |
---|
2966 | 3264 | |
---|
2967 | 3265 | return 0; |
---|
| 3266 | +} |
---|
| 3267 | + |
---|
| 3268 | +static void dw_hdmi_connector_atomic_commit(struct drm_connector *connector, |
---|
| 3269 | + struct drm_connector_state *state) |
---|
| 3270 | +{ |
---|
| 3271 | + struct dw_hdmi *hdmi = |
---|
| 3272 | + container_of(connector, struct dw_hdmi, connector); |
---|
| 3273 | + |
---|
| 3274 | + if (hdmi->update) { |
---|
| 3275 | + dw_hdmi_setup(hdmi, &hdmi->previous_mode); |
---|
| 3276 | + mdelay(50); |
---|
| 3277 | + handle_plugged_change(hdmi, true); |
---|
| 3278 | + hdmi_writeb(hdmi, HDMI_FC_GCP_CLEAR_AVMUTE, HDMI_FC_GCP); |
---|
| 3279 | + hdmi->update = false; |
---|
| 3280 | + } |
---|
2968 | 3281 | } |
---|
2969 | 3282 | |
---|
2970 | 3283 | void dw_hdmi_set_quant_range(struct dw_hdmi *hdmi) |
---|
.. | .. |
---|
3006 | 3319 | } |
---|
3007 | 3320 | EXPORT_SYMBOL_GPL(dw_hdmi_get_output_type_cap); |
---|
3008 | 3321 | |
---|
| 3322 | +void dw_hdmi_set_hpd_wake(struct dw_hdmi *hdmi) |
---|
| 3323 | +{ |
---|
| 3324 | + if (!hdmi->cec) |
---|
| 3325 | + return; |
---|
| 3326 | + |
---|
| 3327 | + dw_hdmi_hpd_wake_up(hdmi->cec); |
---|
| 3328 | +} |
---|
| 3329 | +EXPORT_SYMBOL_GPL(dw_hdmi_set_hpd_wake); |
---|
| 3330 | + |
---|
3009 | 3331 | static void dw_hdmi_connector_force(struct drm_connector *connector) |
---|
3010 | 3332 | { |
---|
3011 | 3333 | struct dw_hdmi *hdmi = container_of(connector, struct dw_hdmi, |
---|
.. | .. |
---|
3045 | 3367 | .get_modes = dw_hdmi_connector_get_modes, |
---|
3046 | 3368 | .best_encoder = drm_atomic_helper_best_encoder, |
---|
3047 | 3369 | .atomic_check = dw_hdmi_connector_atomic_check, |
---|
| 3370 | + .atomic_commit = dw_hdmi_connector_atomic_commit, |
---|
3048 | 3371 | }; |
---|
3049 | 3372 | |
---|
3050 | 3373 | static void dw_hdmi_attach_properties(struct dw_hdmi *hdmi) |
---|
.. | .. |
---|
3172 | 3495 | if (hdmi->next_bridge) |
---|
3173 | 3496 | return MODE_OK; |
---|
3174 | 3497 | |
---|
| 3498 | + if (!(hdmi_readb(hdmi, HDMI_PHY_STAT0) & HDMI_PHY_HPD) && hdmi->hdr2sdr) |
---|
| 3499 | + return MODE_OK; |
---|
| 3500 | + |
---|
3175 | 3501 | if (hdmi->plat_data->mode_valid) |
---|
3176 | 3502 | mode_status = hdmi->plat_data->mode_valid(connector, mode); |
---|
3177 | 3503 | |
---|
.. | .. |
---|
3195 | 3521 | static void dw_hdmi_bridge_disable(struct drm_bridge *bridge) |
---|
3196 | 3522 | { |
---|
3197 | 3523 | struct dw_hdmi *hdmi = bridge->driver_private; |
---|
| 3524 | + void *data = hdmi->plat_data->phy_data; |
---|
3198 | 3525 | |
---|
3199 | 3526 | mutex_lock(&hdmi->mutex); |
---|
3200 | 3527 | hdmi->disabled = true; |
---|
| 3528 | + handle_plugged_change(hdmi, false); |
---|
3201 | 3529 | dw_hdmi_update_power(hdmi); |
---|
3202 | 3530 | dw_hdmi_update_phy_mask(hdmi); |
---|
| 3531 | + if (hdmi->plat_data->dclk_set) |
---|
| 3532 | + hdmi->plat_data->dclk_set(hdmi->plat_data->phy_data, false, 0); |
---|
3203 | 3533 | mutex_unlock(&hdmi->mutex); |
---|
| 3534 | + |
---|
| 3535 | + mutex_lock(&hdmi->i2c->lock); |
---|
| 3536 | + if (hdmi->plat_data->set_ddc_io) |
---|
| 3537 | + hdmi->plat_data->set_ddc_io(data, false); |
---|
| 3538 | + mutex_unlock(&hdmi->i2c->lock); |
---|
3204 | 3539 | } |
---|
3205 | 3540 | |
---|
3206 | 3541 | static void dw_hdmi_bridge_enable(struct drm_bridge *bridge) |
---|
.. | .. |
---|
3209 | 3544 | |
---|
3210 | 3545 | mutex_lock(&hdmi->mutex); |
---|
3211 | 3546 | hdmi->disabled = false; |
---|
| 3547 | + if (hdmi->plat_data->dclk_set) |
---|
| 3548 | + hdmi->plat_data->dclk_set(hdmi->plat_data->phy_data, true, 0); |
---|
3212 | 3549 | dw_hdmi_update_power(hdmi); |
---|
3213 | 3550 | dw_hdmi_update_phy_mask(hdmi); |
---|
| 3551 | + handle_plugged_change(hdmi, true); |
---|
3214 | 3552 | mutex_unlock(&hdmi->mutex); |
---|
3215 | 3553 | } |
---|
3216 | 3554 | |
---|
.. | .. |
---|
3456 | 3794 | static const struct dw_hdmi_cec_ops dw_hdmi_cec_ops = { |
---|
3457 | 3795 | .write = hdmi_writeb, |
---|
3458 | 3796 | .read = hdmi_readb, |
---|
| 3797 | + .mod = hdmi_modb, |
---|
3459 | 3798 | .enable = dw_hdmi_cec_enable, |
---|
3460 | 3799 | .disable = dw_hdmi_cec_disable, |
---|
3461 | 3800 | }; |
---|
.. | .. |
---|
3464 | 3803 | .reg_bits = 32, |
---|
3465 | 3804 | .val_bits = 8, |
---|
3466 | 3805 | .reg_stride = 1, |
---|
3467 | | - .max_register = HDMI_I2CM_FS_SCL_LCNT_0_ADDR, |
---|
| 3806 | + .max_register = HDMI_I2CM_SCDC_UPDATE1, |
---|
3468 | 3807 | }; |
---|
3469 | 3808 | |
---|
3470 | 3809 | static const struct regmap_config hdmi_regmap_32bit_config = { |
---|
3471 | 3810 | .reg_bits = 32, |
---|
3472 | 3811 | .val_bits = 32, |
---|
3473 | 3812 | .reg_stride = 4, |
---|
3474 | | - .max_register = HDMI_I2CM_FS_SCL_LCNT_0_ADDR << 2, |
---|
| 3813 | + .max_register = HDMI_I2CM_SCDC_UPDATE1 << 2, |
---|
3475 | 3814 | }; |
---|
3476 | 3815 | |
---|
3477 | 3816 | static int dw_hdmi_status_show(struct seq_file *s, void *v) |
---|
.. | .. |
---|
3852 | 4191 | hdmi->connector.stereo_allowed = 1; |
---|
3853 | 4192 | hdmi->plat_data = plat_data; |
---|
3854 | 4193 | hdmi->dev = dev; |
---|
| 4194 | + hdmi->audio_enable = true; |
---|
3855 | 4195 | hdmi->sample_rate = 48000; |
---|
3856 | 4196 | hdmi->disabled = true; |
---|
3857 | 4197 | hdmi->rxsense = true; |
---|
.. | .. |
---|
3983 | 4323 | if (ret) |
---|
3984 | 4324 | goto err_iahb; |
---|
3985 | 4325 | |
---|
| 4326 | + hdmi->logo_plug_out = false; |
---|
3986 | 4327 | hdmi->initialized = false; |
---|
3987 | 4328 | ret = hdmi_readb(hdmi, HDMI_PHY_STAT0); |
---|
3988 | 4329 | if (((ret & HDMI_PHY_TX_PHY_LOCK) && (ret & HDMI_PHY_HPD) && |
---|
.. | .. |
---|
3992 | 4333 | hdmi->bridge_is_on = true; |
---|
3993 | 4334 | hdmi->phy.enabled = true; |
---|
3994 | 4335 | hdmi->initialized = true; |
---|
| 4336 | + if (hdmi->plat_data->set_ddc_io) |
---|
| 4337 | + hdmi->plat_data->set_ddc_io(hdmi->plat_data->phy_data, true); |
---|
| 4338 | + if (hdmi->plat_data->dclk_set) |
---|
| 4339 | + hdmi->plat_data->dclk_set(hdmi->plat_data->phy_data, true, 0); |
---|
3995 | 4340 | } else if (ret & HDMI_PHY_TX_PHY_LOCK) { |
---|
3996 | 4341 | hdmi->phy.ops->disable(hdmi, hdmi->phy.data); |
---|
| 4342 | + if (hdmi->plat_data->set_ddc_io) |
---|
| 4343 | + hdmi->plat_data->set_ddc_io(hdmi->plat_data->phy_data, false); |
---|
3997 | 4344 | } |
---|
3998 | 4345 | |
---|
3999 | 4346 | init_hpd_work(hdmi); |
---|
.. | .. |
---|
4007 | 4354 | |
---|
4008 | 4355 | hdmi->irq = irq; |
---|
4009 | 4356 | ret = devm_request_threaded_irq(dev, irq, dw_hdmi_hardirq, |
---|
4010 | | - dw_hdmi_irq, IRQF_SHARED, |
---|
| 4357 | + dw_hdmi_irq, IRQF_SHARED | IRQF_ONESHOT, |
---|
4011 | 4358 | dev_name(dev), hdmi); |
---|
4012 | 4359 | if (ret) |
---|
4013 | 4360 | goto err_iahb; |
---|
.. | .. |
---|
4126 | 4473 | cec.ops = &dw_hdmi_cec_ops; |
---|
4127 | 4474 | cec.irq = irq; |
---|
4128 | 4475 | |
---|
| 4476 | + irq = platform_get_irq(pdev, 1); |
---|
| 4477 | + if (irq < 0) |
---|
| 4478 | + dev_dbg(hdmi->dev, "can't get cec wake up irq\n"); |
---|
| 4479 | + |
---|
| 4480 | + cec.wake_irq = irq; |
---|
| 4481 | + |
---|
4129 | 4482 | pdevinfo.name = "dw-hdmi-cec"; |
---|
4130 | 4483 | pdevinfo.data = &cec; |
---|
4131 | 4484 | pdevinfo.size_data = sizeof(cec); |
---|
.. | .. |
---|
4136 | 4489 | |
---|
4137 | 4490 | hdmi->extcon = devm_extcon_dev_allocate(hdmi->dev, dw_hdmi_cable); |
---|
4138 | 4491 | if (IS_ERR(hdmi->extcon)) { |
---|
4139 | | - dev_err(hdmi->dev, "allocate extcon failed\n"); |
---|
| 4492 | + ret = PTR_ERR(hdmi->extcon); |
---|
| 4493 | + dev_err(hdmi->dev, "allocate extcon failed: %d\n", ret); |
---|
4140 | 4494 | goto err_iahb; |
---|
4141 | 4495 | } |
---|
4142 | 4496 | |
---|