Beispiel #1
0
/**
    \brief This function creates a task and allocates all the necessary resources. Note that creating a task do not start it automatically, an explicit call to IWTaskStart must be made.

    \param pFunc        Pointer to the function that will be executed in the task context.
    \param Priority     Priority of the task. The minimum priority is 0, the maximum is 255.
    \param StackSize    Size of the stack to allocate for this task.
    \param pHandle      Pointer to the handle buffer.

    \return The call result:
            - TM_OK: the call was successful
            - TMDL_ERR_DLHDMICEC_NO_RESOURCES: the resource is not available
            - TMDL_ERR_DLHDMICEC_INCONSISTENT_PARAMS: an input parameter is
              inconsistent

******************************************************************************/
tmErrorCode_t tmdlHdmiTxIWTaskCreate
(
    tmdlHdmiTxIWFuncPtr_t     pFunc,
    UInt8           priority,
    UInt16          stackSize,
    tmdlHdmiTxIWTaskHandle_t  *pHandle
)
{
    UInt32 i;

    /* check that input pointer is not NULL */
    RETIF(pFunc == Null, TMDL_ERR_DLHDMICEC_INCONSISTENT_PARAMS)

    /* check that input pointer is not NULL */
    RETIF(pHandle == Null, TMDL_ERR_DLHDMICEC_INCONSISTENT_PARAMS)

    /* search for available task slot */
    for(i = 0; i < MAX_TASKS; i++)
    {
        if (taskTable[i].created == False)
            break;

    }
    RETIF(i >= MAX_TASKS, TMDL_ERR_DLHDMICEC_NO_RESOURCES)

    /* store task parameters into the dedicated structure */
    taskTable[i].priority = priority;
    taskTable[i].stackSize = stackSize;
    taskTable[i].associatedTask = pFunc;
    taskTable[i].created = True;

    *pHandle = (tmdlHdmiTxIWTaskHandle_t)i;

    return(TM_OK);
}
Beispiel #2
0
/*============================================================================*/
tmErrorCode_t
checkUnitSetDis
(
    tmUnitSelect_t   txUnit,
    tmHdmiTxobject_t **ppDis
)
{
    /* Return error if unit numbr is out of range */
    RETIF(txUnit < tmUnit0, TMBSL_ERR_HDMI_BAD_UNIT_NUMBER)
//	printk(KERN_INFO "[hycho00] -- 1\n");
    RETIF(txUnit >= HDMITX_UNITS_MAX, TMBSL_ERR_HDMI_BAD_UNIT_NUMBER)
//	printk(KERN_INFO "[hycho00] -- 2\n");

    /* Point to unit's Device Instance Structure */
    *ppDis = &gHdmiTxInstance[txUnit];

    /* Return if this device instance is not initialised */
    if(!(*ppDis)->bInitialized)
    {
        printk(KERN_ERR "[HDMI] TMBSL_ERR_HDMI_NOT_INITIALIZED  %s %d\n",__func__,__LINE__);
        return TMBSL_ERR_HDMI_NOT_INITIALIZED;
    }
//	printk(KERN_INFO "[hycho00] -- 3\n");
    return TM_OK;
}
tmErrorCode_t 
tmdlHdmiTxIWSemaphoreCreate(tmdlHdmiTxIWSemHandle_t *pHandle)
{

    
    static int i = 0;
    struct semaphore * mutex[3];
    // check that input pointer is not NULL
    RETIF(pHandle == Null, TMDL_ERR_DLHDMITX_INCONSISTENT_PARAMS)
       
    mutex[0] = &mutex0;
    mutex[1] = &mutex1;
    mutex[2] = &mutex2;

    if (i > 2 || i < 0)
    {
        printk("%s,create semphore error\n", __func__);
        return -1;
    }
    *pHandle = (tmdlHdmiTxIWSemHandle_t)mutex[i];
    i++;

    RETIF(pHandle == NULL, TMDL_ERR_DLHDMITX_NO_RESOURCES)

    return(TM_OK);
}
Beispiel #4
0
/*============================================================================*/
tmErrorCode_t
setHwRegisters
(
    tmHdmiTxobject_t *pDis,
    UInt16 regShadPageAddr,
    UInt8 *pData,
    UInt16 lenData
)
{
    tmErrorCode_t   err;        /* Error code */
    UInt8           regShad;    /* The index to the register's shadow copy */
    UInt8           regPage;    /* The index to the register's page        */
    UInt8           regAddr;    /* The register's address on the page      */
    UInt8           newRegPage; /* The register's new page number          */
    tmbslHdmiTxSysArgs_t sysArgs; /* Arguments passed to system function   */

    /* Unpack 1st register's shadow index, page index and address */
    regShad = SPA2SHAD(regShadPageAddr);
    regPage = SPA2PAGE(regShadPageAddr);
    regAddr = SPA2ADDR(regShadPageAddr);
    newRegPage = kPageIndexToPage[regPage];

    /* Check length does not overflow page */
    RETIF_BADPARAM((regAddr+lenData) > E_REG_CURPAGE_ADR_W)

    /* Check 1st reg does not have a shadow - whole range assumed likewise */
    RETIF_BADPARAM(regShad != E_SNONE)

    /* Set page register if required - whole range is on same page */
    if (pDis->curRegPage != newRegPage)
    {
        /* All non-OK results are errors */
        sysArgs.slaveAddr       = pDis->uHwAddress;
        sysArgs.firstRegister   = E_REG_CURPAGE_ADR_W;
        sysArgs.lenData         = 1;
        sysArgs.pData           = &newRegPage;
        err = pDis->sysFuncWrite(&sysArgs);
        RETIF(err != TM_OK, TMBSL_ERR_HDMI_I2C_WRITE)
        pDis->curRegPage = newRegPage;
    }

    /* Write to I2C register range - all non-OK results are errors */
    sysArgs.slaveAddr       = pDis->uHwAddress;
    sysArgs.firstRegister   = regAddr;
    sysArgs.lenData         = (UInt8)lenData;
    sysArgs.pData           = pData;
    err = pDis->sysFuncWrite(&sysArgs);

    if (err == TM_OK)
    {
        return TM_OK;

    }
    else
    {
        printk(KERN_ERR "[HDMI] TMBSL_ERR_HDMI_I2C_WRITE  %s %d\n",__func__,__LINE__);
        return TMBSL_ERR_HDMI_I2C_WRITE;
    }
}
Beispiel #5
0
/*============================================================================*/
tmErrorCode_t
setHwRegister
(
    tmHdmiTxobject_t *pDis,
    UInt16  regShadPageAddr,
    UInt8   regValue
)
{
    tmErrorCode_t   err;        /* Error code */
    UInt8           regShad;    /* The index to the register's shadow copy */
    UInt8           regPage;    /* The index to the register's page        */
    UInt8           regAddr;    /* The register's address on the page      */
    UInt8           newRegPage; /* The register's new page number          */
    tmbslHdmiTxSysArgs_t sysArgs; /* Arguments passed to system function   */

    /* Unpack register shadow index, page index and address */
    regShad = SPA2SHAD(regShadPageAddr);
    regPage = SPA2PAGE(regShadPageAddr);
    regAddr = SPA2ADDR(regShadPageAddr);
    newRegPage = kPageIndexToPage[regPage];

    /* Set page register if required */
    if (pDis->curRegPage != newRegPage)
    {
        /* All non-OK results are errors */
        sysArgs.slaveAddr       = pDis->uHwAddress;
        sysArgs.firstRegister   = E_REG_CURPAGE_ADR_W;
        sysArgs.lenData         = 1;
        sysArgs.pData           = &newRegPage;
        err = pDis->sysFuncWrite(&sysArgs);
        RETIF(err != TM_OK, TMBSL_ERR_HDMI_I2C_WRITE)
        pDis->curRegPage = newRegPage;
    }

    /* Set shadow copy */
    if (regShad != E_SNONE)
    {
        pDis->shadowReg[regShad] = regValue;
    }

    /* Write to I2C - all non-OK results are errors */
    sysArgs.slaveAddr       = pDis->uHwAddress;
    sysArgs.firstRegister   = regAddr;
    sysArgs.lenData         = 1;
    sysArgs.pData           = &regValue;
    err = pDis->sysFuncWrite(&sysArgs);

    if (err == TM_OK)
    {
        return TM_OK;

    }
    else
    {
        printk(KERN_ERR "[HDMI] TMBSL_ERR_HDMI_I2C_WRITE  %s %d\n",__func__,__LINE__);
        return TMBSL_ERR_HDMI_I2C_WRITE;
    }
}
Beispiel #6
0
/*============================================================================*/
tmErrorCode_t
setHwRegisterMsbLsb
(
    tmHdmiTxobject_t *pDis,
    UInt16  regShadPageAddr,
    UInt16  regWord
)
{
    tmErrorCode_t   err;        /* Error code */
    UInt8           regPage;    /* The index to the register's page        */
    UInt8           regAddr;    /* The register's address on the page      */
    UInt8           newRegPage; /* The register's new page number          */
    UInt8           msbLsb[2];  /* The bytes from regWord                  */
    tmbslHdmiTxSysArgs_t sysArgs; /* Arguments passed to system function   */

    /* Unpack register shadow index, page index and address */
    regPage = SPA2PAGE(regShadPageAddr);
    regAddr = SPA2ADDR(regShadPageAddr);
    newRegPage = kPageIndexToPage[regPage];

    /* Unpack regWord bytes, MSB first */
    msbLsb[0] = (UInt8)(regWord >> 8);
    msbLsb[1] = (UInt8)(regWord & 0xFF);

    /* Set page register if required */
    if (pDis->curRegPage != newRegPage)
    {
        /* All non-OK results are errors */
        sysArgs.slaveAddr       = pDis->uHwAddress;
        sysArgs.firstRegister   = E_REG_CURPAGE_ADR_W;
        sysArgs.lenData         = 1;
        sysArgs.pData           = &newRegPage;
        err = pDis->sysFuncWrite(&sysArgs);
        RETIF(err != TM_OK, TMBSL_ERR_HDMI_I2C_WRITE)
        pDis->curRegPage = newRegPage;
    }

    /* No word registers are shadowed */

    /* Write to I2C - all non-OK results are errors */
    sysArgs.slaveAddr       = pDis->uHwAddress;
    sysArgs.firstRegister   = regAddr;
    sysArgs.lenData         = 2;
    sysArgs.pData           = &msbLsb[0];
    err = pDis->sysFuncWrite(&sysArgs);

    if (err == TM_OK)
    {
        return TM_OK;

    }
    else
    {
        printk(KERN_ERR "[HDMI] TMBSL_ERR_HDMI_I2C_WRITE  %s %d\n",__func__,__LINE__);
        return TMBSL_ERR_HDMI_I2C_WRITE;
    }
}
/*============================================================================*/
tmErrorCode_t
getHwRegister
(
    tmHdmiTxobject_t *pDis, 
    UInt16  regShadPageAddr, 
    UInt8   *pRegValue
)
{
    tmErrorCode_t   err;        /* Error code */
    UInt8           regShad;    /* The index to the register's shadow copy */
    UInt8           regPage;    /* The index to the register's page        */
    UInt8           regAddr;    /* The register's address on the page      */
    UInt8           newRegPage; /* The register's new page number          */
    tmbslHdmiTxSysArgs_t sysArgs; /* Arguments passed to system function   */

    /* Unpack register shadow index, page index and address */
    regShad = SPA2SHAD(regShadPageAddr);
    regPage = SPA2PAGE(regShadPageAddr);
    regAddr = SPA2ADDR(regShadPageAddr);
    newRegPage = kPageIndexToPage[regPage];
    
    /* Set page register if required */
    if (pDis->curRegPage != newRegPage)
    {
        /* All non-OK results are errors */
        sysArgs.slaveAddr       = pDis->uHwAddress;
        sysArgs.firstRegister   = E_REG_CURPAGE_ADR_W;
        sysArgs.lenData         = 1;
        sysArgs.pData           = &newRegPage;
        err = pDis->sysFuncWrite(&sysArgs);
        RETIF(err != TM_OK, TMBSL_ERR_HDMI_I2C_WRITE)
        pDis->curRegPage = newRegPage;
    }

    if ((regShad != E_SNONE) 
    && (regShadPageAddr != E_REG_P00_INT_FLAGS_0_RW)
    && (regShadPageAddr != E_REG_P00_INT_FLAGS_1_RW)
    && (regShadPageAddr != E_REG_P00_INT_FLAGS_2_RW))
    {
        /* Get shadow copy - shadowed registers can't be read */
        /* Don't read shadow copy of interrupt status flags! */
        *pRegValue = pDis->shadowReg[regShad];
        return TM_OK;
    }    
    else
    {
        /* Get I2C register - all non-OK results are errors */
        sysArgs.slaveAddr       = pDis->uHwAddress;
        sysArgs.firstRegister   = regAddr;
        sysArgs.lenData         = 1;
        sysArgs.pData           = pRegValue;
        err = pDis->sysFuncRead(&sysArgs);
        return (err == TM_OK) ? TM_OK : TMBSL_ERR_HDMI_I2C_READ;
    }
}
/*============================================================================*/
tmErrorCode_t
    tmbslTDA9989EdidGetAudioCapabilities
    (tmUnitSelect_t txUnit,
     tmbslHdmiTxEdidSad_t *pEdidAFmts, UInt aFmtLength, UInt *pAFmtsAvail, UInt8 *pAudioFlags) {
	tmHdmiTxobject_t *pDis;	/* Pointer to Device Instance Structure */
	tmErrorCode_t err;	/* Error code */
	UInt i;			/* Loop index */

	/* Check unit parameter and point to TX unit object */
	err = checkUnitSetDis(txUnit, &pDis);
	RETIF(err != TM_OK, err)

	    /* Check remaining parameter(s) */
	    RETIF_BADPARAM(pEdidAFmts == Null)
	    RETIF_BADPARAM(aFmtLength < 1)
	    RETIF_BADPARAM(pAFmtsAvail == Null)
	    RETIF_BADPARAM(pAudioFlags == Null)

	    if ((pDis->EdidStatus == HDMITX_EDID_READ) ||
		(pDis->EdidStatus == HDMITX_EDID_ERROR_CHK)) {
		/* allow if edid are read or if there are a chk error on an other block than block 0 */

		/* Copy the Device Instance Structure EdidAFmts descriptors to
		 * pEdidAFmts until we run out or no more space in structure.
		 */
		if (pDis->EdidSadCnt > 0) {
			for (i = 0; (i < (UInt) pDis->EdidSadCnt) && (i < aFmtLength); i++) {
				pEdidAFmts[i].ModeChans = pDis->EdidAFmts[i].ModeChans;
				pEdidAFmts[i].Freqs = pDis->EdidAFmts[i].Freqs;
				pEdidAFmts[i].Byte3 = pDis->EdidAFmts[i].Byte3;
			}
		} else {
			/* No pEdidAFmts to copy so set a zero format to be safe */
			pEdidAFmts[0].ModeChans = 0;
			pEdidAFmts[0].Freqs = 0;
			pEdidAFmts[0].Byte3 = 0;
		}

		/* Fill Audio Flags parameter */
		*pAudioFlags = ((pDis->EdidCeaFlags & 0x40) << 1);	/* Basic audio */
		if (pDis->EdidSinkAi == True) {
			*pAudioFlags += 0x40;	/* Mask in AI support */
		}

		/* Fill number of SADs available parameter */
		*pAFmtsAvail = pDis->EdidSadCnt;
	} else {
		/* Not allowed if EdidStatus value is not valid */
		err = TMBSL_ERR_HDMI_RESOURCE_NOT_AVAILABLE;
	}
	return err;
}
/*============================================================================*/
tmErrorCode_t
checkUnitSetDis
(
    tmUnitSelect_t   txUnit,
    tmHdmiTxobject_t **ppDis
)
{
    /* Return error if unit numbr is out of range */
    RETIF(txUnit < tmUnit0, TMBSL_ERR_HDMI_BAD_UNIT_NUMBER)
    RETIF(txUnit >= HDMITX_UNITS_MAX, TMBSL_ERR_HDMI_BAD_UNIT_NUMBER)

    /* Point to unit's Device Instance Structure */
    *ppDis = &gHdmiTxInstance[txUnit];

    /* Return if this device instance is not initialised */
    if(!(*ppDis)->bInitialized)
    {
        return TMBSL_ERR_HDMI_NOT_INITIALIZED;
    }

    return TM_OK;
}
/******************************************************************************
    \brief  This function destroys an existing semaphore.

    \param  Handle  Handle of the semaphore to be destroyed.

    \return The call result:
            - TM_OK: the call was successful
            - TMDL_ERR_DLHDMITX_BAD_HANDLE: the handle number is wrong

******************************************************************************/
tmErrorCode_t tmdlHdmiTxIWSemaphoreDestroy
(
    tmdlHdmiTxIWSemHandle_t handle
)
{
    RETIF(handle == False, TMDL_ERR_DLHDMITX_BAD_HANDLE);

    if (atomic_read((atomic_t*)&((struct semaphore *)handle)->count) < 1) {
        printk(KERN_ERR "release catched semaphore");
    }

    kfree((void*)handle);

    return(TM_OK);
}
/*============================================================================*/
tmErrorCode_t tmbslTDA9989EdidGetStatus(tmUnitSelect_t txUnit, UInt8 *puEdidStatus) {
	tmHdmiTxobject_t *pDis;	/* Pointer to Device Instance Structure */
	tmErrorCode_t err;	/* Error code */

	/* Check unit parameter and point to TX unit object */
	err = checkUnitSetDis(txUnit, &pDis);
	RETIF(err != TM_OK, err)

	    /* Check remaining parameter(s) */
	    RETIF_BADPARAM(puEdidStatus == Null)

	    if (puEdidStatus) {
		*puEdidStatus = pDis->EdidStatus;
	}

	return err;
}
/*============================================================================*/
tmErrorCode_t tmbslTDA9989EdidGetBlockCount(tmUnitSelect_t txUnit, UInt8 *puEdidBlockCount) {
	tmHdmiTxobject_t *pDis;	/* Pointer to Device Instance Structure */
	tmErrorCode_t err;	/* Error code */

	/* Check unit parameter and point to TX unit object */
	err = checkUnitSetDis(txUnit, &pDis);
	RETIF(err != TM_OK, err)

	    /* Check remaining parameter(s) */
	    RETIF_BADPARAM(puEdidBlockCount == Null)

	    if ((pDis->EdidStatus == HDMITX_EDID_READ) ||
		(pDis->EdidStatus == HDMITX_EDID_ERROR_CHK)) {
		/* allow if edid are read or if there are a chk error on an other block than block 0 */
		*puEdidBlockCount = pDis->EdidBlockCnt;
	} else {
		/* Not allowed if EdidStatus value is not valid */
		err = TMBSL_ERR_HDMI_RESOURCE_NOT_AVAILABLE;
	}

	return err;
}
/******************************************************************************
    \brief  This function creates a semaphore.

    \param  pHandle Pointer to the handle buffer.

    \return The call result:
            - TM_OK: the call was successful
            - TMDL_ERR_DLHDMITX_NO_RESOURCES: the resource is not available
            - TMDL_ERR_DLHDMITX_INCONSISTENT_PARAMS: an input parameter is
              inconsistent

******************************************************************************/
tmErrorCode_t tmdlHdmiTxIWSemaphoreCreate
(
    tmdlHdmiTxIWSemHandle_t *pHandle
)
{
    struct semaphore * mutex;

    /* check that input pointer is not NULL */
    RETIF(pHandle == Null, TMDL_ERR_DLHDMITX_INCONSISTENT_PARAMS)

    mutex = (struct semaphore *)kmalloc(sizeof(struct semaphore),GFP_KERNEL);
    if (!mutex) {
        printk(KERN_ERR "malloc failed in %s\n",__func__);
        return TMDL_ERR_DLHDMITX_NO_RESOURCES;
    }

    init_MUTEX(mutex);
    *pHandle = (tmdlHdmiTxIWSemHandle_t)mutex;

    RETIF(pHandle == NULL, TMDL_ERR_DLHDMITX_NO_RESOURCES)

    return(TM_OK);
}
/*============================================================================*/
tmErrorCode_t
setHwRegisterField
(
    tmHdmiTxobject_t *pDis, 
    UInt16  regShadPageAddr, 
    UInt8   fieldMask, 
    UInt8   fieldValue
)
{
    tmErrorCode_t   err;        /* Error code */
    UInt8           regShad;    /* The index to the register's shadow copy */
    UInt8           regPage;    /* The index to the register's page        */
    UInt8           regAddr;    /* The register's address on the page      */
    UInt8           newRegPage; /* The register's new page number          */
    UInt8           regValue;   /* The register's current value            */
    tmbslHdmiTxSysArgs_t sysArgs; /* Arguments passed to system function   */

    /* Unpack register shadow index, page index and address */
    regShad = SPA2SHAD(regShadPageAddr);
    regPage = SPA2PAGE(regShadPageAddr);
    regAddr = SPA2ADDR(regShadPageAddr);
    newRegPage = kPageIndexToPage[regPage];
   
    /* Set page register if required */
    if (pDis->curRegPage != newRegPage)
    {
        /* All non-OK results are errors */
        sysArgs.slaveAddr       = pDis->uHwAddress;
        sysArgs.firstRegister   = E_REG_CURPAGE_ADR_W;
        sysArgs.lenData         = 1;
        sysArgs.pData           = &newRegPage;
        err = pDis->sysFuncWrite(&sysArgs);
        RETIF(err != TM_OK, TMBSL_ERR_HDMI_I2C_WRITE)
        pDis->curRegPage = newRegPage;
    }

    if (regShad != E_SNONE)
    {
        /* Get shadow copy */
        regValue = pDis->shadowReg[regShad];
    }
    else
    {
        /* Read I2C register value.
         * All bitfield registers are either shadowed or can be read.
         */
        sysArgs.slaveAddr       = pDis->uHwAddress;
        sysArgs.firstRegister   = regAddr;
        sysArgs.lenData         = 1;
        sysArgs.pData           = &regValue;
        err = pDis->sysFuncRead(&sysArgs);
        RETIF(err != TM_OK, TMBSL_ERR_HDMI_I2C_READ)
    }

    /* Reset register bits that are set in the mask */
    regValue = regValue & (UInt8)(~fieldMask);

    /* Shift the field value left to align its bits with the mask */
    fieldValue <<= kMaskToShift[fieldMask];

    /* Reset shifted field bits that are not set in the mask */
    fieldValue &= fieldMask;

    /* Set the shifted bitfield */
    regValue |= fieldValue;

    /* Set shadow copy */
    if (regShad != E_SNONE)
    {
        pDis->shadowReg[regShad] = regValue;
    }

    /* Write to I2C - all non-OK results are errors */
    sysArgs.slaveAddr       = pDis->uHwAddress;
    sysArgs.firstRegister   = regAddr;
    sysArgs.lenData         = 1;
    sysArgs.pData           = &regValue;
    err = pDis->sysFuncWrite(&sysArgs);
    return (err == TM_OK) ? TM_OK : TMBSL_ERR_HDMI_I2C_WRITE;
}
Beispiel #15
0
/* Will only be used in ioctl(MTK_HDMI_AUDIO_VIDEO_ENABLE) */
static HDMI_STATUS hdmi_drv_init(void)
{
    int lcm_width, lcm_height;
    int tmpBufferSize;
		M4U_PORT_STRUCT portStruct;

    HDMI_FUNC();

    RETIF(p->output_mode == HDMI_OUTPUT_MODE_DPI_BYPASS, 0);

    p->hdmi_width = 1280;
    p->hdmi_height = 720;

    lcm_width = DISP_GetScreenWidth();
    lcm_height = DISP_GetScreenHeight();

    //printk("[hdmi]%s, hdmi_width=%d, hdmi_height=%d\n", __func__, p->hdmi_width, p->hdmi_height);
    HDMI_LOG("lcm_width=%d, lcm_height=%d\n", lcm_width, lcm_height);

    tmpBufferSize = lcm_width * lcm_height *4 * 4;

    temp_va = (unsigned int) vmalloc(tmpBufferSize);
    if (((void*) temp_va) == NULL)
    {
        HDMI_LOG("vmalloc %dbytes fail\n", tmpBufferSize);
        return -1;
    }

    // WDMA1
    if (m4u_alloc_mva(M4U_CLNTMOD_WDMA, 
						temp_va, 
						tmpBufferSize,
						0,
						0,
						&temp_mva_w))
    {
        HDMI_LOG("m4u_alloc_mva for temp_mva_w fail\n");
        return -1;
    }
		m4u_dma_cache_maint(M4U_CLNTMOD_WDMA, 
						temp_va, 
						tmpBufferSize,
						DMA_BIDIRECTIONAL);

	portStruct.ePortID = M4U_PORT_WDMA1;			 //hardware port ID, defined in M4U_PORT_ID_ENUM
	portStruct.Virtuality = 1;							 
	portStruct.Security = 0;
	portStruct.domain = 0;						//domain : 0 1 2 3
	portStruct.Distance = 1;
	portStruct.Direction = 0; 	
	m4u_config_port(&portStruct);

    HDMI_LOG("temp_va=0x%08x, temp_mva_w=0x%08x\n", temp_va, temp_mva_w);

    p->lcm_width = lcm_width;
    p->lcm_height = lcm_height;
    p->output_video_resolution = hdmi_params->init_config.vformat;
    p->output_audio_format = hdmi_params->init_config.aformat;

//#ifdef NEW_HDMI_ARCH
//    hdmi_display_path_overlay_config(true);
//#endif
	DISP_Config_Overlay_to_Memory(temp_mva_w, 1);

    //hdmi_dpi_config_clock(); // configure dpi clock

    //hdmi_dpi_power_switch(false);   // but dpi power is still off
    //hdmi_drv->suspend();

#if 0
    LCD_WaitForNotBusy();
    LCD_SetOutputMode(3); // LCD write to memory and LCM
#endif

    return HDMI_STATUS_OK;
}
/*============================================================================*/
tmErrorCode_t
    tmbslTDA9989HwGetCapabilities
    (tmUnitSelect_t txUnit, tmbslHdmiTxHwFeature_t deviceCapability, Bool *pFeatureSupported) {
	tmHdmiTxobject_t *pDis;
	tmErrorCode_t err = TM_OK;

	/* Check unit parameter and point to its object */
	err = checkUnitSetDis(txUnit, &pDis);
	RETIF(err != TM_OK, err)

	    RETIF_BADPARAM(pFeatureSupported == Null)

	    * pFeatureSupported = False;


	switch (deviceCapability) {
	case HDMITX_FEATURE_HW_HDCP:
		if ((pDis->uDeviceFeatures & E_MASKREG_P00_VERSION_not_h) == 0) {
			*pFeatureSupported = True;
		}
		break;
	case HDMITX_FEATURE_HW_SCALER:
		if ((pDis->uDeviceFeatures & E_MASKREG_P00_VERSION_not_s) == 0) {
			*pFeatureSupported = True;
		}
		break;
	case HDMITX_FEATURE_HW_AUDIO_OBA:
		*pFeatureSupported = True;
		break;
	case HDMITX_FEATURE_HW_AUDIO_DST:
		*pFeatureSupported = False;
		break;
	case HDMITX_FEATURE_HW_AUDIO_HBR:
		*pFeatureSupported = False;
		break;
	case HDMITX_FEATURE_HW_HDMI_1_1:
		*pFeatureSupported = True;
		break;
	case HDMITX_FEATURE_HW_HDMI_1_2A:
		*pFeatureSupported = True;
		break;
	case HDMITX_FEATURE_HW_HDMI_1_3A:
		*pFeatureSupported = False;
		break;

	case HDMITX_FEATURE_HW_DEEP_COLOR_30:
		*pFeatureSupported = False;
		break;

	case HDMITX_FEATURE_HW_DEEP_COLOR_36:
		*pFeatureSupported = False;
		break;

	case HDMITX_FEATURE_HW_DEEP_COLOR_48:
		*pFeatureSupported = False;
		break;

	case HDMITX_FEATURE_HW_UPSAMPLER:
		*pFeatureSupported = True;
		break;

	case HDMITX_FEATURE_HW_DOWNSAMPLER:
		*pFeatureSupported = True;
		break;

	case HDMITX_FEATURE_HW_COLOR_CONVERSION:
		*pFeatureSupported = True;
		break;

	default:
		*pFeatureSupported = False;
		break;
	}


	return err;
}