Hello,
I have contacted internal team for this, please see below:
This feature was not part of the SOW with Microsoft and as such was not implemented nor planed. We are occupied with testing of new BSP version at the moment, but we would like to have a look at after, if situation will allowed it.
Directions for the implementation of brightness control received from Microsoft are:
For brightness control in GPU/display driver, please direct the customer to Supporting Brightness Controls on Integrated Display Panels - Windows drivers | Microsoft Learn
We recommend the customer to implement DXGK_BRIGHTNESS_INTERFACE_2, Windows brightness UI calls into this interface's member functions for brightness control.
This interface should be exposed from GcKmBaseDisplayController::QueryInterface().
One quirk about the brightness interface is that QueryInterface->DeviceUid is DISPLAY_ADAPTER_HW_ID (-1)
Conceptually we can think of brightness as a global state, so monitors have the same brightness/Windows doesn't change brightness of monitors individually.
QueryInterface->Interface is a pointer of DXGK_BRIGHTNESS_INTERFACE_2, driver should follow MSDN doc to fill it in.
The GcKmBaseDisplayController pointer can be return as DXGK_BRIGHTNESS_INTERFACE_2::Context
For member functions of DXGK_BRIGHTNESS_INTERFACE_2, in general the Display Controller need to call Set functions for all active displays but handle Get functions by itself.
The customer is probably using the LVDS or MIPI display, so they need to add a SetBrightness() virtual function to GcKmBaseDisplay and GcKmImx8mpDisplay (for LVDS) or GcKmImx8mpMipiDsiDisplay (for MIPI).
Brightness control is not supported for external monitor like HDMI on Windows.
It is best that GcKmBaseDisplay::SetBrightness() has an empty/default implementation.
For sample code of driver interface, the customer can take a look at GcKmImx8mpHdmiDisplay::QueryInterface() for a custom audio interface.
It is possible the customer uses PWM or I2C to control the panel's brightness,
We do have some code for display controller to call into I2C driver, please see imx-windows-iot\driver\display\dispdll\os\windows\src\comm.cpp
PWM flow should be similar.
// The display controller's code is in imx-windows-iot\driver\display\dispdll
NTSTATUS GcKmBaseDisplayController::QueryInterface(
IN_PQUERY_INTERFACE QueryInterface)
{
NTSTATUS Status = STATUS_NOT_SUPPORTED;
GcKmDisplay* pDisplayPipeline = FindDisplayPipeline(QueryInterface->DeviceUid);
if (pDisplayPipeline) {
Status = pDisplayPipeline->QueryInterface(QueryInterface);
}
return Status;
}
3: kd> dv
this = 0xffffcd05`cc248000
QueryInterface = 0xfffff20f`6b0fb910
Status = <value unavailable>
//
// C:\Program Files (x86)\Windows Kits\10\Include\10.0.22000.0\km\dispmprt.h
// DEFINE_GUID(GUID_DEVINTERFACE_BRIGHTNESS_2, 0x148A3C98, 0x0ECD, 0x465A, 0xB6, 0x34, 0xB0, 0x5F, 0x19, 0x5F, 0x77, 0x39);
3: kd> dx QueryInterface
QueryInterface : 0xfffff20f6b0fb910 [Type: _QUERY_INTERFACE *]
[+0x000] InterfaceType : 0xfffff80330750210 : {148A3C98-0ECD-465A-B634-B05F195F7739} [Type: _GUID *]
[+0x008] Size : 0x58 [Type: unsigned short]
[+0x00a] Version : 0x2 [Type: unsigned short]
[+0x010] Interface : 0xffffcd05caedd400 [Type: _INTERFACE *]
[+0x018] InterfaceSpecificData : 0x0 [Type: void *]
[+0x020] DeviceUid : 0xffffffff [Type: unsigned long]
//
// QueryInterface() comes directly from dxgkrnl.sys, not monitor.sys. Later on monitor.sys calls into driver through dxgkrnl.sys
3: kd> k
# Child-SP RetAddr Call Site
00 fffff20f`6b0fb800 fffff803`32e584e8 dispctrl!GcKmBaseDisplayController::QueryInterface+0x18 [C:\nxp-bsp\imx-windows-iot\driver\display\dispdll\GcKmdBaseDisplayController.cpp @ 174]
01 fffff20f`6b0fb830 fffff803`32e56b64 galcore!GcKmAdapter::QueryInterface+0x48 [N:\imx8m-3\drivers\wddmfw\lib\GcKmdAdapter.cpp @ 853]
02 fffff20f`6b0fb860 fffff803`3082d2c4 galcore!GcKmdDdi::DdiQueryInterface+0x64 [N:\imx8m-3\drivers\wddmfw\lib\GcKmdDdi.cpp @ 498]
03 fffff20f`6b0fb890 fffff803`3082d204 dxgkrnl!DpiDxgkDdiQueryInterface+0x74 [onecoreuap\windows\core\dxkernel\dxgkrnl\port\dpetw.cxx @ 412]
04 fffff20f`6b0fb900 fffff803`3082c1ac dxgkrnl!DpiQueryMiniportInterface+0x4c [onecoreuap\windows\core\dxkernel\dxgkrnl\port\dpsup.cxx @ 2461]
05 fffff20f`6b0fb950 fffff803`3082c3f0 dxgkrnl!DpiBrightnessSetupInterfaceV2+0x4c [onecoreuap\windows\core\dxkernel\dxgkrnl\port\dpbright.cxx @ 457]
06 fffff20f`6b0fb990 fffff803`3082b708 dxgkrnl!DpiBrightnessStartDevice+0x98 [onecoreuap\windows\core\dxkernel\dxgkrnl\port\dpbright.cxx @ 581]
07 fffff20f`6b0fb9c0 fffff803`3082a8d4 dxgkrnl!DpiFdoStartAdapter+0x830 [onecoreuap\windows\core\dxkernel\dxgkrnl\port\dpfdo.cxx @ 13704]
08 fffff20f`6b0fbae0 fffff803`30843084 dxgkrnl!DpiFdoStartAdapterThreadImpl+0x2a4 [onecoreuap\windows\core\dxkernel\dxgkrnl\port\dpfdo.cxx @ 14743]
09 fffff20f`6b0fbce0 fffff802`e6020f1c dxgkrnl!DpiFdoStartAdapterThread+0x34 [onecoreuap\windows\core\dxkernel\dxgkrnl\port\dpfdo.cxx @ 14207]
0a fffff20f`6b0fbd30 fffff802`e600c208 nt!PspSystemThreadStartup+0x4c [minkernel\ntos\ps\psexec.c @ 9746]
0b fffff20f`6b0fbd90 00000000`00000000 nt!KiStartSystemThread+0x20 [minkernel\ntos\ke\arm64\threadbg.asm @ 73]
//
// C:\Program Files (x86)\Windows Kits\10\Include\10.0.22000.0\km\dispmprt.h
typedef struct
{
IN USHORT Size;
IN USHORT Version;
OUT PVOID Context;
OUT PINTERFACE_REFERENCE InterfaceReference;
OUT PINTERFACE_DEREFERENCE InterfaceDereference;
OUT DXGK_BRIGHTNESS_GET_POSSIBLE GetPossibleBrightness;
OUT DXGK_BRIGHTNESS_SET SetBrightness;
OUT DXGK_BRIGHTNESS_GET GetBrightness;
OUT DXGK_BRIGHTNESS_GET_CAPS GetBrightnessCaps;
OUT DXGK_BRIGHTNESS_SET_STATE SetBrightnessState;
OUT DXGK_BRIGHTNESS_SET_BACKLIGHT_OPTIMIZATION SetBacklightOptimization;
OUT DXGK_BRIGHTNESS_GET_BACKLIGHT_REDUCTION GetBacklightReduction;
} DXGK_BRIGHTNESS_INTERFACE_2, *PDXGK_BRIGHTNESS_INTERFACE_2;
Best regards/Saludos,
Aldo.