/*****************************************************************************/
/* Copyright (c) 2009 NXP B.V.                                               */
/*                                                                           */
/* This library is free software; you can redistribute it and/or             */
/* modify it under the terms of the GNU Lesser General Public                */
/* License as published by the Free Software Foundation, using               */
/* version 2.1 of the License.                                               */
/*                                                                           */
/* This library 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          */
/* Lesser General Public License for more details.                           */
/*                                                                           */
/* You should have received a copy of the GNU Lesser General Public          */
/* License along with this library; if not, write to the Free Software       */
/* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA   */
/*                                                                           */
/*****************************************************************************/
/**
    @file   phStbDFB_Utils.c
    @brief  Utility functions for DirectFB.

@b  Component:  phStbDFB.

*//*

Rev Date        Author      Comments
--------------------------------------------------------------------------------
  1 20050920    laird    First implementation.
  2 20051005    laird    Added a sleep of 1 second before updating PNX8510
  3 20051103    laird    Better error handling
  4 20060327    neill    Remove the delay before updating PNX8510
  5 20060621    laird    Use new Video denc api so no need for util functions.
  6 20060630    laird    XCheck rework.
  7 20060704    laird    Adding more support for encoders.
  8 20060714    laird    support for video denc control of connectors.
  9 20060726    laird    Adding support for mode database and more debug.
 10 20060726    laird    XCheck rework.
 11 20060726    neill    Change SCART switch to AK470X
-------------------------STB225-------------------------------------------------
 11 20070112    laird    Moving to STB225.
 12 10070116    laird    Crosscheck Rework.
 13 20070702    neill    Add power mode control
 14 20070723    neill    Add gamma correction adjustment
 15 20071017    burningh Fix QA C coverage errors
 16 20071029    burningh Improve QA C confidence factor
 17 20081022    legendrd Add UDA3000
 18 20090120    batelaan Update file copyright/license text
--------------------------------------------------------------------------------
   For consistency and standardisation retain the Section Separators.
*/

/***********************************************
* INCLUDE FILES                                *
************************************************/
#include <phStbDFB_Local.h>

/***********************************************
* LOCAL MACROS                                 *
* recommendation only: <MODULE><_WORD>+        *
************************************************/

/******************************************************************
* LOCAL TYPEDEFS                                                  *
* recommendation only:                [p]phStbTemplate_<Word>+_t  *
*******************************************************************/

/******************************************************************
* STATIC FUNCTION PROTOTYPES                  <Module>_<Word>+    *
*******************************************************************/
static phStbDFB_VdencMap_t* findFreeVdenc(phStbDFB_ScreenData_t *screen_data);

static phStbDFB_VdencMap_t* findVdenc(phStbDFB_ScreenData_t *screen_data,
                                      int renderer,
                                      int encoder);

/******************************************************************
* STATIC DATA                  g[k|p|kp|pk|kpk]<Module>_<Word>+   *
*******************************************************************/

#ifdef CONFIG_SCART_AK470X
/**
 * @brief Device name to control the AK470X.
 */
static const char *pAvSwitchDevName = "/dev/ak470x";
#elif CONFIG_SCART_UDA3000
/**
 * @brief Device name to control the UDA3000.
 */
static const char *pAvSwitchDevName = "/dev/uda3000";
#endif


/**************************************************************************
* EXPORTED DATA                     g[k|p|kp|pk|kpk]phStbTemplate_<Word>+ *
***************************************************************************/

/*******************************************************************************
* FUNCTION IMPLEMENTATION  <Module>[_<Word>+] for static functions             *
*                          tm[<screen>]<Module>[_<Word>+] for exported functions*
********************************************************************************/
/**
 * Find a empty structure.
 *
 * @return phStbDFB_VdencMap_t if empty one found or NULL if full.
 */
static phStbDFB_VdencMap_t* findFreeVdenc(phStbDFB_ScreenData_t *screen_data)
{
    unsigned int i = 0;
    for(i = 0; i < PH_STBDFB_MAX_ENCODERS_RENDERER; i++)
    {
        if(screen_data->vdencMapping[i].inUse == false)
        {
            return &screen_data->vdencMapping[i];
        }
    }
    return NULL;
}

/**
 * Find a structure that is inuse and matches the renderer and encoder.
 *
 *  @param renderer IN the renderer number to match against.
 *  @param encoder  IN the encoder number to match against.
 *
 *  @return phStbDFB_VdencMap_t if matched or NULL.
 */
static phStbDFB_VdencMap_t* findVdenc(phStbDFB_ScreenData_t *screen_data,
                                      int renderer,
                                      int encoder)
{
    unsigned int i = 0;

    for(i = 0; i < PH_STBDFB_MAX_ENCODERS_RENDERER; i++)
    {
        if(screen_data->vdencMapping[i].renderer == renderer &&
           screen_data->vdencMapping[i].encoder == encoder &&
           screen_data->vdencMapping[i].inUse == true)
        {
            return &screen_data->vdencMapping[i];
        }
    }
    return NULL;
}

/******************************************************************************/
extern int StbDFB_GetNumberVideoDencs(int rendererNum)
{
    char vdencName[32];
    int tmpVdenc;
    unsigned int numEncoders = 0;
    int i;

    DBG_PRINT1(gphStbDFB_DbgUnit, DBG_INTERNAL_ENTER, "%s", __FUNCTION__);

    for(i = 0; i < VIDEODENC_MAX; i++)
    {
        sprintf(vdencName, "/dev/vdenc/renderer%d/vdenc%d", rendererNum, i);
        if ((tmpVdenc = open(vdencName, O_RDWR)) < 0)
        {
            /*As vdencs should be sequential break out of loop*/
            break;
        }
        else
        {
            numEncoders++;
            close(tmpVdenc);
        }
    }
    if(numEncoders > PH_STBDFB_MAX_ENCODERS_RENDERER)
    {
        D_WARN("You have more than %d Video Dencs on Renderer %d this is not supported\n", PH_STBDFB_MAX_ENCODERS_RENDERER, rendererNum);
    }

    DBG_PRINT((gphStbDFB_DbgUnit, DBG_INTERNAL_LEAVE, "%s: Num of Encoders found %d", __FUNCTION__, numEncoders));
    return (int)numEncoders;
}

/******************************************************************************/
extern DFBResult StbDFB_InitVideoDenc(phStbDFB_ScreenData_t *screen_data,
                                      int encoder,
                                      DFBScreenEncoderDescription *pEncDesc)
{
    char vdencName[32];
    int tmpVdenc;
    DFBResult result = DFB_ITEMNOTFOUND;
    int localError;
    int conIndex;
    unsigned int numModes;
    struct videodenc_fix_screeninfo fixInfo;
    phStbDFB_VdencMap_t* vdenc;

    DBG_PRINT1(gphStbDFB_DbgUnit, DBG_INTERNAL_ENTER, "%s", __FUNCTION__);
    sprintf(vdencName, "/dev/vdenc/renderer%d/vdenc%d", screen_data->unitId, encoder);

    if (( tmpVdenc = open(vdencName, O_RDWR)) < 0)
    {
        D_INFO("Failed to open device %s\n", vdencName);
    }
    else
    {
        /*We have found a valid device now we need to get the settings and compare name*/
        /*Write the settings to the board*/
        if ((localError = ioctl(tmpVdenc, VIDEODENC_IOGET_FSCREENINFO, &fixInfo)) < 0)
        {
            close(tmpVdenc);
            D_WARN("ERROR: sending vdenc command %s (%d)\n", strerror(errno), localError);
            result = DFB_FAILURE;
            goto RETURN;
        }
        else
        {
            /*Find empty Entry*/
            vdenc = findFreeVdenc(screen_data);

            /*Copy the name into the description.*/
            strcpy(pEncDesc->name, fixInfo.id);

            /*Copy in the connectors we support.*/
            for(conIndex =0; conIndex < VIDEODENC_CONNECTORS_MAX; conIndex++)
            {
                if(fixInfo.all_connectors->in_use)
                {
                    int supportedConnector = CONVERT_TO_DFB_OUTPUT_CONNECTOR(fixInfo.all_connectors[conIndex].type,
                                                                             fixInfo.all_connectors[conIndex].connector_id);
                    pEncDesc->all_connectors |= supportedConnector;
                }
            }

            if(fixInfo.sout_signals & VIDEODENC_OUTSIGNAL_CVBS)
            {
                pEncDesc->out_signals |= DSOS_CVBS;
            }
            if(fixInfo.sout_signals & VIDEODENC_OUTSIGNAL_YC)
            {
                pEncDesc->out_signals |= DSOS_YC;
            }
            if(fixInfo.sout_signals & VIDEODENC_OUTSIGNAL_YPRPB)
            {
                pEncDesc->out_signals |= DSOS_YCBCR;
            }
            if(fixInfo.sout_signals & VIDEODENC_OUTSIGNAL_RGB)
            {
                pEncDesc->out_signals |= DSOS_RGB;
                if(pEncDesc->all_connectors & DSOC_VGA)
                {
                    pEncDesc->out_signals |= DSOS_VGA;
                }
            }
            if(fixInfo.sout_signals & VIDEODENC_OUTSIGNAL_DIGITAL)
            {
                pEncDesc->out_signals |= DSOS_HDMI;
            }

            /*Store values*/
            vdenc->encoder = encoder;
            vdenc->renderer = screen_data->unitId;
            vdenc->inUse = true;
            strcpy(vdenc->devName, vdencName);

            /* Now get the number of modes and then increment through them.*/
            if ((localError = ioctl(tmpVdenc, VIDEODENC_IOGET_NUM_MODES, &numModes)) < 0)
            {
                close(tmpVdenc);
                D_WARN("ERROR: sending vdenc command %s (%d)\n", strerror(errno), localError);
                result = DFB_FAILURE;
                goto RETURN;
            }
            else
            {
                char *buffer;
                struct videodenc_videomode *curVidMode;
                int modeIndex;

                buffer = malloc(numModes * sizeof(struct videodenc_videomode));
                curVidMode = (struct videodenc_videomode *)buffer;

                if ((localError = ioctl(tmpVdenc, VIDEODENC_IOGET_MODES, buffer)) < 0)
                {
                    close(tmpVdenc);
                    free(buffer);
                    D_WARN("ERROR: sending vdenc command %s (%d)\n", strerror(errno), localError);
                    result = DFB_FAILURE;
                    goto RETURN;
                }
                for(modeIndex = 0; modeIndex < numModes; modeIndex++)
                {
                    pEncDesc->tv_standards |= CONVERT_TO_DFB_TVSTANDARD(curVidMode->tv_standard);
                    pEncDesc->all_resolutions |= CONVERT_TO_DFB_OUTPUT_RESOLUTION(curVidMode->xres, curVidMode->yres);
                    curVidMode++;
                }
                free(buffer);
                result = DFB_OK;
            }
        }
    }
    /*If no errors then close the device*/
    if(result == DFB_OK)
    {
        close(tmpVdenc);
    }
RETURN:
    DBG_PRINT1(gphStbDFB_DbgUnit, DBG_INTERNAL_LEAVE, "%s", __FUNCTION__);

    return result;
}

#ifdef CONFIG_SCART_AK470X

/******************************************************************************/
extern bool StbDFB_AK470XInstalled(void)
{
    bool result = false;
    int fdScart;

    DBG_PRINT1(gphStbDFB_DbgUnit, DBG_INTERNAL_ENTER, "%s", __FUNCTION__);

    /*Only open if this setting is supported*/
    if ((fdScart = open(pAvSwitchDevName, O_RDWR)) < 0)
    {
        result = false;
    }
    else
    {
        /*Close the file descriptor*/
        close(fdScart);
        result = true;
    }

    DBG_PRINT((gphStbDFB_DbgUnit, DBG_INTERNAL_LEAVE, "%s: => 0x%x", __FUNCTION__, result));
    return result;
}

/******************************************************************************/
extern DFBResult StbDFB_SetupAK470X(av_switch_data *pAvSwitchSettings)
{
    DFBResult result = DFB_OK;
    int fdScart;
    int localError;

    DBG_PRINT1(gphStbDFB_DbgUnit, DBG_INTERNAL_ENTER, "%s", __FUNCTION__);

    /*Only oepn if this setting is supported*/
    if ((fdScart = open(pAvSwitchDevName, O_RDWR)) < 0)
    {
        D_WARN("ERROR: opening %s\n", pAvSwitchDevName);
        result = DFB_FAILURE;
        goto RETURN;
    }

    /*Write the settings to the board*/
    if ((localError = ioctl(fdScart, AK470X_IOCTL_SWITCH_MODE_SET, pAvSwitchSettings)) < 0)
    {
        close(fdScart);
        D_WARN("ERROR: sending ak470x command %s (%d)\n", strerror(errno), localError);
        result = DFB_FAILURE;
        goto RETURN;
    }

    /*Close the file descriptor*/
    close(fdScart);

RETURN:
    DBG_PRINT((gphStbDFB_DbgUnit, DBG_INTERNAL_LEAVE, "%s:  => 0x%x", __FUNCTION__, result));
    return result;
}


/******************************************************************************/
extern DFBResult StbDFB_GetSetupAK470X(av_switch_data *pAvSwitchSettings)
{
    DFBResult result = DFB_OK;
    int fdScart;
    int localError;

    DBG_PRINT1(gphStbDFB_DbgUnit, DBG_INTERNAL_ENTER, "%s", __FUNCTION__);

    /*Only oepn if this setting is supported*/
    if ((fdScart = open(pAvSwitchDevName, O_RDWR)) < 0)
    {
        D_WARN("ERROR: opening %s\n", pAvSwitchDevName);
        result = DFB_FAILURE;
        goto RETURN;
    }

    if ((localError = ioctl(fdScart, AK470X_IOCTL_SWITCH_MODE_GET, pAvSwitchSettings)) < 0)
    {
        close(fdScart);
        D_WARN("ERROR: sending ak470x command %s (%d)\n", strerror(errno), localError);
        result = DFB_FAILURE;
        goto RETURN;
    }

    /*Close the file descriptor*/
    close(fdScart);

RETURN:
    DBG_PRINT((gphStbDFB_DbgUnit, DBG_INTERNAL_LEAVE, "%s: => 0x%x", __FUNCTION__, result));
    return result;
}

#elif CONFIG_SCART_UDA3000

/******************************************************************************/
bool StbDFB_UDA3000Installed(void)
{
    bool result = false;
    int fdScart;

    DBG_PRINT1(gphStbDFB_DbgUnit, DBG_INTERNAL_ENTER, "%s", __FUNCTION__);

    /*Only open if this setting is supported*/
    if ((fdScart = open(pAvSwitchDevName, O_RDWR)) < 0)
    {
        result = false;
    }
    else
    {
        /*Close the file descriptor*/
        close(fdScart);
        result = true;
    }

    DBG_PRINT((gphStbDFB_DbgUnit, DBG_INTERNAL_LEAVE, "%s: => 0x%x", __FUNCTION__, result));
    return result;
}

/******************************************************************************/
DFBResult StbDFB_SetupUDA3000(phStbScartSwitchScartId_t  kScartNumber,
                                                     phStbScartSwitchSBMode_t kMode, 
                                                     phStbScartSwitchSBValue_t kValue)
{
    DFBResult result = DFB_OK;
    int fdScart;
    int localError;
    phStbScartSwitchSetSBModeData_t SBMode;
    phStbScartSwitchSetSBValueData_t SBValue;

    DBG_PRINT1(gphStbDFB_DbgUnit, DBG_INTERNAL_ENTER, "%s", __FUNCTION__);

    /*Only open if this setting is supported*/
    if ((fdScart = open(pAvSwitchDevName, O_RDWR)) < 0)
    {
        D_WARN("ERROR: opening %s\n", pAvSwitchDevName);
        result = DFB_FAILURE;
        goto RETURN;
    }

    /* Initialize the values */
    SBMode.kScartNumber = kScartNumber;
    SBMode.kMode = kMode;
    SBValue.kScartNumber = kScartNumber;
    SBValue.kValue = kValue;
    
    /*Write the settings to the board*/
    if ((localError = ioctl(fdScart, phStbScartSwitch_SET_SB_MODE, &SBMode)) < 0)
    {
        close(fdScart);
        D_WARN("ERROR: sending uda3000 command phStbScartSwitch_SET_SB_MODE %s (%d)\n", strerror(errno), localError);
        result = DFB_FAILURE;
        goto RETURN;
    }
    
    if ((localError = ioctl(fdScart, phStbScartSwitch_SET_SB_VALUE, &SBValue)) < 0)
    {
        close(fdScart);
        D_WARN("ERROR: sending uda3000 command phStbScartSwitch_SET_SB_VALUE %s (%d)\n", strerror(errno), localError);
        result = DFB_FAILURE;
        goto RETURN;
    }

    /*Close the file descriptor*/
    close(fdScart);

RETURN:
    DBG_PRINT((gphStbDFB_DbgUnit, DBG_INTERNAL_LEAVE, "%s:  => 0x%x", __FUNCTION__, result));
    return result;
}


/******************************************************************************/
DFBResult StbDFB_GetSetupUDA3000(phStbScartSwitchScartId_t   kScartNumber,
                                                          phStbScartSwitchSBValue_t *pValue)
{
    DFBResult result = DFB_OK;
    int fdScart;
    int localError;
    phStbScartSwitchGetSBValueData_t SBValue;

    DBG_PRINT1(gphStbDFB_DbgUnit, DBG_INTERNAL_ENTER, "%s", __FUNCTION__);

    /*Only oepn if this setting is supported*/
    if ((fdScart = open(pAvSwitchDevName, O_RDWR)) < 0)
    {
        D_WARN("ERROR: opening %s\n", pAvSwitchDevName);
        result = DFB_FAILURE;
        goto RETURN;
    }
    
    /* Initialize scart number */
    SBValue.kScartNumber = kScartNumber;

    if ((localError = ioctl(fdScart, phStbScartSwitch_GET_SB_VALUE, &SBValue)) < 0)
    {
        close(fdScart);
        D_WARN("ERROR: sending uda3000 command phStbScartSwitch_GET_SB_VALUE %s (%d)\n", strerror(errno), localError);
        result = DFB_FAILURE;
        goto RETURN;
    }
    
    /* Get the SB value */
    *pValue = SBValue.kValue;

    /*Close the file descriptor*/
    close(fdScart);

RETURN:
    DBG_PRINT((gphStbDFB_DbgUnit, DBG_INTERNAL_LEAVE, "%s: => 0x%x", __FUNCTION__, result));
    return result;
}

#endif

/******************************************************************************/
extern DFBResult StbDFB_SetupDenc(phStbDFB_ScreenData_t *screen_data,
                                  int encoder,
                                  struct videodenc_var_screeninfo *pDencSettings)
{
    DFBResult result = DFB_OK;
    int localError;
    phStbDFB_VdencMap_t *vdenc;
    int fd;

    DBG_PRINT((gphStbDFB_DbgUnit, DBG_INTERNAL_ENTER,
               "%s: xres=>%d: yres=>%d: scantype=>0x%08x: tv_standard=>0x%08x: out_signal=>0x%08x: refresh=>0x%08x\n",
               __FUNCTION__,
               pDencSettings->xres,
               pDencSettings->yres,
               pDencSettings->scantype,
               pDencSettings->tv_standard,
               pDencSettings->output_signal,
               pDencSettings->refresh));

    vdenc = findVdenc(screen_data, screen_data->unitId, encoder);
    if(vdenc == NULL)
    {
        D_WARN("ERROR: Specified Video denc not found (renderer %d, encoder %d)\n", screen_data->unitId, encoder);
        result = DFB_ITEMNOTFOUND;
        goto RETURN;
    }
    /* Now open the device */
    if (( fd = open(vdenc->devName, O_RDWR)) < 0)
    {
        D_WARN("Failed to open device - error %s\n", strerror(errno), vdenc->devName);
        result = DFB_FILENOTFOUND;
        goto RETURN;
    }

    if ((localError = ioctl(fd,
                            VIDEODENC_IOSET_MODE,
                            pDencSettings)) < 0)
    {
        D_WARN("ERROR: Invalid Video Denc command %s (%d)\n", strerror(errno), localError);
        result = DFB_FAILURE;
        goto RETURN;
    }
    /* Now close the device */
    close(fd);

RETURN:
    DBG_PRINT((gphStbDFB_DbgUnit, DBG_INTERNAL_LEAVE, "%s: => 0x%x", __FUNCTION__, result));
    return result;
}

/******************************************************************************/
extern DFBResult StbDFB_GetDencSetup(phStbDFB_ScreenData_t *screen_data,
                                     int encoder,
                                     struct videodenc_var_screeninfo *pDencSettings)
{
    DFBResult result = DFB_OK;
    int localError;
    phStbDFB_VdencMap_t *vdenc;
    int fd;

    DBG_PRINT1(gphStbDFB_DbgUnit, DBG_INTERNAL_ENTER, "%s", __FUNCTION__);

    vdenc = findVdenc(screen_data, screen_data->unitId, encoder);
    if (vdenc == NULL)
    {
        D_WARN("ERROR: Specified Video denc not found (renderer %d, encoder %d)\n", screen_data->unitId, encoder);
        result = DFB_ITEMNOTFOUND;
        goto RETURN;
    }
    /* Now open the device */
    if (( fd = open(vdenc->devName, O_RDWR)) < 0)
    {
        D_WARN("Failed to open device - error %s\n", strerror(errno), vdenc->devName);
        result = DFB_FILENOTFOUND;
        goto RETURN;
    }

    /*Write the settings to the board*/
    if ((localError = ioctl(fd,
                            VIDEODENC_IOGET_VSCREENINFO,
                            pDencSettings)) < 0)
    {
        D_WARN("ERROR: sending Video Denc command %s (%d)\n", strerror(errno), localError);
        result = DFB_FAILURE;
        goto RETURN;
    }
    /* Now close the device */
    close(fd);

    DBG_PRINT((gphStbDFB_DbgUnit, DBG_INTERNAL_ENTER,
               "%s: xres=>%d: yres=>%d: scantype=>0x%08x: tv_standard=>0x%08x: out_signal=>0x%08x: refresh=>0x%08x\n",
               __FUNCTION__,
               pDencSettings->xres,
               pDencSettings->yres,
               pDencSettings->scantype,
               pDencSettings->tv_standard,
               pDencSettings->output_signal,
               pDencSettings->refresh));
RETURN:
    return result;
}

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

extern DFBResult StbDFB_SetPowerMode(
    CoreScreen             *screen,
    void                   *driver_data,
    void                   *screen_data,
    DFBScreenPowerMode      mode )
{
    DFBResult result = DFB_OK;
    phStbDFB_ScreenData_t *pScreenData = (phStbDFB_ScreenData_t*)screen_data;
    int num_encoders;
    int encoder;

    DBG_PRINT1(gphStbDFB_DbgUnit, DBG_INTERNAL_ENTER, "%s", __FUNCTION__);

    num_encoders = StbDFB_GetNumberVideoDencs(pScreenData->unitId);
    for(encoder = 0; encoder < num_encoders; encoder++)
    {
        int fd;
        int localError;
        phStbDFB_VdencMap_t *vdenc;
        vdenc = findVdenc(screen_data, pScreenData->unitId, encoder);

        if(vdenc == NULL)
        {
            D_WARN("ERROR: Specified Video denc not found (renderer %d, encoder %d)\n", pScreenData->unitId, encoder);
            result = DFB_ITEMNOTFOUND;
            goto RETURN;
        }
        /* Now open the device */
        if (( fd = open(vdenc->devName, O_RDWR)) < 0)
        {
            D_WARN("Failed to open device - error %s\n", strerror(errno), vdenc->devName);
            result = DFB_FILENOTFOUND;
            goto RETURN;
        }

        if ((localError = ioctl(fd, VIDEODENC_IOBLANK, mode == DSPM_ON ? False : True)) < 0)
        {
            D_WARN("ERROR: Invalid Video Denc command %s (%d)\n", strerror(errno), localError);
            result = DFB_FAILURE;
            goto RETURN;
        }
        /* Now close the device */
        close(fd);
    }

RETURN:
    DBG_PRINT((gphStbDFB_DbgUnit, DBG_INTERNAL_LEAVE, "%s: => 0x%x", __FUNCTION__, result));
    return result;
}
/******************************************************************************/
extern DFBResult StbDFB_SetupDencGamma(phStbDFB_ScreenData_t *screen_data,
                                       int encoder,
                                       unsigned int *pGammaValues)
{
    DFBResult result = DFB_OK;
    int localError;
    phStbDFB_VdencMap_t *vdenc;
    int fd;

    DBG_PRINT1(gphStbDFB_DbgUnit, DBG_INTERNAL_ENTER, "%s", __FUNCTION__);

    vdenc = findVdenc(screen_data, screen_data->unitId, encoder);
    if(vdenc == NULL)
    {
        D_WARN("ERROR: Specified Video denc not found (renderer %d, encoder %d)\n", screen_data->unitId, encoder);
        result = DFB_ITEMNOTFOUND;
        goto RETURN;
    }
    /* Now open the device */
    if (( fd = open(vdenc->devName, O_RDWR)) < 0)
    {
        D_WARN("Failed to open device - error %s\n", strerror(errno), vdenc->devName);
        result = DFB_FILENOTFOUND;
        goto RETURN;
    }

    if ((localError = ioctl(fd,
                            VIDEODENC_IOSET_GAMMA,
                            pGammaValues)) < 0)
    {
        D_WARN("ERROR: Invalid Video Denc command %s (%d)\n", strerror(errno), localError);
        result = DFB_FAILURE;
        goto RETURN;
    }
    /* Now close the device */
    close(fd);

RETURN:
    DBG_PRINT((gphStbDFB_DbgUnit, DBG_INTERNAL_LEAVE, "%s: => 0x%x", __FUNCTION__, result));
    return result;
}
