/*****************************************************************************/
/* Copyright (c) 2009 NXP Semiconductors BV                                  */
/*                                                                           */
/* This program is free software; you can redistribute it and/or modify      */
/* it under the terms of the GNU General Public License as published by      */
/* the Free Software Foundation, using version 2 of the License.             */
/*                                                                           */
/* This program is distributed in the hope that it will be useful,           */
/* but WITHOUT ANY WARRANTY; without even the implied warranty of            */
/* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the              */
/* GNU General Public License for more details.                              */
/*                                                                           */
/* You should have received a copy of the GNU General Public License         */
/* along with this program; if not, write to the Free Software               */
/* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307       */
/* USA.                                                                      */
/*                                                                           */
/*****************************************************************************/
/**
 *
 * \file          tmdlHdmiTx.c
 *
 * \version       Revision: 1
 *
 * \date          Date: 10/08/07 10:00
 *
 * \brief         devlib driver component API for the TDA998x HDMI Transmitters
 *
 * \section refs  Reference Documents
 * HDMI Tx Driver - FRS.doc,
 *
 * \section info  Change Information
 *
 * \verbatim

   History:       tmdlHdmiTx.c
 *
 * *****************  Version 1  *****************
 * User: J. Lamotte Date: 10/08/07   Time: 10:00
 * Updated in $/Source/tmdlHdmiTx/inc
 * initial version
 
   \endverbatim
 *
*/

/*============================================================================*/
/*                             INCLUDE FILES                                  */
/*============================================================================*/
#include "tmdlHdmiTx_IW.h"
#include "tmdlHdmiTx.h"
#include "tmdlHdmiTx_local.h"
#include "tmdlHdmiTx_cfg.h"
#include "tmbslHdmiTx_funcMapping.h"

/*============================================================================*/
/*                          TYPES DECLARATIONS                                */
/*============================================================================*/

/* Macro to avoid compilation warnings */
#ifdef TMFL_OS_WINDOWS
#define DUMMY_ACCESS(x) x
#else
#define DUMMY_ACCESS(x)
#endif

/*============================================================================*/
/*                       CONSTANTS DECLARATIONS                               */
/*============================================================================*/



/*============================================================================*/
/*                         FUNCTION PROTOTYPES                                */
/*============================================================================*/

/* Prototypes of internal functions */
/* Task functions */
#ifndef TMFL_NO_RTOS
static void CommandTaskUnit0(void);
static void HdcpTaskUnit0(void);
#endif /* TMFL_NO_RTOS */

/* Interrupt callback functions */
static void dlHdmiTxHandleENCRYPT(tmInstance_t instance);
static void dlHdmiTxHandleHPD(tmInstance_t instance);
static void dlHdmiTxHandleT0(tmInstance_t instance);
static void dlHdmiTxHandleBCAPS(tmInstance_t instance);
static void dlHdmiTxHandleBSTATUS(tmInstance_t instance);
static void dlHdmiTxHandleSHA_1(tmInstance_t instance);
static void dlHdmiTxHandlePJ(tmInstance_t instance);
static void dlHdmiTxHandleR0(tmInstance_t instance);
static void dlHdmiTxHandleSW_INT(tmInstance_t instance);
static void dlHdmiTxHandleRX_SENSE(tmInstance_t instance);
static void dlHdmiTxHandleEDID_READ(tmInstance_t instance);
static void dlHdmiTxHandleVS_RPT(tmInstance_t instance);

/* Devlib internal color bar management functions */ 
#ifndef NO_HDCP
static void dlHdmiTxCheckColorBar(tmInstance_t instance);
static void dlHdmiTxCheckHdcpColorBar(tmInstance_t instance);
#endif

#ifndef NO_HDCP
static void dlHdmiTxFindHdcpSeed(tmInstance_t instance);
#endif /* NO_HDCP */

/* Set the state machine of device library */
static void dlHdmiTxSetState
(
    tmInstance_t instance, 
    tmdlHdmiTxDriverState_t state
);

/* Get the event status (enable or disable) in order to known
   if event should be signaled */
static tmdlHdmiTxEventStatus_t dlHdmiTxGetEventStatus
(
    tmInstance_t        instance,
    tmdlHdmiTxEvent_t   event
);

/* Use by tmdlHdmiTxSetInputOutput in scaler mode */
static Bool dlHdmiTxGetReflineRefpix
(
    tmdlHdmiTxVidFmt_t      vinFmt,    
    tmdlHdmiTxVinMode_t     vinMode,   
    tmdlHdmiTxVidFmt_t      voutFmt,   
    UInt8                   syncIn,
    tmdlHdmiTxPixRate_t     pixRate,
    UInt16                  *pRefPix,  
    UInt16                  *pRefLine, 
    UInt16                  *pScRefPix,
    UInt16                  *pScRefLine,
    Bool                    *pbVerified
);

/* Use by tmdlHdmiTxSetInputOutput to set AVI infoframe */
static tmErrorCode_t dlHdmiTxSetVideoInfoframe
(
    tmInstance_t            instance,
    tmdlHdmiTxVidFmt_t      voutFmt,
    tmdlHdmiTxVoutMode_t    voutMode
);

/* Use to set AVI infoframe with raw data */
static tmErrorCode_t dlHdmiTxSetRawVideoInfoframe 
(
    tmInstance_t            instance,
    tmdlHdmiTxAviIfData_t   *pContentVif,
    Bool                    enable
);

/* Calculate Checksum for info frame */
static UInt8
dlHdmiTxcalculateCheksumIF
(   
    tmbslHdmiTxPktRawAvi_t   *pData     /* Pointer to checksum data */
);

/* IMPORTANT: The 3 functions define below should not be declared in static
   in order to allow applicative API to call them. Those functions are not
   in tmdlHdmiTx_Functions.h but are in tmdlHdmiTxCore.def */

/* Get the device library state */
tmdlHdmiTxDriverState_t dlHdmiTxGetState(tmInstance_t instance);

/* Set pattern ON (Blue screen or color bar) */
tmErrorCode_t dlHdmiTxSetTestPatternOn
(
    tmInstance_t            instance,
    tmdlHdmiTxVidFmt_t		voutFmt,
    tmdlHdmiTxVoutMode_t    voutMode,
    tmdlHdmiTxTestPattern_t pattern
);

/* Set pattern OFF */
tmErrorCode_t dlHdmiTxSetTestPatternOff
(
    tmInstance_t            instance,
    tmdlHdmiTxVidFmt_t      voutFmt,
    tmdlHdmiTxVoutMode_t    voutMode
);

/* Get DTD from BSL */
static tmErrorCode_t dlHdmiTxEdidGetDTD
(
    tmInstance_t                    instance,
    tmdlHdmiTxEdidVideoTimings_t    *pDTDescriptors,
    UInt8                           maxDTDesc,
    UInt8                           *pWrittenDTDesc
);

static tmdlHdmiTxVidFmt_t dlHdmiTxConvertDTDtoCEA_640HAP
(
    tmdlHdmiTxEdidVideoTimings_t    *pDTDescriptors
);

static tmdlHdmiTxVidFmt_t dlHdmiTxConvertDTDtoCEA_720HAP
(
    tmdlHdmiTxEdidVideoTimings_t    *pDTDescriptors,
    tmdlHdmiTxPictAspectRatio_t     pictureAspectRatio
);

static tmdlHdmiTxVidFmt_t dlHdmiTxConvertDTDtoCEA_1280HAP
(
    tmdlHdmiTxEdidVideoTimings_t    *pDTDescriptors
);

static tmdlHdmiTxVidFmt_t dlHdmiTxConvertDTDtoCEA_1920HAP
(
    tmdlHdmiTxEdidVideoTimings_t    *pDTDescriptors,
    Bool                            formatInterlaced
);

static tmdlHdmiTxVidFmt_t dlHdmiTxConvertDTDtoCEA_1440HAP
(
    tmdlHdmiTxEdidVideoTimings_t    *pDTDescriptors,
    tmdlHdmiTxPictAspectRatio_t     pictureAspectRatio,
    Bool                            formatInterlaced
);

static tmdlHdmiTxVidFmt_t dlHdmiTxConvertDTDtoCEA_2880HAP
(
    tmdlHdmiTxEdidVideoTimings_t    *pDTDescriptors,
    tmdlHdmiTxPictAspectRatio_t     pictureAspectRatio,
    Bool                            formatInterlaced
);

static tmdlHdmiTxPictAspectRatio_t dlHdmiTxCalcAspectRatio (
    UInt16    HImageSize,
    UInt16    VImageSize
);

#ifndef NO_HDCP
static void dlHdmiTxCheckHdcpBksv
(
    tmInstance_t    instance,
    UInt8 *         pHdcpBksvTested,
    Bool  *         pbBksvSecure,
    Bool            bBigEndian
);
#endif

/* Calculate table index according to video format value */
static tmdlHdmiTxVidFmt_t dlHdmiTxCalcVidFmtIndex(tmdlHdmiTxVidFmt_t vidFmt);

extern tmErrorCode_t tmbslDebugWriteFakeRegPage( tmUnitSelect_t txUnit );

/*============================================================================*/
/*                       VARIABLES DECLARATIONS                               */
/*============================================================================*/

tmdlHdmiTxIWSemHandle_t dlHdmiTxItSemaphore[MAX_UNITS];

/* Unit configuration structure (device library system configuration) */
unitConfig_t unitTableTx[MAX_UNITS] =
{ 
  { 
    False,
    False,
    (tmdlHdmiTxHdcpOptions_t) HDCP_OPT_DEFAULT,
    False,
    False,
    TMDL_HDMITX_DEVICE_UNKNOWN,
    0,
    0,
    (tmdlHdmiTxIWTaskHandle_t) 0,
    (tmdlHdmiTxIWQueueHandle_t) 0,
    (tmdlHdmiTxIWTaskHandle_t) 0,
    STATE_NOT_INITIALIZED,
    (ptmdlHdmiTxCallback_t) 0,
    {Null, 0,},
  }
};

#ifndef TMFL_NO_RTOS

tmdlHdmiTxIWFuncPtr_t commandTaskTableTx[MAX_UNITS] = {
    CommandTaskUnit0
    };

tmdlHdmiTxIWFuncPtr_t hdcpTaskTableTx[MAX_UNITS] = {
    HdcpTaskUnit0
    };

#endif /* TMFL_NO_RTOS */

tmbslHdmiTxCallbackList_t callbackFuncTableTx;

/* Device library configuration structure completed by dlHdmiTxGetConfig with
   informations contained in config file */
tmdlHdmiTxDriverConfigTable_t gtmdlHdmiTxDriverConfigTable[MAX_UNITS] = {
    {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ,0, 0, 0, 0, 0, 0, 0, TMDL_HDMITX_PATTERN_OFF,0},
};

/* Video info (see instanceStatusInfoTx) */
tmdlHdmiTxVideoInfo_t videoInfoListTx = {
    False,
    {TMDL_HDMITX_VFMT_03_720x480p_60Hz, TMDL_HDMITX_VINMODE_YUV422, TMDL_HDMITX_SYNCSRC_EXT_VS, TMDL_HDMITX_PIXRATE_SINGLE, TMDL_HDMITX_3D_NONE},
    {TMDL_HDMITX_VFMT_03_720x480p_60Hz, TMDL_HDMITX_VOUTMODE_YUV422, TMDL_HDMITX_COLORDEPTH_24,TMDL_HDMITX_VQR_DEFAULT}
};

/* Audio info (see instanceStatusInfoTx) */
tmdlHdmiTxAudioInfo_t audioInfoListTx = {
    False,
    {TMDL_HDMITX_AFMT_SPDIF, TMDL_HDMITX_AFS_48K,TMDL_HDMITX_I2SFOR_PHILIPS_L,TMDL_HDMITX_I2SQ_16BITS,TMDL_HDMITX_DSTRATE_SINGLE,0x00} 
};

/* Event state (see instanceStatusInfoTx) */
tmdlHdmiTxEventState_t eventStateListTx[EVENT_NB] = {
    {TMDL_HDMITX_HDCP_ACTIVE,           TMDL_HDMITX_EVENT_DISABLED},
    {TMDL_HDMITX_HDCP_INACTIVE,         TMDL_HDMITX_EVENT_DISABLED},
    {TMDL_HDMITX_HPD_ACTIVE,            TMDL_HDMITX_EVENT_DISABLED},
    {TMDL_HDMITX_HPD_INACTIVE,          TMDL_HDMITX_EVENT_DISABLED},
    {TMDL_HDMITX_RX_KEYS_RECEIVED,      TMDL_HDMITX_EVENT_DISABLED},
    {TMDL_HDMITX_RX_DEVICE_ACTIVE,      TMDL_HDMITX_EVENT_DISABLED},
    {TMDL_HDMITX_RX_DEVICE_INACTIVE,    TMDL_HDMITX_EVENT_DISABLED},
    {TMDL_HDMITX_EDID_RECEIVED,         TMDL_HDMITX_EVENT_DISABLED},
    {TMDL_HDMITX_VS_RPT_RECEIVED,       TMDL_HDMITX_EVENT_DISABLED}
#ifdef HDMI_TX_REPEATER_ISR_MODE
    ,{TMDL_HDMITX_B_STATUS,              TMDL_HDMITX_EVENT_DISABLED}
#endif /* HDMI_TX_REPEATER_ISR_MODE */
};

/* Color bars state (see instanceStatusInfoTx) */
tmdlHdmiTxColBarState_t colorBarStateTx = {
    False,
    True,
    True,
    False,
    False,
    True,
    False
};

tmdlHdmiTxGamutState_t gamutStateTx = {
    False,
    0,
    TMDL_HDMITX_EXT_COLORIMETRY_XVYCC601,
    False,
    TMDL_HDMITX_YQR_LIMITED
};


/* Instance status (save the actual configuration) */
instanceStatus_t instanceStatusInfoTx[MAX_UNITS] = { 
    {(ptmdlHdmiTxVideoInfo_t)  &videoInfoListTx,
     (ptmdlHdmiTxAudioInfo_t)  &audioInfoListTx,
     (ptmdlHdmiTxEventState_t) eventStateListTx,
     (ptmdlHdmiTxColBarState_t) &colorBarStateTx,
     (ptmdlHdmiTxGamutState_t) &gamutStateTx }
};

/* HDCP seed table, arranged as pairs of 16-bit integers: lookup value, seed value.
 * If no table is programmed and if KEY_SEED in config file is null, HDCP will be disabled */
#define SEED_TABLE_LEN 10
static const UInt16 kSeedTable[SEED_TABLE_LEN][2] = { 
	{0, 0},
	{0, 0},
	{0, 0},
	{0, 0},
	{0, 0},
	{0, 0},
	{0, 0},
	{0, 0},
	{0, 0},
	{0, 0}
};

#ifndef NO_HDCP
tmdlHdmiTxHdcpInfo_t hdcpInfoListTx[MAX_UNITS];
#endif /* NO_HDCP */


static Bool gI2CDebugAccessesEnabled = True; /* For debug purpose only, used to manage underlying I2C accessed */

#ifdef HDMI_TX_REPEATER_ISR_MODE
static Bool gIgnoreNextSha1 = False;
#endif /*HDMI_TX_REPEATER_ISR_MODE*/

/*============================================================================*/
/*                              FUNCTIONS                                     */
/*============================================================================*/

/******************************************************************************
    \brief Get the software version of the driver.

    \param pSWVersion Pointer to the version structure.

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

******************************************************************************/
tmErrorCode_t tmdlHdmiTxGetSWVersion
(
    tmSWVersion_t   *pSWVersion
)
{
    /* Check if SWVersion pointer is Null */
    RETIF(pSWVersion == Null, TMDL_ERR_DLHDMITX_INCONSISTENT_PARAMS)

    /* Copy SW version */
    pSWVersion->compatibilityNr = VERSION_COMPATIBILITY;
    pSWVersion->majorVersionNr = VERSION_MAJOR;
    pSWVersion->minorVersionNr = VERSION_MINOR;

    return TM_OK;
}

/******************************************************************************
    \brief Get the number of available HDMI transmitters devices in the system.
           A unit directly represents a physical device.

    \param pUnitCount Pointer to the number of available units.

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

******************************************************************************/
tmErrorCode_t tmdlHdmiTxGetNumberOfUnits
(
    UInt32  *pUnitCount
)
{
    /* Check if UnitCount pointer is Null */
    RETIF(pUnitCount == Null, TMDL_ERR_DLHDMITX_INCONSISTENT_PARAMS)

    /* Copy the maximum number of units */
    *pUnitCount = MAX_UNITS;

    return TM_OK;
}

/******************************************************************************
    \brief Get the capabilities of unit 0. Capabilities are stored into a
           dedicated structure and are directly read from the HW device.

    \param pCapabilities Pointer to the capabilities structure.

    \return The call result:
            - TM_OK: the call was successful
            - TMDL_ERR_DLHDMITX_BAD_UNIT_NUMBER: the unit number is wrong or
              the receiver instance is not initialised
            - TMDL_ERR_DLHDMITX_INCONSISTENT_PARAMS: an input parameter is
              inconsistent
            - TMDL_ERR_DLHDMITX_BAD_PARAMETER: a parameter is invalid or out
              of range
            - TMBSL_ERR_HDMI_BAD_UNIT_NUMBER: bad transmitter unit number
            - TMBSL_ERR_HDMI_BAD_PARAMETER: a parameter was out of range
            - TMBSL_ERR_HDMI_NOT_INITIALIZED: transmitter not initialized

******************************************************************************/
tmErrorCode_t tmdlHdmiTxGetCapabilities
(
    tmdlHdmiTxCapabilities_t    *pCapabilities
)
{
    /* Directly call GetCapabilitiesM function for unit 0 and return the result */
    return(tmdlHdmiTxGetCapabilitiesM((tmUnitSelect_t)0, pCapabilities));
}

/******************************************************************************
    \brief Get the capabilities of a specific unit. Capabilities are stored
           into a dedicated structure and are directly read from the HW
           device.

    \param unit          Unit to be probed.
    \param pCapabilities Pointer to the capabilities structure.

    \return The call result:
            - TM_OK: the call was successful
            - TMDL_ERR_DLHDMITX_BAD_UNIT_NUMBER: the unit number is wrong or
              the receiver instance is not initialised
            - TMDL_ERR_DLHDMITX_INCONSISTENT_PARAMS: an input parameter is
              inconsistent
            - TMDL_ERR_DLHDMITX_BAD_PARAMETER: a parameter is invalid or out
              of range
            - TMBSL_ERR_HDMI_BAD_UNIT_NUMBER: bad transmitter unit number
            - TMBSL_ERR_HDMI_BAD_PARAMETER: a parameter was out of range
            - TMBSL_ERR_HDMI_NOT_INITIALIZED: transmitter not initialized

******************************************************************************/
tmErrorCode_t tmdlHdmiTxGetCapabilitiesM
(
   tmUnitSelect_t           unit,
   tmdlHdmiTxCapabilities_t *pCapabilities
)
{
    tmErrorCode_t   errCode = TM_OK;
    Bool            featureSupported;    

    /* Check if unit number is in range */
    RETIF((unit < 0) || (unit >= MAX_UNITS), TMDL_ERR_DLHDMITX_BAD_UNIT_NUMBER)

    /* Check if Capalities pointer is Null */
    RETIF(pCapabilities == Null, TMDL_ERR_DLHDMITX_INCONSISTENT_PARAMS)

    /* Device version */
    pCapabilities->deviceVersion = unitTableTx[unit].deviceVersion ;

    /* Retrieve the capabilities from the BSL layer */   

    /* HDCP support */
    RETIF( (errCode = tmbslHdmiTxHwGetCapabilities(unit, 
        HDMITX_FEATURE_HW_HDCP, &featureSupported) ) != TM_OK, errCode)

    pCapabilities->hdcp = featureSupported;

    /* Scaler support */
    RETIF( (errCode = tmbslHdmiTxHwGetCapabilities(unit, 
        HDMITX_FEATURE_HW_SCALER, &featureSupported) ) != TM_OK, errCode)

    pCapabilities->scaler = featureSupported;
    
    /* Audio HBR support */
    RETIF( (errCode = tmbslHdmiTxHwGetCapabilities(unit, 
        HDMITX_FEATURE_HW_AUDIO_HBR, &featureSupported) ) != TM_OK, errCode)

    pCapabilities->audioPacket.HBR = featureSupported;
    
    /* Audio OBA support */
    RETIF( (errCode = tmbslHdmiTxHwGetCapabilities(unit, 
        HDMITX_FEATURE_HW_AUDIO_OBA, &featureSupported) ) != TM_OK, errCode)

    pCapabilities->audioPacket.oneBitAudio = featureSupported;

    /* Audio DST support */
    RETIF( (errCode = tmbslHdmiTxHwGetCapabilities(unit, 
        HDMITX_FEATURE_HW_AUDIO_DST, &featureSupported) ) != TM_OK, errCode)

    pCapabilities->audioPacket.DST = featureSupported;

    /* HDMI version 1.1 support */
    RETIF( (errCode = tmbslHdmiTxHwGetCapabilities(unit, 
        HDMITX_FEATURE_HW_HDMI_1_1, &featureSupported) ) != TM_OK, errCode)

    if (featureSupported)
    {
        pCapabilities->hdmiVersion = TMDL_HDMITX_HDMI_VERSION_1_1;
    }

    /* HDMI version 1.2A support */
    RETIF( (errCode = tmbslHdmiTxHwGetCapabilities(unit, 
        HDMITX_FEATURE_HW_HDMI_1_2A, &featureSupported) ) != TM_OK, errCode)

    if (featureSupported)
    {
        pCapabilities->hdmiVersion = TMDL_HDMITX_HDMI_VERSION_1_2a;
    }

    /* HDMI version 1.3 support */
    RETIF( (errCode = tmbslHdmiTxHwGetCapabilities(unit, 
        HDMITX_FEATURE_HW_HDMI_1_3A, &featureSupported) ) != TM_OK, errCode)

    if (featureSupported)
    {
        pCapabilities->hdmiVersion = TMDL_HDMITX_HDMI_VERSION_1_3a;
    }

    /* Deep Color support */
    /* By default */
    pCapabilities->colorDepth = TMDL_HDMITX_COLORDEPTH_24; 
    
    RETIF( (errCode = tmbslHdmiTxHwGetCapabilities(unit, 
        HDMITX_FEATURE_HW_DEEP_COLOR_30, &featureSupported) ) != TM_OK, errCode)

    if (featureSupported)
    {
        pCapabilities->colorDepth = TMDL_HDMITX_COLORDEPTH_30;
    }

    RETIF( (errCode = tmbslHdmiTxHwGetCapabilities(unit, 
        HDMITX_FEATURE_HW_DEEP_COLOR_36, &featureSupported) ) != TM_OK, errCode)

    if (featureSupported)
    {
        pCapabilities->colorDepth = TMDL_HDMITX_COLORDEPTH_36;
    }

    RETIF( (errCode = tmbslHdmiTxHwGetCapabilities(unit, 
        HDMITX_FEATURE_HW_DEEP_COLOR_48, &featureSupported) ) != TM_OK, errCode)

    if (featureSupported)
    {
        pCapabilities->colorDepth = TMDL_HDMITX_COLORDEPTH_48;
    }

    return errCode;
}

/******************************************************************************
    \brief Open unit 0 of HdmiTx driver and provides the instance number to
           the caller. Note that one unit of HdmiTx represents one physical
           HDMI transmitter and that only one instance per unit can be opened.

    \param pInstance Pointer to the variable that will receive the instance
                     identifier.

    \return The call result:
            - TM_OK: the call was successful
            - TMDL_ERR_DLHDMITX_BAD_UNIT_NUMBER: the unit number is wrong or
              the transmitter instance is not initialised
            - TMDL_ERR_DLHDMITX_BAD_HANDLE: the handle number is wrong
            - TMDL_ERR_DLHDMITX_INCONSISTENT_PARAMS: an input parameter is
              inconsistent
            - TMDL_ERR_DLHDMITX_RESOURCE_OWNED: the resource is already in use
            - TMDL_ERR_DLHDMITX_INVALID_STATE: the state is invalid for
              the function
            - TMDL_ERR_DLHDMITX_INIT_FAILED: the unit instance is already
              initialised or something wrong happened at lower level.
            - TMDL_ERR_DLHDMITX_NO_RESOURCES: the resource is not available
            - TMBSL_ERR_HDMI_BAD_UNIT_NUMBER: bad transmitter unit number 
            - TMBSL_ERR_HDMI_NOT_INITIALIZED: the unit is not initialized
            - TMBSL_ERR_HDMI_BAD_PARAMETER: a parameter is invalid or out 
              of range
            - TMBSL_ERR_HDMI_INIT_FAILED: the unit instance is already 
              initialised
            - TMBSL_ERR_HDMI_COMPATIBILITY: the driver is not compatiable 
              with the internal device version code
            - TMBSL_ERR_HDMI_I2C_WRITE: failed when writing to the I2C bus
            - TMBSL_ERR_HDMI_I2C_READ: failed when reading the I2C bus

******************************************************************************/
tmErrorCode_t tmdlHdmiTxOpen
(
    tmInstance_t   *pInstance
)
{
    /* Directly call OpenM function for unit 0 and return the result */
    return(tmdlHdmiTxOpenM(pInstance, (tmUnitSelect_t)0));
}

/******************************************************************************
    \brief Open a specific unit of HdmiTx driver and provides the instance
           number to the caller. Note that one unit of HdmiTx represents one
           physical HDMI transmitter and that only one instance per unit can be
           opened. This function switches driver's state machine to
           "initialized" state.

    \param pInstance Pointer to the structure that will receive the instance
                     identifier.
    \param unit      Unit number to be opened.

    \return The call result:
            - TM_OK: the call was successful
            - TMDL_ERR_DLHDMITX_BAD_UNIT_NUMBER: the unit number is wrong or
              the transmitter instance is not initialised
            - TMDL_ERR_DLHDMITX_BAD_HANDLE: the handle number is wrong
            - TMDL_ERR_DLHDMITX_INCONSISTENT_PARAMS: an input parameter is
              inconsistent
            - TMDL_ERR_DLHDMITX_RESOURCE_OWNED: the resource is already in use
            - TMDL_ERR_DLHDMITX_INVALID_STATE: the state is invalid for
              the function
            - TMDL_ERR_DLHDMITX_INIT_FAILED: the unit instance is already
              initialised or something wrong happened at lower level.
            - TMDL_ERR_DLHDMITX_NO_RESOURCES: the resource is not available
            - TMBSL_ERR_HDMI_BAD_UNIT_NUMBER: bad transmitter unit number 
            - TMBSL_ERR_HDMI_NOT_INITIALIZED: the unit is not initialized
            - TMBSL_ERR_HDMI_BAD_PARAMETER: a parameter is invalid or out 
              of range
            - TMBSL_ERR_HDMI_INIT_FAILED: the unit instance is already 
              initialised
            - TMBSL_ERR_HDMI_COMPATIBILITY: the driver is not compatiable 
              with the internal device version code
            - TMBSL_ERR_HDMI_I2C_WRITE: failed when writing to the I2C bus
            - TMBSL_ERR_HDMI_I2C_READ: failed when reading the I2C bus

******************************************************************************/
tmErrorCode_t tmdlHdmiTxOpenM
(
    tmInstance_t   *pInstance,
    tmUnitSelect_t  unit
)
{
    tmErrorCode_t           errCode;
    tmErrorCode_t           errCodeSem;
    UInt16                  i;
    UInt8                   deviceVersion;
    Bool                    featureSupported;

    /* Check if unit number is in range */
    RETIF((unit < 0) || (unit >= MAX_UNITS), TMDL_ERR_DLHDMITX_BAD_UNIT_NUMBER)

    /* Check if Instance pointer is Null */
    RETIF(pInstance == Null, TMDL_ERR_DLHDMITX_INCONSISTENT_PARAMS)
    
    /* Create the semaphore to protect variables modified under interruption */
    RETIF( (errCode = tmdlHdmiTxIWSemaphoreCreate(&dlHdmiTxItSemaphore[unit]) ) != TM_OK, errCode)

    /* Take the sempahore */
    RETIF( (errCodeSem = tmdlHdmiTxIWSemaphoreP(dlHdmiTxItSemaphore[unit]) ) != TM_OK, errCodeSem)

    /* Check if unit is already instanciated */
    RETIF_SEM(dlHdmiTxItSemaphore[unit],
        unitTableTx[unit].opened == True, TMDL_ERR_DLHDMITX_RESOURCE_OWNED)

    /* Check the state */
    RETIF_SEM(dlHdmiTxItSemaphore[unit], 
        dlHdmiTxGetState(unit) != STATE_NOT_INITIALIZED, TMDL_ERR_DLHDMITX_INVALID_STATE) 

	/* Instanciate unit and return corresponding instance number */
    /* Since HW unit are only instanciable once, instance = unit */
    unitTableTx[unit].opened                = True;
    unitTableTx[unit].hdcpEnable            = False;
    unitTableTx[unit].repeaterEnable        = False;
    unitTableTx[unit].deviceVersion         = TMDL_HDMITX_DEVICE_UNKNOWN;
    unitTableTx[unit].simplayHd             = False;
    unitTableTx[unit].pCallback             = Null;
    unitTableTx[unit].revocationList.pList  = Null;
    unitTableTx[unit].revocationList.length = 0;
    
    /* Recover the configuration of the device library */
    RETIF_SEM(dlHdmiTxItSemaphore[unit],
        dlHdmiTxGetConfig(unit, &gtmdlHdmiTxDriverConfigTable[unit])!= TM_OK, TMDL_ERR_DLHDMITX_INIT_FAILED)

#ifndef TMFL_NO_RTOS
    
    /* Create message queue associated to this instance/unit */
    RETIF_SEM(dlHdmiTxItSemaphore[unit],
        tmdlHdmiTxIWQueueCreate(gtmdlHdmiTxDriverConfigTable[unit].commandTaskQueueSize,
        &(unitTableTx[unit].queueHandle)) != TM_OK, TMDL_ERR_DLHDMITX_NO_RESOURCES)

    /* Create the command task associated to this instance/unit */
    RETIF_SEM(dlHdmiTxItSemaphore[unit],
        tmdlHdmiTxIWTaskCreate(commandTaskTableTx[unit],
        gtmdlHdmiTxDriverConfigTable[unit].commandTaskPriority,
        gtmdlHdmiTxDriverConfigTable[unit].commandTaskStackSize,
        &(unitTableTx[unit].commandTaskHandle)) != TM_OK, TMDL_ERR_DLHDMITX_NO_RESOURCES)

    RETIF_SEM(dlHdmiTxItSemaphore[unit],
        tmdlHdmiTxIWTaskStart(unitTableTx[unit].commandTaskHandle) != TM_OK, TMDL_ERR_DLHDMITX_NO_RESOURCES)

	/* Create the hdcp check task associated to this instance/unit */
#ifndef NO_HDCP
    RETIF_SEM(dlHdmiTxItSemaphore[unit],
        tmdlHdmiTxIWTaskCreate(hdcpTaskTableTx[unit],
        gtmdlHdmiTxDriverConfigTable[unit].hdcpTaskPriority,
        gtmdlHdmiTxDriverConfigTable[unit].hdcpTaskStackSize,
        &(unitTableTx[unit].hdcpTaskHandle)) != TM_OK, TMDL_ERR_DLHDMITX_NO_RESOURCES)
#endif /* NO_HDCP */

#endif /* TMFL_NO_RTOS */

    *pInstance = (tmInstance_t)unit;

#ifndef NO_HDCP
    hdcpInfoListTx[unit].bKsvSecure = False;
    hdcpInfoListTx[unit].hdcpKsvDevices = 0;
    for(i=0; i<TMDL_HDMITX_KSV_BYTES_PER_DEVICE; i++) { hdcpInfoListTx[unit].hdcpBksv[i] = 0; }
    hdcpInfoListTx[unit].hdcpDeviceDepth = 0;
#endif /* NO_HDCP */

    /* Init the BSL */
	/* Make sure all events are disabled */
    instanceStatusInfoTx[unit].pEventState[TMDL_HDMITX_HDCP_ACTIVE].status = TMDL_HDMITX_EVENT_DISABLED;
    instanceStatusInfoTx[unit].pEventState[TMDL_HDMITX_HDCP_INACTIVE].status = TMDL_HDMITX_EVENT_DISABLED;
    instanceStatusInfoTx[unit].pEventState[TMDL_HDMITX_HPD_ACTIVE].status = TMDL_HDMITX_EVENT_DISABLED;
    instanceStatusInfoTx[unit].pEventState[TMDL_HDMITX_HPD_INACTIVE].status = TMDL_HDMITX_EVENT_DISABLED;
    instanceStatusInfoTx[unit].pEventState[TMDL_HDMITX_RX_KEYS_RECEIVED].status = TMDL_HDMITX_EVENT_DISABLED;
    instanceStatusInfoTx[unit].pEventState[TMDL_HDMITX_RX_DEVICE_ACTIVE].status = TMDL_HDMITX_EVENT_DISABLED;
    instanceStatusInfoTx[unit].pEventState[TMDL_HDMITX_RX_DEVICE_INACTIVE].status = TMDL_HDMITX_EVENT_DISABLED;
    instanceStatusInfoTx[unit].pEventState[TMDL_HDMITX_EDID_RECEIVED].status = TMDL_HDMITX_EVENT_DISABLED;
    instanceStatusInfoTx[unit].pEventState[TMDL_HDMITX_VS_RPT_RECEIVED].status = TMDL_HDMITX_EVENT_DISABLED;
#ifdef HDMI_TX_REPEATER_ISR_MODE
    instanceStatusInfoTx[unit].pEventState[TMDL_HDMITX_B_STATUS].status = TMDL_HDMITX_EVENT_DISABLED;
#endif /* HDMI_TX_REPEATER_ISR_MODE */
    instanceStatusInfoTx[unit].pColBarState->disableColorBarOnR0 = False;
    instanceStatusInfoTx[unit].pColBarState->hdcpColbarChange = False;
    instanceStatusInfoTx[unit].pColBarState->hdcpEncryptOrT0 = True;
    instanceStatusInfoTx[unit].pColBarState->hdcpSecureOrT0 = False;
    instanceStatusInfoTx[unit].pColBarState->inOutFirstSetDone = False;
    instanceStatusInfoTx[unit].pColBarState->colorBarOn = False;
    instanceStatusInfoTx[unit].pColBarState->changeColorBarNow = False;

    instanceStatusInfoTx[unit].pGamutState->gamutOn = False;
    instanceStatusInfoTx[unit].pGamutState->gamutBufNum = 0; /* use buffer 0 by default */
    instanceStatusInfoTx[unit].pGamutState->wideGamutColorSpace = TMDL_HDMITX_EXT_COLORIMETRY_XVYCC601;
    instanceStatusInfoTx[unit].pGamutState->extColOn = False;
    instanceStatusInfoTx[unit].pGamutState->yccQR = TMDL_HDMITX_YQR_LIMITED;


    instanceStatusInfoTx[unit].pAudioInfo->audioMuteState = False; /* Initially audio is not muted */



    /* The funcCallback is not the same between BSL, so fill it dynamically */
    for(i=0; i<HDMITX_CALLBACK_INT_NUM; i++)
    {
        callbackFuncTableTx.funcCallback[i] = Null;
    }
    callbackFuncTableTx.funcCallback[HDMITX_CALLBACK_INT_ENCRYPT] = dlHdmiTxHandleENCRYPT;
    callbackFuncTableTx.funcCallback[HDMITX_CALLBACK_INT_HPD] = dlHdmiTxHandleHPD;
    callbackFuncTableTx.funcCallback[HDMITX_CALLBACK_INT_T0] = dlHdmiTxHandleT0;
    callbackFuncTableTx.funcCallback[HDMITX_CALLBACK_INT_BCAPS] = dlHdmiTxHandleBCAPS;
    callbackFuncTableTx.funcCallback[HDMITX_CALLBACK_INT_BSTATUS] = dlHdmiTxHandleBSTATUS;
    callbackFuncTableTx.funcCallback[HDMITX_CALLBACK_INT_SHA_1] = dlHdmiTxHandleSHA_1;
    callbackFuncTableTx.funcCallback[HDMITX_CALLBACK_INT_PJ] = dlHdmiTxHandlePJ;
    callbackFuncTableTx.funcCallback[HDMITX_CALLBACK_INT_R0] = dlHdmiTxHandleR0;
    callbackFuncTableTx.funcCallback[HDMITX_CALLBACK_INT_SW_INT] = dlHdmiTxHandleSW_INT;
    callbackFuncTableTx.funcCallback[HDMITX_CALLBACK_INT_RX_SENSE] = dlHdmiTxHandleRX_SENSE;
    callbackFuncTableTx.funcCallback[HDMITX_CALLBACK_INT_EDID_BLK_READ] = dlHdmiTxHandleEDID_READ;
    callbackFuncTableTx.funcCallback[HDMITX_CALLBACK_INT_VS_RPT] = dlHdmiTxHandleVS_RPT;

    /* Prepare static TDA9984 driver data as the compiler doesn't seem to */

    tmbslHdmiTxHwStartup();
    errCode = tmbslHdmiTxInit(*pInstance, 
                gtmdlHdmiTxDriverConfigTable[unit].i2cAddress,
                gtmdlHdmiTxDriverConfigTable[unit].i2cWriteFunction,
                gtmdlHdmiTxDriverConfigTable[unit].i2cReadFunction,
                (ptmbslHdmiTxSysFuncEdid_t)0, /* Not used for TDA9984 */
                (ptmbslHdmiTxSysFuncTimer_t)tmdlHdmiTxIWWait,
                &callbackFuncTableTx,
                False, /* Alternate EDID address not used */
                (tmbslHdmiTxVidFmt_t)instanceStatusInfoTx[unit].pVideoInfo->videoInConfig.format,
                (tmbslHdmiTxPixRate_t)instanceStatusInfoTx[unit].pVideoInfo->videoInConfig.pixelRate);
    if (errCode != TM_OK)
    {
        /* Init failed */
        tmbslHdmiTxDeinit(unit);

        /* Release the sempahore */
        RETIF( (errCodeSem = tmdlHdmiTxIWSemaphoreV(dlHdmiTxItSemaphore[unit]) ) != TM_OK, errCodeSem)

        return errCode;
    }
    else
    {
        /* Init passed, continue */

        /* Start by forcing the TMDS ouputs off */
        errCode = tmbslHdmiTxTmdsSetOutputs(unit,
            HDMITX_TMDSOUT_FORCED0);
        RETIF_SEM(dlHdmiTxItSemaphore[unit], (errCode != TM_OK) && (errCode != TMBSL_ERR_HDMI_NOT_SUPPORTED), errCode)

        RETIF_SEM(dlHdmiTxItSemaphore[unit],
            (errCode = tmbslHdmiTxHwGetCapabilities(unit,
            HDMITX_FEATURE_HW_HDCP, &featureSupported) ) != TM_OK, errCode)

#ifndef NO_HDCP
        if (featureSupported == True)
        {
			dlHdmiTxFindHdcpSeed(unit);
        }
#endif /* NO_HDCP */

#ifdef TMFL_TDA19988
        tmbslHdmiTxHdcpPowerDown(unit,True);
#endif
        /* Retrieve the hardware device version from the BSL layer */
        RETIF_SEM(dlHdmiTxItSemaphore[unit],
                  (errCode = tmbslHdmiTxHwGetVersion(unit,&deviceVersion) ) \
                  != TM_OK, errCode);

        /* Store the hardware device version in the global variable */
        switch (deviceVersion)
           {
           case BSLHDMITX_TDA9984:
              unitTableTx[unit].deviceVersion = TMDL_HDMITX_DEVICE_TDA9984;
              break;
              
           case BSLHDMITX_TDA9989:
              unitTableTx[unit].deviceVersion = TMDL_HDMITX_DEVICE_TDA9989;
              break;
              
	       case BSLHDMITX_TDA9981:
              unitTableTx[unit].deviceVersion = TMDL_HDMITX_DEVICE_TDA9981;
              break;
              
           case BSLHDMITX_TDA9983:
              unitTableTx[unit].deviceVersion = TMDL_HDMITX_DEVICE_TDA9983;
              break;
              
           case BSLHDMITX_TDA19989:
              unitTableTx[unit].deviceVersion = TMDL_HDMITX_DEVICE_TDA19989;
              break;
              
           case BSLHDMITX_TDA19988:
              unitTableTx[unit].deviceVersion = TMDL_HDMITX_DEVICE_TDA19988;
              break;
              
	       default:
              unitTableTx[unit].deviceVersion = TMDL_HDMITX_DEVICE_UNKNOWN;
              break;
           }
    }


#ifndef TMFL_NO_RTOS
	/* Start HDCP check task */

#ifndef NO_HDCP
    RETIF_SEM(dlHdmiTxItSemaphore[unit],
        tmdlHdmiTxIWTaskStart(unitTableTx[unit].hdcpTaskHandle) != TM_OK, TMDL_ERR_DLHDMITX_NO_RESOURCES)
#endif /* NO_HDCP */

#endif /* TMFL_NO_RTOS */


	/* Set the state machine to initialized */
    dlHdmiTxSetState(unit, STATE_INITIALIZED);

    /* Release the sempahore */
    RETIF( (errCodeSem = tmdlHdmiTxIWSemaphoreV(dlHdmiTxItSemaphore[unit]) ) != TM_OK, errCodeSem)
    
    return TM_OK;
}

/******************************************************************************
    \brief Close an instance of HdmiTx driver.

    \param instance Instance identifier.

    \return The call result:
            - TM_OK: the call was successful
            - TMDL_ERR_DLHDMITX_BAD_INSTANCE: the instance number is wrong or 
              out of range
            - TMDL_ERR_DLHDMITX_RESOURCE_NOT_OWNED: the caller does not own 
              the resource
            - TMDL_ERR_DLHDMITX_BAD_HANDLE: the handle number is wrong

******************************************************************************/
tmErrorCode_t tmdlHdmiTxClose
(
    tmInstance_t    instance
)
{
    tmErrorCode_t   errCode = TM_OK;

    /* Check if instance number is in range */
    RETIF((instance < 0) || (instance >= MAX_UNITS), TMDL_ERR_DLHDMITX_BAD_INSTANCE)

    /* Take the sempahore */
    RETIF( (errCode = tmdlHdmiTxIWSemaphoreP(dlHdmiTxItSemaphore[instance]) ) != TM_OK, errCode)

    /* Check if unit corresponding to instance is opened */
    RETIF_SEM(dlHdmiTxItSemaphore[instance], 
        unitTableTx[instance].opened == False, TMDL_ERR_DLHDMITX_RESOURCE_NOT_OWNED)

    /* Close instance */
    unitTableTx[instance].opened = False;
    
    /* Set the state machine */
    dlHdmiTxSetState(instance, STATE_NOT_INITIALIZED);
    
    /* Destroy resources allocated for this instance/unit */

#ifndef TMFL_NO_RTOS

#ifndef NO_HDCP
    tmdlHdmiTxIWTaskDestroy(unitTableTx[instance].hdcpTaskHandle);
#endif /* NO_HDCP */

    tmdlHdmiTxIWTaskDestroy(unitTableTx[instance].commandTaskHandle);
    tmdlHdmiTxIWQueueDestroy(unitTableTx[instance].queueHandle);

#endif /* TMFL_NO_RTOS */

    /* Reset an instance of an HDMI transmitter */
	tmbslHdmiTxDeinit(instance);

    /* Release the sempahore */
    RETIF( (errCode = tmdlHdmiTxIWSemaphoreV(dlHdmiTxItSemaphore[instance]) ) != TM_OK, errCode)

    /* Close the handle to the semaphore */
    RETIF( (errCode = tmdlHdmiTxIWSemaphoreDestroy(dlHdmiTxItSemaphore[instance]) ) != TM_OK, errCode)

    return TM_OK;
}

/******************************************************************************
    \brief Set the power state of an instance of the HDMI transmitter.

    \param instance   Instance identifier.
    \param powerState Power state to set.

    \return The call result:
            - TM_OK: the call was successful
            - TMDL_ERR_DLHDMITX_BAD_INSTANCE: the instance number is wrong or 
              out of range
            - TMDL_ERR_DLHDMITX_BAD_HANDLE: the handle number is wrong
            - TMBSL_ERR_HDMI_BAD_UNIT_NUMBER: bad transmitter unit number 
            - TMBSL_ERR_HDMI_BAD_PARAMETER: a parameter was out of range
            - TMBSL_ERR_HDMI_NOT_INITIALIZED: transmitter not initialized
            - TMBSL_ERR_HDMI_I2C_WRITE: failed when writing to the I2C bus
            - TMBSL_ERR_HDMI_I2C_READ: failed when reading to the I2C bus

******************************************************************************/
tmErrorCode_t tmdlHdmiTxSetPowerState
(
    tmInstance_t    instance,
    tmPowerState_t  powerState
)
{
    tmErrorCode_t           errCode;
    tmbslHdmiTxHotPlug_t    hpdStatus;  /* HPD status */

    /* Check if instance number is in range */
    RETIF((instance < 0) || (instance >= MAX_UNITS), TMDL_ERR_DLHDMITX_BAD_INSTANCE)

    /* Take the sempahore */
    RETIF( (errCode = tmdlHdmiTxIWSemaphoreP(dlHdmiTxItSemaphore[instance]) ) != TM_OK, errCode)

    if  (unitTableTx[instance].deviceVersion == TMDL_HDMITX_DEVICE_TDA9984)
    {
	    if (powerState == tmPowerSuspend)
	    {
			RETIF( (errCode = tmdlHdmiTxIWSemaphoreV(dlHdmiTxItSemaphore[instance]) ) != TM_OK, errCode)
	        return TMDL_ERR_DLHDMITX_NOT_SUPPORTED;
	    }
    }




    /* Switch off HDCP */
    if ( ((powerState == tmPowerOff) && (unitTableTx[instance].hdcpEnable == True)) 
         || ((powerState == tmPowerStandby) && (unitTableTx[instance].hdcpEnable == True))
         || ((powerState == tmPowerSuspend) && (unitTableTx[instance].hdcpEnable == True))
       )
    {
        /* Release the sempahore */
        RETIF( (errCode = tmdlHdmiTxIWSemaphoreV(dlHdmiTxItSemaphore[instance]) ) != TM_OK, errCode)
        /* Switch off HDCP */
        RETIF( (errCode = tmdlHdmiTxSetHdcp(instance, False) ) != TM_OK, errCode)
        /* Take the sempahore */
        RETIF( (errCode = tmdlHdmiTxIWSemaphoreP(dlHdmiTxItSemaphore[instance]) ) != TM_OK, errCode)
    }


    /* TDA9989, TDA19989 and TDA19988 only */
    if  ( (unitTableTx[instance].deviceVersion == TMDL_HDMITX_DEVICE_TDA9989)
          ||
          (unitTableTx[instance].deviceVersion == TMDL_HDMITX_DEVICE_TDA19989)
          ||
          (unitTableTx[instance].deviceVersion == TMDL_HDMITX_DEVICE_TDA19988))

    {
        if ((powerState != tmPowerOn) && (powerState != tmPowerSuspend)) {
            dlHdmiTxSetState(instance, STATE_INITIALIZED);
        }

        if ((powerState == tmPowerOn) && (unitTableTx[instance].simplayHd == True)) {

    instanceStatusInfoTx[0].pColBarState->disableColorBarOnR0 = False;
    instanceStatusInfoTx[0].pColBarState->hdcpColbarChange = False;
    instanceStatusInfoTx[0].pColBarState->hdcpEncryptOrT0 = True;
    instanceStatusInfoTx[0].pColBarState->hdcpSecureOrT0 = False;
    instanceStatusInfoTx[0].pColBarState->inOutFirstSetDone = False;
    instanceStatusInfoTx[0].pColBarState->colorBarOn = True;
    instanceStatusInfoTx[0].pColBarState->changeColorBarNow = True;
    
        }

    }

    /* Set the power state of the transmitter */
    RETIF_SEM(dlHdmiTxItSemaphore[instance],
        (errCode = tmbslHdmiTxPowerSetState(instance, 
        powerState) ) != TM_OK, errCode)

    /* Get Hot Plug status */
    RETIF_SEM(dlHdmiTxItSemaphore[instance],
        (errCode = tmbslHdmiTxHotPlugGetStatus(instance,
                                               &hpdStatus,False) ) != TM_OK, errCode)

    if (powerState == tmPowerOn)
    {
        if ((hpdStatus == HDMITX_HOTPLUG_ACTIVE) && (dlHdmiTxGetState(instance) != STATE_EDID_AVAILABLE))
        {
            /* Yes: Wait for DDC line to settle before reading EDID */
            tmbslHdmiTxSysTimerWait(instance,
                    500); /* ms */

            /* Request EDID read */
            RETIF_SEM(dlHdmiTxItSemaphore[instance],
                (errCode = tmbslHdmiTxEdidRequestBlockData(instance,
                unitTableTx[instance].pEdidBuffer, (Int)((unitTableTx[instance].edidBufferSize) >> 7),
                (Int)(unitTableTx[instance].edidBufferSize)) ) != TM_OK, errCode)
        }
    }
        
    /* Release the sempahore */
    RETIF( (errCode = tmdlHdmiTxIWSemaphoreV(dlHdmiTxItSemaphore[instance]) ) != TM_OK, errCode)

    return TM_OK;
}

/******************************************************************************
    \brief Get the power state of an instance of the HDMI transmitter.

    \param instance    Instance identifier.
    \param pPowerState Pointer to the power state.

    \return The call result:
            - TM_OK: the call was successful
            - TMDL_ERR_DLHDMITX_BAD_INSTANCE: the instance number is wrong or 
              out of range
            - TMDL_ERR_DLHDMITX_BAD_HANDLE: the handle number is wrong
            - TMDL_ERR_DLHDMITX_INCONSISTENT_PARAMS: an input parameter is
              inconsistent
            - TMBSL_ERR_HDMI_BAD_UNIT_NUMBER: bad transmitter unit number
            - TMBSL_ERR_HDMI_BAD_PARAMETER: a parameter was out of range
            - TMBSL_ERR_HDMI_NOT_INITIALIZED: transmitter not initialized

******************************************************************************/
tmErrorCode_t tmdlHdmiTxGetPowerState
(
    tmInstance_t    instance,
    tmPowerState_t  *pPowerState
)
{
    tmErrorCode_t   errCode;

    /* Check if instance number is in range */
    RETIF((instance < 0) || (instance >= MAX_UNITS), TMDL_ERR_DLHDMITX_BAD_INSTANCE)

    /* Check if PowerState pointer is Null */
    RETIF(pPowerState == Null, TMDL_ERR_DLHDMITX_INCONSISTENT_PARAMS)

    /* Take the sempahore */
    RETIF( (errCode = tmdlHdmiTxIWSemaphoreP(dlHdmiTxItSemaphore[instance]) ) != TM_OK, errCode)

    /* Get the power state of the transmitter */
    RETIF_SEM(dlHdmiTxItSemaphore[instance],
        (errCode = tmbslHdmiTxPowerGetState(instance,
        pPowerState) ) != TM_OK, errCode)

    /* Release the sempahore */
    RETIF( (errCode = tmdlHdmiTxIWSemaphoreV(dlHdmiTxItSemaphore[instance]) ) != TM_OK, errCode)

    return TM_OK;
}

/******************************************************************************
    \brief Set the configuration of instance attributes. This function is
           required by DVP architecture rules but actually does nothing in this
           driver.

    \param instance    Instance identifier.

    \return The call result:
            - TM_OK: the call was successful
            - TMDL_ERR_DLHDMITX_BAD_INSTANCE: the instance number is wrong or 
              out of range

******************************************************************************/
tmErrorCode_t tmdlHdmiTxInstanceConfig
(
    tmInstance_t    instance
)
{
    /* Check if instance number is in range */
    RETIF((instance < 0) || (instance >= MAX_UNITS), TMDL_ERR_DLHDMITX_BAD_INSTANCE)

    return TM_OK;
}

/******************************************************************************
    \brief Setup the instance with its configuration parameters. This function
           allows basic instance configuration like enabling HDCP, choosing
           HDCP encryption mode or enabling HDCP repeater mode.

    \param instance   Instance identifier.
    \param pSetupInfo Pointer to the structure containing all setup parameters.

    \return The call result:
            - TM_OK: the call was successful
            - TMDL_ERR_DLHDMITX_BAD_INSTANCE: the instance number is wrong or 
              out of range
            - TMDL_ERR_DLHDMITX_BAD_HANDLE: the handle number is wrong
            - TMDL_ERR_DLHDMITX_INCONSISTENT_PARAMS: an input parameter is
              inconsistent
            - TMDL_ERR_DLHDMITX_RESOURCE_NOT_OWNED: the caller does not own 
              the resource
            - TMDL_ERR_DLHDMITX_INVALID_STATE: the state is invalid for
              the function

******************************************************************************/
tmErrorCode_t tmdlHdmiTxInstanceSetup
(
    tmInstance_t                    instance,
    tmdlHdmiTxInstanceSetupInfo_t   *pSetupInfo
)
{
    tmErrorCode_t   errCode;
#ifndef NO_HDCP
    UInt16          i;
#endif

    /* Check if instance number is in range */
    RETIF((instance < 0) || (instance >= MAX_UNITS), TMDL_ERR_DLHDMITX_BAD_INSTANCE)

    /* Check if SetupInfo pointer is NULL */
    RETIF(pSetupInfo == Null, TMDL_ERR_DLHDMITX_INCONSISTENT_PARAMS)

    /* Take the sempahore */
    RETIF( (errCode = tmdlHdmiTxIWSemaphoreP(dlHdmiTxItSemaphore[instance]) ) != TM_OK, errCode)

    /* Check if unit corresponding to instance is opened */
    RETIF_SEM(dlHdmiTxItSemaphore[instance],
        unitTableTx[instance].opened == False, TMDL_ERR_DLHDMITX_RESOURCE_NOT_OWNED)

    /* Check the state */
    RETIF_SEM(dlHdmiTxItSemaphore[instance],
        dlHdmiTxGetState(instance) != STATE_INITIALIZED, TMDL_ERR_DLHDMITX_INVALID_STATE) 

    unitTableTx[instance].repeaterEnable = pSetupInfo->repeaterEnable;
    unitTableTx[instance].simplayHd = pSetupInfo->simplayHd;
    unitTableTx[instance].pEdidBuffer = pSetupInfo->pEdidBuffer;
    unitTableTx[instance].edidBufferSize = pSetupInfo->edidBufferSize;
    
#ifndef NO_HDCP
    /* Reset HDCP DevLib data */
    hdcpInfoListTx[instance].hdcpCheckState = TMDL_HDMITX_HDCP_CHECK_NOT_STARTED;
    hdcpInfoListTx[instance].hdcpErrorState = 0;
    hdcpInfoListTx[instance].hdcpKsvDevices = 0;
    hdcpInfoListTx[instance].bKsvSecure = False;
    for(i=0; i<TMDL_HDMITX_KSV_BYTES_PER_DEVICE; i++) { hdcpInfoListTx[instance].hdcpBksv[i] = 0; }
    hdcpInfoListTx[instance].hdcpDeviceDepth = 0;

    hdcpInfoListTx[instance].hdcpMaxCascExceeded = False;
    hdcpInfoListTx[instance].hdcpMaxDevsExceeded = False;
#endif /* NO_HDCP */

    /* Set state machine to Unplugged */
    dlHdmiTxSetState(instance, STATE_UNPLUGGED);

    /* Release the sempahore */
    RETIF( (errCode = tmdlHdmiTxIWSemaphoreV(dlHdmiTxItSemaphore[instance]) ) != TM_OK, errCode)

    return TM_OK;
}

/******************************************************************************
    \brief Get instance setup parameters.

    \param instance   Instance identifier.
    \param pSetupInfo Pointer to the structure that will receive setup
                      parameters.

    \return The call result:
            - TM_OK: the call was successful
            - TMDL_ERR_DLHDMITX_BAD_INSTANCE: the instance number is wrong or 
              out of range
            - TMDL_ERR_DLHDMITX_BAD_HANDLE: the handle number is wrong
            - TMDL_ERR_DLHDMITX_INCONSISTENT_PARAMS: an input parameter is
              inconsistent
            - TMDL_ERR_DLHDMITX_RESOURCE_NOT_OWNED: the caller does not own 
              the resource

******************************************************************************/
tmErrorCode_t tmdlHdmiTxGetInstanceSetup
(
    tmInstance_t                    instance,
    tmdlHdmiTxInstanceSetupInfo_t   *pSetupInfo
)
{
    tmErrorCode_t   errCode;

    /* Check if instance number is in range */
    RETIF((instance < 0) || (instance >= MAX_UNITS), TMDL_ERR_DLHDMITX_BAD_INSTANCE)

    /* Check if SetupInfo pointer is NULL */
    RETIF(pSetupInfo == Null, TMDL_ERR_DLHDMITX_INCONSISTENT_PARAMS)

    /* Take the sempahore */
    RETIF( (errCode = tmdlHdmiTxIWSemaphoreP(dlHdmiTxItSemaphore[instance]) ) != TM_OK, errCode)

    /* Check if unit corresponding to instance is opened */
    RETIF_SEM(dlHdmiTxItSemaphore[instance], 
        unitTableTx[instance].opened == False, TMDL_ERR_DLHDMITX_RESOURCE_NOT_OWNED)

    pSetupInfo->simplayHd          = unitTableTx[instance].simplayHd;
    pSetupInfo->repeaterEnable     = unitTableTx[instance].repeaterEnable;
    /* JL, TODO */

    /* Release the sempahore */
    RETIF( (errCode = tmdlHdmiTxIWSemaphoreV(dlHdmiTxItSemaphore[instance]) ) != TM_OK, errCode)

    return TM_OK;
}

/******************************************************************************
    \brief Make device library handle an incoming interrupt. This function is
           used by application to tell the device library that the hardware
           sent an interrupt.

    \param instance   Instance identifier.

    \return The call result:
            - TM_OK: the call was successful
            - TMDL_ERR_DLHDMITX_BAD_INSTANCE: the instance number is wrong or 
              out of range
            - TMDL_ERR_DLHDMITX_BAD_HANDLE: the handle number is wrong
            - TMDL_ERR_DLHDMITX_RESOURCE_NOT_OWNED: the caller does not own 
              the resource
            - TMDL_ERR_DLHDMITX_FULL: the queue is full

 ******************************************************************************/
tmErrorCode_t tmdlHdmiTxHandleInterrupt
(
    tmInstance_t    instance
)
{
#ifndef TMFL_NO_RTOS
    tmErrorCode_t errCode;
    UInt8         message = 0;
#else
    tmErrorCode_t err = TM_OK;
#endif /* TMFL_NO_RTOS */

   /* Check if instance number is in range */
    RETIF((instance < 0) || (instance >= MAX_UNITS), TMDL_ERR_DLHDMITX_BAD_INSTANCE)
 
#ifndef TMFL_NO_RTOS   
    RETIF( (errCode = tmdlHdmiTxIWQueueSend(unitTableTx[instance].queueHandle, message)) != TM_OK, errCode)

    /* Disable interrupts for Tx until the callbacks have been done by the command task */
    switch(instance)
    {
        case INSTANCE_0:
            tmdlHdmiTxIWDisableInterrupts(TMDL_HDMI_IW_TX_1);
            break;
        case INSTANCE_1:
            tmdlHdmiTxIWDisableInterrupts(TMDL_HDMI_IW_TX_2);
            break;
        default:
            return TMDL_ERR_DLHDMITX_BAD_INSTANCE;
    }
#else

        /* Clear T0 flag before polling for interrupts */
        instanceStatusInfoTx[0].pColBarState->hdcpSecureOrT0 = False;

        if (gI2CDebugAccessesEnabled == True)
        {

            err = tmbslHdmiTxHwHandleInterrupt(0);
        
            if ((err == TMBSL_ERR_HDMI_I2C_WRITE) || (err == TMBSL_ERR_HDMI_I2C_READ))
            {

                unitTableTx[0].pCallback(TMDL_HDMITX_DEBUG_EVENT_1);
            }

        }/* (gI2CDebugAccessesEnabled == True) */


#endif /* TMFL_NO_RTOS */

    return TM_OK;
}

/******************************************************************************
    \brief Register event callbacks. Only one callback is registered through
           this API. This callback will received the type of event that
           occured throug a dedicated parameter and will be called as many
           times as there is pending events.
           This function is synchronous.
           This function is ISR friendly.

    \param instance   Instance identifier.
    \param pCallback  Pointer to the callback function that will handle events
                      from the devlib.

    \return The call result:
            - TM_OK: the call was successful
            - TMDL_ERR_DLHDMITX_BAD_INSTANCE: the instance number is wrong or
              out of range
            - TMDL_ERR_DLHDMITX_BAD_HANDLE: the handle number is wrong
            - TMDL_ERR_DLHDMITX_RESOURCE_NOT_OWNED: the caller does not own
              the resource
            - TMDL_ERR_DLHDMITX_INVALID_STATE: the state is invalid for
              the function

******************************************************************************/
tmErrorCode_t tmdlHdmiTxRegisterCallbacks
(
    tmInstance_t            instance,
    ptmdlHdmiTxCallback_t   pCallback
)
{
    tmErrorCode_t   errCode;

    /* Check if instance number is in range */
    RETIF((instance < 0) || (instance >= MAX_UNITS), TMDL_ERR_DLHDMITX_BAD_INSTANCE)

    /* Take the sempahore */
    RETIF( (errCode = tmdlHdmiTxIWSemaphoreP(dlHdmiTxItSemaphore[instance]) ) != TM_OK, errCode)

    /* Check if unit corresponding to instance is opened */
    RETIF_SEM(dlHdmiTxItSemaphore[instance],
        unitTableTx[instance].opened == False, TMDL_ERR_DLHDMITX_RESOURCE_NOT_OWNED)
    
    /* Check if instance state is correct */
    RETIF_SEM(dlHdmiTxItSemaphore[instance],
        dlHdmiTxGetState(instance) != STATE_INITIALIZED, TMDL_ERR_DLHDMITX_INVALID_STATE)

    /* Store callback pointers */
    unitTableTx[instance].pCallback = pCallback;

    /* Release the sempahore */
    RETIF( (errCode = tmdlHdmiTxIWSemaphoreV(dlHdmiTxItSemaphore[instance]) ) != TM_OK, errCode)

    return TM_OK;
}

/******************************************************************************
    \brief This function allows enabling a specific event. By default, all
           events are disabled, except input lock.

    \param instance Instance identifier.
    \param event    Event to enable.

    \return The call result:
            - TM_OK: the call was successful
            - TMDL_ERR_DLHDMITX_BAD_INSTANCE: the instance number is wrong or 
              out of range
            - TMDL_ERR_DLHDMITX_BAD_HANDLE: the handle number is wrong

******************************************************************************/
tmErrorCode_t tmdlHdmiTxEnableEvent
(
    tmInstance_t        instance,
    tmdlHdmiTxEvent_t   event
)
{
    tmErrorCode_t   errCode;

    /* Check if instance number is in range */
    RETIF((instance < 0) || (instance >= MAX_UNITS), TMDL_ERR_DLHDMITX_BAD_INSTANCE)

    /* Check if the event exists */
    RETIF_BADPARAM(event >= EVENT_NB)

    /* Take the sempahore */
    RETIF( (errCode = tmdlHdmiTxIWSemaphoreP(dlHdmiTxItSemaphore[instance]) ) != TM_OK, errCode)

    /* Protect the access to this ressource */
    instanceStatusInfoTx[instance].pEventState[event].status = TMDL_HDMITX_EVENT_ENABLED;
  
    /* Release the sempahore */
    RETIF( (errCode = tmdlHdmiTxIWSemaphoreV(dlHdmiTxItSemaphore[instance]) ) != TM_OK, errCode)

    return TM_OK;
}

/******************************************************************************
    \brief This function allows disabling a specific event. By default, all
           events are disabled, except input lock.

    \param instance Instance identifier.
    \param event    Event to disable.

    \return The call result:
            - TM_OK: the call was successful
            - TMDL_ERR_DLHDMITX_BAD_INSTANCE: the instance number is wrong or 
              out of range
            - TMDL_ERR_DLHDMITX_BAD_HANDLE: the handle number is wrong

******************************************************************************/
tmErrorCode_t tmdlHdmiTxDisableEvent
(
    tmInstance_t        instance,
    tmdlHdmiTxEvent_t   event
)
{
    tmErrorCode_t   errCode;

    /* Check if instance number is in range */
    RETIF((instance < 0) || (instance >= MAX_UNITS), TMDL_ERR_DLHDMITX_BAD_INSTANCE)

    /* Check if the event exists */
    RETIF_BADPARAM(event >= EVENT_NB)

    /* Take the sempahore */
    RETIF( (errCode = tmdlHdmiTxIWSemaphoreP(dlHdmiTxItSemaphore[instance]) ) != TM_OK, errCode)

    /* Protect the access to this ressource */
    instanceStatusInfoTx[instance].pEventState[event].status = TMDL_HDMITX_EVENT_DISABLED;

    /* Release the sempahore */
    RETIF( (errCode = tmdlHdmiTxIWSemaphoreV(dlHdmiTxItSemaphore[instance]) ) != TM_OK, errCode)

    return TM_OK;
}

/******************************************************************************
    \brief Get specifications of a given video format. Application can use
           this function to retreives all specifications (frequencies,
           resolution, etc.) of a given IA/CEA 861-D video format.
           This function is synchronous.
           This function is ISR friendly.

    \param instance         Instance identifier.
    \param resolutionID     ID of the resolution to retrieve specs from.
    \param pResolutionSpecs Pointer to the structure receiving specs.

    \return The call result:
            - TM_OK: the call was successful
            - TMDL_ERR_DLHDMITX_BAD_INSTANCE: the instance number is wrong or
              out of range
            - TMDL_ERR_DLHDMITX_INCONSISTENT_PARAMS: an input parameter is
              inconsistent
            - TMDL_ERR_DLHDMITX_RESOLUTION_UNKNOWN: the resolution is unknown

******************************************************************************/
tmErrorCode_t tmdlHdmiTxGetVideoFormatSpecs
(
    tmInstance_t            instance,
    tmdlHdmiTxVidFmt_t      resolutionID,
    tmdlHdmiTxVidFmtSpecs_t *pResolutionSpecs
)
{
    UInt8	i;
    Bool    find = False;

    /* Check if instance number is in range */
    RETIF((instance < 0) || (instance >= MAX_UNITS), TMDL_ERR_DLHDMITX_BAD_INSTANCE)

    /* Check if ResolutionSpecs pointer is Null */
    RETIF(pResolutionSpecs == Null, TMDL_ERR_DLHDMITX_INCONSISTENT_PARAMS)

    for (i = 0; i < RESOLUTION_NB; i++)
    {
        if(resolutionID == gtmdlHdmiTxDriverConfigTable[instance].pResolutionInfo[i].resolutionID)
        {
            find = True;
            pResolutionSpecs->height      = gtmdlHdmiTxDriverConfigTable[instance].pResolutionInfo[i].height;
            pResolutionSpecs->width       = gtmdlHdmiTxDriverConfigTable[instance].pResolutionInfo[i].width;
            pResolutionSpecs->interlaced  = gtmdlHdmiTxDriverConfigTable[instance].pResolutionInfo[i].interlaced;
            pResolutionSpecs->vfrequency  = gtmdlHdmiTxDriverConfigTable[instance].pResolutionInfo[i].vfrequency;
            pResolutionSpecs->aspectRatio = gtmdlHdmiTxDriverConfigTable[instance].pResolutionInfo[i].aspectRatio;
            
            /* Transformation of 2D-interlaced formats into 3DFP-progressif formats */
            if((instanceStatusInfoTx[instance].pVideoInfo->videoInConfig.structure3D == TMDL_HDMITX_3D_FRAME_PACKING)
               && pResolutionSpecs->interlaced && ((resolutionID == TMDL_HDMITX_VFMT_20_1920x1080i_50Hz)
                                                   || (resolutionID == TMDL_HDMITX_VFMT_05_1920x1080i_60Hz)))
            {
                pResolutionSpecs->interlaced = False;
                if(pResolutionSpecs->vfrequency == TMDL_HDMITX_VFREQ_50Hz)
                {
                   pResolutionSpecs->vfrequency = TMDL_HDMITX_VFREQ_25Hz;
                }
                else if((pResolutionSpecs->vfrequency == TMDL_HDMITX_VFREQ_60Hz) || (pResolutionSpecs->vfrequency == TMDL_HDMITX_VFREQ_59Hz))
                {
                   pResolutionSpecs->vfrequency = TMDL_HDMITX_VFREQ_30Hz;
                }
            }
            
            break;
        }
    }

    /* Resolution not found in table */
    RETIF(find == False, TMDL_ERR_DLHDMITX_RESOLUTION_UNKNOWN)

    return TM_OK;
}

/******************************************************************************
    \brief Configures all input and output parameters : format, modes, rates,
           etc. This is the main configuration function of the driver. Here
           are transmitted all crucial input and output parameters of the
           device.
           This function is synchronous.
           This function is not ISR friendly.

    \param instance          Instance identifier.
    \param videoInputConfig  Configuration of the input video.
    \param videoOutputConfig Configuration of the output video.
    \param audioInputConfig  Configuration of the input audio.
    \param sinkType          Type of sink connected to the output of the Tx.

    \return The call result:
            - TM_OK: the call was successful
            - TMDL_ERR_DLHDMITX_BAD_INSTANCE: the instance number is wrong or
              out of range
            - TMDL_ERR_DLHDMITX_BAD_HANDLE: the handle number is wrong
            - TMBSL_ERR_HDMI_BAD_UNIT_NUMBER: bad transmitter unit number
            - TMBSL_ERR_HDMI_BAD_PARAMETER: a parameter was out of range
            - TMBSL_ERR_HDMI_NOT_INITIALIZED: transmitter not initialized
            - TMBSL_ERR_HDMI_I2C_WRITE: failed when writing to the I2C bus
            - TMBSL_ERR_HDMI_I2C_READ: failed when reading to the I2C bus
            - TMBSL_ERR_HDMI_OPERATION_NOT_PERMITTED: not allowed in DVI mode

******************************************************************************/
tmErrorCode_t tmdlHdmiTxSetInputOutput
(
    tmInstance_t                instance,
    tmdlHdmiTxVideoInConfig_t   videoInputConfig,
    tmdlHdmiTxVideoOutConfig_t  videoOutputConfig,
    tmdlHdmiTxAudioInConfig_t   audioInputConfig,
    tmdlHdmiTxSinkType_t        sinkType
)
{
    tmErrorCode_t           errCode;
    UInt8                   pixRepeat;                  /* Pixel repetition */
    tmbslHdmiTxVoutDbits_t  pathBits;                   /* Data path bit width */
    tmbslHdmiTxPixEdge_t    pixelEdge;                  /* Pixel sampling edge */
    tmbslHdmiTxVsMeth_t     syncMethod;                 /* Sync method */
    tmbslHdmiTxPixTogl_t    toggle;                     /* Toggling */
    UInt8                   syncIn;                     /* Embedded or external */
    tmbslHdmiTxPixSubpkt_t  spSync;                     /* Subpacket sync */
    tmbslHdmiTxBlnkSrc_t    blankit;                    /* Blanking */
    tmbslHdmiTxPixRate_t    pixRateSingleDouble;        /* HDMITX_PIXRATE_SINGLE */
    UInt16                  uRefPix;                    /* REFPIX for output */
    UInt16                  uRefLine;                   /* REFLINE for output */
    UInt16                  uScRefPix=0;                /* REFPIX for scaler */
    UInt16                  uScRefLine=0;               /* REFLINE for scaler */
    Bool                    bVerified;                  /* Scaler setting verified */
    tmbslHdmiTxTopSel_t     topSel;                     /* Adjustment for interlaced output */
    tmbslHdmiTxHPhases_t    phasesH;                    /* Horizontal phase */
    tmbslHdmiTxVsOnce_t     once;                       /* Line/pixel counters sync */
    tmbslHdmiTxScaMode_t    scalerMode;                 /* Current scaler mode */
    Bool                    OBASupported;               /* OBA supported or not */
    Bool                    DSTSupported;               /* DST supported or not */
    Bool                    HBRSupported;               /* HBR supporeted or not */

    UInt8                   *pSwapTable = Null;         /* Initialized after (depend on video mode used) */
    UInt8                   *pMirrorTable = Null;       /* Initialized after (depend on video mode used) */
#ifdef TMFL_TDA19988
    UInt8                   *pMux = Null;                 /* Initialized after (depend on video mode used) */
#endif
    UInt8                   *pEnaVideoPortTable = Null; /* Initialized after (depend on video mode used) */
    UInt8                   *pGndVideoPortTable = Null; /* Initialized after (depend on video mode used) */
    tmdlHdmiTxVidFmt_t      vinFmtIndex;                /* index in table kVfmtToShortFmt_TV */

    /* Check if instance number is in range */
    RETIF((instance < 0) || (instance >= MAX_UNITS), TMDL_ERR_DLHDMITX_BAD_INSTANCE)

    /* Take the sempahore */
    RETIF( (errCode = tmdlHdmiTxIWSemaphoreP(dlHdmiTxItSemaphore[instance]) ) != TM_OK, errCode)

    /* Update the instance status information */
    instanceStatusInfoTx[instance].pVideoInfo->videoInConfig.format       = videoInputConfig.format;
    instanceStatusInfoTx[instance].pVideoInfo->videoInConfig.mode         = videoInputConfig.mode;
    instanceStatusInfoTx[instance].pVideoInfo->videoInConfig.syncSource   = videoInputConfig.syncSource;
    instanceStatusInfoTx[instance].pVideoInfo->videoInConfig.pixelRate    = videoInputConfig.pixelRate;
    instanceStatusInfoTx[instance].pVideoInfo->videoInConfig.structure3D  = videoInputConfig.structure3D;

    instanceStatusInfoTx[instance].pVideoInfo->videoOutConfig.format      = videoOutputConfig.format;
    instanceStatusInfoTx[instance].pVideoInfo->videoOutConfig.mode        = videoOutputConfig.mode;
    instanceStatusInfoTx[instance].pVideoInfo->videoOutConfig.colorDepth  = videoOutputConfig.colorDepth;

    /* TODO */
    /*instanceStatusInfoTx[instance].pVideoInfo->videoMuteState            = */

    /* Audio OBA support */
    RETIF_SEM(dlHdmiTxItSemaphore[instance],
        (errCode = tmbslHdmiTxHwGetCapabilities(instance, 
        HDMITX_FEATURE_HW_AUDIO_OBA, &OBASupported) ) != TM_OK, errCode)

    /* Audio DST support */
    RETIF_SEM(dlHdmiTxItSemaphore[instance],
        (errCode = tmbslHdmiTxHwGetCapabilities(instance, 
        HDMITX_FEATURE_HW_AUDIO_DST, &DSTSupported) ) != TM_OK, errCode)

    /* Audio HBR support */
    RETIF_SEM(dlHdmiTxItSemaphore[instance],
        (errCode = tmbslHdmiTxHwGetCapabilities(instance, 
        HDMITX_FEATURE_HW_AUDIO_HBR, &HBRSupported) ) != TM_OK, errCode)

    /* Test if audio input format is supported */
    if ( ((audioInputConfig.format == TMDL_HDMITX_AFMT_OBA) && (OBASupported == False)) ||
	         ((audioInputConfig.format == TMDL_HDMITX_AFMT_DST) && (DSTSupported == False)) ||
             ((audioInputConfig.format == TMDL_HDMITX_AFMT_HBR) && (HBRSupported == False)) )
    {
        /* Release the sempahore */
        RETIF( (errCode = tmdlHdmiTxIWSemaphoreV(dlHdmiTxItSemaphore[instance]) ) != TM_OK, errCode)

        return TMDL_ERR_DLHDMITX_NOT_SUPPORTED;
    }

    instanceStatusInfoTx[instance].pAudioInfo->audioInCfg.format            = audioInputConfig.format;
    instanceStatusInfoTx[instance].pAudioInfo->audioInCfg.i2sFormat         = audioInputConfig.i2sFormat;
    instanceStatusInfoTx[instance].pAudioInfo->audioInCfg.i2sQualifier      = audioInputConfig.i2sQualifier;
    instanceStatusInfoTx[instance].pAudioInfo->audioInCfg.rate              = audioInputConfig.rate;
    instanceStatusInfoTx[instance].pAudioInfo->audioInCfg.channelAllocation = audioInputConfig.channelAllocation;


    if (sinkType == TMDL_HDMITX_SINK_EDID)
    {
        /* Change sink type with the currently defined in EDID */
        RETIF_SEM(dlHdmiTxItSemaphore[instance],
            (errCode = tmbslHdmiTxEdidGetSinkType(instance, 
            (tmbslHdmiTxSinkType_t *)&sinkType) ) != TM_OK, errCode)
    }

    /* forbid format with pixel repetition in DVI */
    if (sinkType == TMDL_HDMITX_SINK_DVI)
    {
        if(((videoOutputConfig.format >= TMDL_HDMITX_VFMT_06_720x480i_60Hz) && (videoOutputConfig.format <= TMDL_HDMITX_VFMT_15_1440x480p_60Hz)) 
        || ((videoOutputConfig.format >= TMDL_HDMITX_VFMT_21_720x576i_50Hz) && (videoOutputConfig.format <= TMDL_HDMITX_VFMT_30_1440x576p_50Hz)) 
        || ((videoOutputConfig.format >= TMDL_HDMITX_VFMT_35_2880x480p_60Hz)&& (videoOutputConfig.format <= TMDL_HDMITX_VFMT_38_2880x576p_50Hz))
          )
        {
            /* Release the sempahore */
            RETIF( (errCode = tmdlHdmiTxIWSemaphoreV(dlHdmiTxItSemaphore[instance]) ) != TM_OK, errCode)

            return TMDL_ERR_DLHDMITX_BAD_PARAMETER;
        }
    }
    
    /* Set color depth according to output config, transmitter termination is disable */
    RETIF_SEM(dlHdmiTxItSemaphore[instance],
        (errCode = tmbslHdmiTxSetColorDepth(instance, 
        (tmbslHdmiTxColorDepth)(videoOutputConfig.colorDepth), False) ) != TM_OK, errCode)

    /* Set the TMDS outputs to a forced state */
    errCode = tmbslHdmiTxTmdsSetOutputs(instance, 
        HDMITX_TMDSOUT_FORCED0);
    RETIF_SEM(dlHdmiTxItSemaphore[instance], (errCode != TM_OK) && (errCode != TMBSL_ERR_HDMI_NOT_SUPPORTED), errCode)

    /* Fine-tune the TMDS serializer */
    errCode = tmbslHdmiTxTmdsSetSerializer(instance, 
        4, 8);
    RETIF_SEM(dlHdmiTxItSemaphore[instance], (errCode != TM_OK) && (errCode != TMBSL_ERR_HDMI_NOT_SUPPORTED), errCode)

    /* Set video output configuration */
    RETIF_SEM(dlHdmiTxItSemaphore[instance],
        (errCode = tmbslHdmiTxVideoOutSetConfig(instance, 
        (tmbslHdmiTxSinkType_t)sinkType, (tmbslHdmiTxVoutMode_t)videoOutputConfig.mode, HDMITX_VOUT_PREFIL_OFF,
		HDMITX_VOUT_YUV_BLNK_16, HDMITX_VOUT_QRANGE_FS) ) != TM_OK, errCode)

    /* Set default config */
    pixRepeat   = HDMITX_PIXREP_DEFAULT;
    pathBits    = HDMITX_VOUT_DBITS_12;
#ifdef STB225_HDMI_SPECIFIC
    pixelEdge   = HDMITX_PIXEDGE_CLK_NEG;
#else
    pixelEdge   = HDMITX_PIXEDGE_CLK_POS;
#endif
    syncMethod  = HDMITX_VSMETH_V_H;
    toggle      = HDMITX_PIXTOGL_ENABLE;
    
    /* Set sync details */
    if (videoInputConfig.syncSource == TMDL_HDMITX_SYNCSRC_EMBEDDED)
    {
        /* Embedded sync */
        syncIn      = EMB;
        spSync      = HDMITX_PIXSUBPKT_SYNC_HEMB;
        blankit     = HDMITX_BLNKSRC_VS_HEMB_VEMB;
        syncMethod  = HDMITX_VSMETH_V_XDE;
    }
    else
    {
        /* External sync */
        syncIn  = EXT;


        if (gtmdlHdmiTxDriverConfigTable[instance].dataEnableSignalAvailable == 1)
        {
        /* DE is available */
        spSync  = HDMITX_PIXSUBPKT_SYNC_DE;
        }
        else
        {
        /* DE is NOT available */
        spSync  = HDMITX_PIXSUBPKT_SYNC_HS;
        }



        blankit = HDMITX_BLNKSRC_NOT_DE;
    }


#ifdef TMFL_TDA19988
    /* by default, mux is not used */
    pMux = &gtmdlHdmiTxDriverConfigTable[instance].pNoMux[0];
#endif

    /* Port swap table */
    switch(videoInputConfig.mode)
    {
        case TMDL_HDMITX_VINMODE_CCIR656:
            pathBits = HDMITX_VOUT_DBITS_8;
            pixelEdge = HDMITX_PIXEDGE_CLK_NEG;
            pSwapTable = gtmdlHdmiTxDriverConfigTable[instance].pSwapTableCCIR656;
            pMirrorTable = gtmdlHdmiTxDriverConfigTable[instance].pMirrorTableCCIR656;
            pEnaVideoPortTable = gtmdlHdmiTxDriverConfigTable[instance].pEnableVideoPortCCIR656;
            pGndVideoPortTable = gtmdlHdmiTxDriverConfigTable[instance].pGroundVideoPortCCIR656;
            break;

        case TMDL_HDMITX_VINMODE_RGB444:
            pSwapTable = gtmdlHdmiTxDriverConfigTable[instance].pSwapTableRGB444;
            pMirrorTable = gtmdlHdmiTxDriverConfigTable[instance].pMirrorTableRGB444;
            pEnaVideoPortTable = gtmdlHdmiTxDriverConfigTable[instance].pEnableVideoPortRGB444;
            pGndVideoPortTable = gtmdlHdmiTxDriverConfigTable[instance].pGroundVideoPortRGB444;
            break;

        case TMDL_HDMITX_VINMODE_YUV444:
            pSwapTable = gtmdlHdmiTxDriverConfigTable[instance].pSwapTableYUV444;
            pMirrorTable = gtmdlHdmiTxDriverConfigTable[instance].pMirrorTableYUV444;
            pEnaVideoPortTable = gtmdlHdmiTxDriverConfigTable[instance].pEnableVideoPortYUV444;
            pGndVideoPortTable = gtmdlHdmiTxDriverConfigTable[instance].pGroundVideoPortYUV444;
            break;

        case TMDL_HDMITX_VINMODE_YUV422:
            pSwapTable = gtmdlHdmiTxDriverConfigTable[instance].pSwapTableYUV422;
            pMirrorTable = gtmdlHdmiTxDriverConfigTable[instance].pMirrorTableYUV422;
            pEnaVideoPortTable = gtmdlHdmiTxDriverConfigTable[instance].pEnableVideoPortYUV422;
            pGndVideoPortTable = gtmdlHdmiTxDriverConfigTable[instance].pGroundVideoPortYUV422;
            break;

#ifdef TMFL_TDA19988
        case TMDL_HDMITX_VINMODE_RGB_DDR_12BITS:
            pSwapTable = gtmdlHdmiTxDriverConfigTable[instance].pSwapTableRGB_DDR_12bits;
            pMirrorTable = gtmdlHdmiTxDriverConfigTable[instance].pMirrorTableRGB_DDR_12bits;
            pMux = &gtmdlHdmiTxDriverConfigTable[instance].pMux_RGB_DDR_12bits[0];
            pEnaVideoPortTable = gtmdlHdmiTxDriverConfigTable[instance].pEnableVideoPortRGB_DDR_12bits;
            pGndVideoPortTable = gtmdlHdmiTxDriverConfigTable[instance].pGroundVideoPortRGB_DDR_12bits;
            break;
#endif
         default:
         break;
    }

    /* Set the audio and video input port configuration */
    errCode = tmbslHdmiTxSetVideoPortConfig(instance, pEnaVideoPortTable, pGndVideoPortTable);
    RETIF_SEM(dlHdmiTxItSemaphore[instance], (errCode != TM_OK) && (errCode != TMBSL_ERR_HDMI_NOT_SUPPORTED), errCode);

#ifdef TMFL_TDA19988
    errCode = tmbslHdmiTxVideoInSetMapping(instance, pSwapTable, pMirrorTable, pMux);
#else
    errCode = tmbslHdmiTxVideoInSetMapping(instance, pSwapTable, pMirrorTable);
#endif
    RETIF_SEM(dlHdmiTxItSemaphore[instance], (errCode != TM_OK) && (errCode != TMBSL_ERR_HDMI_NOT_SUPPORTED), errCode);
    
    /* Set fine image position */
    RETIF_SEM(dlHdmiTxItSemaphore[instance],
              (errCode = tmbslHdmiTxVideoInSetFine(instance, spSync, HDMITX_PIXTOGL_NO_ACTION) ) != TM_OK, errCode);

    /* Set input blanking */
    errCode = tmbslHdmiTxVideoInSetBlanking(instance, blankit, HDMITX_BLNKCODE_ALL_0);
    RETIF_SEM(dlHdmiTxItSemaphore[instance], (errCode != TM_OK) && (errCode != TMBSL_ERR_HDMI_NOT_SUPPORTED), errCode);

    /* Configure video input options and control the upsampler */
    RETIF_SEM(dlHdmiTxItSemaphore[instance],
              (errCode = tmbslHdmiTxVideoInSetConfig(instance, 
                                                     (tmbslHdmiTxVinMode_t)videoInputConfig.mode, (tmbslHdmiTxVidFmt_t)videoOutputConfig.format, 
                                                     (tmbslHdmiTx3DStructure_t)videoInputConfig.structure3D, pixelEdge, 
                                                     (tmbslHdmiTxPixRate_t)videoInputConfig.pixelRate, HDMITX_UPSAMPLE_AUTO) ) != TM_OK, errCode);


    /* Set input ouput - may give NOT_SUPPORTED error */
    RETIF_SEM(dlHdmiTxItSemaphore[instance],
              (errCode = tmbslHdmiTxVideoSetInOut(instance, (tmbslHdmiTxVidFmt_t)videoInputConfig.format, 
                                                  (tmbslHdmiTx3DStructure_t)videoInputConfig.structure3D, 
                                                  HDMITX_SCAMODE_AUTO, (tmbslHdmiTxVidFmt_t)videoOutputConfig.format,
                                                  pixRepeat, HDMITX_MATMODE_AUTO, pathBits, (tmbslHdmiTxVQR_t) videoOutputConfig.dviVqr) ) != TM_OK, errCode);


    /* Only set audio for HDMI, not DVI */
    if (sinkType == TMDL_HDMITX_SINK_HDMI)
    {
        /* Release the sempahore */
        RETIF( (errCode = tmdlHdmiTxIWSemaphoreV(dlHdmiTxItSemaphore[instance]) ) != TM_OK, errCode)
        /* Set audio parameters */
        RETIF( (errCode = tmdlHdmiTxSetAudioInput(instance, audioInputConfig, sinkType) ) != TM_OK, errCode)
        /* Take the sempahore */
        RETIF( (errCode = tmdlHdmiTxIWSemaphoreP(dlHdmiTxItSemaphore[instance]) ) != TM_OK, errCode)
    }

    /* Output fine adjustment */
    pixRateSingleDouble = (tmbslHdmiTxPixRate_t)videoInputConfig.pixelRate;
    if (videoInputConfig.pixelRate == HDMITX_PIXRATE_SINGLE_REPEATED)
    {
	    pixRateSingleDouble = HDMITX_PIXRATE_SINGLE;
    }
    

    if ((videoInputConfig.structure3D != HDMITX_3D_FRAME_PACKING) && 
        dlHdmiTxGetReflineRefpix(videoInputConfig.format, videoInputConfig.mode, videoOutputConfig.format, 
                                    syncIn, (tmdlHdmiTxPixRate_t)pixRateSingleDouble, &uRefPix, &uRefLine, 
									&uScRefPix, &uScRefLine, &bVerified) > 0)
    {
        /* From 720p50/60 or 1080i50/60 up-scaling to 1080p50/60, when external sync,
           toggleV, toggleH and toggleX need to be set to 0 */
        if (syncIn == EXT)
        {
            switch (videoInputConfig.format)
            {
                case TMDL_HDMITX_VFMT_04_1280x720p_60Hz:
                case TMDL_HDMITX_VFMT_19_1280x720p_50Hz:
                case TMDL_HDMITX_VFMT_05_1920x1080i_60Hz:
                case TMDL_HDMITX_VFMT_20_1920x1080i_50Hz:
                    if ( (videoOutputConfig.format == TMDL_HDMITX_VFMT_16_1920x1080p_60Hz) 
                        || (videoOutputConfig.format == TMDL_HDMITX_VFMT_31_1920x1080p_50Hz) )
                    {
                        toggle = HDMITX_PIXTOGL_NO_ACTION;
                    }
                    break;
                default:
                    toggle = HDMITX_PIXTOGL_ENABLE;
                    break;
            }
        }

        /* Combination found in table for scaler: configure input manually */
        RETIF_SEM(dlHdmiTxItSemaphore[instance],
            (errCode = tmbslHdmiTxVideoInSetSyncManual(instance, 
            (tmbslHdmiTxSyncSource_t)videoInputConfig.syncSource, syncMethod, toggle, toggle, toggle, uRefPix, uRefLine) ) != TM_OK, errCode)
    }
    else
    {
        /* Not found so assume non-scaler and auto-configure input */
        RETIF_SEM(dlHdmiTxItSemaphore[instance],
            (errCode = tmbslHdmiTxVideoInSetSyncAuto(instance, 
            (tmbslHdmiTxSyncSource_t)videoInputConfig.syncSource, (tmbslHdmiTxVidFmt_t)videoInputConfig.format,
			(tmbslHdmiTxVinMode_t)videoInputConfig.mode, (tmbslHdmiTx3DStructure_t)videoInputConfig.structure3D)) != TM_OK, errCode)
    }

    /* Only set infoframes for HDMI, not DVI */
    if (sinkType == TMDL_HDMITX_SINK_HDMI)
    {
	    /* Set avi infoframe */
        RETIF_SEM(dlHdmiTxItSemaphore[instance],
            (errCode = dlHdmiTxSetVideoInfoframe(instance, videoOutputConfig.format, videoOutputConfig.mode) ) != TM_OK, 
            errCode)
    }

    errCode = tmbslHdmiTxScalerGetMode(instance, 
                &scalerMode);

    /* Ignore scaler TMBSL_ERR_HDMI_NOT_SUPPORTED error */
    if ((errCode == TM_OK) && (scalerMode == HDMITX_SCAMODE_ON))
    {
        /* Enable scaler mode */
        RETIF_SEM(dlHdmiTxItSemaphore[instance],
            (errCode = tmbslHdmiTxScalerInDisable(instance, 
            False) ) != TM_OK, errCode) 

        /* Correction to interlace */
        topSel = HDMITX_TOPSEL_INTERNAL;
        if ((videoOutputConfig.format == TMDL_HDMITX_VFMT_05_1920x1080i_60Hz)
                || (videoOutputConfig.format == TMDL_HDMITX_VFMT_20_1920x1080i_50Hz))
        {
            /* video input format is range-checked by tmbslHdmiTxVideoSetInOut above */
            vinFmtIndex = dlHdmiTxCalcVidFmtIndex(videoInputConfig.format);
            if ((kVfmtToShortFmt_TV[vinFmtIndex] == TV_480p_60Hz)
            ||  (kVfmtToShortFmt_TV[vinFmtIndex] == TV_576p_50Hz))
            {
                /* Correct for 1080i output for p->i conversion only */
                topSel = HDMITX_TOPSEL_VRF;
            }
        }

        /* Set scaler field positions */
        RETIF_SEM(dlHdmiTxItSemaphore[instance],
            (errCode = tmbslHdmiTxScalerSetFieldOrder(instance, 
            HDMITX_INTEXT_NO_CHANGE, HDMITX_INTEXT_NO_CHANGE, topSel, HDMITX_TOPTGL_NO_CHANGE) ) != TM_OK, errCode) 

        /* Scaler fine adjustment */
        RETIF_SEM(dlHdmiTxItSemaphore[instance],
            (errCode = tmbslHdmiTxScalerSetFine(instance, 
            uScRefPix, uScRefLine) ) != TM_OK, errCode) 

        if ((videoOutputConfig.format == TMDL_HDMITX_VFMT_16_1920x1080p_60Hz) 
            || (videoOutputConfig.format == TMDL_HDMITX_VFMT_31_1920x1080p_50Hz))
        {
            phasesH = HDMITX_H_PHASES_16;
        }
        else
        {
            phasesH = HDMITX_H_PHASES_15;
        }

        /* Set scaler phase */
        RETIF_SEM(dlHdmiTxItSemaphore[instance],
            (errCode = tmbslHdmiTxScalerSetPhase(instance, 
            phasesH) ) != TM_OK, errCode) 

        /* Set scaler latency */
        RETIF_SEM(dlHdmiTxItSemaphore[instance],
            (errCode = tmbslHdmiTxScalerSetLatency(instance, 
            0x22) ) != TM_OK, errCode) 

        /* Set scaler synchronisation option */
        RETIF_SEM(dlHdmiTxItSemaphore[instance],
            (errCode = tmbslHdmiTxScalerSetSync(instance, 
            syncMethod, HDMITX_VSONCE_EACH_FRAME) ) != TM_OK, errCode) 

        /* With scaler, use Only Once setting for tmbslHdmiTxVideoOutSetSync */
        once = HDMITX_VSONCE_ONCE;
    }
    else
    {
        once = HDMITX_VSONCE_EACH_FRAME;
    }

    /* Set video synchronisation */
    RETIF_SEM(dlHdmiTxItSemaphore[instance],
        (errCode = tmbslHdmiTxVideoOutSetSync(instance, 
        HDMITX_VSSRC_INTERNAL, HDMITX_VSSRC_INTERNAL, HDMITX_VSSRC_INTERNAL, 
        HDMITX_VSTGL_TABLE, once) ) != TM_OK, errCode) 
	
    /* Release the sempahore */
    RETIF( (errCode = tmdlHdmiTxIWSemaphoreV(dlHdmiTxItSemaphore[instance]) ) != TM_OK, errCode)

    instanceStatusInfoTx[instance].pColBarState->inOutFirstSetDone = True;
    
    /* Test if pattern is already on */
    if (instanceStatusInfoTx[instance].pColBarState->colorBarOn == True)
    {
        /* If pattern is On, apply new settings */
        instanceStatusInfoTx[instance].pColBarState->changeColorBarNow = True;
    }

    return TM_OK;
}

/*****************************************************************************/
/**
    \brief Configures audio input parameters : format, rate, etc.
           This function is similar to tmdlHdmiTxSetInputOutput except that
           video is not reconfigured.
           This function is synchronous.
           This function is not ISR friendly.

    \param instance          Instance identifier.
    \param audioInputConfig  Configuration of the input audio.
    \param sinkType          Type of sink connected to the output of the Tx.

    \return The call result:
            - TM_OK: the call was successful
            - TMDL_ERR_DLHDMITX_BAD_INSTANCE: the instance number is wrong or
              out of range
            - TMDL_ERR_DLHDMITX_BAD_HANDLE: the handle number is wrong
            - TMBSL_ERR_HDMI_BAD_UNIT_NUMBER: bad transmitter unit number
            - TMBSL_ERR_HDMI_BAD_PARAMETER: a parameter was out of range
            - TMBSL_ERR_HDMI_NOT_INITIALIZED: transmitter not initialized
            - TMBSL_ERR_HDMI_I2C_WRITE: failed when writing to the I2C bus
            - TMBSL_ERR_HDMI_I2C_READ: failed when reading to the I2C bus
            - TMBSL_ERR_HDMI_OPERATION_NOT_PERMITTED: not allowed in DVI mode

******************************************************************************/
tmErrorCode_t tmdlHdmiTxSetAudioInput
(
    tmInstance_t                instance,
    tmdlHdmiTxAudioInConfig_t   audioInputConfig,
    tmdlHdmiTxSinkType_t        sinkType
)
{
    tmErrorCode_t           errCode;
    tmdlHdmiTxVidFmtSpecs_t resolutionSpecs;            /* Used to convert video format to video frequency */
    UInt8                   layout;                     /* 0 or 1 */
    UInt8                   aifChannelCountCode = 0;    /* audio info frame channels */
    tmbslHdmiTxVfreq_t      vOutFreq;                   /* Vertical output frequency */
    tmbslHdmiTxctsRef_t     ctsRef;                     /* CTS ref source */
    UInt16                  uCtsX;                      /* CtsX value */
    tmbslHdmiTxPktAif_t     pktAif;                     /* Audio infoframe packet */
    Bool                    OBASupported;               /* OBA supported or not */
    Bool                    DSTSupported;               /* DST supported or not */
    Bool                    HBRSupported;               /* HBR supporeted or not */
    UInt8                   *pEnaAudioPortCfg;
    UInt8                   *pGndAudioPortCfg;
    UInt8                   *pEnaAudioClockPortCfg;
    UInt8                   *pGndAudioClockPortCfg;

    /* Check if instance number is in range */
    RETIF((instance < 0) || (instance >= MAX_UNITS), TMDL_ERR_DLHDMITX_BAD_INSTANCE)

    /* Take the sempahore */
    RETIF( (errCode = tmdlHdmiTxIWSemaphoreP(dlHdmiTxItSemaphore[instance]) ) != TM_OK, errCode)

    /* Audio OBA support */
    RETIF_SEM(dlHdmiTxItSemaphore[instance],
        (errCode = tmbslHdmiTxHwGetCapabilities(instance, 
        HDMITX_FEATURE_HW_AUDIO_OBA, &OBASupported) ) != TM_OK, errCode)

    /* Audio DST support */
    RETIF_SEM(dlHdmiTxItSemaphore[instance],
        (errCode = tmbslHdmiTxHwGetCapabilities(instance, 
        HDMITX_FEATURE_HW_AUDIO_DST, &DSTSupported) ) != TM_OK, errCode)

    /* Audio HBR support */
    RETIF_SEM(dlHdmiTxItSemaphore[instance],
        (errCode = tmbslHdmiTxHwGetCapabilities(instance, 
        HDMITX_FEATURE_HW_AUDIO_HBR, &HBRSupported) ) != TM_OK, errCode)

    /* Test if audio input format is supported */
    if ( ((audioInputConfig.format == TMDL_HDMITX_AFMT_OBA) && (OBASupported == False)) ||
	         ((audioInputConfig.format == TMDL_HDMITX_AFMT_DST) && (DSTSupported == False)) ||
             ((audioInputConfig.format == TMDL_HDMITX_AFMT_HBR) && (HBRSupported == False)) )
    {
        /* Release the sempahore */
        RETIF( (errCode = tmdlHdmiTxIWSemaphoreV(dlHdmiTxItSemaphore[instance]) ) != TM_OK, errCode)

        return TMDL_ERR_DLHDMITX_NOT_SUPPORTED;
    }
    
    if (sinkType == TMDL_HDMITX_SINK_EDID)
    {
        /* Change sink type with the currently defined in EDID */
        RETIF_SEM(dlHdmiTxItSemaphore[instance],
            (errCode = tmbslHdmiTxEdidGetSinkType(instance, 
            (tmbslHdmiTxSinkType_t *)&sinkType) ) != TM_OK, errCode)
    }

    if (sinkType == TMDL_HDMITX_SINK_HDMI)
    {



	layout = 1;

	if (audioInputConfig.channelAllocation == 0x00) {
	  layout = 0;
	}

	aifChannelCountCode = kChanAllocChanNum[audioInputConfig.channelAllocation] - 1;


        /* Port audio configuration */
        switch(audioInputConfig.format)
        {
            case TMDL_HDMITX_AFMT_SPDIF:
                pEnaAudioPortCfg = gtmdlHdmiTxDriverConfigTable[instance].pEnableAudioPortSPDIF;
                pGndAudioPortCfg = gtmdlHdmiTxDriverConfigTable[instance].pGroundAudioPortSPDIF;
                pEnaAudioClockPortCfg = gtmdlHdmiTxDriverConfigTable[instance].pEnableAudioClockPortSPDIF;
                pGndAudioClockPortCfg = gtmdlHdmiTxDriverConfigTable[instance].pGroundAudioClockPortSPDIF;
                break;

            case TMDL_HDMITX_AFMT_I2S:
                pEnaAudioClockPortCfg = gtmdlHdmiTxDriverConfigTable[instance].pEnableAudioClockPortI2S;
                pGndAudioClockPortCfg = gtmdlHdmiTxDriverConfigTable[instance].pGroundAudioClockPortI2S;

                if(audioInputConfig.channelAllocation >= 1 ) /* For Multi channels */
                {
                    pEnaAudioPortCfg = gtmdlHdmiTxDriverConfigTable[instance].pEnableAudioPortI2S8C;
                    pGndAudioPortCfg = gtmdlHdmiTxDriverConfigTable[instance].pGroundAudioPortI2S8C;
                }
                else
                {
                    pEnaAudioPortCfg = gtmdlHdmiTxDriverConfigTable[instance].pEnableAudioPortI2S;
                    pGndAudioPortCfg = gtmdlHdmiTxDriverConfigTable[instance].pGroundAudioPortI2S;
                }
                break;

            case TMDL_HDMITX_AFMT_OBA:
                pEnaAudioPortCfg = gtmdlHdmiTxDriverConfigTable[instance].pEnableAudioPortOBA;
                pGndAudioPortCfg = gtmdlHdmiTxDriverConfigTable[instance].pGroundAudioPortOBA;
                pEnaAudioClockPortCfg = gtmdlHdmiTxDriverConfigTable[instance].pEnableAudioClockPortOBA;
                pGndAudioClockPortCfg = gtmdlHdmiTxDriverConfigTable[instance].pGroundAudioClockPortOBA;
                break;

            case TMDL_HDMITX_AFMT_DST:
                pEnaAudioPortCfg = gtmdlHdmiTxDriverConfigTable[instance].pEnableAudioPortDST;
                pGndAudioPortCfg = gtmdlHdmiTxDriverConfigTable[instance].pGroundAudioPortDST;
                pEnaAudioClockPortCfg = gtmdlHdmiTxDriverConfigTable[instance].pEnableAudioClockPortDST;
                pGndAudioClockPortCfg = gtmdlHdmiTxDriverConfigTable[instance].pGroundAudioClockPortDST;
                break;

            case TMDL_HDMITX_AFMT_HBR:
                pEnaAudioPortCfg = gtmdlHdmiTxDriverConfigTable[instance].pEnableAudioPortHBR;
                pGndAudioPortCfg = gtmdlHdmiTxDriverConfigTable[instance].pGroundAudioPortHBR;
                pEnaAudioClockPortCfg = gtmdlHdmiTxDriverConfigTable[instance].pEnableAudioClockPortHBR;
                pGndAudioClockPortCfg = gtmdlHdmiTxDriverConfigTable[instance].pGroundAudioClockPortHBR;
                break;

            default:
                /* Release the sempahore */
                RETIF( (errCode = tmdlHdmiTxIWSemaphoreV(dlHdmiTxItSemaphore[instance]) ) != TM_OK, errCode)

                return TMDL_ERR_DLHDMITX_BAD_PARAMETER;
        }

        errCode = tmbslHdmiTxSetAudioPortConfig(instance,
            pEnaAudioPortCfg, pGndAudioPortCfg);
        RETIF_SEM(dlHdmiTxItSemaphore[instance], (errCode != TM_OK) && (errCode != TMBSL_ERR_HDMI_NOT_SUPPORTED), errCode)

        errCode = tmbslHdmiTxSetAudioClockPortConfig(instance,
            pEnaAudioClockPortCfg, pGndAudioClockPortCfg);
        RETIF_SEM(dlHdmiTxItSemaphore[instance], (errCode != TM_OK) && (errCode != TMBSL_ERR_HDMI_NOT_SUPPORTED), errCode)

        RETIF_SEM(dlHdmiTxItSemaphore[instance],
            (errCode = tmbslHdmiTxAudioInSetConfig(instance, 
		    (tmbslHdmiTxaFmt_t)audioInputConfig.format, (tmbslHdmiTxI2sFor_t)audioInputConfig.i2sFormat, 
			audioInputConfig.channelAllocation, HDMITX_CHAN_NO_CHANGE, HDMITX_CLKPOLDSD_NO_CHANGE, HDMITX_SWAPDSD_NO_CHANGE,
			layout, HDMITX_LATENCY_CURRENT, (tmbslHdmiTxDstRate_t)audioInputConfig.dstRate) ) != TM_OK, errCode) 

        /* Find output vertical frequency from output format */
        RETIF_SEM(dlHdmiTxItSemaphore[instance],
            (errCode = tmdlHdmiTxGetVideoFormatSpecs(instance, instanceStatusInfoTx[instance].pVideoInfo->videoOutConfig.format,
            &resolutionSpecs) ) != TM_OK, errCode)
            vOutFreq = (tmbslHdmiTxVfreq_t)resolutionSpecs.vfrequency;

        if ((audioInputConfig.format == TMDL_HDMITX_AFMT_SPDIF)  
                || (audioInputConfig.format == TMDL_HDMITX_AFMT_OBA))
        {
            ctsRef = HDMITX_CTSREF_FS64SPDIF;
            uCtsX = HDMITX_CTSX_64;
        }
        else /* I2S */
        {
            ctsRef = HDMITX_CTSREF_ACLK;
            if (audioInputConfig.i2sQualifier == TMDL_HDMITX_I2SQ_32BITS)
            {
                uCtsX = HDMITX_CTSX_64;
            }
            else
            {
                uCtsX = HDMITX_CTSX_32;
            }
        }

        /* Set the Clock Time Stamp generator in HDMI mode only */
        RETIF_SEM(dlHdmiTxItSemaphore[instance],
            (errCode = tmbslHdmiTxAudioInSetCts(instance, 
            ctsRef, (tmbslHdmiTxafs_t)audioInputConfig.rate, (tmbslHdmiTxVidFmt_t)instanceStatusInfoTx[instance].pVideoInfo->videoOutConfig.format, 
			vOutFreq, HDMITX_CTS_AUTO, uCtsX, HDMITX_CTSK_USE_CTSX, HDMITX_CTSMTS_USE_CTSX,
			(tmbslHdmiTxDstRate_t)audioInputConfig.dstRate) ) != TM_OK, errCode)

        /* Set Channel Status registers
            No need to call tmbslTDA9984AudioOutSetChanStatusMapping, since default Byte 2
            values of "Do not take into account" are adequate */


        if (audioInputConfig.format != TMDL_HDMITX_AFMT_HBR) {

        RETIF_SEM(dlHdmiTxItSemaphore[instance],
            (errCode = tmbslHdmiTxAudioOutSetChanStatus(instance,
                                                        (tmbslHdmiTxAudioData_t)audioInputConfig.channelStatus.PcmIdentification,
                                                        (tmbslHdmiTxCSformatInfo_t)audioInputConfig.channelStatus.FormatInfo,
                                                        (tmbslHdmiTxCScopyright_t)audioInputConfig.channelStatus.CopyrightInfo,
                                                        audioInputConfig.channelStatus.categoryCode,
                                                        (tmbslHdmiTxafs_t)audioInputConfig.rate,
                                                        (tmbslHdmiTxCSclkAcc_t)audioInputConfig.channelStatus.clockAccuracy,
                                                        (tmbslHdmiTxCSmaxWordLength_t)audioInputConfig.channelStatus.maxWordLength,
                                                        (tmbslHdmiTxCSwordLength_t)audioInputConfig.channelStatus.wordLength,
                                                        (tmbslHdmiTxCSorigAfs_t)audioInputConfig.channelStatus.origSampleFreq))!= TM_OK, errCode)
            }
        else {


         RETIF_SEM(dlHdmiTxItSemaphore[instance],
            (errCode = tmbslHdmiTxAudioOutSetChanStatus(instance,
                                                        (tmbslHdmiTxAudioData_t)audioInputConfig.channelStatus.PcmIdentification,
                                                        (tmbslHdmiTxCSformatInfo_t)audioInputConfig.channelStatus.FormatInfo,
                                                        (tmbslHdmiTxCScopyright_t)audioInputConfig.channelStatus.CopyrightInfo,
                                                        audioInputConfig.channelStatus.categoryCode,
                                                        HDMITX_AFS_768K,
                                                        (tmbslHdmiTxCSclkAcc_t)audioInputConfig.channelStatus.clockAccuracy,
                                                        (tmbslHdmiTxCSmaxWordLength_t)audioInputConfig.channelStatus.maxWordLength,
                                                        (tmbslHdmiTxCSwordLength_t)audioInputConfig.channelStatus.wordLength,
                                                        (tmbslHdmiTxCSorigAfs_t)audioInputConfig.channelStatus.origSampleFreq))!= TM_OK, errCode)


        }

 
        /* Set reset_fifo to 1 */
        RETIF_SEM(dlHdmiTxItSemaphore[instance],
            (errCode = tmbslHdmiTxAudioOutSetMute(instance, 
            HDMITX_AMUTE_ON) ) != TM_OK, errCode)

        /* UN Mute audio only if previously not muted */
        if (instanceStatusInfoTx[instance].pAudioInfo->audioMuteState == False) {

               /* Wait for 20 ms */
               RETIF_SEM(dlHdmiTxItSemaphore[instance],(errCode = tmdlHdmiTxIWWait(20) ) != TM_OK, errCode)
               /* Set reset_fifo to 0 */
               RETIF_SEM(dlHdmiTxItSemaphore[instance],
                         (errCode = tmbslHdmiTxAudioOutSetMute(instance, 
                         HDMITX_AMUTE_OFF) ) != TM_OK, errCode)

         }


        /* Set audio infoframe */
        pktAif.ChannelCount     = aifChannelCountCode;
        pktAif.CodingType       = 0; /* refer to stream header */
        pktAif.SampleSize       = 0; /* refer to stream header */
        pktAif.ChannelAlloc     = audioInputConfig.channelAllocation;
        pktAif.LevelShift       = 0; /* 0dB level shift */
        pktAif.DownMixInhibit   = 0; /* down-mix stereo permitted */
        pktAif.SampleFreq       = AIF_SF_REFER_TO_STREAM_HEADER; /* refer to stream header */

        /* SampleFreq parameter need to be set for OBA and DST audio stream */
        if ( (audioInputConfig.format == TMDL_HDMITX_AFMT_OBA) ||
                (audioInputConfig.format == TMDL_HDMITX_AFMT_DST) )
        {
            switch (audioInputConfig.rate)
            {
                case TMDL_HDMITX_AFS_32K:
                    pktAif.SampleFreq = AIF_SF_32K; /* see table 18 of CEA-861 */
                    break;
                case TMDL_HDMITX_AFS_44K:
                    pktAif.SampleFreq = AIF_SF_44K; 
                    break;
                case TMDL_HDMITX_AFS_48K:
                    pktAif.SampleFreq = AIF_SF_48K; 
                    break;
                case TMDL_HDMITX_AFS_88K:
                    pktAif.SampleFreq = AIF_SF_88K; 
                    break;
                case TMDL_HDMITX_AFS_96K:
                    pktAif.SampleFreq = AIF_SF_96K; 
                    break;
                case TMDL_HDMITX_AFS_176K:
                    pktAif.SampleFreq = AIF_SF_176K; 
                    break;
                case TMDL_HDMITX_AFS_192K:
                    pktAif.SampleFreq = AIF_SF_192K; 
                    break;
                default:
                    pktAif.SampleFreq = AIF_SF_REFER_TO_STREAM_HEADER; /* refer to stream header */
                    break;
            }
        }

        RETIF_SEM(dlHdmiTxItSemaphore[instance],
            (errCode = tmbslHdmiTxPktSetAudioInfoframe(instance, 
            &pktAif, True) ) != TM_OK, errCode)
    }

    /* Release the sempahore */
    RETIF( (errCode = tmdlHdmiTxIWSemaphoreV(dlHdmiTxItSemaphore[instance]) ) != TM_OK, errCode)

    return TM_OK;
}

/******************************************************************************
    \brief Defines the content of AVI infoframe to be sent by Tx device.
           This function is synchronous.
           This function is not ISR friendly.

    \param instance     Instance identifier.
    \param enable       Enable/disable infoframe insertion.
    \param pAviIfData   Pointer to the structure containing AVI infoframe
                        parameters.

    \return The call result:
            - TM_OK: the call was successful
            - TMDL_ERR_DLHDMITX_BAD_INSTANCE: the instance number is wrong or
              out of range
            - TMDL_ERR_DLHDMITX_BAD_HANDLE: the handle number is wrong
            - TMDL_ERR_DLHDMITX_INCONSISTENT_PARAMS: an input parameter is
              inconsistent
            - TMBSL_ERR_HDMI_BAD_PARAMETER: a parameter was out of range
            - TMBSL_ERR_HDMI_BAD_UNIT_NUMBER: bad transmitter unit number
            - TMBSL_ERR_HDMI_I2C_WRITE: failed when writing to the I2C bus
            - TMBSL_ERR_HDMI_I2C_READ: failed when reading to the I2C bus
            - TMBSL_ERR_HDMI_NOT_INITIALIZED: transmitter not initialized
            - TMBSL_ERR_HDMI_OPERATION_NOT_PERMITTED: not allowed in DVI mode

******************************************************************************/
tmErrorCode_t tmdlHdmiTxSetVideoInfoframe
(
    tmInstance_t            instance,
    Bool                    enable,
    tmdlHdmiTxAviIfData_t   *pAviIfData
)
{
    tmErrorCode_t       errCode;

    /* Check if instance number is in range */
    RETIF((instance < 0) || (instance >= MAX_UNITS), TMDL_ERR_DLHDMITX_BAD_INSTANCE)

    /* Take the sempahore */
    RETIF( (errCode = tmdlHdmiTxIWSemaphoreP(dlHdmiTxItSemaphore[instance]) ) != TM_OK, errCode)

    if (enable == True)
    {
        /* Check if AviIfData pointer is Null */
        RETIF_SEM(dlHdmiTxItSemaphore[instance], pAviIfData == Null, TMDL_ERR_DLHDMITX_INCONSISTENT_PARAMS)

        errCode = dlHdmiTxSetRawVideoInfoframe(instance, pAviIfData, enable);
    }
    else
    {
        errCode = dlHdmiTxSetRawVideoInfoframe(instance, Null, enable);
    }

    /* Ignore infoframe interlock in DVI mode */
    if (errCode == TMBSL_ERR_HDMI_OPERATION_NOT_PERMITTED)
    {
        errCode = TM_OK;
    }

    RETIF_SEM(dlHdmiTxItSemaphore[instance], errCode != TM_OK, errCode)

    /* Release the sempahore */
    RETIF( (errCode = tmdlHdmiTxIWSemaphoreV(dlHdmiTxItSemaphore[instance]) ) != TM_OK, errCode)

    return TM_OK;
}

/******************************************************************************
    \brief Defines the content of AUD infoframe to be sent by Tx device.
           This function is synchronous.
           This function is not ISR friendly.

    \param instance     Instance identifier.
    \param enable       Enable/disable infoframe insertion.
    \param pAudIfData   Pointer to the structure containing AUD infoframe
                        parameters.

    \return The call result:
            - TM_OK: the call was successful
            - TMDL_ERR_DLHDMITX_BAD_INSTANCE: the instance number is wrong or
              out of range
            - TMDL_ERR_DLHDMITX_BAD_HANDLE: the handle number is wrong
            - TMDL_ERR_DLHDMITX_INCONSISTENT_PARAMS: an input parameter is
              inconsistent
            - TMBSL_ERR_HDMI_BAD_PARAMETER: a parameter was out of range
            - TMBSL_ERR_HDMI_BAD_UNIT_NUMBER: bad transmitter unit number
            - TMBSL_ERR_HDMI_I2C_WRITE: failed when writing to the I2C bus
            - TMBSL_ERR_HDMI_I2C_READ: failed when reading to the I2C bus
            - TMBSL_ERR_HDMI_NOT_INITIALIZED: transmitter not initialized
            - TMBSL_ERR_HDMI_OPERATION_NOT_PERMITTED: not allowed in DVI mode

******************************************************************************/
tmErrorCode_t tmdlHdmiTxSetAudioInfoframe
(
    tmInstance_t            instance,
    Bool                    enable,
    tmdlHdmiTxAudIfData_t   *pAudIfData
)
{
    tmErrorCode_t       errCode;

    /* Check if instance number is in range */
    RETIF((instance < 0) || (instance >= MAX_UNITS), TMDL_ERR_DLHDMITX_BAD_INSTANCE)

    /* Take the sempahore */
    RETIF( (errCode = tmdlHdmiTxIWSemaphoreP(dlHdmiTxItSemaphore[instance]) ) != TM_OK, errCode)

    if (enable == True)
    {
        /* Check if AudIfData pointer is Null */
        RETIF_SEM(dlHdmiTxItSemaphore[instance], pAudIfData == Null, TMDL_ERR_DLHDMITX_INCONSISTENT_PARAMS)

        RETIF_SEM(dlHdmiTxItSemaphore[instance], 
            (errCode = tmbslHdmiTxPktSetAudioInfoframe(instance,
            (tmbslHdmiTxPktAif_t *)pAudIfData, enable) ) != TM_OK, errCode)
    }
    else
    {
        RETIF_SEM(dlHdmiTxItSemaphore[instance], 
            (errCode = tmbslHdmiTxPktSetAudioInfoframe(instance,
            Null, enable) ) != TM_OK, errCode)
    }

    /* Release the sempahore */
    RETIF( (errCode = tmdlHdmiTxIWSemaphoreV(dlHdmiTxItSemaphore[instance]) ) != TM_OK, errCode)

    return TM_OK;
}

/******************************************************************************
    \brief Defines the content of the audio content protection packet to be
           sent by Tx device.
           This function is synchronous.
           This function is not ISR friendly.

    \param instance     Instance identifier.
    \param enable       Enable/disable infoframe insertion.
    \param pAcpPktData  Pointer to the structure containing ACP infoframe
                        parameters.

    \return The call result:
            - TM_OK: the call was successful
            - TMDL_ERR_DLHDMITX_BAD_INSTANCE: the instance number is wrong or
              out of range
            - TMDL_ERR_DLHDMITX_BAD_HANDLE: the handle number is wrong
            - TMDL_ERR_DLHDMITX_INCONSISTENT_PARAMS: an input parameter is
              inconsistent
            - TMBSL_ERR_HDMI_BAD_PARAMETER: a parameter was out of range
            - TMBSL_ERR_HDMI_BAD_UNIT_NUMBER: bad transmitter unit number
            - TMBSL_ERR_HDMI_I2C_WRITE: failed when writing to the I2C bus
            - TMBSL_ERR_HDMI_I2C_READ: failed when reading to the I2C bus
            - TMBSL_ERR_HDMI_NOT_INITIALIZED: transmitter not initialized
            - TMBSL_ERR_HDMI_OPERATION_NOT_PERMITTED: not allowed in DVI mode

******************************************************************************/
tmErrorCode_t tmdlHdmiTxSetACPPacket
(
    tmInstance_t            instance,
    Bool                    enable,
    tmdlHdmiTxAcpPktData_t  *pAcpPktData
)
{
    tmErrorCode_t       errCode;
    tmbslHdmiTxPkt_t    pkt;
    UInt8               i;

    /* Check if instance number is in range */
    RETIF((instance < 0) || (instance >= MAX_UNITS), TMDL_ERR_DLHDMITX_BAD_INSTANCE)

    /* Take the sempahore */
    RETIF( (errCode = tmdlHdmiTxIWSemaphoreP(dlHdmiTxItSemaphore[instance]) ) != TM_OK, errCode)

    if (enable == True)
    {
        /* Check if AcpPktData pointer is Null */
        RETIF_SEM(dlHdmiTxItSemaphore[instance], pAcpPktData == Null, TMDL_ERR_DLHDMITX_INCONSISTENT_PARAMS)

        switch (pAcpPktData->acpType)
        {
            /* Make sure bytes reserved are 0 */
            case 0 : /* Generic audio */
                for (i=0; i<28; i++) { pkt.dataByte[i] = 0; }
                break;

            case 1 : /* IEC 60958 identified audio */
                for (i=0; i<28; i++) { pkt.dataByte[i] = 0; }
                break;

            case 2 : /* DVD Audio */
                for (i=0; i<2; i++) { pkt.dataByte[i] = pAcpPktData->acpData[i]; }
                for (i=2; i<28; i++) { pkt.dataByte[i] = 0; }
                break;

            case 3 : /* SuperAudio CD */
                for (i=0; i<17; i++) { pkt.dataByte[i] = pAcpPktData->acpData[i]; }
                for (i=17; i<28; i++) { pkt.dataByte[i] = 0; }
                break;

            default :
                /* Release the sempahore */
                RETIF( (errCode = tmdlHdmiTxIWSemaphoreV(dlHdmiTxItSemaphore[instance]) ) != TM_OK, errCode)
                return TMDL_ERR_DLHDMITX_INCONSISTENT_PARAMS;
        }

        RETIF_SEM(dlHdmiTxItSemaphore[instance], 
            (errCode = tmbslHdmiTxPktSetAcp(instance,
            &pkt, 28, pAcpPktData->acpType, enable) ) != TM_OK, errCode)
    }
    else
    {
        RETIF_SEM(dlHdmiTxItSemaphore[instance], 
            (errCode = tmbslHdmiTxPktSetAcp(instance,
            Null, 0, 0, enable) ) != TM_OK, errCode)
    }

    /* Release the sempahore */
    RETIF( (errCode = tmdlHdmiTxIWSemaphoreV(dlHdmiTxItSemaphore[instance]) ) != TM_OK, errCode)

    return TM_OK;
}

/******************************************************************************
    \brief Defines the content of the General Control packet to be sent by Tx
           device.
           This function is synchronous.
           This function is not ISR friendly.

    \param instance     Instance identifier.
    \param enable       Enable/disable infoframe insertion.
    \param pGcpPktData  Pointer to the structure containing GCP packet parameters.

    \return The call result:
            - TM_OK: the call was successful
            - TMDL_ERR_DLHDMITX_BAD_INSTANCE: the instance number is wrong or
              out of range
            - TMDL_ERR_DLHDMITX_BAD_HANDLE: the handle number is wrong
            - TMDL_ERR_DLHDMITX_INCONSISTENT_PARAMS: an input parameter is
              inconsistent
            - TMBSL_ERR_HDMI_BAD_PARAMETER: a parameter was out of range
            - TMBSL_ERR_HDMI_BAD_UNIT_NUMBER: bad transmitter unit number
            - TMBSL_ERR_HDMI_I2C_WRITE: failed when writing to the I2C bus
            - TMBSL_ERR_HDMI_I2C_READ: failed when reading to the I2C bus
            - TMBSL_ERR_HDMI_NOT_INITIALIZED: transmitter not initialized
            - TMBSL_ERR_HDMI_OPERATION_NOT_PERMITTED: not allowed in DVI mode

******************************************************************************/
tmErrorCode_t tmdlHdmiTxSetGeneralControlPacket
(
    tmInstance_t            instance,
    Bool                    enable,
    tmdlHdmiTxGcpPktData_t  *pGcpPktData
)
{
    tmErrorCode_t       errCode;
    tmbslHdmiTxaMute_t  aMute;

    /* Check if instance number is in range */
    RETIF((instance < 0) || (instance >= MAX_UNITS), TMDL_ERR_DLHDMITX_BAD_INSTANCE)

    /* Take the sempahore */
    RETIF( (errCode = tmdlHdmiTxIWSemaphoreP(dlHdmiTxItSemaphore[instance]) ) != TM_OK, errCode)
    
    if (enable == True)
    {
        /* Check if GcpPktData pointer is Null */
        RETIF_SEM(dlHdmiTxItSemaphore[instance], pGcpPktData == Null, TMDL_ERR_DLHDMITX_INCONSISTENT_PARAMS)

        if(pGcpPktData->avMute == False)
        {
            aMute = HDMITX_AMUTE_OFF;
        }
        else
        {
            aMute = HDMITX_AMUTE_ON;
        }

        /* Set contents of general control packet & enable/disable packet insertion */
        RETIF_SEM(dlHdmiTxItSemaphore[instance], 
            (errCode = tmbslHdmiTxPktSetGeneralCntrl(instance,
            &aMute, enable) ) != TM_OK, errCode)
    }
    else
    {
        RETIF_SEM(dlHdmiTxItSemaphore[instance], 
            (errCode = tmbslHdmiTxPktSetGeneralCntrl(instance,
            Null, enable) ) != TM_OK, errCode)
    }

    /* Release the sempahore */
    RETIF( (errCode = tmdlHdmiTxIWSemaphoreV(dlHdmiTxItSemaphore[instance]) ) != TM_OK, errCode)

    return TM_OK;
}

/******************************************************************************
    \brief Defines the content of ISRC1 packet to be sent by Tx device.
           This function is synchronous.
           This function is not ISR friendly.

    \param instance         Instance identifier.
    \param enable           Enable/disable infoframe insertion.
    \param pIsrc1PktData    Pointer to the structure containing GCP packet parameters.

    \return The call result:
            - TM_OK: the call was successful
            - TMDL_ERR_DLHDMITX_BAD_INSTANCE: the instance number is wrong or
              out of range
            - TMDL_ERR_DLHDMITX_BAD_HANDLE: the handle number is wrong
            - TMDL_ERR_DLHDMITX_INCONSISTENT_PARAMS: an input parameter is
              inconsistent
            - TMBSL_ERR_HDMI_BAD_PARAMETER: a parameter was out of range
            - TMBSL_ERR_HDMI_BAD_UNIT_NUMBER: bad transmitter unit number
            - TMBSL_ERR_HDMI_I2C_WRITE: failed when writing to the I2C bus
            - TMBSL_ERR_HDMI_I2C_READ: failed when reading to the I2C bus
            - TMBSL_ERR_HDMI_NOT_INITIALIZED: transmitter not initialized
            - TMBSL_ERR_HDMI_OPERATION_NOT_PERMITTED: not allowed in DVI mode

******************************************************************************/
tmErrorCode_t tmdlHdmiTxSetISRC1Packet
(
    tmInstance_t                instance,
    Bool                        enable,
    tmdlHdmiTxIsrc1PktData_t    *pIsrc1PktData
)
{
    tmErrorCode_t       errCode;

    /* Check if instance number is in range */
    RETIF((instance < 0) || (instance >= MAX_UNITS), TMDL_ERR_DLHDMITX_BAD_INSTANCE)

    /* Take the sempahore */
    RETIF( (errCode = tmdlHdmiTxIWSemaphoreP(dlHdmiTxItSemaphore[instance]) ) != TM_OK, errCode)
    
    if (enable == True)
    {
        /* Check if Isrc1PktData pointer is Null */
        RETIF_SEM(dlHdmiTxItSemaphore[instance], pIsrc1PktData == Null, TMDL_ERR_DLHDMITX_INCONSISTENT_PARAMS)

        RETIF_SEM(dlHdmiTxItSemaphore[instance], 
            (errCode = tmbslHdmiTxPktSetIsrc1(instance,
            (tmbslHdmiTxPkt_t *)pIsrc1PktData->UPC_EAN_ISRC, 16, pIsrc1PktData->isrcCont, 
            pIsrc1PktData->isrcValid, pIsrc1PktData->isrcStatus, enable) ) != TM_OK, errCode)
    }
    else
    {
        RETIF_SEM(dlHdmiTxItSemaphore[instance], 
            (errCode = tmbslHdmiTxPktSetIsrc1(instance,
            Null, 0, 0, 0, 0, enable) ) != TM_OK, errCode)
    }

    /* Release the sempahore */
    RETIF( (errCode = tmdlHdmiTxIWSemaphoreV(dlHdmiTxItSemaphore[instance]) ) != TM_OK, errCode)

    return TM_OK;
}

/******************************************************************************
    \brief Defines the content of ISRC2 packet to be sent by Tx device.
           This function is synchronous.
           This function is not ISR friendly.

    \param instance         Instance identifier.
    \param enable           Enable/disable infoframe insertion.
    \param pIsrc2PktData    Pointer to the structure containing GCP packet parameters.

    \return The call result:
            - TM_OK: the call was successful
            - TMDL_ERR_DLHDMITX_BAD_INSTANCE: the instance number is wrong or
              out of range
            - TMDL_ERR_DLHDMITX_BAD_HANDLE: the handle number is wrong
            - TMDL_ERR_DLHDMITX_INCONSISTENT_PARAMS: an input parameter is
              inconsistent
            - TMBSL_ERR_HDMI_BAD_PARAMETER: a parameter was out of range
            - TMBSL_ERR_HDMI_BAD_UNIT_NUMBER: bad transmitter unit number
            - TMBSL_ERR_HDMI_I2C_WRITE: failed when writing to the I2C bus
            - TMBSL_ERR_HDMI_I2C_READ: failed when reading to the I2C bus
            - TMBSL_ERR_HDMI_NOT_INITIALIZED: transmitter not initialized
            - TMBSL_ERR_HDMI_OPERATION_NOT_PERMITTED: not allowed in DVI mode

******************************************************************************/
tmErrorCode_t tmdlHdmiTxSetISRC2Packet
(
    tmInstance_t                instance,
    Bool                        enable,
    tmdlHdmiTxIsrc2PktData_t    *pIsrc2PktData
)
{
    tmErrorCode_t       errCode;

    /* Check if instance number is in range */
    RETIF((instance < 0) || (instance >= MAX_UNITS), TMDL_ERR_DLHDMITX_BAD_INSTANCE)

    /* Take the sempahore */
    RETIF( (errCode = tmdlHdmiTxIWSemaphoreP(dlHdmiTxItSemaphore[instance]) ) != TM_OK, errCode)

    if (enable == True)
    {
        /* Check if Isrc1PktData pointer is Null */
        RETIF_SEM(dlHdmiTxItSemaphore[instance], pIsrc2PktData == Null, TMDL_ERR_DLHDMITX_INCONSISTENT_PARAMS)

        RETIF_SEM(dlHdmiTxItSemaphore[instance], 
            (errCode = tmbslHdmiTxPktSetIsrc2(instance,
            (tmbslHdmiTxPkt_t *)pIsrc2PktData->UPC_EAN_ISRC, 16, enable) ) != TM_OK, errCode)
    }
    else
    {
        RETIF_SEM(dlHdmiTxItSemaphore[instance], 
            (errCode = tmbslHdmiTxPktSetIsrc2(instance,
            Null, 0, enable) ) != TM_OK, errCode)
    }

    /* Release the sempahore */
    RETIF( (errCode = tmdlHdmiTxIWSemaphoreV(dlHdmiTxItSemaphore[instance]) ) != TM_OK, errCode)

    return TM_OK;
}

/******************************************************************************
    \brief Defines the content of MPS infoframe to be sent by Tx device.
           This function is synchronous.
           This function is not ISR friendly.

    \param instance     Instance identifier.
    \param enable       Enable/disable infoframe insertion.
    \param pMpsIfData   Pointer to the structure containing MPS infoframe
                        parameters.

    \return The call result:
            - TM_OK: the call was successful
            - TMDL_ERR_DLHDMITX_BAD_INSTANCE: the instance number is wrong or
              out of range
            - TMDL_ERR_DLHDMITX_BAD_HANDLE: the handle number is wrong
            - TMDL_ERR_DLHDMITX_INCONSISTENT_PARAMS: an input parameter is
              inconsistent
            - TMBSL_ERR_HDMI_BAD_PARAMETER: a parameter was out of range
            - TMBSL_ERR_HDMI_BAD_UNIT_NUMBER: bad transmitter unit number
            - TMBSL_ERR_HDMI_I2C_WRITE: failed when writing to the I2C bus
            - TMBSL_ERR_HDMI_I2C_READ: failed when reading to the I2C bus
            - TMBSL_ERR_HDMI_NOT_INITIALIZED: transmitter not initialized
            - TMBSL_ERR_HDMI_OPERATION_NOT_PERMITTED: not allowed in DVI mode

******************************************************************************/
tmErrorCode_t tmdlHdmiTxSetMPSInfoframe
(
    tmInstance_t            instance,
    Bool                    enable,
    tmdlHdmiTxMpsIfData_t   *pMpsIfData
)
{
    tmErrorCode_t           errCode;

    /* Check if instance number is in range */
    RETIF((instance < 0) || (instance >= MAX_UNITS), TMDL_ERR_DLHDMITX_BAD_INSTANCE)

    /* Take the sempahore */
    RETIF( (errCode = tmdlHdmiTxIWSemaphoreP(dlHdmiTxItSemaphore[instance]) ) != TM_OK, errCode)

    if (enable == True)
    {
        /* Check if MpsIfData pointer is Null */
        RETIF_SEM(dlHdmiTxItSemaphore[instance], pMpsIfData == Null, TMDL_ERR_DLHDMITX_INCONSISTENT_PARAMS)

        RETIF_SEM(dlHdmiTxItSemaphore[instance], 
            (errCode = tmbslHdmiTxPktSetMpegInfoframe(instance,
            (tmbslHdmiTxPktMpeg_t *)pMpsIfData, enable) ) != TM_OK, errCode)
    }
    else
    {
        RETIF_SEM(dlHdmiTxItSemaphore[instance], 
            (errCode = tmbslHdmiTxPktSetMpegInfoframe(instance,
            Null, enable) ) != TM_OK, errCode)
    }

    /* Release the sempahore */
    RETIF( (errCode = tmdlHdmiTxIWSemaphoreV(dlHdmiTxItSemaphore[instance]) ) != TM_OK, errCode)

    return TM_OK;
}

/******************************************************************************
    \brief Defines the content of SPD infoframe to be sent by Tx device.
           This function is synchronous.
           This function is not ISR friendly.

    \param instance     Instance identifier.
    \param enable       Enable/disable infoframe insertion.
    \param pSpdIfData   Pointer to the structure containing SPD infoframe
                        parameters.

    \return The call result:
            - TM_OK: the call was successful
            - TMDL_ERR_DLHDMITX_BAD_INSTANCE: the instance number is wrong or
              out of range
            - TMDL_ERR_DLHDMITX_BAD_HANDLE: the handle number is wrong
            - TMDL_ERR_DLHDMITX_INCONSISTENT_PARAMS: an input parameter is
              inconsistent
            - TMBSL_ERR_HDMI_BAD_PARAMETER: a parameter was out of range
            - TMBSL_ERR_HDMI_BAD_UNIT_NUMBER: bad transmitter unit number
            - TMBSL_ERR_HDMI_I2C_WRITE: failed when writing to the I2C bus
            - TMBSL_ERR_HDMI_I2C_READ: failed when reading to the I2C bus
            - TMBSL_ERR_HDMI_NOT_INITIALIZED: transmitter not initialized
            - TMBSL_ERR_HDMI_OPERATION_NOT_PERMITTED: not allowed in DVI mode

******************************************************************************/
tmErrorCode_t tmdlHdmiTxSetSpdInfoframe
(
    tmInstance_t            instance,
    Bool                    enable,
    tmdlHdmiTxSpdIfData_t   *pSpdIfData
)
{
    tmErrorCode_t       errCode;
    
    /* Check if instance number is in range */
    RETIF((instance < 0) || (instance >= MAX_UNITS), TMDL_ERR_DLHDMITX_BAD_INSTANCE)

    /* Take the sempahore */
    RETIF( (errCode = tmdlHdmiTxIWSemaphoreP(dlHdmiTxItSemaphore[instance]) ) != TM_OK, errCode)

    if (enable == True)
    {
        /* Check if SpdIfData pointer is Null */
        RETIF_SEM(dlHdmiTxItSemaphore[instance], pSpdIfData == Null, TMDL_ERR_DLHDMITX_INCONSISTENT_PARAMS)

        RETIF_SEM(dlHdmiTxItSemaphore[instance],
            (errCode = tmbslHdmiTxPktSetSpdInfoframe(instance,
            (tmbslHdmiTxPktSpd_t *)pSpdIfData, enable) ) != TM_OK, errCode)
    }
    else
    {
        RETIF_SEM(dlHdmiTxItSemaphore[instance],
            (errCode = tmbslHdmiTxPktSetSpdInfoframe(instance,
            Null, enable) ) != TM_OK, errCode)
    }

    /* Release the sempahore */
    RETIF( (errCode = tmdlHdmiTxIWSemaphoreV(dlHdmiTxItSemaphore[instance]) ) != TM_OK, errCode)

    return TM_OK;
}

/******************************************************************************
    \brief Defines the content of VS infoframe to be sent by Tx device.
           This function is synchronous.
           This function is not ISR friendly.

    \param instance     Instance identifier.
    \param enable       Enable/disable infoframe insertion.
    \param pVsIfData    Pointer to the structure containing VS infoframe
                        parameters.

    \return The call result:
            - TM_OK: the call was successful
            - TMDL_ERR_DLHDMITX_BAD_INSTANCE: the instance number is wrong or
              out of range
            - TMDL_ERR_DLHDMITX_BAD_HANDLE: the handle number is wrong
            - TMDL_ERR_DLHDMITX_INCONSISTENT_PARAMS: an input parameter is
              inconsistent
            - TMBSL_ERR_HDMI_BAD_PARAMETER: a parameter was out of range
            - TMBSL_ERR_HDMI_BAD_UNIT_NUMBER: bad transmitter unit number
            - TMBSL_ERR_HDMI_I2C_WRITE: failed when writing to the I2C bus
            - TMBSL_ERR_HDMI_I2C_READ: failed when reading to the I2C bus
            - TMBSL_ERR_HDMI_NOT_INITIALIZED: transmitter not initialized
            - TMBSL_ERR_HDMI_OPERATION_NOT_PERMITTED: not allowed in DVI mode

******************************************************************************/
tmErrorCode_t tmdlHdmiTxSetVsInfoframe
(
    tmInstance_t            instance,
    Bool                    enable,
    tmdlHdmiTxVsPktData_t   *pVsIfData
)
{
    tmErrorCode_t       errCode;
    
    /* Check if instance number is in range */
    RETIF((instance < 0) || (instance >= MAX_UNITS), TMDL_ERR_DLHDMITX_BAD_INSTANCE)

    /* Take the sempahore */
    RETIF( (errCode = tmdlHdmiTxIWSemaphoreP(dlHdmiTxItSemaphore[instance]) ) != TM_OK, errCode)

    if (enable == True)
    {
        /* Check if VsIfData pointer is Null */
        RETIF_SEM(dlHdmiTxItSemaphore[instance], pVsIfData == Null, TMDL_ERR_DLHDMITX_INCONSISTENT_PARAMS)

        RETIF_SEM(dlHdmiTxItSemaphore[instance],
            (errCode = tmbslHdmiTxPktSetVsInfoframe(instance,
            (tmbslHdmiTxPkt_t *)pVsIfData->vsData, HDMITX_PKT_DATA_BYTE_CNT-1, pVsIfData->version, enable) ) != TM_OK, errCode)
    }
    else
    {
        RETIF_SEM(dlHdmiTxItSemaphore[instance], 
            (errCode = tmbslHdmiTxPktSetVsInfoframe(instance,
            Null, 0, pVsIfData->version, enable) ) != TM_OK, errCode)
    }

    /* Release the sempahore */
    RETIF( (errCode = tmdlHdmiTxIWSemaphoreV(dlHdmiTxItSemaphore[instance]) ) != TM_OK, errCode)

    return TM_OK;
}

/******************************************************************************
    \brief Enables/disables NULL packet sending (only used for debug purpose).
           This function is synchronous.
           This function is not ISR friendly.

    \param instance  Instance identifier.
    \param enable    Enable/disable packet insertion.

    \return The call result:
            - TM_OK: the call was successful
            - TMDL_ERR_DLHDMITX_BAD_INSTANCE: the instance number is wrong or
              out of range
            - TMDL_ERR_DLHDMITX_BAD_HANDLE: the handle number is wrong
            - TMBSL_ERR_HDMI_BAD_PARAMETER: a parameter was out of range
            - TMBSL_ERR_HDMI_BAD_UNIT_NUMBER: bad transmitter unit number
            - TMBSL_ERR_HDMI_I2C_WRITE: failed when writing to the I2C bus
            - TMBSL_ERR_HDMI_I2C_READ: failed when reading to the I2C bus
            - TMBSL_ERR_HDMI_NOT_INITIALIZED: transmitter not initialized
            - TMBSL_ERR_HDMI_OPERATION_NOT_PERMITTED: not allowed in DVI mode

******************************************************************************/
tmErrorCode_t tmdlHdmiTxDebugSetNullPacket
(
    tmInstance_t    instance,
    Bool            enable
)
{
    tmErrorCode_t   errCode;

    /* Check if instance number is in range */
    RETIF((instance < 0) || (instance >= MAX_UNITS), TMDL_ERR_DLHDMITX_BAD_INSTANCE)

    /* Take the sempahore */
    RETIF( (errCode = tmdlHdmiTxIWSemaphoreP(dlHdmiTxItSemaphore[instance]) ) != TM_OK, errCode)

    RETIF_SEM(dlHdmiTxItSemaphore[instance], 
        (errCode = tmbslHdmiTxPktSetNullInsert(instance,
        enable) ) != TM_OK, errCode)


    /* Release the sempahore */
    RETIF( (errCode = tmdlHdmiTxIWSemaphoreV(dlHdmiTxItSemaphore[instance]) ) != TM_OK, errCode)

    return TM_OK;
}

/******************************************************************************
    \brief Send one single NULL packet (only used for debug purpose).
           This function is synchronous.
           This function is not ISR friendly.

    \param instance  Instance identifier.

    \return The call result:
            - TM_OK: the call was successful
            - TMDL_ERR_DLHDMITX_BAD_INSTANCE: the instance number is wrong or
              out of range
            - TMDL_ERR_DLHDMITX_BAD_HANDLE: the handle number is wrong
            - TMBSL_ERR_HDMI_BAD_PARAMETER: a parameter was out of range
            - TMBSL_ERR_HDMI_BAD_UNIT_NUMBER: bad transmitter unit number
            - TMBSL_ERR_HDMI_I2C_WRITE: failed when writing to the I2C bus
            - TMBSL_ERR_HDMI_I2C_READ: failed when reading to the I2C bus
            - TMBSL_ERR_HDMI_NOT_INITIALIZED: transmitter not initialized
            - TMBSL_ERR_HDMI_OPERATION_NOT_PERMITTED: not allowed in DVI mode

******************************************************************************/
tmErrorCode_t tmdlHdmiTxDebugSetSingleNullPacket
(
    tmInstance_t    instance
)
{
    tmErrorCode_t   errCode;

    /* Check if instance number is in range */
    RETIF((instance < 0) || (instance >= MAX_UNITS), TMDL_ERR_DLHDMITX_BAD_INSTANCE)

    /* Take the sempahore */
    RETIF( (errCode = tmdlHdmiTxIWSemaphoreP(dlHdmiTxItSemaphore[instance]) ) != TM_OK, errCode)

    RETIF_SEM(dlHdmiTxItSemaphore[instance], 
        (errCode = tmbslHdmiTxPktSetNullSingle(instance) )
        != TM_OK, errCode)

    /* Release the sempahore */
    RETIF( (errCode = tmdlHdmiTxIWSemaphoreV(dlHdmiTxItSemaphore[instance]) ) != TM_OK, errCode)

    return TM_OK;
}

/******************************************************************************
    \brief Set the audio output mute status. This function can be used to mute
           audio output, without muting video. This can be typically used when
           reconfiguring the audio HW after a sample rate change.
           This function is synchronous.
           This function is not ISR friendly.

    \param instance   Instance identifier.
    \param muteStatus Mute status (True/False).

    \return The call result:
            - TM_OK: the call was successful
            - TMDL_ERR_DLHDMITX_BAD_INSTANCE: the instance number is wrong or
              out of range
            - TMDL_ERR_DLHDMITX_BAD_HANDLE: the handle number is wrong
            - TMBSL_ERR_HDMI_BAD_PARAMETER: a parameter was out of range
            - TMBSL_ERR_HDMI_BAD_UNIT_NUMBER: bad transmitter unit number
            - TMBSL_ERR_HDMI_I2C_WRITE: failed when writing to the I2C bus
            - TMBSL_ERR_HDMI_I2C_READ: failed when reading to the I2C bus
            - TMBSL_ERR_HDMI_NOT_INITIALIZED: transmitter not initialized
            - TMBSL_ERR_HDMI_OPERATION_NOT_PERMITTED: not allowed in DVI mode

******************************************************************************/
tmErrorCode_t tmdlHdmiTxSetAudioMute
(
    tmInstance_t    instance,
    Bool            audioMute
)
{
    tmErrorCode_t   errCode;

    /* Check if instance number is in range */
    RETIF((instance < 0) || (instance >= MAX_UNITS), TMDL_ERR_DLHDMITX_BAD_INSTANCE)

    /* Take the sempahore */
    RETIF( (errCode = tmdlHdmiTxIWSemaphoreP(dlHdmiTxItSemaphore[instance]) ) != TM_OK, errCode)

    /* Mute or Un-mute the audio output */
    RETIF_SEM(dlHdmiTxItSemaphore[instance], 
        (errCode = tmbslHdmiTxAudioOutSetMute(instance, 
        (tmbslHdmiTxaMute_t)audioMute) ) != TM_OK, errCode)

    /* Store current audio mute status */
    instanceStatusInfoTx[instance].pAudioInfo->audioMuteState = audioMute;


    /* Release the sempahore */
    RETIF( (errCode = tmdlHdmiTxIWSemaphoreV(dlHdmiTxItSemaphore[instance]) ) != TM_OK, errCode)

    return TM_OK;
}

/******************************************************************************
    \brief Reset audio CTS.
           This function is synchronous.
           This function is not ISR friendly.

    \param instance   Instance identifier.

    \return The call result:
            - TM_OK: the call was successful
            - TMDL_ERR_DLHDMITX_BAD_INSTANCE: the instance number is wrong or
              out of range
            - TMDL_ERR_DLHDMITX_BAD_HANDLE: the handle number is wrong
            - TMBSL_ERR_HDMI_BAD_PARAMETER: a parameter was out of range
            - TMBSL_ERR_HDMI_BAD_UNIT_NUMBER: bad transmitter unit number
            - TMBSL_ERR_HDMI_I2C_WRITE: failed when writing to the I2C bus
            - TMBSL_ERR_HDMI_I2C_READ: failed when reading to the I2C bus
            - TMBSL_ERR_HDMI_NOT_INITIALIZED: transmitter not initialized
            - TMBSL_ERR_HDMI_OPERATION_NOT_PERMITTED: not allowed in DVI mode


******************************************************************************/
tmErrorCode_t tmdlHdmiTxResetAudioCts
(
    tmInstance_t    instance
)
{
    tmErrorCode_t   errCode;

    /* Check if instance number is in range */
    RETIF((instance < 0) || (instance >= MAX_UNITS), TMDL_ERR_DLHDMITX_BAD_INSTANCE)

    /* Take the sempahore */
    RETIF( (errCode = tmdlHdmiTxIWSemaphoreP(dlHdmiTxItSemaphore[instance]) ) != TM_OK, errCode)

    /* Reset the audio Clock Time Stamp generator */
    RETIF_SEM(dlHdmiTxItSemaphore[instance], 
        (errCode = tmbslHdmiTxAudioInResetCts(instance)
        ) != TM_OK, errCode)

    /* Release the sempahore */
    RETIF( (errCode = tmdlHdmiTxIWSemaphoreV(dlHdmiTxItSemaphore[instance]) ) != TM_OK, errCode)

    return TM_OK;
}

/******************************************************************************
    \brief Retrieve EDID Status from driver.
           This function is synchronous.
           This function is ISR friendly.

    \param instance         Instance identifier.
    \param pEdidStatus      Pointer to the array that will receive the EDID Status.
    \param pEdidBlkCount    Pointer to the integer that will receive the number of 
                            read EDID block.

    \return The call result:
            - TM_OK: the call was successful
            - TMDL_ERR_DLHDMITX_BAD_INSTANCE: the instance number is wrong or
              out of range
            - TMDL_ERR_DLHDMITX_BAD_HANDLE: the handle number is wrong
            - TMDL_ERR_DLHDMITX_INCONSISTENT_PARAMS: an input parameter is
              inconsistent
            - TMBSL_ERR_HDMI_BAD_PARAMETER: a parameter was out of range
            - TMBSL_ERR_HDMI_BAD_UNIT_NUMBER: bad transmitter unit number
            - TMBSL_ERR_HDMI_NOT_INITIALIZED: transmitter not initialized

******************************************************************************/
tmErrorCode_t tmdlHdmiTxGetEdidStatus
(
    tmInstance_t            instance,
    tmdlHdmiTxEdidStatus_t  *pEdidStatus,
    UInt8                   *pEdidBlkCount
)
{
    tmErrorCode_t   errCode;
    UInt8           edidStatus;

    /* Check if instance number is in range */
    RETIF((instance < 0) || (instance >= MAX_UNITS), TMDL_ERR_DLHDMITX_BAD_INSTANCE)

    /* Check if EdidStatus and pReadBytesNumber pointers are Null */
    RETIF(pEdidStatus == Null, TMDL_ERR_DLHDMITX_INCONSISTENT_PARAMS)
    RETIF(pEdidBlkCount == Null, TMDL_ERR_DLHDMITX_INCONSISTENT_PARAMS)

    /* Take the sempahore */
    RETIF( (errCode = tmdlHdmiTxIWSemaphoreP(dlHdmiTxItSemaphore[instance]) ) != TM_OK, errCode)

    /* Get the EDID status from BSL driver */
    RETIF_SEM(dlHdmiTxItSemaphore[instance], 
        (errCode = tmbslHdmiTxEdidGetStatus(instance, 
        (UInt8 *)&edidStatus) ) != TM_OK, errCode)

    if (edidStatus >= TMDL_HDMITX_EDID_STATUS_INVALID)
    {
        *pEdidStatus = TMDL_HDMITX_EDID_STATUS_INVALID;
    }
    else
    {
        *pEdidStatus = (tmdlHdmiTxEdidStatus_t)edidStatus;
    }

    if ((*pEdidStatus == TMDL_HDMITX_EDID_READ) ||
        (*pEdidStatus == TMDL_HDMITX_EDID_ERROR_CHK))
    {
        /* Get the read EDID block number from BSL driver */
        RETIF_SEM(dlHdmiTxItSemaphore[instance], 
            (errCode = tmbslHdmiTxEdidGetBlockCount(instance, 
            pEdidBlkCount) ) != TM_OK, errCode)
    }
    
    if (errCode != TM_OK)
    {
        /* Error during read EDID, number of read block is 0 */
        *pEdidBlkCount = 0;
    
        /* Release the sempahore */
        (void)tmdlHdmiTxIWSemaphoreV(dlHdmiTxItSemaphore[instance]);

        return errCode;
    }

    /* Release the sempahore */
    RETIF( (errCode = tmdlHdmiTxIWSemaphoreV(dlHdmiTxItSemaphore[instance]) ) != TM_OK, errCode)

    return TM_OK;
}

/******************************************************************************
    \brief Retrieves audio descriptors from receiver's EDID. This function
           parses the EDID of Tx device to get the relevant data.
           This function is synchronous.
           This function is not ISR friendly.


    \param instance             Instance identifier.
    \param pAudioDescs          Pointer to the array that will receive audio
                                descriptors.
    \param maxAudioDescs        Size of the array.
    \param pWrittenAudioDescs   Pointer to the integer that will receive the actual
                                number of written descriptors.
    \param pAudioFlags          Pointer to the byte to receive Audio Capabilities Flags.

    \return The call result:
            - TM_OK: the call was successful
            - TMDL_ERR_DLHDMITX_BAD_INSTANCE: the instance number is wrong or
              out of range
            - TMDL_ERR_DLHDMITX_BAD_HANDLE: the handle number is wrong
            - TMDL_ERR_DLHDMITX_INCONSISTENT_PARAMS: an input parameter is
              inconsistent
            - TMDL_ERR_DLHDMITX_INVALID_STATE: the state is invalid for
              the function
            - TMBSL_ERR_HDMI_BAD_PARAMETER: a parameter was out of range
            - TMBSL_ERR_HDMI_BAD_UNIT_NUMBER: bad transmitter unit number
            - TMBSL_ERR_HDMI_RESOURCE_NOT_AVAILABLE : EDID not read
            - TMBSL_ERR_HDMI_NOT_INITIALIZED: transmitter not initialized

******************************************************************************/
tmErrorCode_t tmdlHdmiTxGetEdidAudioCaps
(
    tmInstance_t                instance,
    tmdlHdmiTxEdidAudioDesc_t   *pAudioDescs,
    UInt                        maxAudioDescs,
    UInt                        *pWrittenAudioDescs,
    UInt8                       *pAudioFlags
)
{
    tmErrorCode_t           errCode;
    tmbslHdmiTxEdidSad_t    edidSad[HDMI_TX_SAD_MAX_CNT];
    UInt                    i;
    
    /* Check if instance number is in range */
    RETIF((instance < 0) || (instance >= MAX_UNITS), TMDL_ERR_DLHDMITX_BAD_INSTANCE)

    /* Check if AudioDescs, WrittenAudioDescs and AudioFlags pointers are Null */
    RETIF(pAudioDescs == Null, TMDL_ERR_DLHDMITX_INCONSISTENT_PARAMS)
    RETIF(pWrittenAudioDescs == Null, TMDL_ERR_DLHDMITX_INCONSISTENT_PARAMS)
    RETIF(pAudioFlags == Null, TMDL_ERR_DLHDMITX_INCONSISTENT_PARAMS)

    /* Take the sempahore */
    RETIF( (errCode = tmdlHdmiTxIWSemaphoreP(dlHdmiTxItSemaphore[instance]) ) != TM_OK, errCode)

    /* Check the current state */   
    RETIF_SEM(dlHdmiTxItSemaphore[instance], 
        dlHdmiTxGetState(instance) != STATE_EDID_AVAILABLE, TMDL_ERR_DLHDMITX_INVALID_STATE)

    /* Get video capabilities from EDID, return TMDL_ERR_DLHDMITX_NO_RESOURCES if EDID are not read */
    RETIF_SEM(dlHdmiTxItSemaphore[instance], 
        (errCode = tmbslHdmiTxEdidGetAudioCapabilities(instance, 
        edidSad, maxAudioDescs, pWrittenAudioDescs, pAudioFlags) ) != TM_OK, errCode)

    for (i=0; i<*pWrittenAudioDescs; i++)
    {
        pAudioDescs[i].format            = (edidSad[i].ModeChans & 0x78) >> 3; /* Bits[6:3]: EIA/CEA861 mode */
        pAudioDescs[i].channels          = edidSad[i].ModeChans & 0x07;        /* Bits[2:0]: channels */
        pAudioDescs[i].supportedFreqs    = edidSad[i].Freqs;                   /* Supported frequencies */

        if (pAudioDescs[i].format == 1)             /* LPCM format */
        {
            pAudioDescs[i].supportedRes = edidSad[i].Byte3 & 0x07;
            pAudioDescs[i].maxBitrate   = 0x00;
        }
        else if ( (pAudioDescs[i].format >= 2) &&   /* Compressed format */
                    (pAudioDescs[i].format <= 8) )
        {
            pAudioDescs[i].supportedRes = 0x00;
            pAudioDescs[i].maxBitrate   = edidSad[i].Byte3;
        }
        else
        {
            pAudioDescs[i].supportedRes = 0x00;
            pAudioDescs[i].maxBitrate   = 0x00;
        }
    }

    /* Release the sempahore */
    RETIF( (errCode = tmdlHdmiTxIWSemaphoreV(dlHdmiTxItSemaphore[instance]) ) != TM_OK, errCode)

    return TM_OK;
}

/******************************************************************************
    \brief Retrieves supported video formats (short descriptors) from
           receiver's EDID. This function parses the EDID of Rx device to get
           the relevant data.
           This function is synchronous.
           This function is not ISR friendly.

    \param instance             Instance identifier.
    \param pVideoDesc           Pointer to the structure that will receive short
                                video descriptors.
    \param maxVideoFormats      Size of the array.
    \param pWrittenVideoFormats Pointer to the integer that will receive the actual
                                number of written descriptors.
    \param pVideoFlags          Pointer to the byte to receive Video Capability Flags.
                                b7: underscan supported
                                b6: YCbCr 4:4:4 supported
                                b5: YCbCr 4:2:2 supported

    \return The call result:
            - TM_OK: the call was successful
            - TMDL_ERR_DLHDMITX_BAD_INSTANCE: the instance number is wrong or
              out of range
            - TMDL_ERR_DLHDMITX_BAD_HANDLE: the handle number is wrong
            - TMDL_ERR_DLHDMITX_INCONSISTENT_PARAMS: an input parameter is
              inconsistent
            - TMDL_ERR_DLHDMITX_INVALID_STATE: the state is invalid for
              the function
            - TMBSL_ERR_HDMI_BAD_PARAMETER: a parameter was out of range
            - TMBSL_ERR_HDMI_BAD_UNIT_NUMBER: bad transmitter unit number
            - TMBSL_ERR_HDMI_RESOURCE_NOT_AVAILABLE : EDID not read
            - TMBSL_ERR_HDMI_NOT_INITIALIZED: transmitter not initialized

******************************************************************************/
tmErrorCode_t tmdlHdmiTxGetEdidVideoCaps
(
    tmInstance_t                instance,
    tmdlHdmiTxShortVidDesc_t    *pVideoDesc,
    UInt                        maxVideoFormats,
    UInt                        *pWrittenVideoFormats,
    UInt8                       *pVideoFlags
)
{
    tmErrorCode_t                   errCode;
    UInt8                           edidVFmtsBuffer[HDMI_TX_SVD_MAX_CNT];
    tmdlHdmiTxEdidVideoTimings_t    edidDTDBuffer[NUMBER_DTD_STORED];
    UInt8                           i;
    UInt8                           writtenDTD = 0;
    UInt8                           dtdCounter = 0;

    /* Check if instance number is in range */
    RETIF((instance < 0) || (instance >= MAX_UNITS), TMDL_ERR_DLHDMITX_BAD_INSTANCE)

    /* Check if Videoformats, WrittenVideoFormats and VideoFlags pointers are Null */
    RETIF(pVideoDesc == Null, TMDL_ERR_DLHDMITX_INCONSISTENT_PARAMS)
    RETIF(pWrittenVideoFormats == Null, TMDL_ERR_DLHDMITX_INCONSISTENT_PARAMS)
    RETIF(pVideoFlags == Null, TMDL_ERR_DLHDMITX_INCONSISTENT_PARAMS)
    RETIF(maxVideoFormats == 0, TMDL_ERR_DLHDMITX_INCONSISTENT_PARAMS)

    /* Take the sempahore */
    RETIF( (errCode = tmdlHdmiTxIWSemaphoreP(dlHdmiTxItSemaphore[instance]) ) != TM_OK, errCode)

    /* Check the current state */   
    RETIF_SEM(dlHdmiTxItSemaphore[instance],
        dlHdmiTxGetState(instance) != STATE_EDID_AVAILABLE, TMDL_ERR_DLHDMITX_INVALID_STATE)

    /* Get video capabilities from EDID, return TMDL_ERR_DLHDMITX_NO_RESOURCES if EDID are not read */
    RETIF_SEM(dlHdmiTxItSemaphore[instance], 
        (errCode = tmbslHdmiTxEdidGetVideoCapabilities(instance, 
        edidVFmtsBuffer, HDMI_TX_SVD_MAX_CNT, pWrittenVideoFormats, pVideoFlags) ) != TM_OK, errCode)

    /* Get detailled descriptors from EDID, return TMDL_ERR_DLHDMITX_NO_RESOURCES if EDID are not read */
    RETIF_SEM(dlHdmiTxItSemaphore[instance], 
        (errCode = dlHdmiTxEdidGetDTD(instance, edidDTDBuffer, NUMBER_DTD_STORED, &writtenDTD) ) != TM_OK, errCode)

    dtdCounter = 0;
    if (writtenDTD > 0)
    {
        /* Release the sempahore */
        RETIF( (errCode = tmdlHdmiTxIWSemaphoreV(dlHdmiTxItSemaphore[instance]) ) != TM_OK, errCode)

        /* Write first DTD in first position of table video desc  */
        pVideoDesc[0].videoFormat = tmdlHdmiTxConvertDTDtoCEA(instance, &(edidDTDBuffer[dtdCounter]));

        /* Take the sempahore */
        RETIF( (errCode = tmdlHdmiTxIWSemaphoreP(dlHdmiTxItSemaphore[instance]) ) != TM_OK, errCode)

        dtdCounter++;

        pVideoDesc[0].nativeVideoFormat = False;
    }

    /* Start with i = 1 keep the first position for the first DTD */
    for (i = dtdCounter; i< maxVideoFormats ; i++)
    {
        if ((i < (HDMI_TX_SVD_MAX_CNT + dtdCounter)) && (i < ((*pWrittenVideoFormats) + dtdCounter)))
        {
            /* Store SVD */
            pVideoDesc[i].videoFormat = (tmdlHdmiTxVidFmt_t)((Int)edidVFmtsBuffer[i - dtdCounter] & 0x7F); 
            /* if bit 7 is true, it means that is a preferred video format */
            if ((edidVFmtsBuffer[i - dtdCounter] & 0x80) == 0x80)
            {
                pVideoDesc[i].nativeVideoFormat = True;
            }
            else
            {
                pVideoDesc[i].nativeVideoFormat = False;
            }
        }
        else
        {
            if ((dtdCounter < NUMBER_DTD_STORED) && (dtdCounter < writtenDTD))
            {
                /* Release the sempahore */
                RETIF( (errCode = tmdlHdmiTxIWSemaphoreV(dlHdmiTxItSemaphore[instance]) ) != TM_OK, errCode)
                /* Store DTD except first DTD */
                pVideoDesc[i].videoFormat = tmdlHdmiTxConvertDTDtoCEA(instance, &(edidDTDBuffer[dtdCounter]));
                /* Take the sempahore */
                RETIF( (errCode = tmdlHdmiTxIWSemaphoreP(dlHdmiTxItSemaphore[instance]) ) != TM_OK, errCode)

                dtdCounter++;

                pVideoDesc[i].nativeVideoFormat = False;
            }
            else
            {
                /* VGA is always supported */
                pVideoDesc[i].videoFormat = TMDL_HDMITX_VFMT_01_640x480p_60Hz;
                pVideoDesc[i].nativeVideoFormat = False;
                /* Last format supported exit from loop for */
                break;
            }
        }
    }

    *pWrittenVideoFormats = *pWrittenVideoFormats + dtdCounter + 1;     /* + 1 for VGA format */

    /* Release the sempahore */
    RETIF( (errCode = tmdlHdmiTxIWSemaphoreV(dlHdmiTxItSemaphore[instance]) ) != TM_OK, errCode)

    return TM_OK;
}

/******************************************************************************
    \brief Retrieves supported video formats (short descriptors) from
           receiver's EDID. This function parses the EDID of Rx device to get
           the relevant data.
           This function is synchronous.
           This function is not ISR friendly.

    \param instance                 Instance identifier.
    \param pNativeVideoFormat    Pointer to the array that will receive video
                                    timing descriptor.

    \return The call result:
            - TM_OK: the call was successful
            - TMDL_ERR_DLHDMITX_BAD_INSTANCE: the instance number is wrong or
              out of range
            - TMDL_ERR_DLHDMITX_BAD_HANDLE: the handle number is wrong
            - TMDL_ERR_DLHDMITX_INCONSISTENT_PARAMS: an input parameter is
              inconsistent
            - TMDL_ERR_DLHDMITX_INVALID_STATE: the state is invalid for
              the function
            - TMBSL_ERR_HDMI_BAD_PARAMETER: a parameter was out of range
            - TMBSL_ERR_HDMI_BAD_UNIT_NUMBER: bad transmitter unit number
            - TMBSL_ERR_HDMI_RESOURCE_NOT_AVAILABLE : EDID not read
            - TMBSL_ERR_HDMI_NOT_INITIALIZED: transmitter not initialized

******************************************************************************/
tmErrorCode_t tmdlHdmiTxGetEdidVideoPreferred
(
    tmInstance_t                    instance,
    tmdlHdmiTxEdidVideoTimings_t    *pNativeVideoFormat
)
{
    tmErrorCode_t   errCode;
    
    /* Check if instance number is in range */
    RETIF((instance < 0) || (instance >= MAX_UNITS), TMDL_ERR_DLHDMITX_BAD_INSTANCE)

    /* Check if NativeVideoFormat pointer is Null */
    RETIF(pNativeVideoFormat == Null, TMDL_ERR_DLHDMITX_INCONSISTENT_PARAMS)

    /* Take the sempahore */
    RETIF( (errCode = tmdlHdmiTxIWSemaphoreP(dlHdmiTxItSemaphore[instance]) ) != TM_OK, errCode)

    /* Check the current state */   
    RETIF_SEM(dlHdmiTxItSemaphore[instance], 
        dlHdmiTxGetState(instance) != STATE_EDID_AVAILABLE, TMDL_ERR_DLHDMITX_INVALID_STATE)

    /* Get preferred video format from EDID, return TMDL_ERR_DLHDMITX_NO_RESOURCES if EDID are not read */
    RETIF_SEM(dlHdmiTxItSemaphore[instance], 
        (errCode = tmbslHdmiTxEdidGetVideoPreferred(instance,
        (tmbslHdmiTxEdidDtd_t *)pNativeVideoFormat) ) != TM_OK, errCode)

    /* Release the sempahore */
    RETIF( (errCode = tmdlHdmiTxIWSemaphoreV(dlHdmiTxItSemaphore[instance]) ) != TM_OK, errCode)

    return TM_OK;
}

/*****************************************************************************/
/**
    \brief Retrieves supported detailled video descriptors from
           receiver's EDID. This function parses the EDID of Rx device to get
           the relevant data.
           This function is synchronous.
           This function is not ISR friendly.

    \param instance         Instance identifier.
    \param pDTDescriptors   Pointer to the array that will receive detailled 
                            timing descriptors.
    \param maxDTDesc        Size of the array.
    \param pWrittenDesc     Pointer to the integer that will receive the actual
                            number of written descriptors.

    \return The call result:
            - TM_OK: the call was successful
            - TMDL_ERR_DLHDMITX_BAD_INSTANCE: the instance number is wrong or
              out of range
            - TMDL_ERR_DLHDMITX_BAD_HANDLE: the handle number is wrong
            - TMDL_ERR_DLHDMITX_INCONSISTENT_PARAMS: an input parameter is
              inconsistent
            - TMDL_ERR_DLHDMITX_INVALID_STATE: the state is invalid for
              the function
            - TMBSL_ERR_HDMI_BAD_PARAMETER: a parameter was out of range
            - TMBSL_ERR_HDMI_BAD_UNIT_NUMBER: bad transmitter unit number
            - TMBSL_ERR_HDMI_RESOURCE_NOT_AVAILABLE : EDID not read
            - TMBSL_ERR_HDMI_NOT_INITIALIZED: transmitter not initialized

******************************************************************************/
tmErrorCode_t tmdlHdmiTxGetEdidDetailledTimingDescriptors
(
    tmInstance_t                    instance,
    tmdlHdmiTxEdidVideoTimings_t    *pDTDescriptors,
    UInt8                           maxDTDesc,
    UInt8                           *pWrittenDTDesc
)
{
    tmErrorCode_t   errCode;

    /* Check if instance number is in range */
    RETIF((instance < 0) || (instance >= MAX_UNITS), TMDL_ERR_DLHDMITX_BAD_INSTANCE)

    /* Check if DTDescriptors, WrittenDTDesc pointers are Null */
    RETIF(pDTDescriptors == Null, TMDL_ERR_DLHDMITX_INCONSISTENT_PARAMS)
    RETIF(pWrittenDTDesc == Null, TMDL_ERR_DLHDMITX_INCONSISTENT_PARAMS)

    /* Take the sempahore */
    RETIF( (errCode = tmdlHdmiTxIWSemaphoreP(dlHdmiTxItSemaphore[instance]) ) != TM_OK, errCode)

    /* Get detailled descriptors from EDID, return TMDL_ERR_DLHDMITX_NO_RESOURCES if EDID are not read */
    RETIF_SEM(dlHdmiTxItSemaphore[instance], 
        (errCode = dlHdmiTxEdidGetDTD(instance, pDTDescriptors, maxDTDesc, pWrittenDTDesc) ) != TM_OK, errCode)

    /* Release the sempahore */
    RETIF( (errCode = tmdlHdmiTxIWSemaphoreV(dlHdmiTxItSemaphore[instance]) ) != TM_OK, errCode)

    return TM_OK;
}

/*****************************************************************************/
/**
    \brief Retrieves supported monitor descriptor from receiver's EDID.
           This function parses the EDID of Rx device to get
           the relevant data.
           This function is synchronous.
           This function is not ISR friendly.

    \param instance         Instance identifier.
    \param pEdidFirstMD     Pointer to the array that will receive the first monitor
                            descriptors.
    \param pEdidSecondMD    Pointer to the array that will receive the second monitor
                            descriptors.
    \param pEdidOtherMD     Pointer to the array that will receive the other monitor
                            descriptors.
    \param maxOtherMD       Size of the array.
    \param pWrittenOtherMD  Pointer to the integer that will receive the actual
                            number of written descriptors.

    \return The call result:
            - TM_OK: the call was successful
            - TMDL_ERR_DLHDMITX_BAD_INSTANCE: the instance number is wrong or
              out of range
            - TMDL_ERR_DLHDMITX_BAD_HANDLE: the handle number is wrong
            - TMDL_ERR_DLHDMITX_INCONSISTENT_PARAMS: an input parameter is
              inconsistent
            - TMDL_ERR_DLHDMITX_INVALID_STATE: the state is invalid for
              the function
            - TMBSL_ERR_HDMI_BAD_PARAMETER: a parameter was out of range
            - TMBSL_ERR_HDMI_BAD_UNIT_NUMBER: bad transmitter unit number
            - TMBSL_ERR_HDMI_RESOURCE_NOT_AVAILABLE : EDID not read
            - TMBSL_ERR_HDMI_NOT_INITIALIZED: transmitter not initialized

******************************************************************************/
tmErrorCode_t tmdlHdmiTxGetEdidMonitorDescriptors
(
    tmInstance_t                instance,
    tmdlHdmiTxEdidFirstMD_t     *pEdidFirstMD,
    tmdlHdmiTxEdidSecondMD_t    *pEdidSecondMD,
    tmdlHdmiTxEdidOtherMD_t     *pEdidOtherMD,
    UInt8                       maxOtherMD,
    UInt8                       *pWrittenOtherMD
)
{
    tmErrorCode_t   errCode;

    /* Check if instance number is in range */
    RETIF((instance < 0) || (instance >= MAX_UNITS), TMDL_ERR_DLHDMITX_BAD_INSTANCE)

    /* Check if DTDescriptors, WrittenDTDesc pointers are Null */
    RETIF(pEdidFirstMD == Null, TMDL_ERR_DLHDMITX_INCONSISTENT_PARAMS)
    RETIF(pEdidSecondMD == Null, TMDL_ERR_DLHDMITX_INCONSISTENT_PARAMS)
    RETIF(pEdidOtherMD == Null, TMDL_ERR_DLHDMITX_INCONSISTENT_PARAMS)

    /* Take the sempahore */
    RETIF( (errCode = tmdlHdmiTxIWSemaphoreP(dlHdmiTxItSemaphore[instance]) ) != TM_OK, errCode)

    /* Check the current state */   
    RETIF_SEM(dlHdmiTxItSemaphore[instance],
        dlHdmiTxGetState(instance) != STATE_EDID_AVAILABLE, TMDL_ERR_DLHDMITX_INVALID_STATE)

    /* Get monitor descriptors from EDID, return TMDL_ERR_DLHDMITX_NO_RESOURCES if EDID are not read */
    RETIF_SEM(dlHdmiTxItSemaphore[instance], 
        (errCode = tmbslHdmiTxEdidGetMonitorDescriptors(instance, 
        (tmbslHdmiTxEdidFirstMD_t *)pEdidFirstMD, (tmbslHdmiTxEdidSecondMD_t *)pEdidSecondMD, 
        (tmbslHdmiTxEdidOtherMD_t *)pEdidOtherMD, maxOtherMD, pWrittenOtherMD) ) != TM_OK, errCode)

    /* Release the sempahore */
    RETIF( (errCode = tmdlHdmiTxIWSemaphoreV(dlHdmiTxItSemaphore[instance]) ) != TM_OK, errCode)

    return TM_OK;
}

/*****************************************************************************/
/**
    \brief Retrieves TV picture ratio from receiver's EDID. 
           This function parses the EDID of Rx device to get
           the relevant data.
           This function is synchronous.
           This function is not ISR friendly.

    \param instance             Instance identifier.
    \param pEdidTvPictureRatio  Pointer to the array that will receive the TV picture 
                                ratio.

    \return The call result:
            - TM_OK: the call was successful
            - TMDL_ERR_DLHDMITX_BAD_INSTANCE: the instance number is wrong or
              out of range
            - TMDL_ERR_DLHDMITX_BAD_HANDLE: the handle number is wrong
            - TMDL_ERR_DLHDMITX_INCONSISTENT_PARAMS: an input parameter is
              inconsistent
            - TMDL_ERR_DLHDMITX_INVALID_STATE: the state is invalid for
              the function
            - TMBSL_ERR_HDMI_BAD_PARAMETER: a parameter was out of range
            - TMBSL_ERR_HDMI_BAD_UNIT_NUMBER: bad transmitter unit number
            - TMBSL_ERR_HDMI_RESOURCE_NOT_AVAILABLE : EDID not read
            - TMBSL_ERR_HDMI_NOT_INITIALIZED: transmitter not initialized

******************************************************************************/
tmErrorCode_t tmdlHdmiTxGetEdidTVPictureRatio
(
    tmInstance_t                 instance,
    tmdlHdmiTxPictAspectRatio_t  *pEdidTvPictureRatio
)
{
    tmErrorCode_t               errCode;
    tmbslHdmiTxEdidBDParam_t    edidBDParam;
    UInt16                      horizontalSize;
    UInt16                      verticalSize;
    tmbslHdmiTxEdidDtd_t        edidDTDBuffer;
    UInt8                       writtenDTD = 0;
    Bool                        bDataAvailable = False; /* Data available in EDID for calcul TV picture ratio */

    /* Check if instance number is in range */
    RETIF((instance < 0) || (instance >= MAX_UNITS), TMDL_ERR_DLHDMITX_BAD_INSTANCE)

    /* Check if DTDescriptors, WrittenDTDesc pointers are Null */
    RETIF(pEdidTvPictureRatio == Null, TMDL_ERR_DLHDMITX_INCONSISTENT_PARAMS)

    /* Take the sempahore */
    RETIF( (errCode = tmdlHdmiTxIWSemaphoreP(dlHdmiTxItSemaphore[instance]) ) != TM_OK, errCode)

    /* Check the current state */   
    RETIF_SEM(dlHdmiTxItSemaphore[instance],
        dlHdmiTxGetState(instance) != STATE_EDID_AVAILABLE, TMDL_ERR_DLHDMITX_INVALID_STATE)

    /* Get Basic Display Parameter from EDID, return TMDL_ERR_DLHDMITX_NO_RESOURCES if EDID are not read */
    RETIF_SEM(dlHdmiTxItSemaphore[instance], 
        (errCode = tmbslHdmiTxEdidGetBasicDisplayParam(instance, 
        &edidBDParam) ) != TM_OK, errCode)

    horizontalSize  = (UInt16)edidBDParam.uMaxHorizontalSize;
    verticalSize    = (UInt16)edidBDParam.uMaxVerticalSize;

    if ((horizontalSize == 0) && (verticalSize == 0))
    {
        /* Get Basic Display Parameter from EDID, return TMDL_ERR_DLHDMITX_NO_RESOURCES if EDID are not read */
        RETIF_SEM(dlHdmiTxItSemaphore[instance], 
            (errCode = tmbslHdmiTxEdidGetDetailedTimingDescriptors            
                      (instance, &edidDTDBuffer, 1, &writtenDTD) ) != TM_OK, errCode);

        if (writtenDTD == 1)
        {
            horizontalSize  = edidDTDBuffer.uHImageSize;
            verticalSize    = edidDTDBuffer.uVImageSize;
            bDataAvailable = True;
        }
        else
        {
            *pEdidTvPictureRatio = TMDL_HDMITX_P_ASPECT_RATIO_UNDEFINED;
        }
    }
    else
    {
        bDataAvailable = True;
    }

    if (bDataAvailable == True)
    {
        *pEdidTvPictureRatio = dlHdmiTxCalcAspectRatio(horizontalSize, verticalSize);
    }
        
        /* Release the sempahore */
    RETIF( (errCode = tmdlHdmiTxIWSemaphoreV(dlHdmiTxItSemaphore[instance]) ) != TM_OK, errCode)

    return TM_OK;


}

/******************************************************************************
    \brief Retrieves the sink type from receiver's EDID (HDMI or DVI). This
           function parses the EDID of Rx device to get the relevant data.
           This function is synchronous.
           This function is not ISR friendly.

    \param instance  Instance identifier.
    \param pSinkType Pointer to the array that will receive sink type.

    \return The call result:
            - TM_OK: the call was successful
            - TMDL_ERR_DLHDMITX_BAD_INSTANCE: the instance number is wrong or
              out of range
            - TMDL_ERR_DLHDMITX_BAD_HANDLE: the handle number is wrong
            - TMDL_ERR_DLHDMITX_INCONSISTENT_PARAMS: an input parameter is
              inconsistent
            - TMDL_ERR_DLHDMITX_INVALID_STATE: the state is invalid for
              the function
            - TMBSL_ERR_HDMI_BAD_PARAMETER: a parameter was out of range
            - TMBSL_ERR_HDMI_BAD_UNIT_NUMBER: bad transmitter unit number
            - TMBSL_ERR_HDMI_RESOURCE_NOT_AVAILABLE : EDID not read
            - TMBSL_ERR_HDMI_NOT_INITIALIZED: transmitter not initialized

******************************************************************************/
tmErrorCode_t tmdlHdmiTxGetEdidSinkType
(
    tmInstance_t            instance,
    tmdlHdmiTxSinkType_t    *pSinkType
)
{
    tmErrorCode_t   errCode;

    /* Check if instance number is in range */
    RETIF((instance < 0) || (instance >= MAX_UNITS), TMDL_ERR_DLHDMITX_BAD_INSTANCE)

    /* Check if SinkType pointer is Null */
    RETIF(pSinkType == Null, TMDL_ERR_DLHDMITX_INCONSISTENT_PARAMS)

    /* Take the sempahore */
    RETIF( (errCode = tmdlHdmiTxIWSemaphoreP(dlHdmiTxItSemaphore[instance]) ) != TM_OK, errCode)

    /* Check the current state */   
    RETIF_SEM(dlHdmiTxItSemaphore[instance], 
        dlHdmiTxGetState(instance) != STATE_EDID_AVAILABLE, TMDL_ERR_DLHDMITX_INVALID_STATE)

    /* Read the source address from EDID, return TMDL_ERR_DLHDMITX_NO_RESOURCES if EDID are not read */
    RETIF_SEM(dlHdmiTxItSemaphore[instance], 
        (errCode = tmbslHdmiTxEdidGetSinkType(instance,
        (tmbslHdmiTxSinkType_t *)pSinkType) ) != TM_OK, errCode)

    /* Release the sempahore */
    RETIF( (errCode = tmdlHdmiTxIWSemaphoreV(dlHdmiTxItSemaphore[instance]) ) != TM_OK, errCode)

    return TM_OK;
}

/******************************************************************************
    \brief Retrieves source address from receivers's EDID. This
           function parses the EDID of Rx device to get the relevant data.
           This function is synchronous.
           This function is not ISR friendly.

    \param instance         Instance identifier.
    \param pSourceAddress   Pointer to the integer that will receive the EDID source 
                            address.

    \return The call result:
            - TM_OK: the call was successful
            - TMDL_ERR_DLHDMITX_BAD_INSTANCE: the instance number is wrong or
              out of range
            - TMDL_ERR_DLHDMITX_BAD_HANDLE: the handle number is wrong
            - TMDL_ERR_DLHDMITX_INCONSISTENT_PARAMS: an input parameter is
              inconsistent
            - TMDL_ERR_DLHDMITX_INVALID_STATE: the state is invalid for
              the function
            - TMBSL_ERR_HDMI_BAD_PARAMETER: a parameter was out of range
            - TMBSL_ERR_HDMI_BAD_UNIT_NUMBER: bad transmitter unit number
            - TMBSL_ERR_HDMI_RESOURCE_NOT_AVAILABLE : EDID not read
            - TMBSL_ERR_HDMI_NOT_INITIALIZED: transmitter not initialized

******************************************************************************/
tmErrorCode_t tmdlHdmiTxGetEdidSourceAddress
(
    tmInstance_t    instance,
    UInt16          *pSourceAddress
)
{
    tmErrorCode_t   errCode;

    /* Check if instance number is in range */
    RETIF((instance < 0) || (instance >= MAX_UNITS), TMDL_ERR_DLHDMITX_BAD_INSTANCE)

    /* Check if SourceAddress pointer is Null */
    RETIF(pSourceAddress == Null, TMDL_ERR_DLHDMITX_INCONSISTENT_PARAMS)

    /* Take the sempahore */
    RETIF( (errCode = tmdlHdmiTxIWSemaphoreP(dlHdmiTxItSemaphore[instance]) ) != TM_OK, errCode)

    /* Check the current state */   
    RETIF_SEM(dlHdmiTxItSemaphore[instance], 
        dlHdmiTxGetState(instance) != STATE_EDID_AVAILABLE, TMDL_ERR_DLHDMITX_INVALID_STATE)

    /* Read the source address from EDID, return TMDL_ERR_DLHDMITX_NO_RESOURCES if EDID are not read */
    RETIF_SEM(dlHdmiTxItSemaphore[instance], 
        (errCode = tmbslHdmiTxEdidGetSourceAddress(instance, 
        pSourceAddress) ) != TM_OK, errCode)

    /* Release the sempahore */
    RETIF( (errCode = tmdlHdmiTxIWSemaphoreV(dlHdmiTxItSemaphore[instance]) ) != TM_OK, errCode)

    return TM_OK;
}

/******************************************************************************
    \brief Retreives KSV list received by Tx device.
           This function is synchronous.
           This function is not ISR friendly.

    \param instance     Instance identifier.
    \param pKsv         Pointer to the array that will receive the KSV list.
    \param maxKsv       Maximum number of KSV that the array can store.
    \param pWrittenKsv  Actual number of KSV written into the array.
    \param pDepth       Connection tree depth returned with KSV list.

    \return The call result:
            - TM_OK: the call was successful
            - TMDL_ERR_DLHDMITX_BAD_INSTANCE: the instance number is wrong or
              out of range
            - TMDL_ERR_DLHDMITX_BAD_HANDLE: the handle number is wrong
            - TMDL_ERR_DLHDMITX_INCONSISTENT_PARAMS: an input parameter is
              inconsistent
            - TMDL_ERR_DLHDMITX_INVALID_STATE: the state is invalid for
              the function
            - TMDL_ERR_DLHDMITX_NOT_SUPPORTED: device does not support HDCP

******************************************************************************/
tmErrorCode_t tmdlHdmiTxGetKsvList
(
    tmInstance_t    instance,
    UInt8           *pKsv,
    UInt8           maxKsv,
    UInt8           *pWrittenKsv,
    UInt8           *pDepth,
    Bool            *pMaxCascExd,
    Bool            *pMaxDevsExd
)
{
    tmErrorCode_t   errCode;
#ifndef NO_HDCP
    UInt16          i,j;
#endif

    /* Check if instance number is in range */
    RETIF((instance < 0) || (instance >= MAX_UNITS), TMDL_ERR_DLHDMITX_BAD_INSTANCE)

    /* Check if pDepth, Ksv and WrittenKsv pointers are Null */
    RETIF(pKsv == Null, TMDL_ERR_DLHDMITX_INCONSISTENT_PARAMS)
    RETIF(pWrittenKsv == Null, TMDL_ERR_DLHDMITX_INCONSISTENT_PARAMS)
    RETIF(pDepth == Null, TMDL_ERR_DLHDMITX_INCONSISTENT_PARAMS)
    RETIF(pMaxCascExd == Null, TMDL_ERR_DLHDMITX_INCONSISTENT_PARAMS)
    RETIF(pMaxDevsExd == Null, TMDL_ERR_DLHDMITX_INCONSISTENT_PARAMS)

    /* Maximum Ksv is HDMITX_KSV_LIST_MAX_DEVICES, 128 devices */
    RETIF_BADPARAM(maxKsv > HDMITX_KSV_LIST_MAX_DEVICES)

    /* Take the sempahore */
    RETIF( (errCode = tmdlHdmiTxIWSemaphoreP(dlHdmiTxItSemaphore[instance]) ) != TM_OK, errCode)

    /* Check the current state */   
    RETIF_SEM(dlHdmiTxItSemaphore[instance], 
        dlHdmiTxGetState(instance) != STATE_EDID_AVAILABLE, TMDL_ERR_DLHDMITX_INVALID_STATE)

    /* Make sure that *pWrittenKsv is 0 */
    *pWrittenKsv = 0;

    /* Make sure that *pDepth is 0 */
    *pDepth = 0;

#ifndef NO_HDCP

    *pMaxCascExd = hdcpInfoListTx[instance].hdcpMaxCascExceeded;
    *pMaxDevsExd = hdcpInfoListTx[instance].hdcpMaxDevsExceeded;


    /* Copy the bKsv */
    if (maxKsv) {

        for (j=0; j<5 ;j++) {
            pKsv[j] = hdcpInfoListTx[instance].hdcpBksv[4-j];
        }
        *pWrittenKsv = *pWrittenKsv + 1;

    } /* maxKsv */


    /* Copy the Ksv list */
    for (i=1; i <= hdcpInfoListTx[instance].hdcpKsvDevices; i++)
    {
        if (i < maxKsv)
        {
            for (j=0; j<5 ;j++)
            {
                pKsv[(5*i)+j] = hdcpInfoListTx[instance].hdcpKsvList[(5*(i-1))+j];
            }
            *pWrittenKsv = *pWrittenKsv + 1;
        }
    }

    *pDepth = hdcpInfoListTx[instance].hdcpDeviceDepth;

    /* Release the sempahore */
    RETIF( (errCode = tmdlHdmiTxIWSemaphoreV(dlHdmiTxItSemaphore[instance]) ) != TM_OK, errCode)

    return TM_OK;
#else
    /* Release the sempahore */
    RETIF( (errCode = tmdlHdmiTxIWSemaphoreV(dlHdmiTxItSemaphore[instance]) ) != TM_OK, errCode)

    return TMDL_ERR_DLHDMITX_NOT_SUPPORTED;
#endif /* NO_HDCP */
}
#ifdef HDMI_TX_REPEATER_ISR_MODE
/******************************************************************************
    \brief Retreives HDCP depth received by Tx device.
           This function is synchronous.
           This function is not ISR friendly.

    \param instance     Instance identifier.
    \param pDepth       Connection tree depth returned with KSV list.

    \return The call result:
            - TM_OK: the call was successful
            - TMDL_ERR_DLHDMITX_BAD_INSTANCE: the instance number is wrong or
              out of range
            - TMDL_ERR_DLHDMITX_BAD_HANDLE: the handle number is wrong
            - TMDL_ERR_DLHDMITX_INCONSISTENT_PARAMS: an input parameter is
              inconsistent
            - TMDL_ERR_DLHDMITX_INVALID_STATE: the state is invalid for
              the function
            - TMDL_ERR_DLHDMITX_NOT_SUPPORTED: device does not support HDCP

******************************************************************************/
tmErrorCode_t tmdlHdmiTxGetDepth
(
    tmInstance_t    instance,
    UInt8           *pDepth
)
{
    tmErrorCode_t   errCode;

    /* Check if instance number is in range */
    RETIF((instance < 0) || (instance >= MAX_UNITS), TMDL_ERR_DLHDMITX_BAD_INSTANCE)

    /* Check if pDepth, is Null */
    RETIF(pDepth == Null, TMDL_ERR_DLHDMITX_INCONSISTENT_PARAMS)

    /* Take the sempahore */
    RETIF( (errCode = tmdlHdmiTxIWSemaphoreP(dlHdmiTxItSemaphore[instance]) ) != TM_OK, errCode)

    /* Make sure that *pDepth is 0 */
    *pDepth = 0;

#ifndef NO_HDCP


    *pDepth = hdcpInfoListTx[instance].hdcpDeviceDepth;

    /* Release the sempahore */
    RETIF( (errCode = tmdlHdmiTxIWSemaphoreV(dlHdmiTxItSemaphore[instance]) ) != TM_OK, errCode)

    return TM_OK;
#else
    /* Release the sempahore */
    RETIF( (errCode = tmdlHdmiTxIWSemaphoreV(dlHdmiTxItSemaphore[instance]) ) != TM_OK, errCode)

    return TMDL_ERR_DLHDMITX_NOT_SUPPORTED;
#endif /* NO_HDCP */
}

/******************************************************************************
    \brief Generate SHA_1 interrupt if not occured.
           This function is synchronous.
           This function is not ISR friendly.

    \param instance     Instance identifier.


    \return The call result:
            - TM_OK: the call was successful
            - TMDL_ERR_DLHDMITX_BAD_INSTANCE: the instance number is wrong or
              out of range
            - TMDL_ERR_DLHDMITX_BAD_HANDLE: the handle number is wrong
            - TMDL_ERR_DLHDMITX_INCONSISTENT_PARAMS: an input parameter is
              inconsistent
            - TMDL_ERR_DLHDMITX_INVALID_STATE: the state is invalid for
              the function
            - TMDL_ERR_DLHDMITX_NOT_SUPPORTED: device does not support HDCP

******************************************************************************/
tmErrorCode_t tmdlHdmiTxGeneSHA_1_IT
(
    tmInstance_t    instance
)
{
    tmErrorCode_t   errCode;


    /* Check if instance number is in range */
    RETIF((instance < 0) || (instance >= MAX_UNITS), TMDL_ERR_DLHDMITX_BAD_INSTANCE)

    /* Take the sempahore */
    RETIF( (errCode = tmdlHdmiTxIWSemaphoreP(dlHdmiTxItSemaphore[instance]) ) != TM_OK, errCode)

    dlHdmiTxHandleSHA_1(instance);

    /* Release the sempahore */
    RETIF( (errCode = tmdlHdmiTxIWSemaphoreV(dlHdmiTxItSemaphore[instance]) ) != TM_OK, errCode)
    
    return TM_OK;
}
#endif /* HDMI_TX_REPEATER_ISR_MODE */
/******************************************************************************
    \brief Enable/Disable HDCP encryption.
           This function is synchronous.
           This function is not ISR friendly.

    \param instance   Instance identifier.
    \param hdcpEnable HDCP On/Off (true = On, False = Off).

    \return The call result:
            - TM_OK: the call was successful
            - TMDL_ERR_DLHDMITX_BAD_INSTANCE: the instance number is wrong or
              out of range
            - TMDL_ERR_DLHDMITX_BAD_HANDLE: the handle number is wrong
            - TMDL_ERR_DLHDMITX_INVALID_STATE: the state is invalid for
              the function
            - TMDL_ERR_DLHDMITX_RESOLUTION_UNKNOWN: the resolution is unknown
            - TMDL_ERR_DLHDMITX_NOT_SUPPORTED: device does not support HDCP
            - TMBSL_ERR_HDMI_BAD_UNIT_NUMBER: bad transmitter unit number
            - TMBSL_ERR_HDMI_BAD_PARAMETER: a parameter was out of range
            - TMBSL_ERR_HDMI_NOT_INITIALIZED: transmitter not initialized
            - TMBSL_ERR_HDMI_I2C_WRITE: failed when writing to the I2C bus
            - TMBSL_ERR_HDMI_I2C_READ: failed when reading the I2C bus
            - TMBSL_ERR_HDMI_BAD_PARAMETER: a parameter was out of range
            - TMBSL_ERR_HDMI_NOT_SUPPORTED: device does not support HDCP

******************************************************************************/
tmErrorCode_t tmdlHdmiTxSetHdcp
(
    tmInstance_t    instance,
    Bool            hdcpEnable
)
{
    tmErrorCode_t               errCode;
#ifndef NO_HDCP
   tmdlHdmiTxVidFmtSpecs_t     resolutionSpecs;
    tmbslHdmiTxVfreq_t          voutFreq;
    tmbslHdmiTxVidFmt_t         voutFmt;
    tmbslHdmiTxHdcpTxMode_t     txMode; 
    tmbslHdmiTxHdcpOptions_t    options;
    UInt8                       slaveAddress;
    UInt16                      i;
#endif
    tmbslHdmiTxRxSense_t        rxSenseStatus;  /* Rx Sense status */
    tmbslHdmiTxHotPlug_t        hpdStatus;      /* HPD status */

    /* Check if instance number is in range */
    RETIF((instance < 0) || (instance >= MAX_UNITS), TMDL_ERR_DLHDMITX_BAD_INSTANCE)

    /* Take the sempahore */
    RETIF( (errCode = tmdlHdmiTxIWSemaphoreP(dlHdmiTxItSemaphore[instance]) ) != TM_OK, errCode)

    /* Check the current state */   
    RETIF_SEM(dlHdmiTxItSemaphore[instance], 
        dlHdmiTxGetState(instance) != STATE_EDID_AVAILABLE, TMDL_ERR_DLHDMITX_INVALID_STATE)

    /* Hdcp is not supported if keySeed is null */   
    RETIF_SEM(dlHdmiTxItSemaphore[instance], 
        gtmdlHdmiTxDriverConfigTable[instance].keySeed == HDCP_SEED_NULL, TMDL_ERR_DLHDMITX_NOT_SUPPORTED)

    /* Read rxSenseStatus and hpdStatus to authorize HDCP only if active */
    RETIF_SEM(dlHdmiTxItSemaphore[instance], 
        (errCode = tmbslHdmiTxRxSenseGetStatus(instance,
                                               &rxSenseStatus,False) ) != TM_OK, errCode)

    RETIF_SEM(dlHdmiTxItSemaphore[instance], 
        (errCode = tmbslHdmiTxHotPlugGetStatus(instance,
                                               &hpdStatus,False) ) != TM_OK, errCode)

#ifndef NO_HDCP
    if (hdcpEnable == True) /* HDCP ON */
    {
        if ( (rxSenseStatus == HDMITX_RX_SENSE_ACTIVE) && (hpdStatus == HDMITX_HOTPLUG_ACTIVE) )
        {

#ifdef TMFL_TDA19988
           tmbslHdmiTxHdcpPowerDown(instance,False);
#endif
            /* Reset HDCP DevLib data to ensure that new values are used */
            hdcpInfoListTx[instance].hdcpCheckState = TMDL_HDMITX_HDCP_CHECK_IN_PROGRESS;
            hdcpInfoListTx[instance].hdcpErrorState = 0;
            hdcpInfoListTx[instance].hdcpKsvDevices = 0;
            hdcpInfoListTx[instance].bKsvSecure = True;
            for(i=0; i<TMDL_HDMITX_KSV_BYTES_PER_DEVICE; i++) { hdcpInfoListTx[instance].hdcpBksv[i] = 0; }
            hdcpInfoListTx[instance].hdcpDeviceDepth = 0;

            hdcpInfoListTx[instance].hdcpMaxCascExceeded = False;
            hdcpInfoListTx[instance].hdcpMaxDevsExceeded = False;

            /* Current used video output format */
            voutFmt = (tmbslHdmiTxVidFmt_t)instanceStatusInfoTx[instance].pVideoInfo->videoOutConfig.format;

            /* Find output vertical frequency from output format */
            RETIF_SEM(dlHdmiTxItSemaphore[instance], 
                (errCode = tmdlHdmiTxGetVideoFormatSpecs(instance, (tmdlHdmiTxVidFmt_t)voutFmt, &resolutionSpecs) ) != TM_OK, errCode)
                voutFreq = (tmbslHdmiTxVfreq_t)resolutionSpecs.vfrequency;

            /* Configure HDCP */

            /* HDCP DDC Slave address */
            slaveAddress = HDMITX_HDCP_SLAVE_PRIMARY;

            /* Top level or repeater HDCP mode */
            if (unitTableTx[instance].repeaterEnable == True)
            {
                txMode = HDMITX_HDCP_TXMODE_REPEATER;
            }
            else
            {
                txMode = HDMITX_HDCP_TXMODE_TOP_LEVEL;
            }

		    instanceStatusInfoTx[instance].pColBarState->changeColorBarNow = True; 
            instanceStatusInfoTx[instance].pColBarState->colorBarOn = True;
            dlHdmiTxCheckColorBar(instance);

            /* HDCP options */
            options = (tmbslHdmiTxHdcpOptions_t)unitTableTx[instance].hdcpOptions;

            RETIF_SEM(dlHdmiTxItSemaphore[instance], 
                (errCode = tmbslHdmiTxHdcpConfigure(instance, 
                slaveAddress, txMode, options, HDCP_CHECK_INTERVAL_MS, HDCP_NUM_CHECKS) ) != TM_OK, errCode)

            /* Start HDCP */
            RETIF_SEM(dlHdmiTxItSemaphore[instance], 
                (errCode = tmbslHdmiTxHdcpInit(instance, 
                voutFmt, voutFreq) ) != TM_OK, errCode)

            RETIF_SEM(dlHdmiTxItSemaphore[instance], 
                (errCode = tmbslHdmiTxHdcpRun(instance)
                ) != TM_OK, errCode)

            unitTableTx[instance].hdcpEnable = True;

            /* Release the sempahore */
            RETIF( (errCode = tmdlHdmiTxIWSemaphoreV(dlHdmiTxItSemaphore[instance]) ) != TM_OK, errCode)

            return errCode;
        }

        /* Release the sempahore */
        RETIF( (errCode = tmdlHdmiTxIWSemaphoreV(dlHdmiTxItSemaphore[instance]) ) != TM_OK, errCode)

        return TMDL_ERR_DLHDMITX_INVALID_STATE;
    }
    else    /* HDCP OFF */
    {
		RETIF_SEM(dlHdmiTxItSemaphore[instance], 
            (errCode = tmbslHdmiTxHdcpStop(instance)
            ) != TM_OK, errCode)

        unitTableTx[instance].hdcpEnable = False;

        if (dlHdmiTxGetEventStatus(instance, TMDL_HDMITX_HDCP_INACTIVE) == TMDL_HDMITX_EVENT_ENABLED)
        {
            /* Release the sempahore */
            (void)tmdlHdmiTxIWSemaphoreV(dlHdmiTxItSemaphore[instance]);
            unitTableTx[instance].pCallback(TMDL_HDMITX_HDCP_INACTIVE);
            /* Take the sempahore */
            (void)tmdlHdmiTxIWSemaphoreP(dlHdmiTxItSemaphore[instance]);
        }   

        /* Release the sempahore */
        RETIF( (errCode = tmdlHdmiTxIWSemaphoreV(dlHdmiTxItSemaphore[instance]) ) != TM_OK, errCode);
        
#ifdef TMFL_TDA19988
        tmbslHdmiTxHdcpPowerDown(instance,True);
#endif
        return TM_OK;
    }
#else
    /* Release the sempahore */
    RETIF( (errCode = tmdlHdmiTxIWSemaphoreV(dlHdmiTxItSemaphore[instance]) ) != TM_OK, errCode)

    return TMDL_ERR_DLHDMITX_NOT_SUPPORTED;
#endif /* NO_HDCP */
}

/******************************************************************************
    \brief Get the driver HDCP state.
           This function is synchronous.
           This function is not ISR friendly.

    \param instance          Instance identifier.
    \param pHdcpCheckState   Pointer to the integer that will receive the HDCP check state.

    \return The call result:
            - TM_OK: the call was successful
            - TMDL_ERR_DLHDMITX_BAD_INSTANCE: the instance number is wrong or
              out of range
            - TMDL_ERR_DLHDMITX_BAD_HANDLE: the handle number is wrong
            - TMDL_ERR_DLHDMITX_INCONSISTENT_PARAMS: an input parameter is
              inconsistent
            - TMDL_ERR_DLHDMITX_NOT_SUPPORTED: device does not support HDCP

******************************************************************************/
tmErrorCode_t tmdlHdmiTxGetHdcpState
(
    tmInstance_t            instance,
    tmdlHdmiTxHdcpCheck_t   *pHdcpCheckState
)
{
    tmErrorCode_t               errCode;

    /* Check if instance number is in range */
    RETIF((instance < 0) || (instance >= MAX_UNITS), TMDL_ERR_DLHDMITX_BAD_INSTANCE)

    /* Take the sempahore */
    RETIF( (errCode = tmdlHdmiTxIWSemaphoreP(dlHdmiTxItSemaphore[instance]) ) != TM_OK, errCode)
   
    /* Check if HdcpCheckState pointer is Null */
    RETIF_SEM(dlHdmiTxItSemaphore[instance], pHdcpCheckState == Null, TMDL_ERR_DLHDMITX_INCONSISTENT_PARAMS)

#ifndef NO_HDCP
    /* Result of tmbslHdmiTxHdcpCheck */
    *pHdcpCheckState = hdcpInfoListTx[instance].hdcpCheckState;

    /* Release the sempahore */
    RETIF( (errCode = tmdlHdmiTxIWSemaphoreV(dlHdmiTxItSemaphore[instance]) ) != TM_OK, errCode)
   
    return TM_OK;
#else   
    *pHdcpCheckState = TMDL_HDMITX_HDCP_CHECK_NOT_STARTED;

    /* Release the sempahore */
    RETIF( (errCode = tmdlHdmiTxIWSemaphoreV(dlHdmiTxItSemaphore[instance]) ) != TM_OK, errCode)

    return TMDL_ERR_DLHDMITX_NOT_SUPPORTED;
#endif /* NO_HDCP */
}

/******************************************************************************
    \brief Check the result of an HDCP encryption attempt, called at
           intervals (set by timeSinceLastCall) after tmdlHdmiTxSetHdcp(true).
           This API must be used only in case of No Operating System. if OS, 
           this is manage internally of this device library.
           This function is synchronous.
           This function is not ISR friendly.

    \param instance             Instance identifier.
    \param timeSinceLastCall    Time passed in milliseconds since last call,
                                must be shorter than 600 ms.

    \return The call result:
            - TM_OK: the call was successful
            - TMDL_ERR_DLHDMITX_BAD_INSTANCE: the instance number is wrong or
              out of range
            - TMDL_ERR_DLHDMITX_BAD_HANDLE: the handle number is wrong
            - TMDL_ERR_DLHDMITX_NOT_SUPPORTED: device does not support HDCP
            - TMBSL_ERR_HDMI_BAD_UNIT_NUMBER: bad transmitter unit number
            - TMBSL_ERR_HDMI_BAD_PARAMETER: a parameter was out of range
            - TMBSL_ERR_HDMI_NOT_INITIALIZED: transmitter not initialized
            - TMBSL_ERR_HDMI_I2C_READ: failed when reading the I2C bus
            - TMBSL_ERR_HDMI_I2C_WRITE: failed when writing the I2C bus
            - TMBSL_ERR_HDMI_NOT_SUPPORTED: device does not support HDCP

******************************************************************************/
tmErrorCode_t tmdlHdmiTxHdcpCheck
(
    tmInstance_t    instance,
    UInt16          timeSinceLastCall
)
{
    tmErrorCode_t           errCode;
    Bool                    featureSupported;

    /* Check if instance number is in range */
    RETIF((instance < 0) || (instance >= MAX_UNITS), TMDL_ERR_DLHDMITX_BAD_INSTANCE)

    /* Take the sempahore */
    RETIF( (errCode = tmdlHdmiTxIWSemaphoreP(dlHdmiTxItSemaphore[instance]) ) != TM_OK, errCode)

    RETIF_SEM(dlHdmiTxItSemaphore[instance],
        (errCode = tmbslHdmiTxHwGetCapabilities(instance, 
        HDMITX_FEATURE_HW_HDCP, &featureSupported) ) != TM_OK, errCode)

#ifndef NO_HDCP
    dlHdmiTxCheckColorBar(instance);
    dlHdmiTxCheckHdcpColorBar(instance);

    if (featureSupported == True)
    {
        RETIF_SEM(dlHdmiTxItSemaphore[instance],
            (errCode = tmbslHdmiTxHdcpCheck(instance,
            timeSinceLastCall, (tmbslHdmiTxHdcpCheck_t *)&(hdcpInfoListTx[instance].hdcpCheckState)) ) != TM_OK, errCode)
    }

    /* Release the sempahore */
    RETIF( (errCode = tmdlHdmiTxIWSemaphoreV(dlHdmiTxItSemaphore[instance]) ) != TM_OK, errCode)

    return TM_OK;
#else
    /* Release the sempahore */
    RETIF( (errCode = tmdlHdmiTxIWSemaphoreV(dlHdmiTxItSemaphore[instance]) ) != TM_OK, errCode)

    return TMDL_ERR_DLHDMITX_NOT_SUPPORTED;
#endif /* NO_HDCP */
}

/******************************************************************************
    \brief This function loads a gamut metadata packet into the HW. HW will
           actually send it at the beginning of next VS, during the vertical
           blanking.
           This function is synchronous.
           This function is not ISR friendly.

    \param instance     Instance identifier.
    \param enable       Enable/disable gamut metadata packet insertion.
    \param pGamutData   Pointer to the structure containing gamut metadata
                        parameters. 

    \return The call result:
            - TM_OK: the call was successful
            - TMDL_ERR_DLHDMITX_BAD_INSTANCE: the instance number is wrong or
              out of range
            - TMDL_ERR_DLHDMITX_BAD_HANDLE: the handle number is wrong
            - TMDL_ERR_DLHDMITX_INVALID_STATE: the state is invalid for
              the function
            - TMDL_ERR_DLHDMITX_INCONSISTENT_PARAMS: an input parameter is
              inconsistent
            - TMBSL_ERR_HDMI_BAD_PARAMETER: a parameter was out of range
            - TMBSL_ERR_HDMI_BAD_UNIT_NUMBER: bad transmitter unit number
            - TMBSL_ERR_HDMI_I2C_WRITE: failed when writing to the I2C bus
            - TMBSL_ERR_HDMI_I2C_READ: failed when reading to the I2C bus
            - TMBSL_ERR_HDMI_NOT_INITIALIZED: transmitter not initialized
            - TMBSL_ERR_HDMI_OPERATION_NOT_PERMITTED: not allowed in DVI mode

******************************************************************************/
tmErrorCode_t tmdlHdmiTxSetGamutPacket
(
    tmInstance_t            instance,
    Bool                    enable,
    tmdlHdmiTxGamutData_t   *pGamutData
)
{
    tmErrorCode_t           errCode;
    tmbslHdmiTxPktGamut_t   pkt;
    UInt8                   i;

    /* Check if instance number is in range */
    RETIF((instance < 0) || (instance >= MAX_UNITS), TMDL_ERR_DLHDMITX_BAD_INSTANCE)

    /* Take the sempahore */
    RETIF( (errCode = tmdlHdmiTxIWSemaphoreP(dlHdmiTxItSemaphore[instance]) ) != TM_OK, errCode)

    /* Check the current state */   
    RETIF_SEM(dlHdmiTxItSemaphore[instance], 
        dlHdmiTxGetState(instance) != STATE_EDID_AVAILABLE, TMDL_ERR_DLHDMITX_INVALID_STATE)

    if (enable == True)
    {
        /* Check if GamutData pointer is Null */
        RETIF_SEM(dlHdmiTxItSemaphore[instance], pGamutData == Null, TMDL_ERR_DLHDMITX_INCONSISTENT_PARAMS)
    
        /* Fill data */
        pkt.HB[0] = 0x0A;

        pkt.HB[1] = 0x00;
        pkt.HB[1] = (UInt8)(pkt.HB[1] | ((pGamutData->nextField & 0x01) << 7));
        pkt.HB[1] |= (pGamutData->GBD_Profile & 0x07) << 4;
        pkt.HB[1] |= (pGamutData->affectedGamutSeqNum & 0x0F);

        pkt.HB[2] = 0x00;
        pkt.HB[2] = (UInt8)(pkt.HB[2] | ((pGamutData->noCurrentGBD & 0x01) << 7));
        pkt.HB[2] |= (pGamutData->packetSequence & 0x03) << 4;
        pkt.HB[2] |= (pGamutData->currentGamutSeqNum & 0x0F);

        for(i=0; i<28; i++)
        {
            pkt.PB[i] = pGamutData->payload[i];
        }

        /* Store GBD color space */
        if ( ((pGamutData->payload[0]) & 0x03) == 2 )
        {
            instanceStatusInfoTx[instance].pGamutState->wideGamutColorSpace = TMDL_HDMITX_EXT_COLORIMETRY_XVYCC709;
        }
        else
        {
            instanceStatusInfoTx[instance].pGamutState->wideGamutColorSpace = TMDL_HDMITX_EXT_COLORIMETRY_XVYCC601;
        }

        /* Fill Gamut metadata packet */
        RETIF_SEM(dlHdmiTxItSemaphore[instance],
            (errCode = tmbslHdmiTxPktFillGamut(instance,
            &pkt, instanceStatusInfoTx[instance].pGamutState->gamutBufNum) ) != TM_OK, errCode)

        /* Enable Gamut metadata transmission */
        RETIF_SEM(dlHdmiTxItSemaphore[instance],
            (errCode = tmbslHdmiTxPktSendGamut(instance,
            instanceStatusInfoTx[instance].pGamutState->gamutBufNum, enable) ) != TM_OK, errCode)

        /* Use next buffer for next time */
        if (instanceStatusInfoTx[instance].pGamutState->gamutBufNum == 0)
        {
            instanceStatusInfoTx[instance].pGamutState->gamutBufNum = 1;
        }
        else
        {
            instanceStatusInfoTx[instance].pGamutState->gamutBufNum = 0;
        }
    }
    else
    {
        /* Disable Gamut metadata transmission */
        RETIF_SEM(dlHdmiTxItSemaphore[instance],
            (errCode = tmbslHdmiTxPktSendGamut(instance,
            0, enable) ) != TM_OK, errCode)
    }

    /* Store gamut status */
    instanceStatusInfoTx[instance].pGamutState->gamutOn = enable;
    if(enable) instanceStatusInfoTx[instance].pGamutState->extColOn = False;

	/* Set avi infoframe */
    RETIF_SEM(dlHdmiTxItSemaphore[instance],
        (errCode = dlHdmiTxSetVideoInfoframe(instance, 
        instanceStatusInfoTx[instance].pVideoInfo->videoOutConfig.format, 
        instanceStatusInfoTx[instance].pVideoInfo->videoOutConfig.mode) ) != TM_OK, errCode)

    /* Release the sempahore */
    RETIF( (errCode = tmdlHdmiTxIWSemaphoreV(dlHdmiTxItSemaphore[instance]) ) != TM_OK, errCode)

    return TM_OK;
}

/******************************************************************************
    \brief This function set the extended colorimetry with one of the following 
           extended colorimetries(bits EC2-0): xvYCC601, xvYCC709, sYCC601, 
           AdobeYCC601, AdobeRGB. When the parameter extendedColorimetry is 
           xvYCC601 or xvYCC70, this function calls the API tmdlHdmiTxSetGamutPacket
           to send Gamut Packet Data that does not exist for all other types of
           extended colorimetries for which pointer pGamutData can be set to NULL.
           This function also allows to set YCC Quantization Range (YQ1-0)
           
           This function is synchronous.
           This function is not ISR friendly.

    \param instance              Instance identifier.
    \param enable                Enable/Disable extended colorimetry.
    \param extendedColorimetry   value of the extended colorimetry (bits EC2 EC1 EC0). 
    \param yccQR                 YCC quantisation range
    \param pGamutData            Pointer to the structure containing gamut metadata
                                 parameters. 

    \return The call result:
           - TM_OK: the call was successful
           - TMDL_ERR_DLHDMITX_BAD_INSTANCE: the instance number is wrong
           - TMDL_ERR_DLHDMITX_BAD_PARAMETER: a parameter was out of range
           - TMDL_ERR_DLHDMITX_INVALID_STATE: the state is invalid for the function
           - TMBSL_ERR_HDMI_BAD_PARAMETER: a parameter was out of range
           - TMBSL_ERR_HDMI_BAD_UNIT_NUMBER: bad transmitter unit number
           - TMBSL_ERR_HDMI_I2C_WRITE: failed when writing to the I2C bus
           - TMBSL_ERR_HDMI_I2C_READ: failed when reading to the I2C bus
           - TMBSL_ERR_HDMI_NOT_INITIALIZED: transmitter not initialized
           - TMBSL_ERR_HDMI_OPERATION_NOT_PERMITTED: not allowed in DVI mode

******************************************************************************/
tmErrorCode_t tmdlHdmiTxSetExtendedColorimetry
(
    tmInstance_t                 instance,
    Bool                         enable,
    tmdlHdmiTxExtColorimetry_t   extendedColorimetry,
    tmdlHdmiTxYCCQR_t            yccQR,
    tmdlHdmiTxGamutData_t        *pGamutData
)
{
    tmErrorCode_t errCode;

    /* Check if instance number is in range */
    RETIF((instance < 0) || (instance >= MAX_UNITS), TMDL_ERR_DLHDMITX_BAD_INSTANCE)

    /* Check if extendedColorimetry & yccQR values are in the correct range */
    if(enable)  // no need to check them for disable handling
    {
        RETIF(extendedColorimetry >= TMDL_HDMITX_EXT_COLORIMETRY_INVALID, TMDL_ERR_DLHDMITX_BAD_PARAMETER)
        RETIF(yccQR >= TMDL_HDMITX_YQR_INVALID, TMDL_ERR_DLHDMITX_BAD_PARAMETER)
    }
    
    /* Take the sempahore */
    RETIF( (errCode = tmdlHdmiTxIWSemaphoreP(dlHdmiTxItSemaphore[instance]) ) != TM_OK, errCode)

    /* Check the current state */   
    RETIF_SEM(dlHdmiTxItSemaphore[instance], 
        dlHdmiTxGetState(instance) != STATE_EDID_AVAILABLE, TMDL_ERR_DLHDMITX_INVALID_STATE)

    /* Store YCC quantisation range value for later AVI InfoFrame insertion */
    if(enable) instanceStatusInfoTx[instance].pGamutState->yccQR = yccQR;

    /* Extended colorimetries that need to send Gamut Packet Data */
    if( ( (enable == True) && ( (extendedColorimetry == TMDL_HDMITX_EXT_COLORIMETRY_XVYCC601) || 
          (extendedColorimetry == TMDL_HDMITX_EXT_COLORIMETRY_XVYCC709) ) ) 
                         || 
        ( (enable == False) && (instanceStatusInfoTx[instance].pGamutState->gamutOn == True) ) )
    {   
        /* can not have two different types of extended colorimeties enabled in the same time */
        if(enable) instanceStatusInfoTx[instance].pGamutState->extColOn = False;

        /* Release the sempahore */
        RETIF( (errCode = tmdlHdmiTxIWSemaphoreV(dlHdmiTxItSemaphore[instance]) ) != TM_OK, errCode)

        /* Call the API that handles Gamut MetaData */
        RETIF( (errCode = tmdlHdmiTxSetGamutPacket(instance, enable, pGamutData) ) != TM_OK, errCode)

        return TM_OK;
    }

    /* Extended colorimetries that do not need to send Gamut Packet Data */
    if (instanceStatusInfoTx[instance].pGamutState->gamutOn == True)
    {
        /* Disable Gamut metadata transmission */
        RETIF_SEM(dlHdmiTxItSemaphore[instance], (errCode = tmbslHdmiTxPktSendGamut(instance, 0, False) ) != TM_OK, errCode)

        instanceStatusInfoTx[instance].pGamutState->gamutOn = False;
    }

    /* Store the extended colorimetry that does not need sending Gamut Packet Data */
    if(enable) instanceStatusInfoTx[instance].pGamutState->wideGamutColorSpace = extendedColorimetry;
    instanceStatusInfoTx[instance].pGamutState->extColOn = enable;
    
	/* Set avi infoframe */
    RETIF_SEM(dlHdmiTxItSemaphore[instance],
        (errCode = dlHdmiTxSetVideoInfoframe(instance, 
        instanceStatusInfoTx[instance].pVideoInfo->videoOutConfig.format, 
        instanceStatusInfoTx[instance].pVideoInfo->videoOutConfig.mode) ) != TM_OK, errCode)

    /* Release the sempahore */
    RETIF( (errCode = tmdlHdmiTxIWSemaphoreV(dlHdmiTxItSemaphore[instance]) ) != TM_OK, errCode)

    return TM_OK;
}

/******************************************************************************
    \brief This function set the revocation list use for HDCP
           This function is synchronous.
           This function is not ISR friendly.

    \param instance     Instance identifier.
    \param listPtr      Pointer on revocation list provide by application.
    \param length       length of revocation list. 

    \return The call result:
            - TM_OK: the call was successful, however RX keys have
                     not been checked with provided revocation list
                     because they are not available.
            - TMDL_DLHDMITX_HDCP_SECURE: the call was successful, RX keys are secure
            - TMDL_DLHDMITX_HDCP_NOT_SECURE: the call was successful, RX keys are NOT secure
            - TMDL_ERR_DLHDMITX_INVALID_STATE: we are a repeater                             
            - TMDL_ERR_DLHDMITX_BAD_INSTANCE: the instance number is wrong or
              out of range
            - TMDL_ERR_DLHDMITX_BAD_HANDLE: the handle number is wrong
            - TMDL_ERR_DLHDMITX_INCONSISTENT_PARAMS: an input parameter is
              inconsistent

******************************************************************************/

tmErrorCode_t tmdlHdmiTxSetHDCPRevocationList(
    tmInstance_t    instance,
    void            *listPtr, 
    UInt32          length
)
{
  tmErrorCode_t errCode       = TM_OK;
#ifndef NO_HDCP
  tmErrorCode_t errCodeSem    = TM_OK;
  UInt8         aCounter     = 0;
  UInt8         indexKSVList = 0;
  UInt8         i;
  Bool 		bIsSecure = True;
#endif

    /* Check if instance number is in range */
    RETIF((instance < 0) || (instance >= MAX_UNITS), TMDL_ERR_DLHDMITX_BAD_INSTANCE)

    /* Check parameters */
    RETIF((listPtr == Null) || (length == 0), TMDL_ERR_DLHDMITX_INCONSISTENT_PARAMS)

#ifndef NO_HDCP
  /* --------------------- */
  /* Take the semaphore    */
  /* --------------------- */
  RETIF( (errCodeSem = tmdlHdmiTxIWSemaphoreP(dlHdmiTxItSemaphore[instance]) ) != TM_OK, errCodeSem)

  /* Register revocation list */
    unitTableTx[instance].revocationList.pList  = (UInt8 *)listPtr;
    unitTableTx[instance].revocationList.length = length;

  /* Look if hdcpBksv is filled in */
  for (i=0; i<TMDL_HDMITX_KSV_BYTES_PER_DEVICE; i++) {
    if ( hdcpInfoListTx[instance].hdcpBksv[i] == 0) aCounter++;
  }

  /* If it the case ,check bksv */
  if (aCounter != TMDL_HDMITX_KSV_BYTES_PER_DEVICE) {

    dlHdmiTxCheckHdcpBksv (instance, hdcpInfoListTx[instance].hdcpBksv,&bIsSecure, True);

    /* bksv is secure */
    if (bIsSecure == True) {

      /* if HDMI TX is at top level */
      if (unitTableTx[instance].repeaterEnable == False) {

	/* if present, check ksv list */
	if (hdcpInfoListTx[instance].hdcpKsvDevices) {

	  while (( indexKSVList <  TMDL_HDMITX_KSV_LIST_MAX_DEVICES ) &&
		 ( indexKSVList <  hdcpInfoListTx[instance].hdcpKsvDevices ) && 
		 ( bIsSecure == True)) {

	    dlHdmiTxCheckHdcpBksv (instance,
				   &(hdcpInfoListTx[instance].hdcpKsvList[indexKSVList * TMDL_HDMITX_KSV_BYTES_PER_DEVICE]),
				   &bIsSecure,
				   False);
	    indexKSVList++;
	  }

	  if (bIsSecure == True) {
	    errCode = TMDL_DLHDMITX_HDCP_SECURE;
	  }
	  else {
	    errCode = TMDL_DLHDMITX_HDCP_NOT_SECURE;
	  }
	}
	else { /* ksv list does NOT exist */

	  /* we suppose that application calls the API after RX_KEYS_RECEIVED */
	  errCode = TMDL_DLHDMITX_HDCP_SECURE;
	}

      }
      else { /* we are a repeater */
	errCode = TMDL_ERR_DLHDMITX_INVALID_STATE;
      }

    }
    else { /* bksv NOT secure */

      errCode = TMDL_DLHDMITX_HDCP_NOT_SECURE;
    }

  } 
  else {
    /* bksv is not read, could not be tested */
    errCode = TM_OK;
  }

  /* --------------------------- */
    /* Release the sempahore */
  /* --------------------------- */
  RETIF( (errCodeSem = tmdlHdmiTxIWSemaphoreV(dlHdmiTxItSemaphore[instance]) ) != TM_OK, errCodeSem)
#else
     (void)instance; /* Remove compiler warning */
#endif /* NO_HDCP */
  return errCode;
}

/******************************************************************************
    \brief This function set the B... screen
           This function is synchronous.
           This function is not ISR friendly.

    \param instance     Instance identifier.

    \return The call result:
            - TM_OK: the call was successful, however RX keys have
                     not been checked with provided revocation list
                     because they are not available.
            - TMDL_ERR_DLHDMITX_BAD_INSTANCE: the instance number is wrong or
              out of range


******************************************************************************/

tmErrorCode_t tmdlHdmiTxSetBScreen(
    tmInstance_t            instance,
    tmdlHdmiTxTestPattern_t pattern
)
{

    tmErrorCode_t errCodeSem    = TM_OK;
    tmErrorCode_t errCode       = TM_OK;

    /* Check if instance number is in range */
    RETIF((instance < 0) || (instance >= MAX_UNITS), TMDL_ERR_DLHDMITX_BAD_INSTANCE)

    /* --------------------- */
    /* Take the semaphore    */
    /* --------------------- */
    RETIF( (errCodeSem = tmdlHdmiTxIWSemaphoreP(dlHdmiTxItSemaphore[instance]) ) != TM_OK, errCodeSem)

    gtmdlHdmiTxDriverConfigTable[instance].pattern = pattern;

    /* Set service mode colour bar on/off (also used as HDCP logo pattern) */
    (void)dlHdmiTxSetTestPatternOn(instance, instanceStatusInfoTx[instance].pVideoInfo->videoOutConfig.format,
        instanceStatusInfoTx[instance].pVideoInfo->videoOutConfig.mode, 
        gtmdlHdmiTxDriverConfigTable[instance].pattern);

    /* --------------------------- */
    /* Release the sempahore */
    /* --------------------------- */
    RETIF( (errCodeSem = tmdlHdmiTxIWSemaphoreV(dlHdmiTxItSemaphore[instance]) ) != TM_OK, errCodeSem)

    return errCode;

}

/******************************************************************************
    \brief This function set the Remove B.... screen
           This function is synchronous.
           This function is not ISR friendly.

    \param instance     Instance identifier. 

    \return The call result:
            - TM_OK: the call was successful, however RX keys have
                     not been checked with provided revocation list
                     because they are not available.
            - TMDL_ERR_DLHDMITX_BAD_INSTANCE: the instance number is wrong or
              out of range


******************************************************************************/

tmErrorCode_t tmdlHdmiTxRemoveBScreen(
    tmInstance_t    instance
)
{

    tmErrorCode_t errCodeSem    = TM_OK;
    tmErrorCode_t errCode       = TM_OK;

    /* Check if instance number is in range */
    RETIF((instance < 0) || (instance >= MAX_UNITS), TMDL_ERR_DLHDMITX_BAD_INSTANCE)

    /* --------------------- */
    /* Take the semaphore    */
    /* --------------------- */
    RETIF( (errCodeSem = tmdlHdmiTxIWSemaphoreP(dlHdmiTxItSemaphore[instance]) ) != TM_OK, errCodeSem)

    /* Restore last output format and mode */
    (void)dlHdmiTxSetTestPatternOff(instance, 
            instanceStatusInfoTx[instance].pVideoInfo->videoOutConfig.format,
            instanceStatusInfoTx[instance].pVideoInfo->videoOutConfig.mode);

    /* --------------------------- */
    /* Release the sempahore */
    /* --------------------------- */
    RETIF( (errCodeSem = tmdlHdmiTxIWSemaphoreV(dlHdmiTxItSemaphore[instance]) ) != TM_OK, errCodeSem)

    return errCode;

}

/******************************************************************************
    \brief tmdlHdmiTxConvertDTDtoCEA .

    \param DTDescriptors     DTD to convert.

    \return NA.

******************************************************************************/
tmdlHdmiTxVidFmt_t tmdlHdmiTxConvertDTDtoCEA
(
    tmInstance_t    instance,
    tmdlHdmiTxEdidVideoTimings_t    *pDTDescriptors
)
{

    tmdlHdmiTxVidFmt_t          codeCEA;
    tmdlHdmiTxPictAspectRatio_t pictureAspectRatio;
    Bool                        formatInterlaced;

    /* --------------------- */
    /* Take the semaphore    */
    /* --------------------- */
    tmdlHdmiTxIWSemaphoreP(dlHdmiTxItSemaphore[instance]);

    formatInterlaced = False;

    if ((pDTDescriptors->flags) & 0x80)
    {
        formatInterlaced = True;
    }

    pictureAspectRatio = dlHdmiTxCalcAspectRatio (pDTDescriptors->hImageSize, pDTDescriptors->vImageSize);

    switch (pDTDescriptors->hActivePixels)
    {
        case 640:
            codeCEA = dlHdmiTxConvertDTDtoCEA_640HAP(pDTDescriptors);
        break;

        case 720:
            codeCEA = dlHdmiTxConvertDTDtoCEA_720HAP(pDTDescriptors, pictureAspectRatio);
        break;

        case 1280:
            codeCEA = dlHdmiTxConvertDTDtoCEA_1280HAP(pDTDescriptors);
        break;

        case 1920:
            codeCEA = dlHdmiTxConvertDTDtoCEA_1920HAP(pDTDescriptors, formatInterlaced);
        break;

        case 1440:
            codeCEA = dlHdmiTxConvertDTDtoCEA_1440HAP(pDTDescriptors, pictureAspectRatio, formatInterlaced);
        break;

        case 2880:
            codeCEA = dlHdmiTxConvertDTDtoCEA_2880HAP(pDTDescriptors, pictureAspectRatio, formatInterlaced);
        break;

        default:
            /* Not a valid format */
            codeCEA = TMDL_HDMITX_VFMT_NULL;
        break;
    }

    /* --------------------------- */
    /* Release the sempahore */
    /* --------------------------- */
    tmdlHdmiTxIWSemaphoreV(dlHdmiTxItSemaphore[instance]);

    return codeCEA;

}

/*============================================================================*/
/*                           INTERNAL FUNCTION                                */
/*============================================================================*/

/******************************************************************************
    \brief Get the REFPIX and REFLINE for output and scaler 
            for the current settings.

    \param vinFmt       Video input format.
    \param vinMode      Video input mode.
    \param voutFmt      Video output format.
    \param syncIn       Type of synchro (ext or emb).
    \param pixRate      Video pixel rate.
    \param pRefPix      RefPix for output.
    \param pRefLine     RefLine for output.
    \param pScRefPix    RefPix for scaler.
    \param pScRefLine   RefLine for scaler.
    \param pbVerified   Pointer to the boolean that will receive the fact that
                        this scaler setting was verified.

    \return True (Found) or False (Not found).

******************************************************************************/
static Bool dlHdmiTxGetReflineRefpix
(
    tmdlHdmiTxVidFmt_t      vinFmt,    
    tmdlHdmiTxVinMode_t     vinMode,   
    tmdlHdmiTxVidFmt_t      voutFmt,   
    UInt8                   syncIn,
    tmdlHdmiTxPixRate_t     pixRate,
    UInt16                  *pRefPix,  
    UInt16                  *pRefLine, 
    UInt16                  *pScRefPix,
    UInt16                  *pScRefLine,
    Bool                    *pbVerified
)
{
    UInt8 shortVinFmt;
    UInt8 shortVoutFmt;
    int i;
    Bool bFound;
    tmdlHdmiTxVidFmt_t      vinFmtIndex, voutFmtIndex;
    
    /* Search for all values to match in table, until table end is reached
     * when both refPix values are zero */
    *pRefPix    = 0;
    *pRefLine   = 0;
    *pScRefPix  = 0;
    *pScRefLine = 0;
    
    /* If match is not found in table, we can assume a verified non-scaler 
     * combination */
    *pbVerified = 1;
    bFound = False;

    if ((voutFmt  <  TMDL_HDMITX_VFMT_TV_NO_REG_MIN) 
        || ((voutFmt >= HDMITX_VFMT_35_2880x480p_60Hz) && (voutFmt <= HDMITX_VFMT_38_2880x576p_50Hz)))    
    {
        vinFmtIndex  = dlHdmiTxCalcVidFmtIndex(vinFmt);
        voutFmtIndex = dlHdmiTxCalcVidFmtIndex(voutFmt);
        shortVinFmt  = kVfmtToShortFmt_TV[vinFmtIndex];
        shortVoutFmt = kVfmtToShortFmt_TV[voutFmtIndex];

        for (i = 0; kRefpixRefline[i].shortVinFmt != TV_INVALID; i++)
        {
            if ((kRefpixRefline[i].shortVinFmt == shortVinFmt)
                &&  (UNPKMODE(kRefpixRefline[i].modeRateSyncVerf) == vinMode)
                &&  (kRefpixRefline[i].shortVoutFmt == shortVoutFmt)
                &&  (UNPKRATE(kRefpixRefline[i].modeRateSyncVerf) == pixRate)
                &&  (UNPKSYNC(kRefpixRefline[i].modeRateSyncVerf) == syncIn))
            {
                *pRefPix    = kRefpixRefline[i].refPix;
                *pRefLine   = kRefpixRefline[i].refLine;
                *pScRefPix  = kRefpixRefline[i].scRefPix;
                *pScRefLine = kRefpixRefline[i].scRefLine;
                *pbVerified = UNPKVERF(kRefpixRefline[i].modeRateSyncVerf);
                bFound = True;
                break;
            }
        }
    }

    return bFound;
}

/******************************************************************************
    \brief Set the video infoframe.

    \param instance     Instance identifier.
    \param voutFmt      Video output format.
    \param voutMode     Video output mode.

    \return The call result:
            - TM_OK: the call was successful
            - TMDL_ERR_DLHDMITX_BAD_INSTANCE: the instance number is wrong or 
              out of range
            - TMBSL_ERR_HDMI_BAD_PARAMETER: a parameter was out of range
            - TMBSL_ERR_HDMI_BAD_UNIT_NUMBER: bad transmitter unit number
            - TMBSL_ERR_HDMI_I2C_WRITE: failed when writing to the I2C bus
            - TMBSL_ERR_HDMI_I2C_READ: failed when reading to the I2C bus
            - TMBSL_ERR_HDMI_NOT_INITIALIZED: transmitter not initialized

******************************************************************************/
static tmErrorCode_t dlHdmiTxSetVideoInfoframe 
(
    tmInstance_t            instance,
    tmdlHdmiTxVidFmt_t      voutFmt,
    tmdlHdmiTxVoutMode_t    voutMode
)
{
    tmErrorCode_t         errCode;        
    tmdlHdmiTxAviIfData_t contentVif;
    tmdlHdmiTxVidFmt_t    voutFmtIndex;


    /* Check if instance number is in range */
    RETIF((instance < 0) || (instance >= MAX_UNITS), TMDL_ERR_DLHDMITX_BAD_INSTANCE)

    contentVif.colorIndicator           = voutMode; /* 3rd api_set_avi_infoframe param */
    contentVif.activeInfoPresent        = 0;
    contentVif.barInformationDataValid  = 0;
    contentVif.scanInformation          = 0;

    voutFmtIndex = dlHdmiTxCalcVidFmtIndex(voutFmt);
    contentVif.pictureAspectRatio = kVfmtToAspect_TV[voutFmtIndex];

    contentVif.activeFormatAspectRatio = 8;
    contentVif.nonUniformPictureScaling = 0;

#ifdef FORMAT_PC
    if (voutFmt >= TMDL_HDMITX_VFMT_PC_MIN)
    {
        if (voutFmt == TMDL_HDMITX_VFMT_PC_640x480p_60Hz)
        {
            contentVif.videoFormatIdentificationCode = (tmbslHdmiTxVidFmt_t)TMDL_HDMITX_VFMT_01_640x480p_60Hz;
        }
        else
        {
            /* Format PC not Valid in EIA861b */
            contentVif.videoFormatIdentificationCode = (tmbslHdmiTxVidFmt_t)TMDL_HDMITX_VFMT_NULL; 
        }
    }
    else
    {
#endif /* FORMAT_PC */

        contentVif.videoFormatIdentificationCode = (tmbslHdmiTxVidFmt_t)voutFmt;
        
#ifdef FORMAT_PC
    }
#endif /* FORMAT_PC */


    if (((voutFmt >= TMDL_HDMITX_VFMT_06_720x480i_60Hz) && (voutFmt <= TMDL_HDMITX_VFMT_09_720x240p_60Hz))
        || ((voutFmt >= TMDL_HDMITX_VFMT_21_720x576i_50Hz) && (voutFmt <= TMDL_HDMITX_VFMT_24_720x288p_50Hz)))
    {
        /* Force pixel repeat for formats where it's mandatory (Pixel Frequency < 20 Mpix/s)*/
        contentVif.pixelRepetitionFactor = 1; 
    }
    else if((voutFmt == TMDL_HDMITX_VFMT_10_720x480i_60Hz)  || (voutFmt == TMDL_HDMITX_VFMT_11_720x480i_60Hz)  ||
            (voutFmt == TMDL_HDMITX_VFMT_25_720x576i_50Hz)  || (voutFmt == TMDL_HDMITX_VFMT_26_720x576i_50Hz) )
    {
        contentVif.pixelRepetitionFactor = HDMITX_PIXREP_3;    // pixel sent 1 or 10 times, here 4 times
    }
    else if((voutFmt == TMDL_HDMITX_VFMT_14_1440x480p_60Hz) || (voutFmt == TMDL_HDMITX_VFMT_15_1440x480p_60Hz) ||
            (voutFmt == TMDL_HDMITX_VFMT_29_1440x576p_50Hz) || (voutFmt == TMDL_HDMITX_VFMT_30_1440x576p_50Hz))
    {
        contentVif.pixelRepetitionFactor = HDMITX_PIXREP_1;    // pixel sent 1 or 2 times, here 2 times
    }
    else if((voutFmt >= TMDL_HDMITX_VFMT_35_2880x480p_60Hz) && (voutFmt <= TMDL_HDMITX_VFMT_38_2880x576p_50Hz))
    {
            contentVif.pixelRepetitionFactor = HDMITX_PIXREP_3;
    }
    else /* Default to no repeat for all other formats */
    {
        contentVif.pixelRepetitionFactor = HDMITX_PIXREP_NONE; 
    }

    if ((instanceStatusInfoTx[instance].pGamutState->gamutOn  == True) ||
        (instanceStatusInfoTx[instance].pGamutState->extColOn == True))
    {
        contentVif.colorimetry = (UInt8)TMDL_HDMITX_COLORIMETRY_EXTENDED;
    }
    else
    {
        switch (voutFmt)
        {
            case TMDL_HDMITX_VFMT_04_1280x720p_60Hz:
            case TMDL_HDMITX_VFMT_05_1920x1080i_60Hz:
            case TMDL_HDMITX_VFMT_16_1920x1080p_60Hz:
            case TMDL_HDMITX_VFMT_19_1280x720p_50Hz:
            case TMDL_HDMITX_VFMT_20_1920x1080i_50Hz:
            case TMDL_HDMITX_VFMT_31_1920x1080p_50Hz:
                contentVif.colorimetry = (UInt8)TMDL_HDMITX_COLORIMETRY_ITU709;    
                break;

	        default:
                contentVif.colorimetry = (UInt8)TMDL_HDMITX_COLORIMETRY_ITU601;
                break;
        }
    }

    contentVif.lineNumberEndTopBar      = 0;
    contentVif.lineNumberStartBottomBar = 0;
    contentVif.lineNumberEndLeftBar     = 0;
    contentVif.lineNumberStartRightBar  = 0;

    errCode = dlHdmiTxSetRawVideoInfoframe(instance, &contentVif, True);

    /* Ignore infoframe interlock in DVI mode */
    if (errCode == TMBSL_ERR_HDMI_OPERATION_NOT_PERMITTED)
    {
        errCode = TM_OK;
    }
    
    return errCode;
}

/******************************************************************************
    \brief Set the video infoframe.

    \param instance     Instance identifier.
    \param voutFmt      Video output format.
    \param voutMode     Video output mode.

    \return The call result:
            - TM_OK: the call was successful
            - TMDL_ERR_DLHDMITX_BAD_INSTANCE: the instance number is wrong or 
              out of range
            - TMBSL_ERR_HDMI_BAD_PARAMETER: a parameter was out of range
            - TMBSL_ERR_HDMI_BAD_UNIT_NUMBER: bad transmitter unit number
            - TMBSL_ERR_HDMI_I2C_WRITE: failed when writing to the I2C bus
            - TMBSL_ERR_HDMI_I2C_READ: failed when reading to the I2C bus
            - TMBSL_ERR_HDMI_NOT_INITIALIZED: transmitter not initialized
            - TMBSL_ERR_HDMI_OPERATION_NOT_PERMITTED: not allowed in DVI mode

******************************************************************************/
static tmErrorCode_t dlHdmiTxSetRawVideoInfoframe 
(
    tmInstance_t            instance,
    tmdlHdmiTxAviIfData_t   *pContentVif,
    Bool                    enable
)
{

    tmErrorCode_t           errCode;
    tmbslHdmiTxPktRawAvi_t  PktInfoFrame;
    UInt8         i;

    if(pContentVif != Null)
    {

        for(i=0; i<sizeof(PktInfoFrame.PB); i++) { PktInfoFrame.PB[i] = 0; }

        /* Prepare VIF header */
        PktInfoFrame.HB[0] = 0x82;     /* Video InfoFrame */
        PktInfoFrame.HB[1] = 0x02;     /* Version 2 [HDMI 1.2] */
        PktInfoFrame.HB[2] = 0x0D;     /* Length [HDMI 1.2] */

        /* Prepare VIF packet (byte numbers offset by 3) */
        PktInfoFrame.PB[0] = 0;     /* Preset checksum to zero so calculation works! */
        PktInfoFrame.PB[1] = ((pContentVif->colorIndicator& 0x03) << 5) |       /* Y1-0, B1-0,S1-0 */
                    ((pContentVif->barInformationDataValid& 0x03) << 2) |
                        (pContentVif->scanInformation & 0x03);
        if(pContentVif->activeInfoPresent == True)
        {
            PktInfoFrame.PB[1] += 0x10;                              /* A0 bit */
        }

        PktInfoFrame.PB[2] = ((pContentVif->colorimetry & 0x03) << 6) |  /* C1-0, M1-0, R3-0 */
                    ((pContentVif->pictureAspectRatio & 0x03) << 4) |
                        (pContentVif->activeFormatAspectRatio  & 0x0F);

        PktInfoFrame.PB[3] = (pContentVif->nonUniformPictureScaling & 0x03);              /* SC1-0 */ /* [HDMI 1.2] */

            /* Q1-0 = 00 => RGB Quantization Range depends on video format (CEA-861) */
            /* Limited Range for all video formats except PC formats which requires Full Range */

        if (pContentVif->colorimetry == TMDL_HDMITX_COLORIMETRY_EXTENDED)
        {
            PktInfoFrame.PB[3] = (( ((UInt8)instanceStatusInfoTx[instance].pGamutState->wideGamutColorSpace) & 0x07) <<4)
                                | PktInfoFrame.PB[3];
        }

            /* Bit ITC = 0 => No Content Type ; Bit ITC = 1 => Content Type (see CN1-0) */
            /* Today ITC = 0 => No Content Type */

        PktInfoFrame.PB[4] = (pContentVif->videoFormatIdentificationCode & 0x7F);            /* VIC6-0 */

        PktInfoFrame.PB[5] = (pContentVif->pixelRepetitionFactor & 0x0F);          /* PR3-0 */

            /* CN1-0 => Content Type */
            /* Today CN1-0 = 00 => No Data */

        /* YQ1-0 => YCC Quantization Range, only managed for those extended colorimetries */
        if (pContentVif->colorimetry == TMDL_HDMITX_COLORIMETRY_EXTENDED)
        {
            PktInfoFrame.PB[5] |= ( ((UInt8)instanceStatusInfoTx[instance].pGamutState->yccQR) & 0x03) << 6;
        }
        PktInfoFrame.PB[6] = (UInt8)(pContentVif->lineNumberEndTopBar & 0x00FF);
        PktInfoFrame.PB[7] = (UInt8)((pContentVif->lineNumberEndTopBar & 0xFF00) >> 8);
        PktInfoFrame.PB[8] = (UInt8)(pContentVif->lineNumberStartBottomBar & 0x00FF);
        PktInfoFrame.PB[9] = (UInt8)((pContentVif->lineNumberStartBottomBar & 0xFF00) >> 8);
        PktInfoFrame.PB[10] = (UInt8)(pContentVif->lineNumberEndLeftBar & 0x00FF);
        PktInfoFrame.PB[11] = (UInt8)((pContentVif->lineNumberEndLeftBar & 0xFF00) >> 8);
        PktInfoFrame.PB[12] = (UInt8)(pContentVif->lineNumberStartRightBar & 0x00FF);
        PktInfoFrame.PB[13] = (UInt8)((pContentVif->lineNumberStartRightBar & 0xFF00) >> 8);

        /* Calculate checksum - this is worked out on "Length" bytes of the
            * packet, the checksum (which we've preset to zero), and the three
            * header bytes.
            */
        PktInfoFrame.PB[0] = dlHdmiTxcalculateCheksumIF(&PktInfoFrame);

        errCode = tmbslHdmiTxPktSetRawVideoInfoframe(instance,
                    &PktInfoFrame, enable);
    }
    else
    {
        errCode = tmbslHdmiTxPktSetVideoInfoframe(instance,
                                                                                        Null, enable);
    }

    return errCode;

}

/*============================================================================*/
/* calculateChecksum - returns the byte needed to yield a checksum of zero    */
/*============================================================================*/
static UInt8
dlHdmiTxcalculateCheksumIF
(   
    tmbslHdmiTxPktRawAvi_t       *pData     /* Pointer to checksum data */
)
{
    UInt8       checksum = 0;   /* Working checksum calculation */
    UInt8       result = 0;     /* Value to be returned */
    UInt8       numBytes = 0;
    Int         i;

    if(pData != Null)
    {

        numBytes = sizeof(pData->HB);

        for (i = 0; i < numBytes; i++)
        {
            checksum = checksum + pData->HB[i];
        }

        numBytes = sizeof(pData->PB);

        for (i = 0; i < numBytes; i++)
        {
            checksum = checksum + pData->PB[i];
        }

        result = (UInt8)((255 - checksum) + 1);
    }
    return result;          /* returns 0 in the case of null ptr or 0 bytes */
}

/******************************************************************************
    \brief Set colourbar test pattern on with RGB infoframe

    \param instance     Instance identifier.
    \param voutFmt      Video output format.
    \param voutMode     Video output mode.

    \return The call result:
            - TM_OK: the call was successful
            - TMDL_ERR_DLHDMITX_BAD_INSTANCE: the instance number is wrong or 
              out of range
            - TMBSL_ERR_HDMI_BAD_UNIT_NUMBER: bad transmitter unit number
            - TMBSL_ERR_HDMI_BAD_PARAMETER: a parameter was out of range
            - TMBSL_ERR_HDMI_NOT_INITIALIZED: transmitter not initialized
            - TMBSL_ERR_HDMI_I2C_WRITE: failed when writing to the I2C bus

******************************************************************************/
tmErrorCode_t dlHdmiTxSetTestPatternOn
(
    tmInstance_t            instance,
    tmdlHdmiTxVidFmt_t		voutFmt,
    tmdlHdmiTxVoutMode_t    voutMode,
    tmdlHdmiTxTestPattern_t pattern
)
{
    tmErrorCode_t   errCode;

    /* Check if instance number is in range */
    RETIF((instance < 0) || (instance >= MAX_UNITS), TMDL_ERR_DLHDMITX_BAD_INSTANCE)

    RETIF( (errCode = tmbslHdmiTxTestSetPattern(instance, 
                        (tmbslHdmiTxTestPattern_t)pattern) ) != TM_OK, errCode)

    if (pattern > TMDL_HDMITX_PATTERN_CBAR8)
    {
        RETIF( (errCode = dlHdmiTxSetVideoInfoframe(instance, voutFmt, voutMode) ) != TM_OK, errCode)
    }
    else
    {
        /* For TMDL_HDMITX_PATTERN_CBAR8 and TMDL_HDMITX_PATTERN_CBAR4, video mode in infoframe should be RGB */
        RETIF( (errCode = dlHdmiTxSetVideoInfoframe(instance, voutFmt, TMDL_HDMITX_VOUTMODE_RGB444) ) != TM_OK, errCode)
    }
    return TM_OK;
}

/******************************************************************************
    \brief Set colourbar test pattern off with previous infoframe

    \param instance     Instance identifier.
    \param voutFmt      Video output format.
    \param voutMode     Video output mode.

    \return The call result:
            - TM_OK: the call was successful
            - TMDL_ERR_DLHDMITX_BAD_INSTANCE: the instance number is wrong or 
              out of range
            - TMBSL_ERR_HDMI_BAD_UNIT_NUMBER: bad transmitter unit number
            - TMBSL_ERR_HDMI_BAD_PARAMETER: a parameter was out of range
            - TMBSL_ERR_HDMI_NOT_INITIALIZED: transmitter not initialized
            - TMBSL_ERR_HDMI_I2C_WRITE: failed when writing to the I2C bus

******************************************************************************/
tmErrorCode_t dlHdmiTxSetTestPatternOff
(
    tmInstance_t            instance,
    tmdlHdmiTxVidFmt_t      voutFmt,
    tmdlHdmiTxVoutMode_t    voutMode
)
{
    tmErrorCode_t errCode;

    /* Check if instance number is in range */
    RETIF((instance < 0) || (instance >= MAX_UNITS), TMDL_ERR_DLHDMITX_BAD_INSTANCE)

    RETIF( (errCode = tmbslHdmiTxTestSetPattern(instance, 
                        (tmbslHdmiTxTestPattern_t)TMDL_HDMITX_PATTERN_OFF) ) != TM_OK, errCode)

    /* Restore video infoframe */
    RETIF( (errCode = dlHdmiTxSetVideoInfoframe(instance, voutFmt, voutMode) ) != TM_OK, errCode)

    return TM_OK;
}

/******************************************************************************
    \brief HDCP ENCRYPT interrupt callback.

    \param instance     Instance identifier.

    \return NA.

******************************************************************************/
static void dlHdmiTxHandleENCRYPT
(
    tmInstance_t    instance
)
{
#ifndef NO_HDCP

    tmbslHdmiTxHdcpHandleENCRYPT(instance);

    if (instanceStatusInfoTx[instance].pColBarState->disableColorBarOnR0 == False)
    {
        instanceStatusInfoTx[instance].pColBarState->hdcpColbarChange = False;
        instanceStatusInfoTx[instance].pColBarState->hdcpEncryptOrT0 = True;
    }
    instanceStatusInfoTx[instance].pColBarState->disableColorBarOnR0 = False;
#else
    (void)instance; /* Remove compiler warning */
#endif /* NO_HDCP */
}

/******************************************************************************
    \brief HPD interrupt callback.

    \param instance     Instance identifier.

    \return NA.

******************************************************************************/
static void dlHdmiTxHandleHPD
(
    tmInstance_t    instance
)
{
    tmErrorCode_t           errCode;
    tmbslHdmiTxHotPlug_t    hpdStatus;  /* HPD status */
    tmPowerState_t          powerState; /* Power state of transmitter */

    hpdStatus = HDMITX_HOTPLUG_INVALID;

    /* Get Hot Plug status */
    errCode = tmbslHdmiTxHotPlugGetStatus(instance,
                                          &hpdStatus,False);

    if (errCode != TM_OK) return;

    /* Get the power state of the transmitter */
    errCode = tmbslHdmiTxPowerGetState(instance,
                &powerState);

    if (errCode != TM_OK) return;

    /* Has hot plug changed to Active? */
    if (hpdStatus == HDMITX_HOTPLUG_ACTIVE)
    {
        /* Set state machine to Plugged */
        dlHdmiTxSetState(instance, STATE_PLUGGED);

        if (dlHdmiTxGetEventStatus(instance, TMDL_HDMITX_HPD_ACTIVE) == TMDL_HDMITX_EVENT_ENABLED)
        {
            /* Release the sempahore */
            (void)tmdlHdmiTxIWSemaphoreV(dlHdmiTxItSemaphore[instance]);
            unitTableTx[instance].pCallback(TMDL_HDMITX_HPD_ACTIVE);
            /* Take the sempahore */
           (void)tmdlHdmiTxIWSemaphoreP(dlHdmiTxItSemaphore[instance]);
        }        

        if (powerState == tmPowerOn)
        {
            /* Yes: Wait for DDC line to settle before reading EDID */
            tmbslHdmiTxSysTimerWait(instance,
                    500); /* ms */

            /* Request EDID read */
            errCode = tmbslHdmiTxEdidRequestBlockData(instance,
                unitTableTx[instance].pEdidBuffer, (Int)((unitTableTx[instance].edidBufferSize) >> 7),
                (Int)(unitTableTx[instance].edidBufferSize));

            if (errCode != TM_OK) return;
        }
    }
    else
    {
#ifndef NO_HDCP
        if (unitTableTx[instance].hdcpEnable == True)
        {
            /* Release the sempahore */
            (void)tmdlHdmiTxIWSemaphoreV(dlHdmiTxItSemaphore[instance]);
            /* Switch off HDCP */
            (void)tmdlHdmiTxSetHdcp(instance, False);
            /* Take the sempahore */
            (void)tmdlHdmiTxIWSemaphoreP(dlHdmiTxItSemaphore[instance]);
        }
#endif /* NO_HDCP */

        /* Set state machine to Unplugged */
        dlHdmiTxSetState(instance, STATE_UNPLUGGED);

        if (dlHdmiTxGetEventStatus(instance, TMDL_HDMITX_HPD_INACTIVE) == TMDL_HDMITX_EVENT_ENABLED)
        {
            /* Release the sempahore */
            (void)tmdlHdmiTxIWSemaphoreV(dlHdmiTxItSemaphore[instance]);
            unitTableTx[instance].pCallback(TMDL_HDMITX_HPD_INACTIVE);
            /* Take the sempahore */
            (void)tmdlHdmiTxIWSemaphoreP(dlHdmiTxItSemaphore[instance]);
        }        
    }
}

/******************************************************************************
    \brief T0 interrupt callback.

    \param instance     Instance identifier.

    \return NA.

******************************************************************************/
static void dlHdmiTxHandleT0
(
    tmInstance_t    instance
)
{
#ifndef NO_HDCP
    tmErrorCode_t errCode;

    errCode = tmbslHdmiTxHdcpHandleT0(instance);
    
    if (errCode != TM_OK) return;

    tmbslHdmiTxHdcpGetT0FailState(instance,
            &(hdcpInfoListTx[instance].hdcpErrorState));

    if (dlHdmiTxGetEventStatus(instance, TMDL_HDMITX_HDCP_INACTIVE) == TMDL_HDMITX_EVENT_ENABLED)
    {
        /* Release the sempahore */
        (void)tmdlHdmiTxIWSemaphoreV(dlHdmiTxItSemaphore[instance]);
        unitTableTx[instance].pCallback(TMDL_HDMITX_HDCP_INACTIVE);
        /* Take the sempahore */
        (void)tmdlHdmiTxIWSemaphoreP(dlHdmiTxItSemaphore[instance]);
    }        

    instanceStatusInfoTx[instance].pColBarState->hdcpColbarChange = False;
    instanceStatusInfoTx[instance].pColBarState->hdcpEncryptOrT0 = True;
    instanceStatusInfoTx[instance].pColBarState->hdcpSecureOrT0 = True;
#else
    (void)instance;
#endif /* NO_HDCP */
}

/******************************************************************************
    \brief BCAPS interrupt callback.

    \param instance     Instance identifier.

    \return NA.

******************************************************************************/
static void dlHdmiTxHandleBCAPS
(
    tmInstance_t    instance
)
{
#ifndef NO_HDCP
    Bool  bCheckRequired;
    tmErrorCode_t  errCode;

    /* Handle BCAPS interrupt immediately */
    errCode = tmbslHdmiTxHdcpHandleBCAPS(instance);

    if (errCode != TM_OK) return;

    /* Wait for TDA9984 to read BKSV from B device */
    tmbslHdmiTxSysTimerWait(instance, 10); 

    /* Handle BKSV read */
    errCode = tmbslHdmiTxHdcpHandleBKSV(instance,
                hdcpInfoListTx[instance].hdcpBksv, &bCheckRequired);

    if (errCode != TM_OK) return;

    if (bCheckRequired)
    {
         /* check HdcpBksv against a revocation list */
        dlHdmiTxCheckHdcpBksv (instance, hdcpInfoListTx[instance].hdcpBksv,&(hdcpInfoListTx[instance].bKsvSecure), True);
    }
    else
    {
        /* Result is always secure if no check required */
        hdcpInfoListTx[instance].bKsvSecure = True;
    }

    /* Handle BKSV result */
    errCode = tmbslHdmiTxHdcpHandleBKSVResult(instance,
               hdcpInfoListTx[instance].bKsvSecure);

    if (errCode != TM_OK) return;

    
#else
    (void)instance;
#endif /* NO_HDCP */
}

/******************************************************************************
    \brief BSTATUS interrupt callback.

    \param instance     Instance identifier.

    \return NA.

******************************************************************************/
static void dlHdmiTxHandleBSTATUS
(
    tmInstance_t    instance
)
{
#ifndef NO_HDCP
    UInt16 bstatus = 0;

	tmbslHdmiTxHdcpHandleBSTATUS(instance,
            &bstatus);

#ifdef HDMI_TX_REPEATER_ISR_MODE
    gIgnoreNextSha1 = False;
#endif /*HDMI_TX_REPEATER_ISR_MODE*/

    if (((bstatus & HDMITX_HDCP_BSTATUS_MAX_CASCADE_EXCEEDED) > 0)
    ||  ((bstatus & HDMITX_HDCP_BSTATUS_MAX_DEVS_EXCEEDED) > 0))
    {

        hdcpInfoListTx[instance].hdcpDeviceDepth = (UInt8)((bstatus & HDMITX_HDCP_BSTATUS_CASCADE_DEPTH)>>8);

        /* The KsvList length is limited by the smaller of the list array
        * length and the number of devices returned in BSTATUS */
        hdcpInfoListTx[instance].hdcpKsvDevices = 
            (UInt8)(bstatus & HDMITX_HDCP_BSTATUS_DEVICE_COUNT);

        if (HDMITX_KSV_LIST_MAX_DEVICES < hdcpInfoListTx[instance].hdcpKsvDevices)
        {
            hdcpInfoListTx[instance].hdcpKsvDevices = HDMITX_KSV_LIST_MAX_DEVICES;
        }

        if ((bstatus & HDMITX_HDCP_BSTATUS_MAX_CASCADE_EXCEEDED) > 0)
        {
            hdcpInfoListTx[instance].hdcpMaxCascExceeded = True;
        }

        if ((bstatus & HDMITX_HDCP_BSTATUS_MAX_DEVS_EXCEEDED) > 0)
        {
            hdcpInfoListTx[instance].hdcpMaxDevsExceeded = True;
        }

        if (dlHdmiTxGetEventStatus(instance, TMDL_HDMITX_RX_KEYS_RECEIVED) == TMDL_HDMITX_EVENT_ENABLED)
        {
            /* Release the sempahore */
            (void)tmdlHdmiTxIWSemaphoreV(dlHdmiTxItSemaphore[instance]);
            unitTableTx[instance].pCallback(TMDL_HDMITX_RX_KEYS_RECEIVED);
            /* Take the sempahore */
            (void)tmdlHdmiTxIWSemaphoreP(dlHdmiTxItSemaphore[instance]);
        }
    }
    else
    {

#ifdef HDMI_TX_REPEATER_ISR_MODE
        /* Call SHA_1 otherwise this ISR is missed */
        hdcpInfoListTx[instance].hdcpDeviceDepth = (UInt8)((bstatus & HDMITX_HDCP_BSTATUS_CASCADE_DEPTH)>>8);

        if (dlHdmiTxGetEventStatus(instance, TMDL_HDMITX_B_STATUS) == TMDL_HDMITX_EVENT_ENABLED)
        {
            /* Release the sempahore */
            (void)tmdlHdmiTxIWSemaphoreV(dlHdmiTxItSemaphore[instance]);
            unitTableTx[instance].pCallback(TMDL_HDMITX_B_STATUS);
            /* Take the sempahore */
            (void)tmdlHdmiTxIWSemaphoreP(dlHdmiTxItSemaphore[instance]);
        }


#endif /* HDMI_TX_REPEATER_ISR_MODE */
    }


#else
    (void)instance;
#endif /* NO_HDCP */
}

/******************************************************************************
    \brief SHA_1 interrupt callback.

    \param instance     Instance identifier.

    \return NA.

******************************************************************************/
static void dlHdmiTxHandleSHA_1
(
    tmInstance_t    instance
)
{
#ifndef NO_HDCP
    tmErrorCode_t               errCode;
    UInt8                       indexKSVList;

#ifdef HDMI_TX_REPEATER_ISR_MODE
    if (gIgnoreNextSha1 == False)
    {
       gIgnoreNextSha1 = True;
#endif /*HDMI_TX_REPEATER_ISR_MODE*/
    
        errCode = tmbslHdmiTxHdcpHandleSHA_1(instance,
                    HDMITX_KSV_LIST_MAX_DEVICES, hdcpInfoListTx[instance].hdcpKsvList,
                    &(hdcpInfoListTx[instance].hdcpKsvDevices),&(hdcpInfoListTx[instance].hdcpDeviceDepth));
        if (errCode != TM_OK) return;
    
        /* Top level or repeater HDCP mode */
        if (unitTableTx[instance].repeaterEnable == False)
        {
            /* check HdcpKsvList against revocation list */
            
            indexKSVList = 0;
            while (( indexKSVList <  TMDL_HDMITX_KSV_LIST_MAX_DEVICES ) &&
                   ( indexKSVList <  hdcpInfoListTx[instance].hdcpKsvDevices ) && 
                    (hdcpInfoListTx[instance].bKsvSecure == True)
                  )
            {
                dlHdmiTxCheckHdcpBksv (instance,
                                       &(hdcpInfoListTx[instance].hdcpKsvList[indexKSVList * TMDL_HDMITX_KSV_BYTES_PER_DEVICE]),
                                       &(hdcpInfoListTx[instance].bKsvSecure),
                                       False);
                indexKSVList++;
            }
        }
        else
        {
            hdcpInfoListTx[instance].bKsvSecure = True;
        }
    
        /* Handle SHA_1 result */
        errCode = tmbslHdmiTxHdcpHandleSHA_1Result(instance,
                    hdcpInfoListTx[instance].bKsvSecure);
    
        if (dlHdmiTxGetEventStatus(instance, TMDL_HDMITX_RX_KEYS_RECEIVED) == TMDL_HDMITX_EVENT_ENABLED)
        {
            /* Release the sempahore */
            (void)tmdlHdmiTxIWSemaphoreV(dlHdmiTxItSemaphore[instance]);
            unitTableTx[instance].pCallback(TMDL_HDMITX_RX_KEYS_RECEIVED);
            /* Take the sempahore */
            (void)tmdlHdmiTxIWSemaphoreP(dlHdmiTxItSemaphore[instance]);
        }
    
        if (!hdcpInfoListTx[instance].bKsvSecure) 
        {
           instanceStatusInfoTx[instance].pColBarState->changeColorBarNow = True; 
           instanceStatusInfoTx[instance].pColBarState->colorBarOn = True;
           dlHdmiTxCheckColorBar(instance);
        }
#ifdef HDMI_TX_REPEATER_ISR_MODE
    }
#endif /*HDMI_TX_REPEATER_ISR_MODE*/
        

#else
    (void)instance;
#endif /* NO_HDCP */
}

/******************************************************************************
    \brief PJ interrupt callback.

    \param instance     Instance identifier.

    \return NA.

******************************************************************************/
static void dlHdmiTxHandlePJ
(
    tmInstance_t    instance
)
{
#ifndef NO_HDCP
    tmbslHdmiTxHdcpHandlePJ(instance);
#else
    (void)instance;
#endif /* NO_HDCP */
}

/******************************************************************************
    \brief R0 interrupt callback.

    \param instance     Instance identifier.

    \return NA.

******************************************************************************/
static void dlHdmiTxHandleR0
(
    tmInstance_t    instance
)
{
#ifndef NO_HDCP
    tmErrorCode_t             errCode;
    tmbslHdmiTxSinkCategory_t category;



  if (hdcpInfoListTx[instance].bKsvSecure == True)
    {

        if (dlHdmiTxGetEventStatus(instance, TMDL_HDMITX_HDCP_ACTIVE) == TMDL_HDMITX_EVENT_ENABLED)
        {
            /* Release the sempahore */
            (void)tmdlHdmiTxIWSemaphoreV(dlHdmiTxItSemaphore[instance]);
            unitTableTx[instance].pCallback(TMDL_HDMITX_HDCP_ACTIVE);
            /* Take the sempahore */
            (void)tmdlHdmiTxIWSemaphoreP(dlHdmiTxItSemaphore[instance]);
        }

        instanceStatusInfoTx[instance].pColBarState->hdcpSecureOrT0 = False;
    }


    errCode = tmbslHdmiTxHdcpGetSinkCategory(instance,
                                             &category);
    if (errCode != TM_OK) return;

    if (category == HDMITX_SINK_CAT_NOT_REPEATER)
    {
        if (dlHdmiTxGetEventStatus(instance, TMDL_HDMITX_RX_KEYS_RECEIVED) == TMDL_HDMITX_EVENT_ENABLED)
        {
            /* Release the sempahore */
            (void)tmdlHdmiTxIWSemaphoreV(dlHdmiTxItSemaphore[instance]);
            unitTableTx[instance].pCallback(TMDL_HDMITX_RX_KEYS_RECEIVED);
            /* Take the sempahore */
            (void)tmdlHdmiTxIWSemaphoreP(dlHdmiTxItSemaphore[instance]);
        }
    }

    instanceStatusInfoTx[instance].pColBarState->disableColorBarOnR0 = True;
    instanceStatusInfoTx[instance].pColBarState->hdcpColbarChange = True;
#else
    (void)instance;
#endif /* NO_HDCP */
}

/******************************************************************************
    \brief SW_INT interrupt callback.

    \param instance     Instance identifier.

    \return NA.

******************************************************************************/
static void dlHdmiTxHandleSW_INT
(
    tmInstance_t    instance
)
{
    DUMMY_ACCESS(instance);
}

/******************************************************************************
    \brief RX_SENSE interrupt callback.

    \param instance     Instance identifier.

    \return NA.

******************************************************************************/
static void dlHdmiTxHandleRX_SENSE
(
    tmInstance_t    instance
)
{
    tmErrorCode_t           errCode;
    tmbslHdmiTxRxSense_t    rxSenseStatus;  /* Rx Sense status */
    tmbslHdmiTxHotPlug_t    hpdStatus;      /* HPD status */

    errCode = tmbslHdmiTxRxSenseGetStatus(instance,
                                          &rxSenseStatus,False);

    if (errCode != TM_OK) return;

    errCode = tmbslHdmiTxHotPlugGetStatus(instance,
                                          &hpdStatus,False);

    if (errCode != TM_OK) return;

//    if (hpdStatus == HDMITX_HOTPLUG_ACTIVE) 
//    {
        if (rxSenseStatus == HDMITX_RX_SENSE_ACTIVE)
        {
            if (dlHdmiTxGetEventStatus(instance, TMDL_HDMITX_RX_DEVICE_ACTIVE) == TMDL_HDMITX_EVENT_ENABLED)
            {
                /* Release the sempahore */
                (void)tmdlHdmiTxIWSemaphoreV(dlHdmiTxItSemaphore[instance]);
                unitTableTx[instance].pCallback(TMDL_HDMITX_RX_DEVICE_ACTIVE);
                /* Take the sempahore */
				(void)tmdlHdmiTxIWSemaphoreP(dlHdmiTxItSemaphore[instance]);
            }
        }
        else if (rxSenseStatus == HDMITX_RX_SENSE_INACTIVE)
        {

            if (dlHdmiTxGetEventStatus(instance, TMDL_HDMITX_RX_DEVICE_INACTIVE) == TMDL_HDMITX_EVENT_ENABLED)
            {
                /* Release the sempahore */
                (void)tmdlHdmiTxIWSemaphoreV(dlHdmiTxItSemaphore[instance]);
                unitTableTx[instance].pCallback(TMDL_HDMITX_RX_DEVICE_INACTIVE);
                /* Take the sempahore */
                (void)tmdlHdmiTxIWSemaphoreP(dlHdmiTxItSemaphore[instance]);
            }

#ifndef NO_HDCP
            if (unitTableTx[instance].hdcpEnable == True)
            {
                /* Release the sempahore */
                (void)tmdlHdmiTxIWSemaphoreV(dlHdmiTxItSemaphore[instance]);
                /* Switch off HDCP */
                (void)tmdlHdmiTxSetHdcp(instance, False);
                /* Take the sempahore */
                (void)tmdlHdmiTxIWSemaphoreP(dlHdmiTxItSemaphore[instance]);
            }
#endif /* NO_HDCP */
        }
//    }
}

/******************************************************************************
    \brief EDID_READ interrupt callback.

    \param instance     Instance identifier.

    \return NA.

******************************************************************************/
static void dlHdmiTxHandleEDID_READ
(
    tmInstance_t    instance
)
{
    tmErrorCode_t           errCode;
    UInt8                   edidStatus = TMDL_HDMITX_EDID_NOT_READ;

    /* Get the edid status and read the connected device's EDID */

    /* Get Edid status */
    errCode = tmbslHdmiTxEdidGetStatus(instance,
                &edidStatus);

    if (errCode != TM_OK)
    {
        /* Set state machine to Plugged */
        dlHdmiTxSetState(instance, STATE_PLUGGED);
        return;
    }

    /* Has hot plug changed to Active? */
    if ((edidStatus == TMDL_HDMITX_EDID_READ) ||
        (edidStatus == TMDL_HDMITX_EDID_ERROR_CHK))
    {
        /* Set state machine to EDID available */
       dlHdmiTxSetState(instance, STATE_EDID_AVAILABLE);
    }
    else
    {
        /* Set state machine to Plugged */
        dlHdmiTxSetState(instance, STATE_PLUGGED);
    }
    

    if (dlHdmiTxGetEventStatus(instance, TMDL_HDMITX_EDID_RECEIVED) == TMDL_HDMITX_EVENT_ENABLED)
    {
       /* Release the sempahore */
       (void)tmdlHdmiTxIWSemaphoreV(dlHdmiTxItSemaphore[instance]);
       unitTableTx[instance].pCallback(TMDL_HDMITX_EDID_RECEIVED);
       /* Take the sempahore */
       (void)tmdlHdmiTxIWSemaphoreP(dlHdmiTxItSemaphore[instance]);
    }

    
}

/******************************************************************************
    \brief VS_RPT interrupt callback.

    \param instance     Instance identifier.

    \return NA.

******************************************************************************/
static void dlHdmiTxHandleVS_RPT
(
    tmInstance_t    instance
)
{
    if (dlHdmiTxGetEventStatus(instance, TMDL_HDMITX_VS_RPT_RECEIVED) == TMDL_HDMITX_EVENT_ENABLED)
    {
        /* Release the sempahore */
        (void)tmdlHdmiTxIWSemaphoreV(dlHdmiTxItSemaphore[instance]);
        unitTableTx[instance].pCallback(TMDL_HDMITX_VS_RPT_RECEIVED);
        /* Take the sempahore */
        (void)tmdlHdmiTxIWSemaphoreP(dlHdmiTxItSemaphore[instance]);
    }        
}

/******************************************************************************
    \brief dlHdmiTxConvertDTDtoCEA_640HAP .

    \param  pDTDescriptors      DTD to convert.
            pictureAspectRatio  aspect ratio of DTD
            formatInterlaced    DTD Interlaced or progressif

    \return NA.

******************************************************************************/
static tmdlHdmiTxVidFmt_t dlHdmiTxConvertDTDtoCEA_640HAP
(
    tmdlHdmiTxEdidVideoTimings_t    *pDTDescriptors
)
{
    tmdlHdmiTxVidFmt_t          codeCEA;

    switch (pDTDescriptors->vActiveLines)
    {
        case 480:
            codeCEA = TMDL_HDMITX_VFMT_01_640x480p_60Hz;
        break;

        default:
            /* Not a valid format */
            codeCEA = TMDL_HDMITX_VFMT_NULL;
        break;
    }

    return codeCEA;

}

/******************************************************************************
    \brief dlHdmiTxConvertDTDtoCEA_720HAP .

    \param  pDTDescriptors      DTD to convert.
            pictureAspectRatio  aspect ratio of DTD
            formatInterlaced    DTD Interlaced or progressif

    \return NA.

******************************************************************************/
static tmdlHdmiTxVidFmt_t dlHdmiTxConvertDTDtoCEA_720HAP
(
    tmdlHdmiTxEdidVideoTimings_t    *pDTDescriptors,
    tmdlHdmiTxPictAspectRatio_t     pictureAspectRatio
)
{
    tmdlHdmiTxVidFmt_t          codeCEA;

    switch (pDTDescriptors->vActiveLines)
    {
        case 480:
            if (pictureAspectRatio == TMDL_HDMITX_P_ASPECT_RATIO_4_3)
            {
                codeCEA = TMDL_HDMITX_VFMT_02_720x480p_60Hz;
            }
            else
            {
                codeCEA = TMDL_HDMITX_VFMT_03_720x480p_60Hz;
            }
        break;

        case 576:
            if (pictureAspectRatio == TMDL_HDMITX_P_ASPECT_RATIO_4_3)
            {
                codeCEA = TMDL_HDMITX_VFMT_17_720x576p_50Hz;
            }
            else
            {
                codeCEA = TMDL_HDMITX_VFMT_18_720x576p_50Hz;
            }
        break;

        default:
            /* Not a valid format */
            codeCEA = TMDL_HDMITX_VFMT_NULL;
        break;
    }

    return codeCEA;

}
/******************************************************************************
    \brief dlHdmiTxConvertDTDtoCEA_1280HAP .

    \param  pDTDescriptors      DTD to convert.
            pictureAspectRatio  aspect ratio of DTD
            formatInterlaced    DTD Interlaced or progressif

    \return NA.

******************************************************************************/
static tmdlHdmiTxVidFmt_t dlHdmiTxConvertDTDtoCEA_1280HAP
(
    tmdlHdmiTxEdidVideoTimings_t    *pDTDescriptors
)
{
    tmdlHdmiTxVidFmt_t          codeCEA;

    switch (pDTDescriptors->vActiveLines)
    {
        case 720:
            switch (pDTDescriptors->hBlankPixels)
            {
                case 370: 
                    codeCEA = TMDL_HDMITX_VFMT_04_1280x720p_60Hz;
                break;

                case 700: 
                    codeCEA = TMDL_HDMITX_VFMT_19_1280x720p_50Hz;
                break;

                default:
                    /* Not a valid format */
                    codeCEA = TMDL_HDMITX_VFMT_NULL;
                break;
            }
        break;

        default:
            /* Not a valid format */
            codeCEA = TMDL_HDMITX_VFMT_NULL;
        break;
    }


    return codeCEA;
}

/******************************************************************************
    \brief dlHdmiTxConvertDTDtoCEA_1920HAP .

    \param  pDTDescriptors      DTD to convert.
            pictureAspectRatio  aspect ratio of DTD
            formatInterlaced    DTD Interlaced or progressif

    \return NA.

******************************************************************************/
static tmdlHdmiTxVidFmt_t dlHdmiTxConvertDTDtoCEA_1920HAP
(
    tmdlHdmiTxEdidVideoTimings_t    *pDTDescriptors,
    Bool                            formatInterlaced

)
{
    tmdlHdmiTxVidFmt_t          codeCEA;

    switch (pDTDescriptors->hBlankPixels)
    {
        case 280:
            if (formatInterlaced)
            {
                codeCEA = TMDL_HDMITX_VFMT_05_1920x1080i_60Hz;
            }
            else
            {
                if ( pDTDescriptors->pixelClock == 14850 )
                {
                    codeCEA = TMDL_HDMITX_VFMT_16_1920x1080p_60Hz;
                }
                else
                {
                    codeCEA = TMDL_HDMITX_VFMT_34_1920x1080p_30Hz;
                }
            }
        break;

        case 720: 
            if (formatInterlaced)
            {
                codeCEA = TMDL_HDMITX_VFMT_20_1920x1080i_50Hz;
            }
            else
            {
                switch (pDTDescriptors->pixelClock)
                {
                    case 14850:
                        codeCEA = TMDL_HDMITX_VFMT_31_1920x1080p_50Hz;
                    break;

                    case 7425:
                        codeCEA = TMDL_HDMITX_VFMT_33_1920x1080p_25Hz;
                    break;
                    default:
                        /* Not a valid format */
                        codeCEA = TMDL_HDMITX_VFMT_NULL;
                    break;
                }
            }
        break;

        case 830: 
            codeCEA = TMDL_HDMITX_VFMT_32_1920x1080p_24Hz;
        break;

        default:
            /* Not a valid format */
            codeCEA = TMDL_HDMITX_VFMT_NULL;
        break;
    }
           

    return codeCEA;
}

/******************************************************************************
    \brief dlHdmiTxConvertDTDtoCEA_1440HAP .

    \param  pDTDescriptors      DTD to convert.
            pictureAspectRatio  aspect ratio of DTD
            formatInterlaced    DTD Interlaced or progressif

    \return NA.

******************************************************************************/
static tmdlHdmiTxVidFmt_t dlHdmiTxConvertDTDtoCEA_1440HAP
(
    tmdlHdmiTxEdidVideoTimings_t    *pDTDescriptors,
    tmdlHdmiTxPictAspectRatio_t     pictureAspectRatio,
    Bool                            formatInterlaced

)
{
    tmdlHdmiTxVidFmt_t          codeCEA;

    switch (pDTDescriptors->vActiveLines)
    {
        case 240:
            if (formatInterlaced)
            {
                if (pictureAspectRatio == TMDL_HDMITX_P_ASPECT_RATIO_4_3)
                {
                    codeCEA = TMDL_HDMITX_VFMT_06_720x480i_60Hz;
                }
                else
                {
                    codeCEA = TMDL_HDMITX_VFMT_07_720x480i_60Hz;
                }
            }
            else
            {
                if (pictureAspectRatio == TMDL_HDMITX_P_ASPECT_RATIO_4_3)
                {
                    codeCEA = TMDL_HDMITX_VFMT_08_720x240p_60Hz;
                }
                else
                {
                    codeCEA = TMDL_HDMITX_VFMT_09_720x240p_60Hz;
                }
            }
        break;

        case 288:
            if (formatInterlaced)
            {
                if (pictureAspectRatio == TMDL_HDMITX_P_ASPECT_RATIO_4_3)
                {
                    codeCEA = TMDL_HDMITX_VFMT_21_720x576i_50Hz;
                }
                else
                {
                    codeCEA = TMDL_HDMITX_VFMT_22_720x576i_50Hz;
                }
            }
            else
            {
                if (pictureAspectRatio == TMDL_HDMITX_P_ASPECT_RATIO_4_3)
                {
                    codeCEA = TMDL_HDMITX_VFMT_23_720x288p_50Hz;
                }
                else
                {
                    codeCEA = TMDL_HDMITX_VFMT_24_720x288p_50Hz;
                }
            }
        break;

        case 480:
            if (pictureAspectRatio == TMDL_HDMITX_P_ASPECT_RATIO_4_3)
            {
                codeCEA = TMDL_HDMITX_VFMT_14_1440x480p_60Hz;
            }
            else
            {
                codeCEA = TMDL_HDMITX_VFMT_15_1440x480p_60Hz;
            }
        break;

        case 576:
            if (pictureAspectRatio == TMDL_HDMITX_P_ASPECT_RATIO_4_3)
            {
                codeCEA = TMDL_HDMITX_VFMT_29_1440x576p_50Hz;
            }
            else
            {
                codeCEA = TMDL_HDMITX_VFMT_30_1440x576p_50Hz;
            }
        break;

        default:
            /* Not a valid format */
            codeCEA = TMDL_HDMITX_VFMT_NULL;
        break;
    }

    return codeCEA;
}

/******************************************************************************
    \brief dlHdmiTxConvertDTDtoCEA_2880HAP .

    \param  pDTDescriptors      DTD to convert.
            pictureAspectRatio  aspect ratio of DTD
            formatInterlaced    DTD Interlaced or progressif

    \return NA.

******************************************************************************/
static tmdlHdmiTxVidFmt_t dlHdmiTxConvertDTDtoCEA_2880HAP
(
    tmdlHdmiTxEdidVideoTimings_t    *pDTDescriptors,
    tmdlHdmiTxPictAspectRatio_t     pictureAspectRatio,
    Bool                            formatInterlaced
)
{
    tmdlHdmiTxVidFmt_t          codeCEA;

    switch (pDTDescriptors->vActiveLines)
    {
        case 240:
            if (formatInterlaced)
            {
                if (pictureAspectRatio == TMDL_HDMITX_P_ASPECT_RATIO_4_3)
                {
                    codeCEA = TMDL_HDMITX_VFMT_10_720x480i_60Hz;
                }
                else
                {
                    codeCEA = TMDL_HDMITX_VFMT_11_720x480i_60Hz;
                }
            }
            else
            {
                if (pictureAspectRatio == TMDL_HDMITX_P_ASPECT_RATIO_4_3)
                {
                    codeCEA = TMDL_HDMITX_VFMT_12_720x240p_60Hz;
                }
                else
                {
                    codeCEA = TMDL_HDMITX_VFMT_13_720x240p_60Hz;
                }
            }
        break;

        case 288:
            if (formatInterlaced)
            {
                if (pictureAspectRatio == TMDL_HDMITX_P_ASPECT_RATIO_4_3)
                {
                    codeCEA = TMDL_HDMITX_VFMT_25_720x576i_50Hz;
                }
                else
                {
                    codeCEA = TMDL_HDMITX_VFMT_26_720x576i_50Hz;
                }
            }
            else
            {
                if (pictureAspectRatio == TMDL_HDMITX_P_ASPECT_RATIO_4_3)
                {
                    codeCEA = TMDL_HDMITX_VFMT_27_720x288p_50Hz;
                }
                else
                {
                    codeCEA = TMDL_HDMITX_VFMT_28_720x288p_50Hz;
                }
            }
        break;

        default:
            /* Not a valid format */
            codeCEA = TMDL_HDMITX_VFMT_NULL;
        break;
    }

    return codeCEA;
}

/******************************************************************************
    \brief EdidGetDTD .

    \param .

    \return NA.

******************************************************************************/
tmErrorCode_t dlHdmiTxEdidGetDTD
(
    tmInstance_t                    instance,
    tmdlHdmiTxEdidVideoTimings_t    *pDTDescriptors,
    UInt8                           maxDTDesc,
    UInt8                           *pWrittenDTDesc
)
{
    tmErrorCode_t   errCode;

    /* Check the current state */   
    RETIF( dlHdmiTxGetState(instance) != STATE_EDID_AVAILABLE, TMDL_ERR_DLHDMITX_INVALID_STATE)

    /* Get detailled descriptors from EDID, return TMDL_ERR_DLHDMITX_NO_RESOURCES if EDID are not read */
    RETIF((errCode = tmbslHdmiTxEdidGetDetailedTimingDescriptors(
                        instance, (tmbslHdmiTxEdidDtd_t *)pDTDescriptors, maxDTDesc, pWrittenDTDesc) ) != TM_OK, errCode);

    return TM_OK;
}


/******************************************************************************
    \brief Command processing task, dedicated to unit/instance 0.

    \param NA.

    \return NA.

******************************************************************************/

#ifndef TMFL_NO_RTOS
static void CommandTaskUnit0()
{
    UInt8                   command;
    Bool                    loop = True;    /* Just to avoid compiler warning */
    tmErrorCode_t           err = TM_OK;

    while(loop)
    {
        tmdlHdmiTxIWQueueReceive(unitTableTx[0].queueHandle, &command);

        /* Take the sempahore */
        (void)tmdlHdmiTxIWSemaphoreP(dlHdmiTxItSemaphore[0]);

        /* Clear T0 flag before polling for interrupts */
        instanceStatusInfoTx[0].pColBarState->hdcpSecureOrT0 = False;

        if (gI2CDebugAccessesEnabled == True)
        {

            err = tmbslHdmiTxHwHandleInterrupt(0);
        
            if ((err == TMBSL_ERR_HDMI_I2C_WRITE) || (err == TMBSL_ERR_HDMI_I2C_READ))
            {

                unitTableTx[0].pCallback(TMDL_HDMITX_DEBUG_EVENT_1);
            }

        }/* (gI2CDebugAccessesEnabled == True) */

        /* Enable interrupts for Tx (interrupts are disabled in the HandleInterrupt function) */
        tmdlHdmiTxIWEnableInterrupts(TMDL_HDMI_IW_TX_1);

        /* Release the sempahore */
        (void)tmdlHdmiTxIWSemaphoreV(dlHdmiTxItSemaphore[0]);
    };
}
#endif /* TMFL_NO_RTOS */

/******************************************************************************
    \brief Hdcp check task, dedicated to unit/instance 0.

    \param NA.

    \return NA.

******************************************************************************/
#ifndef TMFL_NO_RTOS
static void HdcpTaskUnit0()
{
    Bool loop = True;    /* Just to avoid compiler warning */
    Bool featureSupported;

    tmbslHdmiTxHwGetCapabilities(0, 
            HDMITX_FEATURE_HW_HDCP, &featureSupported);

#ifndef NO_HDCP
    while(loop)
    {
        (void)tmdlHdmiTxIWWait(35);
		
		/* Take the sempahore */
        (void)tmdlHdmiTxIWSemaphoreP(dlHdmiTxItSemaphore[0]);

        if (gI2CDebugAccessesEnabled == True)
        {

            dlHdmiTxCheckColorBar(0);
            dlHdmiTxCheckHdcpColorBar(0);

            if (featureSupported == True)
            {
                tmbslHdmiTxHdcpCheck(0,35, (tmbslHdmiTxHdcpCheck_t *)&(hdcpInfoListTx[0].hdcpCheckState));
            }

        } /*  gI2CDebugAccessesEnabled == True*/

        /* Release the sempahore */
        (void)tmdlHdmiTxIWSemaphoreV(dlHdmiTxItSemaphore[0]);
    };
#else
    (void)loop;
#endif /* NO_HDCP */
}
#endif /* TMFL_NO_RTOS */

#ifndef NO_HDCP
/******************************************************************************
    \brief Check hdcp state to manage color bar.

    \param instance Instance identifier.

    \return NA.

******************************************************************************/
static void dlHdmiTxCheckHdcpColorBar
(
    tmInstance_t instance
)
{
    /* Use HDCP check result to control HDCP colour bars */
    if ( (instanceStatusInfoTx[instance].pColBarState->disableColorBarOnR0 == True)
        && (instanceStatusInfoTx[instance].pColBarState->hdcpColbarChange == True)
        && (instanceStatusInfoTx[instance].pColBarState->hdcpSecureOrT0 == False) )
    {
        /* Remove test pattern once if Authenticated with no error interrupts */ 
        if (instanceStatusInfoTx[instance].pColBarState->colorBarOn != False)
        {
            instanceStatusInfoTx[instance].pColBarState->colorBarOn = False;
            instanceStatusInfoTx[instance].pColBarState->changeColorBarNow = True;

            if (unitTableTx[instance].simplayHd == True) {

           /* Mute or Un-mute the audio output */
           tmbslHdmiTxAudioOutSetMute(instance,(tmbslHdmiTxaMute_t)HDMITX_AMUTE_OFF);

           /* Store current audio mute status */
           instanceStatusInfoTx[instance].pAudioInfo->audioMuteState = False;
            }


        }
        /* Reset state flags */
        instanceStatusInfoTx[instance].pColBarState->hdcpColbarChange = False;
        instanceStatusInfoTx[instance].pColBarState->hdcpSecureOrT0 = True;

#ifdef TMFL_TDA19989
        instanceStatusInfoTx[instance].pColBarState->disableColorBarOnR0 = False;
#endif /* TMFL_TDA19989 */



    }
    
    if ( (instanceStatusInfoTx[instance].pColBarState->hdcpEncryptOrT0 == True)
        && (instanceStatusInfoTx[instance].pColBarState->inOutFirstSetDone == True))
    {
        /* Set test pattern once if not Authenticated, to mask HDCP failure */ 
        if (instanceStatusInfoTx[instance].pColBarState->colorBarOn != True)
        {
            instanceStatusInfoTx[instance].pColBarState->colorBarOn = True;
            instanceStatusInfoTx[instance].pColBarState->changeColorBarNow = True;

            if (unitTableTx[instance].simplayHd == True) {

           /* Mute or Un-mute the audio output */
           tmbslHdmiTxAudioOutSetMute(instance,(tmbslHdmiTxaMute_t)HDMITX_AMUTE_ON);

           /* Store current audio mute status */
           instanceStatusInfoTx[instance].pAudioInfo->audioMuteState = True;
            }

        }
        /* Reset state flag */
        instanceStatusInfoTx[instance].pColBarState->hdcpEncryptOrT0 = False;
    }
}
#endif

#ifndef NO_HDCP
/******************************************************************************
    \brief Show color bars or restore the last video format.

    \param instance Instance identifier.

    \return NA.

******************************************************************************/
static void dlHdmiTxCheckColorBar
(
    tmInstance_t instance
)
{
    if ( (instanceStatusInfoTx[instance].pColBarState->inOutFirstSetDone == True)
			&& (instanceStatusInfoTx[instance].pColBarState->changeColorBarNow == True) )
    {
        instanceStatusInfoTx[instance].pColBarState->changeColorBarNow = False;

        if (unitTableTx[instance].simplayHd == True)
        {
            if (instanceStatusInfoTx[instance].pColBarState->colorBarOn == True)
            {
                /* Set service mode colour bar on/off (also used as HDCP logo pattern) */
                (void)dlHdmiTxSetTestPatternOn(instance, instanceStatusInfoTx[instance].pVideoInfo->videoOutConfig.format,
                    instanceStatusInfoTx[instance].pVideoInfo->videoOutConfig.mode, 
                    gtmdlHdmiTxDriverConfigTable[instance].pattern);
            }
            else
            {
                /* Restore last output format and mode */
                (void)dlHdmiTxSetTestPatternOff(instance, 
                        instanceStatusInfoTx[instance].pVideoInfo->videoOutConfig.format,
                        instanceStatusInfoTx[instance].pVideoInfo->videoOutConfig.mode);
            }
        }
    }
}
#endif

#ifndef NO_HDCP
/******************************************************************************
    \brief Get hdcp seed.

    \param instance Instance identifier.

    \return NA.

******************************************************************************/
static void dlHdmiTxFindHdcpSeed
(
    tmInstance_t instance
)
{
#if HDCP_SEED_DEFAULT == HDCP_SEED_NULL
    UInt8 otp[3];
#endif

    /* If no seed is coded in this file then find it somewhere else */
#if HDCP_SEED_DEFAULT == HDCP_SEED_NULL
    /* See if a seed table has been programmed in flash */
    if (kSeedTable[0][0] != 0xFFFF)
    {
        /* Read OTP LSB at address 0x00 and try to match in flash table */
        if ( (tmbslHdmiTxHdcpGetOtp(instance,
				0x00, otp)) == TM_OK)
        {
            int i;
            for (i = 0; i < SEED_TABLE_LEN; i++)
            {
                if (kSeedTable[i][0] == otp[2]) /* OTP_DATA_LSB */
                {
                    /* Found seed! */
                    gtmdlHdmiTxDriverConfigTable[instance].keySeed = kSeedTable[i][1];
                    break;
                }
            }
        }
    }
#endif  /* HDCP_SEED_DEFAULT != HDCP_SEED_NULL */

    /* Initialise the TDA9984 HDCP keys */
    if (gtmdlHdmiTxDriverConfigTable[instance].keySeed != HDCP_SEED_NULL)
    {
		/* Initialise the HDMI Transmitter HDCP keys */
        tmbslHdmiTxHdcpDownloadKeys(instance,
				gtmdlHdmiTxDriverConfigTable[instance].keySeed, HDMITX_HDCP_DECRYPT_ENABLE);
    }
}
#endif /* NO_HDCP */

/******************************************************************************
    \brief Set the state of the state machine.

    \param instance Instance identifier.
    \param state    State of the state machine.

    \return NA.

******************************************************************************/
static void dlHdmiTxSetState
(
    tmInstance_t            instance,
    tmdlHdmiTxDriverState_t state
)
{
    /* Set the state */
    unitTableTx[instance].state = state;
}

/******************************************************************************
    \brief Get the state of the state machine.

    \param instance Instance identifier.

    \return tmdlHdmiTxDriverState_t Current State of the state machine.

******************************************************************************/
tmdlHdmiTxDriverState_t dlHdmiTxGetState
(
    tmInstance_t instance
)
{
    tmdlHdmiTxDriverState_t state;
   
    /* Get the state */
    state = unitTableTx[instance].state;

    return (state);   
}

/******************************************************************************
    \brief Get the state of the event (enabled or disabled).

    \param instance Instance identifier.
    \param event    Event to give the state.

    \return NA.

******************************************************************************/
static tmdlHdmiTxEventStatus_t dlHdmiTxGetEventStatus
(
    tmInstance_t        instance,
    tmdlHdmiTxEvent_t   event
)
{
    tmdlHdmiTxEventStatus_t   eventStatus;
   
    /* Get the event status */
    eventStatus = instanceStatusInfoTx[instance].pEventState[event].status;

    return (eventStatus);
}

/******************************************************************************
    \brief Caculation of aspect ratio.

    \param HImageSize Horizontal image size.
    \param VImageSize Vertical image size.

    \return NA.

******************************************************************************/
static tmdlHdmiTxPictAspectRatio_t dlHdmiTxCalcAspectRatio (
    UInt16    HImageSize,
    UInt16    VImageSize
)
{
    tmdlHdmiTxPictAspectRatio_t    pictureAspectRatio;
    UInt16                         calcPictureAspectRatio;

    /* Define picture Aspect Ratio                                          */
    /* 16/9 = 1.77777 so the result approach is 2                           */
    /* 4/3 = 1.33333 so the result approach is 1                            */
    /*  operation :                                                         */
    /* ImageSize + (vImageSize/2)                                           */
    /* -------------------------- > vImageSize     ->True 16/9 False 4/3    */
    /*           2                                                          */

    calcPictureAspectRatio = ((UInt16)(HImageSize + ((VImageSize)>>1)))>>1;

    if(calcPictureAspectRatio > VImageSize)
    {
        pictureAspectRatio = TMDL_HDMITX_P_ASPECT_RATIO_16_9;
    }
    else
    {
        pictureAspectRatio = TMDL_HDMITX_P_ASPECT_RATIO_4_3;
    }

    return pictureAspectRatio;

}

#ifndef NO_HDCP
/******************************************************************************
    \brief dlHdmiTxCheckHdcpBksv .

    \param pHdcpBksvTested  ksv To test.
    \param pbBksvSecure     Test result.
    \param bBigEndian       ksv provide by hardware are in little or big endian.

    \return NA.

******************************************************************************/
static void dlHdmiTxCheckHdcpBksv
(
    tmInstance_t    instance,
    UInt8 *         pHdcpBksvTested,
    Bool  *         pbBksvSecure,
    Bool            bBigEndian
)
{

    UInt32 NbInRevocationList;

    NbInRevocationList = 0;

    /* CBE: force secure, otherwise we will not look at anything */
    *pbBksvSecure = True;

    if ((unitTableTx[instance].revocationList.pList != Null) && (unitTableTx[instance].revocationList.length > 0))
    {
        while ((*pbBksvSecure == True) && (NbInRevocationList < unitTableTx[instance].revocationList.length))
        {
            if (bBigEndian)
            {
                if ((pHdcpBksvTested[0] == unitTableTx[instance].revocationList.pList[NbInRevocationList * HDMITX_KSV_BYTES_PER_DEVICE])
                    &&
                    (pHdcpBksvTested[1] == unitTableTx[instance].revocationList.pList[1 + (NbInRevocationList * HDMITX_KSV_BYTES_PER_DEVICE)])
                    &&
                    (pHdcpBksvTested[2] == unitTableTx[instance].revocationList.pList[2 + (NbInRevocationList * HDMITX_KSV_BYTES_PER_DEVICE)])
                    &&
                    (pHdcpBksvTested[3] == unitTableTx[instance].revocationList.pList[3 + (NbInRevocationList * HDMITX_KSV_BYTES_PER_DEVICE)])
                    &&
                    (pHdcpBksvTested[4] == unitTableTx[instance].revocationList.pList[4 + (NbInRevocationList * HDMITX_KSV_BYTES_PER_DEVICE)])
                    )
                {
                    *pbBksvSecure = False;
                }
            }
            else
            {
                if ((pHdcpBksvTested[4] == unitTableTx[instance].revocationList.pList[NbInRevocationList * HDMITX_KSV_BYTES_PER_DEVICE])
                    &&
                    (pHdcpBksvTested[3] == unitTableTx[instance].revocationList.pList[1 + (NbInRevocationList * HDMITX_KSV_BYTES_PER_DEVICE)])
                    &&
                    (pHdcpBksvTested[2] == unitTableTx[instance].revocationList.pList[2 + (NbInRevocationList * HDMITX_KSV_BYTES_PER_DEVICE)])
                    &&
                    (pHdcpBksvTested[1] == unitTableTx[instance].revocationList.pList[3 + (NbInRevocationList * HDMITX_KSV_BYTES_PER_DEVICE)])
                    &&
                    (pHdcpBksvTested[0] == unitTableTx[instance].revocationList.pList[4 + (NbInRevocationList * HDMITX_KSV_BYTES_PER_DEVICE)])
                    )
                {
                    *pbBksvSecure = False;
                }
            }
            NbInRevocationList++;
        }

    }


}
#endif

/******************************************************************************
    \brief dlHdmiTxCalcVidFmtIndex.

    \param vidFmt  video format.

    \return table index.

******************************************************************************/
static tmdlHdmiTxVidFmt_t dlHdmiTxCalcVidFmtIndex(tmdlHdmiTxVidFmt_t vidFmt)
{
    tmdlHdmiTxVidFmt_t vidFmtIndex = vidFmt;
    
    /* Hanlde VIC or table index discontinuity */
    if((vidFmt >= TMDL_HDMITX_VFMT_60_1280x720p_24Hz) && (vidFmt <= TMDL_HDMITX_VFMT_62_1280x720p_30Hz))
    {
        vidFmtIndex = (tmdlHdmiTxVidFmt_t)(TMDL_HDMITX_VFMT_INDEX_60_1280x720p_24Hz + (vidFmt - TMDL_HDMITX_VFMT_60_1280x720p_24Hz));
    }
#ifdef FORMAT_PC
    else if (vidFmt >= TMDL_HDMITX_VFMT_PC_MIN)
    {
        vidFmtIndex = (tmdlHdmiTxVidFmt_t)(TMDL_HDMITX_VFMT_TV_NUM + (vidFmt - TMDL_HDMITX_VFMT_PC_MIN));
    }
#endif /* FORMAT_PC */
    return(vidFmtIndex);
}


tmErrorCode_t tmdlHdmiTxDebugEnableI2CAccesses ( tmInstance_t instance,
                                                 Bool         enableI2C)
{
    tmErrorCode_t   errCode = TM_OK;

    /* Check if instance number is in range */
    if( (instance < 0) || (instance >= MAX_UNITS) ) 
    {
        errCode = TMDL_ERR_DLHDMITX_BAD_INSTANCE;
        return errCode;
    }

    if (enableI2C == True)
    {
        errCode = tmbslDebugWriteFakeRegPage(instance);
        gI2CDebugAccessesEnabled = True;
    } 
    else
    {
        gI2CDebugAccessesEnabled = False;
    }


    return errCode;

} /* tmdlHdmiTxDebugManageI2CAccesses */

/*****************************************************************************/
/**
    \brief Retreives current HDCP link status. This function is typically used
           when an "HDCP INACTIVE" event is received to know why HDCP 
           is INACTIVE.

    \param instance    Instance identifier.
    \param pHdcpStatus Pointer to the enum describing the status.
    \param pRawStatus  Pointer to the byte with the raw error code from HW.

    \return The call result:
            - TM_OK: the call was successful
            - TMDL_ERR_DLHDMITX_BAD_INSTANCE: the instance number is wrong or
              out of range
            - TMDL_ERR_DLHDMITX_BAD_HANDLE: the handle number is wrong
            - TMDL_ERR_DLHDMITX_BAD_PARAMETER: a parameter is invalid or out
              of range
            - TMDL_ERR_DLHDMITX_NOT_INITIALIZED: the transmitter is not initialized

******************************************************************************/
tmErrorCode_t tmdlHdmiTxGetHdcpFailStatus
(
    tmInstance_t            instance,
    tmdlHdmiTxHdcpStatus_t *pHdcpStatus,
    UInt8                  *pRawStatus
)
{
    tmErrorCode_t   errCode = TM_OK;

#ifndef NO_HDCP
    RETIF((instance < 0) || (instance >= MAX_UNITS), TMDL_ERR_DLHDMITX_BAD_INSTANCE)
    RETIF(pHdcpStatus == Null, TMDL_ERR_DLHDMITX_INCONSISTENT_PARAMS)
    RETIF(pRawStatus == Null, TMDL_ERR_DLHDMITX_INCONSISTENT_PARAMS)

    /* Take the sempahore */
    RETIF( (errCode = tmdlHdmiTxIWSemaphoreP(dlHdmiTxItSemaphore[instance]) ) != TM_OK, errCode)

    *pRawStatus  = hdcpInfoListTx[instance].hdcpErrorState;

    switch (hdcpInfoListTx[instance].hdcpErrorState) 
    {

    case 0:
        *pHdcpStatus = TMDL_HDMITX_HDCP_OK;
        break;

    case 0x02:
    case 0x03:
    case 0x04:
    case 0x05:
    case 0x06:
        *pHdcpStatus = TMDL_HDMITX_HDCP_BKSV_RCV_FAIL;
        break;

    case 0x08:
        *pHdcpStatus = TMDL_HDMITX_HDCP_BKSV_CHECK_FAIL;
        break;

    case 0x0C:
        *pHdcpStatus = TMDL_HDMITX_HDCP_BCAPS_RCV_FAIL;
        break;

    case 0x0F:
    case 0x10:
    case 0x11:
        *pHdcpStatus = TMDL_HDMITX_HDCP_AKSV_SEND_FAIL;
        break;

    case 0x23:
    case 0x24:
    case 0x25:
        *pHdcpStatus = TMDL_HDMITX_HDCP_R0_RCV_FAIL;
        break;

    case 0x26:
        *pHdcpStatus = TMDL_HDMITX_HDCP_R0_CHECK_FAIL;
        break;

    case 0x27:
        *pHdcpStatus = TMDL_HDMITX_HDCP_BKSV_NOT_SECURE;
        break;

    case 0x2B:
    case 0x2C:
    case 0x2D:
        *pHdcpStatus = TMDL_HDMITX_HDCP_RI_RCV_FAIL;
        break;

    case 0x77:
    case 0x78:
    case 0x79:
        *pHdcpStatus = TMDL_HDMITX_HDCP_RPT_RI_RCV_FAIL;
        break;

    case 0x2E:
        *pHdcpStatus = TMDL_HDMITX_HDCP_RI_CHECK_FAIL;
    break;

    case 0x7A:
        *pHdcpStatus = TMDL_HDMITX_HDCP_RPT_RI_CHECK_FAIL;
        break;

    case 0x66:
        *pHdcpStatus = TMDL_HDMITX_HDCP_RPT_BCAPS_RCV_FAIL;
        break;

    case 0x67:
        *pHdcpStatus = TMDL_HDMITX_HDCP_RPT_BCAPS_READY_TIMEOUT;
        break;

    case 0x6A:
        *pHdcpStatus = TMDL_HDMITX_HDCP_RPT_V_RCV_FAIL;
        break;

    case 0x6C:
    case 0x6D:
        *pHdcpStatus = TMDL_HDMITX_HDCP_RPT_BSTATUS_RCV_FAIL;
        break;

    case 0x6F:
        *pHdcpStatus = TMDL_HDMITX_HDCP_RPT_KSVLIST_RCV_FAIL;
        break;

    case 0x74:
        *pHdcpStatus = TMDL_HDMITX_HDCP_RPT_KSVLIST_NOT_SECURE;
        break;

    default:
        *pHdcpStatus = TMDL_HDMITX_HDCP_UNKNOWN_STATUS;
        break;
    }

    /* Release the sempahore */
    RETIF( (errCode = tmdlHdmiTxIWSemaphoreV(dlHdmiTxItSemaphore[instance]) ) != TM_OK, errCode)

#else
       (void)instance; /* Remove compiler warning */
#endif /* NO_HDCP */

    return errCode;
}


tmErrorCode_t tmdlHdmiTxGetEdidLatencyInfo
(
    tmInstance_t                instance,
    tmdlHdmiTxEdidLatency_t    *pLatency
)
{
    tmErrorCode_t   errCode;

    /* Check if instance number is in range */
    RETIF((instance < 0) || (instance >= MAX_UNITS), TMDL_ERR_DLHDMITX_BAD_INSTANCE)

    /* Check pointer is Null */
    RETIF( pLatency == Null, TMDL_ERR_DLHDMITX_INCONSISTENT_PARAMS)

    /* Take the sempahore */
    RETIF( (errCode = tmdlHdmiTxIWSemaphoreP(dlHdmiTxItSemaphore[instance]) ) != TM_OK, errCode)

    /* Check the current state */   
    RETIF_SEM(dlHdmiTxItSemaphore[instance], 
        dlHdmiTxGetState(instance) != STATE_EDID_AVAILABLE, TMDL_ERR_DLHDMITX_INVALID_STATE)

    RETIF_SEM(dlHdmiTxItSemaphore[instance], 
        (errCode = tmbslHdmiTxEdidGetLatencyInfo(instance, (tmbslHdmiTxEdidLatency_t *) pLatency) ) != TM_OK, errCode)

    /* Release the sempahore */
    RETIF( (errCode = tmdlHdmiTxIWSemaphoreV(dlHdmiTxItSemaphore[instance]) ) != TM_OK, errCode)

    return TM_OK;
} /* tmdlHdmiTxGetEdidLatencyInfo */

/******************************************************************************
    \brief Retrieves additional data from receiver's EDID VSDB. This function 
           parses the EDID of Rx device to get the relevant data.
           This function is synchronous.
           This function is not ISR friendly.

    \param instance             Instance identifier.
    \param pExtraVsdbData       Pointer to the structure of additional VSDB data 
    
    \return The call result:
            - TM_OK: the call was successful
            - TMDL_ERR_DLHDMITX_BAD_INSTANCE: the instance number is wrong or
              out of range
            - TMDL_ERR_DLHDMITX_INCONSISTENT_PARAMS: an input parameter is
              inconsistent
            - TMDL_ERR_DLHDMITX_INVALID_STATE: the state is invalid for
              the function
            - TMBSL_ERR_HDMI_BAD_PARAMETER: a parameter was out of range
            - TMBSL_ERR_HDMI_BAD_UNIT_NUMBER: bad transmitter unit number
            - TMBSL_ERR_HDMI_RESOURCE_NOT_AVAILABLE : EDID not read
            - TMBSL_ERR_HDMI_NOT_INITIALIZED: transmitter not initialized

******************************************************************************/
tmErrorCode_t tmdlHdmiTxGetEdidExtraVsdbData
(
    tmInstance_t                     instance,
    tmdlHdmiTxEdidExtraVsdbData_t    **pExtraVsdbData
)
{
    tmErrorCode_t   errCode;

    /* Check if instance number is in range */
    RETIF((instance < 0) || (instance >= MAX_UNITS), TMDL_ERR_DLHDMITX_BAD_INSTANCE)

    /* Check pointer is Null */
    RETIF(pExtraVsdbData == Null, TMDL_ERR_DLHDMITX_INCONSISTENT_PARAMS)

    /* Take the sempahore */
    RETIF( (errCode = tmdlHdmiTxIWSemaphoreP(dlHdmiTxItSemaphore[instance]) ) != TM_OK, errCode)

    /* Check the current state */   
    RETIF_SEM(dlHdmiTxItSemaphore[instance], 
        dlHdmiTxGetState(instance) != STATE_EDID_AVAILABLE, TMDL_ERR_DLHDMITX_INVALID_STATE)

    RETIF_SEM(dlHdmiTxItSemaphore[instance], 
        (errCode = tmbslHdmiTxEdidGetExtraVsdbData(instance, (tmbslHdmiTxEdidExtraVsdbData_t **)pExtraVsdbData) ) != TM_OK, errCode)

    /* Release the sempahore */
    RETIF( (errCode = tmdlHdmiTxIWSemaphoreV(dlHdmiTxItSemaphore[instance]) ) != TM_OK, errCode)

    return TM_OK;
} /* tmdlHdmiTxGetEdidExtraVsdbData */


tmErrorCode_t tmdlHdmiTxGetHPDStatus
(
    tmInstance_t            instance,
    tmdlHdmiTxHotPlug_t *   pHPDStatus
)
{
    tmErrorCode_t   errCode;

    /* Check if instance number is in range */
    RETIF((instance < 0) || (instance >= MAX_UNITS), TMDL_ERR_DLHDMITX_BAD_INSTANCE)

    RETIF( pHPDStatus== Null, TMDL_ERR_DLHDMITX_INCONSISTENT_PARAMS)


    /* Take the sempahore */
    RETIF( (errCode = tmdlHdmiTxIWSemaphoreP(dlHdmiTxItSemaphore[instance]) ) != TM_OK, errCode)

    /* Get the HPD status from BSL driver */
        errCode = tmbslHdmiTxHotPlugGetStatus(instance,(tmbslHdmiTxHotPlug_t *)pHPDStatus,True);

    if (errCode == TM_OK) {
        /* do nothing */
    }
    else {
        *pHPDStatus = TMDL_HDMITX_HOTPLUG_INVALID;
    }

    /* Release the sempahore */
    RETIF( (errCode = tmdlHdmiTxIWSemaphoreV(dlHdmiTxItSemaphore[instance]) ) != TM_OK, errCode)

    return TM_OK;

} /* tmdlHdmiTxGetHPDStatus */



tmErrorCode_t tmdlHdmiTxGetRXSenseStatus
(
    tmInstance_t            instance,
    tmdlHdmiTxRxSense_t *   pRXSenseStatus
)
{
    tmErrorCode_t   errCode;

    /* Check if instance number is in range */
    RETIF((instance < 0) || (instance >= MAX_UNITS), TMDL_ERR_DLHDMITX_BAD_INSTANCE)

    RETIF( pRXSenseStatus== Null, TMDL_ERR_DLHDMITX_INCONSISTENT_PARAMS)


    /* Take the sempahore */
    RETIF( (errCode = tmdlHdmiTxIWSemaphoreP(dlHdmiTxItSemaphore[instance]) ) != TM_OK, errCode)

    /* Get the RXS sense status from BSL driver */
        errCode = tmbslHdmiTxRxSenseGetStatus(instance,( tmbslHdmiTxRxSense_t*)pRXSenseStatus,True);

    if (errCode == TM_OK) {
        /* do nothing */
    }
    else {
        *pRXSenseStatus = TMDL_HDMITX_RX_SENSE_INVALID;
    }

    /* Release the sempahore */
    RETIF( (errCode = tmdlHdmiTxIWSemaphoreV(dlHdmiTxItSemaphore[instance]) ) != TM_OK, errCode)

    return TM_OK;

} /* tmdlHdmiTxGetRXSenseStatus */


/******************************************************************************
    \brief Mute or unmute the TMDS outputs.

    \param instance         Instance identifier.
    \param muteTmdsOut      Mute or unmute indication.

    \return NA.
    
******************************************************************************/   
tmErrorCode_t tmdlHdmiTxTmdsSetOutputsMute
(
    tmInstance_t            instance,
    Bool                    muteTmdsOut
)
{
    tmErrorCode_t           errCode;
    tmErrorCode_t           errCodeSem;
    tmbslHdmiTxTmdsOut_t    tmdsOut;
    
    RETIF((instance < 0) || (instance >= MAX_UNITS), TMDL_ERR_DLHDMITX_BAD_INSTANCE)

    if (muteTmdsOut)
        tmdsOut = HDMITX_TMDSOUT_FORCED0;       // forced 0 outputs
    else
        tmdsOut = HDMITX_TMDSOUT_NORMAL;        // normal outputs

    /* Take the sempahore */
    RETIF( (errCodeSem = tmdlHdmiTxIWSemaphoreP(dlHdmiTxItSemaphore[instance]) ) != TM_OK, errCodeSem)

    errCode = tmbslHdmiTxTmdsSetOutputs (instance, tmdsOut);

    /* Release the sempahore */
    RETIF( (errCodeSem = tmdlHdmiTxIWSemaphoreV(dlHdmiTxItSemaphore[instance]) ) != TM_OK, errCodeSem)


    return errCode;
}

/*============================================================================*/
/*                            END OF FILE                                     */
/*============================================================================*/
