/* SPDX-License-Identifier: LGPL-2.1-only OR BSD-3-Clause */
/******************************************************************************
 *
 * This file is provided under a dual license.  When you use or
 * distribute this software, you may choose to be licensed under
 * version 2.1 of the GNU Lesser General Public License
 * ("LGPLv2.1 License") or BSD License.
 *
 * LGPLv2.1 License
 *
 * Copyright(C) 2019 MediaTek Inc.
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of version 2.1 of the GNU Lesser General Public
 * License as published by the Free Software Foundation.
 *
 * 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 https://www.gnu.org/licenses/old-licenses/lgpl-2.1.html for more
 * details.
 *
 * BSD LICENSE
 *
 * Copyright(C) 2019 MediaTek Inc.
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 *  * Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 *  * Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in
 *    the documentation and/or other materials provided with the
 *    distribution.
 *  * Neither the name of the copyright holder nor the names of its
 *    contributors may be used to endorse or promote products derived
 *    from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
 * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 *
 *****************************************************************************/

/*-----------------------------------------------------------------------------
 *
 * $Author: shuo.ding $
 * $Date: 2015/08/04 $
 * $RCSfile: pmx_if.c,v $
 * $Revision: #2 $
 *
 *---------------------------------------------------------------------------*/

/** @file pmx_if.c
 *  plane mixer(pmx) public functions
 */


//-----------------------------------------------------------------------------
// Include files
//-----------------------------------------------------------------------------

#include "pmx_hw.h"
#include "pmx_drvif.h"
#include "x_lint.h"
LINT_EXT_HEADER_BEGIN
#include "drvcust_if.h"
LINT_EXT_HEADER_END


//-----------------------------------------------------------------------------
// Configurations
//-----------------------------------------------------------------------------


//-----------------------------------------------------------------------------
// Constant definitions
//-----------------------------------------------------------------------------


//-----------------------------------------------------------------------------
// Type definitions
//-----------------------------------------------------------------------------

/** Plane mixer configuration.
 */
typedef struct
{
    UINT32 u4BgColor;
    UCHAR aucPlaneOrder[PMX_MAX_INPORT_NS];
} PMX_CONF_T;


//-----------------------------------------------------------------------------
// Macro definitions
//-----------------------------------------------------------------------------


//-----------------------------------------------------------------------------
// Imported variables
//-----------------------------------------------------------------------------


//-----------------------------------------------------------------------------
// Imported functions
//-----------------------------------------------------------------------------


//-----------------------------------------------------------------------------
// Static function forward declarations
//-----------------------------------------------------------------------------


//-----------------------------------------------------------------------------
// Static variables
//-----------------------------------------------------------------------------

static PMX_CONF_T _rPmxConf =
{
    0x000000,
    { PMX_OSD3, PMX_OSD2, PMX_OSD1, PMX_MAIN, PMX_PIP}
};

static UCHAR _fgPmxInit = 0;
static BOOL _fgPmxYuvMode = FALSE;

static UCHAR PMX_GetMixAlphaType(const UINT32 *pu4PlaneOrder);
UINT32 PMX_SetMixAlpha(UCHAR ucType, const UINT32 *pu4Alpha);



//-----------------------------------------------------------------------------
// Macro definitions
//-----------------------------------------------------------------------------

#define VERIFY_NULL(ptr)                                    \
          do {                                              \
            if (ptr == NULL) { return PMX_SET_ERROR; }      \
          } while (0)


//-----------------------------------------------------------------------------
// Static functions
//-----------------------------------------------------------------------------


//-----------------------------------------------------------------------------
// Inter-file functions
//-----------------------------------------------------------------------------


//-----------------------------------------------------------------------------
// Public functions
//-----------------------------------------------------------------------------

//-----------------------------------------------------------------------------
/** initialize pmx
 */
//-----------------------------------------------------------------------------
#ifndef USERDRV_KERNEL_MOD
void PMX_Init(void)
{
    if (_fgPmxInit == 0)
    {
        _PMX_Init();
        PMX_Set_ALPHA_MIX_GRP1_0(TRUE);
        PMX_Set_ALPHA_MIX_GRP12_0(TRUE);
        _fgPmxInit = 1;
    }
}


UINT32 PMX_SetPlaneOrderArray(const UINT32 *pu4PlaneOrder)
{
    UINT32  u4PoIdx;
    UINT32  u4Alpha[4] = {0xff, 0xff, 0xff, 0xff};
    UINT32 *pu4Alpha = u4Alpha;
    VERIFY_NULL(pu4PlaneOrder);

    for (u4PoIdx = 0; u4PoIdx < PMX_MAX_INPORT_NS; u4PoIdx++)
    {
        _rPmxConf.aucPlaneOrder[u4PoIdx] = (UCHAR)pu4PlaneOrder[u4PoIdx];
    }

    if (PMX_MAX_INPORT_NS >= (PMX_PLANE_NUMBER + 0x3))
    {
        pu4Alpha = (UINT32 *)&pu4PlaneOrder[PMX_ALPHA];
    }

    PMX_SetMixAlpha(PMX_GetMixAlphaType(pu4PlaneOrder), pu4Alpha);
    _PMX_SetPlaneOrderArray(pu4PlaneOrder);
    return PMX_SET_OK;
}
#endif

UINT32 PMX_GetPlaneOrderArray(UINT32 *pu4PlaneOrder)
{
    UINT32 u4PoIdx;
    VERIFY_NULL(pu4PlaneOrder);

    for (u4PoIdx = 0; u4PoIdx < PMX_MAX_INPORT_NS; u4PoIdx++)
    {
        pu4PlaneOrder[u4PoIdx]	=	_rPmxConf.aucPlaneOrder[u4PoIdx];
    }

    return PMX_SET_OK;
}



//-----------------------------------------------------------------------------
/** set plane z-order
 *  @param  ucPmxId only PMX_1
 *  @param  ucVdpId video plane=VDP1/osd plane 2=VDP4
 *  @param  ucPlaneOrder PLA_MXR_Z_ORDER_1 or PLA_MXR_Z_ORDER_2
 *  @retval PMX_SET_OK success
 */
//-----------------------------------------------------------------------------
UINT32 PMX_SetPlaneOrder(UCHAR ucVdpId, UCHAR ucPlaneOrder)
{
    if(ucPlaneOrder >= PMX_MAX_INPORT_NS)
    {
        return PMX_SET_ERROR;
    }
    _rPmxConf.aucPlaneOrder[ucPlaneOrder] = ucVdpId;
    _PMX_SetPlaneOrder(ucVdpId, ucPlaneOrder);
    return PMX_SET_OK;
}


//-----------------------------------------------------------------------------
/** get plane z-order
 *  @param  ucPmxId only PMX_1
 *  @param  ucVdpId video plane=VDP1/osd plane 2=VDP4
 *  @param  pucPlaneOrder order pointer
 *  @retval PMX_SET_OK success
 */
//-----------------------------------------------------------------------------
UINT32 PMX_GetPlaneOrder(UCHAR ucVdpId, UCHAR *pucPlaneOrder)
{
    UINT32 u4PoIdx;
    VERIFY_NULL(pucPlaneOrder);

    for (u4PoIdx = 0; u4PoIdx < PMX_MAX_INPORT_NS; u4PoIdx++)
    {
        if (_rPmxConf.aucPlaneOrder[u4PoIdx] == ucVdpId)
        {
            *pucPlaneOrder = (UCHAR)u4PoIdx;
            return PMX_SET_OK;
        }
    }

    *pucPlaneOrder = PMX_MAX_INPORT_NS;
    return PMX_SET_OK;
}


//-----------------------------------------------------------------------------
/** set pmx background color
 *  @param  ucPmxId only PMX_1
 *  @param  u4BgColor background color(0xrrggbb)
 *  @retval PMX_SET_OK success
 */
//-----------------------------------------------------------------------------
#ifdef DRV_SUPPORT_EXTMJC
void PMX_SetYuvMode(BOOL fgYuvMode)
{
    _fgPmxYuvMode = fgYuvMode;
    IGNORE_RET(PMX_SetBg(_rPmxConf.u4BgColor, TRUE));
    PMX_OnOutputVSync();
}
#endif

UINT32 PMX_SetBg(UINT32 u4BgColor, BOOL fgInVsync)
{
    _rPmxConf.u4BgColor = u4BgColor;
    _PMX_SetBgColor(u4BgColor, _fgPmxYuvMode, fgInVsync);
    return PMX_SET_OK;
}

#ifdef CC_FOR_POC_DEMO
UINT32 PMX_SetBlk(UINT32 u4BlkColor)
{
    _PMX_SetBlkColor(u4BlkColor);
    return PMX_SET_OK;
}
#endif

//-----------------------------------------------------------------------------
/** setup alpha value for video plane
 *  @param  ucPlaneId video plane id(onlu VDP_1 in 5381)
 *  @param  ucValue alpha value(0~255)
 *  @retval PMX_SET_OK success
 */
//-----------------------------------------------------------------------------
UINT32 PMX_SetAlpha(UCHAR ucPlaneId, UCHAR ucValue)
{
    if ((ucPlaneId != PMX_MAIN) && (ucPlaneId != PMX_PIP))
    {
        return PMX_SET_ERROR;
    }

    _PMX_SetAlpha(ucPlaneId, ucValue);
    return PMX_SET_OK;
}


void PMX_Set_ALPHA_MIX_GRP1_0(BOOL fgEnable)
{
    _PMX_Set_ALPHA_MIX_GRP1_0(fgEnable);
    return;
}


void PMX_Set_ALPHA_MIX_GRP12_0(BOOL fgEnable)
{
    _PMX_Set_ALPHA_MIX_GRP12_0(fgEnable);
    return;
}



static UCHAR PMX_GetMixAlphaType(const UINT32 *pu4PlaneOrder)
{
    UCHAR   ucTemp          = 0x0;
    UCHAR   ucVideoBot      = 0x0;
#ifdef CC_MT5396
    UCHAR   ucOsdNum        = 0x3;
#else
    UCHAR   ucOsdNum        = 0x2;
#endif

    for (ucTemp = 0x0; ucTemp < ucOsdNum; ucTemp++)
    {
        if ((pu4PlaneOrder[ucTemp] == PMX_OSD1) ||
                (pu4PlaneOrder[ucTemp] == PMX_OSD2) ||
                (pu4PlaneOrder[ucTemp] == PMX_OSD3))
        {
            ucVideoBot++;
        }
    }

    if (ucVideoBot == ucOsdNum)
    {
        return  PMX_MIX_AL_VIDEO_BOT;
    }

    if ((PMX_PIP == pu4PlaneOrder[0]) ||
            (PMX_MAIN == pu4PlaneOrder[0]))
    {
        return PMX_MIX_AL_VIDEO_TOP;
    }

    if ((PMX_PIP == pu4PlaneOrder[PMX_ALPHA - 1]) ||
            (PMX_MAIN == pu4PlaneOrder[PMX_ALPHA - 1]))
    {
        return PMX_MIX_AL_VIDEO_BOT;
    }

    if ((PMX_PIP == pu4PlaneOrder[PMX_ALPHA - 2]) ||
            (PMX_MAIN == pu4PlaneOrder[PMX_ALPHA - 2]))
    {
        return PMX_MIX_AL_VIDEO_1_OSD_BELOW;
    }

    return PMX_MIX_AL_VIDEO_2_OSD_BELOW;
}

//-----------------------------------------------------------------------------
/** setup alpha value for video plane
 *  @param  ucPlaneId video plane id(onlu VDP_1 in 5381)
 *  @param  ucValue alpha value(0~255)
 *  @retval PMX_SET_OK success
 */
//-----------------------------------------------------------------------------
UINT32 PMX_SetMixAlpha(UCHAR ucType, const UINT32 *pu4Alpha)
{
    switch (ucType)
    {
        case PMX_MIX_AL_VIDEO_BOT:
            _PMX_Set_ALPHA_MIX_VIDEO_BOT(pu4Alpha);
            break;

        case PMX_MIX_AL_VIDEO_1_OSD_BELOW:
            _PMX_Set_ALPHA_MIX_VIDEO_1_OSD_BELOW(pu4Alpha);
            break;

        case PMX_MIX_AL_VIDEO_2_OSD_BELOW:
            _PMX_Set_ALPHA_MIX_VIDEO_2_OSD_BELOW(pu4Alpha);
            break;

        case PMX_MIX_AL_VIDEO_TOP:
            _PMX_Set_ALPHA_MIX_VIDEO_TOP(pu4Alpha);
            break;

        default:
            return PMX_SET_ERROR;
    }

    return PMX_SET_OK;
}

