/* 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: brianpc.huang $
 * $Date: 2015/05/29 $
 * $RCSfile: gfx_hw.h,v $
 * $Revision: #1 $
 *
 *---------------------------------------------------------------------------*/

/** @file gfx_hw.h
 *  gfx hardware interface
 *  init, get register base, isr, vpll calibration, reset,
 *  get status, get que length, get idle, get yline, get op count,
 *  get hardware version, set power down mode
 */

#ifndef GFX_HW_H
#define GFX_HW_H

//---------------------------------------------------------------------------
// Include files
//---------------------------------------------------------------------------
#include "gfx_common_if.h"

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


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

//#define GFX_ADDR                IO_ADDR(GRAPH_BASE)
#ifdef __KERNEL__
#define GFX_ADDR                (GRAPH_BASE)
#else
#define GFX_ADDR                (0xf0000000 | GRAPH_BASE)
#endif

#define VGFX_ADDR                (VGRAPH_BASE)
#define VGFX_CMDQUE_ADDR         (VGRAPH_CMDQUE_BASE)
#define VGFX_REG_G_CONFIG        (0x00)

// must use IO_READ32 or IO_WRITE32 to control GFX HW registers
#define GFX_REG_G_CONFIG        (0x00)
#define GFX_REG_G_STATUS        (0x04)
#define GFX_REG_DRAMQ_STAD      (0x08)
#define GFX_REG_DRAMQ_LEN       (0x0C)
#define GFX_REG_G_MODE          (0x10)

#define GFX_REG_LEGAL_START     (0x90)
#define GFX_REG_LEGAL_END       (0x94)

#define GFX_REG_ROP             (0xA0)

#define GFX_REG_0x40E0          (0xE0)
#define GFX_REG_0x40E4          (0xE4)

#define GFX_REG_0x40EC          (0xEC)
#define GFX_REG_0x40F0          (0xF0)
#define GFX_REG_ADDR_MSG_MASK  (0xC0000000)
#define GFX_REG_ADDR_MSG(a)     (((a)&GFX_REG_ADDR_MSG_MASK)>>30)

//------------------------------------------------
// GFX HW registers' shift
//   [G_CONFIG] - 0x4000
#define GREG_SHT_G_RST          30
#define GREG_SHT_CQ_RST         28
#define GREG_SHT_ENG_LP         17
#define GREG_SHT_SHT_CMDQ       16
#define GREG_SHT_SDFIFO_THRS     9
#define GREG_SHT_DRAMQ_MODE      8
#define GREG_SHT_REQ_INTVAL      6
#define GREG_SHT_CMDFIFO_THRS    4
#define GREG_SHT_POST_THRS       2
#define GREG_SHT_INT_MASK        1
#define GREG_SHT_EN_DRAMQ        0
//   [G_STATUS] - 0x4004
#define GREG_SHT_VERSION_ID      8
#define GREG_SHT_IDLE            0
//   [DRAMQ_STAD] - 0x4008
#define GREG_SHT_CYC_SIZE       30
#define GREG_SHT_DRAMQ_BSAD      0
//   [ROP] - 0x40A0
#define GREG_SHT_CMP_FLAG        9

//------------------------------------------------
// GFX HW registers' mask
//   [G_CONFIG] - 0x4000
#define GREG_MSK_G_RST          ((UINT32)0x3 << GREG_SHT_G_RST)
#define GREG_MSK_CQ_RST         ((UINT32)0x3 << GREG_SHT_CQ_RST)
#define GREG_MSK_ENG_LP         ((UINT32)0x1 << GREG_SHT_ENG_LP)
#define GREG_MSK_SHT_CMDQ       ((UINT32)0x1 << GREG_SHT_SHT_CMDQ)
#define GREG_MSK_SDFIFO_THRS    ((UINT32)0x3 << GREG_SHT_SDFIFO_THRS)
#define GREG_MSK_DRAMQ_MODE     ((UINT32)0x1 << GREG_SHT_DRAMQ_MODE)
#define GREG_MSK_REQ_INTVAL     ((UINT32)0x3 << GREG_SHT_REQ_INTVAL)
#define GREG_MSK_CMDFIFO_THRS   ((UINT32)0x3 << GREG_SHT_CMDFIFO_THRS)
#define GREG_MSK_POST_THRS      ((UINT32)0x3 << GREG_SHT_POST_THRS)
#define GREG_MSK_INT_MASK       ((UINT32)0x1 << GREG_SHT_INT_MASK)
#define GREG_MSK_EN_DRAMQ       ((UINT32)0x1 << GREG_SHT_EN_DRAMQ)
//   [G_STATUS] - 0x4004
#define GREG_MSK_VERSION_ID     ((UINT32)0xFF << GREG_SHT_VERSION_ID)
#define GREG_MSK_IDLE           ((UINT32)0x1 << GREG_SHT_IDLE)
//   [DRAMQ_STAD] - 0x4008
#define GREG_MSK_CYC_SIZE       ((UINT32)0x3 << GREG_SHT_CYC_SIZE)
#define GREG_MSK_DRAMQ_BSAD     ((UINT32)0xFFFFFFF << GREG_SHT_DRAMQ_BSAD)
//   [ROP] - 0x40A0
#define GREG_MSK_CMP_FLAG       ((UINT32)0x1 << GREG_SHT_CMP_FLAG)

#define GFX_G_RST_READY         ((UINT32)0x80000000)
#define GFX_CQ_RST_READY        ((UINT32)0x20000000)

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

/// Read 32 bits data from GFX HW registers.
#define GFX_READ32(offset)           IO_READ32(GFX_ADDR, (offset))

/// Write 32 bits data into GFX HW registers.
#define GFX_WRITE32(offset, value)   IO_WRITE32(GFX_ADDR, (offset), (value))

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

// 5 hw engine state
enum EGFX_CORE_STATUS_T
{
    E_GFX_IDLE = 0, E_GFX_BUSY, E_GFX_SEMIIDLE, E_GFX_CRASHED, E_GFX_UNKNOWN
};

// gfx engine clock source
enum EGFX_ENGINE_CLOCK_T
{
    E_GFX_CLK_XTAL_CK = 0, E_GFX_CLK_SYSPLL_D2, // system pll / 2
    E_GFX_CLK_TVDPLL_D3, // tv-dec pll / 3
    E_GFX_CLK_TVDPLL_D5, // tv-dec pll / 5
    E_GFX_CLK_DTDPLL_D3, // dtd    pll / 3   (200 MHz)
    E_GFX_CLK_DTDPLL_D4, // dtd    pll / 4
    E_GFX_CLK_PSPLL_D1, // ps     pll / 1
    E_GFX_CLK_MEM, // mem    pll

    E_GFX_CLK_MAX
};

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


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

extern void GFX_HwInit(void);

extern void GFX_HwGetRegBase(UINT32 **ppu4RegBase);

extern void GFX_HwISR(void);

extern void GFX_HwReset(void);

extern INT32 GFX_HwGetIdle(void);

extern void GFX_HwAction(void);

extern void GFX_HwSetRiscMode(void);

extern void GFX_HwSetCmdQMode(void);

extern void GFX_HwSetEngClkSrc(INT32 i4ClkSrc);

extern INT32 GFX_HwGetMemCompareResult(void);

// for debug use
#if defined(GFX_DEBUG_MODE)
extern void GFX_HwResetEngine(void);

extern void GFX_HwResetCmdQue(void);

extern void GFX_HwGetHwVersion(UINT32 *pu4HwVersion);

extern void GFX_HwEnableLowPowerMode(void);

extern void GFX_HwDisableLowPowerMode(void);

extern void GFX_HwSetSDFifoThreshold(UINT32 u4Value);

extern void GFX_HwSetCMDFifoThreshold(UINT32 u4Value);

extern void GFX_HwSetPOSTFifoThreshold(UINT32 u4Value);

extern void GFX_HwSetReqInterval(UINT32 u4ReqInterval);
#endif // #if defined(GFX_DEBUG_MODE)

#endif // GFX_HW_H
