|
|
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: #include <IOKit/IOLib.h> ! 24: #include <IOKit/graphics/IODisplay.h> ! 25: #include <IOKit/ndrvsupport/IOMacOSVideo.h> ! 26: ! 27: #include <Drivers/platform/drvApplePMU/pmupriv.h> ! 28: #include <Drivers/hidsystem/drvAppleADBDevices/AppleADBButtons.h> ! 29: ! 30: #define kNumber_of_power_states 4 ! 31: #define kNumber_of_power_levels 32 ! 32: ! 33: #define kScreenBit 0x01 ! 34: #define kPowerOn 0x80 ! 35: #define kPowerOff 0x00 ! 36: #define kDisplayOn kScreenBit | kPowerOn ! 37: #define kDisplayOff kScreenBit | kPowerOff ! 38: ! 39: class ApplePMU; ! 40: ! 41: ! 42: class AppleG3SeriesDisplay : public AppleSenseDisplay ! 43: { ! 44: OSDeclareDefaultStructors(AppleG3SeriesDisplay) ! 45: ! 46: private: ! 47: ! 48: int current_user_brightness; // 0-31. The brightness level last selected via the brightness buttons. ! 49: int current_level; // 0-31. The current brightness level ! 50: ApplePMU * PMUdriver; // points to PMU driver ! 51: int * rawTable; // points to table of raw brightess levels ! 52: ! 53: public: ! 54: IOService * probe ( IOService *, SInt32 * ); ! 55: virtual void initForPM ( IOService* ); ! 56: virtual IOReturn setPowerState ( unsigned long, IOService* ); ! 57: virtual unsigned long maxCapabilityForDomainState ( IOPMPowerFlags ); ! 58: virtual unsigned long initialPowerStateForDomainState ( IOPMPowerFlags ); ! 59: virtual unsigned long powerStateForDomainState ( IOPMPowerFlags ); ! 60: virtual void ourButtonHandler ( unsigned int ); ! 61: virtual void setBrightness ( long ); ! 62: }; ! 63: ! 64: void upButtonHandler(AppleG3SeriesDisplay *); ! 65: void downButtonHandler(AppleG3SeriesDisplay *); ! 66: ! 67: ! 68: /* ! 69: The actual display panel has 128 power levels. Copying the MacOS, we only implement 32 of them. ! 70: We further divide the 32 into four IOKit power states which we export to our superclass. ! 71: ! 72: In the lowest state, the display is off. This state consists of only one of the 32 power levels, the lowest. ! 73: In the next state it is in the dimmest usable state. This state also consists of only one of the 32 levels, the second lowest. ! 74: The next state is also dim and consists of seven of the 32 levels. ! 75: The highest state consists of the highest 23 levels. ! 76: ! 77: The display has no state or configuration or programming that would be saved/restored over power state changes, ! 78: and the driver does not register with the superclass as an interested driver. ! 79: ! 80: This driver doesn't have much to do. It changes between the four power state brightnesses on command ! 81: from the superclass, and it raises and lowers the display brightness by one of the 32 brightness levels ! 82: when it receives a brightness-button interrupt from the ADB stack. ! 83: ! 84: The only smart thing it does is keep track of which of the 32 brightness levels the user has selected by button, and it ! 85: never exceeds that on command from the display device object. It only raises above that on an brightness-up-button ! 86: interrupt. ! 87: ! 88: */ ! 89: ! 90: ! 91: static IOPMPowerState ourPowerStates[kNumber_of_power_states] = { ! 92: {1,0,0,0,0,0,0,0,0,0,0,0}, ! 93: {1,IOPMDeviceUsable,0,IOPMPowerOn,0,0,0,0,0,0,0,0}, ! 94: {1,IOPMDeviceUsable,0,IOPMPowerOn,0,0,0,0,0,0,0,0}, ! 95: {1,IOPMDeviceUsable+IOPMMaxPerformance,0,IOPMPowerOn,0,0,0,0,0,0,0,0} ! 96: }; ! 97: ! 98: static int max_brightness_level[kNumber_of_power_states] = {0,1,8,31}; ! 99: ! 100: static int HooperTable[ ] = {127,71,69,67,65,63,61,59, ! 101: 58,56,54,52,50,48,46,44, ! 102: 42,40,38,37,35,33,31,29, ! 103: 27,25,23,21,19,18,16,14 }; ! 104: ! 105: bool ourNotificationHandler( OSObject *, void *, IOService * ); ! 106: ! 107: #define super AppleSenseDisplay ! 108: ! 109: OSDefineMetaClassAndStructors(AppleG3SeriesDisplay, AppleSenseDisplay) ! 110: ! 111: ! 112: // ********************************************************************************** ! 113: // probe ! 114: // ! 115: // ********************************************************************************** ! 116: IOService * AppleG3SeriesDisplay::probe ( IOService * provider, SInt32 * score ) ! 117: { ! 118: IOFramebuffer * framebuffer; ! 119: IOService * ret = 0; ! 120: UInt32 displayType; ! 121: IOIndex ourIndex; ! 122: ! 123: do { ! 124: if ( 0 == super::probe( provider, score ) ) { ! 125: continue; ! 126: } ! 127: ! 128: framebuffer = (IOFramebuffer *)getConnection()->getFramebuffer(); // point to our framebuffer ! 129: ourIndex = getConnection()->getConnection(); // get our connection index on this framebuffer ! 130: ! 131: if ( kIOReturnSuccess != framebuffer->getAppleSense(ourIndex,NULL,NULL,NULL,&displayType) ) { ! 132: continue; ! 133: } ! 134: ! 135: if ( !(displayType == kPanelTFTConnect) ) { // does it have a panel attached? ! 136: continue; // no ! 137: } ! 138: ret = this; // yes, we will control the panel ! 139: ! 140: } while ( false ); ! 141: ! 142: return ( ret ); ! 143: } ! 144: ! 145: ! 146: // ********************************************************************************** ! 147: // initForPM ! 148: // ! 149: // This method overrides the one in IODisplay.h to do PowerBook-only ! 150: // power management of the display. ! 151: // ********************************************************************************** ! 152: void AppleG3SeriesDisplay::initForPM ( IOService * provider ) ! 153: { ! 154: IOByteCount unused; ! 155: const OSSymbol * PMUname; ! 156: IOService * service; ! 157: unsigned long i; ! 158: UInt8 PMUreceiveBuffer[10]; // (I think 1 is enough, but it scares me) ! 159: ! 160: ! 161: displayPMVars->powerControllable = true; ! 162: ! 163: PMinit(); // initialize superclass variables ! 164: ! 165: PMUname = OSSymbol::withCStringNoCopy(kPMUname); // find the PMU driver ! 166: service = waitForService(resourceMatching(PMUname)); ! 167: PMUdriver = OSDynamicCast(ApplePMU, service->getProperty(PMUname)); ! 168: ! 169: rawTable = HooperTable; ! 170: ! 171: PMUdriver->sendMiscCommand(kPMUpower1Read,0, NULL, &unused,PMUreceiveBuffer); ! 172: if ( PMUreceiveBuffer[0] & kScreenBit ) { // is the screen currently on? ! 173: PMUdriver->sendMiscCommand(kPMUReadBrightness,0, NULL, &unused,PMUreceiveBuffer); // yes, figure out the brightness ! 174: current_user_brightness = kNumber_of_power_levels - 1; // ( in case the for-loop doesn't break) ! 175: current_level = kNumber_of_power_levels - 1; ! 176: ! 177: for ( i = 0; i < kNumber_of_power_levels; i++ ) { ! 178: if ( PMUreceiveBuffer[0] >= rawTable[i] ) { ! 179: current_user_brightness = i; ! 180: current_level = i; ! 181: break; ! 182: } ! 183: } ! 184: } ! 185: else { // no ! 186: current_user_brightness = 0; ! 187: current_level = 0; ! 188: } ! 189: ! 190: addNotification( gIOPublishNotification,serviceMatching("AppleADBButtons"), // look for the button driver ! 191: (IOServiceNotificationHandler)ourNotificationHandler, this, 0 ); ! 192: ! 193: provider->joinPMtree(this); // attach into the power management hierarchy ! 194: registerControllingDriver(this,ourPowerStates,kNumber_of_power_states); // register with policy-maker (us) ! 195: } ! 196: ! 197: ! 198: // ********************************************************************************** ! 199: // ourNotificationHandler ! 200: // ! 201: // The ADB button driver has appeared. Tell it we are interested in the ! 202: // brightness-up button and the brightness-down button. ! 203: // ********************************************************************************** ! 204: bool ourNotificationHandler( OSObject * us, void * ref, IOService * yourDevice ) ! 205: { ! 206: if ( yourDevice != NULL ) { ! 207: ((AppleADBButtons *)yourDevice)->registerForButton(kBrightness_up,(IOService *)us,(button_handler)upButtonHandler,true); ! 208: ((AppleADBButtons *)yourDevice)->registerForButton(kBrightness_down,(IOService *)us,(button_handler)downButtonHandler,true); ! 209: } ! 210: return true; ! 211: } ! 212: ! 213: ! 214: // ********************************************************************************** ! 215: // setPowerState ! 216: // ! 217: // All power state changes require a call to the PMU driver, which ! 218: // blocks the thread till the command completes. ! 219: // ********************************************************************************** ! 220: IOReturn AppleG3SeriesDisplay::setPowerState ( unsigned long powerStateOrdinal, IOService* whatDevice ) ! 221: { ! 222: UInt8 displayOn = kDisplayOn; ! 223: UInt8 displayOff = kDisplayOff; ! 224: IOByteCount unused; ! 225: unsigned long i; ! 226: ! 227: if ( powerStateOrdinal < kNumber_of_power_states ) { ! 228: if ( powerStateOrdinal > pm_vars->myCurrentState ) { // raising power ! 229: if ( pm_vars->myCurrentState == 0 ) { // is it currently off? ! 230: PMUdriver->sendMiscCommand(kPMUpower1Cntl,1, &displayOn, &unused,NULL); ! 231: } ! 232: current_level = max_brightness_level[powerStateOrdinal]; ! 233: if ( current_user_brightness < current_level ) { ! 234: current_level = current_user_brightness; // don't exceed what the user used to have it at ! 235: } ! 236: setBrightness(current_level); ! 237: // If we are still higher than we need to be, request a lower state ! 238: for ( i = 0; i < kNumber_of_power_states; i++ ) { // figure out what state we should be in ! 239: if ( current_level <= max_brightness_level[i] ) { ! 240: break; ! 241: } ! 242: } ! 243: if ( pm_vars->myCurrentState > i ) { ! 244: changeStateToPriv(i); ! 245: } ! 246: } ! 247: ! 248: if ( powerStateOrdinal < pm_vars->myCurrentState ) { // lowering power ! 249: if (powerStateOrdinal == 0 ) { // going all the way off? ! 250: PMUdriver->sendMiscCommand(kPMUpower1Cntl,1, &displayOff, &unused,NULL); // yes ! 251: current_level = max_brightness_level[powerStateOrdinal]; ! 252: } ! 253: else { ! 254: if ( current_level > max_brightness_level[powerStateOrdinal] ) { // no ! 255: current_level = max_brightness_level[powerStateOrdinal]; ! 256: setBrightness(current_level); ! 257: } ! 258: } ! 259: } ! 260: } ! 261: return IOPMAckImplied; ! 262: } ! 263: ! 264: ! 265: // ********************************************************************************** ! 266: // maxCapabilityForDomainState ! 267: // ! 268: // This simple device needs only power. If the power domain is supplying ! 269: // power, the display can go to its highest state. If there is no power ! 270: // it can only be in its lowest state, which is off. ! 271: // ********************************************************************************** ! 272: unsigned long AppleG3SeriesDisplay::maxCapabilityForDomainState ( IOPMPowerFlags domainState ) ! 273: { ! 274: if ( domainState & IOPMPowerOn ) { ! 275: return kNumber_of_power_states-1; ! 276: } ! 277: return 0; ! 278: } ! 279: ! 280: ! 281: // ********************************************************************************** ! 282: // initialPowerStateForDomainState ! 283: // ! 284: // The power domain may be changing state. If power is on in the new ! 285: // state, that will not affect our state at all. If domain power is off, ! 286: // we can attain only our lowest state, which is off. ! 287: // ********************************************************************************** ! 288: unsigned long AppleG3SeriesDisplay::initialPowerStateForDomainState ( IOPMPowerFlags domainState ) ! 289: { ! 290: long unsigned i; ! 291: ! 292: if ( domainState & IOPMPowerOn ) { // domain has power ! 293: for ( i = 0; i < kNumber_of_power_states; i++ ) { // find power state that has our current ! 294: if ( current_level <= max_brightness_level[i] ) { // brightness level ! 295: return i; ! 296: break; ! 297: } ! 298: } ! 299: } ! 300: return 0; // domain is down, so display is off ! 301: } ! 302: ! 303: ! 304: // ********************************************************************************** ! 305: // powerStateForDomainState ! 306: // ! 307: // The power domain may be changing state. If power is on in the new ! 308: // state, that will not affect our state at all. If domain power is off, ! 309: // we can attain only our lowest state, which is off. ! 310: // ********************************************************************************** ! 311: unsigned long AppleG3SeriesDisplay::powerStateForDomainState ( IOPMPowerFlags domainState ) ! 312: { ! 313: long unsigned i; ! 314: ! 315: if ( domainState & IOPMPowerOn ) { // domain has power ! 316: for ( i = 0; i < kNumber_of_power_states; i++ ) { // find power state that has our current ! 317: if ( current_level <= max_brightness_level[i] ) { // brightness level ! 318: return i; ! 319: } ! 320: } ! 321: } ! 322: return 0; // domain is down, so display is off ! 323: } ! 324: ! 325: ! 326: // ********************************************************************************** ! 327: // upButtonHandler ! 328: // ! 329: // The display-brightness-up button just went down. ! 330: // We are running on a new thread made by the ADB Button driver ! 331: // ********************************************************************************** ! 332: void upButtonHandler(AppleG3SeriesDisplay * us ) ! 333: { ! 334: ((AppleG3SeriesDisplay *)us)->ourButtonHandler(kBrightness_up); ! 335: } ! 336: ! 337: ! 338: // ********************************************************************************** ! 339: // downButtonHandler ! 340: // ! 341: // The display-brightness-down button just went down. ! 342: // We are running on a new thread made by the ADB Button driver ! 343: // ********************************************************************************** ! 344: void downButtonHandler(AppleG3SeriesDisplay * us ) ! 345: { ! 346: ((AppleG3SeriesDisplay *)us)->ourButtonHandler(kBrightness_down); ! 347: } ! 348: ! 349: ! 350: // ********************************************************************************** ! 351: // ourButtonHandler ! 352: // ! 353: // Alter the backlight brightness up or down by one increment. ! 354: // This involves a call to the PMU driver, which will block the thread. ! 355: // ********************************************************************************** ! 356: void AppleG3SeriesDisplay::ourButtonHandler ( unsigned int keycode ) ! 357: { // If we are idle, ignore the button. ! 358: // The display will be made usable ! 359: if ( ! displayPMVars->displayIdle ) { // by the DisplayWrangler ! 360: switch (keycode) { ! 361: case kBrightness_up: // The brightness-up button has just been pressed ! 362: // We make sure the brightness is not above the maximum ! 363: // brightness level of our current power state. If it ! 364: // is too high, we ask the device to raise power. ! 365: if (current_level < max_brightness_level[pm_vars->myCurrentState] ) { ! 366: current_level++; ! 367: current_user_brightness = current_level; ! 368: setBrightness(current_level); ! 369: } ! 370: else { ! 371: if ( pm_vars->myCurrentState < (kNumber_of_power_states-1) ) { ! 372: current_user_brightness++; // increment user's desire ! 373: if ( changeStateToPriv(pm_vars->myCurrentState + 1) != IOPMNoErr ) { // request higher power ! 374: current_user_brightness--; // can't ! 375: } ! 376: } ! 377: } ! 378: break; ! 379: ! 380: case kBrightness_down: // The brightness-down button has just been pressed ! 381: // We lower the brightness, and if that takes us into a ! 382: // lower power state, we tell our parent about it. ! 383: if ( pm_vars->myCurrentState > 0 ) { // don't lower if in lowest (off) state ! 384: if ( current_level > 0 ) { ! 385: current_level--; ! 386: current_user_brightness = current_level; ! 387: setBrightness(current_level); ! 388: if (current_level <= max_brightness_level[pm_vars->myCurrentState - 1] ) { // if this takes us into the next lower state ! 389: changeStateToPriv(pm_vars->myCurrentState - 1); // request lower power ! 390: } ! 391: } ! 392: } ! 393: break; ! 394: } ! 395: } ! 396: } ! 397: ! 398: ! 399: // ********************************************************************************** ! 400: // setBrightness ! 401: // ! 402: // Instruct PMU to set the display brightness. ! 403: // This will block the thread while the command completes. ! 404: // ********************************************************************************** ! 405: void AppleG3SeriesDisplay::setBrightness ( long brightness ) ! 406: { ! 407: IOByteCount unused; ! 408: UInt8 setBrightnessBuffer; ! 409: ! 410: setBrightnessBuffer = (UInt8)rawTable[brightness]; ! 411: PMUdriver->sendMiscCommand(kPMUSetBrightness,1, &setBrightnessBuffer, &unused,NULL); ! 412: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.