|
1 /* |
|
2 * Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies). |
|
3 * All rights reserved. |
|
4 * This component and the accompanying materials are made available |
|
5 * under the terms of the License "Eclipse Public License v1.0" |
|
6 * which accompanies this distribution, and is available |
|
7 * at the URL "http://www.eclipse.org/legal/epl-v10.html". |
|
8 * |
|
9 * Initial Contributors: |
|
10 * Nokia Corporation - initial contribution. |
|
11 * |
|
12 * Contributors: |
|
13 * |
|
14 * Description: Minimalistic frame buffer driver |
|
15 * |
|
16 */ |
|
17 #include <videodriver.h> |
|
18 #include "platform.h" |
|
19 #include <nkern.h> |
|
20 #include <kernel/kernel.h> |
|
21 #include <kernel/kern_priv.h> |
|
22 #include <kernel/kpower.h> |
|
23 |
|
24 #include <syborg_priv.h> |
|
25 #include "svpframebuffer.h" |
|
26 |
|
27 DLcdPowerHandler * DLcdPowerHandler::pLcd = NULL; |
|
28 |
|
29 TPhysAddr Syborg::VideoRamPhys; |
|
30 TPhysAddr Syborg::VideoRamPhysSecure; // Secure display memory |
|
31 |
|
32 TPhysAddr TSyborg::VideoRamPhys() |
|
33 { |
|
34 __KTRACE_OPT(KEXTENSION,Kern::Printf("TSyborg::VideoRamPhys: VideoRamPhys=0x%x", Syborg::VideoRamPhys)); |
|
35 return Syborg::VideoRamPhys; |
|
36 } |
|
37 |
|
38 TPhysAddr TSyborg::VideoRamPhysSecure() |
|
39 { |
|
40 return Syborg::VideoRamPhysSecure; |
|
41 } |
|
42 |
|
43 LOCAL_C TInt DoHalFunction(TAny* aPtr, TInt aFunction, TAny* a1, TAny* a2) |
|
44 { |
|
45 DLcdPowerHandler* pH=(DLcdPowerHandler*)aPtr; |
|
46 return pH->HalFunction(aFunction,a1,a2); |
|
47 } |
|
48 |
|
49 static void rxMsg(TAny* aPtr) |
|
50 { |
|
51 DLcdPowerHandler& h=*(DLcdPowerHandler*)aPtr; |
|
52 TMessageBase* pM = h.iMsgQ.iMessage; |
|
53 if(pM) |
|
54 h.HandleMsg(pM); |
|
55 } |
|
56 |
|
57 static void power_up_dfc(TAny* aPtr) |
|
58 { |
|
59 ((DLcdPowerHandler*)aPtr)->PowerUpDfc(); |
|
60 } |
|
61 |
|
62 void power_down_dfc(TAny* aPtr) |
|
63 { |
|
64 ((DLcdPowerHandler*)aPtr)->PowerDownDfc(); |
|
65 } |
|
66 |
|
67 void DLcdPowerHandler::DisplayOn() |
|
68 { |
|
69 PowerUpLcd(iSecureDisplay); |
|
70 iDisplayOn = ETrue; |
|
71 } |
|
72 |
|
73 void DLcdPowerHandler::DisplayOff() |
|
74 { |
|
75 PowerDownLcd(); |
|
76 iDisplayOn = EFalse; |
|
77 } |
|
78 |
|
79 void DLcdPowerHandler::SwitchDisplay(TBool aSecure) |
|
80 { |
|
81 if(aSecure) |
|
82 { |
|
83 if(!iSecureDisplay) |
|
84 { |
|
85 DisplayOff(); |
|
86 iSecureDisplay = ETrue; |
|
87 DisplayOn(); |
|
88 } |
|
89 } |
|
90 else |
|
91 { |
|
92 if(iSecureDisplay) |
|
93 { |
|
94 DisplayOff(); |
|
95 iSecureDisplay = EFalse; |
|
96 DisplayOn(); |
|
97 } |
|
98 } |
|
99 } |
|
100 |
|
101 void DLcdPowerHandler::PowerUpDfc() |
|
102 { |
|
103 DisplayOn(); |
|
104 PowerUpDone(); |
|
105 } |
|
106 |
|
107 void DLcdPowerHandler::PowerDownDfc() |
|
108 { |
|
109 DisplayOff(); |
|
110 PowerDownDone(); |
|
111 } |
|
112 |
|
113 void DLcdPowerHandler::PowerDown(TPowerState) |
|
114 { |
|
115 iPowerDownDfc.Enque(); |
|
116 } |
|
117 |
|
118 void DLcdPowerHandler::PowerUp() |
|
119 { |
|
120 iPowerUpDfc.Enque(); |
|
121 } |
|
122 |
|
123 void DLcdPowerHandler::PowerUpLcd(TBool aSecure) |
|
124 { |
|
125 #if 1 |
|
126 WriteReg(iPortAddr, FB_ENABLED, 0); |
|
127 WriteReg(iPortAddr, FB_BASE, aSecure ? iSecurevRamPhys : ivRamPhys); |
|
128 WriteReg(iPortAddr, FB_WIDTH, iVideoInfo.iSizeInPixels.iWidth); |
|
129 WriteReg(iPortAddr, FB_BLANK, 0); |
|
130 WriteReg(iPortAddr, FB_BPP, 32); |
|
131 WriteReg(iPortAddr, FB_COLOR_ORDER, 0); |
|
132 WriteReg(iPortAddr, FB_BYTE_ORDER, 0); |
|
133 WriteReg(iPortAddr, FB_PIXEL_ORDER, 0); |
|
134 WriteReg(iPortAddr, FB_INT_MASK, 0); |
|
135 WriteReg(iPortAddr, FB_ENABLED, 1); |
|
136 WriteReg(iPortAddr, FB_HEIGHT, iVideoInfo.iSizeInPixels.iHeight); |
|
137 #endif |
|
138 } |
|
139 |
|
140 void DLcdPowerHandler::PowerDownLcd() |
|
141 { |
|
142 WriteReg(iPortAddr, FB_BLANK, 1); |
|
143 } |
|
144 |
|
145 DLcdPowerHandler::DLcdPowerHandler() |
|
146 : DPowerHandler(KLitLcd), |
|
147 iMsgQ(rxMsg,this,NULL,1), |
|
148 iPowerUpDfc(&power_up_dfc,this,6), |
|
149 iPowerDownDfc(&power_down_dfc,this,7) |
|
150 { |
|
151 } |
|
152 |
|
153 void DLcdPowerHandler::ScreenInfo(TScreenInfoV01& anInfo) |
|
154 { |
|
155 anInfo.iWindowHandleValid = EFalse; |
|
156 anInfo.iWindowHandle = NULL; |
|
157 anInfo.iScreenAddressValid = ETrue; |
|
158 anInfo.iScreenAddress = (TAny *)(iChunk->LinearAddress()); |
|
159 anInfo.iScreenSize.iWidth = iVideoInfo.iSizeInPixels.iWidth; |
|
160 anInfo.iScreenSize.iHeight = iVideoInfo.iSizeInPixels.iHeight; |
|
161 } |
|
162 |
|
163 void DLcdPowerHandler::HandleMsg(TMessageBase* aMsg) |
|
164 { |
|
165 if(aMsg->iValue) |
|
166 DisplayOn(); |
|
167 else |
|
168 DisplayOff(); |
|
169 aMsg->Complete(KErrNone,ETrue); |
|
170 } |
|
171 |
|
172 void DLcdPowerHandler::WsSwitchOnScreen() |
|
173 { |
|
174 TThreadMessage& m = Kern::Message(); |
|
175 m.iValue = ETrue; |
|
176 m.SendReceive(&iMsgQ); |
|
177 } |
|
178 |
|
179 void DLcdPowerHandler::WsSwitchOffScreen() |
|
180 { |
|
181 TThreadMessage& m = Kern::Message(); |
|
182 m.iValue = EFalse; |
|
183 m.SendReceive(&iMsgQ); |
|
184 } |
|
185 |
|
186 TInt DLcdPowerHandler::GetCurrentDisplayModeInfo(TVideoInfoV01& aInfo, TBool aSecure) |
|
187 { |
|
188 NKern::FMWait(&iLock); |
|
189 if(aSecure) |
|
190 aInfo = iSecureVideoInfo; |
|
191 else |
|
192 aInfo = iVideoInfo; |
|
193 NKern::FMSignal(&iLock); |
|
194 return KErrNone; |
|
195 } |
|
196 |
|
197 TInt DLcdPowerHandler::GetSpecifiedDisplayModeInfo(TInt aMode, TVideoInfoV01& aInfo) |
|
198 { |
|
199 if(aMode < 0 || aMode >= KConfigLcdNumberOfDisplayModes) |
|
200 return KErrArgument; |
|
201 |
|
202 NKern::FMWait(&iLock); |
|
203 aInfo = iVideoInfo; |
|
204 NKern::FMSignal(&iLock); |
|
205 |
|
206 if(aMode != aInfo.iDisplayMode) |
|
207 { |
|
208 aInfo.iOffsetToFirstPixel = KCOnfigOffsetToFirstPixel; |
|
209 aInfo.iIsPalettized = KConfigIsPalettized; |
|
210 aInfo.iOffsetBetweenLines = KCOnfigOffsetBetweenLines; |
|
211 aInfo.iBitsPerPixel = KConfigBitsPerPixel; |
|
212 } |
|
213 return KErrNone; |
|
214 } |
|
215 |
|
216 TInt DLcdPowerHandler::AllocateFrameBuffer() |
|
217 { |
|
218 // Allocate physical RAM for video |
|
219 TInt vSize = TSyborg::VideoRamSize(); |
|
220 |
|
221 NKern::ThreadEnterCS(); |
|
222 TInt r = Epoc::AllocPhysicalRam(vSize,Syborg::VideoRamPhys); |
|
223 if (r != KErrNone) |
|
224 { |
|
225 NKern::ThreadLeaveCS(); |
|
226 Kern::Fault("AllocVideoRam",r); |
|
227 } |
|
228 |
|
229 // Map the video RAM |
|
230 ivRamPhys = TSyborg::VideoRamPhys(); |
|
231 |
|
232 r = DPlatChunkHw::New(iChunk,ivRamPhys,vSize,EMapAttrUserRw|EMapAttrBufferedC); |
|
233 |
|
234 NKern::ThreadLeaveCS(); |
|
235 |
|
236 if(r != KErrNone) |
|
237 return r; |
|
238 |
|
239 TUint* pV = (TUint*)iChunk->LinearAddress(); |
|
240 |
|
241 // Allocate physical RAM for secure display |
|
242 NKern::ThreadEnterCS(); |
|
243 r = Epoc::AllocPhysicalRam(vSize,Syborg::VideoRamPhysSecure); |
|
244 if (r != KErrNone) |
|
245 { |
|
246 NKern::ThreadLeaveCS(); |
|
247 Kern::Fault("AllocVideoRam 2",r); |
|
248 } |
|
249 iSecurevRamPhys = ivRamPhys + vSize; |
|
250 TInt r2 = DPlatChunkHw::New(iSecureChunk,iSecurevRamPhys,vSize,EMapAttrUserRw|EMapAttrBufferedC); |
|
251 |
|
252 NKern::ThreadLeaveCS(); |
|
253 |
|
254 if(r2 != KErrNone) |
|
255 return r2; |
|
256 |
|
257 TUint* pV2 = (TUint*)iSecureChunk->LinearAddress(); |
|
258 |
|
259 iVideoInfo.iSizeInPixels.iWidth = KConfigLcdWidth; |
|
260 iVideoInfo.iSizeInPixels.iHeight = KConfigLcdHeight; |
|
261 iVideoInfo.iDisplayMode = KConfigLcdDisplayMode; |
|
262 iVideoInfo.iOffsetToFirstPixel = KCOnfigOffsetToFirstPixel; |
|
263 iVideoInfo.iOffsetBetweenLines = KCOnfigOffsetBetweenLines; |
|
264 iVideoInfo.iIsPalettized = KConfigIsPalettized; |
|
265 iVideoInfo.iBitsPerPixel = KConfigBitsPerPixel; |
|
266 iVideoInfo.iSizeInTwips.iWidth = KConfigLcdWidthInTwips; |
|
267 iVideoInfo.iSizeInTwips.iHeight = KConfigLcdHeightInTwips; |
|
268 iVideoInfo.iIsMono = KConfigIsMono; |
|
269 iVideoInfo.iVideoAddress = (TInt)pV; |
|
270 iVideoInfo.iIsPixelOrderLandscape = KConfigPixelOrderLandscape; |
|
271 iVideoInfo.iIsPixelOrderRGB = KConfigPixelOrderRGB; |
|
272 |
|
273 iSecureVideoInfo = iVideoInfo; |
|
274 iSecureVideoInfo.iVideoAddress = (TInt)pV2; |
|
275 |
|
276 // Alloc Physical RAM for the Composition Buffers used by the GCE |
|
277 iSize = 4*480*640;//FRAME_BUFFER_SIZE( iVideoInfo.iBitsPerPixel, iVideoInfo.iSizeInPixels.iWidth, iVideoInfo.iSizeInPixels.iHeight); |
|
278 __GCE_DEBUG_PRINT2("DLcdPowerHandler.iSize = %d\n", iSize ); |
|
279 // double and round the page size |
|
280 TUint round = 2*Kern::RoundToPageSize(iSize); |
|
281 |
|
282 r=Epoc::AllocPhysicalRam(round , iCompositionPhysical); |
|
283 if(r!=KErrNone) |
|
284 { |
|
285 return r; |
|
286 } |
|
287 |
|
288 return KErrNone; |
|
289 } |
|
290 |
|
291 |
|
292 TInt DLcdPowerHandler::SetDisplayMode(TInt aMode) |
|
293 { |
|
294 if(aMode < 0 || aMode >= KConfigLcdNumberOfDisplayModes) |
|
295 return KErrArgument; |
|
296 |
|
297 // store the current mode |
|
298 iVideoInfo.iDisplayMode = aMode; |
|
299 |
|
300 // store the current mode for secure screen |
|
301 iSecureVideoInfo.iDisplayMode = aMode; |
|
302 |
|
303 return KErrNone; |
|
304 } |
|
305 |
|
306 TInt DLcdPowerHandler::HalFunction(TInt aFunction, TAny* a1, TAny* a2) |
|
307 { |
|
308 TInt r=KErrNone; |
|
309 switch(aFunction) |
|
310 { |
|
311 case EDisplayHalScreenInfo: |
|
312 { |
|
313 TPckgBuf<TScreenInfoV01> vPckg; |
|
314 ScreenInfo(vPckg()); |
|
315 Kern::InfoCopy(*(TDes8*)a1,vPckg); |
|
316 break; |
|
317 } |
|
318 case EDisplayHalWsRegisterSwitchOnScreenHandling: |
|
319 { |
|
320 iWsSwitchOnScreen=(TBool)a1; |
|
321 break; |
|
322 } |
|
323 case EDisplayHalWsSwitchOnScreen: |
|
324 { |
|
325 WsSwitchOnScreen(); |
|
326 break; |
|
327 } |
|
328 case EDisplayHalModeCount: |
|
329 { |
|
330 TInt ndm = KConfigLcdNumberOfDisplayModes; |
|
331 kumemput32(a1, &ndm, sizeof(ndm)); |
|
332 break; |
|
333 } |
|
334 case EDisplayHalSetMode: |
|
335 { |
|
336 __KTRACE_OPT(KEXTENSION,Kern::Printf("EDisplayHalSetMode")); |
|
337 __SECURE_KERNEL( |
|
338 if(!Kern::CurrentThreadHasCapability(ECapabilityMultimediaDD,__PLATSEC_DIAGNOSTIC_STRING("Checked by Hal function EDisplayHalSetMode"))) |
|
339 return KErrPermissionDenied; |
|
340 ) |
|
341 r = SetDisplayMode((TInt)a1); |
|
342 break; |
|
343 } |
|
344 case EDisplayHalMode: |
|
345 { |
|
346 kumemput32(a1, &iVideoInfo.iDisplayMode, sizeof(iVideoInfo.iDisplayMode)); |
|
347 r = KErrNone; |
|
348 break; |
|
349 } |
|
350 case EDisplayHalSetPaletteEntry: |
|
351 { |
|
352 __SECURE_KERNEL( |
|
353 if(!Kern::CurrentThreadHasCapability(ECapabilityMultimediaDD,__PLATSEC_DIAGNOSTIC_STRING("Checked by Hal function EDisplayHalSetPaletteEntry"))) |
|
354 return KErrPermissionDenied; |
|
355 ) |
|
356 r = KErrNotSupported; |
|
357 break; |
|
358 } |
|
359 case EDisplayHalPaletteEntry: |
|
360 { |
|
361 TInt entry; |
|
362 kumemget32(&entry, a1, sizeof(TInt)); |
|
363 r = KErrNotSupported; |
|
364 break; |
|
365 } |
|
366 case EDisplayHalSetState: |
|
367 { |
|
368 __SECURE_KERNEL( |
|
369 if(!Kern::CurrentThreadHasCapability(ECapabilityPowerMgmt,__PLATSEC_DIAGNOSTIC_STRING("Checked by Hal function EDisplayHalSetState"))) |
|
370 return KErrPermissionDenied; |
|
371 ) |
|
372 if((TBool)a1) |
|
373 WsSwitchOnScreen(); |
|
374 else |
|
375 WsSwitchOffScreen(); |
|
376 break; |
|
377 } |
|
378 case EDisplayHalState: |
|
379 { |
|
380 kumemput32(a1, &iDisplayOn, sizeof(TBool)); |
|
381 break; |
|
382 } |
|
383 case EDisplayHalColors: |
|
384 { |
|
385 TInt mdc = 1<<24; |
|
386 kumemput32(a1, &mdc, sizeof(mdc)); |
|
387 break; |
|
388 } |
|
389 case EDisplayHalCurrentModeInfo: |
|
390 { |
|
391 TPckgBuf<TVideoInfoV01> vPckg; |
|
392 r = GetCurrentDisplayModeInfo(vPckg(), (TBool)a2); |
|
393 if(KErrNone == r) |
|
394 Kern::InfoCopy(*(TDes8*)a1,vPckg); |
|
395 break; |
|
396 } |
|
397 case EDisplayHalSpecifiedModeInfo: |
|
398 { |
|
399 TPckgBuf<TVideoInfoV01> vPckg; |
|
400 TInt mode; |
|
401 kumemget32(&mode, a1, sizeof(mode)); |
|
402 r = GetSpecifiedDisplayModeInfo(mode, vPckg()); |
|
403 if(KErrNone == r) |
|
404 Kern::InfoCopy(*(TDes8*)a2,vPckg); |
|
405 break; |
|
406 } |
|
407 case EDisplayHalSecure: |
|
408 { |
|
409 kumemput32(a1, &iSecureDisplay, sizeof(TBool)); |
|
410 break; |
|
411 } |
|
412 case EDisplayHalSetSecure: |
|
413 { |
|
414 __SECURE_KERNEL( |
|
415 if(!Kern::CurrentThreadHasCapability(ECapabilityMultimediaDD,__PLATSEC_DIAGNOSTIC_STRING("Checked by Hal function EDisplayHalSetSecure"))) |
|
416 return KErrPermissionDenied; |
|
417 ) |
|
418 SwitchDisplay((TBool)a1); |
|
419 break; |
|
420 } |
|
421 default: |
|
422 { |
|
423 r = KErrNotSupported; |
|
424 break; |
|
425 } |
|
426 } |
|
427 return r; |
|
428 } |
|
429 |
|
430 TInt DLcdPowerHandler::Create() |
|
431 { |
|
432 __KTRACE_OPT(KEXTENSION ,Kern::Printf("DLcdPowerHandler::Create") ); |
|
433 pLcd = this; |
|
434 |
|
435 iPortAddr = KHwBaseClcd; |
|
436 |
|
437 iVideoInfo.iSizeInPixels.iWidth = KConfigLcdWidth; |
|
438 iVideoInfo.iSizeInPixels.iHeight = KConfigLcdHeight; |
|
439 iVideoInfo.iDisplayMode = KConfigLcdDisplayMode; |
|
440 iVideoInfo.iOffsetToFirstPixel = KCOnfigOffsetToFirstPixel; |
|
441 iVideoInfo.iOffsetBetweenLines = KCOnfigOffsetBetweenLines; |
|
442 iVideoInfo.iIsPalettized = KConfigIsPalettized; |
|
443 iVideoInfo.iBitsPerPixel = KConfigBitsPerPixel; |
|
444 iVideoInfo.iSizeInTwips.iWidth = KConfigLcdWidthInTwips; |
|
445 iVideoInfo.iSizeInTwips.iHeight = KConfigLcdHeightInTwips; |
|
446 iVideoInfo.iIsMono = KConfigIsMono; |
|
447 // !@! iVideoInfo.iVideoAddress = (TInt)pV; |
|
448 iVideoInfo.iIsPixelOrderLandscape = KConfigPixelOrderLandscape; |
|
449 iVideoInfo.iIsPixelOrderRGB = KConfigPixelOrderRGB; |
|
450 |
|
451 iSecureVideoInfo = iVideoInfo; |
|
452 // !@! iSecureVideoInfo.iVideoAddress = (TInt)pV2; |
|
453 |
|
454 TInt r = AllocateFrameBuffer(); |
|
455 if(r == KErrNone) |
|
456 { |
|
457 r = Kern::AddHalEntry(EHalGroupDisplay,DoHalFunction,this); |
|
458 } |
|
459 |
|
460 if(r != KErrNone) |
|
461 { |
|
462 __KTRACE_OPT(KEXTENSION ,Kern::Printf("DLcdPowerHandler::Create failed %d", r) ); |
|
463 return r; |
|
464 } |
|
465 |
|
466 iPowerUpDfc.SetDfcQ(iDfcQ); |
|
467 iPowerDownDfc.SetDfcQ(iDfcQ); |
|
468 iMsgQ.SetDfcQ(iDfcQ); |
|
469 iMsgQ.Receive(); |
|
470 |
|
471 Add(); |
|
472 DisplayOn(); |
|
473 |
|
474 return KErrNone; |
|
475 } |
|
476 |
|
477 /** |
|
478 * Register the call back function. |
|
479 * Components interested in receiving notification of the Vsync interrupt should register a callback function. |
|
480 */ |
|
481 EXPORT_C TInt DLcdPowerHandler::RegisterCallback(TLcdUserCallBack* aCbPtr) |
|
482 { |
|
483 __KTRACE_OPT(KEXTENSION ,Kern::Printf("DLcdPowerHandler::RegisterCallBack %08x\n",aCbPtr->iCbFn) ); |
|
484 |
|
485 TInt irq=__SPIN_LOCK_IRQSAVE(callbackLock); |
|
486 |
|
487 if(aCbPtr != NULL) |
|
488 { |
|
489 if ( pLcd->iAppCallBk[0] == NULL ) |
|
490 { |
|
491 pLcd->iAppCallBk[0] = aCbPtr; |
|
492 } |
|
493 else |
|
494 { |
|
495 if((pLcd->iAppCallBk[1] == NULL) && (pLcd->iAppCallBk[0]->iCbFn != aCbPtr->iCbFn)) |
|
496 { |
|
497 pLcd->iAppCallBk[1] = aCbPtr; |
|
498 } |
|
499 else |
|
500 { |
|
501 __SPIN_UNLOCK_IRQRESTORE(callbackLock,irq); |
|
502 return KErrInUse; |
|
503 } |
|
504 } |
|
505 |
|
506 __SPIN_UNLOCK_IRQRESTORE(callbackLock,irq); |
|
507 __KTRACE_OPT(KEXTENSION ,Kern::Printf("<DLcdPowerHandler::RegisterCallBack ok %08x\n",aCbPtr->iCbFn) ); |
|
508 return KErrNone; |
|
509 } |
|
510 else |
|
511 { |
|
512 __SPIN_UNLOCK_IRQRESTORE(callbackLock,irq); |
|
513 __KTRACE_OPT(KEXTENSION, Kern::Printf("Error: The supplied listener's callback is NULL")); |
|
514 return KErrArgument; |
|
515 } |
|
516 } |
|
517 |
|
518 |
|
519 /** |
|
520 *DeRegister the call back function |
|
521 */ |
|
522 EXPORT_C void DLcdPowerHandler::DeRegisterCallback(TLcdUserCallBack* aCbPtr) |
|
523 { |
|
524 __KTRACE_OPT(KEXTENSION ,Kern::Printf("DLcdPowerHandler::DeRegisterCallBack %08x\n ",aCbPtr->iCbFn) ); |
|
525 |
|
526 TInt irq=__SPIN_LOCK_IRQSAVE(callbackLock); |
|
527 if(aCbPtr != NULL) |
|
528 { |
|
529 if( pLcd->iAppCallBk[0] != NULL) |
|
530 { |
|
531 if ( (pLcd->iAppCallBk[0]->iDataPtr == aCbPtr->iDataPtr) && (pLcd->iAppCallBk[0]->iCbFn == aCbPtr->iCbFn) ) |
|
532 { |
|
533 pLcd->iAppCallBk[0] = NULL; |
|
534 } |
|
535 } |
|
536 |
|
537 if( pLcd->iAppCallBk[1] != NULL) |
|
538 { |
|
539 if ( (pLcd->iAppCallBk[1]->iDataPtr == aCbPtr->iDataPtr) && (pLcd->iAppCallBk[1]->iCbFn == aCbPtr->iCbFn) ) |
|
540 { |
|
541 pLcd->iAppCallBk[1] = NULL; |
|
542 } |
|
543 } |
|
544 } |
|
545 __SPIN_UNLOCK_IRQRESTORE(callbackLock,irq); |
|
546 __KTRACE_OPT(KEXTENSION ,Kern::Printf("<DLcdPowerHandler::DeRegisterCallBack %08x\n ",aCbPtr->iCbFn) ); |
|
547 } |
|
548 |
|
549 /** |
|
550 Constructor |
|
551 */ |
|
552 DDisplayPddSyborg::DDisplayPddSyborg(): |
|
553 iPendingBuffer(NULL), |
|
554 iActiveBuffer(NULL), |
|
555 iChunk(NULL), |
|
556 iLcdCallback(NULL), |
|
557 iVSyncDfc(&VSyncDfcFn, this, KVSyncDfcPriority) |
|
558 { |
|
559 __GCE_DEBUG_PRINT("DDisplayPddSyborg::DDisplayPddSyborg\n"); |
|
560 |
|
561 iPostFlag = EFalse; |
|
562 } |
|
563 |
|
564 /** |
|
565 Destructor |
|
566 */ |
|
567 DDisplayPddSyborg::~DDisplayPddSyborg() |
|
568 { |
|
569 __GCE_DEBUG_PRINT("DDisplayPddSyborg::~DDisplayPddSyborg() \n"); |
|
570 |
|
571 if(iLcdCallback) |
|
572 { |
|
573 DLcdPowerHandler::pLcd->DeRegisterCallback(iLcdCallback) ; |
|
574 delete iLcdCallback; |
|
575 iLcdCallback = NULL; |
|
576 } |
|
577 |
|
578 //The DFC Queue is owned by DLcdPowerHandler so we shouldn't call Destroy() at this point. |
|
579 if (iDfcQ) |
|
580 { |
|
581 iDfcQ=NULL; |
|
582 } |
|
583 |
|
584 DChunk* chunk = (DChunk*) __e32_atomic_swp_ord_ptr(&iChunk, 0); |
|
585 |
|
586 if(chunk) |
|
587 { |
|
588 Kern::ChunkClose(chunk); |
|
589 } |
|
590 |
|
591 } |
|
592 |
|
593 /** |
|
594 Set the Legacy Mode by setting the appropriate Frame control value. |
|
595 |
|
596 */ |
|
597 TInt DDisplayPddSyborg::SetLegacyMode() |
|
598 { |
|
599 __GCE_DEBUG_PRINT("DDisplayPddSyborg::SetLegacyMode()\n"); |
|
600 |
|
601 return KErrNone; |
|
602 } |
|
603 |
|
604 /** |
|
605 Set the GCE mode by posting a composition buffer. |
|
606 |
|
607 */ |
|
608 TInt DDisplayPddSyborg::SetGceMode() |
|
609 { |
|
610 __GCE_DEBUG_PRINT("DDisplayPddSyborg::SetGceMode()\n"); |
|
611 |
|
612 PostCompositionBuffer(&iLdd->iCompositionBuffer[0]); |
|
613 return KErrNone; |
|
614 } |
|
615 |
|
616 /** |
|
617 @param aDegOfRot The requested rotation |
|
618 @return KErrNone |
|
619 */ |
|
620 TInt DDisplayPddSyborg::SetRotation(TInt aDegOfRot) |
|
621 { |
|
622 return KErrNone; |
|
623 } |
|
624 |
|
625 /** |
|
626 Remove any previous post operations, set the appropriate layer as the next layer to be displayed( This value is updated in synchronization |
|
627 with V Sync so it will take affect in the next V Sync after that) and also set the buffer provided as the buffer to |
|
628 be posted next. Layer 3 is associated with user buffers. |
|
629 |
|
630 @param aNode Pointer to the User buffer to post. |
|
631 */ |
|
632 TInt DDisplayPddSyborg::PostUserBuffer(TBufferNode* aNode) |
|
633 { |
|
634 |
|
635 __GCE_DEBUG_PRINT2("DDisplayPddSyborg::PostUserBuffer : aNode->iAddress = %08x\n", aNode->iAddress); |
|
636 |
|
637 if(iPendingBuffer) |
|
638 { |
|
639 iPendingBuffer->iState = EBufferFree; |
|
640 if (!(iPendingBuffer->iType == EBufferTypeUser) ) |
|
641 { |
|
642 iPendingBuffer->iFree = ETrue; |
|
643 } |
|
644 } |
|
645 |
|
646 aNode->iState = EBufferPending; |
|
647 iPendingBuffer = aNode; |
|
648 iPostFlag = ETrue; |
|
649 |
|
650 // Activate the posted buffer |
|
651 TUint32 physicalAddress = Epoc::LinearToPhysical( aNode->iAddress ); |
|
652 WriteReg(DLcdPowerHandler::pLcd->iPortAddr, DLcdPowerHandler::FB_BASE, physicalAddress ); |
|
653 /* Queue a DFC to complete the request*/ |
|
654 iVSyncDfc.Enque(); |
|
655 |
|
656 return KErrNone; |
|
657 } |
|
658 |
|
659 /** |
|
660 Remove any previous post operations, set the appropriate layer as the next layer to be displayed( This value is updated in synchronization |
|
661 with V Sync so it will take affect in the next V Sync after that) and also set the buffer provided as the buffer to |
|
662 be posted next. Layer 1 and 2 are associated with composition buffers 0 and 1 respectively. |
|
663 |
|
664 @param aNode Pointer to the Composition buffer to post. |
|
665 */ |
|
666 TInt DDisplayPddSyborg::PostCompositionBuffer(TBufferNode* aNode) |
|
667 { |
|
668 |
|
669 __GCE_DEBUG_PRINT2("DDisplayPddSyborg::PostCompositionBuffer : aNode->iAddress = %08x\n", aNode->iAddress); |
|
670 |
|
671 if(iPendingBuffer) |
|
672 { |
|
673 iPendingBuffer->iState = EBufferFree; |
|
674 if (iPendingBuffer->iType == EBufferTypeUser) |
|
675 { |
|
676 RequestComplete(RDisplayChannel::EReqPostUserBuffer, KErrCancel); |
|
677 } |
|
678 else |
|
679 { |
|
680 iPendingBuffer->iFree = ETrue; |
|
681 } |
|
682 } |
|
683 aNode->iState = EBufferPending; |
|
684 aNode->iFree = EFalse; |
|
685 iPendingBuffer = aNode; |
|
686 iPostFlag = ETrue; |
|
687 |
|
688 // Activate the posted buffer |
|
689 TUint32 physicalAddress = Epoc::LinearToPhysical( aNode->iAddress ); |
|
690 WriteReg(DLcdPowerHandler::pLcd->iPortAddr, DLcdPowerHandler::FB_BASE, physicalAddress ); |
|
691 |
|
692 /* Queue a DFC to complete the request*/ |
|
693 iVSyncDfc.Enque(); |
|
694 |
|
695 return KErrNone; |
|
696 } |
|
697 |
|
698 /** |
|
699 Remove any previous post operations, set the appropriate layer as the next layer to be displayed( This value is updated in synchronization |
|
700 with V Sync so it will take affect in the next V Sync after that) and also set the Legacy Buffer as the buffer to |
|
701 be posted next.Layer 0 is associated with legacy buffer. |
|
702 |
|
703 @param aNode Pointer to the Composition buffer to post. |
|
704 */ |
|
705 TInt DDisplayPddSyborg::PostLegacyBuffer() |
|
706 { |
|
707 __GCE_DEBUG_PRINT("DDisplayPddSyborg::PostLegacyBuffer() \n"); |
|
708 |
|
709 if(iPendingBuffer) |
|
710 { |
|
711 iPendingBuffer->iState = EBufferFree; |
|
712 if (iPendingBuffer->iType == EBufferTypeUser) |
|
713 { |
|
714 |
|
715 RequestComplete(RDisplayChannel::EReqPostUserBuffer, KErrCancel); |
|
716 } |
|
717 else |
|
718 { |
|
719 iPendingBuffer->iFree = ETrue; |
|
720 } |
|
721 } |
|
722 |
|
723 |
|
724 iLdd->iLegacyBuffer[0].iState = EBufferPending; |
|
725 iLdd->iLegacyBuffer[0].iFree = EFalse; |
|
726 iPendingBuffer = &iLdd->iLegacyBuffer[0]; |
|
727 iPostFlag = ETrue; |
|
728 |
|
729 // Activate the posted buffer |
|
730 WriteReg(DLcdPowerHandler::pLcd->iPortAddr, DLcdPowerHandler::FB_BASE, TSyborg::VideoRamPhys() ); |
|
731 |
|
732 /* Queue a DFC to complete the request*/ |
|
733 iVSyncDfc.Enque(); |
|
734 |
|
735 return KErrNone; |
|
736 } |
|
737 |
|
738 /** |
|
739 Handles device specific operations when a close message has been sent to the Logical Channel. |
|
740 |
|
741 */ |
|
742 TInt DDisplayPddSyborg::CloseMsg() |
|
743 { |
|
744 __GCE_DEBUG_PRINT("DDisplayPddSyborg::CloseMsg()\n"); |
|
745 |
|
746 iPendingBuffer = NULL; |
|
747 iActiveBuffer = NULL; |
|
748 |
|
749 iVSyncDfc.Cancel(); |
|
750 return KErrNone; |
|
751 } |
|
752 |
|
753 /** |
|
754 Called by the LDD's DoCreate function to handle the device specific part of opening the channel. |
|
755 (DoCreate is called by RDisplayChannel::Open) |
|
756 |
|
757 @param aUnit The screen unit |
|
758 |
|
759 @return KErrNone if successful; or one of the other system wide error codes. |
|
760 */ |
|
761 TInt DDisplayPddSyborg::CreateChannelSetup(TInt aUnit) |
|
762 { |
|
763 __GCE_DEBUG_PRINT("DDisplayPddSyborg::CreateChannelSetup\n"); |
|
764 |
|
765 iScreenInfo = DLcdPowerHandler::pLcd->iVideoInfo; |
|
766 iLdd->iUnit = aUnit; |
|
767 |
|
768 iLdd->iDisplayInfo.iAvailableRotations = RDisplayChannel::ERotationNormal; |
|
769 iLdd->iDisplayInfo.iNormal.iOffsetBetweenLines = iScreenInfo.iOffsetBetweenLines; |
|
770 iLdd->iDisplayInfo.iNormal.iHeight = iScreenInfo.iSizeInPixels.iHeight; |
|
771 iLdd->iDisplayInfo.iNormal.iWidth = iScreenInfo.iSizeInPixels.iWidth; |
|
772 iLdd->iDisplayInfo.iNumCompositionBuffers = KDisplayCBMax; |
|
773 iLdd->iDisplayInfo.iBitsPerPixel = iScreenInfo.iBitsPerPixel; |
|
774 iLdd->iDisplayInfo.iRefreshRateHz = 60; |
|
775 |
|
776 |
|
777 switch (iScreenInfo.iBitsPerPixel) |
|
778 { |
|
779 case 16: |
|
780 iLdd->iDisplayInfo.iPixelFormat = EUidPixelFormatRGB_565; |
|
781 break; |
|
782 case 24: |
|
783 iLdd->iDisplayInfo.iPixelFormat = EUidPixelFormatRGB_888; |
|
784 break; |
|
785 case 32: |
|
786 iLdd->iDisplayInfo.iPixelFormat = EUidPixelFormatARGB_8888; |
|
787 break; |
|
788 default: |
|
789 iLdd->iDisplayInfo.iPixelFormat = EUidPixelFormatUnknown; |
|
790 break; |
|
791 } |
|
792 |
|
793 iLdd->iCurrentRotation = RDisplayChannel::ERotationNormal; |
|
794 |
|
795 // Open shared chunk to the composition framebuffer |
|
796 |
|
797 DChunk* chunk = 0; |
|
798 TLinAddr chunkKernelAddr = 0; |
|
799 TUint32 chunkMapAttr = 0; |
|
800 |
|
801 // round to twice the page size |
|
802 TUint round = 2*Kern::RoundToPageSize(DLcdPowerHandler::pLcd->iSize); |
|
803 |
|
804 __GCE_DEBUG_PRINT2("DDisplayPddSyborg::CreateChannelSetup DLcdPowerHandler::pLcd->iSize = %d\n", DLcdPowerHandler::pLcd->iSize ); |
|
805 |
|
806 TChunkCreateInfo info; |
|
807 info.iType = TChunkCreateInfo::ESharedKernelMultiple; |
|
808 info.iMaxSize = round; |
|
809 info.iMapAttr = EMapAttrFullyBlocking; |
|
810 info.iOwnsMemory = EFalse; |
|
811 info.iDestroyedDfc = 0; |
|
812 |
|
813 TInt r = Kern::ChunkCreate(info, chunk, chunkKernelAddr, chunkMapAttr); |
|
814 |
|
815 __GCE_DEBUG_PRINT2("CreateChannelSetup:ChunkCreate called for composition chunk. Set iChunkKernelAddr = %08x\n", chunkKernelAddr ); |
|
816 |
|
817 if( r == KErrNone) |
|
818 { |
|
819 // map our chunk |
|
820 r = Kern::ChunkCommitPhysical(chunk, 0,round , DLcdPowerHandler::pLcd->iCompositionPhysical); |
|
821 __GCE_DEBUG_PRINT2("Mapping chunk %d", r); |
|
822 if(r != KErrNone) |
|
823 { |
|
824 Kern::ChunkClose(chunk); |
|
825 } |
|
826 } |
|
827 |
|
828 if ( r!= KErrNone) |
|
829 { |
|
830 return r; |
|
831 } |
|
832 |
|
833 iChunk = chunk; |
|
834 |
|
835 // init CB 0 |
|
836 iLdd->iCompositionBuffer[0].iType = EBufferTypeComposition; |
|
837 iLdd->iCompositionBuffer[0].iBufferId = 0; |
|
838 iLdd->iCompositionBuffer[0].iFree = ETrue; |
|
839 iLdd->iCompositionBuffer[0].iState = EBufferFree; |
|
840 iLdd->iCompositionBuffer[0].iAddress = chunkKernelAddr; |
|
841 iLdd->iCompositionBuffer[0].iPhysicalAddress = Epoc::LinearToPhysical(chunkKernelAddr); |
|
842 iLdd->iCompositionBuffer[0].iChunk = chunk; |
|
843 iLdd->iCompositionBuffer[0].iHandle = 0; |
|
844 iLdd->iCompositionBuffer[0].iOffset = 0; |
|
845 iLdd->iCompositionBuffer[0].iSize = DLcdPowerHandler::pLcd->iSize; |
|
846 iLdd->iCompositionBuffer[0].iPendingRequest = 0; |
|
847 |
|
848 // init CB 1 |
|
849 iLdd->iCompositionBuffer[1].iType = EBufferTypeComposition; |
|
850 iLdd->iCompositionBuffer[1].iBufferId = 1; |
|
851 iLdd->iCompositionBuffer[1].iFree = ETrue; |
|
852 iLdd->iCompositionBuffer[1].iState = EBufferFree; |
|
853 iLdd->iCompositionBuffer[1].iAddress = chunkKernelAddr + DLcdPowerHandler::pLcd->iSize; |
|
854 iLdd->iCompositionBuffer[1].iPhysicalAddress = Epoc::LinearToPhysical(chunkKernelAddr + DLcdPowerHandler::pLcd->iSize); |
|
855 iLdd->iCompositionBuffer[1].iChunk = chunk; |
|
856 iLdd->iCompositionBuffer[1].iHandle = 0; |
|
857 iLdd->iCompositionBuffer[1].iOffset = DLcdPowerHandler::pLcd->iSize; |
|
858 iLdd->iCompositionBuffer[1].iSize = DLcdPowerHandler::pLcd->iSize; |
|
859 iLdd->iCompositionBuffer[1].iPendingRequest = 0; |
|
860 |
|
861 iLdd->iCompositionBuffIdx = 0; |
|
862 //Use the same DFC queue created by the DLcdPowerHandler so all hardware accesses are executed under the same DFC thread. |
|
863 iDfcQ= DLcdPowerHandler::pLcd->iDfcQ; |
|
864 |
|
865 // Set the Post DFC. |
|
866 iVSyncDfc.SetDfcQ(iDfcQ); |
|
867 |
|
868 |
|
869 return KErrNone; |
|
870 } |
|
871 |
|
872 /** |
|
873 Detect whether a post operation is pending |
|
874 */ |
|
875 TBool DDisplayPddSyborg::PostPending() |
|
876 { |
|
877 return (iPendingBuffer != NULL); |
|
878 } |
|
879 |
|
880 /** |
|
881 Return the DFC queue to be used for this device. |
|
882 */ |
|
883 TDfcQue * DDisplayPddSyborg::DfcQ(TInt aUnit) |
|
884 { |
|
885 return iDfcQ; |
|
886 } |
|
887 |
|
888 void DDisplayPddSyborg::VSyncDfcFn(TAny* aChannel) |
|
889 { |
|
890 DDisplayPddSyborg * channel =(DDisplayPddSyborg*)aChannel; |
|
891 |
|
892 if (channel->iPostFlag) |
|
893 { |
|
894 channel->iPostFlag = EFalse; |
|
895 |
|
896 if (channel->iActiveBuffer) |
|
897 { |
|
898 //When a User buffer is registered its iFree member becomes EFalse and Deregister sets it |
|
899 //back to ETrue. Composition and Legacy buffers are not free when they are in the pending or |
|
900 //active state. |
|
901 if (channel->iActiveBuffer->iType == EBufferTypeUser) |
|
902 { |
|
903 channel->RequestComplete(RDisplayChannel::EReqPostUserBuffer, KErrNone); |
|
904 } |
|
905 else |
|
906 { |
|
907 channel->iActiveBuffer->iFree = ETrue; |
|
908 } |
|
909 |
|
910 channel->iActiveBuffer->iState = EBufferFree; |
|
911 |
|
912 |
|
913 //If no buffer was available during a call to GetCompositionBuffer the active buffer has |
|
914 //been returned as the next available one, so we must set the buffer to the proper state before we |
|
915 //send the notification. |
|
916 if(channel->iLdd->iPendingReq[RDisplayChannel::EReqGetCompositionBuffer].iStatus) |
|
917 { |
|
918 channel->iActiveBuffer->iState = EBufferCompose; |
|
919 channel->RequestComplete(RDisplayChannel::EReqGetCompositionBuffer, KErrNone); |
|
920 |
|
921 } |
|
922 |
|
923 channel->iActiveBuffer = NULL; |
|
924 } |
|
925 |
|
926 if (channel->iPendingBuffer) |
|
927 { |
|
928 __GCE_DEBUG_PRINT2("DDisplayPddSyborg::VSyncDfcFn moving pending buffer at address %08x to the active state\n", channel->iPendingBuffer->iAddress); |
|
929 channel->iActiveBuffer = channel->iPendingBuffer; |
|
930 channel->iActiveBuffer->iState = EBufferActive; |
|
931 channel->iPendingBuffer = NULL; |
|
932 |
|
933 channel->RequestComplete(RDisplayChannel::EReqWaitForPost, KErrNone); |
|
934 } |
|
935 } |
|
936 } |
|
937 //***************************************************************** |
|
938 //DDisplayPddFactory |
|
939 //*****************************************************************/ |
|
940 |
|
941 |
|
942 /** |
|
943 Constructor |
|
944 */ |
|
945 DDisplayPddFactory::DDisplayPddFactory() |
|
946 { |
|
947 __GCE_DEBUG_PRINT("DDisplayPddFactory::DDisplayPddFactory()\n"); |
|
948 |
|
949 iVersion = TVersion(KDisplayChMajorVersionNumber, |
|
950 KDisplayChMinorVersionNumber, |
|
951 KDisplayChBuildVersionNumber); |
|
952 } |
|
953 |
|
954 /** |
|
955 PDD factory function. Creates a PDD object. |
|
956 |
|
957 @param aChannel A pointer to an PDD channel object which will be initialised on return. |
|
958 |
|
959 @return KErrNone if object successfully allocated, KErrNoMemory if not. |
|
960 */ |
|
961 TInt DDisplayPddFactory::Create(DBase*& aChannel, TInt aUnit, const TDesC8* aInfo, const TVersion& aVer) |
|
962 { |
|
963 DDisplayPddSyborg *device= new DDisplayPddSyborg() ; |
|
964 aChannel=device; |
|
965 if (!device) |
|
966 { |
|
967 return KErrNoMemory; |
|
968 } |
|
969 return KErrNone; |
|
970 } |
|
971 |
|
972 |
|
973 /** |
|
974 Set the Pdd name and return error code |
|
975 */ |
|
976 TInt DDisplayPddFactory::Install() |
|
977 { |
|
978 __GCE_DEBUG_PRINT("DDisplayPddFactory::Install() \n"); |
|
979 |
|
980 TBuf<32> name(RDisplayChannel::Name()); |
|
981 _LIT(KPddExtension,".pdd"); |
|
982 name.Append(KPddExtension); |
|
983 return SetName(&name); |
|
984 } |
|
985 |
|
986 |
|
987 void DDisplayPddFactory::GetCaps(TDes8& /*aDes*/) const |
|
988 { |
|
989 //Not supported |
|
990 } |
|
991 |
|
992 |
|
993 /** |
|
994 Validate version and number of units. |
|
995 */ |
|
996 TInt DDisplayPddFactory::Validate(TInt aUnit, const TDesC8* /*anInfo*/, const TVersion& aVer) |
|
997 { |
|
998 if (!Kern::QueryVersionSupported(iVersion,aVer)) |
|
999 { |
|
1000 return KErrNotSupported; |
|
1001 } |
|
1002 |
|
1003 if (aUnit != 0) |
|
1004 { |
|
1005 return KErrNotSupported; |
|
1006 } |
|
1007 |
|
1008 return KErrNone; |
|
1009 } |
|
1010 |
|
1011 DECLARE_EXTENSION_PDD() |
|
1012 /** |
|
1013 "Standard PDD" entrypoint.Creates PDD factory when Kern::InstallPhysicalDevice is called |
|
1014 |
|
1015 @return pointer to the PDD factory object. |
|
1016 */ |
|
1017 { |
|
1018 __GCE_DEBUG_PRINT("DECLARE_EXTENSION_PDD()\n"); |
|
1019 return new DDisplayPddFactory ; |
|
1020 } |
|
1021 |
|
1022 |
|
1023 DECLARE_STANDARD_EXTENSION() |
|
1024 { |
|
1025 TInt r = KErrNoMemory; |
|
1026 DLcdPowerHandler* pH=new DLcdPowerHandler; |
|
1027 if(pH) |
|
1028 { |
|
1029 r = pH->Create(); |
|
1030 if ( r == KErrNone) |
|
1031 { |
|
1032 pH->iDfcQ = Kern::DfcQue0(); // use low priority DFC queue for this driver |
|
1033 |
|
1034 DDisplayPddFactory * device = new DDisplayPddFactory; |
|
1035 |
|
1036 if (device==NULL) |
|
1037 { |
|
1038 r=KErrNoMemory; |
|
1039 } |
|
1040 else |
|
1041 { |
|
1042 r=Kern::InstallPhysicalDevice(device); |
|
1043 } |
|
1044 |
|
1045 #ifdef CPU_AFFINITY_ANY |
|
1046 NKern::ThreadSetCpuAffinity((NThread*) pH->iDfcQ->iThread, KCpuAffinityAny); |
|
1047 #endif |
|
1048 |
|
1049 __KTRACE_OPT(KEXTENSION,Kern::Printf("Installing the display device from the kernel extension returned with error code %d",r)); |
|
1050 |
|
1051 } |
|
1052 } |
|
1053 |
|
1054 return r; |
|
1055 } |