AppleG3SeriesDisplay.cpp [plain text]
#include <IOKit/IOLib.h>
#include <IOKit/graphics/IODisplay.h>
#include <IOKit/ndrvsupport/IOMacOSVideo.h>
#include <Drivers/hidsystem/drvAppleADBDevices/AppleADBButtons.h>
#define kNumber_of_power_states 4
#define kNumber_of_power_levels 32
#define kScreenBit 0x01
#define kPowerOn 0x80
#define kPowerOff 0x00
#define kDisplayOn kScreenBit | kPowerOn
#define kDisplayOff kScreenBit | kPowerOff
class AppleG3SeriesDisplay : public AppleSenseDisplay
{
OSDeclareDefaultStructors(AppleG3SeriesDisplay)
private:
int current_user_brightness; int current_level; IOService * PMUdriver; int * rawTable;
enum {
kPMUpower1Read = 0x19, kPMUReadBrightness = 0x49, kPMUpower1Cntl = 0x11, kPMUSetBrightness = 0x41 };
typedef struct SendMiscCommandParameterBlock {
int command;
IOByteCount sLength;
UInt8 *sBuffer;
IOByteCount *rLength;
UInt8 *rBuffer;
} SendMiscCommandParameterBlock;
typedef SendMiscCommandParameterBlock *SendMiscCommandParameterBlockPtr;
IOReturn localSendMiscCommand(int command, IOByteCount sLength, UInt8 *sBuffer, IOByteCount *rLength, UInt8 *rBuffer);
public:
IOService * probe ( IOService *, SInt32 * );
virtual void initForPM ( IOService* );
virtual IOReturn setPowerState ( unsigned long, IOService* );
virtual unsigned long maxCapabilityForDomainState ( IOPMPowerFlags );
virtual unsigned long initialPowerStateForDomainState ( IOPMPowerFlags );
virtual unsigned long powerStateForDomainState ( IOPMPowerFlags );
virtual void ourButtonHandler ( unsigned int );
virtual void setBrightness ( long );
};
void upButtonHandler(AppleG3SeriesDisplay *);
void downButtonHandler(AppleG3SeriesDisplay *);
static IOPMPowerState ourPowerStates[kNumber_of_power_states] = {
{1,0,0,0,0,0,0,0,0,0,0,0},
{1,IOPMDeviceUsable,0,IOPMPowerOn,0,0,0,0,0,0,0,0},
{1,IOPMDeviceUsable,0,IOPMPowerOn,0,0,0,0,0,0,0,0},
{1,IOPMDeviceUsable+IOPMMaxPerformance,0,IOPMPowerOn,0,0,0,0,0,0,0,0}
};
static int max_brightness_level[kNumber_of_power_states] = {0,1,8,31};
static int HooperTable[ ] = {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 };
bool ourNotificationHandler( OSObject *, void *, IOService * );
#define super AppleSenseDisplay
OSDefineMetaClassAndStructors(AppleG3SeriesDisplay, AppleSenseDisplay)
IOService * AppleG3SeriesDisplay::probe ( IOService * provider, SInt32 * score )
{
IOFramebuffer * framebuffer;
IOService * ret = 0;
UInt32 displayType;
IOIndex ourIndex;
do {
if ( 0 == super::probe( provider, score ) ) {
continue;
}
framebuffer = (IOFramebuffer *)getConnection()->getFramebuffer(); ourIndex = getConnection()->getConnection();
if ( kIOReturnSuccess != framebuffer->getAppleSense(ourIndex,NULL,NULL,NULL,&displayType) ) {
continue;
}
if ( !(displayType == kPanelTFTConnect) ) { continue; }
ret = this;
} while ( false );
return ( ret );
}
IOReturn AppleG3SeriesDisplay::localSendMiscCommand(int command, IOByteCount sLength, UInt8 *sBuffer, IOByteCount *rLength, UInt8 *rBuffer)
{
IOReturn returnValue = kIOReturnError;
SendMiscCommandParameterBlock prmBlock = {command, sLength, sBuffer, rLength, rBuffer};
IOLog("AppleG3SeriesDisplay::localSendMiscCommand 0x%02x %d 0x%08lx 0x%08lx 0x%08lx\n",
command, sLength, sBuffer, rLength, rBuffer);
if (PMUdriver != NULL) {
IOLog("AppleG3SeriesDisplay::localSendMiscCommand calling PMUdriver->callPlatformFunction\n");
returnValue = PMUdriver->callPlatformFunction("sendMiscCommand", true, (void*)&prmBlock, NULL, NULL, NULL);
}
IOLog("AppleG3SeriesDisplay::localSendMiscCommand end 0x%08lx\n", returnValue);
return returnValue;
}
void AppleG3SeriesDisplay::initForPM ( IOService * provider )
{
unsigned long i;
UInt8 PMUreceiveBuffer[10]; IOByteCount unused = sizeof(PMUreceiveBuffer);
displayPMVars->powerControllable = true;
PMinit();
PMUdriver = waitForService(serviceMatching("ApplePMU"));
rawTable = HooperTable;
localSendMiscCommand(kPMUpower1Read,0, NULL, &unused,PMUreceiveBuffer);
if ( PMUreceiveBuffer[0] & kScreenBit ) { unused = sizeof(PMUreceiveBuffer);
localSendMiscCommand(kPMUReadBrightness,0, NULL, &unused,PMUreceiveBuffer); current_user_brightness = kNumber_of_power_levels - 1; current_level = kNumber_of_power_levels - 1;
for ( i = 0; i < kNumber_of_power_levels; i++ ) {
if ( PMUreceiveBuffer[0] >= rawTable[i] ) {
current_user_brightness = i;
current_level = i;
break;
}
}
}
else { current_user_brightness = 0;
current_level = 0;
}
addNotification( gIOPublishNotification,serviceMatching("AppleADBButtons"), (IOServiceNotificationHandler)ourNotificationHandler, this, 0 );
provider->joinPMtree(this); registerPowerDriver(this,ourPowerStates,kNumber_of_power_states); }
bool ourNotificationHandler( OSObject * us, void * ref, IOService * yourDevice )
{
if ( yourDevice != NULL ) {
((AppleADBButtons *)yourDevice)->registerForButton(kBrightness_up,(IOService *)us,(button_handler)upButtonHandler,true);
((AppleADBButtons *)yourDevice)->registerForButton(kBrightness_down,(IOService *)us,(button_handler)downButtonHandler,true);
}
return true;
}
IOReturn AppleG3SeriesDisplay::setPowerState ( unsigned long powerStateOrdinal, IOService* whatDevice )
{
UInt8 displayOn = kDisplayOn;
UInt8 displayOff = kDisplayOff;
unsigned long i;
if ( powerStateOrdinal < kNumber_of_power_states ) {
if ( powerStateOrdinal > pm_vars->myCurrentState ) { if ( pm_vars->myCurrentState == 0 ) { IOByteCount unused = 0;
localSendMiscCommand(kPMUpower1Cntl,1, &displayOn, &unused,NULL);
}
current_level = max_brightness_level[powerStateOrdinal];
if ( current_user_brightness < current_level ) {
current_level = current_user_brightness; }
setBrightness(current_level);
for ( i = 0; i < kNumber_of_power_states; i++ ) { if ( current_level <= max_brightness_level[i] ) {
break;
}
}
if ( pm_vars->myCurrentState > i ) {
changePowerStateToPriv(i);
}
}
if ( powerStateOrdinal < pm_vars->myCurrentState ) { if (powerStateOrdinal == 0 ) { IOByteCount unused = 0;
localSendMiscCommand(kPMUpower1Cntl,1, &displayOff, &unused,NULL); current_level = max_brightness_level[powerStateOrdinal];
}
else {
if ( current_level > max_brightness_level[powerStateOrdinal] ) { current_level = max_brightness_level[powerStateOrdinal];
setBrightness(current_level);
}
}
}
}
return IOPMAckImplied;
}
unsigned long AppleG3SeriesDisplay::maxCapabilityForDomainState ( IOPMPowerFlags domainState )
{
if ( domainState & IOPMPowerOn ) {
return kNumber_of_power_states-1;
}
return 0;
}
unsigned long AppleG3SeriesDisplay::initialPowerStateForDomainState ( IOPMPowerFlags domainState )
{
long unsigned i;
if ( domainState & IOPMPowerOn ) { for ( i = 0; i < kNumber_of_power_states; i++ ) { if ( current_level <= max_brightness_level[i] ) { return i;
break;
}
}
}
return 0; }
unsigned long AppleG3SeriesDisplay::powerStateForDomainState ( IOPMPowerFlags domainState )
{
long unsigned i;
if ( domainState & IOPMPowerOn ) { for ( i = 0; i < kNumber_of_power_states; i++ ) { if ( current_level <= max_brightness_level[i] ) { return i;
}
}
}
return 0; }
void upButtonHandler(AppleG3SeriesDisplay * us )
{
((AppleG3SeriesDisplay *)us)->ourButtonHandler(kBrightness_up);
}
void downButtonHandler(AppleG3SeriesDisplay * us )
{
((AppleG3SeriesDisplay *)us)->ourButtonHandler(kBrightness_down);
}
void AppleG3SeriesDisplay::ourButtonHandler ( unsigned int keycode )
{ if ( ! displayPMVars->displayIdle ) { switch (keycode) {
case kBrightness_up: if (current_level < max_brightness_level[pm_vars->myCurrentState] ) {
current_level++;
current_user_brightness = current_level;
setBrightness(current_level);
}
else {
if ( pm_vars->myCurrentState < (kNumber_of_power_states-1) ) {
current_user_brightness++; if ( changePowerStateToPriv(pm_vars->myCurrentState + 1) != IOPMNoErr ) { current_user_brightness--; }
}
}
break;
case kBrightness_down: if ( pm_vars->myCurrentState > 0 ) { if ( current_level > 0 ) {
current_level--;
current_user_brightness = current_level;
setBrightness(current_level);
if (current_level <= max_brightness_level[pm_vars->myCurrentState - 1] ) { changePowerStateToPriv(pm_vars->myCurrentState - 1); }
}
}
break;
}
}
}
void AppleG3SeriesDisplay::setBrightness ( long brightness )
{
IOByteCount unused = 0;
UInt8 setBrightnessBuffer;
setBrightnessBuffer = (UInt8)rawTable[brightness];
localSendMiscCommand(kPMUSetBrightness,1, &setBrightnessBuffer, &unused,NULL);
}