import PULS_20160108
[GitHub/mt8127/android_kernel_alcatel_ttab.git] / drivers / misc / mediatek / hdmi / sil9024 / siHdmiTx_902x_TPI.c
1
2 #include <linux/wait.h>
3 #include <linux/delay.h>
4 #include <linux/mutex.h>
5 #include <linux/bug.h>
6 #include <linux/err.h>
7 #include <linux/i2c.h>
8 #include <linux/kernel.h>
9 #include <mach/hardware.h>
10 #include "hdmi_drv.h"
11
12 #include <mach/mt_typedefs.h>
13
14 #include "siHdmiTx_902x_TPI.h"
15 /* #include "SiIIIC.h" */
16
17
18 SIHDMITX_CONFIG siHdmiTx;
19 GLOBAL_SYSTEM g_sys;
20 GLOBAL_HDCP g_hdcp;
21 GLOBAL_EDID g_edid;
22 byte tpivmode[3]; /* saved TPI Reg0x08/Reg0x09/Reg0x0A values. */
23
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;
26
27
28 bool HDCP_Supported = false;
29
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);
35
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;
41
42 /* static struct mxc_lcd_platform_data *Sii902xA_plat_data; */
43
44
45 /* ------------------------------------------------------------------------------ */
46 /* Function Name: DelayMS() */
47 /* Function Description: Introduce a busy-wait delay equal, in milliseconds, to the input parameter. */
48 /* */
49 /* Accepts: Length of required delay in milliseconds (max. 65535 ms) */
50 /* ------------------------------------------------------------------------------ */
51 void DelayMS(word MS)
52 {
53 msleep(MS); /* call linux kernel delay API function */
54 }
55
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)
61 {
62 int i;
63 for (i = RegAddr; i < (NBytes + RegAddr); i++) {
64 Data[i - RegAddr] = i2c_smbus_read_byte_data(client, i);
65 }
66 return IIC_OK;
67 }
68
69 static s32 i2c_smbus_write_byte_nostop(struct i2c_client *client, unsigned char value)
70 {
71 unsigned short old_flag = client->addr;
72
73 client->addr = client->addr & I2C_RS_FLAG;
74 i2c_smbus_write_byte(client, value);
75 client->addr = old_flag;
76
77 return IIC_OK;
78 }
79
80 byte siiReadSegmentBlockEDID(struct i2c_client *client, byte Segment, byte Offset, byte *Buffer,
81 byte Length)
82 {
83 int rc;
84 i2c_smbus_write_byte_nostop(siiSegEDID, Segment);
85 rc = I2CReadBlock(client, Offset, Length, Buffer);
86 if (rc < 0)
87 return -EIO;
88 return IIC_OK;
89 }
90
91 /* ------------------------------------------------------------------------------ */
92 /* Function Name: ReadByteTPI() */
93 /* Function Description: I2C read */
94 /* ------------------------------------------------------------------------------ */
95 byte ReadByteTPI(byte RegOffset)
96 {
97 byte Readnum;
98 Readnum = i2c_smbus_read_byte_data(sii902xA, RegOffset);
99 TPI_DEBUG_PRINT(("[9024]read RegOffset=0x%x,Readnum=0x%x\n", RegOffset, Readnum));
100 return Readnum;
101 }
102
103 /* ------------------------------------------------------------------------------ */
104 /* Function Name: WriteByteTPI() */
105 /* Function Description: I2C write */
106 /* ------------------------------------------------------------------------------ */
107 void WriteByteTPI(byte RegOffset, byte Data)
108 {
109 /* sii9024_i2c_write_byte(sii902xA,RegOffset, Data); */
110 i2c_smbus_write_byte_data(sii902xA, RegOffset, Data);
111
112 TPI_DEBUG_PRINT(("[9024]write RegOffset=0x%x,Data=0x%x\n", RegOffset, Data));
113 }
114
115
116 void ReadSetWriteTPI(byte Offset, byte Pattern)
117 {
118 byte Tmp;
119
120 Tmp = ReadByteTPI(Offset);
121
122 Tmp |= Pattern;
123 WriteByteTPI(Offset, Tmp);
124 }
125
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" */
130 /* unchanged. */
131 /* ------------------------------------------------------------------------------ */
132 void ReadClearWriteTPI(byte Offset, byte Pattern)
133 {
134 byte Tmp;
135
136 Tmp = ReadByteTPI(Offset);
137
138 Tmp &= ~Pattern;
139 WriteByteTPI(Offset, Tmp);
140 }
141
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" */
146 /* unchanged. */
147 /* ------------------------------------------------------------------------------ */
148 void ReadModifyWriteTPI(byte Offset, byte Mask, byte Value)
149 {
150 byte Tmp;
151
152 Tmp = ReadByteTPI(Offset);
153 Tmp &= ~Mask;
154 Tmp |= (Value & Mask);
155 WriteByteTPI(Offset, Tmp);
156 }
157
158 void ReadBlockTPI(byte TPI_Offset, word NBytes, byte *pData)
159 {
160 int i;
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]); */
164 }
165 return;
166 }
167
168
169 void WriteBlockTPI(byte TPI_Offset, word NBytes, byte *pData)
170 {
171 int i;
172 for (i = TPI_Offset; i < (NBytes + TPI_Offset); i++) {
173
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]); */
176 }
177
178 }
179
180 byte ReadIndexedRegister(byte PageNum, byte RegOffset)
181 {
182 WriteByteTPI(0xBC, PageNum); /* Internal page */
183 WriteByteTPI(0xBD, RegOffset); /* Indexed register */
184 return ReadByteTPI(0xBE); /* Return read value */
185 }
186
187 /* ------------------------------------------------------------------------------ */
188 /* Function Name: WriteIndexedRegister() */
189 /* Function Description: Write a value to an indexed register */
190 /* */
191 /* Write: */
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)
197 {
198 WriteByteTPI(0xBC, PageNum); /* Internal page */
199 WriteByteTPI(0xBD, RegOffset); /* Indexed register */
200 WriteByteTPI(0xBE, RegValue); /* Read value into buffer */
201 }
202
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" */
207 /* unchanged. */
208 /* ------------------------------------------------------------------------------ */
209 void ReadModifyWriteIndexedRegister(byte PageNum, byte RegOffset, byte Mask, byte Value)
210 {
211 byte Tmp;
212 WriteByteTPI(0xBC, PageNum);
213 WriteByteTPI(0xBD, RegOffset);
214 Tmp = ReadByteTPI(0xBE);
215
216 Tmp &= ~Mask;
217 Tmp |= (Value & Mask);
218
219 WriteByteTPI(0xBE, Tmp);
220 }
221
222 /* ------------------------------------------------------------------------------ */
223 void TXHAL_InitPostReset(void)
224 {
225 /* Set terminations to default. */
226 WriteByteTPI(0x82, 0x25);
227 /* HW debounce to 64ms (0x14) */
228 WriteByteTPI(0x7C, 0x14);
229 }
230
231 /* ------------------------------------------------------------------------------ */
232 /* Function Name: TxHW_Reset() */
233 /* Function Description: Hardware reset Tx */
234 /* ------------------------------------------------------------------------------ */
235
236 void TxHW_Reset(void)
237 {
238 TPI_TRACE_PRINT((">>TxHW_Reset()\n"));
239
240 HDMI_reset();
241 TXHAL_InitPostReset();
242 }
243
244 /* ------------------------------------------------------------------------------ */
245 /* Function Name: InitializeStateVariables() */
246 /* Function Description: Initialize system state variables */
247 /* ------------------------------------------------------------------------------ */
248 void InitializeStateVariables(void)
249 {
250 g_sys.tmdsPoweredUp = FALSE;
251 g_sys.hdmiCableConnected = FALSE;
252 g_sys.dsRxPoweredUp = FALSE;
253
254 #ifdef DEV_SUPPORT_EDID
255 g_edid.edidDataValid = FALSE;
256 g_edid.HDMI_compatible_VSDB = FALSE;
257 #endif
258 }
259
260 /* ------------------------------------------------------------------------------ */
261 /* Function Name: EnableTMDS() */
262 /* Function Description: Enable TMDS */
263 /* ------------------------------------------------------------------------------ */
264 void EnableTMDS(void)
265 {
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;
270 }
271
272 /* ------------------------------------------------------------------------------ */
273 /* Function Name: DisableTMDS() */
274 /* Function Description: Disable TMDS */
275 /* ------------------------------------------------------------------------------ */
276 void DisableTMDS(void)
277 {
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;
282 }
283
284 /* ------------------------------------------------------------------------------ */
285 /* Function Name: EnableInterrupts() */
286 /* Function Description: Enable the interrupts specified in the input parameter */
287 /* */
288 /* Accepts: A bit pattern with "1" for each interrupt that needs to be */
289 /* set in the Interrupt Enable Register (TPI offset 0x3C) */
290 /* Returns: TRUE */
291 /* Globals: none */
292 /* ------------------------------------------------------------------------------ */
293 byte EnableInterrupts(byte Interrupt_Pattern)
294 {
295 TPI_TRACE_PRINT((">>EnableInterrupts()\n"));
296 ReadSetWriteTPI(0x3C, Interrupt_Pattern);
297 return TRUE;
298 }
299
300 /* ------------------------------------------------------------------------------ */
301 /* Function Name: DisableInterrupts() */
302 /* Function Description: Disable the interrupts specified in the input parameter */
303 /* */
304 /* Accepts: A bit pattern with "1" for each interrupt that needs to be */
305 /* cleared in the Interrupt Enable Register (TPI offset 0x3C) */
306 /* Returns: TRUE */
307 /* Globals: none */
308 /* ------------------------------------------------------------------------------ */
309 byte DisableInterrupts(byte Interrupt_Pattern)
310 {
311 TPI_TRACE_PRINT((">>DisableInterrupts()\n"));
312 ReadClearWriteTPI(0x3C, Interrupt_Pattern);
313
314 return TRUE;
315 }
316
317
318
319 #ifdef DEV_SUPPORT_EDID
320 static u8 g_CommData[EDID_BLOCK_SIZE];
321
322 #define ReadBlockEDID(a, b, c) I2CReadBlock(siiEDID, a, b, c)
323 #define ReadSegmentBlockEDID(a, b, c, d) siiReadSegmentBlockEDID(siiEDID, a, b, d, c)
324
325 /* ------------------------------------------------------------------------------ */
326 /* Function Name: GetDDC_Access() */
327 /* Function Description: Request access to DDC bus from the receiver */
328 /* */
329 /* Accepts: none */
330 /* Returns: TRUE or FLASE */
331 /* Globals: none */
332 /* ------------------------------------------------------------------------------ */
333 #define T_DDC_ACCESS 50
334
335 byte GetDDC_Access(byte *SysCtrlRegVal)
336 {
337 byte sysCtrl;
338 byte DDCReqTimeout = T_DDC_ACCESS;
339 byte TPI_ControlImage;
340
341 TPI_TRACE_PRINT((">>GetDDC_Access()\n"));
342
343 sysCtrl = ReadByteTPI(0x1A); /* Read and store original value. Will be passed into ReleaseDDC() */
344 *SysCtrlRegVal = sysCtrl;
345
346 sysCtrl |= DDC_BUS_REQUEST_REQUESTED;
347 WriteByteTPI(0x1A, sysCtrl);
348
349 while (DDCReqTimeout--) /* Loop till 0x1A[1] reads "1" */
350 {
351 TPI_ControlImage = ReadByteTPI(0x1A);
352
353 if (TPI_ControlImage & DDC_BUS_GRANT_MASK) /* When 0x1A[1] reads "1" */
354 {
355 sysCtrl |= DDC_BUS_GRANT_GRANTED;
356 WriteByteTPI(0x1A, sysCtrl); /* lock host DDC bus access (0x1A[2:1] = 11) */
357 return TRUE;
358 }
359 WriteByteTPI(0x1A, sysCtrl); /* 0x1A[2] = "1" - Requst the DDC bus */
360 DelayMS(200);
361 }
362
363 WriteByteTPI(0x1A, sysCtrl); /* Failure... restore original value. */
364 return FALSE;
365 }
366
367 /* ------------------------------------------------------------------------------ */
368 /* Function Name: ReleaseDDC() */
369 /* Function Description: Release DDC bus */
370 /* */
371 /* Accepts: none */
372 /* Returns: TRUE if bus released successfully. FALSE if failed. */
373 /* Globals: none */
374 /* ------------------------------------------------------------------------------ */
375 byte ReleaseDDC(byte SysCtrlRegVal)
376 {
377 byte DDCReqTimeout = T_DDC_ACCESS;
378 byte TPI_ControlImage;
379
380 TPI_TRACE_PRINT((">>ReleaseDDC()\n"));
381
382 SysCtrlRegVal &= ~BITS_2_1; /* Just to be sure bits [2:1] are 0 before it is written */
383
384 while (DDCReqTimeout--) /* Loop till 0x1A[1] reads "0" */
385 {
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 */
389
390 WriteByteTPI(0x1A, SysCtrlRegVal);
391 TPI_ControlImage = ReadByteTPI(0x1A);
392
393 if (!(TPI_ControlImage & BITS_2_1)) /* When 0x1A[2:1] read "0" */
394 return TRUE;
395 }
396
397 return FALSE; /* Failed to release DDC bus control */
398 }
399
400 /* ------------------------------------------------------------------------------ */
401 /* Function Name: CheckEDID_Header() */
402 /* Function Description: Checks if EDID header is correct per VESA E-EDID standard */
403 /* */
404 /* Accepts: Pointer to 1st EDID block */
405 /* Returns: TRUE or FLASE */
406 /* Globals: EDID data */
407 /* ------------------------------------------------------------------------------ */
408 byte CheckEDID_Header(byte *Block)
409 {
410 byte i = 0;
411
412 if (Block[i]) /* byte 0 must be 0 */
413 return FALSE;
414
415 for (i = 1; i < 1 + EDID_HDR_NO_OF_FF; i++) {
416 if (Block[i] != 0xFF) /* bytes [1..6] must be 0xFF */
417 return FALSE;
418 }
419
420 if (Block[i]) /* byte 7 must be 0 */
421 return FALSE;
422
423 return TRUE;
424 }
425
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 */
430 /* */
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)
436 {
437 byte i;
438 byte CheckSum = 0;
439
440 for (i = 0; i < EDID_BLOCK_SIZE; i++)
441 CheckSum += Block[i];
442
443 if (CheckSum)
444 return FALSE;
445
446 return TRUE;
447 }
448
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. */
453 /* */
454 /* Accepts: Pointer to the 128 byte array where the data read from EDID Block0 is stored. */
455 /* Returns: none */
456 /* Globals: EDID data */
457 /* ------------------------------------------------------------------------------ */
458 #if (CONF__TPI_EDID_PRINT == ENABLE)
459 void ParseEstablishedTiming(byte *Data)
460 {
461 TPI_EDID_PRINT(("Parsing Established Timing:\n"));
462 TPI_EDID_PRINT(("===========================\n"));
463
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"));
481
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"));
499
500 /* Parse Established Timing Byte #2: */
501 if (Data[ESTABLISHED_TIMING_INDEX + 2] & 0x80)
502 TPI_EDID_PRINT(("1152 x 870 @ 75Hz\n"));
503
504 if ((!Data[0]) && (!Data[ESTABLISHED_TIMING_INDEX + 1]) && (!Data[2]))
505 TPI_EDID_PRINT(("No established video modes\n"));
506 }
507
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. */
512 /* */
513 /* Accepts: Pointer to the 128 byte array where the data read from EDID Block0 is stored. */
514 /* Returns: none */
515 /* Globals: EDID data */
516 /* ------------------------------------------------------------------------------ */
517 void ParseStandardTiming(byte *Data)
518 {
519 byte i;
520 byte AR_Code;
521
522 TPI_EDID_PRINT(("Parsing Standard Timing:\n"));
523 TPI_EDID_PRINT(("========================\n"));
524
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 */
529 } else {
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 */
531
532 AR_Code = (Data[STANDARD_TIMING_OFFSET + i + 1] & TWO_MSBITS) >> 6;
533 TPI_EDID_PRINT(("Aspect Ratio: "));
534
535 switch (AR_Code) {
536 case AR16_10:
537 TPI_EDID_PRINT(("16:10\n"));
538 break;
539
540 case AR4_3:
541 TPI_EDID_PRINT(("4:3\n"));
542 break;
543
544 case AR5_4:
545 TPI_EDID_PRINT(("5:4\n"));
546 break;
547
548 case AR16_9:
549 TPI_EDID_PRINT(("16:9\n"));
550 break;
551 }
552 }
553 }
554 }
555
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. */
560 /* */
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. */
563 /* */
564 /* Block indicator to distinguish between block #0 and blocks #2, #3 */
565 /* Returns: none */
566 /* Globals: EDID data */
567 /* ------------------------------------------------------------------------------ */
568 byte ParseDetailedTiming(byte *Data, byte DetailedTimingOffset, byte Block)
569 {
570 byte TmpByte;
571 byte i;
572 word TmpWord;
573
574 TmpWord = Data[DetailedTimingOffset + PIX_CLK_OFFSET] +
575 256 * Data[DetailedTimingOffset + PIX_CLK_OFFSET + 1];
576
577 if (TmpWord == 0x00) /* 18 byte partition is used as either for Monitor Name or for Monitor Range Limits or it is unused */
578 {
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 */
580 {
581 if (Data[DetailedTimingOffset + 3] == 0xFC) /* these 13 bytes are ASCII coded monitor name */
582 {
583 TPI_EDID_PRINT(("Monitor Name: "));
584
585 for (i = 0; i < 13; i++) {
586 TPI_EDID_PRINT(("%c", Data[DetailedTimingOffset + 5 + i])); /* Display monitor name on SiIMon */
587 }
588 TPI_EDID_PRINT(("\n"));
589 }
590
591 else if (Data[DetailedTimingOffset + 3] == 0xFD) /* these 13 bytes contain Monitor Range limits, binary coded */
592 {
593 TPI_EDID_PRINT(("Monitor Range Limits:\n\n"));
594
595 i = 0;
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"));
604 }
605 }
606
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"));
611 return FALSE;
612 }
613 }
614
615 else /* first 2 bytes are not 0 => this is a detailed timing descriptor from either block */
616 {
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"));
623 }
624
625 TPI_EDID_PRINT(("Pixel Clock (MHz * 100): %d\n", (int)TmpWord));
626
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));
630
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));
634
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));
638
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));
642
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));
646
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));
650
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));
654
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));
658
659 TmpWord = Data[DetailedTimingOffset + H_IMAGE_SIZE_OFFSET] +
660 256 *
661 (((Data[DetailedTimingOffset + (H_IMAGE_SIZE_OFFSET + 2)]) >> 4) & FOUR_LSBITS);
662 TPI_EDID_PRINT(("Horizontal Image Size (mm): %d\n", (int)TmpWord));
663
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));
667
668 TmpByte = Data[DetailedTimingOffset + H_BORDER_OFFSET];
669 TPI_EDID_PRINT(("Horizontal Border (Pixels): %d\n", (int)TmpByte));
670
671 TmpByte = Data[DetailedTimingOffset + V_BORDER_OFFSET];
672 TPI_EDID_PRINT(("Vertical Border (Lines): %d\n", (int)TmpByte));
673
674 TmpByte = Data[DetailedTimingOffset + FLAGS_OFFSET];
675
676 TPI_EDID_PRINT(("\n"));
677 }
678 return TRUE;
679 }
680
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. */
685 /* */
686 /* Accepts: Pointer to the 128 byte array where the data read from EDID Block0 is stored. */
687 /* Returns: none */
688 /* Globals: EDID data */
689 /* ------------------------------------------------------------------------------ */
690 void ParseBlock_0_TimingDescriptors(byte *Data)
691 {
692 byte i;
693 byte Offset;
694
695 ParseEstablishedTiming(Data);
696 ParseStandardTiming(Data);
697
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);
701 }
702 }
703 #endif
704
705 /* ------------------------------------------------------------------------------ */
706 /* Function Name: ParseEDID() */
707 /* Function Description: Extract sink properties from its EDID file and save them in */
708 /* global structure g_edid. */
709 /* */
710 /* Accepts: none */
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)
716 {
717 byte i, j, k;
718
719 TPI_EDID_PRINT(("\n"));
720 TPI_EDID_PRINT(("EDID DATA (Segment = 0 Block = 0 Offset = %d):\n",
721 (int)EDID_BLOCK_0_OFFSET));
722
723 for (j = 0, i = 0; j < 128; j++) {
724 k = pEdid[j];
725 TPI_EDID_PRINT(("%2.2X ", (int)k));
726 i++;
727
728 if (i == 0x10) {
729 TPI_EDID_PRINT(("\n"));
730 i = 0;
731 }
732 }
733 TPI_EDID_PRINT(("\n"));
734
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) */
736 {
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;
740 }
741
742 if (!DoEDID_Checksum(pEdid)) {
743 /* non-zero EDID checksum */
744 TPI_DEBUG_PRINT(("EDID -> Checksum Error\n"));
745 return EDID_CHECKSUM_ERROR;
746 }
747 #if (CONF__TPI_EDID_PRINT == ENABLE)
748 ParseBlock_0_TimingDescriptors(pEdid); /* Parse EDID Block #0 Desctiptors */
749 #endif
750
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));
753
754 if (!(*numExt)) {
755 /* No extensions to worry about */
756 return EDID_NO_861_EXTENSIONS;
757 }
758 /* return Parse861Extensions(NumOfExtensions); // Parse 861 Extensions (short and long descriptors); */
759 return (EDID_OK);
760 }
761
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. */
766 /* */
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)
773 {
774 byte LongDescriptorOffset;
775 byte DataBlockLength;
776 byte DataIndex,DataIndexbk;
777 byte ExtendedTagCode;
778 byte VSDB_BaseOffset = 0;
779
780 byte V_DescriptorIndex = 0; /* static to support more than one extension */
781 byte A_DescriptorIndex = 0; /* static to support more than one extension */
782
783 byte TagCode;
784
785 byte i;
786 byte j;
787
788 if (Data[EDID_TAG_ADDR] != EDID_EXTENSION_TAG) {
789 TPI_EDID_PRINT(("EDID -> Extension Tag Error\n"));
790 return EDID_EXT_TAG_ERROR;
791 }
792
793 if (Data[EDID_REV_ADDR] != EDID_REV_THREE) {
794 TPI_EDID_PRINT(("EDID -> Revision Error\n"));
795 return EDID_REV_ADDR_ERROR;
796 }
797
798 LongDescriptorOffset = Data[LONG_DESCR_PTR_IDX]; /* block offset where long descriptors start */
799
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;
806
807 DataIndex = EDID_DATA_START; /* 4 */
808
809 while (DataIndex < LongDescriptorOffset)
810 {
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)
817 {
818 TPI_EDID_PRINT(("EDID -> V Descriptor Overflow\n"));
819 return EDID_V_DESCR_OVERFLOW;
820 }
821
822 i = 0; /* num of short video descriptors in current data block */
823
824 switch (TagCode) {
825 case VIDEO_D_BLOCK:
826 while ((i < DataBlockLength) && (i < MAX_V_DESCRIPTORS)) /* each SVD is 1 byte long */
827 {
828 g_edid.VideoDescriptor[V_DescriptorIndex++] = Data[DataIndex++];
829 i++;
830 }
831 DataIndex += DataBlockLength - i; /* if there are more STDs than MAX_V_DESCRIPTORS, skip the last ones. Update DataIndex */
832
833 TPI_EDID_PRINT(("EDID -> Short Descriptor Video Block\n"));
834 break;
835
836 case AUDIO_D_BLOCK:
837 while (i < DataBlockLength / 3) /* each SAD is 3 bytes long */
838 {
839 j = 0;
840 while (j < AUDIO_DESCR_SIZE) /* 3 */
841 {
842 g_edid.AudioDescriptor[A_DescriptorIndex][j++] =
843 Data[DataIndex++];
844 }
845 A_DescriptorIndex++;
846 i++;
847 }
848 TPI_EDID_PRINT(("EDID -> Short Descriptor Audio Block\n"));
849 break;
850
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"));
855 break;
856
857 case USE_EXTENDED_TAG:
858 ExtendedTagCode = Data[DataIndex++];
859
860 switch (ExtendedTagCode) {
861 case VIDEO_CAPABILITY_D_BLOCK:
862 TPI_EDID_PRINT(("EDID -> Short Descriptor Video Capability Block\n"));
863
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 */
868 break;
869
870 case COLORIMETRY_D_BLOCK:
871 g_edid.ColorimetrySupportFlags = Data[DataIndex++] & BITS_1_0;
872 g_edid.MetadataProfile = Data[DataIndex++] & BITS_2_1_0;
873
874 TPI_EDID_PRINT(("EDID -> Short Descriptor Colorimetry Block\n"));
875 break;
876 }
877 DataIndex = DataIndexbk + DataBlockLength+1;
878 break;
879
880 case VENDOR_SPEC_D_BLOCK:
881 VSDB_BaseOffset = DataIndex - 1;
882
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;
888 }
889 // else
890 //g_edid.HDMI_Sink = FALSE;
891
892
893
894 g_edid.CEC_A_B = Data[DataIndex++]; /* CEC Physical address */
895 g_edid.CEC_C_D = Data[DataIndex++];
896
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. */
900 {
901 word phyAddr;
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);
908 }
909 }
910 #endif
911
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;
916 else
917 g_edid._3D_Supported = FALSE;
918 TPI_EDID_PRINT(("DataIndexbk=0x%x,DataBlockLength=0x%x\n",DataIndexbk,DataBlockLength));
919
920 //DataIndex += DataBlockLength - HDMI_SIGNATURE_LEN - CEC_PHYS_ADDR_LEN; // Point to start of next block
921
922 DataIndex = DataIndexbk + DataBlockLength+1;
923
924 TPI_EDID_PRINT(("DataIndex=0x%x!!!!!!!!!\n",DataIndex));
925 TPI_EDID_PRINT(("EDID -> Short Descriptor Vendor Block\n"));
926 TPI_EDID_PRINT(("\n"));
927 break;
928
929 default:
930 TPI_EDID_PRINT(("EDID -> Unknown Tag Code\n"));
931 return EDID_UNKNOWN_TAG_CODE;
932
933 } /* End, Switch statement */
934 } /* End, while (DataIndex < LongDescriptorOffset) statement */
935
936 return EDID_SHORT_DESCRIPTORS_OK;
937 }
938
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. */
943 /* */
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. */
946 /* Globals: none */
947 /* ------------------------------------------------------------------------------ */
948 byte Parse861LongDescriptors(byte *Data)
949 {
950 byte LongDescriptorsOffset;
951 byte DescriptorNum = 1;
952
953 LongDescriptorsOffset = Data[LONG_DESCR_PTR_IDX]; /* EDID block offset 2 holds the offset */
954
955 if (!LongDescriptorsOffset) /* per CEA-861-D, table 27 */
956 {
957 TPI_DEBUG_PRINT(("EDID -> No Detailed Descriptors\n"));
958 return EDID_NO_DETAILED_DESCRIPTORS;
959 }
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"));
965
966 #if (CONF__TPI_EDID_PRINT == ENABLE)
967 if (!ParseDetailedTiming(Data, LongDescriptorsOffset, EDID_BLOCK_2_3))
968 break;
969 #endif
970 LongDescriptorsOffset += LONG_DESCR_LEN;
971 DescriptorNum++;
972 }
973
974 return EDID_LONG_DESCRIPTORS_OK;
975 }
976
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. */
982 /* */
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)
989 {
990 byte i, j, k;
991
992 byte ErrCode;
993
994 /* byte V_DescriptorIndex = 0; */
995 /* byte A_DescriptorIndex = 0; */
996
997 byte Segment = 0;
998 byte Block = 0;
999 byte Offset = 0;
1000
1001 g_edid.HDMI_Sink = FALSE;
1002 g_edid.HDMI_compatible_VSDB = FALSE;
1003 do
1004 {
1005 Block++;
1006
1007 Offset = 0;
1008 if ((Block % 2) > 0) {
1009 Offset = EDID_BLOCK_SIZE;
1010 }
1011
1012 Segment = (byte) (Block / 2);
1013
1014 if (Block == 1) {
1015 ReadBlockEDID(EDID_BLOCK_1_OFFSET, EDID_BLOCK_SIZE, g_CommData); /* read first 128 bytes of EDID ROM */
1016 } else {
1017 ReadSegmentBlockEDID(Segment, Offset, EDID_BLOCK_SIZE, g_CommData); /* read next 128 bytes of EDID ROM */
1018 }
1019
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++) {
1024 k = g_CommData[j];
1025 TPI_EDID_PRINT(("%2.2X ", (int)k));
1026 i++;
1027
1028 if (i == 0x10) {
1029 TPI_EDID_PRINT(("\n"));
1030 i = 0;
1031 }
1032 }
1033 TPI_EDID_PRINT(("\n"));
1034
1035 if ((NumOfExtensions > 1) && (Block == 1)) {
1036 continue;
1037 }
1038
1039 ErrCode = Parse861ShortDescriptors(g_CommData);
1040 if (ErrCode != EDID_SHORT_DESCRIPTORS_OK) {
1041 return ErrCode;
1042 }
1043
1044 ErrCode = Parse861LongDescriptors(g_CommData);
1045 if (ErrCode != EDID_LONG_DESCRIPTORS_OK) {
1046 return ErrCode;
1047 }
1048
1049 } while (Block < NumOfExtensions);
1050
1051 return EDID_OK;
1052 }
1053
1054 /* ------------------------------------------------------------------------------ */
1055 /* Function Name: DoEdidRead() */
1056 /* Function Description: EDID processing */
1057 /* */
1058 /* Accepts: none */
1059 /* Returns: TRUE or FLASE */
1060 /* Globals: none */
1061 /* ------------------------------------------------------------------------------ */
1062 byte DoEdidRead(void)
1063 {
1064 byte SysCtrlReg;
1065 byte Result;
1066 byte NumOfExtensions;
1067
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;
1082 } else {
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;
1089 }
1090 } else {
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;
1100 }
1101 if(g_edid.HDMI_compatible_VSDB)
1102 g_edid.HDMI_Sink = TRUE;//g_edid.HDMI_Sink = TRUE;
1103 }
1104
1105 if (!ReleaseDDC(SysCtrlReg)) /* Host must release DDC bus once it is done reading EDID */
1106 {
1107 TPI_DEBUG_PRINT(("EDID -> DDC bus release failed\n"));
1108 return EDID_DDC_BUS_RELEASE_FAILURE;
1109 }
1110 } else {
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;
1118 }
1119
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));
1125
1126 g_edid.edidDataValid = TRUE;
1127 }
1128 return EDID_OK;
1129 }
1130
1131 #endif
1132
1133
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. */
1145 /* */
1146 /* Accepts: none */
1147 /* Returns: TRUE if Tx supports HDCP. FALSE if not. */
1148 /* Globals: none */
1149 /* ------------------------------------------------------------------------------ */
1150 byte IsHDCP_Supported(void)
1151 {
1152 byte HDCP_Rev;
1153 byte HDCP_Supported;
1154
1155 TPI_TRACE_PRINT((">>IsHDCP_Supported()\n"));
1156
1157 HDCP_Supported = TRUE;
1158
1159 /* Check Device ID */
1160 HDCP_Rev = ReadByteTPI(0x30);
1161
1162 if (HDCP_Rev != (HDCP_MAJOR_REVISION_VALUE | HDCP_MINOR_REVISION_VALUE)) {
1163 HDCP_Supported = FALSE;
1164 }
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"));
1178 }
1179 }
1180 }
1181 }
1182 }
1183 return HDCP_Supported;
1184 }
1185
1186 /* ------------------------------------------------------------------------------ */
1187 /* Function Name: AreAKSV_OK() */
1188 /* Function Description: Check if AKSVs contain 20 '0' and 20 '1' */
1189 /* */
1190 /* Accepts: none */
1191 /* Returns: TRUE if 20 zeros and 20 ones found in AKSV. FALSE OTHERWISE */
1192 /* Globals: none */
1193 /* ------------------------------------------------------------------------------ */
1194 byte AreAKSV_OK(void)
1195 {
1196 byte B_Data[AKSV_SIZE];
1197 byte NumOfOnes = 0;
1198 byte i, j;
1199
1200 TPI_TRACE_PRINT((">>AreAKSV_OK()\n"));
1201
1202 ReadBlockTPI(0x36, AKSV_SIZE, B_Data);
1203
1204 for (i = 0; i < AKSV_SIZE; i++) {
1205 for (j = 0; j < BYTE_SIZE; j++) {
1206 if (B_Data[i] & 0x01) {
1207 NumOfOnes++;
1208 }
1209 B_Data[i] >>= 1;
1210 }
1211 }
1212 if (NumOfOnes != NUM_OF_ONES_IN_KSV)
1213 return FALSE;
1214
1215 return TRUE;
1216 }
1217
1218 /* ------------------------------------------------------------------------------ */
1219 /* Function Name: HDCP_Off() */
1220 /* Function Description: Switch hdcp off. */
1221 /* ------------------------------------------------------------------------------ */
1222 void HDCP_Off(void)
1223 {
1224 TPI_TRACE_PRINT((">>HDCP_Off()\n"));
1225
1226 /* AV MUTE */
1227 ReadModifyWriteTPI(0x1A, AV_MUTE_MASK, AV_MUTE_MUTED);
1228 WriteByteTPI(0x2A, PROTECTION_LEVEL_MIN);
1229
1230 g_hdcp.HDCP_Started = FALSE;
1231 g_hdcp.HDCP_LinkProtectionLevel =
1232 EXTENDED_LINK_PROTECTION_NONE | LOCAL_LINK_PROTECTION_NONE;
1233 }
1234
1235 /* ------------------------------------------------------------------------------ */
1236 /* Function Name: HDCP_On() */
1237 /* Function Description: Switch hdcp on. */
1238 /* ------------------------------------------------------------------------------ */
1239 void HDCP_On(void)
1240 {
1241 if (g_hdcp.HDCP_Override == FALSE) {
1242 TPI_DEBUG_PRINT(("HDCP Started\n"));
1243
1244 WriteByteTPI(0x2A, PROTECTION_LEVEL_MAX);
1245
1246 g_hdcp.HDCP_Started = TRUE;
1247 } else {
1248 g_hdcp.HDCP_Started = FALSE;
1249 }
1250 }
1251
1252 /* ------------------------------------------------------------------------------ */
1253 /* Function Name: RestartHDCP() */
1254 /* Function Description: Restart HDCP. */
1255 /* ------------------------------------------------------------------------------ */
1256 void RestartHDCP(void)
1257 {
1258 TPI_DEBUG_PRINT(("HDCP -> Restart\n"));
1259
1260 DisableTMDS();
1261 HDCP_Off();
1262 EnableTMDS();
1263 }
1264
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. */
1269 /* */
1270 /* Accepts: none */
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)
1278 {
1279 TPI_TRACE_PRINT((">>HDCP_Init()\n"));
1280
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;
1286
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"));
1292 return;
1293 }
1294 g_hdcp.HDCP_TxSupports = TRUE;
1295
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"));
1301 return;
1302 }
1303 g_hdcp.HDCP_AksvValid = TRUE;
1304
1305 #ifdef KSVFORWARD
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);
1309 #endif
1310
1311 TPI_DEBUG_PRINT(("HDCP -> Supported by TX, AKSVs valid\n"));
1312 }
1313
1314 #ifdef READKSV
1315 /* ------------------------------------------------------------------------------ */
1316 /* Function Name: IsRepeater() */
1317 /* Function Description: Test if sink is a repeater. */
1318 /* */
1319 /* Accepts: none */
1320 /* Returns: TRUE if sink is a repeater. FALSE if not. */
1321 /* Globals: none */
1322 /* ------------------------------------------------------------------------------ */
1323 byte IsRepeater(void)
1324 {
1325 byte RegImage;
1326
1327 TPI_TRACE_PRINT((">>IsRepeater()\n"));
1328
1329 RegImage = ReadByteTPI(0x29);
1330
1331 if (RegImage & HDCP_REPEATER_MASK)
1332 return TRUE;
1333
1334 return FALSE; /* not a repeater */
1335 }
1336
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 */
1341 /* */
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 */
1344 /* Returns: none */
1345 /* Globals: none */
1346 /* ------------------------------------------------------------------------------ */
1347 void ReadBlockHDCP(byte TPI_Offset, word NBytes, byte *pData)
1348 {
1349 I2CReadBlock(siiHDCP, TPI_Offset, NBytes, pData);
1350 }
1351
1352 /* ------------------------------------------------------------------------------ */
1353 /* Function Name: GetKSV() */
1354 /* Function Description: Collect all downstrean KSV for verification. */
1355 /* */
1356 /* Accepts: none */
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 /* ------------------------------------------------------------------------------ */
1360 byte GetKSV(void)
1361 {
1362 byte i;
1363 word KeyCount;
1364 byte KSV_Array[KSV_ARRAY_SIZE];
1365
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);
1371 }
1372
1373
1374
1375 return TRUE;
1376 }
1377 #endif
1378
1379 /* ------------------------------------------------------------------------------ */
1380 /* Function Name: HDCP_CheckStatus() */
1381 /* Function Description: Check HDCP status. */
1382 /* */
1383 /* Accepts: InterruptStatus */
1384 /* Returns: none */
1385 /* Globals: none */
1386 /* ------------------------------------------------------------------------------ */
1387 void HDCP_CheckStatus(byte InterruptStatusImage)
1388 {
1389 byte QueryData;
1390 byte LinkStatus;
1391 byte RegImage;
1392 byte NewLinkProtectionLevel;
1393
1394 #ifdef READKSV
1395 byte RiCnt;
1396 #endif
1397 #ifdef KSVFORWARD
1398 byte ksv;
1399 #endif
1400
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);
1406
1407 if (QueryData & PROTECTION_TYPE_MASK) /* Is HDCP avaialable */
1408 {
1409 HDCP_On();
1410 }
1411 }
1412 /* Check if Link Status has changed: */
1413 if (InterruptStatusImage & SECURITY_CHANGE_EVENT) {
1414 TPI_DEBUG_PRINT(("HDCP -> "));
1415
1416 LinkStatus = ReadByteTPI(0x29);
1417 LinkStatus &= LINK_STATUS_MASK;
1418
1419 ClearInterrupt(SECURITY_CHANGE_EVENT);
1420
1421 switch (LinkStatus) {
1422 case LINK_STATUS_NORMAL:
1423 TPI_DEBUG_PRINT(("Link = Normal\n"));
1424 break;
1425
1426 case LINK_STATUS_LINK_LOST:
1427 TPI_DEBUG_PRINT(("Link = Lost\n"));
1428 RestartHDCP();
1429 break;
1430
1431 case LINK_STATUS_RENEGOTIATION_REQ:
1432 TPI_DEBUG_PRINT(("Link = Renegotiation Required\n"));
1433 HDCP_Off();
1434 HDCP_On();
1435 break;
1436
1437 case LINK_STATUS_LINK_SUSPENDED:
1438 TPI_DEBUG_PRINT(("Link = Suspended\n"));
1439 HDCP_On();
1440 break;
1441 }
1442 }
1443 /* Check if HDCP state has changed: */
1444 if (InterruptStatusImage & HDCP_CHANGE_EVENT) {
1445 RegImage = ReadByteTPI(0x29);
1446
1447 NewLinkProtectionLevel =
1448 RegImage & (EXTENDED_LINK_PROTECTION_MASK | LOCAL_LINK_PROTECTION_MASK);
1449 if (NewLinkProtectionLevel != g_hdcp.HDCP_LinkProtectionLevel) {
1450 TPI_DEBUG_PRINT(("HDCP -> "));
1451
1452 g_hdcp.HDCP_LinkProtectionLevel = NewLinkProtectionLevel;
1453
1454 switch (g_hdcp.HDCP_LinkProtectionLevel) {
1455 case (EXTENDED_LINK_PROTECTION_NONE | LOCAL_LINK_PROTECTION_NONE):
1456 TPI_DEBUG_PRINT(("Protection = None\n"));
1457 RestartHDCP();
1458 break;
1459
1460 case LOCAL_LINK_PROTECTION_SECURE:
1461
1462 if (IsHDMI_Sink()) {
1463 ReadModifyWriteTPI(0x26, AUDIO_MUTE_MASK,
1464 AUDIO_MUTE_NORMAL);
1465 }
1466
1467 ReadModifyWriteTPI(0x1A, AV_MUTE_MASK, AV_MUTE_NORMAL);
1468 TPI_DEBUG_PRINT(("Protection = Local, Video Unmuted\n"));
1469 break;
1470
1471 case (EXTENDED_LINK_PROTECTION_SECURE | LOCAL_LINK_PROTECTION_SECURE):
1472 TPI_DEBUG_PRINT(("Protection = Extended\n"));
1473 #ifdef READKSV
1474 if (IsRepeater()) {
1475 RiCnt = ReadIndexedRegister(INDEXED_PAGE_0, 0x25);
1476 while (RiCnt > 0x70) /* Frame 112 */
1477 {
1478 RiCnt =
1479 ReadIndexedRegister(INDEXED_PAGE_0,
1480 0x25);
1481 }
1482 ReadModifyWriteTPI(0x1A, 0x06, 0x06);
1483 GetKSV();
1484 RiCnt = ReadByteTPI(0x1A);
1485 ReadModifyWriteTPI(0x1A, 0x08, 0x00);
1486 }
1487 #endif
1488 break;
1489
1490 default:
1491 TPI_DEBUG_PRINT(("Protection = Extended but not Local?\n"));
1492 RestartHDCP();
1493 break;
1494 }
1495 }
1496 #ifdef KSVFORWARD
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"));
1506 {
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 */
1510 do {
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));
1516 }
1517 } while ((ksv & KSV_FIFO_LAST_MASK) == KSV_FIFO_LAST_NO);
1518 TPI_DEBUG_PRINT(("KSV Fwd: Last KSV FIFO forward complete\n"));
1519 }
1520 }
1521 #endif
1522 ClearInterrupt(HDCP_CHANGE_EVENT);
1523 }
1524 }
1525 }
1526
1527
1528
1529
1530 /* ///////////////////////////////////////////////////////////////////////////// */
1531 /* ///////////////////////////////////////////////////////////////////////////// */
1532 /* /////////////////////*************************/////////////////////////////// */
1533 /* ///////////////////// AV CONFIG /////////////////////////////// */
1534 /* /////////////////////*************************/////////////////////////////// */
1535 /* ///////////////////////////////////////////////////////////////////////////// */
1536 /* ///////////////////////////////////////////////////////////////////////////// */
1537
1538 /* ------------------------------------------------------------------------------ */
1539 /* Video mode table */
1540 /* ------------------------------------------------------------------------------ */
1541 struct ModeIdType {
1542 byte Mode_C1;
1543 byte Mode_C2;
1544 byte SubMode;
1545 };
1546
1547 struct PxlLnTotalType {
1548 word Pixels;
1549 word Lines;
1550 };
1551 struct HVPositionType {
1552 word H;
1553 word V;
1554 };
1555
1556 struct HVResolutionType {
1557 word H;
1558 word V;
1559 };
1560
1561 struct TagType {
1562 byte RefrTypeVHPol;
1563 word VFreq;
1564 struct PxlLnTotalType Total;
1565 };
1566
1567 struct _656Type {
1568 byte IntAdjMode;
1569 word HLength;
1570 byte VLength;
1571 word Top;
1572 word Dly;
1573 word HBit2HSync;
1574 byte VBit2VSync;
1575 word Field2Offset;
1576 };
1577
1578 struct Vspace_Vblank {
1579 byte VactSpace1;
1580 byte VactSpace2;
1581 byte Vblank1;
1582 byte Vblank2;
1583 byte Vblank3;
1584 };
1585
1586 /* */
1587 /* WARNING! The entries in this enum must remian in the samre order as the PC Codes part */
1588 /* of the VideoModeTable[]. */
1589 /* */
1590 typedef enum {
1591 PC_640x350_85_08 = 0,
1592 PC_640x400_85_08,
1593 PC_720x400_70_08,
1594 PC_720x400_85_04,
1595 PC_640x480_59_94,
1596 PC_640x480_72_80,
1597 PC_640x480_75_00,
1598 PC_640x480_85_00,
1599 PC_800x600_56_25,
1600 PC_800x600_60_317,
1601 PC_800x600_72_19,
1602 PC_800x600_75,
1603 PC_800x600_85_06,
1604 PC_1024x768_60,
1605 PC_1024x768_70_07,
1606 PC_1024x768_75_03,
1607 PC_1024x768_85,
1608 PC_1152x864_75,
1609 PC_1600x1200_60,
1610 PC_1280x768_59_95,
1611 PC_1280x768_59_87,
1612 PC_280x768_74_89,
1613 PC_1280x768_85,
1614 PC_1280x960_60,
1615 PC_1280x960_85,
1616 PC_1280x1024_60,
1617 PC_1280x1024_75,
1618 PC_1280x1024_85,
1619 PC_1360x768_60,
1620 PC_1400x105_59_95,
1621 PC_1400x105_59_98,
1622 PC_1400x105_74_87,
1623 PC_1400x105_84_96,
1624 PC_1600x1200_65,
1625 PC_1600x1200_70,
1626 PC_1600x1200_75,
1627 PC_1600x1200_85,
1628 PC_1792x1344_60,
1629 PC_1792x1344_74_997,
1630 PC_1856x1392_60,
1631 PC_1856x1392_75,
1632 PC_1920x1200_59_95,
1633 PC_1920x1200_59_88,
1634 PC_1920x1200_74_93,
1635 PC_1920x1200_84_93,
1636 PC_1920x1440_60,
1637 PC_1920x1440_75,
1638 PC_12560x1440_60,
1639 PC_SIZE /* Must be last */
1640 } PcModeCode_t;
1641
1642 struct VModeInfoType {
1643 struct ModeIdType ModeId;
1644 dword PixClk;
1645 struct TagType Tag;
1646 struct HVPositionType Pos;
1647 struct HVResolutionType Res;
1648 byte AspectRatio;
1649 struct _656Type _656;
1650 byte PixRep;
1651 struct Vspace_Vblank VsVb;
1652 byte _3D_Struct;
1653 };
1654
1655 #define NSM 0 /* No Sub-Mode */
1656
1657 #define DEFAULT_VIDEO_MODE 0 /* 640 x 480p @ 60 VGA */
1658
1659 #define ProgrVNegHNeg 0x00
1660 #define ProgrVNegHPos 0x01
1661 #define ProgrVPosHNeg 0x02
1662 #define ProgrVPosHPos 0x03
1663
1664 #define InterlaceVNegHNeg 0x04
1665 #define InterlaceVPosHNeg 0x05
1666 #define InterlaceVNgeHPos 0x06
1667 #define InterlaceVPosHPos 0x07
1668
1669 #define VIC_BASE 0
1670 #define HDMI_VIC_BASE 43
1671 #define VIC_3D_BASE 47
1672 #define PC_BASE 64
1673
1674 /* Aspect ratio */
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 */
1679
1680 /* */
1681 /* These are the VIC codes that we support in a 3D mode */
1682 /* */
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 */
1692
1693
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 */
1742
1743 /* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */
1744 /* 4K x 2K Modes: */
1745 /* =================================================================================================================================================================================================================================== */
1746 /* Pulse */
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) */
1754
1755 /* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */
1756 /* 3D Modes: */
1757 /* =================================================================================================================================================================================================================================== */
1758 /* Pulse */
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 */
1779
1780 /* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */
1781 /* NOTE: DO NOT ATTEMPT INPUT RESOLUTIONS THAT REQUIRE PIXEL CLOCK FREQUENCIES HIGHER THAN THOSE SUPPORTED BY THE TRANSMITTER CHIP */
1782
1783 /* =================================================================================================================================================================================================================================== */
1784 /* Sync Pulse */
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 */
1837 };
1838
1839
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
1853 };
1854
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 */
1858 /* or 3D 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
1867 };
1868
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)
1880 {
1881 byte index;
1882
1883 /* */
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. */
1886 /* */
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. */
1890 /* */
1891 if (siHdmiTx.HDMIVideoFormat == VMD_HDMIFORMAT_CEA_VIC) {
1892 /* */
1893 /* This is a regular 861-D format VIC, so we use the VIC to Index */
1894 /* table to look up the index. */
1895 /* */
1896 index = VIC2Index[siHdmiTx.VIC];
1897 } else if (siHdmiTx.HDMIVideoFormat == VMD_HDMIFORMAT_HDMI_VIC) {
1898 /* */
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. */
1901 /* */
1902 if ((siHdmiTx.VIC < 1) || (siHdmiTx.VIC > 4)) {
1903 index = DEFAULT_VIDEO_MODE;
1904 } else {
1905 index = (HDMI_VIC_BASE - 1) + siHdmiTx.VIC;
1906 }
1907 } else if (siHdmiTx.HDMIVideoFormat == VMD_HDMIFORMAT_3D) {
1908 /* */
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. */
1912 /* */
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;
1919 else
1920 index = DEFAULT_VIDEO_MODE;
1921 break;
1922
1923 case VIC_FOR_720P_60Hz:
1924 switch (siHdmiTx.ThreeDStructure) {
1925 case FRAME_PACKING:
1926 index = VIC_3D_BASE + 1;
1927 break;
1928 default:
1929 index = DEFAULT_VIDEO_MODE;
1930 break;
1931 }
1932 break;
1933
1934 case VIC_FOR_1080i_60Hz:
1935 switch (siHdmiTx.ThreeDStructure) {
1936 case FRAME_PACKING:
1937 index = VIC_3D_BASE + 2;
1938 break;
1939 case VMD_3D_FIELDALTERNATIVE:
1940 index = VIC_3D_BASE + 3;
1941 break;
1942 default:
1943 index = DEFAULT_VIDEO_MODE;
1944 break;
1945 }
1946 break;
1947
1948 case VIC_FOR_1080p_60Hz:
1949 switch (siHdmiTx.ThreeDStructure) {
1950 case FRAME_PACKING:
1951 index = VIC_3D_BASE + 4;
1952 break;
1953 case VMD_3D_LINEALTERNATIVE:
1954 index = VIC_3D_BASE + 5;
1955 break;
1956 case SIDE_BY_SIDE_FULL:
1957 index = VIC_3D_BASE + 6;
1958 break;
1959 case SIDE_BY_SIDE_HALF:
1960 index = VIC_3D_BASE + 7;
1961 break;
1962 default:
1963 index = DEFAULT_VIDEO_MODE;
1964 break;
1965 }
1966 break;
1967
1968 case VIC_FOR_720P_50Hz:
1969 switch (siHdmiTx.ThreeDStructure) {
1970 case FRAME_PACKING:
1971 index = VIC_3D_BASE + 8;
1972 break;
1973 case VMD_3D_LDEPTH:
1974 index = VIC_3D_BASE + 9;
1975 break;
1976 case VMD_3D_LDEPTHGRAPHICS:
1977 index = VIC_3D_BASE + 10;
1978 break;
1979 default:
1980 index = DEFAULT_VIDEO_MODE;
1981 break;
1982 }
1983 break;
1984
1985 case VIC_FOR_1080i_50Hz:
1986 switch (siHdmiTx.ThreeDStructure) {
1987 case FRAME_PACKING:
1988 index = VIC_3D_BASE + 11;
1989 break;
1990 case VMD_3D_FIELDALTERNATIVE:
1991 index = VIC_3D_BASE + 12;
1992 break;
1993 default:
1994 index = DEFAULT_VIDEO_MODE;
1995 break;
1996 }
1997 break;
1998
1999 case VIC_FOR_1080p_50Hz:
2000 switch (siHdmiTx.ThreeDStructure) {
2001 case FRAME_PACKING:
2002 index = VIC_3D_BASE + 13;
2003 break;
2004 case VMD_3D_LINEALTERNATIVE:
2005 index = VIC_3D_BASE + 14;
2006 break;
2007 case SIDE_BY_SIDE_FULL:
2008 index = VIC_3D_BASE + 15;
2009 break;
2010 default:
2011 index = DEFAULT_VIDEO_MODE;
2012 break;
2013 }
2014 break;
2015
2016 case VIC_FOR_1080p_24Hz:
2017 switch (siHdmiTx.ThreeDStructure) {
2018 case FRAME_PACKING:
2019 index = VIC_3D_BASE + 16;
2020 break;
2021 default:
2022 index = DEFAULT_VIDEO_MODE;
2023 break;
2024 }
2025 break;
2026
2027 default:
2028 index = DEFAULT_VIDEO_MODE;
2029 break;
2030 }
2031 } else if (siHdmiTx.HDMIVideoFormat == VMD_HDMIFORMAT_PC) {
2032 if (siHdmiTx.VIC < PC_SIZE) {
2033 index = siHdmiTx.VIC + PC_BASE;
2034 } else {
2035 index = DEFAULT_VIDEO_MODE;
2036 }
2037 } else {
2038 /* This should never happen! If so, default to first table entry */
2039 index = DEFAULT_VIDEO_MODE;
2040 }
2041
2042 return index;
2043 }
2044
2045
2046 /* Patches */
2047 /* ======== */
2048 byte TPI_REG0x63_SAVED = 0;
2049
2050 /* ------------------------------------------------------------------------------ */
2051 /* Function Name: SetEmbeddedSync() */
2052 /* Function Description: Set the 9022/4 registers to extract embedded sync. */
2053 /* */
2054 /* Accepts: Index of video mode to set */
2055 /* Returns: TRUE */
2056 /* Globals: VModesTable[] */
2057 /* ------------------------------------------------------------------------------ */
2058 byte SetEmbeddedSync(void)
2059 {
2060 byte ModeTblIndex;
2061 word H_Bit_2_H_Sync;
2062 word Field2Offset;
2063 word H_SyncWidth;
2064
2065 byte V_Bit_2_V_Sync;
2066 byte V_SyncWidth;
2067 byte B_Data[8];
2068
2069 TPI_TRACE_PRINT((">>SetEmbeddedSync()\n"));
2070
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 */
2075
2076 ModeTblIndex = ConvertVIC_To_VM_Index();
2077
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;
2083
2084 B_Data[0] = H_Bit_2_H_Sync & LOW_BYTE; /* Setup HBIT_TO_HSYNC 8 LSBits (0x62) */
2085
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];
2089
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 */
2092
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 */
2097
2098 WriteBlockTPI(0x62, 8, &B_Data[0]);
2099
2100 return TRUE;
2101 }
2102
2103 /* ------------------------------------------------------------------------------ */
2104 /* Function Name: EnableEmbeddedSync() */
2105 /* Function Description: EnableEmbeddedSync */
2106 /* */
2107 /* Accepts: none */
2108 /* Returns: none */
2109 /* Globals: none */
2110 /* ------------------------------------------------------------------------------ */
2111 void EnableEmbeddedSync(void)
2112 {
2113 TPI_TRACE_PRINT((">>EnableEmbeddedSync()\n"));
2114
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);
2119 }
2120
2121 /* ------------------------------------------------------------------------------ */
2122 /* Function Name: SetDE() */
2123 /* Function Description: Set the 9022/4 internal DE generator parameters */
2124 /* */
2125 /* Accepts: none */
2126 /* Returns: DE_SET_OK */
2127 /* Globals: none */
2128 /* */
2129 /* NOTE: 0x60[7] must be set to "0" for the follwing settings to take effect */
2130 /* ------------------------------------------------------------------------------ */
2131 byte SetDE(void)
2132 {
2133 byte RegValue;
2134 byte ModeTblIndex;
2135
2136 word H_StartPos, V_StartPos;
2137 word Htotal, Vtotal;
2138 word H_Res, V_Res;
2139
2140 byte Polarity;
2141 byte B_Data[12];
2142
2143 TPI_TRACE_PRINT((">>SetDE()\n"));
2144
2145 ModeTblIndex = ConvertVIC_To_VM_Index();
2146
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"));
2150 }
2151 /* Make sure that External Sync method is set before enableing the DE Generator: */
2152 RegValue = ReadByteTPI(0x60);
2153
2154 if (RegValue & BIT_7) {
2155 return DE_CANNOT_BE_SET_WITH_EMBEDDED_SYNC;
2156 }
2157
2158 H_StartPos = VModesTable[ModeTblIndex].Pos.H;
2159 V_StartPos = VModesTable[ModeTblIndex].Pos.V;
2160
2161 Htotal = VModesTable[ModeTblIndex].Tag.Total.Pixels;
2162 Vtotal = VModesTable[ModeTblIndex].Tag.Total.Lines;
2163
2164 Polarity = (~VModesTable[ModeTblIndex].Tag.RefrTypeVHPol) & TWO_LSBITS;
2165
2166 H_Res = VModesTable[ModeTblIndex].Res.H;
2167
2168 if ((VModesTable[ModeTblIndex].Tag.RefrTypeVHPol & 0x04)) {
2169 V_Res = (VModesTable[ModeTblIndex].Res.V) >> 1; /* if interlace V-resolution divided by 2 */
2170 } else {
2171 V_Res = (VModesTable[ModeTblIndex].Res.V);
2172 }
2173
2174 B_Data[0] = H_StartPos & LOW_BYTE; /* 8 LSB of DE DLY in 0x62 */
2175
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 */
2179
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 */
2190
2191 WriteBlockTPI(0x62, 12, &B_Data[0]);
2192 TPI_REG0x63_SAVED = B_Data[1];
2193
2194 return DE_SET_OK; /* Write completed successfully */
2195 }
2196
2197 /* ------------------------------------------------------------------------------ */
2198 /* Function Name: SetFormat() */
2199 /* Function Description: Set the 9022/4 format */
2200 /* */
2201 /* Accepts: none */
2202 /* Returns: DE_SET_OK */
2203 /* Globals: none */
2204 /* ------------------------------------------------------------------------------ */
2205 void SetFormat(byte *Data)
2206 {
2207 ReadModifyWriteTPI(0x1A, OUTPUT_MODE_MASK, OUTPUT_MODE_HDMI); /* Set HDMI mode to allow color space conversion */
2208
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 */
2211
2212 if (!IsHDMI_Sink()) {
2213 ReadModifyWriteTPI(0x1A, OUTPUT_MODE_MASK, OUTPUT_MODE_DVI);
2214 }
2215
2216 if (siHdmiTx.SyncMode == EMBEDDED_SYNC)
2217 EnableEmbeddedSync(); /* Last byte of TPI AVI InfoFrame resets Embedded Sync Extraction */
2218 }
2219
2220 /* ------------------------------------------------------------------------------ */
2221 /* Function Name: printVideoMode() */
2222 /* Function Description: print video mode */
2223 /* */
2224 /* Accepts: siHdmiTx.VIC */
2225 /* Returns: none */
2226 /* Globals: none */
2227 /* ------------------------------------------------------------------------------ */
2228 void printVideoMode(void)
2229 {
2230 TPI_TRACE_PRINT((">>Video mode = "));
2231
2232 switch (siHdmiTx.VIC) {
2233 case 6:
2234 TPI_TRACE_PRINT(("HDMI_480I60_4X3\n"));
2235 break;
2236 case 21:
2237 TPI_TRACE_PRINT(("HDMI_576I50_4X3\n"));
2238 break;
2239 case 2:
2240 TPI_TRACE_PRINT(("HDMI_480P60_4X3\n"));
2241 break;
2242 case 17:
2243 TPI_TRACE_PRINT(("HDMI_576P50_4X3\n"));
2244 break;
2245 case 4:
2246 TPI_TRACE_PRINT(("HDMI_720P60\n"));
2247 break;
2248 case 19:
2249 TPI_TRACE_PRINT(("HDMI_720P50\n"));
2250 break;
2251 case 5:
2252 TPI_TRACE_PRINT(("HDMI_1080I60\n"));
2253 break;
2254 case 20:
2255 TPI_TRACE_PRINT(("HDMI_1080I50\n"));
2256 break;
2257 case 16:
2258 TPI_TRACE_PRINT(("HDMI_1080P60\n"));
2259 break;
2260 case 31:
2261 TPI_TRACE_PRINT(("HDMI_1080P50\n"));
2262 break;
2263 case PC_BASE + 13:
2264 TPI_TRACE_PRINT(("HDMI_1024_768_60\n"));
2265 break;
2266 case PC_BASE + 9:
2267 TPI_TRACE_PRINT(("HDMI_800_600_60\n"));
2268 break;
2269 default:
2270 break;
2271 }
2272 }
2273
2274 /* ------------------------------------------------------------------------------ */
2275 /* Function Name: InitVideo() */
2276 /* Function Description: Set the 9022/4 to the video mode determined by GetVideoMode() */
2277 /* */
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 */
2281 /* Returns: TRUE */
2282 /* Globals: VModesTable, VideoCommandImage */
2283 /* ------------------------------------------------------------------------------ */
2284 byte InitVideo(byte TclkSel)
2285 {
2286 byte ModeTblIndex;
2287
2288 #ifdef DEEP_COLOR
2289 byte temp;
2290 #endif
2291 byte B_Data[8];
2292
2293 byte EMB_Status; /* EmbeddedSync set flag */
2294 byte DE_Status;
2295 byte Pattern;
2296
2297 TPI_TRACE_PRINT((">>InitVideo()\n"));
2298 printVideoMode();
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));
2309
2310 ModeTblIndex = (byte) ConvertVIC_To_VM_Index();
2311
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 */
2314
2315 /* Take values from VModesTable[]: */
2316 if ((siHdmiTx.VIC == 6) || (siHdmiTx.VIC == 7) || /* 480i */
2317 (siHdmiTx.VIC == 21) || (siHdmiTx.VIC == 22)) /* 576i */
2318 {
2319 if (siHdmiTx.ColorSpace == YCBCR422_8BITS) /* 27Mhz pixel clock */
2320 {
2321 B_Data[0] = VModesTable[ModeTblIndex].PixClk & 0x00FF;
2322 B_Data[1] = (VModesTable[ModeTblIndex].PixClk >> 8) & 0xFF;
2323 } else /* 13.5Mhz pixel clock */
2324 {
2325 B_Data[0] = (VModesTable[ModeTblIndex].PixClk / 2) & 0x00FF;
2326 B_Data[1] = ((VModesTable[ModeTblIndex].PixClk / 2) >> 8) & 0xFF;
2327 }
2328
2329 } else {
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;
2332 }
2333
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;
2336
2337 if ((siHdmiTx.VIC == 6) || (siHdmiTx.VIC == 7) || /* 480i */
2338 (siHdmiTx.VIC == 21) || (siHdmiTx.VIC == 22)) /* 576i */
2339 {
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;
2342 } else {
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;
2345 }
2346
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;
2349
2350 WriteBlockTPI(0x00, 8, B_Data); /* Write TPI Mode data.//0x00-0x07 :Video Mode Defines the incoming resolution */
2351
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;
2359
2360 #ifdef CLOCK_EDGE_FALLING
2361 B_Data[0] &= ~BIT_EDGE_RISE; /* Set to falling edge */
2362 #endif
2363 #ifdef CLOCK_EDGE_RISING
2364 B_Data[0] |= BIT_EDGE_RISE; /* Set to rising edge */
2365 #endif
2366 tpivmode[0] = B_Data[0]; /* saved TPI Reg0x08 value. */
2367 WriteByteTPI(0x08, B_Data[0]); /* 0x08 */
2368
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 */
2374
2375 if (siHdmiTx.SyncMode == EMBEDDED_SYNC) {
2376 EMB_Status = SetEmbeddedSync();
2377 EnableEmbeddedSync(); /* enablle EmbeddedSync */
2378 }
2379
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 */
2383 }
2384
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 */
2387
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 */
2390
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 */
2394
2395 #ifdef DEEP_COLOR
2396 switch (siHdmiTx.ColorDepth) {
2397 case 0:
2398 temp = 0x00;
2399 ReadModifyWriteTPI(0x40, BIT_2, 0x00);
2400 break;
2401 case 1:
2402 temp = 0x80;
2403 ReadModifyWriteTPI(0x40, BIT_2, BIT_2);
2404 break;
2405 case 2:
2406 temp = 0xC0;
2407 ReadModifyWriteTPI(0x40, BIT_2, BIT_2);
2408 break;
2409 case 3:
2410 temp = 0x40;
2411 ReadModifyWriteTPI(0x40, BIT_2, BIT_2);
2412 break;
2413 default:
2414 temp = 0x00;
2415 ReadModifyWriteTPI(0x40, BIT_2, 0x00);
2416 break;
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. */
2420 }
2421 B_Data[0] = ((B_Data[0] & 0x3F) | temp); /* reg0x09 */
2422 #endif
2423
2424 B_Data[1] = (BITS_OUT_RGB | BITS_OUT_AUTO_RANGE); /* Reg0x0A */
2425
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 */
2430 {
2431 B_Data[1] &= ~BIT_BT_709;
2432 } else {
2433 B_Data[1] |= BIT_BT_709;
2434 }
2435
2436 #ifdef DEEP_COLOR
2437 B_Data[1] = ((B_Data[1] & 0x3F) | temp);
2438 #endif
2439
2440 #ifdef DEV_SUPPORT_EDID
2441 if (!IsHDMI_Sink()) {
2442 B_Data[1] = ((B_Data[1] & 0xFC) | BITS_OUT_RGB);
2443 } else {
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);
2447 } else {
2448 if (g_edid.YCbCr_4_2_2) {
2449 B_Data[1] = ((B_Data[1] & 0xFC) | BITS_OUT_YCBCR422);
2450 } else {
2451 B_Data[1] = ((B_Data[1] & 0xFC) | BITS_OUT_RGB);
2452 }
2453 }
2454 }
2455 #endif
2456
2457 tpivmode[1] = B_Data[0]; /* saved TPI Reg0x09 value. */
2458 tpivmode[2] = B_Data[1]; /* saved TPI Reg0x0A value. */
2459 SetFormat(B_Data);
2460
2461 ReadClearWriteTPI(0x60, BIT_2); /* Number HSync pulses from VSync active edge to Video Data Period should be 20 (VS_TO_VIDEO) */
2462
2463 return TRUE;
2464 }
2465
2466 /* ------------------------------------------------------------------------------ */
2467 /* Function Name: SetAVI_InfoFrames() */
2468 /* Function Description: Load AVI InfoFrame data into registers and send to sink */
2469 /* */
2470 /* Accepts: An API_Cmd parameter that holds the data to be sent in the InfoFrames */
2471 /* Returns: TRUE */
2472 /* Globals: none */
2473 /* */
2474 /* Note: : Infoframe contents are from spec CEA-861-D */
2475 /* */
2476 /* ------------------------------------------------------------------------------ */
2477 byte SetAVI_InfoFrames(void)
2478 {
2479 byte B_Data[SIZE_AVI_INFOFRAME];
2480 byte i;
2481 byte TmpVal;
2482 byte VModeTblIndex;
2483
2484 TPI_TRACE_PRINT((">>SetAVI_InfoFrames()\n"));
2485
2486 for (i = 0; i < SIZE_AVI_INFOFRAME; i++)
2487 B_Data[i] = 0;
2488
2489 #ifdef DEV_SUPPORT_EDID
2490 if (g_edid.YCbCr_4_4_4)
2491 TmpVal = 2;
2492 else if (g_edid.YCbCr_4_2_2)
2493 TmpVal = 1;
2494 else
2495 TmpVal = 0;
2496 #else
2497 TmpVal = 0;
2498 #endif
2499
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 */
2503
2504 if (siHdmiTx.ColorSpace == XVYCC444) /* Extended colorimetry - xvYCC */
2505 {
2506 B_Data[2] = 0xC0; /* Extended colorimetry info (B_Data[3] valid (CEA-861D, Table 11) */
2507
2508 if (siHdmiTx.Colorimetry == COLORIMETRY_601) /* xvYCC601 */
2509 B_Data[3] &= ~BITS_6_5_4;
2510
2511 else if (siHdmiTx.Colorimetry == COLORIMETRY_709) /* xvYCC709 */
2512 B_Data[3] = (B_Data[3] & ~BITS_6_5_4) | BIT_4;
2513 }
2514
2515 else if (siHdmiTx.Colorimetry == COLORIMETRY_709) /* BT.709 */
2516 B_Data[2] = 0x80; /* AVI Byte2: C1C0 */
2517
2518 else if (siHdmiTx.Colorimetry == COLORIMETRY_601) /* BT.601 */
2519 B_Data[2] = 0x40; /* AVI Byte2: C1C0 */
2520
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 */
2525 }
2526
2527 VModeTblIndex = ConvertVIC_To_VM_Index();
2528
2529 B_Data[4] = siHdmiTx.VIC;
2530
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)) {
2538 siHdmiTx.VIC++;
2539 B_Data[4]++;
2540 }
2541 } else {
2542 B_Data[2] |= _4_To_3; /* AVI Byte4: VIC */
2543 }
2544
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 */
2547
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];
2552 }
2553 B_Data[0] = 0x100 - B_Data[0];
2554
2555 /* Write the Inforframe data to the TPI Infoframe registers */
2556 WriteBlockTPI(0x0C, SIZE_AVI_INFOFRAME, B_Data);
2557
2558 if (siHdmiTx.SyncMode == EMBEDDED_SYNC)
2559 EnableEmbeddedSync();
2560
2561 return TRUE;
2562 }
2563
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. */
2569 /* */
2570 /* Accepts: none */
2571 /* Returns: none */
2572 /* Globals: siHdmiTx */
2573 /* ------------------------------------------------------------------------------ */
2574 void siHdmiTx_Init(void)
2575 {
2576 TPI_TRACE_PRINT((">>siHdmiTx_Init()\n"));
2577
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;
2585 }
2586 /* end workaround */
2587
2588 InitVideo(siHdmiTx.TclkSel); /* Set PLL Multiplier to x1 upon power up */
2589
2590 siHdmiTx_PowerStateD0();
2591
2592 if (IsHDMI_Sink()) /* Set InfoFrames only if HDMI output mode */
2593 {
2594 SetAVI_InfoFrames();
2595 siHdmiTx_AudioSet(); /* set audio interface to basic audio (an external command is needed to set to any other mode */
2596 } else {
2597 SetAudioMute(AUDIO_MUTE_MUTED);
2598 }
2599
2600 /* !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! */
2601 /* PATCH!!!PATCH!!!PATCH!!!PATCH!!!PATCH!!!PATCH!!!PATCH!!!PATCH!!!PATCH!!!PATCH!!!PATCH!!!PATCH!!! */
2602
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. */
2606
2607 /* THIS PATCH IS NEEDED BECAUSE SETTING UP AVI InfoFrames CLEARS 0x63 */
2608 WriteByteTPI(0x63, TPI_REG0x63_SAVED);
2609
2610 /* PATCH!!!PATCH!!!PATCH!!!PATCH!!!PATCH!!!PATCH!!!PATCH!!!PATCH!!!PATCH!!!PATCH!!!PATCH!!!PATCH!!! */
2611 /* !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! */
2612
2613 /* ========================================================== */
2614 WriteByteTPI(0x0B, 0x00);
2615
2616
2617 if ((g_hdcp.HDCP_TxSupports == TRUE) && (g_hdcp.HDCPAuthenticated == VMD_HDCP_AUTHENTICATED)
2618 && (Sii9024A_HDCP_supported)) {
2619 if (g_hdcp.HDCP_AksvValid == TRUE) {
2620 /* AV MUTE */
2621 TPI_DEBUG_PRINT(("TMDS -> Enabled (Video Muted)\n"));
2622 ReadModifyWriteTPI(0x1A,
2623 LINK_INTEGRITY_MODE_MASK | TMDS_OUTPUT_CONTROL_MASK |
2624 AV_MUTE_MASK,
2625 LINK_INTEGRITY_DYNAMIC | TMDS_OUTPUT_CONTROL_ACTIVE |
2626 AV_MUTE_MUTED);
2627
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);
2632 }
2633 } else {
2634 TPI_DEBUG_PRINT(("TMDS -> Enabled\n"));
2635 ReadModifyWriteTPI(0x1A,
2636 LINK_INTEGRITY_MODE_MASK | TMDS_OUTPUT_CONTROL_MASK |
2637 AV_MUTE_MASK,
2638 LINK_INTEGRITY_DYNAMIC | TMDS_OUTPUT_CONTROL_ACTIVE |
2639 AV_MUTE_MUTED);
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);
2644 }
2645 }
2646
2647 /* ------------------------------------------------------------------------------ */
2648 /* Function Name: siHdmiTx_VideoSet() */
2649 /* Function Description: Set the 9022/4 video resolution */
2650 /* */
2651 /* Accepts: none */
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 */
2658
2659 byte siHdmiTx_VideoSet(void)
2660 {
2661 TPI_TRACE_PRINT((">>siHdmiTx_VideoSet()\n"));
2662
2663 ReadModifyWriteTPI(0x1A, TMDS_OUTPUT_CONTROL_MASK | AV_MUTE_MASK,
2664 TMDS_OUTPUT_CONTROL_POWER_DOWN | AV_MUTE_MUTED);
2665
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;
2670
2671 /*
2672 #ifdef DEV_SUPPORT_HDCP
2673 HDCP_Off();
2674 #endif
2675
2676 DisableTMDS(); // turn off TMDS output
2677 DelayMS(T_RES_CHANGE_DELAY); // allow control InfoFrames to pass through to the sink device.
2678 */
2679 siHdmiTx_Init();
2680
2681 if (Sii9024A_HDCP_supported){
2682 DelayMS(200);
2683 HDCP_CheckStatus(ReadByteTPI(0x3D));
2684 }
2685
2686 return VIDEO_MODE_SET_OK;
2687 }
2688
2689 /* ------------------------------------------------------------------------------ */
2690 /* Function Name: SetAudioInfoFrames() */
2691 /* Function Description: Load Audio InfoFrame data into registers and send to sink */
2692 /* */
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. */
2698 /* Returns: TRUE */
2699 /* Globals: none */
2700 /* ------------------------------------------------------------------------------ */
2701 byte SetAudioInfoFrames(byte ChannelCount, byte CodingType, byte SS, byte Fs, byte SpeakerConfig)
2702 {
2703 byte B_Data[SIZE_AUDIO_INFOFRAME]; /* 14 */
2704 byte i;
2705 /* byte TmpVal = 0; */
2706
2707 TPI_TRACE_PRINT((">>SetAudioInfoFrames()\n"));
2708
2709 for (i = 0; i < SIZE_AUDIO_INFOFRAME; i++)
2710 B_Data[i] = 0;
2711
2712 WriteByteTPI(MISC_INFO_FRAMES_CTRL, DISABLE_AUDIO); /* Disbale MPEG/Vendor Specific InfoFrames */
2713
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;
2719
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 */
2722
2723 B_Data[5] = ((Fs & THREE_LSBITS) << 2) | (SS & TWO_LSBITS);
2724
2725 B_Data[7] = SpeakerConfig;
2726
2727 for (i = 4; i < SIZE_AUDIO_INFOFRAME; i++)
2728 B_Data[3] += B_Data[i];
2729
2730 B_Data[3] = 0x100 - B_Data[3];
2731
2732 WriteByteTPI(MISC_INFO_FRAMES_CTRL, EN_AND_RPT_AUDIO); /* Re-enable Audio InfoFrame transmission and repeat */
2733
2734 WriteBlockTPI(MISC_INFO_FRAMES_TYPE, SIZE_AUDIO_INFOFRAME, B_Data);
2735
2736 if (siHdmiTx.SyncMode == EMBEDDED_SYNC)
2737 EnableEmbeddedSync();
2738
2739 return TRUE;
2740 }
2741
2742 /* ------------------------------------------------------------------------------ */
2743 /* Function Name: SetAudioMute() */
2744 /* Function Description: Mute audio */
2745 /* */
2746 /* Accepts: Mute or unmute. */
2747 /* Returns: none */
2748 /* Globals: none */
2749 /* ------------------------------------------------------------------------------ */
2750 void SetAudioMute(byte audioMute)
2751 {
2752 ReadModifyWriteTPI(0x26, AUDIO_MUTE_MASK, audioMute);
2753 }
2754
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]) */
2759 /* */
2760 /* Accepts: Number of audio channels: "0 for 2-Channels ."1" for 8. */
2761 /* Returns: none */
2762 /* Globals: none */
2763 /* ------------------------------------------------------------------------------ */
2764 void SetChannelLayout(byte Count)
2765 {
2766 /* Indexed register 0x7A:0x2F[1]: */
2767 WriteByteTPI(0xBC, 0x02); /* Internal page 2 */
2768 WriteByteTPI(0xBD, 0x2F);
2769
2770 Count &= THREE_LSBITS;
2771
2772 if (Count == TWO_CHANNEL_LAYOUT) {
2773 /* Clear 0x2F[1]: */
2774 ReadClearWriteTPI(0xBE, BIT_1);
2775 }
2776
2777 else if (Count == EIGHT_CHANNEL_LAYOUT) {
2778 /* Set 0x2F[1]: */
2779 ReadSetWriteTPI(0xBE, BIT_1);
2780 }
2781 }
2782 #endif
2783
2784 /* ------------------------------------------------------------------------------ */
2785 /* Function Name: siHdmiTx_AudioSet() */
2786 /* Function Description: Set the 9022/4 audio interface to basic audio. */
2787 /* */
2788 /* Accepts: none */
2789 /* Returns: Success message if audio changed successfully. */
2790 /* Error Code if resolution change failed */
2791 /* Globals: siHdmiTx */
2792 /* ------------------------------------------------------------------------------ */
2793 byte siHdmiTx_AudioSet(void)
2794 {
2795 TPI_TRACE_PRINT((">>siHdmiTx_AudioSet()\n"));
2796
2797 SetAudioMute(AUDIO_MUTE_MUTED); /* mute output */
2798
2799 if (siHdmiTx.AudioMode == AMODE_I2S) /* I2S input */
2800 {
2801 ReadModifyWriteTPI(0x26, AUDIO_SEL_MASK, AUD_IF_I2S); /* 0x26 = 0x80 */
2802 WriteByteTPI(0x25, 0x08 | AUD_DO_NOT_CHECK); /* 0x25 */
2803 } else /* SPDIF input */
2804 {
2805 ReadModifyWriteTPI(0x26, AUDIO_SEL_MASK, AUD_IF_SPDIF); /* 0x26 = 0x40 */
2806 WriteByteTPI(0x25, AUD_PASS_BASIC); /* 0x25 = 0x00 */
2807 }
2808
2809 #ifndef F_9022A_9334
2810 if (siHdmiTx.AudioChannels == ACHANNEL_2CH)
2811 SetChannelLayout(TWO_CHANNELS); /* Always 2 channesl in S/PDIF */
2812 else
2813 SetChannelLayout(EIGHT_CHANNELS);
2814 #else
2815 if (siHdmiTx.AudioChannels == ACHANNEL_2CH)
2816 ReadClearWriteTPI(0x26, BIT_5); /* Use TPI 0x26[5] for 9022A/24A and 9334 channel layout */
2817 else
2818 ReadSetWriteTPI(0x26, BIT_5); /* Use TPI 0x26[5] for 9022A/24A and 9334 channel layout */
2819 #endif
2820
2821 if (siHdmiTx.AudioMode == AMODE_I2S) /* I2S input */
2822 {
2823 /* I2S - Map channels - replace with call to API MAPI2S */
2824 WriteByteTPI(0x1F, 0x80); /* 0x1F */
2825
2826 if (siHdmiTx.AudioChannels > ACHANNEL_2CH)
2827 WriteByteTPI(0x1F, 0x91);
2828
2829 if (siHdmiTx.AudioChannels > ACHANNEL_4CH)
2830 WriteByteTPI(0x1F, 0xA2);
2831
2832 if (siHdmiTx.AudioChannels > ACHANNEL_6CH)
2833 WriteByteTPI(0x1F, 0xB3);
2834
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);
2841
2842 /* Oscar 20100929 added for 16bit auido noise issue */
2843 WriteIndexedRegister(INDEXED_PAGE_1, 0x25, siHdmiTx.AudioWordLength);
2844
2845 /* I2S - Input Configuration */
2846 WriteByteTPI(0x20, siHdmiTx.AudioI2SFormat); /* TPI_Reg0x20 */
2847 }
2848
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);
2852
2853 SetAudioMute(AUDIO_MUTE_NORMAL); /* unmute output */
2854
2855 return AUDIO_MODE_SET_OK;
2856 }
2857
2858 #ifdef F_9022A_9334
2859 /* ------------------------------------------------------------------------------ */
2860 /* Function Name: SetGBD_InfoFrame() */
2861 /* Function Description: Sets and sends the the 9022A/4A GBD InfoFrames. */
2862 /* */
2863 /* Accepts: none */
2864 /* Returns: Success message if GBD packet set successfully. Error */
2865 /* Code if failed */
2866 /* Globals: none */
2867 /* NOTE: Currently this function is a place holder. It always returns a Success message */
2868 /* ------------------------------------------------------------------------------ */
2869 byte SetGBD_InfoFrame(void)
2870 {
2871 byte CheckSum;
2872
2873 TPI_TRACE_PRINT((">>SetGBD_InfoFrame()\n"));
2874
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 */
2880
2881 CheckSum = TYPE_GBD_INFOFRAME +
2882 NEXT_FIELD + GBD_PROFILE + AFFECTED_GAMUT_SEQ_NUM + ONLY_PACKET + CURRENT_GAMUT_SEQ_NUM;
2883
2884 CheckSum = 0x100 - CheckSum;
2885
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 */
2888
2889 return GBD_SET_SUCCESSFULLY;
2890 }
2891 #endif
2892
2893 #ifdef DEV_SUPPORT_3D
2894 /* ------------------------------------------------------------------------------ */
2895 /* Function Name: Set_VSIF() */
2896 /* Function Description: Construct Vendor Specific InfoFrame for 3D support. use MPEG InfoFrame */
2897 /* */
2898 /* Accepts: none */
2899 /* Returns: none */
2900 /* Globals: siHdmiTx */
2901 /* ------------------------------------------------------------------------------ */
2902 /* VSIF Constants */
2903 /* ============================================================ */
2904 #define VSIF_TYPE 0x81
2905 #define VSIF_VERSION 0x01
2906 #define VSIF_LEN 0x06
2907
2908 void Set_VSIF(void)
2909 {
2910 byte i;
2911 byte Data[SIZE_MPEG_INFOFRAME]; /* 10 */
2912
2913 for (i = 0; i < SIZE_MPEG_INFOFRAME; i++) {
2914 Data[i] = 0;
2915 }
2916
2917 /* Disable transmission of VSIF during re-configuration */
2918 WriteByteTPI(MISC_INFO_FRAMES_CTRL, DISABLE_MPEG);
2919
2920 /* Header Bytes */
2921 Data[0] = VSIF_TYPE; /* HB0 Packet Type 0x81 */
2922 Data[1] = VSIF_VERSION; /* HB1 Version = 0x01 */
2923
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 */
2928
2929 /* PB4 - HDMI_Video_Format into bits 7:5 */
2930 Data[7] = siHdmiTx.HDMIVideoFormat << 5;
2931
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;
2939 Data[9] = 0;
2940 break;
2941
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) {
2950 Data[2] = VSIF_LEN;
2951 Data[9] = siHdmiTx.ThreeDExtData << 4;
2952 } else {
2953 Data[2] = VSIF_LEN - 1;
2954 }
2955 break;
2956
2957 case VMD_HDMIFORMAT_CEA_VIC:
2958 default:
2959 Data[8] = 0;
2960 Data[9] = 0;
2961 break;
2962 }
2963
2964 /* Packet Bytes */
2965 Data[3] = VSIF_TYPE + /* PB0 partial checksum */
2966 VSIF_VERSION + Data[2];
2967
2968 /* Complete the checksum with PB1 through PB7 */
2969 for (i = 4; i < SIZE_MPEG_INFOFRAME; i++) {
2970 Data[3] += Data[i];
2971 }
2972 /* Data[3] %= 0x100; */
2973 Data[3] = 0x100 - Data[3]; /* Final checksum */
2974
2975 WriteByteTPI(MISC_INFO_FRAMES_CTRL, EN_AND_RPT_MPEG); /* Enable and Repeat MPEG/Vendor Specific InfoFrames */
2976
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. */
2979 }
2980 #endif
2981
2982
2983
2984
2985 /* ///////////////////////////////////////////////////////////////////////////// */
2986 /* ///////////////////////////////////////////////////////////////////////////// */
2987 /* /////////////////////*************************/////////////////////////////// */
2988 /* ///////////////////// TPI /////////////////////////////// */
2989 /* /////////////////////*************************/////////////////////////////// */
2990 /* ///////////////////////////////////////////////////////////////////////////// */
2991 /* ///////////////////////////////////////////////////////////////////////////// */
2992
2993
2994 /* ------------------------------------------------------------------------------ */
2995 /* Function Name: StartTPI() */
2996 /* Function Description: Start HW TPI mode by writing 0x00 to TPI address 0xC7. */
2997 /* */
2998 /* Accepts: none */
2999 /* Returns: TRUE if HW TPI started successfully. FALSE if failed to. */
3000 /* Globals: none */
3001 /* ------------------------------------------------------------------------------ */
3002 byte StartTPI(void)
3003 {
3004 byte devID = 0x00;
3005 word wID = 0x0000;
3006
3007 TPI_TRACE_PRINT((">>StartTPI()\n"));
3008
3009 WriteByteTPI(0xC7, 0x00); /* Write "0" to 72:C7 to start HW TPI mode */
3010
3011 DelayMS(100);
3012
3013 devID = ReadIndexedRegister(INDEXED_PAGE_0, 0x03);
3014 wID = devID;
3015 wID <<= 8;
3016 devID = ReadIndexedRegister(INDEXED_PAGE_0, 0x02);
3017 wID |= devID;
3018
3019 devID = ReadByteTPI(0x1B);
3020
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;
3024
3025 if (wID == 0x9022)
3026 Sii9024A_HDCP_supported = false;
3027 if (devID == SII902XA_DEVICE_ID)
3028 return TRUE;
3029
3030 TPI_TRACE_PRINT(("Unsupported TX, devID = 0x%X\n", (int)devID));
3031 return FALSE;
3032 }
3033
3034 /* ------------------------------------------------------------------------------ */
3035 /* Function Name: siHdmiTx_TPI_Init() */
3036 /* Function Description: TPI initialization: HW Reset, Interrupt enable. */
3037 /* */
3038 /* Accepts: none */
3039 /* Returns: TRUE or FLASE */
3040 /* Globals: none */
3041 /* ------------------------------------------------------------------------------ */
3042 byte siHdmiTx_TPI_Init(void)
3043 {
3044 TPI_TRACE_PRINT(("\n>>siHdmiTx_TPI_Init()\n"));
3045 TPI_TRACE_PRINT(("\n%s\n", TPI_FW_VERSION));
3046
3047 /* Chip powers up in D2 mode. */
3048 g_sys.txPowerState = TX_POWER_STATE_D0;
3049
3050 InitializeStateVariables();
3051
3052 /* Toggle TX reset pin */
3053 TxHW_Reset();
3054 WriteByteTPI(0xF5, 0x00);
3055 /* Enable HW TPI mode, check device ID */
3056 if (StartTPI()) {
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;
3061 HDCP_Init();
3062 }
3063 #ifdef DEV_SUPPORT_CEC
3064 /* SI_CecInit(); */
3065 #endif
3066
3067 EnableInterrupts(HOT_PLUG_EVENT);
3068
3069 return 0;
3070 }
3071
3072 return EPERM;
3073 }
3074
3075 /* ------------------------------------------------------------------------------ */
3076 /* Function Name: OnDownstreamRxPoweredDown() */
3077 /* Function Description: HDMI cable unplug handle. */
3078 /* */
3079 /* Accepts: none */
3080 /* Returns: none */
3081 /* Globals: none */
3082 /* ------------------------------------------------------------------------------ */
3083 void OnDownstreamRxPoweredDown(void)
3084 {
3085 TPI_DEBUG_PRINT(("DSRX -> Powered Down\n"));
3086 g_sys.dsRxPoweredUp = FALSE;
3087
3088 if (g_hdcp.HDCP_Started == TRUE && Sii9024A_HDCP_supported)
3089 HDCP_Off();
3090 DisableTMDS();
3091 ReadModifyWriteTPI(0x1A, OUTPUT_MODE_MASK, OUTPUT_MODE_DVI); /* Set to DVI output mode to reset HDCP */
3092 }
3093
3094 extern void HotPlugService(void);
3095 /* ------------------------------------------------------------------------------ */
3096 /* Function Name: OnDownstreamRxPoweredUp() */
3097 /* Function Description: DSRX power up handle. */
3098 /* */
3099 /* Accepts: none */
3100 /* Returns: none */
3101 /* Globals: none */
3102 /* ------------------------------------------------------------------------------ */
3103 void OnDownstreamRxPoweredUp(void)
3104 {
3105 TPI_DEBUG_PRINT(("DSRX -> Powered Up\n"));
3106 g_sys.dsRxPoweredUp = TRUE;
3107
3108 HotPlugService();
3109 }
3110
3111 /* ------------------------------------------------------------------------------ */
3112 /* Function Name: OnHdmiCableDisconnected() */
3113 /* Function Description: HDMI cable unplug handle. */
3114 /* */
3115 /* Accepts: none */
3116 /* Returns: none */
3117 /* Globals: none */
3118 /* ------------------------------------------------------------------------------ */
3119 void OnHdmiCableDisconnected(void)
3120 {
3121 TPI_DEBUG_PRINT(("HDMI Disconnected\n"));
3122
3123 g_sys.hdmiCableConnected = FALSE;
3124
3125 #ifdef DEV_SUPPORT_EDID
3126 g_edid.edidDataValid = FALSE;
3127 #endif
3128
3129 OnDownstreamRxPoweredDown();
3130 /* siHdmiTx_PowerStateD3(); */
3131 }
3132
3133 /* ------------------------------------------------------------------------------ */
3134 /* Function Name: OnHdmiCableConnected() */
3135 /* Function Description: HDMI cable plug in handle. */
3136 /* */
3137 /* Accepts: none */
3138 /* Returns: none */
3139 /* Globals: none */
3140 /* ------------------------------------------------------------------------------ */
3141 void OnHdmiCableConnected(void)
3142 {
3143 TPI_DEBUG_PRINT(("Cable Connected\n"));
3144 /* No need to call TPI_Init here unless TX has been powered down on cable removal. */
3145 /* TPI_Init(); */
3146
3147 g_sys.hdmiCableConnected = TRUE;
3148
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);
3156 }
3157
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); */
3161
3162 #ifdef DEV_SUPPORT_EDID
3163 DoEdidRead();
3164 #endif
3165
3166 #ifdef READKSV
3167 ReadModifyWriteTPI(0xBB, 0x08, 0x08);
3168 #endif
3169
3170 if (IsHDMI_Sink()) /* select output mode (HDMI/DVI) according to sink capabilty */
3171 {
3172 TPI_DEBUG_PRINT(("HDMI Sink Detected\n"));
3173 ReadModifyWriteTPI(0x1A, OUTPUT_MODE_MASK, OUTPUT_MODE_HDMI);
3174 } else {
3175 TPI_DEBUG_PRINT(("DVI Sink Detected\n"));
3176 ReadModifyWriteTPI(0x1A, OUTPUT_MODE_MASK, OUTPUT_MODE_DVI);
3177 }
3178 }
3179
3180 /* ------------------------------------------------------------------------------ */
3181 /* Function Name: siHdmiTx_PowerStateD0() */
3182 /* Function Description: Set TX to D0 mode. */
3183 /* ------------------------------------------------------------------------------ */
3184 void siHdmiTx_PowerStateD0(void)
3185 {
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;
3189 }
3190
3191 /* ------------------------------------------------------------------------------ */
3192 /* Function Name: siHdmiTx_PowerStateD2() */
3193 /* Function Description: Set TX to D2 mode. */
3194 /* ------------------------------------------------------------------------------ */
3195 void siHdmiTx_PowerStateD2(void)
3196 {
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;
3200 }
3201
3202 /* ------------------------------------------------------------------------------ */
3203 /* Function Name: siHdmiTx_PowerStateD0fromD2() */
3204 /* Function Description: Set TX to D0 mode from D2 mode. */
3205 /* ------------------------------------------------------------------------------ */
3206 void siHdmiTx_PowerStateD0fromD2(void)
3207 {
3208 ReadModifyWriteTPI(0x1E, TX_POWER_STATE_MASK, TX_POWER_STATE_D0);
3209
3210 if (Sii9024A_HDCP_supported)
3211 RestartHDCP();
3212 else
3213 EnableTMDS();
3214
3215 TPI_DEBUG_PRINT(("TX Power State D0 from D2\n"));
3216 g_sys.txPowerState = TX_POWER_STATE_D0;
3217 }
3218
3219
3220 /* ------------------------------------------------------------------------------ */
3221 /* Function Name: siHdmiTx_PowerStateD3() */
3222 /* Function Description: Set TX to D3 mode. */
3223 /* ------------------------------------------------------------------------------ */
3224 /* 2011.06.27 Go to D3 */
3225 #define D3_hot
3226
3227 void siHdmiTx_PowerStateD3(void)
3228 {
3229 #ifdef D3_hot
3230 /* D3 hot */
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;
3236 #endif
3237
3238 #ifdef D3_cold
3239 /* D3 cold Note:It is necessary to unplug the HDMI connector, otherwise would not go to D3 cold. */
3240 WriteByteTPI(0x3D, 0xFF);
3241 TxHW_Reset();
3242 WriteByteTPI(0xC7, 0x00);
3243 DelayMS(100);
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;
3250 #endif
3251 }
3252
3253 /* 2011.06.27 Go to D3 End */
3254
3255 /* ------------------------------------------------------------------------------ */
3256 /* Function Name: HotPlugService() */
3257 /* Function Description: Implement Hot Plug Service Loop activities */
3258 /* */
3259 /* Accepts: none */
3260 /* Returns: An error code that indicates success or cause of failure */
3261 /* Globals: LinkProtectionLevel */
3262 /* ------------------------------------------------------------------------------ */
3263 void HotPlugService(void)
3264 {
3265 TPI_TRACE_PRINT((">>HotPlugService()\n"));
3266
3267 DisableInterrupts(0xFF);
3268
3269 /* siHdmiTx.VIC = g_edid.VideoDescriptor[0]; // use 1st mode supported by sink */
3270
3271 siHdmiTx_Init();
3272 }
3273
3274 /* ------------------------------------------------------------------------------ */
3275 /* Function Name: siHdmiTx_TPI_Poll() */
3276 /* Function Description: Poll Interrupt Status register for new interrupts */
3277 /* */
3278 /* Accepts: none */
3279 /* Returns: none */
3280 /* Globals: none */
3281 /* ------------------------------------------------------------------------------ */
3282
3283 void siHdmiTx_TPI_Poll(void)
3284 {
3285 byte InterruptStatus;
3286
3287 if (g_sys.txPowerState == TX_POWER_STATE_D0) {
3288 InterruptStatus = ReadByteTPI(0x3D);
3289
3290 if (InterruptStatus & HOT_PLUG_EVENT) /* judge if HPD is connected */
3291 {
3292 TPI_DEBUG_PRINT(("HPD -> "));
3293 ReadSetWriteTPI(0x3C, HOT_PLUG_EVENT); /* Enable HPD interrupt bit */
3294
3295 /* Repeat this loop while cable is bouncing: */
3296 do {
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 */
3301
3302 if (((InterruptStatus & HOT_PLUG_STATE) >> 2) != g_sys.hdmiCableConnected) {
3303 if (g_sys.hdmiCableConnected == TRUE) {
3304 OnHdmiCableDisconnected();
3305 hdmi_util.state_callback(0);
3306 } else {
3307 OnHdmiCableConnected();
3308 ReadModifyWriteIndexedRegister(INDEXED_PAGE_0, 0x0A, 0x08,
3309 0x08);
3310 }
3311
3312 if (g_sys.hdmiCableConnected == FALSE) {
3313 return;
3314 }
3315
3316 /*if (g_sys.hdmiCableConnected == FALSE)
3317 {
3318 return;
3319 }*/
3320 }
3321 else if((g_sys.hdmiCableConnected)&&(Sii9024A_HDCP_supported))
3322 {
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);
3326 HDCP_Off();
3327 DelayMS(100);
3328 ReadModifyWriteTPI(0x1A, TMDS_OUTPUT_CONTROL_MASK, TMDS_OUTPUT_CONTROL_ACTIVE);
3329 WriteByteTPI(0x08, tpivmode[0]);
3330 }
3331 }
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);
3338 } else {
3339 OnDownstreamRxPoweredUp();
3340 hdmi_util.state_callback(1);
3341 }
3342 }
3343 DelayMS(100); // Delay for metastability protection and to help filter out connection bouncing
3344 ClearInterrupt(RX_SENSE_EVENT);
3345 }
3346 /* Check if RX_SENSE_EVENT has occurred: */
3347 if (InterruptStatus & RX_SENSE_EVENT) {
3348 ClearInterrupt(RX_SENSE_EVENT);
3349 }
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);
3355 }
3356
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);
3362 }
3363 #ifdef DEV_SUPPORT_CEC
3364 SI_CecHandler(0, 0);
3365 #endif
3366 }
3367
3368 if (g_sys.txPowerState == TX_POWER_STATE_D3)
3369 {
3370 /* HDMI_reset(); */
3371 siHdmiTx_TPI_Init();
3372 /* siHdmiTx_VideoSet(); */
3373 TPI_DEBUG_PRINT(("***up from INT ***\n"));
3374 }
3375
3376 }
3377
3378
3379 /* ------------------------------------------------------------------------------ */
3380 /* Function Name: siHdmiTx_VideoSel() */
3381 /* Function Description: Select output video mode */
3382 /* */
3383 /* Accepts: Video mode */
3384 /* Returns: none */
3385 /* Globals: none */
3386 /* ------------------------------------------------------------------------------ */
3387 void siHdmiTx_VideoSel(byte vmode)
3388 {
3389 siHdmiTx.HDMIVideoFormat = VMD_HDMIFORMAT_CEA_VIC;
3390 siHdmiTx.ColorSpace = RGB;
3391 siHdmiTx.ColorDepth = VMD_COLOR_DEPTH_8BIT;
3392 siHdmiTx.SyncMode = EXTERNAL_HSVSDE;
3393
3394 switch (vmode) {
3395 case HDMI_480I60_4X3:
3396 siHdmiTx.VIC = 6;
3397 siHdmiTx.AspectRatio = VMD_ASPECT_RATIO_4x3;
3398 siHdmiTx.Colorimetry = COLORIMETRY_601;
3399 siHdmiTx.TclkSel = X2;
3400 break;
3401
3402 case HDMI_576I50_4X3:
3403 siHdmiTx.VIC = 21;
3404 siHdmiTx.AspectRatio = VMD_ASPECT_RATIO_4x3;
3405 siHdmiTx.Colorimetry = COLORIMETRY_601;
3406 siHdmiTx.TclkSel = X2;
3407 break;
3408
3409 case HDMI_480P60_4X3:
3410 siHdmiTx.VIC = 2;
3411 siHdmiTx.AspectRatio = VMD_ASPECT_RATIO_4x3;
3412 siHdmiTx.Colorimetry = COLORIMETRY_601;
3413 siHdmiTx.TclkSel = X1;
3414 break;
3415
3416 case HDMI_576P50_4X3:
3417 siHdmiTx.VIC = 17;
3418 siHdmiTx.AspectRatio = VMD_ASPECT_RATIO_4x3;
3419 siHdmiTx.Colorimetry = COLORIMETRY_601;
3420 siHdmiTx.TclkSel = X1;
3421 break;
3422
3423 case HDMI_720P60:
3424 siHdmiTx.VIC = 4;
3425 siHdmiTx.AspectRatio = VMD_ASPECT_RATIO_16x9;
3426 siHdmiTx.Colorimetry = COLORIMETRY_709;
3427 siHdmiTx.TclkSel = X1;
3428 break;
3429
3430 case HDMI_720P50:
3431 siHdmiTx.VIC = 19;
3432 siHdmiTx.AspectRatio = VMD_ASPECT_RATIO_16x9;
3433 siHdmiTx.Colorimetry = COLORIMETRY_709;
3434 siHdmiTx.TclkSel = X1;
3435 break;
3436
3437 case HDMI_1080I60:
3438 siHdmiTx.VIC = 5;
3439 siHdmiTx.AspectRatio = VMD_ASPECT_RATIO_16x9;
3440 siHdmiTx.Colorimetry = COLORIMETRY_709;
3441 siHdmiTx.TclkSel = X1;
3442 break;
3443
3444 case HDMI_1080I50:
3445 siHdmiTx.VIC = 20;
3446 siHdmiTx.AspectRatio = VMD_ASPECT_RATIO_16x9;
3447 siHdmiTx.Colorimetry = COLORIMETRY_709;
3448 siHdmiTx.TclkSel = X1;
3449 break;
3450
3451 case HDMI_1080P60:
3452 siHdmiTx.VIC = 16;
3453 siHdmiTx.AspectRatio = VMD_ASPECT_RATIO_16x9;
3454 siHdmiTx.Colorimetry = COLORIMETRY_709;
3455 siHdmiTx.TclkSel = X1;
3456 break;
3457
3458 case HDMI_1080P50:
3459 siHdmiTx.VIC = 31;
3460 siHdmiTx.AspectRatio = VMD_ASPECT_RATIO_16x9;
3461 siHdmiTx.Colorimetry = COLORIMETRY_709;
3462 siHdmiTx.TclkSel = X1;
3463 break;
3464
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;
3470 break;
3471
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;
3477 break;
3478
3479 case HDMI_1080P30:
3480 siHdmiTx.VIC = 34;
3481 siHdmiTx.AspectRatio = VMD_ASPECT_RATIO_16x9;
3482 siHdmiTx.Colorimetry = COLORIMETRY_709;
3483 siHdmiTx.TclkSel = X1;
3484 break;
3485
3486 case HDMI_1080P24:
3487 siHdmiTx.VIC = 32;
3488 siHdmiTx.AspectRatio = VMD_ASPECT_RATIO_16x9;
3489 siHdmiTx.Colorimetry = COLORIMETRY_709;
3490 siHdmiTx.TclkSel = X1;
3491 break;
3492
3493 default:
3494 break;
3495 }
3496
3497 TPI_DEBUG_PRINT(("siHdmiTx_VideoSel vmode=%d\n", vmode));
3498 }
3499
3500 /* ------------------------------------------------------------------------------ */
3501 /* Function Name: siHdmiTx_AudioSel() */
3502 /* Function Description: Select output audio mode */
3503 /* */
3504 /* Accepts: Audio Fs */
3505 /* Returns: none */
3506 /* Globals: none */
3507 /* ------------------------------------------------------------------------------ */
3508 void siHdmiTx_AudioSel(byte Afs)
3509 {
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 */
3515 }