/* * Copyright (c) 1998-2000 Apple Computer, Inc. All rights reserved. * * @APPLE_LICENSE_HEADER_START@ * * The contents of this file constitute Original Code as defined in and * are subject to the Apple Public Source License Version 1.1 (the * "License"). You may not use this file except in compliance with the * License. Please obtain a copy of the License at * http://www.apple.com/publicsource and read it before using this file. * * This Original Code and all software distributed under the License are * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the * License for the specific language governing rights and limitations * under the License. * * @APPLE_LICENSE_HEADER_END@ */ #include #include #include #include #include #include #include #include #include "IVAD.h" #ifndef kIODisplayTheatreModeKey #define kIODisplayTheatreModeKey "theatre-mode" #endif #ifndef kIODisplayTheatreModeWindowKey #define kIODisplayTheatreModeWindowKey "theatre-mode-window" #endif static IOReturn ApplePMUSendMiscCommand( UInt32 command, IOByteCount sendLength, UInt8 * sendBuffer, IOByteCount * readLength, UInt8 * readBuffer ); IOReturn AppleCudaWriteIIC( UInt8 address, const UInt8 * buffer, IOByteCount * count ); IOReturn AppleCudaReadIIC( UInt8 address, UInt8 * buffer, IOByteCount * count ); /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ class AppleOnboardDisplay : public IOService { OSDeclareDefaultStructors(AppleOnboardDisplay); private: IOFramebuffer * fFramebuffer; OSDictionary * fDisplayParams; IONotifier * fNotifier; UInt32 fIICAddress; IORegistryEntry * fIVAD; const OSSymbol * fIVADPrefsKey; EEPROM * fEEPROM; IVADUserPrefs * fUserPrefs; UInt32 fModeIndex; bool fUsesXPRAM; bool fTheatreMode; bool (*fDoSet)( AppleOnboardDisplay * self, OSDictionary * params, const OSSymbol * paramName, UInt32 value ); bool (*fDoUpdate)( AppleOnboardDisplay * self ); public: virtual bool start( IOService * provider ); virtual IOReturn setProperties( OSObject * properties ); private: static bool _displayHandler( void * target, void * ref, IOService * newService ); static IOReturn framebufferEvent( OSObject * self, void * ref, IOFramebuffer *framebuffer, IOIndex event, void * info ); bool displayHandler( IODisplay * display ); bool addParameter( const OSSymbol * paramName, SInt32 min, SInt32 max ); bool setParameter( const OSSymbol * paramName, SInt32 value ); bool setForKey( OSDictionary * params, const OSSymbol * key, SInt32 value, SInt32 min, SInt32 max ); OSDictionary * getParams( const OSSymbol * sym, SInt32 * value, SInt32 * min, SInt32 * max ); static bool updateNone( AppleOnboardDisplay * self ); // -- static bool setATI( AppleOnboardDisplay * self, OSDictionary * params, const OSSymbol * paramName, UInt32 value ); static bool updateATI( AppleOnboardDisplay * self ); // -- static bool setG3AIO( AppleOnboardDisplay * self, OSDictionary * params, const OSSymbol * paramName, UInt32 value ); // -- static bool setPMU( AppleOnboardDisplay * self, OSDictionary * params, const OSSymbol * paramName, UInt32 value ); // -- static bool setVCP( AppleOnboardDisplay * self, OSDictionary * params, const OSSymbol * paramName, UInt32 value ); bool readVCPRange( UInt8 command, SInt32 * max, SInt32 * current ); bool setupVCP( void ); // -- static bool setIVAD( AppleOnboardDisplay * self, OSDictionary * params, const OSSymbol * paramName, UInt32 value ); static bool updateIVAD( AppleOnboardDisplay * self ); bool setupIVAD( void ); bool setTheatreMode( UInt32 newMode ); bool setTheatreModeATI( IOGBounds * rect ); }; /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ #define super IOService OSDefineMetaClassAndStructors(AppleOnboardDisplay, IOService); const OSSymbol * gIODisplayParametersTheatreModeKey; const OSSymbol * gIODisplayParametersTheatreModeWindowKey; /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ bool AppleOnboardDisplay::start( IOService * provider ) { OSObject * notify; if( !super::start( provider)) return( false); gIODisplayParametersTheatreModeKey = OSSymbol::withCString(kIODisplayTheatreModeKey); gIODisplayParametersTheatreModeWindowKey = OSSymbol::withCString(kIODisplayTheatreModeWindowKey); notify = addNotification( gIOMatchedNotification, serviceMatching("IODisplay"), _displayHandler, this, (void *) 0 ); assert( notify ); return( true ); } bool AppleOnboardDisplay::_displayHandler( void * target, void * ref, IOService * newService ) { return( ((AppleOnboardDisplay *)target)->displayHandler( (IODisplay *) newService )); } bool AppleOnboardDisplay::displayHandler( IODisplay * display ) { IODisplayConnect * connect; IOFramebuffer * framebuffer; IOService * dev; OSData * data; OSNumber * num; // only one onboard display is handled if( fFramebuffer) return( false ); connect = display->getConnection(); if( !connect) return( false ); framebuffer = connect->getFramebuffer(); dev = framebuffer->getProvider(); fUsesXPRAM = true; if( (data = OSDynamicCast(OSData, dev->getProperty("backlight-control"))) && (data->isEqualTo("ati", 3) || (0 == strcmp("ATY,RageM_Lp", dev->getName()))) ) { fDisplayParams = OSDynamicCast( OSDictionary, getProperty("Backlight0")); fDoSet = &AppleOnboardDisplay::setATI; fDoUpdate = &AppleOnboardDisplay::updateATI; fUsesXPRAM = false; } else if( (data = OSDynamicCast(OSData, dev->getProperty("iic-address")))) { fIICAddress = *((UInt32 *) data->getBytesNoCopy()); fIVAD = dev->childFromPath("ivad", gIODTPlane); // (iicAddress == iicIVAD) if( fIVAD) { fFramebuffer = framebuffer; fIVADPrefsKey = OSSymbol::withCString("geometry"); fDisplayParams = OSDynamicCast( OSDictionary, getProperty("IVAD")); fDoSet = &AppleOnboardDisplay::setIVAD; fDoUpdate = &AppleOnboardDisplay::updateIVAD; setupIVAD(); } else { fDisplayParams = OSDynamicCast( OSDictionary, getProperty("VCP")); fDoSet = &AppleOnboardDisplay::setVCP; fDoUpdate = &AppleOnboardDisplay::updateNone; if( !setupVCP()) display = 0; } } else if( (data = OSDynamicCast(OSData, dev->getProperty("ATY,AIO")))) { fDisplayParams = OSDynamicCast( OSDictionary, getProperty("G3AIO")); fDoSet = &AppleOnboardDisplay::setG3AIO; fDoUpdate = &AppleOnboardDisplay::updateNone; } else if( (0 == strcmp("ATY,264LTProA", dev->getName())) || (0 == strcmp("ATY,RageLTPro", dev->getName())) || (0 == strcmp("ATY,264LT-G", dev->getName())) || (0 == strcmp("ATY,264LTPro", dev->getName()))) { fDisplayParams = OSDynamicCast( OSDictionary, getProperty("Backlight1")); fDoSet = &AppleOnboardDisplay::setPMU; fDoUpdate = &AppleOnboardDisplay::updateNone; } else display = 0; if( display) { assert( fDisplayParams ); attach( display ); fFramebuffer = framebuffer; fNotifier = framebuffer->addFramebufferNotification( &AppleOnboardDisplay::framebufferEvent, this, NULL ); display->setProperty( gIODisplayParametersKey, fDisplayParams ); num = OSNumber::withNumber( kAppleOnboardGUID, 64 ); display->setProperty( gIODisplayGUIDKey, num); num->release(); (*fDoUpdate)(this); if( fUsesXPRAM) { UInt8 bytes[2]; SInt32 value, min, max; OSDictionary * params; IODTPlatformExpert * dtPlaform = OSDynamicCast( IODTPlatformExpert, getPlatform() ); if( !dtPlaform || (kIOReturnSuccess != dtPlaform->readXPRAM( 0x50, (UInt8 *) bytes, 2 ))) bytes[0] = bytes[1] = 0; if( (params = getParams( gIODisplayBrightnessKey, 0, &min, &max))) { value = (bytes[0] + (((UInt8) max) + ((UInt8) min)) / 2) & 0xff; setForKey( params, gIODisplayBrightnessKey, value, min, max); } if( (params = getParams( gIODisplayContrastKey, 0, &min, &max))) { value = (bytes[1] + ((UInt8) max)) & 0xff; setForKey( params, gIODisplayContrastKey, value, min, max); } } } return( true ); } OSDictionary * AppleOnboardDisplay::getParams( const OSSymbol * sym, SInt32 * value, SInt32 * min, SInt32 * max ) { OSDictionary * params; OSNumber * num; params = OSDynamicCast( OSDictionary, fDisplayParams->getObject(sym)); if( params) do { if( value) { num = OSDynamicCast( OSNumber, params->getObject(gIODisplayValueKey)); if( !num) continue; *value = num->unsigned32BitValue(); } if( min) { num = OSDynamicCast( OSNumber, params->getObject(gIODisplayMinValueKey)); if( !num) continue; *min = num->unsigned32BitValue(); } if( max) { num = OSDynamicCast( OSNumber, params->getObject(gIODisplayMaxValueKey)); if( !num) continue; *max = num->unsigned32BitValue(); } return( params ); } while( false ); return( 0 ); } bool AppleOnboardDisplay::setForKey( OSDictionary * params, const OSSymbol * sym, SInt32 value, SInt32 min, SInt32 max ) { OSNumber * num; SInt32 adjValue; bool ok; // invert rotation if( sym == gIODisplayRotationKey) adjValue = max - value + min; else adjValue = value; if( (ok = (*fDoSet)( this, params, sym, adjValue ))) { num = OSNumber::withNumber( value, 32 ); params->setObject( gIODisplayValueKey, num ); num->release(); } return( ok ); } IOReturn AppleOnboardDisplay::setProperties( OSObject * properties ) { OSSymbol * sym; OSDictionary * dict; OSDictionary * params; OSNumber * valueNum; OSObject * valueObj; OSDictionary * valueDict; OSIterator * iter; SInt32 min, max, value; bool doCommit = false; bool allOK = true; bool ok; if( !(dict = OSDynamicCast(OSDictionary, properties))) return( kIOReturnUnsupported ); if( dict->getObject(gIODisplayParametersDefaultKey)) { (*fDoSet)( this, 0, gIODisplayParametersDefaultKey, 0 ); (*fDoUpdate)(this); setProperties( fDisplayParams ); } iter = OSCollectionIterator::withCollection( dict ); if( iter) { for( ; (sym = (OSSymbol *) iter->getNextObject()); allOK &= ok) { if( sym == gIODisplayParametersCommitKey) { ok = true; doCommit = true; continue; } if( sym == gIODisplayParametersDefaultKey) { ok = true; continue; } ok = false; if( sym == gIODisplayParametersTheatreModeWindowKey) { OSData * valueData = OSDynamicCast( OSData, dict->getObject(sym) ); if( !valueData || (sizeof(IOGBounds) != valueData->getLength())) continue; ok = setTheatreModeATI( (IOGBounds *) valueData->getBytesNoCopy() ); continue; } if( 0 == (params = getParams( sym, 0, &min, &max))) continue; valueObj = dict->getObject(sym); if( !valueObj) continue; if( (valueDict = OSDynamicCast( OSDictionary, valueObj))) valueObj = valueDict->getObject( gIODisplayValueKey ); valueNum = OSDynamicCast( OSNumber, valueObj ); if( !valueNum) continue; value = valueNum->unsigned32BitValue(); if( value < min) value = min; if( value > max) value = max; ok = setForKey( params, sym, value, min, max ); } iter->release(); } if( doCommit) { (*fDoSet)( this, 0, gIODisplayParametersCommitKey, 0 ); if( fUsesXPRAM) { UInt8 bytes[2]; IODTPlatformExpert * dtPlaform = OSDynamicCast( IODTPlatformExpert, getPlatform() ); if( dtPlaform && (kIOReturnSuccess == dtPlaform->readXPRAM( 0x50, (UInt8 *) bytes, 2 ))) { if( (params = getParams( gIODisplayBrightnessKey, &value, &min, &max))) bytes[0] = value - (min + max) / 2; if( (params = getParams( gIODisplayContrastKey, &value, &min, &max))) bytes[1] = value - max; dtPlaform->writeXPRAM( 0x50, (UInt8 *) bytes, 2 ); } } } return( allOK ? kIOReturnSuccess : kIOReturnError ); } bool AppleOnboardDisplay::addParameter( const OSSymbol * paramName, SInt32 min, SInt32 max ) { OSDictionary * paramDict; OSNumber * num; bool ok = true; paramDict = (OSDictionary *) fDisplayParams->getObject(paramName); if( !paramDict) return( false ); paramDict->setCapacityIncrement(1); num = OSNumber::withNumber( min, 32 ); paramDict->setObject( gIODisplayMinValueKey, num); num->release(); num = OSNumber::withNumber( max, 32 ); paramDict->setObject( gIODisplayMaxValueKey, num); num->release(); return( ok ); } bool AppleOnboardDisplay::setParameter( const OSSymbol * paramName, SInt32 value ) { OSDictionary * paramDict; OSNumber * num; bool ok = true; paramDict = (OSDictionary *) fDisplayParams->getObject(paramName); if( !paramDict) return( false ); // invert rotation if( paramName == gIODisplayRotationKey) { SInt32 min, max; getParams( paramName, NULL, &min, &max ); value = max - value + min; } num = OSNumber::withNumber( value, 32 ); paramDict->setObject( gIODisplayValueKey, num); num->release(); return( ok ); } IOReturn AppleOnboardDisplay::framebufferEvent( OSObject * _self, void * ref, IOFramebuffer *framebuffer, IOIndex event, void * info ) { AppleOnboardDisplay * self = (AppleOnboardDisplay *) _self; IOReturn err; switch(event) { case kIOFBNotifyDisplayModeDidChange: (*self->fDoUpdate)(self); self->setProperties( self->fDisplayParams ); case kIOFBNotifyDisplayModeWillChange: case kIOFBNotifyWillSleep: case kIOFBNotifyDidWake: err = kIOReturnSuccess; break; default: err = kIOReturnUnsupported; break; } return( err); } /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ enum { kATIBacklightControl = 0xc0, kBacklightPowerOff = 0, kBacklightPowerOn = 7 }; struct VDBacklightControlInfo { UInt32 backlightOnOff; UInt32 backlightLevel; UInt32 saveNVRAM; }; bool AppleOnboardDisplay::setATI( AppleOnboardDisplay * self, OSDictionary * params, const OSSymbol * paramName, UInt32 value ) { IONDRVFramebuffer * ndrv = OSDynamicCast( IONDRVFramebuffer, self->fFramebuffer); VDBacklightControlInfo info; IOReturn err; bool ok = false; if( !params) return( true ); if( !ndrv) return( false ); do { bzero(&info, sizeof(info)); err = ndrv->doStatus( kATIBacklightControl, &info); if( err) continue; info.backlightLevel = value; info.saveNVRAM = 1; err = ndrv->doControl( kATIBacklightControl, &info); if( err) continue; ok = true; } while( false ); return( ok ); } bool AppleOnboardDisplay::updateATI( AppleOnboardDisplay * self ) { IONDRVFramebuffer * ndrv = OSDynamicCast( IONDRVFramebuffer, self->fFramebuffer); VDBacklightControlInfo info; IOReturn err; SInt32 value = 0xff; if( !ndrv) return( false ); do { bzero(&info, sizeof(info)); err = ndrv->doStatus( kATIBacklightControl, &info); if( err) continue; value = info.backlightLevel; info.saveNVRAM = 0; ndrv->doControl( kATIBacklightControl, &info); } while( false ); self->setParameter( gIODisplayBrightnessKey, value ); return( true ); } /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ #if 1 #define heathrowBrightnessControl ((volatile UInt8 *)0xf3000032) #define heathrowContrastControl ((volatile UInt8 *)0xf3000033) #endif #if 0 #define defaultBrightness 144 #define defaultContrast 183 #endif bool AppleOnboardDisplay::setG3AIO( AppleOnboardDisplay * self, OSDictionary * params, const OSSymbol * paramName, UInt32 value ) { volatile UInt8 * reg; if( !params) return( true ); if( paramName == gIODisplayBrightnessKey) reg = heathrowBrightnessControl; else if( paramName == gIODisplayContrastKey) reg = heathrowContrastControl; else return( false ); *reg = value; return( true ); } bool AppleOnboardDisplay::updateNone( AppleOnboardDisplay * self ) { // self->setParameter( gIODisplayBrightnessKey, *heathrowBrightnessControl ); // self->setParameter( gIODisplayContrastKey, *heathrowContrastControl ); return( true ); } /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ enum { kPMUSetBrightness = 0x41 }; bool AppleOnboardDisplay::setPMU( AppleOnboardDisplay * self, OSDictionary * params, const OSSymbol * paramName, UInt32 value ) { IOByteCount unused; static UInt8 table[] = { 127,71,69,67,65,63,61,59, 58,56,54,52,50,48,46,44, 42,40,38,37,35,33,31,29, 27,25,23,21,19,18,16,14 }; if( !params) return( true ); ApplePMUSendMiscCommand( kPMUSetBrightness, 1, table + value, &unused, NULL ); return( true ); } /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ enum { kGetVCPFeature = 0x01, kReplyVCPFeature = 0x02, kSetVCPFeature = 0x03, kGetControlKeyMode = 0x04, kReplyControlKeyMode = 0x05, kSetControlKeyMode = 0x06, kGetTimingReport = 0x07, kGetKeyReport = 0x08, kResetVCPFeature = 0x09, kDisableVCPFeature = 0x0A, kEnableVCPFeature = 0x0B, kSaveCurrentSettings = 0x0C }; // VCP minor commands from LGE enum { kDegaussCommand = 0x00, kPresetDefaultCommand = 0x04, kExtBrightnessCommand = 0x10, kExtContrastCommand = 0x12, kRedDriveCommand = 0x16, kGreenDriveCommand = 0x18, kBlueDriveCommand = 0x1A, kHorizontalPositionCommand = 0x20, kHorizontalSizeCommand = 0x22, kPincushionCommand = 0x24, kPincushionBalanceCommand = 0x26, kVerticalPositionCommand = 0x30, kVerticalSizeCommand = 0x32, kParallelogramCommand = 0x40, kTrapezoidCommand = 0x42, kRotationCommand = 0x44, kRedCutoffCommand = 0x80, kGreenCutoffCommand = 0x82, kBlueCutoffCommand = 0x84, kSubContrastCommand = 0x86, kSubBrightnessCommand = 0x88, kABLCommand = 0x8A, kPresetStartCommand = 0xE0, kPresetEndCommand = 0xE2, kClearDataCommand = 0xE4, kSaveDataCommand = 0xEA, kSaveColorCommand = 0xEB, kSaveSystemDataCommand = 0xEC }; enum { kIICReadBufferSize = 4, // this many byte to read to get vcp feature kIICWriteBufferSize = 7, kIICSourceAddress = 0x50, kVCPCommandDataLength = 0x84, kIICBogusSourceAddress = 0xAF, // special address that LGE check to not to go into master mode (Cuda can't do multi master mode) kMinMillisecondsBetweenIICCommands = 35 // Throttle to 30 times a second and round up a bit. }; bool AppleOnboardDisplay::readVCPRange( UInt8 command, SInt32 * oMax, SInt32 * current ) { UInt8 buffer[16]; IOByteCount count; SInt32 max; UInt32 retries; retries = 0; do { buffer[0] = kIICBogusSourceAddress; buffer[1] = kVCPCommandDataLength; buffer[2] = kSetVCPFeature; buffer[3] = command; buffer[4] = 0; buffer[5] = 0; buffer[6] = fIICAddress ^ buffer[0] ^ buffer[1] ^ buffer[2] ^ buffer[3]; count = kIICWriteBufferSize; IOSleep( 100 ); // 100 in 9 AppleCudaWriteIIC( fIICAddress, buffer, &count ); bzero( buffer, sizeof( buffer)); count = kIICReadBufferSize; IOSleep( 50 ); // 50 in 9 AppleCudaReadIIC( fIICAddress + 1, buffer, &count ); max = (buffer[0] << 8) | buffer[1]; } while( (max == 0) && (retries++ < 10)); *oMax = max; *current = (buffer[2] << 8) | buffer[3]; return( max != 0 ); } bool AppleOnboardDisplay::setupVCP( void ) { OSIterator * iter; OSSymbol * sym; OSDictionary * params; OSNumber * num; UInt32 command; SInt32 current, max; IOByteCount count; IOReturn err; current = 0; do { count = 0; IOSleep( 50 ); // 100 in 9 err = AppleCudaWriteIIC( fIICAddress, (UInt8 *) &count, &count ); } while( err && (current++ < 10)); if( kIOReturnSuccess != err) { IOLog("VCP warmup fail (%x)\n", err); return( false ); } iter = OSCollectionIterator::withCollection( fDisplayParams ); if( iter) { while( (sym = (OSSymbol *) iter->getNextObject())) { if( sym == gIODisplayParametersCommitKey) continue; params = OSDynamicCast( OSDictionary, fDisplayParams->getObject(sym)); if( !params) continue; num = (OSNumber *) params->getObject("reg"); if( !num) continue; command = num->unsigned32BitValue(); if( !readVCPRange( command, &max, ¤t )) continue; addParameter( sym, 0, max ); setParameter( sym, current ); } iter->release(); } return( true ); } bool AppleOnboardDisplay::setVCP( AppleOnboardDisplay * self, OSDictionary * params, const OSSymbol * sym, UInt32 value ) { OSNumber * num; UInt8 buffer[16]; IOByteCount count; bool ok = true; UInt8 command; if( sym == gIODisplayParametersDefaultKey) { return( true ); } if( !params) return( true ); num = (OSNumber *) params->getObject("reg"); if( !num) return( false ); command = num->unsigned32BitValue(); if( sym == gIODisplayParametersCommitKey) value = 0; buffer[0] = kIICSourceAddress; buffer[1] = kVCPCommandDataLength; buffer[2] = kSetVCPFeature; buffer[3] = command; buffer[4] = 0; buffer[5] = value; buffer[6] = self->fIICAddress ^ buffer[0] ^ buffer[1] ^ buffer[2] ^ buffer[3] ^ buffer[4] ^ buffer[5]; if( sym == gIODisplayParametersCommitKey) IOSleep( 110 ); else IOSleep( 50 ); // 100 in 9 count = kIICWriteBufferSize; AppleCudaWriteIIC( self->fIICAddress, buffer, &count ); if( sym == gIODisplayParametersCommitKey) IOSleep( 110 ); return( ok ); } /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ enum { kATISetAuxWin = 0x96, kATIGetAuxWin = 0x96, kATISetFader = 0x97, kATIGetFader = 0x97, kAuxWinDelay = 6, kAuxWinPolarity = 0, kEnableAuxWinDelay = 1 }; struct ATIAuxWinRec { UInt16 x; UInt16 y; UInt16 w; UInt16 h; UInt8 enable; UInt8 delay; UInt8 bppDelayEnable; UInt8 polarity; }; struct ATIFaderRec { UInt8 enableFader; }; /* PMU99 I2C command equates (command $9A)*/ enum { kPMUI2CCmd = 0x9A, kI2CStatusBus = 0, /* pseudo bus used for status retrieval*/ kSystemClockBus = 1, kPowerSupplyBus = 2, /* (IVAD is here)*/ kSimpleI2CStream = 0, kSubaddressI2CStream = 1, kCombinedI2CStream = 2, kI2CReplyPendingErr = -4, kI2CTransactionErr = -3, kI2CBusyErr = -2, kI2CParameterErr = -1, kI2CNoErr = 0, kI2CReadData = 1, kI2CDataBufSize = 249 }; struct PMUI2CPB { UInt8 bus; UInt8 xferType; UInt8 secondaryBusNum; UInt8 address; UInt8 subAddr; UInt8 combAddr; UInt8 dataCount; UInt8 data[249]; /* sizeof(PMUI2CPB) = 256*/ }; typedef struct PMUI2CPB PMUI2CPB; #define MAXIICRETRYCOUNT 10 #define STATUS_DATAREAD 1 #define STATUS_OK 0 #define STATUS_BUSY 0xfe static IOReturn ApplePMUReadIIC( UInt8 bus, UInt8 address, UInt8 subAddress, UInt8 * readBuf, IOByteCount count ) { PMUI2CPB iicPB; IOByteCount readLen; UInt32 retries; // loop counter for retry attempts IOReturn ioResult; ioResult = kIOReturnError; // assume error retries = MAXIICRETRYCOUNT; while (retries--) { iicPB.bus = bus; iicPB.xferType = kCombinedI2CStream; iicPB.secondaryBusNum = 0; iicPB.address = address; iicPB.subAddr = subAddress; iicPB.combAddr = 1 + address; iicPB.dataCount = count - 1; readLen = count; readBuf[0] = 0xff; ApplePMUSendMiscCommand( kPMUI2CCmd, 8, (UInt8 *) &iicPB, &readLen, readBuf ); if (readBuf[0] == STATUS_OK) break; // if pb accepted, proceed to status/read phase IOSleep( 15 ); } if (readBuf[0] == STATUS_OK) { retries = MAXIICRETRYCOUNT; while (retries--) { IOSleep( 15 ); iicPB.bus = kI2CStatusBus; readLen = count; readBuf[0] = 0xff; ApplePMUSendMiscCommand( kPMUI2CCmd, 1, (UInt8 *) &iicPB, &readLen, readBuf ); if (readBuf[0] == STATUS_DATAREAD) { ioResult = kIOReturnSuccess; break; } } } return( ioResult ); } static IOReturn ApplePMUWriteIIC( UInt8 bus, UInt8 address, UInt8 subAddress, UInt8 * buffer, IOByteCount count ) { PMUI2CPB iicPB; IOByteCount readLen; UInt8 readBuf[8]; UInt32 retries; // loop counter for retry attempts IOReturn ioResult; ioResult = kIOReturnError; // assume error retries = MAXIICRETRYCOUNT; while (retries--) { iicPB.bus = bus; iicPB.xferType = kSimpleI2CStream; iicPB.secondaryBusNum = 0; iicPB.address = address; iicPB.subAddr = 0; iicPB.combAddr = 0; iicPB.dataCount = 2; iicPB.data[0] = subAddress; bcopy( buffer, &iicPB.data[1], count ); readLen = sizeof( readBuf ); readBuf[0] = 0xff; ApplePMUSendMiscCommand( kPMUI2CCmd, 8 + count, (UInt8 *) &iicPB, &readLen, readBuf ); if (readBuf[0] == STATUS_OK) break; // if pb accepted, proceed to status phase IOSleep( 15 ); } if (readBuf[0] == STATUS_OK) { retries = MAXIICRETRYCOUNT; while (retries--) { IOSleep( 15 ); // attempt to recover status iicPB.bus = kI2CStatusBus; readLen = sizeof( readBuf ); readBuf[0] = 0xff; ApplePMUSendMiscCommand( kPMUI2CCmd, 1, (UInt8 *) &iicPB, &readLen, readBuf ); if (readBuf[0] == STATUS_OK) { ioResult = kIOReturnSuccess; break; } } } return( ioResult ); } bool AppleOnboardDisplay::updateIVAD( AppleOnboardDisplay * self ) { IOReturn err; IODisplayModeID mode; IOIndex depth; IOPixelInformation pixInfo; err = self->fFramebuffer->getCurrentDisplayMode( &mode, &depth ); if( kIOReturnSuccess == err) err = self->fFramebuffer->getPixelInformation( mode, depth, kIOFBSystemAperture, &pixInfo ); if( kIOReturnSuccess == err) switch( pixInfo.activeWidth ) { case 640: self->fModeIndex = 0; break; case 800: default: self->fModeIndex = 1; break; case 1024: self->fModeIndex = 2; break; } self->setParameter( gIODisplayContrastKey, self->fUserPrefs->contrast ); self->setParameter( gIODisplayBrightnessKey, self->fUserPrefs->brightness ); self->setParameter( gIODisplayHorizontalPositionKey, self->fUserPrefs->modeParams[self->fModeIndex].horizontalPosition ^ 0x7f ); self->setParameter( gIODisplayHorizontalSizeKey, self->fUserPrefs->modeParams[self->fModeIndex].horizontalSize ^ 0x7f ); self->setParameter( gIODisplayVerticalPositionKey, self->fUserPrefs->modeParams[self->fModeIndex].verticalPosition ^ 0x7f ); self->setParameter( gIODisplayVerticalSizeKey, self->fUserPrefs->modeParams[self->fModeIndex].verticalSize ); self->setParameter( gIODisplayTrapezoidKey, self->fUserPrefs->modeParams[self->fModeIndex].keystone ); self->setParameter( gIODisplayPincushionKey, self->fUserPrefs->modeParams[self->fModeIndex].pincushion ); self->setParameter( gIODisplayParallelogramKey, self->fUserPrefs->parallelogram ^ 0x7f); self->setParameter( gIODisplayRotationKey, self->fUserPrefs->tilt); self->setParameter( gIODisplayParametersTheatreModeKey, self->fTheatreMode ); return( true ); } bool AppleOnboardDisplay::setupIVAD( void ) { UInt8 buffer[96 + 32]; OSData * data; UInt32 address; SInt32 i; bool ok = false; if( 0 == (data = OSDynamicCast(OSData, fIVAD->getProperty("eeprom-address")))) return( false ); address = *((UInt32 *) data->getBytesNoCopy()); if( !fEEPROM) fEEPROM = IONew( EEPROM, 1 ); if( !fUserPrefs) fUserPrefs = IONew( IVADUserPrefs, 1 ); if( !fEEPROM || !fUserPrefs) return( false ); bzero( buffer, sizeof(buffer) ); for (i = 0; i < (6 * 16); i += 16) { if (kIOReturnSuccess == ApplePMUReadIIC( kPowerSupplyBus, address, i, buffer + i, 17 )) bcopy(1 + buffer + i, buffer + i, 16 ); } bcopy( buffer, fEEPROM, sizeof(EEPROM) ); #if DEBUG IOLog("IVAD EEPROM(%x):\n", fEEPROM->id ); for (int i = 0; i < (6 * 16); i++) { IOLog("%02x ", buffer[i]); if( 15 == (i & 15)) IOLog("\n"); } #endif if( (data = OSDynamicCast(OSData, fIVAD->getProperty(fIVADPrefsKey)))) bcopy( data->getBytesNoCopy(), fUserPrefs, sizeof(IVADUserPrefs)); else { bcopy( fEEPROM->modeParams, fUserPrefs->modeParams, sizeof(fUserPrefs->modeParams)); fUserPrefs->contrast = fEEPROM->stdParams.contrast; fUserPrefs->brightness = fEEPROM->stdParams.brightness; fUserPrefs->parallelogram = fEEPROM->stdParams.parallelogram; fUserPrefs->tilt = fEEPROM->stdParams.tilt; } // fDisplayParams->setCapacityIncrement(1); addParameter( gIODisplayContrastKey, fEEPROM->userLimits.contrast.min, fEEPROM->userLimits.contrast.max ); addParameter( gIODisplayBrightnessKey, fEEPROM->userLimits.brightness.min, fEEPROM->userLimits.brightness.max ); addParameter( gIODisplayHorizontalPositionKey, fEEPROM->userLimits.horizontalPosition.min, fEEPROM->userLimits.horizontalPosition.max ); addParameter( gIODisplayHorizontalSizeKey, fEEPROM->userLimits.horizontalSize.min, fEEPROM->userLimits.horizontalSize.max ); addParameter( gIODisplayVerticalPositionKey, fEEPROM->userLimits.verticalPosition.min, fEEPROM->userLimits.verticalPosition.max ); addParameter( gIODisplayVerticalSizeKey, fEEPROM->userLimits.verticalSize.min, fEEPROM->userLimits.verticalSize.max ); addParameter( gIODisplayTrapezoidKey, fEEPROM->userLimits.keystone.min, fEEPROM->userLimits.keystone.max ); addParameter( gIODisplayPincushionKey, fEEPROM->userLimits.pincushion.min, fEEPROM->userLimits.pincushion.max ); addParameter( gIODisplayParallelogramKey, fEEPROM->userLimits.parallelogram.min, fEEPROM->userLimits.parallelogram.max ); addParameter( gIODisplayRotationKey, fEEPROM->userLimits.tilt.min, fEEPROM->userLimits.tilt.max ); addParameter( gIODisplayParametersTheatreModeKey, 0, 1 ); ATIFaderRec fader; IONDRVFramebuffer * ndrv = OSDynamicCast( IONDRVFramebuffer, fFramebuffer); if( ndrv && (kIOReturnSuccess == ndrv->doStatus( kATIGetFader, &fader))) addParameter( gIODisplayParametersTheatreModeWindowKey, 0, 1 ); return( ok ); } bool AppleOnboardDisplay::setTheatreModeATI( IOGBounds * rect ) { IONDRVFramebuffer * ndrv = OSDynamicCast( IONDRVFramebuffer, fFramebuffer); ATIFaderRec fader; ATIAuxWinRec auxWin; UInt32 newMode; bool ok = true; ok &= (kIOReturnSuccess == ndrv->doControl( kATISetFader, &fader)); ok = (ndrv != 0); if( ok) do { newMode = (rect->maxx != rect->minx); auxWin.enable = true; auxWin.delay = kAuxWinDelay; auxWin.bppDelayEnable = kEnableAuxWinDelay; fader.enableFader = newMode; if( newMode) { auxWin.x = rect->minx; auxWin.y = rect->miny; auxWin.w = rect->maxx - rect->minx; auxWin.h = rect->maxy - rect->miny; auxWin.polarity = kAuxWinPolarity; ok &= (kIOReturnSuccess == ndrv->doControl( kATISetAuxWin, &auxWin)); ok &= (kIOReturnSuccess == ndrv->doControl( kATISetFader, &fader)); } else { auxWin.x = 0; auxWin.y = 0; auxWin.w = 1; auxWin.h = 1; auxWin.polarity = 0; ok &= (kIOReturnSuccess == ndrv->doControl( kATISetFader, &fader)); ok &= (kIOReturnSuccess == ndrv->doControl( kATISetAuxWin, &auxWin)); } } while( false ); return( ok ); } bool AppleOnboardDisplay::setTheatreMode( UInt32 newMode ) { enum { kTMRegCount = 9 }; static const UInt8 regs[kTMRegCount] = { kIVADContrast, kIVADBrightness, kIVADDrive1, kIVADDrive2, kIVADDrive3, kIVADCutoff1, kIVADCutoff2, kIVADCutoff3, kIVADVBLDCLevel }; UInt8 values[kTMRegCount]; bool ok = true; ok = true; newMode = (newMode != 0); if( newMode != fTheatreMode) { if( newMode) { values[0] = fEEPROM->briteParams.contrast; values[1] = fEEPROM->briteParams.brightness; values[2] = fEEPROM->briteParams.drive1; values[3] = fEEPROM->briteParams.drive2; values[4] = fEEPROM->briteParams.drive3; values[5] = fEEPROM->briteParams.cutoff1; values[6] = fEEPROM->briteParams.cutoff2; values[7] = fEEPROM->briteParams.cutoff3; values[8] = fEEPROM->stdParams.vblDCLevel | (fEEPROM->briteParams.gainBoost ? kGainWin : 0); } else { values[0] = fUserPrefs->contrast; values[1] = fUserPrefs->brightness; values[2] = fEEPROM->stdParams.drive1; values[3] = fEEPROM->stdParams.drive2; values[4] = fEEPROM->stdParams.drive3; values[5] = fEEPROM->stdParams.cutoff1; values[6] = fEEPROM->stdParams.cutoff2; values[7] = fEEPROM->stdParams.cutoff3; values[8] = fEEPROM->stdParams.vblDCLevel; } for( int i = 0; i < kTMRegCount; i++) ok &= (kIOReturnSuccess == ApplePMUWriteIIC( kPowerSupplyBus, fIICAddress, regs[i], &values[i], sizeof(UInt8) )); if( ok) fTheatreMode = newMode; } return( ok ); } bool AppleOnboardDisplay::setIVAD( AppleOnboardDisplay * self, OSDictionary * params, const OSSymbol * sym, UInt32 value ) { OSNumber * num; UInt32 reg; UInt8 regValue; bool ok = false; if( sym == gIODisplayParametersDefaultKey) { bcopy( self->fEEPROM->modeParams, self->fUserPrefs->modeParams, sizeof(self->fUserPrefs->modeParams)); self->fUserPrefs->contrast = self->fEEPROM->stdParams.contrast; self->fUserPrefs->brightness = self->fEEPROM->stdParams.brightness; self->fUserPrefs->parallelogram = self->fEEPROM->stdParams.parallelogram; self->fUserPrefs->tilt = self->fEEPROM->stdParams.tilt; return( true ); } else if( sym == gIODisplayParametersCommitKey) { IODTPlatformExpert * dtPlaform = OSDynamicCast( IODTPlatformExpert, getPlatform() ); OSData * data = OSData::withBytesNoCopy( self->fUserPrefs, sizeof(IVADUserPrefs)); if( data && dtPlaform) ok = (kIOReturnSuccess == dtPlaform->writeNVRAMProperty( self->fIVAD, self->fIVADPrefsKey, data )); if( data) data->release(); return( ok ); } else if( sym == gIODisplayParametersTheatreModeKey) return( self->setTheatreMode( value )); if( !params) return( true ); num = (OSNumber *) params->getObject("reg"); if( !num) return( false ); reg = num->unsigned32BitValue(); if( reg & 0x100) regValue = value ^ 0x7f; else regValue = value; ok = (kIOReturnSuccess == ApplePMUWriteIIC( kPowerSupplyBus, self->fIICAddress, reg & 0x1f, ®Value, sizeof(regValue) )); if( ok) { if( sym == gIODisplayContrastKey) self->fUserPrefs->contrast = regValue; else if( sym == gIODisplayBrightnessKey) self->fUserPrefs->brightness = regValue; else if( sym == gIODisplayHorizontalPositionKey) self->fUserPrefs->modeParams[self->fModeIndex].horizontalPosition = regValue; else if( sym == gIODisplayHorizontalSizeKey) self->fUserPrefs->modeParams[self->fModeIndex].horizontalSize = regValue; else if( sym == gIODisplayVerticalPositionKey) self->fUserPrefs->modeParams[self->fModeIndex].verticalPosition = regValue; else if( sym == gIODisplayVerticalSizeKey) self->fUserPrefs->modeParams[self->fModeIndex].verticalSize = regValue; else if( sym == gIODisplayTrapezoidKey) self->fUserPrefs->modeParams[self->fModeIndex].keystone = regValue; else if( sym == gIODisplayPincushionKey) self->fUserPrefs->modeParams[self->fModeIndex].pincushion = regValue; else if( sym == gIODisplayParallelogramKey) self->fUserPrefs->parallelogram = regValue; else if( sym == gIODisplayRotationKey) self->fUserPrefs->tilt = regValue; } return( ok ); } /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ static IOReturn ApplePMUSendMiscCommand( UInt32 command, IOByteCount sendLength, UInt8 * sendBuffer, IOByteCount * readLength, UInt8 * readBuffer ) { struct SendMiscCommandParameterBlock { int command; IOByteCount sLength; UInt8 *sBuffer; IOByteCount *rLength; UInt8 *rBuffer; }; IOReturn ret = kIOReturnError; static IOService * pmu; // Wait for the PMU to show up: if( !pmu) pmu = IOService::waitForService(IOService::serviceMatching("ApplePMU")); SendMiscCommandParameterBlock params = { command, sendLength, sendBuffer, readLength, readBuffer }; if( pmu) ret = pmu->callPlatformFunction( "sendMiscCommand", true, (void*)¶ms, NULL, NULL, NULL ); return( ret ); }