|
|
1.1 ! root 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 18 May 98 - make loadable. ! 30: * sdouglas 23 Jul 98 - start IOKit ! 31: * sdouglas 08 Dec 98 - start cpp ! 32: */ ! 33: ! 34: ! 35: #include <IOKit/graphics/IODisplay.h> ! 36: #include <IOKit/IOLib.h> ! 37: #include <IOKit/assert.h> ! 38: ! 39: ! 40: /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ ! 41: ! 42: #undef super ! 43: #define super IOService ! 44: ! 45: OSDefineMetaClass( IODisplay, IOService ) ! 46: OSDefineAbstractStructors( IODisplay, IOService ) ! 47: ! 48: /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ ! 49: ! 50: IOService * IODisplay::probe( IOService * provider, ! 51: SInt32 * score ) ! 52: { ! 53: connection = OSDynamicCast(IODisplayConnect, provider); ! 54: ! 55: return( this ); ! 56: } ! 57: ! 58: IODisplayConnect * IODisplay::getConnection( void ) ! 59: { ! 60: return( connection ); ! 61: } ! 62: ! 63: ! 64: IOReturn IODisplay::getGammaTableByIndex( ! 65: UInt32 * /* channelCount */, UInt32 * /* dataCount */, ! 66: UInt32 * /* dataWidth */, void ** /* data */ ) ! 67: { ! 68: return( kIOReturnUnsupported); ! 69: } ! 70: ! 71: ! 72: bool IODisplay::start( IOService * provider ) ! 73: { ! 74: if ( super::start(provider) ) { ! 75: if ( connection != NULL ) { ! 76: displayPMVars = (DisplayPMVars *)IOMalloc(sizeof(DisplayPMVars)); // make space for our variables ! 77: assert( displayPMVars ); ! 78: displayPMVars->displayIdle = false; // initialize some ! 79: initForPM(provider); // initialize power management of the device ! 80: registerService(); ! 81: } ! 82: return true; ! 83: } ! 84: return false; ! 85: } ! 86: ! 87: ! 88: /* ! 89: This is the power-controlling driver for a display. It also acts as an agent of the policy-maker for display power ! 90: which is the DisplayWrangler. The Display Wrangler calls here to lower power by one state when it senses ! 91: no user activity. It also calls here to make the display usable after it has been idled down, and it also calls ! 92: here to make the display barely usable if it senses a power emergency (e.g. low battery). ! 93: ! 94: This driver assumes a video display, and it calls the framebuffer driver to control the sync signals. Non-video ! 95: display drivers (e.g. flat panels) subclass IODisplay and override this and other appropriate methods. ! 96: */ ! 97: ! 98: static IOPMPowerState ourPowerStates[kIODisplayMaxPowerStates] = { ! 99: {1,0,0,0,0,0,0,0,0,0,0,0}, ! 100: {1,0,0,IOPMPowerOn,0,0,0,0,0,0,0,0}, ! 101: {1,0,0,IOPMPowerOn,0,0,0,0,0,0,0,0}, ! 102: {1,IOPMDeviceUsable+IOPMMaxPerformance,0,IOPMPowerOn,0,0,0,0,0,0,0,0} ! 103: }; ! 104: ! 105: ! 106: void IODisplay::initForPM ( IOService * provider ) ! 107: { ! 108: UInt32 capabilities = 0; ! 109: unsigned long number_of_power_states; ! 110: UInt32 currentSyncs = 0; ! 111: IOReturn err; ! 112: ! 113: displayPMVars->connectIndex = connection->getConnection(); // find out our index in the nub ! 114: ! 115: // what are the sync-controlling capabilities of the framebuffer? ! 116: err = connection->getAttributeForConnection( displayPMVars->connectIndex, ! 117: kConnectionSyncEnable, &capabilities ); ! 118: ! 119: // find out current state of sync lines ! 120: err = connection->getAttributeForConnection( displayPMVars->connectIndex, ! 121: kConnectionSyncFlags, ¤tSyncs ); ! 122: ! 123: displayPMVars->currentSyncs = currentSyncs; ! 124: displayPMVars->powerControllable = true; ! 125: ! 126: if ( (capabilities & kIOHSyncDisable) && ! 127: (capabilities & kIOVSyncDisable) && ! 128: !(capabilities & kIONoSeparateSyncControl ) ) { // four power states ! 129: number_of_power_states = 4; ! 130: displayPMVars->syncControls[0] = 0 | kIOHSyncDisable | kIOVSyncDisable | kIOCSyncDisable; ! 131: displayPMVars->syncControls[1] = 0 | kIOVSyncDisable | kIOCSyncDisable; ! 132: displayPMVars->syncControls[2] = 0 | kIOHSyncDisable | kIOCSyncDisable; ! 133: displayPMVars->syncControls[3] = 0; ! 134: displayPMVars->syncMask = capabilities & (kIOHSyncDisable | kIOVSyncDisable | kIOCSyncDisable); ! 135: } ! 136: else { ! 137: if ( capabilities & kIOCSyncDisable ) { // two power states ! 138: number_of_power_states = 2; ! 139: ourPowerStates[1].capabilityFlags = ourPowerStates[3].capabilityFlags; ! 140: displayPMVars->syncControls[0] = 0 | kIOCSyncDisable; ! 141: displayPMVars->syncControls[1] = 0; ! 142: displayPMVars->syncMask = 0 | kIOCSyncDisable; ! 143: } ! 144: else { // two power states and not controllable ! 145: number_of_power_states = 2; ! 146: ourPowerStates[1].capabilityFlags = ourPowerStates[3].capabilityFlags; ! 147: ourPowerStates[0].capabilityFlags |= IOPMNotAttainable; ! 148: ourPowerStates[1].capabilityFlags |= IOPMNotAttainable; ! 149: displayPMVars->syncControls[0] = displayPMVars->currentSyncs; ! 150: displayPMVars->syncControls[1] = displayPMVars->currentSyncs; ! 151: displayPMVars->syncMask = displayPMVars->currentSyncs; ! 152: displayPMVars->powerControllable = false; ! 153: } ! 154: } ! 155: ! 156: PMinit(); // initialize superclass variables ! 157: provider->joinPMtree(this); // attach into the power management hierarchy ! 158: ! 159: registerControllingDriver(this,ourPowerStates,number_of_power_states); // register ourselves with policy-maker (us) ! 160: ! 161: } ! 162: ! 163: ! 164: //********************************************************************************* ! 165: // registerControllingDriver ! 166: // ! 167: // We intercept this call to our superclass just to snoop early on ! 168: // the number of power states. ! 169: //********************************************************************************* ! 170: ! 171: IOReturn IODisplay::registerControllingDriver ( IOService* x, IOPMPowerState*y, unsigned long numberOfStates ) ! 172: { ! 173: displayPMVars->max_display_state = numberOfStates - 1; ! 174: return super::registerControllingDriver(x,y,numberOfStates); ! 175: } ! 176: ! 177: ! 178: //********************************************************************************* ! 179: // setAggressiveness ! 180: // ! 181: // We are informed by our power domain parent of a new level of "power management ! 182: // aggressiveness". Our only interest is if it implies a power management ! 183: // emergency, in which case we keep the display brightness low. ! 184: //********************************************************************************* ! 185: ! 186: IOReturn IODisplay::setAggressiveness ( unsigned long type, unsigned long newLevel ) ! 187: { ! 188: unsigned long i; ! 189: ! 190: if ( type == kPMGeneralAggressiveness ) { ! 191: if ( newLevel >= kIOPowerEmergencyLevel ) { // emergency level ! 192: for ( i = 0; i < pm_vars->theNumberOfPowerStates; i++ ) { // find lowest usable state ! 193: if ( pm_vars->thePowerStates[i].capabilityFlags & IOPMDeviceUsable ) { ! 194: break; ! 195: } ! 196: } ! 197: displayPMVars->max_display_state = i; ! 198: if ( pm_vars->myCurrentState > i ) { // if we are currently above that, ! 199: changeStateToPriv(i); // drop to emergency level ! 200: } ! 201: } ! 202: else { // not emergency level ! 203: if ( pm_vars->aggressiveness >= kIOPowerEmergencyLevel ) { // but it was emergency level ! 204: displayPMVars->max_display_state = pm_vars->theNumberOfPowerStates - 1; ! 205: if ( ! displayPMVars->displayIdle ) { ! 206: changeStateToPriv(displayPMVars->max_display_state); // return to normal usable level ! 207: } ! 208: } ! 209: } ! 210: } ! 211: super::setAggressiveness(type, newLevel); ! 212: return IOPMNoErr; ! 213: } ! 214: ! 215: ! 216: // ********************************************************************************** ! 217: // dropOneLevel ! 218: // ! 219: // Called by the display wrangler when it decides there hasn't been user ! 220: // activity for a while. We drop one power level. This can be called by the ! 221: // display wrangler before we have been completely initialized. ! 222: // ********************************************************************************** ! 223: void IODisplay::dropOneLevel ( void ) ! 224: { ! 225: if ( initialized && displayPMVars->powerControllable) { ! 226: displayPMVars->displayIdle = true; ! 227: if ( pm_vars != NULL ) { ! 228: if ( pm_vars->myCurrentState > 0 ) { ! 229: changeStateToPriv(pm_vars->myCurrentState - 1); // drop a level ! 230: } ! 231: else { ! 232: changeStateToPriv(0); // this may rescind previous request for domain power ! 233: } ! 234: } ! 235: } ! 236: } ! 237: ! 238: ! 239: //********************************************************************************* ! 240: // makeDisplayUsable ! 241: // ! 242: // The DisplayWrangler has sensed user activity after we have idled the ! 243: // display and wants us to make it usable again. We are running on its ! 244: // workloop thread. This can be called before we are completely ! 245: // initialized. ! 246: //********************************************************************************* ! 247: void IODisplay::makeDisplayUsable ( void ) ! 248: { ! 249: if ( initialized && displayPMVars->powerControllable) { ! 250: displayPMVars->displayIdle = false; ! 251: if ( pm_vars != NULL ) { ! 252: changeStateToPriv(displayPMVars->max_display_state); ! 253: } ! 254: } ! 255: } ! 256: ! 257: ! 258: // ********************************************************************************** ! 259: // setPowerState ! 260: // ! 261: // Called by the superclass to change the display power state. ! 262: // ********************************************************************************** ! 263: IOReturn IODisplay::setPowerState ( unsigned long powerStateOrdinal, IOService* whatDevice ) ! 264: { ! 265: UInt32 flags; ! 266: ! 267: flags =(displayPMVars->syncControls[powerStateOrdinal])<<8; ! 268: flags |= displayPMVars->syncMask; ! 269: displayPMVars->currentSyncs = displayPMVars->syncControls[powerStateOrdinal]; ! 270: connection->setAttributeForConnection( displayPMVars->connectIndex, kConnectionSyncEnable, flags ); ! 271: ! 272: return IOPMAckImplied; ! 273: } ! 274: ! 275: ! 276: // ********************************************************************************** ! 277: // maxCapabilityForDomainState ! 278: // ! 279: // This simple device needs only power. If the power domain is supplying ! 280: // power, the display can go to its highest state. If there is no power ! 281: // it can only be in its lowest state, which is off. ! 282: // ********************************************************************************** ! 283: unsigned long IODisplay::maxCapabilityForDomainState ( IOPMPowerFlags domainState ) ! 284: { ! 285: if ( domainState & IOPMPowerOn ) { ! 286: return pm_vars->theNumberOfPowerStates-1; ! 287: } ! 288: else { ! 289: return 0; ! 290: } ! 291: } ! 292: ! 293: ! 294: // ********************************************************************************** ! 295: // initialPowerStateForDomainState ! 296: // ! 297: // The power domain may be changing state. If power is on in the new ! 298: // state, that will not affect our state at all. In that case ask the ndrv ! 299: // what our current state is. If domain power is off, we can attain ! 300: // only our lowest state, which is off. ! 301: // ********************************************************************************** ! 302: unsigned long IODisplay::initialPowerStateForDomainState ( IOPMPowerFlags domainState ) ! 303: { ! 304: long unsigned i; ! 305: ! 306: if ( domainState & IOPMPowerOn ) { // domain has power ! 307: for ( i = pm_vars->theNumberOfPowerStates-1; i > 0; i-- ) { // compare to our table to find current power state ! 308: if ( (displayPMVars->syncControls[i] & displayPMVars->syncMask) ! 309: == (displayPMVars->currentSyncs & displayPMVars->syncMask) ) { ! 310: break; ! 311: } ! 312: } ! 313: return i; ! 314: } ! 315: else { ! 316: return 0; // domain is down, so display is off ! 317: } ! 318: } ! 319: ! 320: ! 321: // ********************************************************************************** ! 322: // powerStateForDomainState ! 323: // ! 324: // The power domain may be changing state. If power is on in the new ! 325: // state, that will not affect our state at all. In that case ask the ndrv ! 326: // what our current state is. If domain power is off, we can attain ! 327: // only our lowest state, which is off. ! 328: // ********************************************************************************** ! 329: unsigned long IODisplay::powerStateForDomainState ( IOPMPowerFlags domainState ) ! 330: { ! 331: long unsigned i; ! 332: ! 333: if ( domainState & IOPMPowerOn ) { // domain has power ! 334: for ( i = pm_vars->theNumberOfPowerStates-1; i > 0; i-- ) { // compare to our table to find current power state ! 335: if ( (displayPMVars->syncControls[i] & displayPMVars->syncMask) ! 336: == (displayPMVars->currentSyncs & displayPMVars->syncMask) ) { ! 337: break; ! 338: } ! 339: } ! 340: return i; ! 341: } ! 342: else { ! 343: return 0; // domain is down, so display is off ! 344: } ! 345: } ! 346: ! 347: ! 348: ! 349: /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ ! 350: ! 351: #undef super ! 352: #define super IODisplay ! 353: ! 354: OSDefineMetaClassAndStructors(AppleSenseDisplay, IODisplay) ! 355: ! 356: ! 357: IOService * AppleSenseDisplay::probe( IOService * provider, ! 358: SInt32 * score ) ! 359: { ! 360: IODisplayConnect * connect; ! 361: IOFramebuffer * framebuffer; ! 362: IOService * ret = 0; ! 363: ! 364: do { ! 365: ! 366: if( 0 == super::probe( provider, score )) ! 367: continue; ! 368: ! 369: connect = getConnection(); ! 370: if( !connect) ! 371: continue; ! 372: ! 373: framebuffer = connect->getFramebuffer(); ! 374: assert( framebuffer ); ! 375: ! 376: if( kIOReturnSuccess != framebuffer->getAttributeForConnection( ! 377: connect->getConnection(), ! 378: kConnectionSupportsAppleSense, NULL )) ! 379: continue; ! 380: ! 381: ret = this; ! 382: ! 383: } while( false); ! 384: ! 385: return( ret ); ! 386: } ! 387: ! 388: IOReturn AppleSenseDisplay::getConnectFlagsForDisplayMode( ! 389: IODisplayModeID mode, UInt32 * flags ) ! 390: { ! 391: IOFramebuffer * framebuffer; ! 392: IODisplayConnect * connect; ! 393: ! 394: connect = getConnection(); ! 395: framebuffer = connect->getFramebuffer(); ! 396: ! 397: return( framebuffer->connectFlags( ! 398: connect->getConnection(), ! 399: mode, flags )); ! 400: } ! 401: ! 402: /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ ! 403: ! 404: ! 405: #undef super ! 406: #define super IODisplay ! 407: ! 408: OSDefineMetaClassAndStructors(AppleNoSenseDisplay, IODisplay) ! 409: ! 410: ! 411: IOReturn AppleNoSenseDisplay::getConnectFlagsForDisplayMode( ! 412: IODisplayModeID /* mode */, UInt32 * flags) ! 413: { ! 414: ! 415: *flags = kDisplayModeValidFlag | kDisplayModeSafeFlag; ! 416: ! 417: return( kIOReturnSuccess ); ! 418: } ! 419: ! 420:
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.