//-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.- DtaPPBufferWriteData -.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.- // // This function adds data to the current ping/pong buffer. If the buffer is full, // an error is returned // DtStatus DtaPPBufferWriteData( UInt8* pSourceBuffer, PPBuffer* pPPBuffer, UInt DataSize) { UInt8* pDst = NULL; UInt PPBufferIndex = pPPBuffer->m_CurRwBufferId; DT_ASSERT(pPPBuffer->m_pDmaChannel->m_DmaDirection == DT_DMA_DIRECTION_TO_DEVICE); DT_ASSERT(!DtaPPBufferIsFull(pPPBuffer, PPBufferIndex)); // Check if we do not exceed the size of the available buffer space // If so, we have an overflow situation! if (pPPBuffer->m_BufTransferSize[PPBufferIndex]+DataSize > pPPBuffer->m_BufSize[PPBufferIndex]) return DT_STATUS_BUFFER_OVERFLOW; // Calculate current location of the destiny for ping or pong buffer pDst = pPPBuffer->m_pBufStart + pPPBuffer->m_BufOffset[PPBufferIndex] + pPPBuffer->m_BufTransferSize[PPBufferIndex]; DtMemCopy(pDst, pSourceBuffer, DataSize); pPPBuffer->m_BufTransferSize[PPBufferIndex] += DataSize; return DT_STATUS_OK; }
//.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.- DtWorkItemCopy -.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-. // static DtStatus DtWorkItemStructCopy( DtWorkItemStruct* pWorkItemStructDst, DtWorkItemStruct* pWorkItemStructSrc) { DtMemCopy(pWorkItemStructDst, pWorkItemStructSrc, sizeof(DtWorkItemStruct)); return DT_STATUS_OK; }
//-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.- DtaHdmiControllerThread -.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-. // void DtaHdmiControllerThread(DtThread* pThread, void* pContext) { DtStatus Status = DT_STATUS_OK; DtaNonIpPort* pNonIpPort = (DtaNonIpPort*)pContext; DtaHdmi* pHdmi = &pNonIpPort->m_HdmiRx; Bool ConfigForHd = TRUE; DtDbgOut(MAX, HDMI, "Thread begin"); DtaFwbRegWrite(pNonIpPort->m_pFwbRegs, &pHdmi->m_pFwbHdmiAdv7610Ctrl->Control_Reset, 1); DtSleep(5); DtaFwbRegWrite(pNonIpPort->m_pFwbRegs, &pHdmi->m_pFwbHdmiAdv7610Ctrl->Control_Reset, 0); DtSleep(10); // Disable VGA framing DtaFwbRegWrite(pNonIpPort->m_pFwbRegs, &pHdmi->m_pFwbHdmiAdv7610Ctrl->Control_VgaFraming, DTFWB_HDMI_NO_FRAMING); // Disable powerdown bit if (Status == DT_STATUS_OK) Status = ADV7610_WRITE_REG(GENERAL, IO_REG_0C, 0x42); DtSleep(10); if (Status != DT_STATUS_OK) { DtDbgOut(ERR, HDMI, "Failed to disable powerdown bit: 0x%X", Status); DtaFwbRegWrite(pNonIpPort->m_pFwbRegs, &pHdmi->m_pFwbHdmiAdv7610Ctrl->Control_Reset, 1); DtThreadWaitForStop(pThread); return; } // Initialize I2C addresses of other register pages if (Status == DT_STATUS_OK) Status = ADV7610_WRITE_REG(GENERAL, CEC_SLAVE_ADDRESS, ADV7610_I2CADDR_CEC); if (Status == DT_STATUS_OK) Status = ADV7610_WRITE_REG(GENERAL, INFOFRAME_SLAVE_ADDRESS, ADV7610_I2CADDR_INFOFRAME); if (Status == DT_STATUS_OK) Status = ADV7610_WRITE_REG(GENERAL, KSV_SLAVE_ADDRESS, ADV7610_I2CADDR_KSV); if (Status == DT_STATUS_OK) Status = ADV7610_WRITE_REG(GENERAL, EDID_SLAVE_ADDRESS, ADV7610_I2CADDR_EDID); if (Status == DT_STATUS_OK) Status = ADV7610_WRITE_REG(GENERAL, HDMI_SLAVE_ADDRESS, ADV7610_I2CADDR_HDMI); if (Status == DT_STATUS_OK) Status = ADV7610_WRITE_REG(GENERAL, CP_SLAVE_ADDRESS, ADV7610_I2CADDR_CP); if (Status != DT_STATUS_OK) DtDbgOut(ERR, HDMI, "Failed to set slave I2C addresses: 0x%X", Status); // Setting clock frequency to 27Mhz and pixel bus to mode 2 if (Status == DT_STATUS_OK) Status = ADV7610_WRITE_REG(GENERAL, IO_REG_04, 0x60); // color space settings if (Status == DT_STATUS_OK) Status = ADV7610_WRITE_REG(GENERAL, IO_REG_02, 0xF4); // set IO_REG_05 if (Status == DT_STATUS_OK) Status = ADV7610_WRITE_REG(GENERAL, IO_REG_05, 0x2C); // enabling output if (Status == DT_STATUS_OK) Status = ADV7610_WRITE_REG(GENERAL, IO_REG_15, 0xA8); // disable free run mode if (Status == DT_STATUS_OK) Status = ADV7610_WRITE_REG(CP, HDMI_CP_CNTRL_1, 0x00); // disable cable detect reset if (Status == DT_STATUS_OK) Status = ADV7610_WRITE_REG(HDMI, REGISTER_48, 0x40); // enable termination automatic control if (Status == DT_STATUS_OK) Status = ADV7610_WRITE_REG(HDMI, REGISTER_01, 0x01); // enable clock termination on port a if (Status == DT_STATUS_OK) Status = ADV7610_WRITE_REG(HDMI, REGISTER_02, 0xFE); // enable dynamic eq control if (Status == DT_STATUS_OK) Status = ADV7610_WRITE_REG(HDMI, EQ_DYNAMIC_ENABLE, 0x01); // Set bit width for right justified mode on I2S interface //if (Status == DT_STATUS_OK) // Status = ADV7610_WRITE_REG(HDMI, REGISTER_03, 0x10); // Disable "mute if compressed audio is detected" bit if (Status == DT_STATUS_OK) Status = ADV7610_WRITE_REG(HDMI, MUTE_MASK21_16, 0x1F); if (Status != DT_STATUS_OK) DtDbgOut(ERR, HDMI, "Failed to initialize general registers"); // Write EDID data if (Status == DT_STATUS_OK) { Int i; UInt8 Sum = 0; UInt8 Edid[257]; UInt32 Serial; Edid[0] = 0; // Address byte DtMemCopy(Edid+1, EDID_Block, sizeof(EDID_Block)); Serial = (UInt32)pNonIpPort->m_pDvcData->m_DevInfo.m_Serial; DtMemCopy(Edid+1+0x0C, &Serial, sizeof(Serial)); for (i=0; i<127; i++) Sum += Edid[i+1]; Edid[0x80] = (255 - Sum + 1); Status = DtaI2cmWrite(&pHdmi->m_I2c, ADV7610_I2CADDR_EDID, sizeof(Edid), Edid); } if (Status != DT_STATUS_OK) DtDbgOut(ERR, HDMI, "Write EDID failure"); // enable EDID for port a if (Status == DT_STATUS_OK) Status = ADV7610_WRITE_REG(KSV, HDCP_EDID_CONTROLS, 0x01); if (Status == DT_STATUS_OK) Status = DtaHdmiConfigForHd(pHdmi); ConfigForHd = TRUE; // Set interrupt signal duration to '11': Active until cleared // Set signal configuration '10': drives high when active if (Status == DT_STATUS_OK) Status = ADV7610_WRITE_REG(GENERAL, INT1_CONFIGURATION, 0xE2); // Enable cable detect / encrypted signal interrupts if (Status == DT_STATUS_OK) Status = ADV7610_WRITE_REG(GENERAL, HDMI_LVL_INT_MASKB4, 0x05); // Enable Video clock changed, Audio mode changed, new sample rate, // TMDS freq changed interrupts if (Status == DT_STATUS_OK) Status = ADV7610_WRITE_REG(GENERAL, HDMI_EDG_INT_MASKB3, 0x6A); // Enable TMDS-PLL locked, TMDS clock detect, Vertical sync lock, DE regeneration // lock interrupts if (Status == DT_STATUS_OK) Status = ADV7610_WRITE_REG(GENERAL, HDMI_LVL_INT_MASKB3, 0x53); // Enable NEW_AVI_INFO and NEW_AUDIO_INFO interrupts if (Status == DT_STATUS_OK) Status = ADV7610_WRITE_REG(GENERAL, HDMI_LVL_INT_MASKB1, 0x03); if (Status != DT_STATUS_OK) { DtDbgOut(ERR, HDMI, "HDMI initialization failed."); DtaFwbRegWrite(pNonIpPort->m_pFwbRegs, &pHdmi->m_pFwbHdmiAdv7610Ctrl->Control_Reset, 1); DtThreadWaitForStop(pThread); return; } DtDbgOut(AVG, HDMI, "HDMI initialization complete"); while (!pThread->m_StopThread) { UInt8 Value; DtaHdmiStatus NewStatus; Int NewVidStd = DT_VIDSTD_UNKNOWN; DtaHdmiClearStatus(&NewStatus); // Read/clear cable detect / encrypted signal interrupts Status = ADV7610_READ_REG(GENERAL, HDMI_LVL_INT_STATUS4, &Value); if (Status==DT_STATUS_OK && Value!=0) ADV7610_WRITE_REG(GENERAL, HDMI_LVL_INT_CLR4, Value&0x05); Status = ADV7610_READ_REG(GENERAL, HDMI_LVL_RAW_STATUS4, &Value); if (Status == DT_STATUS_OK) { NewStatus.m_CableDet = (Value&0x01)!=0; NewStatus.m_Encrypted = (Value&0x04)!=0; } // Read/clear TMDS-PLL locked, TMDS clock detect, Vertical sync lock, // DE regeneration lock interrupts Status = ADV7610_READ_REG(GENERAL, HDMI_LVL_INT_STATUS3, &Value); if (Status==DT_STATUS_OK && Value!=0) ADV7610_WRITE_REG(GENERAL, HDMI_LVL_INT_CLR3, Value); // Read/clear TMDS freq changed interrupt Status = ADV7610_READ_REG(GENERAL, HDMI_EDG_STATUS3, &Value); if (Status==DT_STATUS_OK && Value!=0) ADV7610_WRITE_REG(GENERAL, HDMI_EDG_INT_CLR3, Value); if (NewStatus.m_CableDet) { Status = ADV7610_READ_REG(HDMI, REGISTER_04, &Value); NewStatus.m_TmdsPllLocked = (Value&0x02)!=0; NewStatus.m_AudioLocked = (Value&0x01)!=0; } // Read/clear new audio info interrupt Status = ADV7610_READ_REG(GENERAL, HDMI_LVL_INT_STATUS1, &Value); if (Status==DT_STATUS_OK && Value!=0) ADV7610_WRITE_REG(GENERAL, HDMI_LVL_INT_CLR1, Value); if (NewStatus.m_TmdsPllLocked) { Status = ADV7610_READ_REG(HDMI, HDMI_COLORSPACE, &Value); NewStatus.m_InpColorspace = Value&0x0F; Status = ADV7610_READ_REG(HDMI, REGISTER_05, &Value); NewStatus.m_PixelRepetition = Value&0x0F; Status = ADV7610_READ_REG(HDMI, LINE_WIDTH1, &Value); NewStatus.m_VertFilterLocked = (Value&0x80)!=0; NewStatus.m_DeRegenFilterLocked = (Value&0x20)!=0; NewStatus.m_VidWidth = (Value&0x01F)<<8; Status = ADV7610_READ_REG(HDMI, LINE_WIDTH2, &Value); NewStatus.m_VidWidth |= Value; Status = ADV7610_READ_REG(HDMI, FIELD0_HEIGHT1, &Value); NewStatus.m_VidHeight1 = (Value&0x01F)<<8; Status = ADV7610_READ_REG(HDMI, FIELD0_HEIGHT2, &Value); NewStatus.m_VidHeight1 |= Value; Status = ADV7610_READ_REG(HDMI, REGISTER_51, &Value); NewStatus.m_TmdsFreq = Value<<8; Status = ADV7610_READ_REG(HDMI, REGISTER_52, &Value); NewStatus.m_TmdsFreq |= Value; Status = ADV7610_READ_REG(HDMI, FIELD1_HEIGHT1, &Value); switch (Value>>6) { case 0: NewStatus.m_BitsPerChannel = 8; break; case 1: NewStatus.m_BitsPerChannel = 10; break; case 2: NewStatus.m_BitsPerChannel = 12; break; case 3: NewStatus.m_BitsPerChannel = 16; break; } NewStatus.m_Interlaced = (Value&0x20)!=0; NewStatus.m_VidHeight2 = (Value&0x01F)<<8; Status = ADV7610_READ_REG(HDMI, FIELD1_HEIGHT2, &Value); NewStatus.m_VidHeight2 |= Value; Status = ADV7610_READ_REG(GENERAL, HDMI_LVL_RAW_STATUS2, &Value); NewStatus.m_AudioChanStatusValid = (Value&0x80)!=0; if (NewStatus.m_AudioChanStatusValid) { UInt8 RegAddr = ADV7610_HDMI_CHANNEL_STATUS_DATA_1; DtaI2cmWriteRead(&pHdmi->m_I2c, ADV7610_I2CADDR_HDMI, 1, &RegAddr, sizeof(NewStatus.m_AudioChannelStatus), NewStatus.m_AudioChannelStatus); } } if (NewStatus.m_AudioLocked) { Status = ADV7610_READ_REG(HDMI, LINE_WIDTH1, &Value); NewStatus.m_AudioChannelMode = (Value>>6)&1; Status = ADV7610_READ_REG(HDMI, PACKETS_DETECTED_2, &Value); if ((Value&0x01) != 0) NewStatus.m_AudioType = 0; else if ((Value&0x02) != 0) NewStatus.m_AudioType = 1; else if ((Value&0x04) != 0) NewStatus.m_AudioType = 2; else if ((Value&0x08) != 0) NewStatus.m_AudioType = 3; }
//.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.- DtTableGet -.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-. // DtStatus DtTableGet( DtPropertyData* pPropData, const char* pTableName, Int PortIndex, UInt MaxNumEntries, UInt* pNumEntries, DtTableEntry* pTableEntry2, UInt OutBufSize) { DtStatus Status = DT_STATUS_OK; const DtTableStore* pStore = (DtTableStore*)pPropData->m_pTableStore; Int HwRevision = pPropData->m_HardwareRevision; Int FwVariant = pPropData->m_FirmwareVariant; Bool TableNameFound = FALSE; Int FindCount = 0; UInt Index; DtTableLink* pTableLinkFound = NULL; // For devices with no 'EC' VPD resource and no registry key which forces the // hardware revision, treat the hardware revision as 0 if (HwRevision < 0) HwRevision = 0; *pNumEntries = 0; if (pPropData->m_pTableStore == NULL) { DtDbgOut(ERR, TABLE, "There are no tables defined at all for DTX-%d", pPropData->m_TypeNumber); return DT_STATUS_NOT_FOUND; } // If the property is not found for a specific fw-variant try a second time // without specifying a specific fw-variant for (FindCount=0; FindCount<2 && pTableLinkFound==NULL; FindCount++) { if (FindCount == 1) FwVariant = -1; TableNameFound = FALSE; // Search all tables for (Index=0; Index<pStore->m_TableLinkCount; Index++) { const DtTableLink* pTableLink = &pStore->m_pTableLink[Index]; // Check if the table name was already found. If so, we stop if // name <> NULL. if (TableNameFound) { // When the table name was found earlier, only accept entries without // a name. We just stop when (another) named entry is found. if (pTableLink->m_pName != NULL) break; } else { // Compare name to check if we found the first occurrence if (DtAnsiCharArrayIsEqual(pTableName, pTableLink->m_pName)) TableNameFound = TRUE; } if (TableNameFound) { // Check port number and firmware variant if (PortIndex==pTableLink->m_PortIndex && FwVariant==pTableLink->m_FwVariant) { // Check minimal firmware version if (pPropData->m_FirmwareVersion >= pTableLink->m_MinFw) { // Check minimal hardware version if (HwRevision >= pTableLink->m_MinHw) { pTableLinkFound = (DtTableLink*)pTableLink; // We can stop here since the parser has ordened each // property by minimal firmware version/hardware version. // This means the first hit is the best one break; } } } } } } if (!TableNameFound) { DtDbgOut(ERR, TABLE, "Table %s is not found at all for DTX-%d", pTableName, pStore->m_TypeNumber); Status = DT_STATUS_NOT_FOUND; } // Check if the table was found if (pTableLinkFound == NULL) { Status = DT_STATUS_NOT_FOUND; DtDbgOut(ERR, TABLE, "Failed to get table %s for DTX-%d:%d, FW %d, HW %d port %i", pTableName, pPropData->m_TypeNumber, pPropData->m_SubDvc, pPropData->m_FirmwareVersion, pPropData->m_HardwareRevision, PortIndex); } if (DT_SUCCESS(Status) && pTableLinkFound!=NULL) { DtDbgOut(MAX, TABLE, "Found table %s for DTX-%d:%d, FW %d, HW %d. #EL:%i #MAX:%i" , pTableName, pPropData->m_TypeNumber, pPropData->m_SubDvc, pPropData->m_FirmwareVersion, pPropData->m_HardwareRevision, pTableLinkFound->m_TableEntryCount, MaxNumEntries); *pNumEntries = pTableLinkFound->m_TableEntryCount; // Check if enough space for the table if (MaxNumEntries < pTableLinkFound->m_TableEntryCount) { if (MaxNumEntries != 0) DtDbgOut(ERR, TABLE, "Max. number of entries to small. Needed:%i, " "Space for:%i", pTableLinkFound->m_TableEntryCount, MaxNumEntries); } else if (OutBufSize < pTableLinkFound->m_TableEntryCount * sizeof(DtTableEntry)) { DtDbgOut(ERR, TABLE, "Buffer smaller than indicated by MaxNumEntries"); Status = DT_STATUS_INVALID_PARAMETER; } else { // Copy table DtMemCopy(pTableEntry2, (void*)pTableLinkFound->m_pTableEntries, pTableLinkFound->m_TableEntryCount * sizeof(DtTableEntry)); } } return Status; }