diff --git a/reactos/drivers/video/miniport/vbe/edid.c b/reactos/drivers/video/miniport/vbe/edid.c new file mode 100644 index 00000000000..44ab41c63a7 --- /dev/null +++ b/reactos/drivers/video/miniport/vbe/edid.c @@ -0,0 +1,251 @@ +/* + * ReactOS VBE EDID management + * + * Copyright (C) 2006 Hervé Poussineau + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + */ + +/* INCLUDES *******************************************************************/ + +#include "vbemp.h" + +/* PUBLIC AND PRIVATE FUNCTIONS ***********************************************/ + +static VOID NTAPI +VBEWriteClockLine( + PVOID HwDeviceExtension, + UCHAR data) +{ + INT10_BIOS_ARGUMENTS BiosRegisters; + PVBE_DEVICE_EXTENSION VBEDeviceExtension = + (PVBE_DEVICE_EXTENSION)HwDeviceExtension; + + VideoPortZeroMemory(&BiosRegisters, sizeof(BiosRegisters)); + BiosRegisters.Eax = VBE_DDC; + BiosRegisters.Ebx = VBE_DDC_WRITE_SCL_CLOCK_LINE; + BiosRegisters.Ecx = data; + VBEDeviceExtension->Int10Interface.Int10CallBios( + VBEDeviceExtension->Int10Interface.Context, + &BiosRegisters); +} + +static VOID NTAPI +VBEWriteDataLine( + PVOID HwDeviceExtension, + UCHAR data) +{ + INT10_BIOS_ARGUMENTS BiosRegisters; + PVBE_DEVICE_EXTENSION VBEDeviceExtension = + (PVBE_DEVICE_EXTENSION)HwDeviceExtension; + + VideoPortZeroMemory(&BiosRegisters, sizeof(BiosRegisters)); + BiosRegisters.Eax = VBE_DDC; + BiosRegisters.Ebx = VBE_DDC_WRITE_SDA_DATA_LINE; + BiosRegisters.Ecx = data; + VBEDeviceExtension->Int10Interface.Int10CallBios( + VBEDeviceExtension->Int10Interface.Context, + &BiosRegisters); +} + +static BOOLEAN NTAPI +VBEReadClockLine( + PVOID HwDeviceExtension) +{ + INT10_BIOS_ARGUMENTS BiosRegisters; + PVBE_DEVICE_EXTENSION VBEDeviceExtension = + (PVBE_DEVICE_EXTENSION)HwDeviceExtension; + + VideoPortZeroMemory(&BiosRegisters, sizeof(BiosRegisters)); + BiosRegisters.Eax = VBE_DDC; + BiosRegisters.Ebx = VBE_DDC_READ_SCL_CLOCK_LINE; + VBEDeviceExtension->Int10Interface.Int10CallBios( + VBEDeviceExtension->Int10Interface.Context, + &BiosRegisters); + + return BiosRegisters.Edx; +} + +static BOOLEAN NTAPI +VBEReadDataLine( + PVOID HwDeviceExtension) +{ + INT10_BIOS_ARGUMENTS BiosRegisters; + PVBE_DEVICE_EXTENSION VBEDeviceExtension = + (PVBE_DEVICE_EXTENSION)HwDeviceExtension; + + VideoPortZeroMemory(&BiosRegisters, sizeof(BiosRegisters)); + BiosRegisters.Eax = VBE_DDC; + BiosRegisters.Ebx = VBE_DDC_READ_SDA_DATA_LINE; + VBEDeviceExtension->Int10Interface.Int10CallBios( + VBEDeviceExtension->Int10Interface.Context, + &BiosRegisters); + + return BiosRegisters.Edx; +} + +static BOOLEAN +VBEReadEdidUsingSCI( + PVOID HwDeviceExtension, + PVBE_EDID Edid) +{ + INT10_BIOS_ARGUMENTS BiosRegisters; + PVBE_DEVICE_EXTENSION VBEDeviceExtension = + (PVBE_DEVICE_EXTENSION)HwDeviceExtension; + DDC_CONTROL DDCControl; + BOOLEAN ret; + + VideoPortDebugPrint(Trace, "VBEMP: VBEReadEdidUsingSCI() called\n"); + + /* + * Check if graphic card support I²C interface + */ + VideoPortZeroMemory(&BiosRegisters, sizeof(BiosRegisters)); + BiosRegisters.Eax = VBE_DDC; + BiosRegisters.Ebx = VBE_DDC_REPORT_CAPABILITIES; + VBEDeviceExtension->Int10Interface.Int10CallBios( + VBEDeviceExtension->Int10Interface.Context, + &BiosRegisters); + if (BiosRegisters.Eax != VBE_SUCCESS) + return FALSE; + VideoPortDebugPrint(Info, "VBEMP: VBE/SCI version %x\n", BiosRegisters.Ecx); + if ((BiosRegisters.Ebx & 0xF) != 0xF) + return FALSE; + + /* + * Enable I²C interface + */ + VideoPortZeroMemory(&BiosRegisters, sizeof(BiosRegisters)); + BiosRegisters.Eax = VBE_DDC; + BiosRegisters.Ebx = VBE_DDC_BEGIN_SCL_SDA_CONTROL; + VBEDeviceExtension->Int10Interface.Int10CallBios( + VBEDeviceExtension->Int10Interface.Context, + &BiosRegisters); + if (BiosRegisters.Eax != VBE_SUCCESS) + return FALSE; + + /* + * Read EDID information + */ + DDCControl.Size = sizeof(DDC_CONTROL); + DDCControl.I2CCallbacks.WriteClockLine = VBEWriteClockLine; + DDCControl.I2CCallbacks.WriteDataLine = VBEWriteDataLine; + DDCControl.I2CCallbacks.ReadClockLine = VBEReadClockLine; + DDCControl.I2CCallbacks.ReadDataLine = VBEReadDataLine; + DDCControl.EdidSegment = 0; + ret = VideoPortDDCMonitorHelper( + HwDeviceExtension, + &DDCControl, + (PUCHAR)&Edid, + sizeof(VBE_EDID)); + + /* + * Disable I²C interface + */ + VideoPortZeroMemory(&BiosRegisters, sizeof(BiosRegisters)); + BiosRegisters.Eax = VBE_DDC; + BiosRegisters.Ebx = VBE_DDC_END_SCL_SDA_CONTROL; + VBEDeviceExtension->Int10Interface.Int10CallBios( + VBEDeviceExtension->Int10Interface.Context, + &BiosRegisters); + /* Ignore the possible error, as we did our best to prevent problems */ + + return ret; +} + +static BOOLEAN +VBEReadEdid( + PVBE_DEVICE_EXTENSION VBEDeviceExtension, + PVBE_EDID Edid) +{ + INT10_BIOS_ARGUMENTS BiosRegisters; + + VideoPortDebugPrint(Trace, "VBEMP: VBEReadEdid() called\n"); + + /* + * Directly read EDID information + */ + VideoPortZeroMemory(&BiosRegisters, sizeof(BiosRegisters)); + BiosRegisters.Eax = VBE_DDC; + BiosRegisters.Ebx = VBE_DDC_READ_EDID; + BiosRegisters.Edx = 1; + BiosRegisters.Edi = VBEDeviceExtension->TrampolineMemoryOffset; + BiosRegisters.SegEs = VBEDeviceExtension->TrampolineMemorySegment; + VBEDeviceExtension->Int10Interface.Int10CallBios( + VBEDeviceExtension->Int10Interface.Context, + &BiosRegisters); + + if (BiosRegisters.Eax != VBE_SUCCESS) + return FALSE; + + /* + * Copy the EDID information to our buffer + */ + VBEDeviceExtension->Int10Interface.Int10ReadMemory( + VBEDeviceExtension->Int10Interface.Context, + VBEDeviceExtension->TrampolineMemorySegment, + VBEDeviceExtension->TrampolineMemoryOffset, + Edid, + sizeof(VBE_EDID)); + + return TRUE; +} + +VP_STATUS NTAPI +VBEGetVideoChildDescriptor( + IN PVOID HwDeviceExtension, + IN PVIDEO_CHILD_ENUM_INFO ChildEnumInfo, + OUT PVIDEO_CHILD_TYPE VideoChildType, + OUT PUCHAR pChildDescriptor, + OUT PULONG UId, + OUT PULONG pUnused) +{ + PVBE_DEVICE_EXTENSION VBEDeviceExtension = + (PVBE_DEVICE_EXTENSION)HwDeviceExtension; + VBE_EDID Edid; + + /* + * We are called very early in device initialization, even before + * VBEInitialize is called. So, our Int10 interface is not set. + * Ignore this call, we will trigger it ourselves later. + */ + if (VBEDeviceExtension->Int10Interface.Size == 0) + return VIDEO_ENUM_NO_MORE_DEVICES; + + /* + * Try to read EDID information using 2 different methods. + */ + if (VBEReadEdid(HwDeviceExtension, &Edid)) + { + VideoPortDebugPrint(Info, "VBEMP: EDID information read directly\n"); + } + else if (VBEReadEdidUsingSCI(HwDeviceExtension, &Edid)) + { + VideoPortDebugPrint(Info, "VBEMP: EDID information read using I²C\n"); + } + else + { + VideoPortDebugPrint(Warn, "VBEMP: Unable to read EDID information\n"); + return VIDEO_ENUM_NO_MORE_DEVICES; + } + + /* + * Process the EDID data. + */ + /* FIXME */ + VideoPortDebugPrint(Error, "VBEMP: Need to parse EDID information\n"); + return VIDEO_ENUM_NO_MORE_DEVICES; +} diff --git a/reactos/drivers/video/miniport/vbe/vbemp.c b/reactos/drivers/video/miniport/vbe/vbemp.c index 4fdd349e8a4..3341867ab4d 100644 --- a/reactos/drivers/video/miniport/vbe/vbemp.c +++ b/reactos/drivers/video/miniport/vbe/vbemp.c @@ -44,6 +44,7 @@ DriverEntry(IN PVOID Context1, IN PVOID Context2) InitData.HwResetHw = VBEResetHw; InitData.HwGetPowerState = VBEGetPowerState; InitData.HwSetPowerState = VBESetPowerState; + InitData.HwGetVideoChildDescriptor = VBEGetVideoChildDescriptor; InitData.HwDeviceExtensionSize = sizeof(VBE_DEVICE_EXTENSION); return VideoPortInitialize(Context1, Context2, &InitData, NULL); @@ -377,7 +378,7 @@ VBEInitialize(PVOID HwDeviceExtension) VBESortModes(VBEDeviceExtension); /* - * Print the supported video modes when NDEBUG is not set. + * Print the supported video modes. */ for (CurrentMode = 0; @@ -390,6 +391,11 @@ VBEInitialize(PVOID HwDeviceExtension) VBEDeviceExtension->ModeInfo[CurrentMode].BitsPerPixel); } + /* + * Enumerate our children. + */ + VideoPortEnumerateChildren(HwDeviceExtension, NULL); + return TRUE; } diff --git a/reactos/drivers/video/miniport/vbe/vbemp.h b/reactos/drivers/video/miniport/vbe/vbemp.h index 52efd4092f6..c72544a7c13 100644 --- a/reactos/drivers/video/miniport/vbe/vbemp.h +++ b/reactos/drivers/video/miniport/vbe/vbemp.h @@ -71,6 +71,20 @@ #define VBE_AUDIO_INTERFACE_EXTENSIONS 0x4F12 #define VBE_OEM_EXTENSIONS 0x4F13 #define VBE_DISPLAY_DATA_CHANNEL 0x4F14 +#define VBE_DDC 0x4F15 + +/* + * VBE DDC Sub-Functions + */ + +#define VBE_DDC_READ_EDID 0x01 +#define VBE_DDC_REPORT_CAPABILITIES 0x10 +#define VBE_DDC_BEGIN_SCL_SDA_CONTROL 0x11 +#define VBE_DDC_END_SCL_SDA_CONTROL 0x12 +#define VBE_DDC_WRITE_SCL_CLOCK_LINE 0x13 +#define VBE_DDC_WRITE_SDA_DATA_LINE 0x14 +#define VBE_DDC_READ_SCL_CLOCK_LINE 0x15 +#define VBE_DDC_READ_SDA_DATA_LINE 0x16 /* * VBE Video Mode Information Definitions @@ -175,6 +189,11 @@ typedef struct CHAR Reserved4[189]; } VBE_MODEINFO, *PVBE_MODEINFO; +typedef struct +{ + UCHAR Reserved[128]; +} VBE_EDID, *PVBE_EDID; + #include typedef struct @@ -196,6 +215,18 @@ typedef struct USHORT CurrentMode; } VBE_DEVICE_EXTENSION, *PVBE_DEVICE_EXTENSION; +/* edid.c */ + +VP_STATUS NTAPI +VBEGetVideoChildDescriptor( + IN PVOID HwDeviceExtension, + IN PVIDEO_CHILD_ENUM_INFO ChildEnumInfo, + OUT PVIDEO_CHILD_TYPE VideoChildType, + OUT PUCHAR pChildDescriptor, + OUT PULONG UId, + OUT PULONG pUnused); + +/* vbemp.c */ VP_STATUS STDCALL VBEFindAdapter( IN PVOID HwDeviceExtension, diff --git a/reactos/drivers/video/miniport/vbe/vbemp.rbuild b/reactos/drivers/video/miniport/vbe/vbemp.rbuild index 52f7c86f4e8..ace6bb667c7 100644 --- a/reactos/drivers/video/miniport/vbe/vbemp.rbuild +++ b/reactos/drivers/video/miniport/vbe/vbemp.rbuild @@ -2,6 +2,7 @@ . videoprt + edid.c vbemp.c vbemp.rc