From 3c9a77ee1cb91acdc7d9ff9d6f8670f657039167 Mon Sep 17 00:00:00 2001 From: FireWolf <10460478+0xFireWolf@users.noreply.github.com> Date: Sat, 2 Oct 2021 00:14:42 -0700 Subject: [PATCH] Fix the issue that the builtin display remains garbled after the system boots on ICL platforms (#92) --- Changelog.md | 3 + Manual/FAQ.IntelHD.cn.md | 15 +++++ Manual/FAQ.IntelHD.en.md | 16 +++++ README.md | 4 +- WhateverGreen/kern_igfx.hpp | 45 ++++++++++++- WhateverGreen/kern_igfx_memory.cpp | 104 +++++++++++++++++++++++++++++ 6 files changed, 183 insertions(+), 4 deletions(-) diff --git a/Changelog.md b/Changelog.md index fff61894..e3b73ab3 100644 --- a/Changelog.md +++ b/Changelog.md @@ -1,5 +1,8 @@ WhateverGreen Changelog ======================= +#### v1.5.4 +- Added the fix for the short period garbled screen after the system boots on Ice Lake platforms. (by @0xFireWolf, also thanks @m0d16l14n1 and @kingo132) + #### v1.5.3 - Added `no-gfx-spoof` to avoid forcing `device-id` values from PCI I/O. - Added the backlight smoother submodule that makes brightness transitions smoother on Intel IVB+ platforms. (by @0xFireWolf) diff --git a/Manual/FAQ.IntelHD.cn.md b/Manual/FAQ.IntelHD.cn.md index 19215acf..70a72500 100644 --- a/Manual/FAQ.IntelHD.cn.md +++ b/Manual/FAQ.IntelHD.cn.md @@ -2021,6 +2021,21 @@ igfx: @ (DBG) BLS: [COMM] Processing the request: Current = 0x00014ead; Target = +## 修复 Ice Lake 平台上笔记本开机持续花屏7到15秒的问题 + +为核显添加 `enable-dbuf-early-optimizer` 属性或者直接使用 `-igfxdbeo` 启动参数以修复 Ice Lake 笔记本开机后内屏短暂花屏的问题。 +若发现内核日志记录了如下 DBUF 以及 Pipe Underrun 相关的错误信息,请启用此补丁来修复这些错误。 + +
+包含 DBUF 以及 Pipe Underrun 错误信息的内核日志 + +``` +[IGFB][ERROR][DISPLAY ] Display Pipe Underrun occurred on pipe(s) A +[IGFB][ERROR][DISPLAY ] Internal cached DBuf values are not set. Failed to distribute DBufs +``` + +
+ ## 已知问题 *兼容性*: - 受限制的显卡:HD2000 和 HD2500,它们只能用于 IQSV (因为在白苹果中它们只用来干这个),无解。 diff --git a/Manual/FAQ.IntelHD.en.md b/Manual/FAQ.IntelHD.en.md index 3ebb49f9..d65cc126 100644 --- a/Manual/FAQ.IntelHD.en.md +++ b/Manual/FAQ.IntelHD.en.md @@ -2660,6 +2660,22 @@ igfx: @ (DBG) BLS: [COMM] Processing the request: Current = 0x00014ead; Target = +## Fix the issue that the builtin display remains garbled after the system boots on ICL platforms + +Add the `enable-dbuf-early-optimizer` property to `IGPU` or use the `-igfxdbeo` boot argument instead to fix the Display Data Buffer (DBUF) allocation issue on ICL platforms, +otherwise your builtin display remains garbled for 7 to 15 seconds after the system boots. +You need this fix if you observe a bunch of errors mentioning "DBUF" and "pipe underrun" in the kernel log. + +
+Sample kernel log that contains DBUF-related errors + +``` +[IGFB][ERROR][DISPLAY ] Display Pipe Underrun occurred on pipe(s) A +[IGFB][ERROR][DISPLAY ] Internal cached DBuf values are not set. Failed to distribute DBufs +``` + +
+ ## Known Issues **Compatibility** diff --git a/README.md b/README.md index e85e47cd..fd7ecf5e 100644 --- a/README.md +++ b/README.md @@ -34,6 +34,7 @@ WhateverGreen - Supports all valid Core Display Clock (CDCLK) freqencies on Intel ICL platforms. - Fixes the kernel panic caused by an incorrectly calculated amount of DVMT pre-allocated memory on Intel ICL platforms. - Makes brightness transitions smoother on Intel IVB+ platforms. +- Fixes the short period garbled screen issue after the system boots on Intel ICL platforms. #### Documentation @@ -94,6 +95,7 @@ indices of connectors for which online status is enforced. Format is similar to - `-igfxblr` boot argument (and `enable-backlight-registers-fix` property) to fix backlight registers on KBL, CFL and ICL platforms. - `-igfxmpc` boot argument (`enable-max-pixel-clock-override` and `max-pixel-clock-frequency` properties) to increase max pixel clock (as an alternative to patching CoreDisplay.framework). - `-igfxbls` boot argument (and `enable-backlight-smoother` property) to make brightness transitions smoother on IVB+ platforms. [Read the manual](https://github.com/acidanthera/WhateverGreen/blob/master/Manual/FAQ.IntelHD.en.md#customize-the-behavior-of-the-backlight-smoother-to-improve-your-experience) +- `-igfxdbeo` boot argument (and `enable-dbuf-early-optimizer` property) to fix the Display Data Buffer (DBUF) issues on ICL+ platforms. #### Credits @@ -101,7 +103,7 @@ indices of connectors for which online status is enforced. Format is similar to - [AMD](https://www.amd.com) for ATOM VBIOS parsing code - [The PCI ID Repository](http://pci-ids.ucw.cz) for multiple GPU model names - [Andrey1970AppleLife](https://github.com/Andrey1970AppleLife) for [FAQs](https://github.com/acidanthera/WhateverGreen/blob/master/Manual/) -- [FireWolf](https://github.com/0xFireWolf/) for the DPCD maximum link rate fix, infinite loop fix for Intel HDMI connections, LSPCON driver support, Core Display Clock frequency fix for ICL platforms, DVMT pre-allocated memory calculation fix for ICL platforms, and Backlight Smoother for IVB+ platforms. +- [FireWolf](https://github.com/0xFireWolf/) for the DPCD maximum link rate fix, infinite loop fix for Intel HDMI connections, LSPCON driver support, Core Display Clock frequency fix for ICL platforms, DVMT pre-allocated memory calculation fix for ICL platforms, Backlight Smoother for IVB+ platforms, and Display Data Buffer fix for ICL platforms. - [Floris497](https://github.com/Floris497) for the CoreDisplay [patches](https://github.com/Floris497/mac-pixel-clock-patch-v2) - [Fraxul](https://github.com/Fraxul) for original CFL backlight patch - [headkaze](https://github.com/headkaze) for Intel framebuffer patching code and CFL backlight patch improvements diff --git a/WhateverGreen/kern_igfx.hpp b/WhateverGreen/kern_igfx.hpp index b6050bb8..9075f5cd 100644 --- a/WhateverGreen/kern_igfx.hpp +++ b/WhateverGreen/kern_igfx.hpp @@ -1758,7 +1758,45 @@ class IGFX { void processKernel(KernelPatcher &patcher, DeviceInfo *info) override; void processFramebufferKext(KernelPatcher &patcher, size_t index, mach_vm_address_t address, size_t size) override; } modMaxPixelClockOverride; - + + /** + * A submodule to optimize the display data buffer position earlier to solve the 10-second flicker issue on ICL+ + */ + class DisplayDataBufferEarlyOptimizer: public PatchSubmodule { + /** + * The feature control key + */ + static constexpr const char* kFeatureControl = "FeatureControl"; + + /** + * The display data buffer optimizer delay key + */ + static constexpr const char* kOptimizerTime = "DBUFOptimizeTime"; + + /** + * Specify the amount of time in seconds to delay the execution of optimizing the display data buffer allocation + */ + uint32_t optimizerTime {0}; + + /** + * Original AppleIntelFramebufferController::getFeatureControl function + */ + void (*orgGetFeatureControl)(IOService *controller) {nullptr}; + + /** + * Fetch and load the featuer control information + * + * @param controller The hidden implicit `this` pointer + */ + static void wrapGetFeatureControl(IOService *controller); + + public: + // MARK: Patch Submodule IMP + void init() override; + void processKernel(KernelPatcher &patcher, DeviceInfo *info) override; + void processFramebufferKext(KernelPatcher &patcher, size_t index, mach_vm_address_t address, size_t size) override; + } modDisplayDataBufferEarlyOptimizer; + /** * A collection of shared submodules */ @@ -1771,7 +1809,7 @@ class IGFX { /** * A collection of submodules */ - PatchSubmodule *submodules[19] = { + PatchSubmodule *submodules[20] = { &modDVMTCalcFix, &modDPCDMaxLinkRateFix, &modCoreDisplayClockFix, @@ -1790,7 +1828,8 @@ class IGFX { &modBacklightRegistersFix, &modBacklightSmoother, &modFramebufferDebugSupport, - &modMaxPixelClockOverride + &modMaxPixelClockOverride, + &modDisplayDataBufferEarlyOptimizer, }; /** diff --git a/WhateverGreen/kern_igfx_memory.cpp b/WhateverGreen/kern_igfx_memory.cpp index 4af9e8d3..a4b0facd 100644 --- a/WhateverGreen/kern_igfx_memory.cpp +++ b/WhateverGreen/kern_igfx_memory.cpp @@ -10,6 +10,15 @@ #include #include +/// +/// This file contains the following memory-related fixes +/// +/// 1. DVMT calculation fix on ICL+. +/// 2. Display data buffer early optimizer on ICL+. +/// + +// MARK: - DVMT Pre-allocated Memory Calculation Fix + void IGFX::DVMTCalcFix::init() { // We only need to patch the framebuffer driver requiresPatchingGraphics = false; @@ -206,3 +215,98 @@ void IGFX::DVMTCalcFix::processFramebufferKext(KernelPatcher &patcher, size_t in SYSLOG("igfx", "DVMT: Failed to find instructions of interest. Aborted patching."); } +// MARK: - Display Data Buffer Early Optimizer + +void IGFX::DisplayDataBufferEarlyOptimizer::wrapGetFeatureControl(IOService *controller) { + // + // Abstract + // + // Display Data Buffer (DBUF) is critical for display pipes and planes to function properly. + // The graphics driver allocates the buffer by writing a pair to the plane buffer configuration register. + // Apple expects that the firmware has allocated an adequate amount of buffer for the Pipe A that drives the builtin display, + // so the driver can optimize the allocation later to provide better display residency in memory low power modes. + // However, the buffer allocated by the BIOS on Ice Lake-based laptops seems to be not enough for the plane running in the mode configured by the driver, + // resulting in a garbled display that lasts for about 7 to 15 seconds when the system finishes booting and presents the login window. + // This issue will disappear when the function that optimizes the buffer allocation is fired by a timer enabled at the end of mode setting. + // The default delay of executing the optimizer function is 15 seconds which is hard-coded in the framebuffer controller's startup routine. + // Fortunately, we can change the delay by injecting the property "DBUFOptimizeTime" to the feature control dictionary. + // By specifying a delay of 0 second, we can invoke the optimizer function as soon as the graphics driver completes the modeset for the builtin display, + // thus fixing the garbled builtin screen issue on Ice Lake platforms without having any negative impacts on external monitors. + // + // Future Work + // + // Ideally, we should be able to increase the buffer allocation at an early boot stage, + // just like how we fix the Core Display Clock issue on Ice Lake platforms. + // However, I am still trying to figure out where the best place is to inject the code properly. + // + // Acknowledgements + // + // I would like to acknowledge @m0d16l14n1's passion and insistence on this annoying issue since Sep, 2020, + // and @kingo123 for implementing the proof-of-concept code showing that @m0d16l14n1's direction is correct. + // Your findings motivate me to resume this research on the display data buffer issue and find the root cause. + // + // - FireWolf + // - 2021.10 + // + auto module = &callbackIGFX->modDisplayDataBufferEarlyOptimizer; + + do { + // Guard: Fetch the current feature control dictionary + auto features = OSDynamicCast(OSDictionary, controller->getProperty(kFeatureControl)); + if (features == nullptr) { + SYSLOG("igfx", "DBEO: Failed to fetch the feature control dictionary."); + break; + } + + auto clonedFeatures = features->copyCollection(); + if (clonedFeatures == nullptr) { + SYSLOG("igfx", "DBEO: Failed to clone the feature control dictionary."); + break; + } + + auto newFeatures = OSDynamicCast(OSDictionary, clonedFeatures); + PANIC_COND(newFeatures == nullptr, "igfx", "DBEO: The cloned collection is not a dictionary."); + + // Allocate the new optimizer delay + auto delay = OSNumber::withNumber(module->optimizerTime, 32); + if (delay == nullptr) { + SYSLOG("igfx", "DBEO: Failed to allocate the new optimizer delay."); + newFeatures->release(); + break; + } + + // Set the new optimizer delay + newFeatures->setObject(kOptimizerTime, delay); + controller->setProperty(kFeatureControl, newFeatures); + delay->release(); + newFeatures->release(); + DBGLOG("igfx", "DBEO: The new optimizer value has been set to %u.", module->optimizerTime); + } while (false); + + module->orgGetFeatureControl(controller); +} + +void IGFX::DisplayDataBufferEarlyOptimizer::init() { + // We only need to patch the framebuffer driver + requiresPatchingGraphics = false; + requiresPatchingFramebuffer = true; +} + +void IGFX::DisplayDataBufferEarlyOptimizer::processKernel(KernelPatcher &patcher, DeviceInfo *info) { + // Enable the fix if the corresponding boot argument is found + enabled = checkKernelArgument("-igfxdbeo"); + // Of if "enable-dbuf-early-optimizer" is set in IGPU property + if (!enabled) + enabled = info->videoBuiltin->getProperty("enable-dbuf-early-optimizer") != nullptr; + if (!enabled) + return; + + // Fetch the user configuration + if (WIOKit::getOSDataValue(info->videoBuiltin, "dbuf-optimizer-delay", optimizerTime)) + DBGLOG("igfx", "DBEO: User requested optimizer delay = %u.", optimizerTime); +} + +void IGFX::DisplayDataBufferEarlyOptimizer::processFramebufferKext(KernelPatcher &patcher, size_t index, mach_vm_address_t address, size_t size) { + KernelPatcher::RouteRequest request("__ZN31AppleIntelFramebufferController17getFeatureControlEv", wrapGetFeatureControl, orgGetFeatureControl); + SYSLOG_COND(!patcher.routeMultiple(index, &request, 1, address, size), "igfx", "DBEO: Failed to route the function."); +}