//*****************************************************************************
//
// Function Name: dsic_close
// 
// Description:   Close The Driver
//
//*****************************************************************************
Int32 dsic_close ( DISPDRV_HANDLE_T drvH ) 
{
    Int32                   res = 0;
    dsic_panel_t   *pPanel = (dsic_panel_t *)drvH;
    
    pPanel->pFb  = NULL;
    pPanel->pFbA = NULL;

    if ( CSL_DSI_CloseCmVc ( pPanel->dsiCmVcHandle ) ) 
    {
        LCD_DBG ( LCD_DBG_ERR_ID, "[DISPDRV] %s: ERROR, "
            "Closing Command Mode Handle\n\r", __FUNCTION__);
        return ( -1 );
    }
    
    if ( CSL_DSI_CloseClient ( pPanel->clientH ) != CSL_LCD_OK )
    {
        LCD_DBG ( LCD_DBG_ERR_ID, "[DISPDRV] %s: ERROR, Closing DSI Client\n\r",
            __FUNCTION__);
        return ( -1 );
    }
    
    if ( CSL_DSI_Close( pPanel->busId ) != CSL_LCD_OK )
    {
        LCD_DBG ( LCD_DBG_ERR_ID, "[DISPDRV] %s: ERR Closing DSI Controller\n\r",
            __FUNCTION__ );
        return ( -1 );
    }

    pPanel->pwrState = DISP_PWR_OFF;
    pPanel->drvState = DRV_STATE_INIT;
    LCD_DBG ( LCD_DBG_INIT_ID, "[DISPDRV] %s: OK\n\r", __FUNCTION__ );

    return ( res );
}
/*
 *
 * Function Name:   cslDsiDmaStop
 *
 * Description:     RHEA MM DMA - Stop DMA
 *
 */
static CSL_LCD_RES_T cslDsiDmaStop(DSI_UPD_REQ_MSG_T *updMsg)
{
	CSL_LCD_RES_T res = CSL_LCD_ERR;

	LCD_DBG(LCD_DBG_ID, "[CSL DSI] +cslDsiDmaStop\n");

	/* stop DMA transfer */
	if (csl_dma_vc4lite_stop_transfer(updMsg->dmaCh)
	    != DMA_VC4LITE_STATUS_SUCCESS) {
		LCD_DBG(LCD_DBG_ERR_ID, "[CSL DSI] %s: "
			"ERR DMA Stop Transfer\n ", __func__);
		res = CSL_LCD_DMA_ERR;
	}
	/* release DMA channel */
	if (csl_dma_vc4lite_release_channel(updMsg->dmaCh)
	    != DMA_VC4LITE_STATUS_SUCCESS) {
		LCD_DBG(LCD_DBG_ERR_ID, "[CSL DSI] %s: "
			"ERR ERR DMA Release Channel\n ", __func__);
		res = CSL_LCD_DMA_ERR;
	}

	cslDsiClearAllFifos(updMsg->dsiH);
	updMsg->dmaCh = DMA_VC4LITE_CHANNEL_INVALID;

	LCD_DBG(LCD_DBG_ID, "[CSL DSI] -cslDsiDmaStop\n");

	return res;
}
//*****************************************************************************
//
// Function Name: _Update
// 
// Description:   DMA/OS Update using INT frame buffer
//
//*****************************************************************************
Int32 DISPDRV_Update ( 
    DISPDRV_HANDLE_T    drvH, 
    int			fb_idx,
    DISPDRV_WIN_t*	p_win,
    DISPDRV_CB_T        apiCb
    )
{
    DISPDRV_PANEL_T *pPanel = (DISPDRV_PANEL_T *)drvH;
    CSL_LCD_UPD_REQ_T   req;
    Int32               res  = 0;

  //  LCD_DBG ( LCD_DBG_ID, "[DISPDRV] +%s\r\n", __FUNCTION__ );

    DISPDRV_CHECK_PTR_2_RET( drvH, &panel[0], &panel[1], __FUNCTION__ );
    
    if ( pPanel->pwrState != DISP_PWR_SLEEP_OFF )
    {
        LCD_DBG ( LCD_DBG_ERR_ID, "[DISPDRV] +%s: Skip Due To Power State\r\n",__FUNCTION__ );
        return ( -1 );
    }
   
    if (0 == fb_idx)
    	req.buff           = pPanel->pFbA;
     else
	req.buff 	   = (void *)((UInt32)pPanel->pFbA + 
		Disp_Info.width * Disp_Info.height * 2); //@HW

//    req.buff           = pPanel->pFbA;
    req.lineLenP       = Disp_Info.width;
    req.lineCount      = Disp_Info.height;
    req.buffBpp        = 2; //4; //@HW 
    req.timeOut_ms     = 100;   // SKC 1000
   
    LCD_DBG ( LCD_DBG_ID, "buf=%08x, linelenp = %d, linecnt =%d\n", (u32)req.buff, (u32)req.lineLenP, (u32)req.lineCount);
    req.cslLcdCbRec.cslH            = pPanel->clientH;
    req.cslLcdCbRec.dispDrvApiCbRev = DISP_DRV_CB_API_REV_1_0;
    req.cslLcdCbRec.dispDrvApiCb    = (void*) apiCb;
    req.cslLcdCbRec.dispDrvApiCbP1  = NULL;
    
    if( apiCb != NULL )
       req.cslLcdCb = DISPDRV_Cb;
    else
       req.cslLcdCb = NULL;
    
    //if ( CSL_DSI_UpdateCmVc ( pPanel->dsiCmVcHandle, &req, FALSE ) != CSL_LCD_OK )
    if ( CSL_DSI_UpdateCmVc ( pPanel->dsiCmVcHandle, &req, pPanel->isTE ) != CSL_LCD_OK )
    {
        LCD_DBG ( LCD_DBG_ERR_ID, "[DISPDRV] %s: ERROR ret by "
            "CSL_DSI_UpdateCmVc\n\r", __FUNCTION__ );
        res = -1;    
    }
        
    // LCD_DBG ( LCD_DBG_ID, "[DISPDRV] -%s\r\n", __FUNCTION__ );
        
    return ( res );
}
/*
 *
 * Function Name:  cslDsi1UpdateTask
 *
 * Description:    DSI Controller 0 Update Task
 *
 */
static void cslDsi1UpdateTask(void)
{
	DSI_UPD_REQ_MSG_T updMsg;
	OSStatus_t osStat;
	CSL_LCD_RES_T res;
	DSI_HANDLE dsiH = &dsiBus[1];

	for (;;) {
		res = CSL_LCD_OK;

		/* Wait for update request */
		OSQUEUE_Pend(dsiH->updReqQ, (QMsg_t *)&updMsg, TICKS_FOREVER);

		/* Wait For signal from eof DMA */
		osStat = OSSEMAPHORE_Obtain(dsiH->semaDma,
					    TICKS_IN_MILLISECONDS(updMsg.updReq.
								  timeOut_ms));

		if (osStat != OSSTATUS_SUCCESS) {
			if (osStat == OSSTATUS_TIMEOUT) {
				LCD_DBG(LCD_DBG_ERR_ID, "[CSL DSI] %s: "
					"TIMED OUT While waiting for "
					"EOF DMA\n", __func__);
				res = CSL_LCD_OS_TOUT;
			} else {
				LCD_DBG(LCD_DBG_ERR_ID, "[CSL DSI] %s: "
					"OS ERR While waiting for EOF DMA\n",
					__func__);
				res = CSL_LCD_OS_ERR;
			}

			cslDsiDmaStop(&updMsg);
		}

		if (res == CSL_LCD_OK)
			res = cslDsiWaitForInt(dsiH, 100);
		else
			cslDsiWaitForInt(dsiH, 1);

		chal_dsi_de1_enable(dsiH->chalH, FALSE);
		chal_dsi_tx_start(dsiH->chalH, TX_PKT_ENG_1, FALSE);
		chal_dsi_tx_start(dsiH->chalH, TX_PKT_ENG_2, FALSE);

		if (!updMsg.clientH->hasLock)
			OSSEMAPHORE_Release(dsiH->semaDsi);

		if (updMsg.updReq.cslLcdCb) {
			updMsg.updReq.cslLcdCb(res, &updMsg.updReq.cslLcdCbRec);
		} else {
			LCD_DBG(LCD_DBG_ERR_ID, "[CSL DSI] %s: "
				"Callback EQ NULL, Skipping\n", __func__);
		}
	}
}
//*****************************************************************************
//
// Function Name: _Update
// 
// Description:   DMA/OS Update using INT frame buffer
//
//*****************************************************************************
Int32 DISPDRV_Update(DISPDRV_HANDLE_T drvH,
		     void *buff, DISPDRV_WIN_t *p_win, DISPDRV_CB_T apiCb)
{
	DISPDRV_PANEL_T *pPanel = (DISPDRV_PANEL_T *)drvH;
	CSL_LCD_UPD_REQ_T req;
	Int32 res = 0;

	//  LCD_DBG ( LCD_DBG_ID, "[DISPDRV] +%s\r\n", __FUNCTION__ );

	if (pPanel->pwrState == STATE_PWR_OFF) {
		LCD_DBG(LCD_DBG_ERR_ID,
			"[DISPDRV] +%s: Skip Due To Power State\r\n",
			__FUNCTION__);
		return (-1);
	}

	req.buff = buff;
	req.lineLenP = pPanel->disp_info->width;
	req.lineCount = pPanel->disp_info->height;
	req.buffBpp = pPanel->disp_info->Bpp;
	req.timeOut_ms = 100;	

	LCD_DBG(LCD_DBG_ID, "buf=%08x, linelenp = %d, linecnt =%d\n",
		(u32)req.buff, (u32)req.lineLenP, (u32)req.lineCount);
	req.cslLcdCbRec.cslH = pPanel->clientH;
	req.cslLcdCbRec.dispDrvApiCbRev = DISP_DRV_CB_API_REV_1_0;
	req.cslLcdCbRec.dispDrvApiCb = (void *)apiCb;
	req.cslLcdCbRec.dispDrvApiCbP1 = NULL;

	if (apiCb != NULL)
		req.cslLcdCb = DISPDRV_Cb;
	else
		req.cslLcdCb = NULL;

	if((panelID== LCD_PANEL_ID_READ_ERROR)||(panelID==LCD_PANEL_ID_NOT_SET))
	{
	//	printk("[LCD] %s, There are no LCD module\n", __func__);
		if (req.cslLcdCb != NULL)
			DISPDRV_Cb(CSL_LCD_OK, &req.cslLcdCbRec);
		return 0;
	}		

	//if ( CSL_DSI_UpdateCmVc ( pPanel->dsiCmVcHandle, &req, FALSE ) != CSL_LCD_OK )
	if (CSL_DSI_UpdateCmVc(pPanel->dsiCmVcHandle, &req, pPanel->isTE) !=
	    CSL_LCD_OK) {
		LCD_DBG(LCD_DBG_ERR_ID,
			"[DISPDRV] %s: ERROR ret by " "CSL_DSI_UpdateCmVc\n\r",
			__FUNCTION__);
		res = -1;
	}
	// LCD_DBG ( LCD_DBG_ID, "[DISPDRV] -%s\r\n", __FUNCTION__ );

	return (res);
}
//*****************************************************************************
//
// Function Name: dsic_send_data
//
// Description:   DMA/OS Update using INT frame buffer
//
//*****************************************************************************
Int32 dsic_send_data (
	DISPDRV_HANDLE_T	drvH,
	int 				fb_idx,
	DISPDRV_CB_T		apiCb,
	int 		img_width,
	int 		img_height
	)
{
	dsic_panel_t *pPanel = (dsic_panel_t *)drvH;
	CSL_LCD_UPD_REQ_T   req;
	Int32   			res  = 0;

	//LCD_DBG ( LCD_DBG_ID, "[DISPDRV] +%s\r\n", __FUNCTION__ );

	if ( pPanel->pwrState != DISP_PWR_SLEEP_OFF )
	{
		LCD_DBG ( LCD_DBG_ERR_ID, "[DISPDRV] +%s: Skip Due To Power State\r\n",
			__FUNCTION__ );
		return ( -1 );
	}

	if (0 == fb_idx)
		req.buff		   = pPanel->pFbA;
	 else
		req.buff		   = (void *)((UInt32)pPanel->pFbA +
                                      DSI_Display_Info.width * DSI_Display_Info.height * INPUT_BPP);

	req.lineLenP	   = img_width;
	req.lineCount      = img_height;
	req.buffBpp 	   = INPUT_BPP;
	req.timeOut_ms     = 100;
	req.multiLLI	   = false;
	//printk(KERN_ERR "SSSSK buf=%08x, linelenp = %d, linecnt =%d\n", (u32)req.buff, req.lineLenP, req.lineCount);
	req.cslLcdCbRef = NULL;
	dispdrv_cb = apiCb;

	if( apiCb != NULL )
	   req.cslLcdCb = dsi_cb;
	else
	   req.cslLcdCb = NULL;

	dsi_setwindow(drvH);

	if ( CSL_DSI_UpdateCmVc ( pPanel->dsiCmVcHandle, &req ) != CSL_LCD_OK )
	{
		LCD_DBG ( LCD_DBG_ERR_ID, "[DISPDRV] %s: ERROR ret by "
			"CSL_DSI_UpdateCmVc\n\r", __FUNCTION__ );
		res = -1;
	}

	//LCD_DBG ( LCD_DBG_ID, "[DISPDRV] -%s\r\n", __FUNCTION__ );
	return ( res );
}
//*****************************************************************************
//
// Function Name: DISPDRV__Update_ExtFb
// 
// Description:   DMA/OS Update using EXT frame buffer
//
//*****************************************************************************
Int32 DISPDRV_Update_ExtFb ( 
    DISPDRV_HANDLE_T        drvH, 
    void                    *pFb,
    DISPDRV_CB_API_1_1_T    apiCb
    )
{
    DISPDRV_PANEL_T *pPanel = (DISPDRV_PANEL_T *)drvH;
    CSL_LCD_UPD_REQ_T   req;
    Int32               res  = 0;

    LCD_DBG ( LCD_DBG_ID, "[DISPDRV] +%s\r\n", __FUNCTION__ );

    DISPDRV_CHECK_PTR_2_RET( drvH, &panel[0], &panel[1], __FUNCTION__ );
    
    if ( pPanel->pwrState != DISP_PWR_SLEEP_OFF )
    {
        LCD_DBG ( LCD_DBG_ERR_ID, "[DISPDRV] +%s: Skip Due To Power State\r\n", 
            __FUNCTION__ );
        return ( -1 );
    }
    
    req.buff           = pFb;
    req.lineLenP       = Disp_Info.width;
    req.lineCount      = Disp_Info.height;
    req.buffBpp        = 2; //4; //@HW
    req.timeOut_ms     = 100; // SKC 1000

    req.cslLcdCbRec.cslH            = pPanel->clientH;
    req.cslLcdCbRec.dispDrvApiCbRev = DISP_DRV_CB_API_REV_1_1;
    req.cslLcdCbRec.dispDrvApiCb    = (void*) apiCb;
    req.cslLcdCbRec.dispDrvApiCbP1  = pFb;

    if( apiCb != NULL )
       req.cslLcdCb = DISPDRV_Cb;
    else
       req.cslLcdCb = NULL;
        
    if ( CSL_DSI_UpdateCmVc ( pPanel->dsiCmVcHandle, &req, FALSE ) != CSL_LCD_OK )
    {
        LCD_DBG ( LCD_DBG_ERR_ID, "[DISPDRV] %s: ERROR ret by "
            "CSL_DSI_UpdateCmVc\n\r", __FUNCTION__ );
        res = -1;    
    }
        
    LCD_DBG ( LCD_DBG_ID, "[DISPDRV] -%s\n\r", __FUNCTION__ );
        
    return ( res );
}
/*
 *
 * Function Name:  cslDsiAfeLdoSetState
 *
 * Description:    AFE LDO Control
 *
 */
static void cslDsiAfeLdoSetState(DSI_HANDLE dsiH, DSI_LDO_STATE_t state)
{
#define DSI_LDO_HP_EN	  0x00000001
#define DSI_LDO_LP_EN	  0x00000002
#define DSI_LDO_CNTL_ENA  0x00000004
#define DSI_LDO_ISO_OUT	  0x00800000

	unsigned long ldo_val = 0;

	switch (state) {
	case DSI_LDO_HP:
		ldo_val = DSI_LDO_CNTL_ENA | DSI_LDO_HP_EN;
		break;
	case DSI_LDO_LP:
		ldo_val = DSI_LDO_CNTL_ENA | DSI_LDO_LP_EN;
		break;
	case DSI_LDO_OFF:
		ldo_val = DSI_LDO_CNTL_ENA | DSI_LDO_ISO_OUT;
		break;
	default:
		ldo_val = DSI_LDO_CNTL_ENA | DSI_LDO_HP_EN;
		LCD_DBG(LCD_DBG_ERR_ID, "[CSL DSI] %s: "
			"ERROR Invalid LDO State[%d] !\r\n", __func__,
			state);
		break;
	}

	if (dsiH->bus == 0)
		HW_REG_WRITE(0x3C004030, ldo_val);
	else
		HW_REG_WRITE(0x3C004034, ldo_val);

	OSTASK_Sleep(TICKS_IN_MILLISECONDS(1));
}
//*****************************************************************************
//
// Function Name: DISPDRV__GetCtl
// 
// Description:   
//
//*****************************************************************************
Int32 DISPDRV_GetCtl (
            DISPDRV_HANDLE_T    drvH, 
            DISPDRV_CTRL_ID_T   ctrlID, 
            void*               ctrlParams 
            )
{
    DISPDRV_PANEL_T *pPanel = (DISPDRV_PANEL_T *)drvH;
    Int32 res = -1;
    
    DISPDRV_CHECK_PTR_2_RET( drvH, &panel[0], &panel[1], __FUNCTION__ );
    
    switch ( ctrlID )
    {
        case DISPDRV_CTRL_ID_GET_FB_ADDR:
            ((DISPDRV_CTL_GET_FB_ADDR *)ctrlParams)->frame_buffer = 
                pPanel->pFbA;
            res = 0;
            break;
            
        case DISPDRV_CTRL_ID_GET_REG:
            res = DISPDRV_IoCtlRd( drvH, (DISPDRV_CTRL_RW_REG*)ctrlParams );
            break;
            
        default:
            LCD_DBG ( LCD_DBG_ERR_ID, "[DISPDRV] %s: CtrlId[%d] Not "
                "Implemented\n\r", __FUNCTION__, ctrlID );
            break;
    }
    
    return ( res );
}            
//*****************************************************************************
//
// Function Name:  DISPDRV_GenericRead
// 
// Parameters:     
//
// Description:    Able to read up to CSL_DSI_GetMaxRxMsgSize bytes back
//
//*****************************************************************************
static int DISPDRV_GenericRead( 
	DISPDRV_HANDLE_T 	drvH, 
	UInt8 			reg, 	   // register to read from
	UInt8* 			rx_buff,   // read buffer
	UInt32* 		rx_size    // no of bytes read back
	)
{
	DISPDRV_PANEL_T 		*pPanel = (DISPDRV_PANEL_T *)drvH;
	CSL_DSI_CMND_t      		msg;         
	volatile CSL_DSI_REPLY_t 	rxMsg;	    // CSL DSI RX message
	UInt8               		txData[1];  // DCS Rd Command
	Int32               		res = 0;
	CSL_LCD_RES_T       		cslRes;
    

	msg.dsiCmnd    = DSI_DT_SH_DCS_RD_P0;
	msg.msg        = &txData[0];
	msg.msgLen     = 1;
	msg.vc         = DISPDRV_VC;
	msg.isLP       = DISPDRV_CMND_IS_LP;
	msg.isLong     = FALSE;
	msg.endWithBta = TRUE;

	rxMsg.pReadReply = rx_buff;
	msg.reply        = (CSL_DSI_REPLY_t *)&rxMsg;

	*rx_size = 0;

	txData[0] = reg;                                    
	cslRes = CSL_DSI_SendPacket( pPanel->clientH, &msg, FALSE );
	if( (cslRes != CSL_LCD_OK) || ((rxMsg.type & DSI_RX_TYPE_READ_REPLY)==0) )
	{
		LCD_DBG( LCD_DBG_ERR_ID, "[DISPDRV] %s: ERR"
			"Reading error\n\r", 
			__FUNCTION__);
		res = -1;    
		goto failed;
	}
	*rx_size = rxMsg.readReplySize;

	LCD_DBG( LCD_DBG_INIT_ID, "[DISPDRV] %s: We've Received %d Byte(s) "
		"Reading From Reg[0x%02X]\n",
		__FUNCTION__, (unsigned int)rxMsg.readReplySize, reg );
		 
failed:    
    	return(res);	
} // DISPDRV_GenericRead
Int32 dsi_set_dev_border(DISPDRV_HANDLE_T handle, int img_width, int img_height)
{
	dsic_panel_t *dev = (dsic_panel_t *)handle;

	if((DSI_Display_Info.width < img_width) || (DSI_Display_Info.height < img_height)) {
        LCD_DBG ( LCD_DBG_ERR_ID, "[DISPDRV] %s: img width %d is bigger than panel size %d!\n\r",
                   __FUNCTION__, img_width, DSI_Display_Info.width );
        LCD_DBG ( LCD_DBG_ERR_ID, "[DISPDRV] %s: img height %d is bigger than panel size %d!\n\r",
                   __FUNCTION__, img_height, DSI_Display_Info.height );
		return -1;
	}

    dev->col_start = (DSI_Display_Info.width - img_width) / 2;
	dev->col_end = DSI_Display_Info.width - (DSI_Display_Info.width - img_width) / 2 - 1;
	dev->row_start = (DSI_Display_Info.height - img_height) / 2;
	dev->row_end = DSI_Display_Info.height - (DSI_Display_Info.height - img_height) / 2 - 1;
	return 0;
}
//*****************************************************************************
//
// Function Name: dsic_init
// 
// Description:   
//
//*****************************************************************************
Int32 dsic_init ( void )
{
    Int32 res = 0;

    if(     panel[0].drvState != DRV_STATE_INIT 
         && panel[0].drvState != DRV_STATE_OPEN  
         && panel[1].drvState != DRV_STATE_INIT  
         && panel[1].drvState != DRV_STATE_OPEN  )
    {     
        LCD_DBG ( LCD_DBG_INIT_ID, "[DISPDRV] %s: OK\n\r", __FUNCTION__ );
        panel[0].drvState = DRV_STATE_INIT;
        panel[1].drvState = DRV_STATE_INIT;
    } 
    else
    {
        LCD_DBG ( LCD_DBG_INIT_ID, "[DISPDRV] %s: OK, Already Init\n\r",
            __FUNCTION__ );
    }   
    return ( res );
}
/*
 *
 * Function Name:  cslDsi1EofDma
 *
 * Description:    DSI Controller 1 EOF DMA
 *
 */
static void cslDsi1EofDma(DMA_VC4LITE_CALLBACK_STATUS status)
{
	DSI_HANDLE dsiH = &dsiBus[1];

	if (status != DMA_VC4LITE_CALLBACK_SUCCESS) {
		LCD_DBG(LCD_DBG_ERR_ID, "[CSL DSI] %s: ERR DMA!\n",
			__func__);
	}

	OSSEMAPHORE_Release(dsiH->semaDma);
}
//*****************************************************************************
//
// Function Name:  CSL_TECTL_VC4L_CloseInput
// 
// Description:    'Close' TE Input
//                 
//*****************************************************************************
Int32 CSL_TECTL_VC4L_CloseInput(UInt32 teIn)
{

	if (teIn >= TE_IN_COUNT) {
		LCD_DBG(LCD_DBG_ID, "[CSL TECTL] CSL_TECTL_VC4L_CloseInput: "
			"ERROR Invalid TE Input Specified \r\n");
		return (-1);
	}

	if (!teCslCfg[teIn].inUse) {
		LCD_DBG(LCD_DBG_ID, "[CSL TECTL] CSL_TECTL_VC4L_CloseInput: "
			"WARNING TE Input Not Configured \r\n");
		return (-1);
	}
	// disable TE MUX Output 
	chal_te_set_mux_out(TE_VC4L_IN_DISABLE, teCslCfg[teIn].teOut);
	teCslCfg[teIn].inUse = FALSE;

	return (0);
}
//*****************************************************************************
//
// Function Name: BCM91008_ALEX_Init
// 
// Description:   Reset Driver Info
//
//*****************************************************************************
Int32 DISPDRV_Init(struct dispdrv_init_parms *parms, DISPDRV_HANDLE_T *handle)
{
	Int32 res = 0;
	DISPDRV_PANEL_T *pPanel;

	pPanel = &panel[0];

	if (pPanel->drvState == DRV_STATE_OFF) {

		LCD_DBG(LCD_DBG_INIT_ID, "[DISPDRV] %s: Bus        %d \n",
			__func__, parms->w0.bits.bus_type);
		LCD_DBG(LCD_DBG_INIT_ID, "[DISPDRV] %s: BootMode   %d \n",
			__func__, parms->w0.bits.boot_mode);
		LCD_DBG(LCD_DBG_INIT_ID, "[DISPDRV] %s: BusNo      %d \n",
			__func__, parms->w0.bits.bus_no);
		LCD_DBG(LCD_DBG_INIT_ID, "[DISPDRV] %s: col_mode_i %d \n",
			__func__, parms->w0.bits.col_mode_i);
		LCD_DBG(LCD_DBG_INIT_ID, "[DISPDRV] %s: col_mode_o %d \n",
			__func__, parms->w0.bits.col_mode_o);
		LCD_DBG(LCD_DBG_INIT_ID, "[DISPDRV] %s: te_input   %d \n",
			__func__, parms->w0.bits.te_input);

		LCD_DBG(LCD_DBG_INIT_ID, "[DISPDRV] %s: API Rev    %d \n",
			__func__, parms->w1.bits.api_rev);
		LCD_DBG(LCD_DBG_INIT_ID, "[DISPDRV] %s: Rst 0      %d \n",
			__func__, parms->w1.bits.lcd_rst0);
		LCD_DBG(LCD_DBG_INIT_ID, "[DISPDRV] %s: Rst 1      %d \n",
			__func__, parms->w1.bits.lcd_rst1);
		LCD_DBG(LCD_DBG_INIT_ID, "[DISPDRV] %s: Rst 2      %d \n",
			__func__, parms->w1.bits.lcd_rst2);

		if ((u8)parms->w1.bits.api_rev != RHEA_LCD_BOOT_API_REV) {
			LCD_DBG(LCD_DBG_ERR_ID, "[DISPDRV] %s: "
				"Boot Init API Rev Mismatch(%d.%d vs %d.%d)\n",
				__func__,
				(parms->w1.bits.api_rev & 0xF0) >> 8,
				(parms->w1.bits.api_rev & 0x0F),
				(RHEA_LCD_BOOT_API_REV & 0xF0) >> 8,
				(RHEA_LCD_BOOT_API_REV & 0x0F));
			return (-1);
		}
//*****************************************************************************
//
// Function Name: DISPDRV__Close
// 
// Description:   Close The Driver
//
//*****************************************************************************
Int32 DISPDRV_Close(DISPDRV_HANDLE_T drvH)
{
	Int32 res = 0;
	DISPDRV_PANEL_T *pPanel = (DISPDRV_PANEL_T *)drvH;

	if (CSL_DSI_CloseCmVc(pPanel->dsiCmVcHandle)) {
		LCD_DBG(LCD_DBG_ERR_ID, "[DISPDRV] %s: ERROR, "
			"Closing Command Mode Handle\n\r", __FUNCTION__);
		return (-1);
	}

	if (CSL_DSI_CloseClient(pPanel->clientH) != CSL_LCD_OK) {
		LCD_DBG(LCD_DBG_ERR_ID,
			"[DISPDRV] %s: ERROR, Closing DSI Client\n",
			__FUNCTION__);
		return (-1);
	}

	if (CSL_DSI_Close(pPanel->busNo) != CSL_LCD_OK) {
		LCD_DBG(LCD_DBG_ERR_ID,
			"[DISPDRV] %s: ERR Closing DSI Controller\n",
			__FUNCTION__);
		return (-1);
	}

	if (pPanel->isTE)
		DISPDRV_TeOff(pPanel);

	if (brcm_disable_dsi_pll_clocks(pPanel->busNo)) {
		LCD_DBG(LCD_DBG_ERR_ID,
			"[DISPDRV] %s: ERROR to disable the pll clock\n",
			__FUNCTION__);
		return (-1);
	}

	pPanel->pwrState = STATE_PWR_OFF;
	pPanel->drvState = DRV_STATE_INIT;
	LCD_DBG(LCD_DBG_INIT_ID, "[DISPDRV] %s: OK\n", __FUNCTION__);

	return (res);
}
//*****************************************************************************
//
// Function Name: DISPDRV__Stop
// 
// Description:   
//
//*****************************************************************************
Int32 DISPDRV_Stop (struct pi_mgr_dfs_node* dfs_node)
{
    if (brcm_disable_dsi_lcd_clocks(dfs_node,0))
    {
        LCD_DBG ( LCD_DBG_ERR_ID, "[DISPDRV] %s: ERROR to enable the clock\n",
            __FUNCTION__  );
        return ( -1 );
    }


    return ( 0 );
}
//*****************************************************************************
//
// Function Name: DISPDRV__Close
// 
// Description:   Close The Driver
//
//*****************************************************************************
Int32 DISPDRV_Close ( DISPDRV_HANDLE_T drvH ) 
{
    Int32                   res = 0;
    DISPDRV_PANEL_T   *pPanel = (DISPDRV_PANEL_T *)drvH;
    
    DISPDRV_CHECK_PTR_2_RET( drvH, &panel[0], &panel[1], __FUNCTION__ );
    
    pPanel->pFb  = NULL;
    pPanel->pFbA = NULL;
    
    if ( CSL_DSI_CloseCmVc ( pPanel->dsiCmVcHandle ) ) 
    {
        LCD_DBG ( LCD_DBG_ERR_ID, "[DISPDRV] %s: ERROR, "
            "Closing Command Mode Handle\n\r", __FUNCTION__);
        return ( -1 );
    }
    
    if ( CSL_DSI_CloseClient ( pPanel->clientH ) != CSL_LCD_OK )
    {
        LCD_DBG ( LCD_DBG_ERR_ID, "[DISPDRV] %s: ERROR, Closing DSI Client\n\r",
            __FUNCTION__);
        return ( -1 );
    }
    
    if ( CSL_DSI_Close( pPanel->busId ) != CSL_LCD_OK )
    {
        LCD_DBG ( LCD_DBG_ERR_ID, "[DISPDRV] %s: ERR Closing DSI Controller\n\r",
            __FUNCTION__ );
        return ( -1 );
    }
    
   	DISPDRV_TeOff ( pPanel );


    pPanel->pwrState = DISP_PWR_OFF;
    pPanel->drvState = DRV_STATE_INIT;
    LCD_DBG ( LCD_DBG_INIT_ID, "[DISPDRV] %s: OK\n\r", __FUNCTION__ );
    
    return ( res );
}
//*****************************************************************************
//
// Function Name: DISPDRV__Stop
// 
// Description:   
//
//*****************************************************************************
Int32 DISPDRV_Stop(DISPDRV_HANDLE_T drvH, struct pi_mgr_dfs_node *dfs_node)
{
	DISPDRV_PANEL_T *pPanel = (DISPDRV_PANEL_T *)drvH;

	if (brcm_disable_dsi_lcd_clocks(dfs_node, pPanel->busNo)) {
		LCD_DBG(LCD_DBG_ERR_ID,
			"[DISPDRV] %s: ERROR to enable the clock\n",
			__FUNCTION__);
		return (-1);
	}

	return (0);
}
//*****************************************************************************
//
// Function Name:  CSL_TECTL_VC4L_CfgInput
// 
// Description:    Configure TE Input
//                 
//*****************************************************************************
static Int32 csl_tectl_vc4l_CfgInput(UInt32 teIn, pTECTL_CFG teCfg)
{
	Int32 res = 0;

	if (teIn >= TE_IN_COUNT) {
		LCD_DBG(LCD_DBG_ID, "[CSL TECTL] csl_tectl_vc4l_CfgInput: "
			"ERROR Invalid TE Input \r\n");
		return (-1);
	}
#if 0
	if (teCslCfg[teIn].inUse) {
		LCD_DBG(LCD_DBG_ID, "[CSL TECTL] csl_tectl_vc4l_CfgInput: "
			"ERROR TE Input Already In Use \r\n");
		return (-1);
	}
#endif

	if (teIn == TE_VC4L_IN_0_LCD) {
		teCslCfg[teIn].teIn_cHal = TE_VC4L_IN_0;	//  HERA's LCD_TE  input
	} else if (teIn == TE_VC4L_IN_1_DSI0) {
		teCslCfg[teIn].teIn_cHal = TE_VC4L_IN_1;	//  HERA's DSI0_TE input
	} else if (teIn == TE_VC4L_IN_2_DSI1) {
		teCslCfg[teIn].teIn_cHal = TE_VC4L_IN_2;	//  HERA's DSI1_TE input
	}

	teCslCfg[teIn].teCfg.hsync_line = teCfg->hsync_line;
	teCslCfg[teIn].teCfg.vsync_width = teCfg->vsync_width;
	teCslCfg[teIn].teCfg.sync_pol = teCfg->sync_pol;
	teCslCfg[teIn].teCfg.te_mode = teCfg->te_mode;

	if ((res = chal_te_cfg_input(teCslCfg[teIn].teIn_cHal,
				     &teCslCfg[teIn].teCfg)) != -1) {
		teCslCfg[teIn].inUse = TRUE;
	} else {
		teCslCfg[teIn].inUse = FALSE;
	}
	return (res);
}
//*****************************************************************************
//
// Function Name: DISPDRV__Init
// 
// Description:   Reset Driver Info
//
//*****************************************************************************
Int32 DISPDRV_Init ( unsigned int bus_width )
{
    Int32 res = 0;

    /* Temp */
    isFirstboot = 0;

    if(     panel[0].drvState != DRV_STATE_INIT 
         && panel[0].drvState != DRV_STATE_OPEN  
         && panel[1].drvState != DRV_STATE_INIT  
         && panel[1].drvState != DRV_STATE_OPEN  )
    {     
        LCD_DBG ( LCD_DBG_INIT_ID, "[DISPDRV] %s: OK\n\r", __FUNCTION__ );
        panel[0].drvState = DRV_STATE_INIT;
        panel[1].drvState = DRV_STATE_INIT;
    } 
    else
    {
        LCD_DBG ( LCD_DBG_INIT_ID, "[DISPDRV] %s: OK, Already Init\n\r",
            __FUNCTION__ );
    }   
    return ( res );
}
//*****************************************************************************
//
// Function Name: DISPDRV__Start
// 
// Description:   Configure For Updates
//
//*****************************************************************************
Int32 DISPDRV_Start (struct pi_mgr_dfs_node* dfs_node)
{
    if (brcm_enable_dsi_lcd_clocks(dfs_node,0,
    		DISPDRV_dsiCfg.hsBitClk.clkIn_MHz * 1000000,
                DISPDRV_dsiCfg.hsBitClk.clkInDiv,
                DISPDRV_dsiCfg.escClk.clkIn_MHz   * 1000000 / DISPDRV_dsiCfg.escClk.clkInDiv ))
    {
        LCD_DBG ( LCD_DBG_ERR_ID, "[DISPDRV] %s: ERROR to enable the clock\n",
            __FUNCTION__  );
        return ( -1 );
    }

    return ( 0 );
}
/*
 *
 * Function Name:  cslDsiWaitForInt
 *
 * Description:
 *
 */
static CSL_LCD_RES_T cslDsiWaitForInt(DSI_HANDLE dsiH, UInt32 tout_msec)
{
	OSStatus_t osRes;
	CSL_LCD_RES_T res = CSL_LCD_OK;

	osRes =
	    OSSEMAPHORE_Obtain(dsiH->semaInt, TICKS_IN_MILLISECONDS(tout_msec));

	if (osRes != OSSTATUS_SUCCESS) {
		cslDsiDisInt(dsiH);

		if (osRes == OSSTATUS_TIMEOUT) {
			LCD_DBG(LCD_DBG_ERR_ID, "[CSL DSI] %s: "
				"ERR Timed Out!\n", __func__);
			res = CSL_LCD_OS_TOUT;
		} else {
			LCD_DBG(LCD_DBG_ERR_ID, "[CSL DSI] %s: "
				"ERR OS Err...!\n", __func__);
			res = CSL_LCD_OS_ERR;
		}
	}
	return res;
}
//*****************************************************************************
//
// Function Name:  DISPDRV__IoCtlWr
// 
// Parameters:     
//
// Description:    IOCTL WR Test Code - DCS Wr With P0(no parm) or P1(1 parm)
//
//*****************************************************************************
static void DISPDRV_IoCtlWr( 
    DISPDRV_HANDLE_T       drvH,
    DISPDRV_CTRL_RW_REG*   acc 
    )
{
    if( acc->parmCount == 1 )
    { 
        DISPDRV_WrCmndP0 ( drvH, acc->cmnd );
        LCD_DBG ( LCD_DBG_INIT_ID, "[DISPDRV] %s: DSC+P0 "
            "DCS[0x%08X]\n\r", __FUNCTION__, (unsigned int)acc->cmnd );
    }
    else if( acc->parmCount == 2 )
    {
        DISPDRV_WrCmndP1 ( drvH, acc->cmnd, *((UInt8*)acc->pBuff) );
        LCD_DBG ( LCD_DBG_INIT_ID, "[DISPDRV] %s: DSC+P1 "
            "DCS[0x%08X] P[0x%08X]\n\r", __FUNCTION__, 
            (unsigned int)acc->cmnd, (unsigned int)*((UInt8*)acc->pBuff) );
    }
    else
    {
        LCD_DBG ( LCD_DBG_ERR_ID, "[DISPDRV] DISPDRV__IoCtlWr: "
            "Only DCS with 0|1 Parm Supported\n" );
    }        
} // DISPDRV__IoCtlWr   
static int DISPDRV_ReadID(DISPDRV_HANDLE_T drvH, UInt8 reg)
{
	DISPDRV_PANEL_T *pPanel = (DISPDRV_PANEL_T *)drvH;
	CSL_DSI_CMND_t msg;
	volatile CSL_DSI_REPLY_t rxMsg;	// DSI RX message
	UInt8 txData[1];	// DCS Rd Command
	volatile UInt8 rxBuff[3];	// Read Buffer

	CSL_LCD_RES_T cslRes;

	msg.dsiCmnd = DSI_DT_SH_DCS_RD_P0;
	msg.msg = &txData[0];
	msg.msgLen = 1;
	msg.vc = DISPDRV_VC;
	msg.isLP = DISPDRV_CMND_IS_LP;
	msg.isLong = FALSE;
	msg.endWithBta = TRUE;

	rxMsg.pReadReply = (UInt8 *)&rxBuff[0];
	msg.reply = (CSL_DSI_REPLY_t *)&rxMsg;

	txData[0] = reg;
	cslRes = CSL_DSI_SendPacket(pPanel->clientH, &msg, FALSE);
	if ((cslRes != CSL_LCD_OK)
	    || ((rxMsg.type & DSI_RX_TYPE_READ_REPLY) == 0)) {
		LCD_DBG(LCD_DBG_ERR_ID,
			"[DISPDRV] %s: ERR" "Reading From Reg[0x%08X]\n\r",
			__FUNCTION__, (unsigned int)reg);
		return -1;

	}

	printk("[LCD] rxBuff[0]=0x%x, rxBuff[1]=0x%x, rxBuff[2]=0x%x\n", rxBuff[0], rxBuff[1], rxBuff[2]);
	
     if((rxBuff[0] == 0x5B) && (rxBuff[1] == 0x88) && (rxBuff[2] == 0x60)){
        return LCD_PANEL_ID_ONE_L3;
     }else if((rxBuff[0] == 0x5B) && (rxBuff[1] == 0x89) && (rxBuff[2] == 0x60)){
        return LCD_PANEL_ID_TWO_L4;
   	 }
     else{
        return LCD_PANEL_ID_NOT_SET/*DEFAULT*/;
     }

//	return (rxBuff[0]);

}				// bcm91008_ale
//*****************************************************************************
//
// Function Name: DISPDRV__Start
// 
// Description:   Configure For Updates
//
//*****************************************************************************
Int32 DISPDRV_Start(DISPDRV_HANDLE_T drvH, struct pi_mgr_dfs_node *dfs_node)
{
	DISPDRV_PANEL_T *pPanel = (DISPDRV_PANEL_T *)drvH;

	if (brcm_enable_dsi_lcd_clocks(dfs_node, pPanel->busNo,
				       DISPDRV_dsiCfg.hsBitClk.clkIn_MHz *
				       1000000,
				       DISPDRV_dsiCfg.hsBitClk.clkInDiv,
				       DISPDRV_dsiCfg.escClk.clkIn_MHz *
				       1000000 /
				       DISPDRV_dsiCfg.escClk.clkInDiv)) {
		LCD_DBG(LCD_DBG_ERR_ID,
			"[DISPDRV] %s: ERROR to enable the clock\n",
			__FUNCTION__);
		return (-1);
	}

	return (0);
}
//*****************************************************************************
//
// Function Name:  CSL_TECTL_VC4L_OpenInput
// 
// Description:    'Open' TE Input 
//                 
//*****************************************************************************
Int32 CSL_TECTL_VC4L_OpenInput(UInt32 teIn,	// which TE Input Pin
			       UInt32 teOut,	// TECTL MUX Output ( SMI/SPI/DSI Input Selection )
			       pTECTL_CFG teCfg	// TE Configuration
    )
{

	if (teIn >= TE_IN_COUNT) {
		LCD_DBG(LCD_DBG_ID, "[CSL TECTL] CSL_TECTL_VC4L_OpenInput: "
			"ERROR Invalid TE Input \r\n");
		return (-1);
	}

	if (csl_tectl_vc4l_CfgInput(teIn, teCfg) == -1) {
		return (-1);
	}

	teCslCfg[teIn].teOut = teOut;
	chal_te_set_mux_out(teCslCfg[teIn].teIn_cHal, teOut);

	return (0);
}
//*****************************************************************************
//
// Function Name: dsic_set_control
// 
// Description:   
//
//*****************************************************************************
Int32 dsic_set_control ( 
        DISPDRV_HANDLE_T    drvH, 
        DISPDRV_CTRL_ID_T   ctrlID, 
        void*               ctrlParams 
        )
{
    Int32 res = -1;
   
    switch ( ctrlID )
    {
        case DISPDRV_CTRL_ID_SET_REG:
            dsi_ioctlwr( drvH, (DISPDRV_CTRL_RW_REG*)ctrlParams );
            res = 0;
            break;
    
        default:
            LCD_DBG ( LCD_DBG_ERR_ID, "[DISPDRV] %s: "
                "CtrlId[%d] Not Implemented\n\r", __FUNCTION__, ctrlID );
            break;    
    }
    return ( res );
}
/*
 *
 * Function Name:  CSL_DSI_SendPacketTrigger
 *
 * Description:    Send TRIGGER Message
 *
 */
CSL_LCD_RES_T CSL_DSI_SendTrigger(CSL_LCD_HANDLE client, UInt8 trig)
{
	DSI_HANDLE dsiH;
	DSI_CLIENT clientH;
	CSL_LCD_RES_T res;

	clientH = (DSI_CLIENT) client;
	dsiH = (DSI_HANDLE)clientH->lcdH;

	if (!clientH->hasLock)
		OSSEMAPHORE_Obtain(dsiH->semaDsi, TICKS_FOREVER);

	if (dsiH->ulps) {
		LCD_DBG(LCD_DBG_ERR_ID, "[CSL DSI][%d] %s: "
			"ERR, Link Is In ULPS\n", dsiH->bus, __func__);
		res = CSL_LCD_BAD_STATE;
		goto exit_err;
	}

	chal_dsi_clr_status(dsiH->chalH, 0xFFFFFFFF);

#ifdef __CSL_DSI_USE_INT__
	cslDsiEnaIntEvent(dsiH, (UInt32)CHAL_DSI_ISTAT_TXPKT1_DONE);
#endif
	chal_dsi_tx_trig(dsiH->chalH, TX_PKT_ENG_1, trig);

#ifdef __CSL_DSI_USE_INT__
	res = cslDsiWaitForInt(dsiH, 100);
#else
	res = cslDsiWaitForStatAny_Poll(dsiH,
					CHAL_DSI_STAT_TXPKT1_DONE, NULL, 100);
#endif

exit_err:
	if (!clientH->hasLock)
		OSSEMAPHORE_Release(dsiH->semaDsi);

	return res;
}
//*****************************************************************************
//
// Function Name: DISPDRV__SetCtl
// 
// Description:   
//
//*****************************************************************************
Int32 DISPDRV_SetCtl ( 
        DISPDRV_HANDLE_T    drvH, 
        DISPDRV_CTRL_ID_T   ctrlID, 
        void*               ctrlParams 
        )
{
    Int32 res = -1;
    
    DISPDRV_CHECK_PTR_2_RET( drvH, &panel[0], &panel[1], __FUNCTION__ );
    
    switch ( ctrlID )
    {
        case DISPDRV_CTRL_ID_SET_REG:
            DISPDRV_IoCtlWr( drvH, (DISPDRV_CTRL_RW_REG*)ctrlParams );
            res = 0;
            break;
    
        default:
            LCD_DBG ( LCD_DBG_ERR_ID, "[DISPDRV] %s: "
                "CtrlId[%d] Not Implemented\n\r", __FUNCTION__, ctrlID );
            break;    
    }
    return ( res );
}