/* 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: xiaojun.zhu $
 * $Date: 2015/08/08 $
 * $RCSfile: fvr_if.h,v $
 * $Revision: #3 $
 *
 *---------------------------------------------------------------------------*/

/** @file fvr_if.h
 *  FVR driver - FVR Interface Header
 */

#ifndef _FVR_IF_H
#define _FVR_IF_H

#include "dmx_mm_if.h"

#define FVR_SCRAMBLE_PID_INDEX              (4)
#define FVR_KEY_COUNT                       (4)

#define FVR_SINGLE_STREAM_GBL_COUNT         (4)
#define FVR_GBL_COUNT                       (5) //add new record region for ci+1.4.

#define FVR_FIFO_ALIGNMENT                  32

#define FVR_PIC_I_TYPE                      0x1
#define FVR_PIC_P_TYPE                      0x2
#define FVR_PIC_B_TYPE                      0x4
#define FVR_PIC_UNKNOWN                     0xFF

#define FVR_PIC_I_MASK                      0x1
#define FVR_PIC_P_MASK                      0x2
#define FVR_PIC_B_MASK                      0x4

#define FVR_PIC_H264_IDR_TYPE       0x10
#define FVR_PIC_H264_NIDR_TYPE      0x20

#define FVR_CIPLUS14_REGION_IDX          4
//------------------------------------------------------------
// TimeStamp
//------------------------------------------------------------
#define FVR_TIMESTAMP_FLAG_ENABLE           0x00000001
#define FVR_TIMESTAMP_FLAG_CLKDIV           0x00000002
#define FVR_TIMESTAMP_FLAG_MASK             0x00000004
#define FVR_TIMESTAMP_FLAG_COUNTER          0x00000008
#define FVR_TIMESTAMP_FLAG_NONE             0x00000000
#define FVR_TIMESTAMP_FLAG_ALL              0xFFFFFFFF

typedef struct
{	
	UINT8 u1Idx;
    BOOL fgEnable;
    UINT16 u2ClkDiv;
    UINT32 u4Mask;
    UINT32 u4Counter;
} FVR_TIMESTAMP_T;

//------------------------------------------------------------
// GBL Callback
//------------------------------------------------------------
typedef enum
{
    FVR_VIDEO_MPEG = 0,
    FVR_VIDEO_H264,
    FVR_VIDEO_AVS,
    FVR_VIDEO_H265,
    FVR_VIDEO_NONE,
} FVR_VIDEO_TYPE_T;

typedef enum
{
    FVR_GBL_NFY_TIME,
    FVR_GBL_NFY_PKTCOUNT,
    FVR_GBL_NFY_OVERFLOW
} FVR_GBL_NOTIFY_CODE_T;

typedef enum
{
    FVR_CRYPTO_KEY_SECURE_PVR_AES_0 = 0,  ///< secure key
    FVR_CRYPTO_KEY_SECURE_PVR_AES_IV_0,
    FVR_CRYPTO_KEY_AES,
    FVR_CRYPTO_KEY_AES_IV,
    FVR_CRYPTO_KEY_MAX
} FVR_CRYPTO_KEY_TYPE_T;

typedef struct
{
    UINT8  u1TsIndex;
    UPTR u4Addr;
    USIZE u4Size;
    UINT32 u4PktCount;
} FVR_GBL_PKTNOTIFY_INFO_T;

typedef struct
{
    UINT8  u1TsIndex;
    UPTR u4Addr;
    USIZE u4Size;
    UINT32 u4PktCount;
} FVR_GBL_TIMENOTIFY_INFO_T;

typedef struct
{
    UINT8  u1Pidx;
    UINT16 u2PicType;
    UINT32 u4PktCount;
    UINT64 u8Pts33;
} FVR_PID_PICNOTIFY_INFO_T;

typedef struct
{
    UINT8 u1TsIndex;
    UINT8 u1SitPktCnt;
    UPTR u4SitWp;
} FVR_SIT_PKTREPLACE_INFO_T;

typedef union {
    struct {
        UINT32 au4Key[8];
    } rAesKey;

    struct {
        UINT32 au4Iv[4];
    } rAesIv;
} FVR_CRYPTO_KEY_UNION_T;

typedef struct
{
    BOOL fgEven;
    UINT8 u1KeyIdx;
    UINT32 u4KeyLen;
    FVR_CRYPTO_KEY_TYPE_T eKeyType;
    FVR_CRYPTO_KEY_UNION_T uKey;
} FVR_CRYPTO_KEY_INFO_T;

typedef struct
{
    UINT8 u1Pidx;
    UINT8 u1TsIndex;
    UINT8 u1PicType;
    UINT32 u4SeqNum;
    UINT64 u8Pts;
    UINT64 u8PresentationTime;
    UPTR u4MptAddr;
    UINT64 u8MptRingCount;
    UPTR u4Addr;
    UINT64 u8PicRingCount;
    USIZE u4Size;
} TLV_FVR_NOTIFY_INFO_T;

typedef void (*PFN_TLV_FVR_PID_PICSEARCH)(UINT8 u1Pidx, TLV_FVR_NOTIFY_INFO_T *pNotifyInfo, const void *pvTag);
typedef void (*PFN_FVR_GBL_NOTIFY)(FVR_GBL_NOTIFY_CODE_T eCode, UPTR u4Data, const void* pvTag);

//------------------------------------------------------------
// PID Callback
//------------------------------------------------------------
typedef void (*PFN_FVR_PID_PKTSWAP)(UINT8 u1Pidx, UPTR u4Addr);

typedef void (*PFN_FVR_PID_PICSEARCH)(UINT8 u1Pidx, UINT16 u2Type, UINT32 u4PktCount, 
                                    UINT64 u8Pts33, const void* pvTag);

/// Scrambling state
typedef enum
{
    FVR_SCRAMBLE_STATE_CLEAR,           ///< Clear data
    FVR_SCRAMBLE_STATE_SCRAMBLED,       ///< Scrambled data
    FVR_SCRAMBLE_STATE_UNKNOWN,          ///< Unknown data
    FVR_SCRAMBLE_STATE_SWAP_ONCE_COMPLETE = 0x10
} FVR_SCRAMBLE_STATE_T;


typedef BOOL (*PFN_FVR_PID_DETECTSCRAMBLE)(UINT8 u1Pidx, FVR_SCRAMBLE_STATE_T eState);

//-----------------------------------------------------------------------------
// Function bitmap of PID operations
//-----------------------------------------------------------------------------
#define FVR_GBL_FLAG_BUFFER             0x00000001
#define FVR_GBL_FLAG_TARGET_PKT         0x00000002
#define FVR_GBL_FLAG_NOTIFY             0x00000004
#define FVR_GBL_FLAG_TIME_INFO          0x00000008
#define FVR_GBL_FLAG_SYNC_BYTE          0x00000010
#define FVR_GBL_FLAG_SYNC_MASK          0x00000020
#define FVR_GBL_FLAG_CIPUS_TS           0x00000040
#define FVR_GBL_FLAG_TIMESTAMP          0x00000080
#define FVR_GBL_FLAG_REMUX_DIRECTION    0x00000100
#define FVR_GBL_FLAG_NONE               0x00000000
#define FVR_GBL_FLAG_ALL                0xFFFFFFFF

#define FVR_PID_FLAG_ENABLE             0x00000001
#define FVR_PID_FLAG_TSINDEX            0x00000002
#define FVR_PID_FLAG_PID                0x00000004
#define FVR_PID_FLAG_PICSEARCH          0x00000008
#define FVR_PID_FLAG_PKTSWAP            0x00000010
#define FVR_PID_FLAG_SCRAMBLE_ENABLE    0x00000020  // Record encryption
#define FVR_PID_FLAG_CBC_MODE           0x00000040  // Record encryption
#define FVR_PID_FLAG_KEY_TYPE           0x00000080  // Record encryption
#define FVR_PID_FLAG_KEY_LEN            0x00000100  // Record encryption
#define FVR_PID_FLAG_KEY_INDEX          0x00000200  // Record encryption
#define FVR_PID_FLAG_DETECT_SCRAMBLE    0x00000400  // Input TS: Detect descramble or not
#define FVR_PID_FLAG_FREEZE             0x00000800
#define FVR_PID_FLAG_SOURCE             0x00001000
#define FVR_PID_FLAG_TYPE               0x00002000
#define FVR_PID_FLAG_SECNOTIFY          0x00004000  // PSI section filter
#define FVR_PID_FLAG_INSTANCE_TAG       0x00008000  // PSI section filter
#define FVR_PID_FLAG_DESC               0x00010000  // Input TS: Desc mode (CI+, multi-2)
#define FVR_PID_FLAG_LOCAL_TSINDEX      0x00020000 //input ts: for ci+1.4 remux ts local index.
#define FVR_PID_FLAG_SERIAL_NUMBER      0x00040000  ///< Serial nubmer
#define FVR_PID_FLAG_TLV_SWAP_LEN		0x00080000  ///uCode resver buffer len for tlv packet swap
#define FVR_PID_FLAG_NONE               0x00000000
#define FVR_PID_FLAG_ALL                0xFFFFFFFF


//-----------------------------------------------------------------------------
// Time-shift Tick Count
//-----------------------------------------------------------------------------
#define TIMESHIFT_TIME_SLICE               250
#define TIMESHIFT_MAX_TICKCOUNT            40//20

//-----------------------------------------------------------------------------
// Type definitions
//-----------------------------------------------------------------------------
typedef enum
{
    FVR_KEY_EVEN,
    FVR_KEY_ODD,
    FVR_KEY_BOTH
} FVR_KEY_TYPE_T;

typedef struct
{
    UINT16 u2TargetPktCount;
    BOOL fgAllocateBuffer;
    UPTR u4BufStart;
    USIZE u4BufSize;
    UPTR u4Wp;
    UPTR u4Rp;

    BOOL fgSetAlign;
    UINT32 u4BufAlign;

    PFN_FVR_GBL_NOTIFY pfnNotifyFunc;
    void* pvNotifyTag;
   
    UINT32 u4TimeToNotify;
    /*the following item used for ciplus1.4 record.*/
	UINT32 u4SyncPattern; /*ts3 bit[31:24], ts2 bit[23:16], ts1 bit[15:8], ts0bit[7:0]*/
    UINT8  u1CiTsidx; /*for ci input ts index settings*/
    UINT8  u1SyncMask; /*use bit[3:0] */
	BOOL   fgTimeStamp;  /*  for every global regtion,ucode set this to HW  TRUE: enable,FALSE:disable*/	
    BOOL   fgRemuxDirection; /* if the 34thByte (HW enable:1),then ucode config HW CP7_0,data inflow cp7, not remux buffer */
} FVR_GBL_T;

typedef struct
{
    BOOL fgEnable;
    UINT8 u1TsIndex;
	UINT8 u1LocalTsIndex;
    UINT16 u2Pid;

    BOOL fgPktSwap;
	UINT16 u2SwapLen;   //for tlv 
    PFN_FVR_PID_PKTSWAP pfnSwapNotify;
    void *pvSwapNotifyTag;
    BOOL fgPktSwapOnce;

    BOOL fgPicSearch;
    UINT8 u1PicSearchMask;
    PFN_FVR_PID_PICSEARCH pfnPicSearchNotify;
    PFN_TLV_FVR_PID_PICSEARCH pfnTlvPicSearchNotify;
    void *pvPicSearchNotifyTag;

    BOOL fgScramble;
    BOOL fgCBCMode;

    FVR_KEY_TYPE_T eKeyType;
    UINT8 u1KeyIdx;
    UINT32 u4KeyLen;

    BOOL fgDetectScramble;
    PFN_FVR_PID_DETECTSCRAMBLE pfnDetectScrambleNotify;
    PFN_FVR_PID_DETECTSCRAMBLE pfnDetectRawScrambleNotify;
     
    BOOL fgFreeze;
    DMX_SOURCE_T eSource;     // Logical channel: DTV0, DTV1
    DMX_PID_TYPE_T ePidType;

    //----------------------------------
    // Below is for section filter
    BOOL fgDoSFilter;
    BOOL fgAllocateBuffer;      // Allocate buffer or not
    UPTR u4BufAddr;          // Buffer start
    USIZE u4BufSize;            // Buffer length
    UPTR u4Rp;                // Read pointer
    UPTR u4SectionRp;         // Section read pointer
    UPTR u4Wp;                // Write pointer
    PFN_DMX_NOTIFY pfnNotify;   // Demux callback function
    void* pvNotifyTag;          // Tag value of callback function
    void *pvInstanceTag;
    //----------------------------------

    BOOL  fgDesc;               // Decrypt TS (CI+, multi-2)
    UINT8 u1DescKeyidx;           // Decrypt TS (CI+, multi-2)
    DMX_DESC_MODE_T eDescMode;  // Descramble mode
    UINT8 u1SerialNumber;

    UINT8 u1PhyIpIdx;
    UINT8 u1VirIpIdx;

} FVR_PID_T;

typedef struct
{
    UPTR u4BufStart;
    UPTR u4BufEnd;
    UPTR u4Wp;
    UPTR u4Rp;
    UINT32 u4PktCount;
    UINT32 u4OverflowCount;
    USIZE u4BufPeakSize;
} FVR_QUERY_INFO_T;

//------------------------------------------------------------
// Macro
//------------------------------------------------------------
#define GET_BYTE(arg, n)                ((UINT8*)&(arg))[n]

//------------------------------------------------------------
// Function
//------------------------------------------------------------
EXTERN BOOL FVR_Init(void);
EXTERN BOOL FVR_Start(UINT8 u1Idx);
EXTERN BOOL FVR_Stop(UINT8 u1Idx);
EXTERN BOOL FVR_GetResidual(UINT8 u1Idx,UPTR *pu4Addr, USIZE *pu4Size, UINT32 *pu4Index);
EXTERN BOOL FVR_IsRecording(UINT8 u1Idx);
EXTERN void FVR_SetScrambleScheme(BOOL fgOrg);

EXTERN BOOL FVR_SetGBL(UINT8 u1Idx,UINT32 u4Flags, const FVR_GBL_T* prPid);
EXTERN BOOL FVR_GetGBL(UINT8 u1Idx,UINT32 u4Flags, FVR_GBL_T* prPid);
EXTERN BOOL FVR_FreeGBL(UINT8 u1Idx);
EXTERN BOOL FVR_DropScrambledPacket(UINT8 u1Idx, BOOL fgEnalbe);

EXTERN BOOL FVR_SetPid(UINT8 u1Pidx, UINT32 u4Flags, const FVR_PID_T* prPid);
EXTERN BOOL FVR_GetPid(UINT8 u1Pidx, UINT32 u4Flags, FVR_PID_T* prPid);
EXTERN BOOL FVR_FreePid(UINT8 u1Pidx);

EXTERN void FVR_SetTimestamp(UINT32 u4Flags, const FVR_TIMESTAMP_T* prTimeStamp);
EXTERN void FVR_GetTimestamp(UINT32 u4Flags, FVR_TIMESTAMP_T* prTimeStamp);

EXTERN BOOL FVR_FlushBuffer(UINT8 u1Idx);
EXTERN BOOL FVR_GetBuffer(UINT8 u1Idx, UPTR u4Addr, USIZE u4Size, UINT8 *pu1Buf, UPTR *pu4RetSize);
EXTERN BOOL FVR_UnlockBuffer(UINT8 u1Idx, UPTR u4Addr, USIZE u4Size);
EXTERN BOOL FVR_FreeBuffer(UINT8 u1Idx);

EXTERN void FVR_SetIsOverflow(UINT8 u1Idx, BOOL fgIsOverflow);
EXTERN void FVR_QueryStatus(UINT8 u1Idx, FVR_QUERY_INFO_T *prInfo);

EXTERN void FVR_SetByPass(UINT8 u1TsIndex, UINT32 u4Val, BOOL fgEnable);

EXTERN BOOL FVR_SwapSetPattern(UINT8 u1Pidx, UINT8* pu1Pattern, UINT16 u2Len);
EXTERN BOOL FVR_SwapSetNullPattern(UINT8 u1Pidx);
EXTERN BOOL FVR_SwapFreePattern(UINT8 u1Pidx);

EXTERN BOOL FVR_SetVideoTypeEx(UINT8 u1TsIdx, FVR_VIDEO_TYPE_T eVideoType);
EXTERN FVR_VIDEO_TYPE_T FVR_GetVideoTypeEx(UINT8 u1TsIdx);
EXTERN BOOL FVR_SetVideoTypeByPidx(UINT8 u1Pidx, FVR_VIDEO_TYPE_T eVideoType);
EXTERN FVR_VIDEO_TYPE_T FVR_GetVideoTypeByPidx(UINT8 u1Pidx);

EXTERN BOOL FVR_SetAesKey(UINT8 u1KeyIdx, BOOL fgEven, UINT8 *pu1Key);
EXTERN BOOL FVR_SetAesEvenOddIV(UINT8 u1Idx, BOOL fgEven, UINT8 *pu1IV);
EXTERN BOOL FVR_SetCryptoKey(UINT8 u1KeyIdx, BOOL fgEven, FVR_CRYPTO_KEY_TYPE_T eKeyType,
                            const UINT8 *pu1Key, UINT32 u4KeyLen);
EXTERN BOOL FVR_UpdateWritePointer(UINT8 u1Idx, UPTR u4Wp);

EXTERN BOOL FVR_SitSetPattern(UINT8 u1TsIdx, UINT16 u2Pid, const UINT8 *pu1Data, UINT16 u2Len);
EXTERN BOOL FVR_SitFreePattern(UINT8 u1TsIdx);
EXTERN BOOL FVR_SitInsertPattern(UINT8 u1TsIdx);
EXTERN BOOL FVR_SitInsertPatternByTimer(UINT8 u1TsIdx, UINT32 u4MsDelay);
EXTERN BOOL FVR_SitStopTimer(UINT8 u1TsIdx);

EXTERN BOOL FVR_StartInsertDIT(UINT8 u1Pidx, UINT32 u4PcrDiffMs);
EXTERN BOOL FVR_StopInsertDIT(UINT8 u1Pidx);

EXTERN FVR_SCRAMBLE_STATE_T FVR_GetScrambleState(UINT8 u1Pidx);
EXTERN FVR_SCRAMBLE_STATE_T FVR_GetRawScrambleState(UINT8 u1Pidx);
//
// PVR loopback
//
EXTERN BOOL PVRM_Loopback_Init(UINT32 u4BufSize, UINT32 u4RecPktCount, UINT32 u4PlayThreshold);
EXTERN BOOL PVRM_Loopback_SetPid(UINT8 u1Pidx, UINT16 u2PidNum, DMX_PID_TYPE_T eType);
EXTERN BOOL PVRM_Loopback_Start(UINT32 u4Distance);
EXTERN BOOL PVRM_Loopback_Stop(VOID);
EXTERN void PVRM_Loopback_GetDataSize(USIZE *pu4Size, USIZE *pu4Max, USIZE *pu4Min);

EXTERN BOOL PVRM_Loopback_Live(UINT8 u1TsIdx);
EXTERN BOOL PVRM_Loopback_Record(UINT32 u4BufSize);
EXTERN BOOL PVRM_Loopback_SinglePlay(UPTR u4BufAddr, USIZE u4BufSize);
EXTERN BOOL PVRM_Loopback_StreamPlay(UPTR u4BufAddr, USIZE u4BufSize);
EXTERN BOOL PVRM_Loopback_ErrorTest(void);

#endif  // FVR_IF_H

