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
27 #define DDC_EEPROM_ADDRESS 0xA0
29 /* PRIVATE FUNCTIONS **********************************************************/
35 #define READ_SDA() (i2c->ReadDataLine(HwDeviceExtension))
36 #define READ_SCL() (i2c->ReadClockLine(HwDeviceExtension))
37 #define WRITE_SDA(state) (i2c->WriteDataLine(HwDeviceExtension, state))
38 #define WRITE_SCL(state) (i2c->WriteClockLine(HwDeviceExtension, state))
40 static LARGE_INTEGER HalfPeriodDelay
= {{0, 70}};
41 #define DELAY_HALF() KeDelayExecutionThread(KernelMode, FALSE, &HalfPeriodDelay)
45 I2CWrite(PVOID HwDeviceExtension
, PI2C_CALLBACKS i2c
, UCHAR Data
)
51 for (Bit
= (1 << 7); Bit
!= 0; Bit
>>= 1)
54 WRITE_SDA((Data
& Bit
) ? HIGH
: LOW
);
69 while (READ_SCL() != HIGH
);
70 Ack
= (READ_SDA() == LOW
);
73 INFO_(VIDEOPRT
, "I2CWrite: %s\n", Ack
? "Ack" : "Nak");
79 I2CRead(PVOID HwDeviceExtension
, PI2C_CALLBACKS i2c
, BOOL Ack
)
84 /* pull down SCL and release SDA */
89 for (Bit
= (1 << 7); Bit
!= 0; Bit
>>= 1)
95 if (READ_SDA() == HIGH
)
101 WRITE_SDA(Ack
? LOW
: HIGH
);
108 while (READ_SCL() != HIGH
);
115 I2CStop(PVOID HwDeviceExtension
, PI2C_CALLBACKS i2c
)
127 I2CStart(PVOID HwDeviceExtension
, PI2C_CALLBACKS i2c
, UCHAR Address
)
129 /* make sure the bus is free */
130 if (READ_SDA() == LOW
|| READ_SCL() == LOW
)
132 WARN_(VIDEOPRT
, "I2CStart: Bus is not free!\n");
139 if (!I2CWrite(HwDeviceExtension
, i2c
, Address
))
141 /* ??release the bus?? */
142 I2CStop(HwDeviceExtension
, i2c
);
143 WARN_(VIDEOPRT
, "I2CStart: Device not found (Address = 0x%x)\n", Address
);
147 INFO_(VIDEOPRT
, "I2CStart: SUCCESS!\n");
153 I2CRepStart(PVOID HwDeviceExtension
, PI2C_CALLBACKS i2c
, UCHAR Address
)
155 /* setup lines for repeated start condition */
163 return I2CStart(HwDeviceExtension
, i2c
, Address
);
166 /* PUBLIC FUNCTIONS ***********************************************************/
173 VideoPortDDCMonitorHelper(
174 PVOID HwDeviceExtension
,
180 PDDC_CONTROL ddc
= (PDDC_CONTROL
)I2CFunctions
;
181 PI2C_CALLBACKS i2c
= &ddc
->I2CCallbacks
;
183 PUCHAR pBuffer
= (PUCHAR
)pEdidBuffer
;
186 TRACE_(VIDEOPRT
, "VideoPortDDCMonitorHelper()\n");
188 ASSERT_IRQL_LESS_OR_EQUAL(PASSIVE_LEVEL
);
189 if (ddc
->Size
!= sizeof (ddc
))
191 WARN_(VIDEOPRT
, "ddc->Size != %d (%d)\n", sizeof (ddc
), ddc
->Size
);
196 if (!I2CStart(HwDeviceExtension
, i2c
, DDC_EEPROM_ADDRESS
| WRITE
))
199 if (!I2CWrite(HwDeviceExtension
, i2c
, 0x00))
201 /* change into read mode */
202 if (!I2CRepStart(HwDeviceExtension
, i2c
, DDC_EEPROM_ADDRESS
| READ
))
205 RtlZeroMemory(pEdidBuffer
, EdidBufferSize
);
206 Count
= min(128, EdidBufferSize
);
207 for (i
= 0; i
< Count
; i
++)
209 Ack
= ((i
+ 1) < Count
);
210 pBuffer
[i
] = I2CRead(HwDeviceExtension
, i2c
, Ack
);
212 I2CStop(HwDeviceExtension
, i2c
);
214 /* check EDID header */
215 if (pBuffer
[0] != 0x00 || pBuffer
[1] != 0xff ||
216 pBuffer
[2] != 0xff || pBuffer
[3] != 0xff ||
217 pBuffer
[4] != 0xff || pBuffer
[5] != 0xff ||
218 pBuffer
[6] != 0xff || pBuffer
[7] != 0x00)
220 WARN_(VIDEOPRT
, "VideoPortDDCMonitorHelper(): Invalid EDID header!\n");
224 INFO_(VIDEOPRT
, "VideoPortDDCMonitorHelper(): EDID version %d rev. %d\n", pBuffer
[18], pBuffer
[19]);
225 INFO_(VIDEOPRT
, "VideoPortDDCMonitorHelper() - SUCCESS!\n");