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 24 Jul 98 - start IOKit.
30 * sdouglas 15 Dec 98 - cpp.
34 #include <IOKit/IOLib.h>
35 #include <IOKit/IOPlatformExpert.h>
36 #include <IOKit/IODeviceTreeSupport.h>
37 #include <IOKit/IOLocks.h>
38 #include <IOKit/pwr_mgt/RootDomain.h>
39 #include <IOKit/ndrvsupport/IONDRVFramebuffer.h>
40 #include <IOKit/pci/IOAGPDevice.h>
41 #include <IOKit/assert.h>
43 #include <libkern/c++/OSContainers.h>
49 #define kAppleAudioVideoJackStateKey "AppleAudioVideoJackState"
51 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
53 class IOATINDRV
: public IONDRVFramebuffer
55 OSDeclareDefaultStructors(IOATINDRV
)
58 virtual IOReturn
getStartupDisplayMode( IODisplayModeID
* displayMode
,
60 virtual IODeviceMemory
* findVRAM( void );
64 class IOATI128NDRV
: public IOATINDRV
66 OSDeclareDefaultStructors(IOATI128NDRV
)
69 virtual void flushCursor( void );
72 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
75 class IONDRVFramebuffer
* framebuffer
;
77 IOFBInterruptProc handler
;
83 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
85 // IONDRVFramebuffer has two power states, off and on
87 enum { kIONDRVFramebufferPowerStateCount
= 2 };
89 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
91 #define super IOFramebuffer
93 OSDefineMetaClassAndStructors(IONDRVFramebuffer
, IOFramebuffer
)
95 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
101 IOService
* IONDRVFramebuffer::probe( IOService
* provider
,
104 IOService
* inst
= this;
105 IOService
* newInst
= 0;
108 if( !super::probe( provider
, score
))
111 if( 0 != provider
->getProperty(kIONDRVIgnoreKey
)) return( 0 );
113 if( /* IONDRV::fromRegistryEntry( provider ) || */ true) {
115 provider
->setProperty(kIONDRVForXKey
, this, sizeof(this) );
117 // temporary for in-kernel acceleration
118 name
= provider
->getName();
119 if( 0 == strncmp("ATY,Rage128", name
, strlen("ATY,Rage128")))
120 newInst
= new IOATI128NDRV
;
121 else if( 0 == strncmp("ATY,", name
, strlen("ATY,")))
122 newInst
= new IOATINDRV
;
125 if( ! newInst
->init( inst
->getPropertyTable())) {
137 IOReturn
IONDRVFramebuffer::setProperties( OSObject
* properties
)
141 IOReturn kr
= kIOReturnUnsupported
;
143 if( !(dict
= OSDynamicCast( OSDictionary
, properties
)))
144 return( kIOReturnBadArgument
);
146 if( (data
= OSDynamicCast(OSData
,
147 dict
->getObject("driver,AAPL,MacOS,PowerPC")))) {
150 return( kIOReturnStillOpen
);
154 nub
->setProperty("driver,AAPL,MacOS,PowerPC", data
);
155 nub
->removeProperty("AAPL,ndrvInst");
156 ndrv
= IONDRV::fromRegistryEntry( nub
, &_undefinedSymbolHandler
, (void *) this );
158 setName( ndrv
->driverName());
160 kr
= kIOReturnSuccess
;
166 static IOPMrootDomain
* gIOPMRootDomain
;
168 bool IONDRVFramebuffer::start( IOService
* provider
)
175 cachedVDResolution
.csDisplayModeID
= kDisplayModeIDInvalid
;
178 ndrv
= IONDRV::fromRegistryEntry( provider
, &_undefinedSymbolHandler
, this );
180 setName( ndrv
->driverName());
182 consoleDevice
= (0 != provider
->getProperty("AAPL,boot-display"));
185 if( 0 == nub
->getDeviceMemoryCount()) {
186 parent
= OSDynamicCast( IOService
, nub
->getParentEntry(gIODTPlane
));
188 parent
->getResources();
189 OSArray
* array
= parent
->getDeviceMemory();
191 nub
->setDeviceMemory( array
);
196 if( false == super::start( nub
))
199 if( !gIOPMRootDomain
)
200 gIOPMRootDomain
= (IOPMrootDomain
*)
201 IORegistryEntry::fromPath("/IOPowerConnection/IOPMrootDomain", gIOPowerPlane
);
203 platformDeepSleep
= (gIOPMRootDomain
->getSleepSupported()
204 & kFrameBufferDeepSleepSupported
) ? 1 : 0;
206 // default flags can be overriden
208 if(0 == strncmp("3Dfx", provider
->getName(), strlen("3Dfx")))
209 accessFlags
|= kFramebufferDisableAltivecAccess
;
211 if( (data
= OSDynamicCast( OSData
, provider
->getProperty(kIOFBHostAccessFlagsKey
))))
212 accessFlags
= *((UInt32
*) data
->getBytesNoCopy());
214 ok
= true; // Success
221 bool IONDRVFramebuffer::isConsoleDevice( void )
223 return( consoleDevice
);
226 // osfmk/ppc/mappings.h
227 extern "C" { extern void ignore_zero_fault(boolean_t
); }
229 IOReturn
IONDRVFramebuffer::enableController( void )
232 const char * logname
;
235 logname
= getProvider()->getName();
237 if( 0 == strcmp( "control", logname
))
238 waitForService( resourceMatching( "IOiic0" ));
241 err
= kIOReturnNotReady
;
243 err
= IONDRVLibrariesInitialize( getProvider() );
245 if( kIOReturnSuccess
== err
) do {
247 // find out about onboard audio/video jack state
248 // OSObject * notify =
249 addNotification( gIOPublishNotification
,
250 resourceMatching(kAppleAudioVideoJackStateKey
),
251 _videoJackStateChangeHandler
, this, 0 );
253 ignore_zero_fault( true );
255 ignore_zero_fault( false );
258 IOLog("%s: Not usable\n", logname
);
260 IOLog("%s: driver incompatible.\n", logname
);
263 getCurrentConfiguration();
264 vramMemory
= findVRAM();
266 // disable clamshell sleep on a single head portable
268 && (0 == OSDynamicCast( IOPCIDevice
, getProvider()))
269 && (data
= OSDynamicCast( OSData
,
270 getProvider()->getProperty("ATY,PanelActive")))) {
272 if( 0 == *((UInt32
*) data
->getBytesNoCopy()))
273 gIOPMRootDomain
->receivePowerNotification( kIOPMIgnoreClamshell
);
276 // initialize power management of the device
284 bool IONDRVFramebuffer::_videoJackStateChangeHandler( void * target
, void * ref
,
285 IOService
* resourceService
)
287 IONDRVFramebuffer
* self
= (IONDRVFramebuffer
*) target
;
291 OSObject
* jackValue
= resourceService
->getProperty(kAppleAudioVideoJackStateKey
);
295 jackData
= (jackValue
== kOSBooleanTrue
);
297 self
->nub
->setProperty( kAppleAudioVideoJackStateKey
, &jackData
, sizeof(jackData
) );
298 resourceService
->removeProperty(kAppleAudioVideoJackStateKey
);
303 IODeviceMemory
* IONDRVFramebuffer::getVRAMRange( void )
306 vramMemory
->retain();
308 return( vramMemory
);
311 const IOTVector
* IONDRVFramebuffer::_undefinedSymbolHandler( void * self
,
312 const char * libraryName
, const char * symbolName
)
314 return( ((IONDRVFramebuffer
*)self
)->undefinedSymbolHandler( libraryName
, symbolName
) );
317 const IOTVector
* IONDRVFramebuffer::undefinedSymbolHandler( const char * libraryName
,
318 const char * symbolName
)
323 void IONDRVFramebuffer::free( void )
328 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
330 IOReturn
IONDRVFramebuffer::registerForInterruptType( IOSelect interruptType
,
331 IOFBInterruptProc proc
, OSObject
* target
, void * ref
,
332 void ** interruptRef
)
335 _VSLService
* service
;
338 if( (interruptType
== kIOFBVBLInterruptType
)
339 && (getProvider()->getProperty("Ignore VBL")))
340 return( kIOReturnUnsupported
);
342 for( service
= vslServices
;
343 service
&& (service
->type
!= interruptType
);
344 service
= service
->next
) {}
348 if( service
->handler
)
352 service
->target
= target
;
354 service
->handler
= proc
;
355 *interruptRef
= service
;
356 err
= kIOReturnSuccess
;
360 err
= kIOReturnNoResources
;
365 IOReturn
IONDRVFramebuffer::unregisterInterrupt( void * interruptRef
)
367 _VSLService
* service
= (_VSLService
*) interruptRef
;
369 service
->handler
= 0;
371 return( kIOReturnSuccess
);
374 IOReturn
IONDRVFramebuffer::setInterruptState( void * interruptRef
,
377 return( kIOReturnUnsupported
);
380 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
384 OSStatus
IONDRVFramebuffer::VSLNewInterruptService(
386 IOSelect serviceType
,
387 _VSLService
** vslService
)
389 IORegistryEntry
* regEntry
;
390 IONDRVFramebuffer
* fb
;
391 _VSLService
* service
;
392 IOReturn err
= kIOReturnSuccess
;
394 REG_ENTRY_TO_OBJ( (const RegEntryID
*) entryID
, regEntry
)
396 fb
= OSDynamicCast( IONDRVFramebuffer
,
397 regEntry
->getChildEntry( gIOServicePlane
));
401 service
= IONew( _VSLService
, 1 );
404 service
->framebuffer
= fb
;
405 service
->type
= serviceType
;
406 service
->handler
= 0;
407 service
->next
= fb
->vslServices
;
408 fb
->vslServices
= service
;
410 *vslService
= service
;
413 err
= kIOReturnNoMemory
;
416 err
= kIOReturnBadArgument
;
421 OSStatus
IONDRVFramebuffer::VSLDisposeInterruptService(_VSLService
* vslService
)
423 IONDRVFramebuffer
* fb
;
429 fb
= vslService
->framebuffer
;
431 prev
= fb
->vslServices
;
432 if( prev
== vslService
)
433 fb
->vslServices
= vslService
->next
;
435 while( ((next
= prev
->next
) != vslService
) && next
)
438 prev
->next
= vslService
->next
;
441 IODelete( vslService
, _VSLService
, 1 );
444 return( kIOReturnSuccess
);
447 OSStatus
IONDRVFramebuffer::VSLDoInterruptService( _VSLService
* vslService
)
449 IOFBInterruptProc proc
;
452 if( (proc
= vslService
->handler
))
453 (*proc
) (vslService
->target
, vslService
->ref
);
456 return( kIOReturnSuccess
);
459 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
461 struct _VSLCursorRef
{
462 IOFramebuffer
* framebuffer
;
466 Boolean
IONDRVFramebuffer::VSLPrepareCursorForHardwareCursor(
468 IOHardwareCursorDescriptor
* hwDesc
,
469 IOHardwareCursorInfo
* hwCursorInfo
)
471 _VSLCursorRef
* cursor
= (_VSLCursorRef
*) cursorRef
;
474 if( hwCursorInfo
->colorMap
)
475 hwCursorInfo
->colorMap
+= 1;
476 ok
= cursor
->framebuffer
->convertCursorImage(
477 cursor
->cursorImage
, hwDesc
, hwCursorInfo
);
478 if( hwCursorInfo
->colorMap
)
479 hwCursorInfo
->colorMap
-= 1;
484 IOReturn
IONDRVFramebuffer::setCursorImage( void * cursorImage
)
486 _VSLCursorRef cursorRef
;
487 VDSetHardwareCursorRec setCursor
;
491 return( kIOReturnSuccess
);
493 cursorRef
.framebuffer
= this;
494 cursorRef
.cursorImage
= cursorImage
;
496 setCursor
.csCursorRef
= (void *) &cursorRef
;
497 setCursor
.csReserved1
= 0;
498 setCursor
.csReserved2
= 0;
500 err
= doControl( cscSetHardwareCursor
, &setCursor
);
505 IOReturn
IONDRVFramebuffer::setCursorState( SInt32 x
, SInt32 y
, bool visible
)
507 VDDrawHardwareCursorRec drawCursor
;
511 return( kIOReturnSuccess
);
513 if( 0 == OSIncrementAtomic( &ndrvEnter
))
516 drawCursor
.csCursorX
= x
;
517 drawCursor
.csCursorY
= y
;
518 drawCursor
.csCursorVisible
= visible
;
519 drawCursor
.csReserved1
= 0;
520 drawCursor
.csReserved2
= 0;
522 err
= doControl( cscDrawHardwareCursor
, &drawCursor
);
527 OSDecrementAtomic( &ndrvEnter
);
532 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
538 IOReturn
IONDRVFramebuffer::doControl( UInt32 code
, void * params
)
544 return( kIOReturnNotOpen
);
548 pb
.csParams
= params
;
550 OSIncrementAtomic( &ndrvEnter
);
551 err
= ndrv
->doDriverIO( /*ID*/ (UInt32
) &pb
, &pb
,
552 kControlCommand
, kImmediateIOCommandKind
);
553 OSDecrementAtomic( &ndrvEnter
);
558 IOReturn
IONDRVFramebuffer::doStatus( UInt32 code
, void * params
)
564 return( kIOReturnNotOpen
);
568 pb
.csParams
= params
;
570 OSIncrementAtomic( &ndrvEnter
);
571 err
= ndrv
->doDriverIO( /*ID*/ (UInt32
) &pb
, &pb
,
572 kStatusCommand
, kImmediateIOCommandKind
);
573 OSDecrementAtomic( &ndrvEnter
);
579 IOReturn
IONDRVFramebuffer::checkDriver( void )
581 OSStatus err
= noErr
;
582 struct DriverInitInfo initInfo
;
584 VDClutBehavior clutSetting
;
585 VDGammaRecord gammaRec
;
586 VDSwitchInfoRec switchInfo
;
587 IOTimingInformation info
;
590 if( ndrvState
== 0) {
592 initInfo
.refNum
= 0xffcd; // ...sure.
593 MAKE_REG_ENTRY(initInfo
.deviceEntry
, nub
)
595 err
= ndrv
->doDriverIO( 0, &initInfo
,
596 kInitializeCommand
, kImmediateIOCommandKind
);
599 err
= ndrv
->doDriverIO( 0, &pb
,
600 kOpenCommand
, kImmediateIOCommandKind
);
607 // allow calls to ndrv
610 if( (noErr
== doStatus( cscGetCurMode
, &switchInfo
))
611 && (noErr
== getTimingInfoForDisplayMode( switchInfo
.csData
, &info
))
612 && (timingApple_0x0_0hz_Offline
== info
.appleTimingID
)) {
614 IOLog("%s: display offline\n", getName());
615 err
= kIOReturnOffline
;
622 VDCommunicationInfoRec commInfo
;
624 bzero( &commInfo
, sizeof( commInfo
));
625 commInfo
.csBusID
= kVideoDefaultBus
;
627 err
= doStatus( cscGetCommunicationInfo
, &commInfo
);
628 IOLog("%s: cscGetCommunicationInfo: ", getName());
629 if( kIOReturnSuccess
!= err
) {
630 IOLog("fails with %ld\n", err
);
633 if( commInfo
.csSupportedTypes
& (1<<kVideoDDCciReplyType
) )
634 IOLog("supports kVideoDDCciReplyType, ");
635 if( commInfo
.csSupportedTypes
& (1<<kVideoSimpleI2CType
) ) {
636 IOLog("supports kVideoSimpleI2CType");
637 VDCommunicationRec comm
;
639 UInt8 edidRequest
[2];
645 edidData
[128] = 0xAA;
646 edidData
[129] = 0xAA;
647 edidData
[130] = 0xAA;
648 edidData
[131] = 0xAA;
650 memset( edidData
, 0xAA, sizeof( edidData
));
655 comm
.csBusID
= kVideoDefaultBus
;
656 comm
.csReserved0
= 0;
657 comm
.csReserved1
= 0;
658 comm
.csReserved2
= 0;
660 comm
.csSendAddress
= 0xA0;
661 comm
.csSendType
= kVideoSimpleI2CType
;
662 comm
.csSendBuffer
= &edidRequest
[0];
663 comm
.csSendSize
= 0x01;
665 comm
.csReplyAddress
= 0xA1;
666 comm
.csReplyType
= kVideoSimpleI2CType
;
667 comm
.csReplyBuffer
= &edidData
[0];
668 comm
.csReplySize
= 128;
670 comm
.csReserved3
= 0;
671 comm
.csReserved4
= 0;
672 comm
.csReserved5
= 0;
673 comm
.csReserved6
= 0;
676 err
= doControl( cscDoCommunication
, &comm
);
677 IOLog("\nI2C read block[%x](%ld)\n", edidRequest
[0], err
);
678 if( kIOReturnSuccess
!= err
)
680 IOLog(" 0 1 2 3 4 5 6 7 8 9 A B C D E F");
681 for( int i
= 0; i
< 128; i
++) {
683 IOLog("\n%02x: ", i
);
684 IOLog("%02x ", edidData
[i
]);
687 if( edidRequest
[0] || (0 == edidData
[126]))
689 edidRequest
[0] = 0x80;
694 #endif /* IONDRVI2CLOG */
696 // duplicate QD InitGDevice
697 pageInfo
.csMode
= switchInfo
.csMode
;
700 doControl( cscGrayPage
, &pageInfo
);
702 clutSetting
= kSetClutAtSetEntries
;
703 lastClutSetting
= clutSetting
;
704 doControl( cscSetClutBehavior
, &clutSetting
);
707 VDDisplayTimingRangeRec rangeRec
;
709 bzero( &rangeRec
, sizeof( rangeRec
));
710 err
= doStatus( cscGetTimingRanges
, &rangeRec
);
711 if( kIOReturnSuccess
!= err
)
714 setProperty( kIOFBTimingRangeKey
, &rangeRec
, sizeof( rangeRec
));
719 // bogus for ROM control
722 VDGetGammaListRec scan
;
723 VDRetrieveGammaRec get
;
727 scan
.csPreviousGammaTableID
= kGammaTableIDFindFirst
;
728 scan
.csGammaTableName
= name
;
729 err
= doStatus( cscGetGammaInfoList
, &scan
);
730 if( err
|| (scan
.csGammaTableID
== (GammaTableID
) kGammaTableIDNoMoreTables
))
733 table
= (GammaTbl
*)IOMalloc( scan
.csGammaTableSize
);
736 get
.csGammaTableID
= scan
.csGammaTableID
;
737 get
.csGammaTablePtr
= table
;
739 err
= doStatus( cscRetrieveGammaTable
, &get
);
741 kprintf("Setting gamma %s\n", scan
.csGammaTableName
);
742 gammaRec
.csGTable
= (Ptr
) table
;
743 doControl( cscSetGamma
, &gammaRec
);
746 IOFree( table
, scan
.csGammaTableSize
);
755 UInt32
IONDRVFramebuffer::iterateAllModes( IODisplayModeID
* displayModeIDs
)
757 VDResolutionInfoRec info
;
760 info
.csPreviousDisplayModeID
= kDisplayModeIDFindFirstResolution
;
763 (noErr
== doStatus( cscGetNextResolution
, &info
))
764 && ((SInt32
) info
.csDisplayModeID
> 0) ) {
767 displayModeIDs
[ num
] = info
.csDisplayModeID
;
769 info
.csPreviousDisplayModeID
= info
.csDisplayModeID
;
773 if( detailedTimings
) {
774 IOItemCount count
, i
;
776 count
= detailedTimings
->getCount();
777 if( displayModeIDs
) {
778 for( i
= 0; i
< count
; i
++)
779 displayModeIDs
[ num
+ i
] = kDisplayModeIDReservedBase
+ i
;
787 IOReturn
IONDRVFramebuffer::getResInfoForArbMode( IODisplayModeID modeID
,
788 IODisplayModeInformation
* info
)
790 VDVideoParametersInfoRec pixelParams
;
792 VDDetailedTimingRec
* detailed
;
796 err
= validateDisplayMode( modeID
, 0, &detailed
);
798 for( depth
= -1; err
== kIOReturnSuccess
; ) {
799 pixelParams
.csDisplayModeID
= modeID
;
800 pixelParams
.csDepthMode
= ++depth
+ kDepthMode1
;
801 pixelParams
.csVPBlockPtr
= &pixelInfo
;
802 err
= doStatus( cscGetVideoParameters
, &pixelParams
);
806 info
->maxDepthIndex
= depth
- 1;
807 info
->nominalWidth
= pixelInfo
.vpBounds
.right
;
808 info
->nominalHeight
= pixelInfo
.vpBounds
.bottom
;
810 info
->refreshRate
= detailed
->csPixelClock
* 65536ULL /
811 ((detailed
->csVerticalActive
+ detailed
->csVerticalBlanking
)
812 * (detailed
->csHorizontalActive
+ detailed
->csHorizontalBlanking
));
814 info
->refreshRate
= 0;
816 err
= kIOReturnSuccess
;
822 IOReturn
IONDRVFramebuffer::getResInfoForMode( IODisplayModeID modeID
,
823 IODisplayModeInformation
* info
)
826 bzero( info
, sizeof( *info
));
828 if( (UInt32
) modeID
>= (UInt32
) kDisplayModeIDReservedBase
)
829 return( getResInfoForArbMode( modeID
, info
));
831 // unfortunately, there is no "kDisplayModeIDFindSpecific"
832 if( cachedVDResolution
.csDisplayModeID
!= (UInt32
) modeID
) {
834 // try the next after cached mode
835 cachedVDResolution
.csPreviousDisplayModeID
= cachedVDResolution
.csDisplayModeID
;
836 if( (noErr
!= doStatus( cscGetNextResolution
, &cachedVDResolution
))
837 || (cachedVDResolution
.csDisplayModeID
!= (UInt32
) modeID
) ) {
839 // else full blown iterate
840 cachedVDResolution
.csPreviousDisplayModeID
= kDisplayModeIDFindFirstResolution
;
842 (noErr
== doStatus( cscGetNextResolution
, &cachedVDResolution
))
843 && (cachedVDResolution
.csDisplayModeID
!= (UInt32
) modeID
)
844 && ((SInt32
) cachedVDResolution
.csDisplayModeID
> 0)) {
846 cachedVDResolution
.csPreviousDisplayModeID
= cachedVDResolution
.csDisplayModeID
;
851 if( cachedVDResolution
.csDisplayModeID
!= (UInt32
) modeID
) {
852 cachedVDResolution
.csDisplayModeID
= kDisplayModeIDInvalid
;
853 return( kIOReturnUnsupportedMode
);
857 info
->maxDepthIndex
= cachedVDResolution
.csMaxDepthMode
- kDepthMode1
;
858 info
->nominalWidth
= cachedVDResolution
.csHorizontalPixels
;
859 info
->nominalHeight
= cachedVDResolution
.csVerticalLines
;
860 info
->refreshRate
= cachedVDResolution
.csRefreshRate
;
868 kDisplayModeIDPreflight
= kDisplayModeIDReservedBase
+ 1000
871 IOReturn
IONDRVFramebuffer::setDetailedTiming(
872 IODisplayModeID mode
, IOOptionBits options
,
873 void * _desc
, IOByteCount descripSize
)
876 VDResolutionInfoRec info
;
877 VDDetailedTimingRec
* desc
= (VDDetailedTimingRec
*)_desc
;
878 VDDetailedTimingRec look
;
880 bool notPreflight
= (0 == (options
& kModePreflight
));
882 // current must be ok
883 if( mode
== currentDisplayMode
)
884 return( kIOReturnSuccess
);
886 index
= mode
- kDisplayModeIDReservedBase
;
887 bzero( &look
, sizeof( VDDetailedTimingRec
) );
888 look
.csTimingSize
= sizeof( VDDetailedTimingRec
);
890 // look for a programmable
892 info
.csPreviousDisplayModeID
= kDisplayModeIDFindFirstProgrammable
;
893 (noErr
== (err
= doStatus( cscGetNextResolution
, &info
)));
894 info
.csPreviousDisplayModeID
= info
.csDisplayModeID
) {
896 if( (SInt32
) info
.csDisplayModeID
< 0) {
897 err
= kIOReturnNoResources
;
901 look
.csDisplayModeID
= info
.csDisplayModeID
;
902 err
= doStatus( cscGetDetailedTiming
, &look
);
903 if( err
!= kIOReturnSuccess
)
906 // don't toss current
907 if( look
.csDisplayModeAlias
== (UInt32
) currentDisplayMode
)
910 // see if already set to the right timing
911 if( (look
.csDisplayModeAlias
== (UInt32
) mode
)
912 && (look
.csDisplayModeState
== kDMSModeReady
)
914 && (detailedTimingsCurrent
[index
] == detailedTimingsSeed
))
918 if( look
.csDisplayModeState
!= kDMSModeFree
) {
919 look
.csDisplayModeID
= info
.csDisplayModeID
;
920 look
.csDisplayModeAlias
= 0;
921 look
.csDisplayModeState
= kDMSModeFree
;
922 err
= doControl( cscSetDetailedTiming
, &look
);
923 if( err
!= kIOReturnSuccess
)
927 desc
->csDisplayModeID
= info
.csDisplayModeID
;
928 desc
->csDisplayModeAlias
= mode
;
929 desc
->csDisplayModeSeed
= look
.csDisplayModeSeed
;
930 desc
->csDisplayModeState
= kDMSModeReady
;
931 err
= doControl( cscSetDetailedTiming
, desc
);
933 if( kIOReturnSuccess
== err
) {
935 // don't stomp orig record
937 err
= doStatus( cscGetDetailedTiming
, desc
);
939 if( notPreflight
&& (kIOReturnSuccess
== err
))
940 detailedTimingsCurrent
[index
] = detailedTimingsSeed
;
948 IOReturn
IONDRVFramebuffer::validateDisplayMode(
949 IODisplayModeID _mode
, IOOptionBits flags
,
950 VDDetailedTimingRec
** detailed
)
953 IOReturn err
= kIOReturnSuccess
;
958 *detailed
= (VDDetailedTimingRec
*) 0;
960 if( mode
>= (UInt32
) kDisplayModeIDReservedBase
) do {
962 if( mode
== (UInt32
) kDisplayModeIDBootProgrammable
)
965 err
= kIOReturnBadArgument
;
966 if( !detailedTimings
)
969 data
= OSDynamicCast( OSData
, detailedTimings
->getObject(
970 mode
- kDisplayModeIDReservedBase
));
974 bytes
= data
->getBytesNoCopy();
975 err
= setDetailedTiming( mode
, 0, (void *) bytes
, data
->getLength() );
976 if( err
!= kIOReturnSuccess
)
980 *detailed
= (VDDetailedTimingRec
*) bytes
;
987 void IONDRVFramebuffer::getCurrentConfiguration( void )
990 VDSwitchInfoRec switchInfo
;
991 VDGrayRecord grayRec
;
993 grayRec
.csMode
= 0; // turn off luminance map
994 err
= doControl( cscSetGray
, &grayRec
);
995 // driver refused => mono display
996 grayMode
= ((noErr
== err
) && (0 != grayRec
.csMode
));
998 err
= doStatus( cscGetCurMode
, &switchInfo
);
1000 currentDisplayMode
= switchInfo
.csData
;
1001 currentDepth
= switchInfo
.csMode
- kDepthMode1
;
1002 currentPage
= switchInfo
.csPage
;
1003 if( 0 == (physicalFramebuffer
= pmap_extract( kernel_pmap
,
1004 ((vm_address_t
) switchInfo
.csBaseAddr
) )))
1005 physicalFramebuffer
= (UInt32
) switchInfo
.csBaseAddr
;
1007 IOLog("%s: cscGetCurMode failed\n", nub
->getName());
1010 IODeviceMemory
* IONDRVFramebuffer::makeSubRange(
1011 IOPhysicalAddress start
,
1012 IOPhysicalLength length
)
1014 IODeviceMemory
* mem
= 0;
1019 numMaps
= device
->getDeviceMemoryCount();
1021 for( i
= 0; (!mem
) && (i
< numMaps
); i
++) {
1022 mem
= device
->getDeviceMemoryWithIndex(i
);
1025 mem
= IODeviceMemory::withSubRange( mem
,
1026 start
- mem
->getPhysicalAddress(), length
);
1029 mem
= IODeviceMemory::withRange( start
, length
);
1034 IODeviceMemory
* IONDRVFramebuffer::getApertureRange( IOPixelAperture aper
)
1037 IOPixelInformation info
;
1040 err
= getPixelInformation( currentDisplayMode
, currentDepth
, aper
,
1045 bytes
= (info
.bytesPerRow
* info
.activeHeight
) + 128;
1047 return( makeSubRange( physicalFramebuffer
, bytes
));
1050 IODeviceMemory
* IONDRVFramebuffer::findVRAM( void )
1052 VDVideoParametersInfoRec pixelParams
;
1054 VDResolutionInfoRec vdRes
;
1056 IOPhysicalAddress vramBase
= physicalFramebuffer
;
1057 IOByteCount vramLength
;
1062 prop
= OSDynamicCast( OSData
, nub
->getProperty("VRAM,memsize"));
1065 vramLength
= *((IOByteCount
*)prop
->getBytesNoCopy());
1067 vramLength
= (vramLength
+ (vramBase
& 0xffff)) & 0xffff0000;
1068 vramBase
&= 0xffff0000;
1074 vdRes
.csPreviousDisplayModeID
= kDisplayModeIDFindFirstResolution
;
1076 (noErr
== doStatus( cscGetNextResolution
, &vdRes
))
1077 && ((SInt32
) vdRes
.csDisplayModeID
> 0) )
1079 pixelParams
.csDisplayModeID
= vdRes
.csDisplayModeID
;
1080 pixelParams
.csDepthMode
= vdRes
.csMaxDepthMode
;
1081 pixelParams
.csVPBlockPtr
= &pixelInfo
;
1082 err
= doStatus( cscGetVideoParameters
, &pixelParams
);
1086 // Control hangs its framebuffer off the end of the aperture to support
1087 // 832 x 624 @ 32bpp. The commented out version will correctly calculate
1088 // the vram length, but DPS needs the full extent to be mapped, so we'll
1089 // end up mapping an extra page that will address vram through the
1090 // little endian aperture. No other drivers like this known.
1092 size
= 0x40 + pixelInfo
.vpBounds
.bottom
*
1093 (pixelInfo
.vpRowBytes
& 0x7fff);
1095 size
= ( (pixelInfo
.vpBounds
.right
* pixelInfo
.vpPixelSize
) / 8) // last line
1096 + (pixelInfo
.vpBounds
.bottom
- 1) *
1097 (pixelInfo
.vpRowBytes
& 0x7fff);
1099 if( size
> vramLength
)
1102 vdRes
.csPreviousDisplayModeID
= vdRes
.csDisplayModeID
;
1105 vramLength
= (vramLength
+ (vramBase
& 0xffff) + 0xffff) & 0xffff0000;
1106 vramBase
&= 0xffff0000;
1109 return( makeSubRange( vramBase
, vramLength
));
1117 const char * IONDRVFramebuffer::getPixelFormats( void )
1119 static const char * ndrvPixelFormats
=
1120 IO1BitIndexedPixels
"\0"
1121 IO2BitIndexedPixels
"\0"
1122 IO4BitIndexedPixels
"\0"
1123 IO8BitIndexedPixels
"\0"
1124 IO16BitDirectPixels
"\0"
1125 IO32BitDirectPixels
"\0"
1128 return( ndrvPixelFormats
);
1131 IOItemCount
IONDRVFramebuffer::getDisplayModeCount( void )
1133 return( iterateAllModes( 0 ));
1136 IOReturn
IONDRVFramebuffer::getDisplayModes( IODisplayModeID
* allDisplayModes
)
1138 iterateAllModes( allDisplayModes
);
1139 return( kIOReturnSuccess
);
1142 IOReturn
IONDRVFramebuffer::validateDetailedTiming(
1143 void * desc
, IOByteCount descripSize
)
1147 err
= setDetailedTiming( kDisplayModeIDPreflight
,
1148 kModePreflight
, desc
, descripSize
);
1153 IOReturn
IONDRVFramebuffer::setDetailedTimings( OSArray
* array
)
1156 UInt32
* newCurrent
;
1157 IOItemCount newCount
;
1159 newCount
= array
->getCount();
1160 newCurrent
= IONew(UInt32
, newCount
);
1162 if( detailedTimings
)
1163 IODelete( detailedTimingsCurrent
, UInt32
, detailedTimings
->getCount());
1164 detailedTimingsCurrent
= newCurrent
;
1165 bzero( newCurrent
, newCount
* sizeof( UInt32
));
1166 setProperty( kIOFBDetailedTimingsKey
, array
); // retains
1167 detailedTimings
= array
;
1168 detailedTimingsSeed
++;
1170 if( currentDisplayMode
== kDisplayModeIDBootProgrammable
) {
1171 VDDetailedTimingRec look
;
1172 VDDetailedTimingRec
* detailed
;
1174 IODisplayModeID newDisplayMode
;
1176 newDisplayMode
= currentDisplayMode
;
1178 bzero( &look
, sizeof( VDDetailedTimingRec
) );
1179 look
.csTimingSize
= sizeof( VDDetailedTimingRec
);
1180 look
.csDisplayModeID
= kDisplayModeIDBootProgrammable
;
1181 err
= doStatus( cscGetDetailedTiming
, &look
);
1183 if( kIOReturnSuccess
== err
)
1185 (data
= OSDynamicCast( OSData
, detailedTimings
->getObject(i
)));
1188 detailed
= (VDDetailedTimingRec
*) data
->getBytesNoCopy();
1189 if( (detailed
->csHorizontalActive
== look
.csHorizontalActive
)
1190 && (detailed
->csVerticalActive
== look
.csVerticalActive
)) {
1192 newDisplayMode
= i
+ kDisplayModeIDReservedBase
;
1196 if( newDisplayMode
!= currentDisplayMode
) {
1197 err
= validateDisplayMode( newDisplayMode
, 0, 0 );
1198 currentDisplayMode
= newDisplayMode
;
1202 err
= kIOReturnSuccess
;
1204 err
= kIOReturnNoMemory
;
1209 IOReturn
IONDRVFramebuffer::getInformationForDisplayMode(
1210 IODisplayModeID displayMode
, IODisplayModeInformation
* info
)
1214 err
= getResInfoForMode( displayMode
, info
);
1216 err
= kIOReturnUnsupportedMode
;
1222 UInt64
IONDRVFramebuffer::getPixelFormatsForDisplayMode(
1223 IODisplayModeID
/* displayMode */, IOIndex depthIndex
)
1225 return( 1 << (depthIndex
+ startAt8
));
1228 IOReturn
IONDRVFramebuffer::getPixelInformation(
1229 IODisplayModeID displayMode
, IOIndex depth
,
1230 IOPixelAperture aperture
, IOPixelInformation
* info
)
1233 VDVideoParametersInfoRec pixelParams
;
1235 const char * formats
;
1239 bzero( info
, sizeof( *info
));
1242 return( kIOReturnUnsupportedMode
);
1244 err
= validateDisplayMode( displayMode
, 0, 0 );
1249 pixelParams
.csDisplayModeID
= displayMode
;
1250 pixelParams
.csDepthMode
= depth
+ kDepthMode1
;
1251 pixelParams
.csVPBlockPtr
= &pixelInfo
;
1252 err
= doStatus( cscGetVideoParameters
, &pixelParams
);
1256 info
->flags
= accessFlags
;
1258 info
->activeWidth
= pixelInfo
.vpBounds
.right
;
1259 info
->activeHeight
= pixelInfo
.vpBounds
.bottom
;
1260 info
->bytesPerRow
= pixelInfo
.vpRowBytes
& 0x7fff;
1261 info
->bytesPerPlane
= pixelInfo
.vpPlaneBytes
;
1262 info
->bitsPerPixel
= pixelInfo
.vpPixelSize
;
1264 formats
= getPixelFormats();
1265 mask
= getPixelFormatsForDisplayMode( displayMode
, depth
);
1267 for( index
= 0; index
< 32; index
++) {
1268 if( (mask
& (1 << index
)) && ((aperture
--) == 0)) {
1269 strcpy( info
->pixelFormat
, formats
);
1272 formats
+= strlen( formats
) + 1;
1275 if( 0 == strcmp("PPPPPPPP", info
->pixelFormat
)) {
1276 info
->pixelType
= kIOCLUTPixels
;
1277 info
->componentMasks
[0] = 0xff;
1278 info
->bitsPerPixel
= 8;
1279 info
->componentCount
= 1;
1280 info
->bitsPerComponent
= 8;
1282 } else if( 0 == strcmp("-RRRRRGGGGGBBBBB", info
->pixelFormat
)) {
1283 info
->pixelType
= kIORGBDirectPixels
;
1284 info
->componentMasks
[0] = 0x7c00;
1285 info
->componentMasks
[1] = 0x03e0;
1286 info
->componentMasks
[2] = 0x001f;
1287 info
->bitsPerPixel
= 16;
1288 info
->componentCount
= 3;
1289 info
->bitsPerComponent
= 5;
1291 } else if( 0 == strcmp("--------RRRRRRRRGGGGGGGGBBBBBBBB",
1292 info
->pixelFormat
)) {
1293 info
->pixelType
= kIORGBDirectPixels
;
1294 info
->componentMasks
[0] = 0x00ff0000;
1295 info
->componentMasks
[1] = 0x0000ff00;
1296 info
->componentMasks
[2] = 0x000000ff;
1297 info
->bitsPerPixel
= 32;
1298 info
->componentCount
= 3;
1299 info
->bitsPerComponent
= 8;
1307 IOReturn
IONDRVFramebuffer::getTimingInfoForDisplayMode(
1308 IODisplayModeID displayMode
, IOTimingInformation
* info
)
1310 VDTimingInfoRec timingInfo
;
1313 err
= validateDisplayMode( displayMode
, 0, 0 );
1317 timingInfo
.csTimingMode
= displayMode
;
1318 // in case the driver doesn't do it:
1319 timingInfo
.csTimingFormat
= kDeclROMtables
;
1320 err
= doStatus( cscGetModeTiming
, &timingInfo
);
1322 if( timingInfo
.csTimingFormat
== kDeclROMtables
)
1323 info
->appleTimingID
= timingInfo
.csTimingData
;
1325 info
->appleTimingID
= timingInvalid
;
1327 return( kIOReturnSuccess
);
1330 return( kIOReturnUnsupportedMode
);
1333 IOReturn
IONDRVFramebuffer::getCurrentDisplayMode(
1334 IODisplayModeID
* displayMode
, IOIndex
* depth
)
1337 *displayMode
= currentDisplayMode
;
1339 *depth
= currentDepth
;
1341 return( kIOReturnSuccess
);
1344 IOReturn
IONDRVFramebuffer::setDisplayMode( IODisplayModeID displayMode
, IOIndex depth
)
1347 VDSwitchInfoRec switchInfo
;
1348 VDPageInfo pageInfo
;
1350 err
= validateDisplayMode( displayMode
, 0, 0 );
1354 ignore_zero_fault( true );
1355 switchInfo
.csData
= displayMode
;
1356 switchInfo
.csMode
= depth
+ kDepthMode1
;
1357 switchInfo
.csPage
= 0;
1358 err
= doControl( cscSwitchMode
, &switchInfo
);
1360 IOLog("%s: cscSwitchMode:%d\n", nub
->getName(), (int)err
);
1362 // duplicate QD InitGDevice
1363 pageInfo
.csMode
= switchInfo
.csMode
;
1364 pageInfo
.csData
= 0;
1365 pageInfo
.csPage
= 0;
1366 doControl( cscSetMode
, &pageInfo
);
1367 doControl( cscGrayPage
, &pageInfo
);
1368 ignore_zero_fault( false );
1370 getCurrentConfiguration();
1375 IOReturn
IONDRVFramebuffer::setStartupDisplayMode(
1376 IODisplayModeID displayMode
, IOIndex depth
)
1379 VDSwitchInfoRec switchInfo
;
1381 err
= validateDisplayMode( displayMode
, 0, 0 );
1385 switchInfo
.csData
= displayMode
;
1386 switchInfo
.csMode
= depth
+ kDepthMode1
;
1387 err
= doControl( cscSavePreferredConfiguration
, &switchInfo
);
1391 IOReturn
IONDRVFramebuffer::getStartupDisplayMode(
1392 IODisplayModeID
* displayMode
, IOIndex
* depth
)
1395 VDSwitchInfoRec switchInfo
;
1397 err
= doStatus( cscGetPreferredConfiguration
, &switchInfo
);
1399 *displayMode
= switchInfo
.csData
;
1400 *depth
= switchInfo
.csMode
- kDepthMode1
;
1405 IOReturn
IONDRVFramebuffer::setApertureEnable( IOPixelAperture
/* aperture */,
1406 IOOptionBits
/* enable */ )
1408 return( kIOReturnSuccess
);
1411 IOReturn
IONDRVFramebuffer::setCLUTWithEntries(
1412 IOColorEntry
* colors
, UInt32 index
, UInt32 numEntries
,
1413 IOOptionBits options
)
1417 VDSetEntryRecord setEntryRec
;
1418 VDClutBehavior clutSetting
;
1419 VDGrayRecord grayRec
;
1421 if( 0 == powerState
)
1422 return( kIOReturnSuccess
);
1424 if( options
& kSetCLUTWithLuminance
)
1425 grayRec
.csMode
= 1; // turn on luminance map
1427 grayRec
.csMode
= 0; // turn off luminance map
1429 if( grayRec
.csMode
!= lastGrayMode
) {
1430 doControl( cscSetGray
, &grayRec
);
1431 lastGrayMode
= grayRec
.csMode
;
1434 if( options
& kSetCLUTImmediately
)
1435 clutSetting
= kSetClutAtSetEntries
;
1437 clutSetting
= kSetClutAtVBL
;
1439 if( clutSetting
!= lastClutSetting
) {
1440 doControl( cscSetClutBehavior
, &clutSetting
);
1441 lastClutSetting
= clutSetting
;
1444 if( options
& kSetCLUTByValue
)
1445 setEntryRec
.csStart
= -1;
1447 setEntryRec
.csStart
= index
;
1449 setEntryRec
.csTable
= (ColorSpec
*) colors
;
1450 setEntryRec
.csCount
= numEntries
- 1;
1452 code
= cscDirectSetEntries
;
1454 code
= cscSetEntries
;
1455 err
= doControl( code
, &setEntryRec
);
1460 IOReturn
IONDRVFramebuffer::setGammaTable( UInt32 channelCount
, UInt32 dataCount
,
1461 UInt32 dataWidth
, void * data
)
1464 VDGammaRecord gammaRec
;
1466 short gVersion
; /*gamma version number*/
1467 short gType
; /*gamma data type*/
1468 short gFormulaSize
; /*Formula data size */
1469 short gChanCnt
; /*number of channels of data */
1470 short gDataCnt
; /*number of values/channel */
1471 short gDataWidth
; /*bits/corrected value */
1472 /* (data packed to next larger byte size) */
1473 UInt8 gFormulaData
[0]; /* data for formulas followed by gamma values */
1475 GammaTbl
* table
= NULL
;
1476 IOByteCount dataLen
= 0;
1478 if( 0 == powerState
)
1479 return( kIOReturnSuccess
);
1482 dataLen
= (dataWidth
+ 7) / 8;
1483 dataLen
*= dataCount
* channelCount
;
1484 table
= (GammaTbl
*) IOMalloc( dataLen
+ sizeof( struct GammaTbl
));
1486 return( kIOReturnNoMemory
);
1488 table
->gVersion
= 0;
1490 table
->gFormulaSize
= 0;
1491 table
->gChanCnt
= channelCount
;
1492 table
->gDataCnt
= dataCount
;
1493 table
->gDataWidth
= dataWidth
;
1494 bcopy( data
, table
->gFormulaData
, dataLen
);
1497 gammaRec
.csGTable
= (Ptr
) table
;
1498 err
= doControl( cscSetGamma
, &gammaRec
);
1500 IOFree( table
, dataLen
+ sizeof( struct GammaTbl
));
1505 IOReturn
IONDRVFramebuffer::getAttribute( IOSelect attribute
, UInt32
* value
)
1507 IOReturn err
= kIOReturnSuccess
;
1508 VDSupportsHardwareCursorRec hwCrsrSupport
;
1510 switch( attribute
) {
1512 case kIOHardwareCursorAttribute
:
1514 *value
= ((kIOReturnSuccess
==
1515 doStatus( cscSupportsHardwareCursor
, &hwCrsrSupport
))
1516 && (hwCrsrSupport
.csSupportsHardwareCursor
));
1520 err
= super::getAttribute( attribute
, value
);
1526 UInt32
IONDRVFramebuffer::getConnectionCount( void )
1528 VDMultiConnectInfoRec theRecord
;
1530 if( doStatus(cscGetMultiConnect
,&theRecord
) == 0 ) {
1531 return theRecord
.csDisplayCountOrNumber
;
1537 File: DDCPowerOnOffUtils.c <CS3>
1543 kI2CDisplayWriteAddress
= 0x6E,
1544 kI2CDisplayReadAddress
= 0x6F,
1545 // Messed up specification says checksum should be calculated with ACCESS.bus value of 50.
1546 kI2CDisplayReadHostCheckSumAddress
= 0x50,
1547 // Messed up specification says checksum should be calculated with ACCESS.bus value of 50.
1548 kI2CDisplayReadHostAddress
= 0x51,
1550 kI2CVCPGetCode
= 0x01,
1551 kI2CVCPGetLength
= 0x82,
1552 kI2CVCPGetMessageSize
= 0x05,
1554 kI2CVCPReplyLength
= 0x88,
1555 kI2CNullReplyLength
= 0x80,
1556 kI2CNullReplyCheckSum
= 0xBE,
1558 kI2CVCPSetCode
= 0x03,
1559 kI2CVCPSetLength
= 0x84,
1560 kI2CVCPReplyCode
= 0x02,
1566 kBasicI2CCommTransactionsMask
= ( (1<<kVideoNoTransactionType
) | (1<<kVideoSimpleI2CType
)
1567 | (1<<kVideoDDCciReplyType
) )
1570 void IONDRVFramebuffer::displayI2CPower( bool enable
)
1572 VDCommunicationRec i2CRecord
;
1573 VDCommunicationInfoRec i2cInfoRecord
;
1575 Byte replyBuffer
[kVCPReplySize
];
1576 UInt32 supportedCommFlags
= 0;
1577 // Don't do it if we're told it's not supported
1578 bool setThisDisplay
= true;
1581 // Some displays (like Fiji) do not support the reading
1582 // of the current power state. Others (like Mitsubishi
1583 // Diamond Pro 710) report that they do not support
1584 // power management calls.
1586 // I'll avoid sending the power command only in the
1587 // case that I get a valid reply that does says
1588 // it does not support the power selector.
1591 bzero( &i2cInfoRecord
, sizeof(i2cInfoRecord
) );
1592 if( noErr
!= doStatus( cscGetCommunicationInfo
, &i2cInfoRecord
))
1594 if( kBasicI2CCommTransactionsMask
!= (i2cInfoRecord
.csSupportedTypes
& kBasicI2CCommTransactionsMask
))
1596 if( !shouldDoI2CPower
)
1599 supportedCommFlags
= i2cInfoRecord
.csSupportedCommFlags
;
1600 bzero( &i2CRecord
, sizeof(i2CRecord
) );
1601 bzero( &sendBuffer
, sizeof(sendBuffer
) );
1602 bzero( &replyBuffer
, sizeof(replyBuffer
) );
1604 sendBuffer
[0] = kI2CDisplayReadHostAddress
;
1605 sendBuffer
[1] = kI2CVCPGetLength
;
1606 sendBuffer
[2] = kI2CVCPGetCode
; // GetVCP command
1607 sendBuffer
[3] = 0xD6;
1608 sendBuffer
[4] = kI2CDisplayWriteAddress
^
1609 sendBuffer
[0] ^ sendBuffer
[1] ^
1610 sendBuffer
[2] ^ sendBuffer
[3];
1612 i2CRecord
.csBusID
= kVideoDefaultBus
;
1613 i2CRecord
.csSendType
= kVideoSimpleI2CType
;
1614 i2CRecord
.csSendAddress
= kI2CDisplayWriteAddress
;
1615 i2CRecord
.csSendBuffer
= &sendBuffer
;
1616 i2CRecord
.csSendSize
= 7;
1617 i2CRecord
.csReplyType
= kVideoDDCciReplyType
;
1618 i2CRecord
.csReplyAddress
= kI2CDisplayReadAddress
;
1619 i2CRecord
.csReplyBuffer
= &replyBuffer
;
1620 i2CRecord
.csReplySize
= kVCPReplySize
;
1622 if( supportedCommFlags
& kVideoReplyMicroSecDelayMask
)
1624 // We know some displays are slow, this is an important call to get right
1625 i2CRecord
.csCommFlags
|= kVideoReplyMicroSecDelayMask
;
1626 // 50 milliseconds should be enough time for the display to respond.
1627 i2CRecord
.csMinReplyDelay
= 50 * 1000;
1630 if( (noErr
== doControl( cscDoCommunication
, &i2CRecord
))
1631 && (kI2CDisplayWriteAddress
== replyBuffer
[0])
1632 && (kI2CVCPReplyLength
== replyBuffer
[1])
1633 && (kI2CVCPReplyCode
== replyBuffer
[2])) {
1634 Byte checkSum
= kI2CDisplayReadHostCheckSumAddress
^ // host address
1635 replyBuffer
[0] ^ // source address
1636 replyBuffer
[1] ^ // message length (0x88)
1637 replyBuffer
[2] ^ // VCP type code
1638 replyBuffer
[3] ^ // result code
1639 replyBuffer
[4] ^ // VCP op code
1640 replyBuffer
[5] ^ // VCP type code
1641 replyBuffer
[6] ^ // Max value MSB
1642 replyBuffer
[7] ^ // Max value LSB
1643 replyBuffer
[8] ^ // Current value MSB
1644 replyBuffer
[9]; // Current value LSB
1646 if( (checkSum
== replyBuffer
[10]) && // Did the check sum match AND
1647 (0 != replyBuffer
[3])) // Are we not supposed to support this feature?
1648 setThisDisplay
= false; // Don't do it if we're told it's not supported
1651 if( setThisDisplay
) {
1653 bzero( &i2CRecord
, sizeof(i2CRecord
) );
1654 bzero( &sendBuffer
, sizeof(sendBuffer
) );
1655 bzero( &replyBuffer
, sizeof(replyBuffer
) );
1657 sendBuffer
[0] = kI2CDisplayReadHostAddress
;
1658 sendBuffer
[1] = kI2CVCPSetLength
;
1659 sendBuffer
[2] = kI2CVCPSetCode
; // SetVCP command
1660 sendBuffer
[3] = 0xD6;
1661 sendBuffer
[4] = 0; // MSB
1662 sendBuffer
[5] = enable
? kDDCPowerOn
: kDDCPowerOff
; // LSB
1663 sendBuffer
[6] = kI2CDisplayWriteAddress
^
1664 sendBuffer
[0] ^ sendBuffer
[1] ^
1665 sendBuffer
[2] ^ sendBuffer
[3] ^
1666 sendBuffer
[4] ^ sendBuffer
[5];
1668 i2CRecord
.csBusID
= kVideoDefaultBus
;
1669 i2CRecord
.csSendAddress
= kI2CDisplayWriteAddress
;
1670 i2CRecord
.csSendType
= kVideoSimpleI2CType
;
1671 i2CRecord
.csSendBuffer
= &sendBuffer
;
1672 i2CRecord
.csSendSize
= 7;
1673 i2CRecord
.csReplyType
= kVideoNoTransactionType
;
1674 i2CRecord
.csReplyAddress
= 0;
1675 i2CRecord
.csReplyBuffer
= 0;
1676 i2CRecord
.csReplySize
= 0;
1678 if( supportedCommFlags
& kVideoReplyMicroSecDelayMask
) {
1679 // We know some displays are slow, this is an important call to get right
1680 i2CRecord
.csCommFlags
|= kVideoReplyMicroSecDelayMask
;
1681 // 50 milliseconds should be enough time for the display to respond.
1682 i2CRecord
.csMinReplyDelay
= 50 * 1000;
1685 doControl( cscDoCommunication
, &i2CRecord
);
1688 IOReturn
IONDRVFramebuffer::setAttributeForConnection( IOIndex connectIndex
,
1689 IOSelect attribute
, UInt32 info
)
1692 VDSyncInfoRec theVDSyncInfoRec
;
1693 VDPowerStateRec sleepInfo
;
1695 switch( attribute
) {
1697 case kConnectionSyncEnable
:
1699 theVDSyncInfoRec
.csMode
= (unsigned char)(info
>>8);
1700 theVDSyncInfoRec
.csFlags
= (unsigned char)(info
& 0xFF);
1701 doControl( cscSetSync
, &theVDSyncInfoRec
);
1703 sleepInfo
.powerState
= ((info
>>8) & 0xff) ? kAVPowerSuspend
: kAVPowerOn
;
1704 sleepInfo
.powerFlags
= 0;
1705 sleepInfo
.powerReserved1
= 0;
1706 sleepInfo
.powerReserved2
= 0;
1707 doControl( cscSetPowerState
, &sleepInfo
);
1709 displayI2CPower( ((info
>>8) & 0xff) ? false : true );
1711 err
= kIOReturnSuccess
;
1715 err
= super::setAttributeForConnection( connectIndex
,
1723 IOReturn
IONDRVFramebuffer::getAttributeForConnection( IOIndex connectIndex
,
1724 IOSelect attribute
, UInt32
* value
)
1727 VDSyncInfoRec theVDSyncInfoRec
;
1729 switch( attribute
) {
1731 case kConnectionSyncFlags
:
1732 // find out current state of sync lines
1733 theVDSyncInfoRec
.csMode
= 0x00;
1734 doStatus(cscGetSync
,&theVDSyncInfoRec
);
1735 * value
= theVDSyncInfoRec
.csMode
;
1736 ret
= kIOReturnSuccess
;
1738 case kConnectionSyncEnable
:
1739 // what are the sync-controlling capabilities of the ndrv?
1740 theVDSyncInfoRec
.csMode
= 0xFF;
1741 doStatus(cscGetSync
,&theVDSyncInfoRec
);
1742 * value
= (UInt32
)theVDSyncInfoRec
.csMode
;
1743 ret
= kIOReturnSuccess
;
1745 case kConnectionSupportsHLDDCSense
:
1746 case kConnectionSupportsAppleSense
:
1747 ret
= kIOReturnSuccess
;
1750 ret
= super::getAttributeForConnection( connectIndex
,
1758 IOReturn
IONDRVFramebuffer::getAppleSense( IOIndex connectIndex
,
1762 UInt32
* displayType
)
1765 VDMultiConnectInfoRec multiConnect
;
1766 UInt32 sense
, extSense
;
1768 if( connectIndex
== 0 )
1769 err
= doStatus( cscGetConnection
, &multiConnect
.csConnectInfo
);
1772 multiConnect
.csDisplayCountOrNumber
= connectIndex
;
1773 err
= doControl( cscSetMultiConnect
, &multiConnect
);
1778 if( multiConnect
.csConnectInfo
.csConnectFlags
1779 & ((1<<kReportsTagging
) | (1<<kTaggingInfoNonStandard
))
1780 != ((1<<kReportsTagging
)) )
1782 err
= kIOReturnUnsupported
;
1786 sense
= multiConnect
.csConnectInfo
.csConnectTaggedType
;
1787 extSense
= multiConnect
.csConnectInfo
.csConnectTaggedData
;
1788 // bug fixes for really old ATI driver
1790 if( extSense
== 6) {
1792 extSense
= kESCSixStandard
;
1795 if( extSense
== 4) {
1797 extSense
= kESCFourNTSC
;
1803 *extended
= extSense
;
1805 *displayType
= multiConnect
.csConnectInfo
.csDisplayType
;
1812 IOReturn
IONDRVFramebuffer::connectFlags( IOIndex
/* connectIndex */,
1813 IODisplayModeID displayMode
, IOOptionBits
* flags
)
1815 VDTimingInfoRec timingInfo
;
1818 timingInfo
.csTimingMode
= displayMode
;
1819 // in case the driver doesn't do it:
1820 timingInfo
.csTimingFormat
= kDeclROMtables
;
1821 err
= doStatus( cscGetModeTiming
, &timingInfo
);
1823 if( kDetailedTimingFormat
== timingInfo
.csTimingFormat
)
1824 *flags
= kDisplayModeValidFlag
| kDisplayModeSafeFlag
;
1826 *flags
= timingInfo
.csTimingFlags
;
1832 bool IONDRVFramebuffer::hasDDCConnect( IOIndex connectIndex
)
1835 VDMultiConnectInfoRec multiConnect
;
1836 enum { kNeedFlags
= (1<<kReportsDDCConnection
)
1837 | (1<<kHasDDCConnection
) };
1838 if( connectIndex
== 0 )
1839 err
= doStatus( cscGetConnection
, &multiConnect
.csConnectInfo
);
1841 multiConnect
.csDisplayCountOrNumber
= connectIndex
;
1842 err
= doControl( cscSetMultiConnect
, &multiConnect
);
1847 return( (multiConnect
.csConnectInfo
.csConnectFlags
& kNeedFlags
)
1851 // I2C first year for Apple displays.
1852 // Apple monitors older than this (and Manta)
1853 // are never called with I2C commands
1855 kFirstAppleI2CYear
= 1999,
1856 kAppleVESAVendorID
= 0x0610
1861 UInt8 vendorProduct
[4];
1862 UInt8 serialNumber
[4];
1863 UInt8 weekOfManufacture
;
1864 UInt8 yearOfManufacture
;
1867 UInt8 displayParams
[5];
1868 UInt8 colorCharacteristics
[10];
1869 UInt8 establishedTimings
[3];
1870 UInt16 standardTimings
[8];
1871 UInt8 descriptors
[4][18];
1876 static bool IsApplePowerBlock(UInt8
* theBlock
)
1879 0x00000000 == *(UInt32
*)&theBlock
[0] &&
1880 0x00 == theBlock
[4] &&
1881 0x06 == theBlock
[5] &&
1882 0x10 == theBlock
[6] );
1885 IOReturn
IONDRVFramebuffer::getDDCBlock( IOIndex
/* connectIndex */,
1888 IOOptionBits options
,
1889 UInt8
* data
, IOByteCount
* length
)
1893 VDDDCBlockRec ddcRec
;
1894 ByteCount actualLength
= *length
;
1896 ddcRec
.ddcBlockNumber
= blockNumber
;
1897 ddcRec
.ddcBlockType
= blockType
;
1898 ddcRec
.ddcFlags
= options
;
1900 err
= doStatus( cscGetDDCBlock
, &ddcRec
);
1904 if( actualLength
< kDDCBlockSize
)
1905 actualLength
= actualLength
;
1907 actualLength
= kDDCBlockSize
;
1908 bcopy( ddcRec
.ddcBlockData
, data
, actualLength
);
1909 *length
= actualLength
;
1911 if( (1 == blockNumber
) && (kIODDCBlockTypeEDID
== blockType
)
1912 && (actualLength
>= sizeof( EDID
))) do {
1918 edid
= (EDID
*) data
;
1919 vendor
= (edid
->vendorProduct
[0] << 8) | edid
->vendorProduct
[1];
1920 product
= (edid
->vendorProduct
[3] << 8) | edid
->vendorProduct
[2];
1921 if( kAppleVESAVendorID
== vendor
) {
1922 if( (0x01F4 == product
) || (0x9D02 == product
))
1924 if( edid
->yearOfManufacture
&& ((edid
->yearOfManufacture
+ 1990) < kFirstAppleI2CYear
))
1927 shouldDoI2CPower
= (IsApplePowerBlock( &edid
->descriptors
[1][0])
1928 || IsApplePowerBlock( &edid
->descriptors
[2][0])
1929 || IsApplePowerBlock( &edid
->descriptors
[3][0]));
1934 IOLog("%s: i2cPower %d\n", getName(), shouldDoI2CPower
);
1939 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
1942 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
1944 void IONDRVFramebuffer::initForPM( void )
1946 static const IOPMPowerState powerStates
[ kIONDRVFramebufferPowerStateCount
] = {
1947 { 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
1948 { 1, IOPMDeviceUsable
, IOPMPowerOn
, IOPMPowerOn
, 0, 0, 0, 0, 0, 0, 0, 0 }
1950 // register ourselves with superclass policy-maker
1951 registerPowerDriver( this, (IOPMPowerState
*) powerStates
,
1952 kIONDRVFramebufferPowerStateCount
);
1956 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
1957 // maxCapabilityForDomainState
1959 // This simple device needs only power. If the power domain is supplying
1960 // power, the frame buffer can be on. If there is no power it can only be off.
1961 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
1963 unsigned long IONDRVFramebuffer::maxCapabilityForDomainState(
1964 IOPMPowerFlags domainState
)
1966 if( domainState
& IOPMPowerOn
)
1967 return( kIONDRVFramebufferPowerStateCount
- 1);
1972 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
1973 // initialPowerStateForDomainState
1975 // The power domain may be changing state. If power is on in the new
1976 // state, that will not affect our state at all. If domain power is off,
1977 // we can attain only our lowest state, which is off.
1979 // This implementation is incomplete. It only works in a system where
1980 // the frame buffer is never turned off. When we cross that bridge,
1981 // instead of returning 1, it should return 1 if the frame buffer
1982 // is on, or 0 if it is off.
1983 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
1985 unsigned long IONDRVFramebuffer::initialPowerStateForDomainState(
1986 IOPMPowerFlags domainState
)
1988 if( domainState
& IOPMPowerOn
)
1989 return( kIONDRVFramebufferPowerStateCount
- 1);
1995 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
1996 // powerStateForDomainState
1998 // The power domain may be changing state. If power is on in the new
1999 // state, that will not affect our state at all. If domain power is off,
2000 // we can attain only our lowest state, which is off.
2001 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2003 unsigned long IONDRVFramebuffer::powerStateForDomainState(
2004 IOPMPowerFlags domainState
)
2006 if( domainState
& IOPMPowerOn
)
2007 return( pm_vars
->myCurrentState
);
2013 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2016 // Called by the superclass to turn the frame buffer on and off.
2017 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2019 IOReturn
IONDRVFramebuffer::setPowerState( unsigned long powerStateOrdinal
,
2020 IOService
* whichDevice
)
2022 static const unsigned long states
[2][2] =
2023 { { kAVPowerOff
, kAVPowerOn
},
2024 { kHardwareSleep
, kHardwareWake
} };
2026 VDPowerStateRec sleepInfo
;
2030 IOAGPDevice
* agpDev
;
2032 if( powerStateOrdinal
== powerState
)
2033 return( IOPMAckImplied
);
2035 if( 0 == powerStateOrdinal
)
2036 super::setPowerState( powerStateOrdinal
, whichDevice
);
2038 sleepInfo
.powerState
= 0;
2039 sleepInfo
.powerFlags
= 0;
2040 sleepInfo
.powerReserved1
= 0;
2041 sleepInfo
.powerReserved2
= 0;
2043 err
= doStatus( cscGetPowerState
, &sleepInfo
);
2044 if( (kIOReturnSuccess
== err
)
2045 && (kPowerStateSleepCanPowerOffMask
& sleepInfo
.powerFlags
))
2046 deepSleep
= platformDeepSleep
;
2048 newState
= states
[deepSleep
& 1][powerStateOrdinal
& 1];
2049 sleepInfo
.powerState
= newState
;
2050 sleepInfo
.powerFlags
= 0;
2051 sleepInfo
.powerReserved1
= 0;
2052 sleepInfo
.powerReserved2
= 0;
2055 if( newState
== kHardwareSleep
) {
2056 IOMemoryDescriptor
* vram
;
2057 if( (vram
= getVRAMRange())) {
2058 vram
->redirect( kernel_task
, true );
2064 ignore_zero_fault( true );
2065 boolean_t ints
= ml_set_interrupts_enabled( false );
2067 err
= doControl( cscSetPowerState
, &sleepInfo
);
2069 ml_set_interrupts_enabled( ints
);
2070 ignore_zero_fault( false );
2073 if( newState
== kHardwareWake
) {
2074 IOMemoryDescriptor
* vram
;
2075 if( (vram
= getVRAMRange())) {
2076 vram
->redirect( kernel_task
, false );
2082 if( powerStateOrdinal
) {
2083 powerState
= powerStateOrdinal
;
2084 if( kAVPowerOn
== newState
) {
2085 VDPageInfo pageInfo
;
2086 pageInfo
.csData
= 0;
2087 pageInfo
.csPage
= 0;
2088 doControl( cscGrayPage
, &pageInfo
);
2092 setCursorImage( 0 );
2095 agpDev
= OSDynamicCast(IOAGPDevice
, nub
);
2097 agpDev
= OSDynamicCast( IOAGPDevice
, nub
->getParentEntry(gIODTPlane
));
2101 powerState
= powerStateOrdinal
;
2103 if( powerStateOrdinal
)
2104 super::setPowerState( powerStateOrdinal
, whichDevice
);
2106 return( IOPMAckImplied
);
2109 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2112 // Real problem : getStartupMode doesn't.
2114 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2117 #define super IONDRVFramebuffer
2119 OSDefineMetaClassAndStructors(IOATINDRV
, IONDRVFramebuffer
)
2120 OSDefineMetaClassAndStructors(IOATI128NDRV
, IOATINDRV
)
2122 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2124 IOReturn
IOATINDRV::getStartupDisplayMode(
2125 IODisplayModeID
* displayMode
, IOIndex
* depth
)
2130 prop
= OSDynamicCast( OSData
, nub
->getProperty("Sime"));
2132 nvram
= (UInt16
*) prop
->getBytesNoCopy();
2133 *displayMode
= nvram
[ 0 ]; // 1 is physDisplayMode
2134 *depth
= nvram
[ 2 ] - kDepthMode1
;
2135 return( kIOReturnSuccess
);
2137 return(super::getStartupDisplayMode( displayMode
, depth
));
2140 IODeviceMemory
* IOATINDRV::findVRAM( void )
2143 IOByteCount
* lengths
;
2145 IOPhysicalAddress vramBase
;
2146 IOByteCount vramLength
;
2148 prop
= OSDynamicCast( OSData
, nub
->getProperty("ATY,memsize"));
2150 return( super::findVRAM());
2152 lengths
= (IOByteCount
*) prop
->getBytesNoCopy();
2153 count
= prop
->getLength() / sizeof(IOByteCount
);
2155 prop
= OSDynamicCast( OSData
, nub
->getProperty("ATY,Base"));
2157 if( prop
&& (count
> 1)) {
2158 vramBase
= *((IOPhysicalAddress
*)prop
->getBytesNoCopy());
2159 vramLength
= lengths
[1];
2160 vramBase
&= ~(vramLength
- 1);
2162 vramBase
= physicalFramebuffer
;
2163 vramLength
= lengths
[0];
2167 return( super::findVRAM());
2169 vramLength
= (vramLength
+ (vramBase
& 0xffff)) & 0xffff0000;
2170 vramBase
&= 0xffff0000;
2172 return( makeSubRange( vramBase
, vramLength
));
2175 static int g128ExtraCurs
= 8;
2176 static int g128DeltaCurs
= 0x25c0;
2178 void IOATI128NDRV::flushCursor( void )
2180 volatile UInt32
* fb
;
2184 fb
= (volatile UInt32
*) frameBuffer
;
2185 for( i
= 0; i
< g128ExtraCurs
; i
++) {
2187 fb
+= g128DeltaCurs
;
2193 OSMetaClassDefineReservedUnused(IONDRVFramebuffer
, 0);
2194 OSMetaClassDefineReservedUnused(IONDRVFramebuffer
, 1);
2195 OSMetaClassDefineReservedUnused(IONDRVFramebuffer
, 2);
2196 OSMetaClassDefineReservedUnused(IONDRVFramebuffer
, 3);
2197 OSMetaClassDefineReservedUnused(IONDRVFramebuffer
, 4);
2198 OSMetaClassDefineReservedUnused(IONDRVFramebuffer
, 5);
2199 OSMetaClassDefineReservedUnused(IONDRVFramebuffer
, 6);
2200 OSMetaClassDefineReservedUnused(IONDRVFramebuffer
, 7);
2201 OSMetaClassDefineReservedUnused(IONDRVFramebuffer
, 8);
2202 OSMetaClassDefineReservedUnused(IONDRVFramebuffer
, 9);
2203 OSMetaClassDefineReservedUnused(IONDRVFramebuffer
, 10);
2204 OSMetaClassDefineReservedUnused(IONDRVFramebuffer
, 11);
2205 OSMetaClassDefineReservedUnused(IONDRVFramebuffer
, 12);
2206 OSMetaClassDefineReservedUnused(IONDRVFramebuffer
, 13);
2207 OSMetaClassDefineReservedUnused(IONDRVFramebuffer
, 14);
2208 OSMetaClassDefineReservedUnused(IONDRVFramebuffer
, 15);
2209 OSMetaClassDefineReservedUnused(IONDRVFramebuffer
, 16);
2210 OSMetaClassDefineReservedUnused(IONDRVFramebuffer
, 17);
2211 OSMetaClassDefineReservedUnused(IONDRVFramebuffer
, 18);
2212 OSMetaClassDefineReservedUnused(IONDRVFramebuffer
, 19);
2213 OSMetaClassDefineReservedUnused(IONDRVFramebuffer
, 20);
2214 OSMetaClassDefineReservedUnused(IONDRVFramebuffer
, 21);
2215 OSMetaClassDefineReservedUnused(IONDRVFramebuffer
, 22);
2216 OSMetaClassDefineReservedUnused(IONDRVFramebuffer
, 23);
2217 OSMetaClassDefineReservedUnused(IONDRVFramebuffer
, 24);
2218 OSMetaClassDefineReservedUnused(IONDRVFramebuffer
, 25);
2219 OSMetaClassDefineReservedUnused(IONDRVFramebuffer
, 26);
2220 OSMetaClassDefineReservedUnused(IONDRVFramebuffer
, 27);
2221 OSMetaClassDefineReservedUnused(IONDRVFramebuffer
, 28);
2222 OSMetaClassDefineReservedUnused(IONDRVFramebuffer
, 29);
2223 OSMetaClassDefineReservedUnused(IONDRVFramebuffer
, 30);
2224 OSMetaClassDefineReservedUnused(IONDRVFramebuffer
, 31);