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