@@ -1444,23 +1444,27 @@ static void hdmi_config_init()
14441444
14451445 if (hdmi_main_fd < 0 )
14461446 {
1447- hdmi_main_fd = i2c_open (0x39 , 0 );
1447+ int adv_bus = -1 ;
1448+ hdmi_main_fd = i2c_open (0x39 , 0 , -1 , &adv_bus);
14481449 if (hdmi_main_fd < 0 )
14491450 {
14501451 printf (" ADV7513 not found on i2c bus! HDMI won't be available!\n " );
14511452 return ;
14521453 }
14531454 else
14541455 {
1456+ // EDID/SPD are sub-maps of the same chip: pin them to the main bus
1457+ // instead of rescanning, or a phantom that ACKs on another bus can
1458+ // capture the handle and wedge the i2c controller on a real transfer.
14551459 if (hdmi_edid_fd < 0 )
14561460 {
1457- hdmi_edid_fd = i2c_open (0x3f , 0 );
1461+ hdmi_edid_fd = i2c_open (0x3f , 0 , adv_bus );
14581462 if (hdmi_edid_fd < 0 ) printf (" ADV7513: cannot find EDID registers.\n " );
14591463 }
14601464
14611465 if (hdmi_spd_fd < 0 )
14621466 {
1463- hdmi_spd_fd = i2c_open (0x38 , 0 );
1467+ hdmi_spd_fd = i2c_open (0x38 , 0 , adv_bus );
14641468 if (hdmi_spd_fd < 0 ) printf (" ADV7513: cannot find SPD registers.\n " );
14651469 }
14661470 }
@@ -1806,20 +1810,25 @@ static int find_edid_vrr_capability()
18061810
18071811}
18081812
1809- static int is_edid_valid ( )
1813+ static int is_edid_valid_buf ( const uint8_t *buf )
18101814{
18111815 static const uint8_t magic[] = { 0x00 , 0xFF , 0xFF , 0xFF , 0xFF , 0xFF , 0xFF , 0x00 };
18121816 if (sizeof (edid) < sizeof (magic)) return 0 ;
1813- return !memcmp (edid, magic, sizeof (magic));
1817+ return !memcmp (buf, magic, sizeof (magic));
1818+ }
1819+
1820+ static int is_edid_valid ()
1821+ {
1822+ return is_edid_valid_buf (edid);
18141823}
18151824
1816- static void cache_raw_edid_mfg_id ()
1825+ static void cache_raw_edid_mfg_id (const uint8_t *buf )
18171826{
1818- raw_edid_mfg_id = (edid [0x08 ] << 8 ) | edid [0x09 ];
1827+ raw_edid_mfg_id = (buf [0x08 ] << 8 ) | buf [0x09 ];
18191828 raw_edid_mfg_id_valid = true ;
18201829}
18211830
1822- static void read_edid_segment (uint8_t segment, uint8_t *buf)
1831+ static bool read_edid_segment (uint8_t segment, uint8_t *buf)
18231832{
18241833 i2c_smbus_write_byte_data (hdmi_main_fd, 0xC4 , segment);
18251834 i2c_smbus_write_byte_data (hdmi_main_fd, 0xC9 , 0x03 );
@@ -1829,28 +1838,28 @@ static void read_edid_segment(uint8_t segment, uint8_t *buf)
18291838 unsigned long timeout = GetTimer (500 );
18301839 while (!CheckTimer (timeout))
18311840 {
1832- if (i2c_smbus_read_byte_data (hdmi_main_fd, 0x96 ) & 4 )
1841+ int status = i2c_smbus_read_byte_data (hdmi_main_fd, 0x96 );
1842+ if (status >= 0 && (status & 4 ))
18331843 {
18341844 i2c_smbus_write_byte_data (hdmi_main_fd, 0x96 , 4 );
1835- break ;
1845+ for (uint16_t i = 0 ; i < 256 ; i++)
1846+ {
1847+ int value = i2c_smbus_read_byte_data (hdmi_edid_fd, (uint8_t )i);
1848+ buf[i] = (value < 0 ) ? 0 : (uint8_t )value;
1849+ }
1850+ return true ;
18361851 }
18371852 usleep (10000 );
18381853 }
18391854
1840- for (uint16_t i = 0 ; i < 256 ; i++)
1841- {
1842- int value = i2c_smbus_read_byte_data (hdmi_edid_fd, (uint8_t )i);
1843- buf[i] = (value < 0 ) ? 0 : (uint8_t )value;
1844- }
1855+ return false ;
18451856}
18461857
18471858static int read_edid (bool force = false )
18481859{
18491860 if (hdmi_main_fd < 0 || hdmi_edid_fd < 0 ) return 0 ;
18501861 if (is_edid_valid () && !force) return 1 ;
18511862
1852- memset (edid, 0 , sizeof (edid));
1853-
18541863 // Test if adv7513 senses hdmi clock. If not, don't bother with the edid query
18551864 int hpd_state = i2c_smbus_read_byte_data (hdmi_main_fd, 0x42 );
18561865 if (hpd_state < 0 || !(hpd_state & 0x20 ))
@@ -1859,35 +1868,57 @@ static int read_edid(bool force = false)
18591868 return 0 ;
18601869 }
18611870
1871+ // read into scratch; replace live edid[] only on a valid read, so a transient failure can't blank it
1872+ uint8_t buf[sizeof (edid)] = {};
1873+ bool ddc_responded = false ;
1874+
18621875 // waiting for valid EDID
18631876 for (int k = 0 ; k < 20 ; k++)
18641877 {
1865- read_edid_segment (0 , edid);
1866- if (is_edid_valid ()) break ;
1878+ int current = i2c_smbus_read_byte_data (hdmi_main_fd, 0x42 );
1879+ if (current < 0 || !(current & 0x20 ))
1880+ {
1881+ raw_edid_mfg_id_valid = false ;
1882+ return 0 ;
1883+ }
1884+ bool got_interrupt = read_edid_segment (0 , buf);
1885+ if (got_interrupt) ddc_responded = true ;
1886+ if (is_edid_valid_buf (buf)) break ;
1887+ if (!got_interrupt) break ; // no DDC response — display has no EDID, don't retry
18671888 usleep (100000 );
18681889 }
18691890
1870- if (is_edid_valid ( ))
1891+ if (! is_edid_valid_buf (buf ))
18711892 {
1872- uint8_t max_blocks = sizeof (edid) / 256 ;
1873- uint8_t blocks = (2 + edid[126 ]) / 2 ; // each block is 128 bytes
1874- if (blocks > max_blocks) blocks = max_blocks;
1875- for (uint8_t i = 1 ; i < blocks; i++) read_edid_segment (i, edid + (i * 256 ));
1893+ if (ddc_responded)
1894+ {
1895+ // header bad but DDC answered: still cache raw mfg id for non-conformant DAC EDIDs
1896+ cache_raw_edid_mfg_id (buf);
1897+ printf (" Invalid EDID: incorrect header.\n " );
1898+ }
1899+ else
1900+ {
1901+ printf (" Invalid EDID: no DDC response.\n " );
1902+ }
1903+ // stored edid[], not buf: only when a prior valid read is being kept
1904+ if (is_edid_valid ()) printf (" Invalid EDID: keeping last valid EDID.\n " );
1905+
1906+ return 0 ;
18761907 }
18771908
1909+ uint8_t max_blocks = sizeof (edid) / 256 ;
1910+ uint8_t blocks = (2 + buf[126 ]) / 2 ; // each block is 128 bytes
1911+ if (blocks > max_blocks) blocks = max_blocks;
1912+ for (uint8_t i = 1 ; i < blocks; i++) read_edid_segment (i, buf + (i * 256 ));
1913+
1914+ memcpy (edid, buf, sizeof (edid));
1915+
18781916 printf (" EDID:\n " );
18791917 uint8_t n = edid[126 ] + 1 ;
18801918 if (n > sizeof (edid) / 128 ) n = sizeof (edid) / 128 ;
18811919 hexdump (edid, n*128 , 0 );
18821920
1883- cache_raw_edid_mfg_id ();
1884-
1885- if (!is_edid_valid ())
1886- {
1887- printf (" Invalid EDID: incorrect header.\n " );
1888- bzero (edid, sizeof (edid));
1889- return 0 ;
1890- }
1921+ cache_raw_edid_mfg_id (edid);
18911922
18921923 edid_version++;
18931924 return 1 ;
@@ -2686,10 +2717,20 @@ void video_init()
26862717
26872718void video_reinit ()
26882719{
2720+ int prev_ver = edid_version;
2721+ read_edid (true );
2722+
2723+ // re-read gave nothing new but a valid EDID is still held: the mode is unchanged,
2724+ // so don't bounce a working link (some clones can't re-lock mid-operation)
2725+ if (edid_version == prev_ver && is_edid_valid ())
2726+ {
2727+ printf (" *** Video re-init skipped: EDID unchanged.\n " );
2728+ return ;
2729+ }
2730+
26892731 printf (" *** Video re-initialization.\n " );
26902732
26912733 hdmi_config_init ();
2692- read_edid (true );
26932734 hdmi_config_set_hdr ();
26942735
26952736 support_FHD = 0 ;
0 commit comments