Read EDID information from screen (if possible) in HwGetVideoChildDescriptor.

Still doesn't do anything useful with it, but that's a start ;)

svn path=/trunk/; revision=22237
This commit is contained in:
Hervé Poussineau 2006-06-05 16:31:24 +00:00
parent 56f9a0a548
commit 2a685bbbfe
4 changed files with 290 additions and 1 deletions

View file

@ -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;
}

View file

@ -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;
}

View file

@ -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 <poppack.h>
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,

View file

@ -2,6 +2,7 @@
<include base="vbemp">.</include>
<define name="__USE_W32API" />
<library>videoprt</library>
<file>edid.c</file>
<file>vbemp.c</file>
<file>vbemp.rc</file>
</module>