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/IOUserClient.h>
25#include <IOKit/IOTimerEventSource.h>
26
27#define IOFRAMEBUFFER_PRIVATE
28#include <IOKit/IOHibernatePrivate.h>
29#include <IOKit/graphics/IOGraphicsPrivate.h>
30#include <IOKit/graphics/IODisplay.h>
31#include <IOKit/ndrvsupport/IOMacOSVideo.h>
32#include <IOKit/pwr_mgt/RootDomain.h>
33#include <IOKit/pwr_mgt/IOPM.h>
34
35/*
36    We further divide the actual display panel brightness levels into four
37    IOKit power states which we export to our superclass.
38
39    In the lowest state, the display is off.  This state consists of only one
40    of the brightness levels, the lowest. In the next state it is in the dimmest
41    usable state. The highest state consists of all the brightness levels.
42
43    The display has no state or configuration or programming that would be
44    saved/restored over power state changes, and the driver does not register
45    with the superclass as an interested driver.
46
47    This driver doesn't have much to do. It changes between the four power state
48    brightnesses on command from the superclass, and it notices which brightness
49    level the user has set.
50
51    The only smart thing it does is keep track of which of the brightness levels
52    the user has selected, and it never exceeds that on command from the display
53    device object.
54*/
55
56/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
57
58#define super IODisplay
59
60OSDefineMetaClassAndStructors(IOBacklightDisplay, IODisplay)
61
62/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
63
64OSMetaClassDefineReservedUnused(IOBacklightDisplay, 0);
65OSMetaClassDefineReservedUnused(IOBacklightDisplay, 1);
66OSMetaClassDefineReservedUnused(IOBacklightDisplay, 2);
67OSMetaClassDefineReservedUnused(IOBacklightDisplay, 3);
68OSMetaClassDefineReservedUnused(IOBacklightDisplay, 4);
69OSMetaClassDefineReservedUnused(IOBacklightDisplay, 5);
70OSMetaClassDefineReservedUnused(IOBacklightDisplay, 6);
71OSMetaClassDefineReservedUnused(IOBacklightDisplay, 7);
72OSMetaClassDefineReservedUnused(IOBacklightDisplay, 8);
73OSMetaClassDefineReservedUnused(IOBacklightDisplay, 9);
74
75/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
76
77class AppleBacklightDisplay : public IOBacklightDisplay
78{
79    OSDeclareDefaultStructors(AppleBacklightDisplay)
80
81protected:
82    // User preferred brightness level
83//    SInt32      fCurrentUserBrightness;
84    UInt32      fCurrentPowerState;
85    SInt32      fMinBrightness;
86    SInt32      fMaxBrightness;
87
88    IOInterruptEventSource * fDeferredEvents;
89
90    IOTimerEventSource *     fFadeTimer;
91	AbsoluteTime		     fFadeDeadline;
92	AbsoluteTime		     fFadeInterval;
93	uint32_t				 fFadeState;
94	uint32_t				 fFadeStateEnd;
95	uint32_t				 fFadeStateFadeMin;
96	uint32_t				 fFadeStateFadeDelta;
97    uint8_t                  fClamshellSlept;
98	uint8_t					 fDisplayDims;
99	uint8_t					 fProviderPower;
100	uint8_t					 fFadeBacklight;
101	uint8_t					 fFadeGamma;
102	uint8_t					 fFadeDown;
103	uint8_t					 fFadeAbort;
104
105public:
106
107    // IOService overrides
108    virtual IOService * probe( IOService *, SInt32 * );
109    virtual bool start( IOService * provider );
110    virtual void stop( IOService * provider );
111
112    virtual IOReturn setPowerState( unsigned long, IOService * );
113    virtual unsigned long maxCapabilityForDomainState( IOPMPowerFlags );
114    virtual unsigned long initialPowerStateForDomainState( IOPMPowerFlags );
115    virtual unsigned long powerStateForDomainState( IOPMPowerFlags );
116
117    // IODisplay overrides
118    virtual void initPowerManagement( IOService * );
119    virtual bool doIntegerSet( OSDictionary * params,
120                               const OSSymbol * paramName, UInt32 value );
121    virtual bool doUpdate( void );
122    virtual void makeDisplayUsable( void );
123    virtual IOReturn framebufferEvent( IOFramebuffer * framebuffer,
124                                       IOIndex event, void * info );
125
126private:
127	bool updatePowerParam(void);
128    void handlePMSettingCallback(const OSSymbol *, OSObject *, uintptr_t);
129    static void _deferredEvent( OSObject * target,
130                                IOInterruptEventSource * evtSrc, int intCount );
131    void fadeAbort(void);
132    void fadeWork(IOTimerEventSource * sender);
133};
134
135/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
136
137#undef super
138#define super IOBacklightDisplay
139
140OSDefineMetaClassAndStructors(AppleBacklightDisplay, IOBacklightDisplay)
141
142/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
143
144//#define kIOBacklightUserBrightnessKey   "IOBacklightUserBrightness"
145#define fPowerUsesBrightness	fMaxBrightness
146
147#define IOG_FADE 1
148
149enum
150{
151    // fFadeState
152    kFadeIdle        = (1 << 24),
153    kFadePostDelay   = (2 << 24),
154    kFadeUpdatePower = (3 << 24),
155
156	kFadeDimLevel    = ((uint32_t) (0.75f * 1024)),
157	kFadeMidLevel    = ((uint32_t) (0.50f * 1024)),
158};
159
160/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
161// probe
162//
163
164IOService * AppleBacklightDisplay::probe( IOService * provider, SInt32 * score )
165{
166    IOFramebuffer *     framebuffer;
167    IOService *         ret = 0;
168    UInt32              displayType;
169    uintptr_t           connectFlags;
170
171    do
172    {
173        if (!gIOFBHaveBacklight)
174            continue;
175
176        if (!super::probe(provider, score))
177            continue;
178
179        framebuffer = (IOFramebuffer *) getConnection()->getFramebuffer();
180
181        for (IOItemCount idx = 0; idx < framebuffer->getConnectionCount(); idx++)
182        {
183            if (kIOReturnSuccess != framebuffer->getAttributeForConnection(idx,
184                    kConnectionFlags, &connectFlags))
185                continue;
186            if (0 == (kIOConnectionBuiltIn & connectFlags))
187                continue;
188            if (kIOReturnSuccess != framebuffer->getAppleSense(idx, NULL, NULL, NULL, &displayType))
189                continue;
190            if ((kPanelTFTConnect != displayType)
191                    && (kGenericLCD != displayType)
192                    && (kPanelFSTNConnect != displayType))
193                continue;
194
195            ret = this;         // yes, we will control the panel
196            break;
197        }
198    }
199    while (false);
200
201    return (ret);
202}
203
204bool AppleBacklightDisplay::start( IOService * provider )
205{
206    IOFramebuffer * fb;
207    if (!super::start(provider)) return (false);
208
209	fClamshellSlept = gIOFBCurrentClamshellState;
210    fb = getConnection()->getFramebuffer();
211
212    fDeferredEvents = IOInterruptEventSource::interruptEventSource(this, _deferredEvent);
213    if (fDeferredEvents) fb->getControllerWorkLoop()->addEventSource(fDeferredEvents);
214
215	fFadeTimer = IOTimerEventSource::timerEventSource(this,
216								OSMemberFunctionCast(IOTimerEventSource::Action, this,
217													&AppleBacklightDisplay::fadeWork));
218    if (fFadeTimer) fb->getControllerWorkLoop()->addEventSource(fFadeTimer);
219
220	fFadeState = kFadeIdle;
221
222    fb->setProperty(kIOFBBuiltInKey, this, 0);
223
224    return (true);
225}
226
227void AppleBacklightDisplay::stop( IOService * provider )
228{
229    if (fDeferredEvents)
230    {
231        getConnection()->getFramebuffer()->getControllerWorkLoop()->removeEventSource(fDeferredEvents);
232        fDeferredEvents->release();
233        fDeferredEvents = 0;
234    }
235
236    fadeAbort();
237    if (fFadeTimer)
238    {
239    	fFadeTimer->disable();
240        getConnection()->getFramebuffer()->getControllerWorkLoop()->removeEventSource(fFadeTimer);
241        fFadeTimer->release();
242	    fFadeTimer = 0;
243    }
244
245    return (super::stop(provider));
246}
247
248
249/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
250// initForPM
251//
252// This method overrides the one in IODisplay to do PowerBook-only
253// power management of the display.
254
255void AppleBacklightDisplay::initPowerManagement( IOService * provider )
256{
257    OSDictionary * displayParams;
258	OSObject *     obj;
259    OSNumber *     num;
260
261    static const IOPMPowerState ourPowerStates[kIODisplayNumPowerStates] = {
262        // version,
263        //   capabilityFlags,      outputPowerCharacter, inputPowerRequirement,
264        { 1, 0,                                     0, 0,           0,0,0,0,0,0,0,0 },
265        { 1, 0,                                     0, 0,           0,0,0,0,0,0,0,0 },
266        { 1, IOPMDeviceUsable,                      0, kIOPMPowerOn, 0,0,0,0,0,0,0,0 },
267        { 1, IOPMDeviceUsable | IOPMMaxPerformance, 0, kIOPMPowerOn, 0,0,0,0,0,0,0,0 }
268        // staticPower, unbudgetedPower, powerToAttain, timeToAttain, settleUpTime,
269        // timeToLower, settleDownTime, powerDomainBudget
270    };
271
272    // Check initial state of "DisplaySleepUsesDim"
273    obj = getPMRootDomain()->copyPMSetting(
274                    const_cast<OSSymbol *>(gIOFBPMSettingDisplaySleepUsesDimKey));
275    fDisplayDims = (!(num = OSDynamicCast(OSNumber, obj)) || (num->unsigned32BitValue()));
276    if (obj) obj->release();
277
278	fCurrentPowerState = -1U;
279
280    displayParams = OSDynamicCast(OSDictionary, copyProperty(gIODisplayParametersKey));
281    if (displayParams)
282    {
283		SInt32 value, min, max;
284
285        if (getIntegerRange(displayParams, gIODisplayPowerStateKey,
286                             &value, &min, &max))
287        {
288        }
289		else
290		{
291			fMinBrightness = 0;
292			fMaxBrightness = 255;
293		}
294#if IOG_FADE
295		OSDictionary * newParams;
296		newParams = OSDictionary::withDictionary(displayParams);
297		addParameter(newParams, gIODisplayFadeTime1Key, 0, 10000);
298		setParameter(newParams, gIODisplayFadeTime1Key, 500);
299		addParameter(newParams, gIODisplayFadeTime2Key, 0, 10000);
300		setParameter(newParams, gIODisplayFadeTime2Key, 4000);
301		addParameter(newParams, gIODisplayFadeTime3Key, 0, 10000);
302		setParameter(newParams, gIODisplayFadeTime3Key, 500);
303		addParameter(newParams, gIODisplayFadeStyleKey, 0, 10);
304		setParameter(newParams, gIODisplayFadeStyleKey, 0);
305		setProperty(gIODisplayParametersKey, newParams);
306		newParams->release();
307#endif
308        displayParams->release();
309    }
310
311    // initialize superclass variables
312    PMinit();
313    // attach into the power management hierarchy
314    provider->joinPMtree(this);
315
316    // register ourselves with policy-maker (us)
317    registerPowerDriver(this, (IOPMPowerState *) ourPowerStates, kIODisplayNumPowerStates);
318}
319
320/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
321// setPowerState
322//
323
324//#define DEBGFADE(fmt, args...) do { kprintf(fmt, ## args); } while(false)
325#define DEBGFADE(fmt, args...) do {} while(false)
326
327IOReturn AppleBacklightDisplay::setPowerState( unsigned long powerState, IOService * whatDevice )
328{
329    IOReturn ret = IOPMAckImplied;
330    UInt32   fromPowerState;
331
332    if (powerState >= kIODisplayNumPowerStates)
333        return (IOPMAckImplied);
334
335    IOFramebuffer * framebuffer = (IOFramebuffer *) getConnection()->getFramebuffer();
336
337    framebuffer->fbLock();
338
339    if (isInactive() || (fCurrentPowerState == powerState))
340    {
341        framebuffer->fbUnlock();
342        return (IOPMAckImplied);
343    }
344    fromPowerState = fCurrentPowerState;
345    fCurrentPowerState = powerState;
346	if (fCurrentPowerState) fProviderPower = true;
347
348	OSObject * obj;
349	if ((!powerState) && (obj = copyProperty(kIOHibernatePreviewActiveKey, gIOServicePlane)))
350	{
351		obj->release();
352	}
353	else
354	{
355#if IOG_FADE
356        SInt32         current, min, max, steps;
357        OSDictionary * displayParams;
358		uint32_t       fadeTime;
359		uint32_t       dimFade;
360		bool           doFadeDown, doFadeGamma, doFadeBacklight;
361
362        displayParams = OSDynamicCast(OSDictionary, copyProperty(gIODisplayParametersKey));
363		fadeTime        = 0;
364	    doFadeDown      = true;
365	    doFadeGamma     = false;
366	    doFadeBacklight = true;
367
368		DEBGFADE("AppleBacklight: ps [%d->%ld]\n", fromPowerState, powerState);
369
370		if (gIOGFades
371			&& displayParams
372			&& (getIntegerRange(displayParams, gIODisplayBrightnessFadeKey, NULL, &min, &max))
373			&& (getIntegerRange(displayParams, gIODisplayBrightnessKey, &current, NULL, NULL))
374			&& current
375			&& !fFadeAbort)
376		{
377			if (current < ((kFadeMidLevel * max) / 1024)) dimFade = max;
378			else                                          dimFade = (kFadeDimLevel * max) / 1024;
379
380			if (-1U == fromPowerState) { /* boot */ }
381			else if ((powerState > fromPowerState) && (1 >= fromPowerState))
382			{
383				// fade up from off
384				fadeTime    = gIODisplayFadeTime3*1000;
385				doFadeGamma = true;
386				doFadeDown  = false;
387			}
388			if ((3 == powerState) && (1 >= fromPowerState))
389			{
390				// fade up from off
391				fadeTime   = gIODisplayFadeTime3*1000;
392				doFadeDown = false;
393			}
394			if ((3 == powerState) && (2 == fromPowerState))
395			{
396				// fade up from dim
397				fadeTime   = gIODisplayFadeTime3*1000;
398				max        = dimFade;
399				doFadeDown = false;
400			}
401			else if ((0 == powerState) && (3 == fromPowerState))
402			{
403				// user initiated -> off
404				fadeTime    = gIODisplayFadeTime1*1000;
405				doFadeGamma = true;
406			}
407			else if (1 != gIODisplayFadeStyle)
408			{
409				 if ((2 == powerState) && (3 == fromPowerState))
410				 {
411					 // idle initiated -> dim
412					 fadeTime = gIODisplayFadeTime1*1000;
413			         max      = dimFade;
414				 }
415				 if ((1 == powerState) && (2 == fromPowerState))
416				 {
417					 // idle initiated -> off
418					 fadeTime    = gIODisplayFadeTime1*1000;
419					 doFadeBacklight = (dimFade != max);
420					 if (doFadeBacklight) current = max - dimFade;
421					 doFadeGamma = true;
422				 }
423			}
424			else if (1 == gIODisplayFadeStyle)
425			{
426				 if ((2 == powerState) && (3 == fromPowerState))
427				 {
428					 // idle initiated
429					 fCurrentPowerState = 1;
430					 fadeTime           = gIODisplayFadeTime2*1000;
431					 doFadeGamma        = true;
432				 };
433			}
434			DEBGFADE("AppleBacklight: fadeTime %d style %d abort %d\n", fadeTime, gIODisplayFadeStyle, fFadeAbort);
435		}
436
437		if (fadeTime)
438		{
439			steps = fadeTime / 16667;
440
441			DEBGFADE("AppleBacklight: p %d -> %ld, c %d -> m %d\n", fromPowerState, powerState, current, max);
442
443			if (current > max)   current = max;
444
445			fFadeStateFadeMin   = max - current;
446			fFadeStateFadeDelta = current;
447			if (steps > fFadeStateFadeDelta) steps = fFadeStateFadeDelta;
448
449			fFadeDown      = doFadeDown;
450			fFadeGamma     = doFadeGamma;
451			fFadeBacklight = doFadeBacklight;
452
453			DEBGFADE("AppleBacklight:  %d -> %d\n", fFadeStateFadeMin, fFadeStateFadeDelta);
454
455			fFadeState      = 0;
456			if (!fFadeDown) updatePowerParam();
457
458			fFadeDeadline = mach_absolute_time();
459			fadeTime     /= steps;
460			fFadeStateEnd = (steps - 1);
461		    if (framebuffer->isWakingFromHibernateGfxOn()) fFadeState = fFadeStateEnd;
462			clock_interval_to_absolutetime_interval(fadeTime, kMicrosecondScale, &fFadeInterval);
463			fadeWork(fFadeTimer);
464			if (fFadeDown)  ret = 20 * 1000 * 1000;
465		}
466		else
467		{
468			updatePowerParam();
469			fFadeAbort = false;
470		}
471#else
472        updatePowerParam();
473#endif
474	}
475
476	if (!fCurrentPowerState) fProviderPower = false;
477
478    framebuffer->fbUnlock();
479
480    return (ret);
481}
482
483/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
484
485void AppleBacklightDisplay::fadeAbort(void)
486{
487    OSDictionary * displayParams;
488
489	if (kFadeIdle == fFadeState) return;
490	displayParams = OSDynamicCast(OSDictionary, copyProperty(gIODisplayParametersKey));
491	if (!displayParams) return;
492
493	// abort
494	DEBGFADE("AppleBacklight: fadeAbort\n");
495	doIntegerSet(displayParams, gIODisplayBrightnessFadeKey, 0);
496	if (fFadeGamma)
497	{
498		doIntegerSet(displayParams, gIODisplayGammaScaleKey, 65536);
499		doIntegerSet(displayParams, gIODisplayParametersFlushKey, 0);
500	}
501	displayParams->release();
502	if (fFadeDown)  acknowledgeSetPowerState();
503	fFadeState = kFadeIdle;
504}
505
506void AppleBacklightDisplay::fadeWork(IOTimerEventSource * sender)
507{
508    OSDictionary * displayParams;
509	SInt32 fade, gamma, point;
510
511	DEBGFADE("AppleBacklight: fadeWork(fFadeStateEnd %d, fFadeState %d, %d, fFadeStateEnd %d)\n",
512			fFadeStateEnd, fFadeState & 0xffff, fFadeState >> 24, fFadeStateEnd);
513
514	if (kFadeIdle == fFadeState) return;
515	displayParams = OSDynamicCast(OSDictionary, copyProperty(gIODisplayParametersKey));
516	if (!displayParams) return;
517
518    fFadeAbort = (fFadeDown && !fDisplayPMVars->displayIdle);
519
520	if (fFadeAbort) fadeAbort();
521	else if (fFadeState <= fFadeStateEnd)
522    {
523		point = fFadeState;
524		if (!fFadeDown) point = (fFadeStateEnd - point);
525		if (fFadeBacklight)
526		{
527			if (!fFadeDown && !point) fade = 0;
528			else
529			{
530				fade = ((point * fFadeStateFadeDelta) / fFadeStateEnd);
531				fade = fFadeStateFadeMin + fade;
532			}
533			DEBGFADE("AppleBacklight: backlight: %d\n", fade);
534			doIntegerSet(displayParams, gIODisplayBrightnessFadeKey, fade);
535		}
536		if (fFadeGamma)
537		{
538			gamma = 65536 - ((point * 65536) / fFadeStateEnd);
539			DEBGFADE("AppleBacklight: gamma: %d\n", gamma);
540			doIntegerSet(displayParams, gIODisplayGammaScaleKey, gamma);
541			doIntegerSet(displayParams, gIODisplayParametersFlushKey, 0);
542		}
543
544		fFadeState++;
545		if (fFadeState > fFadeStateEnd)
546		{
547			if (fFadeDown) updatePowerParam();
548			fFadeState = kFadePostDelay;
549			clock_interval_to_absolutetime_interval(500, kMillisecondScale, &fFadeInterval);
550		}
551	}
552	else if (kFadePostDelay == fFadeState)
553	{
554		fFadeState = kFadeIdle;
555	}
556
557	if (kFadeIdle == fFadeState)
558	{
559	    DEBGFADE("AppleBacklight: fadeWork ack\n");
560	    if (fFadeDown)  acknowledgeSetPowerState();
561	}
562	else
563	{
564		ADD_ABSOLUTETIME(&fFadeDeadline, &fFadeInterval);
565		fFadeTimer->wakeAtTime(fFadeDeadline);
566	}
567}
568
569/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
570
571void AppleBacklightDisplay::makeDisplayUsable( void )
572{
573    if (kIODisplayMaxPowerState == fCurrentPowerState)
574        setPowerState(fCurrentPowerState, this);
575    super::makeDisplayUsable();
576}
577
578/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
579// maxCapabilityForDomainState
580//
581// This simple device needs only power.  If the power domain is supplying
582// power, the display can go to its highest state.  If there is no power
583// it can only be in its lowest state, which is off.
584
585unsigned long AppleBacklightDisplay::maxCapabilityForDomainState( IOPMPowerFlags domainState )
586{
587    if (domainState & IOPMPowerOn)
588        return (kIODisplayMaxPowerState);
589    else
590        return (0);
591}
592
593/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
594// initialPowerStateForDomainState
595//
596// The power domain may be changing state.  If power is on in the new
597// state, that will not affect our state at all.  If domain power is off,
598// we can attain only our lowest state, which is off.
599
600unsigned long AppleBacklightDisplay::initialPowerStateForDomainState( IOPMPowerFlags domainState )
601{
602    if (domainState & IOPMPowerOn)
603        return (kIODisplayMaxPowerState);
604    else
605        return (0);
606}
607
608/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
609// powerStateForDomainState
610//
611// The power domain may be changing state.  If power is on in the new
612// state, that will not affect our state at all.  If domain power is off,
613// we can attain only our lowest state, which is off.
614
615unsigned long AppleBacklightDisplay::powerStateForDomainState( IOPMPowerFlags domainState )
616{
617    if (domainState & IOPMPowerOn)
618        return (kIODisplayMaxPowerState);
619    else
620        return (0);
621}
622
623/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
624
625// Alter the backlight brightness by user request.
626
627bool AppleBacklightDisplay::doIntegerSet( OSDictionary * params,
628                                       const OSSymbol * paramName, UInt32 value )
629{
630    if ((paramName == gIODisplayParametersCommitKey)
631        && (kIODisplayMaxPowerState != fCurrentPowerState))
632        return (true);
633
634    if (paramName == gIODisplayBrightnessKey)
635    {
636#if 0
637        fCurrentUserBrightness = value;
638        getPMRootDomain()->setProperty(kIOBacklightUserBrightnessKey, fCurrentUserBrightness, 32);
639#endif
640        if (fPowerUsesBrightness && fClamshellSlept)
641			value = 0;
642    }
643
644	return (super::doIntegerSet(params, paramName, value));
645}
646
647bool AppleBacklightDisplay::doUpdate( void )
648{
649    bool ok;
650
651    ok = super::doUpdate();
652
653#if 0
654    OSDictionary * displayParams;
655    if (fDisplayPMVars
656        && (displayParams = OSDynamicCast(OSDictionary, copyProperty(gIODisplayParametersKey))))
657    {
658        setParameter(displayParams, gIODisplayBrightnessKey, fCurrentUserBrightness);
659        displayParams->release();
660    }
661#endif
662
663    return (ok);
664}
665
666/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
667
668bool AppleBacklightDisplay::updatePowerParam(void)
669{
670    OSDictionary * displayParams;
671	SInt32 		   value, current;
672	bool	       ret;
673
674#if DEBUG
675    IOLog("brightness[%d,%d] %d\n", (int) fCurrentPowerState, (int) gIOFBLastClamshellState, (int) value);
676    if (!getControllerWorkLoop()->inGate())
677        OSReportWithBacktrace("AppleBacklightDisplay::updatePowerParam !inGate\n");
678#endif
679
680	DEBG1("B", " fProviderPower %d, fClamshellSlept %d, fCurrentPowerState %d\n",
681			fProviderPower, fClamshellSlept, fCurrentPowerState);
682
683	if (!fProviderPower) return (false);
684
685    displayParams = OSDynamicCast(OSDictionary, copyProperty(gIODisplayParametersKey));
686    if (!displayParams) return (false);
687
688	value = fClamshellSlept ? 0 : fCurrentPowerState;
689
690	if (fPowerUsesBrightness)
691	{
692		switch (value)
693		{
694			case 0:
695				value = 0;
696				break;
697			case 1:
698				value = fMinBrightness;
699				break;
700			case 2:
701				value = fDisplayDims ? (fMinBrightness + 1) : fMaxBrightness;
702				break;
703			case 3:
704				value = fMaxBrightness;
705				break;
706		}
707        if (getIntegerRange(displayParams, gIODisplayBrightnessKey, &current, NULL, NULL)
708		  && (value > current))
709			value = current;
710		//if(gIOFBSystemPower)
711		if (value <= fMinBrightness)
712			value = 0;
713		ret = super::doIntegerSet(displayParams, gIODisplayBrightnessKey, value);
714	}
715	else
716	{
717		switch (value)
718		{
719			case 0:
720				value = kIODisplayPowerStateOff;
721				break;
722			case 1:
723				value = kIODisplayPowerStateOff;
724				break;
725			case 2:
726				value = (fDisplayDims && (kFadeIdle == fFadeState)) ? kIODisplayPowerStateMinUsable : kIODisplayPowerStateOn;
727				break;
728			case 3:
729				value = kIODisplayPowerStateOn;
730				break;
731		}
732		DEBG1("B", " dsyp %d\n", value);
733		ret = super::doIntegerSet(displayParams, gIODisplayPowerStateKey, value);
734#if IOG_FADE2
735        if (kIODisplayPowerStateOff == value) IOSleep(700);
736#endif
737	}
738
739    displayParams->release();
740
741    return (ret);
742}
743
744/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
745
746void AppleBacklightDisplay::_deferredEvent( OSObject * target,
747        IOInterruptEventSource * evtSrc, int intCount )
748{
749    AppleBacklightDisplay * self = (AppleBacklightDisplay *) target;
750
751	self->updatePowerParam();
752}
753
754IOReturn AppleBacklightDisplay::framebufferEvent( IOFramebuffer * framebuffer,
755        IOIndex event, void * info )
756{
757    if ((kIOFBNotifyDidWake == event) && (info))
758    {
759	    fProviderPower = true;
760//		fCurrentPowerState = kIODisplayMaxPowerState;
761//		updatePowerParam();
762    }
763    else if (kIOFBNotifyClamshellChange == event)
764    {
765        if (kOSBooleanTrue == info)
766        {
767#if LCM_HWSLEEP
768            fConnection->getFramebuffer()->changePowerStateTo(0);
769#endif
770            fClamshellSlept = true;
771        }
772        else if (fClamshellSlept)
773        {
774            fClamshellSlept = false;
775        }
776        // may be in the right power state already, but wrong brightness because
777        // of the clamshell state at setPowerState time.
778        if (fDeferredEvents)
779            fDeferredEvents->interruptOccurred(0, 0, 0);
780    }
781    else if (kIOFBNotifyProbed == event)
782    {
783        if (fDeferredEvents)
784            fDeferredEvents->interruptOccurred(0, 0, 0);
785    }
786    else if (kIOFBNotifyDisplayDimsChange == event)
787    {
788		UInt8 newValue = (info != NULL);
789		if (newValue != fDisplayDims)
790		{
791			fDisplayDims = newValue;
792			if (fDeferredEvents)
793				fDeferredEvents->interruptOccurred(0, 0, 0);
794		}
795    }
796
797    return (super::framebufferEvent( framebuffer, event, info ));
798}
799
800
801