I've successfully managed to retrieve the EDID!
Code:
00 ff ff ff ff ff ff 00 30 e4 0a 04 00 00 00 00
00 17 01 04 95 1f 11 78 ea dc 95 a3 58 55 a0 26
0d 50 54 00 00 00 01 01 01 01 01 01 01 01 01 01
01 01 01 01 01 01 ba 36 80 ac 70 38 24 40 3c 24
35 00 35 af 10 00 00 1a 7c 24 80 ac 70 38 24 40
3c 24 35 00 35 af 10 00 00 1a 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 02
00 0c 33 ff 0f 3c 96 19 16 32 96 00 00 00 00 fb
(btw, the wiki says that the last byte is "Checksum (Low Byte of 16-bit sum of 00-7Eh)". I don't think this makes it clear that the sum of all 128 bytes mod 256 should be 0.)
I'm going to collect my thoughts here, then later add a wikipage about DisplayPort (and maybe DDC) and update the Intel HD Graphics page.
Here my the current code. I'll clean it up later.
I2CI2C is a very simple protocol: there is a master and up to 128 slaves. When reading/writing data, bits 7:1 indicate the address and bit 0 indicate a read if set, a write otherwise (i.e. direction). Then bytes are written until a NACK is sent.
DDC2 & EDIDDDC2 is what is used to retrieve the EDID. You must first write the offset, which should be 0, then read 128 bytes. If the data starts with 00 FF FF FF FF FF FF 00 and the sum of the data modulo 256 is 0 you've got it.
DDC/CIDDC/CI is a protocol that is built on top of I2C.
http://boichat.ch/nicolas/ddcci/specs.htmlDisplayPortDisplayPort has two channels: a main channel for video, audio ... and an auxiliary channel for I2C and whatever else.
The AUX CH is a packet-based protocol: each packet is up to 16 (20?) bytes large. The "Source" initiates a request and a "Sink" always replies within a timeout.
Each request starts with a header byte with the following format:
- bit 7: 0 for I2C data, 1 for "native" AUX CH data
- I2C: bit 6: middle-of-transaction (remember, DP packets are max 16 bytes but I2C data can be much longer)
- I2C: bit 5:4: 00 = write, 01 = read, 10 = status_request, 11 = reserved
Each reply also starts with a header byte. For I2C packets it's as follows:
- bit 5:4: 00 = AUX_ACK, 01 = AUX_NACK, 10 = AUX_DEFER, 11 = reserved
- if AUX_ACK: bit 7:6: 00 = I2C_ACK, 01 = I2C_NACK, 10 = I2C_DEFER, 11 = reserved
- if !AUX_ACK: bit 7:6 must be 00
The remaining bits are 0. The DP documentation says the header is in bits 3:0 bit this is misleading since the padding is prepended. The remaining bytes are data.
I2C_DEFER is sent if the I2C device is unable to fill the requested (expected) amount of data before the timeout (300µs). For reading EDID data at >50KHz this shouldn't be an issue if you read byte-by-byte.
The length is encoded as a 4 bit value minus 1 (e.g. 4 bytes of data -> 0b0011)
To read the EDID, the communication looks as follows (> is data sent, < is data received):
Code:
> 0b0_1_00_0000, 0, 0x50 (I2C, MOT = 1, write, address 0x50)
< 0b00_00_0000 (AUX_ACK, I2C_ACK)
> 0b0_1_00_0000, 0, 0x50, 0, 0 (I2C, MOT = 1, write, address 0x50, length 1, data 0)
< 0b00_00_0000 (AUX_ACK, I2C_ACK)
> 0b0_1_01_0000, 0, 0x50 (I2C, MOT = 1, read, address 0x50)
< 0b00_00_0000 (AUX_ACK, I2C_ACK)
loop 128 times:
> 0b0_1_01_0000, 0, 0x50, 0 (I2C, MOT = 1, read, address 0x50, length 1)
< 0b00_00_0000, x (AUX_ACK, I2C_ACK, data x)
repeat loop
> 0b0_0_01_0000, 0, 0x50 (I2C, MOT = 0, read, address 0x50)
< 0b00_00_0000 (AUX_ACK, I2C_ACK)
http://file.yizimg.com/383992/2014090921252964.pdf section 2.4, 2.4.5.4
Intel HD Graphics DP registersThere are 6 registers of note:
- DDI_AUX_CTL
- DDI_AUX_DATA
- DP_AUX_CTL
- DP_AUX_DATA
- SRD_AUX_CTL
- A seemingly unnamed register at 0xC2020
DP_AUX_* and DDI_AUX_* are exactly the same except that the DDI_* can only be used if all SRD_* registers are set as disabled. *_AUX_DATA are actually 5 registers for a total of 20 bytes of data. It may be necessary to set bit 12 of 0xC2020 which does stuff with the clock apparently.
To send a request, copy the request packet to the data registers starting from the most significant byte of the first register. Then set the message length and the send_busy bit. Wait for the done bit or any of the error bits to be set, then use the message length to determine how much data is available in the data registers.
You should preserve all the bits in the *_CTL registers. The firmware has most likely set them up properly already.
https://01.org/linuxgraphics/documentat ... l-platform Volume 02A