1 /*
2  * Copyright (c) 2022 ITE.
3  * Copyright 2022 NXP
4  *
5  * SPDX-License-Identifier: BSD-3-Clause
6  */
7 
8 #include "fsl_it6161.h"
9 #include "hdmi_tx.h"
10 #include "fsl_debug_console.h"
11 
12 static RX_CAP RxCapability;
13 static uint8_t CommonBuff[128] = {0U};
14 
15 static uint8_t bCSCMtx_RGB2YUV_ITU601_16_235[] = {0x00, 0x80, 0x00, 0xB2, 0x04, 0x65, 0x02, 0xE9, 0x00, 0x93, 0x3C,
16                                                   0x18, 0x04, 0x55, 0x3F, 0x49, 0x3D, 0x9F, 0x3E, 0x18, 0x04};
17 
18 static uint8_t bCSCMtx_RGB2YUV_ITU601_0_255[] = {0x10, 0x80, 0x10, 0x09, 0x04, 0x0E, 0x02, 0xC9, 0x00, 0x0F, 0x3D,
19                                                  0x84, 0x03, 0x6D, 0x3F, 0xAB, 0x3D, 0xD1, 0x3E, 0x84, 0x03};
20 
21 static uint8_t bCSCMtx_RGB2YUV_ITU709_16_235[] = {0x00, 0x80, 0x00, 0xB8, 0x05, 0xB4, 0x01, 0x94, 0x00, 0x4a, 0x3C,
22                                                   0x17, 0x04, 0x9F, 0x3F, 0xD9, 0x3C, 0x10, 0x3F, 0x17, 0x04};
23 
24 static uint8_t bCSCMtx_RGB2YUV_ITU709_0_255[] = {0x10, 0x80, 0x10, 0xEa, 0x04, 0x77, 0x01, 0x7F, 0x00, 0xD0, 0x3C,
25                                                  0x83, 0x03, 0xAD, 0x3F, 0x4B, 0x3D, 0x32, 0x3F, 0x83, 0x03};
26 
27 static uint8_t bCSCMtx_YUV2RGB_ITU601_16_235[] = {0x00, 0x00, 0x00, 0x00, 0x08, 0x6B, 0x3A, 0x50, 0x3D, 0x00, 0x08,
28                                                   0xF5, 0x0A, 0x02, 0x00, 0x00, 0x08, 0xFD, 0x3F, 0xDA, 0x0D};
29 
30 static uint8_t bCSCMtx_YUV2RGB_ITU601_0_255[] = {0x04, 0x00, 0xA7, 0x4F, 0x09, 0x81, 0x39, 0xDD, 0x3C, 0x4F, 0x09,
31                                                  0xC4, 0x0C, 0x01, 0x00, 0x4F, 0x09, 0xFD, 0x3F, 0x1F, 0x10};
32 
33 static uint8_t bCSCMtx_YUV2RGB_ITU709_16_235[] = {0x00, 0x00, 0x00, 0x00, 0x08, 0x55, 0x3C, 0x88, 0x3E, 0x00, 0x08,
34                                                   0x51, 0x0C, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x84, 0x0E};
35 
36 static uint8_t bCSCMtx_YUV2RGB_ITU709_0_255[] = {0x04, 0x00, 0xA7, 0x4F, 0x09, 0xBA, 0x3B, 0x4B, 0x3E, 0x4F, 0x09,
37                                                  0x57, 0x0E, 0x02, 0x00, 0x4F, 0x09, 0xFE, 0x3F, 0xE8, 0x10};
38 
HDMITX_LoadRegSetting(display_handle_t * handle,RegSetTable_t * table,uint32_t table_sz)39 void HDMITX_LoadRegSetting(display_handle_t *handle, RegSetTable_t *table, uint32_t table_sz)
40 {
41     uint32_t i;
42 
43     for (i = 0U; i < table_sz / sizeof(RegSetTable_t); i++)
44     {
45         if (table[i].invAndMask == 0xFFU)
46         {
47             HDMITX_WriteI2C_Byte(handle, table[i].offset, table[i].OrMask);
48         }
49         else
50         {
51             HDMITX_SetI2C_Byte(handle, table[i].offset, table[i].invAndMask, table[i].OrMask);
52         }
53     }
54 }
55 
HDMITX_DisableAudioOutput(display_handle_t * handle)56 static void HDMITX_DisableAudioOutput(display_handle_t *handle)
57 {
58     HDMITX_SetI2C_Byte(handle, HDMI_TX_GENERAL_REG04, (B_HDMITX_AUD_RST | B_TX_AREF_RST),
59                        (B_HDMITX_AUD_RST | B_TX_AREF_RST));
60     HDMITX_SetI2C_Byte(handle, 0x0F, 0x10, 0x10);
61 }
62 
HDMITX_VideoReset(display_handle_t * handle)63 void HDMITX_VideoReset(display_handle_t *handle)
64 {
65     HDMITX_SetI2C_Byte(handle, HDMI_TX_GENERAL_REG04, B_HDMITX_VID_RST, B_HDMITX_VID_RST);
66     HDMITX_SetI2C_Byte(handle, HDMI_TX_GENERAL_REG04, B_HDMITX_VID_RST, 0x00);
67     delay1ms(10);
68 }
69 
HDMITX_ChangeBank(display_handle_t * handle,uint8_t value)70 static inline void HDMITX_ChangeBank(display_handle_t *handle, uint8_t value)
71 {
72     HDMITX_SetI2C_Byte(handle, 0x0F, 0x03, (uint32_t)value & 0x03U);
73 }
74 
DumpHDMITXReg(display_handle_t * handle)75 static void DumpHDMITXReg(display_handle_t *handle)
76 {
77 #if (DEBUG_DUMP_HDMITX_REGISTER == 0x01U)
78     int i = 0, j = 0;
79     uint8_t ucData = 0U;
80 
81     PRINTF("       ");
82     for (j = 0; j < 16; j++)
83     {
84         PRINTF(" %02X", j);
85         if ((j == 3) || (j == 7) || (j == 11))
86         {
87             PRINTF("  ");
88         }
89     }
90     PRINTF("\r\n        -----------------------------------------------------\r\n");
91 
92     HDMITX_ChangeBank(handle, 0);
93 
94     for (i = 0; i < 0x100; i += 16)
95     {
96         PRINTF("[%3X]  ", i);
97         for (j = 0; j < 16; j++)
98         {
99             if ((i + j) != 0x17)
100             {
101                 HDMITX_ReadI2C_Byte(handle, (uint8_t)((i + j) & 0xFFU), &ucData);
102                 PRINTF(" %02X", (int)ucData);
103             }
104             else
105             {
106                 PRINTF(" XX", (int)ucData); // for DDC FIFO
107             }
108             if ((j == 3) || (j == 7) || (j == 11))
109             {
110                 PRINTF(" -");
111             }
112         }
113         PRINTF("\r\n");
114         if ((i % 0x40) == 0x30)
115         {
116             PRINTF("        -----------------------------------------------------\r\n");
117         }
118     }
119     HDMITX_ChangeBank(handle, 1);
120     for (i = 0x130; i < 0x200; i += 16)
121     {
122         PRINTF("[%3X]  ", i);
123         for (j = 0; j < 16; j++)
124         {
125             HDMITX_ReadI2C_Byte(handle, (uint8_t)((i + j) & 0xFF), &ucData);
126             PRINTF(" %02X", (int)ucData);
127             if ((j == 3) || (j == 7) || (j == 11))
128             {
129                 PRINTF(" -");
130             }
131         }
132         PRINTF("\r\n");
133         if ((i % 0x40) == 0x20)
134         {
135             PRINTF("        -----------------------------------------------------\r\n");
136         }
137     }
138     PRINTF("        -----------------------------------------------------\r\n");
139     HDMITX_ChangeBank(handle, 0);
140 #endif
141 }
142 
HDMITX_DisableVideoOutput(display_handle_t * handle)143 static void HDMITX_DisableVideoOutput(display_handle_t *handle)
144 {
145     HDMITX_SetI2C_Byte(handle, HDMI_TX_GENERAL_REG04, B_HDMITX_VID_RST, B_HDMITX_VID_RST);
146     HDMITX_WriteI2C_Byte(handle, REG_TX_AFE_DRV_CTRL, B_TX_AFE_DRV_RST | B_TX_AFE_DRV_PWD);
147     HDMITX_SetI2C_Byte(handle, 0x62, 0x90, 0x00);
148     HDMITX_SetI2C_Byte(handle, 0x64, 0x89, 0x00);
149 }
150 
HDMITX_GetSinkHpd(display_handle_t * handle)151 static inline bool HDMITX_GetSinkHpd(display_handle_t *handle)
152 {
153     uint8_t tx_sys_status = 0;
154 
155     HDMITX_ReadI2C_Byte(handle, HDMI_TX_SYS_STATUS_REG0E, &tx_sys_status);
156 
157     return (bool)(tx_sys_status & HDMI_TX_SYS_STATUS_REG0E_RHPDetect_MASK);
158 }
159 
HDMITX_ClearDDCFIFO(display_handle_t * handle)160 static void HDMITX_ClearDDCFIFO(display_handle_t *handle)
161 {
162     HDMITX_WriteI2C_Byte(handle, HDMI_TX_SYS_DDC_CTRL_REG10, HDMI_TX_SYS_DDC_CTRL_REG10_Reg_MasterSel_MASK);
163     HDMITX_WriteI2C_Byte(handle, HDMI_TX_SYS_DDC_CTRL_REG15, HDMI_TX_SYS_DDC_CTRL_REG15_RDDC_Req_DDC_FIFO_clear);
164 }
165 
HDMITX_AbortDDC(display_handle_t * handle)166 static void HDMITX_AbortDDC(display_handle_t *handle)
167 {
168     uint8_t SWReset = 0U;
169     uint8_t uc = 0U, timeout = 0U, i = 0U;
170 
171     // save the SW reset,DDC master,and CP Desire setting.
172     HDMITX_ReadI2C_Byte(handle, HDMI_TX_GENERAL_REG04, &SWReset);
173 
174     HDMITX_WriteI2C_Byte(handle, HDMI_TX_GENERAL_REG04, (uint32_t)SWReset | (uint32_t)B_TX_HDCP_RST_HDMITX);
175     HDMITX_WriteI2C_Byte(handle, HDMI_TX_SYS_DDC_CTRL_REG10, HDMI_TX_SYS_DDC_CTRL_REG10_Reg_MasterSel_MASK);
176 
177     for (i = 0; i < 2U; i++)
178     {
179         HDMITX_WriteI2C_Byte(handle, HDMI_TX_SYS_DDC_CTRL_REG15, HDMI_TX_SYS_DDC_CTRL_REG15_RDDC_Req_Abort_DDC_CMD);
180 
181         for (timeout = 0; timeout < 200U; timeout++)
182         {
183             HDMITX_ReadI2C_Byte(handle, HDMI_TX_SYS_DDC_CTRL_REG16, &uc);
184             if ((uc & HDMI_TX_SYS_DDC_CTRL_REG16_RDDC_Status_Done_MASK) != 0U)
185             {
186                 break; // success
187             }
188             if ((uc & (HDMI_TX_SYS_DDC_CTRL_REG16_RDDC_Status_NoACK_MASK |
189                        HDMI_TX_SYS_DDC_CTRL_REG16_RDDC_Status_WaitBus_MASK |
190                        HDMI_TX_SYS_DDC_CTRL_REG16_RDDC_Status_ArbiLose_MASK)) != 0U)
191             {
192                 break;
193             }
194             delay1ms(1); // delay 1 ms to stable.
195         }
196     }
197 }
198 
getHDMITX_EDIDBytes(display_handle_t * handle,uint8_t * pData,uint8_t bSegment,uint8_t offset,uint16_t Count)199 static bool getHDMITX_EDIDBytes(
200     display_handle_t *handle, uint8_t *pData, uint8_t bSegment, uint8_t offset, uint16_t Count)
201 {
202     uint16_t RemainedCount = 0U, ReqCount = 0U;
203     uint8_t bCurrOffset = 0U;
204     uint16_t TimeOut    = 0U;
205     uint8_t *pBuff      = pData;
206     uint8_t ucdata      = 0U;
207     uint8_t value       = 0U;
208 
209     if (pData == NULL)
210     {
211         return false;
212     }
213     HDMITX_ReadI2C_Byte(handle, HDMI_TX_INT_FLAGS_REG06, &value);
214     if ((value & HDMI_TX_INT_FLAGS_REG06_RInt_DDCBusHang_MASK) != 0U)
215     {
216         HDMITX_DEBUG_PRINTF("Called hdmitx_AboutDDC()\n");
217         HDMITX_AbortDDC(handle);
218     }
219 
220     HDMITX_ClearDDCFIFO(handle);
221 
222     RemainedCount = Count;
223     bCurrOffset   = offset;
224 
225     HDMITX_ChangeBank(handle, 0);
226 
227     while (RemainedCount > 0U)
228     {
229         ReqCount = (RemainedCount > DDC_FIFO_MAXREQ) ? DDC_FIFO_MAXREQ : RemainedCount;
230         HDMITX_DEBUG_PRINTF("getHDMITX_EDIDBytes(): ReqCount = %d,bCurrOffset = %d\n", (int)ReqCount, (int)bCurrOffset);
231 
232         HDMITX_WriteI2C_Byte(handle, HDMI_TX_SYS_DDC_CTRL_REG10, HDMI_TX_SYS_DDC_CTRL_REG10_Reg_MasterSel_MASK);
233         HDMITX_WriteI2C_Byte(handle, HDMI_TX_SYS_DDC_CTRL_REG15, HDMI_TX_SYS_DDC_CTRL_REG15_RDDC_Req_DDC_FIFO_clear);
234 
235         for (TimeOut = 0; TimeOut < 200U; TimeOut++)
236         {
237             HDMITX_ReadI2C_Byte(handle, HDMI_TX_SYS_DDC_CTRL_REG16, &value);
238             if ((value & HDMI_TX_SYS_DDC_CTRL_REG16_RDDC_Status_Done_MASK) != 0U)
239             {
240                 break;
241             }
242             HDMITX_ReadI2C_Byte(handle, HDMI_TX_INT_FLAGS_REG06, &ucdata);
243             if ((value & (HDMI_TX_SYS_DDC_CTRL_REG16_RDDC_Status_NoACK_MASK |
244                           HDMI_TX_SYS_DDC_CTRL_REG16_RDDC_Status_WaitBus_MASK |
245                           HDMI_TX_SYS_DDC_CTRL_REG16_RDDC_Status_ArbiLose_MASK)) != 0U ||
246                 (ucdata & HDMI_TX_INT_FLAGS_REG06_RInt_DDCBusHang_MASK) != 0U)
247             {
248                 HDMITX_DEBUG_PRINTF("Called hdmitx_AboutDDC()\n");
249                 HDMITX_AbortDDC(handle);
250                 return false;
251             }
252         }
253         HDMITX_WriteI2C_Byte(handle, HDMI_TX_SYS_DDC_CTRL_REG10, HDMI_TX_SYS_DDC_CTRL_REG10_Reg_MasterSel_MASK);
254         HDMITX_WriteI2C_Byte(handle, HDMI_TX_SYS_DDC_CTRL_REG11, HDMI_TX_DDC_EDID_ADDR); // for EDID ucdata get
255         HDMITX_WriteI2C_Byte(handle, HDMI_TX_SYS_DDC_CTRL_REG12, bCurrOffset);
256         HDMITX_WriteI2C_Byte(handle, HDMI_TX_SYS_DDC_CTRL_REG13, (uint8_t)ReqCount);
257         HDMITX_WriteI2C_Byte(handle, HDMI_TX_SYS_DDC_CTRL_REG14, bSegment);
258         HDMITX_WriteI2C_Byte(handle, HDMI_TX_SYS_DDC_CTRL_REG15, HDMI_TX_SYS_DDC_CTRL_REG15_RDDC_Req_EDID_read);
259 
260         bCurrOffset += (uint8_t)ReqCount;
261         RemainedCount -= ReqCount;
262 
263         for (TimeOut = 250; TimeOut > 0U; TimeOut--)
264         {
265             delay1ms(1);
266             HDMITX_ReadI2C_Byte(handle, HDMI_TX_SYS_DDC_CTRL_REG16, &ucdata);
267             if ((ucdata & HDMI_TX_SYS_DDC_CTRL_REG16_RDDC_Status_Done_MASK) != 0U)
268             {
269                 break;
270             }
271             if ((ucdata & (HDMI_TX_SYS_DDC_CTRL_REG16_RDDC_Status_NoACK_MASK |
272                            HDMI_TX_SYS_DDC_CTRL_REG16_RDDC_Status_WaitBus_MASK |
273                            HDMI_TX_SYS_DDC_CTRL_REG16_RDDC_Status_ArbiLose_MASK)) != 0U)
274             {
275                 HDMITX_DEBUG_PRINTF("getHDMITX_EDIDBytes(): DDC_STATUS = %02X,fail.\n", (int)ucdata);
276                 return false;
277             }
278         }
279         if (TimeOut == 0U)
280         {
281             HDMITX_DEBUG_PRINTF("getHDMITX_EDIDBytes(): DDC TimeOut. \n", (int)ucdata);
282             return false;
283         }
284         do
285         {
286             HDMITX_ReadI2C_Byte(handle, HDMI_TX_SYS_DDC_CTRL_REG17, pBuff);
287             pBuff++;
288             ReqCount--;
289         } while (ReqCount > 0U);
290     }
291     return true;
292 }
293 
getHDMITX_EDIDBlock(display_handle_t * handle,int32_t EDIDBlockID,uint8_t * pEDIDData)294 static bool getHDMITX_EDIDBlock(display_handle_t *handle, int32_t EDIDBlockID, uint8_t *pEDIDData)
295 {
296     if (pEDIDData == NULL)
297     {
298         return false;
299     }
300     return getHDMITX_EDIDBytes(handle, pEDIDData, (uint8_t)EDIDBlockID / 2U, (uint8_t)((EDIDBlockID % 2) * 128), 128);
301 }
302 
ParseCEAEDID(uint8_t * pCEAEDID)303 static bool ParseCEAEDID(uint8_t *pCEAEDID)
304 
305 {
306     uint8_t offset = 0U, End = 0U;
307     uint8_t count = 0U;
308     uint8_t tag   = 0U;
309     uint8_t i     = 0U;
310 
311     if (pCEAEDID[0] != 0x02U || pCEAEDID[1] != 0x03U)
312     {
313         return false;  // not a CEA BLOCK.
314     }
315     End = pCEAEDID[2]; // CEA description.
316 
317     RxCapability.VDOMode[0] = 0x00;
318     RxCapability.VDOMode[1] = 0x00;
319     RxCapability.VDOMode[2] = 0x00;
320     RxCapability.VDOMode[3] = 0x00;
321     RxCapability.VDOMode[4] = 0x00;
322     RxCapability.VDOMode[5] = 0x00;
323     RxCapability.VDOMode[6] = 0x00;
324     RxCapability.VDOMode[7] = 0x00;
325     RxCapability.PA[0]      = 0x00;
326     RxCapability.PA[1]      = 0x00;
327 
328     RxCapability.VideoMode = pCEAEDID[3];
329 
330     RxCapability.NativeVDOMode = 0xff;
331 
332     for (offset = 4; offset < End;)
333     {
334         tag   = pCEAEDID[offset] >> 5U;
335         count = pCEAEDID[offset] & 0x1fU;
336         switch (tag)
337         {
338             case 0x01: // Audio Data Block ;
339                 RxCapability.AUDDesCount = count / 3U;
340                 HDMITX_DEBUG_PRINTF("RxCapability.AUDDesCount = %d\n", (int)RxCapability.AUDDesCount);
341                 offset++;
342                 for (i = 0U; i < RxCapability.AUDDesCount && i < MAX_AUDDES_COUNT; i++)
343                 {
344                     RxCapability.AUDDes[i].uc[0] = pCEAEDID[offset + i * 3U];
345                     RxCapability.AUDDes[i].uc[1] = pCEAEDID[offset + i * 3U + 1U];
346                     RxCapability.AUDDes[i].uc[2] = pCEAEDID[offset + i * 3U + 2U];
347                 }
348                 offset += count;
349                 break;
350 
351             case 0x02: // Video Data Block ;
352                 offset++;
353                 for (i = 0U; i < count; i++)
354                 {
355                     uint8_t VIC                = 0U;
356                     RxCapability.NativeVDOMode = 0xff;
357 
358                     VIC = (uint8_t)(pCEAEDID[offset + i] & (~0x80U));
359                     if (VIC < 64U)
360                     {
361                         RxCapability.VDOMode[VIC / 8U] |= (1U << (VIC % 8U));
362                         HDMITX_DEBUG_PRINTF("VIC = %d, RxCapability.VDOMode[%d]=%02X\n", (int)VIC, (int)VIC / 8,
363                                             (int)RxCapability.VDOMode[VIC / 8]);
364                         if (((pCEAEDID[offset + i] & 0x80U) != 0U) && (RxCapability.NativeVDOMode == 0xFFU))
365                         {
366                             RxCapability.NativeVDOMode = VIC;
367                             HDMITX_DEBUG_PRINTF("native = %d\n", RxCapability.NativeVDOMode);
368                         }
369                     }
370                 }
371                 offset += count;
372                 break;
373 
374             case 0x03: // Vendor Specific Data Block ;
375                 offset++;
376                 RxCapability.IEEEOUI = (uint32_t)pCEAEDID[offset + 2U];
377                 RxCapability.IEEEOUI <<= 8;
378                 RxCapability.IEEEOUI += (uint32_t)pCEAEDID[offset + 1U];
379                 RxCapability.IEEEOUI <<= 8;
380                 RxCapability.IEEEOUI += (uint32_t)pCEAEDID[offset];
381                 HDMITX_DEBUG_PRINTF("IEEEOUI = %02X %02X %02X %lx", (int)pCEAEDID[offset + 2],
382                                     (int)pCEAEDID[offset + 1], (int)pCEAEDID[offset], RxCapability.IEEEOUI);
383                 if (RxCapability.IEEEOUI == 0x0C03U)
384                 {
385                     uint8_t nextoffset = 0U;
386 
387                     RxCapability.ValidHDMI = 1U;
388 
389                     RxCapability.PA[0] = pCEAEDID[offset + 3U];
390                     RxCapability.PA[1] = pCEAEDID[offset + 4U];
391                     if (count > 5U)
392                     {
393                         RxCapability.dc.uc = pCEAEDID[offset + 5U] & 0x70U;
394                     }
395                     if (count > 6U)
396                     {
397                         RxCapability.MaxTMDSClock = pCEAEDID[offset + 6U];
398                     }
399                     if (count > 7U)
400                     {
401                         nextoffset = 8;
402                         if ((pCEAEDID[offset + 7U] & 0x80U) != 0U)
403                         {
404                             nextoffset += 2U;
405                         } // latency
406                         if ((pCEAEDID[offset + 7U] & 0x40U) != 0U)
407                         {
408                             nextoffset += 2U;
409                         } // interlace latency
410                         if ((pCEAEDID[offset + 7U] & 0x20U) != 0U)
411                         {
412                             HDMITX_DEBUG_PRINTF("next offset = %d", (int)nextoffset);
413                             RxCapability.Valid3D = ((pCEAEDID[offset + nextoffset] & 0x80U) != 0U) ? 1U : 0U;
414                         } // interlace latency
415                     }
416                 }
417                 offset += count; // ignore the remaind.
418 
419                 break;
420 
421             case 0x04: // Speaker Data Block ;
422                 offset++;
423                 RxCapability.SpeakerAllocBlk.uc[0] = pCEAEDID[offset];
424                 RxCapability.SpeakerAllocBlk.uc[1] = pCEAEDID[offset + 1U];
425                 RxCapability.SpeakerAllocBlk.uc[2] = pCEAEDID[offset + 2U];
426                 offset += 3U;
427                 break;
428             case 0x05: // VESA Data Block ;
429                 offset += count + 1U;
430                 break;
431             case 0x07:                // Extended Data Block ;
432                 offset += count + 1U; // ignore
433                 break;
434             default:
435                 offset += count + 1U; // ignore
436                 break;
437         }
438     }
439     RxCapability.ValidCEA = 1;
440 
441     return true;
442 }
443 
ParseEDID(display_handle_t * handle)444 static uint8_t ParseEDID(display_handle_t *handle)
445 {
446     // collect the EDID ucdata of segment 0
447     unsigned char *EDID_Buf = NULL;
448     uint8_t CheckSum        = 0U;
449     uint8_t BlockCount      = 0U;
450     uint8_t err             = 0U;
451     // uint8_t bValidCEA = false ;
452     uint8_t i = 0U;
453     uint8_t j = 0U;
454 
455     EDID_Buf               = CommonBuff;
456     RxCapability.ValidCEA  = 0;
457     RxCapability.ValidHDMI = 0;
458     RxCapability.dc.uc     = 0;
459     RxCapability.IEEEOUI   = 0;
460     getHDMITX_EDIDBlock(handle, 0, EDID_Buf);
461 
462     for (i = 0, CheckSum = 0; i < 128U; i++)
463     {
464         CheckSum += EDID_Buf[i];
465         CheckSum &= 0xFFU;
466     }
467     if (CheckSum != 0U)
468     {
469         return 0;
470     }
471     if (EDID_Buf[0] != 0x00U || EDID_Buf[1] != 0xFFU || EDID_Buf[2] != 0xFFU || EDID_Buf[3] != 0xFFU ||
472         EDID_Buf[4] != 0xFFU || EDID_Buf[5] != 0xFFU || EDID_Buf[6] != 0xFFU || EDID_Buf[7] != 0x00U)
473     {
474         return 0;
475     }
476 
477     BlockCount = EDID_Buf[0x7E];
478 
479     if (BlockCount == 0U)
480     {
481         return 1; // do nothing.
482     }
483     else if (BlockCount > 4U)
484     {
485         BlockCount = 4;
486     }
487     // read all segment for test
488     for (i = 1; i <= BlockCount; i++)
489     {
490         err = (uint8_t)getHDMITX_EDIDBlock(handle, (int32_t)i, EDID_Buf);
491 
492         HDMITX_DEBUG_PRINTF("\r\n");
493         for (j = 0; j < 128U; j++)
494         {
495             HDMITX_DEBUG_PRINTF("%02X%c", (int)EDID_Buf[j], ' ');
496             if ((j & 7U) == 7U)
497             {
498                 HDMITX_DEBUG_PRINTF("\r\n");
499             }
500         }
501 
502         if (err != 0U)
503         {
504             if ((RxCapability.ValidHDMI == 0U) && EDID_Buf[0] == 0x2U && EDID_Buf[1] == 0x3U)
505             {
506                 err = (uint8_t)ParseCEAEDID(EDID_Buf);
507                 HDMITX_DEBUG_PRINTF("err = %s\n", err ? "SUCCESS" : "FAIL");
508                 if (err != 0U)
509                 {
510                     HDMITX_DEBUG_PRINTF("RxCapability.IEEEOUI = %lx\n", RxCapability.IEEEOUI);
511                 }
512             }
513         }
514     }
515     return err;
516 }
517 
HDMITX_GetVideoState(display_handle_t * handle)518 static bool HDMITX_GetVideoState(display_handle_t *handle)
519 {
520     uint8_t value = 0U;
521 
522     HDMITX_ReadI2C_Byte(handle, HDMI_TX_SYS_STATUS_REG0E, &value);
523 
524     return (bool)(HDMI_TX_SYS_STATUS_REG0E_TxVidStable_MASK & value);
525 }
526 
HDMITX_CalcRclk(display_handle_t * handle)527 static int32_t HDMITX_CalcRclk(display_handle_t *handle)
528 {
529     uint32_t i   = 0;
530     uint32_t sum = 0, RCLKCNT = 0, TimeLoMax = 0, retry = 5;
531     uint8_t value = 0U;
532 
533     /* Init CEC  */
534     HDMITX_WriteI2C_Byte(handle, HDMI_TX_COLOR_SPACE_CONVERSION_REG8D,
535                          (HDMI_TX_COLOR_SPACE_CONVERSION_REG8D_RegCECSlvAdr(HDMI_TX_CEC_SLAVE_ADDR) |
536                           HDMI_TX_COLOR_SPACE_CONVERSION_REG8D_RegEnCRCLK_MASK));
537     delay1ms(10);
538 
539     for (i = 0U; i < retry; i++)
540     {
541         HDMITX_CEC_WriteI2C_Byte(handle, 0x09, 1);
542         delay1ms(100);
543         HDMITX_CEC_WriteI2C_Byte(handle, 0x09, 0);
544         HDMITX_CEC_ReadI2C_Byte(handle, 0x47, &value);
545         RCLKCNT = (uint32_t)value;
546         RCLKCNT <<= 8U;
547         HDMITX_CEC_ReadI2C_Byte(handle, 0x46, &value);
548         RCLKCNT |= (uint32_t)value;
549         RCLKCNT <<= 8U;
550         HDMITX_CEC_ReadI2C_Byte(handle, 0x45, &value);
551         RCLKCNT |= (uint32_t)value;
552         sum += RCLKCNT;
553     }
554 
555     sum /= retry;
556     RCLKCNT = sum / 1000U;
557     HDMITX_CEC_WriteI2C_Byte(handle, 0x0C, (RCLKCNT & 0xFFU));
558 
559     /* Disable CEC  */
560     HDMITX_SetI2C_Byte(handle, HDMI_TX_COLOR_SPACE_CONVERSION_REG8D,
561                        HDMI_TX_COLOR_SPACE_CONVERSION_REG8D_RegEnCRCLK_MASK,
562                        HDMI_TX_COLOR_SPACE_CONVERSION_REG8D_RegEnCRCLK(0x00U));
563 
564     it6161.hdmi_tx.rclk = (sum << 4U) / 108U;
565     HDMITX_DEBUG_PRINTF("hdmi tx rclk = %d.%d MHz", it6161.hdmi_tx.rclk / 1000, it6161.hdmi_tx.rclk % 1000);
566 
567     TimeLoMax = (sum << 4) / 10U; /* 10*TxRCLK; */
568     if (TimeLoMax > 0x3FFFFU)
569     {
570         TimeLoMax = 0x3FFFFU;
571     }
572     HDMITX_WriteI2C_Byte(handle, 0x47, (TimeLoMax & 0xFFU));
573     HDMITX_WriteI2C_Byte(handle, 0x48, ((TimeLoMax & 0xFF00U) >> 8U));
574     HDMITX_WriteI2C_Byte(handle, 0x49, 0x23);
575 
576     return (int32_t)it6161.hdmi_tx.rclk;
577 }
578 
HDMITX_CalcPclk(display_handle_t * handle)579 int32_t HDMITX_CalcPclk(display_handle_t *handle)
580 {
581     uint8_t uc = 0U, RCLKFreqSelRead = 0U;
582     int32_t div = 0, i = 0;
583     uint32_t sum = 0, count = 0;
584     uint32_t value = 0U;
585 
586     HDMITX_ChangeBank(handle, 0);
587     HDMITX_ReadI2C_Byte(handle, 0x5D, &value);
588     RCLKFreqSelRead = (uint8_t)(value & 0x04U) >> 2U;
589     /* PCLK Count Pre-Test */
590     HDMITX_SetI2C_Byte(handle, 0xD7, 0xF0, 0x80);
591     delay1ms(1);
592     HDMITX_SetI2C_Byte(handle, 0xD7, 0x80, 0x00);
593 
594     HDMITX_ReadI2C_Byte(handle, 0xD7, &value);
595     count = value & 0xFU;
596     count <<= 8U;
597     HDMITX_ReadI2C_Byte(handle, 0xD8, &value);
598     count |= value;
599 
600     if (RCLKFreqSelRead != 0U)
601     {
602         count <<= 1U;
603     }
604 
605     for (div = 7; div > 0; div--)
606     {
607         if (count < (1U << (uint32_t)(11 - div)))
608         {
609             break;
610         }
611     }
612 
613     if (div < 0)
614     {
615         div = 0;
616     }
617 
618     HDMITX_SetI2C_Byte(handle, 0xD7, 0x70, (uint32_t)div << 4U);
619 
620     HDMITX_ReadI2C_Byte(handle, 0xD7, &value);
621     uc = (uint8_t)value & 0x7FU;
622     for (i = 0, sum = 0; i < 100; i++)
623     {
624         HDMITX_WriteI2C_Byte(handle, 0xD7, (uint32_t)uc | 0x80U);
625         delay1ms(1);
626         HDMITX_WriteI2C_Byte(handle, 0xD7, uc);
627 
628         HDMITX_ReadI2C_Byte(handle, 0xD7, &value);
629         count = value & 0xFU;
630         count <<= 8U;
631         HDMITX_ReadI2C_Byte(handle, 0xD8, &value);
632         count |= value;
633         if (RCLKFreqSelRead != 0U)
634         {
635             count <<= 1U;
636         }
637         sum += count;
638     }
639     sum /= 100U;
640     count = sum;
641 
642     it6161.hdmi_tx.pclk = it6161.hdmi_tx.rclk * 128U / count * 16U; /* 128*16=2048 */
643     it6161.hdmi_tx.pclk *= (uint32_t)(1U << (uint32_t)div);
644 
645     HDMITX_DEBUG_PRINTF("hdmi tx pclk = %d.%d MHz", it6161.hdmi_tx.pclk / 1000, it6161.hdmi_tx.pclk % 1000);
646     return (int32_t)it6161.hdmi_tx.pclk;
647 }
648 
HDMITX_GetDisplayMode(display_handle_t * handle)649 static void HDMITX_GetDisplayMode(display_handle_t *handle)
650 {
651     int32_t interlaced = 0;
652     uint32_t htotal = 0, hdes = 0, hdee = 0, hsyncw = 0, H2ndVRRise = 0;
653     uint32_t vtotal = 0, vdes = 0, vdee = 0, vdes2nd = 0, vdee2nd = 0;
654     uint32_t VRS2nd = 0;
655     uint8_t rega9   = 0;
656     uint8_t value   = 0U;
657 
658     HDMITX_CalcRclk(handle);
659     HDMITX_CalcPclk(handle);
660 
661     /* enable video timing read back */
662     HDMITX_SetI2C_Byte(handle, 0xA8, 0x08, 0x08);
663     HDMITX_ReadI2C_Byte(handle, 0xa9, &value);
664     rega9      = value;
665     interlaced = (int32_t)((rega9 & 0x04U) >> 2U);
666 
667     HDMITX_ReadI2C_Bytes(handle, 0x98, (uint8_t *)&htotal, 2);
668     htotal = htotal & 0x0FFFU;
669     HDMITX_ReadI2C_Bytes(handle, 0x90, (uint8_t *)&hdes, 2);
670     hdes = hdes & 0x0FFFU;
671     HDMITX_ReadI2C_Bytes(handle, 0x92, (uint8_t *)&hdee, 2);
672     hdee = hdee & 0x0FFFU;
673     HDMITX_ReadI2C_Bytes(handle, 0x94, (uint8_t *)&hsyncw, 2);
674     hsyncw = hsyncw & 0x0FFFU;
675 
676     HDMITX_ReadI2C_Bytes(handle, 0xA6, (uint8_t *)&vtotal, 2);
677     vtotal = vtotal & 0x0FFFU;
678     HDMITX_ReadI2C_Bytes(handle, 0x9C, (uint8_t *)&vdes, 2);
679     vdes = vdes & 0x0FFFU;
680     HDMITX_ReadI2C_Bytes(handle, 0x9E, (uint8_t *)&vdee, 2);
681     vdee = vdee & 0x0FFFU;
682     if (interlaced != 0)
683     {
684         HDMITX_ReadI2C_Bytes(handle, 0xA2, (uint8_t *)&vdes2nd, 2);
685         vdes2nd &= 0x0FFFU;
686         HDMITX_ReadI2C_Bytes(handle, 0xA4, (uint8_t *)&vdee2nd, 2);
687         vdee2nd &= 0x0FFFU;
688         HDMITX_ReadI2C_Bytes(handle, 0xB1, (uint8_t *)&VRS2nd, 2);
689         VRS2nd &= 0x0FFFU;
690         HDMITX_ReadI2C_Bytes(handle, 0x96, (uint8_t *)&H2ndVRRise, 2);
691         H2ndVRRise &= 0x0FFFU;
692 
693 #if HDMITX_DEBUG_PRINTF
694         uint32_t vsyncw2nd = 0, vdew2nd = 0, vfph2nd = 0, vbph2nd = 0;
695         uint8_t value = 0U;
696 
697         HDMITX_ReadI2C_Byte(handle, 0xA1, &value);
698         vsyncw2nd = value;
699         vdew2nd   = vdee2nd - vdes2nd;
700         vfph2nd   = VRS2nd - vdee;
701         vbph2nd   = vdes2nd - VRS2nd - vsyncw2nd;
702         HDMITX_DEBUG_PRINTF("vdew2nd    = %d\n", vdew2nd);
703         HDMITX_DEBUG_PRINTF("vfph2nd    = %d\n", vfph2nd);
704         HDMITX_DEBUG_PRINTF("vbph2nd    = %d\n", vbph2nd);
705         HDMITX_DEBUG_PRINTF("VSyncW2nd  = %d\n", vsyncw2nd);
706         HDMITX_DEBUG_PRINTF("H2ndVRRise = %d\n", H2ndVRRise);
707 #endif
708     }
709 
710     /* disable video timing read back */
711     HDMITX_SetI2C_Byte(handle, 0xA8, 0x08, 0x00);
712 }
713 
HDMITX_DisableAviInfoframe(display_handle_t * handle)714 static inline void HDMITX_DisableAviInfoframe(display_handle_t *handle)
715 {
716     HDMITX_ChangeBank(handle, 0);
717     HDMITX_WriteI2C_Byte(handle, HDMI_TX_HDMI_CONTROL_REGCD, 0x00);
718 }
719 
HDMITX_EnableAviInfoframe(display_handle_t * handle)720 static inline void HDMITX_EnableAviInfoframe(display_handle_t *handle)
721 {
722     HDMITX_ChangeBank(handle, 0);
723     HDMITX_WriteI2C_Byte(
724         handle, HDMI_TX_HDMI_CONTROL_REGCD,
725         HDMI_TX_HDMI_CONTROL_REGCD_REGPktAVIInfoEn_MASK | HDMI_TX_HDMI_CONTROL_REGCD_REGPktAVIInfoRpt_MASK);
726 }
727 
HDMI_AviInfoframeInit(struct hdmi_avi_infoframe * frame)728 void HDMI_AviInfoframeInit(struct hdmi_avi_infoframe *frame)
729 {
730     memset(frame, 0, sizeof(*frame));
731 
732     frame->type    = HDMI_INFOFRAME_TYPE_AVI;
733     frame->version = 2;
734     frame->length  = HDMI_AVI_INFOFRAME_SIZE;
735 }
736 
HDMI_SetupAviInfoframe(struct hdmi_avi_infoframe * frame)737 static int32_t HDMI_SetupAviInfoframe(struct hdmi_avi_infoframe *frame)
738 {
739     enum hdmi_picture_aspect picture_aspect = HDMI_PICTURE_ASPECT_NONE;
740     uint8_t vic                             = 0U;
741 
742     if (frame == NULL)
743     {
744         return -1;
745     }
746     HDMI_AviInfoframeInit(frame);
747     frame->pixel_repeat = 0;
748 
749     vic = 2;
750 
751     frame->picture_aspect = HDMI_PICTURE_ASPECT_NONE;
752 
753     frame->content_type = HDMI_CONTENT_TYPE_GRAPHICS;
754     frame->itc          = 0;
755 
756     picture_aspect = HDMI_PICTURE_ASPECT_4_3;
757 
758     frame->video_code     = vic;
759     frame->picture_aspect = picture_aspect;
760     frame->active_aspect  = HDMI_ACTIVE_ASPECT_PICTURE;
761     frame->scan_mode      = HDMI_SCAN_MODE_UNDERSCAN;
762 
763     return 0;
764 }
765 
HDMI_InfoframeChecksum(void * buffer,int32_t size)766 uint8_t HDMI_InfoframeChecksum(void *buffer, int32_t size)
767 {
768     uint8_t csum = 0;
769     uint8_t *ptr = buffer;
770     int32_t i    = 0;
771 
772     /* compute checksum */
773     for (i = 0; i < size; i++)
774     {
775         csum += ptr[i];
776     }
777     return (uint8_t)(256U - csum);
778 }
779 
HDMI_InfoframeSetChecksum(void * buffer,int32_t size)780 void HDMI_InfoframeSetChecksum(void *buffer, int32_t size)
781 {
782     uint8_t *ptr = buffer;
783 
784     ptr[3] = HDMI_InfoframeChecksum(buffer, size);
785 }
786 
HDMI_AviInfoframePack(struct hdmi_avi_infoframe * frame,void * buffer,int32_t size)787 int32_t HDMI_AviInfoframePack(struct hdmi_avi_infoframe *frame, void *buffer, int32_t size)
788 {
789     int32_t length = 0;
790     uint8_t *ptr   = buffer;
791 
792     if (frame->type != HDMI_INFOFRAME_TYPE_AVI || frame->version != 2U || frame->length != HDMI_AVI_INFOFRAME_SIZE)
793     {
794         return -1;
795     }
796     length = HDMI_INFOFRAME_HEADER_SIZE + frame->length;
797 
798     if (size < length)
799     {
800         return -1;
801     }
802 
803     memset(buffer, 0, (uint32_t)size);
804 
805     ptr[0] = (uint8_t)frame->type;
806     ptr[1] = frame->version;
807     ptr[2] = frame->length;
808     ptr[3] = 0; /* checksum */
809 
810     /* start infoframe payload */
811     ptr += HDMI_INFOFRAME_HEADER_SIZE;
812 
813     ptr[0] = (((uint8_t)frame->colorspace & 0x3U) << 5U) | ((uint8_t)frame->scan_mode & 0x3U);
814 
815     /* Data byte 1, bit 4 has to be set if we provide the active format aspect ratio */
816     if (((uint8_t)(frame->active_aspect) & 0xFU) != 0U)
817     {
818         ptr[0] |= BIT(4);
819     }
820 
821     /* Bit 3 and 2 indicate if we transmit horizontal/vertical bar data */
822     if ((bool)frame->top_bar || (bool)frame->bottom_bar)
823     {
824         ptr[0] |= BIT(3);
825     }
826 
827     if ((bool)frame->left_bar || (bool)frame->right_bar)
828     {
829         ptr[0] |= BIT(2);
830     }
831 
832     ptr[1] = (((uint8_t)frame->colorimetry & 0x3U) << 6U) | (((uint8_t)frame->picture_aspect & 0x3U) << 4U) |
833              ((uint8_t)frame->active_aspect & 0xFU);
834 
835     ptr[2] = (((uint8_t)frame->extended_colorimetry & 0x7U) << 4U) |
836              (((uint8_t)frame->quantization_range & 0x3U) << 2U) | ((uint8_t)frame->nups & 0x3U);
837 
838     if (frame->itc)
839     {
840         ptr[2] |= BIT(7);
841     }
842 
843     ptr[3] = frame->video_code & 0x7FU;
844 
845     ptr[4] = (((uint8_t)frame->ycc_quantization_range & 0x3U) << 6U) | (((uint8_t)frame->content_type & 0x3U) << 2U) |
846              ((uint8_t)frame->pixel_repeat & 0xFU);
847 
848     ptr[5]  = (uint8_t)(frame->top_bar & 0xFFU);
849     ptr[6]  = (uint8_t)((frame->top_bar >> 8U) & 0xFFU);
850     ptr[7]  = (uint8_t)(frame->bottom_bar & 0xFFU);
851     ptr[8]  = (uint8_t)((frame->bottom_bar >> 8U) & 0xFFU);
852     ptr[9]  = (uint8_t)(frame->left_bar & 0xFFU);
853     ptr[10] = (uint8_t)((frame->left_bar >> 8U) & 0xFFU);
854     ptr[11] = (uint8_t)(frame->right_bar & 0xFFU);
855     ptr[12] = (uint8_t)((frame->right_bar >> 8U) & 0xFFU);
856 
857     HDMI_InfoframeSetChecksum(buffer, length);
858 
859     return length;
860 }
861 
HDMITX_AviInfoframeSet(display_handle_t * handle)862 static int32_t HDMITX_AviInfoframeSet(display_handle_t *handle)
863 {
864     struct hdmi_avi_infoframe *frame = &it6161.source_avi_infoframe;
865     uint8_t buf[32] = {0U}, i = 0U, *ptr = NULL;
866     int32_t ret = 0;
867 
868     HDMITX_DEBUG_PRINTF("avinfo set\n");
869     HDMITX_DisableAviInfoframe(handle);
870 
871     ret = HDMI_SetupAviInfoframe(frame);
872     if (ret != 0)
873     {
874         HDMITX_DEBUG_PRINTF("Failed to setup AVI infoframe: %d", ret);
875         return ret;
876     }
877     if ((it6161.hdmi_tx.output_color_space & F_MODE_CLRMOD_MASK) == F_MODE_RGB444)
878     {
879         frame->colorspace = HDMI_COLORSPACE_RGB;
880     }
881     if ((it6161.hdmi_tx.output_color_space & F_MODE_CLRMOD_MASK) == F_MODE_YUV444)
882     {
883         frame->colorspace = HDMI_COLORSPACE_YUV444;
884     }
885     if ((it6161.hdmi_tx.output_color_space & F_MODE_CLRMOD_MASK) == F_MODE_YUV422)
886     {
887         frame->colorspace = HDMI_COLORSPACE_YUV422;
888     }
889     ret = HDMI_AviInfoframePack(&it6161.source_avi_infoframe, buf, (int32_t)sizeof(buf));
890     if (ret < 0)
891     {
892         HDMITX_DEBUG_PRINTF("Failed to pack AVI infoframe: %d", ret);
893         return ret;
894     }
895 
896     /* fill PB */
897     HDMITX_ChangeBank(handle, 1);
898     ptr = buf + HDMI_INFOFRAME_HEADER_SIZE;
899     for (i = 0; i < it6161.source_avi_infoframe.length; i++)
900     {
901         HDMITX_WriteI2C_Byte(handle, (uint32_t)HDMI_TX_AVIINFO_DB1 + (uint32_t)i, ptr[i]);
902     }
903     HDMITX_WriteI2C_Byte(handle, HDMI_TX_AVIINFO_SUM, buf[3]);
904 
905     /* Enable */
906     HDMITX_EnableAviInfoframe(handle);
907 
908     return 0;
909 }
910 
HDMI_AudioInfoframePack(struct hdmi_audio_infoframe * frame,void * buffer,int32_t size)911 int32_t HDMI_AudioInfoframePack(struct hdmi_audio_infoframe *frame, void *buffer, int32_t size)
912 {
913     int32_t length   = 0;
914     uint8_t channels = 0U;
915     uint8_t *ptr     = buffer;
916 
917     if (frame->type != HDMI_INFOFRAME_TYPE_AUDIO || frame->version != 1U || frame->length != HDMI_AUDIO_INFOFRAME_SIZE)
918     {
919         return -1;
920     }
921 
922     length = HDMI_INFOFRAME_HEADER_SIZE + frame->length;
923     if (size < length)
924     {
925         return -1;
926     }
927 
928     memset(buffer, 0, (uint32_t)size);
929 
930     if (frame->channels >= 2U)
931     {
932         channels = frame->channels - 1U;
933     }
934     else
935     {
936         channels = 0;
937     }
938 
939     ptr[0] = (uint8_t)frame->type;
940     ptr[1] = frame->version;
941     ptr[2] = frame->length;
942     ptr[3] = 0; /* checksum */
943 
944     /* start infoframe payload */
945     ptr += HDMI_INFOFRAME_HEADER_SIZE;
946 
947     ptr[0] = (((uint8_t)frame->coding_type & 0xFU) << 4U) | (channels & 0x7U);
948     ptr[1] = (((uint8_t)frame->sample_frequency & 0x7U) << 2U) | ((uint8_t)frame->sample_size & 0x3U);
949     ptr[2] = (uint8_t)frame->coding_type_ext & 0x1FU;
950     ptr[3] = (uint8_t)frame->channel_allocation;
951     ptr[4] = ((uint8_t)frame->level_shift_value & 0xFU) << 3U;
952 
953     if (frame->downmix_inhibit)
954     {
955         ptr[4] |= BIT(7);
956     }
957 
958     HDMI_InfoframeSetChecksum(buffer, length);
959 
960     return length;
961 }
962 
HDMITX_AudioInfoframeSet(display_handle_t * handle,uint8_t channels)963 static void HDMITX_AudioInfoframeSet(display_handle_t *handle, uint8_t channels)
964 {
965     struct hdmi_audio_infoframe frame;
966     uint8_t buf[16] = {0U};
967     int32_t ret     = 0;
968 
969     memset((void *)&frame, 0, sizeof(frame));
970     frame.channels    = channels;
971     frame.coding_type = HDMI_AUDIO_CODING_TYPE_STREAM;
972 
973     ret = HDMI_AudioInfoframePack(&frame, buf, (int32_t)sizeof(buf));
974     if (ret < 0)
975     {
976         HDMITX_DEBUG_PRINTF("failed to pack audio infoframe: %d\n", ret);
977         return;
978     }
979 
980     /* set audio Data byte */
981     HDMITX_ChangeBank(handle, 1);
982     HDMITX_WriteI2C_Byte(handle, HDMI_TX_PKT_AUDINFO_SUM, buf[3]);
983     HDMITX_WriteI2C_Byte(handle, HDMI_TX_PKT_AUDINFO_CC, buf[4]);
984     HDMITX_WriteI2C_Byte(handle, HDMI_TX_PKT_AUDINFO_SF, buf[5]);
985     HDMITX_WriteI2C_Byte(handle, HDMI_TX_PKT_AUDINFO_CA, buf[7]);
986     HDMITX_WriteI2C_Byte(handle, HDMI_TX_PKT_AUDINFO_DM_LSV, buf[8]);
987 
988     /* Enable Audio info frame */
989     HDMITX_ChangeBank(handle, 0);
990     HDMITX_WriteI2C_Byte(
991         handle, HDMI_TX_HDMI_CONTROL_REGCE,
992         HDMI_TX_HDMI_CONTROL_REGCE_REGPktAudInfoEn_MASK | HDMI_TX_HDMI_CONTROL_REGCE_REGPktAudInfoRpt_MASK);
993 }
994 
setHDMITX_ChStat(display_handle_t * handle,uint8_t ucIEC60958ChStat[])995 static void setHDMITX_ChStat(display_handle_t *handle, uint8_t ucIEC60958ChStat[])
996 {
997     uint8_t uc = 0U;
998 
999     HDMITX_ChangeBank(handle, 1);
1000     uc = (ucIEC60958ChStat[0] << 1U) & 0x7CU;
1001     HDMITX_WriteI2C_Byte(handle, HDMI_TX_AUDCHST_MODE, uc);
1002     HDMITX_WriteI2C_Byte(handle, HDMI_TX_AUDCHST_CAT, ucIEC60958ChStat[1]);
1003     HDMITX_WriteI2C_Byte(handle, HDMI_TX_AUDCHST_SRCNUM, (uint32_t)ucIEC60958ChStat[2] & 0xFU);
1004     HDMITX_WriteI2C_Byte(handle, HDMI_TX_AUD0CHST_CHTNUM, ((uint32_t)ucIEC60958ChStat[2] >> 4U) & 0xFU);
1005     HDMITX_WriteI2C_Byte(handle, HDMI_TX_AUDCHST_CA_FS, ucIEC60958ChStat[3]);
1006     HDMITX_WriteI2C_Byte(handle, HDMI_TX_AUDCHST_OFS_WL, ucIEC60958ChStat[4]);
1007     HDMITX_ChangeBank(handle, 0);
1008 }
1009 
setHDMITX_LPCMAudio(display_handle_t * handle,uint8_t AudioSrcNum,uint8_t AudSWL,uint8_t bAudInterface)1010 static void setHDMITX_LPCMAudio(display_handle_t *handle, uint8_t AudioSrcNum, uint8_t AudSWL, uint8_t bAudInterface)
1011 {
1012     uint8_t AudioEnable = 0, AudioFormat = 0, bTDMSetting = 0U;
1013 
1014     switch (AudSWL)
1015     {
1016         case 16:
1017             AudioEnable |= HDMI_TX_AUDIO_CHANNEL_REGE0_REGAudSWL_16bits;
1018             break;
1019         case 18:
1020             AudioEnable |= HDMI_TX_AUDIO_CHANNEL_REGE0_REGAudSWL_18bits;
1021             break;
1022         case 20:
1023             AudioEnable |= HDMI_TX_AUDIO_CHANNEL_REGE0_REGAudSWL_20bits;
1024             break;
1025         case 24:
1026         default:
1027             AudioEnable |= HDMI_TX_AUDIO_CHANNEL_REGE0_REGAudSWL_24bits;
1028             break;
1029     }
1030     if (bAudInterface == (uint8_t)AUDIO_IF_SPDIF)
1031     {
1032         AudioFormat &= (uint8_t)~0x40U; /* not full packet mode */
1033         AudioEnable |=
1034             HDMI_TX_AUDIO_CHANNEL_REGE0_REGAudSel_SPDIF | HDMI_TX_AUDIO_CHANNEL_REGE0_REGAudioEn_Enable_Audio_Source_0;
1035     }
1036     else
1037     {
1038         AudioFormat |= 0x40U; /* full packet mode */
1039         switch (AudioSrcNum)
1040         {
1041             case 4:
1042                 AudioEnable |= HDMI_TX_AUDIO_CHANNEL_REGE0_REGAudioEn_Enable_Audio_Source_3 |
1043                                HDMI_TX_AUDIO_CHANNEL_REGE0_REGAudioEn_Enable_Audio_Source_2 |
1044                                HDMI_TX_AUDIO_CHANNEL_REGE0_REGAudioEn_Enable_Audio_Source_1 |
1045                                HDMI_TX_AUDIO_CHANNEL_REGE0_REGAudioEn_Enable_Audio_Source_0;
1046                 break;
1047 
1048             case 3:
1049                 AudioEnable |= 2U | HDMI_TX_AUDIO_CHANNEL_REGE0_REGAudioEn_Enable_Audio_Source_1 |
1050                                HDMI_TX_AUDIO_CHANNEL_REGE0_REGAudioEn_Enable_Audio_Source_0;
1051                 break;
1052 
1053             case 2:
1054                 AudioEnable |= 1U | HDMI_TX_AUDIO_CHANNEL_REGE0_REGAudioEn_Enable_Audio_Source_0;
1055                 break;
1056 
1057             case 1:
1058             default:
1059                 AudioFormat &= (uint8_t)~0x40U;
1060                 AudioEnable |= 0U;
1061                 break;
1062         }
1063     }
1064     AudioFormat |= 0x01U;
1065     it6161.hdmi_tx.bAudioChannelEnable = AudioEnable;
1066 
1067     HDMITX_ChangeBank(handle, 0);
1068     HDMITX_WriteI2C_Byte(handle, HDMI_TX_AUDIO_CHANNEL_REGE0, (uint32_t)AudioEnable & 0xF0U);
1069 
1070     HDMITX_WriteI2C_Byte(handle, HDMI_TX_AUDIO_CHANNEL_REGE1, AudioFormat);
1071     HDMITX_WriteI2C_Byte(handle, HDMI_TX_AUDIO_CHANNEL_REGE2, 0xE4);
1072 
1073     if (bAudInterface == (uint8_t)AUDIO_IF_SPDIF)
1074     {
1075         HDMITX_WriteI2C_Byte(handle, HDMI_TX_AUDIO_CHANNEL_REGE3, HDMI_TX_AUDIO_CHANNEL_REGE3_REGChStSel_MASK);
1076     }
1077     else
1078     {
1079         HDMITX_WriteI2C_Byte(handle, HDMI_TX_AUDIO_CHANNEL_REGE3, 0);
1080     }
1081     HDMITX_WriteI2C_Byte(handle, HDMI_TX_AUDIO_CHANNEL_REGE4, 0x00);
1082     HDMITX_WriteI2C_Byte(handle, HDMI_TX_AUDIO_CHANNEL_REGE5, 0x00);
1083 
1084     if (bAudInterface == (uint8_t)AUDIO_IF_SPDIF)
1085     {
1086         uint8_t i = 0U, value = 0U;
1087 
1088         HDMITX_SetI2C_Byte(handle, 0x5c, (1U << 6U), (1U << 6U));
1089         for (i = 0; i < 100U; i++)
1090         {
1091             HDMITX_ReadI2C_Byte(handle, HDMI_TX_CLOCK_CONTROL_REG5F, &value);
1092             if ((value & HDMI_TX_CLOCK_CONTROL_REG5F_OSFreqLock_MASK) != 0U)
1093             {
1094                 break; /* stable clock. */
1095             }
1096         }
1097     }
1098     else
1099     {
1100         HDMITX_ReadI2C_Byte(handle, HDMI_TX_AUDIO_CHANNEL_REGE5, &bTDMSetting);
1101         if (bAudInterface == (uint8_t)AUDIO_IF_TDM)
1102         {
1103             bTDMSetting |= HDMI_TX_AUDIO_CHANNEL_REGE5_RegEnTDM_MASK;
1104             bTDMSetting &= 0x9FU;
1105             bTDMSetting |= (AudioSrcNum - 1U) << 5U;
1106         }
1107         else
1108         {
1109             bTDMSetting &= (uint8_t)~HDMI_TX_AUDIO_CHANNEL_REGE5_RegEnTDM_MASK;
1110         }
1111 
1112         /* 1 channel NLPCM, no TDM mode. */
1113         HDMITX_WriteI2C_Byte(handle, HDMI_TX_AUDIO_CHANNEL_REGE5, bTDMSetting);
1114     }
1115 }
1116 
setHDMITX_NLPCMAudio(display_handle_t * handle,uint8_t bAudInterface)1117 static void setHDMITX_NLPCMAudio(display_handle_t *handle, uint8_t bAudInterface)
1118 {
1119     uint8_t AudioEnable = 0U;
1120     uint8_t i = 0U, value = 0U;
1121 
1122     /* NLPCM must use standard I2S mode. */
1123     if (bAudInterface == (uint8_t)AUDIO_IF_SPDIF)
1124     {
1125         AudioEnable = HDMI_TX_AUDIO_CHANNEL_REGE0_REGAudSWL_24bits | HDMI_TX_AUDIO_CHANNEL_REGE0_REGAudSel_SPDIF;
1126     }
1127     else
1128     {
1129         AudioEnable = HDMI_TX_AUDIO_CHANNEL_REGE0_REGAudSWL_24bits;
1130     }
1131 
1132     HDMITX_ChangeBank(handle, 0);
1133     HDMITX_WriteI2C_Byte(handle, HDMI_TX_AUDIO_CHANNEL_REGE0, AudioEnable);
1134     HDMITX_WriteI2C_Byte(handle, HDMI_TX_AUDIO_CHANNEL_REGE1, 0x01);
1135     HDMITX_WriteI2C_Byte(handle, HDMI_TX_AUDIO_CHANNEL_REGE2, 0xE4);
1136     HDMITX_WriteI2C_Byte(handle, HDMI_TX_AUDIO_CHANNEL_REGE3, HDMI_TX_AUDIO_CHANNEL_REGE3_REGChStSel_MASK);
1137     HDMITX_WriteI2C_Byte(handle, HDMI_TX_AUDIO_CHANNEL_REGE4, 0x00);
1138     HDMITX_WriteI2C_Byte(handle, HDMI_TX_AUDIO_CHANNEL_REGE5, 0x00);
1139 
1140     if (bAudInterface == (uint8_t)AUDIO_IF_SPDIF)
1141     {
1142         for (i = 0; i < 100U; i++)
1143         {
1144             HDMITX_ReadI2C_Byte(handle, HDMI_TX_CLOCK_CONTROL_REG5F, &value);
1145             if ((value & HDMI_TX_CLOCK_CONTROL_REG5F_OSFreqLock_MASK) != 0U)
1146             {
1147                 break;
1148             }
1149         }
1150     }
1151     else
1152     {
1153         HDMITX_ReadI2C_Byte(handle, HDMI_TX_AUDIO_CHANNEL_REGE5, &value);
1154         value &= (uint8_t)~HDMI_TX_AUDIO_CHANNEL_REGE5_RegEnTDM_MASK;
1155         /* 2 channel NLPCM, no TDM mode. */
1156         HDMITX_WriteI2C_Byte(handle, HDMI_TX_AUDIO_CHANNEL_REGE5, value);
1157     }
1158     HDMITX_WriteI2C_Byte(handle, HDMI_TX_AUDIO_CHANNEL_REGE0, (uint32_t)AudioEnable | 0U);
1159 }
1160 
setHDMITX_HBRAudio(display_handle_t * handle,uint8_t bAudInterface)1161 static void setHDMITX_HBRAudio(display_handle_t *handle, uint8_t bAudInterface)
1162 {
1163     HDMITX_ChangeBank(handle, 0);
1164 
1165     HDMITX_WriteI2C_Byte(handle, HDMI_TX_AUDIO_CHANNEL_REGE1, 0x47);
1166     HDMITX_WriteI2C_Byte(handle, HDMI_TX_AUDIO_CHANNEL_REGE2, 0xE4);
1167 
1168     if (bAudInterface == (uint8_t)AUDIO_IF_SPDIF)
1169     {
1170         HDMITX_WriteI2C_Byte(
1171             handle, HDMI_TX_AUDIO_CHANNEL_REGE0,
1172             HDMI_TX_AUDIO_CHANNEL_REGE0_REGAudSWL_24bits | HDMI_TX_AUDIO_CHANNEL_REGE0_REGAudSel_SPDIF);
1173         HDMITX_WriteI2C_Byte(handle, HDMI_TX_AUDIO_CHANNEL_REGE3, HDMI_TX_AUDIO_CHANNEL_REGE3_REGChStSel_MASK);
1174     }
1175     else
1176     {
1177         HDMITX_WriteI2C_Byte(handle, HDMI_TX_AUDIO_CHANNEL_REGE0, HDMI_TX_AUDIO_CHANNEL_REGE0_REGAudSWL_24bits);
1178         HDMITX_WriteI2C_Byte(handle, HDMI_TX_AUDIO_CHANNEL_REGE3, 0);
1179     }
1180     HDMITX_WriteI2C_Byte(handle, HDMI_TX_AUDIO_CHANNEL_REGE4, 0x08);
1181     HDMITX_WriteI2C_Byte(handle, HDMI_TX_AUDIO_CHANNEL_REGE5, HDMI_TX_AUDIO_CHANNEL_REGE5_RegAudHBR_MASK);
1182 
1183     if (bAudInterface == (uint8_t)AUDIO_IF_SPDIF)
1184     {
1185         uint8_t i = 0U, value = 0U;
1186 
1187         for (i = 0; i < 100U; i++)
1188         {
1189             HDMITX_ReadI2C_Byte(handle, HDMI_TX_CLOCK_CONTROL_REG5F, &value);
1190             if ((value & HDMI_TX_CLOCK_CONTROL_REG5F_OSFreqLock_MASK) != 0U)
1191             {
1192                 break;
1193             }
1194         }
1195         HDMITX_WriteI2C_Byte(handle, HDMI_TX_AUDIO_CHANNEL_REGE0,
1196                              HDMI_TX_AUDIO_CHANNEL_REGE0_REGAudSWL_24bits |
1197                                  HDMI_TX_AUDIO_CHANNEL_REGE0_REGAudSel_SPDIF |
1198                                  HDMI_TX_AUDIO_CHANNEL_REGE0_REGAudioEn_Enable_Audio_Source_0);
1199     }
1200     else
1201     {
1202         HDMITX_WriteI2C_Byte(handle, HDMI_TX_AUDIO_CHANNEL_REGE0,
1203                              HDMI_TX_AUDIO_CHANNEL_REGE0_REGAudSWL_24bits | 3U |
1204                                  HDMI_TX_AUDIO_CHANNEL_REGE0_REGAudioEn_Enable_Audio_Source_2 | 1U |
1205                                  HDMI_TX_AUDIO_CHANNEL_REGE0_REGAudioEn_Enable_Audio_Source_0);
1206     }
1207     HDMITX_SetI2C_Byte(handle, 0x5c, 1U << 6U, 0x00);
1208     HDMITX_ReadI2C_Byte(handle, HDMI_TX_AUDIO_CHANNEL_REGE0, &it6161.hdmi_tx.bAudioChannelEnable);
1209 }
1210 
setHDMITX_DSDAudio(display_handle_t * handle)1211 static void setHDMITX_DSDAudio(display_handle_t *handle)
1212 {
1213     HDMITX_WriteI2C_Byte(handle, HDMI_TX_AUDIO_CHANNEL_REGE1, 0x41);
1214     HDMITX_WriteI2C_Byte(handle, HDMI_TX_AUDIO_CHANNEL_REGE2, 0xE4);
1215     HDMITX_WriteI2C_Byte(handle, HDMI_TX_AUDIO_CHANNEL_REGE0, HDMI_TX_AUDIO_CHANNEL_REGE0_REGAudSWL_24bits);
1216     HDMITX_WriteI2C_Byte(handle, HDMI_TX_AUDIO_CHANNEL_REGE3, 0);
1217     HDMITX_WriteI2C_Byte(handle, HDMI_TX_AUDIO_CHANNEL_REGE4, 0x00);
1218     HDMITX_WriteI2C_Byte(handle, HDMI_TX_AUDIO_CHANNEL_REGE5, HDMI_TX_AUDIO_CHANNEL_REGE5_Reg1BAud_MASK);
1219 
1220     HDMITX_WriteI2C_Byte(handle, HDMI_TX_AUDIO_CHANNEL_REGE0,
1221                          HDMI_TX_AUDIO_CHANNEL_REGE0_REGAudSWL_24bits | 3U |
1222                              HDMI_TX_AUDIO_CHANNEL_REGE0_REGAudioEn_Enable_Audio_Source_2 |
1223                              HDMI_TX_AUDIO_CHANNEL_REGE0_REGAudioEn_Enable_Audio_Source_1 |
1224                              HDMI_TX_AUDIO_CHANNEL_REGE0_REGAudioEn_Enable_Audio_Source_0);
1225 }
1226 
setHDMITX_NCTS(display_handle_t * handle,uint8_t Fs)1227 static void setHDMITX_NCTS(display_handle_t *handle, uint8_t Fs)
1228 {
1229     uint32_t n = 0U, LastCTS = 0;
1230     bool HBR_mode = false;
1231     uint8_t value = 0U;
1232 
1233     HDMITX_ReadI2C_Byte(handle, HDMI_TX_AUDIO_CHANNEL_REGE5, &value);
1234     if ((HDMI_TX_AUDIO_CHANNEL_REGE5_RegAudHBR_MASK & value) != 0U)
1235     {
1236         HBR_mode = true;
1237     }
1238     else
1239     {
1240         HBR_mode = false;
1241     }
1242 
1243     switch (Fs)
1244     {
1245         case AUDFS_32KHz:
1246             n = 4096;
1247             break;
1248         case AUDFS_44p1KHz:
1249             n = 6272;
1250             break;
1251         case AUDFS_48KHz:
1252             n = 6144;
1253             break;
1254         case AUDFS_88p2KHz:
1255             n = 12544;
1256             break;
1257         case AUDFS_96KHz:
1258             n = 12288;
1259             break;
1260         case AUDFS_176p4KHz:
1261             n = 25088;
1262             break;
1263         case AUDFS_192KHz:
1264             n = 24576;
1265             break;
1266         case AUDFS_768KHz:
1267             n = 24576;
1268             break;
1269         default:
1270             n = 6144;
1271             break;
1272     }
1273 
1274     HDMITX_ChangeBank(handle, 1);
1275     HDMITX_WriteI2C_Byte(handle, HDMI_TX_REGPktAudN0, n & 0xFFU);
1276     HDMITX_WriteI2C_Byte(handle, HDMI_TX_REGPktAudN1, (n >> 8U) & 0xFFU);
1277     HDMITX_WriteI2C_Byte(handle, HDMI_TX_REGPktAudN2, (n >> 16U) & 0xFU);
1278 
1279     HDMITX_WriteI2C_Byte(handle, HDMI_TX_REGPktAudCTS0, LastCTS & 0xFFU);
1280     HDMITX_WriteI2C_Byte(handle, HDMI_TX_REGPktAudCTS1, (LastCTS >> 8U) & 0xFFU);
1281     HDMITX_WriteI2C_Byte(handle, HDMI_TX_REGPktAudCTS2, (LastCTS >> 16U) & 0xFU);
1282     HDMITX_ChangeBank(handle, 0);
1283 
1284     HDMITX_WriteI2C_Byte(handle, 0xF8, 0xC3);
1285     HDMITX_WriteI2C_Byte(handle, 0xF8, 0xA5);
1286     /* D[1] = 0, HW auto count CTS */
1287     HDMITX_SetI2C_Byte(handle, HDMI_TX_HDMI_CONTROL_REGC5, HDMI_TX_HDMI_CONTROL_REGC5_REGPktAudNCTSSel_MASK, 0x00);
1288     HDMITX_WriteI2C_Byte(handle, 0xF8, 0xFF);
1289 
1290     if (false == HBR_mode)
1291     {
1292         /* LPCM */
1293         uint8_t uData = 0U, value = 0U;
1294 
1295         HDMITX_ChangeBank(handle, 1);
1296         Fs = AUDFS_768KHz;
1297         HDMITX_WriteI2C_Byte(handle, HDMI_TX_AUDCHST_CA_FS, 0x00U | (uint32_t)Fs);
1298         /* OFS is the one's complement of FS */
1299         Fs = ~Fs;
1300 
1301         HDMITX_ReadI2C_Byte(handle, HDMI_TX_AUDCHST_OFS_WL, &value);
1302         uData = (0x0fU & value);
1303         HDMITX_WriteI2C_Byte(handle, HDMI_TX_AUDCHST_OFS_WL, ((uint32_t)Fs << 4U) | (uint32_t)uData);
1304         HDMITX_ChangeBank(handle, 0);
1305     }
1306 }
1307 
HDMITX_EnableAudioOutput(display_handle_t * handle,uint8_t AudioType,uint8_t bAudInterface,uint32_t SampleFreq,uint8_t ChNum,uint8_t * pIEC60958ChStat)1308 static void HDMITX_EnableAudioOutput(display_handle_t *handle,
1309                                      uint8_t AudioType,
1310                                      uint8_t bAudInterface,
1311                                      uint32_t SampleFreq,
1312                                      uint8_t ChNum,
1313                                      uint8_t *pIEC60958ChStat)
1314 {
1315     static uint8_t ucIEC60958ChStat[5] = {0U};
1316     uint8_t Fs                         = {0U};
1317 
1318     it6161.hdmi_tx.bAudioChannelEnable = 0;
1319     HDMITX_SetI2C_Byte(handle, HDMI_TX_GENERAL_REG04, (B_HDMITX_AUD_RST | B_TX_AREF_RST),
1320                        (B_HDMITX_AUD_RST | B_TX_AREF_RST));
1321     HDMITX_WriteI2C_Byte(
1322         handle, HDMI_TX_CLOCK_CONTROL_REG58,
1323         HDMI_TX_CLOCK_CONTROL_REG58_REGAutoOSCLK_MASK | HDMI_TX_CLOCK_CONTROL_REG58_REGMCLKFreq_2x128Fs | 0x01U);
1324 
1325     /* Power on the TxCLK (for CSC) */
1326     HDMITX_SetI2C_Byte(handle, 0x0F, 0x10, 0x00);
1327 
1328     if (bAudInterface == (uint8_t)AUDIO_IF_SPDIF)
1329     {
1330         if (AudioType == (uint8_t)T_AUDIO_HBR)
1331         {
1332             HDMITX_WriteI2C_Byte(handle, HDMI_TX_CLOCK_CONTROL_REG58, 0x81);
1333         }
1334 
1335         HDMITX_SetI2C_Byte(handle, HDMI_TX_AUDIO_CHANNEL_REGE0, HDMI_TX_AUDIO_CHANNEL_REGE0_REGAudSel_SPDIF,
1336                            HDMI_TX_AUDIO_CHANNEL_REGE0_REGAudSel_SPDIF);
1337     }
1338     else
1339     {
1340         HDMITX_SetI2C_Byte(handle, HDMI_TX_AUDIO_CHANNEL_REGE0, HDMI_TX_AUDIO_CHANNEL_REGE0_REGAudSel_SPDIF, 0x00);
1341     }
1342 
1343     if (AudioType != T_AUDIO_DSD)
1344     {
1345         /* one bit audio have no channel status. */
1346         switch (SampleFreq)
1347         {
1348             case 44100L:
1349                 Fs = AUDFS_44p1KHz;
1350                 break;
1351             case 88200L:
1352                 Fs = AUDFS_88p2KHz;
1353                 break;
1354             case 176400L:
1355                 Fs = AUDFS_176p4KHz;
1356                 break;
1357             case 32000L:
1358                 Fs = AUDFS_32KHz;
1359                 break;
1360             case 48000L:
1361                 Fs = AUDFS_48KHz;
1362                 break;
1363             case 96000L:
1364                 Fs = AUDFS_96KHz;
1365                 break;
1366             case 192000L:
1367                 Fs = AUDFS_192KHz;
1368                 break;
1369             case 768000L:
1370                 Fs = AUDFS_768KHz;
1371                 break;
1372             default:
1373                 SampleFreq = 48000L;
1374                 Fs         = AUDFS_48KHz;
1375                 break;
1376         }
1377 
1378         setHDMITX_NCTS(handle, Fs);
1379         if (pIEC60958ChStat == NULL)
1380         {
1381             ucIEC60958ChStat[0] = 0;
1382             ucIEC60958ChStat[1] = 0;
1383             ucIEC60958ChStat[2] = (ChNum + 1U) / 2U;
1384 
1385             if (ucIEC60958ChStat[2] < 1U)
1386             {
1387                 ucIEC60958ChStat[2] = 1;
1388             }
1389             else if (ucIEC60958ChStat[2] > 4U)
1390             {
1391                 ucIEC60958ChStat[2] = 4;
1392             }
1393             ucIEC60958ChStat[3] = Fs;
1394             ucIEC60958ChStat[4] = (((~Fs) << 4U) & 0xF0U) | CHTSTS_SWCODE;
1395             pIEC60958ChStat     = ucIEC60958ChStat;
1396         }
1397     }
1398     HDMITX_SetI2C_Byte(handle, HDMI_TX_GENERAL_REG04, (B_HDMITX_AUD_RST | B_TX_AREF_RST), B_TX_AREF_RST);
1399 
1400     switch (AudioType)
1401     {
1402         case T_AUDIO_HBR:
1403             HDMITX_DEBUG_PRINTF("T_AUDIO_HBR\n");
1404             pIEC60958ChStat[0] |= 1U << 1U;
1405             pIEC60958ChStat[2] = 0;
1406             pIEC60958ChStat[3] &= 0xF0U;
1407             pIEC60958ChStat[3] |= AUDFS_768KHz;
1408             pIEC60958ChStat[4] |= (((~AUDFS_768KHz) << 4U) & 0xF0U) | 0xBU;
1409             setHDMITX_ChStat(handle, pIEC60958ChStat);
1410             setHDMITX_HBRAudio(handle, bAudInterface);
1411             break;
1412         case T_AUDIO_DSD:
1413             HDMITX_DEBUG_PRINTF("T_AUDIO_DSD\n");
1414             setHDMITX_DSDAudio(handle);
1415             break;
1416         case T_AUDIO_NLPCM:
1417             HDMITX_DEBUG_PRINTF("T_AUDIO_NLPCM\n");
1418             pIEC60958ChStat[0] |= 1U << 1U;
1419             setHDMITX_ChStat(handle, pIEC60958ChStat);
1420             setHDMITX_NLPCMAudio(handle, bAudInterface);
1421             break;
1422         case T_AUDIO_LPCM:
1423             HDMITX_DEBUG_PRINTF("T_AUDIO_LPCM\n");
1424             pIEC60958ChStat[0] &= (uint8_t) ~(1U << 1U);
1425 
1426             setHDMITX_ChStat(handle, pIEC60958ChStat);
1427             setHDMITX_LPCMAudio(handle, (ChNum + 1U) / 2U, SUPPORT_AUDI_AudSWL, bAudInterface);
1428             break;
1429     }
1430     HDMITX_SetI2C_Byte(handle, HDMI_TX_INT_MASK_REG09, HDMI_TX_INT_MASK_REG09_REG_AudioOvFlw_MASK, 0x00);
1431     HDMITX_WriteI2C_Byte(handle, HDMI_TX_AUDIO_CHANNEL_REGE0, it6161.hdmi_tx.bAudioChannelEnable);
1432 
1433     HDMITX_SetI2C_Byte(handle, HDMI_TX_GENERAL_REG04, (B_HDMITX_AUD_RST | B_TX_AREF_RST), 0);
1434 }
1435 
HDMITX_AudioProcess(display_handle_t * handle)1436 static void HDMITX_AudioProcess(display_handle_t *handle)
1437 {
1438     if (it6161.hdmi_tx.support_audio != 0U)
1439     {
1440         HDMITX_DEBUG_PRINTF("%s: %d, it6161.support_audio = 0x%x\n", __func__, __LINE__, it6161.hdmi_tx.support_audio);
1441         HDMITX_AudioInfoframeSet(handle, (uint8_t)it6161.hdmi_tx.output_channel);
1442         HDMITX_EnableAudioOutput(handle, it6161.hdmi_tx.input_audio_type, it6161.hdmi_tx.input_audio_interface,
1443                                  it6161.hdmi_tx.input_audio_sample_freq, it6161.hdmi_tx.output_channel, NULL);
1444     }
1445 }
1446 
HDMITX_SetAvMute(display_handle_t * handle,uint8_t bEnable)1447 static void HDMITX_SetAvMute(display_handle_t *handle, uint8_t bEnable)
1448 {
1449     HDMITX_ChangeBank(handle, 0);
1450     HDMITX_SetI2C_Byte(handle, HDMI_TX_HDMI_CONTROL_REGC1, HDMI_TX_HDMI_CONTROL_REGC1_REGAVMute_MASK,
1451                        bEnable != 0U ? HDMI_TX_HDMI_CONTROL_REGC1_REGAVMute_MASK : 0U);
1452     HDMITX_WriteI2C_Byte(
1453         handle, HDMI_TX_HDMI_CONTROL_REGC6,
1454         HDMI_TX_HDMI_CONTROL_REGC6_REGPktGenCtrlEn_MASK | HDMI_TX_HDMI_CONTROL_REGC6_REGPktGenCtrlRpt_MASK);
1455 }
1456 
HDMITX_SetupPclkDiv2(display_handle_t * handle)1457 static void HDMITX_SetupPclkDiv2(display_handle_t *handle)
1458 {
1459     if (HDMI_TX_PCLK_DIV2)
1460     {
1461         HDMITX_DEBUG_PRINTF("PCLK Divided by 2 mode");
1462         HDMITX_SetI2C_Byte(handle, HDMI_TX_INPUT_DATA_FORMAT_REG70, HDMI_TX_INPUT_DATA_FORMAT_REG70_Reg_PCLKDiv2_MASK,
1463                            HDMI_TX_INPUT_DATA_FORMAT_REG70_Reg_PCLKDiv2_MASK);
1464     }
1465 }
1466 
1467 /*************************************************************************
1468  * Function: HDMITX_SetupCsc
1469  * Parameter: input_mode -
1470  *      D[1:0] - Color Mode
1471  *      D[4] - Colorimetry 0: ITU_BT601 1: ITU_BT709
1472  *      D[5] - Quantization 0: 0_255 1: 16_235
1473  *      D[6] - Up/Dn Filter 'Required'
1474  *         0: no up/down filter
1475  *         1: enable up/down filter when csc need.
1476  *      D[7] - Dither Filter 'Required'
1477  *         0: no dither enabled.
1478  *         1: enable dither and dither free go "when required".
1479  * output_mode -
1480  *      D[1:0] - Color mode.
1481  * Return: N/A
1482  * Remark: reg72~reg8D will be programmed depended the input with table
1483  * **********************************************************************/
HDMITX_SetupCsc(display_handle_t * handle)1484 static void HDMITX_SetupCsc(display_handle_t *handle)
1485 {
1486     uint32_t ucData = 0U, csc = 0, i = 0U;
1487     uint8_t filter      = 0; /* filter is for Video CTRL DN_FREE_GO,EN_DITHER,and ENUDFILT */
1488     uint8_t input_mode  = it6161.hdmi_tx.input_color_space;
1489     uint8_t output_mode = it6161.hdmi_tx.output_color_space;
1490     uint8_t *ptable     = NULL;
1491 
1492     /* (1) YUV422 in,RGB/YUV444 output (Output is 8-bit,input is 12-bit)
1493      * (2) YUV444/422  in,RGB output (CSC enable,and output is not YUV422)
1494      * (3) RGB in,YUV444 output   (CSC enable,and output is not YUV422)
1495      *
1496      * YUV444/RGB24 <-> YUV422 need set up/down filter.
1497      */
1498     HDMITX_DEBUG_PRINTF("hdmi_tx_setup_csc(uint8_t input_mode = %x,uint8_t output_mode = %x)\n", (int)input_mode,
1499                         (int)output_mode);
1500 
1501     switch (input_mode & F_MODE_CLRMOD_MASK)
1502     {
1503         /* YUV444 INPUT */
1504         case F_MODE_YUV444:
1505             switch (output_mode & F_MODE_CLRMOD_MASK)
1506             {
1507                 case F_MODE_YUV444:
1508                     csc = HDMI_TX_INPUT_DATA_FORMAT_REG72_Reg_CSCSel_BYPASS;
1509                     break;
1510                 case F_MODE_YUV422:
1511                     /* YUV444 to YUV422 need up/down filter for processing. */
1512                     if ((input_mode & F_VIDMODE_EN_UDFILT) != 0U)
1513                     {
1514                         filter |= HDMI_TX_INPUT_DATA_FORMAT_REG72_Reg_EN_UDFILTER_MASK;
1515                     }
1516                     csc = HDMI_TX_INPUT_DATA_FORMAT_REG72_Reg_CSCSel_BYPASS;
1517                     break;
1518                 case F_MODE_RGB444:
1519                     csc = HDMI_TX_INPUT_DATA_FORMAT_REG72_Reg_CSCSel_YUV2RGB;
1520                     /* YUV444 to RGB24 need dither */
1521                     if ((input_mode & F_VIDMODE_EN_DITHER) != 0U)
1522                     {
1523                         filter |= HDMI_TX_INPUT_DATA_FORMAT_REG72_Reg_EN_DITHER_MASK |
1524                                   HDMI_TX_INPUT_DATA_FORMAT_REG72_Reg_DNFREE_GO_MASK;
1525                     }
1526                     break;
1527             }
1528 
1529         /* YUV422 INPUT */
1530         case F_MODE_YUV422:
1531             switch (output_mode & F_MODE_CLRMOD_MASK)
1532             {
1533                 case F_MODE_YUV444:
1534                     csc = HDMI_TX_INPUT_DATA_FORMAT_REG72_Reg_CSCSel_BYPASS;
1535                     if ((input_mode & F_VIDMODE_EN_UDFILT) != 0U)
1536                     {
1537                         filter |= HDMI_TX_INPUT_DATA_FORMAT_REG72_Reg_EN_UDFILTER_MASK;
1538                     }
1539                     else if ((input_mode & F_VIDMODE_EN_DITHER) != 0U)
1540                     {
1541                         filter |= HDMI_TX_INPUT_DATA_FORMAT_REG72_Reg_EN_DITHER_MASK |
1542                                   HDMI_TX_INPUT_DATA_FORMAT_REG72_Reg_DNFREE_GO_MASK;
1543                     }
1544                     break;
1545                 case F_MODE_YUV422:
1546                     csc = HDMI_TX_INPUT_DATA_FORMAT_REG72_Reg_CSCSel_BYPASS;
1547                     break;
1548                 case F_MODE_RGB444:
1549                     csc = HDMI_TX_INPUT_DATA_FORMAT_REG72_Reg_CSCSel_YUV2RGB;
1550                     if ((input_mode & F_VIDMODE_EN_UDFILT) != 0U)
1551                     {
1552                         filter |= HDMI_TX_INPUT_DATA_FORMAT_REG72_Reg_EN_UDFILTER_MASK;
1553                     }
1554                     else if ((input_mode & F_VIDMODE_EN_DITHER) != 0U)
1555                     {
1556                         filter |= HDMI_TX_INPUT_DATA_FORMAT_REG72_Reg_EN_DITHER_MASK |
1557                                   HDMI_TX_INPUT_DATA_FORMAT_REG72_Reg_DNFREE_GO_MASK;
1558                     }
1559                     break;
1560             }
1561 
1562         /* RGB444 INPUT */
1563         case F_MODE_RGB444:
1564             switch (output_mode & F_MODE_CLRMOD_MASK)
1565             {
1566                 case F_MODE_YUV444:
1567                     csc = HDMI_TX_INPUT_DATA_FORMAT_REG72_Reg_CSCSel_RGB2YUV;
1568                     if ((input_mode & F_VIDMODE_EN_DITHER) != 0U)
1569                     {
1570                         filter |= HDMI_TX_INPUT_DATA_FORMAT_REG72_Reg_EN_DITHER_MASK |
1571                                   HDMI_TX_INPUT_DATA_FORMAT_REG72_Reg_DNFREE_GO_MASK;
1572                     }
1573                     break;
1574                 case F_MODE_YUV422:
1575                     if ((input_mode & F_VIDMODE_EN_UDFILT) != 0U)
1576                     {
1577                         filter |= HDMI_TX_INPUT_DATA_FORMAT_REG72_Reg_EN_UDFILTER_MASK;
1578                     }
1579                     else if ((input_mode & F_VIDMODE_EN_DITHER) != 0U)
1580                     {
1581                         filter |= HDMI_TX_INPUT_DATA_FORMAT_REG72_Reg_EN_DITHER_MASK |
1582                                   HDMI_TX_INPUT_DATA_FORMAT_REG72_Reg_DNFREE_GO_MASK;
1583                     }
1584                     csc = HDMI_TX_INPUT_DATA_FORMAT_REG72_Reg_CSCSel_RGB2YUV;
1585                     break;
1586                 case F_MODE_RGB444:
1587                     csc = HDMI_TX_INPUT_DATA_FORMAT_REG72_Reg_CSCSel_BYPASS;
1588                     break;
1589             }
1590     }
1591 
1592     /* set the CSC metrix registers by colorimetry and quantization */
1593     if (csc == HDMI_TX_INPUT_DATA_FORMAT_REG72_Reg_CSCSel_RGB2YUV)
1594     {
1595         switch (input_mode & (F_VIDMODE_ITU709 | F_VIDMODE_16_235))
1596         {
1597             case F_VIDMODE_ITU709 | F_VIDMODE_16_235:
1598                 ptable = bCSCMtx_RGB2YUV_ITU709_16_235;
1599                 break;
1600             case F_VIDMODE_ITU709 | F_VIDMODE_0_255:
1601                 ptable = bCSCMtx_RGB2YUV_ITU709_0_255;
1602                 break;
1603             case F_VIDMODE_ITU601 | F_VIDMODE_16_235:
1604                 ptable = bCSCMtx_RGB2YUV_ITU601_16_235;
1605                 break;
1606             case F_VIDMODE_ITU601 | F_VIDMODE_0_255:
1607             default:
1608                 ptable = bCSCMtx_RGB2YUV_ITU601_0_255;
1609                 break;
1610         }
1611     }
1612 
1613     if (csc == HDMI_TX_INPUT_DATA_FORMAT_REG72_Reg_CSCSel_YUV2RGB)
1614     {
1615         switch (input_mode & (F_VIDMODE_ITU709 | F_VIDMODE_16_235))
1616         {
1617             case F_VIDMODE_ITU709 | F_VIDMODE_16_235:
1618                 ptable = bCSCMtx_YUV2RGB_ITU709_16_235;
1619                 break;
1620             case F_VIDMODE_ITU709 | F_VIDMODE_0_255:
1621                 ptable = bCSCMtx_YUV2RGB_ITU709_0_255;
1622                 break;
1623             case F_VIDMODE_ITU601 | F_VIDMODE_16_235:
1624                 ptable = bCSCMtx_YUV2RGB_ITU601_16_235;
1625                 break;
1626             case F_VIDMODE_ITU601 | F_VIDMODE_0_255:
1627             default:
1628                 ptable = bCSCMtx_YUV2RGB_ITU601_0_255;
1629                 break;
1630         }
1631     }
1632 
1633     if (csc == HDMI_TX_INPUT_DATA_FORMAT_REG72_Reg_CSCSel_BYPASS)
1634     {
1635         HDMITX_SetI2C_Byte(handle, 0xF, 0x10, 0x10);
1636     }
1637     else
1638     {
1639         if (ptable != NULL)
1640         {
1641             for (i = 0; i < SIZEOF_CSCMTX; i++)
1642             {
1643                 HDMITX_WriteI2C_Byte(handle, (uint32_t)HDMI_TX_COLOR_SPACE_CONVERSION_REG73 + (uint32_t)i, ptable[i]);
1644             }
1645         }
1646         HDMITX_SetI2C_Byte(handle, 0xF, 0x10, 0x00);
1647     }
1648 
1649     HDMITX_ReadI2C_Byte(handle, HDMI_TX_INPUT_DATA_FORMAT_REG72, &ucData);
1650     ucData &=
1651         ~(HDMI_TX_INPUT_DATA_FORMAT_REG72_Reg_CSCSel_MASK | HDMI_TX_INPUT_DATA_FORMAT_REG72_Reg_DNFREE_GO_MASK |
1652           HDMI_TX_INPUT_DATA_FORMAT_REG72_Reg_EN_DITHER_MASK | HDMI_TX_INPUT_DATA_FORMAT_REG72_Reg_EN_UDFILTER_MASK);
1653     ucData |= filter | csc;
1654 
1655     HDMITX_WriteI2C_Byte(handle, HDMI_TX_INPUT_DATA_FORMAT_REG72, ucData);
1656 }
1657 
HDMITX_SetupAfe(display_handle_t * handle,uint8_t level)1658 static void HDMITX_SetupAfe(display_handle_t *handle, uint8_t level)
1659 {
1660     HDMITX_WriteI2C_Byte(handle, REG_TX_AFE_DRV_CTRL, B_TX_AFE_DRV_RST);
1661     switch (level)
1662     {
1663         case PCLK_HIGH:
1664             HDMITX_SetI2C_Byte(handle, 0x62, 0x90, 0x80);
1665             HDMITX_SetI2C_Byte(handle, 0x64, 0x89, 0x80);
1666             HDMITX_SetI2C_Byte(handle, 0x68, 0x10, 0x00);
1667             HDMITX_SetI2C_Byte(handle, 0x66, 0x80, 0x80);
1668             break;
1669         default:
1670             HDMITX_SetI2C_Byte(handle, 0x62, 0x90, 0x10);
1671             HDMITX_SetI2C_Byte(handle, 0x64, 0x89, 0x09);
1672             HDMITX_SetI2C_Byte(handle, 0x68, 0x10, 0x10);
1673             break;
1674     }
1675     HDMITX_DEBUG_PRINTF("setup afe: %s", level ? "high" : "low");
1676 }
1677 
1678 /* force abort DDC and reset DDC bus */
HDMITX_AbortDdc(display_handle_t * handle)1679 static void HDMITX_AbortDdc(display_handle_t *handle)
1680 {
1681     uint8_t sw_reset = 0U, retry = 2;
1682     uint8_t uc = 0U, timeout = 0U, i = 0U;
1683 
1684     HDMITX_DEBUG_PRINTF("ddc abort\n");
1685     /* save the sw reset, ddc master and cp desire setting */
1686     HDMITX_ReadI2C_Byte(handle, HDMI_TX_GENERAL_REG04, &sw_reset);
1687 
1688     HDMITX_WriteI2C_Byte(handle, HDMI_TX_GENERAL_REG04, (uint32_t)sw_reset | (uint32_t)B_TX_HDCP_RST_HDMITX);
1689     HDMITX_WriteI2C_Byte(handle, HDMI_TX_SYS_DDC_CTRL_REG10, HDMI_TX_SYS_DDC_CTRL_REG10_Reg_MasterSel_MASK);
1690 
1691     /* do abort DDC */
1692     for (i = 0; i < retry; i++)
1693     {
1694         HDMITX_WriteI2C_Byte(handle, HDMI_TX_SYS_DDC_CTRL_REG15, HDMI_TX_SYS_DDC_CTRL_REG15_RDDC_Req_Abort_DDC_CMD);
1695         HDMITX_WriteI2C_Byte(handle, HDMI_TX_SYS_DDC_CTRL_REG15,
1696                              HDMI_TX_SYS_DDC_CTRL_REG15_RDDC_Req_GenerateSCL_clock_pulse);
1697 
1698         for (timeout = 0; timeout < 200U; timeout++)
1699         {
1700             HDMITX_ReadI2C_Byte(handle, HDMI_TX_SYS_DDC_CTRL_REG16, &uc);
1701             if ((uc & HDMI_TX_SYS_DDC_CTRL_REG16_RDDC_Status_Done_MASK) != 0U)
1702             {
1703                 break;
1704             }
1705 
1706             if ((uc & (HDMI_TX_SYS_DDC_CTRL_REG16_RDDC_Status_NoACK_MASK |
1707                        HDMI_TX_SYS_DDC_CTRL_REG16_RDDC_Status_WaitBus_MASK |
1708                        HDMI_TX_SYS_DDC_CTRL_REG16_RDDC_Status_ArbiLose_MASK)) != 0U)
1709             {
1710                 HDMITX_DEBUG_PRINTF("HDMITX_AbortDdc Fail by reg16=%02X\n", (int)uc);
1711                 break;
1712             }
1713             /* delay 1 ms to stable */
1714             delay1ms(1);
1715         }
1716     }
1717 }
1718 
1719 /* DDC master will set to be host */
HDMITX_ClrDdcFifo(display_handle_t * handle)1720 static void HDMITX_ClrDdcFifo(display_handle_t *handle)
1721 {
1722     HDMITX_ChangeBank(handle, 0);
1723     HDMITX_WriteI2C_Byte(handle, HDMI_TX_SYS_DDC_CTRL_REG10, HDMI_TX_SYS_DDC_CTRL_REG10_Reg_MasterSel_MASK);
1724     HDMITX_WriteI2C_Byte(handle, HDMI_TX_SYS_DDC_CTRL_REG15, HDMI_TX_SYS_DDC_CTRL_REG15_RDDC_Req_DDC_FIFO_clear);
1725     HDMITX_SetI2C_Byte(handle, HDMI_TX_SYS_DDC_CTRL_REG10, HDMI_TX_SYS_DDC_CTRL_REG10_Reg_MasterSel_MASK, 0x00);
1726 }
1727 
HDMITX_ClrInt(display_handle_t * handle,uint8_t Reg06,uint8_t Reg07,uint8_t Reg08,uint8_t RegEE)1728 static void HDMITX_ClrInt(display_handle_t *handle, uint8_t Reg06, uint8_t Reg07, uint8_t Reg08, uint8_t RegEE)
1729 {
1730     uint8_t intClear = 0U;
1731 
1732     if ((Reg06 & HDMI_TX_INT_FLAGS_REG06_RInt_AudioOvFlwStus_MASK) != 0U)
1733     {
1734         HDMITX_DEBUG_PRINTF("HDMI_TX_INT_FLAGS_REG06_RInt_AudioOvFlwStus_MASK");
1735         HDMITX_SetI2C_Byte(handle, HDMI_TX_GENERAL_REG04, (B_HDMITX_AUD_RST | B_TX_AREF_RST),
1736                            (B_HDMITX_AUD_RST | B_TX_AREF_RST));
1737         HDMITX_SetI2C_Byte(handle, HDMI_TX_GENERAL_REG04, B_HDMITX_AUD_RST | B_TX_AREF_RST, 0x00);
1738     }
1739     else if ((Reg06 & HDMI_TX_INT_FLAGS_REG06_RInt_DDCFIFOErr_MASK) != 0U)
1740     {
1741         HDMITX_DEBUG_PRINTF("DDC FIFO Error");
1742         HDMITX_ClrDdcFifo(handle);
1743     }
1744     else if ((Reg06 & HDMI_TX_INT_FLAGS_REG06_RInt_DDCBusHang_MASK) != 0U)
1745     {
1746         HDMITX_DEBUG_PRINTF("DDC BUS HANG");
1747         HDMITX_AbortDdc(handle);
1748     }
1749 
1750     /* clear ext interrupt */
1751     HDMITX_WriteI2C_Byte(handle, 0xEE, RegEE);
1752     HDMITX_WriteI2C_Byte(handle, HDMI_TX_INT_CLEAR_REG0C, 0xFF);
1753     HDMITX_WriteI2C_Byte(handle, HDMI_TX_INT_CLEAR_REG0D, 0xFF);
1754     /* write HDMI_TX_SYS_STATUS_REG0E_Reg_IntActDone_MASK '1' to trigger clear interrupt */
1755     HDMITX_ReadI2C_Byte(handle, HDMI_TX_SYS_STATUS_REG0E, &intClear);
1756     intClear |= HDMI_TX_SYS_STATUS_REG0E_Reg_AudCTSClr_MASK | HDMI_TX_SYS_STATUS_REG0E_Reg_IntActDone_MASK;
1757     HDMITX_WriteI2C_Byte(handle, HDMI_TX_SYS_STATUS_REG0E, intClear);
1758 }
1759 
HDMITX_Reg06_Process(display_handle_t * handle,uint8_t Reg06)1760 void HDMITX_Reg06_Process(display_handle_t *handle, uint8_t Reg06)
1761 {
1762     if ((Reg06 & HDMI_TX_INT_FLAGS_REG06_RInt_HPDStus_MASK) != 0U)
1763     {
1764         if (HDMITX_GetSinkHpd(handle))
1765         {
1766             HDMITX_DEBUG_PRINTF("HDMI Cable Plug In");
1767             HDMITX_VideoReset(handle);
1768             ParseEDID(handle);
1769             it6161.hdmi_tx.hdmi_mode = RxCapability.VideoMode;
1770         }
1771         else
1772         {
1773             HDMITX_DEBUG_PRINTF("HDMI Cable Plug Out");
1774             HDMITX_DisableVideoOutput(handle);
1775         }
1776     }
1777 }
1778 
HDMITX_FireAfe(display_handle_t * handle)1779 static void HDMITX_FireAfe(display_handle_t *handle)
1780 {
1781     HDMITX_ChangeBank(handle, 0x00U);
1782     HDMITX_WriteI2C_Byte(handle, REG_TX_AFE_DRV_CTRL, 0x00);
1783 }
1784 
HDMITX_EnableVideoOutput(display_handle_t * handle,uint8_t level)1785 static void HDMITX_EnableVideoOutput(display_handle_t *handle, uint8_t level)
1786 {
1787     HDMITX_WriteI2C_Byte(handle, REG_TX_SW_RST, B_HDMITX_AUD_RST | B_TX_AREF_RST | B_TX_HDCP_RST_HDMITX);
1788     HDMITX_ChangeBank(handle, 1);
1789     HDMITX_WriteI2C_Byte(handle, HDMI_TX_AVIINFO_DB1, 0x00);
1790     HDMITX_ChangeBank(handle, 0);
1791 
1792     if (it6161.hdmi_tx.hdmi_mode != 0U)
1793     {
1794         HDMITX_SetAvMute(handle, 1U);
1795     }
1796 
1797     HDMITX_SetupPclkDiv2(handle);
1798     HDMITX_SetupCsc(handle);
1799     HDMITX_WriteI2C_Byte(handle, HDMI_TX_HDMI_CONTROL_REGC0,
1800                          it6161.hdmi_tx.hdmi_mode != 0U ? HDMI_TX_HDMI_CONTROL_REGC0_REGHDMIMode_HDMI_MODE :
1801                                                           HDMI_TX_HDMI_CONTROL_REGC0_REGHDMIMode_DVI_MODE);
1802     HDMITX_SetupAfe(handle, level);
1803     HDMITX_FireAfe(handle);
1804 }
1805 
HDMITX_SetOutputProcess(display_handle_t * handle)1806 static void HDMITX_SetOutputProcess(display_handle_t *handle)
1807 {
1808     uint8_t level      = 0U;
1809     uint32_t TMDSClock = 0U;
1810 
1811     TMDSClock = it6161.hdmi_tx.pclk * 1000U * (it6161.source_avi_infoframe.pixel_repeat + 1U);
1812 
1813     HDMITX_DEBUG_PRINTF(
1814         "%s: %d, TMDSClock = 0x%x, it6161.hdmi_tx.pclk = 0x%x, it6161.source_avi_infoframe.pixel_repeat = 0x%x\n",
1815         __func__, __LINE__, TMDSClock, it6161.hdmi_tx.pclk, it6161.source_avi_infoframe.pixel_repeat);
1816     HDMITX_DisableAudioOutput(handle);
1817     HDMITX_DisableAviInfoframe(handle);
1818 
1819     if (TMDSClock > 80000000U)
1820     {
1821         level = (uint8_t)PCLK_HIGH;
1822     }
1823     else if (TMDSClock > 20000000U)
1824     {
1825         level = (uint8_t)PCLK_MEDIUM;
1826     }
1827     else
1828     {
1829         level = (uint8_t)PCLK_LOW;
1830     }
1831 
1832     HDMITX_EnableVideoOutput(handle, level);
1833 
1834     /* Power on the TxCLK (for CSC) */
1835     HDMITX_SetI2C_Byte(handle, 0x0F, 0x10, 0x00);
1836     if (it6161.hdmi_tx.hdmi_mode != 0U)
1837     {
1838         HDMITX_AviInfoframeSet(handle);
1839         HDMITX_AudioProcess(handle);
1840     }
1841 
1842     HDMITX_SetAvMute(handle, 0U);
1843 }
1844 
HDMITX_Reg08_Process(display_handle_t * handle,uint8_t Reg08)1845 void HDMITX_Reg08_Process(display_handle_t *handle, uint8_t Reg08)
1846 {
1847     if ((Reg08 & HDMI_TX_INT_FLAGS_REG08_RInt_VidStableStus_MASK) != 0U)
1848     {
1849         HDMITX_WriteI2C_Byte(handle, HDMI_TX_INT_FLAGS_REG08, Reg08);
1850         if (HDMITX_GetVideoState(handle))
1851         {
1852             HDMITX_GetDisplayMode(handle);
1853 
1854             HDMITX_SetOutputProcess(handle);
1855             HDMITX_SetAvMute(handle, 0U);
1856         }
1857     }
1858 }
1859 
HDMITX_RegEE_Process(display_handle_t * handle,uint8_t RegEE)1860 void HDMITX_RegEE_Process(display_handle_t *handle, uint8_t RegEE)
1861 {
1862     if (RegEE != 0x00U)
1863     {
1864         HDMITX_DEBUG_PRINTF("%s%s%s%s%s%s%s", (RegEE & 0x40) ? "video parameter change " : "",
1865                             (RegEE & 0x20) ? "HDCP Pj check done " : "", (RegEE & 0x10) ? "HDCP Ri check done " : "",
1866                             (RegEE & 0x8) ? "DDC bus hang " : "", (RegEE & 0x4) ? "Video input FIFO auto reset " : "",
1867                             (RegEE & 0x2) ? "o audio input interrupt  " : "",
1868                             (RegEE & 0x1) ? "Audio decode error interrupt " : "");
1869     }
1870 }
1871 
HDMITX_DevLoopProc(display_handle_t * handle)1872 void HDMITX_DevLoopProc(display_handle_t *handle)
1873 {
1874     uint8_t Reg06 = 0U, Reg07 = 0U, Reg08 = 0U, RegEE = 0U;
1875 
1876     HDMITX_ReadI2C_Byte(handle, 0x06, &Reg06);
1877     HDMITX_ReadI2C_Byte(handle, 0x07, &Reg07);
1878     HDMITX_ReadI2C_Byte(handle, 0x08, &Reg08);
1879     HDMITX_ReadI2C_Byte(handle, 0xEE, &RegEE);
1880 
1881     if ((Reg06 != 0U) || (Reg07 != 0U) || (Reg08 != 0U))
1882     {
1883         HDMITX_ClrInt(handle, Reg06, Reg07, Reg08, RegEE);
1884     }
1885     HDMITX_Reg06_Process(handle, Reg06);
1886     HDMITX_Reg08_Process(handle, Reg08);
1887     HDMITX_RegEE_Process(handle, RegEE);
1888     DumpHDMITXReg(handle);
1889 }
1890