/** * @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 ); }
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); } }
/////////////////////////////////////////////////////////////////////////// // // 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 SiiMhlTxDrvTmdsControl (bool_t enable) { if (enable) { tmdsPowRdy = true; SiiRegModify(REG_AUDP_TXCTRL, BIT0, SET_BITS); if (1)//(SiiVideoInputIsValid()) { SiiRegModify(REG_TMDS_CCTRL, TMDS_OE, SET_BITS); SendAudioInfoFrame(); SendAviInfoframe(); TX_DEBUG_PRINT(("TMDS Output Enabled\n")); } else { TX_DEBUG_PRINT(("TMDS Output not Enabled due to invalid input\n")); } } else { SiiRegModify(REG_TMDS_CCTRL, TMDS_OE, CLEAR_BITS); SiiRegModify(REG_AUDP_TXCTRL, BIT0, CLEAR_BITS); tmdsPowRdy = false; TX_DEBUG_PRINT(("TMDS Ouput Disabled\n")); } }
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); }
uint8_t siMhlTx_VideoAudioSet (void) { TX_DEBUG_PRINT(("[MHL]: >>siMhlTx_VideoAudioSet()\n")); SiiRegModify(TX_PAGE_L1 | 0xDF, BIT0, SET_BITS); SiiMhlTxDrvTmdsControl( false ); HalTimerWait(T_RES_CHANGE_DELAY); // allow control InfoFrames to pass through to the sink device. //siMhlTx_AudioSet(); AudioVideoIsr(true); //siMhlTx_Init(); SiiRegModify(TX_PAGE_L1 | 0xDF, BIT0, CLEAR_BITS); SiiMhlTxTmdsEnable(); return 0; }
void SiiMhlTxDrvPowBitChange (bool_t enable) { if (enable) { SiiRegModify(REG_DISC_CTRL8, BIT2, SET_BITS); TX_DEBUG_PRINT(("POW bit 0->1, set DISC_CTRL8[2] = 1\n")); } }
void HDCP_On (void) { HDCP_DEBUG_PRINT(("HDCP -> Started. TPI:2A = 05\n")); printk("HDCP -> Started. TPI:2A = 05\n"); #if 1 //( SiiRegModify(TPI_HDCP_CONTROL_DATA_REG , BIT_TPI_HDCP_CONTROL_DATA_DOUBLE_RI_CHECK_MASK | BIT_TPI_HDCP_CONTROL_DATA_COPP_PROTLEVEL_MASK , BIT_TPI_HDCP_CONTROL_DATA_DOUBLE_RI_CHECK_ENABLE | BIT_TPI_HDCP_CONTROL_DATA_COPP_PROTLEVEL_MAX ); #else //)( SiiRegModify(TPI_HDCP_CONTROL_DATA_REG , BIT_TPI_HDCP_CONTROL_DATA_COPP_PROTLEVEL_MASK , BIT_TPI_HDCP_CONTROL_DATA_COPP_PROTLEVEL_MAX ); #endif //) }
/** * @brief Enable or disable HPD for the selected port(s) * * @param[in] portIndex - 0-4: Switch port to control * - 0xFF: Apply to all ports. * @param[in] enableHDCP - true: to enable * - false: to disable * @param[in] mode - true: to tristate the HPD * - false: to clear hpd * * @return void * * @note: The 'portIndex' parameter value 0xFF should not be used unless * all ports are HDMI1.3/a (not MHL or CDC) * *****************************************************************************/ void SiiDrvSwitchDeviceHpdControl ( bool_t enableHPD, uint8_t mode) { uint8_t enableVal; if (mode) enableVal = enableHPD ? VAL_HP_PORT_MHL : CLEAR_BITS; else enableVal = enableHPD ? VAL_HP_PORT_ALL_HI : CLEAR_BITS; SiiRegModify( REG_HP_CTRL, VAL_HP_PORT0_MASK, enableVal ); }
/** * @brief Enable or disable HDCP access for the selected port(s) * * @param[in] portIndex - 0: Switch port to control. * - 0xFF: Apply to all ports. * @param[in] enableHDCP - true: to enable * - false: to disable * * @return void * * @note: The 'portIndex' parameter value 0xFF should not be used unless * all ports are HDMI1.3/a (not MHL or CDC) * *****************************************************************************/ void SiiDrvSwitchDeviceHdcpDdcControl ( bool_t enableHDCP ) { uint8_t enableVal, enableMask; enableVal = enableHDCP ? SET_BITS : CLEAR_BITS; // only one port in 5293, no need to check portIndex enableMask = RX_M__SYS_SWTCH__RX0_EN | RX_M__SYS_SWTCH__DDC0_EN | RX_M__SYS_SWTCH__DDC_DEL_EN; SiiRegModify( RX_A__SYS_SWTCH, enableMask, enableVal ); }
/////////////////////////////////////////////////////////////////////////// // InitCBusRegs // /////////////////////////////////////////////////////////////////////////// static void InitCBusRegs (void) { TX_DEBUG_PRINT(("Drv: InitCBusRegs\n")); SiiRegWrite(REG_CBUS_COMMON_CONFIG, 0xF2); // Increase DDC translation layer timer SiiRegWrite(REG_CBUS_LINK_CONTROL_7, 0x0B); // Drive High Time. -- changed from 0x03 on 2011-11-21 -- changed from 0x0C on 2011-10-03 - 17:00 SiiRegWrite(REG_CBUS_LINK_CONTROL_8, 0x30); // Use programmed timing. SiiRegWrite(REG_CBUS_DRV_STRENGTH_0, 0x03); // CBUS Drive Strength #define DEVCAP_REG(x) (REG_CBUS_DEVICE_CAP_0 | DEVCAP_OFFSET_##x) // Setup our devcap SiiRegWrite(DEVCAP_REG(DEV_STATE ) ,DEVCAP_VAL_DEV_STATE ); SiiRegWrite(DEVCAP_REG(MHL_VERSION ) ,DEVCAP_VAL_MHL_VERSION ); SiiRegWrite(DEVCAP_REG(DEV_CAT ) ,DEVCAP_VAL_DEV_CAT ); SiiRegWrite(DEVCAP_REG(ADOPTER_ID_H ) ,DEVCAP_VAL_ADOPTER_ID_H ); SiiRegWrite(DEVCAP_REG(ADOPTER_ID_L ) ,DEVCAP_VAL_ADOPTER_ID_L ); SiiRegWrite(DEVCAP_REG(VID_LINK_MODE ) ,DEVCAP_VAL_VID_LINK_MODE ); SiiRegWrite(DEVCAP_REG(AUD_LINK_MODE ) ,DEVCAP_VAL_AUD_LINK_MODE ); SiiRegWrite(DEVCAP_REG(VIDEO_TYPE ) ,DEVCAP_VAL_VIDEO_TYPE ); SiiRegWrite(DEVCAP_REG(LOG_DEV_MAP ) ,DEVCAP_VAL_LOG_DEV_MAP ); SiiRegWrite(DEVCAP_REG(BANDWIDTH ) ,DEVCAP_VAL_BANDWIDTH ); SiiRegWrite(DEVCAP_REG(FEATURE_FLAG ) ,DEVCAP_VAL_FEATURE_FLAG ); SiiRegWrite(DEVCAP_REG(DEVICE_ID_H ) ,DEVCAP_VAL_DEVICE_ID_H ); SiiRegWrite(DEVCAP_REG(DEVICE_ID_L ) ,DEVCAP_VAL_DEVICE_ID_L ); SiiRegWrite(DEVCAP_REG(SCRATCHPAD_SIZE) ,DEVCAP_VAL_SCRATCHPAD_SIZE ); SiiRegWrite(DEVCAP_REG(INT_STAT_SIZE ) ,DEVCAP_VAL_INT_STAT_SIZE ); SiiRegWrite(DEVCAP_REG(RESERVED ) ,DEVCAP_VAL_RESERVED ); // Make bits 2,3 (initiator timeout) to 1,1 for register CBUS_LINK_CONTROL_2 SiiRegModify(REG_CBUS_LINK_CONTROL_2,BIT_CBUS_INITIATOR_TIMEOUT_MASK,BIT_CBUS_INITIATOR_TIMEOUT_MASK); // Clear legacy bit on Wolverine TX. and set timeout to 0xF SiiRegWrite(REG_MSC_TIMEOUT_LIMIT, 0x0F); // Set NMax to 1 SiiRegWrite(REG_CBUS_LINK_CONTROL_1, 0x01); SiiRegModify(REG_CBUS_MSC_COMPATIBILITY_CTRL, BIT_CBUS_CEC_DISABLE,BIT_CBUS_CEC_DISABLE); // disallow vendor specific commands }
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); }
static void WriteInitialRegisterValues ( void ) { TX_DEBUG_PRINT(("WriteInitialRegisterValues\n")); SiiRegWrite(REG_POWER_EN, 0x3F); SiiRegWrite(REG_MHLTX_CTL6, 0xBC); SiiRegWrite(REG_MHLTX_CTL2, 0x3C); SiiRegWrite(REG_MHLTX_CTL4, 0xC8); SiiRegWrite(REG_MHLTX_CTL7, 0x03); SiiRegWrite(REG_MHLTX_CTL8, 0x0A); SiiRegWrite(REG_TMDS_CCTRL, 0x08); SiiRegWrite(REG_USB_CHARGE_PUMP_MHL, 0x03); SiiRegWrite(REG_USB_CHARGE_PUMP, 0x8C); SiiRegWrite(REG_SYS_CTRL1, 0x35); SiiRegWrite(REG_DISC_CTRL5, 0x57); SiiRegWrite(REG_DISC_CTRL9, 0x24); SiiRegWrite(REG_DISC_CTRL1, 0x27); SiiRegWrite(REG_DISC_CTRL3, 0x86); CbusReset(); InitCBusRegs(); SiiRegModify(REG_LM_DDC, VID_MUTE, SET_BITS); SiiRegModify(REG_AUDP_TXCTRL, BIT2, SET_BITS); }
static void SendAviInfoframe (void) { uint8_t ifData[SIZE_AVI_INFOFRAME]; extern uint8_t VIDEO_CAPABILITY_D_BLOCK_found; ifData[0] = 0x82; ifData[1] = 0x02; ifData[2] = 0x0D; ifData[3] = 0x00; ifData[4] = video_data.outputColorSpace << 5; ifData[5] = video_data.outputcolorimetryAspectRatio; if(VIDEO_CAPABILITY_D_BLOCK_found){ ifData[6] = 0x04; TX_DEBUG_PRINT(("VIDEO_CAPABILITY_D_BLOCK_found = true, limited range\n")); } else{ ifData[6] = 0x00; TX_DEBUG_PRINT(("VIDEO_CAPABILITY_D_BLOCK_found= false. defult range\n")); } //ifData[4] = video_data.outputColorSpace << 5; ifData[7] = video_data.inputVideoCode; TX_DEBUG_PRINT(("video_data.inputVideoCode:0x%02x, video_data.outputVideoCode=0x%x\n",(int)video_data.inputVideoCode,video_data.outputVideoCode)); //ifData[7] = video_data.outputVideoCode; ifData[8] = 0x00; ifData[9] = 0x00; ifData[10] = 0x00; ifData[11] = 0x00; ifData[12] = 0x00; ifData[13] = 0x00; ifData[14] = 0x00; ifData[15] = 0x00; ifData[16] = 0x00; ifData[3] = CalculateInfoFrameChecksum(ifData); SiiRegModify(TX_PAGE_L1 | 0x3E, BIT0|BIT1, CLEAR_BITS); SiiRegWriteBlock(TX_PAGE_L1 | 0x0040, ifData, SIZE_AVI_INFOFRAME); SiiRegModify(TX_PAGE_L1 | 0x3E, BIT0|BIT1, SET_BITS); }
void ProcessRgnd (void) { uint8_t rgndImpedance; rgndImpedance = SiiRegRead(REG_DISC_STAT2) & 0x03; TX_DEBUG_PRINT(("RGND = %02X : \n", (int)rgndImpedance)); if (0x02 == rgndImpedance) { TX_DEBUG_PRINT(("(MHL Device)\n")); SiiMhlTxNotifyRgndMhl(); } else { SiiRegModify(REG_DISC_CTRL9, BIT3, BIT3); TX_DEBUG_PRINT(("(Non-MHL Device)\n")); } }
/////////////////////////////////////////////////////////////////////////////// // // SiiMhlTxDrvPowBitChange // // Alert the driver that the peer's POW bit has changed so that it can take // action if necessary. // void SiiMhlTxDrvPowBitChange (bool_t enable) { // MHL peer device has it's own power if (enable) { SiiRegModify(REG_DISC_CTRL8, 0x04, 0x04); TX_DEBUG_PRINT(("Drv: POW bit 0->1, set DISC_CTRL8[2] = 1\n")); } #if (VBUS_POWER_CHK == ENABLE) if( vbusPowerState != enable) { vbusPowerState = enable; AppVbusControl( vbusPowerState ); } #endif }
/////////////////////////////////////////////////////////////////////////// // ProcessRgnd // // H/W has detected impedance change and interrupted. // We look for appropriate impedance range to call it MHL and enable the // hardware MHL discovery logic. If not, disable MHL discovery to allow // USB to work appropriately. // // In current chip a firmware driven slow wake up pulses are sent to the // sink to wake that and setup ourselves for full D0 operation. /////////////////////////////////////////////////////////////////////////// void ProcessRgnd (void) { uint8_t rgndImpedance; // // Impedance detection has completed - process interrupt // rgndImpedance = SiiRegRead(REG_DISC_STAT2) & 0x03; TX_DEBUG_PRINT(("Drv: RGND = %02X : \n", (int)rgndImpedance)); // // 00, 01 or 11 means USB. // 10 means 1K impedance (MHL) // // If 1K, then only proceed with wake up pulses if (0x02 == rgndImpedance) { TX_DEBUG_PRINT(("(MHL Device)\n")); SiiMhlTxNotifyRgndMhl(); // this will call the application and then optionally call //The sequence of events during MHL discovery is as follows: // (i) SiI9244 blocks on RGND interrupt (Page0:0x74[6]). // (ii) System firmware turns off its own VBUS if present. // (iii) System firmware waits for about 200ms (spec: TVBUS_CBUS_STABLE, 100 - 1000ms), then checks for the presence of // VBUS from the Sink. // (iv) If VBUS is present then system firmware proceed to drive wake pulses to the Sink as described in previous // section. // (v) If VBUS is absent the system firmware turns on its own VBUS, wait for an additional 200ms (spec: // TVBUS_OUT_TO_STABLE, 100 - 1000ms), and then proceed to drive wake pulses to the Sink as described in above. // AP need to check VBUS power present or absent in here // by oscar 20110527 #if (VBUS_POWER_CHK == ENABLE) // Turn on VBUS output. AppVbusControl( vbusPowerState = false ); #endif TX_DEBUG_PRINT(("[MHL]: Waiting T_SRC_VBUS_CBUS_TO_STABLE (%d ms)\n", (int)T_SRC_VBUS_CBUS_TO_STABLE)); //HalTimerWait(T_SRC_VBUS_CBUS_TO_STABLE); } else { SiiRegModify(REG_DISC_CTRL9, BIT3, BIT3); // USB Established TX_DEBUG_PRINT(("(Non-MHL Device)\n")); } }
//////////////////////////////////////////////////////////////////// // SwitchToD0 // This function performs s/w as well as h/w state transitions. // // Chip comes up in D2. Firmware must first bring it to full operation // mode in D0. //////////////////////////////////////////////////////////////////// void SwitchToD0 (void) { TX_DEBUG_PRINT(("Drv: Switch to D0\n")); // TX_DEBUG_PRINT(("[%d] Drv: Switch To Full power mode (D0)\n", // (int) (HalTimerElapsed( ELAPSED_TIMER ) * MONITORING_PERIOD)) ); // // WriteInitialRegisterValues switches the chip to full power mode. // WriteInitialRegisterValues(); // Force Power State to ON STROBE_POWER_ON // Force Power State to ON SiiRegModify(TPI_DEVICE_POWER_STATE_CTRL_REG, TX_POWER_STATE_MASK, 0x00); fwPowerState = POWER_STATE_D0_NO_MHL; }
static void AudioVideoIsr(bool_t force_update) { AVModeChange_t mode_change = {false, false}; //static AVMode_t mode = {VM_INVALID, AUD_INVALID}; if (force_update) { if (1)//(SiiVideoInputIsValid()) {TX_DEBUG_PRINT(("SiiVideoInputIsValid,audio_changed,video_changed\n")); mode_change.audio_change = true; mode_change.video_change = true; } } else { TX_DEBUG_PRINT(("force_update=false...............\n")); //AVModeDetect(&mode_change, &AVmode); } if (mode_change.audio_change) { TX_DEBUG_PRINT(("SetAudioMode & SetACRNValue\n")); //SetAudioMode(mode.audio_mode); SetAudioMode(AVmode.audio_mode); SetACRNValue(); } if(mode_change.video_change)// && SiiVideoInputIsValid()) { TX_DEBUG_PRINT(("mode_change.video_changed =true\n ")); SiiRegModify(REG_LM_DDC, VID_MUTE, SET_BITS); SiiRegModify(REG_SRST, BIT0, SET_BITS); //video_data.outputColorSpace = video_data.inputColorSpace; video_data.outputVideoCode = video_data.inputVideoCode; video_data.outputcolorimetryAspectRatio = video_data.inputcolorimetryAspectRatio; SiiRegModify(REG_SRST, BIT0, CLEAR_BITS); SiiRegModify(REG_LM_DDC, VID_MUTE, CLEAR_BITS); } if ((mode_change.video_change || mode_change.audio_change) && tmdsPowRdy) { if (1)//(SiiVideoInputIsValid()) { SiiRegModify(REG_TMDS_CCTRL, TMDS_OE, SET_BITS); SendAudioInfoFrame(); TX_DEBUG_PRINT(("((mode_change.video_change || mode_change.audio_change) && tmdsPowRdy) \n")); SendAviInfoframe(); } else { SiiRegModify(REG_TMDS_CCTRL, TMDS_OE, CLEAR_BITS); TX_DEBUG_PRINT (("TMDS Ouput Disabled due to invalid input\n")); } } }
void SiiDrvHdmiTxLiteHandleHdcpEvents (uint8_t HdcpIntStatus,uint8_t queryData) { uint8_t LinkStatus; uint8_t RegImage; uint8_t NewLinkProtectionLevel; #ifdef READKSV //( uint8_t RiCnt; #endif //) #ifdef KSVFORWARD //( uint8_t ksv; #endif //) static uint8_t renegPending=0; HDCP_DEBUG_PRINT(("HDCP: SiiDrvHdmiTxLiteHandleHdcpEvents HdcpIntStatus: 0x%02x\n",(int)HdcpIntStatus)); HDCP_DEBUG_PRINT(("SiiDrvHdmiTxLiteHandleHdcpEvents : REG_TPI_HW_6A = 0x%02x\n", SiiRegRead(REG_TPI_HW_6A))); HDCP_DEBUG_PRINT(("SiiDrvHdmiTxLiteHandleHdcpEvents : REG_TPI_HW_6B = 0x%02x\n", SiiRegRead(REG_TPI_HW_6B))); HDCP_DEBUG_PRINT(("SiiDrvHdmiTxLiteHandleHdcpEvents : REG_TPI_HW_6C = 0x%02x\n", SiiRegRead(REG_TPI_HW_6C))); HDCP_DEBUG_PRINT(("SiiDrvHdmiTxLiteHandleHdcpEvents : REG_TPI_HW_6D = 0x%02x\n", SiiRegRead(REG_TPI_HW_6D))); if (!renegPending) { // Check if Link Status has changed: if (BIT_TPI_INTR_ST0_HDCP_SECURITY_CHANGE_EVENT & HdcpIntStatus ) { #ifdef ENABLE_HDCP_DEBUG_PRINT //( PLACE_IN_CODE_SEG char szFormatString[]="HDCP (%2X) -> Link = (%2X) %s"; #endif //) HDCP_DEBUG_PRINT(("HDCP: \n")); LinkStatus = queryData; LinkStatus &= LINK_STATUS_MASK; // SiiRegWrite(TPI_INTERRUPT_STATUS_REG, HDCP_SECURITY_CHANGE_EVENT_MASK); switch (LinkStatus) { case LINK_STATUS_NORMAL: HDCP_DEBUG_PRINT((szFormatString, (int) HdcpIntStatus, (int) LinkStatus,"Normal\n")); break; case LINK_STATUS_LINK_LOST: HDCP_DEBUG_PRINT((szFormatString, (int) HdcpIntStatus, (int) LinkStatus,"Lost\n")); // AV Unmute if DVI and no HDCP in 29 and Link Lost if( (0 == SiiMhlTxOutputModeIsHDMI()) && (0 == (queryData& 0x08) ) ) { ERROR_DEBUG_PRINT(("Unmute AV coz it is DVI and no HDCP is supported\n")); SiiMhlTxNotifyAuthentication(); // Do nothing, send out video return; } HDCP_Restart(); // we've just reset the HDCP engine, wait until next interrupt to do more processing. return; break; case LINK_STATUS_RENEGOTIATION_REQ: HDCP_DEBUG_PRINT((szFormatString, (int) HdcpIntStatus, (int) LinkStatus,"Renegotiation Required\n")); #if 1 //( // old code set the AV_MUTE bit, // then cleared 2A // then re-enabled encryption SiiMhlTxDrvVideoMute(); SiiDrvHdmiTxLiteDisableEncryption(); #define WAIT_FOR_BKSV_DONE_ON_RENEG #ifdef WAIT_FOR_BKSV_DONE_ON_RENEG //( renegPending = 1; #else //)( HDCP_On(); #endif //) #else //)( HDCP_Restart(); #endif //) // we've just reset the HDCP engine, wait until next interrupt to do more processing. return; break; case LINK_STATUS_LINK_SUSPENDED: HDCP_DEBUG_PRINT((szFormatString, (int) HdcpIntStatus, (int) LinkStatus,"Suspended\n")); #ifdef KENO_DONGLE_DOWNSTREAM1 if ((!packedPixelStatus) && (g_pad_tv_mode == MHL_TV_MODE) && (!MHL_Resume)) { // SiiRegModify(0x01C7,0x20, 0x20);//display black image // SiiRegWrite(REG_VID_MODE, 0x12); // KH, Enable Demuxing data printk("[LINK_STATUS_LINK_SUSPENDED], Enable Demuxing data\n"); //HalTimerWait(100); msleep(1500); SiiRegWrite(REG_VID_MODE, 0x00); // KH, Disable Demuxing data SiiRegModify(0x01C7,0x20, 0x00);//recovery from black image printk("[LINK_STATUS_LINK_SUSPENDED], Disable Demuxing data\n"); } #endif HDCP_On(); //MHL_CTS 20120916+++ //keno20120903 // workaround for try to re-enable AVI Inforframe msleep(100); SiiRegWrite(REG_PKT_FILTER_0, 0xA1); //MHL_CTS 20120916--- break; } } // Check if HDCP state has changed: if (BIT_TPI_INTR_ST0_HDCP_AUTH_STATUS_CHANGE_EVENT & HdcpIntStatus) { RegImage = queryData; HDCP_DEBUG_PRINT(("HDCP: QueryData (TPI:29) = %02X\n", (int)RegImage)); NewLinkProtectionLevel = RegImage & (EXTENDED_LINK_PROTECTION_MASK | LOCAL_LINK_PROTECTION_MASK); { #ifdef ENABLE_HDCP_DEBUG_PRINT //( PLACE_IN_CODE_SEG char szFormatString[]="HDCP (%2X) -> Protection = (%2X) %s"; #endif //) HDCP_DEBUG_PRINT(("HDCP: New prot level = %02X\n", (int)NewLinkProtectionLevel)); switch (NewLinkProtectionLevel) { case (EXTENDED_LINK_PROTECTION_NONE | LOCAL_LINK_PROTECTION_NONE): HDCP_DEBUG_PRINT((szFormatString, (int) HdcpIntStatus, (int) NewLinkProtectionLevel,"None\n")); HDCP_Restart(); return; case LOCAL_LINK_PROTECTION_SECURE: HDCP_DEBUG_PRINT((szFormatString, (int) HdcpIntStatus, (int) NewLinkProtectionLevel,"Local, Unmuting\n")); printk("SiiDrvHdmiTxLiteHandleHdcpEvents : Local, Unmuting\n"); SiiMhlTxNotifyAuthentication(); //MHL_CTS 20120916+++ //keno20120903 // workaround for try to re-enable AVI Inforframe /// SiiRegWrite(REG_PKT_FILTER_0, 0xA1); //MHL_CTS 20120916--- #ifdef DEBUG_RI_VALUES //( g_ri_display = true; #endif //) break; case (EXTENDED_LINK_PROTECTION_SECURE | LOCAL_LINK_PROTECTION_SECURE): HDCP_DEBUG_PRINT((szFormatString, (int) HdcpIntStatus, (int) NewLinkProtectionLevel,"Extended\n")); if (IsRepeater(queryData)) { #ifdef READKSV //( RiCnt = ReadIndexedRegister(INDEXED_PAGE_0, 0x25); while (RiCnt > 0x70) // Frame 112 { RiCnt = ReadIndexedRegister(INDEXED_PAGE_0, 0x25); } SiI_RegisterReadModifyWrite(TPI_SYSTEM_CONTROL_DATA_REG , DDC_BUS_REQUEST_MASK | DDC_BUS_GRANT_MASK , DDC_BUS_REQUEST_REQUESTED | DDC_BUS_GRANT_GRANTED ); GetKSV(); RiCnt = SiiRegRead(TPI_SYSTEM_CONTROL_DATA_REG); #endif //) SiiMhlTxNotifyAuthentication(); } break; default: HDCP_DEBUG_PRINT((szFormatString, (int) HdcpIntStatus, (int) NewLinkProtectionLevel,"Extended but not Local?\n")); HDCP_Restart(); return; } } #ifdef KSVFORWARD //( // Check if KSV FIFO is ready and forward - Bug# 17892 // If interrupt never goes off: // a- KSV formwarding is not enabled // b- not a repeater // c- a repeater with device count == 0 // and therefore no KSV list to forward if ((SiI_RegisterRead(TPI_KSV_FIFO_READY_INT) & KSV_FIFO_READY_MASK) == KSV_FIFO_READY_YES) { ReadModifyWriteTPI(TPI_KSV_FIFO_READY_INT, KSV_FIFO_READY_MASK, KSV_FIFO_READY_YES); HDCP_DEBUG_PRINT(("KSV Fwd: KSV FIFO has data...\n")); { // While !(last byte has been read from KSV FIFO) // if (count = 0) then a byte is not in the KSV FIFO yet, do not read // else read a byte from the KSV FIFO and forward it or keep it for revocation check do { ksv = SiiRegRead(TPI_KSV_FIFO_STATUS_REG); if (ksv & KSV_FIFO_COUNT_MASK) { TPI_DEBUG_PRINT((TPI_DEBUG_CHANNEL,"KSV Fwd: KSV FIFO Count = %d, ", (int)(ksv & KSV_FIFO_COUNT_MASK))); ksv = SiI_RegisterRead(TPI_KSV_FIFO_VALUE_REG); // Forward or store for revocation check HDCP_DEBUG_PRINT(("Value = %d\n", (int)ksv)); } } while ((ksv & KSV_FIFO_LAST_MASK) == KSV_FIFO_LAST_NO); HDCP_DEBUG_PRINT(("KSV Fwd: Last KSV FIFO forward complete\n")); } } #endif //) // SiiRegWrite(TPI_INTERRUPT_STATUS_REG, HDCP_AUTH_STATUS_CHANGE_EVENT_MASK); } } if ( BIT_TPI_INTR_ST0_BKSV_DONE & HdcpIntStatus) { HDCP_DEBUG_PRINT(("HDCP: BKSV read done\n")); HDCP_DEBUG_PRINT(("HDCP: QueryData: 0x%02x 2A==%02bx\n" ,(int)queryData ,SiiRegRead(TPI_HDCP_CONTROL_DATA_REG) )); #ifdef KENO_DONGLE_DOWNSTREAM1 //Set black display twice to cover BULE display issue. if ((!packedPixelStatus) && (g_pad_tv_mode == MHL_TV_MODE) && (!MHL_Resume)) SiiRegModify(0x01C7,0x20, 0x20);//black image #endif if (queryData & PROTECTION_TYPE_MASK) // Is HDCP available { HDCP_DEBUG_PRINT(("HDCP: \n")); renegPending = 0; #ifdef KENO_DONGLE_DOWNSTREAM1 if ((!packedPixelStatus) && (g_pad_tv_mode == MHL_TV_MODE) && (!MHL_Resume)) { // SiiRegModify(0x01C7,0x20, 0x20);//display black image // SiiRegWrite(REG_VID_MODE, 0x12); // KH, Enable Demuxing data printk("[PROTECTION_TYPE_MASK], Enable Demuxing data\n"); //HalTimerWait(100); msleep(1500); SiiRegWrite(REG_VID_MODE, 0x00); // KH, Disable Demuxing data SiiRegModify(0x01C7,0x20, 0x00);//recovery from black image printk("[PROTECTION_TYPE_MASK], Disable Demuxing data\n"); } #endif HDCP_On(); //MHL_CTS 20120916+++ //keno20120903 // workaround for try to re-enable AVI Inforframe msleep(100); SiiRegWrite(REG_PKT_FILTER_0, 0xA1); //MHL_CTS 20120916--- } } if ( BIT_TPI_INTR_ST0_BKSV_ERR & HdcpIntStatus) { HDCP_DEBUG_PRINT(("HDCP: BKSV error - be sure that your sink supports HDCP - restarting\n")); //ASUS_BSP +++ : for non-support HDCP TV issue, re-start HDCP HDCP_Restart(); //ASUS_BSP --- return; } }
/** * @brief Enable or disable RX termination for the selected port(s) * * @param[in] portIndex - 0-1: Switch port to control * - 0xFF: Apply to all ports. * @param[in] enableVal The bit pattern to be used to enable * or disable termination * 0x00 - Enable for HDMI mode * 0x55 - Enable for MHL mode * 0xFF - Disable * * @return void * * @note: The 'enableVal' parameter for this function is NOT boolean as * it is for the companion si_DeviceXXXcontrol functions. * The 'portIndex' parameter value 0xFF should not be used unless * all ports are HDMI1.3/a (not MHL or CDC) * *****************************************************************************/ void SiiDrvSwitchDeviceRXTermControl ( uint8_t enableVal ) { SiiRegModify( REG_RX_CTRL5, MSK_TERM, enableVal ); }
/////////////////////////////////////////////////////////////////////////////// // // SiiMhlTxDrvAcquireUpstreamHPDControlDriveLow // // Acquire the direct control of Upstream HPD. // void SiiMhlTxDrvAcquireUpstreamHPDControlDriveLow (void) { // set reg_hpd_out_ovr_en to first control the hpd and clear reg_hpd_out_ovr_val SiiRegModify(REG_INT_CTRL, BIT5 | BIT4, BIT4); // Force upstream HPD to 0 when not in MHL mode. TX_DEBUG_PRINT(("Drv: Upstream HPD Acquired - driven low.\n")); }
/////////////////////////////////////////////////////////////////////////// // WriteInitialRegisterValues // // /////////////////////////////////////////////////////////////////////////// static void WriteInitialRegisterValues (void) { //TX_DEBUG_PRINT(("Drv: WriteInitialRegisterValues\n")); // Power Up SiiRegWrite(REG_DPD, 0x3F); // Power up CVCC 1.2V core SiiRegWrite(REG_TMDS_CLK_EN, 0x01); // Enable TxPLL Clock SiiRegWrite(REG_TMDS_CH_EN, 0x11); // Enable Tx Clock Path & Equalizer SiiRegWrite(REG_MHLTX_CTL1, 0x10); // TX Source termination ON SiiRegWrite(REG_MHLTX_CTL6, 0xBC); // Enable 1X MHL clock output SiiRegWrite(REG_MHLTX_CTL2, 0x3C); // TX Differential Driver Config SiiRegWrite(REG_MHLTX_CTL4, 0xC8); SiiRegWrite(REG_MHLTX_CTL7, 0x03); // 2011-10-10 SiiRegWrite(REG_MHLTX_CTL8, 0x0A); // PLL bias current, PLL BW Control // Analog PLL Control SiiRegWrite(REG_TMDS_CCTRL, 0x08); // Enable Rx PLL clock 2011-10-10 - select BGR circuit for voltage references SiiRegWrite(REG_USB_CHARGE_PUMP, 0x8C); // 2011-10-10 USB charge pump clock SiiRegWrite(REG_TMDS_CTRL4, 0x02); SiiRegWrite(REG_TMDS0_CCTRL2, 0x00); SiiRegModify(REG_DVI_CTRL3, BIT5, 0); // 2011-10-10 SiiRegWrite(REG_TMDS_TERMCTRL1, 0x60); SiiRegWrite(REG_PLL_CALREFSEL, 0x03); // PLL Calrefsel SiiRegWrite(REG_PLL_VCOCAL, 0x20); // VCO Cal SiiRegWrite(REG_EQ_DATA0, 0xE0); // Auto EQ SiiRegWrite(REG_EQ_DATA1, 0xC0); // Auto EQ SiiRegWrite(REG_EQ_DATA2, 0xA0); // Auto EQ SiiRegWrite(REG_EQ_DATA3, 0x80); // Auto EQ SiiRegWrite(REG_EQ_DATA4, 0x60); // Auto EQ SiiRegWrite(REG_EQ_DATA5, 0x40); // Auto EQ SiiRegWrite(REG_EQ_DATA6, 0x20); // Auto EQ SiiRegWrite(REG_EQ_DATA7, 0x00); // Auto EQ SiiRegWrite(REG_BW_I2C, 0x0A); // Rx PLL BW ~ 4MHz SiiRegWrite(REG_EQ_PLL_CTRL1, 0x06); // Rx PLL BW value from I2C SiiRegWrite(REG_MON_USE_COMP_EN, 0x06); // synchronous s/w reset SiiRegWrite(REG_ZONE_CTRL_SW_RST, 0x60); // Manual zone control SiiRegWrite(REG_ZONE_CTRL_SW_RST, 0xE0); // Manual zone control SiiRegWrite(REG_MODE_CONTROL, 0x00); // PLL Mode Value SiiRegWrite(REG_SYS_CTRL1, 0x35); // bring out from power down (script moved this here from above) SiiRegWrite(REG_DISC_CTRL2, 0xAD); SiiRegWrite(REG_DISC_CTRL5, 0x57); // 1.8V CBUS VTH 5K pullup for MHL state SiiRegWrite(REG_DISC_CTRL6, 0x11); // RGND & single discovery attempt (RGND blocking) SiiRegWrite(REG_DISC_CTRL8, 0x82); // Ignore VBUS SiiRegWrite(REG_DISC_CTRL9, 0x24); // No OTG, Discovery pulse proceed, Wake pulse not bypassed SiiRegWrite(REG_DISC_CTRL4, 0x8C); // Pull-up resistance off for IDLE state. SiiRegWrite(REG_DISC_CTRL1, 0x27); // Enable CBUS discovery SiiRegWrite(REG_DISC_CTRL7, 0x20); // use 1K only setting SiiRegWrite(REG_DISC_CTRL3, 0x86); // MHL CBUS discovery CLR_BIT(REG_INT_CTRL, 6);//change hpd out pin from defult open-drain to push-pull by garyyuan if (fwPowerState != TX_POWER_STATE_D3) { // Don't force HPD to 0 during wake-up from D3 SiiRegModify(REG_INT_CTRL, BIT5 | BIT4, BIT4); // Force HPD to 0 when not in MHL mode. } SiiRegWrite(REG_SRST, 0x84); // Enable Auto soft reset on SCDT = 0 SiiRegWrite(REG_DCTL, 0x1C); // HDMI Transcode mode enable CbusReset(); InitCBusRegs(); }
void SiiMhlTxDrvProcessRgndMhl( void ) { SiiRegModify(REG_DISC_CTRL9, BIT0, BIT0); }
static void ReleaseUsbIdSwitchOpen ( void ) { HalTimerWait(50); SiiRegModify(REG_DISC_CTRL6, BIT6, 0x00); ENABLE_DISCOVERY; }
static void ForceUsbIdSwitchOpen ( void ) { DISABLE_DISCOVERY; SiiRegModify(REG_DISC_CTRL6, BIT6, BIT6); SiiRegWrite(REG_DISC_CTRL3, 0x86); }