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