/** * @brief Switch HDCP Failure Check with Vertical Sync Rate * * @param[in] switch_on true to switch on; false to switch off * *****************************************************************************/ static void switch_hdcp_failure_check_with_v_sync_rate(bool_t switch_on) { if(switch_on) { rx_isr.hdcp_fail_cntr = 1; //rx_isr.check_hdcp_on_vsync = true; // don't clear HDCP Failure Int if this bit is set rx_isr.shadow_interrupt_mask[INT2] |= RX_M__INTR2__VSYNC; rx_isr.shadow_interrupt_mask[INT4] &= ~RX_M__INTR4__HDCP; } else { rx_isr.hdcp_fail_cntr = 0; //rx_isr.check_hdcp_on_vsync = false; rx_isr.shadow_interrupt_mask[INT2] &= ~RX_M__INTR2__VSYNC; rx_isr.shadow_interrupt_mask[INT4] |= RX_M__INTR4__HDCP; } SiiRegWrite(RX_A__INTR2_MASK, rx_isr.shadow_interrupt_mask[INT2]); SiiRegWrite(RX_A__INTR4_MASK, rx_isr.shadow_interrupt_mask[INT4]); // Clear BCH counter. // The counter accomulates BCH errors and if it is not cleared it can cause an HDCP failure interrupt // Capture and clear BCH T4 errors. SiiRegWrite(RX_A__ECC_CTRL, RX_M__ECC_CTRL__CAPTURE_CNT); }
static void MhlTxDrvProcessConnection ( void ) { TX_DEBUG_PRINT (("MHL Cable Connected. CBUS:0x0A = %02X\n", (int) SiiRegRead(REG_CBUS_BUS_STATUS))); if( POWER_STATE_D0_MHL == fwPowerState ) { return; } #ifdef __KERNEL__ //HalGpioSetPin(GPIO_M2U_VBUS_CTRL,0); #else pinM2uVbusCtrlM = 0; #endif #if (SYSTEM_BOARD == SB_EPV5_MARK_II) pinMhlConn = 0; pinUsbConn = 1; #elif (SYSTEM_BOARD == SB_STARTER_KIT_X01) #ifdef __KERNEL__ //HalGpioSetPin(GPIO_MHL_USB,0); #else pinMhlUsb = 0; #endif #endif SiiRegWrite(REG_MHLTX_CTL1, 0x10); fwPowerState = POWER_STATE_D0_MHL; // change TMDS termination to 50 ohm termination(default) //bits 1:0 set to 00 SiiRegWrite(TX_PAGE_2|0x0001, 0x00); ENABLE_DISCOVERY; SiiMhlTxNotifyConnection(true); }
/** * @brief Switch Receive Audio InfoFrame On Every Packet Interrupts Handler * * @param[in] switch_on true to switch on; false to switch off * *****************************************************************************/ void RxIsr_SwitchReceiveInfoFrameOnEveryPacket(uint8_t info_type, bool_t switch_on) { switch(info_type) { case INFO_AVI: SiiRegBitsSet(RX_A__INT_IF_CTRL, RX_M__INT_IF_CTRL__NEW_AVI, switch_on); SiiRegWrite(RX_A__INTR3, RX_M__INTR3__NEW_AVI_PACKET); // reset the interrupt break; case INFO_AUD: SiiRegBitsSet(RX_A__INT_IF_CTRL, RX_M__INT_IF_CTRL__NEW_AUD, switch_on); SiiRegWrite(RX_A__INTR3, RX_M__INTR3__NEW_AUD_PACKET); // reset the interrupt break; case INFO_ACP: SiiRegBitsSet(RX_A__INT_IF_CTRL, RX_M__INT_IF_CTRL__NEW_ACP, switch_on); SiiRegWrite(RX_A__INTR6, RX_M__INTR6__NEW_ACP_PACKET); // reset the interrupt break; case INFO_VSI: SiiRegBitsSet(RX_A__INT_IF_CTRL, RX_M__INT_IF_CTRL__NEW_VSI, switch_on); SiiRegWrite(RX_A__INTR7, RX_M__INTR7__NEW_VSI_PACKET); // reset the interrupt break; default: break; } }
/** * @brief Initialize the CBUS hardware for the current instance. * * @return Status * @retval true Success * @retval false Failure * * @note: Requires that SiiDrvCbusInstanceSet() is called prior to this call * *****************************************************************************/ bool_t SiiDrvCbusInitialize ( void ) { uint_t index; SiiRegModify(RX_A__SWRST2, RX_M__SWRST2__CBUS_SRST, SET_BITS); SiiRegModify(RX_A__SWRST2, RX_M__SWRST2__CBUS_SRST, CLEAR_BITS); memset( pDrvCbus, 0, sizeof( CbusDrvInstanceData_t )); // Setup local DEVCAP registers for read by the peer for ( index = 0; index < (sizeof( cbusInitCbusRegsList) / 2); index += 2 ) { SiiRegWrite( cbusInitCbusRegsList[ index], cbusInitCbusRegsList[ index + 1] ); } // Audio link mode update by switch status if ( SiiSpdifEnableGet() || !SiiTdmEnableGet() ) { SiiRegWrite(REG_CBUS_DEVICE_CAP_6, MHL_AUD_LINK_MODE_2CH); } // Enable the VS commands, all interrupts, and clear legacy SiiRegWrite( REG_CBUS_INTR_0_MASK, 0xFF ); // Enable desired interrupts SiiRegWrite( REG_CBUS_INTR_1_MASK, 0xCC ); // Enable desired interrupts SiiRegWrite( RX_CBUS_CH_RST_CTRL, 0x00 ); // MHL: Tri-state CBUS #ifdef MHAWB_SUPPORT SiiDrvHawbEnable(false); #endif return( true ); }
/////////////////////////////////////////////////////////////////////////// // // MhlTxDrvProcessConnection // /////////////////////////////////////////////////////////////////////////// static void MhlTxDrvProcessConnection (void) { TX_DEBUG_PRINT (("Drv: MHL Cable Connected. CBUS:0x0A = %02X\n", (int) SiiRegRead(TX_PAGE_CBUS | 0x000A))); if( POWER_STATE_D0_MHL == fwPowerState ) { return; } // VBUS control gpio //pinM2uVbusCtrlM = 0; //pinMhlConn = 0; //pinUsbConn = 1; // // Discovery over-ride: reg_disc_ovride // SiiRegWrite(REG_MHLTX_CTL1, 0x10); fwPowerState = POWER_STATE_D0_MHL; // // Increase DDC translation layer timer (uint8_t mode) // Setting DDC Byte Mode // SiiRegWrite(REG_CBUS_COMMON_CONFIG, 0xF2); // Enable segment pointer safety //SET_BIT(0x0C44, 1); // Un-force HPD (it was kept low, now propagate to source //CLR_BIT(REG_INT_CTRL, 4); // Enable TMDS //SiiMhlTxDrvTmdsControl( true ); // Change TMDS termination to 50 ohm termination (default) // Bits 1:0 set to 00 SiiRegWrite(TX_PAGE_2 | 0x0001, 0x00); // Keep the discovery enabled. Need RGND interrupt ENABLE_DISCOVERY // Wait T_SRC_RXSENSE_CHK ms to allow connection/disconnection to be stable (MHL 1.0 specs) // TX_DEBUG_PRINT (("[%d] Drv: Wait T_SRC_RXSENSE_CHK (%d ms) before checking RSEN\n", // (int) (HalTimerElapsed( ELAPSED_TIMER ) * MONITORING_PERIOD), // (int) T_SRC_RXSENSE_CHK) ); // // Ignore RSEN interrupt for T_SRC_RXSENSE_CHK duration. // Get the timer started // // HalTimerSet(TIMER_TO_DO_RSEN_CHK, T_SRC_RXSENSE_CHK); // Notify upper layer of cable connection SiiMhlTxNotifyConnection(mhlConnected = true); }
static void MhlTxDrvProcessDisconnection ( void ) { TX_DEBUG_PRINT(("MhlTxDrvProcessDisconnection\n")); SiiRegWrite(REG_INTR4, SiiRegRead(REG_INTR4)); dsHpdStatus &= ~BIT6; SiiRegWrite(REG_MSC_REQ_ABORT_REASON, dsHpdStatus); SiiMhlTxNotifyDsHpdChange(0); if( POWER_STATE_D0_MHL == fwPowerState ) { SiiMhlTxNotifyConnection(false); } SwitchToD3(); }
static int Int4Isr( void ) { uint8_t int4Status; int4Status = SiiRegRead(REG_INTR4); if(!int4Status) { } else if(0xFF == int4Status) { return I2C_INACCESSIBLE; }else { TX_DEBUG_PRINT(("INT4 Status = %02X\n", (int) int4Status)); if(int4Status & BIT0) { ProcessScdtStatusChange(); } if(int4Status & BIT2) { MhlTxDrvProcessConnection(); } else if(int4Status & BIT3) { TX_DEBUG_PRINT(("uUSB-A type device detected.\n")); SiiRegWrite(REG_DISC_STAT2, 0x80); SwitchToD3(); return I2C_INACCESSIBLE; } if (int4Status & BIT5) { MhlTxDrvProcessDisconnection(); return I2C_INACCESSIBLE; } if((POWER_STATE_D0_MHL != fwPowerState) && (int4Status & BIT6)) { SwitchToD0(); ProcessRgnd(); } if(fwPowerState != POWER_STATE_D3) { if (int4Status & BIT4) { TX_DEBUG_PRINT(("CBus Lockout\n")); ForceUsbIdSwitchOpen(); ReleaseUsbIdSwitchOpen(); } } } SiiRegWrite(REG_INTR4, int4Status); return I2C_ACCESSIBLE; }
//////////////////////////////////////////////////////////////////// // Int5Isr // // // Look for interrupts on INTR5 // 7 = // 6 = // 5 = // 4 = // 3 = // 2 = // 1 = // 0 = //////////////////////////////////////////////////////////////////// static void Int5Isr (void) { uint8_t int5Status; int5Status = SiiRegRead(REG_INTR5); // read status #if 0 if((int5Status & BIT4) || (int5Status & BIT3)) // FIFO U/O { TX_DEBUG_PRINT(("** int5Status = %02X; Applying MHL FIFO Reset\n", (int)int5Status)); SiiRegWrite(REG_SRST, 0x94); SiiRegWrite(REG_SRST, 0x84); } #endif SiiRegWrite(REG_INTR5, int5Status); // clear all interrupts }
////////////////////////////////////////////////////////////////////////////// // // FUNCTION : SendAudioInfoFrame() // // PURPOSE : Load Audio InfoFrame data into registers and send to sink // // INPUT PARAMS : (1) Channel count (2) speaker configuration per CEA-861D // Tables 19, 20 (3) Coding type: 0x09 for DSD Audio. 0 (refer // to stream header) for all the rest (4) Sample Frequency. Non // zero for HBR only (5) Audio Sample Length. Non zero for HBR // only. // // OUTPUT PARAMS : None // // GLOBALS USED : None // // RETURNS : true // ////////////////////////////////////////////////////////////////////////////// void SendAudioInfoFrame (void) { if (sink_type_HDMI == SiiMhlTxGetSinkType()) { uint8_t ifData[SIZE_AUDIO_INFOFRAME]; uint8_t i; ifData[0] = 0x84; ifData[1] = 0x01; ifData[2] = 0x0A; for (i = 3; i < SIZE_AUDIO_INFOFRAME; ++i) { ifData[i] = 0; } ifData[3] = CalculateGenericCheckSum(ifData,0,SIZE_AUDIO_INFOFRAME); SiiRegWrite(REG_TPI_INFO_FSEL , BIT_TPI_INFO_EN | BIT_TPI_INFO_RPT | BIT_TPI_INFO_READ_FLAG_NO_READ | BIT_TPI_INFO_SEL_Audio ); SiiRegWriteBlock(REG_TPI_INFO_BYTE00,ifData,SIZE_AUDIO_INFOFRAME); INFO_DEBUG_PRINT(("REG_TPI_INFO_BYTE13: %02x\n",REG_TPI_INFO_BYTE13)); } }
bool_t SiiCraInitialize ( void ) { uint8_t i, index; craInstance.lastResultCode = RESULT_CRA_SUCCESS; for (i = 0; i < SII_CRA_DEVICE_PAGE_COUNT; i++) { l_pageInstance[i] = 0; } // Perform any register page base address reassignments i = 0; while ( g_siiRegPageBaseReassign[ i] != 0xFFFF ) { index = g_siiRegPageBaseReassign[ i] >> 8; if (( index < SII_CRA_DEVICE_PAGE_COUNT ) && ( g_siiRegPageBaseRegs[ index] != 0xFF)) { // The page base registers allow reassignment of the // I2C device ID for almost all device register pages. SiiRegWrite( g_siiRegPageBaseRegs[ index], g_siiRegPageBaseReassign[ index] & 0x00FF ); } else { craInstance.lastResultCode = SII_ERR_INVALID_PARAMETER; break; } i++; } return( craInstance.lastResultCode == RESULT_CRA_SUCCESS ); }
static void Int5Isr (void) { uint8_t int5Status; int5Status = SiiRegRead(REG_INTR5); if (int5Status) { #if (SYSTEM_BOARD == SB_STARTER_KIT_X01) if((int5Status & BIT3) || (int5Status & BIT2)) { TX_DEBUG_PRINT (("** Apply MHL FIFO Reset\n")); SiiRegModify(REG_SRST, BIT4, SET_BITS); SiiRegModify(REG_SRST, BIT4, CLEAR_BITS); } #endif if (int5Status & BIT4) { TX_DEBUG_PRINT (("** PXL Format changed\n")); #ifndef __KERNEL__ SiiOsBumpMhlTxEvent(); #else //SiiTriggerExtInt(); #endif } SiiRegWrite(REG_INTR5, int5Status); } }
static void Int1Isr(void) { uint8_t regIntr1; regIntr1 = SiiRegRead(REG_INTR1); if (regIntr1) { SiiRegWrite(REG_INTR1,regIntr1); if (BIT6 & regIntr1) { uint8_t cbusStatus; cbusStatus = SiiRegRead(REG_MSC_REQ_ABORT_REASON); TX_DEBUG_PRINT(("Drv: dsHpdStatus =%02X\n", (int) dsHpdStatus)); if(BIT6 & (dsHpdStatus ^ cbusStatus)) { uint8_t status = cbusStatus & BIT6; TX_DEBUG_PRINT(("Drv: Downstream HPD changed to: %02X\n", (int) cbusStatus)); SiiMhlTxNotifyDsHpdChange( status ); if(status) { AudioVideoIsr(true); } dsHpdStatus = cbusStatus; } } if(BIT7 & regIntr1) { TX_DEBUG_PRINT(("MHL soft interrupt triggered \n")); } } }
/////////////////////////////////////////////////////////////////////////// // // ForceUsbIdSwitchOpen // /////////////////////////////////////////////////////////////////////////// static void ForceUsbIdSwitchOpen (void) { DISABLE_DISCOVERY SiiRegModify(REG_DISC_CTRL6, BIT6, BIT6); // Force USB ID switch to open SiiRegWrite(REG_DISC_CTRL3, 0x86); SiiRegModify(REG_INT_CTRL, BIT5 | BIT4, BIT4); // Force HPD to 0 when not in Mobile HD mode. }
void SiiHmdiTxLiteDrvSendHwAviInfoFrame( void ) { /* extern void *memcpy(void *dest, const void *src, uint8_t n); extern void *memset (void *s, char val, int n); uint8_t Real_aviPayLoad[17];*/ INFO_DEBUG_PRINT(("Output Mode: %s\n",(sink_type_HDMI == SiiMhlTxGetSinkType())?"HDMI":"DVI")); if (sink_type_HDMI == SiiMhlTxGetSinkType()) { SiiRegWrite(REG_TPI_INFO_FSEL , BIT_TPI_INFO_EN | BIT_TPI_INFO_RPT | BIT_TPI_INFO_READ_FLAG_NO_READ | BIT_TPI_INFO_SEL_AVI ); /* memset(&Real_aviPayLoad[0], 0x00, 17); memcpy(&Real_aviPayLoad[3],aviPayLoad.ifData,sizeof(aviPayLoad.ifData)); Real_aviPayLoad[0]=0x82; Real_aviPayLoad[1]=0x02; Real_aviPayLoad[2]=0x0D; SiiRegWriteBlock(REG_TPI_AVI_CHSUM, (uint8_t*)&Real_aviPayLoad, 17); DumpAviInfoFrame(&Real_aviPayLoad[0],"outgoing") // no semicolon needed */ SiiRegWriteBlock(REG_TPI_AVI_CHSUM, (uint8_t *)&aviPayLoad.ifData, sizeof(aviPayLoad.ifData)); DumpAviInfoFrame(&aviPayLoad,"outgoing") // no semicolon needed }
void SiiDrvHdmiTxLiteDisableEncryption (void) { HDCP_DEBUG_PRINT(("HDCP -> Stopped. 2A = 0\n")); printk("HDCP -> Stopped. 2A = 0\n"); SiiRegWrite(TPI_HDCP_CONTROL_DATA_REG, 0); }
void SiiRegBitsSet ( SiiReg_t virtualAddr, uint8_t bitMask, bool_t setBits ) { uint8_t aByte; aByte = SiiRegRead( virtualAddr ); aByte = (setBits) ? (aByte | bitMask) : (aByte & ~bitMask); SiiRegWrite( virtualAddr, aByte ); }
/** * @brief Handler for HDCP Error * *****************************************************************************/ static void hdcp_error_handler(bool_t v_sync_mode) { if(v_sync_mode) { if(0 == SiiRegReadWord(RX_A__HDCP_ERR)) { // Recovered- return to normal checking mode DEBUG_PRINT(MSG_STAT, ( "RX: BCH recovered ***\n")); switch_hdcp_failure_check_with_v_sync_rate(OFF); } else { // Another failure rx_isr.hdcp_fail_cntr++; if(HDCP_FAIL_THRESHOLD_1ST == rx_isr.hdcp_fail_cntr) { DEBUG_PRINT(MSG_STAT, ( "RX: Cont. BCH Error ***\n")); // Reset Ri to notify an upstream device about the failure. // In most cases Ri is already mismatched if we see BCH errors, // but there is one rare case when the reseting can help. // It is when Ri and Ri' are matched all the time but Ri and Ri' // switching happens not synchronously causing a snow // screen flashing every 2 seconds. It may happen with // some old incomplaint sources or sinks (especially DVI). SiiRegWrite(RX_A__HDCP_DEBUG, RX_M__HDCP_DEBUG__CLEAR_RI); // Clear BCH counter. // The counter accumulates BCH errors and // if it is not cleared it can cause an HDCP failure interrupt. // Capture and clear BCH T4 errors. SiiRegWrite(RX_A__ECC_CTRL, RX_M__ECC_CTRL__CAPTURE_CNT); // repeat HPD cycle if HDCP is not recovered // in some time rx_isr.hdcp_fail_cntr = HDCP_FAIL_THRESHOLD_1ST - HDCP_FAIL_THRESHOLD_CONTINUED; } } } else { switch_hdcp_failure_check_with_v_sync_rate(ON); DEBUG_PRINT(MSG_STAT, ( "RX: 1st BCH Error ***\n")); } }
void SwitchToD3( void ) { if(POWER_STATE_D3 != fwPowerState) { TX_DEBUG_PRINT(("Switch To D3\n")); #ifdef __KERNEL__ //HalGpioSetPin(GPIO_M2U_VBUS_CTRL,1); #else pinM2uVbusCtrlM = 1; #endif #if (SYSTEM_BOARD == SB_EPV5_MARK_II) pinMhlConn = 1; pinUsbConn = 0; #elif (SYSTEM_BOARD == SB_STARTER_KIT_X01) #ifdef __KERNEL__ //HalGpioSetPin(GPIO_MHL_USB,1); #else pinMhlUsb = 1; #endif #endif // change TMDS termination to high impedance //bits 1:0 set to 03 SiiRegWrite(TX_PAGE_2|0x0001, 0x03); SiiRegWrite(REG_MHLTX_CTL1, 0xD0); // clear all interrupt here before go into D3 mode by oscar SiiRegWrite(REG_INTR1,0xFF); SiiRegWrite(REG_INTR2,0xFF); SiiRegWrite(REG_INTR4,0xFF); SiiRegWrite(REG_INTR5,0xFF); SiiRegWrite(REG_CBUS_INTR_STATUS,0xFF); SiiRegWrite(REG_CBUS_MSC_INT2_STATUS,0xFF); #ifndef __KERNEL__ //if(HalGpioGetPin(pinAllowD3)) { #endif ForceUsbIdSwitchOpen(); HalTimerWait(50); ReleaseUsbIdSwitchOpen(); //HalTimerWait(50); CLR_BIT(REG_POWER_EN, 0); CBusQueueReset(); fwPowerState = POWER_STATE_D3; #ifndef __KERNEL__ }/*else { //fwPowerState = POWER_STATE_D0_NO_MHL; } */ #endif } }
void SiiRegModify ( SiiReg_t virtualAddr, uint8_t mask, uint8_t value) { uint8_t aByte; aByte = SiiRegRead( virtualAddr ); aByte &= (~mask); // first clear all bits in mask aByte |= (mask & value); // then set bits from value SiiRegWrite( virtualAddr, aByte ); }
static void SetACRNValue (void) { uint8_t audioFs; if ((SiiRegRead(TX_PAGE_L1 | 0x14) & BIT1) && !(SiiRegRead(TX_PAGE_L1 | 0x15) & BIT1)) audioFs = SiiRegRead(TX_PAGE_L1 | 0x18) & 0x0F; else audioFs = SiiRegRead(TX_PAGE_L1 | 0x21) & 0x0F; switch (audioFs) { case 0x03: SiiRegWrite(TX_PAGE_L1 | 0x05, (uint8_t)(ACR_N_value_32k >> 16)); SiiRegWrite(TX_PAGE_L1 | 0x04, (uint8_t)(ACR_N_value_32k >> 8)); SiiRegWrite(TX_PAGE_L1 | 0x03, (uint8_t)(ACR_N_value_32k)); break; case 0x00: SiiRegWrite(TX_PAGE_L1 | 0x05, (uint8_t)(ACR_N_value_44k >> 16)); SiiRegWrite(TX_PAGE_L1 | 0x04, (uint8_t)(ACR_N_value_44k >> 8)); SiiRegWrite(TX_PAGE_L1 | 0x03, (uint8_t)(ACR_N_value_44k)); break; case 0x02: SiiRegWrite(TX_PAGE_L1 | 0x05, (uint8_t)(ACR_N_value_48k >> 16)); SiiRegWrite(TX_PAGE_L1 | 0x04, (uint8_t)(ACR_N_value_48k >> 8)); SiiRegWrite(TX_PAGE_L1 | 0x03, (uint8_t)(ACR_N_value_48k)); break; case 0x08: SiiRegWrite(TX_PAGE_L1 | 0x05, (uint8_t)(ACR_N_value_88k >> 16)); SiiRegWrite(TX_PAGE_L1 | 0x04, (uint8_t)(ACR_N_value_88k >> 8)); SiiRegWrite(TX_PAGE_L1 | 0x03, (uint8_t)(ACR_N_value_88k)); break; case 0x0A: SiiRegWrite(TX_PAGE_L1 | 0x05, (uint8_t)(ACR_N_value_96k >> 16)); SiiRegWrite(TX_PAGE_L1 | 0x04, (uint8_t)(ACR_N_value_96k >> 8)); SiiRegWrite(TX_PAGE_L1 | 0x03, (uint8_t)(ACR_N_value_96k)); break; case 0x0C: SiiRegWrite(TX_PAGE_L1 | 0x05, (uint8_t)(ACR_N_value_176k >> 16)); SiiRegWrite(TX_PAGE_L1 | 0x04, (uint8_t)(ACR_N_value_176k >> 8)); SiiRegWrite(TX_PAGE_L1 | 0x03, (uint8_t)(ACR_N_value_176k)); break; case 0x0E: SiiRegWrite(TX_PAGE_L1 | 0x05, (uint8_t)(ACR_N_value_192k >> 16)); SiiRegWrite(TX_PAGE_L1 | 0x04, (uint8_t)(ACR_N_value_192k >> 8)); SiiRegWrite(TX_PAGE_L1 | 0x03, (uint8_t)(ACR_N_value_192k)); break; default: SiiRegWrite(TX_PAGE_L1 | 0x05, (uint8_t)(ACR_N_value_default >> 16)); SiiRegWrite(TX_PAGE_L1 | 0x04, (uint8_t)(ACR_N_value_default >> 8)); SiiRegWrite(TX_PAGE_L1 | 0x03, (uint8_t)(ACR_N_value_default)); break; } SiiRegModify(REG_AUDP_TXCTRL, BIT2, CLEAR_BITS); }
/** * @brief Switch No VSI InfoFrame Interrupts Handler * * @param[in] switch_on true to switch on; false to switch off * *****************************************************************************/ static void switch_NoVSI_interrupt(bool_t switch_on) { uint8_t pipe = SiiDrvRxInstanceGet(); uint8_t mask7 = rx_isr[pipe].shadow_interrupt_mask[INT7]; if(switch_on) { SiiRegWrite(RX_A__INTR7, RX_M__INTR7__NO_VSI_PACKET); // clear No AVI interrupt if it was raised rx_isr[pipe].shadow_interrupt_mask[INT7] |= RX_M__INTR7_MASK__NO_VSI_PACKET; } else { rx_isr[pipe].shadow_interrupt_mask[INT7] &= ~RX_M__INTR7_MASK__NO_VSI_PACKET; } if(mask7!= rx_isr[pipe].shadow_interrupt_mask[INT7]) SiiRegWrite(RX_A__INTR7_MASK, rx_isr[pipe].shadow_interrupt_mask[INT7]); // If NO AVI interrupt is ON, look for NEW AVI only. // If NO AVI interrupt is OFF, look for ANY AVI. RxIsr_SwitchReceiveInfoFrameOnEveryPacket(INFO_VSI, !switch_on); }
/** * @brief Switch HDCP Interrupts Handler * * @param[in] switch_on true to switch on; false to switch off * *****************************************************************************/ void RxIsr_SwitchRxHdcpInterrupts(bool_t switch_on) { if(switch_on) { rx_isr.shadow_interrupt_mask[INT1] |= (RX_M__INTR1__AUTH_START | RX_M__INTR1__AUTH_DONE); SiiRegWrite(RX_A__INTR1, RX_M__INTR1__AUTH_START | RX_M__INTR1__AUTH_DONE); // interrupt reset } else { rx_isr.shadow_interrupt_mask[INT1] &= ~RX_M__INTR1__AUTH_START; rx_isr.shadow_interrupt_mask[INT1] |= RX_M__INTR1__AUTH_DONE; } SiiRegWrite(RX_A__INTR1_MASK, rx_isr.shadow_interrupt_mask[INT1]); // set mask if(!switch_on) // just in case: reset interrupt if they were set { SiiRegWrite(RX_A__INTR1, RX_M__INTR1__AUTH_START | RX_M__INTR1__AUTH_DONE); } }
void SiiRegBitsSetNew ( SiiReg_t virtualAddr, uint8_t bitMask, bool_t setBits ) { uint8_t newByte, oldByte; oldByte = SiiRegRead( virtualAddr ); newByte = (setBits) ? (oldByte | bitMask) : (oldByte & ~bitMask); if ( oldByte != newByte ) { SiiRegWrite( virtualAddr, newByte ); } }
/** * @brief Interrupt Handler for HDMI / DVI Transition * *****************************************************************************/ static void RxIsr_HdmiDviTransition(void) { if(SiiDrvRxHdmiModeGet()) { // Clear BCH counter and the interrupt associated with it. // It'll help avoiding a false HDCP Error interrupt caused by pre-HDMI // counter content. // Capture and clear BCH T4 errors. SiiRegWrite(RX_A__ECC_CTRL, RX_M__ECC_CTRL__CAPTURE_CNT); SiiRegWrite(RX_A__INTR4, RX_M__INTR4__HDCP); // reset the HDCP BCH error interrupt DEBUG_PRINT(MSG_STAT, ("RX: HDMI\n")); RxAudio_ReStart(); } else { DEBUG_PRINT(MSG_STAT, ("RX: DVI\n")); // forget all HDMI settings RxInfo_ResetData(); RxAudio_Stop(); } }
/////////////////////////////////////////////////////////////////////////////// // // Function Name: MHLSinkOrDonglePowerStatusCheck() // // Function Description: Check MHL device is dongle or sink to set inputting current limitation. // void MHLSinkOrDonglePowerStatusCheck (void) { uint8_t RegValue; if( POWER_STATE_D0_MHL == fwPowerState ) { SiiRegWrite( REG_CBUS_PRI_ADDR_CMD, MHL_DEV_CATEGORY_OFFSET ); // DevCap 0x02 SiiRegWrite( REG_CBUS_PRI_START, MSC_START_BIT_READ_REG ); // execute DevCap reg read command RegValue = SiiRegRead( REG_CBUS_PRI_RD_DATA_1ST ); TX_DEBUG_PRINT(("[MHL]: Device Category register=0x%02X...\n", (int)RegValue)); if( MHL_DEV_CAT_DONGLE == (RegValue & 0x0F) ) { TX_DEBUG_PRINT(("[MHL]: DevTypeValue=0x%02X, the peer is a dongle, please limit the VBUS current input from dongle to be 100mA...\n", (int)RegValue)); } else if( MHL_DEV_CAT_SINK == (RegValue & 0x0F) ) { TX_DEBUG_PRINT(("[MHL]: DevTypeValue=0x%02X, the peer is a sink, limit the VBUS current input from sink to be 500mA...\n", (int)RegValue)); } } }
static void ProcessScdtStatusChange(void) { uint8_t scdtStatus; uint8_t mhlFifoStatus; scdtStatus = SiiRegRead(REG_TMDS_CSTAT); TX_DEBUG_PRINT(("Drv: ProcessScdtStatusChange scdtStatus: 0x%02x\n", scdtStatus)); if (scdtStatus & 0x02) { mhlFifoStatus = SiiRegRead(REG_INTR5); TX_DEBUG_PRINT(("MHL FIFO status: 0x%02x\n", mhlFifoStatus)); if (mhlFifoStatus & 0x0C) { SiiRegWrite(REG_INTR5, 0x0C); TX_DEBUG_PRINT(("** Apply MHL FIFO Reset\n")); SiiRegWrite(REG_SRST, 0x94); SiiRegWrite(REG_SRST, 0x84); } } }
/////////////////////////////////////////////////////////////////////////// // // MhlTxDrvProcessDisconnection // /////////////////////////////////////////////////////////////////////////// static void MhlTxDrvProcessDisconnection (void) { TX_DEBUG_PRINT(("Drv: MhlTxDrvProcessDisconnection\n")); // clear all interrupts SiiRegWrite(REG_INTR4, SiiRegRead(REG_INTR4)); SiiRegWrite(REG_MHLTX_CTL1, 0xD0); dsHpdStatus &= ~BIT6; //cable disconnect implies downstream HPD low SiiRegWrite(REG_PRI_XFR_ABORT_REASON, dsHpdStatus); SiiMhlTxNotifyDsHpdChange(0); if( POWER_STATE_D0_MHL == fwPowerState ) { // Notify upper layer of cable removal SiiMhlTxNotifyConnection(false); } // Now put chip in sleep mode SwitchToD3(); }
static void SetAudioMode(inAudioTypes_t audiomode) { if (audiomode >= AUD_TYP_NUM) audiomode = I2S_48; SiiRegWrite(REG_AUDP_TXCTRL, audioData[audiomode].regAUD_path); SiiRegWrite(TX_PAGE_L1 | 0x14, audioData[audiomode].regAUD_mode); SiiRegWrite(TX_PAGE_L1 | 0x1D, audioData[audiomode].regAUD_ctrl); SiiRegWrite(TX_PAGE_L1 | 0x21, audioData[audiomode].regAUD_freq); SiiRegWrite(TX_PAGE_L1 | 0x23, audioData[audiomode].regAUD_src); SiiRegWrite(TX_PAGE_L1 | 0x28, audioData[audiomode].regAUD_tdm_ctrl); // SiiRegWrite(TX_PAGE_L1 | 0x22, 0x0B); //0x02 for word length=16bits SiiRegWrite(TX_PAGE_L1 | 0x22, 0x02); SiiRegWrite(TX_PAGE_L1 | 0x24,0x02); SiiRegWrite(TX_PAGE_L1 | 0x15, 0x00); //0x7A:0x24 = 0x0B for word lenth is defult 24bit TX_DEBUG_PRINT(("SiiRegRead(TX_PAGE_L1 | 0x21)=0x%x\n",SiiRegRead(TX_PAGE_L1 | 0x21))); TX_DEBUG_PRINT(("SiiRegRead(TX_PAGE_L1 | 0x1D)=0x%x\n",SiiRegRead(TX_PAGE_L1 | 0x1D))); }
static void SendAudioInfoFrame (void) { SiiRegModify(TX_PAGE_L1 | 0x3E, BIT4|BIT5, CLEAR_BITS); SiiRegWrite(TX_PAGE_L1 | 0x80, 0x84); SiiRegWrite(TX_PAGE_L1 | 0x81, 0x01); SiiRegWrite(TX_PAGE_L1 | 0x82, 0x0A); SiiRegWrite(TX_PAGE_L1 | 0x83, 0x70); SiiRegWrite(TX_PAGE_L1 | 0x84, 0x01); SiiRegWrite(TX_PAGE_L1 | 0x8D, 0x00); SiiRegModify(TX_PAGE_L1 | 0x3E, BIT4|BIT5, SET_BITS); }
static int Int2Isr( void ) { if(SiiRegRead(REG_INTR2) & INTR_2_DESIRED_MASK) { SiiRegWrite(REG_INTR2, INTR_2_DESIRED_MASK); if(SiiRegRead(REG_SYS_STAT) & BIT1) { TX_DEBUG_PRINT(("PCLK is STABLE\n")); if (tmdsPowRdy) { SendAudioInfoFrame(); SendAviInfoframe(); } } } return 0; }