|
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 "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: EDID data Handler class for HDMI Cable Status FSM. |
|
15 * |
|
16 */ |
|
17 |
|
18 #include <tvoutconfig.h> |
|
19 #include <accpolhdmisink.h> |
|
20 #include <accpolhdmiaudioformat.h> |
|
21 #include <accpolhdmivideoformat.h> |
|
22 #include <accpolhdmilatency.h> |
|
23 #include <accpolhdmispeakerallocation.h> |
|
24 #include <e32cmn.h> |
|
25 #include <e32math.h> |
|
26 #include <accessoriescrkeys.h> |
|
27 #include <centralrepository.h> |
|
28 |
|
29 #include "pdeconstants.h" |
|
30 #include "tvoutconfigforhdmi.h" |
|
31 #include "edidhandler.h" |
|
32 #include "edidparserbase.h" |
|
33 #include "cea861edidparser.h" |
|
34 #include "multifinitestatemachine.h" |
|
35 #include "trace.h" |
|
36 #include "traceediddata.h" |
|
37 |
|
38 const TReal K16d9 = 1.778; |
|
39 const TReal K4d3 = 1.333; |
|
40 |
|
41 const TInt KDefaultCEAMode = E640x480p59_94d60Hz4d3; |
|
42 const TInt KDefaultCEAModeIndex = 0; |
|
43 |
|
44 // Retry Delay for EDID access |
|
45 const TInt KRetryDelay = 50 * 1000; // 50 milliseconds |
|
46 |
|
47 // Maximum retry count for EDID access |
|
48 const TInt KMaxRetryCount = 40; // 40 * 50ms = 2 Seconds |
|
49 |
|
50 const TUint16 KDefaultCEAModePhysImgAspRatioNr = 4; |
|
51 |
|
52 const TUint16 KDefaultCEAModePhysImgAspRatioDr = 3; |
|
53 |
|
54 //------------------------------------------------------------------------------ |
|
55 // Symbian two-phased constructor |
|
56 //------------------------------------------------------------------------------ |
|
57 // |
|
58 CEDIDHandler* CEDIDHandler::NewL( MFSMForBody& aFSM, |
|
59 CTVOutConfigForHDMI& aTVOutConfigForHDMI ) |
|
60 { |
|
61 FUNC_LOG; |
|
62 CEDIDHandler* self = new ( ELeave ) CEDIDHandler( |
|
63 aFSM, aTVOutConfigForHDMI ); |
|
64 CleanupStack::PushL( self ); |
|
65 self->ConstructL(); |
|
66 CleanupStack::Pop( self ); |
|
67 return self; |
|
68 } |
|
69 |
|
70 //------------------------------------------------------------------------------ |
|
71 // Destructor |
|
72 //------------------------------------------------------------------------------ |
|
73 // |
|
74 CEDIDHandler::~CEDIDHandler() |
|
75 { |
|
76 FUNC_LOG; |
|
77 |
|
78 Cancel(); |
|
79 delete iDdcPortAccess; |
|
80 delete iDataBlockPtr; |
|
81 delete iExtensionParserPtr; |
|
82 delete iEdidParserPtr; |
|
83 iRetryTimer.Close(); |
|
84 } |
|
85 |
|
86 //------------------------------------------------------------------------------ |
|
87 // FetchEDIDData |
|
88 //------------------------------------------------------------------------------ |
|
89 // |
|
90 TInt CEDIDHandler::FetchEDIDData() |
|
91 { |
|
92 FUNC_LOG; |
|
93 |
|
94 TInt retVal( KErrNone ); |
|
95 TUint apiVersion = iDdcPortAccess->ApiVersion(); |
|
96 if( KDdcAccessVersion != apiVersion ) |
|
97 { |
|
98 INFO_1( "iDdcPortAccess->ApiVersion() returned unsupported version != KDdcAccessVersion: %d", apiVersion ); |
|
99 retVal = KErrNotSupported; |
|
100 } |
|
101 else |
|
102 { |
|
103 iRetryCounter = KErrNone; |
|
104 TInt err = KErrNone; |
|
105 TRAP( retVal , err = ReadEDIDDataL() ); |
|
106 if ( err != KErrNone ) |
|
107 { |
|
108 retVal = err; |
|
109 } |
|
110 } |
|
111 INFO_1( "CEDIDHandler::FetchEDIDData() retVal: %d", retVal ); |
|
112 return retVal; |
|
113 } |
|
114 |
|
115 //------------------------------------------------------------------------------ |
|
116 // SetVideoParameters |
|
117 //------------------------------------------------------------------------------ |
|
118 // |
|
119 TInt CEDIDHandler::SetVideoParameters() |
|
120 { |
|
121 FUNC_LOG; |
|
122 |
|
123 TInt retVal = KErrNone; |
|
124 RArray<TTvSettings> analogConfigs; |
|
125 RArray<THdmiDviTimings> hdmiConfigs; |
|
126 |
|
127 // Update overscan values from cenrep |
|
128 UpdateOverscanValues(); |
|
129 |
|
130 // Set video parameters |
|
131 INFO( "--------------------------------------------------------------------" ); |
|
132 INFO( "SETTING CEA AND DMT TIMINGS:" ); |
|
133 retVal = SetCeaModes( hdmiConfigs ); |
|
134 ERROR( retVal, "Failed to set CEA modes" ); |
|
135 |
|
136 if( KErrNone == retVal ) |
|
137 { |
|
138 retVal = SetDmtModes( hdmiConfigs ); |
|
139 ERROR( retVal, "Failed to set DMT modes" ); |
|
140 INFO( "--------------------------------------------------------------------" ); |
|
141 |
|
142 if( KErrNone == retVal ) |
|
143 { |
|
144 // Filtering out the unsupported modes |
|
145 // Logical AND(Sink supported modes AND HW supported modes) |
|
146 INFO( "Filtering out the unsupported modes" ); |
|
147 retVal = FilterAvailableTvConfigList( hdmiConfigs ); |
|
148 ERROR( retVal, "Failed to filter the TV config list." ); |
|
149 |
|
150 if( KErrNone == retVal ) |
|
151 { |
|
152 retVal = iTVOutConfigForHDMI.SetAvailableTvConfigList( analogConfigs, hdmiConfigs ); |
|
153 ERROR( retVal, "Failed to set available TV config list." ); |
|
154 } |
|
155 } |
|
156 } |
|
157 |
|
158 // Clean up |
|
159 hdmiConfigs.Close(); |
|
160 analogConfigs.Close(); |
|
161 |
|
162 return retVal; |
|
163 } |
|
164 |
|
165 //------------------------------------------------------------------------------ |
|
166 // GetEDIDDataL |
|
167 //------------------------------------------------------------------------------ |
|
168 // |
|
169 void CEDIDHandler::ResetData() |
|
170 { |
|
171 FUNC_LOG; |
|
172 |
|
173 delete iDataBlockPtr; |
|
174 iDataBlockPtr = NULL; |
|
175 delete iEdidParserPtr; |
|
176 iEdidParserPtr = NULL; |
|
177 delete iExtensionParserPtr; |
|
178 iExtensionParserPtr = NULL; |
|
179 } |
|
180 |
|
181 //------------------------------------------------------------------------------ |
|
182 // CreateHdmiSinkL |
|
183 //------------------------------------------------------------------------------ |
|
184 // |
|
185 CAccPolHdmiSink* CEDIDHandler::CreateHdmiSinkL() |
|
186 { |
|
187 FUNC_LOG; |
|
188 |
|
189 CAccPolHdmiSink* hdmiSink( NULL ); |
|
190 if( iExtensionParserPtr && iTVOutConfigForHDMI.GetTvOutConfig() ) |
|
191 { |
|
192 hdmiSink = CAccPolHdmiSink::NewL( |
|
193 iExtensionParserPtr->BasicAudio(), |
|
194 iTVOutConfigForHDMI.GetTvOutConfig()->CopyProtectionStatus() ); |
|
195 } |
|
196 else |
|
197 { |
|
198 User::Leave( KErrNotFound ); |
|
199 } |
|
200 |
|
201 return hdmiSink; |
|
202 } |
|
203 |
|
204 //------------------------------------------------------------------------------ |
|
205 // CreateHdmiVideoFormatL |
|
206 //------------------------------------------------------------------------------ |
|
207 // |
|
208 void CEDIDHandler::CreateHdmiVideoFormatL( RAccPolHdmiVideoFormatArray& aHdmiVideoFormatArray ) |
|
209 { |
|
210 FUNC_LOG; |
|
211 |
|
212 // Active Video Format object values can be fetched from TvOutConfig interface. |
|
213 if( iEdidParserPtr && iTVOutConfigForHDMI.GetTvOutConfig() ) |
|
214 { |
|
215 THdmiDviTimings hdmiDviTimings; |
|
216 TInt retVal = iTVOutConfigForHDMI.GetTvOutConfig()->GetConfig( |
|
217 hdmiDviTimings ); |
|
218 if( KErrNone == retVal ) |
|
219 { |
|
220 CAccPolHdmiVideoFormat* hdmiVideoFormat = CAccPolHdmiVideoFormat::NewLC(); |
|
221 hdmiVideoFormat->SetCeaFixedMode( hdmiDviTimings.iCeaMode ); |
|
222 hdmiVideoFormat->SetDmtFixedMode( EDmtFixedModeNone ); |
|
223 hdmiVideoFormat->SetPixelRepeat( hdmiDviTimings.iPixelRepeat ); |
|
224 hdmiVideoFormat->SetInterlaced( hdmiDviTimings.iInterlaced ); |
|
225 aHdmiVideoFormatArray.AppendL( hdmiVideoFormat ); |
|
226 CleanupStack::Pop( hdmiVideoFormat ); |
|
227 } |
|
228 else |
|
229 { |
|
230 User::Leave( retVal ); |
|
231 } |
|
232 } |
|
233 else |
|
234 { |
|
235 User::Leave( KErrNotFound ); |
|
236 } |
|
237 } |
|
238 |
|
239 //------------------------------------------------------------------------------ |
|
240 // CreateHdmiLatencyL |
|
241 //------------------------------------------------------------------------------ |
|
242 // |
|
243 void CEDIDHandler::CreateHdmiLatencyL( RAccPolHdmiLatencyArray& aHdmiLatencyArray ) |
|
244 { |
|
245 FUNC_LOG; |
|
246 |
|
247 if( iEdidParserPtr && iExtensionParserPtr ) |
|
248 { |
|
249 // Interlaced audio and video latency |
|
250 CAccPolHdmiLatency* hdmiLatency = CAccPolHdmiLatency::NewLC( |
|
251 HdmiLatency::KUidInterlacedLatency, |
|
252 iExtensionParserPtr->GetInterlacedAudioLatency(), |
|
253 iExtensionParserPtr->GetInterlacedVideoLatency() ); |
|
254 aHdmiLatencyArray.AppendL( hdmiLatency ); |
|
255 CleanupStack::Pop( hdmiLatency ); |
|
256 |
|
257 // Progressive audio and video latency |
|
258 hdmiLatency = CAccPolHdmiLatency::NewLC( |
|
259 HdmiLatency::KUidLatency, |
|
260 iExtensionParserPtr->GetAudioLatency(), |
|
261 iExtensionParserPtr->GetVideoLatency() ); |
|
262 aHdmiLatencyArray.AppendL( hdmiLatency ); |
|
263 CleanupStack::Pop( hdmiLatency ); |
|
264 } |
|
265 else |
|
266 { |
|
267 User::Leave( KErrNotFound ); |
|
268 } |
|
269 } |
|
270 |
|
271 //------------------------------------------------------------------------------ |
|
272 // CreateHdmiAudioFormatL |
|
273 //------------------------------------------------------------------------------ |
|
274 // |
|
275 void CEDIDHandler::CreateHdmiAudioFormatL( RAccPolHdmiAudioFormatArray& aHdmiAudioFormatArray ) |
|
276 { |
|
277 FUNC_LOG; |
|
278 |
|
279 if( iExtensionParserPtr ) |
|
280 { |
|
281 if( iExtensionParserPtr->IsAudioDataBlockSupported() ) |
|
282 { |
|
283 TCEA861AudioDataBlock |
|
284 * audioDataBlock = |
|
285 iExtensionParserPtr->GetParsedInformation()->iShortAudioDescriptors; |
|
286 while( audioDataBlock ) |
|
287 { |
|
288 CAccPolHdmiAudioFormat* hdmiAudioFormat = |
|
289 CAccPolHdmiAudioFormat::NewL(); |
|
290 CleanupStack::PushL( hdmiAudioFormat ); |
|
291 |
|
292 // Set audio format |
|
293 TUid audioFormat; |
|
294 audioFormat.iUid = audioDataBlock->iAudioFormatCode; |
|
295 hdmiAudioFormat->SetAudioFormat( audioFormat ); // const TUid aAudioFormat, |
|
296 |
|
297 // Set bit resolution |
|
298 TUint32 bitResolution( CAccPolHdmiAudioFormat::EUnknownBitsPerSample ); |
|
299 if( audioDataBlock->iSupport24Bit ) |
|
300 { |
|
301 bitResolution |= CAccPolHdmiAudioFormat::EBitsPerSample24; |
|
302 } |
|
303 if( audioDataBlock->iSupport20Bit ) |
|
304 { |
|
305 bitResolution |= CAccPolHdmiAudioFormat::EBitsPerSample20; |
|
306 } |
|
307 if( audioDataBlock->iSupport16Bit ) |
|
308 { |
|
309 bitResolution |= CAccPolHdmiAudioFormat::EBitsPerSample16; |
|
310 } |
|
311 hdmiAudioFormat->SetBitResolution( bitResolution ); // const TUint32 aBitResolution, |
|
312 hdmiAudioFormat->SetMaxBitResolution( audioDataBlock->iMaxBitrate ); // const TUint32 aMaxBitResolution, |
|
313 hdmiAudioFormat->SetChannelCount( audioDataBlock->iMaxChannels ); // const TUint32 aMaxChannelCount, |
|
314 |
|
315 // Set sample frequency |
|
316 TUint32 samFreq( CAccPolHdmiAudioFormat::EUnknownFrequency ); |
|
317 if( audioDataBlock->iSupport192kHz ) |
|
318 { |
|
319 samFreq |
|
320 |= CAccPolHdmiAudioFormat::ESamplingFreq192KHz; |
|
321 } |
|
322 if( audioDataBlock->iSupport176kHz ) |
|
323 { |
|
324 samFreq |
|
325 |= CAccPolHdmiAudioFormat::ESamplingFreq176KHz; |
|
326 } |
|
327 if( audioDataBlock->iSupport96kHz ) |
|
328 { |
|
329 samFreq |
|
330 |= CAccPolHdmiAudioFormat::ESamplingFreq96KHz; |
|
331 } |
|
332 if( audioDataBlock->iSupport88kHz ) |
|
333 { |
|
334 samFreq |
|
335 |= CAccPolHdmiAudioFormat::ESamplingFreq88KHz; |
|
336 } |
|
337 if( audioDataBlock->iSupport48kHz ) |
|
338 { |
|
339 samFreq |
|
340 |= CAccPolHdmiAudioFormat::ESamplingFreq48KHz; |
|
341 } |
|
342 if( audioDataBlock->iSupport44kHz ) |
|
343 { |
|
344 samFreq |
|
345 |= CAccPolHdmiAudioFormat::ESamplingFreq44KHz; |
|
346 } |
|
347 if( audioDataBlock->iSupport32kHz ) |
|
348 { |
|
349 samFreq |
|
350 |= CAccPolHdmiAudioFormat::ESamplingFreq32KHz; |
|
351 } |
|
352 hdmiAudioFormat->SetSamFreq( samFreq ); // const TUint32 aSamFreq, |
|
353 hdmiAudioFormat->SetFormatDependentValue( audioDataBlock->iAudioFormatCodeExtension ); // const TUint32 aFormatDependentValue |
|
354 aHdmiAudioFormatArray.AppendL( hdmiAudioFormat ); |
|
355 CleanupStack::Pop( hdmiAudioFormat ); |
|
356 |
|
357 audioDataBlock = audioDataBlock->iNext; |
|
358 } |
|
359 } |
|
360 } |
|
361 else |
|
362 { |
|
363 User::Leave( KErrNotFound ); |
|
364 } |
|
365 } |
|
366 |
|
367 //------------------------------------------------------------------------------ |
|
368 // CreateHdmiAudioFormatL |
|
369 //------------------------------------------------------------------------------ |
|
370 // |
|
371 CAccPolHdmiSpeakerAllocation* CEDIDHandler::CreateHdmiSpeakerAllocationL() |
|
372 { |
|
373 FUNC_LOG; |
|
374 |
|
375 CAccPolHdmiSpeakerAllocation* hdmiSpeakerAllocation( NULL ); |
|
376 if( iExtensionParserPtr ) |
|
377 { |
|
378 if( iExtensionParserPtr->IsSpeakerAllocationDataBlockSupported() ) |
|
379 { |
|
380 TCEA861SpeakerAllocationData |
|
381 * speakerAllocationData = |
|
382 &( iExtensionParserPtr->GetParsedInformation()->iSpeakerAllocationData ); |
|
383 if( speakerAllocationData ) |
|
384 { |
|
385 hdmiSpeakerAllocation |
|
386 = CAccPolHdmiSpeakerAllocation::NewL( speakerAllocationData->FL_FR(), //const TBool aFrontSpeakers, |
|
387 speakerAllocationData->RL_RR(), //const TBool aRearSpeakers, |
|
388 speakerAllocationData->LFE(), //const TBool aLowFrequencyEffect, |
|
389 speakerAllocationData->FC(), //const TBool aFrontCenter, |
|
390 speakerAllocationData->FCH(), //const TBool aFrontCenterHigh, |
|
391 speakerAllocationData->TC(), //const TBool aTopCenter, |
|
392 speakerAllocationData->RC(), //const TBool aRearCenter, |
|
393 speakerAllocationData->FLC_FRC(), //const TBool aFrontLeftRightCenter, |
|
394 speakerAllocationData->RLC_RRC(), //const TBool aRearLeftRightCenter, |
|
395 speakerAllocationData->FLW_FRW(), //const TBool aFrontWideSpeakers, |
|
396 speakerAllocationData->FLH_FRH() //const TBool aFrontHighSpeakers |
|
397 ); |
|
398 } |
|
399 } |
|
400 } |
|
401 else |
|
402 { |
|
403 User::Leave( KErrNotFound ); |
|
404 } |
|
405 return hdmiSpeakerAllocation; |
|
406 } |
|
407 |
|
408 //------------------------------------------------------------------------------ |
|
409 // GetHdcpSupportStatus |
|
410 //------------------------------------------------------------------------------ |
|
411 // |
|
412 TInt CEDIDHandler::GetHdcpSupportStatus( TBool& aHdcpSupportStatus ) const |
|
413 { |
|
414 FUNC_LOG; |
|
415 |
|
416 TInt retVal( KErrNone ); |
|
417 if( iTVOutConfigForHDMI.GetTvOutConfig() ) |
|
418 { |
|
419 aHdcpSupportStatus |
|
420 = ( iTVOutConfigForHDMI.GetTvOutConfig() )->CopyProtectionStatus(); |
|
421 } |
|
422 else |
|
423 { |
|
424 retVal = KErrNotFound; |
|
425 } |
|
426 return retVal; |
|
427 } |
|
428 |
|
429 //------------------------------------------------------------------------------ |
|
430 // RunL |
|
431 //------------------------------------------------------------------------------ |
|
432 // |
|
433 void CEDIDHandler::RunL() |
|
434 { |
|
435 |
|
436 FUNC_LOG; |
|
437 |
|
438 switch ( iRequestID ) |
|
439 { |
|
440 case EDdcReadRequest: |
|
441 { |
|
442 if( KErrNone == iStatus.Int() ) |
|
443 { |
|
444 TPtrC8 |
|
445 dataBlockDes( iDataBlockPtr->iDataBlock, sizeof( *iDataBlockPtr ) ); |
|
446 iEdidParserPtr = CEdidParserBase::NewL( dataBlockDes ); |
|
447 TInt nbrOfExtensions = iEdidParserPtr->GetNumberOfExtensions(); |
|
448 for( TInt i = 0; i < nbrOfExtensions; ++i ) |
|
449 { |
|
450 if( ECea861Ext == iEdidParserPtr->GetExtensionType( i + 1 ) ) |
|
451 { |
|
452 INFO_1( "ECea861Ext extension data block number: %d", ( i+1 ) ); |
|
453 iExtensionParserPtr |
|
454 = iEdidParserPtr->CreateCea861ExtensionParserL( i + 1 ); |
|
455 break; |
|
456 } |
|
457 } |
|
458 INFO_1( "Data block count in nbrOfExtensions: %d", nbrOfExtensions ); |
|
459 iFSM.Input( EPDEIfEDIDHandler, EPDEIfEDIDHandlerEventEdidDataFetched ); |
|
460 iRetryCounter = KErrNone; |
|
461 } |
|
462 else |
|
463 { |
|
464 INFO_1( "CDdcPortAccess::Read failed, error code: %d", iStatus.Int() ); |
|
465 |
|
466 if( (iStatus.Int() == KErrNotReady) && (iRetryCounter < KMaxRetryCount) ) |
|
467 { |
|
468 iRetryCounter++; |
|
469 iRequestID = ERetryTimerRequest; |
|
470 iRetryTimer.After( iStatus, KRetryDelay ); |
|
471 SetActive(); |
|
472 } |
|
473 else |
|
474 { |
|
475 iRetryCounter = KErrNone; |
|
476 iFSM.Input( EPDEIfEDIDHandler, |
|
477 EPDEIfEDIDHandlerEventEdidDataFetchFailed ); |
|
478 } |
|
479 } |
|
480 break; |
|
481 } |
|
482 case ERetryTimerRequest: |
|
483 { |
|
484 INFO_1( "Retrying... count: %d", iRetryCounter ); |
|
485 if( ReadEDIDDataL() != KErrNone ) |
|
486 { |
|
487 iFSM.Input( EPDEIfEDIDHandler, EPDEIfEDIDHandlerEventEdidDataFetchFailed ); |
|
488 } |
|
489 break; |
|
490 } |
|
491 default: |
|
492 { |
|
493 INFO_1( "Undefined Request ID %d", iRequestID ); |
|
494 break; |
|
495 } |
|
496 } |
|
497 } |
|
498 |
|
499 //------------------------------------------------------------------------------ |
|
500 // From class CActive. |
|
501 // RunL |
|
502 //------------------------------------------------------------------------------ |
|
503 // |
|
504 TInt CEDIDHandler::RunError( TInt aError ) |
|
505 { |
|
506 FUNC_LOG; |
|
507 |
|
508 /*TInt err( aError ); |
|
509 // Avoid Panic in CActiveScheduler |
|
510 if ( err ) |
|
511 { |
|
512 INFO_1( "aError %d", err ); |
|
513 }*/ |
|
514 iFSM.Input( EPDEIfEDIDHandler, EPDEIfEDIDHandlerEventEdidDataFetchFailed ); |
|
515 |
|
516 return KErrNone; |
|
517 } |
|
518 |
|
519 //------------------------------------------------------------------------------- |
|
520 // DoCancel |
|
521 // |
|
522 //------------------------------------------------------------------------------- |
|
523 // |
|
524 void CEDIDHandler::DoCancel() |
|
525 { |
|
526 FUNC_LOG; |
|
527 |
|
528 iDdcPortAccess->CancelAll(); |
|
529 } |
|
530 |
|
531 //------------------------------------------------------------------------------ |
|
532 // ReadEDIDDataL |
|
533 //------------------------------------------------------------------------------ |
|
534 // |
|
535 TInt CEDIDHandler::ReadEDIDDataL() |
|
536 { |
|
537 FUNC_LOG; |
|
538 |
|
539 TInt retVal( KErrNone ); |
|
540 |
|
541 iRequestID = EDdcReadRequest; |
|
542 |
|
543 if( iDataBlockPtr == NULL ) |
|
544 { |
|
545 iDataBlockPtr = new(ELeave) TDataBlock; |
|
546 } |
|
547 |
|
548 retVal = iDdcPortAccess->Read( EMonitorPort, 0, // First block contains EDID data if that exists |
|
549 iDataBlockPtr->iDataBlock, |
|
550 iStatus ); |
|
551 |
|
552 SetActive(); |
|
553 |
|
554 ERROR(retVal, "iDdcPortAccess->Read failed" ); |
|
555 |
|
556 return retVal; |
|
557 } |
|
558 |
|
559 //------------------------------------------------------------------------------ |
|
560 // CEDIDHandler::FillCommonHdmiDviTimings |
|
561 //------------------------------------------------------------------------------ |
|
562 // |
|
563 void CEDIDHandler::FillCommonHdmiDviTimings( THdmiDviTimings& aTimings ) const |
|
564 { |
|
565 FUNC_LOG; |
|
566 |
|
567 aTimings.iTvPhysicalImageWidthMm = iEdidParserPtr->GetHorizontalScreenSize() * 10; |
|
568 aTimings.iTvPhysicalImageHeightMm = iEdidParserPtr->GetVerticalScreenSize() * 10; |
|
569 aTimings.iTvPhysicalImageAspectRatioNumerator = 0; |
|
570 aTimings.iTvPhysicalImageAspectRatioDenominator = 0; |
|
571 aTimings.iHorizontalBorderPixels = 0; |
|
572 aTimings.iVerticalBorderLinesField1 = 0; |
|
573 aTimings.iVerticalBorderLinesField2 = 0; |
|
574 aTimings.iLeftBorderPixels = 0; |
|
575 aTimings.iRightBorderPixels = 0; |
|
576 aTimings.iUnderscanEnabled = EFalse; |
|
577 |
|
578 if( iExtensionParserPtr ) |
|
579 { |
|
580 aTimings.iUnderscanEnabled = iExtensionParserPtr->Underscan(); |
|
581 } |
|
582 |
|
583 if( aTimings.iUnderscanEnabled ) |
|
584 { |
|
585 // Underscan |
|
586 aTimings.iLeftTopCorner.iX = 0; |
|
587 aTimings.iLeftTopCorner.iY = 0; |
|
588 aTimings.iRightBottomCorner.iX = aTimings.iHorizontalActivePixels; |
|
589 aTimings.iRightBottomCorner.iY = aTimings.iVerticalActiveLines; |
|
590 } |
|
591 else |
|
592 { |
|
593 // Calculate overscan |
|
594 CalculateOverscan( aTimings.iLeftTopCorner, |
|
595 aTimings.iRightBottomCorner ); |
|
596 } |
|
597 aTimings.iTvPhysicalImageAspectRatioNumerator = iEdidParserPtr->GetAspectRatioLandscape(); |
|
598 aTimings.iTvPhysicalImageAspectRatioDenominator = iEdidParserPtr->GetAspectRatioPortrait(); |
|
599 aTimings.iConnector = TTvSettings::EHDMI; |
|
600 aTimings.iTvColorCoordinates.iRed.iX = iEdidParserPtr->GetColorCoordinatesRedX(); |
|
601 aTimings.iTvColorCoordinates.iRed.iY = iEdidParserPtr->GetColorCoordinatesRedY(); |
|
602 aTimings.iTvColorCoordinates.iGreen.iX = iEdidParserPtr->GetColorCoordinatesGreenX(); |
|
603 aTimings.iTvColorCoordinates.iGreen.iY = iEdidParserPtr->GetColorCoordinatesGreenY(); |
|
604 aTimings.iTvColorCoordinates.iBlue.iX = iEdidParserPtr->GetColorCoordinatesBlueX(); |
|
605 aTimings.iTvColorCoordinates.iBlue.iY = iEdidParserPtr->GetColorCoordinatesBlueY(); |
|
606 aTimings.iTvColorCoordinates.iWhite.iX = iEdidParserPtr->GetColorCoordinatesWhiteX(); |
|
607 aTimings.iTvColorCoordinates.iWhite.iY = iEdidParserPtr->GetColorCoordinatesWhiteY(); |
|
608 aTimings.iTvHdmiVersion = iEdidParserPtr->GetVersion(); |
|
609 aTimings.iTvHdmiRevision = iEdidParserPtr->GetRevision(); |
|
610 Mem::FillZ( ( TAny* )&aTimings.iProductName, ( sizeof( TChar ) * KProductNameChars ) ); |
|
611 Mem::FillZ( ( TAny* )&aTimings.iProductDescription, ( sizeof( TChar ) * KProductDescriptorsChars ) ); |
|
612 aTimings.iSourceType = THdmiDviTimings::ESourceTypeUnknown; |
|
613 } |
|
614 |
|
615 //------------------------------------------------------------------------------ |
|
616 // CEDIDHandler::FillHdmiDviTimings |
|
617 //------------------------------------------------------------------------------ |
|
618 // |
|
619 void CEDIDHandler::FillHdmiDviTimings( const TTimingItem& aItem, |
|
620 THdmiDviTimings& aTimings ) const |
|
621 { |
|
622 FUNC_LOG; |
|
623 |
|
624 // Fill attributes from the static table |
|
625 if( aItem.iTimingType == ETimingModeCEA ) |
|
626 { |
|
627 // CEA |
|
628 aTimings.iCeaMode = static_cast<TFixedModeCea>( aItem.iTimingId ); |
|
629 } |
|
630 else |
|
631 { |
|
632 // DMT |
|
633 aTimings.iDmtMode = static_cast<TFixedModeDmt>( aItem.iTimingId ); |
|
634 } |
|
635 aTimings.iPixelClockKHz = aItem.iDotClock; |
|
636 aTimings.iHorizontalActivePixels = aItem.iHorizontalActive; |
|
637 aTimings.iHorizontalBlankingPixels = aItem.iHorizontalBlanking; |
|
638 aTimings.iHorizontalSyncOffsetPixels = aItem.iHorizontalFrontPorch; |
|
639 aTimings.iHorizontalSyncPulseWidthPixels = aItem.iHorizontalSync; |
|
640 aTimings.iVerticalActiveLines = aItem.iVertical1stActive; |
|
641 aTimings.iVerticalBlankingLines = aItem.iVertical1stBlanking; |
|
642 aTimings.iVerticalSyncOffsetLinesField1 = aItem.iVertical1stFrontPorch; |
|
643 aTimings.iVerticalSyncPulseWidthLinesField1 = aItem.iVertical1stSync; |
|
644 aTimings.iVerticalSyncOffsetLinesField2 = aItem.iVertical2ndFrontPorch; |
|
645 aTimings.iVerticalSyncPulseWidthLinesField2 = aItem.iVertical2ndSync; |
|
646 aTimings.iInterlaced = aItem.iInterlaced; |
|
647 aTimings.iHorizontalSyncPolarity = aItem.iHorizontalSyncPolarity; |
|
648 aTimings.iVerticalSyncPolarity = aItem.iVerticalSyncPolarity; |
|
649 aTimings.iPixelRepeat = aItem.iPixelRepeat; |
|
650 aTimings.iRightBottomCorner.iX = aItem.iWidth; |
|
651 aTimings.iRightBottomCorner.iY = aItem.iHeight; |
|
652 aTimings.iImageAspectRatio = aItem.iAspectRatio; |
|
653 if( aTimings.iImageAspectRatio == TTvSettings::EUndefRatio ) |
|
654 { |
|
655 // Resolve ratio from width and height |
|
656 aTimings.iImageAspectRatio = ResolveAspectRatio( aItem.iWidth, aItem.iHeight ); |
|
657 } |
|
658 aTimings.iPixelAspectRatioNumerator = aItem.iPixelAspectRatioNumerator; |
|
659 aTimings.iPixelAspectRatioDenominator = aItem.iPixelAspectRatioDenominator; |
|
660 |
|
661 // Fill the common attributes |
|
662 FillCommonHdmiDviTimings( aTimings ); |
|
663 |
|
664 TRACE_TIMINGS( aTimings ); |
|
665 } |
|
666 |
|
667 //------------------------------------------------------------------------------ |
|
668 // CEDIDHandler::FillHdmiDviTimings |
|
669 //------------------------------------------------------------------------------ |
|
670 // |
|
671 void CEDIDHandler::FillHdmiDviTimings( const TEdidDescriptorBlock& aDescBlock, |
|
672 THdmiDviTimings& aTimings ) const |
|
673 { |
|
674 FUNC_LOG; |
|
675 |
|
676 // Fill attributes from timing descriptor |
|
677 aTimings.iCeaMode = ECeaFixedModeNone; |
|
678 aTimings.iDmtMode = EDmtFixedModeNone; |
|
679 aTimings.iPixelClockKHz = aDescBlock.iPixelClock; |
|
680 aTimings.iHorizontalActivePixels = aDescBlock.iHorizontalAddressableVideoPixels; |
|
681 aTimings.iHorizontalBlankingPixels = aDescBlock.iHorizontalBlanking; |
|
682 aTimings.iHorizontalSyncOffsetPixels = aDescBlock.iHorizontalFrontPorch; |
|
683 aTimings.iHorizontalSyncPulseWidthPixels = aDescBlock.iHorizontalSyncPulse; |
|
684 aTimings.iHorizontalBorderPixels = aDescBlock.iHorizontalBorder; |
|
685 aTimings.iVerticalActiveLines = aDescBlock.iVerticalAddressableVideoPixels; |
|
686 aTimings.iVerticalBlankingLines = aDescBlock.iVerticalBlanking; |
|
687 aTimings.iVerticalSyncOffsetLinesField1 = aDescBlock.iVerticalFrontPorch; |
|
688 aTimings.iVerticalSyncPulseWidthLinesField1 = aDescBlock.iVerticalSyncPulse; |
|
689 aTimings.iVerticalBorderLinesField1 = aDescBlock.iVerticalBorder; |
|
690 aTimings.iInterlaced = aDescBlock.iInterlacedVideo; |
|
691 if( aDescBlock.iSyncs == |
|
692 EDigitalSeparateSyncVerticalSyncIsNegativeHorizontalSyncIsNegative ) |
|
693 { |
|
694 aTimings.iVerticalSyncPolarity = EFalse; |
|
695 aTimings.iHorizontalSyncPolarity = EFalse; |
|
696 } |
|
697 else if( aDescBlock.iSyncs == |
|
698 EDigitalSeparateSyncVerticalSyncIsNegativeHorizontalSyncIsPositive ) |
|
699 { |
|
700 aTimings.iVerticalSyncPolarity = EFalse; |
|
701 aTimings.iHorizontalSyncPolarity = ETrue; |
|
702 } |
|
703 else if( aDescBlock.iSyncs == |
|
704 EDigitalSeparateSyncVerticalSyncIsPositiveHorizontalSyncIsNegative ) |
|
705 { |
|
706 aTimings.iVerticalSyncPolarity = ETrue; |
|
707 aTimings.iHorizontalSyncPolarity = EFalse; |
|
708 } |
|
709 else if( aDescBlock.iSyncs == |
|
710 EDigitalSeparateSyncVerticalSyncIsPositiveHorizontalSyncIsPositive ) |
|
711 { |
|
712 aTimings.iVerticalSyncPolarity = ETrue; |
|
713 aTimings.iHorizontalSyncPolarity = ETrue; |
|
714 } |
|
715 aTimings.iPixelRepeat = 1; |
|
716 aTimings.iRightBottomCorner.iX = aDescBlock.iHorizontalAddressableVideoPixels; |
|
717 aTimings.iRightBottomCorner.iY = aDescBlock.iVerticalAddressableVideoPixels; |
|
718 aTimings.iImageAspectRatio = ResolveAspectRatio( |
|
719 aTimings.iHorizontalActivePixels, |
|
720 aTimings.iVerticalActiveLines ); |
|
721 |
|
722 // Fill the common attributes |
|
723 FillCommonHdmiDviTimings( aTimings ); |
|
724 |
|
725 TRACE_TIMINGS( aTimings ); |
|
726 } |
|
727 |
|
728 //------------------------------------------------------------------------------ |
|
729 // SetCeaModes |
|
730 //------------------------------------------------------------------------------ |
|
731 // |
|
732 TInt CEDIDHandler::SetCeaModes( RArray<THdmiDviTimings>& aTimings ) const |
|
733 { |
|
734 FUNC_LOG; |
|
735 |
|
736 TInt retVal(KErrNone); |
|
737 |
|
738 // Use only CEA-861 extension parser |
|
739 if( iExtensionParserPtr ) |
|
740 { |
|
741 // Get parsed information |
|
742 CCea861ExtEdidInformation* info = |
|
743 iExtensionParserPtr->GetParsedInformation(); |
|
744 if( info ) |
|
745 { |
|
746 // Go through all supported CEA modes |
|
747 TCEA861VideoDataBlock* vdb = info->iShortVideoDescriptors; |
|
748 THdmiDviTimings timings; |
|
749 while( vdb ) |
|
750 { |
|
751 // Get a timing item matched with the VIC mode |
|
752 TInt index = vdb->iVIC - 1; |
|
753 if( ( index >= 0 ) && ( index < KCEATimingCount ) ) |
|
754 { |
|
755 const TTimingItem* item = TimingByIndex( index, ETimingModeCEA ); |
|
756 if( item ) |
|
757 { |
|
758 Mem::FillZ( ( TAny* )&timings, sizeof( timings ) ); |
|
759 FillHdmiDviTimings( *item, timings ); |
|
760 retVal = aTimings.Append( timings ); |
|
761 ERROR_1( retVal, "Failed to append CEA timing: %S in array", item->iTimingName ); |
|
762 } |
|
763 else |
|
764 { |
|
765 ERROR_1( KErrArgument, "CEA timing item not found for VIC mode: %d", index ); |
|
766 } |
|
767 } |
|
768 vdb = vdb->iNext; |
|
769 } |
|
770 } |
|
771 } |
|
772 |
|
773 return retVal; |
|
774 } |
|
775 |
|
776 //------------------------------------------------------------------------------ |
|
777 // SetDmtModes |
|
778 //------------------------------------------------------------------------------ |
|
779 // |
|
780 TInt CEDIDHandler::SetDmtModes( RArray<THdmiDviTimings>& aTimings ) const |
|
781 { |
|
782 FUNC_LOG; |
|
783 |
|
784 TInt retVal(KErrNone); |
|
785 |
|
786 // Check established timings 1 and 2 |
|
787 retVal = SetDmtModesFromEstablishedTimings( aTimings ); |
|
788 |
|
789 if( KErrNone == retVal ) |
|
790 { |
|
791 // Check standard timings |
|
792 retVal = SetDmtModesFromStandardTimings( aTimings ); |
|
793 |
|
794 if( KErrNone == retVal ) |
|
795 { |
|
796 // Check timing descriptors |
|
797 retVal = SetDmtModesFromTimingDescriptors( aTimings ); |
|
798 } |
|
799 } |
|
800 |
|
801 return retVal; |
|
802 } |
|
803 |
|
804 //------------------------------------------------------------------------------ |
|
805 // SetDmtModesFromEstablishedTimings |
|
806 //------------------------------------------------------------------------------ |
|
807 // |
|
808 TInt CEDIDHandler::SetDmtModesFromEstablishedTimings( |
|
809 RArray<THdmiDviTimings>& aTimings ) const |
|
810 { |
|
811 FUNC_LOG; |
|
812 |
|
813 TUint8 timings = 0; |
|
814 TUint16 width = 0; |
|
815 TUint16 height = 0; |
|
816 TUint16 refreshRate = 0; |
|
817 TInt retVal(KErrNone); |
|
818 |
|
819 // Established timings 1 |
|
820 // Bits 4, 6 and 7 left out since these does not match to DMT |
|
821 timings = iEdidParserPtr->GetEstablishedTimings1(); |
|
822 if( timings & E800x600_60Hz ) // Bit 0 |
|
823 { |
|
824 width = 800; |
|
825 height = 600; |
|
826 refreshRate = 60; |
|
827 retVal = SetDmtModeByResolution( aTimings, width, height, refreshRate ); |
|
828 } |
|
829 if( timings & E800x600_56Hz ) // Bit 1 |
|
830 { |
|
831 width = 800; |
|
832 height = 600; |
|
833 refreshRate = 56; |
|
834 retVal = SetDmtModeByResolution( aTimings, width, height, refreshRate ); |
|
835 } |
|
836 if( timings & E640x480_75Hz ) // Bit 2 |
|
837 { |
|
838 width = 640; |
|
839 height = 480; |
|
840 refreshRate = 75; |
|
841 retVal = SetDmtModeByResolution( aTimings, width, height, refreshRate ); |
|
842 } |
|
843 if( timings & E640x480_72Hz ) // Bit 3 |
|
844 { |
|
845 width = 640; |
|
846 height = 480; |
|
847 refreshRate = 72; |
|
848 retVal = SetDmtModeByResolution( aTimings, width, height, refreshRate ); |
|
849 } |
|
850 if( timings & E640x480_60Hz ) // Bit 5 |
|
851 { |
|
852 width = 640; |
|
853 height = 480; |
|
854 refreshRate = 60; |
|
855 retVal = SetDmtModeByResolution( aTimings, width, height, refreshRate ); |
|
856 } |
|
857 |
|
858 // Established timings 2 |
|
859 // Bit 5 left out since it does not match to DMT |
|
860 timings = iEdidParserPtr->GetEstablishedTimings2(); |
|
861 if( timings & E1280x1024_75Hz ) // Bit 0 |
|
862 { |
|
863 width = 1280; |
|
864 height = 1024; |
|
865 refreshRate = 75; |
|
866 retVal = SetDmtModeByResolution( aTimings, width, height, refreshRate ); |
|
867 } |
|
868 if( timings & E1024x768_75Hz ) // Bit 1 |
|
869 { |
|
870 width = 1024; |
|
871 height = 768; |
|
872 refreshRate = 75; |
|
873 retVal = SetDmtModeByResolution( aTimings, width, height, refreshRate ); |
|
874 } |
|
875 if( timings & E1024x768_70Hz ) // Bit 2 |
|
876 { |
|
877 width = 1280; |
|
878 height = 768; |
|
879 refreshRate = 70; |
|
880 retVal = SetDmtModeByResolution( aTimings, width, height, refreshRate ); |
|
881 } |
|
882 if( timings & E1024x768_60Hz ) // Bit 3 |
|
883 { |
|
884 width = 1280; |
|
885 height = 768; |
|
886 refreshRate = 60; |
|
887 retVal = SetDmtModeByResolution( aTimings, width, height, refreshRate ); |
|
888 } |
|
889 if( timings & E1024x768_87Hz ) // Bit 4 |
|
890 { |
|
891 width = 1280; |
|
892 height = 768; |
|
893 refreshRate = 87; |
|
894 retVal = SetDmtModeByResolution( aTimings, width, height, refreshRate ); |
|
895 } |
|
896 if( timings & E800x600_75Hz ) // Bit 6 |
|
897 { |
|
898 width = 800; |
|
899 height = 600; |
|
900 refreshRate = 75; |
|
901 retVal = SetDmtModeByResolution( aTimings, width, height, refreshRate ); |
|
902 } |
|
903 if( timings & E800x600_72Hz ) // Bit 7 |
|
904 { |
|
905 width = 800; |
|
906 height = 600; |
|
907 refreshRate = 72; |
|
908 retVal = SetDmtModeByResolution( aTimings, width, height, refreshRate ); |
|
909 } |
|
910 |
|
911 return retVal; |
|
912 } |
|
913 |
|
914 //------------------------------------------------------------------------------ |
|
915 // SetDmtModesFromStandardTimings |
|
916 //------------------------------------------------------------------------------ |
|
917 // |
|
918 TInt CEDIDHandler::SetDmtModesFromStandardTimings( |
|
919 RArray<THdmiDviTimings>& aTimings ) const |
|
920 { |
|
921 FUNC_LOG; |
|
922 |
|
923 // One timing descriptor is specified in two bytes: |
|
924 // 26h: |
|
925 // ------------------------------------------------------------------------- |
|
926 // 01h-FFh: |
|
927 // Horizontal addressable pixels: Value Stored (in hex) = |
|
928 // (Horizontal addressable pixels / 8) – 31 |
|
929 // Range: 256 pixels -> 2288 pixels, in increments of 8 pixels |
|
930 // -------------------------------------------------------------------- |
|
931 // 00h: |
|
932 // Reserved. Do not use! |
|
933 // ------------------------------------------------------------------------- |
|
934 // 27h: |
|
935 // ------------------------------------------------------------------------- |
|
936 // Bits 7 - 6: |
|
937 // Image Aspect Ratio: |
|
938 // 0 0 _ _ _ _ _ _ (16 : 10 AR) |
|
939 // 0 1 _ _ _ _ _ _ ( 4 : 3 AR) |
|
940 // 1 0 _ _ _ _ _ _ ( 5 : 4 AR) |
|
941 // 1 1 _ _ _ _ _ _ (16 : 9 AR) |
|
942 // -------------------------------------------------------------------- |
|
943 // Bits 0 - 5: |
|
944 // Field Refresh Rate: Value Stored (in binary) = |
|
945 // Field Refresh Rate (in Hz) – 60 |
|
946 // Range: 60 Hz -> 123Hz |
|
947 // ------------------------------------------------------------------------- |
|
948 // 27h: |
|
949 // 28h: |
|
950 // ------------------------------------------------------------------------- |
|
951 // etc. |
|
952 |
|
953 // There can be up to 8 standard timings (2 bytes * 8) |
|
954 const TInt KStandardTimingBytes = 16; |
|
955 const TUint KRefreshRateMask = 0x3F; // --XXXXXX |
|
956 TInt retVal(KErrNone); |
|
957 |
|
958 TUint16 width = 0; |
|
959 TUint16 height = 0; |
|
960 TUint16 refreshRate = 0; |
|
961 TUint8 byte1 = 0; |
|
962 TUint8 byte2 = 0; |
|
963 for( TInt i = 0; i < KStandardTimingBytes; i += 2 ) |
|
964 { |
|
965 byte1 = iEdidParserPtr->GetStandardTimings( i ); |
|
966 byte2 = iEdidParserPtr->GetStandardTimings( i + 1 ); |
|
967 |
|
968 // Horizontal pixels |
|
969 width = ( byte1 + 31 ) * 8; |
|
970 |
|
971 // Aspect ratio & vertical lines |
|
972 if( !( byte2 & KBit7 ) && !( byte2 & KBit6 ) ) |
|
973 { |
|
974 // 16 : 10 AR |
|
975 height = ( width * 10 ) / 16; |
|
976 } |
|
977 else if( !( byte2& KBit7 ) && ( byte2 & KBit6 ) ) |
|
978 { |
|
979 // 4 : 3 AR |
|
980 height = ( width * 3 ) / 4; |
|
981 } |
|
982 else if( ( byte2 & KBit7 ) && !( byte2& KBit6 ) ) |
|
983 { |
|
984 // 5 : 4 AR |
|
985 height = ( width * 4 ) / 5; |
|
986 } |
|
987 else // ( byte2 & KBit7 ) && ( byte2 & KBit6 ) |
|
988 { |
|
989 // 16 : 9 AR |
|
990 height = ( width * 9 ) / 16; |
|
991 } |
|
992 |
|
993 // Refresh rate |
|
994 // Nullify bits 6 and 7 |
|
995 byte2 = byte2 & KRefreshRateMask; |
|
996 refreshRate = byte2 + 60; |
|
997 |
|
998 // Set timing item by resolution |
|
999 retVal = SetDmtModeByResolution( aTimings, width, height, refreshRate ); |
|
1000 } |
|
1001 |
|
1002 return retVal; |
|
1003 } |
|
1004 |
|
1005 //------------------------------------------------------------------------------ |
|
1006 // SetDmtModesFromTimingDescriptors |
|
1007 //------------------------------------------------------------------------------ |
|
1008 // |
|
1009 TInt CEDIDHandler::SetDmtModesFromTimingDescriptors( |
|
1010 RArray<THdmiDviTimings>& aTimings ) const |
|
1011 { |
|
1012 FUNC_LOG; |
|
1013 |
|
1014 // 1st 18 byte timing descriptor |
|
1015 THdmiDviTimings timings; |
|
1016 TInt retVal(KErrNone); |
|
1017 |
|
1018 TEdidDescriptorBlock first = |
|
1019 iEdidParserPtr->GetDescriptorBlock( EEdidDescriptorBlockFirstTiming ); |
|
1020 FillHdmiDviTimings( first, timings ); |
|
1021 retVal = aTimings.Append( timings ); |
|
1022 ERROR( retVal, "Failed to append 1st timing descriptor in array" ); |
|
1023 |
|
1024 if( KErrNone == retVal ) |
|
1025 { |
|
1026 // 2nd 18 byte timing descriptor |
|
1027 Mem::FillZ( ( TAny* )&timings, sizeof( timings ) ); |
|
1028 TEdidDescriptorBlock second = |
|
1029 iEdidParserPtr->GetDescriptorBlock( EEdidDescriptorBlockSecondTiming ); |
|
1030 FillHdmiDviTimings( second, timings ); |
|
1031 retVal = aTimings.Append( timings ); |
|
1032 ERROR( retVal, "Failed to append 2nd timing descriptor in array" ); |
|
1033 } |
|
1034 |
|
1035 return retVal; |
|
1036 } |
|
1037 |
|
1038 //------------------------------------------------------------------------------ |
|
1039 // TimingByIndex |
|
1040 //------------------------------------------------------------------------------ |
|
1041 // |
|
1042 const TTimingItem* CEDIDHandler::TimingByIndex( TInt aIndex, |
|
1043 TTimingModeType aType ) const |
|
1044 { |
|
1045 FUNC_LOG; |
|
1046 |
|
1047 const TTimingItem* item = NULL; |
|
1048 if( aIndex >= 0 ) |
|
1049 { |
|
1050 if( aType == ETimingModeCEA ) |
|
1051 { |
|
1052 if( aIndex < KCEATimingCount ) |
|
1053 { |
|
1054 item = &KCEATimings[aIndex]; |
|
1055 } |
|
1056 } |
|
1057 else |
|
1058 { |
|
1059 if( aIndex < KDMTTimingCount ) |
|
1060 { |
|
1061 item = &KDMTTimings[aIndex]; |
|
1062 } |
|
1063 } |
|
1064 } |
|
1065 |
|
1066 return item; |
|
1067 } |
|
1068 |
|
1069 //------------------------------------------------------------------------------ |
|
1070 // TimingByResolution |
|
1071 //------------------------------------------------------------------------------ |
|
1072 // |
|
1073 const TTimingItem* CEDIDHandler::TimingByResolution( TUint16 aWidth, |
|
1074 TUint16 aHeight, |
|
1075 TUint16 aRefreshRate, |
|
1076 TTimingModeType aType ) const |
|
1077 { |
|
1078 FUNC_LOG; |
|
1079 |
|
1080 const TTimingItem* item = NULL; |
|
1081 if( aType == ETimingModeCEA ) |
|
1082 { |
|
1083 // CEA mode |
|
1084 for( TInt i = 0; i < KCEATimingCount; i++ ) |
|
1085 { |
|
1086 item = &KCEATimings[i]; |
|
1087 if( item->iWidth == aWidth && |
|
1088 item->iHeight == aHeight && |
|
1089 item->iFieldRate == aRefreshRate ) |
|
1090 { |
|
1091 // Item found, break |
|
1092 break; |
|
1093 } |
|
1094 item = NULL; |
|
1095 } |
|
1096 } |
|
1097 else |
|
1098 { |
|
1099 // DMT mode |
|
1100 for( TInt i = 0; i < KDMTTimingCount; i++ ) |
|
1101 { |
|
1102 item = &KDMTTimings[i]; |
|
1103 if( item->iWidth == aWidth && |
|
1104 item->iHeight == aHeight && |
|
1105 item->iFieldRate == aRefreshRate ) |
|
1106 { |
|
1107 // Item found, break |
|
1108 break; |
|
1109 } |
|
1110 item = NULL; |
|
1111 } |
|
1112 } |
|
1113 |
|
1114 return item; |
|
1115 } |
|
1116 |
|
1117 //------------------------------------------------------------------------------ |
|
1118 // SetDmtModeByResolution |
|
1119 //------------------------------------------------------------------------------ |
|
1120 // |
|
1121 TInt CEDIDHandler::SetDmtModeByResolution( RArray<THdmiDviTimings>& aTimings, |
|
1122 TUint16 aWidth, |
|
1123 TUint16 aHeight, |
|
1124 TUint16 aRefreshRate ) const |
|
1125 { |
|
1126 FUNC_LOG; |
|
1127 |
|
1128 TInt retVal(KErrNone); |
|
1129 |
|
1130 const TTimingItem* item = TimingByResolution( aWidth, |
|
1131 aHeight, aRefreshRate, ETimingModeDMT ); |
|
1132 if( item ) |
|
1133 { |
|
1134 THdmiDviTimings timings; |
|
1135 FillHdmiDviTimings( *item, timings ); |
|
1136 retVal = aTimings.Append( timings ); |
|
1137 ERROR_1( retVal, "Failed to append DMT timing: %S in array", |
|
1138 item->iTimingName ); |
|
1139 } |
|
1140 else |
|
1141 { |
|
1142 ERROR_3( KErrArgument, "DMT timing item not found for width: %d, height: %d, refresh rate: %d", |
|
1143 aWidth, aHeight, aRefreshRate ); |
|
1144 } |
|
1145 |
|
1146 return retVal; |
|
1147 } |
|
1148 |
|
1149 //------------------------------------------------------------------------------ |
|
1150 // SetDmtModeByResolution |
|
1151 //------------------------------------------------------------------------------ |
|
1152 // |
|
1153 TTvSettings::TAspectRatio CEDIDHandler::ResolveAspectRatio( TUint16 aWidth, |
|
1154 TUint16 aHeight ) const |
|
1155 { |
|
1156 FUNC_LOG; |
|
1157 |
|
1158 TTvSettings::TAspectRatio aspectRatio = TTvSettings::EUndefRatio; |
|
1159 TReal source = ( TReal )aWidth / ( TReal )aHeight; |
|
1160 TReal target = 0.0; |
|
1161 if( Math::Round( target, source, 3 ) == KErrNone ) |
|
1162 { |
|
1163 if( target == K16d9 ) |
|
1164 { |
|
1165 // 16:9 |
|
1166 aspectRatio = TTvSettings::E16d9; |
|
1167 } |
|
1168 else if( target == K4d3 ) |
|
1169 { |
|
1170 // 4:3 |
|
1171 aspectRatio = TTvSettings::E4d3; |
|
1172 } |
|
1173 } |
|
1174 |
|
1175 return aspectRatio; |
|
1176 } |
|
1177 |
|
1178 //------------------------------------------------------------------------------ |
|
1179 // CalculateOverscan |
|
1180 //------------------------------------------------------------------------------ |
|
1181 // |
|
1182 void CEDIDHandler::CalculateOverscan( TPoint& aTLCorner, |
|
1183 TPoint& aBRCorner ) const |
|
1184 { |
|
1185 FUNC_LOG; |
|
1186 |
|
1187 // No need to calculate if the screen size is zero |
|
1188 if( aBRCorner.iX > 0 && aBRCorner.iY > 0 ) |
|
1189 { |
|
1190 // hOverscanPixels = ( ( Width * hOverscan ) + 50 ) / 20000 |
|
1191 // |
|
1192 // hOverscanPixels: |
|
1193 // pixels which are needed to be added to top left X |
|
1194 // pixels which are needed to be reduced from bottom right X |
|
1195 // Width: |
|
1196 // Horizontal resolution |
|
1197 // hOverscan: |
|
1198 // Horizontal overscan in percents (1% == 100) |
|
1199 // 50: |
|
1200 // Used to round up possible decimals |
|
1201 // 20000: |
|
1202 // Used to get rid of percentage multiplier and to get the overscan value |
|
1203 // for one side |
|
1204 TInt hOverscanPixels = ( aBRCorner.iX * iHOverscan + 50 ) / 20000; |
|
1205 aTLCorner.iX = hOverscanPixels; |
|
1206 aBRCorner.iX = ( aBRCorner.iX - hOverscanPixels ); |
|
1207 |
|
1208 // vOverscanPixels = ( ( Height * vOverscan ) + 50 ) / 20000 |
|
1209 // |
|
1210 // vOverscanPixels: |
|
1211 // pixels which are needed to be added to top left Y |
|
1212 // pixels which are needed to be reduced from bottom right Y |
|
1213 // Height: |
|
1214 // Horizontal resolution |
|
1215 // vOverscan: |
|
1216 // Vertical overscan in percents (1% == 100) |
|
1217 // 50: |
|
1218 // Used to round up possible decimals |
|
1219 // 20000: |
|
1220 // Used to get rid of percentage multiplier and to get the overscan value |
|
1221 // for one side |
|
1222 TInt vOverscanPixels = ( aBRCorner.iY * iVOverscan + 50 ) / 20000; |
|
1223 aTLCorner.iY = vOverscanPixels; |
|
1224 aBRCorner.iY = ( aBRCorner.iY - vOverscanPixels ); |
|
1225 } |
|
1226 } |
|
1227 |
|
1228 //------------------------------------------------------------------------------ |
|
1229 // CalculateOverscan |
|
1230 //------------------------------------------------------------------------------ |
|
1231 // |
|
1232 void CEDIDHandler::UpdateOverscanValues() |
|
1233 { |
|
1234 FUNC_LOG; |
|
1235 |
|
1236 // Overscan from cenrep |
|
1237 TInt hOverscan = 0; |
|
1238 TInt vOverscan = 0; |
|
1239 CRepository* cenRep = NULL; |
|
1240 TInt err = KErrNone; |
|
1241 |
|
1242 TRAP( err, cenRep = CRepository::NewL( KCRUidTvoutSettings ) ); |
|
1243 if( err == KErrNone ) |
|
1244 { |
|
1245 |
|
1246 // Horizontal |
|
1247 err = cenRep->Get( KSettingsTvoutHorizontalOverscan, hOverscan ); |
|
1248 if( err != KErrNone ) |
|
1249 { |
|
1250 hOverscan = 0; |
|
1251 } |
|
1252 |
|
1253 // Vertical |
|
1254 err = cenRep->Get( KSettingsTvoutVerticalOverscan, vOverscan ); |
|
1255 if( err != KErrNone ) |
|
1256 { |
|
1257 vOverscan = 0; |
|
1258 } |
|
1259 |
|
1260 // Cleanup |
|
1261 delete cenRep; |
|
1262 } |
|
1263 |
|
1264 // Update overscan values |
|
1265 iHOverscan = hOverscan; |
|
1266 iVOverscan = vOverscan; |
|
1267 } |
|
1268 |
|
1269 // ---------------------------------------------------------------------------- |
|
1270 // CEDIDHandler::FilterAvailableTvConfigList |
|
1271 // |
|
1272 // ---------------------------------------------------------------------------- |
|
1273 // |
|
1274 TInt CEDIDHandler::FilterAvailableTvConfigList( RArray<THdmiDviTimings>& aHdmiConfigs ) |
|
1275 { |
|
1276 FUNC_LOG; |
|
1277 |
|
1278 TUint supportedCount; |
|
1279 TInt retVal( KErrNotFound ); |
|
1280 TInt availableCount( aHdmiConfigs.Count() ); |
|
1281 RArray<TSupportedHdmiDviMode> supportedModes; |
|
1282 |
|
1283 INFO_1( "HDMI CONFIGS --- From SINK -- Total : %d", availableCount ); |
|
1284 |
|
1285 retVal = iTVOutConfigForHDMI.GetSupportedHdmiModes( supportedModes ); |
|
1286 |
|
1287 if( KErrNone == retVal ) |
|
1288 { |
|
1289 TInt availableIndex = 0; |
|
1290 TBool found( EFalse ); |
|
1291 TBool defaultCEAmode( EFalse ); |
|
1292 supportedCount = supportedModes.Count(); |
|
1293 INFO_1( "HDMI CONFIGS --- From HW -- Total : %d", supportedCount ); |
|
1294 |
|
1295 INFO( "Filtered list -- START" ); |
|
1296 while( availableIndex < availableCount ) |
|
1297 { |
|
1298 found = EFalse; |
|
1299 |
|
1300 for( TInt supportedIndex = 0; (supportedIndex < supportedCount); supportedIndex++ ) |
|
1301 { |
|
1302 // Check CEA mode |
|
1303 if( aHdmiConfigs[ availableIndex ].iCeaMode && |
|
1304 (TSupportedHdmiDviMode::ECea == supportedModes[ supportedIndex ].iStandardModeType) && |
|
1305 (aHdmiConfigs[ availableIndex ].iCeaMode == supportedModes[ supportedIndex ].iStandardMode) ) |
|
1306 { |
|
1307 found = ETrue; |
|
1308 if( aHdmiConfigs[ availableIndex].iCeaMode == KDefaultCEAMode ) |
|
1309 { |
|
1310 defaultCEAmode = ETrue; |
|
1311 } |
|
1312 TRACE_TIMINGS( (aHdmiConfigs[ availableIndex ]) ); |
|
1313 break; |
|
1314 } |
|
1315 |
|
1316 // Check DMT mode |
|
1317 if( aHdmiConfigs[ availableIndex ].iDmtMode && |
|
1318 (TSupportedHdmiDviMode::EDmt == supportedModes[ supportedIndex ].iStandardModeType) && |
|
1319 (aHdmiConfigs[ availableIndex ].iDmtMode == supportedModes[ supportedIndex ].iStandardMode) ) |
|
1320 { |
|
1321 found = ETrue; |
|
1322 TRACE_TIMINGS( (aHdmiConfigs[ availableIndex ]) ); |
|
1323 break; |
|
1324 } |
|
1325 } |
|
1326 |
|
1327 if( EFalse == found ) |
|
1328 { |
|
1329 // Remove from the list |
|
1330 aHdmiConfigs.Remove( availableIndex ); |
|
1331 availableCount--; |
|
1332 continue; |
|
1333 } |
|
1334 |
|
1335 availableIndex++; |
|
1336 } |
|
1337 |
|
1338 if( ( (KDefaultCEAModePhysImgAspRatioNr == iEdidParserPtr->GetAspectRatioLandscape()) |
|
1339 && (KDefaultCEAModePhysImgAspRatioDr == iEdidParserPtr->GetAspectRatioPortrait()) ) |
|
1340 && !defaultCEAmode ) |
|
1341 |
|
1342 { |
|
1343 THdmiDviTimings timings; |
|
1344 |
|
1345 // Get a timing item for default CEA Mode (1) |
|
1346 const TTimingItem* item = TimingByIndex( KDefaultCEAModeIndex, ETimingModeCEA ); |
|
1347 if( item ) |
|
1348 { |
|
1349 Mem::FillZ( ( TAny* )&timings, sizeof( timings ) ); |
|
1350 FillHdmiDviTimings( *item, timings ); |
|
1351 retVal = aHdmiConfigs.Append( timings ); |
|
1352 ERROR( retVal, "Failed to append CEA timing in available config array" ); |
|
1353 } |
|
1354 } |
|
1355 |
|
1356 INFO( "Filtered list -- END" ); |
|
1357 supportedModes.Close(); |
|
1358 } |
|
1359 |
|
1360 return retVal; |
|
1361 } |
|
1362 |
|
1363 //------------------------------------------------------------------------------ |
|
1364 // C++ constructor |
|
1365 //------------------------------------------------------------------------------ |
|
1366 // |
|
1367 CEDIDHandler::CEDIDHandler( MFSMForBody& aFSM, |
|
1368 CTVOutConfigForHDMI& aTVOutConfigForHDMI ) : |
|
1369 CActive( CActive::EPriorityLow ), |
|
1370 iFSM( aFSM ), |
|
1371 iTVOutConfigForHDMI( aTVOutConfigForHDMI ), |
|
1372 iRetryCounter( 0 ), |
|
1373 iRequestID( EUndefRequest ) |
|
1374 { |
|
1375 FUNC_LOG; |
|
1376 } |
|
1377 |
|
1378 //------------------------------------------------------------------------------ |
|
1379 // ConstructL |
|
1380 //------------------------------------------------------------------------------ |
|
1381 // |
|
1382 void CEDIDHandler::ConstructL() |
|
1383 { |
|
1384 FUNC_LOG; |
|
1385 |
|
1386 INFO( "Creating Retry Timer object" ); |
|
1387 User::LeaveIfError(iRetryTimer.CreateLocal()); |
|
1388 |
|
1389 INFO( "Creating CDdcPortAccess object" ); |
|
1390 iDdcPortAccess = CDdcPortAccess::NewL(); |
|
1391 |
|
1392 CActiveScheduler::Add( this ); |
|
1393 } |
|
1394 |
|
1395 // ======== GLOBAL FUNCTIONS ======== |
|
1396 |
|
1397 |