So despite my efforts so far, i’m plagued by this problem of the screen going blank when the Intel HD 4000 Framebuffer driver loads. even in safe mode.
This has nothing to do with the Intel HD4000 Graphics kext it seems, instead it the AppleIntelFrameBufferCapri.kext.
The problem exists in the following versions so far…
- Lion 10.7.5
- Mountain Lion 10.8.1
- Mountain Lion 10.8.2
- Mountain Lion 10.8.3
- Mountain Lion 10.8.4
- Mountain Lion 10.8.5 (Beta 12F13)
- Mavericks 10.9 DP2
..which at the time of updating, it every version.
There are many posts around the internet from people having no display, but this almost always turns out to be people not using the correct platform id on their laptop. It normally ends with a post saying ‘i fixed it by injecting this string (which actually injects the correct platform id) or “i ended up using chimera 1.11.something” (which again actually just injects the correct platform id).
Instead my problem is that the display IS detected, but the output to the panel isn’t being activated. It seems that the driver outputs the display on AAPL,DisplayPipe 00 00 00 00 which is where it expects the display on port 04 06 to be.
The only other output port available on this All-in-One is, oddly, VGA. So I plugged a monitor into this port to see what happened, and as soon as the display enables, garbage is output onto the VGA screen! The reason for this, I can only assume, is that display pipe 00 00 00 00 is actually the VGA port, not the internal display, and its garbled because its sending the wrong signal type, DisplayPort.
By searching around the internet, and thanks to various hackintosh folks around the forums eep357, toledo, bcc7 et al, i’ve been able to crack on with some tests.
The Apple driver has VGA support, but its not enabled in any of the Platform IDs, which means i needed to edit the file with a Hex Editor for the platform ID i am using.
I’ve found the tables in the file by searching for ‘05006201’ and changed the entries to that the first port so 0602 (VGA) the second is 0406 (DisplayPort) and the third is 0304, which i think is HDMI, i just shuffled it there to fill up the space.
So with that change made, it made no difference to the output on both screens, even though both displays are now detected.
It’s worth noting that the first entry is always seen as ‘built-in’. I’ve tried swapping the devices around and it doesn’t fix my issue.
but, from here i can see that the VGA uses AAPL,DisplayPipe 01 00 00 00.
For my next experiment, I decided to edit out the internal display 0406, and just try and run on VGA only. the resulted in the internal display suddenly coming to life! sadly, it was the garbled VGA display pipe I was seeing. but…it’s something!
So from this I can conclude, that its sending the displayport signal down pipe 0 which is physically the VGA output, and the VGA signal down pipe 1 which is the display port output. This currently explains everything.
Windows has no such issues, so i thought i would give a Linux install a go, seen what happens. At the time, only Ubuntu 12.10 and Mint 14 have support for HD4000 out of the box. Lo and behold, as soon as they load up, the screen goes off in exactly the same way. It does appear that both drivers seem to make an incorrect assumption that the display will be on pipe 0. in fact i think this All in one is the only computer i’ve used so far configured in this odd way with the pipes inverted.
Now, the chances of Apple changing their driver for me are pretty much zero, so i’m now trying to establish how this pipe to port layout is defined, is it hardwired into the motherboard design? or is set in the bios somewhere?
According to the ACPI specs, the _DOD method defines what is connected to what pipe and port:
Method (_DOD, 0) { Return ( Package() { 0x00000110, // Primary LCD panel, not detectable by BIOS 0x80000100, // CRT type display, not detectable by BIOS 0x80000220, // TV type display, not detectable by the BIOS 0x80000411, // Secondary LCD panel, not detectable by BIOS</pre> } ) } Examples: 0x000xyyyy // Bit 31 = 0. Other proprietary scheme - 0x110 Device ID is an exception. (See Note 3) 0x00000110 // Integrated LCD Panel #1 using a common, backwards compatible ID 0x80000100 // Integrated VGA CRT or VESA compatible Monitor #1 on Port0 0x80000240 // Integrated TV #1 on Port4 0x80000410 // Integrated Internal LCD Panel #1 on Port1 0x80000421 // LVDS Panel #2 Dual-Link using Port2 & 3. (See Note 4) 0x80000131 // VGA CRT or VESA compatible Monitor #2 on Port3 0x80000121 // Dual-Link VGA CRT or VESA compatible Monitor #2 using Port2 & 3. (See Note 4.) 0x80000320 // DVI Monitor #1 on Port2 (shares Port2 with a Dual-Function DVI/TV Encoder). (See Note 5) 0x80000331 // DVI Monitor #2 on Port3 0x80000330 // Dual-Link DVI Monitor #1 using Port2 & 3 0x80000231 // TV #2 on Port2 (shares Port2 with a Dual-Function DVI/TV Encoder). (See Note 5)
On the old MacBook here, the _DOD method looks nice and simple like this, but on this All-in-One computer its huge and complex, full of NDID sections and external checks. I’ve checked on a few other modern computers and they seem to follow the same template.
On the iMac 13,1 the HD 4000 isnt used at all, and the _DOD for the nVidia display matches this example above, it resides in the SSDT-5 table:
Method (_DOD, 0, NotSerialized) { Return (Package (0x01) { 0x80002400 }) }
Which should equate to internal flat panel, on display port 0, with display index 0.
On the MacBookPro10,2, also in SSDT-5, we have the same complex layout I mentioned before:
Method (_DOD, 0, NotSerialized) { If (CondRefOf (IDAB)) {} Else { Store (0x00, NDID) If (LNotEqual (DIDL, Zero)) { Store (SDDL (DIDL), DID1) } If (LNotEqual (DDL2, Zero)) { Store (SDDL (DDL2), DID2) } If (LNotEqual (DDL3, Zero)) { Store (SDDL (DDL3), DID3) } If (LNotEqual (DDL4, Zero)) { Store (SDDL (DDL4), DID4) } If (LNotEqual (DDL5, Zero)) { Store (SDDL (DDL5), DID5) } If (LNotEqual (DDL6, Zero)) { Store (SDDL (DDL6), DID6) } If (LNotEqual (DDL7, Zero)) { Store (SDDL (DDL7), DID7) } If (LNotEqual (DDL8, Zero)) { Store (SDDL (DDL8), DID8) } } If (LEqual (NDID, 0x01)) { Name (TMP1, Package (0x01) { 0xFFFFFFFF }) Store (Or (0x00010000, DID1), Index (TMP1, 0x00)) Return (TMP1) } If (LEqual (NDID, 0x02)) { Name (TMP2, Package (0x02) { 0xFFFFFFFF, 0xFFFFFFFF }) Store (Or (0x00010000, DID1), Index (TMP2, 0x00)) Store (Or (0x00010000, DID2), Index (TMP2, 0x01)) Return (TMP2) } If (LEqual (NDID, 0x03)) { Name (TMP3, Package (0x03) { 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF }) Store (Or (0x00010000, DID1), Index (TMP3, 0x00)) Store (Or (0x00010000, DID2), Index (TMP3, 0x01)) Store (Or (0x00010000, DID3), Index (TMP3, 0x02)) Return (TMP3) } If (LEqual (NDID, 0x04)) { Name (TMP4, Package (0x04) { 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF }) Store (Or (0x00010000, DID1), Index (TMP4, 0x00)) Store (Or (0x00010000, DID2), Index (TMP4, 0x01)) Store (Or (0x00010000, DID3), Index (TMP4, 0x02)) Store (Or (0x00010000, DID4), Index (TMP4, 0x03)) Return (TMP4) } If (LEqual (NDID, 0x05)) { Name (TMP5, Package (0x05) { 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF }) Store (Or (0x00010000, DID1), Index (TMP5, 0x00)) Store (Or (0x00010000, DID2), Index (TMP5, 0x01)) Store (Or (0x00010000, DID3), Index (TMP5, 0x02)) Store (Or (0x00010000, DID4), Index (TMP5, 0x03)) Store (Or (0x00010000, DID5), Index (TMP5, 0x04)) Return (TMP5) } If (LEqual (NDID, 0x06)) { Name (TMP6, Package (0x06) { 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF }) Store (Or (0x00010000, DID1), Index (TMP6, 0x00)) Store (Or (0x00010000, DID2), Index (TMP6, 0x01)) Store (Or (0x00010000, DID3), Index (TMP6, 0x02)) Store (Or (0x00010000, DID4), Index (TMP6, 0x03)) Store (Or (0x00010000, DID5), Index (TMP6, 0x04)) Store (Or (0x00010000, DID6), Index (TMP6, 0x05)) Return (TMP6) } If (LEqual (NDID, 0x07)) { Name (TMP7, Package (0x07) { 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF }) Store (Or (0x00010000, DID1), Index (TMP7, 0x00)) Store (Or (0x00010000, DID2), Index (TMP7, 0x01)) Store (Or (0x00010000, DID3), Index (TMP7, 0x02)) Store (Or (0x00010000, DID4), Index (TMP7, 0x03)) Store (Or (0x00010000, DID5), Index (TMP7, 0x04)) Store (Or (0x00010000, DID6), Index (TMP7, 0x05)) Store (Or (0x00010000, DID7), Index (TMP7, 0x06)) Return (TMP7) } If (LEqual (NDID, 0x08)) { Name (TMP8, Package (0x08) { 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF }) Store (Or (0x00010000, DID1), Index (TMP8, 0x00)) Store (Or (0x00010000, DID2), Index (TMP8, 0x01)) Store (Or (0x00010000, DID3), Index (TMP8, 0x02)) Store (Or (0x00010000, DID4), Index (TMP8, 0x03)) Store (Or (0x00010000, DID5), Index (TMP8, 0x04)) Store (Or (0x00010000, DID6), Index (TMP8, 0x05)) Store (Or (0x00010000, DID7), Index (TMP8, 0x06)) Store (Or (0x00010000, DID8), Index (TMP8, 0x07)) Return (TMP8) } Return (Package (0x01) { 0x0400 }) }
Underneath this is a few devices called (DD01), (DD02) and so forth, DD02 is the only one with _BCL, _BCM and _BQC methods, indicating that this is the device that relates the internal panel.
I get the feeling that I’m on another long path of understanding, only to end up understanding that this isn’t going to fix it anyway!