]> git.saurik.com Git - apple/xnu.git/blob - iokit/Families/IOGraphics/AppleDDCDisplay.cpp
xnu-124.13.tar.gz
[apple/xnu.git] / iokit / Families / IOGraphics / AppleDDCDisplay.cpp
1 /*
2 * Copyright (c) 1998-2000 Apple Computer, Inc. All rights reserved.
3 *
4 * @APPLE_LICENSE_HEADER_START@
5 *
6 * The contents of this file constitute Original Code as defined in and
7 * are subject to the Apple Public Source License Version 1.1 (the
8 * "License"). You may not use this file except in compliance with the
9 * License. Please obtain a copy of the License at
10 * http://www.apple.com/publicsource and read it before using this file.
11 *
12 * This Original Code and all software distributed under the License are
13 * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER
14 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
15 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
16 * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the
17 * License for the specific language governing rights and limitations
18 * under the License.
19 *
20 * @APPLE_LICENSE_HEADER_END@
21 */
22 /*
23 * Copyright (c) 1997-1998 Apple Computer, Inc.
24 *
25 *
26 * HISTORY
27 *
28 * sdouglas 22 Oct 97 - first checked in.
29 * sdouglas 23 Jul 98 - start IOKit
30 * sdouglas 08 Dec 98 - start cpp
31 */
32
33 #include <IOKit/graphics/IODisplay.h>
34 #include <libkern/c++/OSContainers.h>
35 #include <IOKit/IOLib.h>
36
37 #include <IOKit/assert.h>
38
39 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
40
41 struct EDID {
42 UInt8 header[8];
43 UInt8 vendorProduct[4];
44 UInt8 serialNumber[4];
45 UInt8 weekOfManufacture;
46 UInt8 yearOfManufacture;
47 UInt8 version;
48 UInt8 revision;
49 UInt8 displayParams[5];
50 UInt8 colorCharacteristics[10];
51 UInt8 establishedTimings[3];
52 UInt16 standardTimings[8];
53 UInt8 detailedTimings[72];
54 UInt8 extension;
55 UInt8 checksum;
56 };
57
58 struct TimingToEDID {
59 UInt32 timingID;
60 UInt8 spare;
61 UInt8 establishedBit;
62 UInt16 standardTiming;
63 };
64
65 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
66
67 class AppleDDCDisplay : public IODisplay
68 {
69 OSDeclareDefaultStructors(AppleDDCDisplay)
70
71 private:
72 OSData * edidData;
73 OSData * additions;
74 OSData * deletions;
75 TimingToEDID * timingToEDID;
76 int numEDIDEntries;
77
78 public:
79 virtual IOService * probe( IOService * provider,
80 SInt32 * score );
81
82 virtual bool start( IOService * provider );
83
84 virtual IOReturn getConnectFlagsForDisplayMode(
85 IODisplayModeID mode, UInt32 * flags );
86 };
87
88 #undef super
89 #define super IODisplay
90
91 OSDefineMetaClassAndStructors(AppleDDCDisplay, IODisplay)
92
93 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
94
95 IOService * AppleDDCDisplay::probe( IOService * provider,
96 SInt32 * score )
97 {
98 IODisplayConnect * connect;
99 IOFramebuffer * framebuffer;
100 IOService * ret = 0;
101
102 do {
103
104 if( 0 == super::probe( provider, score ))
105 continue;
106
107 connect = getConnection();
108 framebuffer = connect->getFramebuffer();
109 assert( framebuffer );
110
111 if( kIOReturnSuccess != framebuffer->getAttributeForConnection(
112 connect->getConnection(),
113 kConnectionSupportsHLDDCSense, NULL ))
114 continue;
115
116 if( framebuffer->hasDDCConnect( connect->getConnection()))
117 ret = this;
118
119 } while( false);
120
121 return( ret );
122 }
123
124
125 bool AppleDDCDisplay::start( IOService * provider )
126 {
127 IOReturn err;
128 IODisplayConnect * connect;
129 IOFramebuffer * framebuffer;
130 OSData * data;
131 OSData * overrideData;
132 OSArray * array;
133 OSDictionary * dict;
134 OSNumber * off;
135 IOByteCount length;
136 EDID readEDID;
137 EDID * edid;
138 UInt32 vendorProd;
139 UInt32 index;
140 UInt32 numExts;
141
142 connect = getConnection();
143 framebuffer = connect->getFramebuffer();
144 assert( framebuffer );
145
146 do {
147 length = sizeof( EDID);
148 err = framebuffer->getDDCBlock( connect->getConnection(),
149 1, kIODDCBlockTypeEDID, 0, (UInt8 *) &readEDID, &length );
150 if( err || (length != sizeof( EDID)))
151 continue;
152
153 IOLog("%s EDID Version %d, Revision %d\n", framebuffer->getName(),
154 readEDID.version, readEDID.revision );
155 if( readEDID.version != 1)
156 continue;
157
158 if( (data = (OSData *) getProperty( "appleDDC" ))) {
159 timingToEDID = (TimingToEDID *) data->getBytesNoCopy();
160 numEDIDEntries = data->getLength() / sizeof(TimingToEDID);
161 } else
162 continue;
163
164 vendorProd = (readEDID.vendorProduct[0] << 24)
165 | (readEDID.vendorProduct[1] << 16)
166 | (readEDID.vendorProduct[2] << 8)
167 | (readEDID.vendorProduct[3] << 0);
168
169 #if 1
170 IOLog("Vendor/product 0x%08lx, ", vendorProd );
171 IOLog("Est: ");
172 for( index = 0; index < 3; index++)
173 IOLog(" 0x%02x,", readEDID.establishedTimings[ index ] );
174 IOLog("\nStd: " );
175 for( index = 0; index < 8; index++)
176 IOLog(" 0x%04x,", readEDID.standardTimings[ index ] );
177 IOLog("\n");
178 #endif
179
180 data = OSData::withBytes( &readEDID, sizeof( EDID ));
181 if( !data)
182 continue;
183
184 numExts = readEDID.extension;
185 for( index = 2; index < (2 + numExts); index++) {
186 length = sizeof( EDID);
187 err = framebuffer->getDDCBlock( connect->getConnection(),
188 index, kIODDCBlockTypeEDID, 0, (UInt8 *) &readEDID, &length );
189 if( err || (length != sizeof( EDID)))
190 break;
191 if( !data->appendBytes( &readEDID, sizeof( EDID ) ))
192 break;
193 }
194
195 overrideData = 0;
196 additions = 0;
197 if( (array = OSDynamicCast(OSArray, getProperty("overrides")))) {
198 for( index = 0;
199 (dict = OSDynamicCast(OSDictionary, array->getObject(index)));
200 index++ ) {
201 if( 0 == (off = OSDynamicCast(OSNumber, dict->getObject("ID"))))
202 continue;
203 if( vendorProd == off->unsigned32BitValue()) {
204 overrideData = OSDynamicCast(OSData,
205 dict->getObject( "EDID"));
206 additions = OSDynamicCast(OSData,
207 dict->getObject("additions"));
208 deletions = OSDynamicCast(OSData,
209 dict->getObject("deletions"));
210 break;
211 }
212 }
213 }
214
215 if( overrideData)
216 data = overrideData;
217
218 setProperty( kIODisplayEDIDKey, data );
219 data->release();
220 edidData = data;
221
222 edid = (EDID *) edidData->getBytesNoCopy();
223 // vendor
224 vendorProd = (edid->vendorProduct[0] << 8) | edid->vendorProduct[1];
225 setProperty( kDisplayVendorID, vendorProd, 32);
226 // product
227 vendorProd = (edid->vendorProduct[3] << 8) | edid->vendorProduct[2];
228 setProperty( kDisplayProductID, vendorProd, 32);
229
230 return( super::start( provider));
231
232 } while( false);
233
234 return( false);
235 }
236
237 IOReturn AppleDDCDisplay::getConnectFlagsForDisplayMode(
238 IODisplayModeID mode, UInt32 * flags )
239 {
240 IOReturn err;
241 IODisplayConnect * connect;
242 IOFramebuffer * framebuffer;
243 IOTimingInformation info;
244 const TimingToEDID * lookTiming;
245 UInt32 estBit, i;
246 EDID * edid;
247 UInt32 * dataModes;
248 UInt32 numData;
249 UInt32 appleTimingID;
250 bool supported = false;
251 bool deleted = false;
252 enum { kSetFlags = (kDisplayModeValidFlag
253 | kDisplayModeSafeFlag) };
254
255
256 connect = getConnection();
257 framebuffer = connect->getFramebuffer();
258 assert( framebuffer );
259
260 if( kIOReturnSuccess != framebuffer->connectFlags( connect->getConnection(),
261 mode, flags ))
262 *flags = 0;
263
264 err = framebuffer->getTimingInfoForDisplayMode( mode, &info );
265 if( err != kIOReturnSuccess)
266 return( err);
267
268 appleTimingID = info.appleTimingID;
269
270 if( deletions) {
271 numData = deletions->getLength() / sizeof( UInt32);
272 dataModes = (UInt32 *) deletions->getBytesNoCopy();
273 for( i = 0; (!deleted) && (i < numData); i++)
274 deleted = (dataModes[ i ] == appleTimingID);
275 }
276
277 if( !deleted) {
278
279 if( additions) {
280 numData = additions->getLength() / sizeof( UInt32);
281 dataModes = (UInt32 *) additions->getBytesNoCopy();
282 for( i = 0; (!supported) && (i < numData); i++)
283 supported = (dataModes[ i ] == appleTimingID);
284 }
285
286 edid = (EDID *) edidData->getBytesNoCopy();
287 assert( edid );
288 for( lookTiming = timingToEDID;
289 (!supported) && ((lookTiming - timingToEDID) < numEDIDEntries);
290 lookTiming++ ) {
291
292 if( lookTiming->timingID == appleTimingID) {
293 estBit = lookTiming->establishedBit;
294 if( estBit != 0xff)
295 supported = (0 != (edid->establishedTimings[ estBit / 8 ]
296 & (1 << (estBit % 8))));
297
298 for( i = 0; (!supported) && (i < 8); i++ )
299 supported = (lookTiming->standardTiming
300 == edid->standardTimings[i] );
301 }
302 }
303 }
304
305 if( supported)
306 *flags = ((*flags) & ~kDisplayModeSafetyFlags) | kSetFlags;
307
308 // Pass the existing flags (from framebuffer) thru
309 return( err);
310 }
311