2 #include <linux/wait.h>
3 #include <linux/delay.h>
4 #include <linux/mutex.h>
8 #include <linux/kernel.h>
9 #include <mach/hardware.h>
12 #include <mach/mt_typedefs.h>
14 #include "siHdmiTx_902x_TPI.h"
15 /* #include "SiIIIC.h" */
18 SIHDMITX_CONFIG siHdmiTx
;
22 byte tpivmode
[3]; /* saved TPI Reg0x08/Reg0x09/Reg0x0A values. */
24 bool Sii9024A_HDCP_supported
= true; /* if the chip is 9024A, you can support HDCP by set this variable to 1.If the chip is 9022A, it means noting. */
25 extern HDMI_UTIL_FUNCS hdmi_util
;
28 bool HDCP_Supported
= false;
30 extern void HDMI_reset(void);
31 extern byte
sii9024_i2c_read_byte(byte addr
);
32 extern byte
sii9024_i2c_write_byte(struct i2c_client
*client
, byte addr
, byte data
);
33 extern byte
sii9024_i2c_read_block(struct i2c_client
*client
, byte addr
, byte
*data
, word len
);
34 extern int sii9024_i2c_write_block(struct i2c_client
*client
, byte addr
, byte
*data
, word len
);
36 /* ------------------------------------------------------------------------------ */
37 struct i2c_client
*sii902xA
= NULL
;
38 struct i2c_client
*siiEDID
= NULL
;
39 struct i2c_client
*siiSegEDID
= NULL
;
40 struct i2c_client
*siiHDCP
= NULL
;
42 /* static struct mxc_lcd_platform_data *Sii902xA_plat_data; */
45 /* ------------------------------------------------------------------------------ */
46 /* Function Name: DelayMS() */
47 /* Function Description: Introduce a busy-wait delay equal, in milliseconds, to the input parameter. */
49 /* Accepts: Length of required delay in milliseconds (max. 65535 ms) */
50 /* ------------------------------------------------------------------------------ */
53 msleep(MS
); /* call linux kernel delay API function */
56 /* ------------------------------------------------------------------------------ */
57 /* Function Name: I2CReadBlock */
58 /* Function Description: Reads block of data from HDMI Device */
59 /* ------------------------------------------------------------------------------ */
60 byte
I2CReadBlock(struct i2c_client
*client
, byte RegAddr
, byte NBytes
, byte
*Data
)
63 for (i
= RegAddr
; i
< (NBytes
+ RegAddr
); i
++) {
64 Data
[i
- RegAddr
] = i2c_smbus_read_byte_data(client
, i
);
69 static s32
i2c_smbus_write_byte_nostop(struct i2c_client
*client
, unsigned char value
)
71 unsigned short old_flag
= client
->addr
;
73 client
->addr
= client
->addr
& I2C_RS_FLAG
;
74 i2c_smbus_write_byte(client
, value
);
75 client
->addr
= old_flag
;
80 byte
siiReadSegmentBlockEDID(struct i2c_client
*client
, byte Segment
, byte Offset
, byte
*Buffer
,
84 i2c_smbus_write_byte_nostop(siiSegEDID
, Segment
);
85 rc
= I2CReadBlock(client
, Offset
, Length
, Buffer
);
91 /* ------------------------------------------------------------------------------ */
92 /* Function Name: ReadByteTPI() */
93 /* Function Description: I2C read */
94 /* ------------------------------------------------------------------------------ */
95 byte
ReadByteTPI(byte RegOffset
)
98 Readnum
= i2c_smbus_read_byte_data(sii902xA
, RegOffset
);
99 TPI_DEBUG_PRINT(("[9024]read RegOffset=0x%x,Readnum=0x%x\n", RegOffset
, Readnum
));
103 /* ------------------------------------------------------------------------------ */
104 /* Function Name: WriteByteTPI() */
105 /* Function Description: I2C write */
106 /* ------------------------------------------------------------------------------ */
107 void WriteByteTPI(byte RegOffset
, byte Data
)
109 /* sii9024_i2c_write_byte(sii902xA,RegOffset, Data); */
110 i2c_smbus_write_byte_data(sii902xA
, RegOffset
, Data
);
112 TPI_DEBUG_PRINT(("[9024]write RegOffset=0x%x,Data=0x%x\n", RegOffset
, Data
));
116 void ReadSetWriteTPI(byte Offset
, byte Pattern
)
120 Tmp
= ReadByteTPI(Offset
);
123 WriteByteTPI(Offset
, Tmp
);
126 /* ------------------------------------------------------------------------------ */
127 /* Function Name: ReadSetWriteTPI() */
128 /* Function Description: Write "0" to all bits in TPI offset "Offset" that are set */
129 /* to "1" in "Pattern"; Leave all other bits in "Offset" */
131 /* ------------------------------------------------------------------------------ */
132 void ReadClearWriteTPI(byte Offset
, byte Pattern
)
136 Tmp
= ReadByteTPI(Offset
);
139 WriteByteTPI(Offset
, Tmp
);
142 /* ------------------------------------------------------------------------------ */
143 /* Function Name: ReadSetWriteTPI() */
144 /* Function Description: Write "Value" to all bits in TPI offset "Offset" that are set */
145 /* to "1" in "Mask"; Leave all other bits in "Offset" */
147 /* ------------------------------------------------------------------------------ */
148 void ReadModifyWriteTPI(byte Offset
, byte Mask
, byte Value
)
152 Tmp
= ReadByteTPI(Offset
);
154 Tmp
|= (Value
& Mask
);
155 WriteByteTPI(Offset
, Tmp
);
158 void ReadBlockTPI(byte TPI_Offset
, word NBytes
, byte
*pData
)
161 for (i
= TPI_Offset
; i
< (NBytes
+ TPI_Offset
); i
++) {
162 pData
[i
- TPI_Offset
] = i2c_smbus_read_byte_data(sii902xA
, i
);
163 /* pr_debug("[9024]RegOffset=i=0x%x,pData[i-TPI_Offset]=0x%x\n", i, pData[i-TPI_Offset]); */
169 void WriteBlockTPI(byte TPI_Offset
, word NBytes
, byte
*pData
)
172 for (i
= TPI_Offset
; i
< (NBytes
+ TPI_Offset
); i
++) {
174 i2c_smbus_write_byte_data(sii902xA
, i
, pData
[i
- TPI_Offset
]);
175 /* pr_debug("[9024]RegOffset=0x%x,pData[i-TPI_Offset]=0x%x\n", i, pData[i-TPI_Offset]); */
180 byte
ReadIndexedRegister(byte PageNum
, byte RegOffset
)
182 WriteByteTPI(0xBC, PageNum
); /* Internal page */
183 WriteByteTPI(0xBD, RegOffset
); /* Indexed register */
184 return ReadByteTPI(0xBE); /* Return read value */
187 /* ------------------------------------------------------------------------------ */
188 /* Function Name: WriteIndexedRegister() */
189 /* Function Description: Write a value to an indexed register */
192 /* 1. 0xBC => Internal page num */
193 /* 2. 0xBD => Indexed register offset */
194 /* 3. 0xBE => Set the indexed register value */
195 /* ------------------------------------------------------------------------------ */
196 void WriteIndexedRegister(byte PageNum
, byte RegOffset
, byte RegValue
)
198 WriteByteTPI(0xBC, PageNum
); /* Internal page */
199 WriteByteTPI(0xBD, RegOffset
); /* Indexed register */
200 WriteByteTPI(0xBE, RegValue
); /* Read value into buffer */
203 /* ------------------------------------------------------------------------------ */
204 /* Function Name: ReadModifyWriteIndexedRegister() */
205 /* Function Description: Write "Value" to all bits in TPI offset "Offset" that are set */
206 /* to "1" in "Mask"; Leave all other bits in "Offset" */
208 /* ------------------------------------------------------------------------------ */
209 void ReadModifyWriteIndexedRegister(byte PageNum
, byte RegOffset
, byte Mask
, byte Value
)
212 WriteByteTPI(0xBC, PageNum
);
213 WriteByteTPI(0xBD, RegOffset
);
214 Tmp
= ReadByteTPI(0xBE);
217 Tmp
|= (Value
& Mask
);
219 WriteByteTPI(0xBE, Tmp
);
222 /* ------------------------------------------------------------------------------ */
223 void TXHAL_InitPostReset(void)
225 /* Set terminations to default. */
226 WriteByteTPI(0x82, 0x25);
227 /* HW debounce to 64ms (0x14) */
228 WriteByteTPI(0x7C, 0x14);
231 /* ------------------------------------------------------------------------------ */
232 /* Function Name: TxHW_Reset() */
233 /* Function Description: Hardware reset Tx */
234 /* ------------------------------------------------------------------------------ */
236 void TxHW_Reset(void)
238 TPI_TRACE_PRINT((">>TxHW_Reset()\n"));
241 TXHAL_InitPostReset();
244 /* ------------------------------------------------------------------------------ */
245 /* Function Name: InitializeStateVariables() */
246 /* Function Description: Initialize system state variables */
247 /* ------------------------------------------------------------------------------ */
248 void InitializeStateVariables(void)
250 g_sys
.tmdsPoweredUp
= FALSE
;
251 g_sys
.hdmiCableConnected
= FALSE
;
252 g_sys
.dsRxPoweredUp
= FALSE
;
254 #ifdef DEV_SUPPORT_EDID
255 g_edid
.edidDataValid
= FALSE
;
256 g_edid
.HDMI_compatible_VSDB
= FALSE
;
260 /* ------------------------------------------------------------------------------ */
261 /* Function Name: EnableTMDS() */
262 /* Function Description: Enable TMDS */
263 /* ------------------------------------------------------------------------------ */
264 void EnableTMDS(void)
266 TPI_DEBUG_PRINT(("TMDS -> Enabled\n"));
267 ReadModifyWriteTPI(0x1A, TMDS_OUTPUT_CONTROL_MASK
, TMDS_OUTPUT_CONTROL_ACTIVE
);
268 WriteByteTPI(0x08, tpivmode
[0]); /* Write register 0x08 */
269 g_sys
.tmdsPoweredUp
= TRUE
;
272 /* ------------------------------------------------------------------------------ */
273 /* Function Name: DisableTMDS() */
274 /* Function Description: Disable TMDS */
275 /* ------------------------------------------------------------------------------ */
276 void DisableTMDS(void)
278 TPI_DEBUG_PRINT(("TMDS -> Disabled\n"));
279 ReadModifyWriteTPI(0x1A, TMDS_OUTPUT_CONTROL_MASK
| AV_MUTE_MASK
,
280 TMDS_OUTPUT_CONTROL_POWER_DOWN
| AV_MUTE_MUTED
);
281 g_sys
.tmdsPoweredUp
= FALSE
;
284 /* ------------------------------------------------------------------------------ */
285 /* Function Name: EnableInterrupts() */
286 /* Function Description: Enable the interrupts specified in the input parameter */
288 /* Accepts: A bit pattern with "1" for each interrupt that needs to be */
289 /* set in the Interrupt Enable Register (TPI offset 0x3C) */
292 /* ------------------------------------------------------------------------------ */
293 byte
EnableInterrupts(byte Interrupt_Pattern
)
295 TPI_TRACE_PRINT((">>EnableInterrupts()\n"));
296 ReadSetWriteTPI(0x3C, Interrupt_Pattern
);
300 /* ------------------------------------------------------------------------------ */
301 /* Function Name: DisableInterrupts() */
302 /* Function Description: Disable the interrupts specified in the input parameter */
304 /* Accepts: A bit pattern with "1" for each interrupt that needs to be */
305 /* cleared in the Interrupt Enable Register (TPI offset 0x3C) */
308 /* ------------------------------------------------------------------------------ */
309 byte
DisableInterrupts(byte Interrupt_Pattern
)
311 TPI_TRACE_PRINT((">>DisableInterrupts()\n"));
312 ReadClearWriteTPI(0x3C, Interrupt_Pattern
);
319 #ifdef DEV_SUPPORT_EDID
320 static u8 g_CommData
[EDID_BLOCK_SIZE
];
322 #define ReadBlockEDID(a, b, c) I2CReadBlock(siiEDID, a, b, c)
323 #define ReadSegmentBlockEDID(a, b, c, d) siiReadSegmentBlockEDID(siiEDID, a, b, d, c)
325 /* ------------------------------------------------------------------------------ */
326 /* Function Name: GetDDC_Access() */
327 /* Function Description: Request access to DDC bus from the receiver */
330 /* Returns: TRUE or FLASE */
332 /* ------------------------------------------------------------------------------ */
333 #define T_DDC_ACCESS 50
335 byte
GetDDC_Access(byte
*SysCtrlRegVal
)
338 byte DDCReqTimeout
= T_DDC_ACCESS
;
339 byte TPI_ControlImage
;
341 TPI_TRACE_PRINT((">>GetDDC_Access()\n"));
343 sysCtrl
= ReadByteTPI(0x1A); /* Read and store original value. Will be passed into ReleaseDDC() */
344 *SysCtrlRegVal
= sysCtrl
;
346 sysCtrl
|= DDC_BUS_REQUEST_REQUESTED
;
347 WriteByteTPI(0x1A, sysCtrl
);
349 while (DDCReqTimeout
--) /* Loop till 0x1A[1] reads "1" */
351 TPI_ControlImage
= ReadByteTPI(0x1A);
353 if (TPI_ControlImage
& DDC_BUS_GRANT_MASK
) /* When 0x1A[1] reads "1" */
355 sysCtrl
|= DDC_BUS_GRANT_GRANTED
;
356 WriteByteTPI(0x1A, sysCtrl
); /* lock host DDC bus access (0x1A[2:1] = 11) */
359 WriteByteTPI(0x1A, sysCtrl
); /* 0x1A[2] = "1" - Requst the DDC bus */
363 WriteByteTPI(0x1A, sysCtrl
); /* Failure... restore original value. */
367 /* ------------------------------------------------------------------------------ */
368 /* Function Name: ReleaseDDC() */
369 /* Function Description: Release DDC bus */
372 /* Returns: TRUE if bus released successfully. FALSE if failed. */
374 /* ------------------------------------------------------------------------------ */
375 byte
ReleaseDDC(byte SysCtrlRegVal
)
377 byte DDCReqTimeout
= T_DDC_ACCESS
;
378 byte TPI_ControlImage
;
380 TPI_TRACE_PRINT((">>ReleaseDDC()\n"));
382 SysCtrlRegVal
&= ~BITS_2_1
; /* Just to be sure bits [2:1] are 0 before it is written */
384 while (DDCReqTimeout
--) /* Loop till 0x1A[1] reads "0" */
386 /* Cannot use ReadClearWriteTPI() here. A read of TPI_SYSTEM_CONTROL is invalid while DDC is granted. */
387 /* Doing so will return 0xFF, and cause an invalid value to be written back. */
388 /* ReadClearWriteTPI(TPI_SYSTEM_CONTROL,BITS_2_1); // 0x1A[2:1] = "0" - release the DDC bus */
390 WriteByteTPI(0x1A, SysCtrlRegVal
);
391 TPI_ControlImage
= ReadByteTPI(0x1A);
393 if (!(TPI_ControlImage
& BITS_2_1
)) /* When 0x1A[2:1] read "0" */
397 return FALSE
; /* Failed to release DDC bus control */
400 /* ------------------------------------------------------------------------------ */
401 /* Function Name: CheckEDID_Header() */
402 /* Function Description: Checks if EDID header is correct per VESA E-EDID standard */
404 /* Accepts: Pointer to 1st EDID block */
405 /* Returns: TRUE or FLASE */
406 /* Globals: EDID data */
407 /* ------------------------------------------------------------------------------ */
408 byte
CheckEDID_Header(byte
*Block
)
412 if (Block
[i
]) /* byte 0 must be 0 */
415 for (i
= 1; i
< 1 + EDID_HDR_NO_OF_FF
; i
++) {
416 if (Block
[i
] != 0xFF) /* bytes [1..6] must be 0xFF */
420 if (Block
[i
]) /* byte 7 must be 0 */
426 /* ------------------------------------------------------------------------------ */
427 /* Function Name: DoEDID_Checksum() */
428 /* Function Description: Calculte checksum of the 128 byte block pointed to by the */
429 /* pointer passed as parameter */
431 /* Accepts: Pointer to a 128 byte block whose checksum needs to be calculated */
432 /* Returns: TRUE or FLASE */
433 /* Globals: EDID data */
434 /* ------------------------------------------------------------------------------ */
435 byte
DoEDID_Checksum(byte
*Block
)
440 for (i
= 0; i
< EDID_BLOCK_SIZE
; i
++)
441 CheckSum
+= Block
[i
];
449 /* ------------------------------------------------------------------------------ */
450 /* Function Name: ParseEstablishedTiming() */
451 /* Function Description: Parse the established timing section of EDID Block 0 and */
452 /* print their decoded meaning to the screen. */
454 /* Accepts: Pointer to the 128 byte array where the data read from EDID Block0 is stored. */
456 /* Globals: EDID data */
457 /* ------------------------------------------------------------------------------ */
458 #if (CONF__TPI_EDID_PRINT == ENABLE)
459 void ParseEstablishedTiming(byte
*Data
)
461 TPI_EDID_PRINT(("Parsing Established Timing:\n"));
462 TPI_EDID_PRINT(("===========================\n"));
464 /* Parse Established Timing Byte #0 */
465 if (Data
[ESTABLISHED_TIMING_INDEX
] & BIT_7
)
466 TPI_EDID_PRINT(("720 x 400 @ 70Hz\n"));
467 if (Data
[ESTABLISHED_TIMING_INDEX
] & BIT_6
)
468 TPI_EDID_PRINT(("720 x 400 @ 88Hz\n"));
469 if (Data
[ESTABLISHED_TIMING_INDEX
] & BIT_5
)
470 TPI_EDID_PRINT(("640 x 480 @ 60Hz\n"));
471 if (Data
[ESTABLISHED_TIMING_INDEX
] & BIT_4
)
472 TPI_EDID_PRINT(("640 x 480 @ 67Hz\n"));
473 if (Data
[ESTABLISHED_TIMING_INDEX
] & BIT_3
)
474 TPI_EDID_PRINT(("640 x 480 @ 72Hz\n"));
475 if (Data
[ESTABLISHED_TIMING_INDEX
] & BIT_2
)
476 TPI_EDID_PRINT(("640 x 480 @ 75Hz\n"));
477 if (Data
[ESTABLISHED_TIMING_INDEX
] & BIT_1
)
478 TPI_EDID_PRINT(("800 x 600 @ 56Hz\n"));
479 if (Data
[ESTABLISHED_TIMING_INDEX
] & BIT_0
)
480 TPI_EDID_PRINT(("800 x 400 @ 60Hz\n"));
482 /* Parse Established Timing Byte #1: */
483 if (Data
[ESTABLISHED_TIMING_INDEX
+ 1] & BIT_7
)
484 TPI_EDID_PRINT(("800 x 600 @ 72Hz\n"));
485 if (Data
[ESTABLISHED_TIMING_INDEX
+ 1] & BIT_6
)
486 TPI_EDID_PRINT(("800 x 600 @ 75Hz\n"));
487 if (Data
[ESTABLISHED_TIMING_INDEX
+ 1] & BIT_5
)
488 TPI_EDID_PRINT(("832 x 624 @ 75Hz\n"));
489 if (Data
[ESTABLISHED_TIMING_INDEX
+ 1] & BIT_4
)
490 TPI_EDID_PRINT(("1024 x 768 @ 87Hz\n"));
491 if (Data
[ESTABLISHED_TIMING_INDEX
+ 1] & BIT_3
)
492 TPI_EDID_PRINT(("1024 x 768 @ 60Hz\n"));
493 if (Data
[ESTABLISHED_TIMING_INDEX
+ 1] & BIT_2
)
494 TPI_EDID_PRINT(("1024 x 768 @ 70Hz\n"));
495 if (Data
[ESTABLISHED_TIMING_INDEX
+ 1] & BIT_1
)
496 TPI_EDID_PRINT(("1024 x 768 @ 75Hz\n"));
497 if (Data
[ESTABLISHED_TIMING_INDEX
+ 1] & BIT_0
)
498 TPI_EDID_PRINT(("1280 x 1024 @ 75Hz\n"));
500 /* Parse Established Timing Byte #2: */
501 if (Data
[ESTABLISHED_TIMING_INDEX
+ 2] & 0x80)
502 TPI_EDID_PRINT(("1152 x 870 @ 75Hz\n"));
504 if ((!Data
[0]) && (!Data
[ESTABLISHED_TIMING_INDEX
+ 1]) && (!Data
[2]))
505 TPI_EDID_PRINT(("No established video modes\n"));
508 /* ------------------------------------------------------------------------------ */
509 /* Function Name: ParseStandardTiming() */
510 /* Function Description: Parse the standard timing section of EDID Block 0 and */
511 /* print their decoded meaning to the screen. */
513 /* Accepts: Pointer to the 128 byte array where the data read from EDID Block0 is stored. */
515 /* Globals: EDID data */
516 /* ------------------------------------------------------------------------------ */
517 void ParseStandardTiming(byte
*Data
)
522 TPI_EDID_PRINT(("Parsing Standard Timing:\n"));
523 TPI_EDID_PRINT(("========================\n"));
525 for (i
= 0; i
< NUM_OF_STANDARD_TIMINGS
; i
+= 2) {
526 if ((Data
[STANDARD_TIMING_OFFSET
+ i
] == 0x01)
527 && ((Data
[STANDARD_TIMING_OFFSET
+ i
+ 1]) == 1)) {
528 TPI_EDID_PRINT(("Standard Timing Undefined\n")); /* per VESA EDID standard, Release A, Revision 1, February 9, 2000, Sec. 3.9 */
530 TPI_EDID_PRINT(("Horizontal Active pixels: %i\n", (int)((Data
[STANDARD_TIMING_OFFSET
+ i
] + 31) * 8))); /* per VESA EDID standard, Release A, Revision 1, February 9, 2000, Table 3.15 */
532 AR_Code
= (Data
[STANDARD_TIMING_OFFSET
+ i
+ 1] & TWO_MSBITS
) >> 6;
533 TPI_EDID_PRINT(("Aspect Ratio: "));
537 TPI_EDID_PRINT(("16:10\n"));
541 TPI_EDID_PRINT(("4:3\n"));
545 TPI_EDID_PRINT(("5:4\n"));
549 TPI_EDID_PRINT(("16:9\n"));
556 /* ------------------------------------------------------------------------------ */
557 /* Function Name: ParseDetailedTiming() */
558 /* Function Description: Parse the detailed timing section of EDID Block 0 and */
559 /* print their decoded meaning to the screen. */
561 /* Accepts: Pointer to the 128 byte array where the data read from EDID Block0 is stored. */
562 /* Offset to the beginning of the Detailed Timing Descriptor data. */
564 /* Block indicator to distinguish between block #0 and blocks #2, #3 */
566 /* Globals: EDID data */
567 /* ------------------------------------------------------------------------------ */
568 byte
ParseDetailedTiming(byte
*Data
, byte DetailedTimingOffset
, byte Block
)
574 TmpWord
= Data
[DetailedTimingOffset
+ PIX_CLK_OFFSET
] +
575 256 * Data
[DetailedTimingOffset
+ PIX_CLK_OFFSET
+ 1];
577 if (TmpWord
== 0x00) /* 18 byte partition is used as either for Monitor Name or for Monitor Range Limits or it is unused */
579 if (Block
== EDID_BLOCK_0
) /* if called from Block #0 and first 2 bytes are 0 => either Monitor Name or for Monitor Range Limits */
581 if (Data
[DetailedTimingOffset
+ 3] == 0xFC) /* these 13 bytes are ASCII coded monitor name */
583 TPI_EDID_PRINT(("Monitor Name: "));
585 for (i
= 0; i
< 13; i
++) {
586 TPI_EDID_PRINT(("%c", Data
[DetailedTimingOffset
+ 5 + i
])); /* Display monitor name on SiIMon */
588 TPI_EDID_PRINT(("\n"));
591 else if (Data
[DetailedTimingOffset
+ 3] == 0xFD) /* these 13 bytes contain Monitor Range limits, binary coded */
593 TPI_EDID_PRINT(("Monitor Range Limits:\n\n"));
596 TPI_EDID_PRINT(("Min Vertical Rate in Hz: %d\n", (int)Data
[DetailedTimingOffset
+ 5 + i
++])); /* */
597 TPI_EDID_PRINT(("Max Vertical Rate in Hz: %d\n", (int)Data
[DetailedTimingOffset
+ 5 + i
++])); /* */
598 TPI_EDID_PRINT(("Min Horizontal Rate in Hz: %d\n", (int)Data
[DetailedTimingOffset
+ 5 + i
++])); /* */
599 TPI_EDID_PRINT(("Max Horizontal Rate in Hz: %d\n", (int)Data
[DetailedTimingOffset
+ 5 + i
++])); /* */
600 TPI_EDID_PRINT(("Max Supported pixel clock rate in MHz/10: %d\n", (int)Data
[DetailedTimingOffset
+ 5 + i
++])); /* */
601 TPI_EDID_PRINT(("Tag for secondary timing formula (00h=not used): %d\n", (int)Data
[DetailedTimingOffset
+ 5 + i
++])); /* */
602 TPI_EDID_PRINT(("Min Vertical Rate in Hz %d\n", (int)Data
[DetailedTimingOffset
+ 5 + i
])); /* */
603 TPI_EDID_PRINT(("\n"));
607 else if (Block
== EDID_BLOCK_2_3
) /* if called from block #2 or #3 and first 2 bytes are 0x00 (padding) then this */
608 { /* descriptor partition is not used and parsing should be stopped */
609 TPI_EDID_PRINT(("No More Detailed descriptors in this block\n"));
610 TPI_EDID_PRINT(("\n"));
615 else /* first 2 bytes are not 0 => this is a detailed timing descriptor from either block */
617 if ((Block
== EDID_BLOCK_0
) && (DetailedTimingOffset
== 0x36)) {
618 TPI_EDID_PRINT(("\n\n\nParse Results, EDID Block #0, Detailed Descriptor Number 1:\n"));
619 TPI_EDID_PRINT(("===========================================================\n\n"));
620 } else if ((Block
== EDID_BLOCK_0
) && (DetailedTimingOffset
== 0x48)) {
621 TPI_EDID_PRINT(("\n\n\nParse Results, EDID Block #0, Detailed Descriptor Number 2:\n"));
622 TPI_EDID_PRINT(("===========================================================\n\n"));
625 TPI_EDID_PRINT(("Pixel Clock (MHz * 100): %d\n", (int)TmpWord
));
627 TmpWord
= Data
[DetailedTimingOffset
+ H_ACTIVE_OFFSET
] +
628 256 * ((Data
[DetailedTimingOffset
+ H_ACTIVE_OFFSET
+ 2] >> 4) & FOUR_LSBITS
);
629 TPI_EDID_PRINT(("Horizontal Active Pixels: %d\n", (int)TmpWord
));
631 TmpWord
= Data
[DetailedTimingOffset
+ H_BLANKING_OFFSET
] +
632 256 * (Data
[DetailedTimingOffset
+ H_BLANKING_OFFSET
+ 1] & FOUR_LSBITS
);
633 TPI_EDID_PRINT(("Horizontal Blanking (Pixels): %d\n", (int)TmpWord
));
635 TmpWord
= (Data
[DetailedTimingOffset
+ V_ACTIVE_OFFSET
]) +
636 256 * ((Data
[DetailedTimingOffset
+ (V_ACTIVE_OFFSET
) + 2] >> 4) & FOUR_LSBITS
);
637 TPI_EDID_PRINT(("Vertical Active (Lines): %d\n", (int)TmpWord
));
639 TmpWord
= Data
[DetailedTimingOffset
+ V_BLANKING_OFFSET
] +
640 256 * (Data
[DetailedTimingOffset
+ V_BLANKING_OFFSET
+ 1] & LOW_NIBBLE
);
641 TPI_EDID_PRINT(("Vertical Blanking (Lines): %d\n", (int)TmpWord
));
643 TmpWord
= Data
[DetailedTimingOffset
+ H_SYNC_OFFSET
] +
644 256 * ((Data
[DetailedTimingOffset
+ (H_SYNC_OFFSET
+ 3)] >> 6) & TWO_LSBITS
);
645 TPI_EDID_PRINT(("Horizontal Sync Offset (Pixels): %d\n", (int)TmpWord
));
647 TmpWord
= Data
[DetailedTimingOffset
+ H_SYNC_PW_OFFSET
] +
648 256 * ((Data
[DetailedTimingOffset
+ (H_SYNC_PW_OFFSET
+ 2)] >> 4) & TWO_LSBITS
);
649 TPI_EDID_PRINT(("Horizontal Sync Pulse Width (Pixels): %d\n", (int)TmpWord
));
651 TmpWord
= (Data
[DetailedTimingOffset
+ V_SYNC_OFFSET
] >> 4) & FOUR_LSBITS
+
652 256 * ((Data
[DetailedTimingOffset
+ (V_SYNC_OFFSET
+ 1)] >> 2) & TWO_LSBITS
);
653 TPI_EDID_PRINT(("Vertical Sync Offset (Lines): %d\n", (int)TmpWord
));
655 TmpWord
= (Data
[DetailedTimingOffset
+ V_SYNC_PW_OFFSET
]) & FOUR_LSBITS
+
656 256 * (Data
[DetailedTimingOffset
+ (V_SYNC_PW_OFFSET
+ 1)] & TWO_LSBITS
);
657 TPI_EDID_PRINT(("Vertical Sync Pulse Width (Lines): %d\n", (int)TmpWord
));
659 TmpWord
= Data
[DetailedTimingOffset
+ H_IMAGE_SIZE_OFFSET
] +
661 (((Data
[DetailedTimingOffset
+ (H_IMAGE_SIZE_OFFSET
+ 2)]) >> 4) & FOUR_LSBITS
);
662 TPI_EDID_PRINT(("Horizontal Image Size (mm): %d\n", (int)TmpWord
));
664 TmpWord
= Data
[DetailedTimingOffset
+ V_IMAGE_SIZE_OFFSET
] +
665 256 * (Data
[DetailedTimingOffset
+ (V_IMAGE_SIZE_OFFSET
+ 1)] & FOUR_LSBITS
);
666 TPI_EDID_PRINT(("Vertical Image Size (mm): %d\n", (int)TmpWord
));
668 TmpByte
= Data
[DetailedTimingOffset
+ H_BORDER_OFFSET
];
669 TPI_EDID_PRINT(("Horizontal Border (Pixels): %d\n", (int)TmpByte
));
671 TmpByte
= Data
[DetailedTimingOffset
+ V_BORDER_OFFSET
];
672 TPI_EDID_PRINT(("Vertical Border (Lines): %d\n", (int)TmpByte
));
674 TmpByte
= Data
[DetailedTimingOffset
+ FLAGS_OFFSET
];
676 TPI_EDID_PRINT(("\n"));
681 /* ------------------------------------------------------------------------------ */
682 /* Function Name: ParseBlock_0_TimingDescriptors() */
683 /* Function Description: Parse EDID Block 0 timing descriptors per EEDID 1.3 */
684 /* standard. printf() values to screen. */
686 /* Accepts: Pointer to the 128 byte array where the data read from EDID Block0 is stored. */
688 /* Globals: EDID data */
689 /* ------------------------------------------------------------------------------ */
690 void ParseBlock_0_TimingDescriptors(byte
*Data
)
695 ParseEstablishedTiming(Data
);
696 ParseStandardTiming(Data
);
698 for (i
= 0; i
< NUM_OF_DETAILED_DESCRIPTORS
; i
++) {
699 Offset
= DETAILED_TIMING_OFFSET
+ (LONG_DESCR_LEN
* i
);
700 ParseDetailedTiming(Data
, Offset
, EDID_BLOCK_0
);
705 /* ------------------------------------------------------------------------------ */
706 /* Function Name: ParseEDID() */
707 /* Function Description: Extract sink properties from its EDID file and save them in */
708 /* global structure g_edid. */
711 /* Returns: TRUE or FLASE */
712 /* Globals: EDID data */
713 /* NOTE: Fields that are not supported by the 9022/4 (such as deep color) were not parsed. */
714 /* ------------------------------------------------------------------------------ */
715 byte
ParseEDID(byte
*pEdid
, byte
*numExt
)
719 TPI_EDID_PRINT(("\n"));
720 TPI_EDID_PRINT(("EDID DATA (Segment = 0 Block = 0 Offset = %d):\n",
721 (int)EDID_BLOCK_0_OFFSET
));
723 for (j
= 0, i
= 0; j
< 128; j
++) {
725 TPI_EDID_PRINT(("%2.2X ", (int)k
));
729 TPI_EDID_PRINT(("\n"));
733 TPI_EDID_PRINT(("\n"));
735 if (!CheckEDID_Header(pEdid
)) /* Checks if EDID header is correct per VESA E-EDID standard(/byte 0 must be 0, bytes [1..6] must be 0xFF,byte 7 must be 0) */
737 /* first 8 bytes of EDID must be {0, FF, FF, FF, FF, FF, FF, 0} */
738 TPI_DEBUG_PRINT(("EDID -> Incorrect Header\n"));
739 return EDID_INCORRECT_HEADER
;
742 if (!DoEDID_Checksum(pEdid
)) {
743 /* non-zero EDID checksum */
744 TPI_DEBUG_PRINT(("EDID -> Checksum Error\n"));
745 return EDID_CHECKSUM_ERROR
;
747 #if (CONF__TPI_EDID_PRINT == ENABLE)
748 ParseBlock_0_TimingDescriptors(pEdid
); /* Parse EDID Block #0 Desctiptors */
751 *numExt
= pEdid
[NUM_OF_EXTEN_ADDR
]; /* read # of extensions from offset 0x7E of block 0 */
752 TPI_EDID_PRINT(("EDID -> 861 Extensions = %d\n", (int)*numExt
));
755 /* No extensions to worry about */
756 return EDID_NO_861_EXTENSIONS
;
758 /* return Parse861Extensions(NumOfExtensions); // Parse 861 Extensions (short and long descriptors); */
762 /* ------------------------------------------------------------------------------ */
763 /* Function Name: Parse861ShortDescriptors() */
764 /* Function Description: Parse CEA-861 extension short descriptors of the EDID block */
765 /* passed as a parameter and save them in global structure g_edid. */
767 /* Accepts: A pointer to the EDID 861 Extension block being parsed. */
768 /* Returns: EDID_PARSED_OK if EDID parsed correctly. Error code if failed. */
769 /* Globals: EDID data */
770 /* NOTE: Fields that are not supported by the 9022/4 (such as deep color) were not parsed. */
771 /* ------------------------------------------------------------------------------ */
772 byte
Parse861ShortDescriptors(byte
*Data
)
774 byte LongDescriptorOffset
;
775 byte DataBlockLength
;
776 byte DataIndex
,DataIndexbk
;
777 byte ExtendedTagCode
;
778 byte VSDB_BaseOffset
= 0;
780 byte V_DescriptorIndex
= 0; /* static to support more than one extension */
781 byte A_DescriptorIndex
= 0; /* static to support more than one extension */
788 if (Data
[EDID_TAG_ADDR
] != EDID_EXTENSION_TAG
) {
789 TPI_EDID_PRINT(("EDID -> Extension Tag Error\n"));
790 return EDID_EXT_TAG_ERROR
;
793 if (Data
[EDID_REV_ADDR
] != EDID_REV_THREE
) {
794 TPI_EDID_PRINT(("EDID -> Revision Error\n"));
795 return EDID_REV_ADDR_ERROR
;
798 LongDescriptorOffset
= Data
[LONG_DESCR_PTR_IDX
]; /* block offset where long descriptors start */
800 g_edid
.UnderScan
= ((Data
[MISC_SUPPORT_IDX
]) >> 7) & LSBIT
; /* byte #3 of CEA extension version 3 */
801 g_edid
.BasicAudio
= ((Data
[MISC_SUPPORT_IDX
]) >> 6) & LSBIT
;
802 /* g_edid.YCbCr_4_4_4 = ((Data[MISC_SUPPORT_IDX]) >> 5) & LSBIT; */
803 /* g_edid.YCbCr_4_2_2 = ((Data[MISC_SUPPORT_IDX]) >> 4) & LSBIT; */
804 g_edid
.YCbCr_4_4_4
= false;
805 g_edid
.YCbCr_4_2_2
= false;
807 DataIndex
= EDID_DATA_START
; /* 4 */
809 while (DataIndex
< LongDescriptorOffset
)
811 DataIndexbk
= DataIndex
;
812 TPI_EDID_PRINT(("Data[0x%x]: 0x%x\n", (int)DataIndex
,(int)Data
[DataIndex
]));
813 TagCode
= (Data
[DataIndex
] >> 5) & THREE_LSBITS
;
814 DataBlockLength
= Data
[DataIndex
++] & FIVE_LSBITS
;
815 TPI_EDID_PRINT(("Data[0x%x]: 0x%x. TagCode=0x%x,DataBlockLengt=0x%x\n", (int)DataIndex
-1,(int)Data
[DataIndex
-1],TagCode
,DataBlockLength
));
816 if ((DataIndex
+ DataBlockLength
) > LongDescriptorOffset
)
818 TPI_EDID_PRINT(("EDID -> V Descriptor Overflow\n"));
819 return EDID_V_DESCR_OVERFLOW
;
822 i
= 0; /* num of short video descriptors in current data block */
826 while ((i
< DataBlockLength
) && (i
< MAX_V_DESCRIPTORS
)) /* each SVD is 1 byte long */
828 g_edid
.VideoDescriptor
[V_DescriptorIndex
++] = Data
[DataIndex
++];
831 DataIndex
+= DataBlockLength
- i
; /* if there are more STDs than MAX_V_DESCRIPTORS, skip the last ones. Update DataIndex */
833 TPI_EDID_PRINT(("EDID -> Short Descriptor Video Block\n"));
837 while (i
< DataBlockLength
/ 3) /* each SAD is 3 bytes long */
840 while (j
< AUDIO_DESCR_SIZE
) /* 3 */
842 g_edid
.AudioDescriptor
[A_DescriptorIndex
][j
++] =
848 TPI_EDID_PRINT(("EDID -> Short Descriptor Audio Block\n"));
851 case SPKR_ALLOC_D_BLOCK
:
852 g_edid
.SpkrAlloc
[i
++] = Data
[DataIndex
++]; /* although 3 bytes are assigned to Speaker Allocation, only */
853 DataIndex
+= 2; /* the first one carries information, so the next two are ignored by this code. */
854 TPI_EDID_PRINT(("EDID -> Short Descriptor Speaker Allocation Block\n"));
857 case USE_EXTENDED_TAG
:
858 ExtendedTagCode
= Data
[DataIndex
++];
860 switch (ExtendedTagCode
) {
861 case VIDEO_CAPABILITY_D_BLOCK
:
862 TPI_EDID_PRINT(("EDID -> Short Descriptor Video Capability Block\n"));
864 /* TO BE ADDED HERE: Save "video capability" parameters in g_edid data structure */
865 /* Need to modify that structure definition */
866 /* In the meantime: just increment DataIndex by 1 */
867 DataIndex
+= 1; /* replace with reading and saving the proper data per CEA-861 sec. 7.5.6 while incrementing DataIndex */
870 case COLORIMETRY_D_BLOCK
:
871 g_edid
.ColorimetrySupportFlags
= Data
[DataIndex
++] & BITS_1_0
;
872 g_edid
.MetadataProfile
= Data
[DataIndex
++] & BITS_2_1_0
;
874 TPI_EDID_PRINT(("EDID -> Short Descriptor Colorimetry Block\n"));
877 DataIndex
= DataIndexbk
+ DataBlockLength
+1;
880 case VENDOR_SPEC_D_BLOCK
:
881 VSDB_BaseOffset
= DataIndex
- 1;
883 if ((Data
[DataIndex
++] == 0x03) && // check if sink is HDMI compatible
884 (Data
[DataIndex
++] == 0x0C) &&
885 (Data
[DataIndex
++] == 0x00)){
886 g_edid
.HDMI_compatible_VSDB
= true;
887 //g_edid.HDMI_Sink = TRUE;
890 //g_edid.HDMI_Sink = FALSE;
894 g_edid
.CEC_A_B
= Data
[DataIndex
++]; /* CEC Physical address */
895 g_edid
.CEC_C_D
= Data
[DataIndex
++];
897 #ifdef DEV_SUPPORT_CEC
898 /* Take the Address that was passed in the EDID and use this API */
899 /* to set the physical address for CEC. */
902 phyAddr
= (word
) g_edid
.CEC_C_D
; /* Low-order nibbles */
903 phyAddr
|= ((word
) g_edid
.CEC_A_B
<< 8); /* Hi-order nibbles */
904 /* Is the new PA different from the current PA? */
905 if (phyAddr
!= SI_CecGetDevicePA()) {
906 /* Yes! So change the PA */
907 SI_CecSetDevicePA(phyAddr
);
912 if ((DataIndex
+ 7) > VSDB_BaseOffset
+ DataBlockLength
) /* Offset of 3D_Present bit in VSDB */
913 g_edid
._3D_Supported
= FALSE
;
914 else if (Data
[DataIndex
+ 7] >> 7)
915 g_edid
._3D_Supported
= TRUE
;
917 g_edid
._3D_Supported
= FALSE
;
918 TPI_EDID_PRINT(("DataIndexbk=0x%x,DataBlockLength=0x%x\n",DataIndexbk
,DataBlockLength
));
920 //DataIndex += DataBlockLength - HDMI_SIGNATURE_LEN - CEC_PHYS_ADDR_LEN; // Point to start of next block
922 DataIndex
= DataIndexbk
+ DataBlockLength
+1;
924 TPI_EDID_PRINT(("DataIndex=0x%x!!!!!!!!!\n",DataIndex
));
925 TPI_EDID_PRINT(("EDID -> Short Descriptor Vendor Block\n"));
926 TPI_EDID_PRINT(("\n"));
930 TPI_EDID_PRINT(("EDID -> Unknown Tag Code\n"));
931 return EDID_UNKNOWN_TAG_CODE
;
933 } /* End, Switch statement */
934 } /* End, while (DataIndex < LongDescriptorOffset) statement */
936 return EDID_SHORT_DESCRIPTORS_OK
;
939 /* ------------------------------------------------------------------------------ */
940 /* Function Name: Parse861LongDescriptors() */
941 /* Function Description: Parse CEA-861 extension long descriptors of the EDID block */
942 /* passed as a parameter and printf() them to the screen. */
944 /* Accepts: A pointer to the EDID block being parsed */
945 /* Returns: An error code if no long descriptors found; EDID_PARSED_OK if descriptors found. */
947 /* ------------------------------------------------------------------------------ */
948 byte
Parse861LongDescriptors(byte
*Data
)
950 byte LongDescriptorsOffset
;
951 byte DescriptorNum
= 1;
953 LongDescriptorsOffset
= Data
[LONG_DESCR_PTR_IDX
]; /* EDID block offset 2 holds the offset */
955 if (!LongDescriptorsOffset
) /* per CEA-861-D, table 27 */
957 TPI_DEBUG_PRINT(("EDID -> No Detailed Descriptors\n"));
958 return EDID_NO_DETAILED_DESCRIPTORS
;
960 /* of the 1st 18-byte descriptor */
961 while (LongDescriptorsOffset
+ LONG_DESCR_LEN
< EDID_BLOCK_SIZE
) {
962 TPI_EDID_PRINT(("Parse Results - CEA-861 Long Descriptor #%d:\n",
963 (int)DescriptorNum
));
964 TPI_EDID_PRINT(("===============================================================\n"));
966 #if (CONF__TPI_EDID_PRINT == ENABLE)
967 if (!ParseDetailedTiming(Data
, LongDescriptorsOffset
, EDID_BLOCK_2_3
))
970 LongDescriptorsOffset
+= LONG_DESCR_LEN
;
974 return EDID_LONG_DESCRIPTORS_OK
;
977 /* ------------------------------------------------------------------------------ */
978 /* Function Name: Parse861Extensions() */
979 /* Function Description: Parse CEA-861 extensions from EDID ROM (EDID blocks beyond */
980 /* block #0). Save short descriptors in global structure */
981 /* g_edid. printf() long descriptors to the screen. */
983 /* Accepts: The number of extensions in the EDID being parsed */
984 /* Returns: EDID_PARSED_OK if EDID parsed correctly. Error code if failed. */
985 /* Globals: EDID data */
986 /* NOTE: Fields that are not supported by the 9022/4 (such as deep color) were not parsed. */
987 /* ------------------------------------------------------------------------------ */
988 byte
Parse861Extensions(byte NumOfExtensions
)
994 /* byte V_DescriptorIndex = 0; */
995 /* byte A_DescriptorIndex = 0; */
1001 g_edid
.HDMI_Sink
= FALSE
;
1002 g_edid
.HDMI_compatible_VSDB
= FALSE
;
1008 if ((Block
% 2) > 0) {
1009 Offset
= EDID_BLOCK_SIZE
;
1012 Segment
= (byte
) (Block
/ 2);
1015 ReadBlockEDID(EDID_BLOCK_1_OFFSET
, EDID_BLOCK_SIZE
, g_CommData
); /* read first 128 bytes of EDID ROM */
1017 ReadSegmentBlockEDID(Segment
, Offset
, EDID_BLOCK_SIZE
, g_CommData
); /* read next 128 bytes of EDID ROM */
1020 TPI_TRACE_PRINT(("\n"));
1021 TPI_TRACE_PRINT(("EDID DATA (Segment = %d Block = %d Offset = %d):\n", (int)Segment
,
1022 (int)Block
, (int)Offset
));
1023 for (j
= 0, i
= 0; j
< 128; j
++) {
1025 TPI_EDID_PRINT(("%2.2X ", (int)k
));
1029 TPI_EDID_PRINT(("\n"));
1033 TPI_EDID_PRINT(("\n"));
1035 if ((NumOfExtensions
> 1) && (Block
== 1)) {
1039 ErrCode
= Parse861ShortDescriptors(g_CommData
);
1040 if (ErrCode
!= EDID_SHORT_DESCRIPTORS_OK
) {
1044 ErrCode
= Parse861LongDescriptors(g_CommData
);
1045 if (ErrCode
!= EDID_LONG_DESCRIPTORS_OK
) {
1049 } while (Block
< NumOfExtensions
);
1054 /* ------------------------------------------------------------------------------ */
1055 /* Function Name: DoEdidRead() */
1056 /* Function Description: EDID processing */
1059 /* Returns: TRUE or FLASE */
1061 /* ------------------------------------------------------------------------------ */
1062 byte
DoEdidRead(void)
1066 byte NumOfExtensions
;
1068 /* If we already have valid EDID data, ship this whole thing */
1069 if (g_edid
.edidDataValid
== FALSE
) {
1070 /* Request access to DDC bus from the receiver */
1071 if (GetDDC_Access(&SysCtrlReg
)) {
1072 ReadBlockEDID(EDID_BLOCK_0_OFFSET
, EDID_BLOCK_SIZE
, g_CommData
); /* read first 128 bytes of EDID ROM */
1073 Result
= ParseEDID(g_CommData
, &NumOfExtensions
);
1074 if (Result
!= EDID_OK
) {
1075 if (Result
== EDID_NO_861_EXTENSIONS
) {
1076 TPI_DEBUG_PRINT(("EDID -> No 861 Extensions\n"));
1077 g_edid
.HDMI_Sink
= FALSE
;
1078 g_edid
.YCbCr_4_4_4
= FALSE
;
1079 g_edid
.YCbCr_4_2_2
= FALSE
;
1080 g_edid
.CEC_A_B
= 0x00;
1081 g_edid
.CEC_C_D
= 0x00;
1083 TPI_DEBUG_PRINT(("EDID -> Parse FAILED\n"));
1084 g_edid
.HDMI_Sink
= TRUE
;
1085 g_edid
.YCbCr_4_4_4
= FALSE
;
1086 g_edid
.YCbCr_4_2_2
= FALSE
;
1087 g_edid
.CEC_A_B
= 0x00;
1088 g_edid
.CEC_C_D
= 0x00;
1091 TPI_DEBUG_PRINT(("EDID -> Parse OK\n"));
1092 Result
= Parse861Extensions(NumOfExtensions
); /* Parse 861 Extensions (short and long descriptors); */
1093 if (Result
!= EDID_OK
) {
1094 TPI_DEBUG_PRINT(("EDID -> Extension Parse FAILED\n"));
1095 g_edid
.HDMI_Sink
= false;/* g_edid.HDMI_Sink = TRUE; */
1096 g_edid
.YCbCr_4_4_4
= FALSE
;
1097 g_edid
.YCbCr_4_2_2
= FALSE
;
1098 g_edid
.CEC_A_B
= 0x00;
1099 g_edid
.CEC_C_D
= 0x00;
1101 if(g_edid
.HDMI_compatible_VSDB
)
1102 g_edid
.HDMI_Sink
= TRUE
;//g_edid.HDMI_Sink = TRUE;
1105 if (!ReleaseDDC(SysCtrlReg
)) /* Host must release DDC bus once it is done reading EDID */
1107 TPI_DEBUG_PRINT(("EDID -> DDC bus release failed\n"));
1108 return EDID_DDC_BUS_RELEASE_FAILURE
;
1111 TPI_DEBUG_PRINT(("EDID -> DDC bus request failed\n"));
1112 g_edid
.HDMI_Sink
= TRUE
;
1113 g_edid
.YCbCr_4_4_4
= FALSE
;
1114 g_edid
.YCbCr_4_2_2
= FALSE
;
1115 g_edid
.CEC_A_B
= 0x00;
1116 g_edid
.CEC_C_D
= 0x00;
1117 return EDID_DDC_BUS_REQ_FAILURE
;
1120 TPI_DEBUG_PRINT(("EDID -> g_edid.HDMI_Sink = %d\n", (int)g_edid
.HDMI_Sink
));
1121 TPI_DEBUG_PRINT(("EDID -> g_edid.YCbCr_4_4_4 = %d\n", (int)g_edid
.YCbCr_4_4_4
));
1122 TPI_DEBUG_PRINT(("EDID -> g_edid.YCbCr_4_2_2 = %d\n", (int)g_edid
.YCbCr_4_2_2
));
1123 TPI_DEBUG_PRINT(("EDID -> g_edid.CEC_A_B = 0x%x\n", (int)g_edid
.CEC_A_B
));
1124 TPI_DEBUG_PRINT(("EDID -> g_edid.CEC_C_D = 0x%x\n", (int)g_edid
.CEC_C_D
));
1126 g_edid
.edidDataValid
= TRUE
;
1134 /* ///////////////////////////////////////////////////////////////////////////// */
1135 /* ///////////////////////////////////////////////////////////////////////////// */
1136 /* /////////////////////*************************/////////////////////////////// */
1137 /* ///////////////////// HDCP /////////////////////////////// */
1138 /* /////////////////////*************************/////////////////////////////// */
1139 /* ///////////////////////////////////////////////////////////////////////////// */
1140 /* ///////////////////////////////////////////////////////////////////////////// */
1141 /* ------------------------------------------------------------------------------ */
1142 /* Function Name: IsHDCP_Supported() */
1143 /* Function Description: Check Tx revision number to find if this Tx supports HDCP */
1144 /* by reading the HDCP revision number from TPI register 0x30. */
1147 /* Returns: TRUE if Tx supports HDCP. FALSE if not. */
1149 /* ------------------------------------------------------------------------------ */
1150 byte
IsHDCP_Supported(void)
1153 byte HDCP_Supported
;
1155 TPI_TRACE_PRINT((">>IsHDCP_Supported()\n"));
1157 HDCP_Supported
= TRUE
;
1159 /* Check Device ID */
1160 HDCP_Rev
= ReadByteTPI(0x30);
1162 if (HDCP_Rev
!= (HDCP_MAJOR_REVISION_VALUE
| HDCP_MINOR_REVISION_VALUE
)) {
1163 HDCP_Supported
= FALSE
;
1165 /* Even if HDCP is supported check for incorrect Device ID // for SiI_9022AYBT_DEVICEID_CHECK */
1166 HDCP_Rev
= ReadByteTPI(0x36);
1167 if (HDCP_Rev
== 0x09) {
1168 HDCP_Rev
= ReadByteTPI(0x37);
1169 if (HDCP_Rev
== 0x00) {
1170 HDCP_Rev
= ReadByteTPI(0x38);
1171 if (HDCP_Rev
== 0x02) {
1172 HDCP_Rev
= ReadByteTPI(0x39);
1173 if (HDCP_Rev
== 0x02) {
1174 HDCP_Rev
= ReadByteTPI(0x3A);
1175 if (HDCP_Rev
== 0x0a) {
1176 HDCP_Supported
= FALSE
;
1177 TPI_TRACE_PRINT((">>sii902xA found, NO HDCP supported\n"));
1183 return HDCP_Supported
;
1186 /* ------------------------------------------------------------------------------ */
1187 /* Function Name: AreAKSV_OK() */
1188 /* Function Description: Check if AKSVs contain 20 '0' and 20 '1' */
1191 /* Returns: TRUE if 20 zeros and 20 ones found in AKSV. FALSE OTHERWISE */
1193 /* ------------------------------------------------------------------------------ */
1194 byte
AreAKSV_OK(void)
1196 byte B_Data
[AKSV_SIZE
];
1200 TPI_TRACE_PRINT((">>AreAKSV_OK()\n"));
1202 ReadBlockTPI(0x36, AKSV_SIZE
, B_Data
);
1204 for (i
= 0; i
< AKSV_SIZE
; i
++) {
1205 for (j
= 0; j
< BYTE_SIZE
; j
++) {
1206 if (B_Data
[i
] & 0x01) {
1212 if (NumOfOnes
!= NUM_OF_ONES_IN_KSV
)
1218 /* ------------------------------------------------------------------------------ */
1219 /* Function Name: HDCP_Off() */
1220 /* Function Description: Switch hdcp off. */
1221 /* ------------------------------------------------------------------------------ */
1224 TPI_TRACE_PRINT((">>HDCP_Off()\n"));
1227 ReadModifyWriteTPI(0x1A, AV_MUTE_MASK
, AV_MUTE_MUTED
);
1228 WriteByteTPI(0x2A, PROTECTION_LEVEL_MIN
);
1230 g_hdcp
.HDCP_Started
= FALSE
;
1231 g_hdcp
.HDCP_LinkProtectionLevel
=
1232 EXTENDED_LINK_PROTECTION_NONE
| LOCAL_LINK_PROTECTION_NONE
;
1235 /* ------------------------------------------------------------------------------ */
1236 /* Function Name: HDCP_On() */
1237 /* Function Description: Switch hdcp on. */
1238 /* ------------------------------------------------------------------------------ */
1241 if (g_hdcp
.HDCP_Override
== FALSE
) {
1242 TPI_DEBUG_PRINT(("HDCP Started\n"));
1244 WriteByteTPI(0x2A, PROTECTION_LEVEL_MAX
);
1246 g_hdcp
.HDCP_Started
= TRUE
;
1248 g_hdcp
.HDCP_Started
= FALSE
;
1252 /* ------------------------------------------------------------------------------ */
1253 /* Function Name: RestartHDCP() */
1254 /* Function Description: Restart HDCP. */
1255 /* ------------------------------------------------------------------------------ */
1256 void RestartHDCP(void)
1258 TPI_DEBUG_PRINT(("HDCP -> Restart\n"));
1265 /* ------------------------------------------------------------------------------ */
1266 /* Function Name: HDCP_Init() */
1267 /* Function Description: Tests Tx and Rx support of HDCP. If found, checks if */
1268 /* and attempts to set the security level accordingly. */
1271 /* Returns: TRUE if HW TPI started successfully. FALSE if failed to. */
1272 /* Globals: HDCP_TxSupports - initialized to FALSE, set to TRUE if supported by this device */
1273 /* HDCP_AksvValid - initialized to FALSE, set to TRUE if valid AKSVs are read from this device */
1274 /* HDCP_Started - initialized to FALSE */
1275 /* HDCP_LinkProtectionLevel - initialized to (EXTENDED_LINK_PROTECTION_NONE | LOCAL_LINK_PROTECTION_NONE) */
1276 /* ------------------------------------------------------------------------------ */
1277 void HDCP_Init(void)
1279 TPI_TRACE_PRINT((">>HDCP_Init()\n"));
1281 g_hdcp
.HDCP_TxSupports
= FALSE
;
1282 g_hdcp
.HDCP_AksvValid
= FALSE
;
1283 g_hdcp
.HDCP_Started
= FALSE
;
1284 g_hdcp
.HDCP_LinkProtectionLevel
=
1285 EXTENDED_LINK_PROTECTION_NONE
| LOCAL_LINK_PROTECTION_NONE
;
1287 /* This is TX-related... need only be done once. */
1288 if (!IsHDCP_Supported()) {
1289 /* The TX does not support HDCP, so authentication will never be attempted. */
1290 /* Video will be shown as soon as TMDS is enabled. */
1291 TPI_DEBUG_PRINT(("HDCP -> TX does not support HDCP\n"));
1294 g_hdcp
.HDCP_TxSupports
= TRUE
;
1296 /* This is TX-related... need only be done once. */
1297 if (!AreAKSV_OK()) {
1298 /* The TX supports HDCP, but does not have valid AKSVs. */
1299 /* Video will not be shown. */
1300 TPI_DEBUG_PRINT(("HDCP -> Illegal AKSV\n"));
1303 g_hdcp
.HDCP_AksvValid
= TRUE
;
1306 /* Enable the KSV Forwarding feature and the KSV FIFO Intererrupt */
1307 ReadModifyWriteTPI(0x2A, KSV_FORWARD_MASK
, KSV_FORWARD_ENABLE
);
1308 ReadModifyWriteTPI(0x3E _EN
, KSV_FIFO_READY_EN_MASK
, KSV_FIFO_READY_ENABLE
);
1311 TPI_DEBUG_PRINT(("HDCP -> Supported by TX, AKSVs valid\n"));
1315 /* ------------------------------------------------------------------------------ */
1316 /* Function Name: IsRepeater() */
1317 /* Function Description: Test if sink is a repeater. */
1320 /* Returns: TRUE if sink is a repeater. FALSE if not. */
1322 /* ------------------------------------------------------------------------------ */
1323 byte
IsRepeater(void)
1327 TPI_TRACE_PRINT((">>IsRepeater()\n"));
1329 RegImage
= ReadByteTPI(0x29);
1331 if (RegImage
& HDCP_REPEATER_MASK
)
1334 return FALSE
; /* not a repeater */
1337 /* ------------------------------------------------------------------------------ */
1338 /* Function Name: ReadBlockHDCP() */
1339 /* Function Description: Read NBytes from offset Addr of the HDCP slave address */
1340 /* into a byte Buffer pointed to by Data */
1342 /* Accepts: HDCP port offset, number of bytes to read and a pointer to the data buffer where */
1343 /* the data read will be saved */
1346 /* ------------------------------------------------------------------------------ */
1347 void ReadBlockHDCP(byte TPI_Offset
, word NBytes
, byte
*pData
)
1349 I2CReadBlock(siiHDCP
, TPI_Offset
, NBytes
, pData
);
1352 /* ------------------------------------------------------------------------------ */
1353 /* Function Name: GetKSV() */
1354 /* Function Description: Collect all downstrean KSV for verification. */
1357 /* Returns: TRUE if KSVs collected successfully. False if not. */
1358 /* Globals: KSV_Array[], The buffer is limited to KSV_ARRAY_SIZE due to the 8051 implementation. */
1359 /* ------------------------------------------------------------------------------ */
1364 byte KSV_Array
[KSV_ARRAY_SIZE
];
1366 TPI_TRACE_PRINT((">>GetKSV()\n"));
1367 ReadBlockHDCP(DDC_BSTATUS_ADDR_L
, 1, &i
);
1368 KeyCount
= (i
& DEVICE_COUNT_MASK
) * 5;
1369 if (KeyCount
!= 0) {
1370 ReadBlockHDCP(DDC_KSV_FIFO_ADDR
, KeyCount
, KSV_Array
);
1379 /* ------------------------------------------------------------------------------ */
1380 /* Function Name: HDCP_CheckStatus() */
1381 /* Function Description: Check HDCP status. */
1383 /* Accepts: InterruptStatus */
1386 /* ------------------------------------------------------------------------------ */
1387 void HDCP_CheckStatus(byte InterruptStatusImage
)
1392 byte NewLinkProtectionLevel
;
1401 if ((g_hdcp
.HDCP_TxSupports
== TRUE
) && (g_hdcp
.HDCP_AksvValid
== TRUE
)) {
1402 if ((g_hdcp
.HDCP_LinkProtectionLevel
==
1403 (EXTENDED_LINK_PROTECTION_NONE
| LOCAL_LINK_PROTECTION_NONE
))
1404 && (g_hdcp
.HDCP_Started
== FALSE
)) {
1405 QueryData
= ReadByteTPI(0x29);
1407 if (QueryData
& PROTECTION_TYPE_MASK
) /* Is HDCP avaialable */
1412 /* Check if Link Status has changed: */
1413 if (InterruptStatusImage
& SECURITY_CHANGE_EVENT
) {
1414 TPI_DEBUG_PRINT(("HDCP -> "));
1416 LinkStatus
= ReadByteTPI(0x29);
1417 LinkStatus
&= LINK_STATUS_MASK
;
1419 ClearInterrupt(SECURITY_CHANGE_EVENT
);
1421 switch (LinkStatus
) {
1422 case LINK_STATUS_NORMAL
:
1423 TPI_DEBUG_PRINT(("Link = Normal\n"));
1426 case LINK_STATUS_LINK_LOST
:
1427 TPI_DEBUG_PRINT(("Link = Lost\n"));
1431 case LINK_STATUS_RENEGOTIATION_REQ
:
1432 TPI_DEBUG_PRINT(("Link = Renegotiation Required\n"));
1437 case LINK_STATUS_LINK_SUSPENDED
:
1438 TPI_DEBUG_PRINT(("Link = Suspended\n"));
1443 /* Check if HDCP state has changed: */
1444 if (InterruptStatusImage
& HDCP_CHANGE_EVENT
) {
1445 RegImage
= ReadByteTPI(0x29);
1447 NewLinkProtectionLevel
=
1448 RegImage
& (EXTENDED_LINK_PROTECTION_MASK
| LOCAL_LINK_PROTECTION_MASK
);
1449 if (NewLinkProtectionLevel
!= g_hdcp
.HDCP_LinkProtectionLevel
) {
1450 TPI_DEBUG_PRINT(("HDCP -> "));
1452 g_hdcp
.HDCP_LinkProtectionLevel
= NewLinkProtectionLevel
;
1454 switch (g_hdcp
.HDCP_LinkProtectionLevel
) {
1455 case (EXTENDED_LINK_PROTECTION_NONE
| LOCAL_LINK_PROTECTION_NONE
):
1456 TPI_DEBUG_PRINT(("Protection = None\n"));
1460 case LOCAL_LINK_PROTECTION_SECURE
:
1462 if (IsHDMI_Sink()) {
1463 ReadModifyWriteTPI(0x26, AUDIO_MUTE_MASK
,
1467 ReadModifyWriteTPI(0x1A, AV_MUTE_MASK
, AV_MUTE_NORMAL
);
1468 TPI_DEBUG_PRINT(("Protection = Local, Video Unmuted\n"));
1471 case (EXTENDED_LINK_PROTECTION_SECURE
| LOCAL_LINK_PROTECTION_SECURE
):
1472 TPI_DEBUG_PRINT(("Protection = Extended\n"));
1475 RiCnt
= ReadIndexedRegister(INDEXED_PAGE_0
, 0x25);
1476 while (RiCnt
> 0x70) /* Frame 112 */
1479 ReadIndexedRegister(INDEXED_PAGE_0
,
1482 ReadModifyWriteTPI(0x1A, 0x06, 0x06);
1484 RiCnt
= ReadByteTPI(0x1A);
1485 ReadModifyWriteTPI(0x1A, 0x08, 0x00);
1491 TPI_DEBUG_PRINT(("Protection = Extended but not Local?\n"));
1497 /* Check if KSV FIFO is ready and forward - Bug# 17892 */
1498 /* If interrupt never goes off: */
1499 /* a) KSV formwarding is not enabled */
1500 /* b) not a repeater */
1501 /* c) a repeater with device count == 0 */
1502 /* and therefore no KSV list to forward */
1503 if ((ReadByteTPI(0x3E) & KSV_FIFO_READY_MASK
) == KSV_FIFO_READY_YES
) {
1504 ReadModifyWriteTPI(0x3E, KSV_FIFO_READY_MASK
, KSV_FIFO_READY_YES
);
1505 TPI_DEBUG_PRINT(("KSV Fwd: KSV FIFO has data...\n"));
1507 /* While !(last byte has been read from KSV FIFO) */
1508 /* if (count = 0) then a byte is not in the KSV FIFO yet, do not read */
1509 /* else read a byte from the KSV FIFO and forward it or keep it for revocation check */
1511 ksv
= ReadByteTPI(0x41);
1512 if (ksv
& KSV_FIFO_COUNT_MASK
) {
1513 TPI_DEBUG_PRINT(("KSV Fwd: KSV FIFO Count = %d, ", (int)(ksv
& KSV_FIFO_COUNT_MASK
)));
1514 ksv
= ReadByteTPI(0x42); /* Forward or store for revocation check */
1515 TPI_DEBUG_PRINT(("Value = %d\n", (int)ksv
));
1517 } while ((ksv
& KSV_FIFO_LAST_MASK
) == KSV_FIFO_LAST_NO
);
1518 TPI_DEBUG_PRINT(("KSV Fwd: Last KSV FIFO forward complete\n"));
1522 ClearInterrupt(HDCP_CHANGE_EVENT
);
1530 /* ///////////////////////////////////////////////////////////////////////////// */
1531 /* ///////////////////////////////////////////////////////////////////////////// */
1532 /* /////////////////////*************************/////////////////////////////// */
1533 /* ///////////////////// AV CONFIG /////////////////////////////// */
1534 /* /////////////////////*************************/////////////////////////////// */
1535 /* ///////////////////////////////////////////////////////////////////////////// */
1536 /* ///////////////////////////////////////////////////////////////////////////// */
1538 /* ------------------------------------------------------------------------------ */
1539 /* Video mode table */
1540 /* ------------------------------------------------------------------------------ */
1547 struct PxlLnTotalType
{
1551 struct HVPositionType
{
1556 struct HVResolutionType
{
1564 struct PxlLnTotalType Total
;
1578 struct Vspace_Vblank
{
1587 /* WARNING! The entries in this enum must remian in the samre order as the PC Codes part */
1588 /* of the VideoModeTable[]. */
1591 PC_640x350_85_08
= 0,
1629 PC_1792x1344_74_997
,
1639 PC_SIZE
/* Must be last */
1642 struct VModeInfoType
{
1643 struct ModeIdType ModeId
;
1646 struct HVPositionType Pos
;
1647 struct HVResolutionType Res
;
1649 struct _656Type _656
;
1651 struct Vspace_Vblank VsVb
;
1655 #define NSM 0 /* No Sub-Mode */
1657 #define DEFAULT_VIDEO_MODE 0 /* 640 x 480p @ 60 VGA */
1659 #define ProgrVNegHNeg 0x00
1660 #define ProgrVNegHPos 0x01
1661 #define ProgrVPosHNeg 0x02
1662 #define ProgrVPosHPos 0x03
1664 #define InterlaceVNegHNeg 0x04
1665 #define InterlaceVPosHNeg 0x05
1666 #define InterlaceVNgeHPos 0x06
1667 #define InterlaceVPosHPos 0x07
1670 #define HDMI_VIC_BASE 43
1671 #define VIC_3D_BASE 47
1675 /* ================================================= */
1676 #define R_4 0 /* 4:3 */
1677 #define R_4or16 1 /* 4:3 or 16:9 */
1678 #define R_16 2 /* 16:9 */
1681 /* These are the VIC codes that we support in a 3D mode */
1683 #define VIC_FOR_480P_60Hz_4X3 2 /* 720p x 480p @60Hz */
1684 #define VIC_FOR_480P_60Hz_16X9 3 /* 720p x 480p @60Hz */
1685 #define VIC_FOR_720P_60Hz 4 /* 1280 x 720p @60Mhz */
1686 #define VIC_FOR_1080i_60Hz 5 /* 1920 x 1080i @60Mhz */
1687 #define VIC_FOR_1080p_60Hz 16 /* 1920 x 1080i @60hz */
1688 #define VIC_FOR_720P_50Hz 19 /* 1280 x 720p @50Mhz */
1689 #define VIC_FOR_1080i_50Hz 20 /* 1920 x 1080i @50Mhz */
1690 #define VIC_FOR_1080p_50Hz 31 /* 1920 x 720p @50Hz */
1691 #define VIC_FOR_1080p_24Hz 32 /* 1920 x 720p @24Hz */
1694 static struct VModeInfoType VModesTable
[] = {
1695 /* =================================================================================================================================================================================================================================== */
1696 /* VIC Refresh type Refresh-Rate Pixel-Totals Position Active Aspect Int Length Hbit Vbit Field Pixel Vact Space/Blank */
1697 /* 1 2 SubM PixClk V/H Position VFreq H V H V H V Ratio Adj H V Top Dly HSync VSync Offset Repl Space1 Space2 Blank1 Blank2 Blank3 3D */
1698 /* =================================================================================================================================================================================================================================== */
1699 {{1, 0, NSM
}, 2517, {ProgrVNegHNeg
, 6000, {800, 525} }, {144, 35}, {640, 480}, R_4
, {0, 96, 2, 33, 48, 16, 10, 0}, 0, {0, 0, 0, 0, 0}, NO_3D_SUPPORT
}, /* 0 - 1. 640 x 480p @ 60 VGA */
1700 {{2, 3, NSM
}, 2700, {ProgrVNegHNeg
, 6000, {858, 525} }, {122, 36}, {720, 480}, R_4or16
, {0, 62, 6, 30, 60, 19, 9, 0}, 0, {0, 0, 0, 0, 0}, NO_3D_SUPPORT
}, /* 1 - 2,3 720 x 480p */
1701 {{4, 0, NSM
}, 7425, {ProgrVPosHPos
, 6000, {1650, 750} }, {260, 25}, {1280, 720}, R_16
, {0, 40, 5, 20, 220, 110, 5, 0}, 0, {0, 0, 0, 0, 0}, NO_3D_SUPPORT
}, /* 2 - 4 1280 x 720p@60Hz */
1702 {{5, 0, NSM
}, 7425, {InterlaceVPosHPos
, 6000, {2200, 562} }, {192, 20}, {1920, 1080}, R_16
, {0, 44, 5, 15, 148, 88, 2, 1100}, 0, {0, 0, 0, 0, 0}, NO_3D_SUPPORT
}, /* 3 - 5 1920 x 1080i */
1703 {{6, 7, NSM
}, 2700, {InterlaceVNegHNeg
, 6000, {1716, 264} }, {119, 18}, {720, 480}, R_4or16
, {3, 62, 3, 15, 114, 17, 5, 429}, 1, {0, 0, 0, 0, 0}, NO_3D_SUPPORT
}, /* 4 - 6,7 1440 x 480i,pix repl */
1704 {{8, 9, 1}, 2700, {ProgrVNegHNeg
, 6000, {1716, 262} }, {119, 18}, {1440, 240}, R_4or16
, {0, 124, 3, 15, 114, 38, 4, 0}, 1, {0, 0, 0, 0, 0}, NO_3D_SUPPORT
}, /* 5 - 8,9(1) 1440 x 240p */
1705 {{8, 9, 2}, 2700, {ProgrVNegHNeg
, 6000, {1716, 263} }, {119, 18}, {1440, 240}, R_4or16
, {0, 124, 3, 15, 114, 38, 4, 0}, 1, {0, 0, 0, 0, 0}, NO_3D_SUPPORT
}, /* 6 - 8,9(2) 1440 x 240p */
1706 {{10, 11, NSM
}, 5400, {InterlaceVNegHNeg
, 6000, {3432, 525} }, {238, 18}, {2880, 480}, R_4or16
, {0, 248, 3, 15, 228, 76, 4, 1716}, 0, {0, 0, 0, 0, 0}, NO_3D_SUPPORT
}, /* 7 - 10,11 2880 x 480i */
1707 {{12, 13, 1}, 5400, {ProgrVNegHNeg
, 6000, {3432, 262} }, {238, 18}, {2880, 240}, R_4or16
, {0, 248, 3, 15, 228, 76, 4, 0}, 1, {0, 0, 0, 0, 0}, NO_3D_SUPPORT
}, /* 8 - 12,13(1) 2880 x 240p */
1708 {{12, 13, 2}, 5400, {ProgrVNegHNeg
, 6000, {3432, 263} }, {238, 18}, {2880, 240}, R_4or16
, {0, 248, 3, 15, 228, 76, 4, 0}, 1, {0, 0, 0, 0, 0}, NO_3D_SUPPORT
}, /* 9 - 12,13(2) 2880 x 240p */
1709 {{14, 15, NSM
}, 5400, {ProgrVNegHNeg
, 6000, {1716, 525} }, {244, 36}, {1440, 480}, R_4or16
, {0, 124, 6, 30, 120, 32, 9, 0}, 0, {0, 0, 0, 0, 0}, NO_3D_SUPPORT
}, /* 10 - 14,15 1440 x 480p */
1710 {{16, 0, NSM
}, 14835, {ProgrVPosHPos
, 6000, {2200, 1125} }, {192, 41}, {1920, 1080}, R_16
, {0, 44, 5, 36, 148, 88, 4, 0}, 0, {0, 0, 0, 0, 0}, NO_3D_SUPPORT
}, /* 11 - 16 1920 x 1080p */
1711 {{17, 18, NSM
}, 2700, {ProgrVNegHNeg
, 5000, {864, 625} }, {132, 44}, {720, 576}, R_4or16
, {0, 64, 5, 39, 68, 12, 5, 0}, 0, {0, 0, 0, 0, 0}, NO_3D_SUPPORT
}, /* 12 - 17,18 720 x 576p */
1712 {{19, 0, NSM
}, 7425, {ProgrVPosHPos
, 5000, {1980, 750} }, {260, 25}, {1280, 720}, R_16
, {0, 40, 5, 20, 220, 440, 5, 0}, 0, {0, 0, 0, 0, 0}, NO_3D_SUPPORT
}, /* 13 - 19 1280 x 720p@50Hz */
1713 {{20, 0, NSM
}, 7425, {InterlaceVPosHPos
, 5000, {2640, 1125} }, {192, 20}, {1920, 1080}, R_16
, {0, 44, 5, 15, 148, 528, 2, 1320}, 0, {0, 0, 0, 0, 0}, NO_3D_SUPPORT
}, /* 14 - 20 1920 x 1080i */
1714 {{21, 22, NSM
}, 2700, {InterlaceVNegHNeg
, 5000, {1728, 625} }, {132, 22}, {720, 576}, R_4
, {3, 63, 3, 19, 138, 24, 2, 432}, 1, {0, 0, 0, 0, 0}, NO_3D_SUPPORT
}, /* 15 - 21,22 1440 x 576i */
1715 {{23, 24, 1}, 2700, {ProgrVNegHNeg
, 5000, {1728, 312} }, {132, 22}, {1440, 288}, R_4or16
, {0, 126, 3, 19, 138, 24, 2, 0}, 1, {0, 0, 0, 0, 0}, NO_3D_SUPPORT
}, /* 16 - 23,24(1) 1440 x 288p */
1716 {{23, 24, 2}, 2700, {ProgrVNegHNeg
, 5000, {1728, 313} }, {132, 22}, {1440, 288}, R_4or16
, {0, 126, 3, 19, 138, 24, 2, 0}, 1, {0, 0, 0, 0, 0}, NO_3D_SUPPORT
}, /* 17 - 23,24(2) 1440 x 288p */
1717 {{23, 24, 3}, 2700, {ProgrVNegHNeg
, 5000, {1728, 314} }, {132, 22}, {1440, 288}, R_4or16
, {0, 126, 3, 19, 138, 24, 2, 0}, 1, {0, 0, 0, 0, 0}, NO_3D_SUPPORT
}, /* 18 - 23,24(3) 1440 x 288p */
1718 {{25, 26, NSM
}, 5400, {InterlaceVNegHNeg
, 5000, {3456, 625} }, {264, 22}, {2880, 576}, R_4or16
, {0, 252, 3, 19, 276, 48, 2, 1728}, 1, {0, 0, 0, 0, 0}, NO_3D_SUPPORT
}, /* 19 - 25,26 2880 x 576i */
1719 {{27, 28, 1}, 5400, {ProgrVNegHNeg
, 5000, {3456, 312} }, {264, 22}, {2880, 288}, R_4or16
, {0, 252, 3, 19, 276, 48, 2, 0}, 1, {0, 0, 0, 0, 0}, NO_3D_SUPPORT
}, /* 20 - 27,28(1) 2880 x 288p */
1720 {{27, 28, 2}, 5400, {ProgrVNegHNeg
, 5000, {3456, 313} }, {264, 22}, {2880, 288}, R_4or16
, {0, 252, 3, 19, 276, 48, 3, 0}, 1, {0, 0, 0, 0, 0}, NO_3D_SUPPORT
}, /* 21 - 27,28(2) 2880 x 288p */
1721 {{27, 28, 3}, 5400, {ProgrVNegHNeg
, 5000, {3456, 314} }, {264, 22}, {2880, 288}, R_4or16
, {0, 252, 3, 19, 276, 48, 4, 0}, 1, {0, 0, 0, 0, 0}, NO_3D_SUPPORT
}, /* 22 - 27,28(3) 2880 x 288p */
1722 {{29, 30, NSM
}, 5400, {ProgrVPosHNeg
, 5000, {1728, 625} }, {264, 44}, {1440, 576}, R_4or16
, {0, 128, 5, 39, 136, 24, 5, 0}, 0, {0, 0, 0, 0, 0}, NO_3D_SUPPORT
}, /* 23 - 29,30 1440 x 576p */
1723 {{31, 0, NSM
}, 14850, {ProgrVPosHPos
, 5000, {2640, 1125} }, {192, 41}, {1920, 1080}, R_16
, {0, 44, 5, 36, 148, 528, 4, 0}, 0, {0, 0, 0, 0, 0}, NO_3D_SUPPORT
}, /* 24 - 31(1) 1920 x 1080p */
1724 {{32, 0, NSM
}, 7417, {ProgrVPosHPos
, 2400, {2750, 1125} }, {192, 41}, {1920, 1080}, R_16
, {0, 44, 5, 36, 148, 638, 4, 0}, 0, {0, 0, 0, 0, 0}, NO_3D_SUPPORT
}, /* 25 - 32(2) 1920 x 1080p@24Hz */
1725 {{33, 0, NSM
}, 7425, {ProgrVPosHPos
, 2500, {2640, 1125} }, {192, 41}, {1920, 1080}, R_16
, {0, 44, 5, 36, 148, 528, 4, 0}, 0, {0, 0, 0, 0, 0}, NO_3D_SUPPORT
}, /* 26 - 33(3) 1920 x 1080p */
1726 {{34, 0, NSM
}, 7417, {ProgrVPosHPos
, 3000, {2200, 1125} }, {192, 41}, {1920, 1080}, R_16
, {0, 44, 5, 36, 148, 528, 4, 0}, 0, {0, 0, 0, 0, 0}, NO_3D_SUPPORT
}, /* 27 - 34(4) 1920 x 1080p */
1727 {{35, 36, NSM
}, 10800, {ProgrVNegHNeg
, 5994, {3432, 525} }, {488, 36}, {2880, 480}, R_4or16
, {0, 248, 6, 30, 240, 64, 10, 0}, 0, {0, 0, 0, 0, 0}, NO_3D_SUPPORT
}, /* 28 - 35, 36 2880 x 480p@59.94/60Hz */
1728 {{37, 38, NSM
}, 10800, {ProgrVNegHNeg
, 5000, {3456, 625} }, {272, 39}, {2880, 576}, R_4or16
, {0, 256, 5, 40, 272, 48, 5, 0}, 0, {0, 0, 0, 0, 0}, NO_3D_SUPPORT
}, /* 29 - 37, 38 2880 x 576p@50Hz */
1729 {{39, 0, NSM
}, 7200, {InterlaceVNegHNeg
, 5000, {2304, 1250} }, {352, 62}, {1920, 1080}, R_16
, {0, 168, 5, 87, 184, 32, 24, 0}, 0, {0, 0, 0, 0, 0}, NO_3D_SUPPORT
}, /* 30 - 39 1920 x 1080i@50Hz */
1730 {{40, 0, NSM
}, 14850, {InterlaceVPosHPos
, 10000, {2640, 1125} }, {192, 20}, {1920, 1080}, R_16
, {0, 44, 5, 15, 148, 528, 2, 1320}, 0, {0, 0, 0, 0, 0}, NO_3D_SUPPORT
}, /* 31 - 40 1920 x 1080i@100Hz */
1731 {{41, 0, NSM
}, 14850, {InterlaceVPosHPos
, 10000, {1980, 750} }, {260, 25}, {1280, 720}, R_16
, {0, 40, 5, 20, 220, 400, 5, 0}, 0, {0, 0, 0, 0, 0}, NO_3D_SUPPORT
}, /* 32 - 41 1280 x 720p@100Hz */
1732 {{42, 43, NSM
}, 5400, {ProgrVNegHNeg
, 10000, {864, 144} }, {132, 44}, {720, 576}, R_4or16
, {0, 64, 5, 39, 68, 12, 5, 0}, 0, {0, 0, 0, 0, 0}, NO_3D_SUPPORT
}, /* 33 - 42, 43, 720p x 576p@100Hz */
1733 {{44, 45, NSM
}, 5400, {InterlaceVNegHNeg
, 10000, {864, 625} }, {132, 22}, {720, 576}, R_4or16
, {0, 63, 3, 19, 69, 12, 2, 432}, 1, {0, 0, 0, 0, 0}, NO_3D_SUPPORT
}, /* 34 - 44, 45, 720p x 576i@100Hz, pix repl */
1734 {{46, 0, NSM
}, 14835, {InterlaceVPosHPos
, 11988, {2200, 1125} }, {192, 20}, {1920, 1080}, R_16
, {0, 44, 5, 15, 149, 88, 2, 1100}, 0, {0, 0, 0, 0, 0}, NO_3D_SUPPORT
}, /* 35 - 46, 1920 x 1080i@119.88/120Hz */
1735 {{47, 0, NSM
}, 14835, {ProgrVPosHPos
, 11988, {1650, 750} }, {260, 25}, {1280, 720}, R_16
, {0, 40, 5, 20, 220, 110, 5, 1100}, 0, {0, 0, 0, 0, 0}, NO_3D_SUPPORT
}, /* 36 - 47, 1280 x 720p@119.88/120Hz */
1736 {{48, 49, NSM
}, 5400, {ProgrVNegHNeg
, 11988, {858, 525} }, {122, 36}, {720, 480}, R_4or16
, {0, 62, 6, 30, 60, 16, 10, 0}, 0, {0, 0, 0, 0, 0}, NO_3D_SUPPORT
}, /* 37 - 48, 49 720 x 480p@119.88/120Hz */
1737 {{50, 51, NSM
}, 5400, {InterlaceVNegHNeg
, 11988, {858, 525} }, {119, 18}, {720, 480}, R_4or16
, {0, 62, 3, 15, 57, 19, 4, 429}, 1, {0, 0, 0, 0, 0}, NO_3D_SUPPORT
}, /* 38 - 50, 51 720 x 480i@119.88/120Hz */
1738 {{52, 53, NSM
}, 10800, {ProgrVNegHNeg
, 20000, {864, 625} }, {132, 44}, {720, 576}, R_4or16
, {0, 64, 5, 39, 68, 12, 5, 0}, 0, {0, 0, 0, 0, 0}, NO_3D_SUPPORT
}, /* 39 - 52, 53, 720 x 576p@200Hz */
1739 {{54, 55, NSM
}, 10800, {InterlaceVNegHNeg
, 20000, {864, 625} }, {132, 22}, {720, 576}, R_4or16
, {0, 63, 3, 19, 69, 12, 2, 432}, 1, {0, 0, 0, 0, 0}, NO_3D_SUPPORT
}, /* 40 - 54, 55, 1440 x 576i @200Hz, pix repl */
1740 {{56, 57, NSM
}, 10800, {ProgrVNegHNeg
, 24000, {858, 525} }, {122, 42}, {720, 480}, R_4or16
, {0, 62, 6, 30, 60, 16, 9, 0}, 0, {0, 0, 0, 0, 0}, NO_3D_SUPPORT
}, /* 41 - 56, 57, 720 x 480p @239.76/240Hz */
1741 {{58, 59, NSM
}, 10800, {InterlaceVNegHNeg
, 24000, {858, 525} }, {119, 18}, {720, 480}, R_4or16
, {0, 62, 3, 15, 57, 19, 4, 429}, 1, {0, 0, 0, 0, 0}, NO_3D_SUPPORT
}, /* 42 - 58, 59, 1440 x 480i @239.76/240Hz, pix repl */
1743 /* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */
1744 /* 4K x 2K Modes: */
1745 /* =================================================================================================================================================================================================================================== */
1747 /* VIC Refresh type Refresh-Rate Pixel-Totals Position Active Aspect Int Width Hbit Vbit Field Pixel Vact Space/Blank */
1748 /* 1 2 SubM PixClk V/H Position VFreq H V H V H V Ratio Adj H V Top Dly HSync VSync Offset Repl Space1 Space2 Blank1 Blank2 Blank3 3D */
1749 /* =================================================================================================================================================================================================================================== */
1750 {{1, 0, NSM
}, 297000, {ProgrVNegHNeg
, 30000, {4400, 2250} }, {384, 82}, {3840, 2160}, R_16
, {0, 88, 10, 72, 296, 176, 8, 0}, 0, {0, 0, 0, 0, 0}, NO_3D_SUPPORT
}, /* 43 - 4k x 2k 29.97/30Hz (297.000 MHz) */
1751 {{2, 0, NSM
}, 297000, {ProgrVNegHNeg
, 29700, {5280, 2250} }, {384, 82}, {3840, 2160}, R_16
, {0, 88, 10, 72, 296, 1056, 8, 0}, 0, {0, 0, 0, 0, 0}, NO_3D_SUPPORT
}, /* 44 - 4k x 2k 25Hz */
1752 {{3, 0, NSM
}, 297000, {ProgrVNegHNeg
, 24000, {5500, 2250} }, {384, 82}, {3840, 2160}, R_16
, {0, 88, 10, 72, 296, 1276, 8, 0}, 0, {0, 0, 0, 0, 0}, NO_3D_SUPPORT
}, /* 45 - 4k x 2k 24Hz (297.000 MHz) */
1753 {{4, 0, NSM
}, 297000, {ProgrVNegHNeg
, 24000, {6500, 2250} }, {384, 82}, {4096, 2160}, R_16
, {0, 88, 10, 72, 296, 1020, 8, 0}, 0, {0, 0, 0, 0, 0}, NO_3D_SUPPORT
}, /* 46 - 4k x 2k 24Hz (SMPTE) */
1755 /* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */
1757 /* =================================================================================================================================================================================================================================== */
1759 /* VIC Refresh type Refresh-Rate Pixel-Totals Position Active Aspect Int Width Hbit Vbit Field Pixel Vact Space/Blank */
1760 /* 1 2 SubM PixClk V/H Position VFreq H V H V H V Ratio Adj H V Top Dly HSync VSync Offset Repl Space1 Space2 Blank1 Blank2 Blank3 3D */
1761 /* =================================================================================================================================================================================================================================== */
1762 {{2, 3, NSM
}, 2700, {ProgrVPosHPos
, 6000, {858, 525} }, {122, 36}, {720, 480}, R_4or16
, {0, 62, 6, 30, 60, 16, 9, 0}, 0, {0, 0, 0, 0, 0}, 8}, /* 47 - 3D, 2,3 720p x 480p /60Hz, Side-by-Side (Half) */
1763 {{4, 0, NSM
}, 14850, {ProgrVPosHPos
, 6000, {1650, 750} }, {260, 25}, {1280, 720}, R_16
, {0, 40, 5, 20, 220, 110, 5, 0}, 0, {0, 0, 0, 0, 0}, 0}, /* 48 - 3D 4 1280 x 720p@60Hz, Frame Packing */
1764 {{5, 0, NSM
}, 14850, {InterlaceVPosHPos
, 6000, {2200, 562} }, {192, 20}, {1920, 540}, R_16
, {0, 44, 5, 15, 148, 88, 2, 1100}, 0, {23, 22, 0, 0, 0}, 0}, /* 49 - 3D, 5, 1920 x 1080i/60Hz, Frame Packing */
1765 {{5, 0, NSM
}, 14850, {InterlaceVPosHPos
, 6000, {2200, 562} }, {192, 20}, {1920, 540}, R_16
, {0, 44, 5, 15, 148, 88, 2, 1100}, 0, {0, 0, 22, 22, 23}, 1}, /* 50 - 3D, 5, 1920 x 1080i/60Hz, Field Alternative */
1766 {{16, 0, NSM
}, 29700, {ProgrVPosHPos
, 6000, {2200, 1125} }, {192, 41}, {1920, 1080}, R_16
, {0, 44, 5, 36, 148, 88, 4, 0}, 0, {0, 0, 0, 0, 0}, 0}, /* 51 - 3D, 16, 1920 x 1080p/60Hz, Frame Packing */
1767 {{16, 0, NSM
}, 29700, {ProgrVPosHPos
, 6000, {2200, 1125} }, {192, 41}, {1920, 1080}, R_16
, {0, 44, 5, 36, 148, 88, 4, 0}, 0, {0, 0, 0, 0, 0}, 2}, /* 52 - 3D, 16, 1920 x 1080p/60Hz, Line Alternative */
1768 {{16, 0, NSM
}, 29700, {ProgrVPosHPos
, 6000, {2200, 1125} }, {192, 41}, {1920, 1080}, R_16
, {0, 44, 5, 36, 148, 88, 4, 0}, 0, {0, 0, 0, 0, 0}, 3}, /* 53 - 3D, 16, 1920 x 1080p/60Hz, Side-by-Side (Full) */
1769 {{16, 0, NSM
}, 14850, {ProgrVPosHPos
, 6000, {2200, 1125} }, {192, 41}, {1920, 1080}, R_16
, {0, 44, 5, 36, 148, 88, 4, 0}, 0, {0, 0, 0, 0, 0}, 8}, /* 54 - 3D, 16, 1920 x 1080p/60Hz, Side-by-Side (Half) */
1770 {{19, 0, NSM
}, 14850, {ProgrVPosHPos
, 5000, {1980, 750} }, {260, 25}, {1280, 720}, R_16
, {0, 40, 5, 20, 220, 440, 5, 0}, 0, {0, 0, 0, 0, 0}, 0}, /* 55 - 3D, 19, 1280 x 720p@50Hz, Frame Packing */
1771 {{19, 0, NSM
}, 14850, {ProgrVPosHPos
, 5000, {1980, 750} }, {260, 25}, {1280, 720}, R_16
, {0, 40, 5, 20, 220, 440, 5, 0}, 0, {0, 0, 0, 0, 0}, 4}, /* 56 - 3D, 19, 1280 x 720p/50Hz, (L + depth) */
1772 {{19, 0, NSM
}, 29700, {ProgrVPosHPos
, 5000, {1980, 750} }, {260, 25}, {1280, 720}, R_16
, {0, 40, 5, 20, 220, 440, 5, 0}, 0, {0, 0, 0, 0, 0}, 5}, /* 57 - 3D, 19, 1280 x 720p/50Hz, (L + depth + Gfx + G-depth) */
1773 {{20, 0, NSM
}, 14850, {InterlaceVPosHPos
, 5000, {2640, 562} }, {192, 20}, {1920, 540}, R_16
, {0, 44, 5, 15, 148, 528, 2, 1220}, 0, {23, 22, 0, 0, 0}, 0}, /* 58 - 3D, 20, 1920 x 1080i/50Hz, Frame Packing */
1774 {{20, 0, NSM
}, 14850, {InterlaceVPosHPos
, 5000, {2640, 562} }, {192, 20}, {1920, 540}, R_16
, {0, 44, 5, 15, 148, 528, 2, 1220}, 0, {0, 0, 22, 22, 23}, 1}, /* 59 - 3D, 20, 1920 x 1080i/50Hz, Field Alternative */
1775 {{31, 0, NSM
}, 29700, {ProgrVPosHPos
, 5000, {2640, 1125} }, {192, 41}, {1920, 1080}, R_16
, {0, 44, 5, 36, 148, 528, 4, 0}, 0, {0, 0, 0, 0, 0}, 0}, /* 60 - 3D, 31, 1920 x 1080p/50Hz, Frame Packing */
1776 {{31, 0, NSM
}, 29700, {ProgrVPosHPos
, 5000, {2640, 1125} }, {192, 41}, {1920, 1080}, R_16
, {0, 44, 5, 36, 148, 528, 4, 0}, 0, {0, 0, 0, 0, 0}, 2}, /* 61 - 3D, 31, 1920 x 1080p/50Hz, Line Alternative */
1777 {{31, 0, NSM
}, 29700, {ProgrVPosHPos
, 5000, {2650, 1125} }, {192, 41}, {1920, 1080}, R_16
, {0, 44, 5, 36, 148, 528, 4, 0}, 0, {0, 0, 0, 0, 0}, 3}, /* 62 - 3D, 31, 1920 x 1080p/50Hz, Side-by-Side (Full) */
1778 {{32, 0, NSM
}, 14850, {ProgrVPosHPos
, 2400, {2750, 1125} }, {192, 41}, {1920, 1080}, R_16
, {0, 44, 5, 36, 148, 638, 4, 0}, 0, {0, 0, 0, 0, 0}, 0}, /* 63 - 3D, 32, 1920 x 1080p@24Hz, Frame Packing */
1780 /* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */
1781 /* NOTE: DO NOT ATTEMPT INPUT RESOLUTIONS THAT REQUIRE PIXEL CLOCK FREQUENCIES HIGHER THAN THOSE SUPPORTED BY THE TRANSMITTER CHIP */
1783 /* =================================================================================================================================================================================================================================== */
1785 /* VIC Refresh type fresh-Rate Pixel-Totals Position Active Aspect Int Width Hbit Vbit Field Pixel Vact Space/Blank */
1786 /* 1 2 SubM PixClk V/H Position VFreq H V H V H V Ratio {Adj H V Top Dly HSync VSync Offset} Repl Space1 Space2 Blank1 Blank2 Blank3 3D */
1787 /* =================================================================================================================================================================================================================================== */
1788 {{PC_BASE
, 0, NSM
}, 3150, {ProgrVNegHPos
, 8508, {832, 445} }, {160, 63}, {640, 350}, R_16
, {0, 64, 3, 60, 96, 32, 32, 0}, 0, {0, 0, 0, 0, 0}, NO_3D_SUPPORT
}, /* 64 - 640x350@85.08 */
1789 {{PC_BASE
+ 1, 0, NSM
}, 3150, {ProgrVPosHNeg
, 8508, {832, 445} }, {160, 44}, {640, 400}, R_16
, {0, 64, 3, 41, 96, 32, 1, 0}, 0, {0, 0, 0, 0, 0}, NO_3D_SUPPORT
}, /* 65 - 640x400@85.08 */
1790 {{PC_BASE
+ 2, 0, NSM
}, 2700, {ProgrVPosHNeg
, 7008, {900, 449} }, {0, 0}, {720, 400}, R_16
, {0, 0, 0, 0, 0, 0, 0, 0}, 0, {0, 0, 0, 0, 0}, NO_3D_SUPPORT
}, /* 66 - 720x400@70.08 */
1791 {{PC_BASE
+ 3, 0, NSM
}, 3500, {ProgrVPosHNeg
, 8504, {936, 446} }, {20, 45}, {720, 400}, R_16
, {0, 72, 3, 42, 108, 36, 1, 0}, 0, {0, 0, 0, 0, 0}, NO_3D_SUPPORT
}, /* 67 - 720x400@85.04 */
1792 {{PC_BASE
+ 4, 0, NSM
}, 2517, {ProgrVNegHNeg
, 5994, {800, 525} }, {144, 35}, {640, 480}, R_4
, {0, 96, 2, 33, 48, 16, 10, 0}, 0, {0, 0, 0, 0, 0}, NO_3D_SUPPORT
}, /* 68 - 640x480@59.94 */
1793 {{PC_BASE
+ 5, 0, NSM
}, 3150, {ProgrVNegHNeg
, 7281, {832, 520} }, {144, 31}, {640, 480}, R_4
, {0, 40, 3, 28, 128, 128, 9, 0}, 0, {0, 0, 0, 0, 0}, NO_3D_SUPPORT
}, /* 69 - 640x480@72.80 */
1794 {{PC_BASE
+ 6, 0, NSM
}, 3150, {ProgrVNegHNeg
, 7500, {840, 500} }, {21, 19}, {640, 480}, R_4
, {0, 64, 3, 28, 128, 24, 9, 0}, 0, {0, 0, 0, 0, 0}, NO_3D_SUPPORT
}, /* 70 - 640x480@75.00 */
1795 {{PC_BASE
+ 7, 0, NSM
}, 3600, {ProgrVNegHNeg
, 8500, {832, 509} }, {168, 28}, {640, 480}, R_4
, {0, 56, 3, 25, 128, 24, 9, 0}, 0, {0, 0, 0, 0, 0}, NO_3D_SUPPORT
}, /* 71 - 640x480@85.00 */
1796 {{PC_BASE
+ 8, 0, NSM
}, 3600, {ProgrVPosHPos
, 5625, {1024, 625} }, {200, 24}, {800, 600}, R_4
, {0, 72, 2, 22, 128, 24, 1, 0}, 0, {0, 0, 0, 0, 0}, NO_3D_SUPPORT
}, /* 72 - 800x600@56.25 */
1797 {{PC_BASE
+ 9, 0, NSM
}, 4000, {ProgrVPosHPos
, 6032, {1056, 628} }, {216, 27}, {800, 600}, R_4
, {0, 128, 4, 23, 88, 40, 1, 0}, 0, {0, 0, 0, 0, 0}, NO_3D_SUPPORT
}, /* 73 - 800x600@60.317 */
1798 {{PC_BASE
+ 10, 0, NSM
}, 5000, {ProgrVPosHPos
, 7219, {1040, 666} }, {184, 29}, {800, 600}, R_4
, {0, 120, 6, 23, 64, 56, 37, 0}, 0, {0, 0, 0, 0, 0}, NO_3D_SUPPORT
}, /* 74 - 800x600@72.19 */
1799 {{PC_BASE
+ 11, 0, NSM
}, 4950, {ProgrVPosHPos
, 7500, {1056, 625} }, {240, 24}, {800, 600}, R_4
, {0, 80, 3, 21, 160, 16, 1, 0}, 0, {0, 0, 0, 0, 0}, NO_3D_SUPPORT
}, /* 75 - 800x600@75 */
1800 {{PC_BASE
+ 12, 0, NSM
}, 5625, {ProgrVPosHPos
, 8506, {1048, 631} }, {216, 30}, {800, 600}, R_4
, {0, 64, 3, 27, 152, 32, 1, 0}, 0, {0, 0, 0, 0, 0}, NO_3D_SUPPORT
}, /* 76 - 800x600@85.06 */
1801 {{PC_BASE
+ 13, 0, NSM
}, 6500, {ProgrVNegHNeg
, 6000, {1344, 806} }, {296, 35}, {1024, 768}, R_4
, {0, 136, 6, 29, 160, 24, 3, 0}, 0, {0, 0, 0, 0, 0}, NO_3D_SUPPORT
}, /* 77 - 1024x768@60 */
1802 {{PC_BASE
+ 14, 0, NSM
}, 7500, {ProgrVNegHNeg
, 7007, {1328, 806} }, {280, 35}, {1024, 768}, R_4
, {0, 136, 6, 19, 144, 24, 3, 0}, 0, {0, 0, 0, 0, 0}, NO_3D_SUPPORT
}, /* 78 - 1024x768@70.07 */
1803 {{PC_BASE
+ 15, 0, NSM
}, 7875, {ProgrVPosHPos
, 7503, {1312, 800} }, {272, 31}, {1024, 768}, R_4
, {0, 96, 3, 28, 176, 16, 1, 0}, 0, {0, 0, 0, 0, 0}, NO_3D_SUPPORT
}, /* 79 - 1024x768@75.03 */
1804 {{PC_BASE
+ 16, 0, NSM
}, 9450, {ProgrVPosHPos
, 8500, {1376, 808} }, {304, 39}, {1024, 768}, R_4
, {0, 96, 3, 36, 208, 48, 1, 0}, 0, {0, 0, 0, 0, 0}, NO_3D_SUPPORT
}, /* 80 - 1024x768@85 */
1805 {{PC_BASE
+ 17, 0, NSM
}, 10800, {ProgrVPosHPos
, 7500, {1600, 900} }, {384, 35}, {1152, 864}, R_4
, {0, 128, 3, 32, 256, 64, 1, 0}, 0, {0, 0, 0, 0, 0}, NO_3D_SUPPORT
}, /* 81 - 1152x864@75 */
1806 {{PC_BASE
+ 18, 0, NSM
}, 16200, {ProgrVPosHPos
, 6000, {2160, 1250} }, {496, 49}, {1600, 1200}, R_4
, {0, 304, 3, 46, 304, 64, 1, 0}, 0, {0, 0, 0, 0, 0}, NO_3D_SUPPORT
}, /* 82 - 1600x1200@60 */
1807 {{PC_BASE
+ 19, 0, NSM
}, 6825, {ProgrVNegHPos
, 6000, {1440, 790} }, {112, 19}, {1280, 768}, R_16
, {0, 32, 7, 12, 80, 48, 3, 0}, 0, {0, 0, 0, 0, 0}, NO_3D_SUPPORT
}, /* 83 - 1280x768@59.95 */
1808 {{PC_BASE
+ 20, 0, NSM
}, 7950, {ProgrVPosHNeg
, 5987, {1664, 798} }, {320, 27}, {1280, 768}, R_16
, {0, 128, 7, 20, 192, 64, 3, 0}, 0, {0, 0, 0, 0, 0}, NO_3D_SUPPORT
}, /* 84 - 1280x768@59.87 */
1809 {{PC_BASE
+ 21, 0, NSM
}, 10220, {ProgrVPosHNeg
, 6029, {1696, 805} }, {320, 27}, {1280, 768}, R_16
, {0, 128, 7, 27, 208, 80, 3, 0}, 0, {0, 0, 0, 0, 0}, NO_3D_SUPPORT
}, /* 85 - 1280x768@74.89 */
1810 {{PC_BASE
+ 22, 0, NSM
}, 11750, {ProgrVPosHNeg
, 8484, {1712, 809} }, {352, 38}, {1280, 768}, R_16
, {0, 136, 7, 31, 216, 80, 3, 0}, 0, {0, 0, 0, 0, 0}, NO_3D_SUPPORT
}, /* 86 - 1280x768@85 */
1811 {{PC_BASE
+ 23, 0, NSM
}, 10800, {ProgrVPosHPos
, 6000, {1800, 1000} }, {424, 39}, {1280, 960}, R_4
, {0, 112, 3, 36, 312, 96, 1, 0}, 0, {0, 0, 0, 0, 0}, NO_3D_SUPPORT
}, /* 87 - 1280x960@60 */
1812 {{PC_BASE
+ 24, 0, NSM
}, 14850, {ProgrVPosHPos
, 8500, {1728, 1011} }, {384, 50}, {1280, 960}, R_4
, {0, 160, 3, 47, 224, 64, 1, 0}, 0, {0, 0, 0, 0, 0}, NO_3D_SUPPORT
}, /* 88 - 1280x960@85 */
1813 {{PC_BASE
+ 25, 0, NSM
}, 10800, {ProgrVPosHPos
, 6002, {1688, 1066} }, {360, 41}, {1280, 1024}, R_4
, {0, 112, 3, 38, 248, 48, 1, 0}, 0, {0, 0, 0, 0, 0}, NO_3D_SUPPORT
}, /* 89 - 1280x1024@60 */
1814 {{PC_BASE
+ 26, 0, NSM
}, 13500, {ProgrVPosHPos
, 7502, {1688, 1066} }, {392, 41}, {1280, 1024}, R_4
, {0, 144, 3, 38, 248, 16, 1, 0}, 0, {0, 0, 0, 0, 0}, NO_3D_SUPPORT
}, /* 90 - 1280x1024@75 */
1815 {{PC_BASE
+ 27, 0, NSM
}, 15750, {ProgrVPosHPos
, 8502, {1728, 1072} }, {384, 47}, {1280, 1024}, R_4
, {0, 160, 3, 4, 224, 64, 1, 0}, 0, {0, 0, 0, 0, 0}, NO_3D_SUPPORT
}, /* 91 - 1280x1024@85 */
1816 {{PC_BASE
+ 28, 0, NSM
}, 8550, {ProgrVPosHPos
, 6002, {1792, 795} }, {368, 24}, {1360, 768}, R_16
, {0, 112, 6, 18, 256, 64, 3, 0}, 0, {0, 0, 0, 0, 0}, NO_3D_SUPPORT
}, /* 92 - 1360x768@60 */
1817 {{PC_BASE
+ 29, 0, NSM
}, 10100, {ProgrVNegHPos
, 5995, {1560, 1080} }, {112, 27}, {1400, 1050}, R_4
, {0, 32, 4, 23, 80, 48, 3, 0}, 0, {0, 0, 0, 0, 0}, NO_3D_SUPPORT
}, /* 93 - 1400x105@59.95 */
1818 {{PC_BASE
+ 30, 0, NSM
}, 12175, {ProgrVPosHNeg
, 5998, {1864, 1089} }, {376, 36}, {1400, 1050}, R_4
, {0, 144, 4, 32, 232, 88, 3, 0}, 0, {0, 0, 0, 0, 0}, NO_3D_SUPPORT
}, /* 94 - 1400x105@59.98 */
1819 {{PC_BASE
+ 31, 0, NSM
}, 15600, {ProgrVPosHNeg
, 7487, {1896, 1099} }, {392, 46}, {1400, 1050}, R_4
, {0, 144, 4, 22, 248, 104, 3, 0}, 0, {0, 0, 0, 0, 0}, NO_3D_SUPPORT
}, /* 95 - 1400x105@74.87 */
1820 {{PC_BASE
+ 32, 0, NSM
}, 17950, {ProgrVPosHNeg
, 8496, {1912, 1105} }, {408, 52}, {1400, 1050}, R_4
, {0, 152, 4, 48, 256, 104, 3, 0}, 0, {0, 0, 0, 0, 0}, NO_3D_SUPPORT
}, /* 96 - 1400x105@84.96 */
1821 {{PC_BASE
+ 33, 0, NSM
}, 17550, {ProgrVPosHPos
, 6500, {2160, 1250} }, {496, 49}, {1600, 1200}, R_4
, {0, 192, 3, 46, 304, 64, 1, 0}, 0, {0, 0, 0, 0, 0}, NO_3D_SUPPORT
}, /* 97 - 1600x1200@65 */
1822 {{PC_BASE
+ 34, 0, NSM
}, 18900, {ProgrVPosHPos
, 7000, {2160, 1250} }, {496, 49}, {1600, 1200}, R_4
, {0, 192, 3, 46, 304, 64, 1, 0}, 0, {0, 0, 0, 0, 0}, NO_3D_SUPPORT
}, /* 98 - 1600x1200@70 */
1823 {{PC_BASE
+ 35, 0, NSM
}, 20250, {ProgrVPosHPos
, 7500, {2160, 1250} }, {496, 49}, {1600, 1200}, R_4
, {0, 192, 3, 46, 304, 64, 1, 0}, 0, {0, 0, 0, 0, 0}, NO_3D_SUPPORT
}, /* 99 - 1600x1200@75 */
1824 {{PC_BASE
+ 36, 0, NSM
}, 22950, {ProgrVPosHPos
, 8500, {2160, 1250} }, {496, 49}, {1600, 1200}, R_4
, {0, 192, 3, 46, 304, 64, 1, 0}, 0, {0, 0, 0, 0, 0}, NO_3D_SUPPORT
}, /* 100 - 1600x1200@85 */
1825 {{PC_BASE
+ 37, 0, NSM
}, 20475, {ProgrVPosHNeg
, 6000, {2448, 1394} }, {528, 49}, {1792, 1344}, R_4
, {0, 200, 3, 46, 328, 128, 1, 0}, 0, {0, 0, 0, 0, 0}, NO_3D_SUPPORT
}, /* 101 - 1792x1344@60 */
1826 {{PC_BASE
+ 38, 0, NSM
}, 26100, {ProgrVPosHNeg
, 7500, {2456, 1417} }, {568, 72}, {1792, 1344}, R_4
, {0, 216, 3, 69, 352, 96, 1, 0}, 0, {0, 0, 0, 0, 0}, NO_3D_SUPPORT
}, /* 102 - 1792x1344@74.997 */
1827 {{PC_BASE
+ 39, 0, NSM
}, 21825, {ProgrVPosHNeg
, 6000, {2528, 1439} }, {576, 46}, {1856, 1392}, R_4
, {0, 224, 3, 43, 352, 96, 1, 0}, 0, {0, 0, 0, 0, 0}, NO_3D_SUPPORT
}, /* 103 - 1856x1392@60 */
1828 {{PC_BASE
+ 40, 0, NSM
}, 28800, {ProgrVPosHNeg
, 7500, {2560, 1500} }, {576, 107}, {1856, 1392}, R_4
, {0, 224, 3, 104, 352, 128, 1, 0}, 0, {0, 0, 0, 0, 0}, NO_3D_SUPPORT
}, /* 104 - 1856x1392@75 */
1829 {{PC_BASE
+ 41, 0, NSM
}, 15400, {ProgrVNegHPos
, 5995, {2080, 1235} }, {112, 32}, {1920, 1200}, R_16
, {0, 32, 6, 26, 80, 48, 3, 0}, 0, {0, 0, 0, 0, 0}, NO_3D_SUPPORT
}, /* 106 - 1920x1200@59.95 */
1830 {{PC_BASE
+ 42, 0, NSM
}, 19325, {ProgrVPosHNeg
, 5988, {2592, 1245} }, {536, 42}, {1920, 1200}, R_16
, {0, 200, 6, 36, 336, 136, 3, 0}, 0, {0, 0, 0, 0, 0}, NO_3D_SUPPORT
}, /* 107 - 1920x1200@59.88 */
1831 {{PC_BASE
+ 43, 0, NSM
}, 24525, {ProgrVPosHNeg
, 7493, {2608, 1255} }, {552, 52}, {1920, 1200}, R_16
, {0, 208, 6, 46, 344, 136, 3, 0}, 0, {0, 0, 0, 0, 0}, NO_3D_SUPPORT
}, /* 108 - 1920x1200@74.93 */
1832 {{PC_BASE
+ 44, 0, NSM
}, 28125, {ProgrVPosHNeg
, 8493, {2624, 1262} }, {560, 59}, {1920, 1200}, R_16
, {0, 208, 6, 53, 352, 144, 3, 0}, 0, {0, 0, 0, 0, 0}, NO_3D_SUPPORT
}, /* 109 - 1920x1200@84.93 */
1833 {{PC_BASE
+ 45, 0, NSM
}, 23400, {ProgrVPosHNeg
, 6000, {2600, 1500} }, {552, 59}, {1920, 1440}, R_4
, {0, 208, 3, 56, 344, 128, 1, 0}, 0, {0, 0, 0, 0, 0}, NO_3D_SUPPORT
}, /* 110 - 1920x1440@60 */
1834 {{PC_BASE
+ 46, 0, NSM
}, 29700, {ProgrVPosHNeg
, 7500, {2640, 1500} }, {576, 59}, {1920, 1440}, R_4
, {0, 224, 3, 56, 352, 144, 1, 0}, 0, {0, 0, 0, 0, 0}, NO_3D_SUPPORT
}, /* 111 - 1920x1440@75 */
1835 {{PC_BASE
+ 47, 0, NSM
}, 24150, {ProgrVPosHNeg
, 6000, {2720, 1481} }, {48, 3}, {2560, 1440}, R_16
, {0, 32, 5, 56, 352, 144, 1, 0}, 0, {0, 0, 0, 0, 0}, NO_3D_SUPPORT
}, /* 112 - 2560x1440@60 // %%% need work */
1836 {{PC_BASE
+ 48, 0, NSM
}, 2700, {InterlaceVNegHNeg
, 6000, {1716, 264} }, {244, 18}, {1440, 480}, R_4or16
, {3, 124, 3, 15, 114, 17, 5, 429}, 0, {0, 0, 0, 0, 0}, NO_3D_SUPPORT
}, /* 113 - 1440 x 480i */
1840 /* ------------------------------------------------------------------------------ */
1841 /* Aspect Ratio table defines the aspect ratio as function of VIC. This table */
1842 /* should be used in conjunction with the 861-D part of VModeInfoType VModesTable[] */
1843 /* (formats 0 - 59) because some formats that differ only in their AR are grouped */
1844 /* together (e.g., formats 2 and 3). */
1845 /* ------------------------------------------------------------------------------ */
1846 static u8 AspectRatioTable
[] = {
1847 R_4
, R_4
, R_16
, R_16
, R_16
, R_4
, R_16
, R_4
, R_16
, R_4
,
1848 R_16
, R_4
, R_16
, R_4
, R_16
, R_16
, R_4
, R_16
, R_16
, R_16
,
1849 R_4
, R_16
, R_4
, R_16
, R_4
, R_16
, R_4
, R_16
, R_4
, R_16
,
1850 R_16
, R_16
, R_16
, R_16
, R_4
, R_16
, R_4
, R_16
, R_16
, R_16
,
1851 R_16
, R_4
, R_16
, R_4
, R_16
, R_16
, R_16
, R_4
, R_16
, R_4
,
1852 R_16
, R_4
, R_16
, R_4
, R_16
, R_4
, R_16
, R_4
, R_16
1855 /* ------------------------------------------------------------------------------ */
1856 /* VIC to Indexc table defines which VideoModeTable entry is appropreate for this VIC code. */
1857 /* Note: This table is valid ONLY for VIC codes in 861-D formats, NOT for HDMI_VIC codes */
1859 /* ------------------------------------------------------------------------------ */
1860 static u8 VIC2Index
[] = {
1861 0, 0, 1, 1, 2, 3, 4, 4, 5, 5,
1862 7, 7, 8, 8, 10, 10, 11, 12, 12, 13,
1863 14, 15, 15, 16, 16, 19, 19, 20, 20, 23,
1864 23, 24, 25, 26, 27, 28, 28, 29, 29, 30,
1865 31, 32, 33, 33, 34, 34, 35, 36, 37, 37,
1866 38, 38, 39, 39, 40, 40, 41, 41, 42, 42
1869 /* ------------------------------------------------------------------------------ */
1870 /* Function Name: ConvertVIC_To_VM_Index() */
1871 /* Function Description: Convert Video Identification Code to the corresponding */
1872 /* index of VModesTable[]. Conversion also depends on the */
1873 /* value of the 3D_Structure parameter in the case of 3D video format. */
1874 /* Accepts: VIC to be converted; 3D_Structure value */
1875 /* Returns: Index into VModesTable[] corrsponding to VIC */
1876 /* Globals: VModesTable[] siHdmiTx */
1877 /* Note: Conversion is for 861-D formats, HDMI_VIC or 3D */
1878 /* ------------------------------------------------------------------------------ */
1879 byte
ConvertVIC_To_VM_Index(void)
1884 /* The global VideoModeDescription contains all the information we need about */
1885 /* the Video mode for use to find its entry in the Videio mode table. */
1887 /* The first issue. The "VIC" may be a 891-D VIC code, or it might be an */
1888 /* HDMI_VIC code, or it might be a 3D code. Each require different handling */
1889 /* to get the proper video mode table index. */
1891 if (siHdmiTx
.HDMIVideoFormat
== VMD_HDMIFORMAT_CEA_VIC
) {
1893 /* This is a regular 861-D format VIC, so we use the VIC to Index */
1894 /* table to look up the index. */
1896 index
= VIC2Index
[siHdmiTx
.VIC
];
1897 } else if (siHdmiTx
.HDMIVideoFormat
== VMD_HDMIFORMAT_HDMI_VIC
) {
1899 /* HDMI_VIC conversion is simple. We need to subtract one because the codes start */
1900 /* with one instead of zero. These values are from HDMI 1.4 Spec Table 8-13. */
1902 if ((siHdmiTx
.VIC
< 1) || (siHdmiTx
.VIC
> 4)) {
1903 index
= DEFAULT_VIDEO_MODE
;
1905 index
= (HDMI_VIC_BASE
- 1) + siHdmiTx
.VIC
;
1907 } else if (siHdmiTx
.HDMIVideoFormat
== VMD_HDMIFORMAT_3D
) {
1909 /* Currently there are only a few VIC modes that we can do in 3D. If the VIC code is not */
1910 /* one of these OR if the packing type is not supported for that VIC code, then it is an */
1911 /* error and we go to the default video mode. See HDMI Spec 1.4 Table H-6. */
1913 switch (siHdmiTx
.VIC
) {
1914 case VIC_FOR_480P_60Hz_4X3
:
1915 case VIC_FOR_480P_60Hz_16X9
:
1916 /* We only support Side-by-Side (Half) for these modes */
1917 if (siHdmiTx
.ThreeDStructure
== SIDE_BY_SIDE_HALF
)
1918 index
= VIC_3D_BASE
+ 0;
1920 index
= DEFAULT_VIDEO_MODE
;
1923 case VIC_FOR_720P_60Hz
:
1924 switch (siHdmiTx
.ThreeDStructure
) {
1926 index
= VIC_3D_BASE
+ 1;
1929 index
= DEFAULT_VIDEO_MODE
;
1934 case VIC_FOR_1080i_60Hz
:
1935 switch (siHdmiTx
.ThreeDStructure
) {
1937 index
= VIC_3D_BASE
+ 2;
1939 case VMD_3D_FIELDALTERNATIVE
:
1940 index
= VIC_3D_BASE
+ 3;
1943 index
= DEFAULT_VIDEO_MODE
;
1948 case VIC_FOR_1080p_60Hz
:
1949 switch (siHdmiTx
.ThreeDStructure
) {
1951 index
= VIC_3D_BASE
+ 4;
1953 case VMD_3D_LINEALTERNATIVE
:
1954 index
= VIC_3D_BASE
+ 5;
1956 case SIDE_BY_SIDE_FULL
:
1957 index
= VIC_3D_BASE
+ 6;
1959 case SIDE_BY_SIDE_HALF
:
1960 index
= VIC_3D_BASE
+ 7;
1963 index
= DEFAULT_VIDEO_MODE
;
1968 case VIC_FOR_720P_50Hz
:
1969 switch (siHdmiTx
.ThreeDStructure
) {
1971 index
= VIC_3D_BASE
+ 8;
1974 index
= VIC_3D_BASE
+ 9;
1976 case VMD_3D_LDEPTHGRAPHICS
:
1977 index
= VIC_3D_BASE
+ 10;
1980 index
= DEFAULT_VIDEO_MODE
;
1985 case VIC_FOR_1080i_50Hz
:
1986 switch (siHdmiTx
.ThreeDStructure
) {
1988 index
= VIC_3D_BASE
+ 11;
1990 case VMD_3D_FIELDALTERNATIVE
:
1991 index
= VIC_3D_BASE
+ 12;
1994 index
= DEFAULT_VIDEO_MODE
;
1999 case VIC_FOR_1080p_50Hz
:
2000 switch (siHdmiTx
.ThreeDStructure
) {
2002 index
= VIC_3D_BASE
+ 13;
2004 case VMD_3D_LINEALTERNATIVE
:
2005 index
= VIC_3D_BASE
+ 14;
2007 case SIDE_BY_SIDE_FULL
:
2008 index
= VIC_3D_BASE
+ 15;
2011 index
= DEFAULT_VIDEO_MODE
;
2016 case VIC_FOR_1080p_24Hz
:
2017 switch (siHdmiTx
.ThreeDStructure
) {
2019 index
= VIC_3D_BASE
+ 16;
2022 index
= DEFAULT_VIDEO_MODE
;
2028 index
= DEFAULT_VIDEO_MODE
;
2031 } else if (siHdmiTx
.HDMIVideoFormat
== VMD_HDMIFORMAT_PC
) {
2032 if (siHdmiTx
.VIC
< PC_SIZE
) {
2033 index
= siHdmiTx
.VIC
+ PC_BASE
;
2035 index
= DEFAULT_VIDEO_MODE
;
2038 /* This should never happen! If so, default to first table entry */
2039 index
= DEFAULT_VIDEO_MODE
;
2048 byte TPI_REG0x63_SAVED
= 0;
2050 /* ------------------------------------------------------------------------------ */
2051 /* Function Name: SetEmbeddedSync() */
2052 /* Function Description: Set the 9022/4 registers to extract embedded sync. */
2054 /* Accepts: Index of video mode to set */
2056 /* Globals: VModesTable[] */
2057 /* ------------------------------------------------------------------------------ */
2058 byte
SetEmbeddedSync(void)
2061 word H_Bit_2_H_Sync
;
2065 byte V_Bit_2_V_Sync
;
2069 TPI_TRACE_PRINT((">>SetEmbeddedSync()\n"));
2071 ReadModifyWriteIndexedRegister(INDEXED_PAGE_0
, 0x0A, 0x01, 0x01); /* set Output Format YCbCr 4:4:4 */
2072 ReadClearWriteTPI(0x60, MSBIT
); /* set 0x60[7] = 0 for External DE mode */
2073 WriteByteTPI(0x63, 0x30); /* Vsync and Hsync Polarity settings 1 : Negative(leading edge falls) */
2074 ReadSetWriteTPI(0x60, MSBIT
); /* set 0x60[7] = 1 for Embedded Sync */
2076 ModeTblIndex
= ConvertVIC_To_VM_Index();
2078 H_Bit_2_H_Sync
= VModesTable
[ModeTblIndex
]._656
.HBit2HSync
;
2079 Field2Offset
= VModesTable
[ModeTblIndex
]._656
.Field2Offset
;
2080 H_SyncWidth
= VModesTable
[ModeTblIndex
]._656
.HLength
;
2081 V_Bit_2_V_Sync
= VModesTable
[ModeTblIndex
]._656
.VBit2VSync
;
2082 V_SyncWidth
= VModesTable
[ModeTblIndex
]._656
.VLength
;
2084 B_Data
[0] = H_Bit_2_H_Sync
& LOW_BYTE
; /* Setup HBIT_TO_HSYNC 8 LSBits (0x62) */
2086 B_Data
[1] = (H_Bit_2_H_Sync
>> 8) & TWO_LSBITS
; /* HBIT_TO_HSYNC 2 MSBits */
2087 /* B_Data[1] |= BIT_EN_SYNC_EXTRACT; // and Enable Embedded Sync to 0x63 */
2088 TPI_REG0x63_SAVED
= B_Data
[1];
2090 B_Data
[2] = Field2Offset
& LOW_BYTE
; /* 8 LSBits of "Field2 Offset" to 0x64 */
2091 B_Data
[3] = (Field2Offset
>> 8) & LOW_NIBBLE
; /* 2 MSBits of "Field2 Offset" to 0x65 */
2093 B_Data
[4] = H_SyncWidth
& LOW_BYTE
;
2094 B_Data
[5] = (H_SyncWidth
>> 8) & TWO_LSBITS
; /* HWIDTH to 0x66, 0x67 */
2095 B_Data
[6] = V_Bit_2_V_Sync
; /* VBIT_TO_VSYNC to 0x68 */
2096 B_Data
[7] = V_SyncWidth
; /* VWIDTH to 0x69 */
2098 WriteBlockTPI(0x62, 8, &B_Data
[0]);
2103 /* ------------------------------------------------------------------------------ */
2104 /* Function Name: EnableEmbeddedSync() */
2105 /* Function Description: EnableEmbeddedSync */
2110 /* ------------------------------------------------------------------------------ */
2111 void EnableEmbeddedSync(void)
2113 TPI_TRACE_PRINT((">>EnableEmbeddedSync()\n"));
2115 ReadClearWriteTPI(0x60, MSBIT
); /* set 0x60[7] = 0 for DE mode */
2116 WriteByteTPI(0x63, 0x30);
2117 ReadSetWriteTPI(0x60, MSBIT
); /* set 0x60[7] = 1 for Embedded Sync */
2118 ReadSetWriteTPI(0x63, BIT_6
);
2121 /* ------------------------------------------------------------------------------ */
2122 /* Function Name: SetDE() */
2123 /* Function Description: Set the 9022/4 internal DE generator parameters */
2126 /* Returns: DE_SET_OK */
2129 /* NOTE: 0x60[7] must be set to "0" for the follwing settings to take effect */
2130 /* ------------------------------------------------------------------------------ */
2136 word H_StartPos
, V_StartPos
;
2137 word Htotal
, Vtotal
;
2143 TPI_TRACE_PRINT((">>SetDE()\n"));
2145 ModeTblIndex
= ConvertVIC_To_VM_Index();
2147 if (VModesTable
[ModeTblIndex
]._3D_Struct
!= NO_3D_SUPPORT
) {
2148 return DE_CANNOT_BE_SET_WITH_3D_MODE
;
2149 TPI_TRACE_PRINT((">>SetDE() not allowed with 3D video format\n"));
2151 /* Make sure that External Sync method is set before enableing the DE Generator: */
2152 RegValue
= ReadByteTPI(0x60);
2154 if (RegValue
& BIT_7
) {
2155 return DE_CANNOT_BE_SET_WITH_EMBEDDED_SYNC
;
2158 H_StartPos
= VModesTable
[ModeTblIndex
].Pos
.H
;
2159 V_StartPos
= VModesTable
[ModeTblIndex
].Pos
.V
;
2161 Htotal
= VModesTable
[ModeTblIndex
].Tag
.Total
.Pixels
;
2162 Vtotal
= VModesTable
[ModeTblIndex
].Tag
.Total
.Lines
;
2164 Polarity
= (~VModesTable
[ModeTblIndex
].Tag
.RefrTypeVHPol
) & TWO_LSBITS
;
2166 H_Res
= VModesTable
[ModeTblIndex
].Res
.H
;
2168 if ((VModesTable
[ModeTblIndex
].Tag
.RefrTypeVHPol
& 0x04)) {
2169 V_Res
= (VModesTable
[ModeTblIndex
].Res
.V
) >> 1; /* if interlace V-resolution divided by 2 */
2171 V_Res
= (VModesTable
[ModeTblIndex
].Res
.V
);
2174 B_Data
[0] = H_StartPos
& LOW_BYTE
; /* 8 LSB of DE DLY in 0x62 */
2176 B_Data
[1] = (H_StartPos
>> 8) & TWO_LSBITS
; /* 2 MSBits of DE DLY to 0x63 */
2177 B_Data
[1] |= (Polarity
<< 4); /* V and H polarity */
2178 B_Data
[1] |= BIT_EN_DE_GEN
; /* enable DE generator */
2180 B_Data
[2] = V_StartPos
& SEVEN_LSBITS
; /* DE_TOP in 0x64 */
2181 B_Data
[3] = 0x00; /* 0x65 is reserved */
2182 B_Data
[4] = H_Res
& LOW_BYTE
; /* 8 LSBits of DE_CNT in 0x66 */
2183 B_Data
[5] = (H_Res
>> 8) & LOW_NIBBLE
; /* 4 MSBits of DE_CNT in 0x67 */
2184 B_Data
[6] = V_Res
& LOW_BYTE
; /* 8 LSBits of DE_LIN in 0x68 */
2185 B_Data
[7] = (V_Res
>> 8) & THREE_LSBITS
; /* 3 MSBits of DE_LIN in 0x69 */
2186 B_Data
[8] = Htotal
& LOW_BYTE
; /* 8 LSBits of H_RES in 0x6A */
2187 B_Data
[9] = (Htotal
>> 8) & LOW_NIBBLE
; /* 4 MSBITS of H_RES in 0x6B */
2188 B_Data
[10] = Vtotal
& LOW_BYTE
; /* 8 LSBits of V_RES in 0x6C */
2189 B_Data
[11] = (Vtotal
>> 8) & BITS_2_1_0
; /* 3 MSBITS of V_RES in 0x6D */
2191 WriteBlockTPI(0x62, 12, &B_Data
[0]);
2192 TPI_REG0x63_SAVED
= B_Data
[1];
2194 return DE_SET_OK
; /* Write completed successfully */
2197 /* ------------------------------------------------------------------------------ */
2198 /* Function Name: SetFormat() */
2199 /* Function Description: Set the 9022/4 format */
2202 /* Returns: DE_SET_OK */
2204 /* ------------------------------------------------------------------------------ */
2205 void SetFormat(byte
*Data
)
2207 ReadModifyWriteTPI(0x1A, OUTPUT_MODE_MASK
, OUTPUT_MODE_HDMI
); /* Set HDMI mode to allow color space conversion */
2209 WriteBlockTPI(0x09, 2, Data
); /* Program TPI AVI Input and Output Format */
2210 WriteByteTPI(0x19, 0x00); /* Set last byte of TPI AVI InfoFrame for TPI AVI I/O Format to take effect */
2212 if (!IsHDMI_Sink()) {
2213 ReadModifyWriteTPI(0x1A, OUTPUT_MODE_MASK
, OUTPUT_MODE_DVI
);
2216 if (siHdmiTx
.SyncMode
== EMBEDDED_SYNC
)
2217 EnableEmbeddedSync(); /* Last byte of TPI AVI InfoFrame resets Embedded Sync Extraction */
2220 /* ------------------------------------------------------------------------------ */
2221 /* Function Name: printVideoMode() */
2222 /* Function Description: print video mode */
2224 /* Accepts: siHdmiTx.VIC */
2227 /* ------------------------------------------------------------------------------ */
2228 void printVideoMode(void)
2230 TPI_TRACE_PRINT((">>Video mode = "));
2232 switch (siHdmiTx
.VIC
) {
2234 TPI_TRACE_PRINT(("HDMI_480I60_4X3\n"));
2237 TPI_TRACE_PRINT(("HDMI_576I50_4X3\n"));
2240 TPI_TRACE_PRINT(("HDMI_480P60_4X3\n"));
2243 TPI_TRACE_PRINT(("HDMI_576P50_4X3\n"));
2246 TPI_TRACE_PRINT(("HDMI_720P60\n"));
2249 TPI_TRACE_PRINT(("HDMI_720P50\n"));
2252 TPI_TRACE_PRINT(("HDMI_1080I60\n"));
2255 TPI_TRACE_PRINT(("HDMI_1080I50\n"));
2258 TPI_TRACE_PRINT(("HDMI_1080P60\n"));
2261 TPI_TRACE_PRINT(("HDMI_1080P50\n"));
2264 TPI_TRACE_PRINT(("HDMI_1024_768_60\n"));
2267 TPI_TRACE_PRINT(("HDMI_800_600_60\n"));
2274 /* ------------------------------------------------------------------------------ */
2275 /* Function Name: InitVideo() */
2276 /* Function Description: Set the 9022/4 to the video mode determined by GetVideoMode() */
2278 /* Accepts: Index of video mode to set; Flag that distinguishes between */
2279 /* calling this function after power up and after input */
2280 /* resolution change */
2282 /* Globals: VModesTable, VideoCommandImage */
2283 /* ------------------------------------------------------------------------------ */
2284 byte
InitVideo(byte TclkSel
)
2293 byte EMB_Status
; /* EmbeddedSync set flag */
2297 TPI_TRACE_PRINT((">>InitVideo()\n"));
2299 TPI_TRACE_PRINT((" HF:%d", (int)siHdmiTx
.HDMIVideoFormat
));
2300 TPI_TRACE_PRINT((" VIC:%d", (int)siHdmiTx
.VIC
));
2301 TPI_TRACE_PRINT((" A:%x", (int)siHdmiTx
.AspectRatio
));
2302 TPI_TRACE_PRINT((" CS:%x", (int)siHdmiTx
.ColorSpace
));
2303 TPI_TRACE_PRINT((" CD:%x", (int)siHdmiTx
.ColorDepth
));
2304 TPI_TRACE_PRINT((" CR:%x", (int)siHdmiTx
.Colorimetry
));
2305 TPI_TRACE_PRINT((" SM:%x", (int)siHdmiTx
.SyncMode
));
2306 TPI_TRACE_PRINT((" TCLK:%x", (int)siHdmiTx
.TclkSel
));
2307 TPI_TRACE_PRINT((" 3D:%d", (int)siHdmiTx
.ThreeDStructure
));
2308 TPI_TRACE_PRINT((" 3Dx:%d\n", (int)siHdmiTx
.ThreeDExtData
));
2310 ModeTblIndex
= (byte
) ConvertVIC_To_VM_Index();
2312 Pattern
= (TclkSel
<< 6) & TWO_MSBITS
; /* Use TPI 0x08[7:6] for 9022A/24A video clock multiplier */
2313 ReadSetWriteTPI(0x08, Pattern
); /* TClkSel1:Ratio of output TMDS clock to input video clock,00-x0.5,01- x1 (default),10 -x2,11-x4 */
2315 /* Take values from VModesTable[]: */
2316 if ((siHdmiTx
.VIC
== 6) || (siHdmiTx
.VIC
== 7) || /* 480i */
2317 (siHdmiTx
.VIC
== 21) || (siHdmiTx
.VIC
== 22)) /* 576i */
2319 if (siHdmiTx
.ColorSpace
== YCBCR422_8BITS
) /* 27Mhz pixel clock */
2321 B_Data
[0] = VModesTable
[ModeTblIndex
].PixClk
& 0x00FF;
2322 B_Data
[1] = (VModesTable
[ModeTblIndex
].PixClk
>> 8) & 0xFF;
2323 } else /* 13.5Mhz pixel clock */
2325 B_Data
[0] = (VModesTable
[ModeTblIndex
].PixClk
/ 2) & 0x00FF;
2326 B_Data
[1] = ((VModesTable
[ModeTblIndex
].PixClk
/ 2) >> 8) & 0xFF;
2330 B_Data
[0] = VModesTable
[ModeTblIndex
].PixClk
& 0x00FF; /* write Pixel clock to TPI registers 0x00, 0x01 */
2331 B_Data
[1] = (VModesTable
[ModeTblIndex
].PixClk
>> 8) & 0xFF;
2334 B_Data
[2] = VModesTable
[ModeTblIndex
].Tag
.VFreq
& 0x00FF; /* write Vertical Frequency to TPI registers 0x02, 0x03 */
2335 B_Data
[3] = (VModesTable
[ModeTblIndex
].Tag
.VFreq
>> 8) & 0xFF;
2337 if ((siHdmiTx
.VIC
== 6) || (siHdmiTx
.VIC
== 7) || /* 480i */
2338 (siHdmiTx
.VIC
== 21) || (siHdmiTx
.VIC
== 22)) /* 576i */
2340 B_Data
[4] = (VModesTable
[ModeTblIndex
].Tag
.Total
.Pixels
/ 2) & 0x00FF; /* write total number of pixels to TPI registers 0x04, 0x05 */
2341 B_Data
[5] = ((VModesTable
[ModeTblIndex
].Tag
.Total
.Pixels
/ 2) >> 8) & 0xFF;
2343 B_Data
[4] = VModesTable
[ModeTblIndex
].Tag
.Total
.Pixels
& 0x00FF; /* write total number of pixels to TPI registers 0x04, 0x05 */
2344 B_Data
[5] = (VModesTable
[ModeTblIndex
].Tag
.Total
.Pixels
>> 8) & 0xFF;
2347 B_Data
[6] = VModesTable
[ModeTblIndex
].Tag
.Total
.Lines
& 0x00FF; /* write total number of lines to TPI registers 0x06, 0x07 */
2348 B_Data
[7] = (VModesTable
[ModeTblIndex
].Tag
.Total
.Lines
>> 8) & 0xFF;
2350 WriteBlockTPI(0x00, 8, B_Data
); /* Write TPI Mode data.//0x00-0x07 :Video Mode Defines the incoming resolution */
2352 /* TPI Input Bus and Pixel Repetition Data */
2353 /* B_Data[0] = Reg0x08; */
2354 B_Data
[0] = 0; /* Set to default 0 for use again */
2355 /* B_Data[0] = (VModesTable[ModeTblIndex].PixRep) & LOW_BYTE; // Set pixel replication field of 0x08 */
2356 B_Data
[0] |= BIT_BUS_12
; /* Set 24 bit bus:Input Bus Select. The input data bus can be either one pixel wide or 1/2 pixel wide. The bit defaults to 1 to select full pixel mode. In 1/2 pixel mode, the full pixel is brought in on two successive clock edges (one rising, one falling). */
2357 /* All parts support 24-bit full-pixel and 12-bit half-pixel input modes. */
2358 B_Data
[0] |= (TclkSel
<< 6) & TWO_MSBITS
;
2360 #ifdef CLOCK_EDGE_FALLING
2361 B_Data
[0] &= ~BIT_EDGE_RISE
; /* Set to falling edge */
2363 #ifdef CLOCK_EDGE_RISING
2364 B_Data
[0] |= BIT_EDGE_RISE
; /* Set to rising edge */
2366 tpivmode
[0] = B_Data
[0]; /* saved TPI Reg0x08 value. */
2367 WriteByteTPI(0x08, B_Data
[0]); /* 0x08 */
2369 /* TPI AVI Input and Output Format Data */
2370 /* B_Data[0] = Reg0x09; */
2371 /* B_Data[1] = Reg0x0A; */
2372 B_Data
[0] = 0; /* Set to default 0 for use again */
2373 B_Data
[1] = 0; /* Set to default 0 for use again */
2375 if (siHdmiTx
.SyncMode
== EMBEDDED_SYNC
) {
2376 EMB_Status
= SetEmbeddedSync();
2377 EnableEmbeddedSync(); /* enablle EmbeddedSync */
2380 if (siHdmiTx
.SyncMode
== INTERNAL_DE
) {
2381 ReadClearWriteTPI(0x60, MSBIT
); /* set 0x60[7] = 0 for External Sync */
2382 DE_Status
= SetDE(); /* Call SetDE() with Video Mode as a parameter */
2385 if (siHdmiTx
.ColorSpace
== RGB
)
2386 B_Data
[0] = (((BITS_IN_RGB
| BITS_IN_AUTO_RANGE
) & ~BIT_EN_DITHER_10_8
) & ~BIT_EXTENDED_MODE
); /* reg0x09 */
2388 else if (siHdmiTx
.ColorSpace
== YCBCR444
)
2389 B_Data
[0] = (((BITS_IN_YCBCR444
| BITS_IN_AUTO_RANGE
) & ~BIT_EN_DITHER_10_8
) & ~BIT_EXTENDED_MODE
); /* 0x09 */
2391 else if ((siHdmiTx
.ColorSpace
== YCBCR422_16BITS
)
2392 || (siHdmiTx
.ColorSpace
== YCBCR422_8BITS
))
2393 B_Data
[0] = (((BITS_IN_YCBCR422
| BITS_IN_AUTO_RANGE
) & ~BIT_EN_DITHER_10_8
) & ~BIT_EXTENDED_MODE
); /* 0x09 */
2396 switch (siHdmiTx
.ColorDepth
) {
2399 ReadModifyWriteTPI(0x40, BIT_2
, 0x00);
2403 ReadModifyWriteTPI(0x40, BIT_2
, BIT_2
);
2407 ReadModifyWriteTPI(0x40, BIT_2
, BIT_2
);
2411 ReadModifyWriteTPI(0x40, BIT_2
, BIT_2
);
2415 ReadModifyWriteTPI(0x40, BIT_2
, 0x00);
2417 /* General Control Packet ¨C Deep color settings require the General Control Packet to be sent once per video field */
2418 /* with the correct PP and CD information. This must be enabled by software via TPI Deep Color Packet Enable */
2419 /* Register 0x40[2] = 1, enable transmission of the GCP packet. */
2421 B_Data
[0] = ((B_Data
[0] & 0x3F) | temp
); /* reg0x09 */
2424 B_Data
[1] = (BITS_OUT_RGB
| BITS_OUT_AUTO_RANGE
); /* Reg0x0A */
2426 if ((siHdmiTx
.VIC
== 6) || (siHdmiTx
.VIC
== 7) || /* 480i */
2427 (siHdmiTx
.VIC
== 21) || (siHdmiTx
.VIC
== 22) || /* 576i */
2428 (siHdmiTx
.VIC
== 2) || (siHdmiTx
.VIC
== 3) || /* 480p */
2429 (siHdmiTx
.VIC
== 17) || (siHdmiTx
.VIC
== 18)) /* 576p */
2431 B_Data
[1] &= ~BIT_BT_709
;
2433 B_Data
[1] |= BIT_BT_709
;
2437 B_Data
[1] = ((B_Data
[1] & 0x3F) | temp
);
2440 #ifdef DEV_SUPPORT_EDID
2441 if (!IsHDMI_Sink()) {
2442 B_Data
[1] = ((B_Data
[1] & 0xFC) | BITS_OUT_RGB
);
2444 /* Set YCbCr color space depending on EDID */
2445 if (g_edid
.YCbCr_4_4_4
) {
2446 B_Data
[1] = ((B_Data
[1] & 0xFC) | BITS_OUT_YCBCR444
);
2448 if (g_edid
.YCbCr_4_2_2
) {
2449 B_Data
[1] = ((B_Data
[1] & 0xFC) | BITS_OUT_YCBCR422
);
2451 B_Data
[1] = ((B_Data
[1] & 0xFC) | BITS_OUT_RGB
);
2457 tpivmode
[1] = B_Data
[0]; /* saved TPI Reg0x09 value. */
2458 tpivmode
[2] = B_Data
[1]; /* saved TPI Reg0x0A value. */
2461 ReadClearWriteTPI(0x60, BIT_2
); /* Number HSync pulses from VSync active edge to Video Data Period should be 20 (VS_TO_VIDEO) */
2466 /* ------------------------------------------------------------------------------ */
2467 /* Function Name: SetAVI_InfoFrames() */
2468 /* Function Description: Load AVI InfoFrame data into registers and send to sink */
2470 /* Accepts: An API_Cmd parameter that holds the data to be sent in the InfoFrames */
2474 /* Note: : Infoframe contents are from spec CEA-861-D */
2476 /* ------------------------------------------------------------------------------ */
2477 byte
SetAVI_InfoFrames(void)
2479 byte B_Data
[SIZE_AVI_INFOFRAME
];
2484 TPI_TRACE_PRINT((">>SetAVI_InfoFrames()\n"));
2486 for (i
= 0; i
< SIZE_AVI_INFOFRAME
; i
++)
2489 #ifdef DEV_SUPPORT_EDID
2490 if (g_edid
.YCbCr_4_4_4
)
2492 else if (g_edid
.YCbCr_4_2_2
)
2500 B_Data
[1] = (TmpVal
<< 5) & BITS_OUT_FORMAT
; /* AVI Byte1: Y1Y0 (output format) */
2501 B_Data
[1] |= 0x12; /* A0 = 1; Active format identification data is present in the AVI InfoFrame. // S1:S0 = 01; Overscanned (television). */
2502 /* S1:S0 = 10; Underscanned */
2504 if (siHdmiTx
.ColorSpace
== XVYCC444
) /* Extended colorimetry - xvYCC */
2506 B_Data
[2] = 0xC0; /* Extended colorimetry info (B_Data[3] valid (CEA-861D, Table 11) */
2508 if (siHdmiTx
.Colorimetry
== COLORIMETRY_601
) /* xvYCC601 */
2509 B_Data
[3] &= ~BITS_6_5_4
;
2511 else if (siHdmiTx
.Colorimetry
== COLORIMETRY_709
) /* xvYCC709 */
2512 B_Data
[3] = (B_Data
[3] & ~BITS_6_5_4
) | BIT_4
;
2515 else if (siHdmiTx
.Colorimetry
== COLORIMETRY_709
) /* BT.709 */
2516 B_Data
[2] = 0x80; /* AVI Byte2: C1C0 */
2518 else if (siHdmiTx
.Colorimetry
== COLORIMETRY_601
) /* BT.601 */
2519 B_Data
[2] = 0x40; /* AVI Byte2: C1C0 */
2521 else /* Carries no data */
2522 { /* AVI Byte2: C1C0 */
2523 B_Data
[2] &= ~BITS_7_6
; /* colorimetry = 0 */
2524 B_Data
[3] &= ~BITS_6_5_4
; /* Extended colorimetry = 0 */
2527 VModeTblIndex
= ConvertVIC_To_VM_Index();
2529 B_Data
[4] = siHdmiTx
.VIC
;
2531 /* Set the Aspect Ration info into the Infoframe Byte 2 */
2532 if (siHdmiTx
.AspectRatio
== VMD_ASPECT_RATIO_16x9
) {
2533 B_Data
[2] |= _16_To_9
; /* AVI Byte2: M1M0 */
2534 /* If the Video Mode table says this mode can be 4x3 OR 16x9, and we are pointing to the */
2535 /* table entry that is 4x3, then we bump to the next Video Table entry which will be for 16x9. */
2536 if ((VModesTable
[VModeTblIndex
].AspectRatio
== R_4or16
)
2537 && (AspectRatioTable
[siHdmiTx
.VIC
- 1] == R_4
)) {
2542 B_Data
[2] |= _4_To_3
; /* AVI Byte4: VIC */
2545 B_Data
[2] |= SAME_AS_AR
; /* AVI Byte2: R3..R1 - Set to "Same as Picture Aspect Ratio" */
2546 B_Data
[5] = VModesTable
[VModeTblIndex
].PixRep
; /* AVI Byte5: Pixel Replication - PR3..PR0 */
2548 /* Calculate AVI InfoFrame ChecKsum */
2549 B_Data
[0] = 0x82 + 0x02 + 0x0D;
2550 for (i
= 1; i
< SIZE_AVI_INFOFRAME
; i
++) {
2551 B_Data
[0] += B_Data
[i
];
2553 B_Data
[0] = 0x100 - B_Data
[0];
2555 /* Write the Inforframe data to the TPI Infoframe registers */
2556 WriteBlockTPI(0x0C, SIZE_AVI_INFOFRAME
, B_Data
);
2558 if (siHdmiTx
.SyncMode
== EMBEDDED_SYNC
)
2559 EnableEmbeddedSync();
2564 extern void siHdmiTx_PowerStateD0(void);
2565 extern void SetAudioMute(byte audioMute
);
2566 /* ------------------------------------------------------------------------------ */
2567 /* Function Name: siHdmiTx_Init() */
2568 /* Function Description: Set the 9022/4 video and video. */
2572 /* Globals: siHdmiTx */
2573 /* ------------------------------------------------------------------------------ */
2574 void siHdmiTx_Init(void)
2576 TPI_TRACE_PRINT((">>siHdmiTx_Init()\n"));
2578 /* workaround for Bug#18128 */
2579 if (siHdmiTx
.ColorDepth
== VMD_COLOR_DEPTH_8BIT
) {
2580 /* Yes it is, so force 16bpps first! */
2581 siHdmiTx
.ColorDepth
= VMD_COLOR_DEPTH_16BIT
;
2582 InitVideo(siHdmiTx
.TclkSel
);
2583 /* Now put it back to 8bit and go do the expected InitVideo() call */
2584 siHdmiTx
.ColorDepth
= VMD_COLOR_DEPTH_8BIT
;
2586 /* end workaround */
2588 InitVideo(siHdmiTx
.TclkSel
); /* Set PLL Multiplier to x1 upon power up */
2590 siHdmiTx_PowerStateD0();
2592 if (IsHDMI_Sink()) /* Set InfoFrames only if HDMI output mode */
2594 SetAVI_InfoFrames();
2595 siHdmiTx_AudioSet(); /* set audio interface to basic audio (an external command is needed to set to any other mode */
2597 SetAudioMute(AUDIO_MUTE_MUTED
);
2600 /* !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! */
2601 /* PATCH!!!PATCH!!!PATCH!!!PATCH!!!PATCH!!!PATCH!!!PATCH!!!PATCH!!!PATCH!!!PATCH!!!PATCH!!!PATCH!!! */
2603 /* THIS PATCH IS NEEDED BECAUSE SETTING UP AVI InfoFrames CLEARS 0x63 and 0x60[5] */
2604 if (siHdmiTx
.ColorSpace
== YCBCR422_8BITS
)
2605 ReadSetWriteTPI(0x60, BIT_5
); /* Set 0x60[5] according to input color space. */
2607 /* THIS PATCH IS NEEDED BECAUSE SETTING UP AVI InfoFrames CLEARS 0x63 */
2608 WriteByteTPI(0x63, TPI_REG0x63_SAVED
);
2610 /* PATCH!!!PATCH!!!PATCH!!!PATCH!!!PATCH!!!PATCH!!!PATCH!!!PATCH!!!PATCH!!!PATCH!!!PATCH!!!PATCH!!! */
2611 /* !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! */
2613 /* ========================================================== */
2614 WriteByteTPI(0x0B, 0x00);
2617 if ((g_hdcp
.HDCP_TxSupports
== TRUE
) && (g_hdcp
.HDCPAuthenticated
== VMD_HDCP_AUTHENTICATED
)
2618 && (Sii9024A_HDCP_supported
)) {
2619 if (g_hdcp
.HDCP_AksvValid
== TRUE
) {
2621 TPI_DEBUG_PRINT(("TMDS -> Enabled (Video Muted)\n"));
2622 ReadModifyWriteTPI(0x1A,
2623 LINK_INTEGRITY_MODE_MASK
| TMDS_OUTPUT_CONTROL_MASK
|
2625 LINK_INTEGRITY_DYNAMIC
| TMDS_OUTPUT_CONTROL_ACTIVE
|
2628 WriteByteTPI(0x08, tpivmode
[0]); /* Write register 0x08 */
2629 g_sys
.tmdsPoweredUp
= TRUE
;
2630 EnableInterrupts(HOT_PLUG_EVENT
| RX_SENSE_EVENT
| AUDIO_ERROR_EVENT
|
2631 SECURITY_CHANGE_EVENT
| HDCP_CHANGE_EVENT
);
2634 TPI_DEBUG_PRINT(("TMDS -> Enabled\n"));
2635 ReadModifyWriteTPI(0x1A,
2636 LINK_INTEGRITY_MODE_MASK
| TMDS_OUTPUT_CONTROL_MASK
|
2638 LINK_INTEGRITY_DYNAMIC
| TMDS_OUTPUT_CONTROL_ACTIVE
|
2640 ReadModifyWriteTPI(0x1A, AV_MUTE_MASK
, AV_MUTE_NORMAL
);
2641 WriteByteTPI(0x08, tpivmode
[0]); /* Write register 0x08 */
2642 g_sys
.tmdsPoweredUp
= TRUE
;
2643 EnableInterrupts(HOT_PLUG_EVENT
| RX_SENSE_EVENT
| AUDIO_ERROR_EVENT
);
2647 /* ------------------------------------------------------------------------------ */
2648 /* Function Name: siHdmiTx_VideoSet() */
2649 /* Function Description: Set the 9022/4 video resolution */
2652 /* Returns: Success message if video resolution changed successfully. */
2653 /* Error Code if resolution change failed */
2654 /* Globals: siHdmiTx */
2655 /* ------------------------------------------------------------------------------ */
2656 /* ============================================================ */
2657 #define T_RES_CHANGE_DELAY 128 /* delay between turning TMDS bus off and changing output resolution */
2659 byte
siHdmiTx_VideoSet(void)
2661 TPI_TRACE_PRINT((">>siHdmiTx_VideoSet()\n"));
2663 ReadModifyWriteTPI(0x1A, TMDS_OUTPUT_CONTROL_MASK
| AV_MUTE_MASK
,
2664 TMDS_OUTPUT_CONTROL_POWER_DOWN
| AV_MUTE_MUTED
);
2666 // Note: this's necessary for fixing 480i_13.5MHz to 1080p_148.5MHz no display issue.
2667 //siHdmiTx_TPI_Init();
2668 g_sys
.hdmiCableConnected
= TRUE
;
2669 g_sys
.dsRxPoweredUp
= TRUE
;
2672 #ifdef DEV_SUPPORT_HDCP
2676 DisableTMDS(); // turn off TMDS output
2677 DelayMS(T_RES_CHANGE_DELAY); // allow control InfoFrames to pass through to the sink device.
2681 if (Sii9024A_HDCP_supported
){
2683 HDCP_CheckStatus(ReadByteTPI(0x3D));
2686 return VIDEO_MODE_SET_OK
;
2689 /* ------------------------------------------------------------------------------ */
2690 /* Function Name: SetAudioInfoFrames() */
2691 /* Function Description: Load Audio InfoFrame data into registers and send to sink */
2693 /* Accepts: (1) Channel count */
2694 /* (2) speaker configuration per CEA-861D Tables 19, 20 */
2695 /* (3) Coding type: 0x09 for DSD Audio. 0 (refer to stream header) for all the rest */
2696 /* (4) Sample Frequency. Non zero for HBR only */
2697 /* (5) Audio Sample Length. Non zero for HBR only. */
2700 /* ------------------------------------------------------------------------------ */
2701 byte
SetAudioInfoFrames(byte ChannelCount
, byte CodingType
, byte SS
, byte Fs
, byte SpeakerConfig
)
2703 byte B_Data
[SIZE_AUDIO_INFOFRAME
]; /* 14 */
2705 /* byte TmpVal = 0; */
2707 TPI_TRACE_PRINT((">>SetAudioInfoFrames()\n"));
2709 for (i
= 0; i
< SIZE_AUDIO_INFOFRAME
; i
++)
2712 WriteByteTPI(MISC_INFO_FRAMES_CTRL
, DISABLE_AUDIO
); /* Disbale MPEG/Vendor Specific InfoFrames */
2714 B_Data
[0] = TYPE_AUDIO_INFOFRAMES
; /* 0x84 */
2715 B_Data
[1] = AUDIO_INFOFRAMES_VERSION
; /* 0x01 */
2716 B_Data
[2] = AUDIO_INFOFRAMES_LENGTH
; /* 0x0A */
2717 B_Data
[3] = TYPE_AUDIO_INFOFRAMES
+ /* Calculate checksum - 0x84 + 0x01 + 0x0A */
2718 AUDIO_INFOFRAMES_VERSION
+ AUDIO_INFOFRAMES_LENGTH
;
2720 B_Data
[4] = ChannelCount
; /* 0 for "Refer to Stream Header" or for 2 Channels. 0x07 for 8 Channels */
2721 B_Data
[4] |= (CodingType
<< 4); /* 0xC7[7:4] == 0b1001 for DSD Audio */
2723 B_Data
[5] = ((Fs
& THREE_LSBITS
) << 2) | (SS
& TWO_LSBITS
);
2725 B_Data
[7] = SpeakerConfig
;
2727 for (i
= 4; i
< SIZE_AUDIO_INFOFRAME
; i
++)
2728 B_Data
[3] += B_Data
[i
];
2730 B_Data
[3] = 0x100 - B_Data
[3];
2732 WriteByteTPI(MISC_INFO_FRAMES_CTRL
, EN_AND_RPT_AUDIO
); /* Re-enable Audio InfoFrame transmission and repeat */
2734 WriteBlockTPI(MISC_INFO_FRAMES_TYPE
, SIZE_AUDIO_INFOFRAME
, B_Data
);
2736 if (siHdmiTx
.SyncMode
== EMBEDDED_SYNC
)
2737 EnableEmbeddedSync();
2742 /* ------------------------------------------------------------------------------ */
2743 /* Function Name: SetAudioMute() */
2744 /* Function Description: Mute audio */
2746 /* Accepts: Mute or unmute. */
2749 /* ------------------------------------------------------------------------------ */
2750 void SetAudioMute(byte audioMute
)
2752 ReadModifyWriteTPI(0x26, AUDIO_MUTE_MASK
, audioMute
);
2755 #ifndef F_9022A_9334
2756 /* ------------------------------------------------------------------------------ */
2757 /* Function Name: SetChannelLayout() */
2758 /* Function Description: Set up the Channel layout field of internal register 0x2F (0x2F[1]) */
2760 /* Accepts: Number of audio channels: "0 for 2-Channels ."1" for 8. */
2763 /* ------------------------------------------------------------------------------ */
2764 void SetChannelLayout(byte Count
)
2766 /* Indexed register 0x7A:0x2F[1]: */
2767 WriteByteTPI(0xBC, 0x02); /* Internal page 2 */
2768 WriteByteTPI(0xBD, 0x2F);
2770 Count
&= THREE_LSBITS
;
2772 if (Count
== TWO_CHANNEL_LAYOUT
) {
2773 /* Clear 0x2F[1]: */
2774 ReadClearWriteTPI(0xBE, BIT_1
);
2777 else if (Count
== EIGHT_CHANNEL_LAYOUT
) {
2779 ReadSetWriteTPI(0xBE, BIT_1
);
2784 /* ------------------------------------------------------------------------------ */
2785 /* Function Name: siHdmiTx_AudioSet() */
2786 /* Function Description: Set the 9022/4 audio interface to basic audio. */
2789 /* Returns: Success message if audio changed successfully. */
2790 /* Error Code if resolution change failed */
2791 /* Globals: siHdmiTx */
2792 /* ------------------------------------------------------------------------------ */
2793 byte
siHdmiTx_AudioSet(void)
2795 TPI_TRACE_PRINT((">>siHdmiTx_AudioSet()\n"));
2797 SetAudioMute(AUDIO_MUTE_MUTED
); /* mute output */
2799 if (siHdmiTx
.AudioMode
== AMODE_I2S
) /* I2S input */
2801 ReadModifyWriteTPI(0x26, AUDIO_SEL_MASK
, AUD_IF_I2S
); /* 0x26 = 0x80 */
2802 WriteByteTPI(0x25, 0x08 | AUD_DO_NOT_CHECK
); /* 0x25 */
2803 } else /* SPDIF input */
2805 ReadModifyWriteTPI(0x26, AUDIO_SEL_MASK
, AUD_IF_SPDIF
); /* 0x26 = 0x40 */
2806 WriteByteTPI(0x25, AUD_PASS_BASIC
); /* 0x25 = 0x00 */
2809 #ifndef F_9022A_9334
2810 if (siHdmiTx
.AudioChannels
== ACHANNEL_2CH
)
2811 SetChannelLayout(TWO_CHANNELS
); /* Always 2 channesl in S/PDIF */
2813 SetChannelLayout(EIGHT_CHANNELS
);
2815 if (siHdmiTx
.AudioChannels
== ACHANNEL_2CH
)
2816 ReadClearWriteTPI(0x26, BIT_5
); /* Use TPI 0x26[5] for 9022A/24A and 9334 channel layout */
2818 ReadSetWriteTPI(0x26, BIT_5
); /* Use TPI 0x26[5] for 9022A/24A and 9334 channel layout */
2821 if (siHdmiTx
.AudioMode
== AMODE_I2S
) /* I2S input */
2823 /* I2S - Map channels - replace with call to API MAPI2S */
2824 WriteByteTPI(0x1F, 0x80); /* 0x1F */
2826 if (siHdmiTx
.AudioChannels
> ACHANNEL_2CH
)
2827 WriteByteTPI(0x1F, 0x91);
2829 if (siHdmiTx
.AudioChannels
> ACHANNEL_4CH
)
2830 WriteByteTPI(0x1F, 0xA2);
2832 if (siHdmiTx
.AudioChannels
> ACHANNEL_6CH
)
2833 WriteByteTPI(0x1F, 0xB3);
2835 /* I2S - Stream Header Settings - replace with call to API SetI2S_StreamHeader */
2836 WriteByteTPI(0x21, 0x00); /* 0x21 */
2837 WriteByteTPI(0x22, 0x00);
2838 WriteByteTPI(0x23, 0x00);
2839 WriteByteTPI(0x24, siHdmiTx
.AudioFs
);
2840 WriteByteTPI(0x25, (siHdmiTx
.AudioFs
<< 4) | siHdmiTx
.AudioWordLength
);
2842 /* Oscar 20100929 added for 16bit auido noise issue */
2843 WriteIndexedRegister(INDEXED_PAGE_1
, 0x25, siHdmiTx
.AudioWordLength
);
2845 /* I2S - Input Configuration */
2846 WriteByteTPI(0x20, siHdmiTx
.AudioI2SFormat
); /* TPI_Reg0x20 */
2849 WriteByteTPI(0x27, REFER_TO_STREAM_HDR
);
2850 SetAudioInfoFrames(siHdmiTx
.AudioChannels
& THREE_LSBITS
, REFER_TO_STREAM_HDR
,
2851 REFER_TO_STREAM_HDR
, REFER_TO_STREAM_HDR
, 0x00);
2853 SetAudioMute(AUDIO_MUTE_NORMAL
); /* unmute output */
2855 return AUDIO_MODE_SET_OK
;
2859 /* ------------------------------------------------------------------------------ */
2860 /* Function Name: SetGBD_InfoFrame() */
2861 /* Function Description: Sets and sends the the 9022A/4A GBD InfoFrames. */
2864 /* Returns: Success message if GBD packet set successfully. Error */
2865 /* Code if failed */
2867 /* NOTE: Currently this function is a place holder. It always returns a Success message */
2868 /* ------------------------------------------------------------------------------ */
2869 byte
SetGBD_InfoFrame(void)
2873 TPI_TRACE_PRINT((">>SetGBD_InfoFrame()\n"));
2875 /* Set MPEG InfoFrame Header to GBD InfoFrame Header values: */
2876 WriteByteTPI(MISC_INFO_FRAMES_CTRL
, DISABLE_MPEG
); /* 0xBF = Use MPEG InfoFrame for GBD - 0x03 */
2877 WriteByteTPI(MISC_INFO_FRAMES_TYPE
, TYPE_GBD_INFOFRAME
); /* 0xC0 = 0x0A */
2878 WriteByteTPI(MISC_INFO_FRAMES_VER
, NEXT_FIELD
| GBD_PROFILE
| AFFECTED_GAMUT_SEQ_NUM
); /* 0x0C1 = 0x81 */
2879 WriteByteTPI(MISC_INFO_FRAMES_LEN
, ONLY_PACKET
| CURRENT_GAMUT_SEQ_NUM
); /* 0x0C2 = 0x31 */
2881 CheckSum
= TYPE_GBD_INFOFRAME
+
2882 NEXT_FIELD
+ GBD_PROFILE
+ AFFECTED_GAMUT_SEQ_NUM
+ ONLY_PACKET
+ CURRENT_GAMUT_SEQ_NUM
;
2884 CheckSum
= 0x100 - CheckSum
;
2886 WriteByteTPI(MISC_INFO_FRAMES_CTRL
, EN_AND_RPT_MPEG
); /* Enable and Repeat MPEG InfoFrames */
2887 WriteByteTPI(MISC_INFO_FRAMES_CHKSUM
, CheckSum
); /* 0X00 - Send header only */
2889 return GBD_SET_SUCCESSFULLY
;
2893 #ifdef DEV_SUPPORT_3D
2894 /* ------------------------------------------------------------------------------ */
2895 /* Function Name: Set_VSIF() */
2896 /* Function Description: Construct Vendor Specific InfoFrame for 3D support. use MPEG InfoFrame */
2900 /* Globals: siHdmiTx */
2901 /* ------------------------------------------------------------------------------ */
2902 /* VSIF Constants */
2903 /* ============================================================ */
2904 #define VSIF_TYPE 0x81
2905 #define VSIF_VERSION 0x01
2906 #define VSIF_LEN 0x06
2911 byte Data
[SIZE_MPEG_INFOFRAME
]; /* 10 */
2913 for (i
= 0; i
< SIZE_MPEG_INFOFRAME
; i
++) {
2917 /* Disable transmission of VSIF during re-configuration */
2918 WriteByteTPI(MISC_INFO_FRAMES_CTRL
, DISABLE_MPEG
);
2921 Data
[0] = VSIF_TYPE
; /* HB0 Packet Type 0x81 */
2922 Data
[1] = VSIF_VERSION
; /* HB1 Version = 0x01 */
2924 /* PB1 - PB3 contain the 24bit IEEE Registration Identifier */
2925 Data
[4] = 0x03; /* HDMI Signature LS Byte */
2926 Data
[5] = 0x0C; /* HDMI Signature middle byte */
2927 Data
[6] = 0x00; /* HDMI Signature MS Byte */
2929 /* PB4 - HDMI_Video_Format into bits 7:5 */
2930 Data
[7] = siHdmiTx
.HDMIVideoFormat
<< 5;
2932 /* PB5 - Depending on the video format, this byte will contain either the HDMI_VIC */
2933 /* code in buts 7:0, OR the 3D_Structure in bits 7:4. */
2934 switch (siHdmiTx
.HDMIVideoFormat
) {
2935 case VMD_HDMIFORMAT_HDMI_VIC
:
2936 /* This is a 2x4K mode, set the HDMI_VIC in buts 7:0. Values */
2937 /* are from HDMI 1.4 Spec, 8.2.3.1 (Table 8-13). */
2938 Data
[8] = siHdmiTx
.VIC
;
2942 case VMD_HDMIFORMAT_3D
:
2943 /* This is a 3D mode, set the 3D_Structure in buts 7:4 */
2944 /* Bits 3:0 are reseved so set to 0. Values are from HDMI 1.4 */
2945 /* Spec, Appendix H (Table H-2). */
2946 Data
[8] = siHdmiTx
.ThreeDStructure
<< 4;
2947 /* Add the Extended data field when the 3D format is Side-by-Side(Half). */
2948 /* See Spec Table H-3 for details. */
2949 if ((Data
[8] >> 4) == VMD_3D_SIDEBYSIDEHALF
) {
2951 Data
[9] = siHdmiTx
.ThreeDExtData
<< 4;
2953 Data
[2] = VSIF_LEN
- 1;
2957 case VMD_HDMIFORMAT_CEA_VIC
:
2965 Data
[3] = VSIF_TYPE
+ /* PB0 partial checksum */
2966 VSIF_VERSION
+ Data
[2];
2968 /* Complete the checksum with PB1 through PB7 */
2969 for (i
= 4; i
< SIZE_MPEG_INFOFRAME
; i
++) {
2972 /* Data[3] %= 0x100; */
2973 Data
[3] = 0x100 - Data
[3]; /* Final checksum */
2975 WriteByteTPI(MISC_INFO_FRAMES_CTRL
, EN_AND_RPT_MPEG
); /* Enable and Repeat MPEG/Vendor Specific InfoFrames */
2977 WriteBlockTPI(MISC_INFO_FRAMES_TYPE
, SIZE_MPEG_INFOFRAME
, Data
); /* Write VSIF to MPEG registers and start transmission */
2978 WriteByteTPI(0xDE, 0x00); /* Set last byte of MPEG InfoFrame for data to be sent to sink. */
2985 /* ///////////////////////////////////////////////////////////////////////////// */
2986 /* ///////////////////////////////////////////////////////////////////////////// */
2987 /* /////////////////////*************************/////////////////////////////// */
2988 /* ///////////////////// TPI /////////////////////////////// */
2989 /* /////////////////////*************************/////////////////////////////// */
2990 /* ///////////////////////////////////////////////////////////////////////////// */
2991 /* ///////////////////////////////////////////////////////////////////////////// */
2994 /* ------------------------------------------------------------------------------ */
2995 /* Function Name: StartTPI() */
2996 /* Function Description: Start HW TPI mode by writing 0x00 to TPI address 0xC7. */
2999 /* Returns: TRUE if HW TPI started successfully. FALSE if failed to. */
3001 /* ------------------------------------------------------------------------------ */
3007 TPI_TRACE_PRINT((">>StartTPI()\n"));
3009 WriteByteTPI(0xC7, 0x00); /* Write "0" to 72:C7 to start HW TPI mode */
3013 devID
= ReadIndexedRegister(INDEXED_PAGE_0
, 0x03);
3016 devID
= ReadIndexedRegister(INDEXED_PAGE_0
, 0x02);
3019 devID
= ReadByteTPI(0x1B);
3021 TPI_TRACE_PRINT(("0x%04X\n", (int)wID
));
3022 TPI_TRACE_PRINT(("%s:%d:devID=0x%04x\n", __func__
, __LINE__
, devID
));
3023 Sii9024A_HDCP_supported
= true;
3026 Sii9024A_HDCP_supported
= false;
3027 if (devID
== SII902XA_DEVICE_ID
)
3030 TPI_TRACE_PRINT(("Unsupported TX, devID = 0x%X\n", (int)devID
));
3034 /* ------------------------------------------------------------------------------ */
3035 /* Function Name: siHdmiTx_TPI_Init() */
3036 /* Function Description: TPI initialization: HW Reset, Interrupt enable. */
3039 /* Returns: TRUE or FLASE */
3041 /* ------------------------------------------------------------------------------ */
3042 byte
siHdmiTx_TPI_Init(void)
3044 TPI_TRACE_PRINT(("\n>>siHdmiTx_TPI_Init()\n"));
3045 TPI_TRACE_PRINT(("\n%s\n", TPI_FW_VERSION
));
3047 /* Chip powers up in D2 mode. */
3048 g_sys
.txPowerState
= TX_POWER_STATE_D0
;
3050 InitializeStateVariables();
3052 /* Toggle TX reset pin */
3054 WriteByteTPI(0xF5, 0x00);
3055 /* Enable HW TPI mode, check device ID */
3057 if (Sii9024A_HDCP_supported
) {
3058 TPI_DEBUG_PRINT(("siHdmiTx_TPI_Init,Sii9024A_HDCP_supported\n"));
3059 g_hdcp
.HDCP_Override
= FALSE
;
3060 g_hdcp
.HDCPAuthenticated
= VMD_HDCP_AUTHENTICATED
;
3063 #ifdef DEV_SUPPORT_CEC
3067 EnableInterrupts(HOT_PLUG_EVENT
);
3075 /* ------------------------------------------------------------------------------ */
3076 /* Function Name: OnDownstreamRxPoweredDown() */
3077 /* Function Description: HDMI cable unplug handle. */
3082 /* ------------------------------------------------------------------------------ */
3083 void OnDownstreamRxPoweredDown(void)
3085 TPI_DEBUG_PRINT(("DSRX -> Powered Down\n"));
3086 g_sys
.dsRxPoweredUp
= FALSE
;
3088 if (g_hdcp
.HDCP_Started
== TRUE
&& Sii9024A_HDCP_supported
)
3091 ReadModifyWriteTPI(0x1A, OUTPUT_MODE_MASK
, OUTPUT_MODE_DVI
); /* Set to DVI output mode to reset HDCP */
3094 extern void HotPlugService(void);
3095 /* ------------------------------------------------------------------------------ */
3096 /* Function Name: OnDownstreamRxPoweredUp() */
3097 /* Function Description: DSRX power up handle. */
3102 /* ------------------------------------------------------------------------------ */
3103 void OnDownstreamRxPoweredUp(void)
3105 TPI_DEBUG_PRINT(("DSRX -> Powered Up\n"));
3106 g_sys
.dsRxPoweredUp
= TRUE
;
3111 /* ------------------------------------------------------------------------------ */
3112 /* Function Name: OnHdmiCableDisconnected() */
3113 /* Function Description: HDMI cable unplug handle. */
3118 /* ------------------------------------------------------------------------------ */
3119 void OnHdmiCableDisconnected(void)
3121 TPI_DEBUG_PRINT(("HDMI Disconnected\n"));
3123 g_sys
.hdmiCableConnected
= FALSE
;
3125 #ifdef DEV_SUPPORT_EDID
3126 g_edid
.edidDataValid
= FALSE
;
3129 OnDownstreamRxPoweredDown();
3130 /* siHdmiTx_PowerStateD3(); */
3133 /* ------------------------------------------------------------------------------ */
3134 /* Function Name: OnHdmiCableConnected() */
3135 /* Function Description: HDMI cable plug in handle. */
3140 /* ------------------------------------------------------------------------------ */
3141 void OnHdmiCableConnected(void)
3143 TPI_DEBUG_PRINT(("Cable Connected\n"));
3144 /* No need to call TPI_Init here unless TX has been powered down on cable removal. */
3147 g_sys
.hdmiCableConnected
= TRUE
;
3149 if ((Sii9024A_HDCP_supported
)
3150 && (g_hdcp
.HDCP_TxSupports
== TRUE
)
3151 && (g_hdcp
.HDCP_AksvValid
== TRUE
)
3152 && (g_hdcp
.HDCPAuthenticated
== VMD_HDCP_AUTHENTICATED
)) {
3153 TPI_DEBUG_PRINT(("Cable Connected, Sii9024A_HDCP_supported\n"));
3154 WriteIndexedRegister(INDEXED_PAGE_0
, 0xCE, 0x00); /* Clear BStatus */
3155 WriteIndexedRegister(INDEXED_PAGE_0
, 0xCF, 0x00);
3158 /* Added for EDID read for Michael Wang recommaned by oscar 20100908 */
3159 /* siHdmiTx_PowerStateD0(); */
3160 /* ReadModifyWriteTPI(0x1A, TMDS_OUTPUT_CONTROL_MASK | AV_MUTE_MASK, TMDS_OUTPUT_CONTROL_ACTIVE | AV_MUTE_MUTED); */
3162 #ifdef DEV_SUPPORT_EDID
3167 ReadModifyWriteTPI(0xBB, 0x08, 0x08);
3170 if (IsHDMI_Sink()) /* select output mode (HDMI/DVI) according to sink capabilty */
3172 TPI_DEBUG_PRINT(("HDMI Sink Detected\n"));
3173 ReadModifyWriteTPI(0x1A, OUTPUT_MODE_MASK
, OUTPUT_MODE_HDMI
);
3175 TPI_DEBUG_PRINT(("DVI Sink Detected\n"));
3176 ReadModifyWriteTPI(0x1A, OUTPUT_MODE_MASK
, OUTPUT_MODE_DVI
);
3180 /* ------------------------------------------------------------------------------ */
3181 /* Function Name: siHdmiTx_PowerStateD0() */
3182 /* Function Description: Set TX to D0 mode. */
3183 /* ------------------------------------------------------------------------------ */
3184 void siHdmiTx_PowerStateD0(void)
3186 ReadModifyWriteTPI(0x1E, TX_POWER_STATE_MASK
, TX_POWER_STATE_D0
);
3187 TPI_DEBUG_PRINT(("TX Power State D0\n"));
3188 g_sys
.txPowerState
= TX_POWER_STATE_D0
;
3191 /* ------------------------------------------------------------------------------ */
3192 /* Function Name: siHdmiTx_PowerStateD2() */
3193 /* Function Description: Set TX to D2 mode. */
3194 /* ------------------------------------------------------------------------------ */
3195 void siHdmiTx_PowerStateD2(void)
3197 ReadModifyWriteTPI(0x1E, TX_POWER_STATE_MASK
, TX_POWER_STATE_D2
);
3198 TPI_DEBUG_PRINT(("TX Power State D2\n"));
3199 g_sys
.txPowerState
= TX_POWER_STATE_D2
;
3202 /* ------------------------------------------------------------------------------ */
3203 /* Function Name: siHdmiTx_PowerStateD0fromD2() */
3204 /* Function Description: Set TX to D0 mode from D2 mode. */
3205 /* ------------------------------------------------------------------------------ */
3206 void siHdmiTx_PowerStateD0fromD2(void)
3208 ReadModifyWriteTPI(0x1E, TX_POWER_STATE_MASK
, TX_POWER_STATE_D0
);
3210 if (Sii9024A_HDCP_supported
)
3215 TPI_DEBUG_PRINT(("TX Power State D0 from D2\n"));
3216 g_sys
.txPowerState
= TX_POWER_STATE_D0
;
3220 /* ------------------------------------------------------------------------------ */
3221 /* Function Name: siHdmiTx_PowerStateD3() */
3222 /* Function Description: Set TX to D3 mode. */
3223 /* ------------------------------------------------------------------------------ */
3224 /* 2011.06.27 Go to D3 */
3227 void siHdmiTx_PowerStateD3(void)
3231 WriteByteTPI(0x3C, HOT_PLUG_EVENT
| 0x08);
3232 WriteByteTPI(0x3D, 0xFF);
3233 ReadModifyWriteTPI(0x1E, TX_POWER_STATE_MASK
, TX_POWER_STATE_D3
);
3234 TPI_DEBUG_PRINT(("TX Power State D3 hot\n"));
3235 g_sys
.txPowerState
= TX_POWER_STATE_D3
;
3239 /* D3 cold Note:It is necessary to unplug the HDMI connector, otherwise would not go to D3 cold. */
3240 WriteByteTPI(0x3D, 0xFF);
3242 WriteByteTPI(0xC7, 0x00);
3244 WriteByteTPI(0x3C, HOT_PLUG_EVENT
| 0x08);
3245 WriteByteTPI(0x3D, 0xFF);
3246 WriteByteTPI(0x1E, 0x04);
3247 ReadModifyWriteTPI(0x1E, TX_POWER_STATE_MASK
, TX_POWER_STATE_D3
);
3248 TPI_DEBUG_PRINT(("TX Power State D3 cold\n"));
3249 g_sys
.txPowerState
= TX_POWER_STATE_D3
;
3253 /* 2011.06.27 Go to D3 End */
3255 /* ------------------------------------------------------------------------------ */
3256 /* Function Name: HotPlugService() */
3257 /* Function Description: Implement Hot Plug Service Loop activities */
3260 /* Returns: An error code that indicates success or cause of failure */
3261 /* Globals: LinkProtectionLevel */
3262 /* ------------------------------------------------------------------------------ */
3263 void HotPlugService(void)
3265 TPI_TRACE_PRINT((">>HotPlugService()\n"));
3267 DisableInterrupts(0xFF);
3269 /* siHdmiTx.VIC = g_edid.VideoDescriptor[0]; // use 1st mode supported by sink */
3274 /* ------------------------------------------------------------------------------ */
3275 /* Function Name: siHdmiTx_TPI_Poll() */
3276 /* Function Description: Poll Interrupt Status register for new interrupts */
3281 /* ------------------------------------------------------------------------------ */
3283 void siHdmiTx_TPI_Poll(void)
3285 byte InterruptStatus
;
3287 if (g_sys
.txPowerState
== TX_POWER_STATE_D0
) {
3288 InterruptStatus
= ReadByteTPI(0x3D);
3290 if (InterruptStatus
& HOT_PLUG_EVENT
) /* judge if HPD is connected */
3292 TPI_DEBUG_PRINT(("HPD -> "));
3293 ReadSetWriteTPI(0x3C, HOT_PLUG_EVENT
); /* Enable HPD interrupt bit */
3295 /* Repeat this loop while cable is bouncing: */
3297 WriteByteTPI(0x3D, HOT_PLUG_EVENT
); /* Write 1 to interrupt bits to clear the 'pending' status. */
3298 DelayMS(T_HPD_DELAY
); /* Delay for metastability protection and to help filter out connection bouncing */
3299 InterruptStatus
= ReadByteTPI(0x3D); /* Read Interrupt status register */
3300 } while (InterruptStatus
& HOT_PLUG_EVENT
); /* loop as long as HP interrupts recur */
3302 if (((InterruptStatus
& HOT_PLUG_STATE
) >> 2) != g_sys
.hdmiCableConnected
) {
3303 if (g_sys
.hdmiCableConnected
== TRUE
) {
3304 OnHdmiCableDisconnected();
3305 hdmi_util
.state_callback(0);
3307 OnHdmiCableConnected();
3308 ReadModifyWriteIndexedRegister(INDEXED_PAGE_0
, 0x0A, 0x08,
3312 if (g_sys
.hdmiCableConnected
== FALSE
) {
3316 /*if (g_sys.hdmiCableConnected == FALSE)
3321 else if((g_sys
.hdmiCableConnected
)&&(Sii9024A_HDCP_supported
))
3323 TPI_DEBUG_PRINT (("HPD -> deglitched"));
3324 ReadModifyWriteTPI(0x1A, TMDS_OUTPUT_CONTROL_MASK
| AV_MUTE_MASK
,
3325 TMDS_OUTPUT_CONTROL_POWER_DOWN
| AV_MUTE_MUTED
);
3328 ReadModifyWriteTPI(0x1A, TMDS_OUTPUT_CONTROL_MASK
, TMDS_OUTPUT_CONTROL_ACTIVE
);
3329 WriteByteTPI(0x08, tpivmode
[0]);
3332 /* Check rx power */
3333 if (((InterruptStatus
& RX_SENSE_STATE
) >> 3) != g_sys
.dsRxPoweredUp
) {
3334 if (g_sys
.hdmiCableConnected
== TRUE
) {
3335 if (g_sys
.dsRxPoweredUp
== TRUE
) {
3336 OnDownstreamRxPoweredDown();
3337 hdmi_util
.state_callback(0);
3339 OnDownstreamRxPoweredUp();
3340 hdmi_util
.state_callback(1);
3343 DelayMS(100); // Delay for metastability protection and to help filter out connection bouncing
3344 ClearInterrupt(RX_SENSE_EVENT
);
3346 /* Check if RX_SENSE_EVENT has occurred: */
3347 if (InterruptStatus
& RX_SENSE_EVENT
) {
3348 ClearInterrupt(RX_SENSE_EVENT
);
3350 /* Check if Audio Error event has occurred: */
3351 if (InterruptStatus
& AUDIO_ERROR_EVENT
) {
3352 /* TPI_DEBUG_PRINT (("TP -> Audio Error Event\n")); */
3353 /* The hardware handles the event without need for host intervention (PR, p. 31) */
3354 ClearInterrupt(AUDIO_ERROR_EVENT
);
3357 if ((Sii9024A_HDCP_supported
)
3358 && (g_sys
.hdmiCableConnected
== TRUE
)
3359 && (g_sys
.dsRxPoweredUp
== TRUE
)
3360 && (g_hdcp
.HDCPAuthenticated
== VMD_HDCP_AUTHENTICATED
)) {
3361 HDCP_CheckStatus(InterruptStatus
);
3363 #ifdef DEV_SUPPORT_CEC
3364 SI_CecHandler(0, 0);
3368 if (g_sys
.txPowerState
== TX_POWER_STATE_D3
)
3371 siHdmiTx_TPI_Init();
3372 /* siHdmiTx_VideoSet(); */
3373 TPI_DEBUG_PRINT(("***up from INT ***\n"));
3379 /* ------------------------------------------------------------------------------ */
3380 /* Function Name: siHdmiTx_VideoSel() */
3381 /* Function Description: Select output video mode */
3383 /* Accepts: Video mode */
3386 /* ------------------------------------------------------------------------------ */
3387 void siHdmiTx_VideoSel(byte vmode
)
3389 siHdmiTx
.HDMIVideoFormat
= VMD_HDMIFORMAT_CEA_VIC
;
3390 siHdmiTx
.ColorSpace
= RGB
;
3391 siHdmiTx
.ColorDepth
= VMD_COLOR_DEPTH_8BIT
;
3392 siHdmiTx
.SyncMode
= EXTERNAL_HSVSDE
;
3395 case HDMI_480I60_4X3
:
3397 siHdmiTx
.AspectRatio
= VMD_ASPECT_RATIO_4x3
;
3398 siHdmiTx
.Colorimetry
= COLORIMETRY_601
;
3399 siHdmiTx
.TclkSel
= X2
;
3402 case HDMI_576I50_4X3
:
3404 siHdmiTx
.AspectRatio
= VMD_ASPECT_RATIO_4x3
;
3405 siHdmiTx
.Colorimetry
= COLORIMETRY_601
;
3406 siHdmiTx
.TclkSel
= X2
;
3409 case HDMI_480P60_4X3
:
3411 siHdmiTx
.AspectRatio
= VMD_ASPECT_RATIO_4x3
;
3412 siHdmiTx
.Colorimetry
= COLORIMETRY_601
;
3413 siHdmiTx
.TclkSel
= X1
;
3416 case HDMI_576P50_4X3
:
3418 siHdmiTx
.AspectRatio
= VMD_ASPECT_RATIO_4x3
;
3419 siHdmiTx
.Colorimetry
= COLORIMETRY_601
;
3420 siHdmiTx
.TclkSel
= X1
;
3425 siHdmiTx
.AspectRatio
= VMD_ASPECT_RATIO_16x9
;
3426 siHdmiTx
.Colorimetry
= COLORIMETRY_709
;
3427 siHdmiTx
.TclkSel
= X1
;
3432 siHdmiTx
.AspectRatio
= VMD_ASPECT_RATIO_16x9
;
3433 siHdmiTx
.Colorimetry
= COLORIMETRY_709
;
3434 siHdmiTx
.TclkSel
= X1
;
3439 siHdmiTx
.AspectRatio
= VMD_ASPECT_RATIO_16x9
;
3440 siHdmiTx
.Colorimetry
= COLORIMETRY_709
;
3441 siHdmiTx
.TclkSel
= X1
;
3446 siHdmiTx
.AspectRatio
= VMD_ASPECT_RATIO_16x9
;
3447 siHdmiTx
.Colorimetry
= COLORIMETRY_709
;
3448 siHdmiTx
.TclkSel
= X1
;
3453 siHdmiTx
.AspectRatio
= VMD_ASPECT_RATIO_16x9
;
3454 siHdmiTx
.Colorimetry
= COLORIMETRY_709
;
3455 siHdmiTx
.TclkSel
= X1
;
3460 siHdmiTx
.AspectRatio
= VMD_ASPECT_RATIO_16x9
;
3461 siHdmiTx
.Colorimetry
= COLORIMETRY_709
;
3462 siHdmiTx
.TclkSel
= X1
;
3465 case HDMI_1024_768_60
:
3466 siHdmiTx
.VIC
= PC_BASE
+ 13;
3467 siHdmiTx
.AspectRatio
= VMD_ASPECT_RATIO_4x3
;
3468 siHdmiTx
.Colorimetry
= COLORIMETRY_709
;
3469 siHdmiTx
.TclkSel
= X1
;
3472 case HDMI_800_600_60
:
3473 siHdmiTx
.VIC
= PC_BASE
+ 9;
3474 siHdmiTx
.AspectRatio
= VMD_ASPECT_RATIO_4x3
;
3475 siHdmiTx
.Colorimetry
= COLORIMETRY_709
;
3476 siHdmiTx
.TclkSel
= X1
;
3481 siHdmiTx
.AspectRatio
= VMD_ASPECT_RATIO_16x9
;
3482 siHdmiTx
.Colorimetry
= COLORIMETRY_709
;
3483 siHdmiTx
.TclkSel
= X1
;
3488 siHdmiTx
.AspectRatio
= VMD_ASPECT_RATIO_16x9
;
3489 siHdmiTx
.Colorimetry
= COLORIMETRY_709
;
3490 siHdmiTx
.TclkSel
= X1
;
3497 TPI_DEBUG_PRINT(("siHdmiTx_VideoSel vmode=%d\n", vmode
));
3500 /* ------------------------------------------------------------------------------ */
3501 /* Function Name: siHdmiTx_AudioSel() */
3502 /* Function Description: Select output audio mode */
3504 /* Accepts: Audio Fs */
3507 /* ------------------------------------------------------------------------------ */
3508 void siHdmiTx_AudioSel(byte Afs
)
3510 siHdmiTx
.AudioMode
= AMODE_I2S
;
3511 siHdmiTx
.AudioChannels
= ACHANNEL_2CH
;
3512 siHdmiTx
.AudioFs
= Afs
;
3513 siHdmiTx
.AudioWordLength
= ALENGTH_16BITS
;
3514 siHdmiTx
.AudioI2SFormat
= (MCLK256FS
<< 4) | SCK_SAMPLE_RISING_EDGE
| 0x00; /* last num 0x00-->0x02 */