////////////////////////////////////////////////////////////////////////////// // // FUNCTION : SiiDrvHdmiTxLiteIsAksvValid() // // PURPOSE : Check if AKSVs contain 20 '0' and 20 '1' // // INPUT PARAMS : None // // OUTPUT PARAMS : None // // GLOBALS USED : TBD // // RETURNS : true if 20 zeros and 20 ones found in AKSV. false OTHERWISE // ////////////////////////////////////////////////////////////////////////////// bool_t SiiDrvHdmiTxLiteIsAksvValid (void) { uint8_t B_Data[AKSV_SIZE]; uint8_t NumOfOnes = 0; uint8_t i; SiiRegReadBlock(TPI_AKSV_1_REG, B_Data, AKSV_SIZE); for (i=0; i < AKSV_SIZE; i++) { while (B_Data[i] != 0x00) { if (B_Data[i] & 0x01) { NumOfOnes++; } B_Data[i] >>= 1; } } if (NumOfOnes != NUM_OF_ONES_IN_KSV) { HDCP_DEBUG_PRINT(("HDCP -> Illegal AKSV\n")); printk("HDCP -> Illegal AKSV\n"); return false; } return true; }
static void MhlCbusIsr( void ) { uint8_t cbusInt; uint8_t gotData[4]; uint8_t i; cbusInt = SiiRegRead(REG_CBUS_MSC_INT2_STATUS); if(cbusInt == 0xFF) { return; } if( cbusInt ) { if ( BIT0 & cbusInt) { SiiMhlTxMscWriteBurstDone( cbusInt ); } if(cbusInt & BIT2) { uint8_t intr[4]={0}; TX_DEBUG_PRINT(("MHL INTR Received\n")); SiiRegReadBlock(REG_CBUS_SET_INT_0, intr, 4); SiiMhlTxGotMhlIntr( intr[0], intr[1] ); SiiRegWriteBlock(REG_CBUS_SET_INT_0, intr, 4); } if(cbusInt & BIT3) { uint8_t status[4]={0}; TX_DEBUG_PRINT(("MHL STATUS Received\n")); for (i = 0; i < 4;++i) { status[i] = SiiRegRead(REG_CBUS_WRITE_STAT_0 + i); SiiRegWrite((REG_CBUS_WRITE_STAT_0 + i), 0xFF ); } SiiMhlTxGotMhlStatus( status[0], status[1] ); } SiiRegWrite(REG_CBUS_MSC_INT2_STATUS, cbusInt); TX_DEBUG_PRINT(("Drv: Clear CBUS INTR_2: %02X\n", (int) cbusInt)); } cbusInt = SiiRegRead(REG_CBUS_INTR_STATUS); if (cbusInt) { SiiRegWrite(REG_CBUS_INTR_STATUS, cbusInt); TX_DEBUG_PRINT(("Drv: Clear CBUS INTR_1: %02X\n", (int) cbusInt)); } if((cbusInt & BIT3)) { uint8_t mscMsg[2]; TX_DEBUG_PRINT(("MSC_MSG Received\n")); mscMsg[0] = SiiRegRead(REG_CBUS_PRI_VS_CMD); mscMsg[1] = SiiRegRead(REG_CBUS_PRI_VS_DATA); TX_DEBUG_PRINT(("MSC MSG: %02X %02X\n", (int)mscMsg[0], (int)mscMsg[1] )); SiiMhlTxGotMhlMscMsg( mscMsg[0], mscMsg[1] ); } if (cbusInt & (BIT_MSC_ABORT | BIT_MSC_XFR_ABORT | BIT_DDC_ABORT)) { gotData[0] = CBusProcessErrors(cbusInt); mscCmdInProgress = false; } if(cbusInt & BIT4) { TX_DEBUG_PRINT(("MSC_REQ_DONE\n")); mscCmdInProgress = false; SiiMhlTxMscCommandDone( SiiRegRead(REG_CBUS_PRI_RD_DATA_1ST) ); } if (cbusInt & BIT7) { TX_DEBUG_PRINT(("Parity error count reaches 15\n")); SiiRegWrite(REG_CBUS_STAT2, 0x00); } }
/////////////////////////////////////////////////////////////////////////// // // MhlCbusIsr // // Only when MHL connection has been established. This is where we have the // first looks on the CBUS incoming commands or returned data bytes for the // previous outgoing command. // // It simply stores the event and allows application to pick up the event // and respond at leisure. // // Look for interrupts on CBUS:CBUS_INTR_STATUS [0xC8:0x08] // 7 = RSVD (reserved) // 6 = MSC_RESP_ABORT (interested) // 5 = MSC_REQ_ABORT (interested) // 4 = MSC_REQ_DONE (interested) // 3 = MSC_MSG_RCVD (interested) // 2 = DDC_ABORT (interested) // 1 = RSVD (reserved) // 0 = rsvd (reserved) /////////////////////////////////////////////////////////////////////////// static void MhlCbusIsr (void) { uint8_t cbusInt; uint8_t gotData[4]; // Max four status and int registers. // // Main CBUS interrupts on CBUS_INTR_STATUS // cbusInt = SiiRegRead(REG_CBUS_INTR_STATUS); // When I2C is inoperational (D3) and a previous interrupt brought us here, do nothing. if(cbusInt == 0xFF) { return; } if( cbusInt ) { // // Clear all interrupts that were raised even if we did not process // SiiRegWrite(REG_CBUS_INTR_STATUS, cbusInt); TX_DEBUG_PRINT(("Drv: Clear CBUS INTR_1: %02X\n", (int) cbusInt)); } // MSC_MSG (RCP/RAP) if ((cbusInt & BIT_CBUS_MSC_MR_MSC_MSG)) { uint8_t mscMsg[2]; TX_DEBUG_PRINT(("Drv: MSC_MSG Received\n")); // // Two bytes arrive at registers 0x18 and 0x19 // mscMsg[0] = SiiRegRead(REG_CBUS_PRI_VS_CMD); mscMsg[1] = SiiRegRead(REG_CBUS_PRI_VS_DATA); TX_DEBUG_PRINT(("Drv: MSC MSG: %02X %02X\n", (int)mscMsg[0], (int)mscMsg[1] )); SiiMhlTxGotMhlMscMsg( mscMsg[0], mscMsg[1] ); } if (cbusInt & (BIT_MSC_ABORT | BIT_MSC_XFR_ABORT | BIT_DDC_ABORT)) { gotData[0] = CBusProcessErrors(cbusInt); mscCmdInProgress = false; } // MSC_REQ_DONE received. if (cbusInt & BIT_CBUS_MSC_MT_DONE) { TX_DEBUG_PRINT(("Drv: MSC_REQ_DONE\n")); mscCmdInProgress = false; // only do this after cBusInt interrupts are cleared above SiiMhlTxMscCommandDone( SiiRegRead(REG_CBUS_PRI_RD_DATA_1ST) ); } // // Clear all interrupts that were raised even if we did not process // // // Now look for interrupts on register 0x1E. CBUS_MSC_INT2 // 7:4 = Reserved // 3 = msc_mr_write_state = We got a WRITE_STAT // 2 = msc_mr_set_int. We got a SET_INT // 1 = reserved // 0 = msc_mr_write_burst. We received WRITE_BURST // cbusInt = SiiRegRead(REG_CBUS_MSC_INT2_STATUS); if(cbusInt) { // // Clear all interrupts that were raised even if we did not process // SiiRegWrite(REG_CBUS_MSC_INT2_STATUS, cbusInt); TX_DEBUG_PRINT(("Drv: Clear CBUS INTR_2: %02X\n", (int) cbusInt)); } if ( BIT_CBUS_MSC_MR_WRITE_BURST & cbusInt) { // WRITE_BURST complete SiiMhlTxMscWriteBurstDone( cbusInt ); } if(cbusInt & BIT_CBUS_MSC_MR_SET_INT) { uint8_t intr[4]; TX_DEBUG_PRINT(("Drv: MHL INTR Received\n")); SiiRegReadBlock(REG_CBUS_SET_INT_0, intr, 4); SiiRegWriteBlock(REG_CBUS_SET_INT_0, intr, 4); // We are interested only in first two bytes. SiiMhlTxGotMhlIntr( intr[0], intr[1] ); } if (cbusInt & BIT_CBUS_MSC_MR_WRITE_STATE) { uint8_t status[4]; uint8_t clear[4]={0xff,0xff,0xff,0xff};// must write 0xFF to clear regardless! // don't put debug output here, it just creates confusion. SiiRegReadBlock(REG_CBUS_WRITE_STAT_0, status, 4); SiiRegWriteBlock(REG_CBUS_WRITE_STAT_0, clear, 4); SiiMhlTxGotMhlStatus( status[0], status[1] ); } }
void SiiMhlTxDrvGetScratchPad (uint8_t startReg,uint8_t *pData,uint8_t length) { SiiRegReadBlock(REG_CBUS_SCRATCHPAD_0+startReg, pData, length); }
void SiiRxInterruptHandler(void) { uint8_t interrupts[NMB_OF_RX_INTERRUPTS]; //DEBUG_PRINT(MSG_STAT, ("RX Interrupt detected!\n")); // get interrupt requests SiiRegReadBlock(RX_A__INTR1, &interrupts[INT1], 4); SiiRegReadBlock(RX_A__INTR5, &interrupts[INT5], 2); SiiRegReadBlock(RX_A__INTR7, &interrupts[INT7], 2); // do not touch interrupts which are masked out interrupts[INT1] &= rx_isr.shadow_interrupt_mask[INT1]; interrupts[INT2] &= rx_isr.shadow_interrupt_mask[INT2]; interrupts[INT3] &= rx_isr.shadow_interrupt_mask[INT3]; interrupts[INT4] &= rx_isr.shadow_interrupt_mask[INT4]; interrupts[INT5] &= rx_isr.shadow_interrupt_mask[INT5]; interrupts[INT6] &= rx_isr.shadow_interrupt_mask[INT6]; interrupts[INT7] &= rx_isr.shadow_interrupt_mask[INT7]; interrupts[INT8] &= rx_isr.shadow_interrupt_mask[INT8]; // Cable plug-in / plug-out interrupts are handled elsewhere //interrupts[INT6] &= ~RX_M__INTR6__CABLE_UNPLUG; //interrupts[INT8] &= ~RX_M__INTR8__CABLE_IN; // clear interrupt requests SiiRegWriteBlock(RX_A__INTR1, &interrupts[INT1], 4); SiiRegWriteBlock(RX_A__INTR5, &interrupts[INT5], 2); SiiRegWriteBlock(RX_A__INTR7, &interrupts[INT7], 2); if(interrupts[INT1] & RX_M__INTR1__AUTH_DONE) { DEBUG_PRINT(MSG_STAT, ("RX: Authentication done!\n")); switch_hdcp_failure_check_with_v_sync_rate(OFF); } if(interrupts[INT2] & RX_M__INTR2__VID_CLK_CHANGED) { rx_isr.bVidStableChgEvent = true; DEBUG_PRINT(MSG_STAT, ("RX: video clock change\n")); } if(interrupts[INT2] & RX_M__INTR2__SCDT) { switch_hdcp_failure_check_with_v_sync_rate(OFF); SiiDrvRxMuteVideo(ON); rx_isr.bVidStableChgEvent = true; if(SiiDrvRxIsSyncDetected()) { // SCDT detection for vdin utility. printk("sii9293 irq got SCDT!\n"); rx_isr.bScdtState = true; #if defined(__KERNEL__) SiiConnectionStateNotify(true); #endif } else { // SCDT detection for vdin utility. printk("sii9293 irq lost SCDT!\n"); sii_signal_notify(0); rx_isr.bScdtState = false; SiiDrvSoftwareReset(RX_M__SRST__SRST); VMD_ResetTimingData(); DEBUG_PRINT(MSG_STAT, ("RX: IDLE!\n")); } } if(interrupts[INT2] & RX_M__INTR2__HDMI_MODE) { DEBUG_PRINT(MSG_STAT, ("RX: HDMI mode change!\n")); RxIsr_HdmiDviTransition(); } if(interrupts[INT2] & RX_M__INTR2__VSYNC) { hdcp_error_handler(true); } if(interrupts[INT4] & RX_M__INTR4__HDCP) { hdcp_error_handler(false); } if((interrupts[INT5] & RX_M__INTR5__AUDIO_FS_CHANGED) || (interrupts[INT6] & RX_M__INTR6__CHST_READY)) { // Note: RX_M__INTR6__CHST_READY interrupt may be disabled //DEBUG_PRINT(MSG_STAT, ("RX: New Audio Fs\n")); RxAudio_OnChannelStatusChange(); } if(interrupts[INT4] & RX_M__INTR4__NO_AVI) { RxInfo_NoAviHandler(); rx_isr.bVidStableChgEvent = true; } if(interrupts[INT3] & RX_M__INTR3__NEW_AVI_PACKET) { RxInfo_InterruptHandler(INFO_AVI); rx_isr.bVidStableChgEvent = true; } if(interrupts[INT7] & RX_M__INTR7__NO_VSI_PACKET) { // Clear also vsif_received flag (indicating any VSIF packet detection). // If there is any other VSIF packet, the flag will be set again shortly. RxInfo_NoVsiHandler(); } if(interrupts[INT7] & RX_M__INTR7__NEW_VSI_PACKET) { RxInfo_InterruptHandler(INFO_VSI); } if(interrupts[INT3] & RX_M__INTR3__NEW_AUD_PACKET) { RxInfo_InterruptHandler(INFO_AUD); } if(interrupts[INT6] & RX_M__INTR6__NEW_ACP_PACKET) { RxInfo_InterruptHandler(INFO_AUD); } if (interrupts[INT6] & RX_M__INTR6__CABLE_UNPLUG) { if (SiiRegRead(RX_A__INTR6) & RX_M__INTR6__CABLE_UNPLUG) { rx_isr.bCableChgEvent = true; rx_isr.bCableState = false; rx_isr.shadow_interrupt_mask[INT6] &= ~RX_M__INTR6__CABLE_UNPLUG; // Disable 5v plug-out interrup rx_isr.shadow_interrupt_mask[INT8] |= RX_M__INTR8__CABLE_IN; // Enable 5v plug-in interrupt SiiRegWrite(RX_A__INTR6_MASK, rx_isr.shadow_interrupt_mask[INT6]); SiiRegWrite(RX_A__INTR8_MASK, rx_isr.shadow_interrupt_mask[INT8]); sii9293_cable_status_notify(0); } } if (interrupts[INT8] & RX_M__INTR8__CABLE_IN) { if (SiiRegRead(RX_A__INTR8) & RX_M__INTR8__CABLE_IN) { rx_isr.bCableChgEvent = true; rx_isr.bCableState = true; rx_isr.shadow_interrupt_mask[INT6] |= RX_M__INTR6__CABLE_UNPLUG; // Enable 5v plug-out interrup rx_isr.shadow_interrupt_mask[INT8] &= ~RX_M__INTR8__CABLE_IN; // Disable 5v plug-in interrupt SiiRegWrite(RX_A__INTR6_MASK, rx_isr.shadow_interrupt_mask[INT6]); SiiRegWrite(RX_A__INTR8_MASK, rx_isr.shadow_interrupt_mask[INT8]); sii9293_cable_status_notify(1); } } }