2 * Copyright (c) 1998-2000 Apple Computer, Inc. All rights reserved.
4 * @APPLE_LICENSE_HEADER_START@
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.
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
20 * @APPLE_LICENSE_HEADER_END@
23 * Copyright (c) 1997-1998 Apple Computer, Inc.
28 * sdouglas 22 Oct 97 - first checked in.
29 * sdouglas 23 Jul 98 - start IOKit
30 * sdouglas 08 Dec 98 - start cpp
33 #include <IOKit/graphics/IODisplay.h>
34 #include <libkern/c++/OSContainers.h>
35 #include <IOKit/IOLib.h>
37 #include <IOKit/assert.h>
39 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
43 UInt8 vendorProduct
[4];
44 UInt8 serialNumber
[4];
45 UInt8 weekOfManufacture
;
46 UInt8 yearOfManufacture
;
49 UInt8 displayParams
[5];
50 UInt8 colorCharacteristics
[10];
51 UInt8 establishedTimings
[3];
52 UInt16 standardTimings
[8];
53 UInt8 detailedTimings
[72];
62 UInt16 standardTiming
;
65 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
67 class AppleDDCDisplay
: public IODisplay
69 OSDeclareDefaultStructors(AppleDDCDisplay
)
75 TimingToEDID
* timingToEDID
;
79 virtual IOService
* probe( IOService
* provider
,
82 virtual bool start( IOService
* provider
);
84 virtual IOReturn
getConnectFlagsForDisplayMode(
85 IODisplayModeID mode
, UInt32
* flags
);
89 #define super IODisplay
91 OSDefineMetaClassAndStructors(AppleDDCDisplay
, IODisplay
)
93 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
95 IOService
* AppleDDCDisplay::probe( IOService
* provider
,
98 IODisplayConnect
* connect
;
99 IOFramebuffer
* framebuffer
;
104 if( 0 == super::probe( provider
, score
))
107 connect
= getConnection();
108 framebuffer
= connect
->getFramebuffer();
109 assert( framebuffer
);
111 if( kIOReturnSuccess
!= framebuffer
->getAttributeForConnection(
112 connect
->getConnection(),
113 kConnectionSupportsHLDDCSense
, NULL
))
116 if( framebuffer
->hasDDCConnect( connect
->getConnection()))
125 bool AppleDDCDisplay::start( IOService
* provider
)
128 IODisplayConnect
* connect
;
129 IOFramebuffer
* framebuffer
;
131 OSData
* overrideData
;
142 connect
= getConnection();
143 framebuffer
= connect
->getFramebuffer();
144 assert( framebuffer
);
147 length
= sizeof( EDID
);
148 err
= framebuffer
->getDDCBlock( connect
->getConnection(),
149 1, kIODDCBlockTypeEDID
, 0, (UInt8
*) &readEDID
, &length
);
150 if( err
|| (length
!= sizeof( EDID
)))
153 IOLog("%s EDID Version %d, Revision %d\n", framebuffer
->getName(),
154 readEDID
.version
, readEDID
.revision
);
155 if( readEDID
.version
!= 1)
158 if( (data
= (OSData
*) getProperty( "appleDDC" ))) {
159 timingToEDID
= (TimingToEDID
*) data
->getBytesNoCopy();
160 numEDIDEntries
= data
->getLength() / sizeof(TimingToEDID
);
164 vendorProd
= (readEDID
.vendorProduct
[0] << 24)
165 | (readEDID
.vendorProduct
[1] << 16)
166 | (readEDID
.vendorProduct
[2] << 8)
167 | (readEDID
.vendorProduct
[3] << 0);
170 IOLog("Vendor/product 0x%08lx, ", vendorProd
);
172 for( index
= 0; index
< 3; index
++)
173 IOLog(" 0x%02x,", readEDID
.establishedTimings
[ index
] );
175 for( index
= 0; index
< 8; index
++)
176 IOLog(" 0x%04x,", readEDID
.standardTimings
[ index
] );
180 data
= OSData::withBytes( &readEDID
, sizeof( EDID
));
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
)))
191 if( !data
->appendBytes( &readEDID
, sizeof( EDID
) ))
197 if( (array
= OSDynamicCast(OSArray
, getProperty("overrides")))) {
199 (dict
= OSDynamicCast(OSDictionary
, array
->getObject(index
)));
201 if( 0 == (off
= OSDynamicCast(OSNumber
, dict
->getObject("ID"))))
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"));
218 setProperty( kIODisplayEDIDKey
, data
);
222 edid
= (EDID
*) edidData
->getBytesNoCopy();
224 vendorProd
= (edid
->vendorProduct
[0] << 8) | edid
->vendorProduct
[1];
225 setProperty( kDisplayVendorID
, vendorProd
, 32);
227 vendorProd
= (edid
->vendorProduct
[3] << 8) | edid
->vendorProduct
[2];
228 setProperty( kDisplayProductID
, vendorProd
, 32);
230 return( super::start( provider
));
237 IOReturn
AppleDDCDisplay::getConnectFlagsForDisplayMode(
238 IODisplayModeID mode
, UInt32
* flags
)
241 IODisplayConnect
* connect
;
242 IOFramebuffer
* framebuffer
;
243 IOTimingInformation info
;
244 const TimingToEDID
* lookTiming
;
249 UInt32 appleTimingID
;
250 bool supported
= false;
251 bool deleted
= false;
252 enum { kSetFlags
= (kDisplayModeValidFlag
253 | kDisplayModeSafeFlag
) };
256 connect
= getConnection();
257 framebuffer
= connect
->getFramebuffer();
258 assert( framebuffer
);
260 if( kIOReturnSuccess
!= framebuffer
->connectFlags( connect
->getConnection(),
264 err
= framebuffer
->getTimingInfoForDisplayMode( mode
, &info
);
265 if( err
!= kIOReturnSuccess
)
268 appleTimingID
= info
.appleTimingID
;
271 numData
= deletions
->getLength() / sizeof( UInt32
);
272 dataModes
= (UInt32
*) deletions
->getBytesNoCopy();
273 for( i
= 0; (!deleted
) && (i
< numData
); i
++)
274 deleted
= (dataModes
[ i
] == appleTimingID
);
280 numData
= additions
->getLength() / sizeof( UInt32
);
281 dataModes
= (UInt32
*) additions
->getBytesNoCopy();
282 for( i
= 0; (!supported
) && (i
< numData
); i
++)
283 supported
= (dataModes
[ i
] == appleTimingID
);
286 edid
= (EDID
*) edidData
->getBytesNoCopy();
288 for( lookTiming
= timingToEDID
;
289 (!supported
) && ((lookTiming
- timingToEDID
) < numEDIDEntries
);
292 if( lookTiming
->timingID
== appleTimingID
) {
293 estBit
= lookTiming
->establishedBit
;
295 supported
= (0 != (edid
->establishedTimings
[ estBit
/ 8 ]
296 & (1 << (estBit
% 8))));
298 for( i
= 0; (!supported
) && (i
< 8); i
++ )
299 supported
= (lookTiming
->standardTiming
300 == edid
->standardTimings
[i
] );
306 *flags
= ((*flags
) & ~kDisplayModeSafetyFlags
) | kSetFlags
;
308 // Pass the existing flags (from framebuffer) thru