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 Library General Public
8 * License as published by the Free Software Foundation; either
9 * version 2 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 * Library General Public License for more details.
16 * You should have received a copy of the GNU Library General Public
17 * License along with this library; see the file COPYING.LIB.
18 * If not, write to the Free Software Foundation,
19 * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
25 #define DDC_EEPROM_ADDRESS 0xA0
27 /* PRIVATE FUNCTIONS **********************************************************/
33 #define READ_SDA() (i2c->ReadDataLine(HwDeviceExtension))
34 #define READ_SCL() (i2c->ReadClockLine(HwDeviceExtension))
35 #define WRITE_SDA(state) (i2c->WriteDataLine(HwDeviceExtension, state))
36 #define WRITE_SCL(state) (i2c->WriteClockLine(HwDeviceExtension, state))
38 STATIC LARGE_INTEGER HalfPeriodDelay
= { { 70LL } };
39 #define DELAY_HALF() KeDelayExecutionThread(KernelMode, FALSE, &HalfPeriodDelay)
43 I2CWrite(PVOID HwDeviceExtension
, PI2C_CALLBACKS i2c
, UCHAR Data
)
49 for (Bit
= (1 << 7); Bit
!= 0; Bit
>>= 1)
52 WRITE_SDA((Data
& Bit
) ? HIGH
: LOW
);
67 while (READ_SCL() != HIGH
);
68 Ack
= (READ_SDA() == LOW
);
71 INFO_(VIDEOPRT
, "I2CWrite: %s\n", Ack
? "Ack" : "Nak");
77 I2CRead(PVOID HwDeviceExtension
, PI2C_CALLBACKS i2c
, BOOL Ack
)
82 /* pull down SCL and release SDA */
87 for (Bit
= (1 << 7); Bit
!= 0; Bit
>>= 1)
93 if (READ_SDA() == HIGH
)
99 WRITE_SDA(Ack
? LOW
: HIGH
);
106 while (READ_SCL() != HIGH
);
113 I2CStop(PVOID HwDeviceExtension
, PI2C_CALLBACKS i2c
)
125 I2CStart(PVOID HwDeviceExtension
, PI2C_CALLBACKS i2c
, UCHAR Address
)
127 /* make sure the bus is free */
128 if (READ_SDA() == LOW
|| READ_SCL() == LOW
)
130 WARN_(VIDEOPRT
, "I2CStart: Bus is not free!\n");
137 if (!I2CWrite(HwDeviceExtension
, i2c
, Address
))
139 /* ??release the bus?? */
140 I2CStop(HwDeviceExtension
, i2c
);
141 WARN_(VIDEOPRT
, "I2CStart: Device not found (Address = 0x%x)\n", Address
);
145 INFO_(VIDEOPRT
, "I2CStart: SUCCESS!\n");
151 I2CRepStart(PVOID HwDeviceExtension
, PI2C_CALLBACKS i2c
, UCHAR Address
)
153 /* setup lines for repeated start condition */
161 return I2CStart(HwDeviceExtension
, i2c
, Address
);
164 /* PUBLIC FUNCTIONS ***********************************************************/
171 VideoPortDDCMonitorHelper(
172 PVOID HwDeviceExtension
,
178 PDDC_CONTROL ddc
= (PDDC_CONTROL
)I2CFunctions
;
179 PI2C_CALLBACKS i2c
= &ddc
->I2CCallbacks
;
181 PUCHAR pBuffer
= (PUCHAR
)pEdidBuffer
;
184 TRACE_(VIDEOPRT
, "VideoPortDDCMonitorHelper()\n");
186 ASSERT_IRQL_LESS_OR_EQUAL(PASSIVE_LEVEL
);
187 if (ddc
->Size
!= sizeof (ddc
))
189 WARN_(VIDEOPRT
, "ddc->Size != %d (%d)\n", sizeof (ddc
), ddc
->Size
);
194 if (!I2CStart(HwDeviceExtension
, i2c
, DDC_EEPROM_ADDRESS
| WRITE
))
197 if (!I2CWrite(HwDeviceExtension
, i2c
, 0x00))
199 /* change into read mode */
200 if (!I2CRepStart(HwDeviceExtension
, i2c
, DDC_EEPROM_ADDRESS
| READ
))
203 RtlZeroMemory(pEdidBuffer
, EdidBufferSize
);
204 Count
= min(128, EdidBufferSize
);
205 for (i
= 0; i
< Count
; i
++)
207 Ack
= ((i
+ 1) < Count
);
208 pBuffer
[i
] = I2CRead(HwDeviceExtension
, i2c
, Ack
);
210 I2CStop(HwDeviceExtension
, i2c
);
212 /* check EDID header */
213 if (pBuffer
[0] != 0x00 || pBuffer
[1] != 0xff ||
214 pBuffer
[2] != 0xff || pBuffer
[3] != 0xff ||
215 pBuffer
[4] != 0xff || pBuffer
[5] != 0xff ||
216 pBuffer
[6] != 0xff || pBuffer
[7] != 0x00)
218 WARN_(VIDEOPRT
, "VideoPortDDCMonitorHelper(): Invalid EDID header!\n");
222 INFO_(VIDEOPRT
, "VideoPortDDCMonitorHelper(): EDID version %d rev. %d\n", pBuffer
[18], pBuffer
[19]);
223 INFO_(VIDEOPRT
, "VideoPortDDCMonitorHelper() - SUCCESS!\n");