2 * ReactOS VBE EDID management
4 * Copyright (C) 2006 Hervé Poussineau
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.
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.
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.
22 /* INCLUDES *******************************************************************/
26 /* PUBLIC AND PRIVATE FUNCTIONS ***********************************************/
30 PVOID HwDeviceExtension
,
33 INT10_BIOS_ARGUMENTS BiosRegisters
;
34 PVBE_DEVICE_EXTENSION VBEDeviceExtension
=
35 (PVBE_DEVICE_EXTENSION
)HwDeviceExtension
;
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
,
49 PVOID HwDeviceExtension
,
52 INT10_BIOS_ARGUMENTS BiosRegisters
;
53 PVBE_DEVICE_EXTENSION VBEDeviceExtension
=
54 (PVBE_DEVICE_EXTENSION
)HwDeviceExtension
;
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
,
68 PVOID HwDeviceExtension
)
70 INT10_BIOS_ARGUMENTS BiosRegisters
;
71 PVBE_DEVICE_EXTENSION VBEDeviceExtension
=
72 (PVBE_DEVICE_EXTENSION
)HwDeviceExtension
;
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
,
82 return BiosRegisters
.Edx
;
87 PVOID HwDeviceExtension
)
89 INT10_BIOS_ARGUMENTS BiosRegisters
;
90 PVBE_DEVICE_EXTENSION VBEDeviceExtension
=
91 (PVBE_DEVICE_EXTENSION
)HwDeviceExtension
;
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
,
101 return BiosRegisters
.Edx
;
106 IN PVOID HwDeviceExtension
,
110 INT10_BIOS_ARGUMENTS BiosRegisters
;
111 PVBE_DEVICE_EXTENSION VBEDeviceExtension
=
112 (PVBE_DEVICE_EXTENSION
)HwDeviceExtension
;
113 DDC_CONTROL DDCControl
;
116 VideoPortDebugPrint(Trace
, "VBEMP: VBEReadEdidUsingSCI() called\n");
119 * Check if graphic card support I²C interface
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
,
128 if (VBE_GETRETURNCODE(BiosRegisters
.Eax
) != VBE_SUCCESS
)
130 VideoPortDebugPrint(Info
, "VBEMP: VBE/SCI version %x\n", BiosRegisters
.Ecx
);
131 if ((BiosRegisters
.Ebx
& 0xF) != 0xF)
135 * Enable I²C interface
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
,
144 if (VBE_GETRETURNCODE(BiosRegisters
.Eax
) != VBE_SUCCESS
)
148 * Read EDID information
150 VBEDeviceExtension
->CurrentChildIndex
= ChildIndex
;
151 DDCControl
.Size
= sizeof(DDC_CONTROL
);
152 DDCControl
.I2CCallbacks
.WriteClockLine
= VBEWriteClockLine
;
153 DDCControl
.I2CCallbacks
.WriteDataLine
= VBEWriteDataLine
;
154 DDCControl
.I2CCallbacks
.ReadClockLine
= VBEReadClockLine
;
155 DDCControl
.I2CCallbacks
.ReadDataLine
= VBEReadDataLine
;
156 DDCControl
.EdidSegment
= 0;
157 ret
= VideoPortDDCMonitorHelper(
164 * Disable I²C interface
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
,
172 /* Ignore the possible error, as we did our best to prevent problems */
179 IN PVBE_DEVICE_EXTENSION VBEDeviceExtension
,
183 INT10_BIOS_ARGUMENTS BiosRegisters
;
185 VideoPortDebugPrint(Trace
, "VBEMP: VBEReadEdid() called\n");
188 * Directly read EDID information
190 VideoPortZeroMemory(&BiosRegisters
, sizeof(BiosRegisters
));
191 BiosRegisters
.Eax
= VBE_DDC
;
192 BiosRegisters
.Ebx
= VBE_DDC_READ_EDID
;
193 BiosRegisters
.Ecx
= ChildIndex
;
194 BiosRegisters
.Edx
= 1;
195 BiosRegisters
.Edi
= VBEDeviceExtension
->TrampolineMemoryOffset
;
196 BiosRegisters
.SegEs
= VBEDeviceExtension
->TrampolineMemorySegment
;
197 VBEDeviceExtension
->Int10Interface
.Int10CallBios(
198 VBEDeviceExtension
->Int10Interface
.Context
,
201 if (VBE_GETRETURNCODE(BiosRegisters
.Eax
) != VBE_SUCCESS
)
205 * Copy the EDID information to our buffer
207 VBEDeviceExtension
->Int10Interface
.Int10ReadMemory(
208 VBEDeviceExtension
->Int10Interface
.Context
,
209 VBEDeviceExtension
->TrampolineMemorySegment
,
210 VBEDeviceExtension
->TrampolineMemoryOffset
,
218 VBEGetVideoChildDescriptor(
219 IN PVOID HwDeviceExtension
,
220 IN PVIDEO_CHILD_ENUM_INFO ChildEnumInfo
,
221 OUT PVIDEO_CHILD_TYPE VideoChildType
,
222 OUT PUCHAR pChildDescriptor
,
226 PVBE_DEVICE_EXTENSION VBEDeviceExtension
=
227 (PVBE_DEVICE_EXTENSION
)HwDeviceExtension
;
231 * We are called very early in device initialization, even before
232 * VBEInitialize is called. So, our Int10 interface is not set.
233 * Ignore this call, we will trigger another one later.
235 if (VBEDeviceExtension
->Int10Interface
.Size
== 0)
236 return VIDEO_ENUM_NO_MORE_DEVICES
;
238 if (ChildEnumInfo
->Size
!= sizeof(VIDEO_CHILD_ENUM_INFO
))
240 VideoPortDebugPrint(Error
, "VBEMP: Wrong VIDEO_CHILD_ENUM_INFO structure size\n");
241 return VIDEO_ENUM_NO_MORE_DEVICES
;
243 else if (ChildEnumInfo
->ChildDescriptorSize
< MAX_SIZE_OF_EDID
)
245 VideoPortDebugPrint(Warn
, "VBEMP: Too small buffer for EDID\n");
246 return VIDEO_ENUM_NO_MORE_DEVICES
;
248 else if (ChildEnumInfo
->ChildIndex
== DISPLAY_ADAPTER_HW_ID
)
250 *VideoChildType
= VideoChip
;
252 return VIDEO_ENUM_MORE_DEVICES
; /* FIXME: not sure... */
258 if (ChildEnumInfo
->ChildIndex
!= 0)
259 ChildIndex
= ChildEnumInfo
->ChildIndex
;
261 ChildIndex
= ChildEnumInfo
->ACPIHwId
;
262 VideoPortDebugPrint(Info
, "VBEMP: ChildEnumInfo->ChildIndex %lu, ChildEnumInfo->ACPIHwId %lu => %lu\n",
263 ChildEnumInfo
->ChildIndex
, ChildEnumInfo
->ACPIHwId
, ChildIndex
);
266 * Try to read EDID information using 2 different methods.
268 if (VBEReadEdid(HwDeviceExtension
, ChildIndex
, pChildDescriptor
))
270 VideoPortDebugPrint(Info
, "VBEMP: EDID information read directly\n");
272 else if (VBEReadEdidUsingSCI(HwDeviceExtension
, ChildIndex
, pChildDescriptor
))
274 VideoPortDebugPrint(Info
, "VBEMP: EDID information read using I²C\n");
276 else if (ChildEnumInfo
->ChildIndex
== 1)
278 /* We must have 1 monitor, so just report it with no EDID information */
279 VideoPortDebugPrint(Info
, "VBEMP: Reporting monitor with no EDID information\n");
283 VideoPortDebugPrint(Warn
, "VBEMP: Unable to read EDID information\n");
284 return VIDEO_ENUM_NO_MORE_DEVICES
;
290 *VideoChildType
= Monitor
;
294 * This is the actual display adapter
296 *UId
= DISPLAY_ADAPTER_HW_ID
;
301 return VIDEO_ENUM_MORE_DEVICES
;