On Friday 30 January 2015 20:45:28 Ville Syrjälä wrote:
On Tue, Jan 27, 2015 at 03:43:49PM +0000, Simon Farnsworth wrote:
DisplayPort to DVI-D Dual Link adapters designed by Bizlink have bugs in their I2C over AUX implementation. They work fine with Windows, but fail with Linux.
It turns out that they cannot keep an I2C transaction open unless the previous read was 16 bytes; shorter reads can only be followed by a zero byte transfer ending the I2C transaction.
Copy Windows's behaviour, and read 16 bytes at a time. If we get a short reply, assume that there's a hardware bottleneck, and shrink our read size to match. For this purpose, use the algorithm in the DisplayPort 1.2 spec, in the hopes that it'll be closest to what Windows does, as no sink I've found actually gives short replies.
Also provide a module parameter for testing smaller transfer sizes, in case there are sinks out there that cannot work with Windows.
Signed-off-by: Simon Farnsworth simon.farnsworth@onelan.co.uk
v3 changes, after feedback from Ville and more testing of Windows:
Change the short reply algorithm to match Ville's description of the DisplayPort 1.2 spec wording.
Add a module parameter to set the default transfer size for experiments. Requested over IRC by Ville.
No-one's been able to find a device that does short replies, but experiments show that bigger reads are faster on most devices. Ville got:
DP->DVI (OUI 001cf8): 40ms -> 35ms DP->VGA (OUI 0022b9): 45ms -> 38ms Zotac DP->2xHDMI: 25ms -> 4ms
Another datapoint: Asus PB278 monitor: 22ms -> 3ms
I've been pondering about these massive improvements for the Zotac and Asus. After reading the DP spec a bit more I've noticed just how wasteful AUX is. If my understanding of the spec and arithmetic aren't totally off, the effective bandwidth for EDID reads is ~400kbps when using 16 byte AUX messages, but it drops to only ~60kbps when doing 1 byte AUX messages. Those seem to match reasonably well with my measurements. I never realized just how slow it can be since the 1Mbps number feels like plenty, and no one ever seems to mention the effective bandwidth.
Doing the maths myself, to see if you're in the right ballpark:
Each AUX message has 24 bits worth of SYNC/STOP overhead, and between 10 and 16 bits of precharge overhead.
You've got 32 bits of data in the request. In the reply, you have 8 overhead bits, and however many bits of data you requested.
Each request therefore takes 66 to 72 bits to make. A reply has 42 to 48 bits of overhead, plus the bits you requested. This makes 108 to 120 bits of overhead for each I2C transfer.
At one byte per request, we're using 116 to 128 bit times for every EDID byte. This is 14.5 to 16 bit times per payload bit transferred, for a payload bit rate on a 1 MHz channel between 62.5 kbit/s and 69.0 kbit/s.
At 16 bytes per request, we're using 236 to 248 bit times for every 16 bytes of EDID. This is 1.84 to 1.94 bit times per payload bit transferred, for a payload bit rate between 516.1 kbit/s and 542.3 kbit/s.