|
|
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.