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

#include "ext_command_frc_if.h"
#include "mtk_tv_drm_video_display.h"
#include "hwreg_render_video_frc.h"

//-------------------------------------------------------------------------------------------------
//  Local Defines
//-------------------------------------------------------------------------------------------------
#define  MEMC_BLOCK_H_ALIGN 16
#define  MEMC_BLOCK_V_ALIGN 16

#define RV55_CMD_LENGTH 40
#define MAX_FRC_SMI_MIU2GMC_NUM 48
#define MAX_FRC_SMI_PORT_NUM 48
#define MAX_FRC_MAX_FRAME_CNT (20)
#define BURST_CMD_MAX_SIZE (39)

#define AIPQ_INFO_LBOX_MAX (4)
#define MAX_CMD_HISTORY_SIZE (100)
#define FRC_TIME_BUFFER_SIZE (32)

//-------------------------------------------------------------------------------------------------
//  Enum
//-------------------------------------------------------------------------------------------------
enum MEMC_Version_Index {
	Version_Major                = 0x00,
	Version_Minor                = 0x01,
};

enum Frc_command_list {
	//Get command
	FRC_MB_CMD_GET_SW_VERSION                       = 0x02,
	FRC_MB_CMD_GET_RWDIFF                           = 0x03,

	//Set command
	FRC_MB_CMD_INIT                                 = 0x04,
	FRC_MB_CMD_SET_TIMING                           = 0x05,
	FRC_MB_CMD_SET_INPUT_FRAME_SIZE                 = 0x06,
	FRC_MB_CMD_SET_OUTPUT_FRAME_SIZE                = 0x07,
	FRC_MB_CMD_SET_FPLL_LOCK_DONE                   = 0x08,
	FRC_MB_CMD_SWITCH_TO_SHM                        = 0x0A,
	FRC_MB_CMD_SET_MEMC_BYPASS                      = 0x0E,
	FRC_MB_CMD_SET_FRC_MODE                         = 0x0F,
	FRC_MB_CMD_SET_MFC_MODE                         = 0x10,
	FRC_MB_CMD_SET_FRC_GAME_MODE                    = 0x11,
	FRC_MB_CMD_SET_MFC_DEMO_MODE                    = 0x12,
	FRC_MB_CMD_60_REALCINEMA_MODE                   = 0x13,
	FRC_MB_CMD_SET_INPUT_TYPE                       = 0x14,
	FRC_MB_CMD_SET_MFC_DECODE_IDX_DIFF              = 0x20,
	FRC_MB_CMD_SET_MFC_FRC_DS_SETTINGS              = 0x21,
	FRC_MB_CMD_SET_MFC_CROPWIN_CHANGE               = 0x22,
	FRC_MB_CMD_MEMC_MASK_WINDOWS_H                  = 0x30,
	FRC_MB_CMD_MEMC_MASK_WINDOWS_V                  = 0x31,
	FRC_MB_CMD_MEMC_ACTIVE_WINDOWS_H                = 0x32,
	FRC_MB_CMD_MEMC_ACTIVE_WINDOWS_V                = 0x33,
	FRC_MB_CMD_FILM_CADENCE_CTRL                    = 0x34,
	FRC_MB_CMD_INIT_DONE                            = 0x35,
	FRC_MB_CMD_SET_SHARE_MEMORY_ADDR                = 0x36,
	FRC_MB_CMD_SET_QoS                            = 0x37,
	FRC_MB_CMD_GET_QoS                            = 0x38,
	FRC_MB_CMD_SUSPEND                            = 0x39,
	FRC_MB_CMD_RESUME                             = 0x3A,

	//SONY Command
	FRC_MB_CMD_SET_MEMC_DEBUG_CADENCE               = 0x40,
	FRC_MB_CMD_SET_MEMC_DEBUG_OUTSR                 = 0x41,
	FRC_MB_CMD_SET_MEMC_DEBUG_FALLBACKW3            = 0x42,
	FRC_MB_CMD_SET_MEMC_DEBUG_FALLBACKW0            = 0x43,
	FRC_MB_CMD_SET_MEMC_DEBUG_MOTION                = 0x44,
	FRC_MB_CMD_SET_MEMC_DEBUG_SHOW_FILM_ERROR       = 0x45,
	FRC_MB_CMD_SET_MEMC_DEBUG_AUTOMODE              = 0x46,
	FRC_MB_CMD_SET_MEMC_DEBUG_AUTOMODE_FINAL        = 0x47,
	FRC_MB_CMD_SET_MEMC_DEBUG_OSDMASK               = 0x48,
	FRC_MB_CMD_SET_MEMC_DEBUG_HALO_REDUCTION        = 0x49,
	FRC_MB_CMD_SET_MEMC_DEBUG_SEARCH_RANGE          = 0x4A,
	FRC_MB_CMD_SET_MEMC_DEBUG_PERIODICAL            = 0x4B,
	FRC_MB_CMD_SET_MEMC_DEBUG_BADEDIT               = 0x4C,
	FRC_MB_CMD_SET_MEMC_DEBUG_MVSTICKING            = 0x4D,
	FRC_MB_CMD_SET_MEMC_DEBUG_SMALL_OBJECT          = 0x4E,
	FRC_MB_CMD_SET_MEMC_DEBUG_SPOTLIGHT             = 0x4F,
	FRC_MB_CMD_SET_MEMC_DEBUG_BOUNDARY_HALO         = 0x50,
	FRC_MB_CMD_SET_MEMC_DEBUG_POSITION_RATIO_TABLE  = 0x51,
	FRC_MB_CMD_SET_MEMC_DEBUG_IMPREMENTATION_FRAME  = 0x52,
	FRC_MB_CMD_SET_MEMC_RELPOS_RATIO_INDEX          = 0x53,

	//Send burst command
	FRC_MB_CMD_SET_MECM_LEVEL                       = 0x80,

	//Get command for MEMC alg LTP
	FRC_MB_CMD_GET_MECM_ALG_STATUS                  = 0xF0,
};

enum mtk_video_plane_memc_initstate {
	MEMC_INIT_CHECKRV55,
	MEMC_INIT_SENDDONE,
	MEMC_INIT_FINISH,

	MEMC_INIT_STATE_NUM
};

enum mtk_video_frc_input_hdr_type {
	INPUT_HDR_TYPE_SDR,
	INPUT_HDR_TYPE_DOLBY,
	INPUT_HDR_TYPE_HDR10,
	INPUT_HDR_TYPE_TCH,
	INPUT_HDR_TYPE_HLG,
	INPUT_HDR_TYPE_HDR10_PLUS,
	INPUT_HDR_TYPE_HDR_VIVID,
	INPUT_HDR_TYPE_MAX,
};

enum mtk_video_memc_poweron_state {
	MEMC_INIT_AC,
	MEMC_INIT_DC,
	MEMC_INIT_NUM,
};

enum mtk_video_frc_pq_scene {
	MEMC_PQ_SCENE_NORMAL = 0,
	MEMC_PQ_SCENE_GAME,
	MEMC_PQ_SCENE_GAME_CROP,
	MEMC_PQ_SCENE_PC,
	MEMC_PQ_SCENE_PHOTO,
	MEMC_PQ_SCENE_FORCE_P,
	MEMC_PQ_SCENE_HFR,
	MEMC_PQ_SCENE_GAME_WITH_MEMC,
	MEMC_PQ_SCENE_3D,
	MEMC_PQ_SCENE_SLICED_GAME,
	MEMC_PQ_SCENE_GAME_WITH_PC,
	MEMC_PQ_SCENE_GAME_CROP_WITH_MEMC,
	MEMC_PQ_SCENE_MAX,
};

enum mtk_frc_debug_cmd_type {
	E_FRC_DEBUG_CMD_BASE = 0xD600,
	E_FRC_DEBUG_CMD_SWITCH,           // 0xD601
	E_FRC_DEBUG_CMD_DS_SWITCH,        // 0xD602
	E_FRC_DEBUG_CMD_SWITCH_CHG,       // 0xD603
	E_FRC_DEBUG_CMD_MUTE,             // 0xD604
	E_FRC_DEBUG_CMD_DS_MUTE,          // 0xD605
	E_FRC_DEBUG_CMD_DS_MUTE_INST,     // 0xD606
	E_FRC_DEBUG_CMD_DS_FREEZE_INST,   // 0xD607
	E_FRC_DEBUG_CMD_LINE_CNT,         // 0xD608
	E_FRC_DEBUG_CMD_VGSYNC,           // 0xD609
	E_FRC_DEBUG_CMD_VGSYNC_ADVANCE,   // 0xD60A
	E_FRC_DEBUG_CMD_VGSYNC_VAILD,     // 0xD60B
};

enum mtk_frc_debug_cadencenum {
	E_FRC_DEBUG_VIDEO_G0 = 0x1,
	E_FRC_DEBUG_22_G0,
	E_FRC_DEBUG_32_G0,
	E_FRC_DEBUG_4222_G0,
	E_FRC_DEBUG_32322_G0,
	E_FRC_DEBUG_21111_G0,
	E_FRC_DEBUG_2332_G0,
	E_FRC_DEBUG_2111_G0,
	E_FRC_DEBUG_33_G0,
	E_FRC_DEBUG_44_G0,
	E_FRC_DEBUG_55_G0,
	E_FRC_DEBUG_42222_G0,

	E_FRC_DEBUG_CADENCE_NONE,
};

struct mtk_frc_dynamic_latency {
	uint32_t input_freq;
	uint32_t output_freq;
	uint32_t u32ContentW;
	uint32_t u32ContentH;
	uint32_t u32SrcW;
	uint32_t u32SrcH;
	uint32_t u32SrcFps;
	uint32_t u32MaxFps;
	uint32_t u32TempW;
	uint32_t u32TempH;
	uint32_t u32RelFps;
	bool bHbbtv;
	bool bAdaptive;
	bool bB2r;
	bool bMse;
	bool bLowLatency;
	bool bBypassMemc;
};

struct mtk_frc_pattern_info {
	bool bEnble;
	bool bSwap;
	bool bForce;
	enum E_DRV_FRC_VIDEO_FRC_PATTERN sel;
	enum E_DRV_FRC_MOVABLE_PAT_INFO MoveType;
	uint8_t frc_pattern_trig_cnt;
	uint16_t speed;
	bool bOpmF2;
	bool bOpmF3;
	uint16_t F2_fcnt;
	uint16_t F3_fcnt;
};

struct mtk_frc_context {

	uint8_t frc_ip_version;
	bool frcopmMaskEnable;
	bool bIspre_memc_en_Status[MAX_WINDOW_NUM];
	bool bTsMode;
	struct mtk_frc_dynamic_latency dynamic_latency;
	uint16_t frc_latency;
	uint16_t frc_rwdiff;
	uint16_t frc_user_rwdiff_en;
	uint16_t frc_user_rwdiff;
	uint16_t frc_dts_rwdiff;

	enum mtk_video_plane_memc_initstate memc_InitState;
	bool bConnCop;

	uint64_t u64frcpts;
	uint16_t frc_frame_count;
	uint32_t frc_shm_size;
	uint64_t frc_shm_adr;
	unsigned long frc_shm_virAdr;

	uint8_t video_memc_mode;
	uint8_t video_frc_mode;
	uint8_t mfc_mode;
	uint8_t frc_alg_run_on;
	uint8_t frc_frame_cnt60Hz;
	uint8_t frc_frame_cnt120Hz;
	uint8_t frc_a2dp_max_frame_cnt;

	uint32_t frc_vgsync_shm_size;
	uint64_t frc_vgsync_shm_adr;
	unsigned long frc_vgsync_shm_virAdr;
	uint8_t frc_perfect_vgsync;
	uint8_t frc_vgcnt;
	bool frc_vgsync_en[PQU_RENDER_DS_NUM];
	bool frc_afd_working;
	bool frc_vgsync_working;
	bool frc_afd_en[PQU_RENDER_DS_NUM];
	struct hwregFrcMlInfo frc_ml_info[PQU_RENDER_DS_NUM];
	struct hwregFrcMlDumpInfo frc_ml_dump_info;

	uint8_t frc_as_hse;

	uint8_t frc_a2dp_enable;

	// smi
	uint8_t frc_smi_number;
	uint8_t frc_smi_miu2gmc[MAX_FRC_SMI_MIU2GMC_NUM];
	uint8_t frc_smi_port[MAX_FRC_SMI_PORT_NUM];

	uint16_t frc_ipm_hsize;
	uint16_t frc_ipm_vsize;

	uint8_t frc_photo_enable;
	uint8_t frc_photo_rw_diff;

	bool frc_user_extra_delay_enable;
	uint8_t frc_user_extra_delay_num;

	uint8_t frc_qms_rw_diff_60;
	uint8_t frc_qms_rw_diff_120;

	enum mtk_video_frc_input_hdr_type frc_input_hdr_type;
	bool bSkipGameMemc;
	enum mtk_video_frc_pq_scene frc_scene;
	bool bMemcFakeFlag;
	unsigned int plane_idx;

	uint8_t frc_force_low_latency;

	enum mtk_video_memc_poweron_state memc_poweron_stats;

	uint8_t frc_444_frame_cnt;
	uint8_t frc_444_rw_diff;

	bool frc_efuse_val_disable_memc;

	// Debug command used
	struct hwregFrcDebugInfo dInfo;
	struct hwregFrcDebugInfo pre_dInfo;
	struct hwregFrcVgsyncDebug dDsInfo;
	struct hwregFrcVgsyncDebug pre_dDsInfo;
	bool bDebugCmdEn;
	uint8_t debugCmdLevel;
	enum mtk_frc_debug_cmd_type debugCmdType;
	bool bForceDynamicPathLogEn;
	bool bForceDynamicPathBypass;
	bool bForceDynamicPathEn;
	bool bForceDynamicPathSel;
	enum E_DRV_FRC_MEMC_SUPPORT_INFO eMEMC_support_info;
	bool IsLowLatencyPreplay;

	struct mtk_frc_pattern_info stPatInfo;
};

//-------------------------------------------------------------------------------------------------
//  Structures
//-------------------------------------------------------------------------------------------------
struct mtk_frc_timinginfo_tbl {
	uint32_t input_freq_L;
	uint32_t input_freq_H;
	uint32_t frc_memc_latency;
	uint32_t frc_game_latency;
};

struct mtk_frc_shm_info {
	uint64_t pts;
	uint16_t frame_count;
	uint8_t extra_delay_num;
};

struct mtk_frc_vgsync_buf_info {
	uint8_t u8CurBufIdx;
	struct window_info stCurWinInfo;
	uint8_t u8BufCnt;
	uint8_t u8PqOutCurBufIdx;
	struct window_info astWinInfo[MAX_FRC_MAX_FRAME_CNT];
	enum E_DRV_FRC_LBW_F2F3_PATH eLbwPath;
	uint16_t u16wout_lbox[AIPQ_INFO_LBOX_MAX];
	uint8_t u8wout_filmtype;
	uint8_t u8wout_is24p;
};

struct kmfc_cmd_param {
	uint32_t CmdID; // 0x00 ~0xFF
	uint32_t D1;
	uint32_t D2;
	uint32_t D3;
	uint32_t D4;
};

struct ext_pqu_frc_send_cmd_param {
	int32_t u32RoleID;
	int32_t CmdID; // 0x00 ~0xFF
	int32_t D1;
	int32_t D2;
	int32_t D3;
	int32_t D4;
};

struct ext_pqu_frc_send_burstcmd_param {
	int32_t u32RoleID;
	int32_t CmdID; // 0x00 ~0xFF
	uint8_t Data[BURST_CMD_MAX_SIZE];
};

struct mtk_frc_info_for_latency {
	uint32_t input_freq;
	int32_t contentW;
	int32_t contentH;
	int32_t srcW;
	int32_t srcH;
	int32_t srcFps;
	int32_t maxFps;
	uint8_t disp_mode;
	bool IsHbbtv;
	bool IsInputSrcDD;
	bool IsAdaptive;
	bool IsLowLatency;
};

struct mtk_frc_debug_info {
	bool bRecorded;
	bool bIsMemcPath;
	struct pqu_frc_send_cmd_param cmd;
	int sendCmdRet;
	char time_buffer[FRC_TIME_BUFFER_SIZE];
};

struct mtk_frc_debug_info_history {
	struct mtk_frc_debug_info dbgHistroy[MAX_CMD_HISTORY_SIZE];
	int currentIndex;
};

//-------------------------------------------------------------------------------------------------
//  Global Functions
//-------------------------------------------------------------------------------------------------
struct mtk_tv_kms_context;

uint32_t mtk_video_display_frc_set_Qos(uint8_t QosMode);
uint32_t mtk_video_display_frc_get_Qos(uint8_t *pQosMode);

uint32_t mtk_video_display_frc_set_rv55_burst_cmd(uint16_t *u16Data, uint16_t u16Length);
uint32_t mtk_video_display_frc_set_rv55_cmd(uint16_t *u16Data, uint16_t u16Length,
	struct mtk_frc_context *pctx_frc);

int mtk_video_display_frc_get_memc_level(uint8_t *memc_level, uint16_t u16Length);
void _mtk_video_frc_get_latency_preplay(struct mtk_frc_info_for_latency *pInfolatency,
	struct mtk_tv_kms_context *pctx);

void mtk_video_display_frc_suspend(struct device *dev, struct mtk_tv_kms_context *pctx);
void mtk_video_display_frc_resume(struct device *dev, struct mtk_tv_kms_context *pctx);

void mtk_video_display_frc_init(
	struct device *dev,
	struct mtk_tv_kms_context *pctx);

void mtk_video_display_set_frc_opm_path(struct mtk_plane_state *state,
						 bool enable);
void mtk_video_display_set_frc_property(
	struct video_plane_prop *plane_props,
	enum ext_video_plane_prop prop);
void mtk_video_display_get_frc_property(
	struct video_plane_prop *plane_props,
	enum ext_video_plane_prop prop);

void mtk_video_display_set_frc_opm_mask_enable(
	struct mtk_tv_kms_context *pctx);

void mtk_video_display_set_frc_freeze(
		struct mtk_tv_kms_context *pctx,
		unsigned int plane_inx,
		bool enable);

void mtk_video_display_set_frc_still_mode_freeze(
		struct mtk_tv_kms_context *pctx,
		unsigned int plane_inx,
		bool enable);

bool mtk_video_display_check_frc_freeze(
		bool memc_enable,
		bool memc_freeze);

E_DRV_MFC_UNMASK mtk_video_frc_get_unmask(struct mtk_video_context *pctx_video);

bool mtk_frc_get_value_from_string(char *buf, char *name,
	unsigned int len, int *value);
int mtk_frc_get_all_value_from_string(char *buf, char *delim,
	unsigned int len, uint16_t *value, uint16_t *TokenCnt);

void mtk_video_display_frc_set_rv55_extra_delay_num(
	struct mtk_tv_kms_context *pctx, uint8_t real_extra_latency_cnt);
uint8_t mtk_video_display_frc_get_FramedelayCnt(uint32_t input_freq,
	uint32_t output_freq, uint8_t extra_latency_diff, uint8_t frc_ip_version);

extern int mtk_miu2gmc_mask(u32 miu2gmc_id, u32 port_id, bool enable);
extern int mtk_miu2gmc_node_mask(struct device_node *np, u32 port_id, bool enable);

#ifdef MEMC_IN_ARM_ENABLE
extern void KDrv_MfcAlgo_SendCommand(struct kmfc_cmd_param *cmd);
#endif

uint32_t mtk_video_display_frc_set_memc_onoff(bool enable);

int mtk_video_display_frc_debug(void *priv_data);
bool mtk_video_display_frc_get_perfect_vgsync_support(
	unsigned int plane_idx,
	struct mtk_tv_kms_context *pctx);
bool mtk_video_display_frc_get_vgs_onoff(void);

int mtk_video_display_frc_set_per_vsync(struct mtk_tv_drm_crtc *mtk_tv_crtc);

int mtk_video_display_frc_set_qms_vrr_info(uint8_t u8QMSVRR_rd_idx,
	uint8_t u8QMSVRR_rd_idx_OP_Cnt, uint8_t u8QMSVRR_rd_next_mode);

void mtk_tv_drm_video_set_vrr_mode_type(
	enum drm_render_vrr_mode_type eVrr);

int mtk_video_display_frc_set_timing_to_algo(
	struct mtk_tv_kms_context *pctx,
	uint64_t framesync_mode,
	uint64_t plane_id,
	uint32_t output_vfreq);

uint32_t mtk_video_display_frc_set_memc_onoff_direct(
	struct mtk_frc_context *pctx_frc,
	bool enable);

void mtk_video_set_frc_display_info_in_ds(
	unsigned int plane_idx,
	struct mtk_tv_kms_context *pctx,
	struct pqu_render_share_memory_info *metabuf_addr);

void mtk_video_display_frc_check_vgsync_onoff(
	unsigned int plane_idx,
	struct mtk_tv_kms_context *pctx);

void mtk_video_display_frc_shm_data_store(uint32_t start,
	uint32_t end, uint8_t sel);
#endif
