/**
 *  @brief Reset the 5293 chip by toggle the reset pin at 5293
 *
 *  @param[in]      hwResetPeriod       The delay time during the low level.
 *  @param[in]      hwResetDelay        The delay time after reset hw.
 *
 *****************************************************************************/
void SiiHwReset(uint16_t hwResetPeriod,uint16_t hwResetDelay)
{
    // Toggle RX reset pin
    SiiGpioControl(GPIO_RST, false);
    HalTimerWait(hwResetPeriod);
    SiiGpioControl(GPIO_RST, true);

    // then wait per spec
    HalTimerWait(hwResetDelay);
}
void CbusReset (void)
{
    uint8_t idx;
	TX_DEBUG_PRINT( ("CBUS reset!!!\n"));
	SET_BIT(REG_SRST, 3);
	HalTimerWait(2);
	CLR_BIT(REG_SRST, 3);
	mscCmdInProgress = false;
    UNMASK_INTR_4_INTERRUPTS;
#if (SYSTEM_BOARD == SB_STARTER_KIT_X01)
    UNMASK_INTR_1_INTERRUPTS;
    UNMASK_INTR_2_INTERRUPTS;
    UNMASK_INTR_5_INTERRUPTS;
#else
    MASK_INTR_1_INTERRUPTS;
    MASK_INTR_5_INTERRUPTS;
#endif
    UNMASK_CBUS1_INTERRUPTS;
    UNMASK_CBUS2_INTERRUPTS;
	for(idx=0; idx < 4; idx++)
	{
		WriteByteCBUS((0xE0 + idx), 0xFF);
		WriteByteCBUS((0xF0 + idx), 0xFF);
	}
}
///////////////////////////////////////////////////////////////////////////
//
// CbusReset
//
///////////////////////////////////////////////////////////////////////////
void CbusReset (void)
{
uint8_t enable[4]={0xff,0xff,0xff,0xff};// must write 0xFF to clear regardless!
	SET_BIT(REG_SRST, 3);
	HalTimerWait(2);
	CLR_BIT(REG_SRST, 3);

	mscCmdInProgress = false;

	// Adjust interrupt mask everytime reset is performed.
    UNMASK_INTR_1_INTERRUPTS;
	UNMASK_INTR_4_INTERRUPTS;
    if (g_chipRevId < 1)
    {
    	if(fwPowerState != POWER_STATE_FIRST_INIT)
			UNMASK_INTR_5_INTERRUPTS;
	}
	else
	{
		//RG disabled due to auto FIFO reset
	    MASK_INTR_5_INTERRUPTS;
	}

	UNMASK_CBUS1_INTERRUPTS;
	UNMASK_CBUS2_INTERRUPTS;

		// Enable WRITE_STAT interrupt for writes to all 4 MSC Status registers.
    SiiRegWriteBlock(REG_CBUS_WRITE_STAT_ENABLE_0,enable,4);
		// Enable SET_INT interrupt for writes to all 4 MSC Interrupt registers.
    SiiRegWriteBlock(REG_CBUS_SET_INT_ENABLE_0,enable,4);
}
Beispiel #4
0
void main ( void )
{
    uint8_t         monitorState;
    static uint8_t  oldMute             = 0x00;
    BOOL            externalAccess;
    uint8_t         u8Data, rotarySwitch;

    externalAccess      = false;
    oldMute             = true;

    HalInitialize();
    HalTimerInit();
    HalUartInit();
	HalTimerWait(100);
   GPIOC->DDR |=  0x30;            
   GPIOC->CR1 |=  0x30;
   GPIOC->ODR |= 0x30;
    /* Perform a hard reset on the device to ensure that it is in a known   */
    /* state (also downloads a fresh copy of EDID from NVRAM).              */

    DEBUG_PRINT(MSG_ALWAYS,("\nPower up Initialize..."));
    u8Data = SI_DevicePowerUpBoot(0);
    if ( u8Data <= 0x02 )
    {
        DEBUG_PRINT( MSG_ALWAYS, ( "0 FAILED - " ));
    }
    DEBUG_PRINT(MSG_ALWAYS,("\n0 Base Address: %02X  BSM Status: %02X\n", (int)u8Data, (int)SiIRegioRead(0, REG_BSM_STAT )));
    /*u8Data = SI_DevicePowerUpBoot(1);
    if ( u8Data <= 0x02 )
    {
        DEBUG_PRINT( MSG_ALWAYS, ( "1 FAILED - " ));
    }
    DEBUG_PRINT(MSG_ALWAYS,("\n1 Base Address: %02X  BSM Status: %02X\n", (int)u8Data, (int)SiIRegioRead(1, REG_BSM_STAT )));
*/

    CpDisplayChipInfo(0);
	//CpDisplayChipInfo(1);
    //HalTimerSet( TIMER_POLLING, DEM_POLLING_DELAY );
    while ( 1 )
    {
   		HalTimerWait(100);
       process(0);
	  // process(1);
    }
}
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
	}
}
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;
}
Beispiel #7
0
/**
 *  @brief Thread function that periodically polls for MHLTx events.
 *
 *  @param[in]	data	Pointer to driver context structure
 *
 *  @return		Always returns zero when the thread exits.
 *
 *****************************************************************************/
static int EventThread(void *data)
{
	printk("%s EventThread starting up\n", MHL_DRIVER_NAME);

	while (true)
	{
		if (kthread_should_stop())
		{
			printk("%s EventThread exiting\n", MHL_DRIVER_NAME);
			break;
		}

		HalTimerWait(EVENT_POLL_INTERVAL_30_MS);
		SiiMhlTxDeviceIsr();
	}
	return 0;
}
Beispiel #8
0
static void ResumeWorkFunc(struct work_struct *work)
{
    printk(KERN_INFO "%s Resume MHL start.\n", __func__);

	Sii8334_plat_data->reset();

	msleep(1000);
    //deleted by zhangyue on 2011-12-15 for solving the hpd problems start
    //enable_irq(sii8334_PAGE_TPI->irq);
    //deleted by zhangyue on 2011-12-15 for solving the hpd problems end
    SiiMhlTxInitialize();
    //added by zhangyue on 2011-12-19 for debugging the mhl irq problem start
    printk(KERN_INFO "%s Init Register End.\n", __func__);
    HalTimerWait(30);//wait 30ms before enable registers
    mhl_set_irq_locked(true, false);
    //added by zhangyue on 2011-12-19 for debugging the mhl irq problem end
}
///////////////////////////////////////////////////////////////////////////////
//
// SiiMhlTxDrvNotifyEdidChange
//
// MhlTx may need to inform upstream device of an EDID change. This can be
// achieved by toggling the HDMI HPD signal or by simply calling EDID read
// function.
//
void SiiMhlTxDrvNotifyEdidChange (void)
{
    TX_DEBUG_PRINT(("Drv: SiiMhlTxDrvNotifyEdidChange\n"));
	//
	// Prepare to toggle HPD to upstream
	//
    SiiMhlTxDrvAcquireUpstreamHPDControl();

	// reg_hpd_out_ovr_val = LOW to force the HPD low
	CLR_BIT(REG_INT_CTRL, 5);

	// wait a bit
	HalTimerWait(110);

	// release HPD back to high by reg_hpd_out_ovr_val = HIGH
	SET_BIT(REG_INT_CTRL, 5);

    // release control to allow transcoder to modulate for CLR_HPD and SET_HPD
    SiiMhlTxDrvReleaseUpstreamHPDControl();
}
/**
 *  @brief Thread function that periodically polls for MHLTx events.
 *
 *  @param[in]	data	Pointer to driver context structure
 *
 *  @return		Always returns zero when the thread exits.
 *
 *****************************************************************************/
static int EventThread(void *data)
{
	uint8_t 				event;
	uint8_t 				eventParam;


	printk("%s EventThread starting up\n", MHL_DRIVER_NAME);

	while (true)
	{
		if (kthread_should_stop())
		{
			printk("%s EventThread exiting\n", MHL_DRIVER_NAME);
			break;
		}

		HalTimerWait(30);
		SiiMhlTxDeviceIsr();
	}
	return 0;
}
bool_t SiiMhlTxChipInitialize (void)
{
	tmdsPoweredUp = false;
	mhlConnected = false;
	mscCmdInProgress = false;	// false when it is okay to send a new command
	dsHpdStatus = 0;
	fwPowerState = POWER_STATE_FIRST_INIT;
    //SI_OS_DISABLE_DEBUG_CHANNEL(SII_OSAL_DEBUG_SCHEDULER);

    g_chipRevId = SiiRegRead(REG_DEV_REV);

	// then wait 100ms per MHL spec
	HalTimerWait(TX_HW_RESET_DELAY);
	TX_DEBUG_PRINT(("Drv: SiiMhlTxChipInitialize: %02X%02X%02x\n",
						g_chipRevId,
					SiiRegRead(TX_PAGE_L0 | 0x03),
					SiiRegRead(TX_PAGE_L0 | 0x02)));

	// setup device registers. Ensure RGND interrupt would happen.
	WriteInitialRegisterValues();

    //SiiOsMhlTxInterruptEnable();

	// CBUS interrupts are unmasked after performing the reset.
	// UNMASK_CBUS1_INTERRUPTS;
	// UNMASK_CBUS2_INTERRUPTS;

	//
	// Allow regular operation - i.e. pinAllowD3 is high so we do enter
	// D3 first time. Later on, SiIMon shall control this GPIO.
	//
	//pinAllowD3 = 1;

	SwitchToD3();

	return true;
}
Beispiel #12
0
/**
 *  @brief Thread function that periodically polls for MHLTx events.
 *
 *  @param[in]	data	Pointer to driver context structure
 *
 *  @return		Always returns zero when the thread exits.
 *
 *****************************************************************************/
static int EventThread(void *data)
{
    uint8_t 				event;
    uint8_t 				eventParam;
    
    
    printk("%s EventThread starting up\n", MHL_DRIVER_NAME);
    
    while (true){
        if (kthread_should_stop()){
            printk("%s EventThread exiting\n", MHL_DRIVER_NAME);
            break;
        }
        
        HalTimerWait(EVENT_POLL_INTERVAL_30_MS);
        
        SiiMhlTxGetEvents(&event, &eventParam);
        
        if( MHL_TX_EVENT_NONE != event ) {
            AppRcpDemo( event, eventParam);
        }
    }
    return 0;
}
Beispiel #13
0
/*
 * i2c client ftn.
 */
static int __devinit mhl_Sii8334_probe(struct i2c_client *client,
			const struct i2c_device_id *dev_id)
{
    int ret = 0;
    if(match_id(&mhl_Sii8334_idtable[0], client)){
        sii8334_PAGE_TPI = client;
        dev_info(&client->adapter->dev, "attached %s "
                "into i2c adapter successfully\n", dev_id->name);
    }
    /*
    else if(match_id(&mhl_Sii8334_idtable[1], client)){
        sii8334_PAGE_TX_L0 = client;
        dev_info(&client->adapter->dev, "attached %s "
                "into i2c adapter successfully \n", dev_id->name);
    }
    */
    else if(match_id(&mhl_Sii8334_idtable[2], client)){
        sii8334_PAGE_TX_L1 = client;
        dev_info(&client->adapter->dev, "attached %s "
                "into i2c adapter successfully \n", dev_id->name);
    }else if(match_id(&mhl_Sii8334_idtable[3], client)){
        sii8334_PAGE_TX_2 = client;
        dev_info(&client->adapter->dev, "attached %s "
                "into i2c adapter successfully\n", dev_id->name);
    }else if(match_id(&mhl_Sii8334_idtable[4], client)){
        sii8334_PAGE_TX_3 = client;
        dev_info(&client->adapter->dev, "attached %s "
                "into i2c adapter successfully\n", dev_id->name);
    }else if(match_id(&mhl_Sii8334_idtable[5], client))    {
        sii8334_PAGE_CBUS = client;
        dev_info(&client->adapter->dev, "attached %s "
            "into i2c adapter successfully\n", dev_id->name);
    }else{
        dev_info(&client->adapter->dev, "invalid i2c adapter: can not found dev_id matched\n");
        return -EIO;
    }
    
    
    if(sii8334_PAGE_TPI != NULL 
      //&&sii8334_PAGE_TX_L0 != NULL 
      &&sii8334_PAGE_TX_L1 != NULL 
      && sii8334_PAGE_TX_2 != NULL
      && sii8334_PAGE_TX_3 != NULL
      && sii8334_PAGE_CBUS != NULL){
        
        Sii8334_plat_data = sii8334_PAGE_TPI->dev.platform_data;
        #ifdef mhl_power_dbg
        ret = Sii8334_plat_data->mhl_power_on();
        if(ret){
            printk("%s:call mhl_power_on failed.\n", __func__);	
        }
	  //added by zhangyue on 2011-11-21 for config irq	
	  Sii8334_plat_data->mhl_irq_config();
	  //added by zhangyue on 2011-11-21 end
        #endif
        if(false == Sii8334_mhl_reset()){
            printk("/nCan't find the reset function in your platform file============================================\n");
            return -EIO;
        }
        
        // Announce on RS232c port.
        //
        printk("\n============================================\n");
        printk("SiI-8334 Driver Version based on 8051 driver Version 1.14 \n");
        printk("============================================\n");
        
        //
        // Initialize the registers as required. Setup firmware vars.
        //
        
	  SiiMhlTxInitialize();
        
        #ifdef SiI8334DRIVER_INTERRUPT_MODE
        #ifdef zy_dbg_err_handle
        sii8334work = kmalloc(sizeof(*sii8334work), GFP_KERNEL);
         if(NULL == sii8334work){
            printk(KERN_ERR "NO memory for allocating sii8334work.\n");
            ret = -ENOMEM;
            goto ERR_ALLOC_INT_WORK;
        }
        #else
        sii8334work = kmalloc(sizeof(*sii8334work), GFP_ATOMIC);
        #endif
        INIT_WORK(sii8334work, work_queue); 
        #ifdef mhl_power_dbg
        #ifdef zy_dbg_err_handle
        ResumeWork = kmalloc(sizeof(*ResumeWork ),  GFP_ATOMIC);
        if(NULL == ResumeWork){
            printk(KERN_ERR "NO memory for allocating ResumeWork.\n");
	      ret = -ENOMEM;
            goto ERR_ALLOC_RESUM_WORK;
        }
        #else
        ResumeWork = kmalloc(sizeof(*ResumeWork ),  GFP_ATOMIC);
        #endif
        INIT_DELAYED_WORK(ResumeWork, ResumeWorkFunc);
        #endif
        #ifdef ZY_IMPLEMENT_RCP
        mhl_state.rmt_input = input_allocate_device();
        if(NULL == mhl_state.rmt_input){
            printk(KERN_INFO "Bad input_allocate_device()\n");
	      ret = -ENOMEM;
	      goto ERR_ALLOC_INPUT;
        }
	
        mhl_init_rmt_input_dev();
        //Register with the Input subsystem	
        ret = input_register_device(mhl_state.rmt_input);
        if(ret){
            printk(KERN_INFO "Register input device failed.\n ");
            goto ERR_REG_INPUT;
        }
        #endif
        #ifdef zy_dbg_irq
	  //modified by zhangyue on 2011-12-07 
	  //for debugging, because some time, the irq handler not run when the irq came.
	  ret = request_threaded_irq(sii8334_PAGE_TPI->irq, NULL, Sii8334_mhl_interrupt, IRQ_TYPE_LEVEL_LOW |IRQF_ONESHOT, 
        	sii8334_PAGE_TPI->name, sii8334_PAGE_TPI); 
	 #else
        ret = request_irq(sii8334_PAGE_TPI->irq, Sii8334_mhl_interrupt, IRQ_TYPE_LEVEL_LOW,
        sii8334_PAGE_TPI->name, sii8334_PAGE_TPI); 
	  #endif
	  
        if (ret){
            printk(KERN_INFO "%s:%d:Sii8334 interrupt failed\n", __func__,__LINE__);	
            #ifdef zy_dbg_err_handle
            goto ERR_REQ_IRQ;
            #endif
            //free_irq(irq, iface);
        }else{
            #ifdef zy_usrspace_enalbe_mhl_irq
		//modified by zhangyue on 2011-12-26 for debugging the mhl charging	start
		disable_irq(sii8334_PAGE_TPI->irq);
		HalTimerWait(40);//sleep 40ms
		enable_irq(sii8334_PAGE_TPI->irq);
            //disable_irq(sii8334_PAGE_TPI->irq);
		//modified by zhangyue on 2011-12-26 for debugging the mhl charging	end
	      #else
            enable_irq_wake(sii8334_PAGE_TPI->irq);
	      #endif  
            //printk(KERN_INFO "%s:%d:Sii8334 interrupt successed\n", __func__,__LINE__);	
        }
        #ifdef zy_usrspace_enalbe_mhl_irq
        mhl_state.irq_Inited = false;
	 #endif
        #ifdef mhl_power_dbg
        mhl_state.state = true;
        #endif
        #else
        StartEventThread();		/* begin monitoring for events if using polling mode*/
        #endif
        #ifdef zy_dbg_err_handle
        goto ERR_ALLOC_INT_WORK;
        #endif
    ERR_REQ_IRQ:
        input_unregister_device(mhl_state.rmt_input);
    ERR_REG_INPUT:
        input_free_device(mhl_state.rmt_input);
    ERR_ALLOC_INPUT:
        kfree(ResumeWork);
    ERR_ALLOC_RESUM_WORK:
        kfree(sii8334work);
    }
ERR_ALLOC_INT_WORK:
    return ret;
}
Beispiel #14
0
uint8_t SiiMhlRxIntrHandler ()
{
    uint8_t result = SUCCESS;
    bool_t retrycheck = false;
    /* Check the channel interrupt status to see if anybody is  */
    /* talking to us. If they are, talk back.                   */
    result = CBusCheckInterruptStatus();

    /* Don't bother with the rest if the heart is gone. */
    if ( result != SUCCESS )
    {
        if (result & ERROR_CBUS_ABORT)
        {
            //Set abort timer
#if defined(__KERNEL__)
            SiiCbusAbortTimerStart();
#else
            pCbus->chState.abortTimer = SiiTimerTotalElapsed();
#endif
            SiiCbusAbortStateSet(true);
            pCbus->chState.state = CBUS_IDLE;
            SiiMhlRxSetQueueEmpty();
        }
        else if (result & ERROR_CBUS_ABORT_OTHER)
        {
            //send MSC error cannot retry
            if (pCbus->chState.state == CBUS_SENT)
            {
                pCbus->chState.state = CBUS_IDLE;
                pCbus->chState.request[ CH_ACTIVE_INDEX ].reqStatus = CBUS_REQ_IDLE;
            }
        }
        else if (result & (ERROR_CBUS_TIMEOUT | ERROR_NACK_FROM_PEER))
        {
            //send MSC error, retry if possible
            if (pCbus->chState.state == CBUS_SENT)
            {
                retrycheck = true;
            }
        }
    }

    // If there's some in the burst queue, send it out
    CBusBurstNextInQueue();

    // Check if there's any cbus message arrived
    if (pCbus->chState.receive.arrived)
    {
        SiiMhlRxRcpRapRcvdNtfy(pCbus->chState.receive.command, pCbus->chState.receive.offsetData);
        pCbus->chState.receive.arrived = false;
    }

    /* Update the channel state machine as necessary.   */
    if ( pCbus->chState.state == CBUS_XFR_DONE )
    {
        pCbus->chState.state = CBUS_IDLE;

        /* We may be waiting for a response message, but the    */
        /* request queue is idle.                               */
        if ( pCbus->chState.request[ CH_ACTIVE_INDEX ].command == MHL_READ_DEVCAP )
        {
            DEBUG_PRINT( MSG_DBG, "Response data Received, %02X\n", pCbus->chState.request[ CH_ACTIVE_INDEX ].retData[0] );
            if (pCbus->chState.request[ CH_ACTIVE_INDEX ].offsetData < 15)
                SiiMhlRxReadDevCapReg(pCbus->chState.request[ CH_ACTIVE_INDEX ].offsetData+1);
            else
                pCbus->chState.dcap_ongoing = false;
            pCbus->chState.remote_dcap[pCbus->chState.request[ CH_ACTIVE_INDEX ].offsetData] = pCbus->chState.request[ CH_ACTIVE_INDEX ].retData[0];
        }
        if ( (pCbus->chState.request[ CH_ACTIVE_INDEX ].command == MHL_MSC_MSG )
            && ((pCbus->chState.request[ CH_ACTIVE_INDEX ].msgData[0] == MHL_MSC_MSG_RCPE) ||
            (pCbus->chState.request[ CH_ACTIVE_INDEX ].msgData[0] == MHL_MSC_MSG_UCPE)))
        {
            //Add a little delay after sending RCPE/UCPE
            HalTimerWait(20);
        }
        pCbus->chState.request[ CH_ACTIVE_INDEX ].reqStatus = CBUS_REQ_IDLE;
        CH_ACTIVE_INDEX = (CH_ACTIVE_INDEX + 1)% CBUS_MAX_COMMAND_QUEUE;
    }
#if 0
    if (pCbus->chState.state == CBUS_SENT)
    {
        //From spec need Wait for TCMD_RECEIVER_TIMEOUT, at least 320ms
        if (pCbus->chState.request[ CH_ACTIVE_INDEX ].reqStatus == CBUS_REQ_SENT)
        {
            if (SiiTimerTotalElapsed() - pCbus->chState.request[ CH_ACTIVE_INDEX ].reqTimer > CBUS_CMD_TIMEOUT)
            {
                //should never be here, when this timeout occured, there should be abort interrupt firstly.
                retrycheck = true;
            }
        }
        else
        {
            //should never be here
            pCbus->chState.state = CBUS_IDLE;
            result = ERROR_INVALID;
            return result;
        }
    }
#endif

    if (retrycheck)
    {
        pCbus->chState.state = CBUS_IDLE;
        if (pCbus->chState.request[ CH_ACTIVE_INDEX ].retry)
        {
            pCbus->chState.request[ CH_ACTIVE_INDEX ].reqStatus = CBUS_REQ_PENDING;
            pCbus->chState.request[ CH_ACTIVE_INDEX ].retry--;
        }
        else
        {
            // retry failed, skip the current index, and move on. 
            pCbus->chState.request[ CH_ACTIVE_INDEX ].reqStatus = CBUS_REQ_IDLE;
            CH_ACTIVE_INDEX = (CH_ACTIVE_INDEX + 1)% CBUS_MAX_COMMAND_QUEUE;
        }
    }

    if (pCbus->chState.state == CBUS_IDLE)
    {
        result = CBusSendNextInQueue();     // No command in progress, write new command immediately.
    }

    return( result );
}
static void ReleaseUsbIdSwitchOpen ( void )
{
	HalTimerWait(50); 
	SiiRegModify(REG_DISC_CTRL6, BIT6, 0x00);
	ENABLE_DISCOVERY;
}
void SiiMhlTriggerSoftInt(void)
{
    SiiRegBitsSet(REG_INT_CTRL,BIT3,true);
	HalTimerWait(5);
    SiiRegBitsSet(REG_INT_CTRL,BIT3,false);
}
long SiiMhlIoctl(struct file *pFile, unsigned int ioctlCode, unsigned long ioctlParam)
{
	long retStatus = 0;
	Register_t RegisterInfo;
	uint8_t reg;
	UserControl_t user_control;
	if (HalAcquireIsrLock() != HAL_RET_SUCCESS) {
		return -ERESTARTSYS;
	}
	switch (ioctlCode) {
	case SII_IOCTRL_REGISTER_READ:
		retStatus = copy_from_user(&RegisterInfo, (Register_t *) ioctlParam,
					   sizeof(Register_t));
		if (!retStatus) {
			RegisterInfo.value =
			    I2C_ReadByte(RegisterInfo.dev_address, RegisterInfo.subaddr);
			retStatus =
			    copy_to_user((Register_t *) ioctlParam, &RegisterInfo,
					 sizeof(Register_t));
		} else {
			pr_info("register read error!\n");
		}
		break;
	case SII_IOCTRL_REGISTER_WRITE:
		retStatus = copy_from_user(&RegisterInfo, (Register_t *) ioctlParam,
					   sizeof(Register_t));
		reg = I2C_ReadByte(RegisterInfo.dev_address, RegisterInfo.subaddr);
		reg = (reg & (~RegisterInfo.mask)) | (RegisterInfo.mask & RegisterInfo.value);
		I2C_WriteByte(RegisterInfo.dev_address, RegisterInfo.subaddr, reg);
		break;
	case SII_IOCTRL_USER:
		retStatus = copy_from_user(&user_control, (UserControl_t *) ioctlParam,
					   sizeof(UserControl_t));
		switch (user_control.ControlID) {
		case USER_GPIO_GET:
			/* HalGpioGetPin(user_control.SubCommand.GpioCtrl.GpioIndex, &user_control.SubCommand.GpioCtrl.Value); */
			break;
		case USER_GPIO_SET:
			/* HalGpioSetPin(user_control.SubCommand.GpioCtrl.GpioIndex, user_control.SubCommand.GpioCtrl.Value); */
			break;
		case USER_TRIGGER_EXT_INT:
			/* SiiTriggerExtInt(); */
			break;
		case USER_TRIGGER_MHL_INT:
			{
				if (TestDelay != NULL) {
					SiiOsTimerDelete(TestDelay);
					TestDelay = NULL;
				}
				SiiOsTimerCreate("Abort Time Out", SiiMhlTimerTestCB, NULL, true,
						 2000, false, &TestDelay);
			}
			break;
		case USER_ON_OFF_MHL_INT:
			HalEnableIrq(user_control.SubCommand.iSubCommand ? 1 : 0);
			break;
		case USER_RESET_MHL_CHIP:
			SiiMhlTxInitialize(EVENT_POLL_INTERVAL_MS);
			break;
		case USER_READ_SINK_EDID:
			{
#define _MASK_(aByte, bitMask, setBits) ((setBits) ? (aByte | bitMask) : (aByte & ~bitMask))
				int RepeatNums = 5, i;
				int iRepeatCnt = 0;
				uint8_t reg;
				uint8_t reg_save;
				reg_save = reg = I2C_ReadByte(0x72, 0xC7);
				reg = _MASK_(reg, BIT0, 1);
				I2C_WriteByte(0x72, 0xc7, reg);
				do {
					if (++iRepeatCnt > RepeatNums)
						break;
					reg = I2C_ReadByte(0x72, 0xC7);
					HalTimerWait(10);
				} while (!(reg & BIT1));
				if (iRepeatCnt > RepeatNums) {
					printk("try time out\n");
				} else {
					reg = I2C_ReadByte(0x72, 0xC7);
					reg = _MASK_(reg, BIT2, 1);
					I2C_WriteByte(0x72, 0xc7, reg);
					for (i = 0; i < 256; i++) {
					}
					I2C_ReadBlock(0xa0, 0, user_control.SubCommand.EDID, 128);
					I2C_ReadBlock(0xa0, 128, &user_control.SubCommand.EDID[128],
						      128);
					I2C_WriteByte(0x72, 0xc7, reg_save);
				}
			}
			break;
		}
		retStatus = copy_to_user((UserControl_t *) ioctlParam,
					 &user_control, sizeof(UserControl_t));
		break;
	default:
		SII_DEBUG_PRINT(SII_OSAL_DEBUG_TRACE,
				"SiiMhlIoctl, unrecognized ioctlCode 0x%0x received!\n", ioctlCode);
		retStatus = -EINVAL;
		break;
	}
	HalReleaseIsrLock();
	return retStatus;
}
void SwitchToD3 (void)
{
	if(POWER_STATE_D3 != fwPowerState)
	{
		TX_DEBUG_PRINT(("Drv: Switch To D3\n"));
		//SiiRegModify(REG_DISC_CTRL6,  BIT4, BIT4); //Block RGND INT in Discovery SM. added by garyyuan 20100804
//		TX_DEBUG_PRINT(("[%d] Drv: Switch To D3: pinAllowD3 = %d\n",
//							(int) (HalTimerElapsed( ELAPSED_TIMER ) * MONITORING_PERIOD), (int) pinAllowD3 ) );

		//pinM2uVbusCtrlM = 1;
		//pinMhlConn = 1;
		//pinUsbConn = 0;

		ForceUsbIdSwitchOpen();
		HalTimerWait(50);

		//
		// To allow RGND engine to operate correctly.
		// So when moving the chip from D0 MHL connected to D3 the values should be
		// 94[1:0] = 00  reg_cbusmhl_pup_sel[1:0] should be set for open
		// 93[7:6] = 00  reg_cbusdisc_pup_sel[1:0] should be set for open
		// 93[5:4] = 00  reg_cbusidle_pup_sel[1:0] = open (default)
		//
		// Disable CBUS pull-up during RGND measurement
//		I2C_WriteByte(PAGE_0_0X72, 0x93, 0x04);
//		ReadModifyWritePage0(0x93, BIT_7 | BIT_6 | BIT_5 | BIT_4, 0);

//		ReadModifyWritePage0(0x94, BIT_1 | BIT_0, 0);

		// 1.8V CBUS VTH & GND threshold
//		I2C_WriteByte(PAGE_0_0X72, 0x94, 0x64);

		ReleaseUsbIdSwitchOpen();



		// Force HPD to 0 when not in MHL mode.
        SiiMhlTxDrvAcquireUpstreamHPDControlDriveLow();

		// Change TMDS termination to high impedance on disconnection; reduce leakage to QCOM HDMI out, due to QCOM HDMI out can't be truly tri-stated. Each TMDS pin has about 0.1125mA leakage from AVCC33.
		// Bits 1:0 set to 11


		SiiRegWrite(REG_MHLTX_CTL1, 0xD0);
		
		// clear all interrupt here before go into D3 mode by oscar
		SiiRegWrite(TX_PAGE_TPI | 0x0071, 0xFF);
		SiiRegWrite(TX_PAGE_TPI | 0x0072, 0xFF);
		SiiRegWrite(TX_PAGE_TPI | 0x0074, 0xBF);  // keep BIT6 for fast plug case
		SiiRegWrite(TX_PAGE_CBUS | 0x0008, 0xFF);
		SiiRegWrite(TX_PAGE_CBUS | 0x001E, 0xFF);

		//
		// GPIO controlled from SiIMon can be utilized to disallow
		// low power mode, thereby allowing SiIMon to debug register contents.
		// Otherwise SiIMon reads all registers as 0xFF
		//
//		if(pinAllowD3)
//		{
			// wait Tsrc:cbus_float
			HalTimerWait(50);
			//
			// Change state to D3 by clearing bit 0 of 3D (SW_TPI, Page 1) register
			// ReadModifyWriteIndexedRegister(INDEXED_PAGE_1, 0x3D, BIT_0, 0x00);
			//
			CLR_BIT(TX_PAGE_L1 | 0x003D, 0);
			
			CBusQueueReset();

			fwPowerState = POWER_STATE_D3;
//		}

#if (VBUS_POWER_CHK == ENABLE)		// Turn VBUS power off when switch to D3(cable out)
		if( vbusPowerState == false )
		{
			AppVbusControl( vbusPowerState = true );
		}
#endif
	}
	else
	{
		fwPowerState = POWER_STATE_D0_NO_MHL;
	}

}