4 * Copyright (C) 2002, 2003, 2004 ReactOS Team
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
11 * This library 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 GNU
14 * Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
24 #define DDC_EEPROM_ADDRESS 0xA0
26 /* PRIVATE FUNCTIONS **********************************************************/
32 #define READ_SDA() (i2c->ReadDataLine(HwDeviceExtension))
33 #define READ_SCL() (i2c->ReadClockLine(HwDeviceExtension))
34 #define WRITE_SDA(state) (i2c->WriteDataLine(HwDeviceExtension, state))
35 #define WRITE_SCL(state) (i2c->WriteClockLine(HwDeviceExtension, state))
37 static LARGE_INTEGER HalfPeriodDelay
= {{0, 70}};
38 #define DELAY_HALF() KeDelayExecutionThread(KernelMode, FALSE, &HalfPeriodDelay)
42 I2CWrite(PVOID HwDeviceExtension
, PI2C_CALLBACKS i2c
, UCHAR Data
)
48 for (Bit
= (1 << 7); Bit
!= 0; Bit
>>= 1)
51 WRITE_SDA((Data
& Bit
) ? HIGH
: LOW
);
66 while (READ_SCL() != HIGH
);
67 Ack
= (READ_SDA() == LOW
);
70 INFO_(VIDEOPRT
, "I2CWrite: %s\n", Ack
? "Ack" : "Nak");
76 I2CRead(PVOID HwDeviceExtension
, PI2C_CALLBACKS i2c
, BOOL Ack
)
81 /* pull down SCL and release SDA */
86 for (Bit
= (1 << 7); Bit
!= 0; Bit
>>= 1)
92 if (READ_SDA() == HIGH
)
98 WRITE_SDA(Ack
? LOW
: HIGH
);
105 while (READ_SCL() != HIGH
);
112 I2CStop(PVOID HwDeviceExtension
, PI2C_CALLBACKS i2c
)
124 I2CStart(PVOID HwDeviceExtension
, PI2C_CALLBACKS i2c
, UCHAR Address
)
126 /* make sure the bus is free */
127 if (READ_SDA() == LOW
|| READ_SCL() == LOW
)
129 WARN_(VIDEOPRT
, "I2CStart: Bus is not free!\n");
136 if (!I2CWrite(HwDeviceExtension
, i2c
, Address
))
138 /* ??release the bus?? */
139 I2CStop(HwDeviceExtension
, i2c
);
140 WARN_(VIDEOPRT
, "I2CStart: Device not found (Address = 0x%x)\n", Address
);
144 INFO_(VIDEOPRT
, "I2CStart: SUCCESS!\n");
150 I2CRepStart(PVOID HwDeviceExtension
, PI2C_CALLBACKS i2c
, UCHAR Address
)
152 /* setup lines for repeated start condition */
160 return I2CStart(HwDeviceExtension
, i2c
, Address
);
163 /* PUBLIC FUNCTIONS ***********************************************************/
170 VideoPortDDCMonitorHelper(
171 PVOID HwDeviceExtension
,
177 PDDC_CONTROL ddc
= (PDDC_CONTROL
)I2CFunctions
;
178 PI2C_CALLBACKS i2c
= &ddc
->I2CCallbacks
;
180 PUCHAR pBuffer
= (PUCHAR
)pEdidBuffer
;
183 TRACE_(VIDEOPRT
, "VideoPortDDCMonitorHelper()\n");
185 ASSERT_IRQL_LESS_OR_EQUAL(PASSIVE_LEVEL
);
186 if (ddc
->Size
!= sizeof (ddc
))
188 WARN_(VIDEOPRT
, "ddc->Size != %d (%d)\n", sizeof (ddc
), ddc
->Size
);
193 if (!I2CStart(HwDeviceExtension
, i2c
, DDC_EEPROM_ADDRESS
| WRITE
))
196 if (!I2CWrite(HwDeviceExtension
, i2c
, 0x00))
198 /* change into read mode */
199 if (!I2CRepStart(HwDeviceExtension
, i2c
, DDC_EEPROM_ADDRESS
| READ
))
202 RtlZeroMemory(pEdidBuffer
, EdidBufferSize
);
203 Count
= min(128, EdidBufferSize
);
204 for (i
= 0; i
< Count
; i
++)
206 Ack
= ((i
+ 1) < Count
);
207 pBuffer
[i
] = I2CRead(HwDeviceExtension
, i2c
, Ack
);
209 I2CStop(HwDeviceExtension
, i2c
);
211 /* check EDID header */
212 if (pBuffer
[0] != 0x00 || pBuffer
[1] != 0xff ||
213 pBuffer
[2] != 0xff || pBuffer
[3] != 0xff ||
214 pBuffer
[4] != 0xff || pBuffer
[5] != 0xff ||
215 pBuffer
[6] != 0xff || pBuffer
[7] != 0x00)
217 WARN_(VIDEOPRT
, "VideoPortDDCMonitorHelper(): Invalid EDID header!\n");
221 INFO_(VIDEOPRT
, "VideoPortDDCMonitorHelper(): EDID version %d rev. %d\n", pBuffer
[18], pBuffer
[19]);
222 INFO_(VIDEOPRT
, "VideoPortDDCMonitorHelper() - SUCCESS!\n");