#include <libkern/OSAtomic.h>
#include <IOKit/graphics/IODisplay.h>
#include <IOKit/IOLib.h>
#include <IOKit/assert.h>
const OSSymbol * gIODisplayParametersKey;
const OSSymbol * gIODisplayGUIDKey;
const OSSymbol * gIODisplayValueKey;
const OSSymbol * gIODisplayMinValueKey;
const OSSymbol * gIODisplayMaxValueKey;
const OSSymbol * gIODisplayContrastKey;
const OSSymbol * gIODisplayBrightnessKey;
const OSSymbol * gIODisplayHorizontalPositionKey;
const OSSymbol * gIODisplayHorizontalSizeKey;
const OSSymbol * gIODisplayVerticalPositionKey;
const OSSymbol * gIODisplayVerticalSizeKey;
const OSSymbol * gIODisplayTrapezoidKey;
const OSSymbol * gIODisplayPincushionKey;
const OSSymbol * gIODisplayParallelogramKey;
const OSSymbol * gIODisplayRotationKey;
const OSSymbol * gIODisplayParametersCommitKey;
const OSSymbol * gIODisplayParametersDefaultKey;
#undef super
#define super IOService
OSDefineMetaClass( IODisplay, IOService )
OSDefineAbstractStructors( IODisplay, IOService )
void IODisplay::initialize( void )
{
gIODisplayParametersKey = OSSymbol::withCStringNoCopy(
kIODisplayParametersKey );
gIODisplayGUIDKey = OSSymbol::withCStringNoCopy(
kIODisplayGUIDKey );
gIODisplayValueKey = OSSymbol::withCStringNoCopy(
kIODisplayValueKey );
gIODisplayMinValueKey = OSSymbol::withCStringNoCopy(
kIODisplayMinValueKey );
gIODisplayMaxValueKey = OSSymbol::withCStringNoCopy(
kIODisplayMaxValueKey );
gIODisplayContrastKey = OSSymbol::withCStringNoCopy(
kIODisplayContrastKey );
gIODisplayBrightnessKey = OSSymbol::withCStringNoCopy(
kIODisplayBrightnessKey );
gIODisplayHorizontalPositionKey = OSSymbol::withCStringNoCopy(
kIODisplayHorizontalPositionKey );
gIODisplayHorizontalSizeKey = OSSymbol::withCStringNoCopy(
kIODisplayHorizontalSizeKey );
gIODisplayVerticalPositionKey = OSSymbol::withCStringNoCopy(
kIODisplayVerticalPositionKey );
gIODisplayVerticalSizeKey = OSSymbol::withCStringNoCopy(
kIODisplayVerticalSizeKey );
gIODisplayTrapezoidKey = OSSymbol::withCStringNoCopy(
kIODisplayTrapezoidKey );
gIODisplayPincushionKey = OSSymbol::withCStringNoCopy(
kIODisplayPincushionKey );
gIODisplayParallelogramKey = OSSymbol::withCStringNoCopy(
kIODisplayParallelogramKey );
gIODisplayRotationKey = OSSymbol::withCStringNoCopy(
kIODisplayRotationKey );
gIODisplayParametersCommitKey = OSSymbol::withCStringNoCopy(
kIODisplayParametersCommitKey );
gIODisplayParametersDefaultKey = OSSymbol::withCStringNoCopy(
kIODisplayParametersDefaultKey );
}
IOService * IODisplay::probe( IOService * provider,
SInt32 * score )
{
connection = OSDynamicCast(IODisplayConnect, provider);
return( this );
}
IODisplayConnect * IODisplay::getConnection( void )
{
return( connection );
}
IOReturn IODisplay::getGammaTableByIndex(
UInt32 * , UInt32 * ,
UInt32 * , void ** )
{
return( kIOReturnUnsupported);
}
bool IODisplay::start( IOService * provider )
{
if ( super::start(provider) ) {
if ( connection != NULL ) {
displayPMVars = (DisplayPMVars *)IOMalloc(sizeof(DisplayPMVars)); assert( displayPMVars );
displayPMVars->displayIdle = false; initForPM(provider); registerService();
}
return true;
}
return false;
}
IOReturn IODisplay::setProperties( OSObject * properties )
{
IOService * handler;
OSDictionary * dict;
OSDictionary * dict2;
dict = OSDynamicCast( OSDictionary, properties);
if( !dict)
return( kIOReturnUnsupported );
dict2 = OSDynamicCast( OSDictionary, dict->getObject(gIODisplayParametersKey));
if( dict2)
dict = dict2;
handler = getClientWithCategory(gIODisplayParametersKey);
if( !handler)
return( kIOReturnUnsupported );
return( handler->setProperties( dict ) );
}
static IOPMPowerState ourPowerStates[kIODisplayMaxPowerStates] = {
{1,0,0,0,0,0,0,0,0,0,0,0},
{1,0,0,0,0,0,0,0,0,0,0,0},
{1,0,0,0,0,0,0,0,0,0,0,0},
{1,IOPMDeviceUsable+IOPMMaxPerformance,0,IOPMPowerOn,0,0,0,0,0,0,0,0}
};
void IODisplay::initForPM ( IOService * provider )
{
UInt32 capabilities = 0;
unsigned long number_of_power_states;
UInt32 currentSyncs = 0;
IOReturn err;
displayPMVars->connectIndex = connection->getConnection();
err = connection->getAttributeForConnection( displayPMVars->connectIndex,
kConnectionSyncEnable, &capabilities );
err = connection->getAttributeForConnection( displayPMVars->connectIndex,
kConnectionSyncFlags, ¤tSyncs );
displayPMVars->currentSyncs = currentSyncs;
displayPMVars->powerControllable = true;
if ( (capabilities & kIOHSyncDisable) &&
(capabilities & kIOVSyncDisable) &&
!(capabilities & kIONoSeparateSyncControl ) ) { number_of_power_states = 4;
displayPMVars->syncControls[0] = 0 | kIOHSyncDisable | kIOVSyncDisable | kIOCSyncDisable;
displayPMVars->syncControls[1] = 0 | kIOVSyncDisable | kIOCSyncDisable;
displayPMVars->syncControls[2] = 0 | kIOHSyncDisable | kIOCSyncDisable;
displayPMVars->syncControls[3] = 0;
displayPMVars->syncMask = capabilities & (kIOHSyncDisable | kIOVSyncDisable | kIOCSyncDisable);
}
else {
if ( capabilities & kIOCSyncDisable ) { number_of_power_states = 2;
ourPowerStates[1].capabilityFlags = ourPowerStates[3].capabilityFlags;
displayPMVars->syncControls[0] = 0 | kIOCSyncDisable;
displayPMVars->syncControls[1] = 0;
displayPMVars->syncMask = 0 | kIOCSyncDisable;
}
else { number_of_power_states = 2;
ourPowerStates[1].capabilityFlags = ourPowerStates[3].capabilityFlags;
ourPowerStates[0].capabilityFlags |= IOPMNotAttainable;
ourPowerStates[1].capabilityFlags |= IOPMNotAttainable;
displayPMVars->syncControls[0] = displayPMVars->currentSyncs;
displayPMVars->syncControls[1] = displayPMVars->currentSyncs;
displayPMVars->syncMask = displayPMVars->currentSyncs;
displayPMVars->powerControllable = false;
}
}
PMinit(); provider->joinPMtree(this);
registerPowerDriver(this,ourPowerStates,number_of_power_states);
}
IOReturn IODisplay::registerPowerDriver ( IOService* x, IOPMPowerState*y, unsigned long numberOfStates )
{
displayPMVars->max_display_state = numberOfStates - 1;
return super::registerPowerDriver(x,y,numberOfStates);
}
IOReturn IODisplay::setAggressiveness ( unsigned long type, unsigned long newLevel )
{
unsigned long i;
if ( type == kPMGeneralAggressiveness ) {
if ( newLevel >= kIOPowerEmergencyLevel ) { for ( i = 0; i < pm_vars->theNumberOfPowerStates; i++ ) { if ( pm_vars->thePowerStates[i].capabilityFlags & IOPMDeviceUsable ) {
break;
}
}
displayPMVars->max_display_state = i;
if ( pm_vars->myCurrentState > i ) { changePowerStateToPriv(i); }
}
else { if ( pm_vars->aggressiveness >= kIOPowerEmergencyLevel ) { displayPMVars->max_display_state = pm_vars->theNumberOfPowerStates - 1;
if ( ! displayPMVars->displayIdle ) {
changePowerStateToPriv(displayPMVars->max_display_state); }
}
}
}
super::setAggressiveness(type, newLevel);
return IOPMNoErr;
}
void IODisplay::dropOneLevel ( void )
{
if ( initialized && displayPMVars->powerControllable) {
displayPMVars->displayIdle = true;
if ( pm_vars != NULL ) {
if ( pm_vars->myCurrentState > 0 ) {
changePowerStateToPriv(pm_vars->myCurrentState - 1); }
else {
changePowerStateToPriv(0); }
}
}
}
void IODisplay::makeDisplayUsable ( void )
{
if ( initialized && displayPMVars->powerControllable) {
displayPMVars->displayIdle = false;
if ( pm_vars != NULL ) {
changePowerStateToPriv(displayPMVars->max_display_state);
}
}
}
IOReturn IODisplay::setPowerState ( unsigned long powerStateOrdinal, IOService* whatDevice )
{
UInt32 flags;
if( initialized) {
flags =(displayPMVars->syncControls[powerStateOrdinal])<<8;
flags |= displayPMVars->syncMask;
displayPMVars->currentSyncs = displayPMVars->syncControls[powerStateOrdinal];
connection->setAttributeForConnection( displayPMVars->connectIndex, kConnectionSyncEnable, flags );
}
return IOPMAckImplied;
}
unsigned long IODisplay::maxCapabilityForDomainState ( IOPMPowerFlags domainState )
{
if ( domainState & IOPMPowerOn ) {
return pm_vars->theNumberOfPowerStates-1;
}
else {
return 0;
}
}
unsigned long IODisplay::initialPowerStateForDomainState ( IOPMPowerFlags domainState )
{
long unsigned i;
if ( domainState & IOPMPowerOn ) { for ( i = pm_vars->theNumberOfPowerStates-1; i > 0; i-- ) { if ( (displayPMVars->syncControls[i] & displayPMVars->syncMask)
== (displayPMVars->currentSyncs & displayPMVars->syncMask) ) {
break;
}
}
return i;
}
else {
return 0; }
}
unsigned long IODisplay::powerStateForDomainState ( IOPMPowerFlags domainState )
{
long unsigned i;
if ( domainState & IOPMPowerOn ) { for ( i = pm_vars->theNumberOfPowerStates-1; i > 0; i-- ) { if ( (displayPMVars->syncControls[i] & displayPMVars->syncMask)
== (displayPMVars->currentSyncs & displayPMVars->syncMask) ) {
break;
}
}
return i;
}
else {
return 0; }
}
#undef super
#define super IODisplay
OSDefineMetaClassAndStructors(AppleSenseDisplay, IODisplay)
IOService * AppleSenseDisplay::probe( IOService * provider,
SInt32 * score )
{
IODisplayConnect * connect;
IOFramebuffer * framebuffer;
IOService * ret = 0;
UInt32 sense, extSense;
UInt32 senseType, displayType;
do {
if( 0 == super::probe( provider, score ))
continue;
connect = getConnection();
if( !connect)
continue;
framebuffer = connect->getFramebuffer();
assert( framebuffer );
if( kIOReturnSuccess != framebuffer->getAttributeForConnection(
connect->getConnection(),
kConnectionSupportsAppleSense, NULL ))
continue;
ret = this;
if( kIOReturnSuccess != framebuffer->getAppleSense(
connect->getConnection(),
&senseType, &sense, &extSense, &displayType ))
continue;
sense = ((sense & 0xff) << 8) | (extSense & 0xff);
setProperty( kDisplayProductID, sense, 32);
setProperty( kDisplayVendorID, kDisplayVendorIDUnknown, 32);
setProperty( "AppleDisplayType", displayType, 32);
} while( false);
return( ret );
}
IOReturn AppleSenseDisplay::getConnectFlagsForDisplayMode(
IODisplayModeID mode, UInt32 * flags )
{
IOFramebuffer * framebuffer;
IODisplayConnect * connect;
connect = getConnection();
framebuffer = connect->getFramebuffer();
return( framebuffer->connectFlags(
connect->getConnection(),
mode, flags ));
}
#undef super
#define super IODisplay
OSDefineMetaClassAndStructors(AppleNoSenseDisplay, IODisplay)
IOReturn AppleNoSenseDisplay::getConnectFlagsForDisplayMode(
IODisplayModeID , UInt32 * flags)
{
*flags = kDisplayModeValidFlag | kDisplayModeSafeFlag;
setProperty( kDisplayProductID, kDisplayProductIDGeneric, 32);
setProperty( kDisplayVendorID, kDisplayVendorIDUnknown, 32);
return( kIOReturnSuccess );
}