ReactOS  0.4.15-dev-3303-g1ade494
edid.c
Go to the documentation of this file.
1 /*
2  * ReactOS VBE EDID management
3  *
4  * Copyright (C) 2006 Herv Poussineau
5  *
6  * This program is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU General Public License
8  * as published by the Free Software Foundation; either version 2
9  * of the License, or (at your option) any later version.
10  *
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License along
17  * with this program; if not, write to the Free Software Foundation, Inc.,
18  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
19  *
20  */
21 
22 /* INCLUDES *******************************************************************/
23 
24 #include "vbemp.h"
25 
26 /* PUBLIC AND PRIVATE FUNCTIONS ***********************************************/
27 
28 static VOID NTAPI
30  PVOID HwDeviceExtension,
31  UCHAR data)
32 {
33  INT10_BIOS_ARGUMENTS BiosRegisters;
34  PVBE_DEVICE_EXTENSION VBEDeviceExtension =
35  (PVBE_DEVICE_EXTENSION)HwDeviceExtension;
36 
37  VideoPortZeroMemory(&BiosRegisters, sizeof(BiosRegisters));
38  BiosRegisters.Eax = VBE_DDC;
39  BiosRegisters.Ebx = VBE_DDC_WRITE_SCL_CLOCK_LINE;
40  BiosRegisters.Ecx = VBEDeviceExtension->CurrentChildIndex;
41  BiosRegisters.Edx = data;
42  VBEDeviceExtension->Int10Interface.Int10CallBios(
43  VBEDeviceExtension->Int10Interface.Context,
44  &BiosRegisters);
45 }
46 
47 static VOID NTAPI
49  PVOID HwDeviceExtension,
50  UCHAR data)
51 {
52  INT10_BIOS_ARGUMENTS BiosRegisters;
53  PVBE_DEVICE_EXTENSION VBEDeviceExtension =
54  (PVBE_DEVICE_EXTENSION)HwDeviceExtension;
55 
56  VideoPortZeroMemory(&BiosRegisters, sizeof(BiosRegisters));
57  BiosRegisters.Eax = VBE_DDC;
58  BiosRegisters.Ebx = VBE_DDC_WRITE_SDA_DATA_LINE;
59  BiosRegisters.Ecx = VBEDeviceExtension->CurrentChildIndex;
60  BiosRegisters.Edx = data;
61  VBEDeviceExtension->Int10Interface.Int10CallBios(
62  VBEDeviceExtension->Int10Interface.Context,
63  &BiosRegisters);
64 }
65 
66 static BOOLEAN NTAPI
68  PVOID HwDeviceExtension)
69 {
70  INT10_BIOS_ARGUMENTS BiosRegisters;
71  PVBE_DEVICE_EXTENSION VBEDeviceExtension =
72  (PVBE_DEVICE_EXTENSION)HwDeviceExtension;
73 
74  VideoPortZeroMemory(&BiosRegisters, sizeof(BiosRegisters));
75  BiosRegisters.Eax = VBE_DDC;
76  BiosRegisters.Ebx = VBE_DDC_READ_SCL_CLOCK_LINE;
77  BiosRegisters.Ecx = VBEDeviceExtension->CurrentChildIndex;
78  VBEDeviceExtension->Int10Interface.Int10CallBios(
79  VBEDeviceExtension->Int10Interface.Context,
80  &BiosRegisters);
81 
82  return BiosRegisters.Edx;
83 }
84 
85 static BOOLEAN NTAPI
87  PVOID HwDeviceExtension)
88 {
89  INT10_BIOS_ARGUMENTS BiosRegisters;
90  PVBE_DEVICE_EXTENSION VBEDeviceExtension =
91  (PVBE_DEVICE_EXTENSION)HwDeviceExtension;
92 
93  VideoPortZeroMemory(&BiosRegisters, sizeof(BiosRegisters));
94  BiosRegisters.Eax = VBE_DDC;
95  BiosRegisters.Ebx = VBE_DDC_READ_SDA_DATA_LINE;
96  BiosRegisters.Ecx = VBEDeviceExtension->CurrentChildIndex;
97  VBEDeviceExtension->Int10Interface.Int10CallBios(
98  VBEDeviceExtension->Int10Interface.Context,
99  &BiosRegisters);
100 
101  return BiosRegisters.Edx;
102 }
103 
104 static BOOLEAN
106  IN PVOID HwDeviceExtension,
107  IN ULONG ChildIndex,
108  OUT PVOID Edid)
109 {
110  INT10_BIOS_ARGUMENTS BiosRegisters;
111  PVBE_DEVICE_EXTENSION VBEDeviceExtension =
112  (PVBE_DEVICE_EXTENSION)HwDeviceExtension;
113  DDC_CONTROL DDCControl;
114  BOOLEAN ret;
115 
116  VideoPortDebugPrint(Trace, "VBEMP: VBEReadEdidUsingSCI() called\n");
117 
118  /*
119  * Check if graphic card support IC interface
120  */
121  VideoPortZeroMemory(&BiosRegisters, sizeof(BiosRegisters));
122  BiosRegisters.Eax = VBE_DDC;
123  BiosRegisters.Ebx = VBE_DDC_REPORT_CAPABILITIES;
124  BiosRegisters.Ecx = ChildIndex;
125  VBEDeviceExtension->Int10Interface.Int10CallBios(
126  VBEDeviceExtension->Int10Interface.Context,
127  &BiosRegisters);
128  if (VBE_GETRETURNCODE(BiosRegisters.Eax) != VBE_SUCCESS)
129  return FALSE;
130  VideoPortDebugPrint(Info, "VBEMP: VBE/SCI version %x\n", BiosRegisters.Ecx);
131  if ((BiosRegisters.Ebx & 0xF) != 0xF)
132  return FALSE;
133 
134  /*
135  * Enable IC interface
136  */
137  VideoPortZeroMemory(&BiosRegisters, sizeof(BiosRegisters));
138  BiosRegisters.Eax = VBE_DDC;
139  BiosRegisters.Ebx = VBE_DDC_BEGIN_SCL_SDA_CONTROL;
140  BiosRegisters.Ecx = ChildIndex;
141  VBEDeviceExtension->Int10Interface.Int10CallBios(
142  VBEDeviceExtension->Int10Interface.Context,
143  &BiosRegisters);
144  if (VBE_GETRETURNCODE(BiosRegisters.Eax) != VBE_SUCCESS)
145  return FALSE;
146 
147  /*
148  * Read EDID information
149  */
150  VBEDeviceExtension->CurrentChildIndex = ChildIndex;
151  DDCControl.Size = sizeof(DDC_CONTROL);
156  DDCControl.EdidSegment = 0;
158  HwDeviceExtension,
159  &DDCControl,
160  (PUCHAR)&Edid,
162 
163  /*
164  * Disable IC interface
165  */
166  VideoPortZeroMemory(&BiosRegisters, sizeof(BiosRegisters));
167  BiosRegisters.Eax = VBE_DDC;
168  BiosRegisters.Ebx = VBE_DDC_END_SCL_SDA_CONTROL;
169  VBEDeviceExtension->Int10Interface.Int10CallBios(
170  VBEDeviceExtension->Int10Interface.Context,
171  &BiosRegisters);
172  /* Ignore the possible error, as we did our best to prevent problems */
173 
174  return ret;
175 }
176 
177 static BOOLEAN
179  IN PVBE_DEVICE_EXTENSION VBEDeviceExtension,
180  IN ULONG ChildIndex,
181  OUT PVOID Edid)
182 {
183  INT10_BIOS_ARGUMENTS BiosRegisters;
184 
185  VideoPortDebugPrint(Trace, "VBEMP: VBEReadEdid() called\n");
186 
187  /*
188  * Check if DDC1/DDC2 is supported
189  */
190  VideoPortZeroMemory(&BiosRegisters, sizeof(BiosRegisters));
191  BiosRegisters.Eax = VBE_DDC;
192  VBEDeviceExtension->Int10Interface.Int10CallBios(
193  VBEDeviceExtension->Int10Interface.Context,
194  &BiosRegisters);
195  if (VBE_GETRETURNCODE(BiosRegisters.Eax) != VBE_SUCCESS)
196  return FALSE;
197  if ((BiosRegisters.Ebx & 3) == 0)
198  return FALSE;
199 
200  /*
201  * Directly read EDID information
202  */
203  VideoPortZeroMemory(&BiosRegisters, sizeof(BiosRegisters));
204  BiosRegisters.Eax = VBE_DDC;
205  BiosRegisters.Ebx = VBE_DDC_READ_EDID;
206  BiosRegisters.Ecx = ChildIndex;
207  BiosRegisters.Edi = VBEDeviceExtension->TrampolineMemoryOffset;
208  BiosRegisters.SegEs = VBEDeviceExtension->TrampolineMemorySegment;
209  VBEDeviceExtension->Int10Interface.Int10CallBios(
210  VBEDeviceExtension->Int10Interface.Context,
211  &BiosRegisters);
212 
213  if (VBE_GETRETURNCODE(BiosRegisters.Eax) != VBE_SUCCESS)
214  return FALSE;
215 
216  /*
217  * Copy the EDID information to our buffer
218  */
219  VBEDeviceExtension->Int10Interface.Int10ReadMemory(
220  VBEDeviceExtension->Int10Interface.Context,
221  VBEDeviceExtension->TrampolineMemorySegment,
222  VBEDeviceExtension->TrampolineMemoryOffset,
223  Edid,
225 
226  return TRUE;
227 }
228 
231  IN PVOID HwDeviceExtension,
232  IN PVIDEO_CHILD_ENUM_INFO ChildEnumInfo,
233  OUT PVIDEO_CHILD_TYPE VideoChildType,
234  OUT PUCHAR pChildDescriptor,
235  OUT PULONG UId,
236  OUT PULONG pUnused)
237 {
238  PVBE_DEVICE_EXTENSION VBEDeviceExtension =
239  (PVBE_DEVICE_EXTENSION)HwDeviceExtension;
240  ULONG ChildIndex;
241 
242  /*
243  * We are called very early in device initialization, even before
244  * VBEInitialize is called. So, our Int10 interface is not set.
245  * Ignore this call, we will trigger another one later.
246  */
247  if (VBEDeviceExtension->Int10Interface.Size == 0)
249 
250  if (ChildEnumInfo->Size != sizeof(VIDEO_CHILD_ENUM_INFO))
251  {
252  VideoPortDebugPrint(Error, "VBEMP: Wrong VIDEO_CHILD_ENUM_INFO structure size\n");
254  }
255  else if (ChildEnumInfo->ChildDescriptorSize < MAX_SIZE_OF_EDID)
256  {
257  VideoPortDebugPrint(Warn, "VBEMP: Too small buffer for EDID\n");
259  }
260  else if (ChildEnumInfo->ChildIndex == DISPLAY_ADAPTER_HW_ID)
261  {
262  *VideoChildType = VideoChip;
263  *UId = 0;
264  return VIDEO_ENUM_MORE_DEVICES; /* FIXME: not sure... */
265  }
266 
267  /*
268  * Get Child ID
269  */
270  if (ChildEnumInfo->ChildIndex != 0)
271  ChildIndex = ChildEnumInfo->ChildIndex;
272  else
273  ChildIndex = ChildEnumInfo->ACPIHwId;
274  VideoPortDebugPrint(Info, "VBEMP: ChildEnumInfo->ChildIndex %lu, ChildEnumInfo->ACPIHwId %lu => %lu\n",
275  ChildEnumInfo->ChildIndex, ChildEnumInfo->ACPIHwId, ChildIndex);
276 
277  /*
278  * Try to read EDID information using 2 different methods.
279  */
280  if (VBEReadEdid(HwDeviceExtension, ChildIndex, pChildDescriptor))
281  {
282  VideoPortDebugPrint(Info, "VBEMP: EDID information read directly\n");
283  }
284  else if (VBEReadEdidUsingSCI(HwDeviceExtension, ChildIndex, pChildDescriptor))
285  {
286  VideoPortDebugPrint(Info, "VBEMP: EDID information read using IC\n");
287  }
288  else if (ChildEnumInfo->ChildIndex == 1)
289  {
290  /* We must have 1 monitor, so just report it with no EDID information */
291  VideoPortDebugPrint(Info, "VBEMP: Reporting monitor with no EDID information\n");
292  }
293  else
294  {
295  VideoPortDebugPrint(Warn, "VBEMP: Unable to read EDID information\n");
297  }
298 
299  /*
300  * Fill return data
301  */
302  *VideoChildType = Monitor;
303  if (ChildIndex == 0)
304  {
305  /*
306  * This is the actual display adapter
307  */
308  *UId = DISPLAY_ADAPTER_HW_ID;
309  }
310  else
311  *UId = ChildIndex;
312  *pUnused = 0;
314 }
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)
Definition: edid.c:230
#define DISPLAY_ADAPTER_HW_ID
Definition: video.h:115
static BOOLEAN NTAPI VBEReadClockLine(PVOID HwDeviceExtension)
Definition: edid.c:67
#define IN
Definition: typedefs.h:39
IN UCHAR EdidSegment
Definition: video.h:700
#define TRUE
Definition: types.h:120
unsigned char * PUCHAR
Definition: retypes.h:3
#define VBE_DDC_READ_SDA_DATA_LINE
Definition: vbemp.h:80
#define VBE_GETRETURNCODE(x)
Definition: vbemp.h:100
static BOOLEAN VBEReadEdid(IN PVBE_DEVICE_EXTENSION VBEDeviceExtension, IN ULONG ChildIndex, OUT PVOID Edid)
Definition: edid.c:178
#define VBE_DDC_WRITE_SDA_DATA_LINE
Definition: vbemp.h:78
VPAPI VOID NTAPI VideoPortZeroMemory(IN PVOID Destination, IN ULONG Length)
IN I2C_CALLBACKS I2CCallbacks
Definition: video.h:699
_Must_inspect_result_ _In_ WDFCHILDLIST _In_ PWDF_CHILD_LIST_ITERATOR _Out_ WDFDEVICE _Inout_opt_ PWDF_CHILD_RETRIEVE_INFO Info
Definition: wdfchildlist.h:683
#define VBE_DDC_WRITE_SCL_CLOCK_LINE
Definition: vbemp.h:77
#define VBE_SUCCESS
Definition: vbemp.h:95
NTSTATUS(* NTAPI)(IN PFILE_FULL_EA_INFORMATION EaBuffer, IN ULONG EaLength, OUT PULONG ErrorOffset)
Definition: IoEaTest.cpp:117
#define FALSE
Definition: types.h:117
static BOOLEAN VBEReadEdidUsingSCI(IN PVOID HwDeviceExtension, IN ULONG ChildIndex, OUT PVOID Edid)
Definition: edid.c:105
unsigned char BOOLEAN
IN PVIDEO_READ_CLOCK_LINE ReadClockLine
Definition: video.h:372
IN PVIDEO_READ_DATA_LINE ReadDataLine
Definition: video.h:373
#define VBE_DDC_READ_SCL_CLOCK_LINE
Definition: vbemp.h:79
static BOOLEAN NTAPI VBEReadDataLine(PVOID HwDeviceExtension)
Definition: edid.c:86
#define VIDEO_ENUM_MORE_DEVICES
Definition: video.h:139
#define VBE_DDC
Definition: vbemp.h:67
IN PVIDEO_WRITE_CLOCK_LINE WriteClockLine
Definition: video.h:370
#define VBE_DDC_END_SCL_SDA_CONTROL
Definition: vbemp.h:76
Definition: video.h:581
#define VBE_DDC_BEGIN_SCL_SDA_CONTROL
Definition: vbemp.h:75
#define MAX_SIZE_OF_EDID
Definition: vbemp.h:187
BOOL Error
Definition: chkdsk.c:66
GLint GLenum GLsizei GLsizei GLsizei GLint GLsizei const GLvoid * data
Definition: gl.h:1950
struct _DDC_CONTROL DDC_CONTROL
IN PVIDEO_WRITE_DATA_LINE WriteDataLine
Definition: video.h:371
unsigned char UCHAR
Definition: xmlstorage.h:181
int ret
#define Trace(x)
Definition: inflate.c:42
VIDEO_PORT_INT10_INTERFACE Int10Interface
Definition: vbemp.h:194
ULONG CurrentChildIndex
Definition: vbemp.h:210
Definition: video.h:270
unsigned int * PULONG
Definition: retypes.h:1
struct VBE_DEVICE_EXTENSION * PVBE_DEVICE_EXTENSION
static VOID NTAPI VBEWriteClockLine(PVOID HwDeviceExtension, UCHAR data)
Definition: edid.c:29
IN ULONG Size
Definition: video.h:698
#define OUT
Definition: typedefs.h:40
unsigned int ULONG
Definition: retypes.h:1
OUT PINT10_CALL_BIOS Int10CallBios
Definition: video.h:782
LONG VP_STATUS
Definition: video.h:153
enum _VIDEO_CHILD_TYPE * PVIDEO_CHILD_TYPE
#define VBE_DDC_READ_EDID
Definition: vbemp.h:73
VPAPI VOID __cdecl VideoPortDebugPrint(IN VIDEO_DEBUG_LEVEL DebugPrintLevel, IN PSTR DebugMessage, IN ...)
static VOID NTAPI VBEWriteDataLine(PVOID HwDeviceExtension, UCHAR data)
Definition: edid.c:48
#define VIDEO_ENUM_NO_MORE_DEVICES
Definition: video.h:140
VPAPI BOOLEAN NTAPI VideoPortDDCMonitorHelper(IN PVOID HwDeviceExtension, IN PVOID DDCControl, IN OUT PUCHAR EdidBuffer, IN ULONG EdidBufferSize)
#define VBE_DDC_REPORT_CAPABILITIES
Definition: vbemp.h:74