I’ve been planning on a new Hacintosh computer for a while and I finally got the hardware earlier this summer, a Dell Optiplex 9020 (MT). I’ve been working on the install off and on and doing some troubleshooting with the hardware so I’m not yet ready to write up a guide. But I did want to start with this post where I will list off some of the challenges faced in getting it running.
For starters, the guide I was following was written for the initial release of MacOS Mavericks (10.9.0) and hadn’t yet been updated. It turned out that while the instructions were still valid, the kernel needed to be patched. The whole subject about the kernel patch was really interesting, actually. Effectively, for Haswell chips, you just need to kill off a part of the code that tries to write to MSRs (which would work on a real Mac but not on hardware with a BIOS not equipped for it). Although the kernel is open source, the part that does the MSR writing is not and therefore is not included. But racerrehabman figured out the fix and can patch the kernel with a simple perl sed line. The updated kernel did indeed do the trick for me.
The next issue to tackle was the issue of the computer sleeping and waking. As built, the computer would sleep okay but wouldn’t wake up. Well, actually, to clarify, since this is a desktop computer, there really is no “sleeping”, per se. That’s when the computer goes into a power saving mode but stays powered up to decrease the battery usage. Hibernating is when the computer stores the current state and then powers off so that when it powers back on, it will resume where it left off. But when most of us talk about “sleeping” a desktop, we actually mean “hibernate” and therefore I’ll keep calling it “sleeping”.
The guide I was following was posted on a site that deals with laptops so it makes sense that the guide was born of a laptop solution. (Why am I looking at a laptop site for a desktop? Because the site is well moderated and staffed with enthusiastic experts – much easier to find things there than other sites.) But part of the fix for getting the desktop to sleep correctly was to un-laptop-ify the solution by removing some of the kexts that were included in the guide: AppleSmartBatteryManager and Patched_10.7_AppleRTC.kext. The second step turned out to be simply telling the MacOS that when sleeping, it would need to store the state of the computer to disk, and not just keep it in memory. You do that on a Mac with the following command:
sudo pmset hibernatemode 3
After that change, the computer will sleep (hibernate) and wake up just fine.
The audio had been sort of working but not well (single channel audio with scratchy results). The guide included a version of VoodooHDA that appeared to be getting things working but I was confident I could do better. And I have patched audio for a computer before by using an Apple HDA patching guide and it had worked out pretty well. So I followed the guide for this computer and immediately had a problem. The computer has two sound “cards” – one for HDMI output and one for analog output. The analog one, listed as ACL280, is the one I need to use for the AppleHDA patching but it is a phantom – Realtek doesn’t list it as a chip on their site. It appears to be a virtual codec – embedded only in the Haswell chip. I tried proceeding with the patching anyway, following the guide but with the second audio “card” (#1), but I never got the computer to respond to it. I figured maybe the problem is that the OS sees the codec as an Intel codec even though it is a Realtek codec, so I tried substituting the intel vendor and product IDs in places where the Realtek ALC280 had been – substituting one by one to see what would happen and still no response at all. I couldn’t get the audio to kick off at all.
Since I wasn’t going to get source code to AppleHDA, I figured I should at least start working on my own version of VoodooHDA that would work with the chip. The ALSA org has reportedly included a patch in their code for the ALC280 claiming that it was similar to the ALC269, which is known to work with Hacintoshes, so I also got the source for ALSA. I figured I’d see what changed in the ALSA source for ALC280 and apply that to the VoodooHDA. But before I could get through the VoodooHDA changes, the author of the 9020 guide came up with a solution: simply modify the Info.plist of VoodooHDA to work with the specific vendor and device ID – the Intel one, not the Realtek one. That fixed it. So the only change needed is to change from IOPCIClassMatch = <whatever> to IOPCIMatch = 0x8c208086.
At this point the computer was working well for me, but the guide’s author reported problems with sleep for him and my suggestion for changing hibernatemode didn’t fix it for him. In fact, after trying the build all over again, he couldn’t get it to boot up at all. By comparing his build, mine, and one other, we discovered that the issue was the type of monitor connection used. I had been using one Display Port monitor and one DVI monitor, the other install that was working was using two Display Port monitor connections, and the one that failed was using two DVI connections. My DP monitor also has a DVI input and I had an additional DVI to DP adapter so I swapped the connection type and found exactly the same problem as had been reported by the guide author. (I should clarify for anyone who isn’t familiar with the Dell Optiplex 9020: it has two on-board DP connections on it but no other video connections.) And I then confirmed that using only one DVI connection would still work. Therefore, we have the following: one DVI monitor works, one DP monitor works, one DVI monitor plus one DP monitor works, two DP monitors work, and two DVI monitors do not work. So strange. And while it hadn’t been a problem for me at this point, it would be eventually because the monitor that is hooked in via DP would actually go through a DVI KVM when the system is put into regular use (and the monitor not on the KVM has only DVI input).
I felt pretty confident I was going to be able fix this one. Fortunately, there has been a lot of work already in decoding the contents of AppleIntelFramebufferAzul, the kext used for display when a Haswell chip is used. So I figured it was just a matter of sorting out the connector types and applying the right ones in the right place. First of all, there are at least 16 different “ID”s that Chameleon uses to identify the Azul type. They vary by VRAM, connectors, etc.. When I was first setting up the computer, I had been through the whole list to see which worked best and discovered that only “10” worked at all. So now looking at what ID=10 means, I discovered more information. From Pike’s posts on the subject (Post #1, Post #2, and Post #3), I was able to discern the following:
ID = 10 means to use device-id = 03 00 22 0D
3 ports, 3 pipes, 3 framebuffers
stolen RAM = 32 Mb
frame buffer size = 19 Mb
cursor size = 0 Mb
VRAM = 1536 Mb
Backlight Freq = 5273
PWM Freq = 5273
Port 1 = DP, delay = 87
Port 2 = DP, delay = 87
Port 3 = DP, delay = 11
My computer only had two DP connectors and the RAM spec numbers all seemed strange to me. From what I could tell from Linux, my video card should have memory “prefetchable” = 4Mb and “non-prefetchable”=256Mb. I had no idea how to match up the names to any of the specs in the FB kext nor did the numbers seem to match up with anything. So I started by assuming that the numbers were wrong or that I had the wrong ID. But after playing around with the numbers and different IDs, I can say with confidence that numbers other than those spec’ed above caused lots of interesting and strange behaviors. The only one I was able to change without overtly negative results is the frame buffer size and my modification was a modest change from 19 Mb to 16 Mb – that appeared to have no impact.
That left me with the port content to change. And this is where I finally had some success. Rather than have two ports with the same delay, I changed one to be a delay of 30. (The “delay” thing seems to be actually a matter of setting priority where the higher the number, the longer the delay to kick in, the more likely that port will supersede that of ports with lower delays.) This change got the computer booting up well – an improvement over not being able to boot up at all. But the computer wouldn’t sleep. In fact, it wouldn’t even shutdown (or reboot) or even correctly allow the display to sleep. Ugh.
More research led me to another of Pike’s posts where he described having an issue with one of his two external monitors being considered “built-in” on a computer that couldn’t have any monitor built in. (Since it was a Mac Pro and since “built-in” shows the picture of the computer, it’s worth clicking on the link to see the screenshot where the computer tries to indicate that the monitor is inside a Mac Pro.) He found a way to change the port information to remove the notion of having something built in. It turned out that my delay of “30” was equivalent to saying “this is the built-in monitor” – lucky me choosing the key that did that! So I was able to fix the “built-in” issue by moving the “30” to port 1 and change the port type to VGA. The computer then booted up without any “built-in” display and it correctly grabbed the right information for the two external monitors. Yay!
Except that didn’t help display sleep, computer hibernate, or shutdown/reboot. Crap. Recapping at this point, my issue is that having two DVI monitors make it fail on display sleep/hibernate/shutdown/reboot but if one monitor is DP, then all is well. What the hell could it be? I beat my head against the keyboard for a solid 12 hour day working on this and got nowhere. Googling came up mostly empty, although there were a few reports of real Mac owners having problems with DP connectors after an upgrade in OS from 10.9.1 to 10.9.2. But no mention of a solution and certainly no information out there about what to change in AppleIntelFramebufferAzul to fix it. This is one of the many times when I just say “okay, I give up, show me the answer in the source code”. Like in grade school looking at the answer in the back of the book. Except there is no source code to see. It’s just a black box. And while I could try 1000s of permutations of digits to see if I got anywhere, I just didn’t have that kind of time.
I compared the IORegistryExplorer results from the @2Display section when the DVI adapter was used and when the monitor was hooked in via DP. There were a number of differences. Some were the kind you’d expect from resources just being allocated differently across different boots so I ignored those. Some where the kind you’d expect when using a different device type like with ac-signal-type. The EDID data was different but I think that probably makes sense since the DVI connection doesn’t pass through any audio content whereas the DP connection does, so that’s a fair difference too. The only major difference that I couldn’t explain was that when the DP was connected, all three Framebuffers (including the one that had no monitor connected) had an additional property named IOScreenRestoreState with a value of “<00 00 00 00>”. When both monitors were hooked in via DVI, none of the Framebuffers had that property. So I briefly considered trying to inject that property into the registry somehow through a custom DSDT but ultimately, since I had never done that sort of thing before, decided against pursuing it.
Eventually I settled on a cop-out. Figuring that my two passive DVI to DP adapters (StarTech DP2DVI and DP2DVI2) were doing the right thing and telling the computer that a DVI monitor was connected through the DP port, I assumed that if I had an active adapter, it would tell the computer that a DP monitor was connected through the DP port. So I bought one locally ($30 but here it is at Amazon: XFX MAAP01PD1K for $5 less) and plugged it in. Immediate success. No more kext twiddling. No DSDT property injection. And no more instability. Why does this work? Well, my guess is that the Framebuffer kext has issues when dealing with DP connections that are exacerbated when the monitor connected is a DVI monitor. (The active adapter makes it so the computer thinks a DP monitor is plugged in and negotiates with the monitor to get the information. In other words, instead of being a dumb rearrangement of wires, it is like putting an additional device between the computer and monitor.) I suspect if Apple hardware offered the same port selections, it would have the same kind of problem and therefore, that there is a limitation or bug in the Apple software somewhere that just hasn’t been addressed because it hasn’t come up. Perhaps one day it will. For now, for anyone who needs both DP ports to hook into DVI monitors, the easy fix is an adapter for $25 to $30.
Before I leave the topic of the AppleIntelFramebufferAzul, I should point out that Pike now has a script that will help with patching the kext. It’s new but it is very cool. I wasn’t able to use it since I was trying to do things that aren’t normal patching. But I recommend it for anyone who is interested in patching their Azul. As a side benefit, it means that there will be fewer postings of the kext and instead people can simply patch their own with the script and a set of instructions. You can get the script from github and follow along on Pike’s Universum.