Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

249 lines
6.4 KiB

  1. /*++
  2. Copyright (c) 1997 Microsoft Corporation
  3. Module Name:
  4. ddc.c
  5. Abstract:
  6. This module contains the code that support DDC querying..
  7. Environment:
  8. Kernel mode
  9. Revision History:
  10. --*/
  11. #include <dderror.h>
  12. #include <devioctl.h>
  13. #include <miniport.h>
  14. #include <ntddvdeo.h>
  15. #include <video.h>
  16. #include <cirrus.h>
  17. VOID WriteClockLine(PHW_DEVICE_EXTENSION HwDeviceExtension, UCHAR ucData);
  18. VOID WriteDataLine(PHW_DEVICE_EXTENSION HwDeviceExtension, UCHAR ucData);
  19. BOOLEAN ReadClockLine(PHW_DEVICE_EXTENSION HwDeviceExtension);
  20. BOOLEAN ReadDataLine(PHW_DEVICE_EXTENSION HwDeviceExtension);
  21. VOID WaitForVsyncActive(PHW_DEVICE_EXTENSION HwDeviceExtension);
  22. /****************************************************************
  23. ; DDC register
  24. ;
  25. ; Controls the individual toggling of bits in Sr8 to produce
  26. ; clock and data pulses.
  27. ;
  28. ; Sr8 is defined as follows:
  29. ;
  30. ; 7 ... 2 1 0 SCW = CLK Write
  31. ; |---|---|---|---|---| SDW = DATA Write
  32. ; |SDR ...|SCR|SDW|SCW| SCR = CLK Read
  33. ; --------------------- SDR = DATA Read
  34. ;
  35. ;****************************************************************/
  36. #define DDC_PORT (HwDeviceExtension->IOAddress + SEQ_DATA_PORT)
  37. #define STATUS_PORT (HwDeviceExtension->IOAddress + INPUT_STATUS_1_COLOR)
  38. #define VSYNC_ACTIVE 0x08
  39. VOID WriteClockLine(PHW_DEVICE_EXTENSION HwDeviceExtension, UCHAR ucData)
  40. {
  41. UCHAR ucPortData;
  42. //
  43. // read the current value and reset the clock line.
  44. //
  45. ucPortData = (VideoPortReadPortUchar(DDC_PORT) & 0xFE) | ucData;
  46. VideoPortWritePortUchar(DDC_PORT, ucPortData);
  47. }
  48. VOID WriteDataLine(PHW_DEVICE_EXTENSION HwDeviceExtension, UCHAR ucData)
  49. {
  50. UCHAR ucPortData;
  51. //
  52. // read the current value and reset the data line.
  53. //
  54. ucPortData = (VideoPortReadPortUchar(DDC_PORT) & 0xFD) | (ucData << 1);
  55. VideoPortWritePortUchar(DDC_PORT, ucPortData);
  56. }
  57. BOOLEAN ReadClockLine(PHW_DEVICE_EXTENSION HwDeviceExtension)
  58. {
  59. UCHAR uc;
  60. uc = VideoPortReadPortUchar(DDC_PORT);
  61. //VideoDebugPrint((0, "Read = 0x%x\n", uc));
  62. return ((VideoPortReadPortUchar(DDC_PORT) & 0x04) >> 2);
  63. }
  64. BOOLEAN ReadDataLine(PHW_DEVICE_EXTENSION HwDeviceExtension)
  65. {
  66. UCHAR uc;
  67. uc = VideoPortReadPortUchar(DDC_PORT);
  68. //VideoDebugPrint((0, "Read = 0x%x\n", uc));
  69. return ((VideoPortReadPortUchar(DDC_PORT) & 0x80) >> 7);
  70. }
  71. VOID WaitForVsyncActive(PHW_DEVICE_EXTENSION HwDeviceExtension)
  72. {
  73. while ((VideoPortReadPortUchar(STATUS_PORT) & VSYNC_ACTIVE) != 0);
  74. while ((VideoPortReadPortUchar(STATUS_PORT) & VSYNC_ACTIVE) == 0);
  75. }
  76. BOOLEAN
  77. GetDdcInformation(
  78. PHW_DEVICE_EXTENSION HwDeviceExtension,
  79. PUCHAR QueryBuffer,
  80. ULONG BufferSize)
  81. /*++
  82. Routine Description:
  83. Reads the basic EDID structure from the monitor using DDC2.
  84. Arguments:
  85. HwDeviceExtension - Points to per-adapter device extension.
  86. QueryBuffer - Buffer where information will be stored.
  87. BufferSize - Size of the buffer to fill.
  88. Return Value:
  89. Whether the call succeeded or not.
  90. --*/
  91. {
  92. UCHAR ucData;
  93. BOOLEAN bRet = FALSE;
  94. I2C_FNC_TABLE i2c;
  95. ULONG i;
  96. UCHAR OldSeqIdx;
  97. UCHAR ucSr6;
  98. UCHAR ucSr8;
  99. // workaround for Cirrus HW problem (part 1/2)
  100. static UCHAR onceQueryBuffer [512]; // EDID length is expected to be 128 or 256 bytes
  101. static UCHAR onceReadAttempt = FALSE;
  102. static UCHAR onceReturnedValue;
  103. if (onceReadAttempt) {
  104. VideoDebugPrint((1, "CIRRUS: ONCE READ => returning previously obtained data\n"));
  105. if (BufferSize > 512) {
  106. return FALSE;
  107. }
  108. memcpy (QueryBuffer, onceQueryBuffer, BufferSize);
  109. return onceReturnedValue;
  110. }
  111. // end of the workaround (part 1/2)
  112. OldSeqIdx = VideoPortReadPortUchar(HwDeviceExtension->IOAddress
  113. + SEQ_ADDRESS_PORT);
  114. //
  115. // Make sure the extension registers are unlocked.
  116. //
  117. VideoPortWritePortUchar(
  118. HwDeviceExtension->IOAddress + SEQ_ADDRESS_PORT,
  119. 0x6);
  120. ucSr6 = VideoPortReadPortUchar(
  121. HwDeviceExtension->IOAddress + SEQ_DATA_PORT);
  122. VideoPortWritePortUchar(
  123. HwDeviceExtension->IOAddress + SEQ_DATA_PORT,
  124. 0x12);
  125. VideoPortWritePortUchar(
  126. HwDeviceExtension->IOAddress + SEQ_ADDRESS_PORT,
  127. 0x08);
  128. ucSr8 = VideoPortReadPortUchar(
  129. HwDeviceExtension->IOAddress + SEQ_DATA_PORT);
  130. VideoPortWritePortUchar(
  131. HwDeviceExtension->IOAddress + SEQ_DATA_PORT,
  132. (UCHAR)(ucSr8 | 0x40));
  133. i2c.WriteClockLine = WriteClockLine;
  134. i2c.WriteDataLine = WriteDataLine;
  135. i2c.ReadClockLine = ReadClockLine;
  136. i2c.ReadDataLine = ReadDataLine;
  137. i2c.WaitVsync = WaitForVsyncActive;
  138. i2c.Size = sizeof(I2C_FNC_TABLE);
  139. // 5430/5440 has a problem doing DDC unless we wait for vsync first.
  140. if (HwDeviceExtension->ChipType == CL543x && HwDeviceExtension->ChipRevision == CL5430_ID)
  141. {
  142. WaitForVsyncActive(HwDeviceExtension);
  143. }
  144. bRet = VideoPortDDCMonitorHelper(HwDeviceExtension,
  145. &i2c,
  146. QueryBuffer,
  147. BufferSize);
  148. VideoPortWritePortUchar(
  149. HwDeviceExtension->IOAddress + SEQ_ADDRESS_PORT,
  150. 0x08);
  151. VideoPortWritePortUchar(
  152. HwDeviceExtension->IOAddress + SEQ_DATA_PORT,
  153. ucSr8);
  154. VideoPortWritePortUchar(
  155. HwDeviceExtension->IOAddress + SEQ_ADDRESS_PORT,
  156. 0x6);
  157. VideoPortWritePortUchar(
  158. HwDeviceExtension->IOAddress + SEQ_DATA_PORT,
  159. ucSr6);
  160. VideoPortWritePortUchar(
  161. HwDeviceExtension->IOAddress + SEQ_ADDRESS_PORT,
  162. OldSeqIdx);
  163. // workaround for Cirrus HW problem (part 2/2)
  164. onceReadAttempt = TRUE;
  165. onceReturnedValue = bRet;
  166. VideoDebugPrint((1, "CIRRUS: first EDID reading attempt "));
  167. if (onceReturnedValue)
  168. VideoDebugPrint((1, "succeeded"));
  169. else
  170. VideoDebugPrint((1, "failed"));
  171. VideoDebugPrint((1, " - the result saved\n"));
  172. memcpy (onceQueryBuffer, QueryBuffer, BufferSize);
  173. // end of the workaround (part 1/2)
  174. return bRet;
  175. }