From 0a0cdc450e63aea36a1cc75c1a1e842b06e1f2cd Mon Sep 17 00:00:00 2001 From: Visual Ehrmanntraut <30368284+VisualEhrmanntraut@users.noreply.github.com> Date: Wed, 9 Oct 2024 02:40:12 +0300 Subject: [PATCH] fix: Use old PWM brightness control logic on Raven Closes #236 Temporary workaround. FIXME! --- NootedRed/X6000FB.cpp | 54 ++++++++++++++++++++++++++++++++----------- NootedRed/X6000FB.hpp | 24 +++++++++++++++---- 2 files changed, 60 insertions(+), 18 deletions(-) diff --git a/NootedRed/X6000FB.cpp b/NootedRed/X6000FB.cpp index 833fcd89..e0e494e0 100644 --- a/NootedRed/X6000FB.cpp +++ b/NootedRed/X6000FB.cpp @@ -60,6 +60,12 @@ bool X6000FB::processKext(KernelPatcher &patcher, size_t id, mach_vm_address_t s PANIC_COND(!solveRequest.solve(patcher, id, slide, size), "X6000FB", "Failed to resolve CAIL_ASIC_CAPS_TABLE"); if (NRed::callback->attributes.isBacklightEnabled()) { + if (NRed::callback->attributes.isBigSurAndLater() && NRed::callback->attributes.isRaven()) { + SolveRequestPlus solveRequest {"_dce_driver_set_backlight", this->orgDceDriverSetBacklight, + kDceDriverSetBacklightPattern, kDceDriverSetBacklightPatternMask}; + PANIC_COND(!solveRequest.solve(patcher, id, slide, size), "X6000FB", + "Failed to resolve dce_driver_set_backlight"); + } if (NRed::callback->attributes.isSonoma1404AndLater()) { SolveRequestPlus solveRequest {"_dc_link_set_backlight_level", this->orgDcLinkSetBacklightLevel, kDcLinkSetBacklightLevelPattern14_4}; @@ -145,6 +151,19 @@ bool X6000FB::processKext(KernelPatcher &patcher, size_t id, mach_vm_address_t s } if (NRed::callback->attributes.isBacklightEnabled()) { + if (NRed::callback->attributes.isBigSurAndLater() && NRed::callback->attributes.isRaven()) { + if (NRed::callback->attributes.isSonoma1404AndLater()) { + RouteRequestPlus request = {"_dce_panel_cntl_hw_init", wrapDcePanelCntlHwInit, + this->orgDcePanelCntlHwInit, kDcePanelCntlHwInitPattern14_4}; + PANIC_COND(!request.route(patcher, id, slide, size), "X6000FB", + "Failed to route dce_panel_cntl_hw_init (14.4+)"); + } else { + RouteRequestPlus request = {"_dce_panel_cntl_hw_init", wrapDcePanelCntlHwInit, + this->orgDcePanelCntlHwInit, kDcePanelCntlHwInitPattern}; + PANIC_COND(!request.route(patcher, id, slide, size), "X6000FB", + "Failed to route dce_panel_cntl_hw_init"); + } + } RouteRequestPlus requests[] = { {"_link_create", wrapLinkCreate, this->orgLinkCreate, kLinkCreatePattern, kLinkCreateMask}, {"__ZN35AMDRadeonX6000_AmdRadeonFramebuffer25setAttributeForConnectionEijm", @@ -354,7 +373,7 @@ bool X6000FB::OnAppleBacklightDisplayLoad(void *, void *, IOService *newService, } void X6000FB::registerDispMaxBrightnessNotif() { - if (callback->dispNotif) { return; } + if (callback->dispNotif != nullptr) { return; } auto *matching = IOService::serviceMatching("AppleBacklightDisplay"); if (matching == nullptr) { @@ -374,11 +393,12 @@ IOReturn X6000FB::wrapSetAttributeForConnection(IOService *framebuffer, IOIndex connectIndex, attribute, value); if (attribute != FbAttributeBacklight) { return ret; } - if (callback->maxPwmBacklightLvl == 0) { return kIOReturnSuccess; } - if (callback->embeddedPanelLink == nullptr) { return kIOReturnNoDevice; } - - // Set the backlight callback->curPwmBacklightLvl = static_cast(value); + + if (callback->panelCntlPtr == nullptr || callback->embeddedPanelLink == nullptr) { return kIOReturnNoDevice; } + + if (callback->maxPwmBacklightLvl == 0) { return kIOReturnInternalError; } + UInt32 percentage = callback->curPwmBacklightLvl * 100 / callback->maxPwmBacklightLvl; // AMDGPU doesn't use AUX on HDR/SDR displays that can use it. Why? @@ -386,15 +406,18 @@ IOReturn X6000FB::wrapSetAttributeForConnection(IOService *framebuffer, IOIndex // TODO: Obtain the actual max brightness for the screen UInt32 auxValue = (callback->maxOLED * percentage) / 100; // dc_link_set_backlight_level_nits doesn't print the new backlight level, so we'll do it - DBGLOG("X6000FB", "setAttributeForConnection: New AUX brightness: %d millinits (%d nits)", auxValue, - (auxValue / 1000)); - if (callback->orgDcLinkSetBacklightLevelNits(callback->embeddedPanelLink, true, auxValue, 15000)) { - return kIOReturnSuccess; - } + DBGLOG("X6000FB", "%s: New AUX brightness: %d millinits (%d nits)", __FUNCTION__, auxValue, (auxValue / 1000)); + callback->orgDcLinkSetBacklightLevelNits(callback->embeddedPanelLink, true, auxValue, 15000); + } else if (NRed::callback->attributes.isRaven() && NRed::callback->attributes.isBigSurAndLater()) { + // XX: Use the old brightness logic for now on Raven + // until I can find out the actual problem with DMCU. + UInt32 pwmValue = percentage >= 100 ? 0x1FF00 : ((percentage * 0xFF) / 100) << 8U; + DBGLOG("X6000FB", "%s: New PWM brightness: 0x%X", __FUNCTION__, pwmValue); + callback->orgDceDriverSetBacklight(callback->panelCntlPtr, pwmValue); + return kIOReturnSuccess; } else { UInt32 pwmValue = (percentage * 0xFFFF) / 100; - DBGLOG("X6000FB", "setAttributeForConnection: New PWM brightness: 0x%X", pwmValue); - + DBGLOG("X6000FB", "%s: New PWM brightness: 0x%X", __FUNCTION__, pwmValue); if (callback->orgDcLinkSetBacklightLevel(callback->embeddedPanelLink, pwmValue, 0)) { return kIOReturnSuccess; } } @@ -459,6 +482,11 @@ void X6000FB::wrapDpReceiverPowerCtrl(void *link, bool power_on) { IOSleep(250); // Link needs a bit of delay to change power state } +UInt32 X6000FB::wrapDcePanelCntlHwInit(void *panelCntl) { + callback->panelCntlPtr = panelCntl; + return FunctionCast(wrapDcePanelCntlHwInit, callback->orgDcePanelCntlHwInit)(panelCntl); +} + void *X6000FB::wrapLinkCreate(void *data) { void *ret = FunctionCast(wrapLinkCreate, callback->orgLinkCreate)(data); @@ -480,7 +508,7 @@ void *X6000FB::wrapLinkCreate(void *data) { SYSLOG("X6000FB", "REPORT THIS TO THE DEVELOPERS AS SOON AS POSSIBLE!!!!"); } callback->embeddedPanelLink = ret; - if ((callback->dcLinkCapsField.get(ret) & DC_DPCD_EXT_CAPS_OLED) != 0) { callback->supportsAUX = true; } + callback->supportsAUX = (callback->dcLinkCapsField.get(ret) & DC_DPCD_EXT_CAPS_OLED) != 0; DBGLOG("X6000FB", "Will use %s for display brightness control.", callback->supportsAUX ? "AUX" : "DMCU"); } diff --git a/NootedRed/X6000FB.hpp b/NootedRed/X6000FB.hpp index 3eef8a3d..e50673dd 100644 --- a/NootedRed/X6000FB.hpp +++ b/NootedRed/X6000FB.hpp @@ -8,6 +8,7 @@ #include using t_MessageAccelerator = IOReturn (*)(void *that, UInt32 requestType, void *arg2, void *arg3, void *arg4); +using t_DceDriverSetBacklight = void (*)(void *panelCntl, UInt32 backlightPwm); using t_DcLinkSetBacklightLevel = bool (*)(void *link, UInt32 backlightPwm, UInt32 frameRamp); using t_DcLinkSetBacklightLevelNits = bool (*)(void *link, bool isHDR, UInt32 backlightMillinits, UInt32 transitionTimeMs); @@ -25,7 +26,7 @@ class X6000FB { ObjectField dcLinkCapsField {}; bool fixedVBIOS {false}; - UInt32 curPwmBacklightLvl {0}, maxPwmBacklightLvl {0xFF}; + UInt32 curPwmBacklightLvl {0}, maxPwmBacklightLvl {0xFFFF}; UInt32 maxOLED {1000 * 512}; IONotifier *dispNotif {nullptr}; void *embeddedPanelLink {nullptr}; @@ -39,6 +40,9 @@ class X6000FB { t_MessageAccelerator orgMessageAccelerator {nullptr}; mach_vm_address_t orgControllerPowerUp {0}; mach_vm_address_t orgDpReceiverPowerCtrl {0}; + t_DceDriverSetBacklight orgDceDriverSetBacklight {nullptr}; + mach_vm_address_t orgDcePanelCntlHwInit {0}; + void *panelCntlPtr {nullptr}; mach_vm_address_t orgLinkCreate {0}; t_DcLinkSetBacklightLevel orgDcLinkSetBacklightLevel {0}; t_DcLinkSetBacklightLevelNits orgDcLinkSetBacklightLevelNits {0}; @@ -58,6 +62,7 @@ class X6000FB { static void wrapIRQMGRWriteRegister(void *ctx, UInt64 index, UInt32 value); static UInt32 wrapControllerPowerUp(void *that); static void wrapDpReceiverPowerCtrl(void *link, bool power_on); + static UInt32 wrapDcePanelCntlHwInit(void *panelCntl); static void *wrapLinkCreate(void *data); static bool wrapInitWithPciInfo(void *that, void *pciDevice); static void wrapDoGPUPanic(char const *fmt, ...); @@ -69,10 +74,6 @@ class X6000FB { static const UInt8 kCailAsicCapsTablePattern[] = {0x6E, 0x00, 0x00, 0x00, 0x98, 0x67, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00}; -static const UInt8 kDceDriverSetBacklight[] = {0x55, 0x48, 0x89, 0xE5, 0x41, 0x57, 0x41, 0x56, 0x41, 0x55, 0x41, 0x54, - 0x53, 0x50, 0x41, 0x89, 0xF7, 0x49, 0x89, 0xFE, 0x31, 0xC0, 0x4C, 0x8D, 0x65, 0xD0, 0x41, 0x89, 0x04, 0x24, 0x4C, - 0x8D, 0x6D, 0xD4, 0x41, 0x89, 0x45, 0x00, 0x48, 0x8B, 0x7F, 0x08, 0x49, 0x8B, 0x46, 0x28, 0x8B, 0x70, 0x10}; - static const UInt8 kPopulateVramInfoPattern[] = {0x55, 0x48, 0x89, 0xE5, 0x41, 0x57, 0x41, 0x56, 0x53, 0x48, 0x81, 0xEC, 0x08, 0x01, 0x00, 0x00, 0x40, 0x89, 0xF0, 0x40, 0x89, 0xF0, 0x4C, 0x8D, 0xBD, 0xE0, 0xFE, 0xFF, 0xFF}; static const UInt8 kPopulateVramInfoMask[] = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, @@ -100,6 +101,19 @@ static const UInt8 kDpReceiverPowerCtrl[] = {0x55, 0x48, 0x89, 0xE5, 0x41, 0x57, static const UInt8 kDpReceiverPowerCtrl14_4[] = {0x55, 0x48, 0x89, 0xE5, 0x41, 0x57, 0x41, 0x56, 0x41, 0x54, 0x53, 0x48, 0x83, 0xEC, 0x10, 0x41, 0x89, 0xF7, 0xB0, 0x02, 0x44, 0x28, 0xF8}; +static const UInt8 kDcePanelCntlHwInitPattern[] = {0x55, 0x48, 0x89, 0xE5, 0x41, 0x57, 0x41, 0x56, 0x41, 0x55, 0x41, + 0x54, 0x53, 0x50, 0x49, 0x89, 0xFD, 0x4C, 0x8D, 0x45, 0xD4, 0x41, 0xC7, 0x00, 0x00, 0x00, 0x00, 0x00}; +static const UInt8 kDcePanelCntlHwInitPattern14_4[] = {0x55, 0x48, 0x89, 0xE5, 0x41, 0x57, 0x41, 0x56, 0x41, 0x54, 0x53, + 0x48, 0x83, 0xEC, 0x10, 0x48, 0x89, 0xFB, 0x4C, 0x8D, 0x45, 0xDC, 0x41, 0xC7, 0x00, 0x00, 0x00, 0x00, 0x00}; + +static const UInt8 kDceDriverSetBacklightPattern[] = {0x55, 0x48, 0x89, 0xE5, 0x41, 0x57, 0x41, 0x56, 0x41, 0x55, 0x41, + 0x54, 0x53, 0x50, 0x41, 0x89, 0xF0, 0x40, 0x89, 0xF0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x48, 0x8B, 0x7F, 0x08, 0x40, 0x8B, 0x40, 0x28, 0x8B, 0x70, 0x10}; +static const UInt8 kDceDriverSetBacklightPatternMask[] = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xF0, 0xF0, 0xFF, 0xF0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xF0, 0xFF, 0xF0, 0xFF, 0xFF, 0xFF, + 0xFF}; + static const UInt8 kLinkCreatePattern[] = {0x55, 0x48, 0x89, 0xE5, 0x41, 0x57, 0x41, 0x56, 0x41, 0x55, 0x41, 0x54, 0x53, 0x48, 0x81, 0xEC, 0x00, 0x03, 0x00, 0x00, 0x49, 0x89, 0xFD, 0x48, 0x8B, 0x05, 0x00, 0x00, 0x00, 0x00, 0x48, 0x8B, 0x00, 0x48, 0x00, 0x00, 0x00, 0xBF, 0x00, 0x00, 0x00, 0x00, 0xE8, 0x00, 0x00, 0x00, 0x00};