/*****************************************************************************/
/* 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_Screens.c
    @brief  Screen part of graphics driver for DirectFB.

@b  Component:  phStbDFB.

*//*

Rev Date        Author      Comments
--------------------------------------------------------------------------------
  1 20050711    batelaan    First implementation.
  2 20050713    batelaan    Crosscheck fixes
  3 20050714    laird       Added Screen Support.
  4 20050714    laird       XCheck rework.
  5 20050802    laird       Adding support for encoder.
  6 20050808    laird       XCheck rework
6.1.1 20050816  laird       Adding slow blanking support
6.1.2 20050816  laird       Adding ability to remember what the blanking settings are
6.1.3 20050817  laird       Oops.... Bit of a typo here
6.1.4 20050823  charrett    Clean up and add register function
  7 20050817    laird       Adding ability to change to NTSC
  8 20050822    laird       Merged 'phStbDFB_Screen.c=7' with 'phStbDFB_Screen.c=6.1.4'.
  9 20050830    laird       Xcheck rework.
 10 20050908    neill       Add second SCART and correct denc output settings
 11 20050913    laird       Add support for second screen.
 12 20050920    laird       Refactored
 13 20050920    laird       Xcheck Rework
 14 20050920    neill       Merged in branch
 15 20060626    laird       Adding support for vdenc framework.
 16 20060703    laird       XCheck rework.
 17 20060705    laird       Store the number of encoders.
 18 20060727    laird       Removing Asserts.
----------------------------STB225----------------------------------------
 15 20070112    laird       Moving to STB225.
 16 20070116    laird       Crosscheck rework.
 17 20070619    neill       Add mixer support and LCD screen
 18 20070702    neill       Add power mode control
 19 20071017    burningh    Fixing QA C coverage errors
 20 20071029    burningh    Improving QA C confidence factor
 21 20080807    laird       Tidy Up.
 22 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 DATA                  g[k|p|kp|pk|kpk]<Module>_<Word>+   *
*******************************************************************/

/**
 * @brief Name the Outputs.
 */
static Char *gphStbDFB_ScreenName[PH_STBVIDEORENDERER_MAX_INSTANCES] =
{
    "Main",
    "FrontPanel"
};

static ScreenFuncs gphStbDFB_ScreenFuncs = {
    /*.ScreenDataSize    = */ StbDFB_ScreenDataSize,
    /*.InitScreen        = */ StbDFB_InitScreen,
    /*.InitMixer         = */ StbDFB_InitMixer,
    /*.InitEncoder       = */ StbDFB_InitEncoder,
    0,
    /*.SetPowerMode      = */ StbDFB_SetPowerMode,
    0,
    /*.TestMixerConfig   = */ StbDFB_TestMixerConfig,
    /*.SetMixerConfig    = */ StbDFB_SetMixerConfig,
    /*.TestEncoderConfig = */ StbDFB_TestEncoderConfig,
    /*.SetEncoderConfig  = */ StbDFB_SetEncoderConfig,
    0,
    0,
    /*.GetScreenSize     = */ StbDFB_GetScreenSize
};


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

/*******************************************************************************
* FUNCTION IMPLEMENTATION  <Module>[_<Word>+] for static functions             *
*                          tm[<screen>]<Module>[_<Word>+] for exported functions*
********************************************************************************/
DFBResult phStbDFB_ScreenRegister(GraphicsDevice *device)
{
    DBG_PRINT1(gphStbDFB_DbgUnit, DBG_INTERNAL_ENTER, "%s: Registering Screens", __FUNCTION__);

    gpphStbDFB_Screen[PH_STBDFB_SCREEN_MAIN] = dfb_screens_register_primary(device,
                                                                            (void *)PH_STBDFB_SCREEN_MAIN,
                                                                            &gphStbDFB_ScreenFuncs);

    gpphStbDFB_Screen[PH_STBDFB_SCREEN_LCD] = dfb_screens_register(device,
                                                                   (void *)PH_STBDFB_SCREEN_LCD,
                                                                   &gphStbDFB_ScreenFuncs);

    DBG_PRINT1(gphStbDFB_DbgUnit, DBG_INTERNAL_LEAVE, "%s: Screens registered", __FUNCTION__);
    return DFB_OK;
}
/******************************************************************************/

extern int
StbDFB_ScreenDataSize(void)
{
    return sizeof(phStbDFB_ScreenData_t);
}

/******************************************************************************/
extern DFBResult StbDFB_GetScreenSize(
    CoreScreen                  *screen,
    void                        *driver_data,
    void                        *screen_data,
    int                         *ret_width,
    int                         *ret_height)
{
    tmErrorCode_t err;
    DFBResult result = DFB_FAILURE;

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

    err = phStbVideoRenderer_GetOutputResolution(phStbVideoRenderer_DisplayChain_Main,
                                                 (unsigned int *)ret_width,
                                                 (unsigned int *)ret_height);

    result = DFB_OK;

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

/******************************************************************************/
extern DFBResult
StbDFB_InitScreen(
    CoreScreen                   *screen,
    GraphicsDevice               *device,
    void                         *driver_data,
    void                         *screen_data,
    DFBScreenDescription         *description )
{
    DFBResult result = DFB_OK;
    phStbDFB_ScreenData_t *pScreenData = (phStbDFB_ScreenData_t*)screen_data;

    DBG_PRINT((gphStbDFB_DbgUnit, DBG_LEVEL_1, "%s: driver_data = 0x%08x", __FUNCTION__, driver_data));
    pScreenData->unitId = (int)driver_data;
    DBG_PRINT((gphStbDFB_DbgUnit, DBG_INTERNAL_ENTER, "%s: unitId=%u '%s'", __FUNCTION__, pScreenData->unitId, gphStbDFB_ScreenName[pScreenData->unitId]));
    DBG_PRINT((gphStbDFB_DbgUnit, DBG_LEVEL_1, "%s: screenData=0x%x", __FUNCTION__, pScreenData));

    /* Get pScreenData->screenWidth and pScreenData->screenHeight */
    TM_TO_DFB_RETURN_ON_ERR(StbDFB_GetScreenSize(screen,
                                                 device,
                                                 screen_data,
                                                 (int *)&(pScreenData->screenWidth),
                                                 (int *)&(pScreenData->screenHeight)),
                            "Error calling StbDFB_GetScreenSize Renderer(%d) 0x%08x\n",
                            pScreenData->unitId, err);

    description->caps = PH_STBDFB_SCREEN_CAPABILITIES;

    snprintf(description->name,
             DFB_SCREEN_DESC_NAME_LENGTH, "Screen");

    description->mixers = pScreenData->unitId == PH_STBDFB_SCREEN_MAIN ? 2 : 0;

    /*We just get the number of encoders for each renderer.
      If the number is greater than 0 then set the number of outputs to 1.
     */
    description->encoders = StbDFB_GetNumberVideoDencs(pScreenData->unitId);
    /* Store the number of Encoders. */
    pScreenData->numberEncoders = description->encoders;
    if(description->encoders > 0)
    {
        description->caps |= (DSCCAPS_ENCODERS | DSCCAPS_OUTPUTS);
        /* TODO: Must work out number of outputs*/
        description->outputs = 0;
    }

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


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

extern DFBResult StbDFB_WaitVSync(
    CoreScreen             *screen,
    void                   *driver_data,
    void                   *screen_data)
{
    static int  init = 0;
    static int volatile * pMmio;
    DFBResult result = DFB_OK;

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

    if (init == 0)
    {
        static int file;

        /* Access the MMIO device */
        file = open( "/dev/mmio", O_RDWR);
        if (file < 0)
        {
            printf("Error: Cannot open MMIO device /dev/mmio\n" );
            return result;
        }

        /* Memory map the MMIO Space */
        pMmio = (int volatile *)mmap(0,
                                     PH_STBDFB_MMIO_SIZE,
                                     PROT_READ | PROT_WRITE,
                                     MAP_SHARED,
                                     file, 0);
        if (pMmio == MAP_FAILED)
        {
            printf("Error: Cannot mmap MMIO memory\n" );
            return result;
        }
        init = 1;
    }

    /*Sync on a display chain */

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