/* SPDX-License-Identifier: (GPL-2.0 OR BSD-3-Clause)*/
/*
 * Copyright (c) 2020 MediaTek Inc.
 */


#ifndef __DRV_DSCMB_H__
#define __DRV_DSCMB_H__


#include "tsd_dataType.h"

#include <linux/version.h>
#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 15, 0)
#if LINUX_VERSION_CODE >= KERNEL_VERSION(6, 6, 0)
#include <linux/tee_drv.h>
#else
#include "tee_drv_5_15_13.h"
#endif
#else
#include <linux/tee_drv.h>
#endif
#include <media/dvb_ca_en50221.h>

#include <utpa2_DSCMB.h>


#include <uapi/linux/tee.h>
#include "tee_client_api.h"


extern struct tee_shm *tee_shm_alloc(struct tee_context *ctx,
						size_t size, u32 flags);
extern void *tee_shm_get_va(struct tee_shm *shm, size_t offs);


#ifdef __cplusplus
extern "C" {
#endif

#define DSCMB_ERR(fmt, ...)	\
		pr_err("[%s][%d]" fmt,	\
				__func__, __LINE__, ##__VA_ARGS__)	\

#define DSCMB_WARN(fmt, ...)	\
		pr_warn("[%s][%d]" fmt,	\
				__func__, __LINE__, ##__VA_ARGS__)	\

#define DSCMB_INFO(fmt, ...)	\
		pr_info("[%s][%d]" fmt,	\
				__func__, __LINE__, ##__VA_ARGS__)	\

#define DSCMB_DEBUG(fmt, ...)	\
		pr_debug("[%s][%d]" fmt,	\
				__func__, __LINE__, ##__VA_ARGS__)	\

/// Descrambler null engine ID
#define DRV_DSCMB_ENG_NULL          0xFFFFFFFF
/// Descrambler null filter ID
#define DRV_DSCMB_FLT_NULL          0xFFFFFFFF
#define DSCMB_IV_LENGTH 16
#define DSCMB_KEY_LENGTH 16
#define DSCMB_KEYTOKEN_LENGTH 4
#define DSCMB_MULTI2_SYSKEY_LENGTH  32
#define DSCMB_HDCP2_RIV_LENGTH      8
#define INDEX_0               0
#define INDEX_1               1
#define INDEX_2               2
#define INDEX_3               3
#define INDEX_32              32

#define DSCMB_ASSERT_AND_RETURN(x)             if (!(x)){pr_err ("ASSERT FAIL: %s %s %d\n", __FILE__, __FUNCTION__, __LINE__); return FALSE;}
#define DSCMB_ASSERT_AND_RETURN_VALUE(x,ret)   if (!(x)){pr_err("ASSERT FAIL: %s %s %d\n", __FILE__, __FUNCTION__, __LINE__); return ret;}

	typedef struct DLL_PACKED {
		MS_U32 u32Status;
	} DSCMB_Status;


	typedef enum {
		/// Descrambler Slot Type :
		E_SLOT_TYPE_NORMAL = 0,	// Normal
		E_SLOT_TYPE_SHARE,	// Share
	} DSCMB_SLOT_Type;





/// Scramble level
	typedef enum {
		/// Descrambler level : none
		E_DSCMB_NONE = 0x00000000,
		/// Descrambler level : TS level
		E_DSCMB_TS = 0x00000001,
		/// Descrambler level : PES level
		E_DSCMB_PES = 0x00000002,
		/// Descrambler level : TS and PES level
		E_DSCMB_TS_PES = (E_DSCMB_TS | E_DSCMB_PES),
	} SCMB_Level;

	typedef struct _DSCMB_ENGFREE {
		MS_U32 u32EngId;
	} DSCMB_ENGFREE;

	typedef enum {
		// HDCP2.2 Errata
		E_DSCMB_CFG_HDCP2_TX_CONTENT_CATEGORY_SUPPORT,

		// update scramble bit @ PUSI packet
		E_DSCMB_CFG_SCMB_STATUS_PUSI_ONLY,

	} DSCMB_Option;


	typedef enum {
		//Live 0~3, Filein 0~3
		E_DSCMB_TSIF_LIVE0,
		E_DSCMB_TSIF_LIVE1,
		E_DSCMB_TSIF_LIVE2,
		E_DSCMB_TSIF_LIVE3,
		E_DSCMB_TSIF_FILE0,
		E_DSCMB_TSIF_FILE1,
		E_DSCMB_TSIF_FILE2,
		E_DSCMB_TSIF_FILE3,
		//Live 4~6, Filein 4~6
		E_DSCMB_TSIF_LIVE4,
		E_DSCMB_TSIF_LIVE5,
		E_DSCMB_TSIF_LIVE6,
		E_DSCMB_TSIF_FILE4,
		E_DSCMB_TSIF_FILE5,
		E_DSCMB_TSIF_FILE6,
		E_DSCMB_TSIF_NUM,
	} DSCMB_TSIF;

	typedef enum {
		// State is backup in DRAM, components power off.
		E_POWER_SUSPEND = 1,
		// Resume from Suspend or Hibernate mode
		E_POWER_RESUME = 2,
		// Full power off mode. System return to working
		//state only after full reboot
		E_POWER_MECHANICAL = 3,
		// The system appears to be off,
		E_POWER_SOFT_OFF = 4,
		//but some components remain powered for trigging boot-up.
	} EN_POWER_MODE;

	typedef struct {
		DSCMB_MainAlgo_Type eMainAlgo;
		MS_U32 u32SelId;
		MS_U32 u32EngId;
		MS_U64 u64Keytoken;
	} DSCMB_ENGALLOC;


	typedef struct {
		MS_U32 u32EngId;
		MS_U32 u32DscmbId;
	} DSCMB_FLTFREE;

	typedef struct {
		MS_U32 u32EngId;
		MS_U32 u32DscmbId;
		MS_U32 u32DmxFltId;
		MS_U64 u64Keytoken;
		MS_U32 u32PipeId;
	} DSCMB_CONNECTFLT, DSCMB_CONNECTSTATUS;

	typedef struct {
		MS_U32 u32EngId;
		MS_U32 u32DscmbId;
		MS_U32 u32DmxFltId;
	} DSCMB_DISCONNECTFLT;

	typedef struct {
		MS_U32 u32EngId;
		MS_U32 u32DscmbId;
		MS_BOOL bDscmb;
		MS_U64 u64Keytoken;
	} DSCMB_FLTDSCMB;

	typedef struct {
		MS_U32 u32EngId;
		MS_U32 u32DscmbId;
		DSCMB_Key_Type eKeyType;
		union {
			MS_U8 *pu8IV;
			MS_U8 *pu8Key;
		};
		MS_U64 u64Keytoken;
	} DSCMB_FLTIVSET, DSCMB_FLTKEYSET, DSCMB_ENGIV;

	typedef struct {
		MS_U32 u32EngId;
		MS_U32 u32DscmbId;
		DSCMB_Key_Type eKeyType;
		MS_U64 u64Keytoken;
	} DSCMB_FLTKEYRESET;

	typedef struct {
		MS_U32 u32EngId;
		MS_U32 u32DscmbId;
		DSCMB_Type eType;
		MS_U64 u64Keytoken;
	} DSCMB_TYPESET;

	typedef struct {
		MS_U32 u32EngId;
		MS_U8 *pu8SysKey;
	} DSCMB_MULTI2_SETSYSKEY;

	typedef struct {
		MS_U32 u32EngId;
		MS_U32 u32Round;
	} DSCMB_MULTI2_SETROUND;

	typedef struct {
		MS_U32 u32EngId;
		DSCMB_Flt_Type eFltType;
		MS_U32 u32DscmbId;
		MS_U64 u64Keytoken;
		MS_U32 u32EncryptType;
	} DSCMB_FLTALLOC, DSCMB_FLTSWITCHTYPE;

	typedef struct {
		MS_U32      u32EngId;
		MS_U8      *pu8Riv;
	} DSCMB_HDCP2_SETRIV;

	typedef struct {
		MS_U32      u32EngId;
		MS_BOOL     bEnable;
	} DSCMB_TLVPATH;

	struct dscmb_config_out {
		MS_U32 u32SCMB;
		MS_U32 u32FltHit;
		MS_U32 u32DBGVal1;
		MS_U32 u32keyValid;
	};

	struct DSCMB_CONFIG {
		MS_U32 u32EngId;
		MS_U32 u32DscmbId;
		MS_U32 u32DmxFltId;
		struct dscmb_config_out *pconfig_out;
		//MS_U32 u32SCMB;
		//MS_U32 u32FltHit;
		//MS_U32 u32DBGVal1;
		//MS_U32 u32keyValid;
	};

	struct dscmb_config_in {
		MS_U32 u32EngId;
		MS_U32 u32DscmbId;
		MS_U32 u32DmxFltId;
	};


//---------------------------------------------------
//  Functions
//---------------------------------------------------
// descrambler initial function
//-----------------
// DSCMB_General
//-----------------
//-----------------------------------------------------
/// Initialize DSCMB module
/// @ingroup DSCMB_General
/// @return TRUE  : Succeed
/// @return FALSE : Fail
//-----------------------------------------------------
MS_BOOL MDrv_DSCMB2_Init(void);

//------------------------------------------------------
/// Finalize DSCMB module
/// @ingroup DSCMB_General
/// @return TRUE  : Succeed
/// @return FALSE : Fail
//------------------------------------------------------
MS_BOOL MDrv_DSCMB2_Exit(void);

//-----------------
// DSCMB_Engine_Control
//-----------------
//-------------------------------------------------------
/// Allocate a dscrambler engine
/// @ingroup DSCMB_Engine_Control
/// @param eMainAlgo \b IN: The descrambler main algorithm
/// @param pu32SelId \b IN: Select certain descrambler engine ID.
//    NULL means engine is selected by driver
/// @return TRUE  : Succeed - Descrambler engine ID
/// @return FALSE : Fail - DRV_DSCMB_ENG_NULL
//---------------------------------------------------------
MS_U32 MDrv_DSCMB_EngAlloc(DSCMB_MainAlgo_Type eMainAlgo, MS_U32 u32SelId,
			    MS_U64 u64Keytoken);

MS_U32 MDrv_DSCMB2_EngAlloc(DSCMB_MainAlgo_Type eMainAlgo, MS_U32 u32SelId);

//-------------------------------------------------------
/// Free a dscrambler engine
/// @ingroup DSCMB_Engine_Control
/// @param u32EngId \b IN: Descrambler engine ID obtained from
///     MDrv_DSCMB2_EngAlloc
/// @return TRUE  : Succeed
/// @return FALSE : Fail
//-----------------------------------------------------------
MS_BOOL MDrv_DSCMB_EngFree(MS_U32 u32EngId);

//-----------------------------------------------------------------------
/// Allocate a dscrambler filter (Slot).
///(Only this function can allocate share key slot).
/// (Just keep MDrv_DSCMB2_FltAlloc and refine it)
/// @ingroup DSCMB_ToBeRemove
/// @param u32EngId  \b IN: DSCMB engine id.
/// @param eFltType    \b IN: Type for descramber filter.
/// @return TRUE  : Succeed - Descrambler filter slot.
/// @return FALSE : Fail - DRV_DSCMB_FLT_NULL
//-----------------------------------------------------------------------
MS_U32 MDrv_DSCMB_FltAlloc(MS_U32 u32EngId, MS_U64 u64Keytoken,
		DSCMB_Flt_Type eFltType, MS_U32 *pu32PipeId);

MS_U32 MDrv_DSCMB2_FltAlloc_Ex(MS_U32 u32EngId, DSCMB_Flt_Type eFltType);

//-----------------
// DSCMB_Slot_Control
//-----------------
//-----------------------------------------------------------------------
/// Free a dscrambler slot.
/// @ingroup DSCMB_Slot_Control
/// @param u32EngId        \b IN: DSCMB engine id.
/// @param u32DscmbId    \b IN: DSCMB slot.
/// @return TRUE  : Succeed
/// @return FALSE : Fail
//------------------------------------------------------------------------
MS_BOOL MDrv_DSCMB_FltFree(MS_U32 u32EngId, MS_U32 u32DscmbId);


//-------------------------------------------------------------------------
/// Connect DSCMB slot with DMX PID filter by filter index for Enc/Dec used.
/// @ingroup DSCMB_Slot_Control
/// @param u32EngId        \b IN: DSCMB engine id.
/// @param u32DscmbId    \b IN: DSCMB slot.
/// @param u32FltId          \b IN: DMX PID filter index.
/// @return TRUE  : Succeed
/// @return FALSE : Fail
//------------------------------------------------------------------------
MS_BOOL MDrv_DSCMB_FltConnectFltId(MS_U64 u64Keytoken, MS_U32 u32EngId,
		MS_U32 u32DscmbId, MS_U32 u32FltId, MS_U32 *pu32PipeId);

MS_BOOL MDrv_DSCMB2_FltConnectFltId(MS_U32 u32EngId, MS_U32 u32DscmbId,
    MS_U32 u32FltId);

//------------------------------------------------------------------------
/// Dis-connect DSCMB slot with DMX PID filter by filter index.
/// @ingroup DSCMB_Slot_Control
/// @param u32EngId        \b IN: DSCMB engine id.
/// @param u32DscmbId    \b IN: DSCMB slot.
/// @param u32FltId          \b IN: DMX PID filter index.
/// @return TRUE  : Succeed
/// @return FALSE : Fail
//---------------------------------------------------------------------------
MS_BOOL MDrv_DSCMB_FltDisconnectFltId(MS_U32 u32EngId,
		MS_U32 u32DscmbId, MS_U32 u32FltId);

//-----------------
// DSCMB_Key
//-----------------
//-----------------------------------------------------------------
/// Set descrambler algorithm by common predefined descramble type.
/// @ingroup DSCMB_Key
/// @param u32EngId       \b IN: DSCMB engine id
/// @param u32DscmbId   \b IN: DSCMB slot.
/// @param DscmbType    \b IN: The descrambler algorithm
/// @return TRUE  - Success
/// @return FALSE - Failure
//---------------------------------------------------------------------
MS_BOOL MDrv_DSCMB2_FltTypeSet(MS_U32 u32EngId, MS_U32 u32DscmbId,
		DSCMB_Type DscmbType);
//--------------------------------------------------------------------
/// Set descrambler key of the Dscmb ID
/// @ingroup DSCMB_Key
/// @param u32EngId       \b IN: DSCMB engine id
/// @param u32DscmbId   \b IN: DSCMB slot.
/// @param eKeyType      \b IN: Descrambler key type
/// @param pu8Key         \b IN: pointer to the key (Array)
/// @return TRUE - Success
/// @return FALSE - Failure
//--------------------------------------------------------------------
MS_BOOL MDrv_DSCMB2_FltKeySet(MS_U32 u32EngId, MS_U32 u32DscmbId,
		DSCMB_Key_Type eKeyType, MS_U8 *pu8Key);
//----------------------------------------------------------------------
/// Reset descrambler key of the Dscmb ID. (It will set key to 0)
/// @ingroup DSCMB_Key
/// @param u32EngId       \b IN: DSCMB engine id
/// @param u32DscmbId   \b IN: DSCMB slot.
/// @param eKeyType      \b IN: Descrambler key type
/// @return TRUE - Success
/// @return FALSE - Failure
//-------------------------------------------------------------------
MS_BOOL MDrv_DSCMB2_FltKeyReset(MS_U32 u32EngId, MS_U32 u32DscmbId,
				DSCMB_Key_Type eKeyType);

//-------------------------------------------------------------------
/// Set descrambler initial vector of the Dscmb ID
/// @ingroup DSCMB_Key
/// @param u32EngId       \b IN: DSCMB engine id
/// @param u32DscmbId   \b IN: DSCMB slot.
/// @param eKeyType      \b IN: Descrambler key type
/// @param pu8IV     \b IN: pointer to the key. (Instruction Vector)
/// @return TRUE - Success
/// @return FALSE - Failure
//------------------------------------------------------------------
MS_BOOL MDrv_DSCMB2_FltIVSet(MS_U32 u32EngId, MS_U32 u32DscmbId,
		DSCMB_Key_Type eKeyType, MS_U8 *pu8IV);

//-----------------------------------------------------------------
/// Query dscrambler capability information
/// @ingroup DSCMB_General
/// @param u32EngId      \b IN: DSCMB engine id.
/// @param eQueryType  \b IN: type for query
/// @param pInput          \b IN: intput parameter
/// @param pOutput        \b OUT: result for the query type
/// @return TRUE - Success
/// @return FALSE - Failure
//--------------------------------------------------------------------
MS_BOOL MDrv_DSCMB2_GetCap(MS_U32 u32EngId, DSCMB_Query_Type eQueryType,
		void *pInput, void *pOutput);
//--------------------------------------------------------------------
/// Get DSCMB driver library information
/// @ingroup DSCMB_General
/// @param ppVersion \b OUT: Descrambler library version information
/// @return TRUE - Success
/// @return FALSE - Failure
//-----------------------------------------------------------------------

//-------------------------------------------------------------------------
/// Set rounds of descrambler algorithm MULTI2
/// @ingroup DSCMB_Key
/// @param u32EngId     \b IN: DSCMB engine id
/// @param u32Round    \b IN: # rounds to apply, multiple of 4 and
///    maximum value is 252
/// @return TRUE  - Success
/// @return FALSE - Failure
//------------------------------------------------------------------------
MS_BOOL MDrv_DSCMB2_Multi2_SetRound(MS_U32 u32EngId, MS_U32 u32Round);
//-------------------------------------------------------------------------
/// Set system key of descrambler algorithm MULTI2
/// @ingroup DSCMB_Key
/// @param u32EngId     \b IN: DSCMB engine id
/// @param u32SysKey  \b IN: the array of system key (u8SysKey[32]):
///    there are 32 group system key(8-bit should be 32 group)
///    should be set.
/// @[0-31][32-63][64-95][96-127][128-159][160-191][192-223][224-255]
///    and the bit order is MSB.
/// @return TRUE  - Success
/// @return FALSE - Failure
//-----------------------------------------------------------------------
MS_BOOL MDrv_DSCMB2_Multi2_SetSystemKey(MS_U32 u32EngId,
		MS_U8 *u8Syskey);
//-------------------------------------------------------------------------
/// Set Riv of HDCP2, which is 64-bits number
///   generated from transmitter
/// @ingroup DSCMB_Key
/// @param u32EngId   \b IN: DSCMB engine id
/// @param pu8RIV      \b IN:
///    pointer to 64bit Riv buffer in BIG ENDIAN order
/// @return TRUE  - Success
/// @return FALSE - Failure
//---------------------------------------------------------------------
MS_BOOL MDrv_DSCMB2_HDCP2_SetRIV(MS_U32 u32EngId, MS_U8 *pu8RIV);
//----------------------------------------------------------------------
/// Set Riv of HDCP2, which is 64-bits number generated from transmitter
/// @ingroup DSCMB_Key
/// @param u32EngId   \b IN: DSCMB engine id
/// @param u32EngId   \b IN: DSCMB slot
/// @param pu8RIV      \b IN: pointer to 64bit Riv buffer in BIG ENDIAN order
/// @return TRUE  - Success
/// @return FALSE - Failure
//-----------------------------------------------------------------------
MS_BOOL MDrv_DSCMB2_HDCP2_SetRIV_Ex(MS_U32 u32EngId, MS_U32 u32DscmbId,
		MS_U8 *pu8RIV);

//-----------------
// DSCMB_STR
//-----------------
//------------------------------------------------------------------
/// Control DSCMB STR functions.
/// @ingroup DSCMB_STR
/// @param  u16PowerState  \b IN: STR power mode. (to control STR
///suspend & resume case.)
/// @return : Utopia status - UTOPIA_STATUS_SUCCESS  or UTOPIA_STATUS_FAIL
//-----------------------------------------------------------------
MS_U32 MDrv_DSCMB2_SetPowerState(EN_POWER_MODE u16PowerState);


//---------------------------------------------------------------------
/// Get Dscmb driver status (There is no any code use this parameter)
/// @ingroup DSCMB_ToBeRemove
/// @param pStatus   \b OUT: Descrambler status
/// @return TRUE - Success
/// @return FALSE - Failure
//----------------------------------------------------------------------
MS_BOOL MDrv_DSCMB_GetStatus(DSCMB_Status *pStatus);

MS_BOOL MDrv_DSCMB2_Init(void);

//-----------------
// DSCMB_ToBeRemove
//-----------------
//---------------------------------------------------------------------
/// Initialize DSCMB module. (Already have another function: DSCMB2_Init)
/// @ingroup DSCMB_ToBeRemove
/// @return TRUE  : Succeed
/// @return FALSE : Fail
//---------------------------------------------------------------------
MS_BOOL MDrv_DSCMB_Init(void);
//----------------------------------------------------------------------
/// Finalize DSCMB module. (Already have another function: DSCMB2_Exit)
/// @ingroup DSCMB_ToBeRemove
/// @return TRUE  : Succeed
/// @return FALSE : Fail
//--------------------------------------------------------------------
MS_BOOL MDrv_DSCMB_Exit(void);

//--------------------------------------------------------------------
/// Set DSCMB Debug Level. (Already have another function:
///DSCMB2_SetDBGLevel)
/// @ingroup DSCMB_ToBeRemove
/// @param  u32Level  \b IN: debug level.
/// @return TRUE  : Succeed
/// @return FALSE : Fail
//-------------------------------------------------------------------
MS_BOOL MDrv_DSCMB_SetDBGLevel(MS_U32 u32Level);

//----------------------------------------------------------------------
/// Control DSCMB STR functions.
///(Already have another function: DSCMB2_SetPowerState)
/// @ingroup DSCMB_ToBeRemove
/// @param  u16PowerState  \b IN: STR power mode.
///(to control STR suspend & resume case.)
/// @return : Utopia status - UTOPIA_STATUS_SUCCESS
///(Succeed) or UTOPIA_STATUS_FAIL (Fail)
//------------------------------------------------------------------------
MS_U32 MApi_DSCMB_SetPowerState(EN_POWER_MODE u16PowerState);

//----------------------------------------------------------------------
/// Control DSCMB TLV path.
/// @param u32EngId   \b IN: DSCMB engine id
/// @param bEnable      \b IN:
///   BOOL to identify TLV stream or not TRUE: TLV FALSE: TS
/// @return TRUE  - Success
/// @return FALSE - Failure
//------------------------------------------------------------------------
MS_BOOL MDrv_DSCMB2_SetTLVPath(MS_U32 u32EngId, MS_BOOL bEnable);

MS_BOOL MDrv_DSCMB2_GetConfig(struct dscmb_config_in config_in,
					struct dscmb_config_out *config_out);

#ifdef __cplusplus
}
#endif
#endif
